diff --git a/changelog.txt b/changelog.txt index a5fe6bf4f..9d83c5974 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,8 @@ 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...) Akkadius: Character creation process crash fix and query cleanup Akkadius: Created `character_lookup` table for applications that mirrors all `character_` table fields minus blob fields for application lookups - A 2.4GB character_ table will take 7 seconds to query on a SSD versus .1s on the character_lookup table diff --git a/zone/entity.cpp b/zone/entity.cpp index 45c203dc5..2ca3f640d 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/queryserv.cpp b/zone/queryserv.cpp index 2b02d193c..ad7de0424 100644 --- a/zone/queryserv.cpp +++ b/zone/queryserv.cpp @@ -47,6 +47,6 @@ void QueryServ::PlayerLogEvent(int Event_Type, int Character_ID, std::string Eve { std::string query = StringFormat( "INSERT INTO `qs_player_events` (event, char_id, event_desc, time) VALUES (%i, %i, '%s', UNIX_TIMESTAMP(now()))", - Event_Type, Character_ID, EscapeString(Event_Desc.c_str()).c_str()); + Event_Type, Character_ID, EscapeString(Event_Desc).c_str()); SendQuery(query); -} \ No newline at end of file +} 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();