#using scripts\codescripts\struct; #using scripts\shared\callbacks_shared; #using scripts\shared\challenges_shared; #using scripts\shared\drown; #using scripts\shared\system_shared; #using scripts\shared\util_shared; #using scripts\shared\weapons\_weapon_utils; #using scripts\mp\gametypes\_loadout; #using scripts\mp\_util; #using scripts\mp\killstreaks\_counteruav; #using scripts\mp\killstreaks\_emp; #using scripts\mp\killstreaks\_killstreaks; #using scripts\mp\killstreaks\_satellite; #using scripts\mp\killstreaks\_uav; #namespace challenges; function autoexec __init__sytem__() { system::register("challenges",&__init__,undefined,undefined); } function __init__() { callback::on_start_gametype( &start_gametype ); callback::on_spawned( &on_player_spawn ); level.heroAbilityActivateNearDeath = &heroAbilityActivateNearDeath; level.callbackEndHeroSpecialistEMP = &callbackEndHeroSpecialistEMP; level.capturedObjectiveFunction = &capturedObjectiveFunction; } function start_gametype() { if ( !isdefined( level.ChallengesCallbacks ) ) { level.ChallengesCallbacks = []; } waittillframeend; if ( isdefined ( level.scoreEventGameEndCallback ) ) { challenges::registerChallengesCallback( "gameEnd",level.scoreEventGameEndCallback ); } if ( canProcessChallenges() ) { challenges::registerChallengesCallback( "playerKilled",&challengeKills ); challenges::registerChallengesCallback( "gameEnd",&challengeGameEndMP ); } callback::on_connect( &on_player_connect ); } function on_player_connect() { initChallengeData(); self addSpecialistUsedStatOnConnect(); self thread spawnWatcher(); self thread monitorReloads(); self thread monitorGrenadeFire(); } function initChallengeData() { self.pers["bulletStreak"] = 0; self.pers["lastBulletKillTime"] = 0; self.pers["stickExplosiveKill"] = 0; self.pers["carepackagesCalled"] = 0; self.pers["challenge_destroyed_air"] = 0; self.pers["challenge_destroyed_ground"] = 0; self.pers["challenge_anteup_earn"] = 0; self.pers["specialistStatAbilityUsage"] = 0; self.pers["canSetSpecialistStat"] = self isSpecialistUnlocked(); self.pers["activeKillstreaks"] = []; } function addSpecialistUsedStatOnConnect() { if ( !isdefined(self.pers["challenge_heroweaponkills"]) ) { // intentionally using "used" hero weapon on connect to determine frequency of specialist usage // which is the sum of "specialist ability" usage and "specialist weapon" usage. heroWeaponName = self GetLoadoutItemRef( 0, "heroWeapon" ); heroWeapon = GetWeapon( heroWeaponName ); if ( heroWeapon == level.weaponNone ) { heroAbilityName = self GetHeroAbilityName(); heroWeapon = GetWeapon( heroAbilityName ); } if ( heroWeapon != level.weaponNone ) { self addweaponstat( heroWeapon, "used", 1 ); } self.pers["challenge_heroweaponkills"] = 0; } } function spawnWatcher() { self endon( "disconnect" ); self.pers["killNemesis"] = 0; self.pers["killsFastMagExt"] = 0; self.pers["longshotsPerLife"] = 0; self.pers["specialistStatAbilityUsage"] = 0; self.challenge_defenderkillcount = 0; self.challenge_offenderkillcount = 0; self.challenge_offenderProjectileMultiKillcount = 0; self.challenge_offenderComlinkKillcount = 0; self.challenge_offenderSentryTurretKillCount = 0; self.challenge_objectiveDefensiveKillcount = 0; self.challenge_objectiveOffensiveKillcount = 0; self.challenge_scavengedCount = 0; self.challenge_resuppliedNameKills = 0; self.challenge_objectiveDefensive = undefined; self.challenge_objectiveOffensive = undefined; self.challenge_lastsurvivewithflakfrom = undefined; self.explosiveInfo = []; for(;;) { self waittill("spawned_player"); self.weaponKillsThisSpawn = []; self.attachmentKillsThisSpawn = []; self.challenge_hatchetTossCount = 0; self.challenge_hatchetkills = 0; self.retreivedBlades = 0; self.challenge_combatRobotAttackClientID = []; self thread watchDoubleJump(); self thread watchJump(); self thread watchSwimming(); self thread watchWallrun(); self thread watchSlide(); self thread watchSprint(); self thread watchScavengeLethal(); self thread watchWallRunTwoOppositeWallsNoGround(); self thread watchWeaponChangeComplete(); } } function watchScavengeLethal() { self endon( "death" ); self endon( "disconnect" ); self.challenge_scavengedCount = 0; for(;;) { self waittill( "scavenged_primary_grenade" ); self.challenge_scavengedCount++; } } function watchDoublejump() { self endon( "death" ); self endon( "disconnect" ); self.challenge_doublejump_begin = 0; self.challenge_doublejump_end = 0; for(;;) { ret = util::waittill_any_return( "doublejump_begin", "doublejump_end", "disconnect" ); switch( ret ) { case "doublejump_begin": self.challenge_doublejump_begin = gettime(); break; case "doublejump_end": self.challenge_doublejump_end = gettime(); break; } } } function watchJump() { self endon( "death" ); self endon( "disconnect" ); self.challenge_jump_begin = 0; self.challenge_jump_end = 0; for(;;) { ret = util::waittill_any_return( "jump_begin", "jump_end", "disconnect" ); switch( ret ) { case "jump_begin": self.challenge_jump_begin = gettime(); break; case "jump_end": self.challenge_jump_end = gettime(); break; } } } function watchSwimming() { self endon( "death" ); self endon( "disconnect" ); self.challenge_swimming_begin = 0; self.challenge_swimming_end = 0; for(;;) { ret = util::waittill_any_return( "swimming_begin", "swimming_end", "disconnect" ); switch( ret ) { case "swimming_begin": self.challenge_swimming_begin = gettime(); break; case "swimming_end": self.challenge_swimming_end = gettime(); break; } } } function watchWallrun() { self endon( "death" ); self endon( "disconnect" ); self.challenge_wallrun_begin = 0; self.challenge_wallrun_end = 0; for(;;) { ret = util::waittill_any_return( "wallrun_begin", "wallrun_end", "disconnect" ); switch( ret ) { case "wallrun_begin": self.challenge_wallrun_begin = gettime(); break; case "wallrun_end": self.challenge_wallrun_end = gettime(); break; } } } function watchSlide() { self endon( "death" ); self endon( "disconnect" ); self.challenge_slide_begin = 0; self.challenge_slide_end = 0; for(;;) { ret = util::waittill_any_return( "slide_begin", "slide_end", "disconnect" ); switch( ret ) { case "slide_begin": self.challenge_slide_begin = gettime(); break; case "slide_end": self.challenge_slide_end = gettime(); break; } } } function watchSprint() { self endon( "death" ); self endon( "disconnect" ); self.challenge_sprint_begin = 0; self.challenge_sprint_end = 0; for(;;) { ret = util::waittill_any_return( "sprint_begin", "sprint_end", "disconnect" ); switch( ret ) { case "sprint_begin": self.challenge_sprint_begin = gettime(); break; case "sprint_end": self.challenge_sprint_end = gettime(); break; } } } function challengeKills( data ) { victim = data.victim; attacker = data.attacker; time = data.time; level.numKills++; attacker.lastKilledPlayer = victim; attackerDoubleJumping = data.attackerDoubleJumping; attackerflashbackTime = data.attackerflashbackTime; attackerHeroAbility = data.attackerHeroAbility; attackerHeroAbilityActive = data.attackerHeroAbilityActive; attackerSliding = data.attackerSliding; attackerSpeedburst = data.attackerSpeedburst; attackerTraversing = data.attackerTraversing; attackerVisionPulseActivateTime = data.attackerVisionPulseActivateTime; attackerVisionPulseArray = data.attackerVisionPulseArray; attackerVisionPulseOrigin = data.attackerVisionPulseOrigin; attackerVisionPulseOriginArray = data.attackerVisionPulseOriginArray; attackerWallRunning = data.attackerWallRunning; attackerWasConcussed = data.attackerWasConcussed; attackerWasFlashed = data.attackerWasFlashed; attackerWasHeatWaveStunned = data.attackerWasHeatWaveStunned; attackerWasOnGround = data.attackerOnGround; attackerWasUnderwater = data.attackerWasUnderwater; attackerLastFastReloadTime = data.attackerLastFastReloadTime; lastWeaponBeforeToss = data.lastWeaponBeforeToss; meansOfDeath = data.sMeansOfDeath; ownerWeaponAtLaunch = data.ownerWeaponAtLaunch; victimBedOut = data.bledOut; victimOrigin = data.victimOrigin; victimCombatEfficiencyLastOnTime = data.victimCombatEfficiencyLastOnTime; victimCombatEfficieny = data.victimCombatEfficieny; victimElectrifiedBy = data.victimElectrifiedBy; victimflashbackTime = data.victimflashbackTime; victimHeroAbility = data.victimHeroAbility; victimHeroAbilityActive = data.victimHeroAbilityActive; victimSpeedburst = data.victimSpeedburst; victimSpeedburstLastOnTime = data.victimSpeedburstLastOnTime; victimVisionPulseActivateTime = data.victimVisionPulseActivateTime; victimVisionPulseActivateTime = data.victimVisionPulseActivateTime; victimVisionPulseArray = data.victimVisionPulseArray; victimVisionPulseOrigin = data.victimVisionPulseOrigin; victimVisionPulseOriginArray = data.victimVisionPulseOriginArray; victimAttackersThisSpawn = data.victimAttackersThisSpawn; victimWasDoubleJumping = data.victimWasDoubleJumping; victimWasInSlamState = data.victimWasInSlamState; victimWasLungingWithArmBlades = data.victimWasLungingWithArmBlades; victimWasOnGround = data.victimOnGround; victimWasUnderwater = data.wasUnderwater; victimWasWallRunning = data.victimWasWallRunning; victimLastStunnedBy = data.victimLastStunnedBy; victimActiveProximityGrenades = data.victim.activeProximityGrenades; victimActiveBouncingBetties = data.victim.activeBouncingBetties; attackerLastFlashedBy = data.attackerLastFlashedBy; attackerLastStunnedBy = data.attackerLastStunnedBy; attackerLastStunnedTime = data.attackerLastStunnedTime; attackerWasSliding = data.attackerWasSliding; attackerWasSprinting = data.attackerWasSprinting; wasDefusing = data.wasDefusing; wasPlanting = data.wasPlanting; inflictorOwnerWasSprinting = data.inflictorOwnerWasSprinting; player = data.attacker; playerOrigin = data.attackerOrigin; weapon = data.weapon; victim_doublejump_begin = data.victim_doublejump_begin; victim_doublejump_end = data.victim_doublejump_end; victim_jump_begin = data.victim_jump_begin; victim_jump_end = data.victim_jump_end; victim_swimming_begin = data.victim_swimming_begin; victim_swimming_end = data.victim_swimming_end; victim_slide_begin = data.victim_slide_begin; victim_slide_end = data.victim_slide_end; victim_wallrun_begin = data.victim_wallrun_begin; victim_wallrun_end = data.victim_wallrun_end; victim_was_drowning = data.victim_was_drowning; attacker_doublejump_begin = data.attacker_doublejump_begin; attacker_doublejump_end = data.attacker_doublejump_end; attacker_jump_begin = data.attacker_jump_begin; attacker_jump_end = data.attacker_jump_end; attacker_swimming_begin = data.attacker_swimming_begin; attacker_swimming_end = data.attacker_swimming_end; attacker_slide_begin = data.attacker_slide_begin; attacker_slide_end = data.attacker_slide_end; attacker_wallrun_begin = data.attacker_wallrun_begin; attacker_wallrun_end = data.attacker_wallrun_end; attacker_was_drowning = data.attacker_was_drowning; attacker_sprint_end = data.attacker_sprint_end; attacker_sprint_begin = data.attacker_sprint_begin; attacker_wallRanTwoOppositeWallsNoGround = data.attacker_wallRanTwoOppositeWallsNoGround; inflictorIsCooked = data.inflictorIsCooked; inflictorChallenge_hatchetTossCount = data.inflictorChallenge_hatchetTossCount; inflictorOwnerWasSprinting = data.inflictorOwnerWasSprinting; inflictorPlayerHasEngineerPerk = data.inflictorPlayerHasEngineerPerk; inflictor = data.eInflictor; // MAY ALREADY BE REMOVED if ( !isdefined( data.weapon ) ) { return; } if ( !isdefined( player ) || !isplayer( player ) || ( weapon == level.weaponNone ) ) { return; } // getting the altweapon name is not ideal, but acceptable for BO3's current weapons in MP; // TODO: add code-based accessor to parentWeaponName ("Stat Name" in APE) weaponClass = util::getWeaponClass( weapon ); baseWeapon = getBaseWeapon( weapon ); baseWeaponItemIndex = GetBaseWeaponItemIndex( baseWeapon ); weaponPurchased = player isItemPurchased( baseWeaponItemIndex ); victimSupportIndex = victim.team; playerSupportIndex = player.team; if ( !level.teambased ) { playerSupportIndex = player.entnum; victimSupportIndex = victim.entnum; } if ( meansOfDeath == "MOD_HEAD_SHOT" || meansOfDeath == "MOD_PISTOL_BULLET" || meansOfDeath == "MOD_RIFLE_BULLET" ) { bulletKill = true; } else { bulletKill = false; } if ( level.teambased ) { if ( player.team == victim.team ) { return; } } else { if ( player == victim ) { return; } } killstreak = killstreaks::get_from_weapon( data.weapon ); if ( !isdefined( killstreak ) ) { player processSpecialistChallenge( "kills" ); if ( weapon.isheroWeapon == true ) { player processSpecialistChallenge( "kills_weapon" ); player.heroWeaponKillsThisActivation++; player.pers["challenge_heroweaponkills"]++; if ( player.pers["challenge_heroweaponkills"] >= 6 ) { player processSpecialistChallenge( "kill_one_game_weapon" ); player.pers["challenge_heroweaponkills"] = 0; } } } if ( bulletKill ) { if ( weaponPurchased ) { if ( weaponclass == "weapon_sniper" ) { if ( isdefined ( victim.firstTimeDamaged ) && victim.firstTimeDamaged == time ) { player AddPlayerStat( "kill_enemy_one_bullet_sniper", 1 ); player AddWeaponStat( weapon, "kill_enemy_one_bullet_sniper", 1 ); } } else if ( weaponclass == "weapon_cqb" ) { if ( isdefined ( victim.firstTimeDamaged ) && victim.firstTimeDamaged == time ) { player AddPlayerStat( "kill_enemy_one_bullet_shotgun", 1 ); player AddWeaponStat( weapon, "kill_enemy_one_bullet_shotgun", 1 ); } } } if ( GetDvarInt( "ui_enablePromoTracking", 0 ) && meansOfDeath == "MOD_HEAD_SHOT" ) { util::increment_zmhd_thermometer( 1 ); } if ( ( time - data.attacker_swimming_end <= 2000 ) && ( time - data.attacker_doublejump_begin <= 2000 ) ) { player AddPlayerStat( "kill_after_doublejump_out_of_water", 1 ); } if ( attackerWasSliding ) { if ( attacker_doublejump_end == attacker_slide_begin ) { player AddPlayerStat( "kill_while_sliding_from_doublejump", 1 ); } } if ( ( player IsBonusCardActive( 2, player.class_num ) ) && player IsItemPurchased( GetItemIndexFromRef( "bonuscard_primary_gunfighter_3" ) ) ) { if ( isdefined( weapon.attachments ) && weapon.attachments.size == 6 ) { player AddPlayerStat( "kill_with_gunfighter", 1 ); } } //Check for the killstreak 5 challenge completion checkkillstreak5( baseWeapon, player ); if ( weapon.isDualWield && weaponPurchased ) { checkDualWield( baseWeapon, player, attacker, time, attackerwassprinting, attacker_sprint_end ); } if ( isdefined( weapon.attachments ) && weapon.attachments.size > 0 ) { attachmentName = player GetWeaponOptic( weapon ); if ( isdefined( attachmentName ) && attachmentName != "" && player WeaponHasAttachmentAndUnlocked( weapon, attachmentName ) ) { if ( weapon.attachments.size > 5 && player AllWeaponAttachmentsUnlocked( weapon ) && !isdefined( attacker.tookWeaponFrom[ weapon ] ) ) { player AddPlayerStat( "kill_optic_5_attachments", 1 ); } if ( isdefined( player.attachmentKillsThisSpawn[ attachmentName ] ) ) { player.attachmentKillsThisSpawn[ attachmentName ]++; if ( player.attachmentKillsThisSpawn[ attachmentName ] == 5 ) { player AddWeaponStat( weapon, "killstreak_5_attachment", 1 ); } } else { player.attachmentKillsThisSpawn[ attachmentName ] = 1; } if ( weapon_utils::isPistol( weapon.rootweapon ) ) { if ( player weaponHasAttachmentAndUnlocked( weapon, "suppressed", "extbarrel" ) ) { player AddPlayerStat( "kills_pistol_lasersight_suppressor_longbarrel", 1 ); } } } if ( player weaponHasAttachmentAndUnlocked( weapon, "suppressed" ) ) { if ( attacker util::has_hard_wired_perk_purchased_and_equipped() // hardwired && attacker util::has_ghost_perk_purchased_and_equipped() // ghost && attacker util::has_jetquiet_perk_purchased_and_equipped() ) // blast suppressor { player AddPlayerStat( "kills_suppressor_ghost_hardwired_blastsuppressor", 1 ); } } if ( player PlayerAds() == 1 ) { if ( isdefined( player.smokeGrenadeTime ) && isdefined( player.smokeGrenadePosition ) ) { if ( player.smokeGrenadeTime + 14000 > time ) { if ( player util::is_looking_at( player.smokeGrenadePosition ) || ( distancesquared( player.origin, player.smokeGrenadePosition ) < 200 * 200 )) { if ( player weaponHasAttachmentAndUnlocked( weapon, "ir" ) ) { player AddPlayerStat( "kill_with_thermal_and_smoke_ads", 1 ); player AddWeaponStat( weapon, "kill_thermal_through_smoke", 1 ); } } } } } if ( weapon.attachments.size > 1 ) { if ( player PlayerAds() == 1 ) { if ( player weaponHasAttachmentAndUnlocked( weapon, "grip", "quickdraw" ) ) { player AddPlayerStat( "kills_ads_quickdraw_and_grip", 1 ); } if ( player weaponHasAttachmentAndUnlocked( weapon, "swayreduc", "stalker" ) ) { player AddPlayerStat( "kills_ads_stock_and_cpu", 1 ); } } else { if ( player weaponHasAttachmentAndUnlocked( weapon, "rf", "steadyaim" ) ) { if ( attacker util::has_fast_hands_perk_purchased_and_equipped() ) { player AddPlayerStat( "kills_hipfire_rapidfire_lasersights_fasthands", 1 ); } } } if ( player weaponHasAttachmentAndUnlocked( weapon, "fastreload", "extclip" ) ) { player.pers["killsFastMagExt"]++; if ( player.pers["killsFastMagExt"] > 4 ) { player AddPlayerStat( "kills_one_life_fastmags_and_extclip", 1 ); player.pers["killsFastMagExt"] = 0; } } } if ( weapon.attachments.size > 2 ) { if ( meansOfDeath == "MOD_HEAD_SHOT" ) { if ( player weaponHasAttachmentAndUnlocked( weapon, "fmj", "damage", "extbarrel" ) ) { player AddPlayerStat( "headshot_fmj_highcaliber_longbarrel", 1 ); } } } if ( weapon.attachments.size > 4 ) { if ( player weaponHasAttachmentAndUnlocked( weapon, "extclip", "grip", "fastreload", "quickdraw", "stalker" ) ) { player AddPlayerStat( "kills_extclip_grip_fastmag_quickdraw_stock", 1 ); } } } if ( victim_was_drowning && attacker_was_drowning ) { player AddPlayerStat( "dr_lung", 1 ); } if ( isdefined( attackerLastFastReloadTime ) && ( time - attackerLastFastReloadTime <= 5000 ) && player WeaponHasAttachmentAndUnlocked( weapon, "fastreload" ) ) { player AddPlayerStat( "kills_after_reload_fastreload", 1 ); } if ( victim.iDFlagsTime == time ) { if ( victim.iDFlags & 8 ) { player AddPlayerStat( "kill_enemy_through_wall", 1 ); if ( player weaponHasAttachmentAndUnlocked( weapon, "fmj" ) ) { player AddPlayerStat( "kill_enemy_through_wall_with_fmj", 1 ); } } } if ( attacker_wallRanTwoOppositeWallsNoGround === true ) { player AddPlayerStat( "kill_while_wallrunning_2_walls", 1 ); } // end if ( bulletkill ) } else if ( weapon_utils::isMeleeMOD( meansOfDeath ) && !isdefined( killstreak ) ) { player AddPlayerStat( "melee", 1 ); if ( weapon_utils::isPunch( weapon ) ) { player AddPlayerStat( "kill_enemy_with_fists", 1 ); } //Check for the killstreak 5 challenge completion checkkillstreak5( baseWeapon, player ); } else { if ( weaponPurchased ) { if ( weapon == player.grenadeTypePrimary ) { if ( player.challenge_scavengedCount > 0 ) { player.challenge_resuppliedNameKills++; if ( player.challenge_resuppliedNameKills >= 3 ) { player AddPlayerStat( "kills_3_resupplied_nade_one_life", 1 ); player.challenge_resuppliedNameKills = 0; } player.challenge_scavengedCount--; } } if ( isdefined( inflictorIsCooked ) ) { if ( inflictorIsCooked == true && weapon.rootweapon.name != "hatchet" ) { player AddPlayerStat( "kill_with_cooked_grenade", 1 ); } } if ( victimLastStunnedBy === player ) { if ( weaponclass == "weapon_grenade" ) { player AddPlayerStat( "kill_stun_lethal", 1 ); } } if ( baseWeapon == level.weaponSpecialCrossbow ) { if ( weapon.isDualWield ) // determined purchased { checkDualWield( baseWeapon, player, attacker, time, attackerwassprinting, attacker_sprint_end ); } } // for "energy" shotgun if ( baseWeapon == level.weaponShotgunEnergy ) { if ( isdefined ( victim.firstTimeDamaged ) && victim.firstTimeDamaged == time ) { player AddPlayerStat( "kill_enemy_one_bullet_shotgun", 1 ); player AddWeaponStat( weapon, "kill_enemy_one_bullet_shotgun", 1 ); } } } if ( baseWeapon.forceDamageHitLocation || baseWeapon == level.weaponSpecialCrossbow || baseWeapon == level.weaponShotgunEnergy || baseWeapon == level.weaponSpecialDiscGun || baseWeapon == level.weaponBallisticKnife || baseWeapon == level.weaponLauncherEx41 ) { //Check for the killstreak 5 challenge completion checkkillstreak5( baseWeapon, player ); } } if ( isdefined( attacker.tookWeaponFrom[ weapon ] ) && isdefined( attacker.tookWeaponFrom[ weapon ].previousOwner ) ) { if ( !isdefined( attacker.tookWeaponFrom[ weapon ].previousOwner.team ) || attacker.tookWeaponFrom[ weapon ].previousOwner.team != player.team ) { player AddPlayerStat( "kill_with_pickup", 1 ); } } awarded_kill_enemy_that_blinded_you = false; playerHasTacticalMask = loadout::hasTacticalMask( player ); if ( attackerWasFlashed ) { if ( attackerLastFlashedBy === victim && !playerHasTacticalMask ) { player AddPlayerStat( "kill_enemy_that_blinded_you", 1 ); awarded_kill_enemy_that_blinded_you = true; } } if ( !awarded_kill_enemy_that_blinded_you && isdefined( attackerLastStunnedTime ) && attackerLastStunnedTime + 5000 > time ) { if ( attackerLastStunnedBy === victim && !playerHasTacticalMask ) { player AddPlayerStat( "kill_enemy_that_blinded_you", 1 ); awarded_kill_enemy_that_blinded_you = true; } } killedStunnedVictim = false; if ( isdefined( victim.lastConcussedBy ) && victim.lastConcussedBy == attacker ) { if ( victim.concussionEndTime > time ) { if ( player util::is_item_purchased( "concussion_grenade" ) ) { player AddPlayerStat( "kill_concussed_enemy", 1 ); } killedStunnedVictim = true; player AddWeaponStat( GetWeapon( "concussion_grenade" ), "CombatRecordStat", 1 ); } } if ( isdefined( victim.lastShockedBy ) && victim.lastShockedBy == attacker ) { if ( victim.shockEndTime > time ) { if ( player util::is_item_purchased( "proximity_grenade" ) ) { player AddPlayerStat( "kill_shocked_enemy", 1 ); } player AddWeaponStat( GetWeapon( "proximity_grenade" ), "CombatRecordStat", 1 ); killedStunnedVictim = true; if ( weapon.rootweapon.name == "bouncingbetty" ) { player AddPlayerStat( "kill_trip_mine_shocked", 1 ); } } } if ( victim util::isFlashbanged() ) { if ( isdefined( victim.lastFlashedBy ) && victim.lastFlashedBy == player ) { killedStunnedVictim = true; if ( player util::is_item_purchased( "flash_grenade" ) ) { player AddPlayerStat( "kill_flashed_enemy", 1 ); } player AddWeaponStat( GetWeapon( "flash_grenade" ), "CombatRecordStat", 1 ); } } if ( level.teamBased ) { if ( ( !isDefined( player.pers["kill_every_enemy_with_specialist"] ) ) && ( level.playerCount[victim.pers["team"]] > 3 && player.pers["killed_players_with_specialist"].size >= level.playerCount[victim.pers["team"]] ) ) { player AddPlayerStat( "kill_every_enemy", 1 ); player.pers["kill_every_enemy_with_specialist"] = true; } if ( isdefined( victimAttackersThisSpawn ) && IsArray( victimAttackersThisSpawn ) ) { if ( victimAttackersThisSpawn.size > 5 ) { attackerCount = 0; foreach( attacking_player in victimAttackersThisSpawn ) { if ( !isdefined( attacking_player ) ) continue; if ( attacking_player == attacker ) continue; if ( attacking_player.team != attacker.team ) continue; attackerCount++; } if ( attackerCount > 4 ) { // note: "kill_enemy_5_teammates_assists" should be awarded withing on life, not just assist player AddPlayerStat( "kill_enemy_5_teammates_assists", 1 ); } } } } if ( isdefined( killstreak ) ) { if ( killstreak == "rcbomb" || killstreak == "inventory_rcbomb" ) { if ( !victimWasOnGround || victimWasWallRunning ) { player AddPlayerStat( "kill_wallrunner_or_air_with_rcbomb", 1 ); } } if ( killstreak == "autoturret" || killstreak == "inventory_autoturret" ) { if ( isdefined( inflictor ) && player util::is_item_purchased( "killstreak_auto_turret" ) ) { if ( !isdefined( inflictor.challenge_killcount ) ) { inflictor.challenge_killcount = 0; } inflictor.challenge_killcount++; if ( inflictor.challenge_killcount == 5 ) { player AddPlayerStat( "kills_auto_turret_5", 1 ); } } } } if ( isdefined( victim.challenge_combatRobotAttackClientID[player.clientid] ) ) { if ( !isdefined( inflictor ) || !isdefined( inflictor.killstreakType ) || !IsString( inflictor.killstreakType ) || ( inflictor.killstreakType != "combat_robot" ) ) { player AddPlayerStat( "kill_enemy_who_damaged_robot", 1 ); } } if ( player IsBonusCardActive( 8, player.class_num ) && player util::is_item_purchased( "bonuscard_danger_close" ) ) { if ( weaponclass == "weapon_grenade" ) { player AddBonusCardStat( 8, "kills", 1, player.class_num ); } if ( weapon.rootweapon.name == "hatchet" && inflictorChallenge_hatchetTossCount <= 2 ) { player.challenge_hatchetkills++; if ( player.challenge_hatchetkills == 2 ) { player AddPlayerStat( "kills_first_throw_both_hatchets", 1 ); } } } player trackKillstreakSupportKills( victim ); // PERKS if ( !isdefined( killstreak ) ) { if ( attackerWasUnderwater ) { player AddPlayerStat( "kill_while_underwater", 1 ); } if ( player util::has_purchased_perk_equipped( "specialty_jetcharger" ) ) // afterburner { if ( ( attacker_doublejump_begin > attacker_doublejump_end || attacker_doublejump_end + 3000 > time ) || ( attacker_slide_begin > attacker_slide_end || attacker_slide_end + 3000 > time ) ) { player AddPlayerStat( "kills_after_jumping_or_sliding", 1 ); if ( player util::has_purchased_perk_equipped( "specialty_overcharge" ) ) { { player AddPlayerStat( "kill_overclock_afterburner_specialist_weapon_after_thrust", 1 ); } } } } trackedPlayer = false; if ( player util::has_purchased_perk_equipped( "specialty_tracker" ) ) { if ( !victim hasPerk ( "specialty_trackerjammer" ) ) // hardwired { player AddPlayerStat( "kill_detect_tracker", 1 ); trackedPlayer = true; } } if ( player util::has_purchased_perk_equipped( "specialty_detectnearbyenemies" ) ) // sixth sense { if ( !victim hasPerk ( "specialty_sixthsensejammer" ) ) { player AddPlayerStat( "kill_enemy_sixth_sense", 1 ); if ( player util::has_purchased_perk_equipped( "specialty_loudenemies" ) ) // awareness { if ( !victim hasPerk ( "specialty_quieter" ) ) // dead silence { player AddPlayerStat( "kill_sixthsense_awareness", 1 ); } } } if ( trackedPlayer ) { player AddPlayerStat( "kill_tracker_sixthsense", 1 ); } } if ( weapon.isheroWeapon == true || attackerHeroAbilityActive ) { if ( player util::has_purchased_perk_equipped( "specialty_overcharge" ) ) // overclock { player AddPlayerStat( "kill_with_specialist_overclock", 1 ); } } if ( player util::has_purchased_perk_equipped( "specialty_gpsjammer" ) ) // ghost { if ( uav::HasUAV( victimSupportIndex ) ) { player AddPlayerStat( "kill_uav_enemy_with_ghost", 1 ); } if ( player util::has_blind_eye_perk_purchased_and_equipped() ) // blindeye { activeKillstreaks = victim killstreaks::getActiveKillstreaks(); awarded_kill_blindeye_ghost_aircraft = false; foreach( activeStreak in activeKillstreaks ) { if ( awarded_kill_blindeye_ghost_aircraft ) break; switch( activeStreak.killstreakType ) { case "sentinel": case "helicopter_comlink": case "drone_striked": case "uav": player AddPlayerStat( "kill_blindeye_ghost_aircraft", 1 ); awarded_kill_blindeye_ghost_aircraft = true; break; } } } } if ( player util::has_purchased_perk_equipped( "specialty_flakjacket" ) ) { if ( isdefined ( player.challenge_lastsurvivewithflakfrom ) && player.challenge_lastsurvivewithflakfrom == victim ) { player AddPlayerStat( "kill_enemy_survive_flak", 1 ); } if ( player util::has_tactical_mask_purchased_and_equipped() ) { recentlySurvivedFlak = false; if ( isdefined ( player.challenge_lastsurvivewithflaktime ) ) { if ( ( player.challenge_lastsurvivewithflaktime + 3000 ) > time ) { recentlySurvivedFlak = true; } } recentlyStunned = false; if ( isdefined( player.lastStunnedTime ) ) { if ( player.lastStunnedTime + 2000 > time ) { recentlyStunned = true; } } if ( recentlySurvivedFlak || ( player util::isFlashbanged() ) || recentlyStunned ) { player AddPlayerStat( "kill_flak_tac_while_stunned", 1 ); } } } if ( player util::has_hard_wired_perk_purchased_and_equipped() ) // hard wired { if ( victim counteruav::HasIndexActiveCounterUAV( victimSupportIndex ) || victim emp::hasactiveemp() ) { player AddPlayerStat( "kills_counteruav_emp_hardline", 1 ); } } if ( player util::has_scavenger_perk_purchased_and_equipped() ) { if ( player.scavenged ) { player AddPlayerStat( "kill_after_resupply", 1 ); if ( trackedPlayer ) { player AddPlayerStat( "kill_scavenger_tracker_resupply", 1 ); } } } if ( player util::has_fast_hands_perk_purchased_and_equipped() ) // fasthands { if ( bulletKill ) { if ( attackerWasSprinting || attacker_sprint_end + 3000 > time ) { player AddPlayerStat( "kills_after_sprint_fasthands", 1 ); if ( player util::has_gung_ho_perk_purchased_and_equipped() ) // gungho { player AddPlayerStat( "kill_fasthands_gungho_sprint", 1 ); } } } } if ( player util::has_hard_wired_perk_purchased_and_equipped() ) // hardwired { if ( player util::has_cold_blooded_perk_purchased_and_equipped() ) // cold blooded { player AddPlayerStat( "kill_hardwired_coldblooded", 1 ); } } killedPlayerWithGungHo = false; if ( player util::has_gung_ho_perk_purchased_and_equipped() ) // gung ho { if ( bulletKill ) { killedPlayerWithGungHo = true; if ( attackerWasSprinting && player PlayerAds() != 1 ) { player AddPlayerStat( "kill_hip_gung_ho", 1 ); } } if ( weaponclass == "weapon_grenade" ) { if ( isdefined( inflictorOwnerWasSprinting ) && inflictorOwnerWasSprinting == true ) { killedPlayerWithGungHo = true; player AddPlayerStat( "kill_hip_gung_ho", 1 ); } } } if ( player util::has_jetquiet_perk_purchased_and_equipped() ) // blast surpressor { if ( attackerDoubleJumping || ( attacker_doublejump_end + 3000 > time ) ) { player AddPlayerStat( "kill_blast_doublejump", 1 ); if ( player util::has_ghost_perk_purchased_and_equipped() ) // ghost { if ( uav::HasUAV( victimSupportIndex ) ) { player AddPlayerStat( "kill_doublejump_uav_engineer_hardwired", 1 ); } } } } if ( player util::has_awareness_perk_purchased_and_equipped() ) // awareness { player AddPlayerStat( "kill_awareness", 1 ); } if ( killedStunnedVictim ) { if ( player util::has_tactical_mask_purchased_and_equipped() ) // tacmask { player AddPlayerStat( "kill_stunned_tacmask", 1 ); if ( killedPlayerWithGungHo == true ) { player AddPlayerStat( "kill_sprint_stunned_gungho_tac", 1 ); } } } if ( player util::has_ninja_perk_purchased_and_equipped() ) // dead silence { player AddPlayerStat( "kill_dead_silence", 1 ); if ( distanceSquared( playerOrigin, victimOrigin ) < 120 * 120 ) { if ( player util::has_awareness_perk_purchased_and_equipped() ) // awareness { player AddPlayerStat( "kill_close_deadsilence_awareness", 1 ); } if ( player util::has_jetquiet_perk_purchased_and_equipped() ) // blast suppressr { player AddPlayerStat( "kill_close_blast_deadsilence", 1 ); } } } greedCardsActive = 0; if ( player IsBonusCardActive( 5, player.class_num ) && player util::is_item_purchased( "bonuscard_perk_1_greed" ) ) { greedCardsActive++; } if ( player IsBonusCardActive( 6, player.class_num ) && player util::is_item_purchased( "bonuscard_perk_2_greed" ) ) { greedCardsActive++; } if ( player IsBonusCardActive( 7, player.class_num ) && player util::is_item_purchased( "bonuscard_perk_3_greed" ) ) { greedCardsActive++; } if ( greedCardsActive >= 2 ) { player AddPlayerStat( "kill_2_greed_2_perks_each", 1 ); } if ( player BonusCardActiveCount( player.class_num ) >= 2 ) { player AddPlayerStat( "kill_2_wildcards", 1 ); } gunfighterOverkillActive = false; if ( player IsBonusCardActive( 4, player.class_num ) && player util::is_item_purchased( "bonuscard_overkill" ) ) { primaryAttachmentsTotal = 0; if ( isdefined( player.primaryLoadoutWeapon ) ) primaryAttachmentsTotal = player.primaryLoadoutWeapon.attachments.size; secondaryAttachmentsTotal = 0; if ( isdefined( player.secondaryLoadoutWeapon ) ) secondaryAttachmentsTotal = player.secondaryLoadoutWeapon.attachments.size; if ( primaryAttachmentsTotal + secondaryAttachmentsTotal >= 5 ) { gunfighterOverkillActive = true; } } if ( ( isdefined (player.primaryLoadoutWeapon ) && weapon == player.primaryLoadoutWeapon ) || ( isdefined (player.primaryLoadoutAltWeapon ) && weapon == player.primaryLoadoutAltWeapon ) ) { if ( player IsBonusCardActive( 0, player.class_num ) && player util::is_item_purchased( "bonuscard_primary_gunfighter" ) ) { player AddBonusCardStat( 0, "kills", 1, player.class_num ); player AddPlayerStat( "kill_with_loadout_weapon_with_3_attachments", 1 ); } if ( isdefined( player.secondaryWeaponKill ) && player.secondaryWeaponKill == true ) { player.primaryWeaponKill = false; player.secondaryWeaponKill = false; if ( player IsBonusCardActive( 4, player.class_num ) && player util::is_item_purchased( "bonuscard_overkill" ) ) { player AddBonusCardStat( 4, "kills", 1, player.class_num ); player AddPlayerStat( "kill_with_both_primary_weapons", 1 ); if ( gunfighterOverkillActive ) { player AddPlayerStat( "kill_overkill_gunfighter_5_attachments", 1 ); } } } else { player.primaryWeaponKill = true; } } else if ( ( isdefined( player.secondaryLoadoutWeapon ) && weapon == player.secondaryLoadoutWeapon ) || ( isdefined( player.secondaryLoadoutAltWeapon ) && weapon == player.secondaryLoadoutAltWeapon ) ) { if ( player IsBonusCardActive( 3, player.class_num ) && player util::is_item_purchased( "bonuscard_secondary_gunfighter" ) ) { player AddBonusCardStat( 3, "kills", 1, player.class_num ); } if ( isdefined( player.primaryWeaponKill ) && player.primaryWeaponKill == true ) { player.primaryWeaponKill = false; player.secondaryWeaponKill = false; if ( player IsBonusCardActive( 4, player.class_num ) && player util::is_item_purchased( "bonuscard_overkill" ) ) { player AddBonusCardStat( 4, "kills", 1, player.class_num ); player AddPlayerStat( "kill_with_both_primary_weapons", 1 ); if ( gunfighterOverkillActive ) { player AddPlayerStat( "kill_overkill_gunfighter_5_attachments", 1 ); } } } else { player.secondaryWeaponKill = true; } } if ( player util::has_hacker_perk_purchased_and_equipped() && player util::has_hard_wired_perk_purchased_and_equipped() ) { should_award_kill_near_plant_engineer_hardwired = false; if ( isdefined( victimActiveBouncingBetties ) ) { foreach( bouncingBettyInfo in victimActiveBouncingBetties ) { if ( !isdefined( bouncingBettyInfo ) || !isdefined( bouncingBettyInfo.origin ) ) continue; if ( DistanceSquared( bouncingBettyInfo.origin, victimOrigin ) < ( (400) * (400) ) ) { should_award_kill_near_plant_engineer_hardwired = true; break; } } } if ( isdefined( victimActiveProximityGrenades ) && should_award_kill_near_plant_engineer_hardwired == false ) { foreach( proximityGrenadeInfo in victimActiveProximityGrenades ) { if ( !isdefined( proximityGrenadeInfo ) || !isdefined( proximityGrenadeInfo.origin ) ) continue; if ( DistanceSquared( proximityGrenadeInfo.origin, victimOrigin ) < ( (400) * (400) ) ) { should_award_kill_near_plant_engineer_hardwired = true; break; } } } if ( should_award_kill_near_plant_engineer_hardwired ) { player AddPlayerStat( "kill_near_plant_engineer_hardwired", 1 ); } } } else // it was a killstreak { if ( weapon.name == "supplydrop" ) { if (isdefined( inflictorPlayerHasEngineerPerk ) ) { player AddPlayerStat( "kill_booby_trap_engineer", 1 ); } } } if ( weapon.isHeroWeapon == true || attackerHeroAbilityActive || isdefined( killstreak ) ) { if ( player util::has_purchased_perk_equipped( "specialty_overcharge" ) // overclock && ( player util::has_purchased_perk_equipped( "specialty_anteup" ) ) ) // anteup { player AddPlayerStat( "kill_anteup_overclock_scorestreak_specialist", 1 ); } } } function on_player_spawn() { if ( canProcessChallenges() ) { self fix_challenge_stats_on_spawn(); } } function get_challenge_stat( stat_name ) { return self GetDStat( "playerstatslist", stat_name, "challengevalue" ); } function force_challenge_stat( stat_name, stat_value ) { // make the stat value and challenge value identical self SetDStat( "playerstatslist", stat_name, "statvalue", stat_value ); self SetDStat( "playerstatslist", stat_name, "challengevalue", stat_value ); } function get_challenge_group_stat( group_name, stat_name ) { return self GetDStat( "groupstats", group_name, "stats", stat_name, "challengevalue" ); } function fix_challenge_stats_on_spawn() { // use this method to fix up any challenge inconsistencies at spawn player = self; if ( !isdefined( player ) ) return; if ( player.fix_challenge_stats_performed === true ) return; player fix_TU6_weapon_for_diamond( "special_crossbow_for_diamond" ); player fix_TU6_weapon_for_diamond( "melee_crowbar_for_diamond" ); player fix_TU6_weapon_for_diamond( "melee_sword_for_diamond" ); player fix_TU6_ar_garand(); player fix_TU6_pistol_shotgun(); player TU7_fix_100_percenter(); player.fix_challenge_stats_performed = true; } function fix_TU6_weapon_for_diamond( stat_name ) { player = self; wepaon_for_diamond = player get_challenge_stat( stat_name ); if ( wepaon_for_diamond == 1 ) { // valid values for X_for_diamond are 0, 2, and 3; TU5 has an issue for some challenges // where only 1 point was awarded if pistol diamond was awarded ( and some challenges where any secondary diamond camo was awwarded ) // this fixes the issue by setting it to either zero or two secondary_mastery = player get_challenge_stat( "secondary_mastery" ); if ( secondary_mastery == 3 ) { player force_challenge_stat( stat_name, 2 ); } else { player force_challenge_stat( stat_name, 0 ); } } } function fix_TU6_ar_garand() { player = self; group_weapon_assault = player get_challenge_group_stat( "weapon_assault", "challenges" ); weapons_mastery_assault = player get_challenge_stat( "weapons_mastery_assault" ); // earning weapons mastery on assault rifles prior to TU6 will exhibit an issue of not being able to obtain diamond camo for ar_garand // this fixes the issue by awarding ar_garand_for_diamond if weapons_mastery_assault was not obtained // 49 obtained from challenge 648 in statsmilestones3.csv if ( group_weapon_assault >= 49 && weapons_mastery_assault < 1 ) { player force_challenge_stat( "weapons_mastery_assault", 1 ); // intentionally forced stat here to avoid stat processing player AddPlayerStat( "ar_garand_for_diamond", 1 ); // now add stat with stat processing } } function fix_TU6_pistol_shotgun() { player = self; group_weapon_pistol = player get_challenge_group_stat( "weapon_pistol", "challenges" ); secondary_mastery_pistol = player get_challenge_stat( "secondary_mastery_pistol" ); // see comments in fix_TU6_ar_garand for more related details // 21 obtained from challenge 649 in statsmilestones3.csv if ( group_weapon_pistol >= 21 && secondary_mastery_pistol < 1 ) { player force_challenge_stat( "secondary_mastery_pistol", 1 ); // intentionally forced stat here to avoid stat processing player AddPlayerStat( "pistol_shotgun_for_diamond", 1 ); // now add stat with stat processing } } function completed_specific_challenge( target_value, challenge_name ) { challenge_count = self get_challenge_stat( challenge_name ); return ( challenge_count >= target_value ); } function tally_completed_challenge( target_value, challenge_name ) { return ( ( self completed_specific_challenge( target_value, challenge_name ) ) ? 1 : 0 ); } function TU7_fix_100_percenter() { self TU7_fix_mastery_perk_2(); } function TU7_fix_mastery_perk_2() { player = self; // if mastery_perk_2 is compeleted, then no need to try to fix up mastery_perk_2 = player get_challenge_stat( "mastery_perk_2" ); if ( mastery_perk_2 >= 12 ) return; // if earn_scorestreak_anteup has not been completed, no need to try to fix up if ( player completed_specific_challenge( 200, "earn_scorestreak_anteup") == false ) return; perk_2_tally = 1; // init to 1 because earn_scorestreak_anteup is already completed perk_2_tally += player tally_completed_challenge( 100, "destroy_ai_scorestreak_coldblooded" ); //destroy_ai_scorestreak_coldblooded perk_2_tally += player tally_completed_challenge( 100, "kills_counteruav_emp_hardline" ); //kills_counteruav_emp_hardline perk_2_tally += player tally_completed_challenge( 200, "kill_after_resupply" ); //kill_after_resupply perk_2_tally += player tally_completed_challenge( 100, "kills_after_sprint_fasthands" ); //kills_after_sprint_fasthands perk_2_tally += player tally_completed_challenge( 200, "kill_detect_tracker" ); //kill_detect_tracker //perk_2_tally += player tally_completed_challenge( 200, "earn_scorestreak_anteup" ); //earn_scorestreak_anteup perk_2_tally += player tally_completed_challenge( 10, "earn_5_scorestreaks_anteup" ); //earn_5_scorestreaks_anteup perk_2_tally += player tally_completed_challenge( 25, "kill_scavenger_tracker_resupply" ); //kill_scavenger_tracker_resupply perk_2_tally += player tally_completed_challenge( 25, "kill_hardwired_coldblooded" ); //kill_hardwired_coldblooded perk_2_tally += player tally_completed_challenge( 25, "kill_anteup_overclock_scorestreak_specialist" ); //kill_anteup_overclock_scorestreak_specialist perk_2_tally += player tally_completed_challenge( 50, "kill_fasthands_gungho_sprint" ); //kill_fasthands_gungho_sprint perk_2_tally += player tally_completed_challenge( 50, "kill_tracker_sixthsense" ); //kill_tracker_sixthsense if ( mastery_perk_2 < perk_2_tally ) { // award "mastery_perk_2" player AddPlayerStat( "mastery_perk_2", 1 ); } } function getBaseWeapon( weapon ) { // TODO: need to get weapon stat name available from script (and make sure all stat names are populated properly for weapons) base_weapon_param = [[ level.get_base_weapon_param ]]( weapon ); // we have a "root" weapon after this executes base_weapon_param_name = str_strip_lh_or_dw( base_weapon_param.name ); base_weapon_param_name = str_strip_lh_from_crossbow( base_weapon_param_name ); // unique case because of poor naming convention return GetWeapon( GetRefFromItemIndex( GetBaseWeaponItemIndex( GetWeapon( base_weapon_param_name ) ) ) ); } function str_strip_lh_from_crossbow( str ) { if ( StrEndsWith( str, "crossbowlh" ) ) { return GetSubStr( str, 0, str.size - 2 ); } return str; } function str_strip_lh_or_dw( str ) { if ( StrEndsWith( str, "_lh" ) || StrEndsWith( str, "_dw" ) ) { return GetSubStr( str, 0, str.size - 3 ); } return str; } function checkKillStreak5( baseWeapon, player ) { if ( isdefined( player.weaponKillsThisSpawn[ baseWeapon ] ) ) { player.weaponKillsThisSpawn[ baseWeapon ]++; if ( ( player.weaponKillsThisSpawn[ baseWeapon ] ) % 5 == 0 ) { player AddWeaponStat( baseWeapon, "killstreak_5", 1 ); } } else { player.weaponKillsThisSpawn[ baseWeapon ] = 1; } } function checkDualWield( baseWeapon, player, attacker, time, attackerWasSprinting, attacker_sprint_end ) { // note: check weapon.isDualWield and weaponPurchased before calling checkDualWield for challenges. if ( attackerWasSprinting || ( attacker_sprint_end + 1000 > time ) ) { if ( attacker util::has_gung_ho_perk_purchased_and_equipped() ) { player AddPlayerStat( "kills_sprinting_dual_wield_and_gung_ho", 1 ); } } } function challengeGameEndMP( data ) { player = data.player; winner = data.winner; if ( !isdefined( player ) ) return; if ( endedEarly( winner ) ) return; if ( level.teambased ) { winnerScore = game["teamScores"][winner]; loserScore = getLosersTeamScores( winner ); } mostKillsLeastDeaths = true; for ( index = 0; index < level.placement["all"].size; index++ ) { if ( level.placement["all"][index].deaths < player.deaths ) { mostKillsLeastDeaths = false; } if ( level.placement["all"][index].kills > player.kills ) { mostKillsLeastDeaths = false; } } if ( mostKillsLeastDeaths && player.kills > 0 && level.placement["all"].size > 3 ) { if ( level.teambased ) { playerIsWinner = ( player.team === winner ); } else { // see if in top 3 playerIsWinner = ( ( level.placement["all"][0] === winner ) || ( level.placement["all"][1] === winner ) || ( level.placement["all"][2] === winner ) ); } if ( playerIsWinner ) { player AddPlayerStat( "most_kills_least_deaths", 1 ); } } } function killedBaseOffender( objective, weapon ) { self endon( "disconnect" ); self AddPlayerStatWithGameType( "defends", 1 ); // awards the player for being a "defender" as they killed an offender self.challenge_offenderkillcount++; if ( !isdefined( self.challenge_objectiveOffensive ) || self.challenge_objectiveOffensive != objective ) { self.challenge_objectiveOffensiveKillcount = 0; } self.challenge_objectiveOffensiveKillcount++; self.challenge_ObjectiveOffensive = objective; killstreak = killstreaks::get_from_weapon( weapon ); if ( isdefined( killstreak ) ) { switch ( killstreak ) { case "planemortar": case "inventory_planemortar": case "remote_missile": case "inventory_remote_missile": case "drone_strike": case "inventory_drone_strike": self.challenge_offenderProjectileMultiKillcount++; break; case "helicopter_comlink": case "inventory_helicopter_comlink": self.challenge_offenderComlinkKillcount++; break; case "combat_robot": case "inventory_combat_robot": self AddPlayerStat( "kill_attacker_with_robot_or_tank", 1 ); break; case "inventory_autoturret": case "autoturret": self.challenge_offenderSentryTurretKillCount++; self AddPlayerStat( "kill_attacker_with_robot_or_tank", 1 ); break; } } if ( self.challenge_offenderComlinkKillcount == 2 ) { self AddPlayerStat( "kill_2_attackers_with_comlink", 1 ); } if ( self.challenge_objectiveOffensiveKillcount > 4 ) { self AddPlayerStatWithGameType( "multikill_5_attackers", 1 ); self.challenge_objectiveOffensiveKillcount = 0; } if ( self.challenge_offenderSentryTurretKillCount > 2 ) { self AddPlayerStat( "multikill_3_attackers_ai_tank", 1 ); self.challenge_offenderSentryTurretKillCount = 0; } self util::player_contract_event( "offender_kill" ); self waitTillTimeoutOrDeath( 4.0 ); if ( self.challenge_offenderkillcount > 1 ) { self AddPlayerStat( "double_kill_attackers", 1 ); } self.challenge_offenderkillcount = 0; if ( self.challenge_offenderProjectileMultiKillcount >= 2 ) { self AddPlayerStat( "multikill_2_objective_scorestreak_projectile", 1 ); } self.challenge_offenderProjectileMultiKillcount = 0; } function killedBaseDefender( objective ) { self endon( "disconnect" ); self AddPlayerStatWithGameType( "offends", 1 ); // awards the player for being an "offender" as they killed a defender if ( !isdefined( self.challenge_objectiveDefensive ) || self.challenge_objectiveDefensive != objective ) { self.challenge_objectiveDefensiveKillcount = 0; } self.challenge_objectiveDefensiveKillcount++; self.challenge_ObjectiveDefensive = objective; self.challenge_defenderkillcount++; self util::player_contract_event( "defender_kill" ); self waitTillTimeoutOrDeath( 4.0 ); if ( self.challenge_defenderkillcount > 1 ) { self AddPlayerStat( "double_kill_defenders", 1 ); } self.challenge_defenderkillcount = 0; } function waitTillTimeoutOrDeath( timeout ) { self endon( "death" ); wait( timeout ); } function killstreak_30_noscorestreaks() { if ( level.gameType == "dm" ) { self AddPlayerStat( "killstreak_30_no_scorestreaks", 1 ); } } function heroAbilityActivateNearDeath() { if ( isdefined( self.heroAbility ) && self.pers["canSetSpecialistStat"] ) { switch( self.heroAbility.name ) { case "gadget_camo": case "gadget_armor": case "gadget_clone": case "gadget_speed_burst": case "gadget_vision_pulse": case "gadget_flashback": case "gadget_heat_wave": self thread checkForHeroSurvival(); break; } } } function checkForHeroSurvival() { self endon ("death"); self endon ("disconnect"); self util::waittill_any_timeout( 8.0, "challenge_survived_from_death", "disconnect" ); self AddPlayerStat( "death_dodger", 1 ); } function callbackEndHeroSpecialistEMP() { empOwner = self emp::EnemyEMPOwner(); if ( isdefined( empOwner ) && IsPlayer( empOwner ) ) { empOwner AddPlayerStat( "end_enemy_specialist_ability_with_emp", 1 ); return; } if ( isdefined( self.empStartTime ) && self.empStartTime > ( getTime() - 100 ) ) { if ( isdefined(self.empedBy) && IsPlayer( self.empedBy ) ) { self.empedBy AddPlayerStat( "end_enemy_specialist_ability_with_emp", 1 ); return; } } } function calledInComlinkChopper() { self.challenge_offenderComlinkKillcount = 0; } function combat_robot_damage( eAttacker, combatRobotOwner ) { if ( !isdefined( eAttacker.challenge_combatRobotAttackClientID[combatRobotOwner.clientid] ) ) { eAttacker.challenge_combatRobotAttackClientID[combatRobotOwner.clientid] = spawnstruct(); } } function trackKillstreakSupportKills( victim ) { if ( level.activePlayerEMPs[ self.entNum ] > 0 ) { self AddWeaponStat( GetWeapon( "emp" ), "kills_while_active", 1 ); } if ( ( level.activePlayerUAVs[ self.entNum ] > 0 ) && ( !isdefined( level.forceradar ) || level.forceRadar == false ) ) { self AddWeaponStat( GetWeapon( "uav" ), "kills_while_active", 1 ); } if ( level.activePlayerSatellites[ self.entNum ] > 0 ) { self AddWeaponStat( GetWeapon( "satellite" ), "kills_while_active", 1 ); } if ( level.activePlayerCounterUAVs[ self.entNum ] > 0 ) { self AddWeaponStat( GetWeapon( "counteruav" ), "kills_while_active", 1 ); } if ( isdefined( victim.lastMicrowavedBy ) && victim.lastMicrowavedBy == self ) { self AddWeaponStat( GetWeapon( "microwave_turret" ), "kills_while_active", 1 ); } } function monitorReloads() { self endon("disconnect"); self endon("killMonitorReloads"); while(1) { self waittill("reload"); currentWeapon = self getCurrentWeapon(); if ( currentWeapon == level.weaponNone ) { continue; } time = getTime(); self.lastReloadTime = time; if ( WeaponHasAttachment( currentWeapon, "fastreload" ) ) // aka fastmags or Fast Mags { self.lastFastReloadTime = time; } } } function monitorGrenadeFire() { self notify( "grenadeTrackingStart" ); self endon( "grenadeTrackingStart" ); self endon( "disconnect" ); for (;;) { self waittill ( "grenade_fire", grenade, weapon ); if ( !isdefined( grenade ) ) { continue; } if ( weapon.rootweapon.name == "hatchet" ) { self.challenge_hatchetTossCount++; grenade.challenge_hatchetTossCount = self.challenge_hatchetTossCount; } if ( self issprinting() ) { grenade.ownerWasSprinting = true; } } } function watchWeaponChangeComplete() { self endon( "death" ); self endon( "disconnect" ); self endon( "joined_team" ); self endon( "joined_spectators" ); while( 1 ) { self.heroWeaponKillsThisActivation = 0; self waittill( "weapon_change_complete" ); } } function longDistanceKillMP( weapon ) { self AddWeaponStat( weapon, "longshot_kill", 1 ); if ( self weaponHasAttachmentAndUnlocked( weapon, "extbarrel", "suppressed" ) ) { if ( self GetWeaponOptic( weapon ) != "" ) { self addPlayerStat( "long_shot_longbarrel_suppressor_optic", 1 ); } } } function capturedObjectiveFunction() { if ( self IsBonusCardActive( 9, self.class_num ) && self util::is_item_purchased( "bonuscard_two_tacticals" ) ) { self AddPlayerStat( "capture_objective_tactician", 1 ); } } function watchWallRunTwoOppositeWallsNoGround() { player = self; player endon( "death" ); player endon( "disconnect" ); player endon( "joined_team" ); player endon( "joined_spectators" ); self.wallRanTwoOppositeWallsNoGround = false; while ( 1 ) { if ( !player IsWallRunning() ) { self.wallRanTwoOppositeWallsNoGround = false; player waittill( "wallrun_begin" ); } ret = player util::waittill_any_return( "jump_begin", "wallrun_end", "disconnect", "joined_team", "joined_spectators" ); if ( ret == "wallrun_end" ) continue; wall_normal = player GetWallRunWallNormal(); player waittill( "jump_end" ); if ( !player IsWallRunning() ) continue; last_wall_normal = wall_normal; wall_normal = player GetWallRunWallNormal(); opposite_walls = ( VectorDot( wall_normal, last_wall_normal ) < -0.5 ); if ( !opposite_walls ) continue; player.wallRanTwoOppositeWallsNoGround = true; while ( player IsWallRunning() ) { ret = player util::waittill_any_return( "jump_end", "wallrun_end", "disconnect", "joined_team", "joined_spectators" ); if ( ret == "wallrun_end" ) break; } {wait(.05);}; while ( !player IsOnGround() ) { {wait(.05);}; } } } function processSpecialistChallenge( statName ) { if ( self.pers["canSetSpecialistStat"] ) { self AddSpecialistStat( statName, 1 ); } } function flakjacketProtectedMP( weapon, attacker ) { if ( weapon.name == "claymore" ) { self.flakJacketClaymore[ attacker.clientid ] = true; } self AddPlayerStat( "survive_with_flak", 1 ); self.challenge_lastsurvivewithflakfrom = attacker; self.challenge_lastsurvivewithflaktime = getTime(); }