mirror of
https://github.com/JezuzLizard/t4sp_bot_warfare.git
synced 2025-07-07 11:41:49 +00:00
Compare commits
97 Commits
experiment
...
7acc701c04
Author | SHA1 | Date | |
---|---|---|---|
7acc701c04 | |||
b05344f0d7 | |||
7fb2906d62 | |||
1272026e97 | |||
96e8fb36b6 | |||
73141eddf4 | |||
7a19d85393 | |||
4adaab9841 | |||
772259aa13 | |||
5020458595 | |||
680440946f | |||
484eedd4a2 | |||
6a49312538 | |||
4748f0e8ce | |||
9ac08f9d15 | |||
3aad2db86d | |||
dd1ea5ca07 | |||
18abf5e007 | |||
daeed3e27d | |||
9c663186aa | |||
2492ffc97b | |||
4aba1289f2 | |||
9e2025e86a | |||
271ea76c3e | |||
b85f5af73a | |||
532eb70a47 | |||
7458491ac1 | |||
f95e0ac9fb | |||
95d7947d54 | |||
6737000c72 | |||
0af3e4ca90 | |||
a7a72cb85f | |||
43608a1b67 | |||
a92a5798d6 | |||
9114d20f73 | |||
f342a64ca2 | |||
977dc41f18 | |||
12c74cc6f4 | |||
a91d8a769e | |||
40edab1671 | |||
cc91952f4d | |||
b9bf6e4d7b | |||
93829034d7 | |||
91d1728e41 | |||
8a9aa8fdb4 | |||
50cc792fd4 | |||
68ab7dad3b | |||
120b3edec6 | |||
2d719726dc | |||
b7254c0131 | |||
3f41b61b8f | |||
edb0004fd8 | |||
f035a2badd | |||
e25adccf15 | |||
411a1a047a | |||
2fad2787a0 | |||
84e0677420 | |||
81e65a3adb | |||
65ad154eb6 | |||
1302a40869 | |||
7c9f6fca11 | |||
2f5a21fd8c | |||
3d3c7e7fa4 | |||
aae462fb95 | |||
2bd494c8d7 | |||
01dcaaff95 | |||
f5753789db | |||
280ec4c318 | |||
81094096cb | |||
8343d597c7 | |||
845b377eff | |||
6994631128 | |||
09780b4ea0 | |||
0e68c20fcd | |||
cf77a0237e | |||
07a10e74f3 | |||
b117cdb1fa | |||
5b5133a629 | |||
5a3f920155 | |||
a906e6f34e | |||
5faf834803 | |||
a209af39b8 | |||
b9fe21d15f | |||
1c835bd77b | |||
da170b8f9e | |||
caa27fcfc2 | |||
52ebe9961f | |||
c7558faa47 | |||
dbf6ce6f3e | |||
c730347c25 | |||
e4254b5fcb | |||
9a8df716bb | |||
aea546f469 | |||
87f57db2dc | |||
19d7be701a | |||
111e81efa1 | |||
c0b19f00c7 |
27
.astylerc
Normal file
27
.astylerc
Normal file
@ -0,0 +1,27 @@
|
||||
# try to mimic the original gsc provided
|
||||
# mode=ghc
|
||||
mode=c
|
||||
style=allman
|
||||
|
||||
indent=force-tab=2
|
||||
lineend=windows
|
||||
|
||||
pad-oper
|
||||
pad-paren-in
|
||||
pad-header
|
||||
# pad-brackets-in
|
||||
fill-empty-lines
|
||||
squeeze-lines=2
|
||||
squeeze-ws
|
||||
break-one-line-headers
|
||||
add-braces
|
||||
remove-comment-prefix
|
||||
|
||||
break-blocks
|
||||
|
||||
indent-switches
|
||||
indent-cases
|
||||
indent-after-parens
|
||||
indent-col1-comments
|
||||
|
||||
remove-comment-prefix
|
11
.editorconfig
Normal file
11
.editorconfig
Normal file
@ -0,0 +1,11 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = tab
|
||||
indent_size = 2
|
||||
charset = latin1
|
||||
trim_trailing_whitespace = false
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
21
.github/workflows/main.yml
vendored
Normal file
21
.github/workflows/main.yml
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
name: main
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
main-win:
|
||||
name: Test on Windows
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- name: Check out files
|
||||
uses: actions/checkout@main
|
||||
|
||||
- name: Setup gsc-tool
|
||||
uses: xensik/setup-gsc-tool@v1
|
||||
with:
|
||||
version: '1.4.0'
|
||||
|
||||
- name: Compile test script
|
||||
run: |
|
||||
gsc-tool.exe -m parse -g iw5 -s pc .
|
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
*.log
|
||||
missingasset.csv
|
||||
console.log*
|
15
.vscode/settings.json
vendored
Normal file
15
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"astyle.astylerc": "${workspaceRoot}/.astylerc",
|
||||
"astyle.additional_languages": [
|
||||
"gsc"
|
||||
],
|
||||
"[gsc]": {
|
||||
"editor.defaultFormatter": "chiehyu.vscode-astyle",
|
||||
},
|
||||
"editor.quickSuggestions": {
|
||||
"other": true,
|
||||
"comments": true,
|
||||
"strings": true
|
||||
},
|
||||
"vscode-codscript.use_builtin_completionItems": false
|
||||
}
|
21
README.md
21
README.md
@ -1,5 +1,20 @@
|
||||
# T4ZM-Zombie-Bots
|
||||
Bots for T4ZM.
|
||||
# T4SP-Bots
|
||||
Bots for T4SP.
|
||||
|
||||
Coby basted code from https://github.com/ineedbots/t4m_bot_warfare
|
||||
## TODO:
|
||||
- Bots need to open doors
|
||||
- Bots need to turn on power
|
||||
- Bots need better decisions for buying weapons
|
||||
- Add following a player around
|
||||
- Add boarding up windows
|
||||
- Activate traps
|
||||
- Pack a punch
|
||||
- Do pack a punch quest
|
||||
- Do EEs
|
||||
- Use teleporters
|
||||
- Use zipline
|
||||
- Bot menu
|
||||
- Bot chat (needs sayall)
|
||||
|
||||
Coby basted code from https://github.com/ineedbots/t4_bot_warfare
|
||||
Credit to ineedbots for his bot warfare mods for various games.
|
||||
|
641
maps/bots/_bot.gsc
Normal file
641
maps/bots/_bot.gsc
Normal file
@ -0,0 +1,641 @@
|
||||
#include common_scripts\utility;
|
||||
#include maps\_utility;
|
||||
#include maps\bots\_bot_utility;
|
||||
|
||||
/*
|
||||
Initiates the whole bot scripts.
|
||||
*/
|
||||
init()
|
||||
{
|
||||
level.bw_version = "2.2.0 PR 1";
|
||||
|
||||
if ( getdvar( "bots_main" ) == "" )
|
||||
{
|
||||
setdvar( "bots_main", true );
|
||||
}
|
||||
|
||||
if ( !getdvarint( "bots_main" ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !wait_for_builtins() )
|
||||
{
|
||||
println( "FATAL: NO BUILT-INS FOR BOTS" );
|
||||
}
|
||||
|
||||
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", false ); // 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 ( getdvar( "bots_t8_mode" ) == "" )
|
||||
{
|
||||
setdvar( "bots_t8_mode", false );
|
||||
}
|
||||
|
||||
if ( getdvar( "bots_play_opendoors" ) == "" )
|
||||
{
|
||||
setdvar( "bots_play_opendoors", true );
|
||||
}
|
||||
|
||||
if ( !isdefined( game[ "botWarfare" ] ) )
|
||||
{
|
||||
game[ "botWarfare" ] = true;
|
||||
game[ "botWarfareInitTime" ] = gettime();
|
||||
}
|
||||
|
||||
level.bot_inittime = gettime();
|
||||
|
||||
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 = 128;
|
||||
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();
|
||||
level thread onPlayerChat();
|
||||
|
||||
level thread maps\bots\_bot_script::bot_script_init();
|
||||
}
|
||||
|
||||
/*
|
||||
Starts the threads for bots.
|
||||
*/
|
||||
handleBots()
|
||||
{
|
||||
level thread diffBots();
|
||||
level addBots();
|
||||
|
||||
while ( !isdefined( level.intermission ) || !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++ )
|
||||
{
|
||||
BotBuiltinCmdExec( "clientkick " + bots[ i ] getentitynumber() );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
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() && getdvarint( "bots_t8_mode" ) )
|
||||
{
|
||||
if ( ( level.script == "nazi_zombie_asylum" || level.script == "nazi_zombie_sumpf" ) && self hasperk( "specialty_armorvest" ) )
|
||||
{
|
||||
iDamage = int( iDamage * 0.333 );
|
||||
}
|
||||
else
|
||||
{
|
||||
iDamage = int( iDamage * 0.1 );
|
||||
}
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
onActorDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, iModelIndex, iTimeOffset )
|
||||
{
|
||||
if ( isdefined( eAttacker ) && isplayer( eAttacker ) && eAttacker is_bot() && getdvarint( "bots_t8_mode" ) && ( !isdefined( self.magic_bullet_shield ) || !self.magic_bullet_shield ) )
|
||||
{
|
||||
iDamage += int( self.maxhealth * randomfloatrange( 0.25, 1.25 ) );
|
||||
}
|
||||
|
||||
self [[ level.prevcallbackactordamage ]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, iModelIndex, iTimeOffset );
|
||||
}
|
||||
|
||||
/*
|
||||
Starts the callbacks.
|
||||
*/
|
||||
hook_callbacks()
|
||||
{
|
||||
wait 0.05;
|
||||
level.prevcallbackplayerdamage = level.callbackplayerdamage;
|
||||
level.callbackplayerdamage = ::onPlayerDamage;
|
||||
|
||||
level.prevcallbackactordamage = level.callbackactordamage;
|
||||
level.callbackactordamage = ::onActorDamage;
|
||||
}
|
||||
|
||||
/*
|
||||
Thread when any player connects. Starts the threads needed.
|
||||
*/
|
||||
onPlayerConnect()
|
||||
{
|
||||
for ( ;; )
|
||||
{
|
||||
level waittill( "connected", player );
|
||||
|
||||
player thread connected();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
When a bot disconnects.
|
||||
*/
|
||||
onDisconnectAll()
|
||||
{
|
||||
name = self.playername;
|
||||
|
||||
self waittill( "disconnect" );
|
||||
|
||||
level.players = array_remove( level.players, self );
|
||||
|
||||
waittillframeend;
|
||||
|
||||
for ( i = 0; i < level.bots.size; i++ )
|
||||
{
|
||||
bot = level.bots[ i ];
|
||||
bot BotNotifyBotEvent( "connection", "disconnected", self, name );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
When any client spawns
|
||||
*/
|
||||
onSpawnedAll()
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
self waittill( "spawned_player" );
|
||||
|
||||
self.lastspawntime = gettime();
|
||||
|
||||
if ( getdvarint( "bots_main_debug" ) )
|
||||
{
|
||||
self.score = 100000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
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;
|
||||
|
||||
for ( i = 0; i < level.bots.size; i++ )
|
||||
{
|
||||
bot = level.bots[ i ];
|
||||
bot BotNotifyBotEvent( "connection", "connected", self, self.playername );
|
||||
}
|
||||
|
||||
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 ( getdvarint( "bots_main_debug" ) >= 2 )
|
||||
{
|
||||
big_str = "Bot Warfare debug: " + self.playername + ": " + msg;
|
||||
|
||||
if ( isdefined( str ) && isstring( str ) )
|
||||
{
|
||||
big_str += ", " + str;
|
||||
}
|
||||
|
||||
if ( isdefined( b ) && isstring( b ) )
|
||||
{
|
||||
big_str += ", " + b;
|
||||
}
|
||||
|
||||
if ( isdefined( c ) && isstring( c ) )
|
||||
{
|
||||
big_str += ", " + c;
|
||||
}
|
||||
|
||||
if ( isdefined( d ) && isstring( d ) )
|
||||
{
|
||||
big_str += ", " + d;
|
||||
}
|
||||
|
||||
if ( isdefined( e ) && isstring( e ) )
|
||||
{
|
||||
big_str += ", " + e;
|
||||
}
|
||||
|
||||
if ( isdefined( f ) && isstring( f ) )
|
||||
{
|
||||
big_str += ", " + f;
|
||||
}
|
||||
|
||||
if ( isdefined( g ) && isstring( g ) )
|
||||
{
|
||||
big_str += ", " + g;
|
||||
}
|
||||
|
||||
BotBuiltinPrintConsole( big_str );
|
||||
}
|
||||
else if ( msg == "debug" && getdvarint( "bots_main_debug" ) )
|
||||
{
|
||||
BotBuiltinPrintConsole( "Bot Warfare debug: " + self.playername + ": " + str );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
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 = BotBuiltinAddTestClient();
|
||||
|
||||
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 = getBotToKick();
|
||||
|
||||
if ( isdefined( tempBot ) )
|
||||
{
|
||||
BotBuiltinCmdExec( "clientkick " + tempBot getentitynumber() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
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();
|
||||
|
||||
while ( !isdefined( level.intermission ) || !level.intermission )
|
||||
{
|
||||
wait 1.5;
|
||||
|
||||
addBots_loop();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
When a player chats
|
||||
*/
|
||||
onPlayerChat()
|
||||
{
|
||||
for ( ;; )
|
||||
{
|
||||
level waittill( "say", message, player, is_hidden );
|
||||
|
||||
for ( i = 0; i < level.bots.size; i++ )
|
||||
{
|
||||
bot = level.bots[ i ];
|
||||
|
||||
bot BotNotifyBotEvent( "chat", "chat", message, player, is_hidden );
|
||||
}
|
||||
}
|
||||
}
|
303
maps/bots/_bot_debug.gsc
Normal file
303
maps/bots/_bot_debug.gsc
Normal file
@ -0,0 +1,303 @@
|
||||
/*
|
||||
_bot_debug
|
||||
Author: INeedGames
|
||||
Date: 07/09/2023
|
||||
The ingame waypoint visualizer. Designed to be ran on the client (not the server)
|
||||
*/
|
||||
|
||||
#include maps\_utility;
|
||||
#include common_scripts\utility;
|
||||
#include maps\_hud_util;
|
||||
#include maps\bots\_bot_utility;
|
||||
|
||||
init()
|
||||
{
|
||||
if ( getdvar( "bots_main_debug" ) == "" )
|
||||
{
|
||||
setdvar( "bots_main_debug", 0 );
|
||||
}
|
||||
|
||||
if ( !getdvarint( "bots_main_debug" ) || !getdvarint( "bots_main_debug_wp_vis" ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !getdvarint( "developer" ) )
|
||||
{
|
||||
setdvar( "developer_script", 1 );
|
||||
setdvar( "developer", 2 );
|
||||
|
||||
setdvar( "sv_mapRotation", "map " + getdvar( "mapname" ) );
|
||||
exitlevel( false );
|
||||
return;
|
||||
}
|
||||
|
||||
setdvar( "bots_main", false );
|
||||
setdvar( "bots_main_menu", false );
|
||||
setdvar( "bots_manage_fill_mode", 0 );
|
||||
setdvar( "bots_manage_fill", 0 );
|
||||
setdvar( "bots_manage_add", 0 );
|
||||
setdvar( "bots_manage_fill_kick", true );
|
||||
setdvar( "bots_manage_fill_spec", true );
|
||||
|
||||
if ( getdvar( "bots_main_debug_distance" ) == "" )
|
||||
{
|
||||
setdvar( "bots_main_debug_distance", 512.0 );
|
||||
}
|
||||
|
||||
if ( getdvar( "bots_main_debug_cone" ) == "" )
|
||||
{
|
||||
setdvar( "bots_main_debug_cone", 0.65 );
|
||||
}
|
||||
|
||||
if ( getdvar( "bots_main_debug_minDist" ) == "" )
|
||||
{
|
||||
setdvar( "bots_main_debug_minDist", 32.0 );
|
||||
}
|
||||
|
||||
if ( getdvar( "bots_main_debug_drawThrough" ) == "" )
|
||||
{
|
||||
setdvar( "bots_main_debug_drawThrough", false );
|
||||
}
|
||||
|
||||
thread load_waypoints();
|
||||
|
||||
level waittill( "connected", player );
|
||||
player thread onPlayerSpawned();
|
||||
}
|
||||
|
||||
onPlayerSpawned()
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
self waittill( "spawned_player" );
|
||||
self thread beginDebug();
|
||||
}
|
||||
}
|
||||
|
||||
beginDebug()
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
self endon( "zombified" );
|
||||
|
||||
self thread debug();
|
||||
self thread watch_for_unlink();
|
||||
self thread textScroll( "^1xDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD" );
|
||||
}
|
||||
|
||||
watch_for_unlink()
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
self endon( "zombified" );
|
||||
|
||||
self BotBuiltinNotifyOnPlayerCommand( "+smoke", "toggle_unlink" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
self waittill( "toggle_unlink" );
|
||||
|
||||
if ( self.closest == -1 )
|
||||
{
|
||||
self iprintln( "not close to node" );
|
||||
continue;
|
||||
}
|
||||
|
||||
firstwp = level.waypoints[ self.closest ];
|
||||
|
||||
self iprintln( "wp selected for unlink: " + firstwp BotBuiltinGetNodeNumber() );
|
||||
|
||||
self waittill( "toggle_unlink" );
|
||||
|
||||
if ( self.closest == -1 )
|
||||
{
|
||||
self iprintln( "not close to node" );
|
||||
continue;
|
||||
}
|
||||
|
||||
self toggle_link( firstwp, level.waypoints[ self.closest ] );
|
||||
}
|
||||
}
|
||||
|
||||
array_contains( arr, it )
|
||||
{
|
||||
for ( i = 0; i < arr.size; i++ )
|
||||
{
|
||||
if ( arr[ i ] == it )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
toggle_link( firstwp, secondwp )
|
||||
{
|
||||
// check if it exists
|
||||
key = firstwp BotBuiltinGetNodeNumber() + "";
|
||||
secnum = secondwp BotBuiltinGetNodeNumber();
|
||||
|
||||
links = firstwp BotBuiltinGetLinkedNodes();
|
||||
linked = false;
|
||||
|
||||
for ( i = 0; i < links.size; i++ )
|
||||
{
|
||||
if ( links[ i ] BotBuiltinGetNodeNumber() == secnum )
|
||||
{
|
||||
linked = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !linked )
|
||||
{
|
||||
self iprintln( "no link: " + key + " " + secnum );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( key == secnum + "" )
|
||||
{
|
||||
self iprintln( "same unlink: " + key + " " + secnum );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( isdefined( level.bot_ignore_links[ key ] ) && array_contains( level.bot_ignore_links[ key ], secnum ) )
|
||||
{
|
||||
a = level.bot_ignore_links[ key ];
|
||||
|
||||
a = array_remove( a, secnum );
|
||||
|
||||
if ( a.size <= 0 )
|
||||
{
|
||||
level.bot_ignore_links[ key ] = undefined;
|
||||
}
|
||||
else
|
||||
{
|
||||
level.bot_ignore_links[ key ] = a;
|
||||
}
|
||||
|
||||
self iprintln( "removed unlink: " + key + " " + secnum );
|
||||
BotBuiltinPrintConsole( "toggle_link: add: " + key + " " + secnum );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !isdefined( level.bot_ignore_links[ key ] ) )
|
||||
{
|
||||
level.bot_ignore_links[ key ] = [];
|
||||
}
|
||||
|
||||
a = level.bot_ignore_links[ key ];
|
||||
a[ a.size ] = secnum;
|
||||
|
||||
level.bot_ignore_links[ key ] = a;
|
||||
|
||||
self iprintln( "added unlink: " + key + " " + secnum );
|
||||
BotBuiltinPrintConsole( "toggle_link: del: " + key + " " + secnum );
|
||||
}
|
||||
}
|
||||
|
||||
debug()
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
self endon( "zombified" );
|
||||
|
||||
self.closest = -1;
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
wait 0.05;
|
||||
|
||||
closest = -1;
|
||||
myEye = self gettagorigin( "j_head" );
|
||||
myAngles = self getplayerangles();
|
||||
|
||||
for ( i = level.waypoints.size - 1; i >= 0; i-- )
|
||||
{
|
||||
if ( closest == -1 || closer( self.origin, level.waypoints[ i ].origin, level.waypoints[ closest ].origin ) )
|
||||
{
|
||||
closest = i;
|
||||
}
|
||||
|
||||
wpOrg = level.waypoints[ i ].origin + ( 0, 0, 25 );
|
||||
|
||||
if ( distance( level.waypoints[ i ].origin, self.origin ) < getdvarfloat( "bots_main_debug_distance" ) && ( sighttracepassed( myEye, wpOrg, false, self ) || getdvarint( "bots_main_debug_drawThrough" ) ) && getConeDot( wpOrg, myEye, myAngles ) > getdvarfloat( "bots_main_debug_cone" ) )
|
||||
{
|
||||
linked = level.waypoints[ i ] BotBuiltinGetLinkedNodes();
|
||||
node_num_str = level.waypoints[ i ] BotBuiltinGetNodeNumber() + "";
|
||||
|
||||
for ( h = linked.size - 1; h >= 0; h-- )
|
||||
{
|
||||
if ( isdefined( level.bot_ignore_links[ node_num_str ] ) )
|
||||
{
|
||||
found = false;
|
||||
this_node_num = linked[ h ] BotBuiltinGetNodeNumber();
|
||||
|
||||
for ( j = 0; j < level.bot_ignore_links[ node_num_str ].size; j++ )
|
||||
{
|
||||
if ( level.bot_ignore_links[ node_num_str ][ j ] == this_node_num )
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( found )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
line( wpOrg, linked[ h ].origin + ( 0, 0, 25 ), ( 1, 0, 1 ) );
|
||||
}
|
||||
|
||||
print3d( wpOrg, node_num_str, ( 1, 0, 0 ), 2 );
|
||||
|
||||
if ( isdefined( level.waypoints[ i ].animscript ) )
|
||||
{
|
||||
line( wpOrg, wpOrg + anglestoforward( level.waypoints[ i ].angles ) * 64, ( 1, 1, 1 ) );
|
||||
print3d( wpOrg + ( 0, 0, 15 ), level.waypoints[ i ].animscript, ( 1, 0, 0 ), 2 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( distance( self.origin, level.waypoints[ closest ].origin ) < 64 )
|
||||
{
|
||||
self.closest = closest;
|
||||
}
|
||||
else
|
||||
{
|
||||
self.closest = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
destroyOnDeath( hud )
|
||||
{
|
||||
hud endon( "death" );
|
||||
self waittill_either( "zombified", "disconnect" );
|
||||
hud destroy();
|
||||
}
|
||||
|
||||
textScroll( string )
|
||||
{
|
||||
self endon( "zombified" );
|
||||
self endon( "disconnect" );
|
||||
// thanks ActionScript
|
||||
|
||||
back = createbar( ( 0, 0, 0 ), 1000, 30 );
|
||||
back setpoint( "CENTER", undefined, 0, 220 );
|
||||
self thread destroyOnDeath( back );
|
||||
|
||||
text = createfontstring( "default", 1.5 );
|
||||
text settext( string );
|
||||
self thread destroyOnDeath( text );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
text setpoint( "CENTER", undefined, 1200, 220 );
|
||||
text setpoint( "CENTER", undefined, -1200, 220, 20 );
|
||||
wait 20;
|
||||
}
|
||||
}
|
2494
maps/bots/_bot_internal.gsc
Normal file
2494
maps/bots/_bot_internal.gsc
Normal file
File diff suppressed because it is too large
Load Diff
534
maps/bots/_bot_script.gsc
Normal file
534
maps/bots/_bot_script.gsc
Normal file
@ -0,0 +1,534 @@
|
||||
#include common_scripts\utility;
|
||||
#include maps\_utility;
|
||||
#include maps\bots\_bot_utility;
|
||||
|
||||
/*
|
||||
Initialize bot script level functions
|
||||
*/
|
||||
bot_script_init()
|
||||
{
|
||||
level thread maps\bots\objectives\_manager::init();
|
||||
}
|
||||
|
||||
/*
|
||||
When the bot gets added into the game.
|
||||
*/
|
||||
added()
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
|
||||
self set_diff();
|
||||
}
|
||||
|
||||
/*
|
||||
When the bot connects to the game.
|
||||
*/
|
||||
connected()
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
|
||||
self thread difficulty();
|
||||
self thread onBotSpawned();
|
||||
self thread onSpawned();
|
||||
|
||||
self thread maps\bots\objectives\_manager::connected();
|
||||
}
|
||||
|
||||
/*
|
||||
The callback for when the bot gets damaged.
|
||||
*/
|
||||
onDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, modelIndex, psOffsetTime )
|
||||
{
|
||||
if ( !isdefined( self ) || !isdefined( self.team ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !isalive( self ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( sMeansOfDeath == "MOD_FALLING" || sMeansOfDeath == "MOD_SUICIDE" )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( iDamage <= 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !isdefined( eAttacker ) || !isdefined( eAttacker.team ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( eAttacker == self )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !isalive( eAttacker ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
self SetAttacker( eAttacker );
|
||||
}
|
||||
|
||||
/*
|
||||
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" ][ "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" ][ "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" ][ "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" ][ "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" ][ "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" ][ "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" ][ "jump" ] = 90;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
wait 5;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Sets the bot difficulty.
|
||||
*/
|
||||
set_diff()
|
||||
{
|
||||
rankVar = getdvarint( "bots_skill" );
|
||||
|
||||
switch ( rankVar )
|
||||
{
|
||||
case 0:
|
||||
self.pers[ "bots" ][ "skill" ][ "base" ] = Round( random_normal_distribution( 3.5, 1.75, 1, 7 ) );
|
||||
break;
|
||||
|
||||
case 8:
|
||||
break;
|
||||
|
||||
case 9:
|
||||
self.pers[ "bots" ][ "skill" ][ "base" ] = randomintrange( 1, 7 );
|
||||
self.pers[ "bots" ][ "skill" ][ "aim_time" ] = 0.05 * randomintrange( 1, 20 );
|
||||
self.pers[ "bots" ][ "skill" ][ "init_react_time" ] = 50 * randomint( 100 );
|
||||
self.pers[ "bots" ][ "skill" ][ "reaction_time" ] = 50 * randomint( 100 );
|
||||
self.pers[ "bots" ][ "skill" ][ "no_trace_ads_time" ] = 50 * randomint( 100 );
|
||||
self.pers[ "bots" ][ "skill" ][ "no_trace_look_time" ] = 50 * randomint( 100 );
|
||||
self.pers[ "bots" ][ "skill" ][ "remember_time" ] = 50 * randomint( 100 );
|
||||
self.pers[ "bots" ][ "skill" ][ "fov" ] = randomfloatrange( -1, 1 );
|
||||
|
||||
randomNum = randomintrange( 500, 25000 );
|
||||
self.pers[ "bots" ][ "skill" ][ "dist_start" ] = randomNum;
|
||||
self.pers[ "bots" ][ "skill" ][ "dist_max" ] = randomNum * 2;
|
||||
|
||||
self.pers[ "bots" ][ "skill" ][ "spawn_time" ] = 0.05 * randomint( 20 );
|
||||
self.pers[ "bots" ][ "skill" ][ "help_dist" ] = randomintrange( 500, 25000 );
|
||||
self.pers[ "bots" ][ "skill" ][ "semi_time" ] = randomfloatrange( 0.05, 1 );
|
||||
self.pers[ "bots" ][ "skill" ][ "shoot_after_time" ] = randomfloatrange( 0.05, 1 );
|
||||
self.pers[ "bots" ][ "skill" ][ "aim_offset_time" ] = randomfloatrange( 0.05, 1 );
|
||||
self.pers[ "bots" ][ "skill" ][ "aim_offset_amount" ] = randomfloatrange( 0.05, 1 );
|
||||
self.pers[ "bots" ][ "skill" ][ "bone_update_interval" ] = randomfloatrange( 0.05, 1 );
|
||||
self.pers[ "bots" ][ "skill" ][ "bones" ] = "j_head,j_spineupper,j_ankle_ri,j_ankle_le";
|
||||
|
||||
self.pers[ "bots" ][ "behavior" ][ "strafe" ] = randomint( 100 );
|
||||
self.pers[ "bots" ][ "behavior" ][ "nade" ] = randomint( 100 );
|
||||
self.pers[ "bots" ][ "behavior" ][ "sprint" ] = randomint( 100 );
|
||||
self.pers[ "bots" ][ "behavior" ][ "camp" ] = randomint( 100 );
|
||||
self.pers[ "bots" ][ "behavior" ][ "follow" ] = randomint( 100 );
|
||||
self.pers[ "bots" ][ "behavior" ][ "crouch" ] = randomint( 100 );
|
||||
self.pers[ "bots" ][ "behavior" ][ "switch" ] = randomint( 100 );
|
||||
self.pers[ "bots" ][ "behavior" ][ "jump" ] = randomint( 100 );
|
||||
break;
|
||||
|
||||
default:
|
||||
self.pers[ "bots" ][ "skill" ][ "base" ] = rankVar;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
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 thread maps\bots\objectives\_manager::spawned();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Starts all the bot thinking
|
||||
*/
|
||||
start_bot_threads()
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
level endon( "intermission" );
|
||||
self endon( "zombified" );
|
||||
|
||||
self thread doReloadCancel();
|
||||
|
||||
self thread maps\bots\objectives\_manager::start_bot_threads();
|
||||
}
|
||||
|
||||
/*
|
||||
Changes to the weap
|
||||
*/
|
||||
changeToWeapon( weap )
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
self endon( "zombified" );
|
||||
level endon( "game_ended" );
|
||||
|
||||
if ( !self hasweapon( weap ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
self switchtoweapon( 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_any_return( "reload", "weapon_change" );
|
||||
|
||||
if ( self BotIsFrozen() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( self usebuttonpressed() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( self inLastStand() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
curWeap = self getcurrentweapon();
|
||||
|
||||
if ( !self isWeaponPrimary( curWeap ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ret == "reload" )
|
||||
{
|
||||
// check single reloads
|
||||
if ( self getweaponammoclip( 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 ( !self isWeaponPrimary( weapon ) )
|
||||
{
|
||||
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( "zombified" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
self doReloadCancel_loop();
|
||||
}
|
||||
}
|
1794
maps/bots/_bot_utility.gsc
Normal file
1794
maps/bots/_bot_utility.gsc
Normal file
File diff suppressed because it is too large
Load Diff
168
maps/bots/objectives/_manager.gsc
Normal file
168
maps/bots/objectives/_manager.gsc
Normal file
@ -0,0 +1,168 @@
|
||||
#include common_scripts\utility;
|
||||
#include maps\_utility;
|
||||
#include maps\bots\_bot_utility;
|
||||
#include maps\bots\objectives\_utility;
|
||||
|
||||
init()
|
||||
{
|
||||
level.bot_objectives = [];
|
||||
level.bot_objectives[ level.bot_objectives.size ] = CreateObjectiveForManger( "revive", maps\bots\objectives\_revive::Finder, maps\bots\objectives\_revive::Priority, maps\bots\objectives\_revive::Executer, 1000 );
|
||||
level.bot_objectives[ level.bot_objectives.size ] = CreateObjectiveForManger( "powerup", maps\bots\objectives\_powerup::Finder, maps\bots\objectives\_powerup::Priority, maps\bots\objectives\_powerup::Executer, 2500 );
|
||||
level.bot_objectives[ level.bot_objectives.size ] = CreateObjectiveForManger( "wallweapon", maps\bots\objectives\_wallweapon::Finder, maps\bots\objectives\_wallweapon::Priority, maps\bots\objectives\_wallweapon::Executer, 7500 );
|
||||
level.bot_objectives[ level.bot_objectives.size ] = CreateObjectiveForManger( "treasurechest", maps\bots\objectives\_treasurechest::Finder, maps\bots\objectives\_treasurechest::Priority, maps\bots\objectives\_treasurechest::Executer, 7000 );
|
||||
maps\bots\objectives\_perkmachine::init();
|
||||
level.bot_objectives[ level.bot_objectives.size ] = CreateObjectiveForManger( "perkmachine", maps\bots\objectives\_perkmachine::Finder, maps\bots\objectives\_perkmachine::Priority, maps\bots\objectives\_perkmachine::Executer, 10000 );
|
||||
}
|
||||
|
||||
connected()
|
||||
{
|
||||
self.bot_current_objective = undefined;
|
||||
}
|
||||
|
||||
spawned()
|
||||
{
|
||||
self.bot_current_objective = undefined;
|
||||
|
||||
self thread clean_objective_on_completion();
|
||||
self thread watch_for_objective_canceled();
|
||||
}
|
||||
|
||||
watch_for_objective_canceled()
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
level endon( "intermission" );
|
||||
self endon( "zombified" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
self waittill( "cancel_bot_objective", reason );
|
||||
|
||||
obj_name = "undefined";
|
||||
|
||||
if ( isdefined( self.bot_current_objective ) )
|
||||
{
|
||||
obj_name = self.bot_current_objective.sname;
|
||||
}
|
||||
|
||||
self BotNotifyBotEvent( "debug", "watch_for_objective_canceled: " + obj_name + ": " + reason );
|
||||
}
|
||||
}
|
||||
|
||||
clean_objective_on_completion()
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
level endon( "intermission" );
|
||||
self endon( "zombified" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
self waittill( "completed_bot_objective", successful, reason );
|
||||
|
||||
obj_name = "undefined";
|
||||
|
||||
if ( isdefined( self.bot_current_objective ) )
|
||||
{
|
||||
obj_name = self.bot_current_objective.sname;
|
||||
|
||||
self.bot_current_objective.eparentobj.abotprocesstimes[ self getentitynumber() + "" ] = gettime();
|
||||
}
|
||||
|
||||
self BotNotifyBotEvent( "debug", "clean_objective_on_completion: " + obj_name + ": " + successful + ": " + reason );
|
||||
|
||||
waittillframeend;
|
||||
self.bot_current_objective = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
start_bot_threads()
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
level endon( "intermission" );
|
||||
self endon( "zombified" );
|
||||
|
||||
self thread bot_objective_think();
|
||||
}
|
||||
|
||||
bot_objective_think()
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
level endon( "intermission" );
|
||||
self endon( "zombified" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
wait 1;
|
||||
|
||||
// find all avail objectives
|
||||
objectives = [];
|
||||
now = gettime();
|
||||
our_key = self getentitynumber() + "";
|
||||
|
||||
for ( i = 0; i < level.bot_objectives.size; i++ )
|
||||
{
|
||||
objective = level.bot_objectives[ i ];
|
||||
|
||||
// check the process rate
|
||||
if ( isdefined( objective.abotprocesstimes[ our_key ] ) && now - objective.abotprocesstimes[ our_key ] < objective.iprocessrate )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
objectives = array_merge( objectives, self [[ objective.fpfinder ]]( objective ) );
|
||||
objective.abotprocesstimes[ our_key ] = now;
|
||||
}
|
||||
|
||||
if ( objectives.size <= 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// sort according to priority
|
||||
heap = NewHeap( ::HeapPriority );
|
||||
|
||||
for ( i = 0; i < objectives.size; i++ )
|
||||
{
|
||||
if ( objectives[ i ].fpriority <= -100 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
heap HeapInsert( objectives[ i ] );
|
||||
}
|
||||
|
||||
// pop the top!
|
||||
best_prio = heap.data[ 0 ];
|
||||
|
||||
if ( !isdefined( best_prio ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// already on a better obj
|
||||
if ( isdefined( self.bot_current_objective ) && ( best_prio.guid == self.bot_current_objective.guid || best_prio.fpriority < self [[ self.bot_current_objective.eparentobj.fppriorty ]]( self.bot_current_objective.eparentobj, self.bot_current_objective.eent ) ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// DO THE OBJ
|
||||
// cancel the old obj
|
||||
if ( isdefined( self.bot_current_objective ) )
|
||||
{
|
||||
// cancel it
|
||||
self CancelObjective( "new obj: " + best_prio.sname );
|
||||
|
||||
// wait for it to clean up
|
||||
self waittill( "completed_bot_objective" );
|
||||
|
||||
// redo the loop, should do the obj next iteration
|
||||
best_prio.eparentobj.abotprocesstimes[ our_key ] = undefined;
|
||||
continue;
|
||||
}
|
||||
|
||||
// ready to execute
|
||||
self BotNotifyBotEvent( "debug", "bot_objective_think: " + best_prio.sname );
|
||||
|
||||
self.bot_current_objective = best_prio;
|
||||
self thread [[ best_prio.eparentobj.fpexecuter ]]( best_prio );
|
||||
}
|
||||
}
|
287
maps/bots/objectives/_perkmachine.gsc
Normal file
287
maps/bots/objectives/_perkmachine.gsc
Normal file
@ -0,0 +1,287 @@
|
||||
#include common_scripts\utility;
|
||||
#include maps\_utility;
|
||||
#include maps\bots\_bot_utility;
|
||||
#include maps\bots\objectives\_utility;
|
||||
|
||||
init()
|
||||
{
|
||||
vending_triggers = getentarray( "zombie_vending", "targetname" );
|
||||
|
||||
if ( !isdefined( vending_triggers ) || vending_triggers.size < 1 )
|
||||
{
|
||||
vending_triggers = getentarray( "harrybo21_perk_trigger", "targetname" );
|
||||
|
||||
if ( !isdefined( vending_triggers ) || vending_triggers.size < 1 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for ( i = 0 ; i < vending_triggers.size; i++ )
|
||||
{
|
||||
vending_triggers[ i ] thread init_vending_trigger();
|
||||
}
|
||||
}
|
||||
|
||||
init_vending_trigger()
|
||||
{
|
||||
self endon( "death" );
|
||||
|
||||
if ( self.targetname == "harrybo21_perk_trigger" )
|
||||
{
|
||||
machine = self getMachine();
|
||||
|
||||
machine waittill( "activate_machine" );
|
||||
|
||||
self.bot_powered_on = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
perk = self getVendingPerk();
|
||||
notify_name = perk + "_power_on";
|
||||
|
||||
level waittill( notify_name );
|
||||
|
||||
self.bot_powered_on = true;
|
||||
}
|
||||
}
|
||||
|
||||
Finder( eObj )
|
||||
{
|
||||
answer = [];
|
||||
|
||||
if ( self inLastStand() )
|
||||
{
|
||||
return answer;
|
||||
}
|
||||
|
||||
vending_triggers = getentarray( "zombie_vending", "targetname" );
|
||||
|
||||
if ( !isdefined( vending_triggers ) || vending_triggers.size < 1 )
|
||||
{
|
||||
vending_triggers = getentarray( "harrybo21_perk_trigger", "targetname" );
|
||||
|
||||
if ( !isdefined( vending_triggers ) || vending_triggers.size < 1 )
|
||||
{
|
||||
return answer;
|
||||
}
|
||||
}
|
||||
|
||||
for ( i = 0 ; i < vending_triggers.size; i++ )
|
||||
{
|
||||
vending = vending_triggers[ i ];
|
||||
|
||||
if ( !isdefined( vending.bot_powered_on ) || !vending.bot_powered_on )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
perk = vending getVendingPerk();
|
||||
cost = vending getPerkCost();
|
||||
|
||||
if ( self.score < cost )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// perk limit??
|
||||
if ( self hasperk( perk ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
machine = vending getMachine();
|
||||
|
||||
if ( !isdefined( machine ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
org = self getOffset( machine );
|
||||
|
||||
if ( GetPathIsInaccessible( self.origin, org ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
answer[ answer.size ] = self CreateFinderObjectiveEZ( eObj, vending );
|
||||
}
|
||||
|
||||
return answer;
|
||||
}
|
||||
|
||||
getMachine()
|
||||
{
|
||||
return getent( self.target, "targetname" );
|
||||
}
|
||||
|
||||
getVendingPerk()
|
||||
{
|
||||
if ( self.targetname == "harrybo21_perk_trigger" )
|
||||
{
|
||||
machine = self getMachine();
|
||||
return machine.script_string;
|
||||
}
|
||||
|
||||
return self.script_noteworthy;
|
||||
}
|
||||
|
||||
getPerkCost()
|
||||
{
|
||||
if ( self.targetname == "harrybo21_perk_trigger" )
|
||||
{
|
||||
return level.zombie_perks[ self getVendingPerk() ].perk_cost;
|
||||
}
|
||||
|
||||
cost = level.zombie_vars[ "zombie_perk_cost" ];
|
||||
|
||||
switch ( self getVendingPerk() )
|
||||
{
|
||||
case "specialty_armorvest":
|
||||
cost = 2500;
|
||||
break;
|
||||
|
||||
case "specialty_quickrevive":
|
||||
cost = 1500;
|
||||
break;
|
||||
|
||||
case "specialty_fastreload":
|
||||
cost = 3000;
|
||||
break;
|
||||
|
||||
case "specialty_rof":
|
||||
cost = 2000;
|
||||
break;
|
||||
|
||||
default:
|
||||
cost = 10000;
|
||||
break;
|
||||
}
|
||||
|
||||
return cost;
|
||||
}
|
||||
|
||||
getOffset( model )
|
||||
{
|
||||
org = model get_angle_offset_node( 40, ( 0, -90, 0 ), ( 0, 0, 1 ) );
|
||||
|
||||
return org;
|
||||
}
|
||||
|
||||
Priority( eObj, eEnt )
|
||||
{
|
||||
// TODO rank perks
|
||||
base_priority = 2;
|
||||
base_priority += ClampLerp( get_path_dist( self.origin, eEnt.origin ), 500, 1600, 3, 0 );
|
||||
|
||||
if ( self HasBotObjective() && self GetBotObjectiveEnt() != eEnt )
|
||||
{
|
||||
base_priority -= 1;
|
||||
}
|
||||
|
||||
return base_priority;
|
||||
}
|
||||
|
||||
Executer( eObj )
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
self endon( "zombified" );
|
||||
|
||||
vending = eObj.eent;
|
||||
|
||||
self thread WatchForCancel( vending );
|
||||
|
||||
self GoDoPerkMachine( eObj );
|
||||
|
||||
self WatchForCancelCleanup();
|
||||
self ClearScriptAimPos();
|
||||
self ClearScriptGoal();
|
||||
|
||||
self CompletedObjective( eObj.bwassuccessful, eObj.sreason );
|
||||
}
|
||||
|
||||
WatchForCancelCleanup()
|
||||
{
|
||||
self notify( "WatchForCancelPerkmachine" );
|
||||
}
|
||||
|
||||
WatchForCancel( vending )
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
self endon( "zombified" );
|
||||
self endon( "WatchForCancelPerkmachine" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
wait 0.05;
|
||||
|
||||
if ( self inLastStand() )
|
||||
{
|
||||
self CancelObjective( "self inLastStand()" );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WatchToGoToMachine( vending )
|
||||
{
|
||||
self endon( "cancel_bot_objective" );
|
||||
self endon( "disconnect" );
|
||||
self endon( "zombified" );
|
||||
self endon( "goal" );
|
||||
self endon( "bad_path" );
|
||||
self endon( "new_goal" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
wait 0.05;
|
||||
|
||||
if ( self istouching( vending ) || vending PointInsideUseTrigger( self.origin ) )
|
||||
{
|
||||
self notify( "goal" );
|
||||
break; // is this needed?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GoDoPerkMachine( eObj )
|
||||
{
|
||||
self endon( "cancel_bot_objective" );
|
||||
|
||||
vending = eObj.eent;
|
||||
machine = vending getMachine();
|
||||
perk = vending getVendingPerk();
|
||||
org = self getOffset( machine );
|
||||
|
||||
// go to machine
|
||||
self thread WatchToGoToMachine( vending );
|
||||
self SetScriptGoal( org, 32 );
|
||||
|
||||
result = self waittill_any_return( "goal", "bad_path", "new_goal" );
|
||||
|
||||
if ( result != "goal" )
|
||||
{
|
||||
eObj.sreason = "didn't go to machine";
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !self istouching( vending ) && !vending PointInsideUseTrigger( self.origin ) )
|
||||
{
|
||||
eObj.sreason = "not touching machine";
|
||||
return;
|
||||
}
|
||||
|
||||
// ok we are touching machine, lets look at it
|
||||
self SetScriptAimPos( vending.origin );
|
||||
|
||||
// wait to look at it
|
||||
wait 1;
|
||||
|
||||
// press use
|
||||
self thread BotPressUse( 0.15 );
|
||||
wait 0.1;
|
||||
|
||||
// ok we pressed use, DONE
|
||||
eObj.sreason = "completed " + perk;
|
||||
eObj.bwassuccessful = true;
|
||||
}
|
142
maps/bots/objectives/_powerup.gsc
Normal file
142
maps/bots/objectives/_powerup.gsc
Normal file
@ -0,0 +1,142 @@
|
||||
#include common_scripts\utility;
|
||||
#include maps\_utility;
|
||||
#include maps\bots\_bot_utility;
|
||||
#include maps\bots\objectives\_utility;
|
||||
|
||||
Finder( eObj )
|
||||
{
|
||||
answer = [];
|
||||
|
||||
if ( self inLastStand() )
|
||||
{
|
||||
return answer;
|
||||
}
|
||||
|
||||
ents = getentarray( "script_model", "classname" );
|
||||
|
||||
for ( i = 0; i < ents.size; i++ )
|
||||
{
|
||||
// not a powerup script_model
|
||||
if ( !isdefined( ents[ i ].powerup_name ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// can we path to it?
|
||||
if ( GetPathIsInaccessible( self.origin, ents[ i ].origin ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// make sure we are the only one going for it
|
||||
if ( self GetBotsAmountForEntity( ents[ i ] ) >= 1 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
answer[ answer.size ] = self CreateFinderObjectiveEZ( eObj, ents[ i ] );
|
||||
}
|
||||
|
||||
return answer;
|
||||
}
|
||||
|
||||
Priority( eObj, eEnt )
|
||||
{
|
||||
// TODO: check powerup type
|
||||
base_priority = 0;
|
||||
base_priority += ClampLerp( get_path_dist( self.origin, eEnt.origin ), 300, 700, 2, -2 );
|
||||
|
||||
if ( self HasBotObjective() && self GetBotObjectiveEnt() != eEnt )
|
||||
{
|
||||
base_priority -= 1;
|
||||
}
|
||||
|
||||
return base_priority;
|
||||
}
|
||||
|
||||
Executer( eObj )
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
self endon( "zombified" );
|
||||
|
||||
powerup = eObj.eent;
|
||||
org = powerup.origin;
|
||||
|
||||
self thread IncrementBotsForEntity( powerup );
|
||||
self thread WatchForCancel( powerup );
|
||||
|
||||
self GoDoPowerup( eObj );
|
||||
|
||||
self WatchForCancelCleanup();
|
||||
self DecrementBotsForEntity( powerup );
|
||||
self ClearScriptGoal();
|
||||
|
||||
if ( distance( org, self.origin ) <= 64 )
|
||||
{
|
||||
eObj.sreason = "completed";
|
||||
eObj.bwassuccessful = true;
|
||||
}
|
||||
|
||||
self CompletedObjective( eObj.bwassuccessful, eObj.sreason );
|
||||
}
|
||||
|
||||
WatchForCancelCleanup()
|
||||
{
|
||||
self notify( "WatchForCancelPowerup" );
|
||||
}
|
||||
|
||||
WatchForCancel( powerup )
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
self endon( "zombified" );
|
||||
self endon( "WatchForCancelPowerup" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
wait 0.05;
|
||||
|
||||
if ( self inLastStand() )
|
||||
{
|
||||
self CancelObjective( "self inLastStand()" );
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !isdefined( powerup ) )
|
||||
{
|
||||
self CancelObjective( "!isdefined( powerup )" );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GoDoPowerup( eObj )
|
||||
{
|
||||
self endon( "cancel_bot_objective" );
|
||||
|
||||
powerup = eObj.eent;
|
||||
|
||||
// go to it
|
||||
self SetScriptGoal( powerup.origin, 32 );
|
||||
|
||||
result = self waittill_any_return( "goal", "bad_path", "new_goal" );
|
||||
|
||||
if ( result != "goal" )
|
||||
{
|
||||
eObj.sreason = "didn't go to powerup";
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !isdefined( powerup ) || !isdefined( powerup.origin ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( distance( powerup.origin, self.origin ) > 64 )
|
||||
{
|
||||
eObj.sreason = "not touching it";
|
||||
return;
|
||||
}
|
||||
|
||||
eObj.sreason = "completed";
|
||||
eObj.bwassuccessful = true;
|
||||
}
|
209
maps/bots/objectives/_revive.gsc
Normal file
209
maps/bots/objectives/_revive.gsc
Normal file
@ -0,0 +1,209 @@
|
||||
#include common_scripts\utility;
|
||||
#include maps\_utility;
|
||||
#include maps\bots\_bot_utility;
|
||||
#include maps\bots\objectives\_utility;
|
||||
|
||||
Finder( eObj )
|
||||
{
|
||||
Players = get_players();
|
||||
Answer = [];
|
||||
|
||||
if ( self inLastStand() )
|
||||
{
|
||||
return Answer;
|
||||
}
|
||||
|
||||
for ( i = 0; i < Players.size; i++ )
|
||||
{
|
||||
Player = Players[ i ];
|
||||
|
||||
if ( !isdefined( Player ) || !isdefined( Player.team ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( Player == self )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( Player.sessionstate != "playing" )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( !Player inLastStand() || Player.revivetrigger.beingrevived )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( GetPathIsInaccessible( self.origin, Player.origin ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( self GetBotsAmountForEntity( Player ) >= 1 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Answer[ Answer.size ] = self CreateFinderObjectiveEZ( eObj, Player );
|
||||
}
|
||||
|
||||
return Answer;
|
||||
}
|
||||
|
||||
Priority( eObj, eEnt )
|
||||
{
|
||||
base_priority = 3;
|
||||
base_priority += ClampLerp( get_path_dist( self.origin, eEnt.origin ), 500, 1200, 2, 0 );
|
||||
|
||||
if ( self HasBotObjective() && self GetBotObjectiveEnt() != eEnt )
|
||||
{
|
||||
base_priority -= 1;
|
||||
}
|
||||
|
||||
return base_priority;
|
||||
}
|
||||
|
||||
Executer( eObj )
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
self endon( "zombified" );
|
||||
|
||||
revivee = eObj.eent;
|
||||
|
||||
self thread IncrementBotsForEntity( revivee );
|
||||
self thread WatchForCancelRevive( revivee );
|
||||
|
||||
self GoDoRevive( eObj );
|
||||
|
||||
self WatchForCancelReviveCleanup();
|
||||
self DecrementBotsForEntity( revivee );
|
||||
self ClearScriptAimPos();
|
||||
self ClearScriptGoal();
|
||||
self ClearPriorityObjective();
|
||||
|
||||
self CompletedObjective( eObj.bwassuccessful, eObj.sreason );
|
||||
}
|
||||
|
||||
WatchForCancelReviveCleanup()
|
||||
{
|
||||
self notify( "WatchForCancelRevive" );
|
||||
}
|
||||
|
||||
WatchForCancelRevive( revivee )
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
self endon( "zombified" );
|
||||
self endon( "WatchForCancelRevive" );
|
||||
|
||||
org = revivee.origin;
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
wait 0.05;
|
||||
|
||||
if ( self inLastStand() )
|
||||
{
|
||||
self CancelObjective( "self inLastStand()" );
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !isdefined( revivee ) || !revivee inLastStand() )
|
||||
{
|
||||
self CancelObjective( "!isdefined( revivee ) || !revivee inLastStand()" );
|
||||
break;
|
||||
}
|
||||
|
||||
if ( revivee.revivetrigger.beingrevived && !self isReviving( revivee ) )
|
||||
{
|
||||
self CancelObjective( "revivee.revivetrigger.beingrevived && !self isReviving( revivee )" );
|
||||
break;
|
||||
}
|
||||
|
||||
if ( distance( revivee.origin, org ) > 16 )
|
||||
{
|
||||
self CancelObjective( "distance( revivee.origin, org ) > 16" );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WatchToGoToGuy( revivee )
|
||||
{
|
||||
self endon( "cancel_bot_objective" );
|
||||
self endon( "disconnect" );
|
||||
self endon( "zombified" );
|
||||
self endon( "goal" );
|
||||
self endon( "bad_path" );
|
||||
self endon( "new_goal" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
wait 1;
|
||||
|
||||
if ( self istouching( revivee.revivetrigger ) )
|
||||
{
|
||||
self notify( "goal" );
|
||||
break; // is this needed?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WatchForSuccessRevive( eObj )
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
self endon( "zombified" );
|
||||
|
||||
revivee = eObj.eent;
|
||||
|
||||
ret = self waittill_either_return( "cancel_bot_objective", "completed_bot_objective" );
|
||||
|
||||
if ( ret == "cancel_bot_objective" && isdefined( revivee ) && !revivee inLastStand() )
|
||||
{
|
||||
eObj.bwassuccessful = true;
|
||||
eObj.sreason = "revived him!";
|
||||
}
|
||||
}
|
||||
|
||||
GoDoRevive( eObj )
|
||||
{
|
||||
self endon( "cancel_bot_objective" );
|
||||
|
||||
revivee = eObj.eent;
|
||||
|
||||
// go to guy
|
||||
self thread WatchToGoToGuy( revivee );
|
||||
self SetPriorityObjective();
|
||||
self SetScriptGoal( revivee.origin, 32 );
|
||||
|
||||
result = self waittill_any_return( "goal", "bad_path", "new_goal" );
|
||||
|
||||
if ( result != "goal" )
|
||||
{
|
||||
eObj.sreason = "didn't go to guy";
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !self istouching( revivee.revivetrigger ) )
|
||||
{
|
||||
eObj.sreason = "not touching guy";
|
||||
return;
|
||||
}
|
||||
|
||||
// ok we are touching guy, lets look at him
|
||||
self SetScriptAimPos( revivee.origin );
|
||||
|
||||
// now lets hold use until he is up or otherwise
|
||||
self thread WatchForSuccessRevive( eObj );
|
||||
|
||||
while ( self istouching( revivee.revivetrigger ) )
|
||||
{
|
||||
self thread BotPressUse( 0.15 );
|
||||
|
||||
wait 0.1;
|
||||
}
|
||||
|
||||
eObj.sreason = "not touching guy";
|
||||
}
|
284
maps/bots/objectives/_treasurechest.gsc
Normal file
284
maps/bots/objectives/_treasurechest.gsc
Normal file
@ -0,0 +1,284 @@
|
||||
#include common_scripts\utility;
|
||||
#include maps\_utility;
|
||||
#include maps\bots\_bot_utility;
|
||||
#include maps\bots\objectives\_utility;
|
||||
|
||||
Finder( eObj )
|
||||
{
|
||||
answer = [];
|
||||
|
||||
if ( self inLastStand() )
|
||||
{
|
||||
return answer;
|
||||
}
|
||||
|
||||
weapons = self getweaponslist();
|
||||
|
||||
// TODO check if need a new weapon, rate weapons too is better then current etc
|
||||
chests = level.chests;
|
||||
|
||||
if ( !isdefined( chests ) )
|
||||
{
|
||||
chests = getentarray( "treasure_chest_use", "targetname" );
|
||||
}
|
||||
|
||||
if ( !isdefined( chests ) || chests.size <= 0 )
|
||||
{
|
||||
return answer;
|
||||
}
|
||||
|
||||
for ( i = 0; i < chests.size; i ++ )
|
||||
{
|
||||
chest = chests[ i ];
|
||||
|
||||
// not active chest
|
||||
if ( isdefined( chest.disabled ) && chest.disabled )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// box is waiting for someone to grab weapon
|
||||
if ( isdefined( chest.grab_weapon_hint ) && chest.grab_weapon_hint )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
cost = 950;
|
||||
|
||||
if ( isdefined( level.zombie_treasure_chest_cost ) )
|
||||
{
|
||||
cost = level.zombie_treasure_chest_cost;
|
||||
}
|
||||
else if ( isdefined( chest.zombie_cost ) )
|
||||
{
|
||||
cost = chest.zombie_cost;
|
||||
}
|
||||
|
||||
// check cost
|
||||
if ( self.score < cost )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
lid = getent( chest.target, "targetname" );
|
||||
|
||||
if ( !isdefined( lid ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
weapon_spawn_org = getent( lid.target, "targetname" );
|
||||
|
||||
if ( !isdefined( weapon_spawn_org ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
org = self getOffset( lid );
|
||||
|
||||
if ( GetPathIsInaccessible( self.origin, org ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
answer[ answer.size ] = self CreateFinderObjectiveEZ( eObj, chest );
|
||||
}
|
||||
|
||||
return answer;
|
||||
}
|
||||
|
||||
getOffset( model )
|
||||
{
|
||||
org = model get_angle_offset_node( 52, ( 0, 90, 0 ), ( 0, 0, 1 ) );
|
||||
|
||||
return org;
|
||||
}
|
||||
|
||||
Priority( eObj, eEnt )
|
||||
{
|
||||
base_priority = 1;
|
||||
base_priority += ClampLerp( get_path_dist( self.origin, eEnt.origin ), 600, 1800, 2, 0 );
|
||||
|
||||
if ( self HasBotObjective() && self GetBotObjectiveEnt() != eEnt )
|
||||
{
|
||||
base_priority -= 1;
|
||||
}
|
||||
|
||||
return base_priority;
|
||||
}
|
||||
|
||||
Executer( eObj )
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
self endon( "zombified" );
|
||||
|
||||
chest = eObj.eent;
|
||||
|
||||
self thread WatchForCancel( chest );
|
||||
|
||||
self GoDoTreasureChest( eObj );
|
||||
|
||||
self WatchForCancelCleanup();
|
||||
self ClearScriptAimPos();
|
||||
self ClearScriptGoal();
|
||||
self ClearPriorityObjective();
|
||||
|
||||
self CompletedObjective( eObj.bwassuccessful, eObj.sreason );
|
||||
}
|
||||
|
||||
WatchForCancelCleanup()
|
||||
{
|
||||
self notify( "WatchForCancelTreasurechest" );
|
||||
}
|
||||
|
||||
WatchForCancel( chest )
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
self endon( "zombified" );
|
||||
self endon( "WatchForCancelTreasurechest" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
wait 0.05;
|
||||
|
||||
if ( self inLastStand() )
|
||||
{
|
||||
self CancelObjective( "self inLastStand()" );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WatchToGoToChest( chest )
|
||||
{
|
||||
self endon( "cancel_bot_objective" );
|
||||
self endon( "disconnect" );
|
||||
self endon( "zombified" );
|
||||
self endon( "goal" );
|
||||
self endon( "bad_path" );
|
||||
self endon( "new_goal" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
wait 0.05;
|
||||
|
||||
if ( self istouching( chest ) || chest PointInsideUseTrigger( self.origin ) )
|
||||
{
|
||||
self notify( "goal" );
|
||||
break; // is this needed?
|
||||
}
|
||||
|
||||
if ( isdefined( chest.disabled ) && chest.disabled )
|
||||
{
|
||||
self notify( "bad_path" );
|
||||
break; // is this needed?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GoDoTreasureChest( eObj )
|
||||
{
|
||||
self endon( "cancel_bot_objective" );
|
||||
|
||||
chest = eObj.eent;
|
||||
lid = getent( chest.target, "targetname" );
|
||||
weapon_spawn_org = getent( lid.target, "targetname" );
|
||||
org = self getOffset( lid );
|
||||
|
||||
weap = self getcurrentweapon();
|
||||
|
||||
if ( weap == "none" || !self getammocount( weap ) )
|
||||
{
|
||||
self SetPriorityObjective();
|
||||
}
|
||||
|
||||
// go to box
|
||||
self thread WatchToGoToChest( chest );
|
||||
self SetScriptGoal( org, 32 );
|
||||
|
||||
result = self waittill_any_return( "goal", "bad_path", "new_goal" );
|
||||
|
||||
if ( result != "goal" )
|
||||
{
|
||||
eObj.sreason = "didn't go to chest";
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !self istouching( chest ) && !chest PointInsideUseTrigger( self.origin ) )
|
||||
{
|
||||
eObj.sreason = "not touching chest";
|
||||
return;
|
||||
}
|
||||
|
||||
// ok we are touching weapon, lets look at it
|
||||
self SetScriptAimPos( chest.origin );
|
||||
|
||||
// wait to look at it
|
||||
wait 1;
|
||||
|
||||
// press use
|
||||
self thread BotPressUse( 0.15 );
|
||||
wait 0.25;
|
||||
|
||||
// ok we pressed use, wait for randomization to complete
|
||||
self ClearScriptAimPos();
|
||||
self ClearPriorityObjective();
|
||||
|
||||
// randomization isnt happening...
|
||||
if ( !isdefined( chest.disabled ) || !chest.disabled )
|
||||
{
|
||||
eObj.sreason = "chest isnt randomizing";
|
||||
return;
|
||||
}
|
||||
|
||||
ret = weapon_spawn_org waittill_any_timeout( 5, "randomization_done" );
|
||||
|
||||
if ( ret == "timeout" )
|
||||
{
|
||||
eObj.sreason = "randomization_done timed out";
|
||||
return;
|
||||
}
|
||||
|
||||
if ( isdefined( level.flag[ "moving_chest_now" ] ) && flag( "moving_chest_now" ) )
|
||||
{
|
||||
eObj.sreason = "chest is moving!";
|
||||
return;
|
||||
}
|
||||
|
||||
waittillframeend;
|
||||
weap = weapon_spawn_org.weapon_string;
|
||||
// weapon is done cooking, grabit!
|
||||
self SetPriorityObjective();
|
||||
|
||||
// go to box
|
||||
self thread WatchToGoToChest( chest );
|
||||
self SetScriptGoal( org, 32 );
|
||||
|
||||
result = self waittill_any_return( "goal", "bad_path", "new_goal" );
|
||||
|
||||
if ( result != "goal" )
|
||||
{
|
||||
eObj.sreason = "didn't go to chest";
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !self istouching( chest ) && !chest PointInsideUseTrigger( self.origin ) )
|
||||
{
|
||||
eObj.sreason = "not touching chest";
|
||||
return;
|
||||
}
|
||||
|
||||
// ok we are touching weapon, lets look at it
|
||||
self SetScriptAimPos( chest.origin );
|
||||
|
||||
// wait to look at it
|
||||
wait 1;
|
||||
|
||||
// press use
|
||||
self thread BotPressUse( 0.15 );
|
||||
wait 0.1;
|
||||
|
||||
// complete!
|
||||
eObj.sreason = "completed " + weap;
|
||||
eObj.bwassuccessful = true;
|
||||
}
|
114
maps/bots/objectives/_utility.gsc
Normal file
114
maps/bots/objectives/_utility.gsc
Normal file
@ -0,0 +1,114 @@
|
||||
#include common_scripts\utility;
|
||||
#include maps\_utility;
|
||||
#include maps\bots\_bot_utility;
|
||||
|
||||
CreateObjectiveForManger( sName, fpFinder, fpPriorty, fpExecuter, iProcessRate )
|
||||
{
|
||||
Answer = spawnstruct();
|
||||
|
||||
Answer.sname = sName;
|
||||
Answer.fpfinder = fpFinder;
|
||||
Answer.fpexecuter = fpExecuter;
|
||||
Answer.fppriorty = fpPriorty;
|
||||
|
||||
Answer.abotprocesstimes = [];
|
||||
Answer.iprocessrate = iProcessRate;
|
||||
|
||||
return Answer;
|
||||
}
|
||||
|
||||
CreateFinderObjectiveEZ( eObj, eEnt )
|
||||
{
|
||||
return self CreateFinderObjective( eObj, eObj.sname + "_" + eEnt getentitynumber(), eEnt, self [[ eObj.fppriorty ]]( eObj, eEnt ) );
|
||||
}
|
||||
|
||||
CreateFinderObjective( eObj, sName, eEnt, fPriority )
|
||||
{
|
||||
Answer = spawnstruct();
|
||||
|
||||
Answer.eparentobj = eObj;
|
||||
Answer.sname = sName;
|
||||
Answer.eent = eEnt;
|
||||
Answer.fpriority = fPriority;
|
||||
Answer.guid = eEnt getentitynumber();
|
||||
|
||||
Answer.bwassuccessful = false;
|
||||
Answer.sreason = "canceled";
|
||||
|
||||
return Answer;
|
||||
}
|
||||
|
||||
GetBotsAmountForEntity( eEnt )
|
||||
{
|
||||
if ( !isdefined( eEnt.bots ) )
|
||||
{
|
||||
eEnt.bots = 0;
|
||||
}
|
||||
|
||||
return eEnt.bots;
|
||||
}
|
||||
|
||||
IncrementBotsForEntity( eEnt )
|
||||
{
|
||||
self endon( "bots_for_entity_cleanup" );
|
||||
|
||||
eEnt.bots++;
|
||||
|
||||
self waittill_either( "disconnect", "zombified" );
|
||||
|
||||
if ( isdefined( eEnt ) )
|
||||
{
|
||||
eEnt.bots--;
|
||||
}
|
||||
}
|
||||
|
||||
DecrementBotsForEntity( eEnt )
|
||||
{
|
||||
self notify( "bots_for_entity_cleanup" );
|
||||
|
||||
if ( isdefined( eEnt ) )
|
||||
{
|
||||
eEnt.bots--;
|
||||
}
|
||||
}
|
||||
|
||||
CleanupBotsForEntity( eEnt )
|
||||
{
|
||||
self notify( "bots_for_entity_cleanup" );
|
||||
}
|
||||
|
||||
CancelObjective( reason )
|
||||
{
|
||||
self notify( "cancel_bot_objective", reason );
|
||||
}
|
||||
|
||||
CompletedObjective( successful, reason )
|
||||
{
|
||||
self notify( "completed_bot_objective", successful, reason );
|
||||
}
|
||||
|
||||
GetBotObjectiveEnt()
|
||||
{
|
||||
if ( !self HasBotObjective() )
|
||||
{
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return self GetBotObjective().eent;
|
||||
}
|
||||
|
||||
/*
|
||||
Gets bot objective
|
||||
*/
|
||||
GetBotObjective()
|
||||
{
|
||||
return self.bot_current_objective;
|
||||
}
|
||||
|
||||
/*
|
||||
Does the bot have an objective?
|
||||
*/
|
||||
HasBotObjective()
|
||||
{
|
||||
return isdefined( self GetBotObjective() );
|
||||
}
|
237
maps/bots/objectives/_wallweapon.gsc
Normal file
237
maps/bots/objectives/_wallweapon.gsc
Normal file
@ -0,0 +1,237 @@
|
||||
#include common_scripts\utility;
|
||||
#include maps\_utility;
|
||||
#include maps\bots\_bot_utility;
|
||||
#include maps\bots\objectives\_utility;
|
||||
|
||||
Finder( eObj )
|
||||
{
|
||||
answer = [];
|
||||
|
||||
if ( self inLastStand() )
|
||||
{
|
||||
return answer;
|
||||
}
|
||||
|
||||
weapon_spawns = getentarray( "weapon_upgrade", "targetname" );
|
||||
|
||||
if ( !isdefined( weapon_spawns ) || weapon_spawns.size <= 0 )
|
||||
{
|
||||
return answer;
|
||||
}
|
||||
|
||||
weapons = self getweaponslist();
|
||||
|
||||
// TODO check if need a new weapon, rate weapons too is better then current etc
|
||||
|
||||
for ( i = 0; i < weapon_spawns.size; i++ )
|
||||
{
|
||||
player_has_weapon = false;
|
||||
|
||||
if ( !isdefined( weapon_spawns[ i ].zombie_weapon_upgrade ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for ( h = 0; h < weapons.size; h++ )
|
||||
{
|
||||
if ( weapons[ h ] == weapon_spawns[ i ].zombie_weapon_upgrade )
|
||||
{
|
||||
player_has_weapon = true;
|
||||
}
|
||||
}
|
||||
|
||||
is_grenade = ( weapontype( weapon_spawns[ i ].zombie_weapon_upgrade ) == "grenade" );
|
||||
|
||||
if ( !player_has_weapon || is_grenade )
|
||||
{
|
||||
func = BotBuiltinGetFunction( "maps/_zombiemode_weapons", "get_weapon_cost" );
|
||||
|
||||
if ( self.score < [[ func ]]( weapon_spawns[ i ].zombie_weapon_upgrade ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
func = BotBuiltinGetFunction( "maps/_zombiemode_weapons", "get_ammo_cost" );
|
||||
|
||||
if ( self.score < [[ func ]]( weapon_spawns[ i ].zombie_weapon_upgrade ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
model = weapon_spawns[ i ];
|
||||
|
||||
if ( isdefined( weapon_spawns[ i ].target ) )
|
||||
{
|
||||
model = getent( weapon_spawns[ i ].target, "targetname" );
|
||||
}
|
||||
|
||||
if ( !isdefined( model ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
org = self getOffset( model, weapon_spawns[ i ] );
|
||||
|
||||
if ( GetPathIsInaccessible( self.origin, org ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
answer[ answer.size ] = self CreateFinderObjectiveEZ( eObj, weapon_spawns[ i ] );
|
||||
}
|
||||
|
||||
return answer;
|
||||
}
|
||||
|
||||
getOffset( model, weapon )
|
||||
{
|
||||
org = model get_angle_offset_node( 40, ( 0, -90, 0 ), ( 0, 0, 1 ) );
|
||||
|
||||
test_org = ( org[ 0 ], org[ 1 ], weapon.origin[ 2 ] );
|
||||
|
||||
if ( !weapon PointInsideUseTrigger( test_org ) )
|
||||
{
|
||||
org = model get_angle_offset_node( 40, ( 0, 90, 0 ), ( 0, 0, 1 ) );
|
||||
}
|
||||
|
||||
return org;
|
||||
}
|
||||
|
||||
Priority( eObj, eEnt )
|
||||
{
|
||||
// TODO: check weallweapon type
|
||||
|
||||
base_priority = 0;
|
||||
base_priority += ClampLerp( get_path_dist( self.origin, eEnt.origin ), 0, 800, 1, -2 );
|
||||
|
||||
if ( self HasBotObjective() && self GetBotObjectiveEnt() != eEnt )
|
||||
{
|
||||
base_priority -= 1;
|
||||
}
|
||||
|
||||
if ( issubstr( eEnt.zombie_weapon_upgrade, "kar98k" ) || issubstr( eEnt.zombie_weapon_upgrade, "type99" ) )
|
||||
{
|
||||
base_priority -= 999;
|
||||
}
|
||||
|
||||
return base_priority;
|
||||
}
|
||||
|
||||
Executer( eObj )
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
self endon( "zombified" );
|
||||
|
||||
weapon = eObj.eent;
|
||||
|
||||
self thread WatchForCancel( weapon );
|
||||
|
||||
self GoDoWallweapon( eObj );
|
||||
|
||||
self WatchForCancelCleanup();
|
||||
self ClearScriptAimPos();
|
||||
self ClearScriptGoal();
|
||||
self ClearPriorityObjective();
|
||||
|
||||
self CompletedObjective( eObj.bwassuccessful, eObj.sreason );
|
||||
}
|
||||
|
||||
WatchForCancelCleanup()
|
||||
{
|
||||
self notify( "WatchForCancelWallweapon" );
|
||||
}
|
||||
|
||||
WatchForCancel( weapon )
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
self endon( "zombified" );
|
||||
self endon( "WatchForCancelWallweapon" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
wait 0.05;
|
||||
|
||||
if ( self inLastStand() )
|
||||
{
|
||||
self CancelObjective( "self inLastStand()" );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WatchToGoToWeapon( weapon )
|
||||
{
|
||||
self endon( "cancel_bot_objective" );
|
||||
self endon( "disconnect" );
|
||||
self endon( "zombified" );
|
||||
self endon( "goal" );
|
||||
self endon( "bad_path" );
|
||||
self endon( "new_goal" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
wait 0.05;
|
||||
|
||||
if ( self istouching( weapon ) || weapon PointInsideUseTrigger( self.origin ) )
|
||||
{
|
||||
self notify( "goal" );
|
||||
break; // is this needed?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GoDoWallweapon( eObj )
|
||||
{
|
||||
self endon( "cancel_bot_objective" );
|
||||
|
||||
weapon = eObj.eent;
|
||||
model = weapon;
|
||||
|
||||
if ( isdefined( weapon.target ) )
|
||||
{
|
||||
model = getent( weapon.target, "targetname" );
|
||||
}
|
||||
|
||||
org = self getOffset( model, weapon );
|
||||
|
||||
weap = self getcurrentweapon();
|
||||
|
||||
if ( weap == "none" || !self getammocount( weap ) )
|
||||
{
|
||||
self SetPriorityObjective();
|
||||
}
|
||||
|
||||
// go to weapon
|
||||
self thread WatchToGoToWeapon( weapon );
|
||||
self SetScriptGoal( org, 32 );
|
||||
|
||||
result = self waittill_any_return( "goal", "bad_path", "new_goal" );
|
||||
|
||||
if ( result != "goal" )
|
||||
{
|
||||
eObj.sreason = "didn't go to weapon";
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !self istouching( weapon ) && !weapon PointInsideUseTrigger( self.origin ) )
|
||||
{
|
||||
eObj.sreason = "not touching weapon";
|
||||
return;
|
||||
}
|
||||
|
||||
// ok we are touching weapon, lets look at it
|
||||
self SetScriptAimPos( weapon.origin );
|
||||
|
||||
// wait to look at it
|
||||
wait 1;
|
||||
|
||||
// press use
|
||||
self thread BotPressUse( 0.15 );
|
||||
wait 0.1;
|
||||
|
||||
eObj.sreason = "completed";
|
||||
eObj.bwassuccessful = true;
|
||||
}
|
@ -1,423 +0,0 @@
|
||||
#include common_scripts\utility;
|
||||
#include maps\_utility;
|
||||
#include scripts\sp\bots\_bot_utility;
|
||||
|
||||
/*
|
||||
Initiates the whole bot scripts.
|
||||
*/
|
||||
init()
|
||||
{
|
||||
level.bw_VERSION = "2.1.0";
|
||||
|
||||
if ( getDvar( "bots_main" ) == "" )
|
||||
setDvar( "bots_main", true );
|
||||
|
||||
if ( !getDvarInt( "bots_main" ) )
|
||||
return;
|
||||
|
||||
//thread load_waypoints(); //Don't call for now
|
||||
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 scripts\sp\bots\_bot_internal::onDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, iModelIndex, timeOffset );
|
||||
self scripts\sp\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 scripts\sp\bots\_bot_internal::connected();
|
||||
self thread scripts\sp\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 scripts\sp\bots\_bot_internal::added();
|
||||
//self thread scripts\sp\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();
|
||||
}
|
||||
}
|
4
scripts/sp/bots.gsc
Normal file
4
scripts/sp/bots.gsc
Normal file
@ -0,0 +1,4 @@
|
||||
init()
|
||||
{
|
||||
level thread maps\bots\_bot::init();
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
117
scripts/sp/bots_adapter_pt4.gsc
Normal file
117
scripts/sp/bots_adapter_pt4.gsc
Normal file
@ -0,0 +1,117 @@
|
||||
init()
|
||||
{
|
||||
level.bot_builtins[ "printconsole" ] = ::do_printconsole;
|
||||
level.bot_builtins[ "botaction" ] = ::do_botaction;
|
||||
level.bot_builtins[ "botstop" ] = ::do_botstop;
|
||||
level.bot_builtins[ "botmovement" ] = ::do_botmovement;
|
||||
level.bot_builtins[ "botmeleeparams" ] = ::do_botmeleeparams;
|
||||
level.bot_builtins[ "isbot" ] = ::do_isbot;
|
||||
level.bot_builtins[ "generatepath" ] = ::do_generatepath;
|
||||
level.bot_builtins[ "getfunction" ] = ::do_getfunction;
|
||||
level.bot_builtins[ "getmins" ] = ::do_getmins;
|
||||
level.bot_builtins[ "getmaxs" ] = ::do_getmaxs;
|
||||
level.bot_builtins[ "getguid" ] = ::do_getguid;
|
||||
level.bot_builtins[ "setallowedtraversals" ] = ::do_setallowedtraversals;
|
||||
level.bot_builtins[ "setignoredlinks" ] = ::do_setignoredlinks;
|
||||
level.bot_builtins[ "getnodenumber" ] = ::do_getnodenumber;
|
||||
level.bot_builtins[ "getlinkednodes" ] = ::do_getlinkednodes;
|
||||
level.bot_builtins[ "addtestclient" ] = ::do_addtestclient;
|
||||
level.bot_builtins[ "notifyonplayercommand" ] = ::do_notifyonplayercommand;
|
||||
level.bot_builtins[ "cmdexec" ] = ::do_cmdexec;
|
||||
level.bot_builtins[ "ishost" ] = ::do_ishost;
|
||||
}
|
||||
|
||||
do_printconsole( s )
|
||||
{
|
||||
printconsole( s );
|
||||
}
|
||||
|
||||
do_botaction( action )
|
||||
{
|
||||
self botaction( action );
|
||||
}
|
||||
|
||||
do_botstop()
|
||||
{
|
||||
self botstop();
|
||||
}
|
||||
|
||||
do_botmovement( left, forward )
|
||||
{
|
||||
self botmovement( left, forward );
|
||||
}
|
||||
|
||||
do_botmeleeparams( yaw, dist )
|
||||
{
|
||||
self botmeleeparams( yaw, dist );
|
||||
}
|
||||
|
||||
do_isbot()
|
||||
{
|
||||
return self isbot();
|
||||
}
|
||||
|
||||
do_generatepath( from, to, team, best_effort )
|
||||
{
|
||||
return generatepath( from, to, team, best_effort );
|
||||
}
|
||||
|
||||
do_getfunction( file, threadname )
|
||||
{
|
||||
return getfunction( file, threadname );
|
||||
}
|
||||
|
||||
do_getmins()
|
||||
{
|
||||
return self getmins();
|
||||
}
|
||||
|
||||
do_getmaxs()
|
||||
{
|
||||
return self getmaxs();
|
||||
}
|
||||
|
||||
do_getguid()
|
||||
{
|
||||
return self getguid();
|
||||
}
|
||||
|
||||
do_setallowedtraversals( a )
|
||||
{
|
||||
setallowedtraversals( a );
|
||||
}
|
||||
|
||||
do_setignoredlinks( a )
|
||||
{
|
||||
setignoredlinks( a );
|
||||
}
|
||||
|
||||
do_getnodenumber()
|
||||
{
|
||||
return self getnodenumber();
|
||||
}
|
||||
|
||||
do_getlinkednodes()
|
||||
{
|
||||
return self getlinkednodes();
|
||||
}
|
||||
|
||||
do_addtestclient()
|
||||
{
|
||||
return addtestclient();
|
||||
}
|
||||
|
||||
do_notifyonplayercommand( a, b )
|
||||
{
|
||||
self notifyonplayercommand( a, b );
|
||||
}
|
||||
|
||||
do_cmdexec( a )
|
||||
{
|
||||
cmdexec( a );
|
||||
}
|
||||
|
||||
do_ishost()
|
||||
{
|
||||
return self ishost();
|
||||
}
|
4
scripts/sp/bots_debug.gsc
Normal file
4
scripts/sp/bots_debug.gsc
Normal file
@ -0,0 +1,4 @@
|
||||
init()
|
||||
{
|
||||
level thread maps\bots\_bot_debug::init();
|
||||
}
|
Reference in New Issue
Block a user