1
0

Fix spells to properly cleanup in function SpellProcess::CheckRemoveTargetFromSpell -- RemoveEffectsFromLuaSpell was not properly cleaning up special effects like sneak/snare/root/so on lingered on to cause a crash with dead spells with /reload spells or other activity

This commit is contained in:
Emagi 2025-02-04 18:45:48 -05:00
parent 8dff68f6ab
commit 5d191927cf
3 changed files with 51 additions and 32 deletions

View File

@ -1954,10 +1954,10 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
else { else {
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Reloading Spells & NPC Spell Lists (Note: Must Reload Spawns/Repop to reset npc spells)..."); client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Reloading Spells & NPC Spell Lists (Note: Must Reload Spawns/Repop to reset npc spells)...");
world.SetReloadingSubsystem("Spells"); world.SetReloadingSubsystem("Spells");
zone_list.DeleteSpellProcess();
if (lua_interface) if (lua_interface)
lua_interface->DestroySpells(); lua_interface->DestroySpells();
zone_list.DeleteSpellProcess();
master_spell_list.Reload(); master_spell_list.Reload();
zone_list.LoadSpellProcess(); zone_list.LoadSpellProcess();
world.RemoveReloadingSubSystem("Spells"); world.RemoveReloadingSubSystem("Spells");

View File

@ -150,6 +150,22 @@ void LuaInterface::DestroySpells() {
for(inner_itr = spell_script_itr->second.begin(); inner_itr != spell_script_itr->second.end(); inner_itr++) { for(inner_itr = spell_script_itr->second.begin(); inner_itr != spell_script_itr->second.end(); inner_itr++) {
LuaSpell* cur_spell = inner_itr->second; LuaSpell* cur_spell = inner_itr->second;
MSpellDelete.lock(); 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); RemoveCurrentSpell(inner_itr->first, inner_itr->second, false, true, false);
lua_close(inner_itr->first); lua_close(inner_itr->first);
safe_delete(cur_spell); safe_delete(cur_spell);

View File

@ -62,6 +62,9 @@ void SpellProcess::RemoveCaster(Spawn* caster, bool lock_spell_process){
void SpellProcess::RemoveAllSpells(bool reload_spells){ void SpellProcess::RemoveAllSpells(bool reload_spells){
ClearSpellScriptTimerList(); ClearSpellScriptTimerList();
if(reload_spells) {
active_spells.clear();
}
MutexList<LuaSpell*>::iterator active_spells_itr = active_spells.begin(); MutexList<LuaSpell*>::iterator active_spells_itr = active_spells.begin();
while(active_spells_itr.Next()){ while(active_spells_itr.Next()){
DeleteCasterSpell(active_spells_itr->value, "", true, 0, !reload_spells); DeleteCasterSpell(active_spells_itr->value, "", true, 0, !reload_spells);
@ -69,11 +72,13 @@ void SpellProcess::RemoveAllSpells(bool reload_spells){
MSpellProcess.lock(); MSpellProcess.lock();
if(!reload_spells) {
active_spells_itr = active_spells.begin(); active_spells_itr = active_spells.begin();
while(active_spells_itr.Next()){ while(active_spells_itr.Next()){
active_spells.Remove(active_spells_itr->value); active_spells.Remove(active_spells_itr->value);
} }
active_spells.clear(); active_spells.clear();
}
InterruptStruct* interrupt = 0; InterruptStruct* interrupt = 0;
MutexList<InterruptStruct*>::iterator interrupt_list_itr = interrupt_list.begin(); MutexList<InterruptStruct*>::iterator interrupt_list_itr = interrupt_list.begin();
@ -2820,6 +2825,7 @@ void SpellProcess::CheckRemoveTargetFromSpell(LuaSpell* spell, bool allow_delete
MRemoveTargetList.writelock(__FUNCTION__, __LINE__); MRemoveTargetList.writelock(__FUNCTION__, __LINE__);
if (remove_target_list.size() > 0){ if (remove_target_list.size() > 0){
vector<Spawn*> spawnsToRemove;
map<LuaSpell*, vector<int32>*>::iterator remove_itr; map<LuaSpell*, vector<int32>*>::iterator remove_itr;
vector<int32>::iterator remove_target_itr; vector<int32>::iterator remove_target_itr;
vector<int32>::iterator target_itr; vector<int32>::iterator target_itr;
@ -2828,6 +2834,7 @@ void SpellProcess::CheckRemoveTargetFromSpell(LuaSpell* spell, bool allow_delete
Spawn* remove_spawn = 0; Spawn* remove_spawn = 0;
bool should_delete = false; bool should_delete = false;
bool dropped_lock = false; bool dropped_lock = false;
bool targets_empty = false;
for (remove_itr = remove_target_list.begin(); remove_itr != remove_target_list.end(); remove_itr++){ for (remove_itr = remove_target_list.begin(); remove_itr != remove_target_list.end(); remove_itr++){
if (remove_itr->first == spell){ if (remove_itr->first == spell){
targets = &spell->targets; targets = &spell->targets;
@ -2835,10 +2842,7 @@ void SpellProcess::CheckRemoveTargetFromSpell(LuaSpell* spell, bool allow_delete
if (remove_targets && targets){ if (remove_targets && targets){
spell->MSpellTargets.writelock(__FUNCTION__, __LINE__); spell->MSpellTargets.writelock(__FUNCTION__, __LINE__);
for (remove_target_itr = remove_targets->begin(); remove_target_itr != remove_targets->end(); remove_target_itr++){ for (remove_target_itr = remove_targets->begin(); remove_target_itr != remove_targets->end(); remove_target_itr++){
if(!spell->caster || !spell->caster->GetZone()) remove_spawn = spell->zone->GetSpawnByID((*remove_target_itr));
continue;
remove_spawn = spell->caster->GetZone()->GetSpawnByID((*remove_target_itr));
if (remove_spawn) { if (remove_spawn) {
bool found_target = false; bool found_target = false;
if(remove_spawn->IsPlayer()) if(remove_spawn->IsPlayer())
@ -2856,32 +2860,18 @@ void SpellProcess::CheckRemoveTargetFromSpell(LuaSpell* spell, bool allow_delete
((Entity*)remove_spawn)->RemoveMaintainedSpell(spell); ((Entity*)remove_spawn)->RemoveMaintainedSpell(spell);
LogWrite(SPELL__DEBUG, 0, "Spell", "%s CheckRemoveTargetFromSpell %s (%u).", spell->spell->GetName(), remove_spawn->GetName(), remove_spawn->GetID()); LogWrite(SPELL__DEBUG, 0, "Spell", "%s CheckRemoveTargetFromSpell %s (%u).", spell->spell->GetName(), remove_spawn->GetName(), remove_spawn->GetID());
targets->erase(target_itr); targets->erase(target_itr);
if (remove_spawn->IsEntity()) if(remove_spawn && std::find(spawnsToRemove.begin(), spawnsToRemove.end(), remove_spawn) == spawnsToRemove.end())
((Entity*)remove_spawn)->RemoveEffectsFromLuaSpell(spell); spawnsToRemove.push_back(remove_spawn);
break; break;
} }
} }
if (targets->size() == 0 && spell->char_id_targets.size() == 0 && allow_delete) { targets_empty = (targets->size() == 0 && spell->char_id_targets.size() == 0);
spell->MSpellTargets.releasewritelock(__FUNCTION__, __LINE__); if (targets_empty && allow_delete) {
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);
should_delete = true; should_delete = true;
dropped_lock = true;
break; break;
} }
else { else if(remove_spawn && std::find(spawnsToRemove.begin(), spawnsToRemove.end(), remove_spawn) == spawnsToRemove.end()) {
spell->MSpellTargets.releasewritelock(__FUNCTION__, __LINE__); spawnsToRemove.push_back(remove_spawn);
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;
} }
} }
} }
@ -2891,9 +2881,22 @@ void SpellProcess::CheckRemoveTargetFromSpell(LuaSpell* spell, bool allow_delete
} }
} }
if(dropped_lock) { MRemoveTargetList.releasewritelock(__FUNCTION__, __LINE__);
MRemoveTargetList.writelock(__FUNCTION__, __LINE__); for(int s=0;s<spawnsToRemove.size();s++) {
Spawn* target = spawnsToRemove.at(s);
if(target) {
bool not_last_itr = (s != spawnsToRemove.size() - 1);
if(target->IsEntity())
((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); remove_target_list.erase(spell);
if (remove_targets) if (remove_targets)