diff --git a/maps/mp/bots/_bot.gsc b/maps/mp/bots/_bot.gsc index 3a7d7c7..5eae1a0 100644 --- a/maps/mp/bots/_bot.gsc +++ b/maps/mp/bots/_bot.gsc @@ -9,109 +9,177 @@ init() level.bw_version = "2.1.0"; if ( getcvar( "bots_main" ) == "" ) + { setcvar( "bots_main", true ); + } if ( !getcvarint( "bots_main" ) ) + { return; + } if ( !wait_for_builtins() ) + { println( "FATAL: NO BUILT-INS FOR BOTS" ); + } thread load_waypoints(); thread hook_callbacks(); if ( getcvar( "bots_main_GUIDs" ) == "" ) - setcvar( "bots_main_GUIDs", "" ); //guids of players who will be given host powers, comma seperated + { + setcvar( "bots_main_GUIDs", "" ); //guids of players who will be given host powers, comma seperated + } if ( getcvar( "bots_main_firstIsHost" ) == "" ) - setcvar( "bots_main_firstIsHost", true ); //first player to connect is a host + { + setcvar( "bots_main_firstIsHost", true ); //first player to connect is a host + } if ( getcvar( "bots_main_waitForHostTime" ) == "" ) - setcvar( "bots_main_waitForHostTime", 10.0 ); //how long to wait to wait for the host player + { + setcvar( "bots_main_waitForHostTime", 10.0 ); //how long to wait to wait for the host player + } if ( getcvar( "bots_main_kickBotsAtEnd" ) == "" ) - setcvar( "bots_main_kickBotsAtEnd", false ); //kicks the bots at game end + { + setcvar( "bots_main_kickBotsAtEnd", false ); //kicks the bots at game end + } if ( getcvar( "bots_manage_add" ) == "" ) - setcvar( "bots_manage_add", 0 ); //amount of bots to add to the game + { + setcvar( "bots_manage_add", 0 ); //amount of bots to add to the game + } if ( getcvar( "bots_manage_fill" ) == "" ) - setcvar( "bots_manage_fill", 0 ); //amount of bots to maintain + { + setcvar( "bots_manage_fill", 0 ); //amount of bots to maintain + } if ( getcvar( "bots_manage_fill_spec" ) == "" ) - setcvar( "bots_manage_fill_spec", true ); //to count for fill if player is on spec team + { + setcvar( "bots_manage_fill_spec", true ); //to count for fill if player is on spec team + } if ( getcvar( "bots_manage_fill_mode" ) == "" ) - setcvar( "bots_manage_fill_mode", 0 ); //fill mode, 0 adds everyone, 1 just bots, 2 maintains at maps, 3 is 2 with 1 + { + setcvar( "bots_manage_fill_mode", 0 ); //fill mode, 0 adds everyone, 1 just bots, 2 maintains at maps, 3 is 2 with 1 + } if ( getcvar( "bots_manage_fill_kick" ) == "" ) - setcvar( "bots_manage_fill_kick", false ); //kick bots if too many + { + setcvar( "bots_manage_fill_kick", false ); //kick bots if too many + } if ( getcvar( "bots_team" ) == "" ) - setcvar( "bots_team", "autoassign" ); //which team for bots to join + { + setcvar( "bots_team", "autoassign" ); //which team for bots to join + } if ( getcvar( "bots_team_amount" ) == "" ) - setcvar( "bots_team_amount", 0 ); //amount of bots on axis team + { + setcvar( "bots_team_amount", 0 ); //amount of bots on axis team + } if ( getcvar( "bots_team_force" ) == "" ) - setcvar( "bots_team_force", false ); //force bots on team + { + setcvar( "bots_team_force", false ); //force bots on team + } if ( getcvar( "bots_team_mode" ) == "" ) - setcvar( "bots_team_mode", 0 ); //counts just bots when 1 + { + setcvar( "bots_team_mode", 0 ); //counts just bots when 1 + } if ( getcvar( "bots_skill" ) == "" ) - setcvar( "bots_skill", 0 ); //0 is random, 1 is easy 7 is hard, 8 is custom, 9 is completely random + { + setcvar( "bots_skill", 0 ); //0 is random, 1 is easy 7 is hard, 8 is custom, 9 is completely random + } if ( getcvar( "bots_skill_axis_hard" ) == "" ) - setcvar( "bots_skill_axis_hard", 0 ); //amount of hard bots on axis team + { + setcvar( "bots_skill_axis_hard", 0 ); //amount of hard bots on axis team + } if ( getcvar( "bots_skill_axis_med" ) == "" ) + { setcvar( "bots_skill_axis_med", 0 ); + } if ( getcvar( "bots_skill_allies_hard" ) == "" ) + { setcvar( "bots_skill_allies_hard", 0 ); + } if ( getcvar( "bots_skill_allies_med" ) == "" ) + { setcvar( "bots_skill_allies_med", 0 ); + } if ( getcvar( "bots_skill_min" ) == "" ) + { setcvar( "bots_skill_min", 1 ); + } if ( getcvar( "bots_skill_max" ) == "" ) + { setcvar( "bots_skill_max", 7 ); + } if ( getcvar( "bots_loadout_rank" ) == "" ) // what rank the bots should be around, -1 is around the players, 0 is all random + { setcvar( "bots_loadout_rank", -1 ); + } if ( getcvar( "bots_play_move" ) == "" ) //bots move + { setcvar( "bots_play_move", true ); + } if ( getcvar( "bots_play_knife" ) == "" ) //bots knife + { setcvar( "bots_play_knife", true ); + } if ( getcvar( "bots_play_fire" ) == "" ) //bots fire + { setcvar( "bots_play_fire", true ); + } if ( getcvar( "bots_play_nade" ) == "" ) //bots grenade + { setcvar( "bots_play_nade", true ); + } if ( getcvar( "bots_play_obj" ) == "" ) //bots play the obj + { setcvar( "bots_play_obj", true ); + } if ( getcvar( "bots_play_camp" ) == "" ) //bots camp and follow + { setcvar( "bots_play_camp", true ); + } if ( getcvar( "bots_play_jumpdrop" ) == "" ) //bots jump and dropshot + { setcvar( "bots_play_jumpdrop", true ); + } if ( getcvar( "bots_play_ads" ) == "" ) //bot ads + { setcvar( "bots_play_ads", true ); + } if ( getcvar( "bots_play_aim" ) == "" ) + { setcvar( "bots_play_aim", true ); + } if ( !isdefined( game[ "botWarfare" ] ) ) + { game[ "botWarfare" ] = true; + } level.defuseobject = undefined; level.bots_smokelist = List(); @@ -210,7 +278,9 @@ init() level.teambased = true; if ( getcvar( "g_gametype" ) == "dm" ) + { level.teambased = false; + } } /* @@ -223,12 +293,16 @@ handleBots() level addBots(); while ( !level.mapended ) + { wait 0.05; + } setcvar( "bots_manage_add", getBotArray().size ); if ( !getcvarint( "bots_main_kickBotsAtEnd" ) ) + { return; + } bots = getBotArray(); @@ -333,7 +407,9 @@ watchWeapons() self thread watchAmmoUsage( weap ); while ( weap == self getcurrentweapon() ) + { wait 0.05; + } self notify( "weapon_change", self getcurrentweapon() ); } @@ -354,12 +430,18 @@ watchAmmoUsage( weap ) aCount = self getweaponslotclipammo( slot ); while ( aCount == self getweaponslotclipammo( slot ) ) + { wait 0.05; + } if ( self getweaponslotclipammo( slot ) < aCount ) + { self notify( "weapon_fired" ); + } else + { self notify( "reload" ); + } } } @@ -403,7 +485,9 @@ killTags() if ( isdefined( self.tags ) ) { for ( i = 0; i < self.tags.size; i++ ) + { self.tags[ i ] delete(); + } self.tags = undefined; self.tagmap = undefined; @@ -457,10 +541,14 @@ connected() self thread onDisconnectPlayer(); if ( !isdefined( self.pers[ "bot_host" ] ) ) + { self thread doHostCheck(); + } if ( !self is_bot() ) + { return; + } if ( !isdefined( self.pers[ "isBot" ] ) ) { @@ -501,25 +589,39 @@ watchBotDebugEvent() 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 ); } @@ -581,10 +683,14 @@ diffBots_loop() player = level.players[ i ]; if ( !isdefined( player.pers[ "team" ] ) ) + { continue; + } if ( !player is_bot() ) + { continue; + } if ( player.pers[ "team" ] == "axis" ) { @@ -599,7 +705,9 @@ diffBots_loop() player.pers[ "bots" ][ "skill" ][ "base" ] = 4; } else + { player.pers[ "bots" ][ "skill" ][ "base" ] = 1; + } } else if ( player.pers[ "team" ] == "allies" ) { @@ -614,7 +722,9 @@ diffBots_loop() player.pers[ "bots" ][ "skill" ][ "base" ] = 4; } else + { player.pers[ "bots" ][ "skill" ][ "base" ] = 1; + } } } } @@ -627,7 +737,9 @@ diffBots_loop() player = level.players[ i ]; if ( !player is_bot() ) + { continue; + } player.pers[ "bots" ][ "skill" ][ "base" ] = var_skill; } @@ -642,7 +754,9 @@ diffBots_loop() 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 ) ); } @@ -681,21 +795,31 @@ teamBots_loop() 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++; + } } } @@ -719,7 +843,9 @@ teamBots_loop() toTeam = "axis"; if ( axis > allies ) + { toTeam = "allies"; + } } } @@ -732,20 +858,32 @@ teamBots_loop() 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; } @@ -761,10 +899,14 @@ teamBots_loop() player = level.players[ i ]; if ( !isdefined( player.pers[ "team" ] ) ) + { continue; + } if ( !player is_bot() ) + { continue; + } if ( player.pers[ "team" ] == "axis" ) { @@ -816,7 +958,9 @@ addBots_loop() setcvar( "bots_manage_add", 0 ); if ( botsToAdd > 64 ) + { botsToAdd = 64; + } for ( ; botsToAdd > 0; botsToAdd-- ) { @@ -828,7 +972,9 @@ addBots_loop() fillMode = getcvarint( "bots_manage_fill_mode" ); if ( fillMode == 2 || fillMode == 3 ) + { setcvar( "bots_manage_fill", getGoodMapAmount() ); + } fillAmount = getcvarint( "bots_manage_fill" ); @@ -843,11 +989,17 @@ addBots_loop() 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 ( !randomint( 999 ) ) @@ -870,15 +1022,23 @@ addBots_loop() player = level.players[ i ]; if ( player is_bot() ) + { continue; + } if ( !isdefined( player.pers[ "team" ] ) ) + { continue; + } if ( player.pers[ "team" ] == "axis" ) + { axisplayers++; + } else if ( player.pers[ "team" ] == "allies" ) + { alliesplayers++; + } } result = fillAmount - abs( axisplayers - alliesplayers ) + bots; @@ -886,11 +1046,17 @@ addBots_loop() if ( players == 0 ) { if ( bots < fillAmount ) + { result = fillAmount - 1; + } else if ( bots > fillAmount ) + { result = fillAmount + 1; + } else + { result = fillAmount; + } } bots = result; @@ -899,19 +1065,27 @@ addBots_loop() amount = bots; if ( fillMode == 0 || fillMode == 2 ) + { amount += players; + } if ( getcvarint( "bots_manage_fill_spec" ) ) + { amount += spec; + } if ( amount < fillAmount ) + { setcvar( "bots_manage_add", 1 ); + } else if ( amount > fillAmount && getcvarint( "bots_manage_fill_kick" ) ) { tempBot = getBotToKick(); if ( isdefined( tempBot ) ) + { kick( tempBot getentitynumber() ); + } } } @@ -995,9 +1169,13 @@ watchNade() if ( gettime() - creationTime > 4000 ) { if ( lengthsquared( velocity ) <= 0.05 ) + { timeSlow += 0.05; + } else + { timeSlow = 0; + } } if ( timeSlow > 1 ) @@ -1022,10 +1200,14 @@ watchNades_loop() nade = nades[ i ]; if ( !isdefined( nade ) ) + { continue; + } if ( isdefined( nade.bot_audit ) ) + { continue; + } nade.bot_audit = true; @@ -1060,12 +1242,16 @@ watchGameEnded() if ( isdefined( level.roundended ) ) { if ( level.roundended ) + { break; + } } else if ( isdefined( level.mapended ) ) { if ( level.mapended ) + { break; + } } } diff --git a/maps/mp/bots/_bot_internal.gsc b/maps/mp/bots/_bot_internal.gsc index 681b86c..ac1ed7a 100644 --- a/maps/mp/bots/_bot_internal.gsc +++ b/maps/mp/bots/_bot_internal.gsc @@ -75,7 +75,9 @@ forceRespawn() wait 0.5; if ( !isdefined( self.respawntext ) ) + { continue; + } self thread use( 0.1 ); } @@ -256,7 +258,9 @@ doBotMovement_loop( data ) { // check if need to crouch if ( bullettracepassed( startPos - ( 0, 0, 25 ), startPosForward - ( 0, 0, 25 ), false, self ) && !self.bot.climbing ) + { self crouch(); + } } // move! @@ -320,12 +324,16 @@ watchPickupGun() wait 1; if ( self usebuttonpressed() ) + { continue; + } weap = self getcurrentweapon(); if ( weap != "none" && self getAmmoCount( weap ) ) + { continue; + } self thread use( 0.5 ); } @@ -337,7 +345,9 @@ watchPickupGun() SetWeaponDistMulti( weap ) { if ( weap == "none" ) + { return 1; + } switch ( weaponClass( weap ) ) { @@ -361,10 +371,14 @@ SetWeaponDistMulti( weap ) IsWeapSniper( weap ) { if ( weap == "none" ) + { return false; + } if ( weaponClass( weap ) != "sniper" ) + { return false; + } return true; } @@ -382,7 +396,9 @@ watchHoldBreath() wait 1; if ( self.bot.isfrozen ) + { continue; + } self holdbreath( self playerads() > 0 ); } @@ -408,7 +424,9 @@ onWeaponChange() 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 ); @@ -428,15 +446,21 @@ reload_watch_loop() ret = self waittill_any_timeout( 7.5, "reload" ); if ( ret == "timeout" ) + { break; + } weap = self getcurrentweapon(); if ( weap == "none" ) + { break; + } if ( self getweaponslotclipammo( self getWeaponSlot( weap ) ) >= WeaponClipSize( weap ) ) + { break; + } } self.bot.isreloading = false; @@ -466,18 +490,26 @@ stance_loop() self.bot.climbing = false; if ( self.bot.isfrozen ) + { return; + } 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 ( toStance == "climb" ) { @@ -486,14 +518,22 @@ stance_loop() } if ( toStance != "stand" && toStance != "crouch" && toStance != "prone" ) + { toStance = "crouch"; + } if ( toStance == "stand" ) + { self stand(); + } else if ( toStance == "crouch" ) + { self crouch(); + } else + { self prone(); + } } /* @@ -539,21 +579,29 @@ reload_thread() wait 2.5; 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 getweaponslotammo( self getWeaponSlot( cur ) ) ) + { return; + } maxsize = WeaponClipSize( cur ); cursize = self getweaponslotclipammo( self getWeaponSlot( cur ) ); if ( cursize / maxsize < 0.5 ) + { self thread reload(); + } } /* @@ -572,7 +620,9 @@ updateBones() self waittill_notify_or_timeout( "new_enemy", waittime ); if ( !isdefined( self.bot.target ) ) + { continue; + } self.bot.target.bone = random( bones ); } @@ -611,20 +661,28 @@ updateAimOffset( obj ) diffAimAmount = self.pers[ "bots" ][ "skill" ][ "aim_offset_amount" ]; if ( diffAimAmount > 0 ) + { obj.aim_offset_base = ( randomfloatrange( 0 - diffAimAmount, diffAimAmount ), randomfloatrange( 0 - diffAimAmount, diffAimAmount ), randomfloatrange( 0 - diffAimAmount, diffAimAmount ) ); + } 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 = vector_scale( obj.aim_offset_base, offsetScalar ); } @@ -647,9 +705,13 @@ targetObjUpdateTraced( obj, daDist, ent, theTime, isScriptObj ) if ( !isScriptObj ) { if ( daDist > distMax ) + { timeMulti = 0; + } else if ( daDist > distClose ) + { timeMulti = 1 - ( ( daDist - distClose ) / ( distMax - distClose ) ); + } } obj.no_trace_time = 0; @@ -710,7 +772,9 @@ target_loop() if ( i == -1 ) { if ( !isdefined( self.bot.script_target ) ) + { continue; + } ent = self.bot.script_target; key = ent getentitynumber() + ""; @@ -720,7 +784,9 @@ target_loop() entOrigin = ent.origin; if ( isdefined( self.bot.script_target_offset ) ) + { entOrigin += self.bot.script_target_offset; + } if ( SmokeTrace( myEye, entOrigin, level.smokeradius ) && bullettracepassed( myEye, entOrigin, false, ent ) ) { @@ -737,7 +803,9 @@ target_loop() else { if ( !isObjDef ) + { continue; + } self targetObjUpdateNoTrace( obj ); @@ -753,7 +821,9 @@ target_loop() player = level.players[ i ]; if ( player == self ) + { continue; + } key = player getentitynumber() + ""; obj = self.bot.targets[ key ]; @@ -763,7 +833,9 @@ target_loop() if ( ( level.teambased && self.team == player.team ) || player.sessionstate != "playing" || !isalive( player ) ) { if ( isObjDef ) + { self.bot.targets[ key ] = undefined; + } continue; } @@ -811,7 +883,9 @@ target_loop() else { if ( !isObjDef ) + { continue; + } self targetObjUpdateNoTrace( obj ); @@ -824,10 +898,14 @@ target_loop() } if ( !isdefined( obj ) ) + { continue; + } if ( theTime - obj.time < initReactTime ) + { continue; + } timeDiff = theTime - obj.trace_time_time; @@ -846,7 +924,9 @@ target_loop() } if ( hasTarget && isdefined( bestTargets[ self.bot.target.entity getentitynumber() + "" ] ) ) + { return; + } closest = 2147483647; toBeTarget = undefined; @@ -856,7 +936,9 @@ target_loop() theDist = bestTargets[ bestKeys[ i ] ].dist; if ( theDist > closest ) + { continue; + } closest = theDist; toBeTarget = bestTargets[ bestKeys[ i ] ]; @@ -866,10 +948,14 @@ target_loop() 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 ) { @@ -907,13 +993,19 @@ onNewEnemy() 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(); } @@ -931,47 +1023,73 @@ watchToLook() 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 ( !getcvarint( "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 jump(); @@ -979,7 +1097,9 @@ watchToLook() 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(); @@ -1053,12 +1173,16 @@ aim_loop() 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; @@ -1069,10 +1193,14 @@ aim_loop() bone = self.bot.target.bone; if ( !isdefined( bone ) ) + { bone = "j_spineupper"; + } if ( self.bot.isfraggingafter || self.bot.issmokingafter || issubstr( "_grenade_", curweap ) ) + { nadeAimOffset = dist / 3000; + } if ( no_trace_time && ( !isdefined( self.bot.after_target ) || self.bot.after_target != target ) ) { @@ -1090,9 +1218,13 @@ aim_loop() time = 0.5; if ( !isSecondaryGrenade( nade ) ) + { self thread frag( time ); + } else + { self thread smoke( time ); + } self notify( "kill_goal" ); } @@ -1104,7 +1236,9 @@ aim_loop() 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(); + } } } @@ -1119,7 +1253,9 @@ aim_loop() aimpos = target getTagOrigin( bone ); if ( !isdefined( aimpos ) ) + { return; + } aimpos += offset; aimpos += aimoffset; @@ -1128,9 +1264,13 @@ aim_loop() conedot = getConeDot( aimpos, eyePos, angles ); if ( !nadeAimOffset && conedot > 0.999 && lengthsquared( aimoffset ) < 0.05 ) + { self thread bot_lookat( aimpos, 0.05 ); + } else + { self thread bot_lookat( aimpos, aimspeed, target getVelocity(), true ); + } } else { @@ -1142,9 +1282,13 @@ aim_loop() conedot = getConeDot( aimpos, eyePos, angles ); if ( !nadeAimOffset && conedot > 0.999 && lengthsquared( aimoffset ) < 0.05 ) + { self thread bot_lookat( aimpos, 0.05 ); + } else + { self thread bot_lookat( aimpos, aimspeed ); + } } if ( isplay && !self.bot.isknifingafter && conedot > 0.9 && dist < level.bots_maxknifedistance && trace_time > reaction_time && getcvarint( "bots_play_knife" ) ) @@ -1155,7 +1299,9 @@ aim_loop() } if ( !self canFire( curweap ) || !self isInRange( dist, curweap ) ) + { return; + } canADS = ( self canAds( dist, curweap ) && conedot > 0.75 ); @@ -1166,22 +1312,32 @@ aim_loop() 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 ( trace_time > reaction_time ) { if ( ( !canADS || adsAmount >= 1.0 || self GetStance() == "prone" ) && ( conedot > 0.99 || dist < level.bots_maxknifedistance ) && getcvarint( "bots_play_fire" ) ) + { self botFire(); + } if ( isplay ) + { self thread start_bot_after_target( target ); + } } return; @@ -1196,7 +1352,9 @@ aim_loop() dist = distancesquared( self.origin, last_pos ); if ( self.bot.isfraggingafter || self.bot.issmokingafter || issubstr( "_grenade_", curweap ) ) + { nadeAimOffset = dist / 3000; + } aimpos = last_pos + ( 0, 0, self getEyeHeight() + nadeAimOffset ); conedot = getConeDot( aimpos, eyePos, angles ); @@ -1204,7 +1362,9 @@ aim_loop() self thread bot_lookat( aimpos, aimspeed ); if ( !self canFire( curweap ) || !self isInRange( dist, curweap ) ) + { return; + } canADS = ( self canAds( dist, curweap ) && conedot > 0.75 ); @@ -1215,17 +1375,25 @@ aim_loop() 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 GetStance() == "prone" ) && ( conedot > 0.95 || dist < level.bots_maxknifedistance ) && getcvarint( "bots_play_fire" ) ) + { self botFire(); + } return; } @@ -1245,12 +1413,18 @@ aim_loop() lookat = undefined; if ( self.bot.second_next_wp != -1 && !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 getEyeHeight() ), aimspeed ); + } } } @@ -1267,7 +1441,9 @@ aim() wait 0.05; if ( level.gameended || self.bot.isfrozen ) + { continue; + } self aim_loop(); } @@ -1287,7 +1463,9 @@ botFire() } if ( self.bot.semi_time ) + { return; + } self thread pressFire(); self thread doSemiTime(); @@ -1314,7 +1492,9 @@ doSemiTime() canFire( curweap ) { if ( curweap == "none" ) + { return false; + } return self getweaponslotclipammo( self getWeaponSlot( curweap ) ); } @@ -1325,20 +1505,28 @@ canFire( curweap ) canAds( dist, curweap ) { if ( curweap == "none" ) + { return false; + } if ( !getcvarint( "bots_play_ads" ) ) + { return false; + } far = level.bots_noadsdistance; if ( dist < far ) + { return false; + } weapclass = ( weaponClass( curweap ) ); if ( weapclass == "spread" ) + { return false; + } return true; } @@ -1349,12 +1537,16 @@ canAds( dist, curweap ) isInRange( dist, curweap ) { if ( curweap == "none" ) + { return false; + } weapclass = weaponClass( curweap ); if ( weapclass == "spread" && dist > level.bots_maxshotgundistance ) + { return false; + } return true; } @@ -1396,7 +1588,9 @@ walk_loop() curweap = self getcurrentweapon(); if ( self.bot.target.entity.classname == "script_vehicle" ) + { return; + } if ( self.bot.isfraggingafter || self.bot.issmokingafter ) { @@ -1406,10 +1600,14 @@ walk_loop() if ( isplayer( self.bot.target.entity ) && self.bot.target.trace_time && self canFire( curweap ) && self isInRange( self.bot.target.dist, curweap ) ) { if ( 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; } @@ -1418,7 +1616,9 @@ walk_loop() dist = 16; if ( level.waypointcount ) + { goal = level.waypoints[ randomint( level.waypointcount ) ].origin; + } else { self thread killWalkCauseNoWaypoints(); @@ -1469,7 +1669,9 @@ walk_loop() else { if ( hasTarget ) + { goal = self.bot.target.last_seen_pos; + } self notify( "new_goal_internal" ); } @@ -1495,10 +1697,14 @@ walk() self botSetMoveTo( self.origin ); if ( !getcvarint( "bots_play_move" ) ) + { continue; + } if ( level.gameended || self.bot.isfrozen || self.bot.stop_move ) + { continue; + } self walk_loop(); } @@ -1526,7 +1732,9 @@ strafe( target ) strafe = traceLeft[ "position" ]; if ( traceRight[ "fraction" ] > traceLeft[ "fraction" ] ) + { strafe = traceRight[ "position" ]; + } self.bot.last_next_wp = -1; self.bot.last_second_next_wp = -1; @@ -1545,7 +1753,9 @@ watchOnGoal( goal, dis ) self endon( "kill_goal" ); while ( distancesquared( self.origin, goal ) > dis ) + { wait 0.05; + } self notify( "goal_internal" ); } @@ -1558,7 +1768,9 @@ 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 ); + } } /* @@ -1569,12 +1781,16 @@ 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; } @@ -1587,7 +1803,9 @@ removeAStar() remove = self.bot.astar.size - 1; if ( level.teambased ) + { RemoveWaypointUsage( self.bot.astar[ remove ], self.team ); + } self.bot.astar[ remove ] = undefined; @@ -1620,9 +1838,13 @@ doWalkScriptNotify() self endon( "kill_goal" ); if ( self waittill_either_return( "goal_internal", "bad_path_internal" ) == "goal_internal" ) + { self notify( "goal" ); + } else + { self notify( "bad_path" ); + } } /* @@ -1637,7 +1859,9 @@ doWalk( goal, dist, isScriptGoal ) dist *= dist; if ( isScriptGoal ) + { self thread doWalkScriptNotify(); + } self thread killWalkOnEvents(); self thread watchOnGoal( goal, dist ); @@ -1646,7 +1870,9 @@ doWalk( goal, dist, isScriptGoal ) // 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 ) { @@ -1659,7 +1885,9 @@ doWalk( goal, dist, isScriptGoal ) self.bot.second_next_wp = -1; if ( current > 0 ) + { self.bot.second_next_wp = self.bot.astar[ current - 1 ]; + } self notify( "new_static_waypoint" ); @@ -1688,7 +1916,9 @@ doWalk( goal, dist, isScriptGoal ) wait 1; if ( distancesquared( self.origin, goal ) > dist ) + { self notify( "bad_path_internal" ); + } } /* @@ -1697,7 +1927,9 @@ doWalk( goal, dist, isScriptGoal ) movetowards( goal ) { if ( !isdefined( goal ) ) + { return; + } self.bot.towards_goal = goal; @@ -1742,7 +1974,9 @@ movetowards( goal ) else if ( time == 2000 ) { if ( distancesquared( self.origin, lastOri ) < 32 * 32 ) + { self crouch(); + } } else if ( time == 1750 ) { @@ -1760,12 +1994,18 @@ movetowards( goal ) time += 50; if ( lengthsquared( self getVelocity() ) < 1000 ) + { timeslow += 50; + } else + { timeslow = 0; + } if ( stucks == 2 ) + { self notify( "bad_path_internal" ); + } } self.bot.towards_goal = undefined; @@ -1827,9 +2067,13 @@ getRandomLargestStafe( dist ) holdbreath( what ) { if ( what ) + { self BotBuiltinBotAction( "+holdbreath" ); + } else + { self BotBuiltinBotAction( "-holdbreath" ); + } } /* @@ -1882,14 +2126,18 @@ frag( time ) 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; @@ -1909,14 +2157,18 @@ smoke( time ) 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; @@ -1933,9 +2185,13 @@ fire( what ) self notify( "bot_fire" ); if ( what ) + { self BotBuiltinBotAction( "+fire" ); + } else + { self BotBuiltinBotAction( "-fire" ); + } } /* @@ -1949,12 +2205,16 @@ pressFire( time ) self endon( "bot_fire" ); if ( !isdefined( time ) ) + { time = 0.05; + } self BotBuiltinBotAction( "+fire" ); if ( time ) + { wait time; + } self BotBuiltinBotAction( "-fire" ); } @@ -1967,9 +2227,13 @@ ads( what ) self notify( "bot_ads" ); if ( what ) + { self BotBuiltinBotAction( "+ads" ); + } else + { self BotBuiltinBotAction( "-ads" ); + } } /* @@ -1983,12 +2247,16 @@ pressADS( time ) self endon( "bot_ads" ); if ( !isdefined( time ) ) + { time = 0.05; + } self BotBuiltinBotAction( "+ads" ); if ( time ) + { wait time; + } self BotBuiltinBotAction( "-ads" ); } @@ -2004,12 +2272,16 @@ use( time ) self endon( "bot_use" ); if ( !isdefined( time ) ) + { time = 0.05; + } self BotBuiltinBotAction( "+activate" ); if ( time ) + { wait time; + } self BotBuiltinBotAction( "-activate" ); } @@ -2083,24 +2355,36 @@ bot_lookat( pos, time, vel, doAimPredict ) level endon ( "game_ended" ); if ( level.gameended || self.bot.isfrozen || !getcvarint( "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; + } myEye = self getEyePos(); // get our eye pos diff --git a/maps/mp/bots/_bot_script.gsc b/maps/mp/bots/_bot_script.gsc index 9f3ba12..d1376d2 100644 --- a/maps/mp/bots/_bot_script.gsc +++ b/maps/mp/bots/_bot_script.gsc @@ -38,28 +38,44 @@ onKilled( eInflictor, eAttacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, 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; @@ -71,31 +87,49 @@ onKilled( eInflictor, eAttacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, 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; + } self bot_cry_for_help( eAttacker ); @@ -131,10 +165,14 @@ bot_cry_for_help( attacker ) } if ( !isdefined( player.team ) ) + { continue; + } if ( !player IsPlayerModelOK() ) + { continue; + } if ( !isalive( player ) ) { @@ -472,15 +510,21 @@ teamWatch() for ( ;; ) { while ( !isdefined( self.pers[ "team" ] ) || !allowTeamChoice() ) + { wait .05; + } wait 0.1; if ( self.team != "axis" && self.team != "allies" ) + { self notify( "menuresponse", game[ "menu_team" ], getcvar( "bots_team" ) ); + } while ( isdefined( self.pers[ "team" ] ) ) + { wait .05; + } } } @@ -552,17 +596,23 @@ classWatch() for ( ;; ) { while ( !isdefined( self.pers[ "team" ] ) || !allowClassChoice() ) + { wait .05; + } wait 0.5; if ( !isdefined( self.pers[ "weapon" ] ) || self.pers[ "weapon" ] == "" || !isdefined( self.bot_change_class ) ) + { self notify( "menuresponse", game[ "menu_weapon_" + self.team ], self chooseRandomClass() ); + } self.bot_change_class = true; while ( isdefined( self.pers[ "team" ] ) && isdefined( self.pers[ "weapon" ] ) && self.pers[ "weapon" ] != "" && isdefined( self.bot_change_class ) ) + { wait .05; + } } } @@ -578,7 +628,9 @@ onSpawned() self waittill( "spawned_player" ); if ( randomint( 100 ) <= self.pers[ "bots" ][ "behavior" ][ "class" ] ) + { self.bot_change_class = undefined; + } self.bot_lock_goal = false; self.help_time = undefined; diff --git a/maps/mp/bots/_bot_utility.gsc b/maps/mp/bots/_bot_utility.gsc index 6898381..d48ad0a 100644 --- a/maps/mp/bots/_bot_utility.gsc +++ b/maps/mp/bots/_bot_utility.gsc @@ -8,12 +8,18 @@ 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; @@ -95,7 +101,9 @@ doHostCheck() self.pers[ "bot_host" ] = false; if ( self is_bot() ) + { return; + } result = false; @@ -109,7 +117,9 @@ doHostCheck() } if ( getcvar( "bots_main_firstIsHost" ) == self getguid() + "" ) + { result = true; + } } DvarGUID = getcvar( "bots_main_GUIDs" ); @@ -121,12 +131,16 @@ doHostCheck() for ( i = 0; i < guids.size; i++ ) { if ( self getguid() + "" == guids[ i ] ) + { result = true; + } } } if ( !result ) + { return; + } self.pers[ "bot_host" ] = true; } @@ -209,7 +223,9 @@ BotGetRandom() BotGetTargetRandom() { if ( !isdefined( self.bot.target ) ) + { return undefined; + } return self.bot.target.rand; } @@ -254,7 +270,9 @@ BotFreezeControls( what ) self.bot.isfrozen = what; if ( what ) + { self notify( "kill_goal" ); + } } /* @@ -273,7 +291,9 @@ BotStopMoving( what ) self.bot.stop_move = what; if ( what ) + { self notify( "kill_goal" ); + } } /* @@ -307,7 +327,9 @@ GetScriptGoal() SetScriptGoal( goal, dist ) { if ( !isdefined( dist ) ) + { dist = 16; + } self.bot.script_goal = goal; self.bot.script_goal_dist = dist; @@ -387,7 +409,9 @@ ClearScriptEnemy() GetThreat() { if ( !isdefined( self.bot.target ) ) + { return undefined; + } return self.bot.target.entity; } @@ -462,10 +486,14 @@ getValidGrenade() for ( i = 0; i < grenadeTypes.size; i++ ) { if ( !self hasweapon( grenadeTypes[ i ] ) ) + { continue; + } if ( !self getAmmoCount( grenadeTypes[ i ] ) ) + { continue; + } possibles[ possibles.size ] = grenadeTypes[ i ]; } @@ -505,7 +533,9 @@ weaponClass( weap ) answer = level.bots_weapon_class_names[ weap ]; if ( !isdefined( answer ) ) + { answer = ""; + } return answer; } @@ -518,7 +548,9 @@ WeaponClipSize( weap ) answer = level.bots_weapon_clip_sizes[ weap ]; if ( !isdefined( answer ) ) + { answer = 1; + } return answer; } @@ -529,9 +561,13 @@ WeaponClipSize( weap ) getWeaponSlot( weap ) { if ( self getweaponslotweapon( "primary" ) == weap ) + { return "primary"; + } else + { return "primaryb"; + } } /* @@ -562,10 +598,14 @@ getStance() height = myEye[ 2 ] - self.origin[ 2 ]; if ( height > 50 ) + { return "stand"; + } if ( height < 20 ) + { return "prone"; + } return "crouch"; } @@ -576,7 +616,9 @@ getStance() getVelocity() { if ( !isalive( self ) ) + { return ( 0, 0, 0 ); + } return self.velocity; } @@ -625,10 +667,14 @@ getEyeHeight() getTagOrigin( where ) { if ( !isalive( self ) ) + { return ( 0, 0, 0 ); + } if ( !isdefined( self.bot_model_fix ) ) + { return self.origin; + } if ( !isdefined( self.tags ) ) { @@ -637,7 +683,9 @@ getTagOrigin( where ) } if ( isdefined( self.tagmap[ where ] ) ) + { return self.tagmap[ where ].origin; + } obj = spawn( "script_origin", ( 0, 0, 0 ) ); obj linkto( self, where, ( 0, 0, 0 ), ( 0, 0, 0 ) ); @@ -672,7 +720,9 @@ waittill_either_return_( str1, str2 ) waittill_either_return( str1, str2 ) { if ( !isdefined( self waittill_either_return_( str1, str2 ) ) ) + { return str1; + } return str2; } @@ -692,7 +742,9 @@ waittill_either( not, not1 ) waittill_string( msg, ent ) { if ( msg != "death" ) + { self endon( "death" ); + } ent endon( "die" ); self waittill( msg ); @@ -704,29 +756,37 @@ waittill_string( msg, ent ) */ waittill_any_timeout( timeOut, string1, string2, string3, string4, string5 ) { - if ( ( !isdefined( string1 ) || string1 != "death" ) && - ( !isdefined( string2 ) || string2 != "death" ) && - ( !isdefined( string3 ) || string3 != "death" ) && - ( !isdefined( string4 ) || string4 != "death" ) && - ( !isdefined( string5 ) || string5 != "death" ) ) + if ( ( !isdefined( string1 ) || string1 != "death" ) && ( !isdefined( string2 ) || string2 != "death" ) && ( !isdefined( string3 ) || string3 != "death" ) && ( !isdefined( string4 ) || string4 != "death" ) && ( !isdefined( string5 ) || string5 != "death" ) ) + { self endon( "death" ); + } ent = spawnstruct(); if ( isdefined( string1 ) ) + { self thread waittill_string( string1, ent ); + } if ( isdefined( string2 ) ) + { self thread waittill_string( string2, ent ); + } if ( isdefined( string3 ) ) + { self thread waittill_string( string3, ent ); + } if ( isdefined( string4 ) ) + { self thread waittill_string( string4, ent ); + } if ( isdefined( string5 ) ) + { self thread waittill_string( string5, ent ); + } ent thread _timeout( timeOut ); @@ -762,7 +822,9 @@ random( arr ) size = arr.size; if ( !size ) + { return undefined; + } return arr[ randomint( size ) ]; } @@ -779,7 +841,9 @@ array_remove( ents, remover ) index = ents[ i ]; if ( index != remover ) + { newents[ newents.size ] = index; + } } return newents; @@ -804,7 +868,9 @@ GetHostPlayer() player = level.players[ i ]; if ( !player is_host() ) + { continue; + } return player; } @@ -820,36 +886,48 @@ bot_wait_for_host() host = undefined; while ( !isdefined( level ) || !isdefined( level.players ) ) + { wait 0.05; + } for ( i = getcvarfloat( "bots_main_waitForHostTime" ); i > 0; i -= 0.05 ) { host = GetHostPlayer(); if ( isdefined( host ) ) + { break; + } wait 0.05; } if ( !isdefined( host ) ) + { return; + } for ( i = getcvarfloat( "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 = getcvarfloat( "bots_main_waitForHostTime" ); i > 0; i -= 0.05 ) { if ( host.pers[ "team" ] == "allies" || host.pers[ "team" ] == "axis" ) + { break; + } wait 0.05; } @@ -866,7 +944,9 @@ sqrt( num ) // "bit" starts at the highest power of four <= the argument. while ( bit > num ) + { bit >>= 2; + } while ( bit != 0 ) { @@ -876,7 +956,9 @@ sqrt( num ) res = ( res >> 1 ) + bit; } else + { res >>= 1; + } bit >>= 2; } @@ -894,10 +976,14 @@ RaySphereIntersect( start, end, spherePos, radius ) 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; @@ -910,7 +996,9 @@ RaySphereIntersect( start, end, spherePos, 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); @@ -923,13 +1011,17 @@ RaySphereIntersect( start, end, spherePos, radius ) // 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; } @@ -953,7 +1045,9 @@ SmokeTrace( start, end, rad ) nade = level.bots_smokelist.data[ i ]; if ( !RaySphereIntersect( start, end, nade.origin, rad ) ) + { continue; + } return false; } @@ -992,12 +1086,18 @@ RoundNum( x ) if ( abs( x ) - abs( y ) > 0.5 ) { if ( x < 0 ) + { return y - 1; + } else + { return y + 1; + } } else + { return y; + } } /* @@ -1008,9 +1108,13 @@ RoundUp( floatVal ) i = int( floatVal ); if ( i != floatVal ) + { return i + 1; + } else + { return i; + } } /* @@ -1022,7 +1126,9 @@ AngleClamp180( angle ) angle = ( angleFrac - int( angleFrac ) ) * 360.0; if ( angle > 180.0 ) + { return angle - 360.0; + } return angle; } @@ -1033,7 +1139,9 @@ AngleClamp180( angle ) max( a, b ) { if ( a > b ) + { return a; + } return b; } @@ -1044,7 +1152,9 @@ max( a, b ) min( a, b ) { if ( a > b ) + { return b; + } return a; } @@ -1198,7 +1308,9 @@ parseTokensIntoWaypoint( tokens ) waypoint.children = []; for ( j = 0; j < childToks.size; j++ ) + { waypoint.children[ j ] = int( childToks[ j ] ); + } type = tokens[ 2 ]; waypoint.type = type; @@ -1210,7 +1322,9 @@ parseTokensIntoWaypoint( tokens ) anglesToks = strtok( anglesStr, " " ); if ( anglesToks.size >= 3 ) + { waypoint.angles = ( float_old( anglesToks[ 0 ] ), float_old( anglesToks[ 1 ] ), float_old( anglesToks[ 2 ] ) ); + } } return waypoint; @@ -1226,7 +1340,9 @@ readWpsFromFile( mapname ) f = openfile( filename, "read" ); if ( f < 0 ) + { return waypoints; + } BotBuiltinPrintConsole( "Attempting to read waypoints from " + filename ); @@ -1235,12 +1351,16 @@ readWpsFromFile( mapname ) argc = freadln( f ); if ( argc <= 0 ) + { break; + } waypointCount = int( fgetarg( f, 0 ) ); if ( waypointCount <= 0 ) + { break; + } for ( i = 1; i <= waypointCount; i++ ) { @@ -1256,7 +1376,9 @@ readWpsFromFile( mapname ) } if ( !isdefined( line ) || line == "" ) + { continue; + } tokens = strtok( line, "," ); @@ -1291,10 +1413,14 @@ loadmbotWps( mapname, gametype ) wps = []; if ( f < 0 ) + { f = openfile( mapname + "_" + gametype + ".tmp", "read" ); + } if ( f < 0 ) + { return wps; + } argc = freadln( f ); @@ -1320,7 +1446,9 @@ loadmbotWps( mapname, gametype ) t = strtok( s, " ," ); if ( !isdefined( t ) || t.size < 6 ) + { break; + } wp = spawnstruct(); wp.origin = ( float_old( t[ 0 ] ), float_old( t[ 1 ] ), float_old( t[ 2 ] ) ); @@ -1328,20 +1456,30 @@ loadmbotWps( mapname, gametype ) stance = "stand"; if ( t[ 4 ] == "1" ) + { stance = "crouch"; + } else if ( t[ 4 ] == "2" ) + { stance = "prone"; + } wp.children = []; k = 0; for ( k = 0; k < int( t[ 5 ] ); k++ ) + { wp.children[ k ] = int( t[ 6 + k ] ); + } if ( t[ 3 ] == "l" || t[ 3 ] == "m" || t[ 3 ] == "f" || t[ 3 ] == "j" ) + { wp.type = "climb"; + } else if ( t[ 3 ] == "g" ) + { wp.type = "grenade"; + } else if ( t[ 3 ] == "c" ) { wp.type = "crouch"; @@ -1351,7 +1489,9 @@ loadmbotWps( mapname, gametype ) wp.children[ 0 ] = wpc; } else + { wp.type = stance; + } if ( ( t.size == 9 && t[ 3 ] == "w" && t[ 5 ] == "1" ) || t[ 3 ] == "g" || t[ 3 ] == "c" ) { @@ -1381,7 +1521,9 @@ load_waypoints() if ( !isdefined( level.waypoints ) ) + { level.waypoints = []; + } wps = readWpsFromFile( mapname ); @@ -1400,7 +1542,9 @@ load_waypoints() } if ( level.waypoints.size ) + { BotBuiltinPrintConsole( "Loaded " + level.waypoints.size + " waypoints from script." ); + } } if ( !level.waypoints.size ) @@ -1410,7 +1554,9 @@ load_waypoints() level.waypoints = wps; if ( level.waypoints.size ) + { BotBuiltinPrintConsole( "Loaded mbot " + level.waypoints.size + " wps" ); + } } if ( !level.waypoints.size ) @@ -1423,13 +1569,19 @@ load_waypoints() for ( i = 0; i < level.waypointcount; 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; } @@ -1447,7 +1599,9 @@ nearAnyOfWaypoints( dist, waypoints ) waypoint = level.waypoints[ waypoints[ i ] ]; if ( distancesquared( waypoint.origin, self.origin ) > dist ) + { continue; + } return true; } @@ -1469,7 +1623,9 @@ waypointsNear( waypoints, dist ) wp = level.waypoints[ waypoints[ i ] ]; if ( distancesquared( wp.origin, self.origin ) > dist ) + { continue; + } answer[ answer.size ] = waypoints[ i ]; } @@ -1491,7 +1647,9 @@ getNearestWaypointOfWaypoints( waypoints ) thisDist = distancesquared( self.origin, waypoint.origin ); if ( isdefined( answer ) && thisDist > closestDist ) + { continue; + } answer = waypoints[ i ]; closestDist = thisDist; @@ -1514,13 +1672,19 @@ getWaypointsOfType( type ) if ( type == "camp" ) { if ( wp.type != "crouch" ) + { continue; + } if ( wp.children.size != 1 ) + { continue; + } } else if ( type != wp.type ) + { continue; + } answer[ answer.size ] = i; } @@ -1534,7 +1698,9 @@ getWaypointsOfType( type ) getWaypointForIndex( i ) { if ( !isdefined( i ) ) + { return undefined; + } return level.waypoints[ i ]; } @@ -1571,16 +1737,24 @@ waittill_any( string1, string2, string3, string4, string5 ) assert( isdefined( string1 ) ); if ( isdefined( string2 ) ) + { self endon( string2 ); + } if ( isdefined( string3 ) ) + { self endon( string3 ); + } if ( isdefined( string4 ) ) + { self endon( string4 ); + } if ( isdefined( string5 ) ) + { self endon( string5 ); + } self waittill( string1 ); } @@ -1601,7 +1775,9 @@ getBotToKick() bots = getBotArray(); if ( !isdefined( bots ) || !isdefined( bots.size ) || bots.size <= 0 || !isdefined( bots[ 0 ] ) ) + { return undefined; + } tokick = undefined; axis = 0; @@ -1614,14 +1790,22 @@ getBotToKick() 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 @@ -1635,7 +1819,9 @@ getBotToKick() team = "allies"; if ( axis > allies ) + { team = "axis"; + } } else { @@ -1648,22 +1834,32 @@ getBotToKick() 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++ ) @@ -1671,13 +1867,19 @@ getBotToKick() 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; } @@ -1698,7 +1900,9 @@ getBotArray() player = level.players[ i ]; if ( !player is_bot() ) + { continue; + } result[ result.size ] = player; } @@ -1724,7 +1928,9 @@ WaypointsToKDTree() _WaypointsToKDTree( waypoints, dem ) { if ( !waypoints.size ) + { return; + } callbacksort = undefined; @@ -1764,10 +1970,16 @@ _WaypointsToKDTree( waypoints, dem ) 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 ] ); @@ -1881,25 +2093,37 @@ _KDTreeInsert( node, data, dem, x0, y0, z0, x1, y1, z1 ) { 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; } @@ -1913,7 +2137,9 @@ _KDTreeInsert( node, data, dem, x0, y0, z0, x1, y1, z1 ) KDTreeNearest( origin ) { if ( !isdefined( self.root ) ) + { return undefined; + } return self _KDTreeNearest( self.root, origin, self.root.data, distancesquared( self.root.data.origin, origin ), 0 ); } @@ -1965,20 +2191,32 @@ RectDistanceSquared( origin ) 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; } @@ -2059,7 +2297,9 @@ HeapInsert( item ) 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; @@ -2075,15 +2315,23 @@ _HeapNextChild( node, hsize ) 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; + } } /* @@ -2094,7 +2342,9 @@ HeapRemove() remove = self.data.size; if ( !remove ) + { return remove; + } move = self.data[ remove - 1 ]; self.data[ 0 ] = move; @@ -2102,7 +2352,9 @@ HeapRemove() remove--; if ( !remove ) + { return remove; + } last = 1; next = self _HeapNextChild( 1, remove ); @@ -2110,7 +2362,9 @@ HeapRemove() 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; @@ -2136,15 +2390,21 @@ ReverseHeapAStar( item, item2 ) RemoveWaypointUsage( wp, team ) { if ( !isdefined( level.waypointusage ) ) + { return; + } if ( !isdefined( level.waypointusage[ team ][ wp + "" ] ) ) + { return; + } level.waypointusage[ team ][ wp + "" ]--; if ( level.waypointusage[ team ][ wp + "" ] <= 0 ) + { level.waypointusage[ team ][ wp + "" ] = undefined; + } } /* @@ -2158,12 +2418,16 @@ GetNearestWaypointWithSight( pos ) for ( i = 0; i < level.waypointcount; i++ ) { if ( !bullettracepassed( pos + ( 0, 0, 15 ), level.waypoints[ i ].origin + ( 0, 0, 15 ), false, undefined ) ) + { continue; + } curdis = distancesquared( level.waypoints[ i ].origin, pos ); if ( curdis > dist ) + { continue; + } dist = curdis; candidate = i; @@ -2185,7 +2449,9 @@ getNearestWaypoint( pos ) curdis = distancesquared( level.waypoints[ i ].origin, pos ); if ( curdis > dist ) + { continue; + } dist = curdis; candidate = i; @@ -2209,29 +2475,41 @@ AStarSearch( start, goal, team, greedy_path ) 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(); @@ -2264,7 +2542,9 @@ AStarSearch( start, goal, team, greedy_path ) if ( isdefined( team ) && isdefined( level.waypointusage ) ) { if ( !isdefined( level.waypointusage[ team ][ bestNode.index + "" ] ) ) + { level.waypointusage[ team ][ bestNode.index + "" ] = 0; + } level.waypointusage[ team ][ bestNode.index + "" ]++; } @@ -2291,15 +2571,21 @@ AStarSearch( start, goal, team, greedy_path ) temppen = 1; if ( isdefined( level.waypointusage[ team ][ child + "" ] ) ) - temppen = level.waypointusage[ team ][ child + "" ]; //consider how many bots are taking this path + { + temppen = level.waypointusage[ team ][ child + "" ]; //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 @@ -2308,21 +2594,31 @@ AStarSearch( start, goal, team, greedy_path ) inopen = isdefined( openset[ child + "" ] ); if ( inopen && openset[ child + "" ].g <= newg ) + { continue; + } inclosed = isdefined( closed[ child + "" ] ); if ( inclosed && closed[ child + "" ].g <= newg ) + { continue; + } node = undefined; if ( inopen ) + { node = openset[ child + "" ]; + } else if ( inclosed ) + { node = closed[ child + "" ]; + } else + { node = spawnstruct(); + } node.parent = bestNode; node.g = newg; @@ -2332,7 +2628,9 @@ AStarSearch( start, goal, team, greedy_path ) //check if in closed, remove it if ( inclosed ) + { closed[ child + "" ] = undefined; + } //check if not in open, add it if ( !inopen )