- [+] rename dragon to wyrm

- [+] cooked food shouldn't "completely rot away"
- [+] fire l6: meteor - large version of fireball
- [+] burning feet
- [+] evaporate should be a fire spell too.
- [+] more gods should remove curse for you.
- [+] eyebats shouldn't sleep
- [+] make hecta's prayers even more powerful.
- [+] fix bug in bjorn's truestrike effect
- [+] bjorn should un-dull weapons
- [+] fix buggy supply closet definitions - was getting 1-5 of same
      object rather than 1-5 different ones
- [+] restrict potion of growth to lower levels.
- [+] change method of determining how much you can carry.
- [+] change initial modification spell to 'enlarge object'
- [+] enlarge object
    - [+] door -> seals with surroundings
    - [+] rock -> boulder
    - [+] sword -> greatsword
    - [+] buckler -> next size shield
    - [+] bag -> next size bag
    - [+] or should this be a different spell?
- [+] immolate
    - [+] if a successful unarmed attack, lf catches on fire.
- [+] wizard isn't weilding staff. are fists better?
- [+] freezing touch shouldn't work on dragonwood
- [+] fix bug preventing vision when meditating
- [+] auto shortcuts
    - [+] wizards: pri/sec spells are 1/2
    - [+] cook:  lowest shortcut left.
- [+] statbar not being updated when i drink potion of magic.
- [+] warn that flying will stop mapping.
- [+] bjorn gifts should only be ones which you are skilled in!
    - [+] add 'appropriate'
    - [+] then apply to god.c
- [+] warn if you pick up poison stuff and you god doesn't like it
    - [+] "I hope you're not planning on using that/those...."
- [+] superheat - throw potion like a grenade
This commit is contained in:
Rob Pearce 2012-01-29 22:47:43 +00:00
parent a4ac951f15
commit ee42bdc73f
22 changed files with 877 additions and 265 deletions

44
ai.c
View File

@ -1,3 +1,4 @@
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -576,6 +577,21 @@ int aigetspelltarget(lifeform_t *lf, objecttype_t *spelltype, lifeform_t *victim
if (spellcell) *spellcell = l->cell;
if (spellob) *spellob = NULL;
}
} else if (spelltype->id == OT_S_SUPERHEAT) {
// get all potions
object_t *poss[MAXPILEOBS],*o;
int nposs = 0;
for (o = lf->pack->first ; o ; o = o->next) {
if (hasflag(o->flags, F_DRINKABLE)) {
poss[nposs++] = o;
}
}
assert(nposs); // aispellok should have checked.
if (spelllf) *spelllf = NULL;
if (spellcell) *spellcell = victim->cell;
if (spellob) *spellob = poss[rnd(0,nposs-1)];
}
}
return B_FALSE;
@ -907,18 +923,31 @@ int ai_bored(lifeform_t *lf, lifeform_t *master, int icanattack) {
// returns true if we did somethign
int ai_handle_emergencies(lifeform_t *lf, enum ATTRBRACKET iqb) {
int db = B_FALSE;
int moveawayfromcell = B_FALSE;
if (lfhasflag(lf, F_DEBUG)) db = B_TRUE;
if (lfhasflag(lf, F_RAGE)) return B_FALSE;
if (iqb >= AT_AVERAGE) {
if (celldangerous(lf, lf->cell, B_TRUE, NULL)) {
if (db) dblog("%s o O { there is something dangerous here, moving away } ", lf->race->name);
// if our cell is dangerous, move away!
if (!dorandommove(lf, B_NOBADMOVES, B_FALSE)) {
moveawayfromcell = B_TRUE;
}
}
// hot feet? move somewhere.
if (!moveawayfromcell && lfhasflag(lf, F_HOTFEET) && !isimmuneto(lf->flags, DT_FIRE, B_FALSE)) {
if (db) dblog("%s o O { i have f_hotfeet, moving away } ", lf->race->name);
moveawayfromcell = B_TRUE;
}
if (moveawayfromcell) {
if (!dorandommove(lf, B_NOBADMOVES, B_FALSE, B_TRUE)) {
return B_TRUE;
}
}
}
// flying monsters not flying?
if (!isprone(lf)) {
@ -1347,7 +1376,7 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) {
} else if (isadjacent(lf->cell, target->cell)) {
if (db) dblog(".oO { i can see my master adjacent - moving randomly }");
// move randomly. TODO: just return ??
dorandommove(lf, B_NOBADMOVES, B_TRUE);
dorandommove(lf, B_NOBADMOVES, B_TRUE, B_FALSE);
return B_FALSE;
}
// otherwise fall through to below movement code.
@ -1645,7 +1674,7 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) {
if (onein(2)) {
rest(lf, B_TRUE);
} else {
if (dorandommove(lf, B_NOBADMOVES, B_FALSE)) {
if (dorandommove(lf, B_NOBADMOVES, B_FALSE, B_FALSE)) {
rest(lf, B_TRUE);
}
}
@ -1915,7 +1944,7 @@ void aiturn(lifeform_t *lf) {
// DEFAULT - try to move in a random direction
if (db) dblog(".oO { default - moving randomly }");
dorandommove(lf, B_NOBADMOVES, B_TRUE); // this function will call rest() if we cant move
dorandommove(lf, B_NOBADMOVES, B_TRUE, B_FALSE); // this function will call rest() if we cant move
// somehow still here?
if (!lf->timespent) {
@ -2182,6 +2211,11 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
if (getnearbypeaceful(lf)) {
ok = B_TRUE;
}
} else if (ot->id == OT_S_SUPERHEAT) {
// got a potion?
if (victim && hasobwithflag(lf->pack, F_DRINKABLE) && haslof(lf->cell, victim->cell, LOF_NEED, NULL)) {
ok = B_TRUE;
}
} else {
if (db) dblog(".oO { cant cast %s - specialcase conditions not yet coded }", ot ? ot->name : "?unkownspell?");
return B_FALSE;

View File

@ -18,6 +18,9 @@
extern lifeform_t *player;
extern lifeform_t *godlf[];
extern int ngodlfs;
extern enum ERROR reason;
int applyarmourdamage(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damtype, lifeform_t *attacker) {
@ -512,11 +515,21 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
}
}
if (lfhasflag(lf, F_USEDPOISON)) {
int i;
flag_t *f;
killflagsofid(lf->flags, F_USEDPOISON);
angergodmaybe(R_GODPURITY, 100, GA_POISON);
angergodmaybe(R_GODMERCY, 25, GA_POISON);
angergodmaybe(R_GODBATTLE, 25, GA_POISON);
pleasegodmaybe(R_GODDEATH, 3);
for (i = 0; i < ngodlfs; i++) {
if (godlf[i]) {
f = lfhasflag(godlf[i], F_GODPOISON);
if (f) {
if (f->val[0]) {
pleasegodmaybe(godlf[i]->race->id, f->val[1]);
} else {
angergodmaybe(godlf[i]->race->id, f->val[1], GA_POISON);
}
}
}
}
}
}
}
@ -561,7 +574,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
enum BODYPART critpos = BP_NONE;
if (wep) {
wepsk = getobskill(wep);
wepsk = getobskill(wep->flags);
}
if (lfhasflag(lf, F_DEBUG)) {

120
data.c
View File

@ -1039,6 +1039,8 @@ void initobjects(void) {
addflag_real(lastbrand->flags, F_EQUIPCONFER, F_SLOWMOVE, 5, NA, NULL, PERMENANT, B_UNKNOWN, -1);
addbrand(BR_STEALTH, "of stealth", BP_FEET, B_UNCURSED, 0);
addflag_real(lastbrand->flags, F_EQUIPCONFER, F_SILENTMOVE, B_TRUE, NA, NULL, PERMENANT, B_UNKNOWN, -1);
addbrand(BR_PUNISHMENT, "of punishment", BP_FEET, B_CURSED, 80);
addflag_real(lastbrand->flags, F_EQUIPCONFER, F_HOTFEET, 1, DT_FIRE, "red-hot footwear", PERMENANT, B_UNKNOWN, -1);
// hands
addbrand(BR_POWER, "of power", BP_HANDS, B_UNCURSED, 0);
@ -1132,10 +1134,11 @@ void initobjects(void) {
addflag(lastmaterial->flags, F_MATCONVERT, MT_FIRE, NA, NA, "lump of melted wax");
addflag(lastmaterial->flags, F_MATCONVERTTEXT, MT_FIRE, NA, NA, "melts");
addflag(lastmaterial->flags, F_MATCONVERTTEXTPL, MT_FIRE, NA, NA, "melt");
addmaterial(MT_DRAGONWOOD, "dragonwood", 3);
addmaterial(MT_DRAGONWOOD, "wyrmwood", 3);
addflag(lastmaterial->flags, F_HARDNESS, 5, NA, NA, NULL);
addflag(lastmaterial->flags, F_CANGETWET, B_TRUE, NA, NA, NULL);
addflag(lastmaterial->flags, F_DTIMMUNE, DT_FIRE, NA, NA, NULL);
addflag(lastmaterial->flags, F_DTIMMUNE, DT_COLD, NA, NA, NULL);
addmaterial(MT_RUBBER, "rubber", 4);
addmaterial(MT_LEATHER, "leather", 4);
addflag(lastmaterial->flags, F_CANGETWET, B_TRUE, NA, NA, NULL);
@ -1593,7 +1596,6 @@ void initobjects(void) {
addflag(lastot->flags, F_REPELBLESSED, B_BLESSED, B_CURSED, NA, NULL);
addflag(lastot->flags, F_NOFEEL, B_TRUE, NA, NA, NULL);
addot(OT_PORTAL, "magic portal", "A magical portal to a different place...", MT_MAGIC, 0, OC_DFEATURE, SZ_LARGE);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, RR_VERYRARE, NULL);
addflag(lastot->flags, F_GLYPH, C_BOLDGREEN, '^', NA, NULL);
@ -1815,7 +1817,6 @@ void initobjects(void) {
addflag(lastot->flags, F_OBHP, 80, 80, NA, NULL);
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "50-100 stones");
addot(OT_ICICLE, "huge icicle", "A massive ice stalacmite.", MT_ICE, 200, OC_ROCK, SZ_LARGE);
addflag(lastot->flags, F_GLYPH, C_CYAN, '\'', NA, NULL);
addflag(lastot->flags, F_IMPASSABLE, SZ_MIN, SZ_LARGE, NA, NULL);
@ -2224,7 +2225,7 @@ void initobjects(void) {
addot(OT_POT_CANINETRACKING, "potion of canine tracking", "Mimics the effects of a 'canine tracking' spell.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_COMMON, NULL);
addot(OT_POT_GROWTH, "potion of growth", "A magical liquid which causes the imbiber's body to instantly undergo rapid growth.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_RARE, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 75, RR_RARE, NULL);
addflag(lastot->flags, F_VALUE, 50, NA, NA, NULL);
addot(OT_POT_HEALINGMIN, "potion of minor healing", "Restores 1-10 health to whoever drinks it.", MT_GLASS, 1, OC_POTION, SZ_TINY);
@ -2856,6 +2857,16 @@ void initobjects(void) {
// elemental - fire
///////////////////
// l1
addot(OT_S_BURNINGFEET, "hotfoot", "Heats the soles of the target's feet to an uncomfortable level, dealing 1 fire damage each turn they remain still.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "If the target is wearing metal footwear, damage is inceased to 2 per turn.");
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The spell's power determines its duration (maximum 6 turns).");
addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL);
addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_RANGE, 3, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 3, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
addot(OT_S_SPARK, "flambe", "Creates very hot but short lived burst of flame around the target, dealing 2d2 fire damage to creatures and objects.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL);
addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL);
@ -2884,15 +2895,37 @@ void initobjects(void) {
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_NEED, NA, NULL);
addot(OT_S_IMMOLATE, "immolate", "If the caster can successfully touch the target, they are instantly engulfed in flames.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
addflag(lastot->flags, F_RANGE, 1, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL);
addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_NEED, NA, NULL);
addot(OT_S_SUPERHEAT, "superheat", "Excites the liquid molecules in a single potion, causing its contents to explode upon impact (8d2 damage).", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_SPECIAL, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_NEED, NA, NULL);
// l3
addot(OT_S_FLAMEBURST, "flame burst", "Creates a radial blast of fire out from the caster, inflicting 2d6 fire damage to all within.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The size of the radial blast is based on the spell's power.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJSELF, NA, NA, NULL);
addot(OT_S_FIREBALL, "fireball", "Creates a huge ball of fire, dealing up to ^bpower^nd3 damage.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The damage is lower for enemies further away from the ball's centre.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
addflag(lastot->flags, F_RANGE, 6, NA, NA, NULL);
addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); // TODO: should be "near victim"
addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_NEED, NA, NULL);
// l4
addot(OT_S_FLAMEPILLAR, "flame pillar", "Creates a tall pillar of flame.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines the size and duration of the fire.");
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines the spell's range, and the fire's size.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
@ -2910,10 +2943,11 @@ void initobjects(void) {
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_RANGE, 3, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_WALLSTOP, NA, NULL);
addot(OT_S_FIREBALL, "fireball", "Creates a huge ball of fire, dealing up to ^bpower^nd3 damage.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
// l6
addot(OT_S_METEOR, "meteor", "Launches a white-hot meteorite towards the target location, dealing up to ^bpower^nd6+30 damage.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The damage is lower for enemies further away from the ball's centre.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 5, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); // TODO: should be "near victim"
addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_NEED, NA, NULL);
@ -3114,6 +3148,14 @@ void initobjects(void) {
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
// l3
addot(OT_S_EVAPORATE, "evaporate", "Instantly converts all water in the given area into scalding steam (including potions).", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The spell's power determines the amount of water affected.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER|TT_OBJECT, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
addot(OT_S_CALLLIGHTNING, "call lightning", "Blasts a single enemy with a bolt of lightning from the sky, dealing 3d6 damage (4d6 if outdoors).", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_AIR, NA, NA, NULL);
@ -3145,12 +3187,6 @@ void initobjects(void) {
addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL);
addflag(lastot->flags, F_TARGETTEDSPELL, TT_OBJECT, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
addot(OT_S_EVAPORATE, "evaporate", "Instantly converts all water in the given area into steam.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The spell's power determines the amount of water affected.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
addflag(lastot->flags, F_TARGETTEDSPELL, TT_OBJECT, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
addot(OT_S_SLEETSTORM, "sleet storm", "Creates an cloud of sleet, hampering vision and movement.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The spell's power determines the size of the storm.");
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "This spell's power is boosted when cast outside.");
@ -3484,6 +3520,11 @@ void initobjects(void) {
// modification
///////////////////
// l1
addot(OT_S_OBJECTGROWTH, "enlarge object", "Causes the target object to grow to an enormous size.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL);
addflag(lastot->flags, F_TARGETTEDSPELL, TT_OBJECT, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
addot(OT_S_HOLDPORTAL, "seal entrance", "Magically closes and jams a door, preventing it from opening.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ENCHANTMENT, NA, NA, NULL);
@ -5114,7 +5155,7 @@ void initobjects(void) {
addflag(lastot->flags, F_OBHP, 3, 3, NA, NULL);
addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL);
addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_WALKDAM,DT_FIRE, NA, NA, "8d4");
addflag(lastot->flags, F_WALKDAM,DT_FIRE, NA, NA, "6d4");
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_PRODUCESLIGHT, 10, NA, NA, NULL);
addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!");
@ -6644,7 +6685,7 @@ void initobjects(void) {
addflag(lastot->flags, F_GLYPH, C_BROWN, ')', NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_RARE, NULL);
addflag(lastot->flags, F_RARITY, H_CAVE, 100, RR_RARE, NULL);
addflag(lastot->flags, F_DAM, DT_BASH, 2, NA, NULL);
addflag(lastot->flags, F_DAM, DT_BASH, 3, NA, NULL);
addflag(lastot->flags, F_OBATTACKDELAY, 100, NA, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_LORE_ARCANA, NA, NA, NULL);
@ -6657,7 +6698,7 @@ void initobjects(void) {
addflag(lastot->flags, F_GLYPH, C_BROWN, ')', NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_RARE, NULL);
addflag(lastot->flags, F_RARITY, H_CAVE, 100, RR_RARE, NULL);
addflag(lastot->flags, F_DAM, DT_BASH, 2, NA, NULL);
addflag(lastot->flags, F_DAM, DT_BASH, 3, NA, NULL);
addflag(lastot->flags, F_OBATTACKDELAY, 100, NA, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_LORE_ARCANA, NA, NA, NULL);
@ -6671,7 +6712,7 @@ void initobjects(void) {
addflag(lastot->flags, F_GLYPH, C_BROWN, ')', NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_RARE, NULL);
addflag(lastot->flags, F_RARITY, H_CAVE, 100, RR_RARE, NULL);
addflag(lastot->flags, F_DAM, DT_BASH, 2, NA, NULL);
addflag(lastot->flags, F_DAM, DT_BASH, 3, NA, NULL);
addflag(lastot->flags, F_OBATTACKDELAY, 100, NA, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_LORE_ARCANA, NA, NA, NULL);
@ -6684,7 +6725,7 @@ void initobjects(void) {
addflag(lastot->flags, F_GLYPH, C_BROWN, ')', NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_VERYRARE, NULL);
addflag(lastot->flags, F_RARITY, H_CAVE, 100, RR_VERYRARE, NULL);
addflag(lastot->flags, F_DAM, DT_BASH, 2, NA, NULL);
addflag(lastot->flags, F_DAM, DT_BASH, 3, NA, NULL);
addflag(lastot->flags, F_OBATTACKDELAY, 100, NA, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_LORE_ARCANA, NA, NA, NULL);
@ -6698,7 +6739,7 @@ void initobjects(void) {
addflag(lastot->flags, F_GLYPH, C_BROWN, ')', NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_VERYRARE, NULL);
addflag(lastot->flags, F_RARITY, H_CAVE, 100, RR_VERYRARE, NULL);
addflag(lastot->flags, F_DAM, DT_BASH, 2, NA, NULL);
addflag(lastot->flags, F_DAM, DT_BASH, 3, NA, NULL);
addflag(lastot->flags, F_OBATTACKDELAY, 100, NA, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_LORE_ARCANA, NA, NA, NULL);
@ -6712,7 +6753,7 @@ void initobjects(void) {
addflag(lastot->flags, F_GLYPH, C_BROWN, ')', NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_VERYRARE, NULL);
addflag(lastot->flags, F_RARITY, H_CAVE, 100, RR_VERYRARE, NULL);
addflag(lastot->flags, F_DAM, DT_BASH, 2, NA, NULL);
addflag(lastot->flags, F_DAM, DT_BASH, 3, NA, NULL);
addflag(lastot->flags, F_OBATTACKDELAY, 100, NA, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_LORE_ARCANA, NA, NA, NULL);
@ -7590,6 +7631,7 @@ void initrace(void) {
addflag(lastrace->flags, F_CANWILL, OT_S_WISHLIMITED, NA, NA, "pw:10;");
addflag(lastrace->flags, F_CANWILL, OT_S_PLANESHIFT, NA, NA, "pw:1;");
// likes/dislikes
addflag(lastrace->flags, F_GODPOISON, B_FALSE, 100, NA, NULL);
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "destroying the undead");
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "killing evil creatures");
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "blessing objects");
@ -7644,6 +7686,7 @@ void initrace(void) {
addflag(lastrace->flags, F_CANWILL, OT_A_HURRICANESTRIKE, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_A_FLURRY, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_A_SHIELDBASH, NA, NA, NULL);
addflag(lastrace->flags, F_GODPOISON, B_FALSE, 25, NA, NULL);
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "victory in battle");
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "prolonged peace");
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "the use of poison");
@ -7742,6 +7785,7 @@ void initrace(void) {
addflag(lastrace->flags, F_CANWILL, OT_S_WISHLIMITED, NA, NA, "pw:10;");
addflag(lastrace->flags, F_CANWILL, OT_S_PLANESHIFT, NA, NA, "pw:1;");
// likes
addflag(lastrace->flags, F_GODPOISON, B_TRUE, 3, NA, NULL);
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "killing (especially the good-aligned)");
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "attacking the helpless");
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "casting necromancy spells");
@ -7834,6 +7878,7 @@ void initrace(void) {
addflag(lastrace->flags, F_CANWILL, OT_S_DISPERSAL, NA, NA, "pw:10;");
addflag(lastrace->flags, F_CANWILL, OT_S_SLEEP, NA, NA, "pw:10;");
addflag(lastrace->flags, F_CANWILL, OT_S_PLANESHIFT, NA, NA, "pw:1;");
addflag(lastrace->flags, F_GODPOISON, B_FALSE, 25, NA, NULL);
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "the successful casting of healing spells");
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "allowing fleeing creatures to escape");
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "acts of charity");
@ -7910,7 +7955,7 @@ void initrace(void) {
addflag(lastrace->flags, F_MINIONS, 20, 1, 3, "goblin warrior");
addflag(lastrace->flags, F_MORALE, 10, NA, NA, NULL);
addrace(R_COCKATRICE, "cockatrice", 5, 'c', C_YELLOW, MT_FLESH, RC_MAGIC, "A small two-legged dragon with a rooster's head. Its touch is said to petrify the flesh of living creatures.");
addrace(R_COCKATRICE, "cockatrice", 5, 'c', C_YELLOW, MT_FLESH, RC_DRAGON, "A small two-legged wyrm with a rooster's head. Its touch is said to petrify the flesh of living creatures.");
setbodytype(lastrace, BT_QUADRAPED);
addbodypart(lastrace, BP_WINGS, NULL);
addbodypart(lastrace, BP_TAIL, NULL);
@ -8016,6 +8061,7 @@ void initrace(void) {
addflag(lastrace->flags, F_STARTSKILL, SK_PERCEPTION, PR_ADEPT, NA, NULL);
addflag(lastrace->flags, F_NOISETEXT, N_FLY, 1, NA, "^flapping wings");
addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL);
addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL);
addrace(R_TRICLOPS, "triclops", 160, 'H', C_BROWN, MT_FLESH, RC_HUMANOID, "The three-eyes triclops race are blessed with extraordiny perceptive and are nearly impossible to surprise. They commonly use their third eye to stun enemies, then finish them off with their huge weapons.");
setbodytype(lastrace, BT_HUMANOID);
@ -10567,8 +10613,8 @@ void initrace(void) {
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
// end animals
// dragons
addrace(R_DRAGONBLUE, "blue dragon", 400, 'D', C_BLUE, MT_FLESH, RC_DRAGON, "Blue dragons are massive reptilian creatures who can (and will) consume almost any living creature.");
// dragons / wyrms
addrace(R_DRAGONBLUE, "blue wyrm", 400, 'D', C_BLUE, MT_FLESH, RC_DRAGON, "Blue wyrms are massive reptilian creatures who can (and will) consume almost any living creature.");
setbodytype(lastrace, BT_HUMANOID);
addbodypart(lastrace, BP_WINGS, NULL);
addbodypart(lastrace, BP_TAIL, NULL);
@ -10616,7 +10662,7 @@ void initrace(void) {
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CARNIVORE, B_TRUE, NA, NA, NULL);
addrace(R_DRAGONBLUEY, "young blue dragon", 150, 'D', C_BLUE, MT_FLESH, RC_DRAGON, "Blue dragons are massive reptilian creatures who can (and will) consume almost any living creature.");
addrace(R_DRAGONBLUEY, "young blue wyrms", 150, 'D', C_BLUE, MT_FLESH, RC_DRAGON, "Blue wyrms are massive reptilian creatures who can (and will) consume almost any living creature.");
setbodytype(lastrace, BT_HUMANOID);
addbodypart(lastrace, BP_WINGS, NULL);
addbodypart(lastrace, BP_TAIL, NULL);
@ -10664,7 +10710,7 @@ void initrace(void) {
addflag(lastrace->flags, F_WANTS, OT_GOLD, NA, NA, NULL);
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CARNIVORE, B_TRUE, NA, NA, NULL);
addrace(R_DRAGONBLUEA, "ancient blue dragon", 600, 'D', C_BLUE, MT_FLESH, RC_DRAGON, "Blue dragons are massive reptilian creatures who can (and will) consume almost any living creature.");
addrace(R_DRAGONBLUEA, "ancient blue wyrms", 600, 'D', C_BLUE, MT_FLESH, RC_DRAGON, "Blue wyrms are massive reptilian creatures who can (and will) consume almost any living creature.");
setbodytype(lastrace, BT_HUMANOID);
addbodypart(lastrace, BP_WINGS, NULL);
addbodypart(lastrace, BP_TAIL, NULL);
@ -10720,7 +10766,7 @@ void initrace(void) {
addflag(lastrace->flags, F_CARNIVORE, B_TRUE, NA, NA, NULL);
addrace(R_DRAGONRED, "red dragon", 400, 'D', C_RED, MT_FLESH, RC_DRAGON, "Red dragons are massive evil reptilians who thrive on destruction, especially by means of fire.");
addrace(R_DRAGONRED, "red wyrms", 400, 'D', C_RED, MT_FLESH, RC_DRAGON, "Red wyrms are massive evil reptilians who thrive on destruction, especially by means of fire.");
setbodytype(lastrace, BT_HUMANOID);
addbodypart(lastrace, BP_WINGS, NULL);
addbodypart(lastrace, BP_TAIL, NULL);
@ -10768,7 +10814,7 @@ void initrace(void) {
addflag(lastrace->flags, F_WANTS, OT_GOLD, NA, NA, NULL);
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CARNIVORE, B_TRUE, NA, NA, NULL);
addrace(R_DRAGONREDY, "young red dragon", 150, 'D', C_RED, MT_FLESH, RC_DRAGON, "Red dragons are massive evil reptilians who thrive on destruction, especially by means of fire.");
addrace(R_DRAGONREDY, "young red wyrms", 150, 'D', C_RED, MT_FLESH, RC_DRAGON, "Red wyrms are massive evil reptilians who thrive on destruction, especially by means of fire.");
setbodytype(lastrace, BT_HUMANOID);
addbodypart(lastrace, BP_WINGS, NULL);
addbodypart(lastrace, BP_TAIL, NULL);
@ -10812,7 +10858,7 @@ void initrace(void) {
addflag(lastrace->flags, F_WANTS, OT_GOLD, NA, NA, NULL);
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CARNIVORE, B_TRUE, NA, NA, NULL);
addrace(R_DRAGONREDA, "ancient red dragon", 600, 'D', C_RED, MT_FLESH, RC_DRAGON, "Red dragons are massive evil reptilians who thrive on destruction, especially by means of fire.");
addrace(R_DRAGONREDA, "ancient red wyrms", 600, 'D', C_RED, MT_FLESH, RC_DRAGON, "Red wyrms are massive evil reptilians who thrive on destruction, especially by means of fire.");
setbodytype(lastrace, BT_HUMANOID);
addbodypart(lastrace, BP_WINGS, NULL);
addbodypart(lastrace, BP_TAIL, NULL);
@ -10863,7 +10909,7 @@ void initrace(void) {
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CARNIVORE, B_TRUE, NA, NA, NULL);
addrace(R_DRAGONWHITE, "white dragon", 400, 'D', C_WHITE, MT_FLESH, RC_DRAGON, "Although white dragons are smaller than other varieties, their icy breath still makes them a formidable threat.");
addrace(R_DRAGONWHITE, "white wyrms", 400, 'D', C_WHITE, MT_FLESH, RC_DRAGON, "Although white wyrms are smaller than other varieties, their icy breath still makes them a formidable threat.");
setbodytype(lastrace, BT_HUMANOID);
addbodypart(lastrace, BP_WINGS, NULL);
addbodypart(lastrace, BP_TAIL, NULL);
@ -10910,7 +10956,7 @@ void initrace(void) {
addflag(lastrace->flags, F_WANTS, OT_GOLD, NA, NA, NULL);
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CARNIVORE, B_TRUE, NA, NA, NULL);
addrace(R_DRAGONWHITEY, "young white dragon", 150, 'D', C_WHITE, MT_FLESH, RC_DRAGON, "Although white dragons are smaller than other varieties, their icy breath still makes them a formidable threat.");
addrace(R_DRAGONWHITEY, "young white wyrms", 150, 'D', C_WHITE, MT_FLESH, RC_DRAGON, "Although white wyrms are smaller than other varieties, their icy breath still makes them a formidable threat.");
setbodytype(lastrace, BT_HUMANOID);
addbodypart(lastrace, BP_WINGS, NULL);
addbodypart(lastrace, BP_TAIL, NULL);
@ -10952,7 +10998,7 @@ void initrace(void) {
addflag(lastrace->flags, F_WANTS, OT_GOLD, NA, NA, NULL);
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CARNIVORE, B_TRUE, NA, NA, NULL);
addrace(R_DRAGONWHITEA, "ancient white dragon", 600, 'D', C_WHITE, MT_FLESH, RC_DRAGON, "Although white dragons are smaller than other varieties, their icy breath still makes them a formidable threat.");
addrace(R_DRAGONWHITEA, "ancient white wyrms", 600, 'D', C_WHITE, MT_FLESH, RC_DRAGON, "Although white wyrms are smaller than other varieties, their icy breath still makes them a formidable threat.");
setbodytype(lastrace, BT_HUMANOID);
addbodypart(lastrace, BP_WINGS, NULL);
addbodypart(lastrace, BP_TAIL, NULL);
@ -11002,7 +11048,7 @@ void initrace(void) {
addflag(lastrace->flags, F_WANTS, OT_GOLD, NA, NA, NULL);
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CARNIVORE, B_TRUE, NA, NA, NULL);
// end dragons
// end dragons / wyrms
// insects
addrace(R_BLASTBUG, "blastbug", 2, 'x', C_ORANGE, MT_STONE, RC_INSECT, "Blastbugs have somehow evolved the ability to de-stabalise nearby oxygen molecules, resulting in devestation explosions.");
@ -11468,7 +11514,7 @@ void initrace(void) {
addflag(lastrace->flags, F_HASATTACK, OT_TOUCHCHILL, 7, NA, NULL);
addflag(lastrace->flags, F_DTVULN, DT_FIRE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "shoddy cloak");
addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 3, NA, "scheeches^a screech");
addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 3, NA, "screeches^a screech");
addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SEEINDARK, B_TRUE, NA, NA, NULL);
@ -11779,7 +11825,7 @@ void initraceclasses(void) {
addraceclass(RC_ANIMAL, "animal", "animals and insects", SK_LORE_NATURE);
addraceclass(RC_AQUATIC, "aquatic creature", "aquatic creatures", SK_LORE_NATURE);
addraceclass(RC_DEMON, "demon", "demons", SK_LORE_DEMONS);
addraceclass(RC_DRAGON, "dragon", "dragons", SK_LORE_DRAGONS);
addraceclass(RC_DRAGON, "wyrm", "wyrms", SK_LORE_DRAGONS);
addraceclass(RC_GOD, "god", "dieties", SK_NONE);
addraceclass(RC_HUMANOID, "humanoid", "humanoid creatures", SK_LORE_HUMANOID);
addraceclass(RC_INSECT, "insect", "insects and animals", SK_LORE_NATURE);
@ -11965,17 +12011,15 @@ void initskills(void) {
addskilldesc(SK_TWOWEAPON, PR_EXPERT, "^gYou gain the 'flurry attack' ability.^n", B_FALSE);
addskilldesc(SK_TWOWEAPON, PR_MASTER, "^gYou can now deflect attacks with your second weapon.^n", B_TRUE);
// knowledge
// descriptions for all of these will be added later.
addskill(SK_LORE_ARCANA, "Lore:Arcana", "Allows you a chance of recognising magical objects and creatures.", 5);
addskilldesc(SK_LORE_ARCANA, PR_NOVICE, "^gYou can attempt to identify objects with the 'inspect' ability.^n", B_FALSE);
addskilldesc(SK_LORE_ARCANA, PR_ADEPT, "^gYou gain the 'study scrolls' ability.", B_FALSE);
// descriptions will be added later.
addskill(SK_LORE_DEMONS, "Lore:Demonology", "Determines your knowledge about demons.", 5);
// descriptions will be added later.
addskill(SK_LORE_DRAGONS, "Lore:Dragons", "Determines your knowledge about dragons.", 5);
// descriptions will be added later.
addskill(SK_LORE_HUMANOID, "Lore:Humanoid", "Determines your knowledge about humanoid (bipedal) creatures.", 5);
addskill(SK_LORE_NATURE, "Lore:Nature", "Determines your knowledge of plants, animals and insects.", 5);
addskill(SK_LORE_UNDEAD, "Lore:Undead", "Determines your knowledge of the undead.", 5);
addskill(SK_LORE_DRAGONS, "Lore:Wyrms", "Determines your knowledge about wryms.", 5);
// weaponry
addskill(SK_AXES, "Axes", "Helps you use chopping weapons like axes.", 50);

Binary file not shown.

13
defs.h
View File

@ -19,6 +19,7 @@
// Text
#define TEXT_WARN_ATTACK_NOXP "You will not gain experience until you train. Really attack?"
#define TEXT_WARN_CLIMB "Really attempt to climb without Climbing skill?"
#define TEXT_WARN_FLY "Warning: while airborne you will not map your surroundings."
// Defaults
#define DEF_AIFOLLOWTIME (50) // if target lf is out of view
@ -1360,13 +1361,17 @@ enum OBTYPE {
OT_S_WINDSHIELD,
// -- elemental - fire
OT_S_BLADEBURN,
OT_S_BURNINGFEET,
OT_S_BURNINGWAVE,
OT_S_FIREDART,
OT_S_FIREBALL,
OT_S_FLAMEPILLAR,
OT_S_FLAMEBURST,
OT_S_IMMOLATE,
OT_S_METEOR,
OT_S_PYROMANIA,
OT_S_SPARK,
OT_S_SUPERHEAT,
// -- elemental - ice
OT_S_ABSOLUTEZERO,
OT_S_CHILL,
@ -1429,6 +1434,7 @@ enum OBTYPE {
OT_S_KNOCK,
OT_S_LIGHT,
OT_S_MENDING,
OT_S_OBJECTGROWTH,
OT_S_PASSWALL,
OT_S_PETRIFY,
OT_S_POLYMORPH,
@ -2100,7 +2106,7 @@ enum FLAG {
F_GOESON, // val0 = where it can be equipped.
F_GOESONMULTI, // ob is equipped on _ALL_ F_GOESON flags, rather than
// equipped on _ONE OF_ the.
F_BONUS, // val0=bonus/penalty to damage/armour. ie. +1 sword
F_BONUS, // val0=bonus/penalty to damage+accuracy/armour. ie. +1 sword
F_THROWMISSILE, // weapon would make a good thrown missle - used by AI
F_UNIQUE, // only one may appear
F_GLYPH, // override the glyph with the first char of text.
@ -2508,6 +2514,8 @@ enum FLAG {
F_TOOKACTION, // lf purposely took action in their last turn.
F_MOVED, // lf purposely walked/flew/swum/moved in prev turn
F_HASBEENMOVED, // an object moved this lf since their last turn.
F_HOTFEET, // target takes v0 damage of type v1 unless they move.
// text = killed by xxx
F_WASROBBED, // your stuff was stolen while you were
// unconscious. announce it when you wake up.
F_TURNED, // lf turned this turn.
@ -2776,6 +2784,8 @@ enum FLAG {
// if v0 is b_true, means this is a goddess
F_GODLIKES, // text = something this god likes (ie. incs piety)
F_GODDISLIKES, // text = something this god likes (ie. decs piety)
F_GODPOISON, // v0=TRUE: god likes using poison. gain v1 piety
// v0=FALSE: god hates using poison. lose v1 piety
// for all sacrifice flags:
// v2: amt of piety for each sacrifice
// text: "the xxx disappears in yyyy"
@ -3932,6 +3942,7 @@ enum BRAND {
BR_ANTIMAG,
BR_CONCEALMENT,
BR_SHARPNESS,
BR_PUNISHMENT,
BR_PYROMANIA,
BR_REVENGE,
BR_REFLECTION,

167
god.c
View File

@ -570,6 +570,18 @@ enum PIETYLEV getpietylev(enum RACE rid, enum COLOUR *col, char *happiness) {
return PL_INDIFFERENT;
}
int getprayedgods(lifeform_t **retgod, int *nretgods) {
int i;
*nretgods = 0;
for (i = 0; i < ngodlfs; i++) {
if (lfhasflag(godlf[i], F_PRAYEDTO)) {
retgod[*nretgods] = godlf[i];
(*nretgods)++;
}
}
return *nretgods;
}
lifeform_t *getrandomgod(void) {
if (ngodlfs == 0) {
return NULL;
@ -673,10 +685,10 @@ int godgiftmaybe(enum RACE rid, int fromtemple) {
rollagain = B_FALSE;
switch (rnd(1,2)) {
case 1:
snprintf(obtogive, BUFLEN, "excellent branded weapon");
snprintf(obtogive, BUFLEN, "excellent appropriate branded weapon");
break;
case 2:
snprintf(obtogive, BUFLEN, "excellent branded armour");
snprintf(obtogive, BUFLEN, "excellent appropriate branded armour");
break;
}
}
@ -1005,7 +1017,7 @@ void pleasegod(enum RACE rid, int amt) {
msg("You feel Lumara's presense nearby.");
break;
case R_GODMERCY:
msg("You feel a sense of peace.");
msg("You feel a sense of serenity.");
break;
case R_GODPURITY:
msg("You hear a distant choir singing.");
@ -1042,6 +1054,7 @@ void pleasegodmaybe(enum RACE rid, int amt) {
int prayto(lifeform_t *lf, lifeform_t *god) {
int piety,i;
char assisttext[BUFLEN];
taketime(lf, getactspeed(lf));
@ -1076,14 +1089,35 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
// if we get here, piety is >= 100.
// you get some help...
godsay(god->race->id, B_TRUE, "You appear in need of assistance, mortal!");
switch (god->race->id) {
case R_GODBATTLE:
strcpy(assisttext, "Message received, soldier!");
break;
case R_GODTHIEVES:
strcpy(assisttext, "What mischief have you gotten yourself into, then?");
break;
case R_GODDEATH:
strcpy(assisttext, "You desire a favour, fleshling?");
break;
case R_GODMERCY:
strcpy(assisttext, "I hear your prayer, child.");
break;
case R_GODMAGIC:
strcpy(assisttext, "One calls upon the eldritch powers...");
break;
case R_GODPURITY:
default:
strcpy(assisttext, "You appear in need of assistance, mortal!");
break;
}
godsay(god->race->id, B_TRUE, assisttext);
switch (god->race->id) {
lifeform_t *l;
int donesomething = B_FALSE;
int donesomething = B_FALSE,n;
cell_t *c;
object_t *o;
object_t *oposs[MAXPILEOBS];
int noposs = 0, n;
case R_GODBATTLE:
if (isinbattle(player, B_TRUE)) {
int redo = B_TRUE;
@ -1121,11 +1155,35 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
}// end while redo
} else {
// not in battle...
int redo = B_TRUE,i;
object_t *o;
int done = B_FALSE;
object_t *o,*wep;
wep = getweapon(player);
if (uncurse_one_equipped(lf, "\"Be free of your curse!\"")){
done = B_TRUE;
}
if (!done) {
// try to repair armour or undull weapons
i = 0;
for (o = lf->pack->first ; o ; o = o->next) {
if (isequipped(o)) {
if (isdamaged(o) || (getobbonus(o, B_FALSE) < 0)) {
dospelleffects(lf, OT_S_MENDING, 10, NULL, o, NULL, B_BLESSED, NULL, B_FALSE);
i++;
}
}
}
if (i) {
msg("\"Keep fighting, warrior!\"");
done = B_TRUE;
}
}
if (!done) {
int redo = B_TRUE;
while (redo) {
redo = B_FALSE;
switch (rnd(1,3)) {
switch (rnd(1,2)) {
case 1: // detect life
msg("\"Seek out battle in my name!\"");
dospelleffects(god, OT_S_DETECTLIFE, 10, lf, NULL, lf->cell, B_BLESSED, NULL, B_TRUE);
@ -1139,23 +1197,10 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
redo = B_TRUE;
}
break;
case 3: // repair armour
i = 0;
for (o = lf->pack->first ; o ; o = o->next) {
if (isdamaged(o)) {
dospelleffects(lf, OT_S_MENDING, 10, NULL, o, NULL, B_BLESSED, NULL, B_FALSE);
i++;
}
}
if (i) {
msg("\"Keep fighting, warrior!\"");
} else {
redo = B_TRUE;
}
break;
} // end switch
}// end while redo
}
}
break;
case R_GODPURITY:
msg("\"Witness the holy radiance of purity!\"");
@ -1163,17 +1208,12 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
if (c) {
dospelleffects(god, OT_S_LIGHT, 10, NULL, NULL, c, B_BLESSED, NULL, B_TRUE);
}
// get list of cursed obs
noposs = 0;
// uncurse ALL equipped obs
for (o = lf->pack->first ; o ; o = o->next) {
if (iscursed(o)) {
oposs[noposs++] = o;
}
}
if (noposs) {
o = oposs[rnd(0,noposs-1)];
if (iscursed(o) && isequipped(o)) {
blessob(o);
}
}
// smite evil
for (l = lf->cell->map->lf ; l ; l = l->next) {
if (getalignment(l) == AL_EVIL) {
@ -1191,12 +1231,11 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
msg("\"Behold, the power of death!\"");
c = NULL;
n = OT_NONE;
switch (rnd(0,4)) {
switch (rnd(0,3)) {
case 0: n = OT_S_PAIN; break;
case 1: n = OT_S_DRAINLIFE; break;
case 2: n = OT_S_BLINDNESS; break;
case 3: n = OT_S_FLAYFLESH; break;
case 4: n = OT_S_HECTASSERVANT;
case 2: n = OT_S_FLAYFLESH; break;
case 3: n = OT_S_HECTASSERVANT;
c = getrandomadjcell(player->cell, WE_WALKABLE, B_ALLOWEXPAND);
break;
}
@ -1210,14 +1249,21 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
}
if (n != OT_NONE) {
// kill first lifeform in sight.
for (i = 1; i < lf->nlos; i++) {
lifeform_t *who;
who = lf->los[i]->lf;
if (who && !areallies(lf, who)) {
if (isundead(who)) {
makepeaceful(who, god);
} else if (gethitdice(who) <= 4) {
// instakill
who->lastdamtype = DT_NECROTIC;
setlastdam(who, "Hecta's finger of death.");
who->hp = 0;
} else {
castspell(god, n, who, NULL, who->cell, NULL, NULL);
dospelleffects(god, n, 20, who, NULL, who->cell, B_UNCURSED, NULL, B_FALSE);
break;
}
}
@ -1277,6 +1323,13 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
int redo = B_TRUE;
object_t *possob[MAXPILEOBS];
int npossob,i,first;
object_t *o;
// uncurse one equipped ob
if (uncurse_one_equipped(lf, "\"Curses, schmurses!\"")){
redo = B_FALSE;
}
while (redo) {
redo = B_FALSE;
switch (rnd(1,2)) {
@ -1332,10 +1385,18 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
case R_GODMAGIC:
if (player->mp <= (getmaxmp(player)/2)) {
gainmp(lf, getmaxmp(lf));
msg("\"I have replenished your magical reserves!\"");
msg("\"One's magical reserves have been filled!\"");
} else {
object_t *toid[MAXPILEOBS],*touncurse[MAXPILEOBS];
int idnum = 0, uncursenum = 0;
int done = B_FALSE;
// uncurse one equipped ob
if (uncurse_one_equipped(lf, "\"One's curse is lifted.\"")){
done = B_TRUE;
}
if (!done) {
// any unid'd scrolls/books?
for (o = player->pack->first ; o ; o = o->next) {
if ((o->type->obclass->id == OC_SCROLL) || (o->type->obclass->id == OC_BOOK)) {
@ -1349,17 +1410,18 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
}
if (idnum) {
msg("\"I grant you the favour of knowledge!\"");
msg("\"One is granted the favour of knowledge!\"");
o = toid[rnd(0,idnum-1)];
dospelleffects(god, OT_S_IDENTIFY, 10, NULL, o, NULL, B_UNCURSED, NULL, B_FALSE);
} else if (uncursenum) {
msg("\"I grant you the favour of redemption!\"");
msg("\"One is granted the favour of redemption!\"");
o = touncurse[rnd(0,uncursenum-1)];
uncurseob(o, NULL);
} else {
// just regain mana.
gainmp(lf, getmaxmp(lf));
msg("\"I have replenished your magical reserves!\"");
msg("\"One's magical reserves have been filled!\"");
}
}
}
break;
@ -1379,6 +1441,9 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
castspell(god, OT_S_HEALINGMAJ, player, NULL, player->cell, NULL, NULL);
donesomething = B_TRUE;
}
// uncurse one equipped ob
uncurse_one_equipped(lf, "\"Let thy curse be ended!\"");
break;
default:
break;
@ -1410,3 +1475,25 @@ void setpiety(enum RACE rid, int amt) {
f->val[0] = amt;
limit(&f->val[0], PIETY_MIN, PIETY_MAX);
}
// uncurse one equipped ob
// returns true if we do somethign
int uncurse_one_equipped(lifeform_t *lf, char *text) {
object_t *possob[MAXPILEOBS],*o;
int npossob;
npossob = 0;
for (o = lf->pack->first ; o ; o = o->next) {
if (iscursed(o) && isequipped(o)) {
possob[npossob++] = o;
}
}
if (npossob) {
o = possob[rnd(0,npossob-1)];
if (text) {
msg(text);
}
blessob(o);
return B_TRUE;
}
return B_FALSE;
}

2
god.h
View File

@ -7,6 +7,7 @@ lifeform_t *findgod(enum RACE rid);
enum RACE getopposinggod(enum RACE rid);
int getpiety(enum RACE rid);
enum PIETYLEV getpietylev(enum RACE rid, enum COLOUR *col, char *happiness);
int getprayedgods(lifeform_t **retgod, int *nretgods);
lifeform_t *getrandomgod(void);
lifeform_t *getrandomprayedgod(void);
lifeform_t *godappears(enum RACE rid, cell_t *where);
@ -19,3 +20,4 @@ void pleasegod(enum RACE rid, int amt);
void pleasegodmaybe(enum RACE rid, int amt);
int prayto(lifeform_t *lf, lifeform_t *god);
void setpiety(enum RACE rid, int amt);
int uncurse_one_equipped(lifeform_t *lf, char *text);

59
io.c
View File

@ -1468,8 +1468,17 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
donesomething = B_TRUE;
}
break;
case F_HOTFEET:
if (isplayer(lf)) {
msg("Your %s feel like they are on fire!", getbodypartname(lf, BP_FEET));
donesomething = B_TRUE;
} else {
msg("%s%s %s are on fire!", lfname, getpossessive(lfname), getbodypartname(lf, BP_FEET));
donesomething = B_TRUE;
}
break;
case F_ICESLIDE:
msg("Sheets of ice start forming under %s%s feet!",lfname, getpossessive(lfname));
msg("Sheets of ice start forming under %s%s %s!",lfname, getpossessive(lfname), getbodypartname(lf, BP_FEET));
donesomething = B_TRUE;
break;
case F_INJURY:
@ -1593,6 +1602,9 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
case F_FLYING:
msg("%s begin%s to fly!",lfname, isplayer(lf) ? "" : "s");
donesomething = B_TRUE;
if (isplayer(lf)) {
real_warnabout(TEXT_WARN_FLY, PERMENANT, B_FALSE);
}
break;
case F_FROZEN:
// strip "frozen" out...
@ -1633,6 +1645,9 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
break;
case F_LEVITATING:
msg("%s begin%s to levitate in the air!",lfname, isplayer(lf) ? "" : "s");
if (isplayer(lf)) {
real_warnabout(TEXT_WARN_FLY, PERMENANT, B_FALSE);
}
donesomething = B_TRUE;
break;
case F_MAGSHIELD:
@ -2140,6 +2155,15 @@ int announceflagloss(lifeform_t *lf, flag_t *f) {
donesomething = B_TRUE;
}
break;
case F_HOTFEET:
if (isplayer(lf)) {
msg("Your %s feel cooler now.", getbodypartname(lf, BP_FEET));
donesomething = B_TRUE;
} else {
msg("%s%s %s look cooler now", lfname, getpossessive(lfname), getbodypartname(lf, BP_FEET));
donesomething = B_TRUE;
}
break;
case F_ICESLIDE:
msg("%s%s feet are longer generating ice.",lfname, getpossessive(lfname));
donesomething = B_TRUE;
@ -5892,6 +5916,10 @@ char *makedesc_ob(object_t *o, char *retbuf) {
sprintf(buf2, "%s decreases gravity around you.\n", buf);
strncat(retbuf, buf2, HUGEBUFLEN);
break;
case F_HOTFEET:
sprintf(buf2, "%s causes your feet to constantly burn.\n", buf);
strncat(retbuf, buf2, HUGEBUFLEN);
break;
case F_DODGES:
sprintf(buf2, "%s allows you to dodge attacks.\n", buf);
strncat(retbuf, buf2, HUGEBUFLEN);
@ -9155,13 +9183,7 @@ void handleinput(void) {
break;
case 'm': // 'm'agic/abilities (magic)
addflag(player->flags, F_LASTCMD, NA, NA, NA, temp);
if (wantrepeat) {
//domagic(repeatflag.val[2], repeatflag.val[0], repeatflag.val[1]);
// don't repeat the target cell!
domagic(repeatflag.val[2], NA, NA);
} else {
domagic(OT_NONE, NA, NA);
}
break;
case 'M': // 'M'emorise magic/ability shortcut
domemmagic();
@ -11903,9 +11925,13 @@ void showlfstats(lifeform_t *lf, int showall) {
mvwprintw(mainwin, y, 0, "%s %s surrounded by a holy aura.", you(lf), is(lf));
y++;
}
f = lfhasknownflag(lf, F_HOTFEET);
if (f) {
msg("%s feet are on fire (%s %s damage per turn stationary)",your(lf), f->val[0], getdamnamenoun(f->val[1]));
}
f = lfhasknownflag(lf, F_ICESLIDE);
if (f) {
msg("%s%s feet automatically generating sheets of ice.",your(lf));
msg("%s feet automatically generating sheets of ice.",your(lf));
}
f = lfhasknownflag(lf, F_FREEZINGTOUCH);
@ -12333,9 +12359,15 @@ void tombstone(lifeform_t *lf) {
endwin();
}
int warnabout(char *what) {
return real_warnabout(what, DEF_WARNINGTIME, B_TRUE);
}
//
// returns TRUE if you answered 'Yes' or you'd already accepted this warning
int warnabout(char *what) {
//
int real_warnabout(char *what, int lifetime, int doquestion) {
char ch = 'n';
warning_t *w;
// have we already warned about this?
@ -12343,13 +12375,18 @@ int warnabout(char *what) {
if (w) {
w->lifetime = DEF_WARNINGTIME;
ch = 'y';
} else {
} else if (doquestion) {
char ques[BUFLEN];
sprintf(ques, "%s", what);
ch = askchar(what, "yn", "n", B_TRUE, B_FALSE);
} else {
more();
msg("%s", what);
more();
ch = 'y';
}
if (ch == 'y') {
addwarning(what);
addwarning(what, lifetime);
return B_TRUE;
}
return B_FALSE;

1
io.h
View File

@ -136,4 +136,5 @@ void tombstone(lifeform_t *lf);
void updatestatus(void);
int updateviewfor(cell_t *cell);
int warnabout(char *what);
int real_warnabout(char *what, int lifetime, int doquestion);
char wrapprint(WINDOW *win, int *y, int *x, char *format, ... );

116
lf.c
View File

@ -1157,12 +1157,15 @@ int cansee_real(lifeform_t *viewer, lifeform_t *viewee, int uselos) {
}
// viewer asleep?
if (lfhasflag(viewer, F_ASLEEP)) {
f = lfhasflag(viewer, F_ASLEEP);
if (f) {
if (f->val[1] != ST_MEDITATING) {
// can only 'see' yourself
if (viewee != viewer) {
return B_FALSE;
}
}
}
/*
if (areallies(player, viewee) && !isplayer(viewee) && canhear(player, viewee->cell, 3)) {
@ -2427,7 +2430,7 @@ void die(lifeform_t *lf) {
if (god && !godisangry(god->race->id)) {
switch (god->race->id) {
case R_GODBATTLE:
godsay(god->race->id, B_TRUE, "Rest in peace, brave warrior!"); more();
godsay(god->race->id, B_TRUE, "Rest in peace, brave warrior."); more();
break;
case R_GODDEATH:
godsay(god->race->id, B_TRUE, "Come to me, my servant..."); more();
@ -6826,9 +6829,8 @@ int getattacks(lifeform_t *lf, int *min, int *max) {
float getmaxcarryweight(lifeform_t *lf) {
float max;
float mod;
enum ATTRBRACKET sbrack;
/*
sbrack = getattrbracket(getattr(lf, A_STR), A_STR, NULL);
switch (sbrack) {
case AT_EXLOW:
@ -6854,6 +6856,10 @@ float getmaxcarryweight(lifeform_t *lf) {
}
max = getlfweight(lf, B_NOOBS) * mod;
*/
// half your weight + your strength
max = (getlfweight(lf, B_NOOBS)/2) + getattr(lf, A_STR);
if (lfhasflagval(lf, F_INJURY, IJ_RIBBROKEN, NA, NA, NULL)) {
max /= 2;
@ -8531,7 +8537,7 @@ enum SKILLLEVEL getweaponskill(lifeform_t *lf, object_t *o) {
if (!o) {
return getskill(lf, SK_UNARMED);
}
sk = getobskill(o);
sk = getobskill(o->flags);
if (sk) {
enum SKILLLEVEL weplev;
weplev = getskill(lf, sk->id);
@ -9290,7 +9296,7 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp) {
if (isplayer(lf)) addflag(o->flags, F_NOPOINTS, B_TRUE, NA, NA, NULL);
// give one extra rank of skill in this weapon
sk = getobskill(o);
sk = getobskill(o->flags);
giveskill(lf, sk->id);
}
}
@ -12104,6 +12110,37 @@ char *assignnpcname(lifeform_t *lf) {
return sel->name;
}
void autoshortcut(lifeform_t *lf, enum OBTYPE spellid) {
flag_t *retflag[MAXCANDIDATES],*f;
int nretflags,i,found = B_FALSE;
int min = 1;
objecttype_t *ot = NULL;
getflags(lf->flags, retflag, &nretflags, F_CANCAST, F_CANWILL, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->val[0] == spellid) {
found = B_TRUE;
}
}
if (!found) {
return;
}
ot = findot(spellid);
if (ot) {
// set to lowest possible shortcut
getflags(lf->flags, retflag, &nretflags, F_CANCAST, F_CANWILL, F_NONE);
for (i = 0; i < nretflags; i++) {
if (retflag[i]->val[0] > min) {
min = retflag[i]->val[0];
}
}
if (min < 10) {
addflag(lf->flags, F_SHORTCUT, min, NA, NA, ot->name);
}
}
}
// make sure player has at least novice skill in all their start weapons/armour
void autoskill(lifeform_t *lf) {
skill_t *sk;
@ -12129,7 +12166,7 @@ void autoskill(lifeform_t *lf) {
for (o = lf->pack->first ; o ; o = o->next) {
//if (isweapon(o) && canweild(lf, o)) {
if (isweapon(o)) {
sk = getobskill(o);
sk = getobskill(o->flags);
if (sk && !getskill(lf, sk->id)) {
giveskilllev(lf, sk->id, slev);
}
@ -13964,6 +14001,25 @@ int pickup(lifeform_t *lf, object_t *what, int howmany, int fromground, int want
return B_TRUE;
}
// picked up something our god doesn't like?
if (isplayer(lf)) {
if ( hasflagknown(o->flags, F_POISONED) ||
hasflagvalknown(o->flags, F_HITCONFER, F_POISONED, NA, NA, NULL)) {
int i,nretgods;
lifeform_t *retgod[MAXGODS];
getprayedgods(retgod, &nretgods);
for (i = 0 ; i < nretgods; i++) {
if (lfhasflagval(retgod[i], F_GODPOISON, B_FALSE, NA, NA, NULL)) {
// warn...
godsay(retgod[i]->race->id, B_TRUE, "I hope you're not planning on using that...");
break;
}
}
}
}
return B_FALSE;
}
@ -16318,6 +16374,7 @@ void startlfturn(lifeform_t *lf) {
int donefeetwet = B_FALSE;
flag_t *retflag[MAXCANDIDATES];
int nretflags;
int movedlastturn = B_FALSE;
map = lf->cell->map;
@ -16372,8 +16429,9 @@ void startlfturn(lifeform_t *lf) {
// clear one-turn-only flags
killflagsofid(lf->flags, F_DONELISTEN);
killflagsofid(lf->flags, F_NOSWAP);
killflagsofid(lf->flags, F_HASBEENMOVED);
killflagsofid(lf->flags, F_MOVED);
movedlastturn = 0;
movedlastturn += killflagsofid(lf->flags, F_HASBEENMOVED);
movedlastturn += killflagsofid(lf->flags, F_MOVED);
// if we didn't turn lsat move, kill our turncounter
if (!killflagsofid(lf->flags, F_TURNED)) {
@ -16677,6 +16735,8 @@ void startlfturn(lifeform_t *lf) {
getlfname(lf, lfname);
msg("%s is repelled away from %s!",buf, lfname);
}
} else if (o->material->id == MT_WATER) {
killtransitoryflags(lf->flags, F_HOTFEET);
}
}
}
@ -17015,6 +17075,34 @@ void startlfturn(lifeform_t *lf) {
}
if (isdead(lf)) return;
if (!movedlastturn) {
getflags(lf->flags, retflag, &nretflags, F_HOTFEET, F_NONE);
if (nretflags && !hasobofmaterial(lf->cell->obpile, MT_WATER)) {
for (i = 0; i < nretflags; i++) {
int dam;
enum DAMTYPE dt;
f = retflag[i];
dam = f->val[0];
dt = f->val[1];
o = getarmour(lf, BP_FEET);
if (o && ismetal(o->material->id)) {
dam *= 2;
}
if (losehp(lf, dam, dt, NULL, f->text)) {
if (isplayer(lf)) {
msg("^bYour %s burn!^n", getbodypartname(lf, BP_FEET));
} else if (cansee(player, lf)) {
char lfname[BUFLEN];
getlfname(lf, lfname);
msg("^b%s%s %s burn!^n", lfname, getpossessive(lfname), getbodypartname(lf, BP_FEET));
}
}
}
}
}
if (isdead(lf)) return;
// effects from cell objects?
for (o = lf->cell->obpile->first ; o ; o = o->next) {
f = hasflag(o->flags, F_WALKDAM);
@ -17206,13 +17294,17 @@ void startlfturn(lifeform_t *lf) {
}
if (f->id == F_STRIKETOKO) {
object_t *weapon;
weapon = getweapon(lf);
if (weapon) { // (unarmed is ok)
skill_t *sk;
sk = getobskill(getweapon(lf));
sk = getobskill(weapon->flags);
if (!sk || (sk->id != SK_CLUBS)) {
killflag(f);
continue;
}
}
}
// recharge abilities
if (f->id == F_CANWILL) {
@ -17252,7 +17344,7 @@ void startlfturn(lifeform_t *lf) {
// hp drain
if (f->id == F_HPDRAIN) {
losehp(lf, f->val[0], DT_DIRECT, NULL, f->text);
losehp(lf, f->val[0], f->val[1], NULL, f->text);
if (isdead(lf)) {
break;
}
@ -19672,7 +19764,7 @@ int weild(lifeform_t *lf, object_t *o) {
} else {
// warn if unskilled in this weapon
skill_t *sk;
sk = getobskill(o);
sk = getobskill(o->flags);
if (sk && !getskill(lf, sk->id)) {
msg("^wYou feel rather inept with this weapon.");
} else {

1
lf.h
View File

@ -21,6 +21,7 @@ int armourfits(lifeform_t *lf, object_t *o, enum ERROR *reason);
int askforinfo(lifeform_t *lf, int diffmod);
int askforpayment(lifeform_t *shk, lifeform_t *lf);
char *assignnpcname(lifeform_t *lf);
void autoshortcut(lifeform_t *lf, enum OBTYPE spellid);
void autoskill(lifeform_t *lf);
void autotarget(lifeform_t *lf);
void autoweild(lifeform_t *lf);

44
map.c
View File

@ -4785,6 +4785,8 @@ void explodecells(cell_t *c, int dam, int killwalls, object_t *o, int range, int
void expand_cave(map_t *map, int numpasses) {
int n,x,y,dir;
cell_t *c;
int chancetoclear;
chancetoclear = rnd(15,25);
for (n = 0; n < numpasses; n++) {
// for each dug map cell, 25% chance of clearing each adjacent cell
for (y = 0; y < map->h; y++) {
@ -4795,7 +4797,7 @@ void expand_cave(map_t *map, int numpasses) {
// check for surrounding solid cells
for (dir = DC_N; dir <= DC_NW; dir++) {
c2 = getcellindir(c, dir);
if (c2 && c2->type->solid && pctchance(25)) {
if (c2 && c2->type->solid && pctchance(chancetoclear)) {
setcelltype(c2, map->habitat->emptycelltype);
}
}
@ -7046,9 +7048,8 @@ void setcelltype(cell_t *cell, enum CELLTYPE id) {
// returns true if something happened
int shattercell(cell_t *c, lifeform_t *fromlf, char *damstring) {
lifeform_t *target;
char targetname[BUFLEN], buf[BUFLEN];
char targetname[BUFLEN];
object_t *o, *nexto;
int seen = B_FALSE;
int rv = B_FALSE;
target = c->lf;
@ -7057,42 +7058,7 @@ int shattercell(cell_t *c, lifeform_t *fromlf, char *damstring) {
}
// shatter solid glass cells
if (c->type->solid && willshatter(c->type->material->id)) {
enum MATERIAL origmat;
rv = B_TRUE;
// announce
if (haslos(player, c)) {
msg("%s %s shatters!",needan(c->type->name) ? "An" : "A", c->type->name);
seen = B_TRUE;
} else {
// very loud
noise(c, NULL, NC_OTHER, SV_CAR, "shattering glass.", NULL);
}
if (target) {
if (seen) {
msg("%s %s showered in %s shards!", targetname, is(target), c->type->material->name);
}
losehp(target, rnd(1,100), DT_SLASH, fromlf, damstring); // BIG damage
}
// remember original material
origmat = c->type->material->id;
// change cell type
setcelltype(c, c->habitat->emptycelltype);
// place shards
if (origmat == MT_GLASS) {
int numshards;
numshards = rnd(50,100);
snprintf(buf, BUFLEN, "%d pieces of broken glass",numshards);
addob(c->obpile, buf);
} else if (origmat == MT_ICE) {
int numshards;
numshards = rnd(50,100);
snprintf(buf, BUFLEN, "%d chunks of ice",numshards);
addob(c->obpile, buf);
}
damagecell(c, 9999, DT_DIRECT);
}
// shatter lifeform-owned objects

8
move.c
View File

@ -513,7 +513,7 @@ int diropposite(int dir) {
// restonfail means "if we can't find any valid moves, just rest"
// returns true on error
int dorandommove(lifeform_t *lf, int badmovesok, int restonfail) {
int dorandommove(lifeform_t *lf, int badmovesok, int restonfail, int strafe) {
int origtimespent;
int dir;
int tries = 0;
@ -561,7 +561,7 @@ int dorandommove(lifeform_t *lf, int badmovesok, int restonfail) {
}
origtimespent = lf->timespent;
rv = trymove(lf, dir, B_TRUE, B_FALSE);
rv = trymove(lf, dir, B_TRUE, strafe);
if (restonfail && (rv || (lf->timespent == origtimespent))) {
// ie move failed
rest(lf, B_TRUE);
@ -942,7 +942,7 @@ int moveawayfrom(lifeform_t *lf, cell_t *dst, int dirtype, int keepinlof, int st
int rv = B_TRUE;
if (isblind(lf)) {
dorandommove(lf, B_TRUE, B_TRUE);
dorandommove(lf, B_TRUE, B_TRUE, B_FALSE);
return B_FALSE;
}
@ -1701,7 +1701,7 @@ int movetowards(lifeform_t *lf, cell_t *dst, int dirtype, int strafe) {
if (isblind(lf)) {
if (db) dblog(".oO { i am blind - movetorwards calling dorandommove. }");
dorandommove(lf, B_TRUE, B_TRUE);
dorandommove(lf, B_TRUE, B_TRUE, B_FALSE);
return B_FALSE;
}

2
move.h
View File

@ -8,7 +8,7 @@ int closedoorat(lifeform_t *lf, cell_t *c);
int closedoor(lifeform_t *lf, object_t *o);
enum RELATIVEDIR getrelativedir(lifeform_t *lf, int dir);
int diropposite(int dir);
int dorandommove(lifeform_t *lf, int badmovesok, int restonfail);
int dorandommove(lifeform_t *lf, int badmovesok, int restonfail, int strafe);
int getdiraway(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, int dirtype, int keepinlof);
int getdirtowards(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, int dirtype);
int getwalkoffdir(lifeform_t *lf, int dir);

13
nexus.c
View File

@ -297,7 +297,6 @@ int main(int argc, char **argv) {
/*o = hasob(where->obpile, OT_PLAYERSTART);
killob(o);*/
// place the portal to realm of gods
c = getrandomcell(surfmap);
while (!cellwalkable(NULL, c, NULL)) {
@ -375,6 +374,7 @@ int main(int argc, char **argv) {
}
if (sb1) {
addflag(player->flags, F_CANCAST, sb1->contents->first->type->id, NA, NA, NULL);
addflag(player->flags, F_SHORTCUT, 1, NA, NA, sb1->contents->first->type->name);
addflag(sb1->flags, F_NOPOINTS, B_TRUE, NA, NA, NULL);
}
@ -409,6 +409,7 @@ int main(int argc, char **argv) {
}
if (sb2) {
addflag(player->flags, F_CANCAST, sb2->contents->first->type->id, NA, NA, NULL);
addflag(player->flags, F_SHORTCUT, 2, NA, NA, sb2->contents->first->type->name);
addflag(sb2->flags, F_NOPOINTS, B_TRUE, NA, NA, NULL);
}
identify(sb1);
@ -455,6 +456,10 @@ int main(int argc, char **argv) {
petify(pet, player);
}
// more automated shortcuts
autoshortcut(player, OT_A_COOK);
getplayernamefull(pname);
snprintf(welcomemsg, BUFLEN, "Greetings %s, welcome to nexus!", pname);
// 00:00 - 23:59
@ -612,7 +617,7 @@ celltype_t *addcelltype(int id, char *name, int glyph, int colour, int solid, in
return a;
}
warning_t *addwarning(char *text) {
warning_t *addwarning(char *text, int lifetime) {
warning_t *a;
// add to the end of the list
@ -632,7 +637,7 @@ warning_t *addwarning(char *text) {
// set props
a->text = strdup(text);
a->lifetime = DEF_WARNINGTIME;
a->lifetime = lifetime;
return a;
}
@ -1798,9 +1803,11 @@ void timeeffectsworld(map_t *map, int updategametime) {
// time out warnings
for (w = firstwarning ;w ; w = nextw) {
nextw = w->next;
if (w->lifetime > 0) {
w->lifetime--;
if (w->lifetime <= 0) killwarning(w);
}
}
//dblog("AFTER SORT AND ADJUST.....");
//dumplf();

View File

@ -1,7 +1,7 @@
#include "defs.h"
celltype_t *addcelltype(int id, char *name, int glyph, int colour, int solid, int transparent, enum MATERIAL mat, int floorheight, int hp);
warning_t *addwarning(char *text);
warning_t *addwarning(char *text, int lifetime);
void checkdeath(void);
void checkendgame(void);
void cleanup(void);

View File

@ -462,6 +462,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
int nom = 0;
int n;
int bookcontents = -1;// a skill for manuals, or a spellschool id for spellbooks
lifeform_t *matchlfskills = NULL;
int wantblessknown = B_FALSE;
enum DEPTH wantdepth = DP_MAX;
int wantlit = B_FALSE;
@ -708,6 +709,15 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
wantrarity = RR_VERYRARE;
p += strlen("very rare ");
donesomething = B_TRUE;
// force weapon/armour to be ones the holder is skilled in?
} else if (strstarts(p, "appropriate ")) {
if (where->owner) {
matchlfskills = where->owner;
} else {
matchlfskills = player;
}
p += strlen("appropriate ");
donesomething = B_TRUE;
// weapon "goodness"
} else if (strstarts(p, "average ")) {
wantgoodness = G_AVERAGE;
@ -891,6 +901,9 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
int found = B_FALSE;
// check for things like "weapon" or "random ring"
// for weapons and armour, "matchlfskills" being set
// means that we should only select weapons/armour which
// matchlfskills is skilled in.
for (oc = objectclass; oc ; oc = oc->next) {
int i;
int matched = B_FALSE;
@ -905,7 +918,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
// want a specific rarity?
rrtorarity(wantrarity, &minrarity, &maxrarity);
ot = getrandomobofclass(oc->id, minrarity, maxrarity);
ot = getrandomobofclass(oc->id, minrarity, maxrarity, matchlfskills);
if (ot) {
found = B_TRUE;
break;
@ -1291,7 +1304,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
getrarityrange(where->where->map->depth, &min, &max, RARITYVARIANCEOB, B_FALSE);
// random potion type
ot = getrandomobofclass(OC_POTION, min, max);
ot = getrandomobofclass(OC_POTION, min, max, NULL);
if (ot) {
f->val[0] = ot->id;
}
@ -2227,6 +2240,17 @@ void adjustdamob(object_t *o, int *dam, enum DAMTYPE damtype) {
}
}
// cooked food won't decay to nothing
if ((damtype == DT_DECAY) && hasflag(o->flags, F_PREPARED)) {
int hpcur;
hpcur = getobhp(o, NULL);
if (hpcur <= *dam) {
// go to 1 hp
*dam = hpcur - 1;
return;
}
}
// adjust damage
if (o->blessed == B_BLESSED) {
// high chance of no hp loss
@ -3665,9 +3689,10 @@ int getobpoints(object_t *o) {
}
// returns the skill associated with this object
skill_t *getobskill(object_t *o) {
// (via its flagpile)
skill_t *getobskill(flagpile_t *fp) {
flag_t *f;
f = hasflag(o->flags, F_USESSKILL);
f = hasflag(fp, F_USESSKILL);
if (f) {
return findskill(f->val[0]);
}
@ -3974,29 +3999,39 @@ brand_t *getrandombrandfor(objecttype_t *ot) {
return result;
}
objecttype_t *getrandomobofclass(enum OBCLASS ocid, int minrarity, int maxrarity) {
objecttype_t *getrandomobofclass(enum OBCLASS ocid, int minrarity, int maxrarity, lifeform_t *forlf) {
objecttype_t *ot;
int count = 0,sel,n;
flag_t *f;
for (ot = objecttype ; ot ; ot = ot->next) {
if ((ot->obclass->id == ocid) && !hasflag(ot->flags, F_UNIQUE)) {
int rarityok = B_FALSE;
int skillok = B_FALSE;
// does rarity match?
f = hasflag(ot->flags, F_RARITY);
if (f) {
int ok = B_FALSE;
if (f->val[1] == NA) {
ok = B_TRUE;
rarityok = B_TRUE;
} else if ( ((minrarity == NA) || (f->val[1] >= minrarity)) &&
((maxrarity == NA) || (f->val[1] <= maxrarity)) ) {
ok = B_TRUE;
rarityok = B_TRUE;
}
if (ok) {
}
// if we're randomly selecting an objcet for a lf, make sure it matches their
// skillset
if (forlf) {
skill_t *sk;
sk = getobskill(ot->flags);
if (!sk || getskill(forlf, sk->id)) {
skillok = B_TRUE;
}
} else skillok = B_TRUE;
if (skillok && rarityok) {
count++;
}
}
}
}
if (count <= 0) {
return NULL;
}
@ -4006,15 +4041,28 @@ objecttype_t *getrandomobofclass(enum OBCLASS ocid, int minrarity, int maxrarity
if ((ot->obclass->id == ocid) && !hasflag(ot->flags, F_UNIQUE)) {
f = hasflag(ot->flags, F_RARITY);
if (f) {
int ok = B_FALSE;
int rarityok = B_FALSE;
int skillok = B_FALSE;
// does rarity match?
f = hasflag(ot->flags, F_RARITY);
if (f) {
if (f->val[1] == NA) {
ok = B_TRUE;
rarityok = B_TRUE;
} else if ( ((minrarity == NA) || (f->val[1] >= minrarity)) &&
((maxrarity == NA) || (f->val[1] <= maxrarity)) ) {
ok = B_TRUE;
rarityok = B_TRUE;
}
if (ok) {
}
// if we're randomly selecting an objcet for a lf, make sure it matches their
// skillset
if (forlf) {
skill_t *sk;
sk = getobskill(ot->flags);
if (!sk || getskill(forlf, sk->id)) {
skillok = B_TRUE;
}
} else skillok = B_TRUE;
if (skillok && rarityok) {
n++;
if (n == sel) {
return ot;
@ -4187,6 +4235,17 @@ int getobattackdelay(object_t *o) {
return delay;
}
int getobhp(object_t *o, int *max) {
flag_t *f;
f = hasflag(o->flags, F_OBHP);
if (f) {
if (max) *max = f->val[1];
return f->val[0];
}
// default
if (max) *max = 1;
return 1;
}
float getobhppct(object_t *o) {
float pct;
@ -9960,7 +10019,7 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, object_t *o, enum BLESSTYPE
if (getmaxmp(lf) > 0) {
msg("Your magical energy is restored.");
lf->mp = getmaxmp(lf);
gainmp(lf, getmaxmp(lf));
} else {
nothinghappens();
if (seen) *seen = B_FALSE;
@ -11357,7 +11416,7 @@ int real_takedamage(object_t *o, int howmuch, int damtype, int wantannounce) {
makewet(o, howmuch);
}
// catches on fire?
// initial effects based on damage type
if (damtype == DT_FIRE) {
if ( ((o->type->id == OT_CANDLE) || (o->type->id == OT_TORCH) || (o->type->id == OT_CANDELABRUM)) &&
!isactivated(o)) {

View File

@ -83,7 +83,7 @@ int getmissileaccuracy(lifeform_t *thrower, cell_t *where, object_t *missile, ob
int getobaccuracy(object_t *wep, lifeform_t *weilder);
int getobbonus(object_t *o, int onlyknown);
int getobpoints(object_t *o);
skill_t *getobskill(object_t *o);
skill_t *getobskill(flagpile_t *fp);
enum LFSIZE getobsize(object_t *o);
int getobspellpower(object_t *o, lifeform_t *lf);
int getobvalue(object_t *o);
@ -96,7 +96,7 @@ objecttype_t *getbasicweaponforskill(enum SKILL skid);
object_t *getrandomammo(lifeform_t *lf);
objecttype_t *getrandomammofor(object_t *o);
brand_t *getrandombrandfor(objecttype_t *ot);
objecttype_t *getrandomobofclass(enum OBCLASS ocid, int minrarity, int maxrarity);
objecttype_t *getrandomobofclass(enum OBCLASS ocid, int minrarity, int maxrarity, lifeform_t *forlf);
enum OBTYPE getrandomtrapforob(void);
char *getdamname(enum DAMTYPE damtype);
char *getdamnamenoun(enum DAMTYPE damtype);
@ -108,6 +108,7 @@ int gethardness(enum MATERIAL matid);
char *genhiddenname(enum OBCLASS id);
char *gethiddenname(object_t *o);
int getobattackdelay(object_t *o);
int getobhp(object_t *o, int *max);
float getobhppct(object_t *o);
int getobmaxhp(object_t *o);
int getletindex(char let);

293
spell.c
View File

@ -1882,12 +1882,16 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
msg("The scroll crumbles to dust.");
removeob(o, 1);
} else if (abilid == OT_A_STRIKETOKO) {
object_t *wep;
wep = getweapon(user);
if (wep) {
skill_t *sk;
sk = getobskill(getweapon(user));
sk = getobskill(wep->flags);
if (!sk || (sk->id != SK_CLUBS)) {
if (isplayer(user)) msg("You can only use bashing weapons to fight mercifully.");
return B_TRUE;
}
}
if (lfhasflag(user, F_STRIKETOKO)) {
killflagsofid(user->flags, F_STRIKETOKO);
@ -2709,7 +2713,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
wep = getweapon(user);
if (wep) {
wepsk = getobskill(wep);
wepsk = getobskill(wep->flags);
} else {
wepsk = findskill(SK_UNARMED);
}
@ -4006,6 +4010,25 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
f = addtempflag(caster->flags, F_SLOWMOVE, 5, NA, NA, NULL, FROMSPELL);
f->obfrom = spellid;
}
} else if (spellid == OT_S_BURNINGFEET) {
char killertext[BUFLEN];
if (!target) {
target = targcell->lf;
}
if (!target) {
fizzle(caster);
return B_TRUE;
}
if (!hasbp(target, BP_FEET)) {
fizzle(caster);
return B_TRUE;
}
sprintf(killertext, "%s%s hotfoot spell", castername, getpossessive(castername));
addflag(target->flags, F_HOTFEET, 1, DT_FIRE, NA, killertext);
if (isplayer(target) || cansee(player, target)) {
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
} else if (spellid == OT_S_BURNINGWAVE) {
cell_t *retcell[MAXRETCELLS];
int nretcell;
@ -4681,7 +4704,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
return B_TRUE;
}
for (i = 0; i < power; i++) {
ot = getrandomobofclass(OC_FOOD, NA, NA);
ot = getrandomobofclass(OC_FOOD, NA, NA, NULL);
o = addobfast(targcell->obpile, ot->id);
if (i == 0) {
getobname(o, obname, o->amt);
@ -5282,31 +5305,58 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// don't need line of fire!
getradiuscells(targcell, power, DT_ORTH, B_FALSE, LOF_NEED, B_TRUE, cell, &ncells, B_FALSE);
for (i = 0; i < ncells; i++) {
object_t *o,*nexto;
for (o = cell[i]->obpile->first ; o ; o = nexto) {
nexto = o->next;
if (getmaterialstate(o->material->id) == MS_LIQUID) {
int cellseen = B_FALSE;
object_t *o,*nexto;
if (haslos(player, cell[i])) {
cellseen = B_TRUE;
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
for (o = cell[i]->obpile->first ; o ; o = nexto) {
int dosteam = B_FALSE;
nexto = o->next;
if (getmaterialstate(o->material->id) == MS_LIQUID) {
// if 20kilos or more, make steam
if (getobweight(o) >= 25) {
addob(cell[i]->obpile, "cloud of steam");
dosteam = B_TRUE;
if (cellseen) nsteamseen++;
}
nseen++;
removeob(o, ALL);
} else if (o->material->id == MT_ICE) {
takedamage(o, roll("2d6"), DT_FIRE);
} else if ((o->material->id == MT_ICE) || (o->type->obclass->id == OC_POTION)) {
char obname[BUFLEN];
dosteam = B_TRUE;
if (cellseen) nsteamseen++;
nseen++;
getobname(o, obname, o->amt);
msg("%s boil%s and explode%s!", obname, OBS1(o), OBS1(o));
removeob(o, ALL);
}
if (dosteam) {
addob(cell[i]->obpile, "cloud of steam");
}
}
if (cell[i]->lf) {
for (o = cell[i]->lf->pack->first ; o ; o = nexto) {
nexto = o->next;
if ((o->material->id == MT_ICE) || (o->type->obclass->id == OC_POTION)) {
char obname[BUFLEN];
if (cellseen) nsteamseen++;
nseen++;
getobname(o, obname, o->amt);
msg("%s boil%s and explode%s!", obname, OBS1(o), OBS1(o));
removeob(o, ALL);
addob(cell[i]->obpile, "cloud of steam");
}
}
}
}
if (nsteamseen) {
if (seenbyplayer) *seenbyplayer = B_TRUE;
msg("A huge cloud of steam appears!");
} else if (nseen) {
if (seenbyplayer) *seenbyplayer = B_TRUE;
msg("Some nearby liquid evaporates!");
} else {
fizzle(caster);
@ -5713,22 +5763,36 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
losehp(target, rolldie(power,4), DT_MAGIC, caster, "an energy bolt");
}
} else if (spellid == OT_S_FIREBALL) {
} else if ((spellid == OT_S_FIREBALL) || (spellid == OT_S_METEOR)) {
int failed = B_FALSE;
char fbname[BUFLEN];
enum OBTYPE fire1, fire2,fire3;
if (spellid == OT_S_FIREBALL) {
strcpy(fbname, "a huge ball of fire");
fire1 = OT_FIREMED;
fire2 = OT_FIREMED;
fire3 = OT_FIRESMALL;
} else {
strcpy(fbname, "a flaming meteorite");
fire1 = OT_FIRELARGE;
fire2 = OT_FIRELARGE;
fire3 = OT_FIREMED;
}
if (targcell) {
if (!targcell->type->solid || hasflag(targcell->type->material->flags, F_FLAMMABLE)) {
int dir;
cell_t *c;
object_t *o;
// centre fireball here...
if (isplayer(caster)) {
msg("You launch an enormous ball of fire!");
msg("You launch %s!", fbname);
if (seenbyplayer) *seenbyplayer = B_TRUE;
} else if (cansee(player, caster)) {
msg("%s launches an enormous ball of fire!",castername);
msg("%s launches %s!",castername, fbname);
if (seenbyplayer) *seenbyplayer = B_TRUE;
} else if (haslos(player, targcell)) {
msg("An enormous ball of fire explodes!");
msg("%s explodes!", fbname);
}
anim(caster->cell, targcell, '^', C_RED);
@ -5742,16 +5806,20 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// 232
// 1
// add large fires to surrounding cells
addob(targcell->obpile, "medium fire");
addobfast(targcell->obpile, fire1);
for (dir = D_N; dir <= D_W; dir++) {
c = getcellindir(targcell, dir);
if (c && (!c->type->solid || hasflag(c->type->material->flags, F_FLAMMABLE)) ) {
o = addob(c->obpile, "medium fire");
o = addobfast(c->obpile, fire1);
if (o) {
setobcreatedby(o, caster);
}
if (c->lf) {
if (spellid == OT_S_FIREBALL) {
losehp(c->lf, rolldie(power,3), DT_FIRE, caster, "a fireball");
} else {
losehp(c->lf, 30+rolldie(power,6), DT_FIRE, caster, "a meterorite");
}
}
}
}
@ -5759,14 +5827,20 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
cell_t *c;
c = getcellindir(targcell, dir);
if (c && (!c->type->solid || hasflag(c->type->material->flags, F_FLAMMABLE)) ) {
o = addob(c->obpile, "medium fire");
o = addobfast(c->obpile, fire2);
if (o) {
setobcreatedby(o, caster);
}
if (c->lf) {
int ndice;
ndice = power / 2; if (ndice < 1) ndice = 1;
if (spellid == OT_S_FIREBALL) {
losehp(c->lf, rolldie(ndice,3), DT_FIRE, caster, "a fireball");
} else {
losehp(c->lf, 15+rolldie(ndice,5), DT_FIRE, caster, "a meteorite");
}
}
}
}
@ -5776,14 +5850,19 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (c) {
c = getcellindir(c, dir);
if (c && (!c->type->solid || hasflag(c->type->material->flags, F_FLAMMABLE)) ) {
o = addob(c->obpile, "small fire");
o = addobfast(c->obpile, fire3);
if (o) {
setobcreatedby(o, caster);
}
if (c->lf) {
int ndice;
ndice = power / 2; if (ndice < 1) ndice = 1;
if (spellid == OT_S_FIREBALL) {
losehp(c->lf, rolldie(ndice,2), DT_FIRE, caster, "a fireball");
} else {
losehp(c->lf, 7+rolldie(ndice,4), DT_FIRE, caster, "a meteorite");
}
}
}
}
@ -6134,7 +6213,11 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else {
int rv;
getobname(o, buf, o->amt);
if (isimmuneto(o->flags, DT_COLD, B_FALSE)) {
rv = E_NOEFFECT;
} else {
rv = changemat(o, MT_ICE);
}
if (rv) {
if (rv == E_NOEFFECT) {
if (o->pile->owner) {
@ -6453,7 +6536,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (!frompot) {
pleasegodmaybe(R_GODMERCY, 3);
}
angergodmaybe(R_GODDEATH, 20, GA_HERESY);
// god of death REALLY doesn't like healing.
angergodmaybe(R_GODDEATH, 40, GA_HERESY);
}
// hostile monsters might calm down
if (!frompot && donesomething && isplayer(caster) && !isplayer(target) && (getallegiance(target) == AL_HOSTILE)) {
@ -6730,6 +6814,32 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else {
// monsters can't id things!
}
} else if (spellid == OT_S_IMMOLATE) {
char targname[BUFLEN],buf[BUFLEN];
if (!target) {
target = targcell->lf;
}
if (!target) {
fizzle(caster);
return B_TRUE;
}
getlfname(target, targname);
if (rolltohit(caster, target, NULL, NULL)) {
if (isplayer(caster) || cansee(player, caster)) {
construct_hit_string(caster, target, castername, targname, targname, NULL, DT_TOUCH, 0, target->maxhp,
0, B_FALSE, B_FALSE, B_FALSE, B_TRUE, buf);
msg("%s", buf);
if (seenbyplayer) *seenbyplayer = B_TRUE;
msg("%s is engulfed in roaring flames!", targname);
addobfast(target->cell->obpile, OT_FIRESMALL);
}
} else {
if (isplayer(caster)) {
msg("You try to touch %s, but fail.", targname);
} else if (cansee(player, caster)) {
msg("%s tries to touch %s, but fails.", castername, targname);
}
}
} else if (spellid == OT_S_INFINITEDEATH) {
lifeform_t *l;
if (isplayer(caster)) {
@ -7045,12 +7155,98 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
msg("%s is unaffected.", lfname);
}
}
} else if (spellid == OT_S_OBJECTGROWTH) {
enum OBTYPE newoid = OT_NONE;
enum LFSIZE newsize = SZ_ANY;
skill_t *obsk = SK_NONE;
char obname[BUFLEN],newobname[BUFLEN];
int seen;
if (targcell->obpile->first) {
targob = doaskobject(targcell->obpile, "Target which object", NULL, B_TRUE, B_FALSE, B_FALSE, '\0', AO_NONE, F_NONE);
}
if (!targob) {
fizzle(caster);
return B_TRUE;
}
targcell = getoblocation(targob);
if (haslos(player, targcell)) {
seen = B_TRUE;
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
getobname(targob, obname, 1);
obsk = getobskill(targob->flags);
if (isweapon(targob) && (obsk->id == SK_LONGBLADES)) {
newoid = OT_GREATSWORD;
} else if (isweapon(targob) && (obsk->id == SK_SHORTBLADES)) {
newoid = OT_GREATSWORD;
} else if (isweapon(targob) && (obsk->id == SK_CLUBS)) {
newoid = OT_GREATCLUB;
} else if (isweapon(targob) && (obsk->id == SK_AXES)) {
newoid = OT_GREATAXE;
} else if (targob->type->obclass->id == OC_ROCK) {
newoid = OT_BOULDER;
} else if ((targob->type->obclass->id == OC_ARMOUR) &&
hasflag(targob->flags, F_MULTISIZE) &&
(getarmoursize(targob) < SZ_LARGE)) {
newsize = getarmoursize(targob) + 1;
} else {
switch (targob->type->id) {
case OT_ASH: newoid = OT_STONE; break;
case OT_ASHCONCEAL: newoid = OT_STONE; break;
case OT_ASHEXPLODE: newoid = OT_STONE; break;
case OT_ASHSLEEP: newoid = OT_STONE; break;
case OT_BAGOFHOLDING: newoid = OT_BAGOFHOLDINGLARGE; break;
case OT_BAGOFHOLDINGLARGE: newoid = OT_BAGOFHOLDINGHUGE; break;
case OT_BUCKLER: newoid = OT_SHIELD; break;
case OT_DOORWOOD: newoid = OT_DOORIRON; break;
case OT_FIRESMALL: newoid = OT_FIREMED; break;
case OT_FIREMED: newoid = OT_FIRELARGE; break;
case OT_FLOWER: newoid = OT_SHRUB; break;
case OT_FOUNTAIN: newoid = OT_WATERDEEP; break;
case OT_WOODENSTOOL: newoid = OT_WOODENTABLE; break;
case OT_ICESHEET: newoid = OT_ICICLE; break;
case OT_LEAF: newoid = OT_SHRUB; break;
case OT_MISTLETOE: newoid = OT_SHRUB; break;
case OT_SACK: newoid = OT_SACKLARGE; break;
case OT_SACKLARGE: newoid = OT_SACKHUGE; break;
case OT_SHIELDHIDE: newoid = OT_SHIELD; break;
case OT_SHIELD: newoid = OT_SHIELDLARGE; break;
case OT_SHIELDLARGE: newoid = OT_SHIELDTOWER; break;
case OT_SHRUB: newoid = OT_TREE; break;
case OT_STUMP: newoid = OT_TREE; break;
default: break;
}
}
if (newsize != SZ_ANY) {
resizeobject(targob, newsize);
getobname(targob, obname, 1);
if (seen) msg("%s grows into %s!", obname, newobname);
} else if (newoid == targob->id) {
if (seen) msg("%s shudders for a moment.", obname);
} else if (newoid != OT_NONE) {
obpile_t *op;
op = targob->pile;
killob(targob);
targob = addobfast(op, newoid);
if (targob) {
getobname(targob, newobname, 1);
if (seen) msg("%s grows into %s!", obname, newobname);
} else {
if (seen) msg("%s shudders then explodes!", obname);
}
} else {
if (seen) msg("%s shudders for a moment.", obname);
}
} else if (spellid == OT_S_ACCELMETAL) {
char oidbuf[BUFLEN];
flag_t *f;
if (!targob) {
// ask for an object
targob = askobject(caster->pack, "Fire which object", NULL, 't', AO_NONE);
targob = askobject(caster->pack, "Accelerate which object", NULL, 't', AO_NONE);
}
if (!targob || !ismetal(targob->material->id) ) {
fizzle(caster);
@ -9405,6 +9601,51 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else {
fizzle(caster);
}
} else if (spellid == OT_S_SUPERHEAT) {
char obname[BUFLEN];
// needs:
// object = which potion to throw
// cell = where to throw the potion
if (!targob && isplayer(caster)) {
targob = askobjectwithflag(caster->pack, "Superheat which potion", NULL, 'q', AO_NONE, F_DRINKABLE);
}
if (!targob) {
fizzle(caster);
return B_TRUE;
}
targob = splitob(targob);
if (!targob) {
if (isplayer(caster)) {
msg("Your pack is too full for this spell to work!");
}
fizzle(caster);
return B_TRUE;
}
getobname(targob, obname, 1);
if (isplayer(caster)) {
msg("Your %s begins to bubble violently!", noprefix(obname)); more();
} else if (cansee(player, caster)) {
msg("%s%s %s begins to bubble violently!", castername, getpossessive(castername), noprefix(obname));
}
// potion will explode next turn if you don't throw it.
addflag(targob->flags, F_EXPLODEONDEATH, NA, 1, NA, "6d2"); //ie . 6-12 damage
addflag(targob->flags, F_EXPLODEONDAM, NA, 1, NA, "6d2"); //ie . 6-12 damage
addflag(targob->flags, F_OBHPDRAIN, 1, NA, NA, NULL);
if (isplayer(caster) && !targcell) {
char buf[BUFLEN],buf2[BUFLEN];
sprintf(buf, "Throw %s where?", obname);
sprintf(buf2, "Superheat->%s->", obname);
targcell = askcoords(buf, buf2,TT_MONSTER, caster, getmaxthrowrange(caster, targob), LOF_NEED, B_TRUE);
}
if (!targcell) {
fizzle(caster);
return B_TRUE;
}
fireat(caster, targob, 1, targcell, getthrowspeed(caster), NULL);
} else if (spellid == OT_S_TAILWIND) {
if (!target) target = caster;
if (isplayer(target)) {
@ -9742,9 +9983,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
fizzle(caster);
return B_FALSE;
}
f = addtempflag(caster->flags, F_TRUESTRIKE, power, NA, NA, NULL, FROMSPELL);
f = addtempflag(target->flags, F_TRUESTRIKE, power, NA, NA, NULL, FROMSPELL);
f->obfrom = spellid;
f = addtempflag(caster->flags, F_NOSTRDAMMOD, B_TRUE, NA, NA, NULL, FROMSPELL);
f = addtempflag(target->flags, F_NOSTRDAMMOD, B_TRUE, NA, NA, NULL, FROMSPELL);
f->obfrom = spellid;
} else if (spellid == OT_S_TURNUNDEAD) {
int i;
@ -10582,7 +10823,8 @@ enum OBTYPE getfirstwizspell(enum SPELLSCHOOL school) {
case SS_DEATH: firstspell = OT_S_STENCH; break;
case SS_DIVINATION: firstspell = OT_S_SIXTHSENSE; break;
case SS_GRAVITY: firstspell = OT_S_TRUESTRIKE; break;
case SS_MODIFICATION: firstspell = OT_S_HOLDPORTAL; break;
//case SS_MODIFICATION: firstspell = OT_S_HOLDPORTAL; break;
case SS_MODIFICATION: firstspell = OT_S_OBJECTGROWTH; break;
case SS_TRANSLOCATION: firstspell = OT_S_APPORTATION; break;
case SS_SUMMONING: firstspell = OT_S_GLYPHWARDING; break;
default:
@ -11177,6 +11419,9 @@ int getspellrange(lifeform_t *lf, enum OBTYPE spellid, int power) {
case OT_S_DIG:
range = power;
break;
case OT_S_FLAMEPILLAR:
range = power;
break;
case OT_S_LIGHTNINGBOLT:
range = (power*3);
break;

8
text.c
View File

@ -95,7 +95,11 @@ char *construct_hit_string(lifeform_t *lf, lifeform_t *victim, char *attackernam
// default
strcpy(retbuf, "");
if (wep) {
getobname(wep, wepname, 1);
} else {
strcpy(wepname, "?noweapon?"); // should never be displayed
}
// modify victimname if required
//if (helpless && !isbehind(lf, victim)) {
@ -139,7 +143,7 @@ char *construct_hit_string(lifeform_t *lf, lifeform_t *victim, char *attackernam
}
strcpy(extradambuf, "");
if (dam == 0) {
if ((dam == 0) && (damtype != DT_TOUCH)) {
if (!victim || getlorelevel(lf, victim->race->raceclass->id)) {
//strcpy(extradambuf, " but do no damage");
strcpy(extradambuf, " ineffectually");
@ -986,7 +990,7 @@ char *getobmodprefix(object_t *o, obmod_t *om) {
} else if (isweapon(o)) {
flag_t *f = NULL;
skill_t *sk;
sk = getobskill(o);
sk = getobskill(o->flags);
if (sk) {
if (om->id == OM_MASTERWORK) {
switch (sk->id) {

View File

@ -9,7 +9,11 @@
#:cell:rock wall
+:ob:wooden door
+:exit
o:ob:1-5 random tools
o:ob:random tool
o:ob:random tool:50
o:ob:random tool:50
o:ob:random tool:50
o:ob:random tool:50
@end
@flags

View File

@ -9,7 +9,11 @@
#:cell:rock wall
+:ob:wooden door
+:exit
o:ob:1-5 random technology
o:ob:random technology
o:ob:random technology:50
o:ob:random technology:50
o:ob:random technology:50
o:ob:random technology:50
@end
@flags