From a5872b165fbe8582d8f779774291eaee16893aa4 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Wed, 1 Apr 2015 13:00:38 -0400 Subject: [PATCH 1/2] Zoning into a new zone did not properly display PCs with tree/object illusions and NPCs wearing gear in non-weapon slots. The illusion thing: Not sure why, but te opcode for BulkZoneSpawn doesn't display the tree/object illusions. I did notice that even OP_Illusion gets rejected by the client if sent before Client_Ready. Maybe that is why. The BULKSpawns cannot be sent that late, I tried moving it in the sequence but it never did the illusions correctly, at any point. So, we new new the single spawn OP code for PCs with those illusions. This works. The NPC gear thing. Same story with BulkZoneSpawn, Not sure why. The data is sent correctly. So now we update the client zoning in (only them) with what the NPCs are wearing. Every othe client already is up to date. --- common/races.h | 2 ++ zone/entity.cpp | 37 ++++++++++++++++++++++++++++++++++--- zone/mob.cpp | 12 ++++++++++-- zone/mob.h | 2 +- 4 files changed, 47 insertions(+), 6 deletions(-) diff --git a/common/races.h b/common/races.h index 2c360e908..68add5cca 100644 --- a/common/races.h +++ b/common/races.h @@ -47,6 +47,8 @@ #define IKSAR 128 #define VAHSHIR 130 #define CONTROLLED_BOAT 141 +#define MINOR_ILL_OBJ 142 +#define TREE 143 #define IKSAR_SKELETON 161 #define FROGLOK 330 #define FROGLOK2 74 // Not sure why /who all reports race as 74 for frogloks diff --git a/zone/entity.cpp b/zone/entity.cpp index a28a4b846..a2fb2657d 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -1149,19 +1149,50 @@ void EntityList::SendZoneSpawnsBulk(Client *client) NewSpawn_Struct ns; Mob *spawn; uint32 maxspawns = 100; + EQApplicationPacket *app; if (maxspawns > mob_list.size()) maxspawns = mob_list.size(); BulkZoneSpawnPacket *bzsp = new BulkZoneSpawnPacket(client, maxspawns); + + int32 race=-1; for (auto it = mob_list.begin(); it != mob_list.end(); ++it) { spawn = it->second; if (spawn && spawn->InZone()) { if (spawn->IsClient() && (spawn->CastToClient()->GMHideMe(client) || spawn->CastToClient()->IsHoveringForRespawn())) continue; - memset(&ns, 0, sizeof(NewSpawn_Struct)); - spawn->FillSpawnStruct(&ns, client); - bzsp->AddSpawn(&ns); + + race = spawn->GetRace(); + + // Illusion races on PCs don't work as a mass spawn + // But they will work as an add_spawn AFTER CLIENT_CONNECTED. + if (spawn->IsClient() && (race == MINOR_ILL_OBJ || race == TREE)) { + app = new EQApplicationPacket; + spawn->CreateSpawnPacket(app); + client->QueuePacket(app, true, Client::CLIENT_CONNECTED); + safe_delete(app); + } + else { + memset(&ns, 0, sizeof(NewSpawn_Struct)); + spawn->FillSpawnStruct(&ns, client); + bzsp->AddSpawn(&ns); + } + + // On NPCs wearing gear from loottable or previously traded + // to them, mass spawn does not properly update the visual look. + // (Bulk packet sends the same info - client just doesn't use it. + // except on primary/secondary - tested on multiple client types) + // Do that using a Wear Change now. + if (!spawn->IsClient()) { + const Item_Struct *item; + for (int i=0; i< 7 ; ++i) { + item=database.GetItem(spawn->GetEquipment(i)); + if (item != 0) { + spawn->SendWearChange(i,client); + } + } + } } } safe_delete(bzsp); diff --git a/zone/mob.cpp b/zone/mob.cpp index 2053594be..f21ed3d6e 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -2540,7 +2540,7 @@ uint32 NPC::GetEquipment(uint8 material_slot) const return equipment[invslot]; } -void Mob::SendWearChange(uint8 material_slot) +void Mob::SendWearChange(uint8 material_slot, Client *one_client) { EQApplicationPacket* outapp = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct)); WearChange_Struct* wc = (WearChange_Struct*)outapp->pBuffer; @@ -2552,7 +2552,15 @@ void Mob::SendWearChange(uint8 material_slot) wc->color.Color = GetEquipmentColor(material_slot); wc->wear_slot_id = material_slot; - entity_list.QueueClients(this, outapp); + if (!one_client) + { + entity_list.QueueClients(this, outapp); + } + else + { + one_client->QueuePacket(outapp, false, Client::CLIENT_CONNECTED); + } + safe_delete(outapp); } diff --git a/zone/mob.h b/zone/mob.h index 979d9728a..f35857823 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -166,7 +166,7 @@ public: void SendAppearanceEffect(uint32 parm1, uint32 parm2, uint32 parm3, uint32 parm4, uint32 parm5, Client *specific_target=nullptr); void SendTargetable(bool on, Client *specific_target = nullptr); - virtual void SendWearChange(uint8 material_slot); + virtual void SendWearChange(uint8 material_slot, Client *one_client = nullptr); virtual void SendTextureWC(uint8 slot, uint16 texture, uint32 hero_forge_model = 0, uint32 elite_material = 0, uint32 unknown06 = 0, uint32 unknown18 = 0); virtual void SetSlotTint(uint8 material_slot, uint8 red_tint, uint8 green_tint, uint8 blue_tint); From bf93d72a431a3037e7105a2a1c8fb42f1751f9fa Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Thu, 2 Apr 2015 13:25:12 -0400 Subject: [PATCH 2/2] Added more changes so mobs armor will appear correctly (pc races only) when the spawn vie gm command or normally with loot tables that equip. Refined previous changes that fixed the issue with zoning in and not seeing previosuly spawned armor by sharing the same module. --- zone/entity.cpp | 26 +++++++++++--------------- zone/mob.cpp | 28 ++++++++++++++++++++++++++++ zone/mob.h | 1 + 3 files changed, 40 insertions(+), 15 deletions(-) diff --git a/zone/entity.cpp b/zone/entity.cpp index a2fb2657d..c6de7b33e 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -618,6 +618,7 @@ void EntityList::AddNPC(NPC *npc, bool SendSpawnPacket, bool dontqueue) EQApplicationPacket *app = new EQApplicationPacket; npc->CreateSpawnPacket(app, npc); QueueClients(npc, app); + npc->SendArmorAppearance(); safe_delete(app); } else { NewSpawn_Struct *ns = new NewSpawn_Struct; @@ -726,10 +727,16 @@ void EntityList::CheckSpawnQueue() EQApplicationPacket *outapp = 0; iterator.Reset(); + NewSpawn_Struct *ns; + while(iterator.MoreElements()) { outapp = new EQApplicationPacket; - Mob::CreateSpawnPacket(outapp, iterator.GetData()); + ns = iterator.GetData(); + Mob::CreateSpawnPacket(outapp, ns); QueueClients(0, outapp); + auto it = npc_list.find(ns->spawn.spawnId); + NPC *pnpc = it->second; + pnpc->SendArmorAppearance(); safe_delete(outapp); iterator.RemoveCurrent(); } @@ -1179,20 +1186,9 @@ void EntityList::SendZoneSpawnsBulk(Client *client) bzsp->AddSpawn(&ns); } - // On NPCs wearing gear from loottable or previously traded - // to them, mass spawn does not properly update the visual look. - // (Bulk packet sends the same info - client just doesn't use it. - // except on primary/secondary - tested on multiple client types) - // Do that using a Wear Change now. - if (!spawn->IsClient()) { - const Item_Struct *item; - for (int i=0; i< 7 ; ++i) { - item=database.GetItem(spawn->GetEquipment(i)); - if (item != 0) { - spawn->SendWearChange(i,client); - } - } - } + // Despite being sent in the OP_ZoneSpawns packet, the client + // does not display worn armor correctly so display it. + spawn->SendArmorAppearance(client); } } safe_delete(bzsp); diff --git a/zone/mob.cpp b/zone/mob.cpp index 9e9bcbd5d..9b4c2f88e 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -2552,6 +2552,34 @@ uint32 NPC::GetEquipment(uint8 material_slot) const return equipment[invslot]; } +void Mob::SendArmorAppearance(Client *one_client) +{ + // one_client of 0 means sent to all clients + // + // Despite the fact that OP_NewSpawn and OP_ZoneSpawns include the + // armor being worn and its mats, the client doesn't update the display + // on arrival of these packets reliably. + // + // Send Wear changes if mob is a PC race and item is an armor slot. + // The other packets work for primary/secondary. + + if (IsPlayerRace(race)) + { + if (!IsClient()) + { + const Item_Struct *item; + for (int i=0; i< 7 ; ++i) + { + item=database.GetItem(GetEquipment(i)); + if (item != 0) + { + SendWearChange(i,one_client); + } + } + } + } +} + void Mob::SendWearChange(uint8 material_slot, Client *one_client) { EQApplicationPacket* outapp = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct)); diff --git a/zone/mob.h b/zone/mob.h index 22f9cb5f1..ada2c56dd 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -171,6 +171,7 @@ public: void SendAppearanceEffect(uint32 parm1, uint32 parm2, uint32 parm3, uint32 parm4, uint32 parm5, Client *specific_target=nullptr); void SendTargetable(bool on, Client *specific_target = nullptr); + virtual void SendArmorAppearance(Client *one_client = nullptr); virtual void SendWearChange(uint8 material_slot, Client *one_client = nullptr); virtual void SendTextureWC(uint8 slot, uint16 texture, uint32 hero_forge_model = 0, uint32 elite_material = 0, uint32 unknown06 = 0, uint32 unknown18 = 0);