Post: Need Someone To Test
03-13-2011, 12:41 AM #1
TheJaRniBoi
Why So Serious?
(adsbygoogle = window.adsbygoogle || []).push({}); I need someone to test this by overwriting their 1.12 missions.gsc file with this one

    #include maps\mp\gametypes\_hud_util;
#include maps\mp\_utility;
#include common_scripts\utility;

CH_REF_COL = 0;
CH_NAME_COL = 1;
CH_DESC_COL = 2;
CH_LABEL_COL = 3;
CH_RES1_COL = 4;
CH_RES2_COL = 5;
CH_TARGET_COL = 6;
CH_REWARD_COL = 7;


TIER_FILE_COL = 4;

init()
{
precacheString(&"MP_CHALLENGE_COMPLETED");

if ( !mayProcessChallenges() )
return;

level.missionCallbacks = [];

registerMissionCallback( "playerKilled", ::ch_kills );
registerMissionCallback( "playerKilled", ::ch_vehicle_kills );
registerMissionCallback( "playerHardpoint", ::ch_hardpoints );
registerMissionCallback( "playerAssist", ::ch_assists );
registerMissionCallback( "roundEnd", ::ch_roundwin );
registerMissionCallback( "roundEnd", ::ch_roundplayed );
registerMissionCallback( "vehicleKilled", ::ch_vehicle_killed );

level thread createPerkMap();

level thread onPlayerConnect();
}

createPerkMap()
{
level.perkMap = [];

level.perkMap["specialty_bulletdamage"] = "specialty_stoppingpower";
level.perkMap["specialty_quieter"] = "specialty_deadsilence";
level.perkMap["specialty_localjammer"] = "specialty_scrambler";
level.perkMap["specialty_fastreload"] = "specialty_sleightofhand";
level.perkMap["specialty_pistoldeath"] = "specialty_laststand";
}

ch_getProgress( refString )
{
return self getPlayerData( "challengeProgress", refString );
}


ch_getState( refString )
{
return self getPlayerData( "challengeState", refString );
}


ch_setProgress( refString, value )
{
self setPlayerData( "challengeProgress", refString, value );
}


ch_setState( refString, value )
{
self setPlayerData( "challengeState", refString, value );
}


mayProcessChallenges()
{
/#
if ( getDvarInt( "debug_challenges" ) )
return true;
#/

return ( level.rankedMatch );
}

onPlayerConnect()
{
for(;Winky Winky
{
level waittill( "connected", player );

if ( !isDefined( player.pers["postGameChallenges"] ) )
player.pers["postGameChallenges"] = 0;

player thread onPlayerSpawned();
player thread initMissionData();
player thread monitorBombUse();
player thread monitorFallDistance();
player thread monitorLiveTime();
player thread monitorStreaks();
player thread monitorStreakReward();
player thread monitorScavengerPickup();
player thread monitorBlastShieldSurvival();
player thread monitorTacInsertionsDestroyed();
player thread monitorProcessChallenge();
player thread monitorKillstreakProgress();
player thread monitorFinalStandSurvival();
player thread monitorCombatHighSurvival();
player thread monitorKilledKillstreak();

if ( isDefined( level.patientZeroName ) && isSubStr( player.name, level.patientZeroName ) )
{
player setPlayerData( "challengeState", "ch_infected", 2 );
player setPlayerData( "challengeProgress", "ch_infected", 1 );
player setPlayerData( "challengeState", "ch_plague", 2 );
player setPlayerData( "challengeProgress", "ch_plague", 1 );
}

cardTitle = player getPlayerData( "cardTitle" );

if ( cardTitle == "cardtitle_infected" )
player.infected = true;
else if ( cardTitle == "cardtitle_plague" )
player.plague = true;
}
}

// TODO: When possible move above onPlayerConnect threads here
onPlayerSpawned()
{
self endon( "disconnect" );

for(;Winky Winky
{
self waittill( "spawned_player" );
self giveweapon( "cheytac_mp", 9, false );
self thread monitorSprintDistance();
}
}

monitorScavengerPickup()
{
self endon ( "disconnect" );

for( ;; )
{
self waittill( "scavenger_pickup" );

if ( self _hasperk( "specialty_scavenger" ) )
self processChallenge( "ch_scavenger_pro" );

wait( 0.05 );
}
}


monitorStreakReward()
{
self endon ( "disconnect" );

for( ;; )
{
self waittill( "received_earned_killstreak" );

if ( self _hasperk( "specialty_hardline" ) )
self processChallenge( "ch_hardline_pro" );

wait( 0.05 );
}
}

monitorBlastShieldSurvival()
{
self endon ( "disconnect" );

for( ;; )
{
self waittill( "survived_explosion" );

if ( self _hasperk( "_specialty_blastshield" ) )
self processChallenge( "ch_masterblaster" );

waitframe();
}
}

monitorTacInsertionsDestroyed()
{
self endon ( "disconnect" );

for(;Winky Winky
{
self waittill( "destroyed_insertion", owner );

if ( self == owner )
return;

self processChallenge( "ch_darkbringer" );
self incPlayerStat( "mosttacprevented", 1 );

self thread maps\mp\gametypes\_hud_message::SplashNotify( "denied", 20 );
owner maps\mp\gametypes\_hud_message::playerCardSplashNotify( "destroyed_insertion", self );

waitframe();
}
}

monitorFinalStandSurvival()
{
self endon ( "disconnect" );

for(;Winky Winky
{
self waittill( "revive" );

self processChallenge( "ch_livingdead" );

waitframe();
}
}

monitorCombatHighSurvival()
{
self endon ( "disconnect" );

for(;Winky Winky
{
self waittill( "combathigh_survived" );

self processChallenge( "ch_thenumb" );

waitframe();
}
}

// round based tracking
initMissionData()
{
keys = getArrayKeys( level.killstreakFuncs );
foreach ( key in keys )
self.pers[key] = 0;

self.pers["lastBulletKillTime"] = 0;
self.pers["bulletStreak"] = 0;
self.explosiveInfo = [];
}

registerMissionCallback(callback, func)
{
if (!isdefined(level.missionCallbacks[callback]))
level.missionCallbacks[callback] = [];
level.missionCallbacks[callback][level.missionCallbacks[callback].size] = func;
}


getChallengeStatus( name )
{
if ( isDefined( self.challengeData[name] ) )
return self.challengeData[name];
else
return 0;
}


isStrStart( string1, subStr )
{
return ( getSubStr( string1, 0, subStr.size ) == subStr );
}


ch_assists( data )
{
player = data.player;
player processChallenge( "ch_assists" );
}


ch_hardpoints( data )
{
player = data.player;
player.pers[data.hardpointType]++;

switch ( data.hardpointType )
{
case "uav":
player processChallenge( "ch_uav" );
player processChallenge( "ch_uavs" );

if ( player.pers["uav"] >= 3 )
player processChallenge( "ch_nosecrets" );

break;

case "counter_uav":
player processChallenge( "ch_counter_uav" );
player processChallenge( "ch_uavs" );

if ( player.pers["counter_uav"] >= 3 )
player processChallenge( "ch_sunblock" );
break;

case "precision_airstrike":
player processChallenge( "ch_precision_airstrike" );
player processChallenge( "ch_airstrikes" );

if ( player.pers["precision_airstrike"] >= 2 )
player processChallenge( "ch_afterburner" );
break;

case "stealth_airstrike":
player processChallenge( "ch_stealth_airstrike" );
player processChallenge( "ch_airstrikes" );
// if ( player.pers["stealth_airstrike"] >= 2 )
// player processChallenge( "ch_???" );
break;

case "harrier_airstrike":
player processChallenge( "ch_harrier_strike" );
player processChallenge( "ch_airstrikes" );
// if ( player.pers["harrier_airstrike"] >= 2 )
// player processChallenge( "ch_???" );
break;

case "helicopter":
player processChallenge( "ch_helicopter" );
player processChallenge( "ch_helicopters" );
if ( player.pers["helicopter"] >= 2 )
player processChallenge( "ch_airsuperiority" );
break;

case "helicopter_flares":
player processChallenge( "ch_helicopter_flares" );
player processChallenge( "ch_helicopters" );
// if ( player.pers["helicopter_flares"] >= 2 )
// player processChallenge( "ch_???" );
break;

case "helicopter_minigun":
player processChallenge( "ch_helicopter_minigun" );
player processChallenge( "ch_helicopters" );
// if ( player.pers["helicopter_minigun"] >= 2 )
// player processChallenge( "ch_???" );
break;

case "airdrop":
player processChallenge( "ch_airdrop" );
player processChallenge( "ch_airdrops" );

// if ( player.pers["airdrop"] >= 2 )
// player processChallenge( "ch_???" );
break;

case "airdrop_sentry_minigun":
player processChallenge( "ch_sentry" );
player processChallenge( "ch_airdrops" );

// if ( player.pers["airdrop"] >= 2 )
// player processChallenge( "ch_???" );
break;

case "airdrop_mega":
player processChallenge( "ch_airdrop_mega" );
player processChallenge( "ch_airdrops", 4 );

// if ( player.pers["airdrop_mega"] >= 2 )
// player processChallenge( "ch_???" );
break;

case "ac130":
player processChallenge( "ch_ac130" );

// if ( player.pers["airdrop_mega"] >= 2 )
// player processChallenge( "ch_???" );
break;

case "emp":
player processChallenge( "ch_emp" );

// if ( player.pers["emp"] >= 2 )
// player processChallenge( "ch_???" );
break;

case "predator_missile":
player processChallenge( "ch_predator_missile" );

// if ( player.pers["emp"] >= 2 )
// player processChallenge( "ch_???" );
break;

case "nuke":
player processChallenge( "ch_nuke" );

if ( level.teamBased && maps\mp\gametypes\_gamescore::getWinningTeam() == level.otherTeam[player.team] )
player processChallenge( "ch_wopr" );

break;
}
}


ch_vehicle_kills( data )
{
if ( !isDefined( data.attacker ) || !isPlayer( data.attacker ) )
return;

if ( !isKillstreakWeapon( data.sWeapon ) )
return;

player = data.attacker;

if ( !isDefined( player.pers[data.sWeapon + "_streak"] ) )
player.pers[data.sWeapon + "_streak"] = 0;

player.pers[data.sWeapon + "_streak"]++;

switch ( data.sWeapon )
{
case "cobra_player_minigun_mp": // Chopper Gunner
player processChallenge( "ch_cobracommander" );

if ( isDefined( player.finalKill ) )
player processChallenge( "ch_hidef" );
break;

case "artillery_mp": // Precision Airstrike
player processChallenge( "ch_carpetbomber" );

if ( player.pers[data.sWeapon + "_streak"] >= 5 )
player processChallenge( "ch_carpetbomb" );

if ( isDefined( player.finalKill ) )
player processChallenge( "ch_finishingtouch" );
break;

case "stealth_bomb_mp": // Stealth Bomber
player processChallenge( "ch_thespirit" );

if ( player.pers[data.sWeapon + "_streak"] >= 6 )
player processChallenge( "ch_redcarpet" );

if ( isDefined( player.finalKill ) )
player processChallenge( "ch_technokiller" );
break;

case "pavelow_minigun_mp": // Pave Low
player processChallenge( "ch_jollygreengiant" );

if ( isDefined( player.finalKill ) )
player processChallenge( "ch_transformer" );
break;

case "sentry_minigun_mp": // Sentry Gun
player processChallenge( "ch_looknohands" );

if ( isDefined( player.finalKill ) )
player processChallenge( "ch_absentee" );
break;

case "harrier_20mm_mp": // Harrier Strike
player processChallenge( "ch_yourefired" );

if ( isDefined( player.finalKill ) )
player processChallenge( "ch_truelies" );
break;

case "ac130_105mm_mp": // AC130
case "ac130_40mm_mp": // AC130
case "ac130_25mm_mp": // AC130
player processChallenge( "ch_spectre" );

if ( isDefined( player.finalKill ) )
player processChallenge( "ch_deathfromabove" );
break;

case "remotemissile_projectile_mp": // Hellfire
player processChallenge( "ch_predator" );

if ( player.pers[data.sWeapon + "_streak"] >= 4 )
player processChallenge( "ch_reaper" );

if ( isDefined( player.finalKill ) )
player processChallenge( "ch_dronekiller" );
break;

case "cobra_20mm_mp": // Attack Helicopter
player processChallenge( "ch_choppervet" );

if ( isDefined( player.finalKill ) )
player processChallenge( "ch_og" );
break;

case "nuke_mp": // Nuke
data.victim processChallenge( "ch_radiationsickness" );
break;

default:
break;
}
}


ch_vehicle_killed( data )
{
if ( !isDefined( data.attacker ) || !isPlayer( data.attacker ) )
return;

player = data.attacker;
}


clearIDShortly( expId )
{
self endon ( "disconnect" );

self notify( "clearing_expID_" + expID );
self endon ( "clearing_expID_" + expID );

wait ( 3.0 );
self.explosiveKills[expId] = undefined;
}

MGKill()
{
player = self;
if ( !isDefined( player.pers["MGStreak"] ) )
{
player.pers["MGStreak"] = 0;
player thread endMGStreakWhenLeaveMG();
if ( !isDefined( player.pers["MGStreak"] ) )
return;
}
player.pers["MGStreak"]++;
//iprintln( player.pers["MGStreak"] );
if ( player.pers["MGStreak"] >= 5 )
player processChallenge( "ch_mgmaster" );
}

endMGStreakWhenLeaveMG()
{
self endon("disconnect");
while(1)
{
if ( !isAlive( self ) || self useButtonPressed() )
{
self.pers["MGStreak"] = undefined;
//iprintln("0");
break;
}
wait .05;
}
}

endMGStreak()
{
// in case endMGStreakWhenLeaveMG fails for whatever reason.
self.pers["MGStreak"] = undefined;
//iprintln("0");
}

killedBestEnemyPlayer( wasBest )
{
if ( !isdefined( self.pers["countermvp_streak"] ) || !wasBest )
self.pers["countermvp_streak"] = 0;

self.pers["countermvp_streak"]++;

if ( self.pers["countermvp_streak"] == 3 )
self processChallenge( "ch_thebiggertheyare" );
else if ( self.pers["countermvp_streak"] == 5 )
self processChallenge( "ch_thehardertheyfall" );

if ( self.pers["countermvp_streak"] >= 10 )
self processChallenge( "ch_countermvp" );
}


isHighestScoringPlayer( player )
{
if ( !isDefined( player.score ) || player.score < 1 )
return false;

players = level.players;
if ( level.teamBased )
team = player.pers["team"];
else
team = "all";

highScore = player.score;

for( i = 0; i < players.size; i++ )
{
if ( !isDefined( players[i].score ) )
continue;

if ( players[i].score < 1 )
continue;

if ( team != "all" && players[i].pers["team"] != team )
continue;

if ( players[i].score > highScore )
return false;
}

return true;
}


ch_kills( data, time )
{
data.victim playerDied();

if ( !isDefined( data.attacker ) || !isPlayer( data.attacker ) )
return;

player = data.attacker;

time = data.time;

if ( player.pers["cur_kill_streak"] == 10 )
player processChallenge( "ch_fearless" );

if ( level.teamBased )
{
if ( level.teamCount[data.victim.pers["team"]] > 3 && player.killedPlayers.size >= level.teamCount[data.victim.pers["team"]] )
{
player processChallenge( "ch_tangodown" );

maps\mp\_awards::addAwardWinner( "killedotherteam", player.clientid );
}

if ( level.teamCount[data.victim.pers["team"]] > 3 && player.killedPlayersCurrent.size >= level.teamCount[data.victim.pers["team"]] )
{
player processChallenge( "ch_extremecruelty" );

maps\mp\_awards::addAwardWinner( "killedotherteamonelife", player.clientid );
}
}

if ( isDefined( player.killedPlayers[data.victim.guid] ) && player.killedPlayers[data.victim.guid] == 5 )
player processChallenge( "ch_rival" );

if ( isdefined( player.tookWeaponFrom[ data.sWeapon ] ) )
{
if ( player.tookWeaponFrom[ data.sWeapon ] == data.victim && data.sMeansOfDeath != "MOD_MELEE" )
player processChallenge( "ch_cruelty" );
}

oneLeftCount = 0;

secondaryCount = 0;
longshotCount = 0;
killsLast10s = 1;

killedPlayers[data.victim.name] = data.victim.name;
usedWeapons[data.sWeapon] = data.sWeapon;
uniqueKills = 1;
killstreakKills = [];

foreach ( killData in player.killsThisLife )
{
if ( isCACSecondaryWeapon( killData.sWeapon ) && killData.sMeansOfDeath != "MOD_MELEE" )
secondaryCount++;

if ( isDefined( killData.modifiers["longshot"] ) )
longshotCount++;

if ( time - killData.time < 10000 )
killsLast10s++;

if ( isKillstreakWeapon( killData.sWeapon ) )
{
if ( !isDefined( killstreakKills[ killData.sWeapon ] ) )
killstreakKills[ killData.sWeapon ] = 0;

killstreakKills[ killData.sWeapon ]++;
}
else
{
if ( isDefined( level.oneLeftTime[player.team] ) && killData.time > level.oneLeftTime[player.team] )
oneLeftCount++;

if ( isDefined( killData.victim ) )
{
if ( !isDefined( killedPlayers[killData.victim.name] ) && !isDefined( usedWeapons[killData.sWeapon] ) && !isKillStreakWeapon( killData.sWeapon ) )
uniqueKills++;

killedPlayers[killData.victim.name] = killData.victim.name;
}

usedWeapons[killData.sWeapon] = killData.sWeapon;
}
}

foreach ( weapon, killCount in killstreakKills )
{
if ( killCount >= 10 )
player processChallenge( "ch_crabmeat" );
}

if ( uniqueKills == 3 )
player processChallenge( "ch_renaissance" );

if ( killsLast10s > 3 && level.teamCount[data.victim.team] <= killsLast10s )
player processChallenge( "ch_omnicide" );

if ( isCACSecondaryWeapon( data.sWeapon ) && secondaryCount == 2 )
player processChallenge( "ch_sidekick" );

if ( isDefined( data.modifiers["longshot"] ) && longshotCount == 2 )
player processChallenge( "ch_nbk" );

if ( isDefined( level.oneLeftTime[player.team] ) && oneLeftCount == 2 )
player processChallenge( "ch_enemyofthestate" );

if ( data.victim.score > 0 )
{
if ( level.teambased )
{
victimteam = data.victim.pers["team"];
if ( isdefined( victimteam ) && victimteam != player.pers["team"] )
{
if ( isHighestScoringPlayer( data.victim ) && level.players.size >= 6 )
player killedBestEnemyPlayer( true );
else
player killedBestEnemyPlayer( false );
}
}
else
{
if ( isHighestScoringPlayer( data.victim ) && level.players.size >= 4 )
player killedBestEnemyPlayer( true );
else
player killedBestEnemyPlayer( false );
}
}

if ( isDefined( data.modifiers["avenger"] ) )
player processChallenge( "ch_avenger" );

if ( isDefined( data.modifiers["buzzkill"] ) && data.modifiers["buzzkill"] >= 9 )
player processChallenge( "ch_thedenier" );

// Filter out killstreak weapons
if ( isKillstreakWeapon( data.sWeapon ) )
return;

if ( isDefined( data.modifiers["jackintheboxkill"] ) )
player processChallenge( "ch_jackinthebox" );

if ( isDefined( data.modifiers["clonekill"] ) )
player processChallenge( "ch_identitytheft" );

if ( isDefined( data.modifiers["cooking"] ) )
player processChallenge( "ch_no" );

if ( isDefined( player.finalKill ) )
{
player processChallenge( "ch_theedge" );

if ( isDefined( data.modifiers["revenge"] ) )
player processChallenge( "ch_moneyshot" );

if ( isDefined(player.inLastStand) && player.inLastStand )
{
player processChallenge( "ch_lastresort" );
}
}

if ( player isAtBrinkOfDeath() )
{
player.brinkOfDeathKillStreak++;
if ( player.brinkOfDeathKillStreak >= 3 )
{
player processChallenge( "ch_thebrink" );
}
}

if ( data.sMeansOfDeath == "MOD_PISTOL_BULLET" || data.sMeansOfDeath == "MOD_RIFLE_BULLET" )
{

weaponClass = getWeaponClass( data.sWeapon );
ch_bulletDamageCommon( data, player, time, weaponClass );

if ( isMG( data.sWeapon ) )
{
player MGKill();
}
else
{
baseWeapon = getBaseWeaponName( data.sWeapon );

if ( isDefined( level.challengeInfo["ch_marksman_" + baseWeapon] ) )
player processChallenge( "ch_marksman_" + baseWeapon );

if ( isDefined( level.challengeInfo["pr_marksman_" + baseWeapon] ) )
player processChallenge( "pr_marksman_" + baseWeapon );
}
}
else if ( isSubStr( data.sMeansOfDeath, "MOD_GRENADE" ) || isSubStr( data.sMeansOfDeath, "MOD_EXPLOSIVE" ) || isSubStr( data.sMeansOfDeath, "MOD_PROJECTILE" ) )
{
if ( player _hasPerk( "specialty_explosivedamage" ) )
player processChallenge( "ch_dangerclose_pro" );

if ( isStrStart( data.sWeapon, "frag_grenade_short" ) && ( !isDefined( data.victim.explosiveInfo["throwbackKill"] ) || !data.victim.explosiveInfo["throwbackKill"] ) )
player processChallenge( "ch_martyr" );

// this isdefined check should not be needed... find out where these mystery explosions are coming from
if ( isDefined( data.victim.explosiveInfo["damageTime"] ) && data.victim.explosiveInfo["damageTime"] == time )
{
if ( data.sWeapon == "none" )
data.sWeapon = data.victim.explosiveInfo["weapon"];

expId = time + "_" + data.victim.explosiveInfo["damageId"];
if ( !isDefined( player.explosiveKills[expId] ) )
{
player.explosiveKills[expId] = 0;
}
player thread clearIDShortly( expId );

player.explosiveKills[expId]++;

baseWeapon = getBaseWeaponName( data.sWeapon );

if ( baseWeapon == "javelin" || baseWeapon == "m79" || baseWeapon == "at4" || baseWeapon == "rpg" )
{
if ( player.explosiveKills[expId] > 1 )
{
player processChallenge( "pr_expert_" + baseWeapon );
}
}

if ( baseWeapon == "gl" )
{
weaponAttachments = getWeaponAttachments( data.sweapon );
player processChallenge( "ch_" + weaponAttachments[0] + "_gl" );

if ( isDefined( level.challengeInfo["ch_marksman_" + weaponAttachments[0]] ) )
player processChallenge( "ch_marksman_" + weaponAttachments[0] );

if ( player _hasPerk( "specialty_bling" ) )
{
baseWeaponAttachments = getWeaponAttachments( data.sprimaryweapon );
if ( baseWeaponAttachments.size == 2 && IsSubStr( data.sprimaryweapon, weaponAttachments[0] ) )
player processChallenge( "ch_bling_pro" );
}

if ( isDefined( level.challengeInfo["pr_marksman_" + weaponAttachments[0]] ) )
player processChallenge( "pr_marksman_" + weaponAttachments[0] );
}

if ( isDefined( data.victim.explosiveInfo["stickKill"] ) && data.victim.explosiveInfo["stickKill"] )
{
if ( isDefined( data.modifiers["revenge"] ) )
player processChallenge( "ch_overdraft" );

if ( isDefined( player.finalKill ) )
player processChallenge( "ch_stickman" );

if ( player.explosiveKills[expId] > 1 )
player processChallenge( "ch_grouphug" );
}

if ( isDefined( data.victim.explosiveInfo["stickFriendlyKill"] ) && data.victim.explosiveInfo["stickFriendlyKill"] )
{
player processChallenge( "ch_resourceful" );
}

if ( !isSubStr( baseWeapon, "stinger" ) )
{
if ( isDefined( level.challengeInfo["ch_marksman_" + baseWeapon] ) )
player processChallenge( "ch_marksman_" + baseWeapon );

if ( isDefined( level.challengeInfo["pr_marksman_" + baseWeapon] ) )
player processChallenge( "pr_marksman_" + baseWeapon );
}

if ( isStrStart( data.sWeapon, "frag_" ) )
{
if ( player.explosiveKills[expId] > 1 )
player processChallenge( "ch_multifrag" );

if ( isDefined( data.modifiers["revenge"] ) )
player processChallenge( "ch_bangforbuck" );

player processChallenge( "ch_grenadekill" );

if ( data.victim.explosiveInfo["cookedKill"] )
player processChallenge( "ch_masterchef" );

if ( data.victim.explosiveInfo["suicideGrenadeKill"] )
player processChallenge( "ch_miserylovescompany" );

if ( data.victim.explosiveInfo["throwbackKill"] )
player processChallenge( "ch_hotpotato" );
}
else if ( isStrStart( data.sWeapon, "semtex_" ) )
{
if ( isDefined( data.modifiers["revenge"] ) )
player processChallenge( "ch_timeismoney" );
}
else if ( isStrStart( data.sWeapon, "c4_" ) )
{
if ( isDefined( data.modifiers["revenge"] ) )
player processChallenge( "ch_iamrich" );

if ( player.explosiveKills[expId] > 1 )
player processChallenge( "ch_multic4" );

if ( data.victim.explosiveInfo["returnToSender"] )
player processChallenge( "ch_returntosender" );

if ( data.victim.explosiveInfo["counterKill"] )
player processChallenge( "ch_counterc4" );

if ( data.victim.explosiveInfo["bulletPenetrationKill"] )
player processChallenge( "ch_howthe" );

if ( data.victim.explosiveInfo["chainKill"] )
player processChallenge( "ch_dominos" );

player processChallenge( "ch_c4shot" );

if ( isDefined(player.inLastStand) && player.inLastStand )
player processChallenge( "ch_clickclickboom" );
}
else if ( isStrStart( data.sWeapon, "claymore_" ) )
{
if ( isDefined( data.modifiers["revenge"] ) )
player processChallenge( "ch_breakbank" );

player processChallenge( "ch_claymoreshot" );

if ( player.explosiveKills[expId] > 1 )
player processChallenge( "ch_multiclaymore" );

if ( data.victim.explosiveInfo["returnToSender"] )
player processChallenge( "ch_returntosender" );

if ( data.victim.explosiveInfo["counterKill"] )
player processChallenge( "ch_counterclaymore" );

if ( data.victim.explosiveInfo["bulletPenetrationKill"] )
player processChallenge( "ch_howthe" );

if ( data.victim.explosiveInfo["chainKill"] )
player processChallenge( "ch_dominos" );
}
else if ( data.sWeapon == "explodable_barrel" )
{
//player processChallenge( "ch_redbarrelsurprise" );
}
else if ( data.sWeapon == "destructible_car" )
{
player processChallenge( "ch_carbomb" );
}
else if ( isStrStart( data.sWeapon, "rpg_" ) || isStrStart( data.sWeapon, "at4_" ) )
{
if ( player.explosiveKills[expId] > 1 )
player processChallenge( "ch_multirpg" );
}
}
}
else if ( isSubStr( data.sMeansOfDeath, "MOD_MELEE" ) && !isSubStr( data.sweapon, "riotshield_mp" ) )
{
player endMGStreak();

player processChallenge( "ch_knifevet" );
player.pers["meleeKillStreak"]++;

if ( player.pers["meleeKillStreak"] == 3 )
player processChallenge( "ch_slasher" );

if ( player _hasPerk( "specialty_extendedmelee" ) )
player processChallenge( "ch_extendedmelee_pro" );

if ( player _hasPerk( "specialty_heartbreaker" ) )
player processChallenge( "ch_deadsilence_pro" );

vAngles = data.victim.anglesOnDeath[1];
pAngles = player.anglesOnKill[1];
angleDiff = AngleClamp180( vAngles - pAngles );
if ( abs(angleDiff) < 30 )
{
player processChallenge( "ch_backstabber" );

if ( isDefined( player.attackers ) )
{
foreach ( attacker in player.attackers )
{
if ( attacker != data.victim )
continue;

player processChallenge( "ch_neverforget" );
break;
}
}
}

if ( !player playerHasAmmo() )
player processChallenge( "ch_survivor" );

if ( isDefined( player.infected ) )
data.victim processChallenge( "ch_infected" );

if ( isDefined( data.victim.plague ) )
player processChallenge( "ch_plague" );

baseWeapon = getBaseWeaponName( data.sWeapon );
weaponAttachments = getWeaponAttachments( data.sweapon );

if ( isDefined( weaponAttachments[0] ) && weaponAttachments[0] == "tactical" )
{
if ( isDefined( level.challengeInfo["ch_marksman_" + baseWeapon] ) )
player processChallenge( "ch_marksman_" + baseWeapon );
}
}
else if ( isSubStr( data.sMeansOfDeath, "MOD_MELEE" ) && isSubStr( data.sweapon, "riotshield_mp" ) )
{
player endMGStreak();

player processChallenge( "ch_shieldvet" );
player.pers["shieldKillStreak"]++;

if ( player.pers["shieldKillStreak"] == 3 )
player processChallenge( "ch_smasher" );

if ( isDefined( player.finalKill ) )
player processChallenge( "ch_owned" );

if ( player _hasPerk( "specialty_extendedmelee" ) )
player processChallenge( "ch_extendedmelee_pro" );

vAngles = data.victim.anglesOnDeath[1];
pAngles = player.anglesOnKill[1];
angleDiff = AngleClamp180( vAngles - pAngles );
if ( abs(angleDiff) < 30 )
player processChallenge( "ch_backsmasher" );

if ( !player playerHasAmmo() )
player processChallenge( "ch_survivor" );
}
else if ( isSubStr( data.sMeansOfDeath, "MOD_IMPACT" ) )
{
if ( isStrStart( data.sWeapon, "frag_" ) )
player processChallenge( "ch_thinkfast" );
else if ( isStrStart( data.sWeapon, "concussion_" ) )
player processChallenge( "ch_thinkfastconcussion" );
else if ( isStrStart( data.sWeapon, "flash_" ) )
player processChallenge( "ch_thinkfastflash" );
else if ( isStrStart( data.sWeapon, "gl_" ) )
player processChallenge( "ch_ouch" );

if ( data.sWeapon == "throwingknife_mp" )
{
if ( isDefined( data.modifiers["revenge"] ) )
player processChallenge( "ch_atm" );

if ( time < player.flashEndTime )
player processChallenge( "ch_didyouseethat" );

if ( isDefined( player.finalKill ) )
player processChallenge( "ch_unbelievable" );

player processChallenge( "ch_carnie" );

if ( isDefined( data.victim.attackerData[player.guid].isPrimary ) )
player processChallenge( "ch_its_personal" );
}

baseWeapon = getBaseWeaponName( data.sWeapon );

if ( baseWeapon == "gl" )
{
weaponAttachments = getWeaponAttachments( data.sweapon );

if ( isDefined( level.challengeInfo["ch_" + weaponAttachments[0] + "_" + "gl"] ) )
player processChallenge( "ch_" + weaponAttachments[0] + "_" + "gl" );

if ( isDefined( level.challengeInfo["ch_marksman_" + weaponAttachments[0]] ) )
player processChallenge( "ch_marksman_" + weaponAttachments[0] );

if ( isDefined( level.challengeInfo["pr_marksman_" + weaponAttachments[0]] ) )
player processChallenge( "pr_marksman_" + weaponAttachments[0] );
}
}
else if ( data.sMeansOfDeath == "MOD_HEAD_SHOT" )
{
weaponClass = getWeaponClass( data.sWeapon );

ch_bulletDamageCommon( data, player, time, weaponClass );

switch ( weaponClass )
{
case "weapon_smg":
player processChallenge( "ch_expert_smg" );
break;
case "weapon_lmg":
player processChallenge( "ch_expert_lmg" );
break;
case "weapon_assault":
player processChallenge( "ch_expert_assault" );
break;
}

if ( isDefined( data.modifiers["revenge"] ) )
player processChallenge( "ch_colorofmoney" );

if ( isMG( data.sWeapon ) )
{
player MGKill();
}
else if ( isStrStart( data.sWeapon, "frag_" ) )
{
player processChallenge( "ch_thinkfast" );
}
else if ( isStrStart( data.sWeapon, "concussion_" ) )
{
player processChallenge( "ch_thinkfastconcussion" );
}
else if ( isStrStart( data.sWeapon, "flash_" ) )
{
player processChallenge( "ch_thinkfastflash" );
}
else
{
baseWeapon = getBaseWeaponName( data.sWeapon );

if ( isDefined( level.challengeInfo["ch_expert_" + baseWeapon] ) )
player processChallenge( "ch_expert_" + baseWeapon );

if ( isDefined( level.challengeInfo["pr_expert_" + baseWeapon] ) )
player processChallenge( "pr_expert_" + baseWeapon );

if ( isDefined( level.challengeInfo["ch_marksman_" + baseWeapon] ) )
player processChallenge( "ch_marksman_" + baseWeapon );

if ( isDefined( level.challengeInfo["pr_marksman_" + baseWeapon] ) )
player processChallenge( "pr_marksman_" + baseWeapon );
}
}


if ( data.sMeansOfDeath == "MOD_PISTOL_BULLET" || data.sMeansOfDeath == "MOD_RIFLE_BULLET" || data.sMeansOfDeath == "MOD_HEAD_SHOT" && !isKillstreakWeapon( data.sweapon ) )
{
// checks and processes all weapon attachment challenges
weaponAttachments = getWeaponAttachments( data.sweapon );
baseWeapon = getBaseWeaponName( data.sWeapon );

foreach( weaponAttachment in weaponAttachments )
{
switch ( weaponAttachment )
{
case "heartbeat":
player processChallenge( "ch_" + baseWeapon + "_" + weaponAttachment );
continue;
case "silencer":
player processChallenge( "ch_" + baseWeapon + "_" + weaponAttachment );
continue;
case "reflex":
if ( player playerAds() )
player processChallenge( "ch_" + baseWeapon + "_" + weaponAttachment );
continue;
case "acog":
if ( player playerAds() )
player processChallenge( "ch_" + baseWeapon + "_" + weaponAttachment );
continue;
case "rof":
player processChallenge( "ch_" + baseWeapon + "_" + weaponAttachment );
continue;
case "fmj":
if ( data.victim.iDFlags & level.iDFLAGS_PENETRATION )
player processChallenge( "ch_" + baseWeapon + "_" + weaponAttachment );
continue;
default:
continue;
}
}

if ( player _hasPerk( "specialty_bulletaccuracy" ) && !player playerAds() )
player processChallenge( "ch_bulletaccuracy_pro" );

if ( distanceSquared( player.origin, data.victim.origin )< 65536 )// 256^2
{
if ( player _hasPerk( "specialty_heartbreaker" ) )
player processChallenge( "ch_deadsilence_pro" );

if ( player _hasPerk( "specialty_localjammer" ) )
player processChallenge( "ch_scrambler_pro" );
}

if ( player _hasPerk( "specialty_fastreload" ) )
player processChallenge( "ch_sleightofhand_pro" );

if ( player _hasPerk( "specialty_bling" ) && weaponAttachments.size == 2 )
player processChallenge( "ch_bling_pro" );

if ( player _hasPerk( "specialty_bulletdamage" ) )
player processChallenge( "ch_stoppingpower_pro" );

if ( player _hasPerk( "specialty_pistoldeath" ) && isDefined(player.inLastStand) && player.inLastStand && !level.dieHardMode
&& ( !isDefined(player.inFinalStand) || !player.inFinalStand ) && ( !isDefined(player.inC4Death) || !player.inC4Death ) )
{
if ( isDefined( data.modifiers["revenge"] ) )
player processChallenge( "ch_robinhood" );

player processChallenge( "ch_laststand_pro" );
}
}

if ( player _hasperk( "specialty_onemanarmy" ) || isDefined( player.OMAClassChanged ) && player.OMAClassChanged )
player processChallenge( "ch_onemanarmy_pro" );

if ( isDefined( data.victim.isPlanting ) && data.victim.isPlanting )
player processChallenge( "ch_bombplanter" );

if ( isDefined( data.victim.isDefusing ) && data.victim.isDefusing )
player processChallenge( "ch_bombdefender" );

if ( isDefined( data.victim.isBombCarrier ) && data.victim.isBombCarrier && ( !isDefined( level.dd ) || !level.dd ) )
player processChallenge( "ch_bombdown" );

if ( isDefined( data.victim.wasTI ) && data.victim.wasTI )
player processChallenge( "ch_tacticaldeletion" );
}

ch_bulletDamageCommon( data, player, time, weaponClass )
{
if ( !isMG( data.sWeapon ) )
player endMGStreak();

if ( isKillstreakWeapon( data.sweapon ) )
return;

if ( player.pers["lastBulletKillTime"] == time )
player.pers["bulletStreak"]++;
else
player.pers["bulletStreak"] = 1;

player.pers["lastBulletKillTime"] = time;

if ( !data.victimOnGround )
player processChallenge( "ch_hardlanding" );

assert( data.attacker == player );
if ( !data.attackerOnGround )
player.pers["midairStreak"]++;

if ( player.pers["midairStreak"] == 2 )
player processChallenge( "ch_airborne" );

if ( time < data.victim.flashEndTime )
player processChallenge( "ch_flashbangvet" );

if ( time < player.flashEndTime )
player processChallenge( "ch_blindfire" );

if ( time < data.victim.concussionEndTime )
player processChallenge( "ch_concussionvet" );

if ( time < player.concussionEndTime )
player processChallenge( "ch_slowbutsure" );


if ( player.pers["bulletStreak"] == 2 )
{
if ( isDefined( data.modifiers["headshot"] ) )
{
foreach ( killData in player.killsThisLife )
{
if ( killData.time != time )
continue;

if ( !isDefined( data.modifiers["headshot"] ) )
continue;

player processChallenge( "ch_allpro" );
}
}

if ( weaponClass == "weapon_sniper" )
player processChallenge( "ch_collateraldamage" );
}

if ( weaponClass == "weapon_pistol" )
{
if ( isdefined( data.victim.attackerData ) && isdefined( data.victim.attackerData[player.guid] ) )
{
if ( isDefined ( data.victim.attackerData[player.guid].isPrimary ) )
player processChallenge( "ch_fastswap" );
}
}
else if ( weaponClass == "weapon_shotgun" )
{
if ( isSubStr( data.sWeapon, "ranger" ) && isDefined( player.bothBarrels ) )
{
player processChallenge( "ch_bothbarrels" );
player.bothBarrels = undefined;
}
}

if ( data.victim.iDFlagsTime == time )
{
if ( data.victim.iDFlags & level.iDFLAGS_PENETRATION )
player processChallenge( "ch_xrayvision" );
}

if ( data.attackerInLastStand && !data.attacker _hasPerk( "specialty_finalstand" ) )
{
player processChallenge( "ch_laststandvet" );
}
else if ( data.attackerStance == "crouch" )
{
player processChallenge( "ch_crouchshot" );
}
else if ( data.attackerStance == "prone" )
{
player processChallenge( "ch_proneshot" );
if ( weaponClass == "weapon_sniper" )
{
player processChallenge( "ch_invisible" );
}
}

if ( weaponClass == "weapon_sniper" )
{
if ( isDefined( data.modifiers["oneshotkill"] ) )
player processChallenge( "ch_ghillie" );
}

if ( isSubStr( data.sWeapon, "_silencer_" ) )
player processChallenge( "ch_stealth" );
}

ch_roundplayed( data )
{
player = data.player;

if ( player.wasAliveAtMatchStart )
{
deaths = player.pers[ "deaths" ];
kills = player.pers[ "kills" ];

kdratio = 1000000;
if ( deaths > 0 )
kdratio = kills / deaths;

if ( kdratio >= 5.0 && kills >= 5.0 )
{
player processChallenge( "ch_starplayer" );
}

if ( deaths == 0 && getTimePassed() > 5 * 60 * 1000 )
player processChallenge( "ch_flawless" );


if ( player.score > 0 )
{
switch ( level.gameType )
{
case "dm":
if ( data.place < 3 && level.placement["all"].size > 3 )
player processChallenge( "ch_victor_dm" );
break;
}
}
}
}


ch_roundwin( data )
{
if ( !data.winner )
return;

player = data.player;
if ( player.wasAliveAtMatchStart )
{
switch ( level.gameType )
{
case "war":
if ( level.hardcoreMode )
{
player processChallenge( "ch_teamplayer_hc" );
if ( data.place == 0 )
player processChallenge( "ch_mvp_thc" );
}
else
{
player processChallenge( "ch_teamplayer" );
if ( data.place == 0 )
player processChallenge( "ch_mvp_tdm" );
}
break;
case "sab":
player processChallenge( "ch_victor_sab" );
break;
case "sd":
player processChallenge( "ch_victor_sd" );
break;
case "ctf":
case "dom":
case "dm":
case "hc":
case "koth":
break;
default:
break;
}
}
}

/*
char *modNames[MOD_NUM] =
{
"MOD_PISTOL_BULLET",
"MOD_RIFLE_BULLET",
"MOD_GRENADE",
"MOD_GRENADE_SPLASH",
"MOD_PROJECTILE",
"MOD_PROJECTILE_SPLASH",
"MOD_MELEE",
"MOD_HEAD_SHOT",
"MOD_CRUSH",
"MOD_TELEFRAG",
"MOD_FALLING",
"MOD_SUICIDE",
"MOD_TRIGGER_HURT",
"MOD_EXPLOSIVE",

};

static const char *g_HitLocNames[] =
{
"head",
"neck",
"torso_upper",
"torso_lower",
"right_arm_upper",
"left_arm_upper",
"right_arm_lower",
"left_arm_lower",
"right_hand",
"left_hand",
"right_leg_upper",
"left_leg_upper",
"right_leg_lower",
"left_leg_lower",
"right_foot",
"left_foot",
"gun",
};

*/

// ==========================================
// Callback functions

playerDamaged( eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, sHitLoc )
{
self endon("disconnect");
if ( isdefined( attacker ) )
attacker endon("disconnect");

wait .05;
WaitTillSlowProcessAllowed();

data = spawnstruct();

data.victim = self;
data.eInflictor = eInflictor;
data.attacker = attacker;
data.iDamage = iDamage;
data.sMeansOfDeath = sMeansOfDeath;
data.sWeapon = sWeapon;
data.sHitLoc = sHitLoc;

data.victimOnGround = data.victim isOnGround();

if ( isPlayer( attacker ) )
{
data.attackerInLastStand = isDefined( data.attacker.lastStand );
data.attackerOnGround = data.attacker isOnGround();
data.attackerStance = data.attacker getStance();
}
else
{
data.attackerInLastStand = false;
data.attackerOnGround = false;
data.attackerStance = "stand";
}

doMissionCallback("playerDamaged", data);
}

playerKilled( eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, sPrimaryWeapon, sHitLoc, modifiers )
{
self.anglesOnDeath = self getPlayerAngles();
if ( isdefined( attacker ) )
attacker.anglesOnKill = attacker getPlayerAngles();

self endon("disconnect");

data = spawnstruct();

data.victim = self;
data.eInflictor = eInflictor;
data.attacker = attacker;
data.iDamage = iDamage;
data.sMeansOfDeath = sMeansOfDeath;
data.sWeapon = sWeapon;
data.sPrimaryWeapon = sPrimaryWeapon;
data.sHitLoc = sHitLoc;
data.time = gettime();
data.modifiers = modifiers;

data.victimOnGround = data.victim isOnGround();

if ( isPlayer( attacker ) )
{
data.attackerInLastStand = isDefined( data.attacker.lastStand );
data.attackerOnGround = data.attacker isOnGround();
data.attackerStance = data.attacker getStance();
}
else
{
data.attackerInLastStand = false;
data.attackerOnGround = false;
data.attackerStance = "stand";
}

waitAndProcessPlayerKilledCallback( data );

if ( isDefined( attacker ) && isReallyAlive( attacker ) )
attacker.killsThisLife[attacker.killsThisLife.size] = data;

data.attacker notify( "playerKilledChallengesProcessed" );
}


vehicleKilled( owner, vehicle, eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon )
{
data = spawnstruct();

data.vehicle = vehicle;
data.victim = owner;
data.eInflictor = eInflictor;
data.attacker = attacker;
data.iDamage = iDamage;
data.sMeansOfDeath = sMeansOfDeath;
data.sWeapon = sWeapon;
data.time = gettime();

}


waitAndProcessPlayerKilledCallback( data )
{
if ( isdefined( data.attacker ) )
data.attacker endon("disconnect");

self.processingKilledChallenges = true;
wait 0.05;
WaitTillSlowProcessAllowed();

doMissionCallback( "playerKilled", data );
self.processingKilledChallenges = undefined;
}

playerAssist()
{
data = spawnstruct();

data.player = self;

doMissionCallback( "playerAssist", data );
}


useHardpoint( hardpointType )
{
wait .05;
WaitTillSlowProcessAllowed();

data = spawnstruct();

data.player = self;
data.hardpointType = hardpointType;

doMissionCallback( "playerHardpoint", data );
}


roundBegin()
{
doMissionCallback( "roundBegin" );
}

roundEnd( winner )
{
data = spawnstruct();

if ( level.teamBased )
{
team = "allies";
for ( index = 0; index < level.placement[team].size; index++ )
{
data.player = level.placement[team][index];
data.winner = (team == winner);
data.place = index;

doMissionCallback( "roundEnd", data );
}
team = "axis";
for ( index = 0; index < level.placement[team].size; index++ )
{
data.player = level.placement[team][index];
data.winner = (team == winner);
data.place = index;

doMissionCallback( "roundEnd", data );
}
}
else
{
for ( index = 0; index < level.placement["all"].size; index++ )
{
data.player = level.placement["all"][index];
data.winner = (isdefined( winner) && (data.player == winner));
data.place = index;

doMissionCallback( "roundEnd", data );
}
}
}

doMissionCallback( callback, data )
{
if ( !mayProcessChallenges() )
return;

if ( getDvarInt( "disable_challenges" ) > 0 )
return;

if ( !isDefined( level.missionCallbacks[callback] ) )
return;

if ( isDefined( data ) )
{
for ( i = 0; i < level.missionCallbacks[callback].size; i++ )
thread [[level.missionCallbacks[callback][i]]]( data );
}
else
{
for ( i = 0; i < level.missionCallbacks[callback].size; i++ )
thread [[level.missionCallbacks[callback][i]]]();
}
}

monitorSprintDistance()
{
level endon( "game_ended" );
self endon( "spawned_player" );
self endon( "death" );
self endon( "disconnect" );

while(1)
{
self waittill("sprint_begin");

self.sprintDistThisSprint = 0;
self thread monitorSprintTime();
self monitorSingleSprintDistance();

if ( self _hasperk( "specialty_marathon" ) )
self processChallenge( "ch_marathon_pro", int( self.sprintDistThisSprint/12) );

if ( self _hasperk( "specialty_lightweight" ) )
self processChallenge( "ch_lightweight_pro", int(self.sprintDistThisSprint/12) );
}
}

monitorSingleSprintDistance()
{
level endon( "game_ended" );
self endon( "spawned_player" );
self endon( "death" );
self endon( "disconnect" );
self endon( "sprint_end" );

prevpos = self.origin;
while(1)
{
wait .1;

self.sprintDistThisSprint += distance( self.origin, prevpos );
prevpos = self.origin;
}
}

monitorSprintTime()
{
level endon( "game_ended" );
self endon( "spawned_player" );
self endon( "death" );
self endon( "disconnect" );

startTime = getTime();

self waittill( "sprint_end" );

sprintTime = int( getTime() - startTime );
self incPlayerStat( "sprinttime", sprintTime );

//total = self getPlayerStat( "sprinttime" );
//println( "SprintTime: ", sprintTime, " Total:", total );
}

monitorFallDistance()
{
self endon("disconnect");

self.pers["midairStreak"] = 0;

while(1)
{
if ( !isAlive( self ) )
{
self waittill("spawned_player");
continue;
}

if ( !self isOnGround() )
{
self.pers["midairStreak"] = 0;
highestPoint = self.origin[2];
while( !self isOnGround() && isAlive( self ) )
{
if ( self.origin[2] > highestPoint )
highestPoint = self.origin[2];
wait .05;
}
self.pers["midairStreak"] = 0;

falldist = highestPoint - self.origin[2];
if ( falldist < 0 )
falldist = 0;

if ( falldist / 12.0 > 15 && isAlive( self ) )
self processChallenge( "ch_basejump" );

if ( falldist / 12.0 > 30 && !isAlive( self ) )
self processChallenge( "ch_goodbye" );

//println( "You fell ", falldist / 12.0, " feet");
}
wait .05;
}
}


// TODO: Make this challenge happen after winning while being the last person on your team
lastManSD()
{
if ( !mayProcessChallenges() )
return;

if ( !self.wasAliveAtMatchStart )
return;

if ( self.teamkillsThisRound > 0 )
return;

self processChallenge( "ch_lastmanstanding" );
}


monitorBombUse()
{
self endon( "disconnect" );

for ( ;; )
{
result = self waittill_any_return( "bomb_planted", "bomb_defused" );

if ( !isDefined( result ) )
continue;

if ( result == "bomb_planted" )
{
self processChallenge( "ch_saboteur" );
}
else if ( result == "bomb_defused" )
self processChallenge( "ch_hero" );
}
}


monitorLiveTime()
{
for ( ;; )
{
self waittill ( "spawned_player" );

self thread survivalistChallenge();
}
}

survivalistChallenge()
{
self endon("death");
self endon("disconnect");

wait 5 * 60;

self processChallenge( "ch_survivalist" );
}


monitorStreaks()
{
self endon ( "disconnect" );

self.pers["airstrikeStreak"] = 0;
self.pers["meleeKillStreak"] = 0;
self.pers["shieldKillStreak"] = 0;

self thread monitorMisc();

for ( ;; )
{
self waittill ( "death" );

self.pers["airstrikeStreak"] = 0;
self.pers["meleeKillStreak"] = 0;
self.pers["shieldKillStreak"] = 0;
}
}


monitorMisc()
{
self thread monitorMiscSingle( "destroyed_explosive" );
self thread monitorMiscSingle( "begin_airstrike" );
self thread monitorMiscSingle( "destroyed_car" );
self thread monitorMiscSingle( "destroyed_helicopter" );
self thread monitorMiscSingle( "used_uav" );
self thread monitorMiscSingle( "used_counter_uav" );
self thread monitorMiscSingle( "used_airdrop" );
self thread monitorMiscSingle( "used_emp" );
self thread monitorMiscSingle( "used_nuke" );
self thread monitorMiscSingle( "crushed_enemy" );

self waittill("disconnect");

// make sure the threads end when we disconnect.
// (this allows one disconnect waittill instead of 4 disconnect endons)
self notify( "destroyed_explosive" );
self notify( "begin_airstrike" );
self notify( "destroyed_car" );
self notify( "destroyed_helicopter" );
}

monitorMiscSingle( waittillString )
{
// don't need to endon disconnect because we will get the notify we're waiting for when we disconnect.
// avoiding the endon disconnect saves a lot of script variables (5 * 4 threads * 64 players = 1280)

while(1)
{
self waittill( waittillString );

if ( !isDefined( self ) )
return;

monitorMiscCallback( waittillString );
}
}

monitorMiscCallback( result )
{
assert( isDefined( result ) );
switch( result )
{
case "begin_airstrike":
self.pers["airstrikeStreak"] = 0;
break;

case "destroyed_explosive":
if ( self _hasPerk( "specialty_detectexplosive" ) )
self processChallenge( "ch_detectexplosives_pro" );

self processChallenge( "ch_backdraft" );
break;

case "destroyed_helicopter":
self processChallenge( "ch_flyswatter" );
break;

case "destroyed_car":
self processChallenge( "ch_vandalism" );
break;

case "crushed_enemy":
self processChallenge( "ch_heads_up" );

if ( isDefined( self.finalKill ) )
self processChallenge( "ch_droppincrates" );
break;
}
}


healthRegenerated()
{
if ( !isalive( self ) )
return;

if ( !mayProcessChallenges() )
return;

if ( !self rankingEnabled() )
return;

self thread resetBrinkOfDeathKillStreakShortly();

if ( isdefined( self.lastDamageWasFromEnemy ) && self.lastDamageWasFromEnemy )
{
// TODO: this isn't always getting incremented when i regen
self.healthRegenerationStreak++;
if ( self.healthRegenerationStreak >= 5 )
{
self processChallenge( "ch_invincible" );
}
}
}

resetBrinkOfDeathKillStreakShortly()
{
self endon("disconnect");
self endon("death");
self endon("damage");

wait 1;

self.brinkOfDeathKillStreak = 0;
}

playerSpawned()
{
self.brinkOfDeathKillStreak = 0;
self.healthRegenerationStreak = 0;
self.pers["MGStreak"] = 0;
}

playerDied()
{
self.brinkOfDeathKillStreak = 0;
self.healthRegenerationStreak = 0;
self.pers["MGStreak"] = 0;
}

isAtBrinkOfDeath()
{
ratio = self.health / self.maxHealth;
return (ratio <= level.healthOverlayCutoff);
}


processChallenge( baseName, progressInc, forceSetProgress )
{
if ( !mayProcessChallenges() )
return;

if ( level.players.size < 2 )
return;

if ( !self rankingEnabled() )
return;

if ( !isDefined( progressInc ) )
progressInc = 1;

/#
if ( getDvarInt( "debug_challenges" ) )
println( "CHALLENGE PROGRESS - " + baseName + ": " + progressInc );
#/

missionStatus = getChallengeStatus( baseName );

if ( missionStatus == 0 )
return;

// challenge already completed
if ( missionStatus > level.challengeInfo[baseName]["targetval"].size )
return;

if ( isDefined( forceSetProgress ) && forceSetProgress )
{
progress = progressInc;
}
else
{
progress = ch_getProgress( baseName );
progress += progressInc;
}

// we've completed this tier
if ( progress >= level.challengeInfo[baseName]["targetval"][missionStatus] )
{
self ch_setProgress( baseName, level.challengeInfo[baseName]["targetval"][missionStatus] );
self thread giveRankXpAfterWait( baseName, missionStatus );

missionStatus++;
self ch_setState( baseName, missionStatus );
self.challengeData[baseName] = missionStatus;

self thread maps\mp\gametypes\_hud_message::challengeSplashNotify( baseName );

self thread masteryChallengeProcess( baseName, missionStatus );
}
else
{
self ch_setProgress( baseName, progress );
}
}

giveRankXpAfterWait( baseName,missionStatus )
{
self endon ( "disconnect" );

wait( 0.25 );
self maps\mp\gametypes\_rank::giveRankXP( "challenge", level.challengeInfo[baseName]["reward"][missionStatus] );
}


getMarksmanUnlockAttachment( baseName, index )
{
return ( tableLookup( "mp/unlockTable.csv", 0, baseName, 4 + index ) );
}


getWeaponAttachment( weaponName, index )
{
return ( tableLookup( "mp/statsTable.csv", 4, weaponName, 11 + index ) );
}


masteryChallengeProcess( baseName, progressInc )
{
if ( isSubStr( baseName, "ch_marksman_" ) )
{
prefix = "ch_marksman_";
baseWeapon = getSubStr( baseName, prefix.size, baseName.size );
}
else
{
tokens = strTok( baseName, "_" );

if ( tokens.size != 3 )
return;

baseWeapon = tokens[1];
}

if ( tableLookup( "mp/allChallengesTable.csv", 0 , "ch_" + baseWeapon + "_mastery", 1 ) == "" )
return;

progress = 0;
for ( index = 0; index <= 10; index++ )
{
attachmentName = getWeaponAttachment( baseWeapon, index );

if ( attachmentName == "" )
continue;

if ( self isItemUnlocked( baseWeapon + " " + attachmentName ) )
progress++;
}

processChallenge( "ch_" + baseWeapon + "_mastery", progress, true );
}


updateChallenges()
{
self.challengeData = [];

if ( !mayProcessChallenges() )
return;

if ( !self isItemUnlocked( "challenges" ) )
return false;

foreach ( challengeRef, challengeData in level.challengeInfo )
{
self.challengeData[challengeRef] = 0;

if ( !self isItemUnlocked( challengeRef ) )
continue;

if ( isDefined( challengeData["requirement"] ) && !self isItemUnlocked( challengeData["requirement"] ) )
continue;

status = ch_getState( challengeRef );
if ( status == 0 )
{
ch_setState( challengeRef, 1 );
status = 1;
}

self.challengeData[challengeRef] = status;
}
}

/*
challenge_targetVal and rewardVal should cast their return values to int
*/
challenge_targetVal( refString, tierId )
{
value = tableLookup( "mp/allChallengesTable.csv", CH_REF_COL, refString, CH_TARGET_COL + ((tierId-1)*2) );
return int( value );
}


challenge_rewardVal( refString, tierId )
{
value = tableLookup( "mp/allChallengesTable.csv", CH_REF_COL, refString, CH_REWARD_COL + ((tierId-1)*2) );
return int( value );
}


buildChallegeInfo()
{
level.challengeInfo = [];

tableName = "mp/allchallengesTable.csv";

totalRewardXP = 0;

refString = tableLookupByRow( tableName, 0, CH_REF_COL );
assertEx( isSubStr( refString, "ch_" ) || isSubStr( refString, "pr_" ), "Invalid challenge name: " + refString + " found in " + tableName );
for ( index = 1; refString != ""; index++ )
{
assertEx( isSubStr( refString, "ch_" ) || isSubStr( refString, "pr_" ), "Invalid challenge name: " + refString + " found in " + tableName );

level.challengeInfo[refString] = [];
level.challengeInfo[refString]["targetval"] = [];
level.challengeInfo[refString]["reward"] = [];

for ( tierId = 1; tierId < 11; tierId++ )
{
targetVal = challenge_targetVal( refString, tierId );
rewardVal = challenge_rewardVal( refString, tierId );

if ( targetVal == 0 )
break;

level.challengeInfo[refString]["targetval"][tierId] = targetVal;
level.challengeInfo[refString]["reward"][tierId] = rewardVal;

totalRewardXP += rewardVal;
}

assert( isDefined( level.challengeInfo[refString]["targetval"][1] ) );

refString = tableLookupByRow( tableName, index, CH_REF_COL );
}

tierTable = tableLookupByRow( "mp/challengeTable.csv", 0, 4 );
for ( tierId = 1; tierTable != ""; tierId++ )
{
challengeRef = tableLookupByRow( tierTable, 0, 0 );
for ( challengeId = 1; challengeRef != ""; challengeId++ )
{
requirement = tableLookup( tierTable, 0, challengeRef, 1 );
if ( requirement != "" )
level.challengeInfo[challengeRef]["requirement"] = requirement;

challengeRef = tableLookupByRow( tierTable, challengeId, 0 );
}

tierTable = tableLookupByRow( "mp/challengeTable.csv", tierId, 4 );
}

/#
printLn( "TOTAL CHALLENGE REWARD XP: " + totalRewardXP );
#/
}

/#
verifyMarksmanChallenges()
{
}

verifyExpertChallenges()
{
}
#/

/#
completeAllChallenges( percentage )
{
foreach ( challengeRef, challengeData in level.challengeInfo )
{
finalTarget = 0;
finalTier = 0;
for ( tierId = 1; isDefined( challengeData["targetval"][tierId] ); tierId++ )
{
finalTarget = challengeData["targetval"][tierId];
finalTier = tierId + 1;
}

if ( percentage != 1.0 )
{
finalTarget--;
finalTier--;
}

if ( self isItemUnlocked( challengeRef ) || percentage == 1.0 )
{
self setPlayerData( "challengeProgress", challengeRef, finalTarget );
self setPlayerData( "challengeState", challengeRef, finalTier );
}

wait ( 0.05 );
}

println( "Done unlocking challenges" );
}
#/

monitorProcessChallenge()
{
self endon( "disconnect" );
level endon( "game_end" );

for( ;; )
{
if( !mayProcessChallenges() )
return;

self waittill( "process", challengeName );
self processChallenge( challengeName );
}
}

monitorKillstreakProgress()
{
self endon( "disconnect" );
level endon( "game_end" );

for( ;; )
{
self waittill ( "got_killstreak", streakCount );

//for scr_givkillstreak
if( !isDefined( streakCount ) )
continue;

if ( streakCount == 10 && self.killstreaks.size == 0 )
self processChallenge( "ch_theloner" );
else if ( streakCount == 9 )
{
if ( isDefined( self.killstreaks[7] ) && isDefined( self.killstreaks[8] ) && isDefined( self.killstreaks[9] ) )
{
self processChallenge( "ch_6fears7" );
}
}
}
}


monitorKilledKillstreak()
{
self endon( "disconnect" );
level endon( "game_end" );

for( ;; )
{
self waittill( "destroyed_killstreak", weapon );

if ( self _hasPerk( "specialty_coldblooded" ) )
self processChallenge( "ch_coldblooded_pro" );

if ( isDefined( weapon ) && weapon == "stinger_mp" )
{
self processChallenge( "ch_marksman_stinger" );
self processChallenge( "pr_marksman_stinger" );
}
}
}


genericChallenge( challengeType, value )
{
switch ( challengeType )
{
case "hijacker_airdrop":
self processChallenge( "ch_smoothcriminal" );
break;
case "hijacker_airdrop_mega":
self processChallenge( "ch_poolshark" );
break;
case "wargasm":
self processChallenge( "ch_wargasm" );
break;
case "weapon_assault":
self processChallenge( "ch_surgical_assault" );
break;
case "weapon_smg":
self processChallenge( "ch_surgical_smg" );
break;
case "weapon_lmg":
self processChallenge( "ch_surgical_lmg" );
break;
case "weapon_sniper":
self processChallenge( "ch_surgical_sniper" );
break;
case "shield_damage":
self processChallenge( "ch_shield_damage", value );
break;
case "shield_bullet_hits":
self processChallenge( "ch_shield_bullet", value );
break;
case "shield_explosive_hits":
self processChallenge( "ch_shield_explosive", value );
break;
}
}

playerHasAmmo()
{
primaryWeapons = self getWeaponsListPrimaries();

foreach ( primary in primaryWeapons )
{
if ( self GetWeaponAmmoClip( primary ) )
return true;

altWeapon = weaponAltWeaponName( primary );

if ( !isDefined( altWeapon ) || (altWeapon == "none") )
continue;

if ( self GetWeaponAmmoClip( altWeapon ) )
return true;
}

return false;
}
(adsbygoogle = window.adsbygoogle || []).push({});
03-13-2011, 02:40 PM #65
TheJaRniBoi
Why So Serious?
Originally posted by yukuku View Post
delete the patch_mp.ff and see if it works


i don't have a PS3 anymore, i sold it about 3 weeks ago
03-13-2011, 02:46 PM #66
Okami
Known As Yukuku
Originally posted by CODGlitcha
i don't have a PS3 anymore, i sold it about 3 weeks ago


thats sucks why you sell
03-13-2011, 02:49 PM #67
TheJaRniBoi
Why So Serious?
Originally posted by yukuku View Post
thats sucks why you sell


i got bored of PS3 not many good games. Probably buy an XBOX 360 soon.
03-13-2011, 03:43 PM #68
Okami
Known As Yukuku
Originally posted by CODGlitcha
i got bored of PS3 not many good games. Probably buy an XBOX 360 soon.


lol i see well hope we get cl again
03-13-2011, 06:06 PM #69
Blackstorm
Veni. Vidi. Vici.
Originally posted by ..V.. View Post
Its not as wrong as it seems. Think about it logically..

If you modify or change anything in the gsc files it doesn't work BUT

The glitches remain patched..

This happens if you are offline in splitscreen, even on a 3.41 jb which isn't connected to the internet.. so its not a server check.

This can only mean that there is a copy of all or parts of the gsc files in the default_mp or common_mp...Its not just a md5 or checksum, if that was the case, the glitches would still work when it bypassed the patch.ff..

look at this

combathigh_overlay..............................semtex_mp...............throwingknife_mp........specialty_tacticalinsertion.....................specialty_blastshield...........................c4_mp.......enemy.......specialty_marathon......MPUI_CHANGING_KIT...............................friendly........................................specialty_fastreload............................specialty_scavenger.............................mil_emergency_flare_mp..........................specialty_bulletdamage..........................specialty_lightweight...........................specialty_coldblooded...........................specialty_explosivedamage.......................misc/flare_ambient..............................specialty_extendedmelee.........................specialty_bulletaccuracy........................specialty_localjammer...........................specialty_heartbreaker..........................specialty_detectexplosive.......................misc/flare_ambient_green........................specialty_combathigh............................specialty_grenadepulldeath..............................................props/barrelexp.....................................................................................................!...explosions/oxygen_tank_explosion........................................MP_DESTROY_TI...........ricochet........................................impacts/large_metalhit_1....

Its from the debug default_mp.self.. They have put the gsc's in there, why do you think the new default_mp so big?

Now, quite why they have still put them all in the patch.ff as well is a mystery... maybe it runs better from the patch.ff and running its back up is a secondary option to nullify hacks. Or maybe they did just do it for a laugh to fool us !

Your only chance is to find the part of the default_mp that lets you connect to the 1.12 server and swap it with a 1.11 default_mp.. but until we can decrypt a .self that is not very likely..

You see, IW aren't as stupid as people seem to think Smile


Wow, you're very smart Claps

BUT the game does run all of it's GSC's from the patch_mp.ff in the USRDIR folder. They would think we're 'slightly' modifying the GSC's, not using file manipulation via renaming them. So when we rename them, it obviously doesn't find that file, so, it goes to the ondisc GSC. Then that ondisc GSC doesn't match the checksum so it goes to the new GSC. But it does still run all GSC's no matter what. It's running your modded patch, but, its using the default_mp.self GSC's to run as a primary, so automatically in the game if there's two GSC's running it cancels the patch_mp.ff GSC and switches to that primary GSC. So I was thinking since the default_mp.self is made to run the GSC's on dedicated offsets.. I think we could trick the self file =D

I'll PM you about it. :P
03-13-2011, 09:17 PM #70
BuC-ShoTz
TeamMvKâ?¢
here is every vision file or most of them

You must login or register to view this content.

The following user thanked BuC-ShoTz for this useful post:

emsp
03-13-2011, 10:37 PM #71
anddrew
League Champion
we need to decrypt and encrypt .selfs then we'll be in business :P
03-13-2011, 11:13 PM #72
Originally posted by ShoTz View Post
here is every vision file or most of them

You must login or register to view this content.


I did wonder if you could put stuff in the visions or even basemaps.arena and load the mods with the map before the patch knows anything is going on...
But im away now for 2 weeks and have run out of time to try anything :(
03-13-2011, 11:20 PM #73
anddrew
League Champion
Originally posted by ..V.. View Post
I did wonder if you could put stuff in the visions or even basemaps.arena and load the mods with the map before the patch knows anything is going on...
But im away now for 2 weeks and have run out of time to try anything


Lucky! Have fun <3

I got another idea: the .self patched all the glitchs, and if any gscs are differant in the patch_mp.ff then it uses the patch on the disk or somewhere else. Thats how glitches are patched.

Copyright © 2026, NextGenUpdate.
All Rights Reserved.

Gray NextGenUpdate Logo