Merge branch 'tob_stringupgrade' into tob_buffupdate

This commit is contained in:
dannuic
2026-04-25 23:52:20 -06:00
9 changed files with 164 additions and 143 deletions
+8 -5
View File
@@ -4,9 +4,9 @@
#pragma once
#include "client_version.h"
#include "common/emu_opcodes.h"
#include <cstdint>
#include <vector>
#include "common/types.h"
@@ -24,11 +24,14 @@ public:
IBuff() = default;
virtual ~IBuff() = default;
virtual EQApplicationPacket* MakeLegacyBuffsPacket(Mob* mob, int32_t timer, bool for_target, bool clear_buffs) const = 0;
virtual std::unique_ptr<EQApplicationPacket> MakeLegacyBuffsPacket(Mob* mob, int32_t timer, bool for_target,
bool clear_buffs) const = 0;
virtual EQApplicationPacket* BuffDefinition(Mob* mob, const Buffs_Struct& buff, int slot, bool fade) const = 0;
virtual EQApplicationPacket* RefreshBuffs(EmuOpcode opcode, Mob* mob, int32_t timer, bool remove, bool buff_timers_suspended, const std::vector<uint32_t>& slots) const = 0;
virtual void SetRefreshType(EQApplicationPacket* packet, Mob* source, Client* target) const = 0;
virtual std::unique_ptr<EQApplicationPacket> BuffDefinition(Mob* mob, const Buffs_Struct& buff, int slot,
bool fade) const = 0;
virtual std::unique_ptr<EQApplicationPacket> RefreshBuffs(EmuOpcode opcode, Mob* mob, int32_t timer, bool remove,
bool buff_timers_suspended, const std::vector<uint32_t>& slots) const = 0;
virtual void SetRefreshType(const std::unique_ptr<EQApplicationPacket>& packet, Mob* source, Client* target) const = 0;
};
} // namespace Buff
+6 -4
View File
@@ -37,12 +37,14 @@ public:
virtual ~IMessage() = default;
// these two are the basic string message packets
[[nodiscard]] virtual EQApplicationPacket* Simple(uint32_t color, uint32_t id) const = 0;
[[nodiscard]] virtual EQApplicationPacket* Formatted(uint32_t color, uint32_t id, const std::array<const char*, 9>& args) const = 0;
virtual std::unique_ptr<EQApplicationPacket> Simple(uint32_t color, uint32_t id) const = 0;
virtual std::unique_ptr<EQApplicationPacket> Formatted(uint32_t color, uint32_t id,
const std::array<const char*, 9>& args) const = 0;
// These aren't technically messages, but they use the same format and are similar enough to include here
virtual EQApplicationPacket* InterruptSpell(uint32_t message, uint32_t spawn_id, const char* spell_link) const = 0;
virtual EQApplicationPacket* InterruptSpellOther(Mob* sender, uint32_t message, uint32_t spawn_id,
virtual std::unique_ptr<EQApplicationPacket> InterruptSpell(uint32_t message, uint32_t spawn_id,
const char* spell_link) const = 0;
virtual std::unique_ptr<EQApplicationPacket> InterruptSpellOther(Mob* sender, uint32_t message, uint32_t spawn_id,
const char* name, const char* spell_link) const = 0;
};
+39 -37
View File
@@ -26,6 +26,8 @@
#include "common/patches/rof2.h"
#include "common/patches/tob.h"
#include <array>
using Version = EQ::versions::ClientVersion;
struct ClientComponents
@@ -34,64 +36,64 @@ struct ClientComponents
{
switch (version) {
case Version::TOB:
buffComponent = std::make_shared<Buff::TOB>();
messageComponent = std::make_shared<Message::TOB>();
buffComponent = std::make_unique<Buff::TOB>();
messageComponent = std::make_unique<Message::TOB>();
break;
case Version::RoF2:
buffComponent = std::make_shared<Buff::RoF2>();
messageComponent = std::make_shared<Message::RoF2>();
buffComponent = std::make_unique<Buff::RoF2>();
messageComponent = std::make_unique<Message::RoF2>();
break;
case Version::RoF:
buffComponent = std::make_shared<Buff::RoF>();
messageComponent = std::make_shared<Message::RoF>();
buffComponent = std::make_unique<Buff::RoF>();
messageComponent = std::make_unique<Message::RoF>();
break;
case Version::UF:
buffComponent = std::make_shared<Buff::UF>();
messageComponent = std::make_shared<Message::UF>();
buffComponent = std::make_unique<Buff::UF>();
messageComponent = std::make_unique<Message::UF>();
break;
case Version::SoD:
buffComponent = std::make_shared<Buff::SoD>();
messageComponent = std::make_shared<Message::SoD>();
buffComponent = std::make_unique<Buff::SoD>();
messageComponent = std::make_unique<Message::SoD>();
break;
case Version::SoF:
buffComponent = std::make_shared<Buff::SoF>();
messageComponent = std::make_shared<Message::SoF>();
buffComponent = std::make_unique<Buff::SoF>();
messageComponent = std::make_unique<Message::SoF>();
break;
case Version::Titanium:
buffComponent = std::make_unique<Buff::Titanium>();
messageComponent = std::make_unique<Message::Titanium>();
break;
default:
buffComponent = std::make_shared<Buff::Titanium>();
messageComponent = std::make_shared<Message::Titanium>();
break;
}
}
const Version version;
std::shared_ptr<Buff::IBuff> buffComponent;
std::shared_ptr<Message::IMessage> messageComponent;
std::unique_ptr<Buff::IBuff> buffComponent;
std::unique_ptr<Message::IMessage> messageComponent;
};
static const ClientComponents& GetComponents(Version version)
{
static const std::unordered_map<Version, ClientComponents> patches = [] {
std::unordered_map<Version, ClientComponents> p;
p.emplace(Version::Titanium, Version::Titanium);
p.emplace(Version::SoF, Version::SoF);
p.emplace(Version::SoD, Version::SoD);
p.emplace(Version::UF, Version::UF);
p.emplace(Version::RoF, Version::RoF);
p.emplace(Version::RoF2, Version::RoF2);
p.emplace(Version::TOB, Version::TOB);
return p;
}();
// this array must be in the same order as the Version enum because it converts Version to index directly
static const std::array<ClientComponents, EQ::versions::ClientVersionCount> s_patches = {
{
ClientComponents(Version::Unknown), // empty
ClientComponents(Version::Client62), // empty
ClientComponents(Version::Titanium),
ClientComponents(Version::SoF),
ClientComponents(Version::SoD),
ClientComponents(Version::UF),
ClientComponents(Version::RoF),
ClientComponents(Version::RoF2),
ClientComponents(Version::TOB),
}
};
return patches.at(version);
const std::unique_ptr<Buff::IBuff>& GetBuffComponent(Version version)
{
return s_patches.at(static_cast<uint32_t>(version)).buffComponent;
}
const std::shared_ptr<Buff::IBuff>& GetBuffComponent(Version version)
const std::unique_ptr<Message::IMessage>& GetMessageComponent(Version version)
{
return GetComponents(version).buffComponent;
}
const std::shared_ptr<Message::IMessage>& GetMessageComponent(Version version)
{
return GetComponents(version).messageComponent;
return s_patches.at(static_cast<uint32_t>(version)).messageComponent;
}
+3 -2
View File
@@ -11,5 +11,6 @@ namespace Buff { class IBuff; }
namespace Message { class IMessage; }
// store all static functions for the different patches here
const std::shared_ptr<Buff::IBuff>& GetBuffComponent(EQ::versions::ClientVersion version);
const std::shared_ptr<Message::IMessage>& GetMessageComponent(EQ::versions::ClientVersion version);
// store all static functions for the different patches here, this can return nullptr for unsupported patches
const std::unique_ptr<Buff::IBuff>& GetBuffComponent(EQ::versions::ClientVersion version);
const std::unique_ptr<Message::IMessage>& GetMessageComponent(EQ::versions::ClientVersion version);
+19 -21
View File
@@ -3924,12 +3924,11 @@ namespace Titanium
} /*Titanium*/
namespace Message {
EQApplicationPacket* Titanium::Simple(uint32_t color, uint32_t id) const
std::unique_ptr<EQApplicationPacket> Titanium::Simple(uint32_t color, uint32_t id) const
{
uint32_t string_id = ResolveID(id);
if (string_id > 0) {
auto outapp = new EQApplicationPacket(OP_SimpleMessage, sizeof(SimpleMessage_Struct));
auto outapp = std::make_unique<EQApplicationPacket>(OP_SimpleMessage, sizeof(SimpleMessage_Struct));
auto* sms = reinterpret_cast<SimpleMessage_Struct*>(outapp->pBuffer);
sms->string_id = string_id;
sms->color = color;
@@ -3941,7 +3940,7 @@ EQApplicationPacket* Titanium::Simple(uint32_t color, uint32_t id) const
return nullptr;
}
EQApplicationPacket* Titanium::Formatted(
std::unique_ptr<EQApplicationPacket> Titanium::Formatted(
uint32_t color, uint32_t id, const std::array<const char*, 9>& args) const
{
uint32_t string_id = ResolveID(id);
@@ -3963,15 +3962,16 @@ EQApplicationPacket* Titanium::Formatted(
buf.WriteUInt8(0);
return new EQApplicationPacket(OP_FormattedMessage, std::move(buf));
return std::make_unique<EQApplicationPacket>(OP_FormattedMessage, std::move(buf));
}
return nullptr;
}
EQApplicationPacket* Titanium::InterruptSpell(uint32_t message, uint32_t spawn_id, const char* spell_link) const
std::unique_ptr<EQApplicationPacket> Titanium::InterruptSpell(uint32_t message, uint32_t spawn_id,
const char* spell_link) const
{
auto outapp = new EQApplicationPacket(OP_InterruptCast, sizeof(InterruptCast_Struct));
auto outapp = std::make_unique<EQApplicationPacket>(OP_InterruptCast, sizeof(InterruptCast_Struct));
auto ic = reinterpret_cast<InterruptCast_Struct*>(outapp->pBuffer);
ic->messageid = ResolveID(message);
ic->spawnid = spawn_id;
@@ -3980,10 +3980,11 @@ EQApplicationPacket* Titanium::InterruptSpell(uint32_t message, uint32_t spawn_i
return outapp;
}
EQApplicationPacket* Titanium::InterruptSpellOther(Mob* sender, uint32_t message, uint32_t spawn_id, const char* name,
std::unique_ptr<EQApplicationPacket> Titanium::InterruptSpellOther(Mob* sender, uint32_t message, uint32_t spawn_id,
const char* name,
const char* spell_link) const
{
auto outapp = new EQApplicationPacket(OP_InterruptCast, sizeof(InterruptCast_Struct) + strlen(name) + 1);
auto outapp = std::make_unique<EQApplicationPacket>(OP_InterruptCast, sizeof(InterruptCast_Struct) + strlen(name) + 1);
auto ic = reinterpret_cast<InterruptCast_Struct*>(outapp->pBuffer);
ic->messageid = ResolveID(message);
ic->spawnid = spawn_id;
@@ -4018,7 +4019,8 @@ void Titanium::ResolveArguments(uint32_t id, std::array<const char*, 9>& args) c
} // namespace Message
namespace Buff {
EQApplicationPacket* Titanium::MakeLegacyBuffsPacket(Mob* mob, int32_t timer, bool for_target, bool clear_buffs) const
std::unique_ptr<EQApplicationPacket> Titanium::MakeLegacyBuffsPacket(Mob* mob, int32_t timer, bool for_target,
bool clear_buffs) const
{
uint32 count = 0;
uint32 buff_count;
@@ -4040,15 +4042,10 @@ EQApplicationPacket* Titanium::MakeLegacyBuffsPacket(Mob* mob, int32_t timer, bo
}
}
EQApplicationPacket* outapp = nullptr;
//Create it for a targeting window, else create it for a create buff packet.
if(for_target) {
outapp = new EQApplicationPacket(OP_RefreshTargetBuffs, sizeof(BuffIcon_Struct) + sizeof(BuffIconEntry_Struct) * count);
}
else {
outapp = new EQApplicationPacket(OP_RefreshBuffs, sizeof(BuffIcon_Struct) + sizeof(BuffIconEntry_Struct) * count);
}
auto outapp = std::make_unique<EQApplicationPacket>(for_target ? OP_RefreshTargetBuffs : OP_RefreshBuffs,
sizeof(BuffIcon_Struct) + sizeof(BuffIconEntry_Struct) * count);
BuffIcon_Struct *buff = (BuffIcon_Struct*)outapp->pBuffer;
buff->entity_id = mob->GetID();
buff->count = count;
@@ -4078,17 +4075,18 @@ EQApplicationPacket* Titanium::MakeLegacyBuffsPacket(Mob* mob, int32_t timer, bo
return outapp;
}
EQApplicationPacket* Titanium::BuffDefinition(Mob* mob, const Buffs_Struct& buff, int slot, bool fade) const
std::unique_ptr<EQApplicationPacket> Titanium::BuffDefinition(Mob* mob, const Buffs_Struct& buff, int slot,
bool fade) const
{
return nullptr;
}
EQApplicationPacket* Titanium::RefreshBuffs(EmuOpcode opcode, Mob* mob, int32_t timer, bool remove,
std::unique_ptr<EQApplicationPacket> Titanium::RefreshBuffs(EmuOpcode opcode, Mob* mob, int32_t timer, bool remove,
bool buff_timers_suspended, const std::vector<uint32_t>& slots) const
{
return nullptr;
}
void Titanium::SetRefreshType(EQApplicationPacket* packet, Mob* source, Client* target) const {}
void Titanium::SetRefreshType(const std::unique_ptr<EQApplicationPacket>& packet, Mob* source, Client* target) const {}
} // namespace Buff
+14 -8
View File
@@ -60,11 +60,14 @@ public:
Titanium() = default;
~Titanium() override = default;
[[nodiscard]] EQApplicationPacket* Simple(uint32_t color, uint32_t id) const override;
[[nodiscard]] EQApplicationPacket* Formatted(uint32_t color, uint32_t id, const std::array<const char*, 9>& args) const override;
std::unique_ptr<EQApplicationPacket> Simple(uint32_t color, uint32_t id) const override;
std::unique_ptr<EQApplicationPacket> Formatted(uint32_t color, uint32_t id,
const std::array<const char*, 9>& args) const override;
EQApplicationPacket* InterruptSpell(uint32_t message, uint32_t spawn_id, const char* spell_link) const override;
EQApplicationPacket* InterruptSpellOther(Mob* sender, uint32_t message, uint32_t spawn_id, const char* name,
std::unique_ptr<EQApplicationPacket> InterruptSpell(uint32_t message, uint32_t spawn_id,
const char* spell_link) const override;
std::unique_ptr<EQApplicationPacket> InterruptSpellOther(Mob* sender, uint32_t message, uint32_t spawn_id,
const char* name,
const char* spell_link) const override;
protected:
@@ -82,11 +85,14 @@ public:
Titanium() = default;
~Titanium() override = default;
EQApplicationPacket* MakeLegacyBuffsPacket(Mob* mob, int32_t timer, bool for_target, bool clear_buffs) const override;
std::unique_ptr<EQApplicationPacket> MakeLegacyBuffsPacket(Mob* mob, int32_t timer, bool for_target,
bool clear_buffs) const override;
EQApplicationPacket* BuffDefinition(Mob* mob, const Buffs_Struct& buff, int slot, bool fade) const override;
EQApplicationPacket* RefreshBuffs(EmuOpcode opcode, Mob* mob, int32_t timer, bool remove, bool buff_timers_suspended, const std::vector<uint32_t>& slots) const override;
void SetRefreshType(EQApplicationPacket* packet, Mob* source, Client* target) const override;
std::unique_ptr<EQApplicationPacket>
BuffDefinition(Mob* mob, const Buffs_Struct& buff, int slot, bool fade) const override;
std::unique_ptr<EQApplicationPacket> RefreshBuffs(EmuOpcode opcode, Mob* mob, int32_t timer, bool remove,
bool buff_timers_suspended, const std::vector<uint32_t>& slots) const override;
void SetRefreshType(const std::unique_ptr<EQApplicationPacket>& packet, Mob* source, Client* target) const override;
};
} // namespace Buff
+17 -13
View File
@@ -5550,7 +5550,8 @@ void TOB::ResolveArguments(uint32_t id, std::array<const char*, 9>& args) const
}
}
EQApplicationPacket* TOB::Formatted(uint32_t color, uint32_t id, const std::array<const char*, 9>& args) const
std::unique_ptr<EQApplicationPacket> TOB::Formatted(uint32_t color, uint32_t id,
const std::array<const char*, 9>& args) const
{
uint32_t string_id = ResolveID(id);
if (string_id > 0) {
@@ -5576,15 +5577,16 @@ EQApplicationPacket* TOB::Formatted(uint32_t color, uint32_t id, const std::arra
buffer.WriteUInt32(0);
}
return new EQApplicationPacket(OP_FormattedMessage, std::move(buffer));
return std::make_unique<EQApplicationPacket>(OP_FormattedMessage, std::move(buffer));
}
return nullptr;
}
EQApplicationPacket* TOB::InterruptSpell(uint32_t message, uint32_t spawn_id, const char* spell_link) const
std::unique_ptr<EQApplicationPacket> TOB::InterruptSpell(uint32_t message, uint32_t spawn_id,
const char* spell_link) const
{
auto outapp = new EQApplicationPacket(OP_InterruptCast, sizeof(InterruptCast_Struct) + strlen(spell_link) + 1);
auto outapp = std::make_unique<EQApplicationPacket>(OP_InterruptCast, sizeof(InterruptCast_Struct) + strlen(spell_link) + 1);
auto ic = reinterpret_cast<InterruptCast_Struct*>(outapp->pBuffer);
ic->messageid = ResolveID(message);
ic->spawnid = spawn_id;
@@ -5594,10 +5596,11 @@ EQApplicationPacket* TOB::InterruptSpell(uint32_t message, uint32_t spawn_id, co
return outapp;
}
EQApplicationPacket* TOB::InterruptSpellOther(Mob* sender, uint32_t message, uint32_t spawn_id, const char* name,
std::unique_ptr<EQApplicationPacket> TOB::InterruptSpellOther(Mob* sender, uint32_t message, uint32_t spawn_id,
const char* name,
const char* spell_link) const
{
auto outapp = new EQApplicationPacket(OP_InterruptCast,
auto outapp = std::make_unique<EQApplicationPacket>(OP_InterruptCast,
sizeof(InterruptCast_Struct) + strlen(name) + strlen(spell_link) + 2);
auto ic = reinterpret_cast<InterruptCast_Struct*>(outapp->pBuffer);
ic->messageid = ResolveID(message);
@@ -5610,12 +5613,12 @@ EQApplicationPacket* TOB::InterruptSpellOther(Mob* sender, uint32_t message, uin
} // namespace Message
namespace Buff {
std::unique_ptr<EQApplicationPacket> TOB::MakeLegacyBuffsPacket(Mob* mob, int32_t timer, bool for_target,
bool clear_buffs) const { return nullptr; }
EQApplicationPacket* TOB::MakeLegacyBuffsPacket(Mob* mob, int32_t timer, bool for_target, bool clear_buffs) const { return nullptr; }
EQApplicationPacket* TOB::BuffDefinition(Mob* mob, const Buffs_Struct& buff, int slot, bool fade) const
std::unique_ptr<EQApplicationPacket> TOB::BuffDefinition(Mob* mob, const Buffs_Struct& buff, int slot, bool fade) const
{
auto packet = new EQApplicationPacket(OP_BuffDefinition, sizeof(::TOB::structs::EQAffectPacket_Struct));
auto packet = std::make_unique<EQApplicationPacket>(OP_BuffDefinition, sizeof(::TOB::structs::EQAffectPacket_Struct));
auto affect = reinterpret_cast<::TOB::structs::EQAffectPacket_Struct*>(packet->pBuffer);
// base packet
@@ -5665,7 +5668,8 @@ EQApplicationPacket* TOB::BuffDefinition(Mob* mob, const Buffs_Struct& buff, int
return packet;
}
EQApplicationPacket* TOB::RefreshBuffs(EmuOpcode opcode, Mob* mob, int32_t timer, bool remove, bool buff_timers_suspended, const std::vector<uint32_t>& slots) const
std::unique_ptr<EQApplicationPacket> TOB::RefreshBuffs(EmuOpcode opcode, Mob* mob, int32_t timer, bool remove,
bool buff_timers_suspended, const std::vector<uint32_t>& slots) const
{
Buffs_Struct* buffs = mob->GetBuffs();
@@ -5704,11 +5708,11 @@ EQApplicationPacket* TOB::RefreshBuffs(EmuOpcode opcode, Mob* mob, int32_t timer
buffer.WriteUInt8(opcode == OP_RefreshPetBuffs ? 2 : 0);
buffer.WriteUInt8(buff_timers_suspended ? 1 : 0); // bBuffTimersOnHold
return new EQApplicationPacket(opcode, std::move(buffer));
return std::make_unique<EQApplicationPacket>(opcode, std::move(buffer));
}
// 0 = self buff window, 1 = self target window, 2 = pet buff or target window, 4 = group, 5 = PC, 7 = NPC
void TOB::SetRefreshType(EQApplicationPacket* packet, Mob* source, Client* target) const
void TOB::SetRefreshType(const std::unique_ptr<EQApplicationPacket>& packet, Mob* source, Client* target) const
{
unsigned char* type = &packet->pBuffer[packet->size - 2];
+13 -7
View File
@@ -42,10 +42,13 @@ public:
TOB() = default;
~TOB() override = default;
[[nodiscard]] EQApplicationPacket* Formatted(uint32_t color, uint32_t id, const std::array<const char*, 9>& args) const override;
std::unique_ptr<EQApplicationPacket> Formatted(uint32_t color, uint32_t id,
const std::array<const char*, 9>& args) const override;
EQApplicationPacket* InterruptSpell(uint32_t message, uint32_t spawn_id, const char* spell_link) const override;
EQApplicationPacket* InterruptSpellOther(Mob* sender, uint32_t message, uint32_t spawn_id, const char* name, const char* spell_link) const override;
std::unique_ptr<EQApplicationPacket> InterruptSpell(uint32_t message, uint32_t spawn_id,
const char* spell_link) const override;
std::unique_ptr<EQApplicationPacket> InterruptSpellOther(Mob* sender, uint32_t message, uint32_t spawn_id,
const char* name, const char* spell_link) const override;
protected:
[[nodiscard]] uint32_t ResolveID(uint32_t id) const override;
@@ -62,11 +65,14 @@ public:
TOB() = default;
~TOB() override = default;
EQApplicationPacket* MakeLegacyBuffsPacket(Mob* mob, int32_t timer, bool for_target, bool clear_buffs) const override;
std::unique_ptr<EQApplicationPacket> MakeLegacyBuffsPacket(Mob* mob, int32_t timer, bool for_target,
bool clear_buffs) const override;
EQApplicationPacket* BuffDefinition(Mob* mob, const Buffs_Struct& buff, int slot, bool fade) const override;
EQApplicationPacket* RefreshBuffs(EmuOpcode opcode, Mob* mob, int32_t timer, bool remove, bool buff_timers_suspended, const std::vector<uint32_t>& slots) const override;
void SetRefreshType(EQApplicationPacket* packet, Mob* source, Client* target) const override;
std::unique_ptr<EQApplicationPacket>
BuffDefinition(Mob* mob, const Buffs_Struct& buff, int slot, bool fade) const override;
std::unique_ptr<EQApplicationPacket> RefreshBuffs(EmuOpcode opcode, Mob* mob, int32_t timer, bool remove,
bool buff_timers_suspended, const std::vector<uint32_t>& slots) const override;
void SetRefreshType(const std::unique_ptr<EQApplicationPacket>& packet, Mob* source, Client* target) const override;
};
} // namespace Buff