mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-13 23:01:30 +00:00
[Bug Fix] Fix NPC Reference in EVENT_SPAWN (#2712)
* [Bug Fix] Fix NPC Reference in EVENT_SPAWN
# Notes
- Event parsing was too early and memory wasn't fully allocated, meaning that sometimes you could use the NPC reference and other times you couldn't.
- Most people worked around this by setting timers in `EVENT_SPAWN` then using `EVENT_TIMER` to handle the stuff they wanted to do on spawn.
# Example Code in Perl
```pl
sub EVENT_SPAWN {
quest::shout($npc->GetCleanName() . " just spawned with an ID of " . $npc->GetID() . " and an NPC Type ID of " . $npc->GetNPCTypeID() . ".");
}```
* Update bot.cpp
This commit is contained in:
parent
2253e43d2c
commit
0c105a2b91
@ -8784,14 +8784,14 @@ void EntityList::AddBot(Bot *new_bot, bool send_spawn_packet, bool dont_queue) {
|
|||||||
AddToSpawnQueue(new_bot->GetID(), &ns);
|
AddToSpawnQueue(new_bot->GetID(), &ns);
|
||||||
safe_delete(ns);
|
safe_delete(ns);
|
||||||
}
|
}
|
||||||
|
|
||||||
parse->EventBot(EVENT_SPAWN, new_bot, nullptr, "", 0);
|
|
||||||
|
|
||||||
new_bot->DispatchZoneControllerEvent(EVENT_SPAWN_ZONE, new_bot, "", 0, nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bot_list.push_back(new_bot);
|
bot_list.push_back(new_bot);
|
||||||
mob_list.insert(std::pair<uint16, Mob*>(new_bot->GetID(), new_bot));
|
mob_list.insert(std::pair<uint16, Mob*>(new_bot->GetID(), new_bot));
|
||||||
|
|
||||||
|
parse->EventBot(EVENT_SPAWN, new_bot, nullptr, "", 0);
|
||||||
|
|
||||||
|
new_bot->DispatchZoneControllerEvent(EVENT_SPAWN_ZONE, new_bot, "", 0, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -685,56 +685,61 @@ void EntityList::AddCorpse(Corpse *corpse, uint32 in_id)
|
|||||||
corpse_timer.Start();
|
corpse_timer.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityList::AddNPC(NPC *npc, bool SendSpawnPacket, bool dontqueue)
|
void EntityList::AddNPC(NPC *npc, bool send_spawn_packet, bool dont_queue)
|
||||||
{
|
{
|
||||||
npc->SetID(GetFreeID());
|
npc->SetID(GetFreeID());
|
||||||
|
|
||||||
//If this is not set here we will despawn pets from new AC changes
|
//If this is not set here we will despawn pets from new AC changes
|
||||||
auto owner_id = npc->GetOwnerID();
|
auto owner_id = npc->GetOwnerID();
|
||||||
if(owner_id) {
|
if (owner_id) {
|
||||||
auto owner = entity_list.GetMob(owner_id);
|
auto owner = entity_list.GetMob(owner_id);
|
||||||
if (owner) {
|
if (owner) {
|
||||||
owner->SetPetID(npc->GetID());
|
owner->SetPetID(npc->GetID());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parse->EventNPC(EVENT_SPAWN, npc, nullptr, "", 0);
|
|
||||||
|
|
||||||
uint32 emoteid = npc->GetEmoteID();
|
const auto emote_id = npc->GetEmoteID();
|
||||||
if (emoteid != 0)
|
if (emote_id != 0) {
|
||||||
npc->DoNPCEmote(EQ::constants::EmoteEventTypes::OnSpawn, emoteid);
|
npc->DoNPCEmote(EQ::constants::EmoteEventTypes::OnSpawn, emote_id);
|
||||||
|
}
|
||||||
|
|
||||||
npc->SetSpawned();
|
npc->SetSpawned();
|
||||||
if (SendSpawnPacket) {
|
|
||||||
if (dontqueue) { // aka, SEND IT NOW BITCH!
|
if (send_spawn_packet) {
|
||||||
|
if (dont_queue) {
|
||||||
auto app = new EQApplicationPacket;
|
auto app = new EQApplicationPacket;
|
||||||
npc->CreateSpawnPacket(app, npc);
|
npc->CreateSpawnPacket(app, npc);
|
||||||
QueueClients(npc, app);
|
QueueClients(npc, app);
|
||||||
npc->SendArmorAppearance();
|
npc->SendArmorAppearance();
|
||||||
npc->SetAppearance(npc->GetGuardPointAnim(),false);
|
npc->SetAppearance(npc->GetGuardPointAnim(), false);
|
||||||
if (!npc->IsTargetable())
|
|
||||||
|
if (!npc->IsTargetable()) {
|
||||||
npc->SendTargetable(false);
|
npc->SendTargetable(false);
|
||||||
|
}
|
||||||
|
|
||||||
safe_delete(app);
|
safe_delete(app);
|
||||||
} else {
|
} else {
|
||||||
auto ns = new NewSpawn_Struct;
|
auto ns = new NewSpawn_Struct;
|
||||||
memset(ns, 0, sizeof(NewSpawn_Struct));
|
memset(ns, 0, sizeof(NewSpawn_Struct));
|
||||||
npc->FillSpawnStruct(ns, nullptr); // Not working on player newspawns, so it's safe to use a ForWho of 0
|
npc->FillSpawnStruct(ns, nullptr);
|
||||||
AddToSpawnQueue(npc->GetID(), &ns);
|
AddToSpawnQueue(npc->GetID(), &ns);
|
||||||
safe_delete(ns);
|
safe_delete(ns);
|
||||||
}
|
}
|
||||||
if (npc->IsFindable())
|
|
||||||
|
if (npc->IsFindable()) {
|
||||||
UpdateFindableNPCState(npc, false);
|
UpdateFindableNPCState(npc, false);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
npc_list.insert(std::pair<uint16, NPC *>(npc->GetID(), npc));
|
npc_list.insert(std::pair<uint16, NPC *>(npc->GetID(), npc));
|
||||||
mob_list.insert(std::pair<uint16, Mob *>(npc->GetID(), npc));
|
mob_list.insert(std::pair<uint16, Mob *>(npc->GetID(), npc));
|
||||||
|
|
||||||
|
parse->EventNPC(EVENT_SPAWN, npc, nullptr, "", 0);
|
||||||
|
|
||||||
entity_list.ScanCloseMobs(npc->close_mobs, npc, true);
|
entity_list.ScanCloseMobs(npc->close_mobs, npc, true);
|
||||||
|
|
||||||
/* Zone controller process EVENT_SPAWN_ZONE */
|
|
||||||
npc->DispatchZoneControllerEvent(EVENT_SPAWN_ZONE, npc, "", 0, nullptr);
|
npc->DispatchZoneControllerEvent(EVENT_SPAWN_ZONE, npc, "", 0, nullptr);
|
||||||
|
|
||||||
/**
|
|
||||||
* Set whether NPC was spawned in or out of water
|
|
||||||
*/
|
|
||||||
if (zone->HasMap() && zone->HasWaterMap()) {
|
if (zone->HasMap() && zone->HasWaterMap()) {
|
||||||
npc->SetSpawnedInWater(false);
|
npc->SetSpawnedInWater(false);
|
||||||
if (zone->watermap->InLiquid(npc->GetPosition())) {
|
if (zone->watermap->InLiquid(npc->GetPosition())) {
|
||||||
|
|||||||
@ -278,7 +278,7 @@ public:
|
|||||||
bool MakeTrackPacket(Client* client);
|
bool MakeTrackPacket(Client* client);
|
||||||
void SendTraders(Client* client);
|
void SendTraders(Client* client);
|
||||||
void AddClient(Client*);
|
void AddClient(Client*);
|
||||||
void AddNPC(NPC*, bool SendSpawnPacket = true, bool dontqueue = false);
|
void AddNPC(NPC*, bool send_spawn_packet = true, bool dont_queue = false);
|
||||||
void AddMerc(Merc*, bool SendSpawnPacket = true, bool dontqueue = false);
|
void AddMerc(Merc*, bool SendSpawnPacket = true, bool dontqueue = false);
|
||||||
void AddCorpse(Corpse* pc, uint32 in_id = 0xFFFFFFFF);
|
void AddCorpse(Corpse* pc, uint32 in_id = 0xFFFFFFFF);
|
||||||
void AddObject(Object*, bool SendSpawnPacket = true);
|
void AddObject(Object*, bool SendSpawnPacket = true);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user