From ff13f25bb9bed2fa97b701a62024d6e7830a0714 Mon Sep 17 00:00:00 2001 From: Rob Pearce Date: Sat, 25 Feb 2012 23:42:48 +0000 Subject: [PATCH] Paladin changes - [+] average charisma + speech ? - [+] lose all/most of the warrior abilities - [+] can only voluntarily wear known blessed items (add this to the description) - [+] (glorana must give holy water when you pray) - [+] move most post-damage stuff into losehpeffects() - [+] pass "int doextraeffects" to losehp_real(). - [+] during melee attack, delay this. - [+] otehrwise, it happens in losehp! - [+] add constants for real_getobname params - [+] add constants for real_losehp params - [+] issue - should i be able to say 'have mercy' when i'm not adjacent? - [+] probably not! - [+] don't sell credit cards in shops. - [+] make crowns, velvet robes, wizard hats more likely to have brands - [+] don't say "your feet get wet" when walking from water to water - [+] fix bug in real_warnabout() where multiple warning_t instances were being made for the same text. --- attack.c | 273 ++++++++++++++++++++++++++++----------------- data.c | 13 ++- data/hiscores.db | Bin 13312 -> 13312 bytes defs.h | 25 +++++ god.c | 20 +++- io.c | 44 ++++---- lf.c | 281 ++++++++++++++++++++++++----------------------- lf.h | 3 +- objects.c | 62 ++++++----- objects.h | 1 + shops.c | 16 +++ shops.h | 1 + spell.c | 14 ++- 13 files changed, 450 insertions(+), 303 deletions(-) diff --git a/attack.c b/attack.c index 2b48253..b2972cc 100644 --- a/attack.c +++ b/attack.c @@ -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_FALSE, B_FALSE, B_TRUE, B_FALSE, B_FALSE); + real_getobname(o, obname, o->amt, B_NOPREMODS, B_NOCONDITION, B_BLINDADJUST, B_NOBLESSINGS, 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); @@ -593,6 +593,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) int weppassthrough = B_FALSE; int firstisbackstab = B_FALSE; int blocked = B_FALSE,dodged = B_FALSE; + flag_t *magicarm = NULL; int hit = B_FALSE; int critical = 0; char wepname[BUFLEN]; @@ -750,7 +751,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_FALSE, B_FALSE, B_TRUE, B_FALSE, B_FALSE); + real_getobname(armour, armname, 1, B_NOPREMODS, B_NOCONDITION, B_BLINDADJUST, B_NOBLESSINGS, B_NOSHOWALL); sprintf(noun, "%s", noprefix(armname)); } else { sprintf(noun, "%s", getbodypartname(victim, critpos)); @@ -911,20 +912,19 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) if (ndam > 0) { flag_t *f; for (i = 0; i < ndam; i++) { - int reduceamt = 0; + int damreducedbyarmour = 0; int backstab = B_FALSE; + int prebleed = B_FALSE; flag_t *rust; if (firstisbackstab && (i == 0)) backstab = B_TRUE; - //dblog("initial dam[%d] = %d",i,dam[i]); // slightly more damage for heavy blows if (lfhasflag(lf, F_HEAVYBLOW) || hasflag(wep->flags, F_HEAVYBLOW)) { dam[i] = (int)pctof(110,dam[i]); - //dblog("heavy blow makes dam[%d] = %d",i,dam[i]); } - // modify for rust + // modify for rusted weapon. rust = hasflag(wep->flags, F_RUSTED); if (rust) { switch (damtype[i]) { @@ -943,13 +943,13 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) } } + // blocked by defender's shield? if (i == 0) { int difficulty; char attackname[BUFLEN]; if (lfhasflag(lf, F_HOLYAURA) && isvulnto(victim->flags, DT_HOLY, B_FALSE)) { damtype[i] = DT_HOLY; } - // blocked by defender's shield? sprintf(attackname, "%s%s attack", attackername, getpossessive(attackername)); //difficulty = 20 + ((gethitdice(lf) - gethitdice(victim)) ); //difficulty = 20 + gethitdice(lf); @@ -960,105 +960,130 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) } } - // modify based on resistances + // modify damage based on defender's resistances adjustdamlf(victim, &dam[i], damtype[i]); //dblog("adjusted for lf to dam[%d] = %d",i,dam[i]); - if (lfhasflag(lf, F_PHANTASM)) dam[0] = 0; + // can't do damage to phantasms + if (lfhasflag(lf, F_PHANTASM)) dam[i] = 0; - // armour doesn't reduce damage for backstabs or critical hits. - // BUT in the case of a critical hit, the armour might get - // damaged during criticalhit() - if ((dam[i] > 0) && !backstab && !critical && ismeleedam(damtype[i])) { - // modify for defender's armour - reduceamt = getarmourdamreduction(victim, wep, dam[i], damtype[i]); - - applyarmourdamreduction(victim, wep, reduceamt, &dam[i], damtype[i]); - - //dblog("reduced by armour to dam[%d] = %d",i,dam[i]); + // check for protective spells like heavenly armour + if (dam[i] > 0) { + if (isphysicaldam(damtype[i])) { + getflags(victim->flags, retflag, &nretflags, F_HEAVENARM, F_MAGICARMOUR, F_NONE); + if (nretflags) { + magicarm = retflag[0]; + } + } } - // if damage has dropped to zero, it's not a critical hit anymore. - if (dam[i] <= 0) { - critical = B_FALSE; - critpos = BP_NONE; - } - if (lfhasflag(lf, F_QUIVERINGPALM)) { - // make sure damage isn't fatal + if (!magicarm) { + // armour doesn't reduce damage for backstabs or critical hits. + // BUT in the case of a critical hit, the armour might get + // damaged during the call to criticalhit() later on. + if ((dam[i] > 0) && !backstab && !critical && ismeleedam(damtype[i])) { + // modify for defender's armour + damreducedbyarmour = getarmourdamreduction(victim, wep, dam[i], damtype[i]); + + applyarmourdamreduction(victim, wep, damreducedbyarmour, &dam[i], damtype[i]); + } + + // if damage has been reduced zero, it's not a critical hit anymore. + if (dam[i] <= 0) { + critical = B_FALSE; + critpos = BP_NONE; + } + + // make sure quivering palm damage isn't fatal // becquse we want them to explode + if (lfhasflag(lf, F_QUIVERINGPALM)) { + if (dam[i] >= victim->hp) { + dam[i] = victim->hp - 1; + } + } + + // at this point, is the damage enough to be fatal? we need to know so we + // can determine whether monsters will use feign death or dodge abilities. + // NOTE: whether or not the attack is fatal is re-calculated again + // later on after damage is applied to ensure that the correct + // attack string is displayed ("you hit xxx" vs "you kill xxx"). if (dam[i] >= victim->hp) { - dam[i] = victim->hp - 1; + fatal = B_TRUE; } - } - // at this point, will the damage be fatal? we need to know so we - // can determine whether monsters will use feign death or dodge abilities. - // NOTE: whether or not the attack is fatal is re-calculated again - // later on after damage is applied to ensure that the correct - // attack string is displayed ("you hit xxx" vs "you kill xxx"). - if (dam[i] >= victim->hp) { - fatal = B_TRUE; - } + // another check for phantasms + if (lfhasflag(lf, F_PHANTASM)) dam[0] = 0; - if (lfhasflag(lf, F_PHANTASM)) dam[0] = 0; - - // monsters feigning death? - if (lfhasflag(victim, F_FEIGNINGDEATH)) { - killflagsofid(victim->flags, F_FEIGNINGDEATH); - } else if (!fatal && !isplayer(victim) && cancast(victim, OT_A_FEIGNDEATH, NULL)) { - if (onein(2) || islowhp(victim)) { - // do it! - useability(victim, OT_A_FEIGNDEATH, lf, lf->cell); - feigneddeath = B_TRUE; + // is the victim feigning death? if so, stop now. + if (lfhasflag(victim, F_FEIGNINGDEATH)) { + killflagsofid(victim->flags, F_FEIGNINGDEATH); + } else if (!fatal && !isplayer(victim) && cancast(victim, OT_A_FEIGNDEATH, NULL)) { + // monsters might pretend to be dead. + if (onein(2) || islowhp(victim)) { + // do it! + useability(victim, OT_A_FEIGNDEATH, lf, lf->cell); + feigneddeath = B_TRUE; + } } - } - if (fatal && !feigneddeath && lfhasflag(victim, F_DODGES) && cansee(victim, lf) && hasfreeaction(victim)) { - cell_t *adj; - int candodge = B_FALSE; + // did the defender use the Reflexive Dodging skill to dodge the attack? + if (fatal && !feigneddeath && lfhasflag(victim, F_DODGES) && cansee(victim, lf) && hasfreeaction(victim)) { + cell_t *adj; + int candodge = B_FALSE; - if (isplayer(victim)) { - if (getstamina(victim)) { + if (isplayer(victim)) { + if (getstamina(victim)) { + candodge = B_TRUE; + } + } else if (onein(3)) { candodge = B_TRUE; } - } else if (onein(3)) { - candodge = B_TRUE; - } - if (candodge) { - adj = getrandomadjcell(victim->cell, WE_WALKABLE, B_NOEXPAND); - if (adj) { - flag_t *f; - if (isplayer(victim) || cansee(player, victim)) { - if (cansee(player, lf)) { - msg("^w%s dodge%s %s%s attack!",victimname,isplayer(victim) ? "" : "s", - attackername, getpossessive(attackername)); - } else { - msg("^w%s dodge%s an attack!",victimname,isplayer(victim) ? "" : "s"); + if (candodge) { + adj = getrandomadjcell(victim->cell, WE_WALKABLE, B_NOEXPAND); + if (adj) { + flag_t *f; + if (isplayer(victim) || cansee(player, victim)) { + if (cansee(player, lf)) { + msg("^w%s dodge%s %s%s attack!",victimname,isplayer(victim) ? "" : "s", + attackername, getpossessive(attackername)); + } else { + msg("^w%s dodge%s an attack!",victimname,isplayer(victim) ? "" : "s"); + } + } else if (isplayer(lf)) { + msg("You attack something, but it dodges!"); + } else if (cansee(player, lf)) { + msg("%s attacks something, but it dodges!", attackername); } - } else if (isplayer(lf)) { - msg("You attack something, but it dodges!"); - } else if (cansee(player, lf)) { - msg("%s attacks something, but it dodges!", attackername); - } - f = addflag(victim->flags, F_NOTIME, B_TRUE, NA, NA, NULL); - moveto(victim, adj, B_FALSE, B_FALSE); - killflag(f); + f = addflag(victim->flags, F_NOTIME, B_TRUE, NA, NA, NULL); + moveto(victim, adj, B_FALSE, B_FALSE); + killflag(f); - if (isplayer(victim)) { - setstamina(victim, 0); + if (isplayer(victim)) { + setstamina(victim, 0); + } + // remember that we dodged, to avoid otehr attack effects like + // heavy blow, etc. + dodged = B_TRUE; + // stop processing now. + break; } - // remember that we dodged, to avoid otehr attack effects like - // heavy blow, etc. - dodged = B_TRUE; - // stop processing now. - break; } } - } - if (willheal) { + } // end if !magicarm + + prebleed = isbleeding(victim); + + // Now handle the actual hit. + + if (magicarm) { + // if you have a forcefield/magic armour, you can never be killed until + // it vanishes. + fatal = B_FALSE; + } else if (willheal) { + // some magical weapons will heal instead of doing damage if (cansee(player, victim)) { flag_t *f; if (areallies(player, victim)) { @@ -1072,12 +1097,13 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) } } gainhp(victim, dam[i]); - reduceamt = 0; + damreducedbyarmour = 0; } else if (lfhasflag(lf, F_QUIVERINGPALM)) { // victim explodes! - losehp_real(victim, victim->hp, DT_EXPLOSIVE, lf, "a quivering palm strike", B_FALSE, NULL, B_FALSE, NULL); - reduceamt = 0; + losehp_real(victim, victim->hp, DT_EXPLOSIVE, lf, "a quivering palm strike", B_FALSE, NULL, B_FALSE, NULL, B_FALSE); + damreducedbyarmour = 0; } else { + // actually deal the melee damage! char attackername2[BUFLEN]; real_getlfname(lf, attackername2, B_FALSE, B_TRUE); if (lf->race->raceclass->id == RC_GOD) { @@ -1090,11 +1116,11 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) } strcat(attackername2, gf->text); } - // victim loses hp - // don't adjust damage - we've already done that + + // get name of weapon/attacker, for "killedby" text if (wep && !isunarmed) { char wepname[BUFLEN]; - real_getobname(wep, wepname, 1, B_TRUE, B_FALSE, B_FALSE, B_TRUE, B_FALSE); + real_getobname(wep, wepname, 1, B_PREMODS, B_NOCONDITION, B_NOBLINDADJUST, B_BLESSINGS, B_NOSHOWALL); /* snprintf(buf, BUFLEN, "%s^%s %s",attackername2, (lf == victim) ? "using" : "weilding", @@ -1105,7 +1131,18 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) } else { strcpy(buf, attackername2); } - losehp_real(victim, dam[i], damtype[i], lf, buf, B_FALSE, wep, B_FALSE, &waskod); + + // apply damage to victim + // note: we delay extra effects from the damage so that we get a chance to first annoiunce + // the hit. + // + // otherwise the messages are in the wrong order, eg: + // "the fire sets you alight!" + // "xxx hits you with a flaming sword." + + // don't adjust damage for resistences - we've already done that + losehp_real(victim, dam[i], damtype[i], lf, buf, B_NODAMADJUST, wep, B_NORETALIATE, + &waskod, B_NODAMEFFECTS); } // was it fatal ? override previously calculated value. if ((victim->hp <= 0) && !waskod) { @@ -1113,7 +1150,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) } else { fatal = B_FALSE; } - // announce it + // announce the hit if (!feigneddeath) { if (isplayer(lf) || isplayer(victim) || cansee(player, lf) || cansee(player, victim)) { construct_hit_string(lf, victim, attackername, victimname, victimbpname, wep, damtype[i], dam[i], victim->maxhp, i, backstab, critical, fatal, isunarmed, buf); @@ -1121,8 +1158,6 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) warn("%s", buf); } } - //if (!isplayer(lf) && !isplayer(victim)) { - //} if (fatal) { if (strstr(buf, "behead")) { // we'll need to place the severed head object @@ -1135,20 +1170,53 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) } } } + } // end if !feigneddeath + + // now magic armour will pulse and maybe vanish. + if (magicarm) { + int damprevented; + // prevent all damage if possible + damprevented = dam[i]; + magicarm->val[0] -= damprevented; + if (magicarm->val[0] <= 0) { + // did magic armour come from a spell? + if (magicarm->lifetime == FROMSPELL) { + flag_t *spellflag; + spellflag = hasactivespell(victim, magicarm->obfrom); + if (spellflag) { + killflag(spellflag); + } + } + // magic armour vanishes now. + killflag(magicarm); + } else { + if (cansee(player, victim)) { + msg("^%c%s%s %s pulses!^n", + CC_GOOD, + victimname, getpossessive(victimname), + magicarm->text); + } + } + } else { + // victim's armour loses hp. note that it loses the full + // amount of damage dealt, not just what it reduced. + if (damreducedbyarmour && !critical) { + applyarmourdamage(victim, wep, dam[i], damtype[i], lf); + // train armour + practice(victim, SK_ARMOUR, 1); + } } // make noise noise(lf->cell, lf, NC_FIGHTING, SV_SHOUT, "fighting.", NULL); - // victim's armour loses hp - if (reduceamt && !critical) { - applyarmourdamage(victim, wep, dam[i], damtype[i], lf); - // train armour - practice(victim, SK_ARMOUR, 1); - } if (backstab) { practice(lf, SK_BACKSTAB, 1); } + + // 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! } // end foreach damtype @@ -1186,10 +1254,10 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) char lfname[BUFLEN]; dam = rolldie(f->val[0], f->val[1]) + f->val[2]; real_getlfname(lf, lfname, B_FALSE, B_FALSE); - losehp_real(victim, dam, DT_BITE, lf, lfname, B_FALSE, NULL, B_FALSE, NULL); if (isplayer(victim) || cansee(player, victim)) { msg("^%c%s bites %s!", isplayer(victim) ? 'b' : 'n', lfname, victimname); } + losehp_real(victim, dam, DT_BITE, lf, lfname, B_FALSE, NULL, B_FALSE, NULL, B_TRUE); } } @@ -1212,10 +1280,10 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) if (nmatched >= f->val[2]) { char damstring[BUFLEN]; snprintf(damstring, BUFLEN, "%s pack", lfname); - losehp_real(victim, f->val[0], f->val[1], lf, damstring, B_TRUE, NULL, B_FALSE, NULL); if (isplayer(victim) || cansee(player, victim)) { msg("^%c%s pack attacks %s!", isplayer(victim) ? 'b' : 'c', lfname, victimname); } + losehp_real(victim, f->val[0], f->val[1], lf, damstring, B_TRUE, NULL, B_FALSE, NULL, B_TRUE); } } @@ -1282,7 +1350,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) attackername); } snprintf(damstring, BUFLEN, "%s%s %s", victimname, getpossessive(victimname), noprefix(f->text)); - losehp_real(lf, rdam, f->val[2], victim, damstring, B_TRUE, NULL, B_TRUE, NULL); + losehp_real(lf, rdam, f->val[2], victim, damstring, B_TRUE, NULL, B_TRUE, NULL, B_TRUE); } } } @@ -1709,7 +1777,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_TRUE, B_FALSE, B_TRUE, B_FALSE, B_FALSE); + real_getobname(shield[i], shname, 1, B_PREMODS, B_NOCONDITION, B_BLINDADJUST, B_NOBLESSINGS, 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 @@ -1922,7 +1990,6 @@ int getarmourdamreduction(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE d reduceamt = rnd(min, max); - // special case if (damtype == DT_PROJECTILE) { o = getequippedob(lf->pack, BP_BODY); diff --git a/data.c b/data.c index 38c0ea9..b0d9dd6 100644 --- a/data.c +++ b/data.c @@ -157,12 +157,12 @@ void initjobs(void) { // subjob definitions - keep these in alphabetical order addsubjob(SJ_BATTLEMAGE, "Battlemage", "Unlike other warriors Battlemages are skilled in magic, but at the expense of the regular warrior abilities.", 'b'); - addsubjob(SJ_FIREMAGE, "Firemage", "", 'f'); - addsubjob(SJ_ICEMAGE, "Icemage", "", 'i'); + addsubjob(SJ_FIREMAGE, "Firemage", "Firemages weild the destructive powers of fire to incinerate their enemies.", 'f'); + addsubjob(SJ_ICEMAGE, "Icemage", "Icemages are masters over the powers of cold. Their magic is less direct damaging than that of their fire-based cousins, but can also be used for defence.", 'i'); addsubjob(SJ_NECROMANCER, "Necromancer", "", 'n'); - addsubjob(SJ_PALADIN, "Paladin", "Paladins are holy warriors dedicated to the Goddess of Life. They have access to powerful healing magic, but this power is dependant upon their goddess' approval.", 'p'); + addsubjob(SJ_PALADIN, "Paladin", "Paladins are holy warriors dedicated to the Goddess of Life. They gain powerful abilities and have access to healing magics, but these powers are dependant upon their goddess' approval. Paladins must take holy vows to only ever use battle equipiment which has first been blessed.", 'p'); addsubjob(SJ_SCOURGE, "Scourge", "Scourges have dedicated their life to ridding the world of magic. Strict training has granted them an innate immunity to magic, but this immunity also extends to beneficial effects.", 's'); - addsubjob(SJ_AIRMAGE, "Skymage", "", 's'); + addsubjob(SJ_AIRMAGE, "Skymage", "Initially the weakest of the mages, higher level Skymages become both extremely versatile and extremely power.", 's'); addsubjob(SJ_WILDMAGE, "Wizard", "", 'w'); // job definitions @@ -5779,6 +5779,8 @@ void initobjects(void) { addflag(lastot->flags, F_ARMOURRATING, 1, NA, NA, NULL); addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL); addflag(lastot->flags, F_CRITPROTECTION, 75, NA, NA, NULL); + addflag(lastot->flags, F_BRANDCHANCE, 20, NA, NA, NULL); + // armour - shoulders @@ -6000,6 +6002,7 @@ void initobjects(void) { addflag(lastot->flags, F_ARMOURRATING, 1, NA, NA, NULL); addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL); addflag(lastot->flags, F_CRITPROTECTION, 33, NA, NA, NULL); + addflag(lastot->flags, F_BRANDCHANCE, 30, NA, NA, NULL); addot(OT_HELMBONE, "bone helmet", "Scary-looking helmet made from the bones of an animal (?).", MT_BONE, 1, OC_ARMOUR, SZ_SMALL); addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_COMMON, NULL); addflag(lastot->flags, F_RARITY, H_FOREST, 100, RR_UNCOMMON, NULL); @@ -6016,6 +6019,7 @@ void initobjects(void) { addflag(lastot->flags, F_NOQUALITY, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, "pointy hat"); addflag(lastot->flags, F_CRITPROTECTION, 100, NA, NA, NULL); + addflag(lastot->flags, F_BRANDCHANCE, 15, NA, NA, NULL); // armour - ears addot(OT_EARPLUGS, "set of earplugs", "A pair of cloth plugs designed to give the wearer a peaceful night's sleep. ", MT_CLOTH, 0.01, OC_ARMOUR, SZ_SMALL); @@ -9908,6 +9912,7 @@ void initrace(void) { addrace(R_SPRITEGRAVE, "grave sprite", 5, 'n', C_BLUE, MT_FLESH, RC_MAGIC, "A small magical creature made from corpse dust."); setbodytype(lastrace, BT_HUMANOID); + addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL); addflag(lastrace->flags, F_NOCORPSE, NA, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, AT_LOW, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, AT_AVERAGE, NA, NULL); diff --git a/data/hiscores.db b/data/hiscores.db index 90903bcfbfc13323a39ad793b54ba544f3357a9f..43ba885ae067112f66cc0b97a6f0fa96783c7198 100644 GIT binary patch delta 249 zcmV;vZm;setI$pgd#zXP=cumh`; zA_%av&C0<%mCSOEqKR|C2L1+%IPSOgX<00;o`008m^?c_3jRXK7(> zbRcGRZf<34cV%KAZ*CxLWp-t3ATuCuW*~HEWgus7Vr*${AY);60%dcvg)n;qqWelH delta 227 zcmV<90382-Xn<&t8v&NF9OVZg0!RR40geCz`vdU<>;vZm;setI$pgd#zXP=cumh_D zrjsBDu(Q$#b^!zffB*)wObS>51_f6H0{{WDstZ^I7FPfX0P+9;@&POXi2@1&Jp$|l zBLil$7!VWzlRzCTvse+V9%l^zh5!JD0JZ?+0T=;C0eS(#0uTaQ0;U4}14sk205bq5 z189O82LJ*SErBHoZvX%QQvd-IHE{rPZ(>Y#F(62FZDDR8LSb}tY-Md>XJt!iY;0v@ dAYyqSVIX8>VRUF9Xm53HWRop38?%NmdIR;aKv4hy diff --git a/defs.h b/defs.h index 106d435..c7c032b 100644 --- a/defs.h +++ b/defs.h @@ -142,6 +142,29 @@ #define B_BIG (-1) +// for losehp_real +#define B_DAMADJUST (-1) +#define B_NODAMADJUST (0) + +#define B_RETALIATE (-1) +#define B_NORETALIATE (0) + +#define B_DAMEFFECTS (-1) +#define B_NODAMEFFECTS (0) + +// for real_getobname +#define B_PREMODS (-1) +#define B_NOPREMODS (0) +#define B_CONDITION (-1) +#define B_NOCONDITION (0) +#define B_BLINDADJUST (-1) +#define B_NOBLINDADJUST (0) +#define B_BLESSINGS (-1) +#define B_NOBLESSINGS (0) +#define B_SHOWALL (-1) +#define B_NOSHOWALL (0) + + // Limits // must be >= max # of spells/abilities AND @@ -2140,6 +2163,7 @@ enum FLAG { F_BATTLESPOILS, // this obejct was dropped by a monster which the // player killed, and has not yet been touched. F_BEINGUSED, // this object is currently being used + F_BRANDCHANCE, // this object has v0% extra chance of being branded F_DEAD, // object will be removed F_ONEPERCELL, // only one of these objects can exist per cell F_ONLYINROOM, // object nay only appear in rooms (not corridors) @@ -3408,6 +3432,7 @@ enum ERROR { E_NOLOS, E_NOLOF, E_IMPOSSIBLE, + E_PALADIN, E_NOTARGET, E_NOAMMO, E_GRAVBOOSTED, diff --git a/god.c b/god.c index 2b85355..0b7d532 100644 --- a/god.c +++ b/god.c @@ -1661,6 +1661,7 @@ void pleasegodmaybe(enum RACE rid, int amt) { int prayto(lifeform_t *lf, lifeform_t *god) { int piety,i,x,y; char assisttext[BUFLEN]; + enum PIETYLEV plev; taketime(lf, getactspeed(lf)); @@ -1702,7 +1703,7 @@ int prayto(lifeform_t *lf, lifeform_t *god) { // if we get here, piety is >= 100. // you get some help... - + plev = getpietylev(god->race->id, NULL, NULL); switch (god->race->id) { case R_GODBATTLE: strcpy(assisttext, "Message received, soldier!"); @@ -2018,8 +2019,8 @@ int prayto(lifeform_t *lf, lifeform_t *god) { dospelleffects(NULL, OT_S_SATEHUNGER, 10, player, NULL, player->cell, B_UNCURSED, NULL, B_FALSE); donesomething = B_TRUE; } - if (lf->mp < getmaxmp(lf)) { - gainmp(lf, getmaxmp(lf)); + if (lf->mp < (getmaxmp(lf)/2)) { + gainmp(lf, getmaxmp(lf)/2); donesomething = B_TRUE; } if (lfhasflag(lf, F_INJURY)) { @@ -2030,13 +2031,20 @@ int prayto(lifeform_t *lf, lifeform_t *god) { gainhp(lf, lf->maxhp); donesomething = B_TRUE; statdirty = B_TRUE; - } if (isinbattle(lf, B_TRUE)) { - enum PIETYLEV plev; - plev = getpietylev(R_GODLIFE, NULL, NULL); if (plev >= PL_INDIFFERENT) { dospelleffects(NULL, OT_S_HEAVENARM, plev+1, player, NULL, player->cell, B_UNCURSED, NULL, B_FALSE); + donesomething = B_TRUE; + } + } + // will bless player's water if nothing else done. + if (!donesomething && (plev >= PL_PLEASED)) { + object_t *o; + for (o = player->pack->first ; o ; o = o->next) { + if ((o->type->id == OT_POT_WATER) && !isblessed(o)) { + blessob(o); + } } } if (donesomething) { diff --git a/io.c b/io.c index 89f6113..f7b677b 100644 --- a/io.c +++ b/io.c @@ -780,7 +780,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_FALSE, B_FALSE, B_TRUE, B_FALSE, B_FALSE); + real_getobname(o, obname, o->amt, B_NOPREMODS, B_NOCONDITION, B_BLINDADJUST, B_NOBLESSINGS, B_NOSHOWALL); if (strlen(extrainfo)) strcat(extrainfo, ", "); snprintf(buf2, BUFLEN, "stuck in %s",obname); strcat(extrainfo, buf2); @@ -2569,7 +2569,7 @@ int announceobflaggain(object_t *o, flag_t *f) { wantpremods = B_FALSE; } - real_getobname(o, obname, o->amt, wantpremods, B_FALSE, B_TRUE, B_TRUE, B_FALSE); + real_getobname(o, obname, o->amt, wantpremods, B_NOPREMODS, B_CONDITION, B_BLESSINGS, B_NOSHOWALL); if (o->pile->owner) { @@ -2622,7 +2622,7 @@ void announceobflagloss(object_t *o, flag_t *f) { if (!haslos(player, loc)) { return; } - real_getobname(o, obname, o->amt, B_TRUE, B_FALSE, B_TRUE, B_TRUE, B_FALSE); + real_getobname(o, obname, o->amt, B_PREMODS, B_NOCONDITION, B_BLINDADJUST, B_BLESSINGS, B_NOSHOWALL); if (o->pile->owner) { if (isplayer(o->pile->owner)) { @@ -3951,23 +3951,24 @@ void docomms(lifeform_t *lf) { } } - if (areenemies(player, lf)) { - addchoice(&prompt, 'm', "Have mercy!", NULL, NULL, NULL); - } - - // if you are allies, use 'trade items' instead - if (isadjacent(lf->cell, player->cell) && !areallies(player,lf)) { - if (isgod(lf)) { - // may only donate the godstone - godstone = hasob(player->pack, getopposinggodstone(lf->race->id)); - if (godstone) { - char buf[BUFLEN],obname[BUFLEN]; - getobname(godstone, obname, 1); - sprintf(buf, "(offer %s)", obname); - addchoice(&prompt, 'd', buf, NULL, NULL, NULL); + if (isadjacent(lf->cell, player->cell)) { + if (areenemies(player, lf)) { + addchoice(&prompt, 'm', "Have mercy!", NULL, NULL, NULL); + } + // if yo are allies, use 'trade items' instead + if (!areallies(player, lf)) { + if (isgod(lf)) { + // may only donate the godstone + godstone = hasob(player->pack, getopposinggodstone(lf->race->id)); + if (godstone) { + char buf[BUFLEN],obname[BUFLEN]; + getobname(godstone, obname, 1); + sprintf(buf, "(offer %s)", obname); + addchoice(&prompt, 'd', buf, NULL, NULL, NULL); + } + } else { + addchoice(&prompt, 'd', "(donate an item)", NULL, NULL, NULL); } - } else { - addchoice(&prompt, 'd', "(donate an item)", NULL, NULL, NULL); } } @@ -12921,8 +12922,10 @@ int real_warnabout(char *what, int lifetime, int doquestion) { // have we already warned about this? w = findwarning(what); if (w) { - w->lifetime = DEF_WARNINGTIME; + // if so, just update the existing warning's lifetime + w->lifetime = lifetime; ch = 'y'; + return B_TRUE; } else if (doquestion) { char ques[BUFLEN]; sprintf(ques, "%s", what); @@ -12934,6 +12937,7 @@ int real_warnabout(char *what, int lifetime, int doquestion) { ch = 'y'; } if (ch == 'y') { + // accepted the warning. add it to the list. addwarning(what, lifetime); return B_TRUE; } diff --git a/lf.c b/lf.c index 3413a7f..5951a03 100644 --- a/lf.c +++ b/lf.c @@ -16,6 +16,7 @@ #include "move.h" #include "nexus.h" #include "objects.h" +#include "shops.h" #include "spell.h" #include "text.h" @@ -1291,6 +1292,13 @@ int canwear(lifeform_t *lf, object_t *o, enum BODYPART where) { reason = E_IMPOSSIBLE; return B_FALSE; } + // paladin? + if (getsubjob(lf) == SJ_PALADIN) { + if (!isblessed(o) || !o->blessknown) { + reason = E_PALADIN; + return B_FALSE; + } + } // injuries? if ((where == BP_HANDS) && lfhasflagval(lf, F_INJURY, IJ_HANDSWOLLEN, NA, NA, NULL)) { reason = E_INJURED; @@ -1398,6 +1406,14 @@ int canweild(lifeform_t *lf, object_t *o) { return B_FALSE; } + // paladin? + if (getsubjob(lf) == SJ_PALADIN) { + if (!isblessed(o) || !o->blessknown) { + reason = E_PALADIN; + return B_FALSE; + } + } + // too heavy? if (o && lfhasflagval(lf, F_INJURY, IJ_SHOULDERDISLOCATED, NA, NA, NULL)) { if (isheavyweapon(o)) { @@ -2055,7 +2071,7 @@ int checkfordrowning(lifeform_t *lf, object_t *o) { } addflag(lf->flags, F_NODEATHANNOUNCE, B_TRUE, NA, NA, NULL); lf->hp = 0; - real_getobname(o, obname, o->amt, B_FALSE, B_FALSE, B_FALSE, B_FALSE, B_TRUE); + getobnametruebase(o, obname, o->amt); setlastdam(lf, obname); setkillverb(lf, "Drowned"); } else { @@ -2069,7 +2085,7 @@ int checkfordrowning(lifeform_t *lf, object_t *o) { msg("^%c%s is drowning!", getlfcol(lf, CC_VBAD), lfname); didsomething = B_TRUE; } - real_getobname(o, obname, o->amt, B_FALSE, B_FALSE, B_FALSE, B_FALSE, B_TRUE); + getobnametruebase(o, obname, o->amt); losehp(lf, damamt, DT_DIRECT, NULL, obname); setlastdam(lf, obname); setkillverb(lf, "Drowned"); @@ -3745,8 +3761,9 @@ int eat(lifeform_t *lf, object_t *o) { } if (fid != F_NONE) { // lose half your max hp! - losehp_real(lf, (lf->maxhp/2), DT_DIRECT, NULL, "the shock of mutation", - B_FALSE, o, B_FALSE, NULL); + losehp_real(lf, (lf->maxhp/2), DT_DIRECT, NULL, + "the shock of mutation", + B_NODAMADJUST, o, B_NORETALIATE, NULL, B_DAMEFFECTS); if (isplayer(lf)) { msg("^%cYou convulse in agony as your body mutates!", getlfcol(lf, CC_BAD)); @@ -7807,7 +7824,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_TRUE, B_FALSE, B_FALSE, B_FALSE, B_FALSE); + real_getobname(wep, obname, 1, B_PREMODS, B_NOCONDITION, B_NOBLINDADJUST, B_NOBLESSINGS, B_NOSHOWALL); snprintf(buf, BUFLEN, "%s%s%s",the,descstring,noprefix(obname)); } else { snprintf(buf, BUFLEN, "%s%s%s%s",the,descstring,lname,jobstring); @@ -9435,9 +9452,11 @@ void givesubjob(lifeform_t *lf, enum SUBJOB sj) { killflagsofid(lf->flags, F_LEVABIL); break; case SJ_PALADIN: - // healing magic + // extra skills - healing magic & speech giveskilllev(lf, SK_SS_LIFE, PR_NOVICE); sb1 = addob(lf->pack, "spellbook of life magic"); + giveskilllev(lf, SK_SPEECH, PR_NOVICE); + // must worship glorana if (isplayer(lf)) { lifeform_t *god; @@ -9447,17 +9466,24 @@ void givesubjob(lifeform_t *lf, enum SUBJOB sj) { // raise WIS to gtaverage for life magic lf->baseatt[A_WIS] = rollattr(AT_GTAVERAGE); lf->att[A_WIS] = lf->baseatt[A_WIS]; + // raise CHA to average for speech + if (getattrbracket(getattr(lf, A_CHA), A_CHA, NULL) < AT_AVERAGE) { + lf->baseatt[A_CHA] = rollattr(AT_AVERAGE); + lf->att[A_CHA] = lf->baseatt[A_CHA]; + } // can permenantly turn undead for 0 power. addtempflag(lf->flags, F_CANWILL, OT_S_TURNUNDEAD, NA, NA, NULL, FROMJOB); if (isplayer(lf)) { addflag(lf->flags, F_SHORTCUT, getnextshortcut(lf), NA, NA, "turn undead"); } - // all gear is blessed + // all starting gear is blessed for (o = lf->pack->first ; o ; o = o->next) { if (isequipped(o)) { blessob(o); } } + // remove warrior's level abilities + killflagsofid(lf->flags, F_LEVABIL); break; case SJ_SCOURGE: addtempflag(lf->flags, F_RESISTMAG, 5, NA, NA, NULL, FROMJOB); @@ -10126,7 +10152,7 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp) { default: break; } if (real_getrandomob(targmap, buf, targmap->depth + depthmod, NA, maxobsize, SK_NONE, B_TRUE, OC_NONE, DT_NONE)) { - if (isshop && strstr(buf, "gold coin")) strcpy(buf, "potion of water"); + if (isshop) apply_shopob_restrictions(buf); o = addob(op, buf); } } @@ -10145,7 +10171,7 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp) { } if (real_getrandomob(targmap, buf, targmap->depth + depthmod, NA, maxobsize, SK_NONE, B_TRUE, OC_NONE, val[1], DT_NONE)) { if (db) snprintf(buf2, BUFLEN, "finished startobdt successfuly."); - if (isshop && strstr(buf, "gold coin")) strcpy(buf, "potion of water"); + if (isshop) apply_shopob_restrictions(buf); o = addob(op, buf); } else { if (db) snprintf(buf2, BUFLEN, "finished startobdt, failed."); @@ -10192,7 +10218,7 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp) { if (real_getrandomob(targmap, buf, getmapdifficulty(targmap) + depthmod, NA, maxobsize, SK_NONE, B_TRUE, val[1], OC_NONE, DT_NONE)) { if (db) snprintf(buf2, BUFLEN, "finished startobclass, success."); - if (isshop && strstr(buf, "gold coin")) strcpy(buf, "potion of water"); + if (isshop) apply_shopob_restrictions(buf); o = addob(op, buf); } else { //obdb = B_FALSE; @@ -13507,18 +13533,16 @@ void loseconsciousness(lifeform_t *lf, int howlong, lifeform_t *fromlf) { // lose hp, and adjust damage based on resistances int losehp(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *fromlf, char *damsrc) { - return losehp_real(lf, amt, damtype, fromlf, damsrc, B_TRUE, NULL, B_TRUE, NULL); + return losehp_real(lf, amt, damtype, fromlf, damsrc, B_DAMADJUST, NULL, B_RETALIATE, NULL, B_DAMEFFECTS); } // returns the amt of damage taken -int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *fromlf, char *damsrc, int reducedam, object_t *fromob, int retaliate, int *waskod) { +int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *fromlf, char *damsrc, int reducedam, object_t *fromob, int retaliate, int *waskod, int doeffects) { char buf[BUFLEN]; char buf2[BUFLEN]; char lfname[BUFLEN]; - int prelowhp = B_FALSE,postlowhp = B_FALSE,ko = B_FALSE; + int prelowhp = B_FALSE,ko = B_FALSE; flag_t *f; - flag_t *retflag[MAXCANDIDATES]; - int nretflags; if (gamemode < GM_GAMESTARTED) return 0; @@ -13532,43 +13556,6 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml prelowhp = B_TRUE; } - // check for protective spells - if (amt > 0) { - if (isphysicaldam(damtype)) { - int i; - getflags(lf->flags, retflag, &nretflags, F_HEAVENARM, F_MAGICARMOUR, F_NONE); - for (i = 0; i < nretflags; i++) { - int damtaken; - f = retflag[i]; - damtaken = amt; - if (damtaken > f->val[0]) { - damtaken = f->val[0]; - } - f->val[0] -= damtaken; - if (f->val[0] <= 0) { - // from a spell? - if (f->lifetime == FROMSPELL) { - flag_t *spellflag; - spellflag = hasactivespell(lf, f->obfrom); - if (spellflag) { - killflag(spellflag); - } - } - killflag(f); - } else { - if (cansee(player, lf)) { - char lfname[BUFLEN]; - getlfname(lf, lfname); - msg("%s%s %s pulses!", lfname, getpossessive(lfname), f->text); - } - } - - // reduce damage - amt -= damtaken; - } - } - } - // adjust for source object's material if (fromob) { @@ -13729,69 +13716,13 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml // if they died if (lf->hp <= 0) { - //if (!fromlf || (fromlf == player)) { if (fromlf && (getallegiance(fromlf) == AL_FRIENDLY)) { addflag(lf->flags, F_KILLEDBYPLAYER, B_TRUE, NA, NA, NULL); } - } else { - // effects based on damage type - if (damtype == DT_COLD) { - int i; - if (lfhasflag(lf, F_COLDBLOOD)) { - // slow them - addtempflag(lf->flags, F_SLOWMOVE, 5, NA, NA, NULL, 10); - } - // catch a cold? - if (!skillcheck(lf, SC_CON, (amt/2) + getexposedlimbs(lf), 0)) { - poison(lf, 20+(amt*3), P_COLD, 0, "the cold"); - } - // cold will heal bruised limbs - getflags(lf->flags, retflag, &nretflags, F_INJURY, F_NONE); - for (i = 0; i < nretflags; i++) { - f = retflag[i]; - if (f->lifetime > 0) { - if ((f->val[0] == IJ_LEGBRUISE) || (f->val[0] == IJ_BLACKEYE)) { - f->lifetime -= 5; - limit(&f->lifetime, 1, NA); - } - } - } - if (fromlf) { - angergodmaybe(R_GODFIRE, 25, GA_HERESY); - } - } else if (damtype == DT_FIRE) { - int i; - // fire will cauterise slash wounds - getflags(lf->flags, retflag, &nretflags, F_FLAMMABLELF, F_INJURY, F_NONE); - for (i = 0; i < nretflags; i++) { - f = retflag[i]; - if (f->id == F_FLAMMABLELF) { - if (isplayer(lf)) { - msg("You are engulfed in flames!"); - } else if (cansee(player, lf)) { - char lfname[BUFLEN]; - getlfname(lf, lfname); - msg("%s is engulfed in flames!", lfname); - } - addobfast(lf->cell->obpile, OT_FIRESMALL); - } else if (f->id == F_INJURY) { - if ((f->val[1] == DT_SLASH) && (f->lifetime > 0)) { - f->lifetime -= 20; - limit(&f->lifetime, 1, NA); - } - } - } - } else if (damtype == DT_POISONGAS) { - if (amt > 0) { - if (!skillcheck(lf, SC_POISON, 35, 0)) { // HARD. - poison(lf, rnd(20,40), P_GAS, 2, "poison gas"); - } - } - } } - if (isbleeding(lf)) { - postlowhp = B_TRUE; + if (doeffects) { + losehpeffects(lf, amt, damtype, fromlf, fromob, retaliate, ko, waskod, prelowhp); } ////////////////////////////////////////// @@ -13808,7 +13739,6 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml strcpy(buf, damsrc); } - // fill in damage amount snprintf(buf2, BUFLEN, "^%d damage",amt); strcat(buf, buf2); @@ -13849,6 +13779,74 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml } } + // update screen + drawstatus(); + updatestatus(); + return amt; +} + +void losehpeffects(lifeform_t *lf, int dam, enum DAMTYPE damtype, lifeform_t *fromlf, object_t *fromob, int retaliate, int ko, int *waskod, int prelowhp) { + int postlowhp = B_FALSE; + flag_t *retflag[MAXCANDIDATES],*f; + int nretflags; + char buf[BUFLEN],lfname[BUFLEN]; + if (lf->hp > 0) { + // effects based on damage type + if (damtype == DT_COLD) { + int i; + if (lfhasflag(lf, F_COLDBLOOD)) { + // slow them + addtempflag(lf->flags, F_SLOWMOVE, 5, NA, NA, NULL, 10); + } + // catch a cold? + if (!skillcheck(lf, SC_CON, (dam/2) + getexposedlimbs(lf), 0)) { + poison(lf, 20+(dam*3), P_COLD, 0, "the cold"); + } + // cold will heal bruised limbs + getflags(lf->flags, retflag, &nretflags, F_INJURY, F_NONE); + for (i = 0; i < nretflags; i++) { + f = retflag[i]; + if (f->lifetime > 0) { + if ((f->val[0] == IJ_LEGBRUISE) || (f->val[0] == IJ_BLACKEYE)) { + f->lifetime -= 5; + limit(&f->lifetime, 1, NA); + } + } + } + if (fromlf) { + angergodmaybe(R_GODFIRE, 25, GA_HERESY); + } + } else if (damtype == DT_FIRE) { + int i; + // fire will ignire flammable lifeforms, cauterise slash wounds, etc + getflags(lf->flags, retflag, &nretflags, F_FLAMMABLELF, F_INJURY, F_NONE); + for (i = 0; i < nretflags; i++) { + f = retflag[i]; + if (f->id == F_FLAMMABLELF) { + if (isplayer(lf)) { + msg("You are engulfed in flames!"); + } else if (cansee(player, lf)) { + char lfname[BUFLEN]; + getlfname(lf, lfname); + msg("%s is engulfed in flames!", lfname); + } + addobfast(lf->cell->obpile, OT_FIRESMALL); + } else if (f->id == F_INJURY) { + if ((f->val[1] == DT_SLASH) && (f->lifetime > 0)) { + f->lifetime -= 20; + limit(&f->lifetime, 1, NA); + } + } + } + } else if (damtype == DT_POISONGAS) { + if (dam > 0) { + if (!skillcheck(lf, SC_POISON, 35, 0)) { // HARD. + poison(lf, rnd(20,40), P_GAS, 2, "poison gas"); + } + } + } + } // end if hp > 0 + // special cases if (lf->race->id == R_FUNGUSDREAM) { char buf2[BUFLEN]; @@ -13862,6 +13860,11 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml spellcloud(lf->cell, 3, UNI_SHADELIGHT, C_RED, OT_A_RAGE, 8, B_TRUE, buf, buf2); } + + if (isbleeding(lf)) { + postlowhp = B_TRUE; + } + // further effects if not dead... if (!isdead(lf)) { // fight back if required @@ -13869,16 +13872,6 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml fightback(lf, fromlf); } - // low hitpoint warning - if (isplayer(lf) && (amt > 0)) { - int warnthresh; - warnthresh = (int)((float)0.25 * (float)lf->maxhp); - if ((lf->hp <= warnthresh) && (lf->hp > 0)) { - warn("*** LOW HITPOINT WARNING ***"); - more(); - } - } - if (ko) { int kotime; // is waskod was passed, allow the calling function to actually @@ -13920,12 +13913,12 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml // fire: dam*10 chance of burning each object which is vulnerable to fire for (o = lf->pack->first ; o ; o = nexto) { nexto = o->next; - if (isvulnto(o->flags, DT_FIRE, B_FALSE) && pctchance(amt*10)) { + if (isvulnto(o->flags, DT_FIRE, B_FALSE) && pctchance(dam*10)) { int newdam; nburnt++; - if (nburnt >= (amt/5)) break; + if (nburnt >= (dam/5)) break; // object takes 1/4 of damage - newdam = pctof(25, amt); + newdam = pctof(25, dam); limit(&newdam, 1, NA); takedamage(o, newdam, DT_FIRE); } @@ -13935,10 +13928,10 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml // cold: dam*10 chance of shattering potions, or damaging other things. for (o = lf->pack->first ; o ; o = nexto) { nexto = o->next; - if (isvulnto(o->flags, DT_COLD, B_FALSE) && pctchance(amt*10)) { + if (isvulnto(o->flags, DT_COLD, B_FALSE) && pctchance(dam*10)) { int newdam; // object takes 1/4 of damage - newdam = pctof(25, amt); + newdam = pctof(25, dam); limit(&newdam, 1, NA); takedamage(o, newdam, DT_COLD); } @@ -13948,12 +13941,16 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml extinguishlf(lf); } - } - - // update screen - drawstatus(); - updatestatus(); - return amt; + // low hitpoint warning for player + if (isplayer(lf) && (dam > 0)) { + int warnthresh; + warnthresh = (int)((float)0.25 * (float)lf->maxhp); + if ((lf->hp <= warnthresh) && (lf->hp > 0)) { + warn("*** LOW HITPOINT WARNING ***"); + more(); + } + } + } // end if !isdead } void losemp(lifeform_t *lf, int amt) { @@ -17444,7 +17441,6 @@ void startlfturn(lifeform_t *lf) { lifeform_t *l; int i; int willvanish = B_FALSE; - int donefeetwet = B_FALSE; flag_t *retflag[MAXCANDIDATES]; int nretflags; int movedlastturn = B_FALSE; @@ -17985,7 +17981,7 @@ void startlfturn(lifeform_t *lf) { if (skillcheck(lf, SC_SEARCH, diff, mod)) { char obname[BUFLEN]; // reveal it - real_getobname(o, obname, o->amt, B_FALSE, B_FALSE, B_FALSE, B_FALSE, B_TRUE); + getobnametruebase(o, obname, o->amt); msg("^wYou notice %s!",obname); interrupt(lf); killflag(f); @@ -18272,9 +18268,12 @@ void startlfturn(lifeform_t *lf) { // certain combinations might give announcements... switch (damtype) { case DT_WATER: - if ((bp == BP_FEET) && isplayer(lf) && hasbp(lf, bp) && !donefeetwet) { - msg("Your %s get wet.", getbodypartname(lf, bp)); - donefeetwet = B_TRUE; // don't keep repeating this + if ((bp == BP_FEET) && isplayer(lf) && hasbp(lf, bp)) { + char warntext[BUFLEN]; + sprintf(warntext,"Your %s get wet.", getbodypartname(lf, bp)); + // only announce this if you've had a turn + // without your feet wet. + real_warnabout(warntext, 2, B_FALSE); } break; default: @@ -19266,7 +19265,7 @@ int touch(lifeform_t *lf, object_t *o) { o->blessknown = B_TRUE; } // use real name here... - real_getobname(o, obname, o->amt, B_TRUE, B_FALSE, B_FALSE, B_TRUE, B_FALSE); + real_getobname(o, obname, o->amt, B_PREMODS, B_NOCONDITION, B_NOBLINDADJUST, B_BLESSINGS, B_NOSHOWALL); snprintf(buf, BUFLEN, "touching %s",obname); losehp(lf, 2, DT_HOLY, NULL, buf); // drop the object if we're holding it @@ -20619,6 +20618,9 @@ int wear(lifeform_t *lf, object_t *o) { case E_DOESNTFIT: if (isplayer(lf)) msg("The unnatural shape of your %s prevents this from fitting.", getbodypartname(lf, bp)); break; + case E_PALADIN: + if (isplayer(lf)) msg("Your vows prevent you from wearing non-blessed armour."); + break; case E_INJURED: if (isplayer(lf)) msg("Your injuries prevent you from wearing this."); break; @@ -20842,6 +20844,9 @@ int weild(lifeform_t *lf, object_t *o) { case E_IMPOSSIBLE: msg("You cannot weild weapons!"); break; + case E_PALADIN: + if (isplayer(lf)) msg("Your vows prevent you from weilding non-blessed weapons."); + break; case E_NOHANDS: msg("You do not have enough free hands to weild this weapon."); break; diff --git a/lf.h b/lf.h index d3405f6..08b6c6b 100644 --- a/lf.h +++ b/lf.h @@ -359,7 +359,8 @@ int loadfirearmfast(lifeform_t *lf, int onpurpose); void loseconcentration(lifeform_t *lf); void loseconsciousness(lifeform_t *lf, int howlong, lifeform_t *fromlf); int losehp(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *fromlf, char *damsrc); -int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *fromlf, char *damsrc, int reducedam, object_t *fromob, int retaliate, int *waskod); +int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *fromlf, char *damsrc, int reducedam, object_t *fromob, int retaliate, int *waskod, int doeffects); +void losehpeffects(lifeform_t *lf, int dam, enum DAMTYPE damtype, lifeform_t *fromlf, object_t *fromob, int retaliate, int ko, int *waskod, int prelowhp); void losemp(lifeform_t *lf, int amt); void makefriendly(lifeform_t *lf, int howlong); int makenauseated(lifeform_t *lf, int amt, int howlong); diff --git a/objects.c b/objects.c index 3020f57..ad0c238 100644 --- a/objects.c +++ b/objects.c @@ -2285,15 +2285,18 @@ void adjustdamob(object_t *o, int *dam, enum DAMTYPE damtype) { // adjust damage if (o->blessed == B_BLESSED) { // high chance of no hp loss - if (pctchance(90)) { + if (pctchance(80)) { lifeform_t *owner; owner = o->pile->owner; - if (owner && isplayer(owner)) { - // become known if owned by player + if (owner && (isplayer(owner) || cansee(player, owner))) { + // become known if seen by player if (!isblessknown(o)) { - char obname[BUFLEN]; + char obname[BUFLEN],lfname[BUFLEN]; + getlfname(owner, lfname); getobname(o, obname, o->amt); - msg("Your %s pulses with holy light as it is struck!",noprefix(obname)); + msg("%s%s %s pulses with holy light as it is struck!", + lfname, getpossessive(lfname), + noprefix(obname)); } o->blessknown = B_TRUE; } @@ -3036,7 +3039,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_TRUE, B_FALSE, B_TRUE, B_TRUE, B_FALSE); + real_getobname(o, obname, o->amt, B_PREMODS, B_NOCONDITION, B_BLINDADJUST, B_BLESSINGS, B_NOSHOWALL); strcpy(desc, ""); @@ -4803,18 +4806,22 @@ char *getshardobname(enum MATERIAL mid, char *buf) { char *getshopobname(object_t *o, char *buf, int count) { if (gettechlevel(o->type->id) > getskill(player, SK_TECHUSAGE)) { // unidentified tech - hide the name - return real_getobname(o, buf, o->amt, B_TRUE, B_TRUE, B_TRUE, B_TRUE, B_FALSE); + return getobname(o, buf, o->amt); } // anything else - show the real name - return real_getobname(o, buf, o->amt, B_TRUE, B_TRUE, B_TRUE, B_TRUE, B_TRUE); + return getobnametrue(o, buf, o->amt); } char *getobname(object_t *o, char *buf, int count) { - return real_getobname(o, buf, count, B_TRUE, B_TRUE, B_TRUE, B_TRUE, B_FALSE); + return real_getobname(o, buf, count, B_PREMODS, B_CONDITION, B_BLINDADJUST, B_BLESSINGS, B_NOSHOWALL); } char *getobnametrue(object_t *o, char *buf, int count) { - return real_getobname(o, buf, count, B_TRUE, B_TRUE, B_FALSE, B_TRUE, B_TRUE); + return real_getobname(o, buf, count, B_PREMODS, B_CONDITION, B_NOBLINDADJUST, B_BLESSINGS, 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); } // buf must already be allocated @@ -5732,6 +5739,7 @@ char *real_getrandomob(map_t *map, char *buf, int forcedepth, int forcehabitat, habitat_t *hab; char habname[BUFLEN]; int rrmoddir = -1; + int brandchance; skill_t *wantsk = NULL; if (!db) db = obdb; @@ -6069,19 +6077,21 @@ char *real_getrandomob(map_t *map, char *buf, int forcedepth, int forcehabitat, strcat(cursestr, "tainted "); } - // get random chance of having a brand (1% per depth)... + // get random chance of having a brand (1% per depth, plus object adjustments)... // if so... strcpy(brandname, ""); - if (rnd(1,100) <= depth) { + + sumflags(ot->flags, F_BRANDCHANCE, &brandchance, NULL, NULL); + brandchance += depth; + + if (pctchance(brandchance)) { brand_t *br; br = getrandombrandfor(ot); if (br) strcpy(brandname, br->suffix); } - snprintf(buf, BUFLEN, "%d %s%s%s", amt, cursestr, pluralname,brandname); - if (db || partdb) dblog("random ob for %s: %d x %s ('%s')", habname, amt, ot->name,pluralname); free(pluralname); return buf; @@ -8239,7 +8249,7 @@ void obdie(object_t *o) { if (!doobdieconvert(o, B_TRUE)) { char desc[BUFLEN]; - real_getobname(o, obname, o->amt, B_TRUE, B_FALSE, B_TRUE, B_TRUE, B_FALSE); + real_getobname(o, obname, o->amt, B_PREMODS, B_NOCONDITION, B_BLINDADJUST, B_BLESSINGS, B_NOSHOWALL); if (!hasflag(o->flags, F_NOOBDIETEXT)) { // announce the death strcpy(desc, ""); @@ -9067,7 +9077,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_FALSE, B_TRUE, B_FALSE, B_TRUE, B_FALSE); // don't adjust for blindness + real_getobname(o, obname, 1, B_NOPREMODS, B_CONDITION, B_NOBLINDADJUST, B_BLESSINGS, B_NOSHOWALL); msg("This is %s!",obname); } } @@ -10047,7 +10057,7 @@ void quaff(lifeform_t *lf, object_t *o) { drawmsg(); } } else if (!isknown(o)) { - real_getobname(o, obname, 1, B_FALSE, B_TRUE, B_FALSE, B_TRUE, B_FALSE); // don't adjust for blindness + real_getobname(o, obname, 1, B_NOPREMODS, B_CONDITION, B_NOBLINDADJUST, B_BLESSINGS, B_NOSHOWALL); // don't adjust for blindness if (isplayer(lf)) { // tell the player msg("This is %s!",obname); @@ -10690,7 +10700,7 @@ int readsomething(lifeform_t *lf, object_t *o) { makeknown(o->type->id); } o->blessknown = B_TRUE; - real_getobname(o, obname, 1, B_FALSE, B_TRUE, B_FALSE, B_TRUE, B_FALSE); // don't adjust for blindness + real_getobname(o, obname, 1, B_NOPREMODS, B_CONDITION, B_NOBLINDADJUST, B_BLESSINGS, B_NOSHOWALL); if (isplayer(lf)) { // tell the player msg("This is %s!",obname); @@ -10764,7 +10774,8 @@ int readsomething(lifeform_t *lf, object_t *o) { if (targob) { if (isplayer(lf)) { // this will be used by maketried() later - real_getobname(targob, triedonbuf, 1, B_FALSE, B_FALSE, B_TRUE, B_FALSE, B_FALSE); + real_getobname(targob, triedonbuf, 1, B_NOPREMODS, B_NOCONDITION, + B_BLINDADJUST, B_NOBLESSINGS, B_NOSHOWALL); } } else { noeffect = B_TRUE; @@ -11069,7 +11080,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_FALSE, B_TRUE, B_FALSE, B_TRUE, B_FALSE); // don't adjust for blindness + real_getobname(o, obname, 1, B_NOPREMODS, B_CONDITION, B_NOBLINDADJUST, B_BLESSINGS, B_NOSHOWALL); // tell the player msg("This is %s!",obname); more(); @@ -11818,8 +11829,8 @@ int real_takedamage(object_t *o, int howmuch, int damtype, int wantannounce) { } // now use the REAL name - real_getobname(o, obname, o->amt, B_TRUE, B_FALSE, B_FALSE, B_FALSE, B_TRUE); - losehp_real(owner, howmuch , damtype, NULL, obname, B_TRUE, o, B_FALSE, NULL); + real_getobname(o, obname, o->amt, B_PREMODS, B_NOCONDITION, B_NOBLINDADJUST, B_NOBLESSINGS, B_SHOWALL); + losehp_real(owner, howmuch , damtype, NULL, obname, B_DAMADJUST, o, B_NORETALIATE, NULL, B_DAMEFFECTS); if (isdead(owner)) { return howmuch; } @@ -11831,7 +11842,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_FALSE, B_FALSE, B_FALSE, B_FALSE, B_FALSE); + real_getobname(o, buf2, 1, B_NOPREMODS, B_NOCONDITION, B_NOBLINDADJUST, B_NOBLESSINGS, B_NOSHOWALL); snprintf(buf, BUFLEN, "a shattering %s", noprefix(buf2)); shatter(o, B_TRUE, buf, B_FALSE); return howmuch; @@ -11949,7 +11960,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_FALSE, B_FALSE, B_TRUE, B_FALSE, B_FALSE); + real_getobname(o, obname, o->amt, B_NOPREMODS, B_NOCONDITION, B_BLINDADJUST, B_NOBLESSINGS, B_NOSHOWALL); getobconditionname(o, predamname); hpflag = hasflag(o->flags, F_OBHP); if (hpflag) { @@ -12715,7 +12726,8 @@ int real_fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int sp if (thrower && (thrower->cell == srcloc)) { whogetsxp = thrower; } - losehp_real(target, dam, DT_PROJECTILE, whogetsxp, damstring, B_TRUE, o, B_TRUE, NULL); + losehp_real(target, dam, DT_PROJECTILE, whogetsxp, damstring, B_DAMADJUST, o, + B_RETALIATE, NULL, B_DAMEFFECTS); } if (reduceamt && (speed >= 3)) { diff --git a/objects.h b/objects.h index 1803537..7dc7acd 100644 --- a/objects.h +++ b/objects.h @@ -131,6 +131,7 @@ char *getobname(object_t *o, char *buf, int count); 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); float getobpileweight(obpile_t *op); char *getobconditionname(object_t *o, char *buf); diff --git a/shops.c b/shops.c index ceaa557..0ca9c81 100644 --- a/shops.c +++ b/shops.c @@ -29,6 +29,22 @@ extern prompt_t prompt; extern lifeform_t *player; extern WINDOW *mainwin; +// "buf" is the name of an object +// +// this function will adjust the object name to avoid objects which shouldn't appear in shops. +// returns TRUE if the name was modified. +int apply_shopob_restrictions(char *buf) { + if (strstr(buf, "gold coin")) { + strcpy(buf, "potion of water"); + return B_TRUE; + } + if (strstr(buf, "credit card")) { + strcpy(buf, "paper clip"); + return B_TRUE; + } + return B_FALSE; +} + // dir == 1 means "better skills increase the price" // dir == -1 means "better skills decrease the price" float applyshoppricemod(float origprice, lifeform_t *lf, object_t *shop, enum SHOPACTION action) { diff --git a/shops.h b/shops.h index ab629be..e4c00a3 100644 --- a/shops.h +++ b/shops.h @@ -1,5 +1,6 @@ #include "defs.h" +int apply_shopob_restrictions(char *buf); float applyshoppricemod(float origprice, lifeform_t *lf, object_t *shop, enum SHOPACTION action); int canafford(lifeform_t *lf, int amt); int getshopblessprice(object_t *o, object_t *shop); diff --git a/spell.c b/spell.c index 50787c6..61ec033 100644 --- a/spell.c +++ b/spell.c @@ -1483,7 +1483,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef // get helper ob helpob = getworkhelpob(user->pack, o->material->id); if (helpob) { - real_getobname(helpob, helpobname, helpob->amt, B_TRUE, B_FALSE, B_TRUE, B_TRUE, B_FALSE); + real_getobname(helpob, helpobname, helpob->amt, B_PREMODS, B_NOCONDITION, B_BLINDADJUST, B_BLESSINGS, B_NOSHOWALL); } else { strcpy(helpobname, ""); } @@ -1493,14 +1493,14 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef f->val[0] = f->val[1]; if (isplayer(user)) { char buf[BUFLEN],withbuf[BUFLEN]; - real_getobname(o, buf, o->amt, B_TRUE, B_FALSE, B_TRUE, B_TRUE, B_FALSE); + 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_TRUE, B_FALSE, B_TRUE, B_TRUE, B_FALSE); + 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, ""); @@ -7004,7 +7004,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ char extrabuf[BUFLEN]; identify(o); //getobname(o, buf, o->amt); - real_getobname(o, buf, o->amt, B_TRUE, B_TRUE, B_TRUE, B_TRUE, B_TRUE); + getobnametrue(o, buf, o->amt); getobextrainfo(o, extrabuf); if (strlen(extrabuf)) strcat(buf, extrabuf); @@ -8384,7 +8384,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ // on the ground? for (o = c->obpile->first ; o ; o = o->next) { char obname[BUFLEN]; - real_getobname(o, obname, o->amt, B_TRUE, B_TRUE, B_FALSE, B_FALSE, B_FALSE); + real_getobname(o, obname, o->amt, B_PREMODS, B_CONDITION, B_NOBLINDADJUST, + B_NOBLESSINGS, B_NOSHOWALL); if (strcasestr(obname, wantname)) { char ptext[BUFLEN]; char distbuf[BUFLEN],dirbuf[BUFLEN]; @@ -8398,7 +8399,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (c->lf) { for (o = c->lf->pack->first ; o ; o = o->next) { char obname[BUFLEN]; - real_getobname(o, obname, o->amt, B_TRUE, B_TRUE, B_FALSE, B_FALSE, B_FALSE); + real_getobname(o, obname, o->amt, B_PREMODS, B_CONDITION, + B_NOBLINDADJUST, B_NOBLESSINGS, B_NOSHOWALL); if (strcasestr(obname, wantname)) { char ptext[BUFLEN]; char distbuf[BUFLEN],dirbuf[BUFLEN];