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

1219 lines
No EOL
26 KiB
Text

/***********************************************************************
ai_monster_hunter_invul.script
monster_hunter_invul
***********************************************************************/
#define INVUL_STATE_WAIT 0
#define INVUL_STATE_INVUL_SURVIVAL 1
#define INVUL_STATE_INVUL 2
#define INVUL_STATE_NORMAL 3
#define INVUL_ATTACK_RATE_NORMAL 3
#define INVUL_ATTACK_RATE_INVUL 4
#define INVUL_ATTACK_RATE_INVUL_SURVIVAL 0
#define SURVIVAL_MODE_TIME 15
#define ATTACK_GROUNDPOUND_NODAMAGE ATTACK_SPECIAL1
#define ATTACK_GROUNDPOUND ATTACK_SPECIAL2
#define ATTACK_ELECTRIC_WALL ATTACK_SPECIAL3
#define BEGIN_HEALTH 5500
#define STAGE_0_HEALTH 3900
#define STAGE_1_HEALTH 2400
#define STAGE_2_HEALTH 1000
#define ARCH_ELECTRIC_WALL_NUM 20
#define ARCH_ELECTRIC_WALL_SEPERATION 48
#define ARCH_ELECTRIC_WALL_RANGE ( ARCH_ELECTRIC_WALL_NUM * ARCH_ELECTRIC_WALL_SEPERATION )
/***********************************************************************
monster_hunter_invul
***********************************************************************/
object monster_hunter_invul : monster_base {
float nextAttack;
string range_attack_anim;
float survivalStart;
float endInvul;
//vector invul_location;
float combatStage;
float hunterState;
// torso anim states
void Torso_Idle();
void Torso_Pain();
void Torso_MeleeAttack();
void Torso_RangeAttack();
void Torso_ElectricWallAttack();
void Torso_InvulRange_Short();
void Torso_InvulRange_Tall();
void Torso_Shockwave();
void Torso_ShockwaveNoDamage();
void Torso_SummonShell();
void Torso_PreSummon();
void Torso_ShutdownShell();
// legs anim states
void Legs_Idle();
void Legs_Walk();
//Initialization
void init();
void destroy();
void endInvuln();
//
// States
//
void state_Begin();
void state_Idle();
void state_Dead();
//Invulnerability States
void state_Invulnerability();
void state_MoveToInvul();
void state_BeginInvulSurvival();
void state_EndInvulSurvival();
void state_BeginInvul();
void state_EndInvul();
//Normal States
//void state_Normal();
void state_BeginNormal();
//void state_EndNormal();
//Combat States
void state_CombatNormal();
void state_CombatInvul();
void state_CombatInvulSurvival();
//Testing States
void state_EasyKill();
// attacks
float check_attacks();
float check_attacks_normal();
float check_attacks_invul();
float check_attacks_invul_survival();
void do_attack( float attack_flags );
void combat_range();
void combat_melee();
void combat_shockwave();
void combat_electricwall();
void combat_shockwave_nodamage();
//void combat_invulrange_short();
//void combat_invulrange_tall();
void spawn_electric_wall( vector org );
void electric_wall_loop();
void electric_wall();
void electric_effect_loop();
float attackCount;
float attack0;
float attack1;
float attack2;
float attack3;
float attack4;
void ClearAttacks();
void PushAttack(float attack);
float SelectRandomAttack();
};
void monster_hunter_invul::ClearAttacks() {
attackCount = 0;
}
void monster_hunter_invul::PushAttack(float attack) {
if (attackCount == 0) {
attack0 = attack;
} else if (attackCount == 1) {
attack1 = attack;
} else if (attackCount == 2) {
attack2 = attack;
} else if (attackCount == 3) {
attack3 = attack;
} else if (attackCount == 4) {
attack4 = attack;
}
attackCount++;
}
float monster_hunter_invul::SelectRandomAttack() {
if(attackCount == 0) {
return 0;
}
float selectedAttack;
selectedAttack = sys.randomInt(attackCount);
if (selectedAttack == 0) {
return attack0;
} else if (selectedAttack == 1) {
return attack1;
} else if (selectedAttack == 2) {
return attack2;
} else if (selectedAttack == 3) {
return attack3;
} else if (selectedAttack == 4) {
return attack4;
}
return 0;
}
/***********************************************************************
Torso animation control
***********************************************************************/
void monster_hunter_invul::Torso_Idle() {
if(hunterState == INVUL_STATE_NORMAL) {
idleAnim( ANIMCHANNEL_TORSO, "idle" );
} else {
idleAnim( ANIMCHANNEL_TORSO, "invuln_idle" );
}
eachFrame {
if ( AI_PAIN ) {
animState( ANIMCHANNEL_TORSO, "Torso_Pain", 3 );
}
waitFrame();
}
}
void monster_hunter_invul::Torso_Pain() {
string animname;
float nextpain;
float currenttime;
animname = getPainAnim();
playAnim( ANIMCHANNEL_TORSO, animname );
nextpain = sys.getTime() + 0.25;
while( !animDone( ANIMCHANNEL_TORSO, 6 ) ) {
if ( AI_PAIN ) {
currenttime = sys.getTime();
if ( currenttime > nextpain ) {
animState( ANIMCHANNEL_TORSO, "Torso_Pain", 3 );
}
}
waitFrame();
}
finishAction( "pain" );
animState( ANIMCHANNEL_TORSO, "Torso_Idle", 6 );
}
void monster_hunter_invul::Torso_MeleeAttack() {
if(hunterState == INVUL_STATE_INVUL) {
playAnim( ANIMCHANNEL_TORSO, "invuln_melee_attack" );
} else {
playAnim( ANIMCHANNEL_TORSO, "melee_attack" );
}
while( !animDone( ANIMCHANNEL_TORSO, 4 ) ) {
waitFrame();
}
finishAction( "melee_attack" );
animState( ANIMCHANNEL_TORSO, "Torso_Idle", 4 );
}
void monster_hunter_invul::Torso_RangeAttack() {
string anim;
disablePain();
allowMovement( false );
if(range_attack_anim == "") {
sys.print("No range attack defined\n");
range_attack_anim = chooseAnim( ANIMCHANNEL_LEGS, "range_attack" );
}
playAnim( ANIMCHANNEL_TORSO, range_attack_anim );
while( !animDone( ANIMCHANNEL_TORSO, 4 ) ) {
lookAt( getEnemy(), 1 );
waitFrame();
}
allowMovement( true );
finishAction( "range_attack" );
animState( ANIMCHANNEL_TORSO, "Torso_Idle", 4 );
}
void monster_hunter_invul::Torso_ElectricWallAttack() {
string anim;
disablePain();
setShaderParm( 4, -sys.getTime() );
setSmokeVisibility( ALL_PARTICLES, 1 );
anim = chooseAnim( ANIMCHANNEL_TORSO, "electricwall_attack" );
if ( testAnimMoveTowardEnemy( anim ) ) {
playAnim( ANIMCHANNEL_TORSO, anim );
} else {
allowMovement( false );
anim = chooseAnim( ANIMCHANNEL_LEGS, "range_attack" );
playAnim( ANIMCHANNEL_TORSO, anim );
}
while( !animDone( ANIMCHANNEL_TORSO, 4 ) ) {
waitFrame();
}
allowMovement( true );
finishAction( "electricwall_attack" );
setSmokeVisibility( ALL_PARTICLES, 0 );
animState( ANIMCHANNEL_TORSO, "Torso_Idle", 4 );
}
void monster_hunter_invul::Torso_InvulRange_Short() {
playAnim( ANIMCHANNEL_TORSO, "missile_low" );
while( !animDone( ANIMCHANNEL_TORSO, 4 ) ) {
waitFrame();
}
finishAction( "invulrange_short" );
animState( ANIMCHANNEL_TORSO, "Torso_Idle", 4 );
}
void monster_hunter_invul::Torso_InvulRange_Tall() {
playAnim( ANIMCHANNEL_TORSO, "missile_high" );
while( !animDone( ANIMCHANNEL_TORSO, 4 ) ) {
waitFrame();
}
finishAction( "invulrange_tall" );
animState( ANIMCHANNEL_TORSO, "Torso_Idle", 4 );
}
void monster_hunter_invul::Torso_Shockwave() {
playAnim( ANIMCHANNEL_TORSO, "invuln_shockwave" );
while( !animDone( ANIMCHANNEL_TORSO, 4 ) ) {
waitFrame();
}
finishAction( "shockwave" );
animState( ANIMCHANNEL_TORSO, "Torso_Idle", 4 );
}
void monster_hunter_invul::Torso_ShockwaveNoDamage() {
playAnim( ANIMCHANNEL_TORSO, "invuln_shockwave_nodamage" );
while( !animDone( ANIMCHANNEL_TORSO, 4 ) ) {
waitFrame();
}
finishAction( "shockwave" );
animState( ANIMCHANNEL_TORSO, "Torso_Idle", 4 );
}
void monster_hunter_invul::Torso_SummonShell() {
playAnim( ANIMCHANNEL_TORSO, "invuln_summon" );
while( !animDone( ANIMCHANNEL_TORSO, 4 ) ) {
waitFrame();
}
finishAction( "summonshell" );
animState( ANIMCHANNEL_TORSO, "Torso_Idle", 4 );
}
void monster_hunter_invul::Torso_PreSummon() {
playAnim( ANIMCHANNEL_TORSO, "pre_summon" );
while( !animDone( ANIMCHANNEL_TORSO, 4 ) ) {
waitFrame();
}
finishAction( "presummon" );
animState( ANIMCHANNEL_TORSO, "Torso_Idle", 4 );
}
void monster_hunter_invul::Torso_ShutdownShell() {
playAnim( ANIMCHANNEL_TORSO, "invuln_shutdown" );
while( !animDone( ANIMCHANNEL_TORSO, 4 ) ) {
waitFrame();
}
finishAction( "shutdownshell" );
animState( ANIMCHANNEL_TORSO, "Torso_Idle", 4 );
}
/***********************************************************************
Legs animation control
***********************************************************************/
void monster_hunter_invul::Legs_Idle() {
idleAnim( ANIMCHANNEL_LEGS, "idle" );
eachFrame {
if ( AI_FORWARD ) { animState( ANIMCHANNEL_LEGS, "Legs_Walk", 4 ); }
}
}
void monster_hunter_invul::Legs_Walk() {
playCycle( ANIMCHANNEL_LEGS, "walk" );
eachFrame {
if ( !AI_FORWARD ) { animState( ANIMCHANNEL_LEGS, "Legs_Idle", 4 ); }
}
}
/***********************************************************************
AI
***********************************************************************/
/*
=====================
monster_hunter_invul::init
=====================
*/
void monster_hunter_invul::init() {
endInvul = 0;
combatStage = 0;
setDamageCap(STAGE_0_HEALTH);
setHealth(BEGIN_HEALTH);
nextAttack = 0;
// Tatoos start off blue
setColor( 0.68, 0.95, 1 );
setState( "state_Begin" );
}
void monster_hunter_invul::destroy() {
}
void monster_hunter_invul::endInvuln() {
endInvul = 1;
}
/***********************************************************************
States
***********************************************************************/
/*
=====================
monster_hunter_invul::state_Begin
=====================
*/
void monster_hunter_invul::state_Begin() {
animState( ANIMCHANNEL_TORSO, "Torso_Idle", 0 );
animState( ANIMCHANNEL_LEGS, "Legs_Idle", 0 );
monster_begin();
setState( "state_Idle" );
}
/*
=====================
monster_hunter_invul::state_Idle
=====================
*/
void monster_hunter_invul::state_Idle() {
setEnemy($player1);
//wait_for_enemy();
//Start a thread to spawn some effects
//thread electric_effect_loop();
setState("state_BeginNormal");
}
/*
=====================
monster_base::state_Dead
=====================
*/
void monster_hunter_invul::state_Dead() {
//Todo: Probably need to warp to a point for the cutscene
//I am dead so for now just stop moving
animState( ANIMCHANNEL_LEGS, "Legs_Idle", 8 );
animState( ANIMCHANNEL_TORSO, "Torso_Pain", 8 );
waitAction( "pain" );
remove();
}
//Invulnerability States
void monster_hunter_invul::state_Invulnerability() {
setState("state_MoveToInvul");
}
void monster_hunter_invul::state_MoveToInvul() {
//Let the level know we are moving to the center of the room to begin invulnerability
sys.trigger($movingToInvuln);
//According to the level designers we want to make this last at least 3 seconds to
//let the level play some effects
//float waitTime;
//waitTime = 4;
float startTime, currentTime;
startTime = sys.getTime();
currentTime = sys.getTime();
//The hunter does not take damage while moving to the invulnerable point
ignoreDamage();
//The hunter moves to the center of the room before he goes into invulnerability mode
entity ent;
ent = sys.getEntity("hunter_invul_location");
moveToEntity(ent);
//while( ((currentTime-startTime) < waitTime) || !AI_MOVE_DONE && !AI_DEST_UNREACHABLE ) {
while( !AI_MOVE_DONE && !AI_DEST_UNREACHABLE ) {
currentTime = sys.getTime();
//If the player gets in my way dole out a world of hurt
float canMelee;
canMelee = testMeleeAttack();
if ( AI_ENEMY_IN_FOV ) {
if ( canMelee ) {
combat_melee();
}
}
waitFrame();
}
slideTo(ent.getOrigin(), 0);
//Play little pre invuln animation to give the level some time
//animState( ANIMCHANNEL_TORSO, "Torso_PreSummon", 4 );
//waitAction( "presummon" );
stopMove();
setState("state_BeginInvulSurvival");
}
void monster_hunter_invul::state_BeginInvulSurvival() {
hunterState = INVUL_STATE_INVUL_SURVIVAL;
//Let the level know we are starting the invulnerability survival phase
sys.trigger($beginInvulnSurvival);
//Hunter is invulnerable
ignoreDamage();
stopMove();
//Skin changing and summon
setSkin("skins/monsters/hunter_invul/invuln_summon_shell");
setShaderTime( self );
//Crossfade the color for the tatoos
//thread crossFadeEnt( self, '1 0.18 0', '0.68 0.95 1', 1 );
//Play an animation when he goes into berserk mode
animState( ANIMCHANNEL_TORSO, "Torso_SummonShell", 4 );
waitAction( "summonshell" );
setSkin("skins/monsters/hunter_invul/invuln_shell");
survivalStart = sys.getTime();
setState( "state_CombatInvulSurvival" );
}
void monster_hunter_invul::state_EndInvulSurvival() {
//Let the level know we are going out of survival mode
sys.trigger($endSurvival);
//Go into a move invulnerable mode
//setState( "state_BeginInvul" );
/*
Copied from EndInvul because he is going to skip the move around invul state
and go directly to vulnerable
*/
stopMove();
//Switching the skin back to normal
setSkin("skins/monsters/hunter_invul/invuln_shutdown_shell");
setShaderTime( self );
//Play an animation when he turns off his invuln shell
animState( ANIMCHANNEL_TORSO, "Torso_ShutdownShell", 4 );
waitAction( "shutdownshell" );
if(combatStage >= 0) {
setSkin("skins/monsters/hunter_invul/invuln_no_shell2");
} else {
setSkin("skins/monsters/hunter_invul/invuln_no_shell");
}
//Let the level know we are done with invulnerability
sys.trigger($beginNormal);
setState( "state_BeginNormal");
}
void monster_hunter_invul::state_BeginInvul() {
hunterState = INVUL_STATE_INVUL;
//Hunter is invulnerable
ignoreDamage();
allowMovement(true);
//nextInvAttack = DelayTime( INVUL_ATTACK_RATE_INV );
//Already changed skin during survival mode
/*setSkin("skins/monsters/hunter_invul/invuln_summon_shell");
setShaderTime( self );
//Crossfade the color for the tatoos
//thread crossFadeEnt( self, '1 0.18 0', '0.68 0.95 1', 1 );
//Play an animation when he goes into berserk mode
animState( ANIMCHANNEL_TORSO, "Torso_SummonShell", 4 );
waitAction( "summonshell" );
setSkin("skins/monsters/hunter_invul/invuln_shell");*/
setState( "state_CombatInvul" );
}
void monster_hunter_invul::state_EndInvul() {
stopMove();
//Switching the skin back to normal
setSkin("skins/monsters/hunter_invul/invuln_shutdown_shell");
setShaderTime( self );
//Crossfade the color for the tatoos
//thread crossFadeEnt( self, '1 0.18 0', '0.68 0.95 1', 1 );
//Play an animation when he goes into berserk mode
animState( ANIMCHANNEL_TORSO, "Torso_ShutdownShell", 4 );
waitAction( "shutdownshell" );
if(combatStage >= 0) {
setSkin("skins/monsters/hunter_invul/invuln_no_shell2");
} else {
setSkin("skins/monsters/hunter_invul/invuln_no_shell");
}
//Let the level know we are done with invulnerability
sys.trigger($beginNormal);
setState( "state_BeginNormal");
}
/*void monster_hunter_invul::state_Normal() {
setState("state_EndInvul");
}*/
//Normal States
void monster_hunter_invul::state_BeginNormal() {
allowMovement(true);
hunterState = INVUL_STATE_NORMAL;
stopMove();
//Turn on damage while in normal mode
allowDamage();
setState( "state_CombatNormal" );
}
/*void monster_hunter_invul::state_EndNormal() {
setState( "state_BeginInvul");
}*/
void monster_hunter_invul::state_CombatNormal() {
//Reset So we attack immediate
nextAttack = 0;
//Use the default combat code while in normal mode
setState("state_Combat");
}
void monster_hunter_invul::state_CombatInvul() {
//Reset So we attack immediate
nextAttack = 0;
//Use the default combat code while in invul mode
setState( "state_Combat" );
}
void monster_hunter_invul::state_CombatInvulSurvival() {
float currentTime;
float attack;
stopMove();
//Reset So we attack immediate
nextAttack = 0;
eachFrame {
currentTime = sys.getTime();
//Don't timeout...we will just wait until the level tells us to end
/*if((currentTime - survivalStart) > SURVIVAL_MODE_TIME) {
//We are done with survival mode
setState("state_EndInvulSurvival");
}*/
if ( AI_ENEMY_VISIBLE ) {
lookAt( getEnemy(), 1 );
}
if ( AI_ENEMY_DEAD ) {
enemy_dead();
}
faceEnemy();
attack = check_attacks();
if(attack) {
do_attack(attack);
}
}
}
/*
=====================
monster_hunter_invul::state_EasyKill
Sets the hunter immediately into a state ready to die
=====================
*/
void monster_hunter_invul::state_EasyKill() {
sys.print("Easy Kill!!!!\n");
combatStage = 3;
setHealth(1);
setDamageCap(-1);
setState("state_BeginNormal");
}
/***********************************************************************
attacks
***********************************************************************/
float monster_hunter_invul::check_attacks() {
if(hunterState == INVUL_STATE_NORMAL) {
return check_attacks_normal();
} else if (hunterState == INVUL_STATE_INVUL) {
return check_attacks_invul();
} else if (hunterState == INVUL_STATE_INVUL_SURVIVAL) {
return check_attacks_invul_survival();
}
return 0;
}
float monster_hunter_invul::check_attacks_normal() {
//Check for damage so we know when it is time to jump out of normal mode
float health;
health = getHealth();
if(combatStage == 0) {
if(health <= STAGE_0_HEALTH) {
//sys.print("Moving To Stage 2\n");
setHealth(STAGE_0_HEALTH);
setDamageCap(STAGE_1_HEALTH);
combatStage = 1;
setState("state_Invulnerability");
}
}
if(combatStage == 1) {
if(health <= STAGE_1_HEALTH) {
//sys.print("Moving To Stage 3\n");
setHealth(STAGE_1_HEALTH);
setDamageCap(STAGE_2_HEALTH);
combatStage = 2;
setState("state_Invulnerability");
}
}
if(combatStage == 2) {
if(health <= STAGE_2_HEALTH) {
//sys.print("Moving To Final Stage\n");
setHealth(STAGE_2_HEALTH);
setDamageCap(-1); //Let him die
combatStage = 3;
setState("state_Invulnerability");
}
}
float attack_flags;
attack_flags = 0;
float currentTime;
currentTime = sys.getTime();
float canMelee;
canMelee = testMeleeAttack();
if ( canMelee ) {
attack_flags |= ATTACK_MELEE;
}
float playerHeight;
vector origin;
vector playerOrigin;
origin = getOrigin();
playerOrigin = $player1.getOrigin();
playerHeight = playerOrigin_z - origin_z;
//The player is below me so pound the ground just to scare hime
if(!AI_ENEMY_IN_FOV && currentTime >= nextAttack ) {
if(playerHeight < -10) {
attack_flags |= ATTACK_GROUNDPOUND;
}
}
if(AI_ENEMY_IN_FOV ) {
ClearAttacks();
if ( !canReachEnemy() || ( currentTime >= nextAttack ) ) {
string anim;
anim = chooseAnim( ANIMCHANNEL_LEGS, "range_attack" );
if ( testAnimMoveTowardEnemy( anim ) ) {
if ( canHitEnemyFromAnim( anim ) ) {
range_attack_anim = anim;
PushAttack(ATTACK_MISSILE);
}
}
}
if(( currentTime >= nextAttack ) && playerHeight <= 16) {
//sys.print("player height = " + playerHeight + "\n");
PushAttack(ATTACK_GROUNDPOUND);
}
attack_flags |= SelectRandomAttack();
}
return attack_flags;
}
float monster_hunter_invul::check_attacks_invul() {
//Check if the level has told us it is time to end invuln mode
if(endInvul) {
endInvul = 0;
setState("state_EndInvul");
}
float attack_flags;
attack_flags = 0;
float currentTime;
currentTime = sys.getTime();
float canMelee;
canMelee = testMeleeAttack();
if ( canMelee ) {
attack_flags |= ATTACK_MELEE;
}
float playerHeight;
vector origin;
vector playerOrigin;
origin = getOrigin();
playerOrigin = $player1.getOrigin();
playerHeight = playerOrigin_z - origin_z;
//The player is below me so pound the ground just to scare hime
if(!AI_ENEMY_IN_FOV && currentTime >= nextAttack ) {
if(playerHeight < -10) {
//sys.print("player height = " + playerHeight + "\n");
attack_flags |= ATTACK_GROUNDPOUND;
}
}
if(AI_ENEMY_IN_FOV ) {
ClearAttacks();
if ( !canReachEnemy() || ( currentTime >= nextAttack ) ) {
string anim;
anim = chooseAnim( ANIMCHANNEL_LEGS, "range_attack" );
if ( testAnimMoveTowardEnemy( anim ) ) {
if ( canHitEnemyFromAnim( anim ) ) {
range_attack_anim = anim;
PushAttack(ATTACK_MISSILE);
}
}
}
if(( currentTime >= nextAttack ) && playerHeight <= 16) {
//sys.print("player height = " + playerHeight + "\n");
PushAttack(ATTACK_GROUNDPOUND);
}
attack_flags |= SelectRandomAttack();
}
return attack_flags;
}
float monster_hunter_invul::check_attacks_invul_survival() {
float attack_flags;
attack_flags = 0;
//Check if the level has told us it is time to end invuln mode
if(endInvul) {
endInvul = 0;
setState("state_EndInvulSurvival");
}
//If the player is dumb enough to get close while invulnerable then give em a world of hurt
float canMelee;
canMelee = testMeleeAttack();
if ( AI_ENEMY_IN_FOV ) {
if ( canMelee ) {
attack_flags |= ATTACK_MELEE;
}
}
float currentTime;
currentTime = sys.getTime();
if(currentTime >= nextAttack) {
ClearAttacks();
//Add attacks that are always available
PushAttack(ATTACK_MISSILE);
PushAttack(ATTACK_ELECTRIC_WALL);
//Add the groundpund attack if the player is near the ground level
float playerHeight;
vector origin;
vector playerOrigin;
origin = getOrigin();
playerOrigin = $player1.getOrigin();
playerHeight = playerOrigin_z - origin_z;
attackCount = 2;
if(playerHeight <= 16) {
PushAttack(ATTACK_GROUNDPOUND);
}
attack_flags |= SelectRandomAttack();
}
return attack_flags;
}
void monster_hunter_invul::do_attack( float attack_flags ) {
if ( attack_flags & ATTACK_MELEE ) {
combat_melee();
} else if ( attack_flags & ATTACK_MISSILE ) {
combat_range();
} else if ( attack_flags & ATTACK_GROUNDPOUND_NODAMAGE) {
combat_shockwave_nodamage();
} else if ( attack_flags & ATTACK_GROUNDPOUND) {
combat_shockwave();
} else if ( attack_flags & ATTACK_ELECTRIC_WALL) {
combat_electricwall();
}
if(hunterState == INVUL_STATE_NORMAL) {
nextAttack = DelayTime( INVUL_ATTACK_RATE_NORMAL );
} else if (hunterState == INVUL_STATE_INVUL) {
nextAttack = DelayTime( INVUL_ATTACK_RATE_INVUL );
} else if (hunterState == INVUL_STATE_INVUL_SURVIVAL) {
nextAttack = DelayTime( INVUL_ATTACK_RATE_INVUL_SURVIVAL );
}
}
/*
=====================
monster_hunter_invul::combat_range
=====================
*/
void monster_hunter_invul::combat_range() {
faceEnemy();
stopMove();
animState( ANIMCHANNEL_TORSO, "Torso_RangeAttack", 4 );
waitAction( "range_attack" );
}
/*
=====================
monster_hunter_invul::combat_melee
=====================
*/
void monster_hunter_invul::combat_melee() {
lookAt( getEnemy(), 100 );
faceEnemy();
animState( ANIMCHANNEL_TORSO, "Torso_MeleeAttack", 5 );
waitAction( "melee_attack" );
lookAt( getEnemy(), 1 );
stopMove();
}
/*void monster_hunter_invul::combat_electroblast() {
entity ent;
vector loc;
ent = sys.getEntity("hunter_invul_location");
loc = ent.getOrigin();
slideTo(loc, 0);
allowMovement(false);
animState( ANIMCHANNEL_TORSO, "Torso_ElectroBlast", 5 );
waitAction( "electroblast" );
allowMovement(true);
}*/
void monster_hunter_invul::combat_shockwave() {
/*entity ent;
vector loc;
ent = sys.getEntity("hunter_invul_location");
loc = ent.getOrigin();
slideTo(loc, 0);*/
faceEnemy();
stopMove();
allowMovement(false);
animState( ANIMCHANNEL_TORSO, "Torso_Shockwave", 5 );
waitAction( "shockwave" );
allowMovement(true);
}
void monster_hunter_invul::combat_electricwall() {
faceEnemy();
stopMove();
lookAtEnemy( 0 );
animState( ANIMCHANNEL_TORSO, "Torso_ElectricWallAttack", 4 );
waitAction( "electricwall_attack" );
}
void monster_hunter_invul::combat_shockwave_nodamage() {
/*entity ent;
vector loc;
ent = sys.getEntity("hunter_invul_location");
loc = ent.getOrigin();
slideTo(loc, 0);*/
faceEnemy();
stopMove();
allowMovement(false);
animState( ANIMCHANNEL_TORSO, "Torso_ShockwaveNoDamage", 5 );
waitAction( "shockwave" );
allowMovement(true);
}
void monster_hunter_invul::combat_invulrange_short() {
//sys.print("Range Attack Short\n");
allowMovement(false);
animState( ANIMCHANNEL_TORSO, "Torso_InvulRange_Short", 5 );
waitAction( "invulrange_short" );
allowMovement(true);
}
void monster_hunter_invul::combat_invulrange_tall() {
//sys.print("Range Attack Tall\n");
allowMovement(false);
animState( ANIMCHANNEL_TORSO, "Torso_InvulRange_Tall", 5 );
waitAction( "invulrange_tall" );
allowMovement(true);
}
void monster_hunter_invul::spawn_electric_wall( vector org ) {
entity ent;
vector ang;
ang_y = sys.random( 360 );
ent = sys.spawn( "invul_electricwall" );
ent.setKey( "cinematic_remove", "1" ); // make sure it gets removed in cinematics
ent.setShaderParm( 4, -sys.getTime() );
ent.setShaderParm( 5, sys.random( 1 ) );
ent.setOrigin( org );
ent.setAngles( ang );
ent.setOwner( self );
ent.disable();
sys.wait( 0.2 );
ent.enable();
sys.wait( 0.5 );
ent.disable();
sys.wait( 2.0 );
ent.remove();
}
void monster_hunter_invul::electric_wall_loop() {
float i;
vector dir;
vector ang;
vector pos;
float frac;
ang = getAngles();
dir = sys.angToForward( ang ) * ARCH_ELECTRIC_WALL_SEPERATION;
pos = getOrigin();
for( i = 0; i < ARCH_ELECTRIC_WALL_NUM; i++ ) {
pos_z += 48;
if ( sys.trace( pos, pos + dir, '-8 -8 0', '8 8 16', MASK_SOLID, self ) < 1 ) {
break;
}
pos = pos + dir;
frac = sys.trace( pos, pos - '0 0 96', '-8 -8 0', '8 8 16', MASK_SOLID, self );
if ( frac == 1 ) {
break;
}
pos_z -= 96 * frac;
thread spawn_electric_wall( pos );
sys.wait( 0.075 );
}
}
void monster_hunter_invul::electric_wall() {
thread electric_wall_loop();
}
#define EFFECT_DELAY 2
void monster_hunter_invul::electric_effect_loop() {
float currentTime;
float nextEffect;
nextEffect = 0;
/*while(1) {
if(hunterState == INVUL_STATE_INVUL_SURVIVAL || hunterState == INVUL_STATE_INVUL) {
currentTime = sys.getTime();
if(currentTime >= nextEffect) {
float selectedEffect;
entity ent;
selectedEffect = sys.randomInt(2);
//sys.print("Playing Effect " + selectedEffect + "\n");
if(selectedEffect == 0) {
sys.setSpawnArg( "fx", "fx/hunter/invulnerability/lightning_fx1" );
} else {
sys.setSpawnArg( "fx", "fx/hunter/invulnerability/lightning_fx2" );
}
sys.setSpawnArg( "start", "1" );
ent = sys.spawn( "func_fx" );
ent.setOrigin( getOrigin() );
nextEffect = DelayTime(EFFECT_DELAY);
}
}
waitFrame();
}*/
}