diff --git a/Source/Contents/GuildInfo.cpp b/Source/Contents/GuildInfo.cpp index c8903164..03d24c34 100644 --- a/Source/Contents/GuildInfo.cpp +++ b/Source/Contents/GuildInfo.cpp @@ -1,5 +1,6 @@ #include "Contents/GuildInfo.h" #include "Client/Mode/CGameMode.h" +#include "Client/Session.h" #include "Client/Mode/ModeMgr.h" #include "Contents/Actors/GameActor.h" #include "Contents/Actors/Pc.h" @@ -134,3 +135,106 @@ void GuildInfo::Init() { this->unknown_010C.clear(); this->unknown_0114.clear(); } + +// OFFSET: 0x00AE49F0 +// FUNCTION: fn_18040 +bool GuildInfo::HasRelatedGuild(int unknown_0000) { + for (auto it = this->unknown_00E4.begin(); it != this->unknown_00E4.end(); ++it) { + if (it->unknown_0000 == unknown_0000 && it->unknown_0004 == 0) { + return true; + } + } + return false; +} + +// OFFSET: 0x00AE4A20 +// FUNCTION: fn_18041 +void GuildInfo::UpdateMemberExpRatios() { + double total = 0.0; + for (auto it = this->m_members.begin(); it != this->m_members.end(); ++it) { + total += it->exp; + } + + for (auto it = this->m_members.begin(); it != this->m_members.end(); ++it) { + if (total == 0.0) { + it->expRatio = 0.0f; + } else { + it->expRatio = static_cast(it->exp) * 100.0f / static_cast(total); + } + it->positionName = this->m_positions[it->positionId]; + } +} + +// OFFSET: 0x00AE4CA0 +// FUNCTION: fn_18043 +int GuildInfo::DeleteMember(const char* name) { + for (auto it = this->m_members.begin(); it != this->m_members.end(); ++it) { + if (it->name == name) { + this->m_members.erase(it); + g_windowMgr.RefreshGuildWindows(); + return 1; + } + } + return 0; +} + +// OFFSET: 0x00AE4F50 +// FUNCTION: fn_18045 +void GuildInfo::UpdateMemberStatus(int accountId, int online, int characterId, short unknown_002C, short unknown_0020, short unknown_0024) { + for (auto it = this->m_members.begin(); it != this->m_members.end(); ++it) { + if (it->characterId == characterId) { + it->unknown_002C = unknown_002C; + it->unknown_0020 = unknown_0020; + it->unknown_0024 = unknown_0024; + it->online = online; + break; + } + } + + int count = 0; + for (auto it = this->m_members.begin(); it != this->m_members.end(); ++it) { + if (it->online) { + ++count; + } + } + this->unknown_0068 = count; + g_windowMgr.RefreshGuildWindows(); +} + +// OFFSET: 0x00AE4FD0 +// FUNCTION: fn_18046 +void GuildInfo::SetMemberOnline(int accountId, int online) { + for (auto it = this->m_members.begin(); it != this->m_members.end(); ++it) { + if (it->accountId == accountId) { + it->online = online; + break; + } + } + + int count = 0; + for (auto it = this->m_members.begin(); it != this->m_members.end(); ++it) { + if (it->online) { + ++count; + } + } + this->unknown_0068 = count; + g_windowMgr.RefreshGuildWindows(); +} + +// OFFSET: 0x00AE5030 +// FUNCTION: fn_18047 +void GuildInfo::SetMasterCharacterId(int characterId) { + this->unknown_00D0 = characterId; + this->unknown_00B4 = characterId == static_cast(g_session.m_gid); +} + +// OFFSET: 0x00AE5090 +// FUNCTION: fn_18048 +void GuildInfo::UpdateUnknown00D4(Unknown00D4Entry entry) { + for (auto it = this->unknown_00D4.begin(); it != this->unknown_00D4.end(); ++it) { + if (it->unknown_0004 == entry.unknown_0004) { + *it = entry; + return; + } + } +} diff --git a/Source/Contents/GuildInfo.h b/Source/Contents/GuildInfo.h index 7b6731cb..93aee7f0 100644 --- a/Source/Contents/GuildInfo.h +++ b/Source/Contents/GuildInfo.h @@ -14,12 +14,28 @@ public: /* 0000 */ int accountId; /* 0004 */ int characterId; /* 0008 */ std::string name; - /* 0020 */ unsigned char unknown_0020[0x10]; + /* 0020 */ int unknown_0020; + /* 0024 */ int unknown_0024; + /* 0028 */ unsigned char unknown_0028[0x04]; + /* 002C */ int unknown_002C; /* 0030 */ int positionId; /* 0034 */ std::string positionName; /* 004C */ unsigned char unknown_004C[0x04]; /* 0050 */ std::string unknown_0050; - /* 0068 */ unsigned char unknown_0068[0x10]; + /* 0068 */ float expRatio; + /* 006C */ int exp; + /* 0070 */ int online; + /* 0074 */ unsigned char unknown_0074[0x04]; + }; + + struct Unknown00D4Entry { + /* 0000 */ int unknown_0000; + /* 0004 */ int unknown_0004; + /* 0008 */ std::string unknown_0008; + /* 0020 */ int unknown_0020; + /* 0024 */ int unknown_0024; + /* 0028 */ int unknown_0028; + /* 002C */ int unknown_002C; }; struct RelatedGuild { @@ -56,7 +72,7 @@ public: /* 00C8 */ int unknown_00C8; /* 00CC */ int unknown_00CC; /* 00D0 */ int unknown_00D0; - /* 00D4 */ std::list unknown_00D4; + /* 00D4 */ std::list unknown_00D4; /* 00DC */ std::list m_members; /* 00E4 */ std::list unknown_00E4; /* 00EC */ std::list unknown_00EC; @@ -76,6 +92,13 @@ public: int CountRelatedGuilds(int unknown_0004); int GetUnknown0114Count(); void Init(); + bool HasRelatedGuild(int unknown_0000); + void UpdateMemberExpRatios(); + int DeleteMember(const char* name); + void UpdateMemberStatus(int accountId, int online, int characterId, short unknown_002C, short unknown_0020, short unknown_0024); + void SetMemberOnline(int accountId, int online); + void SetMasterCharacterId(int characterId); + void UpdateUnknown00D4(Unknown00D4Entry entry); }; #if defined(_WIN32) && !defined(_WIN64) @@ -85,6 +108,11 @@ static_assert(offsetof(GuildInfo::Member, characterId) == 0x04); static_assert(offsetof(GuildInfo::Member, positionId) == 0x30); static_assert(offsetof(GuildInfo::Member, positionName) == 0x34); +static_assert(offsetof(GuildInfo::Member, expRatio) == 0x68); +static_assert(offsetof(GuildInfo::Member, online) == 0x70); + +static_assert(sizeof(GuildInfo::Unknown00D4Entry) == 0x30); + static_assert(sizeof(GuildInfo::RelatedGuild) == 0x20); static_assert(sizeof(GuildInfo) == 0x120); diff --git a/Source/Contents/GuildTip.cpp b/Source/Contents/GuildTip.cpp new file mode 100644 index 00000000..708de045 --- /dev/null +++ b/Source/Contents/GuildTip.cpp @@ -0,0 +1,87 @@ +#include "Contents/GuildTip.h" +#include "Client/Input/InputCharset.h" +#include "Contents/Configuration/ServiceConfiguration.h" +#include "File/File.h" +#include "File/ResourcePath.h" + +#include + +// OFFSET: 0x00AE54B0 +// FUNCTION: fn_18052 +std::vector CGuildTip::GetTipList() { + if (this->m_bTryLoading == false) { + this->Load(); + } + + return this->m_tipList; +} + +// OFFSET: 0x00AE55B0 +// FUNCTION: fn_18053 +int CGuildTip::Load() { + this->m_bTryLoading = true; + char* fileBuf = nullptr; + int fileSize = 0; + + if (g_serviceType == 0) { + FILE* file = std::fopen("GuildTip.txt", "r"); + + if (file == nullptr) { + return 0; + } + + std::fseek(file, 0, SEEK_END); + fileSize = std::ftell(file); + fileBuf = new char[fileSize + 1]; + std::fseek(file, 0, SEEK_SET); + std::fread(fileBuf, fileSize, 1, file); + std::fclose(file); + } else { + const char* fName = g_serverLanguage->ServiceName("GuildTip.txt"); + + if (!ResourceExists(fName, 0)) { + return 0; + } + + CFile fp; + + if (!fp.Open(fName, 0, true, false)) { + return 0; + } + + fileSize = static_cast(fp.GetSize()); + fileBuf = new char[fileSize + 1]; + fp.Read(fileBuf, fileSize); + fp.Close(); + } + + fileBuf[fileSize] = 0; + + char* baseBuf = fileBuf; + StringList tmpList; + + for (int i = 0; i < fileSize; ++i) { + switch (fileBuf[i]) { + case 10: { + fileBuf[i] = 0; + std::string line(baseBuf); + tmpList.push_back(line); + baseBuf = fileBuf + i + 1; + break; + } + case '#': + fileBuf[i] = 0; + tmpList.push_back(baseBuf); + this->m_tipList.push_back(tmpList); + tmpList.clear(); + baseBuf = fileBuf + i + 1; + break; + } + } + + if (fileBuf) { + delete[] fileBuf; + } + + return 1; +} diff --git a/Source/Contents/GuildTip.h b/Source/Contents/GuildTip.h new file mode 100644 index 00000000..9054f938 --- /dev/null +++ b/Source/Contents/GuildTip.h @@ -0,0 +1,24 @@ +#ifndef RAGNAROK_SOURCE_CONTENTS_GUILDTIP_H +#define RAGNAROK_SOURCE_CONTENTS_GUILDTIP_H + +#include "Contents/TipOfTheDay.h" + +#include +#include +#include + +class CGuildTip { +public: + std::vector GetTipList(); + int Load(); + + /* 0000 */ bool m_bTryLoading = false; + /* 0004 */ std::vector m_tipList; +}; + +#if defined(_WIN32) && !defined(_WIN64) +static_assert(sizeof(CGuildTip) == 0x10); +static_assert(offsetof(CGuildTip, m_tipList) == 0x4); +#endif + +#endif diff --git a/data/compile.json b/data/compile.json index 2b080486..d191be16 100644 --- a/data/compile.json +++ b/data/compile.json @@ -443,6 +443,7 @@ "Source/Contents/GuildEmblemState.cpp": 4, "Source/Contents/GuildInfo.cpp": 4, "Source/Contents/GuildMgr.cpp": 4, + "Source/Contents/GuildTip.cpp": 4, "Source/Contents/HeadResources.cpp": 4, "Source/Contents/Hotkeys/EmotionHotkeys.cpp": 4, "Source/Contents/Hotkeys/HotkeyInfo.cpp": 4,