mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-16 22:58:34 +00:00
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:
+1
-1
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user