diff --git a/source/WorldServer/LuaFunctions.cpp b/source/WorldServer/LuaFunctions.cpp index 11c3283..2a6fa60 100644 --- a/source/WorldServer/LuaFunctions.cpp +++ b/source/WorldServer/LuaFunctions.cpp @@ -1401,17 +1401,15 @@ int EQ2Emu_lua_SpellHeal(lua_State* state) { if (((Entity*)caster)->SpellHeal(target, distance, luaspell, heal_type, min_heal, max_heal, crit_mod, no_calcs, custom_spell_name)) success = true; } - if ((!success || luaspell->spell->GetSpellData()->group_spell) && luaspell->targets.size() > 0) { + if ((!success || luaspell->spell->GetSpellData()->group_spell) && luaspell->GetTargetCount() > 0) { Spawn* target = 0; - ZoneServer* zone = luaspell->caster->GetZone(); - luaspell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - for (int32 i = 0; i < luaspell->targets.size(); i++) { - if ((target = zone->GetSpawnByID(luaspell->targets[i]))) { + ZoneServer* zone = luaspell->zone; + for (int32 id : luaspell->GetTargets()) { + if ((target = zone->GetSpawnByID(id))) { float distance = caster->GetDistance(target, true); ((Entity*)caster)->SpellHeal(target, distance, luaspell, heal_type, min_heal, max_heal, crit_mod, no_calcs, custom_spell_name); } } - luaspell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); success = true; } if (success) { @@ -1494,17 +1492,15 @@ int EQ2Emu_lua_SpellHealPct(lua_State* state) { if (((Entity*)caster)->SpellHeal(target, distance, luaspell, heal_type, min_heal, max_heal, crit_mod, no_calcs, custom_spell_name)) success = true; } - if ((!success || luaspell->spell->GetSpellData()->group_spell) && luaspell->targets.size() > 0) { + if ((!success || luaspell->spell->GetSpellData()->group_spell) && luaspell->GetTargetCount() > 0) { Spawn* target = 0; - ZoneServer* zone = luaspell->caster->GetZone(); - luaspell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - for (int32 i = 0; i < luaspell->targets.size(); i++) { - if ((target = zone->GetSpawnByID(luaspell->targets[i]))) { + ZoneServer* zone = luaspell->zone; + for (int32 id : luaspell->GetTargets()) { + if ((target = zone->GetSpawnByID(id))) { float distance = caster->GetDistance(target, true); ((Entity*)caster)->SpellHeal(target, distance, luaspell, heal_type, min_heal, max_heal, crit_mod, no_calcs, custom_spell_name); } } - luaspell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); success = true; } if (success) { @@ -1751,10 +1747,9 @@ int EQ2Emu_lua_AddHate(lua_State* state) { if (entity && entity->IsEntity() && amount != 0) { if (luaspell && luaspell->caster) { - ZoneServer* zone = luaspell->caster->GetZone(); - luaspell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - for (int32 i = 0; i < luaspell->targets.size(); i++) { - Spawn* spawn = zone->GetSpawnByID(luaspell->targets.at(i)); + ZoneServer* zone = luaspell->zone; + for (int32 id : luaspell->GetTargets()) { + Spawn* spawn = zone->GetSpawnByID(id); if (spawn && spawn->IsNPC() && spawn->Alive() && spawn->GetZone()) { entity->CheckEncounterState((Entity*)spawn); ((NPC*)spawn)->AddHate((Entity*)entity, amount); @@ -1762,7 +1757,6 @@ int EQ2Emu_lua_AddHate(lua_State* state) { entity->GetZone()->SendThreatPacket(entity, npc, amount, luaspell->spell->GetName()); } } - luaspell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); } else if (npc && npc->IsNPC() && npc->GetZone()) { entity->CheckEncounterState((Entity*)npc); @@ -1910,12 +1904,11 @@ int EQ2Emu_lua_SpellDamage(lua_State* state) { bool race_match = false; bool success = false; luaspell->resisted = false; - if (luaspell->targets.size() > 0) { - ZoneServer* zone = luaspell->caster->GetZone(); + if (luaspell->GetTargetCount() > 0) { + ZoneServer* zone = luaspell->zone; Spawn* target = 0; - luaspell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - for (int32 i = 0; i < luaspell->targets.size(); i++) { - if ((target = zone->GetSpawnByID(luaspell->targets[i]))) { + for (int32 id : luaspell->GetTargets()) { + if ((target = zone->GetSpawnByID(id))) { if (race_req.size() > 0) { for (int8 i = 0; i < race_req.size(); i++) { @@ -1935,7 +1928,6 @@ int EQ2Emu_lua_SpellDamage(lua_State* state) { } } success = true; - luaspell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); } else if (target) { @@ -2018,12 +2010,11 @@ int EQ2Emu_lua_SpellDamageExt(lua_State* state) { bool race_match = false; bool success = false; luaspell->resisted = false; - if (luaspell->targets.size() > 0) { - ZoneServer* zone = luaspell->caster->GetZone(); + if (luaspell->GetTargetCount() > 0) { + ZoneServer* zone = luaspell->zone; Spawn* target = 0; - luaspell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - for (int32 i = 0; i < luaspell->targets.size(); i++) { - if ((target = zone->GetSpawnByID(luaspell->targets[i]))) { + for (int32 id : luaspell->GetTargets()) { + if ((target = zone->GetSpawnByID(id))) { if (race_req.size() > 0) { for (int8 i = 0; i < race_req.size(); i++) { @@ -2043,7 +2034,6 @@ int EQ2Emu_lua_SpellDamageExt(lua_State* state) { } } success = true; - luaspell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); } else if (target) { @@ -2455,10 +2445,9 @@ int EQ2Emu_lua_AddSpellBonus(lua_State* state) { if (value != 0 && type >= 0) { if (luaspell && luaspell->spell && luaspell->caster) { - ZoneServer* zone = luaspell->caster->GetZone(); - luaspell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - for (int32 i = 0; i < luaspell->targets.size(); i++) { - Spawn* target = zone->GetSpawnByID(luaspell->targets[i]); + ZoneServer* zone = luaspell->zone; + for (int32 id : luaspell->GetTargets()) { + Spawn* target = zone->GetSpawnByID(id); if (target) { if (target->IsPlayer()) { ((Player*)target)->AddSpellBonus(luaspell, type, value, class_req, race_req, faction_req); @@ -2473,7 +2462,6 @@ int EQ2Emu_lua_AddSpellBonus(lua_State* state) { lua_interface->LogError("%s: Error applying spell bonus on non entity.", lua_interface->GetScriptName(state)); } } - luaspell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); if (!(luaspell->effect_bitmask & EFFECT_FLAG_SPELLBONUS)) luaspell->effect_bitmask += EFFECT_FLAG_SPELLBONUS; } @@ -2599,22 +2587,20 @@ int EQ2Emu_lua_RemoveSpellBonus(lua_State* state) { else if (luaspell && luaspell->spell) { ZoneServer* zone = nullptr; if (luaspell->caster != nullptr) - zone = luaspell->caster->GetZone(); + zone = luaspell->zone; if(!zone && spawn) { zone = spawn->GetZone(); // workaround to try to establish a zone to find the targets and remove the spells } Spawn* target = 0; if(zone) { - luaspell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - for (int32 i = 0; i < luaspell->targets.size(); i++) { - target = zone->GetSpawnByID(luaspell->targets[i]); + for (int32 id : luaspell->GetTargets()) { + target = zone->GetSpawnByID(id); if (target && target->IsEntity()) { ((Entity*)target)->RemoveSpellBonus(luaspell); if (target->IsPlayer()) ((Player*)target)->SetCharSheetChanged(true); } } - luaspell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); } else { LogWrite(LUA__ERROR, 0, "LUA", "Error removing spell bonus buff %s called by %s, zone is not available.", luaspell->spell ? luaspell->spell->GetName() : "NotSet", spawn ? spawn->GetName() : "N/A"); @@ -2638,11 +2624,10 @@ int EQ2Emu_lua_AddSkillBonus(lua_State* state) { return 0; } spell_id = luaspell->spell->GetSpellID(); - ZoneServer* zone = luaspell->caster->GetZone(); + ZoneServer* zone = luaspell->zone; Spawn* target = 0; - luaspell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - for (int32 i = 0; i < luaspell->targets.size(); i++) { - target = zone->GetSpawnByID(luaspell->targets[i]); + for (int32 id : luaspell->GetTargets()) { + target = zone->GetSpawnByID(id); if (target && target->Alive()) { if (target->IsPlayer()) { ((Player*)target)->AddSkillBonus(spell_id, skill_id, value); @@ -2664,7 +2649,6 @@ int EQ2Emu_lua_AddSkillBonus(lua_State* state) { LogWrite(LUA__ERROR, 0, "LUA", "Error applying bonus buff on '%s'. Not a NPC or player.", target->GetName()); } } - luaspell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); } else if (spawn) { if (spawn->IsPlayer()) { @@ -2699,11 +2683,10 @@ int EQ2Emu_lua_RemoveSkillBonus(lua_State* state) { return 0; } spell_id = luaspell->spell->GetSpellID(); - ZoneServer* zone = luaspell->caster->GetZone(); + ZoneServer* zone = luaspell->zone; Spawn* target = 0; - luaspell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - for (int32 i = 0; i < luaspell->targets.size(); i++) { - target = zone->GetSpawnByID(luaspell->targets[i]); + for (int32 id : luaspell->GetTargets()) { + target = zone->GetSpawnByID(id); if (target) { if (target->IsPlayer()) { ((Player*)target)->RemoveSkillBonus(spell_id); @@ -2720,7 +2703,6 @@ int EQ2Emu_lua_RemoveSkillBonus(lua_State* state) { LogWrite(LUA__ERROR, 0, "LUA", "Error removing skill bonus on '%s'. Not a NPC or player.", spawn->GetName()); } } - luaspell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); } else if (spawn) { if (spawn->IsPlayer()) { @@ -2754,11 +2736,10 @@ int EQ2Emu_lua_AddControlEffect(lua_State* state) { } if (!only_add_spawn && luaspell && luaspell->spell && luaspell->caster && type != 0) { - ZoneServer* zone = luaspell->caster->GetZone(); + ZoneServer* zone = luaspell->zone; Spawn* target = 0; - luaspell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - for (int32 i = 0; i < luaspell->targets.size(); i++) { - target = zone->GetSpawnByID(luaspell->targets[i]); + for (int32 id : luaspell->GetTargets()) { + target = zone->GetSpawnByID(id); if (target && target->IsEntity()) { if (type == CONTROL_EFFECT_TYPE_MEZ) { ((Entity*)target)->AddMezSpell(luaspell); @@ -2840,7 +2821,6 @@ int EQ2Emu_lua_AddControlEffect(lua_State* state) { else lua_interface->LogError("%s: Error applying control effect on non entity '%s'.", lua_interface->GetScriptName(state), (target != nullptr) ? target->GetName() : "NO_TARGET"); } - luaspell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); } else if (only_add_spawn && spawn && spawn->IsEntity()) { if (type == CONTROL_EFFECT_TYPE_MEZ) { @@ -2921,11 +2901,10 @@ int EQ2Emu_lua_RemoveControlEffect(lua_State* state) { lua_interface->ResetFunctionStack(state); if (spawn && spawn->IsEntity()) { if (!only_remove_spawn && luaspell && luaspell->spell && luaspell->caster) { - ZoneServer* zone = luaspell->caster->GetZone(); + ZoneServer* zone = luaspell->zone; Spawn* target = 0; - luaspell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - for (int32 i = 0; i < luaspell->targets.size(); i++) { - target = zone->GetSpawnByID(luaspell->targets[i]); + for (int32 id : luaspell->GetTargets()) { + target = zone->GetSpawnByID(id); if (target) { if (type == CONTROL_EFFECT_TYPE_MEZ) ((Entity*)target)->RemoveMezSpell(luaspell); @@ -2955,7 +2934,6 @@ int EQ2Emu_lua_RemoveControlEffect(lua_State* state) { lua_interface->LogError("%s: Unhandled control effect type of %u.", lua_interface->GetScriptName(state), type); } } - luaspell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); } else if (only_remove_spawn) { if (type == CONTROL_EFFECT_TYPE_MEZ) @@ -6578,10 +6556,9 @@ int EQ2Emu_lua_AddWard(lua_State* state) { bool ward_was_added = false; - ZoneServer* zone = spell->caster->GetZone(); - spell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - for (int32 i = 0; i < spell->targets.size(); i++) { - Spawn* target = zone->GetSpawnByID(spell->targets.at(i)); + ZoneServer* zone = spell->zone; + for (int32 id : spell->GetTargets()) { + Spawn* target = zone->GetSpawnByID(id); if (!target) continue; if (target->IsEntity()) { @@ -6629,7 +6606,6 @@ int EQ2Emu_lua_AddWard(lua_State* state) { ward_was_added = true; } } - spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); if (ward_was_added && spell->caster->IsPlayer()) { spell->had_dmg_remaining = true; @@ -6651,23 +6627,25 @@ int EQ2Emu_lua_AddToWard(lua_State* state) { if(!spell || spell->resisted) { return 0; } - ZoneServer* zone = spell->caster->GetZone(); - spell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - if (spell->targets.size() > 0 && zone->GetSpawnByID(spell->targets.at(0))->IsEntity()) { - Entity* target = (Entity*)zone->GetSpawnByID(spell->targets.at(0)); + if(!spell->caster || !spell->zone) { + return 0; + } + ZoneServer* zone = spell->zone; + Entity* target = nullptr; + if (auto target_id_opt = spell->GetPrimaryTarget(); + target_id_opt && (target = (Entity*)zone->GetSpawnByID(*target_id_opt))) { ward = target->GetWard(spell->spell->GetSpellID()); if (target && ward) { ward->DamageLeft += amount; if (ward->DamageLeft > ward->BaseDamage) ward->DamageLeft = ward->BaseDamage; - for (int32 i = 0; i < spell->targets.size(); i++) { - if (Spawn* spawn = zone->GetSpawnByID(spell->targets.at(i))) + for (int32 id : spell->GetTargets()) { + if (Spawn* spawn = zone->GetSpawnByID(id)) zone->SendHealPacket(ward->Spell->caster, spawn, HEAL_PACKET_TYPE_REGEN_ABSORB, amount, ward->Spell->spell->GetName()); } } } - spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); if (ward && spell->caster->IsPlayer()) ClientPacketFunctions::SendMaintainedExamineUpdate(((Player*)spell->caster)->GetClient(), spell->slot_pos, ward->DamageLeft, 1); @@ -6686,17 +6664,15 @@ int EQ2Emu_lua_GetWardAmountLeft(lua_State* state) { return 0; } - spell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - if (spell->caster && spell->caster->GetZone() && spell->targets.size() > 0 && spell->caster->GetZone()->GetSpawnByID(spell->targets.at(0))->IsEntity()) { - Entity* target = (Entity*)spell->caster->GetZone()->GetSpawnByID(spell->targets.at(0)); + Entity* target = nullptr; + if (auto target_id_opt = spell->GetPrimaryTarget(); + target_id_opt && spell->zone && (target = (Entity*)spell->zone->GetSpawnByID(*target_id_opt))) { WardInfo* ward = target->GetWard(spell->spell->GetSpellID()); if (ward) { lua_interface->SetInt32Value(state, ward->DamageLeft); - spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); return 1; } } - spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); return 0; } @@ -6714,11 +6690,9 @@ int EQ2Emu_lua_GetWardValue(lua_State* state) { string type = lua_interface->GetStringValue(state, 2); lua_interface->ResetFunctionStack(state); - - spell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - if (spell->caster && spell->caster->GetZone() && spell->targets.size() > 0 && spell->caster->GetZone()->GetSpawnByID(spell->targets.at(0))->IsEntity()) { - - Entity* target = (Entity*)spell->caster->GetZone()->GetSpawnByID(spell->targets.at(0)); + Entity* target = nullptr; + if (auto target_id_opt = spell->GetPrimaryTarget(); + target_id_opt && spell->zone && (target = (Entity*)spell->zone->GetSpawnByID(*target_id_opt))) { WardInfo* ward = target->GetWard(spell->spell->GetSpellID()); if (ward) { if (boost::iequals(type, "damageleft")) @@ -6745,12 +6719,9 @@ int EQ2Emu_lua_GetWardValue(lua_State* state) { lua_interface->SetInt32Value(state, ward->MaxHitCount); else lua_interface->LogError("%s: LUA GetWardValue command argument type '%s' did not match any options", lua_interface->GetScriptName(state), type.c_str()); - - spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); return 1; } } - spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); return 0; } @@ -6770,21 +6741,19 @@ int EQ2Emu_lua_RemoveWard(lua_State* state) { return 0; } - ZoneServer* zone = spell->caster->GetZone(); + ZoneServer* zone = spell->zone; if(!zone) { lua_interface->LogError("%s: RemoveWard error: no valid zone for caster", lua_interface->GetScriptName(state)); return 0; } Spawn* target = 0; - spell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - for (int32 i = 0; i < spell->targets.size(); i++) { - target = zone->GetSpawnByID(spell->targets.at(i)); + for (int32 id : spell->GetTargets()) { + target = zone->GetSpawnByID(id); if (target && target->IsEntity()) { ((Entity*)target)->RemoveWard(spell->spell->GetSpellID()); } } - spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); return 0; } @@ -6824,15 +6793,13 @@ int EQ2Emu_lua_Interrupt(lua_State* state) } if (!target && spell) { - spell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - for (int8 i = 0; i < spell->targets.size(); i++) { - target = caster->GetZone()->GetSpawnByID(spell->targets.at(i)); + for (int32 id : spell->GetTargets()) { + target = caster->GetZone()->GetSpawnByID(id); if (!target || !target->IsEntity()) continue; ((Entity*)target)->GetZone()->GetSpellProcess()->Interrupted((Entity*)target, caster, SPELL_ERROR_INTERRUPTED); } - spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); } else caster->GetZone()->GetSpellProcess()->Interrupted((Entity*)target, caster, SPELL_ERROR_INTERRUPTED); @@ -6854,7 +6821,7 @@ int EQ2Emu_lua_Stealth(lua_State* state) { return 0; } - ZoneServer* zone = spell->caster->GetZone(); + ZoneServer* zone = spell->zone; if (spawn) { if (spawn->IsEntity()) { @@ -6876,9 +6843,8 @@ int EQ2Emu_lua_Stealth(lua_State* state) { } } else { - spell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - for (int32 i = 0; i < spell->targets.size(); i++) { - spawn = zone->GetSpawnByID(spell->targets.at(i)); + for (int32 id : spell->GetTargets()) { + spawn = zone->GetSpawnByID(id); if (!spawn || !spawn->IsEntity()) continue; @@ -6897,7 +6863,6 @@ int EQ2Emu_lua_Stealth(lua_State* state) { break; } } - spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); } return 0; } @@ -7237,16 +7202,14 @@ int EQ2Emu_lua_PlayAnimationString(lua_State* state) { return 0; } - if (spell && spell->caster && spell->caster->GetZone() && use_all_spelltargets) { + if (spell && spell->zone && use_all_spelltargets) { Spawn* target; - spell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - for (int8 i = 0; i < spell->targets.size(); i++) { - target = spell->caster->GetZone()->GetSpawnByID(spell->targets.at(i)); + for (int32 id : spell->GetTargets()) { + target = spell->zone->GetSpawnByID(id); if(target && (!ignore_self || spawn != target)) { - spell->caster->GetZone()->HandleEmote(target, name, opt_target, set_no_target); + spell->zone->HandleEmote(target, name, opt_target, set_no_target); } } - spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); } else { spawn->GetZone()->HandleEmote(spawn, name, opt_target, set_no_target); @@ -8732,17 +8695,15 @@ int EQ2Emu_lua_AddProc(lua_State* state) { return 0; } - if (spell && spell->caster && spell->caster->GetZone() && use_all_spelltargets) { + if (spell && spell->zone && use_all_spelltargets) { Spawn* target; - spell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - for (int8 i = 0; i < spell->targets.size(); i++) { - target = spell->caster->GetZone()->GetSpawnByID(spell->targets.at(i)); + for (int32 id : spell->GetTargets()) { + target = spell->zone->GetSpawnByID(id); if (!target || !target->IsEntity()) continue; ((Entity*)target)->AddProc(type, chance, item, spell); } - spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); } else ((Entity*)spawn)->AddProc(type, chance, item, spell); @@ -8788,17 +8749,15 @@ int EQ2Emu_lua_AddProcExt(lua_State* state) { return 0; } - if (spell && spell->caster && spell->caster->GetZone() && use_all_spelltargets) { + if (spell && spell->zone && use_all_spelltargets) { Spawn* target; - spell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - for (int8 i = 0; i < spell->targets.size(); i++) { - target = spell->caster->GetZone()->GetSpawnByID(spell->targets.at(i)); + for (int32 id : spell->GetTargets()) { + target = spell->zone->GetSpawnByID(id); if (!target || !target->IsEntity()) continue; ((Entity*)target)->AddProc(type, chance, item, spell, damage_type, hp_ratio, below_health, target_health, extended_version); } - spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); } else ((Entity*)spawn)->AddProc(type, chance, item, spell); @@ -8827,17 +8786,15 @@ int EQ2Emu_lua_RemoveProc(lua_State* state) { if(spawn && spawn->IsEntity()) { ((Entity*)spawn)->RemoveProc(item, spell); } - else if (spell && spell->caster && spell->caster->GetZone()) { + else if (spell && spell->zone) { Spawn* target; - spell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - for (int8 i = 0; i < spell->targets.size(); i++) { - target = spell->caster->GetZone()->GetSpawnByID(spell->targets.at(i)); + for (int32 id : spell->GetTargets()) { + target = spell->zone->GetSpawnByID(id); if (!target || !target->IsEntity()) continue; ((Entity*)target)->RemoveProc(item, spell); } - spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); spell->caster->RemoveProc(item, spell); } else if (!spawn) { @@ -9180,7 +9137,7 @@ int EQ2Emu_lua_AddSpellTimer(lua_State* state) { return 0; } - if (!spell || (!spell->caster || !spell->caster->GetZone())) { + if (!spell || (!spell->caster || !spell->zone)) { lua_interface->LogError("%s: LUA AddSpellTimer command error: spell not found, AddSpellTimer must be used in a spell script", lua_interface->GetScriptName(state)); return 0; } @@ -9206,7 +9163,7 @@ int EQ2Emu_lua_AddSpellTimer(lua_State* state) { if (target) timer->target = target->GetID(); - spell->caster->GetZone()->GetSpellProcess()->AddSpellScriptTimer(timer); + spell->zone->GetSpellProcess()->AddSpellScriptTimer(timer); return 0; } @@ -9232,65 +9189,59 @@ int EQ2Emu_lua_Resurrect(lua_State* state) { } Entity* caster = spell->caster; - if (!caster) { - lua_interface->LogError("%s: LUA command error: could not find caster", lua_interface->GetScriptName(state)); + if (!caster || !caster->GetZone()) { + lua_interface->LogError("%s: LUA command error: could not find caster or caster has no zone", lua_interface->GetScriptName(state)); return 0; } Client* client = 0; PendingResurrection* rez = 0; - ZoneServer* zone = spell->caster->GetZone(); + ZoneServer* zone = spell->zone; if (!target) { - spell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - if (spell->targets.size() > 0) { - vector spell_targets = spell->targets; - for (int8 i = 0; i < spell_targets.size(); i++) { - target = zone->GetSpawnByID(spell_targets.at(i)); - if (!target) - continue; - if (!target->IsPlayer()) - continue; + for (int32 id : spell->GetTargets()) { + target = zone->GetSpawnByID(id); + if (!target) + continue; + if (!target->IsPlayer()) + continue; - client = ((Player*)target)->GetClient(); + client = ((Player*)target)->GetClient(); - if (!client) - continue; + if (!client) + continue; - rez = client->GetCurrentRez(); - if (rez->active) - continue; - - client->GetResurrectMutex()->writelock(__FUNCTION__, __LINE__); - rez->active = true; - rez->caster = caster->GetID(); - rez->expire_timer = new Timer; - int32 duration = spell->spell->GetSpellDuration(); - rez->expire_timer->Start(duration * 100); - rez->hp_perc = hp_perc; - rez->mp_perc = power_perc; - rez->range = spell->spell->GetSpellData()->range; - rez->spell_name = spell->spell->GetName(); - if (heal_name.length() > 0) - rez->heal_name = heal_name; - else - rez->heal_name = rez->spell_name; - rez->orig_spell_id = spell->spell->GetSpellID(); - rez->orig_spell_tier = spell->spell->GetSpellTier(); - rez->revive_sickness_spell_id = revive_spell_id; - rez->revive_sickness_spell_tier = revive_spell_tier; - rez->no_calcs = no_calcs; - rez->crit_mod = crit_mod; - rez->spell_visual = spell->spell->GetSpellData()->spell_visual; - if (send_window) - client->SendResurrectionWindow(); - else { - target->GetZone()->ResurrectSpawn(target, client); - rez->should_delete = true; - } - client->GetResurrectMutex()->releasewritelock(__FUNCTION__, __LINE__); + rez = client->GetCurrentRez(); + if (rez->active) + continue; + client->GetResurrectMutex()->writelock(__FUNCTION__, __LINE__); + rez->active = true; + rez->caster = caster->GetID(); + rez->expire_timer = new Timer; + int32 duration = spell->spell->GetSpellDuration(); + rez->expire_timer->Start(duration * 100); + rez->hp_perc = hp_perc; + rez->mp_perc = power_perc; + rez->range = spell->spell->GetSpellData()->range; + rez->spell_name = spell->spell->GetName(); + if (heal_name.length() > 0) + rez->heal_name = heal_name; + else + rez->heal_name = rez->spell_name; + rez->orig_spell_id = spell->spell->GetSpellID(); + rez->orig_spell_tier = spell->spell->GetSpellTier(); + rez->revive_sickness_spell_id = revive_spell_id; + rez->revive_sickness_spell_tier = revive_spell_tier; + rez->no_calcs = no_calcs; + rez->crit_mod = crit_mod; + rez->spell_visual = spell->spell->GetSpellData()->spell_visual; + if (send_window) + client->SendResurrectionWindow(); + else { + target->GetZone()->ResurrectSpawn(target, client); + rez->should_delete = true; } + client->GetResurrectMutex()->releasewritelock(__FUNCTION__, __LINE__); } - spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); } else { if(!target->IsPlayer()) @@ -9357,10 +9308,10 @@ int EQ2Emu_lua_SetVision(lua_State* state) { return 0; } - if (spell && spell->targets.size() > 0) { - ZoneServer* zone = spell->caster->GetZone(); - for (int8 i = 0; i < spell->targets.size(); i++) { - Spawn* target = zone->GetSpawnByID(spell->targets.at(i)); + if (spell && spell->GetTargetCount() > 0) { + ZoneServer* zone = spell->zone; + for (int32 id : spell->GetTargets()) { + Spawn* target = zone->GetSpawnByID(id); if (target && target->IsEntity()) { ((Entity*)target)->GetInfoStruct()->set_vision(vision); if (target->IsPlayer()) @@ -9395,10 +9346,10 @@ int EQ2Emu_lua_BlurVision(lua_State* state) { return 0; } - if (spell && spell->targets.size() > 0) { - ZoneServer* zone = spell->caster->GetZone(); - for (int8 i = 0; i < spell->targets.size(); i++) { - Spawn* target = zone->GetSpawnByID(spell->targets.at(i)); + if (spell && spell->GetTargetCount() > 0) { + ZoneServer* zone = spell->zone; + for (int32 id : spell->GetTargets()) { + Spawn* target = zone->GetSpawnByID(id); if (target && target->IsEntity()) { ((Entity*)target)->GetInfoStruct()->set_drunk(intensity); if (target->IsPlayer()) @@ -9433,10 +9384,10 @@ int EQ2Emu_lua_BreatheUnderwater(lua_State* state) { return 0; } - if (spell && spell->targets.size() > 0) { - ZoneServer* zone = spell->caster->GetZone(); - for (int8 i = 0; i < spell->targets.size(); i++) { - Spawn* target = zone->GetSpawnByID(spell->targets.at(i)); + if (spell && spell->GetTargetCount() > 0) { + ZoneServer* zone = spell->zone; + for (int32 id : spell->GetTargets()) { + Spawn* target = zone->GetSpawnByID(id); if (target && target->IsEntity()) { ((Entity*)target)->GetInfoStruct()->set_breathe_underwater(breatheUnderwater); if (target->IsPlayer()) @@ -9488,10 +9439,10 @@ int EQ2Emu_lua_SetSpeedMultiplier(lua_State* state) { if (val > 1.0f) val = 1.0f - (val / 100.0f); - if (spell && spell->spell && spell->targets.size() > 0) { - ZoneServer* zone = spell->caster->GetZone(); - for (int32 i = 0; i != spell->targets.size(); i++) { - Spawn* spawn = zone->GetSpawnByID(spell->targets.at(i)); + if (spell && spell->spell && spell->GetTargetCount() > 0) { + ZoneServer* zone = spell->zone; + for (int32 id : spell->GetTargets()) { + Spawn* spawn = zone->GetSpawnByID(id); if (spawn && spawn->IsEntity()) { ((Entity*)spawn)->SetSpeedMultiplier(val); if (spawn->IsPlayer()) @@ -9519,10 +9470,10 @@ int EQ2Emu_lua_SetIllusion(lua_State* state) { LuaSpell* spell = lua_interface->GetCurrentSpell(state); lua_interface->ResetFunctionStack(state); - if (spell && spell->spell && spell->targets.size() > 0) { - ZoneServer* zone = spell->caster->GetZone(); - for (int32 i = 0; i < spell->targets.size(); i++) { - Spawn* target = zone->GetSpawnByID(spell->targets.at(i)); + if (spell && spell->spell && spell->GetTargetCount() > 0) { + ZoneServer* zone = spell->zone; + for (int32 id : spell->GetTargets()) { + Spawn* target = zone->GetSpawnByID(id); if (target) target->SetIllusionModel(model); } @@ -9547,10 +9498,10 @@ int EQ2Emu_lua_ResetIllusion(lua_State* state) { LuaSpell* spell = lua_interface->GetCurrentSpell(state); lua_interface->ResetFunctionStack(state); - if (spell && spell->spell && spell->targets.size() > 0) { - ZoneServer* zone = spell->caster->GetZone(); - for (int32 i = 0; i < spell->targets.size(); i++) { - Spawn* target = zone->GetSpawnByID(spell->targets.at(i)); + if (spell && spell->spell && spell->GetTargetCount() > 0) { + ZoneServer* zone = spell->zone; + for (int32 id : spell->GetTargets()) { + Spawn* target = zone->GetSpawnByID(id); if (target) target->SetIllusionModel(0); } @@ -9694,13 +9645,11 @@ int EQ2Emu_lua_CureByType(lua_State* state) { } } else { - ZoneServer* zone = spell->caster->GetZone(); + ZoneServer* zone = spell->zone; vector targets = spell->targets; vector targets_to_cure; - spell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - for (int8 i = 0; i < targets.size(); i++) { - target = zone->GetSpawnByID(targets.at(i)); - + for (int32 id : spell->GetTargets()) { + target = zone->GetSpawnByID(id); if (!target || !target->IsEntity()) continue; @@ -9708,7 +9657,6 @@ int EQ2Emu_lua_CureByType(lua_State* state) { targets_to_cure.push_back((Entity*)target); } } - spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); vector::iterator itr; for(itr = targets_to_cure.begin(); itr != targets_to_cure.end(); itr++) { @@ -9746,12 +9694,9 @@ int EQ2Emu_lua_CureByControlEffect(lua_State* state) { ((Entity*)target)->CureDetrimentByControlEffect(cure_count, cure_type, cure_name.length() > 0 ? cure_name : (string)spell->spell->GetName(), spell->caster, cure_level); } else { - ZoneServer* zone = spell->caster->GetZone(); - vector targets = spell->targets; - - spell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - for (int8 i = 0; i < targets.size(); i++) { - target = zone->GetSpawnByID(targets.at(i)); + ZoneServer* zone = spell->zone; + for (int32 id : spell->GetTargets()) { + target = zone->GetSpawnByID(id); if (!target || !target->IsEntity()) continue; @@ -9759,7 +9704,6 @@ int EQ2Emu_lua_CureByControlEffect(lua_State* state) { if (((Entity*)target)->GetDetCount() > 0) ((Entity*)target)->CureDetrimentByControlEffect(cure_count, cure_type, cure_name.length() > 0 ? cure_name : (string)spell->spell->GetName(), spell->caster, cure_level); } - spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); } return 0; } @@ -9781,12 +9725,12 @@ int EQ2Emu_lua_CancelSpell(lua_State* state) { return 0; } - if (!spell->caster->GetZone()) { + if (!spell->zone) { lua_interface->LogError("%s: LUA CancelSpell command error: unable to get the zone of the caster", lua_interface->GetScriptName(state)); return 0; } - spell->caster->GetZone()->GetSpellProcess()->AddSpellCancel(spell); + spell->zone->GetSpellProcess()->AddSpellCancel(spell); return 0; } @@ -9807,16 +9751,14 @@ int EQ2Emu_lua_RemoveStealth(lua_State* state) { if (spawn && spawn->IsEntity()) ((Entity*)spawn)->RemoveStealthSpell(spell); else { - ZoneServer* zone = spell->caster->GetZone(); - spell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - for (int32 i = 0; i < spell->targets.size(); i++) { - spawn = zone->GetSpawnByID(spell->targets.at(i)); + ZoneServer* zone = spell->zone; + for (int32 id : spell->GetTargets()) { + spawn = zone->GetSpawnByID(id); if (!spawn || !spawn->IsEntity()) continue; ((Entity*)spawn)->RemoveStealthSpell(spell); } - spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); } return 0; } @@ -9837,16 +9779,14 @@ int EQ2Emu_lua_RemoveInvis(lua_State* state) { if (spawn && spawn->IsEntity()) ((Entity*)spawn)->RemoveInvisSpell(spell); else { - ZoneServer* zone = spell->caster->GetZone(); - spell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - for (int32 i = 0; i < spell->targets.size(); i++) { - spawn = zone->GetSpawnByID(spell->targets.at(i)); + ZoneServer* zone = spell->zone; + for (int32 id : spell->GetTargets()) { + spawn = zone->GetSpawnByID(id); if (!spawn || !spawn->IsEntity()) continue; ((Entity*)spawn)->RemoveInvisSpell(spell); } - spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); } return 0; } @@ -9973,7 +9913,7 @@ int EQ2Emu_lua_RemoveTriggerFromSpell(lua_State* state) { return 0; } - if (!spell->caster || !spell->caster->GetZone()) { + if (!spell->caster || !spell->zone) { lua_interface->LogError("%s: LUA RemoveTriggerFromSpell command error: caster / caster zone must be set!", lua_interface->GetScriptName(state)); lua_interface->ResetFunctionStack(state); return 0; @@ -9989,7 +9929,7 @@ int EQ2Emu_lua_RemoveTriggerFromSpell(lua_State* state) { if (remove_count >= spell->num_triggers) { spell->num_triggers = 0; if (spell->cancel_after_all_triggers) - spell->caster->GetZone()->GetSpellProcess()->AddSpellCancel(spell); + spell->zone->GetSpellProcess()->AddSpellCancel(spell); } else { spell->num_triggers -= remove_count; @@ -10064,16 +10004,14 @@ int EQ2Emu_lua_AddImmunitySpell(lua_State* state) { Entity* entity = ((Entity*)spawn); entity->AddImmunity(spell, type); } - else if(spell->caster && spell->caster->GetZone()) { - spell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - for (int8 i = 0; i < spell->targets.size(); i++) { - spawn = spell->caster->GetZone()->GetSpawnByID(spell->targets.at(i)); + else if(spell->zone) { + for (int32 id : spell->GetTargets()) { + spawn = spell->zone->GetSpawnByID(id); if (!spawn || !spawn->IsEntity()) continue; Entity* entity = ((Entity*)spawn); entity->AddImmunity(spell, type); } - spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); } return 0; @@ -10101,16 +10039,14 @@ int EQ2Emu_lua_RemoveImmunitySpell(lua_State* state) { Entity* entity = ((Entity*)spawn); entity->RemoveImmunity(spell, type); } - else if(spell->caster && spell->caster->GetZone()) { - spell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - for (int8 i = 0; i < spell->targets.size(); i++) { - spawn = spell->caster->GetZone()->GetSpawnByID(spell->targets.at(i)); + else if(spell->zone) { + for (int32 id : spell->GetTargets()) { + spawn = spell->zone->GetSpawnByID(id); if (!spawn || !spawn->IsEntity()) continue; Entity* entity = ((Entity*)spawn); entity->RemoveImmunity(spell, type); } - spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); } return 0; @@ -10142,16 +10078,14 @@ int EQ2Emu_lua_SetSpellSnareValue(lua_State* state) { ((Entity*)spawn)->SetSnareValue(spell, val); } - else if(spell && spell->caster && spell->caster->GetZone()) { - spell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - for (int8 i = 0; i < spell->targets.size(); i++) { - spawn = spell->caster->GetZone()->GetSpawnByID(spell->targets.at(i)); + else if(spell && spell->zone) { + for (int32 id : spell->GetTargets()) { + spawn = spell->zone->GetSpawnByID(id); if (!spawn || !spawn->IsEntity()) continue; ((Entity*)spawn)->SetSnareValue(spell, val); } - spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); } return 0; @@ -11355,18 +11289,18 @@ int EQ2Emu_lua_Evac(lua_State* state) { else { LuaSpell* spell = lua_interface->GetCurrentSpell(state); - - if(!spell || !spell->caster || !spell->caster->GetZone()) { + + if(!spell || !spell->caster || !spell->zone) { lua_interface->ResetFunctionStack(state); return 0; } + + ZoneServer* zone = spell->zone; - ZoneServer* zone = spell->caster->GetZone(); - - float x = spell->caster->GetZone()->GetSafeX(); - float y = spell->caster->GetZone()->GetSafeY(); - float z = spell->caster->GetZone()->GetSafeZ(); - float h = spell->caster->GetZone()->GetSafeHeading(); + float x = spell->zone->GetSafeX(); + float y = spell->zone->GetSafeY(); + float z = spell->zone->GetSafeZ(); + float h = spell->zone->GetSafeHeading(); int numargs = lua_interface->GetNumberOfArgs(state); @@ -11376,12 +11310,11 @@ int EQ2Emu_lua_Evac(lua_State* state) { z = lua_interface->GetFloatValue(state,3); h = lua_interface->GetFloatValue(state,4); } - + lua_interface->ResetFunctionStack(state); - - spell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - for (int32 i = 0; i < spell->targets.size(); i++) { - Spawn* target2 = zone->GetSpawnByID(spell->targets.at(i)); + + for (int32 id : spell->GetTargets()) { + Spawn* target2 = zone->GetSpawnByID(id); if (!target2) continue; @@ -11389,7 +11322,7 @@ int EQ2Emu_lua_Evac(lua_State* state) { Client* client = ((Player*)target2)->GetClient(); if (client) { client->GetCurrentZone()->ClearHate(client->GetPlayer()); - + client->SetReloadingZone(true); target2->SetX(x); target2->SetY(y); @@ -11402,9 +11335,9 @@ int EQ2Emu_lua_Evac(lua_State* state) { target2->SetSpawnOrigHeading(h); target2->SetAppearancePosition(x,y,z); - + client->SetZoningCoords(x,y,z,h); - + PacketStruct* packet = configReader.getStruct("WS_TeleportWithinZone", client->GetVersion()); if (packet) { @@ -11414,14 +11347,12 @@ int EQ2Emu_lua_Evac(lua_State* state) { client->QueuePacket(packet->serialize()); safe_delete(packet); } - client->GetCurrentZone()->RemoveSpawn(target2, false, false, true, true); client->GetPlayer()->SetSpawnSentState(target2, SpawnState::SPAWN_STATE_SENT); } } } - spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); } return 0; @@ -12367,10 +12298,10 @@ int EQ2Emu_lua_SetAlignment(lua_State* state) { lua_interface->ResetFunctionStack(state); - if (spell && spell->targets.size() > 0) { - ZoneServer* zone = spell->caster->GetZone(); - for (int8 i = 0; i < spell->targets.size(); i++) { - Spawn* target = zone->GetSpawnByID(spell->targets.at(i)); + if (spell && spell->GetTargetCount() > 0) { + ZoneServer* zone = spell->zone; + for (int32 id : spell->GetTargets()) { + Spawn* target = zone->GetSpawnByID(id); if (target && target->IsEntity()) { ((Entity*)target)->GetInfoStruct()->set_alignment((sint8)alignment); if (target->IsPlayer()) @@ -14367,11 +14298,11 @@ int EQ2Emu_lua_GetSpellInitialTarget(lua_State* state) { lua_interface->LogError("%s: LUA GetSpellInitialTarget command error, caster does not exist.", lua_interface->GetScriptName(state)); return 0; } - if(!spell->caster->GetZone()) { + if(!spell->zone) { lua_interface->LogError("%s: LUA GetSpellInitialTarget command error, zone does not exist.", lua_interface->GetScriptName(state)); return 0; } - Spawn* spawn = spell->caster->GetZone()->GetSpawnByID(spell->initial_target); + Spawn* spawn = spell->zone->GetSpawnByID(spell->initial_target); if (spawn) { lua_interface->SetSpawnValue(state, spawn); return 1; @@ -14439,22 +14370,23 @@ int EQ2Emu_lua_GetSpellTargets(lua_State* state) { lua_interface->LogError("%s: LUA GetSpellTargets command error, caster does not exist.", lua_interface->GetScriptName(state)); return 0; } - if(!spell->caster->GetZone()) { + if(!spell->zone) { lua_interface->LogError("%s: LUA GetSpellTargets command error, zone does not exist.", lua_interface->GetScriptName(state)); return 0; } - if (spell && spell->caster) { - ZoneServer* zone = spell->caster->GetZone(); - spell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - lua_createtable(state, spell->targets.size(), 0); + if (spell) { + ZoneServer* zone = spell->zone; + std::vector targets = spell->GetTargets(); // snapshot under lock + lua_createtable(state, targets.size(), 0); // preallocate array size int newTable = lua_gettop(state); - for (int32 i = 0; i < spell->targets.size(); i++) { - Spawn* spawn = zone->GetSpawnByID(spell->targets.at(i)); + + int i = 0; + for (int32_t id : targets) { + Spawn* spawn = zone->GetSpawnByID(id); lua_interface->SetSpawnValue(state, spawn); - lua_rawseti(state, newTable, i + 1); + lua_rawseti(state, newTable, ++i); // Lua is 1-indexed } - spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); return 1; } } diff --git a/source/WorldServer/LuaInterface.cpp b/source/WorldServer/LuaInterface.cpp index 94445ce..46371bc 100644 --- a/source/WorldServer/LuaInterface.cpp +++ b/source/WorldServer/LuaInterface.cpp @@ -879,6 +879,9 @@ void LuaInterface::RemoveSpawnFromSpell(LuaSpell* spell, Spawn* spawn) { ((Entity*)spawn)->RemoveSpellBonus(spell); ((Entity*)spawn)->RemoveEffectsFromLuaSpell(spell); ((Entity*)spawn)->RemoveWard(spell); + + if(spell->spell->GetSpellData()->det_type > 0 && (spell->spell->GetSpellDuration() > 0 || spell->spell->GetSpellData()->duration_until_cancel)) + ((Entity*)spawn)->RemoveDetrimentalSpell(spell); } } @@ -959,32 +962,27 @@ void LuaInterface::RemoveSpell(LuaSpell* spell, bool call_remove_function, bool return; } - spell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - for (int8 i = 0; i < spell->targets.size(); i++) { + for (int32 id : spell->GetTargets()) { if(!spell->zone) break; - Spawn* target = spell->zone->GetSpawnByID(spell->targets.at(i)); + Spawn* target = spell->zone->GetSpawnByID(id); if (!target || !target->IsEntity()) continue; RemoveSpawnFromSpell(spell, target); } - - multimap::iterator entries; - for(entries = spell->char_id_targets.begin(); entries != spell->char_id_targets.end(); entries++) - { - Client* tmpClient = zone_list.GetClientByCharID(entries->first); + + for (const auto& [char_id, pet_type] : spell->GetCharIDTargets()) { + Client* tmpClient = zone_list.GetClientByCharID(char_id); if(tmpClient && tmpClient->GetPlayer()) { RemoveSpawnFromSpell(spell, tmpClient->GetPlayer()); } } - spell->char_id_targets.clear(); // TODO: reach out to those clients in different + spell->ClearCharTargets(); // TODO: reach out to those clients in different spell->timer.Disable(); - - spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); if(removing_all_spells) { if(spell->zone && spell->zone->GetSpellProcess()) { @@ -1735,10 +1733,8 @@ void LuaInterface::DeletePendingSpells(bool all) { if(!all) { // rely on targets the spell->caster could be corrupt - if(spell->targets.size() > 0) { - spell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - for (int8 i = 0; i < spell->targets.size(); i++) { - Spawn* target = spell->zone->GetSpawnByID(spell->targets.at(i)); + for (int32 id : spell->GetTargets()) { + Spawn* target = spell->zone->GetSpawnByID(id); if (!target || !target->IsEntity()) continue; @@ -1746,14 +1742,12 @@ void LuaInterface::DeletePendingSpells(bool all) { RemoveSpawnFromSpell(spell, target); } } - spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); - } if(spell->zone && spell->zone->GetSpellProcess()) { spell->zone->GetSpellProcess()->DeleteActiveSpell(spell, true); } } - + if (spell->spell->IsCopiedSpell()) { RemoveCustomSpell(spell->spell->GetSpellID()); @@ -2160,7 +2154,6 @@ LuaSpell* LuaInterface::LoadSpellScript(const char* name) { spell->interrupted = false; spell->last_spellattack_hit = false; spell->crit = false; - spell->MSpellTargets.SetName("LuaSpell.MSpellTargets"); spell->cancel_after_all_triggers = false; spell->num_triggers = 0; spell->num_calls = 0; @@ -2510,7 +2503,6 @@ LuaSpell* LuaInterface::CreateSpellScript(const char* name, lua_State* existStat new_spell->interrupted = false; new_spell->crit = false; new_spell->last_spellattack_hit = false; - new_spell->MSpellTargets.SetName("LuaSpell.MSpellTargets"); new_spell->cancel_after_all_triggers = false; new_spell->num_triggers = 0; new_spell->num_calls = 0; diff --git a/source/WorldServer/LuaInterface.h b/source/WorldServer/LuaInterface.h index 379f6dd..0148937 100644 --- a/source/WorldServer/LuaInterface.h +++ b/source/WorldServer/LuaInterface.h @@ -78,8 +78,10 @@ struct LuaSpell{ int32 initial_caster_char_id; int32 initial_target; int32 initial_target_char_id; + mutable std::shared_mutex targets_mutex; vector targets; vector removed_targets; // previously cancelled, expired, used, so on + mutable std::shared_mutex char_id_targets_mutex; multimap char_id_targets; Spell* spell; lua_State* state; @@ -99,13 +101,117 @@ struct LuaSpell{ bool cancel_after_all_triggers; bool had_triggers; bool had_dmg_remaining; - Mutex MSpellTargets; Mutex MScriptMutex; int32 effect_bitmask; bool restored; // restored spell cross zone std::atomic has_proc; ZoneServer* zone; int16 initial_caster_level; + + void AddTarget(int32 target_id) { + std::unique_lock lock(targets_mutex); + targets.push_back(target_id); + } + + int32 GetPrimaryTargetID() const { + std::shared_lock lock(targets_mutex); + return targets.empty() ? -1 : targets[0]; + } + + std::optional GetPrimaryTarget() const { + std::shared_lock lock(targets_mutex); + if (!targets.empty()) + return targets[0]; + return std::nullopt; + } + + + std::vector GetTargets() { + std::shared_lock lock(targets_mutex); + return targets; + } + + bool HasNoTargets() const { + std::shared_lock lock(targets_mutex); + return targets.empty(); + } + + int32 GetTargetCount() const { + std::shared_lock lock(targets_mutex); + return static_cast(targets.size()); + } + + bool HasTarget(int32 id) const { + std::shared_lock lock(targets_mutex); + return std::find(targets.begin(), targets.end(), id) != targets.end(); + } + + + std::vector GetRemovedTargets() const { + std::shared_lock lock(targets_mutex); + return removed_targets; + } + + void RemoveTarget(int32 target_id) { + std::unique_lock lock(targets_mutex); + auto& v = targets; + v.erase(std::remove(v.begin(), v.end(), target_id), v.end()); + removed_targets.push_back(target_id); + } + + void AddRemoveTarget(int32 target_id) { + std::unique_lock lock(targets_mutex); + removed_targets.push_back(target_id); + } + + void SwapTargets(std::vector& new_targets) { + std::unique_lock lock(targets_mutex); + targets.swap(new_targets); + } + + void ClearTargets() { + std::unique_lock lock(targets_mutex); + targets.clear(); + removed_targets.clear(); + } + + std::multimap GetCharIDTargets() const { + std::shared_lock lock(char_id_targets_mutex); + return char_id_targets; + } + + void AddCharIDTarget(int32 char_id, int8 value) { + std::unique_lock lock(char_id_targets_mutex); + char_id_targets.insert({char_id, value}); + } + + bool HasNoCharIDTargets() const { + std::shared_lock lock(char_id_targets_mutex); + return char_id_targets.empty(); + } + + void RemoveCharIDTarget(int32 char_id) { + std::unique_lock lock(char_id_targets_mutex); + char_id_targets.erase(char_id); // removes all entries with that key + } + + void RemoveCharIDTargetAndType(int32 char_id, int8 type) { + std::unique_lock lock(char_id_targets_mutex); + + auto range = char_id_targets.equal_range(char_id); + for (auto it = range.first; it != range.second; ++it) { + if (it->second == type) { + char_id_targets.erase(it); + break; // remove only one matching pair + } + } + } + + void ClearCharTargets() { + std::unique_lock lock(char_id_targets_mutex); + char_id_targets.clear(); + } + }; enum class LuaArgType { SINT64, INT64, SINT, INT, FLOAT, STRING, BOOL, SPAWN, ZONE, SKILL, ITEM, QUEST, SPELL /* etc */ }; diff --git a/source/WorldServer/Player.cpp b/source/WorldServer/Player.cpp index 78cbbac..a0e2d25 100644 --- a/source/WorldServer/Player.cpp +++ b/source/WorldServer/Player.cpp @@ -7404,13 +7404,11 @@ void Player::SaveSpellEffects() info->maintained_effects[i].spell->damage_remaining, info->maintained_effects[i].spell->effect_bitmask, info->maintained_effects[i].spell->num_triggers, info->maintained_effects[i].spell->had_triggers, info->maintained_effects[i].spell->cancel_after_all_triggers, info->maintained_effects[i].spell->crit, info->maintained_effects[i].spell->last_spellattack_hit, info->maintained_effects[i].spell->interrupted, info->maintained_effects[i].spell->resisted, info->maintained_effects[i].spell->has_damaged, (info->maintained_effects[i].expire_timestamp) == 0xFFFFFFFF ? "" : database.getSafeEscapeString(spellProcess->SpellScriptTimerCustomFunction(info->maintained_effects[i].spell).c_str()).c_str(), info->maintained_effects[i].spell->initial_caster_level); - info->maintained_effects[i].spell->MSpellTargets.readlock(__FUNCTION__, __LINE__); std::string insertTargets = string("insert into character_spell_effect_targets (caster_char_id, target_char_id, target_type, db_effect_type, spell_id, effect_slot, slot_pos) values "); bool firstTarget = true; map targetsInserted; - for (int8 t = 0; t < info->maintained_effects[i].spell->targets.size(); t++) { - int32 spawn_id = info->maintained_effects[i].spell->targets.at(t); - Spawn* spawn = GetZone()->GetSpawnByID(spawn_id); + for (int32 id : info->maintained_effects[i].spell->GetTargets()) { + Spawn* spawn = GetZone()->GetSpawnByID(id); LogWrite(SPELL__DEBUG, 0, "Spell", "%s has target %u to identify for spell %s", GetName(), spawn_id, info->maintained_effects[i].spell->spell->GetName()); if(spawn && (spawn->IsPlayer() || spawn->IsPet())) { @@ -7446,23 +7444,22 @@ void Player::SaveSpellEffects() ", " + std::to_string(info->maintained_effects[i].slot_pos) + ")"); firstTarget = false; } - } - multimap::iterator entries; - for(entries = info->maintained_effects[i].spell->char_id_targets.begin(); entries != info->maintained_effects[i].spell->char_id_targets.end(); entries++) - { - if(!firstTarget) - insertTargets.append(", "); + } + for (const auto& [char_id, pet_type] : info->maintained_effects[i].spell->GetCharIDTargets()) { + { + if(!firstTarget) + insertTargets.append(", "); - LogWrite(SPELL__DEBUG, 0, "Spell", "%s has target %s (%u) added to spell %s", GetName(), spawn ? spawn->GetName() : "NA", entries->first, info->maintained_effects[i].spell->spell->GetName()); - insertTargets.append("(" + std::to_string(caster_char_id) + ", " + std::to_string(entries->first) + ", " + std::to_string(entries->second) + ", " + - std::to_string(DB_TYPE_MAINTAINEDEFFECTS) + ", " + std::to_string(info->maintained_effects[i].spell_id) + ", " + std::to_string(i) + - ", " + std::to_string(info->maintained_effects[i].slot_pos) + ")"); + LogWrite(SPELL__DEBUG, 0, "Spell", "%s has target (%u) added to spell %s", GetName(), char_id, info->maintained_effects[i].spell->spell->GetName()); + insertTargets.append("(" + std::to_string(caster_char_id) + ", " + std::to_string(char_id) + ", " + std::to_string(pet_type) + ", " + + std::to_string(DB_TYPE_MAINTAINEDEFFECTS) + ", " + std::to_string(info->maintained_effects[i].spell_id) + ", " + std::to_string(i) + + ", " + std::to_string(info->maintained_effects[i].slot_pos) + ")"); - firstTarget = false; - } - info->maintained_effects[i].spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); - if(!firstTarget) { - savedEffects.AddQueryAsync(GetCharacterID(), &database, Q_INSERT, insertTargets.c_str()); + firstTarget = false; + } + if(!firstTarget) { + savedEffects.AddQueryAsync(GetCharacterID(), &database, Q_INSERT, insertTargets.c_str()); + } } } } diff --git a/source/WorldServer/PlayerGroups.cpp b/source/WorldServer/PlayerGroups.cpp index e33037d..d6edb63 100644 --- a/source/WorldServer/PlayerGroups.cpp +++ b/source/WorldServer/PlayerGroups.cpp @@ -1133,8 +1133,7 @@ void PlayerGroupManager::UpdateGroupBuffs() { if (spell && spell->GetSpellData()->group_spell && spell->GetSpellData()->friendly_spell && (spell->GetSpellData()->target_type == SPELL_TARGET_GROUP_AE || spell->GetSpellData()->target_type == SPELL_TARGET_RAID_AE)) { - luaspell->MSpellTargets.writelock(__FUNCTION__, __LINE__); - luaspell->char_id_targets.clear(); + luaspell->ClearCharTargets(); for (target_itr = group->GetMembers()->begin(); target_itr != group->GetMembers()->end(); target_itr++) { group_member = (*target_itr)->member; @@ -1152,8 +1151,9 @@ void PlayerGroupManager::UpdateGroupBuffs() { if (group_member->GetSpellEffect(spell->GetSpellID(), caster)) { has_effect = true; } - if (!has_effect && (std::find(luaspell->removed_targets.begin(), - luaspell->removed_targets.end(), group_member->GetID()) != luaspell->removed_targets.end())) { + std::vector removed_targets = luaspell->GetRemovedTargets(); + if (!has_effect && (std::find(removed_targets.begin(), + removed_targets.end(), group_member->GetID()) != removed_targets.end())) { continue; } // Check if player is within range of the caster @@ -1246,9 +1246,8 @@ void PlayerGroupManager::UpdateGroupBuffs() { } } - luaspell->targets.swap(new_target_list); + luaspell->SwapTargets(new_target_list); SpellProcess::AddSelfAndPet(luaspell, caster); - luaspell->MSpellTargets.releasewritelock(__FUNCTION__, __LINE__); new_target_list.clear(); } } diff --git a/source/WorldServer/SpellProcess.cpp b/source/WorldServer/SpellProcess.cpp index a82559e..72a8f38 100644 --- a/source/WorldServer/SpellProcess.cpp +++ b/source/WorldServer/SpellProcess.cpp @@ -424,6 +424,7 @@ bool SpellProcess::DeleteCasterSpell(Spawn* caster, Spell* spell, string reason) return ret; } + bool SpellProcess::DeleteCasterSpell(LuaSpell* spell, string reason, bool removing_all_spells, Spawn* remove_target, bool zone_shutting_down, bool shared_lock_spell){ if(shared_lock_spell && !removing_all_spells) { MSpellProcess.lock_shared(); @@ -433,30 +434,22 @@ bool SpellProcess::DeleteCasterSpell(LuaSpell* spell, string reason, bool removi Spawn* target = 0; bool target_valid = false; if(spell) { - spell->MSpellTargets.writelock(__FUNCTION__, __LINE__); - if(remove_target && spell->targets.size() > 1) { - for (int32 i = 0; i < spell->targets.size(); i++) { - if(remove_target->GetID() == spell->targets.at(i)) { + if(remove_target) { + for (int32 id : spell->GetTargets()) { + if(remove_target->GetID() == id) { if(remove_target->IsEntity()){ - spell->removed_targets.push_back(remove_target->GetID()); - ((Entity*)remove_target)->RemoveProc(0, spell); - ((Entity*)remove_target)->RemoveSpellEffect(spell); - ((Entity*)remove_target)->RemoveSpellBonus(spell); - if(spell->spell->GetSpellData()->det_type > 0 && (spell->spell->GetSpellDuration() > 0 || spell->spell->GetSpellData()->duration_until_cancel)) - ((Entity*)remove_target)->RemoveDetrimentalSpell(spell); + spell->RemoveTarget(remove_target->GetID()); + lua_interface->RemoveSpawnFromSpell(spell, remove_target); } - spell->targets.erase(spell->targets.begin()+i, spell->targets.begin()+i+1); target_valid = true; break; } } - spell->MSpellTargets.releasewritelock(__FUNCTION__, __LINE__); if(shared_lock_spell && !removing_all_spells) { MSpellProcess.unlock_shared(); } return target_valid; } - spell->MSpellTargets.releasewritelock(__FUNCTION__, __LINE__); if (!zone_shutting_down && spell->caster) { // spell->caster ptr cannot be trusted during zone shutdown if(spell->caster->GetThreatTransfer() && spell->caster->GetThreatTransfer()->Spell == spell) { spell->caster->SetThreatTransfer(nullptr); @@ -490,24 +483,17 @@ bool SpellProcess::DeleteCasterSpell(LuaSpell* spell, string reason, bool removi spell->caster->RemoveProc(0, spell); spell->caster->RemoveMaintainedSpell(spell); CheckRemoveTargetFromSpell(spell, removing_all_spells, removing_all_spells); - ZoneServer* zone = spell->caster->GetZone(); + ZoneServer* zone = spell->zone; if(zone) { - spell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - for (int32 i = 0; i < spell->targets.size(); i++) { - target = zone->GetSpawnByID(spell->targets.at(i)); + for (int32 id : spell->GetTargets()) { + target = zone->GetSpawnByID(id); if(target && target->IsEntity()){ - spell->removed_targets.push_back(target->GetID()); - ((Entity*)target)->RemoveProc(0, spell); - ((Entity*)target)->RemoveSpellEffect(spell); - ((Entity*)target)->RemoveSpellBonus(spell); - if(spell->spell->GetSpellData()->det_type > 0 && (spell->spell->GetSpellDuration() > 0 || spell->spell->GetSpellData()->duration_until_cancel)) - ((Entity*)target)->RemoveDetrimentalSpell(spell); + spell->RemoveTarget(target->GetID()); + lua_interface->RemoveSpawnFromSpell(spell, target); } else{ - spell->caster->RemoveSpellEffect(spell); - spell->caster->RemoveSpellBonus(spell); - if(spell->spell->GetSpellData()->det_type > 0 && (spell->spell->GetSpellDuration() > 0 || spell->spell->GetSpellData()->duration_until_cancel)) - spell->caster->RemoveDetrimentalSpell(spell); + spell->RemoveTarget(spell->caster->GetID()); + lua_interface->RemoveSpawnFromSpell(spell, spell->caster); } if(target && target->IsPlayer() && spell->spell->GetSpellData()->fade_message.length() > 0){ Client* client = ((Player*)target)->GetClient(); @@ -528,7 +514,6 @@ bool SpellProcess::DeleteCasterSpell(LuaSpell* spell, string reason, bool removi } } } - spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); } ret = true; } @@ -553,10 +538,9 @@ bool SpellProcess::ProcessSpell(LuaSpell* spell, bool first_cast, const char* fu else if(lua_interface && !spell->interrupted){ if(all_targets) { - for(int t=0;ttargets.size();t++) - { - if(spell->caster->GetZone()) { - Spawn* altSpawn = spell->caster->GetZone()->GetSpawnByID(spell->targets[t]); + for (int32 id : spell->GetTargets()) { + if(spell->zone) { + Spawn* altSpawn = spell->zone->GetSpawnByID(id); if(altSpawn) { std::string functionCall = ApplyLuaFunction(spell, first_cast, function, timer, altSpawn); @@ -1478,7 +1462,7 @@ void SpellProcess::ProcessSpell(ZoneServer* zone, Spell* spell, Entity* caster, } } - if (lua_spell->targets.size() == 0 && spell->GetSpellData()->max_aoe_targets == 0) + if (lua_spell->GetTargetCount() == 0 && spell->GetSpellData()->max_aoe_targets == 0) { LogWrite(SPELL__ERROR, 0, "Spell", "SpellProcess::ProcessSpell Unable to find any spell targets for spell '%s', spell type: %u, target type %u.", spell->GetName(), spell->GetSpellData()->spell_type, spell->GetSpellData()->target_type); @@ -1719,9 +1703,9 @@ bool SpellProcess::CastProcessedSpell(LuaSpell* spell, bool passive, bool in_her Client* client = 0; if(spell->caster && spell->caster->IsPlayer()) client = ((Player*)spell->caster)->GetClient(); - if (spell->spell->GetSpellData()->max_aoe_targets > 0 && spell->targets.size() == 0) { + if (spell->spell->GetSpellData()->max_aoe_targets > 0 && spell->GetTargetCount() == 0) { GetSpellTargetsTrueAOE(spell); - if (spell->targets.size() == 0) { + if (spell->GetTargetCount() == 0) { if(client) { client->GetPlayer()->UnlockAllSpells(true); @@ -1772,8 +1756,8 @@ bool SpellProcess::CastProcessedSpell(LuaSpell* spell, bool passive, bool in_her ZoneServer* zone = spell->caster->GetZone(); Spawn* target = 0; if(processedSpell){ - for (int32 i = 0; i < spell->targets.size(); i++) { - target = zone->GetSpawnByID(spell->targets[i]); + for (int32 id : spell->GetTargets()) { + target = zone->GetSpawnByID(id); if (!target) continue; @@ -1815,11 +1799,12 @@ bool SpellProcess::CastProcessedSpell(LuaSpell* spell, bool passive, bool in_her return false; } if(!spell->resisted && (spell->spell->GetSpellDuration() > 0 || spell->spell->GetSpellData()->duration_until_cancel || spell->spell->GetSpellData()->spell_book_type == SPELL_BOOK_TYPE_NOT_SHOWN)) { - for (int32 i = 0; i < spell->targets.size(); i++) { + bool firstTarget = true; + for (int32 id : spell->GetTargets()) { //LogWrite(SPELL__ERROR, 0, "Spell", "No precast function found for %s", ((Entity*)target)->GetName()); - target = zone->GetSpawnByID(spell->targets.at(i)); - if (!target && spell->targets.at(i) == spell->caster->GetID()) { + target = zone->GetSpawnByID(id); + if (!target && id == spell->caster->GetID()) { target = spell->caster; } if (!target) { @@ -1828,9 +1813,10 @@ bool SpellProcess::CastProcessedSpell(LuaSpell* spell, bool passive, bool in_her } continue; } - if (i == 0 && !spell->spell->GetSpellData()->not_maintained) { + if (firstTarget && !spell->spell->GetSpellData()->not_maintained) { spell->caster->AddMaintainedSpell(spell); } + firstTarget = false; SpellEffects* effect = ((Entity*)target)->GetSpellEffect(spell->spell->GetSpellID()); if (effect && effect->tier > spell->spell->GetSpellTier()) { @@ -1885,16 +1871,14 @@ bool SpellProcess::CastProcessedSpell(LuaSpell* spell, bool passive, bool in_her ho = soloItr->second; bool match = false; LogWrite(SPELL__DEBUG, 0, "HO", "target = %u", ho->GetTarget()); - spell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - for (int8 i = 0; i < spell->targets.size(); i++) { - LogWrite(SPELL__DEBUG, 0, "HO", "Target ID: %u", spell->targets.at(i)); - if (spell->targets.at(i) == ho->GetTarget() || spell->spell->GetSpellData()->friendly_spell) { + for (int32 id : spell->GetTargets()) { + LogWrite(SPELL__DEBUG, 0, "HO", "Target ID: %u", id); + if (id == ho->GetTarget() || spell->spell->GetSpellData()->friendly_spell) { match = true; LogWrite(SPELL__DEBUG, 0, "HO", "match found"); break; } } - spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); if(match && !spell->spell) LogWrite(SPELL__ERROR, 0, "HO", "%s: spell->spell is nullptr", client->GetPlayer()->GetName()); @@ -1921,10 +1905,9 @@ bool SpellProcess::CastProcessedSpell(LuaSpell* spell, bool passive, bool in_her if (groupItr != m_groupHO.end()) { ho = groupItr->second; int32 group_id = client->GetPlayer()->GetGroupMemberInfo()->group_id; - spell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - if (((spell->targets.size() > 0 && spell->targets.at(0) == ho->GetTarget()) || spell->spell->GetSpellData()->friendly_spell) + int32 first_target = spell->GetPrimaryTargetID(); + if (((first_target != 0xFFFFFFFF && first_target == ho->GetTarget()) || spell->spell->GetSpellData()->friendly_spell) && ho->UpdateHeroicOP(spell->spell->GetSpellIconHeroicOp())) { - spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); world.GetGroupManager()->GroupLock(__FUNCTION__, __LINE__); deque::iterator itr; @@ -1951,8 +1934,6 @@ bool SpellProcess::CastProcessedSpell(LuaSpell* spell, bool passive, bool in_her m_groupHO.erase(groupItr); } } - else - spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); } } MGroupHO.releasewritelock(__FUNCTION__, __LINE__); @@ -2071,14 +2052,12 @@ void SpellProcess::RemoveSpellTimersFromSpawn(Spawn* spawn, bool remove_all, boo bool foundMatch = false; if(spawn != spell->caster) { - spell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - for (i = 0; i < spell->targets.size(); i++){ - if (spawn->GetID() == spell->targets.at(i)){ + for (int32 id : spell->GetTargets()) { + if (spawn->GetID() == id){ foundMatch = true; break; } } - spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); } if(foundMatch) { if (spawn->IsEntity()) @@ -2289,7 +2268,6 @@ void SpellProcess::GetSpellTargets(LuaSpell* luaspell) luaspell->initial_target_char_id = (secondary_target && secondary_target->IsPlayer()) ? ((Player*)secondary_target)->GetCharacterID() : 0; } - luaspell->MSpellTargets.writelock(__FUNCTION__, __LINE__); // Group AE type NOTE: Add support for RAID AE to affect raid members once raids have been completed if (target_type == SPELL_TARGET_GROUP_AE || spell_type == SPELL_TYPE_ALLGROUPTARGETS || target_type == SPELL_TARGET_RAID_AE) { @@ -2418,7 +2396,7 @@ void SpellProcess::GetSpellTargets(LuaSpell* luaspell) } else if (target->IsPlayer() || target->IsBot() || (target->IsNPC() && ((Entity*)target)->GetInfoStruct()->get_friendly_target_npc())) // else it is not raid, group only or group spell AddLuaSpellTarget(luaspell, target->GetID(), false); // return target for single spell - else if ((luaspell->targets.size() < 1) || (!target->IsPet() || (((Entity*)target)->GetOwner() && !((Entity*)target)->GetOwner()->IsPlayer()))) + else if ((luaspell->HasNoTargets()) || (!target->IsPet() || (((Entity*)target)->GetOwner() && !((Entity*)target)->GetOwner()->IsPlayer()))) AddLuaSpellTarget(luaspell, caster->GetID(), false); // and if no target, cast on self } else if (caster->IsNPC()) // caster is an NPC @@ -2562,11 +2540,10 @@ void SpellProcess::GetSpellTargets(LuaSpell* luaspell) } } } - luaspell->MSpellTargets.releasewritelock(__FUNCTION__, __LINE__); } - if (luaspell && luaspell->targets.size() > 20) - LogWrite(SPELL__WARNING, 0, "Spell", "Warning in %s: Size of targets array is %u", __FUNCTION__, luaspell->targets.size()); + if (luaspell && luaspell->GetTargetCount() > 20) + LogWrite(SPELL__WARNING, 0, "Spell", "Warning in %s: Size of targets array is %u", __FUNCTION__, luaspell->GetTargetCount()); } bool SpellProcess::GetPlayerGroupTargets(Player* target, Spawn* caster, LuaSpell* luaspell, bool bypassSpellChecks, bool bypassRangeChecks) @@ -2620,7 +2597,6 @@ void SpellProcess::GetSpellTargetsTrueAOE(LuaSpell* luaspell) { } int32 ignore_target = 0; std::vector> spawns = luaspell->caster->GetZone()->GetAttackableSpawnsByDistance(luaspell->caster, luaspell->spell->GetSpellData()->radius); - luaspell->MSpellTargets.writelock(__FUNCTION__, __LINE__); int32 i = 0; for (const auto& pair : spawns) { if (i == 0){ @@ -2634,7 +2610,7 @@ void SpellProcess::GetSpellTargetsTrueAOE(LuaSpell* luaspell) { i++; - if (luaspell->targets.size() >= luaspell->spell->GetSpellData()->max_aoe_targets) + if (luaspell->GetTargetCount() >= luaspell->spell->GetSpellData()->max_aoe_targets) break; int32 target_id = pair.first; @@ -2653,14 +2629,13 @@ void SpellProcess::GetSpellTargetsTrueAOE(LuaSpell* luaspell) { AddLuaSpellTarget(luaspell, spawn->GetID(), false); } - if (luaspell->targets.size() >= luaspell->spell->GetSpellData()->max_aoe_targets) + if (luaspell->GetTargetCount() >= luaspell->spell->GetSpellData()->max_aoe_targets) break; } - luaspell->MSpellTargets.releasewritelock(__FUNCTION__, __LINE__); } } - if (luaspell->targets.size() > 20) - LogWrite(SPELL__DEBUG, 0, "Spell", "Warning in SpellProcess::GetSpellTargetsTrueAOE Size of targets array is %u", luaspell->targets.size()); + if (luaspell->GetTargetCount() > 20) + LogWrite(SPELL__DEBUG, 0, "Spell", "Warning in SpellProcess::GetSpellTargetsTrueAOE Size of targets array is %u", luaspell->GetTargetCount()); } void SpellProcess::AddSpellScriptTimer(SpellScriptTimer* timer) { @@ -2811,58 +2786,46 @@ 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; - vector* targets; vector* remove_targets = 0; 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; - remove_targets = remove_itr->second; - 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++){ - remove_spawn = spell->zone->GetSpawnByID((*remove_target_itr)); - if (remove_spawn) { - bool found_target = false; - if(remove_spawn->IsPlayer()) - { - multimap::iterator entries; - while((entries = spell->char_id_targets.find(((Player*)remove_spawn)->GetCharacterID())) != spell->char_id_targets.end()) - { - spell->char_id_targets.erase(entries); - } - } - for (target_itr = targets->begin(); target_itr != targets->end(); target_itr++) { - if (remove_spawn->GetID() == (*target_itr)) { - found_target = true; - ((Entity*)remove_spawn)->RemoveProc(0, spell); - ((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 && std::find(spawnsToRemove.begin(), spawnsToRemove.end(), remove_spawn) == spawnsToRemove.end()) - spawnsToRemove.push_back(remove_spawn); - break; - } - } - targets_empty = (targets->size() == 0 && spell->char_id_targets.size() == 0); - if (targets_empty && allow_delete) { - should_delete = true; + auto it = remove_target_list.find(spell); + if (it != remove_target_list.end()) { + remove_targets = it->second; + if (remove_targets){ + for (remove_target_itr = remove_targets->begin(); remove_target_itr != remove_targets->end(); remove_target_itr++){ + remove_spawn = spell->zone->GetSpawnByID((*remove_target_itr)); + if (remove_spawn) { + bool found_target = false; + if(remove_spawn->IsPlayer()) + { + spell->RemoveCharIDTarget(((Player*)remove_spawn)->GetCharacterID()); + } + for (int32 id : spell->GetTargets()) { + if (remove_spawn->GetID() == id) { + found_target = true; + spell->RemoveTarget(id); + lua_interface->RemoveSpawnFromSpell(spell, remove_spawn); + LogWrite(SPELL__DEBUG, 0, "Spell", "%s CheckRemoveTargetFromSpell %s (%u).", spell->spell->GetName(), remove_spawn->GetName(), remove_spawn->GetID()); + if(remove_spawn && std::find(spawnsToRemove.begin(), spawnsToRemove.end(), remove_spawn) == spawnsToRemove.end()) + spawnsToRemove.push_back(remove_spawn); break; } - else if(remove_spawn && std::find(spawnsToRemove.begin(), spawnsToRemove.end(), remove_spawn) == spawnsToRemove.end()) { - spawnsToRemove.push_back(remove_spawn); - } + } + targets_empty = (spell->HasNoTargets() && spell->HasNoCharIDTargets()); + if (targets_empty && allow_delete) { + should_delete = true; + break; + } + else if(remove_spawn && std::find(spawnsToRemove.begin(), spawnsToRemove.end(), remove_spawn) == spawnsToRemove.end()) { + spawnsToRemove.push_back(remove_spawn); } } - spell->MSpellTargets.releasewritelock(__FUNCTION__, __LINE__); } - break; } } @@ -3005,18 +2968,13 @@ void SpellProcess::DeleteSpell(LuaSpell* spell) lua_interface->RemoveCustomSpell(spell->spell->GetSpellID()); safe_delete(spell->spell); } - if(spell->targets.size() > 0) { - spell->MSpellTargets.readlock(__FUNCTION__, __LINE__); - for (int8 i = 0; i < spell->targets.size(); i++) { - Spawn* target = spell->zone->GetSpawnByID(spell->targets.at(i)); - if (!target || !target->IsEntity()) - continue; + for (int32 id : spell->GetTargets()) { + Spawn* target = spell->zone->GetSpawnByID(id); + if (!target || !target->IsEntity()) + continue; - if(target->IsEntity()) { - lua_interface->RemoveSpawnFromSpell(spell, target); - } - } - spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__); + spell->RemoveTarget(target->GetID()); + lua_interface->RemoveSpawnFromSpell(spell, target); } lua_interface->SetLuaUserDataStale(spell); @@ -3078,20 +3036,15 @@ void SpellProcess::DeleteActiveSpell(LuaSpell* spell, bool skipRemoveCurrent) { bool SpellProcess::AddLuaSpellTarget(LuaSpell* lua_spell, int32 id, bool lock_spell_targets) { bool ret = false; - if(lock_spell_targets) - lua_spell->MSpellTargets.writelock(__FUNCTION__, __LINE__); - if(std::find(lua_spell->targets.begin(), lua_spell->targets.end(), id) != lua_spell->targets.end()) { + if(lua_spell->HasTarget(id)) { ret = true; } - else if(std::find(lua_spell->removed_targets.begin(), lua_spell->removed_targets.end(), id) == lua_spell->removed_targets.end()) { - lua_spell->targets.push_back(id); + else if(!lua_spell->HasTarget(id)) { + lua_spell->AddTarget(id); ret = true; } - if(lock_spell_targets) - lua_spell->MSpellTargets.releasewritelock(__FUNCTION__, __LINE__); - return ret; } diff --git a/source/WorldServer/WorldDatabase.cpp b/source/WorldServer/WorldDatabase.cpp index 0ad3817..3332138 100644 --- a/source/WorldServer/WorldDatabase.cpp +++ b/source/WorldServer/WorldDatabase.cpp @@ -8189,9 +8189,7 @@ void WorldDatabase::LoadCharacterSpellEffects(int32 char_id, Client* client, int } else { - lua_spell->MSpellTargets.writelock(__FUNCTION__, __LINE__); - lua_spell->char_id_targets.insert(make_pair(player->GetCharacterID(),0)); - lua_spell->MSpellTargets.releasewritelock(__FUNCTION__, __LINE__); + lua_spell->AddCharIDTarget(player->GetCharacterID(), 0); } player->MSpellEffects.releasewritelock(); continue; @@ -8219,13 +8217,7 @@ void WorldDatabase::LoadCharacterSpellEffects(int32 char_id, Client* client, int info->spell_effects[effect_slot].total_time = total_time; info->spell_effects[effect_slot].spell = lua_spell; - lua_spell->MSpellTargets.writelock(__FUNCTION__, __LINE__); - multimap::iterator entries; - while((entries = lua_spell->char_id_targets.find(player->GetCharacterID())) != lua_spell->char_id_targets.end()) - { - lua_spell->char_id_targets.erase(entries); - } - lua_spell->MSpellTargets.releasewritelock(__FUNCTION__, __LINE__); + lua_spell->AddCharIDTarget(player->GetCharacterID(), 0); lua_spell->slot_pos = slot_pos; if(!isExistingLuaSpell) @@ -8275,8 +8267,6 @@ void WorldDatabase::LoadCharacterSpellEffects(int32 char_id, Client* client, int { if(client != client2) { - lua_spell->MSpellTargets.writelock(__FUNCTION__, __LINE__); - if(client2->GetPlayer()->GetPet() && maintained_target_type == PET_TYPE_COMBAT) { restoreSpells.insert(make_pair(lua_spell, client2->GetPlayer()->GetPet())); @@ -8287,29 +8277,16 @@ void WorldDatabase::LoadCharacterSpellEffects(int32 char_id, Client* client, int restoreSpells.insert(make_pair(lua_spell, client2->GetPlayer()->GetCharmedPet())); // target added via restoreSpells } - - lua_spell->MSpellTargets.releasewritelock(__FUNCTION__, __LINE__); } } // end of pet clause else if(client != client2) // maintained type must be 0, so client restoreSpells.insert(make_pair(lua_spell, client2->GetPlayer())); - lua_spell->MSpellTargets.writelock(__FUNCTION__, __LINE__); - multimap::iterator entries; - for(entries = lua_spell->char_id_targets.begin(); entries != lua_spell->char_id_targets.end(); entries++) - { - int32 ent_char_id = entries->first; - int8 ent_target_type = entries->second; - if(ent_char_id == target_char && ent_target_type == maintained_target_type) - entries = lua_spell->char_id_targets.erase(entries); - } - lua_spell->MSpellTargets.releasewritelock(__FUNCTION__, __LINE__); + lua_spell->RemoveCharIDTargetAndType(target_char, maintained_target_type); } else { - lua_spell->MSpellTargets.writelock(__FUNCTION__, __LINE__); - lua_spell->char_id_targets.insert(make_pair(target_char,maintained_target_type)); - lua_spell->MSpellTargets.releasewritelock(__FUNCTION__, __LINE__); + lua_spell->AddCharIDTarget(target_char,maintained_target_type); } } }