added bazaar vault.

- [+] remove damage from jumping onto other lfs
- [+] when you jump in water or something lands in water: "you hear a
      splash"
- [+] tweaks to how evasion works.
- [+] The book crumbles to dust.  Your manual is no longer glowing.
      FIXED.
- [+] fix msghistbuf for askchar - not showing your choice.
- [+] in shops, show prices in red if you can't afford them.
- [+] retaliate should only work if you're still adjecent
- [+] show Ravenous in RED
- [+] no xp for rapid ivy clones
- [+] make weapon of impact only knockback 33% of the time (instead of
      always)
- [+] don't set F_NOSCORE when quitting.
- [+] some scrolls cost $1??
- [+] You see a masterwork shoddy club here.
    - [+] shouhldn't be able to have both!!!
- [+] change bleeding code.  lowhp doesn't mean bleeding.
    - [+] also change flee on bleed etc
This commit is contained in:
Rob Pearce 2011-12-09 00:37:02 +00:00
parent 089ce94751
commit 0f99007c2a
15 changed files with 275 additions and 107 deletions

2
ai.c
View File

@ -848,7 +848,7 @@ int ai_healing(lifeform_t *lf) {
if (!lfhasflag(lf, F_RAGE)) {
// feigning death with enemies in sight, and hurt?
if (lfhasflag(lf, F_FEIGNINGDEATH) && !safetorest(lf)) {
if (isbleeding(lf)) {
if (islowhp(lf)) {
if (db) dblog(".oO { i am feigning death and bleeding (hp=%d/%d), skipping turn. }",lf->hp,lf->maxhp);
// just wait...
rest(lf, B_TRUE);

View File

@ -920,7 +920,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
if (lfhasflag(victim, F_FEIGNINGDEATH)) {
killflagsofid(victim->flags, F_FEIGNINGDEATH);
} else if (!fatal && !isplayer(victim) && cancast(victim, OT_A_FEIGNDEATH, NULL)) {
if (onein(2) || isbleeding(victim)) {
if (onein(2) || islowhp(victim)) {
// do it!
useability(victim, OT_A_FEIGNDEATH, lf, lf->cell);
feigneddeath = B_TRUE;
@ -1036,7 +1036,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
f = lfhasflag(lf, F_QUICKBITE);
if (f) {
if (isbleeding(victim)) {
if (islowhp(victim)) {
int dam;
char lfname[BUFLEN];
dam = rolldie(f->val[0], f->val[1]) + f->val[2];
@ -1126,7 +1126,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
getflags(victim->flags, retflag, &nretflags, F_RETALIATE, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->id == F_RETALIATE) {
if ((f->id == F_RETALIATE) && (getcelldist(victim->cell, lf->cell) == 1)) {
int rdam;
char damstring[BUFLEN];
rdam = rolldie(f->val[0], f->val[1]);
@ -2170,10 +2170,18 @@ void wepeffects(flagpile_t *fp, cell_t *where, flag_t *damflag, int dam) {
}
} else if ((f->id == F_HEAVYBLOW) && victim && owner) {
int dir;
int chance;
// lifeform flag works all the time. object flag only works sometimes.
if (wep) chance = 33;
else chance = 100;
if (pctchance(chance)) {
// knock back victim
dir = getdirtowards(owner->cell, victim->cell, victim, B_FALSE, DT_COMPASS);
knockback(victim, dir , 2, owner, 30, B_TRUE);
if (cansee(player, owner)) {
f->known = B_TRUE;
}
}
} else if ((f->id == F_HITCONFER) && victim ) {
// only works if we did damage
enum FLAG fid;
@ -2265,7 +2273,7 @@ void wepeffects(flagpile_t *fp, cell_t *where, flag_t *damflag, int dam) {
if (wep && owner && victim) {
enum DRAINTYPE draintype = DR_NONE;
if ((wep->type->id == OT_TEETH) && lfhasflag(owner, F_VAMPIRIC) && isbleeding(victim)) {
if ((wep->type->id == OT_TEETH) && lfhasflag(owner, F_VAMPIRIC) && islowhp(victim)) {
draintype = DR_FROMBITE;
} else if (hasflag(wep->flags, F_VAMPIRIC)) {
draintype = DR_FROMWEP;

20
data.c
View File

@ -2141,7 +2141,7 @@ void initobjects(void) {
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "splash of cockatrice blood");
addflag(lastot->flags, F_VALUE, 35, NA, NA, NULL);
addot(OT_POT_COMPETENCE, "potion of competence", "Permemantly increases the drinker's strength, intelligence or dexterity.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addot(OT_POT_COMPETENCE, "potion of competence", "Permemantly increases the drinker's base attribites (Strength, IQ, etc).", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, NA, NULL);
addflag(lastot->flags, F_VALUE, 160, NA, NA, NULL);
@ -2185,9 +2185,11 @@ void initobjects(void) {
// scrolls
addot(OT_SCR_AWARENESS, "scroll of awareness", "Mimics the effects of a 'heightened awareness' spell.", MT_PAPER, 0.5, OC_SCROLL, SZ_SMALL);
addflag(lastot->flags, F_VALUE, 50, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_UNCOMMON, NULL);
addot(OT_SCR_REMOVECURSE, "scroll of remove curse", "Removes curses from all weilded equipment.", MT_PAPER, 0.5, OC_SCROLL, SZ_SMALL);
addflag(lastot->flags, F_VALUE, 50, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_FREQUENT, NULL);
addot(OT_SCR_IDENTIFY, "scroll of identify", "Completely identifies any one item.", MT_PAPER, 0.5, OC_SCROLL, SZ_SMALL);
@ -2200,10 +2202,12 @@ void initobjects(void) {
addflag(lastot->flags, F_MAXPOWER, 4, NA, NA, NULL);
addot(OT_SCR_NOTHING, "scroll of nothing", "Looks like a magic scroll, but doesn't do anything.", MT_PAPER, 0.5, OC_SCROLL, SZ_SMALL);
addflag(lastot->flags, F_VALUE, 2, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 84, RR_UNCOMMON, NULL);
addot(OT_GRAPHPAPER, "magic map", "Paper containing a set of grid-lines, which automatically draws a map of its surroundings.", MT_PAPER, 0.5, OC_SCROLL, SZ_SMALL);
addflag(lastot->flags, F_HOLDCONFER, F_PHOTOMEM, NA, IFKNOWN, NULL);
addflag(lastot->flags, F_VALUE, 100, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_UNCOMMON, NULL);
addot(OT_MAP, "map", "A visual representation of the area.", MT_PAPER, 0.5, OC_SCROLL, SZ_SMALL);
@ -2267,6 +2271,7 @@ void initobjects(void) {
addflag(lastot->flags, F_RARITY, H_ALL, 75, RR_UNCOMMON, NULL);
addot(OT_SCR_PERMENANCE, "scroll of permenance", "Makes all effects on an object last forever.", MT_PAPER, 0.5, OC_SCROLL, SZ_SMALL);
addflag(lastot->flags, F_VALUE, 400, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 50, RR_RARE, NULL);
addot(OT_SCR_TELEPORT, "scroll of teleportation", "Causes the caster to teleport to a random location within the same level.", MT_PAPER, 0.5, OC_SCROLL, SZ_SMALL);
@ -2280,6 +2285,7 @@ void initobjects(void) {
addflag(lastot->flags, F_RARITY, H_ALL, 70, RR_UNCOMMON, NULL);
addot(OT_SCR_WISH, "scroll of wishing", "Grants the caster any item of their choice (with some limitations).", MT_PAPER, 0.5, OC_SCROLL, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_VERYRARE, NULL);
addflag(lastot->flags, F_LINKSPELL, OT_S_WISHLIMITED, NA, NA, NULL);
@ -3653,6 +3659,9 @@ void initobjects(void) {
addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL);
addflag(lastot->flags, F_STAMCOST, 2, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_NEED, NA, NULL);
addot(OT_A_SNATCH, "snatch", "Quickly grab a single item from an adjacent cell.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_NEED, NA, NULL);
addot(OT_A_SONICBOLT, "sonic bolt", "Emit a damaging burst of sound, targetted at a particular location.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
@ -4417,7 +4426,7 @@ void initobjects(void) {
addot(OT_ACIDSPLASH, "splash of acid", "A splash corrosive acid.", MT_ACID, 0, OC_MISC, SZ_SMALL);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_GLYPH, NA, NA, NA, ",");
addflag(lastot->flags, F_GLYPH, NA, ',', NA, NULL);
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OBDIETEXT, NA, NA, NA, "evaporates");
addflag(lastot->flags, F_OBHP, 3, 3, NA, NULL);
@ -5478,7 +5487,7 @@ void initobjects(void) {
addflag(lastot->flags, F_EQUIPCONFER, F_ATTRMOD, A_CON, 1, NULL); // '1' is randomized during generation
addflag(lastot->flags, F_IDWHENUSED, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_VALUE, 300, NA, NA, NULL);
addot(OT_RING_DEX, "ring of dexterity", "Increases the wearer's dexterity.", MT_METAL, 0.1, OC_RING, SZ_MINI);
addot(OT_RING_DEX, "ring of agility", "Increases the wearer's agility.", MT_METAL, 0.1, OC_RING, SZ_MINI);
addflag(lastot->flags, F_RARITY, H_ALL, 70, RR_UNCOMMON, "");
addflag(lastot->flags, F_EQUIPCONFER, F_ATTRMOD, A_AGI, 1, NULL); // '1' is randomized during generation
addflag(lastot->flags, F_IDWHENUSED, B_TRUE, NA, NA, NULL);
@ -6549,7 +6558,7 @@ void initrace(void) {
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "good armour");
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "good armour");
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "armour");
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "dungeon exit orb");
//addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "dungeon exit orb");
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "concealing powder");
addflag(lastrace->flags, F_FLEEONHPPCT, 40, NA, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_POLEARMS, PR_ADEPT, NA, NULL);
@ -8672,7 +8681,7 @@ void initrace(void) {
addflag(lastrace->flags, F_CANWILL, OT_A_GRAB, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_A_CRUSH, NA, NA, "dam:2d6;");
addflag(lastrace->flags, F_CRITKNOCKDOWN, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_BLEEDABIL, OT_A_RAGE, NA, NA, NULL);
addflag(lastrace->flags, F_LOWHPABIL, OT_A_RAGE, NA, NA, NULL);
addflag(lastrace->flags, F_MINIONS, 25, 1, 2, "bear cub");
addflag(lastrace->flags, F_MORALE, 10, NA, NA, NULL);
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
@ -10471,6 +10480,7 @@ void initskills(void) {
addskilldesc(SK_EVASION, PR_NOVICE, "^gIncreases your EV by 12%.^n", B_FALSE);
addskilldesc(SK_EVASION, PR_BEGINNER, "^gIncreases your EV by 24%.^n", B_FALSE);
addskilldesc(SK_EVASION, PR_ADEPT, "^gIncreases your EV by 36%.^n", B_FALSE);
addskilldesc(SK_EVASION, PR_ADEPT, "^gYou gain the 'snatch' ability.^n", B_FALSE);
addskilldesc(SK_EVASION, PR_SKILLED, "^gIncreases your EV by 48%.^n", B_FALSE);
addskilldesc(SK_EVASION, PR_EXPERT, "^gIncreases your EV by 60%.^n", B_FALSE);
addskilldesc(SK_EVASION, PR_MASTER, "^gIncreases your EV by 72%.^n", B_FALSE);

Binary file not shown.

3
defs.h
View File

@ -1437,6 +1437,7 @@ enum OBTYPE {
OT_A_REPAIR,
OT_A_RESIZE,
OT_A_SHIELDBASH,
OT_A_SNATCH,
OT_A_SONICBOLT,
OT_A_SPRINT,
OT_A_STUDYSCROLL,
@ -2668,7 +2669,7 @@ enum FLAG {
F_CANCAST, // can cast the spell val0 (need MP)
F_CANHEARLF, // you can hear lifeform id v0 (show their glyph)
// this flag does not get announced.
F_BLEEDABIL, // will automatically use the ability v0 when
F_LOWHPABIL, // will automatically use the ability v0 when
// this lf starts bleeding.
F_BREATHWATER, // can breath normally underwater
F_CANWILL, // can cast the spell/ability val0 without using MP

4
god.c
View File

@ -892,7 +892,7 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
if (isinbattle(lf)) {
lifeform_t *l;
int donesomething = B_FALSE;
if (isbleeding(lf)) {
if (islowhp(lf)) {
// teleport away
msg("\"Nothing like a quick getaway!\"");
dospelleffects(NULL, OT_S_DISPERSAL, 10, lf, NULL, lf->cell, B_UNCURSED, NULL, B_FALSE);
@ -953,7 +953,7 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
castspell(god, OT_S_SATEHUNGER, player, NULL, player->cell, NULL, NULL);
donesomething = B_TRUE;
}
if (isbleeding(lf) || !donesomething) {
if (islowhp(lf) || !donesomething) {
msg("\"Let thy wounds be healed.\"");
castspell(god, OT_S_HEALINGMAJ, player, NULL, player->cell, NULL, NULL);
donesomething = B_TRUE;

27
io.c
View File

@ -522,7 +522,7 @@ char askchar(char *prompt, char *validchars, char *def, int showchars, int mayca
curs_set(0);
// update messaage history
sprintf(msghistbuf, "%s%c", buf, (ch == '\0') ? '-' : '\0');
sprintf(msghistbuf, "%s%c", buf, (ch == '\0') ? '-' : ch);
addmsghist(msghistbuf);
clearmsg();
@ -3844,7 +3844,7 @@ void docomms(lifeform_t *lf) {
int mod = 0;
int covets = B_FALSE;
// healing object and they were bleeding?
if (isbleeding(lf) && hasflag(givenob->flags, F_AIHEALITEM)) {
if ((islowhp(lf) || isbleeding(lf)) && hasflag(givenob->flags, F_AIHEALITEM)) {
if (aiobok(lf, givenob, lf)) {
mod += 3;
}
@ -5012,8 +5012,12 @@ char *makedesc_ob(object_t *o, char *retbuf) {
if (f) {
int critprotchance;
critprotchance = getcritprotection(o);
if (critprotchance == 0) {
snprintf(buf, BUFLEN, "It will not protect your %s from critical hits", getbodypartname(player, f->val[0]));
} else {
snprintf(buf, BUFLEN, "It has a %d%% chance of preventing critical hits to your %s",
critprotchance, getbodypartname(player, f->val[0]));
}
if (compareob) {
int diff,comparechance = 0;
@ -5696,10 +5700,10 @@ char *makedesc_ob(object_t *o, char *retbuf) {
strncat(retbuf, buf, HUGEBUFLEN);
if (usable && isweapon(o)) {
if (pctmod > 0) {
sprintf(buf, "^%dYour high %s will increase your effectiveness with this weapon.^n", C_GREEN, getattrname(f->val[0]));
sprintf(buf, "^%dYour high %s will increase your effectiveness with this weapon.^n\n", C_GREEN, getattrname(f->val[0]));
strncat(retbuf, buf, HUGEBUFLEN);
} else if (pctmod < 0) {
sprintf(buf, "^%dYour low %s will decrease your effectiveness with this weapon.^n", C_BROWN, getattrname(f->val[0]));
sprintf(buf, "^%dYour low %s will decrease your effectiveness with this weapon.^n\n", C_BROWN, getattrname(f->val[0]));
strncat(retbuf, buf, HUGEBUFLEN);
}
}
@ -7003,7 +7007,6 @@ void doquit(void) {
char ch;
ch = askchar("Really quit", "yn","n", B_TRUE, B_FALSE);
if (ch == 'y') {
addflag(player->flags, F_NOSCORE, B_TRUE, NA, NA, NULL);
setlastdam(player, "quitting");
player->alive = B_FALSE;
}
@ -9214,18 +9217,16 @@ void drawstatus(void) {
if (hlev == H_NONE) {
strcpy(buf2, "");
} else {
gethungername(player, gethungerlevel(f->val[0]), buf2);
gethungername(player, hlev, buf2);
capitalise(buf2);
}
} else {
strcpy(buf2, "");
if (hlev == H_STARVING) setcol(statwin, C_RED);
else setcol(statwin, C_BROWN);
wprintw(statwin, " %s", buf2);
if (hlev == H_STARVING) unsetcol(statwin, C_RED);
else unsetcol(statwin, C_BROWN);
}
if (strlen(buf2) > 0) {
setcol(statwin, C_BROWN);
wprintw(statwin, " %s", buf2);
unsetcol(statwin, C_BROWN);
}
// good effects
f = lfhasflag(player, F_HIDING);

104
lf.c
View File

@ -1124,9 +1124,11 @@ int cansee_real(lifeform_t *viewer, lifeform_t *viewee, int uselos) {
}
// viewee underwater and more than 1 cell away?
if ((getobdepth(o, viewee) >= DP_HEAD) && (dist > 1)) {
if (!isairborne(viewee)) {
return B_FALSE;
}
}
}
return B_TRUE;
}
@ -3361,13 +3363,13 @@ int eat(lifeform_t *lf, object_t *o) {
// end of turn effects
void endlfturn(lifeform_t *lf) {
// lf will complain if in pain
if (isbleeding(lf) && onein(3) && !hasflag(lf->flags, F_ASLEEP)) {
if (islowhp(lf) && onein(3) && !hasflag(lf->flags, F_ASLEEP)) {
// TODO: replace 4
if (ispetof(lf, player)) {
if (!canhear(player, lf->cell, 4)) {
char realname[BUFLEN];
real_getlfname(lf, realname, B_FALSE);
warn("You feel worried about your %s.", noprefix(realname));
warn("You feel worried about %s%s.", lfhasflag(lf, F_NAME) ? "" : "your ", noprefix(realname));
} else if (cantalk(lf)) {
sayphrase(lf, SP_ALLY_INPAIN, SV_SHOUT, NA, NULL);
} else {
@ -3769,7 +3771,7 @@ void enhanceskills(lifeform_t *lf) {
killflagsofid(lf->flags, F_HASNEWLEVEL);
// ready for another level?
if (lf->xp >= getxpforlev(lf->level + 1)) {
gainlevel(lf); // this will increment 'newlevel'
gainlevel(lf, B_FALSE); // this will increment 'newlevel'
}
killwarningtext(TEXT_WARN_ATTACK_NOXP);
@ -4343,7 +4345,7 @@ void gainhp(lifeform_t *lf, int amt) {
}
}
void gainlevel(lifeform_t *lf) {
void gainlevel(lifeform_t *lf, int autotrain) {
flag_t *f;
race_t *mybaserace;
//int skillready = B_FALSE;
@ -4379,8 +4381,10 @@ void gainlevel(lifeform_t *lf) {
}
if (isplayer(lf)) {
if (!autotrain) {
msg("^GYou are ready to train a new experience level!");
more();
}
} else if (cansee(player, lf)) {
//getlfname(lf, buf);
//msg("%s looks more confident!",buf);
@ -4407,6 +4411,10 @@ void gainlevel(lifeform_t *lf) {
statdirty = B_TRUE;
drawscreen();
}
if (autotrain) {
enhanceskills(lf);
}
}
@ -4485,7 +4493,7 @@ void gainxp(lifeform_t *lf, long amt) {
if (doxp) {
// ready for next level? can only go up ONE level.
if (lf->xp >= getxpforlev(lf->level + 1)) {
gainlevel(lf); // this will increment 'newlevel'
gainlevel(lf, B_FALSE); // this will increment 'newlevel'
}
}
if (newskillpoints) {
@ -5294,17 +5302,14 @@ int getevasion(lifeform_t *lf) {
return 0;
}
//////////////////////////////////////////////////
// positive modifiers first
//////////////////////////////////////////////////
// get natural evasion, adjustments for bulky armour/shield
getflags(lf->flags, retflag, &nretflags, F_ARMOURPENALTY, F_EVASION, F_SHIELDPENALTY, F_NONE);
getflags(lf->flags, retflag, &nretflags, F_EVASION, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->id == F_ARMOURPENALTY) {
ev -= adjustarmourpenalty(lf, f->val[1]);
} else if (f->id == F_EVASION) {
ev += (f->val[0]);
} else if (f->id == F_SHIELDPENALTY) {
ev -= adjustshieldpenalty(lf, f->val[1]);
}
ev += (retflag[i]->val[0]);
}
// level based evasion
@ -5315,9 +5320,25 @@ int getevasion(lifeform_t *lf) {
ev += getattr(lf, A_AGI);
// apply skill based evasion modifier
skillpctmod = 100 + (getskill(lf, SK_EVASION)) * 12;
skillpctmod = 100 + (getskill(lf, SK_EVASION) * 12);
ev = pctof(skillpctmod, ev);
//////////////////////////////////////////////////
// now negative modifiers
//////////////////////////////////////////////////
// get adjustments for bulky armour/shield
getflags(lf->flags, retflag, &nretflags, F_ARMOURPENALTY, F_SHIELDPENALTY, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->id == F_ARMOURPENALTY) {
ev -= adjustarmourpenalty(lf, f->val[1]);
} else if (f->id == F_SHIELDPENALTY) {
ev -= adjustshieldpenalty(lf, f->val[1]);
}
}
// you are easier to hit if you're glowing
if (hasflag(lf->flags, F_PRODUCESLIGHT)) {
ev -= 5;
@ -8399,6 +8420,13 @@ flag_t *giveskill(lifeform_t *lf, enum SKILL id) {
makeknown(OT_MUSHROOMTOAD);
}
}
} else if (id == SK_EVASION) {
if (f->val[1] == PR_ADEPT) {
if (isplayer(lf)) {
newf = addflag(lf->flags, F_CANWILL, OT_A_SNATCH, NA, NA, NULL);
newf->lifetime = FROMSKILL;
}
}
} else if (id == SK_LORE_ARCANA) {
if (f->val[1] == PR_ADEPT) {
newf = hasflagval(lf->flags, F_CANWILL, OT_A_STUDYSCROLL, NA, NA, NULL);
@ -8788,6 +8816,7 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp) {
// SPECIAL CASES
if (lf) {
/*
if (lf->race->id == R_JAILER) {
regionoutline_t *ro;
region_t *r;
@ -8808,6 +8837,7 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp) {
}
addflag(o->flags, F_MAPTO, rt->x, rt->y, OT_GATEWOOD, "a village");
}
*/
// make sure lf doesn't start off burdened!
while (isburdened(lf)) {
@ -9901,19 +9931,15 @@ int isbehind(lifeform_t *lf, lifeform_t *otherlf) {
return B_FALSE;
}
// returns B_FALSE, B_TRUE, or B_FROMINJURY
int isbleeding(lifeform_t *lf) {
float hppct;
hppct = ((float)lf->hp / (float) lf->maxhp) * 100;
if (hppct <= 40) return B_TRUE;
if (lfhasflagval(lf, F_INJURY, NA, NA, DT_SLASH, NULL)) {
return B_FROMINJURY;
//return B_FROMINJURY;
return B_TRUE;
}
return B_FALSE;
}
int isblind(lifeform_t *lf) {
flag_t *f;
if (!lf) return B_FALSE;
@ -10241,6 +10267,14 @@ int isloreskill(enum SKILL skid) {
return B_FALSE;
}
int islowhp(lifeform_t *lf) {
float hppct;
hppct = ((float)lf->hp / (float) lf->maxhp) * 100;
if (hppct <= 40) return B_TRUE;
return B_FALSE;
}
int isspellskill(enum SKILL skid) {
switch (skid) {
case SK_SS_ALLOMANCY:
@ -11638,11 +11672,13 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml
char buf[BUFLEN];
char buf2[BUFLEN];
char lfname[BUFLEN];
int prebleed = B_FALSE,postbleed = B_FALSE,ko = B_FALSE;
int prelowhp = B_FALSE,postlowhp = B_FALSE,ko = B_FALSE;
flag_t *f;
flag_t *retflag[MAXCANDIDATES];
int nretflags;
if (gamemode < GM_GAMESTARTED) return 0;
getlfname(lf, lfname);
if (isplayer(lf)) {
@ -11650,7 +11686,7 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml
}
if (isbleeding(lf)) {
prebleed = B_TRUE;
prelowhp = B_TRUE;
}
// check for psychic armour etc
@ -11849,7 +11885,7 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml
}
if (isbleeding(lf)) {
postbleed = B_TRUE;
postlowhp = B_TRUE;
}
//////////////////////////////////////////
@ -11954,8 +11990,8 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml
}
// automatic onbleed abilities?
if (postbleed && !prebleed) {
f = lfhasflag(lf, F_BLEEDABIL);
if (postlowhp && !prelowhp) {
f = lfhasflag(lf, F_LOWHPABIL);
if (f) {
flag_t *notime;
notime = addflag(lf->flags, F_NOTIME, B_TRUE, NA, NA, NULL);
@ -12576,6 +12612,7 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nclass, int volume,
// announce?
if (isplayer(l) && !lfhasflag(l, F_ASLEEP)) {
// never say "you hear xxx" if you can see the lf that caused the noise.
// or the cell which made the noise
if (noisemaker && cansee(l, noisemaker)) {
if (seetext) {
char lfname[BUFLEN];
@ -12599,6 +12636,11 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nclass, int volume,
}
rv = B_TRUE;
}
} else if (!noisemaker && haslos(player, c)) {
// you can see the cell which made the noise
if (seetext) {
msg("%s", seetext);
}
} else if (text && !isdeaf(l) && ((nclass != NC_MOVEMENT) || !lfhasflag(l, F_DONELISTEN))) {
// this means you can only hear one 'walk' sound per turn
char textnopunc[BUFLEN];
@ -12674,7 +12716,7 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nclass, int volume,
practice(l, SK_LISTEN, 1);
}
}
} // end if !isplayer and not asleep
} // end if isplayer and not asleep
// wake up a little
f = lfhasflag(l, F_ASLEEP);
@ -13918,7 +13960,7 @@ int scare(lifeform_t *lf, lifeform_t *scarer, int howlong, int scarerbonus) {
}
// determine morale check penalty
if (isbleeding(lf)) {
if (isbleeding(lf) || islowhp(lf)) {
penalty += 5;
}
if (lfhasflag(lf, F_HUMANOID)) {
@ -16725,7 +16767,7 @@ int usestairs(lifeform_t *lf, object_t *o, int onpurpose, int climb) {
getobname(o, obname, 1);
obcell = getoblocation(o);
if (initiatemove(lf, NULL, NULL)) {
if (initiatemove(lf, NULL, onpurpose, NULL)) {
// failed?
return B_FALSE;
}
@ -16908,7 +16950,7 @@ int usestairs(lifeform_t *lf, object_t *o, int onpurpose, int climb) {
cell_t *c;
c = getrandomadjcell(newcell, WE_WALKABLE, B_ALLOWEXPAND);
if (c) {
if (!initiatemove(adjally[n], NULL, NULL)) {
if (!initiatemove(adjally[n], NULL, B_TRUE, NULL)) {
int climbtime;
stopsprinting(adjally[n]);
movelf(adjally[n], c);

3
lf.h
View File

@ -107,7 +107,7 @@ void fleefrom(lifeform_t *lf, lifeform_t *enemy, int howlong, int onpurpose);
int fovlist_contains(int *endx, int *endy, int nendcells, int x, int y);
int freezelf(lifeform_t *freezee, lifeform_t *freezer, int howlong);
void gainhp(lifeform_t *lf, int amt);
void gainlevel(lifeform_t *lf);
void gainlevel(lifeform_t *lf, int autotrain);
void gainmp(lifeform_t *lf, int amt);
void gainxp(lifeform_t *lf, long amt);
void genxplist(void);
@ -292,6 +292,7 @@ flag_t *isimmuneto(flagpile_t *fp, enum DAMTYPE dt, int onlytemp);
int isinbattle(lifeform_t *lf);
int isingunrange(lifeform_t *lf, cell_t *where);
int isloreskill(enum SKILL skid);
int islowhp(lifeform_t *lf);
int isspellskill(enum SKILL skid);
int ismadeofice(lifeform_t *lf);
int ismaxedskill(lifeform_t *lf, enum SKILL skid);

12
move.c
View File

@ -1252,6 +1252,8 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
// stop sprinting
stopsprinting(lf);
noise(lf->cell, NULL, NC_OTHER, SV_TALK, "a splash.", NULL);
}
}
}
@ -2110,7 +2112,7 @@ int pullnextto(lifeform_t *lf, cell_t *c) {
// cell can be null if you're using stairs.
// return true if something happened
int initiatemove(lifeform_t *lf, cell_t *cell, int *didmsg) {
int initiatemove(lifeform_t *lf, cell_t *cell, int onpurpose, int *didmsg) {
object_t *o, *nexto;
char buf[BUFLEN];
flag_t *f;
@ -2315,7 +2317,7 @@ int initiatemove(lifeform_t *lf, cell_t *cell, int *didmsg) {
// note however that if a monster is chasing a player (ie
// has F_TARGET,player) then they will simply avoid the cursed
// object rather than failing the movement.
if (cell) {
if (cell && onpurpose) {
for (o = cell->obpile->first ; o ; o = nexto) {
nexto = o->next;
if (!isplayer(lf)) {
@ -2602,7 +2604,7 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) {
if (moveok) {
lifeform_t *alf;
if (initiatemove(lf, cell, &dontclearmsg)) {
if (initiatemove(lf, cell, onpurpose, &dontclearmsg)) {
// failed?
return B_TRUE;
}
@ -2868,7 +2870,7 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) {
}
break;
case E_LFINWAY:
if (initiatemove(lf, cell, &dontclearmsg)) {
if (initiatemove(lf, cell, onpurpose, &dontclearmsg)) {
// failed?
return B_TRUE;
}
@ -3058,7 +3060,7 @@ int walkoffmap(lifeform_t *lf, int dir, int onpurpose) {
cell_t *c;
c = getrandomadjcell(dst, WE_WALKABLE, B_ALLOWEXPAND);
if (c) {
if (!initiatemove(adjally[n], NULL, NULL)) {
if (!initiatemove(adjally[n], NULL, B_TRUE, NULL)) {
movelf(adjally[n], c);
taketime(adjally[n], getmovespeed(adjally[n]));
}

2
move.h
View File

@ -25,7 +25,7 @@ int move_will_hurt(lifeform_t *lf);
int opendoorat(lifeform_t *lf, cell_t *c);
int opendoor(lifeform_t *lf, object_t *o);
int pullnextto(lifeform_t *lf, cell_t *c);
int initiatemove(lifeform_t *lf, cell_t *cell, int *didmsg);
int initiatemove(lifeform_t *lf, cell_t *cell, int onpurpose, int *didmsg);
int isorthogonal(int dir);
int ispossiblemove(lifeform_t *lf, int dir);
void standup(lifeform_t *lf);

View File

@ -1224,6 +1224,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
if (o && (o->type->id == OT_FOUNTAIN)) {
f = hasflag(o->flags, F_LINKOB);
if (where->where && (where->where->habitat->id != H_VILLAGE)) {
if (onein(3)) {
objecttype_t *ot;
int min,max;
@ -1233,6 +1234,9 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
if (ot) {
f->val[0] = ot->id;
}
} else {
f->val[0] = OT_POT_WATER;
}
}
}
@ -2193,8 +2197,13 @@ void applyobmod(object_t *o, obmod_t *om) {
return;
}
if ((om->id == OM_MASTERWORK) || (om->id == OM_SHODDY)) {
if (hasflag(o->flags, F_NOQUALITY)) {
if (om->id == OM_MASTERWORK) {
if (hasflag(o->flags, F_NOQUALITY) || hasflag(o->flags, F_SHODDY)) {
return;
}
}
if (om->id == OM_SHODDY) {
if (hasflag(o->flags, F_NOQUALITY) || hasflag(o->flags, F_MASTERWORK)) {
return;
}
}
@ -7483,6 +7492,10 @@ object_t *real_moveob(object_t *src, obpile_t *dst, int howmany, int stackok) {
removeob(oo, oo->amt);
}
}
if ((oo->type->id == OT_WATERDEEP) && (getmaterialstate(o->material->id) == MS_SOLID)) {
noise(dst->where, NULL, NC_OTHER, SV_TALK, "a splash.", "Splash!");
}
}
}
}
@ -9407,14 +9420,14 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, object_t *o, enum BLESSTYPE
}
if (isplayer(lf)) {
msg("You feel more experienced!");
gainxp(lf, getxpforlev(lf->level+1) - lf->xp);
// purposely not using gainxp
lf->xp = getxpforlev(lf->level+1);
} else {
if (cansee(player, lf)) {
msg("%s looks more experienced!", lfname);
}
gainlevel(lf);
enhanceskills(lf);
}
gainlevel(lf, B_TRUE);
break;
case OT_POT_GASEOUSFORM:
@ -10340,6 +10353,7 @@ int removeob(object_t *o,int howmany) {
}
if (howmany >= o->amt) {
o->dying = B_TRUE;
killob(o);
rv = 0;
} else {

14
shops.c
View File

@ -557,17 +557,25 @@ enum SHOPRETURN shoppurchase(lifeform_t *lf, object_t *vm, int starty, char *top
// list objects for sale
for (o = vm->contents->first ; o ; o = o->next) {
char obname[BUFLEN];
// get the name of the object
int thisprice;
getshopobname(o, obname, o->amt);
thisprice = (int)getshopprice(o, player);
snprintf(buf, BUFLEN, "%c - %s", o->letter, obname);
snprintf(buf2, BUFLEN, "%-60s$%d",buf,(int)getshopprice(o, player));
mvwprintw(mainwin, y, 0, "%s", buf2);
snprintf(buf2, BUFLEN, "^%d%-60s$%d",
(countmoney(player->pack) >= thisprice) ? C_GREY : C_RED,
buf, thisprice);
wmove(mainwin, y, 0);
textwithcol(mainwin, buf2);
y++;
}
strcpy(choices, "");
y++;
wmove(mainwin, y, 0);
textwithcol(mainwin, "^n");
mvwprintw(mainwin, y, 0, "You have $%d.", countmoney(player->pack));
y++;
y++;

88
spell.c
View File

@ -1235,6 +1235,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
cell_t *origcell;
int maxrange = 2;
object_t *o;
int swapped = B_FALSE;
if (isswimming(user) && !lfhasflag(user, F_AQUATIC)) {
if (isplayer(user)) msg("You can't jump while swimming!");
@ -1303,35 +1304,38 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
getlfname(victim,victimname);
// TODO: if jumper is smaller, move them out of the way instead
// move them out of the way
c = getrandomadjcell(victim->cell, WE_EMPTY, B_NOEXPAND);
// nowhere to move? move to player's cell!
if (!c) {
c = user->cell;
}
// nowhere to move? move to where the lf jumped from!
if (c) {
movelf(victim, c);
} else {
swapplaces(victim, user, B_TRUE, B_FALSE);
swapped = B_TRUE;
}
// see if you actually landed on them or they dodge...
acc = 100 - getevasion(victim);
acc = 100 - (getevasion(victim)*2);
if (rnd(1,100) > acc) {
// dodged!
dodged = B_TRUE;
}
}
if (!swapped) {
movelf(user, targcell);
}
// announce
if (isplayer(user)) {
if (victim && !dodged) {
msg("You leap high in the air and land on %s!",victimname);
msg("You leap high in the air onto %s!",victimname);
} else {
msg("You leap high in the air!");
}
} else if (haslos(player, origcell)) {
if (cansee(player, user)) {
if (victim && !dodged) {
msg("%s leaps high in the air and lands on %s!", username,victimname);
msg("%s leaps high in the air onto %s!", username,victimname);
} else {
msg("%s leaps high in the air and lands nearby!", username);
}
@ -1342,7 +1346,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
if (victim && !dodged) {
msg("%s drops from the air and lands nearby!", username);
} else {
msg("%s drops from the air and lands on %s!", username,victimname);
msg("%s drops from the air onto %s!", username,victimname);
}
}
@ -1350,6 +1354,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
for (o = targcell->obpile->first ; o ; o = o->next) {
if ((o->material->id == MT_WATER) && (o->type->id != OT_PUDDLEWATER)) {
addobburst(targcell, 1, DT_COMPASS, "small puddle of water", NULL, LOF_NEED);
noise(targcell, NULL, NC_OTHER, SV_TALK, "a splash.", "Splash!");
break;
}
}
@ -1360,11 +1365,18 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
msg("%s dodges out of the way!", victimname);
}
} else {
int dam;
// they take damage based on the jumper's weight
// 1hp per 15 kg
// TODO: make divisor be dependant on difference in lf size
dam = getlfweight(user, B_WITHOBS) / 15;
/*
int dam = 0;
int diff;
diff = getlfsize(user) - getlfsize(victim);
if (diff > 0) { // user was larger
// victim takes damage based on the jumper's weight
// 1hp per 25 kg
dam = getlfweight(user, B_WITHOBS) / 25;
} else {
// user was same size or smaller
dam = 0;
}
if (dam > 0) {
if (lfhasflag(user, F_EXTRAINFO) || lfhasflag(user, F_OMNIPOTENT)) {
msg("[%s takes %d damage]",victimname,dam);
@ -1372,6 +1384,10 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
snprintf(buf, BUFLEN, "a falling %s", user->race->name);
losehp(victim, dam, DT_BASH, user, buf);
}
*/
// both victim and attacker wall
if (!isdead(victim)) fall(victim, NULL, B_TRUE);
fall(user, NULL, B_TRUE);
}
}
} else if (abilid == OT_A_RAGE) {
@ -1683,6 +1699,41 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
// shield gets damaged
takedamage(shield, roll("1d3"), DT_DIRECT);
} else if (abilid == OT_A_SNATCH) {
object_t *o = NULL;
if (!targcell) {
int dirch;
// ask which dir
dirch = askchar("Snatch from which direction (- to cancel)", "yuhjklbn-","-", B_FALSE, B_TRUE);
if ((dirch == '-') || !dirch) {
if (isplayer(user)) msg("Cancelled.");
return B_TRUE;
} else {
int dir;
dir = chartodir(dirch);
if (dir == D_NONE) {
if (isplayer(user)) msg("Cancelled.");
return B_TRUE;
} else {
targcell = getcellindir(user->cell, dir);
}
}
}
if (targcell->obpile->first) {
// select object from cell...
o = askobject(targcell->obpile, "Snatch which object", NULL, '\0', AO_NONE);
} else {
if (isplayer(user)) msg("There is nothing there to snatch!");
return B_TRUE;
}
if (!o) {
if (isplayer(user)) msg("Cancelled.");
return B_TRUE;
}
pickup(user, o, 1, B_TRUE, B_TRUE);
} else if (abilid == OT_A_SONICBOLT) {
int volume;
@ -2366,7 +2417,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
msg("Cancelled.");
} else {
while (user->level < lev) {
gainlevel(user);
gainlevel(user, B_TRUE);
}
}
} else if (abilid == OT_A_BLINDALL) {
@ -3891,6 +3942,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
} // end while narccells
} else if (spellid == OT_S_CLONE) {
lifeform_t *lf;
// duplicate the caster
targcell = getrandomadjcell(caster->cell, WE_WALKABLE, B_NOEXPAND);
if (!targcell) {
@ -3900,7 +3952,11 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (isplayer(caster) || haslos(player, targcell)) {
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
addmonster(targcell, caster->race->id, NULL, B_FALSE, 1, B_FALSE, NULL);
lf = addmonster(targcell, caster->race->id, NULL, B_FALSE, 1, B_FALSE, NULL);
if (lf) {
killflagsofid(lf->flags, F_XPVAL);
addflag(lf->flags, F_XPVAL, 0, NA, NA, NULL);
}
} else if (spellid == OT_S_CLOUDKILL) {
int radius;

25
vaults/bazaar.vlt Normal file
View File

@ -0,0 +1,25 @@
@id:bazaar
@map
#####X#####
#..s._.s..#
#.._._._..#
X_________X
#.._._._..#
#..s._.s..#
#####X#####
@end
@legend
#:cell:rock floor
#:ob:wooden fence
_:cell:dirt
s:ob:random building
X:exit
@end
@flags
goesin:dungeon
mayrotate
rarity:vrare
@end