From 1c835bd77b9801217545710da18ee52e128ba813 Mon Sep 17 00:00:00 2001 From: JezuzLizard Date: Mon, 1 May 2023 08:09:33 -0700 Subject: [PATCH] Improve action system. Fix objective system to use entity numbers instead of infinitely increasing ids. Fix all known script errors. Add the ability for bots to revive players and pickup powerups automatically. --- maps/bots/_bot.gsc | 67 ++++++--- maps/bots/_bot_script.gsc | 301 +++++++++++++++++++++++-------------- maps/bots/_bot_utility.gsc | 34 ++++- 3 files changed, 255 insertions(+), 147 deletions(-) diff --git a/maps/bots/_bot.gsc b/maps/bots/_bot.gsc index 5006295..46f7d74 100644 --- a/maps/bots/_bot.gsc +++ b/maps/bots/_bot.gsc @@ -112,33 +112,30 @@ init() level thread onPlayerConnect(); level thread handleBots(); - maps\_bot_script::register_bot_action( "objective", "powerup", maps\_bot_script::bot_grab_powerup, - maps\_bot_script::bot_powerup_process_order, - maps\_bot_script::bot_should_grab_powerup, - maps\_bot_script::bot_check_complete_grab_powerup, - maps\_bot_script::bot_set_complete_grab_powerup, - maps\_bot_script::bot_powerup_on_completion, - maps\_bot_script::bot_powerup_should_cancel, - maps\_bot_script::bot_powerup_on_cancel, - maps\_bot_script::bot_powerup_should_postpone, - maps\_bot_script::bot_powerup_on_postpone, - maps\_bot_script::bot_powerup_priority ); + maps\bots\_bot_script::register_bot_action( "objective", "powerup", maps\bots\_bot_script::bot_grab_powerup, + maps\bots\_bot_script::bot_powerup_process_order, + maps\bots\_bot_script::bot_powerup_init, + maps\bots\_bot_script::bot_powerup_post_think, + maps\bots\_bot_script::bot_should_grab_powerup, + maps\bots\_bot_script::bot_check_complete_grab_powerup, + maps\bots\_bot_script::bot_powerup_should_cancel, + maps\bots\_bot_script::bot_powerup_should_postpone, + maps\bots\_bot_script::bot_powerup_priority ); - maps\_bot_script::register_bot_action( "objective", "revive", maps\_bot_script::bot_revive_player, - maps\_bot_script::bot_revive_process_order, - maps\_bot_script::bot_should_revive_player, - maps\_bot_script::bot_check_complete_revive_player, - maps\_bot_script::bot_set_complete_revive_player, - maps\_bot_script::bot_revive_player_on_completion, - maps\_bot_script::bot_revive_player_should_cancel, - maps\_bot_script::bot_revive_player_on_cancel, - maps\_bot_script::bot_revive_player_should_postpone, - maps\_bot_script::bot_revive_player_on_postpone, - maps\_bot_script::bot_revive_player_priority ); - maps\_bot_script::register_bot_objective( "powerup" ); + maps\bots\_bot_script::register_bot_action( "objective", "revive", maps\bots\_bot_script::bot_revive_player, + maps\bots\_bot_script::bot_revive_process_order, + maps\bots\_bot_script::bot_revive_player_init, + maps\bots\_bot_script::bot_revive_player_post_think, + maps\bots\_bot_script::bot_should_revive_player, + maps\bots\_bot_script::bot_check_complete_revive_player, + maps\bots\_bot_script::bot_revive_player_should_cancel, + maps\bots\_bot_script::bot_revive_player_should_postpone, + maps\bots\_bot_script::bot_revive_player_priority ); + maps\bots\_bot_script::register_bot_objective( "powerup" ); + maps\bots\_bot_script::register_bot_objective( "revive" ); - level thread maps\_bot_script::store_powerups_dropped(); - level thread maps\_bot_script::watch_for_downed_players(); + level thread maps\bots\_bot_script::store_powerups_dropped(); + level thread maps\bots\_bot_script::watch_for_downed_players(); } /* @@ -179,6 +176,22 @@ onPlayerDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, self [[level.prevCallbackPlayerDamage]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, modelIndex, psOffsetTime ); } +on_actor_spawned() +{ + if ( isDefined( level.prevCallbackActorSpawned ) ) + { + self [[ level.prevCallbackActorSpawned ]](); + } +} + +on_actor_killed( eInflictor, eAttacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, iTimeOffset ) +{ + if ( isDefined( level.prevCallbackActorKilled ) ) + { + self [[ level.prevCallbackActorKilled ]]( eInflictor, eAttacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, iTimeOffset ); + } +} + /* Starts the callbacks. */ @@ -187,6 +200,10 @@ hook_callbacks() wait 0.05; level.prevCallbackPlayerDamage = level.callbackPlayerDamage; level.callbackPlayerDamage = ::onPlayerDamage; + level.prevCallbackActorSpawned = level.callbackActorSpawned; + level.callbackActorSpawned = ::on_actor_spawned; + level.prevCallbackActorKilled = level.callbackActorKilled; + level.callbackActorKilled = ::on_actor_killed; } /* diff --git a/maps/bots/_bot_script.gsc b/maps/bots/_bot_script.gsc index 7cba1f2..dc0764a 100644 --- a/maps/bots/_bot_script.gsc +++ b/maps/bots/_bot_script.gsc @@ -22,6 +22,10 @@ connected() self thread difficulty(); self thread onBotSpawned(); self thread onSpawned(); + self thread initialize_bot_actions_queue(); + + self.on_powerup_grab_func = ::bot_on_powerup_grab; + self.on_revive_success_func = ::bot_on_revive_success; } /* @@ -385,15 +389,22 @@ register_bot_objective( objective_group ) } } -add_possible_bot_objective( objective_group, id, is_global_shared, target_ent ) +add_possible_bot_objective( objective_group, target_ent, is_global_shared ) { assert( isDefined( level.zbot_objective_glob ), "Trying to add objective before calling register_bot_objective" ); assert( isDefined( level.zbot_objective_glob[ objective_group ] ), "Trying to add objective to group " + objective_group + " before calling register_bot_objective" ); + if ( !isDefined( target_ent ) ) + { + assertMsg( "target_ent is undefined" ); + return; + } + + id = target_ent getEntityNumber(); + objective_struct = spawnStruct(); objective_struct.group = objective_group; - objective_struct.id = id; objective_struct.is_global_shared = is_global_shared; objective_struct.target_ent = target_ent; objective_struct.owner = undefined; @@ -402,8 +413,16 @@ add_possible_bot_objective( objective_group, id, is_global_shared, target_ent ) level.zbot_objective_glob[ objective_group ].active_objectives[ "obj_id_" + id ] = objective_struct; } -get_bot_objective_by_id( objective_group, id ) +get_bot_objective_by_entity_ref( objective_group, ent ) { + if ( !isDefined( ent ) ) + { + assertMsg( "Ent is undefined" ); + return; + } + + id = ent getEntityNumber(); + active_objectives = level.zbot_objective_glob[ objective_group ].active_objectives; objective = active_objectives[ "obj_id_" + id ]; @@ -418,10 +437,18 @@ get_all_objectives_for_group( objective_group ) return level.zbot_objective_glob[ objective_group ].active_objectives; } -set_objective_for_bot( objective_group, id ) +set_objective_for_bot( objective_group, ent ) { + if ( !isDefined( ent ) ) + { + assertMsg( "Ent is undefined" ); + return; + } + possible_objectives = level.zbot_objective_glob[ objective_group ].active_objectives; + id = ent getEntityNumber(); + objective = possible_objectives[ "obj_id_" + id ]; objective_exists = isDefined( objective ); @@ -440,8 +467,24 @@ clear_objective_for_bot() self.zbot_current_objective = undefined; } -set_bot_objective_blocked_by_objective( primary_objective_group, primary_id, blocked_by_objective_group, blocked_by_id ) +set_bot_objective_blocked_by_objective( primary_objective_group, primary_ent, blocked_by_objective_group, blocked_by_ent ) { + if ( !isDefined( primary_ent ) ) + { + assertMsg( "Primary_ent is undefined" ); + return; + } + + if ( !isDefined( blocked_by_ent ) ) + { + assertMsg( "Blocked_by_ent is undefined" ); + return; + } + + primary_id = primary_ent getEntityNumber(); + + blocked_by_id = blocked_by_ent getEntityNumber(); + primary_active_objectives = level.zbot_objective_glob[ primary_objective_group ].active_objectives; primary_objective = primary_active_objectives[ "obj_id_" + primary_id ]; @@ -491,8 +534,16 @@ set_bot_objective_blocked_by_objective( primary_objective_group, primary_id, blo } } -set_bot_global_shared_objective_owner_by_id( objective_group, id, new_owner ) +set_bot_global_shared_objective_owner_by_ent( objective_group, ent, new_owner ) { + if ( !isDefined( ent ) ) + { + assertMsg( "Ent is undefined" ); + return; + } + + id = ent getEntityNumber(); + active_objectives = level.zbot_objective_glob[ objective_group ].active_objectives; objective = active_objectives[ "obj_id_" + id ]; @@ -530,9 +581,17 @@ set_bot_global_shared_objective_owner_by_reference( objective_group, objective, objective.owner = new_owner; } -free_bot_objective( objective_group, id ) +free_bot_objective( objective_group, ent ) { - active_objectives = level.zbot_global_shared_objective_glob[ objective_group ].active_objectives; + if ( !isDefined( ent ) ) + { + assertMsg( "Ent is undefined" ); + return; + } + + id = ent getEntityNumber(); + + active_objectives = level.zbot_objective_glob[ objective_group ].active_objectives; objective = active_objectives[ "obj_id_" + id ]; @@ -555,10 +614,10 @@ free_bot_objective( objective_group, id ) } } - objective = undefined; + active_objectives[ "obj_id_" + id ] = undefined; } -register_bot_action( group_name, action_name, action_func, action_process_order_func, should_do_func, check_if_complete_func, set_complete_func, on_completion_func, should_cancel_func, on_cancel_func, should_postpone_func, on_postpone_func, priority_func ) +register_bot_action( group_name, action_name, action_func, action_process_order_func, init_func, post_think_func, should_do_func, check_if_complete_func, should_cancel_func, should_postpone_func, priority_func ) { if ( !isDefined( level.zbots_actions ) ) { @@ -573,23 +632,23 @@ register_bot_action( group_name, action_name, action_func, action_process_order_ level.zbots_actions[ group_name ][ action_name ] = spawnStruct(); } level.zbots_actions[ group_name ][ action_name ].action = action_func; + level.zbots_actions[ group_name ][ action_name ].init_func = init_func; + level.zbots_actions[ group_name ][ action_name ].post_think_func = post_think_func; level.zbots_actions[ group_name ][ action_name ].should_do_func = should_do_func; level.zbots_actions[ group_name ][ action_name ].action_process_order_func = action_process_order_func; level.zbots_actions[ group_name ][ action_name ].check_if_complete_func = check_if_complete_func; - level.zbots_actions[ group_name ][ action_name ].set_complete_func = set_complete_func; - level.zbots_actions[ group_name ][ action_name ].on_completion_func = on_completion_func; level.zbots_actions[ group_name ][ action_name ].should_cancel_func = should_cancel_func; - level.zbots_actions[ group_name ][ action_name ].on_cancel_func = on_cancel_func; level.zbots_actions[ group_name ][ action_name ].should_postpone_func = should_postpone_func; - level.zbots_actions[ group_name ][ action_name ].on_postpone_func = on_postpone_func; level.zbots_actions[ group_name ][ action_name ].priority_func = priority_func; } initialize_bot_actions_queue() { + self.action_queue = []; group_keys = getArrayKeys( level.zbots_actions ); for ( i = 0; i < group_keys.size; i++ ) { + self.action_queue[ group_keys[ i ] ] = []; action_keys = getArrayKeys( level.zbots_actions[ group_keys[ i ] ] ); for ( j = 0; j < action_keys.size; j++ ) { @@ -613,9 +672,7 @@ register_bot_objective_action_for_queue( group_name, action_name ) self.zbot_actions_in_queue[ group_name ][ action_name ] = spawnStruct(); } self.zbot_actions_in_queue[ group_name ][ action_name ].postponed = false; - self.zbot_actions_in_queue[ group_name ][ action_name ].canceled = false; self.zbot_actions_in_queue[ group_name ][ action_name ].queued = false; - self.zbot_actions_in_queue[ group_name ][ action_name ].completed = false; self.zbot_actions_in_queue[ group_name ][ action_name ].is_current = false; } @@ -628,6 +685,8 @@ process_next_queued_action( group_name ) self.action_queue[ group_name ] = self sort_array_by_priority_field( self.action_queue[ group_name ] ); + self [[ self.action_queue[ group_name ][ 0 ].init_func ]](); + self thread [[ self.action_queue[ group_name ][ 0 ].action ]](); self.zbot_actions_in_queue[ group_name ][ self.action_queue[ group_name ][ 0 ].action_name ].is_current = true; @@ -646,48 +705,47 @@ wait_for_action_completion( group_name, action_name ) action_postpone_name = action_name + "_postpone"; result = self waittill_any_return( action_complete_name, action_cancel_name, action_postpone_name ); + + save_action = false; + + end_state = undefined; + if ( ( result == action_complete_name ) ) { self.zbot_actions_in_queue[ group_name ][ action_name ].postponed = false; self.zbot_actions_in_queue[ group_name ][ action_name ].queued = false; - self.zbot_actions_in_queue[ group_name ][ action_name ].completed = false; - self.action_queue[ group_name ][ 0 ] = undefined; - self thread [[ self.action_queue[ group_name ][ 0 ].on_completion_func ]](); + end_state = "completed"; } else if ( result == action_cancel_name ) { self.zbot_actions_in_queue[ group_name ][ action_name ].postponed = false; self.zbot_actions_in_queue[ group_name ][ action_name ].queued = false; - self.zbot_actions_in_queue[ group_name ][ action_name ].completed = false; - self.action_queue[ group_name ][ 0 ] = undefined; - self thread [[ self.action_queue[ group_name ][ 0 ].on_cancel_func ]](); + end_state = "canceled"; } else if ( result == action_postpone_name ) { self.zbot_actions_in_queue[ group_name ][ action_name ].postponed = true; - postponed_action = self.action_queue[ group_name ][ 0 ]; - self.action_queue[ group_name ][ 0 ] = undefined; - postponed_action.priority = self [[ level.zbots_actions[ group_name ][ action_name ].priority_func ]](); - self.action_queue[ group_name ] = array_insert( self.action_queue[ group_name ], postponed_action, 1 ); - self thread [[ self.action_queue[ group_name ][ 0 ].on_postpone_func ]](); + save_action = true; + end_state = "postponed"; } + self.zbot_actions_in_queue[ group_name ][ action_name ].is_current = false; + self notify( action_name + "_end_think" ); - self.zbot_actions_in_queue[ group_name ][ action_name ].is_current = false; -} + self [[ self.action_queue[ group_name ][ 0 ].post_think_func ]]( end_state ); -copy_default_action_settings_to_queue( group_name, action_name ) -{ - //self.group = level.zbots_actions[ group_name ][ action_name ].group; - self.action = level.zbots_actions[ group_name ][ action_name ].action; - //self.should_do_func = level.zbots_actions[ group_name ][ action_name ].should_do_func; - self.on_completion_func = level.zbots_actions[ group_name ][ action_name ].on_completion_func; - self.should_cancel_func = level.zbots_actions[ group_name ][ action_name ].should_cancel_func; - self.on_cancel_func = level.zbots_actions[ group_name ][ action_name ].on_cancel_func; - self.should_postpone_func = level.zbots_actions[ group_name ][ action_name ].should_postpone_func; - self.on_postpone_func = level.zbots_actions[ group_name ][ action_name ].on_postpone_func; - self.priority_func = level.zbots_actions[ group_name ][ action_name ].priority_func; + if ( save_action ) + { + postponed_action = self.action_queue[ group_name ][ 0 ]; + postponed_action.priority = self [[ level.zbots_actions[ group_name ][ action_name ].priority_func ]](); + self.action_queue[ group_name ] = array_insert( self.action_queue[ group_name ], postponed_action, 2 ); + self.action_queue[ group_name ][ 0 ] = undefined; + } + else + { + self.action_queue[ group_name ][ 0 ] = undefined; + } } pick_actions_to_add_to_queue( group_name ) @@ -803,7 +861,7 @@ bot_action_think() while ( true ) { - wait 0.05; + wait 1; group_name = "objective"; @@ -852,12 +910,9 @@ bot_grab_powerup() { return; } - set_bot_global_shared_objective_owner_by_reference( "powerup", self.available_powerups[ 0 ], self ); - while ( true ) - { - self SetScriptGoal( self.available_powerups[ 0 ].target_ent.origin ); - wait 0.05; - } + set_bot_global_shared_objective_owner_by_ent( "powerup", self.available_powerups[ 0 ].target_ent, self ); + + self SetScriptGoal( self.available_powerups[ 0 ].target_ent.origin ); } bot_powerup_process_order() @@ -865,6 +920,18 @@ bot_powerup_process_order() return 0; } +bot_powerup_init() +{ + self.successfully_grabbed_powerup = false; +} + +bot_powerup_post_think( state ) +{ + self.successfully_grabbed_powerup = false; + self ClearScriptGoal(); + self ClearScriptAimPos(); +} + bot_should_grab_powerup() { if ( level.zbot_objective_glob[ "powerup" ].active_objectives.size <= 0 ) @@ -881,6 +948,10 @@ bot_should_grab_powerup() { obj = powerup_objectives[ obj_keys[ i ] ]; powerup = obj.target_ent; + if ( !isDefined( powerup ) ) + { + continue; + } if ( isDefined( obj.owner ) ) { continue; @@ -908,31 +979,12 @@ bot_should_grab_powerup() bot_check_complete_grab_powerup() { - if ( self.successfully_grabbed_powerup ) - { - return true; - } - return false; -} - -bot_set_complete_grab_powerup() -{ - -} - -bot_powerup_on_completion() -{ - self.successfully_grabbed_powerup = false; + return self.successfully_grabbed_powerup; } bot_powerup_should_cancel() { - return ( !isDefined( self.available_powerups ) || self.available_powerups.size <= 0 ); -} - -bot_powerup_on_cancel() -{ - + return !isDefined( self.available_powerups ) || self.available_powerups.size <= 0 || !isDefined( self.available_powerups[ 0 ].target_ent ); } bot_powerup_should_postpone() @@ -940,11 +992,6 @@ bot_powerup_should_postpone() return false; } -bot_powerup_on_postpone() -{ - -} - bot_powerup_priority() { if ( !isDefined( self.available_powerups ) ) @@ -962,28 +1009,56 @@ bot_revive_player() } self endon( "disconnect" ); + self endon( "revive_end_think" ); + self endon( "player_downed" ); level endon( "end_game" ); player_to_revive_obj = self.available_revives[ 0 ]; - set_bot_global_shared_objective_owner_by_reference( "revive", player_to_revive_obj, self ); + set_bot_global_shared_objective_owner_by_ent( "revive", player_to_revive_obj.target_ent, self ); player_to_revive = player_to_revive_obj.target_ent; - action_id = self.action_queue[ "objective" ][ 0 ].action_id; - //If player is no longer valid to revive stop trying to revive //If bot doesn't have an objective anymore or the objective has changed stop trying to revive - while ( isDefined( player_to_revive ) && isDefined( player_to_revive_obj ) && isDefined( self.action_queue[ "objective" ][ 0 ] ) && action_id == self.action_queue[ "objective" ][ 0 ].action_id ) + while ( isDefined( player_to_revive ) && isDefined( player_to_revive_obj ) ) { - self.target_pos = player_to_revive.origin; + wait 0.05; + //Constantly update the goal just in case the player is moving(T5 or higher only) + self ClearScriptAimPos(); + self SetScriptGoal( player_to_revive.origin, 16 ); - if ( self.can_do_objective_now ) + if ( !self AtScriptGoal() ) { + continue; //TODO: Add check to see if another player is reviving target player //TODO: Add code to revive player, possibly add the ability to circle revive? } - wait 0.2; + if ( !isDefined( player_to_revive.revivetrigger ) ) + { + return; + } + //Check if the bot is reviving the player already and also that the player isn't being revived already + if ( player_to_revive.revivetrigger.beingrevived && !self maps\_laststand::is_reviving( player_to_revive ) ) + { + continue; + } + + SetScriptAimPos( player_to_revive.origin ); + + time = 3; + if ( self hasPerk( "specialty_quickrevive" ) ) + { + time /= 2; + } + self BotPressUse( time ); + + while ( self maps\_laststand::is_reviving( player_to_revive ) ) + { + wait 0.05; + } + //Wait to see if we cleared the objective by successfully reviving the player + waittillframeend; } } @@ -992,6 +1067,18 @@ bot_revive_process_order() return 0; } +bot_revive_player_init() +{ + self.successfully_revived_player = false; +} + +bot_revive_player_post_think( state ) +{ + self.successfully_revived_player = false; + self ClearScriptGoal(); + self ClearScriptAimPos(); +} + bot_should_revive_player() { downed_players_objs = get_all_objectives_for_group( "revive" ); @@ -1017,31 +1104,12 @@ bot_should_revive_player() bot_check_complete_revive_player() { - if ( self.successfully_revived_player ) - { - return true; - } - return false; -} - -bot_set_complete_revive_player() -{ - self.successfully_revived_player = true; -} - -bot_revive_player_on_completion() -{ - self.successfully_revived_player = false; + return self.successfully_revived_player; } bot_revive_player_should_cancel() { - return !isDefined( self.available_revives[ 0 ].target_ent.revivetrigger ); -} - -bot_revive_player_on_cancel() -{ - + return !isDefined( self.available_revives[ 0 ] ) || !isDefined( self.available_revives[ 0 ].target_ent ) || !isDefined( self.available_revives[ 0 ].target_ent.revivetrigger ); } bot_revive_player_should_postpone() @@ -1049,11 +1117,6 @@ bot_revive_player_should_postpone() return false; } -bot_revive_player_on_postpone() -{ - -} - bot_revive_player_priority() { return 0; @@ -1066,7 +1129,6 @@ store_powerups_dropped() level thread free_powerups_dropped(); level.zbots_powerups = []; - id = 0; while ( true ) { level waittill( "powerup_dropped", powerup ); @@ -1074,12 +1136,9 @@ store_powerups_dropped() { continue; } - powerup.id = id; - add_possible_bot_objective( "powerup", id, true, powerup ); - level thread objective_think( "powerup", id ); - scripts\sp\bots\bot_utility::assign_priority_to_powerup( powerup ); - level.zbots_powerups = scripts\sp\bots\bot_utility::sort_array_by_priority_field( level.zbots_powerups, powerup ); - id++; + add_possible_bot_objective( "powerup", powerup, true ); + maps\bots\_bot_utility::assign_priority_to_powerup( powerup ); + level.zbots_powerups = maps\bots\_bot_utility::sort_array_by_priority_field( level.zbots_powerups, powerup ); } } @@ -1090,7 +1149,7 @@ free_powerups_dropped() while ( true ) { level waittill( "powerup_freed", powerup ); - free_bot_objective( "powerup", powerup.id ); + free_bot_objective( "powerup", powerup ); } } @@ -1105,7 +1164,7 @@ watch_for_downed_players() { continue; } - add_possible_bot_objective( "revive", player.client_id, true, player ); + add_possible_bot_objective( "revive", player, true ); player thread free_revive_objective_when_needed(); } } @@ -1120,5 +1179,15 @@ free_revive_objective_when_needed() wait 0.05; } - free_bot_objective( "revive", id ); + free_bot_objective( "revive", self ); +} + +bot_on_powerup_grab( powerup ) +{ + self.successfully_grabbed_powerup = true; +} + +bot_on_revive_success( revivee ) +{ + self.successfully_revived_player = true; } \ No newline at end of file diff --git a/maps/bots/_bot_utility.gsc b/maps/bots/_bot_utility.gsc index f3aa1c6..d9cde5a 100644 --- a/maps/bots/_bot_utility.gsc +++ b/maps/bots/_bot_utility.gsc @@ -267,6 +267,15 @@ ClearScriptGoal() self SetScriptGoal( undefined, 0 ); } +/* + Returns whether the bot is at it's goal +*/ + +AtScriptGoal() +{ + return distanceSquared( self.bot.script_goal, self.origin ) <= self.bot.script_goal_dist * self.bot.script_goal_dist; +} + /* Sets the aim position of the bot */ @@ -1009,11 +1018,22 @@ targetIsGibbed() return isDefined( self.gibbed ) && self.gibbed; } -quickSort(array, compare_func) +swap_array_index( array, index1, index2 ) { - return quickSortMid(array, 0, array.size - 1, compare_func); + 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; @@ -1033,9 +1053,9 @@ quickSortMid( array, start, end, compare_func, compare_func_arg1 ) while ( ![[ compare_func ]](array[k], pivot, compare_func_arg1) && k >= start && k >= i) k--; if (k > i) - array = swap(array, i, k); + array = swap_array_index(array, i, k); } - array = swap(array, start, k); + array = swap_array_index(array, start, k); array = quickSortMid(array, start, k - 1, compare_func); array = quickSortMid(array, k + 1, end, compare_func); } @@ -1098,9 +1118,11 @@ assign_priority_to_powerup( powerup ) { LOW_AMMO_THRESHOLD = 0.3; - for ( i = 0; i < level.players.size; i++ ) + players = getPlayers(); + + for ( i = 0; i < players.size; i++ ) { - weapons = level.players[ i ] getWeaponsListPrimaries(); + weapons = players[ i ] getWeaponsListPrimaries(); for ( j = 0; j < weapons.size; j++ ) { if ( self getWeaponAmmoStock( weapons[ j ] ) <= int( weaponmaxammo( weapons[ j ] ) * LOW_AMMO_THRESHOLD ) )