remove useless pathfinding code.

This commit is contained in:
Venugh
2012-04-09 16:20:22 +02:00
parent d847ce7b0a
commit c8f708f9ad
3 changed files with 31 additions and 355 deletions

View File

@@ -26,8 +26,6 @@
#include "MoveSpline.h"
#include "Player.h"
#include <cmath>
template<class T, typename D>
void TargetedMovementGeneratorMedium<T,D>::_setTargetLocation(T &owner)
{
@@ -65,30 +63,27 @@ void TargetedMovementGeneratorMedium<T,D>::_setTargetLocation(T &owner)
i_target->GetClosePoint(x, y, z, owner.GetObjectSize(), i_offset, i_angle);
}
/*
We MUST not check the distance difference and avoid setting the new location for smaller distances.
By that we risk having far too many GetContactPoint() calls freezing the whole system.
In TargetedMovementGenerator<T>::Update() we check the distance to the target and at
some range we calculate a new position. The calculation takes some processor cycles due to vmaps.
If the distance to the target it too large to ignore,
but the distance to the new contact point is short enough to be ignored,
we will calculate a new contact point each update loop, but will never move to it.
The system will freeze.
ralf
//We don't update Mob Movement, if the difference between New destination and last destination is < BothObjectSize
float bothObjectSize = i_target->GetObjectBoundingRadius() + owner.GetObjectBoundingRadius() + CONTACT_DISTANCE;
if ( i_destinationHolder.HasDestination() && i_destinationHolder.GetDestinationDiff(x,y,z) < bothObjectSize )
return;
*/
if (!i_path)
i_path = new PathFinderMovementGenerator(&owner);
// allow pets following their master to cheat while generating paths
bool forceDest = (owner.GetTypeId() == TYPEID_UNIT && ((Creature*)&owner)->isPet()
&& owner.HasUnitState(UNIT_STAT_FOLLOW));
i_path->calculate(x, y, z, forceDest);
if (i_path->getPathType() & PATHFIND_NOPATH)
return;
D::_addUnitStateMove(owner);
i_targetReached = false;
i_recalculateTravel = false;
owner.AddUnitState(UNIT_STATE_CHASE);
Movement::MoveSplineInit init(owner);
init.MoveTo(x,y,z);
if (!i_target->IsInWater())
init.MovebyPath(i_path->getPath());
else
init.MoveTo(i_target->GetPositionX(), i_target->GetPositionY(), i_target->GetPositionZ(), false, false);
init.SetWalk(((D*)this)->EnableWalking());
init.Launch();
}
@@ -125,7 +120,7 @@ bool TargetedMovementGeneratorMedium<T,D>::Update(T &owner, const uint32 & time_
if (!i_target.isValid() || !i_target->IsInWorld())
return false;
if (!owner.isAlive())
if (!&owner || !owner.isAlive())
return true;
if (owner.HasUnitState(UNIT_STATE_NOT_MOVE))
@@ -152,11 +147,18 @@ bool TargetedMovementGeneratorMedium<T,D>::Update(T &owner, const uint32 & time_
i_recheckDistance.Update(time_diff);
if (i_recheckDistance.Passed())
{
i_recheckDistance.Reset(50);
i_recheckDistance.Reset(100);
//More distance let have better performance, less distance let have more sensitive reaction at target move.
float allowed_dist = i_target->GetObjectSize() + owner.GetObjectSize() + MELEE_RANGE - 0.5f;
float dist = (owner.movespline->FinalDestination() - G3D::Vector3(i_target->GetPositionX(),i_target->GetPositionY(),i_target->GetPositionZ())).squaredLength();
if (dist >= allowed_dist * allowed_dist)
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 && ((Creature*)&owner)->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)
_setTargetLocation(owner);
}

View File

@@ -23,6 +23,7 @@
#include "FollowerReference.h"
#include "Timer.h"
#include "Unit.h"
#include "PathFinderMovementGenerator.h"
class TargetedMovementGeneratorBase
{
@@ -38,12 +39,12 @@ class TargetedMovementGeneratorMedium : public MovementGeneratorMedium< T, D >,
{
protected:
TargetedMovementGeneratorMedium(Unit &target, float offset, float angle) :
TargetedMovementGeneratorBase(target), i_recheckDistance(0),
TargetedMovementGeneratorBase(target), i_recheckDistance(0),, i_path(NULL),
i_offset(offset), i_angle(angle),
i_recalculateTravel(false), i_targetReached(false)
{
}
~TargetedMovementGeneratorMedium() {}
~TargetedMovementGeneratorMedium() { delete i_path; }
public:
bool Update(T &, const uint32 &);
@@ -51,7 +52,7 @@ class TargetedMovementGeneratorMedium : public MovementGeneratorMedium< T, D >,
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 &);
@@ -60,6 +61,7 @@ class TargetedMovementGeneratorMedium : public MovementGeneratorMedium< T, D >,
float i_angle;
bool i_recalculateTravel : 1;
bool i_targetReached : 1;
PathFinderMovementGenerator* i_path;
};
template<class T>

View File

@@ -319,331 +319,3 @@ void FlightPathMovementGenerator::PreloadEndGrid()
else
sLog->outDetail("Unable to determine map to preload flightmaster grid");
}
//
// Unique1's ASTAR Pathfinding Code... For future use & reference...
//
#ifdef __PATHFINDING__
int GetFCost(int to, int num, int parentNum, float *gcost); // Below...
int ShortenASTARRoute(short int *pathlist, int number)
{ // Wrote this to make the routes a little smarter (shorter)... No point looping back to the same places... Unique1
short int temppathlist[MAX_PATHLIST_NODES];
int count = 0;
// int count2 = 0;
int temp, temp2;
int link;
int upto = 0;
for (temp = number; temp >= 0; temp--)
{
qboolean shortened = qfalse;
for (temp2 = 0; temp2 < temp; temp2++)
{
for (link = 0; link < nodes[pathlist[temp]].enodenum; link++)
{
if (nodes[pathlist[temp]].links[link].flags & PATH_BLOCKED)
continue;
//if ((bot->client->ps.eFlags & EF_TANK) && nodes[bot->current_node].links[link].flags & PATH_NOTANKS) //if this path is blocked, skip it
// continue;
//if (nodes[nodes[pathlist[temp]].links[link].targetNode].origin[2] > nodes[pathlist[temp]].origin[2] + 32)
// continue;
if (nodes[pathlist[temp]].links[link].targetNode == pathlist[temp2])
{ // Found a shorter route...
//if (OrgVisible(nodes[pathlist[temp2]].origin, nodes[pathlist[temp]].origin, -1))
{
temppathlist[count] = pathlist[temp2];
temp = temp2;
++count;
shortened = qtrue;
}
}
}
}
if (!shortened)
{
temppathlist[count] = pathlist[temp];
++count;
}
}
upto = count;
for (temp = 0; temp < count; temp++)
{
pathlist[temp] = temppathlist[upto];
--upto;
}
G_Printf("ShortenASTARRoute: Path size reduced from %i to %i nodes...n", number, count);
return count;
}
/*
===========================================================================
CreatePathAStar
This function uses the A* pathfinding algorithm to determine the
shortest path between any two nodes.
It's fairly complex, so I'm not really going to explain it much.
Look up A* and binary heaps for more info.
pathlist stores the ideal path between the nodes, in reverse order,
and the return value is the number of nodes in that path
===========================================================================
*/
int CreatePathAStar(gentity_t *bot, int from, int to, short int *pathlist)
{
//all the data we have to hold...since we can't do dynamic allocation, has to be MAX_NODES
//we can probably lower this later - eg, the open list should never have more than at most a few dozen items on it
short int openlist[MAX_NODES+1]; //add 1 because it's a binary heap, and they don't use 0 - 1 is the first used index
float gcost[MAX_NODES];
int fcost[MAX_NODES];
char list[MAX_NODES]; //0 is neither, 1 is open, 2 is closed - char because it's the smallest data type
short int parent[MAX_NODES];
short int numOpen = 0;
short int atNode, temp, newnode=-1;
qboolean found = qfalse;
int count = -1;
float gc;
int i, u, v, m;
vec3_t vec;
//clear out all the arrays
memset(openlist, 0, sizeof(short int)*(MAX_NODES+1));
memset(fcost, 0, sizeof(int)*MAX_NODES);
memset(list, 0, sizeof(char)*MAX_NODES);
memset(parent, 0, sizeof(short int)*MAX_NODES);
memset(gcost, -1, sizeof(float)*MAX_NODES);
//make sure we have valid data before calculating everything
if ((from == NODE_INVALID) || (to == NODE_INVALID) || (from >= MAX_NODES) || (to >= MAX_NODES) || (from == to))
return -1;
openlist[1] = from; //add the starting node to the open list
++numOpen;
gcost[from] = 0; //its f and g costs are obviously 0
fcost[from] = 0;
while (1)
{
if (numOpen != 0) //if there are still items in the open list
{
//pop the top item off of the list
atNode = openlist[1];
list[atNode] = 2; //put the node on the closed list so we don't check it again
--numOpen;
openlist[1] = openlist[numOpen+1]; //move the last item in the list to the top position
v = 1;
//this while loop reorders the list so that the new lowest fcost is at the top again
while (1)
{
u = v;
if ((2*u+1) < numOpen) //if both children exist
{
if (fcost[openlist[u]] >= fcost[openlist[2*u]])
v = 2*u;
if (fcost[openlist[v]] >= fcost[openlist[2*u+1]])
v = 2*u+1;
}
else
{
if ((2*u) < numOpen) //if only one child exists
{
if (fcost[openlist[u]] >= fcost[openlist[2*u]])
v = 2*u;
}
}
if (u != v) //if they're out of order, swap this item with its parent
{
temp = openlist[u];
openlist[u] = openlist[v];
openlist[v] = temp;
}
else
break;
}
for (i = 0; i < nodes[atNode].enodenum; ++i) //loop through all the links for this node
{
newnode = nodes[atNode].links[i].targetNode;
//if this path is blocked, skip it
if (nodes[atNode].links[i].flags & PATH_BLOCKED)
continue;
//if this path is blocked, skip it
if (bot->client && (bot->client->ps.eFlags & EF_TANK) && nodes[atNode].links[i].flags & PATH_NOTANKS)
continue;
//skip any unreachable nodes
if (bot->client && (nodes[newnode].type & NODE_ALLY_UNREACHABLE) && (bot->client->sess.sessionTeam == TEAM_ALLIES))
continue;
if (bot->client && (nodes[newnode].type & NODE_AXIS_UNREACHABLE) && (bot->client->sess.sessionTeam == TEAM_AXIS))
continue;
if (list[newnode] == 2) //if this node is on the closed list, skip it
continue;
if (list[newnode] != 1) //if this node is not already on the open list
{
openlist[++numOpen] = newnode; //add the new node to the open list
list[newnode] = 1;
parent[newnode] = atNode; //record the node's parent
if (newnode == to) //if we've found the goal, don't keep computing paths!
break; //this will break the 'for' and go all the way to 'if (list[to] == 1)'
//store it's f cost value
fcost[newnode] = GetFCost(to, newnode, parent[newnode], gcost);
//this loop re-orders the heap so that the lowest fcost is at the top
m = numOpen;
while (m != 1) //while this item isn't at the top of the heap already
{
//if it has a lower fcost than its parent
if (fcost[openlist[m]] <= fcost[openlist[m/2]])
{
temp = openlist[m/2];
openlist[m/2] = openlist[m];
openlist[m] = temp; //swap them
m /= 2;
}
else
break;
}
}
else //if this node is already on the open list
{
gc = gcost[atNode];
VectorSubtract(nodes[newnode].origin, nodes[atNode].origin, vec);
gc += VectorLength(vec); //calculate what the gcost would be if we reached this node along the current path
if (gc < gcost[newnode]) //if the new gcost is less (ie, this path is shorter than what we had before)
{
parent[newnode] = atNode; //set the new parent for this node
gcost[newnode] = gc; //and the new g cost
for (i = 1; i < numOpen; ++i) //loop through all the items on the open list
{
if (openlist[i] == newnode) //find this node in the list
{
//calculate the new fcost and store it
fcost[newnode] = GetFCost(to, newnode, parent[newnode], gcost);
//reorder the list again, with the lowest fcost item on top
m = i;
while (m != 1)
{
//if the item has a lower fcost than it's parent
if (fcost[openlist[m]] < fcost[openlist[m/2]])
{
temp = openlist[m/2];
openlist[m/2] = openlist[m];
openlist[m] = temp; //swap them
m /= 2;
}
else
break;
}
break; //exit the 'for' loop because we already changed this node
} //if
} //for
} //if (gc < gcost[newnode])
} //if (list[newnode] != 1) --> else
} //for (loop through links)
} //if (numOpen != 0)
else
{
found = qfalse; //there is no path between these nodes
break;
}
if (list[to] == 1) //if the destination node is on the open list, we're done
{
found = qtrue;
break;
}
} //while (1)
if (found == qtrue) //if we found a path
{
//G_Printf("%s - path found!n", bot->client->pers.netname);
count = 0;
temp = to; //start at the end point
while (temp != from) //travel along the path (backwards) until we reach the starting point
{
pathlist[count++] = temp; //add the node to the pathlist and increment the count
temp = parent[temp]; //move to the parent of this node to continue the path
}
pathlist[count++] = from; //add the beginning node to the end of the pathlist
#ifdef __BOT_SHORTEN_ROUTING__
count = ShortenASTARRoute(pathlist, count); // This isn't working... Dunno why.. Unique1
#endif //__BOT_SHORTEN_ROUTING__
}
else
{
//G_Printf("^1*** ^4BOT DEBUG^5: (CreatePathAStar) There is no route between node ^7%i^5 and node ^7%i^5.n", from, to);
count = CreateDumbRoute(from, to, pathlist);
if (count > 0)
{
#ifdef __BOT_SHORTEN_ROUTING__
count = ShortenASTARRoute(pathlist, count); // This isn't working... Dunno why.. Unique1
#endif //__BOT_SHORTEN_ROUTING__
return count;
}
}
return count; //return the number of nodes in the path, -1 if not found
}
/*
===========================================================================
GetFCost
Utility function used by A* pathfinding to calculate the
cost to move between nodes towards a goal. Using the A*
algorithm F = G + H, G here is the distance along the node
paths the bot must travel, and H is the straight-line distance
to the goal node.
Returned as an int because more precision is unnecessary and it
will slightly speed up heap access
===========================================================================
*/
int GetFCost(int to, int num, int parentNum, float *gcost)
{
float gc = 0;
float hc = 0;
vec3_t v;
if (gcost[num] == -1)
{
if (parentNum != -1)
{
gc = gcost[parentNum];
VectorSubtract(nodes[num].origin, nodes[parentNum].origin, v);
gc += VectorLength(v);
}
gcost[num] = gc;
}
else
gc = gcost[num];
VectorSubtract(nodes[to].origin, nodes[num].origin, v);
hc = VectorLength(v);
return (int)(gc + hc);
}
#endif //__PATHFINDING__