diff --git a/source/WorldServer/Commands/Commands.cpp b/source/WorldServer/Commands/Commands.cpp index 4a7525b..6c0c08e 100644 --- a/source/WorldServer/Commands/Commands.cpp +++ b/source/WorldServer/Commands/Commands.cpp @@ -1954,10 +1954,10 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie else { client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Reloading Spells & NPC Spell Lists (Note: Must Reload Spawns/Repop to reset npc spells)..."); world.SetReloadingSubsystem("Spells"); - - zone_list.DeleteSpellProcess(); if (lua_interface) lua_interface->DestroySpells(); + + zone_list.DeleteSpellProcess(); master_spell_list.Reload(); zone_list.LoadSpellProcess(); world.RemoveReloadingSubSystem("Spells"); diff --git a/source/WorldServer/LuaInterface.cpp b/source/WorldServer/LuaInterface.cpp index aa52893..c509398 100644 --- a/source/WorldServer/LuaInterface.cpp +++ b/source/WorldServer/LuaInterface.cpp @@ -150,6 +150,22 @@ void LuaInterface::DestroySpells() { for(inner_itr = spell_script_itr->second.begin(); inner_itr != spell_script_itr->second.end(); inner_itr++) { LuaSpell* cur_spell = inner_itr->second; MSpellDelete.lock(); + + ZoneServer* zone = nullptr; + if(cur_spell && cur_spell->zone) { + zone = cur_spell->zone; + cur_spell->MSpellTargets.readlock(__FUNCTION__, __LINE__); + for (int8 i = 0; i < cur_spell->targets.size(); i++) { + Spawn* target = cur_spell->zone->GetSpawnByID(cur_spell->targets.at(i)); + if (!target || !target->IsEntity()) + continue; + + cur_spell->zone->RemoveTargetFromSpell(cur_spell, target); + } + cur_spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); + zone->GetSpellProcess()->CheckRemoveTargetFromSpell(cur_spell, false, true); + } + SetLuaUserDataStale(cur_spell); RemoveCurrentSpell(inner_itr->first, inner_itr->second, false, true, false); lua_close(inner_itr->first); safe_delete(cur_spell); diff --git a/source/WorldServer/SpellProcess.cpp b/source/WorldServer/SpellProcess.cpp index 8cac165..b3c3c7c 100644 --- a/source/WorldServer/SpellProcess.cpp +++ b/source/WorldServer/SpellProcess.cpp @@ -62,6 +62,9 @@ void SpellProcess::RemoveCaster(Spawn* caster, bool lock_spell_process){ void SpellProcess::RemoveAllSpells(bool reload_spells){ ClearSpellScriptTimerList(); + if(reload_spells) { + active_spells.clear(); + } MutexList::iterator active_spells_itr = active_spells.begin(); while(active_spells_itr.Next()){ DeleteCasterSpell(active_spells_itr->value, "", true, 0, !reload_spells); @@ -69,11 +72,13 @@ void SpellProcess::RemoveAllSpells(bool reload_spells){ MSpellProcess.lock(); - active_spells_itr = active_spells.begin(); - while(active_spells_itr.Next()){ - active_spells.Remove(active_spells_itr->value); + if(!reload_spells) { + active_spells_itr = active_spells.begin(); + while(active_spells_itr.Next()){ + active_spells.Remove(active_spells_itr->value); + } + active_spells.clear(); } - active_spells.clear(); InterruptStruct* interrupt = 0; MutexList::iterator interrupt_list_itr = interrupt_list.begin(); @@ -2820,6 +2825,7 @@ void SpellProcess::CheckRemoveTargetFromSpell(LuaSpell* spell, bool allow_delete MRemoveTargetList.writelock(__FUNCTION__, __LINE__); if (remove_target_list.size() > 0){ + vector spawnsToRemove; map*>::iterator remove_itr; vector::iterator remove_target_itr; vector::iterator target_itr; @@ -2828,6 +2834,7 @@ void SpellProcess::CheckRemoveTargetFromSpell(LuaSpell* spell, bool allow_delete Spawn* remove_spawn = 0; bool should_delete = false; bool dropped_lock = false; + bool targets_empty = false; for (remove_itr = remove_target_list.begin(); remove_itr != remove_target_list.end(); remove_itr++){ if (remove_itr->first == spell){ targets = &spell->targets; @@ -2835,10 +2842,7 @@ void SpellProcess::CheckRemoveTargetFromSpell(LuaSpell* spell, bool allow_delete if (remove_targets && targets){ spell->MSpellTargets.writelock(__FUNCTION__, __LINE__); for (remove_target_itr = remove_targets->begin(); remove_target_itr != remove_targets->end(); remove_target_itr++){ - if(!spell->caster || !spell->caster->GetZone()) - continue; - - remove_spawn = spell->caster->GetZone()->GetSpawnByID((*remove_target_itr)); + remove_spawn = spell->zone->GetSpawnByID((*remove_target_itr)); if (remove_spawn) { bool found_target = false; if(remove_spawn->IsPlayer()) @@ -2856,32 +2860,18 @@ void SpellProcess::CheckRemoveTargetFromSpell(LuaSpell* spell, bool allow_delete ((Entity*)remove_spawn)->RemoveMaintainedSpell(spell); LogWrite(SPELL__DEBUG, 0, "Spell", "%s CheckRemoveTargetFromSpell %s (%u).", spell->spell->GetName(), remove_spawn->GetName(), remove_spawn->GetID()); targets->erase(target_itr); - if (remove_spawn->IsEntity()) - ((Entity*)remove_spawn)->RemoveEffectsFromLuaSpell(spell); + if(remove_spawn && std::find(spawnsToRemove.begin(), spawnsToRemove.end(), remove_spawn) == spawnsToRemove.end()) + spawnsToRemove.push_back(remove_spawn); break; } } - if (targets->size() == 0 && spell->char_id_targets.size() == 0 && allow_delete) { - spell->MSpellTargets.releasewritelock(__FUNCTION__, __LINE__); - if(!dropped_lock) { - MRemoveTargetList.releasewritelock(__FUNCTION__, __LINE__); - } - if(found_target) - lua_interface->RemoveSpell(spell, true, false, !remove_spawn->Alive() ? "target_dead" : "target_removed", false, false, remove_spawn); + targets_empty = (targets->size() == 0 && spell->char_id_targets.size() == 0); + if (targets_empty && allow_delete) { should_delete = true; - dropped_lock = true; break; } - else { - spell->MSpellTargets.releasewritelock(__FUNCTION__, __LINE__); - if(!dropped_lock) { - MRemoveTargetList.releasewritelock(__FUNCTION__, __LINE__); - } - // call remove function "on death" - if(found_target) - lua_interface->RemoveSpell(spell, true, false, !remove_spawn->Alive() ? "target_dead" : "target_removed", false, true, remove_spawn); - spell->MSpellTargets.writelock(__FUNCTION__, __LINE__); - dropped_lock = true; + else if(remove_spawn && std::find(spawnsToRemove.begin(), spawnsToRemove.end(), remove_spawn) == spawnsToRemove.end()) { + spawnsToRemove.push_back(remove_spawn); } } } @@ -2891,10 +2881,23 @@ void SpellProcess::CheckRemoveTargetFromSpell(LuaSpell* spell, bool allow_delete } } - if(dropped_lock) { - MRemoveTargetList.writelock(__FUNCTION__, __LINE__); + MRemoveTargetList.releasewritelock(__FUNCTION__, __LINE__); + for(int s=0;sIsEntity()) + ((Entity*)target)->RemoveEffectsFromLuaSpell(spell); + if(targets_empty && allow_delete) { + lua_interface->RemoveSpell(spell, true, false, !target->Alive() ? "target_dead" : "target_removed", false, not_last_itr, target); + } + else + lua_interface->RemoveSpell(spell, true, false, !target->Alive() ? "target_dead" : "target_removed", false, true, target); + } } + MRemoveTargetList.writelock(__FUNCTION__, __LINE__); + remove_target_list.erase(spell); if (remove_targets) remove_targets->clear();