- Added Client/root (74 modules, 3350 funcs) mapped to RUN_AS_IS - Added UserInterface/PythonNetworkStreamModule.cpp.json mapped to PORTED - Implemented AudioCommands queue bridging MilesLib SoundManager to Godot AudioDriver - Implemented AudioDriver node for BGM crossfading, 2D UI SFX and 3D spatial sounds - Implemented core platform stubs in PythonApplication, GrpScreen, and PythonGraphic - Passed all 12 port tests (port_gate macos) and python_game_render_test
544 lines
18 KiB
C++
544 lines
18 KiB
C++
#include "UserInterface/StdAfx.h"
|
|
#include "UserInterface/PythonApplication.h"
|
|
#include "UserInterface/MarkManager.h"
|
|
#include "GameLib/GameUtil.h"
|
|
#include "EterLib/Camera.h"
|
|
#include "EterBase/Timer.h"
|
|
#include "EterLib/ResourceManager.h"
|
|
#include "UserInterface/PythonNetworkStream.h"
|
|
#include "UserInterface/AccountConnector.h"
|
|
#include "UserInterface/PythonItem.h"
|
|
#include "UserInterface/PythonTextTail.h"
|
|
#include "UserInterface/PythonSkill.h"
|
|
#include "UserInterface/PythonNonPlayer.h"
|
|
#include "GameLib/ItemManager.h"
|
|
#include "EterLib/NetDevice.h"
|
|
#include "../PlatformStub.h"
|
|
#include "../EterLib/UIRenderCommands.h"
|
|
#include "../EterLib/RenderCommands3D.h"
|
|
#include "EterLib/GrpDevice.h"
|
|
#include "../ScriptLib/PythonBoot.h"
|
|
|
|
// 2V0-d link surface; 2V0-f adds the application lifecycle (Create/Loop/Process/Exit) that
|
|
// prototype.RunApp() drives. The rest of the members still wait for the game slices (2V1-2V3).
|
|
//
|
|
// PORT: there is no CPythonApplication object yet (its members are the whole game: background,
|
|
// network stream, player, ...), so these functions only use the singletons PythonBoot owns
|
|
// (UI::CWindowManager, CTimer, CResourceManager) and never touch a data member.
|
|
CPythonApplication* CPythonApplication::ms_pInstance = nullptr;
|
|
|
|
void CPythonApplication::ShowWebPage(const char*, const RECT&) { MT_PLATFORM_STUB(); }
|
|
void CPythonApplication::MoveWebPage(const RECT&) { MT_PLATFORM_STUB(); }
|
|
void CPythonApplication::HideWebPage() { MT_PLATFORM_STUB(); }
|
|
bool CPythonApplication::IsWebPageMode() { MT_PLATFORM_STUB(); return false; }
|
|
void CPythonApplication::GetInfo(UINT, std::string* out) { MT_PLATFORM_STUB(); if (out) out->clear(); }
|
|
// In 40250, Loop() is: while (1) { if (IsMessage()) { if (!MessageProcess()) break; } else { if (!Process()) break; } }
|
|
// PORT: Godot owns the message pump and forwards input to the window manager between frames
|
|
// (PythonBoot::UIMouseMove & co.), so the loop here only waits for the host's next frame. It runs
|
|
// on PythonBoot's script thread; WM_QUIT is PythonBoot::AppRequestQuit.
|
|
void CPythonApplication::Loop()
|
|
{
|
|
while (PythonBoot::AppLoopWait())
|
|
{
|
|
if (!Process())
|
|
break;
|
|
}
|
|
}
|
|
|
|
// In 40250 this is PostQuitMessage(0).
|
|
void CPythonApplication::Exit() { PythonBoot::AppRequestQuit(); }
|
|
|
|
// 40250 also writes a TraceError banner first; the caller (system.py) has already logged the reason.
|
|
void CPythonApplication::Abort()
|
|
{
|
|
TraceError("============================================================================================================");
|
|
TraceError("Abort!!!!\n\n");
|
|
PythonBoot::AppRequestQuit();
|
|
}
|
|
static float MIN_FOG = 2400.0f;
|
|
void CPythonApplication::SetMinFog(float fMinFog) { MIN_FOG = fMinFog; }
|
|
// In 40250 Process() copies CTimer::GetCurrentSecond() into m_fGlobalTime right after Advance() and
|
|
// this returns it. PORT: no member to hold it; the timer only advances in Process(), so reading it
|
|
// here gives the same value.
|
|
float CPythonApplication::GetGlobalTime() { return CTimer::Instance().GetCurrentSecond(); }
|
|
// In 40250 Process() also copies CTimer::GetElapsedSecond() into m_fGlobalElapsedTime (PythonApplication.cpp:448).
|
|
// PORT: read straight from the timer, as GetGlobalTime above.
|
|
float CPythonApplication::GetGlobalElapsedTime() { return CTimer::Instance().GetElapsedSecond(); }
|
|
static bool s_isFrameSkipDisable = false;
|
|
void CPythonApplication::SetFrameSkip(bool isEnable) { s_isFrameSkipDisable = !isEnable; }
|
|
// PORT: 40250 creates the Win32 window, the D3D8 device, cursors, sound, keyboard, the net device,
|
|
// fonts and the IME here. The Godot window and its canvas already exist when the host starts the
|
|
// script, so the window size is the canvas size (PythonBoot::SetUISize) rather than the width/height
|
|
// passed from metin2.cfg, and the graphic device is the recording device (RecordingDevice.h) at that
|
|
// size. Cursors, sound, keyboard and fonts are not created here yet.
|
|
bool CPythonApplication::Create(PyObject*, const char*, int, int, int)
|
|
{
|
|
unsigned width = 0, height = 0;
|
|
UIRenderGetSize(&width, &height);
|
|
if (!width || !height)
|
|
{
|
|
// appCreate returns NULL on failure; RunApp turns this into the original LogBox.
|
|
TraceError("CreateDevice: GraphicDevice create failed");
|
|
PyErr_SetString(PyExc_RuntimeError, "CREATE_DEVICE");
|
|
return false;
|
|
}
|
|
|
|
// In 40250 m_grpDevice is a member created here (PythonApplication.cpp:909).
|
|
static CGraphicDevice s_grpDevice;
|
|
int iRet = s_grpDevice.Create(NULL, width, height, true, 32, 0);
|
|
|
|
switch (iRet)
|
|
{
|
|
case CGraphicDevice::CREATE_OK:
|
|
break;
|
|
|
|
case CGraphicDevice::CREATE_REFRESHRATE:
|
|
break;
|
|
|
|
case CGraphicDevice::CREATE_GET_DEVICE_CAPS:
|
|
PyErr_SetString(PyExc_RuntimeError, "GetDevCaps failed");
|
|
TraceError("CreateDevice: GetDevCaps failed");
|
|
return false;
|
|
|
|
case CGraphicDevice::CREATE_GET_DEVICE_CAPS2:
|
|
PyErr_SetString(PyExc_RuntimeError, "GetDevCaps2 failed");
|
|
TraceError("CreateDevice: GetDevCaps2 failed");
|
|
return false;
|
|
|
|
default:
|
|
// PORT: the recording device returns only the cases above; the rest is 40250's fallback.
|
|
if (iRet & CGraphicDevice::CREATE_OK)
|
|
break;
|
|
|
|
TraceError("CreateDevice: Unknown Error!");
|
|
PyErr_SetString(PyExc_RuntimeError, "UNKNOWN_ERROR");
|
|
return false;
|
|
}
|
|
|
|
// In 40250 m_netDevice is a member created here (PythonApplication.cpp:1242).
|
|
static CNetworkDevice s_netDevice;
|
|
if (!s_netDevice.Create())
|
|
{
|
|
TraceError("NetDevice::Create failed");
|
|
PyErr_SetString(PyExc_RuntimeError, "CREATE_NETWORK");
|
|
return false;
|
|
}
|
|
|
|
// 40250 m_pyItem.Create() (PythonApplication.cpp:1253): registers dropitem.mse with CEffectManager.
|
|
CPythonItem::Instance().Create();
|
|
|
|
// 40250 PythonApplication.cpp:1258-1259 (after DefaultFont_Startup).
|
|
CPythonIME::Instance().Create(GetWindowHandle());
|
|
CPythonIME::Instance().SetText("", 0);
|
|
|
|
// 40250 PythonApplication.cpp:1260.
|
|
CPythonTextTail::Instance().Initialize();
|
|
return true;
|
|
}
|
|
// 40250 PythonApplication.cpp:105
|
|
void CPythonApplication::GetMousePosition(POINT* ppt)
|
|
{
|
|
CMSApplication::GetMousePosition(ppt);
|
|
}
|
|
|
|
// 40250 PythonApplication.cpp:168, the !PERF_CHECKER_RENDER_GAME branch (the profiling copy below it
|
|
// only adds timers). game.GameWindow.OnRender calls it every frame.
|
|
// PORT: the members are reached through their singletons (see the note at the top of the file).
|
|
void CPythonApplication::RenderGame()
|
|
{
|
|
float fAspect=UI::CWindowManager::Instance().GetAspect();
|
|
float fFarClip=CPythonBackground::Instance().GetFarClip();
|
|
|
|
CPythonGraphic::Instance().SetPerspective(30.0f, fAspect, 100.0, fFarClip);
|
|
|
|
CCullingManager::Instance().Process();
|
|
|
|
CPythonCharacterManager::Instance().Deform();
|
|
CEffectManager::Instance().Update();
|
|
|
|
CPythonBackground::Instance().RenderCharacterShadowToTexture();
|
|
|
|
CPythonGraphic::Instance().SetGameRenderState();
|
|
CPythonGraphic::Instance().PushState();
|
|
|
|
{
|
|
long lx, ly;
|
|
UI::CWindowManager::Instance().GetMousePosition(lx, ly);
|
|
CPythonGraphic::Instance().SetCursorPosition(lx, ly);
|
|
}
|
|
|
|
CPythonBackground::Instance().RenderSky();
|
|
|
|
CPythonBackground::Instance().RenderBeforeLensFlare();
|
|
|
|
CPythonBackground::Instance().RenderCloud();
|
|
|
|
CPythonBackground::Instance().BeginEnvironment();
|
|
CPythonBackground::Instance().Render();
|
|
|
|
CPythonBackground::Instance().SetCharacterDirLight();
|
|
CPythonCharacterManager::Instance().Render();
|
|
|
|
CPythonBackground::Instance().SetBackgroundDirLight();
|
|
CPythonBackground::Instance().RenderWater();
|
|
CPythonBackground::Instance().RenderSnow();
|
|
CPythonBackground::Instance().RenderEffect();
|
|
|
|
CPythonBackground::Instance().EndEnvironment();
|
|
|
|
CEffectManager::Instance().Render();
|
|
CPythonItem::Instance().Render();
|
|
CFlyingManager::Instance().Render();
|
|
|
|
CPythonBackground::Instance().BeginEnvironment();
|
|
CPythonBackground::Instance().RenderPCBlocker();
|
|
CPythonBackground::Instance().EndEnvironment();
|
|
|
|
CPythonBackground::Instance().RenderAfterLensFlare();
|
|
}
|
|
|
|
// 40250 PythonApplication.cpp:321 without the PERF_CHECKER_RENDER_GAME timers. game.GameWindow.OnUpdate
|
|
// calls it every frame. PORT: members through their singletons, as in RenderGame.
|
|
void CPythonApplication::UpdateGame()
|
|
{
|
|
POINT ptMouse;
|
|
GetMousePosition(&ptMouse);
|
|
|
|
CGraphicTextInstance::Hyperlink_UpdateMousePos(ptMouse.x, ptMouse.y);
|
|
|
|
//!@# Alt+Tab 중 SetTransfor 에서 튕김 현상 해결을 위해 - [levites]
|
|
//if (m_isActivateWnd)
|
|
{
|
|
CScreen s;
|
|
float fAspect = UI::CWindowManager::Instance().GetAspect();
|
|
float fFarClip = CPythonBackground::Instance().GetFarClip();
|
|
|
|
s.SetPerspective(30.0f,fAspect, 100.0f, fFarClip);
|
|
s.BuildViewFrustum();
|
|
}
|
|
|
|
TPixelPosition kPPosMainActor;
|
|
CPythonPlayer::Instance().NEW_GetMainActorPosition(&kPPosMainActor);
|
|
|
|
CPythonBackground::Instance().Update(kPPosMainActor.x, kPPosMainActor.y, kPPosMainActor.z);
|
|
|
|
CGameEventManager::Instance().SetCenterPosition(kPPosMainActor.x, kPPosMainActor.y, kPPosMainActor.z);
|
|
CGameEventManager::Instance().Update();
|
|
|
|
CPythonCharacterManager::Instance().Update();
|
|
CEffectManager::Instance().UpdateSound();
|
|
CFlyingManager::Instance().Update();
|
|
CPythonItem::Instance().Update(ptMouse);
|
|
CPythonPlayer::Instance().Update();
|
|
|
|
// NOTE : Update 에서 위치 값이 바뀌므로 다시 얻어 옵니다 - [levites]
|
|
// 이 부분 때문에 메인 케릭터의 Sound가 이전 위치에서 플레이 되는 현상이 있었음.
|
|
CPythonPlayer::Instance().NEW_GetMainActorPosition(&kPPosMainActor);
|
|
SetCenterPosition(kPPosMainActor.x, kPPosMainActor.y, kPPosMainActor.z);
|
|
}
|
|
|
|
// 40250 PythonApplication.cpp:399. Kept in order: timer, network (2V1), input polling (Godot pushes
|
|
// input instead), camera (2V3), resource GC, mouse/UI update, then the render block's interface pass.
|
|
// PORT: the frame-skip bookkeeping and the game render pass are left out; the Godot frame clock
|
|
// decides when this runs, and RenderGame belongs to 2V3.
|
|
bool CPythonApplication::Process()
|
|
{
|
|
ELTimer_SetFrameMSec();
|
|
|
|
CTimer& rkTimer=CTimer::Instance();
|
|
rkTimer.Advance();
|
|
|
|
// Network I/O
|
|
CPythonNetworkStream::Instance().Process();
|
|
// PORT: m_kGuildMarkUploader/m_kGuildMarkDownloader.Process() follow here in 40250; the guild mark
|
|
// transfer is not ported yet (GuildMarkDownloader.cpp/GuildMarkUploader.cpp).
|
|
CAccountConnector::Instance().Process();
|
|
|
|
//!@# Alt+Tab 중 SetTransfor 에서 튕김 현상 해결을 위해 - [levites]
|
|
//if (m_isActivateWnd)
|
|
__UpdateCamera();
|
|
|
|
CResourceManager::Instance().Update();
|
|
|
|
OnCameraUpdate();
|
|
OnUIUpdate();
|
|
|
|
// PORT: the render block without the lost-device restore, ClearDepthBuffer, Show and the render-time
|
|
// statistics (Godot clears and presents the frame). The frame's UI and 3D command lists restart here.
|
|
CCullingManager::Instance().Update();
|
|
UIRenderBeginFrame();
|
|
Render3DBeginFrame();
|
|
CPythonGraphic& rkGraphic = CPythonGraphic::Instance();
|
|
if (rkGraphic.Begin())
|
|
{
|
|
rkGraphic.SetInterfaceRenderState();
|
|
|
|
OnUIRender();
|
|
|
|
rkGraphic.End();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// 40250 PythonApplicationCursor.cpp. PORT: the members live here until the application object exists
|
|
// (initial values from the constructor and CreateCursors); the host draws no hardware cursor, so every
|
|
// shape in [0, CURSOR_COUNT) counts as loaded in place of m_CursorHandleMap.
|
|
PyObject* s_poMouseHandler = NULL; // m_poMouseHandler
|
|
namespace
|
|
{
|
|
int s_iCursorNum = CPythonApplication::CURSOR_SHAPE_NORMAL; // m_iCursorNum
|
|
int s_iContinuousCursorNum = CPythonApplication::CURSOR_SHAPE_NORMAL; // m_iContinuousCursorNum
|
|
BOOL s_bCursorVisible = TRUE; // m_bCursorVisible
|
|
bool s_bLiarCursorOn = false; // m_bLiarCursorOn
|
|
int s_iCursorMode = CPythonApplication::CURSOR_MODE_HARDWARE; // m_iCursorMode
|
|
}
|
|
|
|
void CPythonApplication::SetCursorVisible(BOOL bFlag, bool bLiarCursorOn)
|
|
{
|
|
s_bCursorVisible = bFlag;
|
|
s_bLiarCursorOn = bLiarCursorOn;
|
|
// PORT: 40250 also counts ShowCursor up or down in hardware mode; the host has no OS cursor to hide.
|
|
}
|
|
|
|
BOOL CPythonApplication::GetCursorVisible()
|
|
{
|
|
return s_bCursorVisible;
|
|
}
|
|
|
|
bool CPythonApplication::GetLiarCursorOn()
|
|
{
|
|
return s_bLiarCursorOn;
|
|
}
|
|
|
|
int CPythonApplication::GetCursorMode()
|
|
{
|
|
return s_iCursorMode;
|
|
}
|
|
|
|
int CPythonApplication::GetCursorNum()
|
|
{
|
|
return s_iCursorNum;
|
|
}
|
|
|
|
BOOL CPythonApplication::__IsContinuousChangeTypeCursor(int iCursorNum)
|
|
{
|
|
switch (iCursorNum)
|
|
{
|
|
case CURSOR_SHAPE_NORMAL:
|
|
case CURSOR_SHAPE_ATTACK:
|
|
case CURSOR_SHAPE_TARGET:
|
|
case CURSOR_SHAPE_MAGIC:
|
|
case CURSOR_SHAPE_BUY:
|
|
case CURSOR_SHAPE_SELL:
|
|
return TRUE;
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL CPythonApplication::SetCursorNum(int iCursorNum)
|
|
{
|
|
if (CURSOR_SHAPE_NORMAL == iCursorNum)
|
|
{
|
|
if (!__IsContinuousChangeTypeCursor(s_iCursorNum))
|
|
{
|
|
iCursorNum = s_iContinuousCursorNum;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (__IsContinuousChangeTypeCursor(s_iCursorNum))
|
|
{
|
|
s_iContinuousCursorNum = s_iCursorNum;
|
|
}
|
|
}
|
|
|
|
if (CURSOR_MODE_HARDWARE == s_iCursorMode)
|
|
{
|
|
// PORT: m_CursorHandleMap.find(iCursorNum) and SetCursor(hCursor).
|
|
if (iCursorNum < 0 || iCursorNum >= CURSOR_COUNT)
|
|
return FALSE;
|
|
}
|
|
|
|
s_iCursorNum = iCursorNum;
|
|
|
|
PyCallClassMemberFunc(s_poMouseHandler, "ChangeCursor", Py_BuildValue("(i)", s_iCursorNum));
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void CPythonApplication::SetCursorMode(int iMode)
|
|
{
|
|
switch (iMode)
|
|
{
|
|
case CURSOR_MODE_HARDWARE:
|
|
s_iCursorMode = CURSOR_MODE_HARDWARE;
|
|
break;
|
|
|
|
case CURSOR_MODE_SOFTWARE:
|
|
s_iCursorMode = CURSOR_MODE_SOFTWARE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// 40250 PythonApplication.cpp:871.
|
|
void CPythonApplication::SetMouseHandler(PyObject* poMouseHandler)
|
|
{
|
|
s_poMouseHandler = poMouseHandler;
|
|
}
|
|
void CPythonApplication::SetGlobalCenterPosition(LONG, LONG) { MT_PLATFORM_STUB(); }
|
|
void CPythonApplication::SetFPS(int) {}
|
|
time_t CPythonApplication::GetServerTime() { return time(nullptr); }
|
|
time_t CPythonApplication::GetServerTimeStamp() { return time(nullptr); }
|
|
void CPythonApplication::SetConnectData(const char*, int) { MT_PLATFORM_STUB(); }
|
|
void CPythonApplication::GetConnectData(std::string& ip, int& port) { MT_PLATFORM_STUB(); ip.clear(); port = 0; }
|
|
void CPythonApplication::SetForceSightRange(int) { MT_PLATFORM_STUB(); }
|
|
|
|
int CPythonApplication::CheckDeviceState()
|
|
{
|
|
return DEVICE_STATE_OK;
|
|
}
|
|
|
|
bool CPythonApplication::CreateDevice(int width, int height, int Windowed, int bit, int frequency)
|
|
{
|
|
static CGraphicDevice s_grpDevice;
|
|
return s_grpDevice.Create(NULL, width, height, Windowed ? true : false, bit, frequency) == CGraphicDevice::CREATE_OK;
|
|
}
|
|
|
|
void CPythonApplication::NotifyHack(const char* c_szFormat, ...)
|
|
{
|
|
char szBuf[1024];
|
|
va_list args;
|
|
va_start(args, c_szFormat);
|
|
vsnprintf(szBuf, sizeof(szBuf), c_szFormat, args);
|
|
va_end(args);
|
|
CPythonNetworkStream::Instance().NotifyHack(szBuf);
|
|
}
|
|
|
|
void CPythonApplication::SkipRenderBuffering(DWORD dwSleepMSec)
|
|
{
|
|
MT_PLATFORM_STUB();
|
|
}
|
|
|
|
void CPythonApplication::UpdateClientRect()
|
|
{
|
|
unsigned w = 0, h = 0;
|
|
UIRenderGetSize(&w, &h);
|
|
UI::CWindowManager::Instance().SetResolution(w, h);
|
|
}
|
|
|
|
int CPythonApplication::GetWidth()
|
|
{
|
|
unsigned w = 0, h = 0;
|
|
UIRenderGetSize(&w, &h);
|
|
return (int)w;
|
|
}
|
|
|
|
int CPythonApplication::GetHeight()
|
|
{
|
|
unsigned w = 0, h = 0;
|
|
UIRenderGetSize(&w, &h);
|
|
return (int)h;
|
|
}
|
|
|
|
void CPythonApplication::Clear()
|
|
{
|
|
CPythonSystem::Instance().Clear();
|
|
}
|
|
|
|
void CPythonApplication::Destroy()
|
|
{
|
|
}
|
|
|
|
void CMovieMan::PlayLogo(const char*) { MT_PLATFORM_STUB(); }
|
|
|
|
BOOL PERF_CHECKER_RENDER_GAME = FALSE;
|
|
double g_specularSpd = 0;
|
|
|
|
// 40250 UserInterface/PythonApplication.cpp, verbatim.
|
|
// 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;
|
|
}
|
|
|