mirror of
https://codeberg.org/noisytoot/notnotdnethack.git
synced 2025-07-28 16:32:27 +01:00
Delusions Madness rework, part 1
Laying out the ground for changing the madness -- monsters mimicking monsters needed more thorough handling. Now fools: monster naming functions, probing, farlook, scent/other detection Not found out by most methods. Found out by: being attacked, searching. Many of these functionalities make more sense for the madness than for a mimic that is capable of mimicking a creature.
This commit is contained in:
parent
4abfa5dfe0
commit
a33e39acaa
13 changed files with 75 additions and 42 deletions
|
@ -1568,6 +1568,7 @@ E void FDECL(wake_nearto, (int,int,int));
|
|||
E void FDECL(wake_nearto_noisy, (int,int,int));
|
||||
E void FDECL(seemimic_ambush, (struct monst *));
|
||||
E void FDECL(seemimic, (struct monst *));
|
||||
E void FDECL(see_passive_mimic, (struct monst *));
|
||||
E void NDECL(rescham);
|
||||
E void NDECL(restartcham);
|
||||
E void FDECL(restore_cham, (struct monst *));
|
||||
|
|
|
@ -3797,7 +3797,7 @@ struct obj *obj;
|
|||
}
|
||||
wakeup(mtmp, TRUE);
|
||||
} else {
|
||||
if (mtmp->m_ap_type &&
|
||||
if ((mtmp->m_ap_type && mtmp->m_ap_type != M_AP_MONSTER) &&
|
||||
!Protection_from_shape_changers && !sensemon(mtmp))
|
||||
stumble_onto_mimic(mtmp);
|
||||
else You("flick your whip towards %s.", mon_nam(mtmp));
|
||||
|
|
|
@ -416,9 +416,10 @@ display_monster(x, y, mon, sightflags, worm_tail)
|
|||
/* 2 if detected using Detect_monsters */
|
||||
register xchar worm_tail; /* mon is actually a worm tail */
|
||||
{
|
||||
/* we want M_AP_MONSTER to not be revealed by monster dectection */
|
||||
register boolean mon_mimic = (mon->m_ap_type != M_AP_NOTHING);
|
||||
register int sensed = mon_mimic &&
|
||||
(Protection_from_shape_changers || sensemon(mon));
|
||||
register int sensed = mon_mimic && (Protection_from_shape_changers || sensemon(mon));
|
||||
register int appear = mon->mtyp;
|
||||
/*
|
||||
* We must do the mimic check first. If the mimic is mimicing something,
|
||||
* and the location is in sight, we have to change the hero's memory
|
||||
|
@ -464,14 +465,15 @@ display_monster(x, y, mon, sightflags, worm_tail)
|
|||
}
|
||||
|
||||
case M_AP_MONSTER:
|
||||
show_glyph(x,y, monnum_to_glyph(what_mon((int)mon->mappearance, mon)));
|
||||
appear = mon->mappearance;
|
||||
//show_glyph(x,y, monnum_to_glyph(what_mon((int)mon->mappearance, mon)));
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* If the mimic is unsucessfully mimicing something, display the monster */
|
||||
if (!mon_mimic || sensed) {
|
||||
if (!mon_mimic || sensed || mon->m_ap_type == M_AP_MONSTER) {
|
||||
int num;
|
||||
|
||||
if (mon->mtame && !Hallucination) {
|
||||
|
@ -479,13 +481,13 @@ display_monster(x, y, mon, sightflags, worm_tail)
|
|||
petnum_to_glyph(PM_HUNTING_HORROR_TAIL):
|
||||
petnum_to_glyph(PM_LONG_WORM_TAIL);
|
||||
else
|
||||
num = pet_to_glyph(mon);
|
||||
num = petnum_to_glyph(appear);
|
||||
} else if (mon->mpeaceful && !Hallucination) {
|
||||
if (worm_tail) num = mon->mtyp == PM_HUNTING_HORROR ?
|
||||
peacenum_to_glyph(PM_HUNTING_HORROR_TAIL):
|
||||
peacenum_to_glyph(PM_LONG_WORM_TAIL);
|
||||
else
|
||||
num = peace_to_glyph(mon);
|
||||
num = peacenum_to_glyph(appear);
|
||||
}
|
||||
else if (!Hallucination && (
|
||||
has_template(mon, VAMPIRIC) ||
|
||||
|
@ -499,7 +501,7 @@ display_monster(x, y, mon, sightflags, worm_tail)
|
|||
zombienum_to_glyph(PM_HUNTING_HORROR_TAIL):
|
||||
zombienum_to_glyph(PM_LONG_WORM_TAIL);
|
||||
else
|
||||
num = zombie_to_glyph(mon);
|
||||
num = zombienum_to_glyph(appear);
|
||||
/* [ALI] Only use detected glyphs when monster wouldn't be
|
||||
* visible by any other means.
|
||||
*/
|
||||
|
@ -508,13 +510,13 @@ display_monster(x, y, mon, sightflags, worm_tail)
|
|||
detected_monnum_to_glyph(what_mon(PM_HUNTING_HORROR_TAIL, mon)):
|
||||
detected_monnum_to_glyph(what_mon(PM_LONG_WORM_TAIL, mon));
|
||||
else
|
||||
num = detected_mon_to_glyph(mon);
|
||||
num = detected_monnum_to_glyph(appear);
|
||||
} else {
|
||||
if (worm_tail) num = mon->mtyp == PM_HUNTING_HORROR ?
|
||||
monnum_to_glyph(what_mon(PM_HUNTING_HORROR_TAIL, mon)):
|
||||
monnum_to_glyph(what_mon(PM_LONG_WORM_TAIL, mon));
|
||||
else
|
||||
num = mon_to_glyph(mon);
|
||||
num = monnum_to_glyph(appear);
|
||||
}
|
||||
show_glyph(x,y,num);
|
||||
}
|
||||
|
|
|
@ -918,6 +918,8 @@ boolean called;
|
|||
static char buffers[XMONNAM_BUFFERS][BUFSZ];
|
||||
#endif
|
||||
struct permonst *mdat = mtmp->data;
|
||||
const char * appearname = mdat->mname;
|
||||
int appeartype = mdat->mtyp;
|
||||
boolean do_hallu, do_invis, do_it, do_saddle;
|
||||
boolean name_at_start, has_adjectives;
|
||||
char *bp;
|
||||
|
@ -971,6 +973,12 @@ boolean called;
|
|||
return strcpy(buf, name);
|
||||
}
|
||||
|
||||
/* monsters appearing as other monsters */
|
||||
if ((mtmp->m_ap_type == M_AP_MONSTER) && !(suppress & SUPPRESS_HALLUCINATION)) {
|
||||
appeartype = mtmp->mappearance;
|
||||
appearname = mons[appeartype].mname;
|
||||
}
|
||||
|
||||
/* Shopkeepers: use shopkeeper name. For normal shopkeepers, just
|
||||
* "Asidonhopo"; for unusual ones, "Asidonhopo the invisible
|
||||
* shopkeeper" or "Asidonhopo the blue dragon". If hallucinating,
|
||||
|
@ -986,11 +994,11 @@ boolean called;
|
|||
return buf;
|
||||
}
|
||||
Strcat(buf, shkname(mtmp));
|
||||
if (mdat->mtyp == PM_SHOPKEEPER && !do_invis)
|
||||
if (appeartype == PM_SHOPKEEPER && !do_invis)
|
||||
return buf;
|
||||
Strcat(buf, " the ");
|
||||
if (do_invis) Strcat(buf, "invisible ");
|
||||
if (mtmp->mflee && mtmp->mtyp == PM_BANDERSNATCH){
|
||||
if (mtmp->mflee && appeartype == PM_BANDERSNATCH){
|
||||
Strcat(buf, "frumious ");
|
||||
name_at_start = FALSE;
|
||||
}
|
||||
|
@ -1014,7 +1022,7 @@ boolean called;
|
|||
Sprintf(eos(buf), "%sed ", OBJ_DESCR(objects[mtmp->mvar_syllable]));
|
||||
name_at_start = FALSE;
|
||||
}
|
||||
Strcat(buf, mdat->mname);
|
||||
Strcat(buf, appearname);
|
||||
append_template_desc(mtmp, buf, TRUE);
|
||||
return buf;
|
||||
}
|
||||
|
@ -1044,17 +1052,17 @@ boolean called;
|
|||
} else if (M_HAS_NAME(mtmp)) {
|
||||
char *name = MNAME(mtmp);
|
||||
|
||||
if (mdat->mtyp == PM_GHOST) {
|
||||
if (appeartype == PM_GHOST) {
|
||||
Sprintf(eos(buf), "%s ghost", s_suffix(name));
|
||||
name_at_start = TRUE;
|
||||
} else if (mdat->mtyp == PM_SHADE) {
|
||||
} else if (appeartype == PM_SHADE) {
|
||||
Sprintf(eos(buf), "%s shade", s_suffix(name));
|
||||
name_at_start = TRUE;
|
||||
} else if (mdat->mtyp == PM_BROKEN_SHADOW) {
|
||||
} else if (appeartype == PM_BROKEN_SHADOW) {
|
||||
Sprintf(eos(buf), "%s broken shadow", s_suffix(name));
|
||||
name_at_start = TRUE;
|
||||
} else if (called) {
|
||||
if (mtmp->mflee && mtmp->mtyp == PM_BANDERSNATCH){
|
||||
if (mtmp->mflee && appeartype == PM_BANDERSNATCH){
|
||||
Sprintf(eos(buf), "frumious ");
|
||||
name_at_start = FALSE;
|
||||
}
|
||||
|
@ -1078,7 +1086,7 @@ boolean called;
|
|||
name_at_start = FALSE;
|
||||
}
|
||||
|
||||
Sprintf(eos(buf), "%s", mdat->mname);
|
||||
Sprintf(eos(buf), "%s", appearname);
|
||||
append_template_desc(mtmp, buf, type_is_pname(mdat));
|
||||
Sprintf(eos(buf), " called %s", name);
|
||||
|
||||
|
@ -1109,7 +1117,7 @@ boolean called;
|
|||
name_at_start = FALSE;
|
||||
} else {
|
||||
name_at_start = (boolean)type_is_pname(mdat);
|
||||
if (mtmp->mflee && mtmp->mtyp == PM_BANDERSNATCH){
|
||||
if (mtmp->mflee && appeartype == PM_BANDERSNATCH){
|
||||
Strcat(buf, "frumious ");
|
||||
name_at_start = FALSE;
|
||||
}
|
||||
|
@ -1133,16 +1141,16 @@ boolean called;
|
|||
Sprintf(eos(buf), "%sed ", OBJ_DESCR(objects[mtmp->mvar_syllable]));
|
||||
name_at_start = FALSE;
|
||||
}
|
||||
Strcat(buf, mdat->mname);
|
||||
Strcat(buf, appearname);
|
||||
append_template_desc(mtmp, buf, type_is_pname(mdat));
|
||||
}
|
||||
|
||||
if (name_at_start && (article == ARTICLE_YOUR || !has_adjectives)) {
|
||||
if (mdat->mtyp == PM_WIZARD_OF_YENDOR)
|
||||
if (appeartype == PM_WIZARD_OF_YENDOR)
|
||||
article = ARTICLE_THE;
|
||||
else
|
||||
article = ARTICLE_NONE;
|
||||
} else if ((mdat->geno & G_UNIQ) && article == ARTICLE_A && mdat->mtyp != PM_GOD) {
|
||||
} else if ((mdat->geno & G_UNIQ) && article == ARTICLE_A && appeartype != PM_GOD) {
|
||||
article = ARTICLE_THE;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,7 +39,9 @@ register boolean clumsy;
|
|||
boolean trapkilled = FALSE;
|
||||
int result;
|
||||
|
||||
if(mon->m_ap_type) seemimic(mon);
|
||||
if(mon->m_ap_type) {
|
||||
if(mon->m_ap_type == M_AP_MONSTER) seemimic_ambush(mon); else seemimic(mon);
|
||||
}
|
||||
check_caitiff(mon);
|
||||
|
||||
result = xmeleehity(&youmonst, mon, &basickick, (struct obj **)0, -1, 1000, FALSE);
|
||||
|
|
|
@ -545,7 +545,7 @@ boolean yours; /* is it your fault (for killing monsters) */
|
|||
"fried");
|
||||
}
|
||||
} else if (!silent && cansee(xi, yi)) {
|
||||
if(mtmp->m_ap_type) seemimic(mtmp);
|
||||
if(mtmp->m_ap_type) see_passive_mimic(mtmp);
|
||||
pline("%s is caught in the %s!", Monnam(mtmp), str);
|
||||
}
|
||||
|
||||
|
|
|
@ -1205,7 +1205,7 @@ domove()
|
|||
* different message and makes the player remember the monster. */
|
||||
if(flags.nopick &&
|
||||
(canspotmon(mtmp) || glyph_is_invisible(levl[x][y].glyph))){
|
||||
if(mtmp->m_ap_type && !Protection_from_shape_changers
|
||||
if((mtmp->m_ap_type && mtmp->m_ap_type != M_AP_MONSTER) && !Protection_from_shape_changers
|
||||
&& !sensemon(mtmp))
|
||||
stumble_onto_mimic(mtmp);
|
||||
else if (mtmp->mpeaceful && !Hallucination)
|
||||
|
|
17
src/mon.c
17
src/mon.c
|
@ -5787,7 +5787,7 @@ int anger;
|
|||
mtmp->meating = 0; /* assume there's no salvagable food left */
|
||||
mtmp->mstrategy &= ~(STRAT_WAITMASK);
|
||||
if(anger) setmangry(mtmp);
|
||||
if(mtmp->m_ap_type) seemimic(mtmp);
|
||||
if(mtmp->m_ap_type) see_passive_mimic(mtmp);
|
||||
else if (flags.forcefight && !flags.mon_moving && mtmp->mundetected) {
|
||||
mtmp->mundetected = 0;
|
||||
newsym(mtmp->mx, mtmp->my);
|
||||
|
@ -5932,6 +5932,7 @@ register int x, y, distance;
|
|||
}
|
||||
}
|
||||
|
||||
/* reveals monster-mimickers as well as passive-mimickers with a surprised message */
|
||||
void
|
||||
seemimic_ambush(mtmp)
|
||||
struct monst *mtmp;
|
||||
|
@ -5941,7 +5942,7 @@ struct monst *mtmp;
|
|||
|
||||
seemimic(mtmp);
|
||||
|
||||
if (canseemon(mtmp) && !sensemon(mtmp)) {
|
||||
if (canseemon(mtmp) && !(sensemon(mtmp) && old_ap_type != M_AP_MONSTER)) {
|
||||
const char * app;
|
||||
switch (old_ap_type)
|
||||
{
|
||||
|
@ -5971,6 +5972,7 @@ struct monst *mtmp;
|
|||
|
||||
|
||||
/* NOTE: we must check for mimicry before calling this routine */
|
||||
/* reveals monster-mimickers as well as passive-mimickers, with no message */
|
||||
void
|
||||
seemimic(mtmp)
|
||||
register struct monst *mtmp;
|
||||
|
@ -5993,6 +5995,15 @@ register struct monst *mtmp;
|
|||
newsym(mtmp->mx,mtmp->my);
|
||||
}
|
||||
|
||||
/* seemimic() for furniture and objects only */
|
||||
void
|
||||
see_passive_mimic(mtmp)
|
||||
register struct monst * mtmp;
|
||||
{
|
||||
if (mtmp->m_ap_type == M_AP_FURNITURE || mtmp->m_ap_type == M_AP_OBJECT)
|
||||
seemimic(mtmp);
|
||||
}
|
||||
|
||||
/* force all chameleons to become normal */
|
||||
void
|
||||
rescham()
|
||||
|
@ -6010,7 +6021,7 @@ rescham()
|
|||
}
|
||||
if(is_were(mtmp->data) && mtmp->data->mlet != S_HUMAN)
|
||||
new_were(mtmp);
|
||||
if(mtmp->m_ap_type && cansee(mtmp->mx, mtmp->my)) {
|
||||
if(mtmp->m_ap_type && cansee(mtmp->mx, mtmp->my) && mtmp->m_ap_type != M_AP_MONSTER) {
|
||||
seemimic(mtmp);
|
||||
/* we pretend that the mimic doesn't */
|
||||
/* know that it has been unmasked. */
|
||||
|
|
|
@ -1210,7 +1210,7 @@ register struct obj *otmp;
|
|||
boolean reveal_invis = FALSE;
|
||||
if (mtmp != &youmonst) {
|
||||
mtmp->msleeping = 0;
|
||||
if (mtmp->m_ap_type) seemimic(mtmp);
|
||||
if (mtmp->m_ap_type) see_passive_mimic(mtmp);
|
||||
}
|
||||
switch(otmp->otyp) {
|
||||
case WAN_STRIKING:
|
||||
|
@ -1251,7 +1251,7 @@ register struct obj *otmp;
|
|||
if (cansee(mtmp->mx, mtmp->my))
|
||||
pline("%s resists the magic!", Monnam(mtmp));
|
||||
mtmp->msleeping = 0;
|
||||
if(mtmp->m_ap_type) seemimic(mtmp);
|
||||
if(mtmp->m_ap_type) see_passive_mimic(mtmp);
|
||||
} else if (!tele_restrict(mtmp))
|
||||
(void) rloc(mtmp, FALSE);
|
||||
}
|
||||
|
|
11
src/pager.c
11
src/pager.c
|
@ -2117,9 +2117,18 @@ get_description_of_monster_type(struct monst * mtmp, char * description)
|
|||
struct permonst * ptr = mtmp->data;
|
||||
int monsternumber = monsndx(ptr);
|
||||
|
||||
/* monsters pretending to be other monsters won't be given away by the pokedex */
|
||||
struct monst fakemon;
|
||||
if (mtmp->m_ap_type == M_AP_MONSTER) {
|
||||
fakemon = *mtmp;
|
||||
monsternumber = fakemon.mtyp = mtmp->mappearance;
|
||||
ptr = fakemon.data = &mons[monsternumber];
|
||||
mtmp = &fakemon;
|
||||
}
|
||||
|
||||
char name[BUFSZ] = "";
|
||||
Strcat(name, ptr->mname);
|
||||
if (type_is_pname(mtmp->data)){
|
||||
if (type_is_pname(ptr)){
|
||||
if (has_template(mtmp, MISTWEAVER)){
|
||||
if (mtmp->female) Strcat(name, ", Daughter of the Black Goat");
|
||||
else Strcat(name, ", Child of the Black Goat");
|
||||
|
|
13
src/xhity.c
13
src/xhity.c
|
@ -995,6 +995,7 @@ int tary;
|
|||
continue;
|
||||
}
|
||||
/* make the attack */
|
||||
if ((vis&VIS_MAGR) && magr->mappearance) seemimic_ambush(magr); // its true form must be revealed
|
||||
result = xengulfhity(magr, mdef, attk, vis);
|
||||
/* increment number of attacks made */
|
||||
attacksmade++;
|
||||
|
@ -2279,9 +2280,6 @@ boolean nearmiss;
|
|||
if (!(vis&VIS_MDEF))
|
||||
map_invisible(x(mdef), y(mdef));
|
||||
|
||||
if (mdef->m_ap_type) seemimic(mdef);
|
||||
if (magr->m_ap_type) seemimic(magr);
|
||||
|
||||
pline("%s %s %s.",
|
||||
Monnam(magr),
|
||||
(compat ? "pretends to be friendly to" : "misses"),
|
||||
|
@ -3679,11 +3677,10 @@ boolean ranged;
|
|||
wake_nearto(x(mdef), y(mdef), /* call function to wake nearby monsters */
|
||||
combatNoise(pa) / (((youagr || youdef) && Stealth) ? 2 : 1)); /* range is reduced if the player is involved and stealthy */
|
||||
|
||||
/* show mimics */
|
||||
if (magr->mappearance)
|
||||
seemimic_ambush(magr);
|
||||
if (mdef->mappearance)
|
||||
seemimic(mdef);
|
||||
/* show mimics on successful attack */
|
||||
if (mdef->mappearance && hit) {
|
||||
if (youagr) seemimic_ambush(mdef); else seemimic(mdef);
|
||||
}
|
||||
/* If the monster is undetected and hits you, you should know where the attack came from. */
|
||||
if (youdef && magr->mundetected && hit && (hides_under(pa) || is_underswimmer(pa))) {
|
||||
magr->mundetected = 0;
|
||||
|
|
|
@ -199,7 +199,7 @@ struct obj * wep; /* uwep for attack(), null for kick_monster() */
|
|||
return ATTACKCHECK_NONE;
|
||||
}
|
||||
|
||||
if (mdef->m_ap_type && !Protection_from_shape_changers &&
|
||||
if ((mdef->m_ap_type && mdef->m_ap_type != M_AP_MONSTER) && !Protection_from_shape_changers &&
|
||||
!sensemon(mdef) &&
|
||||
!glyph_is_warning(glyph_at(u.ux + u.dx, u.uy + u.dy))) {
|
||||
/* If a hidden mimic was in a square where a player remembers
|
||||
|
@ -398,6 +398,9 @@ struct monst *mtmp;
|
|||
if(!u.ustuck && !mtmp->mflee && dmgtype(mtmp->data,AD_STCK))
|
||||
u.ustuck = mtmp;
|
||||
|
||||
/* clear mimicking before generating message to get an accurate a_monnam() */
|
||||
seemimic(mtmp);
|
||||
|
||||
if (Blind) {
|
||||
if (!Blind_telepat)
|
||||
what = generic; /* with default fmt */
|
||||
|
@ -423,7 +426,7 @@ struct monst *mtmp;
|
|||
}
|
||||
if (what) pline(fmt, what);
|
||||
|
||||
wakeup(mtmp, TRUE); /* clears mimicking */
|
||||
wakeup(mtmp, TRUE);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -4468,7 +4468,7 @@ struct obj *otmp; /* source of flash */
|
|||
/* at this point, reveal them */
|
||||
mtmp->mundetected = 0;
|
||||
if (mtmp->m_ap_type)
|
||||
seemimic(mtmp);
|
||||
see_passive_mimic(mtmp);
|
||||
newsym(mtmp->mx, mtmp->my);
|
||||
if (mtmp->mtyp == PM_GREMLIN) {
|
||||
/* Rule #1: Keep them out of the light. */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue