0
0
Fork 0
mirror of https://github.com/id-Software/DOOM-3-BFG.git synced 2025-03-15 23:21:35 +00:00
doom3-bfg/base/script/ai_monster_demon_mancubus.script
2022-08-27 13:19:00 +02:00

355 lines
7.5 KiB
Text

/***********************************************************************
ai_monster_demon_mancubus.script
monster_demon_mancubus
***********************************************************************/
#define MANC_WALKTURN 65
#define MANC_ATTACK_RATE 1
#define MANC_MAX_SHOTS 5
#define MANC_MIN_SHOTS 1
#define MANC_NOFOVTIME 8
object monster_demon_mancubus : monster_base {
float nextAttack;
float nextNoFOVAttack;
entity combat_node;
float fire;
// States
void state_Begin();
void state_Idle();
// attacks
float check_attacks();
void do_attack( float attack_flags );
void combat_range();
void combat_melee();
void init();
// torso anim states
void Torso_Idle();
void Torso_Pain();
void Torso_MeleeAttack();
void Torso_RangeAttack();
void Torso_TurretAttack();
// legs anim states
void Legs_Idle();
void Legs_Walk();
};
/***********************************************************************
Torso animation control
***********************************************************************/
void monster_demon_mancubus::Torso_Idle() {
idleAnim( ANIMCHANNEL_TORSO, "stand" );
eachFrame {
if ( AI_PAIN ) {
animState( ANIMCHANNEL_TORSO, "Torso_Pain", 3 );
}
if ( fire ) {
animState( ANIMCHANNEL_TORSO, "Torso_RangeAttack", 4 );
}
}
}
void monster_demon_mancubus::Torso_Pain() {
string animname;
animname = getPainAnim();
playAnim( ANIMCHANNEL_TORSO, animname );
while( !animDone( ANIMCHANNEL_TORSO, 8 ) ) {
preventPain( 2 );
waitFrame();
}
finishAction( "pain" );
animState( ANIMCHANNEL_TORSO, "Torso_Idle", 8 );
}
void monster_demon_mancubus::Torso_MeleeAttack() {
playAnim( ANIMCHANNEL_TORSO, "melee_attack" );
while( !animDone( ANIMCHANNEL_TORSO, 2 ) ) {
waitFrame();
}
finishAction( "melee_attack" );
animState( ANIMCHANNEL_TORSO, "Torso_Idle", 2 );
}
void monster_demon_mancubus::Torso_RangeAttack() {
float endtime;
playAnim( ANIMCHANNEL_TORSO, "range_attack_start" );
while( !animDone( ANIMCHANNEL_TORSO, 0 ) ) {
if ( AI_PAIN ) {
animState( ANIMCHANNEL_TORSO, "Torso_Pain", 3 );
}
waitFrame();
}
while( fire > 0 ) {
playAnim( ANIMCHANNEL_TORSO, "range_attack_loop" );
while( ( fire > 0 ) && !animDone( ANIMCHANNEL_TORSO, 0 ) ) {
if ( AI_PAIN ) {
animState( ANIMCHANNEL_TORSO, "Torso_Pain", 3 );
}
waitFrame();
}
fire = fire - 1;
}
fire = 0;
if ( !animDone( ANIMCHANNEL_TORSO, 0 ) ) {
setBlendFrames( ANIMCHANNEL_TORSO, 4 );
}
playAnim( ANIMCHANNEL_TORSO, "range_attack_end" );
while( !animDone( ANIMCHANNEL_TORSO, 0 ) ) {
if ( AI_PAIN ) {
animState( ANIMCHANNEL_TORSO, "Torso_Pain", 3 );
}
waitFrame();
}
finishAction( "range_attack" );
animState( ANIMCHANNEL_TORSO, "Torso_Idle", 0 );
}
void monster_demon_mancubus::Torso_TurretAttack() {
float endtime;
playAnim( ANIMCHANNEL_TORSO, "range_attack_start" );
while( !animDone( ANIMCHANNEL_TORSO, 0 ) ) {
if ( AI_PAIN ) {
animState( ANIMCHANNEL_TORSO, "Torso_Pain", 3 );
}
waitFrame();
}
fire = MANC_MIN_SHOTS + int( sys.random( MANC_MAX_SHOTS - MANC_MIN_SHOTS ) );
while( fire > 0 ) {
fire = fire - 1;
playAnim( ANIMCHANNEL_TORSO, "range_attack_loop" );
while( !animDone( ANIMCHANNEL_TORSO, 0 ) ) {
if ( AI_PAIN ) {
animState( ANIMCHANNEL_TORSO, "Torso_Pain", 3 );
}
waitFrame();
if ( !canHitEnemyFromAnim( "range_attack_loop" ) ) {
break;
}
}
}
fire = 0;
if ( !animDone( ANIMCHANNEL_TORSO, 0 ) ) {
setBlendFrames( ANIMCHANNEL_TORSO, 4 );
}
playAnim( ANIMCHANNEL_TORSO, "range_attack_end" );
while( !animDone( ANIMCHANNEL_TORSO, 4 ) ) {
if ( AI_PAIN ) {
animState( ANIMCHANNEL_TORSO, "Torso_Pain", 3 );
}
waitFrame();
}
finishAction( "turret_attack" );
animState( ANIMCHANNEL_TORSO, "Torso_Idle", 4 );
}
/***********************************************************************
Legs animation control
***********************************************************************/
void monster_demon_mancubus::Legs_Idle() {
idleAnim( ANIMCHANNEL_LEGS, "stand" );
eachFrame {
if ( AI_FORWARD ) { animState( ANIMCHANNEL_LEGS, "Legs_Walk", 2 ); }
}
}
void monster_demon_mancubus::Legs_Walk() {
playCycle( ANIMCHANNEL_LEGS, "walk" );
eachFrame {
if ( !AI_FORWARD ) { animState( ANIMCHANNEL_LEGS, "Legs_Idle", 2 ); }
}
}
/***********************************************************************
AI
***********************************************************************/
/*
=====================
monster_demon_mancubus::init
=====================
*/
void monster_demon_mancubus::init() {
walk_turn = MANC_WALKTURN;
setState( "state_Begin" );
}
/***********************************************************************
States
***********************************************************************/
/*
=====================
monster_demon_mancubus::state_Begin
=====================
*/
void monster_demon_mancubus::state_Begin() {
fire = 0;
animState( ANIMCHANNEL_TORSO, "Torso_Idle", 0 );
animState( ANIMCHANNEL_LEGS, "Legs_Idle", 0 );
monster_begin();
setMoveType( MOVETYPE_ANIM );
setState( "state_Idle" );
}
/*
=====================
monster_demon_mancubus::state_Idle
=====================
*/
void monster_demon_mancubus::state_Idle() {
wait_for_enemy();
nextAttack = 0;
nextNoFOVAttack = 0;
setState( "state_Combat" );
}
/***********************************************************************
attacks
***********************************************************************/
/*
=====================
monster_demon_mancubus::do_attack
=====================
*/
void monster_demon_mancubus::do_attack( float attack_flags ) {
nextNoFOVAttack = sys.getTime() + MANC_NOFOVTIME;
if ( attack_flags & ATTACK_COMBAT_NODE ) {
combat_ainode( combat_node );
} else if ( attack_flags & ATTACK_MELEE ) {
combat_melee();
} else if ( attack_flags & ATTACK_MISSILE ) {
combat_range();
}
}
/*
=====================
monster_demon_mancubus::check_attacks
=====================
*/
float monster_demon_mancubus::check_attacks() {
float currentTime;
float canMelee;
float attack_flags;
attack_flags = 0;
canMelee = testMeleeAttack();
currentTime = sys.getTime();
if ( !canMelee ) {
combat_node = getCombatNode();
if ( combat_node ) {
attack_flags |= ATTACK_COMBAT_NODE;
}
}
if ( canMelee ) {
attack_flags |= ATTACK_MELEE;
}
if ( ( ( sys.getTime() > nextNoFOVAttack ) && AI_ENEMY_VISIBLE ) || AI_ENEMY_IN_FOV ) {
if ( !canReachEnemy() || ( currentTime >= nextAttack ) ) {
if ( canHitEnemyFromAnim( "range_attack_loop" ) ) {
attack_flags |= ATTACK_MISSILE;
}
}
}
return attack_flags;
}
/*
=====================
monster_demon_mancubus::combat_range
=====================
*/
void monster_demon_mancubus::combat_range() {
float attack_flags;
faceEnemy();
if ( !AI_ENEMY_IN_FOV ) {
sys.wait( 0.4 );
}
fire = MANC_MIN_SHOTS + int( sys.random( MANC_MAX_SHOTS - MANC_MIN_SHOTS ) );
while( fire > 0 ) {
if ( !canHitEnemyFromAnim( "range_attack_loop" ) ) {
break;
}
if ( AI_PAIN ) {
attack_flags = check_attacks();
if ( attack_flags & ATTACK_MELEE ) {
break;
}
}
waitFrame();
}
fire = 0;
while( !inAnimState( ANIMCHANNEL_TORSO, "Torso_Idle" ) ) {
waitFrame();
}
// don't attack for a bit
nextAttack = DelayTime( MANC_ATTACK_RATE );
nextNoFOVAttack = sys.getTime() + MANC_NOFOVTIME;
}
/*
=====================
monster_demon_mancubus::combat_melee
=====================
*/
void monster_demon_mancubus::combat_melee() {
lookAtEnemy( 100 );
faceEnemy();
animState( ANIMCHANNEL_TORSO, "Torso_MeleeAttack", 5 );
waitAction( "melee_attack" );
lookAtEnemy( 1 );
}