Fix some compile errors.

Add base scripts for personality and difficulty presets. Add canceling, and postponing thinks.
This commit is contained in:
JezuzLizard 2023-03-27 16:44:32 -07:00
parent c23fd0fd2d
commit 872630b7e2
6 changed files with 165 additions and 93 deletions

View File

@ -4,6 +4,8 @@
#include scripts\sp\bots\bot_actions_common;
#include scripts\sp\bots\bot_difficulty_presets_common;
#include scripts\sp\bots\bot_personality_presets_common;
#include scripts\sp\bots\actions\combat;
#include scripts\sp\bots\actions\movement;
#include scripts\sp\bots\actions\objective;
@ -44,6 +46,19 @@ main()
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 );
//register_bot_action( "follow" )
register_bot_personality_type( "aggressive" );
register_bot_personality_type( "passive" );
register_bot_personality_type( "supportive" );
register_bot_personality_type( "mixed" );
register_bot_personality_type( "default" );
register_bot_difficulty( "bone" );
register_bot_difficulty( "crossbones" );
register_bot_difficulty( "skull" );
register_bot_difficulty( "knife" );
register_bot_difficulty( "shotguns" );
level.bot_weapon_quality_poor = 0;
level.bot_weapon_quality_fair = 1;
@ -66,10 +81,15 @@ main()
register_bot_powerup_priority( "free_perk", level.bot_powerup_priority_medium, level.bot_powerup_priority_low );
register_bot_powerup_priority( "zombie_blood", level.bot_powerup_priority_high, level.bot_powerup_priority_urgent);
*/
level.zbot_path_nodes = getAllNodes();
level thread store_powerups_dropped();
level thread spawn_bots();
}
//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
init()
{
parse_bot_weapon_stats_from_table();
@ -103,9 +123,9 @@ spawn_bots()
bot.action_queue[ "combat" ] = [];
bot.action_queue[ "movement" ] = [];
bot register_action_queue_actions();
bot thread bot_movement_think();
//bot thread bot_combat_think();
bot thread bot_objective_think();
bot thread bot_combat_think();
bot thread bot_movement_think();
bot_count++;
}
}
@ -121,43 +141,46 @@ bot_objective_think()
while ( true )
{
wait 0.05;
wait 0.25;
if ( !bot_valid( self ) )
{
self.action_queue = [];
wait 1;
continue;
}
/*
action_keys = getArrayKeys( level.zbots_actions );
for ( i = 0; i < action_keys.size; i++ )
{
if ( self.zbot_actions_in_queue[ action_keys[ i ] ].canceled )
{
self.zbot_actions_in_queue[ action_keys[ i ] ].canceled = false;
}
}
action_keys = getArrayKeys( level.zbots_actions );
for ( i = 0; i < action_keys.size; i++ )
{
if ( self.zbot_actions_in_queue[ action_keys[ i ] ].postponed )
{
self.zbot_actions_in_queue[ action_keys[ i ] ].postponed = false;
}
}
*/
action_keys = getArrayKeys( level.zbots_actions[ group_name ] );
//TODO: Use process order funcs to determine the order of actions being added to the queue
/*
for ( i = 0; i < action_keys; i++ )
{
}
*/
self pick_actions_to_add_to_queue( group_name, action_keys );
self.action_queue[ group_name ] = self sort_array_by_priority_field( self.action_queue[ group_name ] );
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 );
}
}
bot_combat_think()
{
group_name = "combat";
level endon( "end_game" );
self endon( "disconnect" );
self waittill( "spawned_player" );
while ( true )
{
wait 0.25;
if ( !bot_valid( self ) )
{
self.action_queue = [];
wait 1;
continue;
}
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 );
}
}
@ -193,6 +216,8 @@ bot_movement_think()
}
}
}
self doBotMovement_loop();
}
}
@ -210,20 +235,38 @@ store_powerups_dropped()
}
assign_priority_to_powerup( powerup );
level.zbots_powerups = sort_array_by_priority_field( level.zbots_powerups, powerup );
powerup thread remove_from_bot_powerups_list_on_death();
}
}
remove_from_bot_powerups_list_on_death()
doBotMovement_loop()
{
self waittill( "death" );
arrayRemoveValue( level.zbots_powerups, self );
arrayRemoveValue( level.zbots_powerups_targeted_for_grab, self );
for ( i = 0; i < level.players.size; i++ )
move_To = self.bot.moveTo;
angles = self GetPlayerAngles();
dir = ( 0, 0, 0 );
if ( DistanceSquared( self.origin, move_To ) >= 49 )
{
if ( is_true( level.players[ i ].pers[ "isBot" ] ) && isDefined( level.players[ i ].available_powerups ) )
{
arrayRemoveValue( level.players[ i ].available_powerups, self );
}
cosa = cos( 0 - angles[1] );
sina = sin( 0 - angles[1] );
// get the direction
dir = move_To - self.origin;
// rotate our direction according to our angles
dir = ( dir[0] * cosa - dir[1] * sina,
dir[0] * sina + dir[1] * cosa,
0 );
// make the length 127
dir = VectorNormalize( dir ) * 127;
// invert the second component as the engine requires this
dir = ( dir[0], 0 - dir[1], 0 );
}
// move!
if ( self.bot.wantsprint && self.bot.issprinting )
dir = ( 127, dir[1], 0 );
self botMovement( int( dir[0] ), int( dir[1] ) );
}

View File

@ -724,12 +724,12 @@ bot_powerup_process_order()
bot_should_grab_powerup()
{
if ( !( isDefined( level.zbots_powerups ) && level.zbots_powerups.size > 0 ) )
if ( !isDefined( level.zbots_powerups ) || level.zbots_powerups.size <= 0 )
{
return false;
}
const MAX_DISTANCE_SQ = 10000 * 10000;
const BOT_SPEED_WHILE_SPRINTING_SQ = 380 * 380;
MAX_DISTANCE_SQ = 10000 * 10000;
BOT_SPEED_WHILE_SPRINTING_SQ = 285 * 285;
self.available_powerups = [];
for ( i = 0; i < level.zbots_powerups.size; i++ )
{
@ -783,27 +783,12 @@ bot_set_complete_grab_powerup()
bot_powerup_on_completion()
{
level endon( "end_game" );
self endon( "disconnect" );
self notify( "powerup_completion_func" );
self endon( "powerup_completion_func" );
self endon( "pause_bot_think" );
self endon( "powerup_cancel" );
self endon( "powerup_postpone" );
while ( !isDefined( self.target_powerup ) )
{
wait 0.05;
}
self.target_powerup waittill( "death" );
self.actions_in_queue[ "powerup" ].queued = false;
self notify( "powerup_completion" );
self.available_powerups = undefined;
self.target_pos = undefined;
}
bot_powerup_should_cancel()
{
return false;
return ( !isDefined( self.available_powerups ) || self.available_powerups.size <= 0 );
}
bot_powerup_on_cancel()

View File

@ -63,14 +63,22 @@ process_next_queued_action( group_name )
{
return;
}
self [[ self.action_queue[ group_name ][ 0 ].action ]]();
if ( self.zbot_actions_in_queue[ group_name ][ self.action_queue[ group_name ][ 0 ].action_name ].queued )
{
return;
}
self.action_queue[ group_name ] = self sort_array_by_priority_field( self.action_queue[ group_name ] );
self thread [[ self.action_queue[ group_name ][ 0 ].action ]]();
self wait_for_action_completion( self.action_queue[ group_name ][ 0 ].action_name );
}
wait_for_action_completion( group_name, action_name )
{
result = self waittill_any_return( action_name + "_completion", action_name + "_cancel", action_name + "_postpone", "disconnect" );
result = self waittill_any_return( action_name + "_complete", action_name + "_cancel", action_name + "_postpone", "disconnect" );
if ( !isDefined( result ) )
{
return;
@ -79,27 +87,27 @@ wait_for_action_completion( group_name, action_name )
{
return;
}
if ( ( result == action_name + "_completion" ) )
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;
arrayRemoveIndex( self.action_queue[ group_name ], 0 );
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;
arrayRemoveIndex( self.action_queue[ group_name ], 0 );
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;
postponed_action = self.action_queue[ group_name ][ 0 ];
arrayRemoveIndex( self.action_queue[ group_name ], 0 );
postponed_action.priority = 0;
self.action_queue[ group_name ][ self.action_queue[ group_name ].size ] = postponed_action;
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 ]]();
}
}
@ -117,8 +125,21 @@ copy_default_action_settings_to_queue( group_name, action_name )
self.priority_func = level.zbots_actions[ group_name ][ action_name ].priority_func;
}
pick_actions_to_add_to_queue( group_name, action_keys )
pick_actions_to_add_to_queue( group_name )
{
//TODO: Use process order funcs to determine the order of actions being added to the queue
//For now just randomize the order of the keys
/*
for ( i = 0; i < action_keys; i++ )
{
}
*/
action_keys = getArrayKeys( level.zbots_actions[ group_name ] );
action_keys = array_randomize( action_keys );
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 ]]() )
@ -131,24 +152,26 @@ pick_actions_to_add_to_queue( group_name, action_keys )
}
}
check_if_actions_should_be_canceled_in_group( group_name, action_keys )
check_if_action_should_be_canceled_in_group( group_name )
{
for ( i = 0; i < action_keys.size; i++ )
if ( [[ level.zbots_actions[ group_name ][ self.action_queue[ group_name ][ 0 ].action_name ].should_cancel_func ]]() )
{
if ( self.zbot_actions_in_queue[ group_name ][ action_keys[ i ] ].queued && [[ level.zbots_actions[ group_name ][ action_keys[ i ] ].should_cancel_func ]]() )
{
self notify( action_keys[ i ] + "_cancel" );
}
self notify( self.action_queue[ group_name ][ 0 ].action_name + "_cancel" );
}
}
check_if_actions_should_be_postponed_in_group( group_name, action_keys )
check_if_action_should_be_postponed_in_group( group_name )
{
for ( i = 0; i < action_keys.size; i++ )
if ( [[ level.zbots_actions[ group_name ][ self.action_queue[ group_name ][ 0 ].action_name ].should_postpone_func ]]() )
{
if ( self.zbot_actions_in_queue[ group_name ][ action_keys[ i ] ].queued && [[ level.zbots_actions[ group_name ][ action_keys[ i ] ].should_postpone_func ]]() )
{
self notify( action_keys[ i ] + "_postpone" );
}
self notify( self.action_queue[ group_name ][ 0 ].action_name + "_postpone" );
}
}
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" );
}
}

View File

@ -0,0 +1,9 @@
register_bot_difficulty( difficulty )
{
if ( !isDefined( level.zbot_difficulties ) )
{
level.zbot_difficulties = [];
}
level.zbot_difficulties[ difficulty ] = true;
}

View File

@ -0,0 +1,10 @@
register_bot_personality_type( personality )
{
if ( !isDefined( level.zbot_personalities ) )
{
level.zbot_personalities = [];
}
level.zbot_personalities[ personality ] = true;
}

View File

@ -1,6 +1,6 @@
#include common_scripts\utility;
#include maps\mp\_utility;
#include maps\mp\zombies\_zm_utility;
#include maps\_utility;
#include maps\_zombiemode_utility;
register_stats_for_bot_weapon( weapon, score )
{
@ -13,8 +13,8 @@ register_stats_for_bot_weapon( weapon, score )
parse_bot_weapon_stats_from_table()
{
const WEAPON_COLUMN = 0;
const SCORE_COLUMN = 1;
WEAPON_COLUMN = 0;
SCORE_COLUMN = 1;
/*
row = 0;
while ( true )
@ -142,8 +142,10 @@ push( array, val, index )
{
// use max free integer as index
index = 0;
foreach ( key in GetArrayKeys( array ) )
keys = GetArrayKeys( array );
for ( i = 0; i < keys.size; i++ )
{
key = keys[ i ];
if ( IsInt( key ) && ( key >= index ) )
{
index = key + 1;
@ -151,7 +153,7 @@ push( array, val, index )
}
}
ArrayInsert( array, val, index );
array = array_insert( array, val, index );
return array;
}
@ -257,8 +259,8 @@ find_gaps()
are_enemies_horded()
{
const MINIMUM_PERCENT_TO_BE_HORDE = 0.9;
const DISTANCE_SQ = 120 * 120;
MINIMUM_PERCENT_TO_BE_HORDE = 0.9;
DISTANCE_SQ = 120 * 120;
zombies = get_zombies();
amount_in_horde = 0;
max_eligible_zombies = isDefined( level.speed_change_round ) ? zombies.size - level.speed_change_num : zombies.size;
@ -338,7 +340,7 @@ predict_entity_position_seconds( seconds )
any_zombies_targeting_self()
{
const ZOMBIE_TARGETING_DIST_SQ = 10 * 10;
ZOMBIE_TARGETING_DIST_SQ = 10 * 10;
zombies = get_zombies();
if ( !array_validate( zombies ) )
{
@ -426,7 +428,7 @@ assign_priority_to_powerup( powerup )
}
if ( powerup_is_max_ammo )
{
const LOW_AMMO_THRESHOLD = 0.3;
LOW_AMMO_THRESHOLD = 0.3;
for ( i = 0; i < level.players.size; i++ )
{