From 52ae78709b207463f6299cd9d6a36b141358be6d Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 24 Aug 2014 05:42:43 -0400 Subject: [PATCH] First attempt at fixing zone shutdown crashes. (Mob timer processing accessing released resources.) --- changelog.txt | 4 ++++ zone/entity.cpp | 2 +- zone/mob_ai.cpp | 29 ++++++++++++++++++++++++++++- zone/quest_parser_collection.cpp | 5 ++--- zone/zone.cpp | 13 +++++++++++++ 5 files changed, 48 insertions(+), 5 deletions(-) diff --git a/changelog.txt b/changelog.txt index bf2ea97f0..082463fe9 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,9 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 08/24/2014 == +Uleat: Fix (attempted) for zone crashes related to zone shut-down. This change disables all Mob AI and disables/deletes all Mob timers once Zone::ShutDown() is called. More areas will be addressed as reports come in. +Note: Perl and Lua quests tested to work..please post any aberrant behavior. (I finally set my spell-check to US English...) + == 08/20/2014 == Uleat: Rework of Trade::AddEntity() - function used to move items into the trade window. Now accepts argument for 'stack_size' and updates client properly. Note: I tested trade with Titanium:{SoF,SoD,UF,RoF} in both directions and no client generated an OP_MoveItem event for attempting to place a stackable diff --git a/zone/entity.cpp b/zone/entity.cpp index 469bf8111..242d1a6b6 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -1598,7 +1598,7 @@ Corpse *EntityList::GetCorpseByName(const char *name) Spawn2 *EntityList::GetSpawnByID(uint32 id) { - if (!zone) + if (!zone || !zone->IsLoaded()) return nullptr; LinkedListIterator iterator(zone->spawn2_list); diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 87fc2ea79..10d41c78e 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -541,13 +541,40 @@ void NPC::AI_Start(uint32 iMoveDelay) { void Mob::AI_Stop() { if (!IsAIControlled()) return; + pAIControlled = false; + safe_delete(AIthink_timer); safe_delete(AIwalking_timer); safe_delete(AImovement_timer); - safe_delete(AItarget_check_timer) + safe_delete(AItarget_check_timer); safe_delete(AIscanarea_timer); safe_delete(AIfeignremember_timer); + safe_delete(PathingLOSCheckTimer); + safe_delete(PathingRouteUpdateTimerShort); + safe_delete(PathingRouteUpdateTimerLong); + + attack_timer.Disable(); + attack_dw_timer.Disable(); + ranged_timer.Disable(); + tic_timer.Disable(); + mana_timer.Disable(); + spellend_timer.Disable(); + projectile_timer.Disable(); + rewind_timer.Disable(); + bindwound_timer.Disable(); + stunned_timer.Disable(); + spun_timer.Disable(); + bardsong_timer.Disable(); + gravity_timer.Disable(); + viral_timer.Disable(); + flee_timer.Disable(); + + for (int sat = 0; sat < MAX_SPECIAL_ATTACK; ++sat) { + if (SpecialAbilities[sat].timer) + SpecialAbilities[sat].timer->Disable(); + } + hate_list.Wipe(); } diff --git a/zone/quest_parser_collection.cpp b/zone/quest_parser_collection.cpp index 376c121d3..8fc0f9c43 100644 --- a/zone/quest_parser_collection.cpp +++ b/zone/quest_parser_collection.cpp @@ -600,9 +600,8 @@ QuestInterface *QuestParserCollection::GetQIByNPCQuest(uint32 npcid, std::string } QuestInterface *QuestParserCollection::GetQIByPlayerQuest(std::string &filename) { - - if(!zone) - return nullptr; + if(!zone || !zone->IsLoaded()) + return nullptr; //first look for /quests/zone/player_v[instance_version].ext (precedence) filename = "quests/"; diff --git a/zone/zone.cpp b/zone/zone.cpp index a3026425c..77ac4401b 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -718,11 +718,24 @@ void Zone::DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw) { } } +bool Zone::IsLoaded() { + return ZoneLoaded; +} + void Zone::Shutdown(bool quite) { if (!ZoneLoaded) return; + std::list mob_list; + entity_list.GetMobList(mob_list); + std::list::iterator mob_itr = mob_list.begin(); + while (mob_itr != mob_list.end()) { + Mob* mob_inst = *mob_itr; + mob_inst->AI_Stop(); + ++mob_itr; + } + std::map::iterator itr; while(zone->npctable.size()) { itr=zone->npctable.begin();