From 3bc50e5a331fb504e0ae6ac5e8b35b9349f0b069 Mon Sep 17 00:00:00 2001 From: ineed bots Date: Sat, 21 Sep 2024 23:36:57 -0600 Subject: [PATCH] bots properally use weapons --- maps/mp/bots/_bot.gsc | 6 +- maps/mp/bots/_bot_script.gsc | 227 +++++++++++++++++++++++++++++ maps/mp/bots/_bot_utility.gsc | 26 ++++ scripts/mp/bots_adapter_libcod.gsc | 105 ++++++++++++- 4 files changed, 360 insertions(+), 4 deletions(-) diff --git a/maps/mp/bots/_bot.gsc b/maps/mp/bots/_bot.gsc index 2a46e28..12c1f11 100644 --- a/maps/mp/bots/_bot.gsc +++ b/maps/mp/bots/_bot.gsc @@ -6,7 +6,7 @@ */ init() { - level.bw_version = "2.2.0 PR 1"; + level.bw_version = "2.3.0 PR 1"; if ( getcvar( "bots_main" ) == "" ) { @@ -43,7 +43,7 @@ init() if ( getcvar( "bots_main_kickBotsAtEnd" ) == "" ) { - setcvar( "bots_main_kickBotsAtEnd", false ); // kicks the bots at game end + setcvar( "bots_main_kickBotsAtEnd", true ); // kicks the bots at game end } if ( getcvar( "bots_manage_add" ) == "" ) @@ -70,7 +70,7 @@ init() { setcvar( "bots_manage_fill_kick", false ); // kick bots if too many } - + if ( getcvar( "bots_manage_fill_watchplayers" ) == "" ) { setcvar( "bots_manage_fill_watchplayers", false ); // add bots when player exists, kick if not diff --git a/maps/mp/bots/_bot_script.gsc b/maps/mp/bots/_bot_script.gsc index a161bbf..652806c 100644 --- a/maps/mp/bots/_bot_script.gsc +++ b/maps/mp/bots/_bot_script.gsc @@ -9,6 +9,11 @@ added() self endon( "disconnect" ); self set_diff(); + + if ( randomfloatrange( 0, 1 ) < 0.5 ) + { + self.pers[ "bots" ][ "behavior" ][ "quickscope" ] = true; + } } /* @@ -662,4 +667,226 @@ start_bot_threads() self endon( "disconnect" ); level endon( "game_ended" ); self endon( "death" ); + + self thread doReloadCancel(); + self thread bot_weapon_think(); +} + +/* + Changes to the weap +*/ +changeToWeapon( weap ) +{ + self endon( "disconnect" ); + self endon( "death" ); + level endon( "game_ended" ); + + if ( !self hasweapon( weap ) ) + { + return false; + } + + self BotBuiltinBotWeapon( weap ); + + if ( self getcurrentweapon() == weap ) + { + return true; + } + + self waittill_any_timeout( 5, "weapon_change" ); + + return ( self getcurrentweapon() == weap ); +} + +/* + Reload cancels +*/ +doReloadCancel_loop() +{ + ret = self waittill_either_return( "reload", "weapon_change" ); + + if ( self BotIsFrozen() ) + { + return; + } + + if ( self isPlantingOrDefusing() ) + { + return; + } + + curWeap = self getcurrentweapon(); + + if ( !isWeaponDroppable( curWeap ) ) + { + return; + } + + if ( ret == "reload" ) + { + // check single reloads + if ( self getweaponslotclipammo( getWeaponSlot( curWeap ) ) < WeaponClipSize( curWeap ) ) + { + return; + } + } + + // check difficulty + if ( self.pers[ "bots" ][ "skill" ][ "base" ] <= 3 ) + { + return; + } + + // check if got another weapon + weaponslist = self getWeaponsListPrimaries(); + weap = ""; + + while ( weaponslist.size ) + { + weapon = weaponslist[ randomint( weaponslist.size ) ]; + weaponslist = array_remove( weaponslist, weapon ); + + if ( !isWeaponDroppable( curWeap ) ) + { + continue; + } + + if ( curWeap == weapon || weapon == "none" || weapon == "" ) + { + continue; + } + + weap = weapon; + break; + } + + if ( weap == "" ) + { + return; + } + + // do the cancel + wait 0.1; + self thread changeToWeapon( weap ); + wait 0.25; + self thread changeToWeapon( curWeap ); + wait 2; +} + +/* + Reload cancels +*/ +doReloadCancel() +{ + self endon( "disconnect" ); + self endon( "death" ); + + for ( ;; ) + { + self doReloadCancel_loop(); + } +} + +/* + Bot logic for switching weapons. +*/ +bot_weapon_think_loop( data ) +{ + ret = self waittill_any_timeout( randomintrange( 2, 4 ), "bot_force_check_switch" ); + + if ( self BotIsFrozen() ) + { + return; + } + + if ( self isPlantingOrDefusing() ) + { + return; + } + + hasTarget = self HasThreat(); + curWeap = self getcurrentweapon(); + + force = ( ret == "bot_force_check_switch" ); + + if ( data.first ) + { + data.first = false; + + if ( randomint( 100 ) > self.pers[ "bots" ][ "behavior" ][ "initswitch" ] ) + { + return; + } + } + else + { + if ( curWeap != "none" && self getAmmoCount( curWeap ) ) + { + if ( randomint( 100 ) > self.pers[ "bots" ][ "behavior" ][ "switch" ] ) + { + return; + } + + if ( hasTarget ) + { + return; + } + } + else + { + force = true; + } + } + + weaponslist = self getWeaponsListPrimaries(); + weap = ""; + + while ( weaponslist.size ) + { + weapon = weaponslist[ randomint( weaponslist.size ) ]; + weaponslist = array_remove( weaponslist, weapon ); + + if ( !self getAmmoCount( weapon ) && !force ) + { + continue; + } + + if ( isWeaponDroppable( weapon ) ) + { + continue; + } + + if ( curWeap == weapon || weapon == "none" || weapon == "" ) + { + continue; + } + + weap = weapon; + break; + } + + if ( weap == "" ) + { + return; + } + + self thread changeToWeapon( weap ); +} + +/* + Bot logic for switching weapons. +*/ +bot_weapon_think() +{ + self endon( "death" ); + self endon( "disconnect" ); + level endon( "game_ended" ); + + data = spawnstruct(); + data.first = true; + + for ( ;; ) + { + self bot_weapon_think_loop( data ); + } } diff --git a/maps/mp/bots/_bot_utility.gsc b/maps/mp/bots/_bot_utility.gsc index f3dc89a..9d3fd71 100644 --- a/maps/mp/bots/_bot_utility.gsc +++ b/maps/mp/bots/_bot_utility.gsc @@ -96,6 +96,17 @@ BotBuiltinBotAngles( angles ) } } +/* + Sets weapon +*/ +BotBuiltinBotWeapon( weapon ) +{ + if ( isdefined( level.bot_builtins ) && isdefined( level.bot_builtins[ "botweapon" ] ) ) + { + self [[ level.bot_builtins[ "botweapon" ] ]]( weapon ); + } +} + /* Returns if player is the host */ @@ -479,6 +490,11 @@ ClearPriorityObjective() self notify( "kill_goal" ); } +isPlantingOrDefusing() +{ + return isdefined( self.progressbackground ); +} + /* If the site is in use */ @@ -591,6 +607,16 @@ getWeaponSlot( weap ) } } +getWeaponsListPrimaries() +{ + answer = []; + + answer[ answer.size ] = self getweaponslotweapon( "primary" ); + answer[ answer.size ] = self getweaponslotweapon( "primaryb" ); + + return answer; +} + /* cOD2 */ diff --git a/scripts/mp/bots_adapter_libcod.gsc b/scripts/mp/bots_adapter_libcod.gsc index 51a48c6..0394d08 100644 --- a/scripts/mp/bots_adapter_libcod.gsc +++ b/scripts/mp/bots_adapter_libcod.gsc @@ -6,6 +6,103 @@ init() level.bot_builtins[ "botmovement" ] = ::do_botmovement; level.bot_builtins[ "isbot" ] = ::do_isbot; level.bot_builtins[ "botangles" ] = ::do_botangles; + level.bot_builtins[ "botweapon" ] = ::do_botweapon; + + thread setup_weaponid_map(); +} + +register_weaponid( weap ) +{ + if ( !isdefined( level.bot_weaponids[ weap ] ) ) + { + level.bot_weaponids[ weap ] = level.bot_weaponids.size; + } +} + +setup_weaponid_map() +{ + waittillframeend; + + level.bot_weaponids = []; + register_weaponid( "none" ); + register_weaponid( "defaultweapon_mp" ); + + turrets = getentarray( "misc_turret", "classname" ); + + for ( i = 0; i < turrets.size; i++ ) + { + if ( !isdefined( turrets[i].weaponinfo ) ) + { + continue; + } + + register_weaponid( turrets[i].weaponinfo ); + } + + // in the order of precache + switch ( game[ "allies" ] ) + { + case "american": + register_weaponid( "frag_grenade_american_mp" ); + register_weaponid( "smoke_grenade_american_mp" ); + register_weaponid( "colt_mp" ); + register_weaponid( "m1carbine_mp" ); + register_weaponid( "m1garand_mp" ); + register_weaponid( "thompson_mp" ); + register_weaponid( "bar_mp" ); + register_weaponid( "springfield_mp" ); + register_weaponid( "greasegun_mp" ); + register_weaponid( "shotgun_mp" ); + break; + + case "british": + register_weaponid( "frag_grenade_british_mp" ); + register_weaponid( "smoke_grenade_british_mp" ); + register_weaponid( "webley_mp" ); + register_weaponid( "enfield_mp" ); + register_weaponid( "sten_mp" ); + register_weaponid( "bren_mp" ); + register_weaponid( "enfield_scope_mp" ); + register_weaponid( "m1garand_mp" ); + register_weaponid( "thompson_mp" ); + register_weaponid( "shotgun_mp" ); + break; + + case "russian": + register_weaponid( "frag_grenade_russian_mp" ); + register_weaponid( "smoke_grenade_russian_mp" ); + register_weaponid( "tt30_mp" ); + register_weaponid( "mosin_nagant_mp" ); + register_weaponid( "svt40_mp" ); + register_weaponid( "pps42_mp" ); + register_weaponid( "ppsh_mp" ); + register_weaponid( "mosin_nagant_sniper_mp" ); + register_weaponid( "shotgun_mp" ); + break; + } + + register_weaponid( "frag_grenade_german_mp" ); + register_weaponid( "smoke_grenade_german_mp" ); + register_weaponid( "luger_mp" ); + register_weaponid( "kar98k_mp" ); + register_weaponid( "g43_mp" ); + register_weaponid( "mp40_mp" ); + register_weaponid( "mp44_mp" ); + register_weaponid( "kar98k_sniper_mp" ); + register_weaponid( "shotgun_mp" ); + register_weaponid( "binoculars_mp" ); +} + +get_weaponid_for_string( weap ) +{ + ans = level.bot_weaponids[ weap ]; + + if ( !isdefined( ans ) ) + { + return 1; + } + + return ans; } do_printconsole( s ) @@ -94,7 +191,7 @@ do_botstop() self setbotstance( "stand" ); self setlean( "none" ); self setwalkdir( "none" ); - self switchtoweaponid( 1 ); // libcod needs weapon name to id + self switchtoweaponid( get_weaponid_for_string( self getcurrentweapon() ) ); // self botstop(); } @@ -138,3 +235,9 @@ do_botangles( angles ) self setplayerangles( angles ); // self botangles( angles[ 0 ], angles[ 1 ], angles[ 2 ] ); } + +do_botweapon( weapon ) +{ + self switchtoweaponid( get_weaponid_for_string( weapon ) ); + // self switchtoweapon( weapon ); +}