They walk bro.

This commit is contained in:
JezuzLizard 2023-04-29 18:11:49 -07:00
parent 1b1c2418ce
commit c0b19f00c7
7 changed files with 1487 additions and 3529 deletions

View File

@ -1,13 +1,13 @@
#include common_scripts\utility; #include common_scripts\utility;
#include maps\_utility; #include maps\_utility;
#include scripts\sp\bots\_bot_utility; #include maps\bots\_bot_utility;
/* /*
Initiates the whole bot scripts. Initiates the whole bot scripts.
*/ */
init() init()
{ {
level.bw_VERSION = "2.1.0"; level.bw_VERSION = "z0.1";
if ( getDvar( "bots_main" ) == "" ) if ( getDvar( "bots_main" ) == "" )
setDvar( "bots_main", true ); setDvar( "bots_main", true );
@ -15,7 +15,7 @@ init()
if ( !getDvarInt( "bots_main" ) ) if ( !getDvarInt( "bots_main" ) )
return; return;
//thread load_waypoints(); //Don't call for now thread load_waypoints();
thread hook_callbacks(); thread hook_callbacks();
if ( getDvar( "bots_main_GUIDs" ) == "" ) if ( getDvar( "bots_main_GUIDs" ) == "" )
@ -144,8 +144,8 @@ onPlayerDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon,
{ {
if ( self is_bot() ) if ( self is_bot() )
{ {
//self scripts\sp\bots\_bot_internal::onDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, iModelIndex, timeOffset ); self maps\bots\_bot_internal::onDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, iModelIndex, timeOffset );
self scripts\sp\bots\_bot_script::onDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, iModelIndex, timeOffset ); self maps\bots\_bot_script::onDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, iModelIndex, timeOffset );
} }
self [[level.prevCallbackPlayerDamage]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, iModelIndex, timeOffset ); self [[level.prevCallbackPlayerDamage]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, iModelIndex, timeOffset );
@ -222,8 +222,8 @@ connected()
self thread added(); self thread added();
} }
self thread scripts\sp\bots\_bot_internal::connected(); self thread maps\bots\_bot_internal::connected();
self thread scripts\sp\bots\_bot_script::connected(); self thread maps\bots\_bot_script::connected();
level.bots[level.bots.size] = self; level.bots[level.bots.size] = self;
self thread onDisconnect(); self thread onDisconnect();
@ -258,8 +258,8 @@ added()
{ {
self endon( "disconnect" ); self endon( "disconnect" );
self thread scripts\sp\bots\_bot_internal::added(); self thread maps\bots\_bot_internal::added();
//self thread scripts\sp\bots\_bot_script::added(); self thread maps\bots\_bot_script::added();
} }
/* /*

1106
maps/bots/_bot_internal.gsc Normal file

File diff suppressed because it is too large Load Diff

315
maps/bots/_bot_script.gsc Normal file
View File

@ -0,0 +1,315 @@
#include common_scripts\utility;
#include maps\_utility;
#include maps\bots\_bot_utility;
/*
When the bot gets added into the game.
*/
added()
{
self endon( "disconnect" );
}
/*
When the bot connects to the game.
*/
connected()
{
self endon( "disconnect" );
self thread difficulty();
self thread onBotSpawned();
self thread onSpawned();
}
/*
The callback for when the bot gets damaged.
*/
onDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, timeOffset )
{
}
/*
Updates the bot's difficulty variables.
*/
difficulty()
{
self endon( "disconnect" );
for ( ;; )
{
if ( GetDvarInt( "bots_skill" ) != 9 )
{
switch ( self.pers["bots"]["skill"]["base"] )
{
case 1:
self.pers["bots"]["skill"]["aim_time"] = 0.6;
self.pers["bots"]["skill"]["init_react_time"] = 1500;
self.pers["bots"]["skill"]["reaction_time"] = 1000;
self.pers["bots"]["skill"]["no_trace_ads_time"] = 500;
self.pers["bots"]["skill"]["no_trace_look_time"] = 600;
self.pers["bots"]["skill"]["remember_time"] = 750;
self.pers["bots"]["skill"]["fov"] = 0.7;
self.pers["bots"]["skill"]["dist_max"] = 2500;
self.pers["bots"]["skill"]["dist_start"] = 1000;
self.pers["bots"]["skill"]["spawn_time"] = 0.75;
self.pers["bots"]["skill"]["help_dist"] = 0;
self.pers["bots"]["skill"]["semi_time"] = 0.9;
self.pers["bots"]["skill"]["shoot_after_time"] = 1;
self.pers["bots"]["skill"]["aim_offset_time"] = 1.5;
self.pers["bots"]["skill"]["aim_offset_amount"] = 4;
self.pers["bots"]["skill"]["bone_update_interval"] = 2;
self.pers["bots"]["skill"]["bones"] = "j_spineupper,j_ankle_le,j_ankle_ri";
self.pers["bots"]["skill"]["ads_fov_multi"] = 0.5;
self.pers["bots"]["skill"]["ads_aimspeed_multi"] = 0.5;
self.pers["bots"]["behavior"]["strafe"] = 0;
self.pers["bots"]["behavior"]["nade"] = 10;
self.pers["bots"]["behavior"]["sprint"] = 30;
self.pers["bots"]["behavior"]["camp"] = 5;
self.pers["bots"]["behavior"]["follow"] = 5;
self.pers["bots"]["behavior"]["crouch"] = 20;
self.pers["bots"]["behavior"]["switch"] = 2;
self.pers["bots"]["behavior"]["class"] = 2;
self.pers["bots"]["behavior"]["jump"] = 0;
break;
case 2:
self.pers["bots"]["skill"]["aim_time"] = 0.55;
self.pers["bots"]["skill"]["init_react_time"] = 1000;
self.pers["bots"]["skill"]["reaction_time"] = 800;
self.pers["bots"]["skill"]["no_trace_ads_time"] = 1000;
self.pers["bots"]["skill"]["no_trace_look_time"] = 1250;
self.pers["bots"]["skill"]["remember_time"] = 1500;
self.pers["bots"]["skill"]["fov"] = 0.65;
self.pers["bots"]["skill"]["dist_max"] = 3000;
self.pers["bots"]["skill"]["dist_start"] = 1500;
self.pers["bots"]["skill"]["spawn_time"] = 0.65;
self.pers["bots"]["skill"]["help_dist"] = 500;
self.pers["bots"]["skill"]["semi_time"] = 0.75;
self.pers["bots"]["skill"]["shoot_after_time"] = 0.75;
self.pers["bots"]["skill"]["aim_offset_time"] = 1;
self.pers["bots"]["skill"]["aim_offset_amount"] = 3;
self.pers["bots"]["skill"]["bone_update_interval"] = 1.5;
self.pers["bots"]["skill"]["bones"] = "j_spineupper,j_ankle_le,j_ankle_ri,j_head";
self.pers["bots"]["skill"]["ads_fov_multi"] = 0.5;
self.pers["bots"]["skill"]["ads_aimspeed_multi"] = 0.5;
self.pers["bots"]["behavior"]["strafe"] = 10;
self.pers["bots"]["behavior"]["nade"] = 15;
self.pers["bots"]["behavior"]["sprint"] = 45;
self.pers["bots"]["behavior"]["camp"] = 5;
self.pers["bots"]["behavior"]["follow"] = 5;
self.pers["bots"]["behavior"]["crouch"] = 15;
self.pers["bots"]["behavior"]["switch"] = 2;
self.pers["bots"]["behavior"]["class"] = 2;
self.pers["bots"]["behavior"]["jump"] = 10;
break;
case 3:
self.pers["bots"]["skill"]["aim_time"] = 0.4;
self.pers["bots"]["skill"]["init_react_time"] = 750;
self.pers["bots"]["skill"]["reaction_time"] = 500;
self.pers["bots"]["skill"]["no_trace_ads_time"] = 1000;
self.pers["bots"]["skill"]["no_trace_look_time"] = 1500;
self.pers["bots"]["skill"]["remember_time"] = 2000;
self.pers["bots"]["skill"]["fov"] = 0.6;
self.pers["bots"]["skill"]["dist_max"] = 4000;
self.pers["bots"]["skill"]["dist_start"] = 2250;
self.pers["bots"]["skill"]["spawn_time"] = 0.5;
self.pers["bots"]["skill"]["help_dist"] = 750;
self.pers["bots"]["skill"]["semi_time"] = 0.65;
self.pers["bots"]["skill"]["shoot_after_time"] = 0.65;
self.pers["bots"]["skill"]["aim_offset_time"] = 0.75;
self.pers["bots"]["skill"]["aim_offset_amount"] = 2.5;
self.pers["bots"]["skill"]["bone_update_interval"] = 1;
self.pers["bots"]["skill"]["bones"] = "j_spineupper,j_spineupper,j_ankle_le,j_ankle_ri,j_head";
self.pers["bots"]["skill"]["ads_fov_multi"] = 0.5;
self.pers["bots"]["skill"]["ads_aimspeed_multi"] = 0.5;
self.pers["bots"]["behavior"]["strafe"] = 20;
self.pers["bots"]["behavior"]["nade"] = 20;
self.pers["bots"]["behavior"]["sprint"] = 50;
self.pers["bots"]["behavior"]["camp"] = 5;
self.pers["bots"]["behavior"]["follow"] = 5;
self.pers["bots"]["behavior"]["crouch"] = 10;
self.pers["bots"]["behavior"]["switch"] = 2;
self.pers["bots"]["behavior"]["class"] = 2;
self.pers["bots"]["behavior"]["jump"] = 25;
break;
case 4:
self.pers["bots"]["skill"]["aim_time"] = 0.3;
self.pers["bots"]["skill"]["init_react_time"] = 600;
self.pers["bots"]["skill"]["reaction_time"] = 400;
self.pers["bots"]["skill"]["no_trace_ads_time"] = 1000;
self.pers["bots"]["skill"]["no_trace_look_time"] = 1500;
self.pers["bots"]["skill"]["remember_time"] = 3000;
self.pers["bots"]["skill"]["fov"] = 0.55;
self.pers["bots"]["skill"]["dist_max"] = 5000;
self.pers["bots"]["skill"]["dist_start"] = 3350;
self.pers["bots"]["skill"]["spawn_time"] = 0.35;
self.pers["bots"]["skill"]["help_dist"] = 1000;
self.pers["bots"]["skill"]["semi_time"] = 0.5;
self.pers["bots"]["skill"]["shoot_after_time"] = 0.5;
self.pers["bots"]["skill"]["aim_offset_time"] = 0.5;
self.pers["bots"]["skill"]["aim_offset_amount"] = 2;
self.pers["bots"]["skill"]["bone_update_interval"] = 0.75;
self.pers["bots"]["skill"]["bones"] = "j_spineupper,j_spineupper,j_ankle_le,j_ankle_ri,j_head,j_head";
self.pers["bots"]["skill"]["ads_fov_multi"] = 0.5;
self.pers["bots"]["skill"]["ads_aimspeed_multi"] = 0.5;
self.pers["bots"]["behavior"]["strafe"] = 30;
self.pers["bots"]["behavior"]["nade"] = 25;
self.pers["bots"]["behavior"]["sprint"] = 55;
self.pers["bots"]["behavior"]["camp"] = 5;
self.pers["bots"]["behavior"]["follow"] = 5;
self.pers["bots"]["behavior"]["crouch"] = 10;
self.pers["bots"]["behavior"]["switch"] = 2;
self.pers["bots"]["behavior"]["class"] = 2;
self.pers["bots"]["behavior"]["jump"] = 35;
break;
case 5:
self.pers["bots"]["skill"]["aim_time"] = 0.25;
self.pers["bots"]["skill"]["init_react_time"] = 500;
self.pers["bots"]["skill"]["reaction_time"] = 300;
self.pers["bots"]["skill"]["no_trace_ads_time"] = 1500;
self.pers["bots"]["skill"]["no_trace_look_time"] = 2000;
self.pers["bots"]["skill"]["remember_time"] = 4000;
self.pers["bots"]["skill"]["fov"] = 0.5;
self.pers["bots"]["skill"]["dist_max"] = 7500;
self.pers["bots"]["skill"]["dist_start"] = 5000;
self.pers["bots"]["skill"]["spawn_time"] = 0.25;
self.pers["bots"]["skill"]["help_dist"] = 1500;
self.pers["bots"]["skill"]["semi_time"] = 0.4;
self.pers["bots"]["skill"]["shoot_after_time"] = 0.35;
self.pers["bots"]["skill"]["aim_offset_time"] = 0.35;
self.pers["bots"]["skill"]["aim_offset_amount"] = 1.5;
self.pers["bots"]["skill"]["bone_update_interval"] = 0.5;
self.pers["bots"]["skill"]["bones"] = "j_spineupper,j_head";
self.pers["bots"]["skill"]["ads_fov_multi"] = 0.5;
self.pers["bots"]["skill"]["ads_aimspeed_multi"] = 0.5;
self.pers["bots"]["behavior"]["strafe"] = 40;
self.pers["bots"]["behavior"]["nade"] = 35;
self.pers["bots"]["behavior"]["sprint"] = 60;
self.pers["bots"]["behavior"]["camp"] = 5;
self.pers["bots"]["behavior"]["follow"] = 5;
self.pers["bots"]["behavior"]["crouch"] = 10;
self.pers["bots"]["behavior"]["switch"] = 2;
self.pers["bots"]["behavior"]["class"] = 2;
self.pers["bots"]["behavior"]["jump"] = 50;
break;
case 6:
self.pers["bots"]["skill"]["aim_time"] = 0.2;
self.pers["bots"]["skill"]["init_react_time"] = 250;
self.pers["bots"]["skill"]["reaction_time"] = 150;
self.pers["bots"]["skill"]["no_trace_ads_time"] = 2000;
self.pers["bots"]["skill"]["no_trace_look_time"] = 3000;
self.pers["bots"]["skill"]["remember_time"] = 5000;
self.pers["bots"]["skill"]["fov"] = 0.45;
self.pers["bots"]["skill"]["dist_max"] = 10000;
self.pers["bots"]["skill"]["dist_start"] = 7500;
self.pers["bots"]["skill"]["spawn_time"] = 0.2;
self.pers["bots"]["skill"]["help_dist"] = 2000;
self.pers["bots"]["skill"]["semi_time"] = 0.25;
self.pers["bots"]["skill"]["shoot_after_time"] = 0.25;
self.pers["bots"]["skill"]["aim_offset_time"] = 0.25;
self.pers["bots"]["skill"]["aim_offset_amount"] = 1;
self.pers["bots"]["skill"]["bone_update_interval"] = 0.25;
self.pers["bots"]["skill"]["bones"] = "j_spineupper,j_head,j_head";
self.pers["bots"]["skill"]["ads_fov_multi"] = 0.5;
self.pers["bots"]["skill"]["ads_aimspeed_multi"] = 0.5;
self.pers["bots"]["behavior"]["strafe"] = 50;
self.pers["bots"]["behavior"]["nade"] = 45;
self.pers["bots"]["behavior"]["sprint"] = 65;
self.pers["bots"]["behavior"]["camp"] = 5;
self.pers["bots"]["behavior"]["follow"] = 5;
self.pers["bots"]["behavior"]["crouch"] = 10;
self.pers["bots"]["behavior"]["switch"] = 2;
self.pers["bots"]["behavior"]["class"] = 2;
self.pers["bots"]["behavior"]["jump"] = 75;
break;
case 7:
self.pers["bots"]["skill"]["aim_time"] = 0.1;
self.pers["bots"]["skill"]["init_react_time"] = 100;
self.pers["bots"]["skill"]["reaction_time"] = 50;
self.pers["bots"]["skill"]["no_trace_ads_time"] = 2500;
self.pers["bots"]["skill"]["no_trace_look_time"] = 4000;
self.pers["bots"]["skill"]["remember_time"] = 7500;
self.pers["bots"]["skill"]["fov"] = 0.4;
self.pers["bots"]["skill"]["dist_max"] = 15000;
self.pers["bots"]["skill"]["dist_start"] = 10000;
self.pers["bots"]["skill"]["spawn_time"] = 0.05;
self.pers["bots"]["skill"]["help_dist"] = 3000;
self.pers["bots"]["skill"]["semi_time"] = 0.1;
self.pers["bots"]["skill"]["shoot_after_time"] = 0;
self.pers["bots"]["skill"]["aim_offset_time"] = 0;
self.pers["bots"]["skill"]["aim_offset_amount"] = 0;
self.pers["bots"]["skill"]["bone_update_interval"] = 0.05;
self.pers["bots"]["skill"]["bones"] = "j_head";
self.pers["bots"]["skill"]["ads_fov_multi"] = 0.5;
self.pers["bots"]["skill"]["ads_aimspeed_multi"] = 0.5;
self.pers["bots"]["behavior"]["strafe"] = 65;
self.pers["bots"]["behavior"]["nade"] = 65;
self.pers["bots"]["behavior"]["sprint"] = 70;
self.pers["bots"]["behavior"]["camp"] = 5;
self.pers["bots"]["behavior"]["follow"] = 5;
self.pers["bots"]["behavior"]["crouch"] = 5;
self.pers["bots"]["behavior"]["switch"] = 2;
self.pers["bots"]["behavior"]["class"] = 2;
self.pers["bots"]["behavior"]["jump"] = 90;
break;
}
}
wait 5;
}
}
/*
When the bot spawned, after the difficulty wait. Start the logic for the bot.
*/
onBotSpawned()
{
self endon( "disconnect" );
level endon( "intermission" );
for ( ;; )
{
self waittill( "bot_spawned" );
self thread start_bot_threads();
}
}
/*
When the bot spawns.
*/
onSpawned()
{
self endon( "disconnect" );
for ( ;; )
{
self waittill( "spawned_player" );
self.bot_lock_goal = false;
self.bot_was_follow_script_update = undefined;
}
}
/*
Starts all the bot thinking
*/
start_bot_threads()
{
self endon( "disconnect" );
level endon( "intermission" );
self endon( "zombified" );
}

View File

@ -69,15 +69,15 @@ BotSetStance( stance )
switch ( stance ) switch ( stance )
{ {
case "stand": case "stand":
//self scripts\sp\bots\_bot_internal::stand(); self maps\bots\_bot_internal::stand();
break; break;
case "crouch": case "crouch":
//self scripts\sp\bots\_bot_internal::crouch(); self maps\bots\_bot_internal::crouch();
break; break;
case "prone": case "prone":
//self scripts\sp\bots\_bot_internal::prone(); self maps\bots\_bot_internal::prone();
break; break;
} }
} }
@ -95,7 +95,7 @@ BotChangeToWeapon( weap )
*/ */
BotPressAttack( time ) BotPressAttack( time )
{ {
self scripts\sp\bots\_bot_internal::pressFire( time ); self maps\bots\_bot_internal::pressFire( time );
} }
/* /*
@ -103,7 +103,7 @@ BotPressAttack( time )
*/ */
BotPressADS( time ) BotPressADS( time )
{ {
self scripts\sp\bots\_bot_internal::pressADS( time ); self maps\bots\_bot_internal::pressADS( time );
} }
/* /*
@ -111,7 +111,7 @@ BotPressADS( time )
*/ */
BotPressUse( time ) BotPressUse( time )
{ {
self scripts\sp\bots\_bot_internal::use( time ); self maps\bots\_bot_internal::use( time );
} }
/* /*
@ -119,7 +119,7 @@ BotPressUse( time )
*/ */
BotPressFrag( time ) BotPressFrag( time )
{ {
self scripts\sp\bots\_bot_internal::frag( time ); self maps\bots\_bot_internal::frag( time );
} }
/* /*
@ -127,7 +127,7 @@ BotPressFrag( time )
*/ */
BotPressSmoke( time ) BotPressSmoke( time )
{ {
self scripts\sp\bots\_bot_internal::smoke( time ); self maps\bots\_bot_internal::smoke( time );
} }
/* /*
@ -378,12 +378,7 @@ getValidTube()
getValidGrenade() getValidGrenade()
{ {
grenadeTypes = []; grenadeTypes = [];
grenadeTypes[grenadeTypes.size] = "frag_grenade_mp"; grenadeTypes[grenadeTypes.size] = "stielhandgranate";
grenadeTypes[grenadeTypes.size] = "molotov_mp";
grenadeTypes[grenadeTypes.size] = "m8_white_smoke_mp";
grenadeTypes[grenadeTypes.size] = "tabun_gas_mp";
grenadeTypes[grenadeTypes.size] = "sticky_grenade_mp";
grenadeTypes[grenadeTypes.size] = "signal_flare_mp";
possibles = []; possibles = [];
@ -417,7 +412,7 @@ PickRandom( arr )
*/ */
isSecondaryGrenade( gnade ) isSecondaryGrenade( gnade )
{ {
return ( gnade == "tabun_gas_mp" || gnade == "m8_white_smoke_mp" || gnade == "signal_flare_mp" ); return ( gnade == "zombie_cymbal_monkey" );
} }
/* /*
@ -655,128 +650,57 @@ float( num )
return GetDvarFloat( "temp_dvar_bot_util" ); return GetDvarFloat( "temp_dvar_bot_util" );
} }
/* get_nodes_in_playable_area()
Tokenizes a string (strtok has limits...) (only one char tok)
*/
tokenizeLine( line, tok )
{ {
tokens = []; total_nodes = getAllNodes();
filtered_nodes = [];
token = ""; for ( i = 0; i < total_nodes.size; i++ )
for ( i = 0; i < line.size; i++ )
{ {
c = line[i]; if ( !is_point_in_playable_area( total_nodes[ i ].origin ) )
if ( c == tok )
{ {
tokens[tokens.size] = token;
token = "";
continue; continue;
} }
token += c; filtered_nodes[ filtered_nodes.size ] = total_nodes[ i ];
}
tokens[tokens.size] = token; if ( ( i % 10 ) == 0 )
return tokens;
}
/*
Parses tokens into a waypoint obj
*/
parseTokensIntoWaypoint( tokens )
{ {
waypoint = spawnStruct(); wait 0.05;
}
orgStr = tokens[0];
orgToks = strtok( orgStr, " " );
waypoint.origin = ( float( orgToks[0] ), float( orgToks[1] ), float( orgToks[2] ) );
childStr = tokens[1];
childToks = strtok( childStr, " " );
waypoint.children = [];
for ( j = 0; j < childToks.size; j++ )
waypoint.children[j] = int( childToks[j] );
type = tokens[2];
waypoint.type = type;
anglesStr = tokens[3];
if ( isDefined( anglesStr ) && anglesStr != "" )
{
anglesToks = strtok( anglesStr, " " );
waypoint.angles = ( float( anglesToks[0] ), float( anglesToks[1] ), float( anglesToks[2] ) );
} }
return waypoint; return filtered_nodes;
} }
/* is_point_in_playable_area( point )
Returns an array of each line
*/
getWaypointLinesFromFile( filename )
{ {
result = spawnStruct(); playable_area = getentarray( "playable_area", "targetname" );
result.lines = [];
waypointStr = fileRead( filename ); in_playable_area = false;
if ( !isDefined( waypointStr ) ) if ( !isDefined( playable_area ) || playable_area.size < 1 )
return result;
line = "";
for ( i = 0; i < waypointStr.size; i++ )
{ {
c = waypointStr[i]; in_playable_area = true;
if ( c == "\n" )
{
result.lines[result.lines.size] = line;
line = "";
continue;
} }
line += c; temp_ent = spawn( "script_origin", point );
}
result.lines[result.lines.size] = line; if ( !in_playable_area )
return result;
}
/*
Read from file a csv, and returns an array of waypoints
*/
readWpsFromFile( mapname )
{ {
waypoints = []; for ( p = 0; p < playable_area.size; p++ )
filename = "waypoints/" + mapname + "_wp.csv";
res = getWaypointLinesFromFile( filename );
if ( !res.lines.size )
return waypoints;
PrintConsole( "Attempting to read waypoints from " + filename + "\n" );
waypointCount = int( res.lines[0] );
for ( i = 1; i <= waypointCount; i++ )
{ {
tokens = tokenizeLine( res.lines[i], "," ); if ( temp_ent isTouching( playable_area[ p ] ) )
{
waypoint = parseTokensIntoWaypoint( tokens ); in_playable_area = true;
break;
waypoints[i - 1] = waypoint; }
}
} }
return waypoints; temp_ent delete ();
return in_playable_area;
} }
/* /*
@ -784,143 +708,10 @@ readWpsFromFile( mapname )
*/ */
load_waypoints() load_waypoints()
{ {
mapname = getDvar( "mapname" ); level.waypoints = GetAllNodes();
level.waypointCount = 0;
level.waypoints = [];
wps = readWpsFromFile( mapname );
if ( wps.size )
{
level.waypoints = wps;
PrintConsole( "Loaded " + wps.size + " waypoints from file.\n" );
}
else
{
if ( level.waypoints.size )
PrintConsole( "Loaded " + level.waypoints.size + " waypoints from script.\n" );
}
level.waypointCount = level.waypoints.size; level.waypointCount = level.waypoints.size;
for ( i = 0; i < level.waypointCount; i++ ) level.waypointsInPlayableArea = get_nodes_in_playable_area();
{
if ( !isDefined( level.waypoints[i].children ) || !isDefined( level.waypoints[i].children.size ) )
level.waypoints[i].children = [];
if ( !isDefined( level.waypoints[i].origin ) )
level.waypoints[i].origin = ( 0, 0, 0 );
if ( !isDefined( level.waypoints[i].type ) )
level.waypoints[i].type = "crouch";
level.waypoints[i].childCount = undefined;
}
}
/*
Is bot near any of the given waypoints
*/
nearAnyOfWaypoints( dist, waypoints )
{
dist *= dist;
for ( i = 0; i < waypoints.size; i++ )
{
waypoint = level.waypoints[waypoints[i]];
if ( DistanceSquared( waypoint.origin, self.origin ) > dist )
continue;
return true;
}
return false;
}
/*
Returns the waypoints that are near
*/
waypointsNear( waypoints, dist )
{
dist *= dist;
answer = [];
for ( i = 0; i < waypoints.size; i++ )
{
wp = level.waypoints[waypoints[i]];
if ( DistanceSquared( wp.origin, self.origin ) > dist )
continue;
answer[answer.size] = waypoints[i];
}
return answer;
}
/*
Returns nearest waypoint of waypoints
*/
getNearestWaypointOfWaypoints( waypoints )
{
answer = undefined;
closestDist = 2147483647;
for ( i = 0; i < waypoints.size; i++ )
{
waypoint = level.waypoints[waypoints[i]];
thisDist = DistanceSquared( self.origin, waypoint.origin );
if ( isDefined( answer ) && thisDist > closestDist )
continue;
answer = waypoints[i];
closestDist = thisDist;
}
return answer;
}
/*
Returns all waypoints of type
*/
getWaypointsOfType( type )
{
answer = [];
for ( i = 0; i < level.waypointCount; i++ )
{
wp = level.waypoints[i];
if ( type == "camp" )
{
if ( wp.type != "crouch" )
continue;
if ( wp.children.size != 1 )
continue;
}
else if ( type != wp.type )
continue;
answer[answer.size] = i;
}
return answer;
}
/*
Returns the waypoint for index
*/
getWaypointForIndex( i )
{
if ( !isDefined( i ) )
return undefined;
return level.waypoints[i];
} }
/* /*
@ -1075,197 +866,6 @@ HeapRemove()
return remove; return remove;
} }
/*
A heap invarient comparitor, used for the astar's nodes, wanting the node with the lowest f to be first in the heap.
*/
ReverseHeapAStar( item, item2 )
{
return item.f < item2.f;
}
/*
Will linearly search for the nearest waypoint to pos that has a direct line of sight.
*/
GetNearestWaypointWithSight( pos )
{
candidate = undefined;
dist = 2147483647;
for ( i = 0; i < level.waypointCount; i++ )
{
if ( !bulletTracePassed( pos + ( 0, 0, 15 ), level.waypoints[i].origin + ( 0, 0, 15 ), false, undefined ) )
continue;
curdis = DistanceSquared( level.waypoints[i].origin, pos );
if ( curdis > dist )
continue;
dist = curdis;
candidate = i;
}
return candidate;
}
/*
Will linearly search for the nearest waypoint
*/
GetNearestWaypoint( pos )
{
candidate = undefined;
dist = 2147483647;
for ( i = 0; i < level.waypointCount; i++ )
{
curdis = DistanceSquared( level.waypoints[i].origin, pos );
if ( curdis > dist )
continue;
dist = curdis;
candidate = i;
}
return candidate;
}
/*
Modified Pezbot astar search.
This makes use of sets for quick look up and a heap for a priority queue instead of simple lists which require to linearly search for elements everytime.
It is also modified to make paths with bots already on more expensive and will try a less congested path first. Thus spliting up the bots onto more paths instead of just one (the smallest).
*/
AStarSearch( start, goal, team, greedy_path )
{
open = NewHeap( ::ReverseHeapAStar ); //heap
openset = [];//set for quick lookup
closed = [];//set for quick lookup
startWp = getNearestWaypoint( start );
if ( !isDefined( startWp ) )
return [];
_startwp = undefined;
if ( !bulletTracePassed( start + ( 0, 0, 15 ), level.waypoints[startWp].origin + ( 0, 0, 15 ), false, undefined ) )
_startwp = GetNearestWaypointWithSight( start );
if ( isDefined( _startwp ) )
startWp = _startwp;
goalWp = getNearestWaypoint( goal );
if ( !isDefined( goalWp ) )
return [];
_goalWp = undefined;
if ( !bulletTracePassed( goal + ( 0, 0, 15 ), level.waypoints[goalWp].origin + ( 0, 0, 15 ), false, undefined ) )
_goalwp = GetNearestWaypointWithSight( goal );
if ( isDefined( _goalwp ) )
goalWp = _goalwp;
node = spawnStruct();
node.g = 0; //path dist so far
node.h = DistanceSquared( level.waypoints[startWp].origin, level.waypoints[goalWp].origin ); //herustic, distance to goal for path finding
node.f = node.h + node.g; // combine path dist and heru, use reverse heap to sort the priority queue by this attru
node.index = startWp;
node.parent = undefined; //we are start, so we have no parent
//push node onto queue
openset[node.index + ""] = node;
open HeapInsert( node );
//while the queue is not empty
while ( open.data.size )
{
//pop bestnode from queue
bestNode = open.data[0];
open HeapRemove();
openset[bestNode.index + ""] = undefined;
wp = level.waypoints[bestNode.index];
//check if we made it to the goal
if ( bestNode.index == goalWp )
{
path = [];
while ( isDefined( bestNode ) )
{
//construct path
path[path.size] = bestNode.index;
bestNode = bestNode.parent;
}
return path;
}
//for each child of bestnode
for ( i = wp.children.size - 1; i >= 0; i-- )
{
child = wp.children[i];
childWp = level.waypoints[child];
penalty = 1;
// have certain types of nodes more expensive
if ( childWp.type == "climb" || childWp.type == "prone" )
penalty += 4;
//calc the total path we have took
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
inopen = isDefined( openset[child + ""] );
if ( inopen && openset[child + ""].g <= newg )
continue;
inclosed = isDefined( closed[child + ""] );
if ( inclosed && closed[child + ""].g <= newg )
continue;
node = undefined;
if ( inopen )
node = openset[child + ""];
else if ( inclosed )
node = closed[child + ""];
else
node = spawnStruct();
node.parent = bestNode;
node.g = newg;
node.h = DistanceSquared( childWp.origin, level.waypoints[goalWp].origin );
node.f = node.g + node.h;
node.index = child;
//check if in closed, remove it
if ( inclosed )
closed[child + ""] = undefined;
//check if not in open, add it
if ( !inopen )
{
open HeapInsert( node );
openset[child + ""] = node;
}
}
//done with children, push onto closed
closed[bestNode.index + ""] = bestNode;
}
return [];
}
/* /*
Returns the natural log of x using harmonic series. Returns the natural log of x using harmonic series.
*/ */
@ -1382,5 +982,13 @@ random_normal_distribution( mean, std_deviation, lower_bound, upper_bound )
*/ */
inLastStand() inLastStand()
{ {
return ( isDefined( self.lastStand ) && self.lastStand ); return self maps\_laststand::player_is_in_laststand();
}
/*
getRandomGoal
*/
getRandomGoal()
{
return PickRandom( level.waypointsInPlayableArea ).origin;
} }

4
scripts/sp/bots.gsc Normal file
View File

@ -0,0 +1,4 @@
init()
{
maps\bots\_bot::init();
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff