#using scripts\codescripts\struct; #using scripts\shared\callbacks_shared; #using scripts\shared\challenges_shared; #using scripts\shared\killstreaks_shared; #using scripts\shared\rank_shared; #using scripts\shared\scoreevents_shared; #using scripts\shared\system_shared; #using scripts\shared\util_shared; #using scripts\shared\abilities\_ability_player; #using scripts\shared\weapons\_weapon_utils; #using scripts\mp\gametypes\_globallogic_score; #using scripts\mp\_challenges; #using scripts\mp\_util; #using scripts\mp\killstreaks\_killstreaks; #using scripts\mp\_teamops; #namespace scoreevents; function autoexec __init__sytem__() { system::register("scoreevents",&__init__,undefined,undefined); } function __init__() { callback::on_start_gametype( &init ); } function init() { level.scoreEventCallbacks = []; level.scoreEventGameEndCallback =&onGameEnd; registerScoreEventCallback( "playerKilled", &scoreevents::scoreEventPlayerKill ); } function scoreEventTableLookupInt( index, scoreEventColumn ) { return int( tableLookup( getScoreEventTableName(), 0, index, scoreEventColumn ) ); } function scoreEventTableLookup( index, scoreEventColumn ) { return tableLookup( getScoreEventTableName(), 0, index, scoreEventColumn ); } function registerScoreEventCallback( callback, func ) { if ( !isdefined( level.scoreEventCallbacks[callback] ) ) { level.scoreEventCallbacks[callback] = []; } level.scoreEventCallbacks[callback][level.scoreEventCallbacks[callback].size] = func; } function scoreEventPlayerKill( data, time ) { victim = data.victim; attacker = data.attacker; time = data.time; level.numKills++; attacker.lastKilledPlayer = victim; wasDefusing = data.wasDefusing; wasPlanting = data.wasPlanting; victimWasOnGround = data.victimOnGround; attackerWasOnGround = data.attackerOnGround; meansOfDeath = data.sMeansOfDeath; attackerTraversing = data.attackerTraversing; attackerWallRunning = data.attackerWallRunning; attackerDoubleJumping = data.attackerDoubleJumping; attackerSliding = data.attackerSliding; victimWasWallRunning = data.victimWasWallRunning; victimWasDoubleJumping = data.victimWasDoubleJumping; attackerSpeedburst = data.attackerSpeedburst; victimSpeedburst = data.victimSpeedburst; victimCombatEfficieny = data.victimCombatEfficieny; attackerflashbackTime = data.attackerflashbackTime; victimflashbackTime = data.victimflashbackTime; victimSpeedburstLastOnTime = data.victimSpeedburstLastOnTime; victimCombatEfficiencyLastOnTime = data.victimCombatEfficiencyLastOnTime; victimVisionPulseActivateTime = data.victimVisionPulseActivateTime; attackerVisionPulseActivateTime = data.attackerVisionPulseActivateTime; victimVisionPulseActivateTime = data.victimVisionPulseActivateTime; attackerVisionPulseArray = data.attackerVisionPulseArray; victimVisionPulseArray = data.victimVisionPulseArray; attackerVisionPulseOriginArray = data.attackerVisionPulseOriginArray; victimVisionPulseOriginArray = data.victimVisionPulseOriginArray; attackerVisionPulseOrigin = data.attackerVisionPulseOrigin; victimVisionPulseOrigin = data.victimVisionPulseOrigin; attackerWasFlashed = data.attackerWasFlashed; attackerWasConcussed = data.attackerWasConcussed; victimWasUnderwater = data.wasUnderwater; victimHeroAbilityActive = data.victimHeroAbilityActive; victimHeroAbility = data.victimHeroAbility; attackerHeroAbilityActive = data.attackerHeroAbilityActive; attackerHeroAbility = data.attackerHeroAbility; attackerWasHeatWaveStunned = data.attackerWasHeatWaveStunned; victimWasHeatWaveStunned = data.victimWasHeatWaveStunned; victimElectrifiedBy = data.victimElectrifiedBy; victimWasInSlamState = data.victimWasInSlamState; victimBledOut = data.bledOut; victimWasLungingWithArmBlades = data.victimWasLungingWithArmBlades; victimPowerArmorLastTookDamageTime = data.victimPowerArmorLastTookDamageTime; victimHeroWeaponKillsThisActivation = data.victimHeroWeaponKillsThisActivation; victimGadgetPower = data.victimGadgetPower; victimGadgetWasActiveLastDamage = ( data.victimGadgetWasActiveLastDamage === true ); victimIsThiefOrRoulette = data.victimIsThiefOrRoulette; attackerIsRoulette = data.attackerIsRoulette; victimHeroAbilityName = data.victimHeroAbilityName; // note that victim hero ability name cannot be reliably taken from victimHeroAbility, so this is done instead attackerInVehicleArchetype = data.attackerInVehicleArchetype; if ( isdefined( victimHeroAbilityName ) ) victimHeroAbilityEquipped = GetWeapon( victimHeroAbilityName ); if ( victimBledOut == true ) // do not process player killed score events if the player bled out return; exlosiveDamage = false; attackerShotVictim = ( meansOfDeath == "MOD_PISTOL_BULLET" || meansOfDeath == "MOD_RIFLE_BULLET" || meansOfDeath == "MOD_HEAD_SHOT" ); weapon = level.weaponNone; inflictor = data.eInflictor; isGrenade = false; if ( isdefined( data.weapon ) ) { weapon = data.weapon; weaponClass = util::getWeaponClass( data.weapon ); isGrenade = weapon.isGrenadeWeapon; killstreak = killstreaks::get_from_weapon( data.weapon ); } victim.anglesOnDeath = victim getPlayerAngles(); if ( meansOfDeath == "MOD_GRENADE" || meansOfDeath == "MOD_GRENADE_SPLASH" || meansOfDeath == "MOD_EXPLOSIVE" || meansOfDeath == "MOD_EXPLOSIVE_SPLASH" || meansOfDeath == "MOD_PROJECTILE" || meansOfDeath == "MOD_PROJECTILE_SPLASH" ) { if ( weapon == level.weaponNone && isdefined( data.victim.explosiveInfo["weapon"] ) ) weapon = data.victim.explosiveInfo["weapon"]; exlosiveDamage = true; } if ( !isdefined( killstreak ) ) { if ( level.teamBased ) { if ( isdefined( victim.lastKillTime ) && ( victim.lastKillTime > time - 3000 ) ) { if ( isdefined( victim.lastkilledplayer ) && victim.lastkilledplayer util::IsEnemyPlayer( attacker ) == false && attacker != victim.lastkilledplayer ) { processScoreEvent( "kill_enemy_who_killed_teammate", attacker, victim, weapon ); victim RecordKillModifier("avenger"); } } if ( isdefined( victim.damagedPlayers ) ) { keys = getarraykeys(victim.damagedPlayers); for ( i = 0; i < keys.size; i++ ) { key = keys[i]; if ( key == attacker.clientid ) continue; if ( !isdefined( victim.damagedPlayers[key].entity ) ) continue; if ( attacker util::IsEnemyPlayer( victim.damagedPlayers[key].entity ) ) continue; if ( ( time - victim.damagedPlayers[key].time ) < 1000 ) { processScoreEvent( "kill_enemy_injuring_teammate", attacker, victim, weapon ); if ( isdefined( victim.damagedPlayers[key].entity ) ) { victim.damagedPlayers[key].entity.lastRescuedBy = attacker; victim.damagedPlayers[key].entity.lastRescuedTime = time; } victim RecordKillModifier("defender"); } } } } if ( isGrenade == false || ( weapon.name == "hero_gravityspikes" ) ) { if ( victimWasDoubleJumping == true ) { if ( attackerDoubleJumping == true ) { processScoreEvent( "kill_enemy_while_both_in_air", attacker, victim, weapon ); } processScoreEvent( "kill_enemy_that_is_in_air", attacker, victim, weapon ); attacker addPlayerStat( "kill_enemy_that_in_air", 1 ); } if ( attackerDoubleJumping == true ) { processScoreEvent( "kill_enemy_while_in_air", attacker, victim, weapon ); attacker addPlayerStat( "kill_while_in_air", 1 ); } if ( victimWasWallRunning == true ) { processScoreEvent( "kill_enemy_that_is_wallrunning", attacker, victim, weapon ); attacker addPlayerStat( "kill_enemy_thats_wallrunning", 1 ); } if ( attackerWallRunning == true ) { processScoreEvent( "kill_enemy_while_wallrunning", attacker, victim, weapon ); attacker addPlayerStat( "kill_while_wallrunning", 1 ); } if ( attackerSliding == true ) { processScoreEvent( "kill_enemy_while_sliding", attacker, victim, weapon ); attacker addPlayerStat( "kill_while_sliding", 1 ); } if ( attackerTraversing == true ) { processScoreEvent( "traversal_kill", attacker, victim, weapon ); attacker addPlayerStat( "kill_while_mantling", 1 ); } if ( attackerWasFlashed ) { processScoreEvent( "kill_enemy_while_flashbanged", attacker, victim, weapon ); } if ( attackerWasConcussed ) { processScoreEvent( "kill_enemy_while_stunned", attacker, victim, weapon ); } if ( attackerWasHeatWaveStunned ) { processScoreEvent( "kill_enemy_that_heatwaved_you", attacker, victim, weapon ); attacker util::player_contract_event( "killed_hero_ability_enemy" ); } if ( victimWasHeatWaveStunned ) { if ( isdefined( victim._heat_wave_stunned_by ) && isdefined( victim._heat_wave_stunned_by[attacker.clientid] ) && victim._heat_wave_stunned_by[attacker.clientid] >= time ) { processScoreEvent( "heatwave_kill", attacker, victim, weapon ); attacker hero_ability_kill_event( getWeapon( "gadget_heat_wave" ), get_equipped_hero_ability( victimHeroAbilityName ) ); attacker specialistMedalAchievement(); attacker thread specialistStatAbilityUsage( 4, false ); } if ( attackerIsRoulette && !victimIsThiefOrRoulette && victimHeroAbilityName === "gadget_heat_wave" ) { processScoreEvent( "kill_enemy_with_their_hero_ability", attacker, victim, weapon ); } } } if ( attackerSpeedburst == true ) { processScoreEvent( "speed_burst_kill", attacker, victim, weapon ); attacker hero_ability_kill_event( GetWeapon( "gadget_speed_burst" ), get_equipped_hero_ability( victimHeroAbilityName ) ); attacker specialistMedalAchievement(); attacker thread specialistStatAbilityUsage( 4, false ); if ( attackerIsRoulette && !victimIsThiefOrRoulette && victimHeroAbilityName === "gadget_speed_burst" ) { processScoreEvent( "kill_enemy_with_their_hero_ability", attacker, victim, weapon ); } } if ( victimSpeedburstLastOnTime > time - 50 ) { processScoreEvent( "kill_enemy_who_is_speedbursting", attacker, victim, weapon ); attacker util::player_contract_event( "killed_hero_ability_enemy" ); } if ( victimCombatEfficiencyLastOnTime > time - 50 ) { processScoreEvent( "kill_enemy_who_is_using_focus", attacker, victim, weapon ); attacker util::player_contract_event( "killed_hero_ability_enemy" ); } if ( attackerflashbackTime != 0 && attackerflashbackTime > time - 4000 ) { processScoreEvent( "flashback_kill", attacker, victim, weapon ); attacker hero_ability_kill_event( GetWeapon( "gadget_flashback" ), get_equipped_hero_ability( victimHeroAbilityName ) ); attacker specialistMedalAchievement(); attacker thread specialistStatAbilityUsage( 4, false ); if ( attackerIsRoulette && !victimIsThiefOrRoulette && victimHeroAbilityName === "gadget_flashback" ) { processScoreEvent( "kill_enemy_with_their_hero_ability", attacker, victim, weapon ); } } if ( victimflashbackTime != 0 && victimflashbackTime > time - 4000 ) { processScoreEvent( "kill_enemy_who_has_flashbacked", attacker, victim, weapon ); attacker util::player_contract_event( "killed_hero_ability_enemy" ); } if ( victimWasInSlamState ) { processScoreEvent( "end_enemy_gravity_spike_attack", attacker, victim, weapon ); attacker util::player_contract_event( "killed_hero_weapon_enemy" ); } if ( challenges::isHighestScoringPlayer( victim ) ) { processScoreEvent( "kill_enemy_who_has_high_score", attacker, victim, weapon ); } if ( victimWasUnderwater && exlosiveDamage ) { processScoreEvent( "kill_underwater_enemy_explosive", attacker, victim, weapon ); } if ( isdefined ( victimElectrifiedBy ) && victimElectrifiedBy != attacker ) { processScoreEvent( "electrified", victimElectrifiedBy, victim, weapon ); } if ( victimVisionPulseActivateTime != 0 && victimVisionPulseActivateTime > time - 4000 ) { gadgetWeapon = getWeapon("gadget_vision_pulse"); for ( i = 0; i < victimVisionPulseArray.size; i++ ) { player = victimVisionPulseArray[i]; if ( player == attacker ) { gadget = GetWeapon( "gadget_vision_pulse" ); if ( victimVisionPulseActivateTime + 300 > time - gadgetWeapon.gadget_pulse_duration ) { distanceToPulse = distance( victimVisionPulseOriginArray[i], victimVisionPulseOrigin ); ratio = distanceToPulse / gadgetWeapon.gadget_pulse_max_range; timing = ratio * gadgetWeapon.gadget_pulse_duration; if ( victimVisionPulseActivateTime + 300 > time - timing ) { break; } } processScoreEvent( "kill_enemy_that_pulsed_you", attacker, victim, weapon ); attacker util::player_contract_event( "killed_hero_ability_enemy" ); break; } } if ( isdefined( victimHeroAbility ) ) { attacker notify( "hero_shutdown", victimHeroAbility ); attacker notify( "hero_shutdown_gadget", victimHeroAbility, victim ); } } if ( attackerVisionPulseActivateTime != 0 && attackerVisionPulseActivateTime > time - ( 2000 + 4000 + 500 ) ) { gadgetWeapon = getWeapon("gadget_vision_pulse"); for ( i = 0; i < attackerVisionPulseArray.size; i++ ) { player = attackerVisionPulseArray[i]; if ( player == victim ) { gadget = GetWeapon( "gadget_vision_pulse" ); if ( attackerVisionPulseActivateTime > time - gadgetWeapon.gadget_pulse_duration ) { distanceToPulse = distance( attackerVisionPulseOriginArray[i], attackerVisionPulseOrigin ); ratio = distanceToPulse / gadgetWeapon.gadget_pulse_max_range; timing = ratio * gadgetWeapon.gadget_pulse_duration; if ( attackerVisionPulseActivateTime > time - timing ) { break; } } processScoreEvent( "vision_pulse_kill", attacker, victim, weapon ); attacker hero_ability_kill_event( gadgetWeapon, get_equipped_hero_ability( victimHeroAbilityName ) ); attacker specialistMedalAchievement(); attacker thread specialistStatAbilityUsage( 4, false ); if ( attackerIsRoulette && !victimIsThiefOrRoulette && victimHeroAbilityName === "gadget_vision_pulse" ) { processScoreEvent( "kill_enemy_with_their_hero_ability", attacker, victim, weapon ); } break; } } } if ( victimHeroAbilityActive && isdefined ( victimHeroAbility ) ) { attacker notify( "hero_shutdown", victimHeroAbility ); attacker notify( "hero_shutdown_gadget", victimHeroAbility, victim ); switch( victimHeroAbility.name ) { case "gadget_armor": processScoreEvent( "kill_enemy_who_has_powerarmor", attacker, victim, weapon ); attacker util::player_contract_event( "killed_hero_ability_enemy" ); break; case "gadget_resurrect": processScoreEvent( "kill_enemy_that_used_resurrect", attacker, victim, weapon ); attacker util::player_contract_event( "killed_hero_ability_enemy" ); break; case "gadget_camo": processScoreEvent( "kill_enemy_that_is_using_optic_camo", attacker, victim, weapon ); attacker util::player_contract_event( "killed_hero_ability_enemy" ); break; case "gadget_clone": processScoreEvent( "end_enemy_psychosis", attacker, victim, weapon ); attacker util::player_contract_event( "killed_hero_ability_enemy" ); break; } } else { if ( isdefined( victimPowerArmorLastTookDamageTime ) && ( time - victimPowerArmorLastTookDamageTime <= 3000 ) ) { attacker notify( "hero_shutdown", victimHeroAbility ); attacker notify( "hero_shutdown_gadget", victimHeroAbility, victim ); processScoreEvent( "kill_enemy_who_has_powerarmor", attacker, victim, weapon ); attacker util::player_contract_event( "killed_hero_ability_enemy" ); } } if ( isdefined( data.victimWeapon ) && isdefined( data.victimWeapon.isHeroWeapon ) && data.victimWeapon.isHeroWeapon == true ) { attacker notify( "hero_shutdown", data.victimWeapon ); attacker notify( "hero_shutdown_gadget", data.victimWeapon, victim ); } else if ( isdefined( victim.heroWeapon ) && victimGadgetWasActiveLastDamage && victimGadgetPower < 100 ) { // need to do this for some hero weapons like armblades attacker notify( "hero_shutdown", victim.heroWeapon ); attacker notify( "hero_shutdown_gadget", victim.heroWeapon, victim ); } if ( attackerHeroAbilityActive && isdefined ( attackerHeroAbility ) ) { abilityToCheck = undefined; switch( attackerHeroAbility.name ) { case "gadget_armor": { processScoreEvent( "power_armor_kill", attacker, victim, weapon ); attacker hero_ability_kill_event( attackerHeroAbility, get_equipped_hero_ability( victimHeroAbilityName ) ); attacker specialistMedalAchievement(); attacker thread specialistStatAbilityUsage( 4, false ); abilityToCheck = attackerHeroAbility.name; } break; case "gadget_resurrect": { processScoreEvent( "resurrect_kill", attacker, victim, weapon ); attacker hero_ability_kill_event( attackerHeroAbility, get_equipped_hero_ability( victimHeroAbilityName ) ); attacker specialistMedalAchievement(); attacker thread specialistStatAbilityUsage( 4, false ); abilityToCheck = attackerHeroAbility.name; } break; case "gadget_camo": { processScoreEvent( "optic_camo_kill", attacker, victim, weapon ); attacker hero_ability_kill_event( attackerHeroAbility, get_equipped_hero_ability( victimHeroAbilityName ) ); attacker specialistMedalAchievement(); attacker thread specialistStatAbilityUsage( 4, false ); abilityToCheck = attackerHeroAbility.name; } break; case "gadget_clone": { processScoreEvent( "kill_enemy_while_using_psychosis", attacker, victim, weapon ); attacker hero_ability_kill_event( attackerHeroAbility, get_equipped_hero_ability( victimHeroAbilityName ) ); attacker specialistMedalAchievement(); attacker thread specialistStatAbilityUsage( 4, false ); abilityToCheck = attackerHeroAbility.name; } break; } if ( attackerIsRoulette && !victimIsThiefOrRoulette && isdefined( abilityToCheck ) && victimHeroAbilityName === abilityToCheck ) { processScoreEvent( "kill_enemy_with_their_hero_ability", attacker, victim, weapon ); } } if ( victimWasLungingWithArmBlades ) { processScoreEvent( "end_enemy_armblades_attack", attacker, victim, weapon ); } if ( isdefined( data.victimWeapon ) ) { killedHeroWeaponEnemy( attacker, victim, weapon, data.victimWeapon, victimGadgetPower, victimGadgetWasActiveLastDamage ); if ( data.victimWeapon.name == "minigun" ) { processScoreEvent( "killed_death_machine_enemy", attacker, victim, weapon ); } else if ( data.victimWeapon.name == "m32" ) { processScoreEvent( "killed_multiple_grenade_launcher_enemy", attacker, victim, weapon ); } // armblade is special case since the victimWeapon can be a primary or secondary weapon is_hero_armblade_and_active = ( isdefined( victim.heroweapon ) && victim.heroweapon.name == "hero_armblade" && victimGadgetWasActiveLastDamage ); if ( ( data.victimWeapon.inventorytype == "hero" || is_hero_armblade_and_active ) && victimGadgetPower < 100 ) { if ( victimHeroWeaponKillsThisActivation == 0 ) { attacker AddPlayerStat( "kill_before_specialist_weapon_use", 1 ); } if ( weapon.inventorytype == "hero" ) { attacker AddPlayerStat( "kill_specialist_with_specialist", 1 ); } // add here attacker_is_thief = ( isdefined( attacker.heroweapon ) && attacker.heroweapon.name == "gadget_thief" ); if ( !attacker_is_thief ) { processScoreEvent( "end_enemy_specialist_weapon", attacker, victim, weapon ); } } } if ( weapon.rootweapon.name == "frag_grenade" ) { attacker thread updateSingleFragMultiKill( victim, weapon, weaponClass, killstreak ); } attacker thread updateMultiKills( weapon, weaponClass, killstreak, victim ); if ( level.numKills == 1 ) { victim RecordKillModifier("firstblood"); processScoreEvent( "first_kill", attacker, victim, weapon ); } else { if ( isdefined( attacker.lastKilledBy ) ) { if ( attacker.lastKilledBy == victim ) { level.globalPaybacks++; processScoreEvent( "revenge_kill", attacker, victim, weapon ); attacker AddWeaponStat( weapon, "revenge_kill", 1 ); victim RecordKillModifier("revenge"); attacker.lastKilledBy = undefined; } } if ( victim killstreaks::is_an_a_killstreak() ) { level.globalBuzzKills++; processScoreEvent( "stop_enemy_killstreak", attacker, victim, weapon ); victim RecordKillModifier("buzzkill"); } if ( isdefined( victim.lastManSD ) && victim.lastManSD == true ) { processScoreEvent( "final_kill_elimination", attacker, victim, weapon ); if ( isdefined( attacker.lastManSD ) && attacker.lastManSD == true ) { processScoreEvent( "elimination_and_last_player_alive", attacker, victim, weapon ); } } } if ( is_weapon_valid( meansOfDeath, weapon, weaponClass, killstreak ) ) { if ( isdefined( victim.vAttackerOrigin ) ) attackerOrigin = victim.vAttackerOrigin; else attackerOrigin = attacker.origin; distToVictim = distanceSquared( victim.origin, attackerOrigin ); weap_min_dmg_range = get_distance_for_weapon( weapon, weaponClass ); if ( distToVictim > weap_min_dmg_range ) { attacker challenges::longDistanceKillMP( weapon ); if ( weapon.rootweapon.name == "hatchet" ) { attacker challenges::longDistanceHatchetKill(); } processScoreEvent( "longshot_kill", attacker, victim, weapon ); attacker.pers["longshots"]++; attacker.longshots = attacker.pers["longshots"]; victim RecordKillModifier("longshot"); } // Record kill distances and num of entries killdistance = distance( victim.origin, attackerOrigin ); attacker.pers["kill_distances"] += killdistance; attacker.pers["num_kill_distance_entries"]++; } if ( isAlive( attacker ) ) { if ( attacker.health < ( attacker.maxHealth * 0.35 ) ) { attacker.lastKillWhenInjured = time; processScoreEvent( "kill_enemy_when_injured", attacker, victim, weapon ); attacker AddWeaponStat( weapon, "kill_enemy_when_injured", 1 ); if ( attacker util::has_toughness_perk_purchased_and_equipped() ) { attacker AddPlayerStat( "perk_bulletflinch_kills", 1 ); } } } else { if ( isdefined( attacker.deathtime ) && ( ( attacker.deathtime + 800 ) < time ) && !attacker IsInVehicle() ) { level.globalAfterlifes++; processScoreEvent( "kill_enemy_after_death", attacker, victim, weapon ); victim RecordKillModifier("posthumous"); } } if( attacker.cur_death_streak >= 3 ) { level.globalComebacks++; processScoreEvent( "comeback_from_deathstreak", attacker, victim, weapon ); victim RecordKillModifier("comeback"); } if ( isdefined( victim.lastMicrowavedBy ) ) { foreach( beingMicrowavedBy in victim.beingMicrowavedBy ) { if ( isdefined( beingMicrowavedBy ) && ( attacker util::IsEnemyPlayer( beingMicrowavedBy ) == false ) ) { if ( beingMicrowavedBy != attacker ) { scoreGiven = processScoreEvent( "microwave_turret_assist", beingMicrowavedBy, victim, weapon ); if ( isdefined ( scoreGiven ) ) { beingMicrowavedBy challenges::earnedMicrowaveAssistScore( scoreGiven ); } } else { attackerMicrowavedVictim = true; } } } if ( attackerMicrowavedVictim === true && weapon.name != "microwave_turret" ) { attacker challenges::killWhileDamagingWithHPM(); } } if ( weapon_utils::isMeleeMOD( meansOfDeath ) && !weapon.isRiotShield ) { // "stabs" are now "melees" attacker.pers["stabs"]++; attacker.stabs = attacker.pers["stabs"]; if ( meansOfDeath == "MOD_MELEE_WEAPON_BUTT" && weapon.name != "ball" ) { processScoreEvent( "kill_enemy_with_gunbutt", attacker, victim, weapon ); } else if ( weapon_utils::isPunch( weapon ) ) { processScoreEvent( "kill_enemy_with_fists", attacker, victim, weapon ); } else if ( weapon_utils::isNonBareHandsMelee( weapon ) ) { vAngles = victim.anglesOnDeath[1]; pAngles = attacker.anglesOnKill[1]; angleDiff = AngleClamp180( vAngles - pAngles ); if ( angleDiff > -30 && angleDiff < 70 ) { level.globalBackstabs++; processScoreEvent( "backstabber_kill", attacker, victim, weapon ); weaponPickedUp = false; if( isdefined( attacker.pickedUpWeapons ) && isdefined( attacker.pickedUpWeapons[weapon] ) ) { weaponPickedUp = true; } attacker AddWeaponStat( weapon, "backstabber_kill", 1, attacker.class_num, weaponPickedUp, undefined, attacker.primaryLoadoutGunSmithVariantIndex, attacker.secondaryLoadoutGunSmithVariantIndex ); attacker.pers["backstabs"]++; attacker.backstabs = attacker.pers["backstabs"]; } } } else { if ( isdefined ( victim.firstTimeDamaged ) && victim.firstTimeDamaged == time && !( isdefined( weapon.isHeroWeapon ) && weapon.isHeroWeapon ) ) { if ( attackerShotVictim ) { attacker thread updateOneShotMultiKills( victim, weapon, victim.firstTimeDamaged ); attacker AddWeaponStat( weapon, "kill_enemy_one_bullet", 1 ); } } } if ( isdefined( attacker.tookWeaponFrom ) && isdefined( attacker.tookWeaponFrom[ weapon ] ) && isdefined( attacker.tookWeaponFrom[ weapon ].previousOwner ) ) { pickedUpWeapon = attacker.tookWeaponFrom[ weapon ]; if ( pickedUpWeapon.previousOwner == victim ) { processScoreEvent( "kill_enemy_with_their_weapon", attacker, victim, weapon ); attacker AddWeaponStat( weapon, "kill_enemy_with_their_weapon", 1 ); if ( isdefined( pickedUpWeapon.sWeapon ) && isdefined( pickedUpWeapon.sMeansOfDeath ) && weapon_utils::isMeleeMOD( pickedUpWeapon.sMeansOfDeath ) ) { foreach( meleeWeapon in level.meleeWeapons ) { if ( weapon != meleeWeapon && pickedUpWeapon.sWeapon.rootweapon == meleeWeapon ) { attacker AddWeaponStat( meleeWeapon, "kill_enemy_with_their_weapon", 1 ); break; // once found and handled, no need to continue } } } } } if ( wasDefusing ) { processScoreEvent( "killed_bomb_defuser", attacker, victim, weapon ); } else if ( wasPlanting ) { processScoreEvent( "killed_bomb_planter", attacker, victim, weapon ); } heroWeaponKill( attacker, victim, weapon ); } // end if ( !isdefined( killstreak ) ) specificWeaponKill( attacker, victim, weapon, killstreak, inflictor ); if( isdefined( level.vtol ) && isdefined( level.vtol.owner ) && ( weapon.name == "helicopter_gunner_turret_secondary" || weapon.name == "helicopter_gunner_turret_tertiary" ) ) { attacker addplayerstat( "kill_as_support_gunner", 1 ); processScoreEvent( "mothership_assist_kill", level.vtol.owner, victim, weapon ); } if ( isdefined( attackerInVehicleArchetype ) ) { if ( attackerInVehicleArchetype == "siegebot" ) { if ( meansOfDeath == "MOD_CRUSH" ) { processScoreEvent( "kill_enemy_with_siegebot_crush", attacker, victim, weapon ); } if(!isdefined(attacker.siegebot_kills))attacker.siegebot_kills=0; attacker.siegebot_kills++; if ( attacker.siegebot_kills % 5 == 0 ) { processScoreEvent( "siegebot_killstreak_5", attacker, victim, weapon ); } } } switch ( weapon.rootweapon.name ) { case "hatchet": { attacker.pers["tomahawks"]++; attacker.tomahawks = attacker.pers["tomahawks"]; processScoreEvent( "hatchet_kill", attacker, victim, weapon ); if ( isdefined( data.victim.explosiveInfo["projectile_bounced"] ) && data.victim.explosiveInfo["projectile_bounced"] == true ) { level.globalBankshots++; processScoreEvent( "bounce_hatchet_kill", attacker, victim, weapon ); } } break; case "supplydrop": case "inventory_supplydrop": case "supplydrop_marker": case "inventory_supplydrop_marker": { if ( meansOfDeath == "MOD_HIT_BY_OBJECT" || meansOfDeath == "MOD_CRUSH" ) { processScoreEvent( "kill_enemy_with_care_package_crush", attacker, victim, weapon ); } else { processScoreEvent( "kill_enemy_with_hacked_care_package", attacker, victim, weapon ); } } break; } if( isdefined( killstreak ) ) { attacker thread updateMultiKills( weapon, weaponClass, killstreak, victim ); victim RecordKillModifier("killstreak"); } attacker.cur_death_streak = 0; attacker disabledeathstreak(); } function get_equipped_hero_ability( ability_name ) { if ( !isdefined( ability_name ) ) return undefined; return GetWeapon( ability_name ); } function heroWeaponKill( attacker, victim, weapon ) { if ( !isdefined( weapon ) ) { return; } if ( isdefined( weapon.isHeroWeapon ) && !weapon.isHeroWeapon ) { return; } switch( weapon.name ) { case "hero_minigun": case "hero_minigun_body3": event = "minigun_kill"; break; case "hero_flamethrower": event = "flamethrower_kill"; break; case "hero_lightninggun": case "hero_lightninggun_arc": event = "lightninggun_kill"; break; case "hero_chemicalgelgun": case "hero_firefly_swarm": event = "gelgun_kill"; break; case "hero_pineapplegun": case "hero_pineapple_grenade": event = "pineapple_kill"; break; case "hero_armblade": event = "armblades_kill"; break; case "hero_bowlauncher": case "hero_bowlauncher2": case "hero_bowlauncher3": case "hero_bowlauncher4": event = "bowlauncher_kill"; break; case "hero_gravityspikes": event = "gravityspikes_kill"; break; case "hero_annihilator": event = "annihilator_kill"; break; default: return; } processScoreEvent( event, attacker, victim, weapon ); } function killedHeroWeaponEnemy( attacker, victim, weapon, victim_weapon, victim_gadget_power, victimGadgetWasActiveLastDamage ) { if ( !isdefined( victim_weapon ) ) { return; } if ( victim_gadget_power >= 100 ) return; switch( victim_weapon.name ) { case "hero_minigun": case "hero_minigun_body3": event = "killed_minigun_enemy"; break; case "hero_flamethrower": event = "killed_flamethrower_enemy"; break; case "hero_lightninggun": case "hero_lightninggun_arc": event = "killed_lightninggun_enemy"; break; case "hero_chemicalgelgun": event = "killed_gelgun_enemy"; break; case "hero_pineapplegun": event = "killed_pineapple_enemy"; break; case "hero_bowlauncher": case "hero_bowlauncher2": case "hero_bowlauncher3": case "hero_bowlauncher4": event = "killed_bowlauncher_enemy"; break; case "hero_gravityspikes": event = "killed_gravityspikes_enemy"; break; case "hero_annihilator": event = "killed_annihilator_enemy"; break; default: if ( isdefined( victim.heroWeapon ) && victim.heroWeapon.name == "hero_armblade" && victimGadgetWasActiveLastDamage ) { event = "killed_armblades_enemy"; } else { return; } } processScoreEvent( event, attacker, victim, weapon ); attacker util::player_contract_event( "killed_hero_weapon_enemy" ); } function specificWeaponKill( attacker, victim, weapon, killstreak, inflictor ) { switchWeapon = weapon.name; if( isdefined( killstreak ) ) { switchWeapon = killstreak; } switch( switchWeapon ) { case "remote_missile": case "inventory_remote_missile": event = "remote_missile_kill"; break; case "autoturret": case "inventory_autoturret": event = "sentry_gun_kill"; break; case "planemortar": case "inventory_planemortar": event = "plane_mortar_kill"; break; case "ai_tank_drop": case "inventory_ai_tank_drop": event = "aitank_kill"; if ( isdefined( inflictor ) && isdefined( inflictor.controlled ) ) { if ( inflictor.controlled == true ) { attacker addPlayerStat( "kill_with_controlled_ai_tank", 1 ); } } break; case "microwave_turret": case "inventory_microwave_turret": case "microwaveturret": case "inventory_microwaveturret": event = "microwave_turret_kill"; break; case "raps": case "inventory_raps": event = "raps_kill"; break; case "sentinel": case "inventory_sentinel": { event = "sentinel_kill"; if ( isdefined( inflictor ) && isdefined( inflictor.controlled ) ) { if ( inflictor.controlled == true ) { attacker addPlayerStat( "kill_with_controlled_sentinel", 1 ); } } } break; case "combat_robot": case "inventory_combat_robot": event = "combat_robot_kill"; break; case "rcbomb": case "inventory_rcbomb": event = "hover_rcxd_kill"; break; case "helicopter_gunner": case "helicopter_gunner_assistant": case "inventory_helicopter_gunner": case "inventory_helicopter_gunner_assistant": event = "vtol_mothership_kill"; break; case "helicopter_comlink": case "inventory_helicopter_comlink": event = "helicopter_comlink_kill"; break; case "drone_strike": case "inventory_drone_strike": event = "drone_strike_kill"; break; case "dart": case "inventory_dart": case "dart_turret": event = "dart_kill"; break; default: return; } if ( isdefined( inflictor ) ) { if ( isdefined( inflictor.killstreak_id ) && isdefined( level.matchRecorderKillstreakKills[inflictor.killstreak_id] ) ) { level.matchRecorderKillstreakKills[inflictor.killstreak_id]++; } else if ( isdefined( inflictor.killcament ) && isdefined( inflictor.killcament.killstreak_id ) && isdefined( level.matchRecorderKillstreakKills[inflictor.killcament.killstreak_id] ) ) { level.matchRecorderKillstreakKills[inflictor.killcament.killstreak_id]++; } } processScoreEvent( event, attacker, victim, weapon ); } function multiKill( killCount, weapon ) { assert( killCount > 1 ); self challenges::multiKill( killCount, weapon ); if ( killCount > 8 ) { processScoreEvent( "multikill_more_than_8", self, undefined, weapon ); } else { processScoreEvent( "multikill_" + killCount, self, undefined, weapon ); } if ( killCount > 2 ) { if ( isdefined( self.challenge_objectiveDefensiveKillcount ) && self.challenge_objectiveDefensiveKillcount > 0 ) { self.challenge_objectiveDefensiveTripleKillMedalOrBetterEarned = true; } } self RecordMultiKill( killCount ); } function multiHeroAbilityKill( killCount, weapon ) { if ( killcount > 1 ) { self addPlayerStat( "multikill_2_with_heroability", int( killCount / 2 ) ); self AddWeaponStat( weapon, "heroability_doublekill", int( killCount / 2 ) ); self addPlayerStat( "multikill_3_with_heroability", int( killCount / 3 ) ); self AddWeaponStat( weapon, "heroability_triplekill", int( killCount / 3 ) ); } } function is_weapon_valid( meansOfDeath, weapon, weaponClass, killstreak ) { valid_weapon = false; if ( isdefined( killstreak ) ) valid_weapon = false; else if ( get_distance_for_weapon( weapon, weaponClass ) == 0 ) valid_weapon = false; else if ( meansOfDeath == "MOD_PISTOL_BULLET" || meansOfDeath == "MOD_RIFLE_BULLET" ) valid_weapon = true; else if ( meansOfDeath == "MOD_HEAD_SHOT" ) valid_weapon = true; else if ( weapon.rootweapon.name == "hatchet" && meansOfDeath == "MOD_IMPACT" ) valid_weapon = true; else { baseWeapon = challenges::getBaseWeapon( weapon ); if ( baseWeapon == level.weaponSpecialCrossbow && meansOfDeath == "MOD_IMPACT" ) valid_weapon = true; else if ( baseWeapon == level.weaponBallisticKnife && meansOfDeath == "MOD_IMPACT" ) valid_weapon = true; else if ( ( baseWeapon.forceDamageHitLocation || baseWeapon == level.weaponShotgunEnergy || baseWeapon == level.weaponSpecialDiscGun ) && meansofDeath == "MOD_PROJECTILE" ) valid_weapon = true; } return valid_weapon; } function updateSingleFragMultiKill( victim, weapon, weaponClass, killstreak ) { self endon ( "disconnect" ); level endon ( "game_ended" ); self notify ( "updateSingleFragMultiKill" ); self endon ( "updateSingleFragMultiKill" ); if ( !isdefined (self.recent_SingleFragMultiKill) || self.recent_SingleFragMultiKillID != victim.explosiveinfo["damageid"] ) self.recent_SingleFragMultiKill = 0; self.recent_SingleFragMultiKillID = victim.explosiveinfo["damageid"]; self.recent_SingleFragMultiKill++; self waitTillTimeoutOrDeath( 0.05 ); if ( self.recent_SingleFragMultiKill >= 2 ) { processScoreEvent( "frag_multikill", self, victim, weapon ); } self.recent_SingleFragMultiKill = 0; } function updatemultikills( weapon, weaponClass, killstreak, victim ) { self endon ( "disconnect" ); level endon ( "game_ended" ); self notify ( "updateRecentKills" ); self endon ( "updateRecentKills" ); baseWeaponParam = [[ level.get_base_weapon_param ]]( weapon ); baseWeapon = GetWeapon( GetRefFromItemIndex( GetBaseWeaponItemIndex( baseWeaponParam ) ) ); if ( !isdefined( self.recentKillVariables ) ) { self resetRecentKillVariables(); } if ( !isdefined( self.recentKillCountWeapon ) || self.recentKillCountWeapon != baseWeapon ) { self.recentKillCountSameWeapon = 0; self.recentKillCountWeapon = baseWeapon; } if (!isdefined(killstreak)) { self.recentKillCountSameWeapon++; self.recentKillCount++; } if ( isdefined( weaponClass ) ) { if ( weaponClass == "weapon_lmg" || weaponClass == "weapon_smg" ) { if ( self PlayerAds() < 1.0 ) { self.recent_LMG_SMG_KillCount++; } } if ( weaponClass == "weapon_grenade" ) { self.recentLethalCount++; } } if ( weapon.name == "satchel_charge" ) { self.recentC4KillCount++; } if ( isdefined( level.killstreakWeapons ) && isdefined( level.killstreakWeapons[weapon] ) ) { switch( level.killstreakWeapons[weapon] ) { case "remote_missile": case "inventory_remote_missile": { self.recentRemoteMissileCount++; } break; case "rcbomb": case "inventory_rcbomb": { self.recentRCBombCount++; } break; } } if ( isdefined( weapon.isHeroWeapon ) && weapon.isHeroWeapon == true ) { self.recentHeroKill = getTime(); self.recentHeroWeaponKillCount++; if ( isdefined( victim ) ) { self.recentHeroWeaponVictims[ victim GetEntityNumber() ] = victim; } switch( weapon.name ) { case "hero_annihilator": self.recentAnihilatorCount++; break; case "hero_minigun": case "hero_minigun_body3": self.recentMiniGunCount++; break; case "hero_bowlauncher": case "hero_bowlauncher2": case "hero_bowlauncher3": case "hero_bowlauncher4": self.recentBowLauncherCount++; break; case "hero_flamethrower": self.recentFlameThrowerCount++; break; case "hero_gravityspikes": self.recentGravitySpikesCount++; break; case "hero_lightninggun": case "hero_lightninggun_arc": self.recentLightningGunCount++; break; case "hero_pineapplegun": case "hero_pineapple_grenade": self.recentPineappleGunCount++; break; case "hero_chemicalgun": case "hero_firefly_swarm": self.recentGelGunCount++; break; case "hero_armblade": self.recentArmBladeCount++; break; } } if ( isdefined( self.heroAbility ) && isdefined( victim ) ) { if ( victim ability_player::gadget_CheckHeroAbilityKill( self ) ) { if ( isdefined( self.recentHeroAbilityKillWeapon ) && self.recentHeroAbilityKillWeapon != self.heroAbility ) { self.recentHeroAbilityKillCount = 0; } self.recentHeroAbilityKillWeapon = self.heroAbility; self.recentHeroAbilityKillCount++; } } if ( isdefined ( killstreak ) ) { switch( killstreak ) { case "remote_missile": self.recentRemoteMissileKillCount++; break; case "rcbomb": self.recentRCBombKillCount++; break; case "inventory_m32": case "m32": self.recentMGLKillCount++; break; } } if ( self.recentKillCountSameWeapon == 2 ) { self AddWeaponStat( weapon, "multikill_2", 1 ); } else if ( self.recentKillCountSameWeapon == 3 ) { self AddWeaponStat( weapon, "multikill_3", 1 ); } self waitTillTimeoutOrDeath( 4.0 ); if ( self.recent_LMG_SMG_KillCount >= 3 ) self challenges::multi_LMG_SMG_Kill(); if ( self.recentRCBombKillCount >= 2 ) self challenges::multi_RCBomb_Kill(); if ( self.recentMGLKillCount >= 3 ) self challenges::multi_MGL_Kill(); if ( self.recentRemoteMissileKillCount >= 3 ) self challenges::multi_RemoteMissile_Kill(); if ( self.recentHeroWeaponKillCount > 1 ) { self scoreevents::hero_weapon_multikill_event( self.recentHeroWeaponKillCount, weapon ); } if ( self.recentHeroWeaponKillCount > 5 ) { ArrayRemoveValue( self.recentHeroWeaponVictims, undefined ); if ( self.recentHeroWeaponVictims.size > 5 ) { self addPlayerStat( "kill_entire_team_with_specialist_weapon", 1 ); } } if ( self.recentAnihilatorCount >= 3 ) { processScoreEvent( "annihilator_multikill", self, undefined, weapon ); self multikillMedalAchievement(); } else if ( self.recentAnihilatorCount == 2 ) { processScoreEvent( "annihilator_multikill_2", self, undefined, weapon ); self multikillMedalAchievement(); } if ( self.recentMiniGunCount >= 3 ) { processScoreEvent( "minigun_multikill", self, undefined, weapon ); self multikillMedalAchievement(); } else if ( self.recentMiniGunCount == 2 ) { processScoreEvent( "minigun_multikill_2", self, undefined, weapon ); self multikillMedalAchievement(); } if ( self.recentBowLauncherCount >= 3 ) { processScoreEvent( "bowlauncher_multikill", self, undefined, weapon ); self multikillMedalAchievement(); } else if ( self.recentBowLauncherCount == 2 ) { processScoreEvent( "bowlauncher_multikill_2", self, undefined, weapon ); self multikillMedalAchievement(); } if ( self.recentFlameThrowerCount >= 3 ) { processScoreEvent( "flamethrower_multikill", self, undefined, weapon ); self multikillMedalAchievement(); } else if ( self.recentFlameThrowerCount == 2 ) { processScoreEvent( "flamethrower_multikill_2", self, undefined, weapon ); self multikillMedalAchievement(); } if ( self.recentGravitySpikesCount >= 3 ) { processScoreEvent( "gravityspikes_multikill", self, undefined, weapon ); self multikillMedalAchievement(); } else if ( self.recentGravitySpikesCount == 2 ) { processScoreEvent( "gravityspikes_multikill_2", self, undefined, weapon ); self multikillMedalAchievement(); } if ( self.recentLightningGunCount >= 3 ) { processScoreEvent( "lightninggun_multikill", self, undefined, weapon ); self multikillMedalAchievement(); } else if ( self.recentLightningGunCount == 2 ) { processScoreEvent( "lightninggun_multikill_2", self, undefined, weapon ); self multikillMedalAchievement(); } if ( self.recentPineappleGunCount >= 3 ) { processScoreEvent( "pineapple_multikill", self, undefined, weapon ); self multikillMedalAchievement(); } else if ( self.recentPineappleGunCount == 2 ) { processScoreEvent( "pineapple_multikill_2", self, undefined, weapon ); self multikillMedalAchievement(); } if ( self.recentGelGunCount >= 3 ) { processScoreEvent( "gelgun_multikill", self, undefined, weapon ); self multikillMedalAchievement(); } else if ( self.recentGelGunCount == 2 ) { processScoreEvent( "gelgun_multikill_2", self, undefined, weapon ); self multikillMedalAchievement(); } if ( self.recentArmBladeCount >= 3 ) { processScoreEvent( "armblades_multikill", self, undefined, weapon ); self multikillMedalAchievement(); } else if ( self.recentArmBladeCount == 2 ) { processScoreEvent( "armblades_multikill_2", self, undefined, weapon ); self multikillMedalAchievement(); } if ( self.recentC4KillCount >= 2 ) { processScoreEvent( "c4_multikill", self, undefined, weapon ); } if ( self.recentRemoteMissileCount >= 3 ) { self addPlayerStat( "multikill_3_remote_missile", 1 ); } if ( self.recentRCBombCount >= 2 ) { self addPlayerStat( "multikill_2_rcbomb", 1 ); } if ( self.recentLethalCount >= 2 ) { if ( !isdefined( self.pers["challenge_kills_double_kill_lethal"] ) ) { self.pers["challenge_kills_double_kill_lethal"] = 0; } self.pers["challenge_kills_double_kill_lethal"]++; if ( self.pers["challenge_kills_double_kill_lethal"] >= 3 ) { self addPlayerStat( "kills_double_kill_3_lethal", 1 ); } } if ( self.recentKillCount > 1 ) self multiKill( self.recentKillCount, weapon ); if ( self.recentHeroAbilityKillCount > 1 ) { self multiHeroAbilityKill( self.recentHeroAbilityKillCount, self.recentHeroAbilityKillWeapon ); self scoreevents::hero_ability_multikill_event( self.recentHeroAbilityKillCount, self.recentHeroAbilityKillWeapon ); } self resetRecentKillVariables(); } function resetRecentKillVariables() { self.recent_LMG_SMG_KillCount = 0; self.recentAnihilatorCount = 0; self.recentArmBladeCount = 0; self.recentBowLauncherCount = 0; self.recentC4KillCount = 0; self.recentFlameThrowerCount = 0; self.recentGelGunCount = 0; self.recentGravitySpikesCount = 0; self.recentHeroAbilityKillCount = 0; self.recentHeroWeaponKillCount = 0; self.recentHeroWeaponVictims = []; self.recentKillCount = 0; self.recentKillCountSameWeapon = 0; self.recentKillCountWeapon = undefined; self.recentLethalCount = 0; self.recentLightningGunCount = 0; self.recentMGLKillCount = 0; self.recentMiniGunCount = 0; self.recentPineappleGunCount = 0; self.recentRCBombCount = 0; self.recentRCBombKillCount = 0; self.recentRemoteMissileCount = 0; self.recentRemoteMissileKillCount = 0; self.recentKillVariables = true; } function waitTillTimeoutOrDeath( timeout ) { self endon( "death" ); wait( timeout ); } function updateoneshotmultikills( victim, weapon, firstTimeDamaged ) { self endon( "death" ); self endon( "disconnect" ); self notify( "updateoneshotmultikills" + firstTimeDamaged ); self endon( "updateoneshotmultikills" + firstTimeDamaged ); if ( !isdefined( self.oneshotmultikills ) || firstTimeDamaged > (isdefined(self.oneshotmultikillsdamagetime)?self.oneshotmultikillsdamagetime:0) ) { self.oneshotmultikills = 0; } self.oneshotmultikills++; self.oneshotmultikillsdamagetime = firstTimeDamaged; wait( 1.0 ); if ( self.oneshotmultikills > 1 ) { processScoreEvent( "kill_enemies_one_bullet", self, victim, weapon ); } else { processScoreEvent( "kill_enemy_one_bullet", self, victim, weapon ); } self.oneshotmultikills = 0; } function get_distance_for_weapon( weapon, weaponClass ) { // this is special for the long shot medal // need to do this on a per weapon category basis, to better control it distance = 0; if( !isdefined( weaponClass ) ) { return 0; } // special case weapons if ( weapon.rootweapon.name == "pistol_shotgun" ) { weaponClass = "weapon_cqb"; // per design } switch ( weaponClass ) { case "weapon_smg": distance = 1500 * 1500; break; case "weapon_assault": distance = 1750 * 1750; break; case "weapon_lmg": distance = 1750 * 1750; break; case "weapon_sniper": distance = 2000 * 2000; break; case "weapon_pistol": distance = 1000 * 1000; break; case "weapon_cqb": distance = 550 * 550; break; case "weapon_special": { baseWeapon = challenges::getBaseWeapon( weapon ); if ( baseWeapon == level.weaponBallisticKnife || baseWeapon == level.weaponSpecialCrossbow || baseWeapon == level.weaponSpecialDiscGun ) { distance = 1500 * 1500; } } break; case "weapon_grenade": if ( weapon.rootweapon.name == "hatchet" ) { distance = 1500 * 1500; } break; default: distance = 0; break; } return distance; } function onGameEnd( data ) { player = data.player; winner = data.winner; if ( isdefined( winner ) ) { if ( level.teambased ) { if ( winner != "tie" && player.team == winner ) { processScoreEvent( "won_match", player ); return; } } else { placement = level.placement["all"]; topThreePlayers = min( 3, placement.size ); for ( index = 0; index < topThreePlayers; index++ ) { if ( level.placement["all"][index] == player ) { processScoreEvent( "won_match", player ); return; } } } } processScoreEvent( "completed_match", player ); } function specialistMedalAchievement() { if( level.rankedMatch ) { if ( !isdefined( self.pers["specialistMedalAchievement"] ) ) { self.pers["specialistMedalAchievement"] = 0; } self.pers["specialistMedalAchievement"]++; if ( self.pers["specialistMedalAchievement"] == 5 ) { self GiveAchievement( "MP_SPECIALIST_MEDALS" ); // Get 5 Medals based on a Specialist Ability in a single game. } self util::player_contract_event( "earned_specialist_ability_medal" ); } } function specialistStatAbilityUsage( usageSingleGame, multiTrackPerLife ) { self endon ( "disconnect" ); level endon ( "game_ended" ); self notify ( "updatethread specialistStatAbilityUsage" ); self endon ( "updatethread specialistStatAbilityUsage" ); isRoulette = ( self.isRoulette === true ); if ( isdefined( self.heroAbility ) && !isRoulette ) { self addWeaponStat( self.heroAbility, "combatRecordStat", 1 ); } self challenges::processSpecialistChallenge( "kills_ability" ); if ( !isdefined( self.pers["specialistUsagePerGame"] ) ) { self.pers["specialistUsagePerGame"] = 0; } self.pers["specialistUsagePerGame"]++; if ( self.pers["specialistUsagePerGame"] >= usageSingleGame ) { self challenges::processSpecialistChallenge( "kill_one_game_ability" ); self.pers["specialistUsagePerGame"] = 0; } if ( multiTrackPerLife ) { self.pers["specialistStatAbilityUsage"]++; if ( self.pers["specialistStatAbilityUsage"] >= 2 ) { self challenges::processSpecialistChallenge( "multikill_ability" ); } } else { if ( !isdefined( self.specialistStatAbilityUsage ) ) { self.specialistStatAbilityUsage = 0; } self.specialistStatAbilityUsage++; self waitTillTimeoutOrDeath( 4.0 ); if ( self.specialistStatAbilityUsage >= 2 ) { self challenges::processSpecialistChallenge( "multikill_ability" ); } self.specialistStatAbilityUsage = 0; } } function multikillMedalAchievement() { if ( level.rankedMatch ) { self GiveAchievement( "MP_MULTI_KILL_MEDALS" ); // Get a Specialist-based medal that requires 3 or more rapid kills while using any Specialist Weapon. self challenges::processSpecialistChallenge( "multikill_weapon" ); } }