port: ItemData, ItemManager, PythonNonPlayer + LoadLocaleData (batch 2 P3-a)
Verbatim 40250 GameLib ItemData/ItemManager and UserInterface PythonNonPlayer(+Module) replace their pending stand-ins and the nonplayer module stub. LoadLocaleData's body moves into the platform CPythonApplication stand-in, so the select phase loads item_proto and mob_proto; CPythonSkill is still pending, so it returns false after the tables load. login_flow checks item 19 (Sword+9) and mob 101 (Wild Dog), offline and live. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
ce9f96398e
commit
f0564a7f12
@@ -24,7 +24,6 @@
|
||||
#include "UserInterface/AbstractApplication.h"
|
||||
#include "UserInterface/PythonMessenger.h"
|
||||
#include "UserInterface/PythonMiniMap.h"
|
||||
#include "UserInterface/PythonNonPlayer.h"
|
||||
#include "EterLib/Profiler.h"
|
||||
#include "UserInterface/PythonQuest.h"
|
||||
#include "UserInterface/PythonSafeBox.h"
|
||||
@@ -393,23 +392,6 @@ void AddStubConstants_miniMap(PyObject* poModule)
|
||||
PyModule_AddIntConstant(poModule, "TYPE_EMPIRE", CPythonMiniMap::TYPE_EMPIRE);
|
||||
}
|
||||
|
||||
// 40250 UserInterface/PythonNonPlayerModule.cpp
|
||||
void AddStubConstants_nonplayer(PyObject* poModule)
|
||||
{
|
||||
(void) poModule;
|
||||
PyModule_AddIntConstant(poModule, "ON_CLICK_EVENT_NONE", CPythonNonPlayer::ON_CLICK_EVENT_NONE);
|
||||
PyModule_AddIntConstant(poModule, "ON_CLICK_EVENT_BATTLE", CPythonNonPlayer::ON_CLICK_EVENT_BATTLE);
|
||||
PyModule_AddIntConstant(poModule, "ON_CLICK_EVENT_SHOP", CPythonNonPlayer::ON_CLICK_EVENT_SHOP);
|
||||
PyModule_AddIntConstant(poModule, "ON_CLICK_EVENT_TALK", CPythonNonPlayer::ON_CLICK_EVENT_TALK);
|
||||
PyModule_AddIntConstant(poModule, "ON_CLICK_EVENT_VEHICLE", CPythonNonPlayer::ON_CLICK_EVENT_VEHICLE);
|
||||
PyModule_AddIntConstant(poModule, "PAWN", 0);
|
||||
PyModule_AddIntConstant(poModule, "S_PAWN", 1);
|
||||
PyModule_AddIntConstant(poModule, "KNIGHT", 2);
|
||||
PyModule_AddIntConstant(poModule, "S_KNIGHT", 3);
|
||||
PyModule_AddIntConstant(poModule, "BOSS", 4);
|
||||
PyModule_AddIntConstant(poModule, "KING", 5);
|
||||
}
|
||||
|
||||
// 40250 UserInterface/PythonProfilerModule.cpp
|
||||
void AddStubConstants_profiler(PyObject* poModule)
|
||||
{
|
||||
|
||||
@@ -14,7 +14,6 @@ void AddStubConstants_ime(PyObject* poModule);
|
||||
void AddStubConstants_item(PyObject* poModule);
|
||||
void AddStubConstants_messenger(PyObject* poModule);
|
||||
void AddStubConstants_miniMap(PyObject* poModule);
|
||||
void AddStubConstants_nonplayer(PyObject* poModule);
|
||||
void AddStubConstants_profiler(PyObject* poModule);
|
||||
void AddStubConstants_quest(PyObject* poModule);
|
||||
void AddStubConstants_safebox(PyObject* poModule);
|
||||
@@ -519,22 +518,6 @@ PyMethodDef methods_miniMap[] = {
|
||||
{ "GetGuildAreaID", stub_miniMap_GetGuildAreaID, METH_VARARGS },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
// 40250 UserInterface/PythonNonPlayerModule.cpp: nonplayer export names.
|
||||
PyObject* stub_nonplayer_GetEventType(PyObject*, PyObject*) { return stub_call_named("nonplayer.GetEventType", Py_BuildValue("i", 0)); }
|
||||
PyObject* stub_nonplayer_GetEventTypeByVID(PyObject*, PyObject*) { return stub_call_named("nonplayer.GetEventTypeByVID", Py_BuildValue("i", 0)); }
|
||||
PyObject* stub_nonplayer_GetLevelByVID(PyObject*, PyObject*) { return stub_call_named("nonplayer.GetLevelByVID", Py_BuildValue("i", 0)); }
|
||||
PyObject* stub_nonplayer_GetGradeByVID(PyObject*, PyObject*) { return stub_call_named("nonplayer.GetGradeByVID", Py_BuildValue("i", 0)); }
|
||||
PyObject* stub_nonplayer_GetMonsterName(PyObject*, PyObject*) { return stub_call_named("nonplayer.GetMonsterName", Py_BuildValue("s", "")); }
|
||||
PyObject* stub_nonplayer_LoadNonPlayerData(PyObject*, PyObject*) { return stub_call_named("nonplayer.LoadNonPlayerData", Py_BuildNone()); }
|
||||
PyMethodDef methods_nonplayer[] = {
|
||||
{ "GetEventType", stub_nonplayer_GetEventType, METH_VARARGS },
|
||||
{ "GetEventTypeByVID", stub_nonplayer_GetEventTypeByVID, METH_VARARGS },
|
||||
{ "GetLevelByVID", stub_nonplayer_GetLevelByVID, METH_VARARGS },
|
||||
{ "GetGradeByVID", stub_nonplayer_GetGradeByVID, METH_VARARGS },
|
||||
{ "GetMonsterName", stub_nonplayer_GetMonsterName, METH_VARARGS },
|
||||
{ "LoadNonPlayerData", stub_nonplayer_LoadNonPlayerData, METH_VARARGS },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
// 40250 UserInterface/PythonProfilerModule.cpp: profiler export names.
|
||||
PyObject* stub_profiler_Push(PyObject*, PyObject*) { return stub_call_named("profiler.Push", Py_BuildNone()); }
|
||||
PyObject* stub_profiler_Pop(PyObject*, PyObject*) { return stub_call_named("profiler.Pop", Py_BuildNone()); }
|
||||
@@ -922,11 +905,6 @@ void init_2v0_gameplay_stubs() {
|
||||
PyModule_AddIntConstant(module, "__port_stub__", 1);
|
||||
AddStubConstants_miniMap(module);
|
||||
}
|
||||
{
|
||||
PyObject* module = Py_InitModule("nonplayer", methods_nonplayer);
|
||||
PyModule_AddIntConstant(module, "__port_stub__", 1);
|
||||
AddStubConstants_nonplayer(module);
|
||||
}
|
||||
{
|
||||
PyObject* module = Py_InitModule("profiler", methods_profiler);
|
||||
PyModule_AddIntConstant(module, "__port_stub__", 1);
|
||||
|
||||
@@ -347,6 +347,7 @@ bool run_main_script_body(const char* lpCmdLine, std::string* error)
|
||||
initchr();
|
||||
initchrmgr();
|
||||
initPlayer();
|
||||
initNonPlayer();
|
||||
initChat();
|
||||
initnet();
|
||||
initeffect();
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
#include "EterLib/ResourceManager.h"
|
||||
#include "UserInterface/PythonNetworkStream.h"
|
||||
#include "UserInterface/AccountConnector.h"
|
||||
#include "UserInterface/PythonSkill.h"
|
||||
#include "UserInterface/PythonNonPlayer.h"
|
||||
#include "GameLib/ItemManager.h"
|
||||
#include "EterLib/NetDevice.h"
|
||||
#include "../PlatformStub.h"
|
||||
#include "../EterLib/UIRenderCommands.h"
|
||||
@@ -311,7 +314,91 @@ BOOL PERF_CHECKER_RENDER_GAME = FALSE;
|
||||
BOOL SKILL_EFFECT_UPGRADE_ENABLE = FALSE;
|
||||
double g_specularSpd = 0;
|
||||
|
||||
bool LoadLocaleData(const char*) { MT_PLATFORM_STUB(); return false; }
|
||||
// 40250 UserInterface/PythonApplication.cpp, verbatim. PORT: CPythonSkill is still a stand-in, so
|
||||
// RegisterSkillDesc fails and the function returns false after the item and mob tables load.
|
||||
// SUPPORT_NEW_KOREA_SERVER
|
||||
bool LoadLocaleData(const char* localePath)
|
||||
{
|
||||
NANOBEGIN
|
||||
CPythonNonPlayer& rkNPCMgr = CPythonNonPlayer::Instance();
|
||||
CItemManager& rkItemMgr = CItemManager::Instance();
|
||||
CPythonSkill& rkSkillMgr = CPythonSkill::Instance();
|
||||
CPythonNetworkStream& rkNetStream = CPythonNetworkStream::Instance();
|
||||
|
||||
char szItemList[256];
|
||||
char szItemProto[256];
|
||||
char szItemDesc[256];
|
||||
char szMobProto[256];
|
||||
char szSkillDescFileName[256];
|
||||
char szSkillTableFileName[256];
|
||||
char szInsultList[256];
|
||||
snprintf(szItemList, sizeof(szItemList) , "%s/item_list.txt", localePath);
|
||||
snprintf(szItemProto, sizeof(szItemProto), "%s/item_proto", localePath);
|
||||
snprintf(szItemDesc, sizeof(szItemDesc), "%s/itemdesc.txt", localePath);
|
||||
snprintf(szMobProto, sizeof(szMobProto), "%s/mob_proto", localePath);
|
||||
snprintf(szSkillDescFileName, sizeof(szSkillDescFileName), "%s/SkillDesc.txt", localePath);
|
||||
snprintf(szSkillTableFileName, sizeof(szSkillTableFileName), "%s/SkillTable.txt", localePath);
|
||||
snprintf(szInsultList, sizeof(szInsultList), "%s/insult.txt", localePath);
|
||||
|
||||
rkNPCMgr.Destroy();
|
||||
rkItemMgr.Destroy();
|
||||
rkSkillMgr.Destroy();
|
||||
|
||||
if (!rkItemMgr.LoadItemList(szItemList))
|
||||
{
|
||||
TraceError("LoadLocaleData - LoadItemList(%s) Error", szItemList);
|
||||
}
|
||||
|
||||
if (!rkItemMgr.LoadItemTable(szItemProto))
|
||||
{
|
||||
TraceError("LoadLocaleData - LoadItemProto(%s) Error", szItemProto);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!rkItemMgr.LoadItemDesc(szItemDesc))
|
||||
{
|
||||
Tracenf("LoadLocaleData - LoadItemDesc(%s) Error", szItemDesc);
|
||||
}
|
||||
|
||||
if (!rkNPCMgr.LoadNonPlayerData(szMobProto))
|
||||
{
|
||||
TraceError("LoadLocaleData - LoadMobProto(%s) Error", szMobProto);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!rkSkillMgr.RegisterSkillDesc(szSkillDescFileName))
|
||||
{
|
||||
TraceError("LoadLocaleData - RegisterSkillDesc(%s) Error", szMobProto);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!rkSkillMgr.RegisterSkillTable(szSkillTableFileName))
|
||||
{
|
||||
TraceError("LoadLocaleData - RegisterSkillTable(%s) Error", szMobProto);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!rkNetStream.LoadInsultList(szInsultList))
|
||||
{
|
||||
Tracenf("CPythonApplication - CPythonNetworkStream::LoadInsultList(%s)", szInsultList);
|
||||
}
|
||||
|
||||
if (LocaleService_IsYMIR())
|
||||
{
|
||||
char szEmpireTextConvFile[256];
|
||||
for (DWORD dwEmpireID=1; dwEmpireID<=3; ++dwEmpireID)
|
||||
{
|
||||
sprintf(szEmpireTextConvFile, "%s/lang%d.cvt", localePath, dwEmpireID);
|
||||
if (!rkNetStream.LoadConvertTable(dwEmpireID, szEmpireTextConvFile))
|
||||
{
|
||||
TraceError("LoadLocaleData - CPythonNetworkStream::LoadConvertTable(%d, %s) FAILURE", dwEmpireID, szEmpireTextConvFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NANOEND
|
||||
return true;
|
||||
}
|
||||
void TextTail_SetLivingTime(long) { MT_PLATFORM_STUB(); }
|
||||
namespace {
|
||||
// The supplied 40250 Client/locale.cfg selects "en" (code page 1252).
|
||||
|
||||
@@ -1,133 +0,0 @@
|
||||
// Stand-in for the 40250 logic unit GameLib/ItemData.cpp, not ported yet: the members the ported units
|
||||
// reference, as platform_stub.py stubs. Delete this file in the commit that ports the unit into port/
|
||||
// (docs/PORT-PLAN.md).
|
||||
#include "GameLib/StdAfx.h"
|
||||
#include "GameLib/ItemData.h"
|
||||
|
||||
#include "../../PlatformStub.h"
|
||||
|
||||
auto CItemData::GetName() const -> const char *
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<const char *>();
|
||||
}
|
||||
|
||||
auto CItemData::GetType() const -> BYTE
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<BYTE>();
|
||||
}
|
||||
|
||||
auto CItemData::GetValue(BYTE) const -> long
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<long>();
|
||||
}
|
||||
|
||||
auto CItemData::GetIndex() const -> DWORD
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<DWORD>();
|
||||
}
|
||||
|
||||
auto CItemData::GetSubType() const -> BYTE
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<BYTE>();
|
||||
}
|
||||
|
||||
auto CItemData::GetRefine() const -> UINT
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<UINT>();
|
||||
}
|
||||
|
||||
auto CItemData::GetWeaponType() const -> DWORD
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<DWORD>();
|
||||
}
|
||||
|
||||
auto CItemData::GetSocketCount() const -> int
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<int>();
|
||||
}
|
||||
|
||||
auto CItemData::GetSpecularPowerf() const -> float
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<float>();
|
||||
}
|
||||
|
||||
auto CItemData::GetModelThing() -> CGraphicThing *
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<CGraphicThing *>();
|
||||
}
|
||||
|
||||
auto CItemData::GetSubModelThing() -> CGraphicThing *
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<CGraphicThing *>();
|
||||
}
|
||||
|
||||
auto CItemData::GetLODModelThingCount() -> DWORD
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<DWORD>();
|
||||
}
|
||||
|
||||
auto CItemData::GetLODModelThingPointer(DWORD, CGraphicThing **) -> BOOL
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<BOOL>();
|
||||
}
|
||||
|
||||
auto CItemData::GetAttachingDataCount() -> DWORD
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<DWORD>();
|
||||
}
|
||||
|
||||
auto CItemData::GetAttachingDataPointer(DWORD, const NRaceData::TAttachingData **) -> BOOL
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<BOOL>();
|
||||
}
|
||||
|
||||
auto CItemData::IsAntiFlag(DWORD) const -> BOOL
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<BOOL>();
|
||||
}
|
||||
|
||||
auto CItemData::IsEquipment() const -> BOOL
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<BOOL>();
|
||||
}
|
||||
|
||||
auto CItemData::IsFlag(DWORD) const -> BOOL
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<BOOL>();
|
||||
}
|
||||
|
||||
auto CItemData::HasNextGrade() const -> BOOL
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<BOOL>();
|
||||
}
|
||||
|
||||
auto CItemData::GetWearFlags() const -> DWORD
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<DWORD>();
|
||||
}
|
||||
|
||||
auto CItemData::GetISellItemPrice() const -> DWORD
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<DWORD>();
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
// Stand-in for the 40250 logic unit GameLib/ItemManager.cpp, not ported yet: the members the ported units
|
||||
// reference, as platform_stub.py stubs. Delete this file in the commit that ports the unit into port/
|
||||
// (docs/PORT-PLAN.md).
|
||||
#include "GameLib/StdAfx.h"
|
||||
#include "GameLib/ItemManager.h"
|
||||
|
||||
#include "../../PlatformStub.h"
|
||||
|
||||
CItemManager::CItemManager()
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
}
|
||||
|
||||
CItemManager::~CItemManager()
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
}
|
||||
|
||||
auto CItemManager::GetItemDataPointer(DWORD, CItemData **) -> BOOL
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<BOOL>();
|
||||
}
|
||||
|
||||
auto CItemManager::SelectItemData(DWORD) -> BOOL
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<BOOL>();
|
||||
}
|
||||
|
||||
auto CItemManager::GetSelectedItemDataPointer() -> CItemData *
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<CItemData *>();
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
// Stand-in for the 40250 logic unit UserInterface/PythonNonPlayer.cpp, not ported yet: the members the ported units
|
||||
// reference, as platform_stub.py stubs. Delete this file in the commit that ports the unit into port/
|
||||
// (docs/PORT-PLAN.md).
|
||||
#include "UserInterface/StdAfx.h"
|
||||
#include "UserInterface/PythonNonPlayer.h"
|
||||
|
||||
#include "../../PlatformStub.h"
|
||||
|
||||
CPythonNonPlayer::CPythonNonPlayer()
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
}
|
||||
|
||||
CPythonNonPlayer::~CPythonNonPlayer()
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
}
|
||||
|
||||
auto CPythonNonPlayer::GetName(DWORD, const char **) -> bool
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<bool>();
|
||||
}
|
||||
|
||||
auto CPythonNonPlayer::GetInstanceType(DWORD, BYTE *) -> bool
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<bool>();
|
||||
}
|
||||
|
||||
auto CPythonNonPlayer::GetEventType(DWORD) -> BYTE
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<BYTE>();
|
||||
}
|
||||
|
||||
auto CPythonNonPlayer::GetMonsterColor(DWORD) -> DWORD
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<DWORD>();
|
||||
}
|
||||
@@ -191,3 +191,20 @@ auto CPythonSkill::SSkillData::GetType() const -> BYTE
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<BYTE>();
|
||||
}
|
||||
|
||||
auto CPythonSkill::Destroy() -> void
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
}
|
||||
|
||||
auto CPythonSkill::RegisterSkillTable(const char *) -> bool
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<bool>();
|
||||
}
|
||||
|
||||
auto CPythonSkill::RegisterSkillDesc(const char *) -> bool
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<bool>();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,464 @@
|
||||
#include "StdAfx.h"
|
||||
#include "../EterLib/ResourceManager.h"
|
||||
|
||||
#include "ItemData.h"
|
||||
|
||||
CDynamicPool<CItemData> CItemData::ms_kPool;
|
||||
|
||||
extern DWORD GetDefaultCodePage();
|
||||
|
||||
CItemData* CItemData::New()
|
||||
{
|
||||
return ms_kPool.Alloc();
|
||||
}
|
||||
|
||||
void CItemData::Delete(CItemData* pkItemData)
|
||||
{
|
||||
pkItemData->Clear();
|
||||
ms_kPool.Free(pkItemData);
|
||||
}
|
||||
|
||||
void CItemData::DestroySystem()
|
||||
{
|
||||
ms_kPool.Destroy();
|
||||
}
|
||||
|
||||
CGraphicThing * CItemData::GetModelThing()
|
||||
{
|
||||
return m_pModelThing;
|
||||
}
|
||||
|
||||
CGraphicThing * CItemData::GetSubModelThing()
|
||||
{
|
||||
if (m_pSubModelThing)
|
||||
return m_pSubModelThing;
|
||||
else
|
||||
return m_pModelThing;
|
||||
}
|
||||
|
||||
CGraphicThing * CItemData::GetDropModelThing()
|
||||
{
|
||||
return m_pDropModelThing;
|
||||
}
|
||||
|
||||
CGraphicSubImage * CItemData::GetIconImage()
|
||||
{
|
||||
if(m_pIconImage == NULL && m_strIconFileName.empty() == false)
|
||||
__SetIconImage(m_strIconFileName.c_str());
|
||||
return m_pIconImage;
|
||||
}
|
||||
|
||||
DWORD CItemData::GetLODModelThingCount()
|
||||
{
|
||||
return m_pLODModelThingVector.size();
|
||||
}
|
||||
|
||||
BOOL CItemData::GetLODModelThingPointer(DWORD dwIndex, CGraphicThing ** ppModelThing)
|
||||
{
|
||||
if (dwIndex >= m_pLODModelThingVector.size())
|
||||
return FALSE;
|
||||
|
||||
*ppModelThing = m_pLODModelThingVector[dwIndex];
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
DWORD CItemData::GetAttachingDataCount()
|
||||
{
|
||||
return m_AttachingDataVector.size();
|
||||
}
|
||||
|
||||
BOOL CItemData::GetCollisionDataPointer(DWORD dwIndex, const NRaceData::TAttachingData ** c_ppAttachingData)
|
||||
{
|
||||
if (dwIndex >= GetAttachingDataCount())
|
||||
return FALSE;
|
||||
|
||||
if (NRaceData::ATTACHING_DATA_TYPE_COLLISION_DATA != m_AttachingDataVector[dwIndex].dwType)
|
||||
return FALSE;
|
||||
|
||||
*c_ppAttachingData = &m_AttachingDataVector[dwIndex];
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CItemData::GetAttachingDataPointer(DWORD dwIndex, const NRaceData::TAttachingData ** c_ppAttachingData)
|
||||
{
|
||||
if (dwIndex >= GetAttachingDataCount())
|
||||
return FALSE;
|
||||
|
||||
*c_ppAttachingData = &m_AttachingDataVector[dwIndex];
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void CItemData::SetSummary(const std::string& c_rstSumm)
|
||||
{
|
||||
m_strSummary=c_rstSumm;
|
||||
}
|
||||
|
||||
void CItemData::SetDescription(const std::string& c_rstDesc)
|
||||
{
|
||||
m_strDescription=c_rstDesc;
|
||||
}
|
||||
/*
|
||||
BOOL CItemData::LoadItemData(const char * c_szFileName)
|
||||
{
|
||||
CTextFileLoader TextFileLoader;
|
||||
|
||||
if (!TextFileLoader.Load(c_szFileName))
|
||||
{
|
||||
//Lognf(1, "CItemData::LoadItemData(c_szFileName=%s) - FAILED", c_szFileName);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
TextFileLoader.SetTop();
|
||||
|
||||
TextFileLoader.GetTokenString("modelfilename", &m_strModelFileName);
|
||||
TextFileLoader.GetTokenString("submodelfilename", &m_strSubModelFileName);
|
||||
TextFileLoader.GetTokenString("dropmodelfilename", &m_strDropModelFileName);
|
||||
TextFileLoader.GetTokenString("iconimagefilename", &m_strIconFileName);
|
||||
|
||||
char szDescriptionKey[32+1];
|
||||
_snprintf(szDescriptionKey, 32, "%ddescription", GetDefaultCodePage());
|
||||
if (!TextFileLoader.GetTokenString(szDescriptionKey, &m_strDescription))
|
||||
{
|
||||
TextFileLoader.GetTokenString("description", &m_strDescription);
|
||||
}
|
||||
|
||||
// LOD Model File Name List
|
||||
CTokenVector * pLODModelList;
|
||||
if (TextFileLoader.GetTokenVector("lodmodellist", &pLODModelList))
|
||||
{
|
||||
m_strLODModelFileNameVector.clear();
|
||||
m_strLODModelFileNameVector.resize(pLODModelList->size());
|
||||
|
||||
for (DWORD i = 0; i < pLODModelList->size(); ++i)
|
||||
{
|
||||
m_strLODModelFileNameVector[i] = pLODModelList->at(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Attaching Data
|
||||
// Item 에 Attaching Data 일단 없음.
|
||||
// if (TextFileLoader.SetChildNode("attachingdata"))
|
||||
// {
|
||||
// if (!NRaceData::LoadAttachingData(TextFileLoader, &m_AttachingDataVector))
|
||||
// return FALSE;
|
||||
//
|
||||
// TextFileLoader.SetParentNode();
|
||||
// }
|
||||
|
||||
__LoadFiles();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
*/
|
||||
void CItemData::SetDefaultItemData(const char * c_szIconFileName, const char * c_szModelFileName)
|
||||
{
|
||||
if(c_szModelFileName)
|
||||
{
|
||||
m_strModelFileName = c_szModelFileName;
|
||||
m_strDropModelFileName = c_szModelFileName;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_strModelFileName = "";
|
||||
m_strDropModelFileName = "d:/ymir work/item/etc/item_bag.gr2";
|
||||
}
|
||||
m_strIconFileName = c_szIconFileName;
|
||||
|
||||
m_strSubModelFileName = "";
|
||||
m_strDescription = "";
|
||||
m_strSummary = "";
|
||||
memset(m_ItemTable.alSockets, 0, sizeof(m_ItemTable.alSockets));
|
||||
|
||||
__LoadFiles();
|
||||
}
|
||||
|
||||
void CItemData::__LoadFiles()
|
||||
{
|
||||
// Model File Name
|
||||
if (!m_strModelFileName.empty())
|
||||
m_pModelThing = (CGraphicThing *)CResourceManager::Instance().GetResourcePointer(m_strModelFileName.c_str());
|
||||
|
||||
if (!m_strSubModelFileName.empty())
|
||||
m_pSubModelThing = (CGraphicThing *)CResourceManager::Instance().GetResourcePointer(m_strSubModelFileName.c_str());
|
||||
|
||||
if (!m_strDropModelFileName.empty())
|
||||
m_pDropModelThing = (CGraphicThing *)CResourceManager::Instance().GetResourcePointer(m_strDropModelFileName.c_str());
|
||||
|
||||
|
||||
if (!m_strLODModelFileNameVector.empty())
|
||||
{
|
||||
m_pLODModelThingVector.clear();
|
||||
m_pLODModelThingVector.resize(m_strLODModelFileNameVector.size());
|
||||
|
||||
for (DWORD i = 0; i < m_strLODModelFileNameVector.size(); ++i)
|
||||
{
|
||||
const std::string & c_rstrLODModelFileName = m_strLODModelFileNameVector[i];
|
||||
m_pLODModelThingVector[i] = (CGraphicThing *)CResourceManager::Instance().GetResourcePointer(c_rstrLODModelFileName.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CItemData::__SetIconImage(const char * c_szFileName)
|
||||
{
|
||||
if (!CResourceManager::Instance().IsFileExist(c_szFileName))
|
||||
{
|
||||
TraceError("%s \306\304\300\317\300\314 \276\370\275\300\264\317\264\331.CItemData::__SetIconImage",c_szFileName);
|
||||
m_pIconImage = NULL;
|
||||
}
|
||||
else if (m_pIconImage == NULL)
|
||||
m_pIconImage = (CGraphicSubImage *)CResourceManager::Instance().GetResourcePointer(c_szFileName);
|
||||
}
|
||||
|
||||
void CItemData::SetItemTableData(TItemTable * pItemTable)
|
||||
{
|
||||
memcpy(&m_ItemTable, pItemTable, sizeof(TItemTable));
|
||||
}
|
||||
|
||||
const CItemData::TItemTable* CItemData::GetTable() const
|
||||
{
|
||||
return &m_ItemTable;
|
||||
}
|
||||
|
||||
DWORD CItemData::GetIndex() const
|
||||
{
|
||||
return m_ItemTable.dwVnum;
|
||||
}
|
||||
|
||||
const char * CItemData::GetName() const
|
||||
{
|
||||
return m_ItemTable.szLocaleName;
|
||||
}
|
||||
|
||||
const char * CItemData::GetDescription() const
|
||||
{
|
||||
return m_strDescription.c_str();
|
||||
}
|
||||
|
||||
const char * CItemData::GetSummary() const
|
||||
{
|
||||
return m_strSummary.c_str();
|
||||
}
|
||||
|
||||
|
||||
BYTE CItemData::GetType() const
|
||||
{
|
||||
return m_ItemTable.bType;
|
||||
}
|
||||
|
||||
BYTE CItemData::GetSubType() const
|
||||
{
|
||||
return m_ItemTable.bSubType;
|
||||
}
|
||||
|
||||
#define DEF_STR(x) #x
|
||||
|
||||
const char* CItemData::GetUseTypeString() const
|
||||
{
|
||||
if (GetType() != CItemData::ITEM_TYPE_USE)
|
||||
return "NOT_USE_TYPE";
|
||||
|
||||
switch (GetSubType())
|
||||
{
|
||||
case USE_TUNING:
|
||||
return DEF_STR(USE_TUNING);
|
||||
case USE_DETACHMENT:
|
||||
return DEF_STR(USE_DETACHMENT);
|
||||
case USE_CLEAN_SOCKET:
|
||||
return DEF_STR(USE_CLEAN_SOCKET);
|
||||
case USE_CHANGE_ATTRIBUTE:
|
||||
return DEF_STR(USE_CHANGE_ATTRIBUTE);
|
||||
case USE_ADD_ATTRIBUTE:
|
||||
return DEF_STR(USE_ADD_ATTRIBUTE);
|
||||
case USE_ADD_ATTRIBUTE2:
|
||||
return DEF_STR(USE_ADD_ATTRIBUTE2);
|
||||
case USE_ADD_ACCESSORY_SOCKET:
|
||||
return DEF_STR(USE_ADD_ACCESSORY_SOCKET);
|
||||
case USE_PUT_INTO_ACCESSORY_SOCKET:
|
||||
return DEF_STR(USE_PUT_INTO_ACCESSORY_SOCKET);
|
||||
case USE_PUT_INTO_BELT_SOCKET:
|
||||
return DEF_STR(USE_PUT_INTO_BELT_SOCKET);
|
||||
case USE_PUT_INTO_RING_SOCKET:
|
||||
return DEF_STR(USE_PUT_INTO_RING_SOCKET);
|
||||
}
|
||||
return "USE_UNKNOWN_TYPE";
|
||||
}
|
||||
|
||||
|
||||
DWORD CItemData::GetWeaponType() const
|
||||
{
|
||||
return m_ItemTable.bSubType;
|
||||
}
|
||||
|
||||
BYTE CItemData::GetSize() const
|
||||
{
|
||||
return m_ItemTable.bSize;
|
||||
}
|
||||
|
||||
BOOL CItemData::IsAntiFlag(DWORD dwFlag) const
|
||||
{
|
||||
return (dwFlag & m_ItemTable.dwAntiFlags) != 0;
|
||||
}
|
||||
|
||||
BOOL CItemData::IsFlag(DWORD dwFlag) const
|
||||
{
|
||||
return (dwFlag & m_ItemTable.dwFlags) != 0;
|
||||
}
|
||||
|
||||
BOOL CItemData::IsWearableFlag(DWORD dwFlag) const
|
||||
{
|
||||
return (dwFlag & m_ItemTable.dwWearFlags) != 0;
|
||||
}
|
||||
|
||||
BOOL CItemData::HasNextGrade() const
|
||||
{
|
||||
return 0 != m_ItemTable.dwRefinedVnum;
|
||||
}
|
||||
|
||||
DWORD CItemData::GetWearFlags() const
|
||||
{
|
||||
return m_ItemTable.dwWearFlags;
|
||||
}
|
||||
|
||||
DWORD CItemData::GetIBuyItemPrice() const
|
||||
{
|
||||
return m_ItemTable.dwIBuyItemPrice;
|
||||
}
|
||||
|
||||
DWORD CItemData::GetISellItemPrice() const
|
||||
{
|
||||
return m_ItemTable.dwISellItemPrice;
|
||||
}
|
||||
|
||||
|
||||
BOOL CItemData::GetLimit(BYTE byIndex, TItemLimit * pItemLimit) const
|
||||
{
|
||||
if (byIndex >= ITEM_LIMIT_MAX_NUM)
|
||||
{
|
||||
assert(byIndex < ITEM_LIMIT_MAX_NUM);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*pItemLimit = m_ItemTable.aLimits[byIndex];
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CItemData::GetApply(BYTE byIndex, TItemApply * pItemApply) const
|
||||
{
|
||||
if (byIndex >= ITEM_APPLY_MAX_NUM)
|
||||
{
|
||||
assert(byIndex < ITEM_APPLY_MAX_NUM);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*pItemApply = m_ItemTable.aApplies[byIndex];
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
long CItemData::GetValue(BYTE byIndex) const
|
||||
{
|
||||
if (byIndex >= ITEM_VALUES_MAX_NUM)
|
||||
{
|
||||
assert(byIndex < ITEM_VALUES_MAX_NUM);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return m_ItemTable.alValues[byIndex];
|
||||
}
|
||||
|
||||
long CItemData::SetSocket(BYTE byIndex,DWORD value)
|
||||
{
|
||||
if (byIndex >= ITEM_SOCKET_MAX_NUM)
|
||||
{
|
||||
assert(byIndex < ITEM_SOCKET_MAX_NUM);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return m_ItemTable.alSockets[byIndex] = value;
|
||||
}
|
||||
|
||||
long CItemData::GetSocket(BYTE byIndex) const
|
||||
{
|
||||
if (byIndex >= ITEM_SOCKET_MAX_NUM)
|
||||
{
|
||||
assert(byIndex < ITEM_SOCKET_MAX_NUM);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return m_ItemTable.alSockets[byIndex];
|
||||
}
|
||||
|
||||
//서버와 동일 서버 함수 변경시 같이 변경!!(이후에 합친다)
|
||||
//SocketCount = 1 이면 초급무기
|
||||
//SocketCount = 2 이면 중급무기
|
||||
//SocketCount = 3 이면 고급무기
|
||||
int CItemData::GetSocketCount() const
|
||||
{
|
||||
return m_ItemTable.bGainSocketPct;
|
||||
}
|
||||
|
||||
DWORD CItemData::GetIconNumber() const
|
||||
{
|
||||
return m_ItemTable.dwVnum;
|
||||
//!@#
|
||||
// return m_ItemTable.dwIconNumber;
|
||||
}
|
||||
|
||||
UINT CItemData::GetSpecularPoweru() const
|
||||
{
|
||||
return m_ItemTable.bSpecular;
|
||||
}
|
||||
|
||||
float CItemData::GetSpecularPowerf() const
|
||||
{
|
||||
UINT uSpecularPower=GetSpecularPoweru();
|
||||
|
||||
return float(uSpecularPower) / 100.0f;
|
||||
}
|
||||
|
||||
//refine 값은 아이템번호 끝자리와 일치한다-_-(테이블이용으로 바꿀 예정)
|
||||
UINT CItemData::GetRefine() const
|
||||
{
|
||||
return GetIndex()%10;
|
||||
}
|
||||
|
||||
BOOL CItemData::IsEquipment() const
|
||||
{
|
||||
switch (GetType())
|
||||
{
|
||||
case ITEM_TYPE_WEAPON:
|
||||
case ITEM_TYPE_ARMOR:
|
||||
return TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void CItemData::Clear()
|
||||
{
|
||||
m_strSummary = "";
|
||||
m_strModelFileName = "";
|
||||
m_strSubModelFileName = "";
|
||||
m_strDropModelFileName = "";
|
||||
m_strIconFileName = "";
|
||||
m_strLODModelFileNameVector.clear();
|
||||
|
||||
m_pModelThing = NULL;
|
||||
m_pSubModelThing = NULL;
|
||||
m_pDropModelThing = NULL;
|
||||
m_pIconImage = NULL;
|
||||
m_pLODModelThingVector.clear();
|
||||
|
||||
memset(&m_ItemTable, 0, sizeof(m_ItemTable));
|
||||
}
|
||||
|
||||
CItemData::CItemData()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
CItemData::~CItemData()
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,404 @@
|
||||
#include "StdAfx.h"
|
||||
#include "../EterPack/EterPackManager.h"
|
||||
#include "../EterLib/ResourceManager.h"
|
||||
|
||||
#include "ItemManager.h"
|
||||
|
||||
static DWORD s_adwItemProtoKey[4] =
|
||||
{
|
||||
173217,
|
||||
72619434,
|
||||
408587239,
|
||||
27973291
|
||||
};
|
||||
|
||||
BOOL CItemManager::SelectItemData(DWORD dwIndex)
|
||||
{
|
||||
TItemMap::iterator f = m_ItemMap.find(dwIndex);
|
||||
|
||||
if (m_ItemMap.end() == f)
|
||||
{
|
||||
int n = m_vec_ItemRange.size();
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
CItemData * p = m_vec_ItemRange[i];
|
||||
const CItemData::TItemTable * pTable = p->GetTable();
|
||||
if ((pTable->dwVnum < dwIndex) &&
|
||||
dwIndex < (pTable->dwVnum + pTable->dwVnumRange))
|
||||
{
|
||||
m_pSelectedItemData = p;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
Tracef(" CItemManager::SelectItemData - FIND ERROR [%d]\n", dwIndex);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
m_pSelectedItemData = f->second;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
CItemData * CItemManager::GetSelectedItemDataPointer()
|
||||
{
|
||||
return m_pSelectedItemData;
|
||||
}
|
||||
|
||||
BOOL CItemManager::GetItemDataPointer(DWORD dwItemID, CItemData ** ppItemData)
|
||||
{
|
||||
if (0 == dwItemID)
|
||||
return FALSE;
|
||||
|
||||
TItemMap::iterator f = m_ItemMap.find(dwItemID);
|
||||
|
||||
if (m_ItemMap.end() == f)
|
||||
{
|
||||
int n = m_vec_ItemRange.size();
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
CItemData * p = m_vec_ItemRange[i];
|
||||
const CItemData::TItemTable * pTable = p->GetTable();
|
||||
if ((pTable->dwVnum < dwItemID) &&
|
||||
dwItemID < (pTable->dwVnum + pTable->dwVnumRange))
|
||||
{
|
||||
*ppItemData = p;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
Tracef(" CItemManager::GetItemDataPointer - FIND ERROR [%d]\n", dwItemID);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*ppItemData = f->second;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
CItemData * CItemManager::MakeItemData(DWORD dwIndex)
|
||||
{
|
||||
TItemMap::iterator f = m_ItemMap.find(dwIndex);
|
||||
|
||||
if (m_ItemMap.end() == f)
|
||||
{
|
||||
CItemData * pItemData = CItemData::New();
|
||||
|
||||
m_ItemMap.insert(TItemMap::value_type(dwIndex, pItemData));
|
||||
|
||||
return pItemData;
|
||||
}
|
||||
|
||||
return f->second;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Load Item Table
|
||||
|
||||
bool CItemManager::LoadItemList(const char * c_szFileName)
|
||||
{
|
||||
CMappedFile File;
|
||||
LPCVOID pData;
|
||||
|
||||
if (!CEterPackManager::Instance().Get(File, c_szFileName, &pData))
|
||||
return false;
|
||||
|
||||
CMemoryTextFileLoader textFileLoader;
|
||||
textFileLoader.Bind(File.Size(), pData);
|
||||
|
||||
CTokenVector TokenVector;
|
||||
for (DWORD i = 0; i < textFileLoader.GetLineCount(); ++i)
|
||||
{
|
||||
if (!textFileLoader.SplitLine(i, &TokenVector, "\t"))
|
||||
continue;
|
||||
|
||||
if (!(TokenVector.size() == 3 || TokenVector.size() == 4))
|
||||
{
|
||||
TraceError(" CItemManager::LoadItemList(%s) - StrangeLine in %d\n", c_szFileName, i);
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::string & c_rstrID = TokenVector[0];
|
||||
//const std::string & c_rstrType = TokenVector[1];
|
||||
const std::string & c_rstrIcon = TokenVector[2];
|
||||
|
||||
DWORD dwItemVNum=atoi(c_rstrID.c_str());
|
||||
|
||||
CItemData * pItemData = MakeItemData(dwItemVNum);
|
||||
|
||||
extern BOOL USE_VIETNAM_CONVERT_WEAPON_VNUM;
|
||||
if (USE_VIETNAM_CONVERT_WEAPON_VNUM)
|
||||
{
|
||||
extern DWORD Vietnam_ConvertWeaponVnum(DWORD vnum);
|
||||
DWORD dwMildItemVnum = Vietnam_ConvertWeaponVnum(dwItemVNum);
|
||||
if (dwMildItemVnum == dwItemVNum)
|
||||
{
|
||||
if (4 == TokenVector.size())
|
||||
{
|
||||
const std::string & c_rstrModelFileName = TokenVector[3];
|
||||
pItemData->SetDefaultItemData(c_rstrIcon.c_str(), c_rstrModelFileName.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
pItemData->SetDefaultItemData(c_rstrIcon.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD dwMildBaseVnum = dwMildItemVnum / 10 * 10;
|
||||
char szMildIconPath[MAX_PATH];
|
||||
sprintf(szMildIconPath, "icon/item/%.5d.tga", dwMildBaseVnum);
|
||||
if (4 == TokenVector.size())
|
||||
{
|
||||
char szMildModelPath[MAX_PATH];
|
||||
sprintf(szMildModelPath, "d:/ymir work/item/weapon/%.5d.gr2", dwMildBaseVnum);
|
||||
pItemData->SetDefaultItemData(szMildIconPath, szMildModelPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
pItemData->SetDefaultItemData(szMildIconPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (4 == TokenVector.size())
|
||||
{
|
||||
const std::string & c_rstrModelFileName = TokenVector[3];
|
||||
pItemData->SetDefaultItemData(c_rstrIcon.c_str(), c_rstrModelFileName.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
pItemData->SetDefaultItemData(c_rstrIcon.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::string& __SnapString(const std::string& c_rstSrc, std::string& rstTemp)
|
||||
{
|
||||
UINT uSrcLen=c_rstSrc.length();
|
||||
if (uSrcLen<2)
|
||||
return c_rstSrc;
|
||||
|
||||
if (c_rstSrc[0]!='"')
|
||||
return c_rstSrc;
|
||||
|
||||
UINT uLeftCut=1;
|
||||
|
||||
UINT uRightCut=uSrcLen;
|
||||
if (c_rstSrc[uSrcLen-1]=='"')
|
||||
uRightCut=uSrcLen-1;
|
||||
|
||||
rstTemp=c_rstSrc.substr(uLeftCut, uRightCut-uLeftCut);
|
||||
return rstTemp;
|
||||
}
|
||||
|
||||
bool CItemManager::LoadItemDesc(const char* c_szFileName)
|
||||
{
|
||||
const VOID* pvData;
|
||||
CMappedFile kFile;
|
||||
if (!CEterPackManager::Instance().Get(kFile, c_szFileName, &pvData))
|
||||
{
|
||||
Tracenf("CItemManager::LoadItemDesc(c_szFileName=%s) - Load Error", c_szFileName);
|
||||
return false;
|
||||
}
|
||||
|
||||
CMemoryTextFileLoader kTextFileLoader;
|
||||
kTextFileLoader.Bind(kFile.Size(), pvData);
|
||||
|
||||
std::string stTemp;
|
||||
|
||||
CTokenVector kTokenVector;
|
||||
for (DWORD i = 0; i < kTextFileLoader.GetLineCount(); ++i)
|
||||
{
|
||||
if (!kTextFileLoader.SplitLineByTab(i, &kTokenVector))
|
||||
continue;
|
||||
|
||||
while (kTokenVector.size()<ITEMDESC_COL_NUM)
|
||||
kTokenVector.push_back("");
|
||||
|
||||
//assert(kTokenVector.size()==ITEMDESC_COL_NUM);
|
||||
|
||||
DWORD dwVnum=atoi(kTokenVector[ITEMDESC_COL_VNUM].c_str());
|
||||
const std::string& c_rstDesc=kTokenVector[ITEMDESC_COL_DESC];
|
||||
const std::string& c_rstSumm=kTokenVector[ITEMDESC_COL_SUMM];
|
||||
TItemMap::iterator f = m_ItemMap.find(dwVnum);
|
||||
if (m_ItemMap.end() == f)
|
||||
continue;
|
||||
|
||||
CItemData* pkItemDataFind = f->second;
|
||||
|
||||
pkItemDataFind->SetDescription(__SnapString(c_rstDesc, stTemp));
|
||||
pkItemDataFind->SetSummary(__SnapString(c_rstSumm, stTemp));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
DWORD GetHashCode( const char* pString )
|
||||
{
|
||||
unsigned long i,len;
|
||||
unsigned long ch;
|
||||
unsigned long result;
|
||||
|
||||
len = strlen( pString );
|
||||
result = 5381;
|
||||
for( i=0; i<len; i++ )
|
||||
{
|
||||
ch = (unsigned long)pString[i];
|
||||
result = ((result<< 5) + result) + ch; // hash * 33 + ch
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool CItemManager::LoadItemTable(const char* c_szFileName)
|
||||
{
|
||||
CMappedFile file;
|
||||
LPCVOID pvData;
|
||||
|
||||
if (!CEterPackManager::Instance().Get(file, c_szFileName, &pvData))
|
||||
return false;
|
||||
|
||||
DWORD dwFourCC, dwElements, dwDataSize;
|
||||
DWORD dwVersion=0;
|
||||
DWORD dwStride=0;
|
||||
|
||||
file.Read(&dwFourCC, sizeof(DWORD));
|
||||
|
||||
if (dwFourCC == MAKEFOURCC('M', 'I', 'P', 'X'))
|
||||
{
|
||||
file.Read(&dwVersion, sizeof(DWORD));
|
||||
file.Read(&dwStride, sizeof(DWORD));
|
||||
|
||||
if (dwVersion != 1)
|
||||
{
|
||||
TraceError("CPythonItem::LoadItemTable: invalid item_proto[%s] VERSION[%d]", c_szFileName, dwVersion);
|
||||
return false;
|
||||
}
|
||||
if (dwStride != sizeof(CItemData::TItemTable))
|
||||
{
|
||||
TraceError("CPythonItem::LoadItemTable: invalid item_proto[%s] STRIDE[%d] != sizeof(SItemTable)",
|
||||
c_szFileName, dwStride, sizeof(CItemData::TItemTable));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (dwFourCC != MAKEFOURCC('M', 'I', 'P', 'T'))
|
||||
{
|
||||
TraceError("CPythonItem::LoadItemTable: invalid item proto type %s", c_szFileName);
|
||||
return false;
|
||||
}
|
||||
|
||||
file.Read(&dwElements, sizeof(DWORD));
|
||||
file.Read(&dwDataSize, sizeof(DWORD));
|
||||
|
||||
BYTE * pbData = new BYTE[dwDataSize];
|
||||
file.Read(pbData, dwDataSize);
|
||||
|
||||
/////
|
||||
|
||||
CLZObject zObj;
|
||||
|
||||
if (!CLZO::Instance().Decompress(zObj, pbData, s_adwItemProtoKey))
|
||||
{
|
||||
delete [] pbData;
|
||||
return false;
|
||||
}
|
||||
|
||||
/////
|
||||
|
||||
char szName[64+1];
|
||||
|
||||
CItemData::TItemTable * table = (CItemData::TItemTable *) zObj.GetBuffer();
|
||||
std::map<DWORD,DWORD> itemNameMap;
|
||||
|
||||
for (DWORD i = 0; i < dwElements; ++i, ++table)
|
||||
{
|
||||
CItemData * pItemData;
|
||||
DWORD dwVnum = table->dwVnum;
|
||||
|
||||
TItemMap::iterator f = m_ItemMap.find(dwVnum);
|
||||
if (m_ItemMap.end() == f)
|
||||
{
|
||||
_snprintf(szName, sizeof(szName), "icon/item/%05d.tga", dwVnum);
|
||||
|
||||
if (CResourceManager::Instance().IsFileExist(szName) == false)
|
||||
{
|
||||
std::map<DWORD, DWORD>::iterator itVnum = itemNameMap.find(GetHashCode(table->szName));
|
||||
|
||||
if (itVnum != itemNameMap.end())
|
||||
_snprintf(szName, sizeof(szName), "icon/item/%05d.tga", itVnum->second);
|
||||
else
|
||||
_snprintf(szName, sizeof(szName), "icon/item/%05d.tga", dwVnum-dwVnum % 10);
|
||||
|
||||
if (CResourceManager::Instance().IsFileExist(szName) == false)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
TraceError("%16s(#%-5d) cannot find icon file. setting to default.", table->szName, dwVnum);
|
||||
#endif
|
||||
const DWORD EmptyBowl = 27995;
|
||||
_snprintf(szName, sizeof(szName), "icon/item/%05d.tga", EmptyBowl);
|
||||
}
|
||||
}
|
||||
|
||||
pItemData = CItemData::New();
|
||||
|
||||
pItemData->SetDefaultItemData(szName);
|
||||
m_ItemMap.insert(TItemMap::value_type(dwVnum, pItemData));
|
||||
}
|
||||
else
|
||||
{
|
||||
pItemData = f->second;
|
||||
}
|
||||
if (itemNameMap.find(GetHashCode(table->szName)) == itemNameMap.end())
|
||||
itemNameMap.insert(std::map<DWORD,DWORD>::value_type(GetHashCode(table->szName),table->dwVnum));
|
||||
pItemData->SetItemTableData(table);
|
||||
if (0 != table->dwVnumRange)
|
||||
{
|
||||
m_vec_ItemRange.push_back(pItemData);
|
||||
}
|
||||
}
|
||||
|
||||
//!@#
|
||||
// CItemData::TItemTable * table = (CItemData::TItemTable *) zObj.GetBuffer();
|
||||
// for (DWORD i = 0; i < dwElements; ++i, ++table)
|
||||
// {
|
||||
// CItemData * pItemData;
|
||||
// DWORD dwVnum = table->dwVnum;
|
||||
//
|
||||
// TItemMap::iterator f = m_ItemMap.find(dwVnum);
|
||||
//
|
||||
// if (m_ItemMap.end() == f)
|
||||
// {
|
||||
// pItemData = CItemData::New();
|
||||
//
|
||||
// pItemData->LoadItemData(_getf("d:/ymir work/item/%05d.msm", dwVnum));
|
||||
// m_ItemMap.insert(TItemMap::value_type(dwVnum, pItemData));
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// pItemData = f->second;
|
||||
// }
|
||||
// pItemData->SetItemTableData(table);
|
||||
// }
|
||||
|
||||
delete [] pbData;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CItemManager::Destroy()
|
||||
{
|
||||
TItemMap::iterator i;
|
||||
for (i=m_ItemMap.begin(); i!=m_ItemMap.end(); ++i)
|
||||
CItemData::Delete(i->second);
|
||||
|
||||
m_ItemMap.clear();
|
||||
}
|
||||
|
||||
CItemManager::CItemManager() : m_pSelectedItemData(NULL)
|
||||
{
|
||||
}
|
||||
CItemManager::~CItemManager()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
#include "StdAfx.h"
|
||||
#include "../EterPack/EterPackManager.h"
|
||||
#include "PythonNonPlayer.h"
|
||||
#include "InstanceBase.h"
|
||||
#include "PythonCharacterManager.h"
|
||||
|
||||
bool CPythonNonPlayer::LoadNonPlayerData(const char * c_szFileName)
|
||||
{
|
||||
static DWORD s_adwMobProtoKey[4] =
|
||||
{
|
||||
4813894,
|
||||
18955,
|
||||
552631,
|
||||
6822045
|
||||
};
|
||||
|
||||
CMappedFile file;
|
||||
LPCVOID pvData;
|
||||
|
||||
Tracef("CPythonNonPlayer::LoadNonPlayerData: %s, sizeof(TMobTable)=%u\n", c_szFileName, sizeof(TMobTable));
|
||||
|
||||
if (!CEterPackManager::Instance().Get(file, c_szFileName, &pvData))
|
||||
return false;
|
||||
|
||||
DWORD dwFourCC, dwElements, dwDataSize;
|
||||
|
||||
file.Read(&dwFourCC, sizeof(DWORD));
|
||||
|
||||
if (dwFourCC != MAKEFOURCC('M', 'M', 'P', 'T'))
|
||||
{
|
||||
TraceError("CPythonNonPlayer::LoadNonPlayerData: invalid Mob proto type %s", c_szFileName);
|
||||
return false;
|
||||
}
|
||||
|
||||
file.Read(&dwElements, sizeof(DWORD));
|
||||
file.Read(&dwDataSize, sizeof(DWORD));
|
||||
|
||||
BYTE * pbData = new BYTE[dwDataSize];
|
||||
file.Read(pbData, dwDataSize);
|
||||
/////
|
||||
|
||||
CLZObject zObj;
|
||||
|
||||
if (!CLZO::Instance().Decompress(zObj, pbData, s_adwMobProtoKey))
|
||||
{
|
||||
delete [] pbData;
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((zObj.GetSize() % sizeof(TMobTable)) != 0)
|
||||
{
|
||||
TraceError("CPythonNonPlayer::LoadNonPlayerData: invalid size %u check data format.", zObj.GetSize());
|
||||
return false;
|
||||
}
|
||||
|
||||
TMobTable * pTable = (TMobTable *) zObj.GetBuffer();
|
||||
for (DWORD i = 0; i < dwElements; ++i, ++pTable)
|
||||
{
|
||||
TMobTable * pNonPlayerData = new TMobTable;
|
||||
|
||||
memcpy(pNonPlayerData, pTable, sizeof(TMobTable));
|
||||
|
||||
//TraceError("%d : %s type[%d] color[%d]", pNonPlayerData->dwVnum, pNonPlayerData->szLocaleName, pNonPlayerData->bType, pNonPlayerData->dwMonsterColor);
|
||||
m_NonPlayerDataMap.insert(TNonPlayerDataMap::value_type(pNonPlayerData->dwVnum, pNonPlayerData));
|
||||
}
|
||||
|
||||
delete [] pbData;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPythonNonPlayer::GetName(DWORD dwVnum, const char ** c_pszName)
|
||||
{
|
||||
const TMobTable * p = GetTable(dwVnum);
|
||||
|
||||
if (!p)
|
||||
return false;
|
||||
|
||||
*c_pszName = p->szLocaleName;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPythonNonPlayer::GetInstanceType(DWORD dwVnum, BYTE* pbType)
|
||||
{
|
||||
const TMobTable * p = GetTable(dwVnum);
|
||||
|
||||
// dwVnum를 찾을 수 없으면 플레이어 캐릭터로 간주 한다. 문제성 코드 -_- [cronan]
|
||||
if (!p)
|
||||
return false;
|
||||
|
||||
*pbType=p->bType;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const CPythonNonPlayer::TMobTable * CPythonNonPlayer::GetTable(DWORD dwVnum)
|
||||
{
|
||||
TNonPlayerDataMap::iterator itor = m_NonPlayerDataMap.find(dwVnum);
|
||||
|
||||
if (itor == m_NonPlayerDataMap.end())
|
||||
return NULL;
|
||||
|
||||
return itor->second;
|
||||
}
|
||||
|
||||
BYTE CPythonNonPlayer::GetEventType(DWORD dwVnum)
|
||||
{
|
||||
const TMobTable * p = GetTable(dwVnum);
|
||||
|
||||
if (!p)
|
||||
{
|
||||
//Tracef("CPythonNonPlayer::GetEventType - Failed to find virtual number\n");
|
||||
return ON_CLICK_EVENT_NONE;
|
||||
}
|
||||
|
||||
return p->bOnClickType;
|
||||
}
|
||||
|
||||
BYTE CPythonNonPlayer::GetEventTypeByVID(DWORD dwVID)
|
||||
{
|
||||
CInstanceBase * pInstance = CPythonCharacterManager::Instance().GetInstancePtr(dwVID);
|
||||
|
||||
if (NULL == pInstance)
|
||||
{
|
||||
//Tracef("CPythonNonPlayer::GetEventTypeByVID - There is no Virtual Number\n");
|
||||
return ON_CLICK_EVENT_NONE;
|
||||
}
|
||||
|
||||
WORD dwVnum = pInstance->GetVirtualNumber();
|
||||
return GetEventType(dwVnum);
|
||||
}
|
||||
|
||||
const char* CPythonNonPlayer::GetMonsterName(DWORD dwVnum)
|
||||
{
|
||||
const CPythonNonPlayer::TMobTable * c_pTable = GetTable(dwVnum);
|
||||
if (!c_pTable)
|
||||
{
|
||||
static const char* sc_szEmpty="";
|
||||
return sc_szEmpty;
|
||||
}
|
||||
|
||||
return c_pTable->szLocaleName;
|
||||
}
|
||||
|
||||
DWORD CPythonNonPlayer::GetMonsterColor(DWORD dwVnum)
|
||||
{
|
||||
const CPythonNonPlayer::TMobTable * c_pTable = GetTable(dwVnum);
|
||||
if (!c_pTable)
|
||||
return 0;
|
||||
|
||||
return c_pTable->dwMonsterColor;
|
||||
}
|
||||
|
||||
void CPythonNonPlayer::GetMatchableMobList(int iLevel, int iInterval, TMobTableList * pMobTableList)
|
||||
{
|
||||
/*
|
||||
pMobTableList->clear();
|
||||
|
||||
TNonPlayerDataMap::iterator itor = m_NonPlayerDataMap.begin();
|
||||
for (; itor != m_NonPlayerDataMap.end(); ++itor)
|
||||
{
|
||||
TMobTable * pMobTable = itor->second;
|
||||
|
||||
int iLowerLevelLimit = iLevel-iInterval;
|
||||
int iUpperLevelLimit = iLevel+iInterval;
|
||||
|
||||
if ((pMobTable->abLevelRange[0] >= iLowerLevelLimit && pMobTable->abLevelRange[0] <= iUpperLevelLimit) ||
|
||||
(pMobTable->abLevelRange[1] >= iLowerLevelLimit && pMobTable->abLevelRange[1] <= iUpperLevelLimit))
|
||||
{
|
||||
pMobTableList->push_back(pMobTable);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void CPythonNonPlayer::Clear()
|
||||
{
|
||||
}
|
||||
|
||||
void CPythonNonPlayer::Destroy()
|
||||
{
|
||||
for (TNonPlayerDataMap::iterator itor=m_NonPlayerDataMap.begin(); itor!=m_NonPlayerDataMap.end(); ++itor)
|
||||
{
|
||||
delete itor->second;
|
||||
}
|
||||
m_NonPlayerDataMap.clear();
|
||||
}
|
||||
|
||||
CPythonNonPlayer::CPythonNonPlayer()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
CPythonNonPlayer::~CPythonNonPlayer(void)
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
#include "StdAfx.h"
|
||||
#include "PythonNonPlayer.h"
|
||||
|
||||
#include "InstanceBase.h"
|
||||
#include "PythonCharacterManager.h"
|
||||
|
||||
PyObject * nonplayerGetEventType(PyObject * poSelf, PyObject * poArgs)
|
||||
{
|
||||
int iVirtualNumber;
|
||||
if (!PyTuple_GetInteger(poArgs, 0, &iVirtualNumber))
|
||||
return Py_BuildException();
|
||||
|
||||
BYTE iType = CPythonNonPlayer::Instance().GetEventType(iVirtualNumber);
|
||||
|
||||
return Py_BuildValue("i", iType);
|
||||
}
|
||||
|
||||
PyObject * nonplayerGetEventTypeByVID(PyObject * poSelf, PyObject * poArgs)
|
||||
{
|
||||
int iVirtualID;
|
||||
if (!PyTuple_GetInteger(poArgs, 0, &iVirtualID))
|
||||
return Py_BuildException();
|
||||
|
||||
BYTE iType = CPythonNonPlayer::Instance().GetEventTypeByVID(iVirtualID);
|
||||
|
||||
return Py_BuildValue("i", iType);
|
||||
}
|
||||
|
||||
PyObject * nonplayerGetLevelByVID(PyObject * poSelf, PyObject * poArgs)
|
||||
{
|
||||
int iVirtualID;
|
||||
if (!PyTuple_GetInteger(poArgs, 0, &iVirtualID))
|
||||
return Py_BuildException();
|
||||
|
||||
CInstanceBase * pInstance = CPythonCharacterManager::Instance().GetInstancePtr(iVirtualID);
|
||||
|
||||
if (!pInstance)
|
||||
return Py_BuildValue("i", -1);
|
||||
|
||||
const CPythonNonPlayer::TMobTable * pMobTable = CPythonNonPlayer::Instance().GetTable(pInstance->GetVirtualNumber());
|
||||
|
||||
if (!pMobTable)
|
||||
return Py_BuildValue("i", -1);
|
||||
|
||||
float fAverageLevel = pMobTable->bLevel;//(float(pMobTable->abLevelRange[0]) + float(pMobTable->abLevelRange[1])) / 2.0f;
|
||||
fAverageLevel = floor(fAverageLevel + 0.5f);
|
||||
return Py_BuildValue("i", int(fAverageLevel));
|
||||
}
|
||||
|
||||
PyObject * nonplayerGetGradeByVID(PyObject * poSelf, PyObject * poArgs)
|
||||
{
|
||||
int iVirtualID;
|
||||
if (!PyTuple_GetInteger(poArgs, 0, &iVirtualID))
|
||||
return Py_BuildException();
|
||||
|
||||
CInstanceBase * pInstance = CPythonCharacterManager::Instance().GetInstancePtr(iVirtualID);
|
||||
|
||||
if (!pInstance)
|
||||
return Py_BuildValue("i", -1);
|
||||
|
||||
const CPythonNonPlayer::TMobTable * pMobTable = CPythonNonPlayer::Instance().GetTable(pInstance->GetVirtualNumber());
|
||||
|
||||
if (!pMobTable)
|
||||
return Py_BuildValue("i", -1);
|
||||
|
||||
return Py_BuildValue("i", pMobTable->bRank);
|
||||
}
|
||||
|
||||
|
||||
PyObject * nonplayerGetMonsterName(PyObject * poSelf, PyObject * poArgs)
|
||||
{
|
||||
int iVNum;
|
||||
if (!PyTuple_GetInteger(poArgs, 0, &iVNum))
|
||||
return Py_BuildException();
|
||||
|
||||
CPythonNonPlayer& rkNonPlayer=CPythonNonPlayer::Instance();
|
||||
return Py_BuildValue("s", rkNonPlayer.GetMonsterName(iVNum));
|
||||
}
|
||||
|
||||
PyObject * nonplayerLoadNonPlayerData(PyObject * poSelf, PyObject * poArgs)
|
||||
{
|
||||
char * szFileName;
|
||||
if(!PyTuple_GetString(poArgs, 0, &szFileName))
|
||||
return Py_BuildException();
|
||||
|
||||
CPythonNonPlayer::Instance().LoadNonPlayerData(szFileName);
|
||||
return Py_BuildNone();
|
||||
}
|
||||
|
||||
void initNonPlayer()
|
||||
{
|
||||
static PyMethodDef s_methods[] =
|
||||
{
|
||||
{ "GetEventType", nonplayerGetEventType, METH_VARARGS },
|
||||
{ "GetEventTypeByVID", nonplayerGetEventTypeByVID, METH_VARARGS },
|
||||
{ "GetLevelByVID", nonplayerGetLevelByVID, METH_VARARGS },
|
||||
{ "GetGradeByVID", nonplayerGetGradeByVID, METH_VARARGS },
|
||||
{ "GetMonsterName", nonplayerGetMonsterName, METH_VARARGS },
|
||||
|
||||
{ "LoadNonPlayerData", nonplayerLoadNonPlayerData, METH_VARARGS },
|
||||
|
||||
{ NULL, NULL, NULL },
|
||||
};
|
||||
|
||||
PyObject * poModule = Py_InitModule("nonplayer", s_methods);
|
||||
|
||||
PyModule_AddIntConstant(poModule, "ON_CLICK_EVENT_NONE", CPythonNonPlayer::ON_CLICK_EVENT_NONE);
|
||||
PyModule_AddIntConstant(poModule, "ON_CLICK_EVENT_BATTLE", CPythonNonPlayer::ON_CLICK_EVENT_BATTLE);
|
||||
PyModule_AddIntConstant(poModule, "ON_CLICK_EVENT_SHOP", CPythonNonPlayer::ON_CLICK_EVENT_SHOP);
|
||||
PyModule_AddIntConstant(poModule, "ON_CLICK_EVENT_TALK", CPythonNonPlayer::ON_CLICK_EVENT_TALK);
|
||||
PyModule_AddIntConstant(poModule, "ON_CLICK_EVENT_VEHICLE", CPythonNonPlayer::ON_CLICK_EVENT_VEHICLE);
|
||||
|
||||
PyModule_AddIntConstant(poModule, "PAWN", 0);
|
||||
PyModule_AddIntConstant(poModule, "S_PAWN", 1);
|
||||
PyModule_AddIntConstant(poModule, "KNIGHT", 2);
|
||||
PyModule_AddIntConstant(poModule, "S_KNIGHT", 3);
|
||||
PyModule_AddIntConstant(poModule, "BOSS", 4);
|
||||
PyModule_AddIntConstant(poModule, "KING", 5);
|
||||
}
|
||||
@@ -47,6 +47,7 @@ void initapp();
|
||||
void initchr();
|
||||
void initchrmgr();
|
||||
void initPlayer();
|
||||
void initNonPlayer();
|
||||
void initChat();
|
||||
void initnet();
|
||||
void initeffect();
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#include "GameLib/RaceMotionData.h"
|
||||
#include "GameLib/FlyingData.h"
|
||||
#include "GameLib/FlyingObjectManager.h"
|
||||
#include "GameLib/ItemManager.h"
|
||||
#include "UserInterface/StdAfx.h"
|
||||
#include "UserInterface/PythonCharacterManager.h"
|
||||
#include "UserInterface/InstanceBase.h"
|
||||
@@ -297,6 +298,23 @@ int main(int argc, char** argv)
|
||||
CHECK(server->Has("state:checker"));
|
||||
}
|
||||
|
||||
// 3c. SetSelectCharacterPhase ran localeInfo.LoadLocaleData() → app.LoadLocaleData(app.GetLocalePath()):
|
||||
// CItemManager read item_list.txt/item_proto/itemdesc.txt and CPythonNonPlayer read mob_proto.
|
||||
{
|
||||
CItemData* sword = nullptr;
|
||||
CHECK(CItemManager::Instance().GetItemDataPointer(19, &sword) && sword);
|
||||
if (sword)
|
||||
{
|
||||
std::printf("port_login_flow_test: item 19 %s type %u refine %u\n", sword->GetName(), sword->GetType(), sword->GetRefine());
|
||||
CHECK(sword->GetType() == CItemData::ITEM_TYPE_WEAPON && sword->GetRefine() == 9);
|
||||
CHECK(sword->GetModelThing() != nullptr);
|
||||
}
|
||||
CHECK(py("import nonplayer\n"
|
||||
"_mob = nonplayer.GetMonsterName(101)\n"
|
||||
"assert _mob, 'mob 101 has no name'\n"
|
||||
"import sys\nsys.stderr.write('port_login_flow_test: mob 101 %s\\n' % _mob)"));
|
||||
}
|
||||
|
||||
// 4-5. Start the game on the slot: DirectEnter, the second game login and the loading phase.
|
||||
if (selecting)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user