Fix up SpellBuff struct

Please report any bugs you find. There shouldn't be unless I messed up the struct
for a client I didn't throughly test for
This commit is contained in:
Michael Cook (mackal)
2016-07-25 16:22:48 -04:00
parent a7fd9312d0
commit bda4fcfb26
22 changed files with 350 additions and 460 deletions
+1 -1
View File
@@ -918,7 +918,7 @@ public:
//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);
void SendBuffDurationPacket(Buffs_Struct &buff, int slot);
void SendBuffNumHitPacket(Buffs_Struct &buff, int slot);
void ProcessInspectRequest(Client* requestee, Client* requester);
+10 -8
View File
@@ -1463,22 +1463,24 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
if (buffs[i].spellid != SPELL_UNKNOWN) {
m_pp.buffs[i].spellid = buffs[i].spellid;
m_pp.buffs[i].bard_modifier = buffs[i].instrument_mod;
m_pp.buffs[i].slotid = 2;
m_pp.buffs[i].effect_type = 2;
m_pp.buffs[i].player_id = 0x2211;
m_pp.buffs[i].level = buffs[i].casterlevel;
m_pp.buffs[i].effect = 0;
m_pp.buffs[i].unknown003 = 0;
m_pp.buffs[i].duration = buffs[i].ticsremaining;
m_pp.buffs[i].counters = buffs[i].counters;
m_pp.buffs[i].num_hits = buffs[i].numhits;
}
else {
m_pp.buffs[i].spellid = SPELLBOOK_UNKNOWN;
m_pp.buffs[i].bard_modifier = 10;
m_pp.buffs[i].slotid = 0;
m_pp.buffs[i].effect_type = 0;
m_pp.buffs[i].player_id = 0;
m_pp.buffs[i].level = 0;
m_pp.buffs[i].effect = 0;
m_pp.buffs[i].unknown003 = 0;
m_pp.buffs[i].duration = 0;
m_pp.buffs[i].counters = 0;
m_pp.buffs[i].num_hits = 0;
}
}
}
@@ -3833,15 +3835,15 @@ void Client::Handle_OP_BoardBoat(const EQApplicationPacket *app)
void Client::Handle_OP_Buff(const EQApplicationPacket *app)
{
if (app->size != sizeof(SpellBuffFade_Struct))
if (app->size != sizeof(SpellBuffPacket_Struct))
{
Log.Out(Logs::General, Logs::Error, "Size mismatch in OP_Buff. expected %i got %i", sizeof(SpellBuffFade_Struct), app->size);
Log.Out(Logs::General, Logs::Error, "Size mismatch in OP_Buff. expected %i got %i", sizeof(SpellBuffPacket_Struct), app->size);
DumpPacket(app);
return;
}
SpellBuffFade_Struct* sbf = (SpellBuffFade_Struct*)app->pBuffer;
uint32 spid = sbf->spellid;
SpellBuffPacket_Struct* sbf = (SpellBuffPacket_Struct*)app->pBuffer;
uint32 spid = sbf->buff.spellid;
Log.Out(Logs::Detail, Logs::Spells, "Client requested that buff with spell id %d be canceled.", spid);
//something about IsDetrimentalSpell() crashes this portion of code..
+7 -7
View File
@@ -579,10 +579,10 @@ void NPC::GetPetState(SpellBuff_Struct *pet_buffs, uint32 *items, char *name) {
for (int i=0; i < GetPetMaxTotalSlots(); i++) {
if (buffs[i].spellid != SPELL_UNKNOWN) {
pet_buffs[i].spellid = buffs[i].spellid;
pet_buffs[i].slotid = i+1;
pet_buffs[i].effect_type = i+1;
pet_buffs[i].duration = buffs[i].ticsremaining;
pet_buffs[i].level = buffs[i].casterlevel;
pet_buffs[i].effect = 10;
pet_buffs[i].bard_modifier = 10;
pet_buffs[i].counters = buffs[i].counters;
pet_buffs[i].bard_modifier = buffs[i].instrument_mod;
}
@@ -590,7 +590,7 @@ void NPC::GetPetState(SpellBuff_Struct *pet_buffs, uint32 *items, char *name) {
pet_buffs[i].spellid = SPELL_UNKNOWN;
pet_buffs[i].duration = 0;
pet_buffs[i].level = 0;
pet_buffs[i].effect = 0;
pet_buffs[i].bard_modifier = 10;
pet_buffs[i].counters = 0;
}
}
@@ -623,10 +623,10 @@ void NPC::SetPetState(SpellBuff_Struct *pet_buffs, uint32 *items) {
else {
buffs[i].spellid = SPELL_UNKNOWN;
pet_buffs[i].spellid = 0xFFFFFFFF;
pet_buffs[i].slotid = 0;
pet_buffs[i].effect_type = 0;
pet_buffs[i].level = 0;
pet_buffs[i].duration = 0;
pet_buffs[i].effect = 0;
pet_buffs[i].bard_modifier = 0;
}
}
for (int j1=0; j1 < GetPetMaxTotalSlots(); j1++) {
@@ -648,10 +648,10 @@ void NPC::SetPetState(SpellBuff_Struct *pet_buffs, uint32 *items) {
case SE_Illusion:
buffs[j1].spellid = SPELL_UNKNOWN;
pet_buffs[j1].spellid = SPELLBOOK_UNKNOWN;
pet_buffs[j1].slotid = 0;
pet_buffs[j1].effect_type = 0;
pet_buffs[j1].level = 0;
pet_buffs[j1].duration = 0;
pet_buffs[j1].effect = 0;
pet_buffs[j1].bard_modifier = 0;
x1 = EFFECT_COUNT;
break;
// We can't send appearance packets yet, put down at CompleteConnect
+1 -1
View File
@@ -3413,7 +3413,7 @@ void Mob::BuffProcess()
{
if(buffs[buffs_i].UpdateClient == true)
{
CastToClient()->SendBuffDurationPacket(buffs[buffs_i]);
CastToClient()->SendBuffDurationPacket(buffs[buffs_i], buffs_i);
// Hack to get UF to play nicer, RoF seems fine without it
if (CastToClient()->ClientVersion() == EQEmu::versions::ClientVersion::UF && buffs[buffs_i].numhits > 0)
CastToClient()->SendBuffNumHitPacket(buffs[buffs_i], buffs_i);
+30 -94
View File
@@ -4797,17 +4797,17 @@ void Client::MakeBuffFadePacket(uint16 spell_id, int slot_id, bool send_message)
{
EQApplicationPacket* outapp;
outapp = new EQApplicationPacket(OP_Buff, sizeof(SpellBuffFade_Struct));
SpellBuffFade_Struct* sbf = (SpellBuffFade_Struct*) outapp->pBuffer;
outapp = new EQApplicationPacket(OP_Buff, sizeof(SpellBuffPacket_Struct));
SpellBuffPacket_Struct* sbf = (SpellBuffPacket_Struct*) outapp->pBuffer;
sbf->entityid=GetID();
sbf->entityid = GetID();
// i dont know why but this works.. for now
sbf->slot=2;
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->spellid=spell_id;
sbf->slotid=slot_id;
sbf->buff.spellid = spell_id;
sbf->slotid = slot_id;
sbf->bufffade = 1;
#if EQDEBUG >= 11
printf("Sending SBF 1 from server:\n");
@@ -4820,7 +4820,7 @@ void Client::MakeBuffFadePacket(uint16 spell_id, int slot_id, bool send_message)
sbf->level=0;
sbf->slot=0;
*/
sbf->spellid=0xffffffff;
sbf->buff.spellid = 0xffffffff;
#if EQDEBUG >= 11
printf("Sending SBF 2 from server:\n");
DumpPacket(outapp);
@@ -4838,7 +4838,6 @@ void Client::MakeBuffFadePacket(uint16 spell_id, int slot_id, bool send_message)
QueuePacket(outapp);
safe_delete(outapp);
}
}
void Client::MemSpell(uint16 spell_id, int slot, bool update_client)
@@ -5274,99 +5273,36 @@ void Mob::_StopSong()
//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)
void Client::SendBuffDurationPacket(Buffs_Struct &buff, int slot)
{
EQApplicationPacket* outapp;
outapp = new EQApplicationPacket(OP_Buff, sizeof(SpellBuffFade_Struct));
SpellBuffFade_Struct* sbf = (SpellBuffFade_Struct*) outapp->pBuffer;
int index;
outapp = new EQApplicationPacket(OP_Buff, sizeof(SpellBuffPacket_Struct));
SpellBuffPacket_Struct* sbf = (SpellBuffPacket_Struct*) outapp->pBuffer;
sbf->entityid = GetID();
sbf->slot = 2;
sbf->spellid = buff.spellid;
sbf->slotid = 0;
sbf->level = buff.casterlevel > 0 ? buff.casterlevel : GetLevel();
// We really don't know what to send as sbf->effect.
// The code used to send level (and still does for cases we don't know)
//
// The fixes below address known issues with sending level in this field.
// Typically, when the packet is sent, or when the user
// next does something on the UI that causes an update (like opening a
// pack), the stats updated by the spell in question get corrupted.
//
// The values were determined by trial and error. I could not find a
// pattern or find a field in spells_new that would work.
sbf->buff.effect_type = 2;
sbf->effect=sbf->level;
if (IsEffectInSpell(buff.spellid, SE_TotalHP))
{
// If any of the lower 6 bits are set, the GUI changes MAX_HP AGAIN.
// If its set to 0 the effect is cancelled.
// 128 seems to work (ie: change only duration).
sbf->effect = 128;
}
else if (IsEffectInSpell(buff.spellid, SE_CurrentHP))
{
// This is mostly a problem when we try and update duration on a
// dot or a hp->mana conversion. Zero cancels the effect
// Sending teh actual change again seems to work.
index = GetSpellEffectIndex(buff.spellid, SE_CurrentHP);
sbf->effect = abs(spells[buff.spellid].base[index]);
}
else if (IsEffectInSpell(buff.spellid, SE_SeeInvis))
{
// 10 seems to not break SeeInvis spells. Level,
// which is what the old client sends breaks the client at at
// least level 9, maybe more.
sbf->effect = 10;
}
else if (IsEffectInSpell(buff.spellid, SE_ArmorClass) ||
IsEffectInSpell(buff.spellid, SE_ResistFire) ||
IsEffectInSpell(buff.spellid, SE_ResistCold) ||
IsEffectInSpell(buff.spellid, SE_ResistPoison) ||
IsEffectInSpell(buff.spellid, SE_ResistDisease) ||
IsEffectInSpell(buff.spellid, SE_ResistMagic) ||
IsEffectInSpell(buff.spellid, SE_STR) ||
IsEffectInSpell(buff.spellid, SE_STA) ||
IsEffectInSpell(buff.spellid, SE_DEX) ||
IsEffectInSpell(buff.spellid, SE_WIS) ||
IsEffectInSpell(buff.spellid, SE_INT) ||
IsEffectInSpell(buff.spellid, SE_AGI))
{
// This seems to work. Previosly stats got corrupted when sending
// level.
sbf->effect = 46;
}
else if (IsEffectInSpell(buff.spellid, SE_MovementSpeed))
{
index = GetSpellEffectIndex(buff.spellid, SE_MovementSpeed);
// So MovementSpeed spells react to effect values as follows:
// 0- cancels the effect (buff stays up - run speed is normal)
// 1-45 - A formula of change where 1-9 yield about a .1 to .9
// reduction of the spell effect, 10 yields about the same, and
// 11-45 gets faster very quickly until the effect well exceeds
// any intended max.
// 46 - seems to do nothing - which is what we need.
sbf->effect = 46;
}
else if (IsEffectInSpell(buff.spellid, SE_CHA))
{
index = GetSpellEffectIndex(buff.spellid, SE_CHA);
sbf->effect = abs(spells[buff.spellid].base[index]);
// Only use this valie if its not a spacer.
if (sbf->effect != 0)
{
// Same as other stats, need this to prevent a double update.
sbf->effect = 46;
}
}
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.numhits;
sbf->buff.y = buff.caston_y;
sbf->buff.x = buff.caston_x;
sbf->buff.z = buff.caston_z;
sbf->slotid = slot;
sbf->bufffade = 0;
sbf->duration = buff.ticsremaining;
sbf->num_hits = buff.numhits;
FastQueuePacket(&outapp);
}
@@ -5496,7 +5432,7 @@ void Mob::BuffModifyDurationBySpellID(uint16 spell_id, int32 newDuration)
buffs[i].ticsremaining = newDuration;
if(IsClient())
{
CastToClient()->SendBuffDurationPacket(buffs[i]);
CastToClient()->SendBuffDurationPacket(buffs[i], i);
}
}
}
+1 -1
View File
@@ -3305,7 +3305,7 @@ void ZoneDatabase::LoadPetInfo(Client *client)
pi->Buffs[slot_id].spellid = spell_id;
pi->Buffs[slot_id].level = caster_level;
pi->Buffs[slot_id].player_id = caster_id;
pi->Buffs[slot_id].slotid = 2; // Always 2 in buffs struct for real buffs
pi->Buffs[slot_id].effect_type = 2; // Always 2 in buffs struct for real buffs
pi->Buffs[slot_id].duration = ticsremaining;
pi->Buffs[slot_id].counters = counters;