]> granicus.if.org Git - nethack/commitdiff
add new #wizkill command
authorPatR <rankin@nethack.org>
Sun, 22 May 2022 00:40:52 +0000 (17:40 -0700)
committerPatR <rankin@nethack.org>
Sun, 22 May 2022 00:40:52 +0000 (17:40 -0700)
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.

doc/Guidebook.mn
doc/Guidebook.tex
doc/fixes3-7-0.txt
src/cmd.c
src/do_name.c

index 80aa63355947a87840635f7a4f0d49d86a7b23f5..80f5aedaed94afbf901bea4a24cd32f69071264a 100644 (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.
index 27cc137e7d240fcd2abb3e5b4bf1a9e5e1bc5ac9..51e808236ea8c1ee63135a596504596aa5c57f3e 100644 (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.
index 5bb014b5d80e24ad31e07eec44c507b3b822788e..1b2457c1a78febab46dd821aa7e448bc1064bf13 100644 (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
index 642c4e3d86778b94828decf910ab4bf41885f139..1809e61cd6dea51fe8cca0765e294b9fc0db1287 100644 (file)
--- a/src/cmd.c
+++ b/src/cmd.c
@@ -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",
index c7e5a5c02e1da9d941f5adde90013d0170e3244a..bf927d8513fd53f8490fc906be920a2305734edf 100644 (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);