📄 behavior.cpp
字号:
mode = 1;
}
else
{
// skip the ready fire animation
animdone = true;
}
case 1 :
// readying gun
if ( !animdone )
{
aim.SetTarget( self.currentEnemy );
aim.Evaluate( self );
break;
}
// start Aiming
animdone = false;
if ( aimanim.length() )
{
self.SetAnim( aimanim.c_str() );
}
//
// save off time, in case we aim for too long
//
aim_time = level.time + 1;
mode = 2;
case 2 :
// Aiming
if ( !self.currentEnemy )
{
return false;
}
//
// see if we aimed for too long
//
if ( aim_time < level.time )
{
return false;
}
aim.SetTarget( self.currentEnemy );
aim.Evaluate( self );
// don't go into our firing animation until our weapon is ready, and we are on target
if ( self.WeaponReady() && self.currentEnemy && self.CanShoot( self.currentEnemy, true ) )
{
animdone = false;
self.Chatter( "snd_inmysights", 5 );
self.SetAnim( fireanim.c_str(), EV_Actor_NotifyBehavior );
enemy_health = self.currentEnemy->health;
mode = 3;
}
else if ( !self.currentEnemy || self.currentEnemy->deadflag ||
( self.currentEnemy->health <= 0 ) || !self.CanShoot( self.currentEnemy, false ) )
{
// either our enemy is dead, or we can't shoot the enemy from here
if ( self.CurrentWeapon() )
{
self.CurrentWeapon()->ForceReload();
}
return false;
}
break;
case 3 :
// Fire
aim.SetTarget( self.currentEnemy );
aim.Evaluate( self );
if ( animdone )
{
if ( !self.currentEnemy || ( self.currentEnemy->health < enemy_health ) )
self.Chatter( "snd_attacktaunt", 4 );
else
self.Chatter( "snd_missed", 7 );
animdone = false;
numshots++;
if ( ( numshots >= maxshots ) || !self.currentEnemy || self.currentEnemy->deadflag ||
( self.currentEnemy->health <= 0 ) || !self.CanShoot( self.currentEnemy, false ) )
{
// either we're out of shots, our enemy is dead, or we can't shoot the enemy from here
if ( self.CurrentWeapon() )
{
self.CurrentWeapon()->ForceReload();
}
return false;
}
else if ( !self.WeaponReady() || !self.CanShoot( self.currentEnemy, false ) )
{
// weapon not ready or not aimed at enemy, so just keep trying to get enemy in our sights
if ( aimanim.length() )
{
self.SetAnim( aimanim.c_str() );
}
//
// save off time, in case we aim for too long
//
aim_time = level.time + 1;
mode = 2;
}
else
{
// keep firing
self.SetAnim( fireanim.c_str(), EV_Actor_NotifyBehavior );
enemy_health = self.currentEnemy->health;
}
}
break;
}
return true;
}
void AimAndShoot::End
(
Actor &self
)
{
aim.End( self );
self.SetAnim( "idle" );
}
/****************************************************************************
AimAndMelee Class Definition
****************************************************************************/
CLASS_DECLARATION( Behavior, AimAndMelee, NULL );
ResponseDef AimAndMelee::Responses[] =
{
{ &EV_Behavior_Args, ( Response )AimAndMelee::SetArgs },
{ &EV_Behavior_AnimDone, ( Response )AimAndMelee::AnimDone },
{ NULL, NULL }
};
AimAndMelee::AimAndMelee()
{
}
void AimAndMelee::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 AimAndMelee::Begin
(
Actor &self
)
{
mode = 0;
numshots = 0;
maxshots = 2 + G_Random( 4 );
animdone = false;
}
void AimAndMelee::SetArgs
(
Event *ev
)
{
int num;
num = ev->GetInteger( 2 );
maxshots = (num>>1) + G_Random( num );
}
void AimAndMelee::AnimDone
(
Event *ev
)
{
animdone = true;
}
qboolean AimAndMelee::Evaluate
(
Actor &self
)
{
float r;
Vector delta;
switch( mode )
{
case 0 :
if ( !self.has_melee || !self.currentEnemy )
{
return false;
}
delta = self.centroid - self.currentEnemy->centroid;
r = delta.length();
if ( r > self.melee_range )
{
return false;
}
aim.SetTarget( self.currentEnemy );
if ( aim.Evaluate( self ) )
{
break;
}
numshots++;
animdone = false;
// melee
self.SetAnim( "melee", EV_Actor_NotifyBehavior );
self.Chatter( "snd_attacktaunt", 4 );
mode = 1;
case 1 :
// finish up the attack
if ( animdone )
{
if ( numshots < maxshots )
{
mode = 0;
}
else
{
return false;
}
}
break;
}
return true;
}
void AimAndMelee::End
(
Actor &self
)
{
aim.End( self );
self.SetAnim( "idle" );
}
/****************************************************************************
Melee Class Definition
****************************************************************************/
CLASS_DECLARATION( Behavior, Melee, NULL );
ResponseDef Melee::Responses[] =
{
{ &EV_Behavior_Args, ( Response )Melee::SetArgs },
{ &EV_Behavior_AnimDone, ( Response )Melee::AnimDone },
{ NULL, NULL }
};
Melee::Melee()
{
}
void Melee::ShowInfo
(
Actor &self
)
{
Behavior::ShowInfo( self );
gi.printf( "\nmode: %d\n", mode );
gi.printf( "animdone: %d\n", animdone );
}
void Melee::Begin
(
Actor &self
)
{
mode = 0;
animdone = false;
}
void Melee::SetArgs
(
Event *ev
)
{
}
void Melee::AnimDone
(
Event *ev
)
{
animdone = true;
}
qboolean Melee::Evaluate
(
Actor &self
)
{
float r;
Vector delta;
Vector ang;
switch( mode )
{
case 0 :
if ( !self.has_melee || !self.currentEnemy )
{
return false;
}
delta = self.currentEnemy->worldorigin - self.worldorigin;
r = delta.length();
if ( r > self.melee_range )
{
return false;
}
animdone = false;
// melee
ang = delta.toAngles();
ang[ PITCH ] = -ang[ PITCH ];
self.setAngles( ang );
self.SetAnim( "melee", EV_Actor_NotifyBehavior );
self.Chatter( "snd_attacktaunt", 4 );
mode = 1;
case 1 :
// finsh up the attack
if ( animdone )
{
return false;
}
break;
}
return true;
}
void Melee::End
(
Actor &self
)
{
self.SetAnim( "idle" );
}
/****************************************************************************
Repel Class Definition
****************************************************************************/
CLASS_DECLARATION( Behavior, Repel, NULL );
ResponseDef Repel::Responses[] =
{
{ &EV_Behavior_Args, ( Response )Repel::SetArgs },
{ NULL, NULL }
};
void Repel::SetArgs
(
Event *ev
)
{
anim = ev->GetString( 2 );
movegoal = AI_FindNode( ev->GetString( 3 ) );
if ( movegoal )
{
goal = movegoal->worldorigin;
}
speed = ev->GetFloat( 4 );
}
void Repel::ShowInfo
(
Actor &self
)
{
Behavior::ShowInfo( self );
gi.printf( "\nanim: %s\n", anim.c_str() );
gi.printf( "dist: %f\n", dist );
gi.printf( "len: %f\n", len );
gi.printf( "speed: %f\n", speed );
gi.printf( "goal: ( %f, %f, %f )\n", goal.x, goal.y, goal.z );
gi.printf( "start: ( %f, %f, %f )\n", start.x, start.y, start.z );
gi.printf( "dir: ( %f, %f, %f )\n", dir.x, dir.y, dir.z );
}
void Repel::Begin
(
Actor &self
)
{
start.x = goal.x;
start.y = goal.y;
start.z = self.worldorigin.z;
dir = goal - start;
len = dir.length();
dir *= 1 / len;
if ( speed <= 0 )
{
speed = 32;
}
if ( anim.length() )
{
self.SetAnim( anim );
}
dist = -1;
}
qboolean Repel::Evaluate
(
Actor &self
)
{
Vector pos;
qboolean done;
float sp;
trace_t trace;
done = false;
// this is silly, but it works
if ( dist < 0 )
{
sp = 0;
}
else if ( dist < 32 )
{
sp = dist * speed / 32;
}
else if ( ( len - dist ) < 32 )
{
sp = ( len - dist ) * speed / 32;
}
else
{
sp = speed;
}
pos = start + dir * ( dist + sp );
dist = ( pos - start ) * dir;
if ( dist >= (len-1) )
{
pos = goal;
done = true;
}
else if ( dist < 1 )
{
dist = 1;
}
trace = G_Trace( self.worldorigin, self.mins, self.maxs, pos, &self, self.edict->clipmask, "Repel" );
self.setOrigin( trace.endpos );
return !done;
}
void Repel::End
(
Actor &self
)
{
self.SetAnim( "idle" );
}
/****************************************************************************
Pickup Behavior Class Definition
****************************************************************************/
CLASS_DECLARATION( Behavior, PickupAndThrow, NULL );
Event EV_PickupAndThrow_Pickup( "pickup" );
Event EV_PickupAndThrow_Throw( "throw" );
ResponseDef PickupAndThrow::Responses[] =
{
{ &EV_Behavior_Args, ( Response )PickupAndThrow::SetArgs },
{ &EV_Behavior_AnimDone, ( Response )PickupAndThrow::AnimDone },
{ &EV_PickupAndThrow_Pickup,( Response )PickupAndThrow::Pickup },
{ &EV_PickupAndThrow_Throw,( Response )PickupAndThrow::Throw },
{ NULL, NULL }
};
PickupAndThrow::PickupAndThrow()
{
}
void PickupAndThrow::ShowInfo
(
Actor &self
)
{
Behavior::ShowInfo( self );
gi.printf( "\naim:\n" );
aim.ShowInfo( self );
gi.printf( "\nmode: %d\n", mode );
gi.printf( "animdone: %d\n", animdone );
if ( pickup_target )
{
gi.printf( "\npickup_target: #%d '%s'\n", pickup_target->entnum, pickup_target->targetname.c_str() );
}
else
{
gi.printf( "\npickup_target: NULL\n" );
}
}
void PickupAndThrow::Begin
(
Actor &self
)
{
mode = 0;
animdone = false;
}
void PickupAndThrow::SetArgs
(
Event *ev
)
{
pickup_target = ev->GetEntity( 2 );
}
void PickupAndThrow::AnimDone
(
Event *ev
)
{
animdone = true;
}
void PickupAndThrow::Pickup
(
Event *ev
)
{
Entity * ent;
Event * e;
ent = ev->GetEntity( 1 );
if ( pickup_target )
{
e = new Event( EV_ThrowObject_Pickup );
e->AddEntity( ent );
e->AddString( ev->GetString( 2 ) );
pickup_target->ProcessEvent( e );
}
}
void PickupAndThrow::Throw
(
Event *ev
)
{
Actor * act;
Event * e;
act = (Actor *)ev->GetEntity( 1 );
if ( pickup_target )
{
if ( !act->currentEnemy )
return;
e = new Event( EV_ThrowObject_Throw );
e->AddEntity( act );
e->AddFloat( 500 );
e->AddEntity( act->currentEnemy );
e->AddFloat( 1 );
pickup_target->ProcessEvent( e );
}
}
qboolean PickupAndThrow::Evaluate
(
Actor &self
)
{
Event * ev;
if ( !self.currentEnemy || !pickup_target )
return false;
switch( mode )
{
case 0 :
if ( self.HasAnim( "pickup" ) )
{
animdone = false;
self.SetAnim( "pickup", EV_Actor_NotifyBehavior );
mode = 1;
}
else
{
// skip the pickup animation
ev = new Event( EV_PickupAndThrow_Pickup );
ev->AddEntity( &self );
ev->AddString( "gun" );
ProcessEvent( ev );
animdone = true;
}
case 1 :
if ( !animdone )
break;
aim.Begin( self );
mode = 2;
if ( self.HasAnim( "throw_aim" ) )
{
self.SetAnim( "throw_aim", EV_Actor_NotifyBehavior );
}
else
{
self.SetAnim( "idle" );
}
case 2 :
// aim towards our target
aim.SetTarget( self.currentEnemy );
if ( aim.Evaluate( self ) )
{
break;
}
mode = 3;
case 3 :
// Throwing
mode = 4;
if ( self.HasAnim( "throw" ) )
{
animdone = false;
self.SetAnim( "throw", EV_Actor_NotifyBehavior );
mode = 4;
}
else
{
// skip the pickup animation
ev = new Event( EV_PickupAndThrow_Throw );
ev->AddEntity( &self );
ProcessEvent( ev );
animdone = true;
}
break;
case 4 :
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -