mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-21 17:54:48 +01:00
Core/Movement: MovementGenerator fixes.
- vmap height search in FleeingMovementGenerator and ConfusedMovementGenerator (until we can search for a nearby position properly) Should solve #7704, needs testing - Removed some unused code in CalculatePath and TargetedMovementGenerator. Ty faramir118 - Allow players to charge through slime and lava liquids. Closes #7967
This commit is contained in:
@@ -70,18 +70,26 @@ bool ConfusedMovementGenerator<T>::Update(T* unit, const uint32& diff)
|
||||
// start moving
|
||||
unit->AddUnitState(UNIT_STATE_CONFUSED_MOVE);
|
||||
|
||||
float x = i_x + 10.0f*((float)rand_norm() - 0.5f);
|
||||
float y = i_y + 10.0f*((float)rand_norm() - 0.5f);
|
||||
float z = i_z;
|
||||
float x = i_x + (4.0f * (float)rand_norm() - 2.0f);
|
||||
float y = i_y + (4.0f * (float)rand_norm() - 2.0f);
|
||||
|
||||
unit->UpdateAllowedPositionZ(x, y, z);
|
||||
Trinity::NormalizeMapCoord(x);
|
||||
Trinity::NormalizeMapCoord(y);
|
||||
|
||||
float z = unit->GetBaseMap()->GetHeight(unit->GetPhaseMask(), x, y, 10.0f, true);
|
||||
|
||||
if (z <= INVALID_HEIGHT || fabs(i_z - z) > 10.0f || !unit->IsWithinLOS(x, y, z))
|
||||
{
|
||||
i_nextMoveTime.Reset(100);
|
||||
return true;
|
||||
}
|
||||
|
||||
PathGenerator path(unit);
|
||||
path.SetPathLengthLimit(30.0f);
|
||||
path.SetPathLengthLimit(20.0f);
|
||||
bool result = path.CalculatePath(x, y, z);
|
||||
if (!result || path.GetPathType() & PATHFIND_NOPATH)
|
||||
if (!result || (path.GetPathType() & PATHFIND_NOPATH))
|
||||
{
|
||||
i_nextMoveTime.Reset(urand(800, 1000));
|
||||
i_nextMoveTime.Reset(100); // short reset
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,16 +39,19 @@ void FleeingMovementGenerator<T>::_setTargetLocation(T* owner)
|
||||
|
||||
float x, y, z;
|
||||
if (!_getPoint(owner, x, y, z))
|
||||
{
|
||||
i_nextCheckTime.Reset(100);
|
||||
return;
|
||||
}
|
||||
|
||||
owner->AddUnitState(UNIT_STATE_FLEEING_MOVE);
|
||||
|
||||
PathGenerator path(owner);
|
||||
path.SetPathLengthLimit(30.0f);
|
||||
path.SetPathLengthLimit(20.0f);
|
||||
bool result = path.CalculatePath(x, y, z);
|
||||
if (!result || path.GetPathType() & PATHFIND_NOPATH)
|
||||
if (!result || (path.GetPathType() & PATHFIND_NOPATH))
|
||||
{
|
||||
i_nextCheckTime.Reset(urand(1000, 1500));
|
||||
i_nextCheckTime.Reset(100);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -86,7 +89,7 @@ bool FleeingMovementGenerator<T>::_getPoint(T* owner, float &x, float &y, float
|
||||
dist = frand(0.4f, 1.3f)*(MIN_QUIET_DISTANCE - dist_from_caster);
|
||||
angle = angle_to_caster + frand(-static_cast<float>(M_PI)/8, static_cast<float>(M_PI)/8);
|
||||
}
|
||||
else if(dist_from_caster > MAX_QUIET_DISTANCE)
|
||||
else if (dist_from_caster > MAX_QUIET_DISTANCE)
|
||||
{
|
||||
dist = frand(0.4f, 1.0f)*(MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE);
|
||||
angle = -angle_to_caster + frand(-static_cast<float>(M_PI)/4, static_cast<float>(M_PI)/4);
|
||||
@@ -102,9 +105,17 @@ bool FleeingMovementGenerator<T>::_getPoint(T* owner, float &x, float &y, float
|
||||
|
||||
x = curr_x + dist * std::cos(angle);
|
||||
y = curr_y + dist * std::sin(angle);
|
||||
z = curr_z;
|
||||
|
||||
owner->UpdateAllowedPositionZ(x, y, z);
|
||||
Trinity::NormalizeMapCoord(x);
|
||||
Trinity::NormalizeMapCoord(y);
|
||||
|
||||
z = owner->GetBaseMap()->GetHeight(owner->GetPhaseMask(), x, y, 10.0f, true);
|
||||
|
||||
if (z <= INVALID_HEIGHT)
|
||||
return false;
|
||||
|
||||
if (fabs(curr_z - z) > 10.0f || !owner->IsWithinLOS(x, y, z))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -152,6 +163,7 @@ bool FleeingMovementGenerator<T>::Update(T* owner, const uint32& time_diff)
|
||||
{
|
||||
if (!owner || !owner->isAlive())
|
||||
return false;
|
||||
|
||||
if (owner->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED))
|
||||
{
|
||||
owner->ClearUnitState(UNIT_STATE_FLEEING_MOVE);
|
||||
@@ -159,7 +171,7 @@ bool FleeingMovementGenerator<T>::Update(T* owner, const uint32& time_diff)
|
||||
}
|
||||
|
||||
i_nextCheckTime.Update(time_diff);
|
||||
if (i_nextCheckTime.Passed() && owner->movespline->Finalized())
|
||||
if (i_nextCheckTime.Passed())
|
||||
_setTargetLocation(owner);
|
||||
|
||||
return true;
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#include "Player.h"
|
||||
|
||||
template<class T, typename D>
|
||||
void TargetedMovementGeneratorMedium<T,D>::_setTargetLocation(T* owner)
|
||||
void TargetedMovementGeneratorMedium<T,D>::_setTargetLocation(T* owner, bool updateDestination)
|
||||
{
|
||||
if (!i_target.isValid() || !i_target->IsInWorld())
|
||||
return;
|
||||
@@ -40,37 +40,42 @@ void TargetedMovementGeneratorMedium<T,D>::_setTargetLocation(T* owner)
|
||||
|
||||
float x, y, z;
|
||||
|
||||
if (!i_offset)
|
||||
if (updateDestination || !i_path)
|
||||
{
|
||||
float dist = 0.0f;
|
||||
|
||||
if (owner->getVictim() && owner->getVictim()->GetGUID() == i_target->GetGUID())
|
||||
dist = owner->GetFloatValue(UNIT_FIELD_COMBATREACH) + i_target->GetFloatValue(UNIT_FIELD_COMBATREACH) - i_target->GetObjectSize() - owner->GetObjectSize() - 1.0f;
|
||||
|
||||
if (dist < 0.5f)
|
||||
dist = 0.5f;
|
||||
|
||||
if (owner->IsWithinLOSInMap(owner->getVictim()))
|
||||
i_target->GetContactPoint(owner, x, y, z, dist);
|
||||
if (!i_offset)
|
||||
{
|
||||
// to nearest contact position
|
||||
i_target->GetContactPoint(owner, x, y, z);
|
||||
}
|
||||
else
|
||||
i_target->GetPosition(x, y, z);
|
||||
{
|
||||
// to at i_offset distance from target and i_angle from target facing
|
||||
i_target->GetClosePoint(x, y, z, owner->GetObjectSize(), i_offset, i_angle);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// to at i_offset distance from target and i_angle from target facing
|
||||
i_target->GetClosePoint(x, y, z, owner->GetObjectSize(), i_offset, i_angle);
|
||||
// the destination has not changed, we just need to refresh the path (usually speed change)
|
||||
G3D::Vector3 end = i_path->GetEndPosition();
|
||||
x = end.x;
|
||||
y = end.y;
|
||||
z = end.z;
|
||||
}
|
||||
|
||||
if (!i_path)
|
||||
i_path = new PathGenerator(owner);
|
||||
|
||||
// allow pets following their master to cheat while generating paths
|
||||
// allow pets to use shortcut if no path found when following their master
|
||||
bool forceDest = (owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()->isPet()
|
||||
&& owner->HasUnitState(UNIT_STATE_FOLLOW));
|
||||
|
||||
bool result = i_path->CalculatePath(x, y, z, forceDest);
|
||||
if (!result || i_path->GetPathType() & PATHFIND_NOPATH)
|
||||
if (!result || (i_path->GetPathType() & PATHFIND_NOPATH))
|
||||
{
|
||||
// Cant reach target
|
||||
i_recalculateTravel = true;
|
||||
return;
|
||||
}
|
||||
|
||||
D::_addUnitStateMove(owner);
|
||||
i_targetReached = false;
|
||||
@@ -79,37 +84,14 @@ void TargetedMovementGeneratorMedium<T,D>::_setTargetLocation(T* owner)
|
||||
|
||||
Movement::MoveSplineInit init(owner);
|
||||
init.MovebyPath(i_path->GetPath());
|
||||
init.SetFacing(i_target.getTarget());
|
||||
if (forceDest && updateDestination)
|
||||
init.SetFacing(i_target.getTarget()->GetOrientation());
|
||||
else
|
||||
init.SetFacing(i_target.getTarget());
|
||||
init.SetWalk(((D*)this)->EnableWalking());
|
||||
init.Launch();
|
||||
}
|
||||
|
||||
template<>
|
||||
void TargetedMovementGeneratorMedium<Player,ChaseMovementGenerator<Player> >::UpdateFinalDistance(float /*fDistance*/)
|
||||
{
|
||||
// nothing to do for Player
|
||||
}
|
||||
|
||||
template<>
|
||||
void TargetedMovementGeneratorMedium<Player,FollowMovementGenerator<Player> >::UpdateFinalDistance(float /*fDistance*/)
|
||||
{
|
||||
// nothing to do for Player
|
||||
}
|
||||
|
||||
template<>
|
||||
void TargetedMovementGeneratorMedium<Creature,ChaseMovementGenerator<Creature> >::UpdateFinalDistance(float fDistance)
|
||||
{
|
||||
i_offset = fDistance;
|
||||
i_recalculateTravel = true;
|
||||
}
|
||||
|
||||
template<>
|
||||
void TargetedMovementGeneratorMedium<Creature,FollowMovementGenerator<Creature> >::UpdateFinalDistance(float fDistance)
|
||||
{
|
||||
i_offset = fDistance;
|
||||
i_recalculateTravel = true;
|
||||
}
|
||||
|
||||
template<class T, typename D>
|
||||
bool TargetedMovementGeneratorMedium<T,D>::Update(T* owner, const uint32& time_diff)
|
||||
{
|
||||
@@ -140,6 +122,7 @@ bool TargetedMovementGeneratorMedium<T,D>::Update(T* owner, const uint32& time_d
|
||||
return true;
|
||||
}
|
||||
|
||||
bool targetMoved = false;
|
||||
i_recheckDistance.Update(time_diff);
|
||||
if (i_recheckDistance.Passed())
|
||||
{
|
||||
@@ -148,16 +131,15 @@ bool TargetedMovementGeneratorMedium<T,D>::Update(T* owner, const uint32& time_d
|
||||
float allowed_dist = owner->GetCombatReach() + sWorld->getRate(RATE_TARGET_POS_RECALCULATION_RANGE);
|
||||
G3D::Vector3 dest = owner->movespline->FinalDestination();
|
||||
|
||||
bool targetMoved = false;
|
||||
if (owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()->CanFly())
|
||||
targetMoved = !i_target->IsWithinDist3d(dest.x, dest.y, dest.z, allowed_dist);
|
||||
else
|
||||
targetMoved = !i_target->IsWithinDist2d(dest.x, dest.y, allowed_dist);
|
||||
|
||||
if (targetMoved || !owner->IsWithinLOSInMap(owner->getVictim()))
|
||||
_setTargetLocation(owner);
|
||||
}
|
||||
|
||||
if (i_recalculateTravel || targetMoved)
|
||||
_setTargetLocation(owner, targetMoved);
|
||||
|
||||
if (owner->movespline->Finalized())
|
||||
{
|
||||
static_cast<D*>(this)->MovementInform(owner);
|
||||
@@ -170,11 +152,7 @@ bool TargetedMovementGeneratorMedium<T,D>::Update(T* owner, const uint32& time_d
|
||||
static_cast<D*>(this)->_reachTarget(owner);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (i_recalculateTravel)
|
||||
_setTargetLocation(owner);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -190,7 +168,7 @@ template<>
|
||||
void ChaseMovementGenerator<Player>::Initialize(Player* owner)
|
||||
{
|
||||
owner->AddUnitState(UNIT_STATE_CHASE | UNIT_STATE_CHASE_MOVE);
|
||||
_setTargetLocation(owner);
|
||||
_setTargetLocation(owner, true);
|
||||
}
|
||||
|
||||
template<>
|
||||
@@ -198,7 +176,7 @@ void ChaseMovementGenerator<Creature>::Initialize(Creature* owner)
|
||||
{
|
||||
owner->SetWalk(false);
|
||||
owner->AddUnitState(UNIT_STATE_CHASE | UNIT_STATE_CHASE_MOVE);
|
||||
_setTargetLocation(owner);
|
||||
_setTargetLocation(owner, true);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
@@ -262,7 +240,7 @@ void FollowMovementGenerator<Player>::Initialize(Player* owner)
|
||||
{
|
||||
owner->AddUnitState(UNIT_STATE_FOLLOW | UNIT_STATE_FOLLOW_MOVE);
|
||||
_updateSpeed(owner);
|
||||
_setTargetLocation(owner);
|
||||
_setTargetLocation(owner, true);
|
||||
}
|
||||
|
||||
template<>
|
||||
@@ -270,7 +248,7 @@ void FollowMovementGenerator<Creature>::Initialize(Creature* owner)
|
||||
{
|
||||
owner->AddUnitState(UNIT_STATE_FOLLOW | UNIT_STATE_FOLLOW_MOVE);
|
||||
_updateSpeed(owner);
|
||||
_setTargetLocation(owner);
|
||||
_setTargetLocation(owner, true);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
@@ -300,10 +278,10 @@ void FollowMovementGenerator<Creature>::MovementInform(Creature* unit)
|
||||
}
|
||||
|
||||
//-----------------------------------------------//
|
||||
template void TargetedMovementGeneratorMedium<Player,ChaseMovementGenerator<Player> >::_setTargetLocation(Player*);
|
||||
template void TargetedMovementGeneratorMedium<Player,FollowMovementGenerator<Player> >::_setTargetLocation(Player*);
|
||||
template void TargetedMovementGeneratorMedium<Creature,ChaseMovementGenerator<Creature> >::_setTargetLocation(Creature*);
|
||||
template void TargetedMovementGeneratorMedium<Creature,FollowMovementGenerator<Creature> >::_setTargetLocation(Creature*);
|
||||
template void TargetedMovementGeneratorMedium<Player,ChaseMovementGenerator<Player> >::_setTargetLocation(Player*, bool);
|
||||
template void TargetedMovementGeneratorMedium<Player,FollowMovementGenerator<Player> >::_setTargetLocation(Player*, bool);
|
||||
template void TargetedMovementGeneratorMedium<Creature,ChaseMovementGenerator<Creature> >::_setTargetLocation(Creature*, bool);
|
||||
template void TargetedMovementGeneratorMedium<Creature,FollowMovementGenerator<Creature> >::_setTargetLocation(Creature*, bool);
|
||||
template bool TargetedMovementGeneratorMedium<Player,ChaseMovementGenerator<Player> >::Update(Player*, const uint32&);
|
||||
template bool TargetedMovementGeneratorMedium<Player,FollowMovementGenerator<Player> >::Update(Player*, const uint32&);
|
||||
template bool TargetedMovementGeneratorMedium<Creature,ChaseMovementGenerator<Creature> >::Update(Creature*, const uint32&);
|
||||
|
||||
@@ -51,10 +51,9 @@ class TargetedMovementGeneratorMedium : public MovementGeneratorMedium< T, D >,
|
||||
Unit* GetTarget() const { return i_target.getTarget(); }
|
||||
|
||||
void unitSpeedChanged() { i_recalculateTravel = true; }
|
||||
void UpdateFinalDistance(float fDistance);
|
||||
bool IsReachable() const { return (i_path) ? (i_path->GetPathType() & PATHFIND_NORMAL) : true; }
|
||||
protected:
|
||||
void _setTargetLocation(T*);
|
||||
void _setTargetLocation(T* owner, bool updateDestination);
|
||||
|
||||
TimeTrackerSmall i_recheckDistance;
|
||||
float i_offset;
|
||||
|
||||
@@ -58,7 +58,6 @@ bool PathGenerator::CalculatePath(float destX, float destY, float destZ, bool fo
|
||||
if (!Trinity::IsValidMapCoord(destX, destY, destZ) || !Trinity::IsValidMapCoord(x, y, z))
|
||||
return false;
|
||||
|
||||
Vector3 oldDest = GetEndPosition();
|
||||
Vector3 dest(destX, destY, destZ);
|
||||
SetEndPosition(dest);
|
||||
|
||||
@@ -81,24 +80,8 @@ bool PathGenerator::CalculatePath(float destX, float destY, float destZ, bool fo
|
||||
|
||||
UpdateFilter();
|
||||
|
||||
// check if destination moved - if not we can optimize something here
|
||||
// we are following old, precalculated path?
|
||||
float dist = _sourceUnit->GetObjectSize();
|
||||
if (oldDest != Vector3::zero() && InRange(oldDest, dest, dist, dist) && _pathPoints.size() > 2)
|
||||
{
|
||||
// our target is not moving - we just coming closer
|
||||
// we are moving on precalculated path - enjoy the ride
|
||||
sLog->outDebug(LOG_FILTER_MAPS, "++ PathGenerator::CalculatePath:: precalculated path\n");
|
||||
|
||||
_pathPoints.erase(_pathPoints.begin());
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// target moved, so we need to update the poly path
|
||||
BuildPolyPath(start, dest);
|
||||
return true;
|
||||
}
|
||||
BuildPolyPath(start, dest);
|
||||
return true;
|
||||
}
|
||||
|
||||
dtPolyRef PathGenerator::GetPathPolyByPosition(dtPolyRef const* polyPath, uint32 polyPathSize, float const* point, float* distance) const
|
||||
@@ -534,10 +517,10 @@ void PathGenerator::CreateFilter()
|
||||
if (creature->canSwim())
|
||||
includeFlags |= (NAV_WATER | NAV_MAGMA | NAV_SLIME); // swim
|
||||
}
|
||||
else if (_sourceUnit->GetTypeId() == TYPEID_PLAYER)
|
||||
else // assume Player
|
||||
{
|
||||
// perfect support not possible, just stay 'safe'
|
||||
includeFlags |= (NAV_GROUND | NAV_WATER);
|
||||
includeFlags |= (NAV_GROUND | NAV_WATER | NAV_MAGMA | NAV_SLIME);
|
||||
}
|
||||
|
||||
_filter.setIncludeFlags(includeFlags);
|
||||
|
||||
@@ -98,7 +98,7 @@ namespace Movement
|
||||
if (!args.HasVelocity)
|
||||
args.velocity = unit->GetSpeed(SelectSpeedType(moveFlags));
|
||||
|
||||
if (!args.Validate(&unit))
|
||||
if (!args.Validate(unit))
|
||||
return 0;
|
||||
|
||||
if (moveFlags & MOVEMENTFLAG_ROOT)
|
||||
|
||||
Reference in New Issue
Block a user