From 7980f4d21956314e284448f7dcedd58f9c23b355 Mon Sep 17 00:00:00 2001
From: HoraK-FDF <horak-fdf@web.de>
Date: Mon, 3 Apr 2023 01:58:15 +0000
Subject: Item mode

---
 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 ++++++
 5 files changed, 26 insertions(+), 1 deletion(-)

(limited to 'src/map')

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<map_session_data> 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<map_session_data> 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<const ScriptBuffer> use_script;
     std::unique_ptr<const ScriptBuffer> 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<map_session_data> 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<double>(itemdb_value_sell(nameid)) * item_list[i].count;
@@ -1009,7 +1015,6 @@ int npc_selllist(dumb_ptr<map_session_data> 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<map_session_data> 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)
     {
-- 
cgit v1.2.3-70-g09d2