822 lines
22 KiB
C++
822 lines
22 KiB
C++
|
|
#include "../../idlib/precompiled.h"
|
|
#pragma hdrstop
|
|
|
|
#include "../Game_local.h"
|
|
|
|
class rvMonsterNetworkGuardian : public idAI {
|
|
public:
|
|
|
|
CLASS_PROTOTYPE( rvMonsterNetworkGuardian );
|
|
|
|
rvMonsterNetworkGuardian ( void );
|
|
|
|
void Spawn ( void );
|
|
|
|
void Save ( idSaveGame *savefile ) const;
|
|
void Restore ( idRestoreGame *savefile );
|
|
|
|
protected:
|
|
|
|
virtual bool CheckActions ( void );
|
|
|
|
int shots;
|
|
int landTime;
|
|
|
|
int flagFlying;
|
|
|
|
float strafeSpeed;
|
|
|
|
//this flag allows the AI to control when it takes off and lands.
|
|
bool flagAutopilot;
|
|
|
|
int battleStage;
|
|
|
|
enum {
|
|
FLY_NONE = 0,
|
|
FLY_TRANSITION,
|
|
FLY_FLYING,
|
|
};
|
|
|
|
private:
|
|
|
|
rvAIAction actionShotgunRocketAttack;
|
|
rvAIAction actionFlyingRangedAttack;
|
|
rvAIAction actionFlyingSweepAttack;
|
|
rvAIAction actionMeleeAttack;
|
|
rvAIAction actionBlasterSweepGround;
|
|
rvAIAction actionBlasterAttack;
|
|
rvAIAction actionMIRVAttack;
|
|
|
|
|
|
|
|
stateResult_t State_Wait_Flying ( const stateParms_t& parms );
|
|
|
|
// stateResult_t State_Dead ( const stateParms_t& parms );
|
|
|
|
// walking melee attacks
|
|
|
|
// walking ranged attacks
|
|
stateResult_t State_Torso_ShotgunRocket ( const stateParms_t& parms );
|
|
stateResult_t State_Torso_BlasterSweepGround ( const stateParms_t& parms );
|
|
stateResult_t State_Torso_BlasterAttack ( const stateParms_t& parms );
|
|
stateResult_t State_Torso_MIRVAttack ( const stateParms_t& parms );
|
|
|
|
//flying evades
|
|
stateResult_t State_Torso_EvadeLeft ( const stateParms_t& parms );
|
|
stateResult_t State_Torso_EvadeRight ( const stateParms_t& parms );
|
|
|
|
//flying ranged attacks
|
|
stateResult_t State_Torso_FlyingRanged ( const stateParms_t& parms );
|
|
stateResult_t State_Torso_FlyingSweep ( const stateParms_t& parms );
|
|
|
|
// flying anims
|
|
stateResult_t State_Torso_LiftOff ( const stateParms_t& parms );
|
|
stateResult_t State_Torso_Fall ( const stateParms_t& parms );
|
|
// walking turn anims
|
|
stateResult_t State_Torso_TurnRight90 ( const stateParms_t& parms );
|
|
stateResult_t State_Torso_TurnLeft90 ( const stateParms_t& parms );
|
|
|
|
|
|
//force the NG into walking mode. This does not play the landing anim, and will make him fall from the sky.
|
|
void Event_ForceWalkMode( void );
|
|
|
|
//These commands change the NG's state, but do so through states and animations.
|
|
void Event_ForceLanding( void );
|
|
void Event_ForceTakeoff( void );
|
|
|
|
//toggles the NG between AI controlled flight and script controlled flight
|
|
void Event_AllowAutopilot( float f);
|
|
|
|
//for staged combat, sets the int value of the battle stage
|
|
void Event_SetBattleStage( float f);
|
|
|
|
CLASS_STATES_PROTOTYPE ( rvMonsterNetworkGuardian );
|
|
};
|
|
|
|
const idEventDef EV_ForceWalkMode( "forceWalkMode" );
|
|
const idEventDef EV_ForceLanding( "forceLanding" );
|
|
const idEventDef EV_ForceTakeoff( "forceTakeoff" );
|
|
const idEventDef EV_AllowAutopilot( "allowAutopilot", "f" );
|
|
const idEventDef EV_SetBattleStage( "setBattleStage", "f" );
|
|
|
|
|
|
CLASS_DECLARATION( idAI, rvMonsterNetworkGuardian )
|
|
EVENT( EV_ForceWalkMode, rvMonsterNetworkGuardian::Event_ForceWalkMode )
|
|
EVENT( EV_ForceLanding, rvMonsterNetworkGuardian::Event_ForceLanding )
|
|
EVENT( EV_ForceTakeoff, rvMonsterNetworkGuardian::Event_ForceTakeoff )
|
|
EVENT( EV_AllowAutopilot, rvMonsterNetworkGuardian::Event_AllowAutopilot )
|
|
EVENT( EV_SetBattleStage, rvMonsterNetworkGuardian::Event_SetBattleStage )
|
|
|
|
END_CLASS
|
|
|
|
/*
|
|
================
|
|
rvMonsterNetworkGuardian::rvMonsterNetworkGuardian
|
|
================
|
|
*/
|
|
rvMonsterNetworkGuardian::rvMonsterNetworkGuardian ( ) {
|
|
shots = 0;
|
|
landTime = 0;
|
|
flagFlying = FLY_NONE;
|
|
battleStage = 1;
|
|
strafeSpeed = 0;
|
|
|
|
}
|
|
|
|
/*
|
|
================
|
|
rvMonsterNetworkGuardian::Spawn
|
|
================
|
|
*/
|
|
void rvMonsterNetworkGuardian::Spawn ( void ) {
|
|
|
|
disablePain = true;
|
|
flagAutopilot = false;
|
|
|
|
strafeSpeed = spawnArgs.GetFloat( "strafeSpeed", "500" );
|
|
|
|
actionShotgunRocketAttack.Init ( spawnArgs, "action_ShotgunRocket", "Torso_ShotgunRocket_Attack", AIACTIONF_ATTACK );
|
|
actionFlyingRangedAttack.Init( spawnArgs, "action_FlyingRangedAttack", "Torso_FlyingRanged_Attack", AIACTIONF_ATTACK );
|
|
actionFlyingSweepAttack.Init( spawnArgs, "action_blasterSweepAirAttack", "Torso_FlyingSweep_Attack", AIACTIONF_ATTACK );
|
|
actionMeleeAttack.Init( spawnArgs, "action_meleeAttack", NULL, AIACTIONF_ATTACK );
|
|
actionBlasterSweepGround.Init( spawnArgs, "action_blasterSweepGroundAttack", "Torso_BlasterSweepGround_Attack", AIACTIONF_ATTACK );
|
|
actionBlasterAttack.Init( spawnArgs, "action_blasterAttack", "Torso_Blaster_Attack", AIACTIONF_ATTACK );
|
|
actionMIRVAttack.Init( spawnArgs, "action_MIRVAttack", "Torso_MIRV_Attack", AIACTIONF_ATTACK );
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
================
|
|
rvMonsterNetworkGuardian::Save
|
|
================
|
|
*/
|
|
void rvMonsterNetworkGuardian::Save ( idSaveGame *savefile ) const {
|
|
savefile->WriteInt( shots );
|
|
savefile->WriteInt( landTime );
|
|
savefile->WriteInt( flagFlying );
|
|
savefile->WriteInt( battleStage );
|
|
savefile->WriteBool( flagAutopilot );
|
|
savefile->WriteFloat( strafeSpeed );
|
|
|
|
actionShotgunRocketAttack.Save( savefile );
|
|
actionFlyingRangedAttack.Save( savefile );
|
|
actionFlyingSweepAttack.Save( savefile );
|
|
actionMeleeAttack.Save( savefile );
|
|
actionBlasterSweepGround.Save( savefile );
|
|
actionBlasterAttack.Save( savefile );
|
|
actionMIRVAttack.Save( savefile );
|
|
}
|
|
|
|
/*
|
|
================
|
|
rvMonsterNetworkGuardian::Restore
|
|
================
|
|
*/
|
|
void rvMonsterNetworkGuardian::Restore ( idRestoreGame *savefile )
|
|
{
|
|
savefile->ReadInt( shots );
|
|
savefile->ReadInt( landTime );
|
|
savefile->ReadInt( flagFlying );
|
|
savefile->ReadInt( battleStage );
|
|
savefile->ReadBool( flagAutopilot );
|
|
savefile->ReadFloat( strafeSpeed );
|
|
|
|
actionShotgunRocketAttack.Restore( savefile );
|
|
actionFlyingRangedAttack.Restore( savefile );
|
|
actionFlyingSweepAttack.Restore( savefile );
|
|
actionMeleeAttack.Restore( savefile );
|
|
actionBlasterSweepGround.Restore( savefile );
|
|
actionBlasterAttack.Restore( savefile );
|
|
actionMIRVAttack.Restore( savefile );
|
|
}
|
|
|
|
/*
|
|
================
|
|
rvMonsterNetworkGuardian::CheckActions
|
|
================
|
|
*/
|
|
bool rvMonsterNetworkGuardian::CheckActions ( void ) {
|
|
// If not moving, try turning in place
|
|
if ( !move.fl.moving && gameLocal.time > combat.investigateTime )
|
|
{
|
|
float turnYaw = idMath::AngleNormalize180 ( move.ideal_yaw - move.current_yaw ) ;
|
|
if ( turnYaw > lookMax[YAW] * 0.75f )
|
|
{
|
|
PerformAction ( "Torso_TurnRight90", 4, true );
|
|
return true;
|
|
}
|
|
else if ( turnYaw < -lookMax[YAW] * 0.75f )
|
|
{
|
|
PerformAction ( "Torso_TurnLeft90", 4, true );
|
|
return true;
|
|
}
|
|
}
|
|
|
|
//if the flight is transitioning, do nothing
|
|
if( flagFlying == FLY_TRANSITION ) {
|
|
return false;
|
|
}
|
|
|
|
//this is the autopilot section.
|
|
if( flagAutopilot ) {
|
|
// If he's been on the ground long enough, fly...
|
|
if ( move.moveType == MOVETYPE_ANIM && move.fl.onGround && !flagFlying && gameLocal.time > landTime )
|
|
{
|
|
PostState ( "Wait_Flying" );
|
|
SetAnimState ( ANIMCHANNEL_TORSO, "Torso_LiftOff", 4 );
|
|
disablePain = true;
|
|
actionMeleeAttack.fl.disabled = true;
|
|
flagFlying = FLY_TRANSITION;
|
|
return true;
|
|
}
|
|
else if ( move.moveType == MOVETYPE_FLY && gameLocal.time > landTime )
|
|
{
|
|
SetMoveType ( MOVETYPE_ANIM );
|
|
animPrefix = "";
|
|
move.fl.noGravity = false;
|
|
physicsObj.UseFlyMove ( false );
|
|
actionMeleeAttack.fl.disabled = false;
|
|
flagFlying = FLY_TRANSITION;
|
|
|
|
SetAnimState ( ANIMCHANNEL_TORSO, "Torso_Fall", 4 );
|
|
PostAnimState ( ANIMCHANNEL_TORSO, "Torso_FinishAction", 0, SFLAG_ONCLEAR );
|
|
PostAnimState ( ANIMCHANNEL_TORSO, "Torso_Idle", 4 );
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
//Normal actions here -----------
|
|
|
|
//if he's close enough for melee, use melee
|
|
if( flagFlying == FLY_NONE) {
|
|
if( PerformAction ( &actionMeleeAttack, (checkAction_t)&idAI::CheckAction_MeleeAttack, NULL ) ) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
//check for ranged attacks on the ground
|
|
if( flagFlying == FLY_NONE ) {
|
|
|
|
switch (battleStage) {
|
|
|
|
case 1:
|
|
if( PerformAction ( &actionShotgunRocketAttack, (checkAction_t)&idAI::CheckAction_RangedAttack, &actionTimerRangedAttack ) ||
|
|
PerformAction ( &actionBlasterAttack, (checkAction_t)&idAI::CheckAction_RangedAttack, &actionTimerRangedAttack ) ||
|
|
PerformAction ( &actionBlasterSweepGround, (checkAction_t)&idAI::CheckAction_RangedAttack, &actionTimerRangedAttack ) ) {
|
|
return true;
|
|
}
|
|
break;
|
|
case 2:
|
|
if( PerformAction ( &actionMIRVAttack, (checkAction_t)&idAI::CheckAction_RangedAttack, &actionTimerRangedAttack ) ||
|
|
PerformAction ( &actionBlasterAttack, (checkAction_t)&idAI::CheckAction_RangedAttack, &actionTimerRangedAttack ) ||
|
|
PerformAction ( &actionBlasterSweepGround, (checkAction_t)&idAI::CheckAction_RangedAttack, &actionTimerRangedAttack ) ||
|
|
PerformAction ( &actionShotgunRocketAttack, (checkAction_t)&idAI::CheckAction_RangedAttack, &actionTimerRangedAttack ) ) {
|
|
return true;
|
|
}
|
|
break;
|
|
default:
|
|
gameLocal.Error("Bad battleStage '%d' set for Network Guardian.", battleStage);
|
|
break;
|
|
}
|
|
|
|
}
|
|
//airborne attack actions
|
|
if( (flagFlying == FLY_FLYING) ) {
|
|
|
|
if( PerformAction ( &actionEvadeLeft, (checkAction_t)&idAI::CheckAction_EvadeLeft, &actionTimerEvade ) ||
|
|
PerformAction ( &actionEvadeRight, (checkAction_t)&idAI::CheckAction_EvadeRight, &actionTimerEvade ) ||
|
|
PerformAction ( &actionFlyingRangedAttack, (checkAction_t)&idAI::CheckAction_RangedAttack, &actionTimerRangedAttack ) ||
|
|
PerformAction ( &actionFlyingSweepAttack, (checkAction_t)&idAI::CheckAction_RangedAttack, &actionTimerRangedAttack ) ){
|
|
return true;
|
|
}
|
|
}
|
|
|
|
//No.
|
|
//return idAI::CheckActions ( );
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
===============================================================================
|
|
|
|
Events
|
|
|
|
===============================================================================
|
|
*/
|
|
|
|
/*
|
|
================
|
|
rvMonsterNetworkGuardian::Event_ForceWalkMode
|
|
================
|
|
*/
|
|
// forces NG to obey gravity and immediately switch to walking mode.
|
|
void rvMonsterNetworkGuardian::Event_ForceWalkMode( void ) {
|
|
|
|
SetMoveType ( MOVETYPE_ANIM );
|
|
animPrefix = "";
|
|
move.fl.noGravity = false;
|
|
physicsObj.UseFlyMove ( false );
|
|
actionMeleeAttack.fl.disabled = false;
|
|
move.fl.allowDirectional = false;
|
|
flagFlying = FLY_NONE;
|
|
|
|
}
|
|
|
|
/*
|
|
================
|
|
rvMonsterNetworkGuardian::Event_ForceLanding
|
|
================
|
|
*/
|
|
// forces NG play his landing animation. He will not just fall from the sky.
|
|
void rvMonsterNetworkGuardian::Event_ForceLanding( void ) {
|
|
|
|
SetMoveType ( MOVETYPE_ANIM );
|
|
animPrefix = "";
|
|
move.fl.noGravity = false;
|
|
physicsObj.UseFlyMove ( false );
|
|
actionMeleeAttack.fl.disabled = false;
|
|
move.fl.allowDirectional = false;
|
|
flagFlying = FLY_TRANSITION;
|
|
|
|
SetAnimState ( ANIMCHANNEL_TORSO, "Torso_Fall", 4 );
|
|
PostAnimState ( ANIMCHANNEL_TORSO, "Torso_FinishAction", 0, SFLAG_ONCLEAR );
|
|
//PostAnimState ( ANIMCHANNEL_TORSO, "Torso_Idle", 4 );
|
|
|
|
}
|
|
|
|
/*
|
|
================
|
|
rvMonsterNetworkGuardian::Event_ForceTakeoff
|
|
================
|
|
*/
|
|
// forces NG to take off and fly.
|
|
void rvMonsterNetworkGuardian::Event_ForceTakeoff( void ) {
|
|
|
|
disablePain = true;
|
|
actionMeleeAttack.fl.disabled = true;
|
|
flagFlying = FLY_TRANSITION;
|
|
SetAnimState ( ANIMCHANNEL_TORSO, "Torso_LiftOff", 4 );
|
|
move.fl.allowDirectional = true;
|
|
SetState ( "Wait_Flying" );
|
|
|
|
}
|
|
|
|
/*
|
|
================
|
|
rvMonsterNetworkGuardian::Event_AllowAutoPilot
|
|
================
|
|
*/
|
|
// toggles the AI autoPilot for deciding when to fly and land.
|
|
void rvMonsterNetworkGuardian::Event_AllowAutopilot( float f ) {
|
|
|
|
flagAutopilot = f ? true : false;
|
|
|
|
}
|
|
|
|
/*
|
|
================
|
|
rvMonsterNetworkGuardian::Event_SetBattleStage
|
|
================
|
|
*/
|
|
// sets the current battle stage. Each stage has different behaviors.
|
|
void rvMonsterNetworkGuardian::Event_SetBattleStage( float f ) {
|
|
|
|
battleStage = f;
|
|
|
|
}
|
|
/*
|
|
===============================================================================
|
|
|
|
States
|
|
|
|
===============================================================================
|
|
*/
|
|
|
|
CLASS_STATES_DECLARATION ( rvMonsterNetworkGuardian )
|
|
STATE ( "Wait_Flying", rvMonsterNetworkGuardian::State_Wait_Flying )
|
|
STATE ( "State_Dead", rvMonsterNetworkGuardian::State_Dead )
|
|
|
|
STATE ( "Torso_ShotgunRocket_Attack", rvMonsterNetworkGuardian::State_Torso_ShotgunRocket )
|
|
STATE ( "Torso_BlasterSweepGround_Attack", rvMonsterNetworkGuardian::State_Torso_BlasterSweepGround )
|
|
STATE ( "Torso_Blaster_Attack", rvMonsterNetworkGuardian::State_Torso_BlasterAttack )
|
|
STATE ( "Torso_MIRV_Attack", rvMonsterNetworkGuardian::State_Torso_MIRVAttack)
|
|
|
|
STATE ( "Torso_EvadeLeft", rvMonsterNetworkGuardian::State_Torso_EvadeLeft )
|
|
STATE ( "Torso_EvadeRight", rvMonsterNetworkGuardian::State_Torso_EvadeRight )
|
|
|
|
STATE ( "Torso_FlyingRanged_Attack", rvMonsterNetworkGuardian::State_Torso_FlyingRanged )
|
|
STATE ( "Torso_FlyingSweep_Attack", rvMonsterNetworkGuardian::State_Torso_FlyingSweep )
|
|
|
|
STATE ( "Torso_LiftOff", rvMonsterNetworkGuardian::State_Torso_LiftOff )
|
|
STATE ( "Torso_Fall", rvMonsterNetworkGuardian::State_Torso_Fall )
|
|
|
|
STATE ( "Torso_TurnRight90", rvMonsterNetworkGuardian::State_Torso_TurnRight90 )
|
|
STATE ( "Torso_TurnLeft90", rvMonsterNetworkGuardian::State_Torso_TurnLeft90 )
|
|
|
|
END_CLASS_STATES
|
|
|
|
|
|
stateResult_t rvMonsterNetworkGuardian::State_Torso_EvadeLeft ( const stateParms_t& parms ) {
|
|
enum {
|
|
STAGE_INIT,
|
|
STAGE_WAIT
|
|
};
|
|
switch ( parms.stage ) {
|
|
case STAGE_INIT:
|
|
{
|
|
idVec3 vel = GetPhysics()->GetLinearVelocity();
|
|
vel += viewAxis[1] * strafeSpeed;
|
|
physicsObj.UseVelocityMove( true );
|
|
GetPhysics()->SetLinearVelocity( vel );
|
|
PlayAnim ( ANIMCHANNEL_TORSO, "evade_left", parms.blendFrames );
|
|
}
|
|
return SRESULT_STAGE ( STAGE_WAIT );
|
|
|
|
case STAGE_WAIT:
|
|
if ( AnimDone ( ANIMCHANNEL_TORSO, parms.blendFrames ) ) {
|
|
return SRESULT_DONE;
|
|
}
|
|
return SRESULT_WAIT;
|
|
}
|
|
return SRESULT_ERROR;
|
|
}
|
|
|
|
stateResult_t rvMonsterNetworkGuardian::State_Torso_EvadeRight ( const stateParms_t& parms ) {
|
|
enum {
|
|
STAGE_INIT,
|
|
STAGE_WAIT
|
|
};
|
|
switch ( parms.stage ) {
|
|
case STAGE_INIT:
|
|
{
|
|
idVec3 vel = GetPhysics()->GetLinearVelocity();
|
|
vel += viewAxis[1] * -strafeSpeed;
|
|
physicsObj.UseVelocityMove( true );
|
|
GetPhysics()->SetLinearVelocity( vel );
|
|
PlayAnim ( ANIMCHANNEL_TORSO, "evade_right", parms.blendFrames );
|
|
}
|
|
return SRESULT_STAGE ( STAGE_WAIT );
|
|
|
|
case STAGE_WAIT:
|
|
if ( AnimDone ( ANIMCHANNEL_TORSO, parms.blendFrames ) ) {
|
|
return SRESULT_DONE;
|
|
}
|
|
return SRESULT_WAIT;
|
|
}
|
|
return SRESULT_ERROR;
|
|
}
|
|
|
|
|
|
/*
|
|
================
|
|
rvMonsterNetworkGuardian::State_Torso_ShotgunRocket
|
|
================
|
|
*/
|
|
stateResult_t rvMonsterNetworkGuardian::State_Torso_ShotgunRocket ( const stateParms_t& parms ) {
|
|
enum {
|
|
STAGE_INIT,
|
|
STAGE_WAIT
|
|
};
|
|
|
|
switch( parms.stage ) {
|
|
case STAGE_INIT:
|
|
DisableAnimState ( ANIMCHANNEL_LEGS );
|
|
PlayAnim ( ANIMCHANNEL_TORSO, "shotgunRocket_attack", parms.blendFrames );
|
|
return SRESULT_STAGE ( STAGE_WAIT);
|
|
|
|
case STAGE_WAIT:
|
|
if ( AnimDone ( ANIMCHANNEL_TORSO, 4 ) ) {
|
|
return SRESULT_DONE;
|
|
}
|
|
return SRESULT_WAIT;
|
|
|
|
}
|
|
|
|
return SRESULT_ERROR;
|
|
|
|
}
|
|
|
|
/*
|
|
================
|
|
rvMonsterNetworkGuardian::State_Torso_BlasterSweepGround
|
|
================
|
|
*/
|
|
stateResult_t rvMonsterNetworkGuardian::State_Torso_BlasterSweepGround ( const stateParms_t& parms ) {
|
|
enum {
|
|
STAGE_INIT,
|
|
STAGE_WAIT
|
|
};
|
|
|
|
switch( parms.stage ) {
|
|
case STAGE_INIT:
|
|
DisableAnimState ( ANIMCHANNEL_LEGS );
|
|
PlayAnim ( ANIMCHANNEL_TORSO, "attack_spray_grd", parms.blendFrames );
|
|
return SRESULT_STAGE ( STAGE_WAIT);
|
|
|
|
case STAGE_WAIT:
|
|
if ( AnimDone ( ANIMCHANNEL_TORSO, 4 ) ) {
|
|
return SRESULT_DONE;
|
|
}
|
|
return SRESULT_WAIT;
|
|
|
|
}
|
|
|
|
return SRESULT_ERROR;
|
|
|
|
}
|
|
/*
|
|
================
|
|
rvMonsterNetworkGuardian::State_Torso_FlyingSweep
|
|
================
|
|
*/
|
|
stateResult_t rvMonsterNetworkGuardian::State_Torso_FlyingSweep ( const stateParms_t& parms ) {
|
|
enum {
|
|
STAGE_INIT,
|
|
STAGE_WAIT
|
|
};
|
|
|
|
switch( parms.stage ) {
|
|
case STAGE_INIT:
|
|
DisableAnimState ( ANIMCHANNEL_LEGS );
|
|
PlayAnim ( ANIMCHANNEL_TORSO, "attack_spray_air", parms.blendFrames );
|
|
return SRESULT_STAGE ( STAGE_WAIT);
|
|
|
|
case STAGE_WAIT:
|
|
if ( AnimDone ( ANIMCHANNEL_TORSO, 4 ) ) {
|
|
return SRESULT_DONE;
|
|
}
|
|
return SRESULT_WAIT;
|
|
|
|
}
|
|
|
|
return SRESULT_ERROR;
|
|
|
|
}
|
|
|
|
/*
|
|
================
|
|
rvMonsterNetworkGuardian::State_Torso_FlyingRanged
|
|
================
|
|
*/
|
|
stateResult_t rvMonsterNetworkGuardian::State_Torso_FlyingRanged ( const stateParms_t& parms ) {
|
|
enum {
|
|
STAGE_INIT,
|
|
STAGE_WAIT
|
|
};
|
|
|
|
switch( parms.stage ) {
|
|
case STAGE_INIT:
|
|
DisableAnimState ( ANIMCHANNEL_LEGS );
|
|
PlayAnim ( ANIMCHANNEL_TORSO, "flyingRanged_attack", parms.blendFrames );
|
|
return SRESULT_STAGE ( STAGE_WAIT);
|
|
|
|
case STAGE_WAIT:
|
|
if ( AnimDone ( ANIMCHANNEL_TORSO, 4 ) ) {
|
|
return SRESULT_DONE;
|
|
}
|
|
return SRESULT_WAIT;
|
|
|
|
}
|
|
|
|
return SRESULT_ERROR;
|
|
|
|
}
|
|
|
|
/*
|
|
================
|
|
rvMonsterNetworkGuardian::State_Torso_MIRVAttack
|
|
================
|
|
*/
|
|
stateResult_t rvMonsterNetworkGuardian::State_Torso_MIRVAttack ( const stateParms_t& parms ) {
|
|
enum {
|
|
STAGE_INIT,
|
|
STAGE_WAIT
|
|
};
|
|
|
|
switch( parms.stage ) {
|
|
case STAGE_INIT:
|
|
DisableAnimState ( ANIMCHANNEL_LEGS );
|
|
PlayAnim ( ANIMCHANNEL_TORSO, "attack_vert", parms.blendFrames );
|
|
return SRESULT_STAGE ( STAGE_WAIT);
|
|
|
|
case STAGE_WAIT:
|
|
if ( AnimDone ( ANIMCHANNEL_TORSO, 4 ) ) {
|
|
return SRESULT_DONE;
|
|
}
|
|
return SRESULT_WAIT;
|
|
|
|
}
|
|
|
|
return SRESULT_ERROR;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
================
|
|
rvMonsterNetworkGuardian::State_Wait_Flying
|
|
================
|
|
*/
|
|
stateResult_t rvMonsterNetworkGuardian::State_Wait_Flying ( const stateParms_t& parms ) {
|
|
if ( move.moveType == MOVETYPE_ANIM ) {
|
|
return SRESULT_WAIT;
|
|
}
|
|
return SRESULT_DONE;
|
|
}
|
|
|
|
/*
|
|
================
|
|
rvMonsterNetworkGuardian::State_Dead
|
|
================
|
|
*/
|
|
/*
|
|
stateResult_t rvMonsterNetworkGuardian::State_Dead ( const stateParms_t& parms ) {
|
|
return SRESULT_DONE;
|
|
}*/
|
|
|
|
/*
|
|
================
|
|
rvMonsterNetworkGuardian::State_Torso_LiftOff
|
|
================
|
|
*/
|
|
stateResult_t rvMonsterNetworkGuardian::State_Torso_LiftOff ( const stateParms_t& parms ) {
|
|
enum {
|
|
STAGE_INIT,
|
|
STAGE_WAIT,
|
|
};
|
|
switch ( parms.stage ) {
|
|
case STAGE_INIT:
|
|
move.fl.noGravity = true;
|
|
DisableAnimState ( ANIMCHANNEL_LEGS );
|
|
PlayAnim ( ANIMCHANNEL_TORSO, "liftoff", parms.blendFrames );
|
|
return SRESULT_STAGE ( STAGE_WAIT );
|
|
|
|
case STAGE_WAIT:
|
|
if ( AnimDone ( ANIMCHANNEL_TORSO, 4 ) ) {
|
|
SetMoveType ( MOVETYPE_FLY );
|
|
landTime = gameLocal.time + DelayTime ( 5000, 10000 );
|
|
animPrefix = "fly";
|
|
SetAnimState ( ANIMCHANNEL_TORSO, "Torso_Idle", 4 );
|
|
SetAnimState ( ANIMCHANNEL_LEGS, "Legs_Idle", 4 );
|
|
flagFlying = FLY_FLYING;
|
|
return SRESULT_DONE;
|
|
}
|
|
return SRESULT_WAIT;
|
|
}
|
|
return SRESULT_ERROR;
|
|
}
|
|
|
|
/*
|
|
================
|
|
rvMonsterNetworkGuardian::State_Torso_Fall
|
|
================
|
|
*/
|
|
stateResult_t rvMonsterNetworkGuardian::State_Torso_Fall ( const stateParms_t& parms ) {
|
|
enum {
|
|
STAGE_FALLSTART,
|
|
STAGE_FALLSTARTWAIT,
|
|
STAGE_FALLLOOPWAIT,
|
|
STAGE_FALLENDWAIT
|
|
};
|
|
switch ( parms.stage ) {
|
|
case STAGE_FALLSTART:
|
|
DisableAnimState ( ANIMCHANNEL_LEGS );
|
|
PlayAnim ( ANIMCHANNEL_TORSO, "fly_descend_start", parms.blendFrames );
|
|
return SRESULT_STAGE ( STAGE_FALLSTARTWAIT );
|
|
|
|
case STAGE_FALLSTARTWAIT:
|
|
if ( move.fl.onGround ) {
|
|
PlayAnim ( ANIMCHANNEL_TORSO, "fly_descend_end", 4 );
|
|
return SRESULT_STAGE ( STAGE_FALLENDWAIT );
|
|
}
|
|
if ( AnimDone ( ANIMCHANNEL_TORSO, 0 ) ) {
|
|
PlayAnim ( ANIMCHANNEL_TORSO, "fly_descend_loop", 0 );
|
|
return SRESULT_STAGE ( STAGE_FALLLOOPWAIT );
|
|
}
|
|
return SRESULT_WAIT;
|
|
|
|
case STAGE_FALLLOOPWAIT:
|
|
if ( move.fl.onGround ) {
|
|
PlayAnim ( ANIMCHANNEL_TORSO, "fly_descend_end", 0 );
|
|
return SRESULT_STAGE ( STAGE_FALLENDWAIT );
|
|
}
|
|
return SRESULT_WAIT;
|
|
|
|
case STAGE_FALLENDWAIT:
|
|
if ( AnimDone ( ANIMCHANNEL_TORSO, 4 ) ) {
|
|
// we've landed! determine the next fly time
|
|
landTime = gameLocal.time + DelayTime ( 10000, 15000 );
|
|
flagFlying = FLY_NONE;
|
|
return SRESULT_DONE;
|
|
}
|
|
return SRESULT_WAIT;
|
|
}
|
|
return SRESULT_ERROR;
|
|
}
|
|
|
|
//================
|
|
//rvMonsterNetworkGuardian::State_Torso_TurnRight90
|
|
//================
|
|
stateResult_t rvMonsterNetworkGuardian::State_Torso_TurnRight90 ( const stateParms_t& parms ) {
|
|
enum {
|
|
STAGE_INIT,
|
|
STAGE_WAIT
|
|
};
|
|
switch ( parms.stage ) {
|
|
case STAGE_INIT:
|
|
DisableAnimState ( ANIMCHANNEL_LEGS );
|
|
PlayAnim ( ANIMCHANNEL_TORSO, "turn_left", parms.blendFrames );
|
|
AnimTurn ( 90.0f, true );
|
|
return SRESULT_STAGE ( STAGE_WAIT );
|
|
|
|
case STAGE_WAIT:
|
|
if ( move.fl.moving || AnimDone ( ANIMCHANNEL_TORSO, 0 )) {
|
|
AnimTurn ( 0, true );
|
|
combat.investigateTime = gameLocal.time + 250;
|
|
return SRESULT_DONE;
|
|
}
|
|
return SRESULT_WAIT;
|
|
}
|
|
return SRESULT_ERROR;
|
|
}
|
|
|
|
//================
|
|
//rvMonsterNetworkGuardian::State_Torso_TurnLeft90
|
|
//================
|
|
stateResult_t rvMonsterNetworkGuardian::State_Torso_TurnLeft90 ( const stateParms_t& parms ) {
|
|
enum {
|
|
STAGE_INIT,
|
|
STAGE_WAIT
|
|
};
|
|
switch ( parms.stage ) {
|
|
case STAGE_INIT:
|
|
DisableAnimState ( ANIMCHANNEL_LEGS );
|
|
PlayAnim ( ANIMCHANNEL_TORSO, "turn_right", parms.blendFrames );
|
|
AnimTurn ( 90.0f, true );
|
|
return SRESULT_STAGE ( STAGE_WAIT );
|
|
|
|
case STAGE_WAIT:
|
|
if ( move.fl.moving || AnimDone ( ANIMCHANNEL_TORSO, 0 )) {
|
|
AnimTurn ( 0, true );
|
|
combat.investigateTime = gameLocal.time + 250;
|
|
return SRESULT_DONE;
|
|
}
|
|
return SRESULT_WAIT;
|
|
}
|
|
return SRESULT_ERROR;
|
|
}
|
|
|
|
//================
|
|
//rvMonsterNetworkGuardian::State_Torso_BlasterAttack
|
|
//================
|
|
stateResult_t rvMonsterNetworkGuardian::State_Torso_BlasterAttack ( const stateParms_t& parms ) {
|
|
|
|
enum {
|
|
STAGE_INIT,
|
|
STAGE_WAITSTART,
|
|
STAGE_LOOP,
|
|
STAGE_WAITLOOP,
|
|
STAGE_WAITEND
|
|
};
|
|
switch ( parms.stage ) {
|
|
case STAGE_INIT:
|
|
//if flying, do not override legs
|
|
if( (flagFlying != FLY_NONE ) && move.fl.moving ) {
|
|
DisableAnimState ( ANIMCHANNEL_LEGS );
|
|
}
|
|
PlayAnim ( ANIMCHANNEL_TORSO, "attack_blaster_start", parms.blendFrames );
|
|
shots = (gameLocal.random.RandomInt ( 12 ) + 8) * combat.aggressiveScale;
|
|
return SRESULT_STAGE ( STAGE_WAITSTART );
|
|
|
|
case STAGE_WAITSTART:
|
|
if ( AnimDone ( ANIMCHANNEL_TORSO, 0 ) ) {
|
|
return SRESULT_STAGE ( STAGE_LOOP );
|
|
}
|
|
return SRESULT_WAIT;
|
|
|
|
case STAGE_LOOP:
|
|
PlayAnim ( ANIMCHANNEL_TORSO, "attack_blaster_loop", 0 );
|
|
return SRESULT_STAGE ( STAGE_WAITLOOP );
|
|
|
|
case STAGE_WAITLOOP:
|
|
if ( AnimDone ( ANIMCHANNEL_TORSO, 0 ) ) {
|
|
if ( --shots <= 0 || (IsEnemyVisible() && !enemy.fl.inFov) ) {
|
|
PlayAnim ( ANIMCHANNEL_TORSO, "attack_blaster_end", 0 );
|
|
return SRESULT_STAGE ( STAGE_WAITEND );
|
|
}
|
|
return SRESULT_STAGE ( STAGE_LOOP );
|
|
}
|
|
return SRESULT_WAIT;
|
|
|
|
case STAGE_WAITEND:
|
|
if ( AnimDone ( ANIMCHANNEL_TORSO, 4 ) ) {
|
|
return SRESULT_DONE;
|
|
}
|
|
return SRESULT_WAIT;
|
|
}
|
|
return SRESULT_ERROR;
|
|
|
|
}
|