📄 behavior.cpp
字号:
gi.printf( "nextsearch: %f\n", nextsearch );
}
void FindFlee::Begin
(
Actor &self
)
{
if ( !anim.length() )
{
anim = "run";
}
movegoal = NULL;
state = 0;
}
qboolean FindFlee::Evaluate
(
Actor &self
)
{
if ( !movegoal )
{
state = 0;
}
switch( state )
{
case 0 :
// Checking for flee node
chase.Begin( self );
movegoal = FindFleeNode( self );
if ( !movegoal )
{
// Couldn't find any!
return false;
}
// Found flee node, going to it
if ( anim.length() && ( anim != self.animname ) )
{
self.SetAnim( anim );
}
state = 1;
nextsearch = level.time + 1;
case 1 :
if ( chase.Evaluate( self ) )
{
if ( nextsearch < level.time )
{
state = 0;
}
return true;
}
// Reached cover
if ( self.CanSeeEnemyFrom( self.worldorigin ) )
{
state = 0;
}
else
{
// standing
self.SetAnim( "idle" );
chase.End( self );
return false;
}
break;
}
return true;
}
void FindFlee::End
(
Actor &self
)
{
chase.End( self );
}
/****************************************************************************
FindEnemy Class Definition
****************************************************************************/
CLASS_DECLARATION( Behavior, FindEnemy, NULL );
ResponseDef FindEnemy::Responses[] =
{
{ &EV_Behavior_Args, ( Response )FindEnemy::SetArgs },
{ NULL, NULL }
};
void FindEnemy::SetArgs
(
Event *ev
)
{
anim = ev->GetString( 2 );
}
void FindEnemy::ShowInfo
(
Actor &self
)
{
Behavior::ShowInfo( self );
gi.printf( "\nchase:\n" );
chase.ShowInfo( self );
gi.printf( "\nstate: %d\n", state );
gi.printf( "nextsearch: %f\n", nextsearch );
gi.printf( "anim: %s\n", anim.c_str() );
}
void FindEnemy::Begin
(
Actor &self
)
{
if ( !anim.length() )
{
anim = "run";
}
movegoal = NULL;
lastSearchNode = NULL;
state = 0;
}
PathNode *FindEnemy::FindClosestSightNode
(
Actor &self
)
{
int i;
PathNode *bestnode;
float bestdist;
PathNode *node;
Vector delta;
float dist;
Vector pos;
if ( self.currentEnemy )
{
pos = self.currentEnemy->worldorigin;
}
else
{
pos = self.worldorigin;
}
bestnode = NULL;
bestdist = 999999999; // greater than ( 8192 * sqr(2) ) ^ 2 -- maximum squared distance
for( i = 0; i <= ai_maxnode; i++ )
{
node = AI_GetNode( i );
if ( node && ( ( node->occupiedTime <= level.time ) || ( node->entnum != self.entnum ) ) )
{
// get the distance squared (faster than getting real distance)
delta = node->worldorigin - pos;
dist = delta * delta;
if ( ( dist < bestdist ) && self.CanSeeFrom( node->worldorigin, self.currentEnemy ) )
{
bestnode = node;
bestdist = dist;
}
}
}
return bestnode;
}
qboolean FindEnemy::Evaluate
(
Actor &self
)
{
if ( !self.currentEnemy )
{
return false;
}
if ( nextsearch < level.time )
{
// check if we should search for the first time
if ( !lastSearchNode )
{
//gi.dprintf( "%d: %s(%d) first time\n", level.framenum, self.targetname.c_str(), self.entnum );
state = 0;
}
else
{
// search less often if we're far away
nextsearch = self.DistanceTo( self.currentEnemy ) * ( 1.0 / 512.0 );
if ( nextsearch < 1 )
{
nextsearch = 1;
}
nextsearch += level.time;
// don't search again if our enemy hasn't moved very far
if ( !self.currentEnemy->WithinDistance( lastSearchPos, 256 ) )
{
//gi.dprintf( "%d: %s(%d) searching again\n", level.framenum, self.targetname.c_str(), self.entnum );
state = 0;
}
}
}
switch( state )
{
case 0 :
// Searching for enemy
chase.Begin( self );
lastSearchPos = self.currentEnemy->worldorigin;
movegoal = PathManager.NearestNode( lastSearchPos, &self );
if ( !movegoal )
{
movegoal = PathManager.NearestNode( lastSearchPos, &self, false );
}
lastSearchNode = movegoal;
if ( movegoal )
{
Path *path;
FindEnemyPath find;
PathNode *from;
find.heuristic.self = &self;
find.heuristic.setSize( self.size );
find.heuristic.entnum = self.entnum;
from = PathManager.NearestNode( self.worldorigin, &self );
if ( ( from == movegoal ) && ( self.DistanceTo( from->worldorigin ) < 8 ) )
{
movegoal = NULL;
from = NULL;
}
if ( from )
{
path = find.FindPath( from, movegoal );
if ( path )
{
chase.SetGoal( movegoal );
chase.SetPath( path );
}
else
{
movegoal = NULL;
}
}
}
if ( !movegoal )
{
if ( self.CanSee( self.currentEnemy ) || ( !self.currentEnemy->groundentity && !self.waterlevel ) )
{
chase.SetGoalPos( self.currentEnemy->worldorigin );
}
else
{
// Couldn't find enemy
// since we can't reach em
// clear out enemy state
//
self.ClearEnemies();
return false;
}
}
// Found enemy, going to it
if ( anim.length() && ( anim != self.animname ) )
{
self.SetAnim( anim );
}
state = 1;
case 1 :
if ( self.CanShoot( self.currentEnemy, false ) )
{
// Reached enemy
chase.End( self );
return false;
}
if ( !chase.Evaluate( self ) )
{
state = 0;
nextsearch = 0;
}
break;
}
return true;
}
void FindEnemy::End
(
Actor &self
)
{
chase.End( self );
}
/****************************************************************************
Hide Class Definition
****************************************************************************/
CLASS_DECLARATION( Behavior, Hide, NULL );
ResponseDef Hide::Responses[] =
{
{ &EV_Behavior_Args, ( Response )Hide::SetArgs },
{ NULL, NULL }
};
void Hide::SetArgs
(
Event *ev
)
{
anim = ev->GetString( 2 );
}
void Hide::ShowInfo
(
Actor &self
)
{
Behavior::ShowInfo( self );
gi.printf( "\nhide:\n" );
hide.ShowInfo( self );
gi.printf( "\nanim: %s\n", anim.c_str() );
gi.printf( "state: %d\n", state );
gi.printf( "checktime: %f\n", checktime );
}
void Hide::Begin
(
Actor &self
)
{
if ( !anim.length() )
{
anim = "run";
}
state = 0;
}
qboolean Hide::Evaluate
(
Actor &self
)
{
switch( state )
{
// init run for cover
case 0 :
state = 1;
hide.Begin( self );
if ( hide.Evaluate( self ) && anim.length() )
{
self.SetAnim( anim );
}
else
{
hide.End( self );
self.SetAnim( "crouch_down" );
state = 2;
checktime = level.time + 1;
}
break;
// running for cover
case 1 :
if ( !hide.Evaluate( self ) )
{
hide.End( self );
self.SetAnim( "crouch_down" );
state = 2;
checktime = level.time + 1;
}
break;
// wait for a bit
case 2 :
if ( checktime < level.time )
{
checktime = level.time + 0.5f;
if ( self.CanSeeEnemyFrom( self.worldorigin ) )
{
hide.Begin( self );
if ( hide.Evaluate( self ) && anim.length() )
{
self.SetAnim( anim );
state = 1;
}
else
{
hide.End( self );
checktime = level.time + 2;
}
}
}
break;
}
return true;
}
void Hide::End
(
Actor &self
)
{
hide.End( self );
self.SetAnim( "crouch_down" );
}
/****************************************************************************
FleeAndRemove Class Definition
****************************************************************************/
CLASS_DECLARATION( Behavior, FleeAndRemove, NULL );
ResponseDef FleeAndRemove::Responses[] =
{
{ &EV_Behavior_Args, ( Response )FleeAndRemove::SetArgs },
{ NULL, NULL }
};
void FleeAndRemove::SetArgs
(
Event *ev
)
{
anim = ev->GetString( 2 );
}
void FleeAndRemove::ShowInfo
(
Actor &self
)
{
Behavior::ShowInfo( self );
gi.printf( "\nfindflee:\n" );
flee.ShowInfo( self );
gi.printf( "\nanim: %s\n", anim.c_str() );
gi.printf( "state: %d\n", state );
gi.printf( "checktime: %f\n", checktime );
}
void FleeAndRemove::Begin
(
Actor &self
)
{
if ( !anim.length() )
{
anim = "run";
}
state = 0;
}
qboolean FleeAndRemove::Evaluate
(
Actor &self
)
{
if ( !self.currentEnemy )
{
return false;
}
switch( state )
{
// init run for cover
case 0 :
state = 1;
if ( anim.length() )
{
self.SetAnim( anim );
}
flee.Begin( self );
// if we fail on the first try, probably can't flee.
if ( !flee.Evaluate( self ) )
{
flee.End( self );
return false;
}
return true;
// running for cover
case 1 :
if ( !flee.Evaluate( self ) )
{
flee.End( self );
state = 2;
checktime = 0;
self.SetAnim( "crouch_down" );
}
break;
// wait for a bit
case 2 :
if ( checktime < level.time )
{
checktime = level.time + 1;
if ( self.CanSeeEnemyFrom( self.worldorigin ) )
{
state = 0;
}
else
{
self.PostEvent( EV_Remove, 0 );
}
}
break;
}
return true;
}
void FleeAndRemove::End
(
Actor &self
)
{
flee.End( self );
self.SetAnim( "crouch_down" );
}
/****************************************************************************
AimAndShoot Class Definition
****************************************************************************/
CLASS_DECLARATION( Behavior, AimAndShoot, NULL );
ResponseDef AimAndShoot::Responses[] =
{
{ &EV_Behavior_Args, ( Response )AimAndShoot::SetArgs },
{ &EV_Behavior_AnimDone, ( Response )AimAndShoot::AnimDone },
{ NULL, NULL }
};
AimAndShoot::AimAndShoot()
{
maxshots = 1;
numshots = 0;
}
void AimAndShoot::ShowInfo
(
Actor &self
)
{
Behavior::ShowInfo( self );
gi.printf( "\naim:\n" );
aim.ShowInfo( self );
gi.printf( "\nmode: %d\n", mode );
gi.printf( "maxshots: %d\n", maxshots );
gi.printf( "numshots: %d\n", numshots );
gi.printf( "animdone: %d\n", animdone );
}
void AimAndShoot::Begin
(
Actor &self
)
{
enemy_health = 0;
mode = 0;
animdone = false;
readyfireanim = animprefix + "readyfire";
if ( !self.HasAnim( readyfireanim.c_str() ) )
{
readyfireanim = "";
}
aimanim = animprefix + "aim";
if ( !self.HasAnim( aimanim.c_str() ) )
{
aimanim = "";
}
fireanim = animprefix + "fire";
if ( !self.HasAnim( fireanim.c_str() ) )
{
fireanim = "";
}
}
void AimAndShoot::SetMaxShots
(
int num
)
{
maxshots = (num>>1) + G_Random( num );
}
void AimAndShoot::SetArgs
(
Event *ev
)
{
SetMaxShots( ev->GetInteger( 2 ) );
if ( ev->NumArgs() > 2 )
{
animprefix = ev->GetString( 3 );
}
}
void AimAndShoot::AnimDone
(
Event *ev
)
{
animdone = true;
}
qboolean AimAndShoot::Evaluate
(
Actor &self
)
{
switch( mode )
{
case 0 :
if ( !self.currentEnemy )
{
return false;
}
if ( !self.CanShoot( self.currentEnemy, false ) )
{
return false;
}
if ( readyfireanim.length() )
{
animdone = false;
self.SetAnim( readyfireanim.c_str(), EV_Actor_NotifyBehavior );
aim.Begin( self );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -