XTargets will move auto entries up on removal like live

This also makes use of the bulk packet so not a crap ton of packets
generated.
This commit is contained in:
Michael Cook (mackal) 2015-09-03 02:56:51 -04:00
parent b7ee4634be
commit 4ae02e5efe
3 changed files with 80 additions and 22 deletions

View File

@ -7041,7 +7041,7 @@ void Client::UpdateClientXTarget(Client *c)
}
}
void Client::AddAutoXTarget(Mob *m)
void Client::AddAutoXTarget(Mob *m, bool send)
{
if(!XTargettingAvailable() || !XTargetAutoAddHaters)
return;
@ -7054,7 +7054,10 @@ void Client::AddAutoXTarget(Mob *m)
if((XTargets[i].Type == Auto) && (XTargets[i].ID == 0))
{
XTargets[i].ID = m->GetID();
if (send) // if we don't send we're bulk sending updates later on
SendXTargetPacket(i, m);
else
XTargets[i].dirty = true;
break;
}
}
@ -7072,13 +7075,11 @@ void Client::RemoveXTarget(Mob *m, bool OnlyAutoSlots)
if (m->GetID() == 0)
return;
for(int i = 0; i < GetMaxXTargets(); ++i)
{
if(OnlyAutoSlots && (XTargets[i].Type !=Auto))
for (int i = 0; i < GetMaxXTargets(); ++i) {
if (OnlyAutoSlots && XTargets[i].Type != Auto)
continue;
if(XTargets[i].ID == m->GetID())
{
if (XTargets[i].ID == m->GetID()) {
if (XTargets[i].Type == CurrentTargetNPC)
XTargets[i].Type = Auto;
@ -7086,18 +7087,37 @@ void Client::RemoveXTarget(Mob *m, bool OnlyAutoSlots)
++FreedAutoSlots;
XTargets[i].ID = 0;
SendXTargetPacket(i, nullptr);
}
else
{
if((XTargets[i].Type == Auto) && (XTargets[i].ID == 0))
XTargets[i].dirty = true;
} else {
if (XTargets[i].Type == Auto && XTargets[i].ID == 0)
HadFreeAutoSlotsBefore = true;
}
}
// If there are more mobs aggro on us than we had auto-hate slots, add one of those haters into the slot(s) we just freed up.
// move shit up!
std::queue<int> empty_slots;
for (int i = 0; i < GetMaxXTargets(); ++i) {
if (XTargets[i].Type != Auto)
continue;
if (XTargets[i].ID == 0) {
empty_slots.push(i);
continue;
}
if (XTargets[i].ID != 0 && !empty_slots.empty()) {
int temp = empty_slots.front();
std::swap(XTargets[i], XTargets[temp]);
XTargets[i].dirty = XTargets[temp].dirty = true;
empty_slots.pop();
empty_slots.push(i);
}
}
// If there are more mobs aggro on us than we had auto-hate slots, add one of those haters into the slot(s) we
// just freed up.
if (!HadFreeAutoSlotsBefore && FreedAutoSlots)
entity_list.RefreshAutoXTargets(this);
SendXTargetUpdates();
}
void Client::UpdateXTargetType(XTargetType Type, Mob *m, const char *Name)
@ -7166,6 +7186,42 @@ void Client::SendXTargetPacket(uint32 Slot, Mob *m)
FastQueuePacket(&outapp);
}
// This is a bulk packet, we use it when we remove something since we need to reorder the xtargets and maybe
// add new mobs! Currently doesn't check if there is a dirty flag set, so it should only be called when there is
void Client::SendXTargetUpdates()
{
if (!XTargettingAvailable())
return;
int count = 0;
// header is 4 bytes max xtargets, 4 bytes count
// entry is 4 bytes slot, 1 byte unknown, 4 bytes ID, 65 char name
auto outapp = new EQApplicationPacket(OP_XTargetResponse, 8 + 74 * GetMaxXTargets()); // fuck it max size
outapp->WriteUInt32(GetMaxXTargets());
outapp->WriteUInt32(1); // we will correct this later
for (int i = 0; i < GetMaxXTargets(); ++i) {
if (XTargets[i].dirty) {
outapp->WriteUInt32(i);
outapp->WriteUInt8(0); // no idea what this is
outapp->WriteUInt32(XTargets[i].ID);
outapp->WriteString(XTargets[i].Name);
count++;
XTargets[i].dirty = false;
}
}
assert(count > 0); // we don't have any logic to prevent this, assert for now
auto newbuff = new uchar[outapp->GetWritePosition()];
memcpy(newbuff, outapp->pBuffer, outapp->GetWritePosition());
safe_delete_array(outapp->pBuffer);
outapp->pBuffer = newbuff;
outapp->size = outapp->GetWritePosition();
outapp->SetWritePosition(4);
outapp->WriteUInt32(count);
FastQueuePacket(&outapp);
}
void Client::RemoveGroupXTargets()
{
if(!XTargettingAvailable())

View File

@ -175,6 +175,7 @@ typedef enum
struct XTarget_Struct
{
XTargetType Type;
bool dirty;
uint16 ID;
char Name[65];
};
@ -1144,9 +1145,10 @@ public:
bool IsClientXTarget(const Client *c) const;
void UpdateClientXTarget(Client *c);
void UpdateXTargetType(XTargetType Type, Mob *m, const char *Name = nullptr);
void AddAutoXTarget(Mob *m);
void AddAutoXTarget(Mob *m, bool send = true);
void RemoveXTarget(Mob *m, bool OnlyAutoSlots);
void SendXTargetPacket(uint32 Slot, Mob *m);
void SendXTargetUpdates();
void RemoveGroupXTargets();
void RemoveAutoXTargets();
void ShowXTargets(Client *c);

View File

@ -1373,7 +1373,7 @@ void EntityList::RefreshAutoXTargets(Client *c)
continue;
if (m->CheckAggro(c) && !c->IsXTarget(m)) {
c->AddAutoXTarget(m);
c->AddAutoXTarget(m, false); // we only call this before a bulk, so lets not send right away
break;
}