‪Black Ops 3 Source Code Explorer  0.1
‪An script explorer for Black Ops 3 by ZeRoY
_bot.gsc
Go to the documentation of this file.
1 #using scripts\codescripts\struct;
2 #using scripts\shared\array_shared;
3 #using scripts\shared\callbacks_shared;
4 #using scripts\shared\killstreaks_shared;
5 #using scripts\shared\math_shared;
6 #using scripts\shared\rank_shared;
7 #using scripts\shared\system_shared;
8 #using scripts\shared\util_shared;
9 #using scripts\shared\weapons_shared;
10 #using scripts\shared\weapons\_weapons;
11 
12 #using scripts\shared\bots\_bot;
13 #using scripts\shared\bots\_bot_combat;
14 #using scripts\shared\bots\bot_traversals;
15 #using scripts\shared\bots\bot_buttons;
16 #using scripts\mp\bots\_bot_combat;
17 #using scripts\mp\bots\_bot_dom;
18 #using scripts\mp\bots\_bot_koth;
19 #using scripts\mp\bots\_bot_loadout;
20 #using scripts\mp\bots\_bot_sd;
21 #using scripts\mp\bots\_bot_ctf;
22 #using scripts\mp\killstreaks\_killstreakrules;
23 #using scripts\mp\killstreaks\_killstreaks;
24 #using scripts\mp\killstreaks\_uav;
25 #using scripts\mp\killstreaks\_satellite;
26 #using scripts\mp\killstreaks\_emp;
27 #using scripts\mp\teams\_teams;
28 #using scripts\mp\_util;
29 
30 #insert scripts\shared\shared.gsh;
31 #insert scripts\mp\bots\_bot.gsh;
32 
33 #define MAX_LOCAL_PLAYERS 10
34 #define MAX_ONLINE_PLAYERS 18
35 #define MAX_ONLINE_PLAYERS_PER_TEAM 6
36 
37 #define RESPAWN_DELAY 0.1
38 #define RESPAWN_INTERVAL 0.1
39 
40 #namespace bot;
41 
42 ‪REGISTER_SYSTEM( "bot_mp", &‪__init__, undefined )
43 
44 function ‪__init__()
45 {
47 
48  level.getBotSettings = &‪get_bot_settings;
49 
50  level.onBotConnect = &‪on_bot_connect;
51  level.onBotSpawned = &‪on_bot_spawned;
52  level.onBotKilled = &‪on_bot_killed;
53 
54  level.botIdle = &‪bot_idle;
55 
56  level.botThreatLost = &‪bot_combat::chase_threat;
57 
58  level.botPreCombat = &‪bot_combat::mp_pre_combat;
59  level.botCombat = &‪bot_combat::combat_think;
60  level.botPostCombat = &‪bot_combat::mp_post_combat;
61 
62  level.botIgnoreThreat = &‪bot_combat::bot_ignore_threat;
63 
64  level.enemyEmpActive = &emp::EnemyEmpActive;
65 }
66 
67 function ‪init()
68 {
69  level endon( "game_ended" );
70 
71  level.botSoak = ‪is_bot_soak();
72 
73  if ( ( level.rankedMatch && !level.botSoak ) || !‪init_bot_gametype() )
74  {
75  return;
76  }
77 
79 
80  level thread ‪populate_bots();
81 }
82 
83 // Init Utils
84 //========================================
85 
86 function ‪is_bot_soak()
87 {
88  return IsDedicated() && GetDvarInt( "sv_botsoak", 0 );
89 }
90 
91 function ‪wait_for_host()
92 {
93  level endon( "game_ended" );
94 
95  if ( level.botSoak )
96  {
97  return;
98  }
99 
101 
102  while ( !isdefined( host ) )
103  {
104  wait( 0.25 );
106  }
107 }
108 
110 {
112 
113  if ( !isdefined( host ) || host.team == "spectator" )
114  {
115  return "allies";
116  }
117 
118  return host.team;
119 }
120 
122 {
123  return false;
124 }
125 
126 
127 // Bot Events
128 //========================================
129 
131 {
132  self endon( "disconnect" );
133  level endon( "game_ended" );
134 
135  if ( ‪IS_TRUE( level.disableClassSelection ) )
136  {
137  self ‪set_rank();
138 
139  // Doesn't work if we don't do it in this order
142 
143  return;
144  }
145 
146  if ( !‪IS_TRUE( self.pers["bot_loadout"] ) )
147  {
148  self ‪set_rank();
149 
150  // Doesn't work if we don't do it in this order
154 
155  self.pers["bot_loadout"] = true;
156  }
157 
159  self ‪choose_class();
160 }
161 
163 {
164  self.bot.goalTag = undefined;
165 }
166 
168 {
169  self endon("disconnect");
170  level endon( "game_ended" );
171  self endon( "spawned" );
172  self waittill ( "death_delay_finished" );
173 
174  wait ‪RESPAWN_DELAY;
175 
176  if ( self ‪choose_class() && level.playerForceRespawn )
177  {
178  return;
179  }
180 
181  self thread ‪respawn();
182 }
183 
184 function ‪respawn()
185 {
186  self endon( "spawned" );
187  self endon( "disconnect" );
188  level endon( "game_ended" );
189 
190  while( 1 )
191  {
192  self ‪bot::tap_use_button();
193 
194  wait ‪RESPAWN_INTERVAL;
195  }
196 }
197 
198 function ‪bot_idle()
199 {
200  if ( self ‪do_supplydrop() )
201  {
202  return;
203  }
204 
205  // TODO: Look for an enemy radar blip
206  // TODO: Get points on navmesh and feed into the spawn system to see if an enemy is likely to spawn there
207  self ‪bot::navmesh_wander();
208  self ‪bot::sprint_to_goal();
209 }
210 
211 // Crate maxs: 23.1482
212 #define CRATE_GOAL_RADIUS 39
213 #define CRATE_USE_RADIUS 62 // Wild guess on usable radius
214 
215 function ‪do_supplydrop( maxRange = 1400 ) // A little under minimap width
216 {
217  crates = GetEntArray( "care_package", "script_noteworthy" );
218 
219  maxRangeSq = maxRange * maxRange;
220 
222 
223  closestCrate = undefined;
224  closestCrateDistSq = undefined;
225 
226  foreach( crate in crates )
227  {
228  if ( !crate IsOnGround() )
229  {
230  continue;
231  }
232 
233  crateDistSq = Distance2DSquared( self.origin, crate.origin );
234 
235  if ( crateDistSq > maxRangeSq )
236  {
237  continue;
238  }
239 
240  inUse = isdefined( crate.useEnt ) && ‪IS_TRUE( crate.useEnt.inUse );
241 
242  if ( crateDistSq <= useRadiusSq )
243  {
244  if ( inUse && !self useButtonPressed() )
245  {
246  continue;
247  }
248 
250  return true;
251  }
252 
253  if ( !self ‪has_minimap() && !self BotSightTracePassed( crate ) )
254  {
255  continue;
256  }
257 
258  if ( !isdefined( closestCrate ) || crateDistSq < closestCrateDistSq )
259  {
260  closestCrate = crate;
261  closestCrateDistSq = crateDistSq;
262  }
263  }
264 
265  if ( isdefined( closestCrate ) )
266  {
267  randomAngle = ( 0, RandomInt( 360 ), 0 );
268  randomVec = AnglesToForward( randomAngle );
269 
270  point = closestCrate.origin + randomVec * ‪CRATE_GOAL_RADIUS;
271 
272  if ( self BotSetGoal( point ) )
273  {
274  self thread ‪watch_crate( closestCrate );
275  return true;
276  }
277  }
278 
279  return false;
280 }
281 
282 function ‪watch_crate( crate )
283 {
284  self endon( "death" );
285  self endon( "bot_goal_reached" );
286  level endon( "game_ended" );
287 
288  while ( isdefined( crate ) && !self ‪bot_combat::has_threat() )
289  {
290  wait level.botSettings.thinkInterval;
291  }
292 
293  self BotSetGoal( self.origin );
294 }
295 
296 // Bot Team Population
297 //========================================
298 
300 {
301  level endon( "game_ended" );
302 
303  if ( level.teambased )
304  {
305  maxAllies = GetDvarInt( "bot_maxAllies", 0 );
306  maxAxis = GetDvarInt( "bot_maxAxis", 0 );
307 
308  level thread ‪monitor_bot_team_population( maxAllies, maxAxis );
309  }
310  else
311  {
312  maxFree = GetDvarInt( "bot_maxFree", 0 );
313 
314  level thread ‪monitor_bot_population( maxFree );
315  }
316 }
317 
318 function ‪monitor_bot_team_population( maxAllies, maxAxis )
319 {
320  level endon( "game_ended" );
321 
322  if ( !maxAllies && !maxAxis )
323  {
324  return;
325  }
326 
327  ‪fill_balanced_teams( maxAllies, maxAxis );
328 
329  while ( 1 )
330  {
331  wait 3;
332 
333  // TODO: Get a player count that includes 'CON_CONNECTING' players
334  allies = GetPlayers( "allies" );
335  axis = GetPlayers( "axis" );
336 
337  if ( allies.size > maxAllies &&
338  ‪remove_best_bot( allies ) )
339  {
340  continue;
341  }
342 
343  if ( axis.size > maxAxis &&
344  ‪remove_best_bot( axis ) )
345  {
346  continue;
347  }
348 
349  if ( allies.size < maxAllies || axis.size < maxAxis )
350  {
351  ‪add_balanced_bot( allies, maxAllies, axis, maxAxis );
352  }
353  }
354 }
355 
356 function ‪fill_balanced_teams( maxAllies, maxAxis )
357 {
358  allies = GetPlayers( "allies" );
359  axis = GetPlayers( "axis" );
360 
361  while ( ( allies.size < maxAllies || axis.size < maxAxis ) &&
362  ‪add_balanced_bot( allies, maxAllies, axis, maxAxis ) )
363  {
365 
366  allies = GetPlayers( "allies" );
367  axis = GetPlayers( "axis" );
368  }
369 }
370 
371 function ‪add_balanced_bot( allies, maxAllies, axis, maxAxis )
372 {
373  bot = undefined;
374 
375  if ( allies.size < maxAllies &&
376  ( allies.size <= axis.size || axis.size >= maxAxis ) )
377  {
378  bot = ‪add_bot( "allies" );
379  }
380  else if ( axis.size < maxAxis )
381  {
382  bot = ‪add_bot( "axis" );
383  }
384 
385  return isdefined( bot );
386 }
387 
388 function ‪monitor_bot_population( maxFree )
389 {
390  level endon( "game_ended" );
391 
392  if ( !maxFree )
393  {
394  return;
395  }
396 
397  // Initial Fill
398  players = GetPlayers( );
399  while ( players.size < maxFree )
400  {
401  ‪add_bot();
403  players = GetPlayers( );
404  }
405 
406  while ( 1 )
407  {
408  wait 3;
409 
410  // TODO: Get a player count that includes 'CON_CONNECTING' players
411  players = GetPlayers( );
412 
413  if ( players.size < maxFree )
414  {
415  ‪add_bot();
416  }
417  else if ( players.size > maxFree )
418  {
419  ‪remove_best_bot( players );
420  }
421  }
422 }
423 
424 function ‪remove_best_bot( players )
425 {
426  bots = ‪filter_bots( players );
427 
428  if ( !bots.size )
429  {
430  return false;
431  }
432 
433  // Prefer non-combat bots
434  bestBots = [];
435 
436  foreach( bot in bots )
437  {
438  // Don't kick bots in the process of connecting
439  if ( bot.sessionstate == "spectator" )
440  {
441  continue;
442  }
443 
444  if ( bot.sessionstate == "dead" || !bot ‪bot_combat::has_threat() )
445  {
446  bestBots[bestBots.size] = bot;
447  }
448  }
449 
450  if ( bestBots.size )
451  {
452  ‪remove_bot( bestBots[RandomInt( bestBots.size )] );
453  }
454  else
455  {
456  ‪remove_bot( bots[RandomInt( bots.size )] );
457  }
458 
459  return true;
460 }
461 
462 // Bot Loadouts
463 //========================================
464 
465 function ‪choose_class()
466 {
467  if ( ‪IS_TRUE( level.disableClassSelection ) )
468  {
469  return false;
470  }
471 
472  currClass = self ‪bot_loadout::get_current_class();
473 
474  if ( !isdefined( currClass ) || RandomInt( 100 ) < ‪VAL( level.botSettings.changeClassWeight, 0 ) )
475  {
476  classIndex = RandomInt( self.loadoutClasses.size );
477  className = self.loadoutClasses[classIndex].name;
478  }
479 
480  if ( !isdefined(className) || className === currClass )
481  {
482  return false;
483  }
484 
485  self notify( "menuresponse", ‪MENU_CHANGE_CLASS, className );
486 
487  return true;
488 }
489 
490 // Killstreaks
491 //========================================
492 
494 {
495  if ( !level.loadoutKillstreaksEnabled ||
496  self ‪emp::EnemyEMPActive() )
497  {
498  return;
499  }
500 
501  weapons = self GetWeaponsList();
502  inventoryWeapon = self GetInventoryWeapon();
503 
504  foreach( weapon in weapons )
505  {
506  killstreak = ‪killstreaks::get_killstreak_for_weapon( weapon );
507 
508  if ( !isdefined( killstreak ) )
509  {
510  continue;
511  }
512 
513  if ( weapon != inventoryWeapon && !self GetWeaponAmmoClip( weapon ) )
514  {
515  continue;
516  }
517 
518  if ( self ‪killstreakrules::isKillstreakAllowed( killstreak, self.team ) )
519  {
520  useWeapon = weapon;
521  break;
522  }
523  }
524 
525  if ( !isdefined( useWeapon ) )
526  {
527  return;
528  }
529 
530  killstreak_ref = ‪killstreaks::get_menu_name( killstreak );
531 
532  switch( killstreak_ref )
533  {
534  case "killstreak_uav":
535  case "killstreak_counteruav":
536  case "killstreak_satellite":
537  case "killstreak_helicopter_player_gunner":
538  case "killstreak_raps":
539  case "killstreak_sentinel":
540  self SwitchToWeapon( useWeapon );
541  break;
542  }
543 }
544 
545 
546 function ‪has_radar()
547 {
548  if ( level.teambased )
549  {
550  return ( ‪uav::HasUAV( self.team ) || ‪satellite::HasSatellite( self.team ) );
551  }
552 
553  return ( ‪uav::HasUAV( self.entnum ) || ‪satellite::HasSatellite( self.entnum ) );
554 }
555 
556 function ‪has_minimap()
557 {
558  if ( self IsEmpJammed() )
559  {
560  return false;
561  }
562 
563  if ( ‪IS_TRUE( level.hardcoreMode ) )
564  {
565  return self ‪has_radar();
566  }
567 
568  return true;
569 }
570 
571 function ‪get_enemies( on_radar )
572 {
573  if ( !isdefined( on_radar ) )
574  {
575  on_radar = false;
576  }
577 
578  enemies = self GetEnemies();
579 
580  if ( on_radar && !self ‪has_radar() )
581  {
582  for ( i = 0; i < enemies.size; i++ )
583  {
584  if ( !isdefined( enemies[i].lastFireTime ) )
585  {
586  ArrayRemoveIndex( enemies, i );
587  i--;
588  }
589  else if ( GetTime() - enemies[i].lastFireTime > 2000 )
590  {
591  ArrayRemoveIndex( enemies, i );
592  i--;
593  }
594  }
595  }
596 
597  return enemies;
598 }
599 
600 function ‪set_rank()
601 {
602  players = GetPlayers();
603 
604  ranks = [];
605  bot_ranks = [];
606  human_ranks = [];
607 
608  for ( i = 0; i < players.size; i++ )
609  {
610  if ( players[i] == self )
611  continue;
612 
613  if ( isdefined( players[i].pers[ "rank" ] ) )
614  {
615  if ( players[i] ‪util::is_bot() )
616  {
617  bot_ranks[ bot_ranks.size ] = players[i].pers[ "rank" ];
618  }
619  else
620  {
621  human_ranks[ human_ranks.size ] = players[i].pers[ "rank" ];
622  }
623  }
624  }
625 
626  if( !human_ranks.size )
627  human_ranks[ human_ranks.size ] = 10;
628 
629  human_avg = ‪math::array_average( human_ranks );
630 
631  while ( bot_ranks.size + human_ranks.size < 5 )
632  {
633  // add some random ranks for better random number distribution
634  r = human_avg + RandomIntRange( -5, 5 );
635  rank = ‪math::clamp( r, 0, level.maxRank );
636  human_ranks[ human_ranks.size ] = rank;
637  }
638 
639  ranks = ArrayCombine( human_ranks, bot_ranks, true, false );
640 
641  avg = ‪math::array_average( ranks );
642  s = ‪math::array_std_deviation( ranks, avg );
643 
644  rank = Int( ‪math::random_normal_distribution( avg, s, 0, level.maxRank ) );
645 
646  while ( !isdefined( self.pers["codpoints"] ) )
647  {
648  wait 0.1;
649  }
650 
651  self.pers[ "rank" ] = rank;
652  self.pers[ "rankxp" ] = ‪rank::getRankInfoMinXP( rank );
653 
654  self setRank( rank );
655  self ‪rank::syncXPStat();
656 }
657 
659 {
660  switch( level.gameType )
661  {
662  case "dm":
663  return true;
664  case "dom":
666  return true;
667  case "koth":
669  return true;
670  case "sd":
671  ‪bot_sd::init();
672  return true;
673  case "tdm":
674  return true;
675  }
676 
677  return false;
678 }
679 
681 {
682  switch ( GetDvarInt( "bot_difficulty", 1 ) )
683  {
684  case 0:
685  bundleName = "bot_mp_easy";
686  break;
687 
688  case 1:
689  bundleName = "bot_mp_normal";
690  break;
691  case 2:
692  bundleName = "bot_mp_hard";
693  break;
694  case 3:
695  default:
696  bundleName = "bot_mp_veteran";
697  break;
698  }
699 
700  return ‪struct::get_script_bundle( "botsettings", bundleName );
701 }
702 
703 function ‪friend_goal_in_radius( goal_name, origin, radius )
704 {
705  return 0;
706 }
707 
708 function ‪friend_in_radius( goal_name, origin, radius )
709 {
710  return false;
711 }
712 
713 function ‪get_friends()
714 {
715  return [];
716 }
717 
718 function ‪get_closest_enemy( origin, someFlag )
719 {
720  return undefined;
721 }
722 
723 function ‪bot_vehicle_weapon_ammo( weaponName )
724 {
725  return false;
726 }
727 
728 function ‪navmesh_points_visible( origin, point )
729 {
730  return false;
731 }
732 
733 function ‪dive_to_prone( exit_stance )
734 {
735 
736 }
737 
‪mp_post_combat
‪function mp_post_combat()
Definition: _bot_combat.gsc:87
‪CRATE_GOAL_RADIUS
‪#define CRATE_GOAL_RADIUS
Definition: _bot.gsc:212
‪filter_bots
‪function filter_bots(players)
Definition: _bot.gsc:177
‪MENU_CHANGE_CLASS
‪#define MENU_CHANGE_CLASS
Definition: shared.gsh:461
‪init_bot_gametype
‪function init_bot_gametype()
Definition: _bot.gsc:658
‪is_bot
‪function is_bot()
Definition: util_shared.gsc:2488
‪build_classes
‪function build_classes()
Definition: _bot_loadout.gsc:125
‪choose_class
‪function choose_class()
Definition: _bot.gsc:465
‪has_threat
‪function has_threat()
Definition: _bot_combat.gsc:93
‪bot_vehicle_weapon_ammo
‪function bot_vehicle_weapon_ammo(weaponName)
Definition: _bot.gsc:723
‪watch_crate
‪function watch_crate(crate)
Definition: _bot.gsc:282
‪tap_use_button
‪function tap_use_button()
Definition: bot_buttons.gsc:58
‪RESPAWN_DELAY
‪#define RESPAWN_DELAY
Definition: _bot.gsc:37
‪on_start_gametype
‪function on_start_gametype(func, obj)
Definition: callbacks_shared.csc:285
‪wait_for_host
‪function wait_for_host()
Definition: _bot.gsc:91
‪respawn
‪function respawn()
Definition: _bot.gsc:184
‪VAL
‪#define VAL(__var, __default)
Definition: shared.gsh:272
‪array_std_deviation
‪function array_std_deviation(array, mean)
Definition: math_shared.csc:111
‪get_menu_name
‪function get_menu_name(killstreakType)
Definition: _killstreaks.gsc:435
‪get_friends
‪function get_friends()
Definition: _bot.gsc:713
‪on_bot_spawned
‪function on_bot_spawned()
Definition: _bot.gsc:162
‪get_enemies
‪function get_enemies(on_radar)
Definition: _bot.gsc:571
‪on_bot_connect
‪function on_bot_connect()
Definition: _bot.gsc:130
‪on_bot_killed
‪function on_bot_killed()
Definition: _bot.gsc:167
‪monitor_bot_population
‪function monitor_bot_population(maxFree)
Definition: _bot.gsc:388
‪EnemyEMPActive
‪function EnemyEMPActive()
Definition: _emp.gsc:365
‪IS_TRUE
‪#define IS_TRUE(__a)
Definition: shared.gsh:251
‪init
‪function init()
Definition: _bot.gsc:67
‪get_host_team
‪function get_host_team()
Definition: _bot.gsc:109
‪use_killstreak
‪function use_killstreak()
Definition: _bot.gsc:493
‪bot_idle
‪function bot_idle()
Definition: _bot.gsc:198
‪fill_balanced_teams
‪function fill_balanced_teams(maxAllies, maxAxis)
Definition: _bot.gsc:356
‪get_closest_enemy
‪function get_closest_enemy(origin, someFlag)
Definition: _bot.gsc:718
‪get_killstreak_for_weapon
‪function get_killstreak_for_weapon(weapon)
Definition: _killstreaks.gsc:1357
‪RESPAWN_INTERVAL
‪#define RESPAWN_INTERVAL
Definition: _bot.gsc:38
‪add_balanced_bot
‪function add_balanced_bot(allies, maxAllies, axis, maxAxis)
Definition: _bot.gsc:371
‪pick_killstreaks
‪function pick_killstreaks()
Definition: _bot_loadout.gsc:307
‪friend_in_radius
‪function friend_in_radius(goal_name, origin, radius)
Definition: _bot.gsc:708
‪remove_best_bot
‪function remove_best_bot(players)
Definition: _bot.gsc:424
‪random_normal_distribution
‪function random_normal_distribution(mean, std_deviation, lower_bound, upper_bound)
Definition: math_shared.gsc:454
‪add_bot
‪function add_bot(team)
Definition: _bot.gsc:105
‪friend_goal_in_radius
‪function friend_goal_in_radius(goal_name, origin, radius)
Definition: _bot.gsc:703
‪syncXPStat
‪function syncXPStat()
Definition: rank_shared.gsc:1049
‪isKillstreakAllowed
‪function isKillstreakAllowed(hardpointType, team)
Definition: _killstreakrules.gsc:352
‪is_bot_comp_stomp
‪function is_bot_comp_stomp()
Definition: _bot.gsc:121
‪chase_threat
‪function chase_threat()
Definition: _bot_combat.gsc:408
‪is_bot_soak
‪function is_bot_soak()
Definition: _bot.gsc:86
‪HasSatellite
‪function HasSatellite(team_or_entnum)
Definition: _satellite.gsc:259
‪combat_think
‪function combat_think()
Definition: _bot_combat.gsc:20
‪HasUAV
‪function HasUAV(team_or_entnum)
Definition: _uav.gsc:304
‪navmesh_wander
‪function navmesh_wander(fwd, radiusMin, radiusMax, spacing, fwdDot)
Definition: _bot.gsc:1000
‪set_rank
‪function set_rank()
Definition: _bot.gsc:600
‪dive_to_prone
‪function dive_to_prone(exit_stance)
Definition: _bot.gsc:733
‪REGISTER_SYSTEM
‪#define REGISTER_SYSTEM(__sys, __func_init_preload, __reqs)
Definition: shared.gsh:204
‪getRankInfoMinXP
‪function getRankInfoMinXP(rankId)
Definition: rank_shared.gsc:306
‪mp_pre_combat
‪function mp_pre_combat()
Definition: _bot_combat.gsc:52
‪getHostPlayerForBots
‪function getHostPlayerForBots()
Definition: util_shared.gsc:2916
‪populate_bots
‪function populate_bots()
Definition: _bot.gsc:299
‪pick_classes
‪function pick_classes()
Definition: _bot_loadout.gsc:202
‪has_radar
‪function has_radar()
Definition: _bot.gsc:546
‪monitor_bot_team_population
‪function monitor_bot_team_population(maxAllies, maxAxis)
Definition: _bot.gsc:318
‪get_script_bundle
‪function get_script_bundle(str_type, str_name)
Definition: struct.csc:45
‪get_bot_settings
‪function get_bot_settings()
Definition: _bot.gsc:680
‪bot_ignore_threat
‪function bot_ignore_threat(entity)
Definition: _bot_combat.gsc:27
‪do_supplydrop
‪function do_supplydrop(maxRange=1400)
Definition: _bot.gsc:215
‪clamp
‪function clamp(val, val_min, val_max)
Definition: math_shared.csc:16
‪CRATE_USE_RADIUS
‪#define CRATE_USE_RADIUS
Definition: _bot.gsc:213
‪remove_bot
‪function remove_bot(bot)
Definition: _bot.gsc:162
‪has_minimap
‪function has_minimap()
Definition: _bot.gsc:556
‪get_current_class
‪function get_current_class()
Definition: _bot_loadout.gsc:244
‪__init__
‪function __init__()
Definition: _bot.gsc:44
‪pick_hero_gadget
‪function pick_hero_gadget()
Definition: _bot_loadout.gsc:266
‪array_average
‪function array_average(array)
Definition: math_shared.csc:86
‪navmesh_points_visible
‪function navmesh_points_visible(origin, point)
Definition: _bot.gsc:728
‪sprint_to_goal
‪function sprint_to_goal()
Definition: _bot.gsc:454
‪press_use_button
‪function press_use_button()
Definition: bot_buttons.gsc:68
‪WAIT_SERVER_FRAME
‪#define WAIT_SERVER_FRAME
Definition: shared.gsh:265