Maintenance: [forced, user-approved] Family G18: remove the Skills bundle family (ClientSkills, SkillUseLevels, SkillWindows, Compani

Batch #10230 by ragnarok-clanker: forced by an admin (9 lower score(s), 42 changed function(s)); checked with 339 compiled unit(s), including every includer of Source/Client/Mode/CGameMode.h, Source/Client/Session.h, Source/Contents/Skills/ClientSkills.h, Source/Contents/Skills/PlayerSkillBundle.h, Source/UI/Shortcuts/ShortcutDetails.h, Source/UI/Shortcuts/ShortcutPainting.h, Source/UI/Shortcuts/ShortcutPress.h, Source/UI/Shortcuts/UIQuickSlotWnd.h, Source/UI/UIBasicCtrl.h, Source/Network/Packets/SkillUpdatePacket.h.
Deletes: Source/Network/Packets/SkillUpdatePacket.h
This commit is contained in:
ragnarok-clanker 2026-11-03 09:49:00 +00:00
commit 9b04a3cae5
30 changed files with 147 additions and 394 deletions

View file

@ -376,6 +376,12 @@ public:
void ReceiveSkillUpdate(
std::uint16_t id, std::int16_t level, std::int16_t spCost, unsigned char upgradable, std::int16_t range, int type, std::int16_t unknown
);
void ApplySkillUpdatePacket(const void* packet);
void ReceiveLearnedSkill(
std::uint16_t id, std::int16_t level, int unknown000C, std::uint8_t unknown0018, std::int16_t unknown0014, std::int16_t unknown001C,
std::int16_t unknown0030
);
void ApplyAdditionalSkillPacket(const void* packet);
std::uint32_t FindUnknown01AC(std::uint32_t key);
std::string ActorName(std::uint32_t id);
std::uint32_t ActorNameColor(int job, std::uint32_t aid);

View file

@ -118,7 +118,7 @@ int CGameMode::GetSkillAttackRange(int id, int level) {
}
int range = 1;
CSkillInfo skill = reinterpret_cast<const ClientSkills&>(g_session).Lookup(id);
CSkillInfo skill = g_session.LookupSkill(id);
if (!skill.available) {
skill = g_session.m_skillBundle.Pending(id);
if (!skill.available) {
@ -3700,15 +3700,7 @@ void CGameMode::ProcessMouseWheel(int requireControl) {
return;
}
ClientSkills skills{
g_session.m_skillBundle,
g_session.m_homunSkills,
g_session.m_mercSkills,
g_session.m_additionalSkills,
reinterpret_cast<const int&>(g_session.m_jobFlags),
g_activeSkillEffects
};
CSkillInfo wheelSkill = skills.bundle.Lookup(0x27F, skills.classMode, skills.HasEffect(1717), skills.HasEffect(1716));
CSkillInfo wheelSkill = g_session.m_skillBundle.Lookup(0x27F);
if (wheelSkill.level > 0) {
const int count = this->unknown_05F4;
if (count > this->unknown_05F8) {
@ -3784,7 +3776,7 @@ void CGameMode::ProcessMouseWheel(int requireControl) {
const float step = g_mouse.wheel > 0 ? -24.3f : 24.3f;
g_cameraDistance = this->camera->camera.desiredDistance - step;
float maxDistance = this->unknown_0254 ? g_serviceOptionJitterScale : g_cameraBaseDistance;
CSkillInfo zoomSkill = skills.bundle.Lookup(0x1B9, skills.classMode, skills.HasEffect(1717), skills.HasEffect(1716));
CSkillInfo zoomSkill = g_session.m_skillBundle.Lookup(0x1B9);
bool extendedZoom = false;
if (this->hasViewParameters) {
if (g_cameraDistance < static_cast<float>(this->viewParameters[0])) {
@ -3868,7 +3860,6 @@ void CGameMode::ReceiveSkillList(int packetType, const std::vector<SkillListEntr
g_session.m_mercSkills.clear();
}
SkillWindows windows{g_windowMgr.window_02C4, g_windowMgr.window_01E8, g_windowMgr};
for (const SkillListEntry& entry : skills) {
CSkillInfo skill;
if ((entry.id != 0 && entry.id < 7999) || g_session.IsHomunculusSkill(entry.id) || g_session.IsMercenarySkill(entry.id)) {
@ -3884,18 +3875,7 @@ void CGameMode::ReceiveSkillList(int packetType, const std::vector<SkillListEntr
g_session.m_skillBundle.ApplyLevelChange(skill);
if (packetType == 0x10F || packetType == 0xB32) {
ClientSkills client{
g_session.m_skillBundle,
g_session.m_homunSkills,
g_session.m_mercSkills,
g_session.m_additionalSkills,
reinterpret_cast<const int&>(g_session.m_jobFlags),
g_activeSkillEffects
};
const SkillUseLevels levels{
g_session.m_skillBundle.unknown_0064, *reinterpret_cast<const std::vector<int>*>(g_session.unknown_0710), g_session.m_homunSkillLevels
};
client.Update(skill, 0, 0, *g_session.m_hotkeyScript, levels, windows);
g_session.UpdateSkill(skill, 0, 0);
} else if (packetType == 0x235) {
g_session.UpdateHomunSkill(skill, 0);
} else if (packetType == 0x29D) {
@ -3905,7 +3885,7 @@ void CGameMode::ReceiveSkillList(int packetType, const std::vector<SkillListEntr
}
if (packetType == 0x10F || packetType == 0xB32) {
windows.Notify();
g_session.NotifySkillWindows();
} else if (packetType == 0x235) {
g_session.NotifyHomunSkillWindows();
} else if (packetType == 0x29D) {
@ -3925,15 +3905,7 @@ void CGameMode::ReceiveSkillUpdate(
) {
*reinterpret_cast<int*>(&this->unknown_0100[0x0C]) = 0;
ClientSkills client{
g_session.m_skillBundle,
g_session.m_homunSkills,
g_session.m_mercSkills,
g_session.m_additionalSkills,
reinterpret_cast<const int&>(g_session.m_jobFlags),
g_activeSkillEffects
};
CSkillInfo skill = client.Lookup(id);
CSkillInfo skill = g_session.LookupSkill(id);
skill.level = level;
skill.unknown_0014 = spCost;
skill.unknown_0018 = upgradable;
@ -3947,11 +3919,7 @@ void CGameMode::ReceiveSkillUpdate(
} else if (g_session.IsMercenarySkill(id)) {
g_session.UpdateMercSkill(skill, 1);
} else {
const SkillUseLevels levels{
g_session.m_skillBundle.unknown_0064, *reinterpret_cast<const std::vector<int>*>(g_session.unknown_0710), g_session.m_homunSkillLevels
};
SkillWindows windows{g_windowMgr.window_02C4, g_windowMgr.window_01E8, g_windowMgr};
client.Update(skill, 1, 1, *g_session.m_hotkeyScript, levels, windows);
g_session.UpdateSkill(skill, 1, 1);
}
if (g_equipmentPropertiesMgr == nullptr) {

View file

@ -4643,7 +4643,7 @@ void CGameMode::ReceiveParChange(unsigned char* data) {
case 12:
*reinterpret_cast<int*>(&g_session.unknown_165C[0]) = packet->value;
g_session.InvalidateWindowFrames();
reinterpret_cast<SkillWindows*>(&g_session)->Notify();
g_session.NotifySkillWindows();
break;
case 13:
g_session.m_standardStats[0] = packet->value;

View file

@ -841,6 +841,15 @@ public:
int IsAdminSubMode(int subMode);
void GetMonsterSkillInfo(const char* monster, int skill, int* action, int* loopType, WindowDialogs& dialogs);
const char* DecodePlayerName() const;
bool HasSkillEffect(std::uint32_t id) const;
CSkillInfo LookupHomunSkill(std::uint32_t id) const;
CSkillInfo LookupMercSkill(std::uint32_t id) const;
CSkillInfo LookupAdditionalSkill(std::uint32_t id) const;
CSkillInfo LookupSkill(std::uint32_t id);
void NotifySkillWindows();
void RemoveSkill(std::uint32_t id);
bool UpdateSkill(const CSkillInfo& value, unsigned char notify, unsigned char updateUnknown000C);
bool UpdateAdditionalSkill(const CSkillInfo& value, int unused);
void NotifyHomunSkillWindows();
void NotifyMercSkillWindows();
int GetPetActionNumber(int hungerLevel, int friendlyLevel, int action);

View file

@ -478,15 +478,7 @@ int AiHomunGetV(lua_State* state) {
case 6:
case 14: {
std::uint32_t skillId = static_cast<std::uint32_t>(lua_tonumber(state, 3));
ClientSkills skills{
g_session.m_skillBundle,
g_session.m_homunSkills,
g_session.m_mercSkills,
g_session.m_additionalSkills,
reinterpret_cast<const int&>(g_session.m_jobFlags),
g_activeSkillEffects
};
CSkillInfo skill = skills.LookupFirst(skillId);
CSkillInfo skill = g_session.LookupHomunSkill(skillId);
if (!skill.available) {
result = 1.0;
} else {
@ -670,15 +662,7 @@ int AiMercenaryGetV(lua_State* state) {
case 6:
case 14: {
std::uint32_t skillId = static_cast<std::uint32_t>(lua_tonumber(state, 3));
ClientSkills skills{
g_session.m_skillBundle,
g_session.m_homunSkills,
g_session.m_mercSkills,
g_session.m_additionalSkills,
reinterpret_cast<const int&>(g_session.m_jobFlags),
g_activeSkillEffects
};
CSkillInfo skill = skills.LookupOther(skillId);
CSkillInfo skill = g_session.LookupMercSkill(skillId);
if (!skill.available) {
result = 1.0;
} else {
@ -1120,15 +1104,7 @@ int AiSkillObject(lua_State* state) {
std::uint32_t skillId = static_cast<std::uint32_t>(lua_tonumber(state, 3));
std::uint32_t target = static_cast<std::uint32_t>(lua_tonumber(state, 4));
ClientSkills skills{
g_session.m_skillBundle,
g_session.m_homunSkills,
g_session.m_mercSkills,
g_session.m_additionalSkills,
reinterpret_cast<const int&>(g_session.m_jobFlags),
g_activeSkillEffects
};
CSkillInfo skill = skills.Lookup(skillId);
CSkillInfo skill = g_session.LookupSkill(skillId);
if (!skill.available) {
return 0;
}

View file

@ -3211,18 +3211,10 @@ void CPlayer::ReapplySkillEffects() {
this->LaunchEffect(0x18A, vector3d{0.0f, 0.0f, 0.0f}, 0.0f);
break;
case 0x98: {
ClientSkills skills{
g_session.m_skillBundle,
g_session.m_homunSkills,
g_session.m_mercSkills,
g_session.m_additionalSkills,
reinterpret_cast<const int&>(g_session.m_jobFlags),
g_activeSkillEffects
};
CSkillInfo skill = skills.bundle.Lookup(0x1B9, skills.classMode, skills.HasEffect(1717), skills.HasEffect(1716));
CSkillInfo skill = g_session.m_skillBundle.Lookup(0x1B9);
int effectId = skill.level;
if (effectId > 0) {
CSkillInfo upgrade = skills.bundle.Lookup(0xA1D, skills.classMode, skills.HasEffect(1717), skills.HasEffect(1716));
CSkillInfo upgrade = g_session.m_skillBundle.Lookup(0xA1D);
if (upgrade.level > 0) {
effectId = 5;
}

View file

@ -117,8 +117,8 @@ namespace {
// OFFSET: 0x00E1DF20
// FUNCTION: fn_23886
bool ClientSkills::HasEffect(std::uint32_t id) const {
for (const ActiveSkillEffect& effect : this->effects) {
bool CSession::HasSkillEffect(std::uint32_t id) const {
for (const ActiveSkillEffect& effect : g_activeSkillEffects) {
if (effect.id == id) {
return true;
}
@ -129,98 +129,78 @@ bool ClientSkills::HasEffect(std::uint32_t id) const {
// OFFSET: 0x00E096F0
// FUNCTION: fn_23782
CSkillInfo ClientSkills::LookupFirst(std::uint32_t id) const {
return Find(this->firstRange, id);
CSkillInfo CSession::LookupHomunSkill(std::uint32_t id) const {
return Find(this->m_homunSkills, id);
}
// OFFSET: 0x00E09A10
// FUNCTION: fn_23787
CSkillInfo ClientSkills::LookupOther(std::uint32_t id) const {
return Find(this->otherRanges, id);
CSkillInfo CSession::LookupMercSkill(std::uint32_t id) const {
return Find(this->m_mercSkills, id);
}
// OFFSET: 0x00E095B0
// FUNCTION: fn_23780
CSkillInfo ClientSkills::LookupAdditional(std::uint32_t id) const {
return Find(this->additional, id);
CSkillInfo CSession::LookupAdditionalSkill(std::uint32_t id) const {
return Find(this->m_additionalSkills, id);
}
// OFFSET: 0x00E088A0
// FUNCTION: fn_23767
CSkillInfo ClientSkills::Lookup(std::uint32_t id) const {
CSkillInfo CSession::LookupSkill(std::uint32_t id) {
if (id - 8000u <= 60) {
return this->LookupFirst(id);
return this->LookupHomunSkill(id);
}
if (id - 8200u <= 41 || id - 8400u <= 57) {
return this->LookupOther(id);
return this->LookupMercSkill(id);
}
if (id - 10000u <= 19) {
return this->LookupAdditional(id);
return this->LookupAdditionalSkill(id);
}
return this->bundle.Lookup(id, this->classMode, this->HasEffect(1717), this->HasEffect(1716));
return this->m_skillBundle.Lookup(id);
}
// OFFSET: 0x00E25240
// FUNCTION: fn_23904
void SkillWindows::Notify() {
if (this->first) {
this->first->SendMsg(nullptr, 23, 0, 0, 0, 0);
void CSession::NotifySkillWindows() {
if (g_windowMgr.window_02C4) {
g_windowMgr.window_02C4->SendMsg(nullptr, 23, 0, 0, 0, 0);
}
if (this->second) {
this->second->SendMsg(nullptr, 23, 0, 0, 0, 0);
if (g_windowMgr.window_01E8) {
g_windowMgr.window_01E8->SendMsg(nullptr, 23, 0, 0, 0, 0);
}
if (UIWindow* window = this->windows.LookupWindow(159)) {
if (UIWindow* window = g_windowMgr.LookupWindow(159)) {
window->SendMsg(nullptr, 23, 0, 0, 0, 0);
}
}
// OFFSET: 0x00E08530
// FUNCTION: fn_23762
void ClientSkills::Remove(std::uint32_t id, SkillWindows& windows) {
if (CSkillInfo* skill = this->bundle.FindGrouped(id)) {
void CSession::RemoveSkill(std::uint32_t id) {
if (CSkillInfo* skill = this->m_skillBundle.FindGrouped(id)) {
int previous;
if (this->bundle.PreviousLevel(static_cast<int>(id), previous)) {
if (this->m_skillBundle.PreviousLevel(static_cast<int>(id), previous)) {
skill->level = previous;
}
windows.Notify();
this->NotifySkillWindows();
return;
}
this->bundle.Remove(id);
if (this->bundle.RemoveExtra(id, windows.windows)) {
windows.Notify();
this->m_skillBundle.Remove(id);
if (this->m_skillBundle.RemoveExtra(id, *reinterpret_cast<WindowManagerWindows*>(&g_windowMgr))) {
this->NotifySkillWindows();
}
}
// OFFSET: 0x00DE0E40
int SkillUseLevels::Lookup(int id) const {
const auto value = static_cast<std::uint32_t>(id);
if (value - 1u <= 0x1F3Du) {
return this->use[value];
}
if (id > 10000) {
return this->additional[value - 10000u];
}
if (value - 8000u <= 60u) {
return this->homunculus[value - 8000u];
}
return 0;
}
// OFFSET: 0x00E07540
// FUNCTION: fn_23746
bool ClientSkills::Update(
const CSkillInfo& value, unsigned char notify, unsigned char updateUnknown000C, LuaScript& script, const SkillUseLevels& levels, SkillWindows& windows
) {
bool CSession::UpdateSkill(const CSkillInfo& value, unsigned char notify, unsigned char updateUnknown000C) {
{
CSkillInfo snapshot(value);
const auto update = [](CSkillInfo& target, const CSkillInfo& source, bool copy000C, bool copy0030) {
@ -240,30 +220,30 @@ bool ClientSkills::Update(
target.unknown_0034 = source.unknown_0034;
};
CSkillInfo* grouped = this->bundle.FindGrouped(snapshot.id);
CSkillInfo* grouped = this->m_skillBundle.FindGrouped(snapshot.id);
if (grouped) {
update(*grouped, snapshot, true, true);
} else if (snapshot.available) {
if (CSkillInfo* extra = this->bundle.FindExtra(snapshot.id)) {
if (CSkillInfo* extra = this->m_skillBundle.FindExtra(snapshot.id)) {
update(*extra, snapshot, true, false);
} else {
snapshot.unknown_0024 = UINT32_MAX;
snapshot.unknown_002C = 0;
this->bundle.AddExtra(snapshot, windows.windows);
this->m_skillBundle.AddExtra(snapshot, *reinterpret_cast<WindowManagerWindows*>(&g_windowMgr));
}
}
if (grouped || snapshot.available) {
if (CSkillInfo::UsesLevel(script, static_cast<int>(snapshot.id)) && snapshot.level != 0) {
const int saved = levels.Lookup(static_cast<int>(snapshot.id));
if (CSkillInfo::UsesLevel(*this->m_hotkeyScript, static_cast<int>(snapshot.id)) && snapshot.level != 0) {
const int saved = reinterpret_cast<const CharacterConfigSave*>(this)->UseLevel(static_cast<int>(snapshot.id));
if (saved <= 0 || saved > snapshot.level) {
this->bundle.SetUnknownValue(static_cast<int>(snapshot.id), snapshot.level);
this->m_skillBundle.SetUnknownValue(static_cast<int>(snapshot.id), snapshot.level);
}
}
}
}
if (CSkillInfo* existing = this->bundle.Find(value.id)) {
if (CSkillInfo* existing = this->m_skillBundle.Find(value.id)) {
existing->level = value.level;
std::memcpy(&existing->unknown_0014, &value.unknown_0014, sizeof(existing->unknown_0014));
std::memcpy(&existing->unknown_001C, &value.unknown_001C, sizeof(existing->unknown_001C));
@ -276,51 +256,15 @@ bool ClientSkills::Update(
existing->unknown_0030 = value.unknown_0030;
existing->unknown_0034 = value.unknown_0034;
if (notify == 1) {
windows.Notify();
this->NotifySkillWindows();
}
return false;
}
this->bundle.Add(value);
this->m_skillBundle.Add(value);
if (notify != 0) {
windows.Notify();
}
return true;
}
void CompanionSkills::Notify() {
if (this->window) {
this->window->SendMsg(nullptr, 23, 0, 0, 0, 0);
}
if (this->sharedWindow) {
this->sharedWindow->SendMsg(nullptr, 23, 0, 0, 0, 0);
}
}
bool CompanionSkills::Update(const CSkillInfo& value, unsigned char notify) {
for (CSkillInfo& skill : this->skills) {
if (skill.id == value.id) {
skill.level = value.level;
std::memcpy(&skill.unknown_0014, &value.unknown_0014, sizeof(skill.unknown_0014));
std::memcpy(&skill.unknown_001C, &value.unknown_001C, sizeof(skill.unknown_001C));
std::memcpy(&skill.unknown_0018, &value.unknown_0018, sizeof(skill.unknown_0018));
std::memcpy(&skill.unknown_000C, &value.unknown_000C, sizeof(skill.unknown_000C));
skill.unknown_0034 = value.unknown_0034;
if (notify) {
this->Notify();
}
return false;
}
}
this->skills.push_back(value);
if (notify) {
this->Notify();
this->NotifySkillWindows();
}
return true;
@ -328,8 +272,8 @@ bool CompanionSkills::Update(const CSkillInfo& value, unsigned char notify) {
// OFFSET: 0x00E07290
// FUNCTION: fn_23740
bool ClientSkills::UpdateAdditional(const CSkillInfo& value, int) {
for (CSkillInfo& skill : this->additional) {
bool CSession::UpdateAdditionalSkill(const CSkillInfo& value, int) {
for (CSkillInfo& skill : this->m_additionalSkills) {
if (skill.id == value.id) {
skill.level = value.level;
std::memcpy(&skill.unknown_0014, &value.unknown_0014, sizeof(skill.unknown_0014));
@ -341,7 +285,7 @@ bool ClientSkills::UpdateAdditional(const CSkillInfo& value, int) {
}
}
this->additional.push_back(value);
this->m_additionalSkills.push_back(value);
return true;
}

View file

@ -3,33 +3,6 @@
#include "Contents/Skills/PlayerSkillBundle.h"
class UIWindow;
struct SkillWindows {
UIWindow*& first;
UIWindow*& second;
WindowManagerWindows& windows;
void Notify();
};
struct SkillUseLevels {
const std::vector<int>& use;
const std::vector<int>& additional;
const std::vector<int>& homunculus;
int Lookup(int id) const;
};
struct CompanionSkills {
std::list<CSkillInfo>& skills;
UIWindow*& window;
UIWindow*& sharedWindow;
bool Update(const CSkillInfo& value, unsigned char notify);
void Notify();
};
struct ActiveSkillEffect {
/* 0000 */ std::uint32_t id;
/* 0004 */ std::uint32_t unknown_0004;
@ -42,29 +15,6 @@ struct ActiveSkillEffect {
extern std::vector<ActiveSkillEffect> g_activeSkillEffects;
struct ClientSkills {
CPlayerSkillBundle& bundle;
const std::list<CSkillInfo>& firstRange;
const std::list<CSkillInfo>& otherRanges;
std::list<CSkillInfo>& additional;
const int& classMode;
const std::vector<ActiveSkillEffect>& effects;
bool HasEffect(std::uint32_t id) const;
CSkillInfo LookupFirst(std::uint32_t id) const;
CSkillInfo LookupOther(std::uint32_t id) const;
CSkillInfo LookupAdditional(std::uint32_t id) const;
CSkillInfo Lookup(std::uint32_t id) const;
bool UpdateAdditional(const CSkillInfo& value, int unused);
void Remove(std::uint32_t id, SkillWindows& windows);
bool Update(
const CSkillInfo& value, unsigned char notify, unsigned char updateUnknown000C, LuaScript& script, const SkillUseLevels& levels, SkillWindows& windows
);
};
static_assert(sizeof(ActiveSkillEffect) == 28);
#if defined(_WIN32) && !defined(_WIN64)
static_assert(offsetof(ActiveSkillEffect, unknown_0018) == 0x18);

View file

@ -1,4 +1,5 @@
#include "Contents/Skills/PlayerSkillBundle.h"
#include "Client/Session.h"
#include "UI/Window/UIWindow.h"
#include "UI/Window/WindowManagerWindows.h"
@ -68,20 +69,17 @@ CSkillInfo* CPlayerSkillBundle::Find(std::uint32_t id) {
// OFFSET: 0x00CACF20
// FUNCTION: fn_21049
std::uint32_t CPlayerSkillBundle::ResolveSkillId(std::uint32_t id, int classMode, bool effect1717, bool effect1716) {
if (classMode != 1 || (id != 6578 && id != 6579)) {
std::uint32_t ResolveSkillId(std::uint32_t id) {
if (g_session.GetUnknown8134() != 1 || (id != 6578 && id != 6579)) {
return id;
}
const auto valid = [&](std::uint32_t key) {
const auto entry = this->index.find(key);
return entry != this->index.end() && entry->second->IsValid();
};
if (effect1717 && valid(6580)) {
CSkillInfo* skill;
if (g_session.HasSkillEffect(1717) && g_session.m_skillBundle.FindIndexed(6580, skill) && skill->IsValid()) {
return 6580;
}
if (effect1716 && valid(6579)) {
if (g_session.HasSkillEffect(1716) && g_session.m_skillBundle.FindIndexed(6579, skill) && skill->IsValid()) {
return 6579;
}
@ -90,12 +88,12 @@ std::uint32_t CPlayerSkillBundle::ResolveSkillId(std::uint32_t id, int classMode
// OFFSET: 0x007716B0
// FUNCTION: fn_08280
CSkillInfo CPlayerSkillBundle::Lookup(std::uint32_t id, int classMode, bool effect1717, bool effect1716) {
CSkillInfo CPlayerSkillBundle::Lookup(std::uint32_t id) {
if (this->skills.empty()) {
return CSkillInfo(-1);
}
const auto entry = this->index.find(this->ResolveSkillId(id, classMode, effect1717, effect1716));
const auto entry = this->index.find(ResolveSkillId(id));
if (entry != this->index.end() && entry->second->IsValid()) {
return *entry->second;
}

View file

@ -29,9 +29,8 @@ public:
void Add(const CSkillInfo& value);
void Remove(std::uint32_t id);
CSkillInfo* Find(std::uint32_t id);
CSkillInfo Lookup(std::uint32_t id, int classMode, bool effect1717, bool effect1716);
CSkillInfo Lookup(std::uint32_t id);
bool FindIndexed(std::uint32_t id, CSkillInfo*& output);
std::uint32_t ResolveSkillId(std::uint32_t id, int classMode, bool effect1717, bool effect1716);
bool UpdatePending(const CSkillInfo& value);
CSkillInfo Pending(std::uint32_t id);
CSkillInfo* FindExtra(std::uint32_t id);

View file

@ -1,5 +1,7 @@
#include "Network/Packets/SkillUpdatePacket.h"
#include "UI/Window/WindowOrdering.h"
#include "Client/Mode/CGameMode.h"
#include "Client/Session.h"
#include "UI/Window/UIWindow.h"
#include "UI/Window/UIWindowMgr.h"
#include <cstring>
@ -14,8 +16,8 @@ namespace {
// OFFSET: 0x00D42AA0
// FUNCTION: fn_21829
void SkillUpdatePacket::Apply(const void* packet) {
this->pending = 0;
void CGameMode::ApplySkillUpdatePacket(const void* packet) {
*reinterpret_cast<int*>(&this->unknown_0100[0x0C]) = 0;
const auto* bytes = static_cast<const unsigned char*>(packet);
const auto opcode = Read<std::uint16_t>(bytes);
@ -24,13 +26,13 @@ void SkillUpdatePacket::Apply(const void* packet) {
switch (opcode) {
case 270:
value = this->client.bundle.Lookup(id, this->client.classMode, this->client.HasEffect(1717), this->client.HasEffect(1716));
value = g_session.m_skillBundle.Lookup(id);
break;
case 569:
value = this->client.LookupFirst(id);
value = g_session.LookupHomunSkill(id);
break;
case 670:
value = this->client.LookupOther(id);
value = g_session.LookupMercSkill(id);
break;
}
@ -39,25 +41,25 @@ void SkillUpdatePacket::Apply(const void* packet) {
value.unknown_0014 = static_cast<std::int32_t>(Read<std::int16_t>(bytes + 6));
value.unknown_0018 = bytes[10];
value.unknown_001C = static_cast<std::int32_t>(Read<std::int16_t>(bytes + 8));
value.unknown_0034 = value.UseApAmount(this->script, value.level);
this->client.bundle.ApplyLevelChange(value);
value.unknown_0034 = value.UseApAmount(*g_session.m_hotkeyScript, value.level);
g_session.m_skillBundle.ApplyLevelChange(value);
switch (opcode) {
case 270:
this->client.Update(value, 1, 0, this->script, this->levels, this->windows);
g_session.UpdateSkill(value, 1, 0);
break;
case 569:
this->first.Update(value, 1);
g_session.UpdateHomunSkill(value, 1);
break;
case 670:
this->other.Update(value, 1);
g_session.UpdateMercSkill(value, 1);
break;
}
}
// OFFSET: 0x00D06AF0
// FUNCTION: fn_21577
void LearnedSkillReceiver::Apply(
void CGameMode::ReceiveLearnedSkill(
std::uint16_t id, std::int16_t level, int unknown000C, std::uint8_t unknown0018, std::int16_t unknown0014, std::int16_t unknown001C, std::int16_t unknown0030
) {
CSkillInfo value;
@ -65,25 +67,25 @@ void LearnedSkillReceiver::Apply(
value.id = id;
value.level = level;
value.unknown_0018 = unknown0018;
value.name = value.IdName(this->script);
value.name = value.IdName(*g_session.m_hotkeyScript);
value.unknown_0014 = unknown0014;
value.unknown_001C = unknown001C;
value.unknown_0030 = unknown0030;
value.unknown_0034 = value.UseApAmount(this->script, level);
value.unknown_0034 = value.UseApAmount(*g_session.m_hotkeyScript, level);
this->client.bundle.RecordLevelChange(value);
g_session.m_skillBundle.RecordLevelChange(value);
if (value.id == 336) {
this->skill336 = 1;
g_session.unknown_5468 = 1;
}
this->client.Update(value, 1, 0, this->script, this->levels, this->windows);
g_session.UpdateSkill(value, 1, 0);
}
// OFFSET: 0x00D2B5C0
// FUNCTION: fn_45442
void AdditionalSkillPacket::Apply(const void* packet) {
this->pending = 0;
this->client.additional.clear();
void CGameMode::ApplyAdditionalSkillPacket(const void* packet) {
*reinterpret_cast<int*>(&this->unknown_0100[0x0C]) = 0;
g_session.m_additionalSkills.clear();
const auto* bytes = static_cast<const unsigned char*>(packet);
@ -98,15 +100,21 @@ void AdditionalSkillPacket::Apply(const void* packet) {
value.unknown_0014 = static_cast<std::int32_t>(Read<std::int16_t>(record + 8));
value.unknown_000C = Read<std::uint32_t>(record + 2);
value.unknown_0018 = record[36];
value.name = value.IdName(this->script);
value.unknown_0034 = value.UseApAmount(this->script, value.level);
value.name = value.IdName(*g_session.m_hotkeyScript);
value.unknown_0034 = value.UseApAmount(*g_session.m_hotkeyScript, value.level);
if (value.id - 10000u <= 19u) {
this->client.UpdateAdditional(value, 1);
g_session.UpdateAdditionalSkill(value, 1);
}
}
this->capacity = Read<std::int16_t>(bytes + 4);
this->ordering.InvalidateFrames(this->frameLatch);
this->windows.Notify();
g_session.m_guildSkillPoint = Read<std::int16_t>(bytes + 4);
g_session.InvalidateWindowFrames();
if (g_windowMgr.window_032C) {
g_windowMgr.window_032C->SendMsg(nullptr, 23, 0, 0, 0, 0);
}
if (g_windowMgr.window_01E8) {
g_windowMgr.window_01E8->SendMsg(nullptr, 23, 0, 0, 0, 0);
}
}

View file

@ -1,45 +0,0 @@
#ifndef RAGNAROK_SOURCE_NETWORK_PACKETS_SKILLUPDATEPACKET_H
#define RAGNAROK_SOURCE_NETWORK_PACKETS_SKILLUPDATEPACKET_H
#include "Contents/Skills/ClientSkills.h"
struct WindowOrdering;
struct SkillUpdatePacket {
int& pending;
ClientSkills& client;
CompanionSkills& first;
CompanionSkills& other;
LuaScript& script;
const SkillUseLevels& levels;
SkillWindows& windows;
void Apply(const void* packet);
};
struct LearnedSkillReceiver {
ClientSkills& client;
LuaScript& script;
const SkillUseLevels& levels;
SkillWindows& windows;
int& skill336;
void Apply(
std::uint16_t id, std::int16_t level, int unknown000C, std::uint8_t unknown0018, std::int16_t unknown0014, std::int16_t unknown001C,
std::int16_t unknown0030
);
};
struct AdditionalSkillPacket {
int& pending;
ClientSkills& client;
LuaScript& script;
int& capacity;
WindowOrdering& ordering;
int& frameLatch;
CompanionSkills& windows;
void Apply(const void* packet);
};
#endif

View file

@ -7012,15 +7012,7 @@ int UISkillDescribeWnd::SendMsg(UIWindow* sender, int message, std::intptr_t a,
this->unknown_00EC = this->unknown_00D4 = skill.DisplayName(*g_luaScript);
this->m_skillId = static_cast<int>(skill.id);
{
ClientSkills skills{
g_session.m_skillBundle,
g_session.m_homunSkills,
g_session.m_mercSkills,
g_session.m_additionalSkills,
reinterpret_cast<const int&>(g_session.m_jobFlags),
g_activeSkillEffects
};
CSkillInfo owned = skills.Lookup(static_cast<std::uint32_t>(a));
CSkillInfo owned = g_session.LookupSkill(static_cast<std::uint32_t>(a));
if (owned.available != 0 && owned.unknown_0014 != 0 && owned.level != 0) {
char cost[64];
if (skill.UseApAmount(*g_luaScript, owned.level) != 0) {

View file

@ -545,7 +545,7 @@ void UIBasicSkillCtrl::Slot28(int, int) {
}
LuaScript& script = *g_session.m_hotkeyScript;
CSkillInfo skill = this->m_skills->Lookup(static_cast<std::uint32_t>(this->m_skillId));
CSkillInfo skill = g_session.LookupSkill(static_cast<std::uint32_t>(this->m_skillId));
const int sp = skill.UseSpAmount(script, skill.level);
const int ap = skill.UseApAmount(script, skill.level);
std::string text;
@ -2283,7 +2283,7 @@ void UIBasicSkillCtrl::Paint() {
this->ClearSurface(0xFFFF00FF);
bool drawn = false;
if (this->m_skillId >= 0) {
CSkillInfo skill = this->m_skills->Lookup(static_cast<std::uint32_t>(this->m_skillId));
CSkillInfo skill = g_session.LookupSkill(static_cast<std::uint32_t>(this->m_skillId));
if (skill.available != 0) {
drawn = true;
if (this->m_level > 0) {

View file

@ -876,7 +876,7 @@ void UIBasicSkillCtrl::Slot10(int, int, std::intptr_t argument3) {
const ModeDragState* drag = reinterpret_cast<const ModeDragState*>(argument3);
if (drag->skill) {
std::string name = drag->skillName;
CSkillInfo skill = reinterpret_cast<const ClientSkills&>(g_session).Lookup(drag->id);
CSkillInfo skill = g_session.LookupSkill(drag->id);
if (skill.level && skill.available && skill.unknown_0014) {
this->m_skillId = static_cast<int>(drag->id);
this->m_level = drag->skillLevel;

View file

@ -415,7 +415,7 @@ void UIQuickSlotWnd::Paint() {
const int x = index * 29 + 5;
if (entry.skill) {
CSkillInfo skill = painting.skills.Lookup(entry.id);
CSkillInfo skill = g_session.LookupSkill(entry.id);
if (!skill.available) {
continue;
}

View file

@ -1,3 +1,4 @@
#include "Client/Session.h"
#include "UI/Shortcuts/ShortcutDetails.h"
#include "UI/Shortcuts/SkillDetailClose.h"
#include "UI/Window/UIWindow.h"
@ -87,7 +88,7 @@ void ShortcutDetails::Open(UIWindow& window, ShortcutGrid& grid, int x, int y, c
return;
}
CSkillInfo skill = this->skills.Lookup(slot->itemId);
CSkillInfo skill = g_session.LookupSkill(slot->itemId);
if (!skill.MatchesShortcut(slot)) {
return;

View file

@ -14,7 +14,6 @@ struct ShortcutDetails {
WindowManagerWindows& windows;
SkillDetailClose& skillClose;
const std::uint32_t& describedSkill;
ClientSkills& skills;
const std::list<ITEM_INFO>& inventory;
const bool& itemSlotActive;
unsigned char& currentRow;

View file

@ -54,14 +54,7 @@ void ShortcutDrop::Drop(UIWindow& window, ShortcutGrid& grid, int x, int y, cons
return;
}
CSkillInfo skill = ClientSkills{
g_session.m_skillBundle,
g_session.m_homunSkills,
g_session.m_mercSkills,
g_session.m_additionalSkills,
reinterpret_cast<const int&>(g_session.m_jobFlags),
g_activeSkillEffects
}.Lookup(id);
CSkillInfo skill = g_session.LookupSkill(id);
if ((skill.level == 0 && skill.available == 0) || grid.rows <= this->currentRow) {
if (this->mode) {
this->mode->SendModeMessage(18, 0, 0, 0, 0);
@ -98,14 +91,7 @@ void ShortcutDrop::Drop(UIWindow& window, ShortcutGrid& grid, int x, int y, cons
Refresh(window);
} else if (originalSlot != -1) {
CSkillInfo skill = ClientSkills{
g_session.m_skillBundle,
g_session.m_homunSkills,
g_session.m_mercSkills,
g_session.m_additionalSkills,
reinterpret_cast<const int&>(g_session.m_jobFlags),
g_activeSkillEffects
}.Lookup(id);
CSkillInfo skill = g_session.LookupSkill(id);
const std::uint32_t key = Grouped(skill.id) ? 9999 : skill.id;
const auto record =
std::find_if(reinterpret_cast<ShortcutCooldowns&>(g_session.m_requestTimers).records.begin(), reinterpret_cast<ShortcutCooldowns&>(g_session.m_requestTimers).records.end(), [&](const ShortcutCooldownRecord& entry) {
@ -205,7 +191,7 @@ void UIQuickSlotWnd::Slot10(int x, int y, std::intptr_t argument) {
const std::string copiedName(value.skillName.c_str(), value.skillName.size());
const int slot = this->SlotAt(x, y);
if (slot != -1) {
CSkillInfo skill = painting.skills.Lookup(value.id);
CSkillInfo skill = g_session.LookupSkill(value.id);
if (skill.level != 0 && skill.available != 0) {
g_session.SetHotkeyEntry(1, skill.id, value.skillLevel, slot);
RemoveAlternate(painting.cooldowns, value.slot, slot);
@ -234,7 +220,7 @@ void UIQuickSlotWnd::Slot10(int x, int y, std::intptr_t argument) {
this->Invalidate();
}
} else if (value.slot != -1) {
CSkillInfo skill = painting.skills.Lookup(value.id);
CSkillInfo skill = g_session.LookupSkill(value.id);
const std::uint32_t key = Grouped(skill.id) ? 9999 : skill.id;
const std::list<ShortcutCooldownRecord>::iterator record =
std::find_if(records.begin(), records.end(), [&](const ShortcutCooldownRecord& entry) { return entry.id == key; });

View file

@ -1,3 +1,4 @@
#include "Client/Session.h"
#include "Render/Text/TextContext.h"
#include "Resource/Bitmap/BitmapResource.h"
#include "Resource/ResourceMgr.h"
@ -95,7 +96,7 @@ void ShortcutPainting::Paint(UIWindow& window, const ShortcutGrid& grid, const N
const int x = 16 + 29 * column;
if (slot.unknown_0000 != 0) {
CSkillInfo skill = this->skills.Lookup(slot.itemId);
CSkillInfo skill = g_session.LookupSkill(slot.itemId);
if (!skill.MatchesShortcut(&slot)) {
continue;
}

View file

@ -17,7 +17,6 @@ struct ShortcutPainting {
ResourceMgr& resources;
FontCache& fonts;
const TextLocale& locale;
ClientSkills& skills;
const std::list<ITEM_INFO>& inventory;
std::list<ShortcutCooldownIcon>& icons;
ShortcutCooldowns& cooldowns;

View file

@ -1,3 +1,4 @@
#include "Client/Session.h"
#include "Client/Mode/ModeDragState.h"
#include "UI/Shortcuts/ShortcutPress.h"
#include "UI/Window/UIFrameWnd.h"
@ -29,7 +30,7 @@ void ShortcutPress::Press(UIFrameWnd& window, ShortcutGrid& grid, int x, int y,
}
if (slot.unknown_0000 != 0) {
CSkillInfo skill = this->skills.Lookup(slot.itemId);
CSkillInfo skill = g_session.LookupSkill(slot.itemId);
if (skill.MatchesShortcut(&slot) && this->drag) {
this->drag->BeginSkill(this->windows, this->resources, 7, skill.id, skill.name, slot.unknown_0005, index);
}

View file

@ -13,7 +13,6 @@ class ResourceMgr;
struct ModeDragState;
struct ShortcutPress {
ClientSkills& skills;
const std::list<ITEM_INFO>& inventory;
ResourceMgr& resources;
WindowManagerWindows& windows;

View file

@ -90,14 +90,7 @@ void UIShortCutWnd::Slot28(int x, int y) {
if (slot.itemId == 0) {
text = shortcut;
} else if (slot.unknown_0000 != 0) {
CSkillInfo skill = ClientSkills{
g_session.m_skillBundle,
g_session.m_homunSkills,
g_session.m_mercSkills,
g_session.m_additionalSkills,
reinterpret_cast<const int&>(g_session.m_jobFlags),
g_activeSkillEffects
}.Lookup(slot.itemId);
CSkillInfo skill = g_session.LookupSkill(slot.itemId);
if (!skill.MatchesShortcut(&slot)) {
text = shortcut;
} else {

View file

@ -55,7 +55,7 @@ void UIQuickSlotWnd::Slot25(int x, int y) {
QuickSlotPainting& painting = *this->m_painting;
const QuickSlotEntry entry = this->m_entries[index];
if (entry.skill) {
CSkillInfo skill = painting.skills.Lookup(entry.id);
CSkillInfo skill = g_session.LookupSkill(entry.id);
if (skill.available && skill.level) {
if (CGameMode* mode = static_cast<CGameMode*>(g_modeMgr.GetGameMode())) {
mode->drag.BeginSkill(g_windowMgr, ResourceMgr::Instance(), 16, skill.id, skill.name, entry.count, index);
@ -102,7 +102,7 @@ void UIQuickSlotWnd::Slot28(int x, int y) {
text.clear();
} else if (this->m_entries[this->m_selected].skill) {
LuaScript& script = *g_session.m_hotkeyScript;
CSkillInfo skill = painting.skills.Lookup(id);
CSkillInfo skill = g_session.LookupSkill(id);
const int level = this->m_entries[this->m_selected].count;
const int sp = skill.UseSpAmount(script, level);
const int ap = skill.UseApAmount(script, level);
@ -212,8 +212,7 @@ int UIQuickSlotWnd::SendMsg(UIWindow* sender, int message, std::intptr_t argumen
continue;
}
ClientSkills& skills = this->m_painting->skills;
CSkillInfo skill = skills.bundle.Lookup(source.itemId, skills.classMode, skills.HasEffect(1717), skills.HasEffect(1716));
CSkillInfo skill = g_session.m_skillBundle.Lookup(source.itemId);
if (skill.available == 0) {
std::list<ShortcutCooldownRecord>& records = this->m_painting->cooldowns.records;
const auto record = std::find_if(records.begin(), records.end(), [&](const ShortcutCooldownRecord& value) { return value.id == source.itemId; });
@ -224,12 +223,12 @@ int UIQuickSlotWnd::SendMsg(UIWindow* sender, int message, std::intptr_t argumen
}
}
skill = skills.LookupFirst(source.itemId);
skill = g_session.LookupHomunSkill(source.itemId);
if (skill.available == 0) {
skill = skills.LookupOther(source.itemId);
skill = g_session.LookupMercSkill(source.itemId);
}
if (skill.available == 0) {
skill = skills.LookupAdditional(source.itemId);
skill = g_session.LookupAdditionalSkill(source.itemId);
}
}
@ -299,7 +298,7 @@ int UIQuickSlotWnd::SendMsg(UIWindow* sender, int message, std::intptr_t argumen
return 0;
}
CSkillInfo skill = this->m_painting->skills.Lookup(entry.id);
CSkillInfo skill = g_session.LookupSkill(entry.id);
if (skill.level != 0 && skill.available != 0) {
static_cast<CMode*>(g_charViewMode)->SendMsg(0x71, reinterpret_cast<int>(&skill), entry.count, 0, 0);
}

View file

@ -9,14 +9,12 @@
class FontCache;
struct TextLocale;
struct ClientSkills;
struct ITEM_INFO;
class AutomaticSkills;
struct QuickSlotPainting {
FontCache& fonts;
const TextLocale& locale;
ClientSkills& skills;
const std::list<ITEM_INFO>& inventory;
std::list<ShortcutCooldownIcon>& icons;
ShortcutCooldowns& cooldowns;

View file

@ -1,4 +1,5 @@
#include "Client/Session.h"
#include "Contents/UserData/CharacterConfigSave.h"
#include "Client/Mode/ModeDragState.h"
#include "Client/Mode/ModeEvents.h"
#include "Client/Mode/CMode.h"
@ -339,14 +340,7 @@ inline void UseShortcutSlot(const NormalItemSlot& slot) {
}
if (slot.unknown_0000 != 0) {
CSkillInfo skill = ClientSkills{
g_session.m_skillBundle,
g_session.m_homunSkills,
g_session.m_mercSkills,
g_session.m_additionalSkills,
reinterpret_cast<const int&>(g_session.m_jobFlags),
g_activeSkillEffects
}.Lookup(slot.itemId);
CSkillInfo skill = g_session.LookupSkill(slot.itemId);
if (skill.MatchesShortcut(&slot)) {
int level = slot.unknown_0005;
if ((skill.id == 6579 || skill.id == 6580) && skill.level < level) {
@ -442,17 +436,6 @@ int UIShortCutWnd::SendMsg(UIWindow* sender, int message, std::intptr_t a, std::
case 23: {
ShortcutCooldowns& cooldowns = reinterpret_cast<ShortcutCooldowns&>(g_session.m_requestTimers);
ClientSkills skills{
g_session.m_skillBundle,
g_session.m_homunSkills,
g_session.m_mercSkills,
g_session.m_additionalSkills,
reinterpret_cast<const int&>(g_session.m_jobFlags),
g_activeSkillEffects
};
const SkillUseLevels levels{
g_session.m_skillBundle.unknown_0064, *reinterpret_cast<const std::vector<int>*>(g_session.unknown_0710), g_session.m_homunSkillLevels
};
for (int index = 0; index < 36; ++index) {
const int source = g_session.RotateShortcut(index, g_session.unknown_06FC);
if (g_session.unknown_06FC == 0 || g_session.unknown_06FC == 1) {
@ -464,7 +447,7 @@ int UIShortCutWnd::SendMsg(UIWindow* sender, int message, std::intptr_t a, std::
continue;
}
CSkillInfo skill = skills.bundle.Lookup(slot.itemId, skills.classMode, skills.HasEffect(1717), skills.HasEffect(1716));
CSkillInfo skill = g_session.m_skillBundle.Lookup(slot.itemId);
if (skill.available == 0) {
const auto record = std::find_if(cooldowns.records.begin(), cooldowns.records.end(), [&](const ShortcutCooldownRecord& value) {
return value.id == slot.itemId;
@ -476,17 +459,17 @@ int UIShortCutWnd::SendMsg(UIWindow* sender, int message, std::intptr_t a, std::
}
}
skill = skills.LookupFirst(slot.itemId);
skill = g_session.LookupHomunSkill(slot.itemId);
if (skill.available == 0) {
skill = skills.LookupOther(slot.itemId);
skill = g_session.LookupMercSkill(slot.itemId);
}
if (skill.available == 0) {
skill = skills.LookupAdditional(slot.itemId);
skill = g_session.LookupAdditionalSkill(slot.itemId);
}
}
if (skill.available != 0 && skill.level != 0 && levels.Lookup(static_cast<int>(skill.id)) == 0) {
if (skill.available != 0 && skill.level != 0 && reinterpret_cast<const CharacterConfigSave*>(&g_session)->UseLevel(static_cast<int>(skill.id)) == 0) {
slot.unknown_0005 = static_cast<std::int16_t>(skill.level);
}
}

View file

@ -8,6 +8,6 @@ UIBasicItemCtrl::UIBasicItemCtrl(WindowManagerWindows& windowList)
// OFFSET: 0x0086C4C0
// FUNCTION: fn_11027
UIBasicSkillCtrl::UIBasicSkillCtrl(ClientSkills& skills)
: UIWindow(0), m_skillId(-1), m_skills(&skills), m_level(0) {
UIBasicSkillCtrl::UIBasicSkillCtrl()
: UIWindow(0), m_skillId(-1), m_level(0) {
}

View file

@ -6,7 +6,6 @@
#include <string>
struct ClientSkills;
#include "UI/Window/WindowManagerWindows.h"
class UIBasicItemCtrl : public UIWindow {
@ -32,7 +31,7 @@ protected:
class UIBasicSkillCtrl : public UIWindow {
public:
UIBasicSkillCtrl(ClientSkills& skills);
UIBasicSkillCtrl();
void Slot10(int argument1, int argument2, std::intptr_t argument3) override;
void Paint() override;
void Slot26(int x, int y) override;
@ -41,9 +40,7 @@ public:
protected:
/* 007C */ int m_skillId;
ClientSkills* m_skills;
void* unknown_controls;
int m_level;
/* 0080 */ int m_level;
};
std::string SkillUseTextPercent(const char* name, int level, int sp, int ap);

View file

@ -72,7 +72,7 @@ UIEscOptionWnd::UIEscOptionWnd()
int escMode;
if (mode->unknown_0250 == 0) {
escMode = 0;
} else if (!mode->HasResurrectionItem() && !reinterpret_cast<const ClientSkills&>(g_session).HasEffect(580)) {
} else if (!mode->HasResurrectionItem() && !g_session.HasSkillEffect(580)) {
escMode = 1;
} else {
escMode = 2;