B01004 No mimic corpse effect on pet (trunk only)

Make a mimic effect that lasts only as long as the
pet is still consuming the corpse.
This commit is contained in:
nethack.allison
2003-11-12 03:28:26 +00:00
parent bc06d02d24
commit 52490ee062
7 changed files with 111 additions and 5 deletions

View File

@@ -422,6 +422,7 @@ E int FDECL(dog_move, (struct monst *,int));
#ifdef USE_TRAMPOLI
E void FDECL(wantdoor, (int,int,genericptr_t));
#endif
E void FDECL(finish_meating,(struct monst *));
/* ### dokick.c ### */

View File

@@ -436,7 +436,7 @@ long nmv; /* number of moves */
if (mtmp->mstun && rn2(imv + 1) > 10/2) mtmp->mstun = 0;
/* might finish eating or be able to use special ability again */
if (imv > mtmp->meating) mtmp->meating = 0;
if (imv > mtmp->meating) finish_meating(mtmp);
else mtmp->meating -= imv;
if (imv > mtmp->mspec_used) mtmp->mspec_used = 0;
else mtmp->mspec_used -= imv;
@@ -837,7 +837,8 @@ boolean was_dead;
struct edog *edog;
boolean quietly = was_dead;
mtmp->meating = 0;
finish_meating(mtmp);
if (!mtmp->mtame) return;
edog = !mtmp->isminion ? EDOG(mtmp) : 0;

View File

@@ -17,6 +17,7 @@ STATIC_DCL struct obj *FDECL(DROPPABLES, (struct monst *));
STATIC_DCL boolean FDECL(can_reach_location,(struct monst *,XCHAR_P,XCHAR_P,
XCHAR_P,XCHAR_P));
STATIC_DCL boolean FDECL(could_reach_item,(struct monst *, XCHAR_P,XCHAR_P));
STATIC_DCL void FDECL(quickmimic, (struct monst *));
STATIC_OVL struct obj *
DROPPABLES(mon)
@@ -124,10 +125,17 @@ boolean devour;
register struct edog *edog = EDOG(mtmp);
boolean poly = FALSE, grow = FALSE, heal = FALSE;
int nutrit;
boolean deadmimic = FALSE;
if(edog->hungrytime < monstermoves)
edog->hungrytime = monstermoves;
nutrit = dog_nutrition(mtmp, obj);
deadmimic = (obj->otyp == CORPSE &&
(obj->corpsenm == PM_SMALL_MIMIC ||
obj->corpsenm == PM_LARGE_MIMIC ||
obj->corpsenm == PM_GIANT_MIMIC));
poly = polyfodder(obj);
grow = mlevelgain(obj);
heal = mhealup(obj);
@@ -192,11 +200,13 @@ boolean devour;
(void) newcham(mtmp, (struct permonst *)0, FALSE,
cansee(mtmp->mx, mtmp->my));
}
/* limit "instant" growth to prevent potential abuse */
if (grow && (int) mtmp->m_lev < (int)mtmp->data->mlevel + 15) {
if (!grow_up(mtmp, (struct monst *)0)) return 2;
}
if (heal) mtmp->mhp = mtmp->mhpmax;
if (deadmimic) quickmimic(mtmp);
return 1;
}
@@ -853,4 +863,79 @@ genericptr_t distance;
}
}
static struct qmchoices {
int mndx; /* type of pet, 0 means any */
char mlet; /* symbol of pet, 0 means any */
unsigned mappearance; /* mimic this */
uchar m_ap_type; /* what is the thing it is mimicing? */
} qm[] = {
/* Things that some pets might be thinking about at the time */
{PM_LITTLE_DOG, 0, PM_KITTEN, M_AP_MONSTER},
{PM_LARGE_DOG, 0, PM_LARGE_CAT, M_AP_MONSTER},
{PM_KITTEN, 0, PM_LITTLE_DOG, M_AP_MONSTER},
{PM_LARGE_CAT, 0, PM_LARGE_DOG, M_AP_MONSTER},
{PM_HOUSECAT, 0, PM_DOG, M_AP_MONSTER},
{PM_DOG, 0, PM_HOUSECAT, M_AP_MONSTER},
{PM_HOUSECAT, 0, PM_GIANT_RAT, M_AP_MONSTER},
#ifdef SINKS
{0, S_DOG, SINK, M_AP_FURNITURE}, /* sorry, no fire hydrants in NetHack */
#endif
{0, 0, TRIPE_RATION, M_AP_OBJECT}, /* leave this at end */
};
void
finish_meating(mtmp)
struct monst *mtmp;
{
mtmp->meating = 0;
if (mtmp->m_ap_type && mtmp->mappearance && !mtmp->cham) {
/* was eating a mimic and now appearance needs resetting */
mtmp->m_ap_type = 0;
mtmp->mappearance = 0;
newsym(mtmp->mx, mtmp->my);
}
}
STATIC_OVL void
quickmimic(mtmp)
struct monst *mtmp;
{
int idx = 0, trycnt = 5;
char buf[BUFSZ];
if (Protection_from_shape_changers || Blind || !mtmp->meating) return;
do {
idx = rn2(SIZE(qm));
if (qm[idx].mndx != 0 && monsndx(mtmp->data) == qm[idx].mndx)
break;
if (qm[idx].mlet != 0 && mtmp->data->mlet == qm[idx].mlet)
break;
if (qm[idx].mndx == 0 && qm[idx].mlet == 0)
break;
} while (--trycnt > 0);
if (trycnt == 0) idx = SIZE(qm)-1;
if (!idx) return; /* impossible */
Strcpy(buf, mon_nam(mtmp));
mtmp->m_ap_type = qm[idx].m_ap_type;
mtmp->mappearance = qm[idx].mappearance;
newsym(mtmp->mx,mtmp->my);
You("see %s appear where %s was!",
(mtmp->m_ap_type == M_AP_FURNITURE) ?
an(defsyms[mtmp->mappearance].explanation) :
(mtmp->m_ap_type == M_AP_OBJECT &&
OBJ_DESCR(objects[mtmp->mappearance])) ?
an(OBJ_DESCR(objects[mtmp->mappearance])) :
(mtmp->m_ap_type == M_AP_OBJECT &&
OBJ_NAME(objects[mtmp->mappearance])) ?
an(OBJ_NAME(objects[mtmp->mappearance])) :
(mtmp->m_ap_type == M_AP_MONSTER) ?
an(mons[mtmp->mappearance].mname) : something, buf);
display_nhwindow(WIN_MAP, TRUE);
}
/*dogmove.c*/

View File

@@ -250,7 +250,7 @@ register struct obj *gold;
long value = gold->quan * objects[gold->otyp].oc_cost;
#endif
mtmp->msleeping = 0;
mtmp->meating = 0;
finish_meating(mtmp);
if(!rn2(4)) setmangry(mtmp); /* not always pleasing */
/* greedy monsters catch gold */

View File

@@ -2098,7 +2098,7 @@ wakeup(mtmp)
register struct monst *mtmp;
{
mtmp->msleeping = 0;
mtmp->meating = 0; /* assume there's no salvagable food left */
finish_meating(mtmp);
setmangry(mtmp);
if(mtmp->m_ap_type) seemimic(mtmp);
else if (context.forcefight && !context.mon_moving && mtmp->mundetected) {

View File

@@ -141,7 +141,10 @@ boolean digest_meal;
(moves % 20 == 0 || regenerates(mon->data))) mon->mhp++;
if (mon->mspec_used) mon->mspec_used--;
if (digest_meal) {
if (mon->meating) mon->meating--;
if (mon->meating) {
mon->meating--;
if (mon->meating <= 0) finish_meating(mon);
}
}
}
@@ -603,6 +606,7 @@ register int after;
if (mtmp->meating) {
mtmp->meating--;
if (mtmp->meating <= 0) finish_meating(mtmp);
return 3; /* still eating */
}
if (hides_under(ptr) && OBJ_AT(mtmp->mx, mtmp->my) && rn2(10))

View File

@@ -305,6 +305,21 @@ register struct monst *mtmp;
}
else if (mtmp->mpeaceful) Strcat(info, ", peaceful");
if (mtmp->meating) Strcat(info, ", eating");
if (mtmp->meating && !mtmp->cham &&
mtmp->mappearance && mtmp->m_ap_type) {
Sprintf(eos(info), ", mimicing %s",
(mtmp->m_ap_type == M_AP_FURNITURE) ?
an(defsyms[mtmp->mappearance].explanation) :
(mtmp->m_ap_type == M_AP_OBJECT &&
OBJ_DESCR(objects[mtmp->mappearance])) ?
an(OBJ_DESCR(objects[mtmp->mappearance])) :
(mtmp->m_ap_type == M_AP_OBJECT &&
OBJ_NAME(objects[mtmp->mappearance])) ?
an(OBJ_NAME(objects[mtmp->mappearance])) :
(mtmp->m_ap_type == M_AP_MONSTER) ?
an(mons[mtmp->mappearance].mname) :
something);
}
if (mtmp->mcan) Strcat(info, ", cancelled");
if (mtmp->mconf) Strcat(info, ", confused");
if (mtmp->mblinded || !mtmp->mcansee)