- [+] djin and efreeti should hate each other

- [+] 'G' isn't remembering direction anymore
- [+] beginner athletics:  give skill where misisng in a melee attack
      doesn't cost stamina
- [+] klikirak shoudl like ALL obejct desctruction, but PREFER via fire.
- [+] insects shoudl ahve infinite stamina
- [+] replace DIECONVERT planks of wood type code
    - [+] instead, materials have dieconvert values based on damage.
        - [+] getsmallbreakob(material,damtype)
        - [+] getlargebreakob(material, damtype)
    - [+] when an object dies, lookup its material  and obejct size
        - [+] ie. large wooden objects turn into "x planks of wood"
        - [+] small ones turn into "x shards of wood"
        - [+] then remove TODO: code from changemat() in objects.c
    - [+] allow for hardcoded getsmallbrekaob, getbigbreakob
        - [+] F_BREAKOB, v0=damtype, v1=howmany, text = what
    - [+] remove specific code, like fire damage = pile of ash.
          ice+bash = shards, etc.
- [+] can use shards/planks of wood as (poor) weapons.
- [+] jackhammer shoudl be tech, not tool./
- [+] digging tools should make noise
- [+] remove freezing touch spell/scroll
- [+] better listen check when asleep - slithering should very rarely
      wake you up
    - [+] use adjusted volume value based on sleeping etc.
- [+] breaking locks by bashing should now work.
- [+] I'm often getting "The hollow tree seems to be blocked." when
      going to the sylvan woods.
    - [+] there is a tree in the way!
    - [+] fixed.
- [+] bug: evil players not getting xp for killing helpless. fixed.
- [+] bug: pullobto() not doing correct impassable check.
- [+] another bug: insylvan woods, stairs were on top of water!!!
- [+] ERROR - couldnt find pos for down stairs while making habitat
      forest.--More--
- [+] repairing should make noise too
    - [+] new flag - USENOISE
- [+] EATCONFER on clove of garlic isn't working
    - [+] it's because i'm only checking this if we have MUTABLE.
    - [+] use EATMUTATE instead for mutations.  then eatconfer works
          with everything.
- [+] more crush bugs
    - [+] You crush some pieces of broken glass underfoot.
          You see 28 pieces of broken glass here.
    - [+] You crush some pieces of broken glass underfoot.
          You see 28 pieces of broken glass here.
- [+] anything with natural flight sohuld still make noise when flying.
       otherwise it's too powerful.
    - [+] "wing flapping" . NV FLY
    - [+] NOISETEXT NV_FLY
    - [+] magical flight can still be silent.
- [+] make how high you can fly depend on the "Flight" or "Natural
      Flight" skill.
    - [+] F_FLYING v0 = height.
    - [+] without this skill, flight is dependant on spell power. 
    - [+] assign sk_flying to races.
    - [+] remove F_FLIGHTEVASION from races. skill now does this
          instead.
    - [+] validaterace:
        - [+] canwill ot_a_flight = need flight skill
    - [+] each rank = +1 size level of height.
    - [+] if you get the skill while already flying, adjust the flag
    - [+] fall from flying if burduned.
    - [+] skill also affacts how much your evasion while flying is
          boosted.
        - [+] this extra EV bonus from flight sohuld only work against
              NON flying creatures!
        - [+] 5 EV per rank
    - [+] have a differnet fly ability
        - [+] ability = flight or fly (use flying skill for height)
            - [+] implement
            - [+] replace monster flight with ability.
        - [+] spell = enchanted flight (use spell power for ehgiht)
        - [+] check all occurences of FROMSPELL, cope with FROMABIL too.
- [+] don't regenerate stamina when doing natural flight.
- [+] ai: if flying and no stamina left, stop flying.
- [+] ai: only start flying if we have >= 80% stamina.
- [+] how did a nutter miss a mammoan from point blank range?
    - [+] the nutter is throwing a peanut - acc = 64, speed = 2
    - [+] maybe fixed now.
- [+] felix should like using poison.
- [+] when asking whether you accept a god's offer, give a '?' option,
      to give help on that god.
    - [+] also have F_GODDECLINE text.
- [+] pipes of peace - calms everyone around you.  charges.
This commit is contained in:
Rob Pearce 2012-11-22 03:13:27 +00:00
parent 2867b4488f
commit e30d5f334f
16 changed files with 1017 additions and 578 deletions

22
ai.c
View File

@ -1452,9 +1452,11 @@ int ai_handle_emergencies(lifeform_t *lf, enum ATTRBRACKET iqb) {
// flying monsters not flying? // flying monsters not flying?
if (!isprone(lf)) { if (!isprone(lf)) {
if (hasflag(lf->race->flags, F_NATURALFLIGHT) && !lfhasflag(lf, F_FLYING)) { if (hasflag(lf->race->flags, F_NATURALFLIGHT) && !lfhasflag(lf, F_FLYING)) {
if (cancast(lf, OT_S_FLIGHT, NULL)) { if (cancast(lf, OT_A_FLY, NULL) && !isburdened(lf)) {
if (!castspell(lf, OT_S_FLIGHT, lf, NULL, lf->cell, NULL, NULL)) { if (getstaminapct(lf) >= 80) {
return B_TRUE; if (!useability(lf, OT_A_FLY, lf, lf->cell)) {
return B_TRUE;
}
} }
} }
} }
@ -1464,6 +1466,14 @@ int ai_handle_emergencies(lifeform_t *lf, enum ATTRBRACKET iqb) {
return B_TRUE; return B_TRUE;
} }
} }
// flying and out of stamina?
if (isflyingwithwings(lf) && isexhausted(lf)) {
// stop flying.
if (!useability(lf, OT_A_FLY, lf, lf->cell)) {
return B_TRUE;
}
}
return B_FALSE; return B_FALSE;
} }
@ -3099,7 +3109,7 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
if (lfhasflag(lf, F_SPRINTING) || !getstamina(lf) || (getstamina(lf) <= (getmaxstamina(lf)/2))) { if (lfhasflag(lf, F_SPRINTING) || !getstamina(lf) || (getstamina(lf) <= (getmaxstamina(lf)/2))) {
specificcheckok = B_FALSE; specificcheckok = B_FALSE;
} }
if (isairborne(lf)) { if (isairborne(lf, NULL)) {
specificcheckok = B_FALSE; specificcheckok = B_FALSE;
} }
} }
@ -3148,13 +3158,13 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
} }
if (ot->id == OT_A_TRIPLF) { if (ot->id == OT_A_TRIPLF) {
if (isairborne(victim)) { if (isairborne(victim, NULL)) {
specificcheckok = B_FALSE; specificcheckok = B_FALSE;
} }
} }
if ((ot->id == OT_A_TUMBLE) || (ot->id == OT_A_JUMP)) { if ((ot->id == OT_A_TUMBLE) || (ot->id == OT_A_JUMP)) {
if (lfhasflag(lf, F_GRABBING) || lfhasflag(lf, F_GRABBEDBY) || isairborne(lf)) { if (lfhasflag(lf, F_GRABBING) || lfhasflag(lf, F_GRABBEDBY) || isairborne(lf, NULL)) {
specificcheckok = B_FALSE; specificcheckok = B_FALSE;
} }
} }

View File

@ -33,10 +33,10 @@ int applyarmourdamage(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damty
int damtaken = 0; int damtaken = 0;
// first of all, only apply some of the damage // first of all, only apply some of the damage
dam /= 2; //dam /= 2;
if (dam == 0) { //if (dam == 0) {
return 0; // return 0;
} // }
// special case - missiles always hit flak jacket // special case - missiles always hit flak jacket
if (damtype == DT_PROJECTILE) { if (damtype == DT_PROJECTILE) {
@ -193,6 +193,7 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
int attackedfriend = B_FALSE; int attackedfriend = B_FALSE;
int attackedpeaceful = B_FALSE; int attackedpeaceful = B_FALSE;
enum SKILLLEVEL slev; enum SKILLLEVEL slev;
int dostamloss = B_TRUE;
// warn if attacking will cause injury // warn if attacking will cause injury
if (!force && isplayer(lf) && haslos(lf, c)) { if (!force && isplayer(lf) && haslos(lf, c)) {
@ -256,7 +257,7 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
} }
attackedpeaceful = B_TRUE; attackedpeaceful = B_TRUE;
// non-evil players get no xp for attacking peaceful lfs // non-evil players get no xp for attacking peaceful lfs
if ((isplayer(lf) || areallies(player, lf)) && (getalignment(lf) != AL_EVIL)) { if ((isplayer(lf) || areallies(player, lf)) && (getalignment(player) != AL_EVIL)) {
killflagsofid(c->lf->flags, F_XPVAL); killflagsofid(c->lf->flags, F_XPVAL);
addflag(c->lf->flags, F_XPVAL, 0, NA, NA, NULL); addflag(c->lf->flags, F_XPVAL, 0, NA, NA, NULL);
real_warnabout(TEXT_WARN_NOXP_GOODVSPEACEFUL, PERMENANT, B_FALSE); real_warnabout(TEXT_WARN_NOXP_GOODVSPEACEFUL, PERMENANT, B_FALSE);
@ -812,13 +813,21 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
} }
} }
//if (isplayer(lf)) { dostamloss = B_TRUE; // default
slev = getskill(lf, SK_COMBAT); slev = getskill(lf, SK_COMBAT);
if (slev != PR_MASTER) { if (slev == PR_MASTER) {
if (!pctchance(slev * 10)) { dostamloss = B_FALSE;
// lose a bit of stamina } else if (lfhasflagval(lf, F_LASTATTACKHIT, B_FALSE, NA, NA, NULL) &&
modstamina(lf, -getattackstamloss(lf)); (getskill(lf, SK_ATHLETICS) >= PR_BEGINNER)) {
} // missed, and we have balance via athletics skill
dostamloss = B_FALSE;
} else if (pctchance(slev * 10)) {
dostamloss = B_FALSE;
}
if (dostamloss) {
// lose a bit of stamina
modstamina(lf, -getattackstamloss(lf));
} }
//} //}
@ -1222,6 +1231,11 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
if (ndam > 0) { if (ndam > 0) {
flag_t *f; flag_t *f;
// hit!
killflagsofid(lf->flags, F_LASTATTACKHIT);
addflag(lf->flags, F_LASTATTACKHIT, B_TRUE, NA, NA, NULL);
for (i = 0; i < ndam; i++) { for (i = 0; i < ndam; i++) {
int damreducedbyarmour = 0; int damreducedbyarmour = 0;
int backstab = B_FALSE; int backstab = B_FALSE;
@ -1285,8 +1299,9 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
// damaged during the call to criticalhit() later on. // damaged during the call to criticalhit() later on.
if ((dam[i] > 0) && !backstab && !critical && ismeleedam(damtype[i])) { if ((dam[i] > 0) && !backstab && !critical && ismeleedam(damtype[i])) {
// modify for defender's armour // modify for defender's armour
// first figure out how much to reduce the damage by.
damreducedbyarmour = getarmourdamreduction(victim, wep, dam[i], damtype[i]); damreducedbyarmour = getarmourdamreduction(victim, wep, dam[i], damtype[i]);
// now actually reduce the damage amount
applyarmourdamreduction(victim, wep, damreducedbyarmour, &dam[i], damtype[i]); applyarmourdamreduction(victim, wep, damreducedbyarmour, &dam[i], damtype[i]);
} }
@ -1590,21 +1605,19 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
if (!lfhasflag(lf, F_HEAVYBLOW) && dam[0]) { if (!lfhasflag(lf, F_HEAVYBLOW) && dam[0]) {
wepeffects(wep->flags, victim->cell, damflag, dam[0], isunarmed); wepeffects(wep->flags, victim->cell, damflag, dam[0], isunarmed);
} }
if (isunarmed) { f = lfhasflag(lf, F_FREEZINGTOUCH);
f = lfhasflag(lf, F_FREEZINGTOUCH); if (f) {
if (f) { int diff;
int diff; diff = f->val[2]*20;
diff = f->val[2]*20; if (isimmuneto(victim->flags, DT_COLD, B_FALSE) || skillcheck(victim, SC_RESISTMAG, diff, 0)) {
if (isimmuneto(victim->flags, DT_COLD, B_FALSE) || skillcheck(victim, SC_RESISTMAG, diff, 0)) { if (isplayer(victim)) {
if (isplayer(victim)) { msg("You feel mildly chilly.");
msg("You feel mildly chilly."); }
} } else {
} else { // victim turns to ice for a while!
// victim turns to ice for a while! freezelf(victim, lf, f->val[1]);
freezelf(victim, lf, f->val[1]);
}
killflag(f);
} }
killflag(f);
} }
// critical hit effects // critical hit effects
@ -1696,6 +1709,8 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
} }
} else { // miss! } else { // miss!
if (aidb) dblog(".oO { i missed! }"); if (aidb) dblog(".oO { i missed! }");
killflagsofid(lf->flags, F_LASTATTACKHIT);
addflag(lf->flags, F_LASTATTACKHIT, B_FALSE, NA, NA, NULL);
// announce it // announce it
if (weppassthrough) { if (weppassthrough) {
if (cansee(player, lf)) { if (cansee(player, lf)) {
@ -1995,13 +2010,14 @@ int attackob(lifeform_t *lf, object_t *o, object_t *wep, flag_t *damflag) {
// still not dead? more checks // still not dead? more checks
if (!isdeadob(o)) { if (!isdeadob(o)) {
object_t *oo;
f = hasflag(o->flags, F_TRAPPED); f = hasflag(o->flags, F_TRAPPED);
if (f && pctchance(75)) { if (f && pctchance(75)) {
doobtraps(o, lf); doobtraps(o, lf);
} else { } else {
// if a trap didn't go off, you might break the lock // if a trap didn't go off, you might break the lock
f = hasflag(o->flags, F_LOCKED); f = hasflag(o->flags, F_LOCKED);
if (f && (damtype[i] == DT_BASH)) { if (f && (damtype[0] == DT_BASH)) {
int difficulty; int difficulty;
int unlockit = B_FALSE; int unlockit = B_FALSE;
difficulty = f->val[1]; difficulty = f->val[1];
@ -2021,7 +2037,18 @@ int attackob(lifeform_t *lf, object_t *o, object_t *wep, flag_t *damflag) {
} }
} }
} }
// objects inside might smash
for (oo = o->contents->first ;oo ; oo = oo->next) {
if (willshatter(oo->material->id) && onein(2)) {
if (isplayer(lf)) {
// since the sound won't work.
msg("You hear shattering glass from inside %s.", obname);
}
// damstring should never be used...
shatter(oo, B_FALSE, "shattering damage", lf);
}
}
} }
return B_FALSE; return B_FALSE;
} }
@ -3025,6 +3052,7 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical,
} else { } else {
int myroll; int myroll;
int reachpenalty = 0; int reachpenalty = 0;
int vicheight = 0;
// actually roll... // actually roll...
baseacc = getlfaccuracy(lf, wep); baseacc = getlfaccuracy(lf, wep);
acc = baseacc; acc = baseacc;
@ -3079,7 +3107,14 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical,
} }
acc -= ev; acc -= ev;
if (db) dblog("%s: minus victim's evaion (%d) -> %d", lfname, ev, acc); if (db) dblog("%s: minus victim's evasion (%d) -> %d", lfname, ev, acc);
// modify if victim is flying and we're not
if (isairborne(victim,&vicheight)) {
if (!isairborne(lf, NULL)) {
acc -= (5 * vicheight);
}
}
// modify if we can't see the victim // modify if we can't see the victim
if (!cansee(lf, victim)) { if (!cansee(lf, victim)) {

483
data.c

File diff suppressed because it is too large Load Diff

Binary file not shown.

27
defs.h
View File

@ -568,6 +568,7 @@ enum SHOPACTION {
#define FROMPOISON (-9862) #define FROMPOISON (-9862)
#define FROMLYCANTHROPY (-9861) #define FROMLYCANTHROPY (-9861)
#define FROMGAMESTART (-9860) #define FROMGAMESTART (-9860)
#define FROMABIL (-9859)
#define IMPOSSIBLE (9999) #define IMPOSSIBLE (9999)
@ -746,6 +747,7 @@ enum SKILL {
SK_COOKING, SK_COOKING,
SK_EVASION, SK_EVASION,
SK_FIRSTAID, SK_FIRSTAID,
SK_FLIGHT,
SK_LISTEN, SK_LISTEN,
SK_LOCKPICKING, SK_LOCKPICKING,
SK_METALWORK, SK_METALWORK,
@ -795,7 +797,7 @@ enum SKILL {
SK_SS_TRANSLOCATION, SK_SS_TRANSLOCATION,
SK_SS_WILD, SK_SS_WILD,
}; };
#define MAXSKILLS 56 #define MAXSKILLS 57
// proficiency levels // proficiency levels
enum SKILLLEVEL { enum SKILLLEVEL {
@ -2004,6 +2006,7 @@ enum OBTYPE {
OT_A_FEIGNDEATH, OT_A_FEIGNDEATH,
OT_A_FLIP, OT_A_FLIP,
OT_A_FLURRY, OT_A_FLURRY,
OT_A_FLY,
OT_A_FULLSHIELD, OT_A_FULLSHIELD,
OT_A_GRAB, OT_A_GRAB,
OT_A_CHARGE, OT_A_CHARGE,
@ -2081,6 +2084,7 @@ enum OBTYPE {
OT_LANTERNOIL, OT_LANTERNOIL,
OT_LOCKPICK, OT_LOCKPICK,
OT_PANPIPES, OT_PANPIPES,
OT_PEACEPIPES,
OT_PICKAXE, OT_PICKAXE,
OT_ROPE, OT_ROPE,
OT_SACK, OT_SACK,
@ -2182,6 +2186,7 @@ enum OBTYPE {
OT_FLESHCHUNK, OT_FLESHCHUNK,
OT_TUSK, OT_TUSK,
OT_WOODPLANK, OT_WOODPLANK,
OT_WOODSHARD,
OT_METALSHEET, OT_METALSHEET,
// trail objects // trail objects
OT_FOOTPRINT, OT_FOOTPRINT,
@ -2787,6 +2792,10 @@ enum FLAG {
// v0 = radius to scatter new object in // v0 = radius to scatter new object in
// (0 or NA means just convert the object) // (0 or NA means just convert the object)
// v1 = dirtype for radius // v1 = dirtype for radius
F_BREAKOB, // if killed by damtype v0, change to
// object 'text'.
// IMPORTANT: can only have up to 2 of these per
// damage type.
F_NOBLESS, // can't be blessed or cursed F_NOBLESS, // can't be blessed or cursed
F_NOQUALITY, // can't be masterwork / shoddy F_NOQUALITY, // can't be masterwork / shoddy
F_NOSTEAL, // this object can't be stolen, blown away, etc. F_NOSTEAL, // this object can't be stolen, blown away, etc.
@ -2883,6 +2892,7 @@ enum FLAG {
F_CHARGEOUTMSG, // text = msg when charges are gone F_CHARGEOUTMSG, // text = msg when charges are gone
F_HELPSCLIMB, // object gives v0 bonus to sc_climb checks. F_HELPSCLIMB, // object gives v0 bonus to sc_climb checks.
F_HELPSDIG, // object can dig. does v0 dam to cells. F_HELPSDIG, // object can dig. does v0 dam to cells.
// also makes noise 'text' at volume v1
F_HELPSDISARM, // object gives v0 bonus to disarm trap checks. F_HELPSDISARM, // object gives v0 bonus to disarm trap checks.
F_HELPSREPAIR, // object gives v1 bonus to repairing obejcts F_HELPSREPAIR, // object gives v1 bonus to repairing obejcts
// made of material v0. Also decreases the // made of material v0. Also decreases the
@ -2918,6 +2928,8 @@ enum FLAG {
F_DRINKABLE, // you can drink this. val1 = nutrition. 100 = a meal F_DRINKABLE, // you can drink this. val1 = nutrition. 100 = a meal
// -1 means "nutrition is weight x abs(val1)" // -1 means "nutrition is weight x abs(val1)"
// if v2=DONTKILL, this object does NOT die when drunk. // if v2=DONTKILL, this object does NOT die when drunk.
F_OPERSOUND, // v0 = volume of sound when operating this
// text = noise
F_OPERABLE, // can operate? F_OPERABLE, // can operate?
F_OPERWITHOUTHANDS, // can operate without having hands or being F_OPERWITHOUTHANDS, // can operate without having hands or being
// humanoid // humanoid
@ -3230,6 +3242,8 @@ enum FLAG {
// with vals v1,v2,text. // with vals v1,v2,text.
// OR // OR
// eating this object gives it. // eating this object gives it.
F_EATMUTATE, // same as eatconfer, but only works if you have
// f_mutable.
// player only flags // player only flags
F_AICONTROLLED, // player will be controlled by the computer F_AICONTROLLED, // player will be controlled by the computer
F_DONEBURNMSG, // tells the game not to say 'the {celltype} burns!' F_DONEBURNMSG, // tells the game not to say 'the {celltype} burns!'
@ -3282,6 +3296,7 @@ enum FLAG {
// power. if not given, power comes from depth. // power. if not given, power comes from depth.
F_NOSMELL, // lf can't smell. not affected by stench, and F_NOSMELL, // lf can't smell. not affected by stench, and
// can't get enhancesmell. // can't get enhancesmell.
F_NOSTAM, // this lf has infinite stamina
F_NOTALK, // override ability to talk F_NOTALK, // override ability to talk
F_NOGIVECRITS, // monsters can't take critical hits F_NOGIVECRITS, // monsters can't take critical hits
F_NOTAKECRITS, // monsters can't take critical hits F_NOTAKECRITS, // monsters can't take critical hits
@ -3290,7 +3305,6 @@ enum FLAG {
// v0 = max time allowed to rest before checkout // v0 = max time allowed to rest before checkout
// v1 = total time rested // v1 = total time rested
// text = obid of hotel // text = obid of hotel
F_FLIGHTEVASION,// +v0 evasion if flying
F_SWIMEVASION, // +v0 evasion if swimming F_SWIMEVASION, // +v0 evasion if swimming
F_ALIGNMENT, // v0 = al_good, al_neutral, al_evil. default neutral. F_ALIGNMENT, // v0 = al_good, al_neutral, al_evil. default neutral.
// if al_none is selected for the player, they // if al_none is selected for the player, they
@ -3537,6 +3551,10 @@ enum FLAG {
// eg: text=="st" means they know of shops+traps // eg: text=="st" means they know of shops+traps
F_NOJOBTEXT, // this lf's name is 'a xxx', not 'a xxx wizard' etc F_NOJOBTEXT, // this lf's name is 'a xxx', not 'a xxx wizard' etc
F_LASTDIR, // this is the last direction we moved. F_LASTDIR, // this is the last direction we moved.
F_LASTATTACKHIT, // did our last attack hit or miss?
// v0 = B_TRUE = hit
// v0 = B_FALSE = miss
//F_OWNERLASTDIR, // for pets, this it the last dir our owner moved //F_OWNERLASTDIR, // for pets, this it the last dir our owner moved
// when we could see them. // when we could see them.
F_ISPRISONER, // this lf wants to escape to the surface F_ISPRISONER, // this lf wants to escape to the surface
@ -3677,6 +3695,7 @@ enum FLAG {
F_GODGIFTTEXT, // text = what the god says when you get a gift F_GODGIFTTEXT, // text = what the god says when you get a gift
F_GODASK1, // text = how the god asks you to join them F_GODASK1, // text = how the god asks you to join them
F_GODASK2, // text = how the god asks you to join them (2nd line) F_GODASK2, // text = how the god asks you to join them (2nd line)
F_GODDECLINE, // text = what the god says if you decline offer to join
F_GODTEXTAPPEAR, // text = godname ->xxxxx<- (when they teleport in) F_GODTEXTAPPEAR, // text = godname ->xxxxx<- (when they teleport in)
F_GODOF, // text = what this lf is the god of. use capitals. F_GODOF, // text = what this lf is the god of. use capitals.
F_GODLIKES, // text = something this god likes (ie. incs piety) F_GODLIKES, // text = something this god likes (ie. incs piety)
@ -3876,7 +3895,7 @@ enum FLAG {
// lower chance of rare monsters // lower chance of rare monsters
F_EXTRAMP, // lf has +v0 % extra maxmp F_EXTRAMP, // lf has +v0 % extra maxmp
F_FEIGNINGDEATH, // lf is pretending to be dead F_FEIGNINGDEATH, // lf is pretending to be dead
F_FLYING, // lf is flying F_FLYING, // lf is flying. v0 = feet height
F_FASTACT, // modifier for action speed F_FASTACT, // modifier for action speed
F_FASTMETAB, // hunger counter increases faster, poison cures faster. F_FASTMETAB, // hunger counter increases faster, poison cures faster.
// v0 is multiplier. // v0 is multiplier.
@ -4016,6 +4035,7 @@ enum FLAG {
F_EATING, // lf is eating obid v0 F_EATING, // lf is eating obid v0
F_DIGGING, // v0/v1 = cell where lf is digging. F_DIGGING, // v0/v1 = cell where lf is digging.
// v2 is how much to dig per turn. // v2 is how much to dig per turn.
// text = obid of tool we are using to dig.
F_REPAIRING, // text = obid of held item we are repairing. F_REPAIRING, // text = obid of held item we are repairing.
F_TRAINING, // are we training? cleared on any action other than rest. F_TRAINING, // are we training? cleared on any action other than rest.
// v0 = current training amount // v0 = current training amount
@ -4556,6 +4576,7 @@ typedef struct habitat_s {
int randvaultpct; // % chance that a room will be a vault int randvaultpct; // % chance that a room will be a vault
//int maxvisrange; //int maxvisrange;
enum OBTYPE upstairtype, downstairtype; enum OBTYPE upstairtype, downstairtype;
int stairsinrooms;
enum CELLTYPE emptycelltype,solidcelltype; enum CELLTYPE emptycelltype,solidcelltype;
struct habitat_s *next, *prev; struct habitat_s *next, *prev;
} habitat_t; } habitat_t;

31
god.c
View File

@ -536,17 +536,24 @@ void askforworship(enum RACE rid) {
say(god, getflagtext(god->flags, F_GODASK1), SV_TALK); more(); say(god, getflagtext(god->flags, F_GODASK1), SV_TALK); more();
msg("\"%s\"", getflagtext(god->flags, F_GODASK2)); more(); msg("\"%s\"", getflagtext(god->flags, F_GODASK2)); more();
yn = askchar("Will you accept", "yn", "n", B_TRUE, B_FALSE); yn = '?';
if (yn == 'y') { while (yn == '?') {
// should never be true, but check just in case... yn = askchar("Will you accept", "yn?", "n", B_TRUE, B_FALSE);
if (!godprayedto(rid)) { if (yn == '?') {
addflag(god->flags, F_PRAYEDTO, B_TRUE, NA, NA, NULL); describegod(god);
} else if (yn == 'y') {
// should never be true, but check just in case...
if (!godprayedto(rid)) {
addflag(god->flags, F_PRAYEDTO, B_TRUE, NA, NA, NULL);
}
// always get a gift, but announce it first.
say(god, getflagtext(god->flags, F_GODGIFTTEXT), SV_TALK); more();
godgiftmaybe(rid, B_TRUE, B_FALSE);
// increment piety so that it doesn't remain around the border.
modpiety(rid, PIETYPRAYLOSS);
} else { // ie. no
msg("\"%s\"", getflagtext(god->flags, F_GODDECLINE)); more();
} }
// always get a gift, but announce it first.
say(god, getflagtext(god->flags, F_GODGIFTTEXT), SV_TALK); more();
godgiftmaybe(rid, B_TRUE, B_FALSE);
// increment piety so that it doesn't remain around the border.
modpiety(rid, PIETYPRAYLOSS);
} }
} }
@ -1550,10 +1557,12 @@ int godgiftmaybe(enum RACE rid, int fromtemple, int announce) {
wep = getweapon(player); wep = getweapon(player);
if (wep && !hasflag(wep->flags, F_HASBRAND)) { if (wep && !hasflag(wep->flags, F_HASBRAND)) {
char obname[BUFLEN]; char obname[BUFLEN];
flag_t *f;
getobname(wep,obname,1); getobname(wep,obname,1);
// announce // announce
msg("Your %s vibrates, and you suddenly thirst for vengeance!", noprefix(obname)); msg("Your %s vibrates, and you suddenly thirst for vengeance!", noprefix(obname));
addflag(wep->flags, F_REVENGE, B_TRUE, NA, NA, NULL); f = addflag(wep->flags, F_REVENGE, B_TRUE, NA, NA, NULL);
f->known = B_TRUE;
} else { } else {
switch (rnd(1,7)) { switch (rnd(1,7)) {
case 1: case 1:

31
io.c
View File

@ -742,6 +742,7 @@ cell_t *real_askcoords(char *prompt, char *subprompt, int targettype, lifeform_t
object_t *wep,*o; object_t *wep,*o;
char extrainfo[BIGBUFLEN]; char extrainfo[BIGBUFLEN];
enum SKILLLEVEL lorelev; enum SKILLLEVEL lorelev;
int height = 0;
lorelev = getlorelevel(player, c->lf->race->raceclass->id); lorelev = getlorelevel(player, c->lf->race->raceclass->id);
strcpy(extrainfo, ""); strcpy(extrainfo, "");
getlfnamea(c->lf, buf); getlfnamea(c->lf, buf);
@ -819,10 +820,12 @@ cell_t *real_askcoords(char *prompt, char *subprompt, int targettype, lifeform_t
// prevent showing 'prone' and 'asleep' // prevent showing 'prone' and 'asleep'
if (strlen(extrainfo)) strcat(extrainfo, ", "); if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, "prone"); strcat(extrainfo, "prone");
} else if (isairborne(c->lf)) { } else if (isairborne(c->lf, &height)) {
if (strlen(extrainfo)) strcat(extrainfo, ", "); if (strlen(extrainfo)) strcat(extrainfo, ", ");
if (lfhasflag(c->lf, F_FLYING)) { if (lfhasflag(c->lf, F_FLYING)) {
strcat(extrainfo, "flying"); char fbuf[BUFLEN];
sprintf(fbuf, "flying:%d",height);
strcat(extrainfo, fbuf);
} else if (lfhasflag(c->lf, F_LEVITATING)) { } else if (lfhasflag(c->lf, F_LEVITATING)) {
strcat(extrainfo, "levitating"); strcat(extrainfo, "levitating");
} else { } else {
@ -1693,6 +1696,14 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
donesomething = B_TRUE; donesomething = B_TRUE;
} }
break; break;
case F_FREEZINGTOUCH:
if (isplayer(lf)) { // don't know if monsters get it
msg("Your hands begin to glow blue!");
} else {
msg("%s%s hands begin to glow blue!", lfname, getpossessive(lfname));
}
donesomething = B_TRUE;
break;
case F_FULLSHIELD: case F_FULLSHIELD:
o = hasobid(lf->pack, atol(f->text)); o = hasobid(lf->pack, atol(f->text));
assert(o); assert(o);
@ -2539,6 +2550,14 @@ int announceflagloss(lifeform_t *lf, flag_t *f) {
msg("^%c%s %s less sick now.^n", getlfcol(lf, CC_VGOOD), lfname, isplayer(lf) ? "feel" : "looks"); msg("^%c%s %s less sick now.^n", getlfcol(lf, CC_VGOOD), lfname, isplayer(lf) ? "feel" : "looks");
donesomething = B_TRUE; donesomething = B_TRUE;
break; break;
case F_FREEZINGTOUCH:
if (isplayer(lf)) {
msg("Your hands are no longer glowing blue.");
} else {
msg("%s%s hands are no longer glowing blue.", lfname, getpossessive(lfname));
}
donesomething = B_TRUE;
break;
case F_FULLSHIELD: case F_FULLSHIELD:
msg("%s %s no longer fully shielded.", lfname, isplayer(lf) ? "are" : "is"); msg("%s %s no longer fully shielded.", lfname, isplayer(lf) ? "are" : "is");
donesomething = B_TRUE; donesomething = B_TRUE;
@ -3292,7 +3311,7 @@ void listobs(WINDOW *win, object_t **mylist, int *sellist, int *selcount, int fi
long points; long points;
points = getobpoints(mylist[i]); points = getobpoints(mylist[i]);
if (points > 0) { if (points > 0) {
snprintf(pointsbuf, BUFLEN, " [%ld points]", points); snprintf(pointsbuf, BUFLEN, " [%ld point%s]", points, (points == 1) ? "" : "s");
} }
} }
@ -7725,7 +7744,6 @@ char *makedesc_race(enum RACE rid, char *retbuf, int showextra, int forplayersel
break; break;
case F_ENHANCESMELL: if (lorelev >= PR_BEGINNER) sprintf(buf, "Enhanced sense of smell (range %d)", f->val[0]); break; case F_ENHANCESMELL: if (lorelev >= PR_BEGINNER) sprintf(buf, "Enhanced sense of smell (range %d)", f->val[0]); break;
case F_FEARLESS: if (lorelev >= PR_BEGINNER) sprintf(buf, "Fearless"); break; case F_FEARLESS: if (lorelev >= PR_BEGINNER) sprintf(buf, "Fearless"); break;
case F_FLIGHTEVASION: if (lorelev >= PR_BEGINNER) sprintf(buf, "%d%% evasion while flying", f->val[0]); break;
case F_FLYING: if (lorelev >= PR_NOVICE) sprintf(buf, "Can fly at will"); break; case F_FLYING: if (lorelev >= PR_NOVICE) sprintf(buf, "Can fly at will"); break;
case F_HEAVYBLOW: if (lorelev >= PR_ADEPT) sprintf(buf, "Attacks will knock enemies backwards"); break; case F_HEAVYBLOW: if (lorelev >= PR_ADEPT) sprintf(buf, "Attacks will knock enemies backwards"); break;
case F_HITCONFER: case F_HITCONFER:
@ -11071,6 +11089,7 @@ void drawstatus(void) {
enum ATTRIB a; enum ATTRIB a;
int myatt[MAXATTS]; int myatt[MAXATTS];
int xpleft; int xpleft;
int height;
curs_set(0); curs_set(0);
wclear(statwin); wclear(statwin);
@ -11213,10 +11232,10 @@ void drawstatus(void) {
unsetcol(statwin, C_BOLDBLUE); unsetcol(statwin, C_BOLDBLUE);
} }
if (isairborne(player)) { if (isairborne(player, &height)) {
if (lfhasflag(player, F_FLYING)) { if (lfhasflag(player, F_FLYING)) {
setcol(statwin, C_BOLDBLUE); setcol(statwin, C_BOLDBLUE);
wprintw(statwin, " Fly"); wprintw(statwin, " Fly:%d",height);
unsetcol(statwin, C_BOLDBLUE); unsetcol(statwin, C_BOLDBLUE);
} else if (lfhasflag(player, F_LEVITATING)) { } else if (lfhasflag(player, F_LEVITATING)) {
setcol(statwin, C_BOLDBLUE); setcol(statwin, C_BOLDBLUE);

392
lf.c
View File

@ -660,6 +660,7 @@ int canbuild(lifeform_t *lf, objecttype_t *ot, char *needtext, enum OBTYPE *need
return B_FALSE; return B_FALSE;
} }
// can lf cast spell/use ability 'oid'
int cancast(lifeform_t *lf, enum OBTYPE oid, int *mpcost) { int cancast(lifeform_t *lf, enum OBTYPE oid, int *mpcost) {
int castable = B_FALSE; int castable = B_FALSE;
flag_t *f; flag_t *f;
@ -1236,8 +1237,8 @@ int canreach(lifeform_t *lf, lifeform_t *victim, int *reachpenalty) {
// harder to hit flying/levitating enemies, or ones climbing // harder to hit flying/levitating enemies, or ones climbing
// (ie they are higher than you) // (ie they are higher than you)
lffootheight = getlfheight(lf); lffootheight = getfeetheight(lf);
victimfootheight = getlfheight(victim); victimfootheight = getfeetheight(victim);
diff = victimfootheight - (getlfsize(lf) + lffootheight); diff = victimfootheight - (getlfsize(lf) + lffootheight);
@ -1298,7 +1299,7 @@ int canreachbp(lifeform_t *lf, lifeform_t *victim, enum BODYPART bp) {
// your reach is defined as anywhere between your feet and just over your // your reach is defined as anywhere between your feet and just over your
// head. flying creatures have more leeway. // head. flying creatures have more leeway.
if (isairborne(lf)) { if (isairborne(lf, NULL)) {
topthresh = 3; topthresh = 3;
bottomthresh = 2; bottomthresh = 2;
} else { } else {
@ -1343,7 +1344,7 @@ int cansee_real(lifeform_t *viewer, lifeform_t *viewee, int uselos) {
} }
dist = getcelldist(viewer->cell, viewee->cell); dist = getcelldist(viewer->cell, viewee->cell);
f = lfhasflag(viewer, F_TREMORSENSE); f = lfhasflag(viewer, F_TREMORSENSE);
if (f && !isairborne(viewee) && !isairborne(viewer)) { if (f && !isairborne(viewee, NULL) && !isairborne(viewer, NULL)) {
if (f->val[0] > 0) { if (f->val[0] > 0) {
tremordist = f->val[0]; tremordist = f->val[0];
} else { } else {
@ -1441,7 +1442,7 @@ int cansee_real(lifeform_t *viewer, lifeform_t *viewee, int uselos) {
} }
// viewee underwater and more than 1 cell away? // viewee underwater and more than 1 cell away?
if ((getobdepth(o, viewee) >= DP_HEAD) && (dist > 1)) { if ((getobdepth(o, viewee) >= DP_HEAD) && (dist > 1)) {
if (!isairborne(viewee)) { if (!isairborne(viewee, NULL)) {
return B_FALSE; return B_FALSE;
} }
} }
@ -2071,7 +2072,8 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
if (targlf && (f->val[2] == B_APPENDYOU)) { if (targlf && (f->val[2] == B_APPENDYOU)) {
char targname[BUFLEN]; char targname[BUFLEN];
if (targlf == lf) { if (targlf == lf) {
strcpy(targname, "itself"); strcpy(targname, it(lf));
strcat(targname, "self");
} else { } else {
getlfname(targlf, targname); getlfname(targlf, targname);
} }
@ -2506,7 +2508,7 @@ int checkfordrowning(lifeform_t *lf, object_t *o) {
flag_t *f; flag_t *f;
enum SKILLLEVEL slev; enum SKILLLEVEL slev;
if (isairborne(lf)) { if (isairborne(lf, NULL)) {
return B_FALSE; return B_FALSE;
} }
@ -2725,6 +2727,7 @@ void copycorpseflags(flagpile_t *dst, flagpile_t *src) {
int continuedigging(lifeform_t *lf) { int continuedigging(lifeform_t *lf) {
cell_t *c; cell_t *c;
flag_t *f = NULL; flag_t *f = NULL;
object_t *digob = NULL;
int digpower; int digpower;
int stopnow = B_FALSE; int stopnow = B_FALSE;
@ -2736,6 +2739,18 @@ int continuedigging(lifeform_t *lf) {
if (!f) { if (!f) {
stopnow = B_TRUE; stopnow = B_TRUE;
} }
if (!stopnow && strlen(f->text)) {
long obid;
// do we still ahve the object we were using to dig?
obid = atol(f->text);
digob = hasobid(lf->pack, obid);
if (!digob) {
stopnow = B_TRUE;
}
}
if (!stopnow) { if (!stopnow) {
c = getcellat(lf->cell->map, f->val[0], f->val[1]); c = getcellat(lf->cell->map, f->val[0], f->val[1]);
if (!c) { if (!c) {
@ -2748,6 +2763,8 @@ int continuedigging(lifeform_t *lf) {
return B_TRUE; return B_TRUE;
} }
if (digob) makeopersound(lf->cell,digob);
digpower = f->val[2]; digpower = f->val[2];
c->hp -= digpower; c->hp -= digpower;
if (c->hp <= 0) { if (c->hp <= 0) {
@ -2867,6 +2884,8 @@ int continuerepairing(lifeform_t *lf, flag_t *repairflag) {
} }
if (helpob) makeopersound(lf->cell,helpob);
// take some time. // take some time.
taketime(lf, getactspeed(lf)); taketime(lf, getactspeed(lf));
@ -4353,8 +4372,16 @@ int digcell(lifeform_t *lf, cell_t *c, object_t *o) {
if (c->type->solid) { if (c->type->solid) {
turntoface(lf, c); turntoface(lf, c);
if (isdiggable(c)) { if (isdiggable(c)) {
char digoid[BUFLEN];
// start digging! // start digging!
addflag(lf->flags, F_DIGGING, c->x, c->y, digpower, NULL); if (o) {
sprintf(digoid, "%ld",o->id);
} else {
strcpy(digoid,"");
}
addflag(lf->flags, F_DIGGING, c->x, c->y, digpower, digoid);
if (isplayer(lf)) { if (isplayer(lf)) {
msg("You start digging into %s %s.", needan(c->type->name) ? "an" : "a", c->type->name); msg("You start digging into %s %s.", needan(c->type->name) ? "an" : "a", c->type->name);
needredraw = B_TRUE; needredraw = B_TRUE;
@ -4491,7 +4518,7 @@ int digup(lifeform_t *lf, object_t *o) {
// if digging with an object, you must be able to reach the roof // if digging with an object, you must be able to reach the roof
if (o) { if (o) {
if (!isairborne(lf)) { if (!isairborne(lf, NULL)) {
if (isplayer(lf)) { if (isplayer(lf)) {
msg("You can't reach the roof!"); msg("You can't reach the roof!");
} }
@ -4984,6 +5011,9 @@ int eat(lifeform_t *lf, object_t *o) {
if (fullyeaten) { if (fullyeaten) {
// special cases // special cases
if (!hasflag(o->flags, F_TAINTED)) { if (!hasflag(o->flags, F_TAINTED)) {
flag_t *mutable = NULL;
flag_t *retflag[MAXCANDIDATES];
int nretflags,i;
if (hasflagval(o->flags, F_CORPSEOF, R_NEWT, NA, NA, NULL)) { if (hasflagval(o->flags, F_CORPSEOF, R_NEWT, NA, NA, NULL)) {
// think "eye of newt" // think "eye of newt"
gainmp(lf, 2); gainmp(lf, 2);
@ -5005,65 +5035,63 @@ int eat(lifeform_t *lf, object_t *o) {
} }
// most eat effects only happen if you have f_MUTABLE. // most eat effects only happen if you have f_MUTABLE.
if (lfhasflag(lf, F_MUTABLE)) { mutable = lfhasflag(lf, F_MUTABLE);
flag_t *retflag[MAXCANDIDATES];
int nretflags,i; getflags(o->flags, retflag, &nretflags, F_EATCONFER, F_EATMUTATE, F_NONE);
getflags(o->flags, retflag, &nretflags, F_EATCONFER, F_NONE); for (i = 0; i < nretflags; i++) {
for (i = 0; i < nretflags; i++) { int chance;
f = retflag[i]; int luckmod = 0;
if (f->val[0] != F_MUTABLE) { f = retflag[i];
int chance; if ((f->id == F_EATMUTATE) && !mutable) continue;
int luckmod = 0;
chance = atoi(f->text); chance = atoi(f->text);
sumflags(lf->flags, F_EXTRALUCK, &luckmod, NULL, NULL); sumflags(lf->flags, F_EXTRALUCK, &luckmod, NULL, NULL);
chance += (luckmod*5); chance += (luckmod*5);
limit(&chance, 0, 100); limit(&chance, 0, 100);
if (pctchance(chance)) { if (pctchance(chance)) {
enum FLAG fid; enum FLAG fid;
int val[2]; int val[2];
fid = f->val[0]; fid = f->val[0];
val[0] = f->val[1]; val[0] = f->val[1];
val[1] = f->val[2]; val[1] = f->val[2];
// already got this? // already got this?
if (lfhasflag(lf, fid)) {
int changed = B_FALSE;
// sometimes improve it
switch (fid) {
case F_DTRESIST: fid = F_DTIMMUNE; changed = B_TRUE; break;
case F_SEEINDARK:
case F_PRODUCESLIGHT:
break; // can have multiple.
default: fid = F_NONE; break;
}
// still got the new one?
if (changed && (fid != F_NONE)) {
if (lfhasflag(lf, fid)) { if (lfhasflag(lf, fid)) {
int changed = B_FALSE; fid = F_NONE;
// sometimes improve it
switch (fid) {
case F_DTRESIST: fid = F_DTIMMUNE; changed = B_TRUE; break;
case F_SEEINDARK:
case F_PRODUCESLIGHT:
break; // can have multiple.
default: fid = F_NONE; break;
}
// still got the new one?
if (changed && (fid != F_NONE)) {
if (lfhasflag(lf, fid)) {
fid = F_NONE;
}
}
}
if (fid != F_NONE) {
// lose half your max hp!
losehp_real(lf, (lf->maxhp/2), DT_DIRECT, NULL,
"the shock of mutation",
B_NODAMADJUST, o, B_NORETALIATE, NULL, B_DAMEFFECTS,
BP_NONE);
if (isplayer(lf)) {
msg("^%cYou convulse in agony as your body mutates!",
getlfcol(lf, CC_BAD));
} else if (cansee(player, lf)) {
msg("^%c%s convulses in agony as its body mutates!",
getlfcol(lf, CC_BAD), lfname);
}
// still alive? you gain the ability!
if (!isdead(lf)) {
addflag(lf->flags, fid, val[0], val[1], NA, NULL);
}
} }
} // end if pctchance }
} // end if v0 not f_mutable }
} // end foreach f_eatconfer flag if (fid != F_NONE) {
} // end if lf has f_mutable // lose half your max hp!
losehp_real(lf, (lf->maxhp/2), DT_DIRECT, NULL,
"the shock of mutation",
B_NODAMADJUST, o, B_NORETALIATE, NULL, B_DAMEFFECTS,
BP_NONE);
if (isplayer(lf)) {
msg("^%cYou convulse in agony as your body mutates!",
getlfcol(lf, CC_BAD));
} else if (cansee(player, lf)) {
msg("^%c%s convulses in agony as its body mutates!",
getlfcol(lf, CC_BAD), lfname);
}
// still alive? you gain the ability!
if (!isdead(lf)) {
addflag(lf->flags, fid, val[0], val[1], NA, NULL);
}
}
} // end if pctchance
} // end foreach f_eatconfer flag
} // end if !tainted } // end if !tainted
// special cases for object types // special cases for object types
@ -5903,7 +5931,7 @@ int fall(lifeform_t *lf, lifeform_t *fromlf, int announce) {
if (isdead(lf)) return B_TRUE; if (isdead(lf)) return B_TRUE;
if (isprone(lf)) return B_TRUE; if (isprone(lf)) return B_TRUE;
if (!isairborne(lf)) { if (!isairborne(lf, NULL)) {
if ((lfhasflag(lf, F_STABILITY) || !hasbp(lf, BP_FEET))) { if ((lfhasflag(lf, F_STABILITY) || !hasbp(lf, BP_FEET))) {
return B_TRUE; return B_TRUE;
} }
@ -7833,10 +7861,10 @@ int getevasion(lifeform_t *lf) {
} }
// flightevasion creatures get extra evasion while flying // flightevasion creatures get extra evasion while flying
f = lfhasflag(lf, F_FLIGHTEVASION); //f = lfhasflag(lf, F_FLIGHTEVASION);
if (f && (isairborne(lf) == F_FLYING)) { //if (f && (isairborne(lf) == F_FLYING)) {
ev += f->val[0]; // ev += f->val[0];
} // }
////////////////////////////////////////////////// //////////////////////////////////////////////////
// now negative modifiers // now negative modifiers
@ -8677,32 +8705,27 @@ enum LFCONDITION getlfcondition(lifeform_t *lf) {
// returns a value representing 'lf's height off the ground. // returns a value representing 'lf's height off the ground.
// higher value means higher // higher value means higher
int getlfheight(lifeform_t *lf) { int getfeetheight(lifeform_t *lf) {
int height = 0; int height = 0;
switch (isairborne(lf)) { int temph;
case F_FLYING: if (isairborne(lf, &temph)) {
height += SZ_HUMAN; height += temph;
break; } else {
case F_LEVITATING: // climbing a wall?
height += SZ_MEDIUM; if (isclimbing(lf)) {
break; if (height < SZ_LARGE) height = SZ_LARGE;
default: } else {
// climbing a wall? object_t *o;
if (isclimbing(lf)) { // is lf climbing on top of something, or on a wall?
if (height < SZ_LARGE) height = SZ_LARGE; o = hasobwithflag(lf->cell->obpile, F_CLIMBOBSTACLE);
} else { if (o) {
object_t *o; flag_t *f;
// is lf climbing on top of something, or on a wall? f = hasflag(o->flags, F_IMPASSABLE);
o = hasobwithflag(lf->cell->obpile, F_CLIMBOBSTACLE); if (f && (f->val[0] > 0)) {
if (o) { height += f->val[0];
flag_t *f; }
f = hasflag(o->flags, F_IMPASSABLE); }
if (f && (f->val[0] > 0)) { }
height += f->val[0];
}
}
}
break;
} }
return height; return height;
} }
@ -8728,16 +8751,6 @@ int getlistendetectrange(lifeform_t *lf) {
return 0; return 0;
} }
int getfeetheight(lifeform_t *lf) {
int howmuch = 0;
switch (isairborne(lf)) {
case F_FLYING: howmuch = SZ_HUMAN; break;
case F_LEVITATING: howmuch = SZ_SMALL; break;
default: break;
}
return howmuch;
}
int getmasterid(lifeform_t *lf) { int getmasterid(lifeform_t *lf) {
flag_t *f; flag_t *f;
f = lfhasflag(lf, F_PETOF); f = lfhasflag(lf, F_PETOF);
@ -8813,6 +8826,19 @@ int getmorale(lifeform_t *lf) {
return gettr(lf); return gettr(lf);
} }
int getnaturalflightheight(lifeform_t *lf) {
switch (getskill(lf, SK_FLIGHT)) {
case PR_NOVICE: return SZ_SMALL;
case PR_BEGINNER: return SZ_MEDIUM;
case PR_ADEPT: return SZ_HUMAN;
case PR_SKILLED: return SZ_LARGE;
case PR_EXPERT: return SZ_HUGE;
case PR_MASTER: return SZ_ENORMOUS;
default: break;
}
return 0;
}
int getnextshortcut(lifeform_t *lf) { int getnextshortcut(lifeform_t *lf) {
flag_t *retflag[MAXCANDIDATES]; flag_t *retflag[MAXCANDIDATES];
int nretflags,i,min = 0; int nretflags,i,min = 0;
@ -9523,7 +9549,7 @@ int getmovespeed(lifeform_t *lf) {
} else if (f->id == F_HIDING) { } else if (f->id == F_HIDING) {
speed += 10; speed += 10;
} else if (f->id == F_INJURY) { } else if (f->id == F_INJURY) {
if (!isairborne(lf)) { if (!isairborne(lf, NULL)) {
switch (f->val[0]) { switch (f->val[0]) {
case IJ_LEGBROKEN: case IJ_LEGBROKEN:
case IJ_HAMSTRUNG: case IJ_HAMSTRUNG:
@ -9533,7 +9559,7 @@ int getmovespeed(lifeform_t *lf) {
} }
} }
} else if (f->id == F_SPRINTING) { } else if (f->id == F_SPRINTING) {
if (!isairborne(lf)) { if (!isairborne(lf, NULL)) {
speed -= 10; speed -= 10;
} }
} }
@ -10103,11 +10129,21 @@ int getstamina(lifeform_t *lf) {
return (int)floor(lf->stamina); return (int)floor(lf->stamina);
} }
int getstaminapct(lifeform_t *lf) {
float max;
max = getmaxstamina(lf);
if ((max == 0) || lfhasflag(lf, F_NOSTAM)) return 100;
return ((float)lf->stamina / max) * 100.0;
}
float getstamregen(lifeform_t *lf) { float getstamregen(lifeform_t *lf) {
float regenrate = STAMREGEN; float regenrate = STAMREGEN;
flag_t *retflag[MAXCANDIDATES]; flag_t *retflag[MAXCANDIDATES];
int nretflags,i; int nretflags,i;
// flying with wings?
if (isflyingwithwings(lf)) return 0;
if (lfhasflag(lf, F_TRAINING)) { if (lfhasflag(lf, F_TRAINING)) {
// don't regain stamina while training! // don't regain stamina while training!
return 0; return 0;
@ -10122,9 +10158,11 @@ float getstamregen(lifeform_t *lf) {
} }
} }
getflags(lf->flags, retflag, &nretflags, F_STAMREGEN, F_NONE); getflags(lf->flags, retflag, &nretflags, F_STAMREGEN, F_FLYING, F_NONE);
for (i = 0; i < nretflags; i++) { for (i = 0; i < nretflags; i++) {
regenrate += atof(retflag[i]->text); if (retflag[i]->id == F_STAMREGEN) {
regenrate += atof(retflag[i]->text);
}
} }
limitf(&regenrate, 0, NA); limitf(&regenrate, 0, NA);
@ -11823,6 +11861,17 @@ flag_t *giveskill(lifeform_t *lf, enum SKILL id) {
} }
} }
if (id == SK_FLIGHT) {
flag_t *f;
int h;
// adjust flight height if we're already flying.
h = getnaturalflightheight(lf);
f = lfhasflag(lf, F_FLYING);
if (f && (f->val[0] < h)) {
f->val[0] = h;
}
}
if (id == SK_ARMOUR) { if (id == SK_ARMOUR) {
if ((gamemode == GM_GAMESTARTED) && isplayer(lf)) { if ((gamemode == GM_GAMESTARTED) && isplayer(lf)) {
if (isplayer(lf)) pleasegodmaybe(R_GODBATTLE, 5); if (isplayer(lf)) pleasegodmaybe(R_GODBATTLE, 5);
@ -13784,13 +13833,23 @@ int haslos_fast(lifeform_t *viewer, cell_t *dest) {
return B_FALSE; return B_FALSE;
} }
enum FLAG isairborne(lifeform_t *lf) { enum FLAG isairborne(lifeform_t *lf, int *height) {
flag_t *f;
if (height) *height = 0;
if (!lf) return B_FALSE; if (!lf) return B_FALSE;
if (lfhasflag(lf, F_FLYING)) { f = lfhasflag(lf, F_FLYING);
if (f) {
if (height) *height = f->val[0];
return F_FLYING; return F_FLYING;
} else if (lfhasflag(lf, F_LEVITATING)) { }
if (lfhasflag(lf, F_LEVITATING)) {
if (height) *height = SZ_MEDIUM;
return F_LEVITATING; return F_LEVITATING;
} else if (lfhasflag(lf, F_ICESLIDE)) { }
if (lfhasflag(lf, F_ICESLIDE)) {
if (height) *height = SZ_MEDIUM;
return F_LEVITATING; return F_LEVITATING;
} }
return F_NONE; return F_NONE;
@ -14037,6 +14096,18 @@ flag_t *isfleeingfrom(lifeform_t *lf, lifeform_t *runfrom) {
return lfhasflagval(lf, F_FLEEFROM, runfrom->id, NA, NA, NULL); return lfhasflagval(lf, F_FLEEFROM, runfrom->id, NA, NA, NULL);
} }
int isflyingwithwings(lifeform_t *lf) {
flag_t *retflag[MAXCANDIDATES];
int nretflags,i;
getflags(lf->flags, retflag, &nretflags, F_FLYING, F_NONE);
for (i = 0; i < nretflags; i++) {
if (retflag[i]->lifetime == FROMABIL) {
return B_TRUE;
}
}
return B_FALSE;
}
int isfreebp(lifeform_t *lf, enum BODYPART bp) { int isfreebp(lifeform_t *lf, enum BODYPART bp) {
if (hasobwithflagval(lf->pack, F_EQUIPPED, bp, NA, NA, NULL)) return B_FALSE; if (hasobwithflagval(lf->pack, F_EQUIPPED, bp, NA, NA, NULL)) return B_FALSE;
@ -14882,7 +14953,7 @@ object_t *addtrail(lifeform_t *lf, cell_t *where, int dir, int doprints, int dos
// footprints first // footprints first
if (doprints) { if (doprints) {
if (!isairborne(lf) && !lfhasflag(lf, F_NONCORPOREAL)) { if (!isairborne(lf, NULL) && !lfhasflag(lf, F_NONCORPOREAL)) {
int fpdir; int fpdir;
if (getskill(lf, SK_PERCEPTION) >= PR_EXPERT) { if (getskill(lf, SK_PERCEPTION) >= PR_EXPERT) {
// no footprints! // no footprints!
@ -14926,7 +14997,7 @@ object_t *addtrail(lifeform_t *lf, cell_t *where, int dir, int doprints, int dos
void adjustspeedforwater(lifeform_t *lf, int *speed) { void adjustspeedforwater(lifeform_t *lf, int *speed) {
object_t *o; object_t *o;
flag_t *f; flag_t *f;
if (!isairborne(lf)) { if (!isairborne(lf, NULL)) {
for (o = lf->cell->obpile->first ; o ; o = o->next) { for (o = lf->cell->obpile->first ; o ; o = o->next) {
f = hasflag(o->flags, F_DEEPWATER); f = hasflag(o->flags, F_DEEPWATER);
if (f) { if (f) {
@ -15862,7 +15933,7 @@ int isswimming(lifeform_t *lf) {
if (gamemode != GM_GAMESTARTED) { if (gamemode != GM_GAMESTARTED) {
return B_FALSE; return B_FALSE;
} }
if (!isairborne(lf) && (getcellwaterdepth(lf->cell, lf) >= DP_WAIST) && if (!isairborne(lf, NULL) && (getcellwaterdepth(lf->cell, lf) >= DP_WAIST) &&
getskill(lf, SK_SWIMMING)) { getskill(lf, SK_SWIMMING)) {
return B_TRUE; return B_TRUE;
} }
@ -16640,7 +16711,7 @@ void losehpeffects(lifeform_t *lf, int dam, enum DAMTYPE damtype, lifeform_t *fr
noise(lf->cell, NULL, NC_OTHER, SV_CAR, "arcing electricity", NULL); noise(lf->cell, NULL, NC_OTHER, SV_CAR, "arcing electricity", NULL);
for (i = 0 ; i < nretcells; i++) { for (i = 0 ; i < nretcells; i++) {
if (retcell[i]->lf && (retcell[i]->lf != lf)) { if (retcell[i]->lf && (retcell[i]->lf != lf)) {
if (!isairborne(retcell[i]->lf)) { if (!isairborne(retcell[i]->lf, NULL)) {
losehp_real(retcell[i]->lf, dam, DT_ELECTRIC, fromlf, "an electric shock", B_TRUE, NULL, B_FALSE, NULL, B_FALSE, BP_NONE); losehp_real(retcell[i]->lf, dam, DT_ELECTRIC, fromlf, "an electric shock", B_TRUE, NULL, B_FALSE, NULL, B_FALSE, BP_NONE);
} }
} }
@ -17488,16 +17559,8 @@ void modstamina(lifeform_t *lf, float howmuch) {
if (howmuch == 0) return; if (howmuch == 0) return;
// some raceclasses have infinite stamina if (lfhasflag(lf, F_NOSTAM)) {
switch (getraceclass(lf)) { return;
case RC_PLANT:
case RC_ROBOT:
case RC_GOD:
case RC_MAGIC:
case RC_SLIME:
case RC_DEMON:
return;
default: break;
} }
if (isundead(lf)) return; if (isundead(lf)) return;
@ -17643,14 +17706,19 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nclass, int volume,
int dist; int dist;
int difficulty; int difficulty;
int lbonus; int lbonus;
int myvol;
int nwalls = 0; int nwalls = 0;
flag_t *f; flag_t *sleepflag;
if (l == noisemaker) continue; if (l == noisemaker) continue;
// ie. if this lf is in the process of swapping places // ie. if this lf is in the process of swapping places
if (!l->cell) continue; if (!l->cell) continue;
sleepflag = lfhasflag(l, F_ASLEEP);
// can't hear while unconscious
if (sleepflag && (sleepflag->val[1] == ST_KO)) continue;
dist = getcelldist(l->cell, c); dist = getcelldist(l->cell, c);
// listen check difficulty is based on sound distance vs max hearing distance // listen check difficulty is based on sound distance vs max hearing distance
@ -17666,19 +17734,23 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nclass, int volume,
difficulty = (int) ( ((float) dist / ((float)gethearingrange(l) + volume)) * 75); difficulty = (int) ( ((float) dist / ((float)gethearingrange(l) + volume)) * 75);
} }
if (sleepflag) {
myvol = volume - 1;
} else {
myvol = volume;
}
limit(&myvol, 0, NA);
// listen bonus is based on sound volume // listen bonus is based on sound volume
lbonus = volume; lbonus = myvol;
f = lfhasflag(l, F_ASLEEP); if (sleepflag) {
if (f) { lbonus -= 5;
// can't hear while unconscious
if (f->val[1] == ST_KO) continue;
lbonus -= 6;
limit(&lbonus, 0, NA); limit(&lbonus, 0, NA);
} }
// skillcheck to hear this // skillcheck to hear this
if ( (isplayer(l) && haslos(l, c)) || // only player can "hear by seeing" if ( (isplayer(l) && haslos(l, c)) || // only player can "hear by seeing"
(canhear(l, c, volume, &nwalls) && (alwayshear || skillcheck(l, SC_LISTEN, difficulty, lbonus)) ) ) { (canhear(l, c, myvol, &nwalls) && (alwayshear || skillcheck(l, SC_LISTEN, difficulty, lbonus)) ) ) {
flag_t *f; flag_t *f;
// announce? // announce?
if (isplayer(l) && !lfhasflag(l, F_ASLEEP)) { if (isplayer(l) && !lfhasflag(l, F_ASLEEP)) {
@ -17824,8 +17896,8 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nclass, int volume,
practice(l, SK_LISTEN, 1); practice(l, SK_LISTEN, 1);
} }
// migraine? // migraine?
if ((volume > 1) && lfhasflagval(l, F_POISONED, P_MIGRAINE, NA, NA, NULL)) { if ((myvol > 1) && lfhasflagval(l, F_POISONED, P_MIGRAINE, NA, NA, NULL)) {
losehp(l, (volume-1), DT_SONIC, NULL, "a migraine"); losehp(l, (myvol-1), DT_SONIC, NULL, "a migraine");
if (isplayer(l)) { if (isplayer(l)) {
msg("Your head explodes in pain at the sound!"); msg("Your head explodes in pain at the sound!");
} }
@ -17837,7 +17909,7 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nclass, int volume,
f = lfhasflag(l, F_ASLEEP); f = lfhasflag(l, F_ASLEEP);
if (f && (f->val[1] != ST_KO)) { if (f && (f->val[1] != ST_KO)) {
if (f->lifetime > 0) { // ie. temporary if (f->lifetime > 0) { // ie. temporary
timeeffectsflag(f, volume + rnd(1,3)); timeeffectsflag(f, myvol + rnd(1,3));
} else if (f->lifetime == PERMENANT) { } else if (f->lifetime == PERMENANT) {
if (f->val[2] == NA) { if (f->val[2] == NA) {
// ie asleep rather than 'resting' // ie asleep rather than 'resting'
@ -17850,7 +17922,7 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nclass, int volume,
} else { } else {
// ie resting on purpose via 'R' // ie resting on purpose via 'R'
// only wake up if the sound if very close // only wake up if the sound if very close
if (volume >= getcelldist(c, l->cell)) { if (myvol >= getcelldist(c, l->cell)) {
// wake up! // wake up!
if (isplayer(l)) { if (isplayer(l)) {
char wakenoise[BUFLEN]; char wakenoise[BUFLEN];
@ -17906,7 +17978,7 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nclass, int volume,
} }
if (targlf && (targlf->cell)) { // ie. not swapping places if (targlf && (targlf->cell)) { // ie. not swapping places
if (getcelldist(l->cell, c) < getcelldist(l->cell, targlf->cell)) { if (getcelldist(l->cell, c) < getcelldist(l->cell, targlf->cell)) {
if ((volume >= 4) && onein(2)) { if ((myvol >= 4) && onein(2)) {
willrespond = B_TRUE; willrespond = B_TRUE;
} }
} }
@ -17953,7 +18025,7 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nclass, int volume,
} else { } else {
int chasetime; int chasetime;
// if NOT within lof, go and investigate // if NOT within lof, go and investigate
chasetime = volume * 10; chasetime = myvol * 10;
aigoto(l, c, MR_SOUND, NULL, chasetime); aigoto(l, c, MR_SOUND, NULL, chasetime);
} }
} }
@ -19181,7 +19253,7 @@ int startresting(lifeform_t *lf, int willtrain) {
// player can't rest while in the air, unless you're in a motel room // player can't rest while in the air, unless you're in a motel room
if (isplayer(lf)) { if (isplayer(lf)) {
if (isairborne(lf) && !lfhasflag(lf, F_RESTINGINMOTEL)) { if (isairborne(lf, NULL) && !lfhasflag(lf, F_RESTINGINMOTEL)) {
msg("You can't %s while airborne!", willtrain ? "train" : "rest"); msg("You can't %s while airborne!", willtrain ? "train" : "rest");
return B_TRUE; return B_TRUE;
} }
@ -20548,7 +20620,7 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging //if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
if (lfhasflag(lf, F_NATURALFLIGHT) && !isairborne(lf)) { if (lfhasflag(lf, F_NATURALFLIGHT) && !isairborne(lf, NULL)) {
if (cancast(lf, OT_S_FLIGHT, NULL)) { if (cancast(lf, OT_S_FLIGHT, NULL)) {
notime = B_TRUE; notime = B_TRUE;
castspell(lf, OT_S_FLIGHT, lf, NULL, lf->cell, NULL, NULL); castspell(lf, OT_S_FLIGHT, lf, NULL, lf->cell, NULL, NULL);
@ -21401,7 +21473,7 @@ int slipon(lifeform_t *lf, object_t *o) {
char obname[BUFLEN]; char obname[BUFLEN];
char lfname[BUFLEN]; char lfname[BUFLEN];
if (lfhasflag(lf, F_NONCORPOREAL) || isairborne(lf)) { if (lfhasflag(lf, F_NONCORPOREAL) || isairborne(lf, NULL)) {
return B_TRUE; return B_TRUE;
} }
@ -21542,6 +21614,7 @@ void startlfturn(lifeform_t *lf) {
int movedlastturn = B_FALSE; int movedlastturn = B_FALSE;
object_t *bloodamu = NULL; object_t *bloodamu = NULL;
enum TIMEPHASE tp; enum TIMEPHASE tp;
enum FLAG inair = F_NONE;
tp = gettimephase(); tp = gettimephase();
map = lf->cell->map; map = lf->cell->map;
@ -21627,11 +21700,11 @@ void startlfturn(lifeform_t *lf) {
killflagsofid(lf->flags, F_DONELISTEN); killflagsofid(lf->flags, F_DONELISTEN);
killflagsofid(lf->flags, F_DONEBURNMSG); killflagsofid(lf->flags, F_DONEBURNMSG);
killflagsofid(lf->flags, F_NOSWAP); killflagsofid(lf->flags, F_NOSWAP);
killflagsofid(lf->flags, F_LASTATTACKHIT);
movedlastturn = 0; movedlastturn = 0;
movedlastturn += killflagsofid(lf->flags, F_HASBEENMOVED); movedlastturn += killflagsofid(lf->flags, F_HASBEENMOVED);
movedlastturn += killflagsofid(lf->flags, F_MOVED); movedlastturn += killflagsofid(lf->flags, F_MOVED);
// if we didn't turn lsat move, kill our turncounter // if we didn't turn lsat move, kill our turncounter
if (!killflagsofid(lf->flags, F_TURNED)) { if (!killflagsofid(lf->flags, F_TURNED)) {
lf->turncounter = 0; lf->turncounter = 0;
@ -22467,8 +22540,13 @@ void startlfturn(lifeform_t *lf) {
} }
// if you are stunned and flying, you fall // if you are stunned and flying, you fall
if (isairborne(lf) && lfhasflag(lf, F_STUNNED)) { inair = isairborne(lf, NULL);
fall_from_air(lf); if (inair) {
if (lfhasflag(lf, F_STUNNED)) {
fall_from_air(lf);
} else if (isburdened(lf)) {
fall_from_air(lf);
}
} }
getflags(lf->flags, retflag, &nretflags, F_POISONED, F_NONE); getflags(lf->flags, retflag, &nretflags, F_POISONED, F_NONE);
@ -22848,7 +22926,7 @@ void startlfturn(lifeform_t *lf) {
for (i = 0; i < nretflags; i++) { for (i = 0; i < nretflags; i++) {
f = retflag[i]; f = retflag[i];
if (f->id == F_WALKDAMBP) { if (f->id == F_WALKDAMBP) {
if (!isairborne(lf)) { if (!isairborne(lf, NULL)) {
object_t *armour; object_t *armour;
int dam; int dam;
enum BODYPART bp; enum BODYPART bp;
@ -23677,7 +23755,7 @@ void timeeffectslf(lifeform_t *lf) {
while (o && donesomething) { while (o && donesomething) {
int willfall = B_FALSE; int willfall = B_FALSE;
donesomething = B_FALSE; donesomething = B_FALSE;
if ((dir == D_DOWN) && !isairborne(lf)) { if ((dir == D_DOWN) && !isairborne(lf, NULL)) {
object_t *amu; object_t *amu;
willfall = B_TRUE; willfall = B_TRUE;
@ -24061,7 +24139,7 @@ int real_touch(lifeform_t *lf, object_t *o, int onpurpose) {
if (isplayer(lf)) { if (isplayer(lf)) {
msg("^bOw! You burn your hands on %s.",obname); msg("^bOw! You burn your hands on %s.",obname);
} else if (cansee(player, lf)) { } else if (cansee(player, lf)) {
msg("%s burns itself on %s.",lfname, obname); msg("%s burns %sself on %s.",lfname, it(lf), obname);
} }
snprintf(buf, BUFLEN, "touching %s",obname); snprintf(buf, BUFLEN, "touching %s",obname);
if (f->id == F_ONFIRE) { if (f->id == F_ONFIRE) {
@ -24553,7 +24631,7 @@ int usestairs(lifeform_t *lf, object_t *o, int onpurpose, int climb) {
// if we just climbed up through a hole, and are not flying, we want to // if we just climbed up through a hole, and are not flying, we want to
// end up adjacent to the hole in the ground. otherwise we'll just fall // end up adjacent to the hole in the ground. otherwise we'll just fall
// straight back down! // straight back down!
if (hasflag(o->flags, F_PIT) && (dir == D_UP) && !isairborne(lf)) { if (hasflag(o->flags, F_PIT) && (dir == D_UP) && !isairborne(lf, NULL)) {
cell_t *noholecell; cell_t *noholecell;
noholecell = real_getrandomadjcell(newcell, &ccwalkable, B_ALLOWEXPAND, LOF_NEED, NULL, NULL ); noholecell = real_getrandomadjcell(newcell, &ccwalkable, B_ALLOWEXPAND, LOF_NEED, NULL, NULL );
if (noholecell) { if (noholecell) {
@ -24585,7 +24663,7 @@ int usestairs(lifeform_t *lf, object_t *o, int onpurpose, int climb) {
moveto(lf, newcell, onpurpose, B_TRUE); moveto(lf, newcell, onpurpose, B_TRUE);
// take time // take time
if ((dir == D_UP) && !isairborne(lf)) { if ((dir == D_UP) && !isairborne(lf, NULL)) {
stopsprinting(lf); // you can sprint down stairs, but not up stopsprinting(lf); // you can sprint down stairs, but not up
if (onpurpose) taketime(lf, getmovespeed(lf)*2); // takes longer to climb if (onpurpose) taketime(lf, getmovespeed(lf)*2); // takes longer to climb
} else { } else {
@ -24602,7 +24680,7 @@ int usestairs(lifeform_t *lf, object_t *o, int onpurpose, int climb) {
stopsprinting(adjally[n]); stopsprinting(adjally[n]);
movelf(adjally[n], c, B_TRUE); movelf(adjally[n], c, B_TRUE);
climbtime = getmovespeed(adjally[n]); climbtime = getmovespeed(adjally[n]);
if ((dir == D_UP) && !isairborne(adjally[n])) { if ((dir == D_UP) && !isairborne(adjally[n], NULL)) {
climbtime *= 2; climbtime *= 2;
} }
if (onpurpose) taketime(adjally[n], climbtime); if (onpurpose) taketime(adjally[n], climbtime);
@ -24809,7 +24887,13 @@ int validateraces(void) {
if (!hasflag(r->flags, F_TR)) { if (!hasflag(r->flags, F_TR)) {
printf("ERROR in race '%s' - missing F_TR (threat level).\n", r->name); printf("ERROR in race '%s' - missing F_TR (threat level).\n", r->name);
goterror = B_TRUE; goterror = B_TRUE;
}
if (hasflagval(r->flags, F_CANWILL, OT_A_FLY, NA, NA, NULL)) {
if (!getskill(lf,SK_FLIGHT)) {
printf("ERROR in race '%s' - has flight but no flight skill.\n", r->name);
goterror = B_TRUE;
}
} }
if (hasflag(r->flags, F_CANCAST) && !hasflag(r->flags, F_CASTWITHOUTIQ)) { if (hasflag(r->flags, F_CANCAST) && !hasflag(r->flags, F_CASTWITHOUTIQ)) {

8
lf.h
View File

@ -207,14 +207,14 @@ int getleftrightwalls(lifeform_t *lf);
int getlfaccuracy(lifeform_t *lf, object_t *wep); int getlfaccuracy(lifeform_t *lf, object_t *wep);
char getlfcol(lifeform_t *lf, enum MSGCHARCOL cc); char getlfcol(lifeform_t *lf, enum MSGCHARCOL cc);
enum LFCONDITION getlfcondition(lifeform_t *lf); enum LFCONDITION getlfcondition(lifeform_t *lf);
int getlfheight(lifeform_t *lf);
int getlistendetectrange(lifeform_t *lf);
int getfeetheight(lifeform_t *lf); int getfeetheight(lifeform_t *lf);
int getlistendetectrange(lifeform_t *lf);
int getmasterid(lifeform_t *lf); int getmasterid(lifeform_t *lf);
enum SKILLLEVEL getmaxskilllevel(lifeform_t *lf, enum SKILL skid); enum SKILLLEVEL getmaxskilllevel(lifeform_t *lf, enum SKILL skid);
int getminions(lifeform_t *lf, lifeform_t **minion, int *nminions); int getminions(lifeform_t *lf, lifeform_t **minion, int *nminions);
int getmiscastchance(lifeform_t *lf); int getmiscastchance(lifeform_t *lf);
int getmorale(lifeform_t *lf); int getmorale(lifeform_t *lf);
int getnaturalflightheight(lifeform_t *lf);
int getnextshortcut(lifeform_t *lf); int getnextshortcut(lifeform_t *lf);
int getnightvisrange(lifeform_t *lf); int getnightvisrange(lifeform_t *lf);
int getnoisedetails(lifeform_t *lf, enum NOISETYPE nid, flag_t *noiseflag, char *heartext,char *seetext, int *volume, flag_t **returnedflag); int getnoisedetails(lifeform_t *lf, enum NOISETYPE nid, flag_t *noiseflag, char *heartext,char *seetext, int *volume, flag_t **returnedflag);
@ -259,6 +259,7 @@ int getallshields(lifeform_t *lf, enum DAMTYPE damtype, object_t **retob, int *c
int getshieldblockmod(lifeform_t *lf, object_t *o); int getshieldblockmod(lifeform_t *lf, object_t *o);
int getspellspeed(lifeform_t *lf); int getspellspeed(lifeform_t *lf);
int getstamina(lifeform_t *lf); int getstamina(lifeform_t *lf);
int getstaminapct(lifeform_t *lf);
float getstamregen(lifeform_t *lf); float getstamregen(lifeform_t *lf);
char *getplayername(char *buf); char *getplayername(char *buf);
char *getplayernamefull(char *buf); char *getplayernamefull(char *buf);
@ -348,7 +349,7 @@ int haslos(lifeform_t *viewer, cell_t *dest);
//int haslosdark(lifeform_t *viewer, cell_t *dest); //int haslosdark(lifeform_t *viewer, cell_t *dest);
int haslos_fast(lifeform_t *viewer, cell_t *dest); int haslos_fast(lifeform_t *viewer, cell_t *dest);
void interrupt(lifeform_t *lf); void interrupt(lifeform_t *lf);
enum FLAG isairborne(lifeform_t *lf); enum FLAG isairborne(lifeform_t *lf, int *height);
int isaquatic(lifeform_t *lf); int isaquatic(lifeform_t *lf);
flag_t *isasleep(lifeform_t *lf); flag_t *isasleep(lifeform_t *lf);
int isbehind(lifeform_t *lf, lifeform_t *otherlf); int isbehind(lifeform_t *lf, lifeform_t *otherlf);
@ -362,6 +363,7 @@ int isdeaf(lifeform_t *lf);
object_t *isdualweilding(lifeform_t *lf); object_t *isdualweilding(lifeform_t *lf);
flag_t *isfleeing(lifeform_t *lf); flag_t *isfleeing(lifeform_t *lf);
flag_t *isfleeingfrom(lifeform_t *lf, lifeform_t *runfrom); flag_t *isfleeingfrom(lifeform_t *lf, lifeform_t *runfrom);
int isflyingwithwings(lifeform_t *lf);
int isfreebp(lifeform_t *lf, enum BODYPART bp); int isfreebp(lifeform_t *lf, enum BODYPART bp);
int isfriendly(lifeform_t *lf); int isfriendly(lifeform_t *lf);
int isfullyhealed(lifeform_t *lf); int isfullyhealed(lifeform_t *lf);

57
map.c
View File

@ -98,7 +98,7 @@ cell_t *addcell(map_t *m, int x, int y) {
return cell; return cell;
} }
habitat_t *addhabitat(enum HABITAT id, char *name, enum CELLTYPE emptycell, enum CELLTYPE solidcell, int thingchance, int obchance, int vaultchance, int maxvisrange, enum OBTYPE upstairtype, enum OBTYPE downstairtype) { habitat_t *addhabitat(enum HABITAT id, char *name, enum CELLTYPE emptycell, enum CELLTYPE solidcell, int thingchance, int obchance, int vaultchance, int maxvisrange, enum OBTYPE upstairtype, enum OBTYPE downstairtype, int stairsinrooms) {
habitat_t *a; habitat_t *a;
// add to the end of the list // add to the end of the list
if (firsthabitat == NULL) { if (firsthabitat == NULL) {
@ -126,6 +126,7 @@ habitat_t *addhabitat(enum HABITAT id, char *name, enum CELLTYPE emptycell, enum
//a->maxvisrange = maxvisrange; //a->maxvisrange = maxvisrange;
a->upstairtype = upstairtype; a->upstairtype = upstairtype;
a->downstairtype = downstairtype; a->downstairtype = downstairtype;
a->stairsinrooms = stairsinrooms;
return a; return a;
} }
@ -3089,6 +3090,10 @@ int calcroompos(map_t *map, int w, int h, int xmargin, int ymargin, int *bx, int
if (cell->lf && isplayer(cell->lf)) { if (cell->lf && isplayer(cell->lf)) {
valid = B_FALSE; continue; valid = B_FALSE; continue;
} }
// - overlap a cell with an important object
if (hasobwithflag(cell->obpile, F_IMPORTANT)) {
valid = B_FALSE; continue;
}
/* /*
// - overlap the inside of an existing room // - overlap the inside of an existing room
if (cellwalkable(NULL, cell, NULL) && isroom(cell)) { if (cellwalkable(NULL, cell, NULL) && isroom(cell)) {
@ -5051,7 +5056,7 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
for (x = 0; x < map->w; x++) { for (x = 0; x < map->w; x++) {
cell_t *c; cell_t *c;
c = getcellat(map, x, y); c = getcellat(map, x, y);
if (c) { if (c && !hasobwithflag(c->obpile, F_IMPORTANT)) {
// add random obs, but not in vaults // add random obs, but not in vaults
if (isempty(c)) { if (isempty(c)) {
if (!getcellvault(c) || (c->habitat->id == H_HEAVEN)) { if (!getcellvault(c) || (c->habitat->id == H_HEAVEN)) {
@ -7079,8 +7084,10 @@ int finalisemap(map_t *map, object_t *entryob, int exitdir) {
initcondv(&okforstairs, CC_EMPTY, B_TRUE, NA, initcondv(&okforstairs, CC_EMPTY, B_TRUE, NA,
CC_OKFORSTAIRS, B_TRUE, NA, CC_OKFORSTAIRS, B_TRUE, NA,
CC_ISROOM, B_TRUE, NA,
CC_NONE); CC_NONE);
if (map->habitat->stairsinrooms) {
addcond(&okforstairs, CC_ISROOM, B_TRUE, NA);
}
// make sure this map has sufficient up/down staircases as defined by its // make sure this map has sufficient up/down staircases as defined by its
// region type. // region type.
@ -7403,9 +7410,10 @@ void finalisemonster(lifeform_t *lf, lifeform_t *leader, flagpile_t *wantflags,
killflagsofid(lf->flags, F_HIDING); killflagsofid(lf->flags, F_HIDING);
} else { } else {
if (hasflag(lf->race->flags, F_NATURALFLIGHT) && !lfhasflag(lf, F_FLYING)) { if (hasflag(lf->race->flags, F_NATURALFLIGHT) && !lfhasflag(lf, F_FLYING)) {
if (cancast(lf, OT_S_FLIGHT, NULL)) { if (cancast(lf, OT_A_FLY, NULL) && !isburdened(lf)) {
notime = B_TRUE; notime = B_TRUE;
castspell(lf, OT_S_FLIGHT, lf, NULL, lf->cell, NULL, NULL); //castspell(lf, OT_S_FLIGHT, lf, NULL, lf->cell, NULL, NULL);
useability(lf, OT_A_FLY, lf, lf->cell);
notime = B_FALSE; notime = B_FALSE;
} }
} }
@ -8447,19 +8455,19 @@ object_t *hastrailof(obpile_t *op, lifeform_t *lf, enum OBTYPE oid, flag_t **tfl
void initmap(void) { void initmap(void) {
// habitats // habitats
// thingchance, obchance, vaultchance, maxvisrange, upstiartype, downstairtype // thingchance, obchance, vaultchance, maxvisrange, upstiartype, downstairtype, stairs_in_rooms
addhabitat(H_DUNGEON, "dungeon", CT_CORRIDOR, CT_WALL, 5, 60, 30, 6, OT_STAIRSUP, OT_STAIRSDOWN); addhabitat(H_DUNGEON, "dungeon", CT_CORRIDOR, CT_WALL, 5, 60, 30, 6, OT_STAIRSUP, OT_STAIRSDOWN, B_TRUE);
addhabitat(H_CAVE, "cave", CT_DIRT, CT_WALLDIRT, 10, 45, 20, 6, OT_TUNNELUP, OT_TUNNELDOWN); addhabitat(H_CAVE, "cave", CT_DIRT, CT_WALLDIRT, 10, 45, 20, 6, OT_TUNNELUP, OT_TUNNELDOWN, B_FALSE);
addhabitat(H_FOREST, "forest", CT_GRASS, CT_WALLTREE, 5, 75, 0, MAXVISRANGE, OT_TREEUP, OT_TREEDOWN); addhabitat(H_FOREST, "forest", CT_GRASS, CT_WALLTREE, 5, 75, 0, MAXVISRANGE, OT_TREEUP, OT_TREEDOWN, B_FALSE);
addhabitat(H_HEAVEN, "heaven", CT_CORRIDOR, CT_WALLGLASS, 5, 0, 0, MAXVISRANGE, OT_NONE, OT_NONE); addhabitat(H_HEAVEN, "heaven", CT_CORRIDOR, CT_WALLGLASS, 5, 0, 0, MAXVISRANGE, OT_NONE, OT_NONE, B_FALSE);
addhabitat(H_PIT, "pit", CT_CORRIDOR, CT_WALL, 0, 0, 0, 5, OT_NONE, OT_NONE); addhabitat(H_PIT, "pit", CT_CORRIDOR, CT_WALL, 0, 0, 0, 5, OT_NONE, OT_NONE, B_FALSE);
addhabitat(H_VILLAGE, "village", CT_GRASS, CT_WALL, 5, 70, 0, MAXVISRANGE, OT_NONE, OT_NONE); addhabitat(H_VILLAGE, "village", CT_GRASS, CT_WALL, 5, 70, 0, MAXVISRANGE, OT_NONE, OT_NONE, B_FALSE);
addhabitat(H_SEWER, "sewer", CT_MOSSROCK, CT_WALL, 10, 50, 0, MAXVISRANGE, OT_GRATINGROOF, OT_NONE); addhabitat(H_SEWER, "sewer", CT_MOSSROCK, CT_WALL, 10, 50, 0, MAXVISRANGE, OT_GRATINGROOF, OT_NONE, B_FALSE);
addhabitat(H_STOMACH, "stomach", CT_FLOORFLESH, CT_WALLFLESH, 5, 80, 0, MAXVISRANGE, OT_NONE, OT_NONE); addhabitat(H_STOMACH, "stomach", CT_FLOORFLESH, CT_WALLFLESH, 5, 80, 0, MAXVISRANGE, OT_NONE, OT_NONE, B_FALSE);
addhabitat(H_SWAMP, "swamp", CT_CORRIDOR, CT_WALL, 5, 50, 0, MAXVISRANGE, OT_STAIRSUP, OT_STAIRSDOWN); addhabitat(H_SWAMP, "swamp", CT_CORRIDOR, CT_WALL, 5, 50, 0, MAXVISRANGE, OT_STAIRSUP, OT_STAIRSDOWN, B_FALSE);
addhabitat(H_BYHUT, "babayaga's hut", CT_FLOORWOOD, CT_WALLDWOOD, 0, 0, 0, MAXVISRANGE, OT_BYHUTDOOR, OT_NONE); addhabitat(H_BYHUT, "babayaga's hut", CT_FLOORWOOD, CT_WALLDWOOD, 0, 0, 0, MAXVISRANGE, OT_BYHUTDOOR, OT_NONE, B_FALSE);
addhabitat(H_ANTNEST, "ant nest", CT_DIRT, CT_WALLDIRT, 10, 40, 0, MAXVISRANGE, OT_STAIRSUP, OT_STAIRSDOWN); addhabitat(H_ANTNEST, "ant nest", CT_DIRT, CT_WALLDIRT, 10, 40, 0, MAXVISRANGE, OT_STAIRSUP, OT_STAIRSDOWN, B_FALSE);
addhabitat(H_MASTERVAULTS, "master vaults", CT_FLOORDURANITE, CT_WALLDURANITE, 10, 0, 0, MAXVISRANGE, OT_VSTAIRSUP, OT_VSTAIRSDOWN); addhabitat(H_MASTERVAULTS, "master vaults", CT_FLOORDURANITE, CT_WALLDURANITE, 10, 0, 0, MAXVISRANGE, OT_VSTAIRSUP, OT_VSTAIRSDOWN, B_FALSE);
// cell types - solid // cell types - solid
// floorheight, hp, volmod, absorbant // floorheight, hp, volmod, absorbant
@ -9779,15 +9787,24 @@ int remove_deadends(map_t *m, int howmuch) {
cell_t *c; cell_t *c;
c = m->cell[n]; c = m->cell[n];
if (!c->room) { if (!c->room) {
int exits;
exits = countcellexits(c, DT_ORTH);
//if ((countcellexits(c, DT_ORTH) == 1) || //if ((countcellexits(c, DT_ORTH) == 1) ||
// (countcellexits(c, DT_COMPASS) == 1)) { // (countcellexits(c, DT_COMPASS) == 1)) {
if (countcellexits(c, DT_ORTH) == 1) { if (exits == 1) {
// erase this cell // erase this cell
clearcell(c); clearcell(c);
setcelltype(c, solidcell); setcelltype(c, solidcell);
setcellreason(c, "dead-end removed."); setcellreason(c, "dead-end removed.");
count++; count++;
thiscount++; thiscount++;
} else if (exits == 0) {
// erase this cell
clearcell(c);
setcelltype(c, solidcell);
setcellreason(c, "zero-exit deadend removed.");
count++;
thiscount++;
} }
} }
} }
@ -10253,7 +10270,7 @@ void updateknowncells(void) {
// you don't remember cells when you're flying, unless you // you don't remember cells when you're flying, unless you
// have a magic map or photographic memory. // have a magic map or photographic memory.
if (isairborne(player) && !lfhasflag(player, F_PHOTOMEM)) { if (isairborne(player, NULL) && !lfhasflag(player, F_PHOTOMEM)) {
return; return;
} }
if (lfhasflag(player, F_RAGE)) { if (lfhasflag(player, F_RAGE)) {

2
map.h
View File

@ -1,7 +1,7 @@
#include "defs.h" #include "defs.h"
cell_t *addcell(map_t *map, int x, int y); cell_t *addcell(map_t *map, int x, int y);
habitat_t *addhabitat(enum HABITAT id, char *name, enum CELLTYPE emptycell, enum CELLTYPE solidcell, int thingchance, int obchance, int vaultchance, int maxvisrange, enum OBTYPE upstairtype, enum OBTYPE downstairtype); habitat_t *addhabitat(enum HABITAT id, char *name, enum CELLTYPE emptycell, enum CELLTYPE solidcell, int thingchance, int obchance, int vaultchance, int maxvisrange, enum OBTYPE upstairtype, enum OBTYPE downstairtype, int stairsinrooms);
void addhomeobs(lifeform_t *lf, int dolevelobs); void addhomeobs(lifeform_t *lf, int dolevelobs);
map_t *addmap(void); map_t *addmap(void);
lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int randomjobok, int amt, int autogen, int *nadded); lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int randomjobok, int amt, int autogen, int *nadded);

40
move.c
View File

@ -227,7 +227,7 @@ int celldangerous(lifeform_t *lf, cell_t *cell, int onlyifknown, enum ERROR *err
} }
f = hasflag(o->flags, F_PIT); f = hasflag(o->flags, F_PIT);
if (f && (f->val[0] == D_DOWN)) { if (f && (f->val[0] == D_DOWN)) {
if (!isairborne(lf)) { if (!isairborne(lf, NULL)) {
if (error) { if (error) {
*error = E_AVOIDOB; *error = E_AVOIDOB;
rdata = o; rdata = o;
@ -238,7 +238,7 @@ int celldangerous(lifeform_t *lf, cell_t *cell, int onlyifknown, enum ERROR *err
f = hasflag(o->flags, F_DEEPWATER); f = hasflag(o->flags, F_DEEPWATER);
if (f) { if (f) {
// non swimming creature in water? // non swimming creature in water?
if (!isairborne(lf) && !lfhasflag(lf, F_AQUATIC)) { if (!isairborne(lf, NULL) && !lfhasflag(lf, F_AQUATIC)) {
if ((getobdepth(o, lf) >= DP_HEAD)) { if ((getobdepth(o, lf) >= DP_HEAD)) {
if (getskill(lf, SK_SWIMMING) - isburdened(lf) <= 0) { if (getskill(lf, SK_SWIMMING) - isburdened(lf) <= 0) {
if (error) { if (error) {
@ -925,7 +925,7 @@ int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher, int fallc
msg("%s stagger%s %s but hold%s %s %s.",lfname,isplayer(lf) ? "" : "s", msg("%s stagger%s %s but hold%s %s %s.",lfname,isplayer(lf) ? "" : "s",
getreldirname(getrelativedir(lf, dir)), getreldirname(getrelativedir(lf, dir)),
isplayer(lf) ? "" : "s", isplayer(lf) ? "your" : "its", isplayer(lf) ? "" : "s", isplayer(lf) ? "your" : "its",
isairborne(lf) ? "position" : "ground"); isairborne(lf, NULL) ? "position" : "ground");
} }
return B_TRUE; return B_TRUE;
} }
@ -1404,7 +1404,7 @@ int movelf(lifeform_t *lf, cell_t *newcell, int onpurpose) {
} }
// check ground objects // check ground objects
flying = isairborne(lf); flying = isairborne(lf, NULL);
if (flying == F_NONE) { if (flying == F_NONE) {
for (o = newcell->obpile->first ; o ; o = nexto ) { for (o = newcell->obpile->first ; o ; o = nexto ) {
nexto = o->next; nexto = o->next;
@ -1471,6 +1471,7 @@ int movelf(lifeform_t *lf, cell_t *newcell, int onpurpose) {
if (!lfhasflag(lf, F_CAREFULMOVE)) { if (!lfhasflag(lf, F_CAREFULMOVE)) {
if (cancrush(lf, o)) { if (cancrush(lf, o)) {
int maxhp;
// crush it // crush it
getobname(o, obname, 1); getobname(o, obname, 1);
@ -1495,9 +1496,16 @@ int movelf(lifeform_t *lf, cell_t *newcell, int onpurpose) {
didmsg = B_TRUE; didmsg = B_TRUE;
} }
// kill object which is being crushed. // kill object which is being crushed.
removeob(o, o->amt); //removeob(o, o->amt);
getobhp(o, &maxhp);
if (maxhp) {
takedamage(o, maxhp, DT_CRUSH, lf);
} else {
removeob(o, ALL);
}
if (isplayer(lf)) { if (isplayer(lf)) {
angergodmaybe(R_GODNATURE, 10, GA_ATTACKOBJECT); angergodmaybe(R_GODNATURE, 10, GA_ATTACKOBJECT);
pleasegodmaybe(R_GODFIRE, 2);
} }
continue; continue;
} }
@ -1717,7 +1725,7 @@ int movelf(lifeform_t *lf, cell_t *newcell, int onpurpose) {
for (i = 0; i < nretflags; i++) { for (i = 0; i < nretflags; i++) {
f = retflag[i]; f = retflag[i];
// will we cause damage to ground objects ? // will we cause damage to ground objects ?
if (!isairborne(lf) || (f->val[2] == B_TRUE)) { if (!isairborne(lf, NULL) || (f->val[2] == B_TRUE)) {
damageallobs(NULL, lf->cell->obpile, f->val[0], f->val[1], lf); damageallobs(NULL, lf->cell->obpile, f->val[0], f->val[1], lf);
} }
} }
@ -1859,14 +1867,14 @@ int moveto(lifeform_t *lf, cell_t *newcell, int onpurpose, int dontclearmsg) {
// (stealth check to avoid this) // (stealth check to avoid this)
willmakenoise = B_TRUE; willmakenoise = B_TRUE;
if (lfhasflag(lf, F_HIDING)) { if (lfhasflag(lf, F_HIDING)) {
if (skillcheck(lf, SC_STEALTH, 70, isairborne(lf) ? 25 : 0)) { if (skillcheck(lf, SC_STEALTH, 70, isairborne(lf, NULL) ? 10 : 0)) {
willmakenoise = B_FALSE; willmakenoise = B_FALSE;
} }
} }
// swapping places? // swapping places?
if (willmakenoise) { if (willmakenoise) {
if (isairborne(lf)) { if (isairborne(lf, NULL)) {
makenoise(lf, N_FLY); makenoise(lf, N_FLY);
} else { } else {
makenoise(lf, N_WALK); makenoise(lf, N_WALK);
@ -1874,7 +1882,7 @@ int moveto(lifeform_t *lf, cell_t *newcell, int onpurpose, int dontclearmsg) {
} }
// slip on blood in new cell? // slip on blood in new cell?
if (!isairborne(lf) && !isswimming(lf)) { if (!isairborne(lf, NULL) && !isswimming(lf)) {
int slip; int slip;
object_t *slipob; object_t *slipob;
@ -1892,7 +1900,7 @@ int moveto(lifeform_t *lf, cell_t *newcell, int onpurpose, int dontclearmsg) {
nexto = o->next; nexto = o->next;
f = hasflag(o->flags, F_TRAP); f = hasflag(o->flags, F_TRAP);
if (f) { if (f) {
if (strstr(f->text, "ground") && isairborne(lf)) { if (strstr(f->text, "ground") && isairborne(lf, NULL)) {
// nothing happens // nothing happens
} else { } else {
triggertrap(lf, NULL, o, lf->cell); triggertrap(lf, NULL, o, lf->cell);
@ -1957,7 +1965,7 @@ int move_will_hurt(lifeform_t *lf) {
if (f->id == F_INJURY) { if (f->id == F_INJURY) {
switch (f->val[0]) { switch (f->val[0]) {
case IJ_LEGBLEED: case IJ_LEGBLEED:
if (!isairborne(lf)) return B_TRUE; if (!isairborne(lf, NULL)) return B_TRUE;
break; break;
case IJ_WINGBLEED: case IJ_WINGBLEED:
getflags(lf->flags, retflag2, &nretflags2, F_FLYING, F_NONE); getflags(lf->flags, retflag2, &nretflags2, F_FLYING, F_NONE);
@ -1973,7 +1981,7 @@ int move_will_hurt(lifeform_t *lf) {
} }
} }
if (hasbleedinginjury(lf, BP_LEGS) && !isairborne(lf)) { if (hasbleedinginjury(lf, BP_LEGS) && !isairborne(lf, NULL)) {
return B_TRUE; return B_TRUE;
} }
return B_FALSE; return B_FALSE;
@ -2430,7 +2438,7 @@ int pullnextto(lifeform_t *lf, cell_t *c) {
char buf[BUFLEN]; char buf[BUFLEN];
getlfname(lf, buf); getlfname(lf, buf);
msg("%s %s pulled %s!", buf, is(lf), msg("%s %s pulled %s!", buf, is(lf),
isairborne(lf) ? "through the air" : isairborne(lf, NULL) ? "through the air" :
"along the ground"); "along the ground");
} }
movelf(lf, dst, B_FALSE); movelf(lf, dst, B_FALSE);
@ -2561,7 +2569,7 @@ int initiatemove(lifeform_t *lf, cell_t *cell, int onpurpose, int *didmsg) {
if (o->type->id == OT_WEB) { if (o->type->id == OT_WEB) {
if (isairborne(lf)) { if (isairborne(lf, NULL)) {
checkmod -= 5; checkmod -= 5;
} }
if (lf->race->raceclass->id == RC_INSECT) { if (lf->race->raceclass->id == RC_INSECT) {
@ -2636,7 +2644,7 @@ int initiatemove(lifeform_t *lf, cell_t *cell, int onpurpose, int *didmsg) {
// slipping on something before moving? // slipping on something before moving?
if (!attacking && onpurpose) { if (!attacking && onpurpose) {
if (!isairborne(lf)) { if (!isairborne(lf, NULL)) {
int slip; int slip;
object_t *slipob; object_t *slipob;
@ -2665,7 +2673,7 @@ int initiatemove(lifeform_t *lf, cell_t *cell, int onpurpose, int *didmsg) {
for (o = cell->obpile->first ; o ; o = nexto) { for (o = cell->obpile->first ; o ; o = nexto) {
nexto = o->next; nexto = o->next;
if (!isplayer(lf)) { if (!isplayer(lf)) {
if ((o->blessed == B_CURSED) && (getraceclass(lf) == RC_ANIMAL) && !isairborne(lf)) { if ((o->blessed == B_CURSED) && (getraceclass(lf) == RC_ANIMAL) && !isairborne(lf, NULL)) {
if (cansee(player, lf)) { if (cansee(player, lf)) {
char lfname[BUFLEN]; char lfname[BUFLEN];
getlfname(lf,lfname); getlfname(lf,lfname);

229
objects.c
View File

@ -4162,6 +4162,143 @@ object_t *getbestcontainer(obpile_t *op) {
return poss2[rnd(0,nposs2-1)]; return poss2[rnd(0,nposs2-1)];
} }
// returns TRUE if an break obejct was found.
int getbreakob(object_t *o, char *bigobname, char *smallobname) {
enum MATERIAL mid;
enum DAMTYPE dt;
enum OBTYPE bigoid = OT_NONE,smalloid = OT_NONE;
objecttype_t *big = NULL,*small = NULL;
flag_t *f;
int nsmall = 0,nbig = 0;
double weight;
char bigadj[BUFLEN],smalladj[BUFLEN];
flag_t *retflag[MAXCANDIDATES];
int nretflags = 0,i;
int found = B_FALSE;
mid = o->material->id;
dt = oblastdamtype(o);
// name to return.
strcpy(bigobname, "");
strcpy(smallobname, "");
// flag overrides code below
found = 0;
getflags(o->flags, retflag, &nretflags, F_BREAKOB, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f && (f->val[0] == dt)) {
if (found == 0) {
strcpy(bigobname, f->text);
} else if (found == 1) {
strcpy(smallobname, f->text);
} else {
msg("ERROR - too many F_BREAKOB flags in %s",o->type->name);
dblog("ERROR - too many F_BREAKOB flags in %s",o->type->name);
}
found++;
}
}
if (found) {
return B_TRUE;
}
// adjectives
strcpy(bigadj, "");
strcpy(smalladj, "");
switch (mid) {
case MT_WOOD:
if (ismeleedam(dt) || (dt == DT_EXPLOSIVE)) {
bigoid = OT_WOODPLANK;
smalloid = OT_WOODSHARD;
} else {
switch (dt) {
case DT_FIRE:
case DT_HEAT:
case DT_ACID:
bigoid = OT_ASH;
smalloid = OT_ASH;
break;
default: break;
}
}
break;
case MT_GLASS:
if (ismeleedam(dt) || (dt == DT_EXPLOSIVE)) {
bigoid = OT_BROKENGLASS;
smalloid = OT_BROKENGLASS;
break;
} else {
switch (dt) {
case DT_FIRE:
case DT_HEAT:
case DT_ACID:
bigoid = OT_ASH;
smalloid = OT_ASH;
break;
default: break;
}
}
break;
case MT_ICE:
if (ismeleedam(dt) || (dt == DT_EXPLOSIVE)) {
bigoid = OT_ICECHUNK;
smalloid = OT_ICECHUNK;
break;
} else {
switch (dt) {
case DT_FIRE:
case DT_HEAT:
bigoid = OT_PUDDLEWATERL;
smalloid = OT_PUDDLEWATER;
break;
default: break;
}
}
break;
case MT_FLESH:
switch (dt) {
case DT_FIRE:
bigoid = OT_ASH;
smalloid = OT_ASH;
break;
default: break;
}
break;
default: break;
}
big = findot(bigoid);
small = findot(smalloid);
// now find out how many big obejcts make up the wight.
// NOTE: purposesly not using getobweight() here since
// we don't case about whther it is in water, etc.
weight = getobweight(o);
if (big) {
nbig = weight / big->weight;
weight -= (nbig*big->weight);
}
if (small){
nsmall = weight / small->weight;
weight -= (nsmall*small->weight);
}
if (nbig) {
sprintf(bigobname, "%d %s",nbig,big->name);
}
if (nsmall) {
sprintf(smallobname, "%d %s",nsmall,small->name);
}
if (strlen(bigobname) || strlen(smallobname)) {
return B_TRUE;
}
return B_FALSE;
}
// returns -1 if object doesn't have the flag // returns -1 if object doesn't have the flag
int getchargeinfo(object_t *o, int *cur, int *max) { int getchargeinfo(object_t *o, int *cur, int *max) {
flag_t *f; flag_t *f;
@ -7677,7 +7814,7 @@ int isimpassableob(object_t *o, lifeform_t *lf, enum LFSIZE forcesize) {
if ((lfsize >= blockmin) && (lfsize <= blockmax)) { if ((lfsize >= blockmin) && (lfsize <= blockmax)) {
// exception - if you're flying over it // exception - if you're flying over it
if (getlfheight(lf) >= blockmax) { if (getfeetheight(lf) >= blockmax) {
} else { } else {
return B_TRUE; return B_TRUE;
} }
@ -7735,6 +7872,7 @@ int ismagicalobtype(objecttype_t *ot) {
case OT_SHILLELAGH: case OT_SHILLELAGH:
case OT_WIZARDSTAFF: case OT_WIZARDSTAFF:
case OT_ARMOURTHORN: case OT_ARMOURTHORN:
case OT_PEACEPIPES:
return B_TRUE; return B_TRUE;
default: break; default: break;
} }
@ -8544,6 +8682,14 @@ void makeknownobclass(enum OBCLASS ocid, enum RARITY rrlev) {
} }
} }
void makeopersound(cell_t *c, object_t *o) {
flag_t *df;
df = hasflag(o->flags, F_OPERSOUND);
if (df) {
noise(c, NULL, NC_OTHER, df->val[0], df->text, NULL);
}
}
void maketemporary(object_t *o, int howlong, char *obdietext) { void maketemporary(object_t *o, int howlong, char *obdietext) {
addflag(o->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(o->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
addflag(o->flags, F_OBHP, howlong, howlong, NA, NULL); addflag(o->flags, F_OBHP, howlong, howlong, NA, NULL);
@ -9204,6 +9350,17 @@ void obdie(object_t *o) {
snprintf(bonestr, BUFLEN, "%d-%d bones",minbones,maxbones); snprintf(bonestr, BUFLEN, "%d-%d bones",minbones,maxbones);
addob(o->pile, bonestr); addob(o->pile, bonestr);
} }
} else {
char bigbreak[BUFLEN],smallbreak[BUFLEN];
// maybe create broken object based on material
getbreakob(o, bigbreak, smallbreak);
if (strlen(smallbreak)) {
addob(loc->obpile, smallbreak);
}
if (strlen(bigbreak)) {
addob(loc->obpile, bigbreak);
}
} }
} }
@ -9227,6 +9384,13 @@ void obdie(object_t *o) {
magicwoods_angry(killer); magicwoods_angry(killer);
} }
if (killer && isplayer(killer)) {
if (oblastdamtype(o) == DT_FIRE) {
pleasegodmaybe(R_GODFIRE, 5);
} else {
pleasegodmaybe(R_GODFIRE, 2);
}
}
killob(o); killob(o);
} }
@ -9430,7 +9594,7 @@ flag_t *obrestrictsmovement(object_t *o, lifeform_t *lf) {
if (lf) { if (lf) {
if ((o->type->id == OT_WEB) && (lf->race->baseid == R_SPIDER)) { if ((o->type->id == OT_WEB) && (lf->race->baseid == R_SPIDER)) {
} else if ((o->type->id == OT_VINE) && hasjob(lf, J_DRUID)) { } else if ((o->type->id == OT_VINE) && hasjob(lf, J_DRUID)) {
} else if (isairborne(lf) && (f->val[2] != B_TRUE)) { } else if (isairborne(lf, NULL) && (f->val[2] != B_TRUE)) {
} else { } else {
return f; return f;
} }
@ -10816,8 +10980,30 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
if (isplayer(lf)) { if (isplayer(lf)) {
msg("You play a few notes on your panpipes."); msg("You play a few notes on your panpipes.");
} else { } else {
noise(lf->cell, lf, NC_OTHER, SV_CAR, "the sound of panpipes.", "plays a tune on its panpipes."); char nbuf[BUFLEN];
sprintf(nbuf, "plays a tune on %ss panpipes.", it(lf));
noise(lf->cell, lf, NC_OTHER, SV_SHOUT, "the sound of panpipes.", nbuf);
} }
} else if (o->type->id == OT_PEACEPIPES) {
lifeform_t *l;
if (isplayer(lf)) {
msg("You play an enchanting melody on your panpipes!");
} else {
char nbuf[BUFLEN];
sprintf(nbuf, "plays a calming melody on %ss panpipes.", it(lf));
noise(lf->cell, lf, NC_OTHER, SV_SHOUT, "an eerily calming melody.", nbuf);
}
for (l = lf->cell->map->lf ; l ; l = l->next) {
if (l == lf) continue;
if (iscursed(o)) {
// enrage
enrage(l, DEF_RAGETIME*2);
} else {
// calm
makepeaceful(l, lf);
}
}
makeknown(o->type->id);
} else if (hasflag(o->flags, F_HELPSDIG)) { } else if (hasflag(o->flags, F_HELPSDIG)) {
int ch,dir; int ch,dir;
cell_t *c; cell_t *c;
@ -11873,7 +12059,7 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, object_t *o, enum BLESSTYPE
// remove damaging objects underneath // remove damaging objects underneath
if (killobswithflag(lf->cell->obpile, F_WALKDAM, B_FALSE)) { if (killobswithflag(lf->cell->obpile, F_WALKDAM, B_FALSE)) {
if (haslos(player, lf->cell)) { if (haslos(player, lf->cell)) {
msg("Some nearby objecst disappear!"); msg("Some nearby objects disappear!");
} }
} }
@ -13030,7 +13216,7 @@ int shatter(object_t *o, int hitlf, char *damstring, lifeform_t *fromlf) {
} }
// announce // announce
if (haslos(player, where)) { if (haslos(player, where) && !o->pile->parentob) {
char prefix[BUFLEN]; char prefix[BUFLEN];
if (o->pile->owner) { if (o->pile->owner) {
@ -13049,7 +13235,7 @@ int shatter(object_t *o, int hitlf, char *damstring, lifeform_t *fromlf) {
noise(where, NULL, NC_OTHER, SV_SHOUT, "shattering glass.", NULL); noise(where, NULL, NC_OTHER, SV_SHOUT, "shattering glass.", NULL);
} }
if (target) { if (target && !o->pile->parentob) {
shatterdam = getshatterdam(o); shatterdam = getshatterdam(o);
if (shatterdam && !isdead(target)) { if (shatterdam && !isdead(target)) {
// extra glass damage // extra glass damage
@ -13067,7 +13253,7 @@ int shatter(object_t *o, int hitlf, char *damstring, lifeform_t *fromlf) {
numshards = getnumshards(o); numshards = getnumshards(o);
// place glass shards // place glass shards
snprintf(buf, BUFLEN, "%d pieces of broken glass",numshards); snprintf(buf, BUFLEN, "%d pieces of broken glass",numshards);
addob(where->obpile, buf); addob(o->pile, buf);
} else if (o->material->id == MT_ICE) { } else if (o->material->id == MT_ICE) {
int numshards; int numshards;
numshards = getnumshards(o) / 15; numshards = getnumshards(o) / 15;
@ -13075,7 +13261,7 @@ int shatter(object_t *o, int hitlf, char *damstring, lifeform_t *fromlf) {
// ice // ice
snprintf(buf, BUFLEN, "%d chunks of ice",numshards); snprintf(buf, BUFLEN, "%d chunks of ice",numshards);
addob(where->obpile, buf); addob(o->pile, buf);
} }
// potion effects (only if you hit)? // potion effects (only if you hit)?
@ -13197,7 +13383,7 @@ int shatter(object_t *o, int hitlf, char *damstring, lifeform_t *fromlf) {
} }
//TODO: holy water blesses everything? //TODO: holy water blesses everything?
// everything here takes water damage // everything here takes water damage
for (oo = where->obpile->first ; oo ; oo = nextoo) { for (oo = o->pile->first ; oo ; oo = nextoo) {
nextoo = oo->next; nextoo = oo->next;
takedamage(oo, 0, DT_WATER, fromlf); takedamage(oo, 0, DT_WATER, fromlf);
} }
@ -13641,22 +13827,6 @@ int real_takedamage(object_t *o, int howmuch, int damtype, int wantannounce, lif
meat->weight = o->weight; meat->weight = o->weight;
copyflag(meat->flags, o->flags, F_CORPSEOF); copyflag(meat->flags, o->flags, F_CORPSEOF);
} }
// fire turns things to ash
addob(o->pile, "pile of ash");
} else if (damtype == DT_BASH) {
if (o->material->id == MT_GLASS) { // bashing damage breaks glass
int nshards;
char buf[BUFLEN];
nshards = getnumshards(o);
snprintf(buf, BUFLEN, "%d pieces of broken glass", nshards);
addob(o->pile, buf);
} else if (o->material->id == MT_ICE) { // bashing breaks ice
int nshards;
char buf[BUFLEN];
nshards = getnumshards(o) / 15;
snprintf(buf, BUFLEN, "%d chunks of ice", nshards);
addob(o->pile, buf);
}
} }
// object dies! // object dies!
@ -14445,7 +14615,7 @@ int real_fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int sp
// will the missile trip them over? // will the missile trip them over?
f = hasflag(o->flags, F_TANGLEMISSILE); f = hasflag(o->flags, F_TANGLEMISSILE);
if (f) { if (f) {
if (isairborne(target) || !skillcheck(target, SC_SLIP, f->val[0], 0)) { if (isairborne(target, NULL) || !skillcheck(target, SC_SLIP, f->val[0], 0)) {
willtangle = B_TRUE; willtangle = B_TRUE;
} }
} }
@ -14587,6 +14757,7 @@ int real_fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int sp
shatter(newob, youhit, dambuf, thrower); shatter(newob, youhit, dambuf, thrower);
if (thrower && isplayer(thrower)) { if (thrower && isplayer(thrower)) {
angergodmaybe(R_GODNATURE, 10, GA_ATTACKOBJECT); angergodmaybe(R_GODNATURE, 10, GA_ATTACKOBJECT);
pleasegodmaybe(R_GODFIRE, 1);
} }
} else if (hasflag(newob->flags, F_MISSILEALWAYSDIES)) { } else if (hasflag(newob->flags, F_MISSILEALWAYSDIES)) {
killob(newob); killob(newob);
@ -15207,9 +15378,11 @@ void timeeffectsob(object_t *o) {
} else { } else {
damtype = f->val[1]; damtype = f->val[1];
} }
// special case - corpses don't decay when on ice // special case - corpses don't decay when on ice or on fire.
if (o->type->id == OT_CORPSE) { if (o->type->id == OT_CORPSE) {
if (hasobofmaterial(o->pile, MT_ICE)) { if (hasflag(o->flags, F_ONFIRE)) {
doit = B_FALSE;
} else if (hasobofmaterial(o->pile, MT_ICE)) {
doit = B_FALSE; doit = B_FALSE;
} }
} }

View File

@ -72,6 +72,7 @@ void genhiddennames(void);
enum LFSIZE getarmoursize(object_t *o); enum LFSIZE getarmoursize(object_t *o);
enum RARITY getavgrarity(flagpile_t *fp); enum RARITY getavgrarity(flagpile_t *fp);
object_t *getbestcontainer(obpile_t *op); object_t *getbestcontainer(obpile_t *op);
int getbreakob(object_t *o, char *bigobname, char *smallobname);
int getchargeinfo(object_t *o, int *cur, int *max); int getchargeinfo(object_t *o, int *cur, int *max);
int getcharges(object_t *o); int getcharges(object_t *o);
enum SKILL getclassloreskill(enum OBCLASS oc); enum SKILL getclassloreskill(enum OBCLASS oc);
@ -247,6 +248,7 @@ int makeduller(object_t *o, int howmuch);
void makehot(object_t *o, int howmuch, int howlong); void makehot(object_t *o, int howmuch, int howlong);
void makeknown(enum OBTYPE otid); void makeknown(enum OBTYPE otid);
void makeknownobclass(enum OBCLASS ocid, enum RARITY rrlev); void makeknownobclass(enum OBCLASS ocid, enum RARITY rrlev);
void makeopersound(cell_t *c, object_t *o);
void maketemporary(object_t *o, int howlong, char *obdietext); void maketemporary(object_t *o, int howlong, char *obdietext);
void maketried(enum OBTYPE otid, char *triedon); void maketried(enum OBTYPE otid, char *triedon);
void makewet(object_t *o, int amt); void makewet(object_t *o, int amt);

174
spell.c
View File

@ -131,7 +131,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
} else if (isstuck(user)) { } else if (isstuck(user)) {
if (isplayer(user)) msg("You can't build anything while stuck!"); if (isplayer(user)) msg("You can't build anything while stuck!");
return B_TRUE; return B_TRUE;
} else if (isairborne(user)) { } else if (isairborne(user, NULL)) {
if (isplayer(user)) msg("You can't build anything while airborne!"); if (isplayer(user)) msg("You can't build anything while airborne!");
return B_TRUE; return B_TRUE;
} }
@ -1214,7 +1214,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
msg("There is nothing to dismantle there."); msg("There is nothing to dismantle there.");
return B_TRUE; return B_TRUE;
} else if (!o) { } else if (!o) {
if (slev >= PR_SKILLED) { if (slev >= PR_ADEPT) {
// you can dismantle doors too... // you can dismantle doors too...
o = hasdoor(c); o = hasdoor(c);
} }
@ -1258,6 +1258,36 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
addflag(target->flags, F_NODEATHANNOUNCE, B_TRUE, NA, NA, NULL); addflag(target->flags, F_NODEATHANNOUNCE, B_TRUE, NA, NA, NULL);
target->hp = 0; target->hp = 0;
killallobs(target->pack); killallobs(target->pack);
} else if (abilid == OT_A_FLY) {
flag_t *retflag[MAXCANDIDATES],*f;
int nretflags,i;
// already flying? stop.
getflags(user->flags, retflag, &nretflags, F_FLYING, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->lifetime == FROMABIL) {
killflag(f);
taketime(user, getactspeed(user));
return B_FALSE;
}
}
if (isimmobile(user)) {
if (isplayer(user)) msg("You can't move!");
return B_TRUE;
} else if (isstuck(user)) {
if (isplayer(user)) msg("You can't start flying while stuck!");
return B_TRUE;
} else if (isburdened(user)) {
if (isplayer(user)) msg("You can't flying while burdened!");
return B_TRUE;
}
// start flying
addtempflag(user->flags, F_FLYING, getnaturalflightheight(user), NA, NA, NULL, FROMABIL);
taketime(user, getactspeed(user));
} else if (abilid == OT_A_FEIGNDEATH) { } else if (abilid == OT_A_FEIGNDEATH) {
lifeform_t *lf; lifeform_t *lf;
if (hasflag(user->flags, F_FEIGNINGDEATH)) { if (hasflag(user->flags, F_FEIGNINGDEATH)) {
@ -1580,7 +1610,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
if (isswimming(user) && !lfhasflag(user, F_AQUATIC)) { if (isswimming(user) && !lfhasflag(user, F_AQUATIC)) {
if (isplayer(user)) msg("You can't jump while swimming!"); if (isplayer(user)) msg("You can't jump while swimming!");
return B_TRUE; return B_TRUE;
} else if (isairborne(user)) { } else if (isairborne(user, NULL)) {
if (isplayer(user)) msg("You can't jump while airbourne!"); if (isplayer(user)) msg("You can't jump while airbourne!");
return B_TRUE; return B_TRUE;
} else if (hasflag(user->flags, F_GRAVBOOSTED)) { } else if (hasflag(user->flags, F_GRAVBOOSTED)) {
@ -2174,7 +2204,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
return B_TRUE; return B_TRUE;
} }
if (isairborne(user)) { if (isairborne(user, NULL)) {
if (isplayer(user)) msg("You can't sprint while airborne!"); if (isplayer(user)) msg("You can't sprint while airborne!");
return B_TRUE; return B_TRUE;
} }
@ -2707,7 +2737,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
if (isplayer(user)) msg("There is nobody there to trip!"); if (isplayer(user)) msg("There is nobody there to trip!");
return B_TRUE; return B_TRUE;
} }
if (isairborne(target)) { if (isairborne(target, NULL)) {
if (isplayer(user)) msg("You can't trip someone in the air!"); if (isplayer(user)) msg("You can't trip someone in the air!");
return B_TRUE; return B_TRUE;
} }
@ -2757,7 +2787,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
if (isswimming(user) && !lfhasflag(user, F_AQUATIC)) { if (isswimming(user) && !lfhasflag(user, F_AQUATIC)) {
if (isplayer(user)) msg("You can't tumble while swimming!"); if (isplayer(user)) msg("You can't tumble while swimming!");
return B_TRUE; return B_TRUE;
} else if (isairborne(user)) { } else if (isairborne(user, NULL)) {
if (isplayer(user)) msg("You can't tumble while airbourne!"); if (isplayer(user)) msg("You can't tumble while airbourne!");
return B_TRUE; return B_TRUE;
} else if (lfhasflag(user, F_GRABBING)) { } else if (lfhasflag(user, F_GRABBING)) {
@ -6164,7 +6194,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (cansee(player, c2->lf)) { if (cansee(player, c2->lf)) {
char lfname[BUFLEN]; char lfname[BUFLEN];
getlfname(c2->lf, lfname); getlfname(c2->lf, lfname);
msg("%s %s showered with debris!", lfname, isplayer(c2->lf) ? "are" : "is"); msg("^%c%s %s showered with debris!",
getlfcol(c2->lf, CC_BAD),
lfname, isplayer(c2->lf) ? "are" : "is");
} }
losehp(c2->lf, dam, DT_PROJECTILE, NULL, "flying debris"); losehp(c2->lf, dam, DT_PROJECTILE, NULL, "flying debris");
} }
@ -7428,131 +7460,27 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
} else if (spellid == OT_S_FLIGHT) { } else if (spellid == OT_S_FLIGHT) {
flag_t *f; flag_t *f;
int height;
// always targetted at caster // always targetted at caster
targcell = caster->cell; targcell = caster->cell;
target = caster; target = caster;
f = addtempflag(caster->flags, F_FLYING, B_TRUE, NA, NA, NULL, FROMSPELL); height = (power/2)+1;
limit(&height, SZ_MEDIUM, NA);
f = addtempflag(caster->flags, F_FLYING, height, NA, NA, NULL, FROMSPELL);
f->obfrom = spellid; f->obfrom = spellid;
} else if (spellid == OT_S_FREEZEOB) { } else if (spellid == OT_S_FREEZEOB) {
object_t *o; if (lfhasflag(caster, F_FREEZINGTOUCH)) {
if (targob) {
o = targob;
} else {
// rings?
o = hasobwithflagval(caster->pack, F_EQUIPPED, BP_RIGHTFINGER, NA, NA, NULL);
if (!o) o = hasobwithflagval(caster->pack, F_EQUIPPED, BP_LEFTFINGER, NA, NA, NULL);
// gloves?
if (!o) o = hasobwithflagval(caster->pack, F_EQUIPPED, BP_HANDS, NA, NA, NULL);
// weapon?
if (!o) o = hasobwithflagval(caster->pack, F_EQUIPPED, BP_WEAPON, NA, NA, NULL);
if (o) {
// at high power, warn...
if (isplayer(caster) && (power > 5)) {
char obname[BUFLEN];
char ch;
getobname(o, obname, o->amt);
msg("%s %s start%s glowing bright blue!",
(o->pile->owner == caster) ? "Your" : "",
(o->pile->owner == caster) ? noprefix(obname) : obname,
OBS1(o));
more();
ch = askchar("Abort your spell?", "yn","y", B_TRUE, B_FALSE);
if (ch == 'y') {
msg("You release your spell into the air.");
return B_FALSE;
}
}
} else {
// next thing touched
addflag(caster->flags, F_FREEZINGTOUCH, 1, power, 10+power, NULL);
if (isplayer(caster)) {
msg("Your hands begin to glow blue!");
if (seenbyplayer) *seenbyplayer = B_TRUE;
} else if (cansee(player, caster)) {
getlfname(caster, buf);
msg("%s's hands begin to glow blue!", buf);
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
return B_FALSE;
}
}
if (!o) {
if (isplayer(caster)) {
msg("Your hands feel freezing cold for a moment.");
}
fizzle(caster); fizzle(caster);
return B_TRUE; return B_TRUE;
} }
if (isplayer(caster) || cansee(player, caster)) {
// object will turn to ice immediately... if (seenbyplayer) *seenbyplayer = B_TRUE;
if (o->material->id == MT_ICE) { // already made of ice?
cell_t *loc;
flag_t *f;
loc = getoblocation(o);
// announce
if (haslos(player, loc)) {
char obname[BUFLEN];
getobname(o, obname, o->amt);
msg("%s %s freeze%s some more.",
(o->pile->owner == caster) ? "Your" : "",
(o->pile->owner == caster) ? noprefix(obname) : obname,
OBS1(o));
}
// restore it
f = hasflag(o->flags, F_OBHP);
if (f) {
f->val[0] = f->val[1];
}
return B_TRUE;
} 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) {
if (isplayer(o->pile->owner)) {
msg("Your %s glows blue for a moment.",noprefix(buf));
if (seenbyplayer) *seenbyplayer = B_TRUE;
} else if (haslos(player, o->pile->owner->cell)) {
char buf2[BUFLEN];
getlfname(o->pile->owner, buf2);
msg("%s%s %s glows blue for a moment.", noprefix(buf2),getpossessive(buf2), buf);
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
} else if (haslos(player, o->pile->where)) {
msg("%s glows blue for a moment.", buf);
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
} else {
if (isplayer(caster)) {
nothinghappens();
}
}
return B_TRUE;
} else {
if (o->pile->owner) {
if (isplayer(o->pile->owner)) {
msg("Your %s turn%s to ice!",noprefix(buf), OBS1(o));
if (seenbyplayer) *seenbyplayer = B_TRUE;
} else if (haslos(player, o->pile->owner->cell)) {
getlfname(o->pile->owner, buf);
msg("A small cloud of vapour rises up from %s.", buf);
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
} else if (haslos(player, o->pile->where)) {
msg("%s turns to ice!", buf);
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
}
} }
// next thing touched
addflag(caster->flags, F_FREEZINGTOUCH, 1, power, 10+power, NULL);
return B_FALSE;
} else if (spellid == OT_S_FROSTBITE) { } else if (spellid == OT_S_FROSTBITE) {
char lfname[BUFLEN]; char lfname[BUFLEN];
int exposedlimbs,dam; int exposedlimbs,dam;
@ -14737,7 +14665,7 @@ void pullobto(object_t *o, lifeform_t *lf) {
} }
// can we pick up the object? // can we pick up the object?
if (hasflag(o->flags, F_NOPICKUP) || hasflag(o->flags, F_IMPASSABLE) || !canpickup(lf, o, ALL)) { if (hasflag(o->flags, F_NOPICKUP) || isimpassableob(o, lf, getlfsize(lf)) || !canpickup(lf, o, ALL)) {
char buf[BUFLEN]; char buf[BUFLEN];
int dir; int dir;
cell_t *obloc,*newcell; cell_t *obloc,*newcell;

4
text.c
View File

@ -1191,6 +1191,10 @@ char *getflagsourcetext(flag_t *f) {
return " (god gift)"; return " (god gift)";
case FROMGODPIETY: case FROMGODPIETY:
return " (piety bonus)"; return " (piety bonus)";
case FROMSPELL:
return " (from spell)";
case FROMABIL:
return " (from ability)";
default: break; default: break;
} }
return ""; return "";