Core/Scripts: Implemented 2 new target selectors, one specialized for spells, checking auras, range and attributes; and the other is a very simple non-tank selection what is sufficient for most cases
This commit is contained in:
@@ -23,6 +23,7 @@
|
||||
#include "SpellAuraEffects.h"
|
||||
#include "SpellMgr.h"
|
||||
#include "SpellInfo.h"
|
||||
#include "Spell.h"
|
||||
#include "CreatureAIImpl.h"
|
||||
|
||||
void UnitAI::AttackStart(Unit* victim)
|
||||
@@ -245,3 +246,48 @@ void SimpleCharmedAI::UpdateAI(const uint32 /*diff*/)
|
||||
if (!target || !charmer->IsValidAttackTarget(target))
|
||||
AttackStart(charmer->SelectNearestTargetInAttackDistance());
|
||||
}
|
||||
|
||||
SpellTargetSelector::SpellTargetSelector(Unit* caster, uint32 spellId) :
|
||||
_caster(caster), _spellInfo(sSpellMgr->GetSpellForDifficultyFromSpell(sSpellMgr->GetSpellInfo(spellId), caster))
|
||||
{
|
||||
ASSERT(_spellInfo);
|
||||
}
|
||||
|
||||
bool SpellTargetSelector::operator()(Unit const* target) const
|
||||
{
|
||||
if (_spellInfo->CheckTarget(_caster, target) != SPELL_CAST_OK)
|
||||
return false;
|
||||
|
||||
// copypasta from Spell::CheckRange
|
||||
uint32 range_type = _spellInfo->RangeEntry ? _spellInfo->RangeEntry->type : 0;
|
||||
float max_range = _caster->GetSpellMaxRangeForTarget(target, _spellInfo);
|
||||
float min_range = _caster->GetSpellMinRangeForTarget(target, _spellInfo);
|
||||
|
||||
|
||||
if (target && target != _caster)
|
||||
{
|
||||
if (range_type == SPELL_RANGE_MELEE)
|
||||
{
|
||||
// Because of lag, we can not check too strictly here.
|
||||
if (!_caster->IsWithinMeleeRange(target, max_range))
|
||||
return false;
|
||||
}
|
||||
else if (!_caster->IsWithinCombatRange(target, max_range))
|
||||
return false;
|
||||
|
||||
if (range_type == SPELL_RANGE_RANGED)
|
||||
{
|
||||
if (_caster->IsWithinMeleeRange(target))
|
||||
return false;
|
||||
}
|
||||
else if (min_range && _caster->IsWithinCombatRange(target, min_range)) // skip this check if min_range = 0
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NonTankTargetSelector::operator()(Unit const* target) const
|
||||
{
|
||||
return target != _source->getVictim();
|
||||
}
|
||||
|
||||
@@ -97,6 +97,32 @@ struct DefaultTargetSelector : public std::unary_function<Unit* , bool>
|
||||
}
|
||||
};
|
||||
|
||||
// Target selector for spell casts checking range, auras and attributes
|
||||
// TODO: Add more checks from Spell::CheckCast
|
||||
struct SpellTargetSelector : public std::unary_function<Unit*, bool>
|
||||
{
|
||||
public:
|
||||
SpellTargetSelector(Unit* caster, uint32 spellId);
|
||||
bool operator()(Unit const* target) const;
|
||||
|
||||
private:
|
||||
Unit const* _caster;
|
||||
SpellInfo const* _spellInfo;
|
||||
};
|
||||
|
||||
// Very simple target selector, will just skip main target
|
||||
// NOTE: When passing to UnitAI::SelectTarget remember to use 0 as position for random selection
|
||||
// because tank will not be in the temporary list
|
||||
struct NonTankTargetSelector : public std::unary_function<Unit*, bool>
|
||||
{
|
||||
public:
|
||||
explicit NonTankTargetSelector(Creature* source) : _source(source) { }
|
||||
bool operator()(Unit const* target) const;
|
||||
|
||||
private:
|
||||
Creature const* _source;
|
||||
};
|
||||
|
||||
class UnitAI
|
||||
{
|
||||
protected:
|
||||
|
||||
@@ -5594,6 +5594,13 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
|
||||
instance->DoCastSpellOnPlayers(65037); // Achievement criteria marker
|
||||
break;
|
||||
}
|
||||
// Dark Hunger (The Lich King encounter)
|
||||
case 69383:
|
||||
{
|
||||
basepoints0 = CalculatePctN(int32(damage), 50);
|
||||
triggered_spell_id = 69384;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -9240,7 +9247,7 @@ ReputationRank Unit::GetReactionTo(Unit const* target) const
|
||||
if (GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_FFA_PVP
|
||||
&& target->GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_FFA_PVP)
|
||||
return REP_HOSTILE;
|
||||
|
||||
|
||||
if (selfPlayerOwner)
|
||||
{
|
||||
if (FactionTemplateEntry const* targetFactionTemplateEntry = target->getFactionTemplateEntry())
|
||||
@@ -12416,7 +12423,7 @@ bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell) co
|
||||
&& target->GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_FFA_PVP)
|
||||
return true;
|
||||
|
||||
return (GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_UNK1)
|
||||
return (GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_UNK1)
|
||||
|| (target->GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_UNK1);
|
||||
}
|
||||
return true;
|
||||
@@ -13479,7 +13486,7 @@ void Unit::ApplyDiminishingAura(DiminishingGroup group, bool apply)
|
||||
}
|
||||
}
|
||||
|
||||
float Unit::GetSpellMaxRangeForTarget(Unit* target, SpellInfo const* spellInfo)
|
||||
float Unit::GetSpellMaxRangeForTarget(Unit const* target, SpellInfo const* spellInfo) const
|
||||
{
|
||||
if (!spellInfo->RangeEntry)
|
||||
return 0;
|
||||
@@ -13488,7 +13495,7 @@ float Unit::GetSpellMaxRangeForTarget(Unit* target, SpellInfo const* spellInfo)
|
||||
return spellInfo->GetMaxRange(!IsHostileTo(target));
|
||||
}
|
||||
|
||||
float Unit::GetSpellMinRangeForTarget(Unit* target, SpellInfo const* spellInfo)
|
||||
float Unit::GetSpellMinRangeForTarget(Unit const* target, SpellInfo const* spellInfo) const
|
||||
{
|
||||
if (!spellInfo->RangeEntry)
|
||||
return 0;
|
||||
|
||||
@@ -1255,8 +1255,8 @@ class Unit : public WorldObject
|
||||
void ClearDiminishings() { m_Diminishing.clear(); }
|
||||
|
||||
// target dependent range checks
|
||||
float GetSpellMaxRangeForTarget(Unit* target, SpellInfo const* spellInfo);
|
||||
float GetSpellMinRangeForTarget(Unit* target, SpellInfo const* spellInfo);
|
||||
float GetSpellMaxRangeForTarget(Unit const* target, SpellInfo const* spellInfo) const;
|
||||
float GetSpellMinRangeForTarget(Unit const* target, SpellInfo const* spellInfo) const;
|
||||
|
||||
virtual void Update(uint32 time);
|
||||
|
||||
|
||||
@@ -807,7 +807,7 @@ void Spell::SelectEffectTypeImplicitTargets(uint8 effIndex)
|
||||
|
||||
switch (m_spellInfo->Effects[effIndex].GetImplicitTargetType())
|
||||
{
|
||||
// add explicit object target or self to the target map
|
||||
// add explicit object target or self to the target map
|
||||
case EFFECT_IMPLICIT_TARGET_EXPLICIT:
|
||||
// player which not released his spirit is Unit, but target flag for it is TARGET_FLAG_CORPSE_MASK
|
||||
if (targetMask & (TARGET_FLAG_UNIT_MASK | TARGET_FLAG_CORPSE_MASK))
|
||||
@@ -839,7 +839,7 @@ void Spell::SelectEffectTypeImplicitTargets(uint8 effIndex)
|
||||
AddGOTarget(gObjTarget, 1 << effIndex);
|
||||
}
|
||||
break;
|
||||
// add self to the target map
|
||||
// add self to the target map
|
||||
case EFFECT_IMPLICIT_TARGET_CASTER:
|
||||
if (targetMask & TARGET_FLAG_UNIT_MASK)
|
||||
AddUnitTarget(m_caster, 1 << effIndex, false);
|
||||
|
||||
Reference in New Issue
Block a user