mirror of
https://github.com/JezuzLizard/t4sp_bot_warfare.git
synced 2025-04-22 14:35:44 +00:00
Fix objective system to use entity numbers instead of infinitely increasing ids. Fix all known script errors. Add the ability for bots to revive players and pickup powerups automatically.
486 lines
12 KiB
Plaintext
486 lines
12 KiB
Plaintext
#include common_scripts\utility;
|
|
#include maps\_utility;
|
|
#include maps\bots\_bot_utility;
|
|
|
|
/*
|
|
Initiates the whole bot scripts.
|
|
*/
|
|
init()
|
|
{
|
|
level.bw_VERSION = "z0.1";
|
|
|
|
if ( getDvar( "bots_main" ) == "" )
|
|
setDvar( "bots_main", true );
|
|
|
|
if ( !getDvarInt( "bots_main" ) )
|
|
return;
|
|
|
|
thread load_waypoints();
|
|
thread hook_callbacks();
|
|
|
|
if ( getDvar( "bots_main_GUIDs" ) == "" )
|
|
setDvar( "bots_main_GUIDs", "" ); //guids of players who will be given host powers, comma seperated
|
|
|
|
if ( getDvar( "bots_main_firstIsHost" ) == "" )
|
|
setDvar( "bots_main_firstIsHost", true ); //first player to connect is a host
|
|
|
|
if ( getDvar( "bots_main_waitForHostTime" ) == "" )
|
|
setDvar( "bots_main_waitForHostTime", 10.0 ); //how long to wait to wait for the host player
|
|
|
|
if ( getDvar( "bots_main_kickBotsAtEnd" ) == "" )
|
|
setDvar( "bots_main_kickBotsAtEnd", false ); //kicks the bots at game end
|
|
|
|
if ( getDvar( "bots_manage_add" ) == "" )
|
|
setDvar( "bots_manage_add", 0 ); //amount of bots to add to the game
|
|
|
|
if ( getDvar( "bots_manage_fill" ) == "" )
|
|
setDvar( "bots_manage_fill", 0 ); //amount of bots to maintain
|
|
|
|
if ( getDvar( "bots_manage_fill_mode" ) == "" )
|
|
setDvar( "bots_manage_fill_mode", 0 ); //fill mode, 0 adds everyone, 1 just bots, 2 maintains at maps, 3 is 2 with 1
|
|
|
|
if ( getDvar( "bots_manage_fill_kick" ) == "" )
|
|
setDvar( "bots_manage_fill_kick", false ); //kick bots if too many
|
|
|
|
if ( getDvar( "bots_skill" ) == "" )
|
|
setDvar( "bots_skill", 0 ); //0 is random, 1 is easy 7 is hard, 8 is custom, 9 is completely random
|
|
|
|
if ( getDvar( "bots_skill_hard" ) == "" )
|
|
setDvar( "bots_skill_hard", 0 ); //amount of hard bots on axis team
|
|
|
|
if ( getDvar( "bots_skill_med" ) == "" )
|
|
setDvar( "bots_skill_med", 0 );
|
|
|
|
if ( getDvar( "bots_loadout_rank" ) == "" ) // what rank the bots should be around, -1 is around the players, 0 is all random
|
|
setDvar( "bots_loadout_rank", -1 );
|
|
|
|
if ( getDvar( "bots_loadout_prestige" ) == "" ) // what pretige the bots will be, -1 is the players, -2 is random
|
|
setDvar( "bots_loadout_prestige", -1 );
|
|
|
|
if ( getDvar( "bots_play_move" ) == "" ) //bots move
|
|
setDvar( "bots_play_move", true );
|
|
|
|
if ( getDvar( "bots_play_knife" ) == "" ) //bots knife
|
|
setDvar( "bots_play_knife", true );
|
|
|
|
if ( getDvar( "bots_play_fire" ) == "" ) //bots fire
|
|
setDvar( "bots_play_fire", true );
|
|
|
|
if ( getDvar( "bots_play_nade" ) == "" ) //bots grenade
|
|
setDvar( "bots_play_nade", true );
|
|
|
|
if ( getDvar( "bots_play_ads" ) == "" ) //bot ads
|
|
setDvar( "bots_play_ads", true );
|
|
|
|
if ( getDvar( "bots_play_aim" ) == "" )
|
|
setDvar( "bots_play_aim", true );
|
|
|
|
if ( !isDefined( game["botWarfare"] ) )
|
|
game["botWarfare"] = true;
|
|
|
|
level.bots_minSprintDistance = 315;
|
|
level.bots_minSprintDistance *= level.bots_minSprintDistance;
|
|
level.bots_minGrenadeDistance = 256;
|
|
level.bots_minGrenadeDistance *= level.bots_minGrenadeDistance;
|
|
level.bots_maxGrenadeDistance = 1024;
|
|
level.bots_maxGrenadeDistance *= level.bots_maxGrenadeDistance;
|
|
level.bots_maxKnifeDistance = 80;
|
|
level.bots_maxKnifeDistance *= level.bots_maxKnifeDistance;
|
|
level.bots_goalDistance = 27.5;
|
|
level.bots_goalDistance *= level.bots_goalDistance;
|
|
level.bots_noADSDistance = 200;
|
|
level.bots_noADSDistance *= level.bots_noADSDistance;
|
|
level.bots_maxShotgunDistance = 500;
|
|
level.bots_maxShotgunDistance *= level.bots_maxShotgunDistance;
|
|
|
|
level.players = [];
|
|
level.bots = [];
|
|
|
|
level.bots_fullautoguns = [];
|
|
level.bots_fullautoguns["thompson"] = true;
|
|
level.bots_fullautoguns["mp40"] = true;
|
|
level.bots_fullautoguns["type100smg"] = true;
|
|
level.bots_fullautoguns["ppsh"] = true;
|
|
level.bots_fullautoguns["stg44"] = true;
|
|
level.bots_fullautoguns["30cal"] = true;
|
|
level.bots_fullautoguns["mg42"] = true;
|
|
level.bots_fullautoguns["dp28"] = true;
|
|
level.bots_fullautoguns["bar"] = true;
|
|
level.bots_fullautoguns["fg42"] = true;
|
|
level.bots_fullautoguns["type99lmg"] = true;
|
|
|
|
level thread onPlayerConnect();
|
|
level thread handleBots();
|
|
|
|
maps\bots\_bot_script::register_bot_action( "objective", "powerup", maps\bots\_bot_script::bot_grab_powerup,
|
|
maps\bots\_bot_script::bot_powerup_process_order,
|
|
maps\bots\_bot_script::bot_powerup_init,
|
|
maps\bots\_bot_script::bot_powerup_post_think,
|
|
maps\bots\_bot_script::bot_should_grab_powerup,
|
|
maps\bots\_bot_script::bot_check_complete_grab_powerup,
|
|
maps\bots\_bot_script::bot_powerup_should_cancel,
|
|
maps\bots\_bot_script::bot_powerup_should_postpone,
|
|
maps\bots\_bot_script::bot_powerup_priority );
|
|
|
|
maps\bots\_bot_script::register_bot_action( "objective", "revive", maps\bots\_bot_script::bot_revive_player,
|
|
maps\bots\_bot_script::bot_revive_process_order,
|
|
maps\bots\_bot_script::bot_revive_player_init,
|
|
maps\bots\_bot_script::bot_revive_player_post_think,
|
|
maps\bots\_bot_script::bot_should_revive_player,
|
|
maps\bots\_bot_script::bot_check_complete_revive_player,
|
|
maps\bots\_bot_script::bot_revive_player_should_cancel,
|
|
maps\bots\_bot_script::bot_revive_player_should_postpone,
|
|
maps\bots\_bot_script::bot_revive_player_priority );
|
|
maps\bots\_bot_script::register_bot_objective( "powerup" );
|
|
maps\bots\_bot_script::register_bot_objective( "revive" );
|
|
|
|
level thread maps\bots\_bot_script::store_powerups_dropped();
|
|
level thread maps\bots\_bot_script::watch_for_downed_players();
|
|
}
|
|
|
|
/*
|
|
Starts the threads for bots.
|
|
*/
|
|
handleBots()
|
|
{
|
|
level thread diffBots();
|
|
level addBots();
|
|
|
|
while ( !level.intermission )
|
|
wait 0.05;
|
|
|
|
setDvar( "bots_manage_add", getBotArray().size );
|
|
|
|
if ( !getDvarInt( "bots_main_kickBotsAtEnd" ) )
|
|
return;
|
|
|
|
bots = getBotArray();
|
|
|
|
for ( i = 0; i < bots.size; i++ )
|
|
{
|
|
bots[i] RemoveTestClient();
|
|
}
|
|
}
|
|
|
|
/*
|
|
The hook callback for when any player becomes damaged.
|
|
*/
|
|
onPlayerDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, modelIndex, psOffsetTime )
|
|
{
|
|
if ( self is_bot() )
|
|
{
|
|
self maps\bots\_bot_internal::onDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, modelIndex, psOffsetTime );
|
|
self maps\bots\_bot_script::onDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, modelIndex, psOffsetTime );
|
|
}
|
|
|
|
self [[level.prevCallbackPlayerDamage]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, modelIndex, psOffsetTime );
|
|
}
|
|
|
|
on_actor_spawned()
|
|
{
|
|
if ( isDefined( level.prevCallbackActorSpawned ) )
|
|
{
|
|
self [[ level.prevCallbackActorSpawned ]]();
|
|
}
|
|
}
|
|
|
|
on_actor_killed( eInflictor, eAttacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, iTimeOffset )
|
|
{
|
|
if ( isDefined( level.prevCallbackActorKilled ) )
|
|
{
|
|
self [[ level.prevCallbackActorKilled ]]( eInflictor, eAttacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, iTimeOffset );
|
|
}
|
|
}
|
|
|
|
/*
|
|
Starts the callbacks.
|
|
*/
|
|
hook_callbacks()
|
|
{
|
|
wait 0.05;
|
|
level.prevCallbackPlayerDamage = level.callbackPlayerDamage;
|
|
level.callbackPlayerDamage = ::onPlayerDamage;
|
|
level.prevCallbackActorSpawned = level.callbackActorSpawned;
|
|
level.callbackActorSpawned = ::on_actor_spawned;
|
|
level.prevCallbackActorKilled = level.callbackActorKilled;
|
|
level.callbackActorKilled = ::on_actor_killed;
|
|
}
|
|
|
|
/*
|
|
Thread when any player connects. Starts the threads needed.
|
|
*/
|
|
onPlayerConnect()
|
|
{
|
|
for ( ;; )
|
|
{
|
|
level waittill( "connected", player );
|
|
|
|
player thread connected();
|
|
}
|
|
}
|
|
|
|
/*
|
|
When a bot disconnects.
|
|
*/
|
|
onDisconnectAll()
|
|
{
|
|
self waittill( "disconnect" );
|
|
|
|
level.players = array_remove( level.players, self );
|
|
}
|
|
|
|
/*
|
|
When any client spawns
|
|
*/
|
|
onSpawnedAll()
|
|
{
|
|
self endon( "disconnect" );
|
|
|
|
for ( ;; )
|
|
{
|
|
self waittill( "spawned_player" );
|
|
|
|
self.lastSpawnTime = getTime();
|
|
}
|
|
}
|
|
|
|
/*
|
|
When a bot disconnects.
|
|
*/
|
|
onDisconnect()
|
|
{
|
|
self waittill( "disconnect" );
|
|
|
|
level.bots = array_remove( level.bots, self );
|
|
}
|
|
|
|
/*
|
|
Called when a player connects.
|
|
*/
|
|
connected()
|
|
{
|
|
self endon( "disconnect" );
|
|
|
|
if ( !isDefined( self.pers["bot_host"] ) )
|
|
self thread doHostCheck();
|
|
|
|
level.players[level.players.size] = self;
|
|
self thread onDisconnectAll();
|
|
|
|
self thread onSpawnedAll();
|
|
|
|
if ( !self is_bot() )
|
|
return;
|
|
|
|
if ( !isDefined( self.pers["isBot"] ) )
|
|
{
|
|
// fast restart...
|
|
self.pers["isBot"] = true;
|
|
}
|
|
|
|
if ( !isDefined( self.pers["isBotWarfare"] ) )
|
|
{
|
|
self.pers["isBotWarfare"] = true;
|
|
self thread added();
|
|
}
|
|
|
|
self thread maps\bots\_bot_internal::connected();
|
|
self thread maps\bots\_bot_script::connected();
|
|
|
|
level.bots[level.bots.size] = self;
|
|
self thread onDisconnect();
|
|
|
|
level notify( "bot_connected", self );
|
|
|
|
self thread watchBotDebugEvent();
|
|
}
|
|
|
|
/*
|
|
DEBUG
|
|
*/
|
|
watchBotDebugEvent()
|
|
{
|
|
self endon( "disconnect" );
|
|
|
|
for ( ;; )
|
|
{
|
|
self waittill( "bot_event", msg, str, b, c, d, e, f, g );
|
|
|
|
if ( msg == "debug" && GetDvarInt( "bots_main_debug" ) )
|
|
{
|
|
PrintConsole( "Bot Warfare debug: " + self.name + ": " + str + "\n" );
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
When a bot gets added into the game.
|
|
*/
|
|
added()
|
|
{
|
|
self endon( "disconnect" );
|
|
|
|
self thread maps\bots\_bot_internal::added();
|
|
self thread maps\bots\_bot_script::added();
|
|
}
|
|
|
|
/*
|
|
Adds a bot to the game.
|
|
*/
|
|
add_bot()
|
|
{
|
|
bot = addtestclient();
|
|
|
|
if ( isdefined( bot ) )
|
|
{
|
|
bot.pers["isBot"] = true;
|
|
bot.pers["isBotWarfare"] = true;
|
|
bot thread added();
|
|
}
|
|
}
|
|
|
|
/*
|
|
A server thread for monitoring all bot's difficulty levels for custom server settings.
|
|
*/
|
|
diffBots_loop()
|
|
{
|
|
var_hard = getDVarInt( "bots_skill_hard" );
|
|
var_med = getDVarInt( "bots_skill_med" );
|
|
var_skill = getDvarInt( "bots_skill" );
|
|
|
|
hard = 0;
|
|
med = 0;
|
|
|
|
if ( var_skill == 8 )
|
|
{
|
|
playercount = level.players.size;
|
|
|
|
for ( i = 0; i < playercount; i++ )
|
|
{
|
|
player = level.players[i];
|
|
|
|
if ( !isDefined( player.pers["team"] ) )
|
|
continue;
|
|
|
|
if ( !player is_bot() )
|
|
continue;
|
|
|
|
if ( hard < var_hard )
|
|
{
|
|
hard++;
|
|
player.pers["bots"]["skill"]["base"] = 7;
|
|
}
|
|
else if ( med < var_med )
|
|
{
|
|
med++;
|
|
player.pers["bots"]["skill"]["base"] = 4;
|
|
}
|
|
else
|
|
player.pers["bots"]["skill"]["base"] = 1;
|
|
}
|
|
}
|
|
else if ( var_skill != 0 && var_skill != 9 )
|
|
{
|
|
playercount = level.players.size;
|
|
|
|
for ( i = 0; i < playercount; i++ )
|
|
{
|
|
player = level.players[i];
|
|
|
|
if ( !player is_bot() )
|
|
continue;
|
|
|
|
player.pers["bots"]["skill"]["base"] = var_skill;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
A server thread for monitoring all bot's difficulty levels for custom server settings.
|
|
*/
|
|
diffBots()
|
|
{
|
|
for ( ;; )
|
|
{
|
|
wait 1.5;
|
|
|
|
diffBots_loop();
|
|
}
|
|
}
|
|
|
|
/*
|
|
A server thread for monitoring all bot's in game. Will add and kick bots according to server settings.
|
|
*/
|
|
addBots_loop()
|
|
{
|
|
botsToAdd = GetDvarInt( "bots_manage_add" );
|
|
|
|
if ( botsToAdd > 0 )
|
|
{
|
|
SetDvar( "bots_manage_add", 0 );
|
|
|
|
if ( botsToAdd > 4 )
|
|
botsToAdd = 4;
|
|
|
|
for ( ; botsToAdd > 0; botsToAdd-- )
|
|
{
|
|
level add_bot();
|
|
wait 0.25;
|
|
}
|
|
}
|
|
|
|
fillMode = getDVarInt( "bots_manage_fill_mode" );
|
|
|
|
if ( fillMode == 2 || fillMode == 3 )
|
|
setDvar( "bots_manage_fill", getGoodMapAmount() );
|
|
|
|
fillAmount = getDvarInt( "bots_manage_fill" );
|
|
|
|
players = 0;
|
|
bots = 0;
|
|
|
|
playercount = level.players.size;
|
|
|
|
for ( i = 0; i < playercount; i++ )
|
|
{
|
|
player = level.players[i];
|
|
|
|
if ( player is_bot() )
|
|
bots++;
|
|
else
|
|
players++;
|
|
}
|
|
|
|
amount = bots;
|
|
|
|
if ( fillMode == 0 || fillMode == 2 )
|
|
amount += players;
|
|
|
|
if ( amount < fillAmount )
|
|
setDvar( "bots_manage_add", 1 );
|
|
else if ( amount > fillAmount && getDvarInt( "bots_manage_fill_kick" ) )
|
|
{
|
|
tempBot = PickRandom( getBotArray() );
|
|
|
|
if ( isDefined( tempBot ) )
|
|
tempBot RemoveTestClient();
|
|
}
|
|
}
|
|
|
|
/*
|
|
A server thread for monitoring all bot's in game. Will add and kick bots according to server settings.
|
|
*/
|
|
addBots()
|
|
{
|
|
level endon( "game_ended" );
|
|
|
|
bot_wait_for_host();
|
|
|
|
for ( ;; )
|
|
{
|
|
wait 1.5;
|
|
|
|
addBots_loop();
|
|
}
|
|
}
|