diff --git a/Source/Contents/ChampionMonsterMgr.cpp b/Source/Contents/ChampionMonsterMgr.cpp new file mode 100644 index 00000000..63cf02e9 --- /dev/null +++ b/Source/Contents/ChampionMonsterMgr.cpp @@ -0,0 +1,120 @@ +#include "Contents/ChampionMonsterMgr.h" + +extern "C" { +#include +#include +} +#include +#include +#include +#include +#include +#include + +// GLOBAL: gl_24813 +CChampionMonsterMgr* g_championMonsterMgr; + +// OFFSET: 0x00ADDF50 +// FUNCTION: fn_17951 +__declspec(noinline) void CChampionMonsterMgr::AddItem(int id, float value) { + this->m_items.insert(std::make_pair(id, lcData(value))); +} + +// OFFSET: 0x00ADE1B0 +// FUNCTION: fn_17952 +bool CChampionMonsterMgr::Create() { + if (g_championMonsterMgr == nullptr) { + g_championMonsterMgr = new (std::nothrow) CChampionMonsterMgr(); + if (g_championMonsterMgr != nullptr) { + if (g_championMonsterMgr->m_isValid) { + return true; + } + delete g_championMonsterMgr; + g_championMonsterMgr = nullptr; + } + } + return false; +} + +// OFFSET: 0x00ADE2A0 +// FUNCTION: fn_17953 +void CChampionMonsterMgr::Destroy() { + if (g_championMonsterMgr != nullptr) { + delete g_championMonsterMgr; + g_championMonsterMgr = nullptr; + } +} + +// OFFSET: 0x00ADE6D0 +// FUNCTION: fn_17956 +static __declspec(noinline) std::string FormatChampionMessage(const char* format, ...) { + char buffer[2049]; + std::memset(buffer, 0, sizeof(buffer)); + va_list arguments; + va_start(arguments, format); + _vsnprintf(buffer, 2048, format, arguments); + va_end(arguments); + return std::string(buffer); +} + +// OFFSET: 0x00ADE9D0 +// FUNCTION: fn_17958 +float CChampionMonsterMgr::GetValue(int id) { + if (!this->m_items.empty()) { + std::map::iterator it = this->m_items.find(id); + if (it != this->m_items.end()) { + return it->second.m_value; + } + } + return 0.0f; +} + +// OFFSET: 0x00ADEA20 +// FUNCTION: fn_17959 +bool CChampionMonsterMgr::IsChampion(int id) { + if (!this->m_items.empty()) { + std::map::iterator it = this->m_items.find(id); + if (it != this->m_items.end()) { + return true; + } + } + return false; +} + +// OFFSET: 0x00ADEA70 +// FUNCTION: fn_17960 +int CChampionMonsterMgr::LuaAddItem(lua_State* state) { + if (!lua_isnumber(state, -1)) { + lua_pushboolean(state, 0); + lua_pushstring(state, FormatChampionMessage("2nd argment is must number").c_str()); + } else if (!lua_isnumber(state, -2)) { + lua_pushboolean(state, 0); + lua_pushstring(state, FormatChampionMessage("1st argment is must number").c_str()); + } else { + int id = static_cast(lua_tonumber(state, -2)); + float value = static_cast(lua_tonumber(state, -1)); + g_championMonsterMgr->AddItem(id, value); + lua_pushboolean(state, 1); + lua_pushstring(state, FormatChampionMessage("good").c_str()); + } + return 2; +} + +// OFFSET: 0x00ADEBA0 +// FUNCTION: fn_17961 +int CChampionMonsterMgr::LuaAddEffect(lua_State* state) { + if (!lua_isnumber(state, -1)) { + lua_pushboolean(state, 0); + lua_pushstring(state, FormatChampionMessage("2nd argment is must number").c_str()); + } else if (!lua_isnumber(state, -2)) { + lua_pushboolean(state, 0); + lua_pushstring(state, FormatChampionMessage("1st argment is must number").c_str()); + } else { + int id = static_cast(lua_tonumber(state, -2)); + int effect = static_cast(lua_tonumber(state, -1)); + g_championMonsterMgr->AddEffect(id, effect); + lua_pushboolean(state, 1); + lua_pushstring(state, FormatChampionMessage("good").c_str()); + } + return 2; +} diff --git a/Source/Contents/ChampionMonsterMgr.h b/Source/Contents/ChampionMonsterMgr.h new file mode 100644 index 00000000..33a2ec03 --- /dev/null +++ b/Source/Contents/ChampionMonsterMgr.h @@ -0,0 +1,57 @@ +#ifndef RAGNAROK_SOURCE_CONTENTS_CHAMPIONMONSTERMGR_H +#define RAGNAROK_SOURCE_CONTENTS_CHAMPIONMONSTERMGR_H + +#include +#include + +struct lua_State; + +// VTABLE: vt_01613 +class CChampionMonsterMgr { +public: + // VTABLE: vt_01612 + class lcData { + public: + // INLINED + explicit lcData(float value) : m_value(value) { + } + // INLINED + virtual ~lcData() { + } + + /* 0004 */ float m_value; + /* 0008 */ std::vector m_effects; + }; + + // INLINED + CChampionMonsterMgr() : m_isValid(true) { + } + // INLINED + virtual ~CChampionMonsterMgr() { + } + + static bool Create(); + static void Destroy(); + static int LuaAddItem(lua_State* state); + static int LuaAddEffect(lua_State* state); + + void AddItem(int id, float value); + // INLINED + void AddEffect(int id, int effect) { + if (!this->m_items.empty()) { + std::map::iterator it = this->m_items.find(id); + if (it != this->m_items.end()) { + it->second.m_effects.push_back(effect); + } + } + } + float GetValue(int id); + bool IsChampion(int id); + + /* 0004 */ bool m_isValid; + /* 0008 */ std::map m_items; +}; + +extern CChampionMonsterMgr* g_championMonsterMgr; + +#endif diff --git a/Source/Contents/TownInfoMgr.cpp b/Source/Contents/TownInfoMgr.cpp new file mode 100644 index 00000000..0ce8e603 --- /dev/null +++ b/Source/Contents/TownInfoMgr.cpp @@ -0,0 +1,42 @@ +#include "Contents/TownInfoMgr.h" + +#include + +// GLOBAL: gl_24817 +CTownInfoMgr* g_townInfoMgr; + +// OFFSET: 0x00AE1A60 +// FUNCTION: fn_18003 +TownInfo::TownInfo(int type, std::string name, int x, int y, std::string image) + : type(type), name(name), x(x), y(y), image(image) { +} + +// OFFSET: 0x00AE1B00 +// FUNCTION: fn_18004 +TownInfo::TownInfo() : type(-1), name(""), x(-1), y(-1), image("") { +} + +// OFFSET: 0x00AE2740 +// FUNCTION: fn_18008 +bool CTownInfoMgr::Create() { + if (g_townInfoMgr == nullptr) { + g_townInfoMgr = new (std::nothrow) CTownInfoMgr(); + if (g_townInfoMgr != nullptr) { + if (g_townInfoMgr->m_isValid) { + return true; + } + delete g_townInfoMgr; + g_townInfoMgr = nullptr; + } + } + return false; +} + +// OFFSET: 0x00AE2840 +// FUNCTION: fn_18009 +void CTownInfoMgr::Destroy() { + if (g_townInfoMgr != nullptr) { + delete g_townInfoMgr; + g_townInfoMgr = nullptr; + } +} diff --git a/Source/Contents/TownInfoMgr.h b/Source/Contents/TownInfoMgr.h new file mode 100644 index 00000000..d17ac9b4 --- /dev/null +++ b/Source/Contents/TownInfoMgr.h @@ -0,0 +1,39 @@ +#ifndef RAGNAROK_SOURCE_CONTENTS_TOWNINFOMGR_H +#define RAGNAROK_SOURCE_CONTENTS_TOWNINFOMGR_H + +#include +#include +#include + +struct TownInfo { + TownInfo(); + TownInfo(int type, std::string name, int x, int y, std::string image); + + /* 0000 */ int type; + /* 0004 */ std::string name; + /* 001C */ int x; + /* 0020 */ int y; + /* 0024 */ std::string image; +}; + +// VTABLE: vt_01617 +class CTownInfoMgr { +public: + // INLINED + CTownInfoMgr() : m_isValid(true) { + } + // INLINED + virtual ~CTownInfoMgr() { + } + + static bool Create(); + static void Destroy(); + + /* 0004 */ bool m_isValid; + /* 0008 */ std::map> m_towns; + /* 0010 */ std::vector m_current; +}; + +extern CTownInfoMgr* g_townInfoMgr; + +#endif diff --git a/Source/Render/Text/EmbedFont.cpp b/Source/Render/Text/EmbedFont.cpp new file mode 100644 index 00000000..c1f34a16 --- /dev/null +++ b/Source/Render/Text/EmbedFont.cpp @@ -0,0 +1,147 @@ +#include "Render/Text/EmbedFont.h" + +#include "Client/Application/ErrorDialog.h" + +#include +#include +#include +#include +#include +#include + +// GLOBAL: gl_24812 +CEmbedFont* g_embedFont; + +// INLINED +CEmbedFont::CEmbedFont() : m_module(nullptr), m_unknownC(0) { + std::memset(this->m_rootUrl, 0, sizeof(this->m_rootUrl)); +} + +CEmbedFont::~CEmbedFont() { + this->UnloadModule(); +} + +// OFFSET: 0x00ADCE70 +// FUNCTION: fn_17938 +void FreeEmbedFont() { + if (g_embedFont != nullptr) { + g_embedFont->UnloadModule(); + delete g_embedFont; + g_embedFont = nullptr; + } +} + +// OFFSET: 0x00ADCEB0 +// FUNCTION: fn_17939 +void InitEmbedFont() { + g_embedFont = new CEmbedFont(); + g_embedFont->LoadModule(); +} + +// OFFSET: 0x00ADCF60 +// FUNCTION: fn_17940 +int LoadEmbedFont(HANDLE* fontReference, const char* fileName) { + char message[256]; + char path[256]; + GetCurrentDirectoryA(sizeof(path), path); + std::strcat(path, "\\System\\Font\\"); + std::strcat(path, fileName); + if (std::fopen(path, "r") == nullptr) { + std::sprintf(message, "%s \xc6\xc4\xc0\xcf \xbe\xf8\xc0\xbd!", path); + ShowErrorDialog(nullptr, message, 0); + std::exit(0); + } + if (g_embedFont == nullptr) { + return 0; + } + return g_embedFont->Load(fontReference, fileName, path); +} + +// OFFSET: 0x00ADD090 +// FUNCTION: fn_17941 +void SetEmbedFontRootUrl(const char* url) { + if (g_embedFont != nullptr && url != nullptr) { + std::strcpy(g_embedFont->m_rootUrl, url); + } +} + +// OFFSET: 0x00ADD710 +// FUNCTION: fn_17943 +static unsigned long ReadEmbedFontStream(void* stream, void* buffer, const unsigned long size) { + return static_cast(std::fread(buffer, 1, size, static_cast(stream))); +} + +// OFFSET: 0x00ADD810 +// FUNCTION: fn_17945 +static std::wstring ToWideString(const std::string& text) { + WORD length = static_cast(MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, text.c_str(), -1, nullptr, 0)); + std::vector buffer(length); + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, text.c_str(), -1, buffer.data(), static_cast(buffer.size())); + return std::wstring(buffer.data(), buffer.size()); +} + +// OFFSET: 0x00ADD1B0 +// FUNCTION: fn_17942 +int CEmbedFont::Load(HANDLE* fontReference, const char* familyName, const char* path) { + int result = -2; + *fontReference = nullptr; + if (this->m_module == nullptr) { + return result; + } + const char* rootUrl = this->m_rootUrl; + if (rootUrl == nullptr) { + return -3; + } + if (std::strcmp(rootUrl, "http://222.122.45.46") != 0 && std::strcmp(rootUrl, "http://fontrix.co.kr") != 0 && + std::strcmp(rootUrl, "http://www.puccaracing.co.kr") != 0 && std::strcmp(rootUrl, "http://www.ragnarok.co.kr") != 0) { + return -3; + } + std::string familyNameText = familyName; + std::string pathText = path == nullptr ? familyNameText : std::string(path); + std::wstring wideFamilyName = ToWideString(familyNameText); + std::wstring widePath = ToWideString(pathText); + std::wstring wideRootUrl = ToWideString(std::string(rootUrl)); + TTLOADINFO loadInfo; + loadInfo.usStructSize = sizeof(TTLOADINFO); + loadInfo.usRefStrSize = static_cast(wideRootUrl.size()); + loadInfo.pusRefStr = reinterpret_cast(const_cast(wideRootUrl.c_str())); + FILE* file = _wfopen(widePath.c_str(), L"rb"); + if (file == nullptr) { + return -2; + } + ULONG privStatus = 2; + ULONG status = 1; + typedef LONG(WINAPI * TTLoadEmbeddedFontProc)(HANDLE*, ULONG, ULONG*, ULONG, ULONG*, READEMBEDPROC, LPVOID, LPWSTR, + LPSTR, TTLOADINFO*); + TTLoadEmbeddedFontProc loadEmbeddedFont; + if (this->m_module == nullptr || + (loadEmbeddedFont = reinterpret_cast(GetProcAddress(this->m_module, "TTLoadEmbeddedFont"))) == + nullptr) { + result = 0; + } else { + LONG error = loadEmbeddedFont(fontReference, TTLOAD_PRIVATE, &privStatus, LICENSE_EDITABLE, &status, + ReadEmbedFontStream, file, const_cast(wideFamilyName.c_str()), + const_cast(familyNameText.c_str()), &loadInfo); + if (error < 0) { + result = -2; + } else if (error == 0) { + result = 1; + } else if (error == 0x10f) { + result = 2; + } else if (error == 0x10e) { + result = 2; + } else if (error == 0x100) { + result = -5; + } else if (error == 0x102) { + result = -4; + } else if (error == 0x11c) { + result = -3; + } else if (error == 0x11a) { + result = -3; + } else { + result = -1; + } + } + fclose(file); + return result; +} diff --git a/Source/Render/Text/EmbedFont.h b/Source/Render/Text/EmbedFont.h new file mode 100644 index 00000000..0dbb0aca --- /dev/null +++ b/Source/Render/Text/EmbedFont.h @@ -0,0 +1,45 @@ +#ifndef RAGNAROK_SOURCE_RENDER_TEXT_EMBEDFONT_H +#define RAGNAROK_SOURCE_RENDER_TEXT_EMBEDFONT_H + +#include + +// VTABLE: vt_01611 +class CEmbedFont { +public: + CEmbedFont(); + virtual ~CEmbedFont(); + + // INLINED + void LoadModule() { + if (this->m_module == nullptr) { + HMODULE module = LoadLibraryA("t2embed.dll"); + if (reinterpret_cast(module) > 32) { + this->m_module = module; + } + } + } + + // INLINED + void UnloadModule() { + if (this->m_module != nullptr) { + FreeLibrary(this->m_module); + this->m_module = nullptr; + } + } + + int Load(HANDLE* fontReference, const char* familyName, const char* path); + + /* 0004 */ HMODULE m_module; + /* 0008 */ int m_unknown8; + /* 000C */ int m_unknownC; + /* 0010 */ char m_rootUrl[256]; +}; + +extern CEmbedFont* g_embedFont; + +void FreeEmbedFont(); +void InitEmbedFont(); +int LoadEmbedFont(HANDLE* fontReference, const char* fileName); +void SetEmbedFontRootUrl(const char* url); + +#endif diff --git a/data/compile.json b/data/compile.json index d4283a05..8a4b13a1 100644 --- a/data/compile.json +++ b/data/compile.json @@ -305,6 +305,7 @@ "Source/Contents/Camera/CameraShake.cpp": 3, "Source/Contents/Camera/CameraSmoothing.cpp": 3, "Source/Contents/CashEmotionMgr.cpp": 4, + "Source/Contents/ChampionMonsterMgr.cpp": 4, "Source/Contents/ClanInfo.cpp": 4, "Source/Contents/ClientItemLists.cpp": 4, "Source/Contents/ClientState.cpp": 4, @@ -517,6 +518,7 @@ "Source/Contents/TerrainPathSearch.cpp": 4, "Source/Contents/TipBoxTitles.cpp": 4, "Source/Contents/TipOfTheDay.cpp": 4, + "Source/Contents/TownInfoMgr.cpp": 4, "Source/Contents/UserData/AccountLinkedUserDataLoadAsyncWork.cpp": 4, "Source/Contents/UserData/AccountLinkedUserDataMgr.cpp": 4, "Source/Contents/UserData/AccountLinkedUserDataSaveAsyncWork.cpp": 4, @@ -632,6 +634,7 @@ "Source/Render/ScreenRectangle.cpp": 0, "Source/Render/SpriteGeometry.cpp": 0, "Source/Render/SpriteQuad.cpp": 0, + "Source/Render/Text/EmbedFont.cpp": 0, "Source/Render/Text/FontCache.cpp": 0, "Source/Render/Text/TextContext.cpp": 0, "Source/Render/TextureQuad.cpp": 0,