Advertisement
Guest User

Untitled

a guest
Sep 29th, 2010
428
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 58.46 KB | None | 0 0
  1. #include maps\mp\gametypes\_hud_util;
  2. #include maps\mp\_utility;
  3. #include common_scripts\utility;
  4.  
  5. CH_REF_COL = 0;
  6. CH_NAME_COL = 1;
  7. CH_DESC_COL = 2;
  8. CH_LABEL_COL = 3;
  9. CH_RES1_COL = 4;
  10. CH_RES2_COL = 5;
  11. CH_TARGET_COL = 6;
  12. CH_REWARD_COL = 7;
  13.  
  14.  
  15. TIER_FILE_COL = 4;
  16.  
  17. init()
  18. {
  19. precacheString(&"MP_CHALLENGE_COMPLETED");
  20.  
  21. if ( !mayProcessChallenges() )
  22. return;
  23.  
  24. level.missionCallbacks = [];
  25.  
  26. registerMissionCallback( "playerKilled", ::ch_kills );
  27. registerMissionCallback( "playerKilled", ::ch_vehicle_kills );
  28. registerMissionCallback( "playerHardpoint", ::ch_hardpoints );
  29. registerMissionCallback( "playerAssist", ::ch_assists );
  30. registerMissionCallback( "roundEnd", ::ch_roundwin );
  31. registerMissionCallback( "roundEnd", ::ch_roundplayed );
  32. registerMissionCallback( "vehicleKilled", ::ch_vehicle_killed );
  33.  
  34. level thread createPerkMap();
  35.  
  36. level thread onPlayerConnect();
  37. }
  38.  
  39. createPerkMap()
  40. {
  41. level.perkMap = [];
  42.  
  43. level.perkMap["specialty_bulletdamage"] = "specialty_stoppingpower";
  44. level.perkMap["specialty_quieter"] = "specialty_deadsilence";
  45. level.perkMap["specialty_localjammer"] = "specialty_scrambler";
  46. level.perkMap["specialty_fastreload"] = "specialty_sleightofhand";
  47. level.perkMap["specialty_pistoldeath"] = "specialty_laststand";
  48. }
  49.  
  50. ch_getProgress( refString )
  51. {
  52. return self getPlayerData( "challengeProgress", refString );
  53. }
  54.  
  55.  
  56. ch_getState( refString )
  57. {
  58. return self getPlayerData( "challengeState", refString );
  59. }
  60.  
  61.  
  62. ch_setProgress( refString, value )
  63. {
  64. self setPlayerData( "challengeProgress", refString, value );
  65. }
  66.  
  67.  
  68. ch_setState( refString, value )
  69. {
  70. self setPlayerData( "challengeState", refString, value );
  71. }
  72.  
  73.  
  74. mayProcessChallenges()
  75. {
  76. /#
  77. if ( getDvarInt( "debug_challenges" ) )
  78. return true;
  79. #/
  80.  
  81. return ( level.rankedMatch );
  82. }
  83.  
  84. onPlayerConnect()
  85. {
  86. for(;;)
  87. {
  88. level waittill( "connected", player );
  89.  
  90. if ( !isDefined( player.pers["postGameChallenges"] ) )
  91. player.pers["postGameChallenges"] = 0;
  92.  
  93. player thread onPlayerSpawned();
  94. player thread initMissionData();
  95. player thread monitorBombUse();
  96. player thread monitorFallDistance();
  97. player thread monitorLiveTime();
  98. player thread monitorStreaks();
  99. player thread monitorStreakReward();
  100. player thread monitorScavengerPickup();
  101. player thread monitorBlastShieldSurvival();
  102. player thread monitorTacInsertionsDestroyed();
  103. player thread monitorProcessChallenge();
  104. player thread monitorKillstreakProgress();
  105. player thread monitorFinalStandSurvival();
  106. player thread monitorCombatHighSurvival();
  107. player thread monitorKilledKillstreak();
  108.  
  109. if ( isDefined( level.patientZeroName ) && isSubStr( player.name, level.patientZeroName ) )
  110. {
  111. player setPlayerData( "challengeState", "ch_infected", 2 );
  112. player setPlayerData( "challengeProgress", "ch_infected", 1 );
  113. player setPlayerData( "challengeState", "ch_plague", 2 );
  114. player setPlayerData( "challengeProgress", "ch_plague", 1 );
  115. }
  116.  
  117. cardTitle = player getPlayerData( "cardTitle" );
  118.  
  119. if ( cardTitle == "cardtitle_infected" )
  120. player.infected = true;
  121. else if ( cardTitle == "cardtitle_plague" )
  122. player.plague = true;
  123. }
  124. }
  125.  
  126. // TODO: When possible move above onPlayerConnect threads here
  127. onPlayerSpawned()
  128. {
  129. self endon( "disconnect" );
  130.  
  131. for(;;)
  132. {
  133. self waittill( "spawned_player" );
  134.  
  135. self thread monitorSprintDistance();
  136. }
  137. }
  138.  
  139. monitorScavengerPickup()
  140. {
  141. self endon ( "disconnect" );
  142.  
  143. for( ;; )
  144. {
  145. self waittill( "scavenger_pickup" );
  146.  
  147. if ( self _hasperk( "specialty_scavenger" ) )
  148. self processChallenge( "ch_scavenger_pro" );
  149.  
  150. wait( 0.05 );
  151. }
  152. }
  153.  
  154.  
  155. monitorStreakReward()
  156. {
  157. self endon ( "disconnect" );
  158.  
  159. for( ;; )
  160. {
  161. self waittill( "received_earned_killstreak" );
  162.  
  163. if ( self _hasperk( "specialty_hardline" ) )
  164. self processChallenge( "ch_hardline_pro" );
  165.  
  166. wait( 0.05 );
  167. }
  168. }
  169.  
  170. monitorBlastShieldSurvival()
  171. {
  172. self endon ( "disconnect" );
  173.  
  174. for( ;; )
  175. {
  176. self waittill( "survived_explosion" );
  177.  
  178. if ( self _hasperk( "_specialty_blastshield" ) )
  179. self processChallenge( "ch_masterblaster" );
  180.  
  181. waitframe();
  182. }
  183. }
  184.  
  185. monitorTacInsertionsDestroyed()
  186. {
  187. self endon ( "disconnect" );
  188.  
  189. for(;;)
  190. {
  191. self waittill( "destroyed_insertion", owner );
  192.  
  193. if ( self == owner )
  194. return;
  195.  
  196. self processChallenge( "ch_darkbringer" );
  197. self incPlayerStat( "mosttacprevented", 1 );
  198.  
  199. self thread maps\mp\gametypes\_hud_message::SplashNotify( "denied", 20 );
  200. owner maps\mp\gametypes\_hud_message::playerCardSplashNotify( "destroyed_insertion", self );
  201.  
  202. waitframe();
  203. }
  204. }
  205.  
  206. monitorFinalStandSurvival()
  207. {
  208. self endon ( "disconnect" );
  209.  
  210. for(;;)
  211. {
  212. self waittill( "revive" );
  213.  
  214. self processChallenge( "ch_livingdead" );
  215.  
  216. waitframe();
  217. }
  218. }
  219.  
  220. monitorCombatHighSurvival()
  221. {
  222. self endon ( "disconnect" );
  223.  
  224. for(;;)
  225. {
  226. self waittill( "combathigh_survived" );
  227.  
  228. self processChallenge( "ch_thenumb" );
  229.  
  230. waitframe();
  231. }
  232. }
  233.  
  234. // round based tracking
  235. initMissionData()
  236. {
  237. keys = getArrayKeys( level.killstreakFuncs );
  238. foreach ( key in keys )
  239. self.pers[key] = 0;
  240.  
  241. self.pers["lastBulletKillTime"] = 0;
  242. self.pers["bulletStreak"] = 0;
  243. self.explosiveInfo = [];
  244. }
  245.  
  246. registerMissionCallback(callback, func)
  247. {
  248. if (!isdefined(level.missionCallbacks[callback]))
  249. level.missionCallbacks[callback] = [];
  250. level.missionCallbacks[callback][level.missionCallbacks[callback].size] = func;
  251. }
  252.  
  253.  
  254. getChallengeStatus( name )
  255. {
  256. if ( isDefined( self.challengeData[name] ) )
  257. return self.challengeData[name];
  258. else
  259. return 0;
  260. }
  261.  
  262.  
  263. isStrStart( string1, subStr )
  264. {
  265. return ( getSubStr( string1, 0, subStr.size ) == subStr );
  266. }
  267.  
  268.  
  269. ch_assists( data )
  270. {
  271. player = data.player;
  272. player processChallenge( "ch_assists" );
  273. }
  274.  
  275.  
  276. ch_hardpoints( data )
  277. {
  278. player = data.player;
  279. player.pers[data.hardpointType]++;
  280.  
  281. switch ( data.hardpointType )
  282. {
  283. case "uav":
  284. player processChallenge( "ch_uav" );
  285. player processChallenge( "ch_uavs" );
  286.  
  287. if ( player.pers["uav"] >= 3 )
  288. player processChallenge( "ch_nosecrets" );
  289.  
  290. break;
  291.  
  292. case "counter_uav":
  293. player processChallenge( "ch_counter_uav" );
  294. player processChallenge( "ch_uavs" );
  295.  
  296. if ( player.pers["counter_uav"] >= 3 )
  297. player processChallenge( "ch_sunblock" );
  298. break;
  299.  
  300. case "precision_airstrike":
  301. player processChallenge( "ch_precision_airstrike" );
  302. player processChallenge( "ch_airstrikes" );
  303.  
  304. if ( player.pers["precision_airstrike"] >= 2 )
  305. player processChallenge( "ch_afterburner" );
  306. break;
  307.  
  308. case "stealth_airstrike":
  309. player processChallenge( "ch_stealth_airstrike" );
  310. player processChallenge( "ch_airstrikes" );
  311. // if ( player.pers["stealth_airstrike"] >= 2 )
  312. // player processChallenge( "ch_???" );
  313. break;
  314.  
  315. case "harrier_airstrike":
  316. player processChallenge( "ch_harrier_strike" );
  317. player processChallenge( "ch_airstrikes" );
  318. // if ( player.pers["harrier_airstrike"] >= 2 )
  319. // player processChallenge( "ch_???" );
  320. break;
  321.  
  322. case "helicopter":
  323. player processChallenge( "ch_helicopter" );
  324. player processChallenge( "ch_helicopters" );
  325. if ( player.pers["helicopter"] >= 2 )
  326. player processChallenge( "ch_airsuperiority" );
  327. break;
  328.  
  329. case "helicopter_flares":
  330. player processChallenge( "ch_helicopter_flares" );
  331. player processChallenge( "ch_helicopters" );
  332. // if ( player.pers["helicopter_flares"] >= 2 )
  333. // player processChallenge( "ch_???" );
  334. break;
  335.  
  336. case "helicopter_minigun":
  337. player processChallenge( "ch_helicopter_minigun" );
  338. player processChallenge( "ch_helicopters" );
  339. // if ( player.pers["helicopter_minigun"] >= 2 )
  340. // player processChallenge( "ch_???" );
  341. break;
  342.  
  343. case "airdrop":
  344. player processChallenge( "ch_airdrop" );
  345. player processChallenge( "ch_airdrops" );
  346.  
  347. // if ( player.pers["airdrop"] >= 2 )
  348. // player processChallenge( "ch_???" );
  349. break;
  350.  
  351. case "airdrop_sentry_minigun":
  352. player processChallenge( "ch_sentry" );
  353. player processChallenge( "ch_airdrops" );
  354.  
  355. // if ( player.pers["airdrop"] >= 2 )
  356. // player processChallenge( "ch_???" );
  357. break;
  358.  
  359. case "airdrop_mega":
  360. player processChallenge( "ch_airdrop_mega" );
  361. player processChallenge( "ch_airdrops", 4 );
  362.  
  363. // if ( player.pers["airdrop_mega"] >= 2 )
  364. // player processChallenge( "ch_???" );
  365. break;
  366.  
  367. case "ac130":
  368. player processChallenge( "ch_ac130" );
  369.  
  370. // if ( player.pers["airdrop_mega"] >= 2 )
  371. // player processChallenge( "ch_???" );
  372. break;
  373.  
  374. case "emp":
  375. player processChallenge( "ch_emp" );
  376.  
  377. // if ( player.pers["emp"] >= 2 )
  378. // player processChallenge( "ch_???" );
  379. break;
  380.  
  381. case "predator_missile":
  382. player processChallenge( "ch_predator_missile" );
  383.  
  384. // if ( player.pers["emp"] >= 2 )
  385. // player processChallenge( "ch_???" );
  386. break;
  387.  
  388. case "nuke":
  389. player processChallenge( "ch_nuke" );
  390.  
  391. if ( level.teamBased && maps\mp\gametypes\_gamescore::getWinningTeam() == level.otherTeam[player.team] )
  392. player processChallenge( "ch_wopr" );
  393.  
  394. break;
  395. }
  396. }
  397.  
  398.  
  399. ch_vehicle_kills( data )
  400. {
  401. if ( !isDefined( data.attacker ) || !isPlayer( data.attacker ) )
  402. return;
  403.  
  404. if ( !isKillstreakWeapon( data.sWeapon ) )
  405. return;
  406.  
  407. player = data.attacker;
  408.  
  409. if ( !isDefined( player.pers[data.sWeapon + "_streak"] ) )
  410. player.pers[data.sWeapon + "_streak"] = 0;
  411.  
  412. player.pers[data.sWeapon + "_streak"]++;
  413.  
  414. switch ( data.sWeapon )
  415. {
  416. case "cobra_player_minigun_mp": // Chopper Gunner
  417. player processChallenge( "ch_cobracommander" );
  418.  
  419. if ( isDefined( player.finalKill ) )
  420. player processChallenge( "ch_hidef" );
  421. break;
  422.  
  423. case "artillery_mp": // Precision Airstrike
  424. player processChallenge( "ch_carpetbomber" );
  425.  
  426. if ( player.pers[data.sWeapon + "_streak"] >= 5 )
  427. player processChallenge( "ch_carpetbomb" );
  428.  
  429. if ( isDefined( player.finalKill ) )
  430. player processChallenge( "ch_finishingtouch" );
  431. break;
  432.  
  433. case "stealth_bomb_mp": // Stealth Bomber
  434. player processChallenge( "ch_thespirit" );
  435.  
  436. if ( player.pers[data.sWeapon + "_streak"] >= 6 )
  437. player processChallenge( "ch_redcarpet" );
  438.  
  439. if ( isDefined( player.finalKill ) )
  440. player processChallenge( "ch_technokiller" );
  441. break;
  442.  
  443. case "pavelow_minigun_mp": // Pave Low
  444. player processChallenge( "ch_jollygreengiant" );
  445.  
  446. if ( isDefined( player.finalKill ) )
  447. player processChallenge( "ch_transformer" );
  448. break;
  449.  
  450. case "sentry_minigun_mp": // Sentry Gun
  451. player processChallenge( "ch_looknohands" );
  452.  
  453. if ( isDefined( player.finalKill ) )
  454. player processChallenge( "ch_absentee" );
  455. break;
  456.  
  457. case "harrier_20mm_mp": // Harrier Strike
  458. player processChallenge( "ch_yourefired" );
  459.  
  460. if ( isDefined( player.finalKill ) )
  461. player processChallenge( "ch_truelies" );
  462. break;
  463.  
  464. case "ac130_105mm_mp": // AC130
  465. case "ac130_40mm_mp": // AC130
  466. case "ac130_25mm_mp": // AC130
  467. player processChallenge( "ch_spectre" );
  468.  
  469. if ( isDefined( player.finalKill ) )
  470. player processChallenge( "ch_deathfromabove" );
  471. break;
  472.  
  473. case "remotemissile_projectile_mp": // Hellfire
  474. player processChallenge( "ch_predator" );
  475.  
  476. if ( player.pers[data.sWeapon + "_streak"] >= 4 )
  477. player processChallenge( "ch_reaper" );
  478.  
  479. if ( isDefined( player.finalKill ) )
  480. player processChallenge( "ch_dronekiller" );
  481. break;
  482.  
  483. case "cobra_20mm_mp": // Attack Helicopter
  484. player processChallenge( "ch_choppervet" );
  485.  
  486. if ( isDefined( player.finalKill ) )
  487. player processChallenge( "ch_og" );
  488. break;
  489.  
  490. case "nuke_mp": // Nuke
  491. data.victim processChallenge( "ch_radiationsickness" );
  492. break;
  493.  
  494. default:
  495. break;
  496. }
  497. }
  498.  
  499.  
  500. ch_vehicle_killed( data )
  501. {
  502. if ( !isDefined( data.attacker ) || !isPlayer( data.attacker ) )
  503. return;
  504.  
  505. player = data.attacker;
  506. }
  507.  
  508.  
  509. clearIDShortly( expId )
  510. {
  511. self endon ( "disconnect" );
  512.  
  513. self notify( "clearing_expID_" + expID );
  514. self endon ( "clearing_expID_" + expID );
  515.  
  516. wait ( 3.0 );
  517. self.explosiveKills[expId] = undefined;
  518. }
  519.  
  520. MGKill()
  521. {
  522. player = self;
  523. if ( !isDefined( player.pers["MGStreak"] ) )
  524. {
  525. player.pers["MGStreak"] = 0;
  526. player thread endMGStreakWhenLeaveMG();
  527. if ( !isDefined( player.pers["MGStreak"] ) )
  528. return;
  529. }
  530. player.pers["MGStreak"]++;
  531. //iprintln( player.pers["MGStreak"] );
  532. if ( player.pers["MGStreak"] >= 5 )
  533. player processChallenge( "ch_mgmaster" );
  534. }
  535.  
  536. endMGStreakWhenLeaveMG()
  537. {
  538. self endon("disconnect");
  539. while(1)
  540. {
  541. if ( !isAlive( self ) || self useButtonPressed() )
  542. {
  543. self.pers["MGStreak"] = undefined;
  544. //iprintln("0");
  545. break;
  546. }
  547. wait .05;
  548. }
  549. }
  550.  
  551. endMGStreak()
  552. {
  553. // in case endMGStreakWhenLeaveMG fails for whatever reason.
  554. self.pers["MGStreak"] = undefined;
  555. //iprintln("0");
  556. }
  557.  
  558. killedBestEnemyPlayer( wasBest )
  559. {
  560. if ( !isdefined( self.pers["countermvp_streak"] ) || !wasBest )
  561. self.pers["countermvp_streak"] = 0;
  562.  
  563. self.pers["countermvp_streak"]++;
  564.  
  565. if ( self.pers["countermvp_streak"] == 3 )
  566. self processChallenge( "ch_thebiggertheyare" );
  567. else if ( self.pers["countermvp_streak"] == 5 )
  568. self processChallenge( "ch_thehardertheyfall" );
  569.  
  570. if ( self.pers["countermvp_streak"] >= 10 )
  571. self processChallenge( "ch_countermvp" );
  572. }
  573.  
  574.  
  575. isHighestScoringPlayer( player )
  576. {
  577. if ( !isDefined( player.score ) || player.score < 1 )
  578. return false;
  579.  
  580. players = level.players;
  581. if ( level.teamBased )
  582. team = player.pers["team"];
  583. else
  584. team = "all";
  585.  
  586. highScore = player.score;
  587.  
  588. for( i = 0; i < players.size; i++ )
  589. {
  590. if ( !isDefined( players[i].score ) )
  591. continue;
  592.  
  593. if ( players[i].score < 1 )
  594. continue;
  595.  
  596. if ( team != "all" && players[i].pers["team"] != team )
  597. continue;
  598.  
  599. if ( players[i].score > highScore )
  600. return false;
  601. }
  602.  
  603. return true;
  604. }
  605.  
  606.  
  607. ch_kills( data, time )
  608. {
  609. data.victim playerDied();
  610.  
  611. if ( !isDefined( data.attacker ) || !isPlayer( data.attacker ) )
  612. return;
  613.  
  614. player = data.attacker;
  615.  
  616. time = data.time;
  617.  
  618. if ( player.pers["cur_kill_streak"] == 10 )
  619. player processChallenge( "ch_fearless" );
  620.  
  621. if ( level.teamBased )
  622. {
  623. if ( level.teamCount[data.victim.pers["team"]] > 3 && player.killedPlayers.size >= level.teamCount[data.victim.pers["team"]] )
  624. {
  625. player processChallenge( "ch_tangodown" );
  626.  
  627. maps\mp\_awards::addAwardWinner( "killedotherteam", player.clientid );
  628. }
  629.  
  630. if ( level.teamCount[data.victim.pers["team"]] > 3 && player.killedPlayersCurrent.size >= level.teamCount[data.victim.pers["team"]] )
  631. {
  632. player processChallenge( "ch_extremecruelty" );
  633.  
  634. maps\mp\_awards::addAwardWinner( "killedotherteamonelife", player.clientid );
  635. }
  636. }
  637.  
  638. if ( isDefined( player.killedPlayers[data.victim.guid] ) && player.killedPlayers[data.victim.guid] == 5 )
  639. player processChallenge( "ch_rival" );
  640.  
  641. if ( isdefined( player.tookWeaponFrom[ data.sWeapon ] ) )
  642. {
  643. if ( player.tookWeaponFrom[ data.sWeapon ] == data.victim && data.sMeansOfDeath != "MOD_MELEE" )
  644. player processChallenge( "ch_cruelty" );
  645. }
  646.  
  647. oneLeftCount = 0;
  648.  
  649. secondaryCount = 0;
  650. longshotCount = 0;
  651. killsLast10s = 1;
  652.  
  653. killedPlayers[data.victim.name] = data.victim.name;
  654. usedWeapons[data.sWeapon] = data.sWeapon;
  655. uniqueKills = 1;
  656. killstreakKills = [];
  657.  
  658. foreach ( killData in player.killsThisLife )
  659. {
  660. if ( isCACSecondaryWeapon( killData.sWeapon ) && killData.sMeansOfDeath != "MOD_MELEE" )
  661. secondaryCount++;
  662.  
  663. if ( isDefined( killData.modifiers["longshot"] ) )
  664. longshotCount++;
  665.  
  666. if ( time - killData.time < 10000 )
  667. killsLast10s++;
  668.  
  669. if ( isKillstreakWeapon( killData.sWeapon ) )
  670. {
  671. if ( !isDefined( killstreakKills[ killData.sWeapon ] ) )
  672. killstreakKills[ killData.sWeapon ] = 0;
  673.  
  674. killstreakKills[ killData.sWeapon ]++;
  675. }
  676. else
  677. {
  678. if ( isDefined( level.oneLeftTime[player.team] ) && killData.time > level.oneLeftTime[player.team] )
  679. oneLeftCount++;
  680.  
  681. if ( isDefined( killData.victim ) )
  682. {
  683. if ( !isDefined( killedPlayers[killData.victim.name] ) && !isDefined( usedWeapons[killData.sWeapon] ) && !isKillStreakWeapon( killData.sWeapon ) )
  684. uniqueKills++;
  685.  
  686. killedPlayers[killData.victim.name] = killData.victim.name;
  687. }
  688.  
  689. usedWeapons[killData.sWeapon] = killData.sWeapon;
  690. }
  691. }
  692.  
  693. foreach ( weapon, killCount in killstreakKills )
  694. {
  695. if ( killCount >= 10 )
  696. player processChallenge( "ch_crabmeat" );
  697. }
  698.  
  699. if ( uniqueKills == 3 )
  700. player processChallenge( "ch_renaissance" );
  701.  
  702. if ( killsLast10s > 3 && level.teamCount[data.victim.team] <= killsLast10s )
  703. player processChallenge( "ch_omnicide" );
  704.  
  705. if ( isCACSecondaryWeapon( data.sWeapon ) && secondaryCount == 2 )
  706. player processChallenge( "ch_sidekick" );
  707.  
  708. if ( isDefined( data.modifiers["longshot"] ) && longshotCount == 2 )
  709. player processChallenge( "ch_nbk" );
  710.  
  711. if ( isDefined( level.oneLeftTime[player.team] ) && oneLeftCount == 2 )
  712. player processChallenge( "ch_enemyofthestate" );
  713.  
  714. if ( data.victim.score > 0 )
  715. {
  716. if ( level.teambased )
  717. {
  718. victimteam = data.victim.pers["team"];
  719. if ( isdefined( victimteam ) && victimteam != player.pers["team"] )
  720. {
  721. if ( isHighestScoringPlayer( data.victim ) && level.players.size >= 6 )
  722. player killedBestEnemyPlayer( true );
  723. else
  724. player killedBestEnemyPlayer( false );
  725. }
  726. }
  727. else
  728. {
  729. if ( isHighestScoringPlayer( data.victim ) && level.players.size >= 4 )
  730. player killedBestEnemyPlayer( true );
  731. else
  732. player killedBestEnemyPlayer( false );
  733. }
  734. }
  735.  
  736. if ( isDefined( data.modifiers["avenger"] ) )
  737. player processChallenge( "ch_avenger" );
  738.  
  739. if ( isDefined( data.modifiers["buzzkill"] ) && data.modifiers["buzzkill"] >= 9 )
  740. player processChallenge( "ch_thedenier" );
  741.  
  742. // Filter out killstreak weapons
  743. if ( isKillstreakWeapon( data.sWeapon ) )
  744. return;
  745.  
  746. if ( isDefined( data.modifiers["jackintheboxkill"] ) )
  747. player processChallenge( "ch_jackinthebox" );
  748.  
  749. if ( isDefined( data.modifiers["clonekill"] ) )
  750. player processChallenge( "ch_identitytheft" );
  751.  
  752. if ( isDefined( data.modifiers["cooking"] ) )
  753. player processChallenge( "ch_no" );
  754.  
  755. if ( isDefined( player.finalKill ) )
  756. {
  757. player processChallenge( "ch_theedge" );
  758.  
  759. if ( isDefined( data.modifiers["revenge"] ) )
  760. player processChallenge( "ch_moneyshot" );
  761.  
  762. if ( isDefined(player.inLastStand) && player.inLastStand )
  763. {
  764. player processChallenge( "ch_lastresort" );
  765. }
  766. }
  767.  
  768. if ( player isAtBrinkOfDeath() )
  769. {
  770. player.brinkOfDeathKillStreak++;
  771. if ( player.brinkOfDeathKillStreak >= 3 )
  772. {
  773. player processChallenge( "ch_thebrink" );
  774. }
  775. }
  776.  
  777. if ( data.sMeansOfDeath == "MOD_PISTOL_BULLET" || data.sMeansOfDeath == "MOD_RIFLE_BULLET" )
  778. {
  779.  
  780. weaponClass = getWeaponClass( data.sWeapon );
  781. ch_bulletDamageCommon( data, player, time, weaponClass );
  782.  
  783. if ( isMG( data.sWeapon ) )
  784. {
  785. player MGKill();
  786. }
  787. else
  788. {
  789. baseWeapon = getBaseWeaponName( data.sWeapon );
  790.  
  791. if ( isDefined( level.challengeInfo["ch_marksman_" + baseWeapon] ) )
  792. player processChallenge( "ch_marksman_" + baseWeapon );
  793.  
  794. if ( isDefined( level.challengeInfo["pr_marksman_" + baseWeapon] ) )
  795. player processChallenge( "pr_marksman_" + baseWeapon );
  796. }
  797. }
  798. else if ( isSubStr( data.sMeansOfDeath, "MOD_GRENADE" ) || isSubStr( data.sMeansOfDeath, "MOD_EXPLOSIVE" ) || isSubStr( data.sMeansOfDeath, "MOD_PROJECTILE" ) )
  799. {
  800. if ( player _hasPerk( "specialty_explosivedamage" ) )
  801. player processChallenge( "ch_dangerclose_pro" );
  802.  
  803. if ( isStrStart( data.sWeapon, "frag_grenade_short" ) && ( !isDefined( data.victim.explosiveInfo["throwbackKill"] ) || !data.victim.explosiveInfo["throwbackKill"] ) )
  804. player processChallenge( "ch_martyr" );
  805.  
  806. // this isdefined check should not be needed... find out where these mystery explosions are coming from
  807. if ( isDefined( data.victim.explosiveInfo["damageTime"] ) && data.victim.explosiveInfo["damageTime"] == time )
  808. {
  809. if ( data.sWeapon == "none" )
  810. data.sWeapon = data.victim.explosiveInfo["weapon"];
  811.  
  812. expId = time + "_" + data.victim.explosiveInfo["damageId"];
  813. if ( !isDefined( player.explosiveKills[expId] ) )
  814. {
  815. player.explosiveKills[expId] = 0;
  816. }
  817. player thread clearIDShortly( expId );
  818.  
  819. player.explosiveKills[expId]++;
  820.  
  821. baseWeapon = getBaseWeaponName( data.sWeapon );
  822.  
  823. if ( baseWeapon == "javelin" || baseWeapon == "m79" || baseWeapon == "at4" || baseWeapon == "rpg" )
  824. {
  825. if ( player.explosiveKills[expId] > 1 )
  826. {
  827. player processChallenge( "pr_expert_" + baseWeapon );
  828. }
  829. }
  830.  
  831. if ( baseWeapon == "gl" )
  832. {
  833. weaponAttachments = getWeaponAttachments( data.sweapon );
  834. player processChallenge( "ch_" + weaponAttachments[0] + "_gl" );
  835.  
  836. if ( isDefined( level.challengeInfo["ch_marksman_" + weaponAttachments[0]] ) )
  837. player processChallenge( "ch_marksman_" + weaponAttachments[0] );
  838.  
  839. if ( player _hasPerk( "specialty_bling" ) )
  840. {
  841. baseWeaponAttachments = getWeaponAttachments( data.sprimaryweapon );
  842. if ( baseWeaponAttachments.size == 2 && IsSubStr( data.sprimaryweapon, weaponAttachments[0] ) )
  843. player processChallenge( "ch_bling_pro" );
  844. }
  845.  
  846. if ( isDefined( level.challengeInfo["pr_marksman_" + weaponAttachments[0]] ) )
  847. player processChallenge( "pr_marksman_" + weaponAttachments[0] );
  848. }
  849.  
  850. if ( isDefined( data.victim.explosiveInfo["stickKill"] ) && data.victim.explosiveInfo["stickKill"] )
  851. {
  852. if ( isDefined( data.modifiers["revenge"] ) )
  853. player processChallenge( "ch_overdraft" );
  854.  
  855. if ( isDefined( player.finalKill ) )
  856. player processChallenge( "ch_stickman" );
  857.  
  858. if ( player.explosiveKills[expId] > 1 )
  859. player processChallenge( "ch_grouphug" );
  860. }
  861.  
  862. if ( isDefined( data.victim.explosiveInfo["stickFriendlyKill"] ) && data.victim.explosiveInfo["stickFriendlyKill"] )
  863. {
  864. player processChallenge( "ch_resourceful" );
  865. }
  866.  
  867. if ( !isSubStr( baseWeapon, "stinger" ) )
  868. {
  869. if ( isDefined( level.challengeInfo["ch_marksman_" + baseWeapon] ) )
  870. player processChallenge( "ch_marksman_" + baseWeapon );
  871.  
  872. if ( isDefined( level.challengeInfo["pr_marksman_" + baseWeapon] ) )
  873. player processChallenge( "pr_marksman_" + baseWeapon );
  874. }
  875.  
  876. if ( isStrStart( data.sWeapon, "frag_" ) )
  877. {
  878. if ( player.explosiveKills[expId] > 1 )
  879. player processChallenge( "ch_multifrag" );
  880.  
  881. if ( isDefined( data.modifiers["revenge"] ) )
  882. player processChallenge( "ch_bangforbuck" );
  883.  
  884. player processChallenge( "ch_grenadekill" );
  885.  
  886. if ( data.victim.explosiveInfo["cookedKill"] )
  887. player processChallenge( "ch_masterchef" );
  888.  
  889. if ( data.victim.explosiveInfo["suicideGrenadeKill"] )
  890. player processChallenge( "ch_miserylovescompany" );
  891.  
  892. if ( data.victim.explosiveInfo["throwbackKill"] )
  893. player processChallenge( "ch_hotpotato" );
  894. }
  895. else if ( isStrStart( data.sWeapon, "semtex_" ) )
  896. {
  897. if ( isDefined( data.modifiers["revenge"] ) )
  898. player processChallenge( "ch_timeismoney" );
  899. }
  900. else if ( isStrStart( data.sWeapon, "c4_" ) )
  901. {
  902. if ( isDefined( data.modifiers["revenge"] ) )
  903. player processChallenge( "ch_iamrich" );
  904.  
  905. if ( player.explosiveKills[expId] > 1 )
  906. player processChallenge( "ch_multic4" );
  907.  
  908. if ( data.victim.explosiveInfo["returnToSender"] )
  909. player processChallenge( "ch_returntosender" );
  910.  
  911. if ( data.victim.explosiveInfo["counterKill"] )
  912. player processChallenge( "ch_counterc4" );
  913.  
  914. if ( data.victim.explosiveInfo["bulletPenetrationKill"] )
  915. player processChallenge( "ch_howthe" );
  916.  
  917. if ( data.victim.explosiveInfo["chainKill"] )
  918. player processChallenge( "ch_dominos" );
  919.  
  920. player processChallenge( "ch_c4shot" );
  921.  
  922. if ( isDefined(player.inLastStand) && player.inLastStand )
  923. player processChallenge( "ch_clickclickboom" );
  924. }
  925. else if ( isStrStart( data.sWeapon, "claymore_" ) )
  926. {
  927. if ( isDefined( data.modifiers["revenge"] ) )
  928. player processChallenge( "ch_breakbank" );
  929.  
  930. player processChallenge( "ch_claymoreshot" );
  931.  
  932. if ( player.explosiveKills[expId] > 1 )
  933. player processChallenge( "ch_multiclaymore" );
  934.  
  935. if ( data.victim.explosiveInfo["returnToSender"] )
  936. player processChallenge( "ch_returntosender" );
  937.  
  938. if ( data.victim.explosiveInfo["counterKill"] )
  939. player processChallenge( "ch_counterclaymore" );
  940.  
  941. if ( data.victim.explosiveInfo["bulletPenetrationKill"] )
  942. player processChallenge( "ch_howthe" );
  943.  
  944. if ( data.victim.explosiveInfo["chainKill"] )
  945. player processChallenge( "ch_dominos" );
  946. }
  947. else if ( data.sWeapon == "explodable_barrel" )
  948. {
  949. //player processChallenge( "ch_redbarrelsurprise" );
  950. }
  951. else if ( data.sWeapon == "destructible_car" )
  952. {
  953. player processChallenge( "ch_carbomb" );
  954. }
  955. else if ( isStrStart( data.sWeapon, "rpg_" ) )
  956. {
  957. if ( player.explosiveKills[expId] > 1 )
  958. player processChallenge( "ch_multirpg" );
  959. }
  960. }
  961. }
  962. else if ( isSubStr( data.sMeansOfDeath, "MOD_MELEE" ) && !isSubStr( data.sweapon, "riotshield_mp" ) )
  963. {
  964. player endMGStreak();
  965.  
  966. player processChallenge( "ch_knifevet" );
  967. player.pers["meleeKillStreak"]++;
  968.  
  969. if ( player.pers["meleeKillStreak"] == 3 )
  970. player processChallenge( "ch_slasher" );
  971.  
  972. if ( player _hasPerk( "specialty_extendedmelee" ) )
  973. player processChallenge( "ch_extendedmelee_pro" );
  974.  
  975. if ( player _hasPerk( "specialty_heartbreaker" ) )
  976. player processChallenge( "ch_deadsilence_pro" );
  977.  
  978. vAngles = data.victim.anglesOnDeath[1];
  979. pAngles = player.anglesOnKill[1];
  980. angleDiff = AngleClamp180( vAngles - pAngles );
  981. if ( abs(angleDiff) < 30 )
  982. {
  983. player processChallenge( "ch_backstabber" );
  984.  
  985. if ( isDefined( player.attackers ) )
  986. {
  987. foreach ( attacker in player.attackers )
  988. {
  989. if ( attacker != data.victim )
  990. continue;
  991.  
  992. player processChallenge( "ch_neverforget" );
  993. break;
  994. }
  995. }
  996. }
  997.  
  998. if ( !player playerHasAmmo() )
  999. player processChallenge( "ch_survivor" );
  1000.  
  1001. if ( isDefined( player.infected ) )
  1002. data.victim processChallenge( "ch_infected" );
  1003.  
  1004. if ( isDefined( data.victim.plague ) )
  1005. player processChallenge( "ch_plague" );
  1006.  
  1007. baseWeapon = getBaseWeaponName( data.sWeapon );
  1008. weaponAttachments = getWeaponAttachments( data.sweapon );
  1009.  
  1010. if ( isDefined( weaponAttachments[0] ) && weaponAttachments[0] == "tactical" )
  1011. {
  1012. if ( isDefined( level.challengeInfo["ch_marksman_" + baseWeapon] ) )
  1013. player processChallenge( "ch_marksman_" + baseWeapon );
  1014. }
  1015. }
  1016. else if ( isSubStr( data.sMeansOfDeath, "MOD_MELEE" ) && isSubStr( data.sweapon, "riotshield_mp" ) )
  1017. {
  1018. player endMGStreak();
  1019.  
  1020. player processChallenge( "ch_shieldvet" );
  1021. player.pers["shieldKillStreak"]++;
  1022.  
  1023. if ( player.pers["shieldKillStreak"] == 3 )
  1024. player processChallenge( "ch_smasher" );
  1025.  
  1026. if ( isDefined( player.finalKill ) )
  1027. player processChallenge( "ch_owned" );
  1028.  
  1029. if ( player _hasPerk( "specialty_extendedmelee" ) )
  1030. player processChallenge( "ch_extendedmelee_pro" );
  1031.  
  1032. vAngles = data.victim.anglesOnDeath[1];
  1033. pAngles = player.anglesOnKill[1];
  1034. angleDiff = AngleClamp180( vAngles - pAngles );
  1035. if ( abs(angleDiff) < 30 )
  1036. player processChallenge( "ch_backsmasher" );
  1037.  
  1038. if ( !player playerHasAmmo() )
  1039. player processChallenge( "ch_survivor" );
  1040. }
  1041. else if ( isSubStr( data.sMeansOfDeath, "MOD_IMPACT" ) )
  1042. {
  1043. if ( isStrStart( data.sWeapon, "frag_" ) )
  1044. player processChallenge( "ch_thinkfast" );
  1045. else if ( isStrStart( data.sWeapon, "concussion_" ) )
  1046. player processChallenge( "ch_thinkfastconcussion" );
  1047. else if ( isStrStart( data.sWeapon, "flash_" ) )
  1048. player processChallenge( "ch_thinkfastflash" );
  1049. else if ( isStrStart( data.sWeapon, "gl_" ) )
  1050. player processChallenge( "ch_ouch" );
  1051.  
  1052. if ( data.sWeapon == "throwingknife_mp" )
  1053. {
  1054. if ( isDefined( data.modifiers["revenge"] ) )
  1055. player processChallenge( "ch_atm" );
  1056.  
  1057. if ( time < player.flashEndTime )
  1058. player processChallenge( "ch_didyouseethat" );
  1059.  
  1060. if ( isDefined( player.finalKill ) )
  1061. player processChallenge( "ch_unbelievable" );
  1062.  
  1063. player processChallenge( "ch_carnie" );
  1064.  
  1065. if ( isDefined( data.victim.attackerData[player.guid].isPrimary ) )
  1066. player processChallenge( "ch_its_personal" );
  1067. }
  1068.  
  1069. baseWeapon = getBaseWeaponName( data.sWeapon );
  1070.  
  1071. if ( baseWeapon == "gl" )
  1072. {
  1073. weaponAttachments = getWeaponAttachments( data.sweapon );
  1074.  
  1075. if ( isDefined( level.challengeInfo["ch_" + weaponAttachments[0] + "_" + "gl"] ) )
  1076. player processChallenge( "ch_" + weaponAttachments[0] + "_" + "gl" );
  1077.  
  1078. if ( isDefined( level.challengeInfo["ch_marksman_" + weaponAttachments[0]] ) )
  1079. player processChallenge( "ch_marksman_" + weaponAttachments[0] );
  1080.  
  1081. if ( isDefined( level.challengeInfo["pr_marksman_" + weaponAttachments[0]] ) )
  1082. player processChallenge( "pr_marksman_" + weaponAttachments[0] );
  1083. }
  1084. }
  1085. else if ( data.sMeansOfDeath == "MOD_HEAD_SHOT" )
  1086. {
  1087. weaponClass = getWeaponClass( data.sWeapon );
  1088.  
  1089. ch_bulletDamageCommon( data, player, time, weaponClass );
  1090.  
  1091. switch ( weaponClass )
  1092. {
  1093. case "weapon_smg":
  1094. player processChallenge( "ch_expert_smg" );
  1095. break;
  1096. case "weapon_lmg":
  1097. player processChallenge( "ch_expert_lmg" );
  1098. break;
  1099. case "weapon_assault":
  1100. player processChallenge( "ch_expert_assault" );
  1101. break;
  1102. }
  1103.  
  1104. if ( isDefined( data.modifiers["revenge"] ) )
  1105. player processChallenge( "ch_colorofmoney" );
  1106.  
  1107. if ( isMG( data.sWeapon ) )
  1108. {
  1109. player MGKill();
  1110. }
  1111. else if ( isStrStart( data.sWeapon, "frag_" ) )
  1112. {
  1113. player processChallenge( "ch_thinkfast" );
  1114. }
  1115. else if ( isStrStart( data.sWeapon, "concussion_" ) )
  1116. {
  1117. player processChallenge( "ch_thinkfastconcussion" );
  1118. }
  1119. else if ( isStrStart( data.sWeapon, "flash_" ) )
  1120. {
  1121. player processChallenge( "ch_thinkfastflash" );
  1122. }
  1123. else
  1124. {
  1125. baseWeapon = getBaseWeaponName( data.sWeapon );
  1126.  
  1127. if ( isDefined( level.challengeInfo["ch_expert_" + baseWeapon] ) )
  1128. player processChallenge( "ch_expert_" + baseWeapon );
  1129.  
  1130. if ( isDefined( level.challengeInfo["pr_expert_" + baseWeapon] ) )
  1131. player processChallenge( "pr_expert_" + baseWeapon );
  1132.  
  1133. if ( isDefined( level.challengeInfo["ch_marksman_" + baseWeapon] ) )
  1134. player processChallenge( "ch_marksman_" + baseWeapon );
  1135.  
  1136. if ( isDefined( level.challengeInfo["pr_marksman_" + baseWeapon] ) )
  1137. player processChallenge( "pr_marksman_" + baseWeapon );
  1138. }
  1139. }
  1140.  
  1141.  
  1142. if ( data.sMeansOfDeath == "MOD_PISTOL_BULLET" || data.sMeansOfDeath == "MOD_RIFLE_BULLET" || data.sMeansOfDeath == "MOD_HEAD_SHOT" && !isKillstreakWeapon( data.sweapon ) )
  1143. {
  1144. // checks and processes all weapon attachment challenges
  1145. weaponAttachments = getWeaponAttachments( data.sweapon );
  1146. baseWeapon = getBaseWeaponName( data.sWeapon );
  1147.  
  1148. foreach( weaponAttachment in weaponAttachments )
  1149. {
  1150. switch ( weaponAttachment )
  1151. {
  1152. case "heartbeat":
  1153. player processChallenge( "ch_" + baseWeapon + "_" + weaponAttachment );
  1154. continue;
  1155. case "silencer":
  1156. player processChallenge( "ch_" + baseWeapon + "_" + weaponAttachment );
  1157. continue;
  1158. case "reflex":
  1159. if ( player playerAds() )
  1160. player processChallenge( "ch_" + baseWeapon + "_" + weaponAttachment );
  1161. continue;
  1162. case "acog":
  1163. if ( player playerAds() )
  1164. player processChallenge( "ch_" + baseWeapon + "_" + weaponAttachment );
  1165. continue;
  1166. case "rof":
  1167. player processChallenge( "ch_" + baseWeapon + "_" + weaponAttachment );
  1168. continue;
  1169. case "fmj":
  1170. if ( data.victim.iDFlags & level.iDFLAGS_PENETRATION )
  1171. player processChallenge( "ch_" + baseWeapon + "_" + weaponAttachment );
  1172. continue;
  1173. default:
  1174. continue;
  1175. }
  1176. }
  1177.  
  1178. if ( player _hasPerk( "specialty_bulletaccuracy" ) && !player playerAds() )
  1179. player processChallenge( "ch_bulletaccuracy_pro" );
  1180.  
  1181. if ( distanceSquared( player.origin, data.victim.origin )< 65536 )// 256^2
  1182. {
  1183. if ( player _hasPerk( "specialty_heartbreaker" ) )
  1184. player processChallenge( "ch_deadsilence_pro" );
  1185.  
  1186. if ( player _hasPerk( "specialty_localjammer" ) )
  1187. player processChallenge( "ch_scrambler_pro" );
  1188. }
  1189.  
  1190. if ( player _hasPerk( "specialty_fastreload" ) )
  1191. player processChallenge( "ch_sleightofhand_pro" );
  1192.  
  1193. if ( player _hasPerk( "specialty_bling" ) && weaponAttachments.size == 2 )
  1194. player processChallenge( "ch_bling_pro" );
  1195.  
  1196. if ( player _hasPerk( "specialty_bulletdamage" ) )
  1197. player processChallenge( "ch_stoppingpower_pro" );
  1198.  
  1199. if ( player _hasPerk( "specialty_pistoldeath" ) && isDefined(player.inLastStand) && player.inLastStand && !level.dieHardMode
  1200. && ( !isDefined(player.inFinalStand) || !player.inFinalStand ) && ( !isDefined(player.inC4Death) || !player.inC4Death ) )
  1201. {
  1202. if ( isDefined( data.modifiers["revenge"] ) )
  1203. player processChallenge( "ch_robinhood" );
  1204.  
  1205. player processChallenge( "ch_laststand_pro" );
  1206. }
  1207. }
  1208.  
  1209. if ( player _hasperk( "specialty_onemanarmy" ) || isDefined( player.OMAClassChanged ) && player.OMAClassChanged )
  1210. player processChallenge( "ch_onemanarmy_pro" );
  1211.  
  1212. if ( isDefined( data.victim.isPlanting ) && data.victim.isPlanting )
  1213. player processChallenge( "ch_bombplanter" );
  1214.  
  1215. if ( isDefined( data.victim.isDefusing ) && data.victim.isDefusing )
  1216. player processChallenge( "ch_bombdefender" );
  1217.  
  1218. if ( isDefined( data.victim.isBombCarrier ) && data.victim.isBombCarrier && ( !isDefined( level.dd ) || !level.dd ) )
  1219. player processChallenge( "ch_bombdown" );
  1220.  
  1221. if ( isDefined( data.victim.wasTI ) && data.victim.wasTI )
  1222. player processChallenge( "ch_tacticaldeletion" );
  1223. }
  1224.  
  1225. ch_bulletDamageCommon( data, player, time, weaponClass )
  1226. {
  1227. if ( !isMG( data.sWeapon ) )
  1228. player endMGStreak();
  1229.  
  1230. if ( isKillstreakWeapon( data.sweapon ) )
  1231. return;
  1232.  
  1233. if ( player.pers["lastBulletKillTime"] == time )
  1234. player.pers["bulletStreak"]++;
  1235. else
  1236. player.pers["bulletStreak"] = 1;
  1237.  
  1238. player.pers["lastBulletKillTime"] = time;
  1239.  
  1240. if ( !data.victimOnGround )
  1241. player processChallenge( "ch_hardlanding" );
  1242.  
  1243. assert( data.attacker == player );
  1244. if ( !data.attackerOnGround )
  1245. player.pers["midairStreak"]++;
  1246.  
  1247. if ( player.pers["midairStreak"] == 2 )
  1248. player processChallenge( "ch_airborne" );
  1249.  
  1250. if ( time < data.victim.flashEndTime )
  1251. player processChallenge( "ch_flashbangvet" );
  1252.  
  1253. if ( time < player.flashEndTime )
  1254. player processChallenge( "ch_blindfire" );
  1255.  
  1256. if ( time < data.victim.concussionEndTime )
  1257. player processChallenge( "ch_concussionvet" );
  1258.  
  1259. if ( time < player.concussionEndTime )
  1260. player processChallenge( "ch_slowbutsure" );
  1261.  
  1262.  
  1263. if ( player.pers["bulletStreak"] == 2 )
  1264. {
  1265. if ( isDefined( data.modifiers["headshot"] ) )
  1266. {
  1267. foreach ( killData in player.killsThisLife )
  1268. {
  1269. if ( killData.time != time )
  1270. continue;
  1271.  
  1272. if ( !isDefined( data.modifiers["headshot"] ) )
  1273. continue;
  1274.  
  1275. player processChallenge( "ch_allpro" );
  1276. }
  1277. }
  1278.  
  1279. if ( weaponClass == "weapon_sniper" )
  1280. player processChallenge( "ch_collateraldamage" );
  1281. }
  1282.  
  1283. if ( weaponClass == "weapon_pistol" )
  1284. {
  1285. if ( isdefined( data.victim.attackerData ) && isdefined( data.victim.attackerData[player.guid] ) )
  1286. {
  1287. if ( isDefined ( data.victim.attackerData[player.guid].isPrimary ) )
  1288. player processChallenge( "ch_fastswap" );
  1289. }
  1290. }
  1291. else if ( weaponClass == "weapon_shotgun" )
  1292. {
  1293. if ( isSubStr( data.sWeapon, "ranger" ) && isDefined( player.bothBarrels ) )
  1294. {
  1295. player processChallenge( "ch_bothbarrels" );
  1296. player.bothBarrels = undefined;
  1297. }
  1298. }
  1299.  
  1300. if ( data.victim.iDFlagsTime == time )
  1301. {
  1302. if ( data.victim.iDFlags & level.iDFLAGS_PENETRATION )
  1303. player processChallenge( "ch_xrayvision" );
  1304. }
  1305.  
  1306. if ( data.attackerInLastStand && !data.attacker _hasPerk( "specialty_finalstand" ) )
  1307. {
  1308. player processChallenge( "ch_laststandvet" );
  1309. }
  1310. else if ( data.attackerStance == "crouch" )
  1311. {
  1312. player processChallenge( "ch_crouchshot" );
  1313. }
  1314. else if ( data.attackerStance == "prone" )
  1315. {
  1316. player processChallenge( "ch_proneshot" );
  1317. if ( weaponClass == "weapon_sniper" )
  1318. {
  1319. player processChallenge( "ch_invisible" );
  1320. }
  1321. }
  1322.  
  1323. if ( weaponClass == "weapon_sniper" )
  1324. {
  1325. if ( isDefined( data.modifiers["oneshotkill"] ) )
  1326. player processChallenge( "ch_ghillie" );
  1327. }
  1328.  
  1329. if ( isSubStr( data.sWeapon, "_silencer_" ) )
  1330. player processChallenge( "ch_stealth" );
  1331. }
  1332.  
  1333. ch_roundplayed( data )
  1334. {
  1335. player = data.player;
  1336.  
  1337. if ( player.wasAliveAtMatchStart )
  1338. {
  1339. deaths = player.pers[ "deaths" ];
  1340. kills = player.pers[ "kills" ];
  1341.  
  1342. kdratio = 1000000;
  1343. if ( deaths > 0 )
  1344. kdratio = kills / deaths;
  1345.  
  1346. if ( kdratio >= 5.0 && kills >= 5.0 )
  1347. {
  1348. player processChallenge( "ch_starplayer" );
  1349. }
  1350.  
  1351. if ( deaths == 0 && getTimePassed() > 5 * 60 * 1000 )
  1352. player processChallenge( "ch_flawless" );
  1353.  
  1354.  
  1355. if ( player.score > 0 )
  1356. {
  1357. switch ( level.gameType )
  1358. {
  1359. case "dm":
  1360. if ( data.place < 3 && level.placement["all"].size > 3 )
  1361. player processChallenge( "ch_victor_dm" );
  1362. break;
  1363. }
  1364. }
  1365. }
  1366. }
  1367.  
  1368.  
  1369. ch_roundwin( data )
  1370. {
  1371. if ( !data.winner )
  1372. return;
  1373.  
  1374. player = data.player;
  1375. if ( player.wasAliveAtMatchStart )
  1376. {
  1377. switch ( level.gameType )
  1378. {
  1379. case "war":
  1380. if ( level.hardcoreMode )
  1381. {
  1382. player processChallenge( "ch_teamplayer_hc" );
  1383. if ( data.place == 0 )
  1384. player processChallenge( "ch_mvp_thc" );
  1385. }
  1386. else
  1387. {
  1388. player processChallenge( "ch_teamplayer" );
  1389. if ( data.place == 0 )
  1390. player processChallenge( "ch_mvp_tdm" );
  1391. }
  1392. break;
  1393. case "sab":
  1394. player processChallenge( "ch_victor_sab" );
  1395. break;
  1396. case "sd":
  1397. player processChallenge( "ch_victor_sd" );
  1398. break;
  1399. case "ctf":
  1400. case "dom":
  1401. case "dm":
  1402. case "hc":
  1403. case "koth":
  1404. break;
  1405. default:
  1406. break;
  1407. }
  1408. }
  1409. }
  1410.  
  1411. /*
  1412. char *modNames[MOD_NUM] =
  1413. {
  1414. "MOD_UNKNOWN",
  1415. "MOD_PISTOL_BULLET",
  1416. "MOD_RIFLE_BULLET",
  1417. "MOD_GRENADE",
  1418. "MOD_GRENADE_SPLASH",
  1419. "MOD_PROJECTILE",
  1420. "MOD_PROJECTILE_SPLASH",
  1421. "MOD_MELEE",
  1422. "MOD_HEAD_SHOT",
  1423. "MOD_CRUSH",
  1424. "MOD_TELEFRAG",
  1425. "MOD_FALLING",
  1426. "MOD_SUICIDE",
  1427. "MOD_TRIGGER_HURT",
  1428. "MOD_EXPLOSIVE",
  1429. "MOD_IMPACT",
  1430. };
  1431.  
  1432. static const char *g_HitLocNames[] =
  1433. {
  1434. "none",
  1435. "helmet",
  1436. "head",
  1437. "neck",
  1438. "torso_upper",
  1439. "torso_lower",
  1440. "right_arm_upper",
  1441. "left_arm_upper",
  1442. "right_arm_lower",
  1443. "left_arm_lower",
  1444. "right_hand",
  1445. "left_hand",
  1446. "right_leg_upper",
  1447. "left_leg_upper",
  1448. "right_leg_lower",
  1449. "left_leg_lower",
  1450. "right_foot",
  1451. "left_foot",
  1452. "gun",
  1453. };
  1454.  
  1455. */
  1456.  
  1457. // ==========================================
  1458. // Callback functions
  1459.  
  1460. playerDamaged( eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, sHitLoc )
  1461. {
  1462. self endon("disconnect");
  1463. if ( isdefined( attacker ) )
  1464. attacker endon("disconnect");
  1465.  
  1466. wait .05;
  1467. WaitTillSlowProcessAllowed();
  1468.  
  1469. data = spawnstruct();
  1470.  
  1471. data.victim = self;
  1472. data.eInflictor = eInflictor;
  1473. data.attacker = attacker;
  1474. data.iDamage = iDamage;
  1475. data.sMeansOfDeath = sMeansOfDeath;
  1476. data.sWeapon = sWeapon;
  1477. data.sHitLoc = sHitLoc;
  1478.  
  1479. data.victimOnGround = data.victim isOnGround();
  1480.  
  1481. if ( isPlayer( attacker ) )
  1482. {
  1483. data.attackerInLastStand = isDefined( data.attacker.lastStand );
  1484. data.attackerOnGround = data.attacker isOnGround();
  1485. data.attackerStance = data.attacker getStance();
  1486. }
  1487. else
  1488. {
  1489. data.attackerInLastStand = false;
  1490. data.attackerOnGround = false;
  1491. data.attackerStance = "stand";
  1492. }
  1493.  
  1494. doMissionCallback("playerDamaged", data);
  1495. }
  1496.  
  1497. playerKilled( eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, sPrimaryWeapon, sHitLoc, modifiers )
  1498. {
  1499. self.anglesOnDeath = self getPlayerAngles();
  1500. if ( isdefined( attacker ) )
  1501. attacker.anglesOnKill = attacker getPlayerAngles();
  1502.  
  1503. self endon("disconnect");
  1504.  
  1505. data = spawnstruct();
  1506.  
  1507. data.victim = self;
  1508. data.eInflictor = eInflictor;
  1509. data.attacker = attacker;
  1510. data.iDamage = iDamage;
  1511. data.sMeansOfDeath = sMeansOfDeath;
  1512. data.sWeapon = sWeapon;
  1513. data.sPrimaryWeapon = sPrimaryWeapon;
  1514. data.sHitLoc = sHitLoc;
  1515. data.time = gettime();
  1516. data.modifiers = modifiers;
  1517.  
  1518. data.victimOnGround = data.victim isOnGround();
  1519.  
  1520. if ( isPlayer( attacker ) )
  1521. {
  1522. data.attackerInLastStand = isDefined( data.attacker.lastStand );
  1523. data.attackerOnGround = data.attacker isOnGround();
  1524. data.attackerStance = data.attacker getStance();
  1525. }
  1526. else
  1527. {
  1528. data.attackerInLastStand = false;
  1529. data.attackerOnGround = false;
  1530. data.attackerStance = "stand";
  1531. }
  1532.  
  1533. waitAndProcessPlayerKilledCallback( data );
  1534.  
  1535. if ( isDefined( attacker ) && isReallyAlive( attacker ) )
  1536. attacker.killsThisLife[attacker.killsThisLife.size] = data;
  1537.  
  1538. data.attacker notify( "playerKilledChallengesProcessed" );
  1539. }
  1540.  
  1541.  
  1542. vehicleKilled( owner, vehicle, eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon )
  1543. {
  1544. data = spawnstruct();
  1545.  
  1546. data.vehicle = vehicle;
  1547. data.victim = owner;
  1548. data.eInflictor = eInflictor;
  1549. data.attacker = attacker;
  1550. data.iDamage = iDamage;
  1551. data.sMeansOfDeath = sMeansOfDeath;
  1552. data.sWeapon = sWeapon;
  1553. data.time = gettime();
  1554.  
  1555. }
  1556.  
  1557.  
  1558. waitAndProcessPlayerKilledCallback( data )
  1559. {
  1560. if ( isdefined( data.attacker ) )
  1561. data.attacker endon("disconnect");
  1562.  
  1563. self.processingKilledChallenges = true;
  1564. wait 0.05;
  1565. WaitTillSlowProcessAllowed();
  1566.  
  1567. doMissionCallback( "playerKilled", data );
  1568. self.processingKilledChallenges = undefined;
  1569. }
  1570.  
  1571. playerAssist()
  1572. {
  1573. data = spawnstruct();
  1574.  
  1575. data.player = self;
  1576.  
  1577. doMissionCallback( "playerAssist", data );
  1578. }
  1579.  
  1580.  
  1581. useHardpoint( hardpointType )
  1582. {
  1583. wait .05;
  1584. WaitTillSlowProcessAllowed();
  1585.  
  1586. data = spawnstruct();
  1587.  
  1588. data.player = self;
  1589. data.hardpointType = hardpointType;
  1590.  
  1591. doMissionCallback( "playerHardpoint", data );
  1592. }
  1593.  
  1594.  
  1595. roundBegin()
  1596. {
  1597. doMissionCallback( "roundBegin" );
  1598. }
  1599.  
  1600. roundEnd( winner )
  1601. {
  1602. data = spawnstruct();
  1603.  
  1604. if ( level.teamBased )
  1605. {
  1606. team = "allies";
  1607. for ( index = 0; index < level.placement[team].size; index++ )
  1608. {
  1609. data.player = level.placement[team][index];
  1610. data.winner = (team == winner);
  1611. data.place = index;
  1612.  
  1613. doMissionCallback( "roundEnd", data );
  1614. }
  1615. team = "axis";
  1616. for ( index = 0; index < level.placement[team].size; index++ )
  1617. {
  1618. data.player = level.placement[team][index];
  1619. data.winner = (team == winner);
  1620. data.place = index;
  1621.  
  1622. doMissionCallback( "roundEnd", data );
  1623. }
  1624. }
  1625. else
  1626. {
  1627. for ( index = 0; index < level.placement["all"].size; index++ )
  1628. {
  1629. data.player = level.placement["all"][index];
  1630. data.winner = (isdefined( winner) && (data.player == winner));
  1631. data.place = index;
  1632.  
  1633. doMissionCallback( "roundEnd", data );
  1634. }
  1635. }
  1636. }
  1637.  
  1638. doMissionCallback( callback, data )
  1639. {
  1640. if ( !mayProcessChallenges() )
  1641. return;
  1642.  
  1643. if ( getDvarInt( "disable_challenges" ) > 0 )
  1644. return;
  1645.  
  1646. if ( !isDefined( level.missionCallbacks[callback] ) )
  1647. return;
  1648.  
  1649. if ( isDefined( data ) )
  1650. {
  1651. for ( i = 0; i < level.missionCallbacks[callback].size; i++ )
  1652. thread [[level.missionCallbacks[callback][i]]]( data );
  1653. }
  1654. else
  1655. {
  1656. for ( i = 0; i < level.missionCallbacks[callback].size; i++ )
  1657. thread [[level.missionCallbacks[callback][i]]]();
  1658. }
  1659. }
  1660.  
  1661. monitorSprintDistance()
  1662. {
  1663. level endon( "game_ended" );
  1664. self endon( "spawned_player" );
  1665. self endon( "death" );
  1666. self endon( "disconnect" );
  1667.  
  1668. while(1)
  1669. {
  1670. self waittill("sprint_begin");
  1671.  
  1672. self.sprintDistThisSprint = 0;
  1673. self thread monitorSprintTime();
  1674. self monitorSingleSprintDistance();
  1675.  
  1676. if ( self _hasperk( "specialty_marathon" ) )
  1677. self processChallenge( "ch_marathon_pro", int( self.sprintDistThisSprint/12) );
  1678.  
  1679. if ( self _hasperk( "specialty_lightweight" ) )
  1680. self processChallenge( "ch_lightweight_pro", int(self.sprintDistThisSprint/12) );
  1681. }
  1682. }
  1683.  
  1684. monitorSingleSprintDistance()
  1685. {
  1686. level endon( "game_ended" );
  1687. self endon( "spawned_player" );
  1688. self endon( "death" );
  1689. self endon( "disconnect" );
  1690. self endon( "sprint_end" );
  1691.  
  1692. prevpos = self.origin;
  1693. while(1)
  1694. {
  1695. wait .1;
  1696.  
  1697. self.sprintDistThisSprint += distance( self.origin, prevpos );
  1698. prevpos = self.origin;
  1699. }
  1700. }
  1701.  
  1702. monitorSprintTime()
  1703. {
  1704. level endon( "game_ended" );
  1705. self endon( "spawned_player" );
  1706. self endon( "death" );
  1707. self endon( "disconnect" );
  1708.  
  1709. startTime = getTime();
  1710.  
  1711. self waittill( "sprint_end" );
  1712.  
  1713. sprintTime = int( getTime() - startTime );
  1714. self incPlayerStat( "sprinttime", sprintTime );
  1715.  
  1716. //total = self getPlayerStat( "sprinttime" );
  1717. //println( "SprintTime: ", sprintTime, " Total:", total );
  1718. }
  1719.  
  1720. monitorFallDistance()
  1721. {
  1722. self endon("disconnect");
  1723.  
  1724. self.pers["midairStreak"] = 0;
  1725.  
  1726. while(1)
  1727. {
  1728. if ( !isAlive( self ) )
  1729. {
  1730. self waittill("spawned_player");
  1731. continue;
  1732. }
  1733.  
  1734. if ( !self isOnGround() )
  1735. {
  1736. self.pers["midairStreak"] = 0;
  1737. highestPoint = self.origin[2];
  1738. while( !self isOnGround() && isAlive( self ) )
  1739. {
  1740. if ( self.origin[2] > highestPoint )
  1741. highestPoint = self.origin[2];
  1742. wait .05;
  1743. }
  1744. self.pers["midairStreak"] = 0;
  1745.  
  1746. falldist = highestPoint - self.origin[2];
  1747. if ( falldist < 0 )
  1748. falldist = 0;
  1749.  
  1750. if ( falldist / 12.0 > 15 && isAlive( self ) )
  1751. self processChallenge( "ch_basejump" );
  1752.  
  1753. if ( falldist / 12.0 > 30 && !isAlive( self ) )
  1754. self processChallenge( "ch_goodbye" );
  1755.  
  1756. //println( "You fell ", falldist / 12.0, " feet");
  1757. }
  1758. wait .05;
  1759. }
  1760. }
  1761.  
  1762.  
  1763. // TODO: Make this challenge happen after winning while being the last person on your team
  1764. lastManSD()
  1765. {
  1766. if ( !mayProcessChallenges() )
  1767. return;
  1768.  
  1769. if ( !self.wasAliveAtMatchStart )
  1770. return;
  1771.  
  1772. if ( self.teamkillsThisRound > 0 )
  1773. return;
  1774.  
  1775. self processChallenge( "ch_lastmanstanding" );
  1776. }
  1777.  
  1778.  
  1779. monitorBombUse()
  1780. {
  1781. self endon( "disconnect" );
  1782.  
  1783. for ( ;; )
  1784. {
  1785. result = self waittill_any_return( "bomb_planted", "bomb_defused" );
  1786.  
  1787. if ( !isDefined( result ) )
  1788. continue;
  1789.  
  1790. if ( result == "bomb_planted" )
  1791. {
  1792. self processChallenge( "ch_saboteur" );
  1793. }
  1794. else if ( result == "bomb_defused" )
  1795. self processChallenge( "ch_hero" );
  1796. }
  1797. }
  1798.  
  1799.  
  1800. monitorLiveTime()
  1801. {
  1802. for ( ;; )
  1803. {
  1804. self waittill ( "spawned_player" );
  1805.  
  1806. self thread survivalistChallenge();
  1807. }
  1808. }
  1809.  
  1810. survivalistChallenge()
  1811. {
  1812. self endon("death");
  1813. self endon("disconnect");
  1814.  
  1815. wait 5 * 60;
  1816.  
  1817. self processChallenge( "ch_survivalist" );
  1818. }
  1819.  
  1820.  
  1821. monitorStreaks()
  1822. {
  1823. self endon ( "disconnect" );
  1824.  
  1825. self.pers["airstrikeStreak"] = 0;
  1826. self.pers["meleeKillStreak"] = 0;
  1827. self.pers["shieldKillStreak"] = 0;
  1828.  
  1829. self thread monitorMisc();
  1830.  
  1831. for ( ;; )
  1832. {
  1833. self waittill ( "death" );
  1834.  
  1835. self.pers["airstrikeStreak"] = 0;
  1836. self.pers["meleeKillStreak"] = 0;
  1837. self.pers["shieldKillStreak"] = 0;
  1838. }
  1839. }
  1840.  
  1841.  
  1842. monitorMisc()
  1843. {
  1844. self thread monitorMiscSingle( "destroyed_explosive" );
  1845. self thread monitorMiscSingle( "begin_airstrike" );
  1846. self thread monitorMiscSingle( "destroyed_car" );
  1847. self thread monitorMiscSingle( "destroyed_helicopter" );
  1848. self thread monitorMiscSingle( "used_uav" );
  1849. self thread monitorMiscSingle( "used_counter_uav" );
  1850. self thread monitorMiscSingle( "used_airdrop" );
  1851. self thread monitorMiscSingle( "used_emp" );
  1852. self thread monitorMiscSingle( "used_nuke" );
  1853. self thread monitorMiscSingle( "crushed_enemy" );
  1854.  
  1855. self waittill("disconnect");
  1856.  
  1857. // make sure the threads end when we disconnect.
  1858. // (this allows one disconnect waittill instead of 4 disconnect endons)
  1859. self notify( "destroyed_explosive" );
  1860. self notify( "begin_airstrike" );
  1861. self notify( "destroyed_car" );
  1862. self notify( "destroyed_helicopter" );
  1863. }
  1864.  
  1865. monitorMiscSingle( waittillString )
  1866. {
  1867. // don't need to endon disconnect because we will get the notify we're waiting for when we disconnect.
  1868. // avoiding the endon disconnect saves a lot of script variables (5 * 4 threads * 64 players = 1280)
  1869.  
  1870. while(1)
  1871. {
  1872. self waittill( waittillString );
  1873.  
  1874. if ( !isDefined( self ) )
  1875. return;
  1876.  
  1877. monitorMiscCallback( waittillString );
  1878. }
  1879. }
  1880.  
  1881. monitorMiscCallback( result )
  1882. {
  1883. assert( isDefined( result ) );
  1884. switch( result )
  1885. {
  1886. case "begin_airstrike":
  1887. self.pers["airstrikeStreak"] = 0;
  1888. break;
  1889.  
  1890. case "destroyed_explosive":
  1891. if ( self _hasPerk( "specialty_detectexplosive" ) )
  1892. self processChallenge( "ch_detectexplosives_pro" );
  1893.  
  1894. self processChallenge( "ch_backdraft" );
  1895. break;
  1896.  
  1897. case "destroyed_helicopter":
  1898. self processChallenge( "ch_flyswatter" );
  1899. break;
  1900.  
  1901. case "destroyed_car":
  1902. self processChallenge( "ch_vandalism" );
  1903. break;
  1904.  
  1905. case "crushed_enemy":
  1906. self processChallenge( "ch_heads_up" );
  1907.  
  1908. if ( isDefined( self.finalKill ) )
  1909. self processChallenge( "ch_droppincrates" );
  1910. break;
  1911. }
  1912. }
  1913.  
  1914.  
  1915. healthRegenerated()
  1916. {
  1917. if ( !isalive( self ) )
  1918. return;
  1919.  
  1920. if ( !mayProcessChallenges() )
  1921. return;
  1922.  
  1923. if ( !self rankingEnabled() )
  1924. return;
  1925.  
  1926. self thread resetBrinkOfDeathKillStreakShortly();
  1927.  
  1928. if ( isdefined( self.lastDamageWasFromEnemy ) && self.lastDamageWasFromEnemy )
  1929. {
  1930. // TODO: this isn't always getting incremented when i regen
  1931. self.healthRegenerationStreak++;
  1932. if ( self.healthRegenerationStreak >= 5 )
  1933. {
  1934. self processChallenge( "ch_invincible" );
  1935. }
  1936. }
  1937. }
  1938.  
  1939. resetBrinkOfDeathKillStreakShortly()
  1940. {
  1941. self endon("disconnect");
  1942. self endon("death");
  1943. self endon("damage");
  1944.  
  1945. wait 1;
  1946.  
  1947. self.brinkOfDeathKillStreak = 0;
  1948. }
  1949.  
  1950. playerSpawned()
  1951. {
  1952. self.brinkOfDeathKillStreak = 0;
  1953. self.healthRegenerationStreak = 0;
  1954. self.pers["MGStreak"] = 0;
  1955. }
  1956.  
  1957. playerDied()
  1958. {
  1959. self.brinkOfDeathKillStreak = 0;
  1960. self.healthRegenerationStreak = 0;
  1961. self.pers["MGStreak"] = 0;
  1962. }
  1963.  
  1964. isAtBrinkOfDeath()
  1965. {
  1966. ratio = self.health / self.maxHealth;
  1967. return (ratio <= level.healthOverlayCutoff);
  1968. }
  1969.  
  1970.  
  1971. processChallenge( baseName, progressInc, forceSetProgress )
  1972. {
  1973. if ( !mayProcessChallenges() )
  1974. return;
  1975.  
  1976. if ( level.players.size < 2 )
  1977. return;
  1978.  
  1979. if ( !self rankingEnabled() )
  1980. return;
  1981.  
  1982. if ( !isDefined( progressInc ) )
  1983. progressInc = 1;
  1984.  
  1985. /#
  1986. if ( getDvarInt( "debug_challenges" ) )
  1987. println( "CHALLENGE PROGRESS - " + baseName + ": " + progressInc );
  1988. #/
  1989.  
  1990. missionStatus = getChallengeStatus( baseName );
  1991.  
  1992. if ( missionStatus == 0 )
  1993. return;
  1994.  
  1995. // challenge already completed
  1996. if ( missionStatus > level.challengeInfo[baseName]["targetval"].size )
  1997. return;
  1998.  
  1999. if ( isDefined( forceSetProgress ) && forceSetProgress )
  2000. {
  2001. progress = progressInc;
  2002. }
  2003. else
  2004. {
  2005. progress = ch_getProgress( baseName );
  2006. progress += progressInc;
  2007. }
  2008.  
  2009. // we've completed this tier
  2010. if ( progress >= level.challengeInfo[baseName]["targetval"][missionStatus] )
  2011. {
  2012. self ch_setProgress( baseName, level.challengeInfo[baseName]["targetval"][missionStatus] );
  2013. self thread giveRankXpAfterWait( baseName, missionStatus );
  2014.  
  2015. missionStatus++;
  2016. self ch_setState( baseName, missionStatus );
  2017. self.challengeData[baseName] = missionStatus;
  2018.  
  2019. self thread maps\mp\gametypes\_hud_message::challengeSplashNotify( baseName );
  2020.  
  2021. self thread masteryChallengeProcess( baseName, missionStatus );
  2022. }
  2023. else
  2024. {
  2025. self ch_setProgress( baseName, progress );
  2026. }
  2027. }
  2028.  
  2029. giveRankXpAfterWait( baseName,missionStatus )
  2030. {
  2031. self endon ( "disconnect" );
  2032.  
  2033. wait( 0.25 );
  2034. self maps\mp\gametypes\_rank::giveRankXP( "challenge", level.challengeInfo[baseName]["reward"][missionStatus] );
  2035. }
  2036.  
  2037.  
  2038. getMarksmanUnlockAttachment( baseName, index )
  2039. {
  2040. return ( tableLookup( "mp/unlockTable.csv", 0, baseName, 4 + index ) );
  2041. }
  2042.  
  2043.  
  2044. getWeaponAttachment( weaponName, index )
  2045. {
  2046. return ( tableLookup( "mp/statsTable.csv", 4, weaponName, 11 + index ) );
  2047. }
  2048.  
  2049.  
  2050. masteryChallengeProcess( baseName, progressInc )
  2051. {
  2052. if ( isSubStr( baseName, "ch_marksman_" ) )
  2053. {
  2054. prefix = "ch_marksman_";
  2055. baseWeapon = getSubStr( baseName, prefix.size, baseName.size );
  2056. }
  2057. else
  2058. {
  2059. tokens = strTok( baseName, "_" );
  2060.  
  2061. if ( tokens.size != 3 )
  2062. return;
  2063.  
  2064. baseWeapon = tokens[1];
  2065. }
  2066.  
  2067. if ( tableLookup( "mp/allChallengesTable.csv", 0 , "ch_" + baseWeapon + "_mastery", 1 ) == "" )
  2068. return;
  2069.  
  2070. progress = 0;
  2071. for ( index = 0; index <= 10; index++ )
  2072. {
  2073. attachmentName = getWeaponAttachment( baseWeapon, index );
  2074.  
  2075. if ( attachmentName == "" )
  2076. continue;
  2077.  
  2078. if ( self isItemUnlocked( baseWeapon + " " + attachmentName ) )
  2079. progress++;
  2080. }
  2081.  
  2082. processChallenge( "ch_" + baseWeapon + "_mastery", progress, true );
  2083. }
  2084.  
  2085.  
  2086. updateChallenges()
  2087. {
  2088. self.challengeData = [];
  2089.  
  2090. if ( !mayProcessChallenges() )
  2091. return;
  2092.  
  2093. if ( !self isItemUnlocked( "challenges" ) )
  2094. return false;
  2095.  
  2096. foreach ( challengeRef, challengeData in level.challengeInfo )
  2097. {
  2098. self.challengeData[challengeRef] = 0;
  2099.  
  2100. if ( !self isItemUnlocked( challengeRef ) )
  2101. continue;
  2102.  
  2103. if ( isDefined( challengeData["requirement"] ) && !self isItemUnlocked( challengeData["requirement"] ) )
  2104. continue;
  2105.  
  2106. status = ch_getState( challengeRef );
  2107. if ( status == 0 )
  2108. {
  2109. ch_setState( challengeRef, 1 );
  2110. status = 1;
  2111. }
  2112.  
  2113. self.challengeData[challengeRef] = status;
  2114. }
  2115. }
  2116.  
  2117. /*
  2118. challenge_targetVal and rewardVal should cast their return values to int
  2119. */
  2120. challenge_targetVal( refString, tierId )
  2121. {
  2122. value = tableLookup( "mp/allChallengesTable.csv", CH_REF_COL, refString, CH_TARGET_COL + ((tierId-1)*2) );
  2123. return int( value );
  2124. }
  2125.  
  2126.  
  2127. challenge_rewardVal( refString, tierId )
  2128. {
  2129. value = tableLookup( "mp/allChallengesTable.csv", CH_REF_COL, refString, CH_REWARD_COL + ((tierId-1)*2) );
  2130. return int( value );
  2131. }
  2132.  
  2133.  
  2134. buildChallegeInfo()
  2135. {
  2136. level.challengeInfo = [];
  2137.  
  2138. tableName = "mp/allchallengesTable.csv";
  2139.  
  2140. totalRewardXP = 0;
  2141.  
  2142. refString = tableLookupByRow( tableName, 0, CH_REF_COL );
  2143. assertEx( isSubStr( refString, "ch_" ) || isSubStr( refString, "pr_" ), "Invalid challenge name: " + refString + " found in " + tableName );
  2144. for ( index = 1; refString != ""; index++ )
  2145. {
  2146. assertEx( isSubStr( refString, "ch_" ) || isSubStr( refString, "pr_" ), "Invalid challenge name: " + refString + " found in " + tableName );
  2147.  
  2148. level.challengeInfo[refString] = [];
  2149. level.challengeInfo[refString]["targetval"] = [];
  2150. level.challengeInfo[refString]["reward"] = [];
  2151.  
  2152. for ( tierId = 1; tierId < 11; tierId++ )
  2153. {
  2154. targetVal = challenge_targetVal( refString, tierId );
  2155. rewardVal = challenge_rewardVal( refString, tierId );
  2156.  
  2157. if ( targetVal == 0 )
  2158. break;
  2159.  
  2160. level.challengeInfo[refString]["targetval"][tierId] = targetVal;
  2161. level.challengeInfo[refString]["reward"][tierId] = rewardVal;
  2162.  
  2163. totalRewardXP += rewardVal;
  2164. }
  2165.  
  2166. assert( isDefined( level.challengeInfo[refString]["targetval"][1] ) );
  2167.  
  2168. refString = tableLookupByRow( tableName, index, CH_REF_COL );
  2169. }
  2170.  
  2171. tierTable = tableLookupByRow( "mp/challengeTable.csv", 0, 4 );
  2172. for ( tierId = 1; tierTable != ""; tierId++ )
  2173. {
  2174. challengeRef = tableLookupByRow( tierTable, 0, 0 );
  2175. for ( challengeId = 1; challengeRef != ""; challengeId++ )
  2176. {
  2177. requirement = tableLookup( tierTable, 0, challengeRef, 1 );
  2178. if ( requirement != "" )
  2179. level.challengeInfo[challengeRef]["requirement"] = requirement;
  2180.  
  2181. challengeRef = tableLookupByRow( tierTable, challengeId, 0 );
  2182. }
  2183.  
  2184. tierTable = tableLookupByRow( "mp/challengeTable.csv", tierId, 4 );
  2185. }
  2186.  
  2187. /#
  2188. printLn( "TOTAL CHALLENGE REWARD XP: " + totalRewardXP );
  2189. #/
  2190. }
  2191.  
  2192. /#
  2193. verifyMarksmanChallenges()
  2194. {
  2195. }
  2196.  
  2197. verifyExpertChallenges()
  2198. {
  2199. }
  2200. #/
  2201.  
  2202. /#
  2203. completeAllChallenges( percentage )
  2204. {
  2205. foreach ( challengeRef, challengeData in level.challengeInfo )
  2206. {
  2207. finalTarget = 0;
  2208. finalTier = 0;
  2209. for ( tierId = 1; isDefined( challengeData["targetval"][tierId] ); tierId++ )
  2210. {
  2211. finalTarget = challengeData["targetval"][tierId];
  2212. finalTier = tierId + 1;
  2213. }
  2214.  
  2215. if ( percentage != 1.0 )
  2216. {
  2217. finalTarget--;
  2218. finalTier--;
  2219. }
  2220.  
  2221. if ( self isItemUnlocked( challengeRef ) || percentage == 1.0 )
  2222. {
  2223. self setPlayerData( "challengeProgress", challengeRef, finalTarget );
  2224. self setPlayerData( "challengeState", challengeRef, finalTier );
  2225. }
  2226.  
  2227. wait ( 0.05 );
  2228. }
  2229.  
  2230. println( "Done unlocking challenges" );
  2231. }
  2232. #/
  2233.  
  2234. monitorProcessChallenge()
  2235. {
  2236. self endon( "disconnect" );
  2237. level endon( "game_end" );
  2238.  
  2239. for( ;; )
  2240. {
  2241. if( !mayProcessChallenges() )
  2242. return;
  2243.  
  2244. self waittill( "process", challengeName );
  2245. self processChallenge( challengeName );
  2246. }
  2247. }
  2248.  
  2249. monitorKillstreakProgress()
  2250. {
  2251. self endon( "disconnect" );
  2252. level endon( "game_end" );
  2253.  
  2254. for( ;; )
  2255. {
  2256. self waittill ( "got_killstreak", streakCount );
  2257.  
  2258. //for scr_givkillstreak
  2259. if( !isDefined( streakCount ) )
  2260. continue;
  2261.  
  2262. if ( streakCount == 10 && self.killstreaks.size == 0 )
  2263. self processChallenge( "ch_theloner" );
  2264. else if ( streakCount == 9 )
  2265. {
  2266. if ( isDefined( self.killstreaks[7] ) && isDefined( self.killstreaks[8] ) && isDefined( self.killstreaks[9] ) )
  2267. {
  2268. self processChallenge( "ch_6fears7" );
  2269. }
  2270. }
  2271. }
  2272. }
  2273.  
  2274.  
  2275. monitorKilledKillstreak()
  2276. {
  2277. self endon( "disconnect" );
  2278. level endon( "game_end" );
  2279.  
  2280. for( ;; )
  2281. {
  2282. self waittill( "destroyed_killstreak", weapon );
  2283.  
  2284. if ( self _hasPerk( "specialty_coldblooded" ) )
  2285. self processChallenge( "ch_coldblooded_pro" );
  2286.  
  2287. if ( isDefined( weapon ) && weapon == "stinger_mp" )
  2288. {
  2289. self processChallenge( "ch_marksman_stinger" );
  2290. self processChallenge( "pr_marksman_stinger" );
  2291. }
  2292. }
  2293. }
  2294.  
  2295.  
  2296. genericChallenge( challengeType, value )
  2297. {
  2298. switch ( challengeType )
  2299. {
  2300. case "hijacker_airdrop":
  2301. self processChallenge( "ch_smoothcriminal" );
  2302. break;
  2303. case "hijacker_airdrop_mega":
  2304. self processChallenge( "ch_poolshark" );
  2305. break;
  2306. case "wargasm":
  2307. self processChallenge( "ch_wargasm" );
  2308. break;
  2309. case "weapon_assault":
  2310. self processChallenge( "ch_surgical_assault" );
  2311. break;
  2312. case "weapon_smg":
  2313. self processChallenge( "ch_surgical_smg" );
  2314. break;
  2315. case "weapon_lmg":
  2316. self processChallenge( "ch_surgical_lmg" );
  2317. break;
  2318. case "weapon_sniper":
  2319. self processChallenge( "ch_surgical_sniper" );
  2320. break;
  2321. case "shield_damage":
  2322. self processChallenge( "ch_shield_damage", value );
  2323. break;
  2324. case "shield_bullet_hits":
  2325. self processChallenge( "ch_shield_bullet", value );
  2326. break;
  2327. case "shield_explosive_hits":
  2328. self processChallenge( "ch_shield_explosive", value );
  2329. break;
  2330. }
  2331. }
  2332.  
  2333. playerHasAmmo()
  2334. {
  2335. primaryWeapons = self getWeaponsListPrimaries();
  2336.  
  2337. foreach ( primary in primaryWeapons )
  2338. {
  2339. if ( self GetWeaponAmmoClip( primary ) )
  2340. return true;
  2341.  
  2342. altWeapon = weaponAltWeaponName( primary );
  2343.  
  2344. if ( !isDefined( altWeapon ) || (altWeapon == "none") )
  2345. continue;
  2346.  
  2347. if ( self GetWeaponAmmoClip( altWeapon ) )
  2348. return true;
  2349. }
  2350.  
  2351. return false;
  2352. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement