781 lines
19 KiB
Plaintext
781 lines
19 KiB
Plaintext
// IW6 GSC SOURCE
|
|
// Generated by https://github.com/xensik/gsc-tool
|
|
|
|
load_spitter_fx()
|
|
{
|
|
level._effect["spit_AOE"] = loadfx( "vfx/gameplay/alien/vfx_alien_spitter_gas_cloud" );
|
|
level._effect["spit_AOE_small"] = loadfx( "vfx/gameplay/alien/vfx_alien_spitter_gas_cloud_64" );
|
|
}
|
|
|
|
spitter_init()
|
|
{
|
|
self.gas_cloud_available = 1;
|
|
}
|
|
|
|
spitter_death()
|
|
{
|
|
release_spit_node();
|
|
}
|
|
|
|
is_escape_sequence_active()
|
|
{
|
|
return common_scripts\utility::flag_exist( "hives_cleared" ) && common_scripts\utility::flag( "hives_cleared" );
|
|
}
|
|
|
|
get_max_spit_distance_squared()
|
|
{
|
|
if ( is_escape_sequence_active() )
|
|
return 3240000;
|
|
|
|
return 1440000;
|
|
}
|
|
|
|
get_lookahead_percentage()
|
|
{
|
|
if ( is_escape_sequence_active() )
|
|
return 1.0;
|
|
|
|
return 0.5;
|
|
}
|
|
|
|
spit_projectile( var_0 )
|
|
{
|
|
if ( self.spit_type == "gas_cloud" )
|
|
level.spitter_last_cloud_time = gettime();
|
|
|
|
self.melee_type = "spit";
|
|
self.spit_target = var_0;
|
|
maps\mp\agents\alien\_alien_think::alien_melee( var_0 );
|
|
}
|
|
|
|
spit_attack( var_0 )
|
|
{
|
|
self endon( "melee_pain_interrupt" );
|
|
var_1 = isdefined( var_0 ) && isdefined( var_0.code_classname ) && var_0.code_classname == "script_vehicle";
|
|
|
|
if ( var_1 )
|
|
var_2 = var_0;
|
|
else
|
|
var_2 = self.spit_target;
|
|
|
|
var_2 endon( "death" );
|
|
maps\mp\agents\alien\_alien_anim_utils::turntowardsentity( var_2 );
|
|
|
|
if ( isalive( var_2 ) )
|
|
{
|
|
self.spit_target = var_2;
|
|
|
|
if ( var_1 )
|
|
{
|
|
var_3 = 5;
|
|
var_4 = vectornormalize( anglestoforward( var_2.angles ) );
|
|
var_5 = length( var_2 vehicle_getvelocity() ) * var_3;
|
|
var_6 = var_4 * var_5;
|
|
self.spit_target_location = var_2.origin + var_6 + ( 0, 0, 32 );
|
|
}
|
|
else
|
|
self.spit_target_location = var_2.origin;
|
|
|
|
self.looktarget = var_2;
|
|
maps\mp\alien\_utility::set_alien_emissive( 0.2, 1.0 );
|
|
|
|
if ( isdefined( self.current_spit_node ) && !maps\mp\alien\_utility::is_normal_upright( anglestoup( self.current_spit_node.angles ) ) )
|
|
{
|
|
var_7 = anglestoup( self.current_spit_node.angles );
|
|
var_8 = anglestoforward( self.angles );
|
|
var_9 = vectorcross( var_7, var_8 );
|
|
var_8 = vectorcross( var_9, var_7 );
|
|
var_10 = ( 0, 0, 0 ) - var_9;
|
|
var_11 = axistoangles( var_8, var_10, var_7 );
|
|
self scragentsetorientmode( "face angle abs", var_11 );
|
|
}
|
|
else if ( isdefined( self.enemy ) && var_2 == self.enemy )
|
|
self scragentsetorientmode( "face enemy" );
|
|
else
|
|
{
|
|
var_8 = vectornormalize( var_2.origin - self.origin );
|
|
|
|
if ( isdefined( self.current_spit_node ) )
|
|
var_7 = anglestoup( self.current_spit_node.angles );
|
|
else
|
|
var_7 = anglestoup( self.angles );
|
|
|
|
var_9 = vectorcross( var_7, var_8 );
|
|
var_8 = vectorcross( var_9, var_7 );
|
|
var_10 = ( 0, 0, 0 ) - var_9;
|
|
var_11 = axistoangles( var_8, var_10, var_7 );
|
|
self scragentsetorientmode( "face angle abs", var_11 );
|
|
}
|
|
|
|
if ( self.oriented )
|
|
self scragentsetanimmode( "anim angle delta" );
|
|
else
|
|
self scragentsetanimmode( "anim deltas" );
|
|
|
|
play_spit_anim();
|
|
}
|
|
|
|
maps\mp\alien\_utility::set_alien_emissive_default( 0.2 );
|
|
self.looktarget = undefined;
|
|
self.spit_target = undefined;
|
|
self.spit_target_location = undefined;
|
|
self.spit_type = undefined;
|
|
}
|
|
|
|
play_spit_anim()
|
|
{
|
|
switch ( self.spit_type )
|
|
{
|
|
case "close_range":
|
|
maps\mp\agents\_scriptedagents::playanimuntilnotetrack( "close_spit_attack", "spit_attack", "end", ::handleattacknotetracks );
|
|
break;
|
|
case "gas_cloud":
|
|
maps\mp\agents\_scriptedagents::playanimuntilnotetrack( "gas_spit_attack", "spit_attack", "end", ::handleattacknotetracks );
|
|
break;
|
|
case "long_range":
|
|
var_0 = randomintrange( 2, 3 );
|
|
|
|
for ( var_1 = 0; var_1 < var_0; var_1++ )
|
|
maps\mp\agents\_scriptedagents::playanimuntilnotetrack( "long_range_spit_attack", "spit_attack", "end", ::handleattacknotetracks );
|
|
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
get_best_spit_target( var_0 )
|
|
{
|
|
if ( common_scripts\utility::cointoss() && maps\mp\alien\_utility::get_alien_type() != "seeder" )
|
|
{
|
|
var_1 = get_grief_targets();
|
|
|
|
foreach ( var_3 in var_1 )
|
|
{
|
|
if ( is_valid_spit_target( var_3, 0 ) )
|
|
return var_3;
|
|
}
|
|
|
|
wait 0.05;
|
|
}
|
|
|
|
if ( isdefined( var_0 ) )
|
|
{
|
|
if ( isalive( var_0 ) && is_valid_spit_target( var_0, 0 ) )
|
|
return var_0;
|
|
}
|
|
|
|
var_5 = get_current_possible_targets();
|
|
var_6 = 4;
|
|
var_7 = 0;
|
|
|
|
foreach ( var_9 in var_5 )
|
|
{
|
|
if ( !isalive( var_9 ) )
|
|
continue;
|
|
|
|
if ( isdefined( var_0 ) && var_9 == var_0 )
|
|
continue;
|
|
|
|
if ( is_valid_spit_target( var_9, 1 ) )
|
|
return var_9;
|
|
|
|
var_7++;
|
|
|
|
if ( var_7 >= var_6 )
|
|
{
|
|
common_scripts\utility::waitframe();
|
|
var_7 = 0;
|
|
}
|
|
}
|
|
|
|
return undefined;
|
|
}
|
|
|
|
get_grief_targets()
|
|
{
|
|
var_0 = [];
|
|
|
|
if ( !can_spit_gas_cloud() || is_pet() )
|
|
return var_0;
|
|
|
|
foreach ( var_2 in level.players )
|
|
{
|
|
if ( !isalive( var_2 ) )
|
|
continue;
|
|
|
|
if ( isdefined( var_2.inlaststand ) && var_2.inlaststand )
|
|
var_0[var_0.size] = var_2;
|
|
}
|
|
|
|
if ( isdefined( level.drill ) && isdefined( level.drill.state ) && level.drill.state == "offline" )
|
|
var_0[var_0.size] = level.drill;
|
|
|
|
return common_scripts\utility::array_randomize( var_0 );
|
|
}
|
|
|
|
is_valid_spit_target( var_0, var_1 )
|
|
{
|
|
if ( !isalive( var_0 ) )
|
|
return 0;
|
|
|
|
if ( var_1 && isplayer( var_0 ) && !has_attacker_space( var_0 ) )
|
|
return 0;
|
|
|
|
var_2 = get_max_spit_distance_squared();
|
|
var_3 = distance2dsquared( self.origin, var_0.origin );
|
|
|
|
if ( var_3 > var_2 )
|
|
return 0;
|
|
|
|
self.looktarget = var_0;
|
|
|
|
if ( !isalive( var_0 ) )
|
|
return 0;
|
|
|
|
if ( ( isplayer( var_0 ) || issentient( var_0 ) ) && !isdefined( var_0.usingremote ) )
|
|
var_4 = var_0 geteye();
|
|
else
|
|
var_4 = var_0.origin;
|
|
|
|
var_5 = self gettagorigin( "TAG_BREATH" );
|
|
return bullettracepassed( var_5, var_4, 0, self );
|
|
}
|
|
|
|
get_spit_fire_pos( var_0 )
|
|
{
|
|
return self gettagorigin( "TAG_BREATH" );
|
|
}
|
|
|
|
has_attacker_space( var_0 )
|
|
{
|
|
var_1 = level.maxalienattackerdifficultyvalue - level.alien_types[self.alien_type].attributes["attacker_difficulty"];
|
|
var_2 = maps\mp\agents\alien\_alien_think::get_current_attacker_value( var_0 );
|
|
return var_2 <= var_1;
|
|
}
|
|
|
|
handleattacknotetracks( var_0, var_1, var_2, var_3 )
|
|
{
|
|
if ( isdefined( level.dlc_attacknotetrack_override_func ) )
|
|
{
|
|
self [[ level.dlc_attacknotetrack_override_func ]]( var_0, var_1, var_2, var_3 );
|
|
return;
|
|
}
|
|
|
|
if ( var_0 == "spit" )
|
|
return fire_spit_projectile();
|
|
}
|
|
|
|
fire_spit_projectile()
|
|
{
|
|
if ( !isdefined( self.spit_target ) && !isdefined( self.spit_target_location ) )
|
|
return;
|
|
|
|
var_0 = isalive( self.spit_target );
|
|
var_1 = isdefined( self.spit_target.code_classname ) && self.spit_target.code_classname == "script_vehicle";
|
|
|
|
if ( var_0 && !var_1 )
|
|
var_2 = self.spit_target.origin;
|
|
else
|
|
var_2 = self.spit_target_location;
|
|
|
|
if ( self.spit_type == "gas_cloud" )
|
|
spit_gas_cloud_projectile( var_2 );
|
|
else if ( var_0 )
|
|
{
|
|
var_3 = 1400;
|
|
var_2 = get_lookahead_target_location( var_3, self.spit_target, 0 );
|
|
|
|
if ( !bullettracepassed( var_2, get_spit_fire_pos( var_2 ), 0, self ) )
|
|
var_2 = get_lookahead_target_location( var_3, self.spit_target, 1 );
|
|
|
|
spit_basic_projectile( var_2 );
|
|
}
|
|
}
|
|
|
|
get_lookahead_target_location( var_0, var_1, var_2 )
|
|
{
|
|
if ( !isplayer( var_1 ) )
|
|
return var_1.origin;
|
|
|
|
var_3 = get_lookahead_percentage();
|
|
|
|
if ( var_2 && !isdefined( var_1.usingremote ) )
|
|
var_4 = var_1 geteye();
|
|
else
|
|
var_4 = var_1.origin;
|
|
|
|
var_5 = distance( self.origin, var_4 );
|
|
var_6 = var_5 / var_0;
|
|
var_7 = var_1 getvelocity();
|
|
return var_4 + var_7 * var_3 * var_6;
|
|
}
|
|
|
|
can_spit_gas_cloud()
|
|
{
|
|
if ( !self.gas_cloud_available )
|
|
return 0;
|
|
|
|
if ( isdefined( self.enemy ) && isdefined( self.enemy.no_gas_cloud_attack ) && self.enemy.no_gas_cloud_attack )
|
|
return 0;
|
|
|
|
var_0 = ( gettime() - level.spitter_last_cloud_time ) * 0.001;
|
|
return level.spitter_gas_cloud_count < 3 && var_0 > 3.33;
|
|
}
|
|
|
|
spit_basic_projectile( var_0 )
|
|
{
|
|
var_1 = get_spit_fire_pos( var_0 );
|
|
var_2 = magicbullet( "alienspit_mp", var_1, var_0, self );
|
|
var_2.owner = self;
|
|
|
|
if ( isdefined( var_2 ) )
|
|
var_2 thread spit_basic_projectile_impact_monitor( self );
|
|
}
|
|
|
|
spit_basic_projectile_impact_monitor( var_0 )
|
|
{
|
|
self waittill( "explode", var_1 );
|
|
|
|
if ( !isdefined( var_1 ) )
|
|
return;
|
|
|
|
playfx( level._effect["spit_AOE_small"], var_1 + ( 0, 0, 8 ), ( 0, 0, 1 ), ( 1, 0, 0 ) );
|
|
}
|
|
|
|
spit_gas_cloud_projectile( var_0 )
|
|
{
|
|
var_1 = get_spit_fire_pos( var_0 );
|
|
var_2 = magicbullet( "alienspit_gas_mp", var_1, var_0, self );
|
|
var_2.owner = self;
|
|
|
|
if ( isdefined( var_2 ) )
|
|
var_2 thread spit_gas_cloud_projectile_impact_monitor( self );
|
|
|
|
thread gas_cloud_available_timer();
|
|
}
|
|
|
|
gas_cloud_available_timer()
|
|
{
|
|
self endon( "death" );
|
|
self.gas_cloud_available = 0;
|
|
var_0 = randomfloatrange( 10.0, 15.0 );
|
|
wait( var_0 );
|
|
self.gas_cloud_available = 1;
|
|
}
|
|
|
|
spit_gas_cloud_projectile_impact_monitor( var_0 )
|
|
{
|
|
self waittill( "explode", var_1 );
|
|
|
|
if ( !isdefined( var_1 ) )
|
|
return;
|
|
|
|
var_2 = spawn( "trigger_radius", var_1, 0, 150, 128 );
|
|
|
|
if ( !isdefined( var_2 ) )
|
|
return;
|
|
|
|
level.spitter_gas_cloud_count++;
|
|
var_2.onplayer = 1;
|
|
playfx( level._effect["spit_AOE"], var_1 + ( 0, 0, 8 ), ( 0, 0, 1 ), ( 1, 0, 0 ) );
|
|
thread spit_aoe_cloud_damage( var_1, var_2 );
|
|
level notify( "spitter_spit", var_1 );
|
|
wait 10.0;
|
|
var_2 delete();
|
|
level.spitter_gas_cloud_count--;
|
|
}
|
|
|
|
spit_aoe_cloud_damage( var_0, var_1 )
|
|
{
|
|
var_1 endon( "death" );
|
|
wait 2.0;
|
|
|
|
for (;;)
|
|
{
|
|
var_1 waittill( "trigger", var_2 );
|
|
|
|
if ( !isplayer( var_2 ) )
|
|
continue;
|
|
|
|
if ( !isalive( var_2 ) )
|
|
continue;
|
|
|
|
disorient_player( var_2 );
|
|
damage_player( var_2, var_1 );
|
|
}
|
|
}
|
|
|
|
damage_player( var_0, var_1 )
|
|
{
|
|
var_2 = 0.5;
|
|
var_3 = gettime();
|
|
|
|
if ( !isdefined( var_0.last_spitter_gas_damage_time ) )
|
|
var_4 = var_2;
|
|
else if ( var_0.last_spitter_gas_damage_time + var_2 * 1000.0 > var_3 )
|
|
return;
|
|
else
|
|
var_4 = min( var_2, ( var_3 - var_0.last_spitter_gas_damage_time ) * 0.001 );
|
|
|
|
var_5 = var_0 maps\mp\alien\_perk_utility::perk_getgasdamagescalar();
|
|
var_6 = int( 12.0 * var_4 * var_5 );
|
|
|
|
if ( var_6 > 0 )
|
|
var_0 thread [[ level.callbackplayerdamage ]]( var_1, var_1, var_6, 0, "MOD_SUICIDE", "alienspit_gas_mp", var_1.origin, ( 0, 0, 0 ), "none", 0 );
|
|
|
|
var_0.last_spitter_gas_damage_time = var_3;
|
|
}
|
|
|
|
disorient_player( var_0 )
|
|
{
|
|
if ( maps\mp\alien\_utility::is_chaos_mode() && var_0 maps\mp\alien\_perk_utility::perk_getgasdamagescalar() == 0 )
|
|
return;
|
|
else if ( !var_0 maps\mp\alien\_perk_utility::has_perk( "perk_medic", [ 1, 2, 3, 4 ] ) )
|
|
{
|
|
if ( isdefined( level.shell_shock_override ) )
|
|
var_0 [[ level.shell_shock_override ]]( 0.5 );
|
|
else
|
|
var_0 shellshock( "alien_spitter_gas_cloud", 0.5 );
|
|
}
|
|
}
|
|
|
|
get_rl_toward( var_0 )
|
|
{
|
|
var_1 = vectortoangles( var_0.origin - self.origin );
|
|
var_2 = anglestoright( var_1 );
|
|
|
|
if ( common_scripts\utility::cointoss() )
|
|
var_2 = var_2 * -1;
|
|
|
|
return var_2;
|
|
}
|
|
|
|
spitter_combat( var_0 )
|
|
{
|
|
self endon( "bad_path" );
|
|
self endon( "death" );
|
|
self endon( "alien_main_loop_restart" );
|
|
|
|
for (;;)
|
|
{
|
|
var_1 = find_spitter_attack_node( self.enemy );
|
|
|
|
if ( isdefined( var_1 ) )
|
|
{
|
|
move_to_spitter_attack_node( var_1 );
|
|
spitter_attack( self.enemy );
|
|
continue;
|
|
}
|
|
|
|
wait 0.05;
|
|
}
|
|
}
|
|
|
|
release_spit_node()
|
|
{
|
|
if ( isdefined( self.current_spit_node ) )
|
|
{
|
|
self scragentrelinquishclaimednode( self.current_spit_node );
|
|
self.current_spit_node.claimed = 0;
|
|
self.current_spit_node = undefined;
|
|
}
|
|
}
|
|
|
|
claim_spit_node( var_0 )
|
|
{
|
|
self.current_spit_node = var_0;
|
|
var_0.claimed = 1;
|
|
self scragentclaimnode( var_0 );
|
|
}
|
|
|
|
move_to_spitter_attack_node( var_0 )
|
|
{
|
|
self endon( "player_proximity_during_move" );
|
|
release_spit_node();
|
|
claim_spit_node( var_0 );
|
|
self scragentsetgoalnode( var_0 );
|
|
self scragentsetgoalradius( 64 );
|
|
thread enemy_proximity_during_move_monitor();
|
|
self waittill( "goal_reached" );
|
|
}
|
|
|
|
enemy_proximity_during_move_monitor()
|
|
{
|
|
self endon( "death" );
|
|
self endon( "goal_reached" );
|
|
self endon( "alien_main_loop_restart" );
|
|
|
|
for (;;)
|
|
{
|
|
wait 0.05;
|
|
|
|
if ( !maps\mp\alien\_utility::is_normal_upright( anglestoup( self.angles ) ) )
|
|
continue;
|
|
|
|
if ( !maps\mp\agents\alien\_alien_think::melee_okay() )
|
|
continue;
|
|
|
|
if ( isdefined( self.valid_moving_spit_attack_time ) && gettime() < self.valid_moving_spit_attack_time )
|
|
continue;
|
|
|
|
var_0 = find_player_within_distance( 40000.0 );
|
|
|
|
if ( isdefined( var_0 ) )
|
|
break;
|
|
}
|
|
|
|
release_spit_node();
|
|
self notify( "player_proximity_during_move" );
|
|
self scragentsetgoalentity( var_0 );
|
|
self scragentsetgoalradius( 2048.0 );
|
|
self waittill( "goal_reached" );
|
|
}
|
|
|
|
get_possible_spitter_attack_nodes( var_0 )
|
|
{
|
|
if ( maps\mp\alien\_utility::get_alien_type() == "seeder" )
|
|
var_1 = getnodesinradius( var_0.origin, 768, 128, 512, "jump attack" );
|
|
else
|
|
var_1 = getnodesinradius( var_0.origin, 1000, 300, 512, "jump attack" );
|
|
|
|
var_2 = [];
|
|
|
|
foreach ( var_4 in var_1 )
|
|
{
|
|
if ( isdefined( var_4.claimed ) && var_4.claimed )
|
|
continue;
|
|
|
|
var_2[var_2.size] = var_4;
|
|
}
|
|
|
|
return var_2;
|
|
}
|
|
|
|
is_pet()
|
|
{
|
|
return isdefined( self.pet ) && self.pet;
|
|
}
|
|
|
|
get_current_possible_targets()
|
|
{
|
|
if ( is_pet() )
|
|
return level.agentarray;
|
|
else
|
|
return level.players;
|
|
}
|
|
|
|
find_spitter_attack_node( var_0 )
|
|
{
|
|
var_1 = [];
|
|
|
|
if ( is_escape_sequence_active() && isdefined( level.escape_spitter_target_node ) )
|
|
{
|
|
var_1 = get_possible_spitter_attack_nodes( level.escape_spitter_target_node );
|
|
|
|
if ( var_1.size > 0 )
|
|
var_0 = level.escape_spitter_target_node;
|
|
}
|
|
|
|
if ( var_1.size == 0 && isdefined( var_0 ) )
|
|
var_1 = get_possible_spitter_attack_nodes( var_0 );
|
|
|
|
if ( var_1.size == 0 )
|
|
{
|
|
var_2 = get_current_possible_targets();
|
|
|
|
foreach ( var_4 in var_2 )
|
|
{
|
|
wait 0.05;
|
|
|
|
if ( !isalive( var_4 ) )
|
|
continue;
|
|
|
|
if ( isdefined( var_0 ) && var_4 == var_0 )
|
|
continue;
|
|
|
|
var_1 = get_possible_spitter_attack_nodes( var_4 );
|
|
|
|
if ( var_1.size > 0 )
|
|
{
|
|
var_0 = var_4;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( var_1.size == 0 )
|
|
var_1 = get_possible_spitter_attack_nodes( self );
|
|
|
|
if ( var_1.size == 0 )
|
|
return undefined;
|
|
|
|
var_6 = [];
|
|
|
|
if ( isdefined( var_0 ) )
|
|
{
|
|
var_6["dist_from_enemy_weight"] = 8.0;
|
|
var_6["enemy_los_weight"] = 6.0;
|
|
var_6["height_weight"] = 4.0;
|
|
var_7 = get_rl_toward( var_0 );
|
|
var_0 endon( "death" );
|
|
}
|
|
else
|
|
{
|
|
var_6["dist_from_enemy_weight"] = 0.0;
|
|
var_6["enemy_los_weight"] = 0.0;
|
|
var_6["height_weight"] = 0.0;
|
|
var_7 = get_central_enemies_direction();
|
|
}
|
|
|
|
var_6["direction"] = "override";
|
|
var_6["direction_override"] = var_7;
|
|
var_6["direction_weight"] = 1.0;
|
|
var_6["min_height"] = 64.0;
|
|
var_6["max_height"] = 400.0;
|
|
var_6["enemy_los"] = 1;
|
|
var_6["min_dist_from_enemy"] = 300.0;
|
|
var_6["max_dist_from_enemy"] = 800.0;
|
|
var_6["desired_dist_from_enemy"] = 600.0;
|
|
var_6["min_dist_from_all_enemies"] = 300.0;
|
|
var_6["min_dist_from_all_enemies_weight"] = 5.0;
|
|
var_6["not_recently_used_weight"] = 10.0;
|
|
var_6["recently_used_time_limit"] = 30.0;
|
|
var_6["random_weight"] = 1.0;
|
|
var_8 = maps\mp\agents\alien\_alien_think::get_retreat_node_rated( var_0, var_6, var_1 );
|
|
return var_8;
|
|
}
|
|
|
|
get_central_enemies_direction()
|
|
{
|
|
var_0 = get_current_possible_targets();
|
|
|
|
if ( var_0.size == 0 )
|
|
return self.origin + anglestoforward( self.angles ) * 100;
|
|
|
|
var_1 = ( 0, 0, 0 );
|
|
|
|
foreach ( var_3 in var_0 )
|
|
var_1 = var_1 + var_3.origin;
|
|
|
|
var_1 = var_1 / var_0.size;
|
|
return var_1 - self.origin;
|
|
}
|
|
|
|
spitter_attack( var_0 )
|
|
{
|
|
self endon( "spitter_node_move_requested" );
|
|
|
|
if ( !isdefined( self.current_spit_node ) )
|
|
{
|
|
choose_spit_type( "close_range" );
|
|
spit_projectile( var_0 );
|
|
self.valid_moving_spit_attack_time = gettime() + randomfloatrange( 1.5, 3.0 ) * 1000.0;
|
|
return;
|
|
}
|
|
|
|
set_up_attack_node_watchers();
|
|
|
|
if ( !is_escape_sequence_active() )
|
|
wait( randomfloatrange( 1.5, 3.0 ) * 0.5 );
|
|
|
|
for (;;)
|
|
{
|
|
var_1 = undefined;
|
|
var_2 = 0.0;
|
|
|
|
while ( !isdefined( var_1 ) )
|
|
{
|
|
var_2 = var_2 + 0.2;
|
|
|
|
if ( var_2 >= 1.0 )
|
|
return;
|
|
|
|
wait 0.2;
|
|
|
|
if ( isdefined( var_0 ) && isdefined( var_0.code_classname ) && var_0.code_classname == "script_vehicle" )
|
|
{
|
|
var_1 = var_0;
|
|
continue;
|
|
}
|
|
|
|
var_1 = get_best_spit_target( var_0 );
|
|
}
|
|
|
|
choose_spit_type( "long_range" );
|
|
spit_projectile( var_1 );
|
|
wait( randomfloatrange( 1.5, 3.0 ) );
|
|
}
|
|
}
|
|
|
|
choose_spit_type( var_0 )
|
|
{
|
|
if ( !is_pet() && can_spit_gas_cloud() )
|
|
self.spit_type = "gas_cloud";
|
|
else
|
|
self.spit_type = var_0;
|
|
}
|
|
|
|
set_up_attack_node_watchers()
|
|
{
|
|
thread spitter_node_duration_monitor( 10 );
|
|
thread spitter_node_attacked_monitor( 0.1 );
|
|
|
|
if ( !is_pet() )
|
|
thread spitter_node_player_proximity( 90000.0 );
|
|
}
|
|
|
|
spitter_node_duration_monitor( var_0 )
|
|
{
|
|
self endon( "spitter_node_move_requested" );
|
|
self endon( "death" );
|
|
self endon( "alien_main_loop_restart" );
|
|
wait( var_0 );
|
|
self notify( "spitter_node_move_requested" );
|
|
}
|
|
|
|
spitter_node_attacked_monitor( var_0 )
|
|
{
|
|
self endon( "spitter_node_move_requested" );
|
|
self endon( "death" );
|
|
self endon( "alien_main_loop_restart" );
|
|
self waittill( "damage" );
|
|
wait( var_0 );
|
|
self notify( "spitter_node_move_requested" );
|
|
}
|
|
|
|
spitter_node_player_proximity( var_0 )
|
|
{
|
|
self endon( "spitter_node_move_requested" );
|
|
self endon( "death" );
|
|
self endon( "alien_main_loop_restart" );
|
|
|
|
for (;;)
|
|
{
|
|
var_1 = find_player_within_distance( var_0 );
|
|
|
|
if ( isdefined( var_1 ) )
|
|
break;
|
|
|
|
wait 0.2;
|
|
}
|
|
|
|
self notify( "spitter_node_move_requested" );
|
|
}
|
|
|
|
find_player_within_distance( var_0 )
|
|
{
|
|
foreach ( var_2 in level.players )
|
|
{
|
|
if ( !isalive( var_2 ) )
|
|
continue;
|
|
|
|
var_3 = distance2dsquared( self.origin, var_2.origin );
|
|
|
|
if ( var_3 < var_0 )
|
|
return var_2;
|
|
}
|
|
|
|
return undefined;
|
|
}
|