[ZM] Cold War Zombies amount per round similar algorithm!
-
After lots of calcs and tests I finally got an algorithm similar to the amount of zombies per round on Cold War. Making it exactly to CW wasn't possible for me as lots of CW GSCs are hashed, but still, it's amount identical on high rounds.
To summarize I've played Zombies since BO2 and one of the things I've always disliked on zombies was how the multipliers of Zombies is so agressive, round 100 alone for example has 924 zombies. Playing CW I loved how they changed those multipliers so rounds progresses much fast instead of you spending 5hrs+ to get up to 100.
So i'm going to share this here cuz i've searched everywere on the internet and couldn't find much info.
But first thanks to Ivobardolf for posting the stock code on the forum which them I took and started modifying.#include common_scripts\utility; #include maps\mp\_utility; #include maps\mp\zombies\_zm_utility; #include maps\mp\zombies\_zm_ffotd; #include maps\mp\zombies\_zm; #include maps\mp\_visionset_mgr; #include maps\mp\zombies\_zm_devgui; #include maps\mp\zombies\_zm_zonemgr; #include maps\mp\zombies\_zm_unitrigger; #include maps\mp\zombies\_zm_audio; #include maps\mp\zombies\_zm_blockers; #include maps\mp\zombies\_zm_bot; #include maps\mp\zombies\_zm_clone; #include maps\mp\zombies\_zm_buildables; #include maps\mp\zombies\_zm_equipment; #include maps\mp\zombies\_zm_laststand; #include maps\mp\zombies\_zm_magicbox; #include maps\mp\zombies\_zm_perks; #include maps\mp\zombies\_zm_playerhealth; #include maps\mp\zombies\_zm_power; #include maps\mp\zombies\_zm_powerups; #include maps\mp\zombies\_zm_score; #include maps\mp\zombies\_zm_spawner; #include maps\mp\zombies\_zm_gump; #include maps\mp\zombies\_zm_timer; #include maps\mp\zombies\_zm_traps; #include maps\mp\zombies\_zm_weapons; #include maps\mp\zombies\_zm_tombstone; #include maps\mp\zombies\_zm_stats; #include maps\mp\zombies\_zm_pers_upgrades; #include maps\mp\gametypes_zm\_zm_gametype; #include maps\mp\zombies\_zm_pers_upgrades_functions; #include maps\mp\_demo; #include maps\mp\gametypes_zm\_hud_util; #include maps\mp\zombies\_zm_melee_weapon; #include maps\mp\zombies\_zm_ai_dogs; #include maps\mp\zombies\_zm_pers_upgrades_system; #include maps\mp\gametypes_zm\_weapons; #include maps\mp\zombies\_zm_ai_basic; #include maps\mp\zombies\_zm_game_module; main() { level.round_spawn_func = ::cold_war_spawn; } cold_war_spawn() { level endon( "intermission" ); level endon( "end_of_round" ); level endon( "restart_round" ); /# level endon( "kill_round" ); #/ if ( level.intermission ) return; /# if ( getdvarint( #"zombie_cheat" ) == 2 || getdvarint( #"zombie_cheat" ) >= 4 ) return; #/ if ( level.zombie_spawn_locations.size < 1 ) { /# assertmsg( "No active spawners in the map. Check to see if the zone is active and if it's pointing to spawners." ); #/ return; } ai_calculate_health( level.round_number ); count = 0; players = get_players(); for ( i = 0; i < players.size; i++ ) players[i].zombification_time = 0; // Get maximum zombies and calculate the multiplier max = level.zombie_vars["zombie_max_ai"]; multiplier = level.round_number / 5; if (multiplier < 1) multiplier = 1; if (level.round_number >= 10) multiplier *= (level.round_number * 0.15); player_num = get_players().size; // ADJUST FOR PLAYER NUMBER IF THERE'S ONE PLAYER if (player_num == 1) { // For rounds below 29 if (level.round_number < 29) { max += int(0.5 * level.zombie_vars["zombie_ai_per_player"] * multiplier); } // Calculate caps dynamically for rounds above 29 for one player if (level.round_number >= 29) { // Start from 97 zombies for Round 29 base_zombies = 97; // Initialize added zombies counter added_zombies = 0; // Loop through the rounds and add zombies for (i = 0; i < (level.round_number - 29); i++) { if ((29 + i) % 2 == 1) { // Odd round: add 2 zombies added_zombies += 2; } else { // Even round: add 3 zombies added_zombies += 3; } } // Set the max zombies based on the added zombies from previous rounds max = base_zombies + added_zombies; } } // ADJUST FOR PLAYER NUMBER IF THERE'S TWO PLAYERS else if (player_num == 2) { // For rounds below 29 if (level.round_number < 29) { max += int((player_num - 1) * level.zombie_vars["zombie_ai_per_player"] * multiplier); } // Calculate caps dynamically for rounds above 29 for two players if (level.round_number >= 29) { // Start from 180 zombies for Round 29 base_zombies = 180; // Initialize added zombies counter added_zombies = 0; // Loop through the rounds and add zombies according to the pattern for (i = 0; i < (level.round_number - 29); i++) { if ((29 + i) % 2 == 1) { // Odd rounds (e.g., 29, 31, 33, etc.): add 5 zombies added_zombies += 5; } else { // Even rounds (e.g., 30, 32, 34, etc.): add 6 zombies added_zombies += 6; } } // Set the max zombies based on the base for Round 29 and added zombies from subsequent rounds max = base_zombies + added_zombies; } } // ADJUST FOR PLAYER NUMBER IF THERE'S THREE PLAYERS else if (player_num == 3) { // For rounds below 20, calculate the zombies as usual (you can adjust this as needed) if (level.round_number < 20) { max += int((player_num - 1) * level.zombie_vars["zombie_ai_per_player"] * multiplier); } // Calculate caps dynamically for rounds above 20 for two players if (level.round_number >= 20) { // Start from 168 zombies for Round 20 base_zombies = 168; // Initialize added zombies counter added_zombies = 0; // Loop through the rounds from 20 onwards for (i = 0; i < (level.round_number - 20); i++) { if ((20 + i) % 5 == 0) { // Every 5th round (e.g., round 20, 25, etc.), add 8 zombies added_zombies += 8; } else { // For other rounds, add 7 zombies added_zombies += 7; } } // Set the max zombies based on the base for Round 19 and added zombies from subsequent rounds max = base_zombies + added_zombies; } } // ADJUST FOR PLAYER NUMBER IF THERE'S FOUR PLAYERS else if (player_num == 4) { // For rounds below 20 if (level.round_number < 20) { max += int((player_num - 1) * level.zombie_vars["zombie_ai_per_player"] * multiplier); } // Calculate caps dynamically for rounds above 20 for four players if (level.round_number >= 20) { // Starting from 204 zombies at Round 20 base_zombies = 204; // Calculate zombies for rounds 20 to the current round, adding 9 zombies per round max = base_zombies + ((level.round_number - 20) * 9); } } if ( !isdefined( level.max_zombie_func ) ) level.max_zombie_func = ::default_max_zombie_func; if ( !( isdefined( level.kill_counter_hud ) && level.zombie_total > 0 ) ) { level.zombie_total = [[ level.max_zombie_func ]]( max ); level notify( "zombie_total_set" ); } if ( isdefined( level.zombie_total_set_func ) ) level thread [[ level.zombie_total_set_func ]](); if ( level.round_number < 10 || level.speed_change_max > 0 ) level thread zombie_speed_up(); mixed_spawns = 0; old_spawn = undefined; while ( true ) { while ( get_current_zombie_count() >= level.zombie_ai_limit || level.zombie_total <= 0 ) wait 0.1; while ( get_current_actor_count() >= level.zombie_actor_limit ) { clear_all_corpses(); wait 0.1; } flag_wait( "spawn_zombies" ); while ( level.zombie_spawn_locations.size <= 0 ) wait 0.1; run_custom_ai_spawn_checks(); spawn_point = level.zombie_spawn_locations[randomint( level.zombie_spawn_locations.size )]; if ( !isdefined( old_spawn ) ) old_spawn = spawn_point; else if ( spawn_point == old_spawn ) spawn_point = level.zombie_spawn_locations[randomint( level.zombie_spawn_locations.size )]; old_spawn = spawn_point; if ( isdefined( level.mixed_rounds_enabled ) && level.mixed_rounds_enabled == 1 ) { spawn_dog = 0; if ( level.round_number > 30 ) { if ( randomint( 100 ) < 3 ) spawn_dog = 1; } else if ( level.round_number > 25 && mixed_spawns < 3 ) { if ( randomint( 100 ) < 2 ) spawn_dog = 1; } else if ( level.round_number > 20 && mixed_spawns < 2 ) { if ( randomint( 100 ) < 2 ) spawn_dog = 1; } else if ( level.round_number > 15 && mixed_spawns < 1 ) { if ( randomint( 100 ) < 1 ) spawn_dog = 1; } if ( spawn_dog ) { keys = getarraykeys( level.zones ); for ( i = 0; i < keys.size; i++ ) { if ( level.zones[keys[i]].is_occupied ) { akeys = getarraykeys( level.zones[keys[i]].adjacent_zones ); for ( k = 0; k < akeys.size; k++ ) { if ( level.zones[akeys[k]].is_active && !level.zones[akeys[k]].is_occupied && level.zones[akeys[k]].dog_locations.size > 0 ) { maps\mp\zombies\_zm_ai_dogs::special_dog_spawn( undefined, 1 ); level.zombie_total--; wait_network_frame(); } } } } } } if ( isdefined( level.zombie_spawners ) ) { if ( isdefined( level.use_multiple_spawns ) && level.use_multiple_spawns ) { if ( isdefined( spawn_point.script_int ) ) { if ( isdefined( level.zombie_spawn[spawn_point.script_int] ) && level.zombie_spawn[spawn_point.script_int].size ) spawner = random( level.zombie_spawn[spawn_point.script_int] ); else { /# assertmsg( "Wanting to spawn from zombie group " + spawn_point.script_int + "but it doens't exist" ); #/ } } else if ( isdefined( level.zones[spawn_point.zone_name].script_int ) && level.zones[spawn_point.zone_name].script_int ) spawner = random( level.zombie_spawn[level.zones[spawn_point.zone_name].script_int] ); else if ( isdefined( level.spawner_int ) && ( isdefined( level.zombie_spawn[level.spawner_int].size ) && level.zombie_spawn[level.spawner_int].size ) ) spawner = random( level.zombie_spawn[level.spawner_int] ); else spawner = random( level.zombie_spawners ); } else spawner = random( level.zombie_spawners ); ai = spawn_zombie( spawner, spawner.targetname, spawn_point ); } if ( isdefined( ai ) ) { level.zombie_total--; ai thread round_spawn_failsafe(); count++; } wait( level.zombie_vars["zombie_spawn_delay"] ); wait_network_frame(); } }
What's the code doing:
It will check for 1, 2, 3 or 4 players and apply the corresponded code.
For 1 player for example, seems like from round 29 and onwards on CW, +2 zombies get added every odd round number and +3 for every even round number. On Round 100 you will end up with 275 zombies instead of 924.For 2 Players, round 29 onwards adds +5 zombies for odd rounds and +6 for even rounds.
For 3 players, from round 20 onwards, +8 zombies gets added every 5th round and +7 zombies for others rounds.
For 4 players, from round 20 onwards +9 zombies will be added every round.As for why I said it's a similar algorithm, from round (20/29 onwards) it's 99% identical to CW, but before that it uses the same old formula. I've tried doing maths and everything to create the same multiplier from CW but I'm not really good at coding. And looking at CW GSCs I can see they use lots of variables/multipliers for the calcs.
-
Nice, Having 510 Zombies in round 30 for 4 players is a LOT, changes like this makes high rounds when lots of people are in don't take way too much time and it's all just formulas and math to setup what you want .
-
Ivobardolf Exactly bro Such a good change that came in Cold War
-
Thanks for posting this!
You were pretty much spot on about round 20 and 29 being turning points! However, only solo has the 29 round cap.
If you want to learn more about Cold War's code, here's pseudo code for this exact function. I have replaced all hashes with their real values and changed variable names to make them more helpful to understand, unless they were unknown (only because the scriptbundle required does not exist). Then I put comments for hypothetical values. Round 1-5 are hardcoded values so I have included the max_zombie_func to show that. I hope this helps you understand the code behind it more! Feel free to ask questions. This is Pseudo Code. It will not compile!! Also the default_max_zombie_func will error if you don't handle more than 4 players!:get_zombie_count_for_round(n_round, n_player_count) { n_player_count = GetPlayers().size; max = zombie_utility::get_zombie_var(#"zombie_max_ai"); //We don't know - hardcoded in Cold War (assume 24) if (n_player_count == 1) { highestRound = 29; playerMult = 0.84; additionalMult = zombie_utility::get_zombie_var(#"hash_67b3cbf79292e047"); //We don't know - hardcoded in Cold War (0.5 in bo4) } else { highestRound = 20; playerMult = 0.6; additionalMult = 0.5 + n_player_count / 2; } if (n_round < var_8ca3a339) /*if the round is < 29 on solo OR < 20 on co-op do this*/ { playerMult = zombie_utility::get_zombie_var(#"hash_607bc50072c2a386"); //We don't know - hardcoded in Cold War (0.15 in bo4) multiplier = n_round / 5; if (multiplier < 1) { multiplier = 1; } multiplier *= n_round * playerMult; } else { multiplier = n_round * playerMult; } max += int(additionalMult * zombie_utility::get_zombie_var(#"zombie_ai_per_player") * multiplier); //zombie_ai_per_player is hardcoded in Cold War (we can assume 6) if (!isdefined(level.max_zombie_func)) { level.max_zombie_func = &default_max_zombie_func; } n_zombie_count = [[ level.max_zombie_func ]](max, n_round); return function_c112af8e(n_zombie_count); } default_max_zombie_func(max_num, n_round) { /# count = getdvarint(#"zombie_default_max", -1); if (count > -1) { return count; } #/ n_players = getplayers().size; round1Counts = array(6, 8, 11, 14, 17); round2Counts = array(9, 11, 14, 18, 21); round3Counts = array(13, 15, 20, 25, 31); round4Counts = array(18, 20, 25, 33, 40); round5Counts = array(24, 25, 32, 42, 48); switch (n_round) { case 1: max = round1Counts[n_players - 1]; break; case 2: max = round2Counts[n_players - 1]; break; case 3: max = round3Counts[n_players - 1]; break; case 4: max = round4Counts[n_players - 1]; break; case 5: max = round5Counts[n_players - 1]; break; default: max = max_num; break; } return max; }
Here's the result of said function.
This gets us to about
-
GerardS0406 Oh man that's reaaally nice, thanks! Will take a look when I have some free time