Guest User

Untitled

a guest
Jun 15th, 2013
69
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include maps\mp\_utility;
  2. #include maps\mp\gametypes\_hud_util;
  3. #include maps\mp\gametypes\waffle_util;
  4. #include common_scripts\utility;
  5.  
  6. precachehelicopter(model,type)
  7. {
  8. if(!isdefined(type))
  9. type = "blackhawk";
  10.  
  11. deathfx = loadfx ("explosions/tanker_explosion");
  12.  
  13. precacheModel( model );
  14. level.vehicle_deathmodel[model] = model;
  15.  
  16. //precachevehicle(type);
  17. precacheitem( "cobra_FFAR_mp" );
  18. precacheitem( "hind_FFAR_mp" );
  19. precacheitem( "cobra_20mm_mp" );
  20.  
  21. /******************************************************/
  22. /* SETUP WEAPON TAGS */
  23. /******************************************************/
  24.  
  25. level.cobra_missile_models = [];
  26. level.cobra_missile_models["cobra_Hellfire"] = "projectile_hellfire_missile";
  27. // level.cobra_missile_models["cobra_Sidewinder"] = "projectile_sidewinder_missile";
  28.  
  29. precachemodel( level.cobra_missile_models["cobra_Hellfire"] );
  30. // precachemodel( level.cobra_missile_models["cobra_Sidewinder"] );
  31.  
  32. // helicopter sounds:
  33. level.heli_sound["allies"]["hit"] = "cobra_helicopter_hit";
  34. level.heli_sound["allies"]["hitsecondary"] = "cobra_helicopter_secondary_exp";
  35. level.heli_sound["allies"]["damaged"] = "cobra_helicopter_damaged";
  36. level.heli_sound["allies"]["spinloop"] = "cobra_helicopter_dying_loop";
  37. level.heli_sound["allies"]["spinstart"] = "cobra_helicopter_dying_layer";
  38. level.heli_sound["allies"]["crash"] = "cobra_helicopter_crash";
  39. level.heli_sound["allies"]["missilefire"] = "weap_cobra_missile_fire";
  40. level.heli_sound["axis"]["hit"] = "hind_helicopter_hit";
  41. level.heli_sound["axis"]["hitsecondary"] = "hind_helicopter_secondary_exp";
  42. level.heli_sound["axis"]["damaged"] = "hind_helicopter_damaged";
  43. level.heli_sound["axis"]["spinloop"] = "hind_helicopter_dying_loop";
  44. level.heli_sound["axis"]["spinstart"] = "hind_helicopter_dying_layer";
  45. level.heli_sound["axis"]["crash"] = "hind_helicopter_crash";
  46. level.heli_sound["axis"]["missilefire"] = "weap_hind_missile_fire";
  47. }
  48.  
  49.  
  50. init()
  51. {
  52. // precacheitem("cobra_mp");
  53. // heli_trig = getent( "heli_obj", "targetname" );
  54. // if ( !isdefined( heli_trig ) )
  55. // return;
  56.  
  57. path_start = getentarray( "heli_start", "targetname" ); // start pointers, point to the actual start node on path
  58. loop_start = getentarray( "heli_loop_start", "targetname" ); // start pointers for loop path in the map
  59.  
  60. if ( !path_start.size && !loop_start.size)
  61. return;
  62.  
  63. precachehelicopter( "vehicle_cobra_helicopter_fly" );
  64. precachehelicopter( "vehicle_mi24p_hind_desert" );
  65. precachemodel("weapon_ac130_projectile");
  66. // array of paths, each element is an array of start nodes that all leads to a single destination node
  67. level.chopper = undefined;
  68. level.heli_paths = [];
  69. level.heli_loop_paths = [];
  70. level.heli_leavenodes = [];
  71. level.heli_crash_paths = [];
  72.  
  73. //dvars
  74. thread heli_update_global_dvars();
  75. thread onPlayerConnect();
  76. // thread maps\mp\_ac130::init();
  77. // helicopter fx
  78. level.chopper_fx["explode"]["death"] = loadfx ("explosions/helicopter_explosion_cobra");
  79. level.chopper_fx["explode"]["large"] = loadfx ("explosions/aerial_explosion_large");
  80. level.chopper_fx["explode"]["medium"] = loadfx ("explosions/aerial_explosion");
  81. level.chopper_fx["smoke"]["trail"] = loadfx ("smoke/smoke_trail_white_heli");
  82. level.chopper_fx["fire"]["trail"]["medium"] = loadfx ("smoke/smoke_trail_black_heli");
  83. level.chopper_fx["fire"]["trail"]["large"] = loadfx ("fire/fire_smoke_trail_L");
  84. heli_path_graph();
  85.  
  86. }
  87. onPlayerConnect()
  88. {
  89. for(;;)
  90. {
  91. level waittill("connected", player);
  92. // player thread givehelionfrag();
  93. }
  94. }
  95. givehelionfrag()
  96. {
  97. while(1)
  98. {
  99. wait 0.05;
  100. if( self fragbuttonpressed() )
  101. {
  102. destination = 0;
  103. random_path = randomint( level.heli_paths[destination].size );
  104. startnode = level.heli_paths[destination][random_path];
  105. thread maps\mp\_helicopter::heli_think( self, startnode, self.pers["team"] );
  106. break;
  107. }
  108. }
  109. }
  110. // update helicopter dvars realtime
  111. heli_update_global_dvars()
  112. {
  113. for( ;; )
  114. {
  115. // heli_update_dvar( dvar, default ) returns value
  116. level.heli_loopmax = heli_get_dvar_int( "scr_heli_loopmax", "1" ); // how many times helicopter will circle the map before it leaves
  117. level.heli_missile_rof = heli_get_dvar_int( "scr_heli_missile_rof", "5" ); // missile rate of fire, one every this many seconds per target, could fire two at the same time to different targets
  118. level.heli_armor = heli_get_dvar_int( "scr_heli_armor", "500" ); // armor points, after this much damage is taken, helicopter is easily damaged, and health degrades
  119. level.heli_rage_missile = heli_get_dvar( "scr_heli_rage_missile", "5" ); // higher the value, more frequent the missile assault
  120. level.heli_maxhealth = heli_get_dvar_int( "scr_heli_maxhealth", "1100" ); // max health of the helicopter
  121. level.heli_missile_max = heli_get_dvar_int( "scr_heli_missile_max", "3" ); // max number of missiles helicopter can carry
  122. level.heli_dest_wait = heli_get_dvar_int( "scr_heli_dest_wait", "2" ); // time helicopter waits (hovers) after reaching a destination
  123. level.heli_debug = heli_get_dvar_int( "scr_heli_debug", "0" ); // debug mode, draws debugging info on screen
  124.  
  125. level.heli_targeting_delay = heli_get_dvar( "scr_heli_targeting_delay", "0.5" ); // targeting delay
  126. level.heli_turretReloadTime = heli_get_dvar( "scr_heli_turretReloadTime", "1.5" ); // mini-gun reload time
  127. level.heli_turretClipSize = heli_get_dvar_int( "scr_heli_turretClipSize", "40" ); // mini-gun clip size, rounds before reload
  128. level.heli_visual_range = heli_get_dvar_int( "scr_heli_visual_range", "3500" ); // distance radius helicopter will acquire targets (see)
  129. level.heli_health_degrade = heli_get_dvar_int( "scr_heli_health_degrade", "0" ); // health degradation after injured, health descrease per second for heavy injury, half for light injury
  130.  
  131. level.heli_target_spawnprotection = heli_get_dvar_int( "scr_heli_target_spawnprotection", "5" );// players are this many seconds safe from helicopter after spawn
  132. level.heli_turret_engage_dist = heli_get_dvar_int( "scr_heli_turret_engage_dist", "1000" ); // engaging distance for turret
  133. level.heli_missile_engage_dist = heli_get_dvar_int( "scr_heli_missile_engage_dist", "2000" ); // engaging distance for missiles
  134. level.heli_missile_regen_time = heli_get_dvar( "scr_heli_missile_regen_time", "10" ); // gives one more missile to helicopter every interval - seconds
  135. level.heli_turret_spinup_delay = heli_get_dvar( "scr_heli_turret_spinup_delay", "0.75" ); // seconds it takes for the helicopter mini-gun to spin up before shots fired
  136. level.heli_target_recognition = heli_get_dvar( "scr_heli_target_recognition", "0.5" ); // percentage of the player's body the helicopter sees before it labels him as a target
  137. level.heli_missile_friendlycare = heli_get_dvar_int( "scr_heli_missile_friendlycare", "256" ); // if friendly is within this distance of the target, do not shoot missile
  138. level.heli_missile_target_cone = heli_get_dvar( "scr_heli_missile_target_cone", "0.3" ); // dot product of vector target to helicopter forward, 0.5 is in 90 range, bigger the number, smaller the cone
  139. level.heli_armor_bulletdamage = heli_get_dvar( "scr_heli_armor_bulletdamage", "0.3" ); // damage multiplier to bullets onto helicopter's armor
  140.  
  141. level.heli_attract_strength = heli_get_dvar( "scr_heli_attract_strength", "1000" );
  142. level.heli_attract_range = heli_get_dvar( "scr_heli_attract_range", "4096" );
  143.  
  144. wait 1;
  145. }
  146. }
  147.  
  148. heli_get_dvar_int( dvar, def )
  149. {
  150. return int( heli_get_dvar( dvar, def ) );
  151. }
  152.  
  153. // dvar set/fetch/check
  154. heli_get_dvar( dvar, def )
  155. {
  156. if ( getdvar( dvar ) != "" )
  157. return getdvarfloat( dvar );
  158. else
  159. {
  160. setdvar( dvar, def );
  161. return def;
  162. }
  163. }
  164.  
  165. spawn_helicopter( owner, origin, angles, model, targetname )
  166. {
  167. chopper = spawnHelicopter( owner, origin, angles, model, targetname );
  168. chopper.attractor = Missile_CreateAttractorEnt( chopper, level.heli_attract_strength, level.heli_attract_range );
  169. return chopper;
  170. }
  171. heli_path_graph()
  172. {
  173. // collecting all start nodes in the map to generate path arrays
  174. path_start = getentarray( "heli_start", "targetname" ); // start pointers, point to the actual start node on path
  175. path_dest = getentarray( "heli_dest", "targetname" ); // dest pointers, point to the actual dest node on path
  176. loop_start = getentarray( "heli_loop_start", "targetname" ); // start pointers for loop path in the map
  177. leave_nodes = getentarray( "heli_leave", "targetname" ); // points where the helicopter leaves to
  178. crash_start = getentarray( "heli_crash_start", "targetname" ); // start pointers, point to the actual start node on crash path
  179.  
  180. assertex( ( isdefined( path_start ) && isdefined( path_dest ) ), "Missing path_start or path_dest" );
  181.  
  182. // for each destination, loop through all start nodes in level to populate array of start nodes that leads to this destination
  183. for (i=0; i<path_dest.size; i++)
  184. {
  185. startnode_array = [];
  186.  
  187. // destnode is the final destination from multiple start nodes
  188. destnode_pointer = path_dest[i];
  189. destnode = getent( destnode_pointer.target, "targetname" );
  190.  
  191. // for each start node, traverse to its dest., if same dest. then append to startnode_array
  192. for ( j=0; j<path_start.size; j++ )
  193. {
  194. toDest = false;
  195. currentnode = path_start[j];
  196. // traverse through path to dest.
  197. while( isdefined( currentnode.target ) )
  198. {
  199. nextnode = getent( currentnode.target, "targetname" );
  200. if ( nextnode.origin == destnode.origin )
  201. {
  202. toDest = true;
  203. break;
  204. }
  205.  
  206. // debug ==============================================================
  207. debug_print3d_simple( "+", currentnode, ( 0, 0, -10 ) );
  208. if( isdefined( nextnode.target ) )
  209. debug_line( nextnode.origin, getent(nextnode.target, "targetname" ).origin, ( 0.25, 0.5, 0.25 ) );
  210. if( isdefined( currentnode.script_delay ) )
  211. debug_print3d_simple( "Wait: " + currentnode.script_delay , currentnode, ( 0, 0, 10 ) );
  212.  
  213. currentnode = nextnode;
  214. }
  215. if ( toDest )
  216. startnode_array[startnode_array.size] = getent( path_start[j].target, "targetname" ); // the actual start node on path, not start pointer
  217. }
  218. assertex( ( isdefined( startnode_array ) && startnode_array.size > 0 ), "No path(s) to destination" );
  219.  
  220. // load the array of start nodes that lead to this destination node into level.heli_paths array as an element
  221. level.heli_paths[level.heli_paths.size] = startnode_array;
  222. }
  223.  
  224. // loop paths array
  225. for (i=0; i<loop_start.size; i++)
  226. {
  227. startnode = getent( loop_start[i].target, "targetname" );
  228. level.heli_loop_paths[level.heli_loop_paths.size] = startnode;
  229. }
  230. assertex( isdefined( level.heli_loop_paths[0] ), "No helicopter loop paths found in map" );
  231.  
  232. // leave nodes
  233. for (i=0; i<leave_nodes.size; i++)
  234. level.heli_leavenodes[level.heli_leavenodes.size] = leave_nodes[i];
  235. assertex( isdefined( level.heli_leavenodes[0] ), "No helicopter leave nodes found in map" );
  236.  
  237. // crash paths
  238. for (i=0; i<crash_start.size; i++)
  239. {
  240. crash_start_node = getent( crash_start[i].target, "targetname" );
  241. level.heli_crash_paths[level.heli_crash_paths.size] = crash_start_node;
  242. }
  243. assertex( isdefined( level.heli_crash_paths[0] ), "No helicopter crash paths found in map" );
  244. }
  245. // spawn helicopter at a start node and monitors it
  246. heli_think( owner, startnode, heli_team, requiredDeathCount )
  247. {
  248.  
  249. heliAngles = owner.angles;
  250. heliOrigin = owner.origin + (0,0,2000);
  251.  
  252. if( heli_team == "allies" )
  253. {
  254. chopper = spawn_helicopter( owner, heliOrigin, heliAngles, "cobra_mp", "vehicle_cobra_helicopter_fly" );
  255. chopper playLoopSound( "mp_cobra_helicopter" );
  256. }
  257. else
  258. {
  259. chopper = spawn_helicopter( owner, heliOrigin, heliAngles, "cobra_mp", "vehicle_mi24p_hind_desert" );
  260. chopper playLoopSound( "mp_cobra_helicopter" );
  261. }
  262.  
  263. chopper.requiredDeathCount = owner.deathCount;
  264.  
  265. chopper.team = heli_team;
  266. chopper.pers["team"] = heli_team;
  267.  
  268. chopper.owner = owner;
  269. owner.choppa = chopper;
  270. owner.choppa = chopper;
  271. chopper thread heli_existance();
  272.  
  273. //chopper thread heli_trig_interval( level.heli_trigger, level.heli_hardpoint_timer );
  274. if( isDefined( level.firstchopper ) )
  275. level.secondchopper = chopper;
  276. else
  277. level.firstchopper = chopper;
  278. if( isDefined( level.firstchopper ) && isDefined( level.secondchopper ) )
  279. level.chopper = chopper;
  280. // TO DO: convert all helicopter attributes into dvars
  281. chopper.reached_dest = false; // has helicopter reached destination
  282. chopper.maxhealth = level.heli_maxhealth; // max health
  283. chopper.waittime = level.heli_dest_wait; // the time helicopter will stay stationary at destination
  284. chopper.loopcount = 0; // how many times helicopter circled the map
  285. chopper.evasive = false; // evasive manuvering
  286. chopper.health_bulletdamageble = level.heli_armor; // when damage taken is above this value, helicopter can be damage by bullets to its full amount
  287. chopper.health_evasive = level.heli_armor; // when damage taken is above this value, helicopter performs evasive manuvering
  288. chopper.health_low = level.heli_maxhealth*0.8; // when damage taken is above this value, helicopter catchs on fire
  289. chopper.targeting_delay = level.heli_targeting_delay; // delay between per targeting scan - in seconds
  290. chopper.primaryTarget = undefined; // primary target ( player )
  291. chopper.secondaryTarget = undefined; // secondary target ( player )
  292. chopper.attacker = undefined; // last player that shot the helicopter
  293. chopper.missile_ammo = level.heli_missile_max; // initial missile ammo
  294. chopper.currentstate = "ok"; // health state
  295. chopper.lastRocketFireTime = -1;
  296.  
  297. chopper.angles = owner.angles;
  298. chopper.origin = owner.origin + (0,0,1000);
  299. owner hide();
  300. if( owner.pers["team"] == "allies" )
  301. {
  302. heli_centroid = chopper.origin + ( 0, 0, -145 );
  303. heli_forward_norm = anglestoforward( chopper.angles );
  304. heli_turret_point = heli_centroid + 110*heli_forward_norm;
  305. }
  306. else
  307. {
  308. heli_centroid = chopper.origin + ( 0, 0, -100 );
  309. heli_forward_norm = anglestoforward( chopper.angles );
  310. heli_turret_point = heli_centroid + 120*heli_forward_norm;
  311. }
  312. owner setorigin( heli_turret_point );
  313. owner.flyingheli = true;
  314. self.zething = spawn("script_origin", owner.origin);
  315. owner linkto( self.zething );
  316. self.zething linkto( chopper );
  317. chopper thread heli_fly( owner ); // fly heli to given node and continue on its path
  318. chopper thread heli_damage_monitor(); // monitors damage
  319. chopper thread heli_health(); // display helicopter's health through smoke/fire
  320. }
  321.  
  322. heli_existance()
  323. {
  324. self waittill_any( "death", "crashing", "leaving" );
  325. level notify( "helicopter gone" );
  326. }
  327.  
  328.  
  329. // resets helicopter's motion values
  330. heli_reset()
  331. {
  332. self clearTargetYaw();
  333. self clearGoalYaw();
  334. self setspeed( 60, 25 );
  335. self setyawspeed( 75, 45, 45 );
  336. //self setjitterparams( (30, 30, 30), 4, 6 );
  337. self setmaxpitchroll( 30, 30 );
  338. self setneargoalnotifydist( 256 );
  339. self setturningability(0.9);
  340. }
  341.  
  342. heli_wait( waittime )
  343. {
  344. self endon ( "death" );
  345. self endon ( "crashing" );
  346. self endon ( "evasive" );
  347.  
  348. //self thread heli_hover();
  349. wait( waittime );
  350. //heli_reset();
  351.  
  352. //self notify( "stop hover" );
  353. }
  354.  
  355. // hover movements
  356. heli_hover()
  357. {
  358. // stop hover when anything at all happens
  359. self endon( "death" );
  360. self endon( "stop hover" );
  361. self endon( "evasive" );
  362. self endon( "leaving" );
  363. self endon( "crashing" );
  364.  
  365. original_pos = self.origin;
  366. original_angles = self.angles;
  367. self setyawspeed( 10, 45, 45 );
  368.  
  369. x = 0;
  370. y = 0;
  371.  
  372. // random hovering movement loop
  373. /*
  374. for( ;; )
  375. {
  376. for( idx=0; idx<10; idx++ )
  377. {
  378. heli_speed = 10+randomint(10);
  379. heli_accel = 10+randomint(5);
  380. self setspeed( heli_speed, heli_accel );
  381. x -= randomInt(5);
  382. x += randomInt(5);
  383. y -= randomInt(5);
  384. y += randomInt(5);
  385. self setvehgoalpos( original_pos+( x, y, randomInt(10) ), 0 );
  386. //self setgoalyaw( self.angles[1]+randomint(10), 45, 45 );
  387. self waittillmatch( "goal" );
  388. wait ( 1+randomInt(2) );
  389. }
  390. self setvehgoalpos( original_pos, 0 );
  391. //self setgoalyaw( original_angles[1], 45, 45 );
  392. self waittillmatch( "goal" );
  393. }
  394. */
  395. }
  396.  
  397. // accumulate damage and react
  398. heli_damage_monitor()
  399. {
  400. self endon( "death" );
  401. self endon( "crashing" );
  402. self endon( "leaving" );
  403.  
  404. self.damageTaken = 0;
  405. // self thread maps\mp\gametypes\tankwarfare::watchdamage( self, 500 );
  406. for( ;; )
  407. {
  408. // this damage is done to self.health which isnt used to determine the helicopter's health, damageTaken is.
  409. self waittill( "damage", damage, attacker, direction_vec, P, type );
  410. // self notify( "damage taken" ); // not used anywhere yet
  411.  
  412. if( !isdefined( attacker ) || !isplayer( attacker ) )
  413. continue;
  414.  
  415. heli_friendlyfire = maps\mp\gametypes\_weapons::friendlyFireCheck( self.owner, attacker );
  416. // skip damage if friendlyfire is disabled
  417. if( !heli_friendlyfire )
  418. continue;
  419.  
  420. if( isDefined( self.owner ) && attacker == self.owner )
  421. continue;
  422.  
  423. if ( level.teamBased )
  424. isValidAttacker = (isdefined( attacker.pers["team"] ) && attacker.pers["team"] != self.team);
  425. else
  426. isValidAttacker = true;
  427.  
  428. if ( !isValidAttacker )
  429. continue;
  430.  
  431. attacker thread maps\mp\gametypes\_damagefeedback::updateDamageFeedback( false );
  432. self.attacker = attacker;
  433.  
  434. if ( type == "MOD_RIFLE_BULLET" || type == "MOD_PISTOL_BULLET" )
  435. {
  436. if( self.damageTaken >= self.health_bulletdamageble )
  437. self.damageTaken += damage;
  438. else
  439. self.damageTaken += damage*level.heli_armor_bulletdamage;
  440. }
  441. else
  442. self.damageTaken += damage;
  443.  
  444. if( self.damageTaken > self.maxhealth )
  445. attacker notify( "destroyed_helicopter", self.owner );
  446.  
  447. }
  448. }
  449.  
  450. heli_health()
  451. {
  452. self endon( "death" );
  453. self endon( "leaving" );
  454. self endon( "crashing" );
  455.  
  456. self.currentstate = "ok";
  457. self.laststate = "ok";
  458. self setdamagestage( 3 );
  459.  
  460. for ( ;; )
  461. {
  462. if ( self.health_bulletdamageble > self.health_low )
  463. {
  464. if ( self.damageTaken >= self.health_bulletdamageble )
  465. self.currentstate = "heavy smoke";
  466. else if ( self.damageTaken >= self.health_low )
  467. self.currentstate = "light smoke";
  468. }
  469. else
  470. {
  471. if ( self.damageTaken >= self.health_low )
  472. self.currentstate = "heavy smoke";
  473. else if ( self.damageTaken >= self.health_bulletdamageble )
  474. self.currentstate = "light smoke";
  475. }
  476.  
  477. if ( self.currentstate == "light smoke" && self.laststate != "light smoke" )
  478. {
  479. self setdamagestage( 2 );
  480. self.laststate = self.currentstate;
  481.  
  482. }
  483. if ( self.currentstate == "heavy smoke" && self.laststate != "heavy smoke" )
  484. {
  485. self setdamagestage( 1 );
  486. self notify ( "stop body smoke" );
  487. self.laststate = self.currentstate;
  488.  
  489. // play loop sound "damaged"
  490. //self playloopsound ( level.heli_sound[self.team]["damaged"] );
  491. }
  492.  
  493. if ( self.currentstate == "heavy smoke" )
  494. {
  495. self.damageTaken += level.heli_health_degrade;
  496. level.heli_rage_missile = 20; // increase missile firing rate more
  497. }
  498. if ( self.currentstate == "light smoke" )
  499. {
  500. self.damageTaken += level.heli_health_degrade/2;
  501. level.heli_rage_missile = 10; // increase missile firing rate
  502. }
  503.  
  504. if( self.damageTaken >= self.health_evasive )
  505. {
  506. if( !self.evasive )
  507. self thread heli_evasive();
  508. }
  509.  
  510. if( self.damageTaken > self.maxhealth )
  511. self thread heli_crash();
  512.  
  513. // debug =================================
  514. if( self.damageTaken <= level.heli_armor )
  515. debug_print3d_simple( "Armor: " + (level.heli_armor-self.damageTaken), self, ( 0,0,100 ), 20 );
  516. else
  517. debug_print3d_simple( "Health: " + ( self.maxhealth - self.damageTaken ), self, ( 0,0,100 ), 20 );
  518.  
  519. wait 1;
  520. }
  521. }
  522. // evasive manuvering - helicopter circles the map for awhile then returns to path
  523. heli_evasive()
  524. {
  525. // only one instance allowed
  526. self notify( "evasive" );
  527.  
  528. self.evasive = true;
  529.  
  530. // set helicopter path to circle the map level.heli_loopmax number of times
  531. loop_startnode = level.heli_loop_paths[0];
  532. // self thread heli_fly( loop_startnode );
  533. }
  534.  
  535. // attach helicopter on crash path
  536. heli_crash()
  537. {
  538. self notify( "crashing" );
  539.  
  540. // helicopter losing control and spins
  541. self thread heli_spin( 180 );
  542.  
  543. // body explosion fx when on crash path
  544. playfxontag( level.chopper_fx["explode"]["large"], self, "tag_engine_left" );
  545. // along with a sound
  546. self playSound ( level.heli_sound[self.team]["hitsecondary"] );
  547.  
  548. self setdamagestage( 0 );
  549. // form fire smoke trails on body after explosion
  550. self thread trail_fx( level.chopper_fx["fire"]["trail"]["large"], "tag_engine_left", "stop body fire" );
  551.  
  552. // self waittill( "destination reached" );
  553. self thread heli_explode();
  554. }
  555.  
  556. // self spin at one rev per 2 sec
  557. heli_spin( speed )
  558. {
  559. self endon( "death" );
  560.  
  561. // tail explosion that caused the spinning
  562. playfxontag( level.chopper_fx["explode"]["medium"], self, "tail_rotor_jnt" );
  563. // play hit sound immediately so players know they got it
  564. self playSound ( level.heli_sound[self.team]["hit"] );
  565.  
  566. // play heli crashing spinning sound
  567. self thread spinSoundShortly();
  568.  
  569. // form smoke trails on tail after explosion
  570. self thread trail_fx( level.chopper_fx["smoke"]["trail"], "tail_rotor_jnt", "stop tail smoke" );
  571.  
  572. // spins until death
  573. self setyawspeed( speed, speed, speed );
  574. while ( isdefined( self ) )
  575. {
  576. self settargetyaw( self.angles[1]+(speed*0.9) );
  577. wait ( 1 );
  578. }
  579. }
  580.  
  581. spinSoundShortly()
  582. {
  583. self endon("death");
  584.  
  585. wait .25;
  586.  
  587. self stopLoopSound();
  588. wait .05;
  589. self playLoopSound( level.heli_sound[self.team]["spinloop"] );
  590. wait .05;
  591. self playSound( level.heli_sound[self.team]["spinstart"] );
  592. }
  593.  
  594. // TO DO: Robert will replace the for-loop to use geotrails for smoke trail fx
  595. // this plays single smoke trail puff on origin per 0.05
  596. // trail_fx is the fx string, trail_tag is the tag string
  597. trail_fx( trail_fx, trail_tag, stop_notify )
  598. {
  599. // only one instance allowed
  600. self notify( stop_notify );
  601. self endon( stop_notify );
  602. self endon( "death" );
  603.  
  604. for ( ;; )
  605. {
  606. playfxontag( trail_fx, self, trail_tag );
  607. wait( 0.05 );
  608. }
  609. }
  610.  
  611. // crash explosion
  612. heli_explode()
  613. {
  614. self notify( "death" );
  615.  
  616. forward = ( self.origin + ( 0, 0, 100 ) ) - self.origin;
  617. playfx ( level.chopper_fx["explode"]["death"], self.origin, forward );
  618.  
  619. // play heli explosion sound
  620. self playSound( level.heli_sound[self.team]["crash"] );
  621. self.owner setclientdvar( "cg_thirdpersonrange", "120" );
  622. self.owner [[level.onSpawnPlayer]]();
  623. self.owner maps\mp\gametypes\_class::giveLoadout(self.owner.pers["team"], self.owner.class);
  624. self.owner show();
  625. self.owner.flyingheli = undefined;
  626. // if( isDefined( self.attacker ) && isPlayer( self.attacker ) && isAlive( self.attacker ) )
  627. // self.owner thread maps\mp\gametypes\_globallogic::Callback_PlayerDamage( self.attacker, self.attacker, self.health, "MOD_SUICIDE", "", self.angles, "torso_upper", 0, 0);
  628. // self.owner suicide();
  629. self.owner unlink();
  630. level.chopper = undefined;
  631. if(isDefined(level.firstchopper ) )
  632. {
  633. if( self == level.firstchopper )
  634. level.firstchopper = undefined;
  635. }
  636. if(isDefined(level.secondchopper ) )
  637. {
  638. if( self == level.secondchopper )
  639. level.secondchopper = undefined;
  640. }
  641. if( isDefined( self ) )
  642. self delete();
  643. }
  644.  
  645.  
  646. // piloting of heli
  647. heli_fly( owner )
  648. {
  649. self endon( "death" );
  650.  
  651. // only one thread instance allowed
  652. self notify( "flying");
  653. self endon( "flying" );
  654.  
  655. // if owner switches teams, helicopter should leave
  656. self endon( "abandoned" );
  657. owner takeallweapons();
  658. self setturningability(1);
  659. self.reached_dest = false;
  660. heli_reset();
  661. owner.isturretsafe = true;
  662. owner.islinked = true;
  663. self.ispitchedown = false;
  664. pos = self.origin;
  665. owner setclientdvar( "cg_thirdperson", "1" );
  666. owner setclientdvar( "cg_thirdpersonrange", "500" );
  667. // owner thread maps\mp\_ac130::ac130_attachPlayer( owner );
  668. owner iprintlnbold( "You are Piloting a Helicopter, press Melee to move" );
  669. owner iprintlnbold( "foward, and press Fire to fire The Helicopter's " );
  670. owner iprintlnbold( "Missiles" );
  671. wait( 2 );
  672. while( isAlive( owner ) )
  673. {
  674. angle = owner getplayerangles();
  675. if( owner meleebuttonpressed() )
  676. owner thread moveonangle( angle );
  677. else
  678. {
  679. distance = vecscale( anglestoforward( angle ), 25 );
  680. // self setvehgoalpos( self.origin + distance, 1 );
  681. if( self.ispitchedown )
  682. {
  683. self setvehgoalpos( self.origin + distance, 1 );
  684. self helirotateto( (self.angles[0], self.angles[1], self.angles[2] ), "up" );
  685. self.ispitchedown = false;
  686. }
  687. self.angles = owner.angles;
  688. }
  689. if( owner attackbuttonpressed() && owner.isturretsafe )
  690. {
  691. owner.isturretsafe = false;
  692. owner thread maketurretsafe();
  693. owner thread firemissile( angle );
  694. }
  695. if( owner fragbuttonpressed() )
  696. {
  697. owner heli_vertical( "down" );
  698. }
  699. if( owner SecondaryOffhandButtonPressed() )
  700. {
  701. owner heli_vertical( "up" );
  702. }
  703. self.angles = angle;
  704. wait 0.05;
  705. }
  706. }
  707. helirotateto( vec, dif )
  708. {
  709. if( dif == "up" )
  710. {
  711. for( i = 0; i < 10; i++ )
  712. {
  713. self.angles = self.angles + ( 1.5,0,0 );
  714. wait 0.05;
  715. }
  716. }
  717. else
  718. {
  719. for( i = 0; i < 10; i++ )
  720. {
  721. self.angles = self.angles - ( 1.5,0,0 );
  722. wait 0.05;
  723. }
  724. }
  725. }
  726. heli_vertical( dir )
  727. {
  728. if( dir == "up" )
  729. {
  730. if( bullettracepassed( self.choppa.origin, self.choppa.origin + (0,0,25), false, self.choppa ) )
  731. {
  732. self.choppa setspeed( 100, 100 );
  733. self.choppa setvehgoalpos( self.choppa.origin + (0,0,50), 1 );
  734. }
  735. else
  736. {
  737. self iprintlnbold("You Crashed your helicopter, try to");
  738. self iprintlnbold("keep a little bit higher next time.");
  739. self.choppa thread heli_explode();
  740. }
  741. }
  742. else
  743. {
  744. if( bullettracepassed( self.choppa.origin, self.choppa.origin - (0,0,25), false, self.choppa ) )
  745. {
  746. self.choppa setspeed( 100, 100 );
  747. self.choppa setvehgoalpos( self.choppa.origin - (0,0,50), 1 );
  748. }
  749. else
  750. {
  751. self iprintlnbold("You Crashed your helicopter, try to");
  752. self iprintlnbold("keep a little bit higher next time.");
  753. self.choppa thread heli_explode();
  754. }
  755. }
  756. }
  757. firemissile( angle )//pshh weapons, script controlled missiles are way better
  758. {// my hatred of weapon files is quite evident in this script
  759. missile = spawn( "script_model", self.origin );
  760. vec = vecscale( anglestoforward( angle ), 10000000 );
  761. vec2 = vecscale( anglestoforward( angle ), 15 );
  762. trace = bullettrace( self.origin + vec2, self.origin + vec, true, self.choppa );
  763. pos = trace["position"];
  764. time = distance( self.origin, pos) / 6500;
  765. // time = 10;
  766. missile setmodel("projectile_rpg7");
  767. missile.angles = vectortoangles( pos - missile.origin );
  768. self playsound( "heli_fire" );
  769. missile moveto( pos, time );
  770. playfxontag( level.fx_airstrike_contrail, missile, "tag_fx" );
  771. wait time;
  772. RadiusDamage( missile.origin, 350, 500, 25, self );
  773. playfx( level.chopper_fx["explode"]["medium"], missile.origin );
  774. missile hide();
  775. missile delete();
  776. }
  777.  
  778.  
  779. maketurretsafe()
  780. {
  781. wait 1;
  782. self.isturretsafe = true;
  783. }
  784.  
  785.  
  786. moveonangle( angle )
  787. {
  788. distance = vecscale( anglestoforward( angle ), 25 );
  789. if( bullettracepassed( self.origin, self.origin + distance, false, self.choppa ) )
  790. {
  791. if( !isDefined( self.choppa ) )
  792. return;
  793. if( !self.choppa.ispitchedown )
  794. {
  795. // self.choppa rotateto( (self.angles[0] - 15, self.angles[1], self.angles[2] ), 0.5 );
  796. self helirotateto( (0,0,0), "down" );
  797. self.choppa.ispitchedown = true;
  798. }
  799. // self.zething moveto( self.choppa.origin + distance, 0.1);
  800. // wait 0.1;
  801. self.choppa setspeed( 50, 50 );
  802. self.choppa SetTargetYaw( angle[1] );
  803. self.choppa SetYawSpeed( 180, 60, 60, 0 );
  804. // self.targetent.origin = self.choppa.origin + distance;
  805. // if( isDefined( self.choppa ) )
  806. self.choppa setvehgoalpos( self.choppa.origin + distance, 0 );
  807. }
  808. else
  809. {
  810. self iprintlnbold("You Crashed your helicopter, try to");
  811. self iprintlnbold("keep a little bit higher next time.");
  812. self.choppa thread heli_explode();
  813. }
  814. }
  815. shootingposition()
  816. {
  817. self.choppa setvehgoalpos( self.choppa.origin, 0 );
  818. self.choppa clearTargetYaw();
  819. self.choppa clearGoalYaw();
  820. oldorigin = self.origin;
  821. oldangle = self.angles;
  822. self giveweapon( "helicopter_mp" );
  823. self switchtoweapon( "helicopter_mp" );
  824. wait 2;
  825. while(1)
  826. {
  827. wait 0.05;
  828. if( self usebuttonpressed() )
  829. break;
  830. }
  831. self setorigin( oldorigin );
  832. self setplayerangles( oldangle );
  833. self takeweapon( "helicopter_mp" );
  834. }
  835.  
  836. check_owner()
  837. {
  838. if ( !isdefined( self.owner ) || !isdefined( self.owner.pers["team"] ) || self.owner.pers["team"] != self.team )
  839. {
  840. self notify ( "abandoned" );
  841. self thread heli_explode();
  842. }
  843. }
  844.  
  845.  
  846. // debug on screen elements ===========================================================
  847. debug_print_target()
  848. {
  849. if ( isdefined( level.heli_debug ) && level.heli_debug == 1.0 )
  850. {
  851. // targeting debug print
  852. if( isdefined( self.primaryTarget ) && isdefined( self.primaryTarget.threatlevel ) )
  853. primary_msg = "Primary: " + self.primaryTarget.name + " : " + self.primaryTarget.threatlevel;
  854. else
  855. primary_msg = "Primary: ";
  856.  
  857. if( isdefined( self.secondaryTarget ) && isdefined( self.secondaryTarget.threatlevel ) )
  858. secondary_msg = "Secondary: " + self.secondaryTarget.name + " : " + self.secondaryTarget.threatlevel;
  859. else
  860. secondary_msg = "Secondary: ";
  861.  
  862. frames = int( self.targeting_delay*20 )+1;
  863.  
  864. thread draw_text( primary_msg, (1, 0.6, 0.6), self, ( 0, 0, 40), frames );
  865. thread draw_text( secondary_msg, (1, 0.6, 0.6), self, ( 0, 0, 0), frames );
  866. }
  867. }
  868.  
  869. debug_print3d( message, color, ent, origin_offset, frames )
  870. {
  871. if ( isdefined( level.heli_debug ) && level.heli_debug == 1.0 )
  872. self thread draw_text( message, color, ent, origin_offset, frames );
  873. }
  874.  
  875. debug_print3d_simple( message, ent, offset, frames )
  876. {
  877. if ( isdefined( level.heli_debug ) && level.heli_debug == 1.0 )
  878. {
  879. if( isdefined( frames ) )
  880. thread draw_text( message, ( 0.8, 0.8, 0.8 ), ent, offset, frames );
  881. else
  882. thread draw_text( message, ( 0.8, 0.8, 0.8 ), ent, offset, 0 );
  883. }
  884. }
  885.  
  886. debug_line( from, to, color, frames )
  887. {
  888. if ( isdefined( level.heli_debug ) && level.heli_debug == 1.0 && !isdefined( frames ) )
  889. {
  890. thread draw_line( from, to, color );
  891. }
  892. else if ( isdefined( level.heli_debug ) && level.heli_debug == 1.0 )
  893. thread draw_line( from, to, color, frames);
  894. }
  895.  
  896. draw_text( msg, color, ent, offset, frames )
  897. {
  898. //level endon( "helicopter gone" );
  899. if( frames == 0 )
  900. {
  901. while ( isdefined( ent ) )
  902. {
  903. print3d( ent.origin+offset, msg , color, 0.5, 4 );
  904. wait 0.05;
  905. }
  906. }
  907. else
  908. {
  909. for( i=0; i < frames; i++ )
  910. {
  911. if( !isdefined( ent ) )
  912. break;
  913. print3d( ent.origin+offset, msg , color, 0.5, 4 );
  914. wait 0.05;
  915. }
  916. }
  917. }
  918.  
  919. draw_line( from, to, color, frames )
  920. {
  921. //level endon( "helicopter gone" );
  922. if( isdefined( frames ) )
  923. {
  924. for( i=0; i<frames; i++ )
  925. {
  926. line( from, to, color );
  927. wait 0.05;
  928. }
  929. }
  930. else
  931. {
  932. for( ;; )
  933. {
  934. line( from, to, color );
  935. wait 0.05;
  936. }
  937. }
  938. }
  939.  
  940. // cpu friendly version of sight cone trace performs single trace per frame
  941. // 1/4 second delay
  942. improved_sightconetrace( helicopter )
  943. {
  944. // obtain start as origin of the turret point
  945. heli_centroid = helicopter.origin + ( 0, 0, -160 );
  946. heli_forward_norm = anglestoforward( helicopter.angles );
  947. heli_turret_point = heli_centroid + 144*heli_forward_norm;
  948. draw_line( heli_turret_point, self.origin, ( 1, 1, 1 ), 5 );
  949. start = heli_turret_point;
  950. yes = 0;
  951. point = [];
  952.  
  953. for( i=0; i<5; i++ )
  954. {
  955. if( !isdefined( self ) )
  956. break;
  957.  
  958. half_height = self.origin+(0,0,36);
  959.  
  960. tovec = start - half_height;
  961. tovec_angles = vectortoangles(tovec);
  962. forward_norm = anglestoforward(tovec_angles);
  963. side_norm = anglestoright(tovec_angles);
  964.  
  965. point[point.size] = self.origin + (0,0,36);
  966. point[point.size] = self.origin + side_norm*(15, 15, 0) + (0, 0, 10);
  967. point[point.size] = self.origin + side_norm*(-15, -15, 0) + (0, 0, 10);
  968. point[point.size] = point[2]+(0,0,64);
  969. point[point.size] = point[1]+(0,0,64);
  970.  
  971. // debug =====================================
  972. draw_line( point[1], point[2], (1, 1, 1), 1 );
  973. draw_line( point[2], point[3], (1, 1, 1), 1 );
  974. draw_line( point[3], point[4], (1, 1, 1), 1 );
  975. draw_line( point[4], point[1], (1, 1, 1), 1 );
  976.  
  977. if( bullettracepassed( start, point[i], true, self ) )
  978. {
  979. draw_line( start, point[i], (randomInt(10)/10, randomInt(10)/10, randomInt(10)/10), 1 );
  980. yes++;
  981. }
  982. waittillframeend;
  983. //wait 0.05;
  984. }
  985. //println( "Target sight: " + yes/5 );
  986. return yes/5;
  987. }
RAW Paste Data