218 lines
5.8 KiB
C
218 lines
5.8 KiB
C
/* NetHack 3.7 were.c $NHDT-Date: 1596498227 2020/08/03 23:43:47 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.25 $ */
|
|
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
|
/*-Copyright (c) Robert Patrick Rankin, 2011. */
|
|
/* NetHack may be freely redistributed. See license for details. */
|
|
|
|
#include "hack.h"
|
|
|
|
void
|
|
were_change(struct monst *mon)
|
|
{
|
|
if (!is_were(mon->data))
|
|
return;
|
|
|
|
if (is_human(mon->data)) {
|
|
if (!Protection_from_shape_changers
|
|
&& !rn2(night() ? (flags.moonphase == FULL_MOON ? 3 : 30)
|
|
: (flags.moonphase == FULL_MOON ? 10 : 50))) {
|
|
new_were(mon); /* change into animal form */
|
|
if (!Deaf && !canseemon(mon)) {
|
|
const char *howler;
|
|
|
|
switch (monsndx(mon->data)) {
|
|
case PM_WEREWOLF:
|
|
howler = "wolf";
|
|
break;
|
|
case PM_WEREJACKAL:
|
|
howler = "jackal";
|
|
break;
|
|
default:
|
|
howler = (char *) 0;
|
|
break;
|
|
}
|
|
if (howler)
|
|
You_hear("a %s howling at the moon.", howler);
|
|
}
|
|
}
|
|
} else if (!rn2(30) || Protection_from_shape_changers) {
|
|
new_were(mon); /* change back into human form */
|
|
}
|
|
/* update innate intrinsics (mainly Drain_resistance) */
|
|
set_uasmon(); /* new_were() doesn't do this */
|
|
}
|
|
|
|
int
|
|
counter_were(int pm)
|
|
{
|
|
switch (pm) {
|
|
case PM_WEREWOLF:
|
|
return PM_HUMAN_WEREWOLF;
|
|
case PM_HUMAN_WEREWOLF:
|
|
return PM_WEREWOLF;
|
|
case PM_WEREJACKAL:
|
|
return PM_HUMAN_WEREJACKAL;
|
|
case PM_HUMAN_WEREJACKAL:
|
|
return PM_WEREJACKAL;
|
|
case PM_WERERAT:
|
|
return PM_HUMAN_WERERAT;
|
|
case PM_HUMAN_WERERAT:
|
|
return PM_WERERAT;
|
|
default:
|
|
return NON_PM;
|
|
}
|
|
}
|
|
|
|
/* convert monsters similar to werecritters into appropriate werebeast */
|
|
int
|
|
were_beastie(int pm)
|
|
{
|
|
switch (pm) {
|
|
case PM_WERERAT:
|
|
case PM_SEWER_RAT:
|
|
case PM_GIANT_RAT:
|
|
case PM_RABID_RAT:
|
|
return PM_WERERAT;
|
|
case PM_WEREJACKAL:
|
|
case PM_JACKAL:
|
|
case PM_FOX:
|
|
case PM_COYOTE:
|
|
return PM_WEREJACKAL;
|
|
case PM_WEREWOLF:
|
|
case PM_WOLF:
|
|
case PM_WARG:
|
|
case PM_WINTER_WOLF:
|
|
return PM_WEREWOLF;
|
|
default:
|
|
break;
|
|
}
|
|
return NON_PM;
|
|
}
|
|
|
|
void
|
|
new_were(struct monst *mon)
|
|
{
|
|
int pm;
|
|
|
|
pm = counter_were(monsndx(mon->data));
|
|
if (pm < LOW_PM) {
|
|
impossible("unknown lycanthrope %s.",
|
|
mon->data->pmnames[NEUTRAL]);
|
|
return;
|
|
}
|
|
|
|
if (canseemon(mon) && !Hallucination)
|
|
pline("%s changes into a %s.", Monnam(mon),
|
|
is_human(&mons[pm]) ? "human"
|
|
: pmname(&mons[pm], Mgender(mon)) + 4);
|
|
|
|
set_mon_data(mon, &mons[pm]);
|
|
if (helpless(mon)) {
|
|
/* transformation wakens and/or revitalizes */
|
|
mon->msleeping = 0;
|
|
mon->mfrozen = 0; /* not asleep or paralyzed */
|
|
mon->mcanmove = 1;
|
|
}
|
|
/* regenerate by 1/4 of the lost hit points */
|
|
mon->mhp += (mon->mhpmax - mon->mhp) / 4;
|
|
newsym(mon->mx, mon->my);
|
|
mon_break_armor(mon, FALSE);
|
|
possibly_unwield(mon, FALSE);
|
|
}
|
|
|
|
/* were-creature (even you) summons a horde */
|
|
int
|
|
were_summon(
|
|
struct permonst *ptr,
|
|
boolean yours,
|
|
int *visible, /* number of visible helpers created */
|
|
char *genbuf)
|
|
{
|
|
int i, typ, pm = monsndx(ptr);
|
|
struct monst *mtmp;
|
|
int total = 0;
|
|
|
|
*visible = 0;
|
|
if (Protection_from_shape_changers && !yours)
|
|
return 0;
|
|
for (i = rnd(5); i > 0; i--) {
|
|
switch (pm) {
|
|
case PM_WERERAT:
|
|
case PM_HUMAN_WERERAT:
|
|
typ = rn2(3) ? PM_SEWER_RAT
|
|
: rn2(3) ? PM_GIANT_RAT : PM_RABID_RAT;
|
|
if (genbuf)
|
|
Strcpy(genbuf, "rat");
|
|
break;
|
|
case PM_WEREJACKAL:
|
|
case PM_HUMAN_WEREJACKAL:
|
|
typ = rn2(7) ? PM_JACKAL : rn2(3) ? PM_COYOTE : PM_FOX;
|
|
if (genbuf)
|
|
Strcpy(genbuf, "jackal");
|
|
break;
|
|
case PM_WEREWOLF:
|
|
case PM_HUMAN_WEREWOLF:
|
|
typ = rn2(5) ? PM_WOLF : rn2(2) ? PM_WARG : PM_WINTER_WOLF;
|
|
if (genbuf)
|
|
Strcpy(genbuf, "wolf");
|
|
break;
|
|
default:
|
|
continue;
|
|
}
|
|
mtmp = makemon(&mons[typ], u.ux, u.uy, NO_MM_FLAGS);
|
|
if (mtmp) {
|
|
total++;
|
|
if (canseemon(mtmp))
|
|
*visible += 1;
|
|
}
|
|
if (yours && mtmp)
|
|
(void) tamedog(mtmp, (struct obj *) 0);
|
|
}
|
|
return total;
|
|
}
|
|
|
|
void
|
|
you_were(void)
|
|
{
|
|
char qbuf[QBUFSZ];
|
|
boolean controllable_poly = Polymorph_control && !(Stunned || Unaware);
|
|
|
|
if (Unchanging || u.umonnum == u.ulycn)
|
|
return;
|
|
if (controllable_poly) {
|
|
/* `+4' => skip "were" prefix to get name of beast */
|
|
Sprintf(qbuf, "Do you want to change into %s?",
|
|
an(mons[u.ulycn].pmnames[NEUTRAL] + 4));
|
|
if (!paranoid_query(ParanoidWerechange, qbuf))
|
|
return;
|
|
}
|
|
(void) polymon(u.ulycn);
|
|
}
|
|
|
|
void
|
|
you_unwere(boolean purify)
|
|
{
|
|
boolean controllable_poly = Polymorph_control && !(Stunned || Unaware);
|
|
|
|
if (purify) {
|
|
You_feel("purified.");
|
|
set_ulycn(NON_PM); /* cure lycanthropy */
|
|
}
|
|
if (!Unchanging && is_were(g.youmonst.data)
|
|
&& (!controllable_poly
|
|
|| !paranoid_query(ParanoidWerechange, "Remain in beast form?")))
|
|
rehumanize();
|
|
else if (is_were(g.youmonst.data) && !u.mtimedone)
|
|
u.mtimedone = rn1(200, 200); /* 40% of initial were change */
|
|
}
|
|
|
|
/* lycanthropy is being caught or cured, but no shape change is involved */
|
|
void
|
|
set_ulycn(int which)
|
|
{
|
|
u.ulycn = which;
|
|
/* add or remove lycanthrope's innate intrinsics (Drain_resistance) */
|
|
set_uasmon();
|
|
}
|
|
|
|
/*were.c*/
|