From a23015122821a5aadd20eb2f2f845aeda631cb83 Mon Sep 17 00:00:00 2001 From: JezuzLizard Date: Tue, 28 Mar 2023 04:01:09 -0700 Subject: [PATCH] WIP objective code for powerup and revive type objectives. --- scripts/sp/T4ZM_zbots_main.gsc | 69 ++++++++---- scripts/sp/bots/actions/movement.gsc | 25 +++- scripts/sp/bots/actions/objective.gsc | 110 ++++++++++++------ scripts/sp/bots/bot_actions_common.gsc | 138 +++++++++++++++++++---- scripts/sp/bots/bot_objective_common.gsc | 64 ++++++++++- 5 files changed, 321 insertions(+), 85 deletions(-) diff --git a/scripts/sp/T4ZM_zbots_main.gsc b/scripts/sp/T4ZM_zbots_main.gsc index 7e8a792..d68fad8 100644 --- a/scripts/sp/T4ZM_zbots_main.gsc +++ b/scripts/sp/T4ZM_zbots_main.gsc @@ -42,6 +42,7 @@ main() //Movement actions //These all need definitions register_bot_action( "movement", "movetoobjective", ::bot_movetoobjective, ::bot_movetoobjective_process_order ::bot_should_movetoobjective, ::bot_check_complete_movetoobjective, ::bot_set_complete_movetoobjective, ::bot_movetoobjective_on_completion, ::bot_movetoobjective_should_cancel, ::bot_movetoobjective_on_cancel, ::bot_movetoobjective_should_postpone, ::bot_movetoobjective_on_postpone, ::bot_movetoobjective_priority ); + //register_bot_action( "movement", "atobjective", ::bot_atobjective, ::bot_atobjective_process_order ::bot_should_atobjective, ::bot_check_complete_atobjective, ::bot_set_complete_atobjective, ::bot_atobjective_on_completion, ::bot_atobjective_should_cancel, ::bot_atobjective_on_cancel, ::bot_atobjective_should_postpone, ::bot_atobjective_on_postpone, ::bot_atobjective_priority ); register_bot_action( "movement", "train", ::bot_train, ::bot_train_process_order ::bot_should_train, ::bot_check_complete_train, ::bot_set_complete_train, ::bot_train_on_completion, ::bot_train_should_cancel, ::bot_train_on_cancel, ::bot_train_should_postpone, ::bot_train_on_postpone, ::bot_train_priority ); register_bot_action( "movement", "camp", ::bot_camp, ::bot_camp_process_order ::bot_should_camp, ::bot_check_complete_camp, ::bot_set_complete_camp, ::bot_camp_on_completion, ::bot_camp_should_cancel, ::bot_camp_on_cancel, ::bot_camp_should_postpone, ::bot_camp_on_postpone, ::bot_camp_priority ); register_bot_action( "movement", "flee", ::bot_flee, ::bot_flee_process_order ::bot_should_flee, ::bot_check_complete_flee, ::bot_set_complete_flee, ::bot_flee_on_completion, ::bot_flee_should_cancel, ::bot_flee_on_cancel, ::bot_flee_should_postpone, ::bot_flee_on_postpone, ::bot_flee_priority ); @@ -59,6 +60,20 @@ main() register_bot_difficulty( "knife" ); register_bot_difficulty( "shotguns" ); + register_bot_objective( "magicbox" ); + register_bot_objective( "wallbuy" ); + register_bot_objective( "wallbuyammo" ); + register_bot_objective( "perk" ); + register_bot_objective( "door" ); + register_bot_objective( "debris" ); + register_bot_objective( "trap" ); + register_bot_objective( "packapunch" ); + register_bot_objective( "revive" ); + //register_bot_objective( "grabbuildable" ); + //register_bot_objective( "buildbuildable" ); + //register_bot_objective( "part" ); + register_bot_objective( "powerup" ); + level.bot_weapon_quality_poor = 0; level.bot_weapon_quality_fair = 1; level.bot_weapon_quality_good = 2; @@ -95,6 +110,14 @@ on_player_connect() { level waittill( "connected", player ); player.id = i; + if ( player isBot() ) + { + player.successfully_grabbed_powerup = false; + player.successfully_revived_player = false; + player.successfully_moved_to_objective = false; + player.can_do_objective_now = false; + player.on_powerup_grab_func = ::bot_on_powerup_grab; + } i++; } } @@ -102,6 +125,13 @@ on_player_connect() //TODO: Make postponing save the settings for the action so when the action is being executed again the bot tries to do/get the same thing //TODO: Make global canceling and postponing functionality //TODO: Make shared global objective and normal objective globs work +//TODO: Allow bots to multitask objectives on the way by using the postpone system +//TODO: Cancel most objectives if the bot is invalid +//TODO: Add reset complete functions to reset successfully completed actions variables +//TODO: Ignore objectives if bot is not able fulfill them at the moment, bot can start doing objectives when they are in a good position to do so +//TODO: Add the ability to check if a bot is at an objective to start the action think +//TODO: Add atobjective movement handler to let objectives control movement temporarily +//TODO: Allow bots to still do actions while down if possible init() { @@ -225,37 +255,25 @@ bot_think() wait 0.25; if ( !bot_valid( self ) ) { - self.action_queue = []; - wait 1; - continue; + self notify( "stop_action_think" ); + self bot_clear_actions_queue(); + while ( !bot_valid( self ) ) + { + wait 1; + } } - group_name = "objective"; - - self pick_actions_to_add_to_queue( group_name ); - self process_next_queued_action(); - - self check_if_action_is_completed_in_group( group_name ); - self check_if_action_should_be_postponed_in_group( group_name ); - self check_if_action_should_be_canceled_in_group( group_name ); - group_name = "movement"; - self pick_actions_to_add_to_queue( group_name ); - self process_next_queued_action(); - - self check_if_action_is_completed_in_group( group_name ); - self check_if_action_should_be_postponed_in_group( group_name ); - self check_if_action_should_be_canceled_in_group( group_name ); + self bot_action_think( group_name ); group_name = "combat"; - self pick_actions_to_add_to_queue( group_name ); - self process_next_queued_action(); + self bot_action_think( group_name ); - self check_if_action_is_completed_in_group( group_name ); - self check_if_action_should_be_postponed_in_group( group_name ); - self check_if_action_should_be_canceled_in_group( group_name ); + group_name = "objective"; + + self bot_action_think( group_name ); } } @@ -429,4 +447,9 @@ doBotMovement_loop() dir = ( 127, dir[1], 0 ); self botMovement( int( dir[0] ), int( dir[1] ) ); +} + +bot_on_powerup_grab( powerup ) +{ + self.successfully_grabbed_powerup = true; } \ No newline at end of file diff --git a/scripts/sp/bots/actions/movement.gsc b/scripts/sp/bots/actions/movement.gsc index a00f502..7c8dbb3 100644 --- a/scripts/sp/bots/actions/movement.gsc +++ b/scripts/sp/bots/actions/movement.gsc @@ -1,6 +1,16 @@ bot_movetoobjective() { - + action_id = self.action_queue[ "objective" ][ 0 ].action_id; + at_obj_distance_sq = 48 * 48; + while ( isDefined( self.action_queue[ "objective" ][ 0 ] ) && action_id == self.action_queue[ "objective" ][ 0 ].action_id ) + { + if ( distanceSquared( self.origin, self.target_pos ) < at_obj_distance_sq ) + { + self bot_set_complete_movetoobjective(); + break; + } + wait 0.2; + } } bot_movetoobjective_process_order() @@ -19,17 +29,18 @@ bot_should_movetoobjective() bot_check_complete_movetoobjective() { - return self.zbot_actions_in_queue[ "movement" ][ "movetoobjective" ].completed; + return self.successfully_moved_to_objective; } bot_set_complete_movetoobjective() { - self.zbot_actions_in_queue[ "movement" ][ "movetoobjective" ].completed = true; + self.successfully_moved_to_objective = true; } bot_movetoobjective_on_completion() { - + self.successfully_moved_to_objective = false; + self.can_do_objective_now = true; } bot_movetoobjective_should_cancel() @@ -39,7 +50,8 @@ bot_movetoobjective_should_cancel() bot_movetoobjective_on_cancel() { - + self.successfully_moved_to_objective = false; + self.can_do_objective_now = false; } bot_movetoobjective_should_postpone() @@ -53,7 +65,8 @@ bot_movetoobjective_should_postpone() bot_movetoobjective_on_postpone() { - + self.successfully_moved_to_objective = false; + self.can_do_objective_now = false; } bot_movetoobjective_priority() diff --git a/scripts/sp/bots/actions/objective.gsc b/scripts/sp/bots/actions/objective.gsc index 65f526b..0f9bfa3 100644 --- a/scripts/sp/bots/actions/objective.gsc +++ b/scripts/sp/bots/actions/objective.gsc @@ -486,7 +486,35 @@ bot_packapunch_purchase_priority() bot_revive_player() { + if ( !isDefined( self.available_revives ) || self.available_revives.size <= 0 ) + { + return; + } + self endon( "disconnect" ); + 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 ); + + 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 ) + { + self.target_pos = player_to_revive.origin; + + if ( self.can_do_objective_now ) + { + //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; + } } bot_revive_process_order() @@ -496,27 +524,49 @@ bot_revive_process_order() bot_should_revive_player() { - return false; + downed_players_objs = get_all_objectives_for_group( "revive" ); + if ( downed_players_objs.size <= 0 ) + { + return false; + } + + self.available_revives = []; + + obj_keys = getArrayKeys( downed_players_objs ); + for ( i = 0; i < downed_players_objs.size; i++ ) + { + if ( isDefined( downed_players_objs[ obj_keys[ i ] ].owner ) ) + { + continue; + } + + self.available_revives[ self.available_revives.size ] = downed_players[ obj_keys[ i ] ]; + } + return self.available_revives.size > 0; } 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; } bot_revive_player_should_cancel() { - return false; + return !isDefined( self.available_revives[ 0 ].target_ent.revivetrigger ); } bot_revive_player_on_cancel() @@ -706,15 +756,13 @@ bot_part_priority() bot_grab_powerup() { - self endon( "disconnect" ); - self endon( "new_objective" ); if ( !isDefined( self.available_powerups ) || self.available_powerups.size <= 0 ) { return; } - self.target_pos = self.available_powerups[ 0 ].origin; - self.target_powerup = self.available_powerups[ 0 ]; - level.zbots_powerups_targeted_for_grab[ level.zbots_powerups_targeted_for_grab.size ] = self.available_powerups[ 0 ]; + set_bot_global_shared_objective_owner_by_reference( "powerup", self.available_powerups[ 0 ], self ); + self.target_pos = self.available_powerups[ 0 ].target_ent.origin; + self.should_try_to_move_to_objective = true; } bot_powerup_process_order() @@ -724,55 +772,51 @@ bot_powerup_process_order() bot_should_grab_powerup() { - if ( !isDefined( level.zbots_powerups ) || level.zbots_powerups.size <= 0 ) + if ( !isDefined( level.zbot_objective_glob[ "powerup" ] ) || !isDefined( level.zbot_objective_glob[ "powerup" ].active_objectives ) || level.zbot_objective_glob[ "powerup" ].active_objectives.size <= 0 ) { return false; } MAX_DISTANCE_SQ = 10000 * 10000; BOT_SPEED_WHILE_SPRINTING_SQ = 285 * 285; self.available_powerups = []; - for ( i = 0; i < level.zbots_powerups.size; i++ ) + + powerup_objectives = level.zbot_objective_glob[ "powerup" ].active_objectives; + obj_keys = getArrayKeys( powerup_objectives ); + for ( i = 0; i < powerup_objectives.size; i++ ) { - if ( array_validate( level.zbots_powerups_targeted_for_grab ) ) + if ( isDefined( powerup_objectives[ obj_keys[ i ] ].owner ) ) { - already_targeted = false; - for ( j = 0; j < level.zbots_powerups_targeted_for_grab.size; j++ ) - { - if ( level.zbots_powerups_targeted_for_grab[ j ] == level.zbots_powerups[ i ] ) - { - already_targeted = true; - break; - } - } - if ( already_targeted ) - { - continue; - } + continue; } - time_left = level.zbots_powerups[ i ].time_left_until_timeout; - distance_required_to_reach_powerup = distanceSquared( level.zbots_powerups[ i ].origin, self.origin ); + time_left = powerup_objectives[ obj_keys[ i ] ].target_ent.time_left_until_timeout; + distance_required_to_reach_powerup = distanceSquared( powerup_objectives[ obj_keys[ i ] ].target_ent.origin, self.origin ); if ( distance_required_to_reach_powerup > BOT_SPEED_WHILE_SPRINTING_SQ * time_left ) { continue; } - if ( distanceSquared( level.zbots_powerups[ i ].origin, self.origin ) > MAX_DISTANCE_SQ ) + if ( distanceSquared( powerup_objectives[ obj_keys[ i ] ].target_ent.origin, self.origin ) > MAX_DISTANCE_SQ ) { continue; } - if ( !findPath( self.origin, level.zbots_powerups[ i ].origin ) ) + if ( !findPath( self.origin, powerup_objectives[ obj_keys[ i ] ].target_ent.origin ) ) { continue; } - self.available_powerups[ self.available_powerups.size ] = level.zbots_powerups[ i ]; + self.available_powerups[ self.available_powerups.size ] = powerup_objectives[ obj_keys[ i ] ]; } + + //TODO: Sort powerups by priority here time_left = undefined; distance_required_to_reach_powerup = undefined; - already_targeted = undefined; return self.available_powerups.size > 0; } bot_check_complete_grab_powerup() { + if ( self.successfully_grabbed_powerup ) + { + return true; + } return false; } @@ -783,7 +827,7 @@ bot_set_complete_grab_powerup() bot_powerup_on_completion() { - + self.successfully_grabbed_powerup = false; } bot_powerup_should_cancel() @@ -812,5 +856,5 @@ bot_powerup_priority() { return 0; } - return self.available_powerups[ 0 ].priority; + return self.available_powerups[ 0 ].target_ent.priority; } \ No newline at end of file diff --git a/scripts/sp/bots/bot_actions_common.gsc b/scripts/sp/bots/bot_actions_common.gsc index ab2f864..ffda98d 100644 --- a/scripts/sp/bots/bot_actions_common.gsc +++ b/scripts/sp/bots/bot_actions_common.gsc @@ -68,11 +68,6 @@ register_bot_objective_action_for_queue( group_name, action_name ) process_next_queued_action( group_name ) { - if ( self.action_queue.size <= 0 ) - { - return; - } - if ( self.zbot_actions_in_queue[ group_name ][ self.action_queue[ group_name ][ 0 ].action_name ].queued ) { return; @@ -82,12 +77,18 @@ process_next_queued_action( group_name ) self thread [[ self.action_queue[ group_name ][ 0 ].action ]](); - self wait_for_action_completion( self.action_queue[ group_name ][ 0 ].action_name ); + self.zbot_actions_in_queue[ group_name ][ self.action_queue[ group_name ][ 0 ].action_name ].is_current = true; + + self thread wait_for_action_completion( group_name, self.action_queue[ group_name ][ 0 ].action_name ); } wait_for_action_completion( group_name, action_name ) { - result = self waittill_any_return( action_name + "_complete", action_name + "_cancel", action_name + "_postpone", "disconnect" ); + self endon( "disconnect" ); + self endon( "stop_action_think" ); + level endon( "end_game" ); + + result = self waittill_any_return( action_name + "_complete", action_name + "_cancel", action_name + "_postpone" ); if ( !isDefined( result ) ) { return; @@ -98,29 +99,31 @@ wait_for_action_completion( group_name, action_name ) } if ( ( result == action_name + "_complete" ) ) { - self.zbot_actions_in_queue[ group_name ][ self.action_queue[ group_name ][ 0 ].action_name ].postponed = false; - self.zbot_actions_in_queue[ group_name ][ self.action_queue[ group_name ][ 0 ].action_name ].queued = false; - self.zbot_actions_in_queue[ group_name ][ self.action_queue[ group_name ][ 0 ].action_name ].completed = false; + 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 ]](); } else if ( result == action_name + "_cancel" ) { - self.zbot_actions_in_queue[ group_name ][ self.action_queue[ group_name ][ 0 ].action_name ].postponed = false; - self.zbot_actions_in_queue[ group_name ][ self.action_queue[ group_name ][ 0 ].action_name ].queued = false; - self.zbot_actions_in_queue[ group_name ][ self.action_queue[ group_name ][ 0 ].action_name ].completed = false; + 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 ]](); } else if ( result == action_name + "_postpone" ) { - self.zbot_actions_in_queue[ group_name ][ self.action_queue[ group_name ][ 0 ].action_name ].postponed = true; + 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_keys[ i ] ].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 ]](); } + + self.zbot_actions_in_queue[ group_name ][ action_name ].is_current = false; } copy_default_action_settings_to_queue( group_name, action_name ) @@ -149,23 +152,44 @@ pick_actions_to_add_to_queue( group_name ) } */ + if ( !isDefined( self.action_id ) ) + { + self.action_id = 0; + } + for ( i = 0; i < action_keys.size; i++ ) { if ( !self.zbot_actions_in_queue[ group_name ][ action_keys[ i ] ].queued && [[ level.zbots_actions[ group_name ][ action_keys[ i ] ].should_do_func ]]() ) { self.action_queue[ group_name ][ self.action_queue[ group_name ].size ] = spawnStruct(); self.action_queue[ group_name ][ self.action_queue[ group_name ].size - 1 ].action_name = action_keys[ i ]; + self.action_queue[ group_name ][ self.action_queue[ group_name ].size - 1 ].action_id = self.action_id; self.action_queue[ group_name ][ self.action_queue[ group_name ].size - 1 ].priority = self [[ level.zbots_actions[ group_name ][ action_keys[ i ] ].priority_func ]](); self.zbot_actions_in_queue[ group_name ][ action_keys[ i ] ].queued = true; + self.action_id++; } } } -check_if_action_should_be_canceled_in_group( group_name ) +bot_clear_actions_queue() { - if ( [[ level.zbots_actions[ group_name ][ self.action_queue[ group_name ][ 0 ].action_name ].should_cancel_func ]]() ) + group_keys = getArrayKeys( level.zbots_actions ); + for ( i = 0; i < group_keys.size; i++ ) { - self notify( self.action_queue[ group_name ][ 0 ].action_name + "_cancel" ); + self.action_queue[ group_keys[ i ] ] = []; + action_keys = getArrayKeys( level.zbots_actions[ group_keys[ i ] ] ); + for ( j = 0; j < action_keys.size; j++ ) + { + self register_bot_objective_action_for_queue( group_keys[ i ], action_keys[ j ] ); + } + } +} + +check_if_action_is_completed_in_group( group_name ) +{ + if ( [[ level.zbots_actions[ group_name ][ self.action_queue[ group_name ][ 0 ].action_name ].check_if_complete_func ]]() ) + { + self notify( self.action_queue[ group_name ][ 0 ].action_name + "_complete" ); } } @@ -177,10 +201,84 @@ check_if_action_should_be_postponed_in_group( group_name ) } } -check_if_action_is_completed_in_group( group_name ) +check_if_action_should_be_canceled_in_group( group_name ) { - if ( [[ level.zbots_actions[ group_name ][ self.action_queue[ group_name ][ 0 ].action_name ].check_if_complete_func ]]() ) + if ( [[ level.zbots_actions[ group_name ][ self.action_queue[ group_name ][ 0 ].action_name ].should_cancel_func ]]() ) { - self notify( self.action_queue[ group_name ][ 0 ].action_name + "_complete" ); + self notify( self.action_queue[ group_name ][ 0 ].action_name + "_cancel" ); } +} + +check_if_action_should_be_postponed_globally( group_name ) +{ + if ( action_should_be_postponed_global( group_name, self.action_queue[ group_name ][ 0 ].action_name ) ) + { + self notify( self.action_queue[ group_name ][ 0 ].action_name + "_postpone" ); + } +} + +check_if_action_should_be_canceled_globally( group_name ) +{ + if ( action_should_be_canceled_global( group_name, self.action_queue[ group_name ][ 0 ].action_name ) ) + { + self notify( self.action_queue[ group_name ][ 0 ].action_name + "_cancel" ); + } +} + +//TODO: Figure out way of overriding the current action for flee movement action +check_for_forced_action( group_name ) +{ + action_keys = getArrayKeys( level.zbots_actions[ group_name ] ); + action_priorities_array = []; + for ( i = 0; i < action_keys.size; i++ ); + { + action_priorities_array[ action_priorities_array.size ] = spawnStruct(); + action_priorities_array[ action_priorities_array.size - 1 ].priority = self [[ level.zbots_actions[ group_name ][ action_keys[ i ] ].priority_func ]](); + action_priorities_array[ action_priorities_array.size - 1 ].action_name = action_keys[ i ]; + } + + action_priorities_array = sort_array_by_priority_field( action_priorities_array ); + + if ( self.action_queue[ group_name ][ 0 ].priority < action_priorities_array[ 0 ].priority ) + { + self notify( self.action_queue[ group_name ][ 0 ].action_name + "_cancel" ); + } +} + +bot_action_think( group_name ) +{ + self pick_actions_to_add_to_queue( group_name ); + + //self check_for_forced_action( group_name ); + + if ( self.action_queue[ group_name ].size <= 0 ) + { + return; + } + + self process_next_queued_action( group_name ); + + self check_if_action_is_completed_in_group( group_name ); + self check_if_action_should_be_postponed_in_group( group_name ); + self check_if_action_should_be_canceled_in_group( group_name ); + + self check_if_action_should_be_postponed_globally( group_name ); + self check_if_action_should_be_canceled_globally( group_name ); +} + +action_should_be_postponed_global( primary_group_name, action_name ) +{ + return false; +} + +action_should_be_canceled_global( primary_group_name, action_name ) +{ + return false; +} + +//TODO: Add ability to pause an action so the bot won't be doing it while its paused but when its unpaused they can resume the action with the same settings +//Similar to postpone except instead of selecting a new action the current action is preserved +action_should_be_paused_global( primary_group_name, action_name ) +{ + return false; } \ No newline at end of file diff --git a/scripts/sp/bots/bot_objective_common.gsc b/scripts/sp/bots/bot_objective_common.gsc index b645461..eb3ff69 100644 --- a/scripts/sp/bots/bot_objective_common.gsc +++ b/scripts/sp/bots/bot_objective_common.gsc @@ -1,4 +1,4 @@ -add_possible_bot_objective( objective_group, id, is_global_shared, target_ent ) +register_bot_objective( objective_group ) { if ( !isDefined( level.zbot_objective_glob ) ) { @@ -9,6 +9,13 @@ add_possible_bot_objective( objective_group, id, is_global_shared, target_ent ) level.zbot_objective_glob[ objective_group ] = spawnStruct(); level.zbot_objective_glob[ objective_group ].active_objectives = []; } +} + +add_possible_bot_objective( objective_group, id, is_global_shared, target_ent ) +{ + 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" ); objective_struct = spawnStruct(); objective_struct.group = objective_group; @@ -16,10 +23,44 @@ add_possible_bot_objective( objective_group, id, is_global_shared, target_ent ) objective_struct.is_global_shared = is_global_shared; objective_struct.target_ent = target_ent; objective_struct.owner = undefined; + objective_struct.is_objective = true; level.zbot_objective_glob[ objective_group ].active_objectives[ "obj_id_" + id ] = objective_struct; } +get_bot_objective_by_id( objective_group, id ) +{ + active_objectives = level.zbot_objective_glob[ objective_group ].active_objectives; + + objective = active_objectives[ "obj_id_" + id ]; + + assert( isDefined( objective ), "Objective with " + id + " id does not point to a objective in group " + objective_group ); + + return objective; +} + +get_all_objectives_for_group( objective_group ) +{ + return level.zbot_objective_glob[ objective_group ].active_objectives; +} + +set_objective_for_bot( objective_group, id ) +{ + possible_objectives = level.zbot_objective_glob[ primary_objective_group ].active_objectives; + + objective = possible_objectives[ "obj_id_" + id ]; + + objective_exists = isDefined( primary_objective ); + + assert( objective_exists, "Objective with " + id + " id does not point to a objective in group " + objective_group ); + if ( !objective_exists ) + { + return; + } + + self.zbot_current_objective = objective; +} + set_bot_objective_blocked_by_objective( primary_objective_group, primary_id, blocked_by_objective_group, blocked_by_id ) { primary_active_objectives = level.zbot_objective_glob[ primary_objective_group ].active_objectives; @@ -71,7 +112,7 @@ set_bot_objective_blocked_by_objective( primary_objective_group, primary_id, blo } } -set_bot_global_shared_objective_owner( objective_group, new_owner, id ) +set_bot_global_shared_objective_owner_by_id( objective_group, id, new_owner ) { active_objectives = level.zbot_objective_glob[ objective_group ].active_objectives; @@ -84,7 +125,24 @@ set_bot_global_shared_objective_owner( objective_group, new_owner, id ) return; } - assert( objective.is_global_shared, "Objective with " + id + " id number cannot be set an owner because is_global_shared field is false in group" + objective_group ); + assert( objective.is_global_shared, "Objective with " + id + " id number cannot be set to have an owner because is_global_shared field is false in group " + objective_group ); + if ( !objective.is_global_shared ) + { + return; + } + + objective.owner = new_owner; +} + +set_bot_global_shared_objective_owner_by_reference( objective_group, objective, new_owner ) +{ + is_objective = isDefined( objective.is_objective ); + assert( is_objective, "Objective arg is not a valid objective object" ); + if ( !is_objective ) + { + return; + } + assert( objective.is_global_shared, "Objective with " + id + " id number cannot be set to have an owner because is_global_shared field is false in group " + objective_group ); if ( !objective.is_global_shared ) { return;