📄 behavior.cpp
字号:
void FireOnSight::ShowInfo
(
Actor &self
)
{
Behavior::ShowInfo( self );
gi.printf( "\nchase:\n" );
chase.ShowInfo( self );
gi.printf( "\naim:\n" );
aim.ShowInfo( self );
gi.printf( "\nmode : %d\n", mode );
gi.printf( "anim : %s\n", anim.c_str() );
}
void FireOnSight::Begin
(
Actor &self
)
{
mode = 0;
if ( !anim.length() )
{
anim = "run";
}
}
qboolean FireOnSight::Evaluate
(
Actor &self
)
{
if ( !self.currentEnemy || self.currentEnemy->deadflag || self.currentEnemy->health <= 0 )
{
return false;
}
switch( mode )
{
case 0 :
// Start chasing
self.SetAnim( anim );
chase.Begin( self );
mode = 1;
case 1 :
// Chasing
if ( self.WeaponReady() && self.CanShoot( self.currentEnemy, false ) )
{
chase.End( self );
self.SetAnim( "readyfire" );
aim.Begin( self );
mode = 2;
break;
}
else
{
self.Chatter( "snd_pursuit", 1 );
}
chase.SetTarget( self.currentEnemy );
chase.Evaluate( self );
break;
case 2 :
// Aiming
aim.SetTarget( self.currentEnemy );
aim.Evaluate( self );
if ( self.WeaponReady() && self.CanShoot( self.currentEnemy, true ) )
{
self.Chatter( "snd_inmysights", 5 );
self.SetAnim( "fire" );
mode = 3;
}
else if ( !self.WeaponReady() || !self.CanShoot( self.currentEnemy, false ) )
{
aim.End( self );
mode = 0;
break;
}
break;
case 3 :
// Fire
aim.SetTarget( self.currentEnemy );
aim.Evaluate( self );
if ( !self.CanShoot( self.currentEnemy, true ) )
{
self.SetAnim( "aim" );
mode = 2;
}
else
{
self.Chatter( "snd_attacktaunt", 4 );
}
break;
}
return true;
}
void FireOnSight::End
(
Actor &self
)
{
chase.End( self );
aim.End( self );
}
/****************************************************************************
TurnTo Class Definition
****************************************************************************/
CLASS_DECLARATION( Behavior, TurnTo, NULL );
ResponseDef TurnTo::Responses[] =
{
{ NULL, NULL }
};
TurnTo::TurnTo()
{
dir = Vector( 1, 0, 0 );
mode = 0;
ent = NULL;
yaw = 0;
}
void TurnTo::SetDirection
(
float yaw
)
{
Vector ang;
ang = Vector( 0, yaw, 0 );
this->yaw = anglemod( yaw );
ang.AngleVectors( &dir, NULL, NULL );
mode = 1;
}
void TurnTo::SetTarget
(
Entity *ent
)
{
this->ent = ent;
mode = 2;
}
void TurnTo::ShowInfo
(
Actor &self
)
{
Behavior::ShowInfo( self );
gi.printf( "\nseek:\n" );
seek.ShowInfo( self );
if ( ent )
{
gi.printf( "\nent: #%d '%s'\n", ent->entnum, ent->targetname.c_str() );
}
else
{
gi.printf( "\nent: NULL\n" );
}
gi.printf( "dir: ( %f, %f, %f )\n", dir.x, dir.y, dir.z );
gi.printf( "yaw: %f\n", yaw );
gi.printf( "mode: %d\n", mode );
}
void TurnTo::Begin
(
Actor &self
)
{
seek.Begin( self );
}
qboolean TurnTo::Evaluate
(
Actor &self
)
{
Vector delta;
float ang;
switch( mode )
{
case 1 :
ang = angledist( yaw - self.angles.yaw() );
if ( fabs( ang ) < 1 )
{
self.Accelerate( Vector( 0, ang, 0 ) );
return false;
}
seek.SetTargetPosition( self.worldorigin + dir );
seek.SetTargetVelocity( vec_zero );
break;
case 2 :
if ( !ent )
{
return false;
}
delta = ent->worldorigin - self.worldorigin;
yaw = delta.toYaw();
//if ( self.angles.yaw() == yaw )
// {
// return false;
// }
seek.SetTargetPosition( ent->worldorigin );
seek.SetTargetVelocity( vec_zero );
break;
default :
return false;
}
seek.SetPosition( self.worldorigin );
seek.SetDir( self.movedir );
seek.SetMaxSpeed( self.movespeed );
seek.Evaluate( self );
//seek.DrawForces();
self.Accelerate( seek.steeringforce );
return true;
}
void TurnTo::End
(
Actor &self
)
{
seek.End( self );
}
/****************************************************************************
GotoPathNode Class Definition
****************************************************************************/
CLASS_DECLARATION( Behavior, GotoPathNode, NULL );
ResponseDef GotoPathNode::Responses[] =
{
{ &EV_Behavior_Args, ( Response )GotoPathNode::SetArgs },
{ NULL, NULL }
};
GotoPathNode::GotoPathNode()
{
usevec = false;
movegoal = NULL;
goal = vec_zero;
goalent = NULL;
}
void GotoPathNode::SetArgs
(
Event *ev
)
{
anim = ev->GetString( 2 );
if ( ev->IsVectorAt( 3 ) )
{
goal = ev->GetVector( 3 );
usevec = true;
}
else
{
usevec = false;
movegoal = AI_FindNode( ev->GetString( 3 ) );
if ( !movegoal )
{
goalent = ev->GetEntity( 3 );
}
}
}
void GotoPathNode::SetGoal
(
PathNode *node
)
{
usevec = false;
movegoal = node;
}
void GotoPathNode::ShowInfo
(
Actor &self
)
{
Behavior::ShowInfo( self );
gi.printf( "\nturnto:\n" );
turnto.ShowInfo( self );
gi.printf( "\nchase:\n" );
chase.ShowInfo( self );
gi.printf( "\nstate: %d\n", state );
gi.printf( "usevec: %d\n", usevec );
gi.printf( "time: %f\n", time );
gi.printf( "anim: %s\n", anim.c_str() );
if ( goalent )
{
gi.printf( "\ngoalent: #%d '%s'\n", goalent->entnum, goalent->targetname.c_str() );
}
else
{
gi.printf( "\ngoalent: NULL\n" );
}
gi.printf( "goal: ( %f, %f, %f )\n", goal.x, goal.y, goal.z );
}
void GotoPathNode::Begin
(
Actor &self
)
{
state = 0;
chase.Begin( self );
turnto.Begin( self );
if ( goalent )
{
chase.SetTarget( goalent );
}
else if ( movegoal )
{
chase.SetGoal( movegoal );
}
else
{
chase.SetGoalPos( goal );
}
// don't check for new paths as often
chase.SetPathRate( 4 );
if ( anim.length() )
{
self.SetAnim( anim );
}
}
qboolean GotoPathNode::Evaluate
(
Actor &self
)
{
float yaw;
if ( !usevec && !goalent && !movegoal )
{
return false;
}
switch( state )
{
case 0 :
if ( chase.Evaluate( self ) )
{
break;
}
state = 1;
self.SetAnim( "idle" );
// cascade down to case 1
case 1 :
if ( !movegoal )
{
return false;
}
if ( movegoal->setangles )
{
yaw = movegoal->worldangles.yaw();
turnto.SetDirection( yaw );
if ( turnto.Evaluate( self ) )
{
break;
}
}
if ( movegoal->animname == "" )
{
self.SetAnim( "idle" );
return false;
}
self.SetAnim( movegoal->animname, EV_Actor_FinishedBehavior );
state = 2;
break;
case 2 :
break;
}
return true;
}
void GotoPathNode::End
(
Actor &self
)
{
chase.End( self );
}
/****************************************************************************
Investigate Class Definition
****************************************************************************/
CLASS_DECLARATION( Behavior, Investigate, NULL );
ResponseDef Investigate::Responses[] =
{
{ &EV_Behavior_Args, ( Response )Investigate::SetArgs },
{ NULL, NULL }
};
void Investigate::SetArgs
(
Event *ev
)
{
Entity *ent;
Actor *self;
ent = ev->GetEntity( 1 );
if ( ent && ent->isSubclassOf( Actor ) )
{
self = ( Actor * )ent;
}
anim = ev->GetString( 2 );
goal = ev->GetVector( 3 );
}
void Investigate::ShowInfo
(
Actor &self
)
{
Behavior::ShowInfo( self );
gi.printf( "\nchase:\n" );
chase.ShowInfo( self );
gi.printf( "\nanim: %s\n", anim.c_str() );
gi.printf( "curioustime: %f\n", curioustime );
gi.printf( "goal: ( %f, %f, %f )\n", goal.x, goal.y, goal.z );
}
void Investigate::Begin
(
Actor &self
)
{
//
// we are only interested for about 10 seconds, if we can't get there, lets go back to what we were doing
//
curioustime = level.time + 10;
self.Chatter( "snd_investigate", 10 );
chase.Begin( self );
chase.SetGoalPos( goal );
// Don't allow guys to change their anim if we're already close enough to the goal
if ( !Done( self ) && anim.length() )
{
self.SetAnim( anim );
}
}
qboolean Investigate::Done
(
Actor &self
)
{
Vector delta;
float xydist;
if ( curioustime < level.time )
{
return true;
}
if ( self.CanSeeEnemyFrom( self.worldorigin ) )
{
return true;
}
if ( self.lastmove == STEPMOVE_STUCK )
{
return true;
}
delta = goal - self.worldorigin;
//
// get rid of Z variance
//
delta[ 2 ] = 0;
xydist = delta.length();
if ( xydist < 100 )
{
return true;
}
return false;
}
qboolean Investigate::Evaluate
(
Actor &self
)
{
if ( Done( self ) || !chase.Evaluate( self ) )
{
return false;
}
return true;
}
void Investigate::End
(
Actor &self
)
{
chase.End( self );
}
/****************************************************************************
Flee Class Definition
****************************************************************************/
CLASS_DECLARATION( Behavior, Flee, NULL );
ResponseDef Flee::Responses[] =
{
{ &EV_Behavior_Args, ( Response )Flee::SetArgs },
{ NULL, NULL }
};
void Flee::SetArgs
(
Event *ev
)
{
anim = ev->GetString( 2 );
}
void Flee::ShowInfo
(
Actor &self
)
{
Behavior::ShowInfo( self );
gi.printf( "\nfollow:\n" );
follow.ShowInfo( self );
if ( path )
{
gi.printf( "\npath : ( %f, %f, %f ) to ( %f, %f, %f )\n",
path->Start()->worldorigin.x, path->Start()->worldorigin.y, path->Start()->worldorigin.z,
path->End()->worldorigin.x, path->End()->worldorigin.y, path->End()->worldorigin.z );
}
else
{
gi.printf( "\npath : NULL\n" );
}
gi.printf( "\navoid:\n" );
avoid.ShowInfo( self );
gi.printf( "\navoidtime: %f\n", avoidtime );
gi.printf( "anim: %s\n", anim.c_str() );
}
void Flee::Begin
(
Actor &self
)
{
follow.Begin( self );
avoid.AvoidWalls( false );
avoid.Begin( self );
avoidtime = 0;
path = NULL;
if ( anim.length() )
{
self.SetAnim( anim );
}
}
qboolean Flee::Evaluate
(
Actor &self
)
{
PathNode *node;
int i;
self.Chatter( "snd_panic", 3 );
if ( path && follow.DoneWithPath( self ) )
{
path = NULL;
if ( !self.currentEnemy || !self.CanSee( self.currentEnemy ) )
{
return false;
}
}
if ( !path )
{
for( i = 0; i < 5; i++ )
{
node = AI_GetNode( ( int )G_Random( ai_maxnode + 1 ) );
if ( node )
{
break;
}
}
if ( node )
{
path = follow.SetPath( self, self.worldorigin, node->worldorigin );
}
else
{
return false;
}
}
follow.SetPosition( self.worldorigin );
follow.SetDir( self.movedir );
follow.SetMaxSpeed( self.movespeed );
follow.Evaluate( self );
if ( avoidtime < level.time )
{
avoidtime = level.time + 0.4;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -