diff --git a/maps/bots/_bot_utility.gsc b/maps/bots/_bot_utility.gsc index d0a8a32..22445a5 100644 --- a/maps/bots/_bot_utility.gsc +++ b/maps/bots/_bot_utility.gsc @@ -285,6 +285,7 @@ AtScriptGoal() { return false; } + return distanceSquared( self.origin, self.bot.script_goal ) <= ( self.bot.script_goal_dist * self.bot.script_goal_dist ); } @@ -313,22 +314,6 @@ ClearPriorityObjective() self.bot.prio_objective = false; } -/* - Checks whether the path generated by the ASTAR path finding is inaccessible -*/ -GetPathIsInaccessible( to, best_effort ) -{ - if ( isDefined( best_effort ) ) - { - path = generatePath( self.origin, to, self.team, level.bot_allowed_negotiation_links, best_effort ); - } - else - { - path = generatePath( self.origin, to, self.team, level.bot_allowed_negotiation_links ); - } - return !isDefined( path ) || ( path.size <= 0) ; -} - /* Sets the aim position of the bot */ @@ -712,6 +697,9 @@ float( num ) return GetDvarFloat( "temp_dvar_bot_util" ); } +/* + returns nodes in playable area +*/ get_nodes_in_playable_area() { total_nodes = getAllNodes(); @@ -735,6 +723,9 @@ get_nodes_in_playable_area() return filtered_nodes; } +/* + is the point in playable area? +*/ is_point_in_playable_area( point ) { playable_area = getentarray( "playable_area", "targetname" ); @@ -1075,195 +1066,3 @@ targetIsGibbed() { return isDefined( self.gibbed ) && self.gibbed; } - -swap_array_index( array, index1, index2 ) -{ - temp = array[ index1 ]; - array[ index1 ] = array[ index2 ]; - array[ index2 ] = temp; - return array; -} - -quickSort(array, compare_func, compare_func_arg1) -{ - return quickSortMid( array, 0, array.size - 1, compare_func, compare_func_arg1 ); -} - -/* - Quicksort algorithm copied from T7 modified for T4 -*/ -quickSortMid( array, start, end, compare_func, compare_func_arg1 ) -{ - i = start; - k = end; - - if(!IsDefined(compare_func)) - compare_func = ::quicksort_compare; - - if (end - start >= 1) - { - pivot = array[start]; - - while (k > i) - { - while ( [[ compare_func ]](array[i], pivot, compare_func_arg1) && i <= end && k > i) - i++; - while ( ![[ compare_func ]](array[k], pivot, compare_func_arg1) && k >= start && k >= i) - k--; - if (k > i) - array = swap_array_index(array, i, k); - } - array = swap_array_index(array, start, k); - array = quickSortMid(array, start, k - 1, compare_func); - array = quickSortMid(array, k + 1, end, compare_func); - } - else - return array; - - return array; -} - -quicksort_compare(left, right, compare_func_arg1) -{ - return left <= right; -} - -quicksort_compare_priority_field(left, right, compare_func_arg1) -{ - return left.priority <= right.priority; -} - -quicksort_compare_pers_value_highest_to_lowest( left, right, compare_func_arg1 ) -{ - return left.pers[ compare_func_arg1 ] <= right.pers[ compare_func_arg1 ]; -} - -quicksort_compare_pers_value_lowest_to_highest( left, right, compare_func_arg1 ) -{ - return left.pers[ compare_func_arg1 ] >= right.pers[ compare_func_arg1 ]; -} - -assign_priority_to_powerup( powerup ) -{ - if ( !isDefined( powerup ) ) - { - return; - } - priority = 0; - powerup_is_max_ammo = false; - switch ( powerup.powerup_name ) - { - case "zombie_blood": - case "insta_kill": - case "nuke": - priority += 2; - break; - case "full_ammo": - powerup_is_max_ammo = true; - priority += 1; - break; - case "double_points": - case "fire_sale": - case "carpenter": - case "free_perk": - priority += 1; - break; - default: - priority += 0; - break; - } - if ( powerup_is_max_ammo ) - { - LOW_AMMO_THRESHOLD = 0.3; - - players = getPlayers(); - - for ( i = 0; i < players.size; i++ ) - { - weapons = players[ i ] getWeaponsListPrimaries(); - for ( j = 0; j < weapons.size; j++ ) - { - if ( players[ i ] getWeaponAmmoStock( weapons[ j ] ) <= int( weaponmaxammo( weapons[ j ] ) * LOW_AMMO_THRESHOLD ) ) - { - priority += 1; - break; - } - } - if ( priority > 3 ) - { - break; - } - } - } - - if ( maps\_laststand::player_any_player_in_laststand() ) - { - switch ( powerup.powerup_name ) - { - case "zombie_blood": - case "insta_kill": - case "nuke": - priority += 1; - break; - case "full_ammo": - priority += 0; - break; - case "double_points": - case "fire_sale": - case "carpenter": - case "free_perk": - priority -= 1; - break; - default: - priority += 0; - break; - } - } - - if ( powerup.time_left_until_timeout < 10.0 ) - { - priority += 1; - } - if ( priority < 0 ) - { - priority = 0; - } - powerup.priority = priority; -} - -sort_array_by_priority_field( array, item ) -{ - if ( isDefined( item ) ) - { - array[ array.size ] = item; - } - - array = quickSort( array, ::quicksort_compare_priority_field, undefined ); - return array; -} - -get_players_sorted_by_highest_pers_value( pers_name ) -{ - players = getPlayers(); - - if ( !isDefined( players[ 0 ].pers[ pers_name ] ) ) - { - assertMsg( "Uninitialized pers value: " + pers_name ); - return undefined; - } - - return quickSort( players, ::quicksort_compare_pers_value_highest_to_lowest, pers_name ); -} - -get_players_sorted_by_lowest_pers_value( pers_name ) -{ - players = getPlayers(); - - if ( !isDefined( players[ 0 ].pers[ pers_name ] ) ) - { - assertMsg( "Uninitialized pers value: " + pers_name ); - return undefined; - } - - return quickSort( players, ::quicksort_compare_pers_value_lowest_to_highest, pers_name ); -} \ No newline at end of file diff --git a/maps/bots/script_objectives/_obj_actions.gsc b/maps/bots/script_objectives/_obj_actions.gsc index 8f31b75..726afe3 100644 --- a/maps/bots/script_objectives/_obj_actions.gsc +++ b/maps/bots/script_objectives/_obj_actions.gsc @@ -2,11 +2,12 @@ #include maps\_utility; #include maps\bots\_bot_utility; #include maps\bots\script_objectives\_obj_common; +#include maps\bots\script_objectives\_obj_utility; bot_post_think_common( state ) { obj = bot_objective_history_get_current(); - + switch ( state ) { case "completed": @@ -20,7 +21,7 @@ bot_post_think_common( state ) self thread ClearScriptGoal(); self ClearScriptAimPos(); self ClearPriorityObjective(); - self bot_clear_objective(); + self bot_clear_objective(); } bot_obj_timeout( objective_group, time ) @@ -28,7 +29,7 @@ bot_obj_timeout( objective_group, time ) self endon( objective_group + "_end_think" ); wait time; self.obj_cancel_reason = "Obj timeout"; - self notify( objective_group + "_cancel" ); + self notify( objective_group + "_cancel" ); } bot_grab_powerup() @@ -77,7 +78,7 @@ bot_grab_powerup() powerup_obj.bad = true; } } - else + else { powerup_obj.bad = true; } @@ -187,7 +188,7 @@ bot_revive_player() level endon( "end_game" ); player_to_revive_obj = self.available_revives[ 0 ]; - + player_to_revive = player_to_revive_obj.target_ent; self bot_set_objective( "revive", player_to_revive ); self bot_set_objective_owner( "revive", player_to_revive ); @@ -332,7 +333,7 @@ bot_magicbox_purchase() level endon( "end_game" ); magicbox_obj = self.available_chests[ 0 ]; - + magicbox = magicbox_obj.target_ent; self bot_set_objective( "magicbox", magicbox ); //self bot_set_objective_owner( "magicbox", magicbox ); @@ -470,7 +471,7 @@ bot_should_purchase_magicbox() return self.available_chests.size > 0; } -bot_check_complete_purchase_magicbox() +bot_check_complete_purchase_magicbox() { return self.successfully_grabbed_magicbox_weapon; } @@ -492,13 +493,13 @@ bot_magicbox_purchase_should_cancel() goal_canceled = true; } */ - if ( isDefined( obj.magicbox_weapon_spawn_time ) - && isDefined( obj.target_ent.chest_user ) + if ( isDefined( obj.magicbox_weapon_spawn_time ) + && isDefined( obj.target_ent.chest_user ) && obj.target_ent.chest_user == self && ( getTime() >= ( obj.magicbox_weapon_spawn_time + 12000 ) ) ) { self.obj_cancel_reason = "Weapon timed out"; - goal_canceled = true; + goal_canceled = true; } return goal_canceled; } @@ -537,7 +538,7 @@ bot_perk_purchase() level endon( "end_game" ); perk_obj = self.available_perks[ 0 ]; - + perk_ent = perk_obj.target_ent; self bot_set_objective( "perk", perk_ent ); self bot_objective_print( "perk", perk_obj.id, "Bot <" + self.playername + "> Attempting to purchase " + perk_ent.script_noteworthy, "bot_perk_purchase" ); @@ -660,7 +661,7 @@ bot_door_purchase() level endon( "end_game" ); door_obj = self.available_doors[ 0 ]; - + door_ent = door_obj.target_ent; self bot_set_objective( "door", door_ent ); self bot_objective_print( "door", door_obj.id, "Bot <" + self.playername + "> Attempting to purchase " + door_ent.target, "bot_door_purchase" ); @@ -759,7 +760,7 @@ bot_debris_purchase() level endon( "end_game" ); debris_obj = self.available_debris[ 0 ]; - + debris_ent = debris_obj.target_ent; self bot_set_objective( "debris", debris_ent ); self bot_objective_print( "debris", debris_obj.id, "Bot <" + self.playername + "> Attempting to purchase " + debris_ent.target, "bot_debris_purchase" ); @@ -852,7 +853,7 @@ bot_wallbuy_purchase() level endon( "end_game" ); wallbuy_obj = self.available_wallbuys[ 0 ]; - + wallbuy_ent = wallbuy_obj.target_ent; self bot_set_objective( "wallbuy", wallbuy_ent ); self bot_objective_print( "wallbuy", wallbuy_obj.id, "Bot <" + self.playername + "> Attempting to purchase " + wallbuy_ent.zombie_weapon_upgrade, "bot_wallbuy_purchase" ); @@ -952,7 +953,7 @@ bot_wallbuy_ammo_purchase() level endon( "end_game" ); wallbuy_obj = self.available_wallbuyammos[ 0 ]; - + wallbuy_ent = wallbuy_obj.target_ent; self bot_set_objective( "wallbuyammo", wallbuy_ent ); self bot_objective_print( "wallbuyammo", wallbuy_obj.id, "Bot <" + self.playername + "> Attempting to purchase " + wallbuy_ent.zombie_weapon_upgrade, "bot_wallbuy_ammo_purchase" ); @@ -1057,7 +1058,7 @@ bot_packapunch_purchase() level endon( "end_game" ); packapunch_obj = self.available_packapunchs[ 0 ]; - + packapunch = packapunch_obj.target_ent; self bot_set_objective( "packapunch", packapunch ); //self bot_set_objective_owner( "magicbox", magicbox ); @@ -1086,7 +1087,7 @@ bot_packapunch_purchase() waittillframeend; //self ClearScriptAimPos(); //self ClearScriptGoal(); - + packapunch waittill( "pap_pickup_ready" ); self bot_objective_print( "packapunch", packapunch_obj.id, "Bot <" + self.playername + "> pap_pickup_ready", "bot_packapunch_purchase" ); @@ -1160,13 +1161,13 @@ bot_packapunch_purchase_should_cancel() obj = self bot_get_objective(); goal_canceled = false; - if ( isDefined( obj.target_ent.packapunch_weapon_spawn_time ) - && isDefined( obj.target_ent.packapunch_user ) - && obj.target_ent.packapunch_user == self + if ( isDefined( obj.target_ent.packapunch_weapon_spawn_time ) + && isDefined( obj.target_ent.packapunch_user ) + && obj.target_ent.packapunch_user == self && ( getTime() >= ( obj.target_ent_packapunch_weapon_spawn_time + ( level.packapunch_timeout * 1000 ) ) ) ) { self.obj_cancel_reason = "Weapon timed out"; - goal_canceled = true; + goal_canceled = true; } return goal_canceled; } @@ -1188,10 +1189,10 @@ bot_power_activate() level endon( "end_game" ); power_obj = self.available_powers[ 0 ]; - + power_ent = power_obj.target_ent; self bot_set_objective( "power", power_ent ); - self bot_objective_print( "power", power_obj.id, "Bot <" + self.playername + "> Attempting to activate power" "bot_power_activate" ); + self bot_objective_print( "power", power_obj.id, "Bot <" + self.playername + "> Attempting to activate power", "bot_power_activate" ); lookat_org = power_ent.origin; goal_org = power_ent.bot_use_node; @@ -1220,7 +1221,7 @@ bot_power_activate_init() self.successfully_activated_power = false; } -bot_power_activate_post_think() +bot_power_activate_post_think(state) { self bot_post_think_common( state ); self.successfully_activated_power = false; @@ -1263,7 +1264,7 @@ bot_power_activate_should_cancel() if ( isDefined( level.flag[ "power_on" ] ) && level.flag[ "power_on" ] ) { self.obj_cancel_reason = "Power is already on"; - goal_canceled = true; + goal_canceled = true; } return goal_canceled; } @@ -1271,4 +1272,4 @@ bot_power_activate_should_cancel() bot_power_activate_priority() { return 0; -} \ No newline at end of file +} diff --git a/maps/bots/script_objectives/_obj_common.gsc b/maps/bots/script_objectives/_obj_common.gsc index 8b7018d..067676f 100644 --- a/maps/bots/script_objectives/_obj_common.gsc +++ b/maps/bots/script_objectives/_obj_common.gsc @@ -1,6 +1,7 @@ #include common_scripts\utility; #include maps\_utility; #include maps\bots\_bot_utility; +#include maps\bots\script_objectives\_obj_utility; register_bot_objective( objective_group ) { @@ -95,7 +96,7 @@ bot_set_objective( objective_group, ent, id ) { self.bot_obj_history_index = 0; } - + self.obj_history[ self.bot_obj_history_index ] = new_obj_history; self.zbot_current_objective = objective; } @@ -167,7 +168,7 @@ bot_set_objective_owner( objective_group, ent, id ) { id = ent getEntityNumber(); } - + if ( !objective.is_global_shared ) { objective_assert( objective_group, id, "bot_set_objective_owner", "Objective with " + id + " id number cannot be set to have an owner because is_global_shared field is false in group " + objective_group ); @@ -489,7 +490,7 @@ bot_action_think() { wait 1; } - else + else { wait 1; } @@ -505,7 +506,7 @@ bot_action_think() } continue; } - + self bot_process_action(); while ( !maps\so\zm_common\_zm_utility::is_player_valid( self ) ) @@ -542,7 +543,7 @@ bot_action_pump() else if ( self bot_check_if_action_should_be_canceled_in_group( action_name ) ) { } - + while ( !maps\so\zm_common\_zm_utility::is_player_valid( self ) ) { wait 1; @@ -624,4 +625,4 @@ clamp_to_ground( org ) { trace = playerPhysicsTrace( org + ( 0, 0, 20 ), org - ( 0, 0, 2000 ) ); return trace; -} \ No newline at end of file +} diff --git a/maps/bots/script_objectives/_obj_init.gsc b/maps/bots/script_objectives/_obj_init.gsc index d96d4b0..388904c 100644 --- a/maps/bots/script_objectives/_obj_init.gsc +++ b/maps/bots/script_objectives/_obj_init.gsc @@ -1,13 +1,14 @@ #include common_scripts\utility; #include maps\_utility; #include maps\bots\_bot_utility; +#include maps\bots\script_objectives\_obj_utility; #include maps\bots\script_objectives\_obj_common; #include maps\bots\script_objectives\_obj_actions; #include maps\bots\script_objectives\_obj_trackers; init() { - register_bot_action( "powerup", + register_bot_action( "powerup", ::bot_grab_powerup, ::bot_powerup_init, ::bot_powerup_post_think, @@ -16,7 +17,7 @@ init() ::bot_powerup_should_cancel, ::bot_powerup_priority ); - register_bot_action( "revive", + register_bot_action( "revive", ::bot_revive_player, ::bot_revive_player_init, ::bot_revive_player_post_think, @@ -25,7 +26,7 @@ init() ::bot_revive_player_should_cancel, ::bot_revive_player_priority ); - register_bot_action( "magicbox", + register_bot_action( "magicbox", ::bot_magicbox_purchase, ::bot_magicbox_purchase_init, ::bot_magicbox_purchase_post_think, @@ -34,7 +35,7 @@ init() ::bot_magicbox_purchase_should_cancel, ::bot_magicbox_purchase_priority ); - register_bot_action( "perk", + register_bot_action( "perk", ::bot_perk_purchase, ::bot_perk_purchase_init, ::bot_perk_purchase_post_think, @@ -43,7 +44,7 @@ init() ::bot_perk_purchase_should_cancel, ::bot_perk_purchase_priority ); - register_bot_action( "door", + register_bot_action( "door", ::bot_door_purchase, ::bot_door_purchase_init, ::bot_door_purchase_post_think, @@ -52,7 +53,7 @@ init() ::bot_door_purchase_should_cancel, ::bot_door_purchase_priority ); - register_bot_action( "debris", + register_bot_action( "debris", ::bot_debris_purchase, ::bot_debris_purchase_init, ::bot_debris_purchase_post_think, @@ -61,7 +62,7 @@ init() ::bot_debris_purchase_should_cancel, ::bot_debris_purchase_priority ); - register_bot_action( "wallbuy", + register_bot_action( "wallbuy", ::bot_wallbuy_purchase, ::bot_wallbuy_purchase_init, ::bot_wallbuy_purchase_post_think, @@ -70,7 +71,7 @@ init() ::bot_wallbuy_purchase_should_cancel, ::bot_wallbuy_purchase_priority ); - register_bot_action( "wallbuyammo", + register_bot_action( "wallbuyammo", ::bot_wallbuy_ammo_purchase, ::bot_wallbuy_ammo_purchase_init, ::bot_wallbuy_ammo_purchase_post_think, @@ -79,7 +80,7 @@ init() ::bot_wallbuy_ammo_purchase_should_cancel, ::bot_wallbuy_ammo_purchase_priority ); - register_bot_action( "packapunch", + register_bot_action( "packapunch", ::bot_packapunch_purchase, ::bot_packapunch_purchase_init, ::bot_packapunch_purchase_post_think, @@ -88,7 +89,7 @@ init() ::bot_packapunch_purchase_should_cancel, ::bot_packapunch_purchase_priority ); - register_bot_action( "power", + register_bot_action( "power", ::bot_power_activate, ::bot_power_activate_init, ::bot_power_activate_post_think, diff --git a/maps/bots/script_objectives/_obj_trackers.gsc b/maps/bots/script_objectives/_obj_trackers.gsc index a12a972..5f73039 100644 --- a/maps/bots/script_objectives/_obj_trackers.gsc +++ b/maps/bots/script_objectives/_obj_trackers.gsc @@ -2,6 +2,7 @@ #include maps\_utility; #include maps\bots\_bot_utility; #include maps\bots\script_objectives\_obj_common; +#include maps\bots\script_objectives\_obj_utility; create_static_objectives() { @@ -65,7 +66,7 @@ create_static_objectives() { setDvar( "power_node_angle", -90 ); } - weapon_spawns = GetEntArray( "weapon_upgrade", "targetname" ); + weapon_spawns = GetEntArray( "weapon_upgrade", "targetname" ); if ( isDefined( weapon_spawns ) && weapon_spawns.size > 0 ) { @@ -93,8 +94,8 @@ create_static_objectives() } //TODO: See if its possible to automatically detect if a door is blocking an objective - zombie_doors = GetEntArray( "zombie_door", "targetname" ); - + zombie_doors = GetEntArray( "zombie_door", "targetname" ); + if ( isDefined( zombie_doors ) && zombie_doors.size > 0 ) { for ( i = 0; i < zombie_doors.size; i++ ) @@ -108,7 +109,7 @@ create_static_objectives() level thread watch_door_objectives( zombie_doors ); } - zombie_debris = GetEntArray( "zombie_debris", "targetname" ); + zombie_debris = GetEntArray( "zombie_debris", "targetname" ); if ( isDefined( zombie_debris ) && zombie_debris.size > 0 ) { @@ -141,7 +142,7 @@ create_static_objectives() { obj = add_possible_bot_objective( "power", master_switch, false ); master_switch.bot_use_node = master_switch get_angle_offset_node( getDvarInt( "power_node_forward_size" ), ( 0, getDvarInt( "power_node_angle" ), 0 ), ( 0, 0, getDvarInt( "power_node_vertical_offset" ) ) ); - model thread power_debug(); + //model thread power_debug(); } if ( isDefined( level.chests ) && level.chests.size > 0 ) @@ -346,7 +347,7 @@ packapunch_debug() self.bot_use_node = node; line( self.origin, node, ( 1.0, 1.0, 1.0 ) ); wait 0.05; - } + } } bot_on_powerup_grab( powerup ) @@ -397,4 +398,4 @@ bot_on_wallbuy_ammo_purchase_func( trigger, weapon ) { self bot_objective_print( "wallbuyammo", trigger getEntityNumber(), "bot_on_wallbuy_ammo_purchase_func", "Bot <" + self.playername + "> purchased wallbuy ammo <" + weapon + ">" ); self.successfully_bought_wallbuy_ammo = true; -} \ No newline at end of file +} diff --git a/maps/bots/script_objectives/_obj_utility.gsc b/maps/bots/script_objectives/_obj_utility.gsc new file mode 100644 index 0000000..b0c7f41 --- /dev/null +++ b/maps/bots/script_objectives/_obj_utility.gsc @@ -0,0 +1,211 @@ +#include common_scripts\utility; +#include maps\_utility; +#include maps\bots\_bot_utility; + +/* + Checks whether the path generated by the ASTAR path finding is inaccessible +*/ +GetPathIsInaccessible( to, best_effort ) +{ + if ( isDefined( best_effort ) ) + { + path = generatePath( self.origin, to, self.team, level.bot_allowed_negotiation_links, best_effort ); + } + else + { + path = generatePath( self.origin, to, self.team, level.bot_allowed_negotiation_links ); + } + return !isDefined( path ) || ( path.size <= 0) ; +} + +swap_array_index( array, index1, index2 ) +{ + temp = array[ index1 ]; + array[ index1 ] = array[ index2 ]; + array[ index2 ] = temp; + return array; +} + +quickSort(array, compare_func, compare_func_arg1) +{ + return quickSortMid( array, 0, array.size - 1, compare_func, compare_func_arg1 ); +} + +/* + Quicksort algorithm copied from T7 modified for T4 +*/ +quickSortMid( array, start, end, compare_func, compare_func_arg1 ) +{ + i = start; + k = end; + + if(!IsDefined(compare_func)) + compare_func = ::quicksort_compare; + + if (end - start >= 1) + { + pivot = array[start]; + + while (k > i) + { + while ( [[ compare_func ]](array[i], pivot, compare_func_arg1) && i <= end && k > i) + i++; + while ( ![[ compare_func ]](array[k], pivot, compare_func_arg1) && k >= start && k >= i) + k--; + if (k > i) + array = swap_array_index(array, i, k); + } + array = swap_array_index(array, start, k); + array = quickSortMid(array, start, k - 1, compare_func); + array = quickSortMid(array, k + 1, end, compare_func); + } + else + return array; + + return array; +} + +quicksort_compare(left, right, compare_func_arg1) +{ + return left <= right; +} + +quicksort_compare_priority_field(left, right, compare_func_arg1) +{ + return left.priority <= right.priority; +} + +quicksort_compare_pers_value_highest_to_lowest( left, right, compare_func_arg1 ) +{ + return left.pers[ compare_func_arg1 ] <= right.pers[ compare_func_arg1 ]; +} + +quicksort_compare_pers_value_lowest_to_highest( left, right, compare_func_arg1 ) +{ + return left.pers[ compare_func_arg1 ] >= right.pers[ compare_func_arg1 ]; +} + +assign_priority_to_powerup( powerup ) +{ + if ( !isDefined( powerup ) ) + { + return; + } + priority = 0; + powerup_is_max_ammo = false; + switch ( powerup.powerup_name ) + { + case "zombie_blood": + case "insta_kill": + case "nuke": + priority += 2; + break; + case "full_ammo": + powerup_is_max_ammo = true; + priority += 1; + break; + case "double_points": + case "fire_sale": + case "carpenter": + case "free_perk": + priority += 1; + break; + default: + priority += 0; + break; + } + if ( powerup_is_max_ammo ) + { + LOW_AMMO_THRESHOLD = 0.3; + + players = getPlayers(); + + for ( i = 0; i < players.size; i++ ) + { + weapons = players[ i ] getWeaponsListPrimaries(); + for ( j = 0; j < weapons.size; j++ ) + { + if ( players[ i ] getWeaponAmmoStock( weapons[ j ] ) <= int( weaponmaxammo( weapons[ j ] ) * LOW_AMMO_THRESHOLD ) ) + { + priority += 1; + break; + } + } + if ( priority > 3 ) + { + break; + } + } + } + + if ( maps\_laststand::player_any_player_in_laststand() ) + { + switch ( powerup.powerup_name ) + { + case "zombie_blood": + case "insta_kill": + case "nuke": + priority += 1; + break; + case "full_ammo": + priority += 0; + break; + case "double_points": + case "fire_sale": + case "carpenter": + case "free_perk": + priority -= 1; + break; + default: + priority += 0; + break; + } + } + + if ( powerup.time_left_until_timeout < 10.0 ) + { + priority += 1; + } + if ( priority < 0 ) + { + priority = 0; + } + powerup.priority = priority; +} + +sort_array_by_priority_field( array, item ) +{ + if ( isDefined( item ) ) + { + array[ array.size ] = item; + } + + array = quickSort( array, ::quicksort_compare_priority_field, undefined ); + return array; +} + +get_players_sorted_by_highest_pers_value( pers_name ) +{ + players = getPlayers(); + + if ( !isDefined( players[ 0 ].pers[ pers_name ] ) ) + { + assertMsg( "Uninitialized pers value: " + pers_name ); + return undefined; + } + + return quickSort( players, ::quicksort_compare_pers_value_highest_to_lowest, pers_name ); +} + +get_players_sorted_by_lowest_pers_value( pers_name ) +{ + players = getPlayers(); + + if ( !isDefined( players[ 0 ].pers[ pers_name ] ) ) + { + assertMsg( "Uninitialized pers value: " + pers_name ); + return undefined; + } + + return quickSort( players, ::quicksort_compare_pers_value_lowest_to_highest, pers_name ); +}