3 * Summary: functions for managed Lua item manipulation
25 #include "spl-summoning.h"
28 /////////////////////////////////////////////////////////////////////
36 bool valid() const { return turn
== you
.num_turns
; }
39 void clua_push_item(lua_State
*ls
, item_def
*item
)
42 item_wrapper
*iw
= clua_new_userdata
<item_wrapper
>(ls
, ITEM_METATABLE
);
44 iw
->turn
= you
.num_turns
;
47 item_def
*clua_get_item(lua_State
*ls
, int ndx
)
50 clua_get_userdata
<item_wrapper
>(ls
, ITEM_METATABLE
, ndx
);
51 if (CLua::get_vm(ls
).managed_vm
&& !iwrap
->valid())
52 luaL_error(ls
, "Invalid item");
56 void lua_push_floor_items(lua_State
*ls
, int link
)
60 for (; link
!= NON_ITEM
; link
= mitm
[link
].link
)
62 clua_push_item(ls
, &mitm
[link
]);
63 lua_rawseti(ls
, -2, ++index
);
67 void lua_push_inv_items(lua_State
*ls
= NULL
)
73 for (unsigned slot
= 0; slot
< ENDOFPACK
; ++slot
)
75 if (you
.inv
[slot
].defined())
77 clua_push_item(ls
, &you
.inv
[slot
]);
78 lua_rawseti(ls
, -2, ++index
);
84 static int l_item_##name(lua_State *ls, item_def *item, \
87 #define IDEFN(name, closure) \
88 static int l_item_##name(lua_State *ls, item_def *item, const char *attrs) \
90 clua_push_item(ls, item); \
91 lua_pushcclosure(ls, l_item_##closure, 1); \
95 #define ITEM(name, ndx) \
96 item_def *name = clua_get_item(ls, ndx)
98 #define UDATA_ITEM(name) ITEM(name, lua_upvalueindex(1))
100 static int l_item_do_wield(lua_State
*ls
)
102 if (you
.turn_is_over
)
108 if (item
&& item
->defined() && in_inventory(*item
))
110 bool res
= wield_weapon(true, slot
);
111 lua_pushboolean(ls
, res
);
115 IDEFN(wield
, do_wield
)
117 static int l_item_do_wear(lua_State
*ls
)
119 if (you
.turn_is_over
)
124 if (!item
|| !in_inventory(*item
))
127 bool success
= do_wear_armour(item
->link
, false);
128 lua_pushboolean(ls
, success
);
134 static int l_item_do_puton(lua_State
*ls
)
136 if (you
.turn_is_over
)
141 if (!item
|| !in_inventory(*item
))
144 lua_pushboolean(ls
, puton_ring(item
->link
));
148 IDEFN(puton
, do_puton
)
150 static int l_item_do_remove(lua_State
*ls
)
152 if (you
.turn_is_over
)
160 if (!item
|| !in_inventory(*item
))
166 int eq
= get_equip_slot(item
);
167 if (eq
< 0 || eq
>= NUM_EQUIP
)
169 mpr("Item is not equipped");
175 result
= wield_weapon(true, SLOT_BARE_HANDS
);
176 else if (eq
== EQ_LEFT_RING
|| eq
== EQ_RIGHT_RING
|| eq
== EQ_AMULET
)
177 result
= remove_ring(item
->link
);
179 result
= takeoff_armour(item
->link
);
180 lua_pushboolean(ls
, result
);
184 IDEFN(remove
, do_remove
)
186 static int l_item_do_drop(lua_State
*ls
)
188 if (you
.turn_is_over
)
193 if (!item
|| !in_inventory(*item
))
196 int eq
= get_equip_slot(item
);
197 if (eq
>= 0 && eq
< NUM_EQUIP
)
199 lua_pushboolean(ls
, false);
200 lua_pushstring(ls
, "Can't drop worn items");
204 int qty
= item
->quantity
;
205 if (lua_isnumber(ls
, 1))
207 int q
= luaL_checkint(ls
, 1);
208 if (q
>= 1 && q
<= item
->quantity
)
211 lua_pushboolean(ls
, drop_item(item
->link
, qty
));
219 if (!item
|| !in_inventory(*item
))
220 lua_pushboolean(ls
, false);
222 int eq
= get_equip_slot(item
);
223 if (eq
< 0 || eq
>= NUM_EQUIP
)
224 lua_pushboolean(ls
, false);
226 lua_pushboolean(ls
, true);
231 static int l_item_do_class (lua_State
*ls
)
238 if (lua_isboolean(ls
, 1))
239 terse
= lua_toboolean(ls
, 1);
241 std::string s
= item_class_name(item
->base_type
, terse
);
242 lua_pushstring(ls
, s
.c_str());
249 IDEFN(class, do_class
)
251 // FIXME: Fold this back into itemname.cc.
252 static const char *ring_types
[] =
256 "protection from fire",
258 "protection from cold",
274 "protection from magic",
280 static const char *amulet_types
[] =
282 "rage", "resist slowing", "clarity", "warding", "resist corrosion",
283 "gourmand", "conservation", "controlled flight", "inaccuracy",
291 if (item_type_known(*item
))
293 const char *s
= NULL
;
294 if (item
->base_type
== OBJ_JEWELLERY
)
296 if (jewellery_is_amulet(*item
))
297 s
= amulet_types
[ item
->sub_type
- AMU_RAGE
];
299 s
= ring_types
[item
->sub_type
];
301 else if (item
->base_type
== OBJ_POTIONS
)
303 if (item
->sub_type
== POT_BLOOD
)
305 else if (item
->sub_type
== POT_BLOOD_COAGULATED
)
306 s
= "coagulated blood";
307 else if (item
->sub_type
== POT_WATER
)
309 else if (item
->sub_type
== POT_PORRIDGE
)
311 else if (item
->sub_type
== POT_BERSERK_RAGE
)
313 else if (item
->sub_type
== POT_GAIN_STRENGTH
314 || item
->sub_type
== POT_GAIN_DEXTERITY
315 || item
->sub_type
== POT_GAIN_INTELLIGENCE
)
319 else if (item
->sub_type
== POT_CURE_MUTATION
)
322 else if (item
->base_type
== OBJ_BOOKS
)
324 if (item
->sub_type
== BOOK_MANUAL
)
331 lua_pushstring(ls
, s
);
335 lua_pushnumber(ls
, item
->sub_type
);
347 bool cursed
= item
&& item_ident(*item
, ISFLAG_KNOW_CURSE
)
349 lua_pushboolean(ls
, cursed
);
355 int worn
= get_equip_slot(item
);
357 lua_pushnumber(ls
, worn
);
361 lua_pushstring(ls
, equip_slot_to_name(worn
));
367 static std::string
_item_name(lua_State
*ls
, item_def
* item
)
369 description_level_type ndesc
= DESC_PLAIN
;
370 if (lua_isstring(ls
, 1))
371 ndesc
= description_type_by_name(lua_tostring(ls
, 1));
372 else if (lua_isnumber(ls
, 1))
373 ndesc
= static_cast<description_level_type
>(luaL_checkint(ls
, 1));
374 const bool terse
= lua_toboolean(ls
, 2);
375 return (item
->name(ndesc
, terse
));
378 static int l_item_do_name(lua_State
*ls
)
383 lua_pushstring(ls
, _item_name(ls
, item
).c_str());
391 static int l_item_do_name_coloured(lua_State
*ls
)
397 std::string name
= _item_name(ls
, item
);
398 int col
= menu_colour(name
, menu_colour_item_prefix(*item
));
399 std::string colstr
= colour_to_str(col
);
401 std::ostringstream out
;
403 out
<< "<" << colstr
<< ">" << name
<< "</" << colstr
<< ">";
405 lua_pushstring(ls
, out
.str().c_str());
412 IDEFN(name_coloured
, do_name_coloured
)
416 PLUARET(number
, item
? item
->quantity
: 0);
423 int slot
= in_inventory(*item
) ? item
->link
424 : letter_to_index(item
->slot
);
425 lua_pushnumber(ls
, slot
);
434 PLUARET(boolean
, item
&& in_inventory(*item
));
439 if (!item
|| !item
->defined())
442 equipment_type eq
= EQ_NONE
;
444 if (item
->base_type
== OBJ_WEAPONS
|| item
->base_type
== OBJ_STAVES
)
446 else if (item
->base_type
== OBJ_ARMOUR
)
447 eq
= get_armour_slot(*item
);
448 else if (item
->base_type
== OBJ_JEWELLERY
)
449 eq
= item
->sub_type
>= AMU_RAGE
? EQ_AMULET
: EQ_RINGS
;
453 lua_pushnumber(ls
, eq
);
454 lua_pushstring(ls
, equip_slot_to_name(eq
));
466 if (!item
|| !item
->defined())
469 skill_type skill
= range_skill(*item
);
470 if (skill
== SK_THROWING
)
471 skill
= weapon_skill(*item
);
472 if (skill
== SK_FIGHTING
)
475 lua_pushstring(ls
, skill_name(skill
));
476 lua_pushnumber(ls
, skill
);
482 if (!item
|| !item
->defined())
485 lua_pushboolean(ls
, item
->flags
& ISFLAG_DROPPED
);
492 if (!item
|| !item
->defined())
495 lua_pushboolean(ls
, can_cut_meat(*item
));
502 if (!item
|| !item
->defined())
505 lua_pushboolean(ls
, is_artefact(*item
));
512 if (!item
|| !item
->defined() || !item_type_known(*item
))
515 lua_pushboolean(ls
, item_is_branded(*item
));
521 if (!item
|| !item
->defined())
524 lua_pushboolean(ls
, item_is_snakable(*item
));
529 // DLUA-only functions
530 static int l_item_do_pluses (lua_State
*ls
)
536 if (!item
|| !item
->defined() || !item_ident(*item
, ISFLAG_KNOW_PLUSES
))
538 lua_pushboolean(ls
, false);
542 lua_pushnumber(ls
, item
->plus
);
543 // XXX: May cause issues on items that don't use plus2, ie ammunition.
544 lua_pushnumber(ls
, item
->plus2
);
549 IDEFN(pluses
, do_pluses
)
551 static int l_item_do_destroy (lua_State
*ls
)
557 if (!item
|| !item
->defined())
559 lua_pushboolean(ls
, false);
563 item_was_destroyed(*item
);
564 destroy_item(item
->index());
566 lua_pushboolean(ls
, true);
570 IDEFN(destroy
, do_destroy
)
572 static int l_item_do_dec_quantity (lua_State
*ls
)
578 if (!item
|| !item
->defined())
580 lua_pushboolean(ls
, false);
584 // The quantity to reduce by.
585 int quantity
= luaL_checkint(ls
, 1);
587 bool destroyed
= false;
589 if (in_inventory(*item
))
590 destroyed
= dec_inv_item_quantity(item
->link
, quantity
);
592 destroyed
= dec_mitm_item_quantity(item
->index(), quantity
);
594 lua_pushboolean(ls
, destroyed
);
598 IDEFN(dec_quantity
, do_dec_quantity
)
600 static int l_item_do_inc_quantity (lua_State
*ls
)
606 if (!item
|| !item
->defined())
608 lua_pushboolean(ls
, false);
612 // The quantity to increase by.
613 int quantity
= luaL_checkint(ls
, 1);
615 if (in_inventory(*item
))
616 inc_inv_item_quantity(item
->link
, quantity
);
618 inc_mitm_item_quantity(item
->index(), quantity
);
623 IDEFN(inc_quantity
, do_inc_quantity
)
625 iflags_t
str_to_item_status_flags (std::string flag
)
628 if (flag
.find("curse") != std::string::npos
)
629 flags
&= ISFLAG_KNOW_CURSE
;
630 // type is dealt with using item_type_known.
631 //if (flag.find("type") != std::string::npos)
632 // flags &= ISFLAG_KNOW_TYPE;
633 if (flag
.find("pluses") != std::string::npos
)
634 flags
&= ISFLAG_KNOW_PLUSES
;
635 if (flag
.find("properties") != std::string::npos
)
636 flags
&= ISFLAG_KNOW_PROPERTIES
;
638 flags
= ISFLAG_IDENT_MASK
;
643 static int l_item_do_identified (lua_State
*ls
)
649 if (!item
|| !item
->defined())
655 bool known_status
= false;
656 if (lua_isstring(ls
, 1))
658 std::string flags
= luaL_checkstring(ls
, 1);
659 if (trimmed_string(flags
).empty())
660 known_status
= item_ident(*item
, ISFLAG_IDENT_MASK
);
663 const bool check_type
= strip_tag(flags
, "type");
664 iflags_t item_flags
= str_to_item_status_flags(flags
);
665 known_status
= ((item_flags
|| check_type
)
666 && (!item_flags
|| item_ident(*item
, item_flags
))
667 && (!check_type
|| item_type_known(*item
)));
672 known_status
= item_ident(*item
, ISFLAG_IDENT_MASK
);
675 lua_pushboolean(ls
, known_status
);
679 IDEFN(identified
, do_identified
)
681 // Some dLua convenience functions.
686 lua_pushstring(ls
, base_type_string(*item
).c_str());
694 lua_pushstring(ls
, sub_type_string(*item
).c_str());
700 if (CLua::get_vm(ls
).managed_vm
&& !item_ident(*item
, ISFLAG_KNOW_TYPE
))
702 lua_pushstring(ls
, "unknown");
706 lua_pushstring(ls
, ego_type_string(*item
).c_str());
714 if (is_artefact(*item
))
715 lua_pushstring(ls
, get_artefact_name(*item
, true).c_str());
726 bool cursed
= item
->cursed();
728 lua_pushboolean(ls
, cursed
);
732 // Library functions below
733 static int l_item_inventory(lua_State
*ls
)
735 lua_push_inv_items(ls
);
739 static int l_item_index_to_letter(lua_State
*ls
)
741 int index
= luaL_checkint(ls
, 1);
742 char sletter
[2] = "?";
743 if (index
>= 0 && index
<= ENDOFPACK
)
744 *sletter
= index_to_letter(index
);
745 lua_pushstring(ls
, sletter
);
749 static int l_item_letter_to_index(lua_State
*ls
)
751 const char *s
= luaL_checkstring(ls
, 1);
752 if (!s
|| !*s
|| s
[1])
754 lua_pushnumber(ls
, letter_to_index(*s
));
758 static int l_item_swap_slots(lua_State
*ls
)
760 int slot1
= luaL_checkint(ls
, 1),
761 slot2
= luaL_checkint(ls
, 2);
762 bool verbose
= lua_toboolean(ls
, 3);
763 if (slot1
< 0 || slot1
>= ENDOFPACK
764 || slot2
< 0 || slot2
>= ENDOFPACK
765 || slot1
== slot2
|| !you
.inv
[slot1
].defined())
770 swap_inv_slots(slot1
, slot2
, verbose
);
775 static item_def
*dmx_get_item(lua_State
*ls
, int ndx
, int subndx
)
777 if (lua_istable(ls
, ndx
))
779 lua_rawgeti(ls
, ndx
, subndx
);
788 static int dmx_get_qty(lua_State
*ls
, int ndx
, int subndx
)
791 if (lua_istable(ls
, ndx
))
793 lua_rawgeti(ls
, ndx
, subndx
);
794 if (lua_isnumber(ls
, -1))
795 qty
= luaL_checkint(ls
, -1);
798 else if (lua_isnumber(ls
, ndx
))
800 qty
= luaL_checkint(ls
, ndx
);
805 static bool l_item_pickup2(item_def
*item
, int qty
)
807 if (!item
|| in_inventory(*item
))
810 int floor_link
= item_on_floor(*item
, you
.pos());
811 if (floor_link
== NON_ITEM
)
814 return pickup_single_item(floor_link
, qty
);
817 static int l_item_pickup(lua_State
*ls
)
819 if (you
.turn_is_over
)
822 if (lua_isuserdata(ls
, 1))
825 int qty
= item
->quantity
;
826 if (lua_isnumber(ls
, 2))
827 qty
= luaL_checkint(ls
, 2);
829 if (l_item_pickup2(item
, qty
))
830 lua_pushnumber(ls
, 1);
835 else if (lua_istable(ls
, 1))
838 for (int i
= 1; ; ++i
)
840 lua_rawgeti(ls
, 1, i
);
841 item_def
*item
= dmx_get_item(ls
, -1, 1);
842 int qty
= dmx_get_qty(ls
, -1, 2);
845 if (l_item_pickup2(item
, qty
))
849 // Yes, we bail out on first failure.
854 lua_pushnumber(ls
, dropped
);
862 // Returns item equipped in a slot defined in an argument.
863 static int l_item_equipped_at(lua_State
*ls
)
866 if (lua_isnumber(ls
, 1))
867 eq
= luaL_checkint(ls
, 1);
868 else if (lua_isstring(ls
, 1))
870 const char *eqname
= lua_tostring(ls
, 1);
873 eq
= equip_name_to_slot(eqname
);
876 if (eq
< 0 || eq
>= NUM_EQUIP
)
879 if (you
.equip
[eq
] != -1)
880 clua_push_item(ls
, &you
.inv
[you
.equip
[eq
]]);
887 static int l_item_inslot(lua_State
*ls
)
889 int index
= luaL_checkint(ls
, 1);
890 if (index
>= 0 && index
< 52 && you
.inv
[index
].defined())
891 clua_push_item(ls
, &you
.inv
[index
]);
899 const char *attribute
;
900 int (*accessor
)(lua_State
*ls
, item_def
*item
, const char *attr
);
903 static ItemAccessor item_attrs
[] =
905 { "artefact", l_item_artefact
},
906 { "branded", l_item_branded
},
907 { "snakable", l_item_snakable
},
908 { "class", l_item_class
},
909 { "subtype", l_item_subtype
},
910 { "cursed", l_item_cursed
},
911 { "worn", l_item_worn
},
912 { "name", l_item_name
},
913 { "name_coloured", l_item_name_coloured
},
914 { "quantity", l_item_quantity
},
915 { "slot", l_item_slot
},
916 { "ininventory", l_item_ininventory
},
917 { "wield", l_item_wield
},
918 { "wear", l_item_wear
},
919 { "puton", l_item_puton
},
920 { "remove", l_item_remove
},
921 { "drop", l_item_drop
},
922 { "equipped", l_item_equipped
},
923 { "equip_type", l_item_equip_type
},
924 { "weap_skill", l_item_weap_skill
},
925 { "dropped", l_item_dropped
},
926 { "can_cut_meat", l_item_can_cut_meat
},
927 { "pluses", l_item_pluses
},
928 { "destroy", l_item_destroy
},
929 { "dec_quantity", l_item_dec_quantity
},
930 { "inc_quantity", l_item_inc_quantity
},
931 { "identified", l_item_identified
},
932 { "base_type", l_item_base_type
},
933 { "sub_type", l_item_sub_type
},
934 { "ego_type", l_item_ego_type
},
935 { "artefact_name", l_item_artefact_name
},
936 { "is_cursed", l_item_is_cursed
},
939 static int item_get(lua_State
*ls
)
945 const char *attr
= luaL_checkstring(ls
, 2);
949 for (unsigned i
= 0; i
< sizeof(item_attrs
) / sizeof(item_attrs
[0]); ++i
)
950 if (!strcmp(attr
, item_attrs
[i
].attribute
))
951 return (item_attrs
[i
].accessor(ls
, iw
, attr
));
956 static const struct luaL_reg item_lib
[] =
958 { "inventory", l_item_inventory
},
959 { "letter_to_index", l_item_letter_to_index
},
960 { "index_to_letter", l_item_index_to_letter
},
961 { "swap_slots", l_item_swap_slots
},
962 { "pickup", l_item_pickup
},
963 { "equipped_at", l_item_equipped_at
},
964 { "inslot", l_item_inslot
},
968 void cluaopen_item(lua_State
*ls
)
970 luaL_newmetatable(ls
, ITEM_METATABLE
);
971 lua_pushstring(ls
, "__index");
972 lua_pushcfunction(ls
, item_get
);
973 lua_settable(ls
, -3);
975 // Pop the metatable off the stack.
978 luaL_openlib(ls
, "items", item_lib
, 0);