Fix tentacle slam
This commit is contained in:
@@ -5232,76 +5232,112 @@ class spell_pri_void_volley : public SpellScript
|
||||
};
|
||||
|
||||
// 1227280 - Tentacle Slam
|
||||
// Effect 0 carries the radius the slam damages around the target, effect 2 carries how many enemies
|
||||
// it applies Vampiric Touch to. The two are handled separately, otherwise the shared handler both
|
||||
// deals its damage twice and reads the wrong effect value as the Vampiric Touch target count.
|
||||
class spell_pri_tentacle_slam : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_PRIEST_VAMPIRIC_TOUCH, SPELL_PRIEST_TENTACLE_SLAM_DAMAGE });
|
||||
return ValidateSpellInfo({ SPELL_PRIEST_VAMPIRIC_TOUCH });
|
||||
}
|
||||
|
||||
void HandleDummy(SpellEffIndex /*effIndex*/)
|
||||
// Every enemy the slam reaches around the target, split so targets without Vampiric Touch can
|
||||
// be prioritised as the talent requires
|
||||
void CollectSlamTargets(Unit* caster, Unit* target, std::vector<Unit*>& withoutVampiricTouch, std::vector<Unit*>& withVampiricTouch) const
|
||||
{
|
||||
float const radius = float(GetSpell()->GetSpellInfo()->GetEffect(EFFECT_0).CalcBaseValue(caster, target, 0, 0));
|
||||
if (radius <= 0.0f)
|
||||
return;
|
||||
|
||||
std::list<Unit*> enemyList;
|
||||
Trinity::AnyUnfriendlyUnitInObjectRangeCheck check(target, caster, radius);
|
||||
Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(target, enemyList, check);
|
||||
Cell::VisitAllObjects(target, searcher, radius);
|
||||
|
||||
for (Unit* unit : enemyList)
|
||||
{
|
||||
if (unit->HasAura(SPELL_PRIEST_VAMPIRIC_TOUCH, caster->GetGUID()))
|
||||
withVampiricTouch.push_back(unit);
|
||||
else
|
||||
withoutVampiricTouch.push_back(unit);
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyVampiricTouch(Unit* caster, Unit* target) const
|
||||
{
|
||||
caster->CastSpell(target, SPELL_PRIEST_VAMPIRIC_TOUCH, CastSpellExtraArgsInit{
|
||||
.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR,
|
||||
.TriggeringSpell = GetSpell()
|
||||
});
|
||||
}
|
||||
|
||||
void HandleDamage(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
Unit* caster = GetCaster();
|
||||
Unit* target = GetHitUnit();
|
||||
if (!caster || !target)
|
||||
return;
|
||||
|
||||
// Cast damage spell on the target
|
||||
caster->CastSpell(target, SPELL_PRIEST_TENTACLE_SLAM_DAMAGE, CastSpellExtraArgsInit{
|
||||
.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR,
|
||||
.TriggeringSpell = GetSpell()
|
||||
});
|
||||
// The slam damage lives in a separate spell that the client only references, so it is
|
||||
// skipped when the server data does not carry it. Vampiric Touch still has to be applied.
|
||||
if (!sSpellMgr->GetSpellInfo(SPELL_PRIEST_TENTACLE_SLAM_DAMAGE, DIFFICULTY_NONE))
|
||||
return;
|
||||
|
||||
// Apply Vampiric Touch to enemies without it, up to the spell's effect value
|
||||
int32 maxTargets = GetEffectValueAsInt();
|
||||
std::vector<Unit*> targets;
|
||||
std::vector<Unit*> withoutVampiricTouch, withVampiricTouch;
|
||||
CollectSlamTargets(caster, target, withoutVampiricTouch, withVampiricTouch);
|
||||
|
||||
// Find enemies in range around the target
|
||||
std::list<Unit*> enemyList;
|
||||
float radius = 10.0f; // Base radius for AoE
|
||||
Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(target, caster, radius);
|
||||
Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(target, enemyList, u_check);
|
||||
Cell::VisitAllObjects(target, searcher, radius);
|
||||
|
||||
// Prioritize enemies without Vampiric Touch
|
||||
std::vector<Unit*> withoutVT;
|
||||
std::vector<Unit*> withVT;
|
||||
|
||||
for (Unit* unit : enemyList)
|
||||
{
|
||||
if (unit->HasAura(SPELL_PRIEST_VAMPIRIC_TOUCH))
|
||||
withVT.push_back(unit);
|
||||
else
|
||||
withoutVT.push_back(unit);
|
||||
}
|
||||
|
||||
// Add targets without VT first, then with VT
|
||||
for (Unit* unit : withoutVT)
|
||||
{
|
||||
if (static_cast<int32>(targets.size()) < maxTargets)
|
||||
targets.push_back(unit);
|
||||
}
|
||||
|
||||
for (Unit* unit : withVT)
|
||||
{
|
||||
if (static_cast<int32>(targets.size()) < maxTargets)
|
||||
targets.push_back(unit);
|
||||
}
|
||||
|
||||
// Apply Vampiric Touch to selected targets
|
||||
for (Unit* unit : targets)
|
||||
{
|
||||
caster->CastSpell(unit, SPELL_PRIEST_VAMPIRIC_TOUCH, CastSpellExtraArgsInit{
|
||||
for (Unit* unit : withoutVampiricTouch)
|
||||
caster->CastSpell(unit, SPELL_PRIEST_TENTACLE_SLAM_DAMAGE, CastSpellExtraArgsInit{
|
||||
.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR,
|
||||
.TriggeringSpell = GetSpell()
|
||||
});
|
||||
|
||||
for (Unit* unit : withVampiricTouch)
|
||||
caster->CastSpell(unit, SPELL_PRIEST_TENTACLE_SLAM_DAMAGE, CastSpellExtraArgsInit{
|
||||
.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR,
|
||||
.TriggeringSpell = GetSpell()
|
||||
});
|
||||
}
|
||||
|
||||
void HandleApplyVampiricTouch(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
Unit* caster = GetCaster();
|
||||
Unit* target = GetHitUnit();
|
||||
if (!caster || !target)
|
||||
return;
|
||||
|
||||
int32 const maxTargets = GetEffectValueAsInt();
|
||||
if (maxTargets <= 0)
|
||||
return;
|
||||
|
||||
std::vector<Unit*> withoutVampiricTouch, withVampiricTouch;
|
||||
CollectSlamTargets(caster, target, withoutVampiricTouch, withVampiricTouch);
|
||||
|
||||
int32 applied = 0;
|
||||
for (Unit* unit : withoutVampiricTouch)
|
||||
{
|
||||
if (applied >= maxTargets)
|
||||
break;
|
||||
|
||||
ApplyVampiricTouch(caster, unit);
|
||||
++applied;
|
||||
}
|
||||
|
||||
for (Unit* unit : withVampiricTouch)
|
||||
{
|
||||
if (applied >= maxTargets)
|
||||
break;
|
||||
|
||||
ApplyVampiricTouch(caster, unit);
|
||||
++applied;
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_pri_tentacle_slam::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
OnEffectHitTarget += SpellEffectFn(spell_pri_tentacle_slam::HandleDummy, EFFECT_2, SPELL_EFFECT_DUMMY);
|
||||
OnEffectHitTarget += SpellEffectFn(spell_pri_tentacle_slam::HandleDamage, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
OnEffectHitTarget += SpellEffectFn(spell_pri_tentacle_slam::HandleApplyVampiricTouch, EFFECT_2, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user