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_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\combat;
#include scripts\sp\bots\actions\movement; #include scripts\sp\bots\actions\movement;
#include scripts\sp\bots\actions\objective; #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", "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", "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( "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_poor = 0;
level.bot_weapon_quality_fair = 1; 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( "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); 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 store_powerups_dropped();
level thread spawn_bots(); 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() init()
{ {
parse_bot_weapon_stats_from_table(); parse_bot_weapon_stats_from_table();
@ -103,9 +123,9 @@ spawn_bots()
bot.action_queue[ "combat" ] = []; bot.action_queue[ "combat" ] = [];
bot.action_queue[ "movement" ] = []; bot.action_queue[ "movement" ] = [];
bot register_action_queue_actions(); bot register_action_queue_actions();
bot thread bot_movement_think();
//bot thread bot_combat_think();
bot thread bot_objective_think(); bot thread bot_objective_think();
bot thread bot_combat_think();
bot thread bot_movement_think();
bot_count++; bot_count++;
} }
} }
@ -121,43 +141,46 @@ bot_objective_think()
while ( true ) while ( true )
{ {
wait 0.05; wait 0.25;
if ( !bot_valid( self ) ) if ( !bot_valid( self ) )
{ {
self.action_queue = []; self.action_queue = [];
wait 1; wait 1;
continue; continue;
} }
/* self pick_actions_to_add_to_queue( group_name );
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 process_next_queued_action(); 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 ); assign_priority_to_powerup( powerup );
level.zbots_powerups = sort_array_by_priority_field( level.zbots_powerups, 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" ); move_To = self.bot.moveTo;
arrayRemoveValue( level.zbots_powerups, self ); angles = self GetPlayerAngles();
arrayRemoveValue( level.zbots_powerups_targeted_for_grab, self ); dir = ( 0, 0, 0 );
for ( i = 0; i < level.players.size; i++ )
if ( DistanceSquared( self.origin, move_To ) >= 49 )
{ {
if ( is_true( level.players[ i ].pers[ "isBot" ] ) && isDefined( level.players[ i ].available_powerups ) ) cosa = cos( 0 - angles[1] );
{ sina = sin( 0 - angles[1] );
arrayRemoveValue( level.players[ i ].available_powerups, self );
} // 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() 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; return false;
} }
const MAX_DISTANCE_SQ = 10000 * 10000; MAX_DISTANCE_SQ = 10000 * 10000;
const BOT_SPEED_WHILE_SPRINTING_SQ = 380 * 380; BOT_SPEED_WHILE_SPRINTING_SQ = 285 * 285;
self.available_powerups = []; self.available_powerups = [];
for ( i = 0; i < level.zbots_powerups.size; i++ ) for ( i = 0; i < level.zbots_powerups.size; i++ )
{ {
@ -783,27 +783,12 @@ bot_set_complete_grab_powerup()
bot_powerup_on_completion() 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() bot_powerup_should_cancel()
{ {
return false; return ( !isDefined( self.available_powerups ) || self.available_powerups.size <= 0 );
} }
bot_powerup_on_cancel() bot_powerup_on_cancel()

View File

@ -63,14 +63,22 @@ process_next_queued_action( group_name )
{ {
return; 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 ); self wait_for_action_completion( self.action_queue[ group_name ][ 0 ].action_name );
} }
wait_for_action_completion( group_name, 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 ) ) if ( !isDefined( result ) )
{ {
return; return;
@ -79,27 +87,27 @@ wait_for_action_completion( group_name, action_name )
{ {
return; 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 ].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 ].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 ]](); self thread [[ self.action_queue[ group_name ][ 0 ].on_completion_func ]]();
} }
else if ( result == action_name + "_cancel" ) 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 ].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 ].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 ]](); self thread [[ self.action_queue[ group_name ][ 0 ].on_cancel_func ]]();
} }
else if ( result == action_name + "_postpone" ) 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 ][ self.action_queue[ group_name ][ 0 ].action_name ].postponed = true;
postponed_action = self.action_queue[ group_name ][ 0 ]; postponed_action = self.action_queue[ group_name ][ 0 ];
arrayRemoveIndex( self.action_queue[ group_name ], 0 ); self.action_queue[ group_name ][ 0 ] = undefined;
postponed_action.priority = 0; postponed_action.priority = self [[ level.zbots_actions[ group_name ][ action_keys[ i ] ].priority_func ]]();
self.action_queue[ group_name ][ self.action_queue[ group_name ].size ] = postponed_action; 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 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; 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++ ) 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 ]]() ) 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( self.action_queue[ group_name ][ 0 ].action_name + "_cancel" );
{
self notify( action_keys[ i ] + "_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( self.action_queue[ group_name ][ 0 ].action_name + "_postpone" );
{
self notify( action_keys[ i ] + "_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 common_scripts\utility;
#include maps\mp\_utility; #include maps\_utility;
#include maps\mp\zombies\_zm_utility; #include maps\_zombiemode_utility;
register_stats_for_bot_weapon( weapon, score ) register_stats_for_bot_weapon( weapon, score )
{ {
@ -13,8 +13,8 @@ register_stats_for_bot_weapon( weapon, score )
parse_bot_weapon_stats_from_table() parse_bot_weapon_stats_from_table()
{ {
const WEAPON_COLUMN = 0; WEAPON_COLUMN = 0;
const SCORE_COLUMN = 1; SCORE_COLUMN = 1;
/* /*
row = 0; row = 0;
while ( true ) while ( true )
@ -142,8 +142,10 @@ push( array, val, index )
{ {
// use max free integer as index // use max free integer as index
index = 0; 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 ) ) if ( IsInt( key ) && ( key >= index ) )
{ {
index = key + 1; index = key + 1;
@ -151,7 +153,7 @@ push( array, val, index )
} }
} }
ArrayInsert( array, val, index ); array = array_insert( array, val, index );
return array; return array;
} }
@ -257,8 +259,8 @@ find_gaps()
are_enemies_horded() are_enemies_horded()
{ {
const MINIMUM_PERCENT_TO_BE_HORDE = 0.9; MINIMUM_PERCENT_TO_BE_HORDE = 0.9;
const DISTANCE_SQ = 120 * 120; DISTANCE_SQ = 120 * 120;
zombies = get_zombies(); zombies = get_zombies();
amount_in_horde = 0; amount_in_horde = 0;
max_eligible_zombies = isDefined( level.speed_change_round ) ? zombies.size - level.speed_change_num : zombies.size; 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() any_zombies_targeting_self()
{ {
const ZOMBIE_TARGETING_DIST_SQ = 10 * 10; ZOMBIE_TARGETING_DIST_SQ = 10 * 10;
zombies = get_zombies(); zombies = get_zombies();
if ( !array_validate( zombies ) ) if ( !array_validate( zombies ) )
{ {
@ -426,7 +428,7 @@ assign_priority_to_powerup( powerup )
} }
if ( powerup_is_max_ammo ) if ( powerup_is_max_ammo )
{ {
const LOW_AMMO_THRESHOLD = 0.3; LOW_AMMO_THRESHOLD = 0.3;
for ( i = 0; i < level.players.size; i++ ) for ( i = 0; i < level.players.size; i++ )
{ {