- [+] better body part handling

- [+] bodypart_t[MAXBODYPARTS]
        - [+] enum BODYPART id
        - [+] char *name
    - [+] add defs to all races
    - [+] fix quadrapeds - not all have tails!
    - [+] remove f_bodypartname - use addbodypart instead
    - [+] update hasbp
    - [+] remove  occurences of F_NOBODYPART in races
    - [+] fix up getrandombodypart functions
        - [+] getrandomonbodypart
        - [+] getcrithitpos
        - [+] copy with null returns
    - [+] check all occurences of MAXBODYPARTS, change to "for each
          bodypart of this lf/race"
    - [+] show nobodypart differently in io.c 
    - [+] criticals:  hindlegs / frontlegs -> legs
    - [+] makeunusual shaped be part of the body part. then remove 
          F_NOARMOURON
- [+] critical hits on new body parts
    - [+] wing crits
        - [+] bash - wings are bruised - reduced flight speed
        - [+] slash
            - [+] - wings are torn - can't fly. implement in cancast.
            - [+] bleeding - flying hurts
        - [+] explosive
            - [+] destroyed - can't fly!
    - [+] tail crits
        - [+] slash
            - [+] bleeding
        - [+] bash
            - [+] bruised - accuracy lowered
            - [+] fractured - randomly move the wrong way like
                  drunkenness
        - [+] explosive
            - [+] lacerated - randomly fall like hamstrung
- [+] don't prompt for moving into dangerous cells f moving randomly
      due to drunkenness etc
- [+] bug: double criticals?
    - [+] You flatten the kobold!  The kobold loses consciousness.
          The kobold's hand is swollen!  The kobold's leg is broken!
- [+] all f_flying races should have f_canwill ot_s_fly with no
      spellcasttext
This commit is contained in:
Rob Pearce 2011-11-22 21:32:10 +00:00
parent c596623603
commit c9fcd90a2c
10 changed files with 706 additions and 555 deletions

11
ai.c
View File

@ -1098,9 +1098,11 @@ void aiturn(lifeform_t *lf) {
// flying monsters not flying? // flying monsters not flying?
if (!isprone(lf)) { if (!isprone(lf)) {
if (hasflag(lf->race->flags, F_FLYING) && !lfhasflag(lf, F_FLYING)) { if (hasflag(lf->race->flags, F_FLYING) && !lfhasflag(lf, F_FLYING)) {
copyflag(lf->flags, lf->race->flags, F_FLYING); if (cancast(lf, OT_S_FLIGHT, NULL)) {
taketime(lf, getmovespeed(lf)); if (!castspell(lf, OT_S_FLIGHT, lf, NULL, lf->cell, NULL, NULL)) {
return; return;
}
}
} }
if (hasflag(lf->race->flags, F_LEVITATING) && !lfhasflag(lf, F_LEVITATING)) { if (hasflag(lf->race->flags, F_LEVITATING) && !lfhasflag(lf, F_LEVITATING)) {
copyflag(lf->flags, lf->race->flags, F_LEVITATING); copyflag(lf->flags, lf->race->flags, F_LEVITATING);
@ -1321,8 +1323,9 @@ void aiturn(lifeform_t *lf) {
} }
// do we have better armour? // do we have better armour?
for (bp = BP_RIGHTFINGER ; bp < MAXBODYPARTS; bp++) { for (i = 0; i < lf->race->nbodyparts; i++) {
object_t *curarm; object_t *curarm;
bp = lf->race->bodypart[i].id;
curarm = getarmour(lf, bp); curarm = getarmour(lf, bp);
// do we have a better one? // do we have a better one?
for (o = lf->pack->first ; o ; o = o->next) { for (o = lf->pack->first ; o ; o = o->next) {

View File

@ -645,20 +645,22 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
object_t *armour; object_t *armour;
char noun[BUFLEN]; char noun[BUFLEN];
critpos = getrandomcorebp(victim); critpos = getrandomcorebp(victim);
armour = getequippedob(victim->pack, critpos); if (critpos != BP_NONE) {
if (armour) { armour = getequippedob(victim->pack, critpos);
char armname[BUFLEN]; if (armour) {
real_getobname(armour, armname, 1, B_FALSE, B_FALSE, B_TRUE, B_FALSE, B_FALSE); char armname[BUFLEN];
sprintf(noun, "%s", noprefix(armname)); real_getobname(armour, armname, 1, B_FALSE, B_FALSE, B_TRUE, B_FALSE, B_FALSE);
} else { sprintf(noun, "%s", noprefix(armname));
sprintf(noun, "%s", getbodypartname(victim, critpos)); } else {
} sprintf(noun, "%s", getbodypartname(victim, critpos));
// replace victicname to include body part }
if ((lf == victim) && !isplayer(lf)) { // replace victicname to include body part
snprintf(victimbpname, BUFLEN, "its %s", noun); if ((lf == victim) && !isplayer(lf)) {
} else { snprintf(victimbpname, BUFLEN, "its %s", noun);
getlfname(victim, buf); } else {
snprintf(victimbpname, BUFLEN, "%s%s %s", buf, getpossessive(buf), noun); getlfname(victim, buf);
snprintf(victimbpname, BUFLEN, "%s%s %s", buf, getpossessive(buf), noun);
}
} }
} else { } else {
strcpy(victimbpname, ""); strcpy(victimbpname, "");
@ -1421,6 +1423,9 @@ void criticalhit(lifeform_t *lf, lifeform_t *victim, enum BODYPART hitpos, int d
object_t *o,*armour; object_t *o,*armour;
int protected = B_FALSE; int protected = B_FALSE;
char lfname[BUFLEN],victimname[BUFLEN]; char lfname[BUFLEN],victimname[BUFLEN];
if (hitpos == BP_NONE) return;
// replace some dam types // replace some dam types
if (damtype == DT_UNARMED) damtype = DT_BASH; if (damtype == DT_UNARMED) damtype = DT_BASH;
if (damtype == DT_BITE) damtype = DT_SLASH; if (damtype == DT_BITE) damtype = DT_SLASH;

754
data.c

File diff suppressed because it is too large Load Diff

64
defs.h
View File

@ -1741,21 +1741,27 @@ enum OBTYPE {
#define BP_NONE (-1) #define BP_NONE (-1)
enum BODYPART { enum BODYPART {
// humanoid parts
BP_WEAPON = 0, BP_WEAPON = 0,
BP_SECWEAPON, BP_SECWEAPON = 1,
BP_EARS, BP_EARS = 2,
BP_EYES, BP_EYES = 3,
BP_HEAD, BP_HEAD = 4,
BP_SHOULDERS, BP_SHOULDERS = 5,
BP_BODY, BP_BODY = 6,
BP_HANDS, BP_HANDS = 7,
BP_WAIST, BP_WAIST = 8,
BP_LEGS, BP_LEGS = 9,
BP_FEET, BP_FEET = 10,
BP_RIGHTFINGER, BP_RIGHTFINGER = 11,
BP_LEFTFINGER, BP_LEFTFINGER = 12,
// others...
BP_BACKLEGS = 13,
BP_FRONTLEGS = 14,
BP_WINGS = 15,
BP_TAIL = 16,
}; };
#define MAXBODYPARTS (13) #define MAXBODYPARTS (17)
// depth on a human // depth on a human
@ -2464,7 +2470,7 @@ enum FLAG {
F_SPELLCASTTEXT, // text is announcement for spellcast F_SPELLCASTTEXT, // text is announcement for spellcast
// if text is empty, then don't announce // if text is empty, then don't announce
// this lf's spell casting at all. // this lf's spell casting at all.
// if v0 is set, only use text for spellid v0 // if v0 != OT_NONE, only use text for spellid v0
// if v2 is 'appendyou' " at xxx" will // if v2 is 'appendyou' " at xxx" will
// be appended. // be appended.
F_NODEATHANNOUNCE, // don't say 'the xx dies' if this lf dies F_NODEATHANNOUNCE, // don't say 'the xx dies' if this lf dies
@ -2517,16 +2523,12 @@ enum FLAG {
F_DOESNTMOVE, // this race doesn't move (but can still attack) F_DOESNTMOVE, // this race doesn't move (but can still attack)
F_AQUATIC, // this race can attack normally in water and suffers no F_AQUATIC, // this race can attack normally in water and suffers no
// movement penalties // movement penalties
F_BODYPARTNAME, // for this race, bodypart v0 is called 'text'
F_AVIAN, // this race is an avian F_AVIAN, // this race is an avian
F_CANINE, // this race is a canine F_CANINE, // this race is a canine
F_HUMANOID, // this race can wear armour / use weapons F_HUMANOID, // this race can wear armour / use weapons
F_INSECT, // this race is classed as an insect F_INSECT, // this race is classed as an insect
F_UNDEAD, // this race is classed as undead F_UNDEAD, // this race is classed as undead
F_COLDBLOOD, // this race is coldblooded F_COLDBLOOD, // this race is coldblooded
F_NOARMOURON, // this race can't wear armour on bodypart v0
// obviously doesn't make sense to have both this
// and f_nobodypart for the same body part.
F_NOBODYPART, // this race doesn't have bodypart val0 F_NOBODYPART, // this race doesn't have bodypart val0
// if v0 is true or b_frominjury, you can regrow it // if v0 is true or b_frominjury, you can regrow it
// via a healing potion. // via a healing potion.
@ -2820,10 +2822,13 @@ enum INJURY {
IJ_RIBBROKEN, // can be from explosive too IJ_RIBBROKEN, // can be from explosive too
IJ_RIBCRACKED, // can be from explosive too IJ_RIBCRACKED, // can be from explosive too
IJ_SHOULDERDISLOCATED, IJ_SHOULDERDISLOCATED,
IJ_TAILBRUISED,
IJ_TAILBROKEN,
IJ_TORSOBRUISED, IJ_TORSOBRUISED,
IJ_TORSOBRUISEDBAD, IJ_TORSOBRUISEDBAD,
IJ_WINDED, IJ_WINDED,
IJ_WINDPIPECRUSHED, IJ_WINDPIPECRUSHED,
IJ_WINGBRUISED,
// slashing // slashing
IJ_ARTERYPIERCE, IJ_ARTERYPIERCE,
IJ_CHESTBLEED, IJ_CHESTBLEED,
@ -2834,10 +2839,15 @@ enum INJURY {
IJ_FINGERMISSING, IJ_FINGERMISSING,
IJ_EYELIDSCRAPED, IJ_EYELIDSCRAPED,
IJ_EYEDESTROYED, IJ_EYEDESTROYED,
IJ_TAILBLEED,
IJ_WINGBLEED,
IJ_WINGTORN,
// explosive // explosive
IJ_EARSRINGING, IJ_EARSRINGING,
IJ_HANDMISSING, IJ_HANDMISSING,
IJ_LUNGCOLLAPSED, IJ_LUNGCOLLAPSED,
IJ_TAILLACERATED,
IJ_WINGDESTROYED,
}; };
@ -3002,6 +3012,21 @@ typedef struct coord_s {
int x,y; int x,y;
} coord_t; } coord_t;
enum BODYTYPE {
BT_BIRD,
BT_FISH,
BT_HUMANOID,
BT_QUADRAPED,
BT_SNAKE,
BT_SPIDER,
};
typedef struct bodypart_s {
enum BODYPART id;
char *name;
int armourok;
} bodypart_t;
// command types // command types
typedef struct command_s { typedef struct command_s {
enum COMMAND id; enum COMMAND id;
@ -3246,6 +3271,9 @@ typedef struct race_s {
struct glyph_s glyph; struct glyph_s glyph;
float weight; float weight;
struct flagpile_s *flags; struct flagpile_s *flags;
struct bodypart_s bodypart[MAXBODYPARTS];
int nbodyparts;
// speed modifiers // speed modifiers
// hit dice // hit dice
struct race_s *next, *prev; struct race_s *next, *prev;

64
io.c
View File

@ -31,6 +31,8 @@ WINDOW *statwin;
int statdirty = B_TRUE; int statdirty = B_TRUE;
int inaskcoords = B_FALSE; // are we inside this function?
int hascolour = B_TRUE; int hascolour = B_TRUE;
int noredraw = B_FALSE; int noredraw = B_FALSE;
@ -546,6 +548,11 @@ cell_t *askcoords(char *prompt, char *subprompt, int targettype, lifeform_t *src
int nretflags; int nretflags;
flag_t *retflag[MAXCANDIDATES]; flag_t *retflag[MAXCANDIDATES];
// rememebr that we're in this function. the main use for this is to ensure
// that when adding a fake corpse for lfs who are feigning death, that we don't
// do a screen update (due to adding an object in sight of the player)
inaskcoords = B_TRUE;
iqb = getattrbracket(getattr(player, A_IQ), A_IQ, NULL); iqb = getattrbracket(getattr(player, A_IQ), A_IQ, NULL);
// remember previously targetted lifeforms // remember previously targetted lifeforms
@ -1027,19 +1034,27 @@ cell_t *askcoords(char *prompt, char *subprompt, int targettype, lifeform_t *src
startlf = c->lf->id; startlf = c->lf->id;
} }
restoregamewindows(); restoregamewindows();
inaskcoords = B_FALSE;
return c; return c;
} else if (ch == 'v') { // view } else if (ch == 'v') { // view
// todo: show obpile or view lf // todo: show obpile or view lf
if (c->lf && cansee(player, c->lf)) { if (c->lf && cansee(player, c->lf) && (isplayer(c->lf) || !lfhasflag(c->lf, F_FEIGNINGDEATH))) {
showlfstats(c->lf, B_FALSE); showlfstats(c->lf, B_FALSE);
} else if (haslos(player, c)) { } else if (haslos(player, c)) {
object_t *o; object_t *o,*tempob = NULL;
// lf feigning death here? put down a fake corpse.
if (c->lf && lfhasflag(c->lf, F_FEIGNINGDEATH) && !isplayer(c->lf)) {
char obname[BUFLEN];
sprintf(obname, "%s corpse", c->lf->race->name);
tempob = addob(c->obpile, obname);
}
// show objects // show objects
o = doaskobject(c->obpile, "Describe which object", NULL, B_FALSE, B_FALSE, '\0', AO_NONE, F_NONE); o = doaskobject(c->obpile, "Describe which object", NULL, B_FALSE, B_FALSE, '\0', AO_NONE, F_NONE);
while (o) { while (o) {
describeob(o); describeob(o);
o = doaskobject(c->obpile, "Describe which object", NULL, B_FALSE, B_FALSE, '\0', AO_NONE, F_NONE); o = doaskobject(c->obpile, "Describe which object", NULL, B_FALSE, B_FALSE, '\0', AO_NONE, F_NONE);
} }
if (tempob) killob(tempob);
} }
} else if (ch == 27) { // esc - cancel } else if (ch == 27) { // esc - cancel
finished = B_TRUE; finished = B_TRUE;
@ -1062,6 +1077,8 @@ cell_t *askcoords(char *prompt, char *subprompt, int targettype, lifeform_t *src
} }
} }
inaskcoords = B_FALSE;
clearmsg(); clearmsg();
restoregamewindows(); restoregamewindows();
return NULL; return NULL;
@ -9031,7 +9048,7 @@ void showlfarmour(lifeform_t *lf) {
// default // default
strcpy(rhs, ""); strcpy(rhs, "");
if (!lfhasflagval(lf, F_NOBODYPART, bp, NA, NA, NULL)) { if (hasbp(lf, bp)) {
object_t *outerob; object_t *outerob;
snprintf(buf, BUFLEN, "%13s:%1s",getbodypartname(lf, bp), " "); snprintf(buf, BUFLEN, "%13s:%1s",getbodypartname(lf, bp), " ");
o = getequippedob(lf->pack, bp); o = getequippedob(lf->pack, bp);
@ -9908,29 +9925,29 @@ void showlfstats(lifeform_t *lf, int showall) {
} }
nmissingbp = 0; nmissingbp = 0;
for (bp = BP_WEAPON; bp < MAXBODYPARTS; bp++) { getflags(lf->flags, retflag, &nretflags, F_NOBODYPART, F_NONE);
if (lfhasflagval(lf, F_NOBODYPART, bp, NA, NA, NULL)) { for (i = 0; i < nretflags; i++) {
if (bp == BP_RIGHTFINGER) { bp = retflag[i]->val[0];
if (!lfhasflagval(lf, F_NOBODYPART, BP_HANDS, NA, NA, NULL)) { if (bp == BP_RIGHTFINGER) {
missingbp[nmissingbp] = bp; if (!lfhasflagval(lf, F_NOBODYPART, BP_HANDS, NA, NA, NULL)) {
nmissingbp++;
}
} else if (bp == BP_LEFTFINGER) {
if (!lfhasflagval(lf, F_NOBODYPART, BP_HANDS, NA, NA, NULL) &&
!lfhasflagval(lf, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL)
) {
missingbp[nmissingbp] = bp;
nmissingbp++;
}
} else if (bp == BP_SECWEAPON) {
if (!lfhasflagval(lf, F_NOBODYPART, BP_HANDS, NA, NA, NULL)) {
missingbp[nmissingbp] = bp;
nmissingbp++;
}
} else {
missingbp[nmissingbp] = bp; missingbp[nmissingbp] = bp;
nmissingbp++; nmissingbp++;
} }
} else if (bp == BP_LEFTFINGER) {
if (!lfhasflagval(lf, F_NOBODYPART, BP_HANDS, NA, NA, NULL) &&
!lfhasflagval(lf, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL)
) {
missingbp[nmissingbp] = bp;
nmissingbp++;
}
} else if (bp == BP_SECWEAPON) {
if (!lfhasflagval(lf, F_NOBODYPART, BP_HANDS, NA, NA, NULL)) {
missingbp[nmissingbp] = bp;
nmissingbp++;
}
} else {
missingbp[nmissingbp] = bp;
nmissingbp++;
} }
} }
@ -9986,7 +10003,6 @@ void showlfstats(lifeform_t *lf, int showall) {
mt = findmaterial(getlfmaterial(lf)); mt = findmaterial(getlfmaterial(lf));
wrapprint(mainwin, &y, &x, "%s %s made out of %s. ",you(lf), is(lf), mt->name); wrapprint(mainwin, &y, &x, "%s %s made out of %s. ",you(lf), is(lf), mt->name);
} }
} else if (mode == 'a') { } else if (mode == 'a') {
centre(mainwin, C_WHITE, 0, "ABILITIES"); centre(mainwin, C_WHITE, 0, "ABILITIES");
y = 2; y = 2;

281
lf.c
View File

@ -217,6 +217,17 @@ int bleedfrom(lifeform_t *lf, enum BODYPART bp, int splatter) {
return B_TRUE; return B_TRUE;
} }
int bpcantakearmour(lifeform_t *lf, enum BODYPART bp) {
int i;
// unnaturally shaped limbs?
for (i = 0; i < lf->race->nbodyparts; i++) {
if ((lf->race->bodypart[i].id == bp) && !lf->race->bodypart[i].armourok) {
return B_FALSE;
}
}
return B_TRUE;
}
void breakgrabs(lifeform_t *lf, int fromme, int tome) { void breakgrabs(lifeform_t *lf, int fromme, int tome) {
flag_t *f; flag_t *f;
lifeform_t *alf; lifeform_t *alf;
@ -547,6 +558,17 @@ int cancast(lifeform_t *lf, enum OBTYPE oid, int *mpcost) {
if (f) { if (f) {
int needgrab = B_FALSE; int needgrab = B_FALSE;
// flying with broken/destroyed wings?
if ((oid == OT_S_FLIGHT) && (f->lifetime == FROMRACE)) {
if (lfhasflagval(lf, F_INJURY, IJ_WINGTORN, NA, NA, NULL)) {
reason = E_INJURED;
return B_FALSE;
} else if (lfhasflagval(lf, F_NOBODYPART, BP_WINGS, NA, NA, NULL)) {
reason = E_INJURED;
return B_FALSE;
}
}
// get canwill opts // get canwill opts
texttospellopts(f->text, "needgrab:", &needgrab, NULL); texttospellopts(f->text, "needgrab:", &needgrab, NULL);
@ -845,12 +867,8 @@ int canmakerecipe(lifeform_t *lf, recipe_t *rec) {
int canopendoors(lifeform_t *lf) { int canopendoors(lifeform_t *lf) {
if (lf) { if (lf) {
if (!lfhasflag(lf, F_HUMANOID)) { if (!lfhasflag(lf, F_HUMANOID)) return B_FALSE;
return B_FALSE; if (!hasbp(lf, BP_HANDS)) return B_FALSE;
}
if (lfhasflagval(lf, F_NOBODYPART, BP_HANDS, NA, NA, NULL)) {
return B_FALSE;
}
} }
return B_TRUE; return B_TRUE;
@ -1138,7 +1156,8 @@ int canwear(lifeform_t *lf, object_t *o, enum BODYPART where) {
if (!hasbp(lf, where)) { if (!hasbp(lf, where)) {
reason = E_NOBP; reason = E_NOBP;
return B_FALSE; return B_FALSE;
} else if (lfhasflagval(lf, F_NOARMOURON, where, NA, NA, NULL)) { }
if (!bpcantakearmour(lf, where)) {
reason = E_DOESNTFIT; reason = E_DOESNTFIT;
return B_FALSE; return B_FALSE;
} }
@ -1327,7 +1346,7 @@ int canweild(lifeform_t *lf, object_t *o) {
} }
} else if (f->id == F_TWOHANDED) { } else if (f->id == F_TWOHANDED) {
// need both hands free... // need both hands free...
if (lfhasflagval(lf, F_NOBODYPART, otherloc, NA, NA, NULL)) { if (!hasbp(lf, otherloc)) {
reason = E_NOHANDS; reason = E_NOHANDS;
return B_FALSE; return B_FALSE;
} }
@ -1417,6 +1436,9 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
case E_NOMP: case E_NOMP:
msg("You don't have enough mana to cast that."); msg("You don't have enough mana to cast that.");
break; break;
case E_INJURED:
msg("Your injury prevents you from doing that.");
break;
case E_LOWIQ: case E_LOWIQ:
msg("You are not smart enough to cast spells."); msg("You are not smart enough to cast spells.");
break; break;
@ -1563,7 +1585,7 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
// special case // special case
f = lfhasflagval(lf, F_SPELLCASTTEXT, sid, NA, NA, NULL); // specific text for this spell f = lfhasflagval(lf, F_SPELLCASTTEXT, sid, NA, NA, NULL); // specific text for this spell
if (!f) { if (!f) {
f = lfhasflag(lf, F_SPELLCASTTEXT); // generic spellcast f = lfhasflagval(lf, F_SPELLCASTTEXT, OT_NONE, NA, NA, NULL); // generic spellcast
} }
if (f) { if (f) {
if (strlen(f->text)) { if (strlen(f->text)) {
@ -4702,8 +4724,10 @@ enum ALLEGIENCE getallegiance(lifeform_t *lf) {
int getallouterarmour(lifeform_t *lf, object_t **ob, int *nobs) { int getallouterarmour(lifeform_t *lf, object_t **ob, int *nobs) {
object_t *o; object_t *o;
enum BODYPART bp; enum BODYPART bp;
int i;
*nobs = 0; *nobs = 0;
for (bp = BP_WEAPON; bp < MAXBODYPARTS; bp++) { for (i = 0; i < lf->race->nbodyparts; i++) {
bp = lf->race->bodypart[i].id;
o = getouterequippedob(lf, bp); o = getouterequippedob(lf, bp);
if (o) { if (o) {
int n,found = B_FALSE; int n,found = B_FALSE;
@ -5297,26 +5321,40 @@ object_t *getbestweapon(lifeform_t *lf) {
int getbodyparthitchance(enum BODYPART bp) { int getbodyparthitchance(enum BODYPART bp) {
switch (bp) { switch (bp) {
case BP_WEAPON: return 0;
case BP_SECWEAPON: return 0;
case BP_EYES: return 1; case BP_EYES: return 1;
case BP_HEAD: return 2; case BP_HEAD: return 2;
case BP_WAIST: return 3; case BP_WAIST: return 3;
case BP_HANDS: return 3; case BP_HANDS: return 3;
case BP_FEET: return 3; case BP_FEET: return 3;
case BP_TAIL: return 3;
case BP_FRONTLEGS: return 4;
case BP_BACKLEGS: return 4;
case BP_LEGS: return 4; case BP_LEGS: return 4;
case BP_SHOULDERS: return 4; case BP_SHOULDERS: return 4;
case BP_WINGS: return 4;
case BP_BODY: return 6; case BP_BODY: return 6;
default: break;
case BP_EARS:
case BP_RIGHTFINGER:
case BP_LEFTFINGER:
break;
} }
return 0; // ie rings, ears, weapon return 0; // ie rings, ears, weapon
} }
char *getbodypartname(lifeform_t *lf, enum BODYPART bp) { char *getbodypartname(lifeform_t *lf, enum BODYPART bp) {
flag_t *f;
if (lf) { if (lf) {
f = lfhasflagval(lf, F_BODYPARTNAME, bp, NA, NA, NULL); int i;
if (f) {
return f->text; // does this bodypart have a special name?
for (i = 0; i < lf->race->nbodyparts; i++) {
if (lf->race->bodypart[i].id == bp) {
if (strlen(lf->race->bodypart[i].name)) {
return lf->race->bodypart[i].name;
}
}
} }
} }
@ -5343,10 +5381,18 @@ char *getbodypartname(lifeform_t *lf, enum BODYPART bp) {
return "shoulders"; return "shoulders";
case BP_WAIST: case BP_WAIST:
return "waist"; return "waist";
case BP_FRONTLEGS:
return "front legs";
case BP_BACKLEGS:
return "back legs";
case BP_LEGS: case BP_LEGS:
return "legs"; return "legs";
case BP_FEET: case BP_FEET:
return "feet"; return "feet";
case BP_TAIL:
return "tail";
case BP_WINGS:
return "wings";
} }
return "unknown"; return "unknown";
} }
@ -5362,8 +5408,12 @@ char *getbodypartequipname(enum BODYPART bp) {
case BP_HANDS: case BP_HANDS:
case BP_HEAD: case BP_HEAD:
case BP_BODY: case BP_BODY:
case BP_FRONTLEGS:
case BP_BACKLEGS:
case BP_LEGS: case BP_LEGS:
case BP_FEET: case BP_FEET:
case BP_WINGS:
case BP_TAIL:
return "on"; return "on";
case BP_EYES: case BP_EYES:
case BP_SHOULDERS: case BP_SHOULDERS:
@ -5708,6 +5758,7 @@ int getlfaccuracy(lifeform_t *lf, object_t *wep) {
case IJ_SHOULDERDISLOCATED: case IJ_SHOULDERDISLOCATED:
acc -= 20; break; acc -= 20; break;
case IJ_RIBBROKEN: case IJ_RIBBROKEN:
case IJ_TAILBROKEN:
acc -= 30; break; acc -= 30; break;
} }
} }
@ -6444,8 +6495,14 @@ int getmovespeed(lifeform_t *lf) {
} }
// flying in low gravity? // flying in low gravity?
if (lfhasflag(lf, F_GRAVLESSENED) && lfhasflag(lf, F_FLYING)) { f = lfhasflag(lf, F_FLYING);
speed -= 5; if (f) {
if (lfhasflag(lf, F_GRAVLESSENED)) {
speed -= 5;
}
if ((f->lifetime == FROMRACE) && lfhasflagval(lf, F_INJURY, IJ_WINGBRUISED, NA, NA, NULL)) {
speed += 10;
}
} }
switch (isburdened(lf)) { switch (isburdened(lf)) {
@ -6928,8 +6985,15 @@ enum BODYPART getrandomcorebp(lifeform_t *lf) {
enum BODYPART bp[4],selbp = BP_NONE; enum BODYPART bp[4],selbp = BP_NONE;
if (hasbp(lf, BP_BODY)) bp[nparts++] = BP_BODY; if (hasbp(lf, BP_BODY)) bp[nparts++] = BP_BODY;
if (hasbp(lf, BP_HANDS)) bp[nparts++] = BP_HANDS; if (hasbp(lf, BP_HANDS)) bp[nparts++] = BP_HANDS;
if (hasbp(lf, BP_LEGS)) bp[nparts++] = BP_LEGS;
if (hasbp(lf, BP_HEAD)) bp[nparts++] = BP_HEAD; if (hasbp(lf, BP_HEAD)) bp[nparts++] = BP_HEAD;
if (hasbp(lf, BP_LEGS) || hasbp(lf, BP_FRONTLEGS) || hasbp(lf, BP_BACKLEGS)) {
bp[nparts++] = BP_LEGS;
}
if (!nparts) {
return BP_NONE;
}
for (i = 0;i < nparts; i++) { for (i = 0;i < nparts; i++) {
if (i == 0) { if (i == 0) {
cutoff[i] = getbodyparthitchance(bp[i]); cutoff[i] = getbodyparthitchance(bp[i]);
@ -8633,8 +8697,21 @@ int injure(lifeform_t *lf, enum BODYPART where, enum DAMTYPE damtype) {
object_t *wep = NULL; object_t *wep = NULL;
int howlong; int howlong;
if (where == BP_NONE) return B_TRUE; if (where == BP_NONE) return B_TRUE;
if (!hasbp(lf, where)) return B_TRUE;
if (!hasbp(lf, where)) {
if (where == BP_LEGS) {
// adjust bp_legs into bp_frontlegs/bp_backelgs
if (hasbp(lf, BP_FRONTLEGS) || hasbp(lf, BP_BACKLEGS)) {
// ok.
} else {
return B_TRUE;
}
} else {
return B_TRUE;
}
}
if (lfhasflag(lf, F_NOINJURIES)) return B_TRUE; if (lfhasflag(lf, F_NOINJURIES)) return B_TRUE;
if (lfhasflagval(lf, F_INJURY, NA, where, NA, NULL)) return B_TRUE; if (lfhasflagval(lf, F_INJURY, NA, where, NA, NULL)) return B_TRUE;
@ -8702,6 +8779,21 @@ int injure(lifeform_t *lf, enum BODYPART where, enum DAMTYPE damtype) {
desc = strdup("ankle is swollen^cannot wear/remove boots"); break; desc = strdup("ankle is swollen^cannot wear/remove boots"); break;
} }
} }
break;
case BP_TAIL:
switch (rnd(1,2)) {
case 1:
inj = IJ_TAILBRUISED;
desc = strdup("tail is bruised^accuracy penalty"); break;
case 2:
inj = IJ_TAILBROKEN;
desc = strdup("tail is fractured^occasional random movement"); break;
}
break;
case BP_WINGS:
inj = IJ_WINGBRUISED;
desc = strdup("wings are bruised^flight speed lowered"); break;
break;
default: break; default: break;
} }
} else if (damtype == DT_SLASH) { } else if (damtype == DT_SLASH) {
@ -8787,6 +8879,22 @@ int injure(lifeform_t *lf, enum BODYPART where, enum DAMTYPE damtype) {
inj = IJ_HAMSTRUNG; desc = strdup("left hamstring is torn^lower move speed, chance of falling"); inj = IJ_HAMSTRUNG; desc = strdup("left hamstring is torn^lower move speed, chance of falling");
break; break;
} }
break;
case BP_TAIL:
inj = IJ_TAILBLEED;
desc = strdup("tail is bleeding^no additional effects");
break;
case BP_WINGS:
switch (rnd(1,2)) {
case 1:
inj = IJ_WINGTORN;
desc = strdup("wings are torn^cannot fly");
break;
case 2:
inj = IJ_WINGBLEED;
desc = strdup("wings are bleeding^flying causes damage");
break;
}
default: break; default: break;
} }
} else if (damtype == DT_EXPLOSIVE) { } else if (damtype == DT_EXPLOSIVE) {
@ -8851,6 +8959,16 @@ int injure(lifeform_t *lf, enum BODYPART where, enum DAMTYPE damtype) {
case BP_LEGS: case BP_LEGS:
// lose limb // lose limb
break; break;
case BP_TAIL:
inj = IJ_TAILLACERATED;
desc = strdup("tail is lacerated^chance of falling during movement");
howlong = PERMENANT;
break;
case BP_WINGS:
inj = IJ_WINGDESTROYED;
desc = strdup("wings are destroyed^cannot fly");
howlong = PERMENANT;
break;
default: default:
break; break;
} }
@ -8884,6 +9002,12 @@ int injure(lifeform_t *lf, enum BODYPART where, enum DAMTYPE damtype) {
wep = getweapon(lf); wep = getweapon(lf);
if (wep) drop(wep, wep->amt); if (wep) drop(wep, wep->amt);
break; break;
case IJ_WINGTORN:
killflagsofid(lf->flags, F_FLYING);
break;
case IJ_WINGDESTROYED:
addflag(lf->flags, F_NOBODYPART, BP_WINGS, B_FROMINJURY, NA, NULL);
break;
case IJ_WINDED: case IJ_WINDED:
lf->stamina = 0; lf->stamina = 0;
if (isplayer(lf)) statdirty = B_TRUE; if (isplayer(lf)) statdirty = B_TRUE;
@ -9094,10 +9218,14 @@ void loseobflags(lifeform_t *lf, object_t *o, int kind) {
} }
int hasbp(lifeform_t *lf, enum BODYPART bp) { int hasbp(lifeform_t *lf, enum BODYPART bp) {
int i;
if (lfhasflagval(lf, F_NOBODYPART, bp, NA, NA, NULL)) { if (lfhasflagval(lf, F_NOBODYPART, bp, NA, NA, NULL)) {
return B_FALSE; return B_FALSE;
} }
return B_TRUE; for (i = 0; i < lf->race->nbodyparts; i++) {
if (lf->race->bodypart[i].id == bp) return B_TRUE;
}
return B_FALSE;
} }
flag_t *hasactivespell(lifeform_t *lf, enum OBTYPE sid) { flag_t *hasactivespell(lifeform_t *lf, enum OBTYPE sid) {
@ -9666,6 +9794,8 @@ int isfullyhealed(lifeform_t *lf) {
healed = B_FALSE; healed = B_FALSE;
} else if (getstamina(lf) < getmaxstamina(lf)) { } else if (getstamina(lf) < getmaxstamina(lf)) {
healed = B_FALSE; healed = B_FALSE;
} else if (hashealableinjuries(lf)) {
healed = B_FALSE;
} }
return healed; return healed;
} }
@ -9967,6 +10097,17 @@ job_t *addjob(enum JOB id, char *name, char *desc) {
return a; return a;
} }
void addbodypart(race_t *r, enum BODYPART bp, char *name) {
r->bodypart[r->nbodyparts].id = bp;
if (name) {
r->bodypart[r->nbodyparts].name = strdup(name);
} else {
r->bodypart[r->nbodyparts].name = strdup("");
}
r->bodypart[r->nbodyparts].armourok = B_TRUE;
r->nbodyparts++;
}
lifeform_t *addlf(cell_t *cell, enum RACE rid, int level) { lifeform_t *addlf(cell_t *cell, enum RACE rid, int level) {
return real_addlf(cell, rid, level, C_AI); return real_addlf(cell, rid, level, C_AI);
} }
@ -10074,7 +10215,7 @@ lifeform_t *real_addlf(cell_t *cell, enum RACE rid, int level, int controller) {
// set race - this will inherit race flags and material // set race - this will inherit race flags and material
a->race = NULL; a->race = NULL;
setrace(a, rid, B_FALSE); setrace(a, rid, B_FALSE);
// set stamina AFTER setrace as it depends on your attribs // set stamina AFTER setrace as it depends on your attribs
@ -10130,6 +10271,8 @@ race_t *addrace(enum RACE id, char *name, float weight, char glyph, int glyphcol
a->glyph.ch = glyph; a->glyph.ch = glyph;
a->glyph.colour = glyphcolour; a->glyph.colour = glyphcolour;
a->nbodyparts = 0;
a->flags = addflagpile(NULL, NULL); a->flags = addflagpile(NULL, NULL);
return a; return a;
} }
@ -10641,6 +10784,7 @@ int armourfits(lifeform_t *lf, object_t *o, enum ERROR *reason) {
return B_TRUE; return B_TRUE;
} }
int askforpayment(lifeform_t *shk, lifeform_t *lf) { int askforpayment(lifeform_t *shk, lifeform_t *lf) {
char saybuf[BUFLEN]; char saybuf[BUFLEN];
int totcost = 0; int totcost = 0;
@ -11939,6 +12083,16 @@ int needstorest(lifeform_t *lf, char *validchars) {
return need; return need;
} }
void noarmouron(race_t *r, enum BODYPART bp) {
int i;
for (i = 0; i < r->nbodyparts; i++) {
if (r->bodypart[i].id == bp) {
r->bodypart[i].armourok = B_FALSE;
break;
}
}
}
// returns TRUE if the player heard it. // returns TRUE if the player heard it.
int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nclass, int volume, char *text, char *seetext) { int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nclass, int volume, char *text, char *seetext) {
lifeform_t *l; lifeform_t *l;
@ -13376,6 +13530,61 @@ void setattr(lifeform_t *lf, enum ATTRIB attr, int val) {
} }
} }
void setbodypartname(race_t *r, enum BODYPART bp, char *name) {
int i;
for (i = 0; i < r->nbodyparts; i++) {
if (r->bodypart[i].id == bp) {
free(r->bodypart[i].name);
r->bodypart[i].name = strdup(name);
break;
}
}
}
void setbodytype(race_t *r, enum BODYTYPE bt) {
int i;
switch (bt) {
case BT_BIRD:
addbodypart(r, BP_EYES, NULL);
addbodypart(r, BP_HEAD, NULL);
addbodypart(r, BP_BODY, NULL);
addbodypart(r, BP_LEGS, NULL);
addbodypart(r, BP_FEET, "talons");
addbodypart(r, BP_WINGS, NULL);
break;
case BT_HUMANOID:
for (i = BP_WEAPON; i <= BP_LEFTFINGER; i++) {
addbodypart(r, i, NULL);
}
break;
case BT_QUADRAPED:
addbodypart(r, BP_EYES, NULL);
addbodypart(r, BP_HEAD, NULL);
addbodypart(r, BP_BODY, NULL);
addbodypart(r, BP_BACKLEGS, "back legs");
addbodypart(r, BP_FRONTLEGS, "front legs");
addbodypart(r, BP_FEET, "paws");
break;
case BT_FISH:
addbodypart(r, BP_EYES, NULL);
addbodypart(r, BP_HEAD, NULL);
addbodypart(r, BP_BODY, NULL);
addbodypart(r, BP_TAIL, NULL);
break;
case BT_SNAKE:
addbodypart(r, BP_EYES, NULL);
addbodypart(r, BP_HEAD, NULL);
addbodypart(r, BP_TAIL, NULL);
break;
case BT_SPIDER:
addbodypart(r, BP_EYES, NULL);
addbodypart(r, BP_HEAD, "cephalothorax");
addbodypart(r, BP_BODY, "abdomen");
addbodypart(r, BP_LEGS, NULL);
break;
}
}
int setfacing(lifeform_t *lf, int dir) { int setfacing(lifeform_t *lf, int dir) {
if (isclimbing(lf)) { // can't change dir while climbing if (isclimbing(lf)) { // can't change dir while climbing
return B_TRUE; return B_TRUE;
@ -13634,22 +13843,20 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
} }
for (bp = BP_WEAPON; bp < MAXBODYPARTS; bp++) { for (bp = BP_WEAPON; bp < MAXBODYPARTS; bp++) {
if (lfhasflagval(lf, F_NOBODYPART, bp, NA, NA, NULL)) { if (!hasbp(lf, bp)) {
for (o = lf->pack->first; o ; o = nexto ) { o = getequippedob(lf->pack, bp);
nexto = o->next; if (o) {
if (hasflagval(o->flags, F_EQUIPPED, bp, NA, NA, NULL)) { char obname[BUFLEN];
char obname[BUFLEN]; getobname(o, obname, o->amt);
getobname(o, obname, o->amt); // drop it!
// drop it! if (isplayer(lf)) {
if (isplayer(lf)) { msg("Your %s drops to the ground!",noprefix(obname));
msg("Your %s drops to the ground!",noprefix(obname)); } else if (cansee(player, lf)) {
} else if (cansee(player, lf)) { getlfname(lf, buf);
getlfname(lf, buf); msg("%s%s %s drop to the ground!",buf, getpossessive(buf),
msg("%s%s %s drop to the ground!",buf, getpossessive(buf), noprefix(obname));
noprefix(obname));
}
moveob(o, lf->cell->obpile, o->amt);
} }
moveob(o, lf->cell->obpile, o->amt);
} }
} }
} }

5
lf.h
View File

@ -1,5 +1,6 @@
#include "defs.h" #include "defs.h"
void addbodypart(race_t *r, enum BODYPART bp, char *name);
lifeform_t *addlf(cell_t *cell, enum RACE rid, int level); lifeform_t *addlf(cell_t *cell, enum RACE rid, int level);
lifeform_t *real_addlf(cell_t *cell, enum RACE rid, int level, int controller); lifeform_t *real_addlf(cell_t *cell, enum RACE rid, int level, int controller);
job_t *addjob(enum JOB id, char *name, char *desc); job_t *addjob(enum JOB id, char *name, char *desc);
@ -25,6 +26,7 @@ int appearsrandomly(enum RACE rid);
void awardxpfor(lifeform_t *killed, float pct); void awardxpfor(lifeform_t *killed, float pct);
void bleed(lifeform_t *lf, int splatter); void bleed(lifeform_t *lf, int splatter);
int bleedfrom(lifeform_t *lf, enum BODYPART bp, int splatter); int bleedfrom(lifeform_t *lf, enum BODYPART bp, int splatter);
int bpcantakearmour(lifeform_t *lf, enum BODYPART bp);
void breakgrabs(lifeform_t *lf, int fromme, int tome); void breakgrabs(lifeform_t *lf, int fromme, int tome);
void breakaitargets(lifeform_t *lf, int onlylowerlev); void breakaitargets(lifeform_t *lf, int onlylowerlev);
long calcscore(lifeform_t *lf); long calcscore(lifeform_t *lf);
@ -334,6 +336,7 @@ void modmorale(lifeform_t *lf, int howmuch);
void modstamina(lifeform_t *lf, float howmuch); void modstamina(lifeform_t *lf, float howmuch);
int movecausesnoise(lifeform_t *lf); int movecausesnoise(lifeform_t *lf);
int needstorest(lifeform_t *lf, char *validchars); int needstorest(lifeform_t *lf, char *validchars);
void noarmouron(race_t *r, enum BODYPART bp);
int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nt, int volume, char *text, char *seetext); int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nt, int volume, char *text, char *seetext);
enum NOISECLASS noisetypetoclass(enum NOISETYPE nt); enum NOISECLASS noisetypetoclass(enum NOISETYPE nt);
void outfitlf(lifeform_t *lf); void outfitlf(lifeform_t *lf);
@ -362,6 +365,8 @@ int sayphrase(lifeform_t *lf, enum SAYPHRASE what, int volume, int val0, char *t
int scare(lifeform_t *lf, lifeform_t *scarer, int howlong, int scarerbonus); int scare(lifeform_t *lf, lifeform_t *scarer, int howlong, int scarerbonus);
//int setammo(lifeform_t *lf, object_t *o); //int setammo(lifeform_t *lf, object_t *o);
void setattr(lifeform_t *lf, enum ATTRIB attr, int val); void setattr(lifeform_t *lf, enum ATTRIB attr, int val);
void setbodypartname(race_t *r, enum BODYPART bp, char *name);
void setbodytype(race_t *r, enum BODYTYPE bt);
int setfacing(lifeform_t *lf, int dir); int setfacing(lifeform_t *lf, int dir);
void setfollowdistance(lifeform_t *lf, int min, int max); void setfollowdistance(lifeform_t *lf, int min, int max);
void setguntarget(lifeform_t *lf, lifeform_t *targ); void setguntarget(lifeform_t *lf, lifeform_t *targ);

42
move.c
View File

@ -1000,6 +1000,10 @@ int moveeffects(lifeform_t *lf) {
if (isplayer(lf)) didmsg = B_TRUE; if (isplayer(lf)) didmsg = B_TRUE;
} }
} }
if (onein(10) && lfhasflagval(lf, F_INJURY, IJ_TAILLACERATED, NA, NA, NULL)) {
fall(lf, NULL, B_TRUE);
if (isplayer(lf)) didmsg = B_TRUE;
}
if (isbleeding(lf)) { if (isbleeding(lf)) {
if (hasbleedinginjury(lf, BP_LEGS)) { if (hasbleedinginjury(lf, BP_LEGS)) {
@ -1013,6 +1017,19 @@ int moveeffects(lifeform_t *lf) {
} }
} }
if (lfhasflagval(lf, F_INJURY, IJ_WINGBLEED, NA, NA, NULL)) {
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 == FROMRACE) {
if (!bleedfrom(lf, BP_WINGS, B_FALSE)) {
losehp(lf, 1, DT_DIRECT, NULL, "blood loss");
}
}
}
}
f = lfhasflag(lf, F_PAIN); f = lfhasflag(lf, F_PAIN);
if (f) { if (f) {
if (!lfhasflag(lf, F_DRUNK)) { if (!lfhasflag(lf, F_DRUNK)) {
@ -1634,8 +1651,8 @@ int movetowards(lifeform_t *lf, cell_t *dst, int dirtype, int strafe) {
} }
int move_will_hurt(lifeform_t *lf) { int move_will_hurt(lifeform_t *lf) {
flag_t *retflag[MAXCANDIDATES]; flag_t *retflag[MAXCANDIDATES],*retflag2[MAXCANDIDATES];
int nretflags,i; int nretflags,nretflags2,i,n;
getflags(lf->flags, retflag, &nretflags, F_INJURY, F_PAIN, F_NONE); getflags(lf->flags, retflag, &nretflags, F_INJURY, F_PAIN, F_NONE);
for (i = 0; i < nretflags; i++) { for (i = 0; i < nretflags; i++) {
@ -1645,14 +1662,23 @@ 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:
return B_TRUE; if (!isairborne(lf)) return B_TRUE;
break;
case IJ_WINGBLEED:
getflags(lf->flags, retflag2, &nretflags2, F_FLYING, F_NONE);
for (n = 0; n < nretflags2; n++) {
if (retflag[n]->lifetime == FROMRACE) {
return B_TRUE;
}
}
break;
default: default:
break; break;
} }
} }
} }
if (hasbleedinginjury(lf, BP_LEGS)) { if (hasbleedinginjury(lf, BP_LEGS) && !isairborne(lf)) {
return B_TRUE; return B_TRUE;
} }
return B_FALSE; return B_FALSE;
@ -1910,7 +1936,7 @@ int closedoor(lifeform_t *lf, object_t *o) {
return B_TRUE; return B_TRUE;
} }
if (lf && lfhasflagval(lf, F_NOBODYPART, BP_HANDS, NA, NA, NULL)) { if (lf && !canopendoors(lf)) {
if (isplayer(lf)) { if (isplayer(lf)) {
msg("You have no hands with which to close the door!"); msg("You have no hands with which to close the door!");
} }
@ -2491,10 +2517,14 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) {
} }
} else if (iswoozy(lf)) { } else if (iswoozy(lf)) {
rndmove = B_TRUE; rndmove = B_TRUE;
} else if (lfhasflagval(lf, F_INJURY, IJ_TAILBRUISED, NA, NA, NULL) && onein(6)) {
rndmove = B_TRUE;
} }
if (rndmove) { if (rndmove) {
dir = rnd(DC_N, DC_NW); dir = rnd(DC_N, DC_NW);
strafe = B_TRUE;
} }
cell = getcellindir(lf->cell, dir); cell = getcellindir(lf->cell, dir);
@ -2509,7 +2539,7 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) {
*/ */
// warn before moving onto dangerous cells // warn before moving onto dangerous cells
if (onpurpose && isplayer(lf) && !lfhasflag(lf, F_SNEAK)) { if (onpurpose && isplayer(lf) && !lfhasflag(lf, F_SNEAK) && !rndmove) {
char ques[BUFLEN]; char ques[BUFLEN];
char ch; char ch;
if (cell && celldangerous(lf, cell, B_TRUE, &errcode)) { if (cell && celldangerous(lf, cell, B_TRUE, &errcode)) {

View File

@ -28,6 +28,8 @@ extern material_t *material,*lastmaterial;
extern recipe_t *firstrecipe,*lastrecipe; extern recipe_t *firstrecipe,*lastrecipe;
extern skill_t *firstskill, *lastskill; extern skill_t *firstskill, *lastskill;
extern int inaskcoords;
void (*precalclos)(lifeform_t *); void (*precalclos)(lifeform_t *);
extern object_t *retobs[MAXPILEOBS+1]; extern object_t *retobs[MAXPILEOBS+1];
@ -1651,8 +1653,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
} }
} }
if ((gamemode == GM_GAMESTARTED) && !inaskcoords) {
if (gamemode == GM_GAMESTARTED) {
if (o && where->where && !hasflag(o->flags, F_NOGLYPH) && haslos(player, where->where) ) { if (o && where->where && !hasflag(o->flags, F_NOGLYPH) && haslos(player, where->where) ) {
needredraw = B_TRUE; needredraw = B_TRUE;
} }

2
text.c
View File

@ -771,7 +771,7 @@ char *getkillverb(lifeform_t *victim, object_t *wep, enum DAMTYPE damtype, int d
} }
if (damtype == DT_BITE) return "gore"; if (damtype == DT_BITE) return "gore";
if (damtype == DT_SLASH) { if (damtype == DT_SLASH) {
if (lfhasflagval(victim, F_NOBODYPART, BP_HEAD, NA, NA, NULL)) { if (!hasbp(victim, BP_HEAD)) {
return "bisect"; return "bisect";
} else { } else {
if ((getlfsize(victim) >= SZ_MEDIUM) && onein(3)) { if ((getlfsize(victim) >= SZ_MEDIUM) && onein(3)) {