Move item actions into separate src file
Haven't tested compilation on Windows and VMS ...
This commit is contained in:
@@ -1240,6 +1240,10 @@ extern boolean pmatchi(const char *, const char *) NONNULLPTRS;
|
||||
extern boolean pmatchz(const char *, const char *) NONNULLPTRS;
|
||||
*/
|
||||
|
||||
/* ### iactions.c ### */
|
||||
|
||||
extern int itemactions(struct obj *otmp) NONNULLARG1;
|
||||
|
||||
/* ### insight.c ### */
|
||||
|
||||
extern int doattributes(void);
|
||||
|
||||
@@ -571,6 +571,11 @@ enum hunger_state_types {
|
||||
STARVED = 6
|
||||
};
|
||||
|
||||
/* fake inventory letters, not 'a'..'z' or 'A'..'Z' */
|
||||
#define NOINVSYM '#' /* overflow because all 52 letters are in use */
|
||||
#define CONTAINED_SYM '>' /* designator for inside a container */
|
||||
#define HANDS_SYM '-' /* hands|fingers|self depending on context */
|
||||
|
||||
/* inventory counts (slots in tty parlance)
|
||||
* a...zA..Z invlet_basic (52)
|
||||
* $a...zA..Z# 2 special additions
|
||||
|
||||
716
src/iactions.c
Normal file
716
src/iactions.c
Normal file
@@ -0,0 +1,716 @@
|
||||
/* NetHack 3.7 iactions.c $NHDT-Date: 1762680996 2025/11/09 01:36:36 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.543 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/*-Copyright (c) Pasi Kallinen, 2026. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
#include "hack.h"
|
||||
|
||||
staticfn boolean item_naming_classification(struct obj *, char *, char *);
|
||||
staticfn int item_reading_classification(struct obj *, char *);
|
||||
staticfn void ia_addmenu(winid, int, char, const char *);
|
||||
staticfn void itemactions_pushkeys(struct obj *, int);
|
||||
|
||||
enum item_action_actions {
|
||||
IA_NONE = 0,
|
||||
IA_UNWIELD, /* hack for 'w-' */
|
||||
IA_APPLY_OBJ, /* 'a' */
|
||||
IA_DIP_OBJ, /* 'a' on a potion == dip */
|
||||
IA_NAME_OBJ, /* 'c' name individual item */
|
||||
IA_NAME_OTYP, /* 'C' name item's type */
|
||||
IA_DROP_OBJ, /* 'd' */
|
||||
IA_EAT_OBJ, /* 'e' */
|
||||
IA_ENGRAVE_OBJ, /* 'E' */
|
||||
IA_FIRE_OBJ, /* 'f' */
|
||||
IA_ADJUST_OBJ, /* 'i' #adjust inventory letter */
|
||||
IA_ADJUST_STACK, /* 'I' #adjust with count to split stack */
|
||||
IA_SACRIFICE, /* 'O' offer sacrifice */
|
||||
IA_BUY_OBJ, /* 'p' pay shopkeeper */
|
||||
IA_QUAFF_OBJ,
|
||||
IA_QUIVER_OBJ,
|
||||
IA_READ_OBJ,
|
||||
IA_RUB_OBJ,
|
||||
IA_THROW_OBJ,
|
||||
IA_TAKEOFF_OBJ,
|
||||
IA_TIP_CONTAINER,
|
||||
IA_INVOKE_OBJ,
|
||||
IA_WIELD_OBJ,
|
||||
IA_WEAR_OBJ,
|
||||
IA_SWAPWEAPON,
|
||||
IA_TWOWEAPON,
|
||||
IA_ZAP_OBJ,
|
||||
IA_WHATIS_OBJ, /* '/' specify inventory object */
|
||||
};
|
||||
|
||||
/* construct text for the menu entries for IA_NAME_OBJ and IA_NAME_OTYP */
|
||||
staticfn boolean
|
||||
item_naming_classification(
|
||||
struct obj *obj,
|
||||
char *onamebuf,
|
||||
char *ocallbuf)
|
||||
{
|
||||
static const char
|
||||
Name[] = "Name",
|
||||
Rename[] = "Rename or un-name",
|
||||
Call[] = "Call",
|
||||
/* "re-call" seems a bit weird, but "recall" and
|
||||
"rename" don't fit for changing a type name */
|
||||
Recall[] = "Re-call or un-call";
|
||||
|
||||
onamebuf[0] = ocallbuf[0] = '\0';
|
||||
if (name_ok(obj) == GETOBJ_SUGGEST) {
|
||||
Sprintf(onamebuf, "%s %s %s",
|
||||
(!has_oname(obj) || !*ONAME(obj)) ? Name : Rename,
|
||||
the_unique_obj(obj) ? "the"
|
||||
: !is_plural(obj) ? "this specific"
|
||||
: "this stack of", /*"these",*/
|
||||
simpleonames(obj));
|
||||
}
|
||||
if (call_ok(obj) == GETOBJ_SUGGEST) {
|
||||
char *callname = simpleonames(obj);
|
||||
|
||||
/* prefix known unique item with "the", make all other types plural */
|
||||
if (the_unique_obj(obj)) /* treats unID'd fake amulets as if real */
|
||||
callname = the(callname);
|
||||
else if (!is_plural(obj))
|
||||
callname = makeplural(callname);
|
||||
Sprintf(ocallbuf, "%s the type for %s",
|
||||
(!objects[obj->otyp].oc_uname
|
||||
|| !*objects[obj->otyp].oc_uname) ? Call : Recall,
|
||||
callname);
|
||||
}
|
||||
return (*onamebuf || *ocallbuf) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
/* construct text for the menu entries for IA_READ_OBJ */
|
||||
staticfn int
|
||||
item_reading_classification(struct obj *obj, char *outbuf)
|
||||
{
|
||||
int otyp = obj->otyp, res = IA_READ_OBJ;
|
||||
|
||||
*outbuf = '\0';
|
||||
if (otyp == FORTUNE_COOKIE) {
|
||||
Strcpy(outbuf, "Read the message inside this cookie");
|
||||
} else if (otyp == T_SHIRT) {
|
||||
Strcpy(outbuf, "Read the slogan on the shirt");
|
||||
} else if (otyp == ALCHEMY_SMOCK) {
|
||||
Strcpy(outbuf, "Read the slogan on the apron");
|
||||
} else if (otyp == HAWAIIAN_SHIRT) {
|
||||
Strcpy(outbuf, "Look at the pattern on the shirt");
|
||||
} else if (obj->oclass == SCROLL_CLASS) {
|
||||
const char *magic = ((obj->dknown
|
||||
#ifdef MAIL_STRUCTURES
|
||||
&& otyp != SCR_MAIL
|
||||
#endif
|
||||
&& (otyp != SCR_BLANK_PAPER
|
||||
|| !objects[otyp].oc_name_known))
|
||||
? " to activate its magic" : "");
|
||||
|
||||
Sprintf(outbuf, "Read this scroll%s", magic);
|
||||
} else if (obj->oclass == SPBOOK_CLASS) {
|
||||
boolean novel = (otyp == SPE_NOVEL),
|
||||
blank = (otyp == SPE_BLANK_PAPER
|
||||
&& objects[otyp].oc_name_known),
|
||||
tome = (otyp == SPE_BOOK_OF_THE_DEAD
|
||||
&& objects[otyp].oc_name_known);
|
||||
|
||||
Sprintf(outbuf, "%s this %s",
|
||||
(novel || blank) ? "Read" : tome ? "Examine" : "Study",
|
||||
novel ? simpleonames(obj) /* "novel" or "paperback book" */
|
||||
: tome ? "tome" : "spellbook");
|
||||
} else {
|
||||
res = IA_NONE;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
staticfn void
|
||||
ia_addmenu(winid win, int act, char let, const char *txt)
|
||||
{
|
||||
anything any;
|
||||
int clr = NO_COLOR;
|
||||
|
||||
any = cg.zeroany;
|
||||
any.a_int = act;
|
||||
add_menu(win, &nul_glyphinfo, &any, let, 0,
|
||||
ATR_NONE, clr, txt, MENU_ITEMFLAGS_NONE);
|
||||
}
|
||||
|
||||
/* set up a command to execute on a specific item next */
|
||||
staticfn void
|
||||
itemactions_pushkeys(struct obj *otmp, int act)
|
||||
{
|
||||
switch (act) {
|
||||
default:
|
||||
impossible("Unknown item action %d", act);
|
||||
break;
|
||||
case IA_NONE:
|
||||
break;
|
||||
case IA_UNWIELD:
|
||||
cmdq_add_ec(CQ_CANNED, (otmp == uwep) ? dowield
|
||||
: (otmp == uswapwep) ? remarm_swapwep
|
||||
: (otmp == uquiver) ? dowieldquiver
|
||||
: donull); /* can't happen */
|
||||
cmdq_add_key(CQ_CANNED, HANDS_SYM);
|
||||
break;
|
||||
case IA_APPLY_OBJ:
|
||||
cmdq_add_ec(CQ_CANNED, doapply);
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_DIP_OBJ:
|
||||
/* #altdip instead of normal #dip - takes potion to dip into
|
||||
first (the inventory item instigating this) and item to
|
||||
be dipped second, also ignores floor features such as
|
||||
fountain/sink so we don't need to force m-prefix here */
|
||||
cmdq_add_ec(CQ_CANNED, dip_into);
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_NAME_OBJ:
|
||||
case IA_NAME_OTYP:
|
||||
cmdq_add_ec(CQ_CANNED, docallcmd);
|
||||
cmdq_add_key(CQ_CANNED, (act == IA_NAME_OBJ) ? 'i' : 'o');
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_DROP_OBJ:
|
||||
cmdq_add_ec(CQ_CANNED, dodrop);
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_EAT_OBJ:
|
||||
/* start with m-prefix; for #eat, it means ignore floor food
|
||||
if present and eat food from invent */
|
||||
cmdq_add_ec(CQ_CANNED, do_reqmenu);
|
||||
cmdq_add_ec(CQ_CANNED, doeat);
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_ENGRAVE_OBJ:
|
||||
cmdq_add_ec(CQ_CANNED, doengrave);
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_FIRE_OBJ:
|
||||
cmdq_add_ec(CQ_CANNED, dofire);
|
||||
break;
|
||||
case IA_ADJUST_OBJ:
|
||||
cmdq_add_ec(CQ_CANNED, doorganize); /* #adjust */
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_ADJUST_STACK:
|
||||
cmdq_add_ec(CQ_CANNED, adjust_split); /* #altadjust */
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_SACRIFICE:
|
||||
cmdq_add_ec(CQ_CANNED, dosacrifice);
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_BUY_OBJ:
|
||||
cmdq_add_ec(CQ_CANNED, dopay);
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_QUAFF_OBJ:
|
||||
/* start with m-prefix; for #quaff, it means ignore fountain
|
||||
or sink if present and drink a potion from invent */
|
||||
cmdq_add_ec(CQ_CANNED, do_reqmenu);
|
||||
cmdq_add_ec(CQ_CANNED, dodrink);
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_QUIVER_OBJ:
|
||||
cmdq_add_ec(CQ_CANNED, dowieldquiver);
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_READ_OBJ:
|
||||
cmdq_add_ec(CQ_CANNED, doread);
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_RUB_OBJ:
|
||||
cmdq_add_ec(CQ_CANNED, dorub);
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_THROW_OBJ:
|
||||
cmdq_add_ec(CQ_CANNED, dothrow);
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_TAKEOFF_OBJ:
|
||||
cmdq_add_ec(CQ_CANNED, ia_dotakeoff); /* #altdotakeoff */
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_TIP_CONTAINER:
|
||||
/* start with m-prefix to skip floor containers;
|
||||
for menustyle:Traditional when more than one floor container
|
||||
is present, player will get a #tip menu and have to pick
|
||||
the "tip something being carried" choice, then this item
|
||||
will be already chosen from inventory; suboptimal but
|
||||
possibly an acceptable tradeoff since combining item actions
|
||||
with use of traditional ggetobj() is an unlikely scenario */
|
||||
cmdq_add_ec(CQ_CANNED, do_reqmenu);
|
||||
cmdq_add_ec(CQ_CANNED, dotip);
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_INVOKE_OBJ:
|
||||
cmdq_add_ec(CQ_CANNED, doinvoke);
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_WIELD_OBJ:
|
||||
cmdq_add_ec(CQ_CANNED, dowield);
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_WEAR_OBJ:
|
||||
cmdq_add_ec(CQ_CANNED, dowear);
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_SWAPWEAPON:
|
||||
cmdq_add_ec(CQ_CANNED, doswapweapon);
|
||||
break;
|
||||
case IA_TWOWEAPON:
|
||||
cmdq_add_ec(CQ_CANNED, dotwoweapon);
|
||||
break;
|
||||
case IA_ZAP_OBJ:
|
||||
cmdq_add_ec(CQ_CANNED, dozap);
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_WHATIS_OBJ:
|
||||
cmdq_add_ec(CQ_CANNED, dowhatis); /* "/" command */
|
||||
cmdq_add_key(CQ_CANNED, 'i'); /* "i" == item from inventory */
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Show menu of possible actions hero could do with item otmp */
|
||||
int
|
||||
itemactions(struct obj *otmp)
|
||||
{
|
||||
int n, act = IA_NONE;
|
||||
winid win;
|
||||
char buf[BUFSZ], buf2[BUFSZ];
|
||||
menu_item *selected;
|
||||
struct monst *mtmp;
|
||||
const char *light = otmp->lamplit ? "Extinguish" : "Light";
|
||||
boolean already_worn = (otmp->owornmask & (W_ARMOR | W_ACCESSORY)) != 0;
|
||||
|
||||
win = create_nhwindow(NHW_MENU);
|
||||
start_menu(win, MENU_BEHAVE_STANDARD);
|
||||
|
||||
/* -: unwield; picking current weapon offers an opportunity for 'w-'
|
||||
to wield bare/gloved hands; likewise for 'Q-' with quivered item(s) */
|
||||
if (otmp == uwep || otmp == uswapwep || otmp == uquiver) {
|
||||
const char *verb = (otmp == uquiver) ? "Quiver" : "Wield",
|
||||
*action = (otmp == uquiver) ? "un-ready" : "un-wield",
|
||||
*which = is_plural(otmp) ? "these" : "this",
|
||||
*what = ((otmp->oclass == WEAPON_CLASS || is_weptool(otmp))
|
||||
? "weapon" : "item");
|
||||
/*
|
||||
* TODO: if uwep is ammo, tell player that to shoot instead of toss,
|
||||
* the corresponding launcher must be wielded;
|
||||
*/
|
||||
Sprintf(buf, "%s '%c' to %s %s %s",
|
||||
verb, HANDS_SYM, action, which,
|
||||
is_plural(otmp) ? makeplural(what) : what);
|
||||
ia_addmenu(win, IA_UNWIELD, '-', buf);
|
||||
}
|
||||
|
||||
/* a: apply */
|
||||
if (otmp->oclass == COIN_CLASS)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Flip a coin");
|
||||
else if (otmp->otyp == CREAM_PIE)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a',
|
||||
"Hit yourself with this cream pie");
|
||||
else if (otmp->otyp == BULLWHIP)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Lash out with this whip");
|
||||
else if (otmp->otyp == GRAPPLING_HOOK)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a',
|
||||
"Grapple something with this hook");
|
||||
else if (otmp->otyp == BAG_OF_TRICKS && objects[otmp->otyp].oc_name_known)
|
||||
/* bag of tricks skips this unless discovered */
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Reach into this bag");
|
||||
else if (Is_container(otmp))
|
||||
/* bag of tricks gets here only if not yet discovered */
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Open this container");
|
||||
else if (otmp->otyp == CAN_OF_GREASE)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Use the can to grease an item");
|
||||
else if (otmp->otyp == LOCK_PICK
|
||||
|| otmp->otyp == CREDIT_CARD
|
||||
|| otmp->otyp == SKELETON_KEY)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Use this tool to pick a lock");
|
||||
else if (otmp->otyp == TINNING_KIT)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Use this kit to tin a corpse");
|
||||
else if (otmp->otyp == LEASH)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Tie a pet to this leash");
|
||||
else if (otmp->otyp == SADDLE)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Place this saddle on a pet");
|
||||
else if (otmp->otyp == MAGIC_WHISTLE
|
||||
|| otmp->otyp == TIN_WHISTLE)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Blow this whistle");
|
||||
else if (otmp->otyp == EUCALYPTUS_LEAF)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Use this leaf as a whistle");
|
||||
else if (otmp->otyp == STETHOSCOPE)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Listen through the stethoscope");
|
||||
else if (otmp->otyp == MIRROR)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Show something its reflection");
|
||||
else if (otmp->otyp == BELL || otmp->otyp == BELL_OF_OPENING)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Ring the bell");
|
||||
else if (otmp->otyp == CANDELABRUM_OF_INVOCATION) {
|
||||
Sprintf(buf, "%s the candelabrum", light);
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', buf);
|
||||
} else if (otmp->otyp == WAX_CANDLE || otmp->otyp == TALLOW_CANDLE) {
|
||||
boolean multiple = (otmp->quan == 1L) ? FALSE : TRUE;
|
||||
const char *s = multiple ? "these" : "this";
|
||||
struct obj *o = carrying(CANDELABRUM_OF_INVOCATION);
|
||||
|
||||
if (o && o->spe < 7)
|
||||
Sprintf(buf, "Attach %s to your candelabrum, or %s %s", s,
|
||||
!otmp->lamplit ? "light" : "extinguish", /* [lowercase] */
|
||||
multiple ? "them" : "it");
|
||||
else
|
||||
Sprintf(buf, "%s %s %s", light, s, simpleonames(otmp));
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', buf);
|
||||
} else if (otmp->otyp == OIL_LAMP || otmp->otyp == MAGIC_LAMP
|
||||
|| otmp->otyp == BRASS_LANTERN) {
|
||||
Sprintf(buf, "%s this light source", light);
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', buf);
|
||||
} else if (otmp->otyp == POT_OIL && objects[otmp->otyp].oc_name_known) {
|
||||
Sprintf(buf, "%s this oil", light);
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', buf);
|
||||
} else if (otmp->oclass == POTION_CLASS) {
|
||||
/* FIXME? this should probably be moved to 'D' rather than be 'a' */
|
||||
Sprintf(buf, "Dip something into %s potion%s",
|
||||
is_plural(otmp) ? "one of these" : "this", plur(otmp->quan));
|
||||
ia_addmenu(win, IA_DIP_OBJ, 'a', buf);
|
||||
} else if (otmp->otyp == EXPENSIVE_CAMERA)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Take a photograph");
|
||||
else if (otmp->otyp == TOWEL)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a',
|
||||
"Clean yourself off with this towel");
|
||||
else if (otmp->otyp == CRYSTAL_BALL)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Peer into this crystal ball");
|
||||
else if (otmp->otyp == MAGIC_MARKER)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a',
|
||||
"Write on something with this marker");
|
||||
else if (otmp->otyp == FIGURINE)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Make this figurine transform");
|
||||
else if (otmp->otyp == UNICORN_HORN)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Use this unicorn horn");
|
||||
else if (otmp->otyp == HORN_OF_PLENTY
|
||||
&& objects[otmp->otyp].oc_name_known)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Blow into the horn of plenty");
|
||||
else if (otmp->otyp >= WOODEN_FLUTE && otmp->otyp <= DRUM_OF_EARTHQUAKE)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Play this musical instrument");
|
||||
else if (otmp->otyp == LAND_MINE || otmp->otyp == BEARTRAP)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Arm this trap");
|
||||
else if (otmp->otyp == PICK_AXE || otmp->otyp == DWARVISH_MATTOCK)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Dig with this digging tool");
|
||||
else if (otmp->oclass == WAND_CLASS)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Break this wand");
|
||||
|
||||
/* 'c', 'C' - call an item or its type something */
|
||||
if (item_naming_classification(otmp, buf, buf2)) {
|
||||
if (*buf)
|
||||
ia_addmenu(win, IA_NAME_OBJ, 'c', buf);
|
||||
if (*buf2)
|
||||
ia_addmenu(win, IA_NAME_OTYP, 'C', buf2);
|
||||
}
|
||||
|
||||
/* d: drop item, works on everything except worn items; those will
|
||||
always have a takeoff/remove choice so we don't have to worry
|
||||
about the menu maybe being empty when 'd' is suppressed */
|
||||
if (!already_worn) {
|
||||
Sprintf(buf, "Drop this %s", (otmp->quan > 1L) ? "stack" : "item");
|
||||
ia_addmenu(win, IA_DROP_OBJ, 'd', buf);
|
||||
}
|
||||
|
||||
/* e: eat item */
|
||||
if (otmp->otyp == TIN) {
|
||||
Sprintf(buf, "Open %s%s and eat the contents",
|
||||
(otmp->quan > 1L) ? "one of these tins" : "this tin",
|
||||
(otmp->otyp == TIN && uwep && uwep->otyp == TIN_OPENER)
|
||||
? " with your tin opener" : "");
|
||||
ia_addmenu(win, IA_EAT_OBJ, 'e', buf);
|
||||
} else if (is_edible(otmp)) {
|
||||
Sprintf(buf, "Eat %s", (otmp->quan > 1L) ? "one of these" : "this");
|
||||
ia_addmenu(win, IA_EAT_OBJ, 'e', buf);
|
||||
}
|
||||
|
||||
/* E: engrave with item */
|
||||
if (otmp->otyp == TOWEL) {
|
||||
ia_addmenu(win, IA_ENGRAVE_OBJ, 'E',
|
||||
"Wipe the floor with this towel");
|
||||
} else if (otmp->otyp == MAGIC_MARKER) {
|
||||
ia_addmenu(win, IA_ENGRAVE_OBJ, 'E',
|
||||
"Scribble graffiti on the floor");
|
||||
} else if (otmp->oclass == WEAPON_CLASS || otmp->oclass == WAND_CLASS
|
||||
|| otmp->oclass == GEM_CLASS || otmp->oclass == RING_CLASS) {
|
||||
Sprintf(buf, "%s on the %s with %s",
|
||||
(is_blade(otmp) || otmp->oclass == WAND_CLASS
|
||||
|| ((otmp->oclass == GEM_CLASS || otmp->oclass == RING_CLASS)
|
||||
&& objects[otmp->otyp].oc_tough)) ? "Engrave" : "Write",
|
||||
surface(u.ux, u.uy),
|
||||
(otmp->quan > 1L) ? "one of these items" : "this item");
|
||||
ia_addmenu(win, IA_ENGRAVE_OBJ, 'E', buf);
|
||||
}
|
||||
|
||||
/* f: fire quivered ammo */
|
||||
if (otmp == uquiver) {
|
||||
boolean shoot = ammo_and_launcher(otmp, uwep);
|
||||
|
||||
/* FIXME: see the multi-shot FIXME about "one of" for 't: throw' */
|
||||
Sprintf(buf, "%s %s", shoot ? "Shoot" : "Throw",
|
||||
(otmp->quan > 1L) ? "one of these" : "this");
|
||||
if (shoot) {
|
||||
assert(uwep != NULL);
|
||||
Sprintf(eos(buf), " with your wielded %s", simpleonames(uwep));
|
||||
}
|
||||
ia_addmenu(win, IA_FIRE_OBJ, 'f', buf);
|
||||
}
|
||||
|
||||
/* i: #adjust inventory letter; gold can't be adjusted unless there
|
||||
is some in a slot other than '$' (which shouldn't be possible) */
|
||||
if (otmp->oclass != COIN_CLASS || check_invent_gold("item-action"))
|
||||
ia_addmenu(win, IA_ADJUST_OBJ, 'i',
|
||||
"Adjust inventory by assigning new letter");
|
||||
/* I: #adjust inventory item by splitting its stack */
|
||||
if (otmp->quan > 1L && otmp->oclass != COIN_CLASS)
|
||||
ia_addmenu(win, IA_ADJUST_STACK, 'I',
|
||||
"Adjust inventory by splitting this stack");
|
||||
|
||||
/* O: offer sacrifice */
|
||||
if (IS_ALTAR(levl[u.ux][u.uy].typ) && !u.uswallow) {
|
||||
/* FIXME: this doesn't match #offer's likely candidates, which don't
|
||||
include corpses on Astral and don't include amulets off Astral */
|
||||
if (otmp->otyp == CORPSE)
|
||||
ia_addmenu(win, IA_SACRIFICE, 'O',
|
||||
"Offer this corpse as a sacrifice at this altar");
|
||||
else if (otmp->otyp == AMULET_OF_YENDOR
|
||||
|| otmp->otyp == FAKE_AMULET_OF_YENDOR)
|
||||
ia_addmenu(win, IA_SACRIFICE, 'O',
|
||||
"Offer this amulet as a sacrifice at this altar");
|
||||
}
|
||||
|
||||
/* p: pay for unpaid utems */
|
||||
if (otmp->unpaid
|
||||
/* FIXME: should also handle player owned container (so not
|
||||
flagged 'unpaid') holding shop owned items */
|
||||
&& (mtmp = shop_keeper(*in_rooms(u.ux, u.uy, SHOPBASE))) != 0
|
||||
&& inhishop(mtmp)) {
|
||||
Sprintf(buf, "Buy this unpaid %s",
|
||||
(otmp->quan > 1L) ? "stack" : "item");
|
||||
ia_addmenu(win, IA_BUY_OBJ, 'p', buf);
|
||||
}
|
||||
|
||||
/* P: put on accessory */
|
||||
if (!already_worn) {
|
||||
/* if 'otmp' is worn, we'll skip 'P' and show 'R' below;
|
||||
if not worn, we show 'P - Put on this <simple-item>' if
|
||||
the slot is available, or 'P - <unavailable>'; for the latter,
|
||||
'P' will fail but we don't want to omit the choice because
|
||||
item actions can be used to learn commands */
|
||||
*buf = '\0';
|
||||
if (otmp->oclass == AMULET_CLASS) {
|
||||
Strcpy(buf, !uamul ? "Put this amulet on"
|
||||
: "[already wearing an amulet]");
|
||||
} else if (otmp->oclass == RING_CLASS || otmp->otyp == MEAT_RING) {
|
||||
if (!uleft || !uright)
|
||||
Strcpy(buf, "Put this ring on");
|
||||
else
|
||||
Sprintf(buf, "[both ring %s in use]",
|
||||
makeplural(body_part(FINGER)));
|
||||
} else if (otmp->otyp == BLINDFOLD || otmp->otyp == TOWEL
|
||||
|| otmp->otyp == LENSES) {
|
||||
if (ublindf)
|
||||
Strcpy(buf, "[already wearing eyewear]");
|
||||
else if (otmp->otyp == LENSES)
|
||||
Strcpy(buf, "Put these lenses on");
|
||||
else
|
||||
Sprintf(buf, "Put this on%s",
|
||||
(otmp->otyp == TOWEL) ? " to blindfold yourself" : "");
|
||||
}
|
||||
if (*buf)
|
||||
ia_addmenu(win, IA_WEAR_OBJ, 'P', buf);
|
||||
}
|
||||
|
||||
/* q: drink item */
|
||||
if (otmp->oclass == POTION_CLASS) {
|
||||
Sprintf(buf, "Quaff (drink) %s",
|
||||
(otmp->quan > 1L) ? "one of these potions" : "this potion");
|
||||
ia_addmenu(win, IA_QUAFF_OBJ, 'q', buf);
|
||||
}
|
||||
|
||||
/* Q: quiver throwable item */
|
||||
if ((otmp->oclass == GEM_CLASS || otmp->oclass == WEAPON_CLASS)
|
||||
&& otmp != uquiver) {
|
||||
Sprintf(buf, "Quiver this %s for easy %s with \'f\'ire",
|
||||
(otmp->quan > 1L) ? "stack" : "item",
|
||||
ammo_and_launcher(otmp, uwep) ? "shooting" : "throwing");
|
||||
ia_addmenu(win, IA_QUIVER_OBJ, 'Q', buf);
|
||||
}
|
||||
|
||||
/* r: read item */
|
||||
if (item_reading_classification(otmp, buf) == IA_READ_OBJ)
|
||||
ia_addmenu(win, IA_READ_OBJ, 'r', buf);
|
||||
|
||||
/* R: remove accessory or rub item */
|
||||
if (otmp->owornmask & W_ACCESSORY) {
|
||||
Sprintf(buf, "Remove this %s",
|
||||
(otmp->owornmask & W_AMUL) ? "amulet"
|
||||
: (otmp->owornmask & W_RING) ? "ring"
|
||||
: (otmp->owornmask & W_TOOL) ? "eyewear"
|
||||
: "accessory"); /* catchall -- can't happen */
|
||||
ia_addmenu(win, IA_TAKEOFF_OBJ, 'R', buf);
|
||||
}
|
||||
if (otmp->otyp == OIL_LAMP || otmp->otyp == MAGIC_LAMP
|
||||
|| otmp->otyp == BRASS_LANTERN) {
|
||||
Sprintf(buf, "Rub this %s", simpleonames(otmp));
|
||||
ia_addmenu(win, IA_RUB_OBJ, 'R', buf);
|
||||
} else if (otmp->oclass == GEM_CLASS && is_graystone(otmp))
|
||||
ia_addmenu(win, IA_RUB_OBJ, 'R', "Rub something on this stone");
|
||||
|
||||
/* t: throw item */
|
||||
if (!already_worn) {
|
||||
boolean shoot = ammo_and_launcher(otmp, uwep);
|
||||
|
||||
/*
|
||||
* FIXME:
|
||||
* 'one of these' should be changed to 'some of these' when there
|
||||
* is the possibility of a multi-shot volley but we don't have
|
||||
* any way to determine that except by actually calculating the
|
||||
* volley count and that could randomly yield 1 here and 2..N
|
||||
* while throwing or vice versa.
|
||||
*/
|
||||
Sprintf(buf, "%s %s%s", shoot ? "Shoot" : "Throw",
|
||||
(otmp->quan == 1L) ? "this item"
|
||||
: (otmp->otyp == GOLD_PIECE) ? "them"
|
||||
: "one of these",
|
||||
/* if otmp is quivered, we've already listed
|
||||
'f - shoot|throw this item' as a choice;
|
||||
if 't' is duplicating that, say so ('t' and 'f'
|
||||
behavior differs for throwing a stack of gold) */
|
||||
(otmp == uquiver && (otmp->otyp != GOLD_PIECE
|
||||
|| otmp->quan == 1L))
|
||||
? " (same as 'f')" : "");
|
||||
ia_addmenu(win, IA_THROW_OBJ, 't', buf);
|
||||
}
|
||||
|
||||
/* T: take off armor, tip carried container */
|
||||
if (otmp->owornmask & W_ARMOR)
|
||||
ia_addmenu(win, IA_TAKEOFF_OBJ, 'T', "Take off this armor");
|
||||
if ((Is_container(otmp) && (Has_contents(otmp) || !otmp->cknown))
|
||||
|| (otmp->otyp == HORN_OF_PLENTY && (otmp->spe > 0 || !otmp->known)))
|
||||
ia_addmenu(win, IA_TIP_CONTAINER, 'T',
|
||||
"Tip all the contents out of this container");
|
||||
|
||||
/* V: invoke */
|
||||
if ((otmp->otyp == FAKE_AMULET_OF_YENDOR && !otmp->known)
|
||||
|| otmp->oartifact || objects[otmp->otyp].oc_unique
|
||||
/* non-artifact crystal balls don't have any unique power but
|
||||
the #invoke command lists them as likely candidates */
|
||||
|| otmp->otyp == CRYSTAL_BALL)
|
||||
ia_addmenu(win, IA_INVOKE_OBJ, 'V',
|
||||
"Try to invoke a unique power of this object");
|
||||
|
||||
/* w: wield, hold in hands, works on everything but with different
|
||||
advice text; not mentioned for things that are already wielded */
|
||||
if (otmp == uwep || cantwield(gy.youmonst.data)) {
|
||||
; /* either already wielded or can't wield anything; skip 'w' */
|
||||
} else if (otmp->oclass == WEAPON_CLASS || is_weptool(otmp)
|
||||
|| is_wet_towel(otmp) || otmp->otyp == HEAVY_IRON_BALL) {
|
||||
Sprintf(buf, "Wield this %s as your weapon",
|
||||
(otmp->quan > 1L) ? "stack" : "item");
|
||||
ia_addmenu(win, IA_WIELD_OBJ, 'w', buf);
|
||||
} else if (otmp->otyp == TIN_OPENER) {
|
||||
ia_addmenu(win, IA_WIELD_OBJ, 'w',
|
||||
"Wield the tin opener to easily open tins");
|
||||
} else if (!already_worn) {
|
||||
/* originally this was using "hold this item in your hands" but
|
||||
there's no concept of "holding an item", plus it unwields
|
||||
whatever item you already have wielded so use "wield this item" */
|
||||
Sprintf(buf, "Wield this %s in your %s",
|
||||
(otmp->quan > 1L) ? "stack" : "item",
|
||||
/* only two-handed weapons and unicorn horns care about
|
||||
pluralizing "hand" and they won't reach here, but plural
|
||||
sounds better when poly'd into something with "claw" */
|
||||
makeplural(body_part(HAND)));
|
||||
ia_addmenu(win, IA_WIELD_OBJ, 'w', buf);
|
||||
}
|
||||
|
||||
/* W: wear armor */
|
||||
if (!already_worn) {
|
||||
if (otmp->oclass == ARMOR_CLASS) {
|
||||
/* if 'otmp' is worn we skip 'W' (and show 'T' above instead);
|
||||
if it isn't, we either show "W - wear this" if otmp's slot
|
||||
isn't populated, or "W - [already wearing <simple-armor>]";
|
||||
for the latter, picking 'W' will fail but we don't want to
|
||||
omit 'W' in this situation */
|
||||
long Wmask = armcat_to_wornmask(objects[otmp->otyp].oc_armcat);
|
||||
struct obj *o = wearmask_to_obj(Wmask);
|
||||
|
||||
if (!o)
|
||||
Strcpy(buf, "Wear this armor");
|
||||
else
|
||||
Sprintf(buf, "[already wearing %s]", an(armor_simple_name(o)));
|
||||
|
||||
ia_addmenu(win, IA_WEAR_OBJ, 'W', buf);
|
||||
}
|
||||
}
|
||||
|
||||
/* x: Swap main and readied weapon */
|
||||
if (otmp == uwep && uswapwep)
|
||||
ia_addmenu(win, IA_SWAPWEAPON, 'x',
|
||||
"Swap this with your alternate weapon");
|
||||
else if (otmp == uwep)
|
||||
ia_addmenu(win, IA_SWAPWEAPON, 'x',
|
||||
"Ready this as an alternate weapon");
|
||||
else if (otmp == uswapwep)
|
||||
ia_addmenu(win, IA_SWAPWEAPON, 'x',
|
||||
"Swap this with your main weapon");
|
||||
|
||||
/* this is based on TWOWEAPOK() in wield.c; we don't call can_two_weapon()
|
||||
because it is very verbose; attempting to two-weapon might be rejected
|
||||
but we screen out most reasons for rejection before offering it as a
|
||||
choice */
|
||||
#define MAYBETWOWEAPON(obj) \
|
||||
((((obj)->oclass == WEAPON_CLASS) \
|
||||
? !(is_launcher(obj) || is_ammo(obj) || is_missile(obj)) \
|
||||
: is_weptool(obj)) \
|
||||
&& !bimanual(obj))
|
||||
|
||||
/* X: Toggle two-weapon mode on or off */
|
||||
if ((otmp == uwep || otmp == uswapwep)
|
||||
/* if already two-weaponing, no special checks needed to toggle off */
|
||||
&& (u.twoweap
|
||||
/* but if not, try to filter most "you can't do that" here */
|
||||
|| (could_twoweap(gy.youmonst.data) && !uarms
|
||||
&& uwep && MAYBETWOWEAPON(uwep)
|
||||
&& uswapwep && MAYBETWOWEAPON(uswapwep)))) {
|
||||
Sprintf(buf, "Toggle two-weapon combat %s", u.twoweap ? "off" : "on");
|
||||
ia_addmenu(win, IA_TWOWEAPON, 'X', buf);
|
||||
}
|
||||
|
||||
#undef MAYBETWOWEAPON
|
||||
|
||||
/* z: Zap wand */
|
||||
if (otmp->oclass == WAND_CLASS)
|
||||
ia_addmenu(win, IA_ZAP_OBJ, 'z',
|
||||
"Zap this wand to release its magic");
|
||||
|
||||
/* ?: Look up an item in the game's database */
|
||||
if (ia_checkfile(otmp)) {
|
||||
Sprintf(buf, "Look up information about %s",
|
||||
(otmp->quan > 1L) ? "these" : "this");
|
||||
ia_addmenu(win, IA_WHATIS_OBJ, '/', buf);
|
||||
}
|
||||
|
||||
Sprintf(buf, "Do what with %s?", the(cxname(otmp)));
|
||||
end_menu(win, buf);
|
||||
|
||||
n = select_menu(win, PICK_ONE, &selected);
|
||||
|
||||
if (n > 0) {
|
||||
act = selected[0].item.a_int;
|
||||
free((genericptr_t) selected);
|
||||
|
||||
itemactions_pushkeys(otmp, act);
|
||||
}
|
||||
destroy_nhwindow(win);
|
||||
|
||||
/* finish the 'i' command: no time elapses and cancelling without
|
||||
selecting an action doesn't matter */
|
||||
return ECMD_OK;
|
||||
}
|
||||
|
||||
/*iactions.c*/
|
||||
712
src/invent.c
712
src/invent.c
@@ -5,11 +5,6 @@
|
||||
|
||||
#include "hack.h"
|
||||
|
||||
/* fake inventory letters, not 'a'..'z' or 'A'..'Z' */
|
||||
#define NOINVSYM '#' /* overflow because all 52 letters are in use */
|
||||
#define CONTAINED_SYM '>' /* designator for inside a container */
|
||||
#define HANDS_SYM '-' /* hands|fingers|self depending on context */
|
||||
|
||||
staticfn void inuse_classify(Loot *, struct obj *);
|
||||
staticfn char *loot_xname(struct obj *);
|
||||
staticfn int invletter_value(char);
|
||||
@@ -43,11 +38,6 @@ staticfn int adjust_ok(struct obj *);
|
||||
staticfn int adjust_gold_ok(struct obj *);
|
||||
staticfn int doorganize_core(struct obj *);
|
||||
staticfn char obj_to_let(struct obj *);
|
||||
staticfn boolean item_naming_classification(struct obj *, char *, char *);
|
||||
staticfn int item_reading_classification(struct obj *, char *);
|
||||
staticfn void ia_addmenu(winid, int, char, const char *);
|
||||
staticfn void itemactions_pushkeys(struct obj *, int);
|
||||
staticfn int itemactions(struct obj *);
|
||||
staticfn int dispinv_with_action(char *, boolean, const char *);
|
||||
|
||||
/* enum and structs are defined in wintype.h */
|
||||
@@ -2965,708 +2955,6 @@ xprname(
|
||||
|
||||
RESTORE_WARNING_FORMAT_NONLITERAL
|
||||
|
||||
enum item_action_actions {
|
||||
IA_NONE = 0,
|
||||
IA_UNWIELD, /* hack for 'w-' */
|
||||
IA_APPLY_OBJ, /* 'a' */
|
||||
IA_DIP_OBJ, /* 'a' on a potion == dip */
|
||||
IA_NAME_OBJ, /* 'c' name individual item */
|
||||
IA_NAME_OTYP, /* 'C' name item's type */
|
||||
IA_DROP_OBJ, /* 'd' */
|
||||
IA_EAT_OBJ, /* 'e' */
|
||||
IA_ENGRAVE_OBJ, /* 'E' */
|
||||
IA_FIRE_OBJ, /* 'f' */
|
||||
IA_ADJUST_OBJ, /* 'i' #adjust inventory letter */
|
||||
IA_ADJUST_STACK, /* 'I' #adjust with count to split stack */
|
||||
IA_SACRIFICE, /* 'O' offer sacrifice */
|
||||
IA_BUY_OBJ, /* 'p' pay shopkeeper */
|
||||
IA_QUAFF_OBJ,
|
||||
IA_QUIVER_OBJ,
|
||||
IA_READ_OBJ,
|
||||
IA_RUB_OBJ,
|
||||
IA_THROW_OBJ,
|
||||
IA_TAKEOFF_OBJ,
|
||||
IA_TIP_CONTAINER,
|
||||
IA_INVOKE_OBJ,
|
||||
IA_WIELD_OBJ,
|
||||
IA_WEAR_OBJ,
|
||||
IA_SWAPWEAPON,
|
||||
IA_TWOWEAPON,
|
||||
IA_ZAP_OBJ,
|
||||
IA_WHATIS_OBJ, /* '/' specify inventory object */
|
||||
};
|
||||
|
||||
/* construct text for the menu entries for IA_NAME_OBJ and IA_NAME_OTYP */
|
||||
staticfn boolean
|
||||
item_naming_classification(
|
||||
struct obj *obj,
|
||||
char *onamebuf,
|
||||
char *ocallbuf)
|
||||
{
|
||||
static const char
|
||||
Name[] = "Name",
|
||||
Rename[] = "Rename or un-name",
|
||||
Call[] = "Call",
|
||||
/* "re-call" seems a bit weird, but "recall" and
|
||||
"rename" don't fit for changing a type name */
|
||||
Recall[] = "Re-call or un-call";
|
||||
|
||||
onamebuf[0] = ocallbuf[0] = '\0';
|
||||
if (name_ok(obj) == GETOBJ_SUGGEST) {
|
||||
Sprintf(onamebuf, "%s %s %s",
|
||||
(!has_oname(obj) || !*ONAME(obj)) ? Name : Rename,
|
||||
the_unique_obj(obj) ? "the"
|
||||
: !is_plural(obj) ? "this specific"
|
||||
: "this stack of", /*"these",*/
|
||||
simpleonames(obj));
|
||||
}
|
||||
if (call_ok(obj) == GETOBJ_SUGGEST) {
|
||||
char *callname = simpleonames(obj);
|
||||
|
||||
/* prefix known unique item with "the", make all other types plural */
|
||||
if (the_unique_obj(obj)) /* treats unID'd fake amulets as if real */
|
||||
callname = the(callname);
|
||||
else if (!is_plural(obj))
|
||||
callname = makeplural(callname);
|
||||
Sprintf(ocallbuf, "%s the type for %s",
|
||||
(!objects[obj->otyp].oc_uname
|
||||
|| !*objects[obj->otyp].oc_uname) ? Call : Recall,
|
||||
callname);
|
||||
}
|
||||
return (*onamebuf || *ocallbuf) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
/* construct text for the menu entries for IA_READ_OBJ */
|
||||
staticfn int
|
||||
item_reading_classification(struct obj *obj, char *outbuf)
|
||||
{
|
||||
int otyp = obj->otyp, res = IA_READ_OBJ;
|
||||
|
||||
*outbuf = '\0';
|
||||
if (otyp == FORTUNE_COOKIE) {
|
||||
Strcpy(outbuf, "Read the message inside this cookie");
|
||||
} else if (otyp == T_SHIRT) {
|
||||
Strcpy(outbuf, "Read the slogan on the shirt");
|
||||
} else if (otyp == ALCHEMY_SMOCK) {
|
||||
Strcpy(outbuf, "Read the slogan on the apron");
|
||||
} else if (otyp == HAWAIIAN_SHIRT) {
|
||||
Strcpy(outbuf, "Look at the pattern on the shirt");
|
||||
} else if (obj->oclass == SCROLL_CLASS) {
|
||||
const char *magic = ((obj->dknown
|
||||
#ifdef MAIL_STRUCTURES
|
||||
&& otyp != SCR_MAIL
|
||||
#endif
|
||||
&& (otyp != SCR_BLANK_PAPER
|
||||
|| !objects[otyp].oc_name_known))
|
||||
? " to activate its magic" : "");
|
||||
|
||||
Sprintf(outbuf, "Read this scroll%s", magic);
|
||||
} else if (obj->oclass == SPBOOK_CLASS) {
|
||||
boolean novel = (otyp == SPE_NOVEL),
|
||||
blank = (otyp == SPE_BLANK_PAPER
|
||||
&& objects[otyp].oc_name_known),
|
||||
tome = (otyp == SPE_BOOK_OF_THE_DEAD
|
||||
&& objects[otyp].oc_name_known);
|
||||
|
||||
Sprintf(outbuf, "%s this %s",
|
||||
(novel || blank) ? "Read" : tome ? "Examine" : "Study",
|
||||
novel ? simpleonames(obj) /* "novel" or "paperback book" */
|
||||
: tome ? "tome" : "spellbook");
|
||||
} else {
|
||||
res = IA_NONE;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
staticfn void
|
||||
ia_addmenu(winid win, int act, char let, const char *txt)
|
||||
{
|
||||
anything any;
|
||||
int clr = NO_COLOR;
|
||||
|
||||
any = cg.zeroany;
|
||||
any.a_int = act;
|
||||
add_menu(win, &nul_glyphinfo, &any, let, 0,
|
||||
ATR_NONE, clr, txt, MENU_ITEMFLAGS_NONE);
|
||||
}
|
||||
|
||||
/* set up a command to execute on a specific item next */
|
||||
staticfn void
|
||||
itemactions_pushkeys(struct obj *otmp, int act)
|
||||
{
|
||||
switch (act) {
|
||||
default:
|
||||
impossible("Unknown item action %d", act);
|
||||
break;
|
||||
case IA_NONE:
|
||||
break;
|
||||
case IA_UNWIELD:
|
||||
cmdq_add_ec(CQ_CANNED, (otmp == uwep) ? dowield
|
||||
: (otmp == uswapwep) ? remarm_swapwep
|
||||
: (otmp == uquiver) ? dowieldquiver
|
||||
: donull); /* can't happen */
|
||||
cmdq_add_key(CQ_CANNED, HANDS_SYM);
|
||||
break;
|
||||
case IA_APPLY_OBJ:
|
||||
cmdq_add_ec(CQ_CANNED, doapply);
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_DIP_OBJ:
|
||||
/* #altdip instead of normal #dip - takes potion to dip into
|
||||
first (the inventory item instigating this) and item to
|
||||
be dipped second, also ignores floor features such as
|
||||
fountain/sink so we don't need to force m-prefix here */
|
||||
cmdq_add_ec(CQ_CANNED, dip_into);
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_NAME_OBJ:
|
||||
case IA_NAME_OTYP:
|
||||
cmdq_add_ec(CQ_CANNED, docallcmd);
|
||||
cmdq_add_key(CQ_CANNED, (act == IA_NAME_OBJ) ? 'i' : 'o');
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_DROP_OBJ:
|
||||
cmdq_add_ec(CQ_CANNED, dodrop);
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_EAT_OBJ:
|
||||
/* start with m-prefix; for #eat, it means ignore floor food
|
||||
if present and eat food from invent */
|
||||
cmdq_add_ec(CQ_CANNED, do_reqmenu);
|
||||
cmdq_add_ec(CQ_CANNED, doeat);
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_ENGRAVE_OBJ:
|
||||
cmdq_add_ec(CQ_CANNED, doengrave);
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_FIRE_OBJ:
|
||||
cmdq_add_ec(CQ_CANNED, dofire);
|
||||
break;
|
||||
case IA_ADJUST_OBJ:
|
||||
cmdq_add_ec(CQ_CANNED, doorganize); /* #adjust */
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_ADJUST_STACK:
|
||||
cmdq_add_ec(CQ_CANNED, adjust_split); /* #altadjust */
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_SACRIFICE:
|
||||
cmdq_add_ec(CQ_CANNED, dosacrifice);
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_BUY_OBJ:
|
||||
cmdq_add_ec(CQ_CANNED, dopay);
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_QUAFF_OBJ:
|
||||
/* start with m-prefix; for #quaff, it means ignore fountain
|
||||
or sink if present and drink a potion from invent */
|
||||
cmdq_add_ec(CQ_CANNED, do_reqmenu);
|
||||
cmdq_add_ec(CQ_CANNED, dodrink);
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_QUIVER_OBJ:
|
||||
cmdq_add_ec(CQ_CANNED, dowieldquiver);
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_READ_OBJ:
|
||||
cmdq_add_ec(CQ_CANNED, doread);
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_RUB_OBJ:
|
||||
cmdq_add_ec(CQ_CANNED, dorub);
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_THROW_OBJ:
|
||||
cmdq_add_ec(CQ_CANNED, dothrow);
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_TAKEOFF_OBJ:
|
||||
cmdq_add_ec(CQ_CANNED, ia_dotakeoff); /* #altdotakeoff */
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_TIP_CONTAINER:
|
||||
/* start with m-prefix to skip floor containers;
|
||||
for menustyle:Traditional when more than one floor container
|
||||
is present, player will get a #tip menu and have to pick
|
||||
the "tip something being carried" choice, then this item
|
||||
will be already chosen from inventory; suboptimal but
|
||||
possibly an acceptable tradeoff since combining item actions
|
||||
with use of traditional ggetobj() is an unlikely scenario */
|
||||
cmdq_add_ec(CQ_CANNED, do_reqmenu);
|
||||
cmdq_add_ec(CQ_CANNED, dotip);
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_INVOKE_OBJ:
|
||||
cmdq_add_ec(CQ_CANNED, doinvoke);
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_WIELD_OBJ:
|
||||
cmdq_add_ec(CQ_CANNED, dowield);
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_WEAR_OBJ:
|
||||
cmdq_add_ec(CQ_CANNED, dowear);
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_SWAPWEAPON:
|
||||
cmdq_add_ec(CQ_CANNED, doswapweapon);
|
||||
break;
|
||||
case IA_TWOWEAPON:
|
||||
cmdq_add_ec(CQ_CANNED, dotwoweapon);
|
||||
break;
|
||||
case IA_ZAP_OBJ:
|
||||
cmdq_add_ec(CQ_CANNED, dozap);
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
case IA_WHATIS_OBJ:
|
||||
cmdq_add_ec(CQ_CANNED, dowhatis); /* "/" command */
|
||||
cmdq_add_key(CQ_CANNED, 'i'); /* "i" == item from inventory */
|
||||
cmdq_add_key(CQ_CANNED, otmp->invlet);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Show menu of possible actions hero could do with item otmp */
|
||||
staticfn int
|
||||
itemactions(struct obj *otmp)
|
||||
{
|
||||
int n, act = IA_NONE;
|
||||
winid win;
|
||||
char buf[BUFSZ], buf2[BUFSZ];
|
||||
menu_item *selected;
|
||||
struct monst *mtmp;
|
||||
const char *light = otmp->lamplit ? "Extinguish" : "Light";
|
||||
boolean already_worn = (otmp->owornmask & (W_ARMOR | W_ACCESSORY)) != 0;
|
||||
|
||||
win = create_nhwindow(NHW_MENU);
|
||||
start_menu(win, MENU_BEHAVE_STANDARD);
|
||||
|
||||
/* -: unwield; picking current weapon offers an opportunity for 'w-'
|
||||
to wield bare/gloved hands; likewise for 'Q-' with quivered item(s) */
|
||||
if (otmp == uwep || otmp == uswapwep || otmp == uquiver) {
|
||||
const char *verb = (otmp == uquiver) ? "Quiver" : "Wield",
|
||||
*action = (otmp == uquiver) ? "un-ready" : "un-wield",
|
||||
*which = is_plural(otmp) ? "these" : "this",
|
||||
*what = ((otmp->oclass == WEAPON_CLASS || is_weptool(otmp))
|
||||
? "weapon" : "item");
|
||||
/*
|
||||
* TODO: if uwep is ammo, tell player that to shoot instead of toss,
|
||||
* the corresponding launcher must be wielded;
|
||||
*/
|
||||
Sprintf(buf, "%s '%c' to %s %s %s",
|
||||
verb, HANDS_SYM, action, which,
|
||||
is_plural(otmp) ? makeplural(what) : what);
|
||||
ia_addmenu(win, IA_UNWIELD, '-', buf);
|
||||
}
|
||||
|
||||
/* a: apply */
|
||||
if (otmp->oclass == COIN_CLASS)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Flip a coin");
|
||||
else if (otmp->otyp == CREAM_PIE)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a',
|
||||
"Hit yourself with this cream pie");
|
||||
else if (otmp->otyp == BULLWHIP)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Lash out with this whip");
|
||||
else if (otmp->otyp == GRAPPLING_HOOK)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a',
|
||||
"Grapple something with this hook");
|
||||
else if (otmp->otyp == BAG_OF_TRICKS && objects[otmp->otyp].oc_name_known)
|
||||
/* bag of tricks skips this unless discovered */
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Reach into this bag");
|
||||
else if (Is_container(otmp))
|
||||
/* bag of tricks gets here only if not yet discovered */
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Open this container");
|
||||
else if (otmp->otyp == CAN_OF_GREASE)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Use the can to grease an item");
|
||||
else if (otmp->otyp == LOCK_PICK
|
||||
|| otmp->otyp == CREDIT_CARD
|
||||
|| otmp->otyp == SKELETON_KEY)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Use this tool to pick a lock");
|
||||
else if (otmp->otyp == TINNING_KIT)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Use this kit to tin a corpse");
|
||||
else if (otmp->otyp == LEASH)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Tie a pet to this leash");
|
||||
else if (otmp->otyp == SADDLE)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Place this saddle on a pet");
|
||||
else if (otmp->otyp == MAGIC_WHISTLE
|
||||
|| otmp->otyp == TIN_WHISTLE)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Blow this whistle");
|
||||
else if (otmp->otyp == EUCALYPTUS_LEAF)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Use this leaf as a whistle");
|
||||
else if (otmp->otyp == STETHOSCOPE)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Listen through the stethoscope");
|
||||
else if (otmp->otyp == MIRROR)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Show something its reflection");
|
||||
else if (otmp->otyp == BELL || otmp->otyp == BELL_OF_OPENING)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Ring the bell");
|
||||
else if (otmp->otyp == CANDELABRUM_OF_INVOCATION) {
|
||||
Sprintf(buf, "%s the candelabrum", light);
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', buf);
|
||||
} else if (otmp->otyp == WAX_CANDLE || otmp->otyp == TALLOW_CANDLE) {
|
||||
boolean multiple = (otmp->quan == 1L) ? FALSE : TRUE;
|
||||
const char *s = multiple ? "these" : "this";
|
||||
struct obj *o = carrying(CANDELABRUM_OF_INVOCATION);
|
||||
|
||||
if (o && o->spe < 7)
|
||||
Sprintf(buf, "Attach %s to your candelabrum, or %s %s", s,
|
||||
!otmp->lamplit ? "light" : "extinguish", /* [lowercase] */
|
||||
multiple ? "them" : "it");
|
||||
else
|
||||
Sprintf(buf, "%s %s %s", light, s, simpleonames(otmp));
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', buf);
|
||||
} else if (otmp->otyp == OIL_LAMP || otmp->otyp == MAGIC_LAMP
|
||||
|| otmp->otyp == BRASS_LANTERN) {
|
||||
Sprintf(buf, "%s this light source", light);
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', buf);
|
||||
} else if (otmp->otyp == POT_OIL && objects[otmp->otyp].oc_name_known) {
|
||||
Sprintf(buf, "%s this oil", light);
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', buf);
|
||||
} else if (otmp->oclass == POTION_CLASS) {
|
||||
/* FIXME? this should probably be moved to 'D' rather than be 'a' */
|
||||
Sprintf(buf, "Dip something into %s potion%s",
|
||||
is_plural(otmp) ? "one of these" : "this", plur(otmp->quan));
|
||||
ia_addmenu(win, IA_DIP_OBJ, 'a', buf);
|
||||
} else if (otmp->otyp == EXPENSIVE_CAMERA)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Take a photograph");
|
||||
else if (otmp->otyp == TOWEL)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a',
|
||||
"Clean yourself off with this towel");
|
||||
else if (otmp->otyp == CRYSTAL_BALL)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Peer into this crystal ball");
|
||||
else if (otmp->otyp == MAGIC_MARKER)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a',
|
||||
"Write on something with this marker");
|
||||
else if (otmp->otyp == FIGURINE)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Make this figurine transform");
|
||||
else if (otmp->otyp == UNICORN_HORN)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Use this unicorn horn");
|
||||
else if (otmp->otyp == HORN_OF_PLENTY
|
||||
&& objects[otmp->otyp].oc_name_known)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Blow into the horn of plenty");
|
||||
else if (otmp->otyp >= WOODEN_FLUTE && otmp->otyp <= DRUM_OF_EARTHQUAKE)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Play this musical instrument");
|
||||
else if (otmp->otyp == LAND_MINE || otmp->otyp == BEARTRAP)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Arm this trap");
|
||||
else if (otmp->otyp == PICK_AXE || otmp->otyp == DWARVISH_MATTOCK)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Dig with this digging tool");
|
||||
else if (otmp->oclass == WAND_CLASS)
|
||||
ia_addmenu(win, IA_APPLY_OBJ, 'a', "Break this wand");
|
||||
|
||||
/* 'c', 'C' - call an item or its type something */
|
||||
if (item_naming_classification(otmp, buf, buf2)) {
|
||||
if (*buf)
|
||||
ia_addmenu(win, IA_NAME_OBJ, 'c', buf);
|
||||
if (*buf2)
|
||||
ia_addmenu(win, IA_NAME_OTYP, 'C', buf2);
|
||||
}
|
||||
|
||||
/* d: drop item, works on everything except worn items; those will
|
||||
always have a takeoff/remove choice so we don't have to worry
|
||||
about the menu maybe being empty when 'd' is suppressed */
|
||||
if (!already_worn) {
|
||||
Sprintf(buf, "Drop this %s", (otmp->quan > 1L) ? "stack" : "item");
|
||||
ia_addmenu(win, IA_DROP_OBJ, 'd', buf);
|
||||
}
|
||||
|
||||
/* e: eat item */
|
||||
if (otmp->otyp == TIN) {
|
||||
Sprintf(buf, "Open %s%s and eat the contents",
|
||||
(otmp->quan > 1L) ? "one of these tins" : "this tin",
|
||||
(otmp->otyp == TIN && uwep && uwep->otyp == TIN_OPENER)
|
||||
? " with your tin opener" : "");
|
||||
ia_addmenu(win, IA_EAT_OBJ, 'e', buf);
|
||||
} else if (is_edible(otmp)) {
|
||||
Sprintf(buf, "Eat %s", (otmp->quan > 1L) ? "one of these" : "this");
|
||||
ia_addmenu(win, IA_EAT_OBJ, 'e', buf);
|
||||
}
|
||||
|
||||
/* E: engrave with item */
|
||||
if (otmp->otyp == TOWEL) {
|
||||
ia_addmenu(win, IA_ENGRAVE_OBJ, 'E',
|
||||
"Wipe the floor with this towel");
|
||||
} else if (otmp->otyp == MAGIC_MARKER) {
|
||||
ia_addmenu(win, IA_ENGRAVE_OBJ, 'E',
|
||||
"Scribble graffiti on the floor");
|
||||
} else if (otmp->oclass == WEAPON_CLASS || otmp->oclass == WAND_CLASS
|
||||
|| otmp->oclass == GEM_CLASS || otmp->oclass == RING_CLASS) {
|
||||
Sprintf(buf, "%s on the %s with %s",
|
||||
(is_blade(otmp) || otmp->oclass == WAND_CLASS
|
||||
|| ((otmp->oclass == GEM_CLASS || otmp->oclass == RING_CLASS)
|
||||
&& objects[otmp->otyp].oc_tough)) ? "Engrave" : "Write",
|
||||
surface(u.ux, u.uy),
|
||||
(otmp->quan > 1L) ? "one of these items" : "this item");
|
||||
ia_addmenu(win, IA_ENGRAVE_OBJ, 'E', buf);
|
||||
}
|
||||
|
||||
/* f: fire quivered ammo */
|
||||
if (otmp == uquiver) {
|
||||
boolean shoot = ammo_and_launcher(otmp, uwep);
|
||||
|
||||
/* FIXME: see the multi-shot FIXME about "one of" for 't: throw' */
|
||||
Sprintf(buf, "%s %s", shoot ? "Shoot" : "Throw",
|
||||
(otmp->quan > 1L) ? "one of these" : "this");
|
||||
if (shoot) {
|
||||
assert(uwep != NULL);
|
||||
Sprintf(eos(buf), " with your wielded %s", simpleonames(uwep));
|
||||
}
|
||||
ia_addmenu(win, IA_FIRE_OBJ, 'f', buf);
|
||||
}
|
||||
|
||||
/* i: #adjust inventory letter; gold can't be adjusted unless there
|
||||
is some in a slot other than '$' (which shouldn't be possible) */
|
||||
if (otmp->oclass != COIN_CLASS || check_invent_gold("item-action"))
|
||||
ia_addmenu(win, IA_ADJUST_OBJ, 'i',
|
||||
"Adjust inventory by assigning new letter");
|
||||
/* I: #adjust inventory item by splitting its stack */
|
||||
if (otmp->quan > 1L && otmp->oclass != COIN_CLASS)
|
||||
ia_addmenu(win, IA_ADJUST_STACK, 'I',
|
||||
"Adjust inventory by splitting this stack");
|
||||
|
||||
/* O: offer sacrifice */
|
||||
if (IS_ALTAR(levl[u.ux][u.uy].typ) && !u.uswallow) {
|
||||
/* FIXME: this doesn't match #offer's likely candidates, which don't
|
||||
include corpses on Astral and don't include amulets off Astral */
|
||||
if (otmp->otyp == CORPSE)
|
||||
ia_addmenu(win, IA_SACRIFICE, 'O',
|
||||
"Offer this corpse as a sacrifice at this altar");
|
||||
else if (otmp->otyp == AMULET_OF_YENDOR
|
||||
|| otmp->otyp == FAKE_AMULET_OF_YENDOR)
|
||||
ia_addmenu(win, IA_SACRIFICE, 'O',
|
||||
"Offer this amulet as a sacrifice at this altar");
|
||||
}
|
||||
|
||||
/* p: pay for unpaid utems */
|
||||
if (otmp->unpaid
|
||||
/* FIXME: should also handle player owned container (so not
|
||||
flagged 'unpaid') holding shop owned items */
|
||||
&& (mtmp = shop_keeper(*in_rooms(u.ux, u.uy, SHOPBASE))) != 0
|
||||
&& inhishop(mtmp)) {
|
||||
Sprintf(buf, "Buy this unpaid %s",
|
||||
(otmp->quan > 1L) ? "stack" : "item");
|
||||
ia_addmenu(win, IA_BUY_OBJ, 'p', buf);
|
||||
}
|
||||
|
||||
/* P: put on accessory */
|
||||
if (!already_worn) {
|
||||
/* if 'otmp' is worn, we'll skip 'P' and show 'R' below;
|
||||
if not worn, we show 'P - Put on this <simple-item>' if
|
||||
the slot is available, or 'P - <unavailable>'; for the latter,
|
||||
'P' will fail but we don't want to omit the choice because
|
||||
item actions can be used to learn commands */
|
||||
*buf = '\0';
|
||||
if (otmp->oclass == AMULET_CLASS) {
|
||||
Strcpy(buf, !uamul ? "Put this amulet on"
|
||||
: "[already wearing an amulet]");
|
||||
} else if (otmp->oclass == RING_CLASS || otmp->otyp == MEAT_RING) {
|
||||
if (!uleft || !uright)
|
||||
Strcpy(buf, "Put this ring on");
|
||||
else
|
||||
Sprintf(buf, "[both ring %s in use]",
|
||||
makeplural(body_part(FINGER)));
|
||||
} else if (otmp->otyp == BLINDFOLD || otmp->otyp == TOWEL
|
||||
|| otmp->otyp == LENSES) {
|
||||
if (ublindf)
|
||||
Strcpy(buf, "[already wearing eyewear]");
|
||||
else if (otmp->otyp == LENSES)
|
||||
Strcpy(buf, "Put these lenses on");
|
||||
else
|
||||
Sprintf(buf, "Put this on%s",
|
||||
(otmp->otyp == TOWEL) ? " to blindfold yourself" : "");
|
||||
}
|
||||
if (*buf)
|
||||
ia_addmenu(win, IA_WEAR_OBJ, 'P', buf);
|
||||
}
|
||||
|
||||
/* q: drink item */
|
||||
if (otmp->oclass == POTION_CLASS) {
|
||||
Sprintf(buf, "Quaff (drink) %s",
|
||||
(otmp->quan > 1L) ? "one of these potions" : "this potion");
|
||||
ia_addmenu(win, IA_QUAFF_OBJ, 'q', buf);
|
||||
}
|
||||
|
||||
/* Q: quiver throwable item */
|
||||
if ((otmp->oclass == GEM_CLASS || otmp->oclass == WEAPON_CLASS)
|
||||
&& otmp != uquiver) {
|
||||
Sprintf(buf, "Quiver this %s for easy %s with \'f\'ire",
|
||||
(otmp->quan > 1L) ? "stack" : "item",
|
||||
ammo_and_launcher(otmp, uwep) ? "shooting" : "throwing");
|
||||
ia_addmenu(win, IA_QUIVER_OBJ, 'Q', buf);
|
||||
}
|
||||
|
||||
/* r: read item */
|
||||
if (item_reading_classification(otmp, buf) == IA_READ_OBJ)
|
||||
ia_addmenu(win, IA_READ_OBJ, 'r', buf);
|
||||
|
||||
/* R: remove accessory or rub item */
|
||||
if (otmp->owornmask & W_ACCESSORY) {
|
||||
Sprintf(buf, "Remove this %s",
|
||||
(otmp->owornmask & W_AMUL) ? "amulet"
|
||||
: (otmp->owornmask & W_RING) ? "ring"
|
||||
: (otmp->owornmask & W_TOOL) ? "eyewear"
|
||||
: "accessory"); /* catchall -- can't happen */
|
||||
ia_addmenu(win, IA_TAKEOFF_OBJ, 'R', buf);
|
||||
}
|
||||
if (otmp->otyp == OIL_LAMP || otmp->otyp == MAGIC_LAMP
|
||||
|| otmp->otyp == BRASS_LANTERN) {
|
||||
Sprintf(buf, "Rub this %s", simpleonames(otmp));
|
||||
ia_addmenu(win, IA_RUB_OBJ, 'R', buf);
|
||||
} else if (otmp->oclass == GEM_CLASS && is_graystone(otmp))
|
||||
ia_addmenu(win, IA_RUB_OBJ, 'R', "Rub something on this stone");
|
||||
|
||||
/* t: throw item */
|
||||
if (!already_worn) {
|
||||
boolean shoot = ammo_and_launcher(otmp, uwep);
|
||||
|
||||
/*
|
||||
* FIXME:
|
||||
* 'one of these' should be changed to 'some of these' when there
|
||||
* is the possibility of a multi-shot volley but we don't have
|
||||
* any way to determine that except by actually calculating the
|
||||
* volley count and that could randomly yield 1 here and 2..N
|
||||
* while throwing or vice versa.
|
||||
*/
|
||||
Sprintf(buf, "%s %s%s", shoot ? "Shoot" : "Throw",
|
||||
(otmp->quan == 1L) ? "this item"
|
||||
: (otmp->otyp == GOLD_PIECE) ? "them"
|
||||
: "one of these",
|
||||
/* if otmp is quivered, we've already listed
|
||||
'f - shoot|throw this item' as a choice;
|
||||
if 't' is duplicating that, say so ('t' and 'f'
|
||||
behavior differs for throwing a stack of gold) */
|
||||
(otmp == uquiver && (otmp->otyp != GOLD_PIECE
|
||||
|| otmp->quan == 1L))
|
||||
? " (same as 'f')" : "");
|
||||
ia_addmenu(win, IA_THROW_OBJ, 't', buf);
|
||||
}
|
||||
|
||||
/* T: take off armor, tip carried container */
|
||||
if (otmp->owornmask & W_ARMOR)
|
||||
ia_addmenu(win, IA_TAKEOFF_OBJ, 'T', "Take off this armor");
|
||||
if ((Is_container(otmp) && (Has_contents(otmp) || !otmp->cknown))
|
||||
|| (otmp->otyp == HORN_OF_PLENTY && (otmp->spe > 0 || !otmp->known)))
|
||||
ia_addmenu(win, IA_TIP_CONTAINER, 'T',
|
||||
"Tip all the contents out of this container");
|
||||
|
||||
/* V: invoke */
|
||||
if ((otmp->otyp == FAKE_AMULET_OF_YENDOR && !otmp->known)
|
||||
|| otmp->oartifact || objects[otmp->otyp].oc_unique
|
||||
/* non-artifact crystal balls don't have any unique power but
|
||||
the #invoke command lists them as likely candidates */
|
||||
|| otmp->otyp == CRYSTAL_BALL)
|
||||
ia_addmenu(win, IA_INVOKE_OBJ, 'V',
|
||||
"Try to invoke a unique power of this object");
|
||||
|
||||
/* w: wield, hold in hands, works on everything but with different
|
||||
advice text; not mentioned for things that are already wielded */
|
||||
if (otmp == uwep || cantwield(gy.youmonst.data)) {
|
||||
; /* either already wielded or can't wield anything; skip 'w' */
|
||||
} else if (otmp->oclass == WEAPON_CLASS || is_weptool(otmp)
|
||||
|| is_wet_towel(otmp) || otmp->otyp == HEAVY_IRON_BALL) {
|
||||
Sprintf(buf, "Wield this %s as your weapon",
|
||||
(otmp->quan > 1L) ? "stack" : "item");
|
||||
ia_addmenu(win, IA_WIELD_OBJ, 'w', buf);
|
||||
} else if (otmp->otyp == TIN_OPENER) {
|
||||
ia_addmenu(win, IA_WIELD_OBJ, 'w',
|
||||
"Wield the tin opener to easily open tins");
|
||||
} else if (!already_worn) {
|
||||
/* originally this was using "hold this item in your hands" but
|
||||
there's no concept of "holding an item", plus it unwields
|
||||
whatever item you already have wielded so use "wield this item" */
|
||||
Sprintf(buf, "Wield this %s in your %s",
|
||||
(otmp->quan > 1L) ? "stack" : "item",
|
||||
/* only two-handed weapons and unicorn horns care about
|
||||
pluralizing "hand" and they won't reach here, but plural
|
||||
sounds better when poly'd into something with "claw" */
|
||||
makeplural(body_part(HAND)));
|
||||
ia_addmenu(win, IA_WIELD_OBJ, 'w', buf);
|
||||
}
|
||||
|
||||
/* W: wear armor */
|
||||
if (!already_worn) {
|
||||
if (otmp->oclass == ARMOR_CLASS) {
|
||||
/* if 'otmp' is worn we skip 'W' (and show 'T' above instead);
|
||||
if it isn't, we either show "W - wear this" if otmp's slot
|
||||
isn't populated, or "W - [already wearing <simple-armor>]";
|
||||
for the latter, picking 'W' will fail but we don't want to
|
||||
omit 'W' in this situation */
|
||||
long Wmask = armcat_to_wornmask(objects[otmp->otyp].oc_armcat);
|
||||
struct obj *o = wearmask_to_obj(Wmask);
|
||||
|
||||
if (!o)
|
||||
Strcpy(buf, "Wear this armor");
|
||||
else
|
||||
Sprintf(buf, "[already wearing %s]", an(armor_simple_name(o)));
|
||||
|
||||
ia_addmenu(win, IA_WEAR_OBJ, 'W', buf);
|
||||
}
|
||||
}
|
||||
|
||||
/* x: Swap main and readied weapon */
|
||||
if (otmp == uwep && uswapwep)
|
||||
ia_addmenu(win, IA_SWAPWEAPON, 'x',
|
||||
"Swap this with your alternate weapon");
|
||||
else if (otmp == uwep)
|
||||
ia_addmenu(win, IA_SWAPWEAPON, 'x',
|
||||
"Ready this as an alternate weapon");
|
||||
else if (otmp == uswapwep)
|
||||
ia_addmenu(win, IA_SWAPWEAPON, 'x',
|
||||
"Swap this with your main weapon");
|
||||
|
||||
/* this is based on TWOWEAPOK() in wield.c; we don't call can_two_weapon()
|
||||
because it is very verbose; attempting to two-weapon might be rejected
|
||||
but we screen out most reasons for rejection before offering it as a
|
||||
choice */
|
||||
#define MAYBETWOWEAPON(obj) \
|
||||
((((obj)->oclass == WEAPON_CLASS) \
|
||||
? !(is_launcher(obj) || is_ammo(obj) || is_missile(obj)) \
|
||||
: is_weptool(obj)) \
|
||||
&& !bimanual(obj))
|
||||
|
||||
/* X: Toggle two-weapon mode on or off */
|
||||
if ((otmp == uwep || otmp == uswapwep)
|
||||
/* if already two-weaponing, no special checks needed to toggle off */
|
||||
&& (u.twoweap
|
||||
/* but if not, try to filter most "you can't do that" here */
|
||||
|| (could_twoweap(gy.youmonst.data) && !uarms
|
||||
&& uwep && MAYBETWOWEAPON(uwep)
|
||||
&& uswapwep && MAYBETWOWEAPON(uswapwep)))) {
|
||||
Sprintf(buf, "Toggle two-weapon combat %s", u.twoweap ? "off" : "on");
|
||||
ia_addmenu(win, IA_TWOWEAPON, 'X', buf);
|
||||
}
|
||||
|
||||
#undef MAYBETWOWEAPON
|
||||
|
||||
/* z: Zap wand */
|
||||
if (otmp->oclass == WAND_CLASS)
|
||||
ia_addmenu(win, IA_ZAP_OBJ, 'z',
|
||||
"Zap this wand to release its magic");
|
||||
|
||||
/* ?: Look up an item in the game's database */
|
||||
if (ia_checkfile(otmp)) {
|
||||
Sprintf(buf, "Look up information about %s",
|
||||
(otmp->quan > 1L) ? "these" : "this");
|
||||
ia_addmenu(win, IA_WHATIS_OBJ, '/', buf);
|
||||
}
|
||||
|
||||
Sprintf(buf, "Do what with %s?", the(cxname(otmp)));
|
||||
end_menu(win, buf);
|
||||
|
||||
n = select_menu(win, PICK_ONE, &selected);
|
||||
|
||||
if (n > 0) {
|
||||
act = selected[0].item.a_int;
|
||||
free((genericptr_t) selected);
|
||||
|
||||
itemactions_pushkeys(otmp, act);
|
||||
}
|
||||
destroy_nhwindow(win);
|
||||
|
||||
/* finish the 'i' command: no time elapses and cancelling without
|
||||
selecting an action doesn't matter */
|
||||
return ECMD_OK;
|
||||
}
|
||||
|
||||
/* show some or all of inventory while allowing the picking of an item in
|
||||
order to preform context-sensitive item action on it; always returns 'ok';
|
||||
|
||||
@@ -296,7 +296,7 @@ VOBJ22 = $(O)topl.o $(O)topten.o $(O)trap.o $(O)u_init.o $(O)uhitm.o
|
||||
VOBJ23 = $(O)utf8map.o $(O)vault.o $(O)track.o $(O)vision.o $(O)weapon.o
|
||||
VOBJ24 = $(O)were.o $(O)wield.o $(O)windows.o $(O)wintty.o $(O)wizard.o
|
||||
VOBJ25 = $(O)wizcmds.o $(O)worm.o $(O)worn.o $(O)write.o $(O)zap.o
|
||||
VOBJ26 = $(O)light.o $(O)dlb.o $(REGEX)
|
||||
VOBJ26 = $(O)light.o $(O)dlb.o $(O)iactions.o $(REGEX)
|
||||
|
||||
SOBJ = $(O)msdos.o $(O)pcsys.o $(O)tty.o $(O)unix.o \
|
||||
$(O)video.o $(O)vidtxt.o $(O)pckeys.o
|
||||
@@ -1399,6 +1399,7 @@ $(TARGETPFX)files.o: files.c $(HACK_H) ../include/dlb.h ../include/wintty.h \
|
||||
$(TARGETPFX)fountain.o: fountain.c $(HACK_H)
|
||||
$(TARGETPFX)hack.o: hack.c $(HACK_H)
|
||||
$(TARGETPFX)hacklib.o: hacklib.c $(HACK_H)
|
||||
$(TARGETPFX)iactions.o: iactions.c $(HACK_H)
|
||||
$(TARGETPFX)insight.o: insight.c $(HACK_H)
|
||||
$(TARGETPFX)invent.o: invent.c $(HACK_H)
|
||||
$(TARGETPFX)isaac64.o: isaac64.c $(CONFIG_H) ../include/isaac64.h
|
||||
|
||||
@@ -519,7 +519,7 @@ HACKCSRC = allmain.c alloc.c apply.c artifact.c attrib.c ball.c bones.c \
|
||||
dlb.c do.c do_name.c do_wear.c dog.c dogmove.c dokick.c dothrow.c \
|
||||
drawing.c dungeon.c eat.c end.c engrave.c exper.c explode.c \
|
||||
extralev.c files.c fountain.c hack.c hacklib.c \
|
||||
getpos.c glyphs.c insight.c invent.c isaac64.c light.c \
|
||||
getpos.c glyphs.c iactions.c insight.c invent.c isaac64.c light.c \
|
||||
lock.c mail.c makemon.c mcastu.c mdlib.c mhitm.c \
|
||||
mhitu.c minion.c mklev.c mkmap.c mkmaze.c mkobj.c mkroom.c mon.c \
|
||||
mondata.c monmove.c monst.c mplayer.c mthrowu.c muse.c music.c \
|
||||
@@ -601,6 +601,7 @@ HOBJ = $(TARGETPFX)allmain.o $(TARGETPFX)alloc.o \
|
||||
$(TARGETPFX)engrave.o $(TARGETPFX)exper.o $(TARGETPFX)explode.o \
|
||||
$(TARGETPFX)extralev.o $(TARGETPFX)files.o $(TARGETPFX)fountain.o \
|
||||
$(TARGETPFX)getpos.o $(TARGETPFX)glyphs.o $(TARGETPFX)hack.o \
|
||||
$(TARGETPFX)iactions.o \
|
||||
$(TARGETPFX)insight.o $(TARGETPFX)invent.o $(TARGETPFX)isaac64.o \
|
||||
$(TARGETPFX)light.o $(TARGETPFX)lock.o $(TARGETPFX)mail.o \
|
||||
$(TARGETPFX)makemon.o $(TARGETPFX)mcastu.o $(TARGETPFX)mdlib.o \
|
||||
@@ -1176,6 +1177,7 @@ $(TARGETPFX)getpos.o: getpos.c $(HACK_H)
|
||||
$(TARGETPFX)glyphs.o: glyphs.c $(HACK_H)
|
||||
$(TARGETPFX)hack.o: hack.c $(HACK_H)
|
||||
$(TARGETPFX)hacklib.o: hacklib.c $(HACK_H)
|
||||
$(TARGETPFX)iactions.o: iactions.c $(HACK_H)
|
||||
$(TARGETPFX)insight.o: insight.c $(HACK_H)
|
||||
$(TARGETPFX)invent.o: invent.c $(HACK_H)
|
||||
$(TARGETPFX)isaac64.o: isaac64.c $(CONFIG_H) ../include/isaac64.h
|
||||
|
||||
@@ -151,7 +151,7 @@ HACKCSRC = allmain.c alloc.c apply.c artifact.c attrib.c ball.c bones.c \
|
||||
dig.c display.c dlb.c do.c do_name.c do_wear.c dog.c dogmove.c dokick.c \
|
||||
dothrow.c drawing.c dungeon.c eat.c end.c engrave.c exper.c \
|
||||
explode.c extralev.c files.c fountain.c getpos.c glyphs.c hack.c \
|
||||
hacklib.c insight.c invent.c light.c lock.c \
|
||||
hacklib.c iactions.c insight.c invent.c light.c lock.c \
|
||||
mail.c makemon.c mcastu.c mhitm.c mhitu.c minion.c \
|
||||
mklev.c mkmap.c mkmaze.c mkobj.c mkroom.c mon.c mondata.c \
|
||||
monmove.c monst.c mplayer.c mthrowu.c muse.c music.c o_init.c \
|
||||
@@ -200,7 +200,7 @@ HOBJ1 = allmain.obj,alloc.obj,apply.obj,artifact.obj,attrib.obj, \
|
||||
HOBJ2 = dog.obj,dogmove.obj,dokick.obj,dothrow.obj,drawing.obj, \
|
||||
dungeon.obj,eat.obj,end.obj,engrave.obj,exper.obj,explode.obj, \
|
||||
extralev.obj,files.obj,fountain.obj,getpos.obj,glyphs.obj,hack.obj, \
|
||||
hacklib.obj,insight.obj,invent.obj
|
||||
hacklib.obj,iactions.obj,insight.obj,invent.obj
|
||||
HOBJ3 = light.obj,lock.obj,mail.obj,makemon.obj,mcastu.obj, \
|
||||
mhitm.obj,mhitu.obj,minion.obj,mklev.obj,mkmap.obj,mkmaze.obj, \
|
||||
mkobj.obj,mkroom.obj,mon.obj,mondata.obj,monmove.obj
|
||||
@@ -529,6 +529,7 @@ files.obj : files.c $(HACK_H) $(INC)dlb.h $(INC)wintty.h #zlib.h
|
||||
fountain.obj : fountain.c $(HACK_H)
|
||||
hack.obj : hack.c $(HACK_H)
|
||||
hacklib.obj : hacklib.c $(HACK_H)
|
||||
iactions.obj : iactions.c $(HACK_H)
|
||||
insight.obj : insight.c $(HACK_H)
|
||||
invent.obj : invent.c $(HACK_H)
|
||||
light.obj : light.c $(HACK_H)
|
||||
|
||||
@@ -130,7 +130,7 @@ HACKFILES := allmain alloc apply artifact attrib ball bones botl \
|
||||
sp_lev spell stairs steal steed strutil symbols sys teleport \
|
||||
timeout topten track trap u_init utf8map \
|
||||
uhitm vault version vision weapon were wield \
|
||||
windows wizard wizcmds worm worn write zap
|
||||
windows wizard wizcmds worm worn write zap iactions
|
||||
|
||||
# the date file
|
||||
DATEFILES = date
|
||||
@@ -735,6 +735,7 @@ $(TARGETPFX)getpos.obj: getpos.c $(HACK_H)
|
||||
$(TARGETPFX)glyphs.obj: glyphs.c $(HACK_H)
|
||||
$(TARGETPFX)hack.obj: hack.c $(HACK_H)
|
||||
$(TARGETPFX)hacklib.obj: hacklib.c $(HACK_H)
|
||||
$(TARGETPFX)iactions.obj: iactions.c $(HACK_H)
|
||||
$(TARGETPFX)insight.obj: insight.c $(HACK_H)
|
||||
$(TARGETPFX)invent.obj: invent.c $(HACK_H)
|
||||
$(TARGETPFX)isaac64.obj: isaac64.c $(CONFIG_H) $(INCL)isaac64.h
|
||||
|
||||
@@ -425,7 +425,7 @@ $ c_list = "allmain,apply,artifact,attrib,ball,bones,botl,calendar,cmd" -
|
||||
+ ",do_wear,dog,dogmove,dokick,dungeon,eat,end,engrave,exper,explode" -
|
||||
+ ",extralev,files,fountain,getpos,glyphs"
|
||||
$ gosub compile_list
|
||||
$ c_list = "hack,hacklib,insight,invent,light,lock,mail,makemon" -
|
||||
$ c_list = "hack,hacklib,iactions,insight,invent,light,lock,mail,makemon" -
|
||||
+ ",mcastu,mdlib,mhitm,mhitu,minion,mklev,mkmap,mkmaze" -
|
||||
+ ",mkobj,mkroom,mon,mondata,monmove,mplayer,mthrowu,muse" -
|
||||
+ ",music"
|
||||
|
||||
@@ -1232,7 +1232,7 @@ COREOBJS = $(addsuffix .o, allmain alloc apply artifact attrib ball bones botl \
|
||||
dbridge decl detect dig display dlb do do_name do_wear \
|
||||
dog dogmove dokick dothrow drawing dungeon \
|
||||
eat end engrave exper explode extralev files fountain \
|
||||
getpos glyphs hack insight invent isaac64 light lock \
|
||||
getpos glyphs hack iactions insight invent isaac64 light lock \
|
||||
mail makemon mcastu mdlib mhitm mhitu minion mklev mkmap mkmaze mkobj mkroom \
|
||||
mon mondata monmove monst mplayer mthrowu muse music \
|
||||
nhlobj nhlsel nhlua windsound o_init objects objnam options \
|
||||
|
||||
@@ -659,6 +659,7 @@ HACKCSRC = \
|
||||
$(SRC)drawing.c $(SRC)dungeon.c $(SRC)eat.c $(SRC)end.c \
|
||||
$(SRC)engrave.c $(SRC)exper.c $(SRC)explode.c $(SRC)files.c \
|
||||
$(SRC)fountain.c $(SRC)getpos.c $(SRC)glyphs.c $(SRC)hack.c \
|
||||
$(SRC)iactions.c \
|
||||
$(SRC)insight.c $(SRC)invent.c $(SRC)isaac64.c $(SRC)light.c \
|
||||
$(SRC)lock.c $(SRC)mail.c $(SRC)makemon.c $(SRC)mcastu.c \
|
||||
$(SRC)mdlib.c $(SRC)mhitm.c $(SRC)mhitu.c $(SRC)minion.c \
|
||||
@@ -862,6 +863,7 @@ COREOBJTTY = \
|
||||
$(OTTY)drawing.o $(OTTY)dungeon.o $(OTTY)eat.o $(OTTY)end.o \
|
||||
$(OTTY)engrave.o $(OTTY)exper.o $(OTTY)explode.o $(OTTY)extralev.o \
|
||||
$(OTTY)files.o $(OTTY)fountain.o $(OTTY)getpos.o $(OTTY)glyphs.o \
|
||||
$(OTTY)iactions.o \
|
||||
$(OTTY)hack.o $(OTTY)insight.o $(OTTY)invent.o $(OTTY)isaac64.o \
|
||||
$(OTTY)light.o $(OTTY)lock.o $(OTTY)mail.o $(OTTY)makemon.o \
|
||||
$(OTTY)mcastu.o $(OTTY)mhitm.o $(OTTY)mhitu.o $(OTTY)minion.o \
|
||||
@@ -925,6 +927,7 @@ COREOBJGUI = \
|
||||
$(OGUI)drawing.o $(OGUI)dungeon.o $(OGUI)eat.o $(OGUI)end.o \
|
||||
$(OGUI)engrave.o $(OGUI)exper.o $(OGUI)explode.o $(OGUI)extralev.o \
|
||||
$(OGUI)files.o $(OGUI)fountain.o $(OGUI)getpos.o $(OGUI)glyphs.o \
|
||||
$(OGUI)iactions.o \
|
||||
$(OGUI)hack.o $(OGUI)insight.o $(OGUI)invent.o $(OGUI)isaac64.o \
|
||||
$(OGUI)light.o $(OGUI)lock.o $(OGUI)mail.o $(OGUI)makemon.o \
|
||||
$(OGUI)mcastu.o $(OGUI)mhitm.o $(OGUI)mhitu.o $(OGUI)minion.o \
|
||||
@@ -3257,6 +3260,7 @@ $(OTTY)getpos.o: getpos.c $(HACK_H)
|
||||
$(OTTY)glyphs.o: glyphs.c $(HACK_H)
|
||||
$(OTTY)hack.o: hack.c $(HACK_H)
|
||||
$(OTTY)hacklib.o: hacklib.c $(HACK_H)
|
||||
$(OTTY)iactions.o: iactions.c $(HACK_H)
|
||||
$(OTTY)insight.o: insight.c $(HACK_H)
|
||||
$(OTTY)invent.o: invent.c $(HACK_H)
|
||||
$(OTTY)isaac64.o: isaac64.c $(CONFIG_H) $(INCL)isaac64.h
|
||||
@@ -3636,6 +3640,7 @@ $(OGUI)getpos.o: getpos.c $(HACK_H)
|
||||
$(OGUI)glyphs.o: glyphs.c $(HACK_H)
|
||||
$(OGUI)hack.o: hack.c $(HACK_H)
|
||||
$(OGUI)hacklib.o: hacklib.c $(HACK_H)
|
||||
$(OGUI)iactions.o: iactions.c $(HACK_H)
|
||||
$(OGUI)insight.o: insight.c $(HACK_H)
|
||||
$(OGUI)invent.o: invent.c $(HACK_H)
|
||||
$(OGUI)isaac64.o: isaac64.c $(CONFIG_H) $(INCL)isaac64.h
|
||||
|
||||
@@ -125,6 +125,7 @@
|
||||
<ClCompile Include="$(SrcDir)glyphs.c" />
|
||||
<ClCompile Include="$(SrcDir)hack.c" />
|
||||
<ClCompile Include="$(SrcDir)insight.c" />
|
||||
<ClCompile Include="$(SrcDir)iactions.c" />
|
||||
<ClCompile Include="$(SrcDir)invent.c" />
|
||||
<ClCompile Include="$(SrcDir)isaac64.c" />
|
||||
<ClCompile Include="$(SrcDir)light.c" />
|
||||
|
||||
@@ -146,6 +146,7 @@
|
||||
<ClCompile Include="$(SrcDir)getpos.c" />
|
||||
<ClCompile Include="$(SrcDir)glyphs.c" />
|
||||
<ClCompile Include="$(SrcDir)hack.c" />
|
||||
<ClCompile Include="$(SrcDir)iactions.c" />
|
||||
<ClCompile Include="$(SrcDir)invent.c" />
|
||||
<ClCompile Include="$(SrcDir)insight.c" />
|
||||
<ClCompile Include="$(SrcDir)isaac64.c" />
|
||||
|
||||
Reference in New Issue
Block a user