mirror of
https://github.com/jmarshall23/DoomRTX.git
synced 2026-08-16 08:10:32 +02:00
208 lines
14 KiB
C++
208 lines
14 KiB
C++
// AI_monster_boss_guardian.cpp
|
|
|
|
#include "precompiled.h"
|
|
#pragma hdrstop
|
|
#include "../Game_local.h"
|
|
|
|
|
|
rvmSeekerBase::rvmSeekerBase() {}
|
|
void rvmSeekerBase::Init( idAI* aiOwner ) { rvmMonsterBase::Init( aiOwner ); }
|
|
stateResult_t rvmSeekerBase::RunStateByName( const char* stateName, stateParms_t* parms ) {
|
|
AI_DISPATCH_STATE( "respawnSeeker", respawnSeeker );
|
|
return rvmMonsterBase::RunStateByName( stateName, parms );
|
|
}
|
|
bool rvmSeekerBase::isAlive() const { return owner && owner->health > 0 && !owner->AI_DEAD; }
|
|
stateResult_t rvmSeekerBase::respawnSeeker( stateParms_t* parms ) { return SRESULT_DONE; }
|
|
|
|
rvmMonsterBossGuardianSpawner::rvmMonsterBossGuardianSpawner() { guardian = NULL; inactive_time = active_time = pain_time = 0.0f; }
|
|
void rvmMonsterBossGuardianSpawner::Init( idAI* aiOwner ) {
|
|
rvmMonsterBase::Init( aiOwner );
|
|
inactive_time = GetFloatKey( "inactive_time", SPAWNER_FADEOUT );
|
|
active_time = GetFloatKey( "active_time", SPAWNER_FADEIN_TIME );
|
|
pain_time = GetFloatKey( "pain_time", SPAWNER_PAIN_FADEOUT );
|
|
SetState( "state_Inactive" );
|
|
}
|
|
stateResult_t rvmMonsterBossGuardianSpawner::RunStateByName( const char* stateName, stateParms_t* parms ) {
|
|
AI_DISPATCH_STATE( "update_effects", update_effects );
|
|
AI_DISPATCH_STATE( "setGuardian", setGuardian );
|
|
AI_DISPATCH_STATE( "state_Inactive", state_Inactive );
|
|
AI_DISPATCH_STATE( "state_Active", state_Active );
|
|
AI_DISPATCH_STATE( "state_Killed", state_Killed );
|
|
return rvmMonsterBase::RunStateByName( stateName, parms );
|
|
}
|
|
stateResult_t rvmMonsterBossGuardianSpawner::update_effects( stateParms_t* parms ) { return SRESULT_DONE; }
|
|
stateResult_t rvmMonsterBossGuardianSpawner::setGuardian( stateParms_t* parms ) { guardian = scratchEntity.GetEntity(); return SRESULT_DONE; }
|
|
stateResult_t rvmMonsterBossGuardianSpawner::state_Inactive( stateParms_t* parms ) {
|
|
if ( parms->stage == 0 ) { HideOwner(); IgnoreDamage(); parms->stage = 1; }
|
|
if ( Pain() || Activated() ) { ShowOwner(); AllowDamage(); SetState( "state_Active" ); return SRESULT_DONE; }
|
|
return SRESULT_WAIT;
|
|
}
|
|
stateResult_t rvmMonsterBossGuardianSpawner::state_Active( stateParms_t* parms ) {
|
|
if ( parms->stage == 0 ) { ShowOwner(); AllowDamage(); scratchEndTime = DelayTime( active_time ); parms->stage = 1; return SRESULT_WAIT; }
|
|
if ( Time() < scratchEndTime ) { return SRESULT_WAIT; }
|
|
SetState( "state_Inactive" );
|
|
return SRESULT_DONE;
|
|
}
|
|
stateResult_t rvmMonsterBossGuardianSpawner::state_Killed( stateParms_t* parms ) { return rvmMonsterBase::state_Killed( parms ); }
|
|
|
|
rvmMonsterBossGuardian::rvmMonsterBossGuardian() {
|
|
nextAttack = 0.0f; painNextTime = 0.0f; in_melee = false; rightfoot = false; charge = false;
|
|
seeker1 = seeker2 = seeker3 = spawner = NULL;
|
|
}
|
|
void rvmMonsterBossGuardian::Init( idAI* aiOwner ) {
|
|
rvmMonsterBase::Init( aiOwner );
|
|
SetMoveType( MOVETYPE_ANIM );
|
|
SetAnimState( ANIMCHANNEL_LEGS, "Legs_Idle", 0 );
|
|
SetState( "state_Idle" );
|
|
}
|
|
stateResult_t rvmMonsterBossGuardian::RunStateByName( const char* stateName, stateParms_t* parms ) {
|
|
AI_DISPATCH_STATE( "Legs_Sight", Legs_Sight );
|
|
AI_DISPATCH_STATE( "Legs_Death", Legs_Death );
|
|
AI_DISPATCH_STATE( "Legs_Pain", Legs_Pain );
|
|
AI_DISPATCH_STATE( "Legs_RangeAttack", Legs_RangeAttack );
|
|
AI_DISPATCH_STATE( "Legs_MeleeAttack", Legs_MeleeAttack );
|
|
AI_DISPATCH_STATE( "Legs_Walk_Melee_Left", Legs_Walk_Melee_Left );
|
|
AI_DISPATCH_STATE( "Legs_Walk_Melee_Right", Legs_Walk_Melee_Right );
|
|
AI_DISPATCH_STATE( "Legs_Walk", Legs_Walk );
|
|
AI_DISPATCH_STATE( "Legs_Run_Melee_Left", Legs_Run_Melee_Left );
|
|
AI_DISPATCH_STATE( "Legs_Run_Melee_Right", Legs_Run_Melee_Right );
|
|
AI_DISPATCH_STATE( "Legs_Charge", Legs_Charge );
|
|
AI_DISPATCH_STATE( "Legs_Lost", Legs_Lost );
|
|
AI_DISPATCH_STATE( "Legs_Idle", Legs_Idle );
|
|
AI_DISPATCH_STATE( "Legs_SpawnSeeker", Legs_SpawnSeeker );
|
|
AI_DISPATCH_STATE( "addSeeker", addSeeker );
|
|
AI_DISPATCH_STATE( "sightEnemy", sightEnemy );
|
|
AI_DISPATCH_STATE( "state_Idle", state_Idle );
|
|
AI_DISPATCH_STATE( "state_Killed", state_Killed );
|
|
AI_DISPATCH_STATE( "state_Combat", state_Combat );
|
|
AI_DISPATCH_STATE( "combat_melee", combat_melee );
|
|
AI_DISPATCH_STATE( "combat_range", combat_range );
|
|
AI_DISPATCH_STATE( "combat_charge", combat_charge );
|
|
AI_DISPATCH_STATE( "pound_impact", pound_impact );
|
|
AI_DISPATCH_STATE( "pound_attack", pound_attack );
|
|
AI_DISPATCH_STATE( "pound_attack_left", pound_attack_left );
|
|
AI_DISPATCH_STATE( "pound_attack_right", pound_attack_right );
|
|
AI_DISPATCH_STATE( "smash_ground", smash_ground );
|
|
return rvmMonsterBase::RunStateByName( stateName, parms );
|
|
}
|
|
|
|
stateResult_t rvmMonsterBossGuardian::Legs_Idle( stateParms_t* parms ) {
|
|
if ( parms->stage == 0 ) { IdleAnim( ANIMCHANNEL_LEGS, "idle" ); parms->stage = 1; }
|
|
if ( Pain() ) { SetAnimState( ANIMCHANNEL_LEGS, "Legs_Pain", GUARDIAN_IDLE_TO_PAIN ); return SRESULT_DONE; }
|
|
if ( charge ) { SetAnimState( ANIMCHANNEL_LEGS, "Legs_Charge", GUARDIAN_IDLE_TO_CHARGE ); return SRESULT_DONE; }
|
|
if ( MovingForward() ) { SetAnimState( ANIMCHANNEL_LEGS, "Legs_Walk", GUARDIAN_IDLE_TO_WALK ); return SRESULT_DONE; }
|
|
return SRESULT_WAIT;
|
|
}
|
|
stateResult_t rvmMonsterBossGuardian::Legs_Walk( stateParms_t* parms ) {
|
|
if ( parms->stage == 0 ) { PlayCycle( ANIMCHANNEL_LEGS, "walk" ); parms->stage = 1; }
|
|
if ( Pain() ) { SetAnimState( ANIMCHANNEL_LEGS, "Legs_Pain", GUARDIAN_WALK_TO_PAIN ); return SRESULT_DONE; }
|
|
if ( charge ) { SetAnimState( ANIMCHANNEL_LEGS, "Legs_Charge", GUARDIAN_WALK_TO_CHARGE ); return SRESULT_DONE; }
|
|
if ( !MovingForward() ) { SetAnimState( ANIMCHANNEL_LEGS, "Legs_Idle", GUARDIAN_WALK_TO_IDLE ); return SRESULT_DONE; }
|
|
return SRESULT_WAIT;
|
|
}
|
|
stateResult_t rvmMonsterBossGuardian::Legs_Pain( stateParms_t* parms ) {
|
|
if ( parms->stage == 0 ) { PlayAnim( ANIMCHANNEL_LEGS, GetPainAnim() ); painNextTime = DelayTime( GUARDIAN_PAIN_DELAY ); parms->stage = 1; return SRESULT_WAIT; }
|
|
if ( Pain() && Time() > painNextTime ) { SetAnimState( ANIMCHANNEL_LEGS, "Legs_Pain", GUARDIAN_PAIN_TO_PAIN ); return SRESULT_DONE; }
|
|
if ( AnimDone( ANIMCHANNEL_LEGS, GUARDIAN_PAIN_TO_IDLE ) ) { SetAnimState( ANIMCHANNEL_LEGS, "Legs_Idle", GUARDIAN_PAIN_TO_IDLE ); return SRESULT_DONE; }
|
|
return SRESULT_WAIT;
|
|
}
|
|
stateResult_t rvmMonsterBossGuardian::Legs_Sight( stateParms_t* parms ) {
|
|
if ( parms->stage == 0 ) { PlayAnim( ANIMCHANNEL_LEGS, "sight" ); parms->stage = 1; }
|
|
if ( AnimDone( ANIMCHANNEL_LEGS, GUARDIAN_SIGHT_TO_IDLE ) ) { SetAnimState( ANIMCHANNEL_LEGS, "Legs_Idle", GUARDIAN_SIGHT_TO_IDLE ); return SRESULT_DONE; }
|
|
return SRESULT_WAIT;
|
|
}
|
|
stateResult_t rvmMonsterBossGuardian::Legs_Death( stateParms_t* parms ) {
|
|
if ( parms->stage == 0 ) { PlayAnim( ANIMCHANNEL_LEGS, "death" ); parms->stage = 1; }
|
|
return AnimDone( ANIMCHANNEL_LEGS, 0 ) ? SRESULT_DONE : SRESULT_WAIT;
|
|
}
|
|
stateResult_t rvmMonsterBossGuardian::Legs_RangeAttack( stateParms_t* parms ) {
|
|
if ( parms->stage == 0 ) { StopMove(); FaceEnemy(); PlayAnim( ANIMCHANNEL_LEGS, "range_attack" ); parms->stage = 1; return SRESULT_WAIT; }
|
|
if ( AnimDone( ANIMCHANNEL_LEGS, GUARDIAN_RANGEATTACK_TO_IDLE ) ) { FinishAction( "range_attack" ); SetAnimState( ANIMCHANNEL_LEGS, "Legs_Idle", GUARDIAN_RANGEATTACK_TO_IDLE ); return SRESULT_DONE; }
|
|
return SRESULT_WAIT;
|
|
}
|
|
stateResult_t rvmMonsterBossGuardian::Legs_MeleeAttack( stateParms_t* parms ) {
|
|
if ( parms->stage == 0 ) { StopMove(); FaceEnemy(); in_melee = true; PlayAnim( ANIMCHANNEL_LEGS, "melee_attack" ); parms->stage = 1; return SRESULT_WAIT; }
|
|
if ( AnimDone( ANIMCHANNEL_LEGS, GUARDIAN_MELEE_TO_IDLE ) ) { in_melee = false; FinishAction( "melee_attack" ); SetAnimState( ANIMCHANNEL_LEGS, "Legs_Idle", GUARDIAN_MELEE_TO_IDLE ); return SRESULT_DONE; }
|
|
return SRESULT_WAIT;
|
|
}
|
|
stateResult_t rvmMonsterBossGuardian::Legs_Walk_Melee_Left( stateParms_t* parms ) { if ( parms->stage == 0 ) { PlayAnim( ANIMCHANNEL_LEGS, "walk_melee_left" ); parms->stage = 1; } return AnimDone( ANIMCHANNEL_LEGS, 4 ) ? SRESULT_DONE : SRESULT_WAIT; }
|
|
stateResult_t rvmMonsterBossGuardian::Legs_Walk_Melee_Right( stateParms_t* parms ) { if ( parms->stage == 0 ) { PlayAnim( ANIMCHANNEL_LEGS, "walk_melee_right" ); parms->stage = 1; } return AnimDone( ANIMCHANNEL_LEGS, 4 ) ? SRESULT_DONE : SRESULT_WAIT; }
|
|
stateResult_t rvmMonsterBossGuardian::Legs_Run_Melee_Left( stateParms_t* parms ) { if ( parms->stage == 0 ) { PlayAnim( ANIMCHANNEL_LEGS, "run_melee_left" ); parms->stage = 1; } return AnimDone( ANIMCHANNEL_LEGS, 4 ) ? SRESULT_DONE : SRESULT_WAIT; }
|
|
stateResult_t rvmMonsterBossGuardian::Legs_Run_Melee_Right( stateParms_t* parms ) { if ( parms->stage == 0 ) { PlayAnim( ANIMCHANNEL_LEGS, "run_melee_right" ); parms->stage = 1; } return AnimDone( ANIMCHANNEL_LEGS, 4 ) ? SRESULT_DONE : SRESULT_WAIT; }
|
|
stateResult_t rvmMonsterBossGuardian::Legs_Charge( stateParms_t* parms ) {
|
|
if ( parms->stage == 0 ) { charge = true; ChargeAttack( "damage_guardian_charge" ); PlayCycle( ANIMCHANNEL_LEGS, "charge" ); parms->stage = 1; return SRESULT_WAIT; }
|
|
if ( Pain() ) { charge = false; AttackEnd(); SetAnimState( ANIMCHANNEL_LEGS, "Legs_Pain", GUARDIAN_CHARGE_TO_PAIN ); return SRESULT_DONE; }
|
|
if ( MoveDone() || EnemyRange() < 128.0f ) { charge = false; AttackEnd(); SetAnimState( ANIMCHANNEL_LEGS, "Legs_Idle", GUARDIAN_CHARGE_TO_IDLE ); FinishAction( "charge_attack" ); return SRESULT_DONE; }
|
|
return SRESULT_WAIT;
|
|
}
|
|
stateResult_t rvmMonsterBossGuardian::Legs_Lost( stateParms_t* parms ) { if ( parms->stage == 0 ) { PlayAnim( ANIMCHANNEL_LEGS, "lost" ); parms->stage = 1; } return AnimDone( ANIMCHANNEL_LEGS, GUARDIAN_LOST_TO_IDLE ) ? SRESULT_DONE : SRESULT_WAIT; }
|
|
stateResult_t rvmMonsterBossGuardian::Legs_SpawnSeeker( stateParms_t* parms ) {
|
|
if ( parms->stage == 0 ) { StopMove(); PlayAnim( ANIMCHANNEL_LEGS, "spawn_seeker" ); parms->stage = 1; return SRESULT_WAIT; }
|
|
if ( AnimDone( ANIMCHANNEL_LEGS, GUARDIAN_SPAWN_TO_IDLE ) ) { FinishAction( "spawn_seeker" ); SetAnimState( ANIMCHANNEL_LEGS, "Legs_Idle", GUARDIAN_SPAWN_TO_IDLE ); return SRESULT_DONE; }
|
|
return SRESULT_WAIT;
|
|
}
|
|
stateResult_t rvmMonsterBossGuardian::addSeeker( stateParms_t* parms ) {
|
|
idEntity* ent = scratchEntity.GetEntity();
|
|
if ( !seeker1.GetEntity() ) seeker1 = ent; else if ( !seeker2.GetEntity() ) seeker2 = ent; else seeker3 = ent;
|
|
return SRESULT_DONE;
|
|
}
|
|
stateResult_t rvmMonsterBossGuardian::sightEnemy( stateParms_t* parms ) {
|
|
FaceEnemy();
|
|
SetAnimState( ANIMCHANNEL_LEGS, "Legs_Sight", GUARDIAN_IDLE_TO_SIGHT );
|
|
return SRESULT_DONE;
|
|
}
|
|
stateResult_t rvmMonsterBossGuardian::state_Idle( stateParms_t* parms ) {
|
|
enum { STAGE_START, STAGE_WAIT };
|
|
switch ( parms->stage ) {
|
|
case STAGE_START: StartAction( "wait_for_enemy" ); parms->stage = STAGE_WAIT; return SRESULT_WAIT;
|
|
case STAGE_WAIT:
|
|
if ( InAction() ) return SRESULT_WAIT;
|
|
StartAction( "sightEnemy" );
|
|
nextAttack = DelayTime( 2.0f );
|
|
SetState( "state_Combat" );
|
|
return SRESULT_DONE;
|
|
}
|
|
return SRESULT_ERROR;
|
|
}
|
|
stateResult_t rvmMonsterBossGuardian::state_Killed( stateParms_t* parms ) { return rvmMonsterBase::state_Killed( parms ); }
|
|
stateResult_t rvmMonsterBossGuardian::state_Combat( stateParms_t* parms ) {
|
|
enum { STAGE_SELECT, STAGE_ACTION };
|
|
switch ( parms->stage ) {
|
|
case STAGE_SELECT:
|
|
if ( EnemyDead() ) { SetState( "state_LostCombat" ); return SRESULT_DONE; }
|
|
if ( Pain() ) { SetAnimState( ANIMCHANNEL_LEGS, "Legs_Pain", GUARDIAN_WALK_TO_PAIN ); }
|
|
if ( CheckForMelee() ) { StartAction( "combat_melee" ); parms->stage = STAGE_ACTION; return SRESULT_WAIT; }
|
|
if ( Time() >= nextAttack && EnemyRange() < GUARDIAN_RANGE_ATTACK_RANGE && CanHitEnemy() ) { StartAction( "combat_range" ); parms->stage = STAGE_ACTION; return SRESULT_WAIT; }
|
|
if ( EnemyRange() < GUARDIAN_CHARGE_ATTACK_RANGE && TestChargeAttack() > 0.0f ) { StartAction( "combat_charge" ); parms->stage = STAGE_ACTION; return SRESULT_WAIT; }
|
|
MoveToEnemy();
|
|
return SRESULT_WAIT;
|
|
case STAGE_ACTION:
|
|
if ( InAction() ) { return SRESULT_WAIT; }
|
|
parms->stage = STAGE_SELECT;
|
|
return SRESULT_WAIT;
|
|
}
|
|
return SRESULT_ERROR;
|
|
}
|
|
stateResult_t rvmMonsterBossGuardian::combat_melee( stateParms_t* parms ) {
|
|
if ( parms->stage == 0 ) { waitActionName = "melee_attack"; SetAnimState( ANIMCHANNEL_LEGS, "Legs_MeleeAttack", GUARDIAN_IDLE_TO_MELEE ); parms->stage = 1; return SRESULT_WAIT; }
|
|
return ActionDone( "melee_attack" ) ? SRESULT_DONE : SRESULT_WAIT;
|
|
}
|
|
stateResult_t rvmMonsterBossGuardian::combat_range( stateParms_t* parms ) {
|
|
if ( parms->stage == 0 ) { waitActionName = "range_attack"; SetAnimState( ANIMCHANNEL_LEGS, "Legs_RangeAttack", GUARDIAN_IDLE_TO_RANGE ); parms->stage = 1; return SRESULT_WAIT; }
|
|
if ( !ActionDone( "range_attack" ) ) { return SRESULT_WAIT; }
|
|
nextAttack = DelayTime( GUARDIAN_RANGE_ATTACK_DELAY );
|
|
return SRESULT_DONE;
|
|
}
|
|
stateResult_t rvmMonsterBossGuardian::combat_charge( stateParms_t* parms ) {
|
|
if ( parms->stage == 0 ) { waitActionName = "charge_attack"; charge = true; SetAnimState( ANIMCHANNEL_LEGS, "Legs_Charge", GUARDIAN_IDLE_TO_CHARGE ); parms->stage = 1; return SRESULT_WAIT; }
|
|
if ( !ActionDone( "charge_attack" ) ) { return SRESULT_WAIT; }
|
|
charge = false;
|
|
nextAttack = DelayTime( GUARDIAN_RANGE_ATTACK_DELAY );
|
|
return SRESULT_DONE;
|
|
}
|
|
stateResult_t rvmMonsterBossGuardian::pound_impact( stateParms_t* parms ) { RadiusDamageFromJoint( rightfoot ? "r_foot" : "l_foot", "damage_guardian_footstep" ); return SRESULT_DONE; }
|
|
stateResult_t rvmMonsterBossGuardian::pound_attack( stateParms_t* parms ) { AttackMelee( "damage_guardian_melee" ); return SRESULT_DONE; }
|
|
stateResult_t rvmMonsterBossGuardian::pound_attack_left( stateParms_t* parms ) { rightfoot = false; return pound_attack( parms ); }
|
|
stateResult_t rvmMonsterBossGuardian::pound_attack_right( stateParms_t* parms ) { rightfoot = true; return pound_attack( parms ); }
|
|
stateResult_t rvmMonsterBossGuardian::smash_ground( stateParms_t* parms ) { RadiusDamageFromJoint( "origin", "damage_guardian_smash" ); return SRESULT_DONE; }
|