add new #wizkill command

Add a way to get rid of specific monsters in wizard mode without
fighting, zapping, &c.  #wizkill command lets you kill creatures by
picking them with getpos().

You can pick multiple monsters by targetting them one after another.
You don't have to be able to see or sense them but if you target a
spot that has no monster, the command ends.

By default, the hero gets credit or blame as if having killed the
targets but #wizkill can be preceded by 'm' prefix to treat their
deaths as if they had been caused by a monster.
This commit is contained in:
PatR
2022-05-21 17:40:52 -07:00
parent 15882c5bee
commit af55e3d027
5 changed files with 82 additions and 3 deletions

View File

@@ -1709,6 +1709,10 @@ Default key is \(oq\(haI\(cq.
Set one or more intrinsic attributes.
Autocompletes.
Debug mode only.
.lp "#wizkill "
Remove monsters from play by just pointing at them.
Autocompletes.
Debug mode only.
.lp #wizlevelport
Teleport to another level.
Autocompletes.

View File

@@ -1837,6 +1837,11 @@ Set one or more intrinsic attributes.
Autocompletes.
Debug mode only.
%.lp
\item[\tb{\#wizkill}]
Remove monsters from play by just pointing at them.
Autocompletes.
Debug mode only.
%.lp
\item[\tb{\#wizlevelport}]
Teleport to another level.
Autocompletes.

View File

@@ -1641,6 +1641,7 @@ display detected door traps and chest traps as trapped doors and trapped
if built with DEBUG enabled and running in wizard mode, starting play with
DEBUGFILES=seethru in environment makes clouds on the Plane of Air,
water on Plane of Water, and fumaroles on Plane of Fire be transparent
add wizard mode #wizkill command to remove monster(s) from play
Platform- and/or Interface-Specific New Features

View File

@@ -114,6 +114,7 @@ static int wiz_where(void);
static int wiz_detect(void);
static int wiz_panic(void);
static int wiz_polyself(void);
static int wiz_kill(void);
static int wiz_load_lua(void);
static int wiz_level_tele(void);
static int wiz_level_change(void);
@@ -1155,6 +1156,68 @@ wiz_detect(void)
return ECMD_OK;
}
/* the #wizkill command - pick targets and reduce them to 0HP;
by default, the hero is credited/blamed; use 'm' prefix to avoid that */
static int
wiz_kill()
{
struct monst *mtmp;
coord cc;
int ans;
char c, qbuf[QBUFSZ];
const char *prompt = "Pick first monster to slay";
boolean save_verbose = flags.verbose;
cc.x = u.ux, cc.y = u.uy;
for (;;) {
pline("%s:", prompt);
prompt = "Next monster";
flags.verbose = FALSE;
ans = getpos(&cc, TRUE, "a monster");
flags.verbose = save_verbose;
if (ans < 0 || cc.x < 1)
break;
mtmp = 0;
if (u_at(cc.x, cc.y)) {
if (u.usteed) {
Sprintf(qbuf, "Kill %.110s?", mon_nam(u.usteed));
if ((c = ynq(qbuf)) == 'q')
break;
if (c == 'y')
mtmp = u.usteed;
}
if (!mtmp) {
Sprintf(qbuf, "%s?", Role_if(PM_SAMURAI) ? "Perform seppuku"
: "Commit suicide");
if (paranoid_query(TRUE, qbuf)) {
Sprintf(g.killer.name, "%s own player", uhis());
g.killer.format = KILLED_BY;
done(DIED);
}
break;
}
} else {
mtmp = m_at(cc.x, cc.y);
}
if (mtmp) {
/* we don't require that monster be seen or sensed but when it
isn't, death message will be "You kill it" or "It is killed" */
if (!iflags.menu_requested)
killed(mtmp); /* normal case: hero is credited/blamed */
else
monkilled(mtmp, "", AD_PHYS); /* 'm'-prefix */
} else {
There("is no monster there.");
break;
}
}
/* distinction between ECMD_CANCEL and ECMD_OK is unimportant here */
return ECMD_OK; /* no time elapses */
}
/* the #wizloadlua command - load an arbitrary lua file */
static int
wiz_load_lua(void)
@@ -1166,7 +1229,7 @@ wiz_load_lua(void)
buf[0] = '\0';
getlin("Load which lua file?", buf);
if (buf[0] == '\033' || buf[0] == '\0')
return 0;
return ECMD_CANCEL;
if (!strchr(buf, '.'))
strcat(buf, ".lua");
(void) load_lua(buf, &sbi);
@@ -1185,7 +1248,7 @@ wiz_load_splua(void)
buf[0] = '\0';
getlin("Load which des lua file?", buf);
if (buf[0] == '\033' || buf[0] == '\0')
return 0;
return ECMD_CANCEL;
if (!strchr(buf, '.'))
strcat(buf, ".lua");
@@ -1303,7 +1366,7 @@ wiz_telekinesis(void)
pline("Pick a monster to hurtle.");
do {
ans = getpos(&cc, TRUE, "a monster");
if (ans < 0 || cc.x < 0)
if (ans < 0 || cc.x < 1)
return ECMD_CANCEL;
if ((((mtmp = m_at(cc.x, cc.y)) != 0) && canspotmon(mtmp))
@@ -2524,6 +2587,9 @@ struct ext_func_tab extcmdlist[] = {
wiz_identify, IFBURIED | WIZMODECMD, NULL },
{ '\0', "wizintrinsic", "set an intrinsic",
wiz_intrinsic, IFBURIED | AUTOCOMPLETE | WIZMODECMD, NULL },
{ '\0', "wizkill", "slay a monster",
wiz_kill, (IFBURIED | AUTOCOMPLETE | WIZMODECMD
| CMD_M_PREFIX | NOFUZZERCMD), NULL },
{ C('v'), "wizlevelport", "teleport to another level",
wiz_level_tele, IFBURIED | WIZMODECMD | CMD_M_PREFIX, NULL },
{ '\0', "wizloaddes", "load and execute a des-file lua script",

View File

@@ -136,6 +136,8 @@ getpos_help(boolean force, const char *goal)
visctrl(g.Cmd.spkeys[NHKF_GETPOS_MON_PREV]),
GLOC_MONS);
}
if (goal && !strcmp(goal, "a monster"))
goto skip_non_mons;
if (!iflags.terrainmode || (iflags.terrainmode & TER_OBJ) != 0) {
getpos_help_keyxhelp(tmpwin,
visctrl(g.Cmd.spkeys[NHKF_GETPOS_OBJ_NEXT]),
@@ -195,6 +197,7 @@ getpos_help(boolean force, const char *goal)
: "(Reset 'whatis_coord' option to omit coordinates from '%s' text.)",
visctrl(g.Cmd.spkeys[NHKF_GETPOS_AUTODESC]));
}
skip_non_mons:
/* disgusting hack; the alternate selection characters work for any
getpos call, but only matter for dowhatis (and doquickwhatis) */
doing_what_is = (goal == what_is_an_unknown_object);