mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-30 09:03:47 +00:00
fix(Core/CreatureAI): revert NPC repositioning and path system (temporarily) (#4274)
This commit is contained in:
@@ -586,35 +586,6 @@ void Creature::Update(uint32 diff)
|
||||
RemoveCharmAuras();
|
||||
}
|
||||
|
||||
// Circling the target
|
||||
if (diff >= m_moveCircleMovementTime)
|
||||
{
|
||||
AI()->MoveCircleChecks();
|
||||
m_moveCircleMovementTime = urand(MOVE_CIRCLE_CHECK_INTERVAL * 2, MOVE_CIRCLE_CHECK_INTERVAL * 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_moveCircleMovementTime -= diff;
|
||||
}
|
||||
|
||||
// If we are closer than 50% of the combat reach we are going to reposition the victim
|
||||
if (Unit *victim = GetVictim();
|
||||
victim && GetDistance(victim->GetPosition()) < CalculatePct(GetCombatReach() + victim->GetCombatReach(), 50)) {
|
||||
if (diff >= m_moveBackwardsMovementTime)
|
||||
{
|
||||
AI()->MoveBackwardsChecks();
|
||||
m_moveBackwardsMovementTime = urand(MOVE_BACKWARDS_CHECK_INTERVAL/2, MOVE_BACKWARDS_CHECK_INTERVAL * 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_moveBackwardsMovementTime -= diff;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_moveBackwardsMovementTime = MOVE_BACKWARDS_CHECK_INTERVAL;
|
||||
}
|
||||
|
||||
if (!IsInEvadeMode() && IsAIEnabled)
|
||||
{
|
||||
// do not allow the AI to be changed during update
|
||||
@@ -684,20 +655,6 @@ void Creature::Update(uint32 diff)
|
||||
}
|
||||
}
|
||||
|
||||
bool Creature::IsFreeToMove()
|
||||
{
|
||||
uint32 moveFlags = m_movementInfo.GetMovementFlags();
|
||||
// Do not reposition ourself when we are not allowed to move
|
||||
if ((IsMovementPreventedByCasting() || isMoving() || !CanFreeMove()) &&
|
||||
(GetMotionMaster()->GetCurrentMovementGeneratorType() != CHASE_MOTION_TYPE ||
|
||||
moveFlags & MOVEMENTFLAG_SPLINE_ENABLED))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Creature::Regenerate(Powers power)
|
||||
{
|
||||
uint32 curValue = GetPower(power);
|
||||
@@ -1562,10 +1519,8 @@ bool Creature::CanStartAttack(Unit const* who) const
|
||||
|
||||
// This set of checks is should be done only for creatures
|
||||
if ((HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC) && who->GetTypeId() != TYPEID_PLAYER) || // flag is valid only for non player characters
|
||||
(HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC) && who->GetTypeId() == TYPEID_PLAYER)) // immune to PC and target is a player, return false
|
||||
{
|
||||
(HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC) && who->GetTypeId() == TYPEID_PLAYER)) // immune to PC and target is a player, return false
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Unit* owner = who->GetOwner())
|
||||
if (owner->GetTypeId() == TYPEID_PLAYER && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC)) // immune to PC and target has player owner
|
||||
@@ -2875,16 +2830,6 @@ void Creature::FocusTarget(Spell const* focusSpell, WorldObject const* target)
|
||||
SetInFront(target);
|
||||
}
|
||||
|
||||
bool Creature::HasSpellFocus(Spell const* focusSpell) const
|
||||
{
|
||||
if (isDead()) // dead creatures cannot focus
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return focusSpell ? (focusSpell == _spellFocusInfo.Spell) : (_spellFocusInfo.Spell || _spellFocusInfo.Delay);
|
||||
}
|
||||
|
||||
void Creature::ReleaseFocus(Spell const* focusSpell)
|
||||
{
|
||||
// focused to something else
|
||||
@@ -2942,25 +2887,3 @@ float Creature::GetAttackDistance(Unit const* player) const
|
||||
|
||||
return (retDistance * aggroRate);
|
||||
}
|
||||
|
||||
bool Creature::IsMovementPreventedByCasting() const
|
||||
{
|
||||
Spell* spell = m_currentSpells[CURRENT_CHANNELED_SPELL];
|
||||
// first check if currently a movement allowed channel is active and we're not casting
|
||||
if (!!spell && spell->getState() != SPELL_STATE_FINISHED && spell->IsChannelActive() && spell->GetSpellInfo()->IsMoveAllowedChannel())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (HasSpellFocus())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -520,15 +520,6 @@ public:
|
||||
bool SetWaterWalking(bool enable, bool packetOnly = false) override;
|
||||
bool SetFeatherFall(bool enable, bool packetOnly = false) override;
|
||||
bool SetHover(bool enable, bool packetOnly = false) override;
|
||||
bool HasSpellFocus(Spell const* focusSpell = nullptr) const;
|
||||
|
||||
struct
|
||||
{
|
||||
::Spell const* Spell = nullptr;
|
||||
uint32 Delay = 0; // ms until the creature's target should snap back (0 = no snapback scheduled)
|
||||
uint64 Target; // the creature's "real" target while casting
|
||||
float Orientation = 0.0f; // the creature's "real" orientation while casting
|
||||
} _spellFocusInfo;
|
||||
|
||||
[[nodiscard]] uint32 GetShieldBlockValue() const override
|
||||
{
|
||||
@@ -733,18 +724,11 @@ public:
|
||||
void SetTarget(uint64 guid) override;
|
||||
void FocusTarget(Spell const* focusSpell, WorldObject const* target);
|
||||
void ReleaseFocus(Spell const* focusSpell);
|
||||
bool IsMovementPreventedByCasting() const;
|
||||
|
||||
// Part of Evade mechanics
|
||||
[[nodiscard]] time_t GetLastDamagedTime() const { return _lastDamagedTime; }
|
||||
void SetLastDamagedTime(time_t val) { _lastDamagedTime = val; }
|
||||
|
||||
bool IsFreeToMove();
|
||||
static constexpr uint32 MOVE_CIRCLE_CHECK_INTERVAL = 1500;
|
||||
static constexpr uint32 MOVE_BACKWARDS_CHECK_INTERVAL = 2000;
|
||||
uint32 m_moveCircleMovementTime = MOVE_CIRCLE_CHECK_INTERVAL;
|
||||
uint32 m_moveBackwardsMovementTime = MOVE_BACKWARDS_CHECK_INTERVAL;
|
||||
|
||||
protected:
|
||||
bool CreateFromProto(uint32 guidlow, uint32 Entry, uint32 vehId, const CreatureData* data = nullptr);
|
||||
bool InitEntry(uint32 entry, const CreatureData* data = nullptr);
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
*/
|
||||
|
||||
#include "Common.h"
|
||||
#include "Geometry.h"
|
||||
#include "SharedDefines.h"
|
||||
#include "WorldPacket.h"
|
||||
#include "Opcodes.h"
|
||||
@@ -1151,19 +1150,13 @@ bool WorldObject::IsWithinLOS(float ox, float oy, float oz, LineOfSightChecks ch
|
||||
{
|
||||
if (IsInWorld())
|
||||
{
|
||||
oz += GetCollisionHeight();
|
||||
float x, y, z;
|
||||
if (GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
GetPosition(x, y, z);
|
||||
z += GetCollisionHeight();
|
||||
}
|
||||
else
|
||||
{
|
||||
GetHitSpherePointFor({ ox, oy, oz }, x, y, z);
|
||||
}
|
||||
|
||||
return GetMap()->isInLineOfSight(x, y, z, ox, oy, oz, GetPhaseMask(), checks);
|
||||
return GetMap()->isInLineOfSight(x, y, z + 2.0f, ox, oy, oz + 2.0f, GetPhaseMask(), checks);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1309,7 +1302,12 @@ float Position::GetAngle(const Position* obj) const
|
||||
// Return angle in range 0..2*pi
|
||||
float Position::GetAngle(const float x, const float y) const
|
||||
{
|
||||
return getAngle(GetPositionX(), GetPositionY(), x, y);
|
||||
float dx = x - GetPositionX();
|
||||
float dy = y - GetPositionY();
|
||||
|
||||
float ang = atan2(dy, dx);
|
||||
ang = (ang >= 0) ? ang : 2 * M_PI + ang;
|
||||
return ang;
|
||||
}
|
||||
|
||||
void Position::GetSinCos(const float x, const float y, float& vsin, float& vcos) const
|
||||
@@ -2680,83 +2678,23 @@ void WorldObject::MovePosition(Position& pos, float dist, float angle)
|
||||
pos.m_orientation = m_orientation;
|
||||
}
|
||||
|
||||
Position WorldObject::GetFirstCollisionPosition(float startX, float startY, float startZ, float destX, float destY)
|
||||
void WorldObject::MovePositionToFirstCollision(Position& pos, float dist, float angle)
|
||||
{
|
||||
auto dx = destX - startX;
|
||||
auto dy = destY - startY;
|
||||
|
||||
auto ang = atan2(dy, dx);
|
||||
ang = (ang >= 0) ? ang : 2 * M_PI + ang;
|
||||
Position pos = Position(startX, startY, startZ, ang);
|
||||
|
||||
auto distance = pos.GetExactDist2d(destX,destY);
|
||||
|
||||
MovePositionToFirstCollision(pos, distance, ang);
|
||||
return pos;
|
||||
};
|
||||
|
||||
Position WorldObject::GetFirstCollisionPosition(float destX, float destY, float destZ)
|
||||
{
|
||||
Position pos = GetPosition();
|
||||
auto distance = GetExactDistSq(destX,destY,destZ);
|
||||
|
||||
auto dx = destX - pos.GetPositionX();
|
||||
auto dy = destY - pos.GetPositionY();
|
||||
|
||||
auto ang = atan2(dy, dx);
|
||||
ang = (ang >= 0) ? ang : 2 * M_PI + ang;
|
||||
|
||||
MovePositionToFirstCollision(pos, distance, ang);
|
||||
return pos;
|
||||
};
|
||||
|
||||
Position WorldObject::GetFirstCollisionPosition(float dist, float angle)
|
||||
{
|
||||
Position pos = GetPosition();
|
||||
GetFirstCollisionPosition(pos, dist, angle);
|
||||
return pos;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* \return true -> collision, false -> no collision
|
||||
*/
|
||||
bool WorldObject::MovePositionToFirstCollision(Position& pos, float dist, float angle)
|
||||
{
|
||||
angle += pos.GetOrientation();
|
||||
angle += m_orientation;
|
||||
float destx, desty, destz;
|
||||
destx = pos.m_positionX + dist * cos(angle);
|
||||
desty = pos.m_positionY + dist * sin(angle);
|
||||
destz = pos.m_positionZ;
|
||||
if (isType(TYPEMASK_UNIT | TYPEMASK_PLAYER) && !ToUnit()->IsInWater())
|
||||
destz += 2.0f;
|
||||
|
||||
// Prevent invalid coordinates here, position is unchanged
|
||||
if (!acore::IsValidMapCoord(destx, desty))
|
||||
{
|
||||
sLog->outCrash("WorldObject::MovePositionToFirstCollision invalid coordinates X: %f and Y: %f were passed!", destx, desty);
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Use a detour raycast to get our first collision point
|
||||
PathGenerator path(this);
|
||||
path.SetUseRaycast(true);
|
||||
bool result = path.CalculatePath(destx, desty, destz, false);
|
||||
|
||||
// Check for valid path types before we proceed
|
||||
if (!(path.GetPathType() & PATHFIND_NOT_USING_PATH))
|
||||
{
|
||||
if (path.GetPathType() & ~(PATHFIND_NORMAL | PATHFIND_SHORTCUT | PATHFIND_INCOMPLETE | PATHFIND_FARFROMPOLY_END)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// collision check
|
||||
bool col = (!result || (path.GetPathType() & PATHFIND_SHORTCUT) || (path.GetPathType() & PATHFIND_FARFROMPOLY));
|
||||
|
||||
G3D::Vector3 endPos = path.GetPath().back();
|
||||
destx = endPos.x;
|
||||
desty = endPos.y;
|
||||
destz = endPos.z;
|
||||
|
||||
// Xinef: ugly hack for dalaran arena
|
||||
float selfAddition = 1.5f;
|
||||
float allowedDiff = 6.0f;
|
||||
@@ -2770,8 +2708,10 @@ bool WorldObject::MovePositionToFirstCollision(Position& pos, float dist, float
|
||||
else
|
||||
UpdateAllowedPositionZ(destx, desty, destz);
|
||||
|
||||
bool col = VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(GetMapId(), pos.m_positionX, pos.m_positionY, pos.m_positionZ + selfAddition, destx, desty, destz + 0.5f, destx, desty, destz, -0.5f);
|
||||
|
||||
// collision occured
|
||||
if (VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(GetMapId(), pos.m_positionX, pos.m_positionY, pos.m_positionZ + selfAddition, destx, desty, destz + 0.5f, destx, desty, destz, -0.5f))
|
||||
if (col)
|
||||
{
|
||||
// move back a bit
|
||||
if (pos.GetExactDist2d(destx, desty) > CONTACT_DISTANCE)
|
||||
@@ -2781,11 +2721,13 @@ bool WorldObject::MovePositionToFirstCollision(Position& pos, float dist, float
|
||||
}
|
||||
|
||||
newDist = sqrt((pos.m_positionX - destx) * (pos.m_positionX - destx) + (pos.m_positionY - desty) * (pos.m_positionY - desty));
|
||||
col = true;
|
||||
}
|
||||
|
||||
// check dynamic collision, Collided with a gameobject
|
||||
if (GetMap()->getObjectHitPos(GetPhaseMask(), pos.m_positionX, pos.m_positionY, pos.m_positionZ + selfAddition, destx, desty, destz + 0.5f, destx, desty, destz, -0.5f))
|
||||
// check dynamic collision
|
||||
col = GetMap()->getObjectHitPos(GetPhaseMask(), pos.m_positionX, pos.m_positionY, pos.m_positionZ + selfAddition, destx, desty, destz + 0.5f, destx, desty, destz, -0.5f);
|
||||
|
||||
// Collided with a gameobject
|
||||
if (col)
|
||||
{
|
||||
// move back a bit
|
||||
if (pos.GetExactDist2d(destx, desty) > CONTACT_DISTANCE)
|
||||
@@ -2794,7 +2736,6 @@ bool WorldObject::MovePositionToFirstCollision(Position& pos, float dist, float
|
||||
desty -= CONTACT_DISTANCE * sin(angle);
|
||||
}
|
||||
newDist = sqrt((pos.m_positionX - destx) * (pos.m_positionX - destx) + (pos.m_positionY - desty) * (pos.m_positionY - desty));
|
||||
col = true;
|
||||
}
|
||||
|
||||
float step = newDist / 10.0f;
|
||||
@@ -2836,28 +2777,6 @@ bool WorldObject::MovePositionToFirstCollision(Position& pos, float dist, float
|
||||
|
||||
pos.Relocate(destx, desty, destz);
|
||||
pos.m_orientation = m_orientation;
|
||||
|
||||
// position has no ground under it (or is too far away)
|
||||
/* if (ground <= INVALID_HEIGHT)
|
||||
{
|
||||
if (Unit const* unit = ToUnit())
|
||||
{
|
||||
// unit can fly, ignore.
|
||||
if (unit->CanFly())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// fall back to gridHeight if any
|
||||
float gridHeight = GetMap()->GetHeight(pos.m_positionX, pos.m_positionY, pos.m_positionZ);
|
||||
if (gridHeight > INVALID_HEIGHT)
|
||||
{
|
||||
pos.m_positionZ = gridHeight + unit->GetHoverHeight();
|
||||
}
|
||||
}
|
||||
} */
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
void WorldObject::MovePositionToFirstCollisionForTotem(Position& pos, float dist, float angle, bool forGameObject)
|
||||
@@ -3166,8 +3085,3 @@ uint64 WorldObject::GetTransGUID() const
|
||||
return GetTransport()->GetGUID();
|
||||
return 0;
|
||||
}
|
||||
|
||||
float WorldObject::GetMapHeight(float x, float y, float z, bool vmap/* = true*/, float distanceToSearch/* = DEFAULT_HEIGHT_SEARCH*/) const
|
||||
{
|
||||
return GetMap()->GetHeight(GetPhaseMask(), x, y, z, vmap, distanceToSearch);
|
||||
}
|
||||
|
||||
@@ -792,10 +792,7 @@ public:
|
||||
GetPosition(&pos);
|
||||
MovePosition(pos, dist, angle);
|
||||
}
|
||||
bool MovePositionToFirstCollision(Position& pos, float dist, float angle);
|
||||
Position GetFirstCollisionPosition(float startX, float startY, float startZ, float destX, float destY);
|
||||
Position GetFirstCollisionPosition(float destX, float destY, float destZ);
|
||||
Position GetFirstCollisionPosition(float dist, float angle);
|
||||
void MovePositionToFirstCollision(Position& pos, float dist, float angle);
|
||||
void GetFirstCollisionPosition(Position& pos, float dist, float angle)
|
||||
{
|
||||
GetPosition(&pos);
|
||||
@@ -1059,9 +1056,6 @@ public:
|
||||
[[nodiscard]] virtual float GetStationaryY() const { return GetPositionY(); }
|
||||
[[nodiscard]] virtual float GetStationaryZ() const { return GetPositionZ(); }
|
||||
[[nodiscard]] virtual float GetStationaryO() const { return GetOrientation(); }
|
||||
float GetMapHeight(float x, float y, float z, bool vmap = true, float distanceToSearch = 50.0f) const; // DEFAULT_HEIGHT_SEARCH in map.h
|
||||
|
||||
virtual float GetCollisionHeight() const { return 0.0f; }
|
||||
|
||||
protected:
|
||||
std::string m_name;
|
||||
|
||||
@@ -2559,6 +2559,40 @@ public:
|
||||
|
||||
[[nodiscard]] bool CanFly() const override { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_CAN_FLY); }
|
||||
|
||||
//! Return collision height sent to client
|
||||
float GetCollisionHeight(bool mounted)
|
||||
{
|
||||
if (mounted)
|
||||
{
|
||||
CreatureDisplayInfoEntry const* mountDisplayInfo = sCreatureDisplayInfoStore.LookupEntry(GetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID));
|
||||
if (!mountDisplayInfo)
|
||||
return GetCollisionHeight(false);
|
||||
|
||||
CreatureModelDataEntry const* mountModelData = sCreatureModelDataStore.LookupEntry(mountDisplayInfo->ModelId);
|
||||
if (!mountModelData)
|
||||
return GetCollisionHeight(false);
|
||||
|
||||
CreatureDisplayInfoEntry const* displayInfo = sCreatureDisplayInfoStore.LookupEntry(GetNativeDisplayId());
|
||||
ASSERT(displayInfo);
|
||||
CreatureModelDataEntry const* modelData = sCreatureModelDataStore.LookupEntry(displayInfo->ModelId);
|
||||
ASSERT(modelData);
|
||||
|
||||
float scaleMod = GetFloatValue(OBJECT_FIELD_SCALE_X); // 99% sure about this
|
||||
|
||||
return scaleMod * mountModelData->MountHeight + modelData->CollisionHeight * 0.5f;
|
||||
}
|
||||
else
|
||||
{
|
||||
//! Dismounting case - use basic default model data
|
||||
CreatureDisplayInfoEntry const* displayInfo = sCreatureDisplayInfoStore.LookupEntry(GetNativeDisplayId());
|
||||
ASSERT(displayInfo);
|
||||
CreatureModelDataEntry const* modelData = sCreatureModelDataStore.LookupEntry(displayInfo->ModelId);
|
||||
ASSERT(modelData);
|
||||
|
||||
return modelData->CollisionHeight;
|
||||
}
|
||||
}
|
||||
|
||||
// OURS
|
||||
// saving
|
||||
void AdditionalSavingAddMask(uint8 mask) { m_additionalSaveTimer = 2000; m_additionalSaveMask |= mask; }
|
||||
|
||||
@@ -153,28 +153,9 @@ ProcEventInfo::ProcEventInfo(Unit* actor, Unit* actionTarget, Unit* procTarget,
|
||||
#pragma warning(disable:4355)
|
||||
#endif
|
||||
Unit::Unit(bool isWorldObject) : WorldObject(isWorldObject),
|
||||
m_movedByPlayer(nullptr),
|
||||
m_lastSanctuaryTime(0),
|
||||
IsAIEnabled(false),
|
||||
NeedChangeAI(false),
|
||||
m_ControlledByPlayer(false),
|
||||
m_CreatedByPlayer(false),
|
||||
movespline(new Movement::MoveSpline()),
|
||||
i_AI(nullptr),
|
||||
i_disabledAI(nullptr),
|
||||
m_realRace(0),
|
||||
m_race(0),
|
||||
m_AutoRepeatFirstCast(false),
|
||||
m_procDeep(0),
|
||||
m_removedAurasCount(0),
|
||||
i_motionMaster(new MotionMaster(this)),
|
||||
m_regenTimer(0),
|
||||
m_ThreatManager(this),
|
||||
m_vehicle(nullptr),
|
||||
m_vehicleKit(nullptr),
|
||||
m_unitTypeMask(UNIT_MASK_NONE),
|
||||
m_HostileRefManager(this),
|
||||
m_comboTarget(nullptr)
|
||||
m_movedByPlayer(nullptr), m_lastSanctuaryTime(0), IsAIEnabled(false), NeedChangeAI(false),
|
||||
m_ControlledByPlayer(false), m_CreatedByPlayer(false), movespline(new Movement::MoveSpline()), i_AI(nullptr), i_disabledAI(nullptr), m_realRace(0), m_race(0), m_AutoRepeatFirstCast(false), m_procDeep(0), m_removedAurasCount(0),
|
||||
i_motionMaster(new MotionMaster(this)), m_regenTimer(0), m_ThreatManager(this), m_vehicle(nullptr), m_vehicleKit(nullptr), m_unitTypeMask(UNIT_MASK_NONE), m_HostileRefManager(this)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(default:4355)
|
||||
@@ -596,21 +577,6 @@ bool Unit::IsWithinMeleeRange(const Unit* obj, float dist) const
|
||||
return distsq < maxdist * maxdist;
|
||||
}
|
||||
|
||||
bool Unit::IsWithinRange(Unit const* obj, float dist) const
|
||||
{
|
||||
if (!obj || !IsInMap(obj) || !InSamePhase(obj))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto dx = GetPositionX() - obj->GetPositionX();
|
||||
auto dy = GetPositionY() - obj->GetPositionY();
|
||||
auto dz = GetPositionZ() - obj->GetPositionZ();
|
||||
auto distsq = dx * dx + dy * dy + dz * dz;
|
||||
|
||||
return distsq <= dist * dist;
|
||||
}
|
||||
|
||||
bool Unit::GetRandomContactPoint(const Unit* obj, float& x, float& y, float& z, bool force) const
|
||||
{
|
||||
float combat_reach = GetCombatReach();
|
||||
@@ -2222,125 +2188,6 @@ void Unit::AttackerStateUpdate (Unit* victim, WeaponAttackType attType, bool ext
|
||||
}
|
||||
}
|
||||
|
||||
Position* Unit::GetMeleeAttackPoint(Unit* attacker)
|
||||
{
|
||||
if (!attacker) // only player & pets to save CPU
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AttackerSet attackers = getAttackers();
|
||||
|
||||
if (attackers.size() <= 1) // if the attackers are not more than one
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
float meleeReach = attacker->GetMeleeReach();
|
||||
|
||||
if (meleeReach <= 0)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
float currentAngle, minDistance = 0;
|
||||
Unit *refUnit = nullptr;
|
||||
uint32 validAttackers=0;
|
||||
|
||||
for (const auto& otherAttacker: attackers)
|
||||
{
|
||||
// if the otherAttacker is not valid, skip
|
||||
if (!otherAttacker ||
|
||||
otherAttacker->GetGUID() == attacker->GetGUID() ||
|
||||
!otherAttacker->IsWithinMeleeRange(this) ||
|
||||
otherAttacker->isMoving()
|
||||
)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
float tempDist = attacker->GetExactDist2d(otherAttacker) - (attacker->GetObjectSize()/2) - (otherAttacker->GetObjectSize()/2);
|
||||
|
||||
if (tempDist == 0 || minDistance == 0 || tempDist < minDistance)
|
||||
{
|
||||
minDistance = tempDist;
|
||||
currentAngle = GetAngle(otherAttacker);
|
||||
refUnit = otherAttacker;
|
||||
}
|
||||
|
||||
validAttackers++;
|
||||
}
|
||||
|
||||
auto attackerSize = attacker->GetObjectSize();
|
||||
|
||||
// in instance: the more attacker there are, the higher will be the tollerance
|
||||
// outside: creatures should not intersecate
|
||||
float distanceTollerance = attacker->GetMap()->IsDungeon() ? -attackerSize * tanh(validAttackers / 5.0f) : 0.0f;
|
||||
|
||||
if (!refUnit || minDistance > distanceTollerance)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
double ray = attackerSize > refUnit->GetObjectSize() ? attackerSize / 2.0f : refUnit->GetObjectSize() / 2.0f;
|
||||
double angle = 0;
|
||||
|
||||
// Equation of tangent point to get the ideal angle to
|
||||
// move away from collisions with another unit during combat
|
||||
// NOTE: it works only when there's enough space between the
|
||||
// attacker and the victim. We use a simpler one otherwise.
|
||||
if (GetExactDist2d(refUnit) > ray)
|
||||
{
|
||||
double refUnitX = refUnit->GetPositionX();
|
||||
double refUnitY = refUnit->GetPositionY();
|
||||
double victimX = GetPositionX();
|
||||
double victimY = GetPositionY();
|
||||
|
||||
// calculate tangent star
|
||||
double a = 4.0f * ( pow(ray,2.0f) - pow(refUnitX,2.0f) + (2.0f * refUnitX * victimX) - pow(victimX,2.0f) );
|
||||
double b = 8.0f * ( (refUnitX * refUnitY) + (victimX * victimY) - (victimX * refUnitY) - (refUnitX * victimY) );
|
||||
double c = 4.0f * (- pow(victimY,2.0f) - pow(refUnitY,2.0f) + (2.0f*victimY*refUnitY) + pow(ray,2.0f));
|
||||
|
||||
double sq = sqrt(pow(b,2.0f)-4.0f*a*c);
|
||||
|
||||
double m1 = (-b + sq) / (2.0f*a);
|
||||
double m2 = (-b - sq) / (2.0f*a);
|
||||
|
||||
// tangents
|
||||
double xT1 = ((-1.0f) * (m1*(victimY - m1*victimX - refUnitY) - refUnitX) ) / (1.0f + pow(m1,2.0f));
|
||||
double xT2 = ((-1.0f) * (m2*(victimY - m2*victimX - refUnitY) - refUnitX) ) / (1.0f + pow(m2,2.0f));
|
||||
|
||||
double yT1 = m1*(xT1 - victimX) + victimY;
|
||||
double yT2 = m2*(xT2 - victimX) + victimY;
|
||||
|
||||
double distance = sqrt(pow(yT2-yT1,2.0f) + pow(xT2-xT1,2.0f));
|
||||
double exactDist = GetExactDist2d(xT1, yT1);
|
||||
|
||||
double ortDist = sqrt(pow(exactDist,2.0f) - pow(distance/2.0f,2.0f));
|
||||
|
||||
angle = 2.0f * atan(distance / (2.0f * ortDist));
|
||||
}
|
||||
|
||||
int8 direction = (urand(0, 1) ? -1 : 1);
|
||||
|
||||
angle = frand(0.1f,0.3f) + (angle && !isnan(angle) ? angle : atan(attackerSize / (meleeReach))); // or fallback to the simpler method
|
||||
|
||||
float x, y, z;
|
||||
GetNearPoint(attacker, x, y, z, attackerSize, 0.0f, currentAngle + angle * direction);
|
||||
|
||||
if (!GetMap()->CanReachPositionAndGetCoords(this, x, y, z))
|
||||
{
|
||||
GetNearPoint(attacker, x, y, z, attackerSize, 0.0f, currentAngle + angle * (direction * -1)); // try the other side
|
||||
|
||||
if (!GetMap()->CanReachPositionAndGetCoords(this, x, y, z))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return new Position(x,y,z);
|
||||
}
|
||||
|
||||
void Unit::HandleProcExtraAttackFor(Unit* victim)
|
||||
{
|
||||
while (m_extraAttacks)
|
||||
@@ -12699,7 +12546,7 @@ void Unit::Mount(uint32 mount, uint32 VehicleId, uint32 creatureEntry)
|
||||
WorldPacket data(SMSG_MOVE_SET_COLLISION_HGT, GetPackGUID().size() + 4 + 4);
|
||||
data.append(GetPackGUID());
|
||||
data << uint32(sWorld->GetGameTime()); // Packet counter
|
||||
data << player->GetCollisionHeight();
|
||||
data << player->GetCollisionHeight(true);
|
||||
player->GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
||||
@@ -12719,7 +12566,7 @@ void Unit::Dismount()
|
||||
WorldPacket data(SMSG_MOVE_SET_COLLISION_HGT, GetPackGUID().size() + 4 + 4);
|
||||
data.append(GetPackGUID());
|
||||
data << uint32(sWorld->GetGameTime()); // Packet counter
|
||||
data << thisPlayer->GetCollisionHeight();
|
||||
data << thisPlayer->GetCollisionHeight(false);
|
||||
thisPlayer->GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
||||
@@ -19988,32 +19835,3 @@ bool Unit::IsInCombatWith(Unit const* who) const
|
||||
// Nothing found, false.
|
||||
return false;
|
||||
}
|
||||
|
||||
//! Return collision height sent to client
|
||||
float Unit::GetCollisionHeight() const
|
||||
{
|
||||
uint32 nativeDisplayId = GetNativeDisplayId();
|
||||
if (IsMounted())
|
||||
{
|
||||
if (CreatureDisplayInfoEntry const* mountDisplayInfo = sCreatureDisplayInfoStore.LookupEntry(GetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID));
|
||||
CreatureModelDataEntry const* mountModelData = sCreatureModelDataStore.LookupEntry(mountDisplayInfo->ModelId))
|
||||
{
|
||||
CreatureDisplayInfoEntry const* displayInfo = sCreatureDisplayInfoStore.LookupEntry(nativeDisplayId);
|
||||
ASSERT(displayInfo);
|
||||
CreatureModelDataEntry const* modelData = sCreatureModelDataStore.LookupEntry(displayInfo->ModelId);
|
||||
ASSERT(modelData);
|
||||
|
||||
float scaleMod = GetFloatValue(OBJECT_FIELD_SCALE_X); // 99% sure about this
|
||||
|
||||
return scaleMod * mountModelData->MountHeight + modelData->CollisionHeight * 0.5f;
|
||||
}
|
||||
}
|
||||
|
||||
//! Dismounting case - use basic default model data
|
||||
CreatureDisplayInfoEntry const* displayInfo = sCreatureDisplayInfoStore.LookupEntry(nativeDisplayId);
|
||||
ASSERT(displayInfo);
|
||||
CreatureModelDataEntry const* modelData = sCreatureModelDataStore.LookupEntry(displayInfo->ModelId);
|
||||
ASSERT(modelData);
|
||||
|
||||
return modelData->CollisionHeight;
|
||||
}
|
||||
|
||||
@@ -1254,26 +1254,6 @@ private:
|
||||
GlobalCooldownMgr _GlobalCooldownMgr;
|
||||
};
|
||||
|
||||
struct AttackPosition {
|
||||
AttackPosition(Position pos) : _pos(pos), _taken(false) {}
|
||||
bool operator==(const int val)
|
||||
{
|
||||
return !val;
|
||||
};
|
||||
int operator=(const int val)
|
||||
{
|
||||
if (!val)
|
||||
{
|
||||
// _pos = NULL;
|
||||
_taken = false;
|
||||
return 0; // NULL
|
||||
}
|
||||
return 0; // NULL
|
||||
};
|
||||
Position _pos;
|
||||
bool _taken;
|
||||
};
|
||||
|
||||
// for clearing special attacks
|
||||
#define REACTIVE_TIMER_START 5000
|
||||
|
||||
@@ -1424,7 +1404,6 @@ public:
|
||||
virtual void SetCanDualWield(bool value) { m_canDualWield = value; }
|
||||
[[nodiscard]] float GetCombatReach() const override { return m_floatValues[UNIT_FIELD_COMBATREACH]; }
|
||||
[[nodiscard]] float GetMeleeReach() const { float reach = m_floatValues[UNIT_FIELD_COMBATREACH]; return reach > MIN_MELEE_REACH ? reach : MIN_MELEE_REACH; }
|
||||
[[nodiscard]] bool IsWithinRange(Unit const* obj, float dist) const;
|
||||
bool IsWithinCombatRange(const Unit* obj, float dist2compare) const;
|
||||
bool IsWithinMeleeRange(const Unit* obj, float dist = MELEE_RANGE) const;
|
||||
bool GetRandomContactPoint(const Unit* target, float& x, float& y, float& z, bool force = false) const;
|
||||
@@ -1454,7 +1433,6 @@ public:
|
||||
bool AttackStop();
|
||||
void RemoveAllAttackers();
|
||||
[[nodiscard]] AttackerSet const& getAttackers() const { return m_attackers; }
|
||||
[[nodiscard]] Position* GetMeleeAttackPoint(Unit* attacker);
|
||||
[[nodiscard]] bool isAttackingPlayer() const;
|
||||
[[nodiscard]] Unit* GetVictim() const { return m_attacking; }
|
||||
|
||||
@@ -2195,7 +2173,7 @@ public:
|
||||
|
||||
uint32 GetDisplayId() { return GetUInt32Value(UNIT_FIELD_DISPLAYID); }
|
||||
virtual void SetDisplayId(uint32 modelId);
|
||||
[[nodiscard]] uint32 GetNativeDisplayId() const { return GetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID); }
|
||||
uint32 GetNativeDisplayId() { return GetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID); }
|
||||
void RestoreDisplayId();
|
||||
void SetNativeDisplayId(uint32 modelId) { SetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID, modelId); }
|
||||
void setTransForm(uint32 spellid) { m_transform = spellid;}
|
||||
@@ -2472,8 +2450,6 @@ public:
|
||||
// Movement info
|
||||
Movement::MoveSpline* movespline;
|
||||
|
||||
[[nodiscard]] float GetCollisionHeight() const override;
|
||||
|
||||
protected:
|
||||
explicit Unit (bool isWorldObject);
|
||||
|
||||
@@ -2589,7 +2565,6 @@ private:
|
||||
HostileRefManager m_HostileRefManager;
|
||||
|
||||
FollowerRefManager m_FollowingRefManager;
|
||||
Unit* m_comboTarget;
|
||||
|
||||
ComboPointHolderSet m_ComboPointHolders;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user