2013-04-19 02:52:48 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// RAVEN SOFTWARE - STAR WARS: JK II
|
|
|
|
// (c) 2002 Activision
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// NAVIGATOR
|
|
|
|
// ---------
|
|
|
|
// This file provides an interface to two actor related systems:
|
|
|
|
// - Path Finding
|
|
|
|
// - Steering
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifndef __G_NAVIGATOR__
|
|
|
|
#define __G_NAVIGATOR__
|
|
|
|
|
|
|
|
|
|
|
|
#define USENEWNAVSYSTEM 1
|
|
|
|
|
|
|
|
|
|
|
|
#if !defined(RAVL_VEC_INC)
|
2013-04-19 03:47:29 +00:00
|
|
|
#include "../Ravl/CVec.h"
|
2013-04-19 02:52:48 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// The NAV Namespace
|
|
|
|
//
|
|
|
|
// This namespace provides the public interface to the NPC Navigation and Pathfinding
|
|
|
|
// system. This system is a bidirectional graph of nodes and weighted edges. Finding
|
|
|
|
// a path from one node to another is accomplished with A*, and cached internally for
|
|
|
|
// each actor who requests a path.
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
namespace NAV
|
|
|
|
{
|
|
|
|
typedef int TNodeHandle;
|
|
|
|
typedef int TEdgeHandle;
|
|
|
|
|
|
|
|
|
|
|
|
enum EPointType
|
|
|
|
{
|
|
|
|
PT_NONE = 0,
|
|
|
|
|
|
|
|
PT_WAYNODE,
|
|
|
|
PT_COMBATNODE,
|
|
|
|
PT_GOALNODE,
|
|
|
|
|
|
|
|
PT_MAX
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Save, Load, Construct
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool LoadFromFile(const char *filename, int checksum);
|
|
|
|
bool TestEdge( TNodeHandle NodeA, TNodeHandle NodeB, qboolean IsDebugEdge );
|
|
|
|
bool LoadFromEntitiesAndSaveToFile(const char *filename, int checksum);
|
|
|
|
void SpawnedPoint(gentity_t* ent, EPointType type=PT_WAYNODE);
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Finding Nav Points
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TNodeHandle GetNearestNode(gentity_t* ent, bool forceRecalcNow=false, NAV::TNodeHandle goal=0);
|
|
|
|
TNodeHandle GetNearestNode(const vec3_t& position, TNodeHandle previous=0, NAV::TNodeHandle goal=0, int ignoreEnt=ENTITYNUM_NONE, bool allowZOffset=false);
|
|
|
|
|
|
|
|
TNodeHandle ChooseRandomNeighbor(TNodeHandle NodeHandle);
|
|
|
|
TNodeHandle ChooseRandomNeighbor(TNodeHandle NodeHandle, const vec3_t& position, float maxDistance);
|
|
|
|
TNodeHandle ChooseClosestNeighbor(TNodeHandle NodeHandle, const vec3_t& position);
|
|
|
|
TNodeHandle ChooseFarthestNeighbor(TNodeHandle NodeHandle, const vec3_t& position);
|
|
|
|
TNodeHandle ChooseFarthestNeighbor(gentity_t* actor, const vec3_t& target, float maxSafeDot);
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Get The Location Of A Given Node Handle
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
const vec3_t& GetNodePosition(TNodeHandle NodeHandle);
|
|
|
|
void GetNodePosition(TNodeHandle NodeHandle, vec3_t& position);
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Testing Nearness
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
float EstimateCostToGoal(const vec3_t& position, TNodeHandle Goal);
|
|
|
|
float EstimateCostToGoal(TNodeHandle Start, TNodeHandle Goal);
|
|
|
|
|
|
|
|
bool OnSamePoint(gentity_t* actor, gentity_t* target);
|
|
|
|
bool OnNeighboringPoints(TNodeHandle A, TNodeHandle B);
|
|
|
|
bool OnNeighboringPoints(gentity_t* actor, gentity_t* target);
|
|
|
|
bool OnNeighboringPoints(gentity_t* actor, const vec3_t& position);
|
|
|
|
bool InSameRegion(gentity_t* actor, gentity_t* target);
|
|
|
|
bool InSameRegion(gentity_t* actor, const vec3_t& position);
|
|
|
|
bool InSameRegion(TNodeHandle A, TNodeHandle B);
|
|
|
|
|
|
|
|
bool InSafeRadius(CVec3 at, TNodeHandle atNode, TNodeHandle targetNode=0);
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Finding A Path
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool GoTo(gentity_t* actor, TNodeHandle target, float MaxDangerLevel=1.0f);
|
|
|
|
bool GoTo(gentity_t* actor, gentity_t* target, float MaxDangerLevel=1.0f);
|
|
|
|
bool GoTo(gentity_t* actor, const vec3_t& position, float MaxDangerLevel=1.0f);
|
|
|
|
|
|
|
|
bool FindPath(gentity_t* actor, TNodeHandle target, float MaxDangerLevel=1.0f);
|
|
|
|
bool FindPath(gentity_t* actor, gentity_t* target, float MaxDangerLevel=1.0f);
|
|
|
|
bool FindPath(gentity_t* actor, const vec3_t& position, float MaxDangerLevel=1.0f);
|
|
|
|
|
|
|
|
bool SafePathExists(const CVec3& start, const CVec3& stop, const CVec3& danger, float dangerDistSq);
|
|
|
|
|
|
|
|
bool HasPath(gentity_t* actor, TNodeHandle target=PT_NONE);
|
|
|
|
void ClearPath(gentity_t* actor);
|
|
|
|
bool UpdatePath(gentity_t* actor, TNodeHandle target=PT_NONE, float MaxDangerLevel=1.0f);
|
|
|
|
float PathDangerLevel(gentity_t* actor);
|
|
|
|
int PathNodesRemaining(gentity_t* actor);
|
|
|
|
|
|
|
|
const vec3_t& NextPosition(gentity_t* actor);
|
|
|
|
bool NextPosition(gentity_t* actor, CVec3& Position);
|
|
|
|
bool NextPosition(gentity_t* actor, CVec3& Position, float& SlowingRadius, bool& Fly, bool& Jump);
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Update One Or More Edges As A Result Of An Entity Getting Removed
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void WayEdgesNowClear(gentity_t* ent);
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// How Big Is The Given Ent
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
unsigned int ClassifyEntSize(gentity_t* ent);
|
|
|
|
void RegisterDangerSense(gentity_t* actor, int alertEventIndex);
|
|
|
|
void DecayDangerSenses();
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Debugging Information
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void ShowDebugInfo(const vec3_t& PlayerPosition, TNodeHandle PlayerWaypoint);
|
|
|
|
void ShowStats();
|
|
|
|
|
|
|
|
void TeleportTo(gentity_t* actor, const char* pointName);
|
|
|
|
void TeleportTo(gentity_t* actor, int pointNum);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// The STEER Namespace
|
|
|
|
//
|
|
|
|
// These functions allow access to the steering system.
|
|
|
|
//
|
|
|
|
// The Reset() and Finalize() functions MUST be called before and after any other steering
|
|
|
|
// operations. Beyond that, all other steering operations can be called in any order
|
|
|
|
// and any number of times. Once Finalize() is called, the results of all these
|
|
|
|
// operations will be summed up and applied as accelleration to the actor's velocity.
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
namespace STEER
|
|
|
|
{
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Reset & Finalize
|
|
|
|
//
|
|
|
|
// Call these two operations before and after all other STEER operations. They
|
|
|
|
// clear out and setup the thrust vector for use by the entity.
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void Activate(gentity_t* actor);
|
|
|
|
void DeActivate(gentity_t* actor, usercmd_t* ucmd);
|
|
|
|
bool Active(gentity_t* actor);
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Master Functions
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool GoTo(gentity_t* actor, gentity_t* target, float reachedRadius, bool avoidCollisions=true);
|
|
|
|
bool GoTo(gentity_t* actor, const vec3_t& position, float reachedRadius, bool avoidCollisions=true);
|
|
|
|
|
|
|
|
bool SafeToGoTo(gentity_t* actor, const vec3_t& targetPosition, int targetNode);
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Stop
|
|
|
|
//
|
|
|
|
// Slow down and come to a stop.
|
|
|
|
//
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
float Stop(gentity_t* actor, float weight=1.0f);
|
|
|
|
float MatchSpeed(gentity_t* actor, float speed, float weight=1.0f);
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Seek & Flee
|
|
|
|
//
|
|
|
|
// These two operations form the root of all steering. They do simple
|
|
|
|
// vector operations and add to the thrust vector.
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
float Seek(gentity_t* actor, const CVec3& pos, float slowingDistance=0.0f, float weight=1.0f, float desiredSpeed=0.0f);
|
|
|
|
float Flee(gentity_t* actor, const CVec3& pos, float weight=1.0f);
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Persue & Evade
|
|
|
|
//
|
|
|
|
// Slightly more complicated than Seek & Flee, these operations predict the position
|
|
|
|
// of the target entitiy.
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
float Persue(gentity_t* actor, gentity_t* target, float slowingDistance);
|
|
|
|
float Persue(gentity_t* actor, gentity_t* target, float slowingDistance, float offsetForward, float offsetRight=0.0f, float offsetUp=0.0f, bool relativeToTargetFacing=false);
|
|
|
|
float Evade(gentity_t* actor, gentity_t* target);
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Separation, Alignment, Cohesion
|
|
|
|
//
|
|
|
|
// These standard steering operations will apply thrust to achieve a group oriented
|
|
|
|
// position or direction.
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
float Separation(gentity_t* actor, float Scale=1.0f);
|
|
|
|
float Alignment(gentity_t* actor, float Scale=1.0f);
|
|
|
|
float Cohesion(gentity_t* actor, float Scale=1.0f);
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Wander & Path
|
|
|
|
//
|
|
|
|
// By far the most common way to alter a character's thrust, path maintaines motion
|
|
|
|
// along a navigational path (see NAV namespace), and a random wander path.
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
float Path(gentity_t* actor);
|
|
|
|
float Wander(gentity_t* actor);
|
|
|
|
float FollowLeader(gentity_t* actor, gentity_t* leader, float dist);
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Collision Avoidance
|
|
|
|
//
|
|
|
|
// Usually the last steering operation to call before finialization, this operation
|
|
|
|
// attempts to avoid collisions with nearby entities and architecture by thrusing
|
|
|
|
// away from them.
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
float AvoidCollisions(gentity_t* actor, gentity_t* leader=0);
|
|
|
|
gentity_t* SelectLeader(gentity_t* actor);
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Blocked
|
|
|
|
//
|
|
|
|
// This function records whether AI is blocked while the steering is active
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void Blocked(gentity_t* actor, gentity_t* target);
|
|
|
|
void Blocked(gentity_t* actor, const vec3_t& target);
|
|
|
|
bool HasBeenBlockedFor(gentity_t* actor, int duration);
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Reached
|
|
|
|
//
|
|
|
|
// A quick function to see if a target location has been reached by an actor
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool Reached(gentity_t* actor, gentity_t* target, float targetRadius, bool flying=false);
|
|
|
|
bool Reached(gentity_t* actor, NAV::TNodeHandle target, float targetRadius, bool flying=false);
|
|
|
|
bool Reached(gentity_t* actor, const vec3_t& target, float targetRadius, bool flying=false);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-04-04 22:35:38 +00:00
|
|
|
#endif //__G_NAVIGATOR__
|