📄 behavior.cpp
字号:
avoid.SetMaxSpeed( self.movespeed );
avoid.SetPosition( self.worldorigin );
avoid.SetDir( self.movedir );
avoid.Evaluate( self );
follow.steeringforce += avoid.steeringforce;
}
self.Accelerate( follow.steeringforce );
return true;
}
void Flee::End
(
Actor &self
)
{
avoid.End( self );
follow.End( self );
path = NULL;
}
/****************************************************************************
OpenDoor Class Definition
****************************************************************************/
CLASS_DECLARATION( Behavior, OpenDoor, NULL );
ResponseDef OpenDoor::Responses[] =
{
{ NULL, NULL }
};
OpenDoor::OpenDoor()
{
usedir = false;
}
void OpenDoor::SetArgs
(
Event *ev
)
{
if ( ev->NumArgs() > 1 )
{
dir = ev->GetVector( 2 );
//usedir = true;
}
}
void OpenDoor::ShowInfo
(
Actor &self
)
{
Behavior::ShowInfo( self );
gi.printf( "\ntime: %f\n", time );
gi.printf( "endtime: %f\n", endtime );
gi.printf( "usedir: %d\n", usedir );
gi.printf( "dir: ( %f, %f, %f )\n", dir.x, dir.y, dir.z );
}
void OpenDoor::Begin
(
Actor &self
)
{
Event *e;
trace_t trace;
Entity *ent;
Vector pos;
Vector end;
endtime = 0;
pos = self.worldorigin + self.eyeposition;
if ( usedir )
{
end = pos + dir;
}
else
{
end = pos + Vector( self.orientation[ 0 ] ) * 64;
}
trace = G_Trace( pos, vec_zero, vec_zero, end, &self, self.edict->clipmask, "OpenDoor 1" );
ent = trace.ent->entity;
if ( ent && ent->isSubclassOf( Door ) )
{
self.SetAnim( "idle" );
time = level.time + 0.1;
endtime = time + 1;
e = new Event( EV_Use );
e->AddEntity( &self );
ent->ProcessEvent( e );
}
}
qboolean OpenDoor::Evaluate
(
Actor &self
)
{
trace_t trace;
Vector pos;
if ( level.time > endtime )
{
return false;
}
if ( time < level.time )
{
pos = self.worldorigin + self.eyeposition;
trace = G_Trace( pos, self.mins, self.maxs, pos + Vector( self.orientation[ 0 ] ) * 32, &self, self.edict->clipmask, "OpenDoor 2" );
if ( trace.fraction == 1 )
{
return false;
}
}
return true;
}
void OpenDoor::End
(
Actor &self
)
{
}
/****************************************************************************
PlayAnim Class Definition
****************************************************************************/
CLASS_DECLARATION( Behavior, PlayAnim, NULL );
ResponseDef PlayAnim::Responses[] =
{
{ &EV_Behavior_Args, ( Response )PlayAnim::SetArgs },
{ NULL, NULL }
};
void PlayAnim::SetArgs
(
Event *ev
)
{
anim = ev->GetString( 2 );
}
void PlayAnim::ShowInfo
(
Actor &self
)
{
Behavior::ShowInfo( self );
gi.printf( "\nanim: %s\n", anim.c_str() );
}
void PlayAnim::Begin
(
Actor &self
)
{
if ( anim.length() )
{
if ( !self.SetAnim( anim, EV_Actor_FinishedBehavior ) )
{
//warning( "Begin", "%s does not exist for %s.", anim.c_str(), self.targetname.c_str() );
self.PostEvent( EV_Actor_FinishedBehavior, 0 );
}
}
}
qboolean PlayAnim::Evaluate
(
Actor &self
)
{
return true;
}
void PlayAnim::End
(
Actor &self
)
{
}
/****************************************************************************
Wander Class Definition
****************************************************************************/
/*
CLASS_DECLARATION( Behavior, Wander, NULL );
ResponseDef Wander::Responses[] =
{
{ &EV_Behavior_Args, ( Response )Wander::SetArgs },
{ NULL, NULL }
};
void Wander::SetArgs
(
Event *ev
)
{
anim = ev->GetString( 2 );
maxdistance = ev->GetFloat( 3 );
maxdistance *= maxdistance;
}
PathNode *Wander::FindWanderNode
(
Actor &self
)
{
int i;
PathNode *bestnode;
PathNode *node;
FindCoverPath find;
Path *path;
Vector delta;
float dist;
Vector pos;
int count = 0;
pos = self.worldorigin;
bestnode = NULL;
for ( i = 0; i < 5; i++ )
{
node = AI_GetNode( G_Random( ai_maxnode + 1 ) );
if ( !node )
continue;
delta = node->worldorigin - pos;
dist = delta * delta;
if ( ( dist > 1024 ) && ( dist < maxdistance ) )
{
bestnode = node;
break;
}
}
if ( bestnode )
{
find.heuristic.self = &self;
find.heuristic.setSize( self.size );
find.heuristic.entnum = self.entnum;
path = find.FindPath( self.worldorigin, bestnode->worldorigin );
if ( path )
{
node = path->End();
// Mark node as occupied for a short time
node->occupiedTime = level.time + 1.5;
node->entnum = self.entnum;
chase.SetGoal( node );
chase.SetPath( path );
return node;
}
}
return NULL;
}
void Wander::ShowInfo
(
Actor &self
)
{
Behavior::ShowInfo( self );
gi.printf( "\nchase:\n" );
chase.ShowInfo( self );
gi.printf( "\nanim: %s\n", anim.c_str() );
gi.printf( "state: %d\n", state );
gi.printf( "maxdistance: %f\n", maxdistance );
}
void Wander::Begin
(
Actor &self
)
{
if ( !anim.length() )
{
anim = "walk";
}
movegoal = NULL;
state = 0;
}
qboolean Wander::Evaluate
(
Actor &self
)
{
if ( !movegoal )
{
state = 0;
}
switch( state )
{
case 0 :
chase.Begin( self );
movegoal = FindWanderNode( self );
if ( !movegoal )
{
return false;
}
if ( anim.length() && ( anim != self.animname ) )
{
self.SetAnim( anim );
}
state = 1;
case 1 :
if ( chase.Evaluate( self ) )
{
return true;
}
// Look for another wander node
state = 0;
chase.End( self );
return false;
break;
}
return true;
}
void Wander::End
(
Actor &self
)
{
chase.End( self );
}
*/
/****************************************************************************
FindCover Class Definition
****************************************************************************/
CLASS_DECLARATION( Behavior, FindCover, NULL );
ResponseDef FindCover::Responses[] =
{
{ &EV_Behavior_Args, ( Response )FindCover::SetArgs },
{ NULL, NULL }
};
void FindCover::SetArgs
(
Event *ev
)
{
anim = ev->GetString( 2 );
}
PathNode *FindCover::FindCoverNode
(
Actor &self
)
{
int i;
PathNode *bestnode;
float bestdist;
PathNode *desperatebestnode;
float desperatebestdist;
PathNode *node;
FindCoverPath find;
Path *path;
Vector delta;
float dist;
Vector pos;
pos = self.worldorigin;
bestnode = NULL;
bestdist = 999999999; // greater than ( 8192 * sqr(2) ) ^ 2 -- maximum squared distance
desperatebestnode = NULL;
desperatebestdist = 999999999; // greater than ( 8192 * sqr(2) ) ^ 2 -- maximum squared distance
for( i = 0; i <= ai_maxnode; i++ )
{
node = AI_GetNode( i );
if ( node && ( node->nodeflags & ( AI_DUCK | AI_COVER ) ) &&
( ( 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.CanSeeEnemyFrom( node->worldorigin ) ||//) )//||
( ( node->nodeflags & AI_DUCK ) && !self.CanSeeEnemyFrom( node->worldorigin - Vector( 0, 0, 32 ) ) ) ) )
{
bestnode = node;
bestdist = dist;
}
else if ( ( dist < desperatebestdist ) && ( desperatebestdist > ( 64 * 64 ) ) )
{
desperatebestnode = node;
desperatebestdist = dist;
}
}
}
if ( !bestnode )
{
bestnode = desperatebestnode;
}
if ( bestnode )
{
find.heuristic.self = &self;
find.heuristic.setSize( self.size );
find.heuristic.entnum = self.entnum;
path = find.FindPath( self.worldorigin, bestnode->worldorigin );
if ( path )
{
node = path->End();
// Mark node as occupied for a short time
node->occupiedTime = level.time + 1.5;
node->entnum = self.entnum;
chase.SetGoal( node );
chase.SetPath( path );
return node;
}
}
return NULL;
}
void FindCover::ShowInfo
(
Actor &self
)
{
Behavior::ShowInfo( self );
gi.printf( "\nchase:\n" );
chase.ShowInfo( self );
gi.printf( "\nstate: %d\n", state );
gi.printf( "anim: %s\n", anim.c_str() );
gi.printf( "nextsearch: %f\n", nextsearch );
}
void FindCover::Begin
(
Actor &self
)
{
if ( !anim.length() )
{
anim = "run";
}
movegoal = NULL;
state = 0;
}
qboolean FindCover::Evaluate
(
Actor &self
)
{
if ( !movegoal )
{
state = 0;
}
switch( state )
{
case 0 :
// Checking for cover
chase.Begin( self );
movegoal = FindCoverNode( self );
if ( !movegoal )
{
// Couldn't find any!
return false;
}
// Found cover, 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;
}
if ( movegoal->nodeflags & AI_DUCK )
{
// ducking
self.SetAnim( "crouch_down" );
}
else
{
// standing
self.SetAnim( "idle" );
}
chase.End( self );
return false;
break;
}
return true;
}
void FindCover::End
(
Actor &self
)
{
chase.End( self );
}
/****************************************************************************
FindFlee Class Definition
****************************************************************************/
CLASS_DECLARATION( Behavior, FindFlee, NULL );
ResponseDef FindFlee::Responses[] =
{
{ &EV_Behavior_Args, ( Response )FindFlee::SetArgs },
{ NULL, NULL }
};
void FindFlee::SetArgs
(
Event *ev
)
{
anim = ev->GetString( 2 );
}
PathNode *FindFlee::FindFleeNode
(
Actor &self
)
{
int i;
PathNode *bestnode;
float bestdist;
PathNode *desperatebestnode;
float desperatebestdist;
PathNode *node;
FindFleePath find;
Path *path;
Vector delta;
float dist;
Vector pos;
pos = self.worldorigin;
bestnode = NULL;
bestdist = 999999999; // greater than ( 8192 * sqr(2) ) ^ 2 -- maximum squared distance
desperatebestnode = NULL;
desperatebestdist = 999999999; // greater than ( 8192 * sqr(2) ) ^ 2 -- maximum squared distance
for( i = 0; i <= ai_maxnode; i++ )
{
node = AI_GetNode( i );
if ( node && ( node->nodeflags & AI_FLEE ) &&
( ( 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.CanSeeEnemyFrom( node->worldorigin ) )
{
bestnode = node;
bestdist = dist;
}
else if ( ( dist < desperatebestdist ) && ( desperatebestdist > ( 64 * 64 ) ) )
{
desperatebestnode = node;
desperatebestdist = dist;
}
}
}
if ( !bestnode )
{
bestnode = desperatebestnode;
}
if ( bestnode )
{
find.heuristic.self = &self;
find.heuristic.setSize( self.size );
find.heuristic.entnum = self.entnum;
path = find.FindPath( self.worldorigin, bestnode->worldorigin );
if ( path )
{
node = path->End();
// Mark node as occupied for a short time
node->occupiedTime = level.time + 1.5;
node->entnum = self.entnum;
chase.SetGoal( node );
chase.SetPath( path );
return node;
}
}
return NULL;
}
void FindFlee::ShowInfo
(
Actor &self
)
{
Behavior::ShowInfo( self );
gi.printf( "\nchase:\n" );
chase.ShowInfo( self );
gi.printf( "\nstate: %d\n", state );
gi.printf( "anim: %s\n", anim.c_str() );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -