Decompile 3 functions in Source/Contents/Skills/ClientSkills.cpp, Source/Client/Session.h, ...

Batch #2506 by meitogi: 0 byte-identical, 3 confirmed by peer review.

- fn_23749 CSession::AddProhibitionLog: logic confirmed by peer review
- fn_23750 CSession::ProcessEmotionShortcut: logic confirmed by peer review
- fn_02976 CCashEmotionMgr::PlaySearchedEmotion: logic confirmed by peer review

Reviewed-by: ragnarok-clanker
This commit is contained in:
ragnarok-clanker 2026-10-29 17:23:04 +00:00
commit 1dfd7409f8
4 changed files with 109 additions and 2 deletions

View file

@ -341,6 +341,8 @@ public:
CSkillInfo HomunSkillAt(int index) const;
int CountProhibitionLog(std::uint32_t aid);
void DeleteProhibitionLog(std::uint32_t aid, std::uint32_t minutes, WindowDialogs& dialogs);
void AddProhibitionLog(std::uint32_t aid, std::uint32_t minutes);
int ProcessEmotionShortcut(const char* text);
int IsAdminSubMode(int subMode);
void GetMonsterSkillInfo(const char* monster, int skill, int* action, int* loopType, WindowDialogs& dialogs);
const char* DecodePlayerName() const;

View file

@ -30,7 +30,7 @@ ChatSuggestions* g_chatSuggestions = nullptr;
class ICashEmotionAction {
public:
virtual ~ICashEmotionAction();
virtual void Execute(int packId, int argument) = 0;
virtual bool Execute(int packId, int argument) = 0;
};
class UICashEmotionPack_Purchase : public UICashEmotionPack {
@ -662,6 +662,20 @@ void CCashEmotionMgr::AddShortcut(const std::string& name, int packId, int emoti
}
}
// OFFSET: 0x0059C4F0
// FUNCTION: fn_02976
bool CCashEmotionMgr::PlaySearchedEmotion(const std::string& name) {
if (this->m_action) {
auto found = this->m_searchIndex.find(name);
const std::pair<int, int>* emotion = found == this->m_searchIndex.end() ? nullptr : &found->second;
if (emotion) {
return this->m_action->Execute(emotion->first, emotion->second);
}
}
return false;
}
// OFFSET: 0x0059C0A0
// FUNCTION: fn_02972
void CCashEmotionMgr::SetOwnedPack(int packId, unsigned int expiry) {

View file

@ -12,6 +12,7 @@
#include <vector>
class CCashEmotionMgr;
class ICashEmotionAction;
struct CashEmotionKeyHash {
// INLINED
@ -139,6 +140,7 @@ public:
int LookupSpecialEmotion(CashEmotionSpecial type);
int LookupSpecialEmotion(CashEmotionSpecial type, const char* name);
void AddShortcut(const std::string& name, int packId, int emotionId);
bool PlaySearchedEmotion(const std::string& name);
bool IsChatProhibitEmotion(int emotionId);
bool IsPackAvailable(unsigned int now, int packId);
bool IsOwnedPack(int packId);
@ -150,7 +152,7 @@ public:
protected:
/* 0004 */ bool m_enabled;
/* 0005 */ std::uint8_t unknown_0005[3];
/* 0008 */ void* m_action;
/* 0008 */ ICashEmotionAction* m_action;
/* 000C */ int unknown_000C;
/* 0010 */ std::unordered_map<int, CashEmotionPack, CashEmotionKeyHash> unknown_0010;
/* 0030 */ std::unordered_map<int, CashEmotionTable> m_emotionsByPack;

View file

@ -3,17 +3,21 @@
#include "Client/Mode/CGameMode.h"
#include "Client/Session.h"
#include "Contents/Actors/RenderObject.h"
#include "Contents/CashEmotionMgr.h"
#include "Contents/ClientState.h"
#include "Contents/Jobs/JobId.h"
#include "Contents/Jobs/JobInheritance.h"
#include "Contents/UserData/CharacterConfigSave.h"
#include "Contents/World/World.h"
#include "File/File.h"
#include "Network/TextEncoding.h"
#include "Script/LuaScript.h"
#include "UI/Shortcuts/ShortcutBindings.h"
#include "UI/Window/UIWindow.h"
#include "UI/Window/UIWindowMgr.h"
#include "UI/Window/WindowDialogs.h"
#include "UI/Window/WindowManagerWindows.h"
#include "Utility/Tokenizer.h"
#include <algorithm>
#include <cstring>
@ -738,3 +742,88 @@ CRenderObject* CSession::FindGameActor(std::uint32_t aid) const {
return mode->scene->GetGameActorByAID(aid);
}
// OFFSET: 0x00E07AA0
// FUNCTION: fn_23749
void CSession::AddProhibitionLog(std::uint32_t aid, std::uint32_t minutes) {
const CRenderObject* actor = static_cast<CGameMode*>(g_modeMgr.GetGameMode())->scene->GetGameActorByAID(aid);
if (!actor) {
return;
}
std::uint32_t accountId = actor->render.accountId;
const std::string actorName = static_cast<CGameMode*>(g_modeMgr.GetGameMode())->ActorName(aid);
ProhibitionLogEntry entry;
std::strcpy(entry.name, actorName.c_str());
std::strcpy(entry.ownerName, this->m_serverName.c_str());
entry.minutes = minutes;
entry.aid = aid;
entry.accountId = accountId;
SYSTEMTIME localTime;
GetLocalTime(&localTime);
entry.date = ((localTime.wYear << 8 | localTime.wMonth) << 8) | localTime.wDay;
entry.time = ((localTime.wHour << 8 | localTime.wMinute) << 8) | localTime.wSecond;
this->m_prohibitionLog.push_back(entry);
CFile file;
char path[256];
GetCurrentDirectoryA(sizeof(path), path);
char* data = std::strstr(path, "\\data");
int count = 0;
int size = 0;
if (data) {
std::memcpy(path, path, data - path);
}
std::strcat(path, "\\ProhibitionLog.gd");
char* buffer;
if (file.Open(path, 0, true, false)) {
size = file.GetSize() - 4;
buffer = new char[size];
file.Read(&count, 4);
file.Read(buffer, size);
file.Close();
}
++count;
file.Open(path, 0x1001, true, false);
file.Write(&count, 4);
if (size) {
file.Write(buffer, size);
}
int length = static_cast<int>(std::strlen(entry.name)) + 1;
file.Write(&length, 4);
file.Write(entry.name, length);
length = static_cast<int>(std::strlen(entry.ownerName)) + 1;
file.Write(&length, 4);
file.Write(entry.ownerName, length);
file.Write(&aid, 4);
file.Write(&accountId, 4);
file.Write(&entry.minutes, 4);
file.Write(&entry.date, 4);
file.Write(&entry.time, 4);
file.Close();
if (size) {
delete[] buffer;
}
}
// OFFSET: 0x00E07FB0
// FUNCTION: fn_23750
int CSession::ProcessEmotionShortcut(const char* text) {
if (!text) {
return 0;
}
CTokenizer tokenizer;
tokenizer.Parse(std::string(text));
if (tokenizer.tokens.size() == 0) {
return 0;
}
LowercaseText(tokenizer[0]);
return g_cashEmotionMgr->PlaySearchedEmotion(tokenizer[0]);
}