summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source
diff options
context:
space:
mode:
authorRobert Vollmert <rvollmert@gmx.net>2009-10-20 22:01:09 +0200
committerRobert Vollmert <rvollmert@gmx.net>2009-10-20 22:01:09 +0200
commit52818f7c83ffb5143f798412ee8d4800fc9de7b7 (patch)
tree09616a695880f42bcfe2bb56ba614fa30c288796 /crawl-ref/source
parent30beda4d0f59aa37ee9d33c67d52aba686d53978 (diff)
downloadcrawl-ref-52818f7c83ffb5143f798412ee8d4800fc9de7b7.tar.gz
crawl-ref-52818f7c83ffb5143f798412ee8d4800fc9de7b7.zip
Move library "item" from clua.cc to l_item.cc.
Diffstat (limited to 'crawl-ref/source')
-rw-r--r--crawl-ref/source/clua.cc671
-rw-r--r--crawl-ref/source/food.cc21
-rw-r--r--crawl-ref/source/l_item.cc706
-rw-r--r--crawl-ref/source/l_libs.h5
-rw-r--r--crawl-ref/source/makefile.obj1
5 files changed, 713 insertions, 691 deletions
diff --git a/crawl-ref/source/clua.cc b/crawl-ref/source/clua.cc
index 92212e37e6..e05a378af4 100644
--- a/crawl-ref/source/clua.cc
+++ b/crawl-ref/source/clua.cc
@@ -591,7 +591,6 @@ bool CLua::callfn(const char *fn, int nargs, int nret)
// structs
extern void luaopen_kills(lua_State *ls);
-void luaopen_item(lua_State *ls);
void luaopen_food(lua_State *ls);
void luaopen_file(lua_State *ls);
void luaopen_globals(lua_State *ls);
@@ -617,7 +616,7 @@ void CLua::init_lua()
// Open Crawl bindings
luaopen_kills(_state);
cluaopen_you(_state);
- luaopen_item(_state);
+ cluaopen_item(_state);
luaopen_food(_state);
cluaopen_crawl(_state);
luaopen_file(_state);
@@ -723,674 +722,6 @@ void clua_register_metatable(lua_State *ls, const char *tn,
}
/////////////////////////////////////////////////////////////////////
-// 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);
- else
- result = 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);
- else
- lua_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);
- else
- lua_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]]);
- else
- lua_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());
- }
- else
- lua_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 ];
- else
- s = 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";
- else
- s = "spellbook";
- }
-
- if (s)
- lua_pushstring(ls, s);
- else
- lua_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);
- else
- lua_pushnil(ls);
- if (worn != -1)
- lua_pushstring(ls, equip_slot_to_name(worn));
- else
- lua_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());
- }
- else
- lua_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());
- }
- else
- lua_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]);
- else
- lua_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);
- }
- else
- lua_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);
-}
-
-/////////////////////////////////////////////////////////////////////
// Food information.
static int food_do_eat(lua_State *ls)
diff --git a/crawl-ref/source/food.cc b/crawl-ref/source/food.cc
index 21895531b8..b921a1d861 100644
--- a/crawl-ref/source/food.cc
+++ b/crawl-ref/source/food.cc
@@ -730,27 +730,6 @@ bool butchery(int which_corpse)
return (success);
}
-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);
- }
- }
-}
-
bool prompt_eat_inventory_item(int slot)
{
if (inv_count() < 1)
diff --git a/crawl-ref/source/l_item.cc b/crawl-ref/source/l_item.cc
new file mode 100644
index 0000000000..913f719782
--- /dev/null
+++ b/crawl-ref/source/l_item.cc
@@ -0,0 +1,706 @@
+#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);
+ else
+ result = 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);
+ else
+ lua_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);
+ else
+ lua_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]]);
+ else
+ lua_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());
+ }
+ else
+ lua_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 ];
+ else
+ s = 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";
+ else
+ s = "spellbook";
+ }
+
+ if (s)
+ lua_pushstring(ls, s);
+ else
+ lua_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);
+ else
+ lua_pushnil(ls);
+ if (worn != -1)
+ lua_pushstring(ls, equip_slot_to_name(worn));
+ else
+ lua_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());
+ }
+ else
+ lua_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());
+ }
+ else
+ lua_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]);
+ else
+ lua_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);
+ }
+ else
+ lua_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);
+}
diff --git a/crawl-ref/source/l_libs.h b/crawl-ref/source/l_libs.h
index 178f1f5201..e54480317d 100644
--- a/crawl-ref/source/l_libs.h
+++ b/crawl-ref/source/l_libs.h
@@ -13,6 +13,7 @@
*/
void cluaopen_crawl(lua_State *ls);
+void cluaopen_item(lua_State *ls);
void cluaopen_monsters(lua_State *ls);
void cluaopen_options(lua_State *ls);
void cluaopen_you(lua_State *ls);
@@ -67,6 +68,9 @@ void dluaopen_you(lua_State *ls);
#define FEAT(f, pos) \
dungeon_feature_type f = check_lua_feature(ls, pos)
+#define LUA_ITEM(name, n) \
+ item_def *name = clua_check_item(ls, n);
+
#define LEVEL(lev, br, pos) \
const char *level_name = luaL_checkstring(ls, pos); \
level_area_type lev = str_to_level_area_type(level_name); \
@@ -94,5 +98,6 @@ int dgn_map_add_transform(lua_State *ls,
unsigned int get_tile_idx(lua_State *ls, int arg);
level_id dlua_level_id(lua_State *ls, int ndx);
dungeon_feature_type check_lua_feature(lua_State *ls, int idx);
+item_def *clua_check_item(lua_State *ls, int n);
#endif
diff --git a/crawl-ref/source/makefile.obj b/crawl-ref/source/makefile.obj
index ff593408c8..48e47ef222 100644
--- a/crawl-ref/source/makefile.obj
+++ b/crawl-ref/source/makefile.obj
@@ -50,6 +50,7 @@ l_dgnmon.o \
l_dgntil.o \
l_dgn_bf.o \
l_file.o \
+l_item.o \
l_los.o \
l_mapgrd.o \
l_mapmrk.o \