Version 2.1.0

This commit is contained in:
ineed bots 2022-05-08 17:46:25 -06:00
parent 9c20cf621b
commit a64a0cc810
15 changed files with 9340 additions and 5631 deletions

View File

@ -5,7 +5,7 @@ Bot Warfare is a GSC mod for the [CoD4x project](https://github.com/callofduty4x
It aims to add playable AI to the multiplayer games of CoD4. It aims to add playable AI to the multiplayer games of CoD4.
You can find the ModDB release post [here](https://www.moddb.com/mods/bot-warfare/downloads/cod4x-bot-warfare-latest) and the CoD4x.me post [here](https://cod4x.me/index.php?/forums/topic/3116-release-bot-warfare/). You can find the ModDB release post [here](https://www.moddb.com/mods/bot-warfare/downloads/cod4x-bot-warfare-latest) and the CoD4x forum post [here](https://cod4x.ovh/index.php?/forums/topic/3116-release-bot-warfare/).
## <span style="color:red">Important to public dedicated servers</span> ## <span style="color:red">Important to public dedicated servers</span>
The ```bots_main_firstIsHost``` DVAR is enabled by default! The ```bots_main_firstIsHost``` DVAR is enabled by default!
@ -57,15 +57,15 @@ Make sure to disable this DVAR by adding ```set bots_main_firstIsHost 0``` in yo
- ... And pretty much everything you expect a Combat Training bot to have - ... And pretty much everything you expect a Combat Training bot to have
## Installation ## Installation
Using CoD4x's extended functionality requires to use their Dedicated server, as explained [here](https://cod4x.me/index.php?/forums/topic/2047-add-cod4x-server-gsc-functions-to-the-client/). Using CoD4x's extended functionality requires to use their Dedicated server, as explained [here](https://cod4x.ovh/index.php?/forums/topic/2047-add-cod4x-server-gsc-functions-to-the-client/).
You can easily setup a local LAN dedicated server for you to join and play on. Have a look at [Setting up a CoD4x server](). You can easily setup a local LAN dedicated server for you to join and play on. Have a look at [Setting up a CoD4x server]().
0. Make sure that [CoD4x server + client](https://cod4x.me/) is installed, updated and working properly. 0. Make sure that [CoD4x server + client](https://cod4x.ovh/) is installed, updated and working properly.
- Download the [latest release](https://github.com/ineedbots/cod4x_bot_warfare/releases) of Bot Warfare. - Download the [latest release](https://github.com/ineedbots/cod4x_bot_warfare/releases) of Bot Warfare.
1. Locate your CoD4x server install folder. 1. Locate your CoD4x server install folder.
2. Move the files/folders found in 'Add to root of CoD4x server' from the Bot Warfare release archive you downloaded to the root of your CoD4x server folder. 2. Move the files/folders found in 'Add to root of CoD4x server' from the Bot Warfare release archive you downloaded to the root of your CoD4x server folder.
- The folder/file structure should follow as '.CoD4x server folder\main_shared\maps\mp\bots\_bot.gsc'. - The folder/file structure should follow as `.CoD4x server folder\main_shared\maps\mp\bots\_bot.gsc`.
3. The mod is now installed, now start your server, change the DVARs and start a map. 3. The mod is now installed, now start your server, change the DVARs and start a map.
4. Now start your CoD4x client and connect to your server ('connect 127.0.0.1' in the console most likely) and play! 4. Now start your CoD4x client and connect to your server ('connect 127.0.0.1' in the console most likely) and play!
@ -88,6 +88,7 @@ You can easily setup a local LAN dedicated server for you to join and play on. H
| bots_main_menu | Enable the in-game menu for hosts. | true | | bots_main_menu | Enable the in-game menu for hosts. | true |
| bots_main_debug | Enable the in-game waypoint editor. | false | | bots_main_debug | Enable the in-game waypoint editor. | false |
| bots_main_kickBotsAtEnd | Kick the bots at the end of a match. | false | | bots_main_kickBotsAtEnd | Kick the bots at the end of a match. | false |
| bots_main_chat | The rate bots will chat at, set to 0 to disable. | 1.0 |
| bots_manage_add | Amount of bots to add to the game, once bots are added, resets back to `0`. | 0 | | bots_manage_add | Amount of bots to add to the game, once bots are added, resets back to `0`. | 0 |
| bots_manage_fill | Amount of players/bots (look at `bots_manage_fill_mode`) to maintain in the match. | 0 | | bots_manage_fill | Amount of players/bots (look at `bots_manage_fill_mode`) to maintain in the match. | 0 |
| bots_manage_fill_mode | `bots_manage_fill` players/bots counting method.<ul><li>`0` - counts both players and bots.</li><li>`1` - only counts bots.</li></ul> | 0 | | bots_manage_fill_mode | `bots_manage_fill` players/bots counting method.<ul><li>`0` - counts both players and bots.</li><li>`1` - only counts bots.</li></ul> | 0 |
@ -121,6 +122,17 @@ You can easily setup a local LAN dedicated server for you to join and play on. H
## Changelog ## Changelog
- v2.1.0
- Bot chatter system, bots_main_chat
- Greatly reduce script variable usage
- Improved bots mantling and stuck
- Fix some runtime errors
- Bots sprint more
- Improved bots sight on enemies
- Bots do random actions while waiting at an objective
- Improved bots from getting stuck
- Better bot difficulty management, bots_skill_min and bots_skill_max
- v2.0.1 - v2.0.1
- Reduced bots crouching - Reduced bots crouching
- Increased bots sprinting - Increased bots sprinting

@ -1 +1 @@
Subproject commit 65a344f95388f6d0f0704f3c4517283670bb2818 Subproject commit c734ac790d590225e613fa3c2b10f411c29885aa

View File

@ -8,7 +8,7 @@
*/ */
init() init()
{ {
level.bw_VERSION = "2.0.1"; level.bw_VERSION = "2.1.0";
if ( getDvar( "bots_main" ) == "" ) if ( getDvar( "bots_main" ) == "" )
setDvar( "bots_main", true ); setDvar( "bots_main", true );

File diff suppressed because it is too large Load Diff

View File

@ -10,35 +10,35 @@
/* /*
Will attempt to retreive waypoints from the internet Will attempt to retreive waypoints from the internet
*/ */
getRemoteWaypoints(mapname) getRemoteWaypoints( mapname )
{ {
url = "https://raw.githubusercontent.com/ineedbots/cod4x_waypoints/master/" + mapname + "_wp.csv"; url = "https://raw.githubusercontent.com/ineedbots/cod4x_waypoints/master/" + mapname + "_wp.csv";
filename = "waypoints/" + mapname + "_wp.csv"; filename = "waypoints/" + mapname + "_wp.csv";
printToConsole("Attempting to get remote waypoints from " + url); printToConsole( "Attempting to get remote waypoints from " + url );
res = getLinesFromUrl(url, filename); res = getLinesFromUrl( url, filename );
if (!res.lines.size) if ( !res.lines.size )
return; return;
waypointCount = int(res.lines[0]); waypointCount = int( res.lines[0] );
waypoints = []; waypoints = [];
printToConsole("Loading remote waypoints..."); printToConsole( "Loading remote waypoints..." );
for (i = 1; i <= waypointCount; i++) for ( i = 1; i <= waypointCount; i++ )
{ {
tokens = tokenizeLine(res.lines[i], ","); tokens = tokenizeLine( res.lines[i], "," );
waypoint = parseTokensIntoWaypoint(tokens); waypoint = parseTokensIntoWaypoint( tokens );
waypoints[i-1] = waypoint; waypoints[i - 1] = waypoint;
} }
if (waypoints.size) if ( waypoints.size )
{ {
level.waypoints = waypoints; level.waypoints = waypoints;
printToConsole("Loaded " + waypoints.size + " waypoints from remote."); printToConsole( "Loaded " + waypoints.size + " waypoints from remote." );
} }
} }
@ -49,20 +49,20 @@ doVersionCheck()
{ {
remoteVersion = getRemoteVersion(); remoteVersion = getRemoteVersion();
if (!isDefined(remoteVersion)) if ( !isDefined( remoteVersion ) )
{ {
printToConsole("Error getting remote version of Bot Warfare."); printToConsole( "Error getting remote version of Bot Warfare." );
return false; return false;
} }
if (level.bw_VERSION != remoteVersion) if ( level.bw_VERSION != remoteVersion )
{ {
printToConsole("There is a new version of Bot Warfare!"); printToConsole( "There is a new version of Bot Warfare!" );
printToConsole("You are on version " + level.bw_VERSION + " but " + remoteVersion + " is available!"); printToConsole( "You are on version " + level.bw_VERSION + " but " + remoteVersion + " is available!" );
return false; return false;
} }
printToConsole("You are on the latest version of Bot Warfare!"); printToConsole( "You are on the latest version of Bot Warfare!" );
return true; return true;
} }
@ -77,16 +77,16 @@ getRemoteVersion()
data = undefined; data = undefined;
#endif #endif
if (!isDefined(data)) if ( !isDefined( data ) )
return undefined; return undefined;
return strtok(data, "\n")[0]; return strtok( data, "\n" )[0];
} }
/* /*
Returns an array of each line from the response of the http url request Returns an array of each line from the response of the http url request
*/ */
getLinesFromUrl(url, filename) getLinesFromUrl( url, filename )
{ {
result = spawnStruct(); result = spawnStruct();
result.lines = []; result.lines = [];
@ -97,25 +97,26 @@ getLinesFromUrl(url, filename)
data = undefined; data = undefined;
#endif #endif
if (!isDefined(data)) if ( !isDefined( data ) )
return result; return result;
fd = FS_FOpen(filename, "write"); fd = FS_FOpen( filename, "write" );
line = ""; line = "";
for (i=0;i<data.size;i++)
for ( i = 0; i < data.size; i++ )
{ {
c = data[i]; c = data[i];
if (c == "\n") if ( c == "\n" )
{ {
result.lines[result.lines.size] = line; result.lines[result.lines.size] = line;
if (fd > 0) if ( fd > 0 )
{ {
if (!FS_WriteLine(fd, line)) if ( !FS_WriteLine( fd, line ) )
{ {
FS_FClose(fd); FS_FClose( fd );
fd = 0; fd = 0;
} }
} }
@ -126,10 +127,11 @@ getLinesFromUrl(url, filename)
line += c; line += c;
} }
result.lines[result.lines.size] = line; result.lines[result.lines.size] = line;
if (fd > 0) if ( fd > 0 )
FS_FClose(fd); FS_FClose( fd );
return result; return result;
} }

View File

@ -12,80 +12,81 @@
init() init()
{ {
if(getDvar("bots_main_debug") == "") if ( getDvar( "bots_main_debug" ) == "" )
setDvar("bots_main_debug", 0); setDvar( "bots_main_debug", 0 );
if(!getDVarint("bots_main_debug")) if ( !getDVarint( "bots_main_debug" ) )
return; return;
if(!getDVarint("developer")) if ( !getDVarint( "developer" ) )
{ {
setdvar("developer_script", 1); setdvar( "developer_script", 1 );
setdvar("developer", 1); setdvar( "developer", 1 );
setdvar("sv_mapRotation", "map "+getDvar("mapname")); setdvar( "sv_mapRotation", "map " + getDvar( "mapname" ) );
exitLevel(false); exitLevel( false );
} }
setDvar("bots_main", 0); setDvar( "bots_main", 0 );
setdvar("bots_main_menu", 0); setdvar( "bots_main_menu", 0 );
setdvar("bots_manage_fill_mode", 0); setdvar( "bots_manage_fill_mode", 0 );
setdvar("bots_manage_fill", 0); setdvar( "bots_manage_fill", 0 );
setdvar("bots_manage_add", 0); setdvar( "bots_manage_add", 0 );
setdvar("bots_manage_fill_kick", 1); setdvar( "bots_manage_fill_kick", 1 );
setDvar("bots_manage_fill_spec", 1); setDvar( "bots_manage_fill_spec", 1 );
if (getDvar("bots_main_debug_distance") == "") if ( getDvar( "bots_main_debug_distance" ) == "" )
setDvar("bots_main_debug_distance", 512.0); setDvar( "bots_main_debug_distance", 512.0 );
if (getDvar("bots_main_debug_cone") == "") if ( getDvar( "bots_main_debug_cone" ) == "" )
setDvar("bots_main_debug_cone", 0.65); setDvar( "bots_main_debug_cone", 0.65 );
if (getDvar("bots_main_debug_minDist") == "") if ( getDvar( "bots_main_debug_minDist" ) == "" )
setDvar("bots_main_debug_minDist", 32.0); setDvar( "bots_main_debug_minDist", 32.0 );
if (getDvar("bots_main_debug_drawThrough") == "") if ( getDvar( "bots_main_debug_drawThrough" ) == "" )
setDvar("bots_main_debug_drawThrough", false); setDvar( "bots_main_debug_drawThrough", false );
if(getDvar("bots_main_debug_commandWait") == "") if ( getDvar( "bots_main_debug_commandWait" ) == "" )
setDvar("bots_main_debug_commandWait", 0.5); setDvar( "bots_main_debug_commandWait", 0.5 );
if(getDvar("bots_main_debug_framerate") == "") if ( getDvar( "bots_main_debug_framerate" ) == "" )
setDvar("bots_main_debug_framerate", 58); setDvar( "bots_main_debug_framerate", 58 );
if(getDvar("bots_main_debug_lineDuration") == "") if ( getDvar( "bots_main_debug_lineDuration" ) == "" )
setDvar("bots_main_debug_lineDuration", 3); setDvar( "bots_main_debug_lineDuration", 3 );
if(getDvar("bots_main_debug_printDuration") == "") if ( getDvar( "bots_main_debug_printDuration" ) == "" )
setDvar("bots_main_debug_printDuration", 3); setDvar( "bots_main_debug_printDuration", 3 );
if(getDvar("bots_main_debug_debugRate") == "") if ( getDvar( "bots_main_debug_debugRate" ) == "" )
setDvar("bots_main_debug_debugRate", 0.5); setDvar( "bots_main_debug_debugRate", 0.5 );
setDvar("player_sustainAmmo", 1); setDvar( "player_sustainAmmo", 1 );
level.waypoints = []; level.waypoints = [];
level.waypointCount = 0; level.waypointCount = 0;
level waittill( "connected", player); level waittill( "connected", player );
player thread onPlayerSpawned(); player thread onPlayerSpawned();
} }
onPlayerSpawned() onPlayerSpawned()
{ {
self endon("disconnect"); self endon( "disconnect" );
for(;;)
for ( ;; )
{ {
self waittill("spawned_player"); self waittill( "spawned_player" );
self thread beginDebug(); self thread beginDebug();
} }
} }
beginDebug() beginDebug()
{ {
self endon("disconnect"); self endon( "disconnect" );
self endon("death"); self endon( "death" );
level.wpToLink = -1; level.wpToLink = -1;
level.autoLink = false; level.autoLink = false;
@ -95,10 +96,10 @@ beginDebug()
self clearPerks(); self clearPerks();
self takeAllWeapons(); self takeAllWeapons();
self.specialty = []; self.specialty = [];
self giveWeapon("m16_gl_mp"); self giveWeapon( "m16_gl_mp" );
self SetActionSlot( 3, "altMode" ); self SetActionSlot( 3, "altMode" );
self giveWeapon("frag_grenade_mp"); self giveWeapon( "frag_grenade_mp" );
self freezecontrols(false); self freezecontrols( false );
self thread debug(); self thread debug();
self thread addWaypoints(); self thread addWaypoints();
@ -107,266 +108,277 @@ beginDebug()
self thread watchSaveWaypointsCommand(); self thread watchSaveWaypointsCommand();
self thread sayExtras(); self thread sayExtras();
self thread textScroll("^1SecondaryOffhand - ^2Add Waypoint; ^3MeleeButton - ^4Link Waypoint; ^5FragButton - ^6Delete Waypoint; ^7UseButton + AttackButton - ^8Save"); self thread textScroll( "^1SecondaryOffhand - ^2Add Waypoint; ^3MeleeButton - ^4Link Waypoint; ^5FragButton - ^6Delete Waypoint; ^7UseButton + AttackButton - ^8Save" );
} }
sayExtras() sayExtras()
{ {
self endon("disconnect"); self endon( "disconnect" );
self endon("death"); self endon( "death" );
self iprintln("Making a crouch waypoint with only one link..."); self iprintln( "Making a crouch waypoint with only one link..." );
self iprintln("Makes a camping waypoint."); self iprintln( "Makes a camping waypoint." );
} }
debug() debug()
{ {
self endon("disconnect"); self endon( "disconnect" );
self endon("death"); self endon( "death" );
self setClientDvar("com_maxfps", getDvarInt("bots_main_debug_framerate")); self setClientDvar( "com_maxfps", getDvarInt( "bots_main_debug_framerate" ) );
for(;;) for ( ;; )
{ {
wait getDvarFloat("bots_main_debug_debugRate"); wait getDvarFloat( "bots_main_debug_debugRate" );
if(isDefined(self.command)) if ( isDefined( self.command ) )
continue; continue;
closest = -1; closest = -1;
myEye = self getTagOrigin( "j_head" ); myEye = self getTagOrigin( "j_head" );
myAngles = self GetPlayerAngles(); myAngles = self GetPlayerAngles();
for(i = 0; i < level.waypointCount; i++) for ( i = 0; i < level.waypointCount; i++ )
{ {
if(closest == -1 || closer(self.origin, level.waypoints[i].origin, level.waypoints[closest].origin)) if ( closest == -1 || closer( self.origin, level.waypoints[i].origin, level.waypoints[closest].origin ) )
closest = i; closest = i;
wpOrg = level.waypoints[i].origin + (0, 0, 25); wpOrg = level.waypoints[i].origin + ( 0, 0, 25 );
if(distance(level.waypoints[i].origin, self.origin) < getDvarFloat("bots_main_debug_distance") && (bulletTracePassed(myEye, wpOrg, false, self) || getDVarint("bots_main_debug_drawThrough"))) if ( distance( level.waypoints[i].origin, self.origin ) < getDvarFloat( "bots_main_debug_distance" ) && ( bulletTracePassed( myEye, wpOrg, false, self ) || getDVarint( "bots_main_debug_drawThrough" ) ) )
{ {
for(h = 0; h < level.waypoints[i].childCount; h++) for ( h = level.waypoints[i].children.size - 1; h >= 0; h-- )
line(wpOrg, level.waypoints[level.waypoints[i].children[h]].origin + (0, 0, 25), (1,0,1), 1, 1, getDvarInt("bots_main_debug_lineDuration")); line( wpOrg, level.waypoints[level.waypoints[i].children[h]].origin + ( 0, 0, 25 ), ( 1, 0, 1 ), 1, 1, getDvarInt( "bots_main_debug_lineDuration" ) );
if(getConeDot(wpOrg, myEye, myAngles) > getDvarFloat("bots_main_debug_cone")) if ( getConeDot( wpOrg, myEye, myAngles ) > getDvarFloat( "bots_main_debug_cone" ) )
print3d(wpOrg, i, (1,0,0), 2, 1, 6); print3d( wpOrg, i, ( 1, 0, 0 ), 2, 1, 6 );
if (isDefined(level.waypoints[i].angles) && level.waypoints[i].type != "stand") if ( isDefined( level.waypoints[i].angles ) && level.waypoints[i].type != "stand" )
line(wpOrg, wpOrg + AnglesToForward(level.waypoints[i].angles) * 64, (1,1,1), 1, 1, getDvarInt("bots_main_debug_lineDuration")); line( wpOrg, wpOrg + AnglesToForward( level.waypoints[i].angles ) * 64, ( 1, 1, 1 ), 1, 1, getDvarInt( "bots_main_debug_lineDuration" ) );
} }
} }
self.closest = closest; self.closest = closest;
if(closest != -1) if ( closest != -1 )
{ {
stringChildren = ""; stringChildren = "";
for(i = 0; i < level.waypoints[closest].childCount; i++)
for ( i = 0; i < level.waypoints[closest].children.size; i++ )
{ {
if(i != 0) if ( i != 0 )
stringChildren = stringChildren + "," + level.waypoints[closest].children[i]; stringChildren = stringChildren + "," + level.waypoints[closest].children[i];
else else
stringChildren = stringChildren + level.waypoints[closest].children[i]; stringChildren = stringChildren + level.waypoints[closest].children[i];
} }
print3d(level.waypoints[closest].origin + (0, 0, 35), stringChildren, (0,1,0), 2, 1, getDvarInt("bots_main_debug_printDuration"));
print3d(level.waypoints[closest].origin + (0, 0, 15), level.waypoints[closest].type, (0,1,0), 2, 1, getDvarInt("bots_main_debug_printDuration")); print3d( level.waypoints[closest].origin + ( 0, 0, 35 ), stringChildren, ( 0, 1, 0 ), 2, 1, getDvarInt( "bots_main_debug_printDuration" ) );
print3d( level.waypoints[closest].origin + ( 0, 0, 15 ), level.waypoints[closest].type, ( 0, 1, 0 ), 2, 1, getDvarInt( "bots_main_debug_printDuration" ) );
} }
} }
} }
AddWaypoints() AddWaypoints()
{ {
self endon("disconnect"); self endon( "disconnect" );
self endon("death"); self endon( "death" );
for(;;)
for ( ;; )
{ {
while(!self SecondaryOffhandButtonPressed() || isDefined(self.command)) while ( !self SecondaryOffhandButtonPressed() || isDefined( self.command ) )
wait 0.05; wait 0.05;
pos = self getOrigin(); pos = self getOrigin();
self.command = true; self.command = true;
self iprintln("Adding a waypoint..."); self iprintln( "Adding a waypoint..." );
self iprintln("ADS - climb; Attack + Use - tube"); self iprintln( "ADS - climb; Attack + Use - tube" );
self iprintln("Attack - grenade; Use - claymore"); self iprintln( "Attack - grenade; Use - claymore" );
self iprintln("Else(wait) - your stance"); self iprintln( "Else(wait) - your stance" );
wait getDvarFloat("bots_main_debug_commandWait"); wait getDvarFloat( "bots_main_debug_commandWait" );
self addWaypoint(pos); self addWaypoint( pos );
self.command = undefined; self.command = undefined;
while(self SecondaryOffhandButtonPressed()) while ( self SecondaryOffhandButtonPressed() )
wait 0.05; wait 0.05;
} }
} }
linkWaypoints() linkWaypoints()
{ {
self endon("disconnect"); self endon( "disconnect" );
self endon("death"); self endon( "death" );
for(;;)
for ( ;; )
{ {
while(!self MeleeButtonPressed() || isDefined(self.command)) while ( !self MeleeButtonPressed() || isDefined( self.command ) )
wait 0.05; wait 0.05;
self.command = true; self.command = true;
self iprintln("ADS - Unlink; Else(wait) - Link"); self iprintln( "ADS - Unlink; Else(wait) - Link" );
wait getDvarFloat("bots_main_debug_commandWait"); wait getDvarFloat( "bots_main_debug_commandWait" );
if(!self adsButtonPressed()) if ( !self adsButtonPressed() )
self LinkWaypoint(self.closest); self LinkWaypoint( self.closest );
else else
self UnLinkWaypoint(self.closest); self UnLinkWaypoint( self.closest );
self.command = undefined; self.command = undefined;
while(self MeleeButtonPressed()) while ( self MeleeButtonPressed() )
wait 0.05; wait 0.05;
} }
} }
deleteWaypoints() deleteWaypoints()
{ {
self endon("disconnect"); self endon( "disconnect" );
self endon("death"); self endon( "death" );
for(;;)
for ( ;; )
{ {
while(!self fragButtonPressed() || isDefined(self.command)) while ( !self fragButtonPressed() || isDefined( self.command ) )
wait 0.05; wait 0.05;
self.command = true; self.command = true;
self iprintln("Attack - DeleteAll; ADS - Load"); self iprintln( "Attack - DeleteAll; ADS - Load" );
self iprintln("Else(wait) - Delete"); self iprintln( "Else(wait) - Delete" );
wait getDvarFloat("bots_main_debug_commandWait"); wait getDvarFloat( "bots_main_debug_commandWait" );
if(self attackButtonPressed()) if ( self attackButtonPressed() )
self deleteAllWaypoints(); self deleteAllWaypoints();
else if(self adsButtonPressed()) else if ( self adsButtonPressed() )
self LoadWaypoints(); self LoadWaypoints();
else else
self DeleteWaypoint(self.closest); self DeleteWaypoint( self.closest );
self.command = undefined; self.command = undefined;
while(self fragButtonPressed()) while ( self fragButtonPressed() )
wait 0.05; wait 0.05;
} }
} }
watchSaveWaypointsCommand() watchSaveWaypointsCommand()
{ {
self endon("death"); self endon( "death" );
self endon("disconnect"); self endon( "disconnect" );
for(;;) for ( ;; )
{ {
while(!self useButtonPressed() || !self attackButtonPressed() || isDefined(self.command)) while ( !self useButtonPressed() || !self attackButtonPressed() || isDefined( self.command ) )
wait 0.05; wait 0.05;
self.command = true; self.command = true;
self iprintln("ADS - Autolink; Else(wait) - Save"); self iprintln( "ADS - Autolink; Else(wait) - Save" );
wait getDvarFloat("bots_main_debug_commandWait"); wait getDvarFloat( "bots_main_debug_commandWait" );
if(!self adsButtonPressed()) if ( !self adsButtonPressed() )
{ {
self checkForWarnings(); self checkForWarnings();
wait 1; wait 1;
logprint("***********ABiliTy's WPDump**************\n\n"); logprint( "***********ABiliTy's WPDump**************\n\n" );
logprint("\n\n\n\n"); logprint( "\n\n\n\n" );
mpnm=getMapName(getdvar("mapname")); mpnm = getMapName( getdvar( "mapname" ) );
logprint("\n\n"+mpnm+"()\n{\n/*"); logprint( "\n\n" + mpnm + "()\n{\n/*" );
logprint("*/waypoints = [];\n/*"); logprint( "*/waypoints = [];\n/*" );
for(i = 0; i < level.waypointCount; i++)
for ( i = 0; i < level.waypointCount; i++ )
{ {
logprint("*/waypoints["+i+"] = spawnstruct();\n/*"); logprint( "*/waypoints[" + i + "] = spawnstruct();\n/*" );
logprint("*/waypoints["+i+"].origin = "+level.waypoints[i].origin+";\n/*"); logprint( "*/waypoints[" + i + "].origin = " + level.waypoints[i].origin + ";\n/*" );
logprint("*/waypoints["+i+"].type = \""+level.waypoints[i].type+"\";\n/*"); logprint( "*/waypoints[" + i + "].type = \"" + level.waypoints[i].type + "\";\n/*" );
logprint("*/waypoints["+i+"].childCount = "+level.waypoints[i].childCount+";\n/*");
for(c = 0; c < level.waypoints[i].childCount; c++) for ( c = 0; c < level.waypoints[i].children.size; c++ )
{ {
logprint("*/waypoints["+i+"].children["+c+"] = "+level.waypoints[i].children[c]+";\n/*"); logprint( "*/waypoints[" + i + "].children[" + c + "] = " + level.waypoints[i].children[c] + ";\n/*" );
} }
if(isDefined(level.waypoints[i].angles) && (level.waypoints[i].type == "claymore" || level.waypoints[i].type == "tube" || (level.waypoints[i].type == "crouch" && level.waypoints[i].childCount == 1) || level.waypoints[i].type == "climb" || level.waypoints[i].type == "grenade"))
logprint("*/waypoints["+i+"].angles = "+level.waypoints[i].angles+";\n/*"); if ( isDefined( level.waypoints[i].angles ) && ( level.waypoints[i].type == "claymore" || level.waypoints[i].type == "tube" || ( level.waypoints[i].type == "crouch" && level.waypoints[i].children.size == 1 ) || level.waypoints[i].type == "climb" || level.waypoints[i].type == "grenade" ) )
logprint( "*/waypoints[" + i + "].angles = " + level.waypoints[i].angles + ";\n/*" );
} }
logprint("*/return waypoints;\n}\n\n\n\n");
filename = "waypoints/" + getdvar("mapname") + "_wp.csv"; logprint( "*/return waypoints;\n}\n\n\n\n" );
fd = FS_FOpen(filename, "write");
PrintLn("********* Start Bot Warfare WPDump *********"); filename = "waypoints/" + getdvar( "mapname" ) + "_wp.csv";
PrintLn(level.waypointCount); fd = FS_FOpen( filename, "write" );
if (fd > 0) PrintLn( "********* Start Bot Warfare WPDump *********" );
PrintLn( level.waypointCount );
if ( fd > 0 )
{ {
if (!FS_WriteLine(fd, level.waypointCount+"")) if ( !FS_WriteLine( fd, level.waypointCount + "" ) )
{ {
FS_FClose(fd); FS_FClose( fd );
fd = 0; fd = 0;
} }
} }
for(i = 0; i < level.waypointCount; i++)
for ( i = 0; i < level.waypointCount; i++ )
{ {
str = ""; str = "";
wp = level.waypoints[i]; wp = level.waypoints[i];
str += wp.origin[0] + " " + wp.origin[1] + " " + wp.origin[2] + ","; str += wp.origin[0] + " " + wp.origin[1] + " " + wp.origin[2] + ",";
for(h = 0; h < wp.childCount; h++) for ( h = 0; h < wp.children.size; h++ )
{ {
str += wp.children[h]; str += wp.children[h];
if (h < wp.childCount - 1) if ( h < wp.children.size - 1 )
str += " "; str += " ";
} }
str += "," + wp.type + ","; str += "," + wp.type + ",";
if (isDefined(wp.angles)) if ( isDefined( wp.angles ) )
str += wp.angles[0] + " " + wp.angles[1] + " " + wp.angles[2] + ","; str += wp.angles[0] + " " + wp.angles[1] + " " + wp.angles[2] + ",";
else else
str += ","; str += ",";
str += ","; str += ",";
PrintLn(str); PrintLn( str );
if (fd > 0) if ( fd > 0 )
{ {
if (!FS_WriteLine(fd, str)) if ( !FS_WriteLine( fd, str ) )
{ {
FS_FClose(fd); FS_FClose( fd );
fd = 0; fd = 0;
} }
} }
} }
PrintLn("\n\n\n\n\n\n");
self iprintln("Saved!!! to " + filename); PrintLn( "\n\n\n\n\n\n" );
if (fd > 0) self iprintln( "Saved!!! to " + filename );
FS_FClose(fd);
if ( fd > 0 )
FS_FClose( fd );
} }
else else
{ {
if(level.autoLink) if ( level.autoLink )
{ {
self iPrintlnBold("Auto link disabled"); self iPrintlnBold( "Auto link disabled" );
level.autoLink = false; level.autoLink = false;
level.wpToLink = -1; level.wpToLink = -1;
} }
else else
{ {
self iPrintlnBold("Auto link enabled"); self iPrintlnBold( "Auto link enabled" );
level.autoLink = true; level.autoLink = true;
level.wpToLink = self.closest; level.wpToLink = self.closest;
} }
@ -374,7 +386,7 @@ watchSaveWaypointsCommand()
self.command = undefined; self.command = undefined;
while(self useButtonPressed() && self attackButtonPressed()) while ( self useButtonPressed() && self attackButtonPressed() )
wait 0.05; wait 0.05;
} }
} }
@ -382,7 +394,7 @@ watchSaveWaypointsCommand()
LoadWaypoints() LoadWaypoints()
{ {
self DeleteAllWaypoints(); self DeleteAllWaypoints();
self iPrintlnBold("Loading WPS..."); self iPrintlnBold( "Loading WPS..." );
load_waypoints(); load_waypoints();
wait 1; wait 1;
@ -392,53 +404,50 @@ LoadWaypoints()
checkForWarnings() checkForWarnings()
{ {
if(level.waypointCount <= 0) if ( level.waypointCount <= 0 )
self iprintln("WARNING: waypointCount is "+level.waypointCount); self iprintln( "WARNING: waypointCount is " + level.waypointCount );
if(level.waypointCount != level.waypoints.size) if ( level.waypointCount != level.waypoints.size )
self iprintln("WARNING: waypointCount is not "+level.waypoints.size); self iprintln( "WARNING: waypointCount is not " + level.waypoints.size );
for(i = 0; i < level.waypointCount; i++) for ( i = 0; i < level.waypointCount; i++ )
{ {
if(!isDefined(level.waypoints[i])) if ( !isDefined( level.waypoints[i] ) )
{ {
self iprintln("WARNING: waypoint "+i+" is undefined"); self iprintln( "WARNING: waypoint " + i + " is undefined" );
continue; continue;
} }
if(level.waypoints[i].childCount <= 0) if ( level.waypoints[i].children.size <= 0 )
self iprintln("WARNING: waypoint "+i+" childCount is "+level.waypoints[i].childCount); self iprintln( "WARNING: waypoint " + i + " childCount is " + level.waypoints[i].children.size );
else else
{ {
if (!isDefined(level.waypoints[i].children) || !isDefined(level.waypoints[i].children.size)) if ( !isDefined( level.waypoints[i].children ) || !isDefined( level.waypoints[i].children.size ) )
{ {
self iprintln("WARNING: waypoint "+i+" children is not defined"); self iprintln( "WARNING: waypoint " + i + " children is not defined" );
} }
else else
{ {
if(level.waypoints[i].childCount != level.waypoints[i].children.size) for ( h = level.waypoints[i].children.size - 1; h >= 0; h-- )
self iprintln("WARNING: waypoint "+i+" childCount is not "+level.waypoints[i].children.size);
for (h = 0; h < level.waypoints[i].childCount; h++)
{ {
child = level.waypoints[i].children[h]; child = level.waypoints[i].children[h];
if(!isDefined(level.waypoints[child])) if ( !isDefined( level.waypoints[child] ) )
self iprintln("WARNING: waypoint "+i+" child "+child+" is undefined"); self iprintln( "WARNING: waypoint " + i + " child " + child + " is undefined" );
else if(child == i) else if ( child == i )
self iprintln("WARNING: waypoint "+i+" child "+child+" is itself"); self iprintln( "WARNING: waypoint " + i + " child " + child + " is itself" );
} }
} }
} }
if(!isDefined(level.waypoints[i].type)) if ( !isDefined( level.waypoints[i].type ) )
{ {
self iprintln("WARNING: waypoint "+i+" type is undefined"); self iprintln( "WARNING: waypoint " + i + " type is undefined" );
continue; continue;
} }
if(!isDefined(level.waypoints[i].angles) && (level.waypoints[i].type == "claymore" || level.waypoints[i].type == "tube" || (level.waypoints[i].type == "crouch" && level.waypoints[i].childCount == 1) || level.waypoints[i].type == "climb" || level.waypoints[i].type == "grenade")) if ( !isDefined( level.waypoints[i].angles ) && ( level.waypoints[i].type == "claymore" || level.waypoints[i].type == "tube" || ( level.waypoints[i].type == "crouch" && level.waypoints[i].children.size == 1 ) || level.waypoints[i].type == "climb" || level.waypoints[i].type == "grenade" ) )
self iprintln("WARNING: waypoint "+i+" angles is undefined"); self iprintln( "WARNING: waypoint " + i + " angles is undefined" );
} }
} }
@ -446,40 +455,32 @@ DeleteAllWaypoints()
{ {
level.waypoints = []; level.waypoints = [];
level.waypointCount = 0; level.waypointCount = 0;
level.waypointsKDTree = WaypointsToKDTree();
level.waypointsCamp = []; self iprintln( "DelAllWps" );
level.waypointsTube = [];
level.waypointsGren = [];
level.waypointsClay = [];
self iprintln("DelAllWps");
} }
DeleteWaypoint(nwp) DeleteWaypoint( nwp )
{ {
if(nwp == -1 || distance(self.origin, level.waypoints[nwp].origin) > getDvarFloat("bots_main_debug_minDist")) if ( nwp == -1 || distance( self.origin, level.waypoints[nwp].origin ) > getDvarFloat( "bots_main_debug_minDist" ) )
{ {
self iprintln("No close enough waypoint to delete."); self iprintln( "No close enough waypoint to delete." );
return; return;
} }
level.wpToLink = -1; level.wpToLink = -1;
for(i = 0; i < level.waypoints[nwp].childCount; i++) for ( i = level.waypoints[nwp].children.size - 1; i >= 0; i-- )
{ {
child = level.waypoints[nwp].children[i]; child = level.waypoints[nwp].children[i];
level.waypoints[child].children = array_remove(level.waypoints[child].children, nwp); level.waypoints[child].children = array_remove( level.waypoints[child].children, nwp );
level.waypoints[child].childCount = level.waypoints[child].children.size;
} }
for(i = 0; i < level.waypointCount; i++) for ( i = 0; i < level.waypointCount; i++ )
{ {
for(h = 0; h < level.waypoints[i].childCount; h++) for ( h = level.waypoints[i].children.size - 1; h >= 0; h-- )
{ {
if(level.waypoints[i].children[h] > nwp) if ( level.waypoints[i].children[h] > nwp )
level.waypoints[i].children[h]--; level.waypoints[i].children[h]--;
} }
} }
@ -488,33 +489,35 @@ DeleteWaypoint(nwp)
{ {
if ( entry == nwp ) if ( entry == nwp )
{ {
while ( entry < level.waypointCount-1 ) while ( entry < level.waypointCount - 1 )
{ {
level.waypoints[entry] = level.waypoints[entry+1]; level.waypoints[entry] = level.waypoints[entry + 1];
entry++; entry++;
} }
level.waypoints[entry] = undefined; level.waypoints[entry] = undefined;
break; break;
} }
} }
level.waypointCount--; level.waypointCount--;
self iprintln("DelWp "+nwp); self iprintln( "DelWp " + nwp );
} }
addWaypoint(pos) addWaypoint( pos )
{ {
level.waypoints[level.waypointCount] = spawnstruct(); level.waypoints[level.waypointCount] = spawnstruct();
level.waypoints[level.waypointCount].origin = pos; level.waypoints[level.waypointCount].origin = pos;
if(self AdsButtonPressed()) if ( self AdsButtonPressed() )
level.waypoints[level.waypointCount].type = "climb"; level.waypoints[level.waypointCount].type = "climb";
else if(self AttackButtonPressed() && self UseButtonPressed()) else if ( self AttackButtonPressed() && self UseButtonPressed() )
level.waypoints[level.waypointCount].type = "tube"; level.waypoints[level.waypointCount].type = "tube";
else if(self AttackButtonPressed()) else if ( self AttackButtonPressed() )
level.waypoints[level.waypointCount].type = "grenade"; level.waypoints[level.waypointCount].type = "grenade";
else if(self UseButtonPressed()) else if ( self UseButtonPressed() )
level.waypoints[level.waypointCount].type = "claymore"; level.waypoints[level.waypointCount].type = "claymore";
else else
level.waypoints[level.waypointCount].type = self getStance(); level.waypoints[level.waypointCount].type = self getStance();
@ -522,17 +525,16 @@ addWaypoint(pos)
level.waypoints[level.waypointCount].angles = self getPlayerAngles(); level.waypoints[level.waypointCount].angles = self getPlayerAngles();
level.waypoints[level.waypointCount].children = []; level.waypoints[level.waypointCount].children = [];
level.waypoints[level.waypointCount].childCount = 0;
self iprintln(level.waypoints[level.waypointCount].type + " Waypoint "+ level.waypointCount +" Added at "+pos); self iprintln( level.waypoints[level.waypointCount].type + " Waypoint " + level.waypointCount + " Added at " + pos );
if(level.autoLink) if ( level.autoLink )
{ {
if(level.wpToLink == -1) if ( level.wpToLink == -1 )
level.wpToLink = level.waypointCount - 1; level.wpToLink = level.waypointCount - 1;
level.waypointCount++; level.waypointCount++;
self LinkWaypoint(level.waypointCount - 1); self LinkWaypoint( level.waypointCount - 1 );
} }
else else
{ {
@ -540,62 +542,61 @@ addWaypoint(pos)
} }
} }
UnLinkWaypoint(nwp) UnLinkWaypoint( nwp )
{ {
if(nwp == -1 || distance(self.origin, level.waypoints[nwp].origin) > getDvarFloat("bots_main_debug_minDist")) if ( nwp == -1 || distance( self.origin, level.waypoints[nwp].origin ) > getDvarFloat( "bots_main_debug_minDist" ) )
{ {
self iprintln("Waypoint Unlink Cancelled "+level.wpToLink); self iprintln( "Waypoint Unlink Cancelled " + level.wpToLink );
level.wpToLink = -1; level.wpToLink = -1;
return; return;
} }
if(level.wpToLink == -1 || nwp == level.wpToLink) if ( level.wpToLink == -1 || nwp == level.wpToLink )
{ {
level.wpToLink = nwp; level.wpToLink = nwp;
self iprintln("Waypoint Unlink Started "+nwp); self iprintln( "Waypoint Unlink Started " + nwp );
return; return;
} }
level.waypoints[nwp].children = array_remove(level.waypoints[nwp].children, level.wpToLink); level.waypoints[nwp].children = array_remove( level.waypoints[nwp].children, level.wpToLink );
level.waypoints[level.wpToLink].children = array_remove(level.waypoints[level.wpToLink].children, nwp); level.waypoints[level.wpToLink].children = array_remove( level.waypoints[level.wpToLink].children, nwp );
level.waypoints[nwp].childCount = level.waypoints[nwp].children.size; self iprintln( "Waypoint " + nwp + " Broken to " + level.wpToLink );
level.waypoints[level.wpToLink].childCount = level.waypoints[level.wpToLink].children.size;
self iprintln("Waypoint " + nwp + " Broken to " + level.wpToLink);
level.wpToLink = -1; level.wpToLink = -1;
} }
LinkWaypoint(nwp) LinkWaypoint( nwp )
{ {
if(nwp == -1 || distance(self.origin, level.waypoints[nwp].origin) > getDvarFloat("bots_main_debug_minDist")) if ( nwp == -1 || distance( self.origin, level.waypoints[nwp].origin ) > getDvarFloat( "bots_main_debug_minDist" ) )
{ {
self iprintln("Waypoint Link Cancelled "+level.wpToLink); self iprintln( "Waypoint Link Cancelled " + level.wpToLink );
level.wpToLink = -1; level.wpToLink = -1;
return; return;
} }
if(level.wpToLink == -1 || nwp == level.wpToLink) if ( level.wpToLink == -1 || nwp == level.wpToLink )
{ {
level.wpToLink = nwp; level.wpToLink = nwp;
self iprintln("Waypoint Link Started "+nwp); self iprintln( "Waypoint Link Started " + nwp );
return; return;
} }
weGood = true; weGood = true;
for(i = 0; i < level.waypoints[level.wpToLink].childCount; i++)
for ( i = level.waypoints[level.wpToLink].children.size - 1; i >= 0; i-- )
{ {
if(level.waypoints[level.wpToLink].children[i] == nwp) if ( level.waypoints[level.wpToLink].children[i] == nwp )
{ {
weGood = false; weGood = false;
break; break;
} }
} }
if(weGood)
if ( weGood )
{ {
for(i = 0; i < level.waypoints[nwp].childCount; i++) for ( i = level.waypoints[nwp].children.size - 1; i >= 0; i-- )
{ {
if(level.waypoints[nwp].children[i] == level.wpToLink) if ( level.waypoints[nwp].children[i] == level.wpToLink )
{ {
weGood = false; weGood = false;
break; break;
@ -603,47 +604,45 @@ LinkWaypoint(nwp)
} }
} }
if (!weGood ) if ( !weGood )
{ {
self iprintln("Waypoint Link Cancelled "+nwp+" and "+level.wpToLink+" already linked."); self iprintln( "Waypoint Link Cancelled " + nwp + " and " + level.wpToLink + " already linked." );
level.wpToLink = -1; level.wpToLink = -1;
return; return;
} }
level.waypoints[level.wpToLink].children[level.waypoints[level.wpToLink].childcount] = nwp; level.waypoints[level.wpToLink].children[level.waypoints[level.wpToLink].children.size] = nwp;
level.waypoints[level.wpToLink].childcount++; level.waypoints[nwp].children[level.waypoints[nwp].children.size] = level.wpToLink;
level.waypoints[nwp].children[level.waypoints[nwp].childcount] = level.wpToLink;
level.waypoints[nwp].childcount++;
self iprintln("Waypoint " + nwp + " Linked to " + level.wpToLink); self iprintln( "Waypoint " + nwp + " Linked to " + level.wpToLink );
level.wpToLink = -1; level.wpToLink = -1;
} }
destroyOnDeath(hud) destroyOnDeath( hud )
{ {
hud endon("death"); hud endon( "death" );
self waittill_either("death","disconnect"); self waittill_either( "death", "disconnect" );
hud destroy(); hud destroy();
} }
textScroll(string) textScroll( string )
{ {
self endon("death"); self endon( "death" );
self endon("disconnect"); self endon( "disconnect" );
//thanks ActionScript //thanks ActionScript
back = createBar((0,0,0), 1000, 30); back = createBar( ( 0, 0, 0 ), 1000, 30 );
back setPoint("CENTER", undefined, 0, 220); back setPoint( "CENTER", undefined, 0, 220 );
self thread destroyOnDeath(back); self thread destroyOnDeath( back );
text = createFontString("default", 1.5); text = createFontString( "default", 1.5 );
text setText(string); text setText( string );
self thread destroyOnDeath(text); self thread destroyOnDeath( text );
for (;;) for ( ;; )
{ {
text setPoint("CENTER", undefined, 1200, 220); text setPoint( "CENTER", undefined, 1200, 220 );
text setPoint("CENTER", undefined, -1200, 220, 20); text setPoint( "CENTER", undefined, -1200, 220, 20 );
wait 20; wait 20;
} }
} }

View File

@ -1,4 +1,4 @@
# CoD4x Bot Warfare # CoD4x Bot Warfare v2.1.0
Bot Warfare is a GSC mod for the CoD4x project. Bot Warfare is a GSC mod for the CoD4x project.
It aims to add playable AI to the multiplayer games of CoD4. It aims to add playable AI to the multiplayer games of CoD4.
@ -12,7 +12,7 @@ Make sure to disable this DVAR by adding 'set bots_main_firstIsHost 0' in your s
## Installation ## Installation
0. Make sure that CoD4x server + client is installed, updated and working properly. 0. Make sure that CoD4x server + client is installed, updated and working properly.
- Go to https://cod4x.me/ and download the Windows Server zip file. Move the contents of 'cod4x-windows-server' into your CoD4 game folder. - Go to https://cod4x.ovh/ and download the Windows Server zip file. Move the contents of 'cod4x-windows-server' into your CoD4 game folder.
1. Locate your CoD4x server install folder. 1. Locate your CoD4x server install folder.
2. Move the files/folders found in 'Add to root of CoD4x server' from the Bot Warfare release archive you downloaded to the root of your CoD4x server folder. 2. Move the files/folders found in 'Add to root of CoD4x server' from the Bot Warfare release archive you downloaded to the root of your CoD4x server folder.
- The folder/file structure should follow as '.CoD4x server folder\main_shared\maps\mp\bots\_bot.gsc'. - The folder/file structure should follow as '.CoD4x server folder\main_shared\maps\mp\bots\_bot.gsc'.
@ -30,6 +30,17 @@ Make sure to disable this DVAR by adding 'set bots_main_firstIsHost 0' in your s
- Pressing the menu button again closes menus. - Pressing the menu button again closes menus.
## Changelog ## Changelog
- v2.1.0
- Bot chatter system, bots_main_chat
- Greatly reduce script variable usage
- Improved bots mantling and stuck
- Fix some runtime errors
- Bots sprint more
- Improved bots sight on enemies
- Bots do random actions while waiting at an objective
- Improved bots from getting stuck
- Better bot difficulty management, bots_skill_min and bots_skill_max
- v2.0.1 - v2.0.1
- Reduced bots crouching - Reduced bots crouching
- Increased bots sprinting - Increased bots sprinting

BIN
out/ss.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 MiB