diff --git a/Source/Client/Mode/CGameMode.h b/Source/Client/Mode/CGameMode.h index 98b58539..4f3215c2 100644 --- a/Source/Client/Mode/CGameMode.h +++ b/Source/Client/Mode/CGameMode.h @@ -15,6 +15,7 @@ #include class CView; +class CMousePointer; class CCorpse; class CMsgEffect; class CGameActor; @@ -52,7 +53,8 @@ public: /* 0078 */ unsigned char unknown_0078[0x54]; /* 00CC */ CWorld* scene; /* 00D0 */ CView* camera; - /* 00D4 */ unsigned char unknown_00D4[0x28]; + /* 00D4 */ CMousePointer* mousePointer; + /* 00D8 */ unsigned char unknown_00D8[0x24]; /* 00FC */ int unknown_00FC; /* 0100 */ unsigned char unknown_0100[0x18]; /* 0118 */ std::string unknown_0118; @@ -105,6 +107,13 @@ public: void WorldCell(float x, float z, int& column, int& row) const; void SubcellPosition(int column, int row, int subColumn, int subRow, float& x, float& z) const; void PlayerCell(int* column, int* row) const; + int GetSkillAttackRange(int id, int level); + int TerrainHeight() const; + int TerrainWidth() const; + std::string LocationText(); + bool HasInventoryItem(int id); + bool HasResurrectionItem(); + void SendMousePointerState(int value); bool CanFindPath(int sx, int sy, int cellX, int cellY, int dx, int dy); bool IsAllowedPair(int kind, int value); bool IsWithinRange(const int& x1, const int& y1, const int& x2, const int& y2, int range); diff --git a/Source/Client/Mode/GameMode.cpp b/Source/Client/Mode/GameMode.cpp index 2ccb703a..adaac350 100644 --- a/Source/Client/Mode/GameMode.cpp +++ b/Source/Client/Mode/GameMode.cpp @@ -6,15 +6,22 @@ #include "Contents/Camera/Camera.h" #include "Contents/Configuration/ServiceOptions.h" #include "Contents/MessageTable.h" +#include "Contents/Actors/MousePointer.h" +#include "Contents/Actors/RenderObject.h" +#include "Contents/Items/ItemInfo.h" #include "Contents/Skills/ClientSkills.h" +#include "Contents/Skills/SkillInfo.h" #include "Contents/World/World.h" #include "Network/Packets/PacketLengths.h" #include "Render/Renderer.h" +#include "Resource/World/TerrainResource.h" +#include "Script/LuaScript.h" #include "UI/Window/UIWindow.h" #include "UI/Window/UIWindowMgr.h" #include "Utility/Text/FormatString.h" #include +#include #include #include #include @@ -77,6 +84,121 @@ void CGameMode::CompleteUnknown0194(std::uint32_t id, const std::string& text) { } } +// OFFSET: 0x00CD52F0 +// FUNCTION: fn_21279 +int CGameMode::GetSkillAttackRange(int id, int level) { + if (id == 10000) { + return 5; + } + + int range = 1; + CSkillInfo skill = reinterpret_cast(g_session).Lookup(id); + if (!skill.available) { + skill = g_session.m_skillBundle.Pending(id); + if (!skill.available) { + return range; + } + + level = skill.level; + } + + int reduction = 0; + g_luaScript->Call("GetSkillAttackRange", "ddd>dd", id, level, skill.level, &range, &reduction); + range += skill.unknown_001C - reduction; + return range; +} + +// OFFSET: 0x00CD54D0 +// FUNCTION: fn_21280 +int CGameMode::TerrainHeight() const { + if (!this->scene || !this->scene->terrain) { + return 0; + } + + return this->scene->terrain->height; +} + +// OFFSET: 0x00CD54F0 +// FUNCTION: fn_21281 +int CGameMode::TerrainWidth() const { + if (!this->scene || !this->scene->terrain) { + return 0; + } + + return this->scene->terrain->width; +} + +// OFFSET: 0x00CD5550 +// FUNCTION: fn_21283 +std::string CGameMode::LocationText() { + char text[120]; + std::memset(text, 0, sizeof(text)); + + int column; + int row; + const auto* player = reinterpret_cast(this->scene->player); + this->WorldCell(player->render.position.x, player->render.position.z, column, row); + + std::string name = this->mapName; + if (name.size() > 4) { + name.resize(name.size() - 4); + } + + std::sprintf(text, "Location: %s ( %d , %d )", name.c_str(), column, row); + return text; +} + +// OFFSET: 0x00CD5800 +// FUNCTION: fn_21284 +bool CGameMode::HasInventoryItem(int id) { + const ITEM_INFO item = LookupClientItem(g_session.m_inventoryItems, id, 0); + return item.unknown_0000[1] != 0 && item.quantity > 0; +} + +// OFFSET: 0x00CD58B0 +// FUNCTION: fn_21285 +bool CGameMode::HasResurrectionItem() { + ITEM_INFO item = LookupClientItem(g_session.m_inventoryItems, 7621, 0); + const CWorld* world = this->scene; + if (world->unknown_0048 || world->unknown_004C || world->unknown_0054) { + return false; + } + + if (item.unknown_0000[1] != 0 && item.quantity > 0) { + return true; + } + + item = LookupClientItem(g_session.m_inventoryItems, 6833, 0); + if (item.unknown_0000[1] != 0 && item.quantity > 0) { + return true; + } + + item = LookupClientItem(g_session.m_inventoryItems, 6316, 0); + if (item.unknown_0000[1] != 0 && item.quantity > 0) { + return true; + } + + item = LookupClientItem(g_session.m_inventoryItems, 6293, 0); + if (item.unknown_0000[1] != 0 && item.quantity > 0) { + return true; + } + + item = LookupClientItem(g_session.m_inventoryItems, 25310, 0); + if (item.unknown_0000[1] != 0 && item.quantity > 0) { + return true; + } + + return false; +} + +// OFFSET: 0x00CD5CD0 +// FUNCTION: fn_21287 +void CGameMode::SendMousePointerState(int value) { + if (this->mousePointer) { + this->mousePointer->SendMsg(nullptr, 2, 0, value, value >> 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + } +} + // OFFSET: 0x00CECE00 // FUNCTION: fn_21360 void CGameMode::ClearUnknown0458() {