Advertisement
Guest User

Untitled

a guest
Feb 22nd, 2019
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 24.61 KB | None | 0 0
  1. #include maps\mp\_utility;
  2. #include maps\mp\gametypes\_hud_util;
  3. #include common_scripts\utility;
  4. init()
  5. {
  6. precacheModel( "jokers_stealth" );
  7.  
  8. // level.scr_stealthbomber_height = getdvarx( "scr_stealthbomber_height", "int", 1000, -10000, 50000 );
  9.  
  10. level.bomberfx = loadfx ("explosions/clusterbomb");
  11. level.bombeffect = loadfx ("explosions/artilleryExp_dirt_brown");
  12. level.bombstrike = loadfx ("explosions/wall_explosion_pm_a");
  13. level.fx_airstrike_contrail = loadfx ("smoke/smoke_geotrail_javelin");
  14.  
  15. game["dialog"]["airstrike_inbound"] = "airstrike_friendly";
  16. game["dialog"]["enemy_airstrike_inbound"] = "airstrike_enemy";
  17. }
  18. distance2d(a,b)
  19. {
  20. return distance((a[0],a[1],0), (b[0],b[1],0));
  21. }
  22.  
  23. doBomb(origin, owner, team)
  24. {
  25. num = 17 + randomint(3);
  26.  
  27. level.bomberInProgress = true;
  28. trace = bullettrace(origin, origin + (0,0,-10000), false, undefined);
  29. targetpos = trace["position"];
  30.  
  31. yaw = getBestBomberDirection( targetpos );
  32.  
  33. team = self.pers["team"];
  34. otherTeam = level.otherTeam[team];
  35.  
  36. if ( level.teambased )
  37. {
  38. players = level.players;
  39. if ( !level.hardcoreMode )
  40. {
  41. for(i = 0; i < players.size; i++)
  42. {
  43. if(isalive(players[i]) && (isdefined(players[i].pers["team"])) && (players[i].pers["team"] == team))
  44. {
  45. if ( pointIsInAirstrikeArea( players[i].origin, targetpos, yaw ) )
  46. players[i] iprintlnbold(&"STEALTH BOMBERS Near Your Position");
  47. }
  48. }
  49. }
  50.  
  51. maps\mp\gametypes\_globallogic::leaderDialog( "airstrike_inbound", team );
  52. maps\mp\gametypes\_globallogic::leaderDialog( "enemy_airstrike_inbound", otherteam );
  53. for ( i = 0; i < level.players.size; i++ )
  54. {
  55. player = level.players[i];
  56. playerteam = player.pers["team"];
  57. if ( isdefined( playerteam ) )
  58. {
  59. if ( playerteam == team )
  60. player iprintln( &"STEALTH BOMBERS Ready to Deploy", owner );
  61. }
  62. }
  63. }
  64. else
  65. {
  66. owner maps\mp\gametypes\_globallogic::leaderDialogOnPlayer( "airstrike_inbound" );
  67. /*
  68. for ( i = 0; i < level.players.size; i++ )
  69. {
  70. if ( level.players[i] != owner && isDefined( level.players[i].team ) )
  71. level.players[i] maps\mp\gametypes\_globallogic::leaderDialogOnPlayer( "enemy_airstrike_inbound" );
  72. }
  73. */
  74.  
  75. if ( !level.hardcoreMode )
  76. {
  77. if ( pointIsInAirstrikeArea( owner.origin, targetpos, yaw ) )
  78. owner iprintlnbold(&"STEALTH BOMBERS Near Your Position");
  79. }
  80. }
  81.  
  82. wait 2;
  83.  
  84. if ( !isDefined( owner ) )
  85. {
  86. level.bomberInProgress = undefined;
  87. return;
  88. }
  89.  
  90. owner notify ( "begin_airstrike" );
  91.  
  92. dangerCenter = spawnstruct();
  93. dangerCenter.origin = targetpos;
  94. dangerCenter.forward = anglesToForward( (0,yaw,0) );
  95. level.artilleryDangerCenters[ level.artilleryDangerCenters.size ] = dangerCenter;
  96. /# level thread debugArtilleryDangerCenters(); #/
  97.  
  98. wait 1;
  99. callBomber( owner, targetpos, yaw );
  100. wait 1;
  101. callBomber( owner, targetpos + anglestoright( (0,yaw,0) )*500, yaw );
  102. wait 2;
  103. callBomber( owner, targetpos - anglestoright ( (0, yaw, 0) )*500, yaw );
  104.  
  105. found = false;
  106. newarray = [];
  107. for ( i = 0; i < level.artilleryDangerCenters.size; i++ )
  108. {
  109. if ( !found && level.artilleryDangerCenters[i].origin == targetpos )
  110. {
  111. found = true;
  112. continue;
  113. }
  114.  
  115. newarray[ newarray.size ] = level.artilleryDangerCenters[i];
  116. }
  117. assert( found );
  118. assert( newarray.size == level.artilleryDangerCenters.size - 1 );
  119. level.artilleryDangerCenters = newarray;
  120.  
  121. level.bomberInProgress = undefined;
  122. }
  123.  
  124. getAirstrikeDanger( point )
  125. {
  126. danger = 0;
  127. for ( i = 0; i < level.artilleryDangerCenters.size; i++ )
  128. {
  129. origin = level.artilleryDangerCenters[i].origin;
  130. forward = level.artilleryDangerCenters[i].forward;
  131.  
  132. danger += getSingleAirstrikeDanger( point, origin, forward );
  133. }
  134. return danger;
  135. }
  136.  
  137. getSingleAirstrikeDanger( point, origin, forward )
  138. {
  139. center = origin + level.artilleryDangerForwardPush * level.artilleryDangerMaxRadius * forward;
  140.  
  141. diff = point - center;
  142. diff = (diff[0], diff[1], 0);
  143.  
  144. forwardPart = vectorDot( diff, forward ) * forward;
  145. perpendicularPart = diff - forwardPart;
  146.  
  147. circlePos = perpendicularPart + forwardPart / level.artilleryDangerOvalScale;
  148.  
  149. /* /#
  150. if ( getdvar("scr_airstrikedebug") == "1" )
  151. {
  152. thread airstrikeLine( center, center + perpendicularPart, (1,1,1), 30 );
  153. thread airstrikeLine( center + perpendicularPart, center + circlePos, (1,1,1), 30 );
  154. thread airstrikeLine( center + circlePos, point, (.5,.5,.5), 30 );
  155. }
  156. #/ */
  157.  
  158. distsq = lengthSquared( circlePos );
  159.  
  160. if ( distsq > level.artilleryDangerMaxRadius * level.artilleryDangerMaxRadius )
  161. return 0;
  162.  
  163. if ( distsq < level.artilleryDangerMinRadius * level.artilleryDangerMinRadius )
  164. return 1;
  165.  
  166. dist = sqrt( distsq );
  167. distFrac = (dist - level.artilleryDangerMinRadius) / (level.artilleryDangerMaxRadius - level.artilleryDangerMinRadius);
  168.  
  169. assertEx( distFrac >= 0 && distFrac <= 1, distFrac );
  170.  
  171. return 1 - distFrac;
  172. }
  173.  
  174. pointIsInAirstrikeArea( point, targetpos, yaw )
  175. {
  176. return distance2d( point, targetpos ) <= level.artilleryDangerMaxRadius * 1.25;
  177. }
  178.  
  179. losRadiusDamage(pos, radius, max, min, owner, eInflictor)
  180. {
  181. ents = maps\mp\gametypes\_weapons::getDamageableEnts(pos, radius, true);
  182.  
  183. for (i = 0; i < ents.size; i++)
  184. {
  185. if (ents[i].entity == self)
  186. continue;
  187.  
  188. dist = distance(pos, ents[i].damageCenter);
  189.  
  190. if ( ents[i].isPlayer )
  191. {
  192. // check if there is a path to this entity 130 units above his feet. if not, they're probably indoors
  193. indoors = !maps\mp\gametypes\_weapons::weaponDamageTracePassed( ents[i].entity.origin, ents[i].entity.origin + (0,0,130), 0, undefined );
  194. if ( !indoors )
  195. {
  196. indoors = !maps\mp\gametypes\_weapons::weaponDamageTracePassed( ents[i].entity.origin + (0,0,130), pos + (0,0,130 - 16), 0, undefined );
  197. if ( indoors )
  198. {
  199. // give them a distance advantage for being indoors.
  200. dist *= 4;
  201. if ( dist > radius )
  202. continue;
  203. }
  204. }
  205. }
  206.  
  207. ents[i].damage = int(max + (min-max)*dist/radius);
  208. ents[i].pos = pos;
  209. ents[i].damageOwner = owner;
  210. ents[i].eInflictor = eInflictor;
  211. level.airStrikeDamagedEnts[level.airStrikeDamagedEntsCount] = ents[i];
  212. level.airStrikeDamagedEntsCount++;
  213. }
  214.  
  215. thread BomberDamageEntsThread();
  216. }
  217.  
  218. BomberDamageEntsThread()
  219. {
  220. self notify ( "BomberDamageEntsThread" );
  221. self endon ( "BomberDamageEntsThread" );
  222.  
  223. for ( ; level.airstrikeDamagedEntsIndex < level.airstrikeDamagedEntsCount; level.airstrikeDamagedEntsIndex++ )
  224. {
  225. if ( !isDefined( level.airstrikeDamagedEnts[level.airstrikeDamagedEntsIndex] ) )
  226. continue;
  227.  
  228. ent = level.airstrikeDamagedEnts[level.airstrikeDamagedEntsIndex];
  229.  
  230. if ( !isDefined( ent.entity ) )
  231. continue;
  232.  
  233. if ( !ent.isPlayer || isAlive( ent.entity ) )
  234. {
  235. ent maps\mp\gametypes\_weapons::damageEnt(
  236. ent.eInflictor, // eInflictor = the entity that causes the damage (e.g. a claymore)
  237. ent.damageOwner, // eAttacker = the player that is attacking
  238. ent.damage, // iDamage = the amount of damage to do
  239. "MOD_PROJECTILE_SPLASH", // sMeansOfDeath = string specifying the method of death (e.g. "MOD_PROJECTILE_SPLASH")
  240. "stealth_mp", // sWeapon = string specifying the weapon used (e.g. "claymore_mp")
  241. ent.pos, // damagepos = the position damage is coming from
  242. vectornormalize(ent.damageCenter - ent.pos) // damagedir = the direction damage is moving in
  243. );
  244.  
  245. level.airstrikeDamagedEnts[level.airstrikeDamagedEntsIndex] = undefined;
  246.  
  247. if ( ent.isPlayer )
  248. wait ( 0.05 );
  249. }
  250. else
  251. {
  252. level.airstrikeDamagedEnts[level.airstrikeDamagedEntsIndex] = undefined;
  253. }
  254. }
  255. }
  256.  
  257. radiusArtilleryShellshock(pos, radius, maxduration,minduration)
  258. {
  259. players = level.players;
  260. for (i = 0; i < players.size; i++)
  261. {
  262. if (!isalive(players[i]))
  263. continue;
  264.  
  265. playerpos = players[i].origin + (0,0,32);
  266. dist = distance(pos, playerpos);
  267. if (dist < radius) {
  268. duration = int(maxduration + (minduration-maxduration)*dist/radius);
  269.  
  270. players[i] thread artilleryShellshock("default", duration);
  271. }
  272. }
  273. }
  274.  
  275. artilleryShellshock(type, duration)
  276. {
  277. if (isdefined(self.beingArtilleryShellshocked) && self.beingArtilleryShellshocked)
  278. return;
  279. self.beingArtilleryShellshocked = true;
  280.  
  281. self shellshock(type, duration);
  282. wait(duration + 1);
  283.  
  284. self.beingArtilleryShellshocked = false;
  285. }
  286.  
  287. /#
  288. airstrikeLine( start, end, color, duration )
  289. {
  290. frames = duration * 20;
  291. for ( i = 0; i < frames; i++ )
  292. {
  293. line(start,end,color);
  294. wait .05;
  295. }
  296. }
  297.  
  298. traceBomb()
  299. {
  300. self endon("death");
  301. prevpos = self.origin;
  302. while(1)
  303. {
  304. thread airstrikeLine( prevpos, self.origin, (.5,1,0), 20 );
  305. prevpos = self.origin;
  306. wait .2;
  307. }
  308. }
  309. #/
  310.  
  311. doBombStrike( owner, requiredDeathCount, bombsite, startPoint, endPoint, bombTime, flyTime, direction , airStrikeType)
  312. {
  313. // plane spawning randomness = up to 125 units, biased towards 0
  314. // radius of bomb damage is 512
  315.  
  316. if ( !isDefined( owner ) )
  317. return;
  318.  
  319. startPathRandomness = 150;
  320. endPathRandomness = 150;
  321.  
  322. pathStart = startPoint + ( (randomfloat(2) - 2)*startPathRandomness, (randomfloat(2) - 2)*startPathRandomness, 0 );
  323. pathEnd = endPoint + ( (randomfloat(2) - 2)*endPathRandomness , (randomfloat(2) - 2)*endPathRandomness , 0 );
  324.  
  325. //Assume no change in height on flightpath
  326. height = (startpoint[2] - bombsite[2]);
  327. midpoint = bombsite + (0,0,height);
  328. totaldistance = distance2D(pathstart, pathend);
  329. speed = totaldistance / flytime; //Units per second
  330.  
  331. //Assume 45 degree drop angle to find range in xy from bombsite to releasepoint.
  332. range = height / sin(45) * cos(45);
  333. releasepoint = midpoint - anglestoforward(direction) * range;
  334.  
  335. //Using plane velocity calculate time from start point to release point.
  336. //New bombtime replaces original.
  337. releaseDistance = distance2D(releasepoint, pathStart);
  338. bombtime = releaseDistance / speed;
  339.  
  340. // Spawn the planes
  341. plane = spawnplane( owner, "script_model", pathStart );
  342. plane setModel( "jokers_stealth" );
  343. plane.angles = direction;
  344.  
  345. plane spawnStealthFx();
  346.  
  347. plane moveTo( pathEnd, flyTime, 0, 0 );
  348.  
  349. thread stealthBomber_killCam( plane, pathEnd, flyTime, airStrikeType );
  350.  
  351. thread callBomber_planeSound( plane, bombsite );
  352.  
  353. for ( b = 0; b < 20; b++ ) {
  354. thread callStrike_bombEffect( plane, bombTime - 0.1, owner, requiredDeathCount );
  355. wait 0.09;
  356. }
  357.  
  358. // Delete the plane after its flyby
  359. wait flyTime;
  360. plane notify( "delete" );
  361. plane delete();
  362. }
  363.  
  364. callStrike_bombEffect( plane, launchTime, owner, requiredDeathCount )
  365. {
  366. wait ( launchTime );
  367.  
  368. plane thread play_sound_in_space( "veh_mig29_sonic_boom" );
  369. bomb = spawnbomb( plane.origin, plane.angles );
  370. bomb.ownerRequiredDeathCount = requiredDeathCount;
  371.  
  372. //RUN TRACE TO FIND HIT POINT. ASSUME 45 DEGREE ANGLE
  373. trace = bullettrace( bomb.origin, bomb.origin + anglestoForward( (45, bomb.angles[1], 0) ) * 5000, false, plane);
  374. hit = trace["position"] + (0,0,50);
  375. bomb moveto(hit, 2, 2);
  376. bomb rotateTo( (45,bomb.angles[1], bomb.angles[2]), 2);
  377.  
  378. /#
  379. if ( getdvar("scr_airstrikedebug") == "1" )
  380. bomb thread traceBomb();
  381. #/
  382.  
  383. wait ( 0.85 );
  384. bomb.killCamEnt = spawn( "script_model", bomb.origin + (0,0,200) );
  385. bomb.killCamEnt.angles = bomb.angles;
  386. bomb.killCamEnt thread deleteAfterTime( 10.0 );
  387. bomb.killCamEnt moveTo( bomb.killCamEnt.origin + vector_scale( anglestoforward( plane.angles ), 1000 ), 3.0 );
  388. wait ( 0.15 );
  389.  
  390.  
  391. wait 1; // 2 SECONDS MINUS THE KILLCAM WAIT TIMES.
  392.  
  393. newBomb = spawn( "script_model", bomb.origin );
  394. newBomb setModel( "tag_origin" );
  395. newBomb.origin = bomb.origin;
  396. newBomb.angles = bomb.angles;
  397.  
  398. bomb setModel( "tag_origin" );
  399. wait (0.05);
  400.  
  401.  
  402. bombOrigin = newBomb.origin;
  403. bombAngles = newBomb.angles;
  404. playfxontag( level.bomberfx, newBomb, "tag_origin" );
  405.  
  406. wait ( 0.05 );
  407. repeat = 12; //BOMBLETS
  408. minAngles = 55;
  409. maxAngles = 100;
  410. angleDiff = (maxAngles - minAngles) / repeat;
  411.  
  412. for( i = 0; i < repeat; i++ )
  413. {
  414. traceDir = anglesToForward( bombAngles + (maxAngles-(angleDiff * i),randomInt( 10 )-5,0) );
  415. traceEnd = bombOrigin + vector_scale( traceDir, 100 );
  416. trace = bulletTrace( bombOrigin, traceEnd, false, undefined );
  417.  
  418. traceHit = trace["position"];
  419.  
  420. /#
  421. if ( getdvar("scr_airstrikedebug") == "1" )
  422. thread airstrikeLine( bombOrigin, traceHit, (1,0,0), 20 );
  423. #/
  424.  
  425. thread losRadiusDamage( traceHit + (0,0,16), 512, 200, 100, owner, bomb ); // targetpos, radius, maxdamage, mindamage, player causing damage, entity that player used to cause damage
  426.  
  427. if ( i%3 == 0 )
  428. {
  429. thread playsoundinspace( "artillery_impact", traceHit );
  430. playRumbleOnPosition( "artillery_rumble", traceHit );
  431. earthquake( 0.7, 0.75, traceHit, 1000 );
  432. }
  433.  
  434. wait ( 0.05 );
  435. }
  436. wait ( 5.0 );
  437. newBomb delete();
  438. bomb delete();
  439. }
  440. spawnbomb( origin, angles )
  441. {
  442. bomb = spawn( "script_model", origin );
  443. bomb.angles = angles;
  444. bomb setModel( "projectile_cbu97_clusterbomb" );
  445.  
  446. bomb thread playPlaneFx(); //----------------------------)
  447.  
  448. return bomb;
  449. }
  450.  
  451. deleteAfterTime( time )
  452. {
  453. self endon ( "death" );
  454. wait ( 10.0 );
  455.  
  456. self delete();
  457. }
  458.  
  459. drawLine( start, end, timeSlice )
  460. {
  461. drawTime = int(timeSlice * 20);
  462. for( time = 0; time < drawTime; time++ )
  463. {
  464. line( start, end, (1,0,0),false, 1 );
  465. wait ( 0.05 );
  466. }
  467. }
  468.  
  469. playPlaneFx()
  470. {
  471. self endon ( "death" );
  472.  
  473. wait 0.1;
  474.  
  475. playfxontag( level.fx_airstrike_contrail, self, "tag_fx" );
  476. }
  477.  
  478. stealthBomber_killCam( plane, pathEnd, flyTime, typeOfStrike )
  479. {
  480. plane waittill ( "begin_airstrike" );
  481.  
  482. planedir = anglesToForward( plane.angles );
  483.  
  484. killCamEnt = spawn( "script_model", plane.origin + (0,0,100) - planedir * 200 );
  485. plane.killCamEnt = killCamEnt;
  486. plane.airstrikeType = typeOfStrike;
  487. killCamEnt.startTime = gettime();
  488. killCamEnt thread deleteAfterTime( 15.0 );
  489.  
  490. killCamEnt linkTo( plane, "tag_origin", (-256,768,768), ( 0,0,0 ) );
  491. }
  492.  
  493. getBestBomberDirection( hitpos )
  494. {
  495. if ( getdvarint("scr_airstrikebestangle") != 1 )
  496. return randomfloat( 360 );
  497.  
  498. checkPitch = -25;
  499.  
  500. numChecks = 15;
  501.  
  502. startpos = hitpos + (0,0,64);
  503.  
  504. bestangle = randomfloat( 360 );
  505. bestanglefrac = 0;
  506.  
  507. fullTraceResults = [];
  508.  
  509. for ( i = 0; i < numChecks; i++ )
  510. {
  511. yaw = ((i * 1.0 + randomfloat(1)) / numChecks) * 360.0;
  512. angle = (checkPitch, yaw + 180, 0);
  513. dir = anglesToForward( angle );
  514.  
  515. endpos = startpos + dir * 1500;
  516.  
  517. trace = bullettrace( startpos, endpos, false, undefined );
  518.  
  519. if ( trace["fraction"] > bestanglefrac )
  520. {
  521. bestanglefrac = trace["fraction"];
  522. bestangle = yaw;
  523.  
  524. if ( trace["fraction"] >= 1 )
  525. fullTraceResults[ fullTraceResults.size ] = yaw;
  526. }
  527.  
  528. if ( i % 3 == 0 )
  529. wait .05;
  530. }
  531.  
  532. if ( fullTraceResults.size > 0 )
  533. return fullTraceResults[ randomint( fullTraceResults.size ) ];
  534.  
  535. return bestangle;
  536. }
  537.  
  538. callBomber( owner, coord, yaw )
  539. {
  540. // Get starting and ending point for the plane
  541. direction = ( 0 , yaw , 0 );
  542. planeHalfDistance = 10000;
  543. planeBombExplodeDistance = 500;
  544. planeFlyHeight = 500.0 + randomFloat(500.0);
  545. planeFlySpeed = 1000.0 + randomFloat(1000.0);
  546.  
  547. if ( isdefined( level.airstrikeHeightScale ) )
  548. {
  549. planeFlyHeight *= level.airstrikeHeightScale;
  550. }
  551.  
  552. startPoint = coord + vector_scale( anglestoforward( direction ), -1 * planeHalfDistance );
  553. startPoint += ( 0, 0, planeFlyHeight );
  554.  
  555. endPoint = coord + vector_scale( anglestoforward( direction ), planeHalfDistance );
  556. endPoint += ( 0, 0, planeFlyHeight );
  557.  
  558. // Make the plane fly by
  559. d = length( startPoint - endPoint );
  560. flyTime = ( d / planeFlySpeed );
  561.  
  562. // bomb explodes planeBombExplodeDistance after the plane passes the center
  563. d = abs( d/2 + planeBombExplodeDistance );
  564. bombTime = ( d / planeFlySpeed );
  565.  
  566. owner endon("disconnect");
  567.  
  568. requiredDeathCount = owner.deathCount;
  569.  
  570. level.airstrikeDamagedEnts = [];
  571. level.airStrikeDamagedEntsCount = 0;
  572. level.airStrikeDamagedEntsIndex = 0;
  573. level thread doBombStrike( owner, requiredDeathCount, coord, startPoint+(0,0,randomInt(1000)), endPoint+(0,0,randomInt(1000)), bombTime, flyTime, direction );
  574. }
  575.  
  576. callEscort( owner, coord, yaw, bombtime, requiredDeathCount )
  577. {
  578. // Get starting and ending point for the plane
  579. direction = ( 0 , yaw , 0 );
  580. planeHalfDistance = 10000;
  581. planeFlyHeight = 500.0 + randomFloat(500.0);
  582. planeFlySpeed = 1000.0 + randomFloat(1000.0);
  583.  
  584. if ( isdefined( level.airstrikeHeightScale ) )
  585. {
  586. planeFlyHeight *= level.airstrikeHeightScale;
  587. }
  588.  
  589. startPoint = coord + vector_scale( anglestoforward( direction ), -1 * planeHalfDistance );
  590. startPoint += ( 0, 0, planeFlyHeight );
  591.  
  592. endPoint = coord + vector_scale( anglestoforward( direction ), planeHalfDistance );
  593. endPoint += ( 0, 0, planeFlyHeight );
  594.  
  595. // Make the plane fly by
  596. d = length( startPoint - endPoint );
  597. flyTime = ( d / planeFlySpeed );
  598.  
  599. owner endon("disconnect");
  600.  
  601. level thread doFlyby( owner, requiredDeathCount, coord, startPoint+(0,0,randomInt(1000)), endPoint+(0,0,randomInt(1000)), bombTime, flyTime, direction );
  602.  
  603. }
  604.  
  605. doFlyby( owner, requiredDeathCount, bombsite, startPoint, endPoint, bombTime, flyTime, direction , airStrikeType)
  606. {
  607. // plane spawning randomness = up to 125 units, biased towards 0
  608. if ( !isDefined( owner ) )
  609. return;
  610.  
  611. startPathRandomness = 150;
  612. endPathRandomness = 150;
  613.  
  614. pathStart = startPoint + ( (randomfloat(2) - 2)*startPathRandomness, (randomfloat(2) - 2)*startPathRandomness, 0 );
  615. pathEnd = endPoint + ( (randomfloat(2) - 2)*endPathRandomness , (randomfloat(2) - 2)*endPathRandomness , 0 );
  616.  
  617. //Assume no change in height on flightpath
  618. height = (startpoint[2] - bombsite[2]);
  619. totaldistance = distance2D(pathstart, pathend);
  620. speed = totaldistance / flytime; //Units per second
  621.  
  622. // Spawn the planes
  623. plane = spawnplane( owner, "script_model", pathStart );
  624. plane setModel( "jokers_stealth" ); //CHANGE THE MODEL TO THE MIG
  625. plane.angles = direction;
  626.  
  627. plane spawnStealthFx(); //IS THIS NEEDED?
  628. plane moveTo( pathEnd, flyTime, 0, 0 );
  629.  
  630. thread callBomber_planeSound( plane, bombsite ); //CHANGE TO MIG SOUND
  631.  
  632. // Delete the plane after its flyby
  633. wait flyTime;
  634. plane notify( "delete" );
  635. plane delete();
  636. }
  637.  
  638. callBomber_bomb( bombTime, coord, repeat, owner )
  639. {
  640. accuracyRadius = 512;
  641.  
  642. for( i = 0; i < repeat; i++ )
  643. {
  644. randVec = ( 0, randomint( 360 ), 0 );
  645. bombPoint = coord + vector_scale( anglestoforward( randVec ), accuracyRadius );
  646.  
  647. wait bombTime;
  648.  
  649. thread playsoundinspace( "artillery_impact", bombPoint );
  650. radiusArtilleryShellshock( bombPoint, 512, 8, 4);
  651. losRadiusDamage( bombPoint + (0,0,16), 768, 300, 50, owner); // targetpos, radius, maxdamage, mindamage, player causing damage
  652. }
  653. }
  654.  
  655. callBomber_planeSound( plane, bombsite )
  656. {
  657. plane thread play_loop_sound_on_entity( "veh_mig29_dist_loop" );
  658. while( !targetisclose( plane, bombsite ) )
  659. wait 0.05;
  660. plane notify ( "stop sound" + "veh_mig29_dist_loop" );
  661. plane thread play_loop_sound_on_entity( "veh_mig29_close_loop" );
  662. while( targetisinfront( plane, bombsite ) )
  663. wait 0.05;
  664. wait .5;
  665. //plane thread play_sound_in_space( "veh_mig29_sonic_boom" );
  666. while( targetisclose( plane, bombsite ) )
  667. wait 0.05;
  668. plane notify ( "stop sound" + "veh_mig29_close_loop" );
  669. plane thread play_loop_sound_on_entity( "veh_mig29_dist_loop" );
  670. plane waittill( "delete" );
  671. plane notify ( "stop sound" + "veh_mig29_dist_loop" );
  672. }
  673.  
  674. playSoundinSpace (alias, origin, master)
  675. {
  676. org = spawn ("script_origin",(0,0,1));
  677. if (!isdefined (origin))
  678. origin = self.origin;
  679. org.origin = origin;
  680. if (isdefined(master) && master)
  681. org playsoundasmaster (alias);
  682. else
  683. org playsound (alias);
  684. wait ( 10.0 );
  685. org delete();
  686. }
  687.  
  688. play_loop_sound_on_entity(alias, offset)
  689. {
  690. org = spawn ("script_origin",(0,0,0));
  691. org endon ("death");
  692. thread delete_on_death (org);
  693. if (isdefined (offset))
  694. {
  695. org.origin = self.origin + offset;
  696. org.angles = self.angles;
  697. org linkto (self);
  698. }
  699. else
  700. {
  701. org.origin = self.origin;
  702. org.angles = self.angles;
  703. org linkto (self);
  704. }
  705.  
  706. org playloopsound (alias);
  707. self waittill ("stop sound" + alias);
  708. org stoploopsound (alias);
  709. org delete();
  710. }
  711.  
  712. selectBomberLocation( hardpointType )
  713. {
  714. self beginLocationSelection( "map_artillery_selector", level.artilleryDangerMaxRadius * 1.2 );
  715. self.selectingLocation = true;
  716.  
  717. self thread endSelectionOn( "cancel_location" );
  718. self thread endSelectionOn( "death" );
  719. self thread endSelectionOn( "disconnect" );
  720. self thread endSelectionOn( "used" );
  721. self thread endSelectionOnGameEnd();
  722.  
  723. self endon( "stop_location_selection" );
  724. self waittill( "confirm_location", location );
  725.  
  726. if ( isDefined( level.bomberInProgress ) )
  727. {
  728. self iPrintLnBold( level.hardpointHints["bomber_mp_not_available"] );
  729. self thread stopBomberLocationSelection( false );
  730. return false;
  731. }
  732.  
  733. self.eow_hardpointtype = hardpointtype;
  734. self thread finishBomberUsage( location, ::useBomber );
  735. return true;
  736. }
  737.  
  738. finishBomberUsage( location, usedCallback )
  739. {
  740. self notify( "used" );
  741. wait ( 0.05 );
  742. self thread stopBomberLocationSelection( false );
  743. self thread [[usedCallback]]( location );
  744. return true;
  745. }
  746.  
  747. endSelectionOn( waitfor )
  748. {
  749. self endon( "stop_location_selection" );
  750. self waittill( waitfor );
  751. self thread stopBomberLocationSelection( (waitfor == "disconnect") );
  752. }
  753.  
  754. endSelectionOnGameEnd()
  755. {
  756. self endon( "stop_location_selection" );
  757. level waittill( "game_ended" );
  758. self thread stopBomberLocationSelection( false );
  759. }
  760.  
  761. stopBomberLocationSelection( disconnected )
  762. {
  763. if ( !disconnected )
  764. {
  765. self endLocationSelection();
  766. self.selectingLocation = undefined;
  767. }
  768. self notify( "stop_location_selection" );
  769. }
  770.  
  771. useBomber( pos )
  772. {
  773. trace = bullettrace( self.origin + (0,0,10000), self.origin, false, undefined );
  774. pos = (pos[0], pos[1], trace["position"][2] - 514);
  775.  
  776. thread doBomb( pos, self, self.pers["team"] );
  777. }
  778.  
  779. flat_origin(org)
  780. {
  781. rorg = (org[0],org[1],0);
  782. return rorg;
  783. }
  784.  
  785. flat_angle(angle)
  786. {
  787. rangle = (0,angle[1],0);
  788. return rangle;
  789. }
  790.  
  791. targetisclose(other, target)
  792. {
  793. infront = targetisinfront(other, target);
  794. if(infront)
  795. dir = 1;
  796. else
  797. dir = -1;
  798. a = flat_origin(other.origin);
  799. b = a+vector_scale(anglestoforward(flat_angle(other.angles)), (dir*100000));
  800. point = pointOnSegmentNearestToPoint(a,b, target);
  801. dist = distance(a,point);
  802. if (dist < 3000)
  803. return true;
  804. else
  805. return false;
  806. }
  807.  
  808. targetisinfront(other, target)
  809. {
  810. forwardvec = anglestoforward(flat_angle(other.angles));
  811. normalvec = vectorNormalize(flat_origin(target)-other.origin);
  812. dot = vectordot(forwardvec,normalvec);
  813. if(dot > 0)
  814. return true;
  815. else
  816. return false;
  817. }
  818.  
  819. delete_on_death (ent)
  820. {
  821. ent endon ("death");
  822. self waittill ("death");
  823. if (isdefined (ent))
  824. ent delete();
  825. }
  826.  
  827.  
  828. spawnStealthFx()
  829. {
  830. self endon ( "death" );
  831.  
  832. wait .07;
  833. playfxontag( level.fx_heli_green_blink, self, "tag_left_wingtip" );
  834. playfxontag( level.fx_heli_green_blink, self, "tag_right_wingtip" );
  835. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement