tools/server: shop-item-time patch — NPC shop items carry a new item's time sockets
40250 game zeroes alSockets for NPC (shop.cpp) and extended (shopEx.cpp) shop items, so uitooltip shows 'remaining 0 min' for mounts and item-mall time items. MT_GetNewItemSockets fills them with ITEM_MANAGER::CreateItem's rules (UNIQUE remain time, auto potions, LIMIT_REAL_TIME, LIMIT_TIMER_BASED_ON_WEAR). Deployed on 203; mount shop 20368 verified. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
f9be09d2c2
commit
3aa4c482e9
@@ -11,12 +11,13 @@
|
||||
# Patches, in order (each is a patch -p1 against /usr/metin2/src, saved byte-exact):
|
||||
# inventory-5-pages 5-page inventory; needs its DB migration once (inventory-5-pages/README.md)
|
||||
# hunt-set quest item.set_attribute, free items in extended shops
|
||||
# shop-item-time NPC shop items carry a new item's time sockets (tooltip shows the duration)
|
||||
set -eu
|
||||
|
||||
SRC=${SRC:-/usr/metin2/src}
|
||||
SERVER=${SERVER:-/usr/metin2/server}
|
||||
HERE=$(cd "$(dirname "$0")" && pwd)
|
||||
PATCHES="inventory-5-pages hunt-set"
|
||||
PATCHES="inventory-5-pages hunt-set shop-item-time"
|
||||
TS=$(date +%Y%m%d-%H%M%S)
|
||||
|
||||
patch_state() {
|
||||
@@ -90,7 +91,7 @@ data)
|
||||
start_server
|
||||
;;
|
||||
*)
|
||||
sed -n '2,15p' "$0" >&2
|
||||
sed -n '2,16p' "$0" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
# NPC 商店物品显示剩余时间(203 服务端)
|
||||
|
||||
40250 服务端发商店物品列表时,NPC 商店(`shop.cpp` 的 `StartShop`/`UpdateItem`)和扩展多页商店
|
||||
(`shopEx.cpp`,如百店老板娘 9010)把物品的 socket 全部清零。客户端 `uitooltip.py` 用 socket 算剩余时间
|
||||
(UNIQUE 取 `socket[2]` 分钟数,LIMIT_REAL_TIME 取 `socket[0]` 到期时间戳),于是坐骑、百货店的限时物品
|
||||
在商店里都显示「剩余时间 : 0分」,买下后才正常。
|
||||
|
||||
`server.patch` 在 `shop.cpp` 加 `MT_GetNewItemSockets(vnum, alSockets)`:按 `ITEM_MANAGER::CreateItem`
|
||||
给新物品设 socket 的同一套规则(UNIQUE 剩余时间、自动药水、LIMIT_REAL_TIME、LIMIT_TIMER_BASED_ON_WEAR)
|
||||
填商店包里的 socket。玩家个人商店(有实际物品)不变,仍发物品自身的 socket。只影响显示,买到的物品照旧由
|
||||
`CreateItem` 生成。
|
||||
|
||||
在 hunt-set 之后打(`shopEx.cpp` 上下文依赖它)。`sh rebuild.sh build` 自动打补丁并编译。
|
||||
@@ -0,0 +1,96 @@
|
||||
--- a/server/game/src/shop.cpp
|
||||
+++ b/server/game/src/shop.cpp
|
||||
@@ -18,7 +18,55 @@
|
||||
#include "monarch.h"
|
||||
#include "mob_manager.h"
|
||||
#include "locale_service.h"
|
||||
+#include "unique_item.h"
|
||||
+
|
||||
+// MT: the sockets ITEM_MANAGER::CreateItem gives a new item of this vnum (its remaining time), sent
|
||||
+// with an NPC shop's items so the client tooltip shows how long a bought one lasts instead of 0.
|
||||
+void MT_GetNewItemSockets(DWORD dwVnum, long* alSockets)
|
||||
+{
|
||||
+ memset(alSockets, 0, sizeof(long) * ITEM_SOCKET_MAX_NUM);
|
||||
+
|
||||
+ const TItemTable* table = ITEM_MANAGER::instance().GetTable(dwVnum);
|
||||
+ if (!table)
|
||||
+ return;
|
||||
+
|
||||
+ if (table->bType == ITEM_UNIQUE)
|
||||
+ {
|
||||
+ if (table->alValues[2] == 0)
|
||||
+ alSockets[ITEM_SOCKET_UNIQUE_REMAIN_TIME] = table->alValues[0];
|
||||
+ else
|
||||
+ alSockets[ITEM_SOCKET_UNIQUE_REMAIN_TIME] = get_global_time() + table->alValues[0];
|
||||
+ }
|
||||
+
|
||||
+ switch (dwVnum)
|
||||
+ {
|
||||
+ case ITEM_AUTO_HP_RECOVERY_S:
|
||||
+ case ITEM_AUTO_HP_RECOVERY_M:
|
||||
+ case ITEM_AUTO_HP_RECOVERY_L:
|
||||
+ case ITEM_AUTO_HP_RECOVERY_X:
|
||||
+ case ITEM_AUTO_SP_RECOVERY_S:
|
||||
+ case ITEM_AUTO_SP_RECOVERY_M:
|
||||
+ case ITEM_AUTO_SP_RECOVERY_L:
|
||||
+ case ITEM_AUTO_SP_RECOVERY_X:
|
||||
+ case REWARD_BOX_ITEM_AUTO_SP_RECOVERY_XS:
|
||||
+ case REWARD_BOX_ITEM_AUTO_SP_RECOVERY_S:
|
||||
+ case REWARD_BOX_ITEM_AUTO_HP_RECOVERY_XS:
|
||||
+ case REWARD_BOX_ITEM_AUTO_HP_RECOVERY_S:
|
||||
+ case FUCKING_BRAZIL_ITEM_AUTO_SP_RECOVERY_S:
|
||||
+ case FUCKING_BRAZIL_ITEM_AUTO_HP_RECOVERY_S:
|
||||
+ alSockets[2] = table->alValues[0];
|
||||
+ break;
|
||||
+ }
|
||||
|
||||
+ for (int i = 0; i < ITEM_LIMIT_MAX_NUM; ++i)
|
||||
+ {
|
||||
+ if (LIMIT_REAL_TIME == table->aLimits[i].bType)
|
||||
+ alSockets[0] = time(0) + (table->aLimits[i].lValue ? table->aLimits[i].lValue : 60*60*24*7);
|
||||
+ else if (LIMIT_TIMER_BASED_ON_WEAR == table->aLimits[i].bType)
|
||||
+ alSockets[0] = table->aLimits[i].lValue ? table->aLimits[i].lValue : 60 * 60 * 10;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/* ------------------------------------------------------------------------------------ */
|
||||
CShop::CShop()
|
||||
: m_dwVnum(0), m_dwNPCVnum(0), m_pkPC(NULL)
|
||||
@@ -467,6 +515,8 @@
|
||||
thecore_memcpy(pack2.items[i].alSockets, item.pkItem->GetSockets(), sizeof(pack2.items[i].alSockets));
|
||||
thecore_memcpy(pack2.items[i].aAttr, item.pkItem->GetAttributes(), sizeof(pack2.items[i].aAttr));
|
||||
}
|
||||
+ else
|
||||
+ MT_GetNewItemSockets(item.vnum, pack2.items[i].alSockets);
|
||||
}
|
||||
|
||||
pack.size = sizeof(pack) + sizeof(pack2);
|
||||
@@ -537,7 +587,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
- memset(pack2.item.alSockets, 0, sizeof(pack2.item.alSockets));
|
||||
+ MT_GetNewItemSockets(m_itemVector[pos].vnum, pack2.item.alSockets);
|
||||
memset(pack2.item.aAttr, 0, sizeof(pack2.item.aAttr));
|
||||
}
|
||||
}
|
||||
--- a/server/game/src/shopEx.cpp
|
||||
+++ b/server/game/src/shopEx.cpp
|
||||
@@ -18,6 +18,8 @@
|
||||
#include "monarch.h"
|
||||
#include "mob_manager.h"
|
||||
#include "locale_service.h"
|
||||
+
|
||||
+void MT_GetNewItemSockets(DWORD dwVnum, long* alSockets);
|
||||
#include "desc_client.h"
|
||||
#include "shopEx.h"
|
||||
#include "group_text_parse_tree.h"
|
||||
@@ -96,7 +98,7 @@
|
||||
break;
|
||||
}
|
||||
memset(pack_tab.items[i].aAttr, 0, sizeof(pack_tab.items[i].aAttr));
|
||||
- memset(pack_tab.items[i].alSockets, 0, sizeof(pack_tab.items[i].alSockets));
|
||||
+ MT_GetNewItemSockets(shop_tab.items[i].vnum, pack_tab.items[i].alSockets);
|
||||
}
|
||||
|
||||
memcpy(buf, &pack_tab, sizeof(pack_tab));
|
||||
Reference in New Issue
Block a user