Extensive changes to remove SpellTargets write and read mutex locks to avoi ddeadlocks

This commit is contained in:
Emagi 2025-06-22 13:20:07 -04:00
parent 6b0f551552
commit a8eb9c9ebc
7 changed files with 422 additions and 466 deletions

View File

@ -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<int32> 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<int32> targets = spell->targets;
vector<Entity*> 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<Entity*>::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<int32> 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<int32> 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;
}
}

View File

@ -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<int32,int8>::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;

View File

@ -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<int32> targets;
vector<int32> removed_targets; // previously cancelled, expired, used, so on
mutable std::shared_mutex char_id_targets_mutex;
multimap<int32, int8> 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<bool> 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<int32_t> GetPrimaryTarget() const {
std::shared_lock lock(targets_mutex);
if (!targets.empty())
return targets[0];
return std::nullopt;
}
std::vector<int32> 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<int32>(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<int32> 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<int32>& 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<int32, int8> 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 */ };

View File

@ -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<Spawn*, int8> 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<int32,int8>::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());
}
}
}
}

View File

@ -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<int32> 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();
}
}

View File

@ -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;t<spell->targets.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<GroupMemberInfo*>::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<std::pair<int32, float>> 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<Spawn*> spawnsToRemove;
map<LuaSpell*, vector<int32>*>::iterator remove_itr;
vector<int32>::iterator remove_target_itr;
vector<int32>::iterator target_itr;
vector<int32>* targets;
vector<int32>* 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<int32,int8>::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;
}

View File

@ -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<int32,int8>::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<int32,int8>::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);
}
}
}