mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-06 04:42:28 +00:00
finished the implementation
This commit is contained in:
parent
d16c1b2483
commit
c384ef6215
@ -68,8 +68,7 @@ Below is a status list for the 450 opcodes we currently use on the server for th
|
||||
| `OP_BlockedBuffs` | 🟢 Verified | | |
|
||||
| `OP_BoardBoat` | 🟡 Unverified | | |
|
||||
| `OP_BookButton` | 🟡 Unverified | | |
|
||||
| `OP_BuffDefinition` | 🟡 Unverified | | |
|
||||
| `OP_RefreshBuffs` | 🟡 Unverified | | |
|
||||
| `OP_BuffDefinition` | 🟢 Verified | | |
|
||||
| `OP_BuffRemoveRequest` | 🟡 Unverified | | |
|
||||
| `OP_Bug` | 🟡 Unverified | | |
|
||||
| `OP_BuyerItems` | 🔴 Not-Set | | |
|
||||
@ -395,7 +394,6 @@ Below is a status list for the 450 opcodes we currently use on the server for th
|
||||
| `OP_OpenInventory` | 🔴 Not-Set | | |
|
||||
| `OP_OpenTributeMaster` | 🔴 Not-Set | | |
|
||||
| `OP_PDeletePetition` | 🔴 Not-Set | | |
|
||||
| `OP_RefreshPetBuffs` | 🔴 Not-Set | | |
|
||||
| `OP_PetCommands` | 🔴 Not-Set | | |
|
||||
| `OP_PetCommandState` | 🔴 Not-Set | | |
|
||||
| `OP_PetHoTT` | 🔴 Not-Set | | |
|
||||
@ -451,6 +449,9 @@ Below is a status list for the 450 opcodes we currently use on the server for th
|
||||
| `OP_RecipesFavorite` | 🟡 Unverified | | |
|
||||
| `OP_RecipesSearch` | 🟡 Unverified | | |
|
||||
| `OP_ReclaimCrystals` | 🔴 Not-Set | | |
|
||||
| `OP_RefreshBuffs` | 🟢 Verified | | |
|
||||
| `OP_RefreshPetBuffs` | 🟢 Verified | | |
|
||||
| `OP_RefreshTargetBuffs` | 🟢 Verified | | |
|
||||
| `OP_ReloadUI` | 🔴 Not-Set | | |
|
||||
| `OP_RemoveAllDoors` | 🟡 Unverified | | |
|
||||
| `OP_RemoveBlockedBuffs` | 🟢 Verified | | |
|
||||
@ -551,7 +552,6 @@ Below is a status list for the 450 opcodes we currently use on the server for th
|
||||
| `OP_Surname` | 🔴 Not-Set | | |
|
||||
| `OP_SwapSpell` | 🟢 Verified | | |
|
||||
| `OP_SystemFingerprint` | 🔴 Not-Set | | |
|
||||
| `OP_RefreshTargetBuffs` | 🔴 Not-Set | | |
|
||||
| `OP_TargetCommand` | 🟡 Unverified | | |
|
||||
| `OP_TargetHoTT` | 🔴 Not-Set | | |
|
||||
| `OP_TargetMouse` | 🟡 Unverified | | |
|
||||
|
||||
@ -6326,8 +6326,7 @@ void Client::SuspendMinion(int value)
|
||||
if(value >= 1)
|
||||
{
|
||||
CurrentPet->SetPetState(m_suspendedminion.Buffs, m_suspendedminion.Items);
|
||||
|
||||
CurrentPet->SendPetBuffsToClient();
|
||||
Buff::SendFullBuffRefresh(CurrentPet);
|
||||
}
|
||||
CurrentPet->CalcBonuses();
|
||||
|
||||
|
||||
@ -1268,11 +1268,6 @@ public:
|
||||
const std::string GetAutoLoginCharacterName();
|
||||
bool SetAutoLoginCharacterName(const std::string& character_name);
|
||||
|
||||
//This is used to later set the buff duration of the spell, in slot to duration.
|
||||
//Doesn't appear to work directly after the client recieves an action packet.
|
||||
void SendBuffDurationPacket(Buffs_Struct &buff, int slot);
|
||||
void SendBuffNumHitPacket(Buffs_Struct &buff, int slot);
|
||||
|
||||
void ProcessInspectRequest(Client* requestee, Client* requester);
|
||||
bool ClientFinishedLoading() { return (conn_state == ClientConnectFinished); }
|
||||
int FindSpellBookSlotBySpellID(int32 spellid);
|
||||
@ -1956,7 +1951,6 @@ public:
|
||||
protected:
|
||||
friend class Mob;
|
||||
void CalcEdibleBonuses(StatBonuses* newbon);
|
||||
void MakeBuffFadePacket(int32 spell_id, int slot_id, bool send_message = true);
|
||||
bool client_data_loaded;
|
||||
|
||||
|
||||
|
||||
@ -760,7 +760,7 @@ void Client::CompleteConnect()
|
||||
Mob* pet = GetPet();
|
||||
if (pet) {
|
||||
pet->SendWearChangeAndLighting(EQ::textures::LastTexture);
|
||||
pet->SendPetBuffsToClient();
|
||||
Buff::SendFullBuffRefresh(pet);
|
||||
}
|
||||
|
||||
if (GetGroup())
|
||||
|
||||
@ -295,6 +295,18 @@ inline void SendSingleBuffChange(Mob* sender, const Buffs_Struct& buff, int slot
|
||||
|
||||
ClientPatch::QueueClientsByTarget(sender, ackreq, false, ShouldSendTargetBuffs, mutate)(
|
||||
&IBuff::RefreshBuffs, GetComponent, OP_RefreshTargetBuffs, sender, remove, suspended, slots);
|
||||
|
||||
// the client doesn't automatically do this for some reason (RoF2? I think this is in TOB)
|
||||
// TODO: hook this up to QueueClients, or figure out if there's another missing packet to display the fade text
|
||||
if (remove && sender->IsClient())
|
||||
{
|
||||
const char *fadetext = spells[buff.spellid].spell_fades;
|
||||
auto outapp = std::make_unique<EQApplicationPacket>(OP_ColoredText, sizeof(ColoredText_Struct) + strlen(fadetext));
|
||||
ColoredText_Struct *bfm = (ColoredText_Struct *) outapp->pBuffer;
|
||||
bfm->color = Chat::Spells;
|
||||
memcpy(bfm->msg, fadetext, strlen(fadetext));
|
||||
sender->CastToClient()->QueuePacket(outapp.get());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Buff
|
||||
|
||||
@ -242,7 +242,7 @@ struct Buffs_Struct {
|
||||
int32 virus_spread_time; //time till next attempted viral spread
|
||||
bool persistant_buff;
|
||||
bool client; //True if the caster is a client
|
||||
bool UpdateClient;
|
||||
bool UpdateClient; // This is for legacy client support only. Newer clients take refresh packets for the entire buff list
|
||||
|
||||
// cereal
|
||||
template<class Archive>
|
||||
|
||||
@ -459,7 +459,6 @@ public:
|
||||
int AddBuff(Mob *caster, const int32 spell_id, int duration = 0, int32 level_override = -1, bool disable_buff_overwrite = false);
|
||||
int CanBuffStack(int32 spellid, uint8 caster_level, bool iFailIfOverwrite = false);
|
||||
int CalcBuffDuration(Mob *caster, Mob *target, int32 spell_id, int32 caster_level_override = -1);
|
||||
void SendPetBuffsToClient();
|
||||
virtual int GetCurrentBuffSlots() const { return 0; }
|
||||
virtual int GetCurrentSongSlots() const { return 0; }
|
||||
virtual int GetCurrentDiscSlots() const { return 0; }
|
||||
|
||||
@ -821,7 +821,7 @@ bool Mob::SpellEffect(Mob* caster, int32 spell_id, float partial, int level_over
|
||||
ps->command = 1;
|
||||
entity_list.QueueClients(this, app);
|
||||
safe_delete(app);
|
||||
SendPetBuffsToClient();
|
||||
Buff::SendFullBuffRefresh(this);
|
||||
SendAppearancePacket(AppearanceType::Pet, caster->GetID(), true, true);
|
||||
}
|
||||
|
||||
@ -3864,19 +3864,15 @@ void Mob::BuffProcess()
|
||||
}
|
||||
}
|
||||
|
||||
if(IsClient())
|
||||
{
|
||||
if(buffs[buffs_i].UpdateClient == true)
|
||||
{
|
||||
CastToClient()->SendBuffDurationPacket(buffs[buffs_i], buffs_i);
|
||||
// Hack to get UF to play nicer, RoF seems fine without it
|
||||
if (CastToClient()->ClientVersion() == EQ::versions::ClientVersion::UF && buffs[buffs_i].hit_number > 0)
|
||||
CastToClient()->SendBuffNumHitPacket(buffs[buffs_i], buffs_i);
|
||||
buffs[buffs_i].UpdateClient = false;
|
||||
}
|
||||
// this is for older clients. Newer clients will simply discard this packet
|
||||
if (IsClient() && buffs[buffs_i].UpdateClient == true) {
|
||||
Buff::SendSingleBuffChange(this, buffs[buffs_i], buffs_i);
|
||||
buffs[buffs_i].UpdateClient = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Buff::SendFullBuffRefresh(this);
|
||||
}
|
||||
|
||||
void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster)
|
||||
@ -4248,7 +4244,7 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses)
|
||||
return;
|
||||
|
||||
if (IsClient() && !CastToClient()->IsDead())
|
||||
CastToClient()->MakeBuffFadePacket(buffs[slot].spellid, slot);
|
||||
Buff::SendSingleBuffChange(this, buffs[slot], slot);
|
||||
|
||||
LogSpells("Fading buff [{}] from slot [{}]", buffs[slot].spellid, slot);
|
||||
|
||||
@ -7014,7 +7010,7 @@ void Mob::CheckNumHitsRemaining(NumHit type, int32 buff_slot, int32 spell_id)
|
||||
if (!TryFadeEffect(d))
|
||||
BuffFadeBySlot(d, true);
|
||||
} else if (IsClient()) { // still have numhits and client, update
|
||||
CastToClient()->SendBuffNumHitPacket(buffs[d], d);
|
||||
Buff::SendSingleBuffChange(this, buffs[d], d);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -7029,7 +7025,7 @@ void Mob::CheckNumHitsRemaining(NumHit type, int32 buff_slot, int32 spell_id)
|
||||
if (!TryFadeEffect(buff_slot))
|
||||
BuffFadeBySlot(buff_slot , true);
|
||||
} else if (IsClient()) { // still have numhits and client, update
|
||||
CastToClient()->SendBuffNumHitPacket(buffs[buff_slot], buff_slot);
|
||||
Buff::SendSingleBuffChange(this, buffs[buff_slot], buff_slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -7047,7 +7043,7 @@ void Mob::CheckNumHitsRemaining(NumHit type, int32 buff_slot, int32 spell_id)
|
||||
if (!TryFadeEffect(d))
|
||||
BuffFadeBySlot(d, true);
|
||||
} else if (IsClient()) { // still have numhits and client, update
|
||||
CastToClient()->SendBuffNumHitPacket(buffs[d], d);
|
||||
Buff::SendSingleBuffChange(this, buffs[d], d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
149
zone/spells.cpp
149
zone/spells.cpp
@ -2856,7 +2856,7 @@ bool Mob::SpellFinished(int32 spell_id, Mob *spell_target, CastingSlot slot, int
|
||||
if (IsClient() && IsEffectInSpell(spell_id, SpellEffect::BindSight)) {
|
||||
for (int i = 0; i < GetMaxTotalSlots(); i++) {
|
||||
if (buffs[i].spellid == spell_id) {
|
||||
CastToClient()->SendBuffNumHitPacket(buffs[i], i);//its hack, it works.
|
||||
Buff::SendSingleBuffChange(this, buffs[i], i);//its hack, it works.
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2864,7 +2864,7 @@ bool Mob::SpellFinished(int32 spell_id, Mob *spell_target, CastingSlot slot, int
|
||||
if (IsClient() && spells[spell_id].hit_number) {
|
||||
for (int i = 0; i < GetMaxTotalSlots(); i++) {
|
||||
if (buffs[i].spellid == spell_id && buffs[i].hit_number > 0) {
|
||||
CastToClient()->SendBuffNumHitPacket(buffs[i], i);
|
||||
Buff::SendSingleBuffChange(this, buffs[i], i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -5809,53 +5809,6 @@ void Mob::Mesmerize()
|
||||
StopNavigation();
|
||||
}
|
||||
|
||||
void Client::MakeBuffFadePacket(int32 spell_id, int slot_id, bool send_message)
|
||||
{
|
||||
EQApplicationPacket* outapp = nullptr;
|
||||
|
||||
outapp = new EQApplicationPacket(OP_BuffDefinition, sizeof(SpellBuffPacket_Struct));
|
||||
SpellBuffPacket_Struct* sbf = (SpellBuffPacket_Struct*) outapp->pBuffer;
|
||||
|
||||
sbf->entityid = GetID();
|
||||
// i dont know why but this works.. for now
|
||||
sbf->buff.effect_type = 2;
|
||||
// sbf->slot=m_pp.buffs[slot_id].slotid;
|
||||
// sbf->level=m_pp.buffs[slot_id].level;
|
||||
// sbf->effect=m_pp.buffs[slot_id].effect;
|
||||
sbf->buff.spellid = spell_id;
|
||||
sbf->slotid = slot_id;
|
||||
sbf->bufffade = 1;
|
||||
#if EQDEBUG >= 11
|
||||
printf("Sending SBF 1 from server:\n");
|
||||
DumpPacket(outapp);
|
||||
#endif
|
||||
QueuePacket(outapp);
|
||||
|
||||
/*
|
||||
sbf->effect=0;
|
||||
sbf->level=0;
|
||||
sbf->slot=0;
|
||||
*/
|
||||
sbf->buff.spellid = 0xffffffff;
|
||||
#if EQDEBUG >= 11
|
||||
printf("Sending SBF 2 from server:\n");
|
||||
DumpPacket(outapp);
|
||||
#endif
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
|
||||
if(send_message)
|
||||
{
|
||||
const char *fadetext = spells[spell_id].spell_fades;
|
||||
outapp = new EQApplicationPacket(OP_ColoredText, sizeof(ColoredText_Struct) + strlen(fadetext));
|
||||
ColoredText_Struct *bfm = (ColoredText_Struct *) outapp->pBuffer;
|
||||
bfm->color = Chat::Spells;
|
||||
memcpy(bfm->msg, fadetext, strlen(fadetext));
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
}
|
||||
|
||||
void Client::MemSpell(int32 spell_id, int slot, bool update_client)
|
||||
{
|
||||
if (slot >= EQ::spells::SPELL_GEM_COUNT || slot < 0) {
|
||||
@ -6501,99 +6454,6 @@ int Mob::GetCasterLevel(int32 spell_id) {
|
||||
return std::max(1, level);
|
||||
}
|
||||
|
||||
//This member function sets the buff duration on the client
|
||||
//however it does not work if sent quickly after an action packets, which is what one might perfer to do
|
||||
//Thus I use this in the buff process to update the correct duration once after casting
|
||||
//this allows AAs and focus effects that increase buff duration to work correctly, but could probably
|
||||
//be used for other things as well
|
||||
void Client::SendBuffDurationPacket(Buffs_Struct &buff, int slot)
|
||||
{
|
||||
EQApplicationPacket* outapp = nullptr;
|
||||
outapp = new EQApplicationPacket(OP_BuffDefinition, sizeof(SpellBuffPacket_Struct));
|
||||
SpellBuffPacket_Struct* sbf = (SpellBuffPacket_Struct*) outapp->pBuffer;
|
||||
|
||||
sbf->entityid = GetID();
|
||||
|
||||
sbf->buff.effect_type = 2;
|
||||
|
||||
sbf->buff.level = buff.casterlevel > 0 ? buff.casterlevel : 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;
|
||||
|
||||
sbf->slotid = slot;
|
||||
sbf->bufffade = 0;
|
||||
FastQueuePacket(&outapp);
|
||||
}
|
||||
|
||||
void Client::SendBuffNumHitPacket(Buffs_Struct &buff, int slot)
|
||||
{
|
||||
// UF+ use this packet
|
||||
if (ClientVersion() < EQ::versions::ClientVersion::UF)
|
||||
return;
|
||||
EQApplicationPacket *outapp = nullptr;
|
||||
outapp = new EQApplicationPacket(OP_RefreshBuffs, sizeof(BuffIcon_Struct) + sizeof(BuffIconEntry_Struct));
|
||||
BuffIcon_Struct *bi = (BuffIcon_Struct *)outapp->pBuffer;
|
||||
bi->entity_id = GetID();
|
||||
bi->count = 1;
|
||||
bi->all_buffs = 0;
|
||||
bi->tic_timer = tic_timer.GetRemainingTime();
|
||||
|
||||
bi->entries[0].buff_slot = slot;
|
||||
bi->entries[0].spell_id = buff.spellid;
|
||||
bi->entries[0].tics_remaining = buff.ticsremaining;
|
||||
bi->entries[0].num_hits = buff.hit_number;
|
||||
strn0cpy(bi->entries[0].caster, buff.caster_name, 64);
|
||||
bi->name_lengths = strlen(bi->entries[0].caster);
|
||||
FastQueuePacket(&outapp);
|
||||
}
|
||||
|
||||
void Mob::SendPetBuffsToClient()
|
||||
{
|
||||
// Don't really need this check, as it should be checked before this method is called, but it doesn't hurt
|
||||
// too much to check again.
|
||||
if(!(GetOwner() && GetOwner()->IsClient()))
|
||||
return;
|
||||
|
||||
int PetBuffCount = 0;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_RefreshPetBuffs, sizeof(PetBuff_Struct));
|
||||
PetBuff_Struct* pbs=(PetBuff_Struct*)outapp->pBuffer;
|
||||
memset(outapp->pBuffer,0,outapp->size);
|
||||
pbs->petid=GetID();
|
||||
|
||||
int MaxSlots = GetMaxTotalSlots();
|
||||
|
||||
if(MaxSlots > PET_BUFF_COUNT)
|
||||
MaxSlots = PET_BUFF_COUNT;
|
||||
|
||||
for(int buffslot = 0; buffslot < MaxSlots; buffslot++)
|
||||
{
|
||||
if (IsValidSpell(buffs[buffslot].spellid)) {
|
||||
pbs->spellid[buffslot] = buffs[buffslot].spellid;
|
||||
pbs->ticsremaining[buffslot] = buffs[buffslot].ticsremaining;
|
||||
PetBuffCount++;
|
||||
}
|
||||
}
|
||||
|
||||
pbs->buffcount=PetBuffCount;
|
||||
GetOwner()->CastToClient()->QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
void Mob::BuffModifyDurationBySpellID(int32 spell_id, int32 newDuration)
|
||||
{
|
||||
int buff_count = GetMaxTotalSlots();
|
||||
@ -6602,10 +6462,7 @@ void Mob::BuffModifyDurationBySpellID(int32 spell_id, int32 newDuration)
|
||||
if (buffs[i].spellid == spell_id)
|
||||
{
|
||||
buffs[i].ticsremaining = newDuration;
|
||||
if(IsClient())
|
||||
{
|
||||
CastToClient()->SendBuffDurationPacket(buffs[i], i);
|
||||
}
|
||||
Buff::SendSingleBuffChange(this, buffs[i], i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user