Core/Spells: fix wrong distance calculations in AoE spells

Port From (https://github.com/TrinityCore/TrinityCore/commit/5d076cfe291980bc5be9d44ffbae887e3dd5ad59)
This commit is contained in:
hondacrx
2020-05-06 14:34:20 -04:00
parent 95cca081de
commit ba885908b7
29 changed files with 202 additions and 118 deletions
+5 -5
View File
@@ -2583,7 +2583,7 @@ namespace Game.Spells
case SpellEffectName.ApplyAreaAuraRaid:
{
targetList.Add(GetUnitOwner());
var u_check = new AnyGroupedUnitInObjectRangeCheck(GetUnitOwner(), GetUnitOwner(), radius, effect.Effect == SpellEffectName.ApplyAreaAuraRaid);
var u_check = new AnyGroupedUnitInObjectRangeCheck(GetUnitOwner(), GetUnitOwner(), radius, effect.Effect == SpellEffectName.ApplyAreaAuraRaid, GetSpellInfo().HasAttribute(SpellAttr3.OnlyTargetPlayers), false, true);
var searcher = new UnitListSearcher(GetUnitOwner(), targetList, u_check);
Cell.VisitAllObjects(GetUnitOwner(), searcher, radius);
break;
@@ -2591,14 +2591,14 @@ namespace Game.Spells
case SpellEffectName.ApplyAreaAuraFriend:
{
targetList.Add(GetUnitOwner());
var u_check = new AnyFriendlyUnitInObjectRangeCheck(GetUnitOwner(), GetUnitOwner(), radius);
var u_check = new AnyFriendlyUnitInObjectRangeCheck(GetUnitOwner(), GetUnitOwner(), radius, GetSpellInfo().HasAttribute(SpellAttr3.OnlyTargetPlayers), false, true);
var searcher = new UnitListSearcher(GetUnitOwner(), targetList, u_check);
Cell.VisitAllObjects(GetUnitOwner(), searcher, radius);
break;
}
case SpellEffectName.ApplyAreaAuraEnemy:
{
var u_check = new AnyAoETargetUnitInObjectRangeCheck(GetUnitOwner(), GetUnitOwner(), radius);
var u_check = new AnyAoETargetUnitInObjectRangeCheck(GetUnitOwner(), GetUnitOwner(), radius, GetSpellInfo(), false, true);
var searcher = new UnitListSearcher(GetUnitOwner(), targetList, u_check);
Cell.VisitAllObjects(GetUnitOwner(), searcher, radius);
break;
@@ -2669,13 +2669,13 @@ namespace Game.Spells
List<Unit> targetList = new List<Unit>();
if (effect.TargetB.GetTarget() == Targets.DestDynobjAlly || effect.TargetB.GetTarget() == Targets.UnitDestAreaAlly)
{
var u_check = new AnyFriendlyUnitInObjectRangeCheck(GetDynobjOwner(), dynObjOwnerCaster, radius, GetSpellInfo().HasAttribute(SpellAttr3.OnlyTargetPlayers));
var u_check = new AnyFriendlyUnitInObjectRangeCheck(GetDynobjOwner(), dynObjOwnerCaster, radius, GetSpellInfo().HasAttribute(SpellAttr3.OnlyTargetPlayers), false, true);
var searcher = new UnitListSearcher(GetDynobjOwner(), targetList, u_check);
Cell.VisitAllObjects(GetDynobjOwner(), searcher, radius);
}
else
{
var u_check = new AnyAoETargetUnitInObjectRangeCheck(GetDynobjOwner(), dynObjOwnerCaster, radius);
var u_check = new AnyAoETargetUnitInObjectRangeCheck(GetDynobjOwner(), dynObjOwnerCaster, radius, null, false, true);
var searcher = new UnitListSearcher(GetDynobjOwner(), targetList, u_check);
Cell.VisitAllObjects(GetDynobjOwner(), searcher, radius);
}
+28 -12
View File
@@ -735,7 +735,12 @@ namespace Game.Spells
SpellEffectInfo effect = GetEffect(effIndex);
if (effect == null)
return;
float radius = effect.CalcRadius(m_caster) * m_spellValue.RadiusMod;
// if this is a proximity based aoe (Frost Nova, Psychic Scream, ...), include the caster's own combat reach
if (targetType.IsProximityBasedAoe())
radius += GetCaster().GetCombatReach();
SearchAreaTargets(targets, radius, center, referer, targetType.GetObjectType(), targetType.GetCheckType(), effect.ImplicitTargetConditions);
CallScriptObjectAreaTargetSelectHandlers(targets, effIndex, targetType);
@@ -797,7 +802,7 @@ namespace Game.Spells
float dis = (float)RandomHelper.NextDouble() * (maxDist - minDist) + minDist;
float x, y, z;
float angle = (float)RandomHelper.NextDouble() * (MathFunctions.PI * 35.0f / 180.0f) - (float)(Math.PI * 17.5f / 180.0f);
m_caster.GetClosePoint(out x, out y, out z, SharedConst.DefaultWorldObjectSize, dis, angle);
m_caster.GetClosePoint(out x, out y, out z, SharedConst.DefaultPlayerBoundingRadius, dis, angle);
float ground = m_caster.GetMap().GetHeight(m_caster.GetPhaseShift(), x, y, z, true, 50.0f);
float liquidLevel = MapConst.VMAPInvalidHeightValue;
@@ -830,7 +835,7 @@ namespace Game.Spells
{
float dist = effect.CalcRadius(m_caster);
float angl = targetType.CalcDirectionAngle();
float objSize = m_caster.GetObjectSize();
float objSize = m_caster.GetCombatReach();
switch (targetType.GetTarget())
{
@@ -885,7 +890,7 @@ namespace Game.Spells
if (effect != null)
{
float angle = targetType.CalcDirectionAngle();
float objSize = target.GetObjectSize();
float objSize = target.GetCombatReach();
float dist = effect.CalcRadius(m_caster);
if (dist < objSize)
dist = objSize;
@@ -1108,7 +1113,7 @@ namespace Game.Spells
}
}
float size = Math.Max(obj.GetObjectSize(), 1.0f);
float size = Math.Max(obj.GetCombatReach(), 1.0f);
float objDist2d = srcPos.GetExactDist2d(obj);
float dz = obj.GetPositionZ() - srcPos.posZ;
@@ -4843,12 +4848,12 @@ namespace Game.Spells
if (!target.IsWithinLOSInMap(m_caster)) //Do full LoS/Path check. Don't exclude m2
return SpellCastResult.LineOfSight;
float objSize = target.GetObjectSize();
float objSize = target.GetCombatReach();
float range = m_spellInfo.GetMaxRange(true, m_caster, this) * 1.5f + objSize; // can't be overly strict
m_preGeneratedPath.SetPathLengthLimit(range);
//first try with raycast, if it fails fall back to normal path
float targetObjectSize = Math.Min(target.GetObjectSize(), 4.0f);
float targetObjectSize = Math.Min(target.GetCombatReach(), 4.0f);
bool result = m_preGeneratedPath.CalculatePath(target.GetPositionX(), target.GetPositionY(), target.GetPositionZ() + targetObjectSize, false, true);
if (m_preGeneratedPath.GetPathType().HasAnyFlag(PathType.Short))
return SpellCastResult.OutOfRange;
@@ -7746,8 +7751,7 @@ namespace Game.Spells
{
float _range;
Position _position;
public WorldObjectSpellAreaTargetCheck(float range, Position position, Unit caster,
Unit referer, SpellInfo spellInfo, SpellTargetCheckTypes selectionType, List<Condition> condList)
public WorldObjectSpellAreaTargetCheck(float range, Position position, Unit caster, Unit referer, SpellInfo spellInfo, SpellTargetCheckTypes selectionType, List<Condition> condList)
: base(caster, referer, spellInfo, selectionType, condList)
{
_range = range;
@@ -7757,8 +7761,20 @@ namespace Game.Spells
public override bool Invoke(WorldObject target)
{
if (!target.IsWithinDist3d(_position, _range) && !(target.IsTypeId(TypeId.GameObject) && target.ToGameObject().IsInRange(_position.posX, _position.posY, _position.posZ, _range)))
return false;
if (target.ToGameObject())
{
// isInRange including the dimension of the GO
bool isInRange = target.ToGameObject().IsInRange(_position.GetPositionX(), _position.GetPositionY(), _position.GetPositionZ(), _range);
if (!isInRange)
return false;
}
else
{
bool isInsideCylinder = target.IsWithinDist2d(_position, _range) && Math.Abs(target.GetPositionZ() - _position.GetPositionZ()) <= _range;
if (!isInsideCylinder)
return false;
}
return base.Invoke(target);
}
}
@@ -7780,7 +7796,7 @@ namespace Game.Spells
}
else if (_spellInfo.HasAttribute(SpellCustomAttributes.ConeLine))
{
if (!_caster.HasInLine(target, target.GetObjectSize(), _caster.GetObjectSize()))
if (!_caster.HasInLine(target, target.GetCombatReach(), _caster.GetCombatReach()))
return false;
}
else
@@ -7812,7 +7828,7 @@ namespace Game.Spells
public override bool Invoke(WorldObject target)
{
// return all targets on missile trajectory (0 - size of a missile)
if (!_caster.HasInLine(target, target.GetObjectSize(), SpellConst.TrajectoryMissileSize))
if (!_caster.HasInLine(target, target.GetCombatReach(), SpellConst.TrajectoryMissileSize))
return false;
if (target.GetExactDist2d(_position) > _range)
+9 -9
View File
@@ -2034,7 +2034,7 @@ namespace Game.Spells
float dis = effectInfo.CalcRadius(m_caster);
float fx, fy, fz;
m_caster.GetClosePoint(out fx, out fy, out fz, unitTarget.GetObjectSize(), dis);
m_caster.GetClosePoint(out fx, out fy, out fz, unitTarget.GetCombatReach(), dis);
unitTarget.NearTeleportTo(fx, fy, fz, -m_caster.GetOrientation(), unitTarget == m_caster);
}
@@ -2385,7 +2385,7 @@ namespace Game.Spells
Cypher.Assert(OldSummon.GetMap() == owner.GetMap());
float px, py, pz;
owner.GetClosePoint(out px, out py, out pz, OldSummon.GetObjectSize());
owner.GetClosePoint(out px, out py, out pz, OldSummon.GetCombatReach());
OldSummon.NearTeleportTo(px, py, pz, OldSummon.GetOrientation());
@@ -2402,7 +2402,7 @@ namespace Game.Spells
}
float x, y, z;
owner.GetClosePoint(out x, out y, out z, owner.GetObjectSize());
owner.GetClosePoint(out x, out y, out z, owner.GetCombatReach());
Pet pet = owner.SummonPet(petentry, x, y, z, owner.Orientation, PetType.Summon, 0);
if (!pet)
return;
@@ -2791,7 +2791,7 @@ namespace Game.Spells
if (m_targets.HasDst())
destTarget.GetPosition(out x, out y, out z);
else
m_caster.GetClosePoint(out x, out y, out z, SharedConst.DefaultWorldObjectSize);
m_caster.GetClosePoint(out x, out y, out z, SharedConst.DefaultPlayerBoundingRadius);
Map map = target.GetMap();
@@ -3790,7 +3790,7 @@ namespace Game.Spells
destTarget.GetPosition(out x, out y, out z);
// Summon in random point all other units if location present
else
m_caster.GetClosePoint(out x, out y, out z, SharedConst.DefaultWorldObjectSize);
m_caster.GetClosePoint(out x, out y, out z, SharedConst.DefaultPlayerBoundingRadius);
Map map = m_caster.GetMap();
Position pos = new Position(x, y, z, m_caster.GetOrientation());
@@ -4094,7 +4094,7 @@ namespace Game.Spells
// Spell is not using explicit target - no generated path
if (m_preGeneratedPath.GetPathType() == PathType.Blank)
{
Position pos = unitTarget.GetFirstCollisionPosition(unitTarget.GetObjectSize(), unitTarget.GetRelativeAngle(m_caster.GetPosition()));
Position pos = unitTarget.GetFirstCollisionPosition(unitTarget.GetCombatReach(), unitTarget.GetRelativeAngle(m_caster.GetPosition()));
if (MathFunctions.fuzzyGt(m_spellInfo.Speed, 0.0f) && m_spellInfo.HasAttribute(SpellAttr9.SpecialDelayCalculation))
speed = pos.GetExactDist(m_caster) / speed;
@@ -4530,7 +4530,7 @@ namespace Game.Spells
else if (effectInfo.HasRadius() && m_spellInfo.Speed == 0)
{
float dis = effectInfo.CalcRadius(m_originalCaster);
m_caster.GetClosePoint(out fx, out fy, out fz, SharedConst.DefaultWorldObjectSize, dis);
m_caster.GetClosePoint(out fx, out fy, out fz, SharedConst.DefaultPlayerBoundingRadius, dis);
}
else
{
@@ -4539,7 +4539,7 @@ namespace Game.Spells
float max_dis = m_spellInfo.GetMaxRange(true);
float dis = (float)RandomHelper.NextDouble() * (max_dis - min_dis) + min_dis;
m_caster.GetClosePoint(out fx, out fy, out fz, SharedConst.DefaultWorldObjectSize, dis);
m_caster.GetClosePoint(out fx, out fy, out fz, SharedConst.DefaultPlayerBoundingRadius, dis);
}
Map cMap = m_caster.GetMap();
@@ -4938,7 +4938,7 @@ namespace Game.Spells
// relocate
float px, py, pz;
unitTarget.GetClosePoint(out px, out py, out pz, pet.GetObjectSize(), SharedConst.PetFollowDist, pet.GetFollowAngle());
unitTarget.GetClosePoint(out px, out py, out pz, pet.GetCombatReach(), SharedConst.PetFollowDist, pet.GetFollowAngle());
pet.Relocate(px, py, pz, unitTarget.GetOrientation());
// add to world
+28
View File
@@ -4598,6 +4598,34 @@ namespace Game.Spells
return GetSelectionCategory() == SpellTargetSelectionCategories.Area || GetSelectionCategory() == SpellTargetSelectionCategories.Cone;
}
public bool IsProximityBasedAoe()
{
switch (_target)
{
case Targets.UnitSrcAreaEntry:
case Targets.UnitSrcAreaEnemy:
case Targets.UnitCasterAreaParty:
case Targets.UnitSrcAreaAlly:
case Targets.UnitSrcAreaParty:
case Targets.UnitLastAreaParty:
case Targets.GameobjectSrcArea:
case Targets.UnitCasterAreaRaid:
case Targets.CorpseSrcAreaEnemy:
return true;
case Targets.UnitDestAreaEntry:
case Targets.UnitDestAreaEnemy:
case Targets.UnitDestAreaAlly:
case Targets.UnitDestAreaParty:
case Targets.GameobjectDestArea:
case Targets.UnitAreaRaidClass:
return false;
default:
Log.outWarn(LogFilter.Spells, "SpellImplicitTargetInfo.IsProximityBasedAoe called a non-aoe spell");
return false;
}
}
public SpellTargetSelectionCategories GetSelectionCategory()
{
return _data[(int)_target].SelectionCategory;