1028 lines
26 KiB
Plaintext
1028 lines
26 KiB
Plaintext
// IW6 GSC SOURCE
|
|
// Generated by https://github.com/xensik/gsc-tool
|
|
|
|
load_gargoyle_fx()
|
|
{
|
|
level._effect["gargoyle_darts_fire"] = loadfx( "vfx/gameplay/alien/vfx_alien_gargoyle_darts_01" );
|
|
}
|
|
|
|
gargoyle_level_init()
|
|
{
|
|
if ( !isdefined( level.alien_funcs ) )
|
|
level.agent_funcs = [];
|
|
|
|
level.alien_funcs["gargoyle"]["approach"] = ::gargoyle_approach;
|
|
level.alien_funcs["gargoyle"]["combat"] = maps\mp\agents\alien\_alien_think::default_alien_combat;
|
|
level.alien_funcs["gargoyle"]["badpath"] = ::handle_badpath;
|
|
}
|
|
|
|
gargoyle_init()
|
|
{
|
|
var_0 = gettime();
|
|
self.last_stun_time = var_0;
|
|
self.last_hover_attack_time = var_0;
|
|
self.last_strafe_attack_time = var_0;
|
|
self.last_fly_time = var_0;
|
|
self.last_close_range_attack_time = var_0;
|
|
self.last_air_dodge_time = var_0;
|
|
self.in_air = 0;
|
|
self.air_complete = 0;
|
|
self.air_dodge_allowed = 0;
|
|
self.cannothypno = 1;
|
|
self.fly_end_position = undefined;
|
|
setup_hover_turret();
|
|
|
|
if ( getdvarint( "scr_gargoyle_disable_fly_intro" ) != 1 )
|
|
fly_intro_attack( undefined );
|
|
}
|
|
|
|
fly_intro( var_0 )
|
|
{
|
|
self scragentsetphysicsmode( "noclip" );
|
|
self scragentsetorientmode( "face angle abs", self.angles );
|
|
self.fly_end_position = self.origin + anglestoforward( self.angles ) * 1600;
|
|
self.in_intro = 1;
|
|
self.in_air = 1;
|
|
self.fly_type = "attack";
|
|
fly( var_0 );
|
|
self.air_dodge_allowed = 1;
|
|
thread air_damage_monitor();
|
|
self.air_attacks_available = 0;
|
|
self.in_intro = 0;
|
|
}
|
|
|
|
handle_badpath( var_0 )
|
|
{
|
|
var_1 = 150;
|
|
var_2 = self.origin + ( 0, 0, var_1 );
|
|
|
|
if ( self.badpathcount > 3 )
|
|
{
|
|
self.badpathcount = 0;
|
|
self.badpath = 0;
|
|
perform_melee( var_0, "takeoff" );
|
|
clear_goal_position();
|
|
}
|
|
else
|
|
maps\mp\agents\alien\_alien_think::handle_badpath( var_0 );
|
|
}
|
|
|
|
gargoyle_approach( var_0, var_1 )
|
|
{
|
|
if ( is_enemy_vanguard( var_0 ) )
|
|
return approach_vanguard( var_0 );
|
|
else
|
|
return approach_enemy( var_0 );
|
|
}
|
|
|
|
approach_enemy( var_0 )
|
|
{
|
|
if ( should_stun() )
|
|
{
|
|
if ( distancesquared( self.close_proximity_enemy.origin, self.origin ) > 22500 )
|
|
move_towards_enemy( self.close_proximity_enemy );
|
|
|
|
return "stun";
|
|
}
|
|
|
|
if ( should_begin_air_attacks( var_0 ) )
|
|
{
|
|
var_1 = proceed_to_air_node( var_0 );
|
|
|
|
if ( var_1 )
|
|
return "takeoff";
|
|
}
|
|
|
|
if ( should_end_air_attacks( var_0 ) )
|
|
return "land";
|
|
|
|
while ( self.in_air )
|
|
{
|
|
if ( should_strafe_run( var_0 ) )
|
|
return "strafe_run";
|
|
|
|
if ( should_fly_to_node( var_0, 800, 1, 350 ) )
|
|
{
|
|
self.fly_type = "move";
|
|
return "fly";
|
|
}
|
|
|
|
if ( should_hover_attack( var_0 ) )
|
|
return "hover_attack";
|
|
|
|
wait 0.05;
|
|
}
|
|
|
|
return "none";
|
|
}
|
|
|
|
approach_vanguard( var_0 )
|
|
{
|
|
if ( should_begin_air_attacks( var_0 ) )
|
|
{
|
|
var_1 = proceed_to_air_node( var_0 );
|
|
|
|
if ( var_1 )
|
|
return "takeoff";
|
|
}
|
|
|
|
while ( self.in_air )
|
|
{
|
|
if ( should_fly_to_node( var_0, 1600, 1, 0 ) )
|
|
{
|
|
self.fly_type = "attack";
|
|
return "fly";
|
|
}
|
|
|
|
if ( should_hover_attack( var_0 ) )
|
|
return "hover_attack";
|
|
|
|
wait 0.05;
|
|
}
|
|
|
|
return "none";
|
|
}
|
|
|
|
find_air_attack_node( var_0 )
|
|
{
|
|
var_1 = getnodesinradius( var_0.origin, 1600.0, 700.0, 512, "jump" );
|
|
var_2 = [];
|
|
|
|
foreach ( var_4 in var_1 )
|
|
{
|
|
if ( isdefined( var_4.script_noteworthy ) && var_4.script_noteworthy == "flyable" )
|
|
var_2[var_2.size] = var_4;
|
|
}
|
|
|
|
var_6 = get_air_node_rated( var_0, var_2 );
|
|
return var_6;
|
|
}
|
|
|
|
get_air_node_rated( var_0, var_1 )
|
|
{
|
|
var_2 = [];
|
|
var_2["direction"] = "override";
|
|
var_2["direction_override"] = vectornormalize( self.origin - var_0.origin );
|
|
var_2["direction_weight"] = 3.0;
|
|
var_2["min_height"] = 0.0;
|
|
var_2["max_height"] = 512.0;
|
|
var_2["height_weight"] = 1.0;
|
|
var_2["enemy_los"] = 1;
|
|
var_2["enemy_los_weight"] = 10.0;
|
|
var_2["min_dist_from_enemy"] = 700.0;
|
|
var_2["max_dist_from_enemy"] = 1600.0;
|
|
var_2["desired_dist_from_enemy"] = 600.0;
|
|
var_2["dist_from_enemy_weight"] = 4.0;
|
|
var_2["min_dist_from_all_enemies"] = 200.0;
|
|
var_2["min_dist_from_all_enemies_weight"] = 1.0;
|
|
var_2["not_recently_used_weight"] = 5.0;
|
|
var_2["random_weight"] = 1.0;
|
|
var_2["test_offset"] = ( 0, 0, 128 );
|
|
return maps\mp\agents\alien\_alien_think::get_retreat_node_rated( var_0, var_2, var_1 );
|
|
}
|
|
|
|
move_towards_enemy( var_0 )
|
|
{
|
|
var_1 = maps\mp\agents\alien\_alien_think::do_initial_approach( var_0 );
|
|
maps\mp\agents\alien\_alien_think::go_for_swipe( var_0, var_1 );
|
|
}
|
|
|
|
can_do_pain( var_0 )
|
|
{
|
|
switch ( var_0 )
|
|
{
|
|
case "move":
|
|
return 0;
|
|
case "idle":
|
|
case "melee":
|
|
return !self.in_air;
|
|
default:
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
get_pain_anim_state( var_0 )
|
|
{
|
|
switch ( var_0 )
|
|
{
|
|
case "idle":
|
|
return get_idle_pain_anim_state();
|
|
default:
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
get_idle_pain_anim_state()
|
|
{
|
|
if ( !self.in_air )
|
|
return undefined;
|
|
|
|
return "idle_fly_pain";
|
|
}
|
|
|
|
should_immediate_ragdoll_on_death()
|
|
{
|
|
if ( self.in_air )
|
|
return 1;
|
|
|
|
return undefined;
|
|
}
|
|
|
|
get_turn_in_place_anim_state()
|
|
{
|
|
if ( !self.in_air )
|
|
return undefined;
|
|
|
|
return "air_turn_in_place";
|
|
}
|
|
|
|
can_retreat( var_0 )
|
|
{
|
|
return !self.in_air;
|
|
}
|
|
|
|
should_begin_air_attacks( var_0 )
|
|
{
|
|
if ( self.in_air )
|
|
return 0;
|
|
|
|
var_1 = find_air_attack_node( var_0 );
|
|
|
|
if ( !isdefined( var_1 ) )
|
|
return 0;
|
|
|
|
self.air_jump_node = var_1;
|
|
return 1;
|
|
}
|
|
|
|
should_end_air_attacks( var_0 )
|
|
{
|
|
if ( !self.in_air )
|
|
return 0;
|
|
|
|
return self.air_complete;
|
|
}
|
|
|
|
should_hover_attack( var_0 )
|
|
{
|
|
if ( !isalive( var_0 ) )
|
|
return 0;
|
|
|
|
if ( gettime() < self.last_hover_attack_time + 3000 )
|
|
return 0;
|
|
|
|
var_1 = self gettagorigin( "TAG_tail" );
|
|
var_2 = get_enemy_target_position( var_0 );
|
|
var_3 = bullettracepassed( var_1, var_2, 0, undefined );
|
|
wait 0.05;
|
|
return var_3;
|
|
}
|
|
|
|
should_stun( var_0 )
|
|
{
|
|
return isdefined( self.close_proximity_enemy ) && !self.in_air;
|
|
}
|
|
|
|
should_close_range_attack()
|
|
{
|
|
return !self.in_air && gettime() > self.last_close_range_attack_time + 8000;
|
|
}
|
|
|
|
is_enemy_vanguard( var_0 )
|
|
{
|
|
return isdefined( var_0.helitype ) && var_0.helitype == "remote_uav";
|
|
}
|
|
|
|
get_possible_fly_node_points( var_0, var_1 )
|
|
{
|
|
var_2 = anglestoright( self.angles );
|
|
var_3 = anglestoforward( self.angles );
|
|
var_4 = [];
|
|
var_4[0] = self.origin + var_3 * var_1 + var_0;
|
|
var_4[1] = self.origin + var_2 * var_1 + var_0;
|
|
var_4[2] = self.origin + var_2 * -1 * var_1 + var_0;
|
|
var_4[3] = self.origin + vectornormalize( var_2 + var_3 ) * var_1 + var_0;
|
|
var_4[4] = self.origin + vectornormalize( var_2 * -1 + var_3 ) * var_1 + var_0;
|
|
var_4 = common_scripts\utility::array_randomize( var_4 );
|
|
return var_4;
|
|
}
|
|
|
|
should_fly_to_node( var_0, var_1, var_2, var_3 )
|
|
{
|
|
var_4 = 0.939;
|
|
var_5 = 75;
|
|
var_6 = -300;
|
|
var_7 = 90000;
|
|
|
|
if ( gettime() <= self.last_fly_time + 6000 )
|
|
return 0;
|
|
|
|
var_8 = ( 0, 0, max( var_6, var_0.origin[2] - self.origin[2] ) + var_3 );
|
|
var_9 = get_possible_fly_node_points( var_8, var_1 );
|
|
var_10 = undefined;
|
|
|
|
for ( var_11 = 0; var_11 < var_9.size; var_11++ )
|
|
{
|
|
var_12 = var_9[var_11];
|
|
var_13 = vectornormalize( var_0.origin - self.origin );
|
|
var_14 = vectornormalize( var_12 - self.origin );
|
|
var_15 = vectordot( var_13, var_14 ) > var_4 && abs( var_8[2] ) < var_5 || distancesquared( var_0.origin, var_12 ) < var_7;
|
|
|
|
if ( !var_15 && self aiphysicstracepassed( self.origin, var_12, self.radius, self.height, 1 ) )
|
|
{
|
|
if ( !var_2 || has_valid_ground_nodes( var_12 ) )
|
|
{
|
|
var_10 = var_12;
|
|
break;
|
|
}
|
|
}
|
|
|
|
wait 0.05;
|
|
}
|
|
|
|
self.fly_end_position = var_10;
|
|
return isdefined( self.fly_end_position );
|
|
}
|
|
|
|
should_strafe_run( var_0, var_1, var_2 )
|
|
{
|
|
if ( !isdefined( var_1 ) )
|
|
var_1 = self.origin;
|
|
|
|
if ( !isdefined( var_2 ) )
|
|
var_2 = 0;
|
|
|
|
var_3 = 1000000;
|
|
var_4 = 90000;
|
|
var_5 = distance2dsquared( var_0.origin, self.origin );
|
|
|
|
if ( var_5 > var_3 || var_5 < var_4 )
|
|
return 0;
|
|
|
|
var_6 = 1150;
|
|
|
|
if ( !var_2 && gettime() <= self.last_strafe_attack_time + 12000 )
|
|
return 0;
|
|
|
|
var_7 = vectornormalize( ( var_0.origin - self.origin ) * ( 1, 1, 0 ) );
|
|
var_8 = var_1 + var_7 * var_6;
|
|
|
|
if ( !self aiphysicstracepassed( var_1, var_8, self.radius, self.height, 1 ) )
|
|
return 0;
|
|
|
|
return has_valid_ground_nodes( var_8 );
|
|
}
|
|
|
|
has_valid_ground_nodes( var_0 )
|
|
{
|
|
var_1 = 1000;
|
|
var_2 = var_0 - ( 0, 0, var_1 );
|
|
var_3 = bullettrace( var_0, var_2, 0 );
|
|
var_4 = getnodesinradius( var_3["position"], 500, 0, 128 );
|
|
return isdefined( var_4 ) && var_4.size > 0;
|
|
}
|
|
|
|
air_damage_monitor()
|
|
{
|
|
self endon( "death" );
|
|
self endon( "air_complete" );
|
|
var_0 = [];
|
|
|
|
for (;;)
|
|
{
|
|
self waittill( "damage", var_1 );
|
|
|
|
if ( !self.air_dodge_allowed )
|
|
continue;
|
|
|
|
var_2 = gettime();
|
|
var_3 = var_2 - 1200;
|
|
|
|
for ( var_4 = var_0.size - 1; var_4 >= 0; var_4-- )
|
|
{
|
|
if ( var_0[var_4]["time"] > var_3 )
|
|
continue;
|
|
|
|
var_0 = maps\mp\alien\_utility::array_remove_index( var_0, var_4 );
|
|
}
|
|
|
|
var_5 = var_0.size;
|
|
var_0[var_5]["time"] = var_2;
|
|
var_0[var_5]["damage"] = var_1;
|
|
var_6 = 0;
|
|
|
|
for ( var_4 = 0; var_4 < var_0.size; var_4++ )
|
|
var_6 = var_6 + var_0[var_4]["damage"];
|
|
|
|
if ( var_6 > 100 )
|
|
{
|
|
try_damage_air_dodge();
|
|
wait 0.2;
|
|
}
|
|
}
|
|
}
|
|
|
|
proceed_to_air_node( var_0 )
|
|
{
|
|
self endon( "death" );
|
|
self scragentsetgoalnode( self.air_jump_node );
|
|
self scragentsetgoalradius( 32 );
|
|
thread check_player_proximity();
|
|
var_1 = common_scripts\utility::waittill_any_return( "goal_reached", "close_range_attack" );
|
|
|
|
if ( var_1 == "close_range_attack" )
|
|
return 0;
|
|
|
|
self notify( "at_air_node" );
|
|
|
|
if ( isdefined( var_0 ) )
|
|
{
|
|
maps\mp\agents\alien\_alien_anim_utils::turntowardsentity( var_0 );
|
|
self scragentsetorientmode( "face enemy" );
|
|
}
|
|
|
|
clear_goal_position();
|
|
return 1;
|
|
}
|
|
|
|
check_player_proximity()
|
|
{
|
|
self endon( "death" );
|
|
self endon( "at_air_node" );
|
|
self endon( "alien_main_loop_restart" );
|
|
var_0 = 300;
|
|
|
|
for (;;)
|
|
{
|
|
if ( should_close_range_attack() )
|
|
{
|
|
foreach ( var_2 in level.players )
|
|
{
|
|
if ( distancesquared( self.origin, var_2.origin ) < var_0 * var_0 )
|
|
{
|
|
close_proximity_attack( var_2 );
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
wait 0.1;
|
|
}
|
|
}
|
|
|
|
close_proximity_attack( var_0 )
|
|
{
|
|
self.close_proximity_enemy = var_0;
|
|
clear_goal_position();
|
|
self notify( "alien_main_loop_restart" );
|
|
}
|
|
|
|
air_dodge( var_0 )
|
|
{
|
|
var_1 = "air_dodge";
|
|
self scragentsetanimmode( "anim deltas" );
|
|
maps\mp\agents\_scriptedagents::playanimnuntilnotetrack( var_1, self.air_dodge_index, var_1 );
|
|
clear_goal_position();
|
|
self.last_air_dodge_time = gettime();
|
|
}
|
|
|
|
takeoff( var_0 )
|
|
{
|
|
var_1 = "ground_takeoff";
|
|
self.in_air = 1;
|
|
self scragentsetanimmode( "anim deltas" );
|
|
maps\mp\agents\_scriptedagents::playanimnuntilnotetrack( var_1, 0, var_1 );
|
|
self.air_dodge_allowed = 1;
|
|
thread air_damage_monitor();
|
|
self.air_attacks_available = 0;
|
|
clear_goal_position();
|
|
}
|
|
|
|
do_takeoff_lerp( var_0, var_1, var_2 )
|
|
{
|
|
self endon( "death" );
|
|
var_3 = 64.0;
|
|
var_4 = 0.4;
|
|
var_5 = self getanimentry( var_0, var_1 );
|
|
var_6 = getanimlength( var_5 );
|
|
var_7 = getmovedelta( var_5 );
|
|
var_8 = var_7[2];
|
|
var_9 = randomfloat( var_3 );
|
|
var_10 = self localtoworldcoords( var_7 ) + ( 0, 0, var_9 );
|
|
|
|
if ( !bullettracepassed( var_10, var_2.origin, 0, undefined ) )
|
|
return;
|
|
|
|
var_11 = getmovedelta( var_5, 0.0, var_4 );
|
|
var_12 = self localtoworldcoords( var_11 );
|
|
var_12 = ( var_12[0], var_12[1], var_12[2] + var_9 );
|
|
var_13 = var_6 * var_4;
|
|
self scragentdoanimlerp( self.origin, var_12, var_13 );
|
|
wait( var_13 );
|
|
self scragentsetanimmode( "anim deltas" );
|
|
}
|
|
|
|
clear_goal_position()
|
|
{
|
|
self scragentsetgoalpos( self.origin );
|
|
self scragentsetgoalradius( 4096 );
|
|
}
|
|
|
|
land( var_0 )
|
|
{
|
|
self endon( "death" );
|
|
var_1 = "ground_landing";
|
|
self scragentsetorientmode( "face angle abs", self.angles );
|
|
self notify( "air_complete" );
|
|
thread do_landing_lerp( var_1, 0 );
|
|
maps\mp\agents\_scriptedagents::playanimnuntilnotetrack( var_1, 0, var_1 );
|
|
self.in_air = 0;
|
|
self.air_complete = 0;
|
|
clear_goal_position();
|
|
}
|
|
|
|
do_landing_lerp( var_0, var_1 )
|
|
{
|
|
var_2 = 1000;
|
|
var_3 = 100;
|
|
var_4 = 0.4;
|
|
var_5 = 10;
|
|
var_6 = self.origin - ( 0, 0, var_2 );
|
|
var_7 = self.origin + ( 0, 0, var_3 );
|
|
var_8 = self aiphysicstrace( var_7, var_6, self.radius, self.height, 1 );
|
|
var_9 = self getanimentry( var_0, var_1 );
|
|
var_10 = getanimlength( var_9 );
|
|
var_11 = getmovedelta( var_9, var_4, 1.0 );
|
|
var_12 = length( var_11 * ( 0, 0, 1 ) );
|
|
var_13 = var_8 + ( 0, 0, var_12 + var_5 );
|
|
var_14 = var_10 * var_4;
|
|
self scragentdoanimlerp( self.origin, var_13, var_14 );
|
|
wait( var_14 );
|
|
self scragentsetanimmode( "anim deltas" );
|
|
}
|
|
|
|
gargoyle_idle_state( var_0 )
|
|
{
|
|
if ( self.in_air )
|
|
return "idle_fly";
|
|
|
|
return undefined;
|
|
}
|
|
|
|
run_to_swipe( var_0 )
|
|
{
|
|
maps\mp\agents\alien\_alien_think::run_near_enemy( 150, var_0 );
|
|
return 1;
|
|
}
|
|
|
|
stun_attack( var_0 )
|
|
{
|
|
perform_melee( var_0, "stun" );
|
|
}
|
|
|
|
wing_swipe_attack( var_0 )
|
|
{
|
|
perform_melee( var_0, "wing_swipe" );
|
|
}
|
|
|
|
hover_attack( var_0 )
|
|
{
|
|
perform_melee( var_0, "hover_attack" );
|
|
}
|
|
|
|
strafe_run_attack( var_0 )
|
|
{
|
|
perform_melee( var_0, "strafe_run" );
|
|
}
|
|
|
|
takeoff_attack( var_0 )
|
|
{
|
|
perform_melee( var_0, "takeoff" );
|
|
}
|
|
|
|
landing_attack( var_0 )
|
|
{
|
|
perform_melee( var_0, "land" );
|
|
}
|
|
|
|
fly_attack( var_0 )
|
|
{
|
|
perform_melee( var_0, "fly" );
|
|
}
|
|
|
|
fly_intro_attack( var_0 )
|
|
{
|
|
perform_melee( var_0, "fly_intro" );
|
|
}
|
|
|
|
perform_melee( var_0, var_1 )
|
|
{
|
|
self.melee_type = var_1;
|
|
|
|
if ( !isdefined( var_0 ) )
|
|
{
|
|
var_0 = findanenemy();
|
|
|
|
if ( !isdefined( var_0 ) )
|
|
return;
|
|
}
|
|
|
|
if ( maps\mp\agents\alien\_alien_think::melee_okay() )
|
|
{
|
|
self scragentbeginmelee( var_0 );
|
|
self scragentsetgoalpos( self.origin );
|
|
self scragentsetgoalradius( 4096.0 );
|
|
self waittill( "melee_complete" );
|
|
}
|
|
else
|
|
wait 0.2;
|
|
}
|
|
|
|
findanenemy()
|
|
{
|
|
if ( isdefined( self.enemy ) )
|
|
return self.enemy;
|
|
|
|
foreach ( var_1 in level.players )
|
|
{
|
|
if ( isdefined( var_1 ) )
|
|
return var_1;
|
|
}
|
|
|
|
return undefined;
|
|
}
|
|
|
|
stun( var_0 )
|
|
{
|
|
self endon( "death" );
|
|
self endon( "melee_pain_interrupt" );
|
|
maps\mp\agents\alien\_alien_anim_utils::turntowardsentity( var_0 );
|
|
self scragentsetorientmode( "face enemy" );
|
|
maps\mp\agents\_scriptedagents::playanimnuntilnotetrack( "attack_ground_whip", 0, "attack_melee", undefined, ::handlestunnotetracks );
|
|
maps\mp\agents\alien\_alien_melee::move_back( var_0, 1 );
|
|
self.close_proximity_enemy = undefined;
|
|
self.last_stun_time = gettime();
|
|
self.last_close_range_attack_time = gettime();
|
|
}
|
|
|
|
handlestunnotetracks( var_0, var_1, var_2, var_3 )
|
|
{
|
|
switch ( var_0 )
|
|
{
|
|
case "ground_whip":
|
|
stun_enemy( self.close_proximity_enemy );
|
|
break;
|
|
}
|
|
}
|
|
|
|
stun_enemy( var_0 )
|
|
{
|
|
var_1 = 3.0;
|
|
|
|
if ( isplayer( var_0 ) && isalive( var_0 ) )
|
|
maps\mp\agents\alien\_alien_melee::melee_dodamage( var_0, "swipe" );
|
|
}
|
|
|
|
wing_swipe( var_0 )
|
|
{
|
|
self endon( "death" );
|
|
self endon( "melee_pain_interrupt" );
|
|
maps\mp\agents\alien\_alien_anim_utils::turntowardsentity( var_0 );
|
|
self scragentsetorientmode( "face enemy" );
|
|
maps\mp\agents\alien\_alien_melee::try_preliminary_swipes( "swipe", var_0, 125, 150 );
|
|
maps\mp\agents\alien\_alien_melee::move_back( var_0, 1 );
|
|
self.last_close_range_attack_time = gettime();
|
|
}
|
|
|
|
hover( var_0 )
|
|
{
|
|
self endon( "death" );
|
|
self endon( "damage_dodge_interrupt" );
|
|
maps\mp\agents\alien\_alien_anim_utils::turntowardsentity( var_0 );
|
|
self scragentsetorientmode( "face enemy" );
|
|
|
|
if ( gettime() > self.last_air_dodge_time + 1500 )
|
|
var_1 = 0;
|
|
else
|
|
var_1 = 1;
|
|
|
|
var_2 = get_hover_start_anim_mode( "attack_air_hover_spit_start", var_1 );
|
|
self scragentsetanimmode( var_2 );
|
|
maps\mp\agents\_scriptedagents::playanimnuntilnotetrack( "attack_air_hover_spit_start", var_1, "attack_melee" );
|
|
var_3 = "hover_spit_end";
|
|
self scragentsetanimmode( "anim deltas" );
|
|
|
|
if ( isdefined( var_0 ) )
|
|
{
|
|
thread hover_spit( var_0, var_3 );
|
|
maps\mp\agents\_scriptedagents::playanimnuntilnotetrack( "attack_air_hover_spit_loop", 0, "attack_melee" );
|
|
}
|
|
|
|
self notify( var_3 );
|
|
maps\mp\agents\_scriptedagents::playanimnuntilnotetrack( "attack_air_hover_spit_stop", 0, "attack_melee" );
|
|
self.last_hover_attack_time = gettime();
|
|
register_air_attack_end( var_0 );
|
|
|
|
if ( !self.air_complete && isdefined( var_0 ) )
|
|
try_air_dodge( var_0 );
|
|
}
|
|
|
|
get_hover_start_anim_mode( var_0, var_1 )
|
|
{
|
|
var_2 = self getanimentry( var_0, var_1 );
|
|
var_3 = getmovedelta( var_2 );
|
|
var_4 = self localtoworldcoords( var_3 );
|
|
|
|
if ( self aiphysicstracepassed( self.origin, var_4, self.radius, self.height, 1 ) )
|
|
return "anim deltas";
|
|
|
|
return "code_move";
|
|
}
|
|
|
|
try_air_dodge( var_0 )
|
|
{
|
|
var_1 = randomint( 3 );
|
|
return do_dodge( var_0, var_1 );
|
|
}
|
|
|
|
try_air_dodge_up( var_0 )
|
|
{
|
|
var_1 = randomint( 2 ) + 2;
|
|
return do_dodge( var_0, var_1 );
|
|
}
|
|
|
|
do_dodge( var_0, var_1 )
|
|
{
|
|
var_2 = "air_dodge";
|
|
var_3 = self getanimentry( var_2, var_1 );
|
|
var_4 = getmovedelta( var_3 );
|
|
var_5 = length( var_4 );
|
|
var_6 = vectornormalize( var_4 ) * ( var_5 + 50 );
|
|
var_7 = self localtoworldcoords( var_6 );
|
|
|
|
if ( !self aiphysicstracepassed( self.origin, var_7, self.radius, self.height, 1 ) )
|
|
return 0;
|
|
|
|
if ( !bullettracepassed( var_7, get_enemy_target_position( var_0 ), 0, undefined ) )
|
|
return 0;
|
|
|
|
self scragentsetanimmode( "anim deltas" );
|
|
maps\mp\agents\_scriptedagents::playanimnuntilnotetrack( var_2, var_1, var_2 );
|
|
clear_goal_position();
|
|
return 1;
|
|
}
|
|
|
|
try_damage_air_dodge()
|
|
{
|
|
var_0 = "air_dodge";
|
|
var_1 = [ 0, 1, 2, 3, 4, 5 ];
|
|
var_1 = common_scripts\utility::array_randomize( var_1 );
|
|
|
|
for ( var_2 = 0; var_2 < var_1.size; var_2++ )
|
|
{
|
|
var_3 = var_1[var_2];
|
|
var_4 = self getanimentry( var_0, var_3 );
|
|
var_5 = getmovedelta( var_4 );
|
|
var_6 = length( var_5 );
|
|
var_7 = vectornormalize( var_5 ) * ( var_6 + 50 );
|
|
var_8 = self localtoworldcoords( var_7 );
|
|
|
|
if ( self aiphysicstracepassed( self.origin, var_8, self.radius, self.height, 1 ) )
|
|
{
|
|
if ( !isdefined( self.enemy ) || bullettracepassed( var_8, get_enemy_target_position( self.enemy ), 0, undefined ) )
|
|
{
|
|
self.air_dodge_index = var_3;
|
|
perform_melee( self.enemy, "air_dodge" );
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
register_air_attack_end( self.enemy, 1 );
|
|
self notify( "damage_dodge_interrupt" );
|
|
|
|
if ( self.statelocked )
|
|
self.statelocked = 0;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
wait 0.05;
|
|
}
|
|
}
|
|
|
|
get_enemy_target_position( var_0 )
|
|
{
|
|
if ( issentient( var_0 ) )
|
|
{
|
|
if ( !isdefined( var_0.usingremote ) )
|
|
return var_0 geteye();
|
|
else
|
|
return var_0.origin + ( 0, 0, 32 );
|
|
}
|
|
|
|
return var_0.origin;
|
|
}
|
|
|
|
hover_spit( var_0, var_1 )
|
|
{
|
|
self endon( var_1 );
|
|
self endon( "death" );
|
|
self endon( "melee_pain_interrupt" );
|
|
self endon( "killanimscript" );
|
|
self endon( "damage_dodge_interrupt" );
|
|
var_2 = get_enemy_target_position( var_0 );
|
|
var_3 = "hover_spit_complete";
|
|
|
|
for (;;)
|
|
{
|
|
if ( isdefined( var_0 ) )
|
|
var_2 = get_enemy_target_position( var_0 );
|
|
|
|
fire_weapon( var_2, 0.2, var_1 );
|
|
}
|
|
|
|
self notify( var_3 );
|
|
}
|
|
|
|
fire_weapon( var_0, var_1, var_2 )
|
|
{
|
|
if ( isdefined( self ) && isdefined( self.shooting_target ) )
|
|
{
|
|
self.shooting_target.origin = var_0;
|
|
self.hover_turret settargetentity( self.shooting_target );
|
|
self.hover_turret shootturret();
|
|
wait( var_1 );
|
|
}
|
|
}
|
|
|
|
fly( var_0 )
|
|
{
|
|
self endon( "death" );
|
|
self.air_dodge_allowed = 0;
|
|
var_1 = self.fly_end_position - self.origin;
|
|
maps\mp\agents\alien\_alien_anim_utils::turntowardsvector( var_1 );
|
|
self scragentsetorientmode( "face angle abs", vectortoangles( var_1 ) );
|
|
self scragentsetanimmode( "anim deltas" );
|
|
maps\mp\agents\_scriptedagents::playanimnuntilnotetrack( "attack_fly_start", 0, "attack_melee" );
|
|
|
|
if ( self.fly_type == "attack" )
|
|
fly_loop();
|
|
|
|
var_2 = get_fly_end_anim( var_0 );
|
|
maps\mp\agents\_scriptedagents::playanimnuntilnotetrack( var_2, 0, "attack_melee" );
|
|
self.last_fly_time = gettime();
|
|
register_air_attack_end( var_0, 0 );
|
|
}
|
|
|
|
fly_loop()
|
|
{
|
|
var_0 = randomint( self getanimentrycount( "attack_fly_loop" ) );
|
|
maps\mp\agents\_scriptedagents::playanimnuntilnotetrack( "attack_fly_loop", var_0, "attack_melee" );
|
|
}
|
|
|
|
strafe_run( var_0 )
|
|
{
|
|
self endon( "death" );
|
|
self.air_dodge_allowed = 0;
|
|
maps\mp\agents\alien\_alien_anim_utils::turntowardsentity( var_0 );
|
|
self scragentsetorientmode( "face angle abs", self.angles );
|
|
self scragentsetanimmode( "anim deltas" );
|
|
var_1 = "strafe_run_complete";
|
|
maps\mp\agents\_scriptedagents::playanimnuntilnotetrack( "attack_strafe_run_start", 0, "attack_melee" );
|
|
thread strafing_shoot( var_0, var_1 );
|
|
var_2 = maps\mp\agents\_scriptedagents::getrandomanimentry( "attack_strafe_run_loop" );
|
|
maps\mp\agents\_scriptedagents::playanimnuntilnotetrack( "attack_strafe_run_loop", var_2, "attack_melee" );
|
|
self notify( var_1 );
|
|
var_3 = get_fly_end_anim( var_0 );
|
|
maps\mp\agents\_scriptedagents::playanimnuntilnotetrack( var_3, 0, "attack_melee" );
|
|
self.last_strafe_attack_time = gettime();
|
|
register_air_attack_end( var_0 );
|
|
}
|
|
|
|
get_fly_end_anim( var_0 )
|
|
{
|
|
var_1 = vectornormalize( var_0.origin - self.origin );
|
|
var_2 = anglestoforward( self.angles );
|
|
|
|
if ( vectordot( var_1, var_2 ) > 0.0 )
|
|
return "attack_fly_stop";
|
|
|
|
return "attack_strafe_run_stop";
|
|
}
|
|
|
|
strafing_shoot( var_0, var_1 )
|
|
{
|
|
self endon( var_1 );
|
|
self endon( "death" );
|
|
self endon( "melee_pain_interrupt" );
|
|
self endon( "killanimscript" );
|
|
self endon( "damage_dodge_interrupt" );
|
|
|
|
if ( isdefined( var_0 ) )
|
|
self.hover_turret settargetentity( var_0 );
|
|
|
|
var_2 = 0.2;
|
|
var_3 = 300;
|
|
var_4 = 300;
|
|
var_5 = 20;
|
|
var_6 = vectornormalize( anglestoforward( self.angles ) * ( 1, 1, 0 ) );
|
|
var_7 = vectortoangles( var_6 );
|
|
var_8 = var_6;
|
|
wait( var_2 );
|
|
|
|
for (;;)
|
|
{
|
|
if ( isdefined( var_0 ) )
|
|
{
|
|
var_9 = vectornormalize( ( var_0.origin - self.origin ) * ( 1, 1, 0 ) );
|
|
var_10 = vectortoangles( var_9 );
|
|
|
|
if ( anglesdelta( var_10, var_7 ) > var_5 )
|
|
var_9 = var_8;
|
|
}
|
|
else
|
|
var_9 = var_8;
|
|
|
|
var_11 = self.origin + var_9 * var_3 - ( 0, 0, var_4 );
|
|
fire_weapon( var_11, 0.05, var_1 );
|
|
var_8 = var_9;
|
|
}
|
|
}
|
|
|
|
strafe_run_loop()
|
|
{
|
|
var_0 = randomint( 3 );
|
|
|
|
if ( var_0 == 0 )
|
|
maps\mp\agents\_scriptedagents::playanimnuntilnotetrack( "attack_strafe_run_loop_single", var_0, "attack_melee" );
|
|
else
|
|
{
|
|
var_1 = var_0 - 1;
|
|
maps\mp\agents\_scriptedagents::playanimnuntilnotetrack( "attack_strafe_run_loop_multi_start", var_1, "attack_melee" );
|
|
maps\mp\agents\_scriptedagents::playanimnuntilnotetrack( "attack_strafe_run_loop_multi_loop", var_1, "attack_melee" );
|
|
maps\mp\agents\_scriptedagents::playanimnuntilnotetrack( "attack_strafe_run_loop_multi_exit", var_1, "attack_melee" );
|
|
}
|
|
}
|
|
|
|
register_air_attack_end( var_0, var_1 )
|
|
{
|
|
if ( !isdefined( var_1 ) )
|
|
var_1 = 0;
|
|
|
|
var_2 = getdvarint( "scr_gargoyle_disable_fly_intro" ) != 1 && self.in_intro;
|
|
var_3 = !var_1 && randomfloat( 1.0 ) < 0.85 || var_2;
|
|
|
|
if ( var_3 && isdefined( var_0 ) )
|
|
{
|
|
var_4 = self.origin[2] - var_0.origin[2];
|
|
|
|
if ( var_4 > 800 )
|
|
var_3 = 0;
|
|
else if ( var_4 < 100 )
|
|
var_3 = try_air_dodge_up( var_0 );
|
|
}
|
|
|
|
if ( var_3 )
|
|
{
|
|
var_5 = 100;
|
|
var_6 = self.origin - ( 0, 0, var_5 );
|
|
|
|
if ( !self aiphysicstracepassed( self.origin, var_6, self.radius, self.height, 1 ) )
|
|
var_3 = try_air_dodge_up( var_0 );
|
|
}
|
|
|
|
self.air_complete = !var_3;
|
|
clear_goal_position();
|
|
self.idle_state_locked = !self.air_complete;
|
|
self.air_dodge_allowed = !self.air_complete;
|
|
}
|
|
|
|
setup_hover_turret()
|
|
{
|
|
self.hover_turret = [];
|
|
var_0 = "TAG_tail";
|
|
self.hover_turret = spawnturret( "misc_turret", self gettagorigin( var_0 ), "gargoyle_beam_mp" );
|
|
self.hover_turret linkto( self, var_0 );
|
|
self.hover_turret setmodel( "gargoyle_beam_gun" );
|
|
self.hover_turret.angles = self gettagangles( var_0 );
|
|
self.hover_turret.team = "axis";
|
|
self.hover_turret maketurretinoperable();
|
|
self.hover_turret makeunusable();
|
|
self.hover_turret.health = 1000000;
|
|
self.hover_turret.maxhealth = 1000000;
|
|
self.hover_turret setmode( "manual" );
|
|
self.hover_turret setturretteam( "axis" );
|
|
self.shooting_target = spawn( "script_origin", self.origin );
|
|
thread clean_up_turret();
|
|
}
|
|
|
|
clean_up_turret()
|
|
{
|
|
var_0 = self.hover_turret;
|
|
self waittill( "death" );
|
|
|
|
if ( isdefined( var_0 ) )
|
|
var_0 delete();
|
|
}
|