- [+] fullshield block: ("raise shield") ?

- [+] gain it at beginner level shields
    - [+] make ai use it
        - [+] if i've been hit by a ranged attack.
        - [+] if intelligent: if  my target has a ranged weapon AND i'm
              not adjacent AND i'm in range.
    - [+] make ai stop using it
        - [+] if i'm adjacent to my target
        - [+] OR
        - [+] if i have no target
        - [+] OR
        - [+] if i'm not in battle
- [+] don't show 'bloodstained' if blind
- [+] dusur digs hole in floor
    - [+] CRASH. who->timespent == 0
- [+] when portalling to same levle, don't say 'you arrive back at levl
      xx'
    - [+] instead: 'you arrive elsewhere in level xx'
- [+] maybe: when exhausted:
    - [+] you can still attack, but...
    - [+] attacks deal 0.75% damage
    - [+] attack speed lowered.
    - [+] change of fumbling your attack if you miss.
    - [+] ...then monsters can have stamina again.
    - [+] the %s looks exhausted.
    - [+] if ai is exhausted, wait.
This commit is contained in:
Rob Pearce 2012-11-10 04:06:45 +00:00
parent db635b50db
commit 64412035bb
15 changed files with 206 additions and 75 deletions

80
ai.c
View File

@ -1157,12 +1157,15 @@ flag_t *aigoto(lifeform_t *lf, cell_t *c, enum MOVEREASON why, void *data, int t
int ai_attack_existing_target(lifeform_t *lf) { int ai_attack_existing_target(lifeform_t *lf) {
lifeform_t *target; lifeform_t *target;
int db = B_FALSE; int db = B_FALSE;
enum ATTRBRACKET iqb;
if (lfhasflag(lf, F_DEBUG)) db = B_TRUE; if (lfhasflag(lf, F_DEBUG)) db = B_TRUE;
// do we already have a target we are attacking? // do we already have a target we are attacking?
target = gettargetlf(lf); target = gettargetlf(lf);
if (!target) return B_FALSE; if (!target) return B_FALSE;
iqb = getattrbracket(getattr(lf, A_IQ), A_IQ, NULL);
if (db) dblog(".oO { i have a target: lfid %d (%s). }", target->id, target->race->name); if (db) dblog(".oO { i have a target: lfid %d (%s). }", target->id, target->race->name);
// target dead or unconscious? // target dead or unconscious?
@ -1174,22 +1177,26 @@ int ai_attack_existing_target(lifeform_t *lf) {
real_getlfname(target, text, NULL, B_NOSHOWALL, B_CURRACE); real_getlfname(target, text, NULL, B_NOSHOWALL, B_CURRACE);
sayphrase(lf, SP_ALLY_TARGETKILL, SV_SHOUT, NA, text, target); sayphrase(lf, SP_ALLY_TARGETKILL, SV_SHOUT, NA, text, target);
} }
} else { return B_FALSE;
// aquatic grabbers will try to drag their prey into the water }
if (lfhasflagval(lf, F_GRABBING, target->id, NA, NA, NULL) && isaquatic(lf) ) {
if ( hasobwithflag(lf->cell->obpile, F_DEEPWATER) &&
!hasobwithflag(target->cell->obpile, F_DEEPWATER)) { // aquatic grabbers will try to drag their prey into the water
// move away! if (lfhasflagval(lf, F_GRABBING, target->id, NA, NA, NULL) && isaquatic(lf) ) {
if (!moveawayfrom(lf, target->cell, DT_ORTH, B_FALSE, B_TRUE, B_ONPURPOSE)) { if ( hasobwithflag(lf->cell->obpile, F_DEEPWATER) &&
return B_TRUE; !hasobwithflag(target->cell->obpile, F_DEEPWATER)) {
} // move away!
if (!moveawayfrom(lf, target->cell, DT_ORTH, B_FALSE, B_TRUE, B_ONPURPOSE)) {
return B_TRUE;
} }
} }
// try to move towards them. }
if (!aimovetolf(lf, target, B_TRUE)) {
// success
return B_TRUE; // try to move towards them.
} if (!aimovetolf(lf, target, B_TRUE)) {
// success
return B_TRUE;
} }
return B_FALSE; return B_FALSE;
} }
@ -1582,6 +1589,12 @@ int ai_healing(lifeform_t *lf) {
} }
} }
} }
// no stamina left?
if (isexhausted(lf) && !isinbattle(lf, B_FALSE, B_FALSE)) {
rest(lf, B_TRUE);
return B_TRUE;
}
return B_FALSE; return B_FALSE;
} }
@ -2829,6 +2842,45 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
break; break;
} }
} }
} else if (ot->id == OT_A_FULLSHIELD) {
object_t *targun,*sh;
int dist;
if (lfhasflag(lf, F_FULLSHIELD)) {
// turn off fullshield if:
// - i have no target
// - i have an adjacent target
if (!lfhasflag(lf, F_AIHITBYRANGED)) {
if (!victim || isinbattle(lf, B_FALSE, B_FALSE) ||
!isinbattle(lf, B_TRUE, B_FALSE)) {
ok = B_TRUE;
}
}
} else {
// turn on fullshield if:
//
// - I've recently been hit by a ranged attack.
// - I'm quite intelligent
// AND
// My target has a ranged weapon AND i'm not adjacent AND i'm in range.
sh = getshield(lf, DT_ALL);
if (sh) {
if (lfhasflag(lf, F_AIHITBYRANGED)) {
ok = B_TRUE;
} else {
enum ATTRBRACKET iqb;
iqb = getattrbracket(getattr(lf, A_IQ), A_IQ, NULL);
if (iqb >= AT_GTAVERAGE) {
targun = getfirearm(victim);
dist = getcelldist(lf->cell, victim->cell);
if (targun && getammo(targun) &&
haslof(victim->cell, lf->cell, LOF_NEED, NULL) &&
(dist > 1) && (dist <= getfirearmrange(targun)) ) {
ok = B_TRUE;
}
}
}
}
}
} else if (ot->id == OT_A_JUMP) { } else if (ot->id == OT_A_JUMP) {
cell_t *cell[MAXCANDIDATES],*c; cell_t *cell[MAXCANDIDATES],*c;
int ncells,i; int ncells,i;

View File

@ -192,6 +192,7 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
int attackedhelpless = B_FALSE; int attackedhelpless = B_FALSE;
int attackedfriend = B_FALSE; int attackedfriend = B_FALSE;
int attackedpeaceful = B_FALSE; int attackedpeaceful = B_FALSE;
enum SKILLLEVEL slev;
// 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)) {
@ -505,7 +506,7 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
if (!canattack(lf)) { if (!canattack(lf)) {
if (isplayer(lf)) { if (isplayer(lf)) {
switch (reason) { switch (reason) {
case E_NOSTAM: msg("You are too tired to fight at the moment."); break; //case E_NOSTAM: msg("You are too tired to fight at the moment."); break;
case E_STUNNED: msg("You are too stunned to fight at the moment."); break; case E_STUNNED: msg("You are too stunned to fight at the moment."); break;
case E_IMPOSSIBLE: msg("You have no way of attacking!"); break; case E_IMPOSSIBLE: msg("You have no way of attacking!"); break;
default: msg("For some reason, you cannot attack."); break; default: msg("For some reason, you cannot attack."); break;
@ -811,16 +812,15 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
} }
} }
if (isplayer(lf)) { //if (isplayer(lf)) {
enum SKILLLEVEL slev; slev = getskill(lf, SK_COMBAT);
slev = getskill(lf, SK_COMBAT); if (slev != PR_MASTER) {
if (slev != PR_MASTER) { if (!pctchance(slev * 10)) {
if (!pctchance(slev * 10)) { // lose a bit of stamina
// lose a bit of stamina modstamina(lf, -getattackstamloss(lf));
modstamina(lf, -getattackstamloss(lf));
}
} }
} }
//}
// stop sprinting // stop sprinting
stopsprinting(lf); stopsprinting(lf);
@ -1140,6 +1140,11 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
} }
if (aidb) dblog("rolled dam[%d] = %d",0,dam[0]); if (aidb) dblog("rolled dam[%d] = %d",0,dam[0]);
// half damage if exhausted
if (isexhausted(lf)) {
dam[0] = pctof(75, dam[0]);
}
if (dam[0] < 0) { if (dam[0] < 0) {
willheal = B_TRUE; willheal = B_TRUE;
} }
@ -2201,12 +2206,16 @@ int check_for_block(lifeform_t *lf, lifeform_t *victim, int dam, enum DAMTYPE da
getallshields(victim, damtype, shield, checkmod, &nshields); getallshields(victim, damtype, shield, checkmod, &nshields);
for (i = 0; i < nshields; i++) { for (i = 0; i < nshields; i++) {
int blocked = B_FALSE; int blocked = B_FALSE;
int fullbonus = 0; // did f_fuillblock skill work?
if (fflag && ranged && (shield[i]->id == shid)) { if (fflag && ranged && (shield[i]->id == shid)) {
fullbonus = 40 + (getobsize(shield[i])*5); int fullchance;
fullchance = 40 + (getobsize(shield[i])*5);
if (pctchance(fullchance)) {
blocked = B_TRUE;
}
} }
// did we block with this object? // did we block with this object?
if (skillcheck(victim, SC_SHIELDBLOCK, difficulty, checkmod[i] + fullbonus)) { if (!blocked && skillcheck(victim, SC_SHIELDBLOCK, difficulty, checkmod[i])) {
blocked = B_TRUE; blocked = B_TRUE;
} }
if (blocked) { if (blocked) {
@ -3100,7 +3109,7 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical,
} }
if (fumble && !gothit) { if (fumble && !gothit) {
if ((baseacc <= 60) || !getweaponskill(lf, wep)) { if (isexhausted(lf) || (baseacc <= 60) || !getweaponskill(lf, wep)) {
int nfailed = 0, i; int nfailed = 0, i;
int nrolls = 1; int nrolls = 1;
// chance to fumble // chance to fumble

4
data.c
View File

@ -5550,10 +5550,11 @@ void initobjects(void) {
addflag(lastot->flags, F_STAMCOST, 1, NA, NA, NULL); addflag(lastot->flags, F_STAMCOST, 1, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL);
addot(OT_A_FULLSHIELD, "fullshield", "Raise your shield to (almost) completely cover your body.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); addot(OT_A_FULLSHIELD, "fullshield", "Fully raise your shield to almost completely protect against ranged attacks.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "While in fullshield mode your vision, evasion and accuracy are greatly lowered."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "While in fullshield mode your vision, evasion and accuracy are greatly lowered.");
addflag(lastot->flags, F_STAMCOST, 1, NA, NA, NULL); addflag(lastot->flags, F_STAMCOST, 1, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_SPECIAL, NA, NA, NULL);
addot(OT_A_GRAB, "grab", "You can grab hold of nearby enemies to prevent their escape.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); addot(OT_A_GRAB, "grab", "You can grab hold of nearby enemies to prevent their escape.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL);
@ -19169,6 +19170,7 @@ void initskills(void) {
addskilldesc(SK_SHIELDS, PR_BEGINNER, "^gShield accuracy penalties are reduced by 2.^n", B_FALSE); addskilldesc(SK_SHIELDS, PR_BEGINNER, "^gShield accuracy penalties are reduced by 2.^n", B_FALSE);
addskillabil(SK_SHIELDS, PR_BEGINNER, OT_A_SHIELDBASH, NA, NULL, B_TRUE); addskillabil(SK_SHIELDS, PR_BEGINNER, OT_A_SHIELDBASH, NA, NULL, B_TRUE);
addskilldesc(SK_SHIELDS, PR_ADEPT, "^gShield accuracy penalties are reduced by 3.^n", B_FALSE); addskilldesc(SK_SHIELDS, PR_ADEPT, "^gShield accuracy penalties are reduced by 3.^n", B_FALSE);
addskillabil(SK_SHIELDS, PR_ADEPT, OT_A_FULLSHIELD, NA, NULL, B_TRUE);
addskilldesc(SK_SHIELDS, PR_SKILLED, "^gShield accuracy penalties are reduced by 4.^n", B_FALSE); addskilldesc(SK_SHIELDS, PR_SKILLED, "^gShield accuracy penalties are reduced by 4.^n", B_FALSE);
addskilldesc(SK_SHIELDS, PR_EXPERT, "^gShield accuracy penalties are reduced by 5.^n", B_FALSE); addskilldesc(SK_SHIELDS, PR_EXPERT, "^gShield accuracy penalties are reduced by 5.^n", B_FALSE);
addskilldesc(SK_SHIELDS, PR_MASTER, "^gShield accuracy penalties are reduced by 6.^n", B_FALSE); addskilldesc(SK_SHIELDS, PR_MASTER, "^gShield accuracy penalties are reduced by 6.^n", B_FALSE);

Binary file not shown.

3
defs.h
View File

@ -3510,6 +3510,9 @@ enum FLAG {
// x,y-x,y-x,y-x,y... // x,y-x,y-x,y-x,y...
// //
// v0/v1 = x/y of end cell // v0/v1 = x/y of end cell
F_AIHITBYRANGED, // ai lf has been hit by a ranged attack.
// used to figure out when to use our
// fullshield ability
F_TARGETLF, // lf will attack lfid v0. lastknown x/y is v1/v2 F_TARGETLF, // lf will attack lfid v0. lastknown x/y is v1/v2
// optional text is last known movement dir. // optional text is last known movement dir.
F_IGNORECELL, // won't accept targetcells of v0=x v1=y F_IGNORECELL, // won't accept targetcells of v0=x v1=y

3
flag.c
View File

@ -1654,6 +1654,9 @@ void updatefpindex(flagpile_t *fp) {
fp->nitems = 0; fp->nitems = 0;
for (f = fp->first ;f ; f = f->next) { for (f = fp->first ;f ; f = f->next) {
if (f->next) {
assert(f->next->prev == f);
}
fp->item[fp->nitems] = f; fp->item[fp->nitems] = f;
fp->nitems++; fp->nitems++;
assert(fp->nitems < MAXFLAGS); assert(fp->nitems < MAXFLAGS);

27
io.c
View File

@ -1240,6 +1240,15 @@ char *askstring(char *prompt, char punc, char *retbuf, int retBUFLEN, char *def)
void announcearrival(lifeform_t *lf, map_t *newmap) { void announcearrival(lifeform_t *lf, map_t *newmap) {
if (isplayer(lf)) { if (isplayer(lf)) {
char backtext[BUFLEN];
if (lf->cell->map == newmap) {
strcpy(backtext, "elsewhere ");
} else if (newmap->lastplayervisit == -1) {
// never been here before
strcpy(backtext, "");
} else {
strcpy(backtext, "back ");
}
if (newmap->region->rtype->id == BH_WORLDMAP) { if (newmap->region->rtype->id == BH_WORLDMAP) {
if (lf->cell->map->region->rtype->id == BH_WORLDMAP) { if (lf->cell->map->region->rtype->id == BH_WORLDMAP) {
msg("You arrive in a new area."); msg("You arrive in a new area.");
@ -1250,29 +1259,24 @@ void announcearrival(lifeform_t *lf, map_t *newmap) {
flag_t *f; flag_t *f;
switch (newmap->habitat->id) { switch (newmap->habitat->id) {
case H_ANTNEST: case H_ANTNEST:
msg("You find yourself %sin a giant ant's nest.", msg("You find yourself %sin a giant ant's nest.", backtext);
(newmap->lastplayervisit == -1) ? "" : "back ");
break; break;
case H_CAVE: case H_CAVE:
if ((newmap->depth == 1) && (newmap->lastplayervisit == -1)) { if ((newmap->depth == 1) && (newmap->lastplayervisit == -1)) {
msg("You arrive at the goblin caves."); msg("You arrive at the goblin caves.");
} else { } else {
msg("You arrive %sat level %d of the goblin caves.", msg("You arrive %sat level %d of the goblin caves.",
(newmap->lastplayervisit == -1) ? "" : "back ", backtext, newmap->depth);
newmap->depth);
} }
break; break;
case H_DUNGEON: case H_DUNGEON:
msg("You arrive %sat dungeon level %d.", msg("You arrive %sat dungeon level %d.", backtext, newmap->depth);
(newmap->lastplayervisit == -1) ? "" : "back ",
newmap->depth);
break; break;
case H_FOREST: case H_FOREST:
if ((newmap->depth == 1) && (newmap->lastplayervisit == -1)) { if ((newmap->depth == 1) && (newmap->lastplayervisit == -1)) {
msg("You arrive in the sylvan woods."); msg("You arrive in the sylvan woods.");
} else { } else {
msg("You arrive %sat level %d of the sylvan woods.", msg("You arrive %sat level %d of the sylvan woods.", backtext,
(newmap->lastplayervisit == -1) ? "" : "back ",
newmap->depth); newmap->depth);
} }
break; break;
@ -1285,8 +1289,7 @@ void announcearrival(lifeform_t *lf, map_t *newmap) {
} }
break; break;
case H_SWAMP: case H_SWAMP:
msg("You arrive %sat a swamp.", msg("You arrive %sat a swamp.", backtext);
(newmap->lastplayervisit == -1) ? "" : "back ");
break; break;
case H_SEWER: case H_SEWER:
msg("You find yourself in a sewer."); msg("You find yourself in a sewer.");
@ -1681,7 +1684,7 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
msg("You are now cowering behind your %s.", noprefix(obname)); msg("You are now cowering behind your %s.", noprefix(obname));
donesomething = B_TRUE; donesomething = B_TRUE;
} else { } else {
msg("%s is now cowering behind %s.", lfname, obname); msg("%s starts cowering behind %s.", lfname, obname);
donesomething = B_TRUE; donesomething = B_TRUE;
} }
break; break;

44
lf.c
View File

@ -593,10 +593,12 @@ void callguards(lifeform_t *caller, lifeform_t *victim) {
} }
int canattack(lifeform_t *lf) { int canattack(lifeform_t *lf) {
/*
if (!getstamina(lf)) { if (!getstamina(lf)) {
reason = E_NOSTAM; reason = E_NOSTAM;
return B_FALSE; return B_FALSE;
} else if (lfhasflag(lf, F_STUNNED)) { } else */
if (lfhasflag(lf, F_STUNNED)) {
reason = E_STUNNED; reason = E_STUNNED;
return B_FALSE; return B_FALSE;
} else if (lfhasflag(lf, F_NOATTACK)) { } else if (lfhasflag(lf, F_NOATTACK)) {
@ -6359,6 +6361,9 @@ int flee(lifeform_t *lf) {
if (db) dblog("%s - fleeing from %s", lfname, fleefrom->race->name); if (db) dblog("%s - fleeing from %s", lfname, fleefrom->race->name);
// lower our shield
killflagsofid(lf->flags, F_FULLSHIELD);
breakgrabs(lf, B_TRUE, B_FALSE); // stop grabbing anyone breakgrabs(lf, B_TRUE, B_FALSE); // stop grabbing anyone
// ways of fleeing other than movement? // ways of fleeing other than movement?
@ -7275,6 +7280,10 @@ int getattackspeed(lifeform_t *lf) {
del = getobattackdelay(w); del = getobattackdelay(w);
speed = pctof(del, speed); speed = pctof(del, speed);
} }
// 50% longer to attack if exhausted
if (isexhausted(lf)) {
speed = pctof(150, speed);
}
return (int)speed; return (int)speed;
} }
@ -9612,6 +9621,12 @@ char *real_getlfname(lifeform_t *lf, char *buf, lifeform_t *usevis, int showall,
strcat(descstring, "headless "); strcat(descstring, "headless ");
dobehaviour = B_FALSE; dobehaviour = B_FALSE;
} }
if (!isplayer(lf) && isexhausted(lf) && cansee(player, lf)) {
if (lorelev >= PR_NOVICE) {
strcat(descstring, "exhausted ");
dobehaviour = B_FALSE;
}
}
if (dobehaviour) { if (dobehaviour) {
f = lfhasflag(lf, F_BEHAVIOUR); f = lfhasflag(lf, F_BEHAVIOUR);
@ -13794,6 +13809,11 @@ int isfullyhealed(lifeform_t *lf) {
return healed; return healed;
} }
int isexhausted(lifeform_t *lf) {
if (!getstamina(lf)) return B_TRUE;
return B_FALSE;
}
int isgenius(lifeform_t *lf) { int isgenius(lifeform_t *lf) {
enum ATTRBRACKET iqb; enum ATTRBRACKET iqb;
iqb = getattrbracket(getattr(lf, A_IQ), A_IQ, NULL); iqb = getattrbracket(getattr(lf, A_IQ), A_IQ, NULL);
@ -16113,12 +16133,23 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml
if (fromlf && (getallegiance(fromlf) == AL_FRIENDLY)) { if (fromlf && (getallegiance(fromlf) == AL_FRIENDLY)) {
addflag(lf->flags, F_KILLEDBYPLAYER, B_TRUE, NA, NA, NULL); addflag(lf->flags, F_KILLEDBYPLAYER, B_TRUE, NA, NA, NULL);
} }
} }
if (doeffects || ko) { if (doeffects || ko) {
losehpeffects(lf, amt, damtype, fromlf, fromob, retaliate, ko, waskod, prelowhp, bodypart); losehpeffects(lf, amt, damtype, fromlf, fromob, retaliate, ko, waskod, prelowhp, bodypart);
} }
if ((lf->hp > 0) && !ko && fromlf && (getcelldist(lf->cell, fromlf->cell) > 1)) {
int lifetimeinc;
lifetimeinc = rnd(2,6);
f = lfhasflag(lf, F_AIHITBYRANGED);
if (f) {
f->lifetime += lifetimeinc;
} else {
addtempflag(lf->flags, F_AIHITBYRANGED, B_TRUE, NA, NA, NULL, lifetimeinc);
}
}
if (!predead) { if (!predead) {
////////////////////////////////////////// //////////////////////////////////////////
// Figure out death text for tombstone. // Figure out death text for tombstone.
@ -17126,19 +17157,18 @@ void modstamina(lifeform_t *lf, float howmuch) {
statdirty = B_TRUE; statdirty = B_TRUE;
drawstatus(); drawstatus();
updatestatus(); updatestatus();
if (getstamina(lf) == 0) { if (isexhausted(lf)) {
msg("^BYou are exhausted."); msg("^BYou are exhausted.");
} else if (orig == 0) { } else if (orig == 0) {
msg("You feel less exhausted now."); msg("You feel less exhausted now.");
} }
} } else if (cansee(player, lf)) {
/*else if (cansee(player, lf)) { if (isexhausted(lf)) {
if (getstamina(lf) == 0) {
char lfname[BUFLEN]; char lfname[BUFLEN];
getlfname(lf, lfname); getlfname(lf, lfname);
msg("%s looks exhausted.", lfname); msg("%s looks exhausted.", lfname);
} }
}*/ }
} }
if (getstamina(lf) == 0) { if (getstamina(lf) == 0) {

1
lf.h
View File

@ -354,6 +354,7 @@ flag_t *isfleeingfrom(lifeform_t *lf, lifeform_t *runfrom);
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);
int isexhausted(lifeform_t *lf);
int isgenius(lifeform_t *lf); int isgenius(lifeform_t *lf);
int isgod(lifeform_t *lf); int isgod(lifeform_t *lf);
int ishelplessvictim(lifeform_t *victim, lifeform_t *attacker, enum HELPLESSTYPE *how); int ishelplessvictim(lifeform_t *victim, lifeform_t *attacker, enum HELPLESSTYPE *how);

14
map.c
View File

@ -9226,6 +9226,20 @@ int shattercell(cell_t *c, lifeform_t *fromlf, char *damstring) {
return rv; return rv;
} }
// returns TRUE if we shuffled down.
int shuffledown(map_t *map) {
lifeform_t *l;
int firsttime;
firsttime = map->lf->timespent;
if (firsttime == 0) return B_FALSE;
for (l = map->lf ; l ; l = l->next) {
//dblog("shuffling id %d %s timespent=%d -> %d",l->id,l->race->name, l->timespent, l->timespent - firstlftime);
l->timespent -= firsttime;
assert(l->timespent >= 0);
}
return B_TRUE;
}
int unlinkstairsto(map_t *unlinkmap) { int unlinkstairsto(map_t *unlinkmap) {
map_t *m; map_t *m;
object_t *o; object_t *o;

1
map.h
View File

@ -201,6 +201,7 @@ void setcellknownradius(cell_t *centre, int forcelev, int radius, int dirtype);
void setcellreason(cell_t *c, char *why, ...); void setcellreason(cell_t *c, char *why, ...);
void setcelltype(cell_t *cell, enum CELLTYPE id); void setcelltype(cell_t *cell, enum CELLTYPE id);
int shattercell(cell_t *c, lifeform_t *fromlf, char *damstring); int shattercell(cell_t *c, lifeform_t *fromlf, char *damstring);
int shuffledown(map_t *map);
int unlinkstairsto(map_t *unlinkmap); int unlinkstairsto(map_t *unlinkmap);
void unmakemap(map_t *map); void unmakemap(map_t *map);
void updateknowncells(void); void updateknowncells(void);

2
move.c
View File

@ -2438,7 +2438,7 @@ int initiatemove(lifeform_t *lf, cell_t *cell, int onpurpose, int *didmsg) {
// climbing along a wall? // climbing along a wall?
if (isplayer(lf) && isclimbing(lf)) { if (isplayer(lf) && isclimbing(lf)) {
if (cell != getcellindir(lf->cell, lf->facing)) { // not dropping off the wall if (cell != getcellindir(lf->cell, lf->facing)) { // not dropping off the wall
if (!getstamina(lf)) { if (isexhausted(lf)) {
// this shouldn't be able to happen, since if you run out // this shouldn't be able to happen, since if you run out
// of stamina while on a wall you'll fall off during startlfturn(). // of stamina while on a wall you'll fall off during startlfturn().
msg("You are too tired to climb!"); msg("You are too tired to climb!");

22
nexus.c
View File

@ -911,6 +911,11 @@ void donextturn(map_t *map) {
if (who) { if (who) {
if (db) dblog("**** donextturn for: id %d %s", who->id, who->race->name); if (db) dblog("**** donextturn for: id %d %s", who->id, who->race->name);
if (who->timespent > 0) {
// shuffling lf times...
shuffledown(map);
}
assert(who->timespent == 0); assert(who->timespent == 0);
if (getoption(OPT_TIMEDEBUG)) { if (getoption(OPT_TIMEDEBUG)) {
@ -2041,23 +2046,10 @@ void timeeffectsworld(map_t *map, int updategametime) {
//if (db) dblog("timespent = %d\n", timespent); //if (db) dblog("timespent = %d\n", timespent);
if (db) dblog("firstlftime = %d\n", firstlftime); if (db) dblog("firstlftime = %d\n", firstlftime);
if (firstlftime > 0) { if (firstlftime > 0) {
if (db) dblog("making firstlf timespent = 0 (currently %d):", firstlftime); if (db) dblog("making firstlf timespent = 0 (currently %d):", firstlftime);
//dumplf(); shuffledown(map);
for (l = map->lf ; l ; l = l->next) {
//dblog("shuffling id %d %s timespent=%d -> %d",l->id,l->race->name, l->timespent, l->timespent - firstlftime);
l->timespent -= firstlftime;
assert(l->timespent >= 0);
/*
if (isplayer(l)) {
statdirty = B_TRUE;
}
*/
}
//dblog("after shuffle:");
//dumplf();
} else { } else {
if (db) dblog("firstlf timespent is not greater than 0. no shuffle."); if (db) dblog("firstlf timespent is not greater than 0. no shuffle.");
} }

View File

@ -5737,7 +5737,7 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
// include mods // include mods
// ie. a blessed damaged ->flaming<- +5 silver sword of pyromania // ie. a blessed damaged ->flaming<- +5 silver sword of pyromania
if (wantpremods) { if (wantpremods && (!isblind(player) || !adjustforblind)) {
obmod_t *om; obmod_t *om;
for (om = firstobmod ; om; om = om->next) { for (om = firstobmod ; om; om = om->next) {
if (hasobmod(o, om)) { if (hasobmod(o, om)) {

43
text.c
View File

@ -227,7 +227,7 @@ char *construct_hit_string(lifeform_t *lf, lifeform_t *victim, char *attackernam
if (isplayer(lf)) { if (isplayer(lf)) {
char extradambuf[BUFLEN]; char extradambuf[BUFLEN];
char withwep[BUFLEN]; char withwep[BUFLEN],adjective[BUFLEN],hitwhere[BUFLEN];
char *verb; char *verb;
int needfree = B_FALSE; int needfree = B_FALSE;
int knownnodam = B_FALSE; int knownnodam = B_FALSE;
@ -277,10 +277,24 @@ char *construct_hit_string(lifeform_t *lf, lifeform_t *victim, char *attackernam
} else { } else {
col = C_BROWN; // normal hit col = C_BROWN; // normal hit
} }
snprintf(retbuf, BUFLEN, "^%dYou %s%s %s%s%s%s", col,
usecrittext ? "critically " : "", verb, strcpy(adjective, "");
usecrittext ? victimbpname : locvictimname, withwep,extradambuf, if (isexhausted(lf)) {
(fatal || backstab) ? "!" : "."); if (onein(2)) strcat(adjective, "tiredly ");
else strcat(adjective, "wearily ");
}
if (usecrittext) {
if (strlen(adjective)) {
strcat(adjective, "but critically ");
} else {
strcat(adjective, "critically ");
}
strcpy(hitwhere, victimbpname);
} else {
strcpy(hitwhere, locvictimname);
}
snprintf(retbuf, BUFLEN, "^%dYou %s%s %s%s%s%s", col, adjective, verb,
hitwhere, withwep,extradambuf, (fatal || backstab) ? "!" : ".");
if (needfree) { if (needfree) {
free(verb); free(verb);
@ -289,7 +303,7 @@ char *construct_hit_string(lifeform_t *lf, lifeform_t *victim, char *attackernam
if (cansee(player, lf) || (victim && isplayer(victim))) { if (cansee(player, lf) || (victim && isplayer(victim))) {
int needfree = B_FALSE; int needfree = B_FALSE;
char *verb; char *verb;
char withwep[BUFLEN]; char withwep[BUFLEN],adjective[BUFLEN],hitwhere[BUFLEN];
char nodamstr[BUFLEN]; char nodamstr[BUFLEN];
int nodam = B_FALSE; int nodam = B_FALSE;
int col; int col;
@ -334,11 +348,18 @@ char *construct_hit_string(lifeform_t *lf, lifeform_t *victim, char *attackernam
} else { } else {
col = C_GREY; col = C_GREY;
} }
snprintf(retbuf, BUFLEN, "^%d%s %s%s%s %s%s%s%c", col, buf,
usecrittext ? "critically " : "", verb, strcpy(adjective, "");
needses(verb) ? "es" : "s", if (usecrittext) {
usecrittext ? victimbpname : locvictimname,withwep, nodamstr, strcat(adjective, "critically ");
backstab ? '!' : '.'); strcpy(hitwhere, victimbpname);
} else {
strcpy(hitwhere, locvictimname);
}
snprintf(retbuf, BUFLEN, "^%d%s %s%s%s %s%s%s%c", col, buf, adjective,
verb, needses(verb) ? "es" : "s",
hitwhere, withwep, nodamstr, backstab ? '!' : '.');
if (needfree) { if (needfree) {
free(verb); free(verb);
} }