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:
Shauren
2011-09-24 19:40:57 +02:00
parent cd7060c65a
commit da0229da8f
5 changed files with 87 additions and 8 deletions
+46
View File
@@ -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();
}
+26
View File
@@ -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:
+11 -4
View File
@@ -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;
+2 -2
View File
@@ -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);
+2 -2
View File
@@ -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);