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:
parent
8dff68f6ab
commit
5d191927cf
@ -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");
|
||||||
|
@ -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);
|
||||||
|
@ -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();
|
||||||
|
|
||||||
active_spells_itr = active_spells.begin();
|
if(!reload_spells) {
|
||||||
while(active_spells_itr.Next()){
|
active_spells_itr = active_spells.begin();
|
||||||
active_spells.Remove(active_spells_itr->value);
|
while(active_spells_itr.Next()){
|
||||||
|
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,10 +2881,23 @@ 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)
|
||||||
remove_targets->clear();
|
remove_targets->clear();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user