- [+] fire skeleton shouldn't be immune to cold

- [+] if monster dodges your first atatack, cancel the second!
- [+] make god anger/happiness fade over time, unless they are enraged
      (1 per turn ?)
    - [+] chance of fading is 1 in (abs(piety)/100)
- [+] don't include " [tried] when dumping bones!
- [+] "repair all"!
    - [+] implement repairall
    - [+] make repairall like eating (auto action)
- [+] time taken when you fall down should be longer
- [+] F_STAYINROOM monsters will go back to their lair if they ahve no
      target.
- [+] more object decay in bones files:
    - [+] blood splashes/pools become blood stines
    - [+] all objects have a 1/4 chance of vanishing (someone picked
          them up)
- [+] resting should only please glorana if your'e actually worshipping
      her!
- [+] exploit: stand outside jimbo's room and pelt him! fixed.
- [+] random "behaviours" for more/less hp
- [+] around dlev 8-9, monsters are too easy.  at this point i'm
      dealing 10-20 damage per hit.
    - [+] give monsters a "Challenge Rating" seperate to their hitdice.
    - [+] instead of gethitdice(), use getcr()
    - [+] change dumpmonsters
    - [+] use cr() to determine what monsters will appear, not hit dice.
    - [+] that way i can have certain mosnters have more hp, but still
          appear higher in the dungeon
    - [+] initially, assign CRs based on hit dice
    - [+] when rolling hitdice for monsters, always give maximum, then
          go up/down by 15%
- [+] monsters shoiuld always know spells from their spellbooks.
This commit is contained in:
Rob Pearce 2012-03-06 10:47:26 +00:00
parent 80b87dfd78
commit 95e470238e
22 changed files with 1087 additions and 289 deletions

39
ai.c
View File

@ -76,7 +76,7 @@ int aiattack(lifeform_t *lf, lifeform_t *victim, int timelimit) {
penalty = (getcelldist(lf->cell, victim->cell)-1);
if (penalty < 0) penalty = 0;
penalty *= 3;
checkpassed = skillcheckvs(lf, SC_IQ, -penalty, victim, SC_WILL, 5+gethitdice(victim));
checkpassed = skillcheckvs(lf, SC_IQ, -penalty, victim, SC_WILL, 5+gettr(victim));
}
if (!checkpassed) {
@ -655,6 +655,7 @@ flag_t *aigoto(lifeform_t *lf, cell_t *c, enum MOVEREASON why, void *data, int t
db = B_TRUE;
}
if (lfhasflagval(lf, F_DOESNTMOVE, NA, NA, B_TRUE, NULL)) return NULL;
if (lfhasflagval(lf, F_IGNORECELL, c->x, c->y, NA, NULL)) {
char lfname[BUFLEN];
@ -756,26 +757,22 @@ int ai_bored(lifeform_t *lf, lifeform_t *master, int icanattack) {
}
}
// shopkeepers will return to their shops
/*
if (hasjob(lf, J_SHOPKEEPER)) {
f = lfhasflag(lf, F_OWNSSHOP);
if (f) {
int myshop;
cell_t *where;
myshop = f->val[0];
// find the closest cell of my shop
where = getclosestroomcell(lf, myshop);
// move towards my shop. note that if the player leaves then
// re-enters this map, they will find that we have instantly
// teleported there (see mapentereffects).
if (aigoto(lf, where, MR_OTHER, NULL, PERMENANT)) {
// success
return B_TRUE;
}
// monsters will return to their lairs
f = lfhasflag(lf, F_STAYINROOM);
if (f && (f->val[0] != NA)) {
int roomid;
cell_t *where;
roomid = f->val[0];
// find the closest cell of my home room
where = getclosestroomcell(lf, roomid);
// move towards my shop. note that if the player leaves then
// re-enters this map, they will find that we have instantly
// teleported there (see mapentereffects).
if (aigoto(lf, where, MR_OTHER, NULL, PERMENANT)) {
// success
return B_TRUE;
}
}
*/
if (!lfhasflag(lf, F_STUNNED)) {
lifeform_t *hateposs[MAXCANDIDATES],*poss[MAXCANDIDATES];
@ -1296,6 +1293,8 @@ int ai_movement(lifeform_t *lf) {
flag_t *f;
if (lfhasflag(lf, F_DEBUG)) db = B_TRUE;
if (lfhasflagval(lf, F_DOESNTMOVE, NA, NA, B_TRUE, NULL)) return B_FALSE;
// do we have a target cell?
f = hasflag(lf->flags, F_TARGETCELL);
if (!f) return B_FALSE;
@ -1632,7 +1631,7 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) {
// want to move but our race doesn't move?
if (lfhasflag(lf, F_DOESNTMOVE)) {
if (db) dblog(".oO { want to move towards target but have f_doesntmove - abandonning target. }");
if (db) dblog(".oO { want to move towards target but have f_doesntmove - abandoning target. }");
loseaitargets(lf);
return B_TRUE;
}

View File

@ -306,7 +306,7 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
!lfhasflag(lf, F_RAGE)) {
char obname[BUFLEN],wepname[BUFLEN],buf[BUFLEN];
char ch;
real_getobname(o, obname, o->amt, B_NOPREMODS, B_NOCONDITION, B_BLINDADJUST, B_NOBLESSINGS, B_NOSHOWALL);
real_getobname(o, obname, o->amt, B_NOPREMODS, B_NOCONDITION, B_BLINDADJUST, B_NOBLESSINGS, B_NOUSED, B_NOSHOWALL);
getobname(priwep, wepname, priwep->amt);
snprintf(buf, BUFLEN, "Attacking %s might damage your %s. Proceed?", obname, noprefix(wepname));
ch = askchar(buf, "yn","n", B_TRUE, B_FALSE);
@ -489,7 +489,7 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
if (attacklf(lf, victim, wep[i], damflag[i])) {
// failed
// failed, or victim died/dodged
attacksdone = maxattacks;
break;
}
@ -777,7 +777,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
armour = getequippedob(victim->pack, critpos);
if (armour) {
char armname[BUFLEN];
real_getobname(armour, armname, 1, B_NOPREMODS, B_NOCONDITION, B_BLINDADJUST, B_NOBLESSINGS, B_NOSHOWALL);
real_getobname(armour, armname, 1, B_NOPREMODS, B_NOCONDITION, B_BLINDADJUST, B_NOBLESSINGS, B_NOUSED, B_NOSHOWALL);
sprintf(noun, "%s", noprefix(armname));
} else {
sprintf(noun, "%s", getbodypartname(victim, critpos));
@ -895,7 +895,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
// backstab?
if (willbackstab(lf, victim, wep)) {
addflag(victim->flags, F_STABBEDBY, lf->id, NA, NA, NULL);
//addflag(victim->flags, F_STABBEDBY, lf->id, NA, NA, NULL);
dam[0] *= (getskill(lf, SK_BACKSTAB));
firstisbackstab = B_TRUE;
}
@ -977,9 +977,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
damtype[i] = DT_HOLY;
}
sprintf(attackname, "%s%s attack", attackername, getpossessive(attackername));
//difficulty = 20 + ((gethitdice(lf) - gethitdice(victim)) );
//difficulty = 20 + gethitdice(lf);
difficulty = 24 + gethitdice(victim) - gethitdice(lf);
difficulty = 24 + gettr(victim) - gettr(lf);
if (check_for_block(lf, victim, dam[i], damtype[i], difficulty, attackname)) {
blocked = B_TRUE;
break; // stop processing damage now.
@ -1146,7 +1144,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
// get name of weapon/attacker, for "killedby" text
if (wep && !isunarmed) {
char wepname[BUFLEN];
real_getobname(wep, wepname, 1, B_PREMODS, B_NOCONDITION, B_NOBLINDADJUST, B_BLESSINGS, B_NOSHOWALL);
real_getobname(wep, wepname, 1, B_PREMODS, B_NOCONDITION, B_NOBLINDADJUST, B_BLESSINGS, B_NOUSED, B_NOSHOWALL);
/*
snprintf(buf, BUFLEN, "%s^%s %s",attackername2,
(lf == victim) ? "using" : "weilding",
@ -1188,6 +1186,9 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
if (strstr(buf, "behead")) {
// we'll need to place the severed head object
addflag(victim->flags, F_BEHEADED, B_TRUE, NA, NA, NULL);
addflag(victim->flags, F_MUTILATED, B_TRUE, NA, NA, NULL);
} else if (strstr(buf, "bisect")) {
addflag(victim->flags, F_MUTILATED, B_TRUE, NA, NA, NULL);
}
if ((isplayer(lf) || cansee(player, victim)) && !hasflag(victim->flags, F_NODEATHANNOUNCE)) {
if (!hasflag(victim->flags, F_PHANTASM)) {
@ -1243,7 +1244,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
// now handle the extra hp loss effects which we postponed above.
losehpeffects(victim, dam[i], damtype[i], lf, wep, B_NORETALIATE, waskod, &waskod, prebleed);
if (fatal || waskod) break; // stop now!
if (fatal || waskod || dodged) break; // stop now, don't process further damtypes!
} // end foreach damtype
if (waskod) {
@ -1432,6 +1433,11 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
}
}
if (fatal || waskod || dodged) {
// don't keep attacking if the victim is dead, or moved!
return B_TRUE;
}
if (aidb) dblog(".oO { doattack about to return B_FALSE }");
return B_FALSE;
}
@ -1767,7 +1773,7 @@ int check_for_block(lifeform_t *lf, lifeform_t *victim, int dam, enum DAMTYPE da
char victimname[BUFLEN];
getlfname(victim, victimname);
// announce
real_getobname(shield[i], shname, 1, B_PREMODS, B_NOCONDITION, B_BLINDADJUST, B_NOBLESSINGS, B_NOSHOWALL);
real_getobname(shield[i], shname, 1, B_PREMODS, B_NOCONDITION, B_BLINDADJUST, B_NOBLESSINGS, B_NOUSED, B_NOSHOWALL);
if (isplayer(lf)) { // player is atatcking
msg("%s blocks %s with %s.", victimname, attackname, shname);
} else if (cansee(player, lf) || cansee(player, victim)) { // monster is attacking

569
data.c

File diff suppressed because it is too large Load Diff

Binary file not shown.

30
defs.h
View File

@ -161,10 +161,13 @@
#define B_NOBLINDADJUST (0)
#define B_BLESSINGS (-1)
#define B_NOBLESSINGS (0)
#define B_USED (-1)
#define B_NOUSED (0)
#define B_SHOWALL (-1)
#define B_NOSHOWALL (0)
// Limits
// must be >= max # of spells/abilities AND
@ -923,6 +926,7 @@ enum RACECLASS {
RC_GOD,
RC_HUMANOID,
RC_INSECT,
RC_ROBOT,
RC_SLIME,
RC_MAGIC,
RC_OTHER,
@ -946,6 +950,11 @@ enum RACE {
R_ELF,
R_HUMAN,
R_MAMMOAN,
// robots
R_ANDROID,
R_BOTRIOT,
R_BOTSECURITY,
R_FLAMETURRET,
// human monsters
R_BANDITLDR,
R_BANDIT,
@ -989,7 +998,9 @@ enum RACE {
R_KOBOLD,
R_LEPRECHAUN,
R_LIZARDMAN,
R_MALIK,
R_MINOTAUR,
R_OGRA,
R_OGRE,
R_OGREWARHULK,
R_OOZEGREY,
@ -1016,7 +1027,9 @@ enum RACE {
R_TRICLOPS,
R_TROGLODYTE,
R_TROLL,
R_TROLLKIN,
R_TROLLSNOW,
R_TROLLSWAMP,
R_VAMPIRE,
R_XAT,
// fish
@ -1033,6 +1046,7 @@ enum RACE {
R_FUNGUSRAGE,
R_NUTTER,
R_SAWGRASS,
R_UNYON,
// animals
R_ANT,
R_ANTS,
@ -1071,6 +1085,7 @@ enum RACE {
R_SPIDER,
R_SPIDERFUNNELWEB,
R_SPIDERREDBACK,
R_SPIDERTOMB,
R_WOLFYOUNG,
R_WOLF,
R_WOLFWINTER,
@ -1113,6 +1128,7 @@ enum RACE {
R_GHOUL,
R_MUMMY,
R_MUMMYG,
R_REVENANT,
R_SKELETON,
R_SKELETONFIRE,
R_WRAITHICE,
@ -1739,6 +1755,7 @@ enum OBTYPE {
OT_GRENADESMOKE,
OT_MOTIONSCANNER,
OT_NVGOGGLES,
OT_POWERCORE,
OT_STYPTIC,
OT_TENT,
// tech l3
@ -2938,7 +2955,7 @@ enum FLAG {
// optional: v2 = mr_lf or mr_ob. text=lf or ob id.
F_PHANTASM, // this lf is a phantasm - can deal no damage, and
// uses v0 as a fake hp counter.
F_STABBEDBY, // lf has been stabbed by lfid v0. can't be stabbed
//F_STABBEDBY, // lf has been stabbed by lfid v0. can't be stabbed
// by them again until they go out of sight.
F_FLEEFROM, // lf will run away from this lf id
F_NOFLEEFROM, // lf can not get f_fleefrom lfid v0
@ -2966,6 +2983,9 @@ enum FLAG {
F_NODEATHANNOUNCE, // don't say 'the xx dies' if this lf dies
F_NODEATHSPEECH, // lf doesn't talk when dying
F_BEHEADED, // use special corpse drop code
F_MUTILATED, // this corpse has had its head removed, or been split
// in half. this will stop some monsters from
// reviving.
F_MOVESPEED, // override default move speed
F_ACTIONSPEED, // override default action speed
F_SPELLSPEED, // override default spellcast speed (ie. movespeed)
@ -2976,6 +2996,8 @@ enum FLAG {
F_NUMAPPEAR, // when randomly appearing, can have > 1. val[0] = min, val[1] = max
F_MINIONS, // val0 % chance of appearing with v1-v2 lf of type text
F_HITDICE, // text = xdy+z to roll for maxhp per level.
// if v0 is set, this overrides text as maxhp.
F_TR, // v0 = threat rating of this race.
F_MAXHPMOD, // maxhp = pctof(v0, maxhp)
F_MPDICE, // val0: # d4 to roll for maxmp per level. val1: +xx
F_JOB, // val0 = player's job
@ -3023,7 +3045,12 @@ enum FLAG {
// when v1 drops to 0, flag vanishes.
// for monsters
F_MPMOD, // this race gains/loses v0 mp each level
F_AUTOROTATE, // this race will rotate by v0 each turn (positive =
// clockwise).
// also means they won't respond to noises.
F_DOESNTMOVE, // this race doesn't move (but can still attack)
// if v2 is TRUE, it won't attack either, or even
// try to change its facing.
F_CANTALK, // this lf can talk, even if its raceclass normally
// wouldn't be able to.
F_AQUATIC, // this race can attack normally in water and suffers no
@ -3239,6 +3266,7 @@ enum FLAG {
F_EATING, // lf is eating obid v0
F_DIGGING, // v0/v1 = cell where lf is digging.
// v2 is how much to dig per turn.
F_REPAIRING, // text = obid of held item we are repairing.
F_TRAINING, // are we training? cleared on any action other than rest.
// v0 = current training amount
// v1 = training target.

View File

@ -4,8 +4,10 @@ defs.h:
data.c:
addraceclass(xxx)
add flags based on raceclass.
lf.c:
update cantalk(xxx)
update racecantalk(xxx)
ALSO:
add matching skill!
add matching lore skill!

9
flag.c
View File

@ -542,6 +542,15 @@ int countflags(flagpile_t *fp) {
return count;
}
int countflagsofid(flagpile_t *fp, enum FLAG fid) {
flag_t *f;
int count = 0;
for (f = fp->first ; f ; f = f->next) {
if (f->id == fid) count++;
}
return count;
}
// returns TRUE if knowingly gaining/losing this flag will
// interrupt player actions like resting, training or eating.
int flagcausesinterrupt(flag_t *f, enum GAINORLOSS gol ) {

1
flag.h
View File

@ -17,6 +17,7 @@ void checkflagpile(flagpile_t *fp);
int copyflag(flagpile_t *dst, flagpile_t *src, enum FLAG id);
void copyflags(flagpile_t *dst, flagpile_t *src, int lifetime);
int countflags(flagpile_t *fp);
int countflagsofid(flagpile_t *fp, enum FLAG fid );
int flagcausesinterrupt(flag_t *f, enum GAINORLOSS gol);
int flagcausesloscalc(enum FLAG fid);
int flagcausesredraw(lifeform_t *lf, enum FLAG fid);

4
god.c
View File

@ -726,7 +726,7 @@ enum PIETYLEV getpietylev(enum RACE rid, enum COLOUR *col, char *happiness) {
return PL_TOLERATED;
} else if (piety <= 199) { // 100 - 199
if (col) *col = C_GREY;
if (happiness) strcpy(happiness, "Indifferent");
if (happiness) strcpy(happiness, "Neutral");
return PL_INDIFFERENT;
} else if (piety <= 299) { // 200 - 299
if (col) *col = C_GREEN;
@ -1988,7 +1988,7 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
if (who && !areallies(lf, who)) {
if (isundead(who)) {
makepeaceful(who, god);
} else if (gethitdice(who) <= 4) {
} else if (gettr(who) <= 4) {
// instakill
who->lastdamtype = DT_NECROTIC;
setlastdam(who, "Hecta's finger of death.");

29
io.c
View File

@ -781,7 +781,7 @@ cell_t *askcoords(char *prompt, char *subprompt, int targettype, lifeform_t *src
if (o) {
char obname[BUFLEN];
char buf2[BUFLEN];
real_getobname(o, obname, o->amt, B_NOPREMODS, B_NOCONDITION, B_BLINDADJUST, B_NOBLESSINGS, B_NOSHOWALL);
real_getobname(o, obname, o->amt, B_NOPREMODS, B_NOCONDITION, B_BLINDADJUST, B_NOBLESSINGS, B_NOUSED, B_NOSHOWALL);
if (strlen(extrainfo)) strcat(extrainfo, ", ");
snprintf(buf2, BUFLEN, "stuck in %s",obname);
strcat(extrainfo, buf2);
@ -1498,10 +1498,10 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
break;
case F_HEAVENARM:
if (isplayer(lf)) { // don't know if monsters get it
msg("You are surrounded by a shell of divine armour!");
msg("You are surrounded by a %s!", f->text);
donesomething = B_TRUE;
} else {
msg("%s is surrounded by a shell of divine armour!", lfname);
msg("%s is surrounded by a %s!", lfname, f->text);
donesomething = B_TRUE;
}
break;
@ -2226,10 +2226,10 @@ int announceflagloss(lifeform_t *lf, flag_t *f) {
break;
case F_HEAVENARM:
if (isplayer(lf)) { // don't know if monsters get it
msg("Your shell of divine armour vanishes!");
msg("Your %s vanishes!", f->text);
donesomething = B_TRUE;
} else {
msg("%s%s shield of divine armour vanishes!", lfname, getpossessive(lfname));
msg("%s%s %s vanishes!", lfname, getpossessive(lfname), f->text);
donesomething = B_TRUE;
}
break;
@ -2590,7 +2590,7 @@ int announceobflaggain(object_t *o, flag_t *f) {
wantpremods = B_FALSE;
}
real_getobname(o, obname, o->amt, wantpremods, B_NOPREMODS, B_CONDITION, B_BLESSINGS, B_NOSHOWALL);
real_getobname(o, obname, o->amt, wantpremods, B_NOPREMODS, B_CONDITION, B_BLESSINGS, B_NOUSED, B_NOSHOWALL);
if (o->pile->owner) {
@ -2643,7 +2643,7 @@ void announceobflagloss(object_t *o, flag_t *f) {
if (!haslos(player, loc)) {
return;
}
real_getobname(o, obname, o->amt, B_PREMODS, B_NOCONDITION, B_BLINDADJUST, B_BLESSINGS, B_NOSHOWALL);
real_getobname(o, obname, o->amt, B_PREMODS, B_NOCONDITION, B_BLINDADJUST, B_BLESSINGS, B_NOUSED, B_NOSHOWALL);
if (o->pile->owner) {
if (isplayer(o->pile->owner)) {
@ -4636,7 +4636,7 @@ void docomms_areadangers(char *who, flagpile_t *fp, lifeform_t *lf) {
}
// veryrare monsters
if (strchr(knowflag->text, 'm')) {
gethitdicerange(getmapdifficulty(player->cell->map), &min,&max, RARITYVARIANCELF, B_FALSE);
gettrrange(getmapdifficulty(player->cell->map), &min,&max, RARITYVARIANCELF, B_FALSE);
ndone = 0;
for (y = 0; y < player->cell->map->h ; y++) {
@ -4651,7 +4651,7 @@ void docomms_areadangers(char *who, flagpile_t *fp, lifeform_t *lf) {
} else {
// out of depth monsters?
int hd;
hd = gethitdicerace(c->lf->race);
hd = gettrrace(c->lf->race);
if (hd > max) {
showit = B_TRUE;
}
@ -6819,7 +6819,7 @@ char *makedesc_race(enum RACE rid, char *retbuf, int showextra, int forplayersel
sprintf(bonheading, "^%dStrengths^n:\n", C_WHITE);
sprintf(penheading, "^%dWeaknesses^n:\n", C_WHITE);
// stats
snprintf(buf, HUGEBUFLEN, "HD: %-3d ", gethitdicerace(r));
snprintf(buf, HUGEBUFLEN, "HD: %-3d ", gettrrace(r));
strncat(retbuf, buf, HUGEBUFLEN);
for (a = 0; a < MAXATTS; a++) {
char ch[BUFLENTINY];
@ -7109,6 +7109,7 @@ char *makedesc_race(enum RACE rid, char *retbuf, int showextra, int forplayersel
case F_MPMOD: if (f->val[0] < 0) sprintf(buf, "%d Mana", f->val[0]); break;
case F_NEEDSWATER: if (lorelev >= PR_NOVICE) sprintf(buf, "Will suffocate without water"); break;
case F_NOCTURNAL: if ((lorelev >= PR_BEGINNER) && !forplayersel) sprintf(buf, "Sleeps during the day."); break;
case F_NOSPELLS: if (lorelev >= PR_NOVICE) sprintf(buf, "Cannot use magic."); break;
case F_NOPACK: sprintf(buf, "Cannot carry objects."); break;
case F_SIZE:
if (hasflag(r->flags, F_HUMANOID) && (f->val[0] != SZ_HUMAN)) {
@ -11075,7 +11076,7 @@ void showlfstats(lifeform_t *lf, int showall) {
xpneeded = getxpforlev(lf->level + 1) - lf->xp;
wprintw(mainwin, "%d (%ld XP, %ld for next)", lf->level, lf->xp, xpneeded); y++;
} else {
wprintw(mainwin, "%d", gethitdice(lf)); y++;
wprintw(mainwin, "%d", gettr(lf)); y++;
}
}
@ -12011,11 +12012,11 @@ void showlfstats(lifeform_t *lf, int showall) {
}
getspellname(ot->id, lf, spellname, B_FALSE);
if (castable) setcol(mainwin, C_GREEN);
if (castable || !isplayer(lf)) setcol(mainwin, C_GREEN);
else setcol(mainwin, C_RED);
snprintf(buf, BUFLEN, " %-4d%-26s%-15s%-13s%s",thislev, spellname, getschoolnameshort(getspellschoolknown(lf, ot->id)), powerbuf, mpbuf);
mvwprintw(mainwin, y, 0, "%s\n", buf);
if (castable) unsetcol(mainwin, C_GREEN);
if (castable || !isplayer(lf)) unsetcol(mainwin, C_GREEN);
else unsetcol(mainwin, C_RED);
anyfound = B_TRUE;
if (downline(&y, h, "MAGIC", subheading, promptstr, cmdchars, &ch)) {
@ -12809,7 +12810,7 @@ void showlfstats(lifeform_t *lf, int showall) {
} else {
strcpy(hpbuf, "");
}
mvwprintw(mainwin, y, 0, "%s %s surrounded by a shell of divine armour.%s", you(lf), is(lf), hpbuf);
mvwprintw(mainwin, y, 0, "%s %s surrounded by a %s. %s", you(lf), is(lf), f->text, hpbuf);
y++;
}
f = lfhasknownflag(lf, F_INVULNERABLE);

309
lf.c
View File

@ -274,9 +274,8 @@ void breakaitargets(lifeform_t *lf, int onlylowerlev) {
lifeform_t *l;
for (l = lf->cell->map->lf ; l ; l = l->next) {
flag_t *f;
//if ((l != lf) && (gethitdice(l) <= gethitdice(lf)) ) {
if (l == lf) continue;
if (!onlylowerlev || (gethitdice(l) <= gethitdice(lf)) ) {
if (!onlylowerlev || (gettr(l) <= gettr(lf)) ) {
f = lfhasflagval(l, F_TARGETLF, lf->id, NA, NA, NULL);
if (f) killflag(f);
f = lfhasflagval(l, F_TARGETCELL, lf->cell->x, lf->cell->y, NA, NULL);
@ -2309,6 +2308,61 @@ int continuedigging(lifeform_t *lf) {
return B_FALSE;
}
int continuerepairing(lifeform_t *lf, flag_t *repairflag) {
object_t *helpob,*o;
char helpobname[BUFLEN];
flag_t *f;
o = findobbyid(lf->pack, atol(repairflag->text));
if (!o) {
killflag(repairflag);
return B_TRUE;
}
// in case it's on fire, etc
if (touch(lf, o)) {
taketime(lf, getactspeed(lf));
return B_FALSE;
}
// get helper ob
helpob = getworkhelpob(lf->pack, o->material->id);
if (helpob) {
real_getobname(helpob, helpobname, helpob->amt, B_PREMODS, B_NOCONDITION, B_BLINDADJUST, B_BLESSINGS, B_NOUSED, B_NOSHOWALL);
} else {
strcpy(helpobname, "");
}
// fully repair it.
f = hasflag(o->flags, F_OBHP);
f->val[0] = f->val[1];
if (isplayer(lf)) {
char obname[BUFLEN],withbuf[BUFLEN];
real_getobname(o, obname, o->amt, B_PREMODS, B_NOCONDITION, B_BLINDADJUST, B_BLESSINGS, B_NOUSED, B_NOSHOWALL);
if (helpob) sprintf(withbuf, " (with %s)", helpobname);
else strcpy(withbuf, "");
msg("You repair your %s%s.", noprefix(obname), withbuf);
} else if (cansee(player, lf)) {
char obname[BUFLEN],withbuf[BUFLEN];
char lfname[BUFLEN];
getlfname(lf, lfname);
real_getobname(o, obname, o->amt, B_PREMODS, B_NOCONDITION, B_BLINDADJUST, B_BLESSINGS, B_NOUSED, B_NOSHOWALL);
if (helpob) sprintf(withbuf, " with %s", helpobname);
else strcpy(withbuf, "");
msg("%s repairs %s%s.", lfname, obname, withbuf);
}
practice(lf, SK_METALWORK, 1);
practice(lf, SK_SEWING, 1);
// take some time.
taketime(lf, getactspeed(lf));
// finished repairing this object now.
killflag(repairflag);
return B_FALSE;
}
int countinnateattacks(lifeform_t *lf) {
int count = 0,i;
@ -2389,7 +2443,7 @@ int demandbribe(lifeform_t *lf) {
int satisfied = B_FALSE;
int i,heard;
hd = gethitdice(lf);
hd = gettr(lf);
gold = hasob(player->pack, OT_GOLD);
if (gold) {
totmoney = countmoney(player->pack);
@ -2509,6 +2563,26 @@ void die(lifeform_t *lf) {
needredraw = B_TRUE;
}
// prevent rising from dead?
switch (lf->race->id) {
case R_REVENANT:
if ((lf->lastdamtype == DT_HOLY) || lfhasflag(lf, F_MUTILATED)) {
killflagsofid(lf->flags, F_REVIVETIMER);
}
break;
case R_TROLL:
if (basedamagetype(lf->lastdamtype) == DT_FIRE) {
killflagsofid(lf->flags, F_REVIVETIMER);
}
break;
default:
break;
}
if (lf->lastdamtype == DT_HOLY) {
killflagsofid(lf->flags, F_RISEASGHOST);
}
if (lfhasflag(lf, F_RISEASGHOST)) {
willbecomeghost = B_TRUE;
}
@ -2622,6 +2696,7 @@ void die(lifeform_t *lf) {
}
}
if (!willbecomeghost) {
lf->alive = B_FALSE;
}
@ -2882,9 +2957,13 @@ void die(lifeform_t *lf) {
colourmatchob(corpse, lf);
}
// inherit lifeform knowledge in case we raise it
// inherit lifeform knowledge and abilities in case we raise it
copyflag(corpse->flags, lf->flags, F_KNOWSABOUT);
copyflag(corpse->flags, lf->flags, F_HOMEMAP);
copyflag(corpse->flags, lf->flags, F_CANCAST);
copyflag(corpse->flags, lf->flags, F_CANWILL);
copyflag(corpse->flags, lf->flags, F_JOB);
f = hasflag(corpse->flags, F_CORPSEOF);
if (f) {
@ -2929,6 +3008,15 @@ void die(lifeform_t *lf) {
if (f) {
changeflagtext(f, lf->lastdam);
}
if (hasflag(corpse->flags, F_HEADLESS)) {
object_t *headob;
char headname[BUFLEN];
// drop head too
snprintf(headname, BUFLEN, "%s head",lf->race->name);
headob = addob(corpsecell->obpile, headname);
colourmatchob(headob, lf);
}
}
// For bones files:
@ -2948,16 +3036,6 @@ void die(lifeform_t *lf) {
}
if (hasflag(corpse->flags, F_HEADLESS)) {
object_t *headob;
char headname[BUFLEN];
// drop head too
snprintf(headname, BUFLEN, "%s head",lf->race->name);
headob = addob(corpsecell->obpile, headname);
colourmatchob(headob, lf);
}
if (lf->race->id == R_SPRITEFIRE) {
addobfast(corpsecell->obpile, OT_FIRESMALL);
}
@ -3190,12 +3268,12 @@ void dumpmonsters(void) {
int count = 0,wanthd;
dblog("START MONSTER DUMP:");
for (wanthd = 0; wanthd < maxmonhitdice ; wanthd++) {
dblog("%d HIT DICE MONSTERS:",wanthd);
for (wanthd = 0; wanthd <= maxmonhitdice ; wanthd++) {
dblog("MONSTERS WITH THREAT RATING %d:",wanthd);
for (r = firstrace ; r ; r = r->next) {
int thishd;
thishd = gethitdicerace(r);
thishd = gettrrace(r);
if (thishd == wanthd) {
int ndice,nsides,bonus,min,max;
f = hasflag(r->flags, F_HITDICE);
@ -3203,7 +3281,7 @@ void dumpmonsters(void) {
min = ndice + bonus;
max = (ndice*nsides) + bonus;
dblog("\t%s (%d avg hp)",r->name, (min+max)/2);
dblog("\t%s (%d hp)",r->name, max);
count++;
}
}
@ -3578,12 +3656,12 @@ void dumplev(void) {
// NOTE: this code copied from getrandomrace(), which is used by addmonster().
for (i = 1; i <= 25; i++) {
int min,max,prevmin,prevmax;
gethitdicerange(i-1, &prevmin, &prevmax, RARITYVARIANCELF, B_FALSE);
gethitdicerange(i, &min, &max, RARITYVARIANCELF, B_FALSE);
gettrrange(i-1, &prevmin, &prevmax, RARITYVARIANCELF, B_FALSE);
gettrrange(i, &min, &max, RARITYVARIANCELF, B_FALSE);
fprintf(logfile, "Dlev %d (hd %d-%d): ",i,min,max);
for (r = firstrace ; r; r = r->next) {
int hd = 0;
hd = gethitdicerace(r);
hd = gettrrace(r);
// ok this lev?
if ((hd >= min) && (hd <= max)) {
char buf[BUFLEN];
@ -4862,7 +4940,8 @@ int fall(lifeform_t *lf, lifeform_t *fromlf, int announce) {
}
}
}
//taketime(lf, SP_NORMAL*2);
taketime(lf, SP_NORMAL);
addflag(lf->flags, F_PRONE, B_TRUE, NA, NA, NULL);
loseconcentration(lf);
@ -6422,7 +6501,7 @@ int getevasion(lifeform_t *lf) {
}
// level based evasion
level_ev = gethitdice(lf);
level_ev = gettr(lf);
ev += level_ev;
// dexterity mod
@ -6780,22 +6859,15 @@ int gethearingrange(lifeform_t *lf) {
return range;
}
int gethitdice(lifeform_t *lf) {
if (isplayer(lf) || lfhasflag(lf, F_VARLEVEL)) {
return lf->level;
}
return (lf->maxhp / 4);
}
int gethitdicerace(race_t *r) {
int gettrrace(race_t *r) {
flag_t *f;
f = hasflag(r->flags, F_HITDICE);
if (f) {
f = hasflag(r->flags, F_TR);
/*
int ndice,nsides,bonus;
texttodice(f->text ? f->text : DEF_HITDICE, &ndice,&nsides,&bonus);
return ((ndice*nsides)+bonus) / 4;
}
return 1;
*/
return f->val[0];
}
int gethitstokill(lifeform_t *lf, lifeform_t *victim, int useevasion, int usearmour) {
@ -7781,7 +7853,7 @@ int getmr(lifeform_t *lf) {
sumflags(lf->flags, F_RESISTMAG, &amt, NULL, NULL);
if (hassubjob(lf, SJ_SCOURGE)) {
amt += (gethitdice(lf) * 3);
amt += (gettr(lf) * 3);
}
return amt;
@ -8115,7 +8187,7 @@ char *real_getlfname(lifeform_t *lf, char *buf, int usevis, int showall) {
wep = getweapon(lf);
if (wep) {
char obname[BUFLEN];
real_getobname(wep, obname, 1, B_PREMODS, B_NOCONDITION, B_NOBLINDADJUST, B_NOBLESSINGS, B_NOSHOWALL);
real_getobname(wep, obname, 1, B_PREMODS, B_NOCONDITION, B_NOBLINDADJUST, B_NOBLESSINGS, B_NOUSED, B_NOSHOWALL);
snprintf(buf, BUFLEN, "%s%s%s",the,descstring,noprefix(obname));
} else {
snprintf(buf, BUFLEN, "%s%s%s%s",the,descstring,lname,jobstring);
@ -8611,7 +8683,7 @@ race_t *getrandomrace(cell_t *c, int forcedepth) {
depth = rnd(1,MAXDEPTH);
}
gethitdicerange(depth, &hdmin, &hdmax, RARITYVARIANCELF, B_TRUE);
gettrrange(depth, &hdmin, &hdmax, RARITYVARIANCELF, B_TRUE);
// pick rr...
wantrr = pickrr(TT_MONSTER);
@ -8628,7 +8700,7 @@ race_t *getrandomrace(cell_t *c, int forcedepth) {
enum RARITY thisrr = RR_NEVER;
flag_t *rarflag = NULL;
thishd = gethitdicerace(r);
thishd = gettrrace(r);
if ((thishd < hdmin) || (thishd > hdmax)) {
valid = B_FALSE;
} else {
@ -9057,6 +9129,18 @@ int getteachableskills(lifeform_t *teacher, lifeform_t *student, int *info, enum
return *ninfo;
}
// get threat rating
int gettr(lifeform_t *lf) {
flag_t *f;
if (isplayer(lf) || lfhasflag(lf, F_VARLEVEL)) {
return lf->level;
}
f = hasflag(lf->flags, F_TR);
return f->val[0];
//return (lf->maxhp / 4);
}
char *gettradeinfoname(int what, enum TRADEINFOTYPE tradetype, char *buf) {
if (tradetype == TI_SKILL) {
skill_t *sk;
@ -9525,6 +9609,8 @@ void givejob(lifeform_t *lf, enum JOB jobid) {
}
generatealignment(lf);
if (hasflag(j->flags, F_STAYINROOM)) sethomeroom(lf);
}
void givesubjob(lifeform_t *lf, enum SUBJOB sj) {
@ -9683,14 +9769,32 @@ void givesubjob(lifeform_t *lf, enum SUBJOB sj) {
}
if (sb1) {
addtempflag(lf->flags, F_CANCAST, sb1->contents->first->type->id, NA, NA, NULL, FROMJOB);
if (isplayer(lf)) {
addtempflag(lf->flags, F_CANCAST, sb1->contents->first->type->id, NA, NA, NULL, FROMJOB);
addtempflag(lf->flags, F_SHORTCUT, getnextshortcut(lf), NA, NA, sb1->contents->first->type->name, FROMJOB);
addflag(sb1->flags, F_NOPOINTS, B_TRUE, NA, NA, NULL);
identify(sb1);
} else {
object_t *o;
// monster generally know all spells from the book
for (o = sb1->contents->first ; o ; o = o->next) {
int lev;
lev = getspelllevel(o->type->id);
if (!cancast(lf, o->type->id, NULL) && (gettr(lf) >= lev)) {
int pow;
char pwbuf[BUFLEN];
pow = MINOF((gettr(lf)/2), getspellmaxpower(o->type->id));
sprintf(pwbuf, "pw:%d;", pow);
addflag(lf->flags, F_CANCAST, o->type->id, NA, NA, pwbuf);
}
}
// chance of spellbook vanishing
if (pctchance(66)) {
killob(sb1);
sb1 = NULL;
}
}
identify(sb1);
}
}
@ -12420,6 +12524,10 @@ lifeform_t *real_addlf(cell_t *cell, enum RACE rid, int level, int controller) {
//
a->losdirty = B_TRUE;
addflag(a->flags, F_HOMEMAP, cell->map->id, NA, NA, NULL);
// set home room.
sethomeroom(a);
return a;
}
@ -13078,7 +13186,7 @@ int askforinfo(lifeform_t *lf, int diffmod) {
diffmod += 15;
}
difficulty = 20 + diffmod + ((gethitdice(player) - gethitdice(lf))*2);
difficulty = 20 + diffmod + ((gettr(player) - gettr(lf))*2);
if (real_skillcheck(player, SC_SPEECH, difficulty, alignmod, &result)) {
askingprice = 0;
// passed - free!
@ -13088,7 +13196,7 @@ int askforinfo(lifeform_t *lf, int diffmod) {
askingprice = -1;
} else {
// will help for gold
askingprice = rnd(gethitdice(lf)*5, gethitdice(lf)*15 );
askingprice = rnd(gettr(lf)*5, gettr(lf)*15 );
limit(&askingprice, 1, NA); // just in case
}
}
@ -13237,7 +13345,7 @@ void autoskill(lifeform_t *lf) {
slev = PR_NOVICE;
} else {
int max;
max = gethitdice(lf)/3;
max = gettr(lf)/3;
limit(&max, PR_NOVICE, PR_MASTER);
slev = rnd(PR_NOVICE, max);
}
@ -13347,7 +13455,7 @@ void autospells(lifeform_t *lf, int howmany) {
spellid = poss[sel];
sprintf(pwbuf, "pw:%d;",powerposs[sel]);
//addflag(lf->flags, F_CANCAST, sel, NA, NA, pwbuf);
addflag(lf->flags, F_CANWILL, spellid, NA, NA, pwbuf);
addflag(lf->flags, F_CANCAST, spellid, NA, NA, pwbuf);
// remove this one...
for (n = sel; n < nposs-1; n++) {
poss[n] = poss[n+1];
@ -14128,12 +14236,17 @@ void losehpeffects(lifeform_t *lf, int dam, enum DAMTYPE damtype, lifeform_t *fr
char buf2[BUFLEN];
sprintf(buf, "^w%s releases a cloud of purple spores!", lfname);
sprintf(buf2, "^wSomething releases a cloud of purple spores!");
spellcloud(lf->cell, 3, UNI_SHADELIGHT, C_MAGENTA, OT_S_SLEEP, 8, B_TRUE, buf, buf2);
spellcloud(lf->cell, 3, UNI_SHADELIGHT, C_MAGENTA, OT_S_SLEEP, 8, B_TRUE, buf, buf2, B_FALSE);
} else if (lf->race->id == R_FUNGUSRAGE) {
char buf2[BUFLEN];
sprintf(buf, "^w%s releases a cloud of red spores!", lfname);
sprintf(buf2, "^wSomething releases a cloud of red spores!");
spellcloud(lf->cell, 3, UNI_SHADELIGHT, C_RED, OT_A_RAGE, 8, B_TRUE, buf, buf2);
spellcloud(lf->cell, 3, UNI_SHADELIGHT, C_RED, OT_A_RAGE, 8, B_TRUE, buf, buf2, B_FALSE);
} else if ((lf->race->id == R_UNYON) && ((damtype == DT_SLASH) || (damtype == DT_PIERCE))) {
char buf2[BUFLEN];
sprintf(buf, "^w%s releases a cloud of fumes!", lfname);
sprintf(buf2, "^wSomething releases a cloud of fumes!");
spellcloud(lf->cell, 3, UNI_SHADELIGHT, C_GREY, OT_S_BLINDNESS, 8, B_TRUE, buf, buf2, B_TRUE);
}
@ -14275,11 +14388,11 @@ void makefriendly(lifeform_t *who, int howlong) {
int makelearnable(lifeform_t *lf, enum SKILL skid) {
flag_t *f,*learnable;
int changed = B_FALSE;
f = hasflagval(lf->flags, F_NOSKILL, skid[i], NA, NA, NULL);
f = hasflagval(lf->flags, F_NOSKILL, skid, NA, NA, NULL);
if (f) {
killflag(f);
}
learnable = lfhasflagval(lf, F_CANLEARN, skid[i], NA, NA, NULL);
learnable = lfhasflagval(lf, F_CANLEARN, skid, NA, NA, NULL);
if (learnable) {
if (learnable->val[1] != NA) {
// able to learn thievery, but limitted
@ -14288,7 +14401,7 @@ int makelearnable(lifeform_t *lf, enum SKILL skid) {
}
} else if (!getskill(lf, SK_THIEVERY)) {
// don't have the skill, not learnable
addflag(lf->flags, F_CANLEARN, skid[i], NA, NA, NULL);
addflag(lf->flags, F_CANLEARN, skid, NA, NA, NULL);
changed = B_TRUE;
}
if (changed) {
@ -15078,10 +15191,10 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nclass, int volume,
// monsters will turn to face the sound, as long as they're
// not attacking something
if (!isplayer(l)) {
flag_t *f;
int willrespond = B_FALSE;
f = aihastarget(l);
if (f) {
if (lfhasflag(l, F_AUTOROTATE)) {
} else if (aihastarget(l)) {
// will probably ignore the sound...
if ((volume >= 5) && onein(2)) {
willrespond = B_TRUE;
@ -15820,7 +15933,7 @@ int recruit(lifeform_t *lf) {
int minmult,maxmult;
// since you have to be at least speech=4(skilled) to ask someone to
// join, add +8 to difficulty (pr_skilled * 2)
difficulty = 25 + 8 + ((gethitdice(player) - gethitdice(lf))*2);
difficulty = 25 + 8 + ((gettr(player) - gettr(lf))*2);
if (real_skillcheck(player, SC_SPEECH, difficulty, 0, &result)) {
minmult = 10;
maxmult = 20;
@ -15836,7 +15949,7 @@ int recruit(lifeform_t *lf) {
maxmult = 25;
}
}
askingprice = rnd(gethitdice(lf)*minmult, gethitdice(lf)*maxmult );
askingprice = rnd(gettr(lf)*minmult, gettr(lf)*maxmult );
addflag(lf->flags, F_HIREPRICE, askingprice, NA, NA, NULL);
}
@ -16857,6 +16970,19 @@ void setguntarget(lifeform_t *lf, lifeform_t *targ) {
}
}
void sethomeroom(lifeform_t *lf) {
flag_t *retflag[MAXCANDIDATES];
int nretflags = 0,i;
getflags(lf->flags, retflag, &nretflags, F_STAYINROOM, F_NONE);
for (i = 0; i < nretflags; i++) {
if (retflag[i]->val[1] == NA) {
if (lf->cell->room) {
retflag[i]->val[1] = getroomid(lf->cell);
}
}
}
}
void setkillverb(lifeform_t *lf, char *buf) {
if (lf->killverb) {
free(lf->killverb);
@ -17033,7 +17159,7 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
if ((i == 0) || !isplayer(lf)){
wantmax = B_TRUE;
}
lf->maxhp += rollhitdice(lf, B_TRUE);
lf->maxhp += rollhitdice(lf, wantmax);
assert(lf->maxhp > 0);
}
lf->hp = lf->maxhp;
@ -17387,7 +17513,7 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r
attrib = (getattr(lf, A_IQ) / 10) + lf->level;
break;
case SC_MORALE: // based on morale, level/hitdice and size.
attrib = getmorale(lf) + gethitdice(lf);
attrib = getmorale(lf) + gettr(lf);
attrib += getlfsize(lf);
break;
case SC_SLIP:
@ -17446,8 +17572,7 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r
}
// level modifier
//levmod = (gethitdice(lf) / 3);
levmod = (gethitdice(lf) / 2);
levmod = (gettr(lf) / 2);
// other modifiers
if (ct == SC_CLIMB) {
@ -18035,10 +18160,22 @@ void startlfturn(lifeform_t *lf) {
// god piety gets restored over time
if (isplayer(lf)) {
for (i = 0; i < ngodlfs; i++) {
int piety;
if (!godlf[i]) continue;
if (getpietylev(godlf[i]->race->id, NULL, NULL) == PL_TOLERATED) {
// slowly tick upwards
if (onein(2)) modpiety(godlf[i]->race->id, 1);
if (!godprayedto(godlf[i]->race->id)) continue;
piety = getpiety(godlf[i]->race->id);
if ((piety < 100) || (piety > 199)) {
int dir,chance;
if (piety < 100) {
dir = 1;
} else {
dir = -1;
}
chance = abs(piety) / 100;
if (onein(chance)) {
// slowly move towards zero
modpiety(godlf[i]->race->id, (piety < 0) ? 1 : -1);
}
}
}
}
@ -18202,6 +18339,33 @@ void startlfturn(lifeform_t *lf) {
}
}
f = lfhasflag(lf, F_AUTOROTATE);
if (f && (f->val[0] != 0)) {
if (!gettargetlf(lf)) {
int n,whichway;
if (f->val[0] > 0) whichway = 1;
else whichway = -1;
for (n = 0; n < abs(f->val[0]); n++) {
int newdir;
newdir = lf->facing + whichway;
if (newdir < DC_N) newdir = DC_NW;
if (newdir > DC_NW) newdir = DC_N;
setfacing(lf, newdir);
}
// announce
if (isplayer(lf)) {
msg("You turn to face %s.", getdirname(lf->facing));
} else if (cansee(player, lf)) {
char lfname[BUFLEN];
getlfname(lf, lfname);
msg("%s turns to face %s.", lfname, getdirname(lf->facing));
}
}
}
f = lfhasflag(lf, F_AUTOCREATEOB);
if (f) {
int radius;
@ -18271,7 +18435,7 @@ void startlfturn(lifeform_t *lf) {
int maxhitdice;
// calming strong enough?
maxhitdice = asp->val[2] + 1;
if (gethitdice(lf) <= maxhitdice) {
if (gettr(lf) <= maxhitdice) {
makepeaceful(lf, l);
}
}
@ -18681,7 +18845,7 @@ void startlfturn(lifeform_t *lf) {
// effects for/on your own flags
getflags(lf->flags, retflag, &nretflags, F_ANTICIPATE, F_ATTACHEDTO, F_CANWILL, F_CHARMEDBY, F_CLIMBING, F_FEIGNFOOLEDBY,F_FLEEFROM,
F_GRABBEDBY, F_GRABBING, F_HIDING, F_BOOSTSPELL, F_FEIGNINGDEATH, F_HPDRAIN, F_INJURY,
F_NOFLEEFROM, F_PETOF, F_SIZETIMER, F_SPOTTED, F_STABBEDBY, F_STRIKETOKO, F_TARGETCELL, F_TARGETLF, F_NONE);
F_NOFLEEFROM, F_PETOF, F_SIZETIMER, F_SPOTTED, F_STRIKETOKO, F_TARGETCELL, F_TARGETLF, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
// remove impossible/expired flags
@ -18765,6 +18929,7 @@ void startlfturn(lifeform_t *lf) {
}
}
/*
if (f->id == F_STABBEDBY) {
lifeform_t *lf2;
lf2 = findlf(NULL, f->val[0]);
@ -18774,6 +18939,7 @@ void startlfturn(lifeform_t *lf) {
continue;
}
}
*/
if (f->id == F_SPOTTED) {
lifeform_t *lf2;
lf2 = findlf(NULL, f->val[0]);
@ -19162,7 +19328,7 @@ lifeform_t *summonmonster(lifeform_t *caster, cell_t *c, enum RACE rid, char *ra
lifeform_t *newlf = NULL;
char buf[BUFLEN];
newlf = addmonster(c, rid, racename, B_FALSE, 1, B_FALSE, NULL);
newlf = addmonster(c, rid, racename, B_TRUE, 1, B_FALSE, NULL);
if (newlf) {
if (haslos(player, c)) {
//char *newbuf;
@ -19656,7 +19822,7 @@ int touch(lifeform_t *lf, object_t *o) {
o->blessknown = B_TRUE;
}
// use real name here...
real_getobname(o, obname, o->amt, B_PREMODS, B_NOCONDITION, B_NOBLINDADJUST, B_BLESSINGS, B_NOSHOWALL);
real_getobname(o, obname, o->amt, B_PREMODS, B_NOCONDITION, B_NOBLINDADJUST, B_BLESSINGS, B_NOUSED, B_NOSHOWALL);
snprintf(buf, BUFLEN, "touching %s",obname);
losehp(lf, 2, DT_HOLY, NULL, buf);
// drop the object if we're holding it
@ -19772,6 +19938,7 @@ int touch(lifeform_t *lf, object_t *o) {
void turntoface(lifeform_t *lf, cell_t *dstcell) {
if (isdead(lf)) return;
if (lfhasflag(lf, F_AUTOROTATE)) return;
// not providing srclf, since this will make getdirtowards() not include
// directions in which the next cell is unwalkable. in this case we're
// not actually walking there, so we don't care.
@ -20359,7 +20526,7 @@ int validateraces(void) {
givestartskills(lf, lf->flags);
// remember max. hitdice for use in dumpmonsters()
thishd = gethitdice(lf);
thishd = gettr(lf);
if (thishd > maxmonhitdice) {
maxmonhitdice = thishd;
}
@ -20368,6 +20535,10 @@ int validateraces(void) {
if (!hasflag(r->flags, F_SIZE)) {
printf("ERROR in race '%s' - missing F_SIZE.\n", r->name);
goterror = B_TRUE;
}
if (!hasflag(r->flags, F_TR)) {
printf("ERROR in race '%s' - missing F_TR (threat level).\n", r->name);
goterror = B_TRUE;
}
for (f = r->flags->first ; f ; f = f->next) {
@ -21566,7 +21737,7 @@ int willbackstab(lifeform_t *lf, lifeform_t *victim, object_t *wep) {
if (wep && (getdamtype(wep) == DT_PIERCE) && // stabbing weapon
getskill(lf, SK_BACKSTAB) && // able to backstab
!lfhasflagval(victim, F_STABBEDBY, lf->id, NA, NA, NULL) && // haven't stabbed them already
// !lfhasflagval(victim, F_STABBEDBY, lf->id, NA, NA, NULL) && // haven't stabbed them already
ishelplessvictim(victim, lf, NULL)) { // victim can't see us or is fleeing
return B_TRUE;
}

6
lf.h
View File

@ -76,6 +76,7 @@ float comparelfs(lifeform_t *lf1, lifeform_t *lf2);
int confuse(lifeform_t *lf, int howlong);
void copycorpseflags(flagpile_t *dst, flagpile_t *src);
int continuedigging(lifeform_t *lf);
int continuerepairing(lifeform_t *lf, flag_t *repairflag);
int countinnateattacks(lifeform_t *lf);
int countnearbyallies(lifeform_t *lf);
int countnearbyhurtallies(lifeform_t *lf);
@ -163,8 +164,7 @@ lifeform_t *getguntarget(lifeform_t *lf);
int getguntargetid(lifeform_t *lf);
//int gethealtime(lifeform_t *lf);
int gethearingrange(lifeform_t *lf);
int gethitdice(lifeform_t *lf);
int gethitdicerace(race_t *r);
int gettrrace(race_t *r);
int gethitstokill(lifeform_t *lf, lifeform_t *victim, int useevasion, int usearmour);
int gethppct(lifeform_t *lf);
enum COLOUR gethungercol(enum HUNGER hlev);
@ -257,6 +257,7 @@ char *getskilldesc(enum SKILL id );
char *getskillname(enum SKILL id );
char *getskilllevelname(enum SKILLLEVEL sl);
int getteachableskills(lifeform_t *teacher, lifeform_t *student, int *info, enum TRADEINFOTYPE *tradetype, int *ninfo );
int gettr(lifeform_t *lf);
char *gettradeinfoname(int what, enum TRADEINFOTYPE tradetype, char *buf);
int getthrowspeed(lifeform_t *lf);
int getturnspeed(lifeform_t *lf);
@ -420,6 +421,7 @@ void setbodytype(race_t *r, enum BODYTYPE bt);
int setfacing(lifeform_t *lf, int dir);
void setfollowdistance(lifeform_t *lf, int min, int max);
void setguntarget(lifeform_t *lf, lifeform_t *targ);
void sethomeroom(lifeform_t *lf);
void setkillverb(lifeform_t *lf, char *buf);
void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph);
void setlastdam(lifeform_t *lf, char *buf);

35
map.c
View File

@ -2940,6 +2940,7 @@ void createfakes(map_t *map, cell_t *cell) {
cell->map = map;
cell->lf = NULL;
cell->obpile = addobpile(NULL, NULL, NULL);
cell->room = NULL;
setcelltype(cell, CT_FAKE);
}
@ -5376,7 +5377,7 @@ void finalisemonster(lifeform_t *lf, lifeform_t *leader, flagpile_t *wantflags,
// random monster behaviours
if (canhaverandombehaviour(lf) && onein(6)) {
switch (rnd(0,6)) {
switch (rnd(0,8)) {
case 0: // insane
addflag(lf->flags, F_BEHAVIOUR, NA, NA, NA, "insane");
addflag(lf->flags, F_TERRITORIAL, 2, NA, NA, NULL); // attack anything within 1 cells
@ -5412,6 +5413,17 @@ void finalisemonster(lifeform_t *lf, lifeform_t *leader, flagpile_t *wantflags,
addflag(lf->flags, F_BEHAVIOUR, NA, NA, NA, "lazy");
addflag(lf->flags, F_FOLLOWTIME, (DEF_AIFOLLOWTIME/4), NA, NA, NULL);
break;
case 7: // extra hp
addflag(lf->flags, F_BEHAVIOUR, NA, NA, NA, "muscled");
lf->maxhp = pctof(rnd(125,200), lf->maxhp); // 25-100% more hp
lf->hp = lf->maxhp;
break;
case 8: // less hp
addflag(lf->flags, F_BEHAVIOUR, NA, NA, NA, "scrawny");
lf->maxhp = pctof(rnd(50,75), lf->maxhp); // 25-50% less hp
limit(&(lf->maxhp), 1, NA);
lf->hp = lf->maxhp;
break;
}
}
@ -7169,21 +7181,24 @@ void mapentereffects(map_t *m) {
vault_t *v;
c = m->cell[i];
v = getcellvault(c);
/*
// teleport shopkeepers back to their shops
if (c->lf && hasjob(c->lf, J_SHOPKEEPER) && !isplayer(c->lf)) {
f = lfhasflag(c->lf, F_OWNSSHOP);
if (f) {
// teleport monsters back to their lairs
if (c->lf && !isplayer(c->lf)) {
flag_t *f;
f = lfhasflag(c->lf, F_STAYINROOM);
if (f && (f->val[0] != NA)) {
cell_t *where;
int myshop;
myshop = f->val[0];
// find the closest cell of my shop
where = getclosestroomcell(c->lf, myshop);
int roomid;
roomid = f->val[0];
// find the closest cell of my lair
where = getclosestroomcell(c->lf, roomid);
if (where) {
movelf(c->lf, where);
}
}
}
/*
// replace people in the Inn
if (v && streq(v->id, "inn") && c->lf && (c->lf->race->id == R_HUMAN)) {
lifeform_t *lf;

23
move.c
View File

@ -533,6 +533,11 @@ int dorandommove(lifeform_t *lf, int badmovesok, int restonfail, int strafe) {
int moveok,rv;
enum ERROR why;
if (lfhasflag(lf, F_DOESNTMOVE)) {
rest(lf, B_TRUE);
return B_TRUE;
}
// find a valid direction
dir = getrandomdir(DT_COMPASS);
@ -902,7 +907,7 @@ int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher, int fallc
} else { // ie door or object
getobname(rdata, thing, 1);
}
if (seen) msg("%s slam%s into %s!",lfname,isplayer(lf) ? "" : "s", thing);
if (seen) msg("^%c%s slam%s into %s!^n",getlfcol(lf, CC_BAD), lfname,isplayer(lf) ? "" : "s", thing);
snprintf(buf, BUFLEN, "slamming into %s", thing);
dam = roll("1d6");
losehp(lf, dam, DT_BASH, pusher, buf);
@ -2396,7 +2401,7 @@ int initiatemove(lifeform_t *lf, cell_t *cell, int onpurpose, int *didmsg) {
}
getlfname(lf,lfname);
real_getobname(o, buf, o->amt, B_FALSE, B_FALSE, B_TRUE, B_FALSE, B_FALSE);
real_getobname(o, buf, o->amt, B_PREMODS, B_NOCONDITION, B_BLINDADJUST, B_NOBLESSINGS, B_NOUSED, B_NOSHOWALL);
if (skillcheck(lf, SC_STR, diff, checkmod)) {
if (isplayer(lf)) {
@ -3381,7 +3386,7 @@ int willmove(lifeform_t *lf, int dir, enum ERROR *error) {
*bp = '\0';
power = atoi(buf);
limit(&power, 1, NA);
if ( gethitdice(lf) <= power) {
if ( gettr(lf) <= power) {
if (error) *error = E_WONT;
return B_FALSE;
}
@ -3393,17 +3398,7 @@ int willmove(lifeform_t *lf, int dir, enum ERROR *error) {
if (f) {
int roomid;
roomid = f->val[0];
if (roomid == NA) {
// don't move out of ANY room.
if ((getroomid(lf->cell) != getroomid(cell))) {
if ((f->val[1] != NA) && aihastarget(lf)) {
// exception!
} else {
if (error) *error = E_WONT;
return B_FALSE;
}
}
} else {
if (roomid != NA) {
// don't move out of the given room.
if ((getroomid(lf->cell) == roomid) && (getroomid(lf->cell) != getroomid(cell))) {
if ((f->val[1] != NA) && aihastarget(lf)) {

17
nexus.c
View File

@ -814,6 +814,21 @@ void donextturn(map_t *map) {
}
}
// repairing?
if (donormalmove) {
f = lfhasflag(who, F_REPAIRING);
if (f) {
// this flag might appear more than once. that's okay, we'll handle a new
// one each time.
if (isplayer(who) && checkforkey()) {
msg("Stopped repairing items.");
killflag(f);
} else {
if (!continuerepairing(who, f)) donormalmove = B_FALSE;
}
}
}
// eating?
if (donormalmove) {
f = lfhasflag(who, F_EATING);
@ -966,7 +981,7 @@ warning_t *findwarning(char *text) {
return NULL;
}
void gethitdicerange(int depth, int *min, int *max, int range, int oodok) {
void gettrrange(int depth, int *min, int *max, int range, int oodok) {
int mid;
// adjust depth for out-of-depth monsters

View File

@ -12,7 +12,7 @@ void dobresnham(int d, int xinc1, int yinc1, int dinc1, int xinc2, int yinc2, in
void donextturn(map_t *map);
command_t *findcommand(enum COMMAND id);
warning_t *findwarning(char *text);
void gethitdicerange(int depth, int *min, int *max, int range, int oodok);
void gettrrange(int depth, int *min, int *max, int range, int oodok);
int getoption(enum OPTION id);
enum COLOUR getpctcol(float num, float max);
char getpctletter(float num, float max);

View File

@ -461,8 +461,11 @@ object_t *addobfast(obpile_t *where, enum OBTYPE oid) {
// to join similar objects together into a single
// object with o->amt set, instead of
// creating new obejct entries.
// 'dolinks' determines whether or not to do things like liking holes, assigning destinations to maps, etc.
// basically, set this to false if we are generating temporary/test objects.
// NOTE: This function MUST return number of obs created via global "nretobs"
object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes, enum OBTYPE forceoid) {
object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum OBTYPE forceoid) {
objecttype_t *ot;
object_t *o = NULL;
char *p,*nsp;
@ -1570,7 +1573,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
// create linked holes in adjacent maps
if (wantlinkholes && o && hasflag(o->flags, F_PIT)) {
if (dolinks && o && hasflag(o->flags, F_PIT)) {
cell_t *c;
map_t *adjmap = NULL;
@ -1646,19 +1649,21 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
wantregionthing = poss[rnd(0,nposs-1)];
}
}
assert(wantregionthing);
// we now have the destination regionlink thing which the
// map will lead to.
if (dolinks) {
assert(wantregionthing);
// we now have the destination regionlink thing which the
// map will lead to.
// just using this to fill in srcregion
findregionthing(wantregionthing->id, &srcregion);
srcdepth = wantregionthing->depth;
dstrt = findregiontype(wantregionthing->value);
// just using this to fill in srcregion
findregionthing(wantregionthing->id, &srcregion);
srcdepth = wantregionthing->depth;
dstrt = findregiontype(wantregionthing->value);
strcpy(buf, dstrt->name);
makelowercase(buf);
strcpy(buf, dstrt->name);
makelowercase(buf);
addflag(o->flags, F_MAPTO, srcregion->id, srcdepth, wantregionthing->id, buf);
addflag(o->flags, F_MAPTO, srcregion->id, srcdepth, wantregionthing->id, buf);
}
} else if (o->type->id == OT_STATUE) {
flag_t *f, *rf;
float ratio;
@ -3158,7 +3163,7 @@ int doobdieconvert(object_t *o, int wantannounce) {
if (wantannounce && !hasflag(o->flags, F_NODIECONVERTTEXT)) {
char obname[BUFLEN];
// announce the change
real_getobname(o, obname, o->amt, B_PREMODS, B_NOCONDITION, B_BLINDADJUST, B_BLESSINGS, B_NOSHOWALL);
real_getobname(o, obname, o->amt, B_PREMODS, B_NOCONDITION, B_BLINDADJUST, B_BLESSINGS, B_NOUSED, B_NOSHOWALL);
strcpy(desc, "");
@ -3292,14 +3297,14 @@ void explodeob(object_t *o, flag_t *f, int bigness) {
// announce
if (o->pile->owner) {
if (isplayer(o->pile->owner)) {
msg("Your %s explode%s!", noprefix(obname),OBS1(o));
msg("^BYour %s explode%s!^n", noprefix(obname),OBS1(o));
} else if (cansee(player, o->pile->owner)) {
char lfname[BUFLEN];
getlfname(o->pile->owner, lfname);
msg("%s%s %s explode%s!", lfname, getpossessive(lfname), noprefix(obname),OBS1(o));
msg("^B%s%s %s explode%s!^n", lfname, getpossessive(lfname), noprefix(obname),OBS1(o));
}
} else if (haslos(player, c)) {
msg("%s explode%s!", obname,OBS1(o));
msg("^B%s explode%s!^n", obname,OBS1(o));
}
explodecells(c, dam * o->amt, bigness ? B_TRUE : B_FALSE, o, bigness , DT_ORTH, B_FALSE);
@ -4842,19 +4847,19 @@ char *getshopobname(object_t *o, char *buf, int count) {
}
char *getobname(object_t *o, char *buf, int count) {
return real_getobname(o, buf, count, B_PREMODS, B_CONDITION, B_BLINDADJUST, B_BLESSINGS, B_NOSHOWALL);
return real_getobname(o, buf, count, B_PREMODS, B_CONDITION, B_BLINDADJUST, B_BLESSINGS, B_USED, B_NOSHOWALL);
}
char *getobnametrue(object_t *o, char *buf, int count) {
return real_getobname(o, buf, count, B_PREMODS, B_CONDITION, B_NOBLINDADJUST, B_BLESSINGS, B_SHOWALL);
return real_getobname(o, buf, count, B_PREMODS, B_CONDITION, B_NOBLINDADJUST, B_BLESSINGS, B_NOUSED, B_SHOWALL);
}
char *getobnametruebase(object_t *o, char *buf, int count) {
return real_getobname(o, buf, count, B_NOPREMODS, B_NOCONDITION, B_NOBLINDADJUST, B_NOBLESSINGS, B_SHOWALL);
return real_getobname(o, buf, count, B_NOPREMODS, B_NOCONDITION, B_NOBLINDADJUST, B_NOBLESSINGS, B_NOUSED, B_SHOWALL);
}
// buf must already be allocated
char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wantcondition, int adjustforblind, int wantblesscurse, int showall) {
char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wantcondition, int adjustforblind, int wantblesscurse, int wanttried, int showall) {
char *pluralname;
char prefix[BUFLEN];
char basename[BUFLEN];
@ -5441,7 +5446,7 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
// show if we've tried this
//if (!shopitem && (gamemode == GM_GAMESTARTED)) {
if (gamemode == GM_GAMESTARTED) {
if ((gamemode == GM_GAMESTARTED) && wanttried) {
knowledge_t *k;
strcpy(triedbuf, "");
@ -5747,7 +5752,7 @@ objecttype_t *getoppositestairs(objecttype_t *ot) {
// varargs are:
// OC_CLASS1, OC_CLAS2, OC_NONE, ..., DT_DAMTYPE1, DT_DAMTYPE2, .., DT_NONE
//
// no objectclass given then it will be picked randomly, or (if wepsk isn't sk_none) set to oc_weapon.
// if no objectclass given then it will be picked randomly, or (if wepsk isn't sk_none) set to oc_weapon.
char *real_getrandomob(map_t *map, char *buf, int forcedepth, int forcehabitat, enum LFSIZE maxsize, enum SKILL wepsk, int forpickup, ... ) {
va_list args;
objecttype_t *ot;
@ -8234,7 +8239,7 @@ void obdie(object_t *o) {
if (!doobdieconvert(o, B_TRUE)) {
char desc[BUFLEN];
real_getobname(o, obname, o->amt, B_PREMODS, B_NOCONDITION, B_BLINDADJUST, B_BLESSINGS, B_NOSHOWALL);
real_getobname(o, obname, o->amt, B_PREMODS, B_NOCONDITION, B_BLINDADJUST, B_BLESSINGS, B_NOUSED, B_NOSHOWALL);
if (!hasflag(o->flags, F_NOOBDIETEXT)) {
// announce the death
strcpy(desc, "");
@ -9074,7 +9079,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
// tell player
makeknown(o->type->id);
if (isplayer(lf)) {
real_getobname(o, obname, 1, B_NOPREMODS, B_CONDITION, B_NOBLINDADJUST, B_BLESSINGS, B_NOSHOWALL);
real_getobname(o, obname, 1, B_NOPREMODS, B_CONDITION, B_NOBLINDADJUST, B_BLESSINGS, B_NOUSED, B_NOSHOWALL);
msg("This is %s!",obname);
}
}
@ -10054,7 +10059,7 @@ void quaff(lifeform_t *lf, object_t *o) {
drawmsg();
}
} else if (!isknown(o)) {
real_getobname(o, obname, 1, B_NOPREMODS, B_CONDITION, B_NOBLINDADJUST, B_BLESSINGS, B_NOSHOWALL); // don't adjust for blindness
real_getobname(o, obname, 1, B_NOPREMODS, B_CONDITION, B_NOBLINDADJUST, B_BLESSINGS, B_NOUSED, B_NOSHOWALL); // don't adjust for blindness
if (isplayer(lf)) {
// tell the player
msg("This is %s!",obname);
@ -10697,7 +10702,7 @@ int readsomething(lifeform_t *lf, object_t *o) {
makeknown(o->type->id);
}
o->blessknown = B_TRUE;
real_getobname(o, obname, 1, B_NOPREMODS, B_CONDITION, B_NOBLINDADJUST, B_BLESSINGS, B_NOSHOWALL);
real_getobname(o, obname, 1, B_NOPREMODS, B_CONDITION, B_NOBLINDADJUST, B_BLESSINGS, B_NOUSED, B_NOSHOWALL);
if (isplayer(lf)) {
// tell the player
msg("This is %s!",obname);
@ -10772,7 +10777,7 @@ int readsomething(lifeform_t *lf, object_t *o) {
if (isplayer(lf)) {
// this will be used by maketried() later
real_getobname(targob, triedonbuf, 1, B_NOPREMODS, B_NOCONDITION,
B_BLINDADJUST, B_NOBLESSINGS, B_NOSHOWALL);
B_BLINDADJUST, B_NOBLESSINGS, B_USED, B_NOSHOWALL);
}
} else {
noeffect = B_TRUE;
@ -11077,7 +11082,7 @@ int readsomething(lifeform_t *lf, object_t *o) {
if (isplayer(lf) && !isknown(o)) {
identify(o);
o->blessknown = B_TRUE;
real_getobname(o, obname, 1, B_NOPREMODS, B_CONDITION, B_NOBLINDADJUST, B_BLESSINGS, B_NOSHOWALL);
real_getobname(o, obname, 1, B_NOPREMODS, B_CONDITION, B_NOBLINDADJUST, B_BLESSINGS, B_NOUSED, B_NOSHOWALL);
// tell the player
msg("This is %s!",obname);
more();
@ -11834,7 +11839,7 @@ int real_takedamage(object_t *o, int howmuch, int damtype, int wantannounce) {
}
// now use the REAL name
real_getobname(o, obname, o->amt, B_PREMODS, B_NOCONDITION, B_NOBLINDADJUST, B_NOBLESSINGS, B_SHOWALL);
real_getobname(o, obname, o->amt, B_PREMODS, B_NOCONDITION, B_NOBLINDADJUST, B_NOBLESSINGS, B_NOUSED, B_SHOWALL);
losehp_real(owner, howmuch , damtype, NULL, obname, B_DAMADJUST, o, B_NORETALIATE, NULL, B_DAMEFFECTS);
if (isdead(owner)) {
return howmuch;
@ -11847,7 +11852,7 @@ int real_takedamage(object_t *o, int howmuch, int damtype, int wantannounce) {
if (o->material->id == MT_GLASS) {
char buf[BUFLEN];
char buf2[BUFLEN];
real_getobname(o, buf2, 1, B_NOPREMODS, B_NOCONDITION, B_NOBLINDADJUST, B_NOBLESSINGS, B_NOSHOWALL);
real_getobname(o, buf2, 1, B_NOPREMODS, B_NOCONDITION, B_NOBLINDADJUST, B_NOBLESSINGS, B_NOUSED, B_NOSHOWALL);
snprintf(buf, BUFLEN, "a shattering %s", noprefix(buf2));
shatter(o, B_TRUE, buf, B_FALSE);
return howmuch;
@ -11965,7 +11970,7 @@ int real_takedamage(object_t *o, int howmuch, int damtype, int wantannounce) {
addflag(o->flags, F_LASTDAMTYPE, damtype, NA, NA, NULL);
}
real_getobname(o, obname, o->amt, B_NOPREMODS, B_NOCONDITION, B_BLINDADJUST, B_NOBLESSINGS, B_NOSHOWALL);
real_getobname(o, obname, o->amt, B_NOPREMODS, B_NOCONDITION, B_BLINDADJUST, B_NOBLESSINGS, B_NOUSED, B_NOSHOWALL);
getobconditionname(o, predamname);
hpflag = hasflag(o->flags, F_OBHP);
if (hpflag) {
@ -12322,7 +12327,7 @@ int real_fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int sp
radius = o->amt * 2;
if (radius > 10) radius = 10;
spellcloud(srcloc, radius, UNI_SHADELIGHT, C_RANDOM, OT_S_INVISIBILITY, radius, B_TRUE, buf, "A cloud of twinkling lights appear!");
spellcloud(srcloc, radius, UNI_SHADELIGHT, C_RANDOM, OT_S_INVISIBILITY, radius, B_TRUE, buf, "A cloud of twinkling lights appear!", B_FALSE);
} else if (o->type->id == OT_ASHSLEEP) {
int radius;
char buf[BUFLEN];
@ -12335,7 +12340,7 @@ int real_fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int sp
radius = o->amt * 2;
if (radius > 10) radius = 10;
spellcloud(srcloc, radius, UNI_SHADELIGHT, C_MAGENTA, OT_S_SLEEP, radius, B_TRUE, buf, "A wispy mist appears!");
spellcloud(srcloc, radius, UNI_SHADELIGHT, C_MAGENTA, OT_S_SLEEP, radius, B_TRUE, buf, "A wispy mist appears!", B_FALSE);
} else if (o->type->id == OT_SALT) {
int dist;
dist = getcelldist(srcloc, where);
@ -13094,7 +13099,7 @@ void timeeffectsob(object_t *o) {
// check each flag for this object...
getflags(o->flags, retflag, &nretflags, F_ACTIVATED, F_EDIBLE, F_MATCONVERT, F_HOT, F_OBHPDRAIN, F_ONFIRE,
getflags(o->flags, retflag, &nretflags, F_ACTIVATED, F_EDIBLE, F_EXPLODEONDEATH, F_MATCONVERT, F_HOT, F_OBHPDRAIN, F_ONFIRE,
F_RECHARGE, F_REVIVETIMER, F_WALKDAM, F_WET, F_NONE);
for (i = 0; i < nretflags; i++) {
object_t *oo,*nextoo;
@ -13190,6 +13195,15 @@ void timeeffectsob(object_t *o) {
}
}
if (f->id == F_EXPLODEONDEATH) {
if (o->pile->where && haslos(player, o->pile->where)) {
// pass a perception check to see it sparking...
if (skillcheck(player, SC_SEARCH, 15, 0)) {
msg("^w%s sparks.^n", obname);
}
}
}
if (f->id == F_OBHPDRAIN) {
enum DAMTYPE damtype;
int doit = B_TRUE;
@ -13253,6 +13267,7 @@ void timeeffectsob(object_t *o) {
}
}
}
// regenerates into a lf?
if (f->id == F_REVIVETIMER) {
cell_t *obloc = NULL;
@ -13273,11 +13288,15 @@ void timeeffectsob(object_t *o) {
if (lfloc) {
// revive!
lf = addmonster(lfloc, f->val[2], NULL, B_FALSE, 1, B_FALSE, NULL);
// gain flags form corpse
copyflag(lf->flags, o->flags, F_CANWILL);
copyflag(lf->flags, o->flags, F_CANCAST);
copyflag(lf->flags, o->flags, F_JOB);
// corpse vanishes
removeob(o, o->amt);
// announce
if (haslos(player, lfloc) || haslos(player, obloc)) {
msg("%s comes to life!", obname);
msg("^W%s comes to life!^n", obname);
interrupt(player);
}
return;

View File

@ -11,7 +11,7 @@ objectclass_t *addoc(enum OBCLASS id, char *name, char *desc, char glyph, int gl
void addocnoun(objectclass_t *oc, char *text);
object_t *addob(obpile_t *where, char *name);
object_t *addobfast(obpile_t *where, enum OBTYPE oid);
object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes, enum OBTYPE forceoid);
object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum OBTYPE forceoid);
int addobburst(cell_t *where, int range, int dirtype, char *name, lifeform_t *fromlf, enum LOFTYPE needlof);
obmod_t *addobmod(enum OBMOD id, char *prefix);
obpile_t *addobpile(lifeform_t *owner, cell_t *where, object_t *parentob);
@ -130,7 +130,7 @@ char *getshardobname(enum MATERIAL mid, char *buf);
char *getshopobname(object_t *o, char *buf, int count);
char *getobnametrue(object_t *o, char *buf, int count);
char *getobnametruebase(object_t *o, char *buf, int count);
char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wantcondition, int adjustforblind, int wantblesscurse, int showall);
char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wantcondition, int adjustforblind, int wantblesscurse, int wanttried, int showall);
float getobpileweight(obpile_t *op);
char *getobconditionname(object_t *o, char *buf);
char *getobhurtname(object_t *o, enum DAMTYPE damtype);

9
save.c
View File

@ -1158,6 +1158,9 @@ int saveobtobones(object_t *o, FILE *f, int x, int y) {
char obname[BUFLEN];
if (!obgoesinbones(o)) return B_TRUE;
// chance that someone picked up the object
if (onein(4)) return B_TRUE;
// modify the object?
if (hasflagval(o->flags, F_OBHPDRAIN, NA, DT_DECAY, NA, NULL)) {
// food will decay by the time someone else finds it.
@ -1178,7 +1181,11 @@ int saveobtobones(object_t *o, FILE *f, int x, int y) {
}
}
getobnametrue(o, obname, o->amt);
if (o->material->id == MT_BLOOD) {
sprintf(obname, "a blood stain");
} else {
getobnametrue(o, obname, o->amt);
}
fprintf(f, "at(%d,%d) ob:%s\n", x,y, obname);
return B_FALSE;
}

139
spell.c
View File

@ -941,6 +941,8 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
if (cansee(player, user)) {
msg("^w%s disarm%s %s!",username, isplayer(user) ? "" : "s", targetname);
}
// calling drop() will cause the target to take some time - this will normally give
// free hit in before they can pick it back up.
drop(targetwep, ALL);
} else {
if (isplayer(user)) {
@ -1418,12 +1420,11 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
howlong = DEF_RAGETIME;
addtempflag(user->flags, F_RAGE, B_TRUE, NA, NA, NULL, howlong);
} else if (abilid == OT_A_REPAIR) {
object_t *o,*helpob = NULL;
object_t *o;
enum MATERIAL repairablemats[MAXCANDIDATES];
int cutoffpct[MAXCANDIDATES];
int nmats = 0;
int i;
char helpobname[BUFLEN];
// get list of repairable materials
getworkablematerials(user, SK_METALWORK, repairablemats, cutoffpct, &nmats);
@ -1432,6 +1433,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
// sk_armour lets you repair armour up to xx% (depends on skill)
initprompt(&prompt, "Repair which object?");
addchoice(&prompt, '-', "Cancel", "Cancel", NULL, NULL);
addchoice(&prompt, ',', "All", "All", NULL, NULL);
for (o = user->pack->first ; o ; o = o->next) {
int ok = B_FALSE;
int cutoff = 0;
@ -1456,7 +1458,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
}
}
if (prompt.nchoices <= 1) {
if (prompt.nchoices <= 2) {
if (isplayer(user)) {
msg("You don't have anything which you are able to repair.");
}
@ -1465,51 +1467,54 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
// 2. ask which ones to repair (or ALL)
if (isplayer(user)) {
getchoice(&prompt);
o = (object_t *) prompt.result;
char ch;
ch = getchoice(&prompt);
if (ch == ',') { // all
int n;
for (n = 0 ; n < prompt.nchoices; n++) {
o = (object_t *)prompt.choice[n].data;
if (o) {
char buf[BUFLEN];
sprintf(buf, "%ld", o->id);
addflag(user->flags, F_REPAIRING, NA, NA, NA, buf);
}
}
o = NULL;
} else {
o = (object_t *) prompt.result;
if (!o) {
if (isplayer(user)) msg("Cancelled.");
return B_TRUE;
}
}
} else {
// pick a random one
o = (object_t *) prompt.choice[rnd(0,prompt.nchoices-1)].data;
// pick a random one (not 'cancel' or 'all')
o = (object_t *) prompt.choice[rnd(2,prompt.nchoices-1)].data;
if (!o) return B_TRUE;
}
// in case it's on fire, etc
if (touch(user, o)) {
taketime(user, getactspeed(user));
return B_FALSE;
}
// get helper ob
helpob = getworkhelpob(user->pack, o->material->id);
if (helpob) {
real_getobname(helpob, helpobname, helpob->amt, B_PREMODS, B_NOCONDITION, B_BLINDADJUST, B_BLESSINGS, B_NOSHOWALL);
if (o) {
char buf[BUFLEN];
sprintf(buf, "%ld", o->id);
addflag(user->flags, F_REPAIRING, NA, NA, NA, buf);
getobname(o, buf, o->amt);
if (isplayer(user)) {
msg("You start repairing %s...", buf);
} else if (cansee(player, user)) {
char lfname[BUFLEN];
getlfname(user, lfname);
msg("%s starts repairing %s...", lfname, buf);
}
} else {
strcpy(helpobname, "");
// repairing all...
if (isplayer(user)) {
msg("You start repairing your equipment...");
} else if (cansee(player, user)) {
char lfname[BUFLEN];
getlfname(user, lfname);
msg("%s starts repairing its equipment...", lfname);
}
}
// fully repair it.
f = hasflag(o->flags, F_OBHP);
f->val[0] = f->val[1];
if (isplayer(user)) {
char buf[BUFLEN],withbuf[BUFLEN];
real_getobname(o, buf, o->amt, B_PREMODS, B_NOCONDITION, B_BLINDADJUST, B_BLESSINGS, B_NOSHOWALL);
if (helpob) sprintf(withbuf, " (with %s)", helpobname);
else strcpy(withbuf, "");
msg("You repair your %s%s.", noprefix(buf), withbuf);
} else {
char buf[BUFLEN],withbuf[BUFLEN];
real_getobname(o, buf, o->amt, B_PREMODS, B_NOCONDITION, B_BLINDADJUST, B_BLESSINGS, B_NOSHOWALL);
if (helpob) sprintf(withbuf, " with %s", helpobname);
else strcpy(withbuf, "");
msg("%s repairs %s%s.", username, buf, withbuf);
}
practice(user, SK_METALWORK, 1);
practice(user, SK_SEWING, 1);
// TODO: make this like eating/resting/etc ?
taketime(user, getactspeed(user));
} else if (abilid == OT_A_RESIZE) {
object_t *o;
enum MATERIAL repairablemats[MAXCANDIDATES];
@ -4343,8 +4348,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
for (i = 0; i < caster->nlos; i++) {
c = caster->los[i];
if (c->lf && (c->lf != caster) && (c->lf->race->raceclass->id == RC_ANIMAL) && lfhasflag(c->lf, F_HOSTILE)) {
if (gethitdice(c->lf) <= powerleft) {
powerleft -= gethitdice(c->lf);
if (gettr(c->lf) <= powerleft) {
powerleft -= gettr(c->lf);
makepeaceful(c->lf, caster);
ncalmed++;
@ -4626,7 +4631,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// no saving throw, just depends on hit dice.
// too powerful?
if (gethitdice(target) <= power) {
if (gettr(target) <= power) {
int howlong;
if (isplayer(caster) || cansee(player, target)) {
if (seenbyplayer) *seenbyplayer = B_TRUE;
@ -6847,7 +6852,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
fizzle(target);
return B_TRUE;
}
f = addtempflag(target->flags, F_HEAVENARM, power*10, NA, NA, "divine armour", FROMSPELL);
f = addtempflag(target->flags, F_HEAVENARM, power*10, NA, NA, "shell of divine armour", FROMSPELL);
f->obfrom = spellid;
} else if (spellid == OT_S_HOLDPORTAL) {
object_t *o,*oo;
@ -7405,7 +7410,11 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
ndone++;
}
// now stop active spells
if (killflagsofid(target->flags, F_REVIVETIMER)) {
ndone++;
}
// now stop active spells or abilities
while (ndone < power) {
nposs = 0;
getflags(target->flags, retflag, &nretflags, F_BOOSTSPELL, F_NONE);
@ -8462,7 +8471,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
for (o = c->obpile->first ; o ; o = o->next) {
char obname[BUFLEN];
real_getobname(o, obname, o->amt, B_PREMODS, B_CONDITION, B_NOBLINDADJUST,
B_NOBLESSINGS, B_NOSHOWALL);
B_NOBLESSINGS, B_USED, B_NOSHOWALL);
if (strcasestr(obname, wantname)) {
char ptext[BUFLEN];
char distbuf[BUFLEN],dirbuf[BUFLEN];
@ -8477,7 +8486,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
for (o = c->lf->pack->first ; o ; o = o->next) {
char obname[BUFLEN];
real_getobname(o, obname, o->amt, B_PREMODS, B_CONDITION,
B_NOBLINDADJUST, B_NOBLESSINGS, B_NOSHOWALL);
B_NOBLINDADJUST, B_NOBLESSINGS, B_USED, B_NOSHOWALL);
if (strcasestr(obname, wantname)) {
char ptext[BUFLEN];
char distbuf[BUFLEN],dirbuf[BUFLEN];
@ -8924,7 +8933,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// same race?
if (potrace == target->race) continue;
// too powerful?
if (gethitdicerace(potrace) > power) {
if (gettrrace(potrace) > power) {
continue;
}
// already in the list?
@ -11928,7 +11937,7 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid) {
if (isplayer(lf)) {
power = 1;
// plus your hitdice/3
power += (gethitdice(lf)/3);
power += (gettr(lf)/3);
// plus stat modifier
power += getspellpowerstatmod(lf, school, NULL);
@ -11940,7 +11949,7 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid) {
power += (schoolskill - spelllev);
} else {
// for monsters, just based on hitdice:
power = gethitdice(lf)/2;
power = gettr(lf)/2;
limit(&power, 1, NA);
}
@ -12263,7 +12272,9 @@ int getworkablematerials(lifeform_t *lf, enum SKILL skid , enum MATERIAL *repair
}
if (helpob) cutoff -= 15;
if (cutoff) {
limit(&cutoff, 0, NA);
if (cutoff != 100) {
if (skid == SK_METALWORK) {
repairablemats[*nmats] = MT_METAL;
cutoffpct[*nmats] = cutoff;
@ -12409,7 +12420,7 @@ int schoolappearsinbooks(enum SPELLSCHOOL ss) {
return B_TRUE;
}
void spellcloud(cell_t *srcloc, int radius, int ch, enum COLOUR col, enum OBTYPE sid, int power, int frompot, char *seetext, char *noseetext) {
void spellcloud(cell_t *srcloc, int radius, int ch, enum COLOUR col, enum OBTYPE sid, int power, int frompot, char *seetext, char *noseetext, int aimedateyes) {
int x,y;
objecttype_t *ot;
ot = findot(sid);
@ -12424,12 +12435,18 @@ void spellcloud(cell_t *srcloc, int radius, int ch, enum COLOUR col, enum OBTYPE
c = getcellat(srcloc->map, x, y);
if (c && c->lf && (c != srcloc) && !c->type->solid &&
haslof(srcloc, c, LOF_WALLSTOP, NULL)) {
if (getcelldistorth(srcloc, c) <= radius) {
// cast the spell
if (ot->obclass->id == OC_SPELL) {
dospelleffects(NULL, ot->id, power, c->lf, NULL, c, B_UNCURSED, NULL, frompot);
} else if (ot->obclass->id == OC_ABILITY) {
abilityeffects(c->lf, ot->id, c, c->lf, NULL);
int safe = B_FALSE;
if (aimedateyes && (!hasbp(c->lf, BP_EYES) || getarmour(c->lf, BP_EYES))) {
safe = B_TRUE;
}
if (!safe) {
if (getcelldistorth(srcloc, c) <= radius) {
// cast the spell
if (ot->obclass->id == OC_SPELL) {
dospelleffects(NULL, ot->id, power, c->lf, NULL, c, B_UNCURSED, NULL, frompot);
} else if (ot->obclass->id == OC_ABILITY) {
abilityeffects(c->lf, ot->id, c, c->lf, NULL);
}
}
}
}

View File

@ -35,7 +35,7 @@ int getworkablematerials(lifeform_t *lf, enum SKILL skid , enum MATERIAL *repair
object_t *getworkhelpob(obpile_t *op, enum MATERIAL mat);
void pullobto(object_t *o, lifeform_t *lf);
int schoolappearsinbooks(enum SPELLSCHOOL ss);
void spellcloud(cell_t *srcloc, int radius, int ch, enum COLOUR col, enum OBTYPE sid, int power, int frompot, char *seetext, char *noseetext);
void spellcloud(cell_t *srcloc, int radius, int ch, enum COLOUR col, enum OBTYPE sid, int power, int frompot, char *seetext, char *noseetext, int aimedateyes);
int spellisfromschool(int spellid, enum SPELLSCHOOL school);
int spellokformonsters(int spellid);
int spellresisted(lifeform_t *target, lifeform_t *caster, int spellid, int power, int *seenbyplayer, int announce);

22
text.c
View File

@ -190,8 +190,9 @@ char *construct_hit_string(lifeform_t *lf, lifeform_t *victim, char *attackernam
}
} else { // ie. the attacker is a monster
if (cansee(player, lf) || (victim && isplayer(victim))) {
int needfree = B_FALSE;
char *verb;
char withwep[BUFLEN];
char attackverb[BUFLEN];
char nodamstr[BUFLEN];
int nodam = B_FALSE;
int col;
@ -206,7 +207,7 @@ char *construct_hit_string(lifeform_t *lf, lifeform_t *victim, char *attackernam
strcpy(withwep, "");
}
strcpy(attackverb, getattackverb(lf, wep, damtype,dam,maxhp));
verb = getattackverb(lf, wep, damtype,dam,maxhp);
strcpy(nodamstr, "");
if ((dam == 0) && (damtype != DT_TOUCH) && !lfhasflag(lf, F_PHANTASM)) {
@ -214,15 +215,24 @@ char *construct_hit_string(lifeform_t *lf, lifeform_t *victim, char *attackernam
strcpy(nodamstr, " ineffectually");
}
if (backstab && (idx == 0)) {
verb = strdup("backstab");
needfree = B_TRUE;
}
if (victim && isplayer(victim) && !nodam) {
col = C_YELLOW;
} else {
col = C_GREY;
}
snprintf(retbuf, BUFLEN, "^%d%s %s%s%s %s%s%s.", col, buf,
usecrittext ? "critically " : "", attackverb,
needses(attackverb) ? "es" : "s",
usecrittext ? victimbpname : locvictimname,withwep, nodamstr);
snprintf(retbuf, BUFLEN, "^%d%s %s%s%s %s%s%s%c", col, buf,
usecrittext ? "critically " : "", verb,
needses(verb) ? "es" : "s",
usecrittext ? victimbpname : locvictimname,withwep, nodamstr,
backstab ? '!' : '.');
if (needfree) {
free(verb);
}
}
}
} else { // follow-up weapon damage (ie from a flaming sword etc)