340 lines
7.9 KiB
C++
340 lines
7.9 KiB
C++
/*
|
|
===============================================================================
|
|
|
|
AAS_Find.cpp
|
|
|
|
This file has all aas search classes.
|
|
|
|
===============================================================================
|
|
*/
|
|
|
|
#include "../../idlib/precompiled.h"
|
|
#pragma hdrstop
|
|
|
|
#include "../Game_local.h"
|
|
#include "AI.h"
|
|
#include "AI_Manager.h"
|
|
#include "AI_Util.h"
|
|
#include "AAS_Find.h"
|
|
|
|
/*
|
|
===============================================================================
|
|
|
|
rvAASFindGoalForHide
|
|
|
|
===============================================================================
|
|
*/
|
|
|
|
/*
|
|
============
|
|
rvAASFindGoalForHide::rvAASFindGoalForHide
|
|
============
|
|
*/
|
|
rvAASFindGoalForHide::rvAASFindGoalForHide( const idVec3 &hideFromPos ) {
|
|
int numPVSAreas;
|
|
idBounds bounds( hideFromPos - idVec3( 16, 16, 0 ), hideFromPos + idVec3( 16, 16, 64 ) );
|
|
|
|
// setup PVS
|
|
numPVSAreas = gameLocal.pvs.GetPVSAreas( bounds, PVSAreas, idEntity::MAX_PVS_AREAS );
|
|
hidePVS = gameLocal.pvs.SetupCurrentPVS( PVSAreas, numPVSAreas );
|
|
}
|
|
|
|
/*
|
|
============
|
|
rvAASFindGoalForHide::~rvAASFindGoalForHide
|
|
============
|
|
*/
|
|
rvAASFindGoalForHide::~rvAASFindGoalForHide() {
|
|
gameLocal.pvs.FreeCurrentPVS( hidePVS );
|
|
}
|
|
|
|
/*
|
|
rvAASFindGoalForHide
|
|
rvAASFindHide::TestArea
|
|
============
|
|
*/
|
|
bool rvAASFindGoalForHide::TestArea( class idAAS *aas, int areaNum, const aasArea_t& area ) {
|
|
int numPVSAreas;
|
|
int PVSAreas[ idEntity::MAX_PVS_AREAS ];
|
|
|
|
numPVSAreas = gameLocal.pvs.GetPVSAreas( idBounds( area.center ).Expand( 16.0f ).TranslateSelf(idVec3(0,0,1)), PVSAreas, idEntity::MAX_PVS_AREAS );
|
|
if ( !gameLocal.pvs.InCurrentPVS( hidePVS, PVSAreas, numPVSAreas ) ) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
===============================================================================
|
|
|
|
rvAASFindGoalOutOfRange
|
|
|
|
===============================================================================
|
|
*/
|
|
|
|
/*
|
|
============
|
|
rvAASFindGoalOutOfRange::rvAASFindGoalOutOfRange
|
|
============
|
|
*/
|
|
rvAASFindGoalOutOfRange::rvAASFindGoalOutOfRange( idAI* _owner ) {
|
|
owner = _owner;
|
|
}
|
|
|
|
/*
|
|
============
|
|
rvAASFindAreaOutOfRange::TestArea
|
|
============
|
|
*/
|
|
bool rvAASFindGoalOutOfRange::TestPoint ( idAAS* aas, const idVec3& pos, const float zAllow ) {
|
|
return aiManager.ValidateDestination ( owner, pos );
|
|
}
|
|
|
|
/*
|
|
===============================================================================
|
|
|
|
rvAASFindGoalForAttack
|
|
|
|
Find a position to move to that allows the ai to at their target
|
|
|
|
===============================================================================
|
|
*/
|
|
|
|
/*
|
|
============
|
|
rvAASFindGoalForAttack::rvAASFindGoalForAttack
|
|
============
|
|
*/
|
|
rvAASFindGoalForAttack::rvAASFindGoalForAttack( idAI* _owner ) {
|
|
owner = _owner;
|
|
cachedIndex = 0;
|
|
}
|
|
|
|
/*
|
|
============
|
|
rvAASFindGoalForAttack::~rvAASFindGoalForAttack
|
|
============
|
|
*/
|
|
rvAASFindGoalForAttack::~rvAASFindGoalForAttack ( void ) {
|
|
}
|
|
|
|
/*
|
|
============
|
|
rvAASFindGoalForAttack::Init
|
|
============
|
|
*/
|
|
void rvAASFindGoalForAttack::Init ( void ) {
|
|
// setup PVS
|
|
int numPVSAreas;
|
|
numPVSAreas = gameLocal.pvs.GetPVSAreas( owner->enemy.ent->GetPhysics()->GetAbsBounds(), PVSAreas, idEntity::MAX_PVS_AREAS );
|
|
targetPVS = gameLocal.pvs.SetupCurrentPVS( PVSAreas, numPVSAreas );
|
|
|
|
cachedGoals.SetGranularity ( 1024 );
|
|
}
|
|
|
|
/*
|
|
============
|
|
rvAASFindGoalForAttack::Finish
|
|
============
|
|
*/
|
|
void rvAASFindGoalForAttack::Finish ( void ) {
|
|
gameLocal.pvs.FreeCurrentPVS( targetPVS );
|
|
}
|
|
|
|
/*
|
|
============
|
|
rvAASFindGoalForAttack::TestArea
|
|
============
|
|
*/
|
|
bool rvAASFindGoalForAttack::TestArea( class idAAS *aas, int areaNum, const aasArea_t& area ) {
|
|
int numPVSAreas;
|
|
int PVSAreas[ idEntity::MAX_PVS_AREAS ];
|
|
|
|
cachedAreaNum = areaNum;
|
|
|
|
// If the whole area is out of range then skip it
|
|
float range;
|
|
range = area.bounds.ShortestDistance ( owner->enemy.lastKnownPosition );
|
|
if ( range > owner->combat.attackRange[1] ) {
|
|
return false;
|
|
}
|
|
|
|
// Out of pvs?
|
|
numPVSAreas = gameLocal.pvs.GetPVSAreas( idBounds( area.center ).Expand( 16.0f ), PVSAreas, idEntity::MAX_PVS_AREAS );
|
|
return gameLocal.pvs.InCurrentPVS( targetPVS, PVSAreas, numPVSAreas );
|
|
}
|
|
|
|
/*
|
|
============
|
|
rvAASFindGoalForAttack::TestPoint
|
|
============
|
|
*/
|
|
bool rvAASFindGoalForAttack::TestPoint ( class idAAS *aas, const idVec3& point, const float zAllow ) {
|
|
float dist;
|
|
|
|
idVec3 localPoint = point;
|
|
float bestZ = owner->enemy.ent->GetPhysics()->GetOrigin().z;
|
|
if ( bestZ > localPoint.z ) {
|
|
if ( bestZ > zAllow ) {
|
|
localPoint.z = zAllow;
|
|
} else {
|
|
localPoint.z = bestZ;
|
|
}
|
|
}
|
|
|
|
// Out of attack range?
|
|
dist = (localPoint - owner->enemy.ent->GetPhysics()->GetOrigin ( )).LengthFast ( );
|
|
if ( dist < owner->combat.attackRange[0] || dist > owner->combat.attackRange[1] ) {
|
|
return false;
|
|
}
|
|
|
|
// If tethered make sure the point is within the tether range
|
|
if ( owner->tether ) {
|
|
idVec3 localPoint = point;
|
|
float bestZ = owner->tether.GetEntity()->GetPhysics()->GetOrigin().z;
|
|
if ( bestZ > localPoint.z ) {
|
|
if ( bestZ > zAllow ) {
|
|
localPoint.z = zAllow;
|
|
} else {
|
|
localPoint.z = bestZ;
|
|
}
|
|
}
|
|
if ( !owner->tether->ValidateDestination ( owner, localPoint ) ) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
aasGoal_t& goal = cachedGoals.Alloc ( );
|
|
goal.areaNum = cachedAreaNum;
|
|
goal.origin = localPoint;
|
|
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
============
|
|
rvAASFindGoalForAttack::TestCachedGoal
|
|
============
|
|
*/
|
|
bool rvAASFindGoalForAttack::TestCachedGoal ( int index ) {
|
|
const aasGoal_t& goal = cachedGoals[index];
|
|
|
|
// Out of attack range?
|
|
float dist = (goal.origin - owner->enemy.ent->GetPhysics()->GetOrigin ( ) ).LengthFast ( );
|
|
if ( dist < owner->combat.attackRange[0] || dist > owner->combat.attackRange[1] ) {
|
|
return false;
|
|
}
|
|
|
|
// Someone already there?
|
|
if ( !aiManager.ValidateDestination ( owner, goal.origin, true ) ) {
|
|
return false;
|
|
}
|
|
|
|
// Can we see the enemy from this position?
|
|
if ( !owner->CanSeeFrom ( goal.origin - owner->GetPhysics()->GetGravityNormal ( ) * owner->combat.visStandHeight, owner->GetEnemy(), false ) ) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
============
|
|
rvAASFindGoalForAttack::TestCachedPoints
|
|
============
|
|
*/
|
|
bool rvAASFindGoalForAttack::TestCachedGoals ( int count, aasGoal_t& goal ) {
|
|
int i;
|
|
|
|
goal.areaNum = 0;
|
|
|
|
// Test as many points as we are allowed to test
|
|
for ( i = 0; i < count && cachedIndex < cachedGoals.Num(); cachedIndex ++, i ++ ) {
|
|
// Retest simple checks
|
|
if ( TestCachedGoal( cachedIndex ) ) {
|
|
goal = cachedGoals[cachedIndex];
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return !(cachedIndex >= cachedGoals.Num());
|
|
}
|
|
|
|
/*
|
|
===============================================================================
|
|
|
|
rvAASFindGoalForTether
|
|
|
|
Find a goal to move to that is within the given tether.
|
|
|
|
===============================================================================
|
|
*/
|
|
|
|
/*
|
|
============
|
|
rvAASFindGoalForTether::rvAASFindGoalForTether
|
|
============
|
|
*/
|
|
rvAASFindGoalForTether::rvAASFindGoalForTether( idAI* _owner, rvAITether* _tether ) {
|
|
owner = _owner;
|
|
tether = _tether;
|
|
}
|
|
|
|
/*
|
|
============
|
|
rvAASFindGoalForTether::rvAASFindGoalForTether
|
|
============
|
|
*/
|
|
rvAASFindGoalForTether::~rvAASFindGoalForTether( void ) {
|
|
}
|
|
|
|
/*
|
|
============
|
|
rvAASFindGoalForTether::TestArea
|
|
============
|
|
*/
|
|
bool rvAASFindGoalForTether::TestArea( class idAAS *aas, int areaNum, const aasArea_t& area ) {
|
|
// Test super class first
|
|
if ( !idAASCallback::TestArea ( aas, areaNum, area ) ) {
|
|
return false;
|
|
}
|
|
|
|
// Make sure the area bounds is remotely valid for the tether
|
|
idBounds tempBounds = area.bounds;
|
|
tempBounds[1].z = area.ceiling;
|
|
if ( !tether->ValidateBounds ( tempBounds ) ) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
============
|
|
rvAASFindGoalForTether::TestPoint
|
|
============
|
|
*/
|
|
bool rvAASFindGoalForTether::TestPoint ( class idAAS* aas, const idVec3& point, const float zAllow ) {
|
|
if ( !tether ) {
|
|
return false;
|
|
}
|
|
|
|
idVec3 localPoint = point;
|
|
float bestZ = tether->GetPhysics()->GetOrigin().z;
|
|
if ( bestZ > localPoint.z ) {
|
|
if ( bestZ > zAllow ) {
|
|
localPoint.z = zAllow;
|
|
} else {
|
|
localPoint.z = bestZ;
|
|
}
|
|
}
|
|
if ( !tether->ValidateDestination ( owner, localPoint ) ) {
|
|
return false;
|
|
}
|
|
|
|
if ( !aiManager.ValidateDestination ( owner, localPoint ) ) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|