1 #using scripts\shared\challenges_shared;
2 #using scripts\shared\clientfield_shared;
3 #using scripts\shared\damagefeedback_shared;
4 #using scripts\shared\hostmigration_shared;
5 #using scripts\shared\killstreaks_shared;
6 #using scripts\shared\math_shared;
7 #using scripts\shared\scoreevents_shared;
8 #using scripts\shared\tweakables_shared;
9 #using scripts\shared\util_shared;
10 #using scripts\shared\weapons\_weaponobjects;
11 #using scripts\shared\weapons\_heatseekingmissile;
13 #using scripts\mp\_challenges;
14 #using scripts\mp\_util;
15 #using scripts\mp\gametypes\_globallogic_audio;
16 #using scripts\mp\gametypes\_globallogic_player;
17 #using scripts\mp\gametypes\_hostmigration;
18 #using scripts\mp\gametypes\_spawning;
19 #using scripts\mp\killstreaks\_airsupport;
20 #using scripts\mp\killstreaks\_dogs;
21 #using scripts\mp\killstreaks\_flak_drone;
22 #using scripts\mp\killstreaks\_killstreak_bundles;
23 #using scripts\mp\killstreaks\_killstreak_detect;
24 #using scripts\mp\killstreaks\_killstreak_hacking;
25 #using scripts\mp\killstreaks\_killstreakrules;
26 #using scripts\mp\killstreaks\_killstreaks;
28 #insert scripts\mp\_hacker_tool.gsh;
29 #insert scripts\mp\killstreaks\_killstreaks.gsh;
30 #insert scripts\shared\shared.gsh;
31 #insert scripts\shared\version.gsh;
33 #using_animtree ( "mp_vehicles" );
35 #namespace helicopter;
37 #precache( "locationselector", "compass_objpoint_helicopter" );
38 #precache( "string", "MP_DESTROYED_HELICOPTER");
39 #precache( "string", "KILLSTREAK_DESTROYED_HELICOPTER_GUNNER");
40 #precache( "string", "KILLSTREAK_EARNED_HELICOPTER_COMLINK" );
41 #precache( "string", "KILLSTREAK_HELICOPTER_COMLINK_NOT_AVAILABLE" );
42 #precache( "string", "KILLSTREAK_HELICOPTER_COMLINK_INBOUND" );
43 #precache( "string", "KILLSTREAK_HELICOPTER_COMLINK_HACKED" );
44 #precache( "string", "KILLSTREAK_DESTROYED_SUPPLY_DROP_DEPLOY_SHIP" );
45 #precache( "string", "mpl_killstreak_heli" );
46 #precache( "fx", "killstreaks/fx_heli_exp_lg" );
47 #precache( "fx", "killstreaks/fx_heli_exp_md" );
48 #precache( "fx", "killstreaks/fx_vtol_exp" );
49 #precache( "fx", "killstreaks/fx_heli_exp_sm" );
50 #precache( "fx", "killstreaks/fx_heli_smk_trail_engine_33" );
51 #precache( "fx", "killstreaks/fx_heli_smk_trail_engine_66" );
52 #precache( "fx", "killstreaks/fx_heli_smk_trail_tail" );
53 #precache( "fx", "killstreaks/fx_heli_smk_trail_engine" );
54 #precache( "fx", "killstreaks/fx_sc_lights_grn" );
55 #precache( "fx", "killstreaks/fx_sc_lights_red" );
57 #define HELI_ENTRANCE_Z_HELP 1000
58 #define HELICOPTER_COMLINK "helicopter_comlink"
59 #define INVENTORY_HELICOPTER_COMLINK "inventory_helicopter_comlink"
66 level.vehicle_deathmodel[model] = model;
73 level.heli_sound[
"hit"] =
"evt_helicopter_hit";
74 level.heli_sound[
"hitsecondary"] =
"evt_helicopter_hit";
75 level.heli_sound[
"damaged"] =
"null";
76 level.heli_sound[
"spinloop"] =
"evt_helicopter_spin_loop";
77 level.heli_sound[
"spinstart"] =
"evt_helicopter_spin_start";
78 level.heli_sound[
"crash"] =
"evt_helicopter_midair_exp";
79 level.heli_sound[
"missilefire"] =
"wpn_hellfire_fire_npc";
87 if ( (!isdefined( level.heli_paths ) || !level.heli_paths.size) )
89 /#iprintlnbold(
"Need to add helicopter paths to the level");#/
93 if ( ( hardpointType ==
"helicopter_comlink" ) || ( hardpointType ==
"inventory_helicopter_comlink" ) )
101 missilesEnabled =
false;
102 if ( hardpointType ==
"helicopter_x2" )
104 missilesEnabled =
true;
107 assert( level.heli_paths.size > 0,
"No non-primary helicopter paths found in map" );
109 random_path = randomint( level.heli_paths[destination].size );
111 startnode = level.heli_paths[destination][random_path];
113 protectLocation = undefined;
115 if ( ( hardpointType ==
"helicopter_comlink" ) || ( hardpointType ==
"inventory_helicopter_comlink" ) )
124 if ( killstreak_id == -1 )
127 if ( ( hardpointType ==
"helicopter_comlink" ) || ( hardpointType ==
"inventory_helicopter_comlink" ) )
135 thread
heli_think(
self, startnode,
self.team, missilesEnabled, protectLocation, hardpointType, armored, killstreak_id );
151 path_start = getentarray(
"heli_start",
"targetname" );
152 path_dest = getentarray(
"heli_dest",
"targetname" );
153 loop_start = getentarray(
"heli_loop_start",
"targetname" );
154 gunner_loop_start = getentarray(
"heli_gunner_loop_start",
"targetname" );
155 leave_nodes = getentarray(
"heli_leave",
"targetname" );
156 crash_start = getentarray(
"heli_crash_start",
"targetname" );
158 assert( ( isdefined( path_start ) && isdefined( path_dest ) ),
"Missing path_start or path_dest" );
161 for (i=0; i<path_dest.size; i++)
163 startnode_array = [];
164 isPrimaryDest =
false;
167 destnode_pointer = path_dest[i];
168 destnode = getent( destnode_pointer.target,
"targetname" );
171 for ( j=0; j<path_start.size; j++ )
174 currentnode = path_start[j];
176 while( isdefined( currentnode.target ) )
178 nextnode = getent( currentnode.target,
"targetname" );
179 if ( nextnode.origin == destnode.origin )
185 currentnode = nextnode;
189 startnode_array[startnode_array.size] = getent( path_start[j].target,
"targetname" );
190 if ( isdefined( path_start[j].script_noteworthy ) && ( path_start[j].script_noteworthy ==
"primary" ) )
191 isPrimaryDest =
true;
194 assert( ( isdefined( startnode_array ) && startnode_array.size > 0 ),
"No path(s) to destination" );
198 level.heli_primary_path = startnode_array;
200 level.heli_paths[level.heli_paths.size] = startnode_array;
204 for (i=0; i<loop_start.size; i++)
206 startnode = getent( loop_start[i].target,
"targetname" );
207 level.heli_loop_paths[level.heli_loop_paths.size] = startnode;
209 assert( isdefined( level.heli_loop_paths[0] ),
"No helicopter loop paths found in map" );
212 for ( i = 0 ; i < gunner_loop_start.size ; i++ )
214 startnode = getent( gunner_loop_start[i].target,
"targetname" );
215 startnode.isGunnerPath =
true;
216 level.heli_loop_paths[level.heli_loop_paths.size] = startnode;
220 for (i=0; i<path_start.size; i++)
223 if ( isdefined( path_start[ i ].script_noteworthy ) && ( path_start[ i ].script_noteworthy ==
"primary" ) )
226 level.heli_startnodes[level.heli_startnodes.size] = path_start[i];
228 assert( isdefined( level.heli_startnodes[0] ),
"No helicopter start nodes found in map" );
231 for (i=0; i<leave_nodes.size; i++)
232 level.heli_leavenodes[level.heli_leavenodes.size] = leave_nodes[i];
233 assert( isdefined( level.heli_leavenodes[0] ),
"No helicopter leave nodes found in map" );
236 for (i=0; i<crash_start.size; i++)
238 crash_start_node = getent( crash_start[i].target,
"targetname" );
239 level.heli_crash_paths[level.heli_crash_paths.size] = crash_start_node;
241 assert( isdefined( level.heli_crash_paths[0] ),
"No helicopter crash paths found in map" );
246 path_start = getentarray(
"heli_start",
"targetname" );
247 loop_start = getentarray(
"heli_loop_start",
"targetname" );
250 level.chaff_offset[
"attack"] = ( -130, 0, -140 );
252 level.chopperComlinkFriendly =
"veh_t7_drone_hunter";
253 level.chopperComlinkEnemy =
"veh_t7_drone_hunter";
254 level.chopperRegular =
"veh_t7_drone_hunter";
277 level.heli_paths = [];
278 level.heli_loop_paths = [];
279 level.heli_startnodes = [];
280 level.heli_leavenodes = [];
281 level.heli_crash_paths = [];
283 level.last_start_node_index = 0;
286 level.chopper_fx[
"explode"][
"death"] =
"killstreaks/fx_heli_exp_lg";
287 level.chopper_fx[
"explode"][
"guard"] =
"killstreaks/fx_heli_exp_md";
288 level.chopper_fx[
"explode"][
"gunner"] =
"killstreaks/fx_vtol_exp";
289 level.chopper_fx[
"explode"][
"large"] =
"killstreaks/fx_heli_exp_sm";
290 level.chopper_fx[
"damage"][
"light_smoke"] =
"killstreaks/fx_heli_smk_trail_engine_33";
291 level.chopper_fx[
"damage"][
"heavy_smoke"] =
"killstreaks/fx_heli_smk_trail_engine_66";
292 level.chopper_fx[
"smoke"][
"trail"] =
"killstreaks/fx_heli_smk_trail_tail";
293 level.chopper_fx[
"fire"][
"trail"][
"large"] =
"killstreaks/fx_heli_smk_trail_engine";
295 level._effect[
"heli_comlink_light"][
"friendly"] =
"_debug/fx_debug_deleted_fx";
296 level._effect[
"heli_comlink_light"][
"enemy"] =
"_debug/fx_debug_deleted_fx";
298 level.heliComlinkBootupAnim = %veh_anim_future_heli_gearup_bay_open;
301 killstreaks::register_strings(
"helicopter_comlink", &
"KILLSTREAK_EARNED_HELICOPTER_COMLINK", &
"KILLSTREAK_HELICOPTER_COMLINK_NOT_AVAILABLE", &
"KILLSTREAK_HELICOPTER_COMLINK_INBOUND", undefined, &
"KILLSTREAK_HELICOPTER_COMLINK_HACKED" );
302 killstreaks::register_dialog(
"helicopter_comlink",
"mpl_killstreak_heli",
"helicopterDialogBundle",
"helicopterPilotDialogBundle",
"friendlyHelicopter",
"enemyHelicopter",
"enemyHelicopterMultiple",
"friendlyHelicopterHacked",
"enemyHelicopterHacked",
"requestHelicopter",
"threatHelicopter" );
307 level.killstreaks[
"helicopter_comlink"].threatOnKill =
true;
308 level.killstreaks[
"inventory_helicopter_comlink"].threatOnKill =
true;
310 if ( !path_start.size && !loop_start.size)
324 if ( GetDvarString( dvar ) !=
"" )
325 return getdvarfloat( dvar );
328 SetDvar( dvar, def );
335 self.heliGoalPos = goalpos;
336 self setvehgoalpos( goalPos,
stop );
339 function spawn_helicopter( owner, origin, angles, model, targetname, target_offset, hardpointType, killstreak_id )
341 chopper = spawnHelicopter( owner, origin, angles, model, targetname );
342 chopper.owner = owner;
344 chopper.attackers = [];
345 chopper.attackerData = [];
346 chopper.attackerDamage = [];
347 chopper.flareAttackerDamage = [];
349 chopper.hardpointType = hardpointType;
350 chopper.killstreak_id = killstreak_id;
351 chopper.pilotIsTalking =
false;
352 chopper SetDrawInfrared(
true );
353 chopper.allowContinuedLockonAfterInvis =
true;
354 chopper.soundmod =
"heli";
356 if ( !isdefined( target_offset ) )
357 target_offset = (0,0,0);
359 chopper.target_offset = target_offset;
361 Target_Set(chopper, target_offset);
363 if( ( hardpointtype ==
"helicopter_comlink" ) || ( hardpointtype ==
"inventory_helicopter_comlink" ) )
365 chopper.allowHackingAfterCloak =
true;
367 chopper.treat_owner_damage_as_friendly_fire =
true;
368 chopper.ignore_team_kills =
true;
379 if ( !isdefined( chopper ) )
383 chopper.numFlares = 0;
391 self endon (
"death" );
395 self waittill(
"touch");
402 startnode = level.heli_paths[destination][random_path];
403 path_index = ( random_path + 1 ) % level.heli_paths[destination].size;
406 if( isdefined(inNoFly))
408 protectLocation = (protectLocation[0], protectLocation[1], level.noFlyZones[inNoFly].origin[2] + level.noFlyZones[inNoFly].height);
412 while ( isdefined(noFlyZone) && path_index != random_path )
414 startnode = level.heli_paths[destination][path_index];
416 if( isDefined(noFlyZone) )
418 path_index = ( path_index + 1 ) % level.heli_paths[destination].size;
423 return level.heli_paths[destination][path_index];
428 if(
self === level.vtol )
430 foreach( node
in level.heli_leavenodes )
432 if ( isdefined( node.script_noteworthy ) && ( node.script_noteworthy ==
"primary" ) )
437 random_leave_node = randomInt( level.heli_leavenodes.size );
438 leavenode = level.heli_leavenodes[random_leave_node];
439 path_index = ( random_leave_node + 1 ) % level.heli_leavenodes.size;
441 isPrimary = ( leavenode.script_noteworthy ===
"primary" );
443 while( ( isdefined( noFlyZone ) || isPrimary ) && ( path_index != random_leave_node ) )
445 leavenode = level.heli_leavenodes[path_index];
447 isPrimary = ( leavenode.script_noteworthy ===
"primary" );
448 path_index = ( path_index + 1 ) % level.heli_leavenodes.size;
452 return level.heli_leavenodes[path_index];
457 path_index = randomInt( level.heli_startnodes.size );
458 best_index = path_index;
461 for( i = 0; i < level.heli_startnodes.size; i++ )
463 startnode = level.heli_startnodes[path_index];
466 if( !isdefined( noFlyZone ) )
468 best_index = path_index;
469 if( path_index != level.last_start_node_index )
472 path_index = ( path_index + 1 ) % level.heli_startnodes.size;
475 level.last_start_node_index = best_index;
476 return level.heli_startnodes[best_index];
481 random_leave_node = randomInt( level.heli_crash_paths.size );
482 leavenode = level.heli_crash_paths[random_leave_node];
483 path_index = ( random_leave_node + 1 ) % level.heli_crash_paths.size;
486 while ( isdefined(noFlyZone) && path_index != random_leave_node )
488 leavenode = level.heli_crash_paths[path_index];
490 path_index = ( path_index + 1 ) % level.heli_crash_paths.size;
494 return level.heli_crash_paths[path_index];
506 if ( isdefined ( heli.flak_drone ) )
508 heli.flak_drone flak_drone::configureteam( heli,
true );
511 heli.killstreakEndTime = int( heli.endTime );
516 function heli_think( owner, startnode, heli_team, missilesEnabled, protectLocation, hardpointType, armored, killstreak_id )
518 heliOrigin = startnode.origin;
519 heliAngles = startnode.angles;
521 if ( ( hardpointType ==
"helicopter_comlink" ) || ( hardpointType ==
"inventory_helicopter_comlink" ) )
523 chopperModelFriendly = level.chopperComlinkFriendly;
524 chopperModelEnemy = level.chopperComlinkEnemy;
528 chopperModelFriendly = level.chopperRegular;
529 chopperModelEnemy = level.chopperRegular;
532 chopper =
spawn_helicopter( owner, heliOrigin, heliAngles,
"heli_ai_mp", chopperModelFriendly, (0,0,100), hardpointType, killstreak_id );
533 chopper.harpointType = hardpointType;
542 chopper setEnemyModel(chopperModelEnemy);
547 Target_SetTurretAquire( chopper,
false );
550 if ( ( hardpointType ==
"helicopter_comlink" ) || ( hardpointType ==
"inventory_helicopter_comlink" ) )
551 chopper.defaultWeapon = GetWeapon(
"cobra_20mm_comlink" );
553 chopper.defaultWeapon = GetWeapon(
"cobra_20mm" );
555 chopper.requiredDeathCount = owner.deathCount;
556 chopper.chaff_offset = level.chaff_offset[
"attack"];
558 minigun_snd_ent =
spawn(
"script_origin", chopper GetTagOrigin(
"tag_flash" ) );
559 minigun_snd_ent LinkTo( chopper,
"tag_flash", (0,0,0), (0,0,0) );
560 chopper.minigun_snd_ent = minigun_snd_ent;
565 level.chopper = chopper;
569 chopper.reached_dest =
false;
571 chopper.maxhealth = level.heli_amored_maxhealth;
573 chopper.maxhealth = level.heli_maxhealth;
575 chopper.rocketDamageOneShot = level.heli_maxhealth + 1;
576 chopper.rocketDamageTwoShot = (level.heli_maxhealth / 2) + 1;
578 if ( ( hardpointType ==
"helicopter_comlink" ) || ( hardpointType ==
"inventory_helicopter_comlink" ) )
580 chopper.numFlares = 0;
582 else if( hardpointType ==
"helicopter_guard")
584 chopper.numFlares = 1;
588 chopper.numFlares = 2;
591 chopper.flareOffset = (0,0,-256);
592 chopper.waittime = level.heli_dest_wait;
593 chopper.loopcount = 0;
594 chopper.evasive =
false;
595 chopper.health_bulletdamageble = level.heli_armor;
596 chopper.health_evasive = level.heli_armor;
597 chopper.targeting_delay = level.heli_targeting_delay;
598 chopper.primaryTarget = undefined;
599 chopper.secondaryTarget = undefined;
600 chopper.attacker = undefined;
601 chopper.missile_ammo = level.heli_missile_max;
602 chopper.currentstate =
"ok";
603 chopper.lastRocketFireTime = -1;
606 if ( isdefined(protectLocation) )
608 chopper thread
heli_protect( startNode, protectLocation, hardpointType, heli_team );
613 chopper thread
heli_fly( startnode, 2.0, hardpointType );
623 if( hardpointtype !=
"helicopter_comlink" )
632 self endon(
"death" );
633 level waittill(
"game_ended" );
635 self StopLoopSound();
640 self waittill(
"leaving" );
647 self.flare_ent =
spawn(
"script_model",
self GetTagOrigin(
"tag_origin") );
648 self.flare_ent SetModel(
"tag_origin" );
649 self.flare_ent LinkTo(
self,
"tag_origin", offset );
654 self endon(
"death" );
655 self endon(
"crashing" );
656 self endon(
"leaving" );
660 if(
self.missile_ammo >= level.heli_missile_max )
661 self waittill(
"missile fired" );
665 if (
self.currentstate ==
"heavy smoke" )
666 wait( level.heli_missile_regen_time/4 );
667 else if (
self.currentstate ==
"light smoke" )
668 wait( level.heli_missile_regen_time/2 );
670 wait( level.heli_missile_regen_time );
672 if(
self.missile_ammo < level.heli_missile_max )
680 self endon(
"death" );
681 self endon(
"crashing" );
682 self endon(
"leaving" );
691 players = level.players;
692 for (i = 0; i < players.size; i++)
698 if( isdefined( player ) )
699 targets[targets.size] = player;
703 if( isdefined( player ) )
704 targetsMissile[targetsMissile.size] = player;
712 foreach( dog
in dogs )
716 targets[targets.size] = dog;
720 targetsMissile[targetsMissile.size] = dog;
724 tanks = GetEntArray(
"talon",
"targetname" );
725 tanks = ArrayCombine( tanks, GetEntArray(
"siegebot",
"targetname" ),
false,
false );
727 foreach( tank
in tanks )
731 targets[targets.size] = tank;
735 actors = GetActorArray();
736 foreach( actor
in actors )
738 if( isdefined( actor ) && isdefined( actor.isAiClone ) && IsAlive( actor ) )
742 targets[targets.size] = actor;
748 if ( targets.size == 0 && targetsMissile.size == 0 )
750 self.primaryTarget = undefined;
751 self.secondaryTarget = undefined;
752 self SetGoalYaw(RandomInt(360));
753 wait (
self.targeting_delay );
757 if( targets.size == 1 )
759 if( isdefined( targets[0].isAiClone ) )
763 else if( isdefined( targets[0].type ) && (targets[0].type ==
"dog" || targets[0].type ==
"tank_drone"))
767 else if ( isdefined( targets[0].killstreakType ) )
776 self.primaryTarget = targets[0];
777 self notify(
"primary acquired" );
778 self.secondaryTarget = undefined;
780 else if ( targets.size > 1 )
783 if( targetsMissile.size == 1 )
785 if( !isdefined( targetsMissile[0].type ) || targetsMissile[0].type !=
"dog" || targets[0].type ==
"tank_drone")
789 else if( targetsMissile[0].type ==
"dog" )
794 self.secondaryTarget = targetsMissile[0];
795 self notify(
"secondary acquired" );
797 else if( targetsMissile.size > 1 )
800 wait (
self.targeting_delay );
810 if ( !isalive( player ) || player.sessionstate !=
"playing" )
813 if ( player.ignoreme ===
true )
816 if ( player ==
self.owner )
825 if ( distance( player.origin,
self.origin ) > level.heli_visual_range )
828 if ( !isdefined( player.team ) )
831 if ( level.teamBased && player.team ==
self.team )
834 if ( player.team ==
"spectator" )
837 if ( isdefined( player.spawntime ) && ( gettime() - player.spawntime )/1000 <= level.heli_target_spawnprotection )
840 heli_centroid =
self.origin + ( 0, 0, -160 );
841 heli_forward_norm = anglestoforward(
self.angles );
842 heli_turret_point = heli_centroid + 144*heli_forward_norm;
844 visible_amount = player sightConeTrace( heli_turret_point,
self);
846 if ( visible_amount < level.heli_target_recognition )
858 if( !isalive( actor ) )
861 if( !isdefined( actor.team ) )
864 if( level.teamBased && actor.team == helicopter.team )
867 if( DistanceSquared( actor.origin, helicopter.origin ) > ( level.heli_visual_range * level.heli_visual_range ) )
870 heli_centroid = helicopter.origin + ( 0, 0, -160 );
871 heli_forward_norm = anglestoforward( helicopter.angles );
872 heli_turret_point = heli_centroid + 144 * heli_forward_norm;
874 visible_amount = actor sightConeTrace( heli_turret_point, helicopter );
875 if( visible_amount < level.heli_target_recognition )
883 vector = endOrigin - startOrigin;
885 opposite = startOrigin[2] - endOrigin[2];
889 adjacent = distance2d( startOrigin, endOrigin );
894 if ( adjacent < 0.01 )
897 tangent = opposite / adjacent;
909 if ( !isalive( player ) || player.sessionstate !=
"playing" )
912 if ( player.ignoreme ===
true )
915 if ( player ==
self.owner )
924 if ( distance( player.origin,
self.origin ) > level.heli_missile_range )
927 if ( !isdefined( player.team ) )
930 if ( level.teamBased && player.team ==
self.team )
933 if ( player.team ==
"spectator" )
936 if ( isdefined( player.spawntime ) && ( gettime() - player.spawntime )/1000 <= level.heli_target_spawnprotection )
942 heli_centroid =
self.origin + ( 0, 0, -160 );
943 heli_forward_norm = anglestoforward(
self.angles );
944 heli_turret_point = heli_centroid + 144*heli_forward_norm;
946 if (!isdefined(player.lastHit))
949 player.lastHit =
self HeliTurretSightTrace( heli_turret_point, player, player.lastHit );
950 if (player.lastHit != 0)
961 if ( !isdefined( dog ) )
964 if ( distance( dog.origin,
self.origin ) > level.heli_visual_range )
967 if ( !isdefined( dog.team ) )
970 if ( level.teamBased && (dog.team ==
self.team) )
973 if ( isdefined(dog.script_owner) &&
self.owner == dog.script_owner )
976 heli_centroid =
self.origin + ( 0, 0, -160 );
977 heli_forward_norm = anglestoforward(
self.angles );
978 heli_turret_point = heli_centroid + 144*heli_forward_norm;
980 if (!isdefined(dog.lastHit))
983 dog.lastHit =
self HeliTurretDogTrace( heli_turret_point, dog, dog.lastHit );
984 if ( dog.lastHit != 0 )
995 if ( !isdefined( dog ) )
998 if ( distance( dog.origin,
self.origin ) > level.heli_missile_range )
1001 if ( !isdefined( dog.team ) )
1004 if ( level.teamBased && (dog.team ==
self.team) )
1007 if ( isdefined(dog.script_owner) &&
self.owner == dog.script_owner )
1013 heli_centroid =
self.origin + ( 0, 0, -160 );
1014 heli_forward_norm = anglestoforward(
self.angles );
1015 heli_turret_point = heli_centroid + 144*heli_forward_norm;
1017 if (!isdefined(dog.lastHit))
1020 dog.lastHit =
self HeliTurretDogTrace( heli_turret_point, dog, dog.lastHit );
1021 if (dog.lastHit != 0)
1033 if ( !isdefined( tank ) )
1036 if ( tank.ignoreme ===
true )
1039 if ( distance( tank.origin,
self.origin ) > level.heli_visual_range )
1042 if ( !isdefined( tank.team ) )
1045 if ( level.teamBased && (tank.team ==
self.team) )
1048 if ( isdefined(tank.owner) &&
self.owner == tank.owner )
1057 for( idx=0; idx<targets.size; idx++ )
1059 if( isdefined( targets[idx].isAiClone ) )
1063 else if ( isdefined( targets[idx].type ) && targets[idx].type ==
"dog" )
1067 else if ( IsPlayer( targets[idx] ) )
1077 assert( targets.size >= 2,
"Not enough targets to assign primary and secondary" );
1082 primaryTarget = undefined;
1085 for( idx=0; idx<targets.size; idx++ )
1087 assert( isdefined( targets[idx].threatlevel ),
"Target player does not have threat level" );
1088 if( targets[idx].threatlevel >= highest )
1090 highest = targets[idx].threatlevel;
1091 primaryTarget = targets[idx];
1095 assert( isdefined( primaryTarget ),
"Targets exist, but none was assigned as primary" );
1096 self.primaryTarget = primaryTarget;
1097 self notify(
"primary acquired" );
1103 for( idx = 0; idx < targets.size; idx++ )
1105 if( !isdefined( targets[idx].type ) || targets[idx].type !=
"dog" )
1109 else if( targets[idx].type ==
"dog" || targets[0].type ==
"tank_drone")
1115 assert( targets.size >= 2,
"Not enough targets to assign primary and secondary" );
1120 primaryTarget = undefined;
1121 secondaryTarget = undefined;
1124 for( idx=0; idx<targets.size; idx++ )
1126 assert( isdefined( targets[idx].missilethreatlevel ),
"Target player does not have threat level" );
1127 if( targets[idx].missilethreatlevel >= highest )
1129 highest = targets[idx].missilethreatlevel;
1130 secondaryTarget = targets[idx];
1134 assert( isdefined( secondaryTarget ),
"1+ targets exist, but none was assigned as secondary" );
1135 self.secondaryTarget = secondaryTarget;
1136 self notify(
"secondary acquired" );
1146 self clearTargetYaw();
1147 self clearGoalYaw();
1148 self setspeed( 60, 25 );
1149 self setyawspeed( 75, 45, 45 );
1151 self setmaxpitchroll( 30, 30 );
1152 self setneargoalnotifydist( 256 );
1153 self setturningability(0.9);
1158 self endon (
"death" );
1159 self endon (
"crashing" );
1160 self endon (
"evasive" );
1166 self notify(
"stop hover" );
1173 self endon(
"death" );
1174 self endon(
"stop hover" );
1175 self endon(
"evasive" );
1176 self endon(
"leaving" );
1177 self endon(
"crashing" );
1178 randInt = randomint(360);
1179 self setgoalyaw(
self.angles[1]+randInt );
1185 self endon(
"death" );
1186 self endon(
"crashing" );
1187 self endon(
"leaving" );
1193 self waittill(
"killed", victim );
1195 if ( !isdefined(
self.owner ) || !isdefined( victim ) )
1198 if (
self.owner == victim )
1202 if ( level.teamBased &&
self.owner.team == victim.team )
1211 self endon(
"killed" );
1215 if ( !isdefined(
self ) )
1225 bdaDialog =
"kill1";
1227 else if (
self.bda == 2)
1229 bdaDialog =
"kill2";
1231 else if (
self.bda == 3)
1233 bdaDialog =
"kill3";
1235 else if (
self.bda > 3)
1237 bdaDialog =
"killMultiple";
1242 self notify(
"bda_dialog", bdaDialog );
1250 hackedDamageTaken = helicopter.maxhealth - helicopter.hackedHealth;
1251 assert ( hackedDamageTaken > 0 );
1252 if ( hackedDamageTaken > helicopter.damageTaken )
1254 helicopter.damageTaken = hackedDamageTaken;
1261 self endon(
"death" );
1262 self endon(
"crashing" );
1264 self.damageTaken = 0;
1267 hit_vo_spacing = 6000;
1270 if ( isdefined( tableHealth ) )
1272 self.maxhealth = tableHealth;
1278 if ( !isdefined(
self.attackerData ) )
1280 self.attackers = [];
1281 self.attackerData = [];
1282 self.attackerDamage = [];
1283 self.flareAttackerDamage = [];
1289 self waittill(
"damage",
damage, attacker, direction, point, type, modelName, tagName, partname, weapon, flags, inflictor, chargeLevel );
1291 if( !isdefined( attacker ) || !isplayer( attacker ) )
1296 if( !heli_friendlyfire )
1299 if ( !level.hardcoreMode )
1301 if( isdefined(
self.owner ) && attacker ==
self.owner )
1304 if ( level.teamBased )
1305 isValidAttacker = (isdefined( attacker.team ) && attacker.team !=
self.team);
1307 isValidAttacker =
true;
1309 if ( !isValidAttacker )
1313 self.attacker = attacker;
1317 if ( !isdefined( weapon_damage ) )
1319 if ( type ==
"MOD_RIFLE_BULLET" || type ==
"MOD_PISTOL_BULLET" )
1321 hasFMJ = attacker HasPerk(
"specialty_armorpiercing" );
1328 damage *= level.heli_armor_bulletdamage;
1330 else if( type ==
"MOD_PROJECTILE" || type ==
"MOD_PROJECTILE_SPLASH" || type ==
"MOD_EXPLOSIVE" )
1332 shouldUpdateDamage = ( ( weapon.statIndex != level.weaponPistolEnergy.statIndex )
1333 && ( weapon.statIndex != level.weaponSpecialCrossbow.statIndex )
1334 && ( weapon.statIndex != level.weaponSmgNailGun.statIndex ) );
1336 if ( shouldUpdateDamage )
1338 switch ( weapon.name )
1341 if( isdefined(
self.rocketDamageTwoShot ) )
1344 damage =
self.rocketDamageTwoShot;
1346 else if( isdefined(
self.rocketDamageOneShot ) )
1349 damage =
self.rocketDamageOneShot;
1353 if( isdefined(
self.rocketDamageOneShot ) )
1356 damage =
self.rocketDamageOneShot;
1366 if ( weapon_damage > 0 )
1369 self.damageTaken += weapon_damage;
1371 playerControlled =
false;
1373 if(
self.damageTaken >
self.maxhealth && !isdefined(
self.xpGiven) )
1375 self.xpGiven =
true;
1377 switch( hardpointtype )
1379 case "helicopter_gunner":
1380 playerControlled =
true;
1381 event =
"destroyed_vtol_mothership";
1383 case "helicopter_comlink":
1384 case "inventory_helicopter_comlink":
1385 event =
"destroyed_helicopter_comlink";
1386 if (
self.leaving !==
true )
1392 case "supply_drop_combat_robot":
1393 if( isdefined( helicopter.killstreakWeaponName ) )
1395 switch( helicopter.killstreakWeaponName )
1397 case "inventory_ai_tank_drop":
1398 case "ai_tank_drop":
1399 case "inventory_ai_tank_marker":
1400 case "ai_tank_drop_marker":
1401 case "ai_tank_marker":
1403 event =
"destroyed_helicopter_agr_drop";
1406 case "combat_robot_drop":
1407 case "inventory_combat_robot_drop":
1408 case "combat_robot_marker":
1409 case "inventory_combat_robot_marker":
1411 event =
"destroyed_helicopter_giunit_drop";
1416 event =
"destroyed_helicopter_supply_drop";
1423 event =
"destroyed_helicopter_supply_drop";
1428 if ( isdefined( event ) )
1436 if ( playerControlled ==
true )
1440 if ( hardpointtype ==
"helicopter_player_gunner" )
1442 attacker AddWeaponStat( weapon,
"destroyed_controlled_killstreak", 1 );
1456 weaponStatName =
"destroyed";
1457 switch( weapon.name )
1462 case "tow_turret_drop":
1463 weaponStatName =
"kills";
1466 attacker AddWeaponStat( weapon, weaponStatName, 1 );
1468 notifyString = undefined;
1469 killstreakReference = undefined;
1470 switch( hardpointtype )
1472 case "helicopter_gunner":
1473 killstreakReference =
"killstreak_helicopter_gunner";
1475 case "helicopter_player_gunner":
1476 killstreakReference =
"killstreak_helicopter_player_gunner";
1478 case "helicopter_player_firstperson":
1479 killstreakReference =
"killstreak_helicopter_player_firstperson";
1481 case "helicopter_comlink":
1482 case "inventory_helicopter_comlink":
1484 case "helicopter_x2":
1485 notifyString = &
"KILLSTREAK_DESTROYED_HELICOPTER";
1486 killstreakReference =
"killstreak_helicopter_comlink";
1489 notifyString = &
"KILLSTREAK_DESTROYED_SUPPLY_DROP_DEPLOY_SHIP";
1490 killstreakReference =
"killstreak_supply_drop";
1492 case "helicopter_guard":
1493 killstreakReference =
"killstreak_helicopter_guard";
1497 if( isdefined( killstreakReference ) )
1499 level.globalKillstreaksDestroyed++;
1500 attacker AddWeaponStat( GetWeapon( hardpointtype ),
"destroyed", 1 );
1503 if( hardpointtype ==
"helicopter_player_gunner" )
1505 self.owner SendKillstreakDamageEvent( 600 );
1508 if ( isdefined( notifyString ) )
1510 LUINotifyEvent( &
"player_callout", 2, notifyString, attacker.entnum );
1513 if ( isdefined(
self.attackers ) )
1515 for ( j = 0; j <
self.attackers.size; j++ )
1517 player =
self.attackers[j];
1519 if ( !isdefined( player ) )
1522 if ( player == attacker )
1525 flare_done =
self.flareAttackerDamage[player.clientId];
1526 if ( isdefined ( flare_done ) && flare_done ==
true )
1532 damage_done =
self.attackerDamage[player.clientId];
1536 self.attackers = [];
1538 attacker notify(
"destroyed_helicopter" );
1540 if( Target_IsTarget(
self ) )
1542 Target_remove(
self );
1545 else if ( isdefined(
self.owner ) && IsPlayer(
self.owner ) )
1547 if ( last_hit_vo + hit_vo_spacing < GetTime() )
1549 if ( type ==
"MOD_PROJECTILE" || RandomIntRange(0,3) == 0 )
1553 last_hit_vo = GetTime();
1558 if( ( hardpointtype ==
"helicopter_comlink" ) || ( hardpointtype ==
"inventory_helicopter_comlink" ) )
1568 heli.active_camo_supported =
true;
1569 heli.active_camo_damage = 0;
1570 heli.active_camo_disabled =
false;
1574 if( isdefined( heli.flak_drone ) )
1584 if( !isdefined( heli.active_camo_supported ) )
1594 heli playsound (
"veh_hind_cloak_off");
1596 heli.camo_state_switch_time = gettime();
1600 if( heli.active_camo_disabled )
1613 heli playsound (
"veh_hind_cloak_on");
1615 heli.camo_state_switch_time = gettime();
1617 if ( isdefined( heli.owner ) )
1619 if ( isdefined( heli.play_camo_dialog ) && heli.play_camo_dialog )
1623 heli.play_camo_dialog =
false;
1625 else if ( !isdefined( heli.play_camo_dialog ) )
1628 heli.play_camo_dialog =
true;
1637 if( isdefined( heli.flak_drone ) )
1647 self endon(
"death" );
1648 self endon(
"crashing" );
1652 heli.active_camo_damage +=
damage;
1656 heli.active_camo_disabled =
true;
1669 self endon(
"death" );
1670 self endon(
"crashing" );
1673 heli notify(
"heli_active_camo_damage_disable" );
1674 heli endon(
"heli_active_camo_damage_disable" );
1680 heli.active_camo_damage = 0;
1681 heli.active_camo_disabled =
false;
1687 self endon(
"death" );
1688 self endon(
"crashing" );
1690 self.currentstate =
"ok";
1691 self.laststate =
"ok";
1692 self setdamagestage( 3 );
1697 if ( isdefined( tableHealth ) )
1699 self.maxhealth = tableHealth;
1704 self waittill(
"damage",
damage, attacker, direction, point, type, modelName, tagName, partname, weapon );
1707 if(
self.damageTaken >
self.maxhealth )
1710 self setDamageStage( damageState );
1714 self thread
heli_crash( hardpointType,
self.owner, playerNotify );
1716 else if (
self.damageTaken >= (
self.maxhealth * 0.66) && damageState >= 2 )
1721 if ( isdefined(
self.vehicletype ) &&
self.vehicletype ==
"heli_player_gunner_mp" )
1723 PlayFXOnTag( level.chopper_fx[
"damage"][
"heavy_smoke"],
self,
"tag_origin");
1727 PlayFXOnTag( level.chopper_fx[
"damage"][
"heavy_smoke"],
self,
"tag_main_rotor");
1730 self.currentstate =
"heavy smoke";
1731 self.evasive =
true;
1732 self notify(
"damage state");
1734 else if (
self.damageTaken >= (
self.maxhealth * 0.33) && damageState == 3 )
1737 if ( isdefined(
self.vehicletype ) &&
self.vehicletype ==
"heli_player_gunner_mp" )
1739 PlayFXOnTag( level.chopper_fx[
"damage"][
"light_smoke"],
self,
"tag_origin");
1743 PlayFXOnTag( level.chopper_fx[
"damage"][
"light_smoke"],
self,
"tag_main_rotor");
1746 self.currentstate =
"light smoke";
1747 self notify(
"damage state");
1756 self notify(
"evasive" );
1758 self.evasive =
true;
1761 loop_startnode = level.heli_loop_paths[0];
1763 gunnerPathFound =
true;
1764 if ( hardpointType ==
"helicopter_gunner" )
1766 gunnerPathFound =
false;
1767 for ( i = 0 ; i < level.heli_loop_paths.size ; i++ )
1769 if ( isdefined( level.heli_loop_paths[i].isGunnerPath ) && level.heli_loop_paths[i].isGunnerPath )
1771 loop_startnode = level.heli_loop_paths[i];
1772 gunnerPathFound =
true;
1777 assert( gunnerPathFound,
"No chopper gunner loop paths found in map" );
1780 if ( isdefined(
self.doNotStop ) &&
self.doNotStop )
1783 self thread
heli_fly( loop_startnode, startwait, hardpointType );
1788 if ( !isdefined(player) )
1791 if ( !isdefined(playerNotify) )
1794 player endon(
"disconnect" );
1795 player endon( playerNotify );
1799 player notify( playerNotify );
1804 self.owner endon(
"disconnect" );
1805 self endon(
"death" );
1813 self endon(
"death" );
1814 self notify(
"crashing" );
1818 self stoploopsound(0);
1819 if( isdefined(
self.minigun_snd_ent ) )
1821 self.minigun_snd_ent StopLoopSound();
1823 if( isdefined(
self.alarm_snd_ent ) )
1825 self.alarm_snd_ent StopLoopSound();
1832 crashTypes[0] =
"crashOnPath";
1833 crashTypes[1] =
"spinOut";
1835 crashType = crashTypes[randomInt(2)];
1838 if ( isdefined(
self.crashType ) )
1839 crashType =
self.crashType;
1851 if ( isdefined( player ) )
1861 if ( isdefined( player ) )
1868 heli_speed = 30+randomInt(50);
1869 heli_accel = 10+randomInt(25);
1874 self setspeed( heli_speed, heli_accel );
1877 rateOfSpin = 45 + randomint(90);
1888 if ( isdefined( player ) && isdefined( playerNotify ) )
1889 player notify( playerNotify );
1897 time = randomIntRange(4, 6);
1903 self endon (
"death" );
1904 self SetRotorSpeed( 0.6 );
1909 self endon(
"death" );
1918 crashPathDistance = -1;
1919 crashPath = level.heli_crash_paths[0];
1920 for ( i = 0; i < level.heli_crash_paths.size; i++ )
1922 currentDistance = distance(
self.origin, level.heli_crash_paths[i].origin);
1923 if ( crashPathDistance == -1 || crashPathDistance > currentDistance )
1925 crashPathDistance = currentDistance;
1926 crashPath = level.heli_crash_paths[i];
1930 heli_speed = 30+randomInt(50);
1931 heli_accel = 10+randomInt(25);
1934 self setspeed( heli_speed, heli_accel );
1939 self thread
heli_fly( crashPath, 0, hardpointType );
1941 rateOfSpin = 45 + randomint(90);
1947 self waittill (
"path start" );
1950 self waittill(
"destination reached" );
1957 if( isdefined(
self.model ) )
1959 if(
self.model ==
"veh_t7_drone_hunter" )
1963 case "tag_engine_left":
1964 return "tag_fx_exhaust2";
1965 case "tag_engine_right":
1966 return "tag_fx_exhaust1";
1967 case "tail_rotor_jnt":
1968 return "tag_fx_tail";
1980 self endon(
"death" );
1982 playFxOnTag( level.chopper_fx[
"explode"][
"large"],
self,
self CheckHelicopterTag(
"tag_engine_left" ) );
1984 self playSound ( level.heli_sound[
"hit"] );
1987 if ( isdefined(
self.vehicletype ) &&
self.vehicletype ==
"heli_player_gunner_mp" )
1996 self setdamagestage( 0 );
2002 if ( !isdefined(
self ) )
2005 playFxOnTag( level.chopper_fx[
"explode"][
"large"],
self,
self CheckHelicopterTag(
"tag_engine_left" ) );
2006 self playSound ( level.heli_sound[
"hitsecondary"] );
2012 self endon(
"death" );
2022 self setyawspeed( speed, speed / 3 , speed / 3 );
2023 while ( isdefined(
self ) )
2025 self settargetyaw(
self.angles[1]+(speed*0.9) );
2032 self endon(
"death" );
2036 self stopLoopSound();
2038 self playLoopSound( level.heli_sound[
"spinloop"] );
2040 self playSound( level.heli_sound[
"spinstart"] );
2045 playfxontag(
trail_fx,
self, trail_tag );
2050 team =
self.originalteam;
2052 if ( Target_IsTarget(
self) )
2053 Target_remove(
self );
2057 if( isdefined(
self.interior_model ) )
2059 self.interior_model Delete();
2060 self.interior_model = undefined;
2062 if( isdefined(
self.minigun_snd_ent ) )
2064 self.minigun_snd_ent StopLoopSound();
2065 self.minigun_snd_ent Delete();
2066 self.minigun_snd_ent = undefined;
2068 if( isdefined(
self.alarm_snd_ent ) )
2070 self.alarm_snd_ent Delete();
2071 self.alarm_snd_ent = undefined;
2073 if ( isdefined(
self.flare_ent ) )
2075 self.flare_ent Delete();
2076 self.flare_ent = undefined;
2087 self endon(
"death" );
2089 forward = (
self.origin + ( 0, 0, 100 ) ) -
self.origin;
2090 if( isdefined(
self.helitype) &&
self.helitype ==
"littlebird" )
2092 playfx( level.chopper_fx[
"explode"][
"guard"],
self.origin, forward );
2094 else if ( isdefined(
self.vehicletype ) &&
self.vehicletype ==
"heli_player_gunner_mp" )
2096 playfx( level.chopper_fx[
"explode"][
"gunner"],
self.origin, forward );
2100 playfx( level.chopper_fx[
"explode"][
"death"],
self.origin, forward );
2104 self PlaySound ( level.heli_sound[
"crash"] );
2108 assert( isdefined(
self.destroyFunc ) );
2109 self [[
self.destroyFunc]]();
2122 self notify(
"destintation reached" );
2123 self notify(
"leaving" );
2125 hardpointType =
self.hardpointType;
2127 self.leaving =
true;
2129 if( !
IS_TRUE(
self.detroyScoreEventGiven ) )
2139 self ClearLookAtEnt();
2140 exitAngles = VectorToAngles(leavenode.origin -
self.origin);
2141 self SetGoalYaw( exitAngles[1] );
2144 if ( !isdefined(
self ) )
2149 self setspeed( 180, 65 );
2153 self waittill(
"near_goal" );
2154 if( isdefined(
self ) )
2157 self waittillmatch(
"goal" );
2158 if( isdefined(
self ) )
2160 self stoploopsound(1);
2162 if( isdefined(
self.alarm_snd_ent ) )
2164 self.alarm_snd_ent StopLoopSound();
2165 self.alarm_snd_ent Delete();
2166 self.alarm_snd_ent = undefined;
2169 assert( isdefined(
self.destroyFunc ) );
2170 self [[
self.destroyFunc]]();
2178 self endon(
"death" );
2179 self endon(
"leaving" );
2182 self notify(
"flying" );
2183 self endon(
"flying" );
2186 self endon(
"abandoned" );
2188 self.reached_dest =
false;
2194 while ( isdefined( currentnode.target ) )
2196 nextnode = getent( currentnode.target,
"targetname" );
2197 assert( isdefined( nextnode ),
"Next node in path is undefined, but has targetname" );
2200 pos = nextnode.origin+(0,0,30);
2203 if( isdefined( currentnode.script_airspeed ) && isdefined( currentnode.script_accel ) )
2205 heli_speed = currentnode.script_airspeed;
2206 heli_accel = currentnode.script_accel;
2210 heli_speed = 30+randomInt(20);
2211 heli_accel = 10+randomInt(5);
2214 if ( isdefined(
self.pathSpeedScale ) )
2216 heli_speed *=
self.pathSpeedScale;
2217 heli_accel *=
self.pathSpeedScale;
2221 if ( !isdefined( nextnode.target ) )
2227 if(
self.currentstate ==
"heavy smoke" ||
self.currentstate ==
"light smoke" )
2230 self setspeed( heli_speed, heli_accel );
2233 self waittill(
"near_goal" );
2234 self notify(
"path start" );
2239 if( isdefined( nextnode.script_delay ) && !isdefined(
self.doNotStop ) )
2242 self setspeed( heli_speed, heli_accel );
2245 if ( !isdefined( nextnode.script_delay ) || isdefined(
self.doNotStop ) )
2247 self waittill(
"near_goal" );
2248 self notify(
"path start" );
2253 self setgoalyaw( nextnode.angles[1] );
2256 self waittillmatch(
"goal" );
2262 for( index = 0; index < level.heli_loop_paths.size; index++ )
2264 if ( level.heli_loop_paths[index].origin == nextnode.origin )
2267 if(
self.loopcount >= level.heli_loopmax )
2272 currentnode = nextnode;
2275 self setgoalyaw( currentnode.angles[1] );
2276 self.reached_dest =
true;
2277 self notify (
"destination reached" );
2279 if ( isdefined(
self.waittime ) &&
self.waittime > 0 )
2283 if( isdefined(
self ) )
2289 min_distance = Int(level.heli_protect_radius * .2);
2290 direction = randomintrange(0,360);
2291 distance = randomintrange(min_distance, level.heli_protect_radius);
2298 return (protectDest[0] + x, protectDest[1] + y, nodeHeight);
2307 while( tries != 0 && isdefined( noFlyZone ) )
2315 return ( protect_spot[0], protect_spot[1], noFlyZoneHeight );
2329 self setmaxpitchroll( 30, 30 );
2330 heli_speed = 30+randomInt(20);
2331 heli_accel = 10+randomInt(5);
2332 self setspeed( heli_speed, heli_accel );
2333 self setyawspeed( 75, 45, 45 );
2338 self setmaxpitchroll( 30, 90 );
2339 heli_speed = 50+randomInt(20);
2340 heli_accel = 30+randomInt(5);
2341 self setspeed( heli_speed, heli_accel );
2342 self setyawspeed( 100, 75, 75 );
2347 self setmaxpitchroll( 0, 90 );
2348 self setspeed( 20, 10 );
2349 self setyawspeed( 55, 25, 25 );
2355 if ( isdefined(
self.locking_on) &&
self.locking_on )
2358 if ( isdefined(
self.locked_on) &&
self.locked_on )
2361 if ( isdefined(
self.locking_on_hacking) &&
self.locking_on_hacking )
2369 self endon(
"death" );
2371 self notify(
"flying" );
2372 self endon(
"flying" );
2374 self endon(
"abandoned" );
2376 IPrintLnBold(
"PROTECT ORIGIN: ("+protectDest[0]+
","+protectDest[1]+
","+protectDest[2]+
")\n" );
2380 self SetHoverParams( 50, 100, 50 );
2388 self waittill(
"near_goal" );
2396 self endon(
"death" );
2399 self notify(
"flying" );
2400 self endon(
"flying" );
2403 self endon(
"abandoned" );
2405 self.reached_dest =
false;
2408 self SetHoverParams( 50, 100, 50);
2412 currentDest = protectDest;
2414 nodeHeight = protectDest[2];
2416 nextnode = startNode;
2419 if ( heli_team ==
"axis" )
2424 protectDest = ( protectDest[0], protectDest[1], nodeHeight );
2426 protectDest = ( protectDest[0], protectDest[1], noFlyZoneHeight + heightOffset );
2427 currentDest = protectDest;
2429 self.endTime =
startTime + ( level.heli_protect_time * 1000 );
2430 self.killstreakEndTime = int(
self.endTime );
2432 self SetSpeed( 150, 80 );
2435 self waittill(
"near_goal" );
2437 heli_speed = 30+randomInt(20);
2438 heli_accel = 10+randomInt(5);
2444 while ( getTime() <
self.endTime )
2463 self notify(
"path start" );
2470 time = level.heli_protect_pos_time;
2472 if (
self.evasive ==
true )
2486 prevDest = currentDest;
2489 currentDest = ( currentDest[0], currentDest[1], noFlyZoneHeight + heightOffset );
2491 if ( isdefined( noFlyZones ) && ( noFlyZones.size > 0 ) )
2493 currentDest = prevDest;
2503 self endon(
"death" );
2504 self endon(
"crashing" );
2505 self endon(
"leaving" );
2514 if (
self is_targeted() || ( isdefined(
self.evasive) &&
self.evasive ) )
2526 self notify(
"endTargetYawUpdate" );
2527 self endon(
"death" );
2528 self endon(
"crashing" );
2529 self endon(
"leaving" );
2531 self endon(
"endTargetYawUpdate" );
2535 if ( isdefined(
self.primaryTarget ) )
2538 self setTargetYaw( yaw );
2547 if ( !isdefined( iShots ) )
2549 assert(
self.health > 0 );
2552 weaponShootTime = undefined;
2554 switch( sMissileType )
2557 weapon = GetWeapon(
"hind_FFAR" );
2558 tags[ 0 ] =
"tag_store_r_2";
2561 assertMsg(
"Invalid missile type specified. Must be ffar" );
2564 assert( isdefined( weapon ) );
2565 assert( tags.size > 0 );
2567 weaponShootTime = weapon.fireTime;
2568 assert( isdefined( weaponShootTime ) );
2570 self setVehWeapon( weapon );
2571 nextMissileTag = -1;
2572 for( i = 0 ; i < iShots ; i++ )
2575 if ( nextMissileTag >= tags.size )
2579 eMissile.killcament =
self;
2580 self.lastRocketFireTime = gettime();
2582 if ( i < iShots - 1 )
2583 wait weaponShootTime;
2590 if ( !isdefined(
self.owner ) || !isdefined(
self.owner.team ) ||
self.owner.team !=
self.team )
2592 self notify (
"abandoned" );
2601 if ( missilesEnabled )
2608 self endon(
"death" );
2609 self endon(
"crashing" );
2610 self endon(
"leaving" );
2614 if ( isdefined(
self.secondaryTarget ) )
2616 self.secondaryTarget.antithreat = undefined;
2617 self.missileTarget =
self.secondaryTarget;
2621 while( isdefined(
self.missileTarget ) && isalive(
self.missileTarget ) )
2625 self thread
missile_support(
self.missileTarget, level.heli_missile_rof,
true, undefined );
2631 self.missileTarget.antithreat = antithreat;
2633 wait level.heli_missile_rof;
2636 if ( !isdefined(
self.secondaryTarget ) || ( isdefined(
self.secondaryTarget ) &&
self.missileTarget !=
self.secondaryTarget ) )
2640 if ( isdefined(
self.missileTarget ) )
2641 self.missileTarget.antithreat = undefined;
2643 self waittill(
"secondary acquired" );
2654 chopperYaw =
self.angles[1];
2656 if ( targetYaw < 0 )
2657 targetYaw = targetYaw * -1;
2659 targetYaw = int( targetYaw ) % 360;
2661 if ( chopperYaw < 0 )
2662 chopperYaw = chopperYaw * -1;
2664 chopperYaw = int( chopperYaw ) % 360;
2666 if ( chopperYaw > targetYaw )
2667 difference = chopperYaw - targetYaw;
2669 difference = targetYaw - chopperYaw;
2671 return ( difference <= attackAngle );
2677 heli2target_normal = vectornormalize( target.origin -
self.origin );
2678 heli2forward = anglestoforward(
self.angles );
2679 heli2forward_normal = vectornormalize( heli2forward );
2681 heli_dot_target = vectordot( heli2target_normal, heli2forward_normal );
2683 if ( heli_dot_target >= coneCosine )
2695 self endon(
"death" );
2696 self endon(
"crashing" );
2697 self endon(
"leaving" );
2699 if ( isdefined ( endon_notify ) )
2700 self endon( endon_notify );
2702 self.turret_giveup =
false;
2707 self.turret_giveup =
true;
2708 self notify(
"give up" );
2711 if ( isdefined( target_player ) )
2713 if ( level.teambased )
2716 for (i = 0; i < level.players.size; i++)
2718 player = level.players[i];
2719 if ( isdefined( player.team ) && player.team ==
self.team && distance( player.origin, target_player.origin ) <= level.heli_missile_friendlycare )
2721 self notify (
"missile ready" );
2728 player =
self.owner;
2729 if ( isdefined( player ) && isdefined( player.team ) && player.team ==
self.team && distance( player.origin, target_player.origin ) <= level.heli_missile_friendlycare )
2731 self notify (
"missile ready" );
2737 if (
self.missile_ammo > 0 && isdefined( target_player ) )
2740 self.missile_ammo--;
2741 self notify(
"missile fired" );
2751 self notify (
"missile ready" );
2758 self endon(
"death" );
2759 self endon(
"crashing" );
2760 self endon(
"leaving" );
2761 level endon(
"game_ended" );
2765 if ( isdefined(
self.primaryTarget ) )
2767 self.primaryTarget.antithreat = undefined;
2768 self.turretTarget =
self.primaryTarget;
2770 last_pos = undefined;
2772 while( isdefined(
self.turretTarget ) && isalive(
self.turretTarget ) )
2776 if ( (hardpointType ==
"helicopter_comlink") || (hardpointType ==
"inventory_helicopter_comlink") )
2777 self SetLookAtEnt(
self.turretTarget );
2779 helicopterTurretMaxAngle =
heli_get_dvar_int(
"scr_helicopterTurretMaxAngle", level.helicopterTurretMaxAngle );
2780 while ( isdefined(
self.turretTarget ) && isalive(
self.turretTarget ) &&
self turret_target_check(
self.turretTarget, helicopterTurretMaxAngle ) ==
false )
2783 if ( !isdefined(
self.turretTarget ) || !isalive(
self.turretTarget ) )
2787 self setTurretTargetEnt(
self.turretTarget, ( 0, 0, 50 ) );
2789 self waittill(
"turret_on_target" );
2798 self notify(
"turret_on_target" );
2800 if (!
self.pilotIsTalking)
2812 wait( level.heli_turret_spinup_delay );
2815 weaponShootTime =
self.defaultWeapon.fireTime;
2816 self setVehWeapon(
self.defaultWeapon );
2819 for( i = 0 ; i < level.heli_turretClipSize ; i++ )
2822 if ( isdefined(
self.turretTarget ) && isdefined(
self.primaryTarget ) )
2824 if (
self.primaryTarget !=
self.turretTarget )
2825 self setTurretTargetEnt(
self.primaryTarget, ( 0, 0, 40 ) );
2829 if ( isdefined(
self.targetlost ) &&
self.targetlost && isdefined(
self.turret_last_pos ) )
2831 self setturrettargetvec(
self.turret_last_pos );
2835 self clearturrettarget();
2838 if ( gettime() !=
self.lastRocketFireTime )
2841 self setVehWeapon(
self.defaultWeapon );
2847 if ( i < level.heli_turretClipSize - 1 )
2848 wait weaponShootTime;
2852 self notify(
"turret reloading" );
2856 wait( level.heli_turretReloadTime );
2863 if ( isdefined(
self.turretTarget ) && isalive(
self.turretTarget ) )
2866 self.turretTarget.antithreat = antithreat;
2870 if ( !isdefined(
self.primaryTarget ) || ( isdefined(
self.turretTarget ) && isdefined(
self.primaryTarget ) &&
self.primaryTarget !=
self.turretTarget ) )
2874 if ( isdefined(
self.turretTarget ) )
2875 self.turretTarget.antithreat = undefined;
2877 self waittill(
"primary acquired" );
2888 self notify(
"flag check is running" );
2889 self endon(
"flag check is running" );
2891 self endon(
"death" );
2892 self endon(
"crashing" );
2893 self endon(
"leaving" );
2894 self endon(
"turret reloading" );
2897 if ( isdefined( turrettarget ) )
2899 turrettarget endon(
"death" );
2900 turrettarget endon(
"disconnect" );
2903 self.targetlost =
false;
2904 self.turret_last_pos = undefined;
2906 while( isdefined( turrettarget ) )
2908 heli_centroid =
self.origin + ( 0, 0, -160 );
2909 heli_forward_norm = anglestoforward(
self.angles );
2910 heli_turret_point = heli_centroid + 144*heli_forward_norm;
2912 sight_rec = turrettarget sightconetrace( heli_turret_point,
self );
2913 if ( sight_rec < level.heli_target_recognition )
2919 if( isdefined( turrettarget ) && isdefined( turrettarget.origin ) )
2921 assert( isdefined( turrettarget.origin ),
"turrettarget.origin is undefined after isdefined check" );
2922 self.turret_last_pos = turrettarget.origin + ( 0, 0, 40 );
2923 assert( isdefined(
self.turret_last_pos ),
"self.turret_last_pos is undefined after setting it #1" );
2924 self setturrettargetvec(
self.turret_last_pos );
2925 assert( isdefined(
self.turret_last_pos ),
"self.turret_last_pos is undefined after setting it #2" );
2926 self.targetlost =
true;
2930 self.targetlost = undefined;
2931 self.turret_last_pos = undefined;
2937 self endon(
"emp_jammed" );
2938 self endon(
"emp_grenaded" );
2940 self waittill(
"confirm_location", location );
2947 self beginLocationComlinkSelection(
"compass_objpoint_helicopter", 1500 );
2948 self.selectingLocation =
true;
2954 if ( !isdefined( location ) )
2965 level.helilocation = location;
2972 self endon(
"disconnect" );
2973 destroyedCopter endon(
"disconnect" );
2977 if ( !isdefined( level.teams[
self.team] ) )
2980 if (
self.team == destroyedCopter.team )
2983 assist_level =
"aircraft_destruction_assist";
2985 assist_level_value = int( ceil( ( damagedone.damage / destroyedCopter.maxhealth ) * 4 ) );
2987 if ( assist_level_value > 0 )
2989 if ( assist_level_value > 3 )
2991 assist_level_value = 3;
2993 assist_level = assist_level +
"_" + ( assist_level_value * 25 );
3002 self endon(
"death" );
3003 self endon(
"crashing" );
3004 self endon(
"leaving" );
3005 level endon(
"game_ended" );
3009 Target_SetTurretAquire(
self,
true );
3014 self endon(
"death" );
3015 level endon(
"remote_end" );
3017 if (isdefined(time))
3021 if (!isdefined(
self.pilotVoiceNumber))
3023 self.pilotVoiceNumber = 0;
3025 if (isdefined(voice))
3027 voicenumber = voice;
3031 voicenumber =
self.pilotVoiceNumber;
3033 soundAlias = level.teamPrefix[
self.team] + voicenumber +
"_" + dialog;
3035 if ( isdefined (
self.owner ) )
3043 self endon(
"disconnect" );
3044 self endon(
"joined_team" );
3045 self endon(
"joined_spectators" );
3048 while( isdefined(
self.pilotTalking) &&
self.pilotTalking && tryCounter < 10 )
3050 if ( isdefined( shouldWait ) && !shouldWait )
3055 self.pilotTalking =
true;
3056 self playLocalSound(soundAlias);
3058 self.pilotTalking =
false;
3063 chopper notify(
"watchForEarlyLeave_helicopter" );
3064 chopper endon(
"watchForEarlyLeave_helicopter" );
3065 chopper endon(
"death" );
3066 self endon(
"heli_timeup" );
3070 if ( isdefined( chopper ) )
3073 if ( isdefined(
self ) )
3074 self notify(
"heli_timeup" );
3081 heli endon(
"death" );
3082 heli endon(
"heli_timeup" );
3084 heli.owner waittill(
"emp_jammed" );