initial tie in of makebuffpacket to logic (still need to do buff definition work)

This commit is contained in:
dannuic
2026-04-26 21:42:26 -06:00
parent 301eed2168
commit 05cb1921e8
15 changed files with 261 additions and 275 deletions
+4 -2
View File
@@ -24,14 +24,16 @@ public:
IBuff() = default;
virtual ~IBuff() = default;
virtual std::unique_ptr<EQApplicationPacket> MakeLegacyBuffsPacket(Mob* mob, int32_t timer, bool for_target,
// TODO: I think all of the legacy stuff can just be rolled into regular buff functions and the call sites modified
virtual std::unique_ptr<EQApplicationPacket> MakeLegacyBuffsPacket(Mob* mob, bool for_target,
bool clear_buffs) const = 0;
virtual std::unique_ptr<EQApplicationPacket> LegacyBuffDefinition(Mob* mob, Buffs_Struct& buff, int slot) const = 0; // TODO: add the buffs definition packet
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;
virtual void SetRefreshType(std::unique_ptr<EQApplicationPacket>& packet, Mob* source, Client* target) const = 0;
};
} // namespace Buff
+65
View File
@@ -35,6 +35,8 @@
#include <iostream>
#include <sstream>
#include "zone/mob.h"
namespace SoD
{
@@ -4285,3 +4287,66 @@ namespace SoD
return index; // as long as we guard against bad slots server side, we should be fine
}
} /*SoD*/
namespace Buff {
std::unique_ptr<EQApplicationPacket> SoD::MakeLegacyBuffsPacket(Mob* mob, bool for_target, bool clear_buffs) const
{
// SoD only supports target refresh, not self refresh packets
if (for_target) {
uint32 count = 0;
uint32 buff_count;
// for self we want all buffs, for target, we want to skip song window buffs
// since NPCs and pets don't have a song window, we still see it for them :P
if (for_target) {
buff_count = (clear_buffs) ? 0 : mob->GetMaxBuffSlots();
}
else {
buff_count = mob->GetMaxTotalSlots();
}
Buffs_Struct* buffs = mob->GetBuffs();
for(int i = 0; i < buff_count; ++i) {
if (buffs[i].spellid > 1) {
++count;
}
}
auto outapp = std::make_unique<EQApplicationPacket>(OP_RefreshTargetBuffs,
sizeof(BuffIcon_Struct) + sizeof(BuffIconEntry_Struct) * count);
BuffIcon_Struct *buff = (BuffIcon_Struct*)outapp->pBuffer;
buff->entity_id = mob->GetID();
buff->count = count;
buff->all_buffs = 1;
buff->tic_timer = mob->GetRemainingTicTime();
// there are more types, the client doesn't seem to really care though. The others are also currently hard to fill in here ...
// (see comment in common/eq_packet_structs.h)
if (for_target)
buff->type = mob->IsClient() ? 5 : 7;
else
buff->type = 0;
buff->name_lengths = 0; // hacky shit
uint32 index = 0;
for(int i = 0; i < buff_count; ++i) {
if (buffs[i].spellid > 1) {
buff->entries[index].buff_slot = i;
buff->entries[index].spell_id = buffs[i].spellid;
buff->entries[index].tics_remaining = buffs[i].ticsremaining;
buff->entries[index].num_hits = buffs[i].hit_number;
strn0cpy(buff->entries[index].caster, buffs[i].caster_name, 64);
buff->name_lengths += strlen(buff->entries[index].caster);
++index;
}
}
return outapp;
}
return nullptr;
}
} // namespace Buff
+3
View File
@@ -68,6 +68,9 @@ class SoD : public SoF
public:
SoD() = default;
~SoD() override = default;
std::unique_ptr<EQApplicationPacket> MakeLegacyBuffsPacket(Mob* mob, bool for_target,
bool clear_buffs) const override;
};
} // namespace Buff
+29 -47
View File
@@ -4019,58 +4019,40 @@ void Titanium::ResolveArguments(uint32_t id, std::array<const char*, 9>& args) c
} // namespace Message
namespace Buff {
std::unique_ptr<EQApplicationPacket> Titanium::MakeLegacyBuffsPacket(Mob* mob, int32_t timer, bool for_target,
bool clear_buffs) const
std::unique_ptr<EQApplicationPacket> Titanium::MakeLegacyBuffsPacket(Mob* mob, bool for_target, bool clear_buffs) const
{
uint32 count = 0;
uint32 buff_count;
return nullptr;
}
// for self we want all buffs, for target, we want to skip song window buffs
// since NPCs and pets don't have a song window, we still see it for them :P
if (for_target) {
buff_count = (clear_buffs) ? 0 : mob->GetMaxBuffSlots();
}
else {
buff_count = mob->GetMaxTotalSlots();
}
std::unique_ptr<EQApplicationPacket> Titanium::LegacyBuffDefinition(Mob* mob, Buffs_Struct& buff, int slot) const
{
auto outapp = std::make_unique<EQApplicationPacket>(OP_BuffDefinition, sizeof(SpellBuffPacket_Struct));
SpellBuffPacket_Struct* sbf = (SpellBuffPacket_Struct*) outapp->pBuffer;
Buffs_Struct* buffs = mob->GetBuffs();
sbf->entityid = mob->GetID();
for(int i = 0; i < buff_count; ++i) {
if (buffs[i].spellid > 1) {
++count;
}
}
sbf->buff.effect_type = 2;
//Create it for a targeting window, else create it for a create buff packet.
auto outapp = std::make_unique<EQApplicationPacket>(for_target ? OP_RefreshTargetBuffs : OP_RefreshBuffs,
sizeof(BuffIcon_Struct) + sizeof(BuffIconEntry_Struct) * count);
sbf->buff.level = buff.casterlevel > 0 ? buff.casterlevel : mob->GetLevel();
sbf->buff.bard_modifier = buff.instrument_mod;
sbf->buff.spellid = buff.spellid;
sbf->buff.duration = buff.ticsremaining;
if (buff.dot_rune)
sbf->buff.counters = buff.dot_rune;
else if (buff.magic_rune)
sbf->buff.counters = buff.magic_rune;
else if (buff.melee_rune)
sbf->buff.counters = buff.melee_rune;
else if (buff.counters)
sbf->buff.counters = buff.counters;
sbf->buff.player_id = buff.casterid;
sbf->buff.num_hits = buff.hit_number;
sbf->buff.y = buff.caston_y;
sbf->buff.x = buff.caston_x;
sbf->buff.z = buff.caston_z;
BuffIcon_Struct *buff = (BuffIcon_Struct*)outapp->pBuffer;
buff->entity_id = mob->GetID();
buff->count = count;
buff->all_buffs = 1;
buff->tic_timer = timer;
// there are more types, the client doesn't seem to really care though. The others are also currently hard to fill in here ...
// (see comment in common/eq_packet_structs.h)
if (for_target)
buff->type = mob->IsClient() ? 5 : 7;
else
buff->type = 0;
buff->name_lengths = 0; // hacky shit
uint32 index = 0;
for(int i = 0; i < buff_count; ++i) {
if (buffs[i].spellid > 1) {
buff->entries[index].buff_slot = i;
buff->entries[index].spell_id = buffs[i].spellid;
buff->entries[index].tics_remaining = buffs[i].ticsremaining;
buff->entries[index].num_hits = buffs[i].hit_number;
strn0cpy(buff->entries[index].caster, buffs[i].caster_name, 64);
buff->name_lengths += strlen(buff->entries[index].caster);
++index;
}
}
sbf->slotid = slot;
sbf->bufffade = 0;
return outapp;
}
@@ -4087,6 +4069,6 @@ std::unique_ptr<EQApplicationPacket> Titanium::RefreshBuffs(EmuOpcode opcode, Mo
return nullptr;
}
void Titanium::SetRefreshType(const std::unique_ptr<EQApplicationPacket>& packet, Mob* source, Client* target) const {}
void Titanium::SetRefreshType(std::unique_ptr<EQApplicationPacket>& packet, Mob* source, Client* target) const {}
} // namespace Buff
+3 -2
View File
@@ -85,14 +85,15 @@ public:
Titanium() = default;
~Titanium() override = default;
std::unique_ptr<EQApplicationPacket> MakeLegacyBuffsPacket(Mob* mob, int32_t timer, bool for_target,
std::unique_ptr<EQApplicationPacket> MakeLegacyBuffsPacket(Mob* mob, bool for_target,
bool clear_buffs) const override;
std::unique_ptr<EQApplicationPacket> LegacyBuffDefinition(Mob* mob, Buffs_Struct& buff, int slot) 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;
void SetRefreshType(std::unique_ptr<EQApplicationPacket>& packet, Mob* source, Client* target) const override;
};
} // namespace Buff
+2 -3
View File
@@ -5613,8 +5613,7 @@ std::unique_ptr<EQApplicationPacket> TOB::InterruptSpellOther(Mob* sender, uint3
} // namespace Message
namespace Buff {
std::unique_ptr<EQApplicationPacket> TOB::MakeLegacyBuffsPacket(Mob* mob, int32_t timer, bool for_target,
bool clear_buffs) const { return nullptr; }
// std::unique_ptr<EQApplicationPacket> TOB::MakeLegacyBuffsPacket(Mob* mob, bool for_target, bool clear_buffs) const { return nullptr; }
std::unique_ptr<EQApplicationPacket> TOB::BuffDefinition(Mob* mob, const Buffs_Struct& buff, int slot, bool fade) const
{
@@ -5712,7 +5711,7 @@ std::unique_ptr<EQApplicationPacket> TOB::RefreshBuffs(EmuOpcode opcode, Mob* mo
}
// 0 = self buff window, 1 = self target window, 2 = pet buff or target window, 4 = group, 5 = PC, 7 = NPC
void TOB::SetRefreshType(const std::unique_ptr<EQApplicationPacket>& packet, Mob* source, Client* target) const
void TOB::SetRefreshType(std::unique_ptr<EQApplicationPacket>& packet, Mob* source, Client* target) const
{
unsigned char* type = &packet->pBuffer[packet->size - 2];
+3 -3
View File
@@ -65,14 +65,14 @@ public:
TOB() = default;
~TOB() override = default;
std::unique_ptr<EQApplicationPacket> MakeLegacyBuffsPacket(Mob* mob, int32_t timer, bool for_target,
bool clear_buffs) const override;
// std::unique_ptr<EQApplicationPacket> MakeLegacyBuffsPacket(Mob* mob, bool for_target,
// bool clear_buffs) 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;
void SetRefreshType(std::unique_ptr<EQApplicationPacket>& packet, Mob* source, Client* target) const override;
};
} // namespace Buff
+63
View File
@@ -38,6 +38,8 @@
#include <iostream>
#include <sstream>
#include "zone/mob.h"
namespace UF
{
@@ -5234,3 +5236,64 @@ namespace UF
return index; // as long as we guard against bad slots server side, we should be fine
}
} /*UF*/
namespace Buff {
std::unique_ptr<EQApplicationPacket> UF::MakeLegacyBuffsPacket(Mob* mob, bool for_target, bool clear_buffs) const
{
// UF introduced the self update buff packet
uint32 count = 0;
uint32 buff_count;
// for self we want all buffs, for target, we want to skip song window buffs
// since NPCs and pets don't have a song window, we still see it for them :P
if (for_target) {
buff_count = (clear_buffs) ? 0 : mob->GetMaxBuffSlots();
}
else {
buff_count = mob->GetMaxTotalSlots();
}
Buffs_Struct* buffs = mob->GetBuffs();
for(int i = 0; i < buff_count; ++i) {
if (buffs[i].spellid > 1) {
++count;
}
}
//Create it for a targeting window, else create it for a create buff packet.
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;
buff->all_buffs = 1;
buff->tic_timer = mob->GetRemainingTicTime();
// there are more types, the client doesn't seem to really care though. The others are also currently hard to fill in here ...
// (see comment in common/eq_packet_structs.h)
if (for_target)
buff->type = mob->IsClient() ? 5 : 7;
else
buff->type = 0;
buff->name_lengths = 0; // hacky shit
uint32 index = 0;
for(int i = 0; i < buff_count; ++i) {
if (buffs[i].spellid > 1) {
buff->entries[index].buff_slot = i;
buff->entries[index].spell_id = buffs[i].spellid;
buff->entries[index].tics_remaining = buffs[i].ticsremaining;
buff->entries[index].num_hits = buffs[i].hit_number;
strn0cpy(buff->entries[index].caster, buffs[i].caster_name, 64);
buff->name_lengths += strlen(buff->entries[index].caster);
++index;
}
}
return outapp;
}
} // namespace Buff
+3
View File
@@ -68,6 +68,9 @@ class UF : public SoD
public:
UF() = default;
~UF() override = default;
std::unique_ptr<EQApplicationPacket> MakeLegacyBuffsPacket(Mob* mob, bool for_target,
bool clear_buffs) const override;
};
} // namespace Buff