mirror of
https://github.com/JezuzLizard/t4sp_bot_warfare.git
synced 2025-06-30 00:01:58 +00:00
They walk bro.
This commit is contained in:
423
maps/bots/_bot.gsc
Normal file
423
maps/bots/_bot.gsc
Normal file
@ -0,0 +1,423 @@
|
||||
#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();
|
||||
}
|
||||
|
||||
/*
|
||||
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, iModelIndex, timeOffset )
|
||||
{
|
||||
if ( self is_bot() )
|
||||
{
|
||||
self maps\bots\_bot_internal::onDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, iModelIndex, timeOffset );
|
||||
self maps\bots\_bot_script::onDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, iModelIndex, timeOffset );
|
||||
}
|
||||
|
||||
self [[level.prevCallbackPlayerDamage]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, iModelIndex, timeOffset );
|
||||
}
|
||||
|
||||
/*
|
||||
Starts the callbacks.
|
||||
*/
|
||||
hook_callbacks()
|
||||
{
|
||||
wait 0.05;
|
||||
level.prevCallbackPlayerDamage = level.callbackPlayerDamage;
|
||||
level.callbackPlayerDamage = ::onPlayerDamage;
|
||||
}
|
||||
|
||||
/*
|
||||
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 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();
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
1106
maps/bots/_bot_internal.gsc
Normal file
1106
maps/bots/_bot_internal.gsc
Normal file
File diff suppressed because it is too large
Load Diff
315
maps/bots/_bot_script.gsc
Normal file
315
maps/bots/_bot_script.gsc
Normal file
@ -0,0 +1,315 @@
|
||||
#include common_scripts\utility;
|
||||
#include maps\_utility;
|
||||
#include maps\bots\_bot_utility;
|
||||
|
||||
/*
|
||||
When the bot gets added into the game.
|
||||
*/
|
||||
added()
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
}
|
||||
|
||||
/*
|
||||
When the bot connects to the game.
|
||||
*/
|
||||
connected()
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
|
||||
self thread difficulty();
|
||||
self thread onBotSpawned();
|
||||
self thread onSpawned();
|
||||
}
|
||||
|
||||
/*
|
||||
The callback for when the bot gets damaged.
|
||||
*/
|
||||
onDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, timeOffset )
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
Updates the bot's difficulty variables.
|
||||
*/
|
||||
difficulty()
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
if ( GetDvarInt( "bots_skill" ) != 9 )
|
||||
{
|
||||
switch ( self.pers["bots"]["skill"]["base"] )
|
||||
{
|
||||
case 1:
|
||||
self.pers["bots"]["skill"]["aim_time"] = 0.6;
|
||||
self.pers["bots"]["skill"]["init_react_time"] = 1500;
|
||||
self.pers["bots"]["skill"]["reaction_time"] = 1000;
|
||||
self.pers["bots"]["skill"]["no_trace_ads_time"] = 500;
|
||||
self.pers["bots"]["skill"]["no_trace_look_time"] = 600;
|
||||
self.pers["bots"]["skill"]["remember_time"] = 750;
|
||||
self.pers["bots"]["skill"]["fov"] = 0.7;
|
||||
self.pers["bots"]["skill"]["dist_max"] = 2500;
|
||||
self.pers["bots"]["skill"]["dist_start"] = 1000;
|
||||
self.pers["bots"]["skill"]["spawn_time"] = 0.75;
|
||||
self.pers["bots"]["skill"]["help_dist"] = 0;
|
||||
self.pers["bots"]["skill"]["semi_time"] = 0.9;
|
||||
self.pers["bots"]["skill"]["shoot_after_time"] = 1;
|
||||
self.pers["bots"]["skill"]["aim_offset_time"] = 1.5;
|
||||
self.pers["bots"]["skill"]["aim_offset_amount"] = 4;
|
||||
self.pers["bots"]["skill"]["bone_update_interval"] = 2;
|
||||
self.pers["bots"]["skill"]["bones"] = "j_spineupper,j_ankle_le,j_ankle_ri";
|
||||
self.pers["bots"]["skill"]["ads_fov_multi"] = 0.5;
|
||||
self.pers["bots"]["skill"]["ads_aimspeed_multi"] = 0.5;
|
||||
|
||||
self.pers["bots"]["behavior"]["strafe"] = 0;
|
||||
self.pers["bots"]["behavior"]["nade"] = 10;
|
||||
self.pers["bots"]["behavior"]["sprint"] = 30;
|
||||
self.pers["bots"]["behavior"]["camp"] = 5;
|
||||
self.pers["bots"]["behavior"]["follow"] = 5;
|
||||
self.pers["bots"]["behavior"]["crouch"] = 20;
|
||||
self.pers["bots"]["behavior"]["switch"] = 2;
|
||||
self.pers["bots"]["behavior"]["class"] = 2;
|
||||
self.pers["bots"]["behavior"]["jump"] = 0;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
self.pers["bots"]["skill"]["aim_time"] = 0.55;
|
||||
self.pers["bots"]["skill"]["init_react_time"] = 1000;
|
||||
self.pers["bots"]["skill"]["reaction_time"] = 800;
|
||||
self.pers["bots"]["skill"]["no_trace_ads_time"] = 1000;
|
||||
self.pers["bots"]["skill"]["no_trace_look_time"] = 1250;
|
||||
self.pers["bots"]["skill"]["remember_time"] = 1500;
|
||||
self.pers["bots"]["skill"]["fov"] = 0.65;
|
||||
self.pers["bots"]["skill"]["dist_max"] = 3000;
|
||||
self.pers["bots"]["skill"]["dist_start"] = 1500;
|
||||
self.pers["bots"]["skill"]["spawn_time"] = 0.65;
|
||||
self.pers["bots"]["skill"]["help_dist"] = 500;
|
||||
self.pers["bots"]["skill"]["semi_time"] = 0.75;
|
||||
self.pers["bots"]["skill"]["shoot_after_time"] = 0.75;
|
||||
self.pers["bots"]["skill"]["aim_offset_time"] = 1;
|
||||
self.pers["bots"]["skill"]["aim_offset_amount"] = 3;
|
||||
self.pers["bots"]["skill"]["bone_update_interval"] = 1.5;
|
||||
self.pers["bots"]["skill"]["bones"] = "j_spineupper,j_ankle_le,j_ankle_ri,j_head";
|
||||
self.pers["bots"]["skill"]["ads_fov_multi"] = 0.5;
|
||||
self.pers["bots"]["skill"]["ads_aimspeed_multi"] = 0.5;
|
||||
|
||||
self.pers["bots"]["behavior"]["strafe"] = 10;
|
||||
self.pers["bots"]["behavior"]["nade"] = 15;
|
||||
self.pers["bots"]["behavior"]["sprint"] = 45;
|
||||
self.pers["bots"]["behavior"]["camp"] = 5;
|
||||
self.pers["bots"]["behavior"]["follow"] = 5;
|
||||
self.pers["bots"]["behavior"]["crouch"] = 15;
|
||||
self.pers["bots"]["behavior"]["switch"] = 2;
|
||||
self.pers["bots"]["behavior"]["class"] = 2;
|
||||
self.pers["bots"]["behavior"]["jump"] = 10;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
self.pers["bots"]["skill"]["aim_time"] = 0.4;
|
||||
self.pers["bots"]["skill"]["init_react_time"] = 750;
|
||||
self.pers["bots"]["skill"]["reaction_time"] = 500;
|
||||
self.pers["bots"]["skill"]["no_trace_ads_time"] = 1000;
|
||||
self.pers["bots"]["skill"]["no_trace_look_time"] = 1500;
|
||||
self.pers["bots"]["skill"]["remember_time"] = 2000;
|
||||
self.pers["bots"]["skill"]["fov"] = 0.6;
|
||||
self.pers["bots"]["skill"]["dist_max"] = 4000;
|
||||
self.pers["bots"]["skill"]["dist_start"] = 2250;
|
||||
self.pers["bots"]["skill"]["spawn_time"] = 0.5;
|
||||
self.pers["bots"]["skill"]["help_dist"] = 750;
|
||||
self.pers["bots"]["skill"]["semi_time"] = 0.65;
|
||||
self.pers["bots"]["skill"]["shoot_after_time"] = 0.65;
|
||||
self.pers["bots"]["skill"]["aim_offset_time"] = 0.75;
|
||||
self.pers["bots"]["skill"]["aim_offset_amount"] = 2.5;
|
||||
self.pers["bots"]["skill"]["bone_update_interval"] = 1;
|
||||
self.pers["bots"]["skill"]["bones"] = "j_spineupper,j_spineupper,j_ankle_le,j_ankle_ri,j_head";
|
||||
self.pers["bots"]["skill"]["ads_fov_multi"] = 0.5;
|
||||
self.pers["bots"]["skill"]["ads_aimspeed_multi"] = 0.5;
|
||||
|
||||
self.pers["bots"]["behavior"]["strafe"] = 20;
|
||||
self.pers["bots"]["behavior"]["nade"] = 20;
|
||||
self.pers["bots"]["behavior"]["sprint"] = 50;
|
||||
self.pers["bots"]["behavior"]["camp"] = 5;
|
||||
self.pers["bots"]["behavior"]["follow"] = 5;
|
||||
self.pers["bots"]["behavior"]["crouch"] = 10;
|
||||
self.pers["bots"]["behavior"]["switch"] = 2;
|
||||
self.pers["bots"]["behavior"]["class"] = 2;
|
||||
self.pers["bots"]["behavior"]["jump"] = 25;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
self.pers["bots"]["skill"]["aim_time"] = 0.3;
|
||||
self.pers["bots"]["skill"]["init_react_time"] = 600;
|
||||
self.pers["bots"]["skill"]["reaction_time"] = 400;
|
||||
self.pers["bots"]["skill"]["no_trace_ads_time"] = 1000;
|
||||
self.pers["bots"]["skill"]["no_trace_look_time"] = 1500;
|
||||
self.pers["bots"]["skill"]["remember_time"] = 3000;
|
||||
self.pers["bots"]["skill"]["fov"] = 0.55;
|
||||
self.pers["bots"]["skill"]["dist_max"] = 5000;
|
||||
self.pers["bots"]["skill"]["dist_start"] = 3350;
|
||||
self.pers["bots"]["skill"]["spawn_time"] = 0.35;
|
||||
self.pers["bots"]["skill"]["help_dist"] = 1000;
|
||||
self.pers["bots"]["skill"]["semi_time"] = 0.5;
|
||||
self.pers["bots"]["skill"]["shoot_after_time"] = 0.5;
|
||||
self.pers["bots"]["skill"]["aim_offset_time"] = 0.5;
|
||||
self.pers["bots"]["skill"]["aim_offset_amount"] = 2;
|
||||
self.pers["bots"]["skill"]["bone_update_interval"] = 0.75;
|
||||
self.pers["bots"]["skill"]["bones"] = "j_spineupper,j_spineupper,j_ankle_le,j_ankle_ri,j_head,j_head";
|
||||
self.pers["bots"]["skill"]["ads_fov_multi"] = 0.5;
|
||||
self.pers["bots"]["skill"]["ads_aimspeed_multi"] = 0.5;
|
||||
|
||||
self.pers["bots"]["behavior"]["strafe"] = 30;
|
||||
self.pers["bots"]["behavior"]["nade"] = 25;
|
||||
self.pers["bots"]["behavior"]["sprint"] = 55;
|
||||
self.pers["bots"]["behavior"]["camp"] = 5;
|
||||
self.pers["bots"]["behavior"]["follow"] = 5;
|
||||
self.pers["bots"]["behavior"]["crouch"] = 10;
|
||||
self.pers["bots"]["behavior"]["switch"] = 2;
|
||||
self.pers["bots"]["behavior"]["class"] = 2;
|
||||
self.pers["bots"]["behavior"]["jump"] = 35;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
self.pers["bots"]["skill"]["aim_time"] = 0.25;
|
||||
self.pers["bots"]["skill"]["init_react_time"] = 500;
|
||||
self.pers["bots"]["skill"]["reaction_time"] = 300;
|
||||
self.pers["bots"]["skill"]["no_trace_ads_time"] = 1500;
|
||||
self.pers["bots"]["skill"]["no_trace_look_time"] = 2000;
|
||||
self.pers["bots"]["skill"]["remember_time"] = 4000;
|
||||
self.pers["bots"]["skill"]["fov"] = 0.5;
|
||||
self.pers["bots"]["skill"]["dist_max"] = 7500;
|
||||
self.pers["bots"]["skill"]["dist_start"] = 5000;
|
||||
self.pers["bots"]["skill"]["spawn_time"] = 0.25;
|
||||
self.pers["bots"]["skill"]["help_dist"] = 1500;
|
||||
self.pers["bots"]["skill"]["semi_time"] = 0.4;
|
||||
self.pers["bots"]["skill"]["shoot_after_time"] = 0.35;
|
||||
self.pers["bots"]["skill"]["aim_offset_time"] = 0.35;
|
||||
self.pers["bots"]["skill"]["aim_offset_amount"] = 1.5;
|
||||
self.pers["bots"]["skill"]["bone_update_interval"] = 0.5;
|
||||
self.pers["bots"]["skill"]["bones"] = "j_spineupper,j_head";
|
||||
self.pers["bots"]["skill"]["ads_fov_multi"] = 0.5;
|
||||
self.pers["bots"]["skill"]["ads_aimspeed_multi"] = 0.5;
|
||||
|
||||
self.pers["bots"]["behavior"]["strafe"] = 40;
|
||||
self.pers["bots"]["behavior"]["nade"] = 35;
|
||||
self.pers["bots"]["behavior"]["sprint"] = 60;
|
||||
self.pers["bots"]["behavior"]["camp"] = 5;
|
||||
self.pers["bots"]["behavior"]["follow"] = 5;
|
||||
self.pers["bots"]["behavior"]["crouch"] = 10;
|
||||
self.pers["bots"]["behavior"]["switch"] = 2;
|
||||
self.pers["bots"]["behavior"]["class"] = 2;
|
||||
self.pers["bots"]["behavior"]["jump"] = 50;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
self.pers["bots"]["skill"]["aim_time"] = 0.2;
|
||||
self.pers["bots"]["skill"]["init_react_time"] = 250;
|
||||
self.pers["bots"]["skill"]["reaction_time"] = 150;
|
||||
self.pers["bots"]["skill"]["no_trace_ads_time"] = 2000;
|
||||
self.pers["bots"]["skill"]["no_trace_look_time"] = 3000;
|
||||
self.pers["bots"]["skill"]["remember_time"] = 5000;
|
||||
self.pers["bots"]["skill"]["fov"] = 0.45;
|
||||
self.pers["bots"]["skill"]["dist_max"] = 10000;
|
||||
self.pers["bots"]["skill"]["dist_start"] = 7500;
|
||||
self.pers["bots"]["skill"]["spawn_time"] = 0.2;
|
||||
self.pers["bots"]["skill"]["help_dist"] = 2000;
|
||||
self.pers["bots"]["skill"]["semi_time"] = 0.25;
|
||||
self.pers["bots"]["skill"]["shoot_after_time"] = 0.25;
|
||||
self.pers["bots"]["skill"]["aim_offset_time"] = 0.25;
|
||||
self.pers["bots"]["skill"]["aim_offset_amount"] = 1;
|
||||
self.pers["bots"]["skill"]["bone_update_interval"] = 0.25;
|
||||
self.pers["bots"]["skill"]["bones"] = "j_spineupper,j_head,j_head";
|
||||
self.pers["bots"]["skill"]["ads_fov_multi"] = 0.5;
|
||||
self.pers["bots"]["skill"]["ads_aimspeed_multi"] = 0.5;
|
||||
|
||||
self.pers["bots"]["behavior"]["strafe"] = 50;
|
||||
self.pers["bots"]["behavior"]["nade"] = 45;
|
||||
self.pers["bots"]["behavior"]["sprint"] = 65;
|
||||
self.pers["bots"]["behavior"]["camp"] = 5;
|
||||
self.pers["bots"]["behavior"]["follow"] = 5;
|
||||
self.pers["bots"]["behavior"]["crouch"] = 10;
|
||||
self.pers["bots"]["behavior"]["switch"] = 2;
|
||||
self.pers["bots"]["behavior"]["class"] = 2;
|
||||
self.pers["bots"]["behavior"]["jump"] = 75;
|
||||
break;
|
||||
|
||||
case 7:
|
||||
self.pers["bots"]["skill"]["aim_time"] = 0.1;
|
||||
self.pers["bots"]["skill"]["init_react_time"] = 100;
|
||||
self.pers["bots"]["skill"]["reaction_time"] = 50;
|
||||
self.pers["bots"]["skill"]["no_trace_ads_time"] = 2500;
|
||||
self.pers["bots"]["skill"]["no_trace_look_time"] = 4000;
|
||||
self.pers["bots"]["skill"]["remember_time"] = 7500;
|
||||
self.pers["bots"]["skill"]["fov"] = 0.4;
|
||||
self.pers["bots"]["skill"]["dist_max"] = 15000;
|
||||
self.pers["bots"]["skill"]["dist_start"] = 10000;
|
||||
self.pers["bots"]["skill"]["spawn_time"] = 0.05;
|
||||
self.pers["bots"]["skill"]["help_dist"] = 3000;
|
||||
self.pers["bots"]["skill"]["semi_time"] = 0.1;
|
||||
self.pers["bots"]["skill"]["shoot_after_time"] = 0;
|
||||
self.pers["bots"]["skill"]["aim_offset_time"] = 0;
|
||||
self.pers["bots"]["skill"]["aim_offset_amount"] = 0;
|
||||
self.pers["bots"]["skill"]["bone_update_interval"] = 0.05;
|
||||
self.pers["bots"]["skill"]["bones"] = "j_head";
|
||||
self.pers["bots"]["skill"]["ads_fov_multi"] = 0.5;
|
||||
self.pers["bots"]["skill"]["ads_aimspeed_multi"] = 0.5;
|
||||
|
||||
self.pers["bots"]["behavior"]["strafe"] = 65;
|
||||
self.pers["bots"]["behavior"]["nade"] = 65;
|
||||
self.pers["bots"]["behavior"]["sprint"] = 70;
|
||||
self.pers["bots"]["behavior"]["camp"] = 5;
|
||||
self.pers["bots"]["behavior"]["follow"] = 5;
|
||||
self.pers["bots"]["behavior"]["crouch"] = 5;
|
||||
self.pers["bots"]["behavior"]["switch"] = 2;
|
||||
self.pers["bots"]["behavior"]["class"] = 2;
|
||||
self.pers["bots"]["behavior"]["jump"] = 90;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
wait 5;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
When the bot spawned, after the difficulty wait. Start the logic for the bot.
|
||||
*/
|
||||
onBotSpawned()
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
level endon( "intermission" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
self waittill( "bot_spawned" );
|
||||
|
||||
self thread start_bot_threads();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
When the bot spawns.
|
||||
*/
|
||||
onSpawned()
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
self waittill( "spawned_player" );
|
||||
|
||||
self.bot_lock_goal = false;
|
||||
self.bot_was_follow_script_update = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Starts all the bot thinking
|
||||
*/
|
||||
start_bot_threads()
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
level endon( "intermission" );
|
||||
self endon( "zombified" );
|
||||
}
|
994
maps/bots/_bot_utility.gsc
Normal file
994
maps/bots/_bot_utility.gsc
Normal file
@ -0,0 +1,994 @@
|
||||
#include common_scripts\utility;
|
||||
#include maps\_utility;
|
||||
|
||||
/*
|
||||
Returns if player is the host
|
||||
*/
|
||||
is_host()
|
||||
{
|
||||
return ( isDefined( self.pers["bot_host"] ) && self.pers["bot_host"] );
|
||||
}
|
||||
|
||||
/*
|
||||
Setups the host variable on the player
|
||||
*/
|
||||
doHostCheck()
|
||||
{
|
||||
self.pers["bot_host"] = false;
|
||||
|
||||
if ( self is_bot() )
|
||||
return;
|
||||
|
||||
result = false;
|
||||
|
||||
if ( getDvar( "bots_main_firstIsHost" ) != "0" )
|
||||
{
|
||||
PrintConsole( "WARNING: bots_main_firstIsHost is enabled\n" );
|
||||
|
||||
if ( getDvar( "bots_main_firstIsHost" ) == "1" )
|
||||
{
|
||||
setDvar( "bots_main_firstIsHost", self getguid() );
|
||||
}
|
||||
|
||||
if ( getDvar( "bots_main_firstIsHost" ) == self getguid() + "" )
|
||||
result = true;
|
||||
}
|
||||
|
||||
DvarGUID = getDvar( "bots_main_GUIDs" );
|
||||
|
||||
if ( DvarGUID != "" )
|
||||
{
|
||||
guids = strtok( DvarGUID, "," );
|
||||
|
||||
for ( i = 0; i < guids.size; i++ )
|
||||
{
|
||||
if ( self getguid() + "" == guids[i] )
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !result )
|
||||
return;
|
||||
|
||||
self.pers["bot_host"] = true;
|
||||
}
|
||||
|
||||
/*
|
||||
Returns if the player is a bot.
|
||||
*/
|
||||
is_bot()
|
||||
{
|
||||
return self isBot();
|
||||
}
|
||||
|
||||
/*
|
||||
Set the bot's stance
|
||||
*/
|
||||
BotSetStance( stance )
|
||||
{
|
||||
switch ( stance )
|
||||
{
|
||||
case "stand":
|
||||
self maps\bots\_bot_internal::stand();
|
||||
break;
|
||||
|
||||
case "crouch":
|
||||
self maps\bots\_bot_internal::crouch();
|
||||
break;
|
||||
|
||||
case "prone":
|
||||
self maps\bots\_bot_internal::prone();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Bot changes to the weap
|
||||
*/
|
||||
BotChangeToWeapon( weap )
|
||||
{
|
||||
self botWeapon( weap );
|
||||
}
|
||||
|
||||
/*
|
||||
Bot presses the button for time.
|
||||
*/
|
||||
BotPressAttack( time )
|
||||
{
|
||||
self maps\bots\_bot_internal::pressFire( time );
|
||||
}
|
||||
|
||||
/*
|
||||
Bot presses the ads button for time.
|
||||
*/
|
||||
BotPressADS( time )
|
||||
{
|
||||
self maps\bots\_bot_internal::pressADS( time );
|
||||
}
|
||||
|
||||
/*
|
||||
Bot presses the use button for time.
|
||||
*/
|
||||
BotPressUse( time )
|
||||
{
|
||||
self maps\bots\_bot_internal::use( time );
|
||||
}
|
||||
|
||||
/*
|
||||
Bot presses the frag button for time.
|
||||
*/
|
||||
BotPressFrag( time )
|
||||
{
|
||||
self maps\bots\_bot_internal::frag( time );
|
||||
}
|
||||
|
||||
/*
|
||||
Bot presses the smoke button for time.
|
||||
*/
|
||||
BotPressSmoke( time )
|
||||
{
|
||||
self maps\bots\_bot_internal::smoke( time );
|
||||
}
|
||||
|
||||
/*
|
||||
Returns the bot's random assigned number.
|
||||
*/
|
||||
BotGetRandom()
|
||||
{
|
||||
return self.bot.rand;
|
||||
}
|
||||
|
||||
/*
|
||||
Returns a random number thats different everytime it changes target
|
||||
*/
|
||||
BotGetTargetRandom()
|
||||
{
|
||||
if ( !isDefined( self.bot.target ) )
|
||||
return undefined;
|
||||
|
||||
return self.bot.target.rand;
|
||||
}
|
||||
|
||||
/*
|
||||
Returns if the bot is fragging.
|
||||
*/
|
||||
IsBotFragging()
|
||||
{
|
||||
return self.bot.isfraggingafter;
|
||||
}
|
||||
|
||||
/*
|
||||
Returns if the bot is pressing smoke button.
|
||||
*/
|
||||
IsBotSmoking()
|
||||
{
|
||||
return self.bot.issmokingafter;
|
||||
}
|
||||
|
||||
/*
|
||||
Returns if the bot is sprinting.
|
||||
*/
|
||||
IsBotSprinting()
|
||||
{
|
||||
return self.bot.issprinting;
|
||||
}
|
||||
|
||||
/*
|
||||
Returns if the bot is reloading.
|
||||
*/
|
||||
IsBotReloading()
|
||||
{
|
||||
return self.bot.isreloading;
|
||||
}
|
||||
|
||||
/*
|
||||
Is bot knifing
|
||||
*/
|
||||
IsBotKnifing()
|
||||
{
|
||||
return self.bot.isknifingafter;
|
||||
}
|
||||
|
||||
/*
|
||||
Freezes the bot's controls.
|
||||
*/
|
||||
BotFreezeControls( what )
|
||||
{
|
||||
self.bot.isfrozen = what;
|
||||
|
||||
if ( what )
|
||||
self notify( "kill_goal" );
|
||||
}
|
||||
|
||||
/*
|
||||
Returns if the bot is script frozen.
|
||||
*/
|
||||
BotIsFrozen()
|
||||
{
|
||||
return self.bot.isfrozen;
|
||||
}
|
||||
|
||||
/*
|
||||
Bot will stop moving
|
||||
*/
|
||||
BotStopMoving( what )
|
||||
{
|
||||
self.bot.stop_move = what;
|
||||
|
||||
if ( what )
|
||||
self notify( "kill_goal" );
|
||||
}
|
||||
|
||||
/*
|
||||
Notify the bot chat message
|
||||
*/
|
||||
BotNotifyBotEvent( msg, a, b, c, d, e, f, g )
|
||||
{
|
||||
self notify( "bot_event", msg, a, b, c, d, e, f, g );
|
||||
}
|
||||
|
||||
/*
|
||||
Returns if the bot has a script goal.
|
||||
(like t5 gsc bot)
|
||||
*/
|
||||
HasScriptGoal()
|
||||
{
|
||||
return ( isDefined( self GetScriptGoal() ) );
|
||||
}
|
||||
|
||||
/*
|
||||
Returns the pos of the bot's goal
|
||||
*/
|
||||
GetScriptGoal()
|
||||
{
|
||||
return self.bot.script_goal;
|
||||
}
|
||||
|
||||
/*
|
||||
Sets the bot's goal, will acheive it when dist away from it.
|
||||
*/
|
||||
SetScriptGoal( goal, dist )
|
||||
{
|
||||
if ( !isDefined( dist ) )
|
||||
dist = 16;
|
||||
|
||||
self.bot.script_goal = goal;
|
||||
self.bot.script_goal_dist = dist;
|
||||
waittillframeend;
|
||||
self notify( "new_goal_internal" );
|
||||
self notify( "new_goal" );
|
||||
}
|
||||
|
||||
/*
|
||||
Clears the bot's goal.
|
||||
*/
|
||||
ClearScriptGoal()
|
||||
{
|
||||
self SetScriptGoal( undefined, 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
Sets the aim position of the bot
|
||||
*/
|
||||
SetScriptAimPos( pos )
|
||||
{
|
||||
self.bot.script_aimpos = pos;
|
||||
}
|
||||
|
||||
/*
|
||||
Clears the aim position of the bot
|
||||
*/
|
||||
ClearScriptAimPos()
|
||||
{
|
||||
self SetScriptAimPos( undefined );
|
||||
}
|
||||
|
||||
/*
|
||||
Returns the aim position of the bot
|
||||
*/
|
||||
GetScriptAimPos()
|
||||
{
|
||||
return self.bot.script_aimpos;
|
||||
}
|
||||
|
||||
/*
|
||||
Returns if the bot has a aim pos
|
||||
*/
|
||||
HasScriptAimPos()
|
||||
{
|
||||
return isDefined( self GetScriptAimPos() );
|
||||
}
|
||||
|
||||
/*
|
||||
Sets the bot's target to be this ent.
|
||||
*/
|
||||
SetAttacker( att )
|
||||
{
|
||||
self.bot.target_this_frame = att;
|
||||
}
|
||||
|
||||
/*
|
||||
Sets the script enemy for a bot.
|
||||
*/
|
||||
SetScriptEnemy( enemy, offset )
|
||||
{
|
||||
self.bot.script_target = enemy;
|
||||
self.bot.script_target_offset = offset;
|
||||
}
|
||||
|
||||
/*
|
||||
Removes the script enemy of the bot.
|
||||
*/
|
||||
ClearScriptEnemy()
|
||||
{
|
||||
self SetScriptEnemy( undefined, undefined );
|
||||
}
|
||||
|
||||
/*
|
||||
Returns the entity of the bot's target.
|
||||
*/
|
||||
GetThreat()
|
||||
{
|
||||
if ( !isdefined( self.bot.target ) )
|
||||
return undefined;
|
||||
|
||||
return self.bot.target.entity;
|
||||
}
|
||||
|
||||
/*
|
||||
Returns if the bot has a script enemy.
|
||||
*/
|
||||
HasScriptEnemy()
|
||||
{
|
||||
return ( isDefined( self.bot.script_target ) );
|
||||
}
|
||||
|
||||
/*
|
||||
Returns if the bot has a threat.
|
||||
*/
|
||||
HasThreat()
|
||||
{
|
||||
return ( isDefined( self GetThreat() ) );
|
||||
}
|
||||
|
||||
/*
|
||||
Returns a valid grenade launcher weapon
|
||||
*/
|
||||
getValidTube()
|
||||
{
|
||||
weaps = self getweaponslist();
|
||||
|
||||
for ( i = 0; i < weaps.size; i++ )
|
||||
{
|
||||
weap = weaps[i];
|
||||
|
||||
if ( !self getAmmoCount( weap ) )
|
||||
continue;
|
||||
|
||||
if ( isSubStr( weap, "gl_" ) && !isSubStr( weap, "_gl_" ) )
|
||||
return weap;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/*
|
||||
Returns a random grenade in the bot's inventory.
|
||||
*/
|
||||
getValidGrenade()
|
||||
{
|
||||
grenadeTypes = [];
|
||||
grenadeTypes[grenadeTypes.size] = "stielhandgranate";
|
||||
|
||||
possibles = [];
|
||||
|
||||
for ( i = 0; i < grenadeTypes.size; i++ )
|
||||
{
|
||||
if ( !self hasWeapon( grenadeTypes[i] ) )
|
||||
continue;
|
||||
|
||||
if ( !self getAmmoCount( grenadeTypes[i] ) )
|
||||
continue;
|
||||
|
||||
possibles[possibles.size] = grenadeTypes[i];
|
||||
}
|
||||
|
||||
return PickRandom( possibles );
|
||||
}
|
||||
|
||||
/*
|
||||
Picks a random thing
|
||||
*/
|
||||
PickRandom( arr )
|
||||
{
|
||||
if ( !arr.size )
|
||||
return undefined;
|
||||
|
||||
return arr[randomInt( arr.size )];
|
||||
}
|
||||
|
||||
/*
|
||||
If weap is a secondary gnade
|
||||
*/
|
||||
isSecondaryGrenade( gnade )
|
||||
{
|
||||
return ( gnade == "zombie_cymbal_monkey" );
|
||||
}
|
||||
|
||||
/*
|
||||
CoD4
|
||||
*/
|
||||
getBaseWeaponName( weap )
|
||||
{
|
||||
return strtok( weap, "_" )[0];
|
||||
}
|
||||
|
||||
/*
|
||||
Returns if the given weapon is full auto.
|
||||
*/
|
||||
WeaponIsFullAuto( weap )
|
||||
{
|
||||
weaptoks = strtok( weap, "_" );
|
||||
|
||||
return isDefined( weaptoks[0] ) && isString( weaptoks[0] ) && isdefined( level.bots_fullautoguns[weaptoks[0]] );
|
||||
}
|
||||
|
||||
/*
|
||||
Returns what our eye height is.
|
||||
*/
|
||||
GetEyeHeight()
|
||||
{
|
||||
myEye = self GetEyePos();
|
||||
|
||||
return myEye[2] - self.origin[2];
|
||||
}
|
||||
|
||||
/*
|
||||
Returns (iw4) eye pos.
|
||||
*/
|
||||
GetEyePos()
|
||||
{
|
||||
return self getTagOrigin( "tag_eye" );
|
||||
}
|
||||
|
||||
/*
|
||||
helper
|
||||
*/
|
||||
waittill_either_return_( str1, str2 )
|
||||
{
|
||||
self endon( str1 );
|
||||
self waittill( str2 );
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
Returns which string gets notified first
|
||||
*/
|
||||
waittill_either_return( str1, str2 )
|
||||
{
|
||||
if ( !isDefined( self waittill_either_return_( str1, str2 ) ) )
|
||||
return str1;
|
||||
|
||||
return str2;
|
||||
}
|
||||
|
||||
/*
|
||||
Taken from iw4 script
|
||||
*/
|
||||
waittill_any_timeout( timeOut, string1, string2, string3, string4, string5 )
|
||||
{
|
||||
if ( ( !isdefined( string1 ) || string1 != "death" ) &&
|
||||
( !isdefined( string2 ) || string2 != "death" ) &&
|
||||
( !isdefined( string3 ) || string3 != "death" ) &&
|
||||
( !isdefined( string4 ) || string4 != "death" ) &&
|
||||
( !isdefined( string5 ) || string5 != "death" ) )
|
||||
self endon( "death" );
|
||||
|
||||
ent = spawnstruct();
|
||||
|
||||
if ( isdefined( string1 ) )
|
||||
self thread waittill_string( string1, ent );
|
||||
|
||||
if ( isdefined( string2 ) )
|
||||
self thread waittill_string( string2, ent );
|
||||
|
||||
if ( isdefined( string3 ) )
|
||||
self thread waittill_string( string3, ent );
|
||||
|
||||
if ( isdefined( string4 ) )
|
||||
self thread waittill_string( string4, ent );
|
||||
|
||||
if ( isdefined( string5 ) )
|
||||
self thread waittill_string( string5, ent );
|
||||
|
||||
ent thread _timeout( timeOut );
|
||||
|
||||
ent waittill( "returned", msg );
|
||||
ent notify( "die" );
|
||||
return msg;
|
||||
}
|
||||
|
||||
/*
|
||||
Used for waittill_any_timeout
|
||||
*/
|
||||
_timeout( delay )
|
||||
{
|
||||
self endon( "die" );
|
||||
|
||||
wait( delay );
|
||||
self notify( "returned", "timeout" );
|
||||
}
|
||||
|
||||
/*
|
||||
Gets a player who is host
|
||||
*/
|
||||
GetHostPlayer()
|
||||
{
|
||||
for ( i = 0; i < level.players.size; i++ )
|
||||
{
|
||||
player = level.players[i];
|
||||
|
||||
if ( !player is_host() )
|
||||
continue;
|
||||
|
||||
return player;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/*
|
||||
Waits for a host player
|
||||
*/
|
||||
bot_wait_for_host()
|
||||
{
|
||||
host = undefined;
|
||||
|
||||
while ( !isDefined( level ) || !isDefined( level.players ) )
|
||||
wait 0.05;
|
||||
|
||||
for ( i = getDvarFloat( "bots_main_waitForHostTime" ); i > 0; i -= 0.05 )
|
||||
{
|
||||
host = GetHostPlayer();
|
||||
|
||||
if ( isDefined( host ) )
|
||||
break;
|
||||
|
||||
wait 0.05;
|
||||
}
|
||||
|
||||
if ( !isDefined( host ) )
|
||||
return;
|
||||
|
||||
for ( i = getDvarFloat( "bots_main_waitForHostTime" ); i > 0; i -= 0.05 )
|
||||
{
|
||||
if ( IsDefined( host.pers[ "team" ] ) )
|
||||
break;
|
||||
|
||||
wait 0.05;
|
||||
}
|
||||
|
||||
if ( !IsDefined( host.pers[ "team" ] ) )
|
||||
return;
|
||||
|
||||
for ( i = getDvarFloat( "bots_main_waitForHostTime" ); i > 0; i -= 0.05 )
|
||||
{
|
||||
if ( host.pers[ "team" ] == "allies" || host.pers[ "team" ] == "axis" )
|
||||
break;
|
||||
|
||||
wait 0.05;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Returns the cone dot (like fov, or distance from the center of our screen). 1.0 = directly looking at, 0.0 = completely right angle, -1.0, completely 180
|
||||
*/
|
||||
getConeDot( to, from, dir )
|
||||
{
|
||||
dirToTarget = VectorNormalize( to - from );
|
||||
forward = AnglesToForward( dir );
|
||||
return vectordot( dirToTarget, forward );
|
||||
}
|
||||
|
||||
/*
|
||||
Returns the distance squared in a 2d space
|
||||
*/
|
||||
DistanceSquared2D( to, from )
|
||||
{
|
||||
to = ( to[0], to[1], 0 );
|
||||
from = ( from[0], from[1], 0 );
|
||||
|
||||
return DistanceSquared( to, from );
|
||||
}
|
||||
|
||||
/*
|
||||
Rounds to the nearest whole number.
|
||||
*/
|
||||
Round( x )
|
||||
{
|
||||
y = int( x );
|
||||
|
||||
if ( abs( x ) - abs( y ) > 0.5 )
|
||||
{
|
||||
if ( x < 0 )
|
||||
return y - 1;
|
||||
else
|
||||
return y + 1;
|
||||
}
|
||||
else
|
||||
return y;
|
||||
}
|
||||
|
||||
/*
|
||||
Rounds up the given value.
|
||||
*/
|
||||
RoundUp( floatVal )
|
||||
{
|
||||
i = int( floatVal );
|
||||
|
||||
if ( i != floatVal )
|
||||
return i + 1;
|
||||
else
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
Clamps between value
|
||||
*/
|
||||
Clamp( a, minv, maxv )
|
||||
{
|
||||
return max( min( a, maxv ), minv );
|
||||
}
|
||||
|
||||
/*
|
||||
converts a string into a float
|
||||
*/
|
||||
float( num )
|
||||
{
|
||||
setdvar( "temp_dvar_bot_util", num );
|
||||
|
||||
return GetDvarFloat( "temp_dvar_bot_util" );
|
||||
}
|
||||
|
||||
get_nodes_in_playable_area()
|
||||
{
|
||||
total_nodes = getAllNodes();
|
||||
filtered_nodes = [];
|
||||
|
||||
for ( i = 0; i < total_nodes.size; i++ )
|
||||
{
|
||||
if ( !is_point_in_playable_area( total_nodes[ i ].origin ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
filtered_nodes[ filtered_nodes.size ] = total_nodes[ i ];
|
||||
|
||||
if ( ( i % 10 ) == 0 )
|
||||
{
|
||||
wait 0.05;
|
||||
}
|
||||
}
|
||||
|
||||
return filtered_nodes;
|
||||
}
|
||||
|
||||
is_point_in_playable_area( point )
|
||||
{
|
||||
playable_area = getentarray( "playable_area", "targetname" );
|
||||
|
||||
in_playable_area = false;
|
||||
|
||||
if ( !isDefined( playable_area ) || playable_area.size < 1 )
|
||||
{
|
||||
in_playable_area = true;
|
||||
}
|
||||
|
||||
temp_ent = spawn( "script_origin", point );
|
||||
|
||||
if ( !in_playable_area )
|
||||
{
|
||||
for ( p = 0; p < playable_area.size; p++ )
|
||||
{
|
||||
if ( temp_ent isTouching( playable_area[ p ] ) )
|
||||
{
|
||||
in_playable_area = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
temp_ent delete ();
|
||||
|
||||
return in_playable_area;
|
||||
}
|
||||
|
||||
/*
|
||||
Loads the waypoints. Populating everything needed for the waypoints.
|
||||
*/
|
||||
load_waypoints()
|
||||
{
|
||||
level.waypoints = GetAllNodes();
|
||||
level.waypointCount = level.waypoints.size;
|
||||
|
||||
level.waypointsInPlayableArea = get_nodes_in_playable_area();
|
||||
}
|
||||
|
||||
/*
|
||||
Returns a good amount of players.
|
||||
*/
|
||||
getGoodMapAmount()
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
/*
|
||||
Returns the friendly user name for a given map's codename
|
||||
*/
|
||||
getMapName( map )
|
||||
{
|
||||
return map;
|
||||
}
|
||||
|
||||
/*
|
||||
Returns an array of all the bots in the game.
|
||||
*/
|
||||
getBotArray()
|
||||
{
|
||||
result = [];
|
||||
playercount = level.players.size;
|
||||
|
||||
for ( i = 0; i < playercount; i++ )
|
||||
{
|
||||
player = level.players[i];
|
||||
|
||||
if ( !player is_bot() )
|
||||
continue;
|
||||
|
||||
result[result.size] = player;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
A heap invarient comparitor, used for numbers, numbers with the highest number will be first in the heap.
|
||||
*/
|
||||
Heap( item, item2 )
|
||||
{
|
||||
return item > item2;
|
||||
}
|
||||
|
||||
/*
|
||||
A heap invarient comparitor, used for numbers, numbers with the lowest number will be first in the heap.
|
||||
*/
|
||||
ReverseHeap( item, item2 )
|
||||
{
|
||||
return item < item2;
|
||||
}
|
||||
|
||||
/*
|
||||
A heap invarient comparitor, used for traces. Wanting the trace with the largest length first in the heap.
|
||||
*/
|
||||
HeapTraceFraction( item, item2 )
|
||||
{
|
||||
return item["fraction"] > item2["fraction"];
|
||||
}
|
||||
|
||||
/*
|
||||
Returns a new heap.
|
||||
*/
|
||||
NewHeap( compare )
|
||||
{
|
||||
heap_node = spawnStruct();
|
||||
heap_node.data = [];
|
||||
heap_node.compare = compare;
|
||||
|
||||
return heap_node;
|
||||
}
|
||||
|
||||
/*
|
||||
Inserts the item into the heap. Called on a heap.
|
||||
*/
|
||||
HeapInsert( item )
|
||||
{
|
||||
insert = self.data.size;
|
||||
self.data[insert] = item;
|
||||
|
||||
current = insert + 1;
|
||||
|
||||
while ( current > 1 )
|
||||
{
|
||||
last = current;
|
||||
current = int( current / 2 );
|
||||
|
||||
if ( ![[self.compare]]( item, self.data[current - 1] ) )
|
||||
break;
|
||||
|
||||
self.data[last - 1] = self.data[current - 1];
|
||||
self.data[current - 1] = item;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Helper function to determine what is the next child of the bst.
|
||||
*/
|
||||
_HeapNextChild( node, hsize )
|
||||
{
|
||||
left = node * 2;
|
||||
right = left + 1;
|
||||
|
||||
if ( left > hsize )
|
||||
return -1;
|
||||
|
||||
if ( right > hsize )
|
||||
return left;
|
||||
|
||||
if ( [[self.compare]]( self.data[left - 1], self.data[right - 1] ) )
|
||||
return left;
|
||||
else
|
||||
return right;
|
||||
}
|
||||
|
||||
/*
|
||||
Removes an item from the heap. Called on a heap.
|
||||
*/
|
||||
HeapRemove()
|
||||
{
|
||||
remove = self.data.size;
|
||||
|
||||
if ( !remove )
|
||||
return remove;
|
||||
|
||||
move = self.data[remove - 1];
|
||||
self.data[0] = move;
|
||||
self.data[remove - 1] = undefined;
|
||||
remove--;
|
||||
|
||||
if ( !remove )
|
||||
return remove;
|
||||
|
||||
last = 1;
|
||||
next = self _HeapNextChild( 1, remove );
|
||||
|
||||
while ( next != -1 )
|
||||
{
|
||||
if ( [[self.compare]]( move, self.data[next - 1] ) )
|
||||
break;
|
||||
|
||||
self.data[last - 1] = self.data[next - 1];
|
||||
self.data[next - 1] = move;
|
||||
|
||||
last = next;
|
||||
next = self _HeapNextChild( next, remove );
|
||||
}
|
||||
|
||||
return remove;
|
||||
}
|
||||
|
||||
/*
|
||||
Returns the natural log of x using harmonic series.
|
||||
*/
|
||||
Log( x )
|
||||
{
|
||||
/* if (!isDefined(level.log_cache))
|
||||
level.log_cache = [];
|
||||
|
||||
key = x + "";
|
||||
|
||||
if (isDefined(level.log_cache[key]))
|
||||
return level.log_cache[key];*/
|
||||
|
||||
//thanks Bob__ at stackoverflow
|
||||
old_sum = 0.0;
|
||||
xmlxpl = ( x - 1 ) / ( x + 1 );
|
||||
xmlxpl_2 = xmlxpl * xmlxpl;
|
||||
denom = 1.0;
|
||||
frac = xmlxpl;
|
||||
sum = frac;
|
||||
|
||||
while ( sum != old_sum )
|
||||
{
|
||||
old_sum = sum;
|
||||
denom += 2.0;
|
||||
frac *= xmlxpl_2;
|
||||
sum += frac / denom;
|
||||
}
|
||||
|
||||
answer = 2.0 * sum;
|
||||
|
||||
//level.log_cache[key] = answer;
|
||||
return answer;
|
||||
}
|
||||
|
||||
/*
|
||||
Taken from t5 gsc.
|
||||
Returns an array of number's average.
|
||||
*/
|
||||
array_average( array )
|
||||
{
|
||||
assert( array.size > 0 );
|
||||
total = 0;
|
||||
|
||||
for ( i = 0; i < array.size; i++ )
|
||||
{
|
||||
total += array[i];
|
||||
}
|
||||
|
||||
return ( total / array.size );
|
||||
}
|
||||
|
||||
/*
|
||||
Taken from t5 gsc.
|
||||
Returns an array of number's standard deviation.
|
||||
*/
|
||||
array_std_deviation( array, mean )
|
||||
{
|
||||
assert( array.size > 0 );
|
||||
tmp = [];
|
||||
|
||||
for ( i = 0; i < array.size; i++ )
|
||||
{
|
||||
tmp[i] = ( array[i] - mean ) * ( array[i] - mean );
|
||||
}
|
||||
|
||||
total = 0;
|
||||
|
||||
for ( i = 0; i < tmp.size; i++ )
|
||||
{
|
||||
total = total + tmp[i];
|
||||
}
|
||||
|
||||
return Sqrt( total / array.size );
|
||||
}
|
||||
|
||||
/*
|
||||
Taken from t5 gsc.
|
||||
Will produce a random number between lower_bound and upper_bound but with a bell curve distribution (more likely to be close to the mean).
|
||||
*/
|
||||
random_normal_distribution( mean, std_deviation, lower_bound, upper_bound )
|
||||
{
|
||||
x1 = 0;
|
||||
x2 = 0;
|
||||
w = 1;
|
||||
y1 = 0;
|
||||
|
||||
while ( w >= 1 )
|
||||
{
|
||||
x1 = 2 * RandomFloatRange( 0, 1 ) - 1;
|
||||
x2 = 2 * RandomFloatRange( 0, 1 ) - 1;
|
||||
w = x1 * x1 + x2 * x2;
|
||||
}
|
||||
|
||||
w = Sqrt( ( -2.0 * Log( w ) ) / w );
|
||||
y1 = x1 * w;
|
||||
number = mean + y1 * std_deviation;
|
||||
|
||||
if ( IsDefined( lower_bound ) && number < lower_bound )
|
||||
{
|
||||
number = lower_bound;
|
||||
}
|
||||
|
||||
if ( IsDefined( upper_bound ) && number > upper_bound )
|
||||
{
|
||||
number = upper_bound;
|
||||
}
|
||||
|
||||
return ( number );
|
||||
}
|
||||
|
||||
/*
|
||||
If the player is in laststand
|
||||
*/
|
||||
inLastStand()
|
||||
{
|
||||
return self maps\_laststand::player_is_in_laststand();
|
||||
}
|
||||
|
||||
/*
|
||||
getRandomGoal
|
||||
*/
|
||||
getRandomGoal()
|
||||
{
|
||||
return PickRandom( level.waypointsInPlayableArea ).origin;
|
||||
}
|
Reference in New Issue
Block a user