LV
4
- Joined
- Jan 29, 2026
- Messages
- 103
- Reaction score
- 94
- Points
- 73
- Age
- 41
Multiple banks for the character.
Libraries\common\include\CompCommand.h
Find
C++:
#define defESPE_KBGRID_NUM 4
C++:
#define defESPE_KBGRID_NUM 4
#define defDEF_BANK0_CAPACITY defMAX_KBITEM_NUM_PER_TYPE // main bank tab
#define defDEF_BANK1_CAPACITY 0 // bank tab 2
#define defDEF_BANK2_CAPACITY 0 // bank tab 3
#define defBANK_EXPAND_STEP 6 // slots per expand item use
inline short GetDefaultBankCapacity(char chBankNO)
{
switch (chBankNO)
{
case 0: return defDEF_BANK0_CAPACITY;
case 1: return defDEF_BANK1_CAPACITY;
case 2: return defDEF_BANK2_CAPACITY;
default: return defDEF_BANK0_CAPACITY;
}
}
Server\GameServer\src\Player.h
Delete string
C++:
#define MAX_BANK_NUM 1
Find
C++:
m_CBank[i].Init();
C++:
m_CBank[i].Init(GetDefaultBankCapacity(i));
C++:
bool CPlayer::SynBank(char chBankNO, char chType)
C++:
bool CPlayer::SynBank(char chBankNO, char chType)
{
if (GetCurBankNum() == 0)
return true;
char chStart, chEnd;
if (chBankNO < 0)
{
chStart = 0;
chEnd = GetCurBankNum() - 1;
}
else
{
if (chBankNO >= GetCurBankNum())
return false;
chStart = chEnd = chBankNO;
}
for (char i = chStart; i <= chEnd; i++)
{
CKitbag* pCBank = GetBank(i);
if (!pCBank)
continue;
WPACKET WtPk = GETWPACKET();
WRITE_CMD(WtPk, CMD_MC_NOTIACTION);
WRITE_LONG(WtPk, m_pCtrlCha->GetID());
WRITE_LONG(WtPk, m_pCtrlCha->m_ulPacketID);
WRITE_CHAR(WtPk, enumACTION_BANK);
WRITE_CHAR(WtPk, i);
m_pCtrlCha->WriteKitbag(*pCBank, WtPk, chType);
m_pCtrlCha->ReflectINFof(m_pCtrlCha, WtPk);
}
return true;
}
C++:
if (!SetBankChangeFlag(0))
C++:
if (!SetBankChangeFlag(-1))
C++:
if (!SynBank(0))
C++:
if (!SynBank(-1))
C++:
bool CPlayer::BankHasItem(USHORT sItemID, USHORT& sCount)
C++:
bool CPlayer::BankHasItem(USHORT sItemID, USHORT& sCount)
{
int nCount = 0;
CItemRecord* pItem = GetItemRecordInfo( sItemID );
if( pItem == NULL )
{
SystemNotice( RES_STRING(GM_PLAYER_CPP_00013), sItemID );
return FALSE;
}
SItemGrid *pGridCont;
for (char chBank = 0; chBank < m_chBankNum; chBank++)
{
USHORT sNum = m_CBank[chBank].GetUseGridNum();
if( !pItem->GetIsPile() )
{
for( int i = 0; i < sNum; i++ )
{
pGridCont = m_CBank[chBank].GetGridContByNum( i );
if( pGridCont && sItemID == pGridCont->sID )
{
nCount++;
if( nCount >= sCount )
return true;
}
}
}
else
{
for( int i = 0; i < sNum; i++ )
{
pGridCont = m_CBank[chBank].GetGridContByNum( i );
if( pGridCont && sItemID == pGridCont->sID )
{
nCount += (USHORT)pGridCont->sNum;
if( nCount >= sCount )
return true;
}
}
}
}
return nCount >= sCount;
}
Server\GameServer\src\GameDB.cpp
Find
C++:
sprintf(g_sql, "update %s set \
bank=%s \
where atorID=%d", \
_get_table(), \
szIDBuf, \
atorID);
C++:
sprintf(g_sql, "update %s set \
bank='%s' \
where atorID=%d", \
_get_table(), \
szIDBuf, \
atorID);
C++:
if (lBankNum == 0)
if (!_tab_cha->SaveBankDBID(pPlayer))
return false;
C++:
if (lBankNum == 0)
{
if (!_tab_cha->SaveBankDBID(pPlayer))
return false;
}
// Ensure MAX_BANK_NUM banks exist (online migration for old characters)
while (pPlayer->GetCurBankNum() < MAX_BANK_NUM)
{
if (!CreatePlyBank(pPlayer))
return false;
}
Server\GameServer\src\Expand.h
Find
C++:
extern const char* GetResPath(const char *pszRes);
C++:
extern const char* GetResPath(const char *pszRes);
// Add personal bank tab capacity
// Args: character, bank index (0..MAX_BANK_NUM-1), capacity delta
// Returns: 1 success, 0 failure
inline int lua_AddBankCap(lua_State *pLS)
{
bool bSuccess = true;
#ifdef defPARSE_LOG
g_pCLogObj->Log("AddBankCap\n");
#endif
int nParaNum = lua_gettop(pLS);
if (nParaNum != 3)
{
#ifdef defPARSE_LOG
g_pCLogObj->Log("\tThe parameter numbers [%d] is unlawful,transfer failed!\n", nParaNum);
#endif
bSuccess = false;
goto End;
}
{
CCharacter* pCCha = (CCharacter*)lua_touserdata(pLS, 1);
if (!pCCha)
{
#ifdef defPARSE_LOG
g_pCLogObj->Log("\tThe character object is inexistence,transfer failed ! \n");
#endif
bSuccess = false;
goto End;
}
char chBankNO = (char)lua_tonumber(pLS, 2);
short sAddVal = (short)lua_tonumber(pLS, 3);
if (!pCCha->AddBankCapacity(chBankNO, sAddVal))
{
bSuccess = false;
goto End;
}
}
End:
if (bSuccess)
{
#ifdef defPARSE_LOG
g_pCLogObj->Log("AddBankCapSucceed\n");
#endif
lua_pushnumber(pLS, 1);
}
else
lua_pushnumber(pLS, 0);
return 1;
}
// Get personal bank tab capacity
// Args: character, bank index (0..MAX_BANK_NUM-1)
// Returns: capacity
inline int lua_GetBankCap(lua_State *pLS)
{
bool bSuccess = true;
short sCap = 0;
#ifdef defPARSE_LOG
g_pCLogObj->Log("GetBankCap\n");
#endif
int nParaNum = lua_gettop(pLS);
if (nParaNum != 2)
{
#ifdef defPARSE_LOG
g_pCLogObj->Log("\tThe parameter numbers [%d] is unlawful,transfer failed!\n", nParaNum);
#endif
bSuccess = false;
goto End;
}
{
CCharacter* pCCha = (CCharacter*)lua_touserdata(pLS, 1);
if (!pCCha)
{
#ifdef defPARSE_LOG
g_pCLogObj->Log("\tThe character object is inexistence,transfer failed ! \n");
#endif
bSuccess = false;
goto End;
}
char chBankNO = (char)lua_tonumber(pLS, 2);
sCap = pCCha->GetBankCapacity(chBankNO);
}
End:
if (bSuccess)
{
#ifdef defPARSE_LOG
g_pCLogObj->Log("GetBankCapSucceed\n");
#endif
}
lua_pushnumber(pLS, sCap);
return 1;
}
C++:
REGFN(GetKbCap);
C++:
REGFN(GetKbCap);
REGFN(AddBankCap);
REGFN(GetBankCap);
Server\GameServer\src\CharacterSuperCmd.cpp
Find
C++:
p = player->GetPlayer()->GetBank()->GetGridContByID(positionID)->SetInstAttr(ATTR_TYPE, ATTR_VALUE);
C++:
p = player->GetPlayer()->GetBank(0)->GetGridContByID(positionID)->SetInstAttr(ATTR_TYPE, ATTR_VALUE);
Server\GameServer\src\CharacterPrl.cpp
Find
C++:
case enumACTION_BANK:
{
Char chSrcType = READ_CHAR(pk);
Short sSrcGrid = READ_SHORT(pk);
Short sSrcNum = READ_SHORT(pk);
Char chTarType = READ_CHAR(pk);
Short sTarGrid = READ_SHORT(pk);
Short sRet;
sRet = Cmd_BankOper(chSrcType, sSrcGrid, sSrcNum, chTarType, sTarGrid);
if (sRet != enumITEMOPT_SUCCESS)
ItemOprateFailed(sRet);
}
break;
C++:
case enumACTION_BANK:
{
Char chSrcType = READ_CHAR(pk);
Short sSrcGrid = READ_SHORT(pk);
Short sSrcNum = READ_SHORT(pk);
Char chTarType = READ_CHAR(pk);
Short sTarGrid = READ_SHORT(pk);
Char chSrcBankNO = READ_CHAR(pk);
Char chTarBankNO = READ_CHAR(pk);
Short sRet;
sRet = Cmd_BankOper(chSrcType, sSrcGrid, sSrcNum, chTarType, sTarGrid, chSrcBankNO, chTarBankNO);
if (sRet != enumITEMOPT_SUCCESS)
ItemOprateFailed(sRet);
}
break;
Server\GameServer\src\CharacterCmd.cpp
Find
C++:
pCSrcBag = GetPlayer()->GetBank();
if (chSrcType == chTarType)
pCTarBag = pCSrcBag;
else
{
C++:
pCSrcBag = GetPlayer()->GetBank(chSrcBankNO);
C++:
pCTarBag = GetPlayer()->GetBank();
}
if (pCSrcBag->IsLock() || pCTarBag->IsLock())
return enumITEMOPT_ERROR_KBLOCK;
C++:
pCTarBag = GetPlayer()->GetBank(chTarBankNO);
if (!pCSrcBag || !pCTarBag)
return enumITEMOPT_ERROR_NONE;
if (pCSrcBag->IsLock() || pCTarBag->IsLock())
return enumITEMOPT_ERROR_KBLOCK;
C++:
return enumITEMOPT_ERROR_DISTANCE;
C++:
return enumITEMOPT_ERROR_DISTANCE;
if (chTarType == 1 && pCSrcBag != pCTarBag && pCTarBag->GetCapacity() <= 0)
{
SystemNotice("This bank tab has no open slots. Expand it with an unlock item.");
return enumITEMOPT_ERROR_KBFULL;
}
C++:
{
GetPlayer()->SynBank(0, enumSYN_KITBAG_BANK);
GetPlayer()->SetBankSaveFlag(0);
}
if (chSrcType != chTarType)
{
if (chTarType == 0)
SynKitbagNew(enumSYN_KITBAG_BANK);
else
{
GetPlayer()->SynBank(0, enumSYN_KITBAG_BANK);
GetPlayer()->SetBankSaveFlag(0);
}
}
C++:
{
GetPlayer()->SynBank(chSrcBankNO, enumSYN_KITBAG_BANK);
GetPlayer()->SetBankSaveFlag(chSrcBankNO);
}
if (chSrcType != chTarType || (chSrcType == 1 && chSrcBankNO != chTarBankNO))
{
if (chTarType == 0)
SynKitbagNew(enumSYN_KITBAG_BANK);
else
{
GetPlayer()->SynBank(chTarBankNO, enumSYN_KITBAG_BANK);
GetPlayer()->SetBankSaveFlag(chTarBankNO);
}
}
Server\GameServer\src\Character.h
Find
C++:
dbc::Short Cmd_BankOper(dbc::Char chSrcType, dbc::Short sSrcGridID, dbc::Short sSrcNum, dbc::Char chTarType, dbc::Short sTarGridID);
C++:
dbc::Short Cmd_BankOper(dbc::Char chSrcType, dbc::Short sSrcGridID, dbc::Short sSrcNum, dbc::Char chTarType, dbc::Short sTarGridID, dbc::Char chSrcBankNO = 0, dbc::Char chTarBankNO = 0);
C++:
bool AddKitbagCapacity(dbc::Short sAddVal);
C++:
bool AddKitbagCapacity(dbc::Short sAddVal);
bool AddBankCapacity(char chBankNO, dbc::Short sAddVal);
dbc::Short GetBankCapacity(char chBankNO);
Server\GameServer\src\Character.cpp
Paste after string 933
C++:
bool CCharacter::AddBankCapacity(char chBankNO, dbc::Short sAddVal)
{
CPlayer* pPlayer = GetPlayer();
if (!pPlayer)
return false;
CKitbag* pBank = pPlayer->GetBank(chBankNO);
if (!pBank)
return false;
if (sAddVal <= 0)
return false;
if (pBank->GetCapacity() >= defMAX_KBITEM_NUM_PER_TYPE)
return false;
if (!pBank->AddCapacity(sAddVal))
return false;
pPlayer->SetBankSaveFlag(chBankNO);
pPlayer->SetBankChangeFlag(chBankNO, true);
pPlayer->SynBank(chBankNO, enumSYN_KITBAG_INIT);
return true;
}
dbc::Short CCharacter::GetBankCapacity(char chBankNO)
{
CPlayer* pPlayer = GetPlayer();
if (!pPlayer)
return 0;
CKitbag* pBank = pPlayer->GetBank(chBankNO);
if (!pBank)
return 0;
return pBank->GetCapacity();
}
Client\src\UIGuildBankForm.cpp
Find
C++:
m_kNetBank.chSrcType = EQUIP_TYPE;
C++:
m_kNetBank.chSrcType = 0;
C++:
m_kNetBank.chTarType = BANK_TYPE;
m_kNetBank.sTarID = nGridID;
C++:
m_kNetBank.chTarType = 1;
m_kNetBank.sTarID = nGridID;
m_kNetBank.chSrcBankNO = 0;
m_kNetBank.chTarBankNO = 0;
C++:
m_kNetBank.chTarType = EQUIP_TYPE;
m_kNetBank.sTarID = nGridID;
C++:
m_kNetBank.chTarType = EQUIP_TYPE;
m_kNetBank.sTarID = nGridID;
m_kNetBank.chSrcBankNO = 0;
m_kNetBank.chTarBankNO = 0;
Client\src\UIGoodsGrid.cpp
Find
C++:
#include "packetcmd.h"
C++:
#include "packetcmd.h"
#include "UIBankForm.h"
C++:
CCompent* p = form->GetHitCommand( x, y );
if( !p ) return;
C++:
CCompent* p = form->GetHitCommand( x, y );
if( !p )
{
g_stUIBank.TryAcceptDropOnTab(this, x, y, _nDragIndex);
return;
}
C++:
case enumRefuse:
break;
}
C++:
case enumRefuse:
g_stUIBank.TryAcceptDropOnTab(this, x, y, _nDragIndex);
break;
}
Client\src\UIGlobalVar.cpp
Find
C++:
&& pDrag == g_stUIBank.GetBankGoodsGrid())
C++:
&& g_stUIBank.IsBankGrid(pDrag))
C++:
if ( pSelf == g_stUIBank.GetBankGoodsGrid()
&& pDrag == g_stUIEquip.GetGoodsGrid())
{
g_stUIBank.PushToBank(*pDrag, *pSelf, nGridID, *pItem);
}
C++:
if ( g_stUIBank.IsBankGrid(pSelf)
&& pDrag == g_stUIEquip.GetGoodsGrid())
{
g_stUIBank.PushToBank(*pDrag, *pSelf, nGridID, *pItem);
}
// Bank tab -> bank tab
if ( g_stUIBank.IsBankGrid(pSelf)
&& g_stUIBank.IsBankGrid(pDrag)
&& pSelf != pDrag )
{
g_stUIBank.BankToBank(*pDrag, *pSelf, nGridID, *pItem);
}
Client\src\UIBankForm.h
Replace the entire file
C++:
//--------------------------------------------------------------
// Bank UI manager (multi-tab personal bank)
//--------------------------------------------------------------
#pragma once
#include "UIGlobalVar.h"
#include "NetProtocol.h"
#include "CompCommand.h"
namespace GUI
{
class CForm;
class CGoodsGrid;
class CItemCommand;
class CLabel;
class CPage;
class CGuiData;
struct stNumBox;
class CBankMgr : public CUIInterface
{
public:
void ShowBank();
CGoodsGrid* GetBankGoodsGrid(char chBankNO = -1);
bool IsBankGrid(CGoodsGrid* pGrid) const;
char GetBankNO(CGoodsGrid* pGrid) const;
char GetActiveBankNO() const { return m_chActiveBankNO; }
bool PushToBank(CGoodsGrid& rkDrag, CGoodsGrid& rkSelf, int nGridID, CCommandObj& rkItem);
bool PopFromBank(CGoodsGrid& rkDrag, CGoodsGrid& rkSelf, int nGridID, CCommandObj& rkItem);
bool BankToBank(CGoodsGrid& rkDrag, CGoodsGrid& rkSelf, int nGridID, CCommandObj& rkItem);
/** Drop item onto a bank tab title: move into that tab's first free slot. */
bool TryAcceptDropOnTab(CGoodsGrid* pSrc, int x, int y, int nSrcIndex);
protected:
virtual bool Init();
virtual void CloseForm();
private:
static void _MoveItemsEvent(CCompent *pSender, int nMsgType, int x, int y, DWORD dwKey);
static void _MoveAItemEvent(CCompent *pSender, int nMsgType, int x, int y, DWORD dwKey);
static void _evtBankToBank(CGuiData *pSender, int nFirst, int nSecond, bool& isSwap);
static void _evtOnClose(CForm* pForm, bool& IsClose);
static void _evtSelectPage(CGuiData *pSender);
void _SyncGridVisibility();
char HitBankTabTitle(int x, int y) const;
int FindFreeBankSlot(char chBankNO) const;
bool _IsBannedBankItem(CItemCommand* pkItemCmd) const;
private:
stNumBox* m_pkNumberBox;
stNetBank m_kNetBank;
CForm* frmBank;
CPage* pgeBank;
CGoodsGrid* grdBanks[MAX_BANK_NUM];
CGuiData* labBankTabs[MAX_BANK_NUM];
CLabel* labCharName;
char m_chActiveBankNO;
};
} // namespace GUI
Client\src\UIBankForm.cpp
Replace the entire file
C++:
#include "StdAfx.h"
#include "UIBankForm.h"
#include "uiform.h"
#include "uilabel.h"
#include "uiformmgr.h"
#include "uigoodsgrid.h"
#include "NetProtocol.h"
#include "uiboxform.h"
#include "uiEquipForm.h"
#include "UIGoodsGrid.h"
#include "uiItemCommand.h"
#include "uiform.h"
#include "uiBoatForm.h"
#include "packetcmd.h"
#include "Character.h"
#include "GameApp.h"
#include "UIPage.h"
#include "uiimage.h"
namespace GUI
{
bool CBankMgr::Init()
{
CFormMgr &mgr = CFormMgr::s_Mgr;
frmBank = mgr.Find("frmNPCstorage");
if ( !frmBank)
{
LG("gui", g_oLangRec.GetString(438));
return false;
}
frmBank->evtClose = _evtOnClose;
for (int i = 0; i < MAX_BANK_NUM; i++)
{
grdBanks[i] = nullptr;
labBankTabs[i] = nullptr;
}
m_chActiveBankNO = 0;
memset(&m_kNetBank, 0, sizeof(m_kNetBank));
m_pkNumberBox = nullptr;
pgeBank = dynamic_cast<CPage*>(frmBank->Find("pgeBank"));
if (pgeBank)
{
pgeBank->evtSelectPage = _evtSelectPage;
}
char szGridName[32];
char szLabName[32];
for (int i = 0; i < MAX_BANK_NUM; i++)
{
sprintf(szGridName, "grdNPCstorage%d", i);
grdBanks[i] = dynamic_cast<CGoodsGrid*>(frmBank->Find(szGridName));
if (!grdBanks[i])
{
// Legacy single-grid NPC.clu fallback
if (i == 0)
{
grdBanks[0] = dynamic_cast<CGoodsGrid*>(frmBank->Find("grdNPCstorage"));
}
if (!grdBanks[i])
{
return Error(g_oLangRec.GetString(439), frmBank->GetName(), szGridName);
}
}
grdBanks[i]->evtBeforeAccept = CUIInterface::_evtDragToGoodsEvent;
grdBanks[i]->evtSwapItem = _evtBankToBank;
sprintf(szLabName, "labBankTab%d", i);
labBankTabs[i] = frmBank->Find(szLabName);
}
labCharName = dynamic_cast<CLabel*>(frmBank->Find("labOwnerName"));
if (!labCharName)
{
return Error(g_oLangRec.GetString(439), frmBank->GetName(), "labOwnerName");
}
// Grids stay in form._mouse after UI_AddCompent; hide inactive so hit-test
// (GetHitCommand) does not always pick grdNPCstorage0.
_SyncGridVisibility();
return true;
}
void CBankMgr::_SyncGridVisibility()
{
for (int i = 0; i < MAX_BANK_NUM; i++)
{
if (grdBanks[i])
{
grdBanks[i]->SetIsShow(i == m_chActiveBankNO);
}
}
}
CGoodsGrid* CBankMgr::GetBankGoodsGrid(char chBankNO)
{
if (chBankNO < 0)
{
chBankNO = m_chActiveBankNO;
}
if (chBankNO < 0 || chBankNO >= MAX_BANK_NUM)
{
return nullptr;
}
return grdBanks[chBankNO];
}
bool CBankMgr::IsBankGrid(CGoodsGrid* pGrid) const
{
if (!pGrid)
{
return false;
}
for (int i = 0; i < MAX_BANK_NUM; i++)
{
if (grdBanks[i] == pGrid)
{
return true;
}
}
return false;
}
char CBankMgr::GetBankNO(CGoodsGrid* pGrid) const
{
for (int i = 0; i < MAX_BANK_NUM; i++)
{
if (grdBanks[i] == pGrid)
{
return static_cast<char>(i);
}
}
return -1;
}
void CBankMgr::_evtSelectPage(CGuiData *pSender)
{
CPage* pPage = dynamic_cast<CPage*>(pSender);
if (!pPage)
{
return;
}
int nIndex = pPage->GetIndex();
if (nIndex >= 0 && nIndex < MAX_BANK_NUM)
{
g_stUIBank.m_chActiveBankNO = static_cast<char>(nIndex);
g_stUIBank._SyncGridVisibility();
}
}
void CBankMgr::_evtOnClose( CForm* pForm, bool& IsClose )
{
CS_BeginAction(g_stUIBoat.GetHuman(), enumACTION_CLOSE_BANK, NULL);
CFormMgr::s_Mgr.SetEnableHotKey(HOTKEY_BANK, true);
}
void CBankMgr::ShowBank()
{
if (!g_stUIBoat.GetHuman())
return;
char szBuf[32];
sprintf(szBuf, "%s%s", g_stUIBoat.GetHuman()->getName(), g_oLangRec.GetString(440));
labCharName->SetCaption(szBuf);
if (pgeBank)
{
pgeBank->SetIndex(m_chActiveBankNO);
}
_SyncGridVisibility();
frmBank->Show();
if (!g_stUIEquip.GetItemForm()->GetIsShow())
{
int nLeft = frmBank->GetX2();
int nTop = frmBank->GetY();
g_stUIEquip.GetItemForm()->SetPos(nLeft, nTop);
g_stUIEquip.GetItemForm()->Refresh();
g_stUIEquip.GetItemForm()->Show();
}
CFormMgr::s_Mgr.SetEnableHotKey(HOTKEY_BANK, false);
}
bool CBankMgr::PushToBank(CGoodsGrid& rkDrag, CGoodsGrid& rkSelf, int nGridID, CCommandObj& rkItem)
{
// Always use the visible tab: form hit-test can return a hidden sibling grid.
const char chBankNO = m_chActiveBankNO;
if (chBankNO < 0 || chBankNO >= MAX_BANK_NUM)
{
return false;
}
CGoodsGrid* pBankGrid = GetBankGoodsGrid(chBankNO);
if (!pBankGrid)
{
return false;
}
CItemCommand* pTarItem = dynamic_cast<CItemCommand*>(pBankGrid->GetItem(nGridID));
if (pTarItem && pTarItem->GetItemInfo() && pTarItem->GetItemInfo()->lID == 32767)
{
g_pGameApp->SysInfo("This bank slot is locked. Expand the tab first.");
return false;
}
m_kNetBank.chSrcType = 0;
m_kNetBank.sSrcID = rkDrag.GetDragIndex();
m_kNetBank.chTarType = 1;
m_kNetBank.sTarID = nGridID;
m_kNetBank.chSrcBankNO = 0;
m_kNetBank.chTarBankNO = chBankNO;
CItemCommand* pkItemCmd = dynamic_cast<CItemCommand*>(&rkItem);
if (!pkItemCmd) return false;
CItemRecord* pkItemRecord = pkItemCmd->GetItemInfo();
if (!pkItemRecord) return false;
if( pkItemRecord->lID == 2520 || pkItemRecord->lID == 2521 || pkItemRecord->lID == 6341 || pkItemRecord->lID == 6343
|| pkItemRecord->lID == 6347 || pkItemRecord->lID == 6359 || pkItemRecord->lID == 6370 || pkItemRecord->lID == 6371
|| pkItemRecord->lID == 6373 || pkItemRecord->lID >= 6376 && pkItemRecord->lID <= 6378
|| pkItemRecord->lID >= 6383 && pkItemRecord->lID <= 6385 )
{
g_pGameApp->MsgBox(g_oLangRec.GetString(958));
return false;
}
if ( pkItemCmd->GetItemInfo()->GetIsPile() && pkItemCmd->GetTotalNum() > 1 )
{
m_pkNumberBox =
g_stUIBox.ShowNumberBox(_MoveItemsEvent, pkItemCmd->GetTotalNum(), g_oLangRec.GetString(441), false);
if (m_pkNumberBox->GetNumber() < pkItemCmd->GetTotalNum())
return false;
else
return true;
}
else
{
g_stUIBank.m_kNetBank.sSrcNum = 1;
CS_BeginAction(g_stUIBoat.GetHuman(), enumACTION_BANK, (void*)&(g_stUIBank.m_kNetBank));
return true;
}
}
bool CBankMgr::PopFromBank(CGoodsGrid& rkDrag, CGoodsGrid& rkSelf, int nGridID, CCommandObj& rkItem)
{
const char chBankNO = m_chActiveBankNO;
if (chBankNO < 0 || chBankNO >= MAX_BANK_NUM)
{
return false;
}
m_kNetBank.chSrcType = 1;
m_kNetBank.sSrcID = rkDrag.GetDragIndex();
m_kNetBank.chTarType = 0;
m_kNetBank.sTarID = nGridID;
m_kNetBank.chSrcBankNO = chBankNO;
m_kNetBank.chTarBankNO = 0;
CItemCommand* pkItemCmd = dynamic_cast<CItemCommand*>(&rkItem);
if (!pkItemCmd) return false;
if ( pkItemCmd->GetItemInfo()->GetIsPile() && pkItemCmd->GetTotalNum() > 1 )
{
m_pkNumberBox =
g_stUIBox.ShowNumberBox( _MoveItemsEvent, pkItemCmd->GetTotalNum(), g_oLangRec.GetString(442), false);
if (m_pkNumberBox->GetNumber() < pkItemCmd->GetTotalNum())
return false;
else
return true;
}
else
{
g_stUIBank.m_kNetBank.sSrcNum = 1;
CS_BeginAction(g_stUIBoat.GetHuman(), enumACTION_BANK, (void*)&(g_stUIBank.m_kNetBank));
return true;
}
}
void CBankMgr::_MoveItemsEvent(CCompent *pSender, int nMsgType, int x, int y, DWORD dwKey)
{
if(nMsgType != CForm::mrYes)
return;
int num = g_stUIBank.m_pkNumberBox->GetNumber();
if ( num > 0 )
{
g_stUIBank.m_kNetBank.sSrcNum = num;
CS_BeginAction(g_stUIBoat.GetHuman(), enumACTION_BANK, (void*)&(g_stUIBank.m_kNetBank));
}
}
void CBankMgr::_MoveAItemEvent(CCompent *pSender, int nMsgType, int x, int y, DWORD dwKey)
{
if(nMsgType != CForm::mrYes)
return;
g_stUIBank.m_kNetBank.sSrcNum = 1;
CS_BeginAction(g_stUIBoat.GetHuman(), enumACTION_BANK, (void*)&(g_stUIBank.m_kNetBank));
}
void CBankMgr::CloseForm()
{
if (frmBank->GetIsShow())
{
frmBank->Close();
g_stUIEquip.GetItemForm()->Close();
}
}
void CBankMgr::_evtBankToBank(CGuiData *pSender,int nFirst, int nSecond, bool& isSwap)
{
isSwap = false;
if( !g_stUIBoat.GetHuman() ) return;
const char chBankNO = g_stUIBank.m_chActiveBankNO;
if (chBankNO < 0 || chBankNO >= MAX_BANK_NUM)
{
return;
}
CGoodsGrid* pGrid = g_stUIBank.GetBankGoodsGrid(chBankNO);
if (pGrid)
{
CItemCommand* pFirst = dynamic_cast<CItemCommand*>(pGrid->GetItem(nFirst));
CItemCommand* pSecond = dynamic_cast<CItemCommand*>(pGrid->GetItem(nSecond));
if ((pFirst && pFirst->GetItemInfo() && pFirst->GetItemInfo()->lID == 32767)
|| (pSecond && pSecond->GetItemInfo() && pSecond->GetItemInfo()->lID == 32767))
{
g_pGameApp->SysInfo("This bank slot is locked. Expand the tab first.");
return;
}
}
g_stUIBank.m_kNetBank.chSrcType = 1;
g_stUIBank.m_kNetBank.sSrcID = nSecond;
g_stUIBank.m_kNetBank.sSrcNum = 0;
g_stUIBank.m_kNetBank.chTarType = 1;
g_stUIBank.m_kNetBank.sTarID = nFirst;
g_stUIBank.m_kNetBank.chSrcBankNO = chBankNO;
g_stUIBank.m_kNetBank.chTarBankNO = chBankNO;
CS_BeginAction(g_stUIBoat.GetHuman(), enumACTION_BANK, (void*)&(g_stUIBank.m_kNetBank));
}
bool CBankMgr::BankToBank(CGoodsGrid& rkDrag, CGoodsGrid& rkSelf, int nGridID, CCommandObj& rkItem)
{
const char chSrcBankNO = GetBankNO(&rkDrag);
const char chTarBankNO = GetBankNO(&rkSelf);
if (chSrcBankNO < 0 || chTarBankNO < 0)
{
return false;
}
CItemCommand* pTarItem = dynamic_cast<CItemCommand*>(rkSelf.GetItem(nGridID));
if (pTarItem && pTarItem->GetItemInfo() && pTarItem->GetItemInfo()->lID == 32767)
{
g_pGameApp->SysInfo("This bank slot is locked. Expand the tab first.");
return false;
}
m_kNetBank.chSrcType = 1;
m_kNetBank.sSrcID = rkDrag.GetDragIndex();
m_kNetBank.sSrcNum = 1;
m_kNetBank.chTarType = 1;
m_kNetBank.sTarID = nGridID;
m_kNetBank.chSrcBankNO = chSrcBankNO;
m_kNetBank.chTarBankNO = chTarBankNO;
CItemCommand* pkItemCmd = dynamic_cast<CItemCommand*>(&rkItem);
if (!pkItemCmd) return false;
if ( pkItemCmd->GetItemInfo()->GetIsPile() && pkItemCmd->GetTotalNum() > 1 )
{
m_pkNumberBox =
g_stUIBox.ShowNumberBox( _MoveItemsEvent, pkItemCmd->GetTotalNum(), g_oLangRec.GetString(442), false);
if (m_pkNumberBox->GetNumber() < pkItemCmd->GetTotalNum())
return false;
return true;
}
CS_BeginAction(g_stUIBoat.GetHuman(), enumACTION_BANK, (void*)&m_kNetBank);
return true;
}
bool CBankMgr::_IsBannedBankItem(CItemCommand* pkItemCmd) const
{
if (!pkItemCmd)
{
return true;
}
CItemRecord* pkItemRecord = pkItemCmd->GetItemInfo();
if (!pkItemRecord)
{
return true;
}
const long id = pkItemRecord->lID;
if (id == 2520 || id == 2521 || id == 6341 || id == 6343
|| id == 6347 || id == 6359 || id == 6370 || id == 6371
|| id == 6373 || (id >= 6376 && id <= 6378)
|| (id >= 6383 && id <= 6385))
{
return true;
}
return false;
}
char CBankMgr::HitBankTabTitle(int x, int y) const
{
if (!frmBank || !frmBank->GetIsShow())
{
return -1;
}
if (pgeBank)
{
for (int i = 0; i < MAX_BANK_NUM; i++)
{
CPageItem* pItem = pgeBank->GetPage(static_cast<unsigned int>(i));
if (!pItem)
{
continue;
}
CImage* pTitle = pItem->GetTitle();
if (pTitle && pTitle->InRect(x, y))
{
return static_cast<char>(i);
}
}
}
for (int i = 0; i < MAX_BANK_NUM; i++)
{
if (labBankTabs[i] && labBankTabs[i]->InRect(x, y))
{
return static_cast<char>(i);
}
}
return -1;
}
int CBankMgr::FindFreeBankSlot(char chBankNO) const
{
CGoodsGrid* pGrid = nullptr;
if (chBankNO < 0 || chBankNO >= MAX_BANK_NUM)
{
return -1;
}
pGrid = grdBanks[chBankNO];
if (!pGrid)
{
return -1;
}
const int nMax = pGrid->GetMaxNum();
for (int i = 0; i < nMax; i++)
{
CCommandObj* pCmd = pGrid->GetItem(static_cast<unsigned int>(i));
if (!pCmd)
{
return i;
}
CItemCommand* pItem = dynamic_cast<CItemCommand*>(pCmd);
if (pItem && pItem->GetItemInfo() && pItem->GetItemInfo()->lID == 32767)
{
continue;
}
}
return -1;
}
bool CBankMgr::TryAcceptDropOnTab(CGoodsGrid* pSrc, int x, int y, int nSrcIndex)
{
if (!pSrc || !frmBank || !frmBank->GetIsShow() || !g_stUIBoat.GetHuman())
{
return false;
}
if (nSrcIndex < 0)
{
return false;
}
const char chTarBankNO = HitBankTabTitle(x, y);
if (chTarBankNO < 0 || chTarBankNO >= MAX_BANK_NUM)
{
return false;
}
CGoodsGrid* pInv = g_stUIEquip.GetGoodsGrid();
const bool bFromInv = (pSrc == pInv);
const bool bFromBank = IsBankGrid(pSrc);
if (!bFromInv && !bFromBank)
{
return false;
}
char chSrcBankNO = 0;
if (bFromBank)
{
chSrcBankNO = GetBankNO(pSrc);
if (chSrcBankNO < 0)
{
return false;
}
if (chSrcBankNO == chTarBankNO)
{
return false;
}
}
CItemCommand* pkItemCmd = dynamic_cast<CItemCommand*>(pSrc->GetItem(static_cast<unsigned int>(nSrcIndex)));
if (!pkItemCmd)
{
return false;
}
if (bFromInv && _IsBannedBankItem(pkItemCmd))
{
g_pGameApp->MsgBox(g_oLangRec.GetString(958));
return true; // consumed drop (ban message), do not throw
}
const int nFree = FindFreeBankSlot(chTarBankNO);
if (nFree < 0)
{
g_pGameApp->SysInfo("This bank tab has no open slots.");
return true;
}
if (bFromInv)
{
m_kNetBank.chSrcType = 0;
m_kNetBank.chSrcBankNO = 0;
m_kNetBank.chTarType = 1;
m_kNetBank.chTarBankNO = chTarBankNO;
}
else
{
m_kNetBank.chSrcType = 1;
m_kNetBank.chSrcBankNO = chSrcBankNO;
m_kNetBank.chTarType = 1;
m_kNetBank.chTarBankNO = chTarBankNO;
}
m_kNetBank.sSrcID = static_cast<short>(nSrcIndex);
m_kNetBank.sTarID = static_cast<short>(nFree);
if (pkItemCmd->GetItemInfo()->GetIsPile() && pkItemCmd->GetTotalNum() > 1)
{
const char* pszTip = bFromInv ? g_oLangRec.GetString(441) : g_oLangRec.GetString(442);
m_pkNumberBox =
g_stUIBox.ShowNumberBox(_MoveItemsEvent, pkItemCmd->GetTotalNum(), pszTip, false);
if (m_pkNumberBox->GetNumber() < pkItemCmd->GetTotalNum())
{
return true;
}
return true;
}
m_kNetBank.sSrcNum = 1;
CS_BeginAction(g_stUIBoat.GetHuman(), enumACTION_BANK, (void*)&m_kNetBank);
return true;
}
}
Client\src\ProCirculateCS.cpp
Find
C++:
case enumACTION_BANK:
{
stNetBank *pNetBank = (stNetBank *)param;
pk.WriteChar(pNetBank->chSrcType);
pk.WriteShort(pNetBank->sSrcID);
pk.WriteShort(pNetBank->sSrcNum);
pk.WriteChar(pNetBank->chTarType);
pk.WriteShort(pNetBank->sTarID);
pCNetIf->SendPacketMessage(pk);
LG(szLogName, "###Send(Bank Req):\tTick:[%d]\n", GetTickCount());
LG(szLogName, "\n");
break;
}
C++:
case enumACTION_BANK:
{
stNetBank *pNetBank = (stNetBank *)param;
pk.WriteChar(pNetBank->chSrcType);
pk.WriteShort(pNetBank->sSrcID);
pk.WriteShort(pNetBank->sSrcNum);
pk.WriteChar(pNetBank->chTarType);
pk.WriteShort(pNetBank->sTarID);
pk.WriteChar(pNetBank->chSrcBankNO);
pk.WriteChar(pNetBank->chTarBankNO);
pCNetIf->SendPacketMessage(pk);
LG(szLogName, "###Send(Bank Req):\tTick:[%d]\n", GetTickCount());
LG(szLogName, "\n");
break;
}
Client\src\PacketCmd_SC.cpp
Find
C++:
case enumACTION_BANK:
{
stNetKitbag SKitbag;
ReadChaKitbagPacket(pk, SKitbag, szLogName);
SKitbag.chBagType = 1;
NetChangeKitbag(l_id, SKitbag);
}
C++:
case enumACTION_BANK:
{
char chBankNO = pk.ReadChar();
stNetKitbag SKitbag;
ReadChaKitbagPacket(pk, SKitbag, szLogName);
SKitbag.chBagType = 1;
SKitbag.chBankNO = chBankNO;
NetChangeKitbag(l_id, SKitbag);
}
Client\src\NetProtocol.h
Find
C++:
struct stNetKitbag
{
char chBagType;
char chType;
int nKeybagNum;
struct stGrid
{
short sGridID;
SItemGrid SGridContent;
};
int nGridNum;
stGrid Grid[defMAX_KBITEM_NUM_PER_TYPE];
};
C++:
struct stNetKitbag
{
char chBagType;
char chBankNO;
char chType;
int nKeybagNum;
struct stGrid
{
short sGridID;
SItemGrid SGridContent;
};
int nGridNum;
stGrid Grid[defMAX_KBITEM_NUM_PER_TYPE];
};
Client\src\NetProtocol.cpp
Find
C++:
case 1:
grd = g_stUIBank.GetBankGoodsGrid();
C++:
case 1:
grd = g_stUIBank.GetBankGoodsGrid(SKitbag.chBankNO);
C++:
case enumSYN_KITBAG_INIT:
{
//todo
if(SKitbag.chBagType == 0){
C++:
case enumSYN_KITBAG_INIT:
{
if(SKitbag.chBagType == 0 || SKitbag.chBagType == 1){
C++:
case enumSYN_KITBAG_INIT:
if (SKitbag.chBagType == 1)
C++:
case enumSYN_KITBAG_INIT:
if (SKitbag.chBagType == 1 && SKitbag.chBankNO == 0)
C++:
void NetKitbagLockedSpaces(short slots,CGoodsGrid* grd){
C++:
void NetKitbagLockedSpaces(short slots,CGoodsGrid* grd){
int lockedID = 32767;
CItemRecord* blankItem = GetItemRecordInfo( lockedID );
if(!grd || !blankItem){
return;
}
const int maxSlots = 48;
if(slots < 0){
slots = 0;
}
if(slots > maxSlots){
slots = maxSlots;
}
grd->Clear();
grd->SetContent( 8, 6 );
grd->Init();
grd->Refresh();
for (int index = slots; index < maxSlots; index++){
CItemCommand* pObj = new CItemCommand( blankItem );
pObj->SetCanDrag(false);
grd->SetItem( index, pObj );
}
}
server\GameServer\resource\ItemInfo.txt
Client\scripts\table\iteminfo.txt
C++:
15410 2 Bank Slot n1320_2 10130005 0 0 0 0 0 00 31 0 0 0 0 0 1 1 1 1 1 0 100 -1 0 -1 0 0 -1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0 0 0,0 0 0 0 0 0 0 0 0 0 BankTab2Slot 0 0 0 0 0 0 Increases the second bank tab by 6 cells. 1
15411 3 Bank Slot n1321_2 10130005 0 0 0 0 0 00 31 0 0 0 0 0 1 1 1 1 1 0 100 -1 0 -1 0 0 -1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0 0 0,0 0 0 0 0 0 0 0 0 0 BankTab3Slot 0 0 0 0 0 0 Increases the third bank tab by 6 cells. 1
server\GameServer\resource\script\calculate\ItemEffect.lua
C++:
-- Bank tab 2 expand (+6 slots per use, chBankNO = 1). Wire ItemInfo szEffect to BankTab2Slot.
function BankTab2Slot(role, Item)
local Cha_Boat = GetCtrlBoat(role)
if Cha_Boat ~= nil then
SystemNotice(role, "Cannot use while sailing!")
UseItemFailed(role)
return
end
role = TurnToCha(role)
local cap = GetBankCap(role, 1)
if cap >= 48 then
SystemNotice(role, "Bank tab 2 is already fully expanded!")
UseItemFailed(role)
return
end
if AddBankCap(role, 1, 6) ~= 1 then
SystemNotice(role, "Failed to expand bank tab 2!")
UseItemFailed(role)
return
end
end
-- Bank tab 3 expand (+6 slots per use, chBankNO = 2). Wire ItemInfo szEffect to BankTab3Slot.
function BankTab3Slot(role, Item)
local Cha_Boat = GetCtrlBoat(role)
if Cha_Boat ~= nil then
SystemNotice(role, "Cannot use while sailing!")
UseItemFailed(role)
return
end
role = TurnToCha(role)
local cap = GetBankCap(role, 2)
if cap >= 48 then
SystemNotice(role, "Bank tab 3 is already fully expanded!")
UseItemFailed(role)
return
end
if AddBankCap(role, 2, 6) ~= 1 then
SystemNotice(role, "Failed to expand bank tab 3!")
UseItemFailed(role)
return
end
end
Client\scripts\lua\forms\NPC.clu
Find form
C++:
frmNPCstorage
C++:
frmNPCstorage = UI_CreateForm( "frmNPCstorage", FALSE, 242, 400, 100, 100, TRUE, FALSE )
UI_ShowForm( frmNPCstorage, TRUE )
UI_AddFormToTemplete( frmNPCstorage, FORM_MAIN )
UI_SetIsDrag( frmNPCstorage, TRUE )
imgBakTop = UI_CreateCompent( frmNPCstorage, IMAGE_TYPE, "imgBakTop", 242, 400, 0, 0 )
UI_LoadImage( imgBakTop, "texture/ui/corsairs/bankform48.png", NORMAL, 242, 400, 0, 0 )
labTitle = UI_CreateCompent( frmNPCstorage, LABELEX_TYPE, "labTitle", 40, 12, 10, 2 )
UI_SetCaption( labTitle, "Bank")
UI_SetTextColor( labTitle, COLOR_BLACK )
UI_SetLabelExFont( labTitle, DEFAULT_FONT, TRUE, COLOR_WHITE )
btnClose = UI_CreateCompent( frmNPCstorage, BUTTON_TYPE, "btnClose", 14, 14, 225, 1 )
UI_LoadButtonImage( btnClose, "texture/ui/PublicC.tga", 14, 14, 116, 175, TRUE )
UI_SetButtonModalResult( btnClose, BUTTON_CLOSE )
labOwnerName = UI_CreateCompent( frmNPCstorage, LABELEX_TYPE, "labOwnerName", 100, 12, 50, 2 )
UI_SetCaption( labOwnerName, "" )
UI_SetTextColor( labOwnerName, COLOR_BLACK )
UI_SetLabelExFont( labOwnerName, DEFAULT_FONT, TRUE, COLOR_WHITE )
-- Grids: local (0,0); after UI_AddCompent parent is page at (17,55)
-- Height 280: 8 rows * (32 unit + 3 space) so all locked slots render (277 only fits 7 rows)
grdNPCstorage0 = UI_CreateCompent( frmNPCstorage, GOODS_GRID_TYPE, "grdNPCstorage0", 207, 280, 0, 0 )
UI_SetGridSpace( grdNPCstorage0, 3, 3 )
UI_SetGridContent( grdNPCstorage0, 8, 6 )
UI_SetGridUnitSize( grdNPCstorage0, 32, 32 )
UI_SetMargin( grdNPCstorage0, 0, 0, 0, 0 )
grdNPCstorage1 = UI_CreateCompent( frmNPCstorage, GOODS_GRID_TYPE, "grdNPCstorage1", 207, 280, 0, 0 )
UI_SetGridSpace( grdNPCstorage1, 3, 3 )
UI_SetGridContent( grdNPCstorage1, 8, 6 )
UI_SetGridUnitSize( grdNPCstorage1, 32, 32 )
UI_SetMargin( grdNPCstorage1, 0, 0, 0, 0 )
grdNPCstorage2 = UI_CreateCompent( frmNPCstorage, GOODS_GRID_TYPE, "grdNPCstorage2", 207, 280, 0, 0 )
UI_SetGridSpace( grdNPCstorage2, 3, 3 )
UI_SetGridContent( grdNPCstorage2, 8, 6 )
UI_SetGridUnitSize( grdNPCstorage2, 32, 32 )
UI_SetMargin( grdNPCstorage2, 0, 0, 0, 0 )
-- Page frame = exact white grid area on bankform48.png
pgeBank = UI_CreateCompent( frmNPCstorage, PAGE_TYPE, "pgeBank", 207, 280, 17, 55 )
UI_SetPageButton( pgeBank, PAGE_BUTTON_CUSTOM, 48, 18 )
-- Tab sprites live in bankform48 atlas (right margin), ivntab-style
local tabTex = "texture/ui/corsairs/bankform48.png"
local tabAtlasX = 242
local tabW = 51
local tabH = 28
local tabX = 4
local tabXoff = 54
local tabY = -38
itemid = UI_CreatePageItem( pgeBank )
ttlBank0 = UI_GetPageItemObj( itemid, PAGE_ITEM_TITLE )
UI_LoadImage( ttlBank0, tabTex, PAGE_ITEM_TITLE_ACTIVE, tabW, tabH, tabAtlasX, 0 )
UI_LoadImage( ttlBank0, tabTex, PAGE_ITEM_TITLE_NORMAL, tabW, tabH, tabAtlasX + tabW - 1, 0 )
UI_SetPos( ttlBank0, tabX, tabY )
UI_SetSize( ttlBank0, tabW, tabH )
UI_AddCompent( itemid, grdNPCstorage0 )
itemid = UI_CreatePageItem( pgeBank )
ttlBank1 = UI_GetPageItemObj( itemid, PAGE_ITEM_TITLE )
UI_LoadImage( ttlBank1, tabTex, PAGE_ITEM_TITLE_ACTIVE, tabW, tabH, tabAtlasX, 0 )
UI_LoadImage( ttlBank1, tabTex, PAGE_ITEM_TITLE_NORMAL, tabW, tabH, tabAtlasX + tabW - 1, 0 )
UI_SetPos( ttlBank1, tabX + tabXoff, tabY )
UI_SetSize( ttlBank1, tabW, tabH )
UI_AddCompent( itemid, grdNPCstorage1 )
itemid = UI_CreatePageItem( pgeBank )
ttlBank2 = UI_GetPageItemObj( itemid, PAGE_ITEM_TITLE )
UI_LoadImage( ttlBank2, tabTex, PAGE_ITEM_TITLE_ACTIVE, tabW, tabH, tabAtlasX, 0 )
UI_LoadImage( ttlBank2, tabTex, PAGE_ITEM_TITLE_NORMAL, tabW, tabH, tabAtlasX + tabW - 1, 0 )
UI_SetPos( ttlBank2, tabX + tabXoff * 2, tabY )
UI_SetSize( ttlBank2, tabW, tabH )
UI_AddCompent( itemid, grdNPCstorage2 )
-- Numbers on tabs (header strip y~28)
labBankTab0 = UI_CreateCompent( frmNPCstorage, LABELEX_TYPE, "labBankTab0", 16, 12, 38, 26 )
UI_SetCaption( labBankTab0, "1" )
UI_SetTextColor( labBankTab0, COLOR_BLACK )
UI_SetLabelExFont( labBankTab0, DEFAULT_FONT, TRUE, COLOR_WHITE )
labBankTab1 = UI_CreateCompent( frmNPCstorage, LABELEX_TYPE, "labBankTab1", 16, 12, 92, 26 )
UI_SetCaption( labBankTab1, "2" )
UI_SetTextColor( labBankTab1, COLOR_BLACK )
UI_SetLabelExFont( labBankTab1, DEFAULT_FONT, TRUE, COLOR_WHITE )
labBankTab2 = UI_CreateCompent( frmNPCstorage, LABELEX_TYPE, "labBankTab2", 16, 12, 146, 26 )
UI_SetCaption( labBankTab2, "3" )
UI_SetTextColor( labBankTab2, COLOR_BLACK )
UI_SetLabelExFont( labBankTab2, DEFAULT_FONT, TRUE, COLOR_WHITE )
Compile common, GameServer, Client
Compile clu scripts
Compile client table
Copy texture in client folder
Enjoy!!!

