]> granicus.if.org Git - nethack/commitdiff
Some more therecmdmenu
authorPasi Kallinen <paxed@alt.org>
Fri, 8 Apr 2022 16:45:10 +0000 (19:45 +0300)
committerPasi Kallinen <paxed@alt.org>
Fri, 8 Apr 2022 16:48:01 +0000 (19:48 +0300)
If on, therecmdmenu handles clicking anywhere on the map,
not just on or next to hero.  Add throwing items to the menu.

src/cmd.c

index c1655bc07752f3cd08060eebcb6b24683930c363..a525b9e3a6d3bda0b4b4b719c44d8eede50f4f52 100644 (file)
--- a/src/cmd.c
+++ b/src/cmd.c
@@ -149,7 +149,7 @@ static boolean accept_menu_prefix(const struct ext_func_tab *);
 static void reset_cmd_vars(boolean);
 static void mcmd_addmenu(winid, int, const char *);
 static char here_cmd_menu(void);
-static char there_cmd_menu(int, int);
+static char there_cmd_menu(int, int, int);
 static char readchar_core(int *, int *, int *);
 static char *parse(void);
 static void show_direction_keys(winid, char, boolean);
@@ -4474,7 +4474,7 @@ dotherecmdmenu(void)
         return ECMD_CANCEL;
 
     if (u.dx || u.dy)
-        ch = there_cmd_menu(u.ux + u.dx, u.uy + u.dy);
+        ch = there_cmd_menu(u.ux + u.dx, u.uy + u.dy, CLICK_1);
     else
         ch = here_cmd_menu();
 
@@ -4510,9 +4510,13 @@ enum menucmd {
     MCMD_DROP,
     MCMD_REST,
     MCMD_LOOK_HERE,
+    MCMD_LOOK_AT,
     MCMD_ATTACK_NEXT2U,
     MCMD_UNTRAP_HERE,
     MCMD_OFFER,
+
+    MCMD_THROW_OBJ,
+    MCMD_TRAVEL,
 };
 
 static void
@@ -4526,24 +4530,99 @@ mcmd_addmenu(winid win, int act, const char *txt)
     add_menu(win, &nul_glyphinfo, &any, '\0', 0, ATR_NONE, txt, MENU_ITEMFLAGS_NONE);
 }
 
-/* offer choice of actions to perform at adjacent location <x,y> */
-static char
-there_cmd_menu(int x, int y)
+/* command menu entries when targeting self */
+static int
+there_cmd_menu_self(winid win, int x, int y, int *act UNUSED)
 {
-    winid win;
-    char ch;
+    int K = 0;
+    char buf[BUFSZ];
+    schar typ = levl[x][y].typ;
+    stairway *stway = stairway_at(x, y);
+    struct trap *ttmp;
+
+    if (!u_at(x,y))
+        return K;
+
+    if ((IS_FOUNTAIN(typ) || IS_SINK(typ)) && can_reach_floor(FALSE)) {
+        Sprintf(buf, "Drink from the %s",
+                defsyms[IS_FOUNTAIN(typ) ? S_fountain : S_sink].explanation);
+        mcmd_addmenu(win, MCMD_QUAFF, buf), ++K;
+    }
+    if (IS_FOUNTAIN(typ) && can_reach_floor(FALSE))
+        mcmd_addmenu(win, MCMD_DIP, "Dip something into the fountain"), ++K;
+    if (IS_THRONE(typ))
+        mcmd_addmenu(win, MCMD_SIT, "Sit on the throne"), ++K;
+    if (IS_ALTAR(typ))
+        mcmd_addmenu(win, MCMD_OFFER, "Sacrifice something on the altar"), ++K;
+
+    if (stway && stway->up) {
+        Sprintf(buf, "Go up the %s",
+                stway->isladder ? "ladder" : "stairs");
+        mcmd_addmenu(win, MCMD_UP, buf), ++K;
+    }
+    if (stway && !stway->up) {
+        Sprintf(buf, "Go down the %s",
+                stway->isladder ? "ladder" : "stairs");
+        mcmd_addmenu(win, MCMD_DOWN, buf), ++K;
+    }
+    if (u.usteed) { /* another movement choice */
+        Sprintf(buf, "Dismount %s",
+                x_monnam(u.usteed, ARTICLE_THE, (char *) 0,
+                         SUPPRESS_SADDLE, FALSE));
+        mcmd_addmenu(win, MCMD_DISMOUNT, buf), ++K;
+    }
+
+#if 0
+    if (Upolyd) { /* before objects */
+        Sprintf(buf, "Use %s special ability",
+                s_suffix(pmname(&mons[u.umonnum], Ugender)));
+        mcmd_addmenu(win, MCMD_MONABILITY, buf), ++K;
+    }
+#endif
+
+    if (OBJ_AT(x, y)) {
+        struct obj *otmp = g.level.objects[x][y];
+
+        Sprintf(buf, "Pick up %s", otmp->nexthere ? "items" : doname(otmp));
+        mcmd_addmenu(win, MCMD_PICKUP, buf), ++K;
+
+        if (Is_container(otmp)) {
+            Sprintf(buf, "Loot %s", doname(otmp));
+            mcmd_addmenu(win, MCMD_LOOT, buf), ++K;
+        }
+        if (otmp->oclass == FOOD_CLASS) {
+            Sprintf(buf, "Eat %s", doname(otmp));
+            mcmd_addmenu(win, MCMD_EAT, buf), ++K;
+        }
+    }
+
+    if (g.invent)
+        mcmd_addmenu(win, MCMD_DROP, "Drop items"), ++K;
+
+    mcmd_addmenu(win, MCMD_REST, "Rest one turn"), ++K;
+    mcmd_addmenu(win, MCMD_SEARCH, "Search around you"), ++K;
+    mcmd_addmenu(win, MCMD_LOOK_HERE, "Look at what is here"), ++K;
+
+    if ((ttmp = t_at(x, y)) != 0 && ttmp->tseen) {
+        if (ttmp->ttyp != VIBRATING_SQUARE)
+            mcmd_addmenu(win, MCMD_UNTRAP_HERE,
+                         "Attempt to disarm trap"), ++K;
+    }
+    return K;
+}
+
+/* add entries to there_cmd_menu, when x,y is next to hero */
+static int
+there_cmd_menu_next2u(winid win, int x, int y, int mod, int *act)
+{
+    int K = 0;
     char buf[BUFSZ];
     schar typ = levl[x][y].typ;
-    int npick, K = 0;
-    menu_item *picks = (menu_item *) 0;
     struct trap *ttmp;
     struct monst *mtmp;
-    int dx = sgn(x - u.ux), dy = sgn(y - u.uy);
-    int dir = xytod(dx, dy);
-    boolean do_attack = FALSE;
 
-    win = create_nhwindow(NHW_MENU);
-    start_menu(win, MENU_BEHAVE_STANDARD);
+    if (!next2u(x, y))
+        return K;
 
     if (IS_DOOR(typ)) {
         boolean key_or_pick, card;
@@ -4566,7 +4645,7 @@ there_cmd_menu(int x, int y)
                          "Search the door for a trap"), ++K;
             /* [what about #force?] */
             mcmd_addmenu(win, MCMD_KICK_DOOR, "Kick the door"), ++K;
-        } else if ((dm & D_ISOPEN)) {
+        } else if ((dm & D_ISOPEN) && (mod == CLICK_2)) {
             mcmd_addmenu(win, MCMD_CLOSE_DOOR, "Close the door"), ++K;
         }
     }
@@ -4579,6 +4658,7 @@ there_cmd_menu(int x, int y)
         if (ttmp->ttyp != VIBRATING_SQUARE)
             mcmd_addmenu(win, MCMD_UNTRAP_TRAP,
                                  "Attempt to disarm trap"), ++K;
+        /* TODO: "Step on the <trap>" */
     }
 
     mtmp = m_at(x, y);
@@ -4617,16 +4697,82 @@ there_cmd_menu(int x, int y)
     if (mtmp || glyph_is_invisible(glyph_at(x, y))) {
         Sprintf(buf, "Attack %s", mtmp ? mon_nam(mtmp) : "unseen creature");
         mcmd_addmenu(win, MCMD_ATTACK_NEXT2U, buf), ++K;
-        do_attack = TRUE;
+        /* attacking overrides any other automatic action */
+        *act = MCMD_ATTACK_NEXT2U;
     } else {
         /* "Move %s", direction - handled below */
     }
+    return K;
+}
+
+static int
+there_cmd_menu_far(winid win, xchar x, xchar y, int mod)
+{
+    int K = 0;
+
+    if (mod != CLICK_2)
+        return K;
+
+    if (linedup(u.ux, u.uy, x, y, 1) && (dist2(u.ux, u.uy, x, y) < 18*18)) {
+        mcmd_addmenu(win, MCMD_THROW_OBJ, "Throw something"), ++K;
+    }
+
+    if (flags.travelcmd) {
+        mcmd_addmenu(win, MCMD_TRAVEL, "Travel here"), ++K;
+    }
+
+    return K;
+}
+
+static int
+there_cmd_menu_common(winid win, xchar x UNUSED, xchar y UNUSED, int mod, int *act UNUSED)
+{
+    int K = 0;
+
+    if (mod == CLICK_2 && iflags.clicklook) {
+        mcmd_addmenu(win, MCMD_LOOK_AT, "Look at map symbol"), ++K;
+    }
+
+    return K;
+}
+
+/* offer choice of actions to perform at adjacent location <x,y> */
+static char
+there_cmd_menu(int x, int y, int mod)
+{
+    winid win;
+    char ch = '\0';
+    int npick = 0, K = 0;
+    menu_item *picks = (menu_item *) 0;
+    int dx = sgn(x - u.ux), dy = sgn(y - u.uy);
+    int dir = xytod(dx, dy);
+    int act = MCMD_NOTHING;
+
+    win = create_nhwindow(NHW_MENU);
+    start_menu(win, MENU_BEHAVE_STANDARD);
 
-    /* no menu options, or only the attack option? */
-    if (!K || ((K == 1) && do_attack)) {
-        cmdq_add_ec(move_funcs[dir][MV_WALK]);
+    if (u_at(x, y))
+        K += there_cmd_menu_self(win, x, y, &act);
+    else if (next2u(x, y))
+        K += there_cmd_menu_next2u(win, x, y, mod, &act);
+    else
+        K += there_cmd_menu_far(win, x, y, mod);
+    K += there_cmd_menu_common(win, x, y, mod, &act);
+
+    if (!K) {
+        /* no menu options, try to move */
+        if (next2u(x, y) && !test_move(u.ux, u.uy, x, y, TEST_MOVE))
+            cmdq_add_ec(move_funcs[dir][MV_WALK]);
+        else if (flags.travelcmd) {
+            iflags.travelcc.x = u.tx = x;
+            iflags.travelcc.y = u.ty = y;
+            cmdq_add_ec(dotravel_target);
+        }
         npick = 0;
         ch = '\0';
+    } else if ((K == 1) && (act != MCMD_NOTHING)) {
+        destroy_nhwindow(win);
+        goto act_on_act;
     } else {
         end_menu(win, "What do you want to do?");
         npick = select_menu(win, PICK_ONE, &picks);
@@ -4634,11 +4780,22 @@ there_cmd_menu(int x, int y)
     }
     destroy_nhwindow(win);
     if (npick > 0) {
-        int act = picks->item.a_int;
+        act = picks->item.a_int;
 
         free((genericptr_t) picks);
 
+    act_on_act:
         switch (act) {
+        case MCMD_TRAVEL:
+            iflags.travelcc.x = u.tx = x;
+            iflags.travelcc.y = u.ty = y;
+            cmdq_add_ec(dotravel_target);
+            break;
+        case MCMD_THROW_OBJ:
+            cmdq_add_ec(dothrow);
+            cmdq_add_userinput();
+            cmdq_add_dir(dx, dy, 0);
+            break;
         case MCMD_OPEN_DOOR:
             cmdq_add_ec(doopen);
             cmdq_add_dir(dx, dy, 0);
@@ -4705,104 +4862,6 @@ there_cmd_menu(int x, int y)
             cmdq_add_ec(dotalk);
             cmdq_add_dir(dx, dy, 0);
             break;
-        default: break;
-        }
-        return '\0';
-    }
-    return ch;
-}
-
-static char
-here_cmd_menu(void)
-{
-    winid win;
-    char ch;
-    char buf[BUFSZ];
-    schar typ = levl[u.ux][u.uy].typ;
-    int npick;
-    menu_item *picks = (menu_item *) 0;
-    stairway *stway = stairway_at(u.ux, u.uy);
-    struct trap *ttmp;
-
-    win = create_nhwindow(NHW_MENU);
-    start_menu(win, MENU_BEHAVE_STANDARD);
-
-    if ((IS_FOUNTAIN(typ) || IS_SINK(typ)) && can_reach_floor(FALSE)) {
-        Sprintf(buf, "Drink from the %s",
-                defsyms[IS_FOUNTAIN(typ) ? S_fountain : S_sink].explanation);
-        mcmd_addmenu(win, MCMD_QUAFF, buf);
-    }
-    if (IS_FOUNTAIN(typ) && can_reach_floor(FALSE))
-        mcmd_addmenu(win, MCMD_DIP, "Dip something into the fountain");
-    if (IS_THRONE(typ))
-        mcmd_addmenu(win, MCMD_SIT, "Sit on the throne");
-    if (IS_ALTAR(typ))
-        mcmd_addmenu(win, MCMD_OFFER, "Sacrifice something on the altar");
-
-    if (stway && stway->up) {
-        Sprintf(buf, "Go up the %s",
-                stway->isladder ? "ladder" : "stairs");
-        mcmd_addmenu(win, MCMD_UP, buf);
-    }
-    if (stway && !stway->up) {
-        Sprintf(buf, "Go down the %s",
-                stway->isladder ? "ladder" : "stairs");
-        mcmd_addmenu(win, MCMD_DOWN, buf);
-    }
-    if (u.usteed) { /* another movement choice */
-        Sprintf(buf, "Dismount %s",
-                x_monnam(u.usteed, ARTICLE_THE, (char *) 0,
-                         SUPPRESS_SADDLE, FALSE));
-        mcmd_addmenu(win, MCMD_DISMOUNT, buf);
-    }
-
-#if 0
-    if (Upolyd) { /* before objects */
-        Sprintf(buf, "Use %s special ability",
-                s_suffix(pmname(&mons[u.umonnum], Ugender)));
-        mcmd_addmenu(win, MCMD_MONABILITY, buf);
-    }
-#endif
-
-    if (OBJ_AT(u.ux, u.uy)) {
-        struct obj *otmp = g.level.objects[u.ux][u.uy];
-
-        Sprintf(buf, "Pick up %s", otmp->nexthere ? "items" : doname(otmp));
-        mcmd_addmenu(win, MCMD_PICKUP, buf);
-
-        if (Is_container(otmp)) {
-            Sprintf(buf, "Loot %s", doname(otmp));
-            mcmd_addmenu(win, MCMD_LOOT, buf);
-        }
-        if (otmp->oclass == FOOD_CLASS) {
-            Sprintf(buf, "Eat %s", doname(otmp));
-            mcmd_addmenu(win, MCMD_EAT, buf);
-        }
-    }
-
-    if (g.invent)
-        mcmd_addmenu(win, MCMD_DROP, "Drop items");
-
-    mcmd_addmenu(win, MCMD_REST, "Rest one turn");
-    mcmd_addmenu(win, MCMD_SEARCH, "Search around you");
-    mcmd_addmenu(win, MCMD_LOOK_HERE, "Look at what is here");
-
-    if ((ttmp = t_at(u.ux, u.uy)) != 0 && ttmp->tseen) {
-        if (ttmp->ttyp != VIBRATING_SQUARE)
-            mcmd_addmenu(win, MCMD_UNTRAP_HERE,
-                         "Attempt to disarm trap");
-    }
-
-    end_menu(win, "What do you want to do?");
-    npick = select_menu(win, PICK_ONE, &picks);
-    destroy_nhwindow(win);
-    ch = '\033';
-    if (npick > 0) {
-        int act = picks->item.a_int;
-
-        free((genericptr_t) picks);
-
-        switch (act) {
         case MCMD_QUAFF:
             cmdq_add_ec(dodrink);
             cmdq_add_key('y'); /* "Drink from the fountain?" */
@@ -4843,12 +4902,14 @@ here_cmd_menu(void)
         case MCMD_REST:
             cmdq_add_ec(donull);
             break;
-        case MCMD_SEARCH:
-            cmdq_add_ec(dosearch);
-            break;
         case MCMD_LOOK_HERE:
             cmdq_add_ec(dolook);
             break;
+        case MCMD_LOOK_AT:
+            g.clicklook_cc.x = x;
+            g.clicklook_cc.y = y;
+            cmdq_add_ec(doclicklook);
+            break;
         case MCMD_UNTRAP_HERE:
             cmdq_add_ec(dountrap);
             cmdq_add_dir(0, 0, 1);
@@ -4864,6 +4925,13 @@ here_cmd_menu(void)
     return ch;
 }
 
+static char
+here_cmd_menu(void)
+{
+    there_cmd_menu(u.ux, u.uy, CLICK_1);
+    return '\0';
+}
+
 /*
  * convert a MAP window position into a movement key usable with movecmd()
  */
@@ -4872,28 +4940,18 @@ click_to_cmd(int x, int y, int mod)
 {
     static char cmd[4];
     struct obj *o;
-    int dir, udist;
+    int dir;
 
     cmd[0] = cmd[1] = '\0';
-    if (iflags.clicklook && mod == CLICK_2) {
+    if (!iflags.herecmd_menu && iflags.clicklook && mod == CLICK_2) {
         g.clicklook_cc.x = x;
         g.clicklook_cc.y = y;
         cmdq_add_ec(doclicklook);
         return cmd;
     }
-    /* this used to be inside the 'if (flags.travelcmd)' block, but
-       handle click-on-self even when travel is disabled; unlike
-       accidentally zooming across the level because of a stray click,
-       clicking on self can easily be cancelled if it wasn't intended */
     if (iflags.herecmd_menu && isok(x, y)) {
-        udist = distu(x, y);
-        if (!udist) {
-            cmd[0] = here_cmd_menu();
-            return cmd;
-        } else if (udist <= 2) {
-            cmd[0] = there_cmd_menu(x, y);
-            return cmd;
-        }
+        (void) there_cmd_menu(x, y, mod);
+        return cmd;
     }
 
     x -= u.ux;
@@ -5301,7 +5359,7 @@ dotravel_target(void)
 static int
 doclicklook(void)
 {
-    if (!iflags.clicklook || !isok(g.clicklook_cc.x, g.clicklook_cc.y))
+    if (!isok(g.clicklook_cc.x, g.clicklook_cc.y))
         return 0;
 
     g.context.move = FALSE;