diff options
34 files changed, 207 insertions, 122 deletions
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 3aec5cc1876..8da23deffd2 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -2343,7 +2343,7 @@ bool Creature::CanCreatureAttack(Unit const* victim, bool /*force*/) const else { // include sizes for huge npcs - dist += GetObjectSize() + victim->GetObjectSize(); + dist += GetCombatReach() + victim->GetCombatReach(); // to prevent creatures in air ignore attacks because distance is already too high... if (GetCreatureTemplate()->InhabitType & INHABIT_AIR) @@ -2946,7 +2946,7 @@ void Creature::SetObjectScale(float scale) if (CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelInfo(GetDisplayId())) { SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, (IsPet() ? 1.0f : minfo->bounding_radius) * scale); - SetFloatValue(UNIT_FIELD_COMBATREACH, (IsPet() ? DEFAULT_COMBAT_REACH : minfo->combat_reach) * scale); + SetFloatValue(UNIT_FIELD_COMBATREACH, (IsPet() ? DEFAULT_PLAYER_COMBAT_REACH : minfo->combat_reach) * scale); } } @@ -2957,7 +2957,7 @@ void Creature::SetDisplayId(uint32 modelId) if (CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelInfo(modelId)) { SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, (IsPet() ? 1.0f : minfo->bounding_radius) * GetObjectScale()); - SetFloatValue(UNIT_FIELD_COMBATREACH, (IsPet() ? DEFAULT_COMBAT_REACH : minfo->combat_reach) * GetObjectScale()); + SetFloatValue(UNIT_FIELD_COMBATREACH, (IsPet() ? DEFAULT_PLAYER_COMBAT_REACH : minfo->combat_reach) * GetObjectScale()); } } diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h index 4ef0c9c2e5f..bad48e0693d 100644 --- a/src/server/game/Entities/GameObject/GameObject.h +++ b/src/server/game/Entities/GameObject/GameObject.h @@ -946,7 +946,7 @@ class TC_GAME_API GameObject : public WorldObject, public GridObject<GameObject> void UpdatePackedRotation(); //! Object distance/size - overridden from Object::_IsWithinDist. Needs to take in account proper GO size. - bool _IsWithinDist(WorldObject const* obj, float dist2compare, bool /*is3D*/) const override + bool _IsWithinDist(WorldObject const* obj, float dist2compare, bool /*is3D*/, bool /*incOwnRadius*/, bool /*incTargetRadius*/) const override { //! Following check does check 3d distance return IsInRange(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), dist2compare); diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 70c8e2f46c2..39a058b80d8 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -1108,39 +1108,31 @@ InstanceScript* WorldObject::GetInstanceScript() float WorldObject::GetDistanceZ(const WorldObject* obj) const { float dz = std::fabs(GetPositionZ() - obj->GetPositionZ()); - float sizefactor = GetObjectSize() + obj->GetObjectSize(); + float sizefactor = GetCombatReach() + obj->GetCombatReach(); float dist = dz - sizefactor; return (dist > 0 ? dist : 0); } -bool WorldObject::_IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D) const +bool WorldObject::_IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D, bool incOwnRadius, bool incTargetRadius) const { - float sizefactor = GetObjectSize() + obj->GetObjectSize(); + float sizefactor = 0; + sizefactor += incOwnRadius ? GetCombatReach() : 0.0f; + sizefactor += incTargetRadius ? obj->GetCombatReach() : 0.0f; float maxdist = dist2compare + sizefactor; + Position const* thisOrTransport = this; + Position const* objOrObjTransport = obj; + if (GetTransport() && obj->GetTransport() && obj->GetTransport()->GetGUID().GetCounter() == GetTransport()->GetGUID().GetCounter()) { - float dtx = m_movementInfo.transport.pos.m_positionX - obj->m_movementInfo.transport.pos.m_positionX; - float dty = m_movementInfo.transport.pos.m_positionY - obj->m_movementInfo.transport.pos.m_positionY; - float disttsq = dtx * dtx + dty * dty; - if (is3D) - { - float dtz = m_movementInfo.transport.pos.m_positionZ - obj->m_movementInfo.transport.pos.m_positionZ; - disttsq += dtz * dtz; - } - return disttsq < (maxdist * maxdist); + thisOrTransport = &m_movementInfo.transport.pos; + objOrObjTransport = &obj->m_movementInfo.transport.pos; } - float dx = GetPositionX() - obj->GetPositionX(); - float dy = GetPositionY() - obj->GetPositionY(); - float distsq = dx*dx + dy*dy; if (is3D) - { - float dz = GetPositionZ() - obj->GetPositionZ(); - distsq += dz*dz; - } - - return distsq < maxdist * maxdist; + return thisOrTransport->IsInDist(objOrObjTransport, maxdist); + else + return thisOrTransport->IsInDist2d(objOrObjTransport, maxdist); } bool WorldObject::IsWithinLOSInMap(const WorldObject* obj, VMAP::ModelIgnoreFlags ignoreFlags) const @@ -1159,31 +1151,31 @@ bool WorldObject::IsWithinLOSInMap(const WorldObject* obj, VMAP::ModelIgnoreFlag float WorldObject::GetDistance(const WorldObject* obj) const { - float d = GetExactDist(obj) - GetObjectSize() - obj->GetObjectSize(); + float d = GetExactDist(obj) - GetCombatReach() - obj->GetCombatReach(); return d > 0.0f ? d : 0.0f; } float WorldObject::GetDistance(const Position &pos) const { - float d = GetExactDist(&pos) - GetObjectSize(); + float d = GetExactDist(&pos) - GetCombatReach(); return d > 0.0f ? d : 0.0f; } float WorldObject::GetDistance(float x, float y, float z) const { - float d = GetExactDist(x, y, z) - GetObjectSize(); + float d = GetExactDist(x, y, z) - GetCombatReach(); return d > 0.0f ? d : 0.0f; } float WorldObject::GetDistance2d(const WorldObject* obj) const { - float d = GetExactDist2d(obj) - GetObjectSize() - obj->GetObjectSize(); + float d = GetExactDist2d(obj) - GetCombatReach() - obj->GetCombatReach(); return d > 0.0f ? d : 0.0f; } float WorldObject::GetDistance2d(float x, float y) const { - float d = GetExactDist2d(x, y) - GetObjectSize(); + float d = GetExactDist2d(x, y) - GetCombatReach(); return d > 0.0f ? d : 0.0f; } @@ -1203,22 +1195,22 @@ bool WorldObject::IsInMap(const WorldObject* obj) const bool WorldObject::IsWithinDist3d(float x, float y, float z, float dist) const { - return IsInDist(x, y, z, dist + GetObjectSize()); + return IsInDist(x, y, z, dist + GetCombatReach()); } bool WorldObject::IsWithinDist3d(const Position* pos, float dist) const { - return IsInDist(pos, dist + GetObjectSize()); + return IsInDist(pos, dist + GetCombatReach()); } bool WorldObject::IsWithinDist2d(float x, float y, float dist) const { - return IsInDist2d(x, y, dist + GetObjectSize()); + return IsInDist2d(x, y, dist + GetCombatReach()); } bool WorldObject::IsWithinDist2d(const Position* pos, float dist) const { - return IsInDist2d(pos, dist + GetObjectSize()); + return IsInDist2d(pos, dist + GetCombatReach()); } bool WorldObject::IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D /*= true*/) const @@ -1226,9 +1218,9 @@ bool WorldObject::IsWithinDist(WorldObject const* obj, float dist2compare, bool return obj && _IsWithinDist(obj, dist2compare, is3D); } -bool WorldObject::IsWithinDistInMap(WorldObject const* obj, float dist2compare, bool is3D /*= true*/) const +bool WorldObject::IsWithinDistInMap(WorldObject const* obj, float dist2compare, bool is3D /*= true*/, bool incOwnRadius /*= true*/, bool incTargetRadius /*= true*/) const { - return obj && IsInMap(obj) && InSamePhase(obj) && _IsWithinDist(obj, dist2compare, is3D); + return obj && IsInMap(obj) && InSamePhase(obj) && _IsWithinDist(obj, dist2compare, is3D, incOwnRadius, incTargetRadius); } bool WorldObject::IsWithinLOS(float ox, float oy, float oz, VMAP::ModelIgnoreFlags ignoreFlags) const @@ -1255,7 +1247,7 @@ Position WorldObject::GetHitSpherePointFor(Position const& dest) const { G3D::Vector3 vThis(GetPositionX(), GetPositionY(), GetPositionZ()); G3D::Vector3 vObj(dest.GetPositionX(), dest.GetPositionY(), dest.GetPositionZ()); - G3D::Vector3 contactPoint = vThis + (vObj - vThis).directionOrZero() * std::min(dest.GetExactDist(GetPosition()), GetObjectSize()); + G3D::Vector3 contactPoint = vThis + (vObj - vThis).directionOrZero() * std::min(dest.GetExactDist(GetPosition()), GetCombatReach()); return Position(contactPoint.x, contactPoint.y, contactPoint.z, GetAngle(contactPoint.x, contactPoint.y)); } @@ -1302,7 +1294,7 @@ bool WorldObject::IsInRange(WorldObject const* obj, float minRange, float maxRan distsq += dz*dz; } - float sizefactor = GetObjectSize() + obj->GetObjectSize(); + float sizefactor = GetCombatReach() + obj->GetCombatReach(); // check only for real range if (minRange > 0.0f) @@ -1322,7 +1314,7 @@ bool WorldObject::IsInRange2d(float x, float y, float minRange, float maxRange) float dy = GetPositionY() - y; float distsq = dx*dx + dy*dy; - float sizefactor = GetObjectSize(); + float sizefactor = GetCombatReach(); // check only for real range if (minRange > 0.0f) @@ -1343,7 +1335,7 @@ bool WorldObject::IsInRange3d(float x, float y, float z, float minRange, float m float dz = GetPositionZ() - z; float distsq = dx*dx + dy*dy + dz*dz; - float sizefactor = GetObjectSize(); + float sizefactor = GetCombatReach(); // check only for real range if (minRange > 0.0f) @@ -1366,7 +1358,7 @@ bool WorldObject::IsInBetween(Position const& pos1, Position const& pos2, float return false; if (!size) - size = GetObjectSize() / 2; + size = GetCombatReach() / 2; float angle = pos1.GetAngle(pos2); @@ -1993,7 +1985,7 @@ TempSummon* WorldObject::SummonCreature(uint32 id, float x, float y, float z, fl { if (!x && !y && !z) { - GetClosePoint(x, y, z, GetObjectSize()); + GetClosePoint(x, y, z, GetCombatReach()); ang = GetOrientation(); } @@ -2036,7 +2028,7 @@ GameObject* WorldObject::SummonGameObject(uint32 entry, float x, float y, float { if (!x && !y && !z) { - GetClosePoint(x, y, z, GetObjectSize()); + GetClosePoint(x, y, z, GetCombatReach()); ang = GetOrientation(); } @@ -2162,8 +2154,8 @@ void WorldObject::GetPlayerListInGrid(Container& playerContainer, float maxSearc void WorldObject::GetNearPoint2D(float &x, float &y, float distance2d, float absAngle) const { - x = GetPositionX() + (GetObjectSize() + distance2d) * std::cos(absAngle); - y = GetPositionY() + (GetObjectSize() + distance2d) * std::sin(absAngle); + x = GetPositionX() + (GetCombatReach() + distance2d) * std::cos(absAngle); + y = GetPositionY() + (GetCombatReach() + distance2d) * std::sin(absAngle); Trinity::NormalizeMapCoord(x); Trinity::NormalizeMapCoord(y); @@ -2235,12 +2227,7 @@ Position WorldObject::GetRandomNearPosition(float radius) void WorldObject::GetContactPoint(const WorldObject* obj, float &x, float &y, float &z, float distance2d /*= CONTACT_DISTANCE*/) const { // angle to face `obj` to `this` using distance includes size of `obj` - GetNearPoint(obj, x, y, z, obj->GetObjectSize(), distance2d, GetAngle(obj)); -} - -float WorldObject::GetObjectSize() const -{ - return (m_valuesCount > UNIT_FIELD_COMBATREACH) ? m_floatValues[UNIT_FIELD_COMBATREACH] : DEFAULT_WORLD_OBJECT_SIZE; + GetNearPoint(obj, x, y, z, obj->GetCombatReach(), distance2d, GetAngle(obj)); } void WorldObject::MovePosition(Position &pos, float dist, float angle) diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index 55d3efed548..ffa7183a8b1 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -42,11 +42,11 @@ #define DEFAULT_VISIBILITY_INSTANCE 170.0f // default visible distance in instances, 170 yards #define DEFAULT_VISIBILITY_BGARENAS 533.0f // default visible distance in BG/Arenas, roughly 533 yards -#define DEFAULT_WORLD_OBJECT_SIZE 0.388999998569489f // player size, also currently used (correctly?) for any non Unit world objects -#define DEFAULT_COMBAT_REACH 1.5f -#define MIN_MELEE_REACH 2.0f -#define NOMINAL_MELEE_RANGE 5.0f -#define MELEE_RANGE (NOMINAL_MELEE_RANGE - MIN_MELEE_REACH * 2) //center to center for players +#define DEFAULT_PLAYER_BOUNDING_RADIUS 0.388999998569489f // player size, also currently used (correctly?) for any non Unit world objects +#define DEFAULT_PLAYER_COMBAT_REACH 1.5f +#define MIN_MELEE_REACH 2.0f +#define NOMINAL_MELEE_RANGE 5.0f +#define MELEE_RANGE (NOMINAL_MELEE_RANGE - MIN_MELEE_REACH * 2) //center to center for players enum TempSummonType { @@ -448,7 +448,7 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation Position GetRandomNearPosition(float radius); void GetContactPoint(WorldObject const* obj, float &x, float &y, float &z, float distance2d = CONTACT_DISTANCE) const; - float GetObjectSize() const; + virtual float GetCombatReach() const { return 0.0f; } // overridden (only) in Unit void UpdateGroundPositionZ(float x, float y, float &z) const; void UpdateAllowedPositionZ(float x, float y, float &z) const; @@ -488,7 +488,7 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation bool IsWithinDist2d(Position const* pos, float dist) const; // use only if you will sure about placing both object at same map bool IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D = true) const; - bool IsWithinDistInMap(WorldObject const* obj, float dist2compare, bool is3D = true) const; + bool IsWithinDistInMap(WorldObject const* obj, float dist2compare, bool is3D = true, bool incOwnRadius = true, bool incTargetRadius = true) const; bool IsWithinLOS(float x, float y, float z, VMAP::ModelIgnoreFlags ignoreFlags = VMAP::ModelIgnoreFlags::Nothing) const; bool IsWithinLOSInMap(WorldObject const* obj, VMAP::ModelIgnoreFlags ignoreFlags = VMAP::ModelIgnoreFlags::Nothing) const; Position GetHitSpherePointFor(Position const& dest) const; @@ -647,7 +647,7 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation uint16 m_notifyflags; uint16 m_executed_notifies; - virtual bool _IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D) const; + virtual bool _IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D, bool incOwnRadius = true, bool incTargetRadius = true) const; bool CanNeverSee(WorldObject const* obj) const; virtual bool CanAlwaysSee(WorldObject const* /*obj*/) const { return false; } diff --git a/src/server/game/Entities/Object/Position.cpp b/src/server/game/Entities/Object/Position.cpp index 0fdbaf8e008..a8cb363e272 100644 --- a/src/server/game/Entities/Object/Position.cpp +++ b/src/server/game/Entities/Object/Position.cpp @@ -137,6 +137,12 @@ bool Position::IsWithinBox(const Position& center, float xradius, float yradius, return true; } +bool Position::IsWithinDoubleVerticalCylinder(Position const* center, float radius, float height) const +{ + float verticalDelta = GetPositionZ() - center->GetPositionZ(); + return IsInDist2d(center, radius) && std::abs(verticalDelta) <= height; +} + bool Position::HasInArc(float arc, const Position* obj, float border) const { // always have self in arc diff --git a/src/server/game/Entities/Object/Position.h b/src/server/game/Entities/Object/Position.h index db694a51bfd..4dba3d1f330 100644 --- a/src/server/game/Entities/Object/Position.h +++ b/src/server/game/Entities/Object/Position.h @@ -229,6 +229,11 @@ public: } bool IsWithinBox(const Position& center, float xradius, float yradius, float zradius) const; + + /* + search using this relation: dist2d < radius && abs(dz) < height + */ + bool IsWithinDoubleVerticalCylinder(Position const* center, float radius, float height) const; bool HasInArc(float arcangle, Position const* pos, float border = 2.0f) const; bool HasInLine(Position const* pos, float objSize, float width) const; std::string ToString() const; diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index 5e2619890ec..72fb329b672 100644 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -186,7 +186,7 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c if (IsCritter()) { float px, py, pz; - owner->GetClosePoint(px, py, pz, GetObjectSize(), PET_FOLLOW_DIST, GetFollowAngle()); + owner->GetClosePoint(px, py, pz, GetCombatReach(), PET_FOLLOW_DIST, GetFollowAngle()); Relocate(px, py, pz, owner->GetOrientation()); if (!IsPositionValid()) @@ -245,7 +245,7 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c // Set pet's position after setting level, its size depends on it float px, py, pz; - owner->GetClosePoint(px, py, pz, GetObjectSize(), PET_FOLLOW_DIST, GetFollowAngle()); + owner->GetClosePoint(px, py, pz, GetCombatReach(), PET_FOLLOW_DIST, GetFollowAngle()); Relocate(px, py, pz, owner->GetOrientation()); if (!IsPositionValid()) { diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 3d2ccc388a4..291325dc759 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1047,8 +1047,8 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> void SetObjectScale(float scale) override { Unit::SetObjectScale(scale); - SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, scale * DEFAULT_WORLD_OBJECT_SIZE); - SetFloatValue(UNIT_FIELD_COMBATREACH, scale * DEFAULT_COMBAT_REACH); + SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, scale * DEFAULT_PLAYER_BOUNDING_RADIUS); + SetFloatValue(UNIT_FIELD_COMBATREACH, scale * DEFAULT_PLAYER_COMBAT_REACH); } bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options = 0); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index f813fe3121c..a5f8c98c290 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -581,7 +581,7 @@ void Unit::GetRandomContactPoint(const Unit* obj, float &x, float &y, float &z, { float combat_reach = GetCombatReach(); if (combat_reach < 0.1f) // sometimes bugged for players - combat_reach = DEFAULT_COMBAT_REACH; + combat_reach = DEFAULT_PLAYER_COMBAT_REACH; uint32 attacker_number = getAttackers().size(); if (attacker_number > 0) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index a0ebe4ddf10..bd2a564de61 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1321,7 +1321,7 @@ class TC_GAME_API Unit : public WorldObject bool haveOffhandWeapon() const; bool CanDualWield() const { return m_canDualWield; } virtual void SetCanDualWield(bool value) { m_canDualWield = value; } - float GetCombatReach() const { return m_floatValues[UNIT_FIELD_COMBATREACH]; } + float GetCombatReach() const override { return m_floatValues[UNIT_FIELD_COMBATREACH]; } bool IsWithinCombatRange(const Unit* obj, float dist2compare) const; bool IsWithinMeleeRange(Unit const* obj) const; float GetMeleeRange(Unit const* target) const; diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index b7a1788871f..43681910ac0 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -1396,7 +1396,7 @@ void ObjectMgr::LoadCreatureModelInfo() } if (modelInfo.combat_reach < 0.1f) - modelInfo.combat_reach = DEFAULT_COMBAT_REACH; + modelInfo.combat_reach = DEFAULT_PLAYER_COMBAT_REACH; if (CreatureModelDataEntry const* modelData = sCreatureModelDataStore.LookupEntry(creatureDisplay->ModelId)) modelInfo.is_trigger = strstr(modelData->ModelPath, "InvisibleStalker") != nullptr; diff --git a/src/server/game/Grids/Cells/CellImpl.h b/src/server/game/Grids/Cells/CellImpl.h index 36a15346b8b..aa567051e86 100644 --- a/src/server/game/Grids/Cells/CellImpl.h +++ b/src/server/game/Grids/Cells/CellImpl.h @@ -123,7 +123,7 @@ inline void Cell::Visit(CellCoord const& standing_cell, TypeContainerVisitor<T, { //we should increase search radius by object's radius, otherwise //we could have problems with huge creatures, which won't attack nearest players etc - Visit(standing_cell, visitor, map, radius + obj.GetObjectSize(), obj.GetPositionX(), obj.GetPositionY()); + Visit(standing_cell, visitor, map, radius + obj.GetCombatReach(), obj.GetPositionX(), obj.GetPositionY()); } template<class T, class CONTAINER> diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h index 04857f5c52a..1378b4a5778 100644 --- a/src/server/game/Grids/Notifiers/GridNotifiers.h +++ b/src/server/game/Grids/Notifiers/GridNotifiers.h @@ -927,14 +927,27 @@ namespace Trinity class AnyFriendlyUnitInObjectRangeCheck { public: - AnyFriendlyUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range, bool playerOnly = false) : i_obj(obj), i_funit(funit), i_range(range), i_playerOnly(playerOnly) { } + AnyFriendlyUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range, bool playerOnly = false, bool incOwnRadius = true, bool incTargetRadius = true) + : i_obj(obj), i_funit(funit), i_range(range), i_playerOnly(playerOnly), i_incOwnRadius(incOwnRadius), i_incTargetRadius(incTargetRadius) { } bool operator()(Unit* u) const { - if (u->IsAlive() && i_obj->IsWithinDistInMap(u, i_range) && i_funit->IsFriendlyTo(u) && (!i_playerOnly || u->GetTypeId() == TYPEID_PLAYER)) - return true; - else + if (!u->IsAlive()) + return false; + + float searchRadius = i_range; + if (i_incOwnRadius) + searchRadius += i_obj->GetCombatReach(); + if (i_incTargetRadius) + searchRadius += u->GetCombatReach(); + + if (!u->IsInMap(i_obj) || !u->InSamePhase(i_obj) || !u->IsWithinDoubleVerticalCylinder(i_obj, searchRadius, searchRadius)) return false; + + if (!i_funit->IsFriendlyTo(u)) + return false; + + return !i_playerOnly || u->GetTypeId() == TYPEID_PLAYER; } private: @@ -942,12 +955,15 @@ namespace Trinity Unit const* i_funit; float i_range; bool i_playerOnly; + bool i_incOwnRadius; + bool i_incTargetRadius; }; class AnyGroupedUnitInObjectRangeCheck { public: - AnyGroupedUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range, bool raid, bool playerOnly = false) : _source(obj), _refUnit(funit), _range(range), _raid(raid), _playerOnly(playerOnly) { } + AnyGroupedUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range, bool raid, bool playerOnly = false, bool incOwnRadius = true, bool incTargetRadius = true) + : _source(obj), _refUnit(funit), _range(range), _raid(raid), _playerOnly(playerOnly), i_incOwnRadius(incOwnRadius), i_incTargetRadius(incTargetRadius) { } bool operator()(Unit* u) const { @@ -965,7 +981,19 @@ namespace Trinity else if (!_refUnit->IsInPartyWith(u)) return false; - return !_refUnit->IsHostileTo(u) && u->IsAlive() && _source->IsWithinDistInMap(u, _range); + if (_refUnit->IsHostileTo(u)) + return false; + + if (!u->IsAlive()) + return false; + + float searchRadius = _range; + if (i_incOwnRadius) + searchRadius += _source->GetCombatReach(); + if (i_incTargetRadius) + searchRadius += u->GetCombatReach(); + + return u->IsInMap(_source) && u->InSamePhase(_source) && u->IsWithinDoubleVerticalCylinder(_source, searchRadius, searchRadius); } private: @@ -974,6 +1002,8 @@ namespace Trinity float _range; bool _raid; bool _playerOnly; + bool i_incOwnRadius; + bool i_incTargetRadius; }; class AnyUnitInObjectRangeCheck @@ -1024,8 +1054,8 @@ namespace Trinity class AnyAoETargetUnitInObjectRangeCheck { public: - AnyAoETargetUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range, SpellInfo const* spellInfo = nullptr) - : i_obj(obj), i_funit(funit), _spellInfo(spellInfo), i_range(range) + AnyAoETargetUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range, SpellInfo const* spellInfo = nullptr, bool incOwnRadius = true, bool incTargetRadius = true) + : i_obj(obj), i_funit(funit), _spellInfo(spellInfo), i_range(range), i_incOwnRadius(incOwnRadius), i_incTargetRadius(incTargetRadius) { if (!_spellInfo) if (DynamicObject const* dynObj = i_obj->ToDynObject()) @@ -1041,7 +1071,16 @@ namespace Trinity if (_spellInfo && _spellInfo->HasAttribute(SPELL_ATTR3_ONLY_TARGET_PLAYERS) && u->GetTypeId() != TYPEID_PLAYER) return false; - return i_funit->_IsValidAttackTarget(u, _spellInfo, i_obj->GetTypeId() == TYPEID_DYNAMICOBJECT ? i_obj : nullptr) && i_obj->IsWithinDistInMap(u, i_range); + if (!i_funit->_IsValidAttackTarget(u, _spellInfo, i_obj->GetTypeId() == TYPEID_DYNAMICOBJECT ? i_obj : nullptr)) + return false; + + float searchRadius = i_range; + if (i_incOwnRadius) + searchRadius += i_obj->GetCombatReach(); + if (i_incTargetRadius) + searchRadius += u->GetCombatReach(); + + return u->IsInMap(i_obj) && u->InSamePhase(i_obj) && u->IsWithinDoubleVerticalCylinder(i_obj, searchRadius, searchRadius); } private: @@ -1049,6 +1088,8 @@ namespace Trinity Unit const* i_funit; SpellInfo const* _spellInfo; float i_range; + bool i_incOwnRadius; + bool i_incTargetRadius; }; // do attack at call of help to friendly crearture diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index 888bec05284..a308369ec65 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -430,7 +430,7 @@ void MotionMaster::MoveKnockbackFrom(float srcX, float srcY, float speedXY, floa float dist = 2 * moveTimeHalf * speedXY; float max_height = -Movement::computeFallElevation(moveTimeHalf, false, -speedZ); - _owner->GetNearPoint(_owner, x, y, z, _owner->GetObjectSize(), dist, _owner->GetAngle(srcX, srcY) + float(M_PI)); + _owner->GetNearPoint(_owner, x, y, z, _owner->GetCombatReach(), dist, _owner->GetAngle(srcX, srcY) + float(M_PI)); Movement::MoveSplineInit init(_owner); init.MoveTo(x, y, z); @@ -451,7 +451,7 @@ void MotionMaster::MoveJumpTo(float angle, float speedXY, float speedZ) float moveTimeHalf = speedZ / Movement::gravity; float dist = 2 * moveTimeHalf * speedXY; - _owner->GetClosePoint(x, y, z, _owner->GetObjectSize(), dist, angle); + _owner->GetClosePoint(x, y, z, _owner->GetCombatReach(), dist, angle); MoveJump(x, y, z, 0.0f, speedXY, speedZ); } diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp index 0280b939efb..48e55c9960f 100644 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp @@ -66,7 +66,7 @@ void TargetedMovementGeneratorMedium<T, D>::_setTargetLocation(T* owner, bool up float size; // Pets need special handling. - // We need to subtract GetObjectSize() because it gets added back further down the chain + // We need to subtract GetCombatReach() because it gets added back further down the chain // and that makes pets too far away. Subtracting it allows pets to properly // be (GetCombatReach() + i_offset) away. // Only applies when i_target is pet's owner otherwise pets and mobs end up @@ -74,12 +74,12 @@ void TargetedMovementGeneratorMedium<T, D>::_setTargetLocation(T* owner, bool up if (owner->IsPet() && i_target->GetTypeId() == TYPEID_PLAYER) { dist = 1.0f; //i_target->GetCombatReach(); - size = 1.0f; //i_target->GetCombatReach() - i_target->GetObjectSize(); + size = 1.0f; //i_target->GetCombatReach() - i_target->GetCombatReach(); } else { dist = i_offset + 1.0f; - size = owner->GetObjectSize(); + size = owner->GetCombatReach(); } if (i_target->IsWithinDistInMap(owner, dist)) diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index c9abf8896b7..9430086f288 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -2487,7 +2487,7 @@ void UnitAura::FillTargetMap(std::unordered_map<Unit*, uint8>& targets, Unit* ca case SPELL_EFFECT_APPLY_AREA_AURA_RAID: { units.push_back(GetUnitOwner()); - Trinity::AnyGroupedUnitInObjectRangeCheck u_check(GetUnitOwner(), GetUnitOwner(), radius, m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID, m_spellInfo->HasAttribute(SPELL_ATTR3_ONLY_TARGET_PLAYERS)); + Trinity::AnyGroupedUnitInObjectRangeCheck u_check(GetUnitOwner(), GetUnitOwner(), radius, m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID, m_spellInfo->HasAttribute(SPELL_ATTR3_ONLY_TARGET_PLAYERS), false, true); Trinity::UnitListSearcher<Trinity::AnyGroupedUnitInObjectRangeCheck> searcher(GetUnitOwner(), units, u_check); GetUnitOwner()->VisitNearbyObject(radius, searcher); break; @@ -2495,14 +2495,14 @@ void UnitAura::FillTargetMap(std::unordered_map<Unit*, uint8>& targets, Unit* ca case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND: { units.push_back(GetUnitOwner()); - Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(GetUnitOwner(), GetUnitOwner(), radius, m_spellInfo->HasAttribute(SPELL_ATTR3_ONLY_TARGET_PLAYERS)); + Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(GetUnitOwner(), GetUnitOwner(), radius, m_spellInfo->HasAttribute(SPELL_ATTR3_ONLY_TARGET_PLAYERS), false, true); Trinity::UnitListSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(GetUnitOwner(), units, u_check); GetUnitOwner()->VisitNearbyObject(radius, searcher); break; } case SPELL_EFFECT_APPLY_AREA_AURA_ENEMY: { - Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(GetUnitOwner(), GetUnitOwner(), radius, m_spellInfo); // No GetCharmer in searcher + Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(GetUnitOwner(), GetUnitOwner(), radius, m_spellInfo, false, true); // No GetCharmer in searcher Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck> searcher(GetUnitOwner(), units, u_check); GetUnitOwner()->VisitNearbyObject(radius, searcher); break; @@ -2564,13 +2564,13 @@ void DynObjAura::FillTargetMap(std::unordered_map<Unit*, uint8>& targets, Unit* if (GetSpellInfo()->Effects[effIndex].TargetB.GetTarget() == TARGET_DEST_DYNOBJ_ALLY || GetSpellInfo()->Effects[effIndex].TargetB.GetTarget() == TARGET_UNIT_DEST_AREA_ALLY) { - Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(GetDynobjOwner(), dynObjOwnerCaster, radius, m_spellInfo->HasAttribute(SPELL_ATTR3_ONLY_TARGET_PLAYERS)); + Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(GetDynobjOwner(), dynObjOwnerCaster, radius, m_spellInfo->HasAttribute(SPELL_ATTR3_ONLY_TARGET_PLAYERS), false, true); Trinity::UnitListSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(GetDynobjOwner(), units, u_check); GetDynobjOwner()->VisitNearbyObject(radius, searcher); } else { - Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(GetDynobjOwner(), dynObjOwnerCaster, radius); + Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(GetDynobjOwner(), dynObjOwnerCaster, radius, nullptr, false, true); Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck> searcher(GetDynobjOwner(), units, u_check); GetDynobjOwner()->VisitNearbyObject(radius, searcher); } diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 60a719a8fb2..302579da128 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -1220,6 +1220,10 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge radius *= 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(), m_spellInfo->Effects[effIndex].ImplicitTargetConditions); CallScriptObjectAreaTargetSelectHandlers(targets, effIndex, targetType); @@ -1278,7 +1282,7 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplici float dist = frand(minDist, maxDist); float x, y, z; float angle = float(rand_norm()) * static_cast<float>(M_PI * 35.0f / 180.0f) - static_cast<float>(M_PI * 17.5f / 180.0f); - m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE, dist, angle); + m_caster->GetClosePoint(x, y, z, DEFAULT_PLAYER_BOUNDING_RADIUS, dist, angle); float ground = m_caster->GetMap()->GetHeight(m_caster->GetPhaseMask(), x, y, z, true, 50.0f); float liquidLevel = VMAP_INVALID_HEIGHT_VALUE; @@ -1309,7 +1313,7 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplici { float dist = m_spellInfo->Effects[effIndex].CalcRadius(m_caster); float angle = targetType.CalcDirectionAngle(); - float objSize = m_caster->GetObjectSize(); + float objSize = m_caster->GetCombatReach(); switch (targetType.GetTarget()) { @@ -1364,7 +1368,7 @@ void Spell::SelectImplicitTargetDestTargets(SpellEffIndex effIndex, SpellImplici default: { float angle = targetType.CalcDirectionAngle(); - float objSize = target->GetObjectSize(); + float objSize = target->GetCombatReach(); float dist = m_spellInfo->Effects[effIndex].CalcRadius(m_caster); if (dist < objSize) dist = objSize; @@ -1576,7 +1580,7 @@ void Spell::SelectImplicitTrajTargets(SpellEffIndex effIndex, SpellImplicitTarge } } - const float size = std::max((*itr)->GetObjectSize(), 1.0f); + const float size = std::max((*itr)->GetCombatReach(), 1.0f); const float objDist2d = srcPos.GetExactDist2d(*itr); const float dz = (*itr)->GetPositionZ() - srcPos.m_positionZ; @@ -5234,12 +5238,12 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint if (!target->IsWithinLOSInMap(m_caster)) //Do full LoS/Path check. Don't exclude m2 return SPELL_FAILED_LINE_OF_SIGHT; - 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 = std::min(target->GetObjectSize(), 4.0f); + float targetObjectSize = std::min(target->GetCombatReach(), 4.0f); bool result = m_preGeneratedPath.CalculatePath(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ() + targetObjectSize, false, true); if (m_preGeneratedPath.GetPathType() & PATHFIND_SHORT) return SPELL_FAILED_OUT_OF_RANGE; @@ -7761,8 +7765,20 @@ WorldObjectSpellAreaTargetCheck::WorldObjectSpellAreaTargetCheck(float range, Po bool WorldObjectSpellAreaTargetCheck::operator()(WorldObject* target) { - if (!target->IsWithinDist3d(_position, _range) && !(target->ToGameObject() && target->ToGameObject()->IsInRange(_position->GetPositionX(), _position->GetPositionY(), _position->GetPositionZ(), _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) && std::abs(target->GetPositionZ() - _position->GetPositionZ()) <= _range; + if (!isInsideCylinder) + return false; + } + return WorldObjectSpellTargetCheck::operator ()(target); } @@ -7779,7 +7795,7 @@ bool WorldObjectSpellConeTargetCheck::operator()(WorldObject* target) } else if (_spellInfo->HasAttribute(SPELL_ATTR0_CU_CONE_LINE)) { - if (!_caster->HasInLine(target, target->GetObjectSize(), _caster->GetObjectSize())) + if (!_caster->HasInLine(target, target->GetCombatReach(), _caster->GetCombatReach())) return false; } else @@ -7796,7 +7812,7 @@ WorldObjectSpellTrajTargetCheck::WorldObjectSpellTrajTargetCheck(float range, Po bool WorldObjectSpellTrajTargetCheck::operator()(WorldObject* target) { // return all targets on missile trajectory (0 - size of a missile) - if (!_caster->HasInLine(target, target->GetObjectSize(), TRAJECTORY_MISSILE_SIZE)) + if (!_caster->HasInLine(target, target->GetCombatReach(), TRAJECTORY_MISSILE_SIZE)) return false; if (target->GetExactDist2d(_position) > _range) diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index e8ff2ced069..d98bf2e4812 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -2565,7 +2565,7 @@ void Spell::EffectTeleUnitsFaceCaster(SpellEffIndex effIndex) float dis = m_spellInfo->Effects[effIndex].CalcRadius(m_caster); float fx, fy, fz; - m_caster->GetClosePoint(fx, fy, fz, unitTarget->GetObjectSize(), dis); + m_caster->GetClosePoint(fx, fy, fz, unitTarget->GetCombatReach(), dis); unitTarget->NearTeleportTo(fx, fy, fz, -m_caster->GetOrientation(), unitTarget == m_caster); } @@ -2990,7 +2990,7 @@ void Spell::EffectSummonPet(SpellEffIndex effIndex) //OldSummon->GetMap()->Remove(OldSummon->ToCreature(), false); float px, py, pz; - owner->GetClosePoint(px, py, pz, OldSummon->GetObjectSize()); + owner->GetClosePoint(px, py, pz, OldSummon->GetCombatReach()); OldSummon->NearTeleportTo(px, py, pz, OldSummon->GetOrientation()); //OldSummon->Relocate(px, py, pz, OldSummon->GetOrientation()); @@ -3016,7 +3016,7 @@ void Spell::EffectSummonPet(SpellEffIndex effIndex) } float x, y, z; - owner->GetClosePoint(x, y, z, owner->GetObjectSize()); + owner->GetClosePoint(x, y, z, owner->GetCombatReach()); Pet* pet = owner->SummonPet(petentry, x, y, z, owner->GetOrientation(), SUMMON_PET, 0); if (!pet) return; @@ -3474,7 +3474,7 @@ void Spell::EffectSummonObjectWild(SpellEffIndex effIndex) if (m_targets.HasDst()) destTarget->GetPosition(x, y, z); else - m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE); + m_caster->GetClosePoint(x, y, z, DEFAULT_PLAYER_BOUNDING_RADIUS); Map* map = target->GetMap(); @@ -4412,7 +4412,7 @@ void Spell::EffectSummonObject(SpellEffIndex effIndex) destTarget->GetPosition(x, y, z); // Summon in random point all other units if location present else - m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE); + m_caster->GetClosePoint(x, y, z, DEFAULT_PLAYER_BOUNDING_RADIUS); Map* map = m_caster->GetMap(); G3D::Quat rot = G3D::Matrix3::fromEulerAnglesZYX(m_caster->GetOrientation(), 0.f, 0.f); @@ -4669,7 +4669,7 @@ void Spell::EffectCharge(SpellEffIndex /*effIndex*/) if (m_preGeneratedPath.GetPathType() == PATHFIND_BLANK) { //unitTarget->GetContactPoint(m_caster, pos.m_positionX, pos.m_positionY, pos.m_positionZ); - Position pos = unitTarget->GetFirstCollisionPosition(unitTarget->GetObjectSize(), unitTarget->GetRelativeAngle(m_caster)); + Position pos = unitTarget->GetFirstCollisionPosition(unitTarget->GetCombatReach(), unitTarget->GetRelativeAngle(m_caster)); m_caster->GetMotionMaster()->MoveCharge(pos.m_positionX, pos.m_positionY, pos.m_positionZ, speed); } else @@ -4902,7 +4902,7 @@ void Spell::EffectResurrectPet(SpellEffIndex /*effIndex*/) // Reposition the pet's corpse before reviving so as not to grab aggro // We can use a different, more accurate version of GetClosePoint() since we have a pet float x, y, z; // Will be used later to reposition the pet if we have one - player->GetClosePoint(x, y, z, pet->GetObjectSize(), PET_FOLLOW_DIST, pet->GetFollowAngle()); + player->GetClosePoint(x, y, z, pet->GetCombatReach(), PET_FOLLOW_DIST, pet->GetFollowAngle()); pet->NearTeleportTo(x, y, z, player->GetOrientation()); pet->Relocate(x, y, z, player->GetOrientation()); // This is needed so SaveStayPosition() will get the proper coords. } @@ -5051,7 +5051,7 @@ void Spell::EffectTransmitted(SpellEffIndex effIndex) else if (m_spellInfo->Effects[effIndex].HasRadius() && m_spellInfo->Speed == 0) { float dis = m_spellInfo->Effects[effIndex].CalcRadius(m_originalCaster); - m_caster->GetClosePoint(fx, fy, fz, DEFAULT_WORLD_OBJECT_SIZE, dis); + m_caster->GetClosePoint(fx, fy, fz, DEFAULT_PLAYER_BOUNDING_RADIUS, dis); } else { @@ -5060,7 +5060,7 @@ void Spell::EffectTransmitted(SpellEffIndex effIndex) float max_dis = m_spellInfo->GetMaxRange(true); float dis = (float)rand_norm() * (max_dis - min_dis) + min_dis; - m_caster->GetClosePoint(fx, fy, fz, DEFAULT_WORLD_OBJECT_SIZE, dis); + m_caster->GetClosePoint(fx, fy, fz, DEFAULT_PLAYER_BOUNDING_RADIUS, dis); } Map* cMap = m_caster->GetMap(); diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 1a3b58afa83..efa3d6e8c70 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -66,6 +66,35 @@ bool SpellImplicitTargetInfo::IsArea() const return GetSelectionCategory() == TARGET_SELECT_CATEGORY_AREA || GetSelectionCategory() == TARGET_SELECT_CATEGORY_CONE; } +bool SpellImplicitTargetInfo::IsProximityBasedAoe() const +{ + switch (_target) + { + case TARGET_UNIT_SRC_AREA_ENTRY: + case TARGET_UNIT_SRC_AREA_ENEMY: + case TARGET_UNIT_CASTER_AREA_PARTY: + case TARGET_UNIT_SRC_AREA_ALLY: + case TARGET_UNIT_SRC_AREA_PARTY: + case TARGET_UNIT_LASTTARGET_AREA_PARTY: + case TARGET_GAMEOBJECT_SRC_AREA: + case TARGET_UNIT_CASTER_AREA_RAID: + case TARGET_CORPSE_SRC_AREA_ENEMY: + return true; + + case TARGET_UNIT_DEST_AREA_ENTRY: + case TARGET_UNIT_DEST_AREA_ENEMY: + case TARGET_UNIT_DEST_AREA_ALLY: + case TARGET_UNIT_DEST_AREA_PARTY: + case TARGET_GAMEOBJECT_DEST_AREA: + case TARGET_UNIT_TARGET_AREA_RAID_CLASS: + return false; + + default: + TC_LOG_WARN("spells", "SpellImplicitTargetInfo::IsProximityBasedAoe called a non-aoe spell"); + return false; + } +} + SpellTargetSelectionCategories SpellImplicitTargetInfo::GetSelectionCategory() const { return _data[_target].SelectionCategory; diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index 31bf975428c..4550719b691 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -210,6 +210,7 @@ public: SpellImplicitTargetInfo(uint32 target); bool IsArea() const; + bool IsProximityBasedAoe() const; SpellTargetSelectionCategories GetSelectionCategory() const; SpellTargetReferenceTypes GetReferenceType() const; SpellTargetObjectTypes GetObjectType() const; diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp index 32a299589a0..c907b8f41ad 100644 --- a/src/server/scripts/Commands/cs_debug.cpp +++ b/src/server/scripts/Commands/cs_debug.cpp @@ -927,7 +927,7 @@ public: uint32 entry = (uint32)atoi(e); float x, y, z, o = handler->GetSession()->GetPlayer()->GetOrientation(); - handler->GetSession()->GetPlayer()->GetClosePoint(x, y, z, handler->GetSession()->GetPlayer()->GetObjectSize()); + handler->GetSession()->GetPlayer()->GetClosePoint(x, y, z, handler->GetSession()->GetPlayer()->GetCombatReach()); if (!i) return handler->GetSession()->GetPlayer()->SummonCreature(entry, x, y, z, o) != nullptr; diff --git a/src/server/scripts/Commands/cs_group.cpp b/src/server/scripts/Commands/cs_group.cpp index ec09e960303..60d6f3116b5 100644 --- a/src/server/scripts/Commands/cs_group.cpp +++ b/src/server/scripts/Commands/cs_group.cpp @@ -135,7 +135,7 @@ public: // before GM float x, y, z; - gmPlayer->GetClosePoint(x, y, z, player->GetObjectSize()); + gmPlayer->GetClosePoint(x, y, z, player->GetCombatReach()); player->TeleportTo(gmPlayer->GetMapId(), x, y, z, player->GetOrientation()); } diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 2cf1f39b394..5b8764c0e45 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -561,7 +561,7 @@ public: // before GM float x, y, z; - handler->GetSession()->GetPlayer()->GetClosePoint(x, y, z, target->GetObjectSize()); + handler->GetSession()->GetPlayer()->GetClosePoint(x, y, z, target->GetCombatReach()); target->TeleportTo(handler->GetSession()->GetPlayer()->GetMapId(), x, y, z, target->GetOrientation()); target->SetPhaseMask(handler->GetSession()->GetPlayer()->GetPhaseMask(), true); } diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp index f80c6519b29..22bb02ae547 100644 --- a/src/server/scripts/Commands/cs_npc.cpp +++ b/src/server/scripts/Commands/cs_npc.cpp @@ -1372,7 +1372,7 @@ public: // place pet before player float x, y, z; - player->GetClosePoint (x, y, z, creatureTarget->GetObjectSize(), CONTACT_DISTANCE); + player->GetClosePoint (x, y, z, creatureTarget->GetCombatReach(), CONTACT_DISTANCE); pet->Relocate(x, y, z, float(M_PI) - player->GetOrientation()); // set pet to defensive mode by default (some classes can't control controlled pets in fact). diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp index 607edc61423..1d738d56984 100644 --- a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp @@ -123,7 +123,7 @@ class boss_selin_fireheart : public CreatureScript Crystals.remove(CrystalChosen); float x, y, z; - CrystalChosen->GetClosePoint(x, y, z, me->GetObjectSize(), CONTACT_DISTANCE); + CrystalChosen->GetClosePoint(x, y, z, me->GetCombatReach(), CONTACT_DISTANCE); events.SetPhase(PHASE_DRAIN); me->SetWalk(false); diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/zone_the_scarlet_enclave.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/zone_the_scarlet_enclave.cpp index f1904a50e04..fdc3cb622c4 100644 --- a/src/server/scripts/EasternKingdoms/ScarletEnclave/zone_the_scarlet_enclave.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/zone_the_scarlet_enclave.cpp @@ -99,7 +99,7 @@ public: FlyBackTimer = 500; break; case 1: - player->GetClosePoint(x, y, z, me->GetObjectSize()); + player->GetClosePoint(x, y, z, me->GetCombatReach()); z += 2.5f; x -= 2.0f; y -= 1.5f; diff --git a/src/server/scripts/Northrend/DraktharonKeep/boss_king_dred.cpp b/src/server/scripts/Northrend/DraktharonKeep/boss_king_dred.cpp index 58c7f780adb..84734e48381 100644 --- a/src/server/scripts/Northrend/DraktharonKeep/boss_king_dred.cpp +++ b/src/server/scripts/Northrend/DraktharonKeep/boss_king_dred.cpp @@ -144,7 +144,7 @@ class boss_king_dred : public CreatureScript float x, y, z; - me->GetClosePoint(x, y, z, me->GetObjectSize() / 3, 10.0f); + me->GetClosePoint(x, y, z, me->GetCombatReach() / 3, 10.0f); me->SummonCreature(RAND(NPC_DRAKKARI_GUTRIPPER, NPC_DRAKKARI_SCYTHECLAW), x, y, z, 0, TEMPSUMMON_DEAD_DESPAWN, 1000); events.ScheduleEvent(EVENT_RAPTOR_CALL, urand(20000, 25000)); break; diff --git a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp index a71214b7974..a7e679433c5 100644 --- a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp @@ -127,7 +127,7 @@ class boss_bronjahm : public CreatureScript { summons.Summon(summon); summon->SetReactState(REACT_PASSIVE); - summon->GetMotionMaster()->MoveFollow(me, me->GetObjectSize(), 0.0f); + summon->GetMotionMaster()->MoveFollow(me, me->GetCombatReach(), 0.0f); summon->CastSpell(summon, SPELL_PURPLE_BANISH_VISUAL, true); } } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp index c907aa14c3c..e8110a32438 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp @@ -788,7 +788,7 @@ class npc_high_overlord_saurfang_icc : public CreatureScript if (Creature* deathbringer = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_DEATHBRINGER_SAURFANG))) { float x, y, z; - deathbringer->GetClosePoint(x, y, z, deathbringer->GetObjectSize()); + deathbringer->GetClosePoint(x, y, z, deathbringer->GetCombatReach()); me->SetWalk(true); me->GetMotionMaster()->MovePoint(POINT_CORPSE, x, y, z); } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp index 6a794e36b56..361516582c6 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp @@ -383,7 +383,7 @@ class npc_coldflame : public CreatureScript { float ang = Position::NormalizeOrientation(pos.GetAngle(me)); me->SetOrientation(ang); - owner->GetNearPoint2D(pos.m_positionX, pos.m_positionY, 5.0f - owner->GetObjectSize(), ang); + owner->GetNearPoint2D(pos.m_positionX, pos.m_positionY, 5.0f - owner->GetCombatReach(), ang); } else { @@ -396,7 +396,7 @@ class npc_coldflame : public CreatureScript float ang = Position::NormalizeOrientation(pos.GetAngle(target)); me->SetOrientation(ang); - owner->GetNearPoint2D(pos.m_positionX, pos.m_positionY, 15.0f - owner->GetObjectSize(), ang); + owner->GetNearPoint2D(pos.m_positionX, pos.m_positionY, 15.0f - owner->GetCombatReach(), ang); } me->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), me->GetPositionZ(), me->GetOrientation()); @@ -514,7 +514,7 @@ class spell_marrowgar_coldflame : public SpellScriptLoader { targets.clear(); // select any unit but not the tank (by owners threatlist) - Unit* target = GetCaster()->GetAI()->SelectTarget(SELECT_TARGET_RANDOM, 1, -GetCaster()->GetObjectSize(), true, -SPELL_IMPALED); + Unit* target = GetCaster()->GetAI()->SelectTarget(SELECT_TARGET_RANDOM, 1, -GetCaster()->GetCombatReach(), true, -SPELL_IMPALED); if (!target) target = GetCaster()->GetAI()->SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true); // or the tank if its solo if (!target) diff --git a/src/server/scripts/Northrend/zone_zuldrak.cpp b/src/server/scripts/Northrend/zone_zuldrak.cpp index 26b521a95c7..0199340d0b9 100644 --- a/src/server/scripts/Northrend/zone_zuldrak.cpp +++ b/src/server/scripts/Northrend/zone_zuldrak.cpp @@ -55,7 +55,7 @@ public: me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); float x, y, z; - me->GetClosePoint(x, y, z, me->GetObjectSize() / 3, 0.1f); + me->GetClosePoint(x, y, z, me->GetCombatReach() / 3, 0.1f); if (Creature* summon = me->SummonCreature(NPC_RAGECLAW, x, y, z, 0, TEMPSUMMON_DEAD_DESPAWN, 1000)) { @@ -180,7 +180,7 @@ public: void Reset() override { float x, y, z; - me->GetClosePoint(x, y, z, me->GetObjectSize() / 3, 25.0f); + me->GetClosePoint(x, y, z, me->GetCombatReach() / 3, 25.0f); me->GetMotionMaster()->MovePoint(0, x, y, z); } diff --git a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp index 3e8b3e4ca95..1f3a7c569ea 100644 --- a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp +++ b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp @@ -521,7 +521,7 @@ public: Tapped = true; float x, y, z; - caster->GetClosePoint(x, y, z, me->GetObjectSize()); + caster->GetClosePoint(x, y, z, me->GetCombatReach()); me->SetWalk(false); me->GetMotionMaster()->MovePoint(1, x, y, z); diff --git a/src/server/scripts/World/go_scripts.cpp b/src/server/scripts/World/go_scripts.cpp index ccdde9eb799..12e89755963 100644 --- a/src/server/scripts/World/go_scripts.cpp +++ b/src/server/scripts/World/go_scripts.cpp @@ -356,7 +356,7 @@ public: uint32 BirdEntry = 0; float fX, fY, fZ; - go->GetClosePoint(fX, fY, fZ, go->GetObjectSize(), INTERACTION_DISTANCE); + go->GetClosePoint(fX, fY, fZ, go->GetCombatReach(), INTERACTION_DISTANCE); switch (go->GetEntry()) { diff --git a/src/server/scripts/World/item_scripts.cpp b/src/server/scripts/World/item_scripts.cpp index 5ce6a8301dd..64caa7ec4d1 100644 --- a/src/server/scripts/World/item_scripts.cpp +++ b/src/server/scripts/World/item_scripts.cpp @@ -240,7 +240,7 @@ public: return true; float x, y, z; - go->GetClosePoint(x, y, z, go->GetObjectSize() / 3, 7.0f); + go->GetClosePoint(x, y, z, go->GetCombatReach() / 3, 7.0f); go->SummonGameObject(GO_HIGH_QUALITY_FUR, *go, G3D::Quat(), 1); if (TempSummon* summon = player->SummonCreature(NPC_NESINGWARY_TRAPPER, x, y, z, go->GetOrientation(), TEMPSUMMON_DEAD_DESPAWN, 1000)) { |