mirror of
https://github.com/jmarshall23/DoomRTX.git
synced 2026-08-19 20:19:50 +02:00
Initial Prey Game integration support.
This commit is contained in:
@@ -0,0 +1,250 @@
|
||||
// Copyright (C) 2004 Id Software, Inc.
|
||||
//
|
||||
|
||||
#include "precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "AAS_local.h"
|
||||
|
||||
/*
|
||||
============
|
||||
idAAS::Alloc
|
||||
============
|
||||
*/
|
||||
idAAS *idAAS::Alloc( void ) {
|
||||
return new idAASLocal;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAAS::idAAS
|
||||
============
|
||||
*/
|
||||
idAAS::~idAAS( void ) {
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::idAASLocal
|
||||
============
|
||||
*/
|
||||
idAASLocal::idAASLocal( void ) {
|
||||
file = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::~idAASLocal
|
||||
============
|
||||
*/
|
||||
idAASLocal::~idAASLocal( void ) {
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::Init
|
||||
============
|
||||
*/
|
||||
bool idAASLocal::Init( const idStr &mapName, unsigned int mapFileCRC ) {
|
||||
if ( file && mapName.Icmp( file->GetName() ) == 0 && mapFileCRC == file->GetCRC() ) {
|
||||
common->Printf( "Keeping %s\n", file->GetName() );
|
||||
RemoveAllObstacles();
|
||||
}
|
||||
else {
|
||||
Shutdown();
|
||||
|
||||
file = AASFileManager->LoadAAS( mapName, mapFileCRC );
|
||||
if ( !file ) {
|
||||
common->DWarning( "Couldn't load AAS file: '%s'", mapName.c_str() );
|
||||
return false;
|
||||
}
|
||||
SetupRouting();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::Shutdown
|
||||
============
|
||||
*/
|
||||
void idAASLocal::Shutdown( void ) {
|
||||
if ( file ) {
|
||||
ShutdownRouting();
|
||||
RemoveAllObstacles();
|
||||
AASFileManager->FreeAAS( file );
|
||||
file = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::Stats
|
||||
============
|
||||
*/
|
||||
void idAASLocal::Stats( void ) const {
|
||||
if ( !file ) {
|
||||
return;
|
||||
}
|
||||
common->Printf( "[%s]\n", file->GetName() );
|
||||
file->PrintInfo();
|
||||
RoutingStats();
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::GetSettings
|
||||
============
|
||||
*/
|
||||
const idAASSettings *idAASLocal::GetSettings( void ) const {
|
||||
if ( !file ) {
|
||||
return NULL;
|
||||
}
|
||||
return &file->GetSettings();
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::PointAreaNum
|
||||
============
|
||||
*/
|
||||
int idAASLocal::PointAreaNum( const idVec3 &origin ) const {
|
||||
if ( !file ) {
|
||||
return 0;
|
||||
}
|
||||
return file->PointAreaNum( origin );
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::PointReachableAreaNum
|
||||
============
|
||||
*/
|
||||
int idAASLocal::PointReachableAreaNum( const idVec3 &origin, const idBounds &searchBounds, const int areaFlags ) const {
|
||||
if ( !file ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return file->PointReachableAreaNum( origin, searchBounds, areaFlags, TFL_INVALID );
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::BoundsReachableAreaNum
|
||||
============
|
||||
*/
|
||||
int idAASLocal::BoundsReachableAreaNum( const idBounds &bounds, const int areaFlags ) const {
|
||||
if ( !file ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return file->BoundsReachableAreaNum( bounds, areaFlags, TFL_INVALID );
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::PushPointIntoAreaNum
|
||||
============
|
||||
*/
|
||||
void idAASLocal::PushPointIntoAreaNum( int areaNum, idVec3 &origin ) const {
|
||||
if ( !file ) {
|
||||
return;
|
||||
}
|
||||
file->PushPointIntoAreaNum( areaNum, origin );
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::AreaCenter
|
||||
============
|
||||
*/
|
||||
idVec3 idAASLocal::AreaCenter( int areaNum ) const {
|
||||
if ( !file ) {
|
||||
return vec3_origin;
|
||||
}
|
||||
return file->GetArea( areaNum ).center;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::AreaFlags
|
||||
============
|
||||
*/
|
||||
int idAASLocal::AreaFlags( int areaNum ) const {
|
||||
if ( !file ) {
|
||||
return 0;
|
||||
}
|
||||
return file->GetArea( areaNum ).flags;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::AreaTravelFlags
|
||||
============
|
||||
*/
|
||||
int idAASLocal::AreaTravelFlags( int areaNum ) const {
|
||||
if ( !file ) {
|
||||
return 0;
|
||||
}
|
||||
return file->GetArea( areaNum ).travelFlags;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::Trace
|
||||
============
|
||||
*/
|
||||
bool idAASLocal::Trace( aasTrace_t &trace, const idVec3 &start, const idVec3 &end ) const {
|
||||
if ( !file ) {
|
||||
trace.fraction = 0.0f;
|
||||
trace.lastAreaNum = 0;
|
||||
trace.numAreas = 0;
|
||||
return true;
|
||||
}
|
||||
return file->Trace( trace, start, end );
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::GetPlane
|
||||
============
|
||||
*/
|
||||
const idPlane &idAASLocal::GetPlane( int planeNum ) const {
|
||||
if ( !file ) {
|
||||
static idPlane dummy;
|
||||
return dummy;
|
||||
}
|
||||
return file->GetPlane( planeNum );
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::GetEdgeVertexNumbers
|
||||
============
|
||||
*/
|
||||
void idAASLocal::GetEdgeVertexNumbers( int edgeNum, int verts[2] ) const {
|
||||
if ( !file ) {
|
||||
verts[0] = verts[1] = 0;
|
||||
return;
|
||||
}
|
||||
const int *v = file->GetEdge( abs(edgeNum) ).vertexNum;
|
||||
verts[0] = v[INTSIGNBITSET(edgeNum)];
|
||||
verts[1] = v[INTSIGNBITNOTSET(edgeNum)];
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::GetEdge
|
||||
============
|
||||
*/
|
||||
void idAASLocal::GetEdge( int edgeNum, idVec3 &start, idVec3 &end ) const {
|
||||
if ( !file ) {
|
||||
start.Zero();
|
||||
end.Zero();
|
||||
return;
|
||||
}
|
||||
const int *v = file->GetEdge( abs(edgeNum) ).vertexNum;
|
||||
start = file->GetVertex( v[INTSIGNBITSET(edgeNum)] );
|
||||
end = file->GetVertex( v[INTSIGNBITNOTSET(edgeNum)] );
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
// Copyright (C) 2004 Id Software, Inc.
|
||||
//
|
||||
|
||||
#ifndef __AAS_H__
|
||||
#define __AAS_H__
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
Area Awareness System
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
enum {
|
||||
PATHTYPE_WALK,
|
||||
PATHTYPE_WALKOFFLEDGE,
|
||||
PATHTYPE_BARRIERJUMP,
|
||||
PATHTYPE_JUMP,
|
||||
PATHTYPE_FLY // HUMANHEAD nla
|
||||
};
|
||||
|
||||
typedef struct aasPath_s {
|
||||
int type; // path type
|
||||
idVec3 moveGoal; // point the AI should move towards
|
||||
int moveAreaNum; // number of the area the AI should move towards
|
||||
idVec3 secondaryGoal; // secondary move goal for complex navigation
|
||||
const idReachability * reachability; // reachability used for navigation
|
||||
} aasPath_t;
|
||||
|
||||
|
||||
typedef struct aasGoal_s {
|
||||
int areaNum; // area the goal is in
|
||||
idVec3 origin; // position of goal
|
||||
} aasGoal_t;
|
||||
|
||||
|
||||
typedef struct aasObstacle_s {
|
||||
idBounds absBounds; // absolute bounds of obstacle
|
||||
idBounds expAbsBounds; // expanded absolute bounds of obstacle
|
||||
} aasObstacle_t;
|
||||
|
||||
class idAASCallback {
|
||||
public:
|
||||
virtual ~idAASCallback() {};
|
||||
virtual bool TestArea( const class idAAS *aas, int areaNum ) = 0;
|
||||
};
|
||||
|
||||
typedef int aasHandle_t;
|
||||
class hhPathApproach; // HUMANHEAD jrm
|
||||
|
||||
class idAAS {
|
||||
public:
|
||||
static idAAS * Alloc( void );
|
||||
virtual ~idAAS( void ) = 0;
|
||||
// Initialize for the given map.
|
||||
virtual bool Init( const idStr &mapName, unsigned int mapFileCRC ) = 0;
|
||||
// Print AAS stats.
|
||||
virtual void Stats( void ) const = 0;
|
||||
// Test from the given origin.
|
||||
virtual void Test( const idVec3 &origin ) = 0;
|
||||
// Get the AAS settings.
|
||||
virtual const idAASSettings *GetSettings( void ) const = 0;
|
||||
// Returns the number of the area the origin is in.
|
||||
virtual int PointAreaNum( const idVec3 &origin ) const = 0;
|
||||
// Returns the number of the nearest reachable area for the given point.
|
||||
virtual int PointReachableAreaNum( const idVec3 &origin, const idBounds &bounds, const int areaFlags ) const = 0;
|
||||
// Returns the number of the first reachable area in or touching the bounds.
|
||||
virtual int BoundsReachableAreaNum( const idBounds &bounds, const int areaFlags ) const = 0;
|
||||
// Push the point into the area.
|
||||
virtual void PushPointIntoAreaNum( int areaNum, idVec3 &origin ) const = 0;
|
||||
// Returns a reachable point inside the given area.
|
||||
virtual idVec3 AreaCenter( int areaNum ) const = 0;
|
||||
// Returns the area flags.
|
||||
virtual int AreaFlags( int areaNum ) const = 0;
|
||||
// Returns the travel flags for traveling through the area.
|
||||
virtual int AreaTravelFlags( int areaNum ) const = 0;
|
||||
// Trace through the areas and report the first collision.
|
||||
virtual bool Trace( aasTrace_t &trace, const idVec3 &start, const idVec3 &end ) const = 0;
|
||||
// Get a plane for a trace.
|
||||
virtual const idPlane & GetPlane( int planeNum ) const = 0;
|
||||
// Get wall edges.
|
||||
virtual int GetWallEdges( int areaNum, const idBounds &bounds, int travelFlags, int *edges, int maxEdges ) const = 0;
|
||||
// Sort the wall edges to create continuous sequences of walls.
|
||||
virtual void SortWallEdges( int *edges, int numEdges ) const = 0;
|
||||
// Get the vertex numbers for an edge.
|
||||
virtual void GetEdgeVertexNumbers( int edgeNum, int verts[2] ) const = 0;
|
||||
// Get an edge.
|
||||
virtual void GetEdge( int edgeNum, idVec3 &start, idVec3 &end ) const = 0;
|
||||
// Find all areas within or touching the bounds with the given contents and disable/enable them for routing.
|
||||
virtual bool SetAreaState( const idBounds &bounds, const int areaContents, bool disabled ) = 0;
|
||||
// Add an obstacle to the routing system.
|
||||
virtual aasHandle_t AddObstacle( const idBounds &bounds ) = 0;
|
||||
// Remove an obstacle from the routing system.
|
||||
virtual void RemoveObstacle( const aasHandle_t handle ) = 0;
|
||||
// Remove all obstacles from the routing system.
|
||||
virtual void RemoveAllObstacles( void ) = 0;
|
||||
// Returns the travel time towards the goal area in 100th of a second.
|
||||
virtual int TravelTimeToGoalArea( int areaNum, const idVec3 &origin, int goalAreaNum, int travelFlags ) const = 0;
|
||||
// Get the travel time and first reachability to be used towards the goal, returns true if there is a path.
|
||||
virtual bool RouteToGoalArea( int areaNum, const idVec3 origin, int goalAreaNum, int travelFlags, int &travelTime, idReachability **reach ) const = 0;
|
||||
// Creates a walk path towards the goal.
|
||||
virtual bool WalkPathToGoal( aasPath_t &path, int areaNum, const idVec3 &origin, int goalAreaNum, const idVec3 &goalOrigin, int travelFlags ) const = 0;
|
||||
// Returns true if one can walk along a straight line from the origin to the goal origin.
|
||||
virtual bool WalkPathValid( int areaNum, const idVec3 &origin, int goalAreaNum, const idVec3 &goalOrigin, int travelFlags, idVec3 &endPos, int &endAreaNum ) const = 0;
|
||||
// Creates a fly path towards the goal.
|
||||
virtual bool FlyPathToGoal( aasPath_t &path, int areaNum, const idVec3 &origin, int goalAreaNum, const idVec3 &goalOrigin, int travelFlags ) const = 0;
|
||||
// Returns true if one can fly along a straight line from the origin to the goal origin.
|
||||
virtual bool FlyPathValid( int areaNum, const idVec3 &origin, int goalAreaNum, const idVec3 &goalOrigin, int travelFlags, idVec3 &endPos, int &endAreaNum ) const = 0;
|
||||
// Show the walk path from the origin towards the area.
|
||||
virtual void ShowWalkPath( const idVec3 &origin, int goalAreaNum, const idVec3 &goalOrigin ) const = 0;
|
||||
// Show the fly path from the origin towards the area.
|
||||
virtual void ShowFlyPath( const idVec3 &origin, int goalAreaNum, const idVec3 &goalOrigin ) const = 0;
|
||||
// Find the nearest goal which satisfies the callback.
|
||||
virtual bool FindNearestGoal( aasGoal_t &goal, int areaNum, const idVec3 origin, const idVec3 &target, int travelFlags, aasObstacle_t *obstacles, int numObstacles, idAASCallback &callback ) const = 0;
|
||||
};
|
||||
|
||||
#endif /* !__AAS_H__ */
|
||||
@@ -0,0 +1,223 @@
|
||||
// HUMANHEAD nla
|
||||
|
||||
#include "../../idlib/precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "AAS_local.h"
|
||||
|
||||
|
||||
/*
|
||||
============================
|
||||
idAASLocal::FindNearestPoint
|
||||
============================
|
||||
*/
|
||||
|
||||
idVec3 idAASLocal::FindNearestPoint(const idVec3 &ally,
|
||||
const idVec3 &follower,
|
||||
float distance) {
|
||||
hhNearPoint nearPoint(ally, follower, distance);
|
||||
idList<int> areasEntered;
|
||||
|
||||
if (!file) {
|
||||
return(vec3_origin);
|
||||
}
|
||||
|
||||
|
||||
FindNearestPointInArea(nearPoint,
|
||||
PointReachableAreaNum(follower),
|
||||
areasEntered);
|
||||
|
||||
|
||||
areasEntered.Clear();
|
||||
|
||||
return(nearPoint.getBestPoint());
|
||||
|
||||
} //. idAASLocal::FindNearestPoint(const idVec3 &, const idVec3 &, float)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
=================================
|
||||
idAASLocal::FindNearestPointInArea
|
||||
|
||||
Returns true if a valid point was found
|
||||
=================================
|
||||
*/
|
||||
bool idAASLocal::FindNearestPointInArea(hhNearPoint &nearPoint,
|
||||
int currentArea,
|
||||
idList<int> &areasEntered) {
|
||||
aasArea_t *area;
|
||||
findAreaType_t foundPoint;
|
||||
idReachability *reach;
|
||||
int areaNum;
|
||||
|
||||
|
||||
if (currentArea == 0) {
|
||||
return(false);
|
||||
}
|
||||
|
||||
area = &file->areas[currentArea];
|
||||
|
||||
areasEntered.Append(currentArea);
|
||||
|
||||
// Check all points in the area for a better point. true if a valid
|
||||
// point was found
|
||||
foundPoint = CheckPointsInArea(nearPoint, currentArea);
|
||||
|
||||
switch (foundPoint) {
|
||||
// We are outside of the area completely
|
||||
case AREA_ALL_DESIRED:
|
||||
return(true);
|
||||
break;
|
||||
// We are still too close, try out further
|
||||
case AREA_MIXED:
|
||||
for (reach = area->reach; reach; reach = reach->next) {
|
||||
if (reach->travelType != TFL_WALK) {
|
||||
continue;
|
||||
}
|
||||
|
||||
areaNum = reach->toAreaNum;
|
||||
if (areasEntered.FindIndex(areaNum) == -1) {
|
||||
FindNearestPointInArea(nearPoint, areaNum,
|
||||
areasEntered);
|
||||
}
|
||||
} //. reachable areas loop
|
||||
return(true);
|
||||
break;
|
||||
// No valid points were found in this area, return false
|
||||
case AREA_NO_VALID_POINTS:
|
||||
return(false);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return(false); // Should never get here. :)
|
||||
|
||||
} //. idAASLocal::FindNearestPointInArea(hhNearPoint, int, int)
|
||||
|
||||
|
||||
/*
|
||||
==============================
|
||||
idAASLocal::CheckPointsInArea
|
||||
==============================
|
||||
*/
|
||||
findAreaType_t idAASLocal::CheckPointsInArea(hhNearPoint &nearPoint,
|
||||
int areaNum) {
|
||||
aasArea_t *area;
|
||||
aasFace_t *face;
|
||||
aasEdge_t *edge;
|
||||
aasVertex_t *vert;
|
||||
int numFaces, firstFace, faceNum;
|
||||
int numEdges, firstEdge, edgeNum;
|
||||
int faceCounter, edgeCounter, vertCounter;
|
||||
findPointType_t pointType;
|
||||
findAreaType_t areaType;
|
||||
int pointTotal;
|
||||
|
||||
|
||||
areaType = AREA_NO_VALID_POINTS;
|
||||
pointTotal = 0;
|
||||
|
||||
area = &file->areas[areaNum];
|
||||
numFaces = area->numFaces;
|
||||
firstFace = area->firstFace;
|
||||
|
||||
for (faceCounter = 0; faceCounter < numFaces; ++faceCounter) {
|
||||
faceNum = abs(file->faceIndex[firstFace + faceCounter]);
|
||||
|
||||
face = &file->faces[faceNum];
|
||||
numEdges = face->numEdges;
|
||||
firstEdge = face->firstEdge;
|
||||
|
||||
for (edgeCounter = 0; edgeCounter < numEdges; ++edgeCounter) {
|
||||
edgeNum = abs(file->edgeIndex[firstEdge + edgeCounter]);
|
||||
edge = &file->edges[edgeNum];
|
||||
|
||||
for (vertCounter = 0; vertCounter < 2; ++vertCounter) {
|
||||
vert = &file->vertices[edge->vertexNum[vertCounter]];
|
||||
|
||||
//! Make a function
|
||||
pointType = CheckPoint(*vert, nearPoint);
|
||||
|
||||
pointTotal |= pointType;
|
||||
} //. vertCounter
|
||||
} //. edgeCounter
|
||||
} //. faceCounter
|
||||
|
||||
// If there are any just valid points, we are mixed
|
||||
if (pointTotal & POINT_VALID) {
|
||||
areaType = AREA_MIXED;
|
||||
}
|
||||
// If just desired points, we are all desired
|
||||
else if (pointTotal & POINT_DESIRED) {
|
||||
areaType = AREA_ALL_DESIRED;
|
||||
}
|
||||
|
||||
return(areaType);
|
||||
|
||||
|
||||
} //. idAASLocal::CheckPointsInArea(hhNearPoint &, int)
|
||||
|
||||
|
||||
/*
|
||||
======================
|
||||
idAASLocal::CheckPoint
|
||||
======================
|
||||
*/
|
||||
findPointType_t idAASLocal::CheckPoint(idVec3 &point,
|
||||
hhNearPoint &nearPoint) {
|
||||
idVec3 pointDirection;
|
||||
findPointType_t pointType;
|
||||
aasTrace_t aasTrace;
|
||||
float dot;
|
||||
float lengthSq;
|
||||
bool blocked;
|
||||
bool isBetterDot;
|
||||
|
||||
|
||||
pointDirection = point - nearPoint.ourOrigin;
|
||||
|
||||
pointType = POINT_NOT_VALID;
|
||||
|
||||
if (pointDirection * nearPoint.direction > 0) {
|
||||
pointType = POINT_VALID;
|
||||
|
||||
Trace(aasTrace, nearPoint.ourOrigin, point);
|
||||
blocked = aasTrace.fraction < 1.0;
|
||||
|
||||
lengthSq = pointDirection.LengthSqr();
|
||||
|
||||
// Out far enough
|
||||
if (lengthSq > nearPoint.desiredDistSq) {
|
||||
// If a point inside the desired dist was chosen, reset key comparisons
|
||||
if (nearPoint.bestDistSq < nearPoint.desiredDistSq) {
|
||||
nearPoint.bestDot = 0;
|
||||
nearPoint.bestBlocked = true;
|
||||
}
|
||||
|
||||
dot = pointDirection * nearPoint.direction;
|
||||
|
||||
// Is there something between dest and us
|
||||
isBetterDot = dot > nearPoint.bestDot;
|
||||
|
||||
if ((!blocked && (nearPoint.bestBlocked || isBetterDot)) ||
|
||||
(blocked && nearPoint.bestBlocked && isBetterDot)) {
|
||||
nearPoint.bestPoint = point;
|
||||
nearPoint.bestDot = dot;
|
||||
nearPoint.bestBlocked = blocked;
|
||||
nearPoint.bestDistSq = lengthSq;
|
||||
} //. Better fit for desired direction
|
||||
pointType = POINT_DESIRED;
|
||||
} //. desired point
|
||||
else { // Inside the circle chose the furthest non blocked point
|
||||
if (!blocked && (lengthSq > nearPoint.bestDistSq)) {
|
||||
nearPoint.bestPoint = point;
|
||||
nearPoint.bestDistSq = lengthSq;
|
||||
}
|
||||
} //. Inside the desired circle
|
||||
} //. valid point
|
||||
|
||||
|
||||
return(pointType);
|
||||
|
||||
} //. idAASLocal::CheckPoint(const idVec3 &, hhNearPoint)
|
||||
@@ -0,0 +1,568 @@
|
||||
// Copyright (C) 2004 Id Software, Inc.
|
||||
//
|
||||
|
||||
#include "precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "AAS_local.h"
|
||||
#include "../Game_local.h" // for cvars and debug drawing
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::DrawCone
|
||||
============
|
||||
*/
|
||||
void idAASLocal::DrawCone( const idVec3 &origin, const idVec3 &dir, float radius, const idVec4 &color ) const {
|
||||
int i;
|
||||
idMat3 axis;
|
||||
idVec3 center, top, p, lastp;
|
||||
|
||||
axis[2] = dir;
|
||||
axis[2].NormalVectors( axis[0], axis[1] );
|
||||
axis[1] = -axis[1];
|
||||
|
||||
center = origin + dir;
|
||||
top = center + dir * (3.0f * radius);
|
||||
lastp = center + radius * axis[1];
|
||||
|
||||
for ( i = 20; i <= 360; i += 20 ) {
|
||||
p = center + sin( DEG2RAD(i) ) * radius * axis[0] + cos( DEG2RAD(i) ) * radius * axis[1];
|
||||
gameRenderWorld->DebugLine( color, lastp, p, 0 );
|
||||
gameRenderWorld->DebugLine( color, p, top, 0 );
|
||||
lastp = p;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::DrawReachability
|
||||
============
|
||||
*/
|
||||
void idAASLocal::DrawReachability( const idReachability *reach ) const {
|
||||
#ifdef HUMANHEAD
|
||||
idVec3 dir = (reach->end - reach->start).ToNormal() * 10;
|
||||
gameRenderWorld->DebugArrow( colorCyan, reach->start - dir, reach->end + dir, 2 );
|
||||
gameRenderWorld->DrawText( va( "%d", reach->toAreaNum ), ( reach->start + reach->end ) * 0.5f, 0.1f, colorCyan, gameLocal.GetLocalPlayer()->viewAxis );
|
||||
#else
|
||||
gameRenderWorld->DebugArrow( colorCyan, reach->start, reach->end, 2 );
|
||||
|
||||
if ( gameLocal.GetLocalPlayer() ) {
|
||||
gameRenderWorld->DrawText( va( "%d", reach->edgeNum ), ( reach->start + reach->end ) * 0.5f, 0.1f, colorWhite, gameLocal.GetLocalPlayer()->viewAxis );
|
||||
}
|
||||
#endif
|
||||
|
||||
switch( reach->travelType ) {
|
||||
case TFL_WALK: {
|
||||
const idReachability_Walk *walk = static_cast<const idReachability_Walk *>(reach);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::DrawEdge
|
||||
============
|
||||
*/
|
||||
// HUMANHEAD nla - Added color parameterv
|
||||
void idAASLocal::DrawEdge( int edgeNum, bool arrow, idVec4 *color ) const {
|
||||
const aasEdge_t *edge;
|
||||
|
||||
if ( !file ) {
|
||||
return;
|
||||
}
|
||||
|
||||
edge = &file->GetEdge( edgeNum );
|
||||
if ( arrow ) {
|
||||
gameRenderWorld->DebugArrow( *color, file->GetVertex( edge->vertexNum[0] ), file->GetVertex( edge->vertexNum[1] ), 1 );
|
||||
} else {
|
||||
gameRenderWorld->DebugLine( *color, file->GetVertex( edge->vertexNum[0] ), file->GetVertex( edge->vertexNum[1] ) );
|
||||
}
|
||||
|
||||
if ( gameLocal.GetLocalPlayer() ) {
|
||||
gameRenderWorld->DrawText( va( "%d", edgeNum ), ( file->GetVertex( edge->vertexNum[0] ) + file->GetVertex( edge->vertexNum[1] ) ) * 0.5f + idVec3(0,0,4), 0.1f, colorRed, gameLocal.GetLocalPlayer()->viewAxis );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::DrawFace
|
||||
============
|
||||
*/
|
||||
// HUMANHEAD nla - Added color parameter
|
||||
void idAASLocal::DrawFace( int faceNum, bool side, idVec4 *color ) const {
|
||||
int i, j, numEdges, firstEdge;
|
||||
const aasFace_t *face;
|
||||
idVec3 mid, end;
|
||||
|
||||
if ( !file ) {
|
||||
return;
|
||||
}
|
||||
|
||||
face = &file->GetFace( faceNum );
|
||||
numEdges = face->numEdges;
|
||||
firstEdge = face->firstEdge;
|
||||
|
||||
mid = vec3_origin;
|
||||
for ( i = 0; i < numEdges; i++ ) {
|
||||
DrawEdge( abs( file->GetEdgeIndex( firstEdge + i ) ), ( face->flags & FACE_FLOOR ) != 0, color );
|
||||
j = file->GetEdgeIndex( firstEdge + i );
|
||||
mid += file->GetVertex( file->GetEdge( abs( j ) ).vertexNum[ j < 0 ] );
|
||||
}
|
||||
|
||||
mid /= numEdges;
|
||||
if ( side ) {
|
||||
end = mid - 5.0f * file->GetPlane( file->GetFace( faceNum ).planeNum ).Normal();
|
||||
} else {
|
||||
end = mid + 5.0f * file->GetPlane( file->GetFace( faceNum ).planeNum ).Normal();
|
||||
}
|
||||
gameRenderWorld->DebugArrow( colorGreen, mid, end, 1 );
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::DrawArea
|
||||
============
|
||||
*/
|
||||
void idAASLocal::DrawArea( int areaNum ) const {
|
||||
int i, numFaces, firstFace;
|
||||
const aasArea_t *area;
|
||||
idReachability *reach;
|
||||
|
||||
if ( !file ) {
|
||||
return;
|
||||
}
|
||||
|
||||
area = &file->GetArea( areaNum );
|
||||
numFaces = area->numFaces;
|
||||
firstFace = area->firstFace;
|
||||
|
||||
for ( i = 0; i < numFaces; i++ ) {
|
||||
// HUMANHEAD nla - added color parameter
|
||||
DrawFace( abs( file->GetFaceIndex( firstFace + i ) ), file->GetFaceIndex( firstFace + i ) < 0,
|
||||
&colorRed );
|
||||
}
|
||||
|
||||
for ( reach = area->reach; reach; reach = reach->next ) {
|
||||
DrawReachability( reach );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::DefaultSearchBounds
|
||||
============
|
||||
*/
|
||||
const idBounds &idAASLocal::DefaultSearchBounds( void ) const {
|
||||
return file->GetSettings().boundingBoxes[0];
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::ShowArea
|
||||
============
|
||||
*/
|
||||
void idAASLocal::ShowArea( const idVec3 &origin ) const {
|
||||
static int lastAreaNum;
|
||||
int areaNum;
|
||||
const aasArea_t *area;
|
||||
idVec3 org;
|
||||
|
||||
areaNum = PointReachableAreaNum( origin, DefaultSearchBounds(), (AREA_REACHABLE_WALK|AREA_REACHABLE_FLY) );
|
||||
org = origin;
|
||||
PushPointIntoAreaNum( areaNum, org );
|
||||
|
||||
if ( aas_goalArea.GetInteger() ) {
|
||||
int travelTime;
|
||||
idReachability *reach;
|
||||
|
||||
RouteToGoalArea( areaNum, org, aas_goalArea.GetInteger(), TFL_WALK|TFL_AIR, travelTime, &reach );
|
||||
gameLocal.Printf( "\rtt = %4d", travelTime );
|
||||
if ( reach ) {
|
||||
gameLocal.Printf( " to area %4d", reach->toAreaNum );
|
||||
DrawArea( reach->toAreaNum );
|
||||
}
|
||||
}
|
||||
|
||||
if ( areaNum != lastAreaNum ) {
|
||||
area = &file->GetArea( areaNum );
|
||||
gameLocal.Printf( "area %d: ", areaNum );
|
||||
if ( area->flags & AREA_LEDGE ) {
|
||||
gameLocal.Printf( "AREA_LEDGE " );
|
||||
}
|
||||
if ( area->flags & AREA_REACHABLE_WALK ) {
|
||||
gameLocal.Printf( "AREA_REACHABLE_WALK " );
|
||||
}
|
||||
if ( area->flags & AREA_REACHABLE_FLY ) {
|
||||
gameLocal.Printf( "AREA_REACHABLE_FLY " );
|
||||
}
|
||||
if ( area->contents & AREACONTENTS_CLUSTERPORTAL ) {
|
||||
gameLocal.Printf( "AREACONTENTS_CLUSTERPORTAL " );
|
||||
}
|
||||
if ( area->contents & AREACONTENTS_OBSTACLE ) {
|
||||
gameLocal.Printf( "AREACONTENTS_OBSTACLE " );
|
||||
}
|
||||
gameLocal.Printf( "\n" );
|
||||
lastAreaNum = areaNum;
|
||||
}
|
||||
|
||||
if ( org != origin ) {
|
||||
idBounds bnds = file->GetSettings().boundingBoxes[ 0 ];
|
||||
bnds[ 1 ].z = bnds[ 0 ].z;
|
||||
gameRenderWorld->DebugBounds( colorYellow, bnds, org );
|
||||
}
|
||||
|
||||
DrawArea( areaNum );
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::ShowWalkPath
|
||||
============
|
||||
*/
|
||||
void idAASLocal::ShowWalkPath( const idVec3 &origin, int goalAreaNum, const idVec3 &goalOrigin ) const {
|
||||
int i, areaNum, curAreaNum, travelTime;
|
||||
idReachability *reach;
|
||||
idVec3 org, areaCenter;
|
||||
aasPath_t path;
|
||||
|
||||
if ( !file ) {
|
||||
return;
|
||||
}
|
||||
|
||||
org = origin;
|
||||
areaNum = PointReachableAreaNum( org, DefaultSearchBounds(), AREA_REACHABLE_WALK );
|
||||
PushPointIntoAreaNum( areaNum, org );
|
||||
curAreaNum = areaNum;
|
||||
|
||||
for ( i = 0; i < 100; i++ ) {
|
||||
|
||||
if ( !RouteToGoalArea( curAreaNum, org, goalAreaNum, TFL_WALK|TFL_AIR, travelTime, &reach ) ) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !reach ) {
|
||||
break;
|
||||
}
|
||||
|
||||
gameRenderWorld->DebugArrow( colorGreen, org, reach->start, 2 );
|
||||
DrawReachability( reach );
|
||||
|
||||
if ( reach->toAreaNum == goalAreaNum ) {
|
||||
break;
|
||||
}
|
||||
|
||||
curAreaNum = reach->toAreaNum;
|
||||
org = reach->end;
|
||||
}
|
||||
|
||||
if ( WalkPathToGoal( path, areaNum, origin, goalAreaNum, goalOrigin, TFL_WALK|TFL_AIR ) ) {
|
||||
gameRenderWorld->DebugArrow( colorBlue, origin, path.moveGoal, 2 );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::ShowFlyPath
|
||||
============
|
||||
*/
|
||||
void idAASLocal::ShowFlyPath( const idVec3 &origin, int goalAreaNum, const idVec3 &goalOrigin ) const {
|
||||
int i, areaNum, curAreaNum, travelTime;
|
||||
idReachability *reach;
|
||||
idVec3 org, areaCenter;
|
||||
aasPath_t path;
|
||||
|
||||
if ( !file ) {
|
||||
return;
|
||||
}
|
||||
|
||||
org = origin;
|
||||
areaNum = PointReachableAreaNum( org, DefaultSearchBounds(), AREA_REACHABLE_FLY );
|
||||
PushPointIntoAreaNum( areaNum, org );
|
||||
curAreaNum = areaNum;
|
||||
|
||||
for ( i = 0; i < 100; i++ ) {
|
||||
|
||||
if ( !RouteToGoalArea( curAreaNum, org, goalAreaNum, TFL_WALK|TFL_FLY|TFL_AIR, travelTime, &reach ) ) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !reach ) {
|
||||
break;
|
||||
}
|
||||
|
||||
gameRenderWorld->DebugArrow( colorPurple, org, reach->start, 2 );
|
||||
DrawReachability( reach );
|
||||
|
||||
if ( reach->toAreaNum == goalAreaNum ) {
|
||||
break;
|
||||
}
|
||||
|
||||
curAreaNum = reach->toAreaNum;
|
||||
org = reach->end;
|
||||
}
|
||||
|
||||
if ( FlyPathToGoal( path, areaNum, origin, goalAreaNum, goalOrigin, TFL_WALK|TFL_FLY|TFL_AIR ) ) {
|
||||
gameRenderWorld->DebugArrow( colorBlue, origin, path.moveGoal, 2 );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::ShowWallEdges
|
||||
============
|
||||
*/
|
||||
void idAASLocal::ShowWallEdges( const idVec3 &origin ) const {
|
||||
int i, areaNum, numEdges, edges[1024];
|
||||
idVec3 start, end;
|
||||
idPlayer *player;
|
||||
|
||||
player = gameLocal.GetLocalPlayer();
|
||||
if ( !player ) {
|
||||
return;
|
||||
}
|
||||
|
||||
areaNum = PointReachableAreaNum( origin, DefaultSearchBounds(), (AREA_REACHABLE_WALK|AREA_REACHABLE_FLY) );
|
||||
numEdges = GetWallEdges( areaNum, idBounds( origin ).Expand( 256.0f ), TFL_WALK, edges, 1024 );
|
||||
for ( i = 0; i < numEdges; i++ ) {
|
||||
GetEdge( edges[i], start, end );
|
||||
gameRenderWorld->DebugLine( colorRed, start, end );
|
||||
gameRenderWorld->DrawText( va( "%d", edges[i] ), ( start + end ) * 0.5f, 0.1f, colorWhite, player->viewAxis );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::ShowHideArea
|
||||
============
|
||||
*/
|
||||
void idAASLocal::ShowHideArea( const idVec3 &origin, int targetAreaNum ) const {
|
||||
int areaNum, numObstacles;
|
||||
idVec3 target;
|
||||
aasGoal_t goal;
|
||||
aasObstacle_t obstacles[10];
|
||||
|
||||
areaNum = PointReachableAreaNum( origin, DefaultSearchBounds(), (AREA_REACHABLE_WALK|AREA_REACHABLE_FLY) );
|
||||
target = AreaCenter( targetAreaNum );
|
||||
|
||||
// consider the target an obstacle
|
||||
obstacles[0].absBounds = idBounds( target ).Expand( 16 );
|
||||
numObstacles = 1;
|
||||
|
||||
DrawCone( target, idVec3(0,0,1), 16.0f, colorYellow );
|
||||
|
||||
idAASFindCover findCover( target );
|
||||
if ( FindNearestGoal( goal, areaNum, origin, target, TFL_WALK|TFL_AIR, obstacles, numObstacles, findCover ) ) {
|
||||
DrawArea( goal.areaNum );
|
||||
ShowWalkPath( origin, goal.areaNum, goal.origin );
|
||||
DrawCone( goal.origin, idVec3(0,0,1), 16.0f, colorWhite );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::PullPlayer
|
||||
============
|
||||
*/
|
||||
bool idAASLocal::PullPlayer( const idVec3 &origin, int toAreaNum ) const {
|
||||
int areaNum;
|
||||
idVec3 areaCenter, dir, vel;
|
||||
idAngles delta;
|
||||
aasPath_t path;
|
||||
idPlayer *player;
|
||||
|
||||
player = gameLocal.GetLocalPlayer();
|
||||
if ( !player ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
idPhysics *physics = player->GetPhysics();
|
||||
if ( !physics ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( !toAreaNum ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
areaNum = PointReachableAreaNum( origin, DefaultSearchBounds(), (AREA_REACHABLE_WALK|AREA_REACHABLE_FLY) );
|
||||
areaCenter = AreaCenter( toAreaNum );
|
||||
if ( player->GetPhysics()->GetAbsBounds().Expand( 8 ).ContainsPoint( areaCenter ) ) {
|
||||
return false;
|
||||
}
|
||||
if ( WalkPathToGoal( path, areaNum, origin, toAreaNum, areaCenter, TFL_WALK|TFL_AIR ) ) {
|
||||
dir = path.moveGoal - origin;
|
||||
dir[2] *= 0.5f;
|
||||
dir.Normalize();
|
||||
delta = dir.ToAngles() - player->cmdAngles - player->GetDeltaViewAngles();
|
||||
delta.Normalize180();
|
||||
player->SetDeltaViewAngles( player->GetDeltaViewAngles() + delta * 0.1f );
|
||||
dir[2] = 0.0f;
|
||||
dir.Normalize();
|
||||
dir *= 100.0f;
|
||||
vel = physics->GetLinearVelocity();
|
||||
dir[2] = vel[2];
|
||||
physics->SetLinearVelocity( dir );
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::RandomPullPlayer
|
||||
============
|
||||
*/
|
||||
void idAASLocal::RandomPullPlayer( const idVec3 &origin ) const {
|
||||
int rnd, i, n;
|
||||
|
||||
if ( !PullPlayer( origin, aas_pullPlayer.GetInteger() ) ) {
|
||||
|
||||
rnd = gameLocal.random.RandomFloat() * file->GetNumAreas();
|
||||
|
||||
for ( i = 0; i < file->GetNumAreas(); i++ ) {
|
||||
n = (rnd + i) % file->GetNumAreas();
|
||||
if ( file->GetArea( n ).flags & (AREA_REACHABLE_WALK|AREA_REACHABLE_FLY) ) {
|
||||
aas_pullPlayer.SetInteger( n );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ShowWalkPath( origin, aas_pullPlayer.GetInteger(), AreaCenter( aas_pullPlayer.GetInteger() ) );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::ShowPushIntoArea
|
||||
============
|
||||
*/
|
||||
void idAASLocal::ShowPushIntoArea( const idVec3 &origin ) const {
|
||||
int areaNum;
|
||||
idVec3 target;
|
||||
|
||||
target = origin;
|
||||
areaNum = PointReachableAreaNum( target, DefaultSearchBounds(), (AREA_REACHABLE_WALK|AREA_REACHABLE_FLY) );
|
||||
PushPointIntoAreaNum( areaNum, target );
|
||||
gameRenderWorld->DebugArrow( colorGreen, origin, target, 1 );
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::DrawBounds
|
||||
============
|
||||
*/
|
||||
// HUMANHEAD nla
|
||||
void idAASLocal::DrawBounds( int areaNum ) const {
|
||||
const aasArea_t *area;
|
||||
const idBounds *bounds;
|
||||
const idVec3 *p0, *p1;
|
||||
|
||||
area = &file->GetArea(areaNum);
|
||||
if (area->numFaces < -1) { // Not a valid area
|
||||
return;
|
||||
}
|
||||
|
||||
bounds = &area->bounds;
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
p0 = &(*bounds)[i];
|
||||
p1 = &(*bounds)[(i + 1) % 2];
|
||||
for (int j = 0; j < 3; ++j) {
|
||||
DrawBoundsEdge(*p0, *p1, j, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::DrawBoundsEdge
|
||||
============
|
||||
*/
|
||||
// HUMANHEAD nla
|
||||
void idAASLocal::DrawBoundsEdge( const idVec3 &p0, const idVec3 &ip1, int keep, int draw ) const {
|
||||
idVec3 p1((*(keep == 0 ? &p0 : &ip1))[0],
|
||||
(*(keep == 1 ? &p0 : &ip1))[1],
|
||||
(*(keep == 2 ? &p0 : &ip1))[2]);
|
||||
|
||||
|
||||
if (draw) {
|
||||
gameRenderWorld->DebugLine( colorWhite, p0, p1);
|
||||
}
|
||||
else {
|
||||
for (int i = 1; i < 3; ++i) {
|
||||
DrawBoundsEdge(p0, p1, (keep + i) % 3, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::Test
|
||||
============
|
||||
*/
|
||||
void idAASLocal::Test( const idVec3 &origin ) {
|
||||
|
||||
if ( !file ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( aas_randomPullPlayer.GetBool() ) {
|
||||
RandomPullPlayer( origin );
|
||||
}
|
||||
if ( ( aas_pullPlayer.GetInteger() > 0 ) && ( aas_pullPlayer.GetInteger() < file->GetNumAreas() ) ) {
|
||||
ShowWalkPath( origin, aas_pullPlayer.GetInteger(), AreaCenter( aas_pullPlayer.GetInteger() ) );
|
||||
PullPlayer( origin, aas_pullPlayer.GetInteger() );
|
||||
}
|
||||
if ( ( aas_showPath.GetInteger() > 0 ) && ( aas_showPath.GetInteger() < file->GetNumAreas() ) ) {
|
||||
ShowWalkPath( origin, aas_showPath.GetInteger(), AreaCenter( aas_showPath.GetInteger() ) );
|
||||
}
|
||||
if ( ( aas_showFlyPath.GetInteger() > 0 ) && ( aas_showFlyPath.GetInteger() < file->GetNumAreas() ) ) {
|
||||
ShowFlyPath( origin, aas_showFlyPath.GetInteger(), AreaCenter( aas_showFlyPath.GetInteger() ) );
|
||||
}
|
||||
if ( ( aas_showHideArea.GetInteger() > 0 ) && ( aas_showHideArea.GetInteger() < file->GetNumAreas() ) ) {
|
||||
ShowHideArea( origin, aas_showHideArea.GetInteger() );
|
||||
}
|
||||
if ( ai_debugPath.GetBool() ) {
|
||||
int i, areaNum, numEdges, edges[1024];
|
||||
idVec3 start, end;
|
||||
if ( gameLocal.GetLocalPlayer() ) {
|
||||
areaNum = PointReachableAreaNum( origin, DefaultSearchBounds(), (AREA_REACHABLE_WALK|AREA_REACHABLE_FLY) );
|
||||
numEdges = GetWallEdges( areaNum, idBounds( origin ).Expand( 256.0f ), TFL_WALK, edges, 1024 );
|
||||
for ( i = 0; i < numEdges; i++ ) {
|
||||
GetEdge( edges[i], start, end );
|
||||
gameRenderWorld->DebugLine( colorWhite, start, end );
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( aas_showAreas.GetBool() ) {
|
||||
//HUMANHEAD nla
|
||||
if (aas_showAreas.GetInteger() > 2) {
|
||||
int counter;
|
||||
|
||||
for (counter = 0; counter < file->GetNumAreas(); counter++) {
|
||||
if (aas_showAreas.GetInteger() > 3) {
|
||||
DrawBounds(counter);
|
||||
}
|
||||
else {
|
||||
DrawArea(counter);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
ShowArea( origin );
|
||||
}
|
||||
}
|
||||
if ( aas_showWallEdges.GetBool() ) {
|
||||
ShowWallEdges( origin );
|
||||
}
|
||||
if ( aas_showPushIntoArea.GetBool() ) {
|
||||
ShowPushIntoArea( origin );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
// Copyright (C) 2004 Id Software, Inc.
|
||||
//
|
||||
|
||||
#ifndef __AAS_LOCAL_H__
|
||||
#define __AAS_LOCAL_H__
|
||||
|
||||
#include "AAS.h"
|
||||
#include "../Pvs.h"
|
||||
|
||||
|
||||
class idRoutingCache {
|
||||
friend class idAASLocal;
|
||||
|
||||
public:
|
||||
idRoutingCache( int size );
|
||||
~idRoutingCache( void );
|
||||
|
||||
int Size( void ) const;
|
||||
|
||||
private:
|
||||
int type; // portal or area cache
|
||||
int size; // size of cache
|
||||
int cluster; // cluster of the cache
|
||||
int areaNum; // area of the cache
|
||||
int travelFlags; // combinations of the travel flags
|
||||
idRoutingCache * next; // next in list
|
||||
idRoutingCache * prev; // previous in list
|
||||
idRoutingCache * time_next; // next in time based list
|
||||
idRoutingCache * time_prev; // previous in time based list
|
||||
unsigned short startTravelTime; // travel time to start with
|
||||
unsigned char * reachabilities; // reachabilities used for routing
|
||||
unsigned short * travelTimes; // travel time for every area
|
||||
};
|
||||
|
||||
|
||||
class idRoutingUpdate {
|
||||
friend class idAASLocal;
|
||||
|
||||
private:
|
||||
int cluster; // cluster number of this update
|
||||
int areaNum; // area number of this update
|
||||
unsigned short tmpTravelTime; // temporary travel time
|
||||
unsigned short * areaTravelTimes; // travel times within the area
|
||||
idVec3 start; // start point into area
|
||||
idRoutingUpdate * next; // next in list
|
||||
idRoutingUpdate * prev; // prev in list
|
||||
bool isInList; // true if the update is in the list
|
||||
};
|
||||
|
||||
|
||||
class idRoutingObstacle {
|
||||
friend class idAASLocal;
|
||||
idRoutingObstacle( void ) { }
|
||||
|
||||
private:
|
||||
idBounds bounds; // obstacle bounds
|
||||
idList<int> areas; // areas the bounds are in
|
||||
};
|
||||
|
||||
//HUMANHEAD nla
|
||||
// Helper class/data class for the near point functions
|
||||
class hhNearPoint {
|
||||
|
||||
public:
|
||||
hhNearPoint(const idVec3 &anAllyOrigin, const idVec3 &anOurOrigin, float desiredDist) :
|
||||
allyOrigin(anAllyOrigin), ourOrigin(anOurOrigin),
|
||||
desiredDistSq(desiredDist * desiredDist),
|
||||
bestBlocked(true), bestDot(0), bestPoint(vec3_origin) {
|
||||
|
||||
direction = anOurOrigin - anAllyOrigin;
|
||||
}
|
||||
|
||||
idVec3 getBestPoint(void) { return(bestPoint); }
|
||||
|
||||
// These really should be protected with accessors, but for the sake
|
||||
// of speed, will leave as public access
|
||||
public:
|
||||
idVec3 allyOrigin; // Point where ally is
|
||||
idVec3 ourOrigin; // Point where we are
|
||||
idVec3 direction; // Vector from ally to follower
|
||||
float desiredDistSq; // Min distance to be, squared
|
||||
float bestDistSq; // Current best point distance squared
|
||||
float bestBlocked; // Is the best so far blocked?
|
||||
float bestDot; // Current best point * direction
|
||||
idVec3 bestPoint; // Current best point
|
||||
|
||||
};
|
||||
|
||||
|
||||
//HUMANHEAD nla
|
||||
// Typedefs for return codes
|
||||
typedef enum {
|
||||
AREA_NO_VALID_POINTS, // No valid points were found
|
||||
AREA_MIXED, // Points were a mixture
|
||||
AREA_ALL_DESIRED // All points were desired points
|
||||
} findAreaType_t;
|
||||
|
||||
typedef enum {
|
||||
POINT_NOT_VALID = 0, // Point was on wrong side of origin
|
||||
POINT_VALID = 1, // Point was within desired distance
|
||||
POINT_DESIRED = 2 // Point was outside desired distance
|
||||
} findPointType_t;
|
||||
|
||||
//
|
||||
// HUMANHEAD jrm
|
||||
class hhPathApproach
|
||||
{
|
||||
public:
|
||||
hhPathApproach() {totalPathDistSqr = 0.0f; totalApproachDistSqr = 0.0f; minDistSqr = 0.0f; maxDistSqr = 0.0f;}
|
||||
float totalPathDistSqr; // Total path dist sqr
|
||||
float totalApproachDistSqr; // The total distance squared spent approaching the target
|
||||
float minDistSqr, maxDistSqr; // The closest and farthest we got from the target
|
||||
};
|
||||
|
||||
|
||||
class idAASLocal : public idAAS {
|
||||
public:
|
||||
idAASLocal( void );
|
||||
virtual ~idAASLocal( void );
|
||||
virtual bool Init( const idStr &mapName, unsigned int mapFileCRC );
|
||||
virtual void Shutdown( void );
|
||||
virtual void Stats( void ) const;
|
||||
virtual void Test( const idVec3 &origin );
|
||||
virtual const idAASSettings *GetSettings( void ) const;
|
||||
virtual int PointAreaNum( const idVec3 &origin ) const;
|
||||
virtual int PointReachableAreaNum( const idVec3 &origin, const idBounds &searchBounds, const int areaFlags ) const;
|
||||
virtual int BoundsReachableAreaNum( const idBounds &bounds, const int areaFlags ) const;
|
||||
virtual void PushPointIntoAreaNum( int areaNum, idVec3 &origin ) const;
|
||||
virtual idVec3 AreaCenter( int areaNum ) const;
|
||||
virtual int AreaFlags( int areaNum ) const;
|
||||
virtual int AreaTravelFlags( int areaNum ) const;
|
||||
virtual bool Trace( aasTrace_t &trace, const idVec3 &start, const idVec3 &end ) const;
|
||||
virtual const idPlane & GetPlane( int planeNum ) const;
|
||||
virtual int GetWallEdges( int areaNum, const idBounds &bounds, int travelFlags, int *edges, int maxEdges ) const;
|
||||
virtual void SortWallEdges( int *edges, int numEdges ) const;
|
||||
virtual void GetEdgeVertexNumbers( int edgeNum, int verts[2] ) const;
|
||||
virtual void GetEdge( int edgeNum, idVec3 &start, idVec3 &end ) const;
|
||||
virtual bool SetAreaState( const idBounds &bounds, const int areaContents, bool disabled );
|
||||
virtual aasHandle_t AddObstacle( const idBounds &bounds );
|
||||
virtual void RemoveObstacle( const aasHandle_t handle );
|
||||
virtual void RemoveAllObstacles( void );
|
||||
virtual int TravelTimeToGoalArea( int areaNum, const idVec3 &origin, int goalAreaNum, int travelFlags ) const;
|
||||
virtual bool RouteToGoalArea( int areaNum, const idVec3 origin, int goalAreaNum, int travelFlags, int &travelTime, idReachability **reach ) const;
|
||||
virtual bool WalkPathToGoal( aasPath_t &path, int areaNum, const idVec3 &origin, int goalAreaNum, const idVec3 &goalOrigin, int travelFlags ) const;
|
||||
virtual bool WalkPathValid( int areaNum, const idVec3 &origin, int goalAreaNum, const idVec3 &goalOrigin, int travelFlags, idVec3 &endPos, int &endAreaNum ) const;
|
||||
virtual bool FlyPathToGoal( aasPath_t &path, int areaNum, const idVec3 &origin, int goalAreaNum, const idVec3 &goalOrigin, int travelFlags ) const;
|
||||
virtual bool FlyPathValid( int areaNum, const idVec3 &origin, int goalAreaNum, const idVec3 &goalOrigin, int travelFlags, idVec3 &endPos, int &endAreaNum ) const;
|
||||
virtual void ShowWalkPath( const idVec3 &origin, int goalAreaNum, const idVec3 &goalOrigin ) const;
|
||||
virtual void ShowFlyPath( const idVec3 &origin, int goalAreaNum, const idVec3 &goalOrigin ) const;
|
||||
virtual bool FindNearestGoal( aasGoal_t &goal, int areaNum, const idVec3 origin, const idVec3 &target, int travelFlags, aasObstacle_t *obstacles, int numObstacles, idAASCallback &callback ) const;
|
||||
const char * GetName( void ) const { return file ? file->GetName() : NULL; }
|
||||
|
||||
private:
|
||||
idAASFile * file;
|
||||
idStr name;
|
||||
|
||||
private: // routing data
|
||||
idRoutingCache *** areaCacheIndex; // for each area in each cluster the travel times to all other areas in the cluster
|
||||
int areaCacheIndexSize; // number of area cache entries
|
||||
idRoutingCache ** portalCacheIndex; // for each area in the world the travel times from each portal
|
||||
int portalCacheIndexSize; // number of portal cache entries
|
||||
idRoutingUpdate * areaUpdate; // memory used to update the area routing cache
|
||||
idRoutingUpdate * portalUpdate; // memory used to update the portal routing cache
|
||||
unsigned short * goalAreaTravelTimes; // travel times to goal areas
|
||||
unsigned short * areaTravelTimes; // travel times through the areas
|
||||
int numAreaTravelTimes; // number of area travel times
|
||||
mutable idRoutingCache * cacheListStart; // start of list with cache sorted from oldest to newest
|
||||
mutable idRoutingCache * cacheListEnd; // end of list with cache sorted from oldest to newest
|
||||
mutable int totalCacheMemory; // total cache memory used
|
||||
idList<idRoutingObstacle *> obstacleList; // list with obstacles
|
||||
|
||||
private: // routing
|
||||
bool SetupRouting( void );
|
||||
void ShutdownRouting( void );
|
||||
unsigned short AreaTravelTime( int areaNum, const idVec3 &start, const idVec3 &end ) const;
|
||||
void CalculateAreaTravelTimes( void );
|
||||
void DeleteAreaTravelTimes( void );
|
||||
void SetupRoutingCache( void );
|
||||
void DeleteClusterCache( int clusterNum );
|
||||
void DeletePortalCache( void );
|
||||
void ShutdownRoutingCache( void );
|
||||
void RoutingStats( void ) const;
|
||||
void LinkCache( idRoutingCache *cache ) const;
|
||||
void UnlinkCache( idRoutingCache *cache ) const;
|
||||
void DeleteOldestCache( void ) const;
|
||||
idReachability * GetAreaReachability( int areaNum, int reachabilityNum ) const;
|
||||
int ClusterAreaNum( int clusterNum, int areaNum ) const;
|
||||
void UpdateAreaRoutingCache( idRoutingCache *areaCache ) const;
|
||||
idRoutingCache * GetAreaRoutingCache( int clusterNum, int areaNum, int travelFlags ) const;
|
||||
void UpdatePortalRoutingCache( idRoutingCache *portalCache ) const;
|
||||
idRoutingCache * GetPortalRoutingCache( int clusterNum, int areaNum, int travelFlags ) const;
|
||||
void RemoveRoutingCacheUsingArea( int areaNum );
|
||||
void DisableArea( int areaNum );
|
||||
void EnableArea( int areaNum );
|
||||
bool SetAreaState_r( int nodeNum, const idBounds &bounds, const int areaContents, bool disabled );
|
||||
void GetBoundsAreas_r( int nodeNum, const idBounds &bounds, idList<int> &areas ) const;
|
||||
void SetObstacleState( const idRoutingObstacle *obstacle, bool enable );
|
||||
|
||||
private: // pathing
|
||||
bool EdgeSplitPoint( idVec3 &split, int edgeNum, const idPlane &plane ) const;
|
||||
bool FloorEdgeSplitPoint( idVec3 &split, int areaNum, const idPlane &splitPlane, const idPlane &frontPlane, bool closest ) const;
|
||||
idVec3 SubSampleWalkPath( int areaNum, const idVec3 &origin, const idVec3 &start, const idVec3 &end, int travelFlags, int &endAreaNum ) const;
|
||||
idVec3 SubSampleFlyPath( int areaNum, const idVec3 &origin, const idVec3 &start, const idVec3 &end, int travelFlags, int &endAreaNum ) const;
|
||||
|
||||
private: // debug
|
||||
const idBounds & DefaultSearchBounds( void ) const;
|
||||
void DrawCone( const idVec3 &origin, const idVec3 &dir, float radius, const idVec4 &color ) const;
|
||||
void DrawArea( int areaNum ) const;
|
||||
// HUMANHEAD nla
|
||||
void DrawBounds( int areaNum ) const;
|
||||
void DrawBoundsEdge( const idVec3 &p0, const idVec3 &ip1, int keep, int draw ) const;
|
||||
// HUMANHEAD nla - Added color parameter
|
||||
void DrawFace( int faceNum, bool side, idVec4 *color = &colorRed ) const;
|
||||
void DrawEdge( int edgeNum, bool arrow, idVec4 *color = &colorRed ) const;
|
||||
void DrawReachability( const idReachability *reach ) const;
|
||||
void ShowArea( const idVec3 &origin ) const;
|
||||
void ShowWallEdges( const idVec3 &origin ) const;
|
||||
void ShowHideArea( const idVec3 &origin, int targerAreaNum ) const;
|
||||
bool PullPlayer( const idVec3 &origin, int toAreaNum ) const;
|
||||
void RandomPullPlayer( const idVec3 &origin ) const;
|
||||
void ShowPushIntoArea( const idVec3 &origin ) const;
|
||||
};
|
||||
|
||||
#endif /* !__AAS_LOCAL_H__ */
|
||||
@@ -0,0 +1,696 @@
|
||||
// Copyright (C) 2004 Id Software, Inc.
|
||||
//
|
||||
|
||||
#include "precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "AAS_local.h"
|
||||
|
||||
#define SUBSAMPLE_WALK_PATH 1
|
||||
#define SUBSAMPLE_FLY_PATH 0
|
||||
|
||||
const int maxWalkPathIterations = 10;
|
||||
const float maxWalkPathDistance = 500.0f;
|
||||
const float walkPathSampleDistance = 8.0f;
|
||||
|
||||
const int maxFlyPathIterations = 10;
|
||||
const float maxFlyPathDistance = 500.0f;
|
||||
const float flyPathSampleDistance = 8.0f;
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::EdgeSplitPoint
|
||||
|
||||
calculates split point of the edge with the plane
|
||||
returns true if the split point is between the edge vertices
|
||||
============
|
||||
*/
|
||||
bool idAASLocal::EdgeSplitPoint( idVec3 &split, int edgeNum, const idPlane &plane ) const {
|
||||
const aasEdge_t *edge;
|
||||
idVec3 v1, v2;
|
||||
float d1, d2;
|
||||
|
||||
edge = &file->GetEdge( edgeNum );
|
||||
v1 = file->GetVertex( edge->vertexNum[0] );
|
||||
v2 = file->GetVertex( edge->vertexNum[1] );
|
||||
d1 = v1 * plane.Normal() - plane.Dist();
|
||||
d2 = v2 * plane.Normal() - plane.Dist();
|
||||
|
||||
//if ( (d1 < CM_CLIP_EPSILON && d2 < CM_CLIP_EPSILON) || (d1 > -CM_CLIP_EPSILON && d2 > -CM_CLIP_EPSILON) ) {
|
||||
if ( FLOATSIGNBITSET( d1 ) == FLOATSIGNBITSET( d2 ) ) {
|
||||
return false;
|
||||
}
|
||||
split = v1 + (d1 / (d1 - d2)) * (v2 - v1);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::FloorEdgeSplitPoint
|
||||
|
||||
calculates either the closest or furthest point on the floor of the area which also lies on the pathPlane
|
||||
the point has to be on the front side of the frontPlane to be valid
|
||||
============
|
||||
*/
|
||||
bool idAASLocal::FloorEdgeSplitPoint( idVec3 &bestSplit, int areaNum, const idPlane &pathPlane, const idPlane &frontPlane, bool closest ) const {
|
||||
int i, j, faceNum, edgeNum;
|
||||
const aasArea_t *area;
|
||||
const aasFace_t *face;
|
||||
idVec3 split;
|
||||
float dist, bestDist;
|
||||
|
||||
if ( closest ) {
|
||||
bestDist = maxWalkPathDistance;
|
||||
} else {
|
||||
bestDist = -0.1f;
|
||||
}
|
||||
|
||||
area = &file->GetArea( areaNum );
|
||||
|
||||
for ( i = 0; i < area->numFaces; i++ ) {
|
||||
faceNum = file->GetFaceIndex( area->firstFace + i );
|
||||
face = &file->GetFace( abs(faceNum) );
|
||||
|
||||
if ( !(face->flags & FACE_FLOOR ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for ( j = 0; j < face->numEdges; j++ ) {
|
||||
edgeNum = file->GetEdgeIndex( face->firstEdge + j );
|
||||
|
||||
if ( !EdgeSplitPoint( split, abs( edgeNum ), pathPlane ) ) {
|
||||
continue;
|
||||
}
|
||||
dist = frontPlane.Distance( split );
|
||||
if ( closest ) {
|
||||
if ( dist >= -0.1f && dist < bestDist ) {
|
||||
bestDist = dist;
|
||||
bestSplit = split;
|
||||
}
|
||||
} else {
|
||||
if ( dist > bestDist ) {
|
||||
bestDist = dist;
|
||||
bestSplit = split;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( closest ) {
|
||||
return ( bestDist < maxWalkPathDistance );
|
||||
} else {
|
||||
return ( bestDist > -0.1f );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::WalkPathValid
|
||||
|
||||
returns true if one can walk in a straight line between origin and goalOrigin
|
||||
============
|
||||
*/
|
||||
bool idAASLocal::WalkPathValid( int areaNum, const idVec3 &origin, int goalAreaNum, const idVec3 &goalOrigin, int travelFlags, idVec3 &endPos, int &endAreaNum ) const {
|
||||
int curAreaNum, lastAreaNum, lastAreas[4], lastAreaIndex;
|
||||
idPlane pathPlane, frontPlane, farPlane;
|
||||
idReachability *reach;
|
||||
const aasArea_t *area;
|
||||
idVec3 p, dir;
|
||||
|
||||
if ( file == NULL ) {
|
||||
endPos = goalOrigin;
|
||||
endAreaNum = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
lastAreas[0] = lastAreas[1] = lastAreas[2] = lastAreas[3] = areaNum;
|
||||
lastAreaIndex = 0;
|
||||
|
||||
pathPlane.SetNormal( (goalOrigin - origin).Cross( file->GetSettings().gravityDir ) );
|
||||
pathPlane.Normalize();
|
||||
pathPlane.FitThroughPoint( origin );
|
||||
|
||||
frontPlane.SetNormal( goalOrigin - origin );
|
||||
frontPlane.Normalize();
|
||||
frontPlane.FitThroughPoint( origin );
|
||||
|
||||
farPlane.SetNormal( frontPlane.Normal() );
|
||||
farPlane.FitThroughPoint( goalOrigin );
|
||||
|
||||
curAreaNum = areaNum;
|
||||
lastAreaNum = curAreaNum;
|
||||
|
||||
while ( 1 ) {
|
||||
|
||||
// find the furthest floor face split point on the path
|
||||
if ( !FloorEdgeSplitPoint( endPos, curAreaNum, pathPlane, frontPlane, false ) ) {
|
||||
endPos = origin;
|
||||
}
|
||||
|
||||
// if we found a point near or further than the goal we're done
|
||||
if ( farPlane.Distance( endPos ) > -0.5f ) {
|
||||
break;
|
||||
}
|
||||
|
||||
// if we reached the goal area we're done
|
||||
if ( curAreaNum == goalAreaNum ) {
|
||||
break;
|
||||
}
|
||||
|
||||
frontPlane.SetDist( frontPlane.Normal() * endPos );
|
||||
|
||||
area = &file->GetArea( curAreaNum );
|
||||
|
||||
for ( reach = area->reach; reach; reach = reach->next ) {
|
||||
if ( reach->travelType != TFL_WALK ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// if the reachability goes back to a previous area
|
||||
if ( reach->toAreaNum == lastAreas[0] || reach->toAreaNum == lastAreas[1] ||
|
||||
reach->toAreaNum == lastAreas[2] || reach->toAreaNum == lastAreas[3] ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// if undesired travel flags are required to travel through the area
|
||||
if ( file->GetArea( reach->toAreaNum ).travelFlags & ~travelFlags ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// don't optimize through an area near a ledge
|
||||
if ( file->GetArea( reach->toAreaNum ).flags & AREA_LEDGE ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// find the closest floor face split point on the path
|
||||
if ( !FloorEdgeSplitPoint( p, reach->toAreaNum, pathPlane, frontPlane, true ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// direction parallel to gravity
|
||||
dir = ( file->GetSettings().gravityDir * endPos * file->GetSettings().gravityDir ) -
|
||||
( file->GetSettings().gravityDir * p * file->GetSettings().gravityDir );
|
||||
if ( dir.LengthSqr() > Square( file->GetSettings().maxStepHeight ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// direction orthogonal to gravity
|
||||
dir = endPos - p - dir;
|
||||
if ( dir.LengthSqr() > Square( 0.2f ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !reach ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
lastAreas[lastAreaIndex] = curAreaNum;
|
||||
lastAreaIndex = ( lastAreaIndex + 1 ) & 3;
|
||||
|
||||
curAreaNum = reach->toAreaNum;
|
||||
}
|
||||
|
||||
endAreaNum = curAreaNum;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::SubSampleWalkPath
|
||||
============
|
||||
*/
|
||||
idVec3 idAASLocal::SubSampleWalkPath( int areaNum, const idVec3 &origin, const idVec3 &start, const idVec3 &end, int travelFlags, int &endAreaNum ) const {
|
||||
int i, numSamples, curAreaNum;
|
||||
idVec3 dir, point, nextPoint, endPos;
|
||||
|
||||
dir = end - start;
|
||||
numSamples = (int) (dir.Length() / walkPathSampleDistance) + 1;
|
||||
|
||||
point = start;
|
||||
for ( i = 1; i < numSamples; i++ ) {
|
||||
nextPoint = start + dir * ((float) i / numSamples);
|
||||
if ( (point - nextPoint).LengthSqr() > Square( maxWalkPathDistance ) ) {
|
||||
return point;
|
||||
}
|
||||
if ( !idAASLocal::WalkPathValid( areaNum, origin, 0, nextPoint, travelFlags, endPos, curAreaNum ) ) {
|
||||
return point;
|
||||
}
|
||||
point = nextPoint;
|
||||
endAreaNum = curAreaNum;
|
||||
}
|
||||
return point;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::WalkPathToGoal
|
||||
|
||||
FIXME: don't stop optimizing on first failure ?
|
||||
============
|
||||
*/
|
||||
bool idAASLocal::WalkPathToGoal( aasPath_t &path, int areaNum, const idVec3 &origin, int goalAreaNum, const idVec3 &goalOrigin, int travelFlags ) const {
|
||||
int i, travelTime, curAreaNum, lastAreas[4], lastAreaIndex, endAreaNum;
|
||||
idReachability *reach;
|
||||
idVec3 endPos;
|
||||
|
||||
path.type = PATHTYPE_WALK;
|
||||
path.moveGoal = origin;
|
||||
path.moveAreaNum = areaNum;
|
||||
path.secondaryGoal = origin;
|
||||
path.reachability = NULL;
|
||||
|
||||
if ( file == NULL || areaNum == goalAreaNum ) {
|
||||
path.moveGoal = goalOrigin;
|
||||
return true;
|
||||
}
|
||||
|
||||
lastAreas[0] = lastAreas[1] = lastAreas[2] = lastAreas[3] = areaNum;
|
||||
lastAreaIndex = 0;
|
||||
|
||||
curAreaNum = areaNum;
|
||||
|
||||
for ( i = 0; i < maxWalkPathIterations; i++ ) {
|
||||
|
||||
if ( !idAASLocal::RouteToGoalArea( curAreaNum, path.moveGoal, goalAreaNum, travelFlags, travelTime, &reach ) ) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !reach ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// no need to check through the first area
|
||||
if ( areaNum != curAreaNum ) {
|
||||
// only optimize a limited distance ahead
|
||||
if ( (reach->start - origin).LengthSqr() > Square( maxWalkPathDistance ) ) {
|
||||
#if SUBSAMPLE_WALK_PATH
|
||||
path.moveGoal = SubSampleWalkPath( areaNum, origin, path.moveGoal, reach->start, travelFlags, path.moveAreaNum );
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( !idAASLocal::WalkPathValid( areaNum, origin, 0, reach->start, travelFlags, endPos, endAreaNum ) ) {
|
||||
#if SUBSAMPLE_WALK_PATH
|
||||
path.moveGoal = SubSampleWalkPath( areaNum, origin, path.moveGoal, reach->start, travelFlags, path.moveAreaNum );
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
path.moveGoal = reach->start;
|
||||
path.moveAreaNum = curAreaNum;
|
||||
|
||||
if ( reach->travelType != TFL_WALK ) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !idAASLocal::WalkPathValid( areaNum, origin, 0, reach->end, travelFlags, endPos, endAreaNum ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
path.moveGoal = reach->end;
|
||||
path.moveAreaNum = reach->toAreaNum;
|
||||
|
||||
if ( reach->toAreaNum == goalAreaNum ) {
|
||||
if ( !idAASLocal::WalkPathValid( areaNum, origin, 0, goalOrigin, travelFlags, endPos, endAreaNum ) ) {
|
||||
#if SUBSAMPLE_WALK_PATH
|
||||
path.moveGoal = SubSampleWalkPath( areaNum, origin, path.moveGoal, goalOrigin, travelFlags, path.moveAreaNum );
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
path.moveGoal = goalOrigin;
|
||||
path.moveAreaNum = goalAreaNum;
|
||||
return true;
|
||||
}
|
||||
|
||||
lastAreas[lastAreaIndex] = curAreaNum;
|
||||
lastAreaIndex = ( lastAreaIndex + 1 ) & 3;
|
||||
|
||||
curAreaNum = reach->toAreaNum;
|
||||
|
||||
if ( curAreaNum == lastAreas[0] || curAreaNum == lastAreas[1] ||
|
||||
curAreaNum == lastAreas[2] || curAreaNum == lastAreas[3] ) {
|
||||
common->Warning( "idAASLocal::WalkPathToGoal: local routing minimum going from area %d to area %d", areaNum, goalAreaNum );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !reach ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch( reach->travelType ) {
|
||||
case TFL_WALKOFFLEDGE:
|
||||
path.type = PATHTYPE_WALKOFFLEDGE;
|
||||
path.secondaryGoal = reach->end;
|
||||
path.reachability = reach;
|
||||
break;
|
||||
case TFL_BARRIERJUMP:
|
||||
path.type |= PATHTYPE_BARRIERJUMP;
|
||||
path.secondaryGoal = reach->end;
|
||||
path.reachability = reach;
|
||||
break;
|
||||
case TFL_JUMP:
|
||||
path.type |= PATHTYPE_JUMP;
|
||||
path.secondaryGoal = reach->end;
|
||||
path.reachability = reach;
|
||||
break;
|
||||
/* case TFL_FLY: // HUMANHEAD nla REmoved per AAS error
|
||||
path.type |= PATHTYPE_FLY;
|
||||
path.secondaryGoal = reach->end;
|
||||
path.reachability = reach;
|
||||
*/
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::FlyPathValid
|
||||
|
||||
returns true if one can fly in a straight line between origin and goalOrigin
|
||||
============
|
||||
*/
|
||||
bool idAASLocal::FlyPathValid( int areaNum, const idVec3 &origin, int goalAreaNum, const idVec3 &goalOrigin, int travelFlags, idVec3 &endPos, int &endAreaNum ) const {
|
||||
aasTrace_t trace;
|
||||
|
||||
if ( file == NULL ) {
|
||||
endPos = goalOrigin;
|
||||
endAreaNum = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
file->Trace( trace, origin, goalOrigin );
|
||||
|
||||
endPos = trace.endpos;
|
||||
endAreaNum = trace.lastAreaNum;
|
||||
|
||||
if ( trace.fraction >= 1.0f ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::SubSampleFlyPath
|
||||
============
|
||||
*/
|
||||
idVec3 idAASLocal::SubSampleFlyPath( int areaNum, const idVec3 &origin, const idVec3 &start, const idVec3 &end, int travelFlags, int &endAreaNum ) const {
|
||||
int i, numSamples, curAreaNum;
|
||||
idVec3 dir, point, nextPoint, endPos;
|
||||
|
||||
dir = end - start;
|
||||
numSamples = (int) (dir.Length() / flyPathSampleDistance) + 1;
|
||||
|
||||
point = start;
|
||||
for ( i = 1; i < numSamples; i++ ) {
|
||||
nextPoint = start + dir * ((float) i / numSamples);
|
||||
if ( (point - nextPoint).LengthSqr() > Square( maxFlyPathDistance ) ) {
|
||||
return point;
|
||||
}
|
||||
if ( !idAASLocal::FlyPathValid( areaNum, origin, 0, nextPoint, travelFlags, endPos, curAreaNum ) ) {
|
||||
return point;
|
||||
}
|
||||
point = nextPoint;
|
||||
endAreaNum = curAreaNum;
|
||||
}
|
||||
return point;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::FlyPathToGoal
|
||||
|
||||
FIXME: don't stop optimizing on first failure ?
|
||||
============
|
||||
*/
|
||||
bool idAASLocal::FlyPathToGoal( aasPath_t &path, int areaNum, const idVec3 &origin, int goalAreaNum, const idVec3 &goalOrigin, int travelFlags ) const {
|
||||
int i, travelTime, curAreaNum, lastAreas[4], lastAreaIndex, endAreaNum;
|
||||
idReachability *reach;
|
||||
idVec3 endPos;
|
||||
|
||||
path.type = PATHTYPE_WALK;
|
||||
path.moveGoal = origin;
|
||||
path.moveAreaNum = areaNum;
|
||||
path.secondaryGoal = origin;
|
||||
path.reachability = NULL;
|
||||
|
||||
if ( file == NULL || areaNum == goalAreaNum ) {
|
||||
path.moveGoal = goalOrigin;
|
||||
return true;
|
||||
}
|
||||
|
||||
lastAreas[0] = lastAreas[1] = lastAreas[2] = lastAreas[3] = areaNum;
|
||||
lastAreaIndex = 0;
|
||||
|
||||
curAreaNum = areaNum;
|
||||
|
||||
for ( i = 0; i < maxFlyPathIterations; i++ ) {
|
||||
|
||||
if ( !idAASLocal::RouteToGoalArea( curAreaNum, path.moveGoal, goalAreaNum, travelFlags, travelTime, &reach ) ) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !reach ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// no need to check through the first area
|
||||
if ( areaNum != curAreaNum ) {
|
||||
if ( (reach->start - origin).LengthSqr() > Square( maxFlyPathDistance ) ) {
|
||||
#if SUBSAMPLE_FLY_PATH
|
||||
path.moveGoal = SubSampleFlyPath( areaNum, origin, path.moveGoal, reach->start, travelFlags, path.moveAreaNum );
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( !idAASLocal::FlyPathValid( areaNum, origin, 0, reach->start, travelFlags, endPos, endAreaNum ) ) {
|
||||
#if SUBSAMPLE_FLY_PATH
|
||||
path.moveGoal = SubSampleFlyPath( areaNum, origin, path.moveGoal, reach->start, travelFlags, path.moveAreaNum );
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
path.moveGoal = reach->start;
|
||||
path.moveAreaNum = curAreaNum;
|
||||
|
||||
if ( !idAASLocal::FlyPathValid( areaNum, origin, 0, reach->end, travelFlags, endPos, endAreaNum ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
path.moveGoal = reach->end;
|
||||
path.moveAreaNum = reach->toAreaNum;
|
||||
|
||||
if ( reach->toAreaNum == goalAreaNum ) {
|
||||
if ( !idAASLocal::FlyPathValid( areaNum, origin, 0, goalOrigin, travelFlags, endPos, endAreaNum ) ) {
|
||||
#if SUBSAMPLE_FLY_PATH
|
||||
path.moveGoal = SubSampleFlyPath( areaNum, origin, path.moveGoal, goalOrigin, travelFlags, path.moveAreaNum );
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
path.moveGoal = goalOrigin;
|
||||
path.moveAreaNum = goalAreaNum;
|
||||
return true;
|
||||
}
|
||||
|
||||
lastAreas[lastAreaIndex] = curAreaNum;
|
||||
lastAreaIndex = ( lastAreaIndex + 1 ) & 3;
|
||||
|
||||
curAreaNum = reach->toAreaNum;
|
||||
|
||||
if ( curAreaNum == lastAreas[0] || curAreaNum == lastAreas[1] ||
|
||||
curAreaNum == lastAreas[2] || curAreaNum == lastAreas[3] ) {
|
||||
common->Warning( "idAASLocal::FlyPathToGoal: local routing minimum going from area %d to area %d", areaNum, goalAreaNum );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !reach ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef struct wallEdge_s {
|
||||
int edgeNum;
|
||||
int verts[2];
|
||||
struct wallEdge_s * next;
|
||||
} wallEdge_t;
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::SortWallEdges
|
||||
============
|
||||
*/
|
||||
void idAASLocal::SortWallEdges( int *edges, int numEdges ) const {
|
||||
int i, j, k, numSequences;
|
||||
wallEdge_t **sequenceFirst, **sequenceLast, *wallEdges, *wallEdge;
|
||||
|
||||
wallEdges = (wallEdge_t *) _alloca16( numEdges * sizeof( wallEdge_t ) );
|
||||
sequenceFirst = (wallEdge_t **)_alloca16( numEdges * sizeof( wallEdge_t * ) );
|
||||
sequenceLast = (wallEdge_t **)_alloca16( numEdges * sizeof( wallEdge_t * ) );
|
||||
|
||||
for ( i = 0; i < numEdges; i++ ) {
|
||||
wallEdges[i].edgeNum = edges[i];
|
||||
GetEdgeVertexNumbers( edges[i], wallEdges[i].verts );
|
||||
wallEdges[i].next = NULL;
|
||||
sequenceFirst[i] = &wallEdges[i];
|
||||
sequenceLast[i] = &wallEdges[i];
|
||||
}
|
||||
numSequences = numEdges;
|
||||
|
||||
for ( i = 0; i < numSequences; i++ ) {
|
||||
for ( j = i+1; j < numSequences; j++ ) {
|
||||
if ( sequenceFirst[i]->verts[0] == sequenceLast[j]->verts[1] ) {
|
||||
sequenceLast[j]->next = sequenceFirst[i];
|
||||
sequenceFirst[i] = sequenceFirst[j];
|
||||
break;
|
||||
}
|
||||
if ( sequenceLast[i]->verts[1] == sequenceFirst[j]->verts[0] ) {
|
||||
sequenceLast[i]->next = sequenceFirst[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( j < numSequences ) {
|
||||
numSequences--;
|
||||
for ( k = j; k < numSequences; k++ ) {
|
||||
sequenceFirst[k] = sequenceFirst[k+1];
|
||||
sequenceLast[k] = sequenceLast[k+1];
|
||||
}
|
||||
i = -1;
|
||||
}
|
||||
}
|
||||
|
||||
k = 0;
|
||||
for ( i = 0; i < numSequences; i++ ) {
|
||||
for ( wallEdge = sequenceFirst[i]; wallEdge; wallEdge = wallEdge->next ) {
|
||||
edges[k++] = wallEdge->edgeNum;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idAASLocal::GetWallEdges
|
||||
============
|
||||
*/
|
||||
int idAASLocal::GetWallEdges( int areaNum, const idBounds &bounds, int travelFlags, int *edges, int maxEdges ) const {
|
||||
int i, j, k, l, face1Num, face2Num, edge1Num, edge2Num, numEdges, absEdge1Num;
|
||||
int *areaQueue, curArea, queueStart, queueEnd;
|
||||
byte *areasVisited;
|
||||
const aasArea_t *area;
|
||||
const aasFace_t *face1, *face2;
|
||||
idReachability *reach;
|
||||
|
||||
if ( !file ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
numEdges = 0;
|
||||
|
||||
areasVisited = (byte *) _alloca16( file->GetNumAreas() );
|
||||
memset( areasVisited, 0, file->GetNumAreas() * sizeof( byte ) );
|
||||
areaQueue = (int *) _alloca16( file->GetNumAreas() * sizeof( int ) );
|
||||
|
||||
queueStart = -1;
|
||||
queueEnd = 0;
|
||||
areaQueue[0] = areaNum;
|
||||
areasVisited[areaNum] = true;
|
||||
|
||||
for ( curArea = areaNum; queueStart < queueEnd; curArea = areaQueue[++queueStart] ) {
|
||||
|
||||
area = &file->GetArea( curArea );
|
||||
|
||||
for ( i = 0; i < area->numFaces; i++ ) {
|
||||
face1Num = file->GetFaceIndex( area->firstFace + i );
|
||||
face1 = &file->GetFace( abs(face1Num) );
|
||||
|
||||
if ( !(face1->flags & FACE_FLOOR ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for ( j = 0; j < face1->numEdges; j++ ) {
|
||||
edge1Num = file->GetEdgeIndex( face1->firstEdge + j );
|
||||
absEdge1Num = abs( edge1Num );
|
||||
|
||||
// test if the edge is shared by another floor face of this area
|
||||
for ( k = 0; k < area->numFaces; k++ ) {
|
||||
if ( k == i ) {
|
||||
continue;
|
||||
}
|
||||
face2Num = file->GetFaceIndex( area->firstFace + k );
|
||||
face2 = &file->GetFace( abs(face2Num) );
|
||||
|
||||
if ( !(face2->flags & FACE_FLOOR ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for ( l = 0; l < face2->numEdges; l++ ) {
|
||||
edge2Num = abs( file->GetEdgeIndex( face2->firstEdge + l ) );
|
||||
if ( edge2Num == absEdge1Num ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( l < face2->numEdges ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( k < area->numFaces ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// test if the edge is used by a reachability
|
||||
for ( reach = area->reach; reach; reach = reach->next ) {
|
||||
if ( reach->travelType & travelFlags ) {
|
||||
if ( reach->edgeNum == absEdge1Num ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( reach ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// test if the edge is already in the list
|
||||
for ( k = 0; k < numEdges; k++ ) {
|
||||
if ( edge1Num == edges[k] ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( k < numEdges ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// add the edge to the list
|
||||
edges[numEdges++] = edge1Num;
|
||||
if ( numEdges >= maxEdges ) {
|
||||
return numEdges;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add new areas to the queue
|
||||
for ( reach = area->reach; reach; reach = reach->next ) {
|
||||
if ( reach->travelType & travelFlags ) {
|
||||
// if the area the reachability leads to hasn't been visited yet and the area bounds touch the search bounds
|
||||
if ( !areasVisited[reach->toAreaNum] && bounds.IntersectsBounds( file->GetArea( reach->toAreaNum ).bounds ) ) {
|
||||
areaQueue[queueEnd++] = reach->toAreaNum;
|
||||
areasVisited[reach->toAreaNum] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return numEdges;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,781 @@
|
||||
// Copyright (C) 2004 Id Software, Inc.
|
||||
//
|
||||
|
||||
#ifndef __AI_H__
|
||||
#define __AI_H__
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
idAI
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
const float SQUARE_ROOT_OF_2 = 1.414213562f;
|
||||
const float AI_TURN_PREDICTION = 0.2f;
|
||||
const float AI_TURN_SCALE = 60.0f;
|
||||
const float AI_SEEK_PREDICTION = 0.3f;
|
||||
const float AI_FLY_DAMPENING = 0.01f; // HUMANHEAD JRM: Was 0.06
|
||||
const float AI_HEARING_RANGE = 1024.0f; // HUNANHEAD JRM: Reduced from 2048
|
||||
const int DEFAULT_FLY_OFFSET = 68;
|
||||
|
||||
#define ATTACK_IGNORE 0
|
||||
#define ATTACK_ON_DAMAGE 1
|
||||
#define ATTACK_ON_ACTIVATE 2
|
||||
#define ATTACK_ON_SIGHT 4
|
||||
#define ATTACK_ON_TOUCH 8 // HUMANHEAD JRM
|
||||
|
||||
// defined in script/ai_base.script. please keep them up to date.
|
||||
typedef enum {
|
||||
MOVETYPE_DEAD,
|
||||
MOVETYPE_ANIM,
|
||||
MOVETYPE_SLIDE,
|
||||
MOVETYPE_FLY,
|
||||
MOVETYPE_STATIC,
|
||||
NUM_MOVETYPES
|
||||
} moveType_t;
|
||||
|
||||
typedef enum {
|
||||
MOVE_NONE,
|
||||
MOVE_FACE_ENEMY,
|
||||
MOVE_FACE_ENTITY,
|
||||
|
||||
// commands < NUM_NONMOVING_COMMANDS don't cause a change in position
|
||||
NUM_NONMOVING_COMMANDS,
|
||||
|
||||
MOVE_TO_ENEMY = NUM_NONMOVING_COMMANDS,
|
||||
MOVE_TO_ENEMYHEIGHT,
|
||||
MOVE_TO_ENTITY,
|
||||
MOVE_OUT_OF_RANGE,
|
||||
MOVE_TO_ATTACK_POSITION,
|
||||
MOVE_TO_COVER,
|
||||
MOVE_TO_POSITION,
|
||||
MOVE_TO_POSITION_DIRECT,
|
||||
MOVE_SLIDE_TO_POSITION,
|
||||
MOVE_WANDER,
|
||||
NUM_MOVE_COMMANDS
|
||||
} moveCommand_t;
|
||||
|
||||
typedef enum {
|
||||
TALK_NEVER,
|
||||
TALK_DEAD,
|
||||
TALK_OK,
|
||||
TALK_BUSY,
|
||||
NUM_TALK_STATES
|
||||
} talkState_t;
|
||||
|
||||
//
|
||||
// status results from move commands
|
||||
// make sure to change script/doom_defs.script if you add any, or change their order
|
||||
//
|
||||
typedef enum {
|
||||
MOVE_STATUS_DONE,
|
||||
MOVE_STATUS_MOVING,
|
||||
MOVE_STATUS_WAITING,
|
||||
MOVE_STATUS_DEST_NOT_FOUND,
|
||||
MOVE_STATUS_DEST_UNREACHABLE,
|
||||
MOVE_STATUS_BLOCKED_BY_WALL,
|
||||
MOVE_STATUS_BLOCKED_BY_OBJECT,
|
||||
MOVE_STATUS_BLOCKED_BY_ENEMY,
|
||||
MOVE_STATUS_BLOCKED_BY_MONSTER
|
||||
} moveStatus_t;
|
||||
|
||||
#define DI_NODIR -1
|
||||
|
||||
// obstacle avoidance
|
||||
typedef struct obstaclePath_s {
|
||||
idVec3 seekPos; // seek position avoiding obstacles
|
||||
idEntity * firstObstacle; // if != NULL the first obstacle along the path
|
||||
idVec3 startPosOutsideObstacles; // start position outside obstacles
|
||||
idEntity * startPosObstacle; // if != NULL the obstacle containing the start position
|
||||
idVec3 seekPosOutsideObstacles; // seek position outside obstacles
|
||||
idEntity * seekPosObstacle; // if != NULL the obstacle containing the seek position
|
||||
} obstaclePath_t;
|
||||
|
||||
// path prediction
|
||||
typedef enum {
|
||||
SE_BLOCKED = BIT(0),
|
||||
SE_ENTER_LEDGE_AREA = BIT(1),
|
||||
SE_ENTER_OBSTACLE = BIT(2),
|
||||
SE_FALL = BIT(3),
|
||||
SE_LAND = BIT(4)
|
||||
} stopEvent_t;
|
||||
|
||||
typedef struct predictedPath_s {
|
||||
idVec3 endPos; // final position
|
||||
idVec3 endVelocity; // velocity at end position
|
||||
idVec3 endNormal; // normal of blocking surface
|
||||
int endTime; // time predicted
|
||||
int endEvent; // event that stopped the prediction
|
||||
const idEntity * blockingEntity; // entity that blocks the movement
|
||||
} predictedPath_t;
|
||||
|
||||
//
|
||||
// events
|
||||
//
|
||||
extern const idEventDef AI_BeginAttack;
|
||||
extern const idEventDef AI_EndAttack;
|
||||
extern const idEventDef AI_MuzzleFlash;
|
||||
extern const idEventDef AI_CreateMissile;
|
||||
extern const idEventDef AI_AttackMissile;
|
||||
extern const idEventDef AI_FireMissileAtTarget;
|
||||
extern const idEventDef AI_AttackMelee;
|
||||
extern const idEventDef AI_DirectDamage;
|
||||
extern const idEventDef AI_JumpFrame;
|
||||
extern const idEventDef AI_EnableClip;
|
||||
extern const idEventDef AI_DisableClip;
|
||||
extern const idEventDef AI_EnableGravity;
|
||||
extern const idEventDef AI_DisableGravity;
|
||||
extern const idEventDef AI_TriggerParticles;
|
||||
extern const idEventDef AI_RandomPath;
|
||||
// HUMANHEAD
|
||||
extern const idEventDef AI_SetState;
|
||||
extern const idEventDef AI_FindEnemy;
|
||||
extern const idEventDef AI_Kill;
|
||||
extern const idEventDef AI_FindEnemyAI;
|
||||
extern const idEventDef AI_LookAtEntity;
|
||||
// HUMANHEAD END
|
||||
|
||||
class idPathCorner;
|
||||
|
||||
typedef struct particleEmitter_s {
|
||||
particleEmitter_s() {
|
||||
particle = NULL;
|
||||
time = 0;
|
||||
joint = INVALID_JOINT;
|
||||
};
|
||||
const idDeclParticle *particle;
|
||||
int time;
|
||||
jointHandle_t joint;
|
||||
} particleEmitter_t;
|
||||
|
||||
class idMoveState {
|
||||
public:
|
||||
idMoveState();
|
||||
|
||||
void Save( idSaveGame *savefile ) const;
|
||||
void Restore( idRestoreGame *savefile );
|
||||
|
||||
moveType_t moveType;
|
||||
moveCommand_t moveCommand;
|
||||
moveStatus_t moveStatus;
|
||||
idVec3 moveDest;
|
||||
idVec3 moveDir; // used for wandering and slide moves
|
||||
idEntityPtr<idEntity> goalEntity;
|
||||
idVec3 goalEntityOrigin; // move to entity uses this to avoid checking the floor position every frame
|
||||
int toAreaNum;
|
||||
int startTime;
|
||||
int duration;
|
||||
float speed; // only used by flying creatures
|
||||
float range;
|
||||
float wanderYaw;
|
||||
int nextWanderTime;
|
||||
int blockTime;
|
||||
idEntityPtr<idEntity> obstacle;
|
||||
idVec3 lastMoveOrigin;
|
||||
int lastMoveTime;
|
||||
int anim;
|
||||
bool bEnemyBlocks; // HUMANHEAD mdl: Added flag for when we want the enemy to be treated as an obstacle
|
||||
};
|
||||
|
||||
class idAASFindCover : public idAASCallback {
|
||||
public:
|
||||
idAASFindCover( const idVec3 &hideFromPos );
|
||||
~idAASFindCover();
|
||||
|
||||
virtual bool TestArea( const idAAS *aas, int areaNum );
|
||||
|
||||
private:
|
||||
pvsHandle_t hidePVS;
|
||||
int PVSAreas[ idEntity::MAX_PVS_AREAS ];
|
||||
};
|
||||
|
||||
class idAASFindAreaOutOfRange : public idAASCallback {
|
||||
public:
|
||||
idAASFindAreaOutOfRange( const idVec3 &targetPos, float maxDist );
|
||||
|
||||
virtual bool TestArea( const idAAS *aas, int areaNum );
|
||||
|
||||
private:
|
||||
idVec3 targetPos;
|
||||
float maxDistSqr;
|
||||
};
|
||||
|
||||
class idAASFindAttackPosition : public idAASCallback {
|
||||
public:
|
||||
idAASFindAttackPosition( const idAI *self, const idMat3 &gravityAxis, idEntity *target, const idVec3 &targetPos, const idVec3 &fireOffset );
|
||||
~idAASFindAttackPosition();
|
||||
|
||||
virtual bool TestArea( const idAAS *aas, int areaNum );
|
||||
|
||||
private:
|
||||
const idAI *self;
|
||||
idEntity *target;
|
||||
idBounds excludeBounds;
|
||||
idVec3 targetPos;
|
||||
idVec3 fireOffset;
|
||||
idMat3 gravityAxis;
|
||||
pvsHandle_t targetPVS;
|
||||
int PVSAreas[ idEntity::MAX_PVS_AREAS ];
|
||||
};
|
||||
|
||||
//HUMANHEAD mdc - added to allow for multiple projectile types for a creature
|
||||
// note: this struct just contains all the precomputed info used for projectiles
|
||||
//each time you switch projectile types, this info just gets copied to the variables in idAI
|
||||
typedef struct projectileInfo_s {
|
||||
projectileInfo_s() {
|
||||
projectileDef = NULL;
|
||||
projectileClipModel = NULL;
|
||||
projectileRadius = 0.f;
|
||||
projectileSpeed = 0.f;
|
||||
};
|
||||
const idDict * projectileDef;
|
||||
mutable idClipModel *projectileClipModel;
|
||||
float projectileRadius;
|
||||
float projectileSpeed;
|
||||
idVec3 projectileVelocity;
|
||||
idVec3 projectileGravity;
|
||||
} projectileInfo_t;
|
||||
//HUMANHEAD END
|
||||
|
||||
class idAI : public idActor {
|
||||
public:
|
||||
CLASS_PROTOTYPE( idAI );
|
||||
|
||||
idAI();
|
||||
~idAI();
|
||||
|
||||
void Save( idSaveGame *savefile ) const;
|
||||
void Restore( idRestoreGame *savefile );
|
||||
|
||||
// HUMANHEAD START jrm
|
||||
idAAS* GetAAS(void) {return aas;}
|
||||
bool IsFlying(void) {return move.moveType == MOVETYPE_FLY;}
|
||||
idVec3 GetLastEnemyPos(void) {return lastVisibleEnemyPos;}
|
||||
// HUMANHEAD END
|
||||
// HUMANHEAD nla - Moved from AI_navigate
|
||||
int GetDestEnemyNum( void ) { return( enemyEntityNum ); };
|
||||
// HUMANHEAD jrm
|
||||
int GetMoveType(void) {return move.moveType;}
|
||||
idVec3 GetMoveDest(void) {return move.moveDest;}
|
||||
hhAIVehicleInterface* GetVehicleInterfaceLocal() { return &vehicleInterfaceLocal; }
|
||||
virtual const char * GetJointForFrameCommand( const char *cmd ) { return( va( "%s", cmd ) ); }
|
||||
// HUMANHEAD end
|
||||
|
||||
void Spawn( void );
|
||||
void HeardSound( idEntity *ent, const char *action );
|
||||
idActor *GetEnemy( void ) const;
|
||||
void TalkTo( idActor *actor );
|
||||
talkState_t GetTalkState( void ) const;
|
||||
|
||||
// HUMANHEAD JRM - changed to entity - not just actor
|
||||
virtual
|
||||
bool GetAimDir( const idVec3 &firePos, idEntity *aimAtEnt, const idEntity *ignore, idVec3 &aimDir ) const;
|
||||
|
||||
void TouchedByFlashlight( idActor *flashlight_owner );
|
||||
|
||||
// Outputs a list of all monsters to the console.
|
||||
static void List_f( const idCmdArgs &args );
|
||||
|
||||
// Finds a path around dynamic obstacles.
|
||||
static bool FindPathAroundObstacles( const idPhysics *physics, const idAAS *aas, const idEntity *ignore, const idVec3 &startPos, const idVec3 &seekPos, obstaclePath_t &path );
|
||||
// Frees any nodes used for the dynamic obstacle avoidance.
|
||||
static void FreeObstacleAvoidanceNodes( void );
|
||||
// Predicts movement, returns true if a stop event was triggered.
|
||||
static bool PredictPath( const idEntity *ent, const idAAS *aas, const idVec3 &start, const idVec3 &velocity, int totalTime, int frameTime, int stopEvent, predictedPath_t &path );
|
||||
// Return true if the trajectory of the clip model is collision free.
|
||||
static bool TestTrajectory( const idVec3 &start, const idVec3 &end, float zVel, float gravity, float time, float max_height, const idClipModel *clip, int clipmask, const idEntity *ignore, const idEntity *targetEntity, int drawtime );
|
||||
// Finds the best collision free trajectory for a clip model.
|
||||
static bool PredictTrajectory( const idVec3 &firePos, const idVec3 &target, float projectileSpeed, const idVec3 &projGravity, const idClipModel *clip, int clipmask, float max_height, const idEntity *ignore, const idEntity *targetEntity, int drawtime, idVec3 &aimDir );
|
||||
|
||||
protected:
|
||||
// navigation
|
||||
idAAS * aas;
|
||||
int travelFlags;
|
||||
|
||||
idMoveState move;
|
||||
idMoveState savedMove;
|
||||
|
||||
float kickForce;
|
||||
bool ignore_obstacles;
|
||||
float blockedRadius;
|
||||
int blockedMoveTime;
|
||||
int blockedAttackTime;
|
||||
|
||||
// turning
|
||||
float ideal_yaw;
|
||||
float current_yaw;
|
||||
float turnRate;
|
||||
float turnVel;
|
||||
float anim_turn_yaw;
|
||||
float anim_turn_amount;
|
||||
float anim_turn_angles;
|
||||
|
||||
// physics
|
||||
// HUMANHEAD: aob
|
||||
hhPhysics_AI physicsObj;
|
||||
// HUMANHEAD END
|
||||
|
||||
// flying
|
||||
jointHandle_t flyTiltJoint;
|
||||
float fly_speed;
|
||||
float fly_bob_strength;
|
||||
float fly_bob_vert;
|
||||
float fly_bob_horz;
|
||||
int fly_offset; // prefered offset from player's view
|
||||
float fly_seek_scale;
|
||||
float fly_roll_scale;
|
||||
float fly_roll_max;
|
||||
float fly_roll;
|
||||
float fly_pitch_scale;
|
||||
float fly_pitch_max;
|
||||
float fly_pitch;
|
||||
|
||||
bool allowMove; // disables any animation movement
|
||||
bool allowHiddenMovement; // allows character to still move around while hidden
|
||||
bool disableGravity; // disables gravity and allows vertical movement by the animation
|
||||
bool af_push_moveables; // allow the articulated figure to push moveable objects
|
||||
|
||||
// weapon/attack vars
|
||||
bool lastHitCheckResult;
|
||||
int lastHitCheckTime;
|
||||
int lastAttackTime;
|
||||
float melee_range;
|
||||
float projectile_height_to_distance_ratio; // calculates the maximum height a projectile can be thrown
|
||||
idList<idVec3> missileLaunchOffset;
|
||||
|
||||
//HUMANHEAD mdc - added for multiple projectile support
|
||||
mutable idList<projectileInfo_t> projectileInfos; //list of all precomputed info for the projectiles this AI uses
|
||||
int projectileDefaultDefIndex; //default projectile index (if == -1, means we don't use the projectileInfos at all)
|
||||
//HUMANHEAD END
|
||||
|
||||
const idDict * projectileDef;
|
||||
mutable idClipModel *projectileClipModel;
|
||||
float projectileRadius;
|
||||
float projectileSpeed;
|
||||
idVec3 projectileVelocity;
|
||||
idVec3 projectileGravity;
|
||||
idEntityPtr<idProjectile> projectile;
|
||||
idStr attack;
|
||||
|
||||
// chatter/talking
|
||||
const idSoundShader *chat_snd;
|
||||
int chat_min;
|
||||
int chat_max;
|
||||
int chat_time;
|
||||
talkState_t talk_state;
|
||||
idEntityPtr<idActor> talkTarget;
|
||||
|
||||
// cinematics
|
||||
int num_cinematics;
|
||||
int current_cinematic;
|
||||
|
||||
bool allowJointMod;
|
||||
idEntityPtr<idEntity> focusEntity;
|
||||
idVec3 currentFocusPos;
|
||||
int focusTime;
|
||||
int alignHeadTime;
|
||||
int forceAlignHeadTime;
|
||||
idAngles eyeAng;
|
||||
idAngles lookAng;
|
||||
idAngles destLookAng;
|
||||
idAngles lookMin;
|
||||
idAngles lookMax;
|
||||
idList<jointHandle_t> lookJoints;
|
||||
idList<idAngles> lookJointAngles;
|
||||
// HUMANHEAD pdm: Added support for look joints in head entities
|
||||
idList<jointHandle_t> headLookJoints;
|
||||
idList<idAngles> headLookJointAngles;
|
||||
// HUMANHEAD END
|
||||
float eyeVerticalOffset;
|
||||
float eyeHorizontalOffset;
|
||||
float eyeFocusRate;
|
||||
float headFocusRate;
|
||||
int focusAlignTime;
|
||||
|
||||
// special fx
|
||||
float shrivel_rate;
|
||||
int shrivel_start;
|
||||
|
||||
bool restartParticles; // should smoke emissions restart
|
||||
bool useBoneAxis; // use the bone vs the model axis
|
||||
idList<particleEmitter_t> particles; // particle data
|
||||
|
||||
renderLight_t worldMuzzleFlash; // positioned on world weapon bone
|
||||
int worldMuzzleFlashHandle;
|
||||
jointHandle_t flashJointWorld;
|
||||
int muzzleFlashEnd;
|
||||
int flashTime;
|
||||
|
||||
// joint controllers
|
||||
idAngles eyeMin;
|
||||
idAngles eyeMax;
|
||||
jointHandle_t focusJoint;
|
||||
jointHandle_t orientationJoint;
|
||||
|
||||
// enemy variables
|
||||
idEntityPtr<idActor> enemy;
|
||||
idVec3 lastVisibleEnemyPos;
|
||||
idVec3 lastVisibleEnemyEyeOffset;
|
||||
idVec3 lastVisibleReachableEnemyPos;
|
||||
idVec3 lastReachableEnemyPos;
|
||||
bool wakeOnFlashlight;
|
||||
|
||||
// HUMANHEAD nla
|
||||
// Max size of the clip model in the XY plane. (diameter of sorts)
|
||||
float clipModelXYDiameter;
|
||||
bool frozen;
|
||||
// HUMANHEAD jrm - Moved in from old idNavigate
|
||||
int enemyEntityNum; // If is an enemy, what is his number?
|
||||
hhAIVehicleInterface vehicleInterfaceLocal;
|
||||
// HUMANHEAD END
|
||||
|
||||
// script variables
|
||||
idScriptBool AI_TALK;
|
||||
idScriptBool AI_DAMAGE;
|
||||
idScriptBool AI_PAIN;
|
||||
idScriptFloat AI_SPECIAL_DAMAGE;
|
||||
idScriptBool AI_DEAD;
|
||||
idScriptBool AI_ENEMY_VISIBLE;
|
||||
idScriptBool AI_ENEMY_IN_FOV;
|
||||
idScriptBool AI_ENEMY_DEAD;
|
||||
idScriptBool AI_MOVE_DONE;
|
||||
idScriptBool AI_ONGROUND;
|
||||
idScriptBool AI_ACTIVATED;
|
||||
idScriptBool AI_FORWARD;
|
||||
idScriptBool AI_JUMP;
|
||||
idScriptBool AI_ENEMY_REACHABLE;
|
||||
idScriptBool AI_BLOCKED;
|
||||
idScriptBool AI_OBSTACLE_IN_PATH;
|
||||
idScriptBool AI_DEST_UNREACHABLE;
|
||||
idScriptBool AI_HIT_ENEMY;
|
||||
idScriptBool AI_PUSHED;
|
||||
|
||||
//
|
||||
// ai/ai.cpp
|
||||
//
|
||||
void SetAAS( void );
|
||||
virtual void DormantBegin( void ); // called when entity becomes dormant
|
||||
virtual void DormantEnd( void ); // called when entity wakes from being dormant
|
||||
void Think( void );
|
||||
virtual // HUMANHEAD jsh - made virtual
|
||||
void Activate( idEntity *activator );
|
||||
virtual // HUMANHEAD JRM - made virtual
|
||||
int ReactionTo( const idEntity *ent );
|
||||
bool CheckForEnemy( void );
|
||||
virtual // HUMANHEAD JRM - made virtual
|
||||
void EnemyDead( void );
|
||||
virtual bool CanPlayChatterSounds( void ) const;
|
||||
void SetChatSound( void );
|
||||
void PlayChatter( void );
|
||||
virtual void Hide( void );
|
||||
virtual void Show( void );
|
||||
idVec3 FirstVisiblePointOnPath( const idVec3 origin, const idVec3 &target, int travelFlags ) const;
|
||||
void CalculateAttackOffsets( void );
|
||||
void PlayCinematic( void );
|
||||
|
||||
// movement
|
||||
// HUMANHEAD nla
|
||||
virtual void ClientImpacts( void );
|
||||
virtual void ClampZ( idVec3 &delta, idVec3 &goalPos, idVec3 &goalDelta ) { };
|
||||
// HUMANHEAD END
|
||||
virtual void ApplyImpulse( idEntity *ent, int id, const idVec3 &point, const idVec3 &impulse );
|
||||
virtual // HUMANHEAD JRM - added virtual
|
||||
void GetMoveDelta( const idMat3 &oldaxis, const idMat3 &axis, idVec3 &delta );
|
||||
void CheckObstacleAvoidance( const idVec3 &goalPos, idVec3 &newPos );
|
||||
virtual // HUMANHEAD mdl - Made virtual
|
||||
void DeadMove( void );
|
||||
virtual // HUMANHEAD nla - Made virual for crash logic in hhAI
|
||||
void AnimMove( void );
|
||||
virtual // HUMANHEAD nla - Made virual for crash logic in hhAI
|
||||
void SlideMove( void );
|
||||
virtual // HUMANHEAD mdc - Made virtual
|
||||
void AdjustFlyingAngles( void );
|
||||
void AddFlyBob( idVec3 &vel );
|
||||
virtual // HUMANHEAD jsh - Made virtual
|
||||
void AdjustFlyHeight( idVec3 &vel, const idVec3 &goalPos );
|
||||
void FlySeekGoal( idVec3 &vel, idVec3 &goalPos );
|
||||
virtual // HUMANHEAD jsh - Made virtual
|
||||
void AdjustFlySpeed( idVec3 &vel );
|
||||
virtual //HUMANHEAD mdc - made virtual
|
||||
void FlyTurn( void );
|
||||
virtual // HUMANHEAD cjr - made virtual
|
||||
void FlyMove( void );
|
||||
void StaticMove( void );
|
||||
|
||||
// damage
|
||||
virtual bool Pain( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location );
|
||||
virtual void Killed( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location );
|
||||
|
||||
// navigation
|
||||
void KickObstacles( const idVec3 &dir, float force, idEntity *alwaysKick );
|
||||
virtual //HUMANHEAD jsh
|
||||
bool ReachedPos( const idVec3 &pos, const moveCommand_t moveCommand ) const;
|
||||
float TravelDistance( const idVec3 &start, const idVec3 &end ) const;
|
||||
int PointReachableAreaNum( const idVec3 &pos, const float boundsScale = 2.0f ) const;
|
||||
bool PathToGoal( aasPath_t &path, int areaNum, const idVec3 &origin, int goalAreaNum, const idVec3 &goalOrigin ) const;
|
||||
void DrawRoute( void ) const;
|
||||
bool GetMovePos( idVec3 &seekPos );
|
||||
bool MoveDone( void ) const;
|
||||
bool EntityCanSeePos( idActor *actor, const idVec3 &actorOrigin, const idVec3 &pos );
|
||||
virtual //HUMANHEAD jsh
|
||||
void BlockedFailSafe( void );
|
||||
|
||||
// movement control
|
||||
void StopMove( moveStatus_t status );
|
||||
bool FaceEnemy( void );
|
||||
bool FaceEntity( idEntity *ent );
|
||||
bool DirectMoveToPosition( const idVec3 &pos );
|
||||
bool MoveToEnemyHeight( void );
|
||||
bool MoveOutOfRange( idEntity *entity, float range );
|
||||
bool MoveToAttackPosition( idEntity *ent, int attack_anim );
|
||||
bool MoveToEnemy( void );
|
||||
bool MoveToEntity( idEntity *ent );
|
||||
virtual // HUMANHEAD JRM - made virtual
|
||||
bool MoveToPosition( const idVec3 &pos, bool enemyBlocks = false ); // HUMANHEAD mdl: Added enemyBlocks flag
|
||||
bool MoveToCover( idEntity *entity, const idVec3 &pos );
|
||||
bool SlideToPosition( const idVec3 &pos, float time );
|
||||
bool WanderAround( void );
|
||||
bool StepDirection( float dir );
|
||||
virtual // HUMANHEAD jsh - made virtual
|
||||
bool NewWanderDir( const idVec3 &dest );
|
||||
|
||||
// effects
|
||||
const idDeclParticle *SpawnParticlesOnJoint( particleEmitter_t &pe, const char *particleName, const char *jointName );
|
||||
void SpawnParticles( const char *keyName );
|
||||
bool ParticlesActive( void );
|
||||
|
||||
// turning
|
||||
bool FacingIdeal( void );
|
||||
virtual // HUMANHEAD jsh
|
||||
void Turn( void );
|
||||
virtual // HUMANHEAD JRM
|
||||
bool TurnToward( float yaw );
|
||||
virtual // HUMANHEAD JRM
|
||||
bool TurnToward( const idVec3 &pos );
|
||||
|
||||
// enemy management
|
||||
void ClearEnemy( void );
|
||||
bool EnemyPositionValid( void ) const;
|
||||
void SetEnemyPosition( void );
|
||||
virtual // HUMANHEAD cjr - made virtual
|
||||
void UpdateEnemyPosition( void );
|
||||
virtual // HUMANHEAD JRM - made virtual
|
||||
void SetEnemy( idActor *newEnemy );
|
||||
|
||||
// attacks
|
||||
void CreateProjectileClipModel( void ) const;
|
||||
idProjectile *CreateProjectile( const idVec3 &pos, const idVec3 &dir );
|
||||
void RemoveProjectile( void );
|
||||
virtual // HUMANHEAD jsh = made virtual
|
||||
idProjectile *LaunchProjectile( const char *jointname, idEntity *target, bool clampToAttackCone, const idDict* desiredProjectileDef ); //HUMANHEAD mdc - added desiredProjectileDef
|
||||
|
||||
//HUMANHEAD mdc - added for multiple projectile support
|
||||
void SetCurrentProjectile( int infoIndex ); //sets up the AI member vars for this projectileInfo
|
||||
int FindProjectileInfo( const idDict* findDef ) const; //find a projectileInfo based on a projectileDef
|
||||
//HUMANHEAD END
|
||||
|
||||
virtual void DamageFeedback( idEntity *victim, idEntity *inflictor, int &damage );
|
||||
void DirectDamage( const char *meleeDefName, idEntity *ent );
|
||||
bool TestMelee( void ) const;
|
||||
virtual // HUMANHEAD JSH
|
||||
bool AttackMelee( const char *meleeDefName );
|
||||
void BeginAttack( const char *name );
|
||||
void EndAttack( void );
|
||||
void PushWithAF( void );
|
||||
|
||||
// special effects
|
||||
void GetMuzzle( const char *jointname, idVec3 &muzzle, idMat3 &axis );
|
||||
void InitMuzzleFlash( void );
|
||||
void TriggerWeaponEffects( const idVec3 &muzzle, const idMat3 &axis );
|
||||
virtual // HUMANHEAD JRM
|
||||
void UpdateMuzzleFlash( void );
|
||||
virtual bool UpdateAnimationControllers( void );
|
||||
void UpdateParticles( void );
|
||||
void TriggerParticles( const char *jointName );
|
||||
|
||||
// AI script state management
|
||||
virtual // HUMANHEAD
|
||||
void LinkScriptVariables( void );
|
||||
void UpdateAIScript( void );
|
||||
|
||||
//
|
||||
// ai/ai_events.cpp
|
||||
//
|
||||
virtual // HUMANHEAD mdl: Made virtual
|
||||
void Event_Activate( idEntity *activator );
|
||||
virtual // HUMANHEAD mdl: Made virtual
|
||||
void Event_Touch( idEntity *other, trace_t *trace );
|
||||
virtual // HUMANHEAD JRM - made virtual
|
||||
void Event_FindEnemy( int useFOV );
|
||||
virtual // HUMANHEAD JRM - made virtual
|
||||
void Event_FindEnemyAI( int useFOV );
|
||||
void Event_FindEnemyInCombatNodes( void );
|
||||
void Event_ClosestReachableEnemyOfEntity( idEntity *team_mate );
|
||||
virtual //HUMANHEAD jsh - made virtual
|
||||
void Event_HeardSound( int ignore_team );
|
||||
void Event_SetEnemy( idEntity *ent );
|
||||
void Event_ClearEnemy( void );
|
||||
void Event_MuzzleFlash( const char *jointname );
|
||||
void Event_CreateMissile( const char *jointname );
|
||||
virtual // HUMANHEAD: Made virtual
|
||||
void Event_AttackMissile( const char *jointname, const idDict *projDef = NULL, int boneDir = 0); // HUMANHEAD added projdef as param
|
||||
void Event_FireMissileAtTarget( const char *jointname, const char *targetname );
|
||||
void Event_LaunchMissile( const idVec3 &muzzle, const idAngles &ang );
|
||||
void Event_AttackMelee( const char *meleeDefName );
|
||||
void Event_DirectDamage( idEntity *damageTarget, const char *damageDefName );
|
||||
void Event_RadiusDamageFromJoint( const char *jointname, const char *damageDefName );
|
||||
void Event_BeginAttack( const char *name );
|
||||
void Event_EndAttack( void );
|
||||
void Event_MeleeAttackToJoint( const char *jointname, const char *meleeDefName );
|
||||
void Event_RandomPath( void );
|
||||
virtual // HUMANHEAD mdl: Made virtual
|
||||
void Event_CanBecomeSolid( void );
|
||||
void Event_BecomeSolid( void );
|
||||
void Event_BecomeNonSolid( void );
|
||||
void Event_BecomeRagdoll( void );
|
||||
void Event_StopRagdoll( void );
|
||||
void Event_SetHealth( float newHealth );
|
||||
void Event_GetHealth( void );
|
||||
void Event_AllowDamage( void );
|
||||
void Event_IgnoreDamage( void );
|
||||
void Event_GetCurrentYaw( void );
|
||||
void Event_TurnTo( float angle );
|
||||
void Event_TurnToPos( const idVec3 &pos );
|
||||
void Event_TurnToEntity( idEntity *ent );
|
||||
void Event_MoveStatus( void );
|
||||
void Event_StopMove( void );
|
||||
void Event_MoveToCover( void );
|
||||
void Event_MoveToEnemy( void );
|
||||
void Event_MoveToEnemyHeight( void );
|
||||
void Event_MoveOutOfRange( idEntity *entity, float range );
|
||||
void Event_MoveToAttackPosition( idEntity *entity, const char *attack_anim );
|
||||
void Event_MoveToEntity( idEntity *ent );
|
||||
void Event_MoveToPosition( const idVec3 &pos );
|
||||
void Event_SlideTo( const idVec3 &pos, float time );
|
||||
void Event_Wander( void );
|
||||
void Event_FacingIdeal( void );
|
||||
void Event_FaceEnemy( void );
|
||||
void Event_FaceEntity( idEntity *ent );
|
||||
void Event_WaitAction( const char *waitForState );
|
||||
#ifdef HUMANHEAD //jsh made virtual
|
||||
virtual
|
||||
#endif
|
||||
void Event_GetCombatNode( void );
|
||||
void Event_EnemyInCombatCone( idEntity *ent, int use_current_enemy_location );
|
||||
void Event_WaitMove( void );
|
||||
void Event_GetJumpVelocity( const idVec3 &pos, float speed, float max_height );
|
||||
void Event_EntityInAttackCone( idEntity *ent );
|
||||
void Event_CanSeeEntity( idEntity *ent );
|
||||
void Event_SetTalkTarget( idEntity *target );
|
||||
void Event_GetTalkTarget( void );
|
||||
void Event_SetTalkState( int state );
|
||||
void Event_EnemyRange( void );
|
||||
void Event_EnemyRange2D( void );
|
||||
void Event_GetEnemy( void );
|
||||
void Event_GetEnemyPos( void );
|
||||
void Event_GetEnemyEyePos( void );
|
||||
void Event_PredictEnemyPos( float time );
|
||||
void Event_CanHitEnemy( void );
|
||||
void Event_CanHitEnemyFromAnim( const char *animname );
|
||||
void Event_CanHitEnemyFromJoint( const char *jointname );
|
||||
void Event_EnemyPositionValid( void );
|
||||
void Event_ChargeAttack( const char *damageDef );
|
||||
void Event_TestChargeAttack( void );
|
||||
void Event_TestAnimMoveTowardEnemy( const char *animname );
|
||||
void Event_TestAnimMove( const char *animname );
|
||||
void Event_TestMoveToPosition( const idVec3 &position );
|
||||
void Event_TestMeleeAttack( void );
|
||||
void Event_TestAnimAttack( const char *animname );
|
||||
void Event_Shrivel( float shirvel_time );
|
||||
void Event_Burn( void );
|
||||
void Event_PreBurn( void );
|
||||
void Event_ClearBurn( void );
|
||||
void Event_SetSmokeVisibility( int num, int on );
|
||||
void Event_NumSmokeEmitters( void );
|
||||
void Event_StopThinking( void );
|
||||
void Event_GetTurnDelta( void );
|
||||
void Event_GetMoveType( void );
|
||||
void Event_SetMoveType( int moveType );
|
||||
void Event_SaveMove( void );
|
||||
void Event_RestoreMove( void );
|
||||
void Event_AllowMovement( float flag );
|
||||
void Event_JumpFrame( void );
|
||||
void Event_EnableClip( void );
|
||||
void Event_DisableClip( void );
|
||||
void Event_EnableGravity( void );
|
||||
void Event_DisableGravity( void );
|
||||
void Event_EnableAFPush( void );
|
||||
void Event_DisableAFPush( void );
|
||||
void Event_SetFlySpeed( float speed );
|
||||
void Event_SetFlyOffset( int offset );
|
||||
void Event_ClearFlyOffset( void );
|
||||
void Event_GetClosestHiddenTarget( const char *type );
|
||||
void Event_GetRandomTarget( const char *type );
|
||||
void Event_TravelDistanceToPoint( const idVec3 &pos );
|
||||
void Event_TravelDistanceToEntity( idEntity *ent );
|
||||
void Event_TravelDistanceBetweenPoints( const idVec3 &source, const idVec3 &dest );
|
||||
void Event_TravelDistanceBetweenEntities( idEntity *source, idEntity *dest );
|
||||
// HUMANHEAD
|
||||
virtual
|
||||
// HUMANHEAD END
|
||||
void Event_LookAtEntity( idEntity *ent, float duration );
|
||||
// HUMANHEAD
|
||||
virtual
|
||||
// HUMANHEAD END
|
||||
void Event_LookAtEnemy( float duration );
|
||||
void Event_SetJointMod( int allowJointMod );
|
||||
void Event_ThrowMoveable( void );
|
||||
void Event_ThrowAF( void );
|
||||
void Event_SetAngles( idAngles const &ang );
|
||||
void Event_GetAngles( void );
|
||||
void Event_RealKill( void );
|
||||
void Event_Kill( void );
|
||||
void Event_WakeOnFlashlight( int enable );
|
||||
void Event_LocateEnemy( void );
|
||||
void Event_KickObstacles( idEntity *kickEnt, float force );
|
||||
void Event_GetObstacle( void );
|
||||
void Event_PushPointIntoAAS( const idVec3 &pos );
|
||||
void Event_GetTurnRate( void );
|
||||
void Event_SetTurnRate( float rate );
|
||||
void Event_AnimTurn( float angles );
|
||||
void Event_AllowHiddenMovement( int enable );
|
||||
void Event_TriggerParticles( const char *jointName );
|
||||
void Event_FindActorsInBounds( const idVec3 &mins, const idVec3 &maxs );
|
||||
void Event_CanReachPosition( const idVec3 &pos );
|
||||
void Event_CanReachEntity( idEntity *ent );
|
||||
void Event_CanReachEnemy( void );
|
||||
void Event_GetReachableEntityPosition( idEntity *ent );
|
||||
};
|
||||
|
||||
class idCombatNode : public idEntity {
|
||||
public:
|
||||
CLASS_PROTOTYPE( idCombatNode );
|
||||
|
||||
idCombatNode();
|
||||
|
||||
void Save( idSaveGame *savefile ) const;
|
||||
void Restore( idRestoreGame *savefile );
|
||||
|
||||
void Spawn( void );
|
||||
bool IsDisabled( void ) const;
|
||||
bool EntityInView( idActor *actor, const idVec3 &pos );
|
||||
static void DrawDebugInfo( void );
|
||||
|
||||
private:
|
||||
float min_dist;
|
||||
float max_dist;
|
||||
float cone_dist;
|
||||
float min_height;
|
||||
float max_height;
|
||||
idVec3 cone_left;
|
||||
idVec3 cone_right;
|
||||
idVec3 offset;
|
||||
bool disabled;
|
||||
|
||||
void Event_Activate( idEntity *activator );
|
||||
void Event_MarkUsed( void );
|
||||
};
|
||||
|
||||
#endif /* !__AI_H__ */
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user