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_zombie_commando_tentacle.script
2022-08-27 13:19:00 +02:00

307 lines
7 KiB
Text

/***********************************************************************
ai_monster_zombie_commando_tentacle.script
monster_zombie_commando_tentacle
***********************************************************************/
#define ZCT_RUNDISTANCE 128
#define ZCT_WALKTURN 65
#define ZCT_ATTACK_RATE 5
#define ZCT_TENTACLE_RANGE_MAX 200
#define ZCT_NOFOVTIME 4
#define ATTACK_TENTACLE ATTACK_SPECIAL1
object monster_zombie_commando_tentacle : monster_base {
float nextAttack;
float nextNoFOVAttack;
boolean tentacleDamage;
//
// States
//
void state_Begin();
void state_Idle();
// attacks
float check_attacks();
void do_attack( float attack_flags );
void combat_tentacle();
void combat_melee();
void init();
// torso anim states
void Torso_Idle();
void Torso_Pain();
void Torso_MeleeAttack();
void Torso_TentacleAttack();
// legs anim states
void Legs_Idle();
void Legs_Walk();
void Legs_Run();
};
/***********************************************************************
Torso animation control
***********************************************************************/
void monster_zombie_commando_tentacle::Torso_Idle() {
idleAnim( ANIMCHANNEL_TORSO, "idle" );
eachFrame {
if ( AI_PAIN ) { animState( ANIMCHANNEL_TORSO, "Torso_Pain", 0 ); }
}
}
void monster_zombie_commando_tentacle::Torso_Pain() {
string animname;
float nextpain;
float currenttime;
animname = getPainAnim();
playAnim( ANIMCHANNEL_TORSO, animname );
nextpain = sys.getTime() + 0.25;
while( !animDone( ANIMCHANNEL_TORSO, 2 ) ) {
if ( AI_PAIN ) {
currenttime = sys.getTime();
if ( currenttime > nextpain ) {
animState( ANIMCHANNEL_TORSO, "Torso_Pain", 0 );
}
}
waitFrame();
}
finishAction( "pain" );
animState( ANIMCHANNEL_TORSO, "Torso_Idle", 2 );
}
void monster_zombie_commando_tentacle::Torso_MeleeAttack() {
playAnim( ANIMCHANNEL_TORSO, "melee_attack" );
while( !animDone( ANIMCHANNEL_TORSO, 4 ) ) {
waitFrame();
}
finishAction( "melee_attack" );
animState( ANIMCHANNEL_TORSO, "Torso_Idle", 4 );
}
void monster_zombie_commando_tentacle::Torso_TentacleAttack() {
disablePain();
faceEnemy();
playAnim( ANIMCHANNEL_TORSO, "range_attack" );
while( !animDone( ANIMCHANNEL_TORSO, 4 ) ) {
waitFrame();
}
finishAction( "tentacle_attack" );
animState( ANIMCHANNEL_TORSO, "Torso_Idle", 4 );
}
/***********************************************************************
Legs animation control
***********************************************************************/
void monster_zombie_commando_tentacle::Legs_Idle() {
idleAnim( ANIMCHANNEL_LEGS, "idle" );
eachFrame {
if ( run && AI_FORWARD ) { animState( ANIMCHANNEL_LEGS, "Legs_Run", 4 ); }
if ( AI_FORWARD ) { animState( ANIMCHANNEL_LEGS, "Legs_Walk", 4 ); }
}
}
void monster_zombie_commando_tentacle::Legs_Walk() {
playCycle( ANIMCHANNEL_LEGS, "walk" );
eachFrame {
if ( run && AI_FORWARD ) { animState( ANIMCHANNEL_LEGS, "Legs_Run", 4 ); }
if ( !AI_FORWARD ) { animState( ANIMCHANNEL_LEGS, "Legs_Idle", 4 ); }
}
}
void monster_zombie_commando_tentacle::Legs_Run() {
playCycle( ANIMCHANNEL_LEGS, "run" );
eachFrame {
if ( !run && AI_FORWARD ) { animState( ANIMCHANNEL_LEGS, "Legs_Walk", 4 ); }
if ( !AI_FORWARD ) { animState( ANIMCHANNEL_LEGS, "Legs_Idle", 4 ); }
}
}
/***********************************************************************
AI
***********************************************************************/
/*
=====================
monster_zombie_commando_tentacle::init
=====================
*/
void monster_zombie_commando_tentacle::init() {
run_distance = ZCT_RUNDISTANCE;
walk_turn = ZCT_WALKTURN;
setState( "state_Begin" );
}
/*
=====================
monster_zombie_commando_tentacle::state_Begin
=====================
*/
void monster_zombie_commando_tentacle::state_Begin() {
animState( ANIMCHANNEL_TORSO, "Torso_Idle", 0 );
animState( ANIMCHANNEL_LEGS, "Legs_Idle", 0 );
monster_begin();
setMoveType( MOVETYPE_ANIM );
setState( "state_Idle" );
}
/*
=====================
monster_zombie_commando_tentacle::state_Idle
=====================
*/
void monster_zombie_commando_tentacle::state_Idle() {
wait_for_enemy();
tentacleDamage = false;
nextAttack = 0;
nextNoFOVAttack = 0;
setState( "state_Combat" );
}
/***********************************************************************
attacks
***********************************************************************/
/*
=====================
monster_zombie_commando_tentacle::do_attack
=====================
*/
void monster_zombie_commando_tentacle::do_attack( float attack_flags ) {
nextNoFOVAttack = sys.getTime() + ZCT_NOFOVTIME;
if ( attack_flags & ATTACK_MELEE ) {
combat_melee();
} else if ( attack_flags & ATTACK_TENTACLE ) {
combat_tentacle();
}
}
/*
=====================
monster_zombie_commando_tentacle::check_attacks
=====================
*/
float monster_zombie_commando_tentacle::check_attacks() {
float range;
float currentTime;
float attack_flags;
attack_flags = 0;
if ( testMeleeAttack() ) {
attack_flags |= ATTACK_MELEE;
}
if ( ( ( sys.getTime() > nextNoFOVAttack ) && AI_ENEMY_VISIBLE ) || AI_ENEMY_IN_FOV ) {
range = enemyRange();
currentTime = sys.getTime();
if ( ( range < ZCT_TENTACLE_RANGE_MAX ) && ( !canReachEnemy() || ( currentTime >= nextAttack ) ) ) {
if ( canHitEnemy() ) {
attack_flags |= ATTACK_TENTACLE;
}
}
}
return attack_flags;
}
/*
=====================
monster_zombie_commando_tentacle::tentacle_attack_start
=====================
*/
void monster_zombie_commando_tentacle::tentacle_attack_start() {
tentacleDamage = true;
}
/*
=====================
monster_zombie_commando_tentacle::tentacle_attack_end
=====================
*/
void monster_zombie_commando_tentacle::tentacle_attack_end() {
tentacleDamage = false;
}
/***********************************************************************
Combat
***********************************************************************/
/*
=====================
monster_zombie_commando_tentacle::combat_tentacle
=====================
*/
void monster_zombie_commando_tentacle::combat_tentacle() {
tentacleDamage = false;
stopMove();
animState( ANIMCHANNEL_TORSO, "Torso_TentacleAttack", 4 );
while( inAnimState( ANIMCHANNEL_TORSO, "Torso_TentacleAttack" ) ) {
if ( tentacleDamage ) {
if ( meleeAttackToJoint( "joint13", "melee_commandoTentacle" ) ) {
tentacleDamage = false;
}
}
waitFrame();
}
tentacleDamage = false;
// don't attack for a bit
nextAttack = DelayTime( ZCT_ATTACK_RATE );
nextNoFOVAttack = sys.getTime() + ZCT_NOFOVTIME;
}
/*
=====================
monster_zombie_commando_tentacle::combat_melee
=====================
*/
void monster_zombie_commando_tentacle::combat_melee() {
tentacleDamage = false;
faceEnemy();
animState( ANIMCHANNEL_TORSO, "Torso_MeleeAttack", 5 );
while( inAnimState( ANIMCHANNEL_TORSO, "Torso_MeleeAttack" ) ) {
lookAtEnemy( 1 );
if ( tentacleDamage ) {
if ( meleeAttackToJoint( "joint13", "melee_commandoTentacle" ) ) {
tentacleDamage = false;
}
}
waitFrame();
}
tentacleDamage = false;
}