Advertisement
Guest User

Untitled

a guest
Sep 29th, 2010
604
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 63.93 KB | None | 0 0
  1. #include common_scripts\utility;
  2. #include maps\mp\_utility;
  3.  
  4.  
  5. attachmentGroup( attachmentName )
  6. {
  7. return tableLookup( "mp/attachmentTable.csv", 4, attachmentName, 2 );
  8. }
  9.  
  10. getAttachmentList()
  11. {
  12. attachmentList = [];
  13.  
  14. index = 0;
  15. attachmentName = tableLookup( "mp/attachmentTable.csv", 9, index, 4 );
  16.  
  17. while ( attachmentName != "" )
  18. {
  19. attachmentList[attachmentList.size] = attachmentName;
  20.  
  21. index++;
  22. attachmentName = tableLookup( "mp/attachmentTable.csv", 9, index, 4 );
  23. }
  24.  
  25. return alphabetize( attachmentList );
  26. }
  27.  
  28. init()
  29. {
  30. level.scavenger_altmode = true;
  31. level.scavenger_secondary = true;
  32.  
  33. // 0 is not valid
  34. level.maxPerPlayerExplosives = max( getIntProperty( "scr_maxPerPlayerExplosives", 2 ), 1 );
  35. level.riotShieldXPBullets = getIntProperty( "scr_riotShieldXPBullets", 15 );
  36.  
  37. switch ( getIntProperty( "perk_scavengerMode", 0 ) )
  38. {
  39. case 1: // disable altmode
  40. level.scavenger_altmode = false;
  41. break;
  42.  
  43. case 2: // disable secondary
  44. level.scavenger_secondary = false;
  45. break;
  46.  
  47. case 3: // disable altmode and secondary
  48. level.scavenger_altmode = false;
  49. level.scavenger_secondary = false;
  50. break;
  51. }
  52.  
  53. attachmentList = getAttachmentList();
  54.  
  55. // assigns weapons with stat numbers from 0-149
  56. // attachments are now shown here, they are per weapon settings instead
  57.  
  58. max_weapon_num = 149;
  59.  
  60. level.weaponList = [];
  61. for( weaponId = 0; weaponId <= max_weapon_num; weaponId++ )
  62. {
  63. weapon_name = tablelookup( "mp/statstable.csv", 0, weaponId, 4 );
  64. if( weapon_name == "" )
  65. continue;
  66.  
  67. if ( !isSubStr( tableLookup( "mp/statsTable.csv", 0, weaponId, 2 ), "weapon_" ) )
  68. continue;
  69.  
  70. level.weaponList[level.weaponList.size] = weapon_name + "_mp";
  71. /#
  72. if ( getDvar( "scr_dump_weapon_assets" ) != "" )
  73. {
  74. printLn( "" );
  75. printLn( "// " + weapon_name + " real assets" );
  76. printLn( "weapon,mp/" + weapon_name + "_mp" );
  77. }
  78. #/
  79.  
  80. // the alphabetize function is slow so we try not to do it for every weapon/attachment combo; a code solution would be better.
  81. attachmentNames = [];
  82. for ( innerLoopCount = 0; innerLoopCount < 10; innerLoopCount++ )
  83. {
  84. // generating attachment combinations
  85. attachmentName = tablelookup( "mp/statStable.csv", 0, weaponId, innerLoopCount + 11 );
  86.  
  87. if( attachmentName == "" )
  88. break;
  89.  
  90. attachmentNames[attachmentName] = true;
  91. }
  92.  
  93. // generate an alphabetized attachment list
  94. attachments = [];
  95. foreach ( attachmentName in attachmentList )
  96. {
  97. if ( !isDefined( attachmentNames[attachmentName] ) )
  98. continue;
  99.  
  100. level.weaponList[level.weaponList.size] = weapon_name + "_" + attachmentName + "_mp";
  101. attachments[attachments.size] = attachmentName;
  102. /#
  103. if ( getDvar( "scr_dump_weapon_assets" ) != "" )
  104. println( "weapon,mp/" + weapon_name + "_" + attachmentName + "_mp" );
  105. #/
  106. }
  107.  
  108. attachmentCombos = [];
  109. for ( i = 0; i < (attachments.size - 1); i++ )
  110. {
  111. colIndex = tableLookupRowNum( "mp/attachmentCombos.csv", 0, attachments[i] );
  112. for ( j = i + 1; j < attachments.size; j++ )
  113. {
  114. if ( tableLookup( "mp/attachmentCombos.csv", 0, attachments[j], colIndex ) == "no" )
  115. continue;
  116.  
  117. attachmentCombos[attachmentCombos.size] = attachments[i] + "_" + attachments[j];
  118. }
  119. }
  120.  
  121. /#
  122. if ( getDvar( "scr_dump_weapon_assets" ) != "" && attachmentCombos.size )
  123. println( "// " + weapon_name + " virtual assets" );
  124. #/
  125.  
  126. foreach ( combo in attachmentCombos )
  127. {
  128. /#
  129. if ( getDvar( "scr_dump_weapon_assets" ) != "" )
  130. println( "weapon,mp/" + weapon_name + "_" + combo + "_mp" );
  131. #/
  132.  
  133. level.weaponList[level.weaponList.size] = weapon_name + "_" + combo + "_mp";
  134. }
  135. }
  136.  
  137. foreach ( weaponName in level.weaponList )
  138. {
  139. precacheItem( weaponName );
  140.  
  141. /#
  142. if ( getDvar( "scr_dump_weapon_assets" ) != "" )
  143. {
  144. altWeapon = weaponAltWeaponName( weaponName );
  145. if ( altWeapon != "none" )
  146. println( "weapon,mp/" + altWeapon );
  147. }
  148. #/
  149. }
  150.  
  151. precacheItem( "flare_mp" );
  152. precacheItem( "scavenger_bag_mp" );
  153. precacheItem( "frag_grenade_short_mp" );
  154. precacheItem( "destructible_car" );
  155.  
  156. precacheShellShock( "default" );
  157. precacheShellShock( "concussion_grenade_mp" );
  158. thread maps\mp\_flashgrenades::main();
  159. thread maps\mp\_entityheadicons::init();
  160.  
  161. claymoreDetectionConeAngle = 70;
  162. level.claymoreDetectionDot = cos( claymoreDetectionConeAngle );
  163. level.claymoreDetectionMinDist = 20;
  164. level.claymoreDetectionGracePeriod = .75;
  165. level.claymoreDetonateRadius = 192;
  166.  
  167. // this should move to _stinger.gsc
  168. level.stingerFXid = loadfx ("explosions/aerial_explosion_large");
  169.  
  170. // generating weapon type arrays which classifies the weapon as primary (back stow), pistol, or inventory (side pack stow)
  171. // using mp/statstable.csv's weapon grouping data ( numbering 0 - 149 )
  172. level.primary_weapon_array = [];
  173. level.side_arm_array = [];
  174. level.grenade_array = [];
  175. level.inventory_array = [];
  176. level.stow_priority_model_array = [];
  177. level.stow_offset_array = [];
  178.  
  179. max_weapon_num = 149;
  180. for( i = 0; i < max_weapon_num; i++ )
  181. {
  182. weapon = tableLookup( "mp/statsTable.csv", 0, i, 4 );
  183. stow_model = tableLookup( "mp/statsTable.csv", 0, i, 9 );
  184.  
  185. if ( stow_model == "" )
  186. continue;
  187.  
  188. precacheModel( stow_model );
  189.  
  190. if ( isSubStr( stow_model, "weapon_stow_" ) )
  191. level.stow_offset_array[ weapon ] = stow_model;
  192. else
  193. level.stow_priority_model_array[ weapon + "_mp" ] = stow_model;
  194. }
  195.  
  196. precacheModel( "weapon_claymore_bombsquad" );
  197. precacheModel( "weapon_c4_bombsquad" );
  198. precacheModel( "projectile_m67fraggrenade_bombsquad" );
  199. precacheModel( "projectile_semtex_grenade_bombsquad" );
  200. precacheModel( "weapon_light_stick_tactical_bombsquad" );
  201.  
  202. level.killStreakSpecialCaseWeapons = [];
  203. level.killStreakSpecialCaseWeapons["cobra_player_minigun_mp"] = true;
  204. level.killStreakSpecialCaseWeapons["artillery_mp"] = true;
  205. level.killStreakSpecialCaseWeapons["stealth_bomb_mp"] = true;
  206. level.killStreakSpecialCaseWeapons["pavelow_minigun_mp"] = true;
  207. level.killStreakSpecialCaseWeapons["sentry_minigun_mp"] = true;
  208. level.killStreakSpecialCaseWeapons["harrier_20mm_mp"] = true;
  209. level.killStreakSpecialCaseWeapons["ac130_105mm_mp"] = true;
  210. level.killStreakSpecialCaseWeapons["ac130_40mm_mp"] = true;
  211. level.killStreakSpecialCaseWeapons["ac130_25mm_mp"] = true;
  212. level.killStreakSpecialCaseWeapons["remotemissile_projectile_mp"] = true;
  213. level.killStreakSpecialCaseWeapons["cobra_20mm_mp"] = true;
  214. level.killStreakSpecialCaseWeapons["sentry_minigun_mp"] = true;
  215.  
  216.  
  217. level thread onPlayerConnect();
  218.  
  219. level.c4explodethisframe = false;
  220.  
  221. array_thread( getEntArray( "misc_turret", "classname" ), ::turret_monitorUse );
  222.  
  223. // thread dumpIt();
  224. }
  225.  
  226.  
  227. dumpIt()
  228. {
  229.  
  230. wait ( 5.0 );
  231. /#
  232. max_weapon_num = 149;
  233.  
  234. for( weaponId = 0; weaponId <= max_weapon_num; weaponId++ )
  235. {
  236. weapon_name = tablelookup( "mp/statstable.csv", 0, weaponId, 4 );
  237. if( weapon_name == "" )
  238. continue;
  239.  
  240. if ( !isSubStr( tableLookup( "mp/statsTable.csv", 0, weaponId, 2 ), "weapon_" ) )
  241. continue;
  242.  
  243. if ( getDvar( "scr_dump_weapon_challenges" ) != "" )
  244. {
  245. /*
  246. sharpshooter
  247. marksman
  248. veteran
  249. expert
  250. master
  251. */
  252.  
  253. weaponLStringName = tableLookup( "mp/statsTable.csv", 0, weaponId, 3 );
  254. weaponRealName = tableLookupIString( "mp/statsTable.csv", 0, weaponId, 3 );
  255.  
  256. prefix = "WEAPON_";
  257. weaponCapsName = getSubStr( weaponLStringName, prefix.size, weaponLStringName.size );
  258.  
  259. weaponGroup = tableLookup( "mp/statsTable.csv", 0, weaponId, 2 );
  260.  
  261. weaponGroupSuffix = getSubStr( weaponGroup, prefix.size, weaponGroup.size );
  262.  
  263. /*
  264. iprintln( "REFERENCE TITLE_" + weaponCapsName + "_SHARPSHOOTER" );
  265. iprintln( "LANG_ENGLISH ", weaponRealName, ": Sharpshooter" );
  266. iprintln( "" );
  267. iprintln( "REFERENCE TITLE_" + weaponCapsName + "_MARKSMAN" );
  268. iprintln( "LANG_ENGLISH ", weaponRealName, ": Marksman" );
  269. iprintln( "" );
  270. iprintln( "REFERENCE TITLE_" + weaponCapsName + "_VETERAN" );
  271. iprintln( "LANG_ENGLISH ", weaponRealName, ": Veteran" );
  272. iprintln( "" );
  273. iprintln( "REFERENCE TITLE_" + weaponCapsName + "_EXPERT" );
  274. iprintln( "LANG_ENGLISH ", weaponRealName, ": Expert" );
  275. iprintln( "" );
  276. iprintln( "REFERENCE TITLE_" + weaponCapsName + "_Master" );
  277. iprintln( "LANG_ENGLISH ", weaponRealName, ": Master" );
  278. */
  279.  
  280. iprintln( "cardtitle_" + weapon_name + "_sharpshooter,PLAYERCARDS_TITLE_" + weaponCapsName + "_SHARPSHOOTER,cardtitle_" + weaponGroupSuffix + "_sharpshooter,1,1,1" );
  281. iprintln( "cardtitle_" + weapon_name + "_marksman,PLAYERCARDS_TITLE_" + weaponCapsName + "_MARKSMAN,cardtitle_" + weaponGroupSuffix + "_marksman,1,1,1" );
  282. iprintln( "cardtitle_" + weapon_name + "_veteran,PLAYERCARDS_TITLE_" + weaponCapsName + "_VETERAN,cardtitle_" + weaponGroupSuffix + "_veteran,1,1,1" );
  283. iprintln( "cardtitle_" + weapon_name + "_expert,PLAYERCARDS_TITLE_" + weaponCapsName + "_EXPERT,cardtitle_" + weaponGroupSuffix + "_expert,1,1,1" );
  284. iprintln( "cardtitle_" + weapon_name + "_master,PLAYERCARDS_TITLE_" + weaponCapsName + "_MASTER,cardtitle_" + weaponGroupSuffix + "_master,1,1,1" );
  285.  
  286. wait ( 0.05 );
  287. }
  288. }
  289. #/
  290. }
  291.  
  292. bombSquadWaiter()
  293. {
  294. self endon ( "disconnect" );
  295.  
  296. for ( ;; )
  297. {
  298. self waittill ( "grenade_fire", weaponEnt, weaponName );
  299.  
  300. team = level.otherTeam[self.team];
  301.  
  302. if ( weaponName == "c4_mp" )
  303. weaponEnt thread createBombSquadModel( "weapon_c4_bombsquad", "tag_origin", team, self );
  304. else if ( weaponName == "claymore_mp" )
  305. weaponEnt thread createBombSquadModel( "weapon_claymore_bombsquad", "tag_origin", team, self );
  306. else if ( weaponName == "frag_grenade_mp" )
  307. weaponEnt thread createBombSquadModel( "projectile_m67fraggrenade_bombsquad", "tag_weapon", team, self );
  308. else if ( weaponName == "frag_grenade_short_mp" )
  309. weaponEnt thread createBombSquadModel( "projectile_m67fraggrenade_bombsquad", "tag_weapon", team, self );
  310. else if ( weaponName == "semtex_mp" )
  311. weaponEnt thread createBombSquadModel( "projectile_semtex_grenade_bombsquad", "tag_weapon", team, self );
  312. }
  313. }
  314.  
  315.  
  316. createBombSquadModel( modelName, tagName, teamName, owner )
  317. {
  318. bombSquadModel = spawn( "script_model", (0,0,0) );
  319. bombSquadModel hide();
  320. wait ( 0.05 );
  321.  
  322. if (!isDefined( self ) ) //grenade model may not be around if picked up
  323. return;
  324.  
  325. bombSquadModel thread bombSquadVisibilityUpdater( teamName, owner );
  326. bombSquadModel setModel( modelName );
  327. bombSquadModel linkTo( self, tagName, (0,0,0), (0,0,0) );
  328. bombSquadModel SetContents( 0 );
  329.  
  330. self waittill ( "death" );
  331.  
  332. bombSquadModel delete();
  333. }
  334.  
  335.  
  336. bombSquadVisibilityUpdater( teamName, owner )
  337. {
  338. self endon ( "death" );
  339.  
  340. foreach ( player in level.players )
  341. {
  342. if ( level.teamBased )
  343. {
  344. if ( player.team == teamName && player _hasPerk( "specialty_detectexplosive" ) )
  345. self showToPlayer( player );
  346. }
  347. else
  348. {
  349. if ( isDefined( owner ) && player == owner )
  350. continue;
  351.  
  352. if ( !player _hasPerk( "specialty_detectexplosive" ) )
  353. continue;
  354.  
  355. self showToPlayer( player );
  356. }
  357. }
  358.  
  359. for ( ;; )
  360. {
  361. level waittill_any( "joined_team", "player_spawned", "changed_kit" );
  362.  
  363. self hide();
  364.  
  365. foreach ( player in level.players )
  366. {
  367. if ( level.teamBased )
  368. {
  369. if ( player.team == teamName && player _hasPerk( "specialty_detectexplosive" ) )
  370. self showToPlayer( player );
  371. }
  372. else
  373. {
  374. if ( isDefined( owner ) && player == owner )
  375. continue;
  376.  
  377. if ( !player _hasPerk( "specialty_detectexplosive" ) )
  378. continue;
  379.  
  380. self showToPlayer( player );
  381. }
  382. }
  383. }
  384. }
  385.  
  386.  
  387. onPlayerConnect()
  388. {
  389. for(;;)
  390. {
  391. level waittill("connected", player);
  392.  
  393. player.hits = 0;
  394. player.hasDoneCombat = false;
  395.  
  396. player KC_RegWeaponForFXRemoval( "remotemissile_projectile_mp" );
  397.  
  398. player thread onPlayerSpawned();
  399. player thread bombSquadWaiter();
  400. }
  401. }
  402.  
  403.  
  404. onPlayerSpawned()
  405. {
  406. self endon("disconnect");
  407.  
  408. for(;;)
  409. {
  410. self waittill("spawned_player");
  411.  
  412. self.currentWeaponAtSpawn = self getCurrentWeapon(); // optimization so these threads we start don't have to call it.
  413.  
  414. self.empEndTime = 0;
  415. self.concussionEndTime = 0;
  416. self.hasDoneCombat = false;
  417. self thread watchWeaponUsage();
  418. self thread watchGrenadeUsage();
  419. self thread watchWeaponChange();
  420. self thread watchStingerUsage();
  421. self thread watchJavelinUsage();
  422. self thread watchMissileUsage();
  423. self thread watchSentryUsage();
  424. self thread watchWeaponReload();
  425. self thread maps\mp\gametypes\_class::trackRiotShield();
  426.  
  427. self.lastHitTime = [];
  428.  
  429. self.droppedDeathWeapon = undefined;
  430. self.tookWeaponFrom = [];
  431.  
  432. self thread updateStowedWeapon();
  433.  
  434. self thread updateSavedLastWeapon();
  435.  
  436. if ( self hasWeapon( "semtex_mp" ) )
  437. self thread monitorSemtex();
  438.  
  439. self.currentWeaponAtSpawn = undefined;
  440. }
  441. }
  442.  
  443. WatchStingerUsage()
  444. {
  445. self maps\mp\_stinger::StingerUsageLoop();
  446. }
  447.  
  448.  
  449. WatchJavelinUsage()
  450. {
  451. self maps\mp\_javelin::JavelinUsageLoop();
  452. }
  453.  
  454. watchWeaponChange()
  455. {
  456. self endon("death");
  457. self endon("disconnect");
  458.  
  459. self thread watchStartWeaponChange();
  460. self.lastDroppableWeapon = self.currentWeaponAtSpawn;
  461. self.hitsThisMag = [];
  462.  
  463. weapon = self getCurrentWeapon();
  464.  
  465. if ( isCACPrimaryWeapon( weapon ) && !isDefined( self.hitsThisMag[ weapon ] ) )
  466. self.hitsThisMag[ weapon ] = weaponClipSize( weapon );
  467.  
  468. self.bothBarrels = undefined;
  469.  
  470. if ( isSubStr( weapon, "ranger" ) )
  471. self thread watchRangerUsage( weapon );
  472.  
  473. while(1)
  474. {
  475. self waittill( "weapon_change", newWeapon );
  476.  
  477. tokedNewWeapon = StrTok( newWeapon, "_" );
  478.  
  479. self.bothBarrels = undefined;
  480.  
  481. if ( isSubStr( newWeapon, "ranger" ) )
  482. self thread watchRangerUsage( newWeapon );
  483.  
  484. if ( tokedNewWeapon[0] == "gl" || ( tokedNewWeapon.size > 2 && tokedNewWeapon[2] == "attach" ) )
  485. newWeapon = self getCurrentPrimaryWeapon();
  486.  
  487. if ( newWeapon != "none" )
  488. {
  489. if ( isCACPrimaryWeapon( newWeapon ) && !isDefined( self.hitsThisMag[ newWeapon ] ) )
  490. self.hitsThisMag[ newWeapon ] = weaponClipSize( newWeapon );
  491. }
  492. self.changingWeapon = undefined;
  493. if ( mayDropWeapon( newWeapon ) )
  494. self.lastDroppableWeapon = newWeapon;
  495. }
  496. }
  497.  
  498.  
  499. watchStartWeaponChange()
  500. {
  501. self endon("death");
  502. self endon("disconnect");
  503. self.changingWeapon = undefined;
  504.  
  505. while(1)
  506. {
  507. self waittill( "weapon_switch_started", newWeapon );
  508. self.changingWeapon = newWeapon;
  509. }
  510. }
  511.  
  512. watchWeaponReload()
  513. {
  514. self endon("death");
  515. self endon("disconnect");
  516.  
  517. for ( ;; )
  518. {
  519. self waittill( "reload" );
  520.  
  521. weaponName = self getCurrentWeapon();
  522.  
  523. self.bothBarrels = undefined;
  524.  
  525. if ( !isSubStr( weaponName, "ranger" ) )
  526. continue;
  527.  
  528. self thread watchRangerUsage( weaponName );
  529. }
  530. }
  531.  
  532.  
  533. watchRangerUsage( rangerName )
  534. {
  535. rightAmmo = self getWeaponAmmoClip( rangerName, "right" );
  536. leftAmmo = self getWeaponAmmoClip( rangerName, "left" );
  537.  
  538. self endon ( "reload" );
  539. self endon ( "weapon_change" );
  540.  
  541. for ( ;; )
  542. {
  543. self waittill ( "weapon_fired", weaponName );
  544.  
  545. if ( weaponName != rangerName )
  546. continue;
  547.  
  548. self.bothBarrels = undefined;
  549.  
  550. if ( isSubStr( rangerName, "akimbo" ) )
  551. {
  552. newLeftAmmo = self getWeaponAmmoClip( rangerName, "left" );
  553. newRightAmmo = self getWeaponAmmoClip( rangerName, "right" );
  554.  
  555. if ( leftAmmo != newLeftAmmo && rightAmmo != newRightAmmo )
  556. self.bothBarrels = true;
  557.  
  558. if ( !newLeftAmmo || !newRightAmmo )
  559. return;
  560.  
  561.  
  562. leftAmmo = newLeftAmmo;
  563. rightAmmo = newRightAmmo;
  564. }
  565. else if ( rightAmmo == 2 && !self getWeaponAmmoClip( rangerName, "right" ) )
  566. {
  567. self.bothBarrels = true;
  568. return;
  569. }
  570. }
  571. }
  572.  
  573.  
  574. isHackWeapon( weapon )
  575. {
  576. if ( weapon == "radar_mp" || weapon == "airstrike_mp" || weapon == "helicopter_mp" )
  577. return true;
  578. if ( weapon == "briefcase_bomb_mp" )
  579. return true;
  580. return false;
  581. }
  582.  
  583.  
  584. mayDropWeapon( weapon )
  585. {
  586. if ( weapon == "none" )
  587. return false;
  588.  
  589. if ( isSubStr( weapon, "ac130" ) )
  590. return false;
  591.  
  592. invType = WeaponInventoryType( weapon );
  593. if ( invType != "primary" )
  594. return false;
  595.  
  596. return true;
  597. }
  598.  
  599. dropWeaponForDeath( attacker )
  600. {
  601. weapon = self.lastDroppableWeapon;
  602.  
  603. if ( isdefined( self.droppedDeathWeapon ) )
  604. return;
  605.  
  606. if ( level.inGracePeriod )
  607. return;
  608.  
  609. if ( !isdefined( weapon ) )
  610. {
  611. /#
  612. if ( getdvar("scr_dropdebug") == "1" )
  613. println( "didn't drop weapon: not defined" );
  614. #/
  615. return;
  616. }
  617.  
  618. if ( weapon == "none" )
  619. {
  620. /#
  621. if ( getdvar("scr_dropdebug") == "1" )
  622. println( "didn't drop weapon: weapon == none" );
  623. #/
  624. return;
  625. }
  626.  
  627. if ( !self hasWeapon( weapon ) )
  628. {
  629. /#
  630. if ( getdvar("scr_dropdebug") == "1" )
  631. println( "didn't drop weapon: don't have it anymore (" + weapon + ")" );
  632. #/
  633. return;
  634. }
  635.  
  636. if ( weapon != "riotshield_mp" )
  637. {
  638. if ( !(self AnyAmmoForWeaponModes( weapon )) )
  639. {
  640. /#
  641. if ( getdvar("scr_dropdebug") == "1" )
  642. println( "didn't drop weapon: no ammo for weapon modes" );
  643. #/
  644. return;
  645. }
  646.  
  647. clipAmmoR = self GetWeaponAmmoClip( weapon, "right" );
  648. clipAmmoL = self GetWeaponAmmoClip( weapon, "left" );
  649. if ( !clipAmmoR && !clipAmmoL )
  650. {
  651. /#
  652. if ( getdvar("scr_dropdebug") == "1" )
  653. println( "didn't drop weapon: no ammo in clip" );
  654. #/
  655. return;
  656. }
  657.  
  658. stockAmmo = self GetWeaponAmmoStock( weapon );
  659. stockMax = WeaponMaxAmmo( weapon );
  660. if ( stockAmmo > stockMax )
  661. stockAmmo = stockMax;
  662.  
  663. item = self dropItem( weapon );
  664. item ItemWeaponSetAmmo( clipAmmoR, stockAmmo, clipAmmoL );
  665. }
  666. else
  667. {
  668. item = self dropItem( weapon );
  669. if ( !isDefined( item ) )
  670. return;
  671. item ItemWeaponSetAmmo( 1, 1, 0 );
  672. }
  673.  
  674. /#
  675. if ( getdvar("scr_dropdebug") == "1" )
  676. println( "dropped weapon: " + weapon );
  677. #/
  678.  
  679. self.droppedDeathWeapon = true;
  680.  
  681. item.owner = self;
  682. item.ownersattacker = attacker;
  683.  
  684. item thread watchPickup();
  685.  
  686. item thread deletePickupAfterAWhile();
  687.  
  688. detach_model = getWeaponModel( weapon );
  689.  
  690. if ( !isDefined( detach_model ) )
  691. return;
  692.  
  693. if( isDefined( self.tag_stowed_back ) && detach_model == self.tag_stowed_back )
  694. self detach_back_weapon();
  695.  
  696. if ( !isDefined( self.tag_stowed_hip ) )
  697. return;
  698.  
  699. if( detach_model == self.tag_stowed_hip )
  700. self detach_hip_weapon();
  701. }
  702.  
  703.  
  704. detachIfAttached( model, baseTag )
  705. {
  706. attachSize = self getAttachSize();
  707.  
  708. for ( i = 0; i < attachSize; i++ )
  709. {
  710. attach = self getAttachModelName( i );
  711.  
  712. if ( attach != model )
  713. continue;
  714.  
  715. tag = self getAttachTagName( i );
  716. self detach( model, tag );
  717.  
  718. if ( tag != baseTag )
  719. {
  720. attachSize = self getAttachSize();
  721.  
  722. for ( i = 0; i < attachSize; i++ )
  723. {
  724. tag = self getAttachTagName( i );
  725.  
  726. if ( tag != baseTag )
  727. continue;
  728.  
  729. model = self getAttachModelName( i );
  730. self detach( model, tag );
  731.  
  732. break;
  733. }
  734. }
  735. return true;
  736. }
  737. return false;
  738. }
  739.  
  740.  
  741. deletePickupAfterAWhile()
  742. {
  743. self endon("death");
  744.  
  745. wait 60;
  746.  
  747. if ( !isDefined( self ) )
  748. return;
  749.  
  750. self delete();
  751. }
  752.  
  753. getItemWeaponName()
  754. {
  755. classname = self.classname;
  756. assert( getsubstr( classname, 0, 7 ) == "weapon_" );
  757. weapname = getsubstr( classname, 7 );
  758. return weapname;
  759. }
  760.  
  761. watchPickup()
  762. {
  763. self endon("death");
  764.  
  765. weapname = self getItemWeaponName();
  766.  
  767. while(1)
  768. {
  769. self waittill( "trigger", player, droppedItem );
  770.  
  771. if ( isdefined( droppedItem ) )
  772. break;
  773. // otherwise, player merely acquired ammo and didn't pick this up
  774. }
  775.  
  776. /#
  777. if ( getdvar("scr_dropdebug") == "1" )
  778. println( "picked up weapon: " + weapname + ", " + isdefined( self.ownersattacker ) );
  779. #/
  780.  
  781. assert( isdefined( player.tookWeaponFrom ) );
  782.  
  783. // make sure the owner information on the dropped item is preserved
  784. droppedWeaponName = droppedItem getItemWeaponName();
  785. if ( isdefined( player.tookWeaponFrom[ droppedWeaponName ] ) )
  786. {
  787. droppedItem.owner = player.tookWeaponFrom[ droppedWeaponName ];
  788. droppedItem.ownersattacker = player;
  789. player.tookWeaponFrom[ droppedWeaponName ] = undefined;
  790. }
  791. droppedItem thread watchPickup();
  792.  
  793. // take owner information from self and put it onto player
  794. if ( isdefined( self.ownersattacker ) && self.ownersattacker == player )
  795. {
  796. player.tookWeaponFrom[ weapname ] = self.owner;
  797. }
  798. else
  799. {
  800. player.tookWeaponFrom[ weapname ] = undefined;
  801. }
  802. }
  803.  
  804. itemRemoveAmmoFromAltModes()
  805. {
  806. origweapname = self getItemWeaponName();
  807.  
  808. curweapname = weaponAltWeaponName( origweapname );
  809.  
  810. altindex = 1;
  811. while ( curweapname != "none" && curweapname != origweapname )
  812. {
  813. self itemWeaponSetAmmo( 0, 0, 0, altindex );
  814. curweapname = weaponAltWeaponName( curweapname );
  815. altindex++;
  816. }
  817. }
  818.  
  819.  
  820. handleScavengerBagPickup( scrPlayer )
  821. {
  822. self endon( "death" );
  823. level endon ( "game_ended" );
  824.  
  825. assert( isDefined( scrPlayer ) );
  826.  
  827. // Wait for the pickup to happen
  828. self waittill( "scavenger", destPlayer );
  829. assert( isDefined ( destPlayer ) );
  830.  
  831. destPlayer notify( "scavenger_pickup" );
  832. destPlayer playLocalSound( "scavenger_pack_pickup" );
  833.  
  834. offhandWeapons = destPlayer getWeaponsListOffhands();
  835.  
  836. if ( destPlayer _hasPerk( "specialty_tacticalinsertion" ) && destPlayer getAmmoCount( "flare_mp" ) < 1 )
  837. destPlayer _setPerk( "specialty_tacticalinsertion");
  838.  
  839. foreach ( offhand in offhandWeapons )
  840. {
  841. currentClipAmmo = destPlayer GetWeaponAmmoClip( offhand );
  842. destPlayer SetWeaponAmmoClip( offhand, currentClipAmmo + 1);
  843. }
  844.  
  845. primaryWeapons = destPlayer getWeaponsListPrimaries();
  846. foreach ( primary in primaryWeapons )
  847. {
  848. if ( !isCACPrimaryWeapon( primary ) && !level.scavenger_secondary )
  849. continue;
  850.  
  851. currentStockAmmo = destPlayer GetWeaponAmmoStock( primary );
  852. addStockAmmo = weaponClipSize( primary );
  853.  
  854. destPlayer setWeaponAmmoStock( primary, currentStockAmmo + addStockAmmo );
  855.  
  856. altWeapon = weaponAltWeaponName( primary );
  857.  
  858. if ( !isDefined( altWeapon ) || (altWeapon == "none") || !level.scavenger_altmode )
  859. continue;
  860.  
  861. currentStockAmmo = destPlayer GetWeaponAmmoStock( altWeapon );
  862. addStockAmmo = weaponClipSize( altWeapon );
  863.  
  864. destPlayer setWeaponAmmoStock( altWeapon, currentStockAmmo + addStockAmmo );
  865. }
  866.  
  867. destPlayer maps\mp\gametypes\_damagefeedback::updateDamageFeedback( "scavenger" );
  868. }
  869.  
  870.  
  871. dropScavengerForDeath( attacker )
  872. {
  873. if ( level.inGracePeriod )
  874. return;
  875.  
  876. if( !isDefined( attacker ) )
  877. return;
  878.  
  879. if( attacker == self )
  880. return;
  881.  
  882. dropBag = self dropScavengerBag( "scavenger_bag_mp" );
  883. dropBag thread handleScavengerBagPickup( self );
  884.  
  885. }
  886.  
  887. getWeaponBasedGrenadeCount(weapon)
  888. {
  889. return 2;
  890. }
  891.  
  892. getWeaponBasedSmokeGrenadeCount(weapon)
  893. {
  894. return 1;
  895. }
  896.  
  897. getFragGrenadeCount()
  898. {
  899. grenadetype = "frag_grenade_mp";
  900.  
  901. count = self getammocount(grenadetype);
  902. return count;
  903. }
  904.  
  905. getSmokeGrenadeCount()
  906. {
  907. grenadetype = "smoke_grenade_mp";
  908.  
  909. count = self getammocount(grenadetype);
  910. return count;
  911. }
  912.  
  913.  
  914. watchWeaponUsage( weaponHand )
  915. {
  916. self endon( "death" );
  917. self endon( "disconnect" );
  918. level endon ( "game_ended" );
  919.  
  920. for ( ;; )
  921. {
  922. self waittill ( "weapon_fired", weaponName );
  923.  
  924. self.hasDoneCombat = true;
  925.  
  926. if ( !maps\mp\gametypes\_weapons::isPrimaryWeapon( weaponName ) && !maps\mp\gametypes\_weapons::isSideArm( weaponName ) )
  927. continue;
  928.  
  929. if ( isDefined( self.hitsThisMag[ weaponName ] ) )
  930. self thread updateMagShots( weaponName );
  931.  
  932. totalShots = self maps\mp\gametypes\_persistence::statGetBuffered( "totalShots" ) + 1;
  933. hits = self maps\mp\gametypes\_persistence::statGetBuffered( "hits" );
  934. self maps\mp\gametypes\_persistence::statSetBuffered( "totalShots", totalShots );
  935. self maps\mp\gametypes\_persistence::statSetBuffered( "accuracy", int(hits * 10000 / totalShots) );
  936. self maps\mp\gametypes\_persistence::statSetBuffered( "misses", int(totalShots - hits) );
  937. }
  938. }
  939.  
  940.  
  941. updateMagShots( weaponName )
  942. {
  943. self endon ( "death" );
  944. self endon ( "disconnect" );
  945. self endon ( "updateMagShots_" + weaponName );
  946.  
  947. self.hitsThisMag[ weaponName ]--;
  948.  
  949. wait ( 0.05 );
  950.  
  951. self.hitsThisMag[ weaponName ] = weaponClipSize( weaponName );
  952. }
  953.  
  954.  
  955. checkHitsThisMag( weaponName )
  956. {
  957. self endon ( "death" );
  958. self endon ( "disconnect" );
  959.  
  960. self notify ( "updateMagShots_" + weaponName );
  961. waittillframeend;
  962.  
  963. if ( self.hitsThisMag[ weaponName ] == 0 )
  964. {
  965. weaponClass = getWeaponClass( weaponName );
  966.  
  967. maps\mp\gametypes\_missions::genericChallenge( weaponClass );
  968.  
  969. self.hitsThisMag[ weaponName ] = weaponClipSize( weaponName );
  970. }
  971. }
  972.  
  973.  
  974. checkHit( weaponName, victim )
  975. {
  976. if ( !maps\mp\gametypes\_weapons::isPrimaryWeapon( weaponName ) && !maps\mp\gametypes\_weapons::isSideArm( weaponName ) )
  977. return;
  978.  
  979. // sometimes the "weapon_fired" notify happens after we hit the guy...
  980. waittillframeend;
  981.  
  982. if ( isDefined( self.hitsThisMag[ weaponName ] ) )
  983. self thread checkHitsThisMag( weaponName );
  984.  
  985. if ( !isDefined( self.lastHitTime[ weaponName ] ) )
  986. self.lastHitTime[ weaponName ] = 0;
  987.  
  988. // already hit with this weapon on this frame
  989. if ( self.lastHitTime[ weaponName ] == getTime() )
  990. return;
  991.  
  992. self.lastHitTime[ weaponName ] = getTime();
  993.  
  994. totalShots = self maps\mp\gametypes\_persistence::statGetBuffered( "totalShots" );
  995. hits = self maps\mp\gametypes\_persistence::statGetBuffered( "hits" ) + 1;
  996.  
  997. if ( hits <= totalShots )
  998. {
  999. self maps\mp\gametypes\_persistence::statSetBuffered( "hits", hits );
  1000. self maps\mp\gametypes\_persistence::statSetBuffered( "misses", int(totalShots - hits) );
  1001. self maps\mp\gametypes\_persistence::statSetBuffered( "accuracy", int(hits * 10000 / totalShots) );
  1002. }
  1003. }
  1004.  
  1005.  
  1006. attackerCanDamageItem( attacker, itemOwner )
  1007. {
  1008. return friendlyFireCheck( itemOwner, attacker );
  1009. }
  1010.  
  1011. // returns true if damage should be done to the item given its owner and the attacker
  1012. friendlyFireCheck( owner, attacker, forcedFriendlyFireRule )
  1013. {
  1014. if ( !isdefined( owner ) )// owner has disconnected? allow it
  1015. return true;
  1016.  
  1017. if ( !level.teamBased )// not a team based mode? allow it
  1018. return true;
  1019.  
  1020. attackerTeam = attacker.team;
  1021.  
  1022. friendlyFireRule = level.friendlyfire;
  1023. if ( isdefined( forcedFriendlyFireRule ) )
  1024. friendlyFireRule = forcedFriendlyFireRule;
  1025.  
  1026. if ( friendlyFireRule != 0 )// friendly fire is on? allow it
  1027. return true;
  1028.  
  1029. if ( attacker == owner )// owner may attack his own items
  1030. return true;
  1031.  
  1032. if ( !isdefined( attackerTeam ) )// attacker not on a team? allow it
  1033. return true;
  1034.  
  1035. if ( attackerTeam != owner.team )// attacker not on the same team as the owner? allow it
  1036. return true;
  1037.  
  1038. return false;// disallow it
  1039. }
  1040.  
  1041. watchGrenadeUsage()
  1042. {
  1043. self endon( "death" );
  1044. self endon( "disconnect" );
  1045.  
  1046. self.throwingGrenade = undefined;
  1047. self.gotPullbackNotify = false;
  1048.  
  1049. if ( getIntProperty( "scr_deleteexplosivesonspawn", 1 ) == 1 )
  1050. {
  1051. // delete c4 from previous spawn
  1052. if ( isdefined( self.c4array ) )
  1053. {
  1054. for ( i = 0; i < self.c4array.size; i++ )
  1055. {
  1056. if ( isdefined( self.c4array[ i ] ) )
  1057. self.c4array[ i ] delete();
  1058. }
  1059. }
  1060. self.c4array = [];
  1061. // delete claymores from previous spawn
  1062. if ( isdefined( self.claymorearray ) )
  1063. {
  1064. for ( i = 0; i < self.claymorearray.size; i++ )
  1065. {
  1066. if ( isdefined( self.claymorearray[ i ] ) )
  1067. self.claymorearray[ i ] delete();
  1068. }
  1069. }
  1070. self.claymorearray = [];
  1071. }
  1072. else
  1073. {
  1074. if ( !isdefined( self.c4array ) )
  1075. self.c4array = [];
  1076. if ( !isdefined( self.claymorearray ) )
  1077. self.claymorearray = [];
  1078. }
  1079.  
  1080. thread watchC4();
  1081. thread watchC4Detonation();
  1082. thread watchC4AltDetonation();
  1083. thread watchClaymores();
  1084. thread deleteC4AndClaymoresOnDisconnect();
  1085.  
  1086. self thread watchForThrowbacks();
  1087.  
  1088. for ( ;; )
  1089. {
  1090. self waittill( "grenade_pullback", weaponName );
  1091.  
  1092. self.hasDoneCombat = true;
  1093.  
  1094. if ( weaponName == "claymore_mp" )
  1095. continue;
  1096.  
  1097. self.throwingGrenade = weaponName;
  1098. self.gotPullbackNotify = true;
  1099.  
  1100. if ( weaponName == "c4_mp" )
  1101. self beginC4Tracking();
  1102. else
  1103. self beginGrenadeTracking();
  1104.  
  1105. self.throwingGrenade = undefined;
  1106. }
  1107. }
  1108.  
  1109. beginGrenadeTracking()
  1110. {
  1111. self endon( "death" );
  1112. self endon( "disconnect" );
  1113. self endon( "offhand_end" );
  1114. self endon( "weapon_change" );
  1115.  
  1116. startTime = getTime();
  1117.  
  1118. self waittill( "grenade_fire", grenade, weaponName );
  1119.  
  1120. if ( ( getTime() - startTime > 1000 ) && weaponName == "frag_grenade_mp" )
  1121. grenade.isCooked = true;
  1122.  
  1123. self.changingWeapon = undefined;
  1124.  
  1125. if ( weaponName == "frag_grenade_mp" || weaponName == "semtex_mp" )
  1126. {
  1127. grenade thread maps\mp\gametypes\_shellshock::grenade_earthQuake();
  1128. grenade.originalOwner = self;
  1129. }
  1130.  
  1131. if ( weaponName == "flash_grenade_mp" || weaponName == "concussion_grenade_mp" )
  1132. {
  1133. grenade.owner = self;
  1134. grenade thread empExplodeWaiter();
  1135. }
  1136. }
  1137.  
  1138. AddMissileToSightTraces( team )
  1139. {
  1140. self.team = team;
  1141. level.missilesForSightTraces[ level.missilesForSightTraces.size ] = self;
  1142.  
  1143. self waittill( "death" );
  1144.  
  1145. newArray = [];
  1146. foreach( missile in level.missilesForSightTraces )
  1147. {
  1148. if ( missile != self )
  1149. newArray[ newArray.size ] = missile;
  1150. }
  1151. level.missilesForSightTraces = newArray;
  1152. }
  1153.  
  1154. watchMissileUsage()
  1155. {
  1156. self endon( "death" );
  1157. self endon( "disconnect" );
  1158.  
  1159. for ( ;; )
  1160. {
  1161. self waittill( "missile_fire", missile, weaponName );
  1162.  
  1163. if ( isSubStr( weaponName, "gl_" ) )
  1164. {
  1165. missile.primaryWeapon = self getCurrentPrimaryWeapon();
  1166. missile thread maps\mp\gametypes\_shellshock::grenade_earthQuake();
  1167. }
  1168.  
  1169. switch ( weaponName )
  1170. {
  1171. case "at4_mp":
  1172. case "stinger_mp":
  1173. level notify ( "stinger_fired", self, missile, self.stingerTarget );
  1174. self thread setAltSceneObj( missile, "tag_origin", 65 );
  1175. break;
  1176. case "javelin_mp":
  1177. level notify ( "stinger_fired", self, missile, self.javelinTarget );
  1178. self thread setAltSceneObj( missile, "tag_origin", 65 );
  1179. break;
  1180. default:
  1181. break;
  1182. }
  1183.  
  1184. switch ( weaponName )
  1185. {
  1186. case "at4_mp":
  1187. case "javelin_mp":
  1188. case "rpg_mp":
  1189. case "ac130_105mm_mp":
  1190. case "ac130_40mm_mp":
  1191. case "remotemissile_projectile_mp":
  1192. missile thread maps\mp\gametypes\_shellshock::grenade_earthQuake();
  1193. default:
  1194. break;
  1195. }
  1196. }
  1197. }
  1198.  
  1199.  
  1200. watchSentryUsage()
  1201. {
  1202. self endon( "death" );
  1203. self endon( "disconnect" );
  1204.  
  1205. for ( ;; )
  1206. {
  1207. self waittill( "sentry_placement_finished", sentry );
  1208.  
  1209. self thread setAltSceneObj( sentry, "tag_flash", 65 );
  1210. }
  1211. }
  1212.  
  1213.  
  1214. empExplodeWaiter()
  1215. {
  1216. self thread maps\mp\gametypes\_shellshock::endOnDeath();
  1217. self endon( "end_explode" );
  1218.  
  1219. self waittill( "explode", position );
  1220.  
  1221. ents = getEMPDamageEnts( position, 512, false );
  1222.  
  1223. foreach ( ent in ents )
  1224. {
  1225. if ( isDefined( ent.owner ) && !friendlyFireCheck( self.owner, ent.owner ) )
  1226. continue;
  1227.  
  1228. ent notify( "emp_damage", self.owner, 8.0 );
  1229. }
  1230. }
  1231.  
  1232.  
  1233. beginC4Tracking()
  1234. {
  1235. self endon( "death" );
  1236. self endon( "disconnect" );
  1237.  
  1238. self waittill_any( "grenade_fire", "weapon_change", "offhand_end" );
  1239. }
  1240.  
  1241.  
  1242. watchForThrowbacks()
  1243. {
  1244. self endon( "death" );
  1245. self endon( "disconnect" );
  1246.  
  1247. for ( ;; )
  1248. {
  1249. self waittill( "grenade_fire", grenade, weapname );
  1250.  
  1251. if ( self.gotPullbackNotify )
  1252. {
  1253. self.gotPullbackNotify = false;
  1254. continue;
  1255. }
  1256. if ( !isSubStr( weapname, "frag_" ) && !isSubStr( weapname, "semtex_" ) )
  1257. continue;
  1258.  
  1259. // no grenade_pullback notify! we must have picked it up off the ground.
  1260. grenade.threwBack = true;
  1261. self thread incPlayerStat( "throwbacks", 1 );
  1262.  
  1263. grenade thread maps\mp\gametypes\_shellshock::grenade_earthQuake();
  1264. grenade.originalOwner = self;
  1265. }
  1266. }
  1267.  
  1268.  
  1269. watchC4()
  1270. {
  1271. self endon( "spawned_player" );
  1272. self endon( "disconnect" );
  1273.  
  1274. //maxc4 = 2;
  1275.  
  1276. while ( 1 )
  1277. {
  1278. self waittill( "grenade_fire", c4, weapname );
  1279. if ( weapname == "c4" || weapname == "c4_mp" )
  1280. {
  1281. if ( !self.c4array.size )
  1282. self thread watchC4AltDetonate();
  1283.  
  1284. if ( self.c4array.size )
  1285. {
  1286. self.c4array = array_removeUndefined( self.c4array );
  1287.  
  1288. if( self.c4array.size >= level.maxPerPlayerExplosives )
  1289. {
  1290. self.c4array[0] detonate();
  1291. }
  1292. }
  1293.  
  1294. self.c4array[ self.c4array.size ] = c4;
  1295. c4.owner = self;
  1296. c4.team = self.team;
  1297. c4.activated = false;
  1298. c4.weaponName = weapname;
  1299.  
  1300. c4 thread maps\mp\gametypes\_shellshock::c4_earthQuake();
  1301. c4 thread c4Activate();
  1302. c4 thread c4Damage();
  1303. c4 thread c4EMPDamage();
  1304. c4 thread c4EMPKillstreakWait();
  1305. //c4 thread c4DetectionTrigger( self.pers[ "team" ] );
  1306. }
  1307. }
  1308. }
  1309.  
  1310.  
  1311. c4EMPDamage()
  1312. {
  1313. self endon( "death" );
  1314.  
  1315. for ( ;; )
  1316. {
  1317. self waittill( "emp_damage", attacker, duration );
  1318.  
  1319. playfxOnTag( getfx( "sentry_explode_mp" ), self, "tag_origin" );
  1320.  
  1321. self.disabled = true;
  1322. self notify( "disabled" );
  1323.  
  1324. wait( duration );
  1325.  
  1326. self.disabled = undefined;
  1327. self notify( "enabled" );
  1328. }
  1329. }
  1330.  
  1331.  
  1332. c4EMPKillstreakWait()
  1333. {
  1334. self endon( "death" );
  1335.  
  1336. for ( ;; )
  1337. {
  1338. level waittill( "emp_update" );
  1339.  
  1340. if ( (level.teamBased && level.teamEMPed[self.team]) || (!level.teamBased && isDefined( level.empPlayer ) && level.empPlayer != self.owner ) )
  1341. {
  1342. self.disabled = true;
  1343. self notify( "disabled" );
  1344. }
  1345. else
  1346. {
  1347. self.disabled = undefined;
  1348. self notify( "enabled" );
  1349. }
  1350. }
  1351. }
  1352.  
  1353.  
  1354. setClaymoreTeamHeadIcon( team )
  1355. {
  1356. self endon( "death" );
  1357. wait .05;
  1358. if ( level.teamBased )
  1359. self maps\mp\_entityheadicons::setTeamHeadIcon( team, ( 0, 0, 20 ) );
  1360. else if ( isDefined( self.owner ) )
  1361. self maps\mp\_entityheadicons::setPlayerHeadIcon( self.owner, (0,0,20) );
  1362. }
  1363.  
  1364.  
  1365. watchClaymores()
  1366. {
  1367. self endon( "spawned_player" );
  1368. self endon( "disconnect" );
  1369.  
  1370. self.claymorearray = [];
  1371. while ( 1 )
  1372. {
  1373. self waittill( "grenade_fire", claymore, weapname );
  1374. if ( weapname == "claymore" || weapname == "claymore_mp" )
  1375. {
  1376. self.claymorearray = array_removeUndefined( self.claymorearray );
  1377.  
  1378. if( self.claymoreArray.size >= level.maxPerPlayerExplosives )
  1379. self.claymoreArray[0] detonate();
  1380.  
  1381. self.claymorearray[ self.claymorearray.size ] = claymore;
  1382. claymore.owner = self;
  1383. claymore.team = self.team;
  1384. claymore.weaponName = weapname;
  1385.  
  1386. claymore thread c4Damage();
  1387. claymore thread c4EMPDamage();
  1388. claymore thread c4EMPKillstreakWait();
  1389. claymore thread claymoreDetonation();
  1390. //claymore thread claymoreDetectionTrigger_wait( self.pers[ "team" ] );
  1391. claymore thread setClaymoreTeamHeadIcon( self.pers[ "team" ] );
  1392.  
  1393. /#
  1394. if ( getdvarint( "scr_claymoredebug" ) )
  1395. {
  1396. claymore thread claymoreDebug();
  1397. }
  1398. #/
  1399. }
  1400. }
  1401. }
  1402.  
  1403. /#
  1404. claymoreDebug()
  1405. {
  1406. self waittill( "missile_stuck" );
  1407. self thread showCone( acos( level.claymoreDetectionDot ), level.claymoreDetonateRadius, ( 1, .85, 0 ) );
  1408. self thread showCone( 60, 256, ( 1, 0, 0 ) );
  1409. }
  1410.  
  1411. vectorcross( v1, v2 )
  1412. {
  1413. return( v1[ 1 ] * v2[ 2 ] - v1[ 2 ] * v2[ 1 ], v1[ 2 ] * v2[ 0 ] - v1[ 0 ] * v2[ 2 ], v1[ 0 ] * v2[ 1 ] - v1[ 1 ] * v2[ 0 ] );
  1414. }
  1415.  
  1416. showCone( angle, range, color )
  1417. {
  1418. self endon( "death" );
  1419.  
  1420. start = self.origin;
  1421. forward = anglestoforward( self.angles );
  1422. right = vectorcross( forward, ( 0, 0, 1 ) );
  1423. up = vectorcross( forward, right );
  1424.  
  1425. fullforward = forward * range * cos( angle );
  1426. sideamnt = range * sin( angle );
  1427.  
  1428. while ( 1 )
  1429. {
  1430. prevpoint = ( 0, 0, 0 );
  1431. for ( i = 0; i <= 20; i++ )
  1432. {
  1433. coneangle = i / 20.0 * 360;
  1434. point = start + fullforward + sideamnt * ( right * cos( coneangle ) + up * sin( coneangle ) );
  1435. if ( i > 0 )
  1436. {
  1437. line( start, point, color );
  1438. line( prevpoint, point, color );
  1439. }
  1440. prevpoint = point;
  1441. }
  1442. wait .05;
  1443. }
  1444. }
  1445. #/
  1446.  
  1447. claymoreDetonation()
  1448. {
  1449. self endon( "death" );
  1450.  
  1451. self waittill( "missile_stuck" );
  1452.  
  1453. damagearea = spawn( "trigger_radius", self.origin + ( 0, 0, 0 - level.claymoreDetonateRadius ), 0, level.claymoreDetonateRadius, level.claymoreDetonateRadius * 2 );
  1454. self thread deleteOnDeath( damagearea );
  1455.  
  1456. while ( 1 )
  1457. {
  1458. damagearea waittill( "trigger", player );
  1459.  
  1460. if ( getdvarint( "scr_claymoredebug" ) != 1 )
  1461. {
  1462. if ( isdefined( self.owner ) && player == self.owner )
  1463. continue;
  1464. if ( !friendlyFireCheck( self.owner, player, 0 ) )
  1465. continue;
  1466. }
  1467. if ( lengthsquared( player getVelocity() ) < 10 )
  1468. continue;
  1469.  
  1470. if ( !player shouldAffectClaymore( self ) )
  1471. continue;
  1472.  
  1473. if ( player damageConeTrace( self.origin, self ) > 0 )
  1474. break;
  1475. }
  1476.  
  1477. self playsound ("claymore_activated");
  1478.  
  1479.  
  1480. if ( player _hasPerk( "specialty_delaymine" ) )
  1481. wait 3.0;
  1482. else
  1483. wait level.claymoreDetectionGracePeriod;
  1484.  
  1485. self detonate();
  1486. }
  1487.  
  1488. shouldAffectClaymore( claymore )
  1489. {
  1490. if ( isDefined( claymore.disabled ) )
  1491. return false;
  1492.  
  1493. pos = self.origin + ( 0, 0, 32 );
  1494.  
  1495. dirToPos = pos - claymore.origin;
  1496. claymoreForward = anglesToForward( claymore.angles );
  1497.  
  1498. dist = vectorDot( dirToPos, claymoreForward );
  1499. if ( dist < level.claymoreDetectionMinDist )
  1500. return false;
  1501.  
  1502. dirToPos = vectornormalize( dirToPos );
  1503.  
  1504. dot = vectorDot( dirToPos, claymoreForward );
  1505. return( dot > level.claymoreDetectionDot );
  1506. }
  1507.  
  1508. deleteOnDeath( ent )
  1509. {
  1510. self waittill( "death" );
  1511. wait .05;
  1512. if ( isdefined( ent ) )
  1513. ent delete();
  1514. }
  1515.  
  1516. c4Activate()
  1517. {
  1518. self endon( "death" );
  1519.  
  1520. self waittill( "missile_stuck" );
  1521.  
  1522. wait 0.05;
  1523.  
  1524. self notify( "activated" );
  1525. self.activated = true;
  1526. }
  1527.  
  1528. watchC4AltDetonate()
  1529. {
  1530. self endon( "death" );
  1531. self endon( "disconnect" );
  1532. self endon( "detonated" );
  1533. level endon( "game_ended" );
  1534.  
  1535. buttonTime = 0;
  1536. for ( ;; )
  1537. {
  1538. if ( self UseButtonPressed() )
  1539. {
  1540. buttonTime = 0;
  1541. while ( self UseButtonPressed() )
  1542. {
  1543. buttonTime += 0.05;
  1544. wait( 0.05 );
  1545. }
  1546.  
  1547. println( "pressTime1: " + buttonTime );
  1548. if ( buttonTime >= 0.5 )
  1549. continue;
  1550.  
  1551. buttonTime = 0;
  1552. while ( !self UseButtonPressed() && buttonTime < 0.5 )
  1553. {
  1554. buttonTime += 0.05;
  1555. wait( 0.05 );
  1556. }
  1557.  
  1558. println( "delayTime: " + buttonTime );
  1559. if ( buttonTime >= 0.5 )
  1560. continue;
  1561.  
  1562. if ( !self.c4Array.size )
  1563. return;
  1564.  
  1565. self notify( "alt_detonate" );
  1566. }
  1567. wait( 0.05 );
  1568. }
  1569. }
  1570.  
  1571. watchC4Detonation()
  1572. {
  1573. self endon( "death" );
  1574. self endon( "disconnect" );
  1575.  
  1576. while ( 1 )
  1577. {
  1578. self waittillmatch( "detonate", "c4_mp" );
  1579. newarray = [];
  1580. for ( i = 0; i < self.c4array.size; i++ )
  1581. {
  1582. c4 = self.c4array[ i ];
  1583. if ( isdefined( self.c4array[ i ] ) )
  1584. c4 thread waitAndDetonate( 0.1 );
  1585. }
  1586. self.c4array = newarray;
  1587. self notify( "detonated" );
  1588. }
  1589. }
  1590.  
  1591.  
  1592. watchC4AltDetonation()
  1593. {
  1594. self endon( "death" );
  1595. self endon( "disconnect" );
  1596.  
  1597. while ( 1 )
  1598. {
  1599. self waittill( "alt_detonate" );
  1600. weap = self getCurrentWeapon();
  1601. if ( weap != "c4_mp" )
  1602. {
  1603. newarray = [];
  1604. for ( i = 0; i < self.c4array.size; i++ )
  1605. {
  1606. c4 = self.c4array[ i ];
  1607. if ( isdefined( self.c4array[ i ] ) )
  1608. c4 thread waitAndDetonate( 0.1 );
  1609. }
  1610. self.c4array = newarray;
  1611. self notify( "detonated" );
  1612. }
  1613. }
  1614. }
  1615.  
  1616.  
  1617. waitAndDetonate( delay )
  1618. {
  1619. self endon( "death" );
  1620. wait delay;
  1621.  
  1622. self waitTillEnabled();
  1623.  
  1624. self detonate();
  1625. }
  1626.  
  1627. deleteC4AndClaymoresOnDisconnect()
  1628. {
  1629. self endon( "death" );
  1630. self waittill( "disconnect" );
  1631.  
  1632. c4array = self.c4array;
  1633. claymorearray = self.claymorearray;
  1634.  
  1635. wait .05;
  1636.  
  1637. for ( i = 0; i < c4array.size; i++ )
  1638. {
  1639. if ( isdefined( c4array[ i ] ) )
  1640. c4array[ i ] delete();
  1641. }
  1642. for ( i = 0; i < claymorearray.size; i++ )
  1643. {
  1644. if ( isdefined( claymorearray[ i ] ) )
  1645. claymorearray[ i ] delete();
  1646. }
  1647. }
  1648.  
  1649. c4Damage()
  1650. {
  1651. self endon( "death" );
  1652.  
  1653. self setcandamage( true );
  1654. self.maxhealth = 100000;
  1655. self.health = self.maxhealth;
  1656.  
  1657. attacker = undefined;
  1658.  
  1659. while ( 1 )
  1660. {
  1661. self waittill( "damage", damage, attacker, direction_vec, point, type, modelName, tagName, partName, iDFlags );
  1662. if ( !isPlayer( attacker ) )
  1663. continue;
  1664.  
  1665. // don't allow people to destroy C4 on their team if FF is off
  1666. if ( !friendlyFireCheck( self.owner, attacker ) )
  1667. continue;
  1668.  
  1669. if ( damage < 5 )// ignore concussion grenades
  1670. continue;
  1671.  
  1672. break;
  1673. }
  1674.  
  1675. if ( level.c4explodethisframe )
  1676. wait .1 + randomfloat( .4 );
  1677. else
  1678. wait .05;
  1679.  
  1680. if ( !isdefined( self ) )
  1681. return;
  1682.  
  1683. level.c4explodethisframe = true;
  1684.  
  1685. thread resetC4ExplodeThisFrame();
  1686.  
  1687. if ( isDefined( type ) && ( isSubStr( type, "MOD_GRENADE" ) || isSubStr( type, "MOD_EXPLOSIVE" ) ) )
  1688. self.wasChained = true;
  1689.  
  1690. if ( isDefined( iDFlags ) && ( iDFlags & level.iDFLAGS_PENETRATION ) )
  1691. self.wasDamagedFromBulletPenetration = true;
  1692.  
  1693. self.wasDamaged = true;
  1694.  
  1695. if ( level.teamBased )
  1696. {
  1697. // "destroyed_explosive" notify, for challenges
  1698. if ( isdefined( attacker ) && isdefined( attacker.pers[ "team" ] ) && isdefined( self.owner ) && isdefined( self.owner.pers[ "team" ] ) )
  1699. {
  1700. if ( attacker.pers[ "team" ] != self.owner.pers[ "team" ] )
  1701. attacker notify( "destroyed_explosive" );
  1702. }
  1703. }
  1704. else
  1705. {
  1706. // checking isDefined attacker is defensive but it's too late in the project to risk issues by not having it
  1707. if ( isDefined( self.owner ) && isDefined( attacker ) && attacker != self.owner )
  1708. attacker notify( "destroyed_explosive" );
  1709. }
  1710.  
  1711. self detonate( attacker );
  1712. // won't get here; got death notify.
  1713. }
  1714.  
  1715. resetC4ExplodeThisFrame()
  1716. {
  1717. wait .05;
  1718. level.c4explodethisframe = false;
  1719. }
  1720.  
  1721. saydamaged( orig, amount )
  1722. {
  1723. for ( i = 0; i < 60; i++ )
  1724. {
  1725. print3d( orig, "damaged! " + amount );
  1726. wait .05;
  1727. }
  1728. }
  1729.  
  1730. waitTillEnabled()
  1731. {
  1732. if ( !isDefined( self.disabled ) )
  1733. return;
  1734.  
  1735. self waittill( "enabled" );
  1736. assert( !isDefined( self.disabled ) );
  1737. }
  1738.  
  1739.  
  1740. c4DetectionTrigger( ownerTeam )
  1741. {
  1742. self waittill( "activated" );
  1743.  
  1744. trigger = spawn( "trigger_radius", self.origin - ( 0, 0, 128 ), 0, 512, 256 );
  1745. trigger.detectId = "trigger" + getTime() + randomInt( 1000000 );
  1746.  
  1747. trigger.owner = self;
  1748. trigger thread detectIconWaiter( level.otherTeam[ ownerTeam ] );
  1749.  
  1750. self waittill( "death" );
  1751. trigger notify( "end_detection" );
  1752.  
  1753. if ( isDefined( trigger.bombSquadIcon ) )
  1754. trigger.bombSquadIcon destroy();
  1755.  
  1756. trigger delete();
  1757. }
  1758.  
  1759.  
  1760. claymoreDetectionTrigger_wait( ownerTeam )
  1761. {
  1762. self endon( "death" );
  1763. self waittill( "missile_stuck" );
  1764.  
  1765. self thread claymoreDetectionTrigger( ownerTeam );
  1766. }
  1767.  
  1768. claymoreDetectionTrigger( ownerTeam )
  1769. {
  1770. trigger = spawn( "trigger_radius", self.origin - ( 0, 0, 128 ), 0, 512, 256 );
  1771. trigger.detectId = "trigger" + getTime() + randomInt( 1000000 );
  1772.  
  1773. trigger.owner = self;
  1774. trigger thread detectIconWaiter( level.otherTeam[ ownerTeam ] );
  1775.  
  1776. self waittill( "death" );
  1777. trigger notify( "end_detection" );
  1778.  
  1779. if ( isDefined( trigger.bombSquadIcon ) )
  1780. trigger.bombSquadIcon destroy();
  1781.  
  1782. trigger delete();
  1783. }
  1784.  
  1785.  
  1786. detectIconWaiter( detectTeam )
  1787. {
  1788. self endon( "end_detection" );
  1789. level endon( "game_ended" );
  1790.  
  1791. while ( !level.gameEnded )
  1792. {
  1793. self waittill( "trigger", player );
  1794.  
  1795. if ( !player.detectExplosives )
  1796. continue;
  1797.  
  1798. if ( level.teamBased && player.team != detectTeam )
  1799. continue;
  1800. else if ( !level.teamBased && player == self.owner.owner )
  1801. continue;
  1802.  
  1803. if ( isDefined( player.bombSquadIds[ self.detectId ] ) )
  1804. continue;
  1805.  
  1806. player thread showHeadIcon( self );
  1807. }
  1808. }
  1809.  
  1810.  
  1811. setupBombSquad()
  1812. {
  1813. self.bombSquadIds = [];
  1814.  
  1815. if ( self.detectExplosives && !self.bombSquadIcons.size )
  1816. {
  1817. for ( index = 0; index < 4; index++ )
  1818. {
  1819. self.bombSquadIcons[ index ] = newClientHudElem( self );
  1820. self.bombSquadIcons[ index ].x = 0;
  1821. self.bombSquadIcons[ index ].y = 0;
  1822. self.bombSquadIcons[ index ].z = 0;
  1823. self.bombSquadIcons[ index ].alpha = 0;
  1824. self.bombSquadIcons[ index ].archived = true;
  1825. self.bombSquadIcons[ index ] setShader( "waypoint_bombsquad", 14, 14 );
  1826. self.bombSquadIcons[ index ] setWaypoint( false, false );
  1827. self.bombSquadIcons[ index ].detectId = "";
  1828. }
  1829. }
  1830. else if ( !self.detectExplosives )
  1831. {
  1832. for ( index = 0; index < self.bombSquadIcons.size; index++ )
  1833. self.bombSquadIcons[ index ] destroy();
  1834.  
  1835. self.bombSquadIcons = [];
  1836. }
  1837. }
  1838.  
  1839.  
  1840. showHeadIcon( trigger )
  1841. {
  1842. triggerDetectId = trigger.detectId;
  1843. useId = -1;
  1844. for ( index = 0; index < 4; index++ )
  1845. {
  1846. detectId = self.bombSquadIcons[ index ].detectId;
  1847.  
  1848. if ( detectId == triggerDetectId )
  1849. return;
  1850.  
  1851. if ( detectId == "" )
  1852. useId = index;
  1853. }
  1854.  
  1855. if ( useId < 0 )
  1856. return;
  1857.  
  1858. self.bombSquadIds[ triggerDetectId ] = true;
  1859.  
  1860. self.bombSquadIcons[ useId ].x = trigger.origin[ 0 ];
  1861. self.bombSquadIcons[ useId ].y = trigger.origin[ 1 ];
  1862. self.bombSquadIcons[ useId ].z = trigger.origin[ 2 ] + 24 + 128;
  1863.  
  1864. self.bombSquadIcons[ useId ] fadeOverTime( 0.25 );
  1865. self.bombSquadIcons[ useId ].alpha = 1;
  1866. self.bombSquadIcons[ useId ].detectId = trigger.detectId;
  1867.  
  1868. while ( isAlive( self ) && isDefined( trigger ) && self isTouching( trigger ) )
  1869. wait( 0.05 );
  1870.  
  1871. if ( !isDefined( self ) )
  1872. return;
  1873.  
  1874. self.bombSquadIcons[ useId ].detectId = "";
  1875. self.bombSquadIcons[ useId ] fadeOverTime( 0.25 );
  1876. self.bombSquadIcons[ useId ].alpha = 0;
  1877. self.bombSquadIds[ triggerDetectId ] = undefined;
  1878. }
  1879.  
  1880.  
  1881. // these functions are used with scripted weapons (like c4, claymores, artillery)
  1882. // returns an array of objects representing damageable entities (including players) within a given sphere.
  1883. // each object has the property damageCenter, which represents its center (the location from which it can be damaged).
  1884. // each object also has the property entity, which contains the entity that it represents.
  1885. // to damage it, call damageEnt() on it.
  1886. getDamageableEnts( pos, radius, doLOS, startRadius )
  1887. {
  1888. ents = [];
  1889.  
  1890. if ( !isdefined( doLOS ) )
  1891. doLOS = false;
  1892.  
  1893. if ( !isdefined( startRadius ) )
  1894. startRadius = 0;
  1895.  
  1896. radiusSq = radius * radius;
  1897.  
  1898. // players
  1899. players = level.players;
  1900. for ( i = 0; i < players.size; i++ )
  1901. {
  1902. if ( !isalive( players[ i ] ) || players[ i ].sessionstate != "playing" )
  1903. continue;
  1904.  
  1905. playerpos = get_damageable_player_pos( players[ i ] );
  1906. distSq = distanceSquared( pos, playerpos );
  1907. if ( distSq < radiusSq && ( !doLOS || weaponDamageTracePassed( pos, playerpos, startRadius, players[ i ] ) ) )
  1908. {
  1909. ents[ ents.size ] = get_damageable_player( players[ i ], playerpos );
  1910. }
  1911. }
  1912.  
  1913. // grenades
  1914. grenades = getentarray( "grenade", "classname" );
  1915. for ( i = 0; i < grenades.size; i++ )
  1916. {
  1917. entpos = get_damageable_grenade_pos( grenades[ i ] );
  1918. distSq = distanceSquared( pos, entpos );
  1919. if ( distSq < radiusSq && ( !doLOS || weaponDamageTracePassed( pos, entpos, startRadius, grenades[ i ] ) ) )
  1920. {
  1921. ents[ ents.size ] = get_damageable_grenade( grenades[ i ], entpos );
  1922. }
  1923. }
  1924.  
  1925. destructibles = getentarray( "destructible", "targetname" );
  1926. for ( i = 0; i < destructibles.size; i++ )
  1927. {
  1928. entpos = destructibles[ i ].origin;
  1929. distSq = distanceSquared( pos, entpos );
  1930. if ( distSq < radiusSq && ( !doLOS || weaponDamageTracePassed( pos, entpos, startRadius, destructibles[ i ] ) ) )
  1931. {
  1932. newent = spawnstruct();
  1933. newent.isPlayer = false;
  1934. newent.isADestructable = false;
  1935. newent.entity = destructibles[ i ];
  1936. newent.damageCenter = entpos;
  1937. ents[ ents.size ] = newent;
  1938. }
  1939. }
  1940.  
  1941. destructables = getentarray( "destructable", "targetname" );
  1942. for ( i = 0; i < destructables.size; i++ )
  1943. {
  1944. entpos = destructables[ i ].origin;
  1945. distSq = distanceSquared( pos, entpos );
  1946. if ( distSq < radiusSq && ( !doLOS || weaponDamageTracePassed( pos, entpos, startRadius, destructables[ i ] ) ) )
  1947. {
  1948. newent = spawnstruct();
  1949. newent.isPlayer = false;
  1950. newent.isADestructable = true;
  1951. newent.entity = destructables[ i ];
  1952. newent.damageCenter = entpos;
  1953. ents[ ents.size ] = newent;
  1954. }
  1955. }
  1956.  
  1957. //sentries
  1958. sentries = getentarray( "misc_turret", "classname" );
  1959. foreach ( sentry in sentries )
  1960. {
  1961. entpos = sentry.origin + (0,0,32);
  1962. distSq = distanceSquared( pos, entpos );
  1963. if ( distSq < radiusSq && ( !doLOS || weaponDamageTracePassed( pos, entpos, startRadius, sentry ) ) )
  1964. {
  1965. if ( sentry.model == "sentry_minigun" )
  1966. ents[ ents.size ] = get_damageable_sentry(sentry, entpos);
  1967. }
  1968. }
  1969.  
  1970. return ents;
  1971. }
  1972.  
  1973.  
  1974. getEMPDamageEnts( pos, radius, doLOS, startRadius )
  1975. {
  1976. ents = [];
  1977.  
  1978. if ( !isDefined( doLOS ) )
  1979. doLOS = false;
  1980.  
  1981. if ( !isDefined( startRadius ) )
  1982. startRadius = 0;
  1983.  
  1984. grenades = getEntArray( "grenade", "classname" );
  1985. foreach ( grenade in grenades )
  1986. {
  1987. //if ( !isDefined( grenade.weaponName ) )
  1988. // continue;
  1989.  
  1990. entpos = grenade.origin;
  1991. dist = distance( pos, entpos );
  1992. if ( dist < radius && ( !doLOS || weaponDamageTracePassed( pos, entpos, startRadius, grenade ) ) )
  1993. ents[ ents.size ] = grenade;
  1994. }
  1995.  
  1996. turrets = getEntArray( "misc_turret", "classname" );
  1997. foreach ( turret in turrets )
  1998. {
  1999. //if ( !isDefined( turret.weaponName ) )
  2000. // continue;
  2001.  
  2002. entpos = turret.origin;
  2003. dist = distance( pos, entpos );
  2004. if ( dist < radius && ( !doLOS || weaponDamageTracePassed( pos, entpos, startRadius, turret ) ) )
  2005. ents[ ents.size ] = turret;
  2006. }
  2007.  
  2008. return ents;
  2009. }
  2010.  
  2011.  
  2012. weaponDamageTracePassed( from, to, startRadius, ent )
  2013. {
  2014. midpos = undefined;
  2015.  
  2016. diff = to - from;
  2017. if ( lengthsquared( diff ) < startRadius * startRadius )
  2018. return true;
  2019.  
  2020. dir = vectornormalize( diff );
  2021. midpos = from + ( dir[ 0 ] * startRadius, dir[ 1 ] * startRadius, dir[ 2 ] * startRadius );
  2022.  
  2023. trace = bullettrace( midpos, to, false, ent );
  2024.  
  2025. if ( getdvarint( "scr_damage_debug" ) != 0 )
  2026. {
  2027. thread debugprint( from, ".dmg" );
  2028. if ( isdefined( ent ) )
  2029. thread debugprint( to, "." + ent.classname );
  2030. else
  2031. thread debugprint( to, ".undefined" );
  2032. if ( trace[ "fraction" ] == 1 )
  2033. {
  2034. thread debugline( midpos, to, ( 1, 1, 1 ) );
  2035. }
  2036. else
  2037. {
  2038. thread debugline( midpos, trace[ "position" ], ( 1, .9, .8 ) );
  2039. thread debugline( trace[ "position" ], to, ( 1, .4, .3 ) );
  2040. }
  2041. }
  2042.  
  2043. return( trace[ "fraction" ] == 1 );
  2044. }
  2045.  
  2046. // eInflictor = the entity that causes the damage (e.g. a claymore)
  2047. // eAttacker = the player that is attacking
  2048. // iDamage = the amount of damage to do
  2049. // sMeansOfDeath = string specifying the method of death (e.g. "MOD_PROJECTILE_SPLASH")
  2050. // sWeapon = string specifying the weapon used (e.g. "claymore_mp")
  2051. // damagepos = the position damage is coming from
  2052. // damagedir = the direction damage is moving in
  2053. damageEnt( eInflictor, eAttacker, iDamage, sMeansOfDeath, sWeapon, damagepos, damagedir )
  2054. {
  2055. if ( self.isPlayer )
  2056. {
  2057. self.damageOrigin = damagepos;
  2058. self.entity thread [[ level.callbackPlayerDamage ]](
  2059. eInflictor,// eInflictor The entity that causes the damage.( e.g. a turret )
  2060. eAttacker,// eAttacker The entity that is attacking.
  2061. iDamage,// iDamage Integer specifying the amount of damage done
  2062. 0,// iDFlags Integer specifying flags that are to be applied to the damage
  2063. sMeansOfDeath,// sMeansOfDeath Integer specifying the method of death
  2064. sWeapon,// sWeapon The weapon number of the weapon used to inflict the damage
  2065. damagepos,// vPoint The point the damage is from?
  2066. damagedir,// vDir The direction of the damage
  2067. "none",// sHitLoc The location of the hit
  2068. 0// psOffsetTime The time offset for the damage
  2069. );
  2070. }
  2071. else
  2072. {
  2073. // destructable walls and such can only be damaged in certain ways.
  2074. if ( self.isADestructable && ( sWeapon == "artillery_mp" || sWeapon == "claymore_mp" ) || sWeapon == "stealth_bomb_mp" )
  2075. return;
  2076.  
  2077. self.entity notify( "damage", iDamage, eAttacker, ( 0, 0, 0 ), ( 0, 0, 0 ), "mod_explosive", "", "" );
  2078. }
  2079. }
  2080.  
  2081.  
  2082. debugline( a, b, color )
  2083. {
  2084. for ( i = 0; i < 30 * 20; i++ )
  2085. {
  2086. line( a, b, color );
  2087. wait .05;
  2088. }
  2089. }
  2090.  
  2091. debugprint( pt, txt )
  2092. {
  2093. for ( i = 0; i < 30 * 20; i++ )
  2094. {
  2095. print3d( pt, txt );
  2096. wait .05;
  2097. }
  2098. }
  2099.  
  2100.  
  2101. onWeaponDamage( eInflictor, sWeapon, meansOfDeath, damage, eAttacker )
  2102. {
  2103. self endon( "death" );
  2104. self endon( "disconnect" );
  2105.  
  2106. switch( sWeapon )
  2107. {
  2108. case "concussion_grenade_mp":
  2109. // should match weapon settings in gdt
  2110. radius = 512;
  2111. scale = 1 - ( distance( self.origin, eInflictor.origin ) / radius );
  2112.  
  2113. if ( scale < 0 )
  2114. scale = 0;
  2115.  
  2116. time = 2 + ( 4 * scale );
  2117.  
  2118. wait( 0.05 );
  2119. eAttacker notify( "stun_hit" );
  2120. self shellShock( "concussion_grenade_mp", time );
  2121. self.concussionEndTime = getTime() + ( time * 1000 );
  2122. break;
  2123.  
  2124. case "weapon_cobra_mk19_mp":
  2125. // mk19 is too powerful with shellshock slowdown
  2126. break;
  2127.  
  2128. default:
  2129. // shellshock will only be done if meansofdeath is an appropriate type and if there is enough damage.
  2130. maps\mp\gametypes\_shellshock::shellshockOnDamage( meansOfDeath, damage );
  2131. break;
  2132. }
  2133.  
  2134. }
  2135.  
  2136. // weapon stowing logic ===================================================================
  2137.  
  2138. // weapon class boolean helpers
  2139. isPrimaryWeapon( weapName )
  2140. {
  2141. if ( weapName == "none" )
  2142. return false;
  2143.  
  2144. if ( weaponInventoryType( weapName ) != "primary" )
  2145. return false;
  2146.  
  2147. switch ( weaponClass( weapName ) )
  2148. {
  2149. case "rifle":
  2150. case "smg":
  2151. case "mg":
  2152. case "spread":
  2153. case "pistol":
  2154. case "rocketlauncher":
  2155. case "sniper":
  2156. return true;
  2157.  
  2158. default:
  2159. return false;
  2160. }
  2161. }
  2162.  
  2163.  
  2164. isAltModeWeapon( weapName )
  2165. {
  2166. if ( weapName == "none" )
  2167. return false;
  2168.  
  2169. return ( weaponInventoryType( weapName ) == "altmode" );
  2170. }
  2171.  
  2172. isInventoryWeapon( weapName )
  2173. {
  2174. if ( weapName == "none" )
  2175. return false;
  2176.  
  2177. return ( weaponInventoryType( weapName ) == "item" );
  2178. }
  2179.  
  2180. isRiotShield( weapName )
  2181. {
  2182. if ( weapName == "none" )
  2183. return false;
  2184.  
  2185. return ( WeaponType( weapName ) == "riotshield" );
  2186. }
  2187.  
  2188. isOffhandWeapon( weapName )
  2189. {
  2190. if ( weapName == "none" )
  2191. return false;
  2192.  
  2193. return ( weaponInventoryType( weapName ) == "offhand" );
  2194. }
  2195.  
  2196. isSideArm( weapName )
  2197. {
  2198. if ( weapName == "none" )
  2199. return false;
  2200.  
  2201. if ( weaponInventoryType( weapName ) != "primary" )
  2202. return false;
  2203.  
  2204. return ( weaponClass( weapName ) == "pistol" );
  2205. }
  2206.  
  2207.  
  2208. // This needs for than this.. this would qualify c4 as a grenade
  2209. isGrenade( weapName )
  2210. {
  2211. weapClass = weaponClass( weapName );
  2212. weapType = weaponInventoryType( weapName );
  2213.  
  2214. if ( weapClass != "grenade" )
  2215. return false;
  2216.  
  2217. if ( weapType != "offhand" )
  2218. return false;
  2219. }
  2220.  
  2221.  
  2222. getStowOffsetModel( weaponName )
  2223. {
  2224. assert( isDefined( level.stow_offset_array ) );
  2225.  
  2226. baseName = getBaseWeaponName( weaponName );
  2227.  
  2228. return( level.stow_offset_array[baseName] );
  2229. }
  2230.  
  2231.  
  2232. stowPriorityWeapon()
  2233. {
  2234. assert( isdefined( level.stow_priority_model_array ) );
  2235.  
  2236. // returns the first large projectil the player owns in case player owns more than one
  2237. foreach ( weapon_name, priority_weapon in level.stow_priority_model_array )
  2238. {
  2239. weaponName = getBaseWeaponName( weapon_name );
  2240. weaponList = self getWeaponsListAll();
  2241.  
  2242. foreach ( weapon in weaponList )
  2243. {
  2244. if( self getCurrentWeapon() == weapon )
  2245. continue;
  2246.  
  2247. if ( weaponName == getBaseWeaponName( weapon ) )
  2248. return weaponName + "_mp";
  2249. }
  2250. }
  2251.  
  2252. return "";
  2253. }
  2254.  
  2255. // thread loop life = player's life
  2256. updateStowedWeapon()
  2257. {
  2258. self endon( "spawned" );
  2259. self endon( "killed_player" );
  2260. self endon( "disconnect" );
  2261.  
  2262. self.tag_stowed_back = undefined;
  2263. self.tag_stowed_hip = undefined;
  2264.  
  2265. team = self.team;
  2266. class = self.class;
  2267.  
  2268. self thread stowedWeaponsRefresh();
  2269.  
  2270. while ( true )
  2271. {
  2272. self waittill( "weapon_change", newWeapon );
  2273.  
  2274. if ( newWeapon == "none" )
  2275. continue;
  2276.  
  2277. self thread stowedWeaponsRefresh();
  2278. }
  2279. }
  2280.  
  2281. stowedWeaponsRefresh()
  2282. {
  2283. self endon( "spawned" );
  2284. self endon( "killed_player" );
  2285. self endon( "disconnect" );
  2286.  
  2287. detach_all_weapons();
  2288. stow_on_back();
  2289. stow_on_hip();
  2290. }
  2291.  
  2292.  
  2293. detach_all_weapons()
  2294. {
  2295. if ( isDefined( self.tag_stowed_back ) )
  2296. self detach_back_weapon();
  2297.  
  2298. if ( isDefined( self.tag_stowed_hip ) )
  2299. self detach_hip_weapon();
  2300. }
  2301.  
  2302.  
  2303. detach_back_weapon()
  2304. {
  2305. detach_success = self detachIfAttached( self.tag_stowed_back, "tag_stowed_back" );
  2306.  
  2307. // test for bug
  2308. //assertex( detach_success, "Detaching: " + self.tag_stowed_back + " from tag: tag_stowed_back failed." );
  2309. self.tag_stowed_back = undefined;
  2310. }
  2311.  
  2312.  
  2313. detach_hip_weapon()
  2314. {
  2315. detach_success = self detachIfAttached( self.tag_stowed_hip, "tag_stowed_hip" );
  2316.  
  2317. // test for bug
  2318. //assertex( detach_success, "Detaching: " + detach_model + " from tag: tag_stowed_hip failed." );
  2319. self.tag_stowed_hip = undefined;
  2320. }
  2321.  
  2322.  
  2323. stow_on_back()
  2324. {
  2325. prof_begin( "stow_on_back" );
  2326. currentWeapon = self getCurrentWeapon();
  2327. currentIsAlt = isAltModeWeapon( currentWeapon );
  2328.  
  2329. assert( !isDefined( self.tag_stowed_back ) );
  2330.  
  2331. stowWeapon = undefined;
  2332. stowCamo = 0;
  2333. large_projectile = self stowPriorityWeapon();
  2334. stowOffsetModel = undefined;
  2335.  
  2336. if ( large_projectile != "" )
  2337. {
  2338. stowWeapon = large_projectile;
  2339. }
  2340. else
  2341. {
  2342. weaponsList = self getWeaponsListPrimaries();
  2343. foreach ( weaponName in weaponsList )
  2344. {
  2345. if ( weaponName == currentWeapon )
  2346. continue;
  2347.  
  2348. invType = weaponInventoryType( weaponName );
  2349.  
  2350. if ( invType != "primary" )
  2351. {
  2352. if ( invType == "altmode" )
  2353. continue;
  2354.  
  2355. if ( weaponClass( weaponName ) == "pistol" )
  2356. continue;
  2357. }
  2358.  
  2359. if ( WeaponType( weaponName ) == "riotshield" )
  2360. continue;
  2361.  
  2362. // Don't stow the current on our back when we're using the alt
  2363. if ( currentIsAlt && weaponAltWeaponName( weaponName ) == currentWeapon )
  2364. continue;
  2365.  
  2366. stowWeapon = weaponName;
  2367. stowOffsetModel = getStowOffsetModel( stowWeapon );
  2368.  
  2369. if ( stowWeapon == self.primaryWeapon )
  2370. stowCamo = self.loadoutPrimaryCamo;
  2371. else if ( stowWeapon == self.secondaryWeapon )
  2372. stowCamo = self.loadoutSecondaryCamo;
  2373. else
  2374. stowCamo = 0;
  2375. }
  2376. }
  2377.  
  2378. if ( !isDefined( stowWeapon ) )
  2379. {
  2380. prof_end( "stow_on_back" );
  2381. return;
  2382. }
  2383.  
  2384. if ( large_projectile != "" )
  2385. {
  2386. self.tag_stowed_back = level.stow_priority_model_array[ large_projectile ];
  2387. }
  2388. else
  2389. {
  2390. self.tag_stowed_back = getWeaponModel( stowWeapon, stowCamo );
  2391. }
  2392.  
  2393. if ( isDefined( stowOffsetModel ) )
  2394. {
  2395. self attach( stowOffsetModel, "tag_stowed_back", true );
  2396. attachTag = "tag_stow_back_mid_attach";
  2397. }
  2398. else
  2399. {
  2400. attachTag = "tag_stowed_back";
  2401. }
  2402.  
  2403. self attach( self.tag_stowed_back, attachTag, true );
  2404.  
  2405. hideTagList = GetWeaponHideTags( stowWeapon );
  2406.  
  2407. if ( !isDefined( hideTagList ) )
  2408. {
  2409. prof_end( "stow_on_back" );
  2410. return;
  2411. }
  2412.  
  2413. for ( i = 0; i < hideTagList.size; i++ )
  2414. self HidePart( hideTagList[ i ], self.tag_stowed_back );
  2415.  
  2416. prof_end( "stow_on_back" );
  2417. }
  2418.  
  2419. stow_on_hip()
  2420. {
  2421. currentWeapon = self getCurrentWeapon();
  2422.  
  2423. assert( !isDefined( self.tag_stowed_hip ) );
  2424.  
  2425. stowWeapon = undefined;
  2426.  
  2427. weaponsList = self getWeaponsListOffhands();
  2428. foreach ( weaponName in weaponsList )
  2429. {
  2430. if ( weaponName == currentWeapon )
  2431. continue;
  2432.  
  2433. if ( weaponName != "c4_mp" && weaponName != "claymore_mp" )
  2434. continue;
  2435.  
  2436. stowWeapon = weaponName;
  2437. }
  2438.  
  2439. if ( !isDefined( stowWeapon ) )
  2440. return;
  2441.  
  2442. self.tag_stowed_hip = getWeaponModel( stowWeapon );
  2443. self attach( self.tag_stowed_hip, "tag_stowed_hip_rear", true );
  2444.  
  2445. hideTagList = GetWeaponHideTags( stowWeapon );
  2446.  
  2447. if ( !isDefined( hideTagList ) )
  2448. return;
  2449.  
  2450. for ( i = 0; i < hideTagList.size; i++ )
  2451. self HidePart( hideTagList[ i ], self.tag_stowed_hip );
  2452. }
  2453.  
  2454.  
  2455. updateSavedLastWeapon()
  2456. {
  2457. self endon( "death" );
  2458. self endon( "disconnect" );
  2459.  
  2460. currentWeapon = self.currentWeaponAtSpawn;
  2461. self.saved_lastWeapon = currentWeapon;
  2462.  
  2463. for ( ;; )
  2464. {
  2465. self waittill( "weapon_change", newWeapon );
  2466.  
  2467. if ( newWeapon == "none" )
  2468. {
  2469. self.saved_lastWeapon = currentWeapon;
  2470. continue;
  2471. }
  2472.  
  2473. weaponInvType = weaponInventoryType( newWeapon );
  2474.  
  2475. if ( weaponInvType != "primary" && weaponInvType != "altmode" )
  2476. {
  2477. self.saved_lastWeapon = currentWeapon;
  2478. continue;
  2479. }
  2480.  
  2481. if ( newWeapon == "onemanarmy_mp" )
  2482. {
  2483. self.saved_lastWeapon = currentWeapon;
  2484. continue;
  2485. }
  2486.  
  2487. self updateMoveSpeedScale( "primary" );
  2488.  
  2489. self.saved_lastWeapon = currentWeapon;
  2490. currentWeapon = newWeapon;
  2491. }
  2492. }
  2493.  
  2494.  
  2495. EMPPlayer( numSeconds )
  2496. {
  2497. self endon( "disconnect" );
  2498. self endon( "death" );
  2499.  
  2500. self thread clearEMPOnDeath();
  2501.  
  2502. }
  2503.  
  2504.  
  2505. clearEMPOnDeath()
  2506. {
  2507. self endon( "disconnect" );
  2508.  
  2509. self waittill( "death" );
  2510. }
  2511.  
  2512.  
  2513. updateMoveSpeedScale( weaponType )
  2514. {
  2515. /*
  2516. if ( self _hasPerk( "specialty_lightweight" ) )
  2517. self.moveSpeedScaler = 1.10;
  2518. else
  2519. self.moveSpeedScaler = 1;
  2520. */
  2521.  
  2522. if ( !isDefined( weaponType ) || weaponType == "primary" || weaponType != "secondary" )
  2523. weaponType = self.primaryWeapon;
  2524. else
  2525. weaponType = self.secondaryWeapon;
  2526.  
  2527. if( isDefined(self.primaryWeapon ) && self.primaryWeapon == "riotshield_mp" )
  2528. {
  2529. self setMoveSpeedScale( .8 * self.moveSpeedScaler );
  2530. return;
  2531. }
  2532.  
  2533. if ( !isDefined( weaponType ) )
  2534. weapClass = "none";
  2535. else
  2536. weapClass = weaponClass( weaponType );
  2537.  
  2538.  
  2539. switch ( weapClass )
  2540. {
  2541. case "rifle":
  2542. self setMoveSpeedScale( 0.95 * self.moveSpeedScaler );
  2543. break;
  2544. case "pistol":
  2545. self setMoveSpeedScale( 1.0 * self.moveSpeedScaler );
  2546. break;
  2547. case "mg":
  2548. self setMoveSpeedScale( 0.875 * self.moveSpeedScaler );
  2549. break;
  2550. case "smg":
  2551. self setMoveSpeedScale( 1.0 * self.moveSpeedScaler );
  2552. break;
  2553. case "spread":
  2554. self setMoveSpeedScale( .95 * self.moveSpeedScaler );
  2555. break;
  2556. case "rocketlauncher":
  2557. self setMoveSpeedScale( 0.80 * self.moveSpeedScaler );
  2558. break;
  2559. case "sniper":
  2560. self setMoveSpeedScale( 1.0 * self.moveSpeedScaler );
  2561. break;
  2562. default:
  2563. self setMoveSpeedScale( 1.0 * self.moveSpeedScaler );
  2564. break;
  2565. }
  2566. }
  2567.  
  2568.  
  2569. buildWeaponData( filterPerks )
  2570. {
  2571. attachmentList = getAttachmentList();
  2572. max_weapon_num = 149;
  2573.  
  2574. baseWeaponData = [];
  2575.  
  2576. for( weaponId = 0; weaponId <= max_weapon_num; weaponId++ )
  2577. {
  2578. baseName = tablelookup( "mp/statstable.csv", 0, weaponId, 4 );
  2579. if( baseName == "" )
  2580. continue;
  2581.  
  2582. assetName = baseName + "_mp";
  2583.  
  2584. if ( !isSubStr( tableLookup( "mp/statsTable.csv", 0, weaponId, 2 ), "weapon_" ) )
  2585. continue;
  2586.  
  2587. if ( weaponInventoryType( assetName ) != "primary" )
  2588. continue;
  2589.  
  2590. weaponInfo = spawnStruct();
  2591. weaponInfo.baseName = baseName;
  2592. weaponInfo.assetName = assetName;
  2593. weaponInfo.variants = [];
  2594.  
  2595. weaponInfo.variants[0] = assetName;
  2596. // the alphabetize function is slow so we try not to do it for every weapon/attachment combo; a code solution would be better.
  2597. attachmentNames = [];
  2598. for ( innerLoopCount = 0; innerLoopCount < 6; innerLoopCount++ )
  2599. {
  2600. // generating attachment combinations
  2601. attachmentName = tablelookup( "mp/statStable.csv", 0, weaponId, innerLoopCount + 11 );
  2602.  
  2603. if ( filterPerks )
  2604. {
  2605. switch ( attachmentName )
  2606. {
  2607. case "fmj":
  2608. case "xmags":
  2609. case "rof":
  2610. continue;
  2611. }
  2612. }
  2613.  
  2614. if( attachmentName == "" )
  2615. break;
  2616.  
  2617. attachmentNames[attachmentName] = true;
  2618. }
  2619.  
  2620. // generate an alphabetized attachment list
  2621. attachments = [];
  2622. foreach ( attachmentName in attachmentList )
  2623. {
  2624. if ( !isDefined( attachmentNames[attachmentName] ) )
  2625. continue;
  2626.  
  2627. weaponInfo.variants[weaponInfo.variants.size] = baseName + "_" + attachmentName + "_mp";
  2628. attachments[attachments.size] = attachmentName;
  2629. }
  2630.  
  2631. for ( i = 0; i < (attachments.size - 1); i++ )
  2632. {
  2633. colIndex = tableLookupRowNum( "mp/attachmentCombos.csv", 0, attachments[i] );
  2634. for ( j = i + 1; j < attachments.size; j++ )
  2635. {
  2636. if ( tableLookup( "mp/attachmentCombos.csv", 0, attachments[j], colIndex ) == "no" )
  2637. continue;
  2638.  
  2639. weaponInfo.variants[weaponInfo.variants.size] = baseName + "_" + attachments[i] + "_" + attachments[j] + "_mp";
  2640. }
  2641. }
  2642.  
  2643. baseWeaponData[baseName] = weaponInfo;
  2644. }
  2645.  
  2646. return ( baseWeaponData );
  2647. }
  2648.  
  2649. monitorSemtex()
  2650. {
  2651. self endon( "disconnect" );
  2652. self endon( "death" );
  2653.  
  2654. for( ;; )
  2655. {
  2656. self waittill( "grenade_fire", weapon );
  2657.  
  2658. if ( !isSubStr(weapon.model, "semtex" ) )
  2659. continue;
  2660.  
  2661. weapon waittill( "missile_stuck", stuckTo );
  2662.  
  2663. if ( !isPlayer( stuckTo ) )
  2664. continue;
  2665.  
  2666. if ( level.teamBased && isDefined( stuckTo.team ) && stuckTo.team == self.team )
  2667. {
  2668. weapon.isStuck = "friendly";
  2669. continue;
  2670. }
  2671.  
  2672. weapon.isStuck = "enemy";
  2673. weapon.stuckEnemyEntity = stuckTo;
  2674.  
  2675. stuckTo maps\mp\gametypes\_hud_message::playerCardSplashNotify( "semtex_stuck", self );
  2676.  
  2677. self thread maps\mp\gametypes\_hud_message::SplashNotify( "stuck_semtex", 100 );
  2678. self notify( "process", "ch_bullseye" );
  2679. }
  2680. }
  2681.  
  2682.  
  2683. turret_monitorUse()
  2684. {
  2685. for( ;; )
  2686. {
  2687. self waittill ( "trigger", player );
  2688.  
  2689. self thread turret_playerThread( player );
  2690. }
  2691. }
  2692.  
  2693. turret_playerThread( player )
  2694. {
  2695. player endon ( "death" );
  2696. player endon ( "disconnect" );
  2697.  
  2698. player notify ( "weapon_change", "none" );
  2699.  
  2700. self waittill ( "turret_deactivate" );
  2701.  
  2702. player notify ( "weapon_change", player getCurrentWeapon() );
  2703. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement