mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-15 23:20:36 +01:00
Core/Spells: Remade trajectory target selection (#19048)
* Remade trajectory target selection * Added possibility to apply conditions to trajectory spells * Properly recalculate delay time if CMSG_UPDATE_PROJECTILE_POSITION is received
This commit is contained in:
@@ -119,6 +119,20 @@ void EventProcessor::AddEvent(BasicEvent* Event, uint64 e_time, bool set_addtime
|
||||
m_events.insert(std::pair<uint64, BasicEvent*>(e_time, Event));
|
||||
}
|
||||
|
||||
void EventProcessor::ModifyEventTime(BasicEvent* Event, uint64 newTime)
|
||||
{
|
||||
for (auto itr = m_events.begin(); itr != m_events.end(); ++itr)
|
||||
{
|
||||
if (itr->second != Event)
|
||||
continue;
|
||||
|
||||
Event->m_execTime = newTime;
|
||||
m_events.erase(itr);
|
||||
m_events.insert(std::pair<uint64, BasicEvent*>(newTime, Event));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint64 EventProcessor::CalculateTime(uint64 t_offset) const
|
||||
{
|
||||
return(m_time + t_offset);
|
||||
|
||||
@@ -79,6 +79,7 @@ class TC_COMMON_API EventProcessor
|
||||
void Update(uint32 p_time);
|
||||
void KillAllEvents(bool force);
|
||||
void AddEvent(BasicEvent* Event, uint64 e_time, bool set_addtime = true);
|
||||
void ModifyEventTime(BasicEvent* Event, uint64 newTime);
|
||||
uint64 CalculateTime(uint64 t_offset) const;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -1627,6 +1627,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) const
|
||||
case TARGET_SELECT_CATEGORY_NEARBY:
|
||||
case TARGET_SELECT_CATEGORY_CONE:
|
||||
case TARGET_SELECT_CATEGORY_AREA:
|
||||
case TARGET_SELECT_CATEGORY_TRAJ:
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
@@ -1637,6 +1638,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) const
|
||||
case TARGET_SELECT_CATEGORY_NEARBY:
|
||||
case TARGET_SELECT_CATEGORY_CONE:
|
||||
case TARGET_SELECT_CATEGORY_AREA:
|
||||
case TARGET_SELECT_CATEGORY_TRAJ:
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -159,11 +159,12 @@ bool Position::HasInArc(float arc, const Position* obj, float border) const
|
||||
return ((angle >= lborder) && (angle <= rborder));
|
||||
}
|
||||
|
||||
bool Position::HasInLine(Position const* pos, float width) const
|
||||
bool Position::HasInLine(Position const* pos, float objSize, float width) const
|
||||
{
|
||||
if (!HasInArc(float(M_PI), pos))
|
||||
return false;
|
||||
|
||||
width += objSize;
|
||||
float angle = GetRelativeAngle(pos);
|
||||
return std::fabs(std::sin(angle)) * GetExactDist2d(pos->GetPositionX(), pos->GetPositionY()) < width;
|
||||
}
|
||||
|
||||
@@ -230,7 +230,7 @@ public:
|
||||
|
||||
bool IsWithinBox(const Position& center, float xradius, float yradius, float zradius) const;
|
||||
bool HasInArc(float arcangle, Position const* pos, float border = 2.0f) const;
|
||||
bool HasInLine(Position const* pos, float width) const;
|
||||
bool HasInLine(Position const* pos, float objSize, float width) const;
|
||||
std::string ToString() const;
|
||||
|
||||
// modulos a radian orientation to the range of 0..2PI
|
||||
|
||||
@@ -701,6 +701,9 @@ void WorldSession::HandleUpdateProjectilePosition(WorldPacket& recvPacket)
|
||||
pos.Relocate(x, y, z);
|
||||
spell->m_targets.ModDst(pos);
|
||||
|
||||
// we changed dest, recalculate flight time
|
||||
spell->RecalculateDelayMomentForDst();
|
||||
|
||||
WorldPacket data(SMSG_SET_PROJECTILE_POSITION, 21);
|
||||
data << uint64(casterGuid);
|
||||
data << uint8(castCount);
|
||||
|
||||
@@ -512,7 +512,7 @@ SpellValue::SpellValue(SpellInfo const* proto)
|
||||
Spell::Spell(Unit* caster, SpellInfo const* info, TriggerCastFlags triggerFlags, ObjectGuid originalCasterGUID, bool skipCheck) :
|
||||
m_spellInfo(sSpellMgr->GetSpellForDifficultyFromSpell(info, caster)),
|
||||
m_caster((info->HasAttribute(SPELL_ATTR6_CAST_BY_CHARMER) && caster->GetCharmerOrOwner()) ? caster->GetCharmerOrOwner() : caster)
|
||||
, m_spellValue(new SpellValue(m_spellInfo)), m_preGeneratedPath(PathGenerator(m_caster))
|
||||
, m_spellValue(new SpellValue(m_spellInfo)), _spellEvent(nullptr), m_preGeneratedPath(PathGenerator(m_caster))
|
||||
{
|
||||
m_customError = SPELL_CUSTOM_ERROR_NONE;
|
||||
m_skipCheck = skipCheck;
|
||||
@@ -801,21 +801,35 @@ void Spell::SelectSpellTargets()
|
||||
}
|
||||
}
|
||||
|
||||
if (uint64 dstDelay = CalculateDelayMomentForDst())
|
||||
m_delayMoment = dstDelay;
|
||||
}
|
||||
|
||||
uint64 Spell::CalculateDelayMomentForDst() const
|
||||
{
|
||||
if (m_targets.HasDst())
|
||||
{
|
||||
if (m_targets.HasTraj())
|
||||
{
|
||||
float speed = m_targets.GetSpeedXY();
|
||||
if (speed > 0.0f)
|
||||
m_delayMoment = (uint64)floor(m_targets.GetDist2d() / speed * 1000.0f);
|
||||
return (uint64)floor(m_targets.GetDist2d() / speed * 1000.0f);
|
||||
}
|
||||
else if (m_spellInfo->Speed > 0.0f)
|
||||
{
|
||||
// We should not subtract caster size from dist calculation (fixes execution time desync with animation on client, eg. Malleable Goo cast by PP)
|
||||
float dist = m_caster->GetExactDist(*m_targets.GetDstPos());
|
||||
m_delayMoment = (uint64) std::floor(dist / m_spellInfo->Speed * 1000.0f);
|
||||
return (uint64)std::floor(dist / m_spellInfo->Speed * 1000.0f);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Spell::RecalculateDelayMomentForDst()
|
||||
{
|
||||
m_delayMoment = CalculateDelayMomentForDst();
|
||||
m_caster->m_Events.ModifyEventTime(_spellEvent, GetDelayStart() + m_delayMoment);
|
||||
}
|
||||
|
||||
void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32& processedEffectMask)
|
||||
@@ -868,6 +882,12 @@ void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTar
|
||||
case TARGET_SELECT_CATEGORY_AREA:
|
||||
SelectImplicitAreaTargets(effIndex, targetType, effectMask);
|
||||
break;
|
||||
case TARGET_SELECT_CATEGORY_TRAJ:
|
||||
// just in case there is no dest, explanation in SelectImplicitDestDestTargets
|
||||
CheckDst();
|
||||
|
||||
SelectImplicitTrajTargets(effIndex, targetType);
|
||||
break;
|
||||
case TARGET_SELECT_CATEGORY_DEFAULT:
|
||||
switch (targetType.GetObjectType())
|
||||
{
|
||||
@@ -1378,9 +1398,6 @@ void Spell::SelectImplicitDestDestTargets(SpellEffIndex effIndex, SpellImplicitT
|
||||
case TARGET_DEST_DYNOBJ_NONE:
|
||||
case TARGET_DEST_DEST:
|
||||
return;
|
||||
case TARGET_DEST_TRAJ:
|
||||
SelectImplicitTrajTargets(effIndex);
|
||||
return;
|
||||
default:
|
||||
{
|
||||
float angle = targetType.CalcDirectionAngle();
|
||||
@@ -1506,9 +1523,7 @@ float tangent(float x)
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
#define DEBUG_TRAJ(a) //a
|
||||
|
||||
void Spell::SelectImplicitTrajTargets(SpellEffIndex effIndex)
|
||||
void Spell::SelectImplicitTrajTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType)
|
||||
{
|
||||
if (!m_targets.HasTraj())
|
||||
return;
|
||||
@@ -1517,12 +1532,14 @@ void Spell::SelectImplicitTrajTargets(SpellEffIndex effIndex)
|
||||
if (!dist2d)
|
||||
return;
|
||||
|
||||
float srcToDestDelta = m_targets.GetDstPos()->m_positionZ - m_targets.GetSrcPos()->m_positionZ;
|
||||
Position srcPos = *m_targets.GetSrcPos();
|
||||
srcPos.SetOrientation(m_caster->GetOrientation());
|
||||
float srcToDestDelta = m_targets.GetDstPos()->m_positionZ - srcPos.m_positionZ;
|
||||
|
||||
std::list<WorldObject*> targets;
|
||||
Trinity::WorldObjectSpellTrajTargetCheck check(dist2d, m_targets.GetSrcPos(), m_caster, m_spellInfo);
|
||||
Trinity::WorldObjectSpellTrajTargetCheck check(dist2d, &srcPos, m_caster, m_spellInfo, targetType.GetCheckType(), m_spellInfo->Effects[effIndex].ImplicitTargetConditions);
|
||||
Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellTrajTargetCheck> searcher(m_caster, targets, check, GRID_MAP_TYPE_MASK_ALL);
|
||||
SearchTargets<Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellTrajTargetCheck> > (searcher, GRID_MAP_TYPE_MASK_ALL, m_caster, m_targets.GetSrcPos(), dist2d);
|
||||
SearchTargets<Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellTrajTargetCheck> > (searcher, GRID_MAP_TYPE_MASK_ALL, m_caster, &srcPos, dist2d);
|
||||
if (targets.empty())
|
||||
return;
|
||||
|
||||
@@ -1532,16 +1549,16 @@ void Spell::SelectImplicitTrajTargets(SpellEffIndex effIndex)
|
||||
float a = (srcToDestDelta - dist2d * b) / (dist2d * dist2d);
|
||||
if (a > -0.0001f)
|
||||
a = 0;
|
||||
DEBUG_TRAJ(TC_LOG_ERROR("spells", "Spell::SelectTrajTargets: a %f b %f", a, b);)
|
||||
|
||||
// We should check if triggered spell has greater range (which is true in many cases, and initial spell has too short max range)
|
||||
// limit max range to 300 yards, sometimes triggered spells can have 50000yds
|
||||
float bestDist = m_spellInfo->GetMaxRange(false);
|
||||
if (SpellInfo const* triggerSpellInfo = sSpellMgr->GetSpellInfo(m_spellInfo->Effects[effIndex].TriggerSpell))
|
||||
bestDist = std::min(std::max(bestDist, triggerSpellInfo->GetMaxRange(false)), std::min(dist2d, 300.0f));
|
||||
|
||||
std::list<WorldObject*>::const_iterator itr = targets.begin();
|
||||
for (; itr != targets.end(); ++itr)
|
||||
{
|
||||
if (!m_caster->HasInLine(*itr, 5.0f))
|
||||
continue;
|
||||
|
||||
if (m_spellInfo->CheckTarget(m_caster, *itr, true) != SPELL_CAST_OK)
|
||||
continue;
|
||||
|
||||
@@ -1557,104 +1574,33 @@ void Spell::SelectImplicitTrajTargets(SpellEffIndex effIndex)
|
||||
}
|
||||
}
|
||||
|
||||
const float size = std::max((*itr)->GetObjectSize() * 0.7f, 1.0f); // 1/sqrt(3)
|
||||
/// @todo all calculation should be based on src instead of m_caster
|
||||
const float objDist2d = m_targets.GetSrcPos()->GetExactDist2d(*itr) * std::cos(m_targets.GetSrcPos()->GetRelativeAngle(*itr));
|
||||
const float dz = (*itr)->GetPositionZ() - m_targets.GetSrcPos()->m_positionZ;
|
||||
const float size = std::max((*itr)->GetObjectSize(), 1.0f);
|
||||
const float objDist2d = srcPos.GetExactDist2d(*itr);
|
||||
const float dz = (*itr)->GetPositionZ() - srcPos.m_positionZ;
|
||||
|
||||
DEBUG_TRAJ(TC_LOG_ERROR("spells", "Spell::SelectTrajTargets: check %u, dist between %f %f, height between %f %f.", (*itr)->GetEntry(), objDist2d - size, objDist2d + size, dz - size, dz + size);)
|
||||
|
||||
float dist = objDist2d - size;
|
||||
float height = dist * (a * dist + b);
|
||||
DEBUG_TRAJ(TC_LOG_ERROR("spells", "Spell::SelectTrajTargets: dist %f, height %f.", dist, height);)
|
||||
if (dist < bestDist && height < dz + size && height > dz - size)
|
||||
{
|
||||
bestDist = dist > 0 ? dist : 0;
|
||||
break;
|
||||
}
|
||||
|
||||
#define CHECK_DIST {\
|
||||
DEBUG_TRAJ(TC_LOG_ERROR("spells", "Spell::SelectTrajTargets: dist %f, height %f.", dist, height);)\
|
||||
if (dist > bestDist)\
|
||||
continue;\
|
||||
if (dist < objDist2d + size && dist > objDist2d - size)\
|
||||
{\
|
||||
bestDist = dist;\
|
||||
break;\
|
||||
}\
|
||||
}
|
||||
|
||||
if (!a)
|
||||
{
|
||||
height = dz - size;
|
||||
dist = height / b;
|
||||
CHECK_DIST;
|
||||
|
||||
height = dz + size;
|
||||
dist = height / b;
|
||||
CHECK_DIST;
|
||||
const float horizontalDistToTraj = std::fabs(objDist2d * std::sin(srcPos.GetRelativeAngle(*itr)));
|
||||
const float sizeFactor = std::cos((horizontalDistToTraj / size) * (M_PI / 2.0f));
|
||||
const float distToHitPoint = std::max(objDist2d * std::cos(srcPos.GetRelativeAngle(*itr)) - size * sizeFactor, 0.0f);
|
||||
const float height = distToHitPoint * (a * distToHitPoint + b);
|
||||
|
||||
if (fabs(dz - height) > size + b / 2.0f + TRAJECTORY_MISSILE_SIZE)
|
||||
continue;
|
||||
}
|
||||
|
||||
height = dz - size;
|
||||
float sqrt1 = b * b + 4 * a * height;
|
||||
if (sqrt1 > 0)
|
||||
if (distToHitPoint < bestDist)
|
||||
{
|
||||
sqrt1 = std::sqrt(sqrt1);
|
||||
dist = (sqrt1 - b) / (2 * a);
|
||||
CHECK_DIST;
|
||||
}
|
||||
|
||||
height = dz + size;
|
||||
float sqrt2 = b * b + 4 * a * height;
|
||||
if (sqrt2 > 0)
|
||||
{
|
||||
sqrt2 = std::sqrt(sqrt2);
|
||||
dist = (sqrt2 - b) / (2 * a);
|
||||
CHECK_DIST;
|
||||
|
||||
dist = (-sqrt2 - b) / (2 * a);
|
||||
CHECK_DIST;
|
||||
}
|
||||
|
||||
if (sqrt1 > 0)
|
||||
{
|
||||
dist = (-sqrt1 - b) / (2 * a);
|
||||
CHECK_DIST;
|
||||
bestDist = distToHitPoint;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_targets.GetSrcPos()->GetExactDist2d(m_targets.GetDstPos()) > bestDist)
|
||||
if (dist2d > bestDist)
|
||||
{
|
||||
float x = m_targets.GetSrcPos()->m_positionX + std::cos(m_caster->GetOrientation()) * bestDist;
|
||||
float y = m_targets.GetSrcPos()->m_positionY + std::sin(m_caster->GetOrientation()) * bestDist;
|
||||
float z = m_targets.GetSrcPos()->m_positionZ + bestDist * (a * bestDist + b);
|
||||
|
||||
if (itr != targets.end())
|
||||
{
|
||||
float distSq = (*itr)->GetExactDistSq(x, y, z);
|
||||
float sizeSq = (*itr)->GetObjectSize();
|
||||
sizeSq *= sizeSq;
|
||||
DEBUG_TRAJ(TC_LOG_ERROR("spells", "Initial %f %f %f %f %f", x, y, z, distSq, sizeSq);)
|
||||
if (distSq > sizeSq)
|
||||
{
|
||||
float factor = 1 - std::sqrt(sizeSq / distSq);
|
||||
x += factor * ((*itr)->GetPositionX() - x);
|
||||
y += factor * ((*itr)->GetPositionY() - y);
|
||||
z += factor * ((*itr)->GetPositionZ() - z);
|
||||
|
||||
distSq = (*itr)->GetExactDistSq(x, y, z);
|
||||
DEBUG_TRAJ(TC_LOG_ERROR("spells", "Initial %f %f %f %f %f", x, y, z, distSq, sizeSq);)
|
||||
}
|
||||
}
|
||||
|
||||
Position trajDst;
|
||||
trajDst.Relocate(x, y, z, m_caster->GetOrientation());
|
||||
SpellDestination dest(*m_targets.GetDst());
|
||||
dest.Relocate(trajDst);
|
||||
|
||||
CallScriptDestinationTargetSelectHandlers(dest, effIndex, SpellImplicitTargetInfo(TARGET_DEST_TRAJ));
|
||||
SpellDestination dest(x, y, z, m_caster->GetOrientation());
|
||||
CallScriptDestinationTargetSelectHandlers(dest, effIndex, targetType);
|
||||
m_targets.ModDst(dest);
|
||||
}
|
||||
}
|
||||
@@ -2916,8 +2862,8 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered
|
||||
m_triggeredByAuraSpell = triggeredByAura->GetSpellInfo();
|
||||
|
||||
// create and add update event for this spell
|
||||
SpellEvent* Event = new SpellEvent(this);
|
||||
m_caster->m_Events.AddEvent(Event, m_caster->m_Events.CalculateTime(1));
|
||||
_spellEvent = new SpellEvent(this);
|
||||
m_caster->m_Events.AddEvent(_spellEvent, m_caster->m_Events.CalculateTime(1));
|
||||
|
||||
//Prevent casting at cast another spell (ServerSide check)
|
||||
if (!(_triggeredCastFlags & TRIGGERED_IGNORE_CAST_IN_PROGRESS) && m_caster->IsNonMeleeSpellCast(false, true, true) && m_cast_count)
|
||||
@@ -7685,9 +7631,9 @@ WorldObjectSpellTargetCheck::WorldObjectSpellTargetCheck(Unit* caster, Unit* ref
|
||||
_targetSelectionType(selectionType), _condList(condList)
|
||||
{
|
||||
if (condList)
|
||||
_condSrcInfo = new ConditionSourceInfo(NULL, caster);
|
||||
_condSrcInfo = new ConditionSourceInfo(nullptr, caster);
|
||||
else
|
||||
_condSrcInfo = NULL;
|
||||
_condSrcInfo = nullptr;
|
||||
}
|
||||
|
||||
WorldObjectSpellTargetCheck::~WorldObjectSpellTargetCheck()
|
||||
@@ -7793,7 +7739,7 @@ bool WorldObjectSpellConeTargetCheck::operator()(WorldObject* target)
|
||||
}
|
||||
else if (_spellInfo->HasAttribute(SPELL_ATTR0_CU_CONE_LINE))
|
||||
{
|
||||
if (!_caster->HasInLine(target, _caster->GetObjectSize() + target->GetObjectSize()))
|
||||
if (!_caster->HasInLine(target, target->GetObjectSize(), _caster->GetObjectSize()))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
@@ -7804,15 +7750,19 @@ bool WorldObjectSpellConeTargetCheck::operator()(WorldObject* target)
|
||||
return WorldObjectSpellAreaTargetCheck::operator ()(target);
|
||||
}
|
||||
|
||||
WorldObjectSpellTrajTargetCheck::WorldObjectSpellTrajTargetCheck(float range, Position const* position, Unit* caster, SpellInfo const* spellInfo)
|
||||
: WorldObjectSpellAreaTargetCheck(range, position, caster, caster, spellInfo, TARGET_CHECK_DEFAULT, NULL) { }
|
||||
WorldObjectSpellTrajTargetCheck::WorldObjectSpellTrajTargetCheck(float range, Position const* position, Unit* caster, SpellInfo const* spellInfo, SpellTargetCheckTypes selectionType, ConditionContainer* condList)
|
||||
: WorldObjectSpellTargetCheck(caster, caster, spellInfo, selectionType, condList), _range(range), _position(position) { }
|
||||
|
||||
bool WorldObjectSpellTrajTargetCheck::operator()(WorldObject* target)
|
||||
{
|
||||
// return all targets on missile trajectory (0 - size of a missile)
|
||||
if (!_caster->HasInLine(target, target->GetObjectSize()))
|
||||
if (!_caster->HasInLine(target, target->GetObjectSize(), TRAJECTORY_MISSILE_SIZE))
|
||||
return false;
|
||||
return WorldObjectSpellAreaTargetCheck::operator ()(target);
|
||||
|
||||
if (target->GetExactDist2d(_position) > _range)
|
||||
return false;
|
||||
|
||||
return WorldObjectSpellTargetCheck::operator ()(target);
|
||||
}
|
||||
|
||||
} //namespace Trinity
|
||||
|
||||
@@ -33,9 +33,11 @@ class WorldObject;
|
||||
class Aura;
|
||||
class SpellScript;
|
||||
class ByteBuffer;
|
||||
class SpellEvent;
|
||||
|
||||
#define SPELL_CHANNEL_UPDATE_INTERVAL (1 * IN_MILLISECONDS)
|
||||
#define MAX_SPELL_RANGE_TOLERANCE 3.0f
|
||||
#define TRAJECTORY_MISSILE_SIZE 3.0f
|
||||
|
||||
enum SpellCastFlags
|
||||
{
|
||||
@@ -373,7 +375,7 @@ class TC_GAME_API Spell
|
||||
void SelectImplicitCasterObjectTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType);
|
||||
void SelectImplicitTargetObjectTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType);
|
||||
void SelectImplicitChainTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, WorldObject* target, uint32 effMask);
|
||||
void SelectImplicitTrajTargets(SpellEffIndex effIndex);
|
||||
void SelectImplicitTrajTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType);
|
||||
|
||||
void SelectEffectTypeImplicitTargets(uint8 effIndex);
|
||||
|
||||
@@ -497,6 +499,8 @@ class TC_GAME_API Spell
|
||||
uint64 GetDelayStart() const { return m_delayStart; }
|
||||
void SetDelayStart(uint64 m_time) { m_delayStart = m_time; }
|
||||
uint64 GetDelayMoment() const { return m_delayMoment; }
|
||||
uint64 CalculateDelayMomentForDst() const;
|
||||
void RecalculateDelayMomentForDst();
|
||||
|
||||
bool IsNeedSendToClient() const;
|
||||
|
||||
@@ -694,6 +698,7 @@ class TC_GAME_API Spell
|
||||
uint32 m_spellState;
|
||||
int32 m_timer;
|
||||
|
||||
SpellEvent* _spellEvent;
|
||||
TriggerCastFlags _triggeredCastFlags;
|
||||
|
||||
// if need this can be replaced by Aura copy
|
||||
@@ -754,9 +759,12 @@ namespace Trinity
|
||||
bool operator()(WorldObject* target);
|
||||
};
|
||||
|
||||
struct TC_GAME_API WorldObjectSpellTrajTargetCheck : public WorldObjectSpellAreaTargetCheck
|
||||
struct TC_GAME_API WorldObjectSpellTrajTargetCheck : public WorldObjectSpellTargetCheck
|
||||
{
|
||||
WorldObjectSpellTrajTargetCheck(float range, Position const* position, Unit* caster, SpellInfo const* spellInfo);
|
||||
float _range;
|
||||
Position const* _position;
|
||||
WorldObjectSpellTrajTargetCheck(float range, Position const* position, Unit* caster,
|
||||
SpellInfo const* spellInfo, SpellTargetCheckTypes selectionType, ConditionContainer* condList);
|
||||
bool operator()(WorldObject* target);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -298,7 +298,7 @@ SpellImplicitTargetInfo::StaticData SpellImplicitTargetInfo::_data[TOTAL_SPELL_
|
||||
{TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 86 TARGET_DEST_DEST_RANDOM
|
||||
{TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 87 TARGET_DEST_DEST
|
||||
{TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 88 TARGET_DEST_DYNOBJ_NONE
|
||||
{TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 89 TARGET_DEST_TRAJ
|
||||
{TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_TRAJ, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 89 TARGET_DEST_TRAJ
|
||||
{TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 90 TARGET_UNIT_TARGET_MINIPET
|
||||
{TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 91 TARGET_DEST_DEST_RADIUS
|
||||
{TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 92 TARGET_UNIT_SUMMONER
|
||||
|
||||
@@ -82,7 +82,8 @@ enum SpellTargetSelectionCategories
|
||||
TARGET_SELECT_CATEGORY_CHANNEL,
|
||||
TARGET_SELECT_CATEGORY_NEARBY,
|
||||
TARGET_SELECT_CATEGORY_CONE,
|
||||
TARGET_SELECT_CATEGORY_AREA
|
||||
TARGET_SELECT_CATEGORY_AREA,
|
||||
TARGET_SELECT_CATEGORY_TRAJ
|
||||
};
|
||||
|
||||
enum SpellTargetReferenceTypes
|
||||
|
||||
@@ -2744,6 +2744,24 @@ void SpellMgr::LoadSpellInfoCorrections()
|
||||
if (!spellInfo)
|
||||
continue;
|
||||
|
||||
// Fix range for trajectory triggered spell
|
||||
for (uint8 j = 0; j < MAX_SPELL_EFFECTS; ++j)
|
||||
{
|
||||
if (spellInfo->Effects[j].IsEffect() && (spellInfo->Effects[j].TargetA.GetTarget() == TARGET_DEST_TRAJ || spellInfo->Effects[j].TargetB.GetTarget() == TARGET_DEST_TRAJ))
|
||||
{
|
||||
// Get triggered spell if any
|
||||
if (SpellInfo* spellInfoTrigger = const_cast<SpellInfo*>(GetSpellInfo(spellInfo->Effects[j].TriggerSpell)))
|
||||
{
|
||||
float maxRangeMain = spellInfo->RangeEntry ? spellInfo->RangeEntry->maxRangeHostile : 0.0f;
|
||||
float maxRangeTrigger = spellInfoTrigger->RangeEntry ? spellInfoTrigger->RangeEntry->maxRangeHostile : 0.0f;
|
||||
|
||||
// check if triggered spell has enough max range to cover trajectory
|
||||
if (maxRangeTrigger < maxRangeMain)
|
||||
spellInfoTrigger->RangeEntry = spellInfo->RangeEntry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8 j = 0; j < MAX_SPELL_EFFECTS; ++j)
|
||||
{
|
||||
switch (spellInfo->Effects[j].Effect)
|
||||
|
||||
Reference in New Issue
Block a user