#include maps\_utility; #include animscripts\utility; #include common_scripts\utility; #include maps\_hud_util; // this script handles all major global gameskill considerations setSkill( reset ) { if ( !isdefined( level.script ) ) level.script = ToLower( GetDvar( "mapname" ) ); if ( !isdefined( reset ) || reset == false ) { if ( IsDefined( level.gameSkill ) ) return; if ( !isdefined( level.custom_player_attacker ) ) level.custom_player_attacker = ::return_false; level.global_damage_func_ads = ::empty_kill_func; level.global_damage_func = ::empty_kill_func; level.global_kill_func = ::empty_kill_func; if ( GetDvar( "arcademode" ) == "1" ) thread maps\_arcademode::main(); // first init stuff set_console_status(); foreach ( player in level.players ) { if ( is_coop() ) { player ent_flag_init( "coop_downed" ); player ent_flag_init( "coop_pause_bleedout_timer" ); player ent_flag_init( "coop_proc_running" ); player.coop = SpawnStruct(); } player ent_flag_init( "player_has_red_flashing_overlay" ); player ent_flag_init( "player_is_invulnerable" ); player ent_flag_init( "player_zero_attacker_accuracy" ); player ent_flag_init( "player_no_auto_blur" ); player ent_flag_init( "near_death_vision_enabled" ); player ent_flag_set( "near_death_vision_enabled" ); player.gs = SpawnStruct();// gs = gameskill player.a = SpawnStruct(); player.damage_functions = []; player maps\_player_stats::init_stats(); player ent_flag_init( "global_hint_in_use" ); if ( is_coop() ) player ent_flag_init( "coop_is_dead" ); player.pers = []; //player thread watchWeaponChange(); if ( !isDefined( player.baseIgnoreRandomBulletDamage ) ) player.baseIgnoreRandomBulletDamage = false; player.disabledWeapon = 0; player.disabledWeaponSwitch = 0; player.disabledUsability = 0; player SetOffhandPrimaryClass( "frag" ); } level.difficultyType[ 0 ] = "easy"; level.difficultyType[ 1 ] = "normal"; level.difficultyType[ 2 ] = "hardened"; level.difficultyType[ 3 ] = "veteran"; // string not found for GAMESKILL_EASY level.difficultyString[ "easy" ] = &"GAMESKILL_EASY"; // string not found for GAMESKILL_NORMAL level.difficultyString[ "normal" ] = &"GAMESKILL_NORMAL"; // string not found for GAMESKILL_HARDENED level.difficultyString[ "hardened" ] = &"GAMESKILL_HARDENED"; // string not found for GAMESKILL_VETERAN level.difficultyString[ "veteran" ] = &"GAMESKILL_VETERAN"; //thread update_skill_on_change(); /# thread playerHealthDebug(); #/ thread gameskill_change_monitor(); } //createprintchannel( "script_autodifficulty" ); SetDvarIfUninitialized( "autodifficulty_playerDeathTimer", 0 ); anim.run_accuracy = 0.5; anim.walk_accuracy = 0.8; // if ( GetDvar( "autodifficulty_frac" ) == "" ) SetDvar( "autodifficulty_frac", 0 );// disabled for now level.difficultySettings_frac_data_points = []; foreach ( player in level.players ) { player init_take_cover_warnings(); player thread increment_take_cover_warnings_on_death(); } level.mg42badplace_mintime = 8;// minimum # of seconds a badplace is created on an mg42 after its operator dies level.mg42badplace_maxtime = 16;// maximum # of seconds a badplace is created on an mg42 after its operator dies // RIGHT NOW ONLY .25 AND .75 ARE USED for easy and normal // anim.playerGrenadeBaseTime level.difficultySettings[ "playerGrenadeBaseTime" ][ "easy" ] = 40000; level.difficultySettings[ "playerGrenadeBaseTime" ][ "normal" ] = 35000; level.difficultySettings[ "playerGrenadeBaseTime" ][ "hardened" ] = 25000; level.difficultySettings[ "playerGrenadeBaseTime" ][ "veteran" ] = 25000; // anim.playerGrenadeRangeTime level.difficultySettings[ "playerGrenadeRangeTime" ][ "easy" ] = 20000; level.difficultySettings[ "playerGrenadeRangeTime" ][ "normal" ] = 15000; level.difficultySettings[ "playerGrenadeRangeTime" ][ "hardened" ] = 10000; level.difficultySettings[ "playerGrenadeRangeTime" ][ "veteran" ] = 10000; // time between instances where 2 grenades land near player at once( hardcoded to never happen in easy ) level.difficultySettings[ "playerDoubleGrenadeTime" ][ "easy" ] = 60 * 60 * 1000; level.difficultySettings[ "playerDoubleGrenadeTime" ][ "normal" ] = 150 * 1000; level.difficultySettings[ "playerDoubleGrenadeTime" ][ "hardened" ] = 90 * 1000; level.difficultySettings[ "playerDoubleGrenadeTime" ][ "veteran" ] = 90 * 1000; level.difficultySettings[ "double_grenades_allowed" ][ "easy" ] = false; level.difficultySettings[ "double_grenades_allowed" ][ "normal" ] = true; level.difficultySettings[ "double_grenades_allowed" ][ "hardened" ] = true; level.difficultySettings[ "double_grenades_allowed" ][ "veteran" ] = true; level.difficultySettings[ "threatbias" ][ "easy" ] = 100; level.difficultySettings[ "threatbias" ][ "normal" ] = 150; level.difficultySettings[ "threatbias" ][ "hardened" ] = 200; level.difficultySettings[ "threatbias" ][ "veteran" ] = 400; // level.longRegenTime // this var controls how long it takes before your health comes back // level.difficultySettings[ "base_enemy_accuracy" ][ "easy" ] = 0.9; level.difficultySettings[ "base_enemy_accuracy" ][ "normal" ] = 1.0; level.difficultySettings[ "base_enemy_accuracy" ][ "hardened" ] = 1.15; level.difficultySettings[ "base_enemy_accuracy" ][ "veteran" ] = 1.15; // lower numbers = higher accuracy for AI at a distance level.difficultySettings[ "accuracyDistScale" ][ "easy" ] = 1.0; level.difficultySettings[ "accuracyDistScale" ][ "normal" ] = 1.0; level.difficultySettings[ "accuracyDistScale" ][ "hardened" ] = 0.6; level.difficultySettings[ "accuracyDistScale" ][ "veteran" ] = 0.8; // too many other things make it more difficult // anim.min_sniper_burst_delay_time level.difficultySettings[ "min_sniper_burst_delay_time" ][ "easy" ] = 3.0; level.difficultySettings[ "min_sniper_burst_delay_time" ][ "normal" ] = 2.0; level.difficultySettings[ "min_sniper_burst_delay_time" ][ "hardened" ] = 1.5; level.difficultySettings[ "min_sniper_burst_delay_time" ][ "veteran" ] = 1.1; // anim.max_sniper_burst_delay_time level.difficultySettings[ "max_sniper_burst_delay_time" ][ "easy" ] = 4.0; level.difficultySettings[ "max_sniper_burst_delay_time" ][ "normal" ] = 3.0; level.difficultySettings[ "max_sniper_burst_delay_time" ][ "hardened" ] = 2.0; level.difficultySettings[ "max_sniper_burst_delay_time" ][ "veteran" ] = 1.5; level.difficultySettings[ "dog_health" ][ "easy" ] = 0.25; level.difficultySettings[ "dog_health" ][ "normal" ] = 0.75; level.difficultySettings[ "dog_health" ][ "hardened" ] = 1.0; level.difficultySettings[ "dog_health" ][ "veteran" ] = 1.0; level.difficultySettings[ "dog_presstime" ][ "easy" ] = 415; level.difficultySettings[ "dog_presstime" ][ "normal" ] = 375; level.difficultySettings[ "dog_presstime" ][ "hardened" ] = 250; level.difficultySettings[ "dog_presstime" ][ "veteran" ] = 225; level.difficultySettings[ "dog_hits_before_kill" ][ "easy" ] = 2; level.difficultySettings[ "dog_hits_before_kill" ][ "normal" ] = 1; level.difficultySettings[ "dog_hits_before_kill" ][ "hardened" ] = 0; level.difficultySettings[ "dog_hits_before_kill" ][ "veteran" ] = 0; // anim.pain_test level.difficultySettings[ "pain_test" ][ "easy" ] = ::always_pain; level.difficultySettings[ "pain_test" ][ "normal" ] = ::always_pain; level.difficultySettings[ "pain_test" ][ "hardened" ] = ::pain_protection; level.difficultySettings[ "pain_test" ][ "veteran" ] = ::pain_protection; // missTime is a number based on the distance from the AI to the player + some baseline // it simulates bad aim as the AI starts shooting, and helps give the player a warning before they get hit. // this is used for auto and semi auto. // missTime = missTimeConstant + distance * missTimeDistanceFactor level.difficultySettings[ "missTimeConstant" ][ "easy" ] = 1.0;// 0.2;// 0.3; level.difficultySettings[ "missTimeConstant" ][ "normal" ] = 0.05;// 0.1; level.difficultySettings[ "missTimeConstant" ][ "hardened" ] = 0;// 0.04; level.difficultySettings[ "missTimeConstant" ][ "veteran" ] = 0;// 0.03; // determines which misstime constant to use based on difficulty frac. Hard and Vet use their own settings. level.difficultySettings[ "missTimeDistanceFactor" ][ "easy" ] = 0.8 / 1000;// 0.4 level.difficultySettings[ "missTimeDistanceFactor" ][ "normal" ] = 0.1 / 1000; level.difficultySettings[ "missTimeDistanceFactor" ][ "hardened" ] = 0.05 / 1000; level.difficultySettings[ "missTimeDistanceFactor" ][ "veteran" ] = 0; // determines which missTimeDistanceFactor to use based on difficulty frac. Hard and Vet use their own settings. level.difficultySettings[ "flashbangedInvulFactor" ][ "easy" ] = 0.25; level.difficultySettings[ "flashbangedInvulFactor" ][ "normal" ] = 0; level.difficultySettings[ "flashbangedInvulFactor" ][ "hardened" ] = 0; level.difficultySettings[ "flashbangedInvulFactor" ][ "veteran" ] = 0; // currently disabled // bullets do enough damage to instantly put player in red flashing at this distance level.difficultySettings[ "player_criticalBulletDamageDist" ][ "easy" ] = 0;// 200 level.difficultySettings[ "player_criticalBulletDamageDist" ][ "normal" ] = 0;// 200 level.difficultySettings[ "player_criticalBulletDamageDist" ][ "hardened" ] = 0; level.difficultySettings[ "player_criticalBulletDamageDist" ][ "veteran" ] = 0; // Death Invulnerable Time controls how long the player is death-proof after going into red flashing // This protection resets after the player recovers full health. level.difficultySettings[ "player_deathInvulnerableTime" ][ "easy" ] = 4000; level.difficultySettings[ "player_deathInvulnerableTime" ][ "normal" ] = 2500; level.difficultySettings[ "player_deathInvulnerableTime" ][ "hardened" ] = 600; level.difficultySettings[ "player_deathInvulnerableTime" ][ "veteran" ] = 100; // level.invulTime_preShield: time player is invulnerable when hit before their health is low enough for a red overlay( should be very short ) level.difficultySettings[ "invulTime_preShield" ][ "easy" ] = 0.6; level.difficultySettings[ "invulTime_preShield" ][ "normal" ] = 0.5; level.difficultySettings[ "invulTime_preShield" ][ "hardened" ] = 0.3; level.difficultySettings[ "invulTime_preShield" ][ "veteran" ] = 0.0; // level.invulTime_onShield: time player is invulnerable when hit the first time they get a red health overlay( should be reasonably long ) // should not be more than or too much lower than player_deathInvulnerableTime level.difficultySettings[ "invulTime_onShield" ][ "easy" ] = 1.6; level.difficultySettings[ "invulTime_onShield" ][ "normal" ] = 1.0; level.difficultySettings[ "invulTime_onShield" ][ "hardened" ] = 0.5; level.difficultySettings[ "invulTime_onShield" ][ "veteran" ] = 0.25; // level.invulTime_postShield: time player is invulnerable when hit after the red health overlay is already up( should be short ) level.difficultySettings[ "invulTime_postShield" ][ "easy" ] = 0.5; level.difficultySettings[ "invulTime_postShield" ][ "normal" ] = 0.4; level.difficultySettings[ "invulTime_postShield" ][ "hardened" ] = 0.3; level.difficultySettings[ "invulTime_postShield" ][ "veteran" ] = 0.0; // level.playerHealth_RegularRegenDelay // The delay before you regen health after getting hurt level.difficultySettings[ "playerHealth_RegularRegenDelay" ][ "easy" ] = 4000; level.difficultySettings[ "playerHealth_RegularRegenDelay" ][ "normal" ] = 4000; level.difficultySettings[ "playerHealth_RegularRegenDelay" ][ "hardened" ] = 3000; level.difficultySettings[ "playerHealth_RegularRegenDelay" ][ "veteran" ] = 1200; // level.worthyDamageRatio( player must recieve this much damage as a fraction of maxhealth to get invulTime_PREshield. ) level.difficultySettings[ "worthyDamageRatio" ][ "easy" ] = 0.0; level.difficultySettings[ "worthyDamageRatio" ][ "normal" ] = 0.1; level.difficultySettings[ "worthyDamageRatio" ][ "hardened" ] = 0.3; level.difficultySettings[ "worthyDamageRatio" ][ "veteran" ] = 0.3; // level.playerDifficultyHealth // the amount of health you have in this difficulty level.difficultySettings[ "playerDifficultyHealth" ][ "easy" ] = 475; level.difficultySettings[ "playerDifficultyHealth" ][ "normal" ] = 275; level.difficultySettings[ "playerDifficultyHealth" ][ "hardened" ] = 165; level.difficultySettings[ "playerDifficultyHealth" ][ "veteran" ] = 115; // If you go to red flashing, the amount of time before your health regens level.difficultySettings[ "longRegenTime" ][ "easy" ] = 5000; level.difficultySettings[ "longRegenTime" ][ "normal" ] = 5000; level.difficultySettings[ "longRegenTime" ][ "hardened" ] = 3200; level.difficultySettings[ "longRegenTime" ][ "veteran" ] = 3200; // level.healthOverlayCutoff level.difficultySettings[ "healthOverlayCutoff" ][ "easy" ] = 0.02; level.difficultySettings[ "healthOverlayCutoff" ][ "normal" ] = 0.02; level.difficultySettings[ "healthOverlayCutoff" ][ "hardened" ] = 0.02; level.difficultySettings[ "healthOverlayCutoff" ][ "veteran" ] = 0.02; // self.gs.regenRate // the rate you regen health once it starts to regen level.difficultySettings[ "health_regenRate" ][ "easy" ] = 0.02; level.difficultySettings[ "health_regenRate" ][ "normal" ] = 0.02; level.difficultySettings[ "health_regenRate" ][ "hardened" ] = 0.02; level.difficultySettings[ "health_regenRate" ][ "veteran" ] = 0.02; // level.explosiveplanttime level.difficultySettings[ "explosivePlantTime" ][ "easy" ] = 10; level.difficultySettings[ "explosivePlantTime" ][ "normal" ] = 10; level.difficultySettings[ "explosivePlantTime" ][ "hardened" ] = 5; level.difficultySettings[ "explosivePlantTime" ][ "veteran" ] = 5; // Once a player is downed, the other player gets this much time before they can be downed. level.difficultySettings[ "player_downed_buffer_time" ][ "normal" ] = 2; level.difficultySettings[ "player_downed_buffer_time" ][ "hardened" ] = 1.5; level.difficultySettings[ "player_downed_buffer_time" ][ "veteran" ] = 0; // in case there are no enties in the map. level.lastPlayerSighted = 0; if ( IsDefined( level.custom_gameskill_func ) ) [[ level.custom_gameskill_func ]](); if ( coop_with_one_player_downed() ) { make_remaining_player_a_little_stronger(); } updateGameSkill(); updateAllDifficulty(); // not sure what to do with this SetDvar( "autodifficulty_original_setting", level.gameskill ); SetSavedDvar( "player_meleeDamageMultiplier", 100 / 250 ); } solo_player_in_special_ops() { AssertEx( level.players.size == 1, "This function is only for special ops featuring 1 player." ); SetSavedDvar( "ai_accuracy_attackercountDecrease", "0.6" ); SetSavedDvar( "player_deathInvulnerableToMelee", "1" ); // The delay before you regen health after getting hurt level.difficultySettings[ "playerHealth_RegularRegenDelay" ][ "normal" ] = 2000; level.difficultySettings[ "playerHealth_RegularRegenDelay" ][ "hardened" ] = 2000; level.difficultySettings[ "playerHealth_RegularRegenDelay" ][ "veteran" ] = 900; level.difficultySettings[ "invulTime_onShield" ][ "normal" ] = 2.5; // Death Invulnerable Time controls how long the player is death-proof after going into red flashing // This protection resets after the player recovers full health. level.difficultySettings[ "player_deathInvulnerableTime" ][ "normal" ] = 3000; level.difficultySettings[ "player_deathInvulnerableTime" ][ "hardened" ] = 1300; level.difficultySettings[ "player_deathInvulnerableTime" ][ "veteran" ] = 800; // if you go into red flashing, this long before health comes back level.difficultySettings[ "longRegenTime" ][ "normal" ] = 4500; level.difficultySettings[ "longRegenTime" ][ "hardened" ] = 4500; level.difficultySettings[ "longRegenTime" ][ "veteran" ] = 4500; // how much health you have level.difficultySettings[ "playerDifficultyHealth" ][ "normal" ] = 350; level.difficultySettings[ "playerDifficultyHealth" ][ "hardened" ] = 205; level.difficultySettings[ "playerDifficultyHealth" ][ "veteran" ] = 205; SetSavedDvar( "player_meleeDamageMultiplier", 0.5 ); } solo_player_in_coop_gameskill_settings() { // In missions where one player is on the ground and the other is in a vehicle, both players fail if the player // on the ground dies, so we buff up the ground player a little so he has a better chance, since nobody is going to // revive him. AssertEx( level.players.size == 2, "This function is only for special ops featuring 2 players." ); // Improve DIT so you don't die so easily when you go into red flashing. // Death Invulnerable Time controls how long the player is death-proof after going into red flashing // This protection resets after the player recovers full health. level.difficultySettings[ "player_deathInvulnerableTime" ][ "normal" ] = 2500;// from 600ms level.difficultySettings[ "player_deathInvulnerableTime" ][ "hardened" ] = 1200;// from 600ms level.difficultySettings[ "player_deathInvulnerableTime" ][ "veteran" ] = 200;// from 100ms multiplier = 1.35; // give players more health when their buddy is laid up level.difficultySettings[ "playerDifficultyHealth" ][ "normal" ] = Int( 275 * multiplier ); level.difficultySettings[ "playerDifficultyHealth" ][ "hardened" ] = Int( 165 * multiplier ); level.difficultySettings[ "playerDifficultyHealth" ][ "veteran" ] = Int( 115 * 1.2 ); } make_remaining_player_a_little_stronger() { // Improve DIT so you don't die so easily when you go into red flashing. // Death Invulnerable Time controls how long the player is death-proof after going into red flashing // This protection resets after the player recovers full health. level.difficultySettings[ "player_deathInvulnerableTime" ][ "normal" ] = 2500; level.difficultySettings[ "player_deathInvulnerableTime" ][ "hardened" ] = 1000;// from 600ms //level.difficultySettings[ "player_deathInvulnerableTime" ][ "veteran" ] = 200; // from 100ms multiplier = 1.25; // give players more health when their buddy is laid up level.difficultySettings[ "playerDifficultyHealth" ][ "normal" ] = Int( 275 * multiplier ); level.difficultySettings[ "playerDifficultyHealth" ][ "hardened" ] = Int( 165 * multiplier ); //level.difficultySettings[ "playerDifficultyHealth" ][ "veteran" ] = Int( 115 * 1.12 ); } updateAllDifficulty() { setGlobalDifficulty(); for ( i = 0; i < level.players.size; i++ ) { level.players[ i ] setDifficulty(); } } setDifficulty() { Assert( IsPlayer( self ) ); Assert( IsDefined( self.gameskill ) ); self set_difficulty_from_locked_settings(); } // if level.gameskill changes, we need to call this setGlobalDifficulty() { difficulty_func = ::get_locked_difficulty_val_global; //logString( "difficulty: " + level.gameSkill ); current_skill = get_skill_from_index( level.gameskill ); anim.dog_health = [[ difficulty_func ]]( "dog_health", level.gameskill ); anim.pain_test = level.difficultySettings[ "pain_test" ][ current_skill ]; level.explosiveplanttime = level.difficultySettings[ "explosivePlantTime" ][ current_skill ]; anim.min_sniper_burst_delay_time = [[ difficulty_func ]]( "min_sniper_burst_delay_time", level.gameskill ); anim.max_sniper_burst_delay_time = [[ difficulty_func ]]( "max_sniper_burst_delay_time", level.gameskill ); SetSavedDvar( "ai_accuracyDistScale", [[ difficulty_func ]]( "accuracyDistScale", level.gameskill ) ); if ( is_coop() ) { // Once a player is downed, the other player gets this much time before they can be downed. AssertEx( IsDefined( level.difficultySettings[ "player_downed_buffer_time" ][ current_skill ] ), "No player_downed_buffer_time for " + current_skill ); level.player_downed_death_buffer_time = level.difficultySettings[ "player_downed_buffer_time" ][ current_skill ]; } maps\_mgturret::setdifficulty(); } updateGameSkill() { foreach ( player in level.players ) player.gameskill = player get_player_gameskill(); level.gameskill = level.player.gameskill; if ( is_coop() && ( level.player2.gameskill > level.gameskill ) ) level.gameskill = level.player2.gameskill; level.specops_reward_gameskill = level.player.gameskill; if ( is_coop() && ( level.player2.gameskill < level.specops_reward_gameskill ) ) level.specops_reward_gameskill = level.player2.gameskill; if ( IsDefined( level.forcedgameskill ) ) level.gameskill = level.forcedgameskill; Assert( level.gameSkill >= 0 && level.gameSkill <= 3 ); // Decrement the level.player's gameskill if playing Special Ops and not in coop // if ( is_specialop() && !is_coop() ) // { // level.player.gameskill--; // if ( level.player.gameskill < 0 ) // level.player.gameskill = 0; // } return level.gameSkill; } gameskill_change_monitor() { current_gameskill = level.gameSkill; while ( 1 ) { if ( !isdefined( current_gameskill ) ) { wait 1; current_gameskill = level.gameSkill; continue; } if ( current_gameskill != updateGameSkill() ) { current_gameskill = level.gameSkill; updateAllDifficulty(); } wait 1; } } get_skill_from_index( index ) { return level.difficultyType[ index ]; } aa_should_start_fresh() { if ( level.script == "killhouse" ) return true; return level.gameskill == GetDvarInt( "autodifficulty_original_setting" ); } apply_difficulty_frac_with_func( difficulty_func, current_frac ) { Assert( IsPlayer( self ) ); // TODO: put these properties on the player somehow //prof_begin( "apply_difficulty_frac_with_func" ); self.gs.invulTime_preShield = [[ difficulty_func ]]( "invulTime_preShield", current_frac ); self.gs.invulTime_onShield = [[ difficulty_func ]]( "invulTime_onShield", current_frac ); self.gs.invulTime_postShield = [[ difficulty_func ]]( "invulTime_postShield", current_frac ); self.gs.playerHealth_RegularRegenDelay = [[ difficulty_func ]]( "playerHealth_RegularRegenDelay", current_frac ); self.gs.worthyDamageRatio = [[ difficulty_func ]]( "worthyDamageRatio", current_frac ); self.threatbias = Int( [[ difficulty_func ]]( "threatbias", current_frac ) ); self.gs.longRegenTime = [[ difficulty_func ]]( "longRegenTime", current_frac ); self.gs.healthOverlayCutoff = [[ difficulty_func ]]( "healthOverlayCutoff", current_frac ); self.gs.regenRate = [[ difficulty_func ]]( "health_regenRate", current_frac ); self.gs.player_attacker_accuracy = [[ difficulty_func ]]( "base_enemy_accuracy", current_frac ); update_player_attacker_accuracy(); self.gs.playerGrenadeBaseTime = Int( [[ difficulty_func ]]( "playerGrenadeBaseTime", current_frac ) ); self.gs.playerGrenadeRangeTime = Int( [[ difficulty_func ]]( "playerGrenadeRangeTime", current_frac ) ); self.gs.playerDoubleGrenadeTime = Int( [[ difficulty_func ]]( "playerDoubleGrenadeTime", current_frac ) ); self.gs.min_sniper_burst_delay_time = [[ difficulty_func ]]( "min_sniper_burst_delay_time", current_frac ); self.gs.max_sniper_burst_delay_time = [[ difficulty_func ]]( "max_sniper_burst_delay_time", current_frac ); self.gs.dog_presstime = [[ difficulty_func ]]( "dog_presstime", current_frac ); // Death Invulnerable Time controls how long the player is death-proof after going into red flashing // This protection resets after the player recovers full health. self.deathInvulnerableTime = Int( [[ difficulty_func ]]( "player_deathInvulnerableTime", current_frac ) ); self.criticalBulletDamageDist = Int( [[ difficulty_func ]]( "player_criticalBulletDamageDist", current_frac ) ); self.damageMultiplier = 100 / [[ difficulty_func ]]( "playerDifficultyHealth", current_frac ); //prof_end( "apply_difficulty_frac_with_func" ); } update_player_attacker_accuracy() { if ( self ent_flag( "player_zero_attacker_accuracy" ) ) return; self.IgnoreRandomBulletDamage = self.baseIgnoreRandomBulletDamage; self.attackeraccuracy = self.gs.player_attacker_accuracy; } apply_difficulty_step_with_func( difficulty_func, current_frac ) { Assert( IsPlayer( self ) ); // TODO: put these properties on the player somehow //prof_begin( "apply_difficulty_step_with_func" ); // sets the value of difficulty settings that can't blend between two self.gs.missTimeConstant = [[ difficulty_func ]]( "missTimeConstant", current_frac ); self.gs.missTimeDistanceFactor = [[ difficulty_func ]]( "missTimeDistanceFactor", current_frac ); self.gs.dog_hits_before_kill = [[ difficulty_func ]]( "dog_hits_before_kill", current_frac ); self.gs.double_grenades_allowed = [[ difficulty_func ]]( "double_grenades_allowed", current_frac ); //prof_end( "apply_difficulty_step_with_func" ); } set_difficulty_from_locked_settings() { apply_difficulty_frac_with_func( ::get_locked_difficulty_val_player, 1 ); apply_difficulty_step_with_func( ::get_locked_difficulty_step_val_player, 1 ); } get_locked_difficulty_step_val_player( system, ignored ) { return level.difficultySettings[ system ][ get_skill_from_index( self.gameskill ) ]; } get_locked_difficulty_step_val_global( system, ignored ) { return level.difficultySettings[ system ][ get_skill_from_index( level.gameskill ) ]; } get_blended_difficulty( system, current_frac ) { //prof_begin( "get_blended_difficulty" ); // get the value from the available data points difficulty_array = level.difficultySettings_frac_data_points[ system ]; Assert( IsDefined( difficulty_array ) ); Assert( difficulty_array.size >= 1 ); for ( i = 1; i < difficulty_array.size; i++ ) { high_frac = difficulty_array[ i ][ "frac" ]; high_val = difficulty_array[ i ][ "val" ]; if ( current_frac <= high_frac ) { low_frac = difficulty_array[ i - 1 ][ "frac" ]; low_val = difficulty_array[ i - 1 ][ "val" ]; frac_range = high_frac - low_frac; val_range = high_val - low_val; base_frac = current_frac - low_frac; result_frac = base_frac / frac_range; return low_val + result_frac * val_range; } } //prof_end( "get_blended_difficulty" ); return difficulty_array[ difficulty_array.size - 1 ][ "val" ]; } getCurrentDifficultySetting( msg ) { return level.difficultySettings[ msg ][ get_skill_from_index( self.gameskill ) ]; } getRatio( msg, min, max ) { return( level.difficultySettings[ msg ][ level.difficultyType[ min ] ] * ( 100 - GetDvarInt( "autodifficulty_frac" ) ) + level.difficultySettings[ msg ][ level.difficultyType[ max ] ] * GetDvarInt( "autodifficulty_frac" ) ) * 0.01; } get_locked_difficulty_val_player( msg, ignored )// ignored is there because this is used as a function pointer with another function that does have a second parm { return level.difficultySettings[ msg ][ get_skill_from_index( self.gameskill ) ]; } get_locked_difficulty_val_global( msg, ignored ) { return level.difficultySettings[ msg ][ get_skill_from_index( level.gameskill ) ]; } always_pain() { return false; } pain_protection() { if ( !pain_protection_check() ) return false; return( RandomInt( 100 ) > 25 ); } pain_protection_check() { if ( !isalive( self.enemy ) ) return false; if ( !isplayer( self.enemy ) ) return false; if ( !isalive( level.painAI ) || level.painAI.script != "pain" ) level.painAI = self; // The pain AI can always take pain, so if the player focuses on one guy he'll see pain animations. if ( self == level.painAI ) return false; if ( self.damageWeapon != "none" && WeaponIsBoltAction( self.damageWeapon ) ) return false; return true; } /# playerHealthDebug() { waittillframeend;// for init to finish SetDvarIfUninitialized( "scr_health_debug", "0" ); while ( 1 ) { while ( 1 ) { if ( GetDebugDvar( "scr_health_debug" ) == "1" ) break; wait .5; } thread printHealthDebug(); while ( 1 ) { if ( GetDebugDvar( "scr_health_debug" ) != "1" ) break; wait .5; } level notify( "stop_printing_health_bars" ); destroyHealthDebug(); } } printHealthDebug() { level notify( "stop_printing_health_bars" ); level endon( "stop_printing_health_bars" ); x = 40; y = 40; level.healthBarHudElems = []; healthBarKeys[ 0 ] = "Health"; healthBarKeys[ 1 ] = "No Hit Time"; healthBarKeys[ 2 ] = "No Die Time"; for ( playerIndex = 0; playerIndex < level.players.size; playerIndex++ ) { player = level.players[ playerIndex ]; if ( !isDefined( player.playerInvulTimeEnd ) ) player.playerInvulTimeEnd = 0; if ( !isDefined( player.deathInvulnerableTimeout ) ) player.deathInvulnerableTimeout = 0; for ( i = 0; i < healthBarKeys.size; i++ ) { key = healthBarKeys[ i ]; textelem = NewHudElem(); textelem.x = x; textelem.y = y; textelem.alignX = "left"; textelem.alignY = "top"; textelem.horzAlign = "fullscreen"; textelem.vertAlign = "fullscreen"; textelem SetText( "Player " + ( playerIndex + 1 ) + " " + key ); bar = NewHudElem(); bar.x = x + 80; bar.y = y + 2; bar.alignX = "left"; bar.alignY = "top"; bar.horzAlign = "fullscreen"; bar.vertAlign = "fullscreen"; bar SetShader( "black", 1, 8 ); textelem.bar = bar; textelem.key = key; y += 10; textelem.player = player; level.healthBarHudElems[ level.healthBarHudElems.size ] = textelem; } } while ( 1 ) { wait .05; for ( i = 0; i < level.healthBarHudElems.size; i++ ) { player = level.healthBarHudElems[ i ].player; width = 0; type = i % 3; if ( type == 0 ) width = player.health / player.maxhealth * 300; else if ( type == 1 ) width = ( player.playerInvulTimeEnd - GetTime() ) / 1000 * 40; else if ( type == 2 ) width = ( player.deathInvulnerableTimeout - GetTime() ) / 1000 * 40; width = Int( max( width, 1 ) ); bar = level.healthBarHudElems[ i ].bar; bar SetShader( "black", width, 8 ); } } } destroyHealthDebug() { if ( !isdefined( level.healthBarHudElems ) ) return; for ( i = 0; i < level.healthBarHudElems.size; i++ ) { level.healthBarHudElems[ i ].bar Destroy(); level.healthBarHudElems[ i ] Destroy(); } } #/ /* // this is run on each enemy AI. axisAccuracyControl() { self endon( "long_death" ); self endon( "death" ); //prof_begin( "axisAccuracyControl" ); SetDvarIfUninitialized( "scr_dynamicaccuracy", "off" ); if ( GetDvar( "scr_dynamicaccuracy" ) != "on" ) { // self simpleAccuracyControl(); } else { for ( ;; ) { wait( 0.05 ); waittillframeend;// in case our accuracy changed this frame //prof_begin( "axisAccuracyControl" ); if ( IsDefined( self.enemy ) && IsPlayer( self.enemy ) && self CanSee( self.enemy ) ) { self.a.accuracyGrowthMultiplier += 0.05 * anim.accuracyGrowthRate; if ( self.a.accuracyGrowthMultiplier > anim.accuracyGrowthMax ) self.a.accuracyGrowthMultiplier = anim.accuracyGrowthMax; } else { self.a.accuracyGrowthMultiplier = 1; } self setEnemyAccuracy(); //prof_end( "axisAccuracyControl" ); } } //prof_end( "axisAccuracyControl" ); } alliesAccuracyControl() { self endon( "long_death" ); self endon( "death" ); // self simpleAccuracyControl(); } */ set_accuracy_based_on_situation() { if ( self animscripts\combat_utility::isSniper() && IsAlive( self.enemy ) ) { self setSniperAccuracy(); return; } if ( IsPlayer( self.enemy ) ) { resetMissDebounceTime(); if ( self.a.missTime > GetTime() ) { self.accuracy = 0; return; } } if ( self.script == "move" ) { if ( self isCQBWalkingOrFacingEnemy() ) self.accuracy = anim.walk_accuracy * self.baseAccuracy; else self.accuracy = anim.run_accuracy * self.baseAccuracy; return; } self.accuracy = self.baseAccuracy; // rambo corner is more accurate so it's still a threat to the player if ( IsDefined( self.isRambo ) && IsDefined( self.ramboAccuracyMult ) ) self.accuracy *= self.ramboAccuracyMult; } setSniperAccuracy() { /* // if sniperShotCount isn't defined, a sniper is shooting from some place that's not in normal shoot behavior. // that probably means they're doing some sort of blindfire or something that would look stupid for a sniper to do. Assert( IsDefined( self.sniperShotCount ) ); */ if ( !isdefined( self.sniperShotCount ) ) { // snipers get this error if a dog attacks them self.sniperShotCount = 0; self.sniperHitCount = 0; } self.sniperShotCount++; gameskill = level.gameskill; if ( IsPlayer( self.enemy ) ) gameskill = self.enemy.gameskill; if ( shouldForceSniperMissShot() ) { // miss self.accuracy = 0; if ( gameskill > 0 || self.sniperShotCount > 1 ) self.lastMissedEnemy = self.enemy; return; } // guarantee a hit unless baseAccuracy is 0 self.accuracy = ( 1 + 1 * self.sniperHitCount ) * self.baseAccuracy; self.sniperHitCount++; if ( gameskill < 1 && self.sniperHitCount == 1 ) self.lastMissedEnemy = undefined;// miss again } shouldForceSniperMissShot() { if ( isdefined( self.neverForceSniperMissEnemy ) && self.neverForceSniperMissEnemy ) return false; //dont do this if you're an ally of the player, changed by z for Price cliffhanger sniping if ( self.team == "allies" ) return false; if ( isDefined( self.lastMissedEnemy ) && ( self.enemy == self.lastMissedEnemy ) ) return false; if ( DistanceSquared( self.origin, self.enemy.origin ) > ( 500 * 500 ) ) return false; return true; } shotsAfterPlayerBecomesInvul() { return( 1 + RandomFloat( 4 ) ); } didSomethingOtherThanShooting() { // make sure the next time resetAccuracyAndPause() is called, we reset our misstime for sure self.a.missTimeDebounce = 0; } // called when we start a volley of shots. resetAccuracyAndPause() { self resetMissTime(); // self conserveAmmoWhilePlayerIsInvulnerable(); } waitTimeIfPlayerIsHit() { waittime = 0; waittillframeend; if ( !isalive( self.enemy ) ) return waittime; if ( !isplayer( self.enemy ) ) return waittime; if ( self.enemy ent_flag( "player_is_invulnerable" ) ) waittime = ( 0.3 + RandomFloat( 0.4 ) ); return waittime; } print3d_time( org, text, color, timer ) { timer *= 20; for ( i = 0; i < timer; i++ ) { Print3d( org, text, color ); wait( 0.05 ); } } resetMissTime() { //prof_begin( "resetMissTime" ); if ( !self IsBadGuy() ) return; if ( self.weapon == "none" ) return; if ( !self animscripts\weaponList::usingAutomaticWeapon() && !self animscripts\weaponList::usingSemiAutoWeapon() ) { self.missTime = 0; //prof_end( "resetMissTime" ); return; } if ( !isalive( self.enemy ) ) { //prof_end( "resetMissTime" ); return; } if ( !isplayer( self.enemy ) ) { self.accuracy = self.baseAccuracy; //prof_end( "resetMissTime" ); return; } dist = Distance( self.enemy.origin, self.origin ); self setMissTime( self.enemy.gs.missTimeConstant + dist * self.enemy.gs.missTimeDistanceFactor ); //prof_end( "resetMissTime" ); } resetMissDebounceTime() { self.a.missTimeDebounce = GetTime() + 3000; } setMissTime( howLong ) { AssertEx( self IsBadGuy(), "Non axis tried to set misstime" ); // we can only start missing again if it's been a few seconds since we last shot if ( self.a.missTimeDebounce > GetTime() ) { return; } if ( howLong > 0 ) self.accuracy = 0; howLong *= 1000;// convert to milliseconds self.a.missTime = GetTime() + howLong; self.a.accuracyGrowthMultiplier = 1; // thread print3d_time( self.origin + (0,0,32 ), "Aiming..", (1,1,0), howLong * 0.001 ); //thread player_aim_debug(); } player_aim_debug() { self endon( "death" ); self notify( "playeraim" ); self endon( "playeraim" ); for ( ;; ) { color = ( 0, 1, 0 ); if ( self.a.misstime > GetTime() ) color = ( 1, 0, 0 ); Print3d( self.origin + ( 0, 0, 32 ), self.finalaccuracy, color ); wait( 0.05 ); } } dirt_effect_on_open() { // lerp scale from .3 to 1 over 0.1; scaler = 0.66; self ScaleOverTime( 0.1, Int( 2048 * scaler ), Int( 1024 * scaler ) ) ; self.y = 100; self MoveOverTime( 0.08 ) ; self.y = 0; } dirt_detailed_alpha() { /* dirt_fade_in_time = 0.1; self.alpha = 0; self FadeOverTime( dirt_fade_in_time ); self.alpha = 0.77; wait( dirt_fade_in_time ); self FadeOverTime( dirt_fade_in_time ); self.alpha = 0; wait( dirt_fade_in_time ); self Destroy(); */ dirt_fade_in_time = 0.2; self.alpha = 0.7;// cant do the same fade menus do self FadeOverTime( dirt_fade_in_time ); self.alpha = 0; wait( dirt_fade_in_time ); self Destroy(); } dirt_blurry_alpha() { start_time = GetTime(); dirt_fade_out_time = 1; self.alpha = 0; wait( 0.2 ); self.alpha = 1; wait_for_buffer_time_to_pass( start_time, 2 ); self FadeOverTime( dirt_fade_out_time ); self.alpha = 0; wait( dirt_fade_out_time ); self Destroy(); } dirt_left_effect_on_open() { // lerp scale from 0 to 1 over 0.05; // lerp x from -1000 to 0 over 0.05; scaler = 0.66; self ScaleOverTime( 0.05, Int( 2048 * scaler ), Int( 1024 * scaler ) ) ; self.x = -1000; self MoveOverTime( 0.05 ) ; self.x = 0; } dirt_right_effect_on_open() { // lerp scale from 0 to 1 over 0.1; // lerp x from 300 to 0 over 0.1; scaler = 0.66; self ScaleOverTime( 0.1, Int( 2048 * scaler ), Int( 1024 * scaler ) ) ; self.x = 300; self MoveOverTime( 0.1 ) ; self.x = 0; } dirt_left_blurry_alpha() { // lerp alpha from 0 to 1 over 0.05; start_time = GetTime(); dirt_fade_out_time = 1; dirt_fade_time = 0.05; self.alpha = 0; self FadeOverTime( dirt_fade_time ); self.alpha = 1; wait( dirt_fade_time ); wait_for_buffer_time_to_pass( start_time, 2 ); self FadeOverTime( dirt_fade_out_time ); self.alpha = 0; wait( dirt_fade_out_time ); self Destroy(); } dirt_right_blurry_alpha() { // lerp alpha from 0 to 1 over 0.15; start_time = GetTime(); dirt_fade_out_time = 1; dirt_fade_time = 0.15; self.alpha = 0; self FadeOverTime( dirt_fade_time ); self.alpha = 1; wait( dirt_fade_time ); wait_for_buffer_time_to_pass( start_time, 2 ); self FadeOverTime( dirt_fade_out_time ); self.alpha = 0; wait( dirt_fade_out_time ); self Destroy(); } grenade_dirt_on_screen( type ) { if ( !isalive( self ) ) return; if ( IsDefined( self.is_controlling_UAV ) ) return; // already did this effect on this frame if ( self.dirt_on_screen[ type ] == GetTime() ) return; self.dirt_on_screen[ type ] = GetTime(); self endon( "death" ); dirt_material = "fullscreen_dirt_" + type; switch( type ) { case "bottom_b": width = Int( 640 ); height = Int( 480 ); detailed = create_client_overlay_custom_size( "fullscreen_dirt_bottom", 1, width, height );// a flash of dirt detailed thread dirt_effect_on_open(); detailed thread dirt_detailed_alpha(); blurry = create_client_overlay_custom_size( dirt_material, 0, width, height ); blurry thread dirt_effect_on_open(); blurry thread dirt_blurry_alpha(); break; case "left": blurry = create_client_overlay_custom_size( dirt_material, 0, 1, 1 ); blurry thread dirt_left_effect_on_open(); blurry thread dirt_left_blurry_alpha(); break; case "right": blurry = create_client_overlay_custom_size( dirt_material, 0, 1, 1 ); blurry thread dirt_right_effect_on_open(); blurry thread dirt_right_blurry_alpha(); break; default: AssertMsg( "Erroneous grenade dirt type " + type ); } } playerHurtcheck() { func = ::dirt_on_screen_from_position; mods = []; mods[ "MOD_GRENADE" ] = func; mods[ "MOD_GRENADE_SPLASH" ] = func; mods[ "MOD_PROJECTILE" ] = func; mods[ "MOD_PROJECTILE_SPLASH" ] = func; mods[ "MOD_EXPLOSIVE" ] = func; self.hurtAgain = false; for ( ;; ) { self waittill( "damage", amount, attacker, dir, point, type ); self.hurtAgain = true; self.damagePoint = point; self.damageAttacker = attacker; if ( IsDefined( mods[ type ] ) ) { waittillframeend;// let the scripted grenade - specific stuff from _utility try first [[ mods[ type ] ]]( point ); } } } /*draw_player_health_packets() { Assert( IsPlayer( self ) ); packets = []; red = ( 1, 0, 0 ); orange = ( 1, 0.5, 0 ); green = ( 0, 1, 0 ); for ( i = 0; i < 3; i++ ) { overlay = NewHudElem(); overlay.x = 5 + 20 * i; overlay.y = 20; overlay SetShader( "white", 16, 16 ); overlay.alignX = "left"; overlay.alignY = "top"; overlay.alpha = 1; overlay.color = ( 0, 1, 0 ); packets[ packets.size ] = overlay; } for ( ;; ) { self waittill( "update_health_packets" ); if ( self ent_flag( "player_has_red_flashing_overlay" ) ) { packetBase = 1; for ( i = 0; i < packetBase; i++ ) { packets[ i ] FadeOverTime( 0.5 ); packets[ i ].alpha = 1; packets[ i ].color = red; } for ( i = packetBase; i < 3; i++ ) { packets[ i ] FadeOverTime( 0.5 ); packets[ i ].alpha = 0; packets[ i ].color = red; } self ent_flag_waitopen( "player_has_red_flashing_overlay" ); } packetBase = self.player_health_packets; if ( packetBase <= 0 ) packetBase = 0; color = red; if ( packetBase == 2 ) color = orange; if ( packetBase == 3 ) color = green; for ( i = 0; i < packetBase; i++ ) { packets[ i ] FadeOverTime( 0.5 ); packets[ i ].alpha = 1; packets[ i ].color = color; } for ( i = packetBase; i < 3; i++ ) { packets[ i ] FadeOverTime( 0.5 ); packets[ i ].alpha = 0; packets[ i ].color = red; } } }*/ player_health_packets() { Assert( IsPlayer( self ) ); // thread draw_player_health_packets(); self.player_health_packets = 3; /* for ( ;; ) { self ent_flag_wait( "player_has_red_flashing_overlay" ); // change_player_health_packets( - 1 ); self ent_flag_waitopen( "player_has_red_flashing_overlay" ); } */ } playerHealthRegenInit() { wait( 0.05 );// to give a chance for moscow to init level.strings so it doesnt clear ours level.strings[ "take_cover" ] = SpawnStruct(); // You are Hurt. Get to Cover! level.strings[ "take_cover" ].text = &"GAME_GET_TO_COVER"; } playerHealthRegen() { Assert( IsPlayer( self ) ); //prof_begin( "playerHealthRegen" ); thread healthOverlay(); oldratio = 1; health_add = 0; thread player_health_packets(); veryHurt = false; playerJustGotRedFlashing = false; thread playerBreathingSound( self.maxhealth * 0.35 ); invulTime = 0; hurtTime = 0; newHealth = 0; lastinvulratio = 1; thread playerHurtcheck(); self.boltHit = false; // self thread boltCheck(); for ( ;; ) { wait( 0.05 ); waittillframeend;// if we're on hard, we need to wait until the bolt damage check before we decide what to do //prof_begin( "playerHealthRegen" ); if ( is_coop() ) self thread maps\_coop::player_coop_proc(); if ( self.health == self.maxhealth ) { if ( self ent_flag( "player_has_red_flashing_overlay" ) ) { player_recovers_from_red_flashing(); // self notify( "hit_again" ); was cutting off the overlay fadeout } lastinvulratio = 1; playerJustGotRedFlashing = false; veryHurt = false; continue; } if ( self.health <= 0 ) { /#showHitLog();#/ //prof_end( "playerHealthRegen" ); return; } wasVeryHurt = veryHurt; ratio = self.health / self.maxHealth; if ( ratio <= self.gs.healthOverlayCutoff && self.player_health_packets > 1 ) { veryHurt = true; if ( !wasVeryHurt ) { hurtTime = GetTime(); if ( self ent_flag( "near_death_vision_enabled" ) ) { thread blurView( 3.6, 2 ); thread maps\_ambient::use_eq_settings( "deathsdoor", level.eq_main_track ); thread maps\_ambient::use_reverb_settings( "deathsdoor" ); self PainVisionOn(); } self ent_flag_set( "player_has_red_flashing_overlay" ); playerJustGotRedFlashing = true; } } /* if ( !wasVeryHurt && veryHurt ) nearAIRushesPlayer(); */ if ( self.hurtAgain ) { hurtTime = GetTime(); self.hurtAgain = false; } if ( self.health / self.maxhealth >= oldratio ) { if ( GetTime() - hurttime < self.gs.playerHealth_RegularRegenDelay ) continue; if ( veryHurt ) { newHealth = ratio; if ( GetTime() > hurtTime + self.gs.longRegenTime ) newHealth += self.gs.regenRate; if ( newHealth >= 1 ) reduceTakeCoverWarnings(); } else { newHealth = 1; } if ( newHealth > 1.0 ) newHealth = 1.0; if ( newHealth <= 0 ) { // Player is dead return; } /# if ( newHealth > self.health / self.maxhealth ) logRegen( newHealth ); #/ self SetNormalHealth( newHealth ); oldRatio = self.health / self.maxHealth; continue; } oldratio = lastinvulRatio; worthyDamageRatio = self.gs.worthyDamageRatio; // could tweak for more than 1 guy but 2 guys seem to kill the player well enough if ( self.attackerCount == 1 ) worthyDamageRatio *= 3; invulWorthyHealthDrop = oldratio - ratio >= worthyDamageRatio; if ( self.health <= 1 ) { // if player's health is <= 1, code's player_deathInvulnerableTime has kicked in and the player won't lose health for a while. // set the health to 2 so we can at least detect when they're getting hit. self SetNormalHealth( 2 / self.maxhealth ); invulWorthyHealthDrop = true; /# if ( !isDefined( self.deathInvulnerableTimeout ) ) self.deathInvulnerableTimeout = 0; if ( self.deathInvulnerableTimeout < GetTime() ) self.deathInvulnerableTimeout = GetTime() + self.deathInvulnerableTime; #/ } oldRatio = self.health / self.maxHealth; self notify( "hit_again" ); health_add = 0; hurtTime = GetTime(); thread blurView( 3, 0.8 ); if ( !invulWorthyHealthDrop ) { /#logHit( self.health, 0 );#/ continue; } if ( self ent_flag( "player_is_invulnerable" ) ) continue; self ent_flag_set( "player_is_invulnerable" ); level notify( "player_becoming_invulnerable" );// because "player_is_invulnerable" notify happens on both set * and * clear if ( playerJustGotRedFlashing ) { invulTime = self.gs.invulTime_onShield; playerJustGotRedFlashing = false; } else if ( veryHurt ) { invulTime = self.gs.invulTime_postShield; } else { invulTime = self.gs.invulTime_preShield; } /#logHit( self.health, invulTime );#/ lastinvulratio = self.health / self.maxHealth; self thread playerInvul( invulTime ); } //prof_end( "playerHealthRegen" ); } reduceTakeCoverWarnings() { Assert( IsPlayer( self ) ); //prof_begin( "reduceTakeCoverWarnings" ); if ( !self take_cover_warnings_enabled() ) return; if ( IsAlive( self ) ) { takeCoverWarnings = ( self GetLocalPlayerProfileData( "takeCoverWarnings" ) ); if ( takeCoverWarnings > 0 ) { takeCoverWarnings--; self SetLocalPlayerProfileData( "takeCoverWarnings", takeCoverWarnings ); /#DebugTakeCoverWarnings();#/ } } //prof_end( "reduceTakeCoverWarnings" ); } /# DebugTakeCoverWarnings() { SetDvarIfUninitialized( "scr_debugtakecover", "0" ); if ( GetDebugDvar( "scr_debugtakecover" ) == "1" ) { IPrintLn( "Warnings remaining: ", self GetLocalPlayerProfileData( "takeCoverWarnings" ) - 3 ); } } #/ /# logHit( newhealth, invulTime ) { /* if ( !isdefined( level.hitlog ) ) { level.hitlog = []; thread showHitLog(); } data = SpawnStruct(); data.regen = false; data.time = GetTime(); data.health = newhealth / level.player.maxhealth; data.invulTime = invulTime; level.hitlog[ level.hitlog.size ] = data;*/ } logRegen( newhealth ) { /* if ( !isdefined( level.hitlog ) ) { level.hitlog = []; thread showHitLog(); } data = SpawnStruct(); data.regen = true; data.time = GetTime(); data.health = newhealth / level.player.maxhealth; level.hitlog[ level.hitlog.size ] = data;*/ } showHitLog() { /* level.player waittill( "death" ); PrintLn( "" ); PrintLn( "^3Hit Log:" ); prevhealth = 1; prevtime = 0; for ( i = 0; i < level.hitlog.size; i++ ) { timepassed = ( level.hitlog[ i ].time - prevtime ) / 1000; healthlost = prevhealth - level.hitlog[ i ].health; PrintLn( "^0[ " + timepassed + " seconds passed ]" ); if ( level.hitlog[ i ].regen ) { PrintLn( "^0Regen at time ^3" + level.hitlog[ i ].time / 1000 + "^0 for ^3" + -1 * healthlost + "^0 damage. Health is now " + level.hitlog[ i ].health ); } else { damage = healthlost; if ( damage == 0 ) damage = "unknown"; PrintLn( "^0Hit at time ^3" + level.hitlog[ i ].time / 1000 + "^0 for ^3" + damage + "^0 damage; invul for ^3" + level.hitlog[ i ].invulTime + "^0 seconds. Health is now " + level.hitlog[ i ].health ); } prevtime = level.hitlog[ i ].time; prevhealth = level.hitlog[ i ].health; } PrintLn( "" );*/ } #/ playerInvul( timer ) { Assert( IsPlayer( self ) ); if ( IsDefined( self.flashendtime ) && self.flashendtime > GetTime() ) timer = timer * getCurrentDifficultySetting( "flashbangedInvulFactor" ); if ( timer > 0 ) { if ( !isdefined( self.noPlayerInvul ) ) self.attackeraccuracy = 0; self.IgnoreRandomBulletDamage = true; /# self.playerInvulTimeEnd = GetTime() + timer * 1000; #/ wait( timer ); } update_player_attacker_accuracy(); self ent_flag_clear( "player_is_invulnerable" ); } default_door_node_flashbang_frequency() { //added .doorFragChance and .doorFlashChance for throwing frag/flash grenades through doors. //Set it to a value between 0 and 1; 0 for never, 1 for always if possible. if ( self.team == "allies" ) self.doorFlashChance = .6; if ( self IsBadGuy() ) { if ( level.gameSkill >= 2 ) { // hard and veteran self.doorFlashChance = .8; } else { // normal and easy self.doorFlashChance = .6; } } } grenadeAwareness() { if ( self.team == "allies" ) { self.grenadeawareness = 0.9; return; } if ( self IsBadGuy() ) { if ( level.gameSkill >= 2 ) { // hard and fu if ( RandomInt( 100 ) < 33 ) self.grenadeawareness = 0.2; else self.grenadeawareness = 0.5; } else { // normal if ( RandomInt( 100 ) < 33 ) self.grenadeawareness = 0; else self.grenadeawareness = 0.2; } } } blurView( blur, timer ) { Assert( IsPlayer( self ) ); if ( ent_flag( "player_no_auto_blur" ) ) return; self notify( "blurview_stop" ); self endon( "blurview_stop" ); self SetBlurForPlayer( blur, 0 ); wait( 0.05 ); self SetBlurForPlayer( 0, timer ); } playerBreathingSound( healthcap ) { Assert( IsPlayer( self ) ); wait( 2 ); for ( ;; ) { wait( 0.2 ); if ( self.health <= 0 ) return; // Player still has a lot of health so no breathing sound ratio = self.health / self.maxHealth; if ( ratio > self.gs.healthOverlayCutoff ) continue; self PlayLocalSound( "breathing_hurt" ); wait( 0.1 + RandomFloat( 0.8 ) ); } } healthOverlay() { Assert( IsPlayer( self ) ); self endon( "noHealthOverlay" ); //prof_begin( "healthOverlay" ); overlay = NewClientHudElem( self ); overlay.x = 0; overlay.y = 0; if ( issplitscreen() ) { overlay SetShader( "splatter_alt_sp", 640, 480 * 2 ); // offset the blood a little so it looks different for each player if ( self == level.players[ 0 ] ) { overlay.y -= 120; } } else { overlay SetShader( "splatter_alt_sp", 640, 480 ); } overlay.splatter = true; overlay.alignX = "left"; overlay.alignY = "top"; overlay.sort = 1; overlay.foreground = 0; overlay.horzAlign = "fullscreen"; overlay.vertAlign = "fullscreen"; overlay.alpha = 0; thread healthOverlay_remove( overlay ); thread take_cover_warning_loop(); damageAlpha = 0.0; updateTime = 0.05; lerpRate = 0.3; while ( IsAlive( self ) ) { wait updateTime; targetDamageAlpha = 1.0 - self.health / self.maxHealth; if ( damageAlpha > targetDamageAlpha ) damageAlpha -= ( lerpRate * updateTime ); if ( damageAlpha < targetDamageAlpha ) damageAlpha = targetDamageAlpha; overlay.alpha = damageAlpha; } } take_cover_warning_loop() { while ( IsAlive( self ) ) { self ent_flag_wait( "player_has_red_flashing_overlay" ); //prof_begin( "healthOverlay" ); take_cover_warning(); } } /* overlay_non_flashing_alpha( overlay ) { self endon( "death" ); for ( ;; ) { do_non_flashing_alpha_when_not_hurt( overlay ); self ent_flag_waitopen( "player_has_red_flashing_overlay" ); } } do_non_flashing_alpha_when_not_hurt( overlay ) { level.player_overlay = overlay; level endon( "player_has_red_flashing_overlay" ); // dif = 0.95; for ( ;; ) { // Overlay comes in immediately, but fades out gradually new_alpha = ( 1 - ( self.health * 0.01 ) ) * 0.5; if (new_alpha > overlay.alpha) overlay.alpha = new_alpha; else if ( overlay.alpha - 0.025 < new_alpha ) overlay.alpha = new_alpha; else overlay.alpha -=0.025; wait( 0.05 ); } } */ add_hudelm_position_internal( alignY ) { //prof_begin( "add_hudelm_position_internal" ); if ( level.console ) self.fontScale = 2; else self.fontScale = 1.6; self.x = 0;// 320; self.y = -36;// 200; self.alignX = "center"; /* if ( 0 )// if we ever get the chance to localize or find a way to dynamically find how many lines in a string { if ( IsDefined( alignY ) ) self.alignY = alignY; else self.alignY = "middle"; } else {*/ self.alignY = "bottom"; // } self.horzAlign = "center"; self.vertAlign = "middle"; if ( !isdefined( self.background ) ) return; self.background.x = 0;// 320; self.background.y = -40;// 200; self.background.alignX = "center"; self.background.alignY = "middle"; self.background.horzAlign = "center"; self.background.vertAlign = "middle"; if ( level.console ) self.background SetShader( "popmenu_bg", 650, 52 ); else self.background SetShader( "popmenu_bg", 650, 42 ); self.background.alpha = .5; //prof_end( "add_hudelm_position_internal" ); } create_warning_elem() { Assert( IsPlayer( self ) ); hudelem = NewClientHudElem( self ); hudelem add_hudelm_position_internal(); thread destroy_warning_elem_when_hit_again( hudelem ); hudelem thread destroy_warning_elem_when_mission_failed(); // You are Hurt. Get to Cover! //hudelem SetText( &"GAME_GET_TO_COVER" ); hudelem SetText( level.strings[ "take_cover" ].text ); hudelem.fontscale = 2; hudelem.alpha = 1; hudelem.color = ( 1, 0.9, 0.9 ); hudelem.sort = 1; hudelem.foreground = 1; return hudelem; } waitTillPlayerIsHitAgain() { self endon( "hit_again" ); self waittill( "damage" ); } destroy_warning_elem_when_hit_again( hudelem ) { Assert( IsPlayer( self ) ); hudelem endon( "being_destroyed" ); waitTillPlayerIsHitAgain(); fadeout = ( !isalive( self ) ); hudelem thread destroy_warning_elem( fadeout ); } destroy_warning_elem_when_mission_failed() { self endon( "being_destroyed" ); flag_wait( "missionfailed" ); self thread destroy_warning_elem( true ); } destroy_warning_elem( fadeout ) { self notify( "being_destroyed" ); self.beingDestroyed = true; if ( fadeout ) { self FadeOverTime( 0.5 ); self.alpha = 0; wait 0.5; } self notify( "death" ); self Destroy(); } may_change_cover_warning_alpha( coverWarning ) { if ( !isdefined( coverWarning ) ) return false; if ( IsDefined( coverWarning.beingDestroyed ) ) return false; return true; } fontScaler( scale, timer ) { self endon( "death" ); scale *= 2; dif = scale - self.fontscale; self ChangeFontScaleOverTime( timer ); self.fontscale += dif; } fadeFunc( coverWarning, severity, mult, hud_scaleOnly ) { pulseTime = 0.8; scaleMin = 0.5; fadeInTime = pulseTime * 0.1; stayFullTime = pulseTime * ( .1 + severity * .2 ); fadeOutHalfTime = pulseTime * ( 0.1 + severity * .1 ); fadeOutFullTime = pulseTime * 0.3; remainingTime = pulseTime - fadeInTime - stayFullTime - fadeOutHalfTime - fadeOutFullTime; Assert( remainingTime >= -.001 ); if ( remainingTime < 0 ) remainingTime = 0; halfAlpha = 0.8 + severity * 0.1; leastAlpha = 0.5 + severity * 0.3; if ( may_change_cover_warning_alpha( coverWarning ) ) { if ( !hud_scaleOnly ) { coverWarning FadeOverTime( fadeInTime ); coverWarning.alpha = mult * 1.0; } } if ( IsDefined( coverWarning ) ) coverWarning thread fontScaler( 1.0, fadeInTime ); wait fadeInTime + stayFullTime; if ( may_change_cover_warning_alpha( coverWarning ) ) { if ( !hud_scaleOnly ) { coverWarning FadeOverTime( fadeOutHalfTime ); coverWarning.alpha = mult * halfAlpha; } } wait fadeOutHalfTime; if ( may_change_cover_warning_alpha( coverWarning ) ) { if ( !hud_scaleOnly ) { coverWarning FadeOverTime( fadeOutFullTime ); coverWarning.alpha = mult * leastAlpha; } } if ( IsDefined( coverWarning ) ) coverWarning thread fontScaler( 0.9, fadeOutFullTime ); wait fadeOutFullTime; wait remainingTime; } take_cover_warnings_enabled() { Assert( IsPlayer( self ) ); if ( IsDefined( level.cover_warnings_disabled ) ) { AssertEx( level.cover_warnings_disabled, "level.cover_warnings_disabled must be true or undefined" ); return false; } if ( IsDefined( self.vehicle ) ) return false; return true; } should_show_cover_warning() { Assert( IsPlayer( self ) ); if ( !isAlive( self ) ) return false; if ( self isLinked() ) return false; // why get to cover if you're being ignored? if ( self.ignoreme ) return false; if ( level.MissionFailed ) return false; if ( !self take_cover_warnings_enabled() ) return false; if ( self.gameskill > 1 && !maps\_load::map_is_early_in_the_game() ) return false; // note: takeCoverWarnings is 3 more than the number of warnings left. // this lets it stay away for a while unless we die 3 times in a row without taking cover successfully. takeCoverWarnings = ( self GetLocalPlayerProfileData( "takeCoverWarnings" ) ); if ( takeCoverWarnings <= 3 ) return false; return true; } // You are Hurt. Get to Cover! // &"GAME_GET_TO_COVER"; take_cover_warning() { Assert( IsPlayer( self ) ); self endon( "hit_again" ); self endon( "damage" ); coverWarning = undefined; if ( should_show_cover_warning() ) { // get to cover! coverWarning = create_warning_elem(); // coverWarning may be destroyed at any time if we fail the mission. } stopFlashingBadlyTime = GetTime() + self.gs.longRegenTime; regen_percent = self.gs.regenRate * 100; regen_frames = 100 / regen_percent; regen_time = regen_frames * 50; stopFlashingBadlyTime += regen_time; fadeFunc( coverWarning, 1, 1, false ); while ( GetTime() < stopFlashingBadlyTime && IsAlive( self ) ) fadeFunc( coverWarning, .9, 1, false ); if ( IsAlive( self ) ) fadeFunc( coverWarning, .65, 0.8, false ); if ( may_change_cover_warning_alpha( coverWarning ) ) { coverWarning FadeOverTime( 1.0 ); coverWarning.alpha = 0; } fadeFunc( coverWarning, 0, 0.6, true ); //player_recovers_from_red_flashing(); wait( 0.5 );// for fade out self notify( "take_cover_done" ); self notify( "hit_again" ); } player_recovers_from_red_flashing() { self PainVisionOff(); self ent_flag_clear( "player_has_red_flashing_overlay" ); // recover to the current eq if ( level.eq_track[ level.eq_main_track ] == "" ) { maps\_ambient::deactivate_index( level.eq_main_track ); } else { thread maps\_ambient::use_eq_settings( level.eq_track[ level.eq_main_track ], level.eq_main_track ); } if ( level.reverb_track == "" ) { maps\_ambient::deactivate_reverb(); } else { thread maps\_ambient::use_reverb_settings( level.reverb_track ); } self PlayLocalSound( "breathing_better" ); self notify( "take_cover_done" ); } healthOverlay_remove( overlay ) { Assert( IsPlayer( self ) ); self waittill( "noHealthOverlay" ); overlay Destroy(); } /* ============= ///ScriptDocBegin "Name: resetSkill()" "Summary: Reset the gameskill settings, enabling you to change them." "Module: Gameskill" "Example: resetSkill();" "SPMP: singleplayer" ///ScriptDocEnd ============= */ resetSkill() { waittillframeend;// if we're on the first frame then we want to wait until after _load or animscript has run setskill( true ); } init_take_cover_warnings() { // generates "Get to Cover" x number of times when you first get hurt // dvar defaults to - 1 isPreGameplayLevel = level.script == "roadkill" || level.script == "cliffhanger"; if ( self GetLocalPlayerProfileData( "takeCoverWarnings" ) == -1 || isPreGameplayLevel ) { // takeCoverWarnings is 3 more than the number of warnings we want to occur. self SetLocalPlayerProfileData( "takeCoverWarnings", 9 ); } /#DebugTakeCoverWarnings();#/ } increment_take_cover_warnings_on_death() { self notify( "new_cover_on_death_thread" ); self endon( "new_cover_on_death_thread" ); self waittill( "death" ); // dont increment if player died to grenades, explosion, etc if ( !self ent_flag( "player_has_red_flashing_overlay" ) ) return; if ( !self take_cover_warnings_enabled() ) return; warnings = ( self GetLocalPlayerProfileData( "takeCoverWarnings" ) ); if ( warnings < 10 ) self SetLocalPlayerProfileData( "takeCoverWarnings", warnings + 1 ); /#DebugTakeCoverWarnings();#/ } auto_adjust_difficulty_player_positioner() { Assert( IsPlayer( self ) ); org = self.origin; // thread debug_message( ".", org, 6 ); wait( 5 ); if ( self autospot_is_close_to_player( org ) ) level.autoAdjust_playerSpots[ level.autoAdjust_playerSpots.size ] = org; } autospot_is_close_to_player( org ) { Assert( IsPlayer( self ) ); return DistanceSquared( self.origin, org ) < ( 140 * 140 ); } auto_adjust_difficulty_player_movement_check() { level.autoAdjust_playerSpots = []; level.player.movedRecently = true; wait( 1 );// for lvl start precaching of debug strings for ( ;; ) { level.player thread auto_adjust_difficulty_player_positioner(); level.player.movedRecently = true; newSpots = []; start = level.autoAdjust_playerSpots.size - 5; if ( start < 0 ) start = 0; for ( i = start; i < level.autoAdjust_playerSpots.size; i++ ) { if ( !level.player autospot_is_close_to_player( level.autoAdjust_playerSpots[ i ] ) ) continue; newSpots[ newSpots.size ] = level.autoAdjust_playerSpots[ i ]; level.player.movedRecently = false; // thread debug_message( "!", newSpots[ newSpots.size - 1 ], 1 ); } level.autoAdjust_playerSpots = newSpots; wait( 1 ); } } auto_adjust_difficulty_track_player_death() { // reduce the difficulty timer when you die level.player waittill( "death" ); num = GetDvarInt( "autodifficulty_playerDeathTimer" ); num -= 60; SetDvar( "autodifficulty_playerDeathTimer", num ); // scriptPrintln( "script_autodifficulty", "Set deathtimer to " + num ); } auto_adjust_difficulty_track_player_shots() { // reduce the "time spent alive" by the time between shots fired if there has been significant time between shots lastShotTime = GetTime(); for ( ;; ) { if ( level.player AttackButtonPressed() ) lastShotTime = GetTime(); level.timeBetweenShots = GetTime() - lastShotTime; wait( 0.05 ); /* if ( lastShotTime < 10000 ) continue; playerDeathTimer = getcvarint( "playerDeathTimer" ); playerDeathTimer = Int( playerDeathTimer - lastShotTime * 0.001 ); setcvar( "playerDeathTimer", playerDeathTimer ); */ } } hud_debug_add_frac( msg, num ) { hud_debug_add_display( msg, num * 100, true ); } hud_debug_add( msg, num ) { hud_debug_add_display( msg, num, false ); } hud_debug_clear() { level.hudNum = 0; if ( IsDefined( level.hudDebugNum ) ) { for ( i = 0; i < level.hudDebugNum.size; i++ ) level.hudDebugNum[ i ] Destroy(); } level.hudDebugNum = []; } hud_debug_add_message( msg ) { if ( !isdefined( level.hudMsgShare ) ) level.hudMsgShare = []; if ( !isdefined( level.hudMsgShare[ msg ] ) ) { hud = NewHudElem(); hud.x = level.debugLeft; hud.y = level.debugHeight + level.hudNum * 15; hud.foreground = 1; hud.sort = 100; hud.alpha = 1.0; hud.alignX = "left"; hud.horzAlign = "left"; hud.fontScale = 1.0; hud SetText( msg ); level.hudMsgShare[ msg ] = true; } } hud_debug_add_display( msg, num, isfloat ) { hud_debug_add_message( msg ); num = Int( num ); negative = false; if ( num < 0 ) { negative = true; num *= -1; } thousands = 0; hundreds = 0; tens = 0; ones = 0; while ( num >= 10000 ) num -= 10000; while ( num >= 1000 ) { num -= 1000; thousands++; } while ( num >= 100 ) { num -= 100; hundreds++; } while ( num >= 10 ) { num -= 10; tens++; } while ( num >= 1 ) { num -= 1; ones++; } offset = 0; offsetSize = 10; if ( thousands > 0 ) { hud_debug_add_num( thousands, offset ); offset += offsetSize; hud_debug_add_num( hundreds, offset ); offset += offsetSize; hud_debug_add_num( tens, offset ); offset += offsetSize; hud_debug_add_num( ones, offset ); offset += offsetSize; } else if ( hundreds > 0 || isFloat ) { hud_debug_add_num( hundreds, offset ); offset += offsetSize; hud_debug_add_num( tens, offset ); offset += offsetSize; hud_debug_add_num( ones, offset ); offset += offsetSize; } else if ( tens > 0 ) { hud_debug_add_num( tens, offset ); offset += offsetSize; hud_debug_add_num( ones, offset ); offset += offsetSize; } else { hud_debug_add_num( ones, offset ); offset += offsetSize; } if ( isFloat ) { decimalHud = NewHudElem(); decimalHud.x = 204.5; decimalHud.y = level.debugHeight + level.hudNum * 15; decimalHud.foreground = 1; decimalHud.sort = 100; decimalHud.alpha = 1.0; decimalHud.alignX = "left"; decimalHud.horzAlign = "left"; decimalHud.fontScale = 1.0; decimalHud SetText( "." ); level.hudDebugNum[ level.hudDebugNum.size ] = decimalHud; } if ( negative ) { negativeHud = NewHudElem(); negativeHud.x = 195.5; negativeHud.y = level.debugHeight + level.hudNum * 15; negativeHud.foreground = 1; negativeHud.sort = 100; negativeHud.alpha = 1.0; negativeHud.alignX = "left"; negativeHud.horzAlign = "left"; negativeHud.fontScale = 1.0; negativeHud SetText( " - " ); level.hudDebugNum[ level.hudNum ] = negativeHud; } // level.hudDebugNum[ level.hudNum ] = hud; level.hudNum++; } hud_debug_add_string( msg, msg2 ) { hud_debug_add_message( msg ); hud_debug_add_second_string( msg2, 0 ); level.hudNum++; } hud_debug_add_num( num, offset ) { hud = NewHudElem(); hud.x = 200 + offset * 0.65; hud.y = level.debugHeight + level.hudNum * 15; hud.foreground = 1; hud.sort = 100; hud.alpha = 1.0; hud.alignX = "left"; hud.horzAlign = "left"; hud.fontScale = 1.0; hud SetText( num + "" ); level.hudDebugNum[ level.hudDebugNum.size ] = hud; } hud_debug_add_second_string( num, offset ) { hud = NewHudElem(); hud.x = 200 + offset * 0.65; hud.y = level.debugHeight + level.hudNum * 15; hud.foreground = 1; hud.sort = 100; hud.alpha = 1.0; hud.alignX = "left"; hud.horzAlign = "left"; hud.fontScale = 1.0; hud SetText( num ); level.hudDebugNum[ level.hudDebugNum.size ] = hud; } aa_init_stats() { /# if ( GetDvar( "createfx" ) == "on" ) return; if ( GetDvarInt( "noder" ) || GetDvarInt( "painter" ) ) { return; } if ( GetDvar( "r_reflectionProbeGenerate" ) == "1" ) { return; } #/ //prof_begin( "aa_init_stats" ); level.sp_stat_tracking_func = maps\_gameskill::auto_adjust_new_zone; SetDvar( "aa_player_kills", "0" ); SetDvar( "aa_enemy_deaths", "0" ); SetDvar( "aa_enemy_damage_taken", "0" ); SetDvar( "aa_player_damage_taken", "0" ); SetDvar( "aa_player_damage_dealt", "0" ); SetDvar( "aa_ads_damage_dealt", "0" ); SetDvar( "aa_time_tracking", "0" ); SetDvar( "aa_deaths", "0" ); SetDvar( "player_cheated", 0 ); level.auto_adjust_results = []; thread aa_time_tracking(); thread aa_player_health_tracking(); thread aa_player_ads_tracking(); flag_set( "auto_adjust_initialized" ); flag_init( "aa_main_" + level.script ); flag_set( "aa_main_" + level.script ); //prof_end( "aa_init_stats" ); } command_used( cmd ) { Assert( IsPlayer( self ) ); //prof_begin( "command_used" ); binding = GetKeyBinding( cmd ); if ( binding[ "count" ] <= 0 ) { //prof_end( "command_used" ); return false; } for ( i = 1; i < binding[ "count" ] + 1; i++ ) { if ( self ButtonPressed( binding[ "key" + i ] ) ) { //prof_end( "command_used" ); return true; } } //prof_end( "command_used" ); return false; } aa_time_tracking() { /# if ( GetDvar( "createfx" ) != "" ) return; if ( GetDvar( "scr_generateClipModels" ) != "" && GetDvar( "scr_generateClipModels" ) != "0" ) return;// shortcut for generating clipmodels gah. #/ waittillframeend;// so level.start_point is defined for ( ;; ) { //prof_begin( "aa_time_tracking" ); //aa_add_event_float( "aa_time_tracking", 0.2 ); /# if ( IsGodMode( level.player ) || level.start_point != "default" || GetDvar( "timescale", 1 ) != "1" ) { if ( GetDvar( "player_cheated" ) != "1" ) SetDvar( "player_cheated", 1 ); } #/ /* level.sprint_key = GetKeyBinding( "+breath_sprint" ); sprinting = false; sprinting = level.player command_used( "+sprint" ); if ( !sprinting ) { sprinting = level.player command_used( "+breath_sprint" ); } if ( sprinting ) { aa_add_event_float( "aa_sprint_time", 0.2 ); } */ wait( 0.2 ); } } aa_player_ads_tracking() { level.player endon( "death" ); level.player_ads_time = 0; for ( ;; ) { if ( level.player isADS() ) { level.player_ads_time = GetTime(); while ( level.player isADS() ) { wait( 0.05 ); } continue; } wait( 0.05 ); } } aa_player_health_tracking() { for ( ;; ) { level.player waittill( "damage", amount, a, b, c, d, e, f ); aa_add_event( "aa_player_damage_taken", amount ); if ( !isalive( level.player ) ) { aa_add_event( "aa_deaths", 1 ); return; } } } auto_adjust_new_zone( zone ) { /# if ( GetDvar( "createfx" ) == "on" ) return; #/ if ( !isdefined( level.auto_adjust_flags ) ) { level.auto_adjust_flags = []; } flag_wait( "auto_adjust_initialized" ); //prof_begin( "auto_adjust_new_zone" ); level.auto_adjust_results[ zone ] = []; level.auto_adjust_flags[ zone ] = 0; flag_wait( zone ); //prof_begin( "auto_adjust_new_zone" ); // already processing this zone? if ( GetDvar( "aa_zone" + zone ) == "" ) { SetDvar( "aa_zone" + zone, "on" ); level.auto_adjust_flags[ zone ] = 1; aa_update_flags(); SetDvar( "start_time" + zone, GetDvar( "aa_time_tracking" ) ); // measure always SetDvar( "starting_player_kills" + zone, GetDvar( "aa_player_kills" ) ); SetDvar( "starting_deaths" + zone, GetDvar( "aa_deaths" ) ); SetDvar( "starting_ads_damage_dealt" + zone, GetDvar( "aa_ads_damage_dealt" ) ); SetDvar( "starting_player_damage_dealt" + zone, GetDvar( "aa_player_damage_dealt" ) ); SetDvar( "starting_player_damage_taken" + zone, GetDvar( "aa_player_damage_taken" ) ); SetDvar( "starting_enemy_damage_taken" + zone, GetDvar( "aa_enemy_damage_taken" ) ); SetDvar( "starting_enemy_deaths" + zone, GetDvar( "aa_enemy_deaths" ) ); } else { if ( GetDvar( "aa_zone" + zone ) == "done" ) { //prof_end( "auto_adjust_new_zone" ); return; } } //prof_end( "auto_adjust_new_zone" ); flag_waitopen( zone ); auto_adust_zone_complete( zone ); } auto_adust_zone_complete( zone ) { //prof_begin( "auto_adust_zone_complete" ); SetDvar( "aa_zone" + zone, "done" ); start_time = GetDvarFloat( "start_time" + zone ); starting_player_kills = GetDvarInt( "starting_player_kills" + zone ); starting_enemy_deaths = GetDvarInt( "aa_enemy_deaths" + zone ); starting_enemy_damage_taken = GetDvarInt( "aa_enemy_damage_taken" + zone ); starting_player_damage_taken = GetDvarInt( "aa_player_damage_taken" + zone ); starting_player_damage_dealt = GetDvarInt( "aa_player_damage_dealt" + zone ); starting_ads_damage_dealt = GetDvarInt( "aa_ads_damage_dealt" + zone ); starting_deaths = GetDvarInt( "aa_deaths" + zone ); level.auto_adjust_flags[ zone ] = 0; aa_update_flags(); total_time = GetDvarFloat( "aa_time_tracking" ) - start_time; total_player_kills = GetDvarInt( "aa_player_kills" ) - starting_player_kills; total_enemy_deaths = GetDvarInt( "aa_enemy_deaths" ) - starting_enemy_deaths; player_kill_ratio = 0; if ( total_enemy_deaths > 0 ) { player_kill_ratio = total_player_kills / total_enemy_deaths; player_kill_ratio *= 100; player_kill_ratio = Int( player_kill_ratio ); } total_enemy_damage_taken = GetDvarInt( "aa_enemy_damage_taken" ) - starting_enemy_damage_taken; total_player_damage_dealt = GetDvarInt( "aa_player_damage_dealt" ) - starting_player_damage_dealt; player_damage_dealt_ratio = 0; player_damage_dealt_per_minute = 0; if ( total_enemy_damage_taken > 0 && total_time > 0 ) { player_damage_dealt_ratio = total_player_damage_dealt / total_enemy_damage_taken; player_damage_dealt_ratio *= 100; player_damage_dealt_ratio = Int( player_damage_dealt_ratio ); player_damage_dealt_per_minute = total_player_damage_dealt / total_time; player_damage_dealt_per_minute = player_damage_dealt_per_minute * 60; player_damage_dealt_per_minute = Int( player_damage_dealt_per_minute ); } total_ads_damage_dealt = GetDvarInt( "aa_ads_damage_dealt" ) - starting_ads_damage_dealt; player_ads_damage_ratio = 0; if ( total_player_damage_dealt > 0 ) { player_ads_damage_ratio = total_ads_damage_dealt / total_player_damage_dealt; player_ads_damage_ratio *= 100; player_ads_damage_ratio = Int( player_ads_damage_ratio ); } total_player_damage_taken = GetDvarInt( "aa_player_damage_taken" ) - starting_player_damage_taken; player_damage_taken_ratio = 0; if ( total_time > 0 ) { player_damage_taken_ratio = total_player_damage_taken / total_time; } player_damage_taken_per_minute = player_damage_taken_ratio * 60; player_damage_taken_per_minute = Int( player_damage_taken_per_minute ); total_deaths = GetDvarInt( "aa_deaths" ) - starting_deaths; aa_array = []; aa_array[ "player_damage_taken_per_minute" ] = player_damage_taken_per_minute; aa_array[ "player_damage_dealt_per_minute" ] = player_damage_dealt_per_minute; aa_array[ "minutes" ] = total_time / 60; aa_array[ "deaths" ] = total_deaths; aa_array[ "gameskill" ] = level.gameskill; level.auto_adjust_results[ zone ] = aa_array; msg = "Completed AA sequence: "; /# if ( GetDvar( "player_cheated" ) == "1" ) { msg = "Cheated in AA sequence: "; } #/ msg += level.script + "/" + zone; keys = GetArrayKeys( aa_array ); // array_levelthread( keys, ::aa_print_vals, aa_array ); for ( i = 0; i < keys.size; i++ ) { msg = msg + ", " + keys[ i ] + ": " + aa_array[ keys[ i ] ]; } logString( msg ); PrintLn( "^6" + msg ); //prof_end( "auto_adust_zone_complete" ); } aa_print_vals( key, aa_array ) { logString( key + ": " + aa_array[ key ] ); PrintLn( "^6" + key + ": " + aa_array[ key ] ); } /* aa_print_vals( key, aa_array, file ) { FPrintLn( file, key + ": " + aa_array[ key ] ); } */ aa_update_flags() { } aa_add_event( event, amount ) { old_amount = GetDvarInt( event ); SetDvar( event, old_amount + amount ); } aa_add_event_float( event, amount ) { old_amount = GetDvarFloat( event ); SetDvar( event, old_amount + amount ); } return_false( attacker ) { return false; } player_attacker( attacker ) { if ( [[ level.custom_player_attacker ]]( attacker ) ) return true; if ( IsPlayer( attacker ) ) return true; if ( !isdefined( attacker.car_damage_owner_recorder ) ) return false; return attacker player_did_most_damage(); } player_did_most_damage() { return self.player_damage * 1.75 > self.non_player_damage; } empty_kill_func( type, loc, point ) { } auto_adjust_enemy_died( amount, attacker, type, point ) { //prof_begin( "auto_adjust_enemy_died" ); /* Not worth effecting the speed of the game for one spot in one map in one mode // in case the team got changed. if ( !self IsBadGuy() ) return; if ( self.type == "civilian" ) return; */ aa_add_event( "aa_enemy_deaths", 1 ); if ( !isdefined( attacker ) ) { //prof_end( "auto_adjust_enemy_died" ); return; } if ( !player_attacker( attacker ) ) { //prof_end( "auto_adjust_enemy_died" ); return; } // defaults to empty_kill_func, for arcademode [[ level.global_kill_func ]]( type, self.damagelocation, point ); aa_add_event( "aa_player_kills", 1 ); //prof_end( "auto_adjust_enemy_died" ); } auto_adjust_enemy_death_detection( amount, attacker, direction_vec, point, type, _, _ ) { if ( !isalive( self ) || self.delayeddeath ) { self auto_adjust_enemy_died( amount, attacker, type, point ); return; } if ( !player_attacker( attacker ) ) return; aa_player_attacks_enemy_with_ads( amount, type, point ); } aa_player_attacks_enemy_with_ads( amount, type, point ) { aa_add_event( "aa_player_damage_dealt", amount ); AssertEx( GetDvarInt( "aa_player_damage_dealt" ) > 0 ); if ( !level.player isADS() ) { // defaults to empty_kill_func, for arcademode [[ level.global_damage_func ]]( type, self.damagelocation, point ); return false; } if ( !bullet_attack( type ) ) { // defaults to empty_kill_func, for arcademode [[ level.global_damage_func ]]( type, self.damagelocation, point ); return false; } // defaults to empty_kill_func, for arcademode [[ level.global_damage_func_ads ]]( type, self.damagelocation, point ); // ads only matters for bullet attacks. Otherwise you could throw a grenade then go ads and get a bunch of ads damage aa_add_event( "aa_ads_damage_dealt", amount ); return true; } bullet_attack( type ) { if ( type == "MOD_PISTOL_BULLET" ) return true; return type == "MOD_RIFLE_BULLET"; } /* ============= ///ScriptDocBegin "Name: add_fractional_data_point( , , )" "Summary: Adds difficulty setting data for a specific system at a specified fraction. The in game difficulty will be blended between this and the other data points." "Module: gameskill" "MandatoryArg: : The system being adjusted." "MandatoryArg: : Which fraction from 0 to 1 that this difficulty value exists at." "MandatoryArg: : The value that this system should be set at when the difficulty is at the specified frac." "Example: add_fractional_data_point( "playerGrenadeRangeTime", 1.0, 7500 );" "SPMP: singleplayer" ///ScriptDocEnd ============= */ add_fractional_data_point( name, frac, val ) { //prof_begin( "add_fractional_data_point" ); if ( !isdefined( level.difficultySettings_frac_data_points[ name ] ) ) { level.difficultySettings_frac_data_points[ name ] = []; } array = []; array[ "frac" ] = frac; array[ "val" ] = val; AssertEx( frac >= 0, "Tried to set a difficulty data point less than 0." ); AssertEx( frac <= 1, "Tried to set a difficulty data point greater than 1." ); level.difficultySettings_frac_data_points[ name ][ level.difficultySettings_frac_data_points[ name ].size ] = array; //prof_end( "add_fractional_data_point" ); } coop_with_one_player_downed() { if ( !is_coop() ) return false; if ( level.players.size != 2 ) return false; downed_players = 0; foreach ( player in level.players ) { if ( !player ent_flag( "coop_downed" ) ) continue; downed_players++; } // is only one player downed? return downed_players == 1; }