Import code from another repo(by me).

This commit is contained in:
JezuzLizard
2023-03-25 19:16:32 -07:00
parent 7d01471760
commit 7614efcec3
3 changed files with 1655 additions and 423 deletions

View File

@@ -1,423 +1,279 @@
#include common_scripts\utility; #include common_scripts\utility;
#include maps\_utility; #include maps\mp\_utility;
#include scripts\sp\bots\_bot_utility; #include maps\mp\zombies\_zm_utility;
#include scripts\zm\bots\bot_actions;
/* #include scripts\zm\bots\bot_utility;
Initiates the whole bot scripts. #include scripts\zm\bots\bot_difficulty;
*/ #include scripts\zm\bots\_overrides;
init()
{ main()
level.bw_VERSION = "2.1.0"; {
replaceFunc( maps\mp\zombies\_zm_spawner::zombie_follow_enemy, ::zombie_follow_enemy_override );
if ( getDvar( "bots_main" ) == "" ) replaceFunc( maps\mp\zombies\_zm_powerups::powerup_timeout, ::powerup_timeout_override );
setDvar( "bots_main", true );
register_bot_action( "purchase", "magicbox", ::bot_magicbox_purchase, ::bot_should_purchase_magicbox, ::bot_magicbox_purchase_on_completion, ::bot_magicbox_purchase_should_cancel, ::bot_magicbox_purchase_on_cancel, ::bot_magicbox_purchase_should_postpone, ::bot_magicbox_purchase_on_postpone, ::bot_magicbox_purchase_priority );
if ( !getDvarInt( "bots_main" ) ) register_bot_action( "purchase", "wallbuy", ::bot_wallbuy_purchase, ::bot_should_purchase_wallbuy, ::bot_wallbuy_purchase_on_completion, ::bot_wallbuy_purchase_should_cancel, ::bot_wallbuy_purchase_on_cancel, ::bot_wallbuy_purchase_should_postpone, ::bot_wallbuy_purchase_on_postpone, ::bot_wallbuy_purchase_priority );
return; register_bot_action( "purchase", "wallbuyammo", ::bot_wallbuy_ammo_purchase, ::bot_should_purchase_wallbuy_ammo, ::bot_wallbuy_ammo_purchase_on_completion, ::bot_wallbuy_ammo_purchase_should_cancel, ::bot_wallbuy_ammo_purchase_on_cancel, ::bot_wallbuy_ammo_purchase_should_postpone, ::bot_wallbuy_ammo_purchase_on_postpone, ::bot_wallbuy_ammo_purchase_priority );
register_bot_action( "purchase", "perk", ::bot_perk_purchase, ::bot_should_purchase_perk, ::bot_perk_purchase_on_completion, ::bot_perk_purchase_should_cancel, ::bot_perk_purchase_on_cancel, ::bot_perk_purchase_should_postpone, ::bot_perk_purchase_on_postpone, ::bot_perk_purchase_priority );
//thread load_waypoints(); //Don't call for now register_bot_action( "purchase", "door", ::bot_door_purchase, ::bot_should_purchase_door, ::bot_door_purchase_on_completion, ::bot_door_purchase_should_cancel, ::bot_door_purchase_on_cancel, ::bot_door_purchase_should_postpone, ::bot_door_purchase_on_postpone, ::bot_door_purchase_priority );
thread hook_callbacks(); register_bot_action( "purchase", "debris", ::bot_debris_purchase, ::bot_should_purchase_debris, ::bot_debris_purchase_on_completion, ::bot_debris_purchase_should_cancel, ::bot_debris_purchase_on_cancel, ::bot_debris_purchase_should_postpone, ::bot_debris_purchase_on_postpone, ::bot_debris_purchase_priority );
register_bot_action( "purchase", "trap", ::bot_trap_purchase, ::bot_should_purchase_trap, ::bot_trap_purchase_on_completion, ::bot_trap_purchase_should_cancel, ::bot_trap_purchase_on_cancel, ::bot_trap_purchase_should_postpone, ::bot_trap_purchase_on_postpone, ::bot_trap_purchase_priority );
if ( getDvar( "bots_main_GUIDs" ) == "" ) register_bot_action( "purchase", "packapunch", ::bot_packapunch_purchase, ::bot_should_packapunch );
setDvar( "bots_main_GUIDs", "" ); //guids of players who will be given host powers, comma seperated register_bot_action( "usetriggerhold", "revive", ::bot_revive_player, ::bot_should_revive_player, ::bot_revive_player_on_completion, ::bot_revive_player_should_cancel, ::bot_revive_player_on_cancel, ::bot_revive_player_should_postpone, ::bot_revive_player_on_postpone, ::bot_revive_player_priority );
register_bot_action( "usetrigger", "grabbuildable", ::bot_grab_buildable, ::bot_should_grab_buildable, ::bot_grab_buildable_on_completion, ::bot_grab_buildable_should_cancel, ::bot_grabbuild_buildable_on_cancel, ::bot_grab_buildable_should_postpone, ::bot_grab_buildable_on_postpone, ::bot_grab_buildable_priority );
if ( getDvar( "bots_main_firstIsHost" ) == "" ) register_bot_action( "usetriggerhold", "buildbuildable", ::bot_build_buildable, ::bot_should_build_buildable, ::bot_build_buildable_on_completion, ::bot_build_buildable_should_cancel, ::bot_build_buildable_on_cancel, ::bot_build_buildable_should_postpone, ::bot_build_buildable_on_postpone, ::bot_build_buildable_priority );
setDvar( "bots_main_firstIsHost", true ); //first player to connect is a host register_bot_action( "usetrigger", "part", ::bot_grab_part, ::bot_should_grab_part, ::bot_part_on_completion, ::bot_part_should_cancel, ::bot_part_on_cancel, ::bot_part_should_postpone, ::bot_part_on_postpone, ::bot_part_priority );
register_bot_action( "touchtrigger", "powerup", ::bot_grab_powerup, ::bot_should_grab_powerup, ::bot_powerup_on_completion, ::bot_powerup_should_cancel, ::bot_powerup_on_cancel, ::bot_powerup_should_postpone, ::bot_powerup_on_postpone, ::bot_powerup_priority );
if ( getDvar( "bots_main_waitForHostTime" ) == "" ) //register_bot_action( level.bot_action_type_shoot, "shoot", ::bot_shoot, ::bot_should_shoot );
setDvar( "bots_main_waitForHostTime", 10.0 ); //how long to wait to wait for the host player //register_bot_action( level.bot_action_type_ads, "ads", ::bot_ads, ::bot_should_ads );
//register_bot_action( level.bot_action_type_grenade, "grenade", ::bot_grenade, ::bot_should_grenade );
if ( getDvar( "bots_main_kickBotsAtEnd" ) == "" )
setDvar( "bots_main_kickBotsAtEnd", false ); //kicks the bots at game end level.bot_weapon_quality_poor = 0;
level.bot_weapon_quality_fair = 1;
if ( getDvar( "bots_manage_add" ) == "" ) level.bot_weapon_quality_good = 2;
setDvar( "bots_manage_add", 0 ); //amount of bots to add to the game level.bot_weapon_quality_excellent = 3;
level.bot_weapon_quality_best = 4;
if ( getDvar( "bots_manage_fill" ) == "" )
setDvar( "bots_manage_fill", 0 ); //amount of bots to maintain /*
level.bot_powerup_priority_none = 0;
if ( getDvar( "bots_manage_fill_mode" ) == "" ) level.bot_powerup_priority_low = 1;
setDvar( "bots_manage_fill_mode", 0 ); //fill mode, 0 adds everyone, 1 just bots, 2 maintains at maps, 3 is 2 with 1 level.bot_powerup_priority_medium = 2;
level.bot_powerup_priority_high = 3;
if ( getDvar( "bots_manage_fill_kick" ) == "" ) level.bot_powerup_priority_urgent = 4;
setDvar( "bots_manage_fill_kick", false ); //kick bots if too many register_bot_powerup_priority( "nuke", level.bot_powerup_priority_high, level.bot_powerup_priority_urgent );
register_bot_powerup_priority( "insta_kill", level.bot_powerup_priority_high, level.bot_powerup_priority_urgent );
if ( getDvar( "bots_skill" ) == "" ) register_bot_powerup_priority( "full_ammo", level.bot_powerup_priority_medium, level.bot_powerup_priority_low );
setDvar( "bots_skill", 0 ); //0 is random, 1 is easy 7 is hard, 8 is custom, 9 is completely random register_bot_powerup_priority( "double_points", level.bot_powerup_priority_low, level.bot_powerup_priority_none );
register_bot_powerup_priority( "carpenter", level.bot_powerup_priority_low, level.bot_powerup_priority_none );
if ( getDvar( "bots_skill_hard" ) == "" ) register_bot_powerup_priority( "fire_sale", level.bot_powerup_priority_low, level.bot_powerup_priority_none );
setDvar( "bots_skill_hard", 0 ); //amount of hard bots on axis team register_bot_powerup_priority( "free_perk", level.bot_powerup_priority_medium, level.bot_powerup_priority_low );
register_bot_powerup_priority( "zombie_blood", level.bot_powerup_priority_high, level.bot_powerup_priority_urgent);
if ( getDvar( "bots_skill_med" ) == "" ) */
setDvar( "bots_skill_med", 0 ); level thread store_powerups_dropped();
level thread spawn_bots();
if ( getDvar( "bots_loadout_rank" ) == "" ) // what rank the bots should be around, -1 is around the players, 0 is all random }
setDvar( "bots_loadout_rank", -1 );
init()
if ( getDvar( "bots_loadout_prestige" ) == "" ) // what pretige the bots will be, -1 is the players, -2 is random {
setDvar( "bots_loadout_prestige", -1 ); parse_bot_weapon_stats_from_table();
}
if ( getDvar( "bots_play_move" ) == "" ) //bots move
setDvar( "bots_play_move", true ); register_action_queue_actions()
{
if ( getDvar( "bots_play_knife" ) == "" ) //bots knife self register_bot_action_queue_action( "magicbox" );
setDvar( "bots_play_knife", true ); self register_bot_action_queue_action( "wallbuy" );
self register_bot_action_queue_action( "wallbuyammo" );
if ( getDvar( "bots_play_fire" ) == "" ) //bots fire self register_bot_action_queue_action( "perk" );
setDvar( "bots_play_fire", true ); self register_bot_action_queue_action( "door" );
self register_bot_action_queue_action( "debris" );
if ( getDvar( "bots_play_nade" ) == "" ) //bots grenade self register_bot_action_queue_action( "trap" );
setDvar( "bots_play_nade", true ); self register_bot_action_queue_action( "revive" );
self register_bot_action_queue_action( "buildable" );
if ( getDvar( "bots_play_ads" ) == "" ) //bot ads self register_bot_action_queue_action( "buildbuildable" );
setDvar( "bots_play_ads", true ); self register_bot_action_queue_action( "part" );
self register_bot_action_queue_action( "powerup" );
if ( getDvar( "bots_play_aim" ) == "" ) }
setDvar( "bots_play_aim", true );
spawn_bots()
if ( !isDefined( game["botWarfare"] ) ) {
game["botWarfare"] = true; level waittill( "connected", player );
level.bots_minSprintDistance = 315; while ( true )
level.bots_minSprintDistance *= level.bots_minSprintDistance; {
level.bots_minGrenadeDistance = 256; spawn_bots();
level.bots_minGrenadeDistance *= level.bots_minGrenadeDistance; wait 1;
level.bots_maxGrenadeDistance = 1024; }
level.bots_maxGrenadeDistance *= level.bots_maxGrenadeDistance; }
level.bots_maxKnifeDistance = 80;
level.bots_maxKnifeDistance *= level.bots_maxKnifeDistance; spawn_bots()
level.bots_goalDistance = 27.5; {
level.bots_goalDistance *= level.bots_goalDistance; required_bots = 3;
level.bots_noADSDistance = 200; bot_count = 0;
level.bots_noADSDistance *= level.bots_noADSDistance; while ( bot_count < required_bots )
level.bots_maxShotgunDistance = 500; {
level.bots_maxShotgunDistance *= level.bots_maxShotgunDistance; bot = undefined;
while ( !isDefined( bot ) )
level.players = []; {
level.bots = []; bot = addTestClient();
}
level.bots_fullautoguns = []; bot.pers[ "isBot" ] = true;
level.bots_fullautoguns["thompson"] = true; bot.action_queue = [];
level.bots_fullautoguns["mp40"] = true; bot register_action_queue_actions();
level.bots_fullautoguns["type100smg"] = true; bot thread bot_movement_think();
level.bots_fullautoguns["ppsh"] = true; //bot thread bot_combat_think();
level.bots_fullautoguns["stg44"] = true; bot thread bot_think();
level.bots_fullautoguns["30cal"] = true; bot_count++;
level.bots_fullautoguns["mg42"] = true; }
level.bots_fullautoguns["dp28"] = true; }
level.bots_fullautoguns["bar"] = true;
level.bots_fullautoguns["fg42"] = true; copy_default_action_settings_to_queue( action_name )
level.bots_fullautoguns["type99lmg"] = true; {
//self.group = level.zbots_actions[ action_name ].group;
level thread onPlayerConnect(); self.action = level.zbots_actions[ action_name ].action;
level thread handleBots(); //self.should_do_func = level.zbots_actions[ action_name ].should_do_func;
} self.on_completion_func = level.zbots_actions[ action_name ].on_completion_func;
self.should_cancel_func = level.zbots_actions[ action_name ].should_cancel_func;
/* self.on_cancel_func = level.zbots_actions[ action_name ].on_cancel_func;
Starts the threads for bots. self.should_postpone_func = level.zbots_actions[ action_name ].should_postpone_func;
*/ self.on_postpone_func = level.zbots_actions[ action_name ].on_postpone_func;
handleBots() self.priority_func = level.zbots_actions[ action_name ].priority_func;
{ }
level thread diffBots();
level addBots(); process_next_queued_action()
{
while ( !level.intermission ) if ( self.action_queue.size <= 0 )
wait 0.05; {
return;
setDvar( "bots_manage_add", getBotArray().size ); }
self thread [[ self.action_queue[ 0 ].on_completion_func ]]();
if ( !getDvarInt( "bots_main_kickBotsAtEnd" ) ) if ( self.action_queue[ 0 ].can_cancel )
return; {
self thread [[ self.action_queue[ 0 ].on_cancel_func ]]();
bots = getBotArray(); }
if ( self.action_queue[ 0 ].can_postpone )
for ( i = 0; i < bots.size; i++ ) {
{ self thread [[ self.action_queue[ 0 ].on_postpone_func ]]();
bots[i] RemoveTestClient(); }
} self [[ self.action_queue[ 0 ].action ]]();
}
self wait_for_action_completion( self.action_queue[ 0 ].action_name );
/* }
The hook callback for when any player becomes damaged.
*/ wait_for_action_completion( action_name )
onPlayerDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, iModelIndex, timeOffset ) {
{ result = self waittill_any_return( action_name + "_completion", action_name + "_cancel", action_name + "_postpone" );
if ( self is_bot() ) if ( isDefined( result ) && ( result == action_name + "_completion" || result == action_name + "_cancel" ) )
{ {
//self scripts\sp\bots\_bot_internal::onDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, iModelIndex, timeOffset ); self.actions_in_queue[ self.action_queue[ 0 ].action_name ].queued = false;
self scripts\sp\bots\_bot_script::onDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, iModelIndex, timeOffset ); arrayRemoveIndex( self.action_queue, 0 );
} }
else if ( result == action_name + "_postpone" )
self [[level.prevCallbackPlayerDamage]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, iModelIndex, timeOffset ); {
} postponed_action = self.action_queue[ 0 ];
arrayRemoveIndex( self.action_queue, 0 );
/* postponed_action.priority = 0;
Starts the callbacks. self.action_queue[ self.action_queue.size ] = postponed_action;
*/ }
hook_callbacks() }
{
wait 0.05; bot_think()
level.prevCallbackPlayerDamage = level.callbackPlayerDamage; {
level.callbackPlayerDamage = ::onPlayerDamage; level endon( "end_game" );
} self endon( "disconnect" );
/* self waittill( "spawned_player" );
Thread when any player connects. Starts the threads needed.
*/ while ( true )
onPlayerConnect() {
{ wait 0.05;
for ( ;; ) if ( !bot_valid( self ) )
{ {
level waittill( "connected", player ); self.action_queue = [];
wait 1;
player thread connected(); continue;
} }
} if ( self.action_queue.size > 4 )
{
/* continue;
When a bot disconnects. }
*/ /*
onDisconnectAll() action_keys = getArrayKeys( level.zbots_actions );
{ for ( i = 0; i < action_keys.size; i++ )
self waittill( "disconnect" ); {
if ( self.actions_in_queue[ action_keys[ i ] ].canceled )
level.players = array_remove( level.players, self ); {
} self.actions_in_queue[ action_keys[ i ] ].canceled = false;
}
/* }
When a bot disconnects. action_keys = getArrayKeys( level.zbots_actions );
*/ for ( i = 0; i < action_keys.size; i++ )
onDisconnect() {
{ if ( self.actions_in_queue[ action_keys[ i ] ].postponed )
self waittill( "disconnect" ); {
self.actions_in_queue[ action_keys[ i ] ].postponed = false;
level.bots = array_remove( level.bots, self ); }
} }
*/
/* action_keys = getArrayKeys( level.zbots_actions );
Called when a player connects. for ( i = 0; i < action_keys.size && self.action_queue.size < 3; i++ )
*/ {
connected() if ( !self.actions_in_queue[ action_keys[ i ] ].queued && [[ level.zbots_actions[ action_keys[ i ] ].should_do_func ]]() )
{ {
self endon( "disconnect" ); self.action_queue[ self.action_queue.size ] = spawnStruct();
self.action_queue[ self.action_queue.size - 1 ] copy_default_action_settings_to_queue( action_keys[ i ] );
if ( !isDefined( self.pers["bot_host"] ) ) self.action_queue[ self.action_queue.size - 1 ].action_name = action_keys[ i ];
self thread doHostCheck(); self.action_queue[ self.action_queue.size - 1 ].priority = self [[ level.zbots_actions[ action_keys[ i ] ].priority_func ]]();
self.actions_in_queue[ action_keys[ i ] ].queued = true;
level.players[level.players.size] = self; }
self thread onDisconnectAll(); }
self.action_queue = self sort_array_by_priority_field( self.action_queue );
if ( !self is_bot() ) self process_next_queued_action();
return; }
}
if ( !isDefined( self.pers["isBot"] ) )
{ bot_movement_think()
// fast restart... {
self.pers["isBot"] = true; level endon( "end_game" );
} self endon( "disconnect" );
/*
if ( !isDefined( self.pers["isBotWarfare"] ) ) if ( self any_zombies_targeting_self() )
{ {
self.pers["isBotWarfare"] = true;
self thread added(); }
} */
self.currently_moving = false;
self thread scripts\sp\bots\_bot_internal::connected(); while ( true )
self thread scripts\sp\bots\_bot_script::connected(); {
wait 0.05;
level.bots[level.bots.size] = self; if ( isDefined( self.target_pos ) && !self.currently_moving )
self thread onDisconnect(); {
self lookAt( self.target_pos );
level notify( "bot_connected", self ); self addGoal( self.target_pos, 36, 4, "move_to_target_pos" );
self.currently_moving = true;
self thread watchBotDebugEvent(); }
} if ( self hasGoal( "move_to_target_pos" ) )
{
/* if ( self atGoal( "move_to_target_pos" ) )
DEBUG {
*/ self clearLookat();
watchBotDebugEvent() self.currently_moving = false;
{ if ( isDefined( self.goal_type ) && isDefined( level.bot_at_goal_callback[ self.goal_type ] ) )
self endon( "disconnect" ); {
self [[ level.bot_at_goal_callback[ self.goal_type ] ]]();
for ( ;; ) }
{ }
self waittill( "bot_event", msg, str, b, c, d, e, f, g ); }
}
if ( msg == "debug" && GetDvarInt( "bots_main_debug" ) ) }
{
PrintConsole( "Bot Warfare debug: " + self.name + ": " + str + "\n" ); store_powerups_dropped()
} {
} level.zbots_powerups = [];
} level.zbots_powerups_targeted_for_grab = [];
id_num = 0;
/* while ( true )
When a bot gets added into the game. {
*/ level waittill( "powerup_dropped", powerup );
added() if ( !isDefined( powerup ) )
{ {
self endon( "disconnect" ); continue;
}
self thread scripts\sp\bots\_bot_internal::added(); assign_priority_to_powerup( powerup );
//self thread scripts\sp\bots\_bot_script::added(); level.zbots_powerups = sort_array_by_priority_field( level.zbots_powerups, powerup );
} powerup thread remove_from_bot_powerups_list_on_death();
}
/* }
Adds a bot to the game.
*/ remove_from_bot_powerups_list_on_death()
add_bot() {
{ self waittill( "death" );
bot = addtestclient(); arrayRemoveValue( level.zbots_powerups, self );
arrayRemoveValue( level.zbots_powerups_targeted_for_grab, self );
if ( isdefined( bot ) ) for ( i = 0; i < level.players.size; i++ )
{ {
bot.pers["isBot"] = true; if ( is_true( level.players[ i ].pers[ "isBot" ] ) && isDefined( level.players[ i ].available_powerups ) )
bot.pers["isBotWarfare"] = true; {
bot thread added(); arrayRemoveValue( level.players[ i ].available_powerups, self );
} }
} }
}
/*
A server thread for monitoring all bot's difficulty levels for custom server settings.
*/
diffBots_loop()
{
var_hard = getDVarInt( "bots_skill_hard" );
var_med = getDVarInt( "bots_skill_med" );
var_skill = getDvarInt( "bots_skill" );
hard = 0;
med = 0;
if ( var_skill == 8 )
{
playercount = level.players.size;
for ( i = 0; i < playercount; i++ )
{
player = level.players[i];
if ( !isDefined( player.pers["team"] ) )
continue;
if ( !player is_bot() )
continue;
if ( hard < var_hard )
{
hard++;
player.pers["bots"]["skill"]["base"] = 7;
}
else if ( med < var_med )
{
med++;
player.pers["bots"]["skill"]["base"] = 4;
}
else
player.pers["bots"]["skill"]["base"] = 1;
}
}
else if ( var_skill != 0 && var_skill != 9 )
{
playercount = level.players.size;
for ( i = 0; i < playercount; i++ )
{
player = level.players[i];
if ( !player is_bot() )
continue;
player.pers["bots"]["skill"]["base"] = var_skill;
}
}
}
/*
A server thread for monitoring all bot's difficulty levels for custom server settings.
*/
diffBots()
{
for ( ;; )
{
wait 1.5;
diffBots_loop();
}
}
/*
A server thread for monitoring all bot's in game. Will add and kick bots according to server settings.
*/
addBots_loop()
{
botsToAdd = GetDvarInt( "bots_manage_add" );
if ( botsToAdd > 0 )
{
SetDvar( "bots_manage_add", 0 );
if ( botsToAdd > 4 )
botsToAdd = 4;
for ( ; botsToAdd > 0; botsToAdd-- )
{
level add_bot();
wait 0.25;
}
}
fillMode = getDVarInt( "bots_manage_fill_mode" );
if ( fillMode == 2 || fillMode == 3 )
setDvar( "bots_manage_fill", getGoodMapAmount() );
fillAmount = getDvarInt( "bots_manage_fill" );
players = 0;
bots = 0;
playercount = level.players.size;
for ( i = 0; i < playercount; i++ )
{
player = level.players[i];
if ( player is_bot() )
bots++;
else
players++;
}
amount = bots;
if ( fillMode == 0 || fillMode == 2 )
amount += players;
if ( amount < fillAmount )
setDvar( "bots_manage_add", 1 );
else if ( amount > fillAmount && getDvarInt( "bots_manage_fill_kick" ) )
{
tempBot = PickRandom( getBotArray() );
if ( isDefined( tempBot ) )
tempBot RemoveTestClient();
}
}
/*
A server thread for monitoring all bot's in game. Will add and kick bots according to server settings.
*/
addBots()
{
level endon( "game_ended" );
bot_wait_for_host();
for ( ;; )
{
wait 1.5;
addBots_loop();
}
}

View File

@@ -0,0 +1,649 @@
/*
Bot actions are in two parts
*/
#include common_scripts\utility;
#include maps\mp\_utility;
#include maps\mp\zombies\_zm_utility;
#include scripts\zm\bots\bot_utility;
register_bot_action( group, action_name, action_func, should_do_func, action_completion_func, should_cancel_func, on_cancel_func, should_postpone_func, on_postpone_func, priority_func )
{
if ( !isDefined( level.zbots_actions ) )
{
level.zbots_actions = [];
}
if ( !isDefined( level.zbots_actions[ action_name ] ) )
{
level.zbots_actions[ action_name ] = [];
}
level.zbots_actions[ action_name ] = spawnStruct();
level.zbots_actions[ action_name ].group = group;
level.zbots_actions[ action_name ].action = action_func;
level.zbots_actions[ action_name ].should_do_func = should_do_func;
level.zbots_actions[ action_name ].on_completion_func = action_completion_func;
level.zbots_actions[ action_name ].should_cancel_func = should_cancel_func;
level.zbots_actions[ action_name ].on_cancel_func = on_cancel_func;
level.zbots_actions[ action_name ].should_postpone_func = should_postpone_func;
level.zbots_actions[ action_name ].on_postpone_func = on_postpone_func;
level.zbots_actions[ action_name ].priority_func = priority_func;
}
register_bot_powerup_priority( powerup, priority_normal, priority_emergency )
{
if ( !isDefined( level.zbots_powerup_priorities ) )
{
level.zbots_powerup_priorities = [];
}
level.zbots_powerup_priorities[ powerup ] = spawnStruct();
level.zbots_powerup_priorities[ powerup ].normal = priority_normal;
level.zbots_powerup_priorities[ powerup ].emergency = priority_emergency;
}
register_bot_action_queue_action( action_name )
{
if ( !isDefined( self.actions_in_queue ) )
{
self.actions_in_queue = [];
}
self.actions_in_queue[ action_name ] = spawnStruct();
self.actions_in_queue[ action_name ].postponed = false;
self.actions_in_queue[ action_name ].canceled = false;
self.actions_in_queue[ action_name ].queued = false;
}
bot_magicbox_purchase()
{
self.target_pos = self.available_chests[ 0 ].origin;
}
bot_should_purchase_magicbox()
{
if ( level.chests.size <= 0 )
{
return false;
}
if ( !level.enable_magic )
{
return false;
}
self.available_chests = [];
for ( i = 0; i < level.chests.size; i++ )
{
if ( level.chests[ i ].hidden )
{
continue;
}
if ( self.score < level.chests[ i ].zombie_cost )
{
continue;
}
self.available_chests[ self.available_chests.size ] = level.chests[ i ];
}
if ( self.available_chests.size > 0 )
{
for ( i = 0; i < self.available_chests.size; i++ )
{
if ( isDefined( self.available_chests[ i ].chest_user ) )
{
arrayRemoveIndex( self.available_chests, i );
i--;
}
}
}
return self.available_chests.size > 0;
}
bot_magicbox_purchase_on_completion()
{
}
bot_magicbox_purchase_should_cancel()
{
return false;
}
bot_magicbox_purchase_on_cancel()
{
}
bot_magicbox_purchase_should_postpone()
{
return false;
}
bot_magicbox_purchase_on_postpone()
{
}
bot_magicbox_purchase_priority()
{
priority = 0;
const LOW_AMMO_THRESHOLD = 0.3;
weapons = self getWeaponsListPrimaries();
if ( weapons.size < 2 )
{
priority += 1;
}
for ( j = 0; j < weapons.size; j++ )
{
if ( self getWeaponAmmoStock( weapons[ j ] ) <= int( weaponmaxammo( weapons[ j ] ) * LOW_AMMO_THRESHOLD ) )
{
priority += 1;
}
}
return priority;
}
bot_wallbuy_purchase()
{
}
bot_should_purchase_wallbuy()
{
return false;
}
bot_wallbuy_purchase_on_completion()
{
}
bot_wallbuy_purchase_should_cancel()
{
return false;
}
bot_wallbuy_purchase_on_cancel()
{
}
bot_wallbuy_purchase_should_postpone()
{
return false;
}
bot_wallbuy_purchase_on_postpone()
{
}
bot_wallbuy_purchase_priority()
{
return 0;
}
bot_wallbuy_ammo_purchase()
{
}
bot_should_purchase_wallbuy_ammo()
{
return false;
}
bot_wallbuy_ammo_purchase_on_completion()
{
}
bot_wallbuy_ammo_purchase_should_cancel()
{
return false;
}
bot_wallbuy_ammo_purchase_on_cancel()
{
}
bot_wallbuy_ammo_purchase_should_postpone()
{
return false;
}
bot_wallbuy_ammo_purchase_on_postpone()
{
}
bot_wallbuy_ammo_purchase_priority()
{
return 0;
}
bot_perk_purchase()
{
}
bot_should_purchase_perk()
{
return false;
}
bot_perk_purchase_on_completion()
{
}
bot_perk_purchase_should_cancel()
{
return false;
}
bot_perk_purchase_on_cancel()
{
}
bot_perk_purchase_should_postpone()
{
return false;
}
bot_perk_purchase_on_postpone()
{
}
bot_perk_purchase_priority()
{
return 0;
}
bot_door_purchase()
{
}
bot_should_purchase_door()
{
return false;
}
bot_door_purchase_on_completion()
{
}
bot_door_purchase_should_cancel()
{
return false;
}
bot_door_purchase_on_cancel()
{
}
bot_door_purchase_should_postpone()
{
return false;
}
bot_door_purchase_on_postpone()
{
}
bot_door_purchase_priority()
{
return 0;
}
bot_debris_purchase()
{
}
bot_should_purchase_debris()
{
return false;
}
bot_debris_purchase_on_completion()
{
}
bot_debris_purchase_should_cancel()
{
return false;
}
bot_debris_purchase_on_cancel()
{
}
bot_debris_purchase_should_postpone()
{
return false;
}
bot_debris_purchase_on_postpone()
{
}
bot_debris_purchase_priority()
{
return 0;
}
bot_trap_purchase()
{
}
bot_should_purchase_trap()
{
return false;
}
bot_trap_purchase_on_completion()
{
}
bot_trap_purchase_should_cancel()
{
return false;
}
bot_trap_purchase_on_cancel()
{
}
bot_trap_purchase_should_postpone()
{
return false;
}
bot_trap_purchase_on_postpone()
{
}
bot_trap_purchase_priority()
{
return 0;
}
bot_revive_player()
{
}
bot_should_revive_player()
{
return false;
}
bot_revive_player_on_completion()
{
}
bot_revive_player_should_cancel()
{
return false;
}
bot_revive_player_on_cancel()
{
}
bot_revive_player_should_postpone()
{
return false;
}
bot_revive_player_on_postpone()
{
}
bot_revive_player_priority()
{
return 0;
}
bot_grab_buildable()
{
}
bot_should_grab_buildable()
{
return false;
}
bot_grab_buildable_on_completion()
{
}
bot_grab_buildable_should_cancel()
{
return false;
}
bot_grabbuild_buildable_on_cancel()
{
}
bot_grab_buildable_should_postpone()
{
return false;
}
bot_grab_buildable_on_postpone()
{
}
bot_grab_buildable_priority()
{
return 0;
}
bot_build_buildable()
{
}
bot_should_build_buildable()
{
return false;
}
bot_build_buildable_on_completion()
{
}
bot_build_buildable_should_cancel()
{
return false;
}
bot_build_buildable_on_cancel()
{
}
bot_build_buildable_should_postpone()
{
return false;
}
bot_build_buildable_on_postpone()
{
}
bot_build_buildable_priority()
{
return 0;
}
bot_grab_part()
{
}
bot_should_grab_part()
{
return false;
}
bot_part_on_completion()
{
}
bot_part_should_cancel()
{
return false;
}
bot_part_on_cancel()
{
}
bot_part_should_postpone()
{
return false;
}
bot_part_on_postpone()
{
}
bot_part_priority()
{
return 0;
}
bot_grab_powerup()
{
self endon( "disconnect" );
self endon( "new_objective" );
if ( !isDefined( self.available_powerups ) || self.available_powerups.size <= 0 )
{
return;
}
self.target_pos = self.available_powerups[ 0 ].origin;
self.target_powerup = self.available_powerups[ 0 ];
level.zbots_powerups_targeted_for_grab[ level.zbots_powerups_targeted_for_grab.size ] = self.available_powerups[ 0 ];
}
bot_should_grab_powerup()
{
if ( !( isDefined( level.zbots_powerups ) && level.zbots_powerups.size > 0 ) )
{
return false;
}
const MAX_DISTANCE_SQ = 10000 * 10000;
const BOT_SPEED_WHILE_SPRINTING_SQ = 380 * 380;
self.available_powerups = [];
for ( i = 0; i < level.zbots_powerups.size; i++ )
{
if ( array_validate( level.zbots_powerups_targeted_for_grab ) )
{
already_targeted = false;
for ( j = 0; j < level.zbots_powerups_targeted_for_grab.size; j++ )
{
if ( level.zbots_powerups_targeted_for_grab[ j ] == level.zbots_powerups[ i ] )
{
already_targeted = true;
break;
}
}
if ( already_targeted )
{
continue;
}
}
time_left = level.zbots_powerups[ i ].time_left_until_timeout;
distance_required_to_reach_powerup = distanceSquared( level.zbots_powerups[ i ].origin, self.origin );
if ( distance_required_to_reach_powerup > BOT_SPEED_WHILE_SPRINTING_SQ * time_left )
{
continue;
}
if ( distanceSquared( level.zbots_powerups[ i ].origin, self.origin ) > MAX_DISTANCE_SQ )
{
continue;
}
if ( !findPath( self.origin, level.zbots_powerups[ i ].origin ) )
{
continue;
}
self.available_powerups[ self.available_powerups.size ] = level.zbots_powerups[ i ];
}
time_left = undefined;
distance_required_to_reach_powerup = undefined;
already_targeted = undefined;
return self.available_powerups.size > 0;
}
bot_powerup_on_completion()
{
level endon( "end_game" );
self endon( "disconnect" );
self notify( "powerup_completion_func" );
self endon( "powerup_completion_func" );
self endon( "pause_bot_think" );
self endon( "powerup_cancel" );
self endon( "powerup_postpone" );
while ( !isDefined( self.target_powerup ) )
{
wait 0.05;
}
self.target_powerup waittill( "death" );
self.actions_in_queue[ "powerup" ].queued = false;
self notify( "powerup_completion" );
self.available_powerups = undefined;
self.target_pos = undefined;
}
bot_powerup_should_cancel()
{
return false;
}
bot_powerup_on_cancel()
{
}
bot_powerup_should_postpone()
{
return false;
}
bot_powerup_on_postpone()
{
}
bot_powerup_priority()
{
if ( !isDefined( self.available_powerups ) )
{
return 0;
}
return self.available_powerups[ 0 ].priority;
}

View File

@@ -0,0 +1,727 @@
#include common_scripts\utility;
#include maps\mp\_utility;
#include maps\mp\zombies\_zm_utility;
register_stats_for_bot_weapon( weapon, score )
{
if ( !isDefined( level.bot_weapons_stats ) )
{
level.bot_weapons_stats = [];
}
level.bot_weapons_stats[ weapon ] = score;
}
parse_bot_weapon_stats_from_table()
{
const WEAPON_COLUMN = 0;
const SCORE_COLUMN = 1;
/*
row = 0;
while ( true )
{
weapon = fs_tablelookupcolumnforrow( "tables\bot_weapon_stats.csv", row, WEAPON_COLUMN );
if ( !isDefined( weapon ) || weapon == "" )
{
break;
}
score = fs_tablelookupcolumnforrow( "tables\bot_weapon_stats.csv", row, SCORE_COLUMN );
if ( !isDefined( score ) || score == "" )
{
row++;
continue;
}
if ( isDefined( level.zombie_include_weapons[ weapon + "_zm" ] ) )
{
register_stats_for_bot_weapon( weapon + "_zm", int( score ) );
if ( isDefined( level.zombie_include_weapons[ weapon + "_upgraded_zm" ] ) )
{
register_stats_for_bot_weapon( weapon + "_upgraded_zm", int( score ) + 1 );
}
}
else if ( isDefined( level.zombie_include_weapons[ weapon ] ) )
{
register_stats_for_bot_weapon( weapon, int( score ) );
}
row++;
}
*/
}
array_validate( array )
{
return isDefined( array ) && isArray( array ) && array.size > 0;
}
array_add( array, item )
{
array[ array.size ] = item;
}
swap( array, index1, index2 )
{
temp = array[ index1 ];
array[ index1 ] = array[ index2 ];
array[ index2 ] = temp;
return array;
}
merge_sort( current_list, func_sort, param )
{
if ( current_list.size <= 1 )
{
return current_list;
}
left = [];
right = [];
middle = current_list.size / 2;
for ( x = 0; x < middle; x++ )
{
array_add( left, current_list[ x ] );
}
for ( ; x < current_list.size; x++ )
{
array_add( right, current_list[ x ] );
}
left = merge_sort( left, func_sort, param );
right = merge_sort( right, func_sort, param );
//result = merge( left, right, func_sort, param );
//return result;
}
quickSort(array, compare_func)
{
return quickSortMid(array, 0, array.size -1, compare_func);
}
quickSortMid( array, start, end, compare_func )
{
i = start;
k = end;
if(!IsDefined(compare_func))
compare_func = ::quicksort_compare;
if (end - start >= 1)
{
pivot = array[start];
while (k > i)
{
while ( [[ compare_func ]](array[i], pivot) && i <= end && k > i)
i++;
while ( ![[ compare_func ]](array[k], pivot) && k >= start && k >= i)
k--;
if (k > i)
array = swap(array, i, k);
}
array = swap(array, start, k);
array = quickSortMid(array, start, k - 1, compare_func);
array = quickSortMid(array, k + 1, end, compare_func);
}
else
return array;
return array;
}
quicksort_compare(left, right)
{
return left <= right;
}
push( array, val, index )
{
if ( !isdefined( index ) )
{
// use max free integer as index
index = 0;
foreach ( key in GetArrayKeys( array ) )
{
if ( IsInt( key ) && ( key >= index ) )
{
index = key + 1;
}
}
}
ArrayInsert( array, val, index );
return array;
}
bot_spawn_init()
{
time = gettime();
if ( !isdefined( self.bot ) )
{
self.bot = spawnstruct();
self.bot.threat = spawnstruct();
}
self.bot.glass_origin = undefined;
self.bot.ignore_entity = [];
self.bot.previous_origin = self.origin;
self.bot.time_ads = 0;
self.bot.update_c4 = time + randomintrange( 1000, 3000 );
self.bot.update_crate = time + randomintrange( 1000, 3000 );
self.bot.update_crouch = time + randomintrange( 1000, 3000 );
self.bot.update_failsafe = time + randomintrange( 1000, 3000 );
self.bot.update_idle_lookat = time + randomintrange( 1000, 3000 );
self.bot.update_killstreak = time + randomintrange( 1000, 3000 );
self.bot.update_lookat = time + randomintrange( 1000, 3000 );
self.bot.update_objective = time + randomintrange( 1000, 3000 );
self.bot.update_objective_patrol = time + randomintrange( 1000, 3000 );
self.bot.update_patrol = time + randomintrange( 1000, 3000 );
self.bot.update_toss = time + randomintrange( 1000, 3000 );
self.bot.update_launcher = time + randomintrange( 1000, 3000 );
self.bot.update_weapon = time + randomintrange( 1000, 3000 );
self.bot.threat.entity = undefined;
self.bot.threat.position = ( 0, 0, 0 );
self.bot.threat.time_first_sight = 0;
self.bot.threat.time_recent_sight = 0;
self.bot.threat.time_aim_interval = 0;
self.bot.threat.time_aim_correct = 0;
self.bot.threat.update_riotshield = 0;
}
bot_should_hip_fire()
{
enemy = self.bot.threat.entity;
weapon = self getcurrentweapon();
if ( weapon == "none" )
return 0;
if ( weaponisdualwield( weapon ) )
return 1;
weapon_class = weaponclass( weapon );
if ( isplayer( enemy ) && weapon_class == "spread" )
return 1;
distsq = distancesquared( self.origin, enemy.origin );
distcheck = 0;
switch ( weapon_class )
{
case "mg":
distcheck = 250;
break;
case "smg":
distcheck = 350;
break;
case "spread":
distcheck = 400;
break;
case "pistol":
distcheck = 200;
break;
case "rocketlauncher":
distcheck = 0;
break;
case "rifle":
default:
distcheck = 300;
break;
}
if ( isweaponscopeoverlay( weapon ) )
distcheck = 500;
return distsq < distcheck * distcheck;
}
get_allies()
{
return getPlayers( self.team );
}
get_zombies()
{
return getAiSpeciesArray( level.zombie_team, "all" );
}
find_gaps()
{
}
are_enemies_horded()
{
const MINIMUM_PERCENT_TO_BE_HORDE = 0.9;
const DISTANCE_SQ = 120 * 120;
zombies = get_zombies();
amount_in_horde = 0;
max_eligible_zombies = isDefined( level.speed_change_round ) ? zombies.size - level.speed_change_num : zombies.size;
expected_amount_in_horde_min = int( max_eligible_zombies * MINIMUM_PERCENT_TO_BE_HORDE );
if ( isDefined( level.speed_change_round ) )
{
for ( i = 0; i < zombies.size; i++ )
{
if ( zombies[ i ].zombie_move_speed == "walk" )
{
continue;
}
if ( !isDefined( zombies[ i + 1 ] ) )
{
return false;
}
if ( zombies[ i + 1 ].zombie_move_speed != "walk" )
{
if ( distanceSquared( zombies[ i + 1 ].origin, zombies[ i ].origin ) <= DISTANCE_SQ )
{
amount_in_horde++;
}
}
if ( amount_in_horde >= expected_amount_in_horde_min )
{
return true;
}
}
}
else
{
for ( i = 0; i < zombies.size; i++ )
{
if ( !isDefined( zombies[ i + 1 ] ) )
{
return false;
}
if ( distanceSquared( zombies[ i + 1 ].origin, zombies[ i ].origin ) <= DISTANCE_SQ )
{
amount_in_horde++;
}
if ( amount_in_horde >= expected_amount_in_horde_min )
{
return true;
}
}
}
return false;
}
any_enemies_in_direction( dir )
{
}
predict_entity_position_frames( frames )
{
current_velocity = self getVelocity();
predicted_origin = self.origin;
for ( i = 0; i < frames; i++ )
{
predicted_origin += ( current_velocity / 20 );
}
return predicted_origin;
}
predict_entity_position_seconds( seconds )
{
current_velocity = self getVelocity();
predicted_origin = self.origin;
for ( i = 0; i < seconds; i++ )
{
predicted_origin += current_velocity;
}
return predicted_origin;
}
any_zombies_targeting_self()
{
const ZOMBIE_TARGETING_DIST_SQ = 10 * 10;
zombies = get_zombies();
if ( !array_validate( zombies ) )
{
return false;
}
for ( i = 0; i < zombies.size; i++ )
{
if ( isDefined( zombies[ i ].favoriteenemy ) && zombies[ i ].favoriteenemy == self )
{
return true;
}
if ( isDefined( zombies[ i ].goal_pos ) && distanceSquared( zombies[ i ].goal_pos, self.origin ) < ZOMBIE_TARGETING_DIST_SQ )
{
return true;
}
}
return false;
}
bot_is_in_danger( player )
{
return false;
}
bot_valid( player )
{
if ( !isdefined( player ) )
return false;
if ( !isalive( player ) )
return false;
if ( !isplayer( player ) )
return false;
if ( !is_true( player.pers[ "isBot" ] ) )
return false;
if ( isdefined( player.is_zombie ) && player.is_zombie == 1 )
return false;
if ( player.sessionstate == "spectator" )
return false;
if ( player.sessionstate == "intermission" )
return false;
if ( isdefined( player.intermission ) && player.intermission )
return false;
if ( isdefined( level.is_player_valid_override ) )
return [[ level.is_player_valid_override ]]( player );
return true;
}
assign_priority_to_powerup( powerup )
{
if ( !isDefined( powerup ) )
{
return;
}
priority = 0;
powerup_is_max_ammo = false;
switch ( powerup.powerup_name )
{
case "zombie_blood":
case "insta_kill":
case "nuke":
priority += 2;
break;
case "full_ammo":
powerup_is_max_ammo = true;
priority += 1;
break;
case "double_points":
case "fire_sale":
case "carpenter":
case "free_perk":
priority += 1;
break;
default:
priority += 0;
break;
}
if ( powerup_is_max_ammo )
{
const LOW_AMMO_THRESHOLD = 0.3;
for ( i = 0; i < level.players.size; i++ )
{
weapons = level.players[ i ] getWeaponsListPrimaries();
for ( j = 0; j < weapons.size; j++ )
{
if ( self getWeaponAmmoStock( weapons[ j ] ) <= int( weaponmaxammo( weapons[ j ] ) * LOW_AMMO_THRESHOLD ) )
{
priority += 1;
break;
}
}
if ( priority > 3 )
{
break;
}
}
}
if ( maps\mp\zombies\_zm_laststand::player_any_player_in_laststand() )
{
switch ( powerup.powerup_name )
{
case "zombie_blood":
case "insta_kill":
case "nuke":
priority += 1;
break;
case "full_ammo":
priority += 0;
break;
case "double_points":
case "fire_sale":
case "carpenter":
case "free_perk":
priority -= 1;
break;
default:
priority += 0;
break;
}
}
if ( powerup.time_left_until_timeout < 10.0 )
{
priority += 1;
}
if ( priority < 0 )
{
priority = 0;
}
powerup.priority = priority;
}
sort_array_by_priority_field( array, item )
{
if ( isDefined( item ) )
{
array[ array.size ] = item;
}
priority_array = [];
for ( i = 0; i < array.size; i++ )
{
priority_array[ i ] = array[ i ].priority;
}
priority_array = quickSort( priority_array );
sorted_array = [];
for ( i = 0; i < priority_array.size; i++ )
{
for ( j = 0; j < array.size; j++ )
{
if ( array[ j ].priority == priority_array[ i ] )
{
sorted_array[ sorted_array.size ] = array[ j ];
}
}
}
return sorted_array;
}
/*
We need to calculate where the bot should go to next and update their movement constantly here
If the calculations predicts death or teammates death based on current course we need recalculate next move
Updating every frame(0.05) should be sufficient
Key to movement code is determining gaps, and safe lines to follow
Bot should try to find the nearest safe line and follow it
Due to many different variables(primarily resulting from other players) we need to constantly verify if the line is safe to follow
If the bot doesn't detect any danger allow them to stand still far enough away from the zombies to not draw aggro but close enough to shoot at them
Questions:
Can bots move and use the use button at the same time? Necessary to be able to support circle revive
How do we know the bot is safe where they are currently or where they will be moving to?
How do we determine gaps in zombies/terrain to slip through?
*/
movement_think()
{
while ( true )
{
}
}
/*
bot methods docs
enum BotGoalPriority
{
GOAL_PRIORITY_UNUSED = 0x0,
GOAL_PRIORITY_LOW = 0x1,
GOAL_PRIORITY_NORMAL = 0x2,
GOAL_PRIORITY_HIGH = 0x3,
GOAL_PRIORITY_URGENT = 0x4,
GOAL_PRIORITY_MAX = 0x5,
};
success = bot addGoal( <origin|pathnode>, float<goalRadius>, BotGoalPriority<priority>, string<notify> );
bot cancelGoal( string<notify> );
bot atGoal( string[notify] );
bot hasGoal( string<notify> );
origin = bot getGoal( string<notify> );
bot pressUseButton( float<time_in_seconds> );
bot pressAttackButton( float<time_in_seconds> );
bot pressDtpButton();
bot pressAds( <bool> );
bot pressMelee();
bot throwGrenade( string<weapon_name>, vector<destination> );
dist = bot getLookaheadDist();
dir = bot getLookAheadDir();
bot lookAt( vector<origin> );
bot clearLookat();
pos = bot predictPosition( entity<ent>, int<num_frames> );
success = bot sightTracePassed( entity<ent>, vector[point] );
enemies = bot getThreats( float<fov> ); //Fov value can be -1 to find all enemies instead of enemies in fov.
bot botSetFailsafeNode( pathnode[node] );
player methods docs
player allowStand( <bool> );
player allowCrouch( <bool> );
player allowProne( <bool> );
player allowAds( <bool> );
player allowSprint( <bool> );
player allowMelee( <bool> );
player setSpawnWeapon( string<weapon_name> );
player isLookingAt( <entity> );
ads_amount = player playerAds();
stance = player getstance();
player setStance( string<stance> );
dot = player playerSightTrace( vector<item_position>, int<unk>, int<hitnum> );
entity methods docs
mins = entity getMins();
maxes = entity getMaxes();
absmins = entity getAdbMins();
absmaxes = entity getAbsMaxes();
eye = entity getEye();
centroid = entity getCentroid()
velocity = entity getVelocity();
vector = entity getpointinbounds( float<x>, float<y>, float<z> );
is_touching = entity isTouching( entity<ent>, vector[extra_boundary] );
is_touching = entity isTouchingVolume( vector<origin>, vector<mins>, vector<maxes> );
dot = entity damageConeTrace( vector<damage_origin>, entity[ent], vector[damage_angles], float[damage_amount] );
dot = entity sightConeTrace( vector<damage_origin>, entity[ent], vector[damage_angles], float[damage_amount] );
common functions docs
nodeStringTable = {
"Path",
"Cover Stand",
"Cover Crouch",
"Cover Crouch Window",
"Cover Prone",
"Cover Right",
"Cover Left",
"Cover Pillar",
"Ambush",
"Exposed",
"Conceal Stand",
"Conceal Crouch",
"Conceal Prone",
"Reacquire",
"Balcony",
"Scripted",
"Begin",
"End",
"Turret",
"Guard"
}
enum team_t
{
TEAM_FREE = 0x0,
TEAM_BAD = 0x0,
TEAM_ALLIES = 0x1,
TEAM_AXIS = 0x2,
TEAM_THREE = 0x3,
TEAM_FOUR = 0x4,
TEAM_FIVE = 0x5,
TEAM_SIX = 0x6,
TEAM_SEVEN = 0x7,
TEAM_EIGHT = 0x8,
TEAM_NUM_PLAYING_TEAMS = 0x9,
TEAM_SPECTATOR = 0x9,
TEAM_NUM_TEAMS = 0xA,
TEAM_LOCALPLAYERS = 0xB,
TEAM_FIRST_PLAYING_TEAM = 0x1,
TEAM_LAST_PLAYING_TEAM = 0x8,
};
nodespawn_t nodespawns[21]
{
'node_pathnode'
'node_guard'
'node_turret'
'node_negotiation_end'
'node_negotiation_begin'
'node_scripted'
'node_balcony'
'node_reacquire'
'node_concealment_prone'
'node_concealment_crouch'
'node_concealment_stand'
'node_exposed'
'node_ambush'
'node_cover_pillar'
'node_cover_left'
'node_cover_right'
'node_cover_prone'
'node_cover_crouch_window'
'node_cover_crouch'
'node_cover_stand'
}
node = getNode( string<name>, entkey<key> );
nodes = getNodeArray( string<name>, entkey<key );
nodes = getNodeArraySorted( string<name>, entkey<key>, vector[origin], float[max_dist] );
nodes = getAnyNodeArray( vector<origin>, float<max_dist> );
nodes = getCoverNodeArray( vector<origin>, float<max_dist> );
nodes = getAllNodes();
nodes = getNodesInRadius( vector<origin>, float<max_radius>, float<min_radius>, float[max_height], nodeStringTable[type], int<max_nodes> );
nodes = getNodesInRadiusSorted( vector<origin>, float<max_radius>, float<min_radius>, float[max_height], nodeStringTable[type], int<max_nodes> );
node = getNearestNode( vector<origin> );
node = getVisibleNode( vector<start>, vector<end>, entity[ent] );
nodes = getVisibleNodes( node_ent<node> );
visible = nodesVisible( node_ent<node>, node_ent<node> );
canpath = nodesCanPath( node_ent<node>, node_ent<node> );
canclaimnode = canClaimNode( node_ent<node>, team_t<team> );
setEnableNode( node_ent<node>, [bool] );
linkNodes( node_ent<node>, node_ent<node> );
unLinkNodes( node_ent<node>, node_ent<node> );
nodesAreLinked( node_ent<node>, node_ent<node> );
dropnodetofloor( node_ent<node> );
node = spawnPathNode( nodespawn_t<classname>, vector<origin>, vector<angles>, key[key1], value[val1], ... );
deletePathNode( node_ent<node> );
occupied = isNodeOccupied( node_ent<node> );
nodeowner = getNodeOwner( node_ent<node> );
foundpath = findPath( vector<start>, vector<end>, entity[ent], bool[allow_negotiation_links], bool[allow_negotiation_hints] );
vector = vectorFromLineToPoint( vector<<start_pos>, vector<end_pos>, vector<point> );
point = pointOnSegmentNearestToPoint( vector<start_pos>, vector<end_pos>, vector<test_origin> );
pos_a_is_closer = closer( vector<ref_pos>, vector<a>, vector<b> );
dot = vectorDot( vector<a>, vector<b> );
cross = vectorCross( vector<a>, vector<b> );
normalized_vector = vectorNormalize( vector<vec> );
lerped_vector = vectorLerp( vector<from>, vector<to>, float<lerp> );
combined_angles = combineAngles( vector<a>, vector<b> );
angles = vectorToAngles( vector<vec> );
angle = absAngleClamp180( float<angle> );
angle = absAngleClamp360( float<angle> );
point = rotatePoint( vector<point>, vector<angles> );
trace
{
"fraction",
"position",
"entity",
"normal",
"surfacetype"
}
trace = bulletTrace( vector<end_pos>, vector<start_pos>, bool<use_content_mask_flag>, entity<ignore_ent>, bool[modify_contents_flags1], bool[modify_contents_flags2] );
passed = bulletTracePassed( vector<start_pos>, vector<end_pos>, bool<use_clipmask>, entity<ignore_ent>, entity[ignore_ent2?], bool[check_fx_visibility] );
trace = groundTrace( vector<end_pos>, vector<start_pos>, bool<use_content_mask_flag>, entity<ignore_ent>, bool[modify_contents_flags1], bool[modify_contents_flags2] );
passed = sightTracePassed( vector<start_pos>, vector<end_pos>, bool<use_clipmask>, entity<ignore_ent> );
player_physics_trace = playerPhysicsTrace( vector<end_pos>, vector<start_pos> );
trace = physicsTrace( vector<end_pos>, vector<smins>, vector[maxes], vector[end_pos], entity[ignore_ent] );
trace = worldTrace( vector<end_pos>, vector<start_pos> );
? customs functions to add
node = bot getNextNodeInPath( vector<start>, vector<end>, entity[ent], bool[allow_negotiation_links], bool[allow_negotiation_hints] );
bot botMovementOverride( byte<forward>, byte<right> );
self botButtonOverride( string<button>, string<value> );
self botClearMovementOverride();
self botClearButtonOverride( string<value> );
*/