背包扩展到 5 页:服务端补丁 + DB 迁移 + 客户端 mt_inventory
- GameType.h: c_Inventory_Page_Count 2 -> 5; SQuickSlot.Position BYTE -> WORD - quickslot 包/接口 pos 改为 WORD(CG/GC 5 字节),wire_classic 同步 - mt_inventory PORT 模块:inventorywindow.py 装备格 90 -> EQUIPMENT_SLOT_START 重映射、5 个小页签、 自动药水高亮与 SelectItemWindow 扫描全部 5 页;40250 脚本保持不变 - tools/server/inventory-5-pages: server.patch(格子布局 +135、quickslot WORD)、migrate_db.py、README Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
22d534c5eb
commit
e33e41c12b
@@ -0,0 +1,39 @@
|
||||
# 背包 5 页(服务端)
|
||||
|
||||
40250 背包是 2 页 × 45 格(`INVENTORY_MAX_NUM = 90`)。本补丁改为 5 页 225 格,客户端对应改动见
|
||||
`src/port/UserInterface/GameType.h`(`c_Inventory_Page_Count`)和 `src/platform/ScriptLib/InventoryPagesScript.inc`。
|
||||
|
||||
## 格子布局
|
||||
|
||||
| 区段 | 40250 | 5 页 |
|
||||
| --- | --- | --- |
|
||||
| 背包 | 0..89 | 0..224 |
|
||||
| 穿戴(32) | 90..121 | 225..256 |
|
||||
| 龙魂装备(12) | 122..133 | 257..268 |
|
||||
| 龙魂预留(18) | 134..151 | 269..286 |
|
||||
| 腰带背包(16) | 152..167 | 287..302 |
|
||||
|
||||
背包之后的格子整体 +135,超过 255,所以 `TQuickslot.pos` 从 BYTE 改成 WORD(快捷栏封包变成 5 字节,
|
||||
`player.quickslot` 从 72 字节变成 108 字节)。**旧客户端不兼容**,必须和新客户端一起上线。
|
||||
|
||||
## 文件
|
||||
|
||||
- `server.patch`:对 40250 `src/server` 的改动(`common/length.h`、`common/tables.h`、`game/src` 里把格子号存成 BYTE 的地方、
|
||||
`exchange.cpp` 的每页空间检查)。在 `/usr/metin2/src` 下 `patch -p1 < server.patch`。源码是 EUC-KR + CRLF,补丁按字节保存。
|
||||
- `migrate_db.py`:DB 迁移,停服后运行一次(`python3.9 migrate_db.py [--dry-run] [mysql 参数]`,默认 `-uroot player`)。
|
||||
腰带物品(`window='INVENTORY'` 且 `pos` 152..167)+135;`player`/`player_deleted` 的 `quickslot` 转成 WORD 布局,
|
||||
指向腰带格的物品快捷栏同样 +135。结果记入 `mt_migration` 表,重复运行不会再改。穿戴/龙魂装备按 EQUIPMENT 窗口的相对位置存,不受影响。
|
||||
|
||||
## 构建与部署(203,FreeBSD 13.2 i386)
|
||||
|
||||
Makefile 默认把二进制移到 `share/bin`(线上正在用),构建时要改输出目录:
|
||||
|
||||
```sh
|
||||
cd /usr/metin2/src/server/game/src && gmake -j2 GAMEDIR=/root/inv5-out/new
|
||||
cd ../../db/src && gmake -j2 DBDIR=/root/inv5-out/new
|
||||
```
|
||||
|
||||
部署顺序:`close.sh` → 备份 `player` 库 → `migrate_db.py` → 覆盖 `share/bin/{game,db}` → `echo 1 | sh start.sh`。
|
||||
auth 用的也是 `game` 二进制;`TPlayerTable` 含快捷栏数组,所以 game 和 db 必须一起换。
|
||||
|
||||
2026-09-29 已在 203 部署。备份在 `/root/backup-inv5/`(源码 tgz、原 game/db、迁移前的 player 库)。回滚:停服,恢复这三样。
|
||||
@@ -0,0 +1,79 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Migrate the 40250 player DB to the 5-page bag (server.patch). Run once, with db/game stopped.
|
||||
|
||||
python3 migrate_db.py [--dry-run] [mysql args...] (default mysql args: -uroot player)
|
||||
|
||||
- Belt-inventory items are stored as window INVENTORY at absolute cells 152..167; they move to 287..302
|
||||
(every cell after the bag moves by +135). Worn and dragon-soul-equipped items are stored relative to
|
||||
their EQUIPMENT window and do not move.
|
||||
- player.quickslot / player_deleted.quickslot hold TQuickslot[36] raw: {BYTE type; BYTE pos} (72 bytes)
|
||||
becomes {BYTE type; WORD pos} (108 bytes). Item quick slots (type 1) on a belt cell get +135 too.
|
||||
|
||||
A row in table mt_migration records the run; a second run changes nothing.
|
||||
"""
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
NAME = "inventory-5-pages"
|
||||
QUICKSLOT_MAX_NUM = 36
|
||||
QUICKSLOT_TYPE_ITEM = 1
|
||||
OLD_BELT = range(152, 168)
|
||||
SHIFT = 135
|
||||
|
||||
|
||||
def mysql(args, sql):
|
||||
out = subprocess.run(["mysql", "-N", "-B"] + args, input=sql, capture_output=True, text=True)
|
||||
if out.returncode:
|
||||
sys.exit("mysql failed: " + out.stderr.strip())
|
||||
return [line.split("\t") for line in out.stdout.splitlines()]
|
||||
|
||||
|
||||
def convert(blob):
|
||||
assert len(blob) == QUICKSLOT_MAX_NUM * 2, len(blob)
|
||||
out = bytearray()
|
||||
for i in range(QUICKSLOT_MAX_NUM):
|
||||
kind, pos = blob[2 * i], blob[2 * i + 1]
|
||||
if kind == QUICKSLOT_TYPE_ITEM and pos in OLD_BELT:
|
||||
pos += SHIFT
|
||||
out += bytes([kind, pos & 0xFF, pos >> 8])
|
||||
return bytes(out)
|
||||
|
||||
|
||||
def main():
|
||||
argv = sys.argv[1:]
|
||||
dry = "--dry-run" in argv
|
||||
args = [a for a in argv if a != "--dry-run"] or ["-uroot", "player"]
|
||||
|
||||
mysql(args, "CREATE TABLE IF NOT EXISTS mt_migration (name VARCHAR(64) PRIMARY KEY, done DATETIME)")
|
||||
if mysql(args, "SELECT name FROM mt_migration WHERE name='%s'" % NAME):
|
||||
print("%s: already applied" % NAME)
|
||||
return
|
||||
|
||||
sql = ["UPDATE item SET pos = pos + %d WHERE window = 'INVENTORY' AND pos BETWEEN %d AND %d;"
|
||||
% (SHIFT, OLD_BELT[0], OLD_BELT[-1])]
|
||||
belt = mysql(args, "SELECT COUNT(*) FROM item WHERE window='INVENTORY' AND pos BETWEEN %d AND %d"
|
||||
% (OLD_BELT[0], OLD_BELT[-1]))[0][0]
|
||||
bad = mysql(args, "SELECT COUNT(*) FROM item WHERE window='INVENTORY' AND pos BETWEEN 90 AND 151")[0][0]
|
||||
if bad != "0":
|
||||
sys.exit("%s INVENTORY items at cells 90..151, which 40250 does not use; stop" % bad)
|
||||
rows = 0
|
||||
for table in ("player", "player_deleted"):
|
||||
for pid, blob in mysql(args, "SELECT id, HEX(quickslot) FROM %s" % table):
|
||||
data = bytes.fromhex(blob)
|
||||
if not data:
|
||||
continue
|
||||
if len(data) != QUICKSLOT_MAX_NUM * 2:
|
||||
sys.exit("%s %s: quickslot is %d bytes, expected %d" % (table, pid, len(data), QUICKSLOT_MAX_NUM * 2))
|
||||
sql.append("UPDATE %s SET quickslot = X'%s' WHERE id = %s;" % (table, convert(data).hex().upper(), pid))
|
||||
rows += 1
|
||||
sql.append("INSERT INTO mt_migration VALUES ('%s', NOW());" % NAME)
|
||||
print("%s: %s belt item(s), %d quickslot row(s)" % (NAME, belt, rows))
|
||||
if dry:
|
||||
print("\n".join(sql))
|
||||
return
|
||||
mysql(args, "\n".join(sql))
|
||||
print("%s: applied" % NAME)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,362 @@
|
||||
diff --git a/server/common/length.h b/server/common/length.h
|
||||
index fba03e3..f4cafc3 100755
|
||||
--- a/server/common/length.h
|
||||
+++ b/server/common/length.h
|
||||
@@ -12,7 +12,9 @@ enum EMisc
|
||||
ACCOUNT_STATUS_MAX_LEN = 8,
|
||||
CHARACTER_NAME_MAX_LEN = 24,
|
||||
SHOP_SIGN_MAX_LEN = 32,
|
||||
- INVENTORY_MAX_NUM = 90,
|
||||
+ INVENTORY_PAGE_SIZE = 45, // 5 x 9
|
||||
+ INVENTORY_PAGE_COUNT = 5, // MT: 40250 ships 2 pages (90 cells)
|
||||
+ INVENTORY_MAX_NUM = INVENTORY_PAGE_SIZE * INVENTORY_PAGE_COUNT,
|
||||
ABILITY_MAX_NUM = 50,
|
||||
EMPIRE_MAX_NUM = 4,
|
||||
BANWORD_MAX_LEN = 24,
|
||||
@@ -87,15 +89,15 @@ enum EMisc
|
||||
**** 현재까지 할당 된 아이템 영역 정리 (DB상 Item Position) ****
|
||||
+------------------------------------------------------+ 0
|
||||
| 캐릭터 기본 인벤토리 (45칸 * 2페이지) 90칸 |
|
||||
- +------------------------------------------------------+ 90 = INVENTORY_MAX_NUM(90)
|
||||
+ +------------------------------------------------------+ 225 = INVENTORY_MAX_NUM(225) MT: 5 pages; 40250 had 90 and every cell below moved by +135
|
||||
| 캐릭터 장비 창 (착용중인 아이템) 32칸 |
|
||||
- +------------------------------------------------------+ 122 = INVENTORY_MAX_NUM(90) + WEAR_MAX_NUM(32)
|
||||
+ +------------------------------------------------------+ 257 = INVENTORY_MAX_NUM(225) + WEAR_MAX_NUM(32)
|
||||
| 용혼석 장비 창 (착용중인 용혼석) 12칸 |
|
||||
- +------------------------------------------------------+ 134 = 122 + DS_SLOT_MAX(6) * DRAGON_SOUL_DECK_MAX_NUM(2)
|
||||
+ +------------------------------------------------------+ 269 = 257 + DS_SLOT_MAX(6) * DRAGON_SOUL_DECK_MAX_NUM(2)
|
||||
| 용혼석 장비 창 예약 (아직 미사용) 18칸 |
|
||||
- +------------------------------------------------------+ 152 = 134 + DS_SLOT_MAX(6) * DRAGON_SOUL_DECK_RESERVED_MAX_NUM(3)
|
||||
+ +------------------------------------------------------+ 287 = 269 + DS_SLOT_MAX(6) * DRAGON_SOUL_DECK_RESERVED_MAX_NUM(3)
|
||||
| 벨트 인벤토리 (벨트 착용시에만 벨트 레벨에 따라 활성)|
|
||||
- +------------------------------------------------------+ 168 = 152 + BELT_INVENTORY_SLOT_COUNT(16) = INVENTORY_AND_EQUIP_CELL_MAX
|
||||
+ +------------------------------------------------------+ 303 = 287 + BELT_INVENTORY_SLOT_COUNT(16) = INVENTORY_AND_EQUIP_CELL_MAX
|
||||
| 미사용 |
|
||||
+------------------------------------------------------+ ??
|
||||
*/
|
||||
diff --git a/server/common/tables.h b/server/common/tables.h
|
||||
index 6f7adac..8767f3d 100755
|
||||
--- a/server/common/tables.h
|
||||
+++ b/server/common/tables.h
|
||||
@@ -403,7 +403,7 @@ typedef struct SPlayerItem
|
||||
typedef struct SQuickslot
|
||||
{
|
||||
BYTE type;
|
||||
- BYTE pos;
|
||||
+ WORD pos; // MT: BYTE in 40250; belt cells are >= 256 with 5 inventory pages
|
||||
} TQuickslot;
|
||||
|
||||
typedef struct SPlayerSkill
|
||||
diff --git a/server/game/src/char.h b/server/game/src/char.h
|
||||
index 6eca64e..a6cba74 100755
|
||||
--- a/server/game/src/char.h
|
||||
+++ b/server/game/src/char.h
|
||||
@@ -395,7 +395,7 @@ typedef struct character_point_instant
|
||||
WORD parts[PART_MAX_NUM];
|
||||
|
||||
LPITEM pItems[INVENTORY_AND_EQUIP_SLOT_MAX];
|
||||
- BYTE bItemGrid[INVENTORY_AND_EQUIP_SLOT_MAX];
|
||||
+ WORD bItemGrid[INVENTORY_AND_EQUIP_SLOT_MAX]; // MT: BYTE in 40250; holds cell + 1, and cells reach 302
|
||||
|
||||
// 용혼석 인벤토리.
|
||||
LPITEM pDSItems[DRAGON_SOUL_INVENTORY_MAX_NUM];
|
||||
@@ -877,12 +877,12 @@ class CHARACTER : public CEntity, public CFSM, public CHorseRider
|
||||
|
||||
// Quickslot 관련
|
||||
public:
|
||||
- void SyncQuickslot(BYTE bType, BYTE bOldPos, BYTE bNewPos);
|
||||
+ void SyncQuickslot(BYTE bType, WORD bOldPos, WORD bNewPos);
|
||||
bool GetQuickslot(BYTE pos, TQuickslot ** ppSlot);
|
||||
bool SetQuickslot(BYTE pos, TQuickslot & rSlot);
|
||||
bool DelQuickslot(BYTE pos);
|
||||
bool SwapQuickslot(BYTE a, BYTE b);
|
||||
- void ChainQuickslotItem(LPITEM pItem, BYTE bType, BYTE bOldPos);
|
||||
+ void ChainQuickslotItem(LPITEM pItem, BYTE bType, WORD bOldPos);
|
||||
|
||||
protected:
|
||||
TQuickslot m_quickslot[QUICKSLOT_MAX_NUM];
|
||||
@@ -1120,7 +1120,7 @@ class CHARACTER : public CEntity, public CFSM, public CHorseRider
|
||||
// 착용중인 item을 벗을 수 있는 지 확인하고, 불가능 하다면 캐릭터에게 이유를 알려주는 함수
|
||||
bool CanUnequipNow(const LPITEM item, const TItemPos& srcCell = NPOS, const TItemPos& destCell = NPOS);
|
||||
|
||||
- bool SwapItem(BYTE bCell, BYTE bDestCell);
|
||||
+ bool SwapItem(WORD bCell, WORD bDestCell);
|
||||
LPITEM AutoGiveItem(DWORD dwItemVnum, BYTE bCount=1, int iRarePct = -1, bool bMsg = true);
|
||||
void AutoGiveItem(LPITEM item, bool longOwnerShip = false);
|
||||
|
||||
diff --git a/server/game/src/char_item.cpp b/server/game/src/char_item.cpp
|
||||
index 0c2403f..a77696c 100755
|
||||
--- a/server/game/src/char_item.cpp
|
||||
+++ b/server/game/src/char_item.cpp
|
||||
@@ -523,7 +523,7 @@ bool CHARACTER::IsEmptyItemGrid(TItemPos Cell, BYTE bSize, int iExceptionCell) c
|
||||
{
|
||||
case INVENTORY:
|
||||
{
|
||||
- BYTE bCell = Cell.cell;
|
||||
+ WORD bCell = Cell.cell;
|
||||
|
||||
// bItemCell은 0이 false임을 나타내기 위해 + 1 해서 처리한다.
|
||||
// 따라서 iExceptionCell에 1을 더해 비교한다.
|
||||
@@ -562,16 +562,16 @@ bool CHARACTER::IsEmptyItemGrid(TItemPos Cell, BYTE bSize, int iExceptionCell) c
|
||||
return true;
|
||||
|
||||
int j = 1;
|
||||
- BYTE bPage = bCell / (INVENTORY_MAX_NUM / 2);
|
||||
+ int bPage = bCell / INVENTORY_PAGE_SIZE;
|
||||
|
||||
do
|
||||
{
|
||||
- BYTE p = bCell + (5 * j);
|
||||
+ int p = bCell + (5 * j);
|
||||
|
||||
if (p >= INVENTORY_MAX_NUM)
|
||||
return false;
|
||||
|
||||
- if (p / (INVENTORY_MAX_NUM / 2) != bPage)
|
||||
+ if (p / INVENTORY_PAGE_SIZE != bPage)
|
||||
return false;
|
||||
|
||||
if (m_pointsInstant.bItemGrid[p])
|
||||
@@ -592,16 +592,16 @@ bool CHARACTER::IsEmptyItemGrid(TItemPos Cell, BYTE bSize, int iExceptionCell) c
|
||||
else
|
||||
{
|
||||
int j = 1;
|
||||
- BYTE bPage = bCell / (INVENTORY_MAX_NUM / 2);
|
||||
+ int bPage = bCell / INVENTORY_PAGE_SIZE;
|
||||
|
||||
do
|
||||
{
|
||||
- BYTE p = bCell + (5 * j);
|
||||
+ int p = bCell + (5 * j);
|
||||
|
||||
if (p >= INVENTORY_MAX_NUM)
|
||||
return false;
|
||||
|
||||
- if (p / (INVENTORY_MAX_NUM / 2) != bPage)
|
||||
+ if (p / INVENTORY_PAGE_SIZE != bPage)
|
||||
return false;
|
||||
|
||||
if (m_pointsInstant.bItemGrid[p])
|
||||
@@ -924,7 +924,7 @@ bool CHARACTER::DoRefine(LPITEM item, bool bMoneyOnly)
|
||||
ITEM_MANAGER::CopyAllAttrTo(item, pkNewItem);
|
||||
LogManager::instance().ItemLog(this, pkNewItem, "REFINE SUCCESS", pkNewItem->GetName());
|
||||
|
||||
- BYTE bCell = item->GetCell();
|
||||
+ WORD bCell = item->GetCell();
|
||||
|
||||
// DETAIL_REFINE_LOG
|
||||
NotifyRefineSuccess(this, item, IsRefineThroughGuild() ? "GUILD" : "POWER");
|
||||
@@ -1197,7 +1197,7 @@ bool CHARACTER::DoRefineWithScroll(LPITEM item)
|
||||
ITEM_MANAGER::CopyAllAttrTo(item, pkNewItem);
|
||||
LogManager::instance().ItemLog(this, pkNewItem, "REFINE SUCCESS", pkNewItem->GetName());
|
||||
|
||||
- BYTE bCell = item->GetCell();
|
||||
+ WORD bCell = item->GetCell();
|
||||
|
||||
NotifyRefineSuccess(this, item, szRefineType);
|
||||
DBManager::instance().SendMoneyLog(MONEY_LOG_REFINE, item->GetVnum(), -prt->cost);
|
||||
@@ -1226,7 +1226,7 @@ bool CHARACTER::DoRefineWithScroll(LPITEM item)
|
||||
ITEM_MANAGER::CopyAllAttrTo(item, pkNewItem);
|
||||
LogManager::instance().ItemLog(this, pkNewItem, "REFINE FAIL", pkNewItem->GetName());
|
||||
|
||||
- BYTE bCell = item->GetCell();
|
||||
+ WORD bCell = item->GetCell();
|
||||
|
||||
DBManager::instance().SendMoneyLog(MONEY_LOG_REFINE, item->GetVnum(), -prt->cost);
|
||||
NotifyRefineFail(this, item, szRefineType, -1);
|
||||
@@ -5982,7 +5982,7 @@ bool CHARACTER::PickupItem(DWORD dwVID)
|
||||
return false;
|
||||
}
|
||||
|
||||
-bool CHARACTER::SwapItem(BYTE bCell, BYTE bDestCell)
|
||||
+bool CHARACTER::SwapItem(WORD bCell, WORD bDestCell)
|
||||
{
|
||||
if (!CanHandleItem())
|
||||
return false;
|
||||
@@ -6034,7 +6034,7 @@ bool CHARACTER::SwapItem(BYTE bCell, BYTE bDestCell)
|
||||
if (TItemPos(EQUIPMENT, item2->GetCell()).IsEquipPosition())
|
||||
{
|
||||
BYTE bEquipCell = item2->GetCell() - INVENTORY_MAX_NUM;
|
||||
- BYTE bInvenCell = item1->GetCell();
|
||||
+ WORD bInvenCell = item1->GetCell();
|
||||
|
||||
// 착용중인 아이템을 벗을 수 있고, 착용 예정 아이템이 착용 가능한 상태여야만 진행
|
||||
if (false == CanUnequipNow(item2) || false == CanEquipNow(item1))
|
||||
@@ -6052,8 +6052,8 @@ bool CHARACTER::SwapItem(BYTE bCell, BYTE bDestCell)
|
||||
}
|
||||
else
|
||||
{
|
||||
- BYTE bCell1 = item1->GetCell();
|
||||
- BYTE bCell2 = item2->GetCell();
|
||||
+ WORD bCell1 = item1->GetCell();
|
||||
+ WORD bCell2 = item2->GetCell();
|
||||
|
||||
item1->RemoveFromCharacter();
|
||||
item2->RemoveFromCharacter();
|
||||
@@ -6182,7 +6182,7 @@ bool CHARACTER::EquipItem(LPITEM item, int iCandidateCell)
|
||||
}
|
||||
else
|
||||
{
|
||||
- BYTE bOldCell = item->GetCell();
|
||||
+ WORD bOldCell = item->GetCell();
|
||||
|
||||
if (item->EquipTo(this, iWearCell))
|
||||
{
|
||||
diff --git a/server/game/src/char_quickslot.cpp b/server/game/src/char_quickslot.cpp
|
||||
index 884cd3b..4894fbb 100755
|
||||
--- a/server/game/src/char_quickslot.cpp
|
||||
+++ b/server/game/src/char_quickslot.cpp
|
||||
@@ -9,7 +9,7 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// QUICKSLOT HANDLING
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
-void CHARACTER::SyncQuickslot(BYTE bType, BYTE bOldPos, BYTE bNewPos) // bNewPos == 255 면 DELETE
|
||||
+void CHARACTER::SyncQuickslot(BYTE bType, WORD bOldPos, WORD bNewPos) // bNewPos == 255 면 DELETE
|
||||
{
|
||||
if (bOldPos == bNewPos)
|
||||
return;
|
||||
@@ -135,7 +135,7 @@ bool CHARACTER::SwapQuickslot(BYTE a, BYTE b)
|
||||
return true;
|
||||
}
|
||||
|
||||
-void CHARACTER::ChainQuickslotItem(LPITEM pItem, BYTE bType, BYTE bOldPos)
|
||||
+void CHARACTER::ChainQuickslotItem(LPITEM pItem, BYTE bType, WORD bOldPos)
|
||||
{
|
||||
if (pItem->IsDragonSoul())
|
||||
return;
|
||||
diff --git a/server/game/src/exchange.cpp b/server/game/src/exchange.cpp
|
||||
index a59452d..c3229f0 100755
|
||||
--- a/server/game/src/exchange.cpp
|
||||
+++ b/server/game/src/exchange.cpp
|
||||
@@ -299,30 +299,27 @@ bool CExchange::Check(int * piItemCount)
|
||||
|
||||
bool CExchange::CheckSpace()
|
||||
{
|
||||
- static CGrid s_grid1(5, INVENTORY_MAX_NUM/5 / 2); // inven page 1
|
||||
- static CGrid s_grid2(5, INVENTORY_MAX_NUM/5 / 2); // inven page 2
|
||||
+ // MT: one grid per inventory page (40250 had s_grid1/s_grid2 for its 2 pages)
|
||||
+ static CGrid * s_grids[INVENTORY_PAGE_COUNT];
|
||||
|
||||
- s_grid1.Clear();
|
||||
- s_grid2.Clear();
|
||||
+ for (int page = 0; page < INVENTORY_PAGE_COUNT; ++page)
|
||||
+ {
|
||||
+ if (!s_grids[page])
|
||||
+ s_grids[page] = new CGrid(5, INVENTORY_PAGE_SIZE / 5);
|
||||
+ s_grids[page]->Clear();
|
||||
+ }
|
||||
|
||||
LPCHARACTER victim = GetCompany()->GetOwner();
|
||||
LPITEM item;
|
||||
|
||||
int i;
|
||||
|
||||
- for (i = 0; i < INVENTORY_MAX_NUM / 2; ++i)
|
||||
- {
|
||||
- if (!(item = victim->GetInventoryItem(i)))
|
||||
- continue;
|
||||
-
|
||||
- s_grid1.Put(i, 1, item->GetSize());
|
||||
- }
|
||||
- for (i = INVENTORY_MAX_NUM / 2; i < INVENTORY_MAX_NUM; ++i)
|
||||
+ for (i = 0; i < INVENTORY_MAX_NUM; ++i)
|
||||
{
|
||||
if (!(item = victim->GetInventoryItem(i)))
|
||||
continue;
|
||||
|
||||
- s_grid2.Put(i - INVENTORY_MAX_NUM / 2, 1, item->GetSize());
|
||||
+ s_grids[i / INVENTORY_PAGE_SIZE]->Put(i % INVENTORY_PAGE_SIZE, 1, item->GetSize());
|
||||
}
|
||||
|
||||
// 아... 뭔가 개병신 같지만... 용혼석 인벤을 노멀 인벤 보고 따라 만든 내 잘못이다 ㅠㅠ
|
||||
@@ -387,25 +384,21 @@ bool CExchange::CheckSpace()
|
||||
}
|
||||
else
|
||||
{
|
||||
- int iPos = s_grid1.FindBlank(1, item->GetSize());
|
||||
+ bool bPut = false;
|
||||
|
||||
- if (iPos >= 0)
|
||||
+ for (int page = 0; page < INVENTORY_PAGE_COUNT && !bPut; ++page)
|
||||
{
|
||||
- s_grid1.Put(iPos, 1, item->GetSize());
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- iPos = s_grid2.FindBlank(1, item->GetSize());
|
||||
+ int iPos = s_grids[page]->FindBlank(1, item->GetSize());
|
||||
|
||||
if (iPos >= 0)
|
||||
{
|
||||
- s_grid2.Put(iPos, 1, item->GetSize());
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- return false;
|
||||
+ s_grids[page]->Put(iPos, 1, item->GetSize());
|
||||
+ bPut = true;
|
||||
}
|
||||
}
|
||||
+
|
||||
+ if (!bPut)
|
||||
+ return false;
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/server/game/src/fishing.cpp b/server/game/src/fishing.cpp
|
||||
index b240401..20b2a21 100755
|
||||
--- a/server/game/src/fishing.cpp
|
||||
+++ b/server/game/src/fishing.cpp
|
||||
@@ -877,7 +877,7 @@ int RealRefineRod(LPCHARACTER ch, LPITEM item)
|
||||
|
||||
if (pkNewItem)
|
||||
{
|
||||
- BYTE bCell = rod->GetCell();
|
||||
+ WORD bCell = rod->GetCell();
|
||||
// 낚시대 개량 성공
|
||||
ITEM_MANAGER::instance().RemoveItem(rod, "REMOVE (REFINE FISH_ROD)");
|
||||
pkNewItem->AddToCharacter(ch, TItemPos (INVENTORY, bCell));
|
||||
@@ -895,7 +895,7 @@ int RealRefineRod(LPCHARACTER ch, LPITEM item)
|
||||
LPITEM pkNewItem = ITEM_MANAGER::instance().CreateItem(rod->GetValue(4), 1);
|
||||
if (pkNewItem)
|
||||
{
|
||||
- BYTE bCell = rod->GetCell();
|
||||
+ WORD bCell = rod->GetCell();
|
||||
// 낚시대 개량에 성공
|
||||
ITEM_MANAGER::instance().RemoveItem(rod, "REMOVE (REFINE FISH_ROD)");
|
||||
pkNewItem->AddToCharacter(ch, TItemPos(INVENTORY, bCell));
|
||||
diff --git a/server/game/src/mining.cpp b/server/game/src/mining.cpp
|
||||
index f1ea8a6..b6dd7b8 100755
|
||||
--- a/server/game/src/mining.cpp
|
||||
+++ b/server/game/src/mining.cpp
|
||||
@@ -253,7 +253,7 @@ namespace mining
|
||||
LPITEM pkNewPick = ITEM_MANAGER::instance().CreateItem(rkOldPick.GetRefinedVnum(), 1);
|
||||
if (pkNewPick)
|
||||
{
|
||||
- BYTE bCell = rkOldPick.GetCell();
|
||||
+ WORD bCell = rkOldPick.GetCell();
|
||||
rkItemMgr.RemoveItem(item, "REMOVE (REFINE PICK)");
|
||||
pkNewPick->AddToCharacter(ch, TItemPos(INVENTORY, bCell));
|
||||
LogManager::instance().ItemLog(ch, pkNewPick, "REFINE PICK SUCCESS", pkNewPick->GetName());
|
||||
@@ -270,7 +270,7 @@ namespace mining
|
||||
|
||||
if (pkNewPick)
|
||||
{
|
||||
- BYTE bCell = rkOldPick.GetCell();
|
||||
+ WORD bCell = rkOldPick.GetCell();
|
||||
rkItemMgr.RemoveItem(item, "REMOVE (REFINE PICK)");
|
||||
pkNewPick->AddToCharacter(ch, TItemPos(INVENTORY, bCell));
|
||||
rkLogMgr.ItemLog(ch, pkNewPick, "REFINE PICK FAIL", pkNewPick->GetName());
|
||||
diff --git a/server/game/src/questlua_item.cpp b/server/game/src/questlua_item.cpp
|
||||
index befc676..23200e8 100755
|
||||
--- a/server/game/src/questlua_item.cpp
|
||||
+++ b/server/game/src/questlua_item.cpp
|
||||
@@ -436,7 +436,7 @@ namespace quest
|
||||
ITEM_MANAGER::CopyAllAttrTo(pItem, pkNewItem);
|
||||
LogManager::instance().ItemLog(pChar, pkNewItem, "COPY SUCCESS", pkNewItem->GetName());
|
||||
|
||||
- BYTE bCell = pItem->GetCell();
|
||||
+ WORD bCell = pItem->GetCell();
|
||||
|
||||
ITEM_MANAGER::instance().RemoveItem(pItem, "REMOVE (COPY SUCCESS)");
|
||||
|
||||
Reference in New Issue
Block a user