From cad85663de24befd01b65ff5078f820db415c5d5 Mon Sep 17 00:00:00 2001 From: cohrs Date: Mon, 18 Feb 2002 23:36:46 +0000 Subject: [PATCH] purple worm digestion Generally modify the AD_DGST damage type so that: - players and pets get no AD_DGST nutrition from G_NOCORPSE monsters - undead no longer convey any nutrition, to either monsters or you-as-monster I decided on this based on the age typically assigned to undead corpses. - digestion conveys 50% or normal nutrition, and takes 25% the time to eat. - all AD_DGST attacks are now subject to gas spore explosions, including player --- doc/fixes34.0 | 1 + include/extern.h | 1 + src/mhitm.c | 26 ++++++++++++++++++++++++++ src/mon.c | 42 ++++++++++++++++++++++++++++++++---------- src/uhitm.c | 10 ++++++++-- 5 files changed, 68 insertions(+), 12 deletions(-) diff --git a/doc/fixes34.0 b/doc/fixes34.0 index 646e748c6..63bcaf3b2 100644 --- a/doc/fixes34.0 +++ b/doc/fixes34.0 @@ -433,6 +433,7 @@ if you float_down on a trap in which you're already trapped, don't retrap applying whip toward hidden mimic displays mimic name before "Wait!" message stealing a container didn't multiply cost of stolen contained objects by quan halve air elemental damage to compensate for side effect of speed system +pet purple worms get nutrition from engulfing attack Platform- and/or Interface-Specific Fixes diff --git a/include/extern.h b/include/extern.h index 4841e0527..7137a5ff8 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1079,6 +1079,7 @@ E void NDECL(mcalcdistress); E void FDECL(replmon, (struct monst *,struct monst *)); E void FDECL(relmon, (struct monst *)); E struct obj *FDECL(mlifesaver, (struct monst *)); +E boolean FDECL(corpse_chance,(struct monst *,struct monst *,BOOLEAN_P)); E void FDECL(mondead, (struct monst *)); E void FDECL(mondied, (struct monst *)); E void FDECL(mongone, (struct monst *)); diff --git a/src/mhitm.c b/src/mhitm.c index 0b36cead7..8b5209284 100644 --- a/src/mhitm.c +++ b/src/mhitm.c @@ -557,6 +557,7 @@ mdamagem(magr, mdef, mattk) int protector = mattk->aatyp == AT_TENT ? 0 : mattk->aatyp == AT_KICK ? W_ARMF : W_ARMG; + int num; if (touch_petrifies(pd) && !resists_ston(magr) && (mattk->aatyp != AT_WEAP || !otmp) && @@ -595,6 +596,31 @@ mdamagem(magr, mdef, mattk) tmp = mdef->mhp; /* Use up amulet of life saving */ if (!!(obj = mlifesaver(mdef))) m_useup(mdef, obj); + + /* Is a corpse for nutrition possible? It may kill magr */ + if (!corpse_chance(mdef, magr, TRUE) || magr->mhp < 1) + break; + + /* Pets get nutrition from swallowing monster whole. + * No nutrition from G_NOCORPSE monster, eg, undead. + * DGST monsters don't die from undead corpses + */ + num = monsndx(mdef->data); + if (magr->mtame && !magr->isminion && + !(mvitals[num].mvflags & G_NOCORPSE)) { + struct obj *virtualcorpse = mksobj(CORPSE, FALSE, FALSE); + int nutrit; + + virtualcorpse->corpsenm = num; + virtualcorpse->owt = weight(virtualcorpse); + nutrit = dog_nutrition(magr, virtualcorpse); + dealloc_obj(virtualcorpse); + + /* only 50% nutrition, 25% of normal eating time */ + if (magr->meating > 1) magr->meating = (magr->meating+3)/4; + if (nutrit > 1) nutrit /= 2; + EDOG(magr)->hungrytime += nutrit; + } break; case AD_STUN: if (magr->mcan) break; diff --git a/src/mon.c b/src/mon.c index 721828e16..92163cda0 100644 --- a/src/mon.c +++ b/src/mon.c @@ -12,7 +12,6 @@ #include "edog.h" #include -STATIC_DCL boolean FDECL(corpse_chance,(struct monst *)); STATIC_DCL boolean FDECL(restrap,(struct monst *)); STATIC_DCL long FDECL(mm_aggression, (struct monst *,struct monst *)); #ifdef OVL2 @@ -1381,19 +1380,20 @@ register struct monst *mtmp; m_detach(mtmp, mptr); } -STATIC_OVL boolean -corpse_chance(mon) +/* TRUE if corpse might be dropped, magr may die if mon was swallowed */ +boolean +corpse_chance(mon, magr, swallowed) struct monst *mon; +struct monst *magr; /* killer, if swallowed */ +boolean swallowed; /* digestion */ { struct permonst *mdat = mon->data; int i, tmp; - if (mdat == &mons[PM_VLAD_THE_IMPALER] || mdat->mlet == S_LICH) { - if (cansee(mon->mx, mon->my)) - pline("%s body crumbles into dust.", - s_suffix(Monnam(mon))); - return FALSE; + if (cansee(mon->mx, mon->my) && !swallowed) + pline("%s body crumbles into dust.", s_suffix(Monnam(mon))); + return FALSE; } /* Gas spores always explode upon death */ @@ -1405,6 +1405,28 @@ struct monst *mon; else if(mdat->mattk[i].damd) tmp = d((int)mdat->mlevel+1, (int)mdat->mattk[i].damd); else tmp = 0; + if (swallowed && magr) { + if (magr == &youmonst) { + There("is an explosion in your %s!", + body_part(STOMACH)); + Sprintf(killer_buf, "%s explosion", + s_suffix(mdat->mname)); + losehp(tmp, killer_buf, KILLED_BY_AN); + } else { + if (flags.soundok) You_hear("an explosion."); + magr->mhp -= tmp; + if (magr->mhp < 1) mondied(magr); + if (magr->mhp < 1) { /* maybe lifesaved */ + if (canspotmon(magr)) + pline("%s rips open!", Monnam(magr)); + } else if (canseemon(magr)) + pline("%s seems to have indigestion.", + Monnam(magr)); + } + + return FALSE; + } + Sprintf(killer_buf, "%s explosion", s_suffix(mdat->mname)); killer = killer_buf; killer_format = KILLED_BY_AN; @@ -1440,7 +1462,7 @@ register struct monst *mdef; mondead(mdef); if (mdef->mhp > 0) return; /* lifesaved */ - if (corpse_chance(mdef)) + if (corpse_chance(mdef, (struct monst *)0, FALSE)) (void) make_corpse(mdef); } @@ -1708,7 +1730,7 @@ xkilled(mtmp, dest) * different from whether or not the corpse is "special"; * if we want both, we have to specify it explicitly. */ - if (corpse_chance(mtmp)) + if (corpse_chance(mtmp, (struct monst *)0, FALSE)) (void) make_corpse(mtmp); } if(redisp) newsym(x,y); diff --git a/src/uhitm.c b/src/uhitm.c index 3c3c18323..7e238f751 100644 --- a/src/uhitm.c +++ b/src/uhitm.c @@ -1616,10 +1616,16 @@ register struct attack *mattk; You("hurriedly regurgitate the sizzling in your %s.", body_part(STOMACH)); } else { - u.uhunger += mdef->data->cnutrit; + tmp = 1 + (mdef->data->cwt >> 8); + if (corpse_chance(mdef, &youmonst, TRUE) && + !(mvitals[monsndx(mdef->data)].mvflags & + G_NOCORPSE)) { + /* nutrition only if there can be a corpse */ + u.uhunger += (mdef->data->cnutrit+1) / 2; + } else tmp = 0; Sprintf(msgbuf, "You totally digest %s.", mon_nam(mdef)); - if ((tmp = 3 + (mdef->data->cwt >> 6)) != 0) { + if (tmp != 0) { /* setting afternmv = end_engulf is tempting, * but will cause problems if the player is * attacked (which uses his real location) or