XP6MR3Q24DQOWNEGMSHJX54ZAISKOIF65IR65M4EOR45KR2OSFVQC AQFXAOOWKVZBMJB6WMW3IUZMX6XERZ6ZSFGNGNKIKWLX4OWOQEYAC JCUAPVDH47W6LG4LU6S4QP6FZJJ2NVXJ6LKFSBMVY3AWMC2PALIAC 3A5FX3Y4RPKWQEHKKXZKXZJ7RKV6RKWT7GTR4WFE5UBWKV2HT4RQC T7CCGLOZ25B7BQKKGR6IA6LWBRKUWTXLTIRXUQ4YKQRVAA7AHZKQC MQ62OAMLGJVRW2QIL4PAZRAU6PC52ZVGY2FCOBIY6IWGQIHMU5CAC CJKLBIIM2ZTWTLGISXEZOGK2JANEYUSLOKG3BBOAYAY7AFG33ELQC XPIE6FG6SYZXNQFBRWUBJ3NR5Q6MOMRXAFW3WTKMSLMKKA55ZWCQC K73AS36BODJSSKMT2LRFDKS7BAMETNFLWHZEPQEZFM6KQB6KRA4AC 754PQVFHYQER7P7NEHYNLQVOEALF6I23IQDNGNCOK5IV7OLAEXRQC UL7XFKMUX3WIU4O2LZANK4ECJ654UZPDBFGNXUEYZYOLKBYBCG6AC QXD3HX6QQ37PW6HVKIIKGFLO2ACROLUGKK66KFX7ED6SO4FDXB2AC Q6UWWYLZTERQ4NOLALOJID5DHSFYGZO3QXG3MWY6JFG7C25BXGAAC K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC B7DNCNY7SXL5WAW5B3XZP5KIQSBWOJ3N2YW46WOUQKTRBRRZ7YOQC XEESII7USBFCL5OZMNZBVJOI66HRL6BT7CQMAPKZNSLM7YUBBQHQC W52PCSHX72WAMWKG6L4BPUBVMO6E72KYYBNKAA7554KNOTY6V7WQC WNC5SY6P2PBCU62Q2DB5J2M4HPDS5EJY76ZEPHRGGCLJ4BSLBSSQC NKONHW4JNY6HP2M63MNPM3H64ZWSUNUT5FX2STW4KTS4AMXJXXVQC Q5YUZONIIPGRWOIQNL6DHRGLKF4V3K5XSZCBH2SL7DP4WPLDNOSQC NVSFIV2ZKP44XHCSCXG6OZVGL67OIFINC34J2EMKTA4KULCERUEAC QNSFZBLVAN7BPYYRXUELHBZCLIQTYDATDIXF3YVH7LBBST66VUCQC SIDH2P7NBIG5KEOE27XHD3ZT2NQ2OJZFN6VZXWNWYFFY5YVXSSVQC 77H4BWWPPGLM3PLZH4QTAJRXIZTSDVNCOKZE223I437FN2UJ34RQC 4GYZYBY7FFORRNPIEFTV4ZM2C7Z6D2KTQOM537ZCC2YBXT2TNSHAC UURAYLSSITZLQR56MCWFPIWMECU7F3USMA2UPJAO4IPIY5WVKP5QC KX23OEQBBLMQHTFCA4TYYEGLHCETXVZCXALYR5U5RELKJMMB66SAC Z42PAEBKCSMEQ5ALBM25HERM3QDIUWMQTQODJOPRVOJAEGIWU3UAC M2HMYLYYXSP5XGX6MCI77IT6UW5K4YSEUJWHPQPYXVSW5L36BJ2AC QUFPPRIIRXHUFEDH3EFES7CSHTA7GG2DAXTRHUAUQBYMSWK4BP6AC J2A4YGNZ64W3UVI3GGUXOHWE3YMZAJNODOMW3REP7KIE6TCMGX7QC 53QXO6XQ6QAKCN6T5ADIKZM6UZCSAOAVKIJBHRN56BUVA653OZFAC CIPVRZGLOZHCERK6YPOBV3P2E4IAB4H6D5EHLRQE2O5E4P4VCBUAC RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC SJP5BHX6MFWF3OSQPEF4WUWZWPUGMOVURTT2CUVT6H3A66LETXUAC 6DNB4AIWKSKXWFY7XYHZMSDBEPGQLMIMU4YB2XTTCLN6ZXWKYOKQC ALHRVZZEWK6YGOVB422CRLBKHV6ANAWMPP2EIWURXLKEWSHPHXCAC SCZCQPNBQG2GXZ76LCEYOMB4QMZGI6YV7LJEC7ZVBUG27KLO564AC DCZMEKDHQWSQCQYQD6ZXB3XOMWLVLPSPVSBVVMPXMSZF7GO3BVCAC QVVC7AYGVA6U64PTNA7L27422NLMO327P22BQKXEVIMPZHIHO7MQC 5KJCHLIUFKRPMIVWUAYT6EOF7SW4PTQF6Y5OPEFWXGLE7DUGYLZAC #include "AppHdr.h"#include <sstream>#include "clua.h"#include "l_libs.h"#include "artefact.h"#include "command.h"#include "initfile.h"#include "invent.h"#include "item_use.h"#include "itemprop.h"#include "items.h"#include "output.h"#include "skills2.h"#include "stuff.h"/////////////////////////////////////////////////////////////////////// User bindings to get information on items. We must be careful// to only hand out information the player already has.//static const item_def *excl_item = NULL;item_def *clua_check_item(lua_State *ls, int n){if (!lua_islightuserdata(ls, n)){luaL_argerror(ls, n, "Unexpected arg type");return (NULL);}item_def *item = static_cast<item_def *>(lua_touserdata(ls, n )); \if (excl_item && item != excl_item){luaL_argerror(ls, n, "Unexpected item");return (NULL);}return (item);}void lua_set_exclusive_item(const item_def *item){excl_item = item;}void lua_push_floor_items(lua_State *ls){lua_push_items(ls, igrd(you.pos()));}void lua_push_inv_items(lua_State *ls = NULL){if (!ls)ls = clua.state();lua_newtable(ls);int index = 0;for (unsigned slot = 0; slot < ENDOFPACK; ++slot){if (is_valid_item(you.inv[slot])){lua_pushlightuserdata(ls, &you.inv[slot]);lua_rawseti(ls, -2, ++index);}}}void lua_push_items(lua_State *ls, int link){lua_newtable(ls);int index = 0;for ( ; link != NON_ITEM; link = mitm[link].link){lua_pushlightuserdata(ls, &mitm[link]);lua_rawseti(ls, -2, ++index);}}static int l_item_inventory(lua_State *ls){lua_push_inv_items(ls);return (1);}static int l_item_index_to_letter(lua_State *ls){int index = luaL_checkint(ls, 1);char sletter[2] = "?";if (index >= 0 && index <= ENDOFPACK)*sletter = index_to_letter(index);lua_pushstring(ls, sletter);return (1);}static int l_item_letter_to_index(lua_State *ls){const char *s = luaL_checkstring(ls, 1);if (!s || !*s || s[1])return (0);lua_pushnumber(ls, letter_to_index(*s));return (1);}static int l_item_swap_slots(lua_State *ls){int slot1 = luaL_checkint(ls, 1),slot2 = luaL_checkint(ls, 2);bool verbose = lua_toboolean(ls, 3);if (slot1 < 0 || slot1 >= ENDOFPACK|| slot2 < 0 || slot2 >= ENDOFPACK|| slot1 == slot2 || !is_valid_item(you.inv[slot1])){return (0);}swap_inv_slots(slot1, slot2, verbose);return (0);}static int l_item_wield(lua_State *ls){if (you.turn_is_over)return (0);LUA_ITEM(item, 1);int slot = -1;if (item && is_valid_item(*item) && in_inventory(*item))slot = item->link;bool res = wield_weapon(true, slot);lua_pushboolean(ls, res);return (1);}static int l_item_wear(lua_State *ls){if (you.turn_is_over)return (0);LUA_ITEM(item, 1);if (!item || !in_inventory(*item))return (0);bool success = do_wear_armour(item->link, false);lua_pushboolean(ls, success);return (1);}static int l_item_puton(lua_State *ls){if (you.turn_is_over)return (0);LUA_ITEM(item, 1);if (!item || !in_inventory(*item))return (0);lua_pushboolean(ls, puton_ring(item->link));return (1);}static int l_item_remove(lua_State *ls){if (you.turn_is_over){mpr("Turn is over");return (0);}LUA_ITEM(item, 1);if (!item || !in_inventory(*item)){mpr("Bad item");return (0);}int eq = get_equip_slot(item);if (eq < 0 || eq >= NUM_EQUIP){mpr("Item is not equipped");return (0);}bool result = false;if (eq == EQ_WEAPON)result = wield_weapon(true, -1);else if (eq == EQ_LEFT_RING || eq == EQ_RIGHT_RING || eq == EQ_AMULET)result = remove_ring(item->link);elseresult = takeoff_armour(item->link);lua_pushboolean(ls, result);return (1);}static int l_item_drop(lua_State *ls){if (you.turn_is_over)return (0);LUA_ITEM(item, 1);if (!item || !in_inventory(*item))return (0);int eq = get_equip_slot(item);if (eq >= 0 && eq < NUM_EQUIP){lua_pushboolean(ls, false);lua_pushstring(ls, "Can't drop worn items");return (2);}int qty = item->quantity;if (lua_isnumber(ls, 2)){int q = luaL_checkint(ls, 2);if (q >= 1 && q <= item->quantity)qty = q;}lua_pushboolean(ls, drop_item(item->link, qty));return (1);}static item_def *dmx_get_item(lua_State *ls, int ndx, int subndx){if (lua_istable(ls, ndx)){lua_rawgeti(ls, ndx, subndx);item_def *item = util_get_userdata<item_def>(ls, -1);lua_pop(ls, 1);return (item);}return util_get_userdata<item_def>(ls, ndx);}static int dmx_get_qty(lua_State *ls, int ndx, int subndx){int qty = -1;if (lua_istable(ls, ndx)){lua_rawgeti(ls, ndx, subndx);if (lua_isnumber(ls, -1))qty = luaL_checkint(ls, -1);lua_pop(ls, 1);}else if (lua_isnumber(ls, ndx)){qty = luaL_checkint(ls, ndx);}return (qty);}static bool l_item_pickup2(item_def *item, int qty){if (!item || in_inventory(*item))return (false);int floor_link = item_on_floor(*item, you.pos());if (floor_link == NON_ITEM)return (false);return pickup_single_item(floor_link, qty);}static int l_item_pickup(lua_State *ls){if (you.turn_is_over)return (0);if (lua_islightuserdata(ls, 1)){LUA_ITEM(item, 1);int qty = item->quantity;if (lua_isnumber(ls, 2))qty = luaL_checkint(ls, 2);if (l_item_pickup2(item, qty))lua_pushnumber(ls, 1);elselua_pushnil(ls);return (1);}else if (lua_istable(ls, 1)){int dropped = 0;for (int i = 1; ; ++i){lua_rawgeti(ls, 1, i);item_def *item = dmx_get_item(ls, -1, 1);int qty = dmx_get_qty(ls, -1, 2);lua_pop(ls, 1);if (l_item_pickup2(item, qty))dropped++;else{// Yes, we bail out on first failure.break;}}if (dropped)lua_pushnumber(ls, dropped);elselua_pushnil(ls);return (1);}return (0);}static int l_item_equipped(lua_State *ls){LUA_ITEM(item, 1);if (!item || !in_inventory(*item))return (0);int eq = get_equip_slot(item);if (eq < 0 || eq >= NUM_EQUIP)return (0);return (1);}// Returns item equipped in a slot defined in an argument.static int l_item_equipped_at(lua_State *ls){int eq = -1;if (lua_isnumber(ls, 1))eq = luaL_checkint(ls, 1);else if (lua_isstring(ls, 1)){const char *eqname = lua_tostring(ls, 1);if (!eqname)return (0);eq = equip_name_to_slot(eqname);}if (eq < 0 || eq >= NUM_EQUIP)return (0);if (you.equip[eq] != -1)lua_pushlightuserdata(ls, &you.inv[you.equip[eq]]);elselua_pushnil(ls);return (1);}static int l_item_class(lua_State *ls){LUA_ITEM(item, 1);if (item){bool terse = false;if (lua_isboolean(ls, 2))terse = lua_toboolean(ls, 2);std::string s = item_class_name(item->base_type, terse);lua_pushstring(ls, s.c_str());}elselua_pushnil(ls);return (1);}// FIXME: Fold this back into itemname.cc.static const char *ring_types[] ={"regeneration","protection","protection from fire","poison resistance","protection from cold","strength","slaying","see invisible","invisibility","hunger","teleportation","evasion","sustain abilities","sustenance","dexterity","intelligence","wizardry","magical power","levitation","life protection","protection from magic","fire","ice","teleport control"};static const char *amulet_types[] ={"rage", "resist slowing", "clarity", "warding", "resist corrosion","gourmand", "conservation", "controlled flight", "inaccuracy","resist mutation"};static int l_item_subtype(lua_State *ls){LUA_ITEM(item, 1);if (item){if (item_type_known(*item)){const char *s = NULL;if (item->base_type == OBJ_JEWELLERY){if (jewellery_is_amulet(*item))s = amulet_types[ item->sub_type - AMU_RAGE ];elses = ring_types[item->sub_type];}else if (item->base_type == OBJ_POTIONS){if (item->sub_type == POT_BLOOD)s = "blood";else if (item->sub_type == POT_BLOOD_COAGULATED)s = "coagulated blood";else if (item->sub_type == POT_WATER)s = "water";else if (item->sub_type == POT_PORRIDGE)s = "porridge";else if (item->sub_type == POT_BERSERK_RAGE)s = "berserk";else if (item->sub_type == POT_GAIN_STRENGTH|| item->sub_type == POT_GAIN_DEXTERITY|| item->sub_type == POT_GAIN_INTELLIGENCE){s = "gain ability";}else if (item->sub_type == POT_CURE_MUTATION)s = "cure mutation";}else if (item->base_type == OBJ_BOOKS){if (item->sub_type == BOOK_MANUAL)s = "manual";elses = "spellbook";}if (s)lua_pushstring(ls, s);elselua_pushnil(ls);lua_pushnumber(ls, item->sub_type);return (2);}}lua_pushnil(ls);lua_pushnil(ls);return (2);}static int l_item_cursed(lua_State *ls){LUA_ITEM(item, 1);bool cursed = item && item_ident(*item, ISFLAG_KNOW_CURSE)&& item_cursed(*item);lua_pushboolean(ls, cursed);return (1);}static int l_item_worn(lua_State *ls){LUA_ITEM(item, 1);int worn = get_equip_slot(item);if (worn != -1)lua_pushnumber(ls, worn);elselua_pushnil(ls);if (worn != -1)lua_pushstring(ls, equip_slot_to_name(worn));elselua_pushnil(ls);return (2);}static std::string _item_name(lua_State *ls, item_def* item){description_level_type ndesc = DESC_PLAIN;if (lua_isstring(ls, 2))ndesc = description_type_by_name(lua_tostring(ls, 2));else if (lua_isnumber(ls, 2))ndesc = static_cast<description_level_type>(luaL_checkint(ls, 2));bool terse = lua_toboolean(ls, 3);return (item->name(ndesc, terse));}static int l_item_name(lua_State *ls){LUA_ITEM(item, 1);if (item){std::string name = _item_name(ls, item);lua_pushstring(ls, name.c_str());}elselua_pushnil(ls);return (1);}static int l_item_name_coloured(lua_State *ls){LUA_ITEM(item, 1);if (item){std::string name = _item_name(ls, item);int col = menu_colour(name, menu_colour_item_prefix(*item));std::string colstr = colour_to_str(col);std::ostringstream out;out << "<" << colstr << ">" << name << "</" << colstr << ">";lua_pushstring(ls, out.str().c_str());}elselua_pushnil(ls);return (1);}static int l_item_quantity(lua_State *ls){LUA_ITEM(item, 1);lua_pushnumber(ls, item? item->quantity : 0);return (1);}static int l_item_inslot(lua_State *ls){int index = luaL_checkint(ls, 1);if (index >= 0 && index < 52 && is_valid_item(you.inv[index]))lua_pushlightuserdata(ls, &you.inv[index]);elselua_pushnil(ls);return (1);}static int l_item_slot(lua_State *ls){LUA_ITEM(item, 1);if (item){int slot = in_inventory(*item) ? item->link: letter_to_index(item->slot);lua_pushnumber(ls, slot);}elselua_pushnil(ls);return (1);}static int l_item_ininventory(lua_State *ls){LUA_ITEM(item, 1);lua_pushboolean(ls, item && in_inventory(*item));return (1);}static int l_item_equip_type(lua_State *ls){LUA_ITEM(item, 1);if (!item || !is_valid_item(*item))return (0);equipment_type eq = EQ_NONE;if (item->base_type == OBJ_WEAPONS || item->base_type == OBJ_STAVES)eq = EQ_WEAPON;else if (item->base_type == OBJ_ARMOUR)eq = get_armour_slot(*item);else if (item->base_type == OBJ_JEWELLERY)eq = item->sub_type >= AMU_RAGE? EQ_AMULET : EQ_RINGS;if (eq != EQ_NONE){lua_pushnumber(ls, eq);lua_pushstring(ls, equip_slot_to_name(eq));}else{lua_pushnil(ls);lua_pushnil(ls);}return (2);}static int l_item_weap_skill(lua_State *ls){LUA_ITEM(item, 1);if (!item || !is_valid_item(*item))return (0);int skill = range_skill(*item);if (skill == SK_THROWING)skill = weapon_skill(*item);if (skill == SK_FIGHTING)return (0);lua_pushstring(ls, skill_name(skill));lua_pushnumber(ls, skill);return (2);}static int l_item_dropped(lua_State *ls){LUA_ITEM(item, 1);if (!item || !is_valid_item(*item))return (0);lua_pushboolean(ls, item->flags & ISFLAG_DROPPED);return (1);}static int l_item_can_cut_meat(lua_State *ls){LUA_ITEM(item, 1);if (!item || !is_valid_item(*item))return (0);lua_pushboolean(ls, can_cut_meat(*item));return (1);}static int l_item_artefact(lua_State *ls){LUA_ITEM(item, 1);if (!item || !is_valid_item(*item))return (0);lua_pushboolean(ls, item_ident(*item, ISFLAG_KNOW_PROPERTIES)&& is_artefact(*item));return (1);}static int l_item_branded(lua_State *ls){LUA_ITEM(item, 1);if (!item || !is_valid_item(*item) || !item_type_known(*item))return (0);bool branded = false;switch (item->base_type){case OBJ_WEAPONS:branded = get_weapon_brand(*item) != SPWPN_NORMAL;break;case OBJ_ARMOUR:branded = get_armour_ego_type(*item) != SPARM_NORMAL;break;case OBJ_MISSILES:branded = get_ammo_brand(*item) != SPMSL_NORMAL;break;default:break;}lua_pushboolean(ls, branded);return (1);}static const struct luaL_reg item_lib[] ={{ "artefact", l_item_artefact },{ "branded", l_item_branded },{ "class", l_item_class },{ "subtype", l_item_subtype },{ "cursed", l_item_cursed },{ "worn", l_item_worn },{ "name", l_item_name },{ "name_coloured", l_item_name_coloured },{ "quantity", l_item_quantity },{ "inslot", l_item_inslot },{ "slot", l_item_slot },{ "ininventory", l_item_ininventory },{ "inventory", l_item_inventory },{ "letter_to_index", l_item_letter_to_index },{ "index_to_letter", l_item_index_to_letter },{ "swap_slots", l_item_swap_slots },{ "wield", l_item_wield },{ "wear", l_item_wear },{ "puton", l_item_puton },{ "remove", l_item_remove },{ "drop", l_item_drop },{ "pickup", l_item_pickup },{ "equipped_at", l_item_equipped_at },{ "equipped", l_item_equipped },{ "equip_type", l_item_equip_type },{ "weap_skill", l_item_weap_skill },{ "dropped", l_item_dropped },{ "can_cut_meat", l_item_can_cut_meat },{ NULL, NULL },};void cluaopen_item(lua_State *ls){luaL_openlib(ls, "item", item_lib, 0);}
void lua_push_inv_items(lua_State *ls = NULL){if (!ls)ls = clua.state();lua_newtable(ls);int index = 0;for (unsigned slot = 0; slot < ENDOFPACK; ++slot){if (is_valid_item(you.inv[slot])){lua_pushlightuserdata(ls, &you.inv[slot]);lua_rawseti(ls, -2, ++index);}}}
// Bindings to get information on items. We must be extremely careful// to only hand out information the player already has.//static const item_def *excl_item = NULL;#define LUA_ITEM(name, n) \if (!lua_islightuserdata(ls, n)) \{ \luaL_argerror(ls, n, "Unexpected arg type"); \return (0); \} \\item_def *name = static_cast<item_def *>( lua_touserdata(ls, n ) ); \if (excl_item && name != excl_item) \{ \luaL_argerror(ls, n, "Unexpected item"); \return (0); \}void lua_push_inv_items(lua_State *ls);void lua_set_exclusive_item(const item_def *item){excl_item = item;}void lua_push_items(lua_State *ls, int link){lua_newtable(ls);int index = 0;for ( ; link != NON_ITEM; link = mitm[link].link){lua_pushlightuserdata(ls, &mitm[link]);lua_rawseti(ls, -2, ++index);}}static int l_item_inventory(lua_State *ls){lua_push_inv_items(ls);return (1);}static int l_item_index_to_letter(lua_State *ls){int index = luaL_checkint(ls, 1);char sletter[2] = "?";if (index >= 0 && index <= ENDOFPACK)*sletter = index_to_letter(index);lua_pushstring(ls, sletter);return (1);}static int l_item_letter_to_index(lua_State *ls){const char *s = luaL_checkstring(ls, 1);if (!s || !*s || s[1])return (0);lua_pushnumber(ls, letter_to_index(*s));return (1);}static int l_item_swap_slots(lua_State *ls){int slot1 = luaL_checkint(ls, 1),slot2 = luaL_checkint(ls, 2);bool verbose = lua_toboolean(ls, 3);if (slot1 < 0 || slot1 >= ENDOFPACK|| slot2 < 0 || slot2 >= ENDOFPACK|| slot1 == slot2 || !is_valid_item(you.inv[slot1])){return (0);}swap_inv_slots(slot1, slot2, verbose);return (0);}static int l_item_wield(lua_State *ls){if (you.turn_is_over)return (0);LUA_ITEM(item, 1);int slot = -1;if (item && is_valid_item(*item) && in_inventory(*item))slot = item->link;bool res = wield_weapon(true, slot);lua_pushboolean(ls, res);return (1);}static int l_item_wear(lua_State *ls){if (you.turn_is_over)return (0);LUA_ITEM(item, 1);if (!item || !in_inventory(*item))return (0);bool success = do_wear_armour(item->link, false);lua_pushboolean(ls, success);return (1);}static int l_item_puton(lua_State *ls){if (you.turn_is_over)return (0);LUA_ITEM(item, 1);if (!item || !in_inventory(*item))return (0);lua_pushboolean(ls, puton_ring(item->link));return (1);}static int l_item_remove(lua_State *ls){if (you.turn_is_over){mpr("Turn is over");return (0);}LUA_ITEM(item, 1);if (!item || !in_inventory(*item)){mpr("Bad item");return (0);}int eq = get_equip_slot(item);if (eq < 0 || eq >= NUM_EQUIP){mpr("Item is not equipped");return (0);}bool result = false;if (eq == EQ_WEAPON)result = wield_weapon(true, -1);else if (eq == EQ_LEFT_RING || eq == EQ_RIGHT_RING || eq == EQ_AMULET)result = remove_ring(item->link);elseresult = takeoff_armour(item->link);lua_pushboolean(ls, result);return (1);}static int l_item_drop(lua_State *ls){if (you.turn_is_over)return (0);LUA_ITEM(item, 1);if (!item || !in_inventory(*item))return (0);int eq = get_equip_slot(item);if (eq >= 0 && eq < NUM_EQUIP){lua_pushboolean(ls, false);lua_pushstring(ls, "Can't drop worn items");return (2);}int qty = item->quantity;if (lua_isnumber(ls, 2)){int q = luaL_checkint(ls, 2);if (q >= 1 && q <= item->quantity)qty = q;}lua_pushboolean(ls, drop_item(item->link, qty));return (1);}static item_def *dmx_get_item(lua_State *ls, int ndx, int subndx){if (lua_istable(ls, ndx)){lua_rawgeti(ls, ndx, subndx);item_def *item = util_get_userdata<item_def>(ls, -1);lua_pop(ls, 1);return (item);}return util_get_userdata<item_def>(ls, ndx);}static int dmx_get_qty(lua_State *ls, int ndx, int subndx){int qty = -1;if (lua_istable(ls, ndx)){lua_rawgeti(ls, ndx, subndx);if (lua_isnumber(ls, -1))qty = luaL_checkint(ls, -1);lua_pop(ls, 1);}else if (lua_isnumber(ls, ndx)){qty = luaL_checkint(ls, ndx);}return (qty);}static bool l_item_pickup2(item_def *item, int qty){if (!item || in_inventory(*item))return (false);int floor_link = item_on_floor(*item, you.pos());if (floor_link == NON_ITEM)return (false);return pickup_single_item(floor_link, qty);}static int l_item_pickup(lua_State *ls){if (you.turn_is_over)return (0);if (lua_islightuserdata(ls, 1)){LUA_ITEM(item, 1);int qty = item->quantity;if (lua_isnumber(ls, 2))qty = luaL_checkint(ls, 2);if (l_item_pickup2(item, qty))lua_pushnumber(ls, 1);elselua_pushnil(ls);return (1);}else if (lua_istable(ls, 1)){int dropped = 0;for (int i = 1; ; ++i){lua_rawgeti(ls, 1, i);item_def *item = dmx_get_item(ls, -1, 1);int qty = dmx_get_qty(ls, -1, 2);lua_pop(ls, 1);if (l_item_pickup2(item, qty))dropped++;else{// Yes, we bail out on first failure.break;}}if (dropped)lua_pushnumber(ls, dropped);elselua_pushnil(ls);return (1);}return (0);}static int l_item_equipped(lua_State *ls){LUA_ITEM(item, 1);if (!item || !in_inventory(*item))return (0);int eq = get_equip_slot(item);if (eq < 0 || eq >= NUM_EQUIP)return (0);return (1);}// Returns item equipped in a slot defined in an argument.static int l_item_equipped_at(lua_State *ls){int eq = -1;if (lua_isnumber(ls, 1))eq = luaL_checkint(ls, 1);else if (lua_isstring(ls, 1)){const char *eqname = lua_tostring(ls, 1);if (!eqname)return (0);eq = equip_name_to_slot(eqname);}if (eq < 0 || eq >= NUM_EQUIP)return (0);if (you.equip[eq] != -1)lua_pushlightuserdata(ls, &you.inv[you.equip[eq]]);elselua_pushnil(ls);return (1);}static int l_item_class(lua_State *ls){LUA_ITEM(item, 1);if (item){bool terse = false;if (lua_isboolean(ls, 2))terse = lua_toboolean(ls, 2);std::string s = item_class_name(item->base_type, terse);lua_pushstring(ls, s.c_str());}elselua_pushnil(ls);return (1);}// FIXME: Fold this back into itemname.cc.static const char *ring_types[] ={"regeneration","protection","protection from fire","poison resistance","protection from cold","strength","slaying","see invisible","invisibility","hunger","teleportation","evasion","sustain abilities","sustenance","dexterity","intelligence","wizardry","magical power","levitation","life protection","protection from magic","fire","ice","teleport control"};static const char *amulet_types[] ={"rage", "resist slowing", "clarity", "warding", "resist corrosion","gourmand", "conservation", "controlled flight", "inaccuracy","resist mutation"};static int l_item_subtype(lua_State *ls){LUA_ITEM(item, 1);if (item){if (item_type_known(*item)){const char *s = NULL;if (item->base_type == OBJ_JEWELLERY){if (jewellery_is_amulet(*item))s = amulet_types[ item->sub_type - AMU_RAGE ];elses = ring_types[item->sub_type];}else if (item->base_type == OBJ_POTIONS){if (item->sub_type == POT_BLOOD)s = "blood";else if (item->sub_type == POT_BLOOD_COAGULATED)s = "coagulated blood";else if (item->sub_type == POT_WATER)s = "water";else if (item->sub_type == POT_PORRIDGE)s = "porridge";else if (item->sub_type == POT_BERSERK_RAGE)s = "berserk";else if (item->sub_type == POT_GAIN_STRENGTH|| item->sub_type == POT_GAIN_DEXTERITY|| item->sub_type == POT_GAIN_INTELLIGENCE){s = "gain ability";}else if (item->sub_type == POT_CURE_MUTATION)s = "cure mutation";}else if (item->base_type == OBJ_BOOKS){if (item->sub_type == BOOK_MANUAL)s = "manual";elses = "spellbook";}if (s)lua_pushstring(ls, s);elselua_pushnil(ls);lua_pushnumber(ls, item->sub_type);return (2);}}lua_pushnil(ls);lua_pushnil(ls);return (2);}static int l_item_cursed(lua_State *ls){LUA_ITEM(item, 1);bool cursed = item && item_ident(*item, ISFLAG_KNOW_CURSE)&& item_cursed(*item);lua_pushboolean(ls, cursed);return (1);}static int l_item_worn(lua_State *ls){LUA_ITEM(item, 1);int worn = get_equip_slot(item);if (worn != -1)lua_pushnumber(ls, worn);elselua_pushnil(ls);if (worn != -1)lua_pushstring(ls, equip_slot_to_name(worn));elselua_pushnil(ls);return (2);}static std::string _item_name(lua_State *ls, item_def* item){description_level_type ndesc = DESC_PLAIN;if (lua_isstring(ls, 2))ndesc = description_type_by_name(lua_tostring(ls, 2));else if (lua_isnumber(ls, 2))ndesc = static_cast<description_level_type>(luaL_checkint(ls, 2));bool terse = lua_toboolean(ls, 3);return (item->name(ndesc, terse));}static int l_item_name(lua_State *ls){LUA_ITEM(item, 1);if (item){std::string name = _item_name(ls, item);lua_pushstring(ls, name.c_str());}elselua_pushnil(ls);return (1);}static int l_item_name_coloured(lua_State *ls){LUA_ITEM(item, 1);if (item){std::string name = _item_name(ls, item);int col = menu_colour(name, menu_colour_item_prefix(*item));std::string colstr = colour_to_str(col);std::ostringstream out;out << "<" << colstr << ">" << name << "</" << colstr << ">";lua_pushstring(ls, out.str().c_str());}elselua_pushnil(ls);return (1);}static int l_item_quantity(lua_State *ls){LUA_ITEM(item, 1);lua_pushnumber(ls, item? item->quantity : 0);return (1);}static int l_item_inslot(lua_State *ls){int index = luaL_checkint(ls, 1);if (index >= 0 && index < 52 && is_valid_item(you.inv[index]))lua_pushlightuserdata(ls, &you.inv[index]);elselua_pushnil(ls);return (1);}static int l_item_slot(lua_State *ls){LUA_ITEM(item, 1);if (item){int slot = in_inventory(*item) ? item->link: letter_to_index(item->slot);lua_pushnumber(ls, slot);}elselua_pushnil(ls);return (1);}static int l_item_ininventory(lua_State *ls){LUA_ITEM(item, 1);lua_pushboolean(ls, item && in_inventory(*item));return (1);}static int l_item_equip_type(lua_State *ls){LUA_ITEM(item, 1);if (!item || !is_valid_item(*item))return (0);equipment_type eq = EQ_NONE;if (item->base_type == OBJ_WEAPONS || item->base_type == OBJ_STAVES)eq = EQ_WEAPON;else if (item->base_type == OBJ_ARMOUR)eq = get_armour_slot(*item);else if (item->base_type == OBJ_JEWELLERY)eq = item->sub_type >= AMU_RAGE? EQ_AMULET : EQ_RINGS;if (eq != EQ_NONE){lua_pushnumber(ls, eq);lua_pushstring(ls, equip_slot_to_name(eq));}else{lua_pushnil(ls);lua_pushnil(ls);}return (2);}static int l_item_weap_skill(lua_State *ls){LUA_ITEM(item, 1);if (!item || !is_valid_item(*item))return (0);int skill = range_skill(*item);if (skill == SK_THROWING)skill = weapon_skill(*item);if (skill == SK_FIGHTING)return (0);lua_pushstring(ls, skill_name(skill));lua_pushnumber(ls, skill);return (2);}static int l_item_dropped(lua_State *ls){LUA_ITEM(item, 1);if (!item || !is_valid_item(*item))return (0);lua_pushboolean(ls, item->flags & ISFLAG_DROPPED);return (1);}static int l_item_can_cut_meat(lua_State *ls){LUA_ITEM(item, 1);if (!item || !is_valid_item(*item))return (0);lua_pushboolean(ls, can_cut_meat(*item));return (1);}static int l_item_artefact(lua_State *ls){LUA_ITEM(item, 1);if (!item || !is_valid_item(*item))return (0);lua_pushboolean(ls, item_ident(*item, ISFLAG_KNOW_PROPERTIES)&& is_artefact(*item));return (1);}static int l_item_branded(lua_State *ls){LUA_ITEM(item, 1);if (!item || !is_valid_item(*item) || !item_type_known(*item))return (0);bool branded = false;switch (item->base_type){case OBJ_WEAPONS:branded = get_weapon_brand(*item) != SPWPN_NORMAL;break;case OBJ_ARMOUR:branded = get_armour_ego_type(*item) != SPARM_NORMAL;break;case OBJ_MISSILES:branded = get_ammo_brand(*item) != SPMSL_NORMAL;break;default:break;}lua_pushboolean(ls, branded);return (1);}static const struct luaL_reg item_lib[] ={{ "artefact", l_item_artefact },{ "branded", l_item_branded },{ "class", l_item_class },{ "subtype", l_item_subtype },{ "cursed", l_item_cursed },{ "worn", l_item_worn },{ "name", l_item_name },{ "name_coloured", l_item_name_coloured },{ "quantity", l_item_quantity },{ "inslot", l_item_inslot },{ "slot", l_item_slot },{ "ininventory", l_item_ininventory },{ "inventory", l_item_inventory },{ "letter_to_index", l_item_letter_to_index },{ "index_to_letter", l_item_index_to_letter },{ "swap_slots", l_item_swap_slots },{ "wield", l_item_wield },{ "wear", l_item_wear },{ "puton", l_item_puton },{ "remove", l_item_remove },{ "drop", l_item_drop },{ "pickup", l_item_pickup },{ "equipped_at", l_item_equipped_at },{ "equipped", l_item_equipped },{ "equip_type", l_item_equip_type },{ "weap_skill", l_item_weap_skill },{ "dropped", l_item_dropped },{ "can_cut_meat", l_item_can_cut_meat },{ NULL, NULL },};void luaopen_item(lua_State *ls){luaL_openlib(ls, "item", item_lib, 0);}/////////////////////////////////////////////////////////////////////