#using scripts\codescripts\struct; #using scripts\shared\callbacks_shared; #using scripts\shared\challenges_shared; #using scripts\shared\drown; #using scripts\shared\scoreevents_shared; #using scripts\shared\system_shared; #using scripts\shared\util_shared; #using scripts\shared\weapons\_weapon_utils; #using scripts\mp\_challenges; #using scripts\mp\gametypes\_loadout; #using scripts\mp\_util; // for blackjack challenge: kills while using a specialist weapon or ability // for blackjack challenge: count of unique specialist weapons or abilities used to kill #namespace blackjack_challenges; function autoexec __init__sytem__() { system::register("blackjack_challenges",&__init__,undefined,undefined); } function __init__() { callback::on_start_gametype( &start_gametype ); } function start_gametype() { if ( !isdefined( level.ChallengesCallbacks ) ) { level.ChallengesCallbacks = []; } waittillframeend; if ( challenges::canProcessChallenges() ) { challenges::registerChallengesCallback( "playerKilled",&challenge_kills ); challenges::registerChallengesCallback( "roundEnd",&challenge_round_ended ); challenges::registerChallengesCallback( "gameEnd",&challenge_game_ended ); scoreevents::register_hero_ability_kill_event( &on_hero_ability_kill ); } callback::on_connect( &on_player_connect ); } function on_player_connect() { player = self; if ( challenges::canProcessChallenges() ) { specialistIndex = player GetSpecialistIndex(); isBlackjack = ( specialistIndex == 9 ); if ( isBlackjack ) { player thread track_blackjack_consumable(); if ( !isdefined( self.pers[ "blackjack_challenge_active" ] ) ) { remaining_time = player ConsumableGet( "blackjack", "awarded" ) - player ConsumableGet( "blackjack", "consumed" ); if ( remaining_time > 0 ) { special_card_earned = player get_challenge_stat( "special_card_earned" ); if ( !special_card_earned ) { player.pers[ "blackjack_challenge_active" ] = true; player.pers[ "blackjack_unique_specialist_kills" ] = 0; player.pers[ "blackjack_specialist_kills" ] = 0; player.pers[ "blackjack_unique_weapon_mask" ] = 0; player.pers[ "blackjack_unique_ability_mask" ] = 0; } } } } } } function is_challenge_active() { return ( self.pers[ "blackjack_challenge_active" ] === true ); } function on_hero_ability_kill( ability, victimAbility ) { player = self; if ( !isdefined( player ) || !isplayer( player ) ) return; if ( !isdefined( player.isRoulette ) || !player.isRoulette ) return; if ( player is_challenge_active() ) { player.pers[ "blackjack_specialist_kills" ]++; currentHeroAbilityMask = player.pers[ "blackjack_unique_ability_mask" ]; heroAbilityMask = get_hero_ability_mask( ability ); newHeroAbilityMask = heroAbilityMask | currentHeroAbilityMask; if ( newHeroAbilityMask != currentHeroAbilityMask ) { player.pers[ "blackjack_unique_specialist_kills" ]++; player.pers[ "blackjack_unique_ability_mask" ] = newHeroAbilityMask; } player check_blackjack_challenge(); } } /# function debug_print_already_earned() { if ( GetDvarInt( "scr_blackjack_sidebet_debug", 0 ) == 0 ) return; IPrintLn( "Blackjack Side Bet already earned this game." ); } #/ /# function debug_print_kill_info() { if ( GetDvarInt( "scr_blackjack_sidebet_debug", 0 ) == 0 ) return; player = self; IPrintLn( "Blackjack Side Bet kills: " + player.pers[ "blackjack_specialist_kills" ] + " uniques: " + player.pers[ "blackjack_unique_specialist_kills" ] ); } #/ /# function debug_print_earned() { if ( GetDvarInt( "scr_blackjack_sidebet_debug", 0 ) == 0 ) return; IPrintLn( "Blackjack Side Bet earned!!!" ); } #/ function check_blackjack_challenge() { player = self; /# debug_print_kill_info(); #/ special_card_earned = player get_challenge_stat( "special_card_earned" ); if ( special_card_earned ) { /# debug_print_already_earned(); #/ return; } if ( ( player.pers[ "blackjack_specialist_kills" ] >= 4 ) && ( player.pers[ "blackjack_unique_specialist_kills" ] >= 2 ) ) { player set_challenge_stat( "special_card_earned", 1 ); player AddPlayerStat( "blackjack_challenge", 1 ); /# debug_print_earned(); #/ } } function challenge_kills( data ) { attackerisThief = data.attackerIsThief; attackerIsRoulette = data.attackerIsRoulette; attackerIsThiefOrRoulette = attackerisThief || attackerIsRoulette; if ( !attackerIsThiefOrRoulette ) return; victim = data.victim; attacker = data.attacker; player = attacker; weapon = data.weapon; if ( !isdefined( weapon ) || ( weapon == level.weaponNone ) ) return; if ( !isdefined( player ) || !isplayer( player ) ) return; if ( attackerIsThief ) { if ( weapon.isHeroWeapon === true ) { if ( player is_challenge_active() ) { player.pers[ "blackjack_specialist_kills" ]++; currentHeroWeaponMask = player.pers[ "blackjack_unique_weapon_mask" ]; heroWeaponMask = get_hero_weapon_mask( attacker, weapon ); newHeroWeaponMask = heroWeaponMask | currentHeroWeaponMask; if ( newHeroWeaponMask != currentHeroWeaponMask ) { player.pers[ "blackjack_unique_specialist_kills" ] += 1; player.pers[ "blackjack_unique_weapon_mask" ] = newHeroWeaponMask; } player check_blackjack_challenge(); } } } // ability kills are handled as events fired from score events // if ( attackerIsRoulette ) // { // } } function get_challenge_stat( stat_name ) { return self GetDStat( "tenthspecialistcontract", stat_name ); } function set_challenge_stat( stat_name, stat_value ) { return self SetDStat( "tenthspecialistcontract", stat_name, stat_value ); } function get_hero_weapon_mask( attacker, weapon ) { if ( !isdefined( weapon ) ) return 0; if ( isdefined( weapon.isHeroWeapon ) && !weapon.isHeroWeapon ) return 0; switch( weapon.name ) { case "hero_minigun": case "hero_minigun_body3": return 1; // note: heroWeaponMask needs to stay unique and consistent for function across TUs and FFOTDs break; case "hero_flamethrower": return 1 << 1; break; case "hero_lightninggun": case "hero_lightninggun_arc": return 1 << 2; break; case "hero_chemicalgelgun": case "hero_firefly_swarm": return 1 << 3; break; case "hero_pineapplegun": case "hero_pineapple_grenade": return 1 << 4; break; case "hero_armblade": return 1 << 5; break; case "hero_bowlauncher": case "hero_bowlauncher2": case "hero_bowlauncher3": case "hero_bowlauncher4": return 1 << 6; break; case "hero_gravityspikes": return 1 << 7; break; case "hero_annihilator": return 1 << 8; break; default: return 0; } } function get_hero_ability_mask( ability ) { if ( !isdefined( ability ) ) return 0; switch( ability.name ) { case "gadget_clone": return 1; // note: heroAbilityMask needs to stay unique and consistent for functions across TUs and FFOTDs break; case "gadget_heat_wave": return 1 << 1; break; case "gadget_flashback": return 1 << 2; break; case "gadget_resurrect": return 1 << 3; break; case "gadget_armor": return 1 << 4; break; case "gadget_camo": return 1 << 5; break; case "gadget_vision_pulse": return 1 << 6; break; case "gadget_speed_burst": return 1 << 7; break; case "gadget_combat_efficiency": return 1 << 8; break; default: return 0; } } function challenge_game_ended( data ) { if ( !isdefined( data ) ) return; player = data.player; if ( !isdefined( player ) ) return; if ( !isPlayer( player ) ) return; if ( player util::is_bot() ) return; if ( !player is_challenge_active() ) return; player report_consumable(); } function challenge_round_ended( data ) { if ( !isdefined( data ) ) return; player = data.player; if ( !isdefined( player ) ) return; if ( !isPlayer( player ) ) return; if ( player util::is_bot() ) return; if ( !player is_challenge_active() ) return; player report_consumable(); } function track_blackjack_consumable() { level endon( "game_ended" ); self notify( "track_blackjack_consumable_singleton" ); self endon( "track_blackjack_consumable_singleton" ); self endon( "disconnect" ); player = self; if ( !isdefined( player.last_blackjack_consumable_time ) ) player.last_blackjack_consumable_time = 0; while ( isdefined( player ) ) { random_wait_time = GetDvarFloat( "mp_blackjack_consumable_wait", 20.0 ) + RandomFloatRange( -5.0, 5.0 ); wait random_wait_time; player report_consumable(); } } function report_consumable() { player = self; if ( !isdefined( player ) ) return; if ( !isdefined( player.timePlayed ) || !isdefined( player.timePlayed["total"] ) ) return; current_time_played = player.timePlayed["total"]; time_to_report = current_time_played - player.last_blackjack_consumable_time; if ( time_to_report > 0 ) { max_time_to_report = player ConsumableGet( "blackjack", "awarded" ) - player ConsumableGet( "blackjack", "consumed" ); consumable_increment = int( min( time_to_report, max_time_to_report ) ); if ( consumable_increment > 0 ) { player ConsumableIncrement( "blackjack", "consumed", consumable_increment ); // so we don't go over awarded time } } player.last_blackjack_consumable_time = current_time_played; }