From 0f99007c2ad5c82088472ba8540a790320a5a105 Mon Sep 17 00:00:00 2001 From: Rob Pearce Date: Fri, 9 Dec 2011 00:37:02 +0000 Subject: [PATCH] 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 --- ai.c | 2 +- attack.c | 24 ++++++---- data.c | 20 ++++++--- data/hiscores.db | Bin 13312 -> 13312 bytes defs.h | 3 +- god.c | 4 +- io.c | 31 ++++++------- lf.c | 110 ++++++++++++++++++++++++++++++++-------------- lf.h | 3 +- move.c | 12 ++--- move.h | 2 +- objects.c | 40 +++++++++++------ shops.c | 14 ++++-- spell.c | 92 ++++++++++++++++++++++++++++++-------- vaults/bazaar.vlt | 25 +++++++++++ 15 files changed, 275 insertions(+), 107 deletions(-) create mode 100644 vaults/bazaar.vlt diff --git a/ai.c b/ai.c index 9aec84d..0d926c0 100644 --- a/ai.c +++ b/ai.c @@ -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); diff --git a/attack.c b/attack.c index 6bc8807..e10ab1e 100644 --- a/attack.c +++ b/attack.c @@ -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; - // knock back victim - dir = getdirtowards(owner->cell, victim->cell, victim, B_FALSE, DT_COMPASS); - knockback(victim, dir , 2, owner, 30, B_TRUE); - f->known = B_TRUE; + 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; diff --git a/data.c b/data.c index a67ebdf..37e32be 100644 --- a/data.c +++ b/data.c @@ -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); diff --git a/data/hiscores.db b/data/hiscores.db index a97f37a365495397986adc31241acd7204081041..0a2fc0fa2f46eaed28a1ea0c159cda665405c93e 100644 GIT binary patch delta 131 zcmV-}0DS*|Xn<&t8v&WI99{^Md7slh-pJ2ykg~VQy$)F0H$0$~6K0KT(a3QYkD2@(U{ z00adC00OhK3sD>f4*=`{0PK?pC>;e_1CIl~kwF@hMkuBPFM%Njv+yVs2LlfP;FAY1 MAdzypv*0iw13SAONdN!< diff --git a/defs.h b/defs.h index f758e4b..0c2b7ec 100644 --- a/defs.h +++ b/defs.h @@ -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 diff --git a/god.c b/god.c index 5df9a16..ea48ac3 100644 --- a/god.c +++ b/god.c @@ -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; diff --git a/io.c b/io.c index ac9acb8..a129c77 100644 --- a/io.c +++ b/io.c @@ -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); - snprintf(buf, BUFLEN, "It has a %d%% chance of preventing critical hits to your %s", - critprotchance, getbodypartname(player, f->val[0])); + 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); diff --git a/lf.c b/lf.c index 3e8ed34..47965ca 100644 --- a/lf.c +++ b/lf.c @@ -1124,7 +1124,9 @@ 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)) { - return B_FALSE; + if (!isairborne(viewee)) { + return B_FALSE; + } } } @@ -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)) { - msg("^GYou are ready to train a new experience level!"); - more(); + 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); diff --git a/lf.h b/lf.h index e689ea4..70ed3ac 100644 --- a/lf.h +++ b/lf.h @@ -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); diff --git a/move.c b/move.c index 47eaead..b4b389f 100644 --- a/move.c +++ b/move.c @@ -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])); } diff --git a/move.h b/move.h index 3ec8545..111632d 100644 --- a/move.h +++ b/move.h @@ -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); diff --git a/objects.c b/objects.c index 4ddaf21..5a7349c 100644 --- a/objects.c +++ b/objects.c @@ -1224,14 +1224,18 @@ 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)) { - objecttype_t *ot; - int min,max; - - getrarityrange(where->where->map->depth, &min, &max, RARITYVARIANCEOB, B_FALSE); - // random potion type - ot = getrandomobofclass(OC_POTION, min, max); - if (ot) { - f->val[0] = ot->id; + if (onein(3)) { + objecttype_t *ot; + int min,max; + + getrarityrange(where->where->map->depth, &min, &max, RARITYVARIANCEOB, B_FALSE); + // random potion type + ot = getrandomobofclass(OC_POTION, min, max); + 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 { diff --git a/shops.c b/shops.c index 7a7e046..f58a0b4 100644 --- a/shops.c +++ b/shops.c @@ -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++; diff --git a/spell.c b/spell.c index 8ed9844..75b17e9 100644 --- a/spell.c +++ b/spell.c @@ -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; - } - movelf(victim, c); + // 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; } } - movelf(user, targcell); + 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; diff --git a/vaults/bazaar.vlt b/vaults/bazaar.vlt new file mode 100644 index 0000000..fe2bc52 --- /dev/null +++ b/vaults/bazaar.vlt @@ -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 +