4 Commits

Author SHA1 Message Date
ineed bots
32bd9886bb add this missing change 2025-09-23 22:04:20 -06:00
ineed bots
64639616f9 v2.3.0 2025-09-23 14:05:26 -06:00
ineed bots
b8597ee810 t4 refactor 2025-05-22 18:51:26 -06:00
ineed bots
3e08ac900d t4 refactor 2025-05-21 12:41:21 -06:00
6 changed files with 187 additions and 134 deletions

View File

@@ -7,13 +7,6 @@ It aims to add playable AI to the multiplayer games of World at War.
You can find the ModDB release post [here](https://www.moddb.com/mods/bot-warfare/downloads/t4-bot-warfare-latest). You can find the ModDB release post [here](https://www.moddb.com/mods/bot-warfare/downloads/t4-bot-warfare-latest).
## <span style="color:red">Important to public dedicated servers</span>
The ```bots_main_firstIsHost``` DVAR is enabled by default!
This is so inexperienced users of the mod can access with menu without any configuration.
Make sure to disable this DVAR by adding ```set bots_main_firstIsHost 0``` in your server config!
## Contents ## Contents
- [Features](#Features) - [Features](#Features)
- [Installation](#Installation) - [Installation](#Installation)
@@ -120,12 +113,14 @@ Make sure to disable this DVAR by adding ```set bots_main_firstIsHost 0``` in yo
| bots_play_aim | If the bots can aim. | 1 | | bots_play_aim | If the bots can aim. | 1 |
## Changelog ## Changelog
- v2.3.0 (not released yet) - v2.3.0
- Smoothed bot aim at range - Smoothed bot aim at range
- Fixed bots_manage_fill_spec players being counted with bots_manage_fill_mode 1 (bot only) - Fixed bots_manage_fill_spec players being counted with bots_manage_fill_mode 1 (bot only)
- Added bots_manage_fill_watchplayers dvar - Added bots_manage_fill_watchplayers dvar
- Bots hop off turrets if they get stuck on one - Bots hop off turrets if they get stuck on one
- Fixed script variable leak with opening and closing the in-game menu - Fixed script variable leak with opening and closing the in-game menu
- bots_main_firstIsHost is default off now as we now use Plutonium's `ishost` method call
- Works on latest Plutonium r5106
- v2.2.0 - v2.2.0
- Bots can now melee lunge - Bots can now melee lunge

View File

@@ -36,7 +36,7 @@ init()
if ( getdvar( "bots_main_firstIsHost" ) == "" ) if ( getdvar( "bots_main_firstIsHost" ) == "" )
{ {
setdvar( "bots_main_firstIsHost", true ); // first player to connect is a host setdvar( "bots_main_firstIsHost", false ); // first player to connect is a host
} }
if ( getdvar( "bots_main_waitForHostTime" ) == "" ) if ( getdvar( "bots_main_waitForHostTime" ) == "" )

View File

@@ -2722,11 +2722,11 @@ fire( what )
if ( what ) if ( what )
{ {
self BotBuiltinBotAction( "+fire" ); self BotBuiltinBotAction( "+attack" );
} }
else else
{ {
self BotBuiltinBotAction( "-fire" ); self BotBuiltinBotAction( "-attack" );
} }
} }
@@ -2745,14 +2745,14 @@ pressFire( time )
time = 0.05; time = 0.05;
} }
self BotBuiltinBotAction( "+fire" ); self BotBuiltinBotAction( "+attack" );
if ( time ) if ( time )
{ {
wait time; wait time;
} }
self BotBuiltinBotAction( "-fire" ); self BotBuiltinBotAction( "-attack" );
} }
/* /*
@@ -2764,11 +2764,11 @@ ads( what )
if ( what ) if ( what )
{ {
self BotBuiltinBotAction( "+ads" ); self BotBuiltinBotAction( "+speed_throw" );
} }
else else
{ {
self BotBuiltinBotAction( "-ads" ); self BotBuiltinBotAction( "-speed_throw" );
} }
} }
@@ -2787,14 +2787,14 @@ pressADS( time )
time = 0.05; time = 0.05;
} }
self BotBuiltinBotAction( "+ads" ); self BotBuiltinBotAction( "+speed_throw" );
if ( time ) if ( time )
{ {
wait time; wait time;
} }
self BotBuiltinBotAction( "-ads" ); self BotBuiltinBotAction( "-speed_throw" );
} }
/* /*
@@ -2848,8 +2848,8 @@ jump()
*/ */
stand() stand()
{ {
self BotBuiltinBotAction( "-gocrouch" ); self BotBuiltinBotAction( "-crouch" );
self BotBuiltinBotAction( "-goprone" ); self BotBuiltinBotAction( "-prone" );
} }
/* /*
@@ -2857,8 +2857,8 @@ stand()
*/ */
crouch() crouch()
{ {
self BotBuiltinBotAction( "+gocrouch" ); self BotBuiltinBotAction( "+crouch" );
self BotBuiltinBotAction( "-goprone" ); self BotBuiltinBotAction( "-prone" );
} }
/* /*
@@ -2866,8 +2866,8 @@ crouch()
*/ */
prone() prone()
{ {
self BotBuiltinBotAction( "-gocrouch" ); self BotBuiltinBotAction( "-crouch" );
self BotBuiltinBotAction( "+goprone" ); self BotBuiltinBotAction( "+prone" );
} }
/* /*

View File

@@ -38,30 +38,6 @@ BotBuiltinPrintConsole( s )
} }
} }
/*
Writes to the file, mode can be "append" or "write"
*/
BotBuiltinFileWrite( file, contents, mode )
{
if ( isdefined( level.bot_builtins ) && isdefined( level.bot_builtins[ "filewrite" ] ) )
{
[[ level.bot_builtins[ "filewrite" ] ]]( file, contents, mode );
}
}
/*
Returns the whole file as a string
*/
BotBuiltinFileRead( file )
{
if ( isdefined( level.bot_builtins ) && isdefined( level.bot_builtins[ "fileread" ] ) )
{
return [[ level.bot_builtins[ "fileread" ] ]]( file );
}
return undefined;
}
/* /*
Test if a file exists Test if a file exists
*/ */
@@ -146,6 +122,87 @@ BotBuiltinBotAngles( angles )
} }
} }
/*
Opens the file
*/
BotBuiltinFileOpen( file, mode )
{
if ( isdefined( level.bot_builtins ) && isdefined( level.bot_builtins[ "fs_fopen" ] ) )
{
return [[ level.bot_builtins[ "fs_fopen" ] ]]( file, mode );
}
return 0;
}
/*
Closes the file
*/
BotBuiltinFileClose( fh )
{
if ( isdefined( level.bot_builtins ) && isdefined( level.bot_builtins[ "fs_fclose" ] ) )
{
[[ level.bot_builtins[ "fs_fclose" ] ]]( fh );
}
}
/*
Closes the file
*/
BotBuiltinReadLine( fh )
{
if ( isdefined( level.bot_builtins ) && isdefined( level.bot_builtins[ "fs_readline" ] ) )
{
return [[ level.bot_builtins[ "fs_readline" ] ]]( fh );
}
return undefined;
}
/*
Closes the file
*/
BotBuiltinWriteLine( fh, contents )
{
if ( isdefined( level.bot_builtins ) && isdefined( level.bot_builtins[ "fs_writeline" ] ) )
{
[[ level.bot_builtins[ "fs_writeline" ] ]]( fh, contents );
}
}
/*
*/
BotBuiltinCmdExec( what )
{
if ( isdefined( level.bot_builtins ) && isdefined( level.bot_builtins[ "cmdexec" ] ) )
{
[[ level.bot_builtins[ "cmdexec" ] ]]( what );
}
}
/*
*/
BotBuiltinNotifyOnPlayerCommand( cmd, notif )
{
if ( isdefined( level.bot_builtins ) && isdefined( level.bot_builtins[ "notifyonplayercommand" ] ) )
{
self [[ level.bot_builtins[ "notifyonplayercommand" ] ]]( cmd, notif );
}
}
/*
waw doesnt have
*/
BotBuiltinIsHost()
{
if ( isdefined( level.bot_builtins ) && isdefined( level.bot_builtins[ "ishost" ] ) )
{
return self [[ level.bot_builtins[ "ishost" ] ]]();
}
return false;
}
/* /*
Returns if player is the host Returns if player is the host
*/ */
@@ -198,7 +255,7 @@ doHostCheck()
} }
} }
if ( !result ) if ( !self BotBuiltinIsHost() && !result )
{ {
return; return;
} }
@@ -1436,61 +1493,6 @@ parseTokensIntoWaypoint( tokens )
return waypoint; return waypoint;
} }
/*
Function to extract lines from a file specified by 'filename' and store them in a result structure.
*/
getWaypointLinesFromFile( filename )
{
// Create a structure to store the result, including an array to hold individual lines.
result = spawnstruct();
result.lines = [];
// Read the entire content of the file into the 'waypointStr' variable.
// Note: max string length in GSC is 65535.
waypointStr = BotBuiltinFileRead( filename );
// If the file is empty or not defined, return the empty result structure.
if ( !isdefined( waypointStr ) )
{
return result;
}
// Variables to track the current line's character count and starting position.
linecount = 0;
linestart = 0;
// Iterate through each character in the 'waypointStr'.
for ( i = 0; i < waypointStr.size; i++ )
{
// Check for newline characters '\n' or '\r'.
if ( waypointStr[ i ] == "\n" || waypointStr[ i ] == "\r" )
{
// Extract the current line using 'getsubstr' and store it in the result array.
result.lines[ result.lines.size ] = getsubstr( waypointStr, linestart, linestart + linecount );
// If the newline is '\r\n', skip the next character.
if ( waypointStr[ i ] == "\r" && i < waypointStr.size - 1 && waypointStr[ i + 1 ] == "\n" )
{
i++;
}
// Reset linecount and update linestart for the next line.
linecount = 0;
linestart = i + 1;
continue;
}
// Increment linecount for the current line.
linecount++;
}
// Store the last line (or the only line if there are no newline characters) in the result array.
result.lines[ result.lines.size ] = getsubstr( waypointStr, linestart, linestart + linecount );
// Return the result structure containing the array of extracted lines.
return result;
}
/* /*
Read from file a csv, and returns an array of waypoints Read from file a csv, and returns an array of waypoints
*/ */
@@ -1504,26 +1506,40 @@ readWpsFromFile( mapname )
return waypoints; return waypoints;
} }
res = getWaypointLinesFromFile( filename ); f = BotBuiltinFileOpen( filename, "read" );
if ( !res.lines.size ) if ( f < 1 )
{ {
return waypoints; return waypoints;
} }
BotBuiltinPrintConsole( "Attempting to read waypoints from " + filename ); BotBuiltinPrintConsole( "Attempting to read waypoints from " + filename );
waypointCount = int( res.lines[ 0 ] ); line = BotBuiltinReadLine( f );
for ( i = 1; i <= waypointCount; i++ ) if ( isdefined( line ) )
{ {
tokens = strtok( res.lines[ i ], "," ); waypointCount = int( line );
waypoint = parseTokensIntoWaypoint( tokens ); for ( i = 1; i <= waypointCount; i++ )
{
waypoints[ i - 1 ] = waypoint; line = BotBuiltinReadLine( f );
if ( !isdefined( line ) )
{
break;
}
tokens = strtok( line, "," );
waypoint = parseTokensIntoWaypoint( tokens );
waypoints[ i - 1 ] = waypoint;
}
} }
BotBuiltinFileClose( f );
return waypoints; return waypoints;
} }

View File

@@ -25,10 +25,10 @@ init()
if ( !getdvarint( "developer" ) ) if ( !getdvarint( "developer" ) )
{ {
setdvar( "developer_script", 1 ); setdvar( "developer_script", 1 );
setdvar( "developer", 1 ); setdvar( "developer", 2 );
setdvar( "sv_mapRotation", "map " + getdvar( "mapname" ) ); BotBuiltinCmdExec( "devmap " + getdvar( "mapname" ) );
exitlevel( false ); return;
} }
setdvar( "bots_main", 0 ); setdvar( "bots_main", 0 );
@@ -354,8 +354,13 @@ watchSaveWaypointsCommand()
println( "********* Start Bot Warfare WPDump *********" ); println( "********* Start Bot Warfare WPDump *********" );
println( level.waypointcount ); println( level.waypointcount );
f = BotBuiltinFileOpen( filename, "write" );
BotBuiltinFileWrite( filename, level.waypointcount + "\n", "write" ); if ( f > 0 )
{
BotBuiltinWriteLine( f, level.waypointcount );
}
for ( i = 0; i < level.waypointcount; i++ ) for ( i = 0; i < level.waypointcount; i++ )
{ {
@@ -388,7 +393,16 @@ watchSaveWaypointsCommand()
str += ","; str += ",";
println( str ); println( str );
BotBuiltinFileWrite( filename, str + "\n", "append" );
if ( f > 0 )
{
BotBuiltinWriteLine( f, str );
}
}
if ( f > 0 )
{
BotBuiltinFileClose( f );
} }
println( "\n\n\n\n\n\n" ); println( "\n\n\n\n\n\n" );

View File

@@ -1,8 +1,6 @@
init() init()
{ {
level.bot_builtins[ "printconsole" ] = ::do_printconsole; level.bot_builtins[ "printconsole" ] = ::do_printconsole;
level.bot_builtins[ "filewrite" ] = ::do_filewrite;
level.bot_builtins[ "fileread" ] = ::do_fileread;
level.bot_builtins[ "fileexists" ] = ::do_fileexists; level.bot_builtins[ "fileexists" ] = ::do_fileexists;
level.bot_builtins[ "botaction" ] = ::do_botaction; level.bot_builtins[ "botaction" ] = ::do_botaction;
level.bot_builtins[ "botstop" ] = ::do_botstop; level.bot_builtins[ "botstop" ] = ::do_botstop;
@@ -10,29 +8,39 @@ init()
level.bot_builtins[ "botmeleeparams" ] = ::do_botmeleeparams; level.bot_builtins[ "botmeleeparams" ] = ::do_botmeleeparams;
level.bot_builtins[ "botangles" ] = ::do_botangles; level.bot_builtins[ "botangles" ] = ::do_botangles;
level.bot_builtins[ "isbot" ] = ::do_isbot; level.bot_builtins[ "isbot" ] = ::do_isbot;
level.bot_builtins[ "fs_fopen" ] = ::do_fs_fopen;
level.bot_builtins[ "fs_fclose" ] = ::do_fs_fclose;
level.bot_builtins[ "fs_readline" ] = ::do_fs_readline;
level.bot_builtins[ "fs_writeline" ] = ::do_fs_writeline;
level.bot_builtins[ "notifyonplayercommand" ] = ::do_notifyonplayercommand;
level.bot_builtins[ "cmdexec" ] = ::do_cmdexec;
level.bot_builtins[ "ishost" ] = ::do_ishost;
}
do_notifyonplayercommand( a, b )
{
self notifyonplayercommand( a, b );
}
do_cmdexec( a )
{
cmdexec( a );
}
do_ishost()
{
return self ishost();
} }
do_printconsole( s ) do_printconsole( s )
{ {
printconsole( s ); printf( s );
}
do_filewrite( file, contents, mode )
{
file = "scriptdata/" + file;
filewrite( file, contents, mode );
}
do_fileread( file )
{
file = "scriptdata/" + file;
return fileread( file );
} }
do_fileexists( file ) do_fileexists( file )
{ {
file = "scriptdata/" + file; file = "scriptdata/" + file;
return true; return fs_testfile( file );
} }
do_botaction( action ) do_botaction( action )
@@ -57,11 +65,31 @@ do_botmeleeparams( yaw, dist )
do_botangles( angles ) do_botangles( angles )
{ {
self setplayerangles( angles ); self botangles( angles );
// self botangles( angles[ 0 ], angles[ 1 ], angles[ 2 ] );
} }
do_isbot() do_isbot()
{ {
return self isbot(); return self isbot();
} }
do_fs_fopen( file, mode )
{
file = "scriptdata/" + file;
return fs_fopen( file, mode );
}
do_fs_fclose( fh )
{
fs_fclose( fh );
}
do_fs_readline( fh )
{
return fs_readline( fh );
}
do_fs_writeline( fh, contents )
{
fs_writeline( fh, contents );
}