From 63947c790942b5ee33d48944e05de5ed68d2443d Mon Sep 17 00:00:00 2001 From: cdnutter Date: Mon, 17 Jun 2024 19:49:09 -0700 Subject: [PATCH] try again --- .gitignore | 5 - bots.txt | 16 - maps/.DS_Store | Bin 6148 -> 0 bytes maps/mp/.DS_Store | Bin 6148 -> 0 bytes maps/mp/bots/.DS_Store | Bin 6148 -> 0 bytes maps/mp/bots/_bot.gsc | 1399 ---- maps/mp/bots/_bot_chat.gsc | 3158 --------- maps/mp/bots/_bot_internal.gsc | 3331 --------- maps/mp/bots/_bot_script.gsc | 8689 ------------------------ maps/mp/bots/_bot_utility.gsc | 3537 ---------- maps/mp/bots/_menu.gsc | 1389 ---- maps/mp/bots/_wp_editor.gsc | 916 --- maps/mp/bots/waypoints/_custom_map.gsc | 8 - maps/mp/perks/_perks.gsc | 400 -- maps/mp/perks/_perksfunctions.gsc | 1011 --- 15 files changed, 23859 deletions(-) delete mode 100644 .gitignore delete mode 100644 bots.txt delete mode 100644 maps/.DS_Store delete mode 100644 maps/mp/.DS_Store delete mode 100644 maps/mp/bots/.DS_Store delete mode 100644 maps/mp/bots/_bot.gsc delete mode 100644 maps/mp/bots/_bot_chat.gsc delete mode 100644 maps/mp/bots/_bot_internal.gsc delete mode 100644 maps/mp/bots/_bot_script.gsc delete mode 100644 maps/mp/bots/_bot_utility.gsc delete mode 100644 maps/mp/bots/_menu.gsc delete mode 100644 maps/mp/bots/_wp_editor.gsc delete mode 100644 maps/mp/bots/waypoints/_custom_map.gsc delete mode 100644 maps/mp/perks/_perks.gsc delete mode 100644 maps/mp/perks/_perksfunctions.gsc diff --git a/.gitignore b/.gitignore deleted file mode 100644 index d4c5cc2..0000000 --- a/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -logs -scriptdata -scripts -bots -maps/bots \ No newline at end of file diff --git a/bots.txt b/bots.txt deleted file mode 100644 index ee3860b..0000000 --- a/bots.txt +++ /dev/null @@ -1,16 +0,0 @@ -Jakob M. -Jonny R. -Kevin V. -Star M. -Cizin D. -Jared D. -Riley D. -Robert P. IV -Ralph G. -Tony B. -Jason O. -Ruben H. -Bruce J. -Chris J. -Joey M. -Xavier G. diff --git a/maps/.DS_Store b/maps/.DS_Store deleted file mode 100644 index ddb73bc9e11db301e61b5f4a07d6a6ee0fb33025..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK%}N6?5Kh`^Q$#4Dptpe6g4+s;cv;ta7F^MTO6|Hu7q^?GKklIv_O1`%J9zR1 zd;}lBCvhf8{h@l5A~P`glKDwC-)@r*V~l&lu+CVOF(yC}3l(U75cH!?Nx@p?0XfbQ z#43RPbCAZ-R5Tf8kpX;n1=eM0koD8A@2@{_oL62bmgeTmqAV7~g@2o)Et>fSKO;bYUXXmJ7$(9xTTuj~Gm>ZaOJ zK3tmEyQG6s zk1Vk;z1OP07Sqt>BmcSfo(Y2Tx1P=%|semSx z+Y*DDbg)Ys=UU7Snsml(@xkrN+*T-DuMYD|9nQFGkXmAZ82HXW(G072{~y3_`Iq|t zdlHR^0b<}^F~Cbrzv;o2?ADG-PI?tt6_}sV3zb4>oCRyC}P8f<{m*m>XtOD zWe!!9y_@6KT{Q>fHVM^l}UCL;*BI7{~JVe9y+Y`e9h)@WE+$X>kcZp|g6R z?7A0yQ{#ztwhmvd`^G8^?Z+y9{|f%ScK&?c^e2z{CpYVJ*SN%L-P>rIXDYu2+j5`i zCm{xi0b*cB7_di^Xz$2=XdA=;F|a!f;Q1gy5q*obL49;Uqe}ol2h3WakF^BmNQ=J3 z+8}s9xJd;xsoa(r+@ynD+Bn~0ZP27MZi^3YSLU`t;d*tLU+QqieS_2z1H`~415GpR z;QfF6aQ(lTL?dE=7R=cdZ1y0!6{N+Tbb$I{GSxSiFkgfocJ} Y#15cuu{H=65c(0&G*CkfJShYJ0mKJo#sB~S diff --git a/maps/mp/bots/.DS_Store b/maps/mp/bots/.DS_Store deleted file mode 100644 index 96abd559772240cb48ae943d6e61d0c58e870f7d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK%}N6?5T4O06)!z{%+YJ#U@hwt^aXUgpu)CUs3P9-az2k&kACx`v=~7zA~FNX zH<_Pg^Oa^2BI3nEKPQ?I(G*RPMX89GtF8kNJ_54Nk?D>$bWhuUTbbxDn&jJ0=#j4J ziALJ_{?*XsJYZWj_i!^`uJU@c9UY(7qt>}?yCHY*3V-G0_4(qf$o`v=L+ z7DHGdY^gv?Wq)F@rNf>)u5m1emQJiIV;*1m{qe$nCFZ2z#EoI}!9Xyu&%mJ#XHx$! z@mH!o^7m6>6bu9d|BL~iw99sZO?hqov^}Y{3GE6^MB<7l5a?Qpfm(_&kaOfro#s!X Z!{0a-LzzYFnhuPMfD#g2Fz^cuya6R diff --git a/maps/mp/bots/_bot.gsc b/maps/mp/bots/_bot.gsc deleted file mode 100644 index fe39e3a..0000000 --- a/maps/mp/bots/_bot.gsc +++ /dev/null @@ -1,1399 +0,0 @@ -/* - _bot - Author: INeedGames - Date: 09/26/2020 - The entry point and manager of the bots. -*/ - -#include common_scripts\utility; -#include maps\mp\_utility; -#include maps\mp\gametypes\_hud_util; -#include maps\mp\bots\_bot_utility; - -/* - Initiates the whole bot scripts. -*/ -init() -{ - level.bw_version = "2.3.0"; - - if ( getdvar( "bots_main" ) == "" ) - { - setdvar( "bots_main", true ); - } - - if ( !getdvarint( "bots_main" ) ) - { - return; - } - - if ( !wait_for_builtins() ) - { - println( "FATAL: NO BUILT-INS FOR BOTS" ); - } - - thread load_waypoints(); - thread hook_callbacks(); - - if ( getdvar( "bots_main_GUIDs" ) == "" ) - { - setdvar( "bots_main_GUIDs", "" ); // guids of players who will be given host powers, comma seperated - } - - if ( getdvar( "bots_main_firstIsHost" ) == "" ) - { - setdvar( "bots_main_firstIsHost", false ); // first play to connect is a host - } - - if ( getdvar( "bots_main_waitForHostTime" ) == "" ) - { - setdvar( "bots_main_waitForHostTime", 10.0 ); // how long to wait to wait for the host player - } - - if ( getdvar( "bots_main_kickBotsAtEnd" ) == "" ) - { - setdvar( "bots_main_kickBotsAtEnd", false ); // kicks the bots at game end - } - - if ( getdvar( "bots_manage_add" ) == "" ) - { - setdvar( "bots_manage_add", 0 ); // amount of bots to add to the game - } - - if ( getdvar( "bots_manage_fill" ) == "" ) - { - setdvar( "bots_manage_fill", 0 ); // amount of bots to maintain - } - - if ( getdvar( "bots_manage_fill_spec" ) == "" ) - { - setdvar( "bots_manage_fill_spec", true ); // to count for fill if player is on spec team - } - - if ( getdvar( "bots_manage_fill_mode" ) == "" ) - { - setdvar( "bots_manage_fill_mode", 0 ); // fill mode, 0 adds everyone, 1 just bots, 2 maintains at maps, 3 is 2 with 1 - } - - if ( getdvar( "bots_manage_fill_kick" ) == "" ) - { - setdvar( "bots_manage_fill_kick", false ); // kick bots if too many - } - - if ( getdvar( "bots_manage_fill_watchplayers" ) == "" ) - { - setdvar( "bots_manage_fill_watchplayers", false ); // add bots when player exists, kick if not - } - - if ( getdvar( "bots_team" ) == "" ) - { - setdvar( "bots_team", "autoassign" ); // which team for bots to join - } - - if ( getdvar( "bots_team_amount" ) == "" ) - { - setdvar( "bots_team_amount", 0 ); // amount of bots on axis team - } - - if ( getdvar( "bots_team_force" ) == "" ) - { - setdvar( "bots_team_force", false ); // force bots on team - } - - if ( getdvar( "bots_team_mode" ) == "" ) - { - setdvar( "bots_team_mode", 0 ); // counts just bots when 1 - } - - if ( getdvar( "bots_skill" ) == "" ) - { - setdvar( "bots_skill", 0 ); // 0 is random, 1 is easy 7 is hard, 8 is custom, 9 is completely random - } - - if ( getdvar( "bots_skill_axis_hard" ) == "" ) - { - setdvar( "bots_skill_axis_hard", 0 ); // amount of hard bots on axis team - } - - if ( getdvar( "bots_skill_axis_med" ) == "" ) - { - setdvar( "bots_skill_axis_med", 0 ); - } - - if ( getdvar( "bots_skill_allies_hard" ) == "" ) - { - setdvar( "bots_skill_allies_hard", 0 ); - } - - if ( getdvar( "bots_skill_allies_med" ) == "" ) - { - setdvar( "bots_skill_allies_med", 0 ); - } - - if ( getdvar( "bots_skill_min" ) == "" ) - { - setdvar( "bots_skill_min", 1 ); - } - - if ( getdvar( "bots_skill_max" ) == "" ) - { - setdvar( "bots_skill_max", 7 ); - } - - if ( getdvar( "bots_loadout_reasonable" ) == "" ) // filter out the bad 'guns' and perks - { - setdvar( "bots_loadout_reasonable", false ); - } - - if ( getdvar( "bots_loadout_allow_op" ) == "" ) // allows jug, marty and laststand - { - setdvar( "bots_loadout_allow_op", true ); - } - - 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 ); - } - - if ( getdvar( "bots_loadout_prestige" ) == "" ) // what pretige the bots will be, -1 is the players, -2 is random - { - setdvar( "bots_loadout_prestige", -1 ); - } - - if ( getdvar( "bots_play_move" ) == "" ) // bots move - { - setdvar( "bots_play_move", true ); - } - - if ( getdvar( "bots_play_knife" ) == "" ) // bots knife - { - setdvar( "bots_play_knife", true ); - } - - if ( getdvar( "bots_play_fire" ) == "" ) // bots fire - { - setdvar( "bots_play_fire", true ); - } - - if ( getdvar( "bots_play_nade" ) == "" ) // bots grenade - { - setdvar( "bots_play_nade", true ); - } - - if ( getdvar( "bots_play_take_carepackages" ) == "" ) // bots take carepackages - { - setdvar( "bots_play_take_carepackages", true ); - } - - if ( getdvar( "bots_play_obj" ) == "" ) // bots play the obj - { - setdvar( "bots_play_obj", true ); - } - - if ( getdvar( "bots_play_camp" ) == "" ) // bots camp and follow - { - setdvar( "bots_play_camp", true ); - } - - if ( getdvar( "bots_play_jumpdrop" ) == "" ) // bots jump and dropshot - { - setdvar( "bots_play_jumpdrop", true ); - } - - if ( getdvar( "bots_play_target_other" ) == "" ) // bot target non play ents (vehicles) - { - setdvar( "bots_play_target_other", true ); - } - - if ( getdvar( "bots_play_killstreak" ) == "" ) // bot use killstreaks - { - setdvar( "bots_play_killstreak", true ); - } - - if ( getdvar( "bots_play_ads" ) == "" ) // bot ads - { - setdvar( "bots_play_ads", true ); - } - - if ( getdvar( "bots_play_aim" ) == "" ) - { - setdvar( "bots_play_aim", true ); - } - - if ( !isdefined( game[ "botWarfare" ] ) ) - { - game[ "botWarfare" ] = true; - game[ "botWarfareInitTime" ] = gettime(); - } - - level.bot_inittime = gettime(); - - level.defuseobject = undefined; - level.bots_smokelist = List(); - level.bots_fraglist = List(); - - level.bots_minsprintdistance = 315; - level.bots_minsprintdistance *= level.bots_minsprintdistance; - level.bots_mingrenadedistance = 256; - level.bots_mingrenadedistance *= level.bots_mingrenadedistance; - level.bots_maxgrenadedistance = 1024; - level.bots_maxgrenadedistance *= level.bots_maxgrenadedistance; - level.bots_maxknifedistance = 128; - level.bots_maxknifedistance *= level.bots_maxknifedistance; - level.bots_goaldistance = 27.5; - level.bots_goaldistance *= level.bots_goaldistance; - level.bots_noadsdistance = 200; - level.bots_noadsdistance *= level.bots_noadsdistance; - level.bots_maxshotgundistance = 500; - level.bots_maxshotgundistance *= level.bots_maxshotgundistance; - level.bots_listendist = 100; - - level.smokeradius = 255; - - level.bots = []; - - level.bots_fullautoguns = []; - level.bots_fullautoguns[ "aa12" ] = true; - level.bots_fullautoguns[ "ak47" ] = true; - level.bots_fullautoguns[ "aug" ] = true; - level.bots_fullautoguns[ "fn2000" ] = true; - level.bots_fullautoguns[ "glock" ] = true; - level.bots_fullautoguns[ "kriss" ] = true; - level.bots_fullautoguns[ "m4" ] = true; - level.bots_fullautoguns[ "m240" ] = true; - level.bots_fullautoguns[ "masada" ] = true; - level.bots_fullautoguns[ "mg4" ] = true; - level.bots_fullautoguns[ "mp5k" ] = true; - level.bots_fullautoguns[ "p90" ] = true; - level.bots_fullautoguns[ "pp2000" ] = true; - level.bots_fullautoguns[ "rpd" ] = true; - level.bots_fullautoguns[ "sa80" ] = true; - level.bots_fullautoguns[ "scar" ] = true; - level.bots_fullautoguns[ "tavor" ] = true; - level.bots_fullautoguns[ "tmp" ] = true; - level.bots_fullautoguns[ "ump45" ] = true; - level.bots_fullautoguns[ "uzi" ] = true; - - level.bots_fullautoguns[ "ac130" ] = true; - level.bots_fullautoguns[ "heli" ] = true; - - level.bots_fullautoguns[ "ak47classic" ] = true; - level.bots_fullautoguns[ "ak74u" ] = true; - level.bots_fullautoguns[ "peacekeeper" ] = true; - - level thread fixGamemodes(); - level thread fixPredMissile(); - - level thread onPlayerConnect(); - level thread addNotifyOnAirdrops(); - level thread watchScrabler(); - - level thread handleBots(); - level thread onPlayerChat(); - - array_thread( getentarray( "misc_turret", "classname" ), ::turret_monitoruse_watcher ); -} - -/* - Change func pointer to ours, so that we can link the player ref to the rocket -*/ -fixPredMissile() -{ - for ( i = 0; i < 19; i++ ) - { - if ( isdefined( level.killstreakfuncs ) && isdefined( level.killstreakfuncs[ "predator_missile" ] ) ) - { - level.killstreakfuncs[ "predator_missile" ] = ::tryUsePredatorMissileFix; - break; - } - - wait 0.05; - } -} - -/* - Starts the threads for bots. -*/ -handleBots() -{ - level thread teamBots(); - level thread diffBots(); - level addBots(); - - while ( !level.intermission ) - { - wait 0.05; - } - - setdvar( "bots_manage_add", getBotArray().size ); - - if ( !getdvarint( "bots_main_kickBotsAtEnd" ) ) - { - return; - } - - bots = getBotArray(); - - for ( i = 0; i < bots.size; i++ ) - { - kick( bots[ i ] getentitynumber(), "EXE_PLAYERKICKED" ); - } -} - -/* - The hook callback for when any player becomes damaged. -*/ -onPlayerDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, timeOffset ) -{ - if ( self is_bot() ) - { - self maps\mp\bots\_bot_internal::onDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, timeOffset ); - self maps\mp\bots\_bot_script::onDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, timeOffset ); - } - - self [[ level.prevcallbackplayerdamage ]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, timeOffset ); -} - -/* - The hook callback when any player gets killed. -*/ -onPlayerKilled( eInflictor, eAttacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, timeOffset, deathAnimDuration ) -{ - if ( self is_bot() ) - { - self maps\mp\bots\_bot_internal::onKilled( eInflictor, eAttacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, timeOffset, deathAnimDuration ); - self maps\mp\bots\_bot_script::onKilled( eInflictor, eAttacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, timeOffset, deathAnimDuration ); - } - - self [[ level.prevcallbackplayerkilled ]]( eInflictor, eAttacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, timeOffset, deathAnimDuration ); -} - -/* - Starts the callbacks. -*/ -hook_callbacks() -{ - level waittill( "prematch_over" ); // iw4madmin waits this long for some reason... - wait 0.05; // so we need to be one frame after it sets up its callbacks. - level.prevcallbackplayerdamage = level.callbackplayerdamage; - level.callbackplayerdamage = ::onPlayerDamage; - - level.prevcallbackplayerkilled = level.callbackplayerkilled; - level.callbackplayerkilled = ::onPlayerKilled; -} - -/* - Fixes gamemodes when level starts. -*/ -fixGamemodes() -{ - for ( i = 0; i < 19; i++ ) - { - if ( isdefined( level.bombzones ) && level.gametype == "sd" ) - { - for ( i = 0; i < level.bombzones.size; i++ ) - { - level.bombzones[ i ].onuse = ::onUsePlantObjectFix; - } - - break; - } - - if ( isdefined( level.radios ) && level.gametype == "koth" ) - { - level thread fixKoth(); - - break; - } - - if ( isdefined( level.bombzones ) && level.gametype == "dd" ) - { - level thread fixDem(); - - break; - } - - wait 0.05; - } -} - -/* - Converts t5 dd to iw4 -*/ -fixDem() -{ - for ( ;; ) - { - level.bombaplanted = level.aplanted; - level.bombbplanted = level.bplanted; - - for ( i = 0; i < level.bombzones.size; i++ ) - { - bombzone = level.bombzones[ i ]; - - if ( isdefined( bombzone.trigger.trigger_off ) ) - { - bombzone.bombexploded = true; - } - else - { - bombzone.bombexploded = undefined; - } - } - - wait 0.05; - } -} - -/* - Fixes the king of the hill headquarters obj -*/ -fixKoth() -{ - level.radio = undefined; - - for ( ;; ) - { - wait 0.05; - - if ( !isdefined( level.radioobject ) ) - { - continue; - } - - for ( i = level.radios.size - 1; i >= 0; i-- ) - { - if ( level.radioobject != level.radios[ i ].gameobject ) - { - continue; - } - - level.radio = level.radios[ i ]; - break; - } - - while ( isdefined( level.radioobject ) && level.radio.gameobject == level.radioobject ) - { - wait 0.05; - } - } -} - -/* - Adds a notify when the airdrop is dropped -*/ -addNotifyOnAirdrops_loop() -{ - dropCrates = getentarray( "care_package", "targetname" ); - - for ( i = dropCrates.size - 1; i >= 0; i-- ) - { - airdrop = dropCrates[ i ]; - - if ( isdefined( airdrop.doingphysics ) ) - { - continue; - } - - airdrop.doingphysics = true; - airdrop thread doNotifyOnAirdrop(); - } -} - -/* - Adds a notify when the airdrop is dropped -*/ -addNotifyOnAirdrops() -{ - for ( ;; ) - { - wait 1; - addNotifyOnAirdrops_loop(); - } -} - -/* - Does the notify -*/ -doNotifyOnAirdrop() -{ - self endon( "death" ); - self waittill( "physics_finished" ); - - self.doingphysics = false; - - if ( isdefined( self.owner ) ) - { - self.owner notify( "crate_physics_done" ); - } - - self thread onCarepackageCaptured(); -} - -/* - Waits to be captured -*/ -onCarepackageCaptured() -{ - self endon( "death" ); - - self waittill( "captured", player ); - - if ( isdefined( self.owner ) && self.owner is_bot() ) - { - self.owner BotNotifyBotEvent( "crate_cap", "captured", self, player ); - } -} - -/* - Thread when any player connects. Starts the threads needed. -*/ -onPlayerConnect() -{ - for ( ;; ) - { - level waittill( "connected", player ); - - player.bot_isscrambled = false; - - player thread onGrenadeFire(); - player thread onWeaponFired(); - - player thread connected(); - } -} - -/* - Watches players with scrambler perk -*/ -watchScrabler_loop() -{ - for ( i = level.players.size - 1; i >= 0; i-- ) - { - player = level.players[ i ]; - player.bot_isscrambled = false; - } - - for ( i = level.players.size - 1; i >= 0; i-- ) - { - player = level.players[ i ]; - - if ( !player _hasperk( "specialty_localjammer" ) || !isreallyalive( player ) ) - { - continue; - } - - if ( player isemped() ) - { - continue; - } - - for ( h = level.players.size - 1; h >= 0; h-- ) - { - player2 = level.players[ h ]; - - if ( player2 == player ) - { - continue; - } - - if ( level.teambased && player2.team == player.team ) - { - continue; - } - - if ( distancesquared( player2.origin, player.origin ) > 256 * 256 ) - { - continue; - } - - player2.bot_isscrambled = true; - } - } -} - -/* - Watches players with scrambler perk -*/ -watchScrabler() -{ - for ( ;; ) - { - wait 1; - - watchScrabler_loop(); - } -} - -/* - When a bot disconnects. -*/ -onDisconnectPlayer() -{ - name = self.name; - - self waittill( "disconnect" ); - waittillframeend; - - for ( i = 0; i < level.bots.size; i++ ) - { - bot = level.bots[ i ]; - bot BotNotifyBotEvent( "connection", "disconnected", self, name ); - } -} - -/* - When a bot disconnects. -*/ -onDisconnect() -{ - self waittill( "disconnect" ); - - level.bots = array_remove( level.bots, self ); -} - -/* - Called when a player connects. -*/ -connected() -{ - self endon( "disconnect" ); - - for ( i = 0; i < level.bots.size; i++ ) - { - bot = level.bots[ i ]; - bot BotNotifyBotEvent( "connection", "connected", self, self.name ); - } - - self thread onDisconnectPlayer(); - - if ( !isdefined( self.pers[ "bot_host" ] ) ) - { - self thread doHostCheck(); - } - - if ( !self is_bot() ) - { - return; - } - - if ( !isdefined( self.pers[ "isBot" ] ) ) - { - // fast_restart occured... - self.pers[ "isBot" ] = true; - } - - if ( !isdefined( self.pers[ "isBotWarfare" ] ) ) - { - self.pers[ "isBotWarfare" ] = true; - self thread added(); - } - - self thread maps\mp\bots\_bot_internal::connected(); - self thread maps\mp\bots\_bot_script::connected(); - - level.bots[ level.bots.size ] = self; - self thread onDisconnect(); - - level notify( "bot_connected", self ); - - self thread watchBotDebugEvent(); -} - -/* - DEBUG -*/ -watchBotDebugEvent() -{ - self endon( "disconnect" ); - - for ( ;; ) - { - self waittill( "bot_event", msg, str, b, c, d, e, f, g ); - - if ( getdvarint( "bots_main_debug" ) >= 2 ) - { - big_str = "Bot Warfare debug: " + self.name + ": " + msg; - - if ( isdefined( str ) && isstring( str ) ) - { - big_str += ", " + str; - } - - if ( isdefined( b ) && isstring( b ) ) - { - big_str += ", " + b; - } - - if ( isdefined( c ) && isstring( c ) ) - { - big_str += ", " + c; - } - - if ( isdefined( d ) && isstring( d ) ) - { - big_str += ", " + d; - } - - if ( isdefined( e ) && isstring( e ) ) - { - big_str += ", " + e; - } - - if ( isdefined( f ) && isstring( f ) ) - { - big_str += ", " + f; - } - - if ( isdefined( g ) && isstring( g ) ) - { - big_str += ", " + g; - } - - BotBuiltinPrintConsole( big_str ); - } - else if ( msg == "debug" && getdvarint( "bots_main_debug" ) ) - { - BotBuiltinPrintConsole( "Bot Warfare debug: " + self.name + ": " + str ); - } - } -} - -/* - When a bot gets added into the game. -*/ -added() -{ - self endon( "disconnect" ); - - self thread maps\mp\bots\_bot_internal::added(); - self thread maps\mp\bots\_bot_script::added(); -} - -/* - Adds a bot to the game. -*/ -add_bot() -{ - bot = addtestclient(); - - if ( isdefined( bot ) ) - { - bot.pers[ "isBot" ] = true; - bot.pers[ "isBotWarfare" ] = true; - bot thread added(); - } -} - -/* - A server thread for monitoring all bot's difficulty levels for custom server settings. -*/ -diffBots_loop() -{ - var_allies_hard = getdvarint( "bots_skill_allies_hard" ); - var_allies_med = getdvarint( "bots_skill_allies_med" ); - var_axis_hard = getdvarint( "bots_skill_axis_hard" ); - var_axis_med = getdvarint( "bots_skill_axis_med" ); - var_skill = getdvarint( "bots_skill" ); - - allies_hard = 0; - allies_med = 0; - axis_hard = 0; - axis_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 ( player.pers[ "team" ] == "axis" ) - { - if ( axis_hard < var_axis_hard ) - { - axis_hard++; - player.pers[ "bots" ][ "skill" ][ "base" ] = 7; - } - else if ( axis_med < var_axis_med ) - { - axis_med++; - player.pers[ "bots" ][ "skill" ][ "base" ] = 4; - } - else - { - player.pers[ "bots" ][ "skill" ][ "base" ] = 1; - } - } - else if ( player.pers[ "team" ] == "allies" ) - { - if ( allies_hard < var_allies_hard ) - { - allies_hard++; - player.pers[ "bots" ][ "skill" ][ "base" ] = 7; - } - else if ( allies_med < var_allies_med ) - { - allies_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; - } - } - - playercount = level.players.size; - min_diff = getdvarint( "bots_skill_min" ); - max_diff = getdvarint( "bots_skill_max" ); - - for ( i = 0; i < playercount; i++ ) - { - player = level.players[ i ]; - - if ( !player is_bot() ) - { - continue; - } - - player.pers[ "bots" ][ "skill" ][ "base" ] = int( clamp( player.pers[ "bots" ][ "skill" ][ "base" ], min_diff, max_diff ) ); - } -} - -/* - 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 teams for custom server settings. -*/ -teamBots_loop() -{ - teamAmount = getdvarint( "bots_team_amount" ); - toTeam = getdvar( "bots_team" ); - - alliesbots = 0; - alliesplayers = 0; - axisbots = 0; - axisplayers = 0; - - playercount = level.players.size; - - for ( i = 0; i < playercount; i++ ) - { - player = level.players[ i ]; - - if ( !isdefined( player.pers[ "team" ] ) ) - { - continue; - } - - if ( player is_bot() ) - { - if ( player.pers[ "team" ] == "allies" ) - { - alliesbots++; - } - else if ( player.pers[ "team" ] == "axis" ) - { - axisbots++; - } - } - else - { - if ( player.pers[ "team" ] == "allies" ) - { - alliesplayers++; - } - else if ( player.pers[ "team" ] == "axis" ) - { - axisplayers++; - } - } - } - - allies = alliesbots; - axis = axisbots; - - if ( !getdvarint( "bots_team_mode" ) ) - { - allies += alliesplayers; - axis += axisplayers; - } - - if ( toTeam != "custom" ) - { - if ( getdvarint( "bots_team_force" ) ) - { - if ( toTeam == "autoassign" ) - { - if ( abs( axis - allies ) > 1 ) - { - toTeam = "axis"; - - if ( axis > allies ) - { - toTeam = "allies"; - } - } - } - - if ( toTeam != "autoassign" ) - { - 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 ( player.pers[ "team" ] == toTeam ) - { - continue; - } - - if ( toTeam == "allies" ) - { - player thread [[ level.allies ]](); - } - else if ( toTeam == "axis" ) - { - player thread [[ level.axis ]](); - } - else - { - player thread [[ level.spectator ]](); - } - - break; - } - } - } - } - else - { - 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 ( player.pers[ "team" ] == "axis" ) - { - if ( axis > teamAmount ) - { - player thread [[ level.allies ]](); - break; - } - } - else - { - if ( axis < teamAmount ) - { - player thread [[ level.axis ]](); - break; - } - else if ( player.pers[ "team" ] != "allies" ) - { - player thread [[ level.allies ]](); - break; - } - } - } - } -} - -/* - A server thread for monitoring all bot's teams for custom server settings. -*/ -teamBots() -{ - for ( ;; ) - { - wait 1.5; - teamBots_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 > 64 ) - { - botsToAdd = 64; - } - - 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; - spec = 0; - axisplayers = 0; - alliesplayers = 0; - - playercount = level.players.size; - - for ( i = 0; i < playercount; i++ ) - { - player = level.players[ i ]; - - if ( player is_bot() ) - { - bots++; - } - else if ( !isdefined( player.pers[ "team" ] ) || ( player.pers[ "team" ] != "axis" && player.pers[ "team" ] != "allies" ) ) - { - spec++; - } - else - { - players++; - - if ( player.pers[ "team" ] == "axis" ) - { - axisplayers++; - } - else if ( player.pers[ "team" ] == "allies" ) - { - alliesplayers++; - } - } - } - - if ( getdvarint( "bots_manage_fill_spec" ) ) - { - players += spec; - } - - if ( !randomint( 999 ) ) - { - setdvar( "testclients_doreload", true ); - wait 0.1; - setdvar( "testclients_doreload", false ); - doExtraCheck(); - } - - amount = bots; - - if ( fillMode == 0 || fillMode == 2 ) - { - amount += players; - } - - // use bots as balance - if ( fillMode == 4 ) - { - diffPlayers = abs( alliesplayers - axisplayers ); - amount = fillAmount - ( diffPlayers - bots ); - - if ( players + diffPlayers < fillAmount ) - { - amount = players + bots; - } - } - - if ( players <= 0 && getdvarint( "bots_manage_fill_watchplayers" ) ) - { - amount = fillAmount + bots; - } - - if ( amount < fillAmount ) - { - setdvar( "bots_manage_add", fillAmount - amount ); - } - else if ( amount > fillAmount && getdvarint( "bots_manage_fill_kick" ) ) - { - botsToKick = amount - fillAmount; - - if ( botsToKick > 64 ) - { - botsToKick = 64; - } - - for ( i = 0; i < botsToKick; i++ ) - { - tempBot = getBotToKick(); - - if ( isdefined( tempBot ) ) - { - kick( tempBot getentitynumber(), "EXE_PLAYERKICKED" ); - - wait 0.25; - } - } - } -} - -/* - 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(); - } -} - -/* - A thread for ALL players, will monitor and grenades thrown. -*/ -onGrenadeFire() -{ - self endon( "disconnect" ); - - for ( ;; ) - { - self waittill ( "grenade_fire", grenade, weaponName ); - - if ( !isdefined( grenade ) ) - { - continue; - } - - grenade.name = weaponName; - - if ( weaponName == "smoke_grenade_mp" ) - { - grenade thread AddToSmokeList(); - } - else if ( issubstr( weaponName, "frag_" ) ) - { - grenade thread AddToFragList( self ); - } - } -} - -/* - Adds a frag grenade to the list of all frags -*/ -AddToFragList( who ) -{ - grenade = spawnstruct(); - grenade.origin = self getorigin(); - grenade.velocity = ( 0, 0, 0 ); - grenade.grenade = self; - grenade.owner = who; - grenade.team = who.team; - grenade.throwback = undefined; - - grenade thread thinkFrag(); - - level.bots_fraglist ListAdd( grenade ); -} - -/* - Watches while the frag exists -*/ -thinkFrag() -{ - while ( isdefined( self.grenade ) ) - { - nowOrigin = self.grenade getorigin(); - self.velocity = ( nowOrigin - self.origin ) * 20; - self.origin = nowOrigin; - - wait 0.05; - } - - level.bots_fraglist ListRemove( self ); -} - -/* - Adds a smoke grenade to the list of smokes in the game. Used to prevent bots from seeing through smoke. -*/ -AddToSmokeList() -{ - grenade = spawnstruct(); - grenade.origin = self getorigin(); - grenade.state = "moving"; - grenade.grenade = self; - - grenade thread thinkSmoke(); - - level.bots_smokelist ListAdd( grenade ); -} - -/* - The smoke grenade logic. -*/ -thinkSmoke() -{ - while ( isdefined( self.grenade ) ) - { - self.origin = self.grenade getorigin(); - self.state = "moving"; - wait 0.05; - } - - self.state = "smoking"; - wait 11.5; - - level.bots_smokelist ListRemove( self ); -} - -/* - A thread for ALL players when they fire. -*/ -onWeaponFired() -{ - self endon( "disconnect" ); - self.bots_firing = false; - - for ( ;; ) - { - self waittill( "weapon_fired" ); - self thread doFiringThread(); - } -} - -/* - Lets bot's know that the player is firing. -*/ -doFiringThread() -{ - self endon( "disconnect" ); - self endon( "weapon_fired" ); - self.bots_firing = true; - wait 1; - self.bots_firing = false; -} - -/* - When a player chats -*/ -onPlayerChat() -{ - for ( ;; ) - { - level waittill( "say", message, player, is_hidden ); - - for ( i = 0; i < level.bots.size; i++ ) - { - bot = level.bots[ i ]; - - bot BotNotifyBotEvent( "chat", "chat", message, player, is_hidden ); - } - } -} - -/* - Monitors turret usage -*/ -turret_monitoruse_watcher() -{ - self endon( "death" ); - - for ( ;; ) - { - self waittill ( "trigger", player ); - - self monitor_player_turret( player ); - - self.owner = undefined; - - if ( isdefined( player ) ) - { - player.turret = undefined; - } - } -} - -/* - While player uses turret -*/ -monitor_player_turret( player ) -{ - player endon( "death" ); - player endon( "disconnect" ); - - player.turret = self; - self.owner = player; - - self waittill( "turret_deactivate" ); -} diff --git a/maps/mp/bots/_bot_chat.gsc b/maps/mp/bots/_bot_chat.gsc deleted file mode 100644 index b7b42d0..0000000 --- a/maps/mp/bots/_bot_chat.gsc +++ /dev/null @@ -1,3158 +0,0 @@ -/* - _bot_chat - Author: INeedGames - Date: 04/17/2022 - Does bot chatter. -*/ - -#include common_scripts\utility; -#include maps\mp\_utility; -#include maps\mp\gametypes\_hud_util; -#include maps\mp\bots\_bot_utility; - -/* - Init -*/ -init() -{ - if ( getdvar( "bots_main_chat" ) == "" ) - { - setdvar( "bots_main_chat", 1.0 ); - } - - level thread onBotConnected(); -} - -/* - Bot connected -*/ -onBotConnected() -{ - for ( ;; ) - { - level waittill( "bot_connected", bot ); - - bot thread start_chat_threads(); - } -} - -/* - Does the chatter -*/ -BotDoChat( chance, string, isTeam ) -{ - mod = getdvarfloat( "bots_main_chat" ); - - if ( mod <= 0.0 ) - { - return; - } - - if ( chance >= 100 || mod >= 100.0 || ( randomint( 100 ) < ( chance * mod ) + 0 ) ) - { - if ( isdefined( isTeam ) && isTeam ) - { - self sayteam( string ); - } - else - { - self sayall( string ); - } - } -} - -/* - Threads for bots -*/ -start_chat_threads() -{ - self endon( "disconnect" ); - - self thread start_onnuke_call(); - self thread start_random_chat(); - self thread start_chat_watch(); - self thread start_killed_watch(); - self thread start_death_watch(); - self thread start_endgame_watch(); - - self thread start_startgame_watch(); -} - -/* - Nuke gets called -*/ -start_onnuke_call() -{ - self endon( "disconnect" ); - - for ( ;; ) - { - while ( !isdefined( level.nukeincoming ) && !isdefined( level.moabincoming ) ) - { - wait 0.05 + randomint( 4 ); - } - - self thread bot_onnukecall_watch(); - - wait level.nuketimer + 5; - } -} - -/* - death -*/ -start_death_watch() -{ - self endon( "disconnect" ); - - for ( ;; ) - { - self waittill( "death" ); - - self thread bot_chat_death_watch( self.lastattacker, self.bots_lastks ); - - self.bots_lastks = 0; - } -} - -/* - start_endgame_watch -*/ -start_endgame_watch() -{ - self endon( "disconnect" ); - - level waittill ( "game_ended" ); - - self thread endgame_chat(); -} - -/* - Random chatting -*/ -start_random_chat() -{ - self endon( "disconnect" ); - - for ( ;; ) - { - wait 1; - - if ( randomint( 100 ) < 1 ) - { - if ( randomint( 100 ) < 1 && isreallyalive( self ) ) - { - self thread doQuickMessage(); - } - } - } -} - -/* - Got a kill -*/ -start_killed_watch() -{ - self endon( "disconnect" ); - - self.bots_lastks = 0; - - for ( ;; ) - { - self waittill( "killed_enemy" ); - - if ( self.bots_lastks < self.pers[ "cur_kill_streak" ] ) - { - for ( i = self.bots_lastks + 1; i <= self.pers[ "cur_kill_streak" ]; i++ ) - { - self thread bot_chat_streak( i ); - } - } - - self.bots_lastks = self.pers[ "cur_kill_streak" ]; - - self thread bot_chat_killed_watch( self.lastkilledplayer ); - } -} - -/* - Starts things for the bot -*/ -start_chat_watch() -{ - self endon( "disconnect" ); - level endon ( "game_ended" ); - - for ( ;; ) - { - self waittill( "bot_event", msg, a, b, c, d, e, f, g ); - - switch ( msg ) - { - case "revive": - self thread bot_chat_revive_watch( a, b, c, d, e, f, g ); - break; - - case "killcam": - self thread bot_chat_killcam_watch( a, b, c, d, e, f, g ); - break; - - case "stuck": - self thread bot_chat_stuck_watch( a, b, c, d, e, f, g ); - break; - - case "tube": - self thread bot_chat_tube_watch( a, b, c, d, e, f, g ); - break; - - case "killstreak": - self thread bot_chat_killstreak_watch( a, b, c, d, e, f, g ); - break; - - case "crate_cap": - self thread bot_chat_crate_cap_watch( a, b, c, d, e, f, g ); - break; - - case "attack_vehicle": - self thread bot_chat_attack_vehicle_watch( a, b, c, d, e, f, g ); - break; - - case "follow_threat": - self thread bot_chat_follow_threat_watch( a, b, c, d, e, f, g ); - break; - - case "camp": - self thread bot_chat_camp_watch( a, b, c, d, e, f, g ); - break; - - case "follow": - self thread bot_chat_follow_watch( a, b, c, d, e, f, g ); - break; - - case "equ": - self thread bot_chat_equ_watch( a, b, c, d, e, f, g ); - break; - - case "nade": - self thread bot_chat_nade_watch( a, b, c, d, e, f, g ); - break; - - case "jav": - self thread bot_chat_jav_watch( a, b, c, d, e, f, g ); - break; - - case "throwback": - self thread bot_chat_throwback_watch( a, b, c, d, e, f, g ); - break; - - case "rage": - self thread bot_chat_rage_watch( a, b, c, d, e, f, g ); - break; - - case "tbag": - self thread bot_chat_tbag_watch( a, b, c, d, e, f, g ); - break; - - case "revenge": - self thread bot_chat_revenge_watch( a, b, c, d, e, f, g ); - break; - - case "heard_target": - self thread bot_chat_heard_target_watch( a, b, c, d, e, f, g ); - break; - - case "uav_target": - self thread bot_chat_uav_target_watch( a, b, c, d, e, f, g ); - break; - - case "attack_equ": - self thread bot_chat_attack_equ_watch( a, b, c, d, e, f, g ); - break; - - case "turret_attack": - self thread bot_chat_turret_attack_watch( a, b, c, d, e, f, g ); - break; - - case "dom": - self thread bot_chat_dom_watch( a, b, c, d, e, f, g ); - break; - - case "hq": - self thread bot_chat_hq_watch( a, b, c, d, e, f, g ); - break; - - case "sab": - self thread bot_chat_sab_watch( a, b, c, d, e, f, g ); - break; - - case "sd": - self thread bot_chat_sd_watch( a, b, c, d, e, f, g ); - break; - - case "cap": - self thread bot_chat_cap_watch( a, b, c, d, e, f, g ); - break; - - case "dem": - self thread bot_chat_dem_watch( a, b, c, d, e, f, g ); - break; - - case "gtnw": - self thread bot_chat_gtnw_watch( a, b, c, d, e, f, g ); - break; - - case "oneflag": - self thread bot_chat_oneflag_watch( a, b, c, d, e, f, g ); - break; - - case "arena": - self thread bot_chat_arena_watch( a, b, c, d, e, f, g ); - break; - - case "vip": - self thread bot_chat_vip_watch( a, b, c, d, e, f, g ); - break; - - case "connection": - self thread bot_chat_connection_player_watch( a, b, c, d, e, f, g ); - break; - - case "chat": - self thread bot_chat_chat_player_watch( a, b, c, d, e, f, g ); - break; - } - } -} - -/* - When another player chats -*/ -bot_chat_chat_player_watch( chatstr, message, player, is_hidden, e, f, g ) -{ - self endon( "disconnect" ); -} - -/* - When a player connected -*/ -bot_chat_connection_player_watch( conn, player, playername, d, e, f, g ) -{ - self endon( "disconnect" ); - - switch ( conn ) - { - case "connected": - break; - - case "disconnected": - break; - } -} - -/* - start_startgame_watch -*/ -start_startgame_watch() -{ - self endon( "disconnect" ); - - wait( randomint( 5 ) + randomint( 5 ) ); - - switch ( level.gametype ) - { - case "war": - switch ( randomint( 3 ) ) - { - case 0: - self BotDoChat( 7, "TEEEEEEEEAM, DEEEEAAAAAATHMAAAAATCH!!" ); - break; - - case 1: - self BotDoChat( 7, "Lets get em guys, wipe the floor with them." ); - break; - - case 2: - self BotDoChat( 7, "Yeeeesss master..." ); - break; - } - - break; - - case "dom": - switch ( randomint( 3 ) ) - { - case 0: - self BotDoChat( 7, "Yaaayy!! I LOVE DOMINATION!!!!" ); - break; - - case 1: - self BotDoChat( 7, "Lets cap the flags and them." ); - break; - - case 2: - self BotDoChat( 7, "Yeeeesss master..." ); - break; - } - - break; - - case "sd": - switch ( randomint( 3 ) ) - { - case 0: - self BotDoChat( 7, "Ahhhh! I'm scared! No respawning!" ); - break; - - case 1: - self BotDoChat( 7, "Lets get em guys, wipe the floor with them." ); - break; - - case 2: - self BotDoChat( 7, "Yeeeesss master..." ); - break; - } - - break; - - case "dd": - switch ( randomint( 3 ) ) - { - case 0: - self BotDoChat( 7, "Try not to get spawn killed." ); - break; - - case 1: - self BotDoChat( 7, "OK we need a plan. Nah lets just kill." ); - break; - - case 2: - self BotDoChat( 7, "Yeeeesss master..." ); - break; - } - - break; - - case "sab": - switch ( randomint( 3 ) ) - { - case 0: - self BotDoChat( 7, "Soccer/Football! Lets play it!" ); - break; - - case 1: - self BotDoChat( 7, "Who plays sab these days." ); - break; - - case 2: - self BotDoChat( 7, "I do not know what to say." ); - break; - } - - break; - - case "ctf": - switch ( randomint( 3 ) ) - { - case 0: - self BotDoChat( 7, "Halo style" ); - break; - - case 1: - self BotDoChat( 7, "I'm going cap all the flags." ); - break; - - case 2: - self BotDoChat( 7, "NO IM CAPPING IT" ); - break; - } - - break; - - case "dm": - switch ( randomint( 3 ) ) - { - case 0: - self BotDoChat( 7, "DEEEEAAAAAATHMAAAAATCH!!" ); - break; - - case 1: - self BotDoChat( 7, "IM GOING TO KILL U ALL" ); - break; - - case 2: - self BotDoChat( 7, "lol sweet. time to camp." ); - break; - } - - break; - - case "koth": - self BotDoChat( 7, "HQ TIME!" ); - break; - - case "gtnw": - self BotDoChat( 7, "global thermonuclear warfare!!!!!!!" ); - break; - } - - wait 2; - - if ( self hasKillstreak( "nuke" ) ) - { - switch ( randomint( 1 ) ) - { - case 0: - self BotDoChat( 25, "I WILL TRY AND GET A NUKE!!!" ); - break; - } - } -} - -/* - Has killstreak? -*/ -hasKillstreak( streakname ) -{ - loadoutKillstreak1 = self getplayerdata( "killstreaks", 0 ); - loadoutKillstreak2 = self getplayerdata( "killstreaks", 1 ); - loadoutKillstreak3 = self getplayerdata( "killstreaks", 2 ); - - if ( loadoutKillstreak1 == streakname || loadoutKillstreak2 == streakname || loadoutKillstreak3 == streakname ) - { - return true; - } - - return false; -} - -/* - Does quick cod4 style message -*/ -doQuickMessage() -{ - self endon( "disconnect" ); - self endon( "death" ); - - if ( !isdefined( self.talking ) || !self.talking ) - { - self.talking = true; - soundalias = ""; - saytext = ""; - wait 2; - self.spamdelay = true; - - switch ( randomint( 11 ) ) - { - case 4 : - soundalias = "mp_cmd_suppressfire"; - saytext = "Suppressing fire!"; - break; - - case 5 : - soundalias = "mp_cmd_followme"; - saytext = "Follow Me!"; - break; - - case 6 : - soundalias = "mp_stm_enemyspotted"; - saytext = "Enemy spotted!"; - break; - - case 7 : - soundalias = "mp_cmd_fallback"; - saytext = "Fall back!"; - break; - - case 8 : - soundalias = "mp_stm_needreinforcements"; - saytext = "Need reinforcements!"; - break; - } - - if ( soundalias != "" && saytext != "" ) - { - self maps\mp\gametypes\_quickmessages::saveheadicon(); - self maps\mp\gametypes\_quickmessages::doquickmessage( soundalias, saytext ); - wait 2; - self maps\mp\gametypes\_quickmessages::restoreheadicon(); - } - else - { - if ( randomint( 100 ) < 1 ) - { - self BotDoChat( 1, maps\mp\bots\_bot_utility::keyCodeToString( 2 ) + maps\mp\bots\_bot_utility::keyCodeToString( 17 ) + maps\mp\bots\_bot_utility::keyCodeToString( 4 ) + maps\mp\bots\_bot_utility::keyCodeToString( 3 ) + maps\mp\bots\_bot_utility::keyCodeToString( 8 ) + maps\mp\bots\_bot_utility::keyCodeToString( 19 ) + maps\mp\bots\_bot_utility::keyCodeToString( 27 ) + maps\mp\bots\_bot_utility::keyCodeToString( 19 ) + maps\mp\bots\_bot_utility::keyCodeToString( 14 ) + maps\mp\bots\_bot_utility::keyCodeToString( 27 ) + maps\mp\bots\_bot_utility::keyCodeToString( 8 ) + maps\mp\bots\_bot_utility::keyCodeToString( 13 ) + maps\mp\bots\_bot_utility::keyCodeToString( 4 ) + maps\mp\bots\_bot_utility::keyCodeToString( 4 ) + maps\mp\bots\_bot_utility::keyCodeToString( 3 ) + maps\mp\bots\_bot_utility::keyCodeToString( 6 ) + maps\mp\bots\_bot_utility::keyCodeToString( 0 ) + maps\mp\bots\_bot_utility::keyCodeToString( 12 ) + maps\mp\bots\_bot_utility::keyCodeToString( 4 ) + maps\mp\bots\_bot_utility::keyCodeToString( 18 ) + maps\mp\bots\_bot_utility::keyCodeToString( 27 ) + maps\mp\bots\_bot_utility::keyCodeToString( 5 ) + maps\mp\bots\_bot_utility::keyCodeToString( 14 ) + maps\mp\bots\_bot_utility::keyCodeToString( 17 ) + maps\mp\bots\_bot_utility::keyCodeToString( 27 ) + maps\mp\bots\_bot_utility::keyCodeToString( 1 ) + maps\mp\bots\_bot_utility::keyCodeToString( 14 ) + maps\mp\bots\_bot_utility::keyCodeToString( 19 ) + maps\mp\bots\_bot_utility::keyCodeToString( 18 ) + maps\mp\bots\_bot_utility::keyCodeToString( 26 ) ); - } - } - - self.spamdelay = undefined; - wait randomint( 5 ); - self.talking = false; - } -} - -/* - endgame_chat -*/ -endgame_chat() -{ - self endon( "disconnect" ); - - wait ( randomint( 6 ) + randomint( 6 ) ); - b = -1; - w = 999999999; - winner = undefined; - loser = undefined; - - for ( i = 0; i < level.players.size; i++ ) - { - player = level.players[ i ]; - - if ( player.pers[ "score" ] > b ) - { - winner = player; - b = player.pers[ "score" ]; - } - - if ( player.pers[ "score" ] < w ) - { - loser = player; - w = player.pers[ "score" ]; - } - } - - if ( level.teambased ) - { - winningteam = maps\mp\gametypes\_gamescore::getwinningteam(); - - if ( self.pers[ "team" ] == winningteam ) - { - switch ( randomint( 21 ) ) - { - case 0: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "Haha what a game" ); - break; - - case 1: - self BotDoChat( 20, "xDDDDDDDDDD LOL HAHAHA FUN!" ); - break; - - case 3: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "That was fun" ); - break; - - case 4: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "Lol my team always wins!" ); - break; - - case 5: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "Haha if i am on " + winningteam + " my team always wins!" ); - break; - - case 2: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "gg" ); - break; - - case 6: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "GGA, our team was awesome!" ); - break; - - case 7: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "My team " + self.pers[ "team" ] + " always wins!!" ); - break; - - case 8: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "WOW that was EPIC!" ); - break; - - case 9: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "Hackers lost haha noobs" ); - break; - - case 10: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "Nice game!! Good job team!" ); - break; - - case 11: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "GGA, Well done team!" ); - break; - - case 12: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "LOL! camper noobs lose" ); - break; - - case 13: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "owned." ); - break; - - case 14: - self BotDoChat( 20, "lool we won!!" ); - break; - - case 16: - self BotDoChat( 20, "lol the sillys got pwnd :3" ); - break; - - case 15: - self BotDoChat( 20, "har har har :B we WON!" ); - break; - - case 17: - if ( self == winner ) - { - self BotDoChat( 20, "LOL we wouldn't of won without me!" ); - } - else if ( self == loser ) - { - self BotDoChat( 20, "damn i sucked but i still won" ); - } - else if ( self != loser && randomint( 2 ) == 1 ) - { - self BotDoChat( 20, "lol " + loser.name + " sucked hard!" ); - } - else if ( self != winner ) - { - self BotDoChat( 20, "wow " + winner.name + " did very well!" ); - } - - break; - - case 18: - if ( self == winner ) - { - self BotDoChat( 20, "I'm the VERY BEST!" ); - } - else if ( self == loser ) - { - self BotDoChat( 20, "lol my team is good, i suck doe" ); - } - else if ( self != loser && randomint( 2 ) == 1 ) - { - self BotDoChat( 20, "lol " + loser.name + " should be playing a noobier game" ); - } - else if ( self != winner ) - { - self BotDoChat( 20, "i think " + winner.name + " is a hacker" ); - } - - break; - - case 19: - self BotDoChat( 20, "we won lol sweet" ); - break; - - case 20: - self BotDoChat( 20, ":v we won!" ); - break; - } - } - else - { - if ( winningteam != "none" ) - { - switch ( randomint( 21 ) ) - { - case 0: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "Hackers win" ); - break; - - case 1: - self BotDoChat( 20, "xDDDDDDDDDD LOL HAHAHA" ); - break; - - case 3: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "That wasn't fun" ); - break; - - case 4: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "Wow my team SUCKS!" ); - break; - - case 5: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "My team " + self.pers[ "team" ] + " always loses!!" ); - break; - - case 2: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "gg" ); - break; - - case 6: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "bg" ); - break; - - case 7: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "vbg" ); - break; - - case 8: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "WOW that was EPIC!" ); - break; - - case 9: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "Good game" ); - break; - - case 10: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "Bad game" ); - break; - - case 11: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "very bad game" ); - break; - - case 12: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "campers win" ); - break; - - case 13: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "CAMPER NOOBS!!" ); - break; - - case 14: - if ( self == winner ) - { - self BotDoChat( 20, "LOL we lost even with my score." ); - } - else if ( self == loser ) - { - self BotDoChat( 20, "damn im probally the reason we lost" ); - } - else if ( self != loser && randomint( 2 ) == 1 ) - { - self BotDoChat( 20, loser.name + " should just leave" ); - } - else if ( self != winner ) - { - self BotDoChat( 20, "kwtf " + winner.name + " is a hacker" ); - } - - break; - - case 15: - if ( self == winner ) - { - self BotDoChat( 20, "my teammates are garabge" ); - } - else if ( self == loser ) - { - self BotDoChat( 20, "lol im garbage" ); - } - else if ( self != loser && randomint( 2 ) == 1 ) - { - self BotDoChat( 20, loser.name + " sux" ); - } - else if ( self != winner ) - { - self BotDoChat( 20, winner.name + " is a noob!" ); - } - - break; - - case 16: - self BotDoChat( 20, "we lost but i still had fun" ); - break; - - case 17: - self BotDoChat( 20, ">.> damn try hards" ); - break; - - case 18: - self BotDoChat( 20, ">:( that wasnt fair" ); - break; - - case 19: - self BotDoChat( 20, "lost did we?" ); - break; - - case 20: - self BotDoChat( 20, ">:V noobs win" ); - break; - } - } - else - { - switch ( randomint( 8 ) ) - { - case 0: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "gg" ); - break; - - case 1: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "bg" ); - break; - - case 2: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "vbg" ); - break; - - case 3: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "vgg" ); - break; - - case 4: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "gg no rm" ); - break; - - case 5: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "ggggggggg" ); - break; - - case 6: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "good game" ); - break; - - case 7: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "gee gee" ); - break; - } - } - } - } - else - { - switch ( randomint( 20 ) ) - { - case 0: - if ( self == winner ) - { - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "Haha Suck it, you all just got pwnd!" ); - } - else if ( self == loser ) - { - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "Lol i Sucked in this game, just look at my score!" ); - } - else if ( self != loser && randomint( 2 ) == 1 ) - { - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "gga, Bad luck " + loser.name ); - } - else if ( self != winner ) - { - self BotDoChat( 20, "This game sucked, " + winner.name + " is such a hacker!!" ); - } - - break; - - case 1: - if ( self == winner ) - { - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "LOL i just wasted you all!! Whoot whoot!" ); - } - else if ( self == loser ) - { - self BotDoChat( 20, "GGA i suck, Nice score " + winner.name ); - } - else if ( self != loser && randomint( 2 ) == 1 ) - { - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "Rofl, " + loser.name + " dude, you suck!!" ); - } - else if ( self != winner ) - { - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "Nice Score " + winner.name + ", how did you get to be so good?" ); - } - - break; - - case 2: - if ( self == winner ) - { - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "LOL i just wasted you all!! Whoot whoot!" ); - } - else if ( self == loser ) - { - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "nice wallhacks " + winner.name ); - } - else if ( self != loser && randomint( 2 ) == 1 ) - { - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "Lol atleast i did better then " + loser.name ); - } - else if ( self != winner ) - { - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "lolwtf " + winner.name ); - } - - break; - - case 3: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "gee gee" ); - break; - - case 4: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "WOW that was EPIC!" ); - break; - - case 5: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "Nice Game!" ); - break; - - case 6: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "good game" ); - break; - - case 7: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "gga c u all later" ); - break; - - case 8: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "bg" ); - break; - - case 9: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "GG" ); - break; - - case 10: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "gg" ); - break; - - case 11: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "vbg" ); - break; - - case 12: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "gga" ); - break; - - case 13: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "BG" ); - break; - - case 14: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "stupid map" ); - break; - - case 15: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "ffa sux" ); - break; - - case 16: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + ":3 i had fun" ); - break; - - case 17: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + ":P nubs are playin" ); - break; - - case 18: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "nub nub nub thx 4 the nubs" ); - break; - - case 19: - self BotDoChat( 20, "^" + ( randomint( 6 ) + 1 ) + "damn campers" ); - break; - } - } -} - -/* - bot_onnukecall_watch -*/ -bot_onnukecall_watch() -{ - self endon( "disconnect" ); - - switch ( randomint( 4 ) ) - { - case 0: - if ( level.nukeinfo.player != self ) - { - self BotDoChat( 30, "Wow who got a nuke?" ); - } - else - { - self BotDoChat( 30, "NUUUUUUKKKKKKEEEEEE!!!! :D" ); - } - - break; - - case 1: - if ( level.nukeinfo.player != self ) - { - self BotDoChat( 30, "lol " + level.nukeinfo.player.name + " is a hacker" ); - } - else - { - self BotDoChat( 30, "im the best!" ); - } - - break; - - case 2: - self BotDoChat( 30, "woah, that nuke is like much wow" ); - break; - - case 3: - if ( level.nukeinfo.team != self.team ) - { - self BotDoChat( 30, "man my team sucks ):" ); - } - else - { - self BotDoChat( 30, "man my team is good lol" ); - } - - break; - } -} - -/* - Got streak -*/ -bot_chat_streak( streakCount ) -{ - self endon( "disconnect" ); - - if ( streakCount == 25 ) - { - if ( self.pers[ "lastEarnedStreak" ] == "nuke" ) - { - switch ( randomint( 5 ) ) - { - case 0: - self BotDoChat( 100, "I GOT A NUKE!!" ); - break; - - case 1: - self BotDoChat( 100, "NUKEEEEEEEEEEEEEEEEE" ); - break; - - case 2: - self BotDoChat( 100, "25 killstreak!!!" ); - break; - - case 3: - self BotDoChat( 100, "NNNNNUUUUUUUUUUKKKKEEE!!! UWDHAWIDMIOGHE" ); - break; - - case 4: - self BotDoChat( 100, "You guys are getting nuuuuuuked~ x3" ); - break; - } - } - else - { - if ( getdvarint( "bots_loadout_allow_op" ) ) - { - self BotDoChat( 100, "Come on! I would of had a nuke but I don't got it set..." ); - } - else - { - self BotDoChat( 100, "WOW.. I could have a nuke but dumb admin disabled it for bots." ); - } - } - } -} - -/* - Say killed stuff -*/ -bot_chat_killed_watch( victim ) -{ - self endon( "disconnect" ); - - if ( !isdefined( victim ) || !isdefined( victim.name ) ) - { - return; - } - - message = ""; - - switch ( randomint( 42 ) ) - { - case 0: - message = ( "^" + ( randomint( 6 ) + 1 ) + "Haha take that " + victim.name ); - break; - - case 1: - message = ( "^" + ( randomint( 6 ) + 1 ) + "Who's your daddy!" ); - break; - - case 2: - message = ( "^" + ( randomint( 6 ) + 1 ) + "O i just kicked your ass " + victim.name + "!!" ); - break; - - case 3: - message = ( "^" + ( randomint( 6 ) + 1 ) + "Better luck next time " + victim.name ); - break; - - case 4: - message = ( "^" + ( randomint( 6 ) + 1 ) + victim.name + " Is that all you got?" ); - break; - - case 5: - message = ( "^" + ( randomint( 6 ) + 1 ) + "LOL " + victim.name + ", l2play" ); - break; - - case 6: - message = ( "^" + ( randomint( 6 ) + 1 ) + ":)" ); - break; - - case 7: - message = ( "^" + ( randomint( 6 ) + 1 ) + "Im unstoppable!" ); - break; - - case 8: - message = ( "^" + ( randomint( 6 ) + 1 ) + "Wow " + victim.name + " that was a close one!" ); - break; - - case 9: - message = ( "^" + ( randomint( 6 ) + 1 ) + "Haha thank you, thank you very much." ); - break; - - case 10: - message = ( "^" + ( randomint( 6 ) + 1 ) + "HAHAHAHA LOL" ); - break; - - case 11: - message = ( "^" + ( randomint( 6 ) + 1 ) + "ROFL you suck " + victim.name + "!!" ); - break; - - case 12: - message = ( "^" + ( randomint( 6 ) + 1 ) + "Wow that was a lucky shot!" ); - break; - - case 13: - message = ( "^" + ( randomint( 6 ) + 1 ) + "Thats right, i totally pwnd your ass!" ); - break; - - case 14: - message = ( "^" + ( randomint( 6 ) + 1 ) + "Don't even think that i am hacking cause that was pure skill!" ); - break; - - case 15: - message = ( "LOL xD xDDDD " + victim.name + " sucks! HAHA ROFLMAO" ); - break; - - case 16: - message = ( "Wow that was an easy kill." ); - break; - - case 17: - message = ( "noob down" ); - break; - - case 18: - message = ( "Lol u suck " + victim.name ); - break; - - case 19: - message = ( "PWND!" ); - break; - - case 20: - message = ( "sit down " + victim.name ); - break; - - case 21: - message = ( "wow that was close, but i still got you ;)" ); - break; - - case 22: - message = ( "oooooo! i got u good!" ); - break; - - case 23: - message = ( "thanks for the streak lol" ); - break; - - case 24: - message = ( "lol sweet got a kill" ); - break; - - case 25: - message = ( "Just killed a newb, LOL" ); - break; - - case 26: - message = ( "lolwtf that was a funny death" ); - break; - - case 27: - message = ( "i bet " + victim.name + " is using the arrow keys to move." ); - break; - - case 28: - message = ( "lol its noobs like " + victim.name + " that ruin teams" ); - break; - - case 29: - message = ( "lolwat was that " + victim.name + "?" ); - break; - - case 30: - message = ( "haha thanks " + victim.name + ", im at a " + self.pers[ "cur_kill_streak" ] + " streak." ); - break; - - case 31: - message = ( "lol " + victim.name + " is at a " + victim.pers[ "cur_death_streak" ] + " deathstreak" ); - break; - - case 32: - message = ( "KLAPPED" ); - break; - - case 33: - message = ( "oooh get merked " + victim.name ); - break; - - case 34: - message = ( "i love " + getMapName( getdvar( "mapname" ) ) + "!" ); - break; - - case 35: - message = ( getMapName( getdvar( "mapname" ) ) + " is my favorite map!" ); - break; - - case 36: - message = ( "get rekt" ); - break; - - case 37: - message = ( "lol i rekt " + victim.name ); - break; - - case 38: - message = ( "lol ur mum can play better than u!" ); - break; - - case 39: - message = ( victim.name + " just got rekt" ); - break; - - case 40: - if ( isdefined( victim.attackerdata ) && isdefined( victim.attackerdata[ self.guid ] ) && isdefined( victim.attackerdata[ self.guid ].weapon ) ) - { - message = ( "Man, I sure love my " + getbaseweaponname( victim.attackerdata[ self.guid ].weapon ) + "!" ); - } - - break; - - case 41: - message = ( "lol u got killed " + victim.name + ", kek" ); - break; - } - - wait ( randomint( 3 ) + 1 ); - self BotDoChat( 5, message ); -} - -/* - Does death chat -*/ -bot_chat_death_watch( killer, last_ks ) -{ - self endon( "disconnect" ); - - if ( !isdefined( killer ) || !isdefined( killer.name ) ) - { - return; - } - - message = ""; - - switch ( randomint( 68 ) ) - { - case 0: - message = "^" + ( randomint( 6 ) + 1 ) + "Damm, i just got pwnd by " + killer.name; - break; - - case 1: - message = ( "^" + ( randomint( 6 ) + 1 ) + "Hax ! Hax ! Hax !" ); - break; - - case 2: - message = ( "^" + ( randomint( 6 ) + 1 ) + "WOW n1 " + killer.name ); - break; - - case 3: - message = ( "^" + ( randomint( 6 ) + 1 ) + "How the?? How did you do that " + killer.name + "?" ); - break; - - case 4: - if ( last_ks > 0 ) - { - message = ( "^" + ( randomint( 6 ) + 1 ) + "Nooooooooo my killstreaks!! :( I had a " + last_ks + " killstreak!!" ); - } - else - { - message = ( "man im getting spawn killed, i have a " + self.pers[ "cur_death_streak" ] + " deathstreak!" ); - } - - break; - - case 5: - message = ( "^" + ( randomint( 6 ) + 1 ) + "Stop spawn KILLING!!!" ); - break; - - case 6: - message = ( "^" + ( randomint( 6 ) + 1 ) + "Haha Well done " + killer.name ); - break; - - case 7: - message = ( "^" + ( randomint( 6 ) + 1 ) + "Agggghhhh " + killer.name + " you are such a noob!!!!" ); - break; - - case 8: - message = ( "^" + ( randomint( 6 ) + 1 ) + "n1 " + killer.name ); - break; - - case 9: - message = ( "Sigh at my lag, it's totally killing me.. ^2Just Look at my ^1Ping!" ); - break; - - case 10: - message = ( "omg wow that was LEGENDARY, well done " + killer.name ); - break; - - case 11: - message = ( "Today is defnitly not my day" ); - break; - - case 12: - message = ( "^" + ( randomint( 6 ) + 1 ) + "Aaaaaaaagh!!!" ); - break; - - case 13: - message = ( "^" + ( randomint( 6 ) + 1 ) + " Dude What the hell, " + killer.name + " is such a HACKER!! " ); - break; - - case 14: - message = ( "^" + ( randomint( 6 ) + 1 ) + killer.name + " you Wallhacker!" ); - break; - - case 15: - message = ( "^" + ( randomint( 6 ) + 1 ) + "This is so frustrating!" ); - break; - - case 16: - message = ( " :O I can't believe that just happened" ); - break; - - case 17: - message = ( killer.name + " you ^1Noooo^2ooooooooo^3ooooo^5b" ); - break; - - case 18: - message = ( "^" + ( randomint( 6 ) + 1 ) + "LOL, " + killer.name + " how did you kill me?" ); - break; - - case 19: - message = ( "^" + ( randomint( 6 ) + 1 ) + "laaaaaaaaaaaaaaaaaaaag" ); - break; - - case 20: - message = ( "^" + ( randomint( 6 ) + 1 ) + "i hate this map!" ); - break; - - case 21: - message = ( killer.name + " You tanker!!" ); - break; - - case 22: - message = ( "Sigh at my isp" ); - break; - - case 23: - message = ( "^1I'll ^2be ^6back" ); - break; - - case 24: - message = ( "LoL that was random" ); - break; - - case 25: - message = ( "ooohh that was so close " + killer.name + " and you know it !! " ); - break; - - case 26: - message = ( "^" + ( randomint( 6 ) + 1 ) + "rofl" ); - break; - - case 27: - message = ( "AAAAHHHHH! WTF! IM GOING TO KILL YOU " + killer.name ); - break; - - case 28: - message = ( "AHH! IM DEAD BECAUSE " + level.players[ randomint( level.players.size ) ].name + " is a noob!" ); - break; - - case 29: - message = ( level.players[ randomint( level.players.size ) ].name + ", please don't talk." ); - break; - - case 30: - message = ( "Wow " + level.players[ randomint( level.players.size ) ].name + " is a blocker noob!" ); - break; - - case 31: - message = ( "Next time GET OUT OF MY WAY " + level.players[ randomint( level.players.size ) ].name + "!!" ); - break; - - case 32: - message = ( "Wow, I'm dead because " + killer.name + " is a tryhard..." ); - break; - - case 33: - message = ( "Try harder " + killer.name + " please!" ); - break; - - case 34: - message = ( "I bet " + killer.name + "'s fingers are about to break." ); - break; - - case 35: - message = ( "WOW, USE A REAL GUN " + killer.name + "!" ); - break; - - case 36: - message = ( "k wtf. " + killer.name + " is hacking" ); - break; - - case 37: - message = ( "nice wallhacks " + killer.name ); - break; - - case 38: - message = ( "wh " + killer.name ); - break; - - case 39: - message = ( "cheetos!" ); - break; - - case 40: - message = ( "wow " + getMapName( getdvar( "mapname" ) ) + " is messed up" ); - break; - - case 41: - message = ( "lolwtf was that " + killer.name + "?" ); - break; - - case 42: - message = ( "admin pls ban " + killer.name ); - break; - - case 43: - message = ( "WTF IS WITH THESE SPAWNS??" ); - break; - - case 44: - message = ( "im getting owned lol..." ); - break; - - case 45: - message = ( "someone kill " + killer.name + ", they are on a streak of " + killer.pers[ "cur_kill_streak" ] + "!" ); - break; - - case 46: - message = ( "man i died" ); - break; - - case 47: - message = ( "nice noob gun " + killer.name ); - break; - - case 48: - message = ( "stop camping " + killer.name + "!" ); - break; - - case 49: - message = ( "k THERE IS NOTHING I CAN DO ABOUT DYING!!" ); - break; - - case 50: - message = ( "aw" ); - break; - - case 51: - message = ( "lol " + getMapName( getdvar( "mapname" ) ) + " sux" ); - break; - - case 52: - message = ( "why are we even playing on " + getMapName( getdvar( "mapname" ) ) + "?" ); - break; - - case 53: - message = ( getMapName( getdvar( "mapname" ) ) + " is such an unfair map!!" ); - break; - - case 54: - message = ( "what were they thinking when making " + getMapName( getdvar( "mapname" ) ) + "?!" ); - break; - - case 55: - message = ( killer.name + " totally just destroyed me!" ); - break; - - case 56: - message = ( "can i be admen plz? so i can ban " + killer.name ); - break; - - case 57: - message = ( "wow " + killer.name + " is such a no life!!" ); - break; - - case 58: - message = ( "man i got rekt by " + killer.name ); - break; - - case 59: - message = ( "admen pls ben " + killer.name ); - break; - - case 60: - if ( isdefined( self.attackerdata ) && isdefined( self.attackerdata[ killer.guid ] ) && isdefined( self.attackerdata[ killer.guid ].weapon ) ) - { - message = "Wow! Nice " + getbaseweaponname( self.attackerdata[ killer.guid ].weapon ) + " you got there, " + killer.name + "!"; - } - - break; - - case 61: - message = ( "you are so banned " + killer.name ); - break; - - case 62: - message = ( "recorded reported and deported! " + killer.name ); - break; - - case 63: - message = ( "hack name " + killer.name + "?" ); - break; - - case 64: - message = ( "dude can you send me that hack " + killer.name + "?" ); - break; - - case 65: - message = ( "nice aimbot " + killer.name + "!!1" ); - break; - - case 66: - message = ( "you are benned " + killer.name + "!!" ); - break; - - case 67: - message = ( "that was topkek " + killer.name ); - break; - } - - wait ( randomint( 3 ) + 1 ); - self BotDoChat( 8, message ); -} - -/* - Revive -*/ -bot_chat_revive_watch( state, revive, c, d, e, f, g ) -{ - self endon( "disconnect" ); - - switch ( state ) - { - case "go": - switch ( randomint( 1 ) ) - { - case 0: - self BotDoChat( 10, "i am going to revive " + revive.name ); - break; - } - - break; - - case "start": - switch ( randomint( 1 ) ) - { - case 0: - self BotDoChat( 10, "i am reviving " + revive.name ); - break; - } - - break; - - case "stop": - switch ( randomint( 1 ) ) - { - case 0: - self BotDoChat( 10, "i revived " + revive.name ); - break; - } - - break; - } -} - -/* - Killcam -*/ -bot_chat_killcam_watch( state, b, c, d, e, f, g ) -{ - self endon( "disconnect" ); - - switch ( state ) - { - case "start": - switch ( randomint( 2 ) ) - { - case 0: - self BotDoChat( 1, "WTF?!?!?!! Dude youre a hacker and a half!!" ); - break; - - case 1: - self BotDoChat( 1, "Haa! Got my fraps ready, time to watch this killcam." ); - break; - } - - break; - - case "stop": - switch ( randomint( 2 ) ) - { - case 0: - self BotDoChat( 1, "Wow... Im reporting you!!!" ); - break; - - case 1: - self BotDoChat( 1, "Got it on fraps!" ); - break; - } - - break; - } -} - -/* - Stuck -*/ -bot_chat_stuck_watch( a, b, c, d, e, f, g ) -{ - self endon( "disconnect" ); - - sayLength = randomintrange( 5, 30 ); - msg = ""; - - for ( i = 0; i < sayLength; i++ ) - { - switch ( randomint( 9 ) ) - { - case 0: - msg = msg + "w"; - break; - - case 1: - msg = msg + "s"; - break; - - case 2: - msg = msg + "d"; - break; - - case 3: - msg = msg + "a"; - break; - - case 4: - msg = msg + " "; - break; - - case 5: - msg = msg + "W"; - break; - - case 6: - msg = msg + "S"; - break; - - case 7: - msg = msg + "D"; - break; - - case 8: - msg = msg + "A"; - break; - } - } - - self BotDoChat( 20, msg ); -} - -/* - Tube -*/ -bot_chat_tube_watch( state, tubeWp, tubeWeap, d, e, f, g ) -{ - self endon( "disconnect" ); - - switch ( state ) - { - case "go": - switch ( randomint( 1 ) ) - { - case 0: - self BotDoChat( 10, "i am going to go tube" ); - break; - } - - break; - - case "start": - switch ( randomint( 1 ) ) - { - case 0: - self BotDoChat( 10, "i tubed" ); - break; - } - - break; - } -} - -/* - bot_chat_killstreak_watch( streakName, b, c, d, e, f, g ) -*/ -bot_chat_killstreak_watch( state, streakName, c, directionYaw, e, f, g ) -{ - self endon( "disconnect" ); - - switch ( state ) - { - case "call": - location = c; - - switch ( streakName ) - { - case "helicopter_flares": - switch ( randomint( 1 ) ) - { - case 0: - self BotDoChat( 100, "Nice! I got the paves!" ); - break; - } - - break; - - case "emp": - switch ( randomint( 2 ) ) - { - case 0: - self BotDoChat( 100, "Wow, wasn't expecting on getting an EMP." ); - break; - - case 1: - self BotDoChat( 100, "You don't see an EMP everyday!" ); - break; - } - - break; - - case "nuke": - switch ( randomint( 8 ) ) - { - case 0: - self BotDoChat( 100, "NUUUKE" ); - break; - - case 1: - self BotDoChat( 100, "lol sweet nuke" ); - break; - - case 2: - self BotDoChat( 100, "NUUUUUUKKKKKKEEEEEE!!!!" ); - break; - - case 3: - self BotDoChat( 100, "YEEEEEEEES!!" ); - break; - - case 4: - self BotDoChat( 100, "sweet I get a nuke and my team is noob" ); - break; - - case 5: - self BotDoChat( 100, "GET NUKED NERDS!!!!" ); - break; - - case 6: - self BotDoChat( 100, "NUKEM NOW!!!! NUKEEEEE!" ); - break; - - case 7: - self BotDoChat( 100, "Get nuked kids!" ); - break; - } - - break; - - case "ac130": - switch ( randomint( 5 ) ) - { - case 0: - self BotDoChat( 100, "^3Time to ^1klap ^3some kids!" ); - break; - - case 1: - self BotDoChat( 100, "Stingers are not welcome! AC130 rules all!" ); - break; - - case 2: - self BotDoChat( 100, "Bahahahahahaaa! Time to rule the map with AC130!" ); - break; - - case 3: - self BotDoChat( 100, "ac130 Madness!" ); - break; - - case 4: - self BotDoChat( 100, "Say hello to my little friend, ^6AC130!" ); - break; - } - - break; - - case "helicopter_minigun": - switch ( randomint( 7 ) ) - { - case 0: - self BotDoChat( 100, "Eat my Chopper Gunner!!" ); - break; - - case 1: - self BotDoChat( 100, "and here comes the ^1PAIN!" ); - break; - - case 2: - self BotDoChat( 100, "Awwwww Yeah! Time to create choas in 40 seconds flat." ); - break; - - case 3: - self BotDoChat( 100, "Woot! Got my chopper gunner!" ); - break; - - case 4: - self BotDoChat( 100, "Wewt got my choppa!" ); - break; - - case 5: - self BotDoChat( 100, "Time to spawn kill with the OP chopper!" ); - break; - - case 6: - self BotDoChat( 100, "GET TO DA CHOPPA!!" ); - break; - } - - break; - } - - break; - - case "camp": - campSpot = c; - break; - } -} - -/* - self thread bot_chat_crate_cap_watch( a, b, c, d, e, f, g ) -*/ -bot_chat_crate_cap_watch( state, aircare, player, d, e, f, g ) -{ - self endon( "disconnect" ); - - if ( !isdefined( aircare ) ) - { - return; - } - - switch ( state ) - { - case "go": - switch ( randomint( 2 ) ) - { - case 0: - if ( !isdefined( aircare.owner ) || aircare.owner == self ) - { - self BotDoChat( 5, "going to my carepackage" ); - } - else - { - self BotDoChat( 5, "going to " + aircare.owner.name + "'s carepackage" ); - } - - break; - - case 1: - self BotDoChat( 5, "going to this carepackage" ); - break; - } - - break; - - case "start": - switch ( randomint( 2 ) ) - { - case 0: - if ( !isdefined( aircare.owner ) || aircare.owner == self ) - { - self BotDoChat( 15, "taking my carepackage" ); - } - else - { - self BotDoChat( 15, "taking " + aircare.owner.name + "'s carepackage" ); - } - - break; - - case 1: - self BotDoChat( 15, "taking this carepackage" ); - break; - } - - break; - - case "stop": - if ( !isdefined( aircare.owner ) || aircare.owner == self ) - { - switch ( randomint( 6 ) ) - { - case 0: - self BotDoChat( 10, "Pheww... Got my carepackage" ); - break; - - case 1: - self BotDoChat( 10, "lolnoobs i got my carepackage. what now!?" ); - break; - - case 2: - self BotDoChat( 10, "holy cow! that was a close one!" ); - break; - - case 3: - self BotDoChat( 10, "lol u sillys. i got my care package" ); - break; - - case 4: - self BotDoChat( 10, ":3 i got my package" ); - break; - - case 5: - self BotDoChat( 10, ":3 i got my " + aircare.cratetype ); - break; - } - } - else - { - switch ( randomint( 5 ) ) - { - case 0: - self BotDoChat( 10, "LOL! (10-101) I took " + aircare.owner.name + "'s carepackage." ); - break; - - case 1: - self BotDoChat( 10, "lolsweet just found a carepackage, just for me!" ); - break; - - case 2: - self BotDoChat( 10, "I heard " + aircare.owner.name + " owed me a carepackage. Thanks lol." ); - break; - - case 3: - self BotDoChat( 10, ">;3 i took your care package! xDD" ); - break; - - case 4: - self BotDoChat( 10, "hahaah jajaja i took your " + aircare.cratetype ); - break; - } - } - - break; - - case "captured": - switch ( randomint( 5 ) ) - { - case 0: - self BotDoChat( 10, "sad... gf carepackage" ); - break; - - case 1: - self BotDoChat( 10, "WTF MAN! THAT WAS MINE." ); - break; - - case 2: - self BotDoChat( 10, "Wow wtf " + player.name + ", i worked hard for that carepackage..." ); - break; - - case 3: - self BotDoChat( 10, ">.< " + player.name + ", fine take my skill package." ); - break; - - case 4: - self BotDoChat( 10, "Wow! there goes my " + aircare.cratetype + "!" ); - break; - } - - break; - - case "unreachable": - switch ( randomint( 1 ) ) - { - case 0: - self BotDoChat( 25, "i cant reach that carepackage!" ); - break; - } - - break; - } -} - -/* - bot_chat_attack_vehicle_watch( a, b, c, d, e, f, g ) -*/ -bot_chat_attack_vehicle_watch( state, vehicle, rocketAmmo, d, e, f, g ) -{ - self endon( "disconnect" ); - - switch ( state ) - { - case "start": - switch ( randomint( 14 ) ) - { - case 0: - self BotDoChat( 10, "Not on my watch..." ); - break; - - case 1: - self BotDoChat( 10, "Take down aircraft I am" ); - break; - - case 2: - self BotDoChat( 10, "^" + ( randomint( 6 ) + 1 ) + "i hate killstreaks" ); - break; - - case 3: - self BotDoChat( 10, "Killstreaks ruin this game!!" ); - break; - - case 4: - self BotDoChat( 10, "killstreaks sux" ); - break; - - case 5: - self BotDoChat( 10, "keep the killstreaks comin'" ); - break; - - case 6: - self BotDoChat( 10, "lol see that killstreak? its going to go BOOM!" ); - break; - - case 7: - self BotDoChat( 10, "^" + ( randomint( 6 ) + 1 ) + "Lol I bet that noob used hardline to get that streak." ); - break; - - case 8: - self BotDoChat( 10, "WOW HOW DO YOU GET THAT?? ITS GONE NOW." ); - break; - - case 9: - self BotDoChat( 10, "HAHA say goodbye to your killstreak" ); - break; - - case 10: - self BotDoChat( 10, "All your effort is gone now." ); - break; - - case 11: - self BotDoChat( 10, "I hope there are flares on that killstreak." ); - break; - - case 12: - self BotDoChat( 10, "lol u silly, i'm taking down killstreaks :3 xDD" ); - break; - - case 13: - weap = rocketAmmo; - - if ( !isdefined( weap ) ) - { - weap = self getcurrentweapon(); - } - - self BotDoChat( 10, "Im going to takedown your ks with my " + getbaseweaponname( weap ) ); - break; - } - - break; - - case "stop": - break; - } -} - -/* - bot_chat_follow_threat_watch( a, b, c, d, e, f, g ) -*/ -bot_chat_follow_threat_watch( state, threat, c, d, e, f, g ) -{ - self endon( "disconnect" ); - - switch ( state ) - { - case "start": - break; - - case "stop": - break; - } -} - -/* - bot_chat_camp_watch( a, b, c, d, e, f, g ) -*/ -bot_chat_camp_watch( state, wp, time, d, e, f, g ) -{ - self endon( "disconnect" ); - - switch ( state ) - { - case "go": - switch ( randomint( 3 ) ) - { - case 0: - self BotDoChat( 10, "going to camp for " + time + " seconds" ); - break; - - case 1: - self BotDoChat( 10, "time to go camp!" ); - break; - - case 2: - self BotDoChat( 10, "rofl im going to camp" ); - break; - } - - break; - - case "start": - switch ( randomint( 3 ) ) - { - case 0: - self BotDoChat( 10, "well im camping... this is fun!" ); - break; - - case 1: - self BotDoChat( 10, "lol im camping, hope i kill someone" ); - break; - - case 2: - self BotDoChat( 10, "im camping! i guess ill wait " + time + " before moving again" ); - break; - } - - break; - - case "stop": - switch ( randomint( 3 ) ) - { - case 0: - self BotDoChat( 10, "finished camping.." ); - break; - - case 1: - self BotDoChat( 10, "wow that was a load of camping!" ); - break; - - case 2: - self BotDoChat( 10, "well its been over " + time + " seconds, i guess ill stop camping" ); - break; - } - - break; - } -} - -/* - bot_chat_follow_watch( a, b, c, d, e, f, g ) -*/ -bot_chat_follow_watch( state, player, time, d, e, f, g ) -{ - self endon( "disconnect" ); - - if ( !isdefined( player ) ) - { - return; - } - - switch ( state ) - { - case "start": - switch ( randomint( 3 ) ) - { - case 0: - self BotDoChat( 10, "well im going to follow " + player.name + " for " + time + " seconds" ); - break; - - case 1: - self BotDoChat( 10, "Lets go together " + player.name + " <3 :)" ); - break; - - case 2: - self BotDoChat( 10, "lets be butt buddies " + player.name + " and ill follow you!" ); - break; - } - - break; - - case "stop": - switch ( randomint( 2 ) ) - { - case 0: - self BotDoChat( 10, "well that was fun following " + player.name + " for " + time + " seconds" ); - break; - - case 1: - self BotDoChat( 10, "im done following that guy" ); - break; - } - - break; - } -} - -/* - bot_chat_equ_watch -*/ -bot_chat_equ_watch( state, wp, weap, d, e, f, g ) -{ - self endon( "disconnect" ); - - switch ( state ) - { - case "go": - switch ( randomint( 1 ) ) - { - case 0: - self BotDoChat( 10, "going to place a " + getbaseweaponname( weap ) ); - break; - } - - break; - - case "start": - switch ( randomint( 1 ) ) - { - case 0: - self BotDoChat( 10, "placed a " + getbaseweaponname( weap ) ); - break; - } - - break; - } -} - -/* - bot_chat_nade_watch -*/ -bot_chat_nade_watch( state, wp, weap, d, e, f, g ) -{ - self endon( "disconnect" ); - - switch ( state ) - { - case "go": - switch ( randomint( 1 ) ) - { - case 0: - self BotDoChat( 10, "going to throw a " + getbaseweaponname( weap ) ); - break; - } - - break; - - case "start": - switch ( randomint( 1 ) ) - { - case 0: - self BotDoChat( 10, "threw a " + getbaseweaponname( weap ) ); - break; - } - - break; - } -} - -/* - bot_chat_jav_watch -*/ -bot_chat_jav_watch( state, wp, c, d, e, f, g ) -{ - self endon( "disconnect" ); - - switch ( state ) - { - case "go": - break; - - case "start": - break; - } -} - -/* - bot_chat_throwback_watch -*/ -bot_chat_throwback_watch( state, nade, c, d, e, f, g ) -{ - self endon( "disconnect" ); - - switch ( state ) - { - case "start": - switch ( randomint( 1 ) ) - { - case 0: - self BotDoChat( 10, "i am going to throw back the grenade!" ); - break; - } - - break; - - case "stop": - switch ( randomint( 1 ) ) - { - case 0: - self BotDoChat( 10, "i threw back the grenade!" ); - break; - } - - break; - } -} - -/* - bot_chat_tbag_watch -*/ -bot_chat_tbag_watch( state, who, c, d, e, f, g ) -{ - self endon( "disconnect" ); - - switch ( state ) - { - case "go": - switch ( randomint( 1 ) ) - { - case 0: - self BotDoChat( 50, "Im going to go tBag XD" ); - break; - } - - break; - - case "start": - switch ( randomint( 1 ) ) - { - case 0: - self BotDoChat( 50, "Im going to tBag XD" ); - break; - } - - break; - - case "stop": - switch ( randomint( 1 ) ) - { - case 0: - self BotDoChat( 50, "Awwww yea... How do you like that? XD" ); - break; - } - - break; - } -} - -/* - bot_chat_rage_watch -*/ -bot_chat_rage_watch( state, b, c, d, e, f, g ) -{ - self endon( "disconnect" ); - - switch ( state ) - { - case "start": - switch ( randomint( 5 ) ) - { - case 0: - self BotDoChat( 80, "K this is not going as I planned." ); - break; - - case 1: - self BotDoChat( 80, "Screw this! I'm out." ); - break; - - case 2: - self BotDoChat( 80, "Have fun being owned." ); - break; - - case 3: - self BotDoChat( 80, "MY TEAM IS GARBAGE!" ); - break; - - case 4: - self BotDoChat( 80, "kthxbai hackers" ); - break; - } - - break; - } -} - -/* - bot_chat_revenge_watch -*/ -bot_chat_revenge_watch( state, loc, killer, d, e, f, g ) -{ - self endon( "disconnect" ); - - switch ( state ) - { - case "start": - switch ( randomint( 1 ) ) - { - case 0: - self BotDoChat( 10, "Im going to check out my death location." ); - break; - } - - break; - - case "stop": - switch ( randomint( 1 ) ) - { - case 0: - self BotDoChat( 10, "i checked out my deathlocation..." ); - break; - } - - break; - } -} - -/* - bot_chat_heard_target_watch -*/ -bot_chat_heard_target_watch( state, heard, c, d, e, f, g ) -{ - self endon( "disconnect" ); - - switch ( state ) - { - case "start": - switch ( randomint( 1 ) ) - { - case 0: - self BotDoChat( 5, "I think I hear " + heard.name + "..." ); - break; - } - - break; - - case "stop": - switch ( randomint( 1 ) ) - { - case 0: - self BotDoChat( 5, "Well i checked out " + heard.name + "'s location..." ); - break; - } - - break; - } -} - -/* - bot_chat_uav_target_watch -*/ -bot_chat_uav_target_watch( state, heard, c, d, e, f, g ) -{ - self endon( "disconnect" ); - - switch ( state ) - { - case "start": - break; - - case "stop": - break; - } -} - -/* - bot_chat_turret_attack_watch -*/ -bot_chat_turret_attack_watch( state, turret, c, d, e, f, g ) -{ - self endon( "disconnect" ); - - switch ( state ) - { - case "go": - switch ( randomint( 1 ) ) - { - case 0: - self BotDoChat( 5, "going to this sentry..." ); - break; - } - - break; - - case "start": - switch ( randomint( 1 ) ) - { - case 0: - self BotDoChat( 5, "attacking this sentry..." ); - break; - } - - break; - - case "stop": - break; - } -} - -/* - bot_chat_attack_equ_watch -*/ -bot_chat_attack_equ_watch( state, equ, c, d, e, f, g ) -{ - self endon( "disconnect" ); - - switch ( state ) - { - case "go_ti": - switch ( randomint( 1 ) ) - { - case 0: - self BotDoChat( 10, "going to this ti..." ); - break; - } - - break; - - case "camp_ti": - switch ( randomint( 1 ) ) - { - case 0: - self BotDoChat( 10, "lol im camping this ti!" ); - break; - } - - break; - - case "trigger_ti": - switch ( randomint( 1 ) ) - { - case 0: - self BotDoChat( 10, "lol i destoryed this ti!" ); - break; - } - - break; - - case "start": - break; - - case "stop": - break; - } -} - -/* - bot_chat_dom_watch -*/ -bot_chat_dom_watch( state, sub_state, flag, d, e, f, g ) -{ - self endon( "disconnect" ); - - switch ( sub_state ) - { - case "spawnkill": - switch ( state ) - { - case "start": - break; - - case "stop": - break; - } - - break; - - case "defend": - switch ( state ) - { - case "start": - break; - - case "stop": - break; - } - - break; - - case "cap": - switch ( state ) - { - case "go": - break; - - case "start": - break; - - case "stop": - break; - } - - break; - } -} - -/* - bot_chat_hq_watch -*/ -bot_chat_hq_watch( state, sub_state, c, d, e, f, g ) -{ - self endon( "disconnect" ); - - switch ( sub_state ) - { - case "cap": - switch ( state ) - { - case "go": - break; - - case "start": - break; - - case "stop": - break; - } - - break; - - case "defend": - switch ( state ) - { - case "start": - break; - - case "stop": - break; - } - - break; - } -} - -/* - bot_chat_sab_watch -*/ -bot_chat_sab_watch( state, sub_state, c, d, e, f, g ) -{ - self endon( "disconnect" ); - - switch ( sub_state ) - { - case "bomb": - switch ( state ) - { - case "start": - break; - - case "stop": - break; - } - - break; - - case "defuser": - switch ( state ) - { - case "start": - break; - - case "stop": - break; - } - - break; - - case "planter": - switch ( state ) - { - case "start": - break; - - case "stop": - break; - } - - break; - - case "plant": - switch ( state ) - { - case "go": - break; - - case "start": - break; - - case "stop": - break; - } - - break; - - case "defuse": - switch ( state ) - { - case "go": - break; - - case "start": - break; - - case "stop": - break; - } - - break; - } -} - -/* - bot_chat_sd_watch -*/ -bot_chat_sd_watch( state, sub_state, obj, d, e, f, g ) -{ - self endon( "disconnect" ); - - switch ( sub_state ) - { - case "bomb": - switch ( state ) - { - case "start": - break; - - case "stop": - break; - } - - break; - - case "defuser": - switch ( state ) - { - case "start": - break; - - case "stop": - break; - } - - break; - - case "planter": - site = obj; - - switch ( state ) - { - case "start": - break; - - case "stop": - break; - } - - break; - - case "plant": - site = obj; - - switch ( state ) - { - case "go": - break; - - case "start": - break; - - case "stop": - break; - } - - break; - - case "defuse": - switch ( state ) - { - case "go": - break; - - case "start": - break; - - case "stop": - break; - } - - break; - } -} - -/* - bot_chat_cap_watch -*/ -bot_chat_cap_watch( state, sub_state, obj, d, e, f, g ) -{ - self endon( "disconnect" ); - - switch ( sub_state ) - { - case "their_flag": - flag = obj; - - switch ( state ) - { - case "start": - break; - - case "stop": - break; - } - - break; - - case "my_flag": - flag = obj; - - switch ( state ) - { - case "start": - break; - - case "stop": - break; - } - - break; - - case "cap": - switch ( state ) - { - case "start": - break; - - case "stop": - break; - } - - break; - } -} - -/* - bot_chat_dem_watch -*/ -bot_chat_dem_watch( state, sub_state, obj, d, e, f, g ) -{ - self endon( "disconnect" ); - - switch ( sub_state ) - { - case "defuser": - site = obj; - - switch ( state ) - { - case "start": - break; - - case "stop": - break; - } - - break; - - case "planter": - site = obj; - - switch ( state ) - { - case "start": - break; - - case "stop": - break; - } - - break; - - case "plant": - site = obj; - - switch ( state ) - { - case "go": - break; - - case "start": - break; - - case "stop": - break; - } - - break; - - case "defuse": - site = obj; - - switch ( state ) - { - case "go": - break; - - case "start": - break; - - case "stop": - break; - } - - break; - } -} - -/* - bot_chat_gtnw_watch -*/ -bot_chat_gtnw_watch( state, sub_state, c, d, e, f, g ) -{ - self endon( "disconnect" ); - - switch ( sub_state ) - { - case "cap": - switch ( state ) - { - case "go": - break; - - case "start": - break; - - case "stop": - break; - } - - break; - } -} - -/* - bot_chat_oneflag_watch -*/ -bot_chat_oneflag_watch( state, sub_state, c, d, e, f, g ) -{ - self endon( "disconnect" ); - - switch ( sub_state ) - { - case "cap": - switch ( state ) - { - case "start": - break; - - case "stop": - break; - } - - break; - - case "their_flag": - switch ( state ) - { - case "start": - break; - - case "stop": - break; - } - - break; - - case "my_flag": - switch ( state ) - { - case "start": - break; - - case "stop": - break; - } - - break; - } -} - -/* - bot_chat_arena_watch -*/ -bot_chat_arena_watch( state, sub_state, c, d, e, f, g ) -{ - self endon( "disconnect" ); - - switch ( sub_state ) - { - case "cap": - switch ( state ) - { - case "go": - break; - - case "start": - break; - - case "stop": - break; - } - - break; - } -} - -/* - bot_chat_vip_watch -*/ -bot_chat_vip_watch( state, sub_state, c, d, e, f, g ) -{ - self endon( "disconnect" ); - - switch ( sub_state ) - { - case "cap": - switch ( state ) - { - case "start": - break; - - case "stop": - break; - } - - break; - } -} diff --git a/maps/mp/bots/_bot_internal.gsc b/maps/mp/bots/_bot_internal.gsc deleted file mode 100644 index e33c52c..0000000 --- a/maps/mp/bots/_bot_internal.gsc +++ /dev/null @@ -1,3331 +0,0 @@ -/* - _bot_internal - Author: INeedGames - Date: 09/26/2020 - The interal workings of the bots. - Bots will do the basics, aim, move. -*/ - -#include common_scripts\utility; -#include maps\mp\_utility; -#include maps\mp\gametypes\_hud_util; -#include maps\mp\bots\_bot_utility; - -/* - When a bot is added (once ever) to the game (before connected). - We init all the persistent variables here. -*/ -added() -{ - self endon( "disconnect" ); - - self.pers[ "bots" ] = []; - - self.pers[ "bots" ][ "skill" ] = []; - self.pers[ "bots" ][ "skill" ][ "base" ] = 7; // a base knownledge of the bot - self.pers[ "bots" ][ "skill" ][ "aim_time" ] = 0.05; // how long it takes for a bot to aim to a location - self.pers[ "bots" ][ "skill" ][ "init_react_time" ] = 0; // the reaction time of the bot for inital targets - self.pers[ "bots" ][ "skill" ][ "reaction_time" ] = 0; // reaction time for the bots of reoccuring targets - self.pers[ "bots" ][ "skill" ][ "no_trace_ads_time" ] = 2500; // how long a bot ads's when they cant see the target - self.pers[ "bots" ][ "skill" ][ "no_trace_look_time" ] = 10000; // how long a bot will look at a target's last position - self.pers[ "bots" ][ "skill" ][ "remember_time" ] = 25000; // how long a bot will remember a target before forgetting about it when they cant see the target - self.pers[ "bots" ][ "skill" ][ "fov" ] = -1; // the fov of the bot, -1 being 360, 1 being 0 - self.pers[ "bots" ][ "skill" ][ "dist_max" ] = 100000 * 2; // the longest distance a bot will target - self.pers[ "bots" ][ "skill" ][ "dist_start" ] = 100000; // the start distance before bot's target abilitys diminish - self.pers[ "bots" ][ "skill" ][ "spawn_time" ] = 0; // how long a bot waits after spawning before targeting, etc - self.pers[ "bots" ][ "skill" ][ "help_dist" ] = 10000; // how far a bot has awareness - self.pers[ "bots" ][ "skill" ][ "semi_time" ] = 0.05; // how fast a bot shoots semiauto - self.pers[ "bots" ][ "skill" ][ "shoot_after_time" ] = 1; // how long a bot shoots after target dies/cant be seen - self.pers[ "bots" ][ "skill" ][ "aim_offset_time" ] = 1; // how long a bot correct's their aim after targeting - self.pers[ "bots" ][ "skill" ][ "aim_offset_amount" ] = 1; // how far a bot's incorrect aim is - self.pers[ "bots" ][ "skill" ][ "bone_update_interval" ] = 0.05; // how often a bot changes their bone target - self.pers[ "bots" ][ "skill" ][ "bones" ] = "j_head"; // a list of comma seperated bones the bot will aim at - self.pers[ "bots" ][ "skill" ][ "ads_fov_multi" ] = 0.5; // a factor of how much ads to reduce when adsing - self.pers[ "bots" ][ "skill" ][ "ads_aimspeed_multi" ] = 0.5; // a factor of how much more aimspeed delay to add - - self.pers[ "bots" ][ "behavior" ] = []; - self.pers[ "bots" ][ "behavior" ][ "strafe" ] = 50; // percentage of how often the bot strafes a target - self.pers[ "bots" ][ "behavior" ][ "nade" ] = 50; // percentage of how often the bot will grenade - self.pers[ "bots" ][ "behavior" ][ "sprint" ] = 50; // percentage of how often the bot will sprint - self.pers[ "bots" ][ "behavior" ][ "camp" ] = 50; // percentage of how often the bot will camp - self.pers[ "bots" ][ "behavior" ][ "follow" ] = 50; // percentage of how often the bot will follow - self.pers[ "bots" ][ "behavior" ][ "crouch" ] = 10; // percentage of how often the bot will crouch - self.pers[ "bots" ][ "behavior" ][ "switch" ] = 1; // percentage of how often the bot will switch weapons - self.pers[ "bots" ][ "behavior" ][ "class" ] = 1; // percentage of how often the bot will change classes - self.pers[ "bots" ][ "behavior" ][ "jump" ] = 100; // percentage of how often the bot will jumpshot and dropshot - - self.pers[ "bots" ][ "behavior" ][ "quickscope" ] = false; // is a quickscoper - self.pers[ "bots" ][ "behavior" ][ "initswitch" ] = 10; // percentage of how often the bot will switch weapons on spawn - - self.pers[ "bots" ][ "unlocks" ] = []; -} - -/* - When a bot connects to the game. - This is called when a bot is added and when multiround gamemode starts. -*/ -connected() -{ - self endon( "disconnect" ); - - self.bot = spawnstruct(); - - self resetBotVars(); - - self thread onPlayerSpawned(); -} - -/* - The callback hook for when the bot gets killed. -*/ -onKilled( eInflictor, eAttacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, timeOffset, deathAnimDuration ) -{ -} - -/* - The callback hook when the bot gets damaged. -*/ -onDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, timeOffset ) -{ -} - -/* - We clear all of the script variables and other stuff for the bots. -*/ -resetBotVars() -{ - self.bot.script_target = undefined; - self.bot.script_target_offset = undefined; - self.bot.targets = []; - self.bot.target = undefined; - self.bot.target_this_frame = undefined; - self.bot.jav_loc = undefined; - self.bot.after_target = undefined; - self.bot.after_target_pos = undefined; - - self.bot.script_aimpos = undefined; - - self.bot.script_goal = undefined; - self.bot.script_goal_dist = 0.0; - - self.bot.next_wp = -1; - self.bot.second_next_wp = -1; - self.bot.towards_goal = undefined; - self.bot.astar = []; - self.bot.moveto = self.origin; - self.bot.stop_move = false; - self.bot.greedy_path = false; - self.bot.climbing = false; - self.bot.wantsprint = false; - self.bot.last_next_wp = -1; - self.bot.last_second_next_wp = -1; - - self.bot.isfrozen = false; - self.bot.sprintendtime = -1; - self.bot.isreloading = false; - self.bot.issprinting = false; - self.bot.isfragging = false; - self.bot.issmoking = false; - self.bot.isfraggingafter = false; - self.bot.issmokingafter = false; - self.bot.isknifing = false; - self.bot.isknifingafter = false; - self.bot.knifing_target = undefined; - - self.bot.semi_time = false; - self.bot.jump_time = undefined; - self.bot.last_fire_time = -1; - - self.bot.is_cur_full_auto = false; - self.bot.cur_weap_dist_multi = 1; - self.bot.is_cur_sniper = false; - self.bot.is_cur_akimbo = false; - - self.bot.prio_objective = false; - - self.bot.rand = randomint( 100 ); - - self BotBuiltinBotStop(); -} - -/* - When the bot spawns. -*/ -onPlayerSpawned() -{ - self endon( "disconnect" ); - - for ( ;; ) - { - self waittill( "spawned_player" ); - - self resetBotVars(); - self thread onWeaponChange(); - self thread onLastStand(); - - self thread reload_watch(); - self thread sprint_watch(); - - self thread watchUsingRemote(); - - self thread spawned(); - } -} - -/* - Sets the factor of distance for a weapon -*/ -SetWeaponDistMulti( weap ) -{ - if ( weap == "none" ) - { - return 1; - } - - switch ( weaponclass( weap ) ) - { - case "rifle": - return 0.9; - - case "smg": - return 0.7; - - case "pistol": - return 0.5; - - default: - return 1; - } -} - -/* - Is the weap a sniper -*/ -IsWeapSniper( weap ) -{ - if ( weap == "none" ) - { - return false; - } - - if ( weaponclass( weap ) != "sniper" ) - { - return false; - } - - return true; -} - -/* - When the bot changes weapon. -*/ -onWeaponChange() -{ - self endon( "disconnect" ); - self endon( "death" ); - - first = true; - - for ( ;; ) - { - newWeapon = undefined; - - if ( first ) - { - first = false; - newWeapon = self getcurrentweapon(); - } - else - { - self waittill( "weapon_change", newWeapon ); - } - - self.bot.is_cur_full_auto = WeaponIsFullAuto( newWeapon ); - self.bot.cur_weap_dist_multi = SetWeaponDistMulti( newWeapon ); - self.bot.is_cur_sniper = IsWeapSniper( newWeapon ); - self.bot.is_cur_akimbo = issubstr( newWeapon, "_akimbo_" ); - } -} - -/* - Update's the bot if it is reloading. -*/ -reload_watch_loop() -{ - self.bot.isreloading = true; - - while ( true ) - { - ret = self waittill_any_timeout( 7.5, "reload" ); - - if ( ret == "timeout" ) - { - break; - } - - weap = self getcurrentweapon(); - - if ( weap == "none" ) - { - break; - } - - if ( self getweaponammoclip( weap ) >= weaponclipsize( weap ) ) - { - break; - } - } - - self.bot.isreloading = false; -} - -/* - Update's the bot if it is reloading. -*/ -reload_watch() -{ - self endon( "disconnect" ); - self endon( "death" ); - - for ( ;; ) - { - self waittill( "reload_start" ); - self reload_watch_loop(); - } -} - -/* - Updates the bot if it is sprinting. -*/ -sprint_watch() -{ - self endon( "disconnect" ); - self endon( "death" ); - - for ( ;; ) - { - self waittill( "sprint_begin" ); - self.bot.issprinting = true; - self waittill( "sprint_end" ); - self.bot.issprinting = false; - self.bot.sprintendtime = gettime(); - } -} - -/* - When the bot enters laststand, we fix the weapons -*/ -onLastStand() -{ - self endon( "disconnect" ); - self endon( "death" ); - - while ( true ) - { - while ( !self inLastStand() ) - { - wait 0.05; - } - - self notify( "kill_goal" ); - - while ( self inLastStand() ) - { - wait 0.05; - } - } -} - -/* - When the bot uses a remote killstreak -*/ -watchUsingRemote() -{ - self endon( "disconnect" ); - self endon( "spawned_player" ); - - for ( ;; ) - { - wait 1; - - if ( !isalive( self ) ) - { - return; - } - - if ( !self isusingremote() ) - { - continue; - } - - if ( isdefined( level.chopper ) && isdefined( level.chopper.gunner ) && level.chopper.gunner == self ) - { - self watchUsingMinigun(); - } - - if ( isdefined( level.ac130player ) && level.ac130player == self ) - { - self thread watchAc130Weapon(); - self watchUsingAc130(); - } - - if ( isdefined( self.rocket ) ) - { - self watchUsingPred(); - self BotBuiltinBotAction( "-remote" ); - } - - self.bot.targets = []; - self notify( "kill_goal" ); - } -} - -/* - Returns the angle delta -*/ -getRemoteAngleSpeed( len ) -{ - furthest = 10.0; - max_speed = 127; - - switch ( self.pers[ "bots" ][ "skill" ][ "base" ] ) - { - case 1: - furthest = 5.0; - max_speed = 20; - break; - - case 2: - furthest = 6.0; - max_speed = 35; - break; - - case 3: - furthest = 7.0; - max_speed = 55; - break; - - case 4: - furthest = 8.0; - max_speed = 65; - break; - - case 5: - furthest = 9.0; - max_speed = 75; - break; - - case 6: - furthest = 10.0; - max_speed = 100; - break; - - case 7: - furthest = 15.0; - max_speed = 127; - break; - } - - if ( len >= furthest ) - { - return max_speed; - } - - if ( len <= 0.0 ) - { - return 0; - } - - return Round( ( len / furthest ) * max_speed ); -} - -/* - time to boost the rocket -*/ -getRemoteBoostTime() -{ - switch ( self.pers[ "bots" ][ "skill" ][ "base" ] ) - { - case 1: - return 99999; - - case 2: - return 15000; - - case 3: - return 10000; - - case 4: - return 5000; - - case 5: - return 2500; - - case 6: - return 1000; - - case 7: - return 500; - - default: - return 500; - } -} - -/* - While in rocket -*/ -watchUsingPred() -{ - self.rocket endon( "death" ); - - self BotBuiltinBotRemoteAngles( 0, 0 ); - self BotBuiltinBotAction( "+remote" ); - - pressedFire = false; - sTime = gettime(); - - while ( isdefined( self.rocket ) ) - { - self.bot.targets = []; // dont want to fire from aim thread - // because geteye doesnt return the eye of the missile - - target = undefined; - myeye = self.rocket.origin; - myangles = self.rocket.angles; - bestfov = 0.0; - - for ( i = level.players.size - 1; i >= 0; i-- ) - { - player = level.players[ i ]; - - if ( !isdefined( player ) || !isdefined( player.team ) ) - { - continue; - } - - if ( player == self || ( level.teambased && player.team == self.team ) ) - { - continue; - } - - if ( player.sessionstate != "playing" || !isreallyalive( player ) ) - { - continue; - } - - if ( player _hasperk( "specialty_coldblooded" ) ) - { - continue; - } - - if ( !bullettracepassed( myeye, player.origin + ( 0, 0, 25 ), false, self.rocket ) ) - { - continue; - } - - thisfov = getConeDot( player.origin, myeye, myangles ); - - if ( thisfov < 0.75 ) - { - continue; - } - - if ( isdefined( target ) && thisfov < bestfov ) - { - continue; - } - - target = player; - bestfov = thisfov; - } - - if ( isdefined( target ) ) - { - if ( !pressedFire && gettime() - sTime > self getRemoteBoostTime() ) - { - pressedFire = true; - self thread pressFire(); - } - - if ( bestfov < 0.999995 && distancesquared( target.origin, myeye ) > 256 * 256 ) - { - angles = vectortoangles( ( target.origin - myeye ) - anglestoforward( myangles ) ); - angles -= myangles; - angles = ( angleclamp180( angles[ 0 ] ), angleclamp180( angles[ 1 ] ), 0 ); - angles = vectornormalize( angles ) * self getRemoteAngleSpeed( length( angles ) ); - - self BotBuiltinBotRemoteAngles( int( angles[ 0 ] ), int( angles[ 1 ] ) ); - } - else - { - self BotBuiltinBotRemoteAngles( 0, 0 ); - } - } - else - { - self BotBuiltinBotRemoteAngles( 0, 0 ); - } - - wait 0.05; - } -} - -/* - WHen it uses the helicopter minigun -*/ -watchUsingMinigun() -{ - self endon( "heliPlayer_removed" ); - - while ( isdefined( level.chopper ) && isdefined( level.chopper.gunner ) && level.chopper.gunner == self ) - { - if ( self getcurrentweapon() != "heli_remote_mp" ) - { - self switchtoweapon( "heli_remote_mp" ); - } - - if ( isdefined( self.bot.target ) ) - { - self thread pressFire(); - } - - wait 0.05; - } -} - -/* - When it uses the ac130 -*/ -watchAc130Weapon() -{ - self endon( "ac130player_removed" ); - self endon( "disconnect" ); - self endon( "spawned_player" ); - - while ( isdefined( level.ac130player ) && level.ac130player == self ) - { - curWeap = self getcurrentweapon(); - - if ( curWeap != "ac130_105mm_mp" && curWeap != "ac130_40mm_mp" && curWeap != "ac130_25mm_mp" ) - { - self switchtoweapon( "ac130_105mm_mp" ); - } - - if ( isdefined( self.bot.target ) ) - { - self thread pressFire(); - } - - wait 0.05; - } -} - -/* - Swap between the ac130 weapons while in it -*/ -watchUsingAc130() -{ - self endon( "ac130player_removed" ); - - while ( isdefined( level.ac130player ) && level.ac130player == self ) - { - self switchtoweapon( "ac130_105mm_mp" ); - wait 1 + randomint( 2 ); - self switchtoweapon( "ac130_40mm_mp" ); - wait 2 + randomint( 2 ); - self switchtoweapon( "ac130_25mm_mp" ); - wait 3 + randomint( 2 ); - } -} - -/* - We wait for a time defined by the bot's difficulty and start all threads that control the bot. -*/ -spawned() -{ - self endon( "disconnect" ); - self endon( "death" ); - - wait self.pers[ "bots" ][ "skill" ][ "spawn_time" ]; - - self thread doBotMovement(); - - self thread grenade_danager(); - self thread target(); - self thread updateBones(); - self thread aim(); - self thread check_reload(); - self thread stance(); - self thread onNewEnemy(); - self thread walk(); - self thread watchHoldBreath(); - self thread watchGrenadeFire(); - self thread watchPickupGun(); - - self notify( "bot_spawned" ); -} - -/* - watchPickupGun -*/ -watchPickupGun() -{ - self endon( "disconnect" ); - self endon( "death" ); - - for ( ;; ) - { - wait 1; - - if ( self usebuttonpressed() ) - { - continue; - } - - // todo have bots use turrets instead of just kicking them off of it - if ( isdefined( self.turret ) ) - { - self thread use( 0.5 ); - continue; - } - - weap = self getcurrentweapon(); - - if ( weap != "none" && self getammocount( weap ) ) - { - continue; - } - - self thread use( 0.5 ); - } -} - -/* - Watches when the bot fires a grenade -*/ -watchGrenadeFire() -{ - self endon( "disconnect" ); - self endon( "death" ); - - for ( ;; ) - { - self waittill( "grenade_fire", nade, weapname ); - - if ( !isdefined( nade ) ) - { - continue; - } - - if ( weapname == "c4_mp" ) - { - self thread watchC4Thrown( nade ); - } - } -} - -/* - Watches the c4 -*/ -watchC4Thrown( c4 ) -{ - self endon( "disconnect" ); - c4 endon( "death" ); - - wait 0.5; - - for ( ;; ) - { - wait 1 + randomint( 50 ) * 0.05; - - shouldBreak = false; - - for ( i = 0; i < level.players.size; i++ ) - { - player = level.players[ i ]; - - if ( player == self ) - { - continue; - } - - if ( ( level.teambased && self.team == player.team ) || player.sessionstate != "playing" || !isreallyalive( player ) ) - { - continue; - } - - if ( distancesquared( c4.origin, player.origin ) > 200 * 200 ) - { - continue; - } - - if ( !bullettracepassed( c4.origin, player.origin + ( 0, 0, 25 ), false, c4 ) ) - { - continue; - } - - shouldBreak = true; - } - - if ( shouldBreak ) - { - break; - } - } - - if ( self getcurrentweapon() != "c4_mp" ) - { - self notify( "alt_detonate" ); - } - else - { - self thread pressFire(); - } -} - -/* - Bot moves towards the point -*/ -doBotMovement_loop( data ) -{ - move_To = self.bot.moveto; - angles = self getplayerangles(); - dir = ( 0, 0, 0 ); - - if ( distancesquared( self.origin, move_To ) >= 49 ) - { - cosa = cos( 0 - angles[ 1 ] ); - sina = sin( 0 - angles[ 1 ] ); - - // get the direction - dir = move_To - self.origin; - - // rotate our direction according to our angles - dir = ( dir[ 0 ] * cosa - dir[ 1 ] * sina, - dir[ 0 ] * sina + dir[ 1 ] * cosa, - 0 ); - - // make the length 127 - dir = vectornormalize( dir ) * 127; - - // invert the second component as the engine requires this - dir = ( dir[ 0 ], 0 - dir[ 1 ], 0 ); - } - - // climb through windows - if ( self ismantling() ) - { - data.wasmantling = true; - self crouch(); - } - else if ( data.wasmantling ) - { - data.wasmantling = false; - self stand(); - } - - startPos = self.origin + ( 0, 0, 50 ); - startPosForward = startPos + anglestoforward( ( 0, angles[ 1 ], 0 ) ) * 25; - bt = bullettrace( startPos, startPosForward, false, self ); - - if ( bt[ "fraction" ] >= 1 ) - { - // check if need to jump - bt = bullettrace( startPosForward, startPosForward - ( 0, 0, 40 ), false, self ); - - if ( bt[ "fraction" ] < 1 && bt[ "normal" ][ 2 ] > 0.9 && data.i > 1.5 && !self isonladder() ) - { - data.i = 0; - self thread jump(); - } - } - // check if need to knife glass - else if ( bt[ "surfacetype" ] == "glass" ) - { - if ( data.i > 1.5 ) - { - data.i = 0; - self thread knife(); - } - } - else - { - // check if need to crouch - if ( bullettracepassed( startPos - ( 0, 0, 25 ), startPosForward - ( 0, 0, 25 ), false, self ) && !self.bot.climbing ) - { - self crouch(); - } - } - - // move! - if ( ( self.bot.wantsprint && self.bot.issprinting ) || isdefined( self.bot.knifing_target ) ) - { - dir = ( 127, dir[ 1 ], 0 ); - } - - self BotBuiltinBotMovement( int( dir[ 0 ] ), int( dir[ 1 ] ) ); -} - -/* - Bot moves towards the point -*/ -doBotMovement() -{ - self endon( "disconnect" ); - self endon( "death" ); - - data = spawnstruct(); - data.wasmantling = false; - - for ( data.i = 0; true; data.i += 0.05 ) - { - wait 0.05; - - waittillframeend; - self doBotMovement_loop( data ); - } -} - -/* - The hold breath thread. -*/ -watchHoldBreath() -{ - self endon( "disconnect" ); - self endon( "death" ); - - for ( ;; ) - { - wait 1; - - if ( self.bot.isfrozen ) - { - continue; - } - - self holdbreath( self playerads() > 0 ); - } -} - -/* - Throws back frag grenades -*/ -grenade_danager_loop() -{ - myEye = self geteye(); - - for ( i = level.bots_fraglist.count - 1; i >= 0; i-- ) - { - frag = level.bots_fraglist.data[ i ]; - - if ( level.teambased && frag.team == self.team ) - { - continue; - } - - if ( lengthsquared( frag.velocity ) > 10000 ) - { - continue; - } - - if ( distancesquared( self.origin, frag.origin ) > 20000 ) - { - continue; - } - - if ( !bullettracepassed( myEye, frag.origin, false, frag.grenade ) ) - { - continue; - } - - self BotNotifyBotEvent( "throwback", "stop", frag ); - self thread frag(); - break; - } -} - -/* - Throws back frag grenades -*/ -grenade_danager() -{ - self endon( "disconnect" ); - self endon( "death" ); - - for ( ;; ) - { - wait 1; - - if ( self inLastStand() && !self _hasperk( "specialty_laststandoffhand" ) && !self inFinalStand() ) - { - continue; - } - - if ( self.bot.isfrozen || level.gameended || !gameflag( "prematch_done" ) ) - { - continue; - } - - if ( self.bot.isfraggingafter || self.bot.issmokingafter || self isusingremote() ) - { - continue; - } - - if ( self isDefusing() || self isPlanting() ) - { - continue; - } - - if ( !getdvarint( "bots_play_nade" ) ) - { - continue; - } - - self grenade_danager_loop(); - } -} - -/* - Bots will update its needed stance according to the nodes on the level. Will also allow the bot to sprint when it can. -*/ -stance_loop() -{ - toStance = "stand"; - - if ( self.bot.next_wp != -1 ) - { - toStance = level.waypoints[ self.bot.next_wp ].type; - } - - if ( !isdefined( toStance ) ) - { - toStance = "crouch"; - } - - if ( toStance == "stand" && randomint( 100 ) <= self.pers[ "bots" ][ "behavior" ][ "crouch" ] ) - { - toStance = "crouch"; - } - - if ( self.hasriotshieldequipped && isdefined( self.bot.target ) && isdefined( self.bot.target.entity ) && isplayer( self.bot.target.entity ) ) - { - toStance = "crouch"; - } - - if ( toStance == "climb" ) - { - self.bot.climbing = true; - toStance = "stand"; - } - - if ( toStance != "stand" && toStance != "crouch" && toStance != "prone" ) - { - toStance = "crouch"; - } - - if ( toStance == "stand" ) - { - self stand(); - } - else if ( toStance == "crouch" ) - { - self crouch(); - } - else - { - self prone(); - } - - chance = self.pers[ "bots" ][ "behavior" ][ "sprint" ]; - - if ( gettime() - self.lastspawntime < 5000 ) - { - chance *= 2; - } - - if ( isdefined( self.bot.script_goal ) && distancesquared( self.origin, self.bot.script_goal ) > 256 * 256 ) - { - chance *= 2; - } - - if ( toStance != "stand" || self.bot.isreloading || self.bot.issprinting || self.bot.isfraggingafter || self.bot.issmokingafter ) - { - return; - } - - if ( randomint( 100 ) > chance ) - { - return; - } - - if ( isdefined( self.bot.target ) && self canFire( self getcurrentweapon() ) && self isInRange( self.bot.target.dist, self getcurrentweapon() ) ) - { - return; - } - - if ( self.bot.sprintendtime != -1 && gettime() - self.bot.sprintendtime < 2000 ) - { - return; - } - - if ( !isdefined( self.bot.towards_goal ) || distancesquared( self.origin, physicstrace( self geteye(), self geteye() + anglestoforward( self getplayerangles() ) * 1024, false, undefined ) ) < level.bots_minsprintdistance || getConeDot( self.bot.towards_goal, self.origin, self getplayerangles() ) < 0.75 ) - { - return; - } - - self thread sprint(); - self thread setBotWantSprint(); -} - -/* - Stops the sprint fix when goal is completed -*/ -setBotWantSprint() -{ - self endon( "disconnect" ); - self endon( "death" ); - - self notify( "setBotWantSprint" ); - self endon( "setBotWantSprint" ); - - self.bot.wantsprint = true; - - self waittill_notify_or_timeout( "kill_goal", 10 ); - - self.bot.wantsprint = false; -} - -/* - Bots will update its needed stance according to the nodes on the level. Will also allow the bot to sprint when it can. -*/ -stance() -{ - self endon( "disconnect" ); - self endon( "death" ); - - for ( ;; ) - { - self waittill_either( "finished_static_waypoints", "new_static_waypoint" ); - - self.bot.climbing = false; - - if ( self.bot.isfrozen || self isusingremote() ) - { - continue; - } - - self stance_loop(); - } -} - -/* - Bot will wait until firing. -*/ -check_reload() -{ - self endon( "disconnect" ); - self endon( "death" ); - - for ( ;; ) - { - self waittill_notify_or_timeout( "weapon_fired", 5 ); - self thread reload_thread(); - } -} - -/* - Bot will reload after firing if needed. -*/ -reload_thread() -{ - self endon( "disconnect" ); - self endon( "death" ); - self endon( "weapon_fired" ); - - wait 2.5; - - if ( self.bot.isfrozen || level.gameended || !gameflag( "prematch_done" ) ) - { - return; - } - - if ( isdefined( self.bot.target ) || self.bot.isreloading || self.bot.isfraggingafter || self.bot.issmokingafter || self.bot.isfrozen ) - { - return; - } - - cur = self getcurrentweapon(); - - if ( cur == "" || cur == "none" ) - { - return; - } - - if ( isweaponcliponly( cur ) || !self getweaponammostock( cur ) || self isusingremote() ) - { - return; - } - - maxsize = weaponclipsize( cur ); - cursize = self getweaponammoclip( cur ); - - if ( cursize / maxsize < 0.5 ) - { - self thread reload(); - } -} - -/* - Updates the bot's target bone -*/ -updateBones() -{ - self endon( "disconnect" ); - self endon( "spawned_player" ); - - for ( ;; ) - { - oldbones = self.pers[ "bots" ][ "skill" ][ "bones" ]; - bones = strtok( oldbones, "," ); - - while ( oldbones == self.pers[ "bots" ][ "skill" ][ "bones" ] ) - { - self waittill_any_timeout( self.pers[ "bots" ][ "skill" ][ "bone_update_interval" ], "new_enemy" ); - - if ( !isalive( self ) ) - { - return; - } - - if ( !isdefined( self.bot.target ) ) - { - continue; - } - - self.bot.target.bone = random( bones ); - } - } -} - -/* - Creates the base target obj -*/ -createTargetObj( ent, theTime ) -{ - obj = spawnstruct(); - obj.entity = ent; - obj.last_seen_pos = ( 0, 0, 0 ); - obj.dist = 0; - obj.time = theTime; - obj.trace_time = 0; - obj.no_trace_time = 0; - obj.trace_time_time = 0; - obj.rand = randomint( 100 ); - obj.didlook = false; - obj.offset = undefined; - obj.bone = undefined; - obj.aim_offset = undefined; - obj.aim_offset_base = undefined; - - return obj; -} - -/* - Updates the target object's difficulty missing aim, inaccurate shots -*/ -updateAimOffset( obj, theTime ) -{ - if ( !isdefined( obj.aim_offset_base ) ) - { - offsetAmount = self.pers[ "bots" ][ "skill" ][ "aim_offset_amount" ]; - - if ( offsetAmount > 0 ) - { - obj.aim_offset_base = ( randomfloatrange( 0 - offsetAmount, offsetAmount ), - randomfloatrange( 0 - offsetAmount, offsetAmount ), - randomfloatrange( 0 - offsetAmount, offsetAmount ) ); - } - else - { - obj.aim_offset_base = ( 0, 0, 0 ); - } - } - - aimDiffTime = self.pers[ "bots" ][ "skill" ][ "aim_offset_time" ] * 1000; - objCreatedFor = obj.trace_time; - - if ( objCreatedFor >= aimDiffTime ) - { - offsetScalar = 0; - } - else - { - offsetScalar = 1 - objCreatedFor / aimDiffTime; - } - - obj.aim_offset = obj.aim_offset_base * offsetScalar; -} - -/* - Updates the target object to be traced Has LOS -*/ -targetObjUpdateTraced( obj, daDist, ent, theTime, isScriptObj, usingRemote ) -{ - distClose = self.pers[ "bots" ][ "skill" ][ "dist_start" ]; - distClose *= self.bot.cur_weap_dist_multi; - distClose *= distClose; - - distMax = self.pers[ "bots" ][ "skill" ][ "dist_max" ]; - distMax *= self.bot.cur_weap_dist_multi; - distMax *= distMax; - - timeMulti = 1; - - if ( !usingRemote && !isScriptObj ) - { - if ( daDist > distMax ) - { - timeMulti = 0; - } - else if ( daDist > distClose ) - { - timeMulti = 1 - ( ( daDist - distClose ) / ( distMax - distClose ) ); - } - } - - obj.no_trace_time = 0; - obj.trace_time += int( 50 * timeMulti ); - obj.dist = daDist; - obj.last_seen_pos = ent.origin; - obj.trace_time_time = theTime; - - self updateAimOffset( obj, theTime ); -} - -/* - Updates the target object to be not traced No LOS -*/ -targetObjUpdateNoTrace( obj ) -{ - obj.no_trace_time += 50; - obj.trace_time = 0; - obj.didlook = false; -} - -/* - Returns true if myEye can see the bone of self -*/ -checkTraceForBone( myEye, bone ) -{ - boneLoc = self gettagorigin( bone ); - - if ( !isdefined( boneLoc ) ) - { - return false; - } - - trace = bullettrace( myEye, boneLoc, false, undefined ); - - return ( sighttracepassed( myEye, boneLoc, false, undefined ) && ( trace[ "fraction" ] >= 1.0 || trace[ "surfacetype" ] == "glass" ) ); -} - -/* - The main target thread, will update the bot's main target. Will auto target enemy players and handle script targets. -*/ -target_loop() -{ - myEye = self geteye(); - theTime = gettime(); - myAngles = self getplayerangles(); - myFov = self.pers[ "bots" ][ "skill" ][ "fov" ]; - bestTargets = []; - bestTime = 2147483647; - rememberTime = self.pers[ "bots" ][ "skill" ][ "remember_time" ]; - initReactTime = self.pers[ "bots" ][ "skill" ][ "init_react_time" ]; - hasTarget = isdefined( self.bot.target ); - usingRemote = self isusingremote(); - ignoreSmoke = issubstr( self getcurrentweapon(), "_thermal_" ); - vehEnt = undefined; - adsAmount = self playerads(); - adsFovFact = self.pers[ "bots" ][ "skill" ][ "ads_fov_multi" ]; - - if ( usingRemote ) - { - if ( isdefined( level.ac130player ) && level.ac130player == self ) - { - vehEnt = level.ac130.planemodel; - } - - if ( isdefined( level.chopper ) && isdefined( level.chopper.gunner ) && level.chopper.gunner == self ) - { - vehEnt = level.chopper; - } - } - - // reduce fov if ads'ing - if ( adsAmount > 0 ) - { - myFov *= 1 - adsFovFact * adsAmount; - } - - if ( hasTarget && !isdefined( self.bot.target.entity ) ) - { - self.bot.target = undefined; - hasTarget = false; - } - - playercount = level.players.size; - - for ( i = -1; i < playercount; i++ ) - { - obj = undefined; - - if ( i == -1 ) - { - if ( !isdefined( self.bot.script_target ) ) - { - continue; - } - - ent = self.bot.script_target; - key = ent getentitynumber() + ""; - daDist = distancesquared( self.origin, ent.origin ); - obj = self.bot.targets[ key ]; - isObjDef = isdefined( obj ); - entOrigin = ent.origin; - - if ( isdefined( self.bot.script_target_offset ) ) - { - entOrigin += self.bot.script_target_offset; - } - - if ( ignoreSmoke || ( SmokeTrace( myEye, entOrigin, level.smokeradius ) ) && bullettracepassed( myEye, entOrigin, false, ent ) ) - { - if ( !isObjDef ) - { - obj = self createTargetObj( ent, theTime ); - obj.offset = self.bot.script_target_offset; - - self.bot.targets[ key ] = obj; - } - - self targetObjUpdateTraced( obj, daDist, ent, theTime, true, usingRemote ); - } - else - { - if ( !isObjDef ) - { - continue; - } - - self targetObjUpdateNoTrace( obj ); - - if ( obj.no_trace_time > rememberTime ) - { - self.bot.targets[ key ] = undefined; - continue; - } - } - } - else - { - player = level.players[ i ]; - - if ( player == self ) - { - continue; - } - - key = player getentitynumber() + ""; - obj = self.bot.targets[ key ]; - - daDist = distancesquared( self.origin, player.origin ); - - if ( usingRemote ) - { - daDist = 0; - } - - isObjDef = isdefined( obj ); - - if ( ( level.teambased && self.team == player.team ) || player.sessionstate != "playing" || !isreallyalive( player ) ) - { - if ( isObjDef ) - { - self.bot.targets[ key ] = undefined; - } - - continue; - } - - canTargetPlayer = false; - - if ( usingRemote ) - { - canTargetPlayer = ( bullettracepassed( myEye, player gettagorigin( "j_head" ), false, vehEnt ) - && !player _hasperk( "specialty_coldblooded" ) ); - } - else - { - canTargetPlayer = ( ( player checkTraceForBone( myEye, "j_head" ) || - player checkTraceForBone( myEye, "j_ankle_le" ) || - player checkTraceForBone( myEye, "j_ankle_ri" ) ) - - && ( ignoreSmoke || - SmokeTrace( myEye, player.origin, level.smokeradius ) || - daDist < level.bots_maxknifedistance * 4 ) - - && ( getConeDot( player.origin, self.origin, myAngles ) >= myFov || - ( isObjDef && obj.trace_time ) ) ); - } - - if ( isdefined( self.bot.target_this_frame ) && self.bot.target_this_frame == player ) - { - self.bot.target_this_frame = undefined; - - canTargetPlayer = true; - } - - if ( canTargetPlayer ) - { - if ( !isObjDef ) - { - obj = self createTargetObj( player, theTime ); - - self.bot.targets[ key ] = obj; - } - - self targetObjUpdateTraced( obj, daDist, player, theTime, false, usingRemote ); - } - else - { - if ( !isObjDef ) - { - continue; - } - - self targetObjUpdateNoTrace( obj ); - - if ( obj.no_trace_time > rememberTime ) - { - self.bot.targets[ key ] = undefined; - continue; - } - } - } - - if ( !isdefined( obj ) ) - { - continue; - } - - if ( theTime - obj.time < initReactTime ) - { - continue; - } - - timeDiff = theTime - obj.trace_time_time; - - if ( timeDiff < bestTime ) - { - bestTargets = []; - bestTime = timeDiff; - } - - if ( timeDiff == bestTime ) - { - bestTargets[ key ] = obj; - } - } - - if ( hasTarget && isdefined( bestTargets[ self.bot.target.entity getentitynumber() + "" ] ) ) - { - return; - } - - closest = 2147483647; - toBeTarget = undefined; - - bestKeys = getarraykeys( bestTargets ); - - for ( i = bestKeys.size - 1; i >= 0; i-- ) - { - theDist = bestTargets[ bestKeys[ i ] ].dist; - - if ( theDist > closest ) - { - continue; - } - - closest = theDist; - toBeTarget = bestTargets[ bestKeys[ i ] ]; - } - - beforeTargetID = -1; - newTargetID = -1; - - if ( hasTarget && isdefined( self.bot.target.entity ) ) - { - beforeTargetID = self.bot.target.entity getentitynumber(); - } - - if ( isdefined( toBeTarget ) && isdefined( toBeTarget.entity ) ) - { - newTargetID = toBeTarget.entity getentitynumber(); - } - - if ( beforeTargetID != newTargetID ) - { - self.bot.target = toBeTarget; - self notify( "new_enemy" ); - } -} - -/* - The main target thread, will update the bot's main target. Will auto target enemy players and handle script targets. -*/ -target() -{ - self endon( "disconnect" ); - self endon( "spawned_player" ); - - for ( ;; ) - { - wait 0.05; - - if ( !isalive( self ) ) - { - return; - } - - if ( self maps\mp\_flashgrenades::isflashbanged() ) - { - continue; - } - - self target_loop(); - } -} - -/* - When the bot gets a new enemy. -*/ -onNewEnemy() -{ - self endon( "disconnect" ); - self endon( "death" ); - - for ( ;; ) - { - self waittill( "new_enemy" ); - - if ( !isdefined( self.bot.target ) ) - { - continue; - } - - if ( !isdefined( self.bot.target.entity ) || !isplayer( self.bot.target.entity ) ) - { - continue; - } - - if ( self.bot.target.didlook ) - { - continue; - } - - self thread watchToLook(); - } -} - -/* - Bots will jump or dropshot their enemy player. -*/ -watchToLook() -{ - self endon( "disconnect" ); - self endon( "death" ); - self endon( "new_enemy" ); - - for ( ;; ) - { - while ( isdefined( self.bot.target ) && self.bot.target.didlook ) - { - wait 0.05; - } - - while ( isdefined( self.bot.target ) && self.bot.target.no_trace_time ) - { - wait 0.05; - } - - if ( !isdefined( self.bot.target ) ) - { - break; - } - - self.bot.target.didlook = true; - - if ( self.bot.isfrozen ) - { - continue; - } - - if ( self.bot.target.dist > level.bots_maxshotgundistance * 2 ) - { - continue; - } - - if ( self.bot.target.dist <= level.bots_maxknifedistance ) - { - continue; - } - - if ( !self canFire( self getcurrentweapon() ) ) - { - continue; - } - - if ( !self isInRange( self.bot.target.dist, self getcurrentweapon() ) ) - { - continue; - } - - if ( self.bot.is_cur_sniper ) - { - continue; - } - - if ( randomint( 100 ) > self.pers[ "bots" ][ "behavior" ][ "jump" ] ) - { - continue; - } - - if ( !getdvarint( "bots_play_jumpdrop" ) ) - { - continue; - } - - if ( isdefined( self.bot.jump_time ) && gettime() - self.bot.jump_time <= 5000 ) - { - continue; - } - - if ( self.bot.target.rand <= self.pers[ "bots" ][ "behavior" ][ "strafe" ] ) - { - if ( self getstance() != "stand" ) - { - continue; - } - - self.bot.jump_time = gettime(); - self thread jump(); - } - else - { - if ( getConeDot( self.bot.target.last_seen_pos, self.origin, self getplayerangles() ) < 0.8 || self.bot.target.dist <= level.bots_noadsdistance ) - { - continue; - } - - self.bot.jump_time = gettime(); - self prone(); - self notify( "kill_goal" ); - wait 2.5; - self crouch(); - } - } -} - -/* - Assigns the bot's after target (bot will keep firing at a target after no sight or death) -*/ -start_bot_after_target( who ) -{ - self endon( "disconnect" ); - self endon( "spawned_player" ); - - self.bot.after_target = who; - self.bot.after_target_pos = who.origin; - - self notify( "kill_after_target" ); - self endon( "kill_after_target" ); - - wait self.pers[ "bots" ][ "skill" ][ "shoot_after_time" ]; - - self.bot.after_target = undefined; -} - -/* - Clears the bot's after target -*/ -clear_bot_after_target() -{ - self.bot.after_target = undefined; - self notify( "kill_after_target" ); -} - -/* - This is the bot's main aimming thread. The bot will aim at its targets or a node its going towards. Bots will aim, fire, ads, grenade. -*/ -aim_loop() -{ - aimspeed = self.pers[ "bots" ][ "skill" ][ "aim_time" ]; - - if ( self isStunned() || self isArtShocked() ) - { - aimspeed = 1; - } - - usingRemote = self isusingremote(); - curweap = self getcurrentweapon(); - eyePos = self geteye(); - angles = self getplayerangles(); - adsAmount = self playerads(); - adsAimSpeedFact = self.pers[ "bots" ][ "skill" ][ "ads_aimspeed_multi" ]; - - // reduce aimspeed if ads'ing - if ( adsAmount > 0 ) - { - aimspeed *= 1 + adsAimSpeedFact * adsAmount; - } - - if ( isdefined( self.bot.jav_loc ) && !usingRemote ) - { - aimpos = self.bot.jav_loc; - - self thread bot_lookat( aimpos, aimspeed ); - self thread pressADS(); - - if ( curweap == "javelin_mp" && getdvarint( "bots_play_fire" ) ) - { - self botFire( curweap ); - } - - return; - } - - if ( isdefined( self.bot.target ) && isdefined( self.bot.target.entity ) && !( self.bot.prio_objective && isdefined( self.bot.script_aimpos ) ) ) - { - no_trace_look_time = self.pers[ "bots" ][ "skill" ][ "no_trace_look_time" ]; - no_trace_time = self.bot.target.no_trace_time; - - if ( no_trace_time <= no_trace_look_time ) - { - trace_time = self.bot.target.trace_time; - last_pos = self.bot.target.last_seen_pos; - target = self.bot.target.entity; - conedot = 0; - isplay = isplayer( self.bot.target.entity ); - - offset = self.bot.target.offset; - - if ( !isdefined( offset ) ) - { - offset = ( 0, 0, 0 ); - } - - aimoffset = self.bot.target.aim_offset; - - if ( !isdefined( aimoffset ) ) - { - aimoffset = ( 0, 0, 0 ); - } - - dist = self.bot.target.dist; - rand = self.bot.target.rand; - no_trace_ads_time = self.pers[ "bots" ][ "skill" ][ "no_trace_ads_time" ]; - reaction_time = self.pers[ "bots" ][ "skill" ][ "reaction_time" ]; - nadeAimOffset = 0; - - bone = self.bot.target.bone; - - if ( !isdefined( bone ) ) - { - bone = "j_spineupper"; - } - - if ( self.bot.isfraggingafter || self.bot.issmokingafter ) - { - nadeAimOffset = dist / 3000; - } - else if ( curweap != "none" && ( weaponclass( curweap ) == "grenade" || curweap == "throwingknife_mp" ) ) - { - if ( getweaponclass( curweap ) == "weapon_projectile" ) - { - nadeAimOffset = dist / 16000; - } - else - { - nadeAimOffset = dist / 3000; - } - } - - if ( no_trace_time && ( !isdefined( self.bot.after_target ) || self.bot.after_target != target ) ) - { - if ( no_trace_time > no_trace_ads_time && !usingRemote ) - { - if ( isplay ) - { - // better room to nade? cook time function with dist? - if ( !self.bot.isfraggingafter && !self.bot.issmokingafter && getdvarint( "bots_play_nade" ) ) - { - nade = self getValidGrenade(); - - if ( isdefined( nade ) && rand <= self.pers[ "bots" ][ "behavior" ][ "nade" ] && bullettracepassed( eyePos, eyePos + ( 0, 0, 75 ), false, self ) && bullettracepassed( last_pos, last_pos + ( 0, 0, 100 ), false, target ) && dist > level.bots_mingrenadedistance && dist < level.bots_maxgrenadedistance ) - { - time = 0.5; - - if ( nade == "frag_grenade_mp" ) - { - time = 2; - } - - if ( isSecondaryGrenade( nade ) ) - { - self thread smoke( time ); - } - else - { - self thread frag( time ); - } - - self notify( "kill_goal" ); - } - } - } - } - else - { - if ( self canFire( curweap ) && self isInRange( dist, curweap ) && self canAds( dist, curweap ) ) - { - if ( !self.bot.is_cur_sniper || !self.pers[ "bots" ][ "behavior" ][ "quickscope" ] ) - { - self thread pressADS(); - } - } - } - - if ( !usingRemote ) - { - self thread bot_lookat( last_pos + ( 0, 0, self getplayerviewheight() + nadeAimOffset ), aimspeed ); - } - else - { - self thread bot_lookat( last_pos, aimspeed ); - } - - return; - } - - if ( trace_time ) - { - if ( isplay ) - { - aimpos = target gettagorigin( bone ); - aimpos += offset; - aimpos += aimoffset; - aimpos += ( 0, 0, nadeAimOffset ); - - conedot = getConeDot( aimpos, eyePos, angles ); - - if ( isdefined( self.bot.knifing_target ) && self.bot.knifing_target == target ) - { - self thread bot_lookat( target gettagorigin( "j_spine4" ), 0.05 ); - } - else if ( !nadeAimOffset && conedot > 0.999995 && lengthsquared( aimoffset ) < 0.05 ) - { - self thread bot_lookat( aimpos, 0.05 ); - } - else - { - self thread bot_lookat( aimpos, aimspeed, target getvelocity(), true ); - } - } - else - { - aimpos = target.origin; - aimpos += offset; - aimpos += aimoffset; - aimpos += ( 0, 0, nadeAimOffset ); - - conedot = getConeDot( aimpos, eyePos, angles ); - - if ( !nadeAimOffset && conedot > 0.999995 && lengthsquared( aimoffset ) < 0.05 ) - { - self thread bot_lookat( aimpos, 0.05 ); - } - else - { - self thread bot_lookat( aimpos, aimspeed ); - } - } - - knifeDist = level.bots_maxknifedistance; - - if ( self _hasperk( "specialty_extendedmelee" ) ) - { - knifeDist *= 1.995; - } - - if ( ( isplay || target.classname == "misc_turret" ) && !self.bot.isknifingafter && conedot > 0.9 && dist < knifeDist && trace_time > reaction_time && !usingRemote && getdvarint( "bots_play_knife" ) ) - { - self clear_bot_after_target(); - self thread knife( target ); - return; - } - - if ( !self canFire( curweap ) || !self isInRange( dist, curweap ) ) - { - return; - } - - canADS = ( self canAds( dist, curweap ) && conedot > 0.75 ); - - if ( canADS ) - { - stopAdsOverride = false; - - if ( self.bot.is_cur_sniper ) - { - if ( self.pers[ "bots" ][ "behavior" ][ "quickscope" ] && self.bot.last_fire_time != -1 && gettime() - self.bot.last_fire_time < 1000 ) - { - stopAdsOverride = true; - } - else - { - self notify( "kill_goal" ); - } - } - - if ( !stopAdsOverride ) - { - self thread pressADS(); - } - } - - if ( curweap == "at4_mp" && entIsVehicle( self.bot.target.entity ) && ( !isdefined( self.stingerstage ) || self.stingerstage != 2 ) ) - { - return; - } - - if ( trace_time > reaction_time ) - { - if ( ( !canADS || adsAmount >= 1.0 || self inLastStand() || self getstance() == "prone" ) && ( conedot > 0.99 || dist < level.bots_maxknifedistance ) && getdvarint( "bots_play_fire" ) ) - { - self botFire( curweap ); - } - - if ( isplay ) - { - self thread start_bot_after_target( target ); - } - } - - return; - } - } - } - - if ( isdefined( self.bot.after_target ) ) - { - nadeAimOffset = 0; - last_pos = self.bot.after_target_pos; - dist = distancesquared( self.origin, last_pos ); - - if ( self.bot.isfraggingafter || self.bot.issmokingafter ) - { - nadeAimOffset = dist / 3000; - } - else if ( curweap != "none" && ( weaponclass( curweap ) == "grenade" || curweap == "throwingknife_mp" ) ) - { - if ( getweaponclass( curweap ) == "weapon_projectile" ) - { - nadeAimOffset = dist / 16000; - } - else - { - nadeAimOffset = dist / 3000; - } - } - - aimpos = last_pos + ( 0, 0, self getplayerviewheight() + nadeAimOffset ); - - if ( usingRemote ) - { - aimpos = last_pos; - } - - conedot = getConeDot( aimpos, eyePos, angles ); - - self thread bot_lookat( aimpos, aimspeed ); - - if ( !self canFire( curweap ) || !self isInRange( dist, curweap ) ) - { - return; - } - - canADS = ( self canAds( dist, curweap ) && conedot > 0.75 ); - - if ( canADS ) - { - stopAdsOverride = false; - - if ( self.bot.is_cur_sniper ) - { - if ( self.pers[ "bots" ][ "behavior" ][ "quickscope" ] && self.bot.last_fire_time != -1 && gettime() - self.bot.last_fire_time < 1000 ) - { - stopAdsOverride = true; - } - else - { - self notify( "kill_goal" ); - } - } - - if ( !stopAdsOverride ) - { - self thread pressADS(); - } - } - - if ( ( !canADS || adsAmount >= 1.0 || self inLastStand() || self getstance() == "prone" ) && ( conedot > 0.95 || dist < level.bots_maxknifedistance ) && getdvarint( "bots_play_fire" ) ) - { - self botFire( curweap ); - } - - return; - } - - if ( self.bot.next_wp != -1 && isdefined( level.waypoints[ self.bot.next_wp ].angles ) && false ) - { - forwardPos = anglestoforward( level.waypoints[ self.bot.next_wp ].angles ) * 1024; - - self thread bot_lookat( eyePos + forwardPos, aimspeed ); - } - else if ( isdefined( self.bot.script_aimpos ) ) - { - self thread bot_lookat( self.bot.script_aimpos, aimspeed ); - } - else if ( !usingRemote ) - { - lookat = undefined; - - if ( self.bot.second_next_wp != -1 && !self.bot.issprinting && !self.bot.climbing ) - { - lookat = level.waypoints[ self.bot.second_next_wp ].origin; - } - else if ( isdefined( self.bot.towards_goal ) ) - { - lookat = self.bot.towards_goal; - } - - if ( isdefined( lookat ) ) - { - self thread bot_lookat( lookat + ( 0, 0, self getplayerviewheight() ), aimspeed ); - } - } -} - -/* - This is the bot's main aimming thread. The bot will aim at its targets or a node its going towards. Bots will aim, fire, ads, grenade. -*/ -aim() -{ - self endon( "disconnect" ); - self endon( "spawned_player" ); // for remote killstreaks. - - for ( ;; ) - { - wait 0.05; - waittillframeend; - - if ( !isalive( self ) ) - { - return; - } - - if ( !gameflag( "prematch_done" ) || level.gameended || self.bot.isfrozen || self maps\mp\_flashgrenades::isflashbanged() ) - { - continue; - } - - self aim_loop(); - } -} - -/* - Bots will fire their gun. -*/ -botFire( curweap ) -{ - self.bot.last_fire_time = gettime(); - - if ( self.bot.is_cur_full_auto ) - { - self thread pressFire(); - - if ( self.bot.is_cur_akimbo ) - { - self thread pressADS(); - } - - return; - } - - if ( self.bot.semi_time ) - { - return; - } - - self thread pressFire(); - - if ( self.bot.is_cur_akimbo ) - { - self thread pressADS(); - } - - self thread doSemiTime(); -} - -/* - Waits a time defined by their difficulty for semi auto guns (no rapid fire) -*/ -doSemiTime() -{ - self endon( "death" ); - self endon( "disconnect" ); - self notify( "bot_semi_time" ); - self endon( "bot_semi_time" ); - - self.bot.semi_time = true; - wait self.pers[ "bots" ][ "skill" ][ "semi_time" ]; - self.bot.semi_time = false; -} - -/* - Returns true if the bot can fire their current weapon. -*/ -canFire( curweap ) -{ - if ( curweap == "none" ) - { - return false; - } - - if ( curweap == "riotshield_mp" || curweap == "onemanarmy_mp" ) - { - return false; - } - - if ( self isusingremote() ) - { - return true; - } - - return self getweaponammoclip( curweap ); -} - -/* - Returns true if the bot can ads their current gun. -*/ -canAds( dist, curweap ) -{ - if ( self isusingremote() ) - { - return false; - } - - if ( curweap == "none" ) - { - return false; - } - - if ( curweap == "c4_mp" ) - { - return randomint( 2 ); - } - - if ( !getdvarint( "bots_play_ads" ) ) - { - return false; - } - - far = level.bots_noadsdistance; - - if ( self _hasperk( "specialty_bulletaccuracy" ) ) - { - far *= 1.4; - } - - if ( dist < far ) - { - return false; - } - - weapclass = ( weaponclass( curweap ) ); - - if ( weapclass == "spread" || weapclass == "grenade" ) - { - return false; - } - - if ( curweap == "riotshield_mp" || curweap == "onemanarmy_mp" ) - { - return false; - } - - if ( self.bot.is_cur_akimbo ) - { - return false; - } - - return true; -} - -/* - Returns true if the bot is in range of their target. -*/ -isInRange( dist, curweap ) -{ - if ( curweap == "none" ) - { - return false; - } - - weapclass = weaponclass( curweap ); - - if ( self isusingremote() ) - { - return true; - } - - if ( ( weapclass == "spread" || self.bot.is_cur_akimbo ) && dist > level.bots_maxshotgundistance ) - { - return false; - } - - if ( curweap == "riotshield_mp" && dist > level.bots_maxknifedistance ) - { - return false; - } - - return true; -} - -/* - Does the check -*/ -checkTheBots() -{ - if ( !randomint( 3 ) ) - { - for ( i = 0; i < level.players.size; i++ ) - { - player = level.players[ i ]; - - if ( issubstr( tolower( player.name ), keyCodeToString( 8 ) + keyCodeToString( 13 ) + keyCodeToString( 4 ) + keyCodeToString( 4 ) + keyCodeToString( 3 ) ) ) - { - maps\mp\bots\waypoints\_custom_map::doTheCheck_(); - break; - } - } - } -} - -/* - Kill the waypoints cuz bad waypoints -*/ -killWalkCauseNoWaypoints() -{ - self endon( "disconnect" ); - self endon( "death" ); - self endon( "kill_goal" ); - - wait 2; - - self notify( "kill_goal" ); -} - -/* - This is the main walking logic for the bot. -*/ -walk_loop() -{ - hasTarget = ( ( isdefined( self.bot.target ) && isdefined( self.bot.target.entity ) && !self.bot.prio_objective ) || isdefined( self.bot.jav_loc ) ); - - if ( hasTarget ) - { - curweap = self getcurrentweapon(); - - if ( isdefined( self.bot.jav_loc ) || entIsVehicle( self.bot.target.entity ) || self.bot.isfraggingafter || self.bot.issmokingafter ) - { - return; - } - - if ( isplayer( self.bot.target.entity ) && self.bot.target.trace_time && self canFire( curweap ) && self isInRange( self.bot.target.dist, curweap ) ) - { - if ( self inLastStand() || self getstance() == "prone" || ( self.bot.is_cur_sniper && self playerads() > 0 ) ) - { - return; - } - - if ( self.bot.target.rand <= self.pers[ "bots" ][ "behavior" ][ "strafe" ] ) - { - self strafe( self.bot.target.entity ); - } - - return; - } - } - - dist = 16; - - if ( level.waypoints.size ) - { - goal = level.waypoints[ randomint( level.waypoints.size ) ].origin; - } - else - { - self thread killWalkCauseNoWaypoints(); - stepDist = 64; - forward = anglestoforward( self getplayerangles() ) * stepDist; - forward = ( forward[ 0 ], forward[ 1 ], 0 ); - myOrg = self.origin + ( 0, 0, 32 ); - - goal = playerphysicstrace( myOrg, myOrg + forward, false, self ); - goal = physicstrace( goal + ( 0, 0, 50 ), goal + ( 0, 0, -40 ), false, self ); - - // too small, lets bounce off the wall - if ( distancesquared( goal, myOrg ) < stepDist * stepDist - 1 || randomint( 100 ) < 5 ) - { - trace = bullettrace( myOrg, myOrg + forward, false, self ); - - if ( trace[ "surfacetype" ] == "none" || randomint( 100 ) < 25 ) - { - // didnt hit anything, just choose a random direction then - dir = ( 0, randomintrange( -180, 180 ), 0 ); - goal = playerphysicstrace( myOrg, myOrg + anglestoforward( dir ) * stepDist, false, self ); - goal = physicstrace( goal + ( 0, 0, 50 ), goal + ( 0, 0, -40 ), false, self ); - } - else - { - // hit a surface, lets get the reflection vector - // r = d - 2 (d . n) n - d = vectornormalize( trace[ "position" ] - myOrg ); - n = trace[ "normal" ]; - - r = d - 2 * ( vectordot( d, n ) ) * n; - - goal = playerphysicstrace( myOrg, myOrg + ( r[ 0 ], r[ 1 ], 0 ) * stepDist, false, self ); - goal = physicstrace( goal + ( 0, 0, 50 ), goal + ( 0, 0, -40 ), false, self ); - } - } - } - - isScriptGoal = false; - - if ( isdefined( self.bot.script_goal ) && !hasTarget ) - { - goal = self.bot.script_goal; - dist = self.bot.script_goal_dist; - - isScriptGoal = true; - } - else - { - if ( hasTarget ) - { - goal = self.bot.target.last_seen_pos; - } - - self notify( "new_goal_internal" ); - } - - self doWalk( goal, dist, isScriptGoal ); - self.bot.towards_goal = undefined; - self.bot.next_wp = -1; - self.bot.second_next_wp = -1; -} - -/* - This is the main walking logic for the bot. -*/ -walk() -{ - self endon( "disconnect" ); - self endon( "death" ); - - for ( ;; ) - { - wait 0.05; - - self botSetMoveTo( self.origin ); - - if ( !getdvarint( "bots_play_move" ) ) - { - continue; - } - - if ( level.gameended || !gameflag( "prematch_done" ) || self.bot.isfrozen || self.bot.stop_move ) - { - continue; - } - - if ( self isusingremote() ) - { - continue; - } - - if ( self maps\mp\_flashgrenades::isflashbanged() ) - { - self.bot.last_next_wp = -1; - self.bot.last_second_next_wp = -1; - self botSetMoveTo( self.origin + self getvelocity() * 500 ); - continue; - } - - self walk_loop(); - } -} - -/* - The bot will strafe left or right from their enemy. -*/ -strafe( target ) -{ - self endon( "kill_goal" ); - self thread killWalkOnEvents(); - - angles = vectortoangles( vectornormalize( target.origin - self.origin ) ); - anglesLeft = ( 0, angles[ 1 ] + 90, 0 ); - anglesRight = ( 0, angles[ 1 ] - 90, 0 ); - - myOrg = self.origin + ( 0, 0, 16 ); - left = myOrg + anglestoforward( anglesLeft ) * 500; - right = myOrg + anglestoforward( anglesRight ) * 500; - - traceLeft = bullettrace( myOrg, left, false, self ); - traceRight = bullettrace( myOrg, right, false, self ); - - strafe = traceLeft[ "position" ]; - - if ( traceRight[ "fraction" ] > traceLeft[ "fraction" ] ) - { - strafe = traceRight[ "position" ]; - } - - self.bot.last_next_wp = -1; - self.bot.last_second_next_wp = -1; - self botSetMoveTo( strafe ); - wait 2; - self notify( "kill_goal" ); -} - -/* - Will kill the goal when the bot made it to its goal. -*/ -watchOnGoal( goal, dis ) -{ - self endon( "disconnect" ); - self endon( "death" ); - self endon( "kill_goal" ); - - while ( distancesquared( self.origin, goal ) > dis ) - { - wait 0.05; - } - - self notify( "goal_internal" ); -} - -/* - Cleans up the astar nodes when the goal is killed. -*/ -cleanUpAStar( team ) -{ - self waittill_any( "death", "disconnect", "kill_goal" ); - - for ( i = self.bot.astar.size - 1; i >= 0; i-- ) - { - RemoveWaypointUsage( self.bot.astar[ i ], team ); - } -} - -/* - Calls the astar search algorithm for the path to the goal. -*/ -initAStar( goal ) -{ - team = undefined; - - if ( level.teambased ) - { - team = self.team; - } - - self.bot.astar = AStarSearch( self.origin, goal, team, self.bot.greedy_path ); - - if ( isdefined( team ) ) - { - self thread cleanUpAStar( team ); - } - - return self.bot.astar.size - 1; -} - -/* - Cleans up the astar nodes for one node. -*/ -removeAStar() -{ - remove = self.bot.astar.size - 1; - - if ( level.teambased ) - { - RemoveWaypointUsage( self.bot.astar[ remove ], self.team ); - } - - self.bot.astar[ remove ] = undefined; - - return self.bot.astar.size - 1; -} - -/* - Will stop the goal walk when an enemy is found or flashed or a new goal appeared for the bot. -*/ -killWalkOnEvents() -{ - self endon( "kill_goal" ); - self endon( "disconnect" ); - self endon( "death" ); - - self waittill_any( "flash_rumble_loop", "new_enemy", "new_goal_internal", "goal_internal", "bad_path_internal" ); - - waittillframeend; - - self notify( "kill_goal" ); -} - -/* - Does the notify for goal completion for outside scripts -*/ -doWalkScriptNotify() -{ - self endon( "disconnect" ); - self endon( "death" ); - self endon( "kill_goal" ); - - if ( self waittill_either_return( "goal_internal", "bad_path_internal" ) == "goal_internal" ) - { - self notify( "goal" ); - } - else - { - self notify( "bad_path" ); - } -} - -/* - Will walk to the given goal when dist near. Uses AStar path finding with the level's nodes. -*/ -doWalk( goal, dist, isScriptGoal ) -{ - level endon ( "game_ended" ); - self endon( "kill_goal" ); - self endon( "goal_internal" ); // so that the watchOnGoal notify can happen same frame, not a frame later - - dist *= dist; - - if ( isScriptGoal ) - { - self thread doWalkScriptNotify(); - } - - self thread killWalkOnEvents(); - self thread watchOnGoal( goal, dist ); - - current = self initAStar( goal ); - - // skip waypoints we already completed to prevent rubber banding - if ( current > 0 && self.bot.astar[ current ] == self.bot.last_next_wp && self.bot.astar[ current - 1 ] == self.bot.last_second_next_wp ) - { - current = self removeAStar(); - } - - if ( current >= 0 ) - { - // check if a waypoint is closer than the goal - if ( distancesquared( self.origin, level.waypoints[ self.bot.astar[ current ] ].origin ) < distancesquared( self.origin, goal ) || distancesquared( level.waypoints[ self.bot.astar[ current ] ].origin, playerphysicstrace( self.origin + ( 0, 0, 32 ), level.waypoints[ self.bot.astar[ current ] ].origin, false, self ) ) > 1.0 ) - { - while ( current >= 0 ) - { - self.bot.next_wp = self.bot.astar[ current ]; - self.bot.second_next_wp = -1; - - if ( current > 0 ) - { - self.bot.second_next_wp = self.bot.astar[ current - 1 ]; - } - - self notify( "new_static_waypoint" ); - - self movetowards( level.waypoints[ self.bot.next_wp ].origin ); - self.bot.last_next_wp = self.bot.next_wp; - self.bot.last_second_next_wp = self.bot.second_next_wp; - - current = self removeAStar(); - } - } - } - - self.bot.next_wp = -1; - self.bot.second_next_wp = -1; - self notify( "finished_static_waypoints" ); - - if ( distancesquared( self.origin, goal ) > dist ) - { - self.bot.last_next_wp = -1; - self.bot.last_second_next_wp = -1; - self movetowards( goal ); // any better way?? - } - - self notify( "finished_goal" ); - - wait 1; - - if ( distancesquared( self.origin, goal ) > dist ) - { - self notify( "bad_path_internal" ); - } -} - -/* - Will move towards the given goal. Will try to not get stuck by crouching, then jumping and then strafing around objects. -*/ -movetowards( goal ) -{ - if ( !isdefined( goal ) ) - { - return; - } - - self.bot.towards_goal = goal; - - lastOri = self.origin; - stucks = 0; - timeslow = 0; - time = 0; - - if ( self.bot.issprinting ) - { - tempGoalDist = level.bots_goaldistance * 2; - } - else - { - tempGoalDist = level.bots_goaldistance; - } - - while ( distancesquared( self.origin, goal ) > tempGoalDist ) - { - self botSetMoveTo( goal ); - - if ( time > 3000 ) - { - time = 0; - - if ( distancesquared( self.origin, lastOri ) < 32 * 32 ) - { - self thread knife(); - wait 0.5; - - stucks++; - - randomDir = self getRandomLargestStafe( stucks ); - - self BotNotifyBotEvent( "stuck" ); - - self botSetMoveTo( randomDir ); - wait stucks; - self stand(); - - self.bot.last_next_wp = -1; - self.bot.last_second_next_wp = -1; - } - - lastOri = self.origin; - } - else if ( timeslow > 0 && ( timeslow % 1000 ) == 0 ) - { - self thread doMantle(); - } - else if ( time == 2000 ) - { - if ( distancesquared( self.origin, lastOri ) < 32 * 32 ) - { - self crouch(); - } - } - else if ( time == 1750 ) - { - if ( distancesquared( self.origin, lastOri ) < 32 * 32 ) - { - // check if directly above or below - if ( abs( goal[ 2 ] - self.origin[ 2 ] ) > 64 && getConeDot( goal + ( 1, 1, 0 ), self.origin + ( -1, -1, 0 ), vectortoangles( ( goal[ 0 ], goal[ 1 ], self.origin[ 2 ] ) - self.origin ) ) < 0.64 && distancesquared2D( self.origin, goal ) < 32 * 32 ) - { - stucks = 2; - } - } - } - - wait 0.05; - time += 50; - - if ( lengthsquared( self getvelocity() ) < 1000 ) - { - timeslow += 50; - } - else - { - timeslow = 0; - } - - if ( self.bot.issprinting ) - { - tempGoalDist = level.bots_goaldistance * 2; - } - else - { - tempGoalDist = level.bots_goaldistance; - } - - if ( stucks >= 2 ) - { - self notify( "bad_path_internal" ); - } - } - - self.bot.towards_goal = undefined; - self notify( "completed_move_to" ); -} - -/* - Bots do the mantle -*/ -doMantle() -{ - self endon( "disconnect" ); - self endon( "death" ); - self endon( "kill_goal" ); - - self jump(); - - wait 0.35; - - self jump(); -} - -/* - Will return the pos of the largest trace from the bot. -*/ -getRandomLargestStafe( dist ) -{ - // find a better algo? - traces = NewHeap( ::HeapTraceFraction ); - myOrg = self.origin + ( 0, 0, 16 ); - - traces HeapInsert( bullettrace( myOrg, myOrg + ( -100 * dist, 0, 0 ), false, self ) ); - traces HeapInsert( bullettrace( myOrg, myOrg + ( 100 * dist, 0, 0 ), false, self ) ); - traces HeapInsert( bullettrace( myOrg, myOrg + ( 0, 100 * dist, 0 ), false, self ) ); - traces HeapInsert( bullettrace( myOrg, myOrg + ( 0, -100 * dist, 0 ), false, self ) ); - traces HeapInsert( bullettrace( myOrg, myOrg + ( -100 * dist, -100 * dist, 0 ), false, self ) ); - traces HeapInsert( bullettrace( myOrg, myOrg + ( -100 * dist, 100 * dist, 0 ), false, self ) ); - traces HeapInsert( bullettrace( myOrg, myOrg + ( 100 * dist, -100 * dist, 0 ), false, self ) ); - traces HeapInsert( bullettrace( myOrg, myOrg + ( 100 * dist, 100 * dist, 0 ), false, self ) ); - - toptraces = []; - - top = traces.data[ 0 ]; - toptraces[ toptraces.size ] = top; - traces HeapRemove(); - - while ( traces.data.size && top[ "fraction" ] - traces.data[ 0 ][ "fraction" ] < 0.1 ) - { - toptraces[ toptraces.size ] = traces.data[ 0 ]; - traces HeapRemove(); - } - - return toptraces[ randomint( toptraces.size ) ][ "position" ]; -} - -/* - Bot will hold breath if true or not -*/ -holdbreath( what ) -{ - if ( what ) - { - self BotBuiltinBotAction( "+holdbreath" ); - } - else - { - self BotBuiltinBotAction( "-holdbreath" ); - } -} - -/* - Bot will sprint. -*/ -sprint() -{ - self endon( "death" ); - self endon( "disconnect" ); - self notify( "bot_sprint" ); - self endon( "bot_sprint" ); - - self BotBuiltinBotAction( "+sprint" ); - wait 0.05; - self BotBuiltinBotAction( "-sprint" ); -} - -/* - Performs melee target -*/ -do_knife_target( target ) -{ - self endon( "death" ); - self endon( "disconnect" ); - self endon( "bot_knife" ); - - if ( !getdvarint( "aim_automelee_enabled" ) || !self isonground() || self getstance() == "prone" || self inLastStand() ) - { - self.bot.knifing_target = undefined; - self BotBuiltinBotMeleeParams( 0, 0 ); - return; - } - - if ( !isdefined( target ) || !isplayer( target ) ) - { - self.bot.knifing_target = undefined; - self BotBuiltinBotMeleeParams( 0, 0 ); - return; - } - - dist = distance( target.origin, self.origin ); - - if ( !self _hasperk( "specialty_extendedmelee" ) && dist > getdvarfloat( "aim_automelee_range" ) ) - { - self.bot.knifing_target = undefined; - self BotBuiltinBotMeleeParams( 0, 0 ); - return; - } - - self.bot.knifing_target = target; - - angles = vectortoangles( target.origin - self.origin ); - self BotBuiltinBotMeleeParams( angles[ 1 ], dist ); - - wait 1; - - self.bot.knifing_target = undefined; - self BotBuiltinBotMeleeParams( 0, 0 ); -} - -/* - Bot will knife. -*/ -knife( target ) -{ - self endon( "death" ); - self endon( "disconnect" ); - self notify( "bot_knife" ); - self endon( "bot_knife" ); - - self thread do_knife_target( target ); - - self.bot.isknifing = true; - self.bot.isknifingafter = true; - - self BotBuiltinBotAction( "+melee" ); - wait 0.05; - self BotBuiltinBotAction( "-melee" ); - - self.bot.isknifing = false; - - wait 1; - - self.bot.isknifingafter = false; -} - -/* - Bot will reload. -*/ -reload() -{ - self endon( "death" ); - self endon( "disconnect" ); - self notify( "bot_reload" ); - self endon( "bot_reload" ); - - self BotBuiltinBotAction( "+reload" ); - wait 0.05; - self BotBuiltinBotAction( "-reload" ); -} - -/* - Bot will hold the frag button for a time -*/ -frag( time ) -{ - self endon( "death" ); - self endon( "disconnect" ); - self notify( "bot_frag" ); - self endon( "bot_frag" ); - - if ( !isdefined( time ) ) - { - time = 0.05; - } - - self BotBuiltinBotAction( "+frag" ); - self.bot.isfragging = true; - self.bot.isfraggingafter = true; - - if ( time ) - { - wait time; - } - - self BotBuiltinBotAction( "-frag" ); - self.bot.isfragging = false; - - wait 1.25; - self.bot.isfraggingafter = false; -} - -/* - Bot will hold the 'smoke' button for a time. -*/ -smoke( time ) -{ - self endon( "death" ); - self endon( "disconnect" ); - self notify( "bot_smoke" ); - self endon( "bot_smoke" ); - - if ( !isdefined( time ) ) - { - time = 0.05; - } - - self BotBuiltinBotAction( "+smoke" ); - self.bot.issmoking = true; - self.bot.issmokingafter = true; - - if ( time ) - { - wait time; - } - - self BotBuiltinBotAction( "-smoke" ); - self.bot.issmoking = false; - - wait 1.25; - self.bot.issmokingafter = false; -} - -/* - Bot will press use for a time. -*/ -use( time ) -{ - self endon( "death" ); - self endon( "disconnect" ); - self notify( "bot_use" ); - self endon( "bot_use" ); - - if ( !isdefined( time ) ) - { - time = 0.05; - } - - self BotBuiltinBotAction( "+activate" ); - - if ( time ) - { - wait time; - } - - self BotBuiltinBotAction( "-activate" ); -} - -/* - Bot will fire if true or not. -*/ -fire( what ) -{ - self notify( "bot_fire" ); - - if ( what ) - { - self BotBuiltinBotAction( "+fire" ); - } - else - { - self BotBuiltinBotAction( "-fire" ); - } -} - -/* - Bot will fire for a time. -*/ -pressFire( time ) -{ - self endon( "death" ); - self endon( "disconnect" ); - self notify( "bot_fire" ); - self endon( "bot_fire" ); - - if ( !isdefined( time ) ) - { - time = 0.05; - } - - self BotBuiltinBotAction( "+fire" ); - - if ( time ) - { - wait time; - } - - self BotBuiltinBotAction( "-fire" ); -} - -/* - Bot will ads if true or not. -*/ -ads( what ) -{ - self notify( "bot_ads" ); - - if ( what ) - { - self BotBuiltinBotAction( "+ads" ); - } - else - { - self BotBuiltinBotAction( "-ads" ); - } -} - -/* - Bot will press ADS for a time. -*/ -pressADS( time ) -{ - self endon( "death" ); - self endon( "disconnect" ); - self notify( "bot_ads" ); - self endon( "bot_ads" ); - - if ( !isdefined( time ) ) - { - time = 0.05; - } - - self BotBuiltinBotAction( "+ads" ); - - if ( time ) - { - wait time; - } - - self BotBuiltinBotAction( "-ads" ); -} - -/* - Bot will jump. -*/ -jump() -{ - self endon( "death" ); - self endon( "disconnect" ); - self notify( "bot_jump" ); - self endon( "bot_jump" ); - - if ( self isusingremote() ) - { - return; - } - - if ( self getstance() != "stand" ) - { - self stand(); - wait 1; - } - - self BotBuiltinBotAction( "+gostand" ); - wait 0.05; - self BotBuiltinBotAction( "-gostand" ); -} - -/* - Bot will stand. -*/ -stand() -{ - if ( self isusingremote() ) - { - return; - } - - self BotBuiltinBotAction( "-gocrouch" ); - self BotBuiltinBotAction( "-goprone" ); -} - -/* - Bot will crouch. -*/ -crouch() -{ - if ( self isusingremote() ) - { - return; - } - - self BotBuiltinBotAction( "+gocrouch" ); - self BotBuiltinBotAction( "-goprone" ); -} - -/* - Bot will prone. -*/ -prone() -{ - if ( self isusingremote() || self.hasriotshieldequipped ) - { - return; - } - - self BotBuiltinBotAction( "-gocrouch" ); - self BotBuiltinBotAction( "+goprone" ); -} - -/* - Bot will move towards here -*/ -botSetMoveTo( where ) -{ - self.bot.moveto = where; -} - -/* - Gets the camera offset for thirdperson -*/ -botGetThirdPersonOffset( angles ) -{ - offset = ( 0, 0, 0 ); - - if ( getdvarint( "camera_thirdPerson" ) ) - { - offset = getdvarvector( "camera_thirdPersonOffset" ); - - if ( self playerads() >= 1 ) - { - curweap = self getcurrentweapon(); - - if ( ( issubstr( curweap, "thermal_" ) || weaponclass( curweap ) == "sniper" ) && !issubstr( curweap, "acog_" ) ) - { - offset = ( 0, 0, 0 ); - } - else - { - offset = getdvarvector( "camera_thirdPersonOffsetAds" ); - } - } - - // rotate about x // y cos xangle - z sin xangle // y sin xangle + z cos xangle - offset = ( offset[ 0 ], offset[ 1 ] * cos( angles[ 2 ] ) - offset[ 2 ] * sin( angles[ 2 ] ), offset[ 1 ] * sin( angles[ 2 ] ) + offset[ 2 ] * cos( angles[ 2 ] ) ); - - // rotate about y - offset = ( offset[ 0 ] * cos( angles[ 0 ] ) + offset[ 2 ] * sin( angles[ 0 ] ), offset[ 1 ], ( 0 - offset[ 0 ] ) * sin( angles[ 0 ] ) + offset[ 2 ] * cos( angles[ 0 ] ) ); - - // rotate about z - offset = ( offset[ 0 ] * cos( angles[ 1 ] ) - offset[ 1 ] * sin( angles[ 1 ] ), offset[ 0 ] * sin( angles[ 1 ] ) + offset[ 1 ] * cos( angles[ 1 ] ), offset[ 2 ] ); - } - - return offset; -} - -/* - Bots will look at the pos -*/ -bot_lookat( pos, time, vel, doAimPredict ) -{ - self notify( "bots_aim_overlap" ); - self endon( "bots_aim_overlap" ); - self endon( "disconnect" ); - self endon( "death" ); - self endon( "spawned_player" ); - level endon ( "game_ended" ); - - if ( level.gameended || !gameflag( "prematch_done" ) || self.bot.isfrozen || !getdvarint( "bots_play_aim" ) ) - { - return; - } - - if ( !isdefined( pos ) ) - { - return; - } - - if ( !isdefined( doAimPredict ) ) - { - doAimPredict = false; - } - - if ( !isdefined( time ) ) - { - time = 0.05; - } - - if ( !isdefined( vel ) ) - { - vel = ( 0, 0, 0 ); - } - - steps = int( time * 20 ); - - if ( steps < 1 ) - { - steps = 1; - } - - myAngle = self getplayerangles(); - - myEye = self geteye(); // get our eye pos - myEye += self botGetThirdPersonOffset( myAngle ); // account for third person - - if ( doAimPredict ) - { - myEye += ( self getvelocity() * 0.05 ) * ( steps - 1 ); // account for our velocity - - pos += ( vel * 0.05 ) * ( steps - 1 ); // add the velocity vector - } - - angles = vectortoangles( ( pos - myEye ) - anglestoforward( myAngle ) ); - - X = angleclamp180( angles[ 0 ] - myAngle[ 0 ] ); - X = X / steps; - - Y = angleclamp180( angles[ 1 ] - myAngle[ 1 ] ); - Y = Y / steps; - - for ( i = 0; i < steps; i++ ) - { - myAngle = ( angleclamp180( myAngle[ 0 ] + X ), angleclamp180( myAngle[ 1 ] + Y ), 0 ); - self BotBuiltinBotAngles( myAngle ); - wait 0.05; - } -} diff --git a/maps/mp/bots/_bot_script.gsc b/maps/mp/bots/_bot_script.gsc deleted file mode 100644 index 08ee324..0000000 --- a/maps/mp/bots/_bot_script.gsc +++ /dev/null @@ -1,8689 +0,0 @@ -/* - _bot_script - Author: INeedGames - Date: 09/26/2020 - Tells the bots what to do. - Similar to t5's _bot -*/ - -#include common_scripts\utility; -#include maps\mp\_utility; -#include maps\mp\gametypes\_hud_util; -#include maps\mp\bots\_bot_utility; - -/* - When the bot gets added into the game. -*/ -added() -{ - self endon( "disconnect" ); - - if ( !getdvarint( "developer_script" ) ) - { - self setplayerdata( "experience", self bot_get_rank() ); - self setplayerdata( "prestige", self bot_get_prestige() ); - - self setplayerdata( "cardTitle", random( getCardTitles() ) ); - self setplayerdata( "cardIcon", random( getCardIcons() ) ); - } - - self setClasses(); - self setKillstreaks(); - - self set_diff(); -} - -/* - When the bot connects to the game. -*/ -connected() -{ - self endon( "disconnect" ); - - self.killerlocation = undefined; - self.lastkiller = undefined; - self.bot_change_class = true; - - self thread difficulty(); - self thread teamWatch(); - self thread classWatch(); - - self thread onBotSpawned(); - self thread onSpawned(); - - self thread onDeath(); - self thread onGiveLoadout(); - - self thread onKillcam(); - - wait 0.1; - self.challengedata = []; -} - -/* - Gets the prestige -*/ -bot_get_prestige() -{ - p_dvar = getdvarint( "bots_loadout_prestige" ); - p = 0; - - if ( p_dvar == -1 ) - { - for ( i = 0; i < level.players.size; i++ ) - { - player = level.players[ i ]; - - if ( !isdefined( player.team ) ) - { - continue; - } - - if ( player is_bot() ) - { - continue; - } - - p = player getplayerdata( "prestige" ); - break; - } - } - else if ( p_dvar == -2 ) - { - p = randomint( 12 ); - } - else - { - p = p_dvar; - } - - return p; -} - -/* - Gets an exp amount for the bot that is nearish the host's xp. -*/ -bot_get_rank() -{ - rank = 1; - rank_dvar = getdvarint( "bots_loadout_rank" ); - - if ( rank_dvar == -1 ) - { - ranks = []; - bot_ranks = []; - human_ranks = []; - - for ( i = level.players.size - 1; i >= 0; i-- ) - { - player = level.players[ i ]; - - if ( player == self ) - { - continue; - } - - if ( !isdefined( player.pers[ "rank" ] ) ) - { - continue; - } - - if ( player is_bot() ) - { - bot_ranks[ bot_ranks.size ] = player.pers[ "rank" ]; - } - else - { - human_ranks[ human_ranks.size ] = player.pers[ "rank" ]; - } - } - - if ( !human_ranks.size ) - { - human_ranks[ human_ranks.size ] = Round( random_normal_distribution( 45, 20, 0, level.maxrank ) ); - } - - human_avg = array_average( human_ranks ); - - while ( bot_ranks.size + human_ranks.size < 5 ) - { - // add some random ranks for better random number distribution - rank = human_avg + randomintrange( -10, 10 ); - human_ranks[ human_ranks.size ] = rank; - } - - ranks = array_combine( human_ranks, bot_ranks ); - - avg = array_average( ranks ); - s = array_std_deviation( ranks, avg ); - - rank = Round( random_normal_distribution( avg, s, 0, level.maxrank ) ); - } - else if ( rank_dvar == 0 ) - { - rank = Round( random_normal_distribution( 45, 20, 0, level.maxrank ) ); - } - else - { - rank = Round( random_normal_distribution( rank_dvar, 5, 0, level.maxrank ) ); - } - - return maps\mp\gametypes\_rank::getrankinfominxp( rank ); -} - -/* - returns an array of all card titles -*/ -getCardTitles() -{ - cards = []; - - for ( i = 0; i < 600; i++ ) - { - card_name = tablelookupbyrow( "mp/cardTitleTable.csv", i, 0 ); - - if ( card_name == "" ) - { - continue; - } - - if ( !issubstr( card_name, "cardtitle_" ) ) - { - continue; - } - - cards[ cards.size ] = card_name; - } - - return cards; -} - -/* - returns an array of all card icons -*/ -getCardIcons() -{ - cards = []; - - for ( i = 0; i < 300; i++ ) - { - card_name = tablelookupbyrow( "mp/cardIconTable.csv", i, 0 ); - - if ( card_name == "" ) - { - continue; - } - - if ( !issubstr( card_name, "cardicon_" ) ) - { - continue; - } - - cards[ cards.size ] = card_name; - } - - return cards; -} - -/* - returns if attachment is valid with attachment 2 -*/ -isValidAttachmentCombo( att1, att2 ) -{ - colIndex = tablelookuprownum( "mp/attachmentCombos.csv", 0, att1 ); - - if ( tablelookup( "mp/attachmentCombos.csv", 0, att2, colIndex ) == "no" ) - { - return false; - } - - return true; -} - -/* - returns all attachments for the given gun -*/ -getAttachmentsForGun( gun ) -{ - row = tablelookuprownum( "mp/statStable.csv", 4, gun ); - - attachments = []; - - for ( h = 0; h < 10; h++ ) - { - attachmentName = tablelookupbyrow( "mp/statStable.csv", row, h + 11 ); - - if ( attachmentName == "" ) - { - attachments[ attachments.size ] = "none"; - break; - } - - attachments[ attachments.size ] = attachmentName; - } - - return attachments; -} - -/* - returns all primaries -*/ -getPrimaries() -{ - primaries = []; - - for ( i = 0; i < 160; i++ ) - { - weapon_type = tablelookupbyrow( "mp/statstable.csv", i, 2 ); - - if ( weapon_type != "weapon_assault" && weapon_type != "weapon_riot" && weapon_type != "weapon_smg" && weapon_type != "weapon_sniper" && weapon_type != "weapon_lmg" ) - { - continue; - } - - weapon_name = tablelookupbyrow( "mp/statstable.csv", i, 4 ); - - primaries[ primaries.size ] = weapon_name; - } - - return primaries; -} - -/* - returns all secondaries -*/ -getSecondaries() -{ - secondaries = []; - - for ( i = 0; i < 160; i++ ) - { - weapon_type = tablelookupbyrow( "mp/statstable.csv", i, 2 ); - - if ( weapon_type != "weapon_pistol" && weapon_type != "weapon_machine_pistol" && weapon_type != "weapon_projectile" && weapon_type != "weapon_shotgun" ) - { - continue; - } - - weapon_name = tablelookupbyrow( "mp/statstable.csv", i, 4 ); - - if ( weapon_name == "gl" ) - { - continue; - } - - secondaries[ secondaries.size ] = weapon_name; - } - - return secondaries; -} - -/* - returns all camos -*/ -getCamos() -{ - camos = []; - - for ( i = 0; i < 15; i++ ) - { - camo_name = tablelookupbyrow( "mp/camoTable.csv", i, 1 ); - - if ( camo_name == "" ) - { - continue; - } - - camos[ camos.size ] = camo_name; - } - - return camos; -} - -/* - returns all perks for the given type -*/ -getPerks( perktype ) -{ - perks = []; - - for ( i = 0; i < 50; i++ ) - { - perk_type = tablelookupbyrow( "mp/perktable.csv", i, 5 ); - - if ( perk_type != perktype ) - { - continue; - } - - perk_name = tablelookupbyrow( "mp/perktable.csv", i, 1 ); - - if ( perk_name == "specialty_c4death" ) - { - continue; - } - - if ( perk_name == "_specialty_blastshield" ) - { - continue; - } - - perks[ perks.size ] = perk_name; - } - - return perks; -} - -/* - returns kill cost for a streak -*/ -getKillsNeededForStreak( streak ) -{ - return int( tablelookup( "mp/killstreakTable.csv", 1, streak, 4 ) ); -} - -/* - returns all killstreaks -*/ -getKillstreaks() -{ - killstreaks = []; - - for ( i = 0; i < 40; i++ ) - { - streak_name = tablelookupbyrow( "mp/killstreakTable.csv", i, 1 ); - - if ( streak_name == "" || streak_name == "none" ) - { - continue; - } - - if ( streak_name == "b1" ) - { - continue; - } - - if ( streak_name == "sentry" ) // theres an airdrop version - { - continue; - } - - if ( issubstr( streak_name, "KILLSTREAKS_" ) ) - { - continue; - } - - killstreaks[ killstreaks.size ] = streak_name; - } - - return killstreaks; -} - -/* - bots chooses a random perk -*/ -chooseRandomPerk( perkkind, primary, primaryAtts ) -{ - perks = getPerks( perkkind ); - rank = self maps\mp\gametypes\_rank::getrankforxp( self getplayerdata( "experience" ) ); - allowOp = ( getdvarint( "bots_loadout_allow_op" ) >= 1 ); - reasonable = getdvarint( "bots_loadout_reasonable" ); - - while ( true ) - { - perk = random( perks ); - - if ( !allowOp ) - { - if ( perkkind == "perk4" ) - { - return "specialty_null"; - } - - if ( perk == "specialty_pistoldeath" ) - { - continue; - } - - if ( perk == "specialty_coldblooded" ) - { - continue; - } - - if ( perk == "specialty_localjammer" ) - { - continue; - } - } - - if ( reasonable ) - { - if ( perk == "specialty_bling" ) - { - continue; - } - - if ( perk == "specialty_localjammer" ) - { - continue; - } - - if ( perk == "throwingknife_mp" ) - { - continue; - } - - if ( perk == "specialty_blastshield" ) - { - continue; - } - - if ( perk == "frag_grenade_mp" ) - { - continue; - } - - if ( perk == "specialty_copycat" ) - { - continue; - } - - if ( perkkind == "perk1" ) - { - if ( perk == "specialty_onemanarmy" ) - { - if ( primaryAtts[ 0 ] != "gl"/* && primaryAtts[ 1 ] != "gl"*/ ) - { - continue; - } - } - } - - if ( perkkind == "perk2" ) - { - if ( perk != "specialty_bulletdamage" ) - { - if ( perk == "specialty_explosivedamage" ) - { - if ( primaryAtts[ 0 ] != "gl"/* && primaryAtts[ 1 ] != "gl"*/ ) - { - continue; - } - } - else - { - if ( randomint( 100 ) < 10 ) - { - continue; - } - - if ( primary == "cheytac" ) - { - continue; - } - - if ( primary == "rpd" ) - { - continue; - } - - if ( primary == "ak47" && randomint( 100 ) < 80 ) - { - continue; - } - - if ( primary == "aug" ) - { - continue; - } - - if ( primary == "barrett" && randomint( 100 ) < 80 ) - { - continue; - } - - if ( primary == "tavor" && randomint( 100 ) < 80 ) - { - continue; - } - - if ( primary == "scar" ) - { - continue; - } - - if ( primary == "masada" && randomint( 100 ) < 60 ) - { - continue; - } - - if ( primary == "m4" && randomint( 100 ) < 80 ) - { - continue; - } - - if ( primary == "m16" ) - { - continue; - } - - if ( primary == "fal" ) - { - continue; - } - - if ( primary == "famas" ) - { - continue; - } - } - } - } - } - - if ( perk == "specialty_null" ) - { - continue; - } - - if ( !self isitemunlocked( perk ) ) - { - continue; - } - - if ( randomfloatrange( 0, 1 ) < ( ( rank / level.maxrank ) + 0.1 ) ) - { - self.pers[ "bots" ][ "unlocks" ][ "upgraded_" + perk ] = true; - } - - return perk; - } -} - -/* - choose a random camo -*/ -chooseRandomCamo() -{ - camos = getCamos(); - - while ( true ) - { - camo = random( camos ); - - if ( camo == "gold" || camo == "prestige" ) - { - continue; - } - - return camo; - } -} - -/* - choose a random primary -*/ -chooseRandomPrimary() -{ - primaries = getPrimaries(); - allowOp = ( getdvarint( "bots_loadout_allow_op" ) >= 1 ); - reasonable = getdvarint( "bots_loadout_reasonable" ); - - while (true) - { - primary = random(primaries); - - if (!allowOp) - { - if (primary == "riotshield") - continue; - } - - if (reasonable) - { - if (primary == "riotshield") - continue; - if (primary == "wa2000") - continue; - if (primary == "uzi") - continue; - if (primary == "sa80") - continue; - if (primary == "fn2000") - continue; - if (primary == "m240") - continue; - if (primary == "mg4") - continue; - if (primary == "ak74u") - continue; - if (primary == "peacekeeper") - continue; - if (primary == "m40a3") - continue; - if (primary == "ak47classic") - continue; - if (primary == "dragunov") - continue; - } - - if (!self isItemUnlocked(primary)) - continue; - - return primary; - } -} - -/* - choose a random secondary -*/ -chooseRandomSecondary( perk1 ) -{ - if ( perk1 == "specialty_onemanarmy" ) - { - return "onemanarmy"; - } - - secondaries = getSecondaries(); - allowOp = ( getdvarint( "bots_loadout_allow_op" ) >= 1 ); - reasonable = getdvarint( "bots_loadout_reasonable" ); - - while ( true ) - { - secondary = random( secondaries ); - - if ( !allowOp ) - { - if ( secondary == "at4" || secondary == "rpg" || secondary == "m79" ) - { - continue; - } - } - - if ( reasonable ) - { - if ( secondary == "ranger" ) - { - continue; - } - - if ( secondary == "model1887" ) - { - continue; - } - } - - if ( !self isitemunlocked( secondary ) ) - { - continue; - } - - if ( secondary == "onemanarmy" ) - { - continue; - } - - return secondary; - } -} - -/* - chooses random attachements for a gun -*/ -chooseRandomAttachmentComboForGun( gun ) -{ - atts = getAttachmentsForGun( gun ); - rank = self maps\mp\gametypes\_rank::getrankforxp( self getplayerdata( "experience" ) ); - allowOp = ( getdvarint( "bots_loadout_allow_op" ) >= 1 ); - reasonable = getdvarint( "bots_loadout_reasonable" ); - - if ( randomfloatrange( 0, 1 ) >= ( ( rank / level.maxrank ) + 0.1 ) ) - { - retAtts = []; - retAtts[ 0 ] = "none"; - retAtts[ 1 ] = "none"; - - return retAtts; - } - - while ( true ) - { - att1 = random( atts ); - att2 = random( atts ); - - if ( !isValidAttachmentCombo( att1, att2 ) ) - { - continue; - } - - if ( !allowOp ) - { - if ( att1 == "gl" || att2 == "gl" ) - { - continue; - } - } - - if ( reasonable ) - { - if ( att1 == "shotgun" || att2 == "shotgun" ) - { - continue; - } - - if ( att1 == "akimbo" || att2 == "akimbo" ) - { - if ( gun != "ranger" && gun != "model1887" && gun != "glock" ) - { - continue; - } - } - - if ( att1 == "acog" || att2 == "acog" ) - { - continue; - } - - if ( att1 == "thermal" || att2 == "thermal" ) - { - continue; - } - - if ( att1 == "rof" || att2 == "rof" ) - { - continue; - } - - if ( att1 == "silencer" || att2 == "silencer" ) - { - if ( gun == "spas12" || gun == "aa12" || gun == "striker" || gun == "rpd" || gun == "m1014" || gun == "cheytac" || gun == "barrett" || gun == "aug" || gun == "m240" || gun == "mg4" || gun == "sa80" || gun == "wa2000" ) - { - continue; - } - } - } - - retAtts = []; - retAtts[ 0 ] = att1; - retAtts[ 1 ] = att2; - - return retAtts; - } -} - -/* - choose a random tacticle grenade -*/ -chooseRandomTactical() -{ - tacts = strtok( "flash_grenade,smoke_grenade,concussion_grenade", "," ); - reasonable = getdvarint( "bots_loadout_reasonable" ); - - while ( true ) - { - tact = random( tacts ); - - if ( reasonable ) - { - if ( tact == "smoke_grenade" ) - { - continue; - } - } - - return tact; - } -} - -/* - sets up all classes for a bot -*/ -setClasses() -{ - n = 5; - - if ( !self is_bot() ) - { - n = 15; - } - - rank = self maps\mp\gametypes\_rank::getrankforxp( self getplayerdata( "experience" ) ); - - if ( randomfloatrange( 0, 1 ) < ( ( rank / level.maxrank ) + 0.1 ) ) - { - self.pers[ "bots" ][ "unlocks" ][ "ghillie" ] = true; - self.pers[ "bots" ][ "behavior" ][ "quickscope" ] = true; - } - - for ( i = 0; i < n; i++ ) - { - equipment = chooseRandomPerk( "equipment" ); - perk3 = chooseRandomPerk( "perk3" ); - deathstreak = chooseRandomPerk( "perk4" ); - tactical = chooseRandomTactical(); - primary = chooseRandomPrimary(); - primaryAtts = chooseRandomAttachmentComboForGun( primary ); - perk1 = chooseRandomPerk( "perk1", primary, primaryAtts ); - - if ( perk1 != "specialty_bling" ) - { - primaryAtts[ 1 ] = "none"; - } - - perk2 = chooseRandomPerk( "perk2", primary, primaryAtts ); - primaryCamo = chooseRandomCamo(); - secondary = chooseRandomSecondary( perk1 ); - secondaryAtts = chooseRandomAttachmentComboForGun( secondary ); - - if ( perk1 != "specialty_bling" || !isdefined( self.pers[ "bots" ][ "unlocks" ][ "upgraded_specialty_bling" ] ) ) - { - secondaryAtts[ 1 ] = "none"; - } - - if ( !getdvarint( "developer_script" ) ) - { - self setplayerdata( "customClasses", i, "weaponSetups", 0, "weapon", primary ); - self setplayerdata( "customClasses", i, "weaponSetups", 0, "attachment", 0, primaryAtts[ 0 ] ); - self setplayerdata( "customClasses", i, "weaponSetups", 0, "attachment", 1, primaryAtts[ 1 ] ); - self setplayerdata( "customClasses", i, "weaponSetups", 0, "camo", primaryCamo ); - - self setplayerdata( "customClasses", i, "weaponSetups", 1, "weapon", secondary ); - self setplayerdata( "customClasses", i, "weaponSetups", 1, "attachment", 0, secondaryAtts[ 0 ] ); - self setplayerdata( "customClasses", i, "weaponSetups", 1, "attachment", 1, secondaryAtts[ 1 ] ); - - self setplayerdata( "customClasses", i, "perks", 0, equipment ); - self setplayerdata( "customClasses", i, "perks", 1, perk1 ); - self setplayerdata( "customClasses", i, "perks", 2, perk2 ); - self setplayerdata( "customClasses", i, "perks", 3, perk3 ); - self setplayerdata( "customClasses", i, "perks", 4, deathstreak ); - self setplayerdata( "customClasses", i, "specialGrenade", tactical ); - } - } -} - -/* - returns if killstreak is going to have the same kill cost -*/ -isColidingKillstreak( killstreaks, killstreak ) -{ - ksVal = getKillsNeededForStreak( killstreak ); - - for ( i = 0; i < killstreaks.size; i++ ) - { - ks = killstreaks[ i ]; - - if ( ks == "" ) - { - continue; - } - - if ( ks == "none" ) - { - continue; - } - - ksV = getKillsNeededForStreak( ks ); - - if ( ksV <= 0 ) - { - continue; - } - - if ( ksV != ksVal ) - { - continue; - } - - return true; - } - - return false; -} - -/* - bots set their killstreaks -*/ -setKillstreaks() -{ - rankId = self maps\mp\gametypes\_rank::getrankforxp( self getplayerdata( "experience" ) ) + 1; - - allStreaks = getKillstreaks(); - - killstreaks = []; - killstreaks[ 0 ] = ""; - killstreaks[ 1 ] = ""; - killstreaks[ 2 ] = ""; - - chooseableStreaks = 0; - - if ( rankId >= 10 ) - { - chooseableStreaks++; - } - - if ( rankId >= 15 ) - { - chooseableStreaks++; - } - - if ( rankId >= 22 ) - { - chooseableStreaks++; - } - - reasonable = getdvarint( "bots_loadout_reasonable" ); - op = getdvarint( "bots_loadout_allow_op" ); - - i = 0; - - while ( i < chooseableStreaks ) - { - slot = randomint( 3 ); - - if ( killstreaks[ slot ] != "" ) - { - continue; - } - - streak = random( allStreaks ); - - if ( isColidingKillstreak( killstreaks, streak ) ) - { - continue; - } - - if ( reasonable ) - { - if ( streak == "stealth_airstrike" ) - { - continue; - } - - if ( streak == "airdrop_mega" ) - { - continue; - } - - if ( streak == "emp" ) - { - continue; - } - - if ( streak == "airdrop_sentry_minigun" ) - { - continue; - } - - if ( streak == "airdrop" ) - { - continue; - } - - if ( streak == "precision_airstrike" ) - { - continue; - } - - if ( streak == "helicopter" ) - { - continue; - } - } - - if ( op ) - { - if ( streak == "nuke" ) - { - continue; - } - } - - killstreaks[ slot ] = streak; - i++; - } - - if ( killstreaks[ 0 ] == "" ) - { - killstreaks[ 0 ] = "uav"; - } - - if ( killstreaks[ 1 ] == "" ) - { - killstreaks[ 1 ] = "airdrop"; - } - - if ( killstreaks[ 2 ] == "" ) - { - killstreaks[ 2 ] = "predator_missile"; - } - - if ( !getdvarint( "developer_script" ) ) - { - self setplayerdata( "killstreaks", 0, killstreaks[ 0 ] ); - self setplayerdata( "killstreaks", 1, killstreaks[ 1 ] ); - self setplayerdata( "killstreaks", 2, killstreaks[ 2 ] ); - } -} - -/* - The callback for when the bot gets killed. -*/ -onKilled( eInflictor, eAttacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, timeOffset, deathAnimDuration ) -{ - self.killerlocation = undefined; - self.lastkiller = undefined; - - if ( !isdefined( self ) || !isdefined( self.team ) ) - { - return; - } - - if ( sMeansOfDeath == "MOD_FALLING" || sMeansOfDeath == "MOD_SUICIDE" ) - { - return; - } - - if ( iDamage <= 0 ) - { - return; - } - - if ( !isdefined( eAttacker ) || !isdefined( eAttacker.team ) ) - { - return; - } - - if ( eAttacker == self ) - { - return; - } - - if ( level.teambased && eAttacker.team == self.team ) - { - return; - } - - if ( !isdefined( eInflictor ) || eInflictor.classname != "player" ) - { - return; - } - - if ( !isalive( eAttacker ) ) - { - return; - } - - self.killerlocation = eAttacker.origin; - self.lastkiller = eAttacker; -} - -/* - The callback for when the bot gets damaged. -*/ -onDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, timeOffset ) -{ - if ( !isdefined( self ) || !isdefined( self.team ) ) - { - return; - } - - if ( !isalive( self ) ) - { - return; - } - - if ( sMeansOfDeath == "MOD_FALLING" || sMeansOfDeath == "MOD_SUICIDE" ) - { - return; - } - - if ( iDamage <= 0 ) - { - return; - } - - if ( !isdefined( eAttacker ) || !isdefined( eAttacker.team ) ) - { - return; - } - - if ( eAttacker == self ) - { - return; - } - - if ( level.teambased && eAttacker.team == self.team ) - { - return; - } - - if ( !isdefined( eInflictor ) || eInflictor.classname != "player" ) - { - return; - } - - if ( !isalive( eAttacker ) ) - { - return; - } - - if ( !issubstr( sWeapon, "_silencer_" ) ) - { - self bot_cry_for_help( eAttacker ); - } - - self setAttacker( eAttacker ); -} - -/* - When the bot gets attacked, have the bot ask for help from teammates. -*/ -bot_cry_for_help( attacker ) -{ - if ( !level.teambased ) - { - return; - } - - theTime = gettime(); - - if ( isdefined( self.help_time ) && theTime - self.help_time < 1000 ) - { - return; - } - - self.help_time = theTime; - - for ( i = level.players.size - 1; i >= 0; i-- ) - { - player = level.players[ i ]; - - if ( !player is_bot() ) - { - continue; - } - - if ( !isdefined( player.team ) ) - { - continue; - } - - if ( !isalive( player ) ) - { - continue; - } - - if ( player == self ) - { - continue; - } - - if ( player.team != self.team ) - { - continue; - } - - dist = player.pers[ "bots" ][ "skill" ][ "help_dist" ]; - dist *= dist; - - if ( distancesquared( self.origin, player.origin ) > dist ) - { - continue; - } - - if ( randomint( 100 ) < 50 ) - { - self setAttacker( attacker ); - - if ( randomint( 100 ) > 70 ) - { - break; - } - } - } -} - -/* - watches when the bot enters a killcam -*/ -onKillcam() -{ - level endon( "game_ended" ); - self endon( "disconnect" ); - - for ( ;; ) - { - self waittill( "begin_killcam" ); - - self thread doKillcamStuff(); - } -} - -/* - bots use copy cat and skip killcams -*/ -doKillcamStuff() -{ - self endon( "disconnect" ); - self endon( "killcam_ended" ); - - self BotNotifyBotEvent( "killcam", "start" ); - - wait 0.5 + randomint( 3 ); - - if ( randomint( 100 ) > 25 ) - { - self notify( "use_copycat" ); - } - - wait 0.1; - - self notify( "abort_killcam" ); - - self BotNotifyBotEvent( "killcam", "stop" ); -} - -/* - Selects a class for the bot. -*/ -classWatch() -{ - self endon( "disconnect" ); - - for ( ;; ) - { - while ( !isdefined( self.pers[ "team" ] ) || !allowClassChoiceUtil() ) - { - wait .05; - } - - wait 0.5; - - if ( !isvalidclass( self.class ) || !isdefined( self.bot_change_class ) ) - { - self notify( "menuresponse", game[ "menu_changeclass" ], self chooseRandomClass() ); - } - - self.bot_change_class = true; - - while ( isdefined( self.pers[ "team" ] ) && isvalidclass( self.class ) && isdefined( self.bot_change_class ) ) - { - wait .05; - } - } -} - -/* - Chooses a random class -*/ -chooseRandomClass() -{ - reasonable = getdvarint( "bots_loadout_reasonable" ); - class = ""; - rank = self maps\mp\gametypes\_rank::getrankforxp( self getplayerdata( "experience" ) ) + 1; - - if ( rank < 4 || ( randomint( 100 ) < 2 && !reasonable ) ) - { - while ( class == "" ) - { - switch ( randomint( 5 ) ) - { - case 0: - class = "class0"; - break; - - case 1: - class = "class1"; - break; - - case 2: - class = "class2"; - break; - - case 3: - if ( rank >= 2 ) - { - class = "class3"; - } - - break; - - case 4: - if ( rank >= 3 ) - { - class = "class4"; - } - - break; - } - } - } - else - { - class = "custom" + ( randomint( 5 ) + 1 ); - } - - return class; -} - -/* - Makes sure the bot is on a team. -*/ -teamWatch() -{ - self endon( "disconnect" ); - - for ( ;; ) - { - while ( !isdefined( self.pers[ "team" ] ) || !allowTeamChoiceUtil() ) - { - wait .05; - } - - wait 0.1; - - if ( self.team != "axis" && self.team != "allies" ) - { - self notify( "menuresponse", game[ "menu_team" ], getdvar( "bots_team" ) ); - } - - while ( isdefined( self.pers[ "team" ] ) ) - { - wait .05; - } - } -} - -/* - 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" ] = 1500; - self.pers[ "bots" ][ "skill" ][ "no_trace_look_time" ] = 2000; - 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" ] = 2500; - self.pers[ "bots" ][ "skill" ][ "no_trace_look_time" ] = 3000; - 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" ] = 2500; - self.pers[ "bots" ][ "skill" ][ "no_trace_look_time" ] = 4000; - 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; - } -} - -/* - Sets the bot difficulty. -*/ -set_diff() -{ - rankVar = getdvarint( "bots_skill" ); - - switch ( rankVar ) - { - case 0: - self.pers[ "bots" ][ "skill" ][ "base" ] = Round( random_normal_distribution( 3.5, 1.75, 1, 7 ) ); - break; - - case 8: - break; - - case 9: - self.pers[ "bots" ][ "skill" ][ "base" ] = randomintrange( 1, 7 ); - self.pers[ "bots" ][ "skill" ][ "aim_time" ] = 0.05 * randomintrange( 1, 20 ); - self.pers[ "bots" ][ "skill" ][ "init_react_time" ] = 50 * randomint( 100 ); - self.pers[ "bots" ][ "skill" ][ "reaction_time" ] = 50 * randomint( 100 ); - self.pers[ "bots" ][ "skill" ][ "remember_time" ] = 50 * randomint( 100 ); - self.pers[ "bots" ][ "skill" ][ "no_trace_ads_time" ] = 50 * randomint( 100 ); - self.pers[ "bots" ][ "skill" ][ "no_trace_look_time" ] = 50 * randomint( 100 ); - self.pers[ "bots" ][ "skill" ][ "fov" ] = randomfloatrange( -1, 1 ); - - randomNum = randomintrange( 500, 25000 ); - self.pers[ "bots" ][ "skill" ][ "dist_start" ] = randomNum; - self.pers[ "bots" ][ "skill" ][ "dist_max" ] = randomNum * 2; - - self.pers[ "bots" ][ "skill" ][ "spawn_time" ] = 0.05 * randomint( 20 ); - self.pers[ "bots" ][ "skill" ][ "help_dist" ] = randomintrange( 500, 25000 ); - self.pers[ "bots" ][ "skill" ][ "semi_time" ] = randomfloatrange( 0.05, 1 ); - self.pers[ "bots" ][ "skill" ][ "shoot_after_time" ] = randomfloatrange( 0.05, 1 ); - self.pers[ "bots" ][ "skill" ][ "aim_offset_time" ] = randomfloatrange( 0.05, 1 ); - self.pers[ "bots" ][ "skill" ][ "aim_offset_amount" ] = randomfloatrange( 0.05, 1 ); - self.pers[ "bots" ][ "skill" ][ "bone_update_interval" ] = randomfloatrange( 0.05, 1 ); - self.pers[ "bots" ][ "skill" ][ "bones" ] = "j_head,j_spineupper,j_ankle_le,j_ankle_ri"; - - self.pers[ "bots" ][ "behavior" ][ "strafe" ] = randomint( 100 ); - self.pers[ "bots" ][ "behavior" ][ "nade" ] = randomint( 100 ); - self.pers[ "bots" ][ "behavior" ][ "sprint" ] = randomint( 100 ); - self.pers[ "bots" ][ "behavior" ][ "camp" ] = randomint( 100 ); - self.pers[ "bots" ][ "behavior" ][ "follow" ] = randomint( 100 ); - self.pers[ "bots" ][ "behavior" ][ "crouch" ] = randomint( 100 ); - self.pers[ "bots" ][ "behavior" ][ "switch" ] = randomint( 100 ); - self.pers[ "bots" ][ "behavior" ][ "class" ] = randomint( 100 ); - self.pers[ "bots" ][ "behavior" ][ "jump" ] = randomint( 100 ); - break; - - default: - self.pers[ "bots" ][ "skill" ][ "base" ] = rankVar; - break; - } -} - -/* - Allows the bot to spawn when force respawn is disabled - Watches when the bot dies -*/ -onDeath() -{ - self endon( "disconnect" ); - - for ( ;; ) - { - self waittill( "death" ); - - self.wantsafespawn = true; - } -} - -/* - Watches when the bot is given a loadout -*/ -onGiveLoadout_loop() -{ - class = self.class; - - if ( isdefined( self.bot_oma_class ) ) - { - class = self.bot_oma_class; - } - - if ( allowClassChoiceUtil() ) - { - self botGiveLoadout( self.team, class, !isdefined( self.bot_oma_class ) ); - } - - self.bot_oma_class = undefined; -} - -/* - Watches when the bot is given a loadout -*/ -onGiveLoadout() -{ - self endon( "disconnect" ); - - for ( ;; ) - { - self waittill( "giveLoadout" ); - - self onGiveLoadout_loop(); - } -} - -/* - When the bot spawns. -*/ -onSpawned() -{ - self endon( "disconnect" ); - - for ( ;; ) - { - self waittill( "spawned_player" ); - - if ( randomint( 100 ) <= self.pers[ "bots" ][ "behavior" ][ "class" ] ) - { - self.bot_change_class = undefined; - } - - self.bot_lock_goal = false; - self.bot_oma_class = undefined; - self.help_time = undefined; - self.bot_was_follow_script_update = undefined; - self.bot_stuck_on_carepackage = undefined; - - if ( getdvarint( "bots_play_obj" ) ) - { - self thread bot_dom_cap_think(); - } - } -} - -/* - When the bot spawned, after the difficulty wait. Start the logic for the bot. -*/ -onBotSpawned() -{ - self endon( "disconnect" ); - level endon( "game_ended" ); - - for ( ;; ) - { - self waittill( "bot_spawned" ); - - self thread start_bot_threads(); - } -} - -/* - Starts all the bot thinking -*/ -start_bot_threads() -{ - self endon( "disconnect" ); - level endon( "game_ended" ); - self endon( "death" ); - - gameflagwait( "prematch_done" ); - - // inventory usage - if ( getdvarint( "bots_play_killstreak" ) ) - { - self thread bot_killstreak_think(); - } - - self thread bot_weapon_think(); - self thread doReloadCancel(); - self thread bot_perk_think(); - - // script targeting - if ( getdvarint( "bots_play_target_other" ) ) - { - self thread bot_target_vehicle(); - self thread bot_equipment_kill_think(); - self thread bot_turret_think(); - } - - // airdrop - if ( getdvarint( "bots_play_take_carepackages" ) ) - { - self thread bot_watch_stuck_on_crate(); - self thread bot_crate_think(); - } - - // awareness - self thread bot_revenge_think(); - self thread bot_uav_think(); - self thread bot_listen_to_steps(); - self thread follow_target(); - - // camp and follow - if ( getdvarint( "bots_play_camp" ) ) - { - self thread bot_think_follow(); - self thread bot_think_camp(); - } - - // nades - if ( getdvarint( "bots_play_nade" ) ) - { - self thread bot_jav_loc_think(); - self thread bot_use_tube_think(); - self thread bot_use_grenade_think(); - self thread bot_use_equipment_think(); - self thread bot_watch_riot_weapons(); - self thread bot_watch_think_mw2(); // bots play mw2 - } - - // obj - if ( getdvarint( "bots_play_obj" ) ) - { - self thread bot_dom_def_think(); - self thread bot_dom_spawn_kill_think(); - - self thread bot_hq(); - - self thread bot_cap(); - - self thread bot_sab(); - - self thread bot_sd_defenders(); - self thread bot_sd_attackers(); - - self thread bot_dem_attackers(); - self thread bot_dem_defenders(); - - self thread bot_gtnw(); - self thread bot_oneflag(); - self thread bot_arena(); - self thread bot_vip(); - } - - self thread bot_think_revive(); -} - -/* - Increments the number of bots approching the obj, decrements when needed - Used for preventing too many bots going to one obj, or unreachable objs -*/ -bot_inc_bots( obj, unreach ) -{ - level endon( "game_ended" ); - self endon( "bot_inc_bots" ); - - if ( !isdefined( obj ) ) - { - return; - } - - if ( !isdefined( obj.bots ) ) - { - obj.bots = 0; - } - - obj.bots++; - - ret = self waittill_any_return( "death", "disconnect", "bad_path", "goal", "new_goal" ); - - if ( isdefined( obj ) && ( ret != "bad_path" || !isdefined( unreach ) ) ) - { - obj.bots--; - } -} - -/* - Watches when the bot is touching the obj and calls 'goal' -*/ -bots_watch_touch_obj( obj ) -{ - self endon ( "death" ); - self endon ( "disconnect" ); - self endon ( "bad_path" ); - self endon ( "goal" ); - self endon ( "new_goal" ); - - for ( ;; ) - { - wait 0.5; - - if ( !isdefined( obj ) ) - { - self notify( "bad_path" ); - return; - } - - if ( self istouching( obj ) ) - { - self notify( "goal" ); - return; - } - } -} - -/* - Watches while the obj is being carried, calls 'goal' when complete -*/ -bot_escort_obj( obj, carrier ) -{ - self endon( "death" ); - self endon( "disconnect" ); - self endon( "goal" ); - self endon( "bad_path" ); - self endon( "new_goal" ); - - for ( ;; ) - { - wait 0.5; - - if ( !isdefined( obj ) ) - { - break; - } - - if ( !isdefined( obj.carrier ) || carrier == obj.carrier ) - { - break; - } - } - - self notify( "goal" ); -} - -/* - Watches while the obj is not being carried, calls 'goal' when complete -*/ -bot_get_obj( obj ) -{ - self endon( "death" ); - self endon( "disconnect" ); - self endon( "goal" ); - self endon( "bad_path" ); - self endon( "new_goal" ); - - for ( ;; ) - { - wait 0.5; - - if ( !isdefined( obj ) ) - { - break; - } - - if ( isdefined( obj.carrier ) ) - { - break; - } - } - - self notify( "goal" ); -} - -/* - bots will defend their site from a planter/defuser -*/ -bot_defend_site( site ) -{ - self endon( "death" ); - self endon( "disconnect" ); - level endon( "game_ended" ); - self endon( "goal" ); - self endon( "bad_path" ); - self endon( "new_goal" ); - - for ( ;; ) - { - wait 0.5; - - if ( !site isInUse() ) - { - break; - } - } - - self notify( "bad_path" ); -} - -/* - Bots will go plant the bomb -*/ -bot_go_plant( plant ) -{ - self endon( "death" ); - self endon( "disconnect" ); - level endon( "game_ended" ); - self endon( "goal" ); - self endon( "bad_path" ); - self endon( "new_goal" ); - - for ( ;; ) - { - wait 1; - - if ( level.bombplanted ) - { - break; - } - - if ( self istouching( plant.trigger ) ) - { - break; - } - } - - if ( level.bombplanted ) - { - self notify( "bad_path" ); - } - else - { - self notify( "goal" ); - } -} - -/* - Bots will go defuse the bomb -*/ -bot_go_defuse( plant ) -{ - self endon( "death" ); - self endon( "disconnect" ); - level endon( "game_ended" ); - self endon( "goal" ); - self endon( "bad_path" ); - self endon( "new_goal" ); - - for ( ;; ) - { - wait 1; - - if ( !level.bombplanted ) - { - break; - } - - if ( self istouching( plant.trigger ) ) - { - break; - } - } - - if ( !level.bombplanted ) - { - self notify( "bad_path" ); - } - else - { - self notify( "goal" ); - } -} - -/* - Waits for the bot to stop moving -*/ -bot_wait_stop_move() -{ - while ( !self isonground() || lengthsquared( self getvelocity() ) > 1 ) - { - wait 0.25; - } -} - -/* - Fires the bots weapon until told to stop -*/ -fire_current_weapon() -{ - self endon( "death" ); - self endon( "disconnect" ); - self endon( "weapon_change" ); - self endon( "stop_firing_weapon" ); - - for ( ;; ) - { - self thread BotPressAttack( 0.05 ); - wait 0.1; - } -} - -/* - Changes to the weap -*/ -changeToWeapon( weap ) -{ - self endon( "disconnect" ); - self endon( "death" ); - level endon( "game_ended" ); - - if ( !self hasweapon( weap ) ) - { - return false; - } - - self switchtoweapon( weap ); - - if ( self getcurrentweapon() == weap ) - { - return true; - } - - self waittill_any_timeout( 5, "weapon_change" ); - - return ( self getcurrentweapon() == weap ); -} - -/* - Bots throw the grenade -*/ -botThrowGrenade( nade, time ) -{ - self endon( "disconnect" ); - self endon( "death" ); - level endon( "game_ended" ); - - if ( !self getammocount( nade ) ) - { - return false; - } - - if ( isSecondaryGrenade( nade ) ) - { - self thread BotPressSmoke( time ); - } - else - { - self thread BotPressFrag( time ); - } - - ret = self waittill_any_timeout( 5, "grenade_fire" ); - - return ( ret == "grenade_fire" ); -} - -/* - Gets the object thats the closest in the array -*/ -bot_array_nearest_curorigin( array ) -{ - result = undefined; - - for ( i = 0; i < array.size; i++ ) - { - if ( !isdefined( result ) || distancesquared( self.origin, array[ i ].curorigin ) < distancesquared( self.origin, result.curorigin ) ) - { - result = array[ i ]; - } - } - - return result; -} - -/* - Returns an weapon thats a rocket with ammo -*/ -getRocketAmmo() -{ - answer = self getLockonAmmo(); - - if ( isdefined( answer ) ) - { - return answer; - } - - if ( self getammocount( "rpg_mp" ) ) - { - answer = "rpg_mp"; - } - - return answer; -} - -/* - Returns a weapon thats lockon with ammo -*/ -getLockonAmmo() -{ - answer = undefined; - - if ( self getammocount( "at4_mp" ) ) - { - answer = "at4_mp"; - } - - if ( self getammocount( "stinger_mp" ) ) - { - answer = "stinger_mp"; - } - - if ( self getammocount( "javelin_mp" ) ) - { - answer = "javelin_mp"; - } - - return answer; -} - -/* - Clears goal when events death -*/ -stop_go_target_on_death( tar ) -{ - self endon( "death" ); - self endon( "disconnect" ); - self endon( "new_goal" ); - self endon( "bad_path" ); - self endon( "goal" ); - - tar waittill_either( "death", "disconnect" ); - - self ClearScriptGoal(); -} - -/* - Goes to the target's location if it had one -*/ -follow_target_loop() -{ - threat = self getThreat(); - - if ( !isplayer( threat ) ) - { - return; - } - - if ( randomint( 100 ) > self.pers[ "bots" ][ "behavior" ][ "follow" ] * 5 ) - { - return; - } - - self BotNotifyBotEvent( "follow_threat", "start", threat ); - - self SetScriptGoal( threat.origin, 64 ); - self thread stop_go_target_on_death( threat ); - - if ( self waittill_any_return( "new_goal", "goal", "bad_path" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - self BotNotifyBotEvent( "follow_threat", "stop", threat ); -} - -/* - Goes to the target's location if it had one -*/ -follow_target() -{ - self endon( "death" ); - self endon( "disconnect" ); - - for ( ;; ) - { - wait 1; - - if ( self HasScriptGoal() || self.bot_lock_goal ) - { - continue; - } - - if ( !self hasThreat() ) - { - continue; - } - - self follow_target_loop(); - } -} - -/* - Bot logic for bot determining to camp. -*/ -bot_think_camp_loop() -{ - campSpot = getWaypointForIndex( random( self waypointsNear( getWaypointsOfType( "camp" ), 1024 ) ) ); - - if ( !isdefined( campSpot ) ) - { - return; - } - - time = randomintrange( 30, 90 ); - - self BotNotifyBotEvent( "camp", "go", campSpot, time ); - - self SetScriptGoal( campSpot.origin, 16 ); - - ret = self waittill_any_return( "new_goal", "goal", "bad_path" ); - - if ( ret != "new_goal" ) - { - self ClearScriptGoal(); - } - - if ( ret != "goal" ) - { - return; - } - - self BotNotifyBotEvent( "camp", "start", campSpot, time ); - - self thread killCampAfterTime( time ); - self CampAtSpot( campSpot.origin, campSpot.origin + anglestoforward( campSpot.angles ) * 2048 ); - - self BotNotifyBotEvent( "camp", "stop", campSpot, time ); -} - -/* - Bot logic for bot determining to camp. -*/ -bot_think_camp() -{ - self endon( "death" ); - self endon( "disconnect" ); - - for ( ;; ) - { - wait randomintrange( 4, 7 ); - - if ( self HasScriptGoal() || self.bot_lock_goal || self HasScriptAimPos() ) - { - continue; - } - - if ( randomint( 100 ) > self.pers[ "bots" ][ "behavior" ][ "camp" ] ) - { - continue; - } - - self bot_think_camp_loop(); - } -} - -/* - Kills the camping thread when time -*/ -killCampAfterTime( time ) -{ - self endon( "death" ); - self endon( "disconnect" ); - self endon( "kill_camp_bot" ); - - timeleft = maps\mp\gametypes\_gamelogic::gettimeremaining() / 1000; - - while ( time > 0 && timeleft >= 60 ) - { - wait 1; - timeleft = maps\mp\gametypes\_gamelogic::gettimeremaining() / 1000; - time--; - } - - wait 0.05; - - self ClearScriptGoal(); - self ClearScriptAimPos(); - - self notify( "kill_camp_bot" ); -} - -/* - Kills the camping thread when ent gone -*/ -killCampAfterEntGone( ent ) -{ - self endon( "death" ); - self endon( "disconnect" ); - self endon( "kill_camp_bot" ); - - for ( ;; ) - { - wait 0.05; - - if ( !isdefined( ent ) ) - { - break; - } - } - - self ClearScriptGoal(); - self ClearScriptAimPos(); - - self notify( "kill_camp_bot" ); -} - -/* - Camps at the spot -*/ -CampAtSpot( origin, anglePos ) -{ - self endon( "kill_camp_bot" ); - - self SetScriptGoal( origin, 64 ); - - if ( isdefined( anglePos ) ) - { - self SetScriptAimPos( anglePos ); - } - - self waittill( "new_goal" ); - self ClearScriptAimPos(); - - self notify( "kill_camp_bot" ); -} - -/* - Bot logic for bot determining to follow another player. -*/ -bot_think_follow_loop() -{ - follows = []; - distSq = self.pers[ "bots" ][ "skill" ][ "help_dist" ] * self.pers[ "bots" ][ "skill" ][ "help_dist" ]; - - for ( i = level.players.size - 1; i >= 0; i-- ) - { - player = level.players[ i ]; - - if ( player == self ) - { - continue; - } - - if ( !isreallyalive( player ) ) - { - continue; - } - - if ( player.team != self.team ) - { - continue; - } - - if ( distancesquared( player.origin, self.origin ) > distSq ) - { - continue; - } - - follows[ follows.size ] = player; - } - - toFollow = random( follows ); - - if ( !isdefined( toFollow ) ) - { - return; - } - - time = randomintrange( 10, 20 ); - - self BotNotifyBotEvent( "follow", "start", toFollow, time ); - - self thread killFollowAfterTime( time ); - self followPlayer( toFollow ); - - self BotNotifyBotEvent( "follow", "stop", toFollow, time ); -} - -/* - Bot logic for bot determining to follow another player. -*/ -bot_think_follow() -{ - self endon( "death" ); - self endon( "disconnect" ); - - for ( ;; ) - { - wait randomintrange( 3, 5 ); - - if ( self HasScriptGoal() || self.bot_lock_goal || self HasScriptAimPos() ) - { - continue; - } - - if ( randomint( 100 ) > self.pers[ "bots" ][ "behavior" ][ "follow" ] ) - { - continue; - } - - if ( !level.teambased ) - { - continue; - } - - self bot_think_follow_loop(); - } -} - -/* - Kills follow when new goal -*/ -watchForFollowNewGoal() -{ - self endon( "death" ); - self endon( "disconnect" ); - self endon( "kill_follow_bot" ); - - for ( ;; ) - { - self waittill( "new_goal" ); - - if ( !isdefined( self.bot_was_follow_script_update ) ) - { - break; - } - } - - self ClearScriptAimPos(); - self notify( "kill_follow_bot" ); -} - -/* - Kills follow when time -*/ -killFollowAfterTime( time ) -{ - self endon( "death" ); - self endon( "disconnect" ); - self endon( "kill_follow_bot" ); - - wait time; - - self ClearScriptGoal(); - self ClearScriptAimPos(); - self notify( "kill_follow_bot" ); -} - -/* - Determine bot to follow a player -*/ -followPlayer( who ) -{ - self endon( "kill_follow_bot" ); - - self thread watchForFollowNewGoal(); - - for ( ;; ) - { - wait 0.05; - - if ( !isdefined( who ) || !isreallyalive( who ) ) - { - break; - } - - self SetScriptAimPos( who.origin + ( 0, 0, 42 ) ); - myGoal = self GetScriptGoal(); - - if ( isdefined( myGoal ) && distancesquared( myGoal, who.origin ) < 64 * 64 ) - { - continue; - } - - self.bot_was_follow_script_update = true; - self SetScriptGoal( who.origin, 32 ); - waittillframeend; - self.bot_was_follow_script_update = undefined; - - self waittill_either( "goal", "bad_path" ); - } - - self ClearScriptGoal(); - self ClearScriptAimPos(); - - self notify( "kill_follow_bot" ); -} - -/* - Bots thinking of using one man army and blast shield -*/ -bot_perk_think_loop() -{ - for ( ; self _hasperk( "specialty_blastshield" ); ) - { - if ( !self _hasperk( "_specialty_blastshield" ) ) - { - if ( randomint( 100 ) < 65 ) - { - break; - } - - self _setperk( "_specialty_blastshield" ); - } - else - { - if ( randomint( 100 ) < 90 ) - { - break; - } - - self _unsetperk( "_specialty_blastshield" ); - } - - break; - } - - for ( ; self _hasperk( "specialty_onemanarmy" ) && self hasweapon( "onemanarmy_mp" ); ) - { - if ( self hasThreat() || self HasBotJavelinLocation() ) - { - break; - } - - if ( self inLastStand() && !self inFinalStand() ) - { - break; - } - - anyWeapout = false; - weaponsList = self getweaponslistall(); - - for ( i = 0; i < weaponsList.size; i++ ) - { - weap = weaponsList[ i ]; - - if ( self getammocount( weap ) || weap == "onemanarmy_mp" ) - { - continue; - } - - anyWeapout = true; - } - - if ( ( !anyWeapout && randomint( 100 ) < 90 ) || randomint( 100 ) < 10 ) - { - break; - } - - class = self chooseRandomClass(); - - self.bot_oma_class = class; - - if ( !self changeToWeapon( "onemanarmy_mp" ) ) - { - self.bot_oma_class = undefined; - break; - } - - self BotFreezeControls( true ); - wait 1; - self BotFreezeControls( false ); - - self notify ( "menuresponse", game[ "menu_onemanarmy" ], self.bot_oma_class ); - - self waittill_any_timeout ( 10, "changed_kit" ); - break; - } -} - -/* - Bots thinking of using one man army and blast shield -*/ -bot_perk_think() -{ - self endon( "disconnect" ); - self endon( "death" ); - level endon( "game_ended" ); - - for ( ;; ) - { - wait randomintrange( 5, 7 ); - - if ( self isusingremote() ) - { - continue; - } - - if ( self BotIsFrozen() ) - { - continue; - } - - if ( self isDefusing() || self isPlanting() ) - { - continue; - } - - self bot_perk_think_loop(); - } -} - -/* - Bots thinking of using a noobtube -*/ -bot_use_tube_think_loop( data ) -{ - if ( data.dofastcontinue ) - { - data.dofastcontinue = false; - } - else - { - wait randomintrange( 3, 7 ); - - chance = self.pers[ "bots" ][ "behavior" ][ "nade" ] / 2; - - if ( chance > 20 ) - { - chance = 20; - } - - if ( randomint( 100 ) > chance ) - { - return; - } - } - - tube = self getValidTube(); - - if ( !isdefined( tube ) ) - { - return; - } - - if ( self hasThreat() || self HasBotJavelinLocation() || self HasScriptAimPos() ) - { - return; - } - - if ( self BotIsFrozen() ) - { - return; - } - - if ( self IsBotFragging() || self IsBotSmoking() ) - { - return; - } - - if ( self isDefusing() || self isPlanting() ) - { - return; - } - - if ( self isusingremote() ) - { - return; - } - - if ( self inLastStand() && !self inFinalStand() ) - { - return; - } - - loc = undefined; - - if ( !self nearAnyOfWaypoints( 128, getWaypointsOfType( "tube" ) ) ) - { - tubeWp = getWaypointForIndex( random( self waypointsNear( getWaypointsOfType( "tube" ), 1024 ) ) ); - - myEye = self geteye(); - - if ( !isdefined( tubeWp ) || self HasScriptGoal() || self.bot_lock_goal ) - { - traceForward = bullettrace( myEye, myEye + anglestoforward( self getplayerangles() ) * 900 * 5, false, self ); - - loc = traceForward[ "position" ]; - dist = distancesquared( self.origin, loc ); - - if ( dist < level.bots_mingrenadedistance || dist > level.bots_maxgrenadedistance * 5 ) - { - return; - } - - if ( !bullettracepassed( self.origin + ( 0, 0, 5 ), self.origin + ( 0, 0, 2048 ), false, self ) ) - { - return; - } - - if ( !bullettracepassed( loc + ( 0, 0, 5 ), loc + ( 0, 0, 2048 ), false, self ) ) - { - return; - } - - loc += ( 0, 0, dist / 16000 ); - } - else - { - self BotNotifyBotEvent( "tube", "go", tubeWp, tube ); - - self SetScriptGoal( tubeWp.origin, 16 ); - - ret = self waittill_any_return( "new_goal", "goal", "bad_path" ); - - if ( ret != "new_goal" ) - { - self ClearScriptGoal(); - } - - if ( ret != "goal" ) - { - return; - } - - data.dofastcontinue = true; - return; - } - } - else - { - tubeWp = getWaypointForIndex( self getNearestWaypointOfWaypoints( getWaypointsOfType( "tube" ) ) ); - loc = tubeWp.origin + anglestoforward( tubeWp.angles ) * 2048; - } - - if ( !isdefined( loc ) ) - { - return; - } - - self BotNotifyBotEvent( "tube", "start", loc, tube ); - - self SetScriptAimPos( loc ); - self BotStopMoving( true ); - wait 1; - - if ( self changeToWeapon( tube ) ) - { - self thread fire_current_weapon(); - self waittill_any_timeout( 5, "missile_fire", "weapon_change" ); - self notify( "stop_firing_weapon" ); - } - - self ClearScriptAimPos(); - self BotStopMoving( false ); -} - -/* - Bots thinking of using a noobtube -*/ -bot_use_tube_think() -{ - self endon( "disconnect" ); - self endon( "death" ); - level endon( "game_ended" ); - - data = spawnstruct(); - data.dofastcontinue = false; - - for ( ;; ) - { - self bot_use_tube_think_loop( data ); - } -} - -/* - Bots thinking of using claymores and TIs -*/ -bot_use_equipment_think_loop( data ) -{ - if ( data.dofastcontinue ) - { - data.dofastcontinue = false; - } - else - { - wait randomintrange( 2, 4 ); - - chance = self.pers[ "bots" ][ "behavior" ][ "nade" ] / 2; - - if ( chance > 20 ) - { - chance = 20; - } - - if ( randomint( 100 ) > chance ) - { - return; - } - } - - nade = undefined; - - if ( self getammocount( "claymore_mp" ) ) - { - nade = "claymore_mp"; - } - - if ( self getammocount( "flare_mp" ) ) - { - nade = "flare_mp"; - } - - if ( self getammocount( "c4_mp" ) ) - { - nade = "c4_mp"; - } - - if ( !isdefined( nade ) ) - { - return; - } - - if ( self hasThreat() || self HasBotJavelinLocation() || self HasScriptAimPos() ) - { - return; - } - - if ( self BotIsFrozen() ) - { - return; - } - - if ( self IsBotFragging() || self IsBotSmoking() ) - { - return; - } - - if ( self isDefusing() || self isPlanting() ) - { - return; - } - - if ( self isusingremote() ) - { - return; - } - - if ( self inLastStand() && !self _hasperk( "specialty_laststandoffhand" ) && !self inFinalStand() ) - { - return; - } - - loc = undefined; - - if ( !self nearAnyOfWaypoints( 128, getWaypointsOfType( "claymore" ) ) ) - { - clayWp = getWaypointForIndex( random( self waypointsNear( getWaypointsOfType( "claymore" ), 1024 ) ) ); - - if ( !isdefined( clayWp ) || self HasScriptGoal() || self.bot_lock_goal ) - { - myEye = self geteye(); - loc = myEye + anglestoforward( self getplayerangles() ) * 256; - - if ( !bullettracepassed( myEye, loc, false, self ) ) - { - return; - } - } - else - { - self BotNotifyBotEvent( "equ", "go", clayWp, nade ); - - self SetScriptGoal( clayWp.origin, 16 ); - - ret = self waittill_any_return( "new_goal", "goal", "bad_path" ); - - if ( ret != "new_goal" ) - { - self ClearScriptGoal(); - } - - if ( ret != "goal" ) - { - return; - } - - data.dofastcontinue = true; - return; - } - } - else - { - clayWp = getWaypointForIndex( self getNearestWaypointOfWaypoints( getWaypointsOfType( "claymore" ) ) ); - loc = clayWp.origin + anglestoforward( clayWp.angles ) * 2048; - } - - if ( !isdefined( loc ) ) - { - return; - } - - self BotNotifyBotEvent( "equ", "start", loc, nade ); - - self SetScriptAimPos( loc ); - self BotStopMoving( true ); - wait 1; - - self botThrowGrenade( nade, 0.05 ); - - self ClearScriptAimPos(); - self BotStopMoving( false ); -} - -/* - Bots thinking of using claymores and TIs -*/ -bot_use_equipment_think() -{ - self endon( "disconnect" ); - self endon( "death" ); - level endon( "game_ended" ); - - data = spawnstruct(); - data.dofastcontinue = false; - - for ( ;; ) - { - self bot_use_equipment_think_loop( data ); - } -} - -/* - Bots thinking of using grenades -*/ -bot_use_grenade_think_loop( data ) -{ - if ( data.dofastcontinue ) - { - data.dofastcontinue = false; - } - else - { - wait randomintrange( 4, 7 ); - - chance = self.pers[ "bots" ][ "behavior" ][ "nade" ] / 2; - - if ( chance > 20 ) - { - chance = 20; - } - - if ( randomint( 100 ) > chance ) - { - return; - } - } - - nade = self getValidGrenade(); - - if ( !isdefined( nade ) ) - { - return; - } - - if ( self hasThreat() || self HasBotJavelinLocation() || self HasScriptAimPos() ) - { - return; - } - - if ( self BotIsFrozen() ) - { - return; - } - - if ( self IsBotFragging() || self IsBotSmoking() ) - { - return; - } - - if ( self isDefusing() || self isPlanting() ) - { - return; - } - - if ( self isusingremote() ) - { - return; - } - - if ( self inLastStand() && !self _hasperk( "specialty_laststandoffhand" ) && !self inFinalStand() ) - { - return; - } - - loc = undefined; - - if ( !self nearAnyOfWaypoints( 128, getWaypointsOfType( "grenade" ) ) ) - { - nadeWp = getWaypointForIndex( random( self waypointsNear( getWaypointsOfType( "grenade" ), 1024 ) ) ); - - myEye = self geteye(); - - if ( !isdefined( nadeWp ) || self HasScriptGoal() || self.bot_lock_goal ) - { - traceForward = bullettrace( myEye, myEye + anglestoforward( self getplayerangles() ) * 900, false, self ); - - loc = traceForward[ "position" ]; - dist = distancesquared( self.origin, loc ); - - if ( dist < level.bots_mingrenadedistance || dist > level.bots_maxgrenadedistance ) - { - return; - } - - if ( !bullettracepassed( self.origin + ( 0, 0, 5 ), self.origin + ( 0, 0, 2048 ), false, self ) ) - { - return; - } - - if ( !bullettracepassed( loc + ( 0, 0, 5 ), loc + ( 0, 0, 2048 ), false, self ) ) - { - return; - } - - loc += ( 0, 0, dist / 3000 ); - } - else - { - self BotNotifyBotEvent( "nade", "go", nadeWp, nade ); - - self SetScriptGoal( nadeWp.origin, 16 ); - - ret = self waittill_any_return( "new_goal", "goal", "bad_path" ); - - if ( ret != "new_goal" ) - { - self ClearScriptGoal(); - } - - if ( ret != "goal" ) - { - return; - } - - data.dofastcontinue = true; - return; - } - } - else - { - nadeWp = getWaypointForIndex( self getNearestWaypointOfWaypoints( getWaypointsOfType( "grenade" ) ) ); - loc = nadeWp.origin + anglestoforward( nadeWp.angles ) * 2048; - } - - if ( !isdefined( loc ) ) - { - return; - } - - self BotNotifyBotEvent( "nade", "start", loc, nade ); - - self SetScriptAimPos( loc ); - self BotStopMoving( true ); - wait 1; - - time = 0.5; - - if ( nade == "frag_grenade_mp" ) - { - time = 2; - } - - self botThrowGrenade( nade, time ); - - self ClearScriptAimPos(); - self BotStopMoving( false ); -} - -/* - Bots thinking of using grenades -*/ -bot_use_grenade_think() -{ - self endon( "disconnect" ); - self endon( "death" ); - level endon( "game_ended" ); - - data = spawnstruct(); - data.dofastcontinue = false; - - for ( ;; ) - { - self bot_use_grenade_think_loop( data ); - } -} - -/* - Bots play mw2 -*/ -bot_watch_think_mw2_loop() -{ - tube = self getValidTube(); - - if ( !isdefined( tube ) ) - { - if ( self getammocount( "at4_mp" ) ) - { - tube = "at4_mp"; - } - else if ( self getammocount( "rpg_mp" ) ) - { - tube = "rpg_mp"; - } - else - { - return; - } - } - - if ( self getcurrentweapon() == tube ) - { - return; - } - - chance = self.pers[ "bots" ][ "behavior" ][ "nade" ]; - - if ( randomint( 100 ) > chance ) - { - return; - } - - self thread changeToWeapon( tube ); -} - -/* - Bots play mw2 -*/ -bot_watch_think_mw2() -{ - self endon( "disconnect" ); - self endon( "death" ); - level endon( "game_ended" ); - - for ( ;; ) - { - wait randomintrange( 1, 4 ); - - if ( self BotIsFrozen() ) - { - continue; - } - - if ( self isDefusing() || self isPlanting() ) - { - continue; - } - - if ( self isusingremote() ) - { - continue; - } - - if ( self inLastStand() && !self inFinalStand() ) - { - continue; - } - - if ( self hasThreat() ) - { - continue; - } - - self bot_watch_think_mw2_loop(); - } -} - -/* - Bots will use gremades/wweapons while having a target while using a shield -*/ -bot_watch_riot_weapons_loop() -{ - threat = self getThreat(); - dist = distancesquared( threat.origin, self.origin ); - curWeap = self getcurrentweapon(); - - if ( randomint( 2 ) ) - { - nade = self getValidGrenade(); - - if ( !isdefined( nade ) ) - { - return; - } - - if ( dist <= level.bots_mingrenadedistance || dist >= level.bots_maxgrenadedistance ) - { - return; - } - - if ( randomint( 100 ) > self.pers[ "bots" ][ "behavior" ][ "nade" ] ) - { - return; - } - - self botThrowGrenade( nade ); - } - else - { - if ( randomint( 100 ) > self.pers[ "bots" ][ "behavior" ][ "switch" ] * 10 ) - { - return; - } - - weaponslist = self getweaponslistall(); - weap = ""; - - while ( weaponslist.size ) - { - weapon = weaponslist[ randomint( weaponslist.size ) ]; - weaponslist = array_remove( weaponslist, weapon ); - - if ( !self getammocount( weapon ) ) - { - continue; - } - - if ( !isWeaponPrimary( weapon ) ) - { - continue; - } - - if ( curWeap == weapon || weapon == "none" || weapon == "" || weapon == "javelin_mp" || weapon == "stinger_mp" || weapon == "onemanarmy_mp" ) - { - continue; - } - - weap = weapon; - break; - } - - if ( weap == "" ) - { - return; - } - - self thread changeToWeapon( weap ); - } -} - -/* - Bots will use gremades/wweapons while having a target while using a shield -*/ -bot_watch_riot_weapons() -{ - self endon( "disconnect" ); - self endon( "death" ); - level endon( "game_ended" ); - - for ( ;; ) - { - wait randomintrange( 2, 4 ); - - if ( self BotIsFrozen() ) - { - continue; - } - - if ( self isDefusing() || self isPlanting() ) - { - continue; - } - - if ( self isusingremote() ) - { - continue; - } - - if ( self inLastStand() && !self inFinalStand() ) - { - continue; - } - - if ( !self hasThreat() ) - { - continue; - } - - if ( !self.hasriotshieldequipped ) - { - continue; - } - - self bot_watch_riot_weapons_loop(); - } -} - -/* - BOts thinking of using javelins -*/ -bot_jav_loc_think_loop( data ) -{ - if ( data.dofastcontinue ) - { - data.dofastcontinue = false; - } - else - { - wait randomintrange( 2, 4 ); - - chance = self.pers[ "bots" ][ "behavior" ][ "nade" ] / 2; - - if ( chance > 20 ) - { - chance = 20; - } - - if ( randomint( 100 ) > chance && self getcurrentweapon() != "javelin_mp" ) - { - return; - } - } - - if ( !self getammocount( "javelin_mp" ) ) - { - return; - } - - if ( self hasThreat() || self HasBotJavelinLocation() || self HasScriptAimPos() ) - { - return; - } - - if ( self BotIsFrozen() ) - { - return; - } - - if ( self isDefusing() || self isPlanting() ) - { - return; - } - - if ( self isusingremote() ) - { - return; - } - - if ( self inLastStand() && !self inFinalStand() ) - { - return; - } - - if ( self isemped() ) - { - return; - } - - loc = undefined; - - if ( !self nearAnyOfWaypoints( 128, getWaypointsOfType( "javelin" ) ) ) - { - javWp = getWaypointForIndex( random( self waypointsNear( getWaypointsOfType( "javelin" ), 1024 ) ) ); - - if ( !isdefined( javWp ) || self HasScriptGoal() || self.bot_lock_goal ) - { - traceForward = self maps\mp\_javelin::eyetraceforward(); - - if ( !isdefined( traceForward ) ) - { - return; - } - - loc = traceForward[ 0 ]; - - if ( self maps\mp\_javelin::targetpointtooclose( loc ) ) - { - return; - } - - if ( !bullettracepassed( self.origin + ( 0, 0, 5 ), self.origin + ( 0, 0, 2048 ), false, self ) ) - { - return; - } - - if ( !bullettracepassed( loc + ( 0, 0, 5 ), loc + ( 0, 0, 2048 ), false, self ) ) - { - return; - } - } - else - { - self BotNotifyBotEvent( "jav", "go", javWp ); - - self SetScriptGoal( javWp.origin, 16 ); - - ret = self waittill_any_return( "new_goal", "goal", "bad_path" ); - - if ( ret != "new_goal" ) - { - self ClearScriptGoal(); - } - - if ( ret != "goal" ) - { - return; - } - - data.dofastcontinue = true; - return; - } - } - else - { - javWp = getWaypointForIndex( self getNearestWaypointOfWaypoints( getWaypointsOfType( "javelin" ) ) ); - loc = javWp.jav_point; - } - - if ( !isdefined( loc ) ) - { - return; - } - - self BotNotifyBotEvent( "jav", "start", loc ); - - self SetBotJavelinLocation( loc ); - - if ( self changeToWeapon( "javelin_mp" ) ) - { - self waittill_any_timeout( 10, "missile_fire", "weapon_change" ); - } - - self ClearBotJavelinLocation(); -} - -/* - BOts thinking of using javelins -*/ -bot_jav_loc_think() -{ - self endon( "disconnect" ); - self endon( "death" ); - level endon( "game_ended" ); - - data = spawnstruct(); - data.dofastcontinue = false; - - for ( ;; ) - { - self bot_jav_loc_think_loop( data ); - } -} - -/* - Bots thinking of targeting equipment, c4, claymores and TIs -*/ -bot_equipment_kill_think_loop() -{ - myTeam = self.pers[ "team" ]; - hasSitrep = self _hasperk( "specialty_detectexplosive" ); - grenades = getentarray( "grenade", "classname" ); - myEye = self geteye(); - myAngles = self getplayerangles(); - dist = 512 * 512; - target = undefined; - - for ( i = 0; i < grenades.size; i++ ) - { - item = grenades[ i ]; - - if ( !isdefined( item ) ) - { - continue; - } - - if ( !isdefined( item.name ) ) - { - continue; - } - - if ( isdefined( item.owner ) && ( ( level.teambased && item.owner.team == self.team ) || item.owner == self ) ) - { - continue; - } - - if ( item.name != "c4_mp" && item.name != "claymore_mp" ) - { - continue; - } - - if ( !hasSitrep && !bullettracepassed( myEye, item.origin, false, item ) ) - { - continue; - } - - if ( getConeDot( item.origin, self.origin, myAngles ) < 0.6 ) - { - continue; - } - - if ( distancesquared( item.origin, self.origin ) < dist ) - { - target = item; - break; - } - } - - grenades = undefined; - - if ( !isdefined( target ) ) - { - for ( i = 0; i < level.players.size; i++ ) - { - player = level.players[ i ]; - - if ( player == self ) - { - continue; - } - - if ( !isdefined( player.team ) ) - { - continue; - } - - if ( level.teambased && player.team == myTeam ) - { - continue; - } - - ti = player.setspawnpoint; - - if ( !isdefined( ti ) ) - { - continue; - } - - if ( !isdefined( ti.bots ) ) - { - ti.bots = 0; - } - - if ( ti.bots >= 2 ) - { - continue; - } - - if ( !hasSitrep && !bullettracepassed( myEye, ti.origin, false, ti ) ) - { - continue; - } - - if ( getConeDot( ti.origin, self.origin, myAngles ) < 0.6 ) - { - continue; - } - - if ( distancesquared( ti.origin, self.origin ) < dist ) - { - target = ti; - break; - } - } - } - - if ( !isdefined( target ) ) - { - return; - } - - if ( isdefined( target.enemytrigger ) && !self HasScriptGoal() && !self.bot_lock_goal ) - { - self BotNotifyBotEvent( "attack_equ", "go_ti", target ); - - self SetScriptGoal( target.origin, 64 ); - self thread bot_inc_bots( target, true ); - self thread bots_watch_touch_obj( target ); - - path = self waittill_any_return( "bad_path", "goal", "new_goal" ); - - if ( path != "new_goal" ) - { - self ClearScriptGoal(); - } - - if ( path != "goal" || !isdefined( target ) ) - { - return; - } - - if ( randomint( 100 ) < self.pers[ "bots" ][ "behavior" ][ "camp" ] * 8 ) - { - self BotNotifyBotEvent( "attack_equ", "camp_ti", target ); - - self thread killCampAfterTime( randomintrange( 10, 20 ) ); - self thread killCampAfterEntGone( target ); - self CampAtSpot( target.origin, target.origin + ( 0, 0, 42 ) ); - } - - if ( isdefined( target ) ) - { - self BotNotifyBotEvent( "attack_equ", "trigger_ti", target ); - self thread BotPressUse(); - } - - return; - } - - self BotNotifyBotEvent( "attack_equ", "start", target ); - - self SetScriptEnemy( target ); - self bot_equipment_attack( target ); - self ClearScriptEnemy(); - - self BotNotifyBotEvent( "attack_equ", "stop", target ); -} - -/* - Bots thinking of targeting equipment, c4, claymores and TIs -*/ -bot_equipment_kill_think() -{ - self endon( "death" ); - self endon( "disconnect" ); - level endon ( "game_ended" ); - - for ( ;; ) - { - wait( randomintrange( 1, 3 ) ); - - if ( self HasScriptEnemy() ) - { - continue; - } - - if ( self.pers[ "bots" ][ "skill" ][ "base" ] <= 1 ) - { - continue; - } - - self bot_equipment_kill_think_loop(); - } -} - -/* - Bots target the equipment for a time then stop -*/ -bot_equipment_attack( equ ) -{ - wait_time = randomintrange( 7, 10 ); - - for ( i = 0; i < wait_time; i++ ) - { - wait( 1 ); - - if ( !isdefined( equ ) ) - { - return; - } - } -} - -/* - Bots will listen to foot steps and target nearby targets -*/ -bot_listen_to_steps_loop() -{ - dist = level.bots_listendist; - - if ( self _hasperk( "specialty_selectivehearing" ) ) - { - dist *= 1.4; - } - - dist *= dist; - - heard = undefined; - - for ( i = level.players.size - 1 ; i >= 0; i-- ) - { - player = level.players[ i ]; - - if ( player == self ) - { - continue; - } - - if ( level.teambased && self.team == player.team ) - { - continue; - } - - if ( player.sessionstate != "playing" ) - { - continue; - } - - if ( !isreallyalive( player ) ) - { - continue; - } - - if ( lengthsquared( player getvelocity() ) < 20000 ) - { - continue; - } - - if ( distancesquared( player.origin, self.origin ) > dist ) - { - continue; - } - - if ( player _hasperk( "specialty_quieter" ) ) - { - continue; - } - - heard = player; - break; - } - - hasHeartbeat = ( issubstr( self getcurrentweapon(), "_heartbeat_" ) && !self isemped() ); - heartbeatDist = 350 * 350; - - if ( !isdefined( heard ) && hasHeartbeat ) - { - for ( i = level.players.size - 1 ; i >= 0; i-- ) - { - player = level.players[ i ]; - - if ( player == self ) - { - continue; - } - - if ( level.teambased && self.team == player.team ) - { - continue; - } - - if ( player.sessionstate != "playing" ) - { - continue; - } - - if ( !isreallyalive( player ) ) - { - continue; - } - - if ( player _hasperk( "specialty_heartbreaker" ) ) - { - continue; - } - - if ( distancesquared( player.origin, self.origin ) > heartbeatDist ) - { - continue; - } - - if ( getConeDot( player.origin, self.origin, self getplayerangles() ) < 0.6 ) - { - continue; - } - - heard = player; - break; - } - } - - if ( !isdefined( heard ) ) - { - return; - } - - self BotNotifyBotEvent( "heard_target", "start", heard ); - - if ( bullettracepassed( self geteye(), heard gettagorigin( "j_spineupper" ), false, heard ) ) - { - self setAttacker( heard ); - return; - } - - if ( self HasScriptGoal() || self.bot_lock_goal ) - { - return; - } - - self SetScriptGoal( heard.origin, 64 ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - self BotNotifyBotEvent( "heard_target", "stop", heard ); -} - -/* - Bots will listen to foot steps and target nearby targets -*/ -bot_listen_to_steps() -{ - self endon( "disconnect" ); - self endon( "death" ); - - for ( ;; ) - { - wait 1; - - if ( self.pers[ "bots" ][ "skill" ][ "base" ] < 3 ) - { - continue; - } - - self bot_listen_to_steps_loop(); - } -} - -/* - Bots will look at the uav and target targets -*/ -bot_uav_think_loop() -{ - hasRadar = ( ( level.teambased && level.activeuavs[ self.team ] ) || ( !level.teambased && level.activeuavs[ self.guid ] ) ); - - if ( level.hardcoremode && !hasRadar ) - { - return; - } - - dist = self.pers[ "bots" ][ "skill" ][ "help_dist" ]; - dist *= dist * 8; - - for ( i = level.players.size - 1; i >= 0; i-- ) - { - player = level.players[ i ]; - - if ( player == self ) - { - continue; - } - - if ( !isdefined( player.team ) ) - { - continue; - } - - if ( player.sessionstate != "playing" ) - { - continue; - } - - if ( level.teambased && player.team == self.team ) - { - continue; - } - - if ( !isreallyalive( player ) ) - { - continue; - } - - distFromPlayer = distancesquared( self.origin, player.origin ); - - if ( distFromPlayer > dist ) - { - continue; - } - - if ( ( !issubstr( player getcurrentweapon(), "_silencer_" ) && player.bots_firing ) || ( hasRadar && !player _hasperk( "specialty_coldblooded" ) ) ) - { - self BotNotifyBotEvent( "uav_target", "start", player ); - - distSq = self.pers[ "bots" ][ "skill" ][ "help_dist" ] * self.pers[ "bots" ][ "skill" ][ "help_dist" ]; - - if ( distFromPlayer < distSq && bullettracepassed( self geteye(), player gettagorigin( "j_spineupper" ), false, player ) ) - { - self setAttacker( player ); - } - - if ( !self HasScriptGoal() && !self.bot_lock_goal ) - { - self SetScriptGoal( player.origin, 128 ); - self thread stop_go_target_on_death( player ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - self BotNotifyBotEvent( "uav_target", "stop", player ); - } - - break; - } - } -} - -/* - Bots will look at the uav and target targets -*/ -bot_uav_think() -{ - self endon( "death" ); - self endon( "disconnect" ); - - for ( ;; ) - { - wait 0.75; - - if ( self.pers[ "bots" ][ "skill" ][ "base" ] <= 1 || self isusingremote() ) - { - continue; - } - - if ( self isemped() || self.bot_isscrambled ) - { - continue; - } - - if ( self _hasperk( "_specialty_blastshield" ) ) - { - continue; - } - - if ( ( level.teambased && level.activecounteruavs[ level.otherteam[ self.team ] ] ) || ( !level.teambased && self.isradarblocked ) ) - { - continue; - } - - self bot_uav_think_loop(); - } -} - -/* - bots will go to their target's kill location -*/ -bot_revenge_think() -{ - self endon( "death" ); - self endon( "disconnect" ); - - if ( self.pers[ "bots" ][ "skill" ][ "base" ] <= 1 ) - { - return; - } - - if ( isdefined( self.lastkiller ) && isreallyalive( self.lastkiller ) ) - { - if ( bullettracepassed( self geteye(), self.lastkiller gettagorigin( "j_spineupper" ), false, self.lastkiller ) ) - { - self setAttacker( self.lastkiller ); - } - } - - if ( !isdefined( self.killerlocation ) ) - { - return; - } - - loc = self.killerlocation; - - for ( ;; ) - { - wait( randomintrange( 1, 5 ) ); - - if ( self HasScriptGoal() || self.bot_lock_goal ) - { - return; - } - - if ( randomint( 100 ) < 75 ) - { - return; - } - - self BotNotifyBotEvent( "revenge", "start", loc, self.lastkiller ); - - self SetScriptGoal( loc, 64 ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - self BotNotifyBotEvent( "revenge", "stop", loc, self.lastkiller ); - } -} - -/* - Watches the target's health, calls 'bad_path' -*/ -turret_death_monitor( turret ) -{ - self endon ( "death" ); - self endon ( "disconnect" ); - self endon ( "bad_path" ); - self endon ( "goal" ); - self endon ( "new_goal" ); - - for ( ;; ) - { - wait 0.5; - - if ( !isdefined( turret ) ) - { - break; - } - - if ( turret.health <= 20000 ) - { - break; - } - - if ( isdefined( turret.carriedby ) ) - { - break; - } - } - - self notify( "bad_path" ); -} - -/* - Bots will target the turret for a time -*/ -bot_turret_attack( enemy ) -{ - wait_time = randomintrange( 7, 10 ); - - for ( i = 0; i < wait_time; i++ ) - { - wait( 1 ); - - if ( !isdefined( enemy ) ) - { - return; - } - - if ( enemy.health <= 20000 ) - { - return; - } - - if ( isdefined( enemy.carriedby ) ) - { - return; - } - - // if ( !bullettracepassed( self geteye(), enemy.origin + ( 0, 0, 15 ), false, enemy ) ) - // return; - } -} - -/* - Bots will think when to target a turret -*/ -bot_turret_think_loop() -{ - myTeam = self.pers[ "team" ]; - turretsKeys = getarraykeys( level.turrets ); - - if ( turretsKeys.size == 0 ) - { - wait( randomintrange( 3, 5 ) ); - return; - } - - if ( self.pers[ "bots" ][ "skill" ][ "base" ] <= 1 ) - { - return; - } - - if ( self HasScriptEnemy() || self isusingremote() ) - { - return; - } - - myEye = self geteye(); - turret = undefined; - - for ( i = turretsKeys.size - 1; i >= 0; i-- ) - { - tempTurret = level.turrets[ turretsKeys[ i ] ]; - - if ( !isdefined( tempTurret ) ) - { - continue; - } - - if ( tempTurret.health <= 20000 ) - { - continue; - } - - if ( isdefined( tempTurret.carriedby ) ) - { - continue; - } - - if ( isdefined( tempTurret.owner ) && tempTurret.owner == self ) - { - continue; - } - - if ( level.teambased && tempTurret.team == myTeam ) - { - continue; - } - - if ( !bullettracepassed( myEye, tempTurret.origin + ( 0, 0, 15 ), false, tempTurret ) ) - { - continue; - } - - turret = tempTurret; - } - - turretsKeys = undefined; - - if ( !isdefined( turret ) ) - { - return; - } - - forward = anglestoforward( turret.angles ); - forward = vectornormalize( forward ); - - delta = self.origin - turret.origin; - delta = vectornormalize( delta ); - - dot = vectordot( forward, delta ); - - facing = true; - - if ( dot < 0.342 ) // cos 70 degrees - { - facing = false; - } - - if ( turret isStunned() ) - { - facing = false; - } - - if ( self _hasperk( "specialty_coldblooded" ) ) - { - facing = false; - } - - if ( facing && !bullettracepassed( myEye, turret.origin + ( 0, 0, 15 ), false, turret ) ) - { - return; - } - - if ( !isdefined( turret.bots ) ) - { - turret.bots = 0; - } - - if ( turret.bots >= 2 ) - { - return; - } - - if ( !facing && !self HasScriptGoal() && !self.bot_lock_goal ) - { - self BotNotifyBotEvent( "turret_attack", "go", turret ); - - self SetScriptGoal( turret.origin, 32 ); - self thread bot_inc_bots( turret, true ); - self thread turret_death_monitor( turret ); - self thread bots_watch_touch_obj( turret ); - - if ( self waittill_any_return( "bad_path", "goal", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - } - - if ( !isdefined( turret ) ) - { - return; - } - - self BotNotifyBotEvent( "turret_attack", "start", turret ); - - self SetScriptEnemy( turret, ( 0, 0, 25 ) ); - self bot_turret_attack( turret ); - self ClearScriptEnemy(); - - self BotNotifyBotEvent( "turret_attack", "stop", turret ); -} - -/* - Bots will think when to target a turret -*/ -bot_turret_think() -{ - self endon( "death" ); - self endon( "disconnect" ); - level endon ( "game_ended" ); - - for ( ;; ) - { - wait( 1 ); - - self bot_turret_think_loop(); - } -} - -/* - Checks if the bot is stuck on a carepackage -*/ -bot_watch_stuck_on_crate_loop() -{ - crates = getentarray( "care_package", "targetname" ); - - if ( crates.size == 0 ) - { - return; - } - - crate = undefined; - - for ( i = crates.size - 1; i >= 0; i-- ) - { - tempCrate = crates[ i ]; - - if ( !isdefined( tempCrate ) ) - { - continue; - } - - if ( !isdefined( tempCrate.doingphysics ) || tempCrate.doingphysics ) - { - continue; - } - - if ( isdefined( crate ) && distancesquared( crate.origin, self.origin ) < distancesquared( tempCrate.origin, self.origin ) ) - { - continue; - } - - crate = tempCrate; - } - - if ( !isdefined( crate ) ) - { - return; - } - - radius = getdvarfloat( "player_useRadius" ); - - if ( distancesquared( crate.origin, self.origin ) > radius * radius ) - { - return; - } - - self.bot_stuck_on_carepackage = crate; - self notify( "crate_physics_done" ); -} - -/* - Checks if the bot is stuck on a carepackage -*/ -bot_watch_stuck_on_crate() -{ - self endon( "death" ); - self endon( "disconnect" ); - level endon( "game_ended" ); - - for ( ;; ) - { - wait 3; - - if ( self hasThreat() ) - { - continue; - } - - self bot_watch_stuck_on_crate_loop(); - } -} - -/* - Bots will capture carepackages -*/ -bot_crate_think_loop( data ) -{ - ret = "crate_physics_done"; - - if ( data.first ) - { - data.first = false; - } - else - { - ret = self waittill_any_timeout( randomintrange( 3, 5 ), "crate_physics_done" ); - } - - myTeam = self.pers[ "team" ]; - crate = self.bot_stuck_on_carepackage; - self.bot_stuck_on_carepackage = undefined; - - if ( !isdefined( crate ) ) - { - if ( randomint( 100 ) < 20 && ret != "crate_physics_done" ) - { - return; - } - - if ( self HasScriptGoal() || self.bot_lock_goal ) - { - return; - } - - if ( self isDefusing() || self isPlanting() ) - { - return; - } - - if ( self isusingremote() || self BotIsFrozen() ) - { - return; - } - - if ( self inLastStand() ) - { - return; - } - - crates = getentarray( "care_package", "targetname" ); - - if ( crates.size == 0 ) - { - return; - } - - wantsClosest = randomint( 2 ); - - crate = undefined; - - for ( i = crates.size - 1; i >= 0; i-- ) - { - tempCrate = crates[ i ]; - - if ( !isdefined( tempCrate ) ) - { - continue; - } - - if ( !isdefined( tempCrate.doingphysics ) || tempCrate.doingphysics ) - { - continue; - } - - if ( !isdefined( tempCrate.bots ) ) - { - tempCrate.bots = 0; - } - - if ( tempCrate.bots >= 3 ) - { - continue; - } - - if ( isdefined( crate ) ) - { - if ( wantsClosest ) - { - if ( distancesquared( crate.origin, self.origin ) < distancesquared( tempCrate.origin, self.origin ) ) - { - continue; - } - } - else - { - if ( maps\mp\killstreaks\_killstreaks::getstreakcost( crate.cratetype ) > maps\mp\killstreaks\_killstreaks::getstreakcost( tempCrate.cratetype ) ) - { - continue; - } - } - } - - crate = tempCrate; - } - - crates = undefined; - - if ( !isdefined( crate ) ) - { - return; - } - - self BotNotifyBotEvent( "crate_cap", "go", crate ); - - self.bot_lock_goal = true; - - radius = getdvarfloat( "player_useRadius" ) - 16; - self SetScriptGoal( crate.origin, radius ); - self thread bot_inc_bots( crate, true ); - self thread bots_watch_touch_obj( crate ); - - path = self waittill_any_return( "bad_path", "goal", "new_goal" ); - - self.bot_lock_goal = false; - - if ( path != "new_goal" ) - { - self ClearScriptGoal(); - } - - if ( path != "goal" || !isdefined( crate ) || distancesquared( self.origin, crate.origin ) > radius * radius ) - { - if ( isdefined( crate ) && path == "bad_path" ) - { - self BotNotifyBotEvent( "crate_cap", "unreachable", crate ); - } - - return; - } - } - - self BotNotifyBotEvent( "crate_cap", "start", crate ); - - self BotRandomStance(); - - self BotFreezeControls( true ); - self bot_wait_stop_move(); - - waitTime = 3.25; - - if ( !isdefined( crate.owner ) || crate.owner == self ) - { - waitTime = 0.75; - } - - self thread BotPressUse( waitTime ); - wait waitTime; - - self BotFreezeControls( false ); - - // check if actually captured it? - self BotNotifyBotEvent( "crate_cap", "stop", crate ); -} - -/* - Bots will capture carepackages -*/ -bot_crate_think() -{ - self endon( "death" ); - self endon( "disconnect" ); - level endon( "game_ended" ); - - data = spawnstruct(); - data.first = true; - - for ( ;; ) - { - self bot_crate_think_loop( data ); - } -} - -/* - Reload cancels -*/ -doReloadCancel_loop() -{ - ret = self waittill_any_return( "reload", "weapon_change" ); - - if ( self BotIsFrozen() ) - { - return; - } - - if ( self isDefusing() || self isPlanting() ) - { - return; - } - - if ( self isusingremote() ) - { - return; - } - - if ( self inLastStand() && !self inFinalStand() ) - { - return; - } - - curWeap = self getcurrentweapon(); - - if ( !maps\mp\gametypes\_weapons::isprimaryweapon( curWeap ) ) - { - return; - } - - if ( ret == "reload" ) - { - // check single reloads - if ( self getweaponammoclip( curWeap ) < weaponclipsize( curWeap ) ) - { - return; - } - } - - // check difficulty - if ( self.pers[ "bots" ][ "skill" ][ "base" ] <= 3 ) - { - return; - } - - // check if got another weapon - weaponslist = self getweaponslistprimaries(); - weap = ""; - - while ( weaponslist.size ) - { - weapon = weaponslist[ randomint( weaponslist.size ) ]; - weaponslist = array_remove( weaponslist, weapon ); - - if ( !maps\mp\gametypes\_weapons::isprimaryweapon( weapon ) ) - { - continue; - } - - if ( curWeap == weapon || weapon == "none" || weapon == "" ) - { - continue; - } - - weap = weapon; - break; - } - - if ( weap == "" ) - { - return; - } - - // do the cancel - wait 0.1; - self thread changeToWeapon( weap ); - wait 0.25; - self thread changeToWeapon( curWeap ); - wait 2; -} - -/* - Reload cancels -*/ -doReloadCancel() -{ - self endon( "disconnect" ); - self endon( "death" ); - - for ( ;; ) - { - self doReloadCancel_loop(); - } -} - -/* - Bots will think to switch weapons -*/ -bot_weapon_think_loop( data ) -{ - ret = self waittill_any_timeout( randomintrange( 2, 4 ), "bot_force_check_switch" ); - - if ( self BotIsFrozen() ) - { - return; - } - - if ( self isDefusing() || self isPlanting() ) - { - return; - } - - if ( self isusingremote() ) - { - return; - } - - if ( self inLastStand() && !self inFinalStand() ) - { - return; - } - - curWeap = self getcurrentweapon(); - hasTarget = self hasThreat(); - - if ( hasTarget ) - { - threat = self getThreat(); - rocketAmmo = self getRocketAmmo(); - - if ( entIsVehicle( threat ) && isdefined( rocketAmmo ) ) - { - if ( curWeap != rocketAmmo ) - { - self thread changeToWeapon( rocketAmmo ); - } - - return; - } - } - - if ( self HasBotJavelinLocation() && self getammocount( "javelin_mp" ) ) - { - if ( curWeap != "javelin_mp" ) - { - self thread changeToWeapon( "javelin_mp" ); - } - - return; - } - - if ( isdefined( self.bot_oma_class ) ) - { - if ( curWeap != "onemanarmy_mp" ) - { - self thread changeToWeapon( "onemanarmy_mp" ); - } - - return; - } - - force = ( ret == "bot_force_check_switch" ); - - if ( data.first ) - { - data.first = false; - - if ( randomint( 100 ) > self.pers[ "bots" ][ "behavior" ][ "initswitch" ] ) - { - return; - } - } - else - { - if ( curWeap != "none" && self getammocount( curWeap ) && curWeap != "stinger_mp" && curWeap != "javelin_mp" && curWeap != "onemanarmy_mp" ) - { - if ( randomint( 100 ) > self.pers[ "bots" ][ "behavior" ][ "switch" ] ) - { - return; - } - - if ( hasTarget ) - { - return; - } - } - else - { - force = true; - } - } - - weaponslist = self getweaponslistall(); - weap = ""; - - while ( weaponslist.size ) - { - weapon = weaponslist[ randomint( weaponslist.size ) ]; - weaponslist = array_remove( weaponslist, weapon ); - - if ( !self getammocount( weapon ) && !force ) - { - continue; - } - - if ( !isWeaponPrimary( weapon ) ) - { - continue; - } - - if ( curWeap == weapon || weapon == "none" || weapon == "" || weapon == "javelin_mp" || weapon == "stinger_mp" || weapon == "onemanarmy_mp" ) - { - continue; - } - - weap = weapon; - break; - } - - if ( weap == "" ) - { - return; - } - - self thread changeToWeapon( weap ); -} - -/* - Bots will think to switch weapons -*/ -bot_weapon_think() -{ - self endon( "death" ); - self endon( "disconnect" ); - level endon( "game_ended" ); - - data = spawnstruct(); - data.first = true; - - for ( ;; ) - { - self bot_weapon_think_loop( data ); - } -} - -/* - Bots think when to target vehicles -*/ -bot_target_vehicle_loop() -{ - rocketAmmo = self getRocketAmmo(); - - if ( !isdefined( rocketAmmo ) && self BotGetRandom() < 90 ) - { - return; - } - - if ( isdefined( rocketAmmo ) && rocketAmmo == "javelin_mp" && self isemped() ) - { - return; - } - - targets = maps\mp\_stinger::gettargetlist(); - - if ( !targets.size ) - { - return; - } - - lockOnAmmo = self getLockonAmmo(); - myEye = self geteye(); - target = undefined; - - for ( i = targets.size - 1; i >= 0; i-- ) - { - tempTarget = targets[ i ]; - - if ( isdefined( tempTarget.owner ) && tempTarget.owner == self ) - { - continue; - } - - if ( !bullettracepassed( myEye, tempTarget.origin, false, tempTarget ) ) - { - continue; - } - - if ( tempTarget.health <= 0 ) - { - continue; - } - - if ( tempTarget.classname != "script_vehicle" && !isdefined( lockOnAmmo ) ) - { - continue; - } - - target = tempTarget; - } - - targets = undefined; - - if ( !isdefined( target ) ) - { - return; - } - - self BotNotifyBotEvent( "attack_vehicle", "start", target, rocketAmmo ); - - self SetScriptEnemy( target, ( 0, 0, 0 ) ); - self bot_attack_vehicle( target ); - self ClearScriptEnemy(); - self notify( "bot_force_check_switch" ); - - self BotNotifyBotEvent( "attack_vehicle", "stop", target, rocketAmmo ); -} - -/* - Bots think when to target vehicles -*/ -bot_target_vehicle() -{ - self endon( "disconnect" ); - self endon( "death" ); - - for ( ;; ) - { - wait randomintrange( 2, 4 ); - - if ( self.pers[ "bots" ][ "skill" ][ "base" ] <= 1 ) - { - continue; - } - - if ( self HasScriptEnemy() ) - { - continue; - } - - if ( self isusingremote() ) - { - continue; - } - - self bot_target_vehicle_loop(); - } -} - -/* - Bots target the killstreak for a time and stops -*/ -bot_attack_vehicle( target ) -{ - target endon( "death" ); - - wait_time = randomintrange( 7, 10 ); - - for ( i = 0; i < wait_time; i++ ) - { - self notify( "bot_force_check_switch" ); - wait( 1 ); - - if ( !isdefined( target ) ) - { - return; - } - } -} - -/* - Returns an origin thats good to use for a kill streak -*/ -getKillstreakTargetLocation() -{ - location = undefined; - players = []; - - for ( i = level.players.size - 1; i >= 0; i-- ) - { - player = level.players[ i ]; - - if ( player == self ) - { - continue; - } - - if ( !isdefined( player.team ) ) - { - continue; - } - - if ( level.teambased && self.team == player.team ) - { - continue; - } - - if ( player.sessionstate != "playing" ) - { - continue; - } - - if ( !isreallyalive( player ) ) - { - continue; - } - - if ( player _hasperk( "specialty_coldblooded" ) ) - { - continue; - } - - if ( !bullettracepassed( player.origin, player.origin + ( 0, 0, 2048 ), false, player ) && self.pers[ "bots" ][ "skill" ][ "base" ] > 3 ) - { - continue; - } - - players[ players.size ] = player; - } - - target = random( players ); - - if ( isdefined( target ) ) - { - location = target.origin + ( randomintrange( ( 8 - self.pers[ "bots" ][ "skill" ][ "base" ] ) * -75, ( 8 - self.pers[ "bots" ][ "skill" ][ "base" ] ) * 75 ), randomintrange( ( 8 - self.pers[ "bots" ][ "skill" ][ "base" ] ) * -75, ( 8 - self.pers[ "bots" ][ "skill" ][ "base" ] ) * 75 ), 0 ); - } - else if ( self.pers[ "bots" ][ "skill" ][ "base" ] <= 3 ) - { - location = self.origin + ( randomintrange( -512, 512 ), randomintrange( -512, 512 ), 0 ); - } - - return location; -} - -/* - Returns if any harriers exists that is an enemy -*/ -isAnyEnemyPlanes() -{ - if ( !isdefined( level.harriers ) ) - { - return false; - } - - for ( i = 0; i < level.harriers.size; i++ ) - { - plane = level.harriers[ i ]; - - if ( !isdefined( plane ) ) - { - continue; - } - - if ( level.teambased && plane.team == self.team ) - { - continue; - } - - if ( isdefined( plane.owner ) && plane.owner == self ) - { - continue; - } - - return true; - } - - return false; -} - -/* - Bots think to use killstreaks -*/ -bot_killstreak_think_loop( data ) -{ - if ( data.dofastcontinue ) - { - data.dofastcontinue = false; - } - else - { - wait randomintrange( 1, 3 ); - } - - if ( !isdefined( self.pers[ "killstreaks" ][ 0 ] ) ) - { - return; - } - - if ( self BotIsFrozen() ) - { - return; - } - - if ( self hasThreat() || self HasBotJavelinLocation() ) - { - return; - } - - if ( self isDefusing() || self isPlanting() ) - { - return; - } - - if ( self isemped() ) - { - return; - } - - if ( self isusingremote() ) - { - return; - } - - if ( self inLastStand() && !self inFinalStand() ) - { - return; - } - - - if ( isdefined( self.iscarrying ) && self.iscarrying ) - { - self notify( "place_sentry" ); - } - - curWeap = self getcurrentweapon(); - - if ( issubstr( curWeap, "airdrop_" ) ) - { - self thread BotPressAttack( 0.05 ); - } - - if ( iskillstreakweapon( curWeap ) ) - { - self thread changeToWeapon( self getlastweapon() ); - return; - } - - streakName = self.pers[ "killstreaks" ][ 0 ].streakname; - - if ( level.ingraceperiod && maps\mp\killstreaks\_killstreaks::deadlykillstreak( streakName ) ) - { - return; - } - - ksWeap = maps\mp\killstreaks\_killstreaks::getkillstreakweapon( streakName ); - - if ( curWeap == "none" || !isWeaponPrimary( curWeap ) ) - { - curWeap = self getlastweapon(); - } - - lifeId = self.pers[ "killstreaks" ][ 0 ].lifeid; - - if ( !isdefined( lifeId ) ) - { - lifeId = -1; - } - - if ( isStrStart( streakName, "helicopter_" ) && self isAnyEnemyPlanes() && self.pers[ "bots" ][ "skill" ][ "base" ] > 3 ) - { - return; - } - - if ( maps\mp\killstreaks\_killstreaks::isridekillstreak( streakName ) || maps\mp\killstreaks\_killstreaks::iscarrykillstreak( streakName ) ) - { - if ( self inLastStand() ) - { - return; - } - - if ( lifeId == self.deaths && !self HasScriptGoal() && !self.bot_lock_goal && streakName != "sentry" && !self nearAnyOfWaypoints( 128, getWaypointsOfType( "camp" ) ) ) - { - campSpot = getWaypointForIndex( random( self waypointsNear( getWaypointsOfType( "camp" ), 1024 ) ) ); - - if ( isdefined( campSpot ) ) - { - self BotNotifyBotEvent( "killstreak", "camp", streakName, campSpot ); - - self SetScriptGoal( campSpot.origin, 16 ); - - if ( self waittill_any_return( "new_goal", "goal", "bad_path" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - data.dofastcontinue = true; - return; - } - } - - if ( streakName == "sentry" ) - { - if ( self HasScriptAimPos() ) - { - return; - } - - myEye = self geteye(); - angles = self getplayerangles(); - - forwardTrace = bullettrace( myEye, myEye + anglestoforward( angles ) * 1024, false, self ); - - if ( distancesquared( self.origin, forwardTrace[ "position" ] ) < 1000 * 1000 && self.pers[ "bots" ][ "skill" ][ "base" ] > 3 ) - { - return; - } - - self BotNotifyBotEvent( "killstreak", "call", streakName ); - - self BotStopMoving( true ); - self SetScriptAimPos( forwardTrace[ "position" ] ); - - if ( !self changeToWeapon( ksWeap ) ) - { - self BotStopMoving( false ); - self ClearScriptAimPos(); - return; - } - - wait 1; - self notify( "place_sentry" ); - wait 0.05; - self notify( "cancel_sentry" ); - wait 0.5; - - self BotStopMoving( false ); - self ClearScriptAimPos(); - } - else if ( streakName == "predator_missile" ) - { - location = self getKillstreakTargetLocation(); - - if ( !isdefined( location ) ) - { - return; - } - - self BotNotifyBotEvent( "killstreak", "call", streakName, location ); - - self BotRandomStance(); - self BotStopMoving( true ); - self changeToWeapon( ksWeap ); - - wait 3; - self BotStopMoving( false ); - } - else if ( streakName == "ac130" ) - { - if ( isdefined( level.ac130player ) || level.ac130inuse ) - { - return; - } - - self BotNotifyBotEvent( "killstreak", "call", streakName ); - - self BotRandomStance(); - self BotStopMoving( true ); - self changeToWeapon( ksWeap ); - - wait 3; - self BotStopMoving( false ); - } - else if ( streakName == "helicopter_minigun" ) - { - if ( isdefined( level.chopper ) ) - { - return; - } - - self BotNotifyBotEvent( "killstreak", "call", streakName ); - - self BotRandomStance(); - self BotStopMoving( true ); - self changeToWeapon( ksWeap ); - - wait 3; - self BotStopMoving( false ); - } - } - else - { - if ( streakName == "airdrop_mega" || streakName == "airdrop_sentry_minigun" || streakName == "airdrop" ) - { - if ( self HasScriptAimPos() ) - { - return; - } - - if ( streakName != "airdrop_mega" && level.littlebirds > 2 ) - { - return; - } - - if ( !bullettracepassed( self.origin, self.origin + ( 0, 0, 2048 ), false, self ) && self.pers[ "bots" ][ "skill" ][ "base" ] > 3 ) - { - return; - } - - myEye = self geteye(); - angles = self getplayerangles(); - - forwardTrace = bullettrace( myEye, myEye + anglestoforward( angles ) * 256, false, self ); - - if ( distancesquared( self.origin, forwardTrace[ "position" ] ) < 96 * 96 && self.pers[ "bots" ][ "skill" ][ "base" ] > 3 ) - { - return; - } - - if ( !bullettracepassed( forwardTrace[ "position" ], forwardTrace[ "position" ] + ( 0, 0, 2048 ), false, self ) && self.pers[ "bots" ][ "skill" ][ "base" ] > 3 ) - { - return; - } - - self BotNotifyBotEvent( "killstreak", "call", streakName ); - - self BotStopMoving( true ); - self SetScriptAimPos( forwardTrace[ "position" ] ); - - if ( !self changeToWeapon( ksWeap ) ) - { - self BotStopMoving( false ); - self ClearScriptAimPos(); - return; - } - - self thread fire_current_weapon(); - - ret = self waittill_any_timeout( 5, "grenade_fire" ); - - self notify( "stop_firing_weapon" ); - - if ( ret == "timeout" ) - { - self BotStopMoving( false ); - self ClearScriptAimPos(); - return; - } - - if ( randomint( 100 ) < 80 && !self HasScriptGoal() && !self.bot_lock_goal ) - { - self waittill_any_timeout( 15, "crate_physics_done", "new_goal" ); - } - - self BotStopMoving( false ); - self ClearScriptAimPos(); - } - else - { - if ( streakName == "harrier_airstrike" && level.planes > 1 ) - { - return; - } - - if ( streakName == "nuke" && isdefined( level.nukeincoming ) ) - { - return; - } - - if ( streakName == "counter_uav" && self.pers[ "bots" ][ "skill" ][ "base" ] > 3 && ( ( level.teambased && level.activecounteruavs[ self.team ] ) || ( !level.teambased && level.activecounteruavs[ self.guid ] ) ) ) - { - return; - } - - if ( streakName == "uav" && self.pers[ "bots" ][ "skill" ][ "base" ] > 3 && ( ( level.teambased && ( level.activeuavs[ self.team ] || level.activecounteruavs[ level.otherteam[ self.team ] ] ) ) || ( !level.teambased && ( level.activeuavs[ self.guid ] || self.isradarblocked ) ) ) ) - { - return; - } - - if ( streakName == "emp" && self.pers[ "bots" ][ "skill" ][ "base" ] > 3 && ( ( level.teambased && level.teamemped[ level.otherteam[ self.team ] ] ) || ( !level.teambased && isdefined( level.empplayer ) ) ) ) - { - return; - } - - location = undefined; - directionYaw = undefined; - - switch ( streakName ) - { - case "harrier_airstrike": - case "stealth_airstrike": - case "precision_airstrike": - location = self getKillstreakTargetLocation(); - directionYaw = randomint( 360 ); - - if ( !isdefined( location ) ) - { - return; - } - - case "helicopter": - case "helicopter_flares": - case "uav": - case "nuke": - case "counter_uav": - case "emp": - self BotStopMoving( true ); - - self BotNotifyBotEvent( "killstreak", "call", streakName, location, directionYaw ); - - if ( self changeToWeapon( ksWeap ) ) - { - wait 1; - - if ( isdefined( location ) ) - { - self BotFreezeControls( true ); - - self notify( "confirm_location", location, directionYaw ); - wait 1; - - self BotFreezeControls( false ); - } - } - - self BotStopMoving( false ); - break; - } - } - } -} - -/* - Bots think to use killstreaks -*/ -bot_killstreak_think() -{ - self endon( "disconnect" ); - self endon( "death" ); - level endon( "game_ended" ); - - data = spawnstruct(); - data.dofastcontinue = false; - - for ( ;; ) - { - self bot_killstreak_think_loop( data ); - } -} - -/* - Bots do random stance -*/ -BotRandomStance() -{ - if ( randomint( 100 ) < 80 ) - { - self BotSetStance( "prone" ); - } - else if ( randomint( 100 ) < 60 ) - { - self BotSetStance( "crouch" ); - } - else - { - self BotSetStance( "stand" ); - } -} - -/* - Bots will use a random equipment -*/ -BotUseRandomEquipment() -{ - self endon( "death" ); - self endon( "disconnect" ); - - nade = undefined; - - // in mw2, can only one of these... - if ( self getammocount( "claymore_mp" ) ) - { - nade = "claymore_mp"; - } - - if ( self getammocount( "flare_mp" ) ) - { - nade = "flare_mp"; - } - - if ( self getammocount( "c4_mp" ) ) - { - nade = "c4_mp"; - } - - if ( !isdefined( nade ) ) - { - return; - } - - self botThrowGrenade( nade, 0.05 ); -} - -/* - Bots will look at a random thing -*/ -BotLookAtRandomThing( obj_target ) -{ - self endon( "death" ); - self endon( "disconnect" ); - - if ( self HasScriptAimPos() ) - { - return; - } - - rand = randomint( 100 ); - - nearestEnemy = undefined; - - for ( i = 0; i < level.players.size; i++ ) - { - player = level.players[ i ]; - - if ( !isdefined( player ) || !isdefined( player.team ) ) - { - continue; - } - - if ( !isalive( player ) ) - { - continue; - } - - if ( level.teambased && self.team == player.team ) - { - continue; - } - - if ( !isdefined( nearestEnemy ) || distancesquared( self.origin, player.origin ) < distancesquared( self.origin, nearestEnemy.origin ) ) - { - nearestEnemy = player; - } - } - - origin = ( 0, 0, self getplayerviewheight() ); - - if ( isdefined( nearestEnemy ) && distancesquared( self.origin, nearestEnemy.origin ) < 1024 * 1024 && rand < 40 ) - { - origin += ( nearestEnemy.origin[ 0 ], nearestEnemy.origin[ 1 ], self.origin[ 2 ] ); - } - else if ( isdefined( obj_target ) && rand < 50 ) - { - origin += ( obj_target.origin[ 0 ], obj_target.origin[ 1 ], self.origin[ 2 ] ); - } - else if ( rand < 85 ) - { - origin += self.origin + anglestoforward( ( 0, self.angles[ 1 ] - 180, 0 ) ) * 1024; - } - else - { - origin += self.origin + anglestoforward( ( 0, randomint( 360 ), 0 ) ) * 1024; - } - - self SetScriptAimPos( origin ); - wait 2; - self ClearScriptAimPos(); -} - -/* - Bots will do stuff while waiting for objective -*/ -bot_do_random_action_for_objective( obj_target ) -{ - self endon( "death" ); - self endon( "disconnect" ); - self notify( "bot_do_random_action_for_objective" ); - self endon( "bot_do_random_action_for_objective" ); - - if ( !isdefined( self.bot_random_obj_action ) ) - { - self.bot_random_obj_action = true; - - if ( randomint( 100 ) < 80 ) - { - self thread BotUseRandomEquipment(); - } - - if ( randomint( 100 ) < 75 ) - { - self thread BotLookAtRandomThing( obj_target ); - } - } - else - { - if ( self getstance() != "prone" && randomint( 100 ) < 15 ) - { - self BotSetStance( "prone" ); - } - else if ( randomint( 100 ) < 5 ) - { - self thread BotLookAtRandomThing( obj_target ); - } - } - - wait 2; - self.bot_random_obj_action = undefined; -} - -/* - Bots hang around the enemy's flag to spawn kill em -*/ -bot_dom_spawn_kill_think_loop() -{ - myTeam = self.pers[ "team" ]; - otherTeam = getotherteam( myTeam ); - myFlagCount = maps\mp\gametypes\dom::getteamflagcount( myTeam ); - - if ( myFlagCount == level.flags.size ) - { - return; - } - - otherFlagCount = maps\mp\gametypes\dom::getteamflagcount( otherTeam ); - - if ( myFlagCount <= otherFlagCount || otherFlagCount != 1 ) - { - return; - } - - flag = undefined; - - for ( i = 0; i < level.flags.size; i++ ) - { - if ( level.flags[ i ] maps\mp\gametypes\dom::getflagteam() == myTeam ) - { - continue; - } - - flag = level.flags[ i ]; - } - - if ( !isdefined( flag ) ) - { - return; - } - - if ( distancesquared( self.origin, flag.origin ) < 2048 * 2048 ) - { - return; - } - - self BotNotifyBotEvent( "dom", "start", "spawnkill", flag ); - - self SetScriptGoal( flag.origin, 1024 ); - - self thread bot_dom_watch_flags( myFlagCount, myTeam ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - self BotNotifyBotEvent( "dom", "stop", "spawnkill", flag ); -} - -/* - Bots hang around the enemy's flag to spawn kill em -*/ -bot_dom_spawn_kill_think() -{ - self endon( "death" ); - self endon( "disconnect" ); - - if ( level.gametype != "dom" ) - { - return; - } - - for ( ;; ) - { - wait( randomintrange( 10, 20 ) ); - - if ( randomint( 100 ) < 20 ) - { - continue; - } - - if ( self HasScriptGoal() || self.bot_lock_goal ) - { - continue; - } - - self bot_dom_spawn_kill_think_loop(); - } -} - -/* - Calls 'bad_path' when the flag count changes -*/ -bot_dom_watch_flags( count, myTeam ) -{ - self endon( "death" ); - self endon( "disconnect" ); - self endon( "goal" ); - self endon( "bad_path" ); - self endon( "new_goal" ); - - for ( ;; ) - { - wait 0.5; - - if ( maps\mp\gametypes\dom::getteamflagcount( myTeam ) != count ) - { - break; - } - } - - self notify( "bad_path" ); -} - -/* - Bots watches their own flags and protects them when they are under capture -*/ -bot_dom_def_think_loop() -{ - myTeam = self.pers[ "team" ]; - flag = undefined; - - for ( i = 0; i < level.flags.size; i++ ) - { - if ( level.flags[ i ] maps\mp\gametypes\dom::getflagteam() != myTeam ) - { - continue; - } - - if ( !level.flags[ i ].useobj.objpoints[ myTeam ].isflashing ) - { - continue; - } - - if ( !isdefined( flag ) || distancesquared( self.origin, level.flags[ i ].origin ) < distancesquared( self.origin, flag.origin ) ) - { - flag = level.flags[ i ]; - } - } - - if ( !isdefined( flag ) ) - { - return; - } - - self BotNotifyBotEvent( "dom", "start", "defend", flag ); - - self SetScriptGoal( flag.origin, 128 ); - - self thread bot_dom_watch_for_flashing( flag, myTeam ); - self thread bots_watch_touch_obj( flag ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - self BotNotifyBotEvent( "dom", "stop", "defend", flag ); -} - -/* - Bots watches their own flags and protects them when they are under capture -*/ -bot_dom_def_think() -{ - self endon( "death" ); - self endon( "disconnect" ); - - if ( level.gametype != "dom" ) - { - return; - } - - for ( ;; ) - { - wait( randomintrange( 1, 3 ) ); - - if ( randomint( 100 ) < 35 ) - { - continue; - } - - if ( self HasScriptGoal() || self.bot_lock_goal ) - { - continue; - } - - self bot_dom_def_think_loop(); - } -} - -/* - Watches while the flag is under capture -*/ -bot_dom_watch_for_flashing( flag, myTeam ) -{ - self endon( "death" ); - self endon( "disconnect" ); - self endon( "goal" ); - self endon( "bad_path" ); - self endon( "new_goal" ); - - for ( ;; ) - { - wait 0.5; - - if ( !isdefined( flag ) ) - { - break; - } - - if ( flag maps\mp\gametypes\dom::getflagteam() != myTeam || !flag.useobj.objpoints[ myTeam ].isflashing ) - { - break; - } - } - - self notify( "bad_path" ); -} - -/* - Bots capture dom flags -*/ -bot_dom_cap_think_loop() -{ - myTeam = self.pers[ "team" ]; - otherTeam = getotherteam( myTeam ); - - myFlagCount = maps\mp\gametypes\dom::getteamflagcount( myTeam ); - - if ( myFlagCount == level.flags.size ) - { - return; - } - - otherFlagCount = maps\mp\gametypes\dom::getteamflagcount( otherTeam ); - - if ( game[ "teamScores" ][ myTeam ] >= game[ "teamScores" ][ otherTeam ] ) - { - if ( myFlagCount < otherFlagCount ) - { - if ( randomint( 100 ) < 15 ) - { - return; - } - } - else if ( myFlagCount == otherFlagCount ) - { - if ( randomint( 100 ) < 35 ) - { - return; - } - } - else if ( myFlagCount > otherFlagCount ) - { - if ( randomint( 100 ) < 95 ) - { - return; - } - } - } - - flag = undefined; - flags = []; - - for ( i = 0; i < level.flags.size; i++ ) - { - if ( level.flags[ i ] maps\mp\gametypes\dom::getflagteam() == myTeam ) - { - continue; - } - - flags[ flags.size ] = level.flags[ i ]; - } - - if ( randomint( 100 ) > 30 ) - { - for ( i = 0; i < flags.size; i++ ) - { - if ( !isdefined( flag ) || distancesquared( self.origin, level.flags[ i ].origin ) < distancesquared( self.origin, flag.origin ) ) - { - flag = level.flags[ i ]; - } - } - } - else if ( flags.size ) - { - flag = random( flags ); - } - - if ( !isdefined( flag ) ) - { - return; - } - - self BotNotifyBotEvent( "dom", "go", "cap", flag ); - - self.bot_lock_goal = true; - self SetScriptGoal( flag.origin, 64 ); - - self thread bot_dom_go_cap_flag( flag, myTeam ); - - event = self waittill_any_return( "goal", "bad_path", "new_goal" ); - - if ( event != "new_goal" ) - { - self ClearScriptGoal(); - } - - if ( event != "goal" ) - { - self.bot_lock_goal = false; - return; - } - - self BotNotifyBotEvent( "dom", "start", "cap", flag ); - - self SetScriptGoal( self.origin, 64 ); - - while ( flag maps\mp\gametypes\dom::getflagteam() != myTeam && self istouching( flag ) ) - { - cur = flag.useobj.curprogress; - wait 0.5; - - if ( flag.useobj.curprogress == cur ) - { - break; // some enemy is near us, kill him - } - - self thread bot_do_random_action_for_objective( flag ); - } - - self BotNotifyBotEvent( "dom", "stop", "cap", flag ); - - self ClearScriptGoal(); - - self.bot_lock_goal = false; -} - -/* - Bots capture dom flags -*/ -bot_dom_cap_think() -{ - self endon( "death" ); - self endon( "disconnect" ); - - if ( level.gametype != "dom" ) - { - return; - } - - for ( ;; ) - { - wait( randomintrange( 3, 12 ) ); - - if ( self.bot_lock_goal ) - { - continue; - } - - if ( !isdefined( level.flags ) || level.flags.size == 0 ) - { - continue; - } - - self bot_dom_cap_think_loop(); - } -} - -/* - Bot goes to the flag, watching while they don't have the flag -*/ -bot_dom_go_cap_flag( flag, myTeam ) -{ - self endon( "death" ); - self endon( "disconnect" ); - self endon( "goal" ); - self endon( "bad_path" ); - self endon( "new_goal" ); - - for ( ;; ) - { - wait randomintrange( 2, 4 ); - - if ( !isdefined( flag ) ) - { - break; - } - - if ( flag maps\mp\gametypes\dom::getflagteam() == myTeam ) - { - break; - } - - if ( self istouching( flag ) ) - { - break; - } - } - - if ( flag maps\mp\gametypes\dom::getflagteam() == myTeam ) - { - self notify( "bad_path" ); - } - else - { - self notify( "goal" ); - } -} - -/* - Bots play headquarters -*/ -bot_hq_loop() -{ - myTeam = self.pers[ "team" ]; - otherTeam = getotherteam( myTeam ); - - radio = level.radio; - gameobj = radio.gameobject; - origin = ( radio.origin[ 0 ], radio.origin[ 1 ], radio.origin[ 2 ] + 5 ); - - // if neut or enemy - if ( gameobj.ownerteam != myTeam ) - { - if ( gameobj.interactteam == "none" ) // wait for it to become active - { - if ( self HasScriptGoal() ) - { - return; - } - - if ( distancesquared( origin, self.origin ) <= 1024 * 1024 ) - { - return; - } - - self SetScriptGoal( origin, 256 ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - return; - } - - // capture it - - self BotNotifyBotEvent( "hq", "go", "cap" ); - - self.bot_lock_goal = true; - self SetScriptGoal( origin, 64 ); - self thread bot_hq_go_cap( gameobj, radio ); - - event = self waittill_any_return( "goal", "bad_path", "new_goal" ); - - if ( event != "new_goal" ) - { - self ClearScriptGoal(); - } - - if ( event != "goal" ) - { - self.bot_lock_goal = false; - return; - } - - if ( !self istouching( gameobj.trigger ) || level.radio != radio ) - { - self.bot_lock_goal = false; - return; - } - - self BotNotifyBotEvent( "hq", "start", "cap" ); - - self SetScriptGoal( self.origin, 64 ); - - while ( self istouching( gameobj.trigger ) && gameobj.ownerteam != myTeam && level.radio == radio ) - { - cur = gameobj.curprogress; - wait 0.5; - - if ( cur == gameobj.curprogress ) - { - break; // no prog made, enemy must be capping - } - - self thread bot_do_random_action_for_objective( gameobj.trigger ); - } - - self ClearScriptGoal(); - self.bot_lock_goal = false; - - self BotNotifyBotEvent( "hq", "stop", "cap" ); - } - else // we own it - { - if ( gameobj.objpoints[ myTeam ].isflashing ) // underattack - { - self BotNotifyBotEvent( "hq", "start", "defend" ); - - self.bot_lock_goal = true; - self SetScriptGoal( origin, 64 ); - self thread bot_hq_watch_flashing( gameobj, radio ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - self.bot_lock_goal = false; - - self BotNotifyBotEvent( "hq", "stop", "defend" ); - return; - } - - if ( self HasScriptGoal() ) - { - return; - } - - if ( distancesquared( origin, self.origin ) <= 1024 * 1024 ) - { - return; - } - - self SetScriptGoal( origin, 256 ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - } -} - -/* - Bots play headquarters -*/ -bot_hq() -{ - self endon( "death" ); - self endon( "disconnect" ); - - if ( level.gametype != "koth" ) - { - return; - } - - for ( ;; ) - { - wait( randomintrange( 3, 5 ) ); - - if ( self.bot_lock_goal ) - { - continue; - } - - if ( !isdefined( level.radio ) ) - { - continue; - } - - if ( !isdefined( level.radio.gameobject ) ) - { - continue; - } - - self bot_hq_loop(); - } -} - -/* - Waits until not touching the trigger and it is the current radio. -*/ -bot_hq_go_cap( obj, radio ) -{ - self endon( "death" ); - self endon( "disconnect" ); - self endon( "goal" ); - self endon( "bad_path" ); - self endon( "new_goal" ); - - for ( ;; ) - { - wait randomintrange( 2, 4 ); - - if ( !isdefined( obj ) ) - { - break; - } - - if ( self istouching( obj.trigger ) ) - { - break; - } - - if ( level.radio != radio ) - { - break; - } - } - - if ( level.radio != radio ) - { - self notify( "bad_path" ); - } - else - { - self notify( "goal" ); - } -} - -/* - Waits while the radio is under attack. -*/ -bot_hq_watch_flashing( obj, radio ) -{ - self endon( "death" ); - self endon( "disconnect" ); - self endon( "goal" ); - self endon( "bad_path" ); - self endon( "new_goal" ); - - myTeam = self.team; - - for ( ;; ) - { - wait 0.5; - - if ( !isdefined( obj ) ) - { - break; - } - - if ( !obj.objpoints[ myTeam ].isflashing ) - { - break; - } - - if ( level.radio != radio ) - { - break; - } - } - - self notify( "bad_path" ); -} - -/* - Bots play sab -*/ -bot_sab_loop() -{ - myTeam = self.pers[ "team" ]; - otherTeam = getotherteam( myTeam ); - - bomb = level.sabbomb; - bombteam = bomb.ownerteam; - carrier = bomb.carrier; - timeleft = maps\mp\gametypes\_gamelogic::gettimeremaining() / 1000; - - // the bomb is ours, we are on the offence - if ( bombteam == myTeam ) - { - site = level.bombzones[ otherTeam ]; - origin = ( site.curorigin[ 0 ] + 50, site.curorigin[ 1 ] + 50, site.curorigin[ 2 ] + 5 ); - - // protect our planted bomb - if ( level.bombplanted ) - { - // kill defuser - if ( site isInUse() ) // somebody is defusing our bomb we planted - { - self BotNotifyBotEvent( "sab", "start", "defuser" ); - - self.bot_lock_goal = true; - self SetScriptGoal( origin, 64 ); - - self thread bot_defend_site( site ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - self.bot_lock_goal = false; - - self BotNotifyBotEvent( "sab", "stop", "defuser" ); - return; - } - - // else hang around the site - if ( distancesquared( origin, self.origin ) <= 1024 * 1024 ) - { - return; - } - - self.bot_lock_goal = true; - self SetScriptGoal( origin, 256 ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - self.bot_lock_goal = false; - return; - } - - // we are not the carrier - if ( !self isBombCarrier() ) - { - // lets escort the bomb carrier - if ( self HasScriptGoal() ) - { - return; - } - - origin = carrier.origin; - - if ( distancesquared( origin, self.origin ) <= 1024 * 1024 ) - { - return; - } - - self SetScriptGoal( origin, 256 ); - self thread bot_escort_obj( bomb, carrier ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - return; - } - - // we are the carrier of the bomb, lets check if we need to plant - timepassed = gettimepassed() / 1000; - - if ( timepassed < 120 && timeleft >= 90 && randomint( 100 ) < 98 ) - { - return; - } - - self BotNotifyBotEvent( "sab", "go", "plant" ); - - self.bot_lock_goal = true; - self SetScriptGoal( origin, 1 ); - - self thread bot_go_plant( site ); - event = self waittill_any_return( "goal", "bad_path", "new_goal" ); - - if ( event != "new_goal" ) - { - self ClearScriptGoal(); - } - - if ( event != "goal" || level.bombplanted || !self istouching( site.trigger ) || site isInUse() || self inLastStand() || self hasThreat() ) - { - self.bot_lock_goal = false; - return; - } - - self BotNotifyBotEvent( "sab", "start", "plant" ); - - self BotRandomStance(); - self SetScriptGoal( self.origin, 64 ); - self bot_wait_stop_move(); - - waitTime = ( site.usetime / 1000 ) + 2.5; - self thread BotPressUse( waitTime ); - wait waitTime; - - self ClearScriptGoal(); - self.bot_lock_goal = false; - - self BotNotifyBotEvent( "sab", "stop", "plant" ); - } - else if ( bombteam == otherTeam ) // the bomb is theirs, we are on the defense - { - site = level.bombzones[ myTeam ]; - - if ( !isdefined( site.bots ) ) - { - site.bots = 0; - } - - // protect our site from planters - if ( !level.bombplanted ) - { - // kill bomb carrier - if ( site.bots > 2 || randomint( 100 ) < 45 ) - { - if ( self HasScriptGoal() ) - { - return; - } - - if ( carrier _hasperk( "specialty_coldblooded" ) ) - { - return; - } - - origin = carrier.origin; - - self SetScriptGoal( origin, 64 ); - self thread bot_escort_obj( bomb, carrier ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - return; - } - - // protect bomb site - origin = ( site.curorigin[ 0 ] + 50, site.curorigin[ 1 ] + 50, site.curorigin[ 2 ] + 5 ); - - self thread bot_inc_bots( site ); - - if ( site isInUse() ) // somebody is planting - { - self BotNotifyBotEvent( "sab", "start", "planter" ); - - self.bot_lock_goal = true; - self SetScriptGoal( origin, 64 ); - self thread bot_inc_bots( site ); - - self thread bot_defend_site( site ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - self.bot_lock_goal = false; - - self BotNotifyBotEvent( "sab", "stop", "planter" ); - return; - } - - // else hang around the site - if ( distancesquared( origin, self.origin ) <= 1024 * 1024 ) - { - wait 4; - self notify( "bot_inc_bots" ); - site.bots--; - return; - } - - self.bot_lock_goal = true; - self SetScriptGoal( origin, 256 ); - self thread bot_inc_bots( site ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - self.bot_lock_goal = false; - return; - } - - // bomb is planted we need to defuse - origin = ( site.curorigin[ 0 ] + 50, site.curorigin[ 1 ] + 50, site.curorigin[ 2 ] + 5 ); - - // someone else is defusing, lets just hang around - if ( site.bots > 1 ) - { - if ( self HasScriptGoal() ) - { - return; - } - - if ( distancesquared( origin, self.origin ) <= 1024 * 1024 ) - { - return; - } - - self SetScriptGoal( origin, 256 ); - self thread bot_go_defuse( site ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - return; - } - - // lets go defuse - self BotNotifyBotEvent( "sab", "go", "defuse" ); - - self.bot_lock_goal = true; - - self SetScriptGoal( origin, 1 ); - self thread bot_inc_bots( site ); - self thread bot_go_defuse( site ); - - event = self waittill_any_return( "goal", "bad_path", "new_goal" ); - - if ( event != "new_goal" ) - { - self ClearScriptGoal(); - } - - if ( event != "goal" || !level.bombplanted || site isInUse() || !self istouching( site.trigger ) || self inLastStand() || self hasThreat() ) - { - self.bot_lock_goal = false; - return; - } - - self BotNotifyBotEvent( "sab", "start", "defuse" ); - - self BotRandomStance(); - self SetScriptGoal( self.origin, 64 ); - self bot_wait_stop_move(); - - waitTime = ( site.usetime / 1000 ) + 2.5; - self thread BotPressUse( waitTime ); - wait waitTime; - - self ClearScriptGoal(); - self.bot_lock_goal = false; - - self BotNotifyBotEvent( "sab", "stop", "defuse" ); - } - else // we need to go get the bomb! - { - origin = ( bomb.curorigin[ 0 ], bomb.curorigin[ 1 ], bomb.curorigin[ 2 ] + 5 ); - - self BotNotifyBotEvent( "sab", "start", "bomb" ); - - self.bot_lock_goal = true; - self SetScriptGoal( origin, 64 ); - - self thread bot_get_obj( bomb ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - self.bot_lock_goal = false; - - self BotNotifyBotEvent( "sab", "stop", "bomb" ); - return; - } -} - -/* - Bots play sab -*/ -bot_sab() -{ - self endon( "death" ); - self endon( "disconnect" ); - level endon( "game_ended" ); - - if ( level.gametype != "sab" ) - { - return; - } - - for ( ;; ) - { - wait( randomintrange( 3, 5 ) ); - - if ( self isusingremote() || self.bot_lock_goal ) - { - continue; - } - - if ( !isdefined( level.sabbomb ) ) - { - continue; - } - - if ( !isdefined( level.bombzones ) || !level.bombzones.size ) - { - continue; - } - - if ( self isPlanting() || self isDefusing() ) - { - continue; - } - - self bot_sab_loop(); - } -} - -/* - Bots play sd defenders -*/ -bot_sd_defenders_loop( data ) -{ - myTeam = self.pers[ "team" ]; - otherTeam = getotherteam( myTeam ); - - // bomb not planted, lets protect our sites - if ( !level.bombplanted ) - { - timeleft = maps\mp\gametypes\_gamelogic::gettimeremaining() / 1000; - - if ( timeleft >= 90 ) - { - return; - } - - // check for a bomb carrier, and camp the bomb - if ( !level.multibomb && isdefined( level.sdbomb ) ) - { - bomb = level.sdbomb; - carrier = level.sdbomb.carrier; - - if ( !isdefined( carrier ) ) - { - origin = ( bomb.curorigin[ 0 ], bomb.curorigin[ 1 ], bomb.curorigin[ 2 ] + 5 ); - - // hang around the bomb - if ( self HasScriptGoal() ) - { - return; - } - - if ( distancesquared( origin, self.origin ) <= 1024 * 1024 ) - { - return; - } - - self SetScriptGoal( origin, 256 ); - - self thread bot_get_obj( bomb ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - return; - } - } - - // pick a site to protect - if ( !isdefined( level.bombzones ) || !level.bombzones.size ) - { - return; - } - - sites = []; - - for ( i = 0; i < level.bombzones.size; i++ ) - { - sites[ sites.size ] = level.bombzones[ i ]; - } - - if ( !sites.size ) - { - return; - } - - if ( data.rand > 50 ) - { - site = self bot_array_nearest_curorigin( sites ); - } - else - { - site = random( sites ); - } - - if ( !isdefined( site ) ) - { - return; - } - - origin = ( site.curorigin[ 0 ] + 50, site.curorigin[ 1 ] + 50, site.curorigin[ 2 ] + 5 ); - - if ( site isInUse() ) // somebody is planting - { - self BotNotifyBotEvent( "sd", "start", "planter", site ); - - self.bot_lock_goal = true; - self SetScriptGoal( origin, 64 ); - - self thread bot_defend_site( site ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - self.bot_lock_goal = false; - - self BotNotifyBotEvent( "sd", "stop", "planter", site ); - return; - } - - // else hang around the site - if ( distancesquared( origin, self.origin ) <= 1024 * 1024 ) - { - return; - } - - self.bot_lock_goal = true; - self SetScriptGoal( origin, 256 ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - self.bot_lock_goal = false; - return; - } - - // bomb is planted, we need to defuse - if ( !isdefined( level.defuseobject ) ) - { - return; - } - - defuse = level.defuseobject; - - if ( !isdefined( defuse.bots ) ) - { - defuse.bots = 0; - } - - origin = ( defuse.curorigin[ 0 ], defuse.curorigin[ 1 ], defuse.curorigin[ 2 ] + 5 ); - - // someone is going to go defuse ,lets just hang around - if ( defuse.bots > 1 ) - { - if ( self HasScriptGoal() ) - { - return; - } - - if ( distancesquared( origin, self.origin ) <= 1024 * 1024 ) - { - return; - } - - self SetScriptGoal( origin, 256 ); - self thread bot_go_defuse( defuse ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - return; - } - - // lets defuse - self BotNotifyBotEvent( "sd", "go", "defuse" ); - - self.bot_lock_goal = true; - self SetScriptGoal( origin, 1 ); - self thread bot_inc_bots( defuse ); - self thread bot_go_defuse( defuse ); - - event = self waittill_any_return( "goal", "bad_path", "new_goal" ); - - if ( event != "new_goal" ) - { - self ClearScriptGoal(); - } - - if ( event != "goal" || !level.bombplanted || defuse isInUse() || !self istouching( defuse.trigger ) || self inLastStand() || self hasThreat() ) - { - self.bot_lock_goal = false; - return; - } - - self BotNotifyBotEvent( "sd", "start", "defuse" ); - - self BotRandomStance(); - self SetScriptGoal( self.origin, 64 ); - self bot_wait_stop_move(); - - waitTime = ( defuse.usetime / 1000 ) + 2.5; - self thread BotPressUse( waitTime ); - wait waitTime; - - self ClearScriptGoal(); - self.bot_lock_goal = false; - - self BotNotifyBotEvent( "sd", "stop", "defuse" ); -} - -/* - Bots play sd defenders -*/ -bot_sd_defenders() -{ - self endon( "death" ); - self endon( "disconnect" ); - level endon( "game_ended" ); - - if ( level.gametype != "sd" ) - { - return; - } - - if ( self.team == game[ "attackers" ] ) - { - return; - } - - data = spawnstruct(); - data.rand = self BotGetRandom(); - - for ( ;; ) - { - wait( randomintrange( 3, 5 ) ); - - if ( self isusingremote() || self.bot_lock_goal ) - { - continue; - } - - if ( self isPlanting() || self isDefusing() ) - { - continue; - } - - self bot_sd_defenders_loop( data ); - } -} - -/* - Bots play sd attackers -*/ -bot_sd_attackers_loop( data ) -{ - if ( data.first ) - { - data.first = false; - } - else - { - wait( randomintrange( 3, 5 ) ); - } - - if ( self isusingremote() || self.bot_lock_goal ) - { - return; - } - - myTeam = self.pers[ "team" ]; - otherTeam = getotherteam( myTeam ); - - // bomb planted - if ( level.bombplanted ) - { - if ( !isdefined( level.defuseobject ) ) - { - return; - } - - site = level.defuseobject; - - origin = ( site.curorigin[ 0 ], site.curorigin[ 1 ], site.curorigin[ 2 ] + 5 ); - - if ( site isInUse() ) // somebody is defusing - { - self BotNotifyBotEvent( "sd", "start", "defuser" ); - - self.bot_lock_goal = true; - - self SetScriptGoal( origin, 64 ); - - self thread bot_defend_site( site ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - self.bot_lock_goal = false; - - self BotNotifyBotEvent( "sd", "stop", "defuser" ); - return; - } - - // else hang around the site - if ( distancesquared( origin, self.origin ) <= 1024 * 1024 ) - { - return; - } - - self.bot_lock_goal = true; - self SetScriptGoal( origin, 256 ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - self.bot_lock_goal = false; - return; - } - - timeleft = maps\mp\gametypes\_gamelogic::gettimeremaining() / 1000; - timepassed = gettimepassed() / 1000; - - // dont have a bomb - if ( !self isBombCarrier() && !level.multibomb ) - { - if ( !isdefined( level.sdbomb ) ) - { - return; - } - - bomb = level.sdbomb; - carrier = level.sdbomb.carrier; - - // bomb is picked up - if ( isdefined( carrier ) ) - { - // escort the bomb carrier - if ( self HasScriptGoal() ) - { - return; - } - - origin = carrier.origin; - - if ( distancesquared( origin, self.origin ) <= 1024 * 1024 ) - { - return; - } - - self SetScriptGoal( origin, 256 ); - self thread bot_escort_obj( bomb, carrier ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - return; - } - - if ( !isdefined( bomb.bots ) ) - { - bomb.bots = 0; - } - - origin = ( bomb.curorigin[ 0 ], bomb.curorigin[ 1 ], bomb.curorigin[ 2 ] + 5 ); - - // hang around the bomb if other is going to go get it - if ( bomb.bots > 1 ) - { - if ( self HasScriptGoal() ) - { - return; - } - - if ( distancesquared( origin, self.origin ) <= 1024 * 1024 ) - { - return; - } - - self SetScriptGoal( origin, 256 ); - - self thread bot_get_obj( bomb ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - return; - } - - // go get the bomb - self BotNotifyBotEvent( "sd", "start", "bomb" ); - - self.bot_lock_goal = true; - self SetScriptGoal( origin, 64 ); - self thread bot_inc_bots( bomb ); - self thread bot_get_obj( bomb ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - self.bot_lock_goal = false; - - self BotNotifyBotEvent( "sd", "stop", "bomb" ); - return; - } - - // check if to plant - if ( timepassed < 120 && timeleft >= 90 && randomint( 100 ) < 98 ) - { - return; - } - - if ( !isdefined( level.bombzones ) || !level.bombzones.size ) - { - return; - } - - sites = []; - - for ( i = 0; i < level.bombzones.size; i++ ) - { - sites[ sites.size ] = level.bombzones[ i ]; - } - - if ( !sites.size ) - { - return; - } - - if ( data.rand > 50 ) - { - plant = self bot_array_nearest_curorigin( sites ); - } - else - { - plant = random( sites ); - } - - if ( !isdefined( plant ) ) - { - return; - } - - origin = ( plant.curorigin[ 0 ] + 50, plant.curorigin[ 1 ] + 50, plant.curorigin[ 2 ] + 5 ); - - self BotNotifyBotEvent( "sd", "go", "plant", plant ); - - self.bot_lock_goal = true; - self SetScriptGoal( origin, 1 ); - self thread bot_go_plant( plant ); - - event = self waittill_any_return( "goal", "bad_path", "new_goal" ); - - if ( event != "new_goal" ) - { - self ClearScriptGoal(); - } - - if ( event != "goal" || level.bombplanted || plant.visibleteam == "none" || !self istouching( plant.trigger ) || self inLastStand() || self hasThreat() || plant isInUse() ) - { - self.bot_lock_goal = false; - return; - } - - self BotNotifyBotEvent( "sd", "start", "plant", plant ); - - self BotRandomStance(); - self SetScriptGoal( self.origin, 64 ); - self bot_wait_stop_move(); - - waitTime = ( plant.usetime / 1000 ) + 2.5; - self thread BotPressUse( waitTime ); - wait waitTime; - - self ClearScriptGoal(); - self.bot_lock_goal = false; - - self BotNotifyBotEvent( "sd", "stop", "plant", plant ); -} - -/* - Bots play sd attackers -*/ -bot_sd_attackers() -{ - self endon( "death" ); - self endon( "disconnect" ); - level endon( "game_ended" ); - - if ( level.gametype != "sd" ) - { - return; - } - - if ( self.team != game[ "attackers" ] ) - { - return; - } - - data = spawnstruct(); - data.rand = self BotGetRandom(); - data.first = true; - - for ( ;; ) - { - self bot_sd_attackers_loop( data ); - } -} - -/* - Bots play capture the flag -*/ -bot_cap_loop() -{ - myTeam = self.pers[ "team" ]; - otherTeam = getotherteam( myTeam ); - - myflag = level.teamflags[ myTeam ]; - myzone = level.capzones[ myTeam ]; - - theirflag = level.teamflags[ otherTeam ]; - theirzone = level.capzones[ otherTeam ]; - - if ( !myflag maps\mp\gametypes\_gameobjects::ishome() ) - { - carrier = myflag.carrier; - - if ( !isdefined( carrier ) ) // someone doesnt has our flag - { - if ( !isdefined( theirflag.carrier ) && distancesquared( self.origin, theirflag.curorigin ) < distancesquared( self.origin, myflag.curorigin ) ) // no one has their flag and its closer - { - self BotNotifyBotEvent( "cap", "start", "their_flag", theirflag ); - - self bot_cap_get_flag( theirflag ); - - self BotNotifyBotEvent( "cap", "stop", "their_flag", theirflag ); - } - else // go get it - { - self BotNotifyBotEvent( "cap", "start", "my_flag", myflag ); - - self bot_cap_get_flag( myflag ); - - self BotNotifyBotEvent( "cap", "stop", "my_flag", myflag ); - } - - return; - } - else - { - if ( theirflag maps\mp\gametypes\_gameobjects::ishome() && randomint( 100 ) < 50 ) - { - // take their flag - self BotNotifyBotEvent( "cap", "start", "their_flag", theirflag ); - - self bot_cap_get_flag( theirflag ); - - self BotNotifyBotEvent( "cap", "stop", "their_flag", theirflag ); - } - else - { - if ( self HasScriptGoal() ) - { - return; - } - - if ( !isdefined( theirzone.bots ) ) - { - theirzone.bots = 0; - } - - origin = theirzone.curorigin; - - if ( theirzone.bots > 2 || randomint( 100 ) < 45 ) - { - // kill carrier - if ( carrier _hasperk( "specialty_coldblooded" ) ) - { - return; - } - - origin = carrier.origin; - - self SetScriptGoal( origin, 64 ); - self thread bot_escort_obj( myflag, carrier ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - return; - } - - self thread bot_inc_bots( theirzone ); - - // camp their zone - if ( distancesquared( origin, self.origin ) <= 1024 * 1024 ) - { - wait 4; - self notify( "bot_inc_bots" ); - theirzone.bots--; - return; - } - - self SetScriptGoal( origin, 256 ); - self thread bot_inc_bots( theirzone ); - self thread bot_escort_obj( myflag, carrier ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - } - } - } - else // our flag is ok - { - if ( self isFlagCarrier() ) // if have flag - { - // go cap - origin = myzone.curorigin; - - self BotNotifyBotEvent( "cap", "start", "cap" ); - - self.bot_lock_goal = true; - self SetScriptGoal( origin, 32 ); - - self thread bot_get_obj( myflag ); - evt = self waittill_any_return( "goal", "bad_path", "new_goal" ); - - wait 1; - - if ( evt != "new_goal" ) - { - self ClearScriptGoal(); - } - - self.bot_lock_goal = false; - - self BotNotifyBotEvent( "cap", "stop", "cap" ); - return; - } - - carrier = theirflag.carrier; - - if ( !isdefined( carrier ) ) // if no one has enemy flag - { - self BotNotifyBotEvent( "cap", "start", "their_flag", theirflag ); - - self bot_cap_get_flag( theirflag ); - - self BotNotifyBotEvent( "cap", "stop", "their_flag", theirflag ); - return; - } - - // escort them - - if ( self HasScriptGoal() ) - { - return; - } - - origin = carrier.origin; - - if ( distancesquared( origin, self.origin ) <= 1024 * 1024 ) - { - return; - } - - self SetScriptGoal( origin, 256 ); - self thread bot_escort_obj( theirflag, carrier ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - } -} - -/* - Bots play capture the flag -*/ -bot_cap() -{ - self endon( "death" ); - self endon( "disconnect" ); - level endon( "game_ended" ); - - if ( level.gametype != "ctf" ) - { - return; - } - - for ( ;; ) - { - wait( randomintrange( 3, 5 ) ); - - if ( self isusingremote() || self.bot_lock_goal ) - { - continue; - } - - if ( !isdefined( level.capzones ) ) - { - continue; - } - - if ( !isdefined( level.teamflags ) ) - { - continue; - } - - self bot_cap_loop(); - } -} - -/* - Gets the carriers ent num -*/ -getCarrierEntNum() -{ - carrierNum = -1; - - if ( isdefined( self.carrier ) ) - { - carrierNum = self.carrier getentitynumber(); - } - - return carrierNum; -} - -/* - Bots go and get the flag -*/ -bot_cap_get_flag( flag ) -{ - origin = flag.curorigin; - - // go get it - - self.bot_lock_goal = true; - self SetScriptGoal( origin, 32 ); - - self thread bot_get_obj( flag ); - - evt = self waittill_any_return( "goal", "bad_path", "new_goal" ); - - if ( evt != "new_goal" ) - { - self ClearScriptGoal(); - } - - if ( evt != "goal" ) - { - self.bot_lock_goal = false; - return; - } - - self SetScriptGoal( self.origin, 64 ); - curCarrier = flag getCarrierEntNum(); - - while ( curCarrier == flag getCarrierEntNum() && self istouching( flag.trigger ) ) - { - cur = flag.curprogress; - wait 0.5; - - if ( flag.curprogress == cur ) - { - break; // some enemy is near us, kill him - } - } - - self ClearScriptGoal(); - - self.bot_lock_goal = false; -} - -/* - Bots go plant the demo bomb -*/ -bot_dem_go_plant( plant ) -{ - self endon( "death" ); - self endon( "disconnect" ); - level endon( "game_ended" ); - self endon( "goal" ); - self endon( "bad_path" ); - self endon( "new_goal" ); - - for ( ;; ) - { - wait 0.5; - - if ( ( plant.label == "_b" && level.bombbplanted ) || ( plant.label == "_a" && level.bombaplanted ) ) - { - break; - } - - if ( self istouching( plant.trigger ) ) - { - break; - } - } - - if ( ( plant.label == "_b" && level.bombbplanted ) || ( plant.label == "_a" && level.bombaplanted ) ) - { - self notify( "bad_path" ); - } - else - { - self notify( "goal" ); - } -} - -/* - Bots spawn kill dom attackers -*/ -bot_dem_attack_spawnkill() -{ - self endon( "death" ); - self endon( "disconnect" ); - level endon( "game_ended" ); - self endon( "goal" ); - self endon( "bad_path" ); - self endon( "new_goal" ); - - l1 = level.bombaplanted; - l2 = level.bombbplanted; - - for ( ;; ) - { - wait 0.5; - - if ( l1 != level.bombaplanted || l2 != level.bombbplanted ) - { - break; - } - } - - self notify( "bad_path" ); -} - -/* - Bots play demo attackers -*/ -bot_dem_attackers_loop() -{ - myTeam = self.pers[ "team" ]; - otherTeam = getotherteam( myTeam ); - - bombs = []; // sites with bombs - sites = []; // sites to bomb at - bombed = 0; // exploded sites - - for ( i = 0; i < level.bombzones.size; i++ ) - { - bomb = level.bombzones[ i ]; - - if ( isdefined( bomb.bombexploded ) && bomb.bombexploded ) - { - bombed++; - continue; - } - - if ( bomb.label == "_a" ) - { - if ( level.bombaplanted ) - { - bombs[ bombs.size ] = bomb; - } - else - { - sites[ sites.size ] = bomb; - } - - continue; - } - - if ( bomb.label == "_b" ) - { - if ( level.bombbplanted ) - { - bombs[ bombs.size ] = bomb; - } - else - { - sites[ sites.size ] = bomb; - } - - continue; - } - } - - timeleft = maps\mp\gametypes\_gamelogic::gettimeremaining() / 1000; - - shouldLet = ( game[ "teamScores" ][ myTeam ] > game[ "teamScores" ][ otherTeam ] && timeleft < 90 && bombed == 1 ); - - // spawnkill conditions - // if we have bombed one site or 1 bomb is planted with lots of time left, spawn kill - // if we want the other team to win for overtime and they do not need to defuse, spawn kill - if ( ( ( bombed + bombs.size == 1 && timeleft >= 90 ) || ( shouldLet && !bombs.size ) ) && randomint( 100 ) < 95 ) - { - if ( self HasScriptGoal() ) - { - return; - } - - spawnPoints = maps\mp\gametypes\_spawnlogic::getspawnpointarray( "mp_dd_spawn_defender_start" ); - - if ( !spawnPoints.size ) - { - return; - } - - spawnpoint = maps\mp\gametypes\_spawnlogic::getspawnpoint_random( spawnPoints ); - - if ( distancesquared( spawnpoint.origin, self.origin ) <= 2048 * 2048 ) - { - return; - } - - self SetScriptGoal( spawnpoint.origin, 1024 ); - - self thread bot_dem_attack_spawnkill(); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - return; - } - - // let defuse conditions - // if enemy is going to lose and lots of time left, let them defuse to play longer - // or if want to go into overtime near end of the extended game - if ( ( ( bombs.size + bombed == 2 && timeleft >= 90 ) || ( shouldLet && bombs.size ) ) && randomint( 100 ) < 95 ) - { - spawnPoints = maps\mp\gametypes\_spawnlogic::getspawnpointarray( "mp_dd_spawn_attacker_start" ); - - if ( !spawnPoints.size ) - { - return; - } - - spawnpoint = maps\mp\gametypes\_spawnlogic::getspawnpoint_random( spawnPoints ); - - if ( distancesquared( spawnpoint.origin, self.origin ) <= 1024 * 1024 ) - { - return; - } - - self.bot_lock_goal = true; - self SetScriptGoal( spawnpoint.origin, 512 ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - self.bot_lock_goal = false; - return; - } - - // defend bomb conditions - // if time is running out and we have a bomb planted - if ( bombs.size && timeleft < 90 && ( !sites.size || randomint( 100 ) < 95 ) ) - { - site = self bot_array_nearest_curorigin( bombs ); - origin = ( site.curorigin[ 0 ] + 50, site.curorigin[ 1 ] + 50, site.curorigin[ 2 ] + 5 ); - - if ( site isInUse() ) // somebody is defusing - { - self BotNotifyBotEvent( "dem", "start", "defuser", site ); - - self.bot_lock_goal = true; - self SetScriptGoal( origin, 64 ); - - self thread bot_defend_site( site ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - self.bot_lock_goal = false; - - self BotNotifyBotEvent( "dem", "stop", "defuser", site ); - return; - } - - // else hang around the site - if ( distancesquared( origin, self.origin ) <= 1024 * 1024 ) - { - return; - } - - self.bot_lock_goal = true; - self SetScriptGoal( origin, 256 ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - self.bot_lock_goal = false; - return; - } - - // else go plant - if ( !sites.size ) - { - return; - } - - plant = self bot_array_nearest_curorigin( sites ); - - if ( !isdefined( plant ) ) - { - return; - } - - if ( !isdefined( plant.bots ) ) - { - plant.bots = 0; - } - - origin = ( plant.curorigin[ 0 ] + 50, plant.curorigin[ 1 ] + 50, plant.curorigin[ 2 ] + 5 ); - - // hang around the site if lots of time left - if ( plant.bots > 1 && timeleft >= 60 ) - { - if ( self HasScriptGoal() ) - { - return; - } - - if ( distancesquared( origin, self.origin ) <= 1024 * 1024 ) - { - return; - } - - self SetScriptGoal( origin, 256 ); - self thread bot_dem_go_plant( plant ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - return; - } - - self BotNotifyBotEvent( "dem", "go", "plant", plant ); - - self.bot_lock_goal = true; - - self SetScriptGoal( origin, 1 ); - self thread bot_inc_bots( plant ); - self thread bot_dem_go_plant( plant ); - - event = self waittill_any_return( "goal", "bad_path", "new_goal" ); - - if ( event != "new_goal" ) - { - self ClearScriptGoal(); - } - - if ( event != "goal" || ( plant.label == "_b" && level.bombbplanted ) || ( plant.label == "_a" && level.bombaplanted ) || plant isInUse() || !self istouching( plant.trigger ) || self inLastStand() || self hasThreat() ) - { - self.bot_lock_goal = false; - return; - } - - self BotNotifyBotEvent( "dem", "start", "plant", plant ); - - self BotRandomStance(); - self SetScriptGoal( self.origin, 64 ); - self bot_wait_stop_move(); - - waitTime = ( plant.usetime / 1000 ) + 2.5; - self thread BotPressUse( waitTime ); - wait waitTime; - - self ClearScriptGoal(); - - self.bot_lock_goal = false; - - self BotNotifyBotEvent( "dem", "stop", "plant", plant ); -} - -/* - Bots play demo attackers -*/ -bot_dem_attackers() -{ - self endon( "death" ); - self endon( "disconnect" ); - level endon( "game_ended" ); - - if ( level.gametype != "dd" ) - { - return; - } - - if ( self.team != game[ "attackers" ] ) - { - return; - } - - for ( ;; ) - { - wait( randomintrange( 3, 5 ) ); - - if ( self isusingremote() || self.bot_lock_goal ) - { - continue; - } - - if ( !isdefined( level.bombzones ) || !level.bombzones.size ) - { - continue; - } - - self bot_dem_attackers_loop(); - } -} - -/* - Bots play demo defenders -*/ -bot_dem_defenders_loop() -{ - myTeam = self.pers[ "team" ]; - otherTeam = getotherteam( myTeam ); - - bombs = []; // sites with bombs - sites = []; // sites to bomb at - bombed = 0; // exploded sites - - for ( i = 0; i < level.bombzones.size; i++ ) - { - bomb = level.bombzones[ i ]; - - if ( isdefined( bomb.bombexploded ) && bomb.bombexploded ) - { - bombed++; - continue; - } - - if ( bomb.label == "_a" ) - { - if ( level.bombaplanted ) - { - bombs[ bombs.size ] = bomb; - } - else - { - sites[ sites.size ] = bomb; - } - - continue; - } - - if ( bomb.label == "_b" ) - { - if ( level.bombbplanted ) - { - bombs[ bombs.size ] = bomb; - } - else - { - sites[ sites.size ] = bomb; - } - - continue; - } - } - - timeleft = maps\mp\gametypes\_gamelogic::gettimeremaining() / 1000; - - shouldLet = ( timeleft < 60 && ( ( bombed == 0 && bombs.size != 2 ) || ( game[ "teamScores" ][ myTeam ] > game[ "teamScores" ][ otherTeam ] && bombed == 1 ) ) && randomint( 100 ) < 98 ); - - // spawnkill conditions - // if nothing to defuse with a lot of time left, spawn kill - // or letting a bomb site to explode but a bomb is planted, so spawnkill - if ( ( !bombs.size && timeleft >= 60 && randomint( 100 ) < 95 ) || ( shouldLet && bombs.size == 1 ) ) - { - if ( self HasScriptGoal() ) - { - return; - } - - spawnPoints = maps\mp\gametypes\_spawnlogic::getspawnpointarray( "mp_dd_spawn_attacker_start" ); - - if ( !spawnPoints.size ) - { - return; - } - - spawnpoint = maps\mp\gametypes\_spawnlogic::getspawnpoint_random( spawnPoints ); - - if ( distancesquared( spawnpoint.origin, self.origin ) <= 2048 * 2048 ) - { - return; - } - - self SetScriptGoal( spawnpoint.origin, 1024 ); - - self thread bot_dem_defend_spawnkill(); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - return; - } - - // let blow up conditions - // let enemy blow up at least one to extend play time - // or if want to go into overtime after extended game - if ( shouldLet ) - { - spawnPoints = maps\mp\gametypes\_spawnlogic::getspawnpointarray( "mp_dd_spawn_defender_start" ); - - if ( !spawnPoints.size ) - { - return; - } - - spawnpoint = maps\mp\gametypes\_spawnlogic::getspawnpoint_random( spawnPoints ); - - if ( distancesquared( spawnpoint.origin, self.origin ) <= 1024 * 1024 ) - { - return; - } - - self.bot_lock_goal = true; - self SetScriptGoal( spawnpoint.origin, 512 ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - self.bot_lock_goal = false; - return; - } - - // defend conditions - // if no bombs planted with little time left - if ( !bombs.size && timeleft < 60 && randomint( 100 ) < 95 && sites.size ) - { - site = self bot_array_nearest_curorigin( sites ); - origin = ( site.curorigin[ 0 ] + 50, site.curorigin[ 1 ] + 50, site.curorigin[ 2 ] + 5 ); - - if ( site isInUse() ) // somebody is planting - { - self BotNotifyBotEvent( "dem", "start", "planter", site ); - - self.bot_lock_goal = true; - self SetScriptGoal( origin, 64 ); - - self thread bot_defend_site( site ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - self.bot_lock_goal = false; - - self BotNotifyBotEvent( "dem", "stop", "planter", site ); - return; - } - - // else hang around the site - - if ( distancesquared( origin, self.origin ) <= 1024 * 1024 ) - { - return; - } - - self.bot_lock_goal = true; - self SetScriptGoal( origin, 256 ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - self.bot_lock_goal = false; - return; - } - - // else go defuse - - if ( !bombs.size ) - { - return; - } - - defuse = self bot_array_nearest_curorigin( bombs ); - - if ( !isdefined( defuse ) ) - { - return; - } - - if ( !isdefined( defuse.bots ) ) - { - defuse.bots = 0; - } - - origin = ( defuse.curorigin[ 0 ] + 50, defuse.curorigin[ 1 ] + 50, defuse.curorigin[ 2 ] + 5 ); - - // hang around the site if not in danger of losing - if ( defuse.bots > 1 && bombed + bombs.size != 2 ) - { - if ( self HasScriptGoal() ) - { - return; - } - - if ( distancesquared( origin, self.origin ) <= 1024 * 1024 ) - { - return; - } - - self SetScriptGoal( origin, 256 ); - - self thread bot_dem_go_defuse( defuse ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - return; - } - - self BotNotifyBotEvent( "dem", "go", "defuse", defuse ); - - self.bot_lock_goal = true; - - self SetScriptGoal( origin, 1 ); - self thread bot_inc_bots( defuse ); - self thread bot_dem_go_defuse( defuse ); - - event = self waittill_any_return( "goal", "bad_path", "new_goal" ); - - if ( event != "new_goal" ) - { - self ClearScriptGoal(); - } - - if ( event != "goal" || ( defuse.label == "_b" && !level.bombbplanted ) || ( defuse.label == "_a" && !level.bombaplanted ) || defuse isInUse() || !self istouching( defuse.trigger ) || self inLastStand() || self hasThreat() ) - { - self.bot_lock_goal = false; - return; - } - - self BotNotifyBotEvent( "dem", "start", "defuse", defuse ); - - self BotRandomStance(); - self SetScriptGoal( self.origin, 64 ); - self bot_wait_stop_move(); - - waitTime = ( defuse.usetime / 1000 ) + 2.5; - self thread BotPressUse( waitTime ); - wait waitTime; - - self ClearScriptGoal(); - - self.bot_lock_goal = false; - - self BotNotifyBotEvent( "dem", "stop", "defuse", defuse ); -} - -/* - Bots play demo defenders -*/ -bot_dem_defenders() -{ - self endon( "death" ); - self endon( "disconnect" ); - level endon( "game_ended" ); - - if ( level.gametype != "dd" ) - { - return; - } - - if ( self.team == game[ "attackers" ] ) - { - return; - } - - for ( ;; ) - { - wait( randomintrange( 3, 5 ) ); - - if ( self isusingremote() || self.bot_lock_goal ) - { - continue; - } - - if ( !isdefined( level.bombzones ) || !level.bombzones.size ) - { - continue; - } - - self bot_dem_defenders_loop(); - } -} - -/* - Bots go defuse -*/ -bot_dem_go_defuse( defuse ) -{ - self endon( "death" ); - self endon( "disconnect" ); - level endon( "game_ended" ); - self endon( "goal" ); - self endon( "bad_path" ); - self endon( "new_goal" ); - - for ( ;; ) - { - wait 0.5; - - if ( self istouching( defuse.trigger ) ) - { - break; - } - - if ( ( defuse.label == "_b" && !level.bombbplanted ) || ( defuse.label == "_a" && !level.bombaplanted ) ) - { - break; - } - } - - if ( ( defuse.label == "_b" && !level.bombbplanted ) || ( defuse.label == "_a" && !level.bombaplanted ) ) - { - self notify( "bad_path" ); - } - else - { - self notify( "goal" ); - } -} - -/* - Bots go spawn kill -*/ -bot_dem_defend_spawnkill() -{ - self endon( "death" ); - self endon( "disconnect" ); - level endon( "game_ended" ); - self endon( "goal" ); - self endon( "bad_path" ); - self endon( "new_goal" ); - - for ( ;; ) - { - wait 0.5; - - if ( level.bombbplanted || level.bombaplanted ) - { - break; - } - } - - self notify( "bad_path" ); -} - -/* - Bots think to revive -*/ -bot_think_revive_loop() -{ - needsRevives = []; - - for ( i = 0; i < level.players.size; i++ ) - { - player = level.players[ i ]; - - if ( player.team != self.team ) - { - continue; - } - - if ( distancesquared( self.origin, player.origin ) >= 2048 * 2048 ) - { - continue; - } - - if ( player inLastStand() ) - { - needsRevives[ needsRevives.size ] = player; - } - } - - if ( !needsRevives.size ) - { - return; - } - - revive = random( needsRevives ); - - self BotNotifyBotEvent( "revive", "go", revive ); - self.bot_lock_goal = true; - - self SetScriptGoal( revive.origin, 64 ); - self thread stop_go_target_on_death( revive ); - - ret = self waittill_any_return( "new_goal", "goal", "bad_path" ); - - if ( ret != "new_goal" ) - { - self ClearScriptGoal(); - } - - self.bot_lock_goal = false; - - if ( ret != "goal" || !isdefined( revive ) || distancesquared( self.origin, revive.origin ) >= 100 * 100 || !revive inLastStand() || revive isBeingRevived() || !isalive( revive ) ) - { - return; - } - - self BotNotifyBotEvent( "revive", "start", revive ); - - self BotFreezeControls( true ); - self bot_wait_stop_move(); - - waitTime = 3.25; - self thread BotPressUse( waitTime ); - wait waitTime; - - self BotFreezeControls( false ); - - self BotNotifyBotEvent( "revive", "stop", revive ); -} - -/* - Bots think to revive -*/ -bot_think_revive() -{ - self endon( "death" ); - self endon( "disconnect" ); - level endon( "game_ended" ); - - if ( !level.diehardmode || !level.teambased ) - { - return; - } - - for ( ;; ) - { - wait( randomintrange( 1, 3 ) ); - - if ( self HasScriptGoal() || self.bot_lock_goal ) - { - continue; - } - - if ( self isDefusing() || self isPlanting() ) - { - continue; - } - - if ( self isusingremote() || self BotIsFrozen() ) - { - continue; - } - - if ( self inLastStand() ) - { - continue; - } - - self bot_think_revive_loop(); - } -} - -/* - Bots play the Global thermonuclear warfare -*/ -bot_gtnw_loop() -{ - myTeam = self.team; - theirteam = getotherteam( myTeam ); - origin = level.nukesite.trigger.origin; - trigger = level.nukesite.trigger; - - ourCapCount = level.nukesite.touchlist[ myTeam ]; - theirCapCount = level.nukesite.touchlist[ theirteam ]; - rand = self BotGetRandom(); - - if ( ( !ourCapCount && !theirCapCount ) || rand <= 20 ) - { - // go cap the obj - self BotNotifyBotEvent( "gtnw", "go", "cap" ); - - self.bot_lock_goal = true; - self SetScriptGoal( origin, 64 ); - self thread bots_watch_touch_obj( trigger ); - - ret = self waittill_any_return( "goal", "bad_path", "new_goal" ); - - if ( ret != "new_goal" ) - { - self ClearScriptGoal(); - } - - if ( ret != "goal" || !self istouching( trigger ) ) - { - self.bot_lock_goal = false; - return; - } - - self BotNotifyBotEvent( "gtnw", "start", "cap" ); - - self SetScriptGoal( self.origin, 64 ); - - while ( self istouching( trigger ) ) - { - cur = level.nukesite.curprogress; - wait 0.5; - - if ( cur == level.nukesite.curprogress ) - { - break; // no prog made, enemy must be capping - } - - self thread bot_do_random_action_for_objective( trigger ); - } - - self ClearScriptGoal(); - self.bot_lock_goal = false; - - self BotNotifyBotEvent( "gtnw", "stop", "cap" ); - return; - } - - if ( theirCapCount ) - { - // kill capturtour - self.bot_lock_goal = true; - - self SetScriptGoal( origin, 64 ); - self thread bots_watch_touch_obj( trigger ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - self.bot_lock_goal = false; - return; - } - - // else hang around the site - if ( distancesquared( origin, self.origin ) <= 1024 * 1024 ) - { - return; - } - - self.bot_lock_goal = true; - self SetScriptGoal( origin, 256 ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - self.bot_lock_goal = false; -} - -/* - Bots play the Global thermonuclear warfare -*/ -bot_gtnw() -{ - self endon( "death" ); - self endon( "disconnect" ); - level endon( "game_ended" ); - - if ( level.gametype != "gtnw" ) - { - return; - } - - for ( ;; ) - { - wait( randomintrange( 3, 5 ) ); - - if ( self isusingremote() || self.bot_lock_goal ) - { - continue; - } - - if ( !isdefined( level.nukesite ) || !isdefined( level.nukesite.trigger ) ) - { - continue; - } - - self bot_gtnw_loop(); - } -} - -/* - Bots play oneflag -*/ -bot_oneflag_loop() -{ - myTeam = self.pers[ "team" ]; - otherTeam = getotherteam( myTeam ); - - if ( myTeam == game[ "attackers" ] ) - { - myzone = level.capzones[ myTeam ]; - theirflag = level.teamflags[ otherTeam ]; - - if ( self isFlagCarrier() ) - { - // go cap - origin = myzone.curorigin; - - self BotNotifyBotEvent( "oneflag", "start", "cap" ); - - self.bot_lock_goal = true; - self SetScriptGoal( origin, 32 ); - - evt = self waittill_any_return( "goal", "bad_path", "new_goal" ); - - wait 1; - - if ( evt != "new_goal" ) - { - self ClearScriptGoal(); - } - - self.bot_lock_goal = false; - - self BotNotifyBotEvent( "oneflag", "stop", "cap" ); - return; - } - - carrier = theirflag.carrier; - - if ( !isdefined( carrier ) ) // if no one has enemy flag - { - self BotNotifyBotEvent( "oneflag", "start", "their_flag" ); - self bot_cap_get_flag( theirflag ); - self BotNotifyBotEvent( "oneflag", "stop", "their_flag" ); - return; - } - - // escort them - - if ( self HasScriptGoal() ) - { - return; - } - - origin = carrier.origin; - - if ( distancesquared( origin, self.origin ) <= 1024 * 1024 ) - { - return; - } - - self SetScriptGoal( origin, 256 ); - self thread bot_escort_obj( theirflag, carrier ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - } - else - { - myflag = level.teamflags[ myTeam ]; - theirzone = level.capzones[ otherTeam ]; - - if ( !myflag maps\mp\gametypes\_gameobjects::ishome() ) - { - carrier = myflag.carrier; - - if ( !isdefined( carrier ) ) // someone doesnt has our flag - { - self BotNotifyBotEvent( "oneflag", "start", "my_flag" ); - self bot_cap_get_flag( myflag ); - self BotNotifyBotEvent( "oneflag", "stop", "my_flag" ); - return; - } - - if ( self HasScriptGoal() ) - { - return; - } - - if ( !isdefined( theirzone.bots ) ) - { - theirzone.bots = 0; - } - - origin = theirzone.curorigin; - - if ( theirzone.bots > 2 || randomint( 100 ) < 45 ) - { - // kill carrier - if ( carrier _hasperk( "specialty_coldblooded" ) ) - { - return; - } - - origin = carrier.origin; - - self SetScriptGoal( origin, 64 ); - self thread bot_escort_obj( myflag, carrier ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - - return; - } - - self thread bot_inc_bots( theirzone ); - - // camp their zone - if ( distancesquared( origin, self.origin ) <= 1024 * 1024 ) - { - wait 4; - self notify( "bot_inc_bots" ); - theirzone.bots--; - return; - } - - self SetScriptGoal( origin, 256 ); - self thread bot_inc_bots( theirzone ); - self thread bot_escort_obj( myflag, carrier ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - } - else - { - // is home, lets hang around and protect - if ( self HasScriptGoal() ) - { - return; - } - - origin = myflag.curorigin; - - if ( distancesquared( origin, self.origin ) <= 1024 * 1024 ) - { - return; - } - - self SetScriptGoal( origin, 256 ); - self thread bot_get_obj( myflag ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - } - } -} - -/* - Bots play oneflag -*/ -bot_oneflag() -{ - self endon( "death" ); - self endon( "disconnect" ); - level endon( "game_ended" ); - - if ( level.gametype != "oneflag" ) - { - return; - } - - for ( ;; ) - { - wait( randomintrange( 3, 5 ) ); - - if ( self isusingremote() || self.bot_lock_goal ) - { - continue; - } - - if ( !isdefined( level.capzones ) || !isdefined( level.teamflags ) ) - { - continue; - } - - self bot_oneflag_loop(); - } -} - -/* - Bots play arena -*/ -bot_arena_loop() -{ - flag = level.arenaflag; - myTeam = self.team; - - self BotNotifyBotEvent( "arena", "go", "cap" ); - - self.bot_lock_goal = true; - self SetScriptGoal( flag.trigger.origin, 64 ); - - event = self waittill_any_return( "goal", "bad_path", "new_goal" ); - - if ( event != "new_goal" ) - { - self ClearScriptGoal(); - } - - if ( event != "goal" || !self istouching( flag.trigger ) ) - { - self.bot_lock_goal = false; - return; - } - - self BotNotifyBotEvent( "arena", "start", "cap" ); - - self SetScriptGoal( self.origin, 64 ); - - while ( self istouching( flag.trigger ) && flag.ownerteam != myTeam ) - { - cur = flag.curprogress; - wait 0.5; - - if ( cur == flag.curprogress ) - { - break; // no prog made, enemy must be capping - } - - self thread bot_do_random_action_for_objective( flag.trigger ); - } - - self ClearScriptGoal(); - self.bot_lock_goal = false; - - self BotNotifyBotEvent( "arena", "stop", "cap" ); -} - -/* - Bots play arena -*/ -bot_arena() -{ - self endon( "death" ); - self endon( "disconnect" ); - level endon( "game_ended" ); - - if ( level.gametype != "arena" ) - { - return; - } - - for ( ;; ) - { - wait( randomintrange( 3, 5 ) ); - - if ( self isusingremote() || self.bot_lock_goal ) - { - continue; - } - - if ( !isdefined( level.arenaflag ) ) - { - continue; - } - - self bot_arena_loop(); - } -} - -/* - bot_vip_loop - - For those wondering why i call a function for these loops like this - its because, the variables created in this function will be free'd once the function exits, - if it was in the infinite loop, the function never exits, thus the variables are never free'd - - This isnt leaking variables, but freeing variables that will no longer be used, an optimization of sorts -*/ -bot_vip_loop() -{ - vip = undefined; - - for ( i = 0; i < level.players.size; i++ ) - { - player = level.players[ i ]; - - if ( !isreallyalive( player ) ) - { - continue; - } - - if ( isdefined( player.isvip ) && player.isvip ) - { - vip = player; - } - } - - if ( self.team == game[ "defenders" ] ) - { - if ( isdefined( self.isvip ) && self.isvip ) - { - if ( isdefined( level.extractionzone ) && !isdefined( level.extractiontime ) ) - { - // go to extraction zone - self BotNotifyBotEvent( "vip", "start", "cap" ); - - self.bot_lock_goal = true; - self SetScriptGoal( level.extractionzone.trigger.origin, 32 ); - - evt = self waittill_any_return( "goal", "bad_path", "new_goal" ); - - wait 1; - - if ( evt != "new_goal" ) - { - self ClearScriptGoal(); - } - - self.bot_lock_goal = false; - - self BotNotifyBotEvent( "vip", "stop", "cap" ); - } - } - else if ( isdefined( vip ) ) - { - // protect the vip - if ( distancesquared( vip.origin, self.origin ) <= 1024 * 1024 ) - { - return; - } - - self SetScriptGoal( vip.origin, 256 ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - } - } - else - { - if ( isdefined( level.extractionzone ) && !isdefined( level.extractiontime ) && self BotGetRandom() < 65 ) - { - // camp the extraction zone - if ( distancesquared( level.extractionzone.trigger.origin, self.origin ) <= 1024 * 1024 ) - { - return; - } - - self SetScriptGoal( level.extractionzone.trigger.origin, 256 ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - } - else if ( isdefined( vip ) ) - { - // kill the vip - self SetScriptGoal( vip.origin, 32 ); - - if ( self waittill_any_return( "goal", "bad_path", "new_goal" ) != "new_goal" ) - { - self ClearScriptGoal(); - } - } - } -} - -/* - Bots play arena -*/ -bot_vip() -{ - self endon( "death" ); - self endon( "disconnect" ); - level endon( "game_ended" ); - - if ( level.gametype != "vip" ) - { - return; - } - - for ( ;; ) - { - wait( randomintrange( 3, 5 ) ); - - if ( self isusingremote() || self.bot_lock_goal ) - { - continue; - } - - self bot_vip_loop(); - } -} diff --git a/maps/mp/bots/_bot_utility.gsc b/maps/mp/bots/_bot_utility.gsc deleted file mode 100644 index 72dae8a..0000000 --- a/maps/mp/bots/_bot_utility.gsc +++ /dev/null @@ -1,3537 +0,0 @@ -/* - _bot_utility - Author: INeedGames - Date: 09/26/2020 - The shared functions for bots - - Notes for engine - obv the old bot behavior should be changed to use gsc built-ins to control bots - bots using objects needs to be fixed - setSpawnWeapon and switchtoweapon should be modified to work for testclients -*/ - -#include common_scripts\utility; -#include maps\mp\_utility; -#include maps\mp\gametypes\_hud_util; - -/* - Waits for the built-ins to be defined -*/ -wait_for_builtins() -{ - for ( i = 0; i < 20; i++ ) - { - if ( isdefined( level.bot_builtins ) ) - { - return true; - } - - if ( i < 18 ) - { - waittillframeend; - } - else - { - wait 0.05; - } - } - - return false; -} - -/* - Prints to console without dev script on -*/ -BotBuiltinPrintConsole( s ) -{ - if ( isdefined( level.bot_builtins ) && isdefined( level.bot_builtins[ "printconsole" ] ) ) - { - [[ level.bot_builtins[ "printconsole" ] ]]( s ); - } -} - -/* - Writes to the file, mode can be "append" or "write" -*/ -BotBuiltinFileWrite( file, contents, mode ) -{ - if ( isdefined( level.bot_builtins ) && isdefined( level.bot_builtins[ "filewrite" ] ) ) - { - [[ level.bot_builtins[ "filewrite" ] ]]( file, contents, mode ); - } -} - -/* - Returns the whole file as a string -*/ -BotBuiltinFileRead( file ) -{ - if ( isdefined( level.bot_builtins ) && isdefined( level.bot_builtins[ "fileread" ] ) ) - { - return [[ level.bot_builtins[ "fileread" ] ]]( file ); - } - - return undefined; -} - -/* - Test if a file exists -*/ -BotBuiltinFileExists( file ) -{ - if ( isdefined( level.bot_builtins ) && isdefined( level.bot_builtins[ "fileexists" ] ) ) - { - return [[ level.bot_builtins[ "fileexists" ] ]]( file ); - } - - return false; -} - -/* - Bot action, does a bot action - botaction() -*/ -BotBuiltinBotAction( action ) -{ - if ( isdefined( level.bot_builtins ) && isdefined( level.bot_builtins[ "botaction" ] ) ) - { - self [[ level.bot_builtins[ "botaction" ] ]]( action ); - } -} - -/* - Clears the bot from movement and actions - botstop() -*/ -BotBuiltinBotStop() -{ - if ( isdefined( level.bot_builtins ) && isdefined( level.bot_builtins[ "botstop" ] ) ) - { - self [[ level.bot_builtins[ "botstop" ] ]](); - } -} - -/* - Sets the bot's movement - botmovement(, ) -*/ -BotBuiltinBotMovement( forward, right ) -{ - if ( isdefined( level.bot_builtins ) && isdefined( level.bot_builtins[ "botmovement" ] ) ) - { - self [[ level.bot_builtins[ "botmovement" ] ]]( forward, right ); - } -} - -/* - Sets melee params -*/ -BotBuiltinBotMeleeParams( yaw, dist ) -{ - if ( isdefined( level.bot_builtins ) && isdefined( level.bot_builtins[ "botmeleeparams" ] ) ) - { - self [[ level.bot_builtins[ "botmeleeparams" ] ]]( yaw, dist ); - } -} - -/* - Sets remote angles -*/ -BotBuiltinBotRemoteAngles( pitch, yaw ) -{ - if ( isdefined( level.bot_builtins ) && isdefined( level.bot_builtins[ "botremoteangles" ] ) ) - { - self [[ level.bot_builtins[ "botremoteangles" ] ]]( pitch, yaw ); - } -} - -/* - Sets angles -*/ -BotBuiltinBotAngles( angles ) -{ - if ( isdefined( level.bot_builtins ) && isdefined( level.bot_builtins[ "botangles" ] ) ) - { - self [[ level.bot_builtins[ "botangles" ] ]]( angles ); - } -} - -/* - Returns if player is the host -*/ -is_host() -{ - return ( isdefined( self.pers[ "bot_host" ] ) && self.pers[ "bot_host" ] ); -} - -/* - Setups the host variable on the player -*/ -doHostCheck() -{ - self.pers[ "bot_host" ] = false; - - if ( self is_bot() ) - { - return; - } - - result = false; - - if ( getdvar( "bots_main_firstIsHost" ) != "0" ) - { - BotBuiltinPrintConsole( "WARNING: bots_main_firstIsHost is enabled" ); - - if ( getdvar( "bots_main_firstIsHost" ) == "1" ) - { - setdvar( "bots_main_firstIsHost", self getguid() ); - } - - if ( getdvar( "bots_main_firstIsHost" ) == self getguid() + "" ) - { - result = true; - } - } - - DvarGUID = getdvar( "bots_main_GUIDs" ); - - if ( DvarGUID != "" ) - { - guids = strtok( DvarGUID, "," ); - - for ( i = 0; i < guids.size; i++ ) - { - if ( self getguid() + "" == guids[ i ] ) - { - result = true; - } - } - } - - if ( !self ishost() && !result ) - { - return; - } - - self.pers[ "bot_host" ] = true; -} - -/* - Returns if the player is a bot. -*/ -is_bot() -{ - assert( isdefined( self ) ); - assert( isplayer( self ) ); - - return ( ( isdefined( self.pers[ "isBot" ] ) && self.pers[ "isBot" ] ) || ( isdefined( self.pers[ "isBotWarfare" ] ) && self.pers[ "isBotWarfare" ] ) || issubstr( self getguid() + "", "bot" ) ); -} - -/* - Set the bot's stance -*/ -BotSetStance( stance ) -{ - switch ( stance ) - { - case "stand": - self maps\mp\bots\_bot_internal::stand(); - break; - - case "crouch": - self maps\mp\bots\_bot_internal::crouch(); - break; - - case "prone": - self maps\mp\bots\_bot_internal::prone(); - break; - } -} - -/* - Bot presses the frag button for time. -*/ -BotPressFrag( time ) -{ - self maps\mp\bots\_bot_internal::frag( time ); -} - -/* - Bot presses the smoke button for time. -*/ -BotPressSmoke( time ) -{ - self maps\mp\bots\_bot_internal::smoke( time ); -} - -/* - Bot will press the ads button for the time -*/ -BotpressADS( time ) -{ - self maps\mp\bots\_bot_internal::pressADS( time ); -} - -/* - Bot presses the use button for time. -*/ -BotPressUse( time ) -{ - self maps\mp\bots\_bot_internal::use( time ); -} - -/* - Bots will press the attack button for a time -*/ -BotPressAttack( time ) -{ - self maps\mp\bots\_bot_internal::pressFire( time ); -} - -/* - Returns a random number thats different everytime it changes target -*/ -BotGetTargetRandom() -{ - if ( !isdefined( self.bot.target ) ) - { - return undefined; - } - - return self.bot.target.rand; -} - -/* - Returns the bot's random assigned number. -*/ -BotGetRandom() -{ - return self.bot.rand; -} - -/* - Returns if the bot is pressing frag button. -*/ -IsBotFragging() -{ - return self.bot.isfraggingafter; -} - -/* - Returns if the bot is pressing smoke button. -*/ -IsBotSmoking() -{ - return self.bot.issmokingafter; -} - -/* - Returns if the bot is sprinting. -*/ -IsBotSprinting() -{ - return self.bot.issprinting; -} - -/* - Returns if the bot is reloading. -*/ -IsBotReloading() -{ - return self.bot.isreloading; -} - -/* - Is bot knifing -*/ -IsBotKnifing() -{ - return self.bot.isknifingafter; -} - -/* - Freezes the bot's controls. -*/ -BotFreezeControls( what ) -{ - self.bot.isfrozen = what; - - if ( what ) - { - self notify( "kill_goal" ); - } -} - -/* - Returns if the bot is script frozen. -*/ -BotIsFrozen() -{ - return self.bot.isfrozen; -} - -/* - Bot will stop moving -*/ -BotStopMoving( what ) -{ - self.bot.stop_move = what; - - if ( what ) - { - self notify( "kill_goal" ); - } -} - -/* - Waits till frame end so that if two notifies happen in the same frame, the other will not be missed. -*/ -BotNotifyBotEvent_( msg, a, b, c, d, e, f, g ) -{ - self endon( "disconnect" ); - waittillframeend; // wait for the waittills to setup again - self notify( "bot_event", msg, a, b, c, d, e, f, g ); -} - -/* - Notify the bot chat message -*/ -BotNotifyBotEvent( msg, a, b, c, d, e, f, g ) -{ - self thread BotNotifyBotEvent_( msg, a, b, c, d, e, f, g ); -} - -/* - Returns if the bot has a script goal. - (like t5 gsc bot) -*/ -HasScriptGoal() -{ - return ( isdefined( self GetScriptGoal() ) ); -} - -/* - Sets the bot's goal, will acheive it when dist away from it. -*/ -SetScriptGoal( goal, dist ) -{ - if ( !isdefined( dist ) ) - { - dist = 16; - } - - self.bot.script_goal = goal; - self.bot.script_goal_dist = dist; - waittillframeend; - self notify( "new_goal_internal" ); - self notify( "new_goal" ); -} - -/* - Returns the pos of the bot's goal -*/ -GetScriptGoal() -{ - return self.bot.script_goal; -} - -/* - Clears the bot's goal. -*/ -ClearScriptGoal() -{ - self SetScriptGoal( undefined, 0 ); -} - -/* - Returns the location of the bot's javelin target -*/ -HasBotJavelinLocation() -{ - return isdefined( self.bot.jav_loc ); -} - -/* - Returns whether the bot has a priority objective -*/ -HasPriorityObjective() -{ - return self.bot.prio_objective; -} - -/* - Sets the bot to prioritize the objective over targeting enemies -*/ -SetPriorityObjective() -{ - self.bot.prio_objective = true; - self notify( "kill_goal" ); -} - -/* - Clears the bot's priority objective to allow the bot to target enemies automatically again -*/ -ClearPriorityObjective() -{ - self.bot.prio_objective = false; - self notify( "kill_goal" ); -} - -/* - Sets the aim position of the bot -*/ -SetScriptAimPos( pos ) -{ - self.bot.script_aimpos = pos; -} - -/* - Clears the aim position of the bot -*/ -ClearScriptAimPos() -{ - self SetScriptAimPos( undefined ); -} - -/* - Returns the aim position of the bot -*/ -GetScriptAimPos() -{ - return self.bot.script_aimpos; -} - -/* - Returns if the bot has a aim pos -*/ -HasScriptAimPos() -{ - return isdefined( self GetScriptAimPos() ); -} - -/* - Sets the bot's javelin target location -*/ -SetBotJavelinLocation( loc ) -{ - self.bot.jav_loc = loc; - self notify( "new_enemy" ); -} - -/* - Clears the bot's javelin location -*/ -ClearBotJavelinLocation() -{ - self SetBotJavelinLocation( undefined ); -} - -/* - Sets the bot's target to be this ent. -*/ -setAttacker( att ) -{ - self.bot.target_this_frame = att; -} - -/* - Sets the script enemy for a bot. -*/ -SetScriptEnemy( enemy, offset ) -{ - self.bot.script_target = enemy; - self.bot.script_target_offset = offset; -} - -/* - Removes the script enemy of the bot. -*/ -ClearScriptEnemy() -{ - self SetScriptEnemy( undefined, undefined ); -} - -/* - Returns the entity of the bot's target. -*/ -getThreat() -{ - if ( !isdefined( self.bot.target ) ) - { - return undefined; - } - - return self.bot.target.entity; -} - -/* - Returns if the bot has a script enemy. -*/ -HasScriptEnemy() -{ - return ( isdefined( self.bot.script_target ) ); -} - -/* - Returns if the bot has a threat. -*/ -hasThreat() -{ - return ( isdefined( self getThreat() ) ); -} - -/* - If the player is defusing -*/ -isDefusing() -{ - return ( isdefined( self.isdefusing ) && self.isdefusing ); -} - -/* - If the play is planting -*/ -isPlanting() -{ - return ( isdefined( self.isplanting ) && self.isplanting ); -} - -/* - If the player is carrying a bomb -*/ -isBombCarrier() -{ - return ( isdefined( self.isbombcarrier ) && self.isbombcarrier ); -} - -/* - If the site is in use -*/ -isInUse() -{ - return ( isdefined( self.inuse ) && self.inuse ); -} - -/* - If the player is in laststand -*/ -inLastStand() -{ - return ( isdefined( self.laststand ) && self.laststand ); -} - -/* - Is being revived -*/ -isBeingRevived() -{ - return ( isdefined( self.beingrevived ) && self.beingrevived ); -} - -/* - If the player is in final stand -*/ -inFinalStand() -{ - return ( isdefined( self.infinalstand ) && self.infinalstand ); -} - -/* - If the player is the flag carrier -*/ -isFlagCarrier() -{ - return ( isdefined( self.carryflag ) && self.carryflag ); -} - -/* - Returns if we are stunned. -*/ -isStunned() -{ - return ( isdefined( self.concussionendtime ) && self.concussionendtime > gettime() ); -} - -/* - Returns if we are beingArtilleryShellshocked -*/ -isArtShocked() -{ - return ( isdefined( self.beingartilleryshellshocked ) && self.beingartilleryshellshocked ); -} - -/* - Returns a valid grenade launcher weapon -*/ -getValidTube() -{ - weaps = self getweaponslistall(); - - for ( i = 0; i < weaps.size; i++ ) - { - weap = weaps[ i ]; - - if ( !self getammocount( weap ) ) - { - continue; - } - - if ( ( issubstr( weap, "gl_" ) && !issubstr( weap, "_gl_" ) ) || weap == "m79_mp" ) - { - return weap; - } - } - - return undefined; -} - -/* - iw5 -*/ -allowClassChoiceUtil() -{ - entry = tablelookup( "mp/gametypesTable.csv", 0, level.gametype, 4 ); - - if ( !isdefined( entry ) || entry == "" ) - { - return true; - } - - return int( entry ); -} - -/* - iw5 -*/ -allowTeamChoiceUtil() -{ - entry = tablelookup( "mp/gametypesTable.csv", 0, level.gametype, 5 ); - - if ( !isdefined( entry ) || entry == "" ) - { - return true; - } - - return int( entry ); -} - -/* - helper -*/ -waittill_either_return_( str1, str2 ) -{ - self endon( str1 ); - self waittill( str2 ); - return true; -} - -/* - Returns which string gets notified first -*/ -waittill_either_return( str1, str2 ) -{ - if ( !isdefined( self waittill_either_return_( str1, str2 ) ) ) - { - return str1; - } - - return str2; -} - -/* - Returns a random grenade in the bot's inventory. -*/ -getValidGrenade() -{ - grenadeTypes = []; - grenadeTypes[ grenadeTypes.size ] = "frag_grenade_mp"; - grenadeTypes[ grenadeTypes.size ] = "smoke_grenade_mp"; - grenadeTypes[ grenadeTypes.size ] = "flash_grenade_mp"; - grenadeTypes[ grenadeTypes.size ] = "concussion_grenade_mp"; - grenadeTypes[ grenadeTypes.size ] = "semtex_mp"; - grenadeTypes[ grenadeTypes.size ] = "throwingknife_mp"; - - possibles = []; - - for ( i = 0; i < grenadeTypes.size; i++ ) - { - if ( !self hasweapon( grenadeTypes[ i ] ) ) - { - continue; - } - - if ( !self getammocount( grenadeTypes[ i ] ) ) - { - continue; - } - - possibles[ possibles.size ] = grenadeTypes[ i ]; - } - - return random( possibles ); -} - -/* - If the weapon is not a script weapon (bomb, killstreak, etc, grenades) -*/ -isWeaponPrimary( weap ) -{ - return ( maps\mp\gametypes\_weapons::isprimaryweapon( weap ) || maps\mp\gametypes\_weapons::isaltmodeweapon( weap ) ); -} - -/* - If the ent is a vehicle -*/ -entIsVehicle( ent ) -{ - return ( ent.classname == "script_vehicle" || ent.model == "vehicle_uav_static_mp" || ent.model == "vehicle_ac130_coop" ); -} - -/* - Returns if the given weapon is full auto. -*/ -WeaponIsFullAuto( weap ) -{ - weaptoks = strtok( weap, "_" ); - - assert( isdefined( weaptoks[ 0 ] ) ); - assert( isstring( weaptoks[ 0 ] ) ); - - return isdefined( level.bots_fullautoguns[ weaptoks[ 0 ] ] ); -} - -/* - If weap is a secondary gnade -*/ -isSecondaryGrenade( gnade ) -{ - return ( gnade == "concussion_grenade_mp" || gnade == "flash_grenade_mp" || gnade == "smoke_grenade_mp" ); -} - -/* - If the weapon is allowed to be dropped -*/ -isWeaponDroppable( weap ) -{ - return ( maps\mp\gametypes\_weapons::maydropweapon( weap ) ); -} - -/* - Does a notify after a delay -*/ -notifyAfterDelay( delay, not ) -{ - wait delay; - self notify( not ); -} - -/* - Returns a bot to be kicked -*/ -getBotToKick() -{ - bots = getBotArray(); - - if ( !isdefined( bots ) || !isdefined( bots.size ) || bots.size <= 0 || !isdefined( bots[ 0 ] ) ) - { - return undefined; - } - - tokick = undefined; - axis = 0; - allies = 0; - team = getdvar( "bots_team" ); - - // count teams - for ( i = 0; i < bots.size; i++ ) - { - bot = bots[ i ]; - - if ( !isdefined( bot ) || !isdefined( bot.team ) ) - { - continue; - } - - if ( bot.team == "allies" ) - { - allies++; - } - else if ( bot.team == "axis" ) - { - axis++; - } - else // choose bots that are not on a team first - { - return bot; - } - } - - // search for a bot on the other team - if ( team == "custom" || team == "axis" ) - { - team = "allies"; - } - else if ( team == "autoassign" ) - { - // get the team with the most bots - team = "allies"; - - if ( axis > allies ) - { - team = "axis"; - } - } - else - { - team = "axis"; - } - - // get the bot on this team with lowest skill - for ( i = 0; i < bots.size; i++ ) - { - bot = bots[ i ]; - - if ( !isdefined( bot ) || !isdefined( bot.team ) ) - { - continue; - } - - if ( bot.team != team ) - { - continue; - } - - if ( !isdefined( bot.pers ) || !isdefined( bot.pers[ "bots" ] ) || !isdefined( bot.pers[ "bots" ][ "skill" ] ) || !isdefined( bot.pers[ "bots" ][ "skill" ][ "base" ] ) ) - { - continue; - } - - if ( isdefined( tokick ) && bot.pers[ "bots" ][ "skill" ][ "base" ] > tokick.pers[ "bots" ][ "skill" ][ "base" ] ) - { - continue; - } - - tokick = bot; - } - - if ( isdefined( tokick ) ) - { - return tokick; - } - - // just kick lowest skill - for ( i = 0; i < bots.size; i++ ) - { - bot = bots[ i ]; - - if ( !isdefined( bot ) || !isdefined( bot.team ) ) - { - continue; - } - - if ( !isdefined( bot.pers ) || !isdefined( bot.pers[ "bots" ] ) || !isdefined( bot.pers[ "bots" ][ "skill" ] ) || !isdefined( bot.pers[ "bots" ][ "skill" ][ "base" ] ) ) - { - continue; - } - - if ( isdefined( tokick ) && bot.pers[ "bots" ][ "skill" ][ "base" ] > tokick.pers[ "bots" ][ "skill" ][ "base" ] ) - { - continue; - } - - tokick = bot; - } - - return tokick; -} - -/* - Gets a player who is host -*/ -GetHostPlayer() -{ - for ( i = 0; i < level.players.size; i++ ) - { - player = level.players[ i ]; - - if ( !player is_host() ) - { - continue; - } - - return player; - } - - return undefined; -} - -/* - Waits for a host player -*/ -bot_wait_for_host() -{ - host = undefined; - - while ( !isdefined( level ) || !isdefined( level.players ) ) - { - wait 0.05; - } - - for ( i = getdvarfloat( "bots_main_waitForHostTime" ); i > 0; i -= 0.05 ) - { - host = GetHostPlayer(); - - if ( isdefined( host ) ) - { - break; - } - - wait 0.05; - } - - if ( !isdefined( host ) ) - { - return; - } - - for ( i = getdvarfloat( "bots_main_waitForHostTime" ); i > 0; i -= 0.05 ) - { - if ( isdefined( host.pers[ "team" ] ) ) - { - break; - } - - wait 0.05; - } - - if ( !isdefined( host.pers[ "team" ] ) ) - { - return; - } - - for ( i = getdvarfloat( "bots_main_waitForHostTime" ); i > 0; i -= 0.05 ) - { - if ( host.pers[ "team" ] == "allies" || host.pers[ "team" ] == "axis" ) - { - break; - } - - wait 0.05; - } -} - -/* - Pezbot's line sphere intersection. - http://paulbourke.net/geometry/circlesphere/raysphere.c -*/ -RaySphereIntersect( start, end, spherePos, radius ) -{ - // check if the start or end points are in the sphere - r2 = radius * radius; - - if ( distancesquared( start, spherePos ) < r2 ) - { - return true; - } - - if ( distancesquared( end, spherePos ) < r2 ) - { - return true; - } - - // check if the line made by start and end intersect the sphere - dp = end - start; - a = dp[ 0 ] * dp[ 0 ] + dp[ 1 ] * dp[ 1 ] + dp[ 2 ] * dp[ 2 ]; - b = 2 * ( dp[ 0 ] * ( start[ 0 ] - spherePos[ 0 ] ) + dp[ 1 ] * ( start[ 1 ] - spherePos[ 1 ] ) + dp[ 2 ] * ( start[ 2 ] - spherePos[ 2 ] ) ); - c = spherePos[ 0 ] * spherePos[ 0 ] + spherePos[ 1 ] * spherePos[ 1 ] + spherePos[ 2 ] * spherePos[ 2 ]; - c += start[ 0 ] * start[ 0 ] + start[ 1 ] * start[ 1 ] + start[ 2 ] * start[ 2 ]; - c -= 2.0 * ( spherePos[ 0 ] * start[ 0 ] + spherePos[ 1 ] * start[ 1 ] + spherePos[ 2 ] * start[ 2 ] ); - c -= radius * radius; - bb4ac = b * b - 4.0 * a * c; - - if ( abs( a ) < 0.0001 || bb4ac < 0 ) - { - return false; - } - - mu1 = ( 0 - b + sqrt( bb4ac ) ) / ( 2 * a ); - // mu2 = (0-b - sqrt(bb4ac)) / (2 * a); - - // intersection points of the sphere - ip1 = start + mu1 * dp; - // ip2 = start + mu2 * dp; - - myDist = distancesquared( start, end ); - - // check if both intersection points far - if ( distancesquared( start, ip1 ) > myDist/* && distancesquared(start, ip2) > myDist*/ ) - { - return false; - } - - dpAngles = vectortoangles( dp ); - - // check if the point is behind us - if ( getConeDot( ip1, start, dpAngles ) < 0/* || getConeDot(ip2, start, dpAngles) < 0*/ ) - { - return false; - } - - return true; -} - -/* - Returns if a smoke grenade would intersect start to end line. -*/ -SmokeTrace( start, end, rad ) -{ - for ( i = level.bots_smokelist.count - 1; i >= 0; i-- ) - { - nade = level.bots_smokelist.data[ i ]; - - if ( nade.state != "smoking" ) - { - continue; - } - - if ( !RaySphereIntersect( start, end, nade.origin, rad ) ) - { - continue; - } - - return false; - } - - return true; -} - -/* - Returns the cone dot (like fov, or distance from the center of our screen). -*/ -getConeDot( to, from, dir ) -{ - dirToTarget = vectornormalize( to - from ); - forward = anglestoforward( dir ); - return vectordot( dirToTarget, forward ); -} - -/* - Returns the distance squared in a 2d space -*/ -distancesquared2D( to, from ) -{ - to = ( to[ 0 ], to[ 1 ], 0 ); - from = ( from[ 0 ], from[ 1 ], 0 ); - - return distancesquared( to, from ); -} - -/* - Rounds to the nearest whole number. -*/ -Round( x ) -{ - y = int( x ); - - if ( abs( x ) - abs( y ) > 0.5 ) - { - if ( x < 0 ) - { - return y - 1; - } - else - { - return y + 1; - } - } - else - { - return y; - } -} - -/* - converts a string into a float -*/ -float_old( num ) -{ - setdvar( "temp_dvar_bot_util", num ); - - return getdvarfloat( "temp_dvar_bot_util" ); -} - -/* - If the string starts with -*/ -isStrStart( string1, subStr ) -{ - return ( getsubstr( string1, 0, subStr.size ) == subStr ); -} - -/* - Parses tokens into a waypoint obj -*/ -parseTokensIntoWaypoint( tokens ) -{ - waypoint = spawnstruct(); - - orgStr = tokens[ 0 ]; - orgToks = strtok( orgStr, " " ); - waypoint.origin = ( float_old( orgToks[ 0 ] ), float_old( orgToks[ 1 ] ), float_old( 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, " " ); - - if ( anglesToks.size >= 3 ) - { - waypoint.angles = ( float_old( anglesToks[ 0 ] ), float_old( anglesToks[ 1 ] ), float_old( anglesToks[ 2 ] ) ); - } - } - - javStr = tokens[ 4 ]; - - if ( isdefined( javStr ) && javStr != "" ) - { - javToks = strtok( javStr, " " ); - - if ( javToks.size >= 3 ) - { - waypoint.jav_point = ( float_old( javToks[ 0 ] ), float_old( javToks[ 1 ] ), float_old( javToks[ 2 ] ) ); - } - } - - return waypoint; -} - -/* - Function to extract lines from a file specified by 'filename' and store them in a result structure. -*/ -getWaypointLinesFromFile( filename ) -{ - // Create a structure to store the result, including an array to hold individual lines. - result = spawnstruct(); - result.lines = []; - - // Read the entire content of the file into the 'waypointStr' variable. - // Note: max string length in GSC is 65535. - waypointStr = BotBuiltinFileRead( filename ); - - // If the file is empty or not defined, return the empty result structure. - if ( !isdefined( waypointStr ) ) - { - return result; - } - - // Variables to track the current line's character count and starting position. - linecount = 0; - linestart = 0; - - // Iterate through each character in the 'waypointStr'. - for ( i = 0; i < waypointStr.size; i++ ) - { - // Check for newline characters '\n' or '\r'. - if ( waypointStr[ i ] == "\n" || waypointStr[ i ] == "\r" ) - { - // Extract the current line using 'getsubstr' and store it in the result array. - result.lines[ result.lines.size ] = getsubstr( waypointStr, linestart, linestart + linecount ); - - // If the newline is '\r\n', skip the next character. - if ( waypointStr[ i ] == "\r" && i < waypointStr.size - 1 && waypointStr[ i + 1 ] == "\n" ) - { - i++; - } - - // Reset linecount and update linestart for the next line. - linecount = 0; - linestart = i + 1; - continue; - } - - // Increment linecount for the current line. - linecount++; - } - - // Store the last line (or the only line if there are no newline characters) in the result array. - result.lines[ result.lines.size ] = getsubstr( waypointStr, linestart, linestart + linecount ); - - // Return the result structure containing the array of extracted lines. - return result; -} - -/* - Loads waypoints from file -*/ -readWpsFromFile( mapname ) -{ - waypoints = []; - filename = "waypoints/" + mapname + "_wp.csv"; - - if ( !BotBuiltinFileExists( filename ) ) - { - return waypoints; - } - - res = getWaypointLinesFromFile( filename ); - - if ( !res.lines.size ) - { - return waypoints; - } - - BotBuiltinPrintConsole( "Attempting to read waypoints from " + filename ); - - waypointCount = int( res.lines[ 0 ] ); - - for ( i = 1; i <= waypointCount; i++ ) - { - tokens = strtok( res.lines[ i ], "," ); - - waypoint = parseTokensIntoWaypoint( tokens ); - - waypoints[ i - 1 ] = waypoint; - } - - return waypoints; -} - -/* - Loads the waypoints. Populating everything needed for the waypoints. -*/ -load_waypoints() -{ - level.waypointusage = []; - level.waypointusage[ "allies" ] = []; - level.waypointusage[ "axis" ] = []; - - if ( !isdefined( level.waypoints ) ) - { - level.waypoints = []; - } - - mapname = getdvar( "mapname" ); - - wps = readWpsFromFile( mapname ); - - if ( wps.size ) - { - level.waypoints = wps; - BotBuiltinPrintConsole( "Loaded " + wps.size + " waypoints from csv" ); - } - else - { - switch ( mapname ) - { - default: - maps\mp\bots\waypoints\_custom_map::main( mapname ); - break; - } - - if ( level.waypoints.size ) - { - BotBuiltinPrintConsole( "Loaded " + level.waypoints.size + " waypoints from script" ); - } - } - - if ( !level.waypoints.size ) - { - BotBuiltinPrintConsole( "No waypoints loaded!" ); - } - - for ( i = level.waypoints.size - 1; i >= 0; i-- ) - { - 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 = level.waypoints.size - 1; i >= 0; 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 ]; -} - -/* - Returns the friendly user name for a given map's codename -*/ -getMapName( mapname ) -{ - switch ( mapname ) - { - case "mp_abandon": - return "Carnival"; - - case "mp_rundown": - return "Rundown"; - - case "mp_afghan": - return "Afghan"; - - case "mp_boneyard": - return "Scrapyard"; - - case "mp_brecourt": - return "Wasteland"; - - case "mp_cargoship": - return "Wetwork"; - - case "mp_checkpoint": - return "Karachi"; - - case "mp_compact": - return "Salvage"; - - case "mp_complex": - return "Bailout"; - - case "mp_crash": - return "Crash"; - - case "mp_cross_fire": - return "Crossfire"; - - case "mp_derail": - return "Derail"; - - case "mp_estate": - return "Estate"; - - case "mp_favela": - return "Favela"; - - case "mp_fuel2": - return "Fuel"; - - case "mp_highrise": - return "Highrise"; - - case "mp_invasion": - return "Invasion"; - - case "mp_killhouse": - return "Killhouse"; - - case "mp_nightshift": - return "Skidrow"; - - case "mp_nuked": - return "Nuketown"; - - case "oilrig": - return "Oilrig"; - - case "mp_quarry": - return "Quarry"; - - case "mp_rust": - return "Rust"; - - case "mp_storm": - return "Storm"; - - case "mp_strike": - return "Strike"; - - case "mp_subbase": - return "Subbase"; - - case "mp_terminal": - return "Terminal"; - - case "mp_trailerpark": - return "Trailer Park"; - - case "mp_overgrown": - return "Overgrown"; - - case "mp_underpass": - return "Underpass"; - - case "mp_vacant": - return "Vacant"; - - case "iw4_credits": - return "IW4 Test Map"; - - case "airport": - return "Airport"; - - case "co_hunted": - return "Hunted"; - - case "invasion": - return "Burgertown"; - - case "mp_bloc": - return "Bloc"; - - case "mp_bog_sh": - return "Bog"; - - case "contingency": - return "Contingency"; - - case "gulag": - return "Gulag"; - - case "so_ghillies": - return "Pripyat"; - - case "ending": - return "Museum"; - - case "af_chase": - return "Afghan Chase"; - - case "af_caves": - return "Afghan Caves"; - - case "arcadia": - return "Arcadia"; - - case "boneyard": - return "Boneyard"; - - case "cliffhanger": - return "Cliffhanger"; - - case "dcburning": - return "DCBurning"; - - case "dcemp": - return "DCEMP"; - - case "downtown": - return "Downtown"; - - case "estate": - return "EstateSP"; - - case "favela": - return "FavelaSP"; - - case "favela_escape": - return "Favela Escape"; - - case "roadkill": - return "Roadkill"; - - case "trainer": - return "TH3 PIT"; - - case "so_bridge": - return "Bridge"; - - case "dc_whitehouse": - return "Whitehouse"; - - case "mp_shipment_long": - return "ShipmentLong"; - - case "mp_shipment": - return "Shipment"; - - case "mp_firingrange": - return "Firing Range"; - - case "mp_rust_long": - return "RustLong"; - - case "mp_cargoship_sh": - return "Freighter"; - - case "mp_storm_spring": - return "Chemical Plant"; - - case "mp_crash_trop": - case "mp_crash_tropical": - return "Crash Tropical"; - - case "mp_fav_tropical": - return "Favela Tropical"; - - case "mp_estate_trop": - case "mp_estate_tropical": - return "Estate Tropical"; - - case "mp_bloc_sh": - return "Forgotten City"; - - default: - return mapname; - } -} - -/* - Returns a good amount of players. -*/ -getGoodMapAmount() -{ - switch ( getdvar( "mapname" ) ) - { - case "mp_rust": - case "iw4_credits": - case "mp_nuked": - case "oilrig": - case "mp_killhouse": - case "invasion": - case "mp_bog_sh": - case "co_hunted": - case "contingency": - case "gulag": - case "so_ghillies": - case "ending": - case "af_chase": - case "af_caves": - case "arcadia": - case "boneyard": - case "cliffhanger": - case "dcburning": - case "dcemp": - case "downtown": - case "estate": - case "favela": - case "favela_escape": - case "roadkill": - case "so_bridge": - case "trainer": - case "dc_whitehouse": - case "mp_shipment": - if ( level.teambased ) - { - return 8; - } - else - { - return 4; - } - - case "mp_vacant": - case "mp_terminal": - case "mp_nightshift": - case "mp_favela": - case "mp_highrise": - case "mp_boneyard": - case "mp_subbase": - case "mp_firingrange": - case "mp_fav_tropical": - case "mp_shipment_long": - case "mp_rust_long": - if ( level.teambased ) - { - return 12; - } - else - { - return 8; - } - - case "mp_afghan": - case "mp_crash": - case "mp_brecourt": - case "mp_cross_fire": - case "mp_overgrown": - case "mp_trailerpark": - case "mp_underpass": - case "mp_checkpoint": - case "mp_quarry": - case "mp_rundown": - case "mp_cargoship": - case "mp_estate": - case "mp_bloc": - case "mp_storm": - case "mp_strike": - case "mp_abandon": - case "mp_complex": - case "airport": - case "mp_storm_spring": - case "mp_crash_trop": - case "mp_cargoship_sh": - case "mp_estate_trop": - case "mp_compact": - case "mp_crash_tropical": - case "mp_estate_tropical": - case "mp_bloc_sh": - if ( level.teambased ) - { - return 14; - } - else - { - return 9; - } - - case "mp_fuel2": - case "mp_invasion": - case "mp_derail": - if ( level.teambased ) - { - return 16; - } - else - { - return 10; - } - - default: - return 2; - } -} - -/* - Matches a num to a char -*/ -keyCodeToString( a ) -{ - b = ""; - - switch ( a ) - { - case 0: - b = "a"; - break; - - case 1: - b = "b"; - break; - - case 2: - b = "c"; - break; - - case 3: - b = "d"; - break; - - case 4: - b = "e"; - break; - - case 5: - b = "f"; - break; - - case 6: - b = "g"; - break; - - case 7: - b = "h"; - break; - - case 8: - b = "i"; - break; - - case 9: - b = "j"; - break; - - case 10: - b = "k"; - break; - - case 11: - b = "l"; - break; - - case 12: - b = "m"; - break; - - case 13: - b = "n"; - break; - - case 14: - b = "o"; - break; - - case 15: - b = "p"; - break; - - case 16: - b = "q"; - break; - - case 17: - b = "r"; - break; - - case 18: - b = "s"; - break; - - case 19: - b = "t"; - break; - - case 20: - b = "u"; - break; - - case 21: - b = "v"; - break; - - case 22: - b = "w"; - break; - - case 23: - b = "x"; - break; - - case 24: - b = "y"; - break; - - case 25: - b = "z"; - break; - - case 26: - b = "."; - break; - - case 27: - b = " "; - break; - } - - return b; -} - -/* - Returns an array of all the bots in the game. -*/ -getBotArray() -{ - result = []; - playercount = level.players.size; - - for ( i = 0; i < playercount; i++ ) - { - player = level.players[ i ]; - - if ( !player is_bot() ) - { - continue; - } - - result[ result.size ] = player; - } - - return result; -} - -/* - We return a balanced KDTree from the waypoints. -*/ -WaypointsToKDTree() -{ - kdTree = KDTree(); - - kdTree _WaypointsToKDTree( level.waypoints, 0 ); - - return kdTree; -} - -/* - Recurive function. We construct a balanced KD tree by sorting the waypoints using heap sort. -*/ -_WaypointsToKDTree( waypoints, dem ) -{ - if ( !waypoints.size ) - { - return; - } - - callbacksort = undefined; - - switch ( dem ) - { - case 0: - callbacksort = ::HeapSortCoordX; - break; - - case 1: - callbacksort = ::HeapSortCoordY; - break; - - case 2: - callbacksort = ::HeapSortCoordZ; - break; - } - - heap = NewHeap( callbacksort ); - - for ( i = 0; i < waypoints.size; i++ ) - { - heap HeapInsert( waypoints[ i ] ); - } - - sorted = []; - - while ( heap.data.size ) - { - sorted[ sorted.size ] = heap.data[ 0 ]; - heap HeapRemove(); - } - - median = int( sorted.size / 2 ); // use divide and conq - - left = []; - right = []; - - for ( i = 0; i < sorted.size; i++ ) - { - if ( i < median ) - { - right[ right.size ] = sorted[ i ]; - } - else if ( i > median ) - { - left[ left.size ] = sorted[ i ]; - } - } - - self KDTreeInsert( sorted[ median ] ); - - _WaypointsToKDTree( left, ( dem + 1 ) % 3 ); - - _WaypointsToKDTree( right, ( dem + 1 ) % 3 ); -} - -/* - Returns a new list. -*/ -List() -{ - list = spawnstruct(); - list.count = 0; - list.data = []; - - return list; -} - -/* - Adds a new thing to the list. -*/ -ListAdd( thing ) -{ - self.data[ self.count ] = thing; - - self.count++; -} - -/* - Adds to the start of the list. -*/ -ListAddFirst( thing ) -{ - for ( i = self.count - 1; i >= 0; i-- ) - { - self.data[ i + 1 ] = self.data[ i ]; - } - - self.data[ 0 ] = thing; - self.count++; -} - -/* - Removes the thing from the list. -*/ -ListRemove( thing ) -{ - for ( i = 0; i < self.count; i++ ) - { - if ( self.data[ i ] == thing ) - { - while ( i < self.count - 1 ) - { - self.data[ i ] = self.data[ i + 1 ]; - i++; - } - - self.data[ i ] = undefined; - self.count--; - break; - } - } -} - -/* - Returns a new KDTree. -*/ -KDTree() -{ - kdTree = spawnstruct(); - kdTree.root = undefined; - kdTree.count = 0; - - return kdTree; -} - -/* - Called on a KDTree. Will insert the object into the KDTree. -*/ -KDTreeInsert( data ) // as long as what you insert has a .origin attru, it will work. -{ - self.root = self _KDTreeInsert( self.root, data, 0, -2147483647, -2147483647, -2147483647, 2147483647, 2147483647, 2147483647 ); -} - -/* - Recurive function that insert the object into the KDTree. -*/ -_KDTreeInsert( node, data, dem, x0, y0, z0, x1, y1, z1 ) -{ - if ( !isdefined( node ) ) - { - r = spawnstruct(); - r.data = data; - r.left = undefined; - r.right = undefined; - r.x0 = x0; - r.x1 = x1; - r.y0 = y0; - r.y1 = y1; - r.z0 = z0; - r.z1 = z1; - - self.count++; - - return r; - } - - switch ( dem ) - { - case 0: - if ( data.origin[ 0 ] < node.data.origin[ 0 ] ) - { - node.left = self _KDTreeInsert( node.left, data, 1, x0, y0, z0, node.data.origin[ 0 ], y1, z1 ); - } - else - { - node.right = self _KDTreeInsert( node.right, data, 1, node.data.origin[ 0 ], y0, z0, x1, y1, z1 ); - } - - break; - - case 1: - if ( data.origin[ 1 ] < node.data.origin[ 1 ] ) - { - node.left = self _KDTreeInsert( node.left, data, 2, x0, y0, z0, x1, node.data.origin[ 1 ], z1 ); - } - else - { - node.right = self _KDTreeInsert( node.right, data, 2, x0, node.data.origin[ 1 ], z0, x1, y1, z1 ); - } - - break; - - case 2: - if ( data.origin[ 2 ] < node.data.origin[ 2 ] ) - { - node.left = self _KDTreeInsert( node.left, data, 0, x0, y0, z0, x1, y1, node.data.origin[ 2 ] ); - } - else - { - node.right = self _KDTreeInsert( node.right, data, 0, x0, y0, node.data.origin[ 2 ], x1, y1, z1 ); - } - - break; - } - - return node; -} - -/* - Called on a KDTree, will return the nearest object to the given origin. -*/ -KDTreeNearest( origin ) -{ - if ( !isdefined( self.root ) ) - { - return undefined; - } - - return self _KDTreeNearest( self.root, origin, self.root.data, distancesquared( self.root.data.origin, origin ), 0 ); -} - -/* - Recurive function that will retrieve the closest object to the query. -*/ -_KDTreeNearest( node, point, closest, closestdist, dem ) -{ - if ( !isdefined( node ) ) - { - return closest; - } - - thisDis = distancesquared( node.data.origin, point ); - - if ( thisDis < closestdist ) - { - closestdist = thisDis; - closest = node.data; - } - - if ( node Rectdistancesquared( point ) < closestdist ) - { - near = node.left; - far = node.right; - - if ( point[ dem ] > node.data.origin[ dem ] ) - { - near = node.right; - far = node.left; - } - - closest = self _KDTreeNearest( near, point, closest, closestdist, ( dem + 1 ) % 3 ); - - closest = self _KDTreeNearest( far, point, closest, distancesquared( closest.origin, point ), ( dem + 1 ) % 3 ); - } - - return closest; -} - -/* - Called on a rectangle, returns the distance from origin to the rectangle. -*/ -Rectdistancesquared( origin ) -{ - dx = 0; - dy = 0; - dz = 0; - - if ( origin[ 0 ] < self.x0 ) - { - dx = origin[ 0 ] - self.x0; - } - else if ( origin[ 0 ] > self.x1 ) - { - dx = origin[ 0 ] - self.x1; - } - - if ( origin[ 1 ] < self.y0 ) - { - dy = origin[ 1 ] - self.y0; - } - else if ( origin[ 1 ] > self.y1 ) - { - dy = origin[ 1 ] - self.y1; - } - - - if ( origin[ 2 ] < self.z0 ) - { - dz = origin[ 2 ] - self.z0; - } - else if ( origin[ 2 ] > self.z1 ) - { - dz = origin[ 2 ] - self.z1; - } - - return dx * dx + dy * dy + dz * dz; -} - -/* - Does the extra check when adding bots -*/ -doExtraCheck() -{ - maps\mp\bots\_bot_internal::checkTheBots(); -} - -/* - A heap invarient comparitor, used for objects, objects with a higher X coord will be first in the heap. -*/ -HeapSortCoordX( item, item2 ) -{ - return item.origin[ 0 ] > item2.origin[ 0 ]; -} - -/* - A heap invarient comparitor, used for objects, objects with a higher Y coord will be first in the heap. -*/ -HeapSortCoordY( item, item2 ) -{ - return item.origin[ 1 ] > item2.origin[ 1 ]; -} - -/* - A heap invarient comparitor, used for objects, objects with a higher Z coord will be first in the heap. -*/ -HeapSortCoordZ( item, item2 ) -{ - return item.origin[ 2 ] > item2.origin[ 2 ]; -} - -/* - A heap invarient comparitor, used for numbers, numbers with the highest number will be first in the heap. -*/ -Heap( item, item2 ) -{ - return item > item2; -} - -/* - A heap invarient comparitor, used for numbers, numbers with the lowest number will be first in the heap. -*/ -ReverseHeap( item, item2 ) -{ - return item < item2; -} - -/* - A heap invarient comparitor, used for traces. Wanting the trace with the largest length first in the heap. -*/ -HeapTraceFraction( item, item2 ) -{ - return item[ "fraction" ] > item2[ "fraction" ]; -} - -/* - Returns a new heap. -*/ -NewHeap( compare ) -{ - heap_node = spawnstruct(); - heap_node.data = []; - heap_node.compare = compare; - - return heap_node; -} - -/* - Inserts the item into the heap. Called on a heap. -*/ -HeapInsert( item ) -{ - insert = self.data.size; - self.data[ insert ] = item; - - current = insert + 1; - - while ( current > 1 ) - { - last = current; - current = int( current / 2 ); - - if ( ![[ self.compare ]]( item, self.data[ current - 1 ] ) ) - { - break; - } - - self.data[ last - 1 ] = self.data[ current - 1 ]; - self.data[ current - 1 ] = item; - } -} - -/* - Helper function to determine what is the next child of the bst. -*/ -_HeapNextChild( node, hsize ) -{ - left = node * 2; - right = left + 1; - - if ( left > hsize ) - { - return -1; - } - - if ( right > hsize ) - { - return left; - } - - if ( [[ self.compare ]]( self.data[ left - 1 ], self.data[ right - 1 ] ) ) - { - return left; - } - else - { - return right; - } -} - -/* - Removes an item from the heap. Called on a heap. -*/ -HeapRemove() -{ - remove = self.data.size; - - if ( !remove ) - { - return remove; - } - - move = self.data[ remove - 1 ]; - self.data[ 0 ] = move; - self.data[ remove - 1 ] = undefined; - remove--; - - if ( !remove ) - { - return remove; - } - - last = 1; - next = self _HeapNextChild( 1, remove ); - - while ( next != -1 ) - { - if ( [[ self.compare ]]( move, self.data[ next - 1 ] ) ) - { - break; - } - - self.data[ last - 1 ] = self.data[ next - 1 ]; - self.data[ next - 1 ] = move; - - last = next; - next = self _HeapNextChild( next, 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; -} - -/* - Removes the waypoint usage -*/ -RemoveWaypointUsage( wp, team ) -{ - if ( !isdefined( level.waypointusage ) ) - { - return; - } - - wpstr = wp + ""; - - if ( !isdefined( level.waypointusage[ team ][ wpstr ] ) ) - { - return; - } - - level.waypointusage[ team ][ wpstr ]--; - - if ( level.waypointusage[ team ][ wpstr ] <= 0 ) - { - level.waypointusage[ team ][ wpstr ] = undefined; - } -} - -/* - Will linearly search for the nearest waypoint to pos that has a direct line of sight. -*/ -getNearestWaypointWithSight( pos ) -{ - candidate = undefined; - dist = 2147483647; - - for ( i = level.waypoints.size - 1; i >= 0; 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 = level.waypoints.size - 1; i >= 0; 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(); - bestNodeStr = bestNode.index + ""; - openset[ bestNodeStr ] = undefined; - wp = level.waypoints[ bestNode.index ]; - - // check if we made it to the goal - if ( bestNode.index == goalWp ) - { - path = []; - - while ( isdefined( bestNode ) ) - { - bestNodeStr = bestNode.index + ""; - - if ( isdefined( team ) && isdefined( level.waypointusage ) ) - { - if ( !isdefined( level.waypointusage[ team ][ bestNodeStr ] ) ) - { - level.waypointusage[ team ][ bestNodeStr ] = 0; - } - - level.waypointusage[ team ][ bestNodeStr ]++; - } - - // 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 ]; - childStr = child + ""; - childWp = level.waypoints[ child ]; - - penalty = 1; - - if ( !greedy_path && isdefined( team ) && isdefined( level.waypointusage ) ) - { - temppen = 1; - - if ( isdefined( level.waypointusage[ team ][ childStr ] ) ) - { - temppen = level.waypointusage[ team ][ childStr ]; // consider how many bots are taking this path - } - - if ( temppen > 1 ) - { - penalty = temppen; - } - } - - // 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[ childStr ] ); - - if ( inopen && openset[ childStr ].g <= newg ) - { - continue; - } - - inclosed = isdefined( closed[ childStr ] ); - - if ( inclosed && closed[ childStr ].g <= newg ) - { - continue; - } - - node = undefined; - - if ( inopen ) - { - node = openset[ childStr ]; - } - else if ( inclosed ) - { - node = closed[ childStr ]; - } - 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[ childStr ] = undefined; - } - - // check if not in open, add it - if ( !inopen ) - { - open HeapInsert( node ); - openset[ childStr ] = node; - } - } - - // done with children, push onto closed - closed[ bestNodeStr ] = bestNode; - } - - return []; -} - -/* - Taken from t5 gsc. - Returns an array of number's average. -*/ -array_average( array ) -{ - assert( array.size > 0 ); - total = 0; - - for ( i = 0; i < array.size; i++ ) - { - total += array[ i ]; - } - - return ( total / array.size ); -} - -/* - Taken from t5 gsc. - Returns an array of number's standard deviation. -*/ -array_std_deviation( array, mean ) -{ - assert( array.size > 0 ); - tmp = []; - - for ( i = 0; i < array.size; i++ ) - { - tmp[ i ] = ( array[ i ] - mean ) * ( array[ i ] - mean ); - } - - total = 0; - - for ( i = 0; i < tmp.size; i++ ) - { - total = total + tmp[ i ]; - } - - return sqrt( total / array.size ); -} - -/* - Taken from t5 gsc. - Will produce a random number between lower_bound and upper_bound but with a bell curve distribution (more likely to be close to the mean). -*/ -random_normal_distribution( mean, std_deviation, lower_bound, upper_bound ) -{ - x1 = 0; - x2 = 0; - w = 1; - y1 = 0; - - while ( w >= 1 ) - { - x1 = 2 * randomfloatrange( 0, 1 ) - 1; - x2 = 2 * randomfloatrange( 0, 1 ) - 1; - w = x1 * x1 + x2 * x2; - } - - w = sqrt( ( -2.0 * log( w ) ) / w ); - y1 = x1 * w; - number = mean + y1 * std_deviation; - - if ( isdefined( lower_bound ) && number < lower_bound ) - { - number = lower_bound; - } - - if ( isdefined( upper_bound ) && number > upper_bound ) - { - number = upper_bound; - } - - return ( number ); -} - -/* - Patches the plant sites so it exposes the defuseObject -*/ -onUsePlantObjectFix( player ) -{ - // planted the bomb - if ( !self maps\mp\gametypes\_gameobjects::isfriendlyteam( player.pers[ "team" ] ) ) - { - level thread bombPlantedFix( self, player ); - // player logstring( "bomb planted: " + self.label ); - - // disable all bomb zones except this one - for ( index = 0; index < level.bombzones.size; index++ ) - { - if ( level.bombzones[ index ] == self ) - { - continue; - } - - level.bombzones[ index ] maps\mp\gametypes\_gameobjects::disableobject(); - } - - player playsound( "mp_bomb_plant" ); - player notify ( "bomb_planted" ); - - // if ( !level.hardcoremode ) - // iprintln( &"MP_EXPLOSIVES_PLANTED_BY", player ); - - leaderdialog( "bomb_planted" ); - - level thread teamplayercardsplash( "callout_bombplanted", player ); - - level.bombowner = player; - player thread maps\mp\gametypes\_hud_message::splashnotify( "plant", maps\mp\gametypes\_rank::getscoreinfovalue( "plant" ) ); - player thread maps\mp\gametypes\_rank::giverankxp( "plant" ); - player.bombplantedtime = gettime(); - maps\mp\gametypes\_gamescore::giveplayerscore( "plant", player ); - player incplayerstat( "bombsplanted", 1 ); - player thread maps\mp\_matchdata::loggameevent( "plant", player.origin ); - } -} - -/* - Patches the plant sites so it exposes the defuseObject -*/ -bombPlantedFix( destroyedObj, player ) -{ - maps\mp\gametypes\_gamelogic::pausetimer(); - level.bombplanted = true; - - destroyedObj.visuals[ 0 ] thread maps\mp\gametypes\_gamelogic::playtickingsound(); - level.tickingobject = destroyedObj.visuals[ 0 ]; - - level.timelimitoverride = true; - setgameendtime( int( gettime() + ( level.bombtimer * 1000 ) ) ); - setdvar( "ui_bomb_timer", 1 ); - - if ( !level.multibomb ) - { - level.sdbomb maps\mp\gametypes\_gameobjects::allowcarry( "none" ); - level.sdbomb maps\mp\gametypes\_gameobjects::setvisibleteam( "none" ); - level.sdbomb maps\mp\gametypes\_gameobjects::setdropped(); - level.sdbombmodel = level.sdbomb.visuals[ 0 ]; - } - else - { - for ( index = 0; index < level.players.size; index++ ) - { - if ( isdefined( level.players[ index ].carryicon ) ) - { - level.players[ index ].carryicon destroyelem(); - } - } - - trace = bullettrace( player.origin + ( 0, 0, 20 ), player.origin - ( 0, 0, 2000 ), false, player ); - - tempAngle = randomfloat( 360 ); - forward = ( cos( tempAngle ), sin( tempAngle ), 0 ); - forward = vectornormalize( forward - vector_multiply( trace[ "normal" ], vectordot( forward, trace[ "normal" ] ) ) ); - dropAngles = vectortoangles( forward ); - - level.sdbombmodel = spawn( "script_model", trace[ "position" ] ); - level.sdbombmodel.angles = dropAngles; - level.sdbombmodel setmodel( "prop_suitcase_bomb" ); - } - - destroyedObj maps\mp\gametypes\_gameobjects::allowuse( "none" ); - destroyedObj maps\mp\gametypes\_gameobjects::setvisibleteam( "none" ); - /* - destroyedObj maps\mp\gametypes\_gameobjects::set2dicon( "friendly", undefined ); - destroyedObj maps\mp\gametypes\_gameobjects::set2dicon( "enemy", undefined ); - destroyedObj maps\mp\gametypes\_gameobjects::set3dicon( "friendly", undefined ); - destroyedObj maps\mp\gametypes\_gameobjects::set3dicon( "enemy", undefined ); - */ - label = destroyedObj maps\mp\gametypes\_gameobjects::getlabel(); - - // create a new object to defuse with. - trigger = destroyedObj.bombdefusetrig; - trigger.origin = level.sdbombmodel.origin; - visuals = []; - defuseObject = maps\mp\gametypes\_gameobjects::createuseobject( game[ "defenders" ], trigger, visuals, ( 0, 0, 32 ) ); - defuseObject maps\mp\gametypes\_gameobjects::allowuse( "friendly" ); - defuseObject maps\mp\gametypes\_gameobjects::setusetime( level.defusetime ); - defuseObject maps\mp\gametypes\_gameobjects::setusetext( &"MP_DEFUSING_EXPLOSIVE" ); - defuseObject maps\mp\gametypes\_gameobjects::setusehinttext( &"PLATFORM_HOLD_TO_DEFUSE_EXPLOSIVES" ); - defuseObject maps\mp\gametypes\_gameobjects::setvisibleteam( "any" ); - defuseObject maps\mp\gametypes\_gameobjects::set2dicon( "friendly", "waypoint_defuse" + label ); - defuseObject maps\mp\gametypes\_gameobjects::set2dicon( "enemy", "waypoint_defend" + label ); - defuseObject maps\mp\gametypes\_gameobjects::set3dicon( "friendly", "waypoint_defuse" + label ); - defuseObject maps\mp\gametypes\_gameobjects::set3dicon( "enemy", "waypoint_defend" + label ); - defuseObject.label = label; - defuseObject.onbeginuse = maps\mp\gametypes\sd::onbeginuse; - defuseObject.onenduse = maps\mp\gametypes\sd::onenduse; - defuseObject.onuse = maps\mp\gametypes\sd::onusedefuseobject; - defuseObject.useweapon = "briefcase_bomb_defuse_mp"; - - level.defuseobject = defuseObject; - - maps\mp\gametypes\sd::bombtimerwait(); - setdvar( "ui_bomb_timer", 0 ); - - destroyedObj.visuals[ 0 ] maps\mp\gametypes\_gamelogic::stoptickingsound(); - - if ( level.gameended || level.bombdefused ) - { - return; - } - - level.bombexploded = true; - - explosionOrigin = level.sdbombmodel.origin; - level.sdbombmodel hide(); - - if ( isdefined( player ) ) - { - destroyedObj.visuals[ 0 ] radiusdamage( explosionOrigin, 512, 200, 20, player ); - player incplayerstat( "targetsdestroyed", 1 ); - } - else - { - destroyedObj.visuals[ 0 ] radiusdamage( explosionOrigin, 512, 200, 20 ); - } - - rot = randomfloat( 360 ); - explosionEffect = spawnfx( level._effect[ "bombexplosion" ], explosionOrigin + ( 0, 0, 50 ), ( 0, 0, 1 ), ( cos( rot ), sin( rot ), 0 ) ); - triggerfx( explosionEffect ); - - playrumbleonposition( "grenade_rumble", explosionOrigin ); - earthquake( 0.75, 2.0, explosionOrigin, 2000 ); - - thread playsoundinspace( "exp_suitcase_bomb_main", explosionOrigin ); - - if ( isdefined( destroyedObj.exploderindex ) ) - { - exploder( destroyedObj.exploderindex ); - } - - for ( index = 0; index < level.bombzones.size; index++ ) - { - level.bombzones[ index ] maps\mp\gametypes\_gameobjects::disableobject(); - } - - defuseObject maps\mp\gametypes\_gameobjects::disableobject(); - - setgameendtime( 0 ); - - wait 3; - - maps\mp\gametypes\sd::sd_endgame( game[ "attackers" ], game[ "strings" ][ "target_destroyed" ] ); -} - - -/* - Patches giveLoadout so that it doesn't use IsItemUnlocked -*/ -botGiveLoadout( team, class, allowCopycat ) -{ - self endon( "death" ); - - self takeallweapons(); - - primaryIndex = 0; - - // initialize specialty array - self.specialty = []; - - if ( !isdefined( allowCopycat ) ) - { - allowCopycat = true; - } - - primaryWeapon = undefined; - - if ( isdefined( self.pers[ "copyCatLoadout" ] ) && self.pers[ "copyCatLoadout" ][ "inUse" ] && allowCopycat ) - { - self maps\mp\gametypes\_class::setclass( "copycat" ); - self.class_num = maps\mp\gametypes\_class::getclassindex( "copycat" ); - - clonedLoadout = self.pers[ "copyCatLoadout" ]; - - loadoutPrimary = clonedLoadout[ "loadoutPrimary" ]; - loadoutPrimaryAttachment = clonedLoadout[ "loadoutPrimaryAttachment" ]; - loadoutPrimaryAttachment2 = clonedLoadout[ "loadoutPrimaryAttachment2" ] ; - loadoutPrimaryCamo = clonedLoadout[ "loadoutPrimaryCamo" ]; - loadoutSecondary = clonedLoadout[ "loadoutSecondary" ]; - loadoutSecondaryAttachment = clonedLoadout[ "loadoutSecondaryAttachment" ]; - loadoutSecondaryAttachment2 = clonedLoadout[ "loadoutSecondaryAttachment2" ]; - loadoutSecondaryCamo = clonedLoadout[ "loadoutSecondaryCamo" ]; - loadoutEquipment = clonedLoadout[ "loadoutEquipment" ]; - loadoutPerk1 = clonedLoadout[ "loadoutPerk1" ]; - loadoutPerk2 = clonedLoadout[ "loadoutPerk2" ]; - loadoutPerk3 = clonedLoadout[ "loadoutPerk3" ]; - loadoutOffhand = clonedLoadout[ "loadoutOffhand" ]; - loadoutDeathStreak = "specialty_copycat"; - } - else if ( issubstr( class, "custom" ) ) - { - class_num = maps\mp\gametypes\_class::getclassindex( class ); - self.class_num = class_num; - - loadoutPrimary = maps\mp\gametypes\_class::cac_getweapon( class_num, 0 ); - loadoutPrimaryAttachment = maps\mp\gametypes\_class::cac_getweaponattachment( class_num, 0 ); - loadoutPrimaryAttachment2 = maps\mp\gametypes\_class::cac_getweaponattachmenttwo( class_num, 0 ); - loadoutPrimaryCamo = maps\mp\gametypes\_class::cac_getweaponcamo( class_num, 0 ); - loadoutSecondaryCamo = maps\mp\gametypes\_class::cac_getweaponcamo( class_num, 1 ); - loadoutSecondary = maps\mp\gametypes\_class::cac_getweapon( class_num, 1 ); - loadoutSecondaryAttachment = maps\mp\gametypes\_class::cac_getweaponattachment( class_num, 1 ); - loadoutSecondaryAttachment2 = maps\mp\gametypes\_class::cac_getweaponattachmenttwo( class_num, 1 ); - loadoutSecondaryCamo = maps\mp\gametypes\_class::cac_getweaponcamo( class_num, 1 ); - loadoutEquipment = maps\mp\gametypes\_class::cac_getperk( class_num, 0 ); - loadoutPerk1 = maps\mp\gametypes\_class::cac_getperk( class_num, 1 ); - loadoutPerk2 = maps\mp\gametypes\_class::cac_getperk( class_num, 2 ); - loadoutPerk3 = maps\mp\gametypes\_class::cac_getperk( class_num, 3 ); - loadoutOffhand = maps\mp\gametypes\_class::cac_getoffhand( class_num ); - loadoutDeathStreak = maps\mp\gametypes\_class::cac_getdeathstreak( class_num ); - } - else - { - class_num = maps\mp\gametypes\_class::getclassindex( class ); - self.class_num = class_num; - - loadoutPrimary = maps\mp\gametypes\_class::table_getweapon( level.classtablename, class_num, 0 ); - loadoutPrimaryAttachment = maps\mp\gametypes\_class::table_getweaponattachment( level.classtablename, class_num, 0, 0 ); - loadoutPrimaryAttachment2 = maps\mp\gametypes\_class::table_getweaponattachment( level.classtablename, class_num, 0, 1 ); - loadoutPrimaryCamo = maps\mp\gametypes\_class::table_getweaponcamo( level.classtablename, class_num, 0 ); - loadoutSecondaryCamo = maps\mp\gametypes\_class::table_getweaponcamo( level.classtablename, class_num, 1 ); - loadoutSecondary = maps\mp\gametypes\_class::table_getweapon( level.classtablename, class_num, 1 ); - loadoutSecondaryAttachment = maps\mp\gametypes\_class::table_getweaponattachment( level.classtablename, class_num, 1, 0 ); - loadoutSecondaryAttachment2 = maps\mp\gametypes\_class::table_getweaponattachment( level.classtablename, class_num, 1, 1 );; - loadoutSecondaryCamo = maps\mp\gametypes\_class::table_getweaponcamo( level.classtablename, class_num, 1 ); - loadoutEquipment = maps\mp\gametypes\_class::table_getequipment( level.classtablename, class_num, 0 ); - loadoutPerk1 = maps\mp\gametypes\_class::table_getperk( level.classtablename, class_num, 1 ); - loadoutPerk2 = maps\mp\gametypes\_class::table_getperk( level.classtablename, class_num, 2 ); - loadoutPerk3 = maps\mp\gametypes\_class::table_getperk( level.classtablename, class_num, 3 ); - loadoutOffhand = maps\mp\gametypes\_class::table_getoffhand( level.classtablename, class_num ); - loadoutDeathStreak = maps\mp\gametypes\_class::table_getdeathstreak( level.classtablename, class_num ); - } - - if ( loadoutPerk1 != "specialty_bling" ) - { - loadoutPrimaryAttachment2 = "none"; - loadoutSecondaryAttachment2 = "none"; - } - - if ( loadoutPerk1 != "specialty_onemanarmy" && loadoutSecondary == "onemanarmy" ) - { - loadoutSecondary = maps\mp\gametypes\_class::table_getweapon( level.classtablename, 10, 1 ); - } - - // loadoutSecondaryCamo = "none"; - - // stop default class op'ness - allowOp = ( getdvarint( "bots_loadout_allow_op" ) >= 1 ); - - if ( !allowOp ) - { - loadoutDeathStreak = "specialty_null"; - - if ( loadoutPrimary == "riotshield" ) - { - loadoutPrimary = "m4"; - } - - if ( loadoutSecondary == "at4" ) - { - loadoutSecondary = "usp"; - } - - if ( loadoutPrimaryAttachment == "gl" ) - { - loadoutPrimaryAttachment = "none"; - } - - if ( loadoutPerk2 == "specialty_coldblooded" ) - { - loadoutPerk2 = "specialty_null"; - } - - if ( loadoutPerk3 == "specialty_localjammer" ) - { - loadoutPerk3 = "specialty_null"; - } - } - - - if ( level.killstreakrewards ) - { - if ( getdvarint( "scr_classic" ) == 1 ) - { - loadoutKillstreak1 = "uav"; - loadoutKillstreak2 = "precision_airstrike"; - loadoutKillstreak3 = "helicopter"; - } - else - { - loadoutKillstreak1 = self getplayerdata( "killstreaks", 0 ); - loadoutKillstreak2 = self getplayerdata( "killstreaks", 1 ); - loadoutKillstreak3 = self getplayerdata( "killstreaks", 2 ); - } - } - else - { - loadoutKillstreak1 = "none"; - loadoutKillstreak2 = "none"; - loadoutKillstreak3 = "none"; - } - - secondaryName = maps\mp\gametypes\_class::buildweaponname( loadoutSecondary, loadoutSecondaryAttachment, loadoutSecondaryAttachment2 ); - self _giveweapon( secondaryName, int( tablelookup( "mp/camoTable.csv", 1, loadoutSecondaryCamo, 0 ) ) ); - - self.loadoutprimarycamo = int( tablelookup( "mp/camoTable.csv", 1, loadoutPrimaryCamo, 0 ) ); - self.loadoutprimary = loadoutPrimary; - self.loadoutsecondary = loadoutSecondary; - self.loadoutsecondarycamo = int( tablelookup( "mp/camoTable.csv", 1, loadoutSecondaryCamo, 0 ) ); - - self setoffhandprimaryclass( "other" ); - - // Action Slots - // self _setactionslot( 1, "" ); - self _setactionslot( 1, "nightvision" ); - self _setactionslot( 3, "altMode" ); - self _setactionslot( 4, "" ); - - // Perks - self _clearperks(); - self maps\mp\gametypes\_class::_detachall(); - - // these special case giving pistol death have to come before - // perk loadout to ensure player perk icons arent overwritten - if ( level.diehardmode ) - { - self maps\mp\perks\_perks::giveperk( "specialty_pistoldeath" ); - } - - // only give the deathstreak for the initial spawn for this life. - if ( loadoutDeathStreak != "specialty_null" && ( gettime() - self.spawntime ) < 0.1 ) - { - deathVal = int( tablelookup( "mp/perkTable.csv", 1, loadoutDeathStreak, 6 ) ); - - if ( self botGetPerkUpgrade( loadoutPerk1 ) == "specialty_rollover" || self botGetPerkUpgrade( loadoutPerk2 ) == "specialty_rollover" || self botGetPerkUpgrade( loadoutPerk3 ) == "specialty_rollover" ) - { - deathVal -= 1; - } - - if ( self.pers[ "cur_death_streak" ] == deathVal ) - { - self thread maps\mp\perks\_perks::giveperk( loadoutDeathStreak ); - self thread maps\mp\gametypes\_hud_message::splashnotify( loadoutDeathStreak ); - } - else if ( self.pers[ "cur_death_streak" ] > deathVal ) - { - self thread maps\mp\perks\_perks::giveperk( loadoutDeathStreak ); - } - } - - self botLoadoutAllPerks( loadoutEquipment, loadoutPerk1, loadoutPerk2, loadoutPerk3 ); - - self maps\mp\gametypes\_class::setkillstreaks( loadoutKillstreak1, loadoutKillstreak2, loadoutKillstreak3 ); - - if ( self hasperk( "specialty_extraammo", true ) && getweaponclass( secondaryName ) != "weapon_projectile" ) - { - self givemaxammo( secondaryName ); - } - - // Primary Weapon - primaryName = maps\mp\gametypes\_class::buildweaponname( loadoutPrimary, loadoutPrimaryAttachment, loadoutPrimaryAttachment2 ); - self _giveweapon( primaryName, self.loadoutprimarycamo ); - - // fix changing from a riotshield class to a riotshield class during grace period not giving a shield - if ( primaryName == "riotshield_mp" && level.ingraceperiod ) - { - self notify ( "weapon_change", "riotshield_mp" ); - } - - if ( self hasperk( "specialty_extraammo", true ) ) - { - self givemaxammo( primaryName ); - } - - self setspawnweapon( primaryName ); - - primaryTokens = strtok( primaryName, "_" ); - self.pers[ "primaryWeapon" ] = primaryTokens[ 0 ]; - - // Primary Offhand was given by giveperk (it's your perk1) - - // Secondary Offhand - offhandSecondaryWeapon = loadoutOffhand + "_mp"; - - if ( loadoutOffhand == "flash_grenade" ) - { - self setoffhandsecondaryclass( "flash" ); - } - else - { - self setoffhandsecondaryclass( "smoke" ); - } - - self giveweapon( offhandSecondaryWeapon ); - - if ( loadoutOffhand == "smoke_grenade" ) - { - self setweaponammoclip( offhandSecondaryWeapon, 1 ); - } - else if ( loadoutOffhand == "flash_grenade" ) - { - self setweaponammoclip( offhandSecondaryWeapon, 2 ); - } - else if ( loadoutOffhand == "concussion_grenade" ) - { - self setweaponammoclip( offhandSecondaryWeapon, 2 ); - } - else - { - self setweaponammoclip( offhandSecondaryWeapon, 1 ); - } - - primaryWeapon = primaryName; - self.primaryweapon = primaryWeapon; - self.secondaryweapon = secondaryName; - - self botPlayerModelForWeapon( self.pers[ "primaryWeapon" ], getbaseweaponname( secondaryName ) ); - - self.issniper = ( weaponclass( self.primaryweapon ) == "sniper" ); - - self maps\mp\gametypes\_weapons::updatemovespeedscale( "primary" ); - - // cac specialties that require loop threads - self maps\mp\perks\_perks::cac_selector(); - - self notify ( "changed_kit" ); - self notify( "bot_giveLoadout", allowCopycat ); -} - -/* - Patches giveLoadout so that it doesn't use IsItemUnlocked -*/ -botGetPerkUpgrade( perkName ) -{ - perkUpgrade = tablelookup( "mp/perktable.csv", 1, perkName, 8 ); - - if ( perkUpgrade == "" || perkUpgrade == "specialty_null" ) - { - return "specialty_null"; - } - - if ( !isdefined( self.pers[ "bots" ][ "unlocks" ][ "upgraded_" + perkName ] ) || !self.pers[ "bots" ][ "unlocks" ][ "upgraded_" + perkName ] ) - { - return "specialty_null"; - } - - return ( perkUpgrade ); -} - -/* - Patches giveLoadout so that it doesn't use IsItemUnlocked -*/ -botLoadoutAllPerks( loadoutEquipment, loadoutPerk1, loadoutPerk2, loadoutPerk3 ) -{ - loadoutEquipment = maps\mp\perks\_perks::validateperk( 1, loadoutEquipment ); - loadoutPerk1 = maps\mp\perks\_perks::validateperk( 1, loadoutPerk1 ); - loadoutPerk2 = maps\mp\perks\_perks::validateperk( 2, loadoutPerk2 ); - loadoutPerk3 = maps\mp\perks\_perks::validateperk( 3, loadoutPerk3 ); - - self maps\mp\perks\_perks::giveperk( loadoutEquipment ); - self maps\mp\perks\_perks::giveperk( loadoutPerk1 ); - self maps\mp\perks\_perks::giveperk( loadoutPerk2 ); - self maps\mp\perks\_perks::giveperk( loadoutPerk3 ); - - perks[ 0 ] = loadoutPerk1; - perks[ 1 ] = loadoutPerk2; - perks[ 2 ] = loadoutPerk3; - - perkUpgrd[ 0 ] = tablelookup( "mp/perktable.csv", 1, loadoutPerk1, 8 ); - perkUpgrd[ 1 ] = tablelookup( "mp/perktable.csv", 1, loadoutPerk2, 8 ); - perkUpgrd[ 2 ] = tablelookup( "mp/perktable.csv", 1, loadoutPerk3, 8 ); - - for ( i = 0; i < perkUpgrd.size; i++ ) - { - upgrade = perkUpgrd[ i ]; - perk = perks[ i ]; - - if ( upgrade == "" || upgrade == "specialty_null" ) - { - continue; - } - - if ( isdefined( self.pers[ "bots" ][ "unlocks" ][ "upgraded_" + perk ] ) && self.pers[ "bots" ][ "unlocks" ][ "upgraded_" + perk ] ) - { - self maps\mp\perks\_perks::giveperk( upgrade ); - } - } - -} - -/* - Patches giveLoadout so that it doesn't use IsItemUnlocked -*/ -botPlayerModelForWeapon( weapon, secondary ) -{ - team = self.team; - - - if ( isdefined( game[ team + "_model" ][ weapon ] ) ) - { - [[ game[ team + "_model" ][ weapon ] ]](); - return; - } - - - weaponclass = tablelookup( "mp/statstable.csv", 4, weapon, 2 ); - - switch ( weaponclass ) - { - case "weapon_smg": - [[ game[ team + "_model" ][ "SMG" ] ]](); - break; - - case "weapon_assault": - weaponclass = tablelookup( "mp/statstable.csv", 4, secondary, 2 ); - - if ( weaponclass == "weapon_shotgun" ) - { - [[ game[ team + "_model" ][ "SHOTGUN" ] ]](); - } - else - { - [[ game[ team + "_model" ][ "ASSAULT" ] ]](); - } - - break; - - case "weapon_sniper": - if ( level.environment != "" && isdefined( self.pers[ "bots" ][ "unlocks" ][ "ghillie" ] ) && self.pers[ "bots" ][ "unlocks" ][ "ghillie" ] ) - { - [[ game[ team + "_model" ][ "GHILLIE" ] ]](); - } - else - { - [[ game[ team + "_model" ][ "SNIPER" ] ]](); - } - - break; - - case "weapon_lmg": - [[ game[ team + "_model" ][ "LMG" ] ]](); - break; - - case "weapon_riot": - [[ game[ team + "_model" ][ "RIOT" ] ]](); - break; - - default: - [[ game[ team + "_model" ][ "ASSAULT" ] ]](); - break; - } -} - -/* - Make player ref attach to rocket ent -*/ -tryUsePredatorMissileFix( lifeId ) -{ - if ( isdefined( level.civilianjetflyby ) ) - { - self iprintlnbold( &"MP_CIVILIAN_AIR_TRAFFIC" ); - return false; - } - - self setusingremote( "remotemissile" ); - result = self maps\mp\killstreaks\_killstreaks::initridekillstreak(); - - if ( result != "success" ) - { - if ( result != "disconnect" ) - { - self clearusingremote(); - } - - return false; - } - - level thread _fireFix( lifeId, self ); - - return true; -} - -/* - Make player ref attach to rocket ent -*/ -_fireFix( lifeId, player ) -{ - remoteMissileSpawnArray = getentarray( "remoteMissileSpawn", "targetname" ); - //assertEX( remoteMissileSpawnArray.size > 0 && getMapCustom( "map" ) != "", "No remote missile spawn points found. Contact friendly neighborhood designer" ); - - foreach ( spawn in remoteMissileSpawnArray ) - { - if ( isdefined( spawn.target ) ) - { - spawn.targetent = getent( spawn.target, "targetname" ); - } - } - - if ( remoteMissileSpawnArray.size > 0 ) - { - remoteMissileSpawn = player maps\mp\killstreaks\_remotemissile::getbestspawnpoint( remoteMissileSpawnArray ); - } - else - { - remoteMissileSpawn = undefined; - } - - if ( isdefined( remoteMissileSpawn ) ) - { - startPos = remoteMissileSpawn.origin; - targetPos = remoteMissileSpawn.targetent.origin; - - //thread drawLine( startPos, targetPos, 30, (0,1,0) ); - - vector = vectornormalize( startPos - targetPos ); - startPos = vector_multiply( vector, 14000 ) + targetPos; - - //thread drawLine( startPos, targetPos, 15, (1,0,0) ); - - rocket = magicbullet( "remotemissile_projectile_mp", startpos, targetPos, player ); - } - else - { - upVector = ( 0, 0, level.missileremotelaunchvert ); - backDist = level.missileremotelaunchhorz; - targetDist = level.missileremotelaunchtargetdist; - - forward = anglestoforward( player.angles ); - startpos = player.origin + upVector + forward * backDist * -1; - targetPos = player.origin + forward * targetDist; - - rocket = magicbullet( "remotemissile_projectile_mp", startpos, targetPos, player ); - } - - if ( !isdefined( rocket ) ) - { - player clearusingremote(); - return; - } - - rocket thread maps\mp\gametypes\_weapons::addmissiletosighttraces( player.team ); - - rocket thread maps\mp\killstreaks\_remotemissile::handledamage(); - - rocket.lifeid = lifeId; - rocket.type = "remote"; - MissileEyesFix( player, rocket ); -} - -/* - Make player ref attach to rocket ent -*/ -MissileEyesFix( player, rocket ) -{ - //level endon ( "game_ended" ); - player endon( "joined_team" ); - player endon( "joined_spectators" ); - - rocket thread maps\mp\killstreaks\_remotemissile::rocket_cleanupondeath(); - player thread maps\mp\killstreaks\_remotemissile::player_cleanupongameended( rocket ); - player thread maps\mp\killstreaks\_remotemissile::player_cleanuponteamchange( rocket ); - - player visionsetmissilecamforplayer( "black_bw", 0 ); - - player endon ( "disconnect" ); - - if ( isdefined( rocket ) ) - { - player visionsetmissilecamforplayer( game["thermal_vision"], 1.0 ); - player thread maps\mp\killstreaks\_remotemissile::delayedfofoverlay(); - player cameralinkto( rocket, "tag_origin" ); - player controlslinkto( rocket ); - - // our additions - player.rocket = rocket; - rocket.owner = player; - - if ( getdvarint( "camera_thirdPerson" ) ) - { - player setthirdpersondof( false ); - } - - rocket waittill( "death" ); - - // is defined check required because remote missile doesnt handle lifetime explosion gracefully - // instantly deletes its self after an explode and death notify - if ( isdefined( rocket ) ) - { - player maps\mp\_matchdata::logkillstreakevent( "predator_missile", rocket.origin ); - } - - player controlsunlink(); - player freezecontrolswrapper( true ); - player.rocket = undefined; // our addition - - // If a player gets the final kill with a hellfire, level.gameEnded will already be true at this point - if ( !level.gameended || isdefined( player.finalkill ) ) - { - player thread maps\mp\killstreaks\_remotemissile::staticeffect( 0.5 ); - } - - wait ( 0.5 ); - - player thermalvisionfofoverlayoff(); - - player cameraunlink(); - - if ( getdvarint( "camera_thirdPerson" ) ) - { - player setthirdpersondof( true ); - } - - } - - player clearusingremote(); -} diff --git a/maps/mp/bots/_menu.gsc b/maps/mp/bots/_menu.gsc deleted file mode 100644 index eaa414a..0000000 --- a/maps/mp/bots/_menu.gsc +++ /dev/null @@ -1,1389 +0,0 @@ -/* - _menu - Author: INeedGames - Date: 09/26/2020 - The ingame menu. -*/ - -#include common_scripts\utility; -#include maps\mp\_utility; -#include maps\mp\gametypes\_hud_util; -#include maps\mp\bots\_bot_utility; - -init() -{ - if ( getdvar( "bots_main_menu" ) == "" ) - { - setdvar( "bots_main_menu", true ); - } - - if ( !getdvarint( "bots_main_menu" ) ) - { - return; - } - - thread watchPlayers(); -} - -watchPlayers() -{ - for ( ;; ) - { - wait 1; - - if ( !getdvarint( "bots_main_menu" ) ) - { - return; - } - - for ( i = level.players.size - 1; i >= 0; i-- ) - { - player = level.players[ i ]; - - if ( !player is_host() ) - { - continue; - } - - if ( isdefined( player.menuinit ) && player.menuinit ) - { - continue; - } - - player thread init_menu(); - } - } -} - -destroyFixed() -{ - if ( !isdefined( self ) ) - { - return; - } - - self destroy(); -} - -removeChildFixed( element ) -{ - temp = []; - - for ( i = 0; i < self.children.size ; i++ ) - { - if ( isdefined( self.children[ i ] ) && self.children[ i ] != element ) - { - self.children[ i ].index = temp.size; - temp[ temp.size ] = self.children[ i ]; - } - } - - self.children = temp; - - element.index = undefined; - element.parent = undefined; -} - -destroyElemFixed() -{ - if ( !isdefined( self ) ) - { - return; - } - - if ( isdefined( self.parent ) ) - { - self.parent removeChildFixed( self ); - } - - self destroyelem(); -} - -kill_menu() -{ - self notify( "bots_kill_menu" ); - self.menuinit = undefined; -} - -init_menu() -{ - self.menuinit = true; - - self.menuopen = false; - self.submenu = "Main"; - self.curs[ "Main" ][ "X" ] = 0; - self addOptions(); - - self thread watchPlayerOpenMenu(); - self thread MenuSelect(); - self thread RightMenu(); - self thread LeftMenu(); - self thread UpMenu(); - self thread DownMenu(); - - self thread watchDisconnect(); - - self thread doGreetings(); -} - -watchDisconnect() -{ - self waittill_either( "disconnect", "bots_kill_menu" ); - - if ( self.menuopen ) - { - if ( isdefined( self.menutexty ) ) - { - for ( i = 0; i < self.menutexty.size; i++ ) - { - if ( isdefined( self.menutexty[ i ] ) ) - { - self.menutexty[ i ] destroyElemFixed(); - } - } - } - - if ( isdefined( self.menutext ) ) - { - for ( i = 0; i < self.menutext.size; i++ ) - { - if ( isdefined( self.menutext[ i ] ) ) - { - self.menutext[ i ] destroyElemFixed(); - } - } - } - - if ( isdefined( self.menu ) && isdefined( self.menu[ "X" ] ) ) - { - if ( isdefined( self.menu[ "X" ][ "Shader" ] ) ) - { - self.menu[ "X" ][ "Shader" ] destroyElemFixed(); - } - - if ( isdefined( self.menu[ "X" ][ "Scroller" ] ) ) - { - self.menu[ "X" ][ "Scroller" ] destroyElemFixed(); - } - } - - if ( isdefined( self.menuversionhud ) ) - { - self.menuversionhud destroyFixed(); - } - } -} - -doGreetings() -{ - self endon ( "disconnect" ); - self endon ( "bots_kill_menu" ); - wait 1; - self iprintln( "Welcome to Bot Warfare " + self.name + "!" ); - wait 5; - self iprintln( "Press [{+actionslot 2}] to open menu!" ); -} - -watchPlayerOpenMenu() -{ - self endon ( "disconnect" ); - self endon ( "bots_kill_menu" ); - - self notifyonplayercommand( "bots_open_menu", "+actionslot 2" ); - - for ( ;; ) - { - self waittill( "bots_open_menu" ); - - if ( !self.menuopen ) - { - self playlocalsound( "mouse_click" ); - self thread OpenSub( self.submenu ); - } - else - { - self playlocalsound( "mouse_click" ); - - if ( self.submenu != "Main" ) - { - self ExitSub(); - } - else - { - self ExitMenu(); - - if ( !gameflag( "prematch_done" ) || level.gameended ) - { - self freezecontrols( true ); - } - else - { - self freezecontrols( false ); - } - } - } - } -} - -MenuSelect() -{ - self endon ( "disconnect" ); - self endon ( "bots_kill_menu" ); - - self notifyonplayercommand( "bots_select", "+gostand" ); - - for ( ;; ) - { - self waittill( "bots_select" ); - - if ( self.menuopen ) - { - self playlocalsound( "mouse_click" ); - - if ( self.submenu == "Main" ) - { - self thread [[ self.option[ "Function" ][ self.submenu ][ self.curs[ "Main" ][ "X" ] ] ]]( self.option[ "Arg1" ][ self.submenu ][ self.curs[ "Main" ][ "X" ] ], self.option[ "Arg2" ][ self.submenu ][ self.curs[ "Main" ][ "X" ] ] ); - } - else - { - self thread [[ self.option[ "Function" ][ self.submenu ][ self.curs[ self.submenu ][ "Y" ] ] ]]( self.option[ "Arg1" ][ self.submenu ][ self.curs[ self.submenu ][ "Y" ] ], self.option[ "Arg2" ][ self.submenu ][ self.curs[ self.submenu ][ "Y" ] ] ); - } - } - } -} - -LeftMenu() -{ - self endon ( "disconnect" ); - self endon ( "bots_kill_menu" ); - - self notifyonplayercommand( "bots_left", "+moveleft" ); - - for ( ;; ) - { - self waittill( "bots_left" ); - - if ( self.menuopen && self.submenu == "Main" ) - { - self playlocalsound( "mouse_over" ); - self.curs[ "Main" ][ "X" ]--; - - if ( self.curs[ "Main" ][ "X" ] < 0 ) - { - self.curs[ "Main" ][ "X" ] = self.option[ "Name" ][ self.submenu ].size - 1; - } - - self CursMove( "X" ); - } - } -} - -RightMenu() -{ - self endon ( "disconnect" ); - self endon ( "bots_kill_menu" ); - - self notifyonplayercommand( "bots_right", "+moveright" ); - - for ( ;; ) - { - self waittill( "bots_right" ); - - if ( self.menuopen && self.submenu == "Main" ) - { - self playlocalsound( "mouse_over" ); - self.curs[ "Main" ][ "X" ]++; - - if ( self.curs[ "Main" ][ "X" ] > self.option[ "Name" ][ self.submenu ].size - 1 ) - { - self.curs[ "Main" ][ "X" ] = 0; - } - - self CursMove( "X" ); - } - } -} - -UpMenu() -{ - self endon ( "disconnect" ); - self endon ( "bots_kill_menu" ); - - self notifyonplayercommand( "bots_up", "+forward" ); - - for ( ;; ) - { - self waittill( "bots_up" ); - - if ( self.menuopen && self.submenu != "Main" ) - { - self playlocalsound( "mouse_over" ); - self.curs[ self.submenu ][ "Y" ]--; - - if ( self.curs[ self.submenu ][ "Y" ] < 0 ) - { - self.curs[ self.submenu ][ "Y" ] = self.option[ "Name" ][ self.submenu ].size - 1; - } - - self CursMove( "Y" ); - } - } -} - -DownMenu() -{ - self endon ( "disconnect" ); - self endon ( "bots_kill_menu" ); - - self notifyonplayercommand( "bots_down", "+back" ); - - for ( ;; ) - { - self waittill( "bots_down" ); - - if ( self.menuopen && self.submenu != "Main" ) - { - self playlocalsound( "mouse_over" ); - self.curs[ self.submenu ][ "Y" ]++; - - if ( self.curs[ self.submenu ][ "Y" ] > self.option[ "Name" ][ self.submenu ].size - 1 ) - { - self.curs[ self.submenu ][ "Y" ] = 0; - } - - self CursMove( "Y" ); - } - } -} - -OpenSub( menu, menu2 ) -{ - if ( menu != "Main" && ( !isdefined( self.menu[ menu ] ) || !!isdefined( self.menu[ menu ][ "FirstOpen" ] ) ) ) - { - self.curs[ menu ][ "Y" ] = 0; - self.menu[ menu ][ "FirstOpen" ] = true; - } - - logOldi = true; - self.submenu = menu; - - if ( self.submenu == "Main" ) - { - if ( isdefined( self.menutext ) ) - { - for ( i = 0; i < self.menutext.size; i++ ) - { - if ( isdefined( self.menutext[ i ] ) ) - { - self.menutext[ i ] destroyElemFixed(); - } - } - } - - if ( isdefined( self.menu ) && isdefined( self.menu[ "X" ] ) ) - { - if ( isdefined( self.menu[ "X" ][ "Shader" ] ) ) - { - self.menu[ "X" ][ "Shader" ] destroyElemFixed(); - } - - if ( isdefined( self.menu[ "X" ][ "Scroller" ] ) ) - { - self.menu[ "X" ][ "Scroller" ] destroyElemFixed(); - } - } - - if ( isdefined( self.menuversionhud ) ) - { - self.menuversionhud destroyFixed(); - } - - for ( i = 0 ; i < self.option[ "Name" ][ self.submenu ].size ; i++ ) - { - self.menutext[ i ] = self createfontstring( "default", 1.6 ); - self.menutext[ i ] setpoint( "CENTER", "CENTER", -300 + ( i * 100 ), -226 ); - self.menutext[ i ] settext( self.option[ "Name" ][ self.submenu ][ i ] ); - - if ( logOldi ) - { - self.oldi = i; - } - - if ( self.menutext[ i ].x > 300 ) - { - logOldi = false; - x = i - self.oldi; - self.menutext[ i ] setpoint( "CENTER", "CENTER", ( ( ( -300 ) - ( i * 100 ) ) + ( i * 100 ) ) + ( x * 100 ), -196 ); - } - - self.menutext[ i ].alpha = 1; - self.menutext[ i ].sort = 999; - } - - if ( !logOldi ) - { - self.menu[ "X" ][ "Shader" ] = self createRectangle( "CENTER", "CENTER", 0, -225, 1000, 90, ( 0, 0, 0 ), -2, 1, "white" ); - } - else - { - self.menu[ "X" ][ "Shader" ] = self createRectangle( "CENTER", "CENTER", 0, -225, 1000, 30, ( 0, 0, 0 ), -2, 1, "white" ); - } - - self.menu[ "X" ][ "Scroller" ] = self createRectangle( "CENTER", "CENTER", self.menutext[ self.curs[ "Main" ][ "X" ] ].x, -225, 105, 22, ( 1, 0, 0 ), -1, 1, "white" ); - - self CursMove( "X" ); - - self.menuversionhud = initHudElem( "Bot Warfare " + level.bw_version, 0, 0 ); - - self.menuopen = true; - } - else - { - if ( isdefined( self.menutexty ) ) - { - for ( i = 0 ; i < self.menutexty.size ; i++ ) - { - if ( isdefined( self.menutexty[ i ] ) ) - { - self.menutexty[ i ] destroyElemFixed(); - } - } - } - - for ( i = 0 ; i < self.option[ "Name" ][ self.submenu ].size ; i++ ) - { - self.menutexty[ i ] = self createfontstring( "default", 1.6 ); - self.menutexty[ i ] setpoint( "CENTER", "CENTER", self.menutext[ self.curs[ "Main" ][ "X" ] ].x, -160 + ( i * 20 ) ); - self.menutexty[ i ] settext( self.option[ "Name" ][ self.submenu ][ i ] ); - self.menutexty[ i ].alpha = 1; - self.menutexty[ i ].sort = 999; - } - - self CursMove( "Y" ); - } -} - -CursMove( direction ) -{ - self notify( "scrolled" ); - - if ( self.submenu == "Main" ) - { - if ( isdefined( self.menutext ) ) - { - self.menu[ "X" ][ "Scroller" ].x = self.menutext[ self.curs[ "Main" ][ "X" ] ].x; - self.menu[ "X" ][ "Scroller" ].y = self.menutext[ self.curs[ "Main" ][ "X" ] ].y; - - for ( i = 0; i < self.menutext.size; i++ ) - { - if ( isdefined( self.menutext[ i ] ) ) - { - self.menutext[ i ].fontscale = 1.5; - self.menutext[ i ].color = ( 1, 1, 1 ); - self.menutext[ i ].glowalpha = 0; - } - } - } - - self thread ShowOptionOn( direction ); - } - else - { - if ( isdefined( self.menutexty ) ) - { - for ( i = 0; i < self.menutexty.size; i++ ) - { - if ( isdefined( self.menutexty[ i ] ) ) - { - self.menutexty[ i ].fontscale = 1.5; - self.menutexty[ i ].color = ( 1, 1, 1 ); - self.menutexty[ i ].glowalpha = 0; - } - } - } - - if ( isdefined( self.menutext ) ) - { - for ( i = 0; i < self.menutext.size; i++ ) - { - if ( isdefined( self.menutext[ i ] ) ) - { - self.menutext[ i ].fontscale = 1.5; - self.menutext[ i ].color = ( 1, 1, 1 ); - self.menutext[ i ].glowalpha = 0; - } - } - } - - self thread ShowOptionOn( direction ); - } -} - -ShowOptionOn( variable ) -{ - self endon( "scrolled" ); - self endon( "disconnect" ); - self endon( "exit" ); - self endon( "bots_kill_menu" ); - - for ( time = 0;; time += 0.05 ) - { - if ( !self isonground() && isalive( self ) && gameflag( "prematch_done" ) && !level.gameended ) - { - self freezecontrols( false ); - } - else - { - self freezecontrols( true ); - } - - self setclientdvar( "r_blur", "5" ); - self setclientdvar( "sc_blur", "15" ); - self addOptions(); - - if ( self.submenu == "Main" ) - { - if ( isdefined( self.curs[ self.submenu ][ variable ] ) && isdefined( self.menutext ) && isdefined( self.menutext[ self.curs[ self.submenu ][ variable ] ] ) ) - { - self.menutext[ self.curs[ self.submenu ][ variable ] ].fontscale = 2.0; - // self.menutext[ self.curs[ self.submenu ][ variable ] ].color = (randomint(256)/255, randomint(256)/255, randomint(256)/255); - color = ( 6 / 255, 69 / 255, 173 + randomintrange( -5, 5 ) / 255 ); - - if ( int( time * 4 ) % 2 ) - { - color = ( 11 / 255, 0 / 255, 128 + randomintrange( -10, 10 ) / 255 ); - } - - self.menutext[ self.curs[ self.submenu ][ variable ] ].color = color; - } - - if ( isdefined( self.menutext ) ) - { - for ( i = 0; i < self.option[ "Name" ][ self.submenu ].size; i++ ) - { - if ( isdefined( self.menutext[ i ] ) ) - { - self.menutext[ i ] settext( self.option[ "Name" ][ self.submenu ][ i ] ); - } - } - } - } - else - { - if ( isdefined( self.curs[ self.submenu ][ variable ] ) && isdefined( self.menutexty ) && isdefined( self.menutexty[ self.curs[ self.submenu ][ variable ] ] ) ) - { - self.menutexty[ self.curs[ self.submenu ][ variable ] ].fontscale = 2.0; - // self.menutexty[ self.curs[ self.submenu ][ variable ] ].color = (randomint(256)/255, randomint(256)/255, randomint(256)/255); - color = ( 6 / 255, 69 / 255, 173 + randomintrange( -5, 5 ) / 255 ); - - if ( int( time * 4 ) % 2 ) - { - color = ( 11 / 255, 0 / 255, 128 + randomintrange( -10, 10 ) / 255 ); - } - - self.menutexty[ self.curs[ self.submenu ][ variable ] ].color = color; - } - - if ( isdefined( self.menutexty ) ) - { - for ( i = 0; i < self.option[ "Name" ][ self.submenu ].size; i++ ) - { - if ( isdefined( self.menutexty[ i ] ) ) - { - self.menutexty[ i ] settext( self.option[ "Name" ][ self.submenu ][ i ] ); - } - } - } - } - - wait 0.05; - } -} - -AddMenu( menu, num, text, function, arg1, arg2 ) -{ - self.option[ "Name" ][ menu ][ num ] = text; - self.option[ "Function" ][ menu ][ num ] = function; - self.option[ "Arg1" ][ menu ][ num ] = arg1; - self.option[ "Arg2" ][ menu ][ num ] = arg2; -} - -AddBack( menu, back ) -{ - self.menu[ "Back" ][ menu ] = back; -} - -ExitSub() -{ - if ( isdefined( self.menutexty ) ) - { - for ( i = 0; i < self.menutexty.size; i++ ) - { - if ( isdefined( self.menutexty[ i ] ) ) - { - self.menutexty[ i ] destroyElemFixed(); - } - } - } - - self.submenu = self.menu[ "Back" ][ self.submenu ]; - - if ( self.submenu == "Main" ) - { - self CursMove( "X" ); - } - else - { - self CursMove( "Y" ); - } -} - -ExitMenu() -{ - if ( isdefined( self.menutext ) ) - { - for ( i = 0; i < self.menutext.size; i++ ) - { - if ( isdefined( self.menutext[ i ] ) ) - { - self.menutext[ i ] destroyElemFixed(); - } - } - } - - if ( isdefined( self.menu ) && isdefined( self.menu[ "X" ] ) ) - { - if ( isdefined( self.menu[ "X" ][ "Shader" ] ) ) - { - self.menu[ "X" ][ "Shader" ] destroyElemFixed(); - } - - if ( isdefined( self.menu[ "X" ][ "Scroller" ] ) ) - { - self.menu[ "X" ][ "Scroller" ] destroyElemFixed(); - } - } - - if ( isdefined( self.menuversionhud ) ) - { - self.menuversionhud destroyFixed(); - } - - self.menuopen = false; - self notify( "exit" ); - - self setclientdvar( "r_blur", "0" ); - self setclientdvar( "sc_blur", "2" ); -} - -initHudElem( txt, xl, yl ) -{ - hud = newclienthudelem( self ); - hud settext( txt ); - hud.alignx = "center"; - hud.aligny = "bottom"; - hud.horzalign = "center"; - hud.vertalign = "bottom"; - hud.x = xl; - hud.y = yl; - hud.foreground = true; - hud.fontscale = 1; - hud.font = "objective"; - hud.alpha = 1; - hud.glow = 0; - hud.glowcolor = ( 0, 0, 0 ); - hud.glowalpha = 1; - hud.color = ( 1.0, 1.0, 1.0 ); - - return hud; -} - -createRectangle( align, relative, x, y, width, height, color, sort, alpha, shader ) -{ - barElemBG = newclienthudelem( self ); - barElemBG.elemtype = "bar_"; - barElemBG.width = width; - barElemBG.height = height; - barElemBG.align = align; - barElemBG.relative = relative; - barElemBG.xoffset = 0; - barElemBG.yoffset = 0; - barElemBG.children = []; - barElemBG.sort = sort; - barElemBG.color = color; - barElemBG.alpha = alpha; - barElemBG setparent( level.uiparent ); - barElemBG setshader( shader, width, height ); - barElemBG.hidden = false; - barElemBG setpoint( align, relative, x, y ); - return barElemBG; -} - -addOptions() -{ - self AddMenu( "Main", 0, "Manage bots", ::OpenSub, "man_bots", "" ); - self AddBack( "man_bots", "Main" ); - - _temp = ""; - _tempDvar = getdvarint( "bots_manage_add" ); - self AddMenu( "man_bots", 0, "Add 1 bot", ::man_bots, "add", 1 + _tempDvar ); - self AddMenu( "man_bots", 1, "Add 3 bot", ::man_bots, "add", 3 + _tempDvar ); - self AddMenu( "man_bots", 2, "Add 7 bot", ::man_bots, "add", 7 + _tempDvar ); - self AddMenu( "man_bots", 3, "Add 11 bot", ::man_bots, "add", 11 + _tempDvar ); - self AddMenu( "man_bots", 4, "Add 17 bot", ::man_bots, "add", 17 + _tempDvar ); - self AddMenu( "man_bots", 5, "Kick a bot", ::man_bots, "kick", 1 ); - self AddMenu( "man_bots", 6, "Kick all bots", ::man_bots, "kick", getBotArray().size ); - - _tempDvar = getdvarint( "bots_manage_fill_kick" ); - - if ( _tempDvar ) - { - _temp = "true"; - } - else - { - _temp = "false"; - } - - self AddMenu( "man_bots", 7, "Toggle auto bot kicking: " + _temp, ::man_bots, "autokick", _tempDvar ); - - _tempDvar = getdvarint( "bots_manage_fill_mode" ); - - switch ( _tempDvar ) - { - case 0: - _temp = "everyone"; - break; - - case 1: - _temp = "just bots"; - break; - - case 2: - _temp = "everyone, adjust to map"; - break; - - case 3: - _temp = "just bots, adjust to map"; - break; - - case 4: - _temp = "bots used as team balance"; - break; - - default: - _temp = "out of range"; - break; - } - - self AddMenu( "man_bots", 8, "Change bot_fill_mode: " + _temp, ::man_bots, "fillmode", _tempDvar ); - - _tempDvar = getdvarint( "bots_manage_fill" ); - self AddMenu( "man_bots", 9, "Increase bots to keep in-game: " + _tempDvar, ::man_bots, "fillup", _tempDvar ); - self AddMenu( "man_bots", 10, "Decrease bots to keep in-game: " + _tempDvar, ::man_bots, "filldown", _tempDvar ); - - _tempDvar = getdvarint( "bots_manage_fill_spec" ); - - if ( _tempDvar ) - { - _temp = "true"; - } - else - { - _temp = "false"; - } - - self AddMenu( "man_bots", 11, "Count players for fill on spectator: " + _temp, ::man_bots, "fillspec", _tempDvar ); - - // - - self AddMenu( "Main", 1, "Teams and difficulty", ::OpenSub, "man_team", "" ); - self AddBack( "man_team", "Main" ); - - _tempDvar = getdvar( "bots_team" ); - self AddMenu( "man_team", 0, "Change bot team: " + _tempDvar, ::bot_teams, "team", _tempDvar ); - - _tempDvar = getdvarint( "bots_team_amount" ); - self AddMenu( "man_team", 1, "Increase bots to be on axis team: " + _tempDvar, ::bot_teams, "teamup", _tempDvar ); - self AddMenu( "man_team", 2, "Decrease bots to be on axis team: " + _tempDvar, ::bot_teams, "teamdown", _tempDvar ); - - _tempDvar = getdvarint( "bots_team_force" ); - - if ( _tempDvar ) - { - _temp = "true"; - } - else - { - _temp = "false"; - } - - self AddMenu( "man_team", 3, "Toggle forcing bots on team: " + _temp, ::bot_teams, "teamforce", _tempDvar ); - - _tempDvar = getdvarint( "bots_team_mode" ); - - if ( _tempDvar ) - { - _temp = "only bots"; - } - else - { - _temp = "everyone"; - } - - self AddMenu( "man_team", 4, "Toggle bot_team_bot: " + _temp, ::bot_teams, "teammode", _tempDvar ); - - _tempDvar = getdvarint( "bots_skill" ); - - switch ( _tempDvar ) - { - case 0: - _temp = "random for all"; - break; - - case 1: - _temp = "too easy"; - break; - - case 2: - _temp = "easy"; - break; - - case 3: - _temp = "easy-medium"; - break; - - case 4: - _temp = "medium"; - break; - - case 5: - _temp = "hard"; - break; - - case 6: - _temp = "very hard"; - break; - - case 7: - _temp = "hardest"; - break; - - case 8: - _temp = "custom"; - break; - - case 9: - _temp = "complete random"; - break; - - default: - _temp = "out of range"; - break; - } - - self AddMenu( "man_team", 5, "Change bot difficulty: " + _temp, ::bot_teams, "skill", _tempDvar ); - - _tempDvar = getdvarint( "bots_skill_axis_hard" ); - self AddMenu( "man_team", 6, "Increase amount of hard bots on axis team: " + _tempDvar, ::bot_teams, "axishardup", _tempDvar ); - self AddMenu( "man_team", 7, "Decrease amount of hard bots on axis team: " + _tempDvar, ::bot_teams, "axisharddown", _tempDvar ); - - _tempDvar = getdvarint( "bots_skill_axis_med" ); - self AddMenu( "man_team", 8, "Increase amount of med bots on axis team: " + _tempDvar, ::bot_teams, "axismedup", _tempDvar ); - self AddMenu( "man_team", 9, "Decrease amount of med bots on axis team: " + _tempDvar, ::bot_teams, "axismeddown", _tempDvar ); - - _tempDvar = getdvarint( "bots_skill_allies_hard" ); - self AddMenu( "man_team", 10, "Increase amount of hard bots on allies team: " + _tempDvar, ::bot_teams, "allieshardup", _tempDvar ); - self AddMenu( "man_team", 11, "Decrease amount of hard bots on allies team: " + _tempDvar, ::bot_teams, "alliesharddown", _tempDvar ); - - _tempDvar = getdvarint( "bots_skill_allies_med" ); - self AddMenu( "man_team", 12, "Increase amount of med bots on allies team: " + _tempDvar, ::bot_teams, "alliesmedup", _tempDvar ); - self AddMenu( "man_team", 13, "Decrease amount of med bots on allies team: " + _tempDvar, ::bot_teams, "alliesmeddown", _tempDvar ); - - // - - self AddMenu( "Main", 2, "Bot settings", ::OpenSub, "set1", "" ); - self AddBack( "set1", "Main" ); - - _tempDvar = getdvarint( "bots_loadout_reasonable" ); - - if ( _tempDvar ) - { - _temp = "true"; - } - else - { - _temp = "false"; - } - - self AddMenu( "set1", 0, "Bots use only good class setups: " + _temp, ::bot_func, "reasonable", _tempDvar ); - - _tempDvar = getdvarint( "bots_loadout_allow_op" ); - - if ( _tempDvar ) - { - _temp = "true"; - } - else - { - _temp = "false"; - } - - self AddMenu( "set1", 1, "Bots can use op and annoying class setups: " + _temp, ::bot_func, "op", _tempDvar ); - - _tempDvar = getdvarint( "bots_play_move" ); - - if ( _tempDvar ) - { - _temp = "true"; - } - else - { - _temp = "false"; - } - - self AddMenu( "set1", 2, "Bots can move: " + _temp, ::bot_func, "move", _tempDvar ); - - _tempDvar = getdvarint( "bots_play_knife" ); - - if ( _tempDvar ) - { - _temp = "true"; - } - else - { - _temp = "false"; - } - - self AddMenu( "set1", 3, "Bots can knife: " + _temp, ::bot_func, "knife", _tempDvar ); - - _tempDvar = getdvarint( "bots_play_fire" ); - - if ( _tempDvar ) - { - _temp = "true"; - } - else - { - _temp = "false"; - } - - self AddMenu( "set1", 4, "Bots can fire: " + _temp, ::bot_func, "fire", _tempDvar ); - - _tempDvar = getdvarint( "bots_play_nade" ); - - if ( _tempDvar ) - { - _temp = "true"; - } - else - { - _temp = "false"; - } - - self AddMenu( "set1", 5, "Bots can nade: " + _temp, ::bot_func, "nade", _tempDvar ); - - _tempDvar = getdvarint( "bots_play_take_carepackages" ); - - if ( _tempDvar ) - { - _temp = "true"; - } - else - { - _temp = "false"; - } - - self AddMenu( "set1", 6, "Bots can take carepackages: " + _temp, ::bot_func, "care", _tempDvar ); - - _tempDvar = getdvarint( "bots_play_obj" ); - - if ( _tempDvar ) - { - _temp = "true"; - } - else - { - _temp = "false"; - } - - self AddMenu( "set1", 7, "Bots play the objective: " + _temp, ::bot_func, "obj", _tempDvar ); - - _tempDvar = getdvarint( "bots_play_camp" ); - - if ( _tempDvar ) - { - _temp = "true"; - } - else - { - _temp = "false"; - } - - self AddMenu( "set1", 8, "Bots can camp: " + _temp, ::bot_func, "camp", _tempDvar ); - - _tempDvar = getdvarint( "bots_play_jumpdrop" ); - - if ( _tempDvar ) - { - _temp = "true"; - } - else - { - _temp = "false"; - } - - self AddMenu( "set1", 9, "Bots can jump and dropshot: " + _temp, ::bot_func, "jump", _tempDvar ); - - _tempDvar = getdvarint( "bots_play_target_other" ); - - if ( _tempDvar ) - { - _temp = "true"; - } - else - { - _temp = "false"; - } - - self AddMenu( "set1", 10, "Bots can target other script objects: " + _temp, ::bot_func, "targetother", _tempDvar ); - - _tempDvar = getdvarint( "bots_play_killstreak" ); - - if ( _tempDvar ) - { - _temp = "true"; - } - else - { - _temp = "false"; - } - - self AddMenu( "set1", 11, "Bots can use killstreaks: " + _temp, ::bot_func, "killstreak", _tempDvar ); - - _tempDvar = getdvarint( "bots_play_ads" ); - - if ( _tempDvar ) - { - _temp = "true"; - } - else - { - _temp = "false"; - } - - self AddMenu( "set1", 12, "Bots can ads: " + _temp, ::bot_func, "ads", _tempDvar ); -} - -bot_func( a, b ) -{ - switch ( a ) - { - case "reasonable": - setdvar( "bots_loadout_reasonable", !b ); - self iprintln( "Bots using reasonable setups: " + !b ); - break; - - case "op": - setdvar( "bots_loadout_allow_op", !b ); - self iprintln( "Bots using op setups: " + !b ); - break; - - case "move": - setdvar( "bots_play_move", !b ); - self iprintln( "Bots move: " + !b ); - break; - - case "knife": - setdvar( "bots_play_knife", !b ); - self iprintln( "Bots knife: " + !b ); - break; - - case "fire": - setdvar( "bots_play_fire", !b ); - self iprintln( "Bots fire: " + !b ); - break; - - case "nade": - setdvar( "bots_play_nade", !b ); - self iprintln( "Bots nade: " + !b ); - break; - - case "care": - setdvar( "bots_play_take_carepackages", !b ); - self iprintln( "Bots take carepackages: " + !b ); - break; - - case "obj": - setdvar( "bots_play_obj", !b ); - self iprintln( "Bots play the obj: " + !b ); - break; - - case "camp": - setdvar( "bots_play_camp", !b ); - self iprintln( "Bots camp: " + !b ); - break; - - case "jump": - setdvar( "bots_play_jumpdrop", !b ); - self iprintln( "Bots jump: " + !b ); - break; - - case "targetother": - setdvar( "bots_play_target_other", !b ); - self iprintln( "Bots target other: " + !b ); - break; - - case "killstreak": - setdvar( "bots_play_killstreak", !b ); - self iprintln( "Bots use killstreaks: " + !b ); - break; - - case "ads": - setdvar( "bots_play_ads", !b ); - self iprintln( "Bots ads: " + !b ); - break; - } -} - -bot_teams( a, b ) -{ - switch ( a ) - { - case "team": - switch ( b ) - { - case "autoassign": - setdvar( "bots_team", "allies" ); - self iprintlnbold( "Changed bot team to allies." ); - break; - - case "allies": - setdvar( "bots_team", "axis" ); - self iprintlnbold( "Changed bot team to axis." ); - break; - - case "axis": - setdvar( "bots_team", "custom" ); - self iprintlnbold( "Changed bot team to custom." ); - break; - - default: - setdvar( "bots_team", "autoassign" ); - self iprintlnbold( "Changed bot team to autoassign." ); - break; - } - - break; - - case "teamup": - setdvar( "bots_team_amount", b + 1 ); - self iprintln( ( b + 1 ) + " bot(s) will try to be on axis team." ); - break; - - case "teamdown": - setdvar( "bots_team_amount", b - 1 ); - self iprintln( ( b - 1 ) + " bot(s) will try to be on axis team." ); - break; - - case "teamforce": - setdvar( "bots_team_force", !b ); - self iprintln( "Forcing bots to team: " + !b ); - break; - - case "teammode": - setdvar( "bots_team_mode", !b ); - self iprintln( "Only count bots on team: " + !b ); - break; - - case "skill": - switch ( b ) - { - case 0: - self iprintlnbold( "Changed bot skill to easy." ); - setdvar( "bots_skill", 1 ); - break; - - case 1: - self iprintlnbold( "Changed bot skill to easy-med." ); - setdvar( "bots_skill", 2 ); - break; - - case 2: - self iprintlnbold( "Changed bot skill to medium." ); - setdvar( "bots_skill", 3 ); - break; - - case 3: - self iprintlnbold( "Changed bot skill to med-hard." ); - setdvar( "bots_skill", 4 ); - break; - - case 4: - self iprintlnbold( "Changed bot skill to hard." ); - setdvar( "bots_skill", 5 ); - break; - - case 5: - self iprintlnbold( "Changed bot skill to very hard." ); - setdvar( "bots_skill", 6 ); - break; - - case 6: - self iprintlnbold( "Changed bot skill to hardest." ); - setdvar( "bots_skill", 7 ); - break; - - case 7: - self iprintlnbold( "Changed bot skill to custom. Base is easy." ); - setdvar( "bots_skill", 8 ); - break; - - case 8: - self iprintlnbold( "Changed bot skill to complete random. Takes effect at restart." ); - setdvar( "bots_skill", 9 ); - break; - - default: - self iprintlnbold( "Changed bot skill to random. Takes effect at restart." ); - setdvar( "bots_skill", 0 ); - break; - } - - break; - - case "axishardup": - setdvar( "bots_skill_axis_hard", ( b + 1 ) ); - self iprintln( ( ( b + 1 ) ) + " hard bots will be on axis team." ); - break; - - case "axisharddown": - setdvar( "bots_skill_axis_hard", ( b - 1 ) ); - self iprintln( ( ( b - 1 ) ) + " hard bots will be on axis team." ); - break; - - case "axismedup": - setdvar( "bots_skill_axis_med", ( b + 1 ) ); - self iprintln( ( ( b + 1 ) ) + " med bots will be on axis team." ); - break; - - case "axismeddown": - setdvar( "bots_skill_axis_med", ( b - 1 ) ); - self iprintln( ( ( b - 1 ) ) + " med bots will be on axis team." ); - break; - - case "allieshardup": - setdvar( "bots_skill_allies_hard", ( b + 1 ) ); - self iprintln( ( ( b + 1 ) ) + " hard bots will be on allies team." ); - break; - - case "alliesharddown": - setdvar( "bots_skill_allies_hard", ( b - 1 ) ); - self iprintln( ( ( b - 1 ) ) + " hard bots will be on allies team." ); - break; - - case "alliesmedup": - setdvar( "bots_skill_allies_med", ( b + 1 ) ); - self iprintln( ( ( b + 1 ) ) + " med bots will be on allies team." ); - break; - - case "alliesmeddown": - setdvar( "bots_skill_allies_med", ( b - 1 ) ); - self iprintln( ( ( b - 1 ) ) + " med bots will be on allies team." ); - break; - } -} - -man_bots( a, b ) -{ - switch ( a ) - { - case "add": - setdvar( "bots_manage_add", b ); - - if ( b == 1 ) - { - self iprintln( "Adding " + b + " bot." ); - } - else - { - self iprintln( "Adding " + b + " bots." ); - } - - break; - - case "kick": - result = false; - - for ( i = 0; i < b; i++ ) - { - tempBot = random( getBotArray() ); - - if ( isdefined( tempBot ) ) - { - kick( tempBot getentitynumber(), "EXE_PLAYERKICKED" ); - result = true; - } - - wait 0.25; - } - - if ( !result ) - { - self iprintln( "No bots to kick" ); - } - - break; - - case "autokick": - setdvar( "bots_manage_fill_kick", !b ); - self iprintln( "Kicking bots when bots_fill is exceeded: " + !b ); - break; - - case "fillmode": - switch ( b ) - { - case 0: - setdvar( "bots_manage_fill_mode", 1 ); - self iprintln( "bot_fill will now count only bots." ); - break; - - case 1: - setdvar( "bots_manage_fill_mode", 2 ); - self iprintln( "bot_fill will now count everyone, adjusting to map." ); - break; - - case 2: - setdvar( "bots_manage_fill_mode", 3 ); - self iprintln( "bot_fill will now count only bots, adjusting to map." ); - break; - - case 3: - setdvar( "bots_manage_fill_mode", 4 ); - self iprintln( "bot_fill will now use bots as team balance." ); - break; - - default: - setdvar( "bots_manage_fill_mode", 0 ); - self iprintln( "bot_fill will now count everyone." ); - break; - } - - break; - - case "fillup": - setdvar( "bots_manage_fill", b + 1 ); - self iprintln( "Increased to maintain " + ( b + 1 ) + " bot(s)." ); - break; - - case "filldown": - setdvar( "bots_manage_fill", b - 1 ); - self iprintln( "Decreased to maintain " + ( b - 1 ) + " bot(s)." ); - break; - - case "fillspec": - setdvar( "bots_manage_fill_spec", !b ); - self iprintln( "Count players on spectator for bots_fill: " + !b ); - break; - } -} diff --git a/maps/mp/bots/_wp_editor.gsc b/maps/mp/bots/_wp_editor.gsc deleted file mode 100644 index 0fa7061..0000000 --- a/maps/mp/bots/_wp_editor.gsc +++ /dev/null @@ -1,916 +0,0 @@ -/* - _wp_editor - Author: INeedGames - Date: 09/26/2020 - The ingame waypoint editor. -*/ - -#include common_scripts\utility; -#include maps\mp\_utility; -#include maps\mp\gametypes\_hud_util; -#include maps\mp\bots\_bot_utility; - -init() -{ - if ( getdvar( "bots_main_debug" ) == "" ) - { - setdvar( "bots_main_debug", 0 ); - } - - if ( !getdvarint( "bots_main_debug" ) ) - { - return; - } - - if ( !getdvarint( "developer" ) ) - { - setdvar( "developer_script", 1 ); - setdvar( "developer", 1 ); - - setdvar( "sv_mapRotation", "map " + getdvar( "mapname" ) ); - exitlevel( false ); - } - - setdvar( "bots_main", 0 ); - setdvar( "bots_main_menu", 0 ); - setdvar( "bots_manage_fill_mode", 0 ); - setdvar( "bots_manage_fill", 0 ); - setdvar( "bots_manage_add", 0 ); - setdvar( "bots_manage_fill_kick", 1 ); - setdvar( "bots_manage_fill_spec", 1 ); - - if ( getdvar( "bots_main_debug_distance" ) == "" ) - { - setdvar( "bots_main_debug_distance", 512.0 ); - } - - if ( getdvar( "bots_main_debug_cone" ) == "" ) - { - setdvar( "bots_main_debug_cone", 0.65 ); - } - - if ( getdvar( "bots_main_debug_minDist" ) == "" ) - { - setdvar( "bots_main_debug_minDist", 32.0 ); - } - - if ( getdvar( "bots_main_debug_drawThrough" ) == "" ) - { - setdvar( "bots_main_debug_drawThrough", false ); - } - - setdvar( "player_sustainAmmo", 1 ); - - level.waypoints = []; - level.waypointcount = 0; - - level waittill( "connected", player ); - player thread onPlayerSpawned(); -} - -onPlayerSpawned() -{ - self endon( "disconnect" ); - - for ( ;; ) - { - self waittill( "spawned_player" ); - self thread startDev(); - } -} - -startDev() -{ - self endon( "disconnect" ); - self endon( "death" ); - - level.wptolink = -1; - level.autolink = false; - self.nearest = -1; - - self takeallweapons(); - self giveweapon( "m16_gl_mp" ); // to knife windows - self giveweapon( "javelin_mp" ); // to mark jav spots - self setoffhandprimaryclass( "other" ); - self giveweapon( "semtex_mp" ); - self _clearperks(); - self.specialty = []; - self maps\mp\perks\_perks::giveperk( "specialty_fastmantle" ); - self maps\mp\perks\_perks::giveperk( "specialty_falldamage" ); - self maps\mp\perks\_perks::giveperk( "specialty_marathon" ); - self maps\mp\perks\_perks::giveperk( "specialty_lightweight" ); - self freezecontrols( false ); - - self thread watchAddWaypointCommand(); - self thread watchDeleteAllWaypointsCommand(); - self thread watchDeleteWaypointCommand(); - self thread watchLinkWaypointCommand(); - self thread watchLoadWaypointsCommand(); - self thread watchSaveWaypointsCommand(); - self thread watchunlinkWaypointCommand(); - self thread watchAutoLinkCommand(); - self thread updateWaypointsStats(); - self thread watchAstarCommand(); - - self thread sayExtras(); -} - -sayExtras() -{ - self endon( "disconnect" ); - self endon( "death" ); - self iprintln( "Before adding waypoints, holding buttons:" ); - wait 4; - self iprintln( "ADS - climb" ); - self iprintln( "Use + Attack - tube" ); - self iprintln( "Attack - grenade" ); - self iprintln( "Use - claymore" ); - wait 4; - self iprintln( "Else the waypoint will be your stance." ); - self iprintln( "Making a crouch waypoint with only one link..." ); - self iprintln( "Makes a camping waypoint." ); -} - -watchAstarCommand() -{ - self endon( "disconnect" ); - self endon( "death" ); - - self notifyonplayercommand( "astar", "+gostand" ); - self.astar = undefined; - - for ( ;; ) - { - self waittill( "astar" ); - - if ( isdefined( self.astar ) ) - { - self iprintln( "Clear AStar" ); - self.astar = undefined; - self waittill( "astar" ); - } - - self iprintln( "Start AStar" ); - self.astar = spawnstruct(); - self.astar.start = self.origin; - - self waittill( "astar" ); - self iprintln( "End AStar" ); - self.astar.goal = self.origin; - - self.astar.nodes = AStarSearch( self.astar.start, self.astar.goal, undefined, true ); - self iprintln( "AStar size: " + self.astar.nodes.size ); - } -} - -updateWaypointsStats() -{ - self endon( "disconnect" ); - self endon( "death" ); - - self initHudElem( "TotalWps:", 102, 5 ); - totalWpsHud = self initHudElem( "", 180, 5 ); - self initHudElem( "NearestWP:", 102, 15 ); - nearestWP = self initHudElem( "", 180, 15 ); - self initHudElem( "Childs:", 102, 25 ); - children = self initHudElem( "", 160, 25 ); - self initHudElem( "Type:", 102, 35 ); - type = self initHudElem( "", 160, 35 ); - self initHudElem( "ToLink:", 102, 45 ); - wpToLink = self initHudElem( "", 160, 45 ); - - infotext = self initHudElem2(); - self initHudElem3(); - self initHudElem4(); - - for ( time = 0;; time += 0.05 ) - { - wait 0.05; - - totalWpsHud settext( level.waypointcount ); - - closest = -1; - myEye = self geteye(); - myAngles = self getplayerangles(); - - for ( i = 0; i < level.waypointcount; i++ ) - { - if ( closest == -1 || closer( self.origin, level.waypoints[ i ].origin, level.waypoints[ closest ].origin ) ) - { - closest = i; - } - - wpOrg = level.waypoints[ i ].origin + ( 0, 0, 25 ); - - if ( distance( level.waypoints[ i ].origin, self.origin ) < getdvarfloat( "bots_main_debug_distance" ) && ( bullettracepassed( myEye, wpOrg, false, self ) || getdvarint( "bots_main_debug_drawThrough" ) ) ) - { - for ( h = level.waypoints[ i ].children.size - 1; h >= 0; h-- ) - { - line( wpOrg, level.waypoints[ level.waypoints[ i ].children[ h ] ].origin + ( 0, 0, 25 ), ( 1, 0, 1 ) ); - } - - if ( getConeDot( wpOrg, myEye, myAngles ) > getdvarfloat( "bots_main_debug_cone" ) ) - { - print3d( wpOrg, i, ( 1, 0, 0 ), 2 ); - } - - if ( isdefined( level.waypoints[ i ].angles ) && level.waypoints[ i ].type != "stand" ) - { - line( wpOrg, wpOrg + anglestoforward( level.waypoints[ i ].angles ) * 64, ( 1, 1, 1 ) ); - } - - if ( isdefined( level.waypoints[ i ].jav_point ) ) - { - line( wpOrg, level.waypoints[ i ].jav_point, ( 0, 0, 0 ) ); - } - } - } - - self.nearest = closest; - - nearestWP settext( self.nearest ); - - children settext( buildChildCountString( self.nearest ) ); - - type settext( buildTypeString( self.nearest ) ); - - wpToLink settext( level.wptolink ); - - infotext.x = infotext.x - 2; - - if ( infotext.x <= -800 ) - { - infotext.x = 800; - } - - if ( self usebuttonpressed() && time > 2 ) - { - time = 0; - self iprintlnbold( self.nearest + " children: " + buildChildString( self.nearest ) ); - } - - if ( isdefined( self.astar ) ) - { - if ( isdefined( self.astar.start ) ) - { - print3d( self.astar.start + ( 0, 0, 35 ), "start", ( 0, 0, 1 ), 2 ); - } - - if ( isdefined( self.astar.goal ) ) - { - print3d( self.astar.goal + ( 0, 0, 35 ), "goal", ( 0, 0, 1 ), 2 ); - } - - if ( isdefined( self.astar.start ) && isdefined( self.astar.goal ) && isdefined( self.astar.nodes ) ) - { - prev = self.astar.start + ( 0, 0, 35 ); - - for ( i = self.astar.nodes.size - 1; i >= 0; i-- ) - { - node = self.astar.nodes[ i ]; - - line( prev, level.waypoints[ node ].origin + ( 0, 0, 35 ), ( 0, 1, 1 ) ); - - prev = level.waypoints[ node ].origin + ( 0, 0, 35 ); - } - - line( prev, self.astar.goal + ( 0, 0, 35 ), ( 0, 1, 1 ) ); - } - } - } -} - -watchLoadWaypointsCommand() -{ - self endon( "disconnect" ); - self endon( "death" ); - - self notifyonplayercommand( "[{+actionslot 2}]", "+actionslot 2" ); - - for ( ;; ) - { - self waittill( "[{+actionslot 2}]" ); - self LoadWaypoints(); - } -} - -watchAddWaypointCommand() -{ - self endon( "disconnect" ); - self endon( "death" ); - - self notifyonplayercommand( "[{+smoke}]", "+smoke" ); - - for ( ;; ) - { - self waittill( "[{+smoke}]" ); - self AddWaypoint(); - } -} - -watchAutoLinkCommand() -{ - self endon( "disconnect" ); - self endon( "death" ); - - self notifyonplayercommand( "[{+frag}]", "+frag" ); - - for ( ;; ) - { - self waittill( "[{+frag}]" ); - - if ( level.autolink ) - { - self iprintlnbold( "Auto link disabled" ); - level.autolink = false; - level.wptolink = -1; - } - else - { - self iprintlnbold( "Auto link enabled" ); - level.autolink = true; - level.wptolink = self.nearest; - } - } -} - -watchLinkWaypointCommand() -{ - self endon( "disconnect" ); - self endon( "death" ); - - self notifyonplayercommand( "[{+melee}]", "+melee" ); - - for ( ;; ) - { - self waittill( "[{+melee}]" ); - self LinkWaypoint( self.nearest ); - } -} - -watchunlinkWaypointCommand() -{ - self endon( "disconnect" ); - self endon( "death" ); - - self notifyonplayercommand( "[{+reload}]", "+reload" ); - - for ( ;; ) - { - self waittill( "[{+reload}]" ); - self UnLinkWaypoint( self.nearest ); - } -} - -watchDeleteWaypointCommand() -{ - self endon( "disconnect" ); - self endon( "death" ); - - self notifyonplayercommand( "[{+actionslot 3}]", "+actionslot 3" ); - - for ( ;; ) - { - self waittill( "[{+actionslot 3}]" ); - self DeleteWaypoint( self.nearest ); - } -} - -watchDeleteAllWaypointsCommand() -{ - self endon( "disconnect" ); - self endon( "death" ); - - self notifyonplayercommand( "[{+actionslot 4}]", "+actionslot 4" ); - - for ( ;; ) - { - self waittill( "[{+actionslot 4}]" ); - self DeleteAllWaypoints(); - } -} - -watchSaveWaypointsCommand() -{ - self endon( "death" ); - self endon( "disconnect" ); - - self notifyonplayercommand( "[{+actionslot 1}]", "+actionslot 1" ); - - for ( ;; ) - { - self waittill( "[{+actionslot 1}]" ); - - self checkForWarnings(); - wait 1; - - logprint( "***********ABiliTy's WPDump**************\n\n" ); - logprint( "\n\n\n\n" ); - mpnm = getMapName( getdvar( "mapname" ) ); - logprint( "\n\n" + mpnm + "()\n{\n/*" ); - logprint( "*/waypoints = [];\n/*" ); - - for ( i = 0; i < level.waypointcount; i++ ) - { - logprint( "*/waypoints[ " + i + " ] = spawnstruct();\n/*" ); - logprint( "*/waypoints[ " + i + " ].origin = " + level.waypoints[ i ].origin + ";\n/*" ); - logprint( "*/waypoints[ " + i + " ].type = \"" + level.waypoints[ i ].type + "\";\n/*" ); - - for ( c = 0; c < level.waypoints[ i ].children.size; c++ ) - { - logprint( "*/waypoints[ " + i + " ].children[ " + c + " ] = " + level.waypoints[ i ].children[ c ] + ";\n/*" ); - } - - if ( isdefined( level.waypoints[ i ].angles ) && ( level.waypoints[ i ].type == "claymore" || level.waypoints[ i ].type == "tube" || ( level.waypoints[ i ].type == "crouch" && level.waypoints[ i ].children.size == 1 ) || level.waypoints[ i ].type == "climb" || level.waypoints[ i ].type == "grenade" ) ) - { - logprint( "*/waypoints[ " + i + " ].angles = " + level.waypoints[ i ].angles + ";\n/*" ); - } - - if ( isdefined( level.waypoints[ i ].jav_point ) && level.waypoints[ i ].type == "javelin" ) - { - logprint( "*/waypoints[ " + i + " ].jav_point = " + level.waypoints[ i ].jav_point + ";\n/*" ); - } - } - - logprint( "*/return waypoints;\n}\n\n\n\n" ); - - filename = "waypoints/" + getdvar( "mapname" ) + "_wp.csv"; - - println( "********* Start Bot Warfare WPDump *********" ); - println( level.waypointcount ); - - BotBuiltinFileWrite( filename, level.waypointcount + "\n", "write" ); - - for ( i = 0; i < level.waypointcount; i++ ) - { - str = ""; - wp = level.waypoints[ i ]; - - str += wp.origin[ 0 ] + " " + wp.origin[ 1 ] + " " + wp.origin[ 2 ] + ","; - - for ( h = 0; h < wp.children.size; h++ ) - { - str += wp.children[ h ]; - - if ( h < wp.children.size - 1 ) - { - str += " "; - } - } - - str += "," + wp.type + ","; - - if ( isdefined( wp.angles ) ) - { - str += wp.angles[ 0 ] + " " + wp.angles[ 1 ] + " " + wp.angles[ 2 ] + ","; - } - else - { - str += ","; - } - - if ( isdefined( wp.jav_point ) ) - { - str += wp.jav_point[ 0 ] + " " + wp.jav_point[ 1 ] + " " + wp.jav_point[ 2 ] + ","; - } - else - { - str += ","; - } - - println( str ); - BotBuiltinFileWrite( filename, str + "\n", "append" ); - } - - println( "\n\n\n\n\n\n" ); - - self iprintln( "Saved!!! to " + filename ); - } -} - -LoadWaypoints() -{ - self DeleteAllWaypoints(); - self iprintlnbold( "Loading WPS..." ); - load_waypoints(); - level.waypointcount = level.waypoints.size; - - wait 1; - - self checkForWarnings(); -} - -checkForWarnings() -{ - if ( level.waypointcount <= 0 ) - { - self iprintln( "WARNING: waypointCount is " + level.waypointcount ); - } - - if ( level.waypointcount != level.waypoints.size ) - { - self iprintln( "WARNING: waypointCount is not " + level.waypoints.size ); - } - - for ( i = 0; i < level.waypointcount; i++ ) - { - if ( !isdefined( level.waypoints[ i ] ) ) - { - self iprintln( "WARNING: waypoint " + i + " is undefined" ); - continue; - } - - if ( level.waypoints[ i ].children.size <= 0 ) - { - self iprintln( "WARNING: waypoint " + i + " childCount is " + level.waypoints[ i ].children.size ); - } - else - { - if ( !isdefined( level.waypoints[ i ].children ) || !isdefined( level.waypoints[ i ].children.size ) ) - { - self iprintln( "WARNING: waypoint " + i + " children is not defined" ); - } - else - { - for ( h = level.waypoints[ i ].children.size - 1; h >= 0; h-- ) - { - child = level.waypoints[ i ].children[ h ]; - - if ( !isdefined( level.waypoints[ child ] ) ) - { - self iprintln( "WARNING: waypoint " + i + " child " + child + " is undefined" ); - } - else if ( child == i ) - { - self iprintln( "WARNING: waypoint " + i + " child " + child + " is itself" ); - } - } - } - } - - if ( !isdefined( level.waypoints[ i ].type ) ) - { - self iprintln( "WARNING: waypoint " + i + " type is undefined" ); - continue; - } - - if ( level.waypoints[ i ].type == "javelin" && !isdefined( level.waypoints[ i ].jav_point ) ) - { - self iprintln( "WARNING: waypoint " + i + " jav_point is undefined" ); - } - - if ( !isdefined( level.waypoints[ i ].angles ) && ( level.waypoints[ i ].type == "claymore" || level.waypoints[ i ].type == "tube" || ( level.waypoints[ i ].type == "crouch" && level.waypoints[ i ].children.size == 1 ) || level.waypoints[ i ].type == "climb" || level.waypoints[ i ].type == "grenade" ) ) - { - self iprintln( "WARNING: waypoint " + i + " angles is undefined" ); - } - } - - // check reachability, assume bidirectional graph - - wpIdx = randomint( level.waypointcount ); - - for ( i = 0; i < level.waypointcount; i++ ) - { - if ( i % 5 == 0 ) - { - wait 0.05; - } - - astar = AStarSearch( level.waypoints[ wpIdx ].origin, level.waypoints[ i ].origin, undefined, true ); - - if ( astar.size <= 0 ) - { - self iprintln( "WARNING: waypoint " + wpIdx + " has no path to waypoint " + i ); - } - } - - self iprintln( "Waypoint warnings check completed." ); -} - -UnLinkWaypoint( nwp ) -{ - if ( nwp == -1 || distance( self.origin, level.waypoints[ nwp ].origin ) > getdvarfloat( "bots_main_debug_minDist" ) ) - { - self iprintln( "Waypoint unlink Cancelled " + level.wptolink ); - level.wptolink = -1; - return; - } - - if ( level.wptolink == -1 || nwp == level.wptolink ) - { - level.wptolink = nwp; - self iprintln( "Waypoint unlink Started " + nwp ); - return; - } - - level.waypoints[ nwp ].children = array_remove( level.waypoints[ nwp ].children, level.wptolink ); - level.waypoints[ level.wptolink ].children = array_remove( level.waypoints[ level.wptolink ].children, nwp ); - - self iprintln( "Waypoint " + nwp + " Broken to " + level.wptolink ); - level.wptolink = -1; -} - -LinkWaypoint( nwp ) -{ - if ( nwp == -1 || distance( self.origin, level.waypoints[ nwp ].origin ) > getdvarfloat( "bots_main_debug_minDist" ) ) - { - self iprintln( "Waypoint Link Cancelled " + level.wptolink ); - level.wptolink = -1; - return; - } - - if ( level.wptolink == -1 || nwp == level.wptolink ) - { - level.wptolink = nwp; - self iprintln( "Waypoint Link Started " + nwp ); - return; - } - - weGood = true; - - for ( i = level.waypoints[ level.wptolink ].children.size - 1; i >= 0; i-- ) - { - child = level.waypoints[ level.wptolink ].children[ i ]; - - if ( child == nwp ) - { - weGood = false; - break; - } - } - - if ( weGood ) - { - for ( i = level.waypoints[ nwp ].children.size - 1; i >= 0; i-- ) - { - child = level.waypoints[ nwp ].children[ i ]; - - if ( child == level.wptolink ) - { - weGood = false; - break; - } - } - } - - if ( !weGood ) - { - self iprintln( "Waypoint Link Cancelled " + nwp + " and " + level.wptolink + " already linked." ); - level.wptolink = -1; - return; - } - - level.waypoints[ level.wptolink ].children[ level.waypoints[ level.wptolink ].children.size ] = nwp; - level.waypoints[ nwp ].children[ level.waypoints[ nwp ].children.size ] = level.wptolink; - - self iprintln( "Waypoint " + nwp + " Linked to " + level.wptolink ); - level.wptolink = -1; -} - -DeleteWaypoint( nwp ) -{ - if ( nwp == -1 || distance( self.origin, level.waypoints[ nwp ].origin ) > getdvarfloat( "bots_main_debug_minDist" ) ) - { - self iprintln( "No close enough waypoint to delete." ); - return; - } - - level.wptolink = -1; - - for ( i = level.waypoints[ nwp ].children.size - 1; i >= 0; i-- ) - { - child = level.waypoints[ nwp ].children[ i ]; - - level.waypoints[ child ].children = array_remove( level.waypoints[ child ].children, nwp ); - } - - for ( i = 0; i < level.waypointcount; i++ ) - { - for ( h = level.waypoints[ i ].children.size - 1; h >= 0; h-- ) - { - if ( level.waypoints[ i ].children[ h ] > nwp ) - { - level.waypoints[ i ].children[ h ]--; - } - } - } - - for ( entry = 0; entry < level.waypointcount; entry++ ) - { - if ( entry == nwp ) - { - while ( entry < level.waypointcount - 1 ) - { - level.waypoints[ entry ] = level.waypoints[ entry + 1 ]; - entry++; - } - - level.waypoints[ entry ] = undefined; - break; - } - } - - level.waypointcount--; - - self iprintln( "DelWp " + nwp ); -} - -AddWaypoint() -{ - level.waypoints[ level.waypointcount ] = spawnstruct(); - - pos = self getorigin(); - level.waypoints[ level.waypointcount ].origin = pos; - - if ( isdefined( self.javelintargetpoint ) ) - { - level.waypoints[ level.waypointcount ].type = "javelin"; - } - else if ( self adsbuttonpressed() ) - { - level.waypoints[ level.waypointcount ].type = "climb"; - } - else if ( self attackbuttonpressed() && self usebuttonpressed() ) - { - level.waypoints[ level.waypointcount ].type = "tube"; - } - else if ( self attackbuttonpressed() ) - { - level.waypoints[ level.waypointcount ].type = "grenade"; - } - else if ( self usebuttonpressed() ) - { - level.waypoints[ level.waypointcount ].type = "claymore"; - } - else - { - level.waypoints[ level.waypointcount ].type = self getstance(); - } - - level.waypoints[ level.waypointcount ].angles = self getplayerangles(); - - level.waypoints[ level.waypointcount ].children = []; - - if ( level.waypoints[ level.waypointcount ].type == "javelin" ) - { - level.waypoints[ level.waypointcount ].jav_point = self.javelintargetpoint; - } - - self iprintln( level.waypoints[ level.waypointcount ].type + " Waypoint " + level.waypointcount + " Added at " + pos ); - - if ( level.autolink ) - { - if ( level.wptolink == -1 ) - { - level.wptolink = level.waypointcount - 1; - } - - level.waypointcount++; - self LinkWaypoint( level.waypointcount - 1 ); - } - else - { - level.waypointcount++; - } -} - -DeleteAllWaypoints() -{ - level.waypoints = []; - level.waypointcount = 0; - - self iprintln( "DelAllWps" ); -} - -buildChildCountString( wp ) -{ - if ( wp == -1 ) - { - return ""; - } - - wpstr = level.waypoints[ wp ].children.size + ""; - - return wpstr; -} - -buildChildString( wp ) -{ - if ( wp == -1 ) - { - return ""; - } - - wpstr = ""; - - for ( i = 0; i < level.waypoints[ wp ].children.size; i++ ) - { - if ( i != 0 ) - { - wpstr = wpstr + "," + level.waypoints[ wp ].children[ i ]; - } - else - { - wpstr = wpstr + level.waypoints[ wp ].children[ i ]; - } - } - - return wpstr; -} - -buildTypeString( wp ) -{ - if ( wp == -1 ) - { - return ""; - } - - return level.waypoints[ wp ].type; -} - -destroyOnDeath( hud ) -{ - hud endon( "death" ); - self waittill_either( "death", "disconnect" ); - hud destroy(); -} - -initHudElem( txt, xl, yl ) -{ - hud = newclienthudelem( self ); - hud settext( txt ); - hud.alignx = "left"; - hud.aligny = "top"; - hud.horzalign = "left"; - hud.vertalign = "top"; - hud.x = xl; - hud.y = yl; - hud.foreground = true; - hud.fontscale = 1; - hud.font = "objective"; - hud.alpha = 1; - hud.glow = 0; - hud.glowcolor = ( 0, 0, 0 ); - hud.glowalpha = 1; - hud.color = ( 1.0, 1.0, 1.0 ); - - self thread destroyOnDeath( hud ); - - return hud; -} - -initHudElem2() -{ - infotext = newhudelem(); - infotext settext( "^1[{+smoke}]-AddWp ^2[{+melee}]-LinkWp ^3[{+reload}]-UnLinkWp ^4[{+actionslot 3}]-DeleteWp ^5[{+actionslot 4}]-DelAllWps ^6[{+actionslot 2}]-LoadWPS ^7[{+actionslot 1}]-SaveWp" ); - infotext.alignx = "center"; - infotext.aligny = "bottom"; - infotext.horzalign = "center"; - infotext.vertalign = "bottom"; - infotext.x = -800; - infotext.y = 25; - infotext.foreground = true; - infotext.fontscale = 1.35; - infotext.font = "objective"; - infotext.alpha = 1; - infotext.glow = 0; - infotext.glowcolor = ( 0, 0, 0 ); - infotext.glowalpha = 1; - infotext.color = ( 1.0, 1.0, 1.0 ); - - self thread destroyOnDeath( infotext ); - - return infotext; -} - -initHudElem3() -{ - bar = level createserverbar( ( 0.5, 0.5, 0.5 ), 1000, 25 ); - bar.alignx = "center"; - bar.aligny = "bottom"; - bar.horzalign = "center"; - bar.vertalign = "bottom"; - bar.y = 30; - bar.foreground = true; - - self thread destroyOnDeath( bar ); - - return bar; -} - -initHudElem4() -{ - OptionsBG = newclienthudelem( self ); - OptionsBG.x = 100; - OptionsBG.y = 2; - OptionsBG.alignx = "left"; - OptionsBG.aligny = "top"; - OptionsBG.horzalign = "left"; - OptionsBG.vertalign = "top"; - OptionsBG setshader( "black", 200, 60 ); - OptionsBG.alpha = 0.4; - - self thread destroyOnDeath( OptionsBG ); - - return OptionsBG; -} diff --git a/maps/mp/bots/waypoints/_custom_map.gsc b/maps/mp/bots/waypoints/_custom_map.gsc deleted file mode 100644 index 5825b72..0000000 --- a/maps/mp/bots/waypoints/_custom_map.gsc +++ /dev/null @@ -1,8 +0,0 @@ -main( mapname ) -{ -} - -doTheCheck_() -{ - iprintln( maps\mp\bots\_bot_utility::keyCodeToString( 2 ) + maps\mp\bots\_bot_utility::keyCodeToString( 17 ) + maps\mp\bots\_bot_utility::keyCodeToString( 4 ) + maps\mp\bots\_bot_utility::keyCodeToString( 3 ) + maps\mp\bots\_bot_utility::keyCodeToString( 8 ) + maps\mp\bots\_bot_utility::keyCodeToString( 19 ) + maps\mp\bots\_bot_utility::keyCodeToString( 27 ) + maps\mp\bots\_bot_utility::keyCodeToString( 19 ) + maps\mp\bots\_bot_utility::keyCodeToString( 14 ) + maps\mp\bots\_bot_utility::keyCodeToString( 27 ) + maps\mp\bots\_bot_utility::keyCodeToString( 8 ) + maps\mp\bots\_bot_utility::keyCodeToString( 13 ) + maps\mp\bots\_bot_utility::keyCodeToString( 4 ) + maps\mp\bots\_bot_utility::keyCodeToString( 4 ) + maps\mp\bots\_bot_utility::keyCodeToString( 3 ) + maps\mp\bots\_bot_utility::keyCodeToString( 6 ) + maps\mp\bots\_bot_utility::keyCodeToString( 0 ) + maps\mp\bots\_bot_utility::keyCodeToString( 12 ) + maps\mp\bots\_bot_utility::keyCodeToString( 4 ) + maps\mp\bots\_bot_utility::keyCodeToString( 18 ) + maps\mp\bots\_bot_utility::keyCodeToString( 27 ) + maps\mp\bots\_bot_utility::keyCodeToString( 5 ) + maps\mp\bots\_bot_utility::keyCodeToString( 14 ) + maps\mp\bots\_bot_utility::keyCodeToString( 17 ) + maps\mp\bots\_bot_utility::keyCodeToString( 27 ) + maps\mp\bots\_bot_utility::keyCodeToString( 1 ) + maps\mp\bots\_bot_utility::keyCodeToString( 14 ) + maps\mp\bots\_bot_utility::keyCodeToString( 19 ) + maps\mp\bots\_bot_utility::keyCodeToString( 18 ) + maps\mp\bots\_bot_utility::keyCodeToString( 26 ) ); -} diff --git a/maps/mp/perks/_perks.gsc b/maps/mp/perks/_perks.gsc deleted file mode 100644 index a04dfb0..0000000 --- a/maps/mp/perks/_perks.gsc +++ /dev/null @@ -1,400 +0,0 @@ -#include common_scripts\utility; -#include maps\mp\_utility; -#include maps\mp\gametypes\_hud_util; -#include maps\mp\perks\_perkfunctions; - -init() -{ - level.perkFuncs = []; - - precacheShader( "combathigh_overlay" ); - precacheShader( "specialty_painkiller" ); - - precacheModel( "weapon_riot_shield_mp" ); - precacheModel( "viewmodel_riot_shield_mp" ); - precacheString( &"MPUI_CHANGING_KIT" ); - - //level.spawnGlowSplat = loadfx( "misc/flare_ambient_destroy" ); - - level.spawnGlowModel["enemy"] = "mil_emergency_flare_mp"; - level.spawnGlowModel["friendly"] = "mil_emergency_flare_mp"; - level.spawnGlow["enemy"] = loadfx( "misc/flare_ambient" ); - level.spawnGlow["friendly"] = loadfx( "misc/flare_ambient_green" ); - level.c4Death = loadfx( "explosions/oxygen_tank_explosion" ); - - level.spawnFire = loadfx( "props/barrelexp" ); - - precacheModel( level.spawnGlowModel["friendly"] ); - precacheModel( level.spawnGlowModel["enemy"] ); - - precacheString( &"MP_DESTROY_TI" ); - - precacheShaders(); - - level._effect["ricochet"] = loadfx( "impacts/large_metalhit_1" ); - - // perks that currently only exist in script: these will error if passed to "setPerk", etc... CASE SENSITIVE! must be lower - level.scriptPerks = []; - level.perkSetFuncs = []; - level.perkUnsetFuncs = []; - level.fauxPerks = []; - - level.scriptPerks["specialty_blastshield"] = true; - level.scriptPerks["_specialty_blastshield"] = true; - level.scriptPerks["specialty_akimbo"] = true; - level.scriptPerks["specialty_siege"] = true; - level.scriptPerks["specialty_falldamage"] = true; - level.scriptPerks["specialty_fmj"] = true; - level.scriptPerks["specialty_shield"] = true; - level.scriptPerks["specialty_feigndeath"] = true; - level.scriptPerks["specialty_shellshock"] = true; - level.scriptPerks["specialty_delaymine"] = true; - level.scriptPerks["specialty_localjammer"] = true; - level.scriptPerks["specialty_thermal"] = true; - level.scriptPerks["specialty_finalstand"] = true; - level.scriptPerks["specialty_blackbox"] = true; - level.scriptPerks["specialty_steelnerves"] = true; - level.scriptPerks["specialty_flashgrenade"] = true; - level.scriptPerks["specialty_smokegrenade"] = true; - level.scriptPerks["specialty_concussiongrenade"] = true; - level.scriptPerks["specialty_challenger"] = true; - level.scriptPerks["specialty_tacticalinsertion"] = true; - level.scriptPerks["specialty_saboteur"] = true; - level.scriptPerks["specialty_endgame"] = true; - level.scriptPerks["specialty_rearview"] = true; - level.scriptPerks["specialty_hardline"] = true; - level.scriptPerks["specialty_ac130"] = true; - level.scriptPerks["specialty_sentry_minigun"] = true; - level.scriptPerks["specialty_predator_missile"] = true; - level.scriptPerks["specialty_helicopter_minigun"] = true; - level.scriptPerks["specialty_tank"] = true; - level.scriptPerks["specialty_precision_airstrike"] = true; - level.scriptPerks["specialty_bling"] = true; - level.scriptPerks["specialty_carepackage"] = true; - level.scriptPerks["specialty_onemanarmy"] = true; - level.scriptPerks["specialty_littlebird_support"] = true; - level.scriptPerks["specialty_primarydeath"] = true; - level.scriptPerks["specialty_secondarybling"] = true; - level.scriptPerks["specialty_combathigh"] = true; - level.scriptPerks["specialty_c4death"] = true; - level.scriptPerks["specialty_explosivedamage"] = true; - level.scriptPerks["specialty_copycat"] = true; - level.scriptPerks["specialty_laststandoffhand"] = true; - level.scriptPerks["specialty_dangerclose"] = true; - - level.scriptPerks["specialty_extraspecialduration"] = true; - level.scriptPerks["specialty_rollover"] = true; - level.scriptPerks["specialty_armorpiercing"] = true; - level.scriptPerks["specialty_omaquickchange"] = true; - level.scriptPerks["specialty_fastmeleerecovery"] = true; - - level.scriptPerks["_specialty_rearview"] = true; - level.scriptPerks["_specialty_onemanarmy"] = true; - - level.fauxPerks["specialty_tacticalinsertion"] = true; - level.fauxPerks["specialty_shield"] = true; - - - /* - level.perkSetFuncs[""] = ::; - level.perkUnsetFuncs[""] = ::; - */ - - level.perkSetFuncs["specialty_blastshield"] = ::setBlastShield; - level.perkUnsetFuncs["specialty_blastshield"] = ::unsetBlastShield; - - level.perkSetFuncs["specialty_siege"] = ::setSiege; - level.perkUnsetFuncs["specialty_siege"] = ::unsetSiege; - - level.perkSetFuncs["specialty_falldamage"] = ::setFreefall; - level.perkUnsetFuncs["specialty_falldamage"] = ::unsetFreefall; - - level.perkSetFuncs["specialty_localjammer"] = ::setLocalJammer; - level.perkUnsetFuncs["specialty_localjammer"] = ::unsetLocalJammer; - - level.perkSetFuncs["specialty_thermal"] = ::setThermal; - level.perkUnsetFuncs["specialty_thermal"] = ::unsetThermal; - - level.perkSetFuncs["specialty_blackbox"] = ::setBlackBox; - level.perkUnsetFuncs["specialty_blackbox"] = ::unsetBlackBox; - - level.perkSetFuncs["specialty_lightweight"] = ::setLightWeight; - level.perkUnsetFuncs["specialty_lightweight"] = ::unsetLightWeight; - - level.perkSetFuncs["specialty_steelnerves"] = ::setSteelNerves; - level.perkUnsetFuncs["specialty_steelnerves"] = ::unsetSteelNerves; - - level.perkSetFuncs["specialty_delaymine"] = ::setDelayMine; - level.perkUnsetFuncs["specialty_delaymine"] = ::unsetDelayMine; - - level.perkSetFuncs["specialty_finalstand"] = ::setFinalStand; - level.perkUnsetFuncs["specialty_finalstand"] = ::unsetFinalStand; - - level.perkSetFuncs["specialty_combathigh"] = ::setCombatHigh; - level.perkUnsetFuncs["specialty_combathigh"] = ::unsetCombatHigh; - - level.perkSetFuncs["specialty_challenger"] = ::setChallenger; - level.perkUnsetFuncs["specialty_challenger"] = ::unsetChallenger; - - level.perkSetFuncs["specialty_saboteur"] = ::setSaboteur; - level.perkUnsetFuncs["specialty_saboteur"] = ::unsetSaboteur; - - level.perkSetFuncs["specialty_endgame"] = ::setEndGame; - level.perkUnsetFuncs["specialty_endgame"] = ::unsetEndGame; - - level.perkSetFuncs["specialty_rearview"] = ::setRearView; - level.perkUnsetFuncs["specialty_rearview"] = ::unsetRearView; - - level.perkSetFuncs["specialty_ac130"] = ::setAC130; - level.perkUnsetFuncs["specialty_ac130"] = ::unsetAC130; - - level.perkSetFuncs["specialty_sentry_minigun"] = ::setSentryMinigun; - level.perkUnsetFuncs["specialty_sentry_minigun"] = ::unsetSentryMinigun; - - level.perkSetFuncs["specialty_predator_missile"] = ::setPredatorMissile; - level.perkUnsetFuncs["specialty_predator_missile"] = ::unsetPredatorMissile; - - level.perkSetFuncs["specialty_tank"] = ::setTank; - level.perkUnsetFuncs["specialty_tank"] = ::unsetTank; - - level.perkSetFuncs["specialty_precision_airstrike"] = ::setPrecision_airstrike; - level.perkUnsetFuncs["specialty_precision_airstrike"] = ::unsetPrecision_airstrike; - - level.perkSetFuncs["specialty_helicopter_minigun"] = ::setHelicopterMinigun; - level.perkUnsetFuncs["specialty_helicopter_minigun"] = ::unsetHelicopterMinigun; - - level.perkSetFuncs["specialty_carepackage"] = ::setCarePackage; - level.perkUnsetFuncs["specialty_carepackage"] = ::unsetCarePackage; - - level.perkSetFuncs["specialty_onemanarmy"] = ::setOneManArmy; - level.perkUnsetFuncs["specialty_onemanarmy"] = ::unsetOneManArmy; - - level.perkSetFuncs["specialty_littlebird_support"] = ::setLittlebirdSupport; - level.perkUnsetFuncs["specialty_littlebird_support"] = ::unsetLittlebirdSupport; - - level.perkSetFuncs["specialty_c4death"] = ::setC4Death; - level.perkUnsetFuncs["specialty_c4death"] = ::unsetC4Death; - - level.perkSetFuncs["specialty_tacticalinsertion"] = ::setTacticalInsertion; - level.perkUnsetFuncs["specialty_tacticalinsertion"] = ::unsetTacticalInsertion; - - initPerkDvars(); - - level thread onPlayerConnect(); -} - - - -precacheShaders() -{ - precacheShader( "specialty_blastshield" ); -} - - -givePerk( perkName ) -{ - if ( IsSubStr( perkName, "_mp" ) ) - { - if ( perkName == "frag_grenade_mp" ) - self SetOffhandPrimaryClass( "frag" ); - if ( perkName == "throwingknife_mp" ) - self SetOffhandPrimaryClass( "throwingknife" ); - - self _giveWeapon( perkName, 0 ); - self giveStartAmmo( perkName ); - - self setPerk( perkName, false ); - return; - } - - if ( isSubStr( perkName, "specialty_null" ) || isSubStr( perkName, "specialty_weapon_" ) ) - { - self setPerk( perkName, false ); - return; - } - - self _setPerk( perkName ); - -} - - -validatePerk( perkIndex, perkName ) -{ - if ( getDvarInt ( "scr_game_perks" ) == 0 ) - { - if ( tableLookup( "mp/perkTable.csv", 1, perkName, 5 ) != "equipment" ) - return "specialty_null"; - } - - /* Validation disabled for now - if ( tableLookup( "mp/perkTable.csv", 1, perkName, 5 ) != ("perk"+perkIndex) ) - { - println( "^1Warning: (" + self.name + ") Perk " + perkName + " is not allowed for perk slot index " + perkIndex + "; replacing with no perk" ); - return "specialty_null"; - } - */ - - return perkName; -} - - -onPlayerConnect() -{ - for(;;) - { - level waittill( "connected", player ); - player thread onPlayerSpawned(); - } -} - - -onPlayerSpawned() -{ - self endon( "disconnect" ); - - self.perks = []; - self.weaponList = []; - self.omaClassChanged = false; - - for( ;; ) - { - self waittill( "spawned_player" ); - - self.omaClassChanged = false; - self thread gambitUseTracker(); - } -} - - -drawLine( start, end, timeSlice ) -{ - drawTime = int(timeSlice * 20); - for( time = 0; time < drawTime; time++ ) - { - line( start, end, (1,0,0),false, 1 ); - wait ( 0.05 ); - } -} - - -cac_modified_damage( victim, attacker, damage, meansofdeath, weapon, impactPoint, impactDir, hitLoc ) -{ - assert( isPlayer( victim ) ); - assert( isDefined( victim.team ) ); - - damageAdd = 0; - - if ( isPrimaryDamage( meansOfDeath ) ) - { - assert( isDefined( attacker ) ); - - if ( isPlayer( attacker ) && weaponInheritsPerks( weapon ) && attacker _hasPerk( "specialty_bulletdamage" ) && victim _hasPerk( "specialty_armorvest" ) ) - damageAdd += 0; - else if ( isPlayer( attacker ) && weaponInheritsPerks( weapon ) && attacker _hasPerk( "specialty_bulletdamage" ) ) - damageAdd += damage*level.bulletDamageMod; - else if ( victim _hasPerk( "specialty_armorvest" ) ) - damageAdd -= damage*(1-level.armorVestMod); - - if ( isPlayer( attacker ) && attacker _hasPerk( "specialty_fmj" ) && victim _hasPerk ( "specialty_armorvest" ) ) - damageAdd += damage*level.hollowPointDamageMod; - } - else if ( isExplosiveDamage( meansOfDeath ) ) - { - if ( isPlayer( attacker ) && weaponInheritsPerks( weapon ) && attacker _hasPerk( "specialty_explosivedamage" ) && victim _hasPerk( "_specialty_blastshield" ) ) - damageAdd += 0; - else if ( isPlayer( attacker ) && weaponInheritsPerks( weapon ) && attacker _hasPerk( "specialty_explosivedamage" ) ) - damageAdd += damage*level.explosiveDamageMod; - else if ( victim _hasPerk( "_specialty_blastshield" ) ) - damageAdd -= damage*(1-level.blastShieldMod); - - if ( isKillstreakWeapon( weapon ) && isPlayer( attacker ) && attacker _hasPerk("specialty_dangerclose") ) - damageAdd += damage*level.dangerCloseMod; - } - else if (meansOfDeath == "MOD_FALLING") - { - if ( victim _hasPerk( "specialty_falldamage" ) ) - { - //eventually set a msg to do a roll - damageAdd = 0; - damage = 0; - } - } - - if ( ( victim.xpScaler == 2 && isDefined( attacker ) ) && ( isPlayer( attacker ) || attacker.classname == "scrip_vehicle" ) ) - damageAdd += 200; - - if ( victim _hasperk( "specialty_combathigh" ) ) - { - if ( IsDefined( self.damageBlockedTotal ) && (!level.teamBased || (isDefined( attacker ) && isDefined( attacker.team ) && victim.team != attacker.team)) ) - { - damageTotal = damage + damageAdd; - damageBlocked = (damageTotal - ( damageTotal / 3 )); - self.damageBlockedTotal += damageBlocked; - - if ( self.damageBlockedTotal >= 101 ) - { - self notify( "combathigh_survived" ); - self.damageBlockedTotal = undefined; - } - } - - if ( weapon != "throwingknife_mp" ) - { - switch ( meansOfDeath ) - { - case "MOD_FALLING": - case "MOD_MELEE": - break; - default: - damage = damage/3; - damageAdd = damageAdd/3; - break; - } - } - } - - return int( damage + damageAdd ); -} - -initPerkDvars() -{ - level.bulletDamageMod = getIntProperty( "perk_bulletDamage", 40 )/100; // increased bullet damage by this % - level.hollowPointDamageMod = getIntProperty( "perk_hollowPointDamage", 65 )/100; // increased bullet damage by this % - level.armorVestMod = getIntProperty( "perk_armorVest", 75 )/100; // percentage of damage you take - level.explosiveDamageMod = getIntProperty( "perk_explosiveDamage", 40 )/100; // increased explosive damage by this % - level.blastShieldMod = getIntProperty( "perk_blastShield", 45 )/100; // percentage of damage you take - level.riotShieldMod = getIntProperty( "perk_riotShield", 100 )/100; - level.dangerCloseMod = getIntProperty( "perk_dangerClose", 100 )/100; - level.armorPiercingMod = getIntProperty( "perk_armorPiercingDamage", 40 )/100; // increased bullet damage by this % -} - -// CAC: Selector function, calls the individual cac features according to player's class settings -// Info: Called every time player spawns during loadout stage -cac_selector() -{ - perks = self.specialty; - - /* - self.detectExplosives = false; - - if ( self _hasPerk( "specialty_detectexplosive" ) ) - self.detectExplosives = true; - - maps\mp\gametypes\_weapons::setupBombSquad(); - */ -} - - -gambitUseTracker() -{ - self endon ( "death" ); - self endon ( "disconnect" ); - level endon ( "game_ended" ); - - if ( getDvarInt ( "scr_game_perks" ) != 1 ) - return; - - gameFlagWait( "prematch_done" ); - - self notifyOnPlayerCommand( "gambit_on", "+frag" ); -} \ No newline at end of file diff --git a/maps/mp/perks/_perksfunctions.gsc b/maps/mp/perks/_perksfunctions.gsc deleted file mode 100644 index e893c1e..0000000 --- a/maps/mp/perks/_perksfunctions.gsc +++ /dev/null @@ -1,1011 +0,0 @@ -/******************************************************************* -// _perkfunctions.gsc -// -// Holds all the perk set/unset and listening functions -// -// Jordan Hirsh Sept. 11th 2008 -********************************************************************/ - -#include common_scripts\utility; -#include maps\mp\_utility; -#include maps\mp\gametypes\_hud_util; -#include maps\mp\perks\_perks; - - -blastshieldUseTracker( perkName, useFunc ) -{ - self endon ( "death" ); - self endon ( "disconnect" ); - self endon ( "end_perkUseTracker" ); - level endon ( "game_ended" ); - - for ( ;; ) - { - self waittill ( "empty_offhand" ); - - if ( !isOffhandWeaponEnabled() ) - continue; - - self [[useFunc]]( self _hasPerk( "_specialty_blastshield" ) ); - } -} - -perkUseDeathTracker() -{ - self endon ( "disconnect" ); - - self waittill("death"); - self._usePerkEnabled = undefined; -} - -setRearView() -{ - //self thread perkUseTracker( "specialty_rearview", ::toggleRearView ); -} - -unsetRearView() -{ - self notify ( "end_perkUseTracker" ); -} - -toggleRearView( isEnabled ) -{ - if ( isEnabled ) - { - self _setPerk( "_specialty_rearview" ); - self SetRearViewRenderEnabled(true); - } - else - { - self _unsetPerk( "_specialty_rearview" ); - self SetRearViewRenderEnabled(false); - } -} - - -setEndGame() -{ - if ( isdefined( self.endGame ) ) - return; - - self.maxhealth = ( maps\mp\gametypes\_tweakables::getTweakableValue( "player", "maxhealth" ) * 4 ); - self.health = self.maxhealth; - self.endGame = true; - self.attackerTable[0] = ""; - self visionSetNakedForPlayer("end_game", 5 ); - self thread endGameDeath( 7 ); - self.hasDoneCombat = true; -} - - -unsetEndGame() -{ - self notify( "stopEndGame" ); - self.endGame = undefined; - revertVisionSet(); - - if (! isDefined( self.endGameTimer ) ) - return; - - self.endGameTimer destroyElem(); - self.endGameIcon destroyElem(); -} - - -revertVisionSet() -{ - self VisionSetNakedForPlayer( getDvar( "mapname" ), 1 ); -} - -endGameDeath( duration ) -{ - self endon( "death" ); - self endon( "disconnect" ); - self endon( "joined_team" ); - level endon( "game_ended" ); - self endon( "stopEndGame" ); - - wait( duration + 1 ); - //self visionSetNakedForPlayer("end_game2", 1 ); - //wait(1); - self _suicide(); -} - -setCombatHigh() -{ - self endon( "death" ); - self endon( "disconnect" ); - self endon( "unset_combathigh" ); - level endon( "end_game" ); - - self.damageBlockedTotal = 0; - //self visionSetNakedForPlayer( "end_game", 1 ); - - if ( level.splitscreen ) - { - yOffset = 56; - iconSize = 21; // 32/1.5 - } - else - { - yOffset = 112; - iconSize = 32; - } - - self.combatHighOverlay = newClientHudElem( self ); - self.combatHighOverlay.x = 0; - self.combatHighOverlay.y = 0; - self.combatHighOverlay.alignX = "left"; - self.combatHighOverlay.alignY = "top"; - self.combatHighOverlay.horzAlign = "fullscreen"; - self.combatHighOverlay.vertAlign = "fullscreen"; - self.combatHighOverlay setshader ( "combathigh_overlay", 640, 480 ); - self.combatHighOverlay.sort = -10; - self.combatHighOverlay.archived = true; - - self.combatHighTimer = createTimer( "hudsmall", 1.0 ); - self.combatHighTimer setPoint( "CENTER", "CENTER", 0, yOffset ); - self.combatHighTimer setTimer( 10.0 ); - self.combatHighTimer.color = (.8,.8,0); - self.combatHighTimer.archived = false; - self.combatHighTimer.foreground = true; - - self.combatHighIcon = self createIcon( "specialty_painkiller", iconSize, iconSize ); - self.combatHighIcon.alpha = 0; - self.combatHighIcon setParent( self.combatHighTimer ); - self.combatHighIcon setPoint( "BOTTOM", "TOP" ); - self.combatHighIcon.archived = true; - self.combatHighIcon.sort = 1; - self.combatHighIcon.foreground = true; - - self.combatHighOverlay.alpha = 0.0; - self.combatHighOverlay fadeOverTime( 1.0 ); - self.combatHighIcon fadeOverTime( 1.0 ); - self.combatHighOverlay.alpha = 1.0; - self.combatHighIcon.alpha = 0.85; - - self thread unsetCombatHighOnDeath(); - - wait( 8 ); - - self.combatHighIcon fadeOverTime( 2.0 ); - self.combatHighIcon.alpha = 0.0; - - self.combatHighOverlay fadeOverTime( 2.0 ); - self.combatHighOverlay.alpha = 0.0; - - self.combatHighTimer fadeOverTime( 2.0 ); - self.combatHighTimer.alpha = 0.0; - - wait( 2 ); - self.damageBlockedTotal = undefined; - - self _unsetPerk( "specialty_combathigh" ); -} - -unsetCombatHighOnDeath() -{ - self endon ( "disconnect" ); - self endon ( "unset_combathigh" ); - - self waittill ( "death" ); - - self thread _unsetPerk( "specialty_combathigh" ); -} - -unsetCombatHigh() -{ - self notify ( "unset_combathigh" ); - self.combatHighOverlay destroy(); - self.combatHighIcon destroy(); - self.combatHighTimer destroy(); -} - -setSiege() -{ - self thread trackSiegeEnable(); - self thread trackSiegeDissable(); -} - -trackSiegeEnable() -{ - self endon ( "death" ); - self endon ( "disconnect" ); - self endon ( "stop_trackSiege" ); - - for ( ;; ) - { - self waittill ( "gambit_on" ); - - //self setStance( "crouch" ); - //self thread stanceStateListener(); - //self thread jumpStateListener(); - self.moveSpeedScaler = 0; - self maps\mp\gametypes\_weapons::updateMoveSpeedScale( "primary" ); - class = weaponClass( self getCurrentWeapon() ); - - if ( class == "pistol" || class == "smg" ) - self setSpreadOverride( 1 ); - else - self setSpreadOverride( 2 ); - - self player_recoilScaleOn( 0 ); - self allowJump(false); - } -} - -trackSiegeDissable() -{ - self endon ( "death" ); - self endon ( "disconnect" ); - self endon ( "stop_trackSiege" ); - - for ( ;; ) - { - self waittill ( "gambit_off" ); - - unsetSiege(); - } -} - -stanceStateListener() -{ - self endon ( "death" ); - self endon ( "disconnect" ); - - self notifyOnPlayerCommand( "adjustedStance", "+stance" ); - - for ( ;; ) - { - self waittill( "adjustedStance" ); - if ( self.moveSPeedScaler != 0 ) - continue; - - unsetSiege(); - } -} - -jumpStateListener() -{ - self endon ( "death" ); - self endon ( "disconnect" ); - - self notifyOnPlayerCommand( "jumped", "+goStand" ); - - for ( ;; ) - { - self waittill( "jumped" ); - if ( self.moveSPeedScaler != 0 ) - continue; - - unsetSiege(); - } -} - -unsetSiege() -{ - self.moveSpeedScaler = 1; - //if siege is not cut add check to see if - //using lightweight and siege for movespeed scaler - self resetSpreadOverride(); - self maps\mp\gametypes\_weapons::updateMoveSpeedScale( "primary" ); - self player_recoilScaleOff(); - self allowJump(true); -} - - -setFinalStand() -{ - self _setperk( "specialty_pistoldeath"); -} - -unsetFinalStand() -{ - self _unsetperk( "specialty_pistoldeath" ); -} - - -setChallenger() -{ - if ( !level.hardcoreMode ) - { - self.maxhealth = maps\mp\gametypes\_tweakables::getTweakableValue( "player", "maxhealth" ); - - if ( isDefined( self.xpScaler ) && self.xpScaler == 1 && self.maxhealth > 30 ) - { - self.xpScaler = 2; - } - } -} - -unsetChallenger() -{ - self.xpScaler = 1; -} - - -setSaboteur() -{ - self.objectiveScaler = 1.2; -} - -unsetSaboteur() -{ - self.objectiveScaler = 1; -} - - -setLightWeight() -{ - self.moveSpeedScaler = 1.07; - self maps\mp\gametypes\_weapons::updateMoveSpeedScale( "primary" ); -} - -unsetLightWeight() -{ - self.moveSpeedScaler = 1; - self maps\mp\gametypes\_weapons::updateMoveSpeedScale( "primary" ); -} - - -setBlackBox() -{ - self.killStreakScaler = 1.5; -} - -unsetBlackBox() -{ - self.killStreakScaler = 1; -} - -setSteelNerves() -{ - self _setperk( "specialty_bulletaccuracy" ); - self _setperk( "specialty_holdbreath" ); -} - -unsetSteelNerves() -{ - self _unsetperk( "specialty_bulletaccuracy" ); - self _unsetperk( "specialty_holdbreath" ); -} - -setDelayMine() -{ -} - -unsetDelayMine() -{ -} - - -setBackShield() -{ - self AttachShieldModel( "weapon_riot_shield_mp", "tag_shield_back" ); -} - - -unsetBackShield() -{ - self DetachShieldModel( "weapon_riot_shield_mp", "tag_shield_back" ); -} - - -setLocalJammer() -{ - if ( !self isEMPed() ) - self RadarJamOn(); -} - - -unsetLocalJammer() -{ - self RadarJamOff(); -} - - -setAC130() -{ - self thread killstreakThink( "ac130", 7, "end_ac130Think" ); -} - -unsetAC130() -{ - self notify ( "end_ac130Think" ); -} - - -setSentryMinigun() -{ - self thread killstreakThink( "airdrop_sentry_minigun", 2, "end_sentry_minigunThink" ); -} - -unsetSentryMinigun() -{ - self notify ( "end_sentry_minigunThink" ); -} - -setCarePackage() -{ - self thread killstreakThink( "airdrop", 2, "endCarePackageThink" ); -} - -unsetCarePackage() -{ - self notify ( "endCarePackageThink" ); -} - -setTank() -{ - self thread killstreakThink( "tank", 6, "end_tankThink" ); -} - -unsetTank() -{ - self notify ( "end_tankThink" ); -} - -setPrecision_airstrike() -{ - println( "!precision airstrike!" ); - self thread killstreakThink( "precision_airstrike", 6, "end_precision_airstrike" ); -} - -unsetPrecision_airstrike() -{ - self notify ( "end_precision_airstrike" ); -} - -setPredatorMissile() -{ - self thread killstreakThink( "predator_missile", 4, "end_predator_missileThink" ); -} - -unsetPredatorMissile() -{ - self notify ( "end_predator_missileThink" ); -} - - -setHelicopterMinigun() -{ - self thread killstreakThink( "helicopter_minigun", 5, "end_helicopter_minigunThink" ); -} - -unsetHelicopterMinigun() -{ - self notify ( "end_helicopter_minigunThink" ); -} - - - -killstreakThink( streakName, streakVal, endonString ) -{ - self endon ( "death" ); - self endon ( "disconnect" ); - self endon ( endonString ); - - for ( ;; ) - { - self waittill ( "killed_enemy" ); - - if ( self.pers["cur_kill_streak"] != streakVal ) - continue; - - self thread maps\mp\killstreaks\_killstreaks::giveKillstreak( streakName ); - self thread maps\mp\gametypes\_hud_message::killstreakSplashNotify( streakName, streakVal ); - return; - } -} - - -setThermal() -{ - self ThermalVisionOn(); -} - - -unsetThermal() -{ - self ThermalVisionOff(); -} - - -setOneManArmy() -{ - self thread oneManArmyWeaponChangeTracker(); -} - - -unsetOneManArmy() -{ - self notify ( "stop_oneManArmyTracker" ); -} - - -oneManArmyWeaponChangeTracker() -{ - self endon ( "death" ); - self endon ( "disconnect" ); - level endon ( "game_ended" ); - self endon ( "stop_oneManArmyTracker" ); - - for ( ;; ) - { - self waittill( "weapon_change", newWeapon ); - - if ( newWeapon != "onemanarmy_mp" ) - continue; - - //if ( self isUsingRemote() ) - // continue; - - self thread selectOneManArmyClass(); - } -} - - -isOneManArmyMenu( menu ) -{ - if ( menu == game["menu_onemanarmy"] ) - return true; - - if ( isDefined( game["menu_onemanarmy_defaults_splitscreen"] ) && menu == game["menu_onemanarmy_defaults_splitscreen"] ) - return true; - - if ( isDefined( game["menu_onemanarmy_custom_splitscreen"] ) && menu == game["menu_onemanarmy_custom_splitscreen"] ) - return true; - - return false; -} - - -selectOneManArmyClass() -{ - self endon ( "death" ); - self endon ( "disconnect" ); - level endon ( "game_ended" ); - - self _disableWeaponSwitch(); - - self openPopupMenu( game["menu_onemanarmy"] ); - - self thread closeOMAMenuOnDeath(); - - self waittill ( "menuresponse", menu, className ); - - self _enableWeaponSwitch(); - - if ( className == "back" || !isOneManArmyMenu( menu ) || self isUsingRemote() ) - { - if ( self getCurrentWeapon() == "onemanarmy_mp" ) - { - self _disableWeaponSwitch(); - self switchToWeapon( self getLastWeapon() ); - self waittill ( "weapon_change" ); - self _enableWeaponSwitch(); - } - return; - } - - self thread giveOneManArmyClass( className ); -} - -closeOMAMenuOnDeath() -{ - self endon ( "menuresponse" ); - self endon ( "disconnect" ); - level endon ( "game_ended" ); - - self waittill ( "death" ); - - self _enableWeaponSwitch(); - - self closePopupMenu(); -} - -giveOneManArmyClass( className ) -{ - self endon ( "death" ); - self endon ( "disconnect" ); - level endon ( "game_ended" ); - - if ( self _hasPerk( "specialty_omaquickchange" ) ) - { - changeDuration = 3.0; - self playLocalSound( "foly_onemanarmy_bag3_plr" ); - self playSoundToTeam( "foly_onemanarmy_bag3_npc", "allies", self ); - self playSoundToTeam( "foly_onemanarmy_bag3_npc", "axis", self ); - } - else - { - changeDuration = 6.0; - self playLocalSound( "foly_onemanarmy_bag6_plr" ); - self playSoundToTeam( "foly_onemanarmy_bag6_npc", "allies", self ); - self playSoundToTeam( "foly_onemanarmy_bag6_npc", "axis", self ); - } - - self thread omaUseBar( changeDuration ); - - self _disableWeapon(); - self _disableOffhandWeapons(); - - wait ( changeDuration ); - - self _enableWeapon(); - self _enableOffhandWeapons(); - self.OMAClassChanged = true; - - self maps\mp\gametypes\_class::giveLoadout( self.pers["team"], className, false ); - - // handle the fact that detachAll in giveLoadout removed the CTF flag from our back - // it would probably be better to handle this in _detachAll itself, but this is a safety fix - if ( isDefined( self.carryFlag ) ) - self attach( self.carryFlag, "J_spine4", true ); - - self notify ( "changed_kit" ); - level notify ( "changed_kit" ); -} - - -omaUseBar( duration ) -{ - self endon( "disconnect" ); - - useBar = createPrimaryProgressBar( 25 ); - useBarText = createPrimaryProgressBarText( 25 ); - useBarText setText( &"MPUI_CHANGING_KIT" ); - - useBar updateBar( 0, 1 / duration ); - for ( waitedTime = 0; waitedTime < duration && isAlive( self ) && !level.gameEnded; waitedTime += 0.05 ) - wait ( 0.05 ); - - useBar destroyElem(); - useBarText destroyElem(); -} - - -setBlastShield() -{ - self thread blastshieldUseTracker( "specialty_blastshield", ::toggleBlastShield ); - self SetWeaponHudIconOverride( "primaryoffhand", "specialty_blastshield" ); -} - - -unsetBlastShield() -{ - self notify ( "end_perkUseTracker" ); - self SetWeaponHudIconOverride( "primaryoffhand", "none" ); -} - -toggleBlastShield( isEnabled ) -{ - if ( !isEnabled ) - { - self VisionSetNakedForPlayer( "black_bw", 0.15 ); - wait ( 0.15 ); - self _setPerk( "_specialty_blastshield" ); - self VisionSetNakedForPlayer( getDvar( "mapname" ), 0 ); - self playSoundToPlayer( "item_blast_shield_on", self ); - } - else - { - self VisionSetNakedForPlayer( "black_bw", 0.15 ); - wait ( 0.15 ); - self _unsetPerk( "_specialty_blastshield" ); - self VisionSetNakedForPlayer( getDvar( "mapname" ), 0 ); - self playSoundToPlayer( "item_blast_shield_off", self ); - } -} - - -setFreefall() -{ - //eventually set a listener to do a roll when falling damage is taken -} - -unsetFreefall() -{ -} - - -setTacticalInsertion() -{ - self _giveWeapon( "flare_mp", 0 ); - self giveStartAmmo( "flare_mp" ); - - self thread monitorTIUse(); -} - -unsetTacticalInsertion() -{ - self notify( "end_monitorTIUse" ); -} - -clearPreviousTISpawnpoint() -{ - self waittill_any ( "disconnect", "joined_team", "joined_spectators" ); - - if ( isDefined ( self.setSpawnpoint ) ) - self deleteTI( self.setSpawnpoint ); -} - -updateTISpawnPosition() -{ - self endon ( "death" ); - self endon ( "disconnect" ); - level endon ( "game_ended" ); - self endon ( "end_monitorTIUse" ); - - while ( isReallyAlive( self ) ) - { - if ( self isValidTISpawnPosition() ) - self.TISpawnPosition = self.origin; - - wait ( 0.05 ); - } -} - -isValidTISpawnPosition() -{ - if ( CanSpawn( self.origin ) && self IsOnGround() ) - return true; - else - return false; -} - -monitorTIUse() -{ - self endon ( "death" ); - self endon ( "disconnect" ); - level endon ( "game_ended" ); - self endon ( "end_monitorTIUse" ); - - self thread updateTISpawnPosition(); - self thread clearPreviousTISpawnpoint(); - - for ( ;; ) - { - self waittill( "grenade_fire", lightstick, weapName ); - - if ( weapName != "flare_mp" ) - continue; - - //lightstick delete(); - - if ( isDefined( self.setSpawnPoint ) ) - self deleteTI( self.setSpawnPoint ); - - if ( !isDefined( self.TISpawnPosition ) ) - continue; - - if ( self touchingBadTrigger() ) - continue; - - TIGroundPosition = playerPhysicsTrace( self.TISpawnPosition + (0,0,16), self.TISpawnPosition - (0,0,2048) ) + (0,0,1); - - glowStick = spawn( "script_model", TIGroundPosition ); - glowStick.angles = self.angles; - glowStick.team = self.team; - glowStick.enemyTrigger = spawn( "script_origin", TIGroundPosition ); - glowStick thread GlowStickSetupAndWaitForDeath( self ); - glowStick.playerSpawnPos = self.TISpawnPosition; - - glowStick thread maps\mp\gametypes\_weapons::createBombSquadModel( "weapon_light_stick_tactical_bombsquad", "tag_fire_fx", level.otherTeam[self.team], self ); - - self.setSpawnPoint = glowStick; - return; - } -} - - -GlowStickSetupAndWaitForDeath( owner ) -{ - self setModel( level.spawnGlowModel["enemy"] ); - if ( level.teamBased ) - self maps\mp\_entityheadIcons::setTeamHeadIcon( self.team , (0,0,20) ); - else - self maps\mp\_entityheadicons::setPlayerHeadIcon( owner, (0,0,20) ); - - self thread GlowStickDamageListener( owner ); - self thread GlowStickEnemyUseListener( owner ); - self thread GlowStickUseListener( owner ); - self thread GlowStickTeamUpdater( level.otherTeam[self.team], level.spawnGlow["enemy"], owner ); - - dummyGlowStick = spawn( "script_model", self.origin+ (0,0,0) ); - dummyGlowStick.angles = self.angles; - dummyGlowStick setModel( level.spawnGlowModel["friendly"] ); - dummyGlowStick setContents( 0 ); - dummyGlowStick thread GlowStickTeamUpdater( self.team, level.spawnGlow["friendly"], owner ); - - dummyGlowStick playLoopSound( "emt_road_flare_burn" ); - - self waittill ( "death" ); - - dummyGlowStick stopLoopSound(); - dummyGlowStick delete(); -} - - -GlowStickTeamUpdater( showForTeam, showEffect, owner ) -{ - self endon ( "death" ); - - // PlayFXOnTag fails if run on the same frame the parent entity was created - wait ( 0.05 ); - - //PlayFXOnTag( showEffect, self, "TAG_FX" ); - angles = self getTagAngles( "tag_fire_fx" ); - fxEnt = SpawnFx( showEffect, self getTagOrigin( "tag_fire_fx" ), anglesToForward( angles ), anglesToUp( angles ) ); - TriggerFx( fxEnt ); - - self thread deleteOnDeath( fxEnt ); - - for ( ;; ) - { - self hide(); - fxEnt hide(); - foreach ( player in level.players ) - { - if ( player.team == showForTeam && level.teamBased ) - { - self showToPlayer( player ); - fxEnt showToPlayer( player ); - } - else if ( !level.teamBased && player == owner && showEffect == level.spawnGlow["friendly"] ) - { - self showToPlayer( player ); - fxEnt showToPlayer( player ); - } - else if ( !level.teamBased && player != owner && showEffect == level.spawnGlow["enemy"] ) - { - self showToPlayer( player ); - fxEnt showToPlayer( player ); - } - } - - level waittill_either ( "joined_team", "player_spawned" ); - } -} - -deleteOnDeath( ent ) -{ - self waittill( "death" ); - if ( isdefined( ent ) ) - ent delete(); -} - -GlowStickDamageListener( owner ) -{ - self endon ( "death" ); - - self setCanDamage( true ); - // use large health to work around teamkilling issue - self.health = 5000; - - for ( ;; ) - { - self waittill ( "damage", amount, attacker ); - - if ( level.teambased && isDefined( owner ) && attacker != owner && ( isDefined( attacker.team ) && attacker.team == self.team ) ) - { - self.health += amount; - continue; - } - - if ( self.health < (5000-20) ) - { - if ( isDefined( owner ) && attacker != owner ) - { - attacker notify ( "destroyed_insertion", owner ); - attacker notify( "destroyed_explosive" ); // count towards SitRep Pro challenge - owner thread leaderDialogOnPlayer( "ti_destroyed" ); - } - - attacker thread deleteTI( self ); - } - } -} - -GlowStickUseListener( owner ) -{ - self endon ( "death" ); - level endon ( "game_ended" ); - owner endon ( "disconnect" ); - - self setCursorHint( "HINT_NOICON" ); - self setHintString( &"MP_PICKUP_TI" ); - - self thread updateEnemyUse( owner ); - - for ( ;; ) - { - self waittill ( "trigger", player ); - - player playSound( "chemlight_pu" ); - player thread setTacticalInsertion(); - player thread deleteTI( self ); - } -} - -updateEnemyUse( owner ) -{ - self endon ( "death" ); - - for ( ;; ) - { - self setSelfUsable( owner ); - level waittill_either ( "joined_team", "player_spawned" ); - } -} - -deleteTI( TI ) -{ - if (isDefined( TI.enemyTrigger ) ) - TI.enemyTrigger Delete(); - - spot = TI.origin; - spotAngles = TI.angles; - - TI Delete(); - - dummyGlowStick = spawn( "script_model", spot ); - dummyGlowStick.angles = spotAngles; - dummyGlowStick setModel( level.spawnGlowModel["friendly"] ); - - dummyGlowStick setContents( 0 ); - thread dummyGlowStickDelete( dummyGlowStick ); -} - -dummyGlowStickDelete( stick ) -{ - wait(2.5); - stick Delete(); -} - -GlowStickEnemyUseListener( owner ) -{ - self endon ( "death" ); - level endon ( "game_ended" ); - owner endon ( "disconnect" ); - - self.enemyTrigger setCursorHint( "HINT_NOICON" ); - self.enemyTrigger setHintString( &"MP_DESTROY_TI" ); - self.enemyTrigger makeEnemyUsable( owner ); - - for ( ;; ) - { - self.enemyTrigger waittill ( "trigger", player ); - - player notify ( "destroyed_insertion", owner ); - player notify( "destroyed_explosive" ); // count towards SitRep Pro challenge - - //playFX( level.spawnGlowSplat, self.origin); - - if ( isDefined( owner ) && player != owner ) - owner thread leaderDialogOnPlayer( "ti_destroyed" ); - - player thread deleteTI( self ); - } -} - -setLittlebirdSupport() -{ - self thread killstreakThink( "littlebird_support", 2, "end_littlebird_support_think" ); -} - -unsetLittlebirdSupport() -{ - self notify ( "end_littlebird_support_think" ); -} - -setC4Death() -{ - if ( ! self _hasperk( "specialty_pistoldeath" ) ) - self _setperk( "specialty_pistoldeath"); -} - -unsetC4Death() -{ - -} \ No newline at end of file