Fix multiple script errors.

Bot objective and action improvements.
This commit is contained in:
JezuzLizard 2023-05-02 04:29:34 -07:00
parent 1c835bd77b
commit b9fe21d15f
5 changed files with 301 additions and 46 deletions

View File

@ -93,6 +93,14 @@ init()
level.bots_maxShotgunDistance = 500; level.bots_maxShotgunDistance = 500;
level.bots_maxShotgunDistance *= level.bots_maxShotgunDistance; level.bots_maxShotgunDistance *= level.bots_maxShotgunDistance;
level.bot_allowed_negotiation_links = [];
level.bot_allowed_negotiation_links[ level.bot_allowed_negotiation_links.size ] = "zombie_jump_down_72";
level.bot_allowed_negotiation_links[ level.bot_allowed_negotiation_links.size ] = "zombie_jump_down_96";
level.bot_allowed_negotiation_links[ level.bot_allowed_negotiation_links.size ] = "zombie_jump_down_120";
level.bot_allowed_negotiation_links[ level.bot_allowed_negotiation_links.size ] = "zombie_jump_down_127";
level.bot_allowed_negotiation_links[ level.bot_allowed_negotiation_links.size ] = "zombie_jump_down_184";
level.bot_allowed_negotiation_links[ level.bot_allowed_negotiation_links.size ] = "zombie_jump_down_190";
level.players = []; level.players = [];
level.bots = []; level.bots = [];

View File

@ -1538,9 +1538,11 @@ doWalk( goal, dist, isScriptGoal )
path_was_truncated = ( current + 1 ) >= 32; path_was_truncated = ( current + 1 ) >= 32;
//Couldn't generate path to goal //Couldn't generate path to goal
self.path_inaccessible = false;
if ( current <= -1 ) if ( current <= -1 )
{ {
self notify( "bad_path_internal" ); self notify( "bad_path_internal" );
self.path_inaccessible = true;
return; return;
} }
@ -1757,7 +1759,7 @@ getRandomLargestStafe( dist )
*/ */
initAStar( goal ) initAStar( goal )
{ {
nodes = generatePath( self.origin, goal, self.team, false ); nodes = generatePath( self.origin, goal, self.team, level.bot_allowed_negotiation_links );
if ( !isDefined( nodes ) ) if ( !isDefined( nodes ) )
{ {

View File

@ -23,9 +23,12 @@ connected()
self thread onBotSpawned(); self thread onBotSpawned();
self thread onSpawned(); self thread onSpawned();
self thread initialize_bot_actions_queue(); self thread initialize_bot_actions_queue();
self thread bot_valid_pump();
//self thread bot_objective_inaccessible_pump();
self.on_powerup_grab_func = ::bot_on_powerup_grab; self.on_powerup_grab_func = ::bot_on_powerup_grab;
self.on_revive_success_func = ::bot_on_revive_success; self.on_revive_success_func = ::bot_on_revive_success;
self.path_inaccessible = false;
} }
/* /*
@ -409,6 +412,7 @@ add_possible_bot_objective( objective_group, target_ent, is_global_shared )
objective_struct.target_ent = target_ent; objective_struct.target_ent = target_ent;
objective_struct.owner = undefined; objective_struct.owner = undefined;
objective_struct.is_objective = true; objective_struct.is_objective = true;
objective_struct.bad = false;
level.zbot_objective_glob[ objective_group ].active_objectives[ "obj_id_" + id ] = objective_struct; level.zbot_objective_glob[ objective_group ].active_objectives[ "obj_id_" + id ] = objective_struct;
} }
@ -437,7 +441,17 @@ get_all_objectives_for_group( objective_group )
return level.zbot_objective_glob[ objective_group ].active_objectives; return level.zbot_objective_glob[ objective_group ].active_objectives;
} }
set_objective_for_bot( objective_group, ent ) bot_get_objective()
{
return self.zbot_current_objective;
}
bot_has_objective()
{
return isDefined( self.zbot_current_objective );
}
bot_set_objective( objective_group, ent )
{ {
if ( !isDefined( ent ) ) if ( !isDefined( ent ) )
{ {
@ -534,6 +548,36 @@ set_bot_objective_blocked_by_objective( primary_objective_group, primary_ent, bl
} }
} }
bot_is_objective_owner( objective_group, ent )
{
if ( !isDefined( ent ) )
{
assertMsg( "Ent is undefined" );
return false;
}
id = ent getEntityNumber();
active_objectives = level.zbot_objective_glob[ objective_group ].active_objectives;
objective = active_objectives[ "obj_id_" + id ];
objective_exists = isDefined( objective );
assert( objective_exists, "Objective with " + id + " id number does not point to a objective in group " + objective_group );
if ( !objective_exists )
{
return false;
}
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 false;
}
return isDefined( objective.owner ) && objective.owner == self;
}
set_bot_global_shared_objective_owner_by_ent( objective_group, ent, new_owner ) set_bot_global_shared_objective_owner_by_ent( objective_group, ent, new_owner )
{ {
if ( !isDefined( ent ) ) if ( !isDefined( ent ) )
@ -581,6 +625,30 @@ set_bot_global_shared_objective_owner_by_reference( objective_group, objective,
objective.owner = new_owner; objective.owner = new_owner;
} }
mark_objective_bad( 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 ];
objective_exists = isDefined( objective );
assert( objective_exists, "Objective with " + id + " id number does not point to a objective in group " + objective_group );
if ( !objective_exists )
{
return;
}
objective.bad = true;
}
free_bot_objective( objective_group, ent ) free_bot_objective( objective_group, ent )
{ {
if ( !isDefined( ent ) ) if ( !isDefined( ent ) )
@ -605,9 +673,9 @@ free_bot_objective( objective_group, ent )
players = getPlayers(); players = getPlayers();
for ( i = 0; i < players.size; i++ ) for ( i = 0; i < players.size; i++ )
{ {
if ( players[ i ].pers[ "isBot" ] ) if ( isDefined( players[ i ].pers[ "isBot" ] ) && players[ i ].pers[ "isBot" ] )
{ {
if ( players[ i ].zbot_current_objective == objective ) if ( isDefined( players[ i ].zbot_current_objective ) && players[ i ].zbot_current_objective == objective )
{ {
players[ i ].zbot_current_objective = undefined; players[ i ].zbot_current_objective = undefined;
} }
@ -678,20 +746,22 @@ register_bot_objective_action_for_queue( group_name, action_name )
process_next_queued_action( group_name ) process_next_queued_action( group_name )
{ {
if ( self.zbot_actions_in_queue[ group_name ][ self.action_queue[ group_name ][ 0 ].action_name ].queued ) if ( self.zbot_actions_in_queue[ group_name ][ self.action_queue[ group_name ][ 0 ].action_name ].is_current )
{ {
return; return;
} }
self.action_queue[ group_name ] = self sort_array_by_priority_field( self.action_queue[ 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 ]](); action_name = self.action_queue[ group_name ][ 0 ].action_name;
self thread [[ self.action_queue[ group_name ][ 0 ].action ]](); self [[ level.zbots_actions[ group_name ][ action_name ].init_func ]]();
self.zbot_actions_in_queue[ group_name ][ self.action_queue[ group_name ][ 0 ].action_name ].is_current = true; self thread [[ level.zbots_actions[ group_name ][ action_name ].action ]]();
self thread wait_for_action_completion( group_name, self.action_queue[ group_name ][ 0 ].action_name ); self.zbot_actions_in_queue[ group_name ][ action_name ].is_current = true;
self thread wait_for_action_completion( group_name, action_name );
} }
wait_for_action_completion( group_name, action_name ) wait_for_action_completion( group_name, action_name )
@ -733,7 +803,7 @@ wait_for_action_completion( group_name, action_name )
self notify( action_name + "_end_think" ); self notify( action_name + "_end_think" );
self [[ self.action_queue[ group_name ][ 0 ].post_think_func ]]( end_state ); self [[ level.zbots_actions[ group_name ][ action_name ].post_think_func ]]( end_state );
if ( save_action ) if ( save_action )
{ {
@ -761,6 +831,13 @@ pick_actions_to_add_to_queue( group_name )
} }
*/ */
//Reboot the action queue because the last member was deleted which deletes the array
if ( !isDefined( self.action_queue ) || !isDefined( self.action_queue[ group_name ] ) )
{
self.action_queue = [];
self.action_queue[ group_name ] = [];
}
if ( !isDefined( self.action_id ) ) if ( !isDefined( self.action_id ) )
{ {
self.action_id = 0; self.action_id = 0;
@ -794,43 +871,45 @@ bot_clear_actions_queue()
} }
} }
check_if_action_is_completed_in_group( group_name ) check_if_action_is_completed_in_group( group_name, action_name )
{ {
if ( [[ level.zbots_actions[ group_name ][ self.action_queue[ group_name ][ 0 ].action_name ].check_if_complete_func ]]() ) assert( isDefined( level.zbots_actions[ group_name ][ action_name ].check_if_complete_func ) );
if ( self [[ level.zbots_actions[ group_name ][ action_name ].check_if_complete_func ]]() )
{ {
self notify( self.action_queue[ group_name ][ 0 ].action_name + "_complete" ); self notify( action_name + "_complete" );
} }
} }
check_if_action_should_be_postponed_in_group( group_name ) check_if_action_should_be_postponed_in_group( group_name, action_name )
{ {
if ( [[ level.zbots_actions[ group_name ][ self.action_queue[ group_name ][ 0 ].action_name ].should_postpone_func ]]() ) if ( self [[ level.zbots_actions[ group_name ][ action_name ].should_postpone_func ]]() )
{ {
self notify( self.action_queue[ group_name ][ 0 ].action_name + "_postpone" ); self notify( action_name + "_postpone" );
} }
} }
check_if_action_should_be_canceled_in_group( group_name ) check_if_action_should_be_canceled_in_group( group_name, action_name )
{ {
if ( [[ level.zbots_actions[ group_name ][ self.action_queue[ group_name ][ 0 ].action_name ].should_cancel_func ]]() ) if ( self [[ level.zbots_actions[ group_name ][ action_name ].should_cancel_func ]]() )
{ {
self notify( self.action_queue[ group_name ][ 0 ].action_name + "_cancel" ); self notify( action_name + "_cancel" );
} }
} }
check_if_action_should_be_postponed_globally( group_name ) check_if_action_should_be_postponed_globally( group_name, action_name )
{ {
if ( action_should_be_postponed_global( group_name, self.action_queue[ group_name ][ 0 ].action_name ) ) if ( action_should_be_postponed_global( group_name, action_name ) )
{ {
self notify( self.action_queue[ group_name ][ 0 ].action_name + "_postpone" ); self notify( action_name + "_postpone" );
} }
} }
check_if_action_should_be_canceled_globally( group_name ) check_if_action_should_be_canceled_globally( group_name, action_name )
{ {
if ( action_should_be_canceled_global( group_name, self.action_queue[ group_name ][ 0 ].action_name ) ) if ( action_should_be_canceled_global( group_name, action_name ) )
{ {
self notify( self.action_queue[ group_name ][ 0 ].action_name + "_cancel" ); self notify( action_name + "_cancel" );
} }
} }
@ -861,7 +940,9 @@ bot_action_think()
while ( true ) while ( true )
{ {
wait 1; wait 0.05;
//Wait until the end of the frame so any variables set by _bot_internal in the current frame will have up to date values
waittillframeend;
group_name = "objective"; group_name = "objective";
@ -869,19 +950,21 @@ bot_action_think()
//self check_for_forced_action( group_name ); //self check_for_forced_action( group_name );
if ( self.action_queue[ group_name ].size <= 0 ) if ( !isDefined( self.action_queue[ group_name ][ 0 ] ) )
{ {
continue; continue;
} }
self process_next_queued_action( group_name ); self process_next_queued_action( group_name );
self check_if_action_is_completed_in_group( group_name ); action_name = self.action_queue[ group_name ][ 0 ].action_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_is_completed_in_group( group_name, action_name );
self check_if_action_should_be_canceled_globally( group_name ); self check_if_action_should_be_postponed_in_group( group_name, action_name );
self check_if_action_should_be_canceled_in_group( group_name, action_name );
self check_if_action_should_be_postponed_globally( group_name, action_name );
self check_if_action_should_be_canceled_globally( group_name, action_name );
} }
} }
@ -892,6 +975,11 @@ action_should_be_postponed_global( primary_group_name, action_name )
action_should_be_canceled_global( primary_group_name, action_name ) action_should_be_canceled_global( primary_group_name, action_name )
{ {
obj = self bot_get_objective();
if ( self.path_inaccessible || obj.bad )
{
return true;
}
return false; return false;
} }
@ -904,15 +992,62 @@ action_should_be_paused_global( primary_group_name, action_name )
bot_grab_powerup() bot_grab_powerup()
{ {
self endon( "disconnect" );
self endon( "powerup_end_think" ); self endon( "powerup_end_think" );
self endon( "bot_in_invalid_state" );
level endon( "end_game" );
if ( !isDefined( self.available_powerups ) || self.available_powerups.size <= 0 ) if ( !isDefined( self.available_powerups ) || self.available_powerups.size <= 0 )
{ {
return; return;
} }
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 ); powerup_obj = self.available_powerups[ 0 ];
powerup_obj_ent = powerup_obj.target_ent;
set_bot_global_shared_objective_owner_by_ent( "powerup", powerup_obj_ent, self );
self bot_set_objective( "powerup", powerup_obj_ent );
while ( isDefined( powerup_obj_ent ) && isDefined( powerup_obj ) && self bot_is_objective_owner( "powerup", powerup_obj_ent ) )
{
wait 1;
self ClearScriptAimPos();
self SetScriptGoal( powerup_obj_ent.origin );
result = self waittill_any_return( "goal", "bad_path", "new_goal" );
if ( result != "goal" )
{
continue;
}
//Wait to see if the bot was able to grab the powerup
wait 0.5;
//Check if powerup still exists
if ( isDefined( powerup_obj_ent ) )
{
height_difference = self.origin[ 2 ] - powerup_obj_ent.origin[ 2 ];
if ( height_difference < 49 )
{
self BotJump();
wait 0.5;
waittillframeend;
//Check if bot was able to grab the powerup by jumping
if ( self bot_has_objective() || isDefined( powerup_obj_ent ) )
{
//Mark objective as bad so bots will ignore it from now on
powerup_obj.bad = true;
}
}
else
{
powerup_obj.bad = true;
}
if ( powerup_obj.bad )
{
break;
}
}
}
} }
bot_powerup_process_order() bot_powerup_process_order()
@ -930,6 +1065,7 @@ bot_powerup_post_think( state )
self.successfully_grabbed_powerup = false; self.successfully_grabbed_powerup = false;
self ClearScriptGoal(); self ClearScriptGoal();
self ClearScriptAimPos(); self ClearScriptAimPos();
self clear_objective_for_bot();
} }
bot_should_grab_powerup() bot_should_grab_powerup()
@ -952,6 +1088,10 @@ bot_should_grab_powerup()
{ {
continue; continue;
} }
if ( obj.bad )
{
continue;
}
if ( isDefined( obj.owner ) ) if ( isDefined( obj.owner ) )
{ {
continue; continue;
@ -966,7 +1106,7 @@ bot_should_grab_powerup()
{ {
continue; continue;
} }
if ( !isDefined( generatePath( self.origin, powerup.origin, self.team, false ) ) ) if ( !isDefined( generatePath( self.origin, powerup.origin, self.team, level.bot_allowed_negotiation_links ) ) )
{ {
continue; continue;
} }
@ -1010,7 +1150,7 @@ bot_revive_player()
self endon( "disconnect" ); self endon( "disconnect" );
self endon( "revive_end_think" ); self endon( "revive_end_think" );
self endon( "player_downed" ); self endon( "bot_in_invalid_state" );
level endon( "end_game" ); level endon( "end_game" );
player_to_revive_obj = self.available_revives[ 0 ]; player_to_revive_obj = self.available_revives[ 0 ];
@ -1021,32 +1161,37 @@ bot_revive_player()
//If player is no longer valid to revive stop trying to revive //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 //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 ) ) while ( isDefined( player_to_revive ) && isDefined( player_to_revive_obj ) && self bot_is_objective_owner( "powerup", powerup_obj_ent ) )
{ {
wait 0.05; wait 1;
//Constantly update the goal just in case the player is moving(T5 or higher only) //Constantly update the goal just in case the player is moving(T5 or higher only)
self ClearScriptAimPos(); self ClearScriptAimPos();
self SetScriptGoal( player_to_revive.origin, 16 ); self SetScriptGoal( player_to_revive.origin, 32 );
if ( !self AtScriptGoal() ) result = self waittill_any_return( "goal", "bad_path", "new_goal" );
//printConsole( result );
if ( result != "goal" )
{ {
//printConsole( "Bot is not at goal" );
continue; continue;
//TODO: Add check to see if another player is reviving target player //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? //TODO: Add code to revive player, possibly add the ability to circle revive?
} }
if ( !isDefined( player_to_revive.revivetrigger ) ) if ( !isDefined( player_to_revive.revivetrigger ) )
{ {
self.should_cancel_revive_obj = true;
return; return;
} }
//Check if the bot is reviving the player already and also that the player isn't being revived already //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 ) ) if ( player_to_revive.revivetrigger.beingrevived )
{ {
continue; continue;
} }
SetScriptAimPos( player_to_revive.origin ); SetScriptAimPos( player_to_revive.origin );
time = 3; time = 3.2;
if ( self hasPerk( "specialty_quickrevive" ) ) if ( self hasPerk( "specialty_quickrevive" ) )
{ {
time /= 2; time /= 2;
@ -1069,14 +1214,17 @@ bot_revive_process_order()
bot_revive_player_init() bot_revive_player_init()
{ {
self.should_cancel_revive_obj = false;
self.successfully_revived_player = false; self.successfully_revived_player = false;
} }
bot_revive_player_post_think( state ) bot_revive_player_post_think( state )
{ {
self.should_cancel_revive_obj = false;
self.successfully_revived_player = false; self.successfully_revived_player = false;
self ClearScriptGoal(); self ClearScriptGoal();
self ClearScriptAimPos(); self ClearScriptAimPos();
self clear_objective_for_bot();
} }
bot_should_revive_player() bot_should_revive_player()
@ -1096,7 +1244,10 @@ bot_should_revive_player()
{ {
continue; continue;
} }
if ( obj.bad )
{
continue;
}
self.available_revives[ self.available_revives.size ] = downed_players_objs[ obj_keys[ i ] ]; self.available_revives[ self.available_revives.size ] = downed_players_objs[ obj_keys[ i ] ];
} }
return self.available_revives.size > 0; return self.available_revives.size > 0;
@ -1109,7 +1260,14 @@ bot_check_complete_revive_player()
bot_revive_player_should_cancel() bot_revive_player_should_cancel()
{ {
return !isDefined( self.available_revives[ 0 ] ) || !isDefined( self.available_revives[ 0 ].target_ent ) || !isDefined( self.available_revives[ 0 ].target_ent.revivetrigger ); if ( !isDefined( self.available_revives[ 0 ] )
|| !isDefined( self.available_revives[ 0 ].target_ent )
|| !isDefined( self.available_revives[ 0 ].target_ent.revivetrigger )
|| self.should_cancel_revive_obj )
{
return true;
}
return false;
} }
bot_revive_player_should_postpone() bot_revive_player_should_postpone()
@ -1132,6 +1290,7 @@ store_powerups_dropped()
while ( true ) while ( true )
{ {
level waittill( "powerup_dropped", powerup ); level waittill( "powerup_dropped", powerup );
waittillframeend;
if ( !isDefined( powerup ) ) if ( !isDefined( powerup ) )
{ {
continue; continue;
@ -1182,6 +1341,77 @@ free_revive_objective_when_needed()
free_bot_objective( "revive", self ); free_bot_objective( "revive", self );
} }
bot_valid_pump()
{
level endon( "end_game" );
obj_sav = undefined;
while ( true )
{
obj_sav = self.zbot_current_objective;
wait 0.5;
if ( !maps\so\zm_common\_zm_utility::is_player_valid( self ) )
{
if ( isDefined( self ) )
{
self notify( "bot_in_invalid_state" );
self clear_objective_for_bot();
}
else if ( isDefined( obj_sav ) )
{
set_bot_global_shared_objective_owner_by_ent( obj_sav.group, obj_sav.target_ent, undefined );
}
while ( isDefined( self ) && !maps\so\zm_common\_zm_utility::is_player_valid( self ) )
{
wait 0.5;
}
if ( !isDefined( self ) )
{
return;
}
}
}
}
bot_objective_inaccessible_pump()
{
self endon( "disconnect" );
level endon( "end_game" );
while ( true )
{
invalid_obj = false;
wait 0.5;
while ( !self bot_has_objective() )
{
wait 0.5;
}
while ( self bot_has_objective() )
{
wait 1;
obj = self bot_get_objective();
if ( !isDefined( obj ) || !isDefined( obj.target_ent ) )
{
invalid_obj = true;
}
else if ( !isDefined( generatePath( self.origin, obj.target_ent.origin, self.team, level.bot_allowed_negotiation_links ) ) )
{
invalid_obj = true;
}
if ( invalid_obj )
{
self notify( "bot_objective_inaccessible" );
self.path_inaccessible = true;
break;
}
}
}
}
bot_on_powerup_grab( powerup ) bot_on_powerup_grab( powerup )
{ {
self.successfully_grabbed_powerup = true; self.successfully_grabbed_powerup = true;

View File

@ -130,6 +130,15 @@ BotPressSmoke( time )
self maps\bots\_bot_internal::smoke( time ); self maps\bots\_bot_internal::smoke( time );
} }
/*
Bot jumps
*/
BotJump()
{
self maps\bots\_bot_internal::jump();
}
/* /*
Returns the bot's random assigned number. Returns the bot's random assigned number.
*/ */
@ -273,7 +282,11 @@ ClearScriptGoal()
AtScriptGoal() AtScriptGoal()
{ {
return distanceSquared( self.bot.script_goal, self.origin ) <= self.bot.script_goal_dist * self.bot.script_goal_dist; if ( !isDefined( self.bot.script_goal ) )
{
return false;
}
return distanceSquared( self.origin, self.bot.script_goal ) <= ( self.bot.script_goal_dist * self.bot.script_goal_dist );
} }
/* /*
@ -1125,7 +1138,7 @@ assign_priority_to_powerup( powerup )
weapons = players[ i ] getWeaponsListPrimaries(); weapons = players[ i ] getWeaponsListPrimaries();
for ( j = 0; j < weapons.size; j++ ) for ( j = 0; j < weapons.size; j++ )
{ {
if ( self getWeaponAmmoStock( weapons[ j ] ) <= int( weaponmaxammo( weapons[ j ] ) * LOW_AMMO_THRESHOLD ) ) if ( players[ i ] getWeaponAmmoStock( weapons[ j ] ) <= int( weaponmaxammo( weapons[ j ] ) * LOW_AMMO_THRESHOLD ) )
{ {
priority += 1; priority += 1;
break; break;

View File

@ -20,6 +20,8 @@ init()
if ( getDvar( "killtest_bot_debug" ) == "" ) if ( getDvar( "killtest_bot_debug" ) == "" )
setDvar( "killtest_bot_debug", 1 ); setDvar( "killtest_bot_debug", 1 );
setDvar( "bots_skill", 7 );
level thread addBot(); level thread addBot();
level thread setupcallbacks(); level thread setupcallbacks();