Skip to content

Commit

Permalink
Core/Movement: MovementGenerator fixes.
Browse files Browse the repository at this point in the history
- vmap height search in FleeingMovementGenerator and ConfusedMovementGenerator (until we can search for a nearby position properly) Should solve TrinityCore#7704, needs testing
- Removed some unused code in CalculatePath and TargetedMovementGenerator. Ty faramir118
- Allow players to charge through slime and lava liquids. Closes TrinityCore#7967
  • Loading branch information
kaelima committed Nov 7, 2012
1 parent 023c16a commit 7df5b85
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 99 deletions.
Expand Up @@ -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;
}

Expand Down
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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);
Expand All @@ -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;
}
Expand Down Expand Up @@ -152,14 +163,15 @@ 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);
return true;
}

i_nextCheckTime.Update(time_diff);
if (i_nextCheckTime.Passed() && owner->movespline->Finalized())
if (i_nextCheckTime.Passed())
_setTargetLocation(owner);

return true;
Expand Down
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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)
{
Expand Down Expand Up @@ -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())
{
Expand All @@ -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);
Expand All @@ -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;
}

Expand All @@ -190,15 +168,15 @@ template<>
void ChaseMovementGenerator<Player>::Initialize(Player* owner)
{
owner->AddUnitState(UNIT_STATE_CHASE | UNIT_STATE_CHASE_MOVE);
_setTargetLocation(owner);
_setTargetLocation(owner, true);
}

template<>
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>
Expand Down Expand Up @@ -262,15 +240,15 @@ void FollowMovementGenerator<Player>::Initialize(Player* owner)
{
owner->AddUnitState(UNIT_STATE_FOLLOW | UNIT_STATE_FOLLOW_MOVE);
_updateSpeed(owner);
_setTargetLocation(owner);
_setTargetLocation(owner, true);
}

template<>
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>
Expand Down Expand Up @@ -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&);
Expand Down
Expand Up @@ -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;
Expand Down
25 changes: 4 additions & 21 deletions src/server/game/Movement/PathGenerator.cpp
Expand Up @@ -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);

Expand All @@ -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
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/server/game/Movement/Spline/MoveSplineInit.cpp
Expand Up @@ -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)
Expand Down

0 comments on commit 7df5b85

Please sign in to comment.