Compare commits

..

No commits in common. "master" and "v2.2.0" have entirely different histories.

15 changed files with 155 additions and 434 deletions

View File

@ -13,9 +13,7 @@ jobs:
- name: Setup gsc-tool - name: Setup gsc-tool
uses: xensik/setup-gsc-tool@v1 uses: xensik/setup-gsc-tool@v1
with:
version: '1.4.0'
- name: Compile test script - name: Compile test script
run: | run: |
gsc-tool.exe -m parse -g iw5 -s pc . gsc-tool.exe parse iw5 pc .

View File

@ -84,20 +84,19 @@ You can easily setup a local LAN dedicated server for you to join and play on. H
| bots_main_GUIDs | A comma separated list of GUIDs of players who will be given host. | | | bots_main_GUIDs | A comma separated list of GUIDs of players who will be given host. | |
| bots_main_waitForHostTime | How many seconds to wait for the host player to connect before adding bots to the match. | 10 | | bots_main_waitForHostTime | How many seconds to wait for the host player to connect before adding bots to the match. | 10 |
| bots_main_menu | Enable the in-game menu for hosts. | 1 | | bots_main_menu | Enable the in-game menu for hosts. | 1 |
| bots_main_debug | Enable the in-game waypoint editor at start of the game, or enable bot event prints. <ul><li>`0` - disable</li><li>`1` - for just debug events</li><li>`2` - for every event</li><ul> | 0 | | bots_main_debug | Enable the in-game waypoint editor. | 0 |
| bots_main_kickBotsAtEnd | Kick the bots at the end of a match. | 0 | | bots_main_kickBotsAtEnd | Kick the bots at the end of a match. | 0 |
| bots_main_chat | The rate bots will chat at, set to 0 to disable. | 1.0 | | 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><li>`2` - exactly `0` but auto adjusts `bots_manage_fill` to map.</li><li>`3` - exactly `1` but auto adjusts `bots_manage_fill` to map.</li><li>`4` - bots are used for balancing teams.</li><li>`5` - exactly `4` but auto adjusts `bots_manage_fill` to map.</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 |
| bots_manage_fill_watchplayers | Bots will not be added until one player is in the game | 0 |
| bots_manage_fill_kick | If the amount of players/bots in the match exceeds `bots_manage_fill`, kick bots until no longer exceeds. | 0 | | bots_manage_fill_kick | If the amount of players/bots in the match exceeds `bots_manage_fill`, kick bots until no longer exceeds. | 0 |
| bots_manage_fill_spec | If when counting players for `bots_manage_fill` should include spectators. | 1 | | bots_manage_fill_spec | If when counting players for `bots_manage_fill` should include spectators. | 1 |
| bots_team | One of `autoassign`, `allies`, `axis`, `spectator`, or `custom`. What team the bots should be on. | autoassign | | bots_team | One of `autoassign`, `allies`, `axis`, `spectator`, or `custom`. What team the bots should be on. | autoassign |
| bots_team_amount | When `bots_team` is set to `custom`. The amount of bots to be placed on the axis team. The remainder will be placed on the allies team. | 0 | | bots_team_amount | When `bots_team` is set to `custom`. The amount of bots to be placed on the axis team. The remainder will be placed on the allies team. | 0 |
| bots_team_force | If the server should force bots' teams according to the `bots_team` value. When `bots_team` is `autoassign`, unbalanced teams will be balanced. This dvar is ignored when `bots_team` is `custom`. | 0 | | bots_team_force | If the server should force bots' teams according to the `bots_team` value. When `bots_team` is `autoassign`, unbalanced teams will be balanced. This dvar is ignored when `bots_team` is `custom`. | 0 |
| bots_team_mode | When `bots_team_force` is `1` and `bots_team` is `autoassign`, players/bots counting method. <ul><li>`0` - counts both players and bots.</li><li>`1` - only counts bots</li></ul> | 0 | | bots_team_mode | When `bots_team_force` is `true` and `bots_team` is `autoassign`, players/bots counting method. <ul><li>`0` - counts both players and bots.</li><li>`1` - only counts bots</li></ul> | 0 |
| bots_skill | Bots' difficulty.<ul><li>`0` - Random difficulty for each bot.</li><li>`1` - Easiest difficulty for all bots.</li><li>`2` to `6` - Between easy and hard difficulty for all bots.</li><li>`7` - The hardest difficulty for all bots.</li><li>`8` - custom (look at the `bots_skill_<team>_<difficulty>` dvars)</li><li>`9` - Every difficulty parameter is randomized</li></ul> | 0 | | bots_skill | Bots' difficulty.<ul><li>`0` - Random difficulty for each bot.</li><li>`1` - Easiest difficulty for all bots.</li><li>`2` to `6` - Between easy and hard difficulty for all bots.</li><li>`7` - The hardest difficulty for all bots.</li><li>`8` - custom (look at the `bots_skill_<team>_<difficulty>` dvars)</li></ul> | 0 |
| bots_skill_axis_hard | When `bots_skill` is set to `8`, the amount of hard difficulty bots to set on the axis team. | 0 | | bots_skill_axis_hard | When `bots_skill` is set to `8`, the amount of hard difficulty bots to set on the axis team. | 0 |
| bots_skill_axis_med | When `bots_skill` is set to `8`, the amount of medium difficulty bots to set on the axis team. The remaining bots on the team will be set to easy difficulty. | 0 | | bots_skill_axis_med | When `bots_skill` is set to `8`, the amount of medium difficulty bots to set on the axis team. The remaining bots on the team will be set to easy difficulty. | 0 |
| bots_skill_allies_hard | When `bots_skill` is set to `8`, the amount of hard difficulty bots to set on the allies team. | 0 | | bots_skill_allies_hard | When `bots_skill` is set to `8`, the amount of hard difficulty bots to set on the allies team. | 0 |
@ -121,13 +120,6 @@ You can easily setup a local LAN dedicated server for you to join and play on. H
## Changelog ## Changelog
- v2.3.0 (not released yet)
- Smoothed bot aim at range
- Fixed bots_manage_fill_spec players being counted with bots_manage_fill_mode 1 (bot only)
- Added bots_manage_fill_watchplayers dvar
- Bots hop off turrets if they get stuck on one
- Fixed script variable leak with opening and closing the in-game menu
- v2.2.0 - v2.2.0
- Fixed some chat related script runtime errors - Fixed some chat related script runtime errors
- Waypoints only load from csv now - Waypoints only load from csv now

View File

@ -8,7 +8,7 @@
*/ */
init() init()
{ {
level.bw_version = "2.3.0"; level.bw_version = "2.1.0";
if ( getdvar( "bots_main" ) == "" ) if ( getdvar( "bots_main" ) == "" )
{ {
@ -74,11 +74,6 @@ init()
setdvar( "bots_manage_fill_kick", false ); // kick bots if too many setdvar( "bots_manage_fill_kick", false ); // kick bots if too many
} }
if ( getdvar( "bots_manage_fill_watchplayers" ) == "" )
{
setdvar( "bots_manage_fill_watchplayers", false ); // add bots when player exists, kick if not
}
if ( getdvar( "bots_team" ) == "" ) if ( getdvar( "bots_team" ) == "" )
{ {
setdvar( "bots_team", "autoassign" ); // which team for bots to join setdvar( "bots_team", "autoassign" ); // which team for bots to join
@ -212,11 +207,8 @@ init()
if ( !isdefined( game[ "botWarfare" ] ) ) if ( !isdefined( game[ "botWarfare" ] ) )
{ {
game[ "botWarfare" ] = true; game[ "botWarfare" ] = true;
game[ "botWarfareInitTime" ] = gettime();
} }
level.bot_inittime = gettime();
level.defuseobject = undefined; level.defuseobject = undefined;
level.bots_smokelist = List(); level.bots_smokelist = List();
level.tbl_perkdata[ 0 ][ "reference_full" ] = true; level.tbl_perkdata[ 0 ][ "reference_full" ] = true;
@ -270,9 +262,6 @@ init()
level thread onPlayerConnect(); level thread onPlayerConnect();
level thread handleBots(); level thread handleBots();
level thread onPlayerChat();
array_thread( getentarray( "misc_turret", "classname" ), ::turret_monitoruse_watcher );
} }
/* /*
@ -451,23 +440,6 @@ fixPerksAndScriptKick()
self.pers[ "isBot" ] = true; self.pers[ "isBot" ] = true;
} }
/*
When a bot disconnects.
*/
onDisconnectPlayer()
{
name = self.name;
self waittill( "disconnect" );
waittillframeend;
for ( i = 0; i < level.bots.size; i++ )
{
bot = level.bots[ i ];
bot BotNotifyBotEvent( "connection", "disconnected", self, name );
}
}
/* /*
When a bot disconnects. When a bot disconnects.
*/ */
@ -485,14 +457,6 @@ connected()
{ {
self endon( "disconnect" ); self endon( "disconnect" );
for ( i = 0; i < level.bots.size; i++ )
{
bot = level.bots[ i ];
bot BotNotifyBotEvent( "connection", "connected", self, self.name );
}
self thread onDisconnectPlayer();
if ( !isdefined( self.pers[ "bot_host" ] ) ) if ( !isdefined( self.pers[ "bot_host" ] ) )
{ {
self thread doHostCheck(); self thread doHostCheck();
@ -522,10 +486,10 @@ connected()
level.bots[ level.bots.size ] = self; level.bots[ level.bots.size ] = self;
self thread onDisconnect(); self thread onDisconnect();
self thread watchBotDebugEvent();
waittillframeend; // wait for waittills to process
level notify( "bot_connected", self ); level notify( "bot_connected", self );
self thread watchBotDebugEvent();
} }
/* /*
@ -938,7 +902,7 @@ addBots_loop()
fillMode = getdvarint( "bots_manage_fill_mode" ); fillMode = getdvarint( "bots_manage_fill_mode" );
if ( fillMode == 2 || fillMode == 3 || fillMode == 5 ) if ( fillMode == 2 || fillMode == 3 )
{ {
setdvar( "bots_manage_fill", getGoodMapAmount() ); setdvar( "bots_manage_fill", getGoodMapAmount() );
} }
@ -948,8 +912,6 @@ addBots_loop()
players = 0; players = 0;
bots = 0; bots = 0;
spec = 0; spec = 0;
axisplayers = 0;
alliesplayers = 0;
playercount = level.players.size; playercount = level.players.size;
@ -968,21 +930,7 @@ addBots_loop()
else else
{ {
players++; players++;
if ( player.pers[ "team" ] == "axis" )
{
axisplayers++;
} }
else if ( player.pers[ "team" ] == "allies" )
{
alliesplayers++;
}
}
}
if ( getdvarint( "bots_manage_fill_spec" ) )
{
players += spec;
} }
if ( !randomint( 999 ) ) if ( !randomint( 999 ) )
@ -993,6 +941,58 @@ addBots_loop()
doExtraCheck(); doExtraCheck();
} }
if ( fillMode == 4 )
{
axisplayers = 0;
alliesplayers = 0;
playercount = level.players.size;
for ( i = 0; i < playercount; i++ )
{
player = level.players[ i ];
if ( player is_bot() )
{
continue;
}
if ( !isdefined( player.pers[ "team" ] ) )
{
continue;
}
if ( player.pers[ "team" ] == "axis" )
{
axisplayers++;
}
else if ( player.pers[ "team" ] == "allies" )
{
alliesplayers++;
}
}
result = fillAmount - abs( axisplayers - alliesplayers ) + bots;
if ( players == 0 )
{
if ( bots < fillAmount )
{
result = fillAmount - 1;
}
else if ( bots > fillAmount )
{
result = fillAmount + 1;
}
else
{
result = fillAmount;
}
}
bots = result;
}
amount = bots; amount = bots;
if ( fillMode == 0 || fillMode == 2 ) if ( fillMode == 0 || fillMode == 2 )
@ -1000,46 +1000,22 @@ addBots_loop()
amount += players; amount += players;
} }
// use bots as balance if ( getdvarint( "bots_manage_fill_spec" ) )
if ( fillMode == 4 || fillMode == 5 )
{ {
diffPlayers = abs( alliesplayers - axisplayers ); amount += spec;
amount = fillAmount - ( diffPlayers - bots );
if ( players + diffPlayers < fillAmount )
{
amount = players + bots;
}
}
if ( players <= 0 && getdvarint( "bots_manage_fill_watchplayers" ) )
{
amount = fillAmount + bots;
} }
if ( amount < fillAmount ) if ( amount < fillAmount )
{ {
setdvar( "bots_manage_add", fillAmount - amount ); setdvar( "bots_manage_add", 1 );
} }
else if ( amount > fillAmount && getdvarint( "bots_manage_fill_kick" ) ) else if ( amount > fillAmount && getdvarint( "bots_manage_fill_kick" ) )
{
botsToKick = amount - fillAmount;
if ( botsToKick > 64 )
{
botsToKick = 64;
}
for ( i = 0; i < botsToKick; i++ )
{ {
tempBot = getBotToKick(); tempBot = getBotToKick();
if ( isdefined( tempBot ) ) if ( isdefined( tempBot ) )
{ {
kick( tempBot getentitynumber(), "EXE_PLAYERKICKED" ); kick( tempBot getentitynumber() );
wait 0.25;
}
} }
} }
} }
@ -1271,65 +1247,3 @@ doFiringThread()
wait 1; wait 1;
self.bots_firing = false; self.bots_firing = false;
} }
/*
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 );
}
}
}
/*
Monitors turret usage
*/
turret_monitoruse_watcher()
{
self endon( "death" );
for ( ;; )
{
self waittill ( "trigger", player );
self monitor_player_turret( player );
self.owner = undefined;
if ( isdefined( player ) )
{
player.turret = undefined;
}
}
}
/*
While player uses turret
*/
monitor_player_turret( player )
{
player endon( "death" );
player endon( "disconnect" );
player.turret = self;
self.owner = player;
while ( isdefined( player ) && player usebuttonpressed() )
{
wait 0.05;
}
while ( isdefined( player ) && !player usebuttonpressed() )
{
wait 0.05;
}
}

View File

@ -252,43 +252,10 @@ start_chat_watch()
case "sd": case "sd":
self thread bot_chat_sd_watch( a, b, c, d, e, f, g ); self thread bot_chat_sd_watch( a, b, c, d, e, f, g );
break; break;
case "connection":
self thread bot_chat_connection_player_watch( a, b, c, d, e, f, g );
break;
case "chat":
self thread bot_chat_chat_player_watch( a, b, c, d, e, f, g );
break;
} }
} }
} }
/*
When another player chats
*/
bot_chat_chat_player_watch( chatstr, message, player, is_hidden, e, f, g )
{
self endon( "disconnect" );
}
/*
When a player connected
*/
bot_chat_connection_player_watch( conn, player, playername, d, e, f, g )
{
self endon( "disconnect" );
switch ( conn )
{
case "connected":
break;
case "disconnected":
break;
}
}
/* /*
start_startgame_watch start_startgame_watch
*/ */

View File

@ -251,13 +251,6 @@ watchPickupGun()
continue; continue;
} }
// todo have bots use turrets instead of just kicking them off of it
if ( isdefined( self.turret ) )
{
self thread use( 0.5 );
continue;
}
weap = self getcurrentweapon(); weap = self getcurrentweapon();
if ( weap != "none" && self getammocount( weap ) ) if ( weap != "none" && self getammocount( weap ) )
@ -492,7 +485,7 @@ IsWeapSniper( weap )
return false; return false;
} }
if ( getweaponclass( weap ) != "weapon_sniper" ) if ( maps\mp\gametypes\_missions::getweaponclass( weap ) != "weapon_sniper" )
{ {
return false; return false;
} }
@ -563,12 +556,6 @@ onWeaponChange()
{ {
first = false; first = false;
newWeapon = self getcurrentweapon(); newWeapon = self getcurrentweapon();
// hack fix for botstop overridding weapon
if ( newWeapon != "none" )
{
self switchtoweapon( newWeapon );
}
} }
else else
{ {
@ -916,14 +903,12 @@ updateBones()
self endon( "disconnect" ); self endon( "disconnect" );
self endon( "death" ); self endon( "death" );
bones = strtok( self.pers[ "bots" ][ "skill" ][ "bones" ], "," );
waittime = self.pers[ "bots" ][ "skill" ][ "bone_update_interval" ];
for ( ;; ) for ( ;; )
{ {
oldbones = self.pers[ "bots" ][ "skill" ][ "bones" ]; self waittill_notify_or_timeout( "new_enemy", waittime );
bones = strtok( oldbones, "," );
while ( oldbones == self.pers[ "bots" ][ "skill" ][ "bones" ] )
{
self waittill_notify_or_timeout( "new_enemy", self.pers[ "bots" ][ "skill" ][ "bone_update_interval" ] );
if ( !isdefined( self.bot.target ) ) if ( !isdefined( self.bot.target ) )
{ {
@ -933,7 +918,6 @@ updateBones()
self.bot.target.bone = random( bones ); self.bot.target.bone = random( bones );
} }
} }
}
/* /*
Creates the base target obj Creates the base target obj
@ -1040,23 +1024,6 @@ targetObjUpdateNoTrace( obj )
obj.didlook = false; obj.didlook = false;
} }
/*
Returns true if myEye can see the bone of self
*/
checkTraceForBone( myEye, bone )
{
boneLoc = self gettagorigin( bone );
if ( !isdefined( boneLoc ) )
{
return false;
}
trace = bullettrace( myEye, boneLoc, false, undefined );
return ( sighttracepassed( myEye, boneLoc, false, undefined ) && ( trace[ "fraction" ] >= 1.0 || trace[ "surfacetype" ] == "glass" ) );
}
/* /*
The main target thread, will update the bot's main target. Will auto target enemy players and handle script targets. The main target thread, will update the bot's main target. Will auto target enemy players and handle script targets.
*/ */
@ -1168,9 +1135,21 @@ target_loop()
continue; continue;
} }
canTargetPlayer = ( ( player checkTraceForBone( myEye, "j_head" ) || targetHead = player gettagorigin( "j_head" );
player checkTraceForBone( myEye, "j_ankle_le" ) || targetAnkleLeft = player gettagorigin( "j_ankle_le" );
player checkTraceForBone( myEye, "j_ankle_ri" ) ) targetAnkleRight = player gettagorigin( "j_ankle_ri" );
traceHead = bullettrace( myEye, targetHead, false, undefined );
traceAnkleLeft = bullettrace( myEye, targetAnkleLeft, false, undefined );
traceAnkleRight = bullettrace( myEye, targetAnkleRight, false, undefined );
canTargetPlayer = ( ( sighttracepassed( myEye, targetHead, false, undefined ) ||
sighttracepassed( myEye, targetAnkleLeft, false, undefined ) ||
sighttracepassed( myEye, targetAnkleRight, false, undefined ) )
&& ( ( traceHead[ "fraction" ] >= 1.0 || traceHead[ "surfacetype" ] == "glass" ) ||
( traceAnkleLeft[ "fraction" ] >= 1.0 || traceAnkleLeft[ "surfacetype" ] == "glass" ) ||
( traceAnkleRight[ "fraction" ] >= 1.0 || traceAnkleRight[ "surfacetype" ] == "glass" ) )
&& ( SmokeTrace( myEye, player.origin, level.smokeradius ) || && ( SmokeTrace( myEye, player.origin, level.smokeradius ) ||
daDist < level.bots_maxknifedistance * 4 ) daDist < level.bots_maxknifedistance * 4 )
@ -1529,7 +1508,7 @@ aim_loop()
} }
else if ( curweap != "none" && weaponclass( curweap ) == "grenade" ) else if ( curweap != "none" && weaponclass( curweap ) == "grenade" )
{ {
if ( getweaponclass( curweap ) == "weapon_projectile" ) if ( maps\mp\gametypes\_missions::getweaponclass( curweap ) == "weapon_projectile" )
{ {
nadeAimOffset = dist / 16000; nadeAimOffset = dist / 16000;
} }
@ -1603,11 +1582,11 @@ aim_loop()
conedot = getConeDot( aimpos, eyePos, angles ); conedot = getConeDot( aimpos, eyePos, angles );
if ( isdefined( self.bot.knifing_target ) && self.bot.knifing_target == target ) if ( isdefined( self.bot.knifing_target ) )
{ {
self thread bot_lookat( target gettagorigin( "j_spine4" ), 0.05 ); self thread bot_lookat( target gettagorigin( "j_spine4" ), 0.05 );
} }
else if ( !nadeAimOffset && conedot > 0.999995 && lengthsquared( aimoffset ) < 0.05 ) else if ( !nadeAimOffset && conedot > 0.999 && lengthsquared( aimoffset ) < 0.05 )
{ {
self thread bot_lookat( aimpos, 0.05 ); self thread bot_lookat( aimpos, 0.05 );
} }
@ -1625,7 +1604,7 @@ aim_loop()
conedot = getConeDot( aimpos, eyePos, angles ); conedot = getConeDot( aimpos, eyePos, angles );
if ( !nadeAimOffset && conedot > 0.999995 && lengthsquared( aimoffset ) < 0.05 ) if ( !nadeAimOffset && conedot > 0.999 && lengthsquared( aimoffset ) < 0.05 )
{ {
self thread bot_lookat( aimpos, 0.05 ); self thread bot_lookat( aimpos, 0.05 );
} }
@ -1701,7 +1680,7 @@ aim_loop()
} }
else if ( curweap != "none" && weaponclass( curweap ) == "grenade" ) else if ( curweap != "none" && weaponclass( curweap ) == "grenade" )
{ {
if ( getweaponclass( curweap ) == "weapon_projectile" ) if ( maps\mp\gametypes\_missions::getweaponclass( curweap ) == "weapon_projectile" )
{ {
nadeAimOffset = dist / 16000; nadeAimOffset = dist / 16000;
} }
@ -1794,7 +1773,6 @@ aim()
for ( ;; ) for ( ;; )
{ {
wait 0.05; wait 0.05;
waittillframeend;
if ( level.inprematchperiod || level.gameended || self.bot.isfrozen || self maps\mp\_flashgrenades::isflashbanged() ) if ( level.inprematchperiod || level.gameended || self.bot.isfrozen || self maps\mp\_flashgrenades::isflashbanged() )
{ {
@ -1976,9 +1954,9 @@ walk_loop()
dist = 16; dist = 16;
if ( level.waypoints.size ) if ( level.waypointcount )
{ {
goal = level.waypoints[ randomint( level.waypoints.size ) ].origin; goal = level.waypoints[ randomint( level.waypointcount ) ].origin;
} }
else else
{ {
@ -2865,7 +2843,7 @@ bot_lookat( pos, time, vel, doAimPredict )
for ( i = 0; i < steps; i++ ) for ( i = 0; i < steps; i++ )
{ {
myAngle = ( angleclamp180( myAngle[ 0 ] + X ), angleclamp180( myAngle[ 1 ] + Y ), 0 ); myAngle = ( angleclamp180( myAngle[ 0 ] + X ), angleclamp180( myAngle[ 1 ] + Y ), 0 );
self BotBuiltinBotAngles( myAngle ); self setplayerangles( myAngle );
wait 0.05; wait 0.05;
} }
} }

View File

@ -347,21 +347,6 @@ classWatch()
if ( !maps\mp\gametypes\_globallogic::isvalidclass( self.class ) || !isdefined( self.bot_change_class ) ) if ( !maps\mp\gametypes\_globallogic::isvalidclass( self.class ) || !isdefined( self.bot_change_class ) )
{ {
// mod warfare shtuff
if ( isdefined( level.serverdvars ) )
{
a = [];
a[ a.size ] = "assault";
a[ a.size ] = "specops";
a[ a.size ] = "heavygunner";
a[ a.size ] = "demolitions";
a[ a.size ] = "sniper";
self notify( "menuresponse", game[ "menu_changeclass_" + self.pers[ "team" ] ], random( a ) );
wait 0.5;
}
self notify( "menuresponse", game[ "menu_changeclass" ], self chooseRandomClass() ); self notify( "menuresponse", game[ "menu_changeclass" ], self chooseRandomClass() );
} }
@ -1572,7 +1557,7 @@ bot_think_camp_loop()
self SetScriptGoal( campSpot.origin, 16 ); self SetScriptGoal( campSpot.origin, 16 );
time = randomintrange( 30, 90 ); time = randomintrange( 10, 20 );
self BotNotifyBotEvent( "camp", "go", campSpot, time ); self BotNotifyBotEvent( "camp", "go", campSpot, time );
@ -1631,17 +1616,7 @@ killCampAfterTime( time )
self endon( "disconnect" ); self endon( "disconnect" );
self endon( "kill_camp_bot" ); self endon( "kill_camp_bot" );
timeleft = maps\mp\gametypes\_globallogic::gettimeremaining() / 1000; wait time + 0.05;
while ( time > 0 && timeleft >= 60 )
{
wait 1;
timeleft = maps\mp\gametypes\_globallogic::gettimeremaining() / 1000;
time--;
}
wait 0.05;
self ClearScriptGoal(); self ClearScriptGoal();
self ClearScriptAimPos(); self ClearScriptAimPos();
@ -2866,12 +2841,6 @@ bot_killstreak_think_loop()
{ {
curWeap = self getcurrentweapon(); curWeap = self getcurrentweapon();
if ( curWeap == "radar_mp" || curWeap == "helicopter_mp" || curWeap == "airstrike_mp" )
{
self thread changeToWeapon( self.lastdroppableweapon );
return;
}
if ( curWeap == "none" || !isWeaponDroppable( curWeap ) ) if ( curWeap == "none" || !isWeaponDroppable( curWeap ) )
{ {
curWeap = self.lastdroppableweapon; curWeap = self.lastdroppableweapon;

View File

@ -133,17 +133,6 @@ BotBuiltinBotMeleeParams( yaw, dist )
} }
} }
/*
Sets angles
*/
BotBuiltinBotAngles( angles )
{
if ( isdefined( level.bot_builtins ) && isdefined( level.bot_builtins[ "botangles" ] ) )
{
self [[ level.bot_builtins[ "botangles" ] ]]( angles );
}
}
/* /*
Test if is a bot Test if is a bot
*/ */
@ -437,22 +426,12 @@ BotStopMoving( what )
} }
} }
/*
Waits till frame end so that if two notifies happen in the same frame, the other will not be missed.
*/
BotNotifyBotEvent_( msg, a, b, c, d, e, f, g )
{
self endon( "disconnect" );
waittillframeend; // wait for the waittills to setup again
self notify( "bot_event", msg, a, b, c, d, e, f, g );
}
/* /*
Notify the bot chat message Notify the bot chat message
*/ */
BotNotifyBotEvent( msg, a, b, c, d, e, f, g ) BotNotifyBotEvent( msg, a, b, c, d, e, f, g )
{ {
self thread BotNotifyBotEvent_( msg, a, b, c, d, e, f, g ); self notify( "bot_event", msg, a, b, c, d, e, f, g );
} }
/* /*
@ -1050,22 +1029,6 @@ isItemUnlocked( what, lvl )
} }
} }
/*
ModWarfare removes this func from _missions
*/
getweaponclass( weapon )
{
tokens = strtok( weapon, "_" );
weaponClass = tablelookup( "mp/statstable.csv", 4, tokens[ 0 ], 2 );
if ( ismg( weapon ) )
{
weaponClass = "weapon_mg";
}
return weaponClass;
}
/* /*
If the weapon is allowed to be dropped If the weapon is allowed to be dropped
*/ */
@ -1761,6 +1724,7 @@ load_waypoints()
{ {
mapname = getdvar( "mapname" ); mapname = getdvar( "mapname" );
level.waypointcount = 0;
level.waypointusage = []; level.waypointusage = [];
level.waypointusage[ "allies" ] = []; level.waypointusage[ "allies" ] = [];
level.waypointusage[ "axis" ] = []; level.waypointusage[ "axis" ] = [];
@ -1807,7 +1771,9 @@ load_waypoints()
BotBuiltinPrintConsole( "No waypoints loaded!" ); BotBuiltinPrintConsole( "No waypoints loaded!" );
} }
for ( i = level.waypoints.size - 1; i >= 0; i-- ) level.waypointcount = level.waypoints.size;
for ( i = 0; i < level.waypointcount; i++ )
{ {
if ( !isdefined( level.waypoints[ i ].children ) || !isdefined( level.waypoints[ i ].children.size ) ) if ( !isdefined( level.waypoints[ i ].children ) || !isdefined( level.waypoints[ i ].children.size ) )
{ {
@ -1906,7 +1872,7 @@ getWaypointsOfType( type )
{ {
answer = []; answer = [];
for ( i = level.waypoints.size - 1; i >= 0; i-- ) for ( i = 0; i < level.waypointcount; i++ )
{ {
wp = level.waypoints[ i ]; wp = level.waypoints[ i ];
@ -2713,18 +2679,16 @@ RemoveWaypointUsage( wp, team )
return; return;
} }
wpstr = wp + ""; if ( !isdefined( level.waypointusage[ team ][ wp + "" ] ) )
if ( !isdefined( level.waypointusage[ team ][ wpstr ] ) )
{ {
return; return;
} }
level.waypointusage[ team ][ wpstr ]--; level.waypointusage[ team ][ wp + "" ]--;
if ( level.waypointusage[ team ][ wpstr ] <= 0 ) if ( level.waypointusage[ team ][ wp + "" ] <= 0 )
{ {
level.waypointusage[ team ][ wpstr ] = undefined; level.waypointusage[ team ][ wp + "" ] = undefined;
} }
} }
@ -2736,7 +2700,7 @@ GetNearestWaypointWithSight( pos )
candidate = undefined; candidate = undefined;
dist = 2147483647; dist = 2147483647;
for ( i = level.waypoints.size - 1; i >= 0; i-- ) for ( i = 0; i < level.waypointcount; i++ )
{ {
if ( !bullettracepassed( pos + ( 0, 0, 15 ), level.waypoints[ i ].origin + ( 0, 0, 15 ), false, undefined ) ) if ( !bullettracepassed( pos + ( 0, 0, 15 ), level.waypoints[ i ].origin + ( 0, 0, 15 ), false, undefined ) )
{ {
@ -2765,7 +2729,7 @@ getNearestWaypoint( pos )
candidate = undefined; candidate = undefined;
dist = 2147483647; dist = 2147483647;
for ( i = level.waypoints.size - 1; i >= 0; i-- ) for ( i = 0; i < level.waypointcount; i++ )
{ {
curdis = distancesquared( level.waypoints[ i ].origin, pos ); curdis = distancesquared( level.waypoints[ i ].origin, pos );
@ -2850,8 +2814,7 @@ AStarSearch( start, goal, team, greedy_path )
// pop bestnode from queue // pop bestnode from queue
bestNode = open.data[ 0 ]; bestNode = open.data[ 0 ];
open HeapRemove(); open HeapRemove();
bestNodeStr = bestNode.index + ""; openset[ bestNode.index + "" ] = undefined;
openset[ bestNodeStr ] = undefined;
wp = level.waypoints[ bestNode.index ]; wp = level.waypoints[ bestNode.index ];
// check if we made it to the goal // check if we made it to the goal
@ -2861,16 +2824,14 @@ AStarSearch( start, goal, team, greedy_path )
while ( isdefined( bestNode ) ) while ( isdefined( bestNode ) )
{ {
bestNodeStr = bestNode.index + "";
if ( isdefined( team ) && isdefined( level.waypointusage ) ) if ( isdefined( team ) && isdefined( level.waypointusage ) )
{ {
if ( !isdefined( level.waypointusage[ team ][ bestNodeStr ] ) ) if ( !isdefined( level.waypointusage[ team ][ bestNode.index + "" ] ) )
{ {
level.waypointusage[ team ][ bestNodeStr ] = 0; level.waypointusage[ team ][ bestNode.index + "" ] = 0;
} }
level.waypointusage[ team ][ bestNodeStr ]++; level.waypointusage[ team ][ bestNode.index + "" ]++;
} }
// construct path // construct path
@ -2886,7 +2847,6 @@ AStarSearch( start, goal, team, greedy_path )
for ( i = wp.children.size - 1; i >= 0; i-- ) for ( i = wp.children.size - 1; i >= 0; i-- )
{ {
child = wp.children[ i ]; child = wp.children[ i ];
childStr = child + "";
childWp = level.waypoints[ child ]; childWp = level.waypoints[ child ];
penalty = 1; penalty = 1;
@ -2895,9 +2855,9 @@ AStarSearch( start, goal, team, greedy_path )
{ {
temppen = 1; temppen = 1;
if ( isdefined( level.waypointusage[ team ][ childStr ] ) ) if ( isdefined( level.waypointusage[ team ][ child + "" ] ) )
{ {
temppen = level.waypointusage[ team ][ childStr ]; // consider how many bots are taking this path temppen = level.waypointusage[ team ][ child + "" ]; // consider how many bots are taking this path
} }
if ( temppen > 1 ) if ( temppen > 1 )
@ -2916,16 +2876,16 @@ AStarSearch( start, goal, team, greedy_path )
newg = bestNode.g + distancesquared( wp.origin, childWp.origin ) * penalty; // bots on same team's path are more expensive newg = bestNode.g + distancesquared( wp.origin, childWp.origin ) * penalty; // bots on same team's path are more expensive
// check if this child is in open or close with a g value less than newg // check if this child is in open or close with a g value less than newg
inopen = isdefined( openset[ childStr ] ); inopen = isdefined( openset[ child + "" ] );
if ( inopen && openset[ childStr ].g <= newg ) if ( inopen && openset[ child + "" ].g <= newg )
{ {
continue; continue;
} }
inclosed = isdefined( closed[ childStr ] ); inclosed = isdefined( closed[ child + "" ] );
if ( inclosed && closed[ childStr ].g <= newg ) if ( inclosed && closed[ child + "" ].g <= newg )
{ {
continue; continue;
} }
@ -2934,11 +2894,11 @@ AStarSearch( start, goal, team, greedy_path )
if ( inopen ) if ( inopen )
{ {
node = openset[ childStr ]; node = openset[ child + "" ];
} }
else if ( inclosed ) else if ( inclosed )
{ {
node = closed[ childStr ]; node = closed[ child + "" ];
} }
else else
{ {
@ -2954,19 +2914,19 @@ AStarSearch( start, goal, team, greedy_path )
// check if in closed, remove it // check if in closed, remove it
if ( inclosed ) if ( inclosed )
{ {
closed[ childStr ] = undefined; closed[ child + "" ] = undefined;
} }
// check if not in open, add it // check if not in open, add it
if ( !inopen ) if ( !inopen )
{ {
open HeapInsert( node ); open HeapInsert( node );
openset[ childStr ] = node; openset[ child + "" ] = node;
} }
} }
// done with children, push onto closed // done with children, push onto closed
closed[ bestNodeStr ] = bestNode; closed[ bestNode.index + "" ] = bestNode;
} }
return []; return [];

View File

@ -60,6 +60,7 @@ init_menu()
self.menuinit = true; self.menuinit = true;
self.menuopen = false; self.menuopen = false;
self.menu_player = undefined;
self.submenu = "Main"; self.submenu = "Main";
self.curs[ "Main" ][ "X" ] = 0; self.curs[ "Main" ][ "X" ] = 0;
self addOptions(); self addOptions();
@ -74,47 +75,6 @@ init_menu()
self thread doGreetings(); self thread doGreetings();
} }
destroyFixed()
{
if ( !isdefined( self ) )
{
return;
}
self destroy();
}
removeChildFixed( element )
{
temp = [];
for ( i = 0; i < self.children.size ; i++ )
{
if ( isdefined( self.children[ i ] ) && self.children[ i ] != element )
{
self.children[ i ].index = temp.size;
temp[ temp.size ] = self.children[ i ];
}
}
self.children = temp;
}
destroyElemFixed()
{
if ( !isdefined( self ) )
{
return;
}
if ( isdefined( self.parent ) )
{
self.parent removeChildFixed( self );
}
self destroyelem();
}
kill_menu() kill_menu()
{ {
self notify( "bots_kill_menu" ); self notify( "bots_kill_menu" );
@ -133,7 +93,7 @@ watchDisconnect()
{ {
if ( isdefined( self.menutexty[ i ] ) ) if ( isdefined( self.menutexty[ i ] ) )
{ {
self.menutexty[ i ] destroyElemFixed(); self.menutexty[ i ] destroy();
} }
} }
} }
@ -144,7 +104,7 @@ watchDisconnect()
{ {
if ( isdefined( self.menutext[ i ] ) ) if ( isdefined( self.menutext[ i ] ) )
{ {
self.menutext[ i ] destroyElemFixed(); self.menutext[ i ] destroy();
} }
} }
} }
@ -153,18 +113,18 @@ watchDisconnect()
{ {
if ( isdefined( self.menu[ "X" ][ "Shader" ] ) ) if ( isdefined( self.menu[ "X" ][ "Shader" ] ) )
{ {
self.menu[ "X" ][ "Shader" ] destroyElemFixed(); self.menu[ "X" ][ "Shader" ] destroy();
} }
if ( isdefined( self.menu[ "X" ][ "Scroller" ] ) ) if ( isdefined( self.menu[ "X" ][ "Scroller" ] ) )
{ {
self.menu[ "X" ][ "Scroller" ] destroyElemFixed(); self.menu[ "X" ][ "Scroller" ] destroy();
} }
} }
if ( isdefined( self.menuversionhud ) ) if ( isdefined( self.menuversionhud ) )
{ {
self.menuversionhud destroyFixed(); self.menuversionhud destroy();
} }
} }
} }
@ -372,7 +332,7 @@ OpenSub( menu, menu2 )
{ {
if ( isdefined( self.menutext[ i ] ) ) if ( isdefined( self.menutext[ i ] ) )
{ {
self.menutext[ i ] destroyElemFixed(); self.menutext[ i ] destroy();
} }
} }
} }
@ -381,18 +341,18 @@ OpenSub( menu, menu2 )
{ {
if ( isdefined( self.menu[ "X" ][ "Shader" ] ) ) if ( isdefined( self.menu[ "X" ][ "Shader" ] ) )
{ {
self.menu[ "X" ][ "Shader" ] destroyElemFixed(); self.menu[ "X" ][ "Shader" ] destroy();
} }
if ( isdefined( self.menu[ "X" ][ "Scroller" ] ) ) if ( isdefined( self.menu[ "X" ][ "Scroller" ] ) )
{ {
self.menu[ "X" ][ "Scroller" ] destroyElemFixed(); self.menu[ "X" ][ "Scroller" ] destroy();
} }
} }
if ( isdefined( self.menuversionhud ) ) if ( isdefined( self.menuversionhud ) )
{ {
self.menuversionhud destroyFixed(); self.menuversionhud destroy();
} }
for ( i = 0 ; i < self.option[ "Name" ][ self.submenu ].size ; i++ ) for ( i = 0 ; i < self.option[ "Name" ][ self.submenu ].size ; i++ )
@ -442,7 +402,7 @@ OpenSub( menu, menu2 )
{ {
if ( isdefined( self.menutexty[ i ] ) ) if ( isdefined( self.menutexty[ i ] ) )
{ {
self.menutexty[ i ] destroyElemFixed(); self.menutexty[ i ] destroy();
} }
} }
} }
@ -465,12 +425,12 @@ CursMove( direction )
self notify( "scrolled" ); self notify( "scrolled" );
if ( self.submenu == "Main" ) if ( self.submenu == "Main" )
{
if ( isdefined( self.menutext ) )
{ {
self.menu[ "X" ][ "Scroller" ].x = self.menutext[ self.curs[ "Main" ][ "X" ] ].x; self.menu[ "X" ][ "Scroller" ].x = self.menutext[ self.curs[ "Main" ][ "X" ] ].x;
self.menu[ "X" ][ "Scroller" ].y = self.menutext[ self.curs[ "Main" ][ "X" ] ].y; self.menu[ "X" ][ "Scroller" ].y = self.menutext[ self.curs[ "Main" ][ "X" ] ].y;
if ( isdefined( self.menutext ) )
{
for ( i = 0; i < self.menutext.size; i++ ) for ( i = 0; i < self.menutext.size; i++ )
{ {
if ( isdefined( self.menutext[ i ] ) ) if ( isdefined( self.menutext[ i ] ) )
@ -618,7 +578,7 @@ ExitSub()
{ {
if ( isdefined( self.menutexty[ i ] ) ) if ( isdefined( self.menutexty[ i ] ) )
{ {
self.menutexty[ i ] destroyElemFixed(); self.menutexty[ i ] destroy();
} }
} }
} }
@ -643,7 +603,7 @@ ExitMenu()
{ {
if ( isdefined( self.menutext[ i ] ) ) if ( isdefined( self.menutext[ i ] ) )
{ {
self.menutext[ i ] destroyElemFixed(); self.menutext[ i ] destroy();
} }
} }
} }
@ -652,18 +612,18 @@ ExitMenu()
{ {
if ( isdefined( self.menu[ "X" ][ "Shader" ] ) ) if ( isdefined( self.menu[ "X" ][ "Shader" ] ) )
{ {
self.menu[ "X" ][ "Shader" ] destroyElemFixed(); self.menu[ "X" ][ "Shader" ] destroy();
} }
if ( isdefined( self.menu[ "X" ][ "Scroller" ] ) ) if ( isdefined( self.menu[ "X" ][ "Scroller" ] ) )
{ {
self.menu[ "X" ][ "Scroller" ] destroyElemFixed(); self.menu[ "X" ][ "Scroller" ] destroy();
} }
} }
if ( isdefined( self.menuversionhud ) ) if ( isdefined( self.menuversionhud ) )
{ {
self.menuversionhud destroyFixed(); self.menuversionhud destroy();
} }
self.menuopen = false; self.menuopen = false;
@ -768,10 +728,6 @@ addOptions()
_temp = "bots used as team balance"; _temp = "bots used as team balance";
break; break;
case 5:
_temp = "bots used as team balance, adjust to map";
break;
default: default:
_temp = "out of range"; _temp = "out of range";
break; break;
@ -1338,11 +1294,6 @@ man_bots( a, b )
self iprintln( "bot_fill will now use bots as team balance." ); self iprintln( "bot_fill will now use bots as team balance." );
break; break;
case 4:
setdvar( "bots_manage_fill_mode", 5 );
self iprintln( "bot_fill will now use bots as team balance, adjusting to map." );
break;
default: default:
setdvar( "bots_manage_fill_mode", 0 ); setdvar( "bots_manage_fill_mode", 0 );
self iprintln( "bot_fill will now count everyone." ); self iprintln( "bot_fill will now count everyone." );

View File

@ -461,7 +461,6 @@ LoadWaypoints()
self deleteAllWaypoints(); self deleteAllWaypoints();
self iprintlnbold( "Loading WPS..." ); self iprintlnbold( "Loading WPS..." );
load_waypoints(); load_waypoints();
level.waypointcount = level.waypoints.size;
wait 1; wait 1;

View File

@ -17,11 +17,11 @@ CodeCallback_StartGameType()
level.gametypestarted = true; // so we know that the gametype has been started up level.gametypestarted = true; // so we know that the gametype has been started up
level thread scripts\mp\bots_adapter_cod4x::init(); level thread scripts\bots_adapter_cod4x::init();
level thread scripts\mp\bots_chat::init(); level thread scripts\bots_chat::init();
level thread scripts\mp\bots_menu::init(); level thread scripts\bots_menu::init();
level thread scripts\mp\bots_wp_editor::init(); level thread scripts\bots_wp_editor::init();
level thread scripts\mp\bots::init(); level thread scripts\bots::init();
} }
} }

View File

@ -7,7 +7,6 @@ init()
level.bot_builtins[ "botmovement" ] = ::do_botmovement; level.bot_builtins[ "botmovement" ] = ::do_botmovement;
level.bot_builtins[ "botmoveto" ] = ::do_botmoveto; level.bot_builtins[ "botmoveto" ] = ::do_botmoveto;
level.bot_builtins[ "botmeleeparams" ] = ::do_botmeleeparams; level.bot_builtins[ "botmeleeparams" ] = ::do_botmeleeparams;
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_fopen" ] = ::do_fs_fopen;
level.bot_builtins[ "fs_fclose" ] = ::do_fs_fclose; level.bot_builtins[ "fs_fclose" ] = ::do_fs_fclose;
@ -50,12 +49,6 @@ do_botmeleeparams( yaw, dist )
// cod4x removed lunging due to movement exploits // cod4x removed lunging due to movement exploits
} }
do_botangles( angles )
{
self setplayerangles( angles );
// self botangles( angles[ 0 ], angles[ 1 ], angles[ 2 ] );
}
do_isbot() do_isbot()
{ {
return self.isbot; return self.isbot;