Implement number of hit indicators for UF and RoF

There is a small display bug with the initial cast of the spell,
but it updates quickly enough that it shouldn't be too noticeable
This still needs to be fixed though

Changed SendBuffDurationPacket to take a Buffs_Struct by reference
to allow more of the data to be obtained without more params

Added Client::SendBuffNumHitPacket(Buffs_Struct &buff, int slot)
This commit is contained in:
Michael Cook (mackal) 2014-10-04 03:23:42 -04:00
parent e0e3059498
commit e753685ceb
8 changed files with 118 additions and 56 deletions

View File

@ -534,7 +534,7 @@ struct SpellBuffFade_Struct {
/*007*/ uint8 unknown7;
/*008*/ uint32 spellid;
/*012*/ uint32 duration;
/*016*/ uint32 unknown016;
/*016*/ uint32 num_hits;
/*020*/ uint32 unknown020; //prolly global player ID
/*024*/ uint32 slotid;
/*028*/ uint32 bufffade;
@ -4602,11 +4602,13 @@ struct BuffIconEntry_Struct
uint32 buff_slot;
uint32 spell_id;
uint32 tics_remaining;
uint32 num_hits;
};
struct BuffIcon_Struct
{
uint32 entity_id;
uint8 all_buffs;
uint16 count;
BuffIconEntry_Struct entries[0];
};

View File

@ -376,6 +376,7 @@ namespace RoF
OUT(duration);
eq->playerId = 0x7cde;
OUT(slotid);
OUT(num_hits);
if (emu->bufffade == 1)
eq->bufffade = 1;
else
@ -414,7 +415,7 @@ namespace RoF
__packet->WriteUInt32(emu->entity_id);
__packet->WriteUInt32(0); // PlayerID ?
__packet->WriteUInt8(1); // 1 indicates all buffs on the player (0 to add or remove a single buff)
__packet->WriteUInt8(emu->all_buffs); // 1 indicates all buffs on the player (0 to add or remove a single buff)
__packet->WriteUInt16(emu->count);
for (uint16 i = 0; i < emu->count; ++i)
@ -429,10 +430,10 @@ namespace RoF
__packet->WriteUInt32(buffslot);
__packet->WriteUInt32(emu->entries[i].spell_id);
__packet->WriteUInt32(emu->entries[i].tics_remaining);
__packet->WriteUInt32(0); // Unknown
__packet->WriteUInt32(emu->entries[i].num_hits); // Unknown
__packet->WriteString("");
}
__packet->WriteUInt8(0); // Unknown
__packet->WriteUInt8(!emu->all_buffs); // Unknown
FINISH_ENCODE();
}

View File

@ -712,7 +712,8 @@ struct SpellBuffFade_Struct_Live {
/*012*/ uint32 spellid;
/*016*/ uint32 duration;
/*020*/ uint32 playerId; // Global player ID?
/*024*/ uint8 unknown0028[68];
/*024*/ uint32 num_hits;
/*028*/ uint8 unknown0028[64];
/*092*/ uint32 slotid;
/*096*/ uint32 bufffade;
/*100*/
@ -726,7 +727,7 @@ struct SpellBuffFade_Struct {
/*007*/ uint8 unknown7;
/*008*/ uint32 spellid;
/*012*/ uint32 duration;
/*016*/ uint32 unknown016;
/*016*/ uint32 num_hits;
/*020*/ uint32 unknown020; // Global player ID?
/*024*/ uint32 playerId; // Player id who cast the buff
/*028*/ uint32 slotid;
@ -741,6 +742,27 @@ struct BuffRemoveRequest_Struct
/*08*/
};
#if 0
// not in use
struct BuffIconEntry_Struct {
/*000*/ uint32 buff_slot;
/*004*/ uint32 spell_id;
/*008*/ uint32 tics_remaining;
/*012*/ uint32 num_hits;
// char name[0]; caster name is also here sometimes
// uint8 unknownend; 1 when single, 0 when all opposite of all_buffs?
};
// not in use
struct BuffIcon_Struct {
/*000*/ uint32 entity_id;
/*004*/ uint32 unknown004;
/*008*/ uint8 all_buffs; // 1 when updating all buffs, 0 when doing one
/*009*/ uint16 count;
/*011*/ BuffIconEntry_Struct entires[0];
};
#endif
struct GMTrainee_Struct
{
/*000*/ uint32 npcid;

View File

@ -330,6 +330,7 @@ namespace Underfoot
OUT(duration);
OUT(slotid);
OUT(bufffade); // Live (October 2011) sends a 2 rather than 0 when a buff is created, but it doesn't seem to matter.
OUT(num_hits);
eq->unknown008 = 1.0f;
FINISH_ENCODE();
@ -348,7 +349,7 @@ namespace Underfoot
*((uint32*)ptr) = emu->entity_id;
ptr += sizeof(uint32);
ptr += sizeof(uint32);
*((uint8*)ptr) = 1;
*((uint8*)ptr) = emu->all_buffs;
ptr += sizeof(uchar);
*((uint16*)ptr) = emu->count;
ptr += sizeof(uint16);
@ -371,7 +372,9 @@ namespace Underfoot
ptr += sizeof(uint32);
*((uint32*)ptr) = emu->entries[i].tics_remaining;
ptr += sizeof(uint32);
*((uint32*)ptr) = emu->entries[i].num_hits;
ptr += sizeof(uint32);
*((uint8*)ptr) = !emu->all_buffs;
ptr += 1;
}

View File

@ -564,7 +564,7 @@ struct SpellBuffFade_Struct_Underfoot {
/*008*/ float unknown008;
/*012*/ uint32 spellid;
/*016*/ uint32 duration;
/*020*/ uint32 unknown016;
/*020*/ uint32 num_hits;
/*024*/ uint32 playerId; // Global player ID?
/*028*/ uint32 unknown020;
/*032*/ uint8 unknown0028[48];
@ -589,6 +589,25 @@ struct SpellBuffFade_Struct {
/*036*/
};
#if 0
struct BuffIconEntry_Struct {
/*000*/ uint32 buff_slot;
/*004*/ uint32 spell_id;
/*008*/ uint32 tics_remaining;
/*012*/ uint32 num_hits;
// char name[0]; caster name is also here sometimes
// uint8 unknownend; 1 when single, 0 when all opposite of all_buffs?
};
struct BuffIcon_Struct {
/*000*/ uint32 entity_id;
/*004*/ uint32 unknown004;
/*008*/ uint8 all_buffs; // 1 when updating all buffs, 0 when doing one
/*009*/ uint16 count;
/*011*/ BuffIconEntry_Struct entires[0];
};
#endif
struct BuffRemoveRequest_Struct
{
/*00*/ uint32 SlotID;

View File

@ -896,7 +896,8 @@ 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(uint16 spell_id, int duration, int inlevel);
void SendBuffDurationPacket(Buffs_Struct &buff);
void SendBuffNumHitPacket(Buffs_Struct &buff, int slot);
void ProcessInspectRequest(Client* requestee, Client* requester);
bool ClientFinishedLoading() { return (conn_state == ClientConnectFinished); }

View File

@ -3395,7 +3395,7 @@ void Mob::BuffProcess()
{
if(buffs[buffs_i].UpdateClient == true)
{
CastToClient()->SendBuffDurationPacket(buffs[buffs_i].spellid, buffs[buffs_i].ticsremaining, buffs[buffs_i].casterlevel);
CastToClient()->SendBuffDurationPacket(buffs[buffs_i]);
buffs[buffs_i].UpdateClient = false;
}
}
@ -5559,64 +5559,56 @@ void Mob::CheckNumHitsRemaining(uint8 type, uint32 buff_slot, uint16 spell_id)
uint32 buff_max = GetMaxTotalSlots();
//Spell specific procs [Type 7,10,11]
if (IsValidSpell(spell_id)){
for(uint32 d = 0; d < buff_max; d++) {
if((buffs[d].spellid == spell_id) && (buffs[d].numhits > 0) && (spells[buffs[d].spellid].numhitstype == type)){
if(--buffs[d].numhits == 0) {
if (IsValidSpell(spell_id)) {
for (uint32 d = 0; d < buff_max; d++) {
if (buffs[d].spellid == spell_id && buffs[d].numhits > 0 &&
spells[buffs[d].spellid].numhitstype == type) {
if (--buffs[d].numhits == 0) {
CastOnNumHitFade(buffs[d].spellid);
if(!TryFadeEffect(d))
if (!TryFadeEffect(d))
BuffFadeBySlot(d, true);
} else if (IsClient()) { // still have numhits and client, update
CastToClient()->SendBuffNumHitPacket(buffs[d], d);
}
}
}
}
else if (type == 7){
if (buff_slot > 0){
if(--buffs[buff_slot].numhits == 0) {
} else if (type == 7) {
if (buff_slot > 0) {
if (--buffs[buff_slot].numhits == 0) {
CastOnNumHitFade(buffs[buff_slot].spellid);
if(!TryFadeEffect(buff_slot))
if (!TryFadeEffect(buff_slot))
BuffFadeBySlot(buff_slot , true);
}
} else if (IsClient()) { // still have numhits and client, update
CastToClient()->SendBuffNumHitPacket(buffs[buff_slot], buff_slot);
}
else {
for(int d = 0; d < buff_max; d++) {
if(!m_spellHitsLeft[d])
} else {
for (int d = 0; d < buff_max; d++) {
if (!m_spellHitsLeft[d])
continue;
if ((IsValidSpell(buffs[d].spellid)) && (m_spellHitsLeft[d] == buffs[d].spellid)) {
if(--buffs[d].numhits == 0) {
if (IsValidSpell(buffs[d].spellid) && m_spellHitsLeft[d] == buffs[d].spellid) {
if (--buffs[d].numhits == 0) {
CastOnNumHitFade(buffs[d].spellid);
m_spellHitsLeft[d] = 0;
if(!TryFadeEffect(d))
if (!TryFadeEffect(d))
BuffFadeBySlot(d, true);
} else if (IsClient()) { // still have numhits and client, update
CastToClient()->SendBuffNumHitPacket(buffs[d], d);
}
}
}
}
}
else{
for(uint32 d = 0; d < buff_max; d++) {
if((IsValidSpell(buffs[d].spellid)) && (buffs[d].numhits > 0) && (spells[buffs[d].spellid].numhitstype == type)){
if(--buffs[d].numhits == 0) {
} else {
for (uint32 d = 0; d < buff_max; d++) {
if (IsValidSpell(buffs[d].spellid) && buffs[d].numhits > 0 &&
spells[buffs[d].spellid].numhitstype == type) {
if (--buffs[d].numhits == 0) {
CastOnNumHitFade(buffs[d].spellid);
if(!TryFadeEffect(d)){
if (!TryFadeEffect(d))
BuffFadeBySlot(d, true);
}
} else if (IsClient()) { // still have numhits and client, update
CastToClient()->SendBuffNumHitPacket(buffs[d], d);
}
}
}
}

View File

@ -5164,20 +5164,40 @@ 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(uint16 spell_id, int duration, int inlevel)
void Client::SendBuffDurationPacket(Buffs_Struct &buff)
{
EQApplicationPacket* outapp;
outapp = new EQApplicationPacket(OP_Buff, sizeof(SpellBuffFade_Struct));
SpellBuffFade_Struct* sbf = (SpellBuffFade_Struct*) outapp->pBuffer;
sbf->entityid = GetID();
sbf->slot=2;
sbf->spellid=spell_id;
sbf->slotid=0;
sbf->effect = inlevel > 0 ? inlevel : GetLevel();
sbf->level = inlevel > 0 ? inlevel : GetLevel();
sbf->slot = 2;
sbf->spellid = buff.spellid;
sbf->slotid = 0;
sbf->effect = buff.casterlevel > 0 ? buff.casterlevel : GetLevel();
sbf->level = buff.casterlevel > 0 ? buff.casterlevel : GetLevel();
sbf->bufffade = 0;
sbf->duration = duration;
sbf->duration = buff.ticsremaining;
sbf->num_hits = buff.numhits;
FastQueuePacket(&outapp);
}
void Client::SendBuffNumHitPacket(Buffs_Struct &buff, int slot)
{
// UF+ use this packet
if (GetClientVersion() < EQClientUnderfoot)
return;
EQApplicationPacket *outapp;
outapp = new EQApplicationPacket(OP_BuffCreate, 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->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.numhits;
FastQueuePacket(&outapp);
}
@ -5252,6 +5272,7 @@ EQApplicationPacket *Mob::MakeBuffsPacket(bool for_target)
BuffIcon_Struct *buff = (BuffIcon_Struct*)outapp->pBuffer;
buff->entity_id = GetID();
buff->count = count;
buff->all_buffs = 1;
uint32 index = 0;
for(unsigned int i = 0; i < buff_count; ++i)
@ -5261,6 +5282,7 @@ EQApplicationPacket *Mob::MakeBuffsPacket(bool for_target)
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].numhits;
++index;
}
}
@ -5278,7 +5300,7 @@ void Mob::BuffModifyDurationBySpellID(uint16 spell_id, int32 newDuration)
buffs[i].ticsremaining = newDuration;
if(IsClient())
{
CastToClient()->SendBuffDurationPacket(buffs[i].spellid, buffs[i].ticsremaining, buffs[i].casterlevel);
CastToClient()->SendBuffDurationPacket(buffs[i]);
}
}
}