From 7980f4d21956314e284448f7dcedd58f9c23b355 Mon Sep 17 00:00:00 2001 From: HoraK-FDF Date: Mon, 3 Apr 2023 01:58:15 +0000 Subject: Item mode --- src/ast/item.cpp | 1 + src/ast/item.hpp | 2 ++ src/map/clif.cpp | 11 +++++++++++ src/map/itemdb.cpp | 1 + src/map/itemdb.hpp | 2 ++ src/map/npc.cpp | 7 ++++++- src/map/storage.cpp | 6 ++++++ src/mmo/enums.hpp | 15 +++++++++++++++ src/mmo/extract_enums.hpp | 3 +++ 9 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/ast/item.cpp b/src/ast/item.cpp index d27e231..623f5c6 100644 --- a/src/ast/item.cpp +++ b/src/ast/item.cpp @@ -142,6 +142,7 @@ namespace item SPAN_EXTRACT(TRY_UNWRAP(lex_nonscript(lr, false), return EOL_ERROR(lr)), item.wlv); SPAN_EXTRACT(TRY_UNWRAP(lex_nonscript(lr, false), return EOL_ERROR(lr)), item.elv); SPAN_EXTRACT(TRY_UNWRAP(lex_nonscript(lr, false), return EOL_ERROR(lr)), item.view); + SPAN_EXTRACT(TRY_UNWRAP(lex_nonscript(lr, false), return EOL_ERROR(lr)), item.mode); item.use_script = TRY(lex_script(lr)); item.equip_script = TRY(lex_script(lr)); ItemOrComment rv = std::move(item); diff --git a/src/ast/item.hpp b/src/ast/item.hpp index c772655..90d51a1 100644 --- a/src/ast/item.hpp +++ b/src/ast/item.hpp @@ -63,6 +63,8 @@ namespace item Spanned wlv; Spanned elv; Spanned view; + Spanned mode; + ast::script::ScriptBody use_script; ast::script::ScriptBody equip_script; }; diff --git a/src/map/clif.cpp b/src/map/clif.cpp index 0eb2b8c..e81a510 100644 --- a/src/map/clif.cpp +++ b/src/map/clif.cpp @@ -4617,6 +4617,11 @@ RecvResult clif_parse_DropItem(Session *s, dumb_ptr sd) clif_displaymessage(sd->sess, "Can't drop items here."_s); return rv; } + if (bool(itemdb_search(sd->status.inventory[fixed.ioff2.unshift()].nameid)->mode & ItemMode::NO_DROP)) + { + clif_displaymessage(sd->sess, "This item can't be dropped."_s); + return rv; + } if (sd->npc_id || sd->opt1 != Opt1::ZERO) { @@ -4895,6 +4900,12 @@ RecvResult clif_parse_TradeAddItem(Session *s, dumb_ptr sd) if (fixed.zeny_or_ioff2.index != 0 && !fixed.zeny_or_ioff2.ok()) return RecvResult::Error; + if (fixed.zeny_or_ioff2.ok()) + if (bool(itemdb_search(sd->status.inventory[fixed.zeny_or_ioff2.unshift()].nameid)->mode & ItemMode::NO_TRADE)) + { + clif_displaymessage(sd->sess, "This item can't be traded."_s); + return rv; + } trade_tradeadditem(sd, fixed.zeny_or_ioff2, fixed.amount); return rv; diff --git a/src/map/itemdb.cpp b/src/map/itemdb.cpp index 7b23503..fa675d2 100644 --- a/src/map/itemdb.cpp +++ b/src/map/itemdb.cpp @@ -201,6 +201,7 @@ bool itemdb_readdb(ZString filename) idv.wlv = item.wlv.data; idv.elv = item.elv.data; idv.look = item.view.data; + idv.mode = item.mode.data; idv.use_script = compile_script(STRPRINTF("use script %d"_fmt, idv.nameid), item.use_script, true); idv.equip_script = compile_script(STRPRINTF("equip script %d"_fmt, idv.nameid), item.equip_script, true); diff --git a/src/map/itemdb.hpp b/src/map/itemdb.hpp index 19f40a8..10805f5 100644 --- a/src/map/itemdb.hpp +++ b/src/map/itemdb.hpp @@ -50,6 +50,8 @@ struct item_data ItemLook look; int elv; int wlv; + ItemMode mode; + std::unique_ptr use_script; std::unique_ptr equip_script; }; diff --git a/src/map/npc.cpp b/src/map/npc.cpp index 4d9a8d1..ee2f30c 100644 --- a/src/map/npc.cpp +++ b/src/map/npc.cpp @@ -993,6 +993,12 @@ int npc_selllist(dumb_ptr sd, if (!nameid || sd->status.inventory[item_list[i].ioff2.unshift()].amount < item_list[i].count) return 1; + if (bool(itemdb_search(nameid)->mode & ItemMode::NO_SELL_TO_NPC)) + { + //clif_displaymessage(sd->sess, "This item can't be sold to an NPC."_s); + // M+ already outputs "Unable to sell unsellable item." on return value 3. + return 3; + } if (sd->trade_partner) return 2; // cant sell while trading z += static_cast(itemdb_value_sell(nameid)) * item_list[i].count; @@ -1009,7 +1015,6 @@ int npc_selllist(dumb_ptr sd, } return 0; - } static diff --git a/src/map/storage.cpp b/src/map/storage.cpp index 1327146..54398f3 100644 --- a/src/map/storage.cpp +++ b/src/map/storage.cpp @@ -186,6 +186,12 @@ int storage_storageadd(dumb_ptr sd, IOff0 index, int amount) if (amount < 1 || amount > sd->status.inventory[index].amount) return 0; + if (bool(itemdb_search(sd->status.inventory[index].nameid)->mode & ItemMode::NO_STORAGE)) + { + clif_displaymessage(sd->sess, "This item can't be stored."_s); + return 0; + } + // log_tostorage(sd, index, 0); if (storage_additem(sd, stor, &sd->status.inventory[index], amount) == 0) { diff --git a/src/mmo/enums.hpp b/src/mmo/enums.hpp index 2564ec9..12c82ca 100644 --- a/src/mmo/enums.hpp +++ b/src/mmo/enums.hpp @@ -107,6 +107,20 @@ enum class ItemLook : uint16_t COUNT = 17, }; +namespace e +{ +enum class ItemMode : uint8_t +{ + NONE = 0, + NO_DROP = 1, + NO_TRADE = 2, + NO_SELL_TO_NPC = 4, + NO_STORAGE = 8, +}; +ENUM_BITWISE_OPERATORS(ItemMode) +} +using e::ItemMode; + enum class SEX : uint8_t { FEMALE = 0, @@ -117,6 +131,7 @@ enum class SEX : uint8_t NEUTRAL = 3, __OTHER = 4, // used in ManaPlus only }; + inline char sex_to_char(SEX sex) { diff --git a/src/mmo/extract_enums.hpp b/src/mmo/extract_enums.hpp index 0e8ac4c..14e7b17 100644 --- a/src/mmo/extract_enums.hpp +++ b/src/mmo/extract_enums.hpp @@ -35,6 +35,7 @@ enum class EPOS : uint16_t; enum class Opt1 : uint16_t; enum class Opt2 : uint16_t; enum class Opt0 : uint16_t; +enum class ItemMode : uint8_t; inline bool impl_extract(XString str, EPOS *iv) { return extract_as_int(str, iv); } @@ -44,6 +45,8 @@ inline bool impl_extract(XString str, Opt2 *iv) { return extract_as_int(str, iv); } inline bool impl_extract(XString str, Opt0 *iv) { return extract_as_int(str, iv); } +inline +bool impl_extract(XString str, ItemMode *iv) { return extract_as_int(str, iv); } } // namespace e enum class ItemLook : uint16_t; -- cgit v1.2.3-60-g2f50