iw6-scripts/maps/mp/agents/alien/_alien_think.gsc
2024-02-13 13:20:49 +01:00

2491 lines
61 KiB
Plaintext

// IW6 GSC SOURCE
// Generated by https://github.com/xensik/gsc-tool
onenteranimstate( var_0, var_1 )
{
onexitanimstate( var_0, var_1 );
self.currentanimstate = var_1;
switch ( var_1 )
{
case "idle":
maps\mp\agents\alien\_alien_idle::main();
break;
case "move":
maps\mp\agents\alien\_alien_move::main();
break;
case "traverse":
maps\mp\agents\alien\_alien_traverse::main();
break;
case "melee":
maps\mp\agents\alien\_alien_melee::main();
break;
}
}
onexitanimstate( var_0, var_1 )
{
self notify( "killanimscript" );
switch ( var_0 )
{
case "idle":
maps\mp\agents\alien\_alien_idle::end_script();
break;
case "move":
maps\mp\agents\alien\_alien_move::end_script();
break;
case "traverse":
maps\mp\agents\alien\_alien_traverse::end_script();
break;
case "melee":
maps\mp\agents\alien\_alien_melee::end_script();
break;
}
}
monitorflash()
{
self endon( "death" );
for (;;)
{
self waittill( "flashbang", var_0, var_1, var_2, var_3, var_4, var_5 );
switch ( self.currentanimstate )
{
case "idle":
break;
case "move":
maps\mp\agents\alien\_alien_move::onflashbanged();
break;
}
}
}
ondamagefinish( var_0, var_1, var_2, var_3, var_4, var_5, var_6, var_7, var_8, var_9 )
{
self finishagentdamage( var_0, var_1, var_2, var_3, var_4, var_5, var_6, var_7, var_8, var_9, 0.0 );
if ( self.health <= 0 )
return 1;
var_10 = maps\mp\alien\_utility::is_trap( var_0 );
registerdamage( var_2 );
if ( isdefined( var_1 ) )
{
if ( isplayer( var_1 ) || isdefined( var_1.owner ) && isplayer( var_1.owner ) )
{
if ( !var_10 )
var_1 maps\mp\alien\_damage::check_for_special_damage( self, var_5, var_4 );
if ( var_2 > 0 )
level.alienbbdata["damage_done"] = level.alienbbdata["damage_done"] + var_2;
}
}
var_11 = should_do_stun_damage( var_5, var_4, var_1 );
if ( !var_11 )
{
var_12 = belowcumulativepainthreshold( var_1, var_5 );
if ( var_4 != "MOD_MELEE" && var_12 )
return;
if ( var_4 == "MOD_MELEE" && !var_12 && !should_melee_pushback() )
return;
}
if ( !isdefined( var_7 ) )
var_7 = anglestoforward( self.angles );
notifyjumppain( var_7, var_8, var_2, var_11 );
cleardamagehistory();
if ( var_11 && !var_10 )
{
thread maps\mp\alien\_alien_fx::fx_stun_damage();
var_3 = var_3 | level.idflags_stun;
}
switch ( self.currentanimstate )
{
case "idle":
maps\mp\agents\alien\_alien_idle::ondamage( var_0, var_1, var_2, var_3, var_4, var_5, var_6, var_7, var_8, var_9 );
break;
case "move":
maps\mp\agents\alien\_alien_move::ondamage( var_0, var_1, var_2, var_3, var_4, var_5, var_6, var_7, var_8, var_9 );
break;
case "melee":
maps\mp\agents\alien\_alien_melee::ondamage( var_0, var_1, var_2, var_3, var_4, var_5, var_6, var_7, var_8, var_9 );
break;
}
return 1;
}
should_do_stun_damage( var_0, var_1, var_2 )
{
if ( maps\mp\alien\_utility::get_alien_type() == "elite" )
return 0;
if ( maps\mp\alien\_utility::is_true( self.is_burning ) )
return 0;
if ( isdefined( var_2 ) && isplayer( var_2 ) && var_1 != "MOD_MELEE" )
{
var_3 = isdefined( var_0 ) && var_0 == var_2 getcurrentprimaryweapon();
return var_3 && var_2 maps\mp\alien\_utility::has_stun_ammo();
}
return 0;
}
should_melee_pushback()
{
if ( maps\mp\alien\_utility::get_alien_type() == "elite" )
return 0;
return 1;
}
notifyjumppain( var_0, var_1, var_2, var_3 )
{
self notify( "jump_pain", var_0, var_1, var_2, var_3 );
}
cleardamagehistory()
{
self.recentdamages = [];
self.damagelistindex = 0;
}
registerdamage( var_0 )
{
var_1 = [];
var_1["amount"] = var_0;
var_1["time"] = gettime();
self.recentdamages[self.damagelistindex] = var_1;
self.damagelistindex++;
if ( self.damagelistindex == level.damagelistsize )
self.damagelistindex = 0;
}
belowcumulativepainthreshold( var_0, var_1 )
{
var_2 = maps\mp\alien\_utility::get_alien_type();
var_3 = getcumulativedamage();
var_4 = level.alien_types[var_2].attributes["min_cumulative_pain_threshold"];
return var_3 < var_4;
}
getcumulativedamage()
{
var_0 = maps\mp\alien\_utility::get_alien_type();
var_1 = level.alien_types[var_0].attributes["min_cumulative_pain_buffer_time"] * 1000.0;
var_2 = 0;
var_3 = gettime();
for ( var_4 = 0; var_4 < self.recentdamages.size; var_4++ )
{
if ( var_3 - self.recentdamages[var_4]["time"] < var_1 )
var_2 = var_2 + self.recentdamages[var_4]["amount"];
}
return var_2;
}
gettargetpredictedposition( var_0, var_1 )
{
var_2 = var_0 getentityvelocity();
var_3 = var_0.origin + var_1 * var_2;
return var_3;
}
getattackposition( var_0, var_1, var_2 )
{
var_3 = 15;
var_4 = gettargetpredictedposition( var_0, var_2 );
var_5 = vectornormalize( self.origin - var_4 );
var_6 = var_4 + var_5 * var_1;
var_6 = getgroundposition( var_6, var_3, 64, 64 );
return var_6;
}
attemptmelee()
{
if ( !isdefined( self.enemy ) )
return 0;
self scragentbeginmelee( self.enemy );
return 1;
}
main()
{
self endon( "death" );
common_scripts\utility::waitframe();
var_0 = 0;
var_1 = 0;
if ( should_react_to_downed_enemies() )
thread downed_enemy_monitor();
for (;;)
{
if ( var_0 )
{
alien_test_loop();
continue;
}
if ( var_1 )
{
alien_test_jump();
continue;
}
alien_main_loop();
}
}
should_react_to_downed_enemies()
{
switch ( maps\mp\alien\_utility::get_alien_type() )
{
case "seeder":
case "gargoyle":
case "spitter":
case "minion":
case "elite":
return 0;
default:
return 1;
}
}
downed_enemy_monitor()
{
self endon( "death" );
for (;;)
{
if ( !isplayer( self.enemy ) )
{
wait 0.05;
continue;
}
thread monitor_enemy_for_downed( self.enemy );
common_scripts\utility::waittill_any( "downed_enemy", "enemy" );
}
}
monitor_enemy_for_downed( var_0 )
{
self endon( "enemy" );
self endon( "death" );
var_0 common_scripts\utility::waittill_any( "death", "last_stand" );
var_1 = 65536;
if ( distancesquared( var_0.origin, self.origin ) < var_1 )
{
self.enemy_downed = 1;
self.downed_enemy_location = var_0.origin;
}
self notify( "downed_enemy" );
}
alien_test_loop()
{
var_0 = [ ( -296, 448, -352 ), ( 808, 300, -368 ), ( 1320.6, 482.8, -320 ) ];
wait 10;
for (;;)
{
foreach ( var_2 in var_0 )
{
if ( distancesquared( self.origin, var_2 ) < 100 )
continue;
self scragentsetgoalpos( var_2 );
self waittill( "goal_reached" );
wait 3;
}
}
}
alien_test_jump()
{
var_0 = [ ( -203.3, -898, 151.033 ), ( -1282.2, -669.1, -26.529 ) ];
wait 10;
for (;;)
{
foreach ( var_2 in var_0 )
{
if ( distancesquared( self.origin, var_2 ) < 100 )
continue;
self scragentsetgoalpos( var_2 );
self waittill( "goal_reached" );
wait 3;
}
}
}
handle_attractor_flare( var_0, var_1 )
{
if ( var_1 )
self.attractor_flare = var_0;
else
{
if ( !isdefined( self.attractor_flare ) )
return;
if ( isdefined( var_0 ) && var_0 != self.attractor_flare )
return;
self.attractor_flare = undefined;
}
self notify( "alien_main_loop_restart" );
}
react_to_attractor_flare()
{
var_0 = 3.0;
var_1 = 6.0;
var_2 = get_flare_node();
if ( isdefined( var_2 ) )
{
self scragentsetgoalnode( var_2 );
self scragentsetgoalradius( 64.0 );
self waittill( "goal_reached" );
while ( isdefined( self.attractor_flare ) )
wait 0.2;
}
}
get_flare_node()
{
var_0 = getnodesinradius( self.attractor_flare.origin, 300, 50, 128, "path" );
if ( var_0.size == 0 )
return undefined;
var_1 = [];
var_2 = vectornormalize( self.origin - self.attractor_flare.origin );
foreach ( var_4 in var_0 )
{
var_5 = vectornormalize( var_4.origin - self.attractor_flare.origin );
if ( vectordot( var_5, var_2 ) < 0 )
continue;
var_1[var_1.size] = var_4;
}
if ( var_1.size == 0 )
return var_0[randomint( var_0.size )];
return var_1[randomint( var_1.size )];
}
alien_main_loop()
{
self endon( "alien_main_loop_restart" );
for (;;)
{
self.looktarget = undefined;
var_0 = self.enemy;
if ( isdefined( self.alien_scripted ) && self.alien_scripted == 1 )
{
}
else if ( isdefined( self.attractor_flare ) )
react_to_attractor_flare();
else if ( isdefined( self.enemy_downed ) && self.enemy_downed )
{
posture_after_enemy_downed();
self.enemy_downed = 0;
self.downed_enemy_location = undefined;
}
else if ( isalive( var_0 ) )
{
if ( self.badpath )
[[ level.alien_funcs[maps\mp\alien\_utility::get_alien_type()]["badpath"] ]]( var_0 );
else
[[ level.alien_funcs[maps\mp\alien\_utility::get_alien_type()]["combat"] ]]( var_0 );
}
else if ( isdefined( self.pet ) && self.pet )
alien_pet_follow();
else
alien_noncombat();
wait 0.05;
}
}
posture_after_enemy_downed()
{
self endon( "damage" );
self endon( "enemy_downed_proximity_breached" );
var_0 = 4.0;
var_1 = 6.0;
var_2 = get_downed_posture_node();
if ( isdefined( var_2 ) )
{
self scragentsetgoalnode( var_2 );
self scragentsetgoalradius( 64.0 );
self waittill( "goal_reached" );
}
thread monitor_enemy_proximity_during_enemy_downed();
wait( randomfloatrange( var_0, var_1 ) );
}
monitor_enemy_proximity_during_enemy_downed()
{
self endon( "death" );
self endon( "damage" );
self endon( "alien_main_loop_restart" );
var_0 = 16384;
for (;;)
{
foreach ( var_2 in level.players )
{
if ( distancesquared( var_2.origin, self.origin ) < var_0 )
{
self notify( "enemy_downed_proximity_breached" );
return;
}
}
wait 0.1;
}
}
get_downed_posture_node()
{
var_0 = getnodesinradius( self.origin, 300, 50, 128, "path" );
if ( var_0.size == 0 )
return;
var_1 = [];
var_1["direction"] = "override";
var_1["direction_override"] = vectornormalize( self.origin - self.downed_enemy_location );
var_1["direction_weight"] = 10.0;
var_1["min_height"] = 64.0;
var_1["max_height"] = 400.0;
var_1["height_weight"] = 0.0;
var_1["enemy_los"] = 0;
var_1["enemy_los_weight"] = 0.0;
var_1["min_dist_from_enemy"] = 400.0;
var_1["max_dist_from_enemy"] = 800.0;
var_1["desired_dist_from_enemy"] = 600.0;
var_1["dist_from_enemy_weight"] = 0.0;
var_1["min_dist_from_all_enemies"] = 200.0;
var_1["min_dist_from_all_enemies_weight"] = 6.0;
var_1["not_recently_used_weight"] = 2.0;
var_1["random_weight"] = 1.0;
var_2 = get_retreat_node_rated( self.enemy, var_1, var_0 );
return var_2;
}
default_alien_combat( var_0 )
{
var_0 endon( "death" );
self endon( "enemy" );
self endon( "bad_path" );
clear_attacking( var_0 );
while ( isalive( var_0 ) )
{
self.looktarget = var_0;
if ( should_i_attack( var_0 ) )
{
set_attacking( var_0 );
alien_attack_enemy( var_0 );
clear_attacking( var_0 );
if ( should_i_retreat( var_0 ) )
alien_retreat( var_0 );
continue;
}
alien_wait_for_combat( var_0 );
}
}
alien_attack_enemy( var_0 )
{
if ( use_synched_attack( var_0 ) )
alien_synch_attack_enemy( var_0 );
else
alien_attack_sequence( var_0 );
}
use_synched_attack( var_0 )
{
switch ( maps\mp\alien\_utility::get_alien_type() )
{
case "seeder":
case "mammoth":
case "gargoyle":
case "locust":
case "spitter":
case "minion":
case "elite":
return 0;
default:
break;
}
return isdefined( var_0.synch_attack_setup );
}
alien_attack_sequence( var_0 )
{
var_1 = get_attack_sequence_num();
for ( var_2 = 0; var_2 < var_1; var_2++ )
{
var_3 = get_attack_num();
for ( var_4 = 0; var_4 < var_3; var_4++ )
{
if ( has_attack_abort_been_requested( self ) )
return;
var_5 = [[ level.alien_funcs[maps\mp\alien\_utility::get_alien_type()]["approach"] ]]( var_0, var_4 );
alien_attack( var_0, var_5 );
if ( distancesquared( self.origin, self.enemy.origin ) < 4096 )
break;
}
}
}
alien_synch_attack_enemy( var_0 )
{
if ( distance2dsquared( self.origin, var_0.origin ) > 100 )
{
self scragentsetgoalradius( 100 );
self scragentsetgoalentity( var_0 );
self waittill( "goal_reached" );
}
var_1 = isalive( var_0.synch_attack_setup.primary_attacker ) && var_0.synch_attack_setup.primary_attacker != self;
var_2 = 1;
if ( isdefined( var_0.synch_attack_setup.can_synch_attack_func ) )
var_2 = var_0 [[ var_0.synch_attack_setup.can_synch_attack_func ]]();
if ( !var_1 && var_2 )
{
var_0.synch_attack_setup.primary_attacker = self;
select_synch_index( var_0 );
if ( should_move_to_synch_attack_pos( var_0 ) )
{
self scragentsetgoalradius( 30 );
self scragentsetgoalpos( self.synch_attack_pos );
self waittill( "goal_reached" );
}
synch_melee( var_0 );
}
else
swipe_static_melee( var_0 );
}
select_synch_index( var_0 )
{
var_1 = var_0 maps\mp\alien\_utility::get_synch_direction_list( self );
var_2 = vectornormalize( self.origin - var_0.origin );
var_3 = undefined;
var_4 = undefined;
var_5 = undefined;
var_6 = -1.1;
foreach ( var_17, var_8 in var_1 )
{
var_9 = var_8["attackerAnimState"];
var_10 = self getanimentry( var_9, 0 );
var_11 = getstartorigin( var_0.origin, var_0.angles, var_10 );
var_12 = length( var_11 - var_0.origin );
var_13 = var_8["offset_direction"] * var_12;
var_14 = var_0 localtoworldcoords( var_13 );
var_15 = vectornormalize( var_14 - var_0.origin );
var_16 = vectordot( var_15, var_2 );
if ( var_16 > var_6 )
{
var_3 = var_17;
var_4 = var_9;
var_5 = var_14;
var_6 = var_16;
}
}
self.synch_attack_index = var_3;
self.synch_anim_state = var_4;
self.synch_attack_pos = var_5;
}
should_move_to_synch_attack_pos( var_0 )
{
var_1 = 0.707;
var_2 = vectornormalize( self.synch_attack_pos - var_0.origin );
var_3 = vectornormalize( self.origin - var_0.origin );
var_4 = vectordot( var_2, var_3 ) > var_1;
var_5 = distancesquared( var_0.origin, self.origin ) > distancesquared( var_0.origin, self.synch_attack_pos );
return var_5 || !var_4;
}
alien_attack( var_0, var_1 )
{
self notify( "start_attack" );
switch ( var_1 )
{
case "swipe":
swipe_melee( var_0 );
break;
case "leap":
leap_melee( var_0 );
break;
case "wall":
wall_leap_melee( var_0 );
break;
case "badpath_jump":
badpath_jump( var_0 );
break;
case "spit":
maps\mp\agents\alien\_alien_spitter::spit_projectile( var_0 );
break;
case "charge":
maps\mp\agents\alien\_alien_elite::charge_attack( var_0 );
break;
case "slam":
maps\mp\agents\alien\_alien_elite::ground_slam( var_0 );
break;
case "angered":
maps\mp\agents\alien\_alien_elite::angered( var_0 );
break;
case "synch":
synch_melee( var_0 );
break;
case "swipe_static":
swipe_static_melee( var_0 );
break;
case "explode":
maps\mp\agents\alien\_alien_minion::explode_attack( var_0 );
case "none":
break;
default:
if ( isdefined( level.alien_attack_override_func ) )
{
if ( [[ level.alien_attack_override_func ]]( var_0, var_1 ) )
break;
}
wait 1;
break;
}
}
handle_badpath( var_0 )
{
var_0 endon( "death" );
var_0 endon( "disconnect" );
self endon( "bad_path" );
self.badpath = 0;
if ( !can_attempt_badpath_move() )
return;
if ( self.badpathcount > 3 )
{
if ( attempt_bad_path_move_nearby_node( var_0 ) )
self.badpathcount = 0;
return;
}
if ( !should_bad_path_melee() )
return;
if ( self.badpathcount == 1 )
var_1 = attempt_badpath_move_to_node( var_0, 0, 100, 50 );
else
var_1 = 0;
if ( !var_1 )
{
var_1 = attempt_badpath_move_to_node( var_0, 100, 256, 128 );
if ( !var_1 )
return;
}
if ( attempt_bad_path_melee( var_0 ) )
self.badpathcount = 0;
}
can_attempt_badpath_move()
{
switch ( self.currentanimstate )
{
case "traverse":
return 0;
default:
return 1;
}
}
should_bad_path_melee()
{
switch ( maps\mp\alien\_utility::get_alien_type() )
{
case "seeder":
case "spitter":
return 0;
default:
return 1;
}
}
attempt_bad_path_move_nearby_node( var_0 )
{
var_1 = 128;
var_2 = 512;
var_3 = getnodesinradius( self.origin, var_2, var_1, 256, "node_pathnode" );
if ( var_3.size == 0 )
return 0;
self scragentsetgoalpos( self.origin );
self scragentsetgoalradius( 2048 );
var_4 = var_3[randomint( var_3.size )];
if ( attempt_badpath_jump( var_0, var_4 ) )
return 1;
else
{
self scragentsetgoalnode( var_4 );
self scragentsetgoalradius( 64 );
self waittill( "goal_reached" );
return 1;
}
return 0;
}
attempt_bad_path_melee( var_0 )
{
var_1 = abs( self.origin[2] - var_0.origin[2] );
var_2 = distance2d( self.origin, var_0.origin );
if ( var_2 > 256 )
return 0;
var_3 = self agentcanseesentient( var_0 );
if ( var_3 && var_1 <= 50 && var_2 <= 150 )
{
self.bad_path_handled = 1;
if ( maps\mp\alien\_utility::should_explode() )
{
alien_attack( var_0, "explode" );
return 1;
}
else if ( maps\mp\alien\_utility::is_normal_upright( anglestoup( self.angles ) ) )
{
alien_attack( var_0, "swipe" );
return 1;
}
}
self.leapendpos = maps\mp\agents\alien\_alien_melee::get_leap_end_pos( 1.0, 48, var_0 );
var_4 = maps\mp\agents\_scriptedagents::droppostoground( self.leapendpos, 256 );
if ( !isdefined( var_4 ) )
return 0;
if ( !trajectorycanattemptaccuratejump( self.origin, anglestoup( self.angles ), self.leapendpos, anglestoup( var_0.angles ), level.alien_jump_melee_gravity, 1.01 * level.alien_jump_melee_speed ) )
return 0;
var_5 = getnodesinradiussorted( var_4, 256, 0, 256 );
if ( !var_5.size )
return 0;
var_6 = getpathdist( var_4, var_5[0].origin, 512 );
if ( var_6 < 0 )
return 0;
leap_melee( var_0 );
return 1;
}
attempt_badpath_move_to_node( var_0, var_1, var_2, var_3 )
{
var_4 = getnodesinradius( var_0.origin, var_2, var_1, var_3 );
if ( var_4.size > 0 )
{
var_5 = var_4[randomint( var_4.size )];
self scragentsetgoalnode( var_5 );
self scragentsetgoalradius( 64 );
self waittill( "goal_reached" );
return 1;
}
wait 0.1;
return 0;
}
attempt_badpath_jump( var_0, var_1 )
{
var_2 = trajectorycanattemptaccuratejump( self.origin, anglestoup( self.angles ), var_1.origin, anglestoup( var_1.angles ), level.alien_jump_melee_gravity, 1.01 * level.alien_jump_melee_speed );
if ( var_2 || self.oriented )
{
self.leapendpos = var_1.origin;
self.leapendangles = var_1.angles;
alien_attack( var_0, "badpath_jump" );
self scragentsetgoalpos( self.origin );
self scragentsetgoalradius( 2048 );
self waittill( "goal_reached" );
}
wait 0.5;
return var_2;
}
restart_loop_near_enemy( var_0 )
{
self endon( "alien_main_loop_restart" );
var_0 endon( "death" );
self endon( "death" );
self endon( "bad_path" );
var_1 = 65536.0;
for (;;)
{
if ( distancesquared( self.origin, var_0.origin ) < var_1 )
self notify( "alien_main_loop_restart" );
wait 0.05;
}
}
set_attacking( var_0 )
{
var_0.current_attackers[var_0.current_attackers.size] = self;
self.attacking_player = 1;
self.bypass_max_attacker_counter = 0;
}
clear_attacking( var_0 )
{
if ( !isdefined( var_0.current_attackers ) )
var_0.current_attackers = [];
var_0.current_attackers = common_scripts\utility::array_remove( var_0.current_attackers, self );
self.attacking_player = 0;
self.abort_attack_requested = 0;
}
clean_up_attackers()
{
var_0 = [];
foreach ( var_2 in self.current_attackers )
{
if ( isalive( var_2 ) && isalive( var_2.enemy ) && var_2.enemy == self )
var_0[var_0.size] = var_2;
}
self.current_attackers = var_0;
}
should_i_attack( var_0 )
{
if ( !maps\mp\alien\_utility::is_idle_state_locked() && self.statelocked )
return 0;
var_0 clean_up_attackers();
return 1;
}
should_i_retreat( var_0 )
{
if ( isdefined( level.dlc_alien_can_retreat_override_func ) )
{
if ( ![[ level.dlc_alien_can_retreat_override_func ]]( var_0 ) )
return 0;
}
switch ( maps\mp\alien\_utility::get_alien_type() )
{
case "elite":
return 0;
default:
return 1;
}
}
replace_attacker_request( var_0 )
{
var_0.abort_attack_requested = 1;
}
has_attack_abort_been_requested( var_0 )
{
return isdefined( var_0.abort_attack_requested ) && var_0.abort_attack_requested;
}
find_attacker_to_replace( var_0, var_1 )
{
var_2 = level.alien_types[self.alien_type].attributes["attacker_priority"];
var_3 = level.alien_types[self.alien_type].attributes["attacker_difficulty"] - ( level.maxalienattackerdifficultyvalue - var_1 );
var_4 = [];
foreach ( var_6 in var_0.current_attackers )
{
if ( has_attack_abort_been_requested( var_6 ) )
continue;
if ( var_2 < level.alien_types[var_6.alien_type].attributes["attacker_priority"] )
{
var_3 = var_3 - level.alien_types[var_6.alien_type].attributes["attacker_difficulty"];
var_4[var_4.size] = var_6;
if ( var_3 <= 0 )
break;
}
}
return var_4;
}
get_current_attacker_value( var_0 )
{
var_1 = 0.0;
if ( !isdefined( var_0.current_attackers ) )
return var_1;
foreach ( var_3 in var_0.current_attackers )
{
if ( !isalive( var_3 ) )
continue;
if ( has_attack_abort_been_requested( var_3 ) )
continue;
var_1 = var_1 + level.alien_types[var_3.alien_type].attributes["attacker_difficulty"];
}
return var_1;
}
alien_noncombat()
{
self scragentsetgoalpos( self.origin );
for (;;)
{
if ( isalive( self.enemy ) )
break;
wait 1;
}
}
alien_pet_follow()
{
var_0 = 768;
if ( isdefined( self.petfollowdist ) )
var_0 = self.petfollowdist;
var_1 = var_0 * var_0;
self scragentsetgoalradius( var_0 );
while ( !isalive( self.enemy ) )
{
if ( !isdefined( self.owner ) || !isalive( self.owner ) )
{
var_2 = undefined;
foreach ( var_4 in level.players )
{
if ( isalive( var_4 ) )
{
var_2 = var_4;
break;
}
}
if ( isdefined( var_2 ) )
self.owner = var_2;
else
self scragentsetgoalpos( self.origin );
}
else
{
var_6 = distancesquared( self.owner.origin, self.origin );
if ( var_6 > var_1 )
{
var_7 = get_pet_follow_node( self.owner );
if ( !isdefined( var_7 ) )
{
wait 1.0;
continue;
}
self scragentsetgoalnode( var_7 );
self scragentsetgoalradius( 64 );
self waittill( "goal_reached" );
wait( randomfloatrange( 0.5, 1.5 ) );
}
}
wait 0.05;
}
}
alien_wait_for_combat( var_0 )
{
self endon( "go to combat" );
thread monitor_proximity_with_enemy( var_0 );
thread watch_for_damage( var_0 );
thread random_movemode_change( 0, 70, 30, 1.5, 3.0 );
for (;;)
{
var_1 = common_scripts\utility::cointoss();
var_2 = getnodesinradius( self.origin, 512, 256, 256 );
if ( var_2.size == 0 )
{
wait 1;
self notify( "go to combat" );
return;
}
var_3 = self.origin - var_0.origin;
var_4 = vectortoangles( var_3 );
var_5 = anglestoright( var_4 );
if ( var_1 )
var_5 = var_5 * -1;
var_6 = [];
var_6["direction"] = "override";
var_6["direction_weight"] = 2.0;
var_6["min_height"] = -32.0;
var_6["max_height"] = 128.0;
var_6["height_weight"] = 1.0;
var_6["enemy_los"] = 1;
var_6["enemy_los_weight"] = 2.0;
var_6["min_dist_from_enemy"] = 600.0;
var_6["max_dist_from_enemy"] = 1000.0;
var_6["desired_dist_from_enemy"] = 800.0;
var_6["dist_from_enemy_weight"] = 3.0;
var_6["min_dist_from_all_enemies"] = 400.0;
var_6["min_dist_from_all_enemies_weight"] = 1.0;
var_6["not_recently_used_weight"] = 4.0;
var_6["random_weight"] = 1.0;
var_6["direction_override"] = var_5;
var_7 = get_retreat_node_rated( var_0, var_6, var_2 );
self scragentsetgoalnode( var_7 );
self scragentsetgoalradius( 64 );
self waittill( "goal_reached" );
wait( randomfloatrange( 1.5, 3.5 ) );
if ( should_i_attack( var_0 ) )
{
self notify( "go to combat" );
break;
}
}
}
alien_retreat( var_0 )
{
self notify( "start retreat" );
set_alien_movemode( "run" );
var_1 = "elevated_delay";
var_2 = "alien_forward";
if ( !isdefined( var_1 ) || var_1 == "" )
var_1 = "randomize";
if ( !isdefined( var_2 ) || var_2 == "" )
var_2 = "alien_forward";
if ( var_1 == "randomize" )
{
var_3 = [ "elevated_delay", "cover", "cover", "cover" ];
var_4 = randomint( 4 );
var_1 = var_3[var_4];
}
switch ( var_1 )
{
case "elevated_delay":
elevated_delay_retreat( var_0, var_2 );
break;
case "cover":
cover_retreat( var_0, var_2 );
break;
default:
wait 1;
break;
}
}
monitor_proximity_with_enemy( var_0 )
{
self endon( "go to combat" );
self endon( "damage" );
self endon( "death" );
self endon( "alien_main_loop_restart" );
var_0 endon( "death" );
var_0 endon( "disconnect" );
wait_for_proximity_check_activation( var_0 );
for (;;)
{
if ( distancesquared( self.origin, var_0.origin ) < 65536 )
{
self.attack_sequence_num = 1;
self.attack_num = 1;
self.bypass_max_attacker_counter = 1;
self notify( "go to combat" );
break;
}
common_scripts\utility::waitframe();
}
}
watch_for_damage( var_0 )
{
self endon( "go to combat" );
self endon( "death" );
self endon( "alien_main_loop_restart" );
var_0 endon( "death" );
self waittill( "damage" );
self.bypass_max_attacker_counter = 1;
self notify( "go to combat" );
}
wait_for_proximity_check_activation( var_0 )
{
var_1 = 2;
var_2 = gettime();
for (;;)
{
if ( distancesquared( self.origin, var_0.origin ) > 65536 )
break;
else if ( gettime() - var_2 > var_1 * 1000 )
break;
common_scripts\utility::waitframe();
}
}
elevated_delay_retreat( var_0, var_1 )
{
var_2 = get_elevated_jump_node( var_0, var_1 );
if ( !isdefined( var_2 ) )
{
wait 0.05;
return;
}
self scragentsetgoalnode( var_2 );
self scragentsetgoalradius( 32 );
self waittill( "goal_reached" );
wait 1.5;
}
get_elevated_jump_node( var_0, var_1 )
{
var_2 = getnodesinradius( var_0.origin, 800, 400, 256, "jump" );
if ( var_2.size == 0 )
return;
var_3 = [];
if ( getdvarint( "alien_retreat_towards_spawn" ) == 1 )
{
var_3["direction"] = "override";
var_3["direction_override"] = vectornormalize( self.spawnorigin - var_0.origin );
var_3["direction_weight"] = 8.0;
}
else
{
var_3["direction"] = var_1;
var_3["direction_weight"] = 1.0;
}
var_3["min_height"] = 64.0;
var_3["max_height"] = 400.0;
var_3["height_weight"] = 2.0;
var_3["enemy_los"] = 1;
var_3["enemy_los_weight"] = 2.0;
var_3["min_dist_from_enemy"] = 400.0;
var_3["max_dist_from_enemy"] = 800.0;
var_3["desired_dist_from_enemy"] = 600.0;
var_3["dist_from_enemy_weight"] = 3.0;
var_3["min_dist_from_all_enemies"] = 200.0;
var_3["min_dist_from_all_enemies_weight"] = 1.0;
var_3["not_recently_used_weight"] = 4.0;
var_3["random_weight"] = 1.0;
var_4 = get_retreat_node_rated( var_0, var_3, var_2 );
return var_4;
}
cover_retreat( var_0, var_1 )
{
var_2 = 1;
self endon( "go to combat" );
thread monitor_proximity_with_enemy( var_0 );
thread watch_for_damage( var_0 );
var_3 = [];
if ( getdvarint( "alien_cover_node_retreat" ) == 1 )
{
var_3["direction"] = "cover";
var_3["direction_weight"] = 2.0;
var_3["enemy_los_weight"] = 0.0;
var_3["max_dist_from_enemy"] = 1200.0;
}
else if ( getdvarint( "alien_retreat_towards_spawn" ) == 1 )
{
var_3["direction"] = "override";
var_3["direction_override"] = vectornormalize( self.spawnorigin - var_0.origin );
var_3["direction_weight"] = 8.0;
var_3["enemy_los_weight"] = 6.0;
var_3["max_dist_from_enemy"] = 800.0;
}
else
{
var_3["direction"] = var_1;
var_3["direction_weight"] = 1.0;
var_3["enemy_los_weight"] = 6.0;
var_3["max_dist_from_enemy"] = 800.0;
}
var_3["min_height"] = -32.0;
var_3["max_height"] = 128.0;
var_3["height_weight"] = 1.0;
var_3["enemy_los"] = 0;
var_3["min_dist_from_enemy"] = 400.0;
var_3["desired_dist_from_enemy"] = 600.0;
var_3["dist_from_enemy_weight"] = 2.0;
var_3["min_dist_from_all_enemies"] = 200.0;
var_3["min_dist_from_all_enemies_weight"] = 1.0;
var_3["min_dist_from_current_position"] = 256.0;
var_3["min_dist_from_current_position_weight"] = 3.0;
var_3["not_recently_used_weight"] = 4.0;
var_3["random_weight"] = 1.0;
var_4 = get_cover_node( var_0, var_3 );
if ( !isdefined( var_4 ) )
return;
self scragentsetgoalnode( var_4 );
self scragentsetgoalradius( 64 );
self waittill( "goal_reached" );
for ( var_5 = 0; var_5 < var_2; var_5++ )
{
var_3["direction"] = "alien_forward";
var_4 = get_cover_node( var_0, var_3 );
if ( !isdefined( var_4 ) )
return;
self scragentsetgoalnode( var_4 );
self scragentsetgoalradius( 64 );
self waittill( "goal_reached" );
}
}
get_cover_node( var_0, var_1 )
{
if ( getdvarint( "alien_cover_node_retreat" ) == 1 )
var_2 = getnodesinradius( var_0.origin, 800, 400, 256, "cover stand" );
else
var_2 = getnodesinradius( var_0.origin, 800, 400, 256 );
if ( var_2.size == 0 )
return undefined;
var_3 = get_retreat_node_rated( var_0, var_1, var_2 );
return var_3;
}
circling_retreat( var_0, var_1 )
{
self endon( "go to combat" );
thread monitor_proximity_with_enemy( var_0 );
thread watch_for_damage( var_0 );
var_2 = getnodesinradius( var_0.origin, 800, 400, 256 );
if ( var_2.size == 0 )
var_2 = getnodesinradius( var_0.origin, 2000, 400, 256 );
var_3 = [];
var_3["direction"] = var_1;
var_3["direction_weight"] = 1.0;
var_3["min_height"] = -32.0;
var_3["max_height"] = 32.0;
var_3["height_weight"] = 2.0;
var_3["enemy_los"] = 1;
var_3["enemy_los_weight"] = 2.0;
var_3["min_dist_from_enemy"] = 400.0;
var_3["max_dist_from_enemy"] = 800.0;
var_3["desired_dist_from_enemy"] = 600.0;
var_3["dist_from_enemy_weight"] = 3.0;
var_3["min_dist_from_all_enemies"] = 200.0;
var_3["min_dist_from_all_enemies_weight"] = 1.0;
var_3["not_recently_used_weight"] = 4.0;
var_3["random_weight"] = 2.0;
var_4 = get_retreat_node_rated( var_0, var_3, var_2 );
self scragentsetgoalnode( var_4 );
self scragentsetgoalradius( 64 );
self waittill( "goal_reached" );
var_5 = randomint( 2 );
for ( var_6 = 0; var_6 < getdvarint( "alien_circling_retreat_num_nodes" ) - 1; var_6++ )
{
var_7 = self.origin - var_0.origin;
var_8 = vectortoangles( var_7 );
var_9 = anglestoright( var_8 );
if ( var_5 )
var_9 = var_9 * -1;
var_2 = getnodesinradius( var_0.origin, 800, 500, 256 );
if ( var_2.size == 0 )
var_2 = getnodesinradius( var_0.origin, 2000, 400, 256 );
var_3["direction"] = "override";
var_3["direction_override"] = var_9;
var_3["direction_weight"] = 2.0;
var_3["random_weight"] = 1.0;
var_3["min_dist_from_current_position"] = 256.0;
var_3["min_dist_from_current_position_weight"] = 3.0;
var_10 = get_retreat_node_rated( var_0, var_3, var_2 );
self scragentsetgoalnode( var_10 );
self scragentsetgoalradius( 64 );
self waittill( "goal_reached" );
}
}
elevated_circling_retreat( var_0, var_1 )
{
self endon( "go to combat" );
thread monitor_proximity_with_enemy( var_0 );
thread watch_for_damage( var_0 );
var_2 = get_elevated_jump_node( var_0, var_1 );
if ( !isdefined( var_2 ) )
return;
self scragentsetgoalnode( var_2 );
self scragentsetgoalradius( 64 );
self waittill( "goal_reached" );
var_3 = [];
var_3["direction"] = var_1;
var_3["direction_weight"] = 1.0;
var_3["min_height"] = -32.0;
var_3["max_height"] = 32.0;
var_3["height_weight"] = 2.0;
var_3["enemy_los"] = 1;
var_3["enemy_los_weight"] = 2.0;
var_3["min_dist_from_enemy"] = 400.0;
var_3["max_dist_from_enemy"] = 800.0;
var_3["desired_dist_from_enemy"] = 600.0;
var_3["dist_from_enemy_weight"] = 3.0;
var_3["min_dist_from_all_enemies"] = 200.0;
var_3["min_dist_from_all_enemies_weight"] = 1.0;
var_3["not_recently_used_weight"] = 4.0;
var_3["random_weight"] = 2.0;
var_4 = randomint( 2 );
for ( var_5 = 0; var_5 < getdvarint( "alien_circling_retreat_num_nodes" ) - 1; var_5++ )
{
var_6 = self.origin - var_0.origin;
var_7 = vectortoangles( var_6 );
var_8 = anglestoright( var_7 );
if ( var_4 )
var_8 = var_8 * -1;
var_9 = getnodesinradius( self.origin, 800, 250, 256, "jump" );
if ( var_9.size == 0 )
return;
var_3["direction"] = "override";
var_3["direction_override"] = var_8;
var_3["direction_weight"] = 2.0;
var_3["random_weight"] = 1.0;
var_3["min_dist_from_current_position"] = 256.0;
var_3["min_dist_from_current_position_weight"] = 3.0;
var_10 = get_retreat_node_rated( var_0, var_3, var_9 );
self scragentsetgoalnode( var_10 );
self scragentsetgoalradius( 64 );
self waittill( "goal_reached" );
}
}
close_range_retreat( var_0 )
{
self endon( "go to combat" );
thread monitor_proximity_with_enemy( var_0 );
thread watch_for_damage( var_0 );
set_alien_movemode( "run" );
var_1 = 55;
var_2 = 75;
var_3 = 256;
var_4 = 256;
var_5 = get_offset_location_from_enemy( var_0, var_3, var_4, var_1, var_2 );
var_6 = getnodesinradius( var_5, 256, 0, 128, "path" );
if ( var_6.size == 0 )
var_6 = getnodesinradius( var_5, 500, 256, 128, "path" );
if ( var_6.size == 0 )
{
wait 0.2;
return;
}
var_7 = [];
if ( getdvarint( "alien_retreat_towards_spawn" ) == 1 )
var_7["direction_weight"] = 8.0;
else
var_7["direction_weight"] = 3.0;
var_7["direction"] = "override";
var_7["direction_override"] = vectornormalize( var_5 - self.origin );
var_7["min_height"] = -32.0;
var_7["max_height"] = 32.0;
var_7["height_weight"] = 6.0;
var_7["enemy_los"] = 0;
var_7["enemy_los_weight"] = 0.0;
var_7["min_dist_from_enemy"] = 150.0;
var_7["max_dist_from_enemy"] = 800.0;
var_7["desired_dist_from_enemy"] = 200.0;
var_7["dist_from_enemy_weight"] = 3.0;
var_7["min_dist_from_all_enemies"] = 150.0;
var_7["min_dist_from_all_enemies_weight"] = 1.0;
var_7["not_recently_used_weight"] = 4.0;
var_7["random_weight"] = 2.0;
var_8 = get_retreat_node_rated( var_0, var_7, var_6 );
self scragentsetgoalnode( var_8 );
self scragentsetgoalradius( 64 );
self waittill( "goal_reached" );
}
get_retreat_node_rated( var_0, var_1, var_2 )
{
if ( var_2.size == 0 )
return undefined;
var_3 = var_1["direction"];
var_4 = var_1["direction_weight"];
var_5 = var_1["min_height"];
var_6 = var_1["max_height"];
var_7 = var_1["height_weight"];
var_8 = var_1["enemy_los"];
var_9 = var_1["enemy_los_weight"];
var_10 = var_1["min_dist_from_enemy"];
var_11 = var_1["max_dist_from_enemy"];
var_12 = var_1["desired_dist_from_enemy"];
var_13 = var_1["dist_from_enemy_weight"];
var_14 = var_1["min_dist_from_all_enemies"];
var_15 = var_1["min_dist_from_all_enemies_weight"];
var_16 = var_1["min_dist_from_current_position"];
var_17 = var_1["min_dist_from_current_position_weight"];
var_18 = var_1["not_recently_used_weight"];
var_19 = var_1["random_weight"];
if ( isdefined( var_1["recently_used_time_limit"] ) )
var_20 = var_1["recently_used_time_limit"];
else
var_20 = 10.0;
if ( isdefined( var_1["test_offset"] ) )
var_21 = var_1["test_offset"];
else
var_21 = ( 0, 0, 0 );
var_22 = undefined;
if ( isplayer( var_0 ) )
var_22 = anglestoforward( var_0 getplayerangles() );
else if ( isdefined( var_0 ) )
var_22 = anglestoforward( var_0.angles );
var_23 = undefined;
var_24 = 0;
if ( var_3 == "player_front" )
var_23 = var_22;
else if ( var_3 == "player_behind" )
var_23 = var_22 * -1;
else if ( var_3 == "alien_forward" )
var_23 = anglestoforward( self.angles );
else if ( var_3 == "alien_backward" )
var_23 = anglestoforward( self.angles ) * -1;
else if ( var_3 == "cover" )
var_24 = 1;
else if ( var_3 == "override" )
var_23 = var_1["direction_override"];
else
{
}
var_25 = 0;
var_26 = -1.0;
var_27 = 0;
for ( var_28 = 0; var_25 < var_2.size; var_25++ )
{
var_29 = var_2[var_25];
var_30 = var_29.origin + var_21;
var_31 = 0.0;
if ( var_7 > 0.0 )
{
if ( var_30[2] - var_0.origin[2] > var_5 && var_30[2] - var_0.origin[2] < var_6 )
var_31 = var_31 + var_7;
}
var_32 = undefined;
if ( var_24 )
{
var_23 = anglestoforward( var_29.angles );
var_32 = vectornormalize( var_0.origin - var_30 );
}
else
var_32 = vectornormalize( var_30 - self.origin );
var_33 = vectordot( var_23, var_32 );
var_31 = var_31 + ( var_33 + 1.0 ) * 0.5 * var_4;
if ( var_13 > 0.0 )
{
var_34 = distance( var_30, var_0.origin );
if ( var_34 > var_10 && var_34 < var_11 )
{
var_35 = 0.0;
if ( var_34 > var_12 )
var_35 = var_35 + ( 1 - ( var_34 - var_12 ) / ( var_11 - var_12 ) );
else
var_35 = var_35 + ( var_34 - var_10 ) / ( var_12 - var_10 );
var_31 = var_31 + var_35 * var_13;
}
}
if ( var_15 )
{
var_36 = 1;
foreach ( var_38 in level.players )
{
if ( !isdefined( var_0 ) || var_38 != var_0 )
{
if ( distancesquared( var_30, var_38.origin ) < var_14 * var_14 )
{
var_36 = 0;
break;
}
}
}
if ( var_36 )
var_31 = var_31 + var_15;
}
if ( isdefined( var_17 ) && var_17 > 0.0 )
{
if ( distancesquared( self.origin, var_30 ) > var_16 * var_16 )
var_31 = var_31 + var_17;
}
if ( !node_recently_used( var_29, var_20 ) )
var_31 = var_31 + var_18;
if ( var_19 > 0.0 )
var_31 = var_31 + randomfloat( var_19 );
if ( var_9 > 0.0 && var_31 > var_26 - var_9 )
{
while ( max_traces_reached() )
{
var_28++;
if ( var_28 >= 20 )
break;
common_scripts\utility::waitframe();
}
if ( isdefined( var_0 ) )
{
var_40 = sighttracepassed( var_0 get_eye_position(), var_30 + ( 0, 0, 50 ), 0, self );
level.nodefiltertracesthisframe++;
if ( var_8 == var_40 )
var_31 = var_31 + var_9;
}
}
if ( var_31 > var_26 )
{
var_26 = var_31;
var_27 = var_25;
}
}
register_node( var_2[var_27] );
return var_2[var_27];
}
get_eye_position()
{
if ( isalive( self ) && ( isplayer( self ) || isagent( self ) ) )
return self geteye();
return self.origin;
}
max_traces_reached()
{
var_0 = 5;
if ( gettime() > level.nodefiltertracestime )
{
level.nodefiltertracestime = gettime();
level.nodefiltertracesthisframe = 0;
}
return level.nodefiltertracesthisframe >= var_0;
}
default_approach( var_0, var_1 )
{
var_2 = do_initial_approach( var_0 );
var_3 = self.swipechance;
var_4 = randomfloat( 1.0 ) < var_3;
if ( !var_4 && go_to_leaping_melee_position( var_0 ) )
return "leap";
return go_for_swipe( var_0, var_2 );
}
do_initial_approach( var_0 )
{
thread jogwhenclosetoenemy( var_0 );
var_1 = undefined;
if ( distancesquared( self.origin, var_0.origin ) > 250000.0 )
var_1 = approach_enemy( 400, var_0, 3 );
return var_1;
}
jogwhenclosetoenemy( var_0 )
{
self notify( "jogWhenCloseToEnemy" );
self endon( "jogWhenCloseToEnemy" );
self endon( "death" );
var_0 endon( "death" );
var_0 endon( "disconnect" );
level endon( "game_ended" );
if ( distancesquared( self.origin, var_0.origin ) >= 4000000 )
set_alien_movemode( "run" );
for (;;)
{
wait 1.0;
if ( distancesquared( self.origin, var_0.origin ) < 4000000 )
break;
}
switchtojog();
}
switchtojog()
{
if ( self.movemode == "jog" )
return;
var_0 = 0.9;
set_alien_movemode( "jog" );
self.moveplaybackrate = self.moveplaybackrate * var_0;
thread backtorunondamage( 1 );
}
backtorunondamage( var_0 )
{
self notify( "backToRunOnDamage" );
self endon( "backToRunOnDamage" );
self endon( "death" );
level endon( "game_ended" );
if ( isdefined( var_0 ) && var_0 )
common_scripts\utility::waittill_any( "damage", "start_attack", "bulletwhizby" );
else
common_scripts\utility::waittill_any( "damage", "start_attack" );
set_alien_movemode( "run" );
self.moveplaybackrate = self.defaultmoveplaybackrate;
}
sneak_up_on( var_0 )
{
self endon( "death" );
self endon( "start_attack" );
set_alien_movemode( "walk" );
var_1 = 1.05;
for (;;)
{
wait 1.0;
if ( in_front_players() || distancesquared( self.origin, var_0.origin ) > 160000 * var_1 )
{
set_alien_movemode( "run" );
break;
}
}
}
in_front_players()
{
foreach ( var_1 in level.players )
{
if ( in_front_of( var_1 ) )
return 1;
}
return 0;
}
in_front_of( var_0 )
{
var_1 = 0.5;
var_2 = self.origin - var_0.origin;
var_3 = anglestoforward( var_0.angles );
var_4 = vectordot( var_2, var_3 );
if ( var_4 < 0 )
return 0;
var_5 = var_4 > var_1;
return var_5;
}
go_for_swipe( var_0, var_1 )
{
var_2 = getdvarint( "alien_melee_distance" );
if ( var_2 < 100 )
var_2 = 100;
run_near_enemy( var_2, var_0 );
if ( !self agentcanseesentient( var_0 ) )
return "none";
return "swipe";
}
find_wall_leap_node( var_0 )
{
var_1 = distance( self.origin, var_0.origin );
if ( var_1 < 200 )
return;
var_2 = var_0.origin - self.origin;
var_3 = self.origin + var_2 * 0.5;
var_4 = var_0 get_eye_position();
var_5 = 0.95757;
var_6 = getnodesinradius( var_3, var_1 + 100.0, 100.0, 256.0, "node_jump" );
var_7 = [];
foreach ( var_9 in var_6 )
{
if ( var_9.origin[2] < var_0.origin[2] + 32.0 )
continue;
var_10 = var_0.origin - var_9.origin;
var_11 = self.origin - var_0.origin;
if ( vectordot( var_11, var_10 ) > 0 )
continue;
var_12 = self.origin - var_9.origin;
var_13 = var_11 * -1;
if ( vectordot( var_13, var_12 ) > 0 )
continue;
if ( distancesquared( self.origin, var_9.origin ) < 65536.0 )
continue;
if ( distancesquared( var_0.origin, var_9.origin ) < 65536.0 )
continue;
var_14 = vectornormalize( var_9.origin - var_4 );
var_15 = vectornormalize( var_14 * ( 1, 1, 0 ) );
var_16 = vectordot( var_14, var_15 );
if ( var_16 < var_5 )
continue;
var_17 = self geteye();
var_18 = var_9.origin + ( 0, 0, 32 );
var_19 = bullettrace( var_17, var_18, 0, self );
if ( var_19["surfacetype"] != "none" )
continue;
var_4 = var_0 get_eye_position();
var_19 = bullettrace( var_18, var_4, 0, var_0 );
if ( var_19["surfacetype"] != "none" )
continue;
var_7[var_7.size] = var_9;
}
if ( var_7.size == 0 )
return undefined;
else
{
var_21 = [];
var_21["direction"] = "alien_forward";
var_21["direction_weight"] = 1.0;
var_21["height_weight"] = 0.0;
var_21["enemy_los_weight"] = 0.0;
var_21["dist_from_enemy_weight"] = 0.0;
var_21["min_dist_from_all_enemies_weight"] = 0.0;
var_21["not_recently_used_weight"] = 4.0;
var_21["random_weight"] = 1.0;
var_22 = get_retreat_node_rated( var_0, var_21, var_7 );
return var_22;
}
}
swipe_melee( var_0 )
{
self.melee_type = "swipe";
alien_melee( var_0 );
}
leap_melee( var_0 )
{
self.melee_type = "leap";
alien_melee( var_0 );
}
wall_leap_melee( var_0 )
{
self.melee_type = "wall";
alien_melee( var_0 );
}
synch_melee( var_0 )
{
self.melee_type = "synch";
alien_melee( var_0 );
}
badpath_jump( var_0 )
{
self.melee_type = "badpath_jump";
alien_melee( var_0 );
}
swipe_static_melee( var_0 )
{
self.melee_type = "swipe_static";
alien_melee( var_0 );
}
alien_melee( var_0 )
{
if ( melee_okay() && attemptmelee() )
{
if ( maps\mp\alien\_utility::get_alien_type() != "spitter" && maps\mp\alien\_utility::get_alien_type() != "seeder" )
{
self scragentsetgoalentity( var_0 );
self scragentsetgoalradius( 4096.0 );
}
self waittill( "melee_complete" );
}
else
wait 0.2;
}
watch_for_scripted()
{
self endon( "death" );
for (;;)
{
if ( isdefined( self.alien_scripted ) && self.alien_scripted == 1 )
{
self notify( "alien_main_loop_restart" );
while ( isdefined( self.alien_scripted ) && self.alien_scripted == 1 )
wait 0.05;
}
wait 0.05;
}
}
watch_for_badpath()
{
self endon( "death" );
self.badpath = 0;
for (;;)
{
self waittill( "bad_path", var_0, var_1 );
self.badpath = 1;
if ( !isdefined( self.badpathcount ) || isdefined( self.badpathtime ) && gettime() > self.badpathtime + 2000 )
self.badpathcount = 0;
self.badpathtime = gettime();
self.badpathcount++;
self notify( "alien_main_loop_restart" );
wait 0.05;
}
}
set_alien_movemode( var_0 )
{
switch ( var_0 )
{
case "jog":
case "run":
case "walk":
self.movemode = var_0;
break;
default:
break;
}
}
watch_for_insolid()
{
self endon( "death" );
if ( self.insolid )
handleinsolid();
for (;;)
{
self waittill( "insolid" );
handleinsolid();
}
}
handleinsolid()
{
while ( self.insolid )
wait 0.2;
self scragentsetgoalpos( self.origin );
self notify( "alien_main_loop_restart" );
}
approach_enemy( var_0, var_1, var_2 )
{
if ( var_0 < 32 )
var_0 = 32;
var_3 = get_approach_node( var_1 );
var_4 = var_0 * var_0;
for ( var_5 = 0; isdefined( var_3 ) && var_5 < var_2; var_3 = get_approach_node( var_1 ) )
{
if ( run_to_approach_node( var_3, var_0, var_1 ) )
return var_3;
if ( distancesquared( self.origin, var_1.origin ) < 250000.0 )
break;
var_5++;
}
run_to_enemy( var_0, var_1 );
}
run_to_approach_node( var_0, var_1, var_2 )
{
self notify( "approach_goal_invalid" );
self scragentsetgoalradius( 64 );
self scragentsetgoalnode( var_0 );
wait_till_reached_goal_or_distance_from_enemy( var_0, var_1, var_2 );
return distancesquared( var_2.origin, self.origin ) <= var_1 * var_1;
}
run_to_enemy( var_0, var_1 )
{
self notify( "approach_goal_invalid" );
var_2 = max( var_0 + -48, 32 );
self scragentsetgoalradius( var_2 );
self scragentsetgoalentity( var_1 );
wait_till_distance_from_enemy( var_0, var_1 );
}
wait_till_reached_goal_or_distance_from_enemy( var_0, var_1, var_2 )
{
self endon( "goal_reached" );
self endon( "approach_goal_invalid" );
thread monitor_approach_goal_invalid( var_0, var_2 );
wait_till_distance_from_enemy( var_1, var_2 );
}
monitor_approach_goal_invalid( var_0, var_1 )
{
self endon( "goal_reached" );
self endon( "death" );
self endon( "approach_goal_invalid" );
var_1 endon( "death" );
var_2 = 202500;
while ( isdefined( var_0 ) && isdefined( var_1 ) )
{
if ( distancesquared( var_0.origin, var_1.origin ) > var_2 )
break;
var_3 = vectornormalize( self.origin - var_1.origin );
var_4 = vectornormalize( var_0.origin - var_1.origin );
if ( vectordot( var_3, var_4 ) < 0 )
break;
wait 0.2;
}
self notify( "approach_goal_invalid" );
}
wait_till_distance_from_enemy( var_0, var_1 )
{
var_2 = var_0 * var_0;
for (;;)
{
if ( get_distance_squared_to_enemy( var_1 ) < var_2 )
break;
common_scripts\utility::waitframe();
}
}
get_distance_squared_to_enemy( var_0 )
{
if ( isplayer( var_0 ) && var_0 isonladder() )
return distance2dsquared( self.origin, var_0.origin );
return distancesquared( self.origin, var_0.origin );
}
run_near_enemy( var_0, var_1, var_2 )
{
if ( var_0 < 32 )
var_0 = 32;
if ( !isdefined( var_2 ) || !run_to_approach_node( var_2, var_0, var_1 ) )
run_to_enemy( var_0, var_1 );
}
get_offset_location_from_enemy( var_0, var_1, var_2, var_3, var_4 )
{
if ( getdvarint( "alien_retreat_towards_spawn" ) == 1 )
var_5 = self.spawnorigin;
else
var_5 = self.origin;
var_6 = vectornormalize( ( var_5 - var_0.origin ) * ( 1, 1, 0 ) );
var_7 = randomintrange( var_3, var_4 );
if ( common_scripts\utility::cointoss() )
var_7 = var_7 * -1;
var_8 = ( 0, var_7, 0 );
var_9 = rotatevector( var_6, var_8 );
var_10 = var_1;
if ( var_1 < var_2 )
var_10 = randomintrange( var_1, var_2 );
return var_0.origin + var_9 * var_10;
}
get_approach_node( var_0 )
{
var_1 = 20;
var_2 = 30;
var_3 = getdvarint( "alien_melee_distance" );
if ( var_3 < 100 )
var_3 = 100;
var_4 = get_offset_location_from_enemy( var_0, var_3, var_3, var_1, var_2 );
var_5 = getnodesinradius( var_4, 150, 0, 128, "path" );
if ( var_5.size == 0 )
var_5 = getnodesinradius( var_4, 300, 150, 128, "path" );
var_6 = [];
var_6["direction"] = "override";
var_6["direction_weight"] = 6.0;
var_6["direction_override"] = vectornormalize( var_0.origin - self.origin );
var_6["min_height"] = -32.0;
var_6["max_height"] = 32.0;
var_6["height_weight"] = 6.0;
var_6["enemy_los"] = 0;
var_6["enemy_los_weight"] = 0.0;
var_6["min_dist_from_enemy"] = 150.0;
var_6["max_dist_from_enemy"] = 800.0;
var_6["desired_dist_from_enemy"] = distance( var_4, var_0.origin );
var_6["dist_from_enemy_weight"] = 3.0;
var_6["min_dist_from_all_enemies"] = 150.0;
var_6["min_dist_from_all_enemies_weight"] = 1.0;
var_6["not_recently_used_weight"] = 4.0;
var_6["random_weight"] = 2.0;
return get_retreat_node_rated( var_0, var_6, var_5 );
}
wait_for_valid_leap_melee( var_0 )
{
var_1 = randomintrange( -100, 100 ) + 400;
var_2 = var_1 * var_1;
var_3 = 43264;
for (;;)
{
if ( distancesquared( self.origin, var_0.origin ) < var_2 )
break;
wait 0.05;
}
for (;;)
{
if ( !isalive( var_0 ) )
return 0;
if ( distancesquared( self.origin, var_0.origin ) < var_3 )
return 0;
if ( can_leap_melee( var_0, 400, 208 ) )
return 1;
wait 0.05;
}
}
go_to_leaping_melee_position( var_0 )
{
self scragentsetgoalentity( var_0 );
self scragentsetgoalradius( 160 );
return wait_for_valid_leap_melee( var_0 );
}
go_to_leaping_melee_node( var_0 )
{
var_1 = getnodesinradius( var_0.origin, 512.0, 200.0, 256.0, "node_jump" );
var_2 = [];
var_3 = var_0 get_eye_position();
var_4 = ( 0, 0, 32 );
var_5 = undefined;
foreach ( var_7 in var_1 )
{
var_8 = bullettracepassed( var_7.origin + var_4, var_3, 0, self );
if ( var_8 )
{
var_5 = var_7;
break;
}
}
if ( !isdefined( var_5 ) )
return 0;
self scragentsetgoalnode( var_5 );
self scragentsetgoalradius( 160 );
var_10 = 160000;
var_11 = 0.0;
return wait_for_valid_leap_melee( var_0 );
}
can_leap_melee( var_0, var_1, var_2 )
{
if ( !melee_okay() )
return 0;
if ( isdefined( var_1 ) )
{
if ( distancesquared( self.origin, var_0.origin ) > var_1 * var_1 )
return 0;
}
var_3 = self.origin + ( 0, 0, 32 );
var_4 = var_0 get_eye_position();
var_5 = maps\mp\agents\alien\_alien_melee::get_melee_position( 1.0, 48, var_0 );
self.leapendpos = var_5;
if ( !isdefined( var_5 ) )
return 0;
if ( distancesquared( self.origin, var_5 ) < var_2 )
return 0;
var_6 = trajectorycanattemptaccuratejump( self.origin, anglestoup( self.angles ), var_5, anglestoup( var_0.angles ), level.alien_jump_melee_gravity, 1.01 * level.alien_jump_melee_speed );
return var_6;
}
melee_okay()
{
switch ( self.currentanimstate )
{
case "move":
return 1;
case "melee":
return 1;
case "idle":
return 1;
default:
return 0;
}
}
register_node( var_0 )
{
var_1 = [];
var_1["node"] = var_0;
var_1["time_stamp"] = gettime();
level.used_nodes[level.used_nodes_list_index] = var_1;
level.used_nodes_list_index++;
if ( level.used_nodes_list_index == level.used_nodes_list_size )
level.used_nodes_list_index = 0;
}
node_recently_used( var_0, var_1 )
{
var_2 = 0;
for ( var_3 = 0; var_3 < level.used_nodes_list_size; var_3++ )
{
var_4 = level.used_nodes_list_index - var_3;
if ( var_4 < 0 )
var_4 = level.used_nodes_list_size + var_4;
if ( isdefined( level.used_nodes[var_4] ) )
{
var_5 = level.used_nodes[var_4];
if ( var_0 == var_5["node"] )
{
if ( gettime() - var_5["time_stamp"] < var_1 * 1000 )
var_2 = 1;
break;
}
}
}
return var_2;
}
get_attack_sequence_num()
{
if ( isdefined( self.bypass_max_attacker_counter ) && self.bypass_max_attacker_counter == 1 )
return 1;
if ( isdefined( self.attack_sequence_num ) )
{
var_0 = self.attack_sequence_num;
self.attack_sequence_num = undefined;
return var_0;
}
switch ( maps\mp\alien\_utility::get_alien_type() )
{
case "seeder":
case "gargoyle":
case "locust":
case "spitter":
case "elite":
return 1;
default:
return randomint( 3 ) + 6;
}
}
get_attack_num()
{
if ( isdefined( self.attack_num ) )
{
var_0 = self.attack_num;
self.attack_num = undefined;
return var_0;
}
switch ( maps\mp\alien\_utility::get_alien_type() )
{
case "gargoyle":
case "locust":
return 1;
default:
return randomint( 6 ) + 3;
}
}
random_movemode_change( var_0, var_1, var_2, var_3, var_4 )
{
self endon( "go to combat" );
self endon( "death" );
var_5 = [];
var_5["run"] = var_0;
var_5["jog"] = var_1;
var_5["walk"] = var_2;
var_6 = var_0 + var_1 + var_2;
var_7 = 262144.0;
for (;;)
{
if ( maps\mp\alien\_utility::any_player_nearby( self.origin, var_7 ) )
var_8 = "run";
else
{
var_9 = 0;
var_10 = randomintrange( 0, var_6 );
var_8 = undefined;
foreach ( var_13, var_12 in var_5 )
{
var_9 = var_9 + var_12;
if ( var_10 <= var_9 )
{
var_8 = var_13;
break;
}
}
}
set_alien_movemode( var_8 );
wait( randomfloatrange( var_3, var_4 ) );
}
}
armormitigation( var_0, var_1, var_2 )
{
}
play_shield_impact_fx( var_0, var_1 )
{
if ( !isdefined( var_1 ) || !isdefined( var_0 ) )
return;
var_2 = var_1 * -1;
var_3 = anglestoup( vectortoangles( var_2 ) );
playfx( level._effect["shield_impact"], var_0, var_2, var_3 );
self playsound( "bullet_large_metal" );
}
has_shock_ammo( var_0 )
{
var_1 = maps\mp\alien\_utility::getrawbaseweaponname( var_0 );
if ( isdefined( self.special_ammocount ) && isdefined( self.special_ammocount[var_1] ) && self.special_ammocount[var_1] > 0 )
return 1;
return 0;
}
get_pet_follow_node( var_0 )
{
var_1 = getnodesinradius( var_0.origin, 512, 128, 350, "node_jump" );
var_2 = [];
var_2["direction"] = "player_front";
var_2["direction_weight"] = 2.0;
var_2["min_height"] = -32.0;
var_2["max_height"] = 350.0;
var_2["height_weight"] = 2.0;
var_2["enemy_los"] = 1;
var_2["enemy_los_weight"] = 2.0;
var_2["min_dist_from_enemy"] = 128.0;
var_2["max_dist_from_enemy"] = 512.0;
var_2["desired_dist_from_enemy"] = 350.0;
var_2["dist_from_enemy_weight"] = 3.0;
var_2["min_dist_from_all_enemies"] = 200.0;
var_2["min_dist_from_all_enemies_weight"] = 0.0;
var_2["not_recently_used_weight"] = 4.0;
var_2["random_weight"] = 2.0;
var_3 = get_retreat_node_rated( var_0, var_2, var_1 );
return var_3;
}