IL-GSC/BO1/PC/ZM/maps/_drones.gsc
2024-02-18 17:32:07 -05:00

1745 lines
47 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include maps\_utility;
#include animscripts\Utility;
#include animscripts\SetPoseMovement;
#include animscripts\Combat_utility;
#include animscripts\shared;
#include common_scripts\Utility;
#include maps\_spawner;
#using_animtree( "fakeshooters" );
init()
{
setAnimArray();
level.drone_impact = loadfx( "impacts/fx_flesh_hit" );
level.drone_muzzleflash = loadfx( "weapon/muzzleflashes/fx_standard_flash" );
if( !IsDefined( level.traceHeight ) )
{
level.traceHeight = 400;
}
if( !IsDefined( level.droneStepHeight ) )
{
level.droneStepHeight = 100;
}
if( !IsDefined( level.max_drones ) )
{
level.max_drones = [];
}
if( !IsDefined( level.max_drones["axis"] ) )
{
level.max_drones["axis"] = 32;
}
if( !IsDefined( level.max_drones["allies"] ) )
{
level.max_drones["allies"] = 32;
}
if ( isSplitScreen() )
{
level.max_drones["axis"] = 8;
level.max_drones["allies"] = 8;
}
if( !IsDefined( level.drones ) )
{
level.drones = [];
}
if( !IsDefined( level.drones["axis"] ) )
{
level.drones["axis"] = struct_arrayspawn();
}
if( !IsDefined( level.drones["allies"] ) )
{
level.drones["allies"] = struct_arrayspawn();
}
array_thread( getentarray( "drone_axis", "targetname" ), ::drone_triggers_think );
array_thread( getentarray( "drone_allies", "targetname" ), ::drone_triggers_think );
flag_init("reached_drone_spawn_cap");
level.MAX_DRONES_PER_FRAME = 10;
level.drone_spawned_this_frame = 0;
level thread reset_drone_throttle();
}
build_struct_targeted_origins()
{
if( !IsDefined( self.target ) )
{
return;
}
self.targeted = getstructarray(self.target,"targetname");
}
drone_triggers_think()
{
self endon( "death" );
if( self.targetname == "drone_allies" )
{
team = "allies";
}
else
{
team = "axis";
}
self build_struct_targeted_origins();
qFakeDeath = true;
if( ( IsDefined( self.script_allowdeath ) ) &&( self.script_allowdeath == 0 ) )
{
qFakeDeath = false;
}
qSightTrace = false;
if( ( IsDefined( self.script_trace ) ) &&( self.script_trace > 0 ) )
{
qSightTrace = true;
}
assert( IsDefined( self.targeted ) );
assert( IsDefined( self.targeted[0] ) );
if( IsDefined( self.script_ender ) )
{
level endon( self.script_ender );
}
self waittill( "trigger" );
if( !IsDefined( self.script_repeat ) )
{
repeat_times = 999999;
}
else
{
repeat_times = self.script_repeat;
}
if( ( ( IsDefined( self.script_noteworthy ) ) && ( self.script_noteworthy == "looping" ) ) ||
( isdefined( self.script_noteworthy ) && ( IsSubStr(self.script_noteworthy, "group") ) ) ||
( ( IsDefined( self.script_looping ) ) &&( self.script_looping > 0 ) )
)
{
assert( IsDefined( self.script_delay ) ||( IsDefined( self.script_delay_min ) && IsDefined( self.script_delay_max ) ) );
self endon( "stop_drone_loop" );
for( i = 0; i < repeat_times; i++ )
{
level notify( "new drone Spawn wave" );
spawnSize = undefined;
if( IsDefined( self.script_drones_min ) )
{
max = self.targeted.size;
if( IsDefined( self.script_drones_max ) )
{
max = self.script_drones_max;
}
if( self.script_drones_min == max )
{
spawnSize = max;
}
else
{
spawnSize = ( self.script_drones_min + RandomInt( max - self.script_drones_min ) );
}
}
self thread drone_spawngroup( self.targeted, qFakeDeath, spawnSize, qSightTrace, team );
self drone_triggers_delay_first_spawn();
if( ( IsDefined( self.script_requires_player ) ) &&( self.script_requires_player > 0 ) )
{
self waittill( "trigger" );
}
if( !IsDefined( self.script_repeat ) )
{
repeat_times = 999999;
}
}
}
else
{
spawnSize = undefined;
if( IsDefined( self.script_drones_min ) )
{
max = self.targeted.size;
if( IsDefined( self.script_drones_max ) )
{
max = self.script_drones_max;
}
if( self.script_drones_min == max )
{
spawnSize = max;
}
else
{
spawnSize = ( self.script_drones_min + RandomInt( max - self.script_drones_min ) );
}
}
self drone_triggers_delay_first_spawn();
self thread drone_spawngroup( self.targeted, qFakeDeath, spawnSize, qSightTrace, team );
if( IsDefined( self.count ) && self.count > 1 )
{
wait( 0.05 );
self.count--;
self thread drone_triggers_think();
}
}
}
drone_triggers_delay_first_spawn()
{
if( IsDefined( self.script_delay ) )
{
if( self.script_delay > 0 )
{
wait( self.script_delay );
}
}
else if( IsDefined( self.script_delay_min ) && IsDefined( self.script_delay_max ) )
{
if( self.script_delay_max > self.script_delay_min )
{
wait( RandomFloatRange( self.script_delay_min, self.script_delay_max ) );
}
}
}
generate_offsets( spawncount )
{
offsets = [];
delta = 0.5 / spawncount;
for( i = 0; i < spawncount; i++ )
{
id = randomint( spawncount * 2 );
offsets[i] = id * delta;
}
return offsets;
}
drone_spawngroup( spawnpoint, qFakeDeath, spawnSize, qSightTrace, team )
{
spawncount = spawnpoint.size;
if( IsDefined( spawnSize ) )
{
spawncount = spawnSize;
spawnpoint = array_randomize( spawnpoint );
}
if( ( spawncount > spawnpoint.size ) && ( spawnpoint.size > 1 ) )
{
spawncount = spawnpoint.size;
}
offsets = [];
if( isdefined( self.script_noteworthy ) && ( IsSubStr(self.script_noteworthy, "group") ) )
offsets = generate_offsets( spawncount );
for( i = 0; i < spawncount; i++ )
{
if (IsDefined(self.script_int))
{
wait RandomFloat(0.1, 1.0);
}
while(!self ok_to_trigger_spawn())
wait_network_frame();
if( i < spawnpoint.size )
{
spawnpoint[i] thread drone_spawn( qFakeDeath, qSightTrace, team, offsets[i] );
}
else
{
if( i > 0 && offsets[i-1] == offsets[i] )
wait( randomfloat( .8, 1.1 ) );
else
wait( randomfloat( .5, .9 ) );
spawnpoint[spawnpoint.size - 1] thread drone_spawn( qFakeDeath, qSightTrace, team, offsets[i] );
}
level._numTriggerSpawned ++;
}
}
#using_animtree( "fakeshooters" );
drone_spawn( qFakeDeath, qSightTrace, team, offset,respawner )
{
if(!isDefined(respawner))
{
level endon( "new drone Spawn wave" );
}
if(isDefined(self.script_ender))
{
level endon(self.script_ender);
}
if( !IsDefined( qFakeDeath ) )
{
qFakeDeath = false;
}
if( !IsDefined( qSightTrace ) )
{
qSightTrace = false;
}
check_drone_throttle();
while( ( qSightTrace ) &&( self spawnpoint_playersView() ) )
{
wait 0.2;
}
if( level.drones[team].lastindex > level.max_drones[team] )
{
return;
}
if( isdefined( offset ) )
spawnoffset = offset * 2 - 1;
else
spawnoffset = 0;
spawnpos = self.origin;
if( isdefined( self.radius ) )
{
angles = ( 0, 0, 0 );
if( isdefined( self.angles ) )
angles = self.angles;
right = AnglesToRight( angles );
spawnpos += vector_scale( right, ( spawnoffset * self.radius ) );
}
level.drone_spawned_this_frame++;
guy = Spawn( "script_model", groundpos( spawnpos ) );
guy.droneRunOffset = spawnoffset;
if( IsDefined( self.angles ) )
{
guy.angles = self.angles;
}
else if( IsDefined( self.targeted ) )
{
guy.angles = VectorToAngles( self.targeted[0].origin - guy.origin );
}
assert( IsDefined( level.drone_spawnFunction[team] ) );
if(IsDefined(level.drone_spawnFunction_passNode))
{
guy [[level.drone_spawnFunction[team]]]( self );
}
else
{
guy [[level.drone_spawnFunction[team]]]();
}
if(isDefined(self.weaponinfo))
{
guy.weapon = self.weaponinfo;
weaponModel = GetWeaponModel( guy.weapon );
guy Attach( weaponModel, "tag_weapon_right" );
guy UseWeaponHideTags(guy.weapon);
guy.bulletsInClip = WeaponClipSize( guy.weapon );
}
else
{
guy drone_assign_weapon( team );
}
guy.targetname = "drone";
guy.script_noteworthy = self.script_noteworthy;
guy MakeFakeAI();
guy.team = team;
guy.fakeDeath = qFakeDeath;
guy drone_set_run_cycle();
if( IsDefined(level.drone_run_rate) )
{
guy.droneRunRate = level.drone_run_rate;
}
else if( IsDefined(level.drone_run_rate_multiplier) )
{
guy.droneRunRate = guy.droneRunRate * level.drone_run_rate_multiplier;
}
guy thread drone_think( self );
if(isDefined(self.script_string) && self.script_string == "respawn" )
{
if(isDefined(self.script_ender) )
{
level thread drone_respawn_after_death(guy,self,qFakeDeath, qSightTrace, team, offset,self.script_ender);
}
else
{
level thread drone_respawn_after_death(guy,self,qFakeDeath, qSightTrace, team, offset,undefined);
}
}
}
check_drone_throttle()
{
can_spawn = false;
while(!can_spawn)
{
if(level.drone_spawned_this_frame > level.MAX_DRONES_PER_FRAME)
{
flag_set("reached_drone_spawn_cap");
}
flag_waitopen("reached_drone_spawn_cap");
wait(0.05);
if(level.drone_spawned_this_frame < level.MAX_DRONES_PER_FRAME)
{
can_spawn = true;
}
}
}
reset_drone_throttle()
{
while(true)
{
waittillframeend;
flag_clear("reached_drone_spawn_cap");
level.drone_spawned_this_frame = 0;
wait(0.05);
}
}
drone_respawn_after_death(guy,start_struct,qFakeDeath, qSightTrace, team, offset,ender)
{
if(isDefined(ender))
{
level endon(ender);
}
guy waittill("death");
wait(randomintrange(3,5));
if(isDefined(start_struct.script_string) && start_struct.script_string == "respawn")
{
start_struct thread drone_spawn(qFakeDeath, false, team, offset,1);
}
}
spawnpoint_playersView()
{
if( !IsDefined( level.cos80 ) )
{
level.cos80 = cos( 80 );
}
players = get_players();
player_view_count = 0;
success = false;
for( i = 0; i < players.size; i++ )
{
prof_begin( "drone_math" );
forwardvec = AnglesToForward( players[i].angles );
normalvec = VectorNormalize( self.origin - players[i] GetOrigin() );
vecdot = vectordot( forwardvec, normalvec );
prof_end( "drone_math" );
if( vecdot > level.cos80 )
{
prof_begin( "drone_math" );
success = BulletTracePassed( players[i] GetEye(), self.origin +( 0, 0, 48 ), false, self );
prof_end( "drone_math" );
if( success )
{
player_view_count++;
}
}
}
if( player_view_count != 0 )
{
return true;
}
return false;
}
drone_assign_weapon( team )
{
if( team == "allies" )
{
if( IsDefined( level.drone_weaponlist_allies ) && level.drone_weaponlist_allies.size > 0 )
{
if( level.drone_weaponlist_allies[0] == "unarmed" )
{
self.weapon = undefined;
return;
}
randWeapon = RandomInt( level.drone_weaponlist_allies.size );
self.weapon = level.drone_weaponlist_allies[randWeapon];
ASSERTEX( IsDefined( self.weapon ), "_drones::couldn't assign weapon from level.drone_weaponlist because the array value is undefined." );
}
else
{
switch( level.campaign )
{
case "american":
self.weapon = drone_allies_assignWeapon_american();
break;
case "british":
self.weapon = drone_allies_assignWeapon_british();
break;
case "russian":
self.weapon = drone_allies_assignWeapon_russian();
break;
}
}
}
else
{
if( IsDefined( level.drone_weaponlist_axis ) && level.drone_weaponlist_axis.size > 0 )
{
randWeapon = RandomInt( level.drone_weaponlist_axis.size );
self.weapon = level.drone_weaponlist_axis[randWeapon];
ASSERTEX( IsDefined( self.weapon ), "_drones::couldn't assign weapon from level.drone_weaponlist because the array value is undefined." );
}
else
{
switch( level.campaign )
{
case "american":
self.weapon = drone_axis_assignWeapon_japanese();
break;
case "british":
self.weapon = drone_axis_assignWeapon_german();
break;
case "russian":
self.weapon = drone_axis_assignWeapon_german();
break;
}
}
}
weaponModel = GetWeaponModel( self.weapon );
self Attach( weaponModel, "tag_weapon_right" );
self UseWeaponHideTags(self.weapon);
self.bulletsInClip = WeaponClipSize( self.weapon );
}
drone_allies_assignWeapon_american()
{
array = [];
array[array.size] = "m16_sp";
return array[RandomInt( array.size )];
}
drone_allies_assignWeapon_british()
{
array = [];
array[array.size] = "m16_sp";
return array[RandomInt( array.size )];
}
drone_allies_assignWeapon_russian()
{
array = [];
array[array.size] = "ak47_sp";
return array[RandomInt( array.size )];
}
drone_axis_assignWeapon_german()
{
array = [];
array[array.size] = "ak47_sp";
return array[RandomInt( array.size )];
}
drone_axis_assignWeapon_japanese()
{
array = [];
array[array.size] = "ak47_sp";
return array[RandomInt( array.size )];
}
drone_setName()
{
wait( 0.25 );
if( !IsDefined( self ) )
{
return;
}
if( self.team != "allies" )
{
return;
}
if( !IsDefined( level.names ) )
{
maps\_names::setup_names();
}
if( IsDefined( self.script_friendname ) )
{
self.name = self.script_friendname;
}
else
{
switch( level.campaign )
{
case "american":
self maps\_names::get_name_for_nationality( "american" );
break;
case "russian":
self maps\_names::get_name_for_nationality( "russian" );
break;
case "british":
self maps\_names::get_name_for_nationality( "british" );
break;
}
}
assert( IsDefined( self.name ) );
subText = undefined;
if( !IsDefined( self.weapon ) )
{
subText = &"";
}
else
{
switch( self.weapon )
{
case "commando_sp":
subText = &"";
break;
case "m1garand":
case "m1garand_wet":
case "lee_enfield":
case "m1carbine":
case "SVT40":
case "mosin_rifle":
subText = ( &"WEAPON_RIFLEMAN" );
break;
case "thompson":
case "thompson_wet":
subText = ( &"WEAPON_SUBMACHINEGUNNER" );
break;
case "BAR":
case "ppsh":
default:
subText = ( &"WEAPON_SUPPORTGUNNER" );
break;
}
}
if( ( IsDefined( self.model ) ) &&( issubstr( self.model, "medic" ) ) )
{
subText = ( &"WEAPON_MEDICPLACEHOLDER" );
}
assert( IsDefined( subText ) );
self setlookattext( self.name, &"");
}
drone_think( firstNode )
{
self endon( "death" );
self.health = 1000000;
self thread drone_setName();
if(self.team == "allies")
{
level thread maps\_friendlyfire::friendly_fire_think( self );
}
self thread drones_clear_variables();
structarray_add( level.drones[self.team], self );
level notify( "new_drone" );
if(IsDefined(level._drones_mg_target))
{
self.turrettarget = Spawn( "script_origin", self.origin+( 0, 0, 50 ) );
self.turrettarget LinkTo( self );
}
self endon( "drone_death" );
assert( IsDefined( firstNode ) );
if( IsDefined( level.drone_think_func ) )
{
self thread [[level.drone_think_func]]();
}
if( ( IsDefined( self.fakeDeath ) ) &&( self.fakeDeath == true ) )
{
self thread drone_fakeDeath();
}
self endon( "drone_shooting" );
self.no_death_sink = false;
if( IsDefined( firstNode.script_drone_no_sink ) && firstNode.script_drone_no_sink )
{
self.no_death_sink = true;
}
self drone_runChain( firstNode );
wait( 0.05 );
level notify("drone_at_last_node", self);
self.running = undefined;
idle_org = self.origin;
idle_ang = self.angles;
self useAnimTree( #animtree );
idleAnim[0] = %stand_alert_1;
idleAnim[1] = %stand_alert_2;
idleAnim[2] = %stand_alert_3;
while( IsDefined( self ) )
{
self AnimScripted( "drone_idle_anim", idle_org, idle_ang, idleAnim[RandomInt( idleAnim.size )] );
self waittillmatch( "drone_idle_anim", "end" );
}
}
#using_animtree( "fakeshooters" );
drone_mortarDeath( direction )
{
self useAnimTree( #animtree );
switch( direction )
{
case "up":
self thread drone_doDeath( %death_explosion_up10 );
break;
case "forward":
self thread drone_doDeath( %death_explosion_forward13 );
break;
case "back":
self thread drone_doDeath( %death_explosion_back13 );
break;
case "left":
self thread drone_doDeath( %death_explosion_left11 );
break;
case "right":
self thread drone_doDeath( %death_explosion_right13 );
break;
}
}
#using_animtree( "fakeshooters" );
drone_flameDeath()
{
self useAnimTree( #animtree );
self thread drone_fakeDeath( true, true );
}
#using_animtree( "fakeshooters" );
drone_fakeDeath( instant, flamedeath )
{
if( !IsDefined( instant ) )
{
instant = false;
}
self endon( "delete" );
self endon( "drone_death" );
explosivedeath = false;
explosion_ori = ( 0, 0, 0 );
if(!IsDefined(flamedeath))
{
flamedeath = false;
}
while( IsDefined( self ) )
{
if( !instant )
{
self SetCanDamage( true );
self waittill( "damage", amount, attacker, direction_vec, damage_ori, type );
if( type == "MOD_GRENADE" || type == "MOD_GRENADE_SPLASH" || type == "MOD_EXPLOSIVE" ||
type == "MOD_EXPLOSIVE_SPLASH" || type == "MOD_PROJECTILE" || type == "MOD_PROJECTILE_SPLASH" )
{
self.damageweapon = "none";
explosivedeath = true;
explosion_ori = damage_ori;
}
else if( type == "MOD_BURNED" )
{
flamedeath = true;
}
self death_notify_wrapper( attacker, type );
if( self.team == "axis" && ( IsPlayer( attacker ) || attacker == level.playervehicle ) )
{
level notify( "player killed drone" );
}
}
if( ( IsDefined( self.customFirstAnim ) ) &&( self.customFirstAnim == true ) )
{
self waittill( "customFirstAnim done" );
}
if( !IsDefined( self ) )
{
return;
}
self notify( "Stop shooting" );
self.dontDelete = true;
deathAnim = undefined;
self useAnimTree( #animtree );
if( explosivedeath )
{
direction = drone_get_explosion_death_dir( self.origin, self.angles, explosion_ori, 50 );
self thread drone_mortarDeath( direction );
return;
}
else if( flamedeath )
{
deaths[0] = %ai_flame_death_a;
deaths[1] = %ai_flame_death_b;
deaths[2] = %ai_flame_death_c;
deaths[3] = %ai_flame_death_d;
}
else if( IsDefined( self.running ) )
{
deaths[0] = %death_run_stumble;
deaths[1] = %death_run_onfront;
deaths[2] = %death_run_onleft;
deaths[3] = %death_run_forward_crumple;
}
else
{
deaths[0] = %death_stand_dropinplace;
}
self thread drone_doDeath( deaths[RandomInt( deaths.size )] );
return;
}
}
#using_animtree( "fakeshooters" );
drone_delayed_bulletdeath( waitTime, deathRemoveNotify )
{
self endon( "delete" );
self endon( "drone_death" );
self.dontDelete = true;
if( !IsDefined( waitTime ) )
{
waitTime = 0;
}
if( waitTime > 0 )
{
wait( waitTime );
}
self thread drone_fakeDeath( true );
}
do_death_sound()
{
camp = level.campaign;
team = self.team;
alias = undefined;
if(camp == "american" && team == "allies")
alias = "dds_generic_death_american";
if(camp == "american" && team == "axis")
alias = "dds_generic_death_japanese";
if(camp == "russian" && team == "allies")
alias = "dds_generic_death_russian";
if(camp == "russian" && team == "axis")
alias = "dds_generic_death_german";
if(camp == "vietnamese" && team == "axis")
alias = "dds_generic_death_vietnamese ";
if(IsDefined(alias) && SoundExists(alias) && !IsDefined(level._drones_sounds_disable))
{
self thread play_sound_in_space( alias );
}
}
#using_animtree( "fakeshooters" );
drone_doDeath( deathAnim, deathRemoveNotify )
{
self moveTo( self.origin, 0.05, 0, 0 );
traceDeath = false;
if( ( IsDefined( self.running ) ) && self.running )
{
traceDeath = true;
}
self.running = undefined;
self notify( "drone_death" );
self notify( "Stop shooting" );
self Unlink();
self useAnimTree( #animtree );
self thread drone_doDeath_impacts();
do_death_sound();
prof_begin( "drone_math" );
cancelRunningDeath = false;
if( traceDeath )
{
offset = getcycleoriginoffset( self.angles, deathAnim );
endAnimationLocation = ( self.origin + offset );
endAnimationLocation = PhysicsTrace( ( endAnimationLocation +( 0, 0, 128 ) ), ( endAnimationLocation -( 0, 0, 128 ) ) );
d1 = abs( endAnimationLocation[2] - self.origin[2] );
if( d1 > 20 )
{
cancelRunningDeath = true;
}
else
{
forwardVec = AnglesToForward( self.angles );
rightVec = AnglesToRight( self.angles );
upVec = anglestoup( self.angles );
relativeOffset = ( 50, 0, 0 );
secondPos = endAnimationLocation;
secondPos += vector_scale( forwardVec, relativeOffset[0] );
secondPos += vector_scale( rightVec, relativeOffset[1] );
secondPos += vector_scale( upVec, relativeOffset[2] );
secondPos = PhysicsTrace( ( secondPos +( 0, 0, 128 ) ), ( secondPos -( 0, 0, 128 ) ) );
d2 = abs( secondPos[2] - self.origin[2] );
if( d2 > 20 )
{
cancelRunningDeath = true;
}
}
}
prof_end( "drone_math" );
if( cancelRunningDeath )
{
deathAnim = %death_stand_dropinplace;
}
self animscripted( "drone_death_anim", self.origin, self.angles, deathAnim, "deathplant" );
self thread drone_ragdoll( deathAnim );
self waittillmatch( "drone_death_anim", "end" );
if( !IsDefined( self ) )
{
return;
}
self setcontents( 0 );
if( IsDefined( deathRemoveNotify ) )
{
level waittill( deathRemoveNotify );
}
else
{
wait 3;
}
if( !IsDefined( self ) )
{
return;
}
if( !IsDefined(self.no_death_sink) || (IsDefined(self.no_death_sink) && !self.no_death_sink ))
{
self MoveTo( self.origin - ( 0, 0, 100 ), 7 );
wait( 3 );
}
if( !IsDefined( self ) )
{
return;
}
self.dontDelete = undefined;
self thread drone_delete();
}
drone_ragdoll( deathAnim )
{
time = self GetAnimTime( deathAnim );
wait( time * 0.55 );
if( IsDefined( self.weapon ) )
{
weaponModel = GetWeaponModel( self.weapon );
if( IsDefined( weaponModel ) )
{
self detach( weaponModel, "tag_weapon_right" );
}
}
if( isdefined( level.no_drone_ragdoll ) && level.no_drone_ragdoll == true )
{
}
else
{
self StartRagDoll();
}
}
drone_doDeath_impacts()
{
bone[0] = "J_Knee_LE";
bone[1] = "J_Ankle_LE";
bone[2] = "J_Clavicle_LE";
bone[3] = "J_Shoulder_LE";
bone[4] = "J_Elbow_LE";
impacts = ( 1 + RandomInt( 2 ) );
for( i = 0; i < impacts; i++ )
{
playfxontag( level.drone_impact, self, bone[RandomInt( bone.size )] );
if( !IsDefined(level._drones_sounds_disable))
{
self PlaySound( "prj_bullet_impact_small_flesh" );
}
wait( 0.05 );
}
}
drone_runChain( point_start )
{
self endon( "drone_death" );
self endon( "drone_shooting" );
runPos = undefined;
while( IsDefined( self ) )
{
if( IsDefined( point_start.script_death ) )
{
self.dontDelete = true;
self thread drone_delayed_bulletdeath( 0 );
}
else
if( ( IsDefined( point_start.script_death_min ) ) &&( IsDefined( point_start.script_death_max ) ) )
{
self.dontDelete = true;
self thread drone_delayed_bulletdeath( point_start.script_death_min + RandomFloat( point_start.script_death_max - point_start.script_death_min ) );
}
if( ( IsDefined( point_start.script_delete ) ) &&( point_start.script_delete >= 0 ) )
{
self.dontDelete = undefined;
self thread drone_delete( point_start.script_delete );
}
if( !IsDefined( point_start.targeted ) )
{
break;
}
point_end = point_start.targeted;
if( ( !IsDefined( point_end ) ) ||( !IsDefined( point_end[0] ) ) )
{
break;
}
index = RandomInt( point_end.size );
runPos = groundpos( point_end[index].origin );
if( IsDefined( point_end[index].radius ) )
{
assert( point_end[index].radius > 0 );
if( !IsDefined( self.droneRunOffset ) )
{
self.droneRunOffset = ( 0 - 1 +( RandomFloat( 2 ) ) );
}
if( !IsDefined( point_end[index].angles ) )
{
point_end[index].angles = ( 0, 0, 0 );
}
prof_begin( "drone_math" );
forwardVec = AnglesToForward( point_end[index].angles );
rightVec = AnglesToRight( point_end[index].angles );
upVec = anglestoup( point_end[index].angles );
relativeOffset = ( 0, ( self.droneRunOffset * point_end[index].radius ) , 0 );
runPos += vector_scale( forwardVec, relativeOffset[0] );
runPos += vector_scale( rightVec, relativeOffset[1] );
runPos += vector_scale( upVec, relativeOffset[2] );
prof_end( "drone_math" );
}
script_noteworthy = point_start.script_noteworthy;
script_string = point_start.script_string;
script_int = point_start.script_int;
self ShooterRun( runPos, script_noteworthy, script_string, script_int );
point_start = point_end[index];
}
if( IsDefined( runPos ) )
{
if( IsDefined( point_start.script_noteworthy ) )
{
self ShooterRun( runPos, point_start.script_noteworthy );
}
else
{
self ShooterRun( runPos );
}
}
if( ( IsDefined( point_start.script_delete ) ) &&( point_start.script_delete >= 0 ) )
{
self thread drone_delete( point_start.script_delete );
}
}
drones_clear_variables()
{
if( IsDefined( self.voice ) )
{
self.voice = undefined;
}
}
drone_delete( delayTime )
{
if( ( IsDefined( delayTime ) ) &&( delayTime > 0 ) )
{
wait( delayTime );
}
if( !IsDefined( self ) )
{
return;
}
self notify( "drone_death" );
self notify( "drone_idle_anim" );
if( !( is_in_array( level.drones[self.team].array, self ) ) )
{
self Delete();
return;
}
structarray_remove( level.drones[self.team], self );
if( !IsDefined( self.dontDelete ) )
{
if( IsDefined( self.turrettarget ) )
{
self.turrettarget delete();
}
if( IsDefined( self.shootTarget ) && !self.shootTarget is_vehicle())
{
self.shootTarget delete();
}
self detachall();
self delete();
}
}
#using_animtree( "fakeShooters" );
ShooterRun( destinationPoint, event, target_targetname, script_int )
{
if( !IsDefined( self ) )
{
return;
}
self endon("death");
self notify( "Stop shooting" );
self UseAnimTree( #animtree );
prof_begin( "drone_math" );
d = distance( self.origin, destinationPoint );
if( !IsDefined( self.droneRunRate ) )
{
self.droneRunRate = 200;
}
speed = ( d / self.droneRunRate );
self.lowheight = false;
self turnToFacePoint( destinationPoint, speed );
customFirstAnim = undefined;
if( IsDefined( event ) )
{
switch( event )
{
case "idle_then_alert":
AssertEX( IsDefined(level.droneidleanims) && level.droneidleanims.size > 0, "No drone idle anims setup for the level" );
random_index = RandomInt(level.droneidleanims.size);
self ClearAnim( self.drone_run_cycle, 0 );
self SetAnim(level.droneidleanims[random_index], 1, 0.05);
level waittill("alert_all_drones");
self ClearAnim( level.droneidleanims[random_index], 0);
wait(RandomFloatRange(0.1, 0.5));
self.idletextprint = "idle guy got to his next node";
self.drone_run_cycle = drone_pick_run_anim();
self.running = undefined;
break;
case "cheer_then_run":
AssertEx( IsDefined(level.droneidleanims) && level.droneidleanims.size > 0, "No drone idle anims setup for the level" );
random_index = RandomInt(level.droneidleanims.size);
self ClearAnim( self.drone_run_cycle, 0);
self SetAnim(level.droneidleanims[random_index], 1, 0.05);
level waittill("alert_all_drones");
wait(RandomFloatRange(0.1, 10.0));
self ClearAnim( level.droneidleanims[random_index], 0);
break;
case "jump":
customFirstAnim = %jump_across_100;
break;
case "jumpdown":
customFirstAnim = %jump_down_56;
break;
case "wall_hop":
customFirstAnim = %traverse_wallhop;
break;
case "step_up":
customFirstAnim = %step_up_low_wall;
break;
case "trench_jump_out":
customFirstAnim = %ai_mantle_on_48;
break;
case "low_height":
self.lowheight = true;
break;
case "mortardeath_up":
self thread drone_mortarDeath( "up" );
return;
case "mortardeath_forward":
self thread drone_mortarDeath( "forward" );
return;
case "mortardeath_back":
self thread drone_mortarDeath( "back" );
return;
case "mortardeath_left":
self thread drone_mortarDeath( "left" );
return;
case "mortardeath_right":
self thread drone_mortarDeath( "right" );
return;
case "shoot":
forwardVec = AnglesToForward( self.angles );
rightVec = AnglesToRight( self.angles );
upVec = anglestoup( self.angles );
relativeOffset = ( 300, 0, 64 );
shootPos = self.origin;
shootPos += vector_scale( forwardVec, relativeOffset[0] );
shootPos += vector_scale( rightVec, relativeOffset[1] );
shootPos += vector_scale( upVec, relativeOffset[2] );
self.shootTarget = Spawn( "script_origin", shootPos );
self thread ShooterShoot( self.shootTarget );
return;
case "shoot_then_run_after_notify":
forwardVec = AnglesToForward( self.angles );
rightVec = AnglesToRight( self.angles );
upVec = anglestoup( self.angles );
relativeOffset = ( 300, 0, 64 );
shootPos = self.origin;
shootPos += vector_scale( forwardVec, relativeOffset[0] );
shootPos += vector_scale( rightVec, relativeOffset[1] );
shootPos += vector_scale( upVec, relativeOffset[2] );
self.shootTarget = Spawn( "script_origin", shootPos );
self thread ShooterShoot( self.shootTarget );
self waittill ("Stop shooting");
self ClearAnim(%combat_directions, 0);
self ClearAnim(%exposed_reload, 0);
break;
case "shoot_at_vehicle_then_move":
AssertEx(IsDefined(target_targetname), "Drone shooting at vehicle, but doesn't know which one, set .script_string on node");
vehicleTarget = GetEnt(target_targetname, "targetname");
self.shootTarget = vehicleTarget;
self.num_shots = script_int;
self thread ShooterShoot( self.shootTarget, true );
self waittill("Stop shooting");
self ClearAnim(%combat_directions, 0);
self ClearAnim(%exposed_reload, 0);
break;
case "cover_stand":
self thread drone_cover( event );
self waittill( "drone out of cover" );
self SetFlaggedAnimKnob( "cover_exit", %coverstand_trans_OUT_M, 1, .1, 1 );
self waittillmatch( "cover_exit", "end" );
break;
case "cover_crouch":
self thread drone_cover( event );
self waittill( "drone out of cover" );
self SetFlaggedAnimKnob( "cover_exit", %covercrouch_run_out_M, 1, .1, 1 );
self waittillmatch( "cover_exit", "end" );
break;
case "cover_crouch_fire":
self thread drone_cover_fire( event );
self waittill( "drone out of cover" );
self SetFlaggedAnimKnob( "cover_exit", %covercrouch_run_out_M, 1, 0.5, 1 );
self waittillmatch( "cover_exit", "end" );
break;
case "flamedeath":
self thread drone_flameDeath();
break;
case "run_flame":
self SetCanDamage(false);
self drone_set_run_cycle( %ai_flame_death_run );
self.droneRunRate = 100;
self.running = false;
self thread ShooterRun_doRunAnim();
randomAnimRate = undefined;
d = distance( self.origin, destinationPoint );
speed = ( d / self.droneRunRate );
break;
case "run_fast":
self drone_set_run_cycle();
self.running = false;
self thread ShooterRun_doRunAnim();
randomAnimRate = undefined;
d = distance( self.origin, destinationPoint );
speed = ( d / self.droneRunRate );
break;
}
}
minRate = 0.5;
maxRate = 1.5;
randomAnimRate = minRate + RandomFloat( maxRate - minRate );
if( IsDefined( customFirstAnim ) )
{
self.customFirstAnim = true;
self.running = undefined;
randomAnimRate = undefined;
angles = VectorToAngles( destinationPoint - self.origin );
offset = getcycleoriginoffset( angles, customFirstAnim );
endPos = self.origin + offset;
endPos = PhysicsTrace( ( endPos +( 0, 0, 64 ) ), ( endPos -( 0, 0, level.traceHeight ) ) );
t = getanimlength( customFirstAnim );
assert( t > 0 );
self ClearAnim( self.drone_run_cycle, 0 );
self notify( "stop_run_anim" );
self moveto( endPos, t, 0, 0 );
self SetFlaggedAnimKnobRestart( "drone_custom_anim" , customFirstAnim );
self waittillmatch( "drone_custom_anim", "end" );
self.origin = endPos;
self notify( "customFirstAnim done" );
d = distance( self.origin, destinationPoint );
speed = ( d / self.droneRunRate );
}
self.customFirstAnim = undefined;
self thread ShooterRun_doRunAnim( randomAnimRate );
self drone_runto( destinationPoint, speed );
prof_end( "drone_math" );
}
drone_runto( destinationPoint, totalMoveTime )
{
if( totalMoveTime < 0.1 )
{
return;
}
percentIncrement = 0.1;
percentage = 0.0;
incements = ( 1 / percentIncrement );
dividedMoveTime = ( totalMoveTime * percentIncrement );
startingPos = self.origin;
oldZ = startingPos[2];
for( i = 0; i < incements; i++ )
{
prof_begin( "drone_math" );
percentage += percentIncrement;
x = ( destinationPoint[0] - startingPos[0] ) * percentage + startingPos[0];
y = ( destinationPoint[1] - startingPos[1] ) * percentage + startingPos[1];
if( self.lowheight == true )
{
percentageMark = PhysicsTrace( ( x, y, destinationPoint[2] + 64 ), ( x, y, destinationPoint[2] - level.traceHeight ) );
}
else
{
percentageMark = PhysicsTrace( ( x, y, destinationPoint[2] + level.traceHeight ), ( x, y, destinationPoint[2] - level.traceHeight ) );
}
if( ( percentageMark[2] - oldZ ) > level.droneStepHeight )
{
percentageMark = ( percentageMark[0], percentageMark[1], oldZ );
}
oldZ = percentageMark[2];
prof_end( "drone_math" );
self moveTo( percentageMark, dividedMoveTime, 0, 0 );
wait( dividedMoveTime );
}
}
ShooterShoot( target, rpg, one_clip )
{
if( isDefined(rpg) && rpg == true )
{
self thread ShooterShootThreadRPG( target );
}
else
{
self thread ShooterShootThread( target, one_clip );
}
}
#using_animtree( "fakeShooters" );
ShooterShootThreadRPG( target )
{
self endon( "death" );
self UseAnimTree( #animtree );
self.running = undefined;
self thread aimAtTargetThread( target, "Stop shooting" );
shootAnimLength = 0;
tag_flash = self.origin + (0,0,50);
if(!IsDefined(self.num_shots))
{
self.num_shots = 1;
}
for( i = 0; i < self.num_shots; i++ )
{
if( i > 0 )
{
self SetFlaggedAnimKnobAllRestart( "reloadanim", %exposed_reload, %root, 1, 0.4 );
wait( 1 + RandomFloat( 2 ) );
}
self Set3FlaggedAnimKnobs( "no flag", "aim", "stand", 1, 0.3, 1 );
wait( 1 + RandomFloat( 2) );
AssertEX(IsDefined(level.drone_rpg), "No level.drone_rpg specified for drones to shoot with" );
MagicBullet( level.drone_rpg, tag_flash, target.origin, self );
wait( 1 + RandomFloat( 2) );
}
self notify("Stop shooting");
}
ShooterShootThread( target, one_clip )
{
self notify( "Stop shooting" );
if( !isdefined(one_clip) )
{
one_clip = false;
}
if (!IsDefined(self.script_noteworthy))
{
self notify( "drone_shooting" );
}
else if (IsDefined(self.script_noteworthy) && self.script_noteworthy != "run_n_gun_drones")
{
self notify( "drone_shooting" );
}
self endon( "Stop shooting" );
self UseAnimTree( #animtree );
self.running = undefined;
self thread aimAtTargetThread( target, "Stop shooting" );
shootAnimLength = 0;
while( IsDefined( self ) )
{
if( self.bulletsInClip <= 0 )
{
weaponModel = getWeaponModel( self.weapon );
if( IsDefined( self.weaponModel ) )
{
weaponModel = self.weaponModel;
}
numAttached = self getattachsize();
attachName = [];
for( i = 0; i < numAttached; i++ )
{
attachName[i] = self getattachmodelname( i );
}
self SetFlaggedAnimKnobAllRestart( "reloadanim", %exposed_reload, %root, 1, 0.4 );
self.bulletsInClip = randomintrange (4, 8);
self waittillmatch( "reloadanim", "end" );
if( one_clip )
{
self notify( "Stop shooting" );
}
}
self Set3FlaggedAnimKnobs( "no flag", "aim", "stand", 1, 0.3, 1 );
wait( 1 + RandomFloat( 2 ) );
if( !IsDefined( self ) )
{
return;
}
numShots = RandomInt( 4 )+1;
if( numShots > self.bulletsInClip )
{
numShots = self.bulletsInClip;
}
for( i = 0; i < numShots; i++ )
{
if( !IsDefined( self ) )
{
return;
}
self Set3FlaggedAnimKnobsRestart( "shootinganim", "shoot", "stand", 1, 0.05, 1 );
playfxontag( level.drone_muzzleflash, self, "tag_flash" );
if(!IsDefined(level._drones_sounds_disable))
{
if( self.team == "axis" )
{
switch( level.campaign )
{
case "american":
break;
case "russian":
self PlaySound( "wpn_mosin_fire" );
break;
case "british":
self PlaySound( "wpn_mosin_fire" );
break;
}
}
else
{
switch( level.campaign )
{
case "american":
self PlaySound( "wpn_mosin_fire" );
break;
case "russian":
self PlaySound( "wpn_mosin_fire" );
break;
case "british":
self PlaySound( "wpn_mosin_fire" );
break;
}
}
}
self.bulletsInClip--;
if( shootAnimLength == 0 )
{
shootAnimLength = GetTime();
self waittillmatch( "shootinganim", "end" );
shootAnimLength = ( GetTime() - shootAnimLength ) / 1000;
}
else
{
wait( shootAnimLength - 0.1 + RandomFloat( 0.3 ) );
if( !IsDefined( self ) )
{
return;
}
}
}
}
}
ShooterRun_doRunAnim( animRateMod )
{
if( IsDefined( self.running ) && self.running )
{
return;
}
self notify( "stop_shooterrun" );
self endon( "stop_shooterrun" );
self.running = true;
if( !IsDefined( animRateMod ) )
{
animRateMod = 1.0;
}
self endon( "stop_run_anim" );
adjustAnimRate = false;
while( ( IsDefined( self.running ) ) &&( self.running == true ) )
{
animRate = ( self.droneRunRate / self.drone_run_cycle_speed );
if( adjustAnimRate )
{
animRate = ( animRate * animRateMod );
adjustAnimRate = false;
}
self SetFlaggedAnimKnobRestart( "drone_run_anim" , self.drone_run_cycle, 1, .2, animRate );
self waittillmatch( "drone_run_anim", "end" );
if( !IsDefined( self ) )
{
return;
}
}
}
drone_debugLine( fromPoint, toPoint, color, durationFrames )
{
}
turnToFacePoint( point, speed )
{
desiredAngles = VectorToAngles( point - self.origin );
if( !IsDefined( speed ) )
{
speed = 0.5;
}
else if( speed > 0.5 )
{
speed = 0.5;
}
if( speed < 0.1 )
{
return;
}
self rotateTo( ( 0, desiredAngles[1], 0 ), speed, 0, 0 );
}
Set3FlaggedAnimKnobs( animFlag, animArray, pose, weight, blendTime, rate )
{
if( !IsDefined( self ) )
{
return;
}
self setAnimKnob( %combat_directions, weight, blendTime, rate );
self SetFlaggedAnimKnob( animFlag, level.drone_animArray[animArray][pose]["up"], 1, blendTime, 1 );
self SetAnimKnob( level.drone_animArray[animArray][pose]["straight"], 1, blendTime, 1 );
self SetAnimKnob( level.drone_animArray[animArray][pose]["down"], 1, blendTime, 1 );
}
Set3FlaggedAnimKnobsRestart( animFlag, animArray, pose, weight, blendTime, rate )
{
if( !IsDefined( self ) )
{
return;
}
self setAnimKnobRestart( %combat_directions, weight, blendTime, rate );
self SetFlaggedAnimKnobRestart( animFlag, level.drone_animArray[animArray][pose]["up"], 1, blendTime, 1 );
self SetAnimKnobRestart( level.drone_animArray[animArray][pose]["straight"], 1, blendTime, 1 );
self SetAnimKnobRestart( level.drone_animArray[animArray][pose]["down"], 1, blendTime, 1 );
}
applyBlend( offset )
{
if( offset < 0 )
{
unstraightAnim = %combat_down;
self SetAnim( %combat_up, 0.01, 0, 1 );
offset *= -1;
}
else
{
unstraightAnim = %combat_up;
self SetAnim( %combat_down, 0.01, 0, 1 );
}
if( offset > 1 )
{
offset = 1;
}
unstraight = offset;
if( unstraight >= 1.0 )
{
unstraight = 0.99;
}
if( unstraight <= 0 )
{
unstraight = 0.01;
}
straight = 1 - unstraight;
self SetAnim( unstraightAnim, unstraight, 0, 1 );
self SetAnim( %combat_straight, straight, 0, 1 );
}
aimAtTargetThread( target, stopString )
{
self endon( stopString );
while( IsDefined( self ) )
{
targetPos = target.origin;
turnToFacePoint( targetPos );
offset = getTargetUpDownOffset( targetPos );
applyBlend( offset );
wait( 0.05 );
}
}
getTargetUpDownOffset( target )
{
pos = self.origin;
dir = ( target[0] - pos[0], target[1] - pos[1], target[2] - pos[2] );
dir = VectorNormalize( dir );
return dir[2];
}
setAnimArray()
{
level.drone_animArray["aim"] ["stand"]["down"] = %stand_aim_down;
level.drone_animArray["aim"] ["stand"]["straight"] = %stand_aim_straight;
level.drone_animArray["aim"] ["stand"]["up"] = %stand_aim_up;
level.drone_animArray["aim"] ["crouch"]["down"] = %crouch_aim_down;
level.drone_animArray["aim"] ["crouch"]["straight"] = %crouch_aim_straight;
level.drone_animArray["aim"] ["crouch"]["up"] = %crouch_aim_up;
level.drone_animArray["auto"] ["stand"]["down"] = %stand_shoot_auto_down;
level.drone_animArray["auto"] ["stand"]["straight"] = %stand_shoot_auto_straight;
level.drone_animArray["auto"] ["stand"]["up"] = %stand_shoot_auto_up;
level.drone_animArray["auto"] ["crouch"]["down"] = %crouch_shoot_auto_down;
level.drone_animArray["auto"] ["crouch"]["straight"] = %crouch_shoot_auto_straight;
level.drone_animArray["auto"] ["crouch"]["up"] = %crouch_shoot_auto_up;
level.drone_animArray["shoot"] ["stand"]["down"] = %stand_shoot_down;
level.drone_animArray["shoot"] ["stand"]["straight"] = %stand_shoot_straight;
level.drone_animArray["shoot"] ["stand"]["up"] = %stand_shoot_up;
level.drone_animArray["shoot"] ["crouch"]["down"] = %crouch_shoot_down;
level.drone_animArray["shoot"] ["crouch"]["straight"] = %crouch_shoot_straight;
level.drone_animArray["shoot"] ["crouch"]["up"] = %crouch_shoot_up;
}
drone_cover_fire( type )
{
self endon( "drone_stop_cover" );
self endon( "death" );
while( true )
{
drone_cover( type );
self SetAnimKnob( %stand_aim_straight, 1, 0.3, 1 );
wait(0.3);
forwardVec = AnglesToForward( self.angles );
rightVec = AnglesToRight( self.angles );
upVec = anglestoup( self.angles );
relativeOffset = ( 300, 0, 0 );
shootPos = self.origin;
shootPos += vector_scale( forwardVec, relativeOffset[0] );
shootPos += vector_scale( rightVec, relativeOffset[1] );
shootPos += vector_scale( upVec, relativeOffset[2] );
if(isDefined(self.shootTarget))
{
self.shootTarget Delete();
}
self.shootTarget = Spawn( "script_origin", shootPos );
self.bulletsInClip = randomint(4) + 3;
self thread ShooterShoot( self.shootTarget, false, true );
self waittill( "Stop shooting" );
}
}
drone_cover( type )
{
self endon( "drone_stop_cover" );
if( !IsDefined( self.a ) )
{
self.a = SpawnStruct();
}
self.running = undefined;
self.a.array = [];
if( type == "cover_stand" )
{
self.a.array["hide_idle"] = %coverstand_hide_idle;
self.a.array["hide_idle_twitch"] = array(
%coverstand_hide_idle_twitch01,
%coverstand_hide_idle_twitch02,
%coverstand_hide_idle_twitch03,
%coverstand_hide_idle_twitch04,
%coverstand_hide_idle_twitch05
);
self.a.array["hide_idle_flinch"] = array(
%coverstand_react01,
%coverstand_react02,
%coverstand_react03,
%coverstand_react04
);
self SetFlaggedAnimKnobRestart( "cover_approach", %coverstand_trans_IN_M, 1, .3, 1 );
self waittillmatch( "cover_approach", "end" );
self thread drone_cover_think();
}
else if( type == "cover_crouch" )
{
self.a.array["hide_idle"] = %covercrouch_hide_idle;
self.a.array["hide_idle_twitch"] = array(
%covercrouch_twitch_1,
%covercrouch_twitch_2,
%covercrouch_twitch_3,
%covercrouch_twitch_4
);
self SetFlaggedAnimKnobRestart( "cover_approach", %covercrouch_run_in_M, 1, .3, 1 );
self waittillmatch( "cover_approach", "end" );
self thread drone_cover_think();
}
else if( type == "cover_crouch_fire" )
{
self.a.array["hide_idle"] = %covercrouch_hide_idle;
self.a.array["hide_idle_twitch"] = array(
%covercrouch_twitch_1,
%covercrouch_twitch_2,
%covercrouch_twitch_3,
%covercrouch_twitch_4
);
self SetAnimKnob( %covercrouch_hide_idle, 1, 0.4, 1 );
wait(0.4);
self drone_cover_think( 1 + randomint(3) );
}
}
drone_cover_think( max_loops )
{
self endon( "drone_stop_cover" );
if( !isdefined(max_loops) )
{
max_loops = -1;
}
loops = 0;
while( loops < max_loops || max_loops == -1 )
{
useTwitch = ( RandomInt( 2 ) == 0 );
if( useTwitch )
{
idleanim = animArrayPickRandom( "hide_idle_twitch" );
}
else
{
idleanim = animarray( "hide_idle" );
}
self drone_playIdleAnimation( idleAnim, useTwitch );
loops++;
}
}
drone_playIdleAnimation( idleAnim, needsRestart )
{
self endon( "drone_stop_cover" );
if( needsRestart )
{
self SetFlaggedAnimKnobRestart( "idle", idleAnim, 1, .1, 1 );
}
else
{
self SetFlaggedAnimKnob ( "idle", idleAnim, 1, .1, 1 );
}
self.a.coverMode = "Hide";
self waittillmatch( "idle", "end" );
}
drone_get_explosion_death_dir( self_pos, self_angle, explosion_pos, up_distance )
{
if( Distance2D( self_pos, explosion_pos ) < up_distance )
{
return "up";
}
p1 = self_pos - VectorNormalize( AnglesToForward( self_angle ) ) * 10000;
p2 = self_pos + VectorNormalize( AnglesToForward( self_angle ) ) * 10000;
p_intersect = PointOnSegmentNearestToPoint( p1, p2, explosion_pos );
side_away_dist = Distance2D( p_intersect, explosion_pos );
side_close_dist = Distance2D( p_intersect, self_pos );
if( side_close_dist != 0 )
{
angle = ATan( side_away_dist / side_close_dist );
dot_product = vectordot( AnglesToForward( self_angle ), VectorNormalize( explosion_pos - self_pos ) );
if( dot_product < 0 )
{
angle = 180 - angle;
}
if( angle < 45 )
{
return "back";
}
else if( angle > 135 )
{
return "forward";
}
}
self_right_angle = VectorNormalize( AnglesToRight( self_angle ) );
right_point = self_pos + self_right_angle *( up_distance * 0.5 );
if( Distance2D( right_point, explosion_pos ) < Distance2D( self_pos, explosion_pos ) )
{
return "left";
}
else
{
return "right";
}
}
animArray( animname )
{
assert( IsDefined(self.a.array) );
return self.a.array[animname];
}
animArrayAnyExist( animname )
{
assert( IsDefined( self.a.array ) );
return self.a.array[animname].size > 0;
}
animArrayPickRandom( animname )
{
assert( IsDefined( self.a.array ) );
assert( self.a.array[animname].size > 0 );
if ( self.a.array[animname].size > 1 )
{
index = RandomInt( self.a.array[animname].size );
}
else
{
index = 0;
}
return self.a.array[animname][index];
}
#using_animtree( "fakeshooters" );
drone_pick_run_anim()
{
if(IsDefined(level.drone_run_cycle_override))
{
if(IsArray(level.drone_run_cycle_override))
{
return level.drone_run_cycle_override[RandomInt(level.drone_run_cycle_override.size)];
}
else
{
return level.drone_run_cycle_override;
}
}
droneRunAnims = array( %combat_run_fast_3,
%run_n_gun_F,
%ai_viet_run_n_gun_F,
%ai_viet_run_lowready_f,
%ch_khe_E1B_troopssprint_1,
%ch_khe_E1B_troopssprint_2,
%ch_khe_E1B_troopssprint_3,
%ch_khe_E1B_troopssprint_4,
%ch_khe_E1B_troopssprint_5,
%ch_khe_E1B_troopssprint_6,
%ch_khe_E1B_troopssprint_7 );
index = RandomInt( droneRunAnims.size );
return droneRunAnims[index];
}
drone_set_run_cycle( runAnim )
{
if( !IsDefined(runAnim) )
{
runAnim = drone_pick_run_anim();
}
self.drone_run_cycle = runAnim;
self.drone_run_cycle_speed = drone_run_anim_speed( runAnim );
self.droneRunRate = self.drone_run_cycle_speed;
}
drone_run_anim_speed( runAnim )
{
run_cycle_delta = GetMoveDelta( runAnim, 0, 1 );
run_cycle_dist = Length( run_cycle_delta );
run_cycle_length = GetAnimLength( runAnim );
run_cycle_speed = run_cycle_dist / run_cycle_length;
return run_cycle_speed;
}