//////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// ////////////// ////////// //////// /////// ///////////// // /////// //////// //////// //////////// //// /////// ////////////////// /////////////////// /////////// ///////// ////////// //////////// ////////// / /////////////// //////// ///////////// ///////// /// ///////////////////// /////// ////////////////////// //////// ///// ///////// /////// ///////////// /////// /////// /////// //////// ////////////// //////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// /* MW2 RSE Bots v35 Retarded (Smart) Enemies bots.gsc CUSTOM GSC FILE Feel free to use the code. Just give credit where credit is due! */ init(myteam, bots, team) { level endon("menu_kick"); if(myteam != "none") { if(level.bot_allies_spawning == 1) bots = bots - level.teamCount["allies"]; if(level.bot_axis_spawning == 1) bots = bots - level.teamCount["axis"]; if(bots <= 0) { if(myteam == "allies") { if(level.bot_allies_spawning == 1) level.bot_allies_spawning = 0; else { level.bot_axis_spawning = 0; level.bot_spawning = 0; } } else { if(level.bot_axis_spawning == 1) level.bot_axis_spawning = 0; else { level.bot_allies_spawning = 0; level.bot_spawning = 0; } } } level initTestClients(myteam, bots, team); } else { bots = getdvarInt("init_testclients"); setDvar("init_testclients", 0); level initTestClients("none", bots, "none"); bots = 0; } } initTestClients(myteam, numberOfTestClients, team) { level endon("menu_kick"); if(myteam != "none") { for(i = 0; i < numberOfTestClients; i++) { ent[i] = addtestclient(); if(!isdefined(ent[i])) { wait 0.5; continue; } ent[i].pers["isBot"] = true; ent[i] thread StartBots(team); wait 0.5; } if(myteam == "allies") { if(level.bot_allies_spawning == 1) level.bot_allies_spawning = 0; else { level.bot_axis_spawning = 0; level.bot_spawning = 0; } } else { if(level.bot_axis_spawning == 1) level.bot_axis_spawning = 0; else { level.bot_allies_spawning = 0; level.bot_spawning = 0; } } } else { for(i = 0; i < numberOfTestClients; i++) { ent[i] = addtestclient(); if(!isdefined(ent[i])) { wait 0.5; continue; } ent[i].pers["isBot"] = true; ent[i] thread StartBots("autoassign"); wait 0.5; } } } doResetBotsPerRound() { level.ResetBotsPerRound = 1; foreach(player in level.players) { if(isDefined(player.pers["isBot"]) && player.pers["isBot"] == true) { player notify("bot_reset"); wait 0.3; if(isDefined(player.pers["bot"]["loadout"])) player thread ResetBots(); else player thread CameLateLastRound(); } else wait 0.1; } } ResetBots() { self SetcardTitle( self.pers["bot"]["Title"] ); self SetcardIcon( self.pers["bot"]["Emblem"] ); wait 0.5; self thread onBotSpawned(); self thread onBotDeath(); wait 0.5; self thread aiming(); self thread playerAim(); self thread vehicleAim(); wait 0.5; self thread bots\talk::BotTalkEndGame(); self thread bots\talk::BotTalkKilled(); self thread bots\talk::BotTalkDead(); } CameLateLastRound() { self thread doTitleEmblem(); wait 0.5; self bots\customize::pickPerks(); self bots\customize::pickWeapon(); self bots\customize::pickKillstreaks(); self bots\customize::pickPersonality(); wait 0.5; self.pers["bot"]["ks"] = 0; self thread onBotSpawned(); self thread onBotDeath(); wait 0.5; self thread bots\talk::BotTalkEndGame(); self thread bots\talk::BotTalkKilled(); self thread bots\talk::BotTalkDead(); wait 0.5; self thread aiming(); self thread playerAim(); self thread vehicleAim(); } StartBots(team) { level endon("menu_kick"); if(getdvar("bots_difficulty") == "recruit") { self setPlayerData( "experience", RandomInt(440300) ); } else if(getdvar("bots_difficulty") == "regular") { self setPlayerData( "experience", randomintrange(470900, 2516000) ); } else if(getdvar("bots_difficulty") == "hardened") { self setPlayerData( "prestige", randomintrange(1, 10)); self setPlayerData( "experience", RandomInt(2516000) ); } else if(getdvar("bots_difficulty") == "veteran") { self setPlayerData( "prestige", 10); self setPlayerData( "experience", RandomInt(2516000) ); } else // mixed { switch(randomint(4)) { case 0: self setPlayerData( "experience", RandomInt(440300) ); break; case 1: self setPlayerData( "experience", randomintrange(470900, 2516000) ); break; case 2: self setPlayerData( "prestige", randomintrange(1, 10)); self setPlayerData( "experience", RandomInt(2516000) ); break; case 3: self setPlayerData( "prestige", 10); self setPlayerData( "experience", RandomInt(2516000) ); break; } } self initIndividualBot(team); self bots\customize::pickPerks(); self bots\customize::pickWeapon(); self bots\customize::pickKillstreaks(); self bots\customize::pickPersonality(); self.pers["bot"]["ks"] = 0; self thread onBotSpawned(); self thread onBotDeath(); self thread bots\talk::BotTalkEndGame(); self thread bots\talk::BotTalkKilled(); self thread bots\talk::BotTalkDead(); self thread bots\talk::BotTalkForthWall(); self thread aiming(); self thread playerAim(); self thread vehicleAim(); } initIndividualBot(team) { while(!isdefined(self.pers["team"])) wait 0.1; self notify("menuresponse", game["menu_team"], team); wait 0.3; self notify("menuresponse", "changeclass", "class" + randomInt(15)); self waittill( "spawned_player" ); self thread doTitleEmblem(); } onBotDeath() { self endon("bot_reset"); self endon("disconnect"); for(;;) { self waittill("killed_player"); if(self.fMoveSpeed > 0 || self.animinprogress == true) { self bots\includes::endBotAnim(); self thread bots\includes::doBotDeathAnim(); } if(self.using == true) level.using = false; self.pers["bot"]["ks"] = 0; self thread watchKillcam(); } } watchKillcam() { self endon("bot_reset"); self endon("disconnect"); switch(randomint(3)) { case 1: if(getdvar("testclients_watchkillcam") == 0) { setDvar("testclients_watchkillcam", 1); wait 1 + randomint(6); setDvar("testclients_watchkillcam", 0); } break; } } onBotSpawned() { self endon("bot_reset"); self endon("disconnect"); self bots\includes::endBotAnim(); // init animation vars for(;;) { if(bots\includes::_isReallyAlive(self)) { self.lastwp = undefined; self.aimat = undefined; self.tracking = undefined; self.fMoveSpeed = 0; self.using = false; self.atObjectivePos = false; self.botgoalreach = true; self.standingongoal = true; self.shooting = false; self.shootpos = undefined; self.usingksremote = false; self.DistractedByKillstreak = false; self.AttemptedVehicleKill = false; self.throwingknife = false; self.UsedKnife = false; self.meleeinprogress = false; self.didMeleeKamikaze = false; self.doingMeleeKamikaze = false; self.equipmentinprogress = false; self.placedflare = false; self.placedclaymore = false; self.ThrewEquipment = false; self.ThrewSpecGrenade = 0; self.nadesinprogress = false; self.tiredfromsprint = 0; self.type = "wait"; self thread bots\customize::repeatPerks(); self thread bots\customize::repeatWeapon(); self thread GetObj(); self thread BotGoal_StaticWaypointFollowGoal(); self thread watchClaymoreTrip(); self thread botPace(); self thread botScan(); self thread tracking(); if(self.pers["bot"]["pickperk"]["heart"] != 2) self thread footsteps(); self thread doStuck(); self thread CheckRage(); } self waittill( "spawned_player" ); } } CheckRage() { self endon("disconnect"); if(self.pers["bot"]["hasrage"] == 1 && self.pers["bot"]["didrage"] == false && self.pers["cur_death_streak"] >= (10 - self.pers["bot"]["skill"])) { wait 1 + randomint(3); self.pers["bot"]["didrage"] = true; self thread bots\talk::BotTalkRage(); } } doStuck() { self endon("bot_reset"); self endon("death"); self endon("disconnect"); for(;;) { if( self shouldBeMoving() ) { wait 4; before = self getorigin(); wait 4; if( before == self getorigin() && self shouldBeMoving() ) { wait 4; if( before == self getorigin() && self shouldBeMoving() ) { self suicide(); } } } else { wait 4; } } } shouldBeMoving() { if(((self.type == "stand") || (self.type == "crouch")) && (self.shooting == false) && (self.atObjectivePos == false) && (self.standingongoal == false) && (self.using == false) && (!isDefined( self.lastStand ))) { return true; } return false; } watchClaymoreTrip() { self endon("bot_reset"); self endon("death"); self endon("disconnect"); for(;;) { wait 1; // performance saving measure if(self.animinprogress == true) // make bots trip claymores during an animation { foreach(player in level.players) { if(self IsEnemy(player) && isDefined(player.claymorearray)) { for ( i = 0; i < player.claymorearray.size; i++ ) { if (isdefined( player.claymorearray[ i ] ) && distance(self.origin,player.claymorearray[ i ].origin) < 150) { player.claymorearray[ i ] detonate(); self thread [[level.callbackPlayerDamage]] ( player, player, 150, 8, "MOD_GRENADE_SPLASH", "claymore_mp", (0,0,0), (0,0,0), "torso_lower", 0 ); } } } } } } } doTitleEmblem() { self bots\customize::Title(); self bots\customize::Emblem(); wait randomint(12); self thread bots\talk::BotTalkMatchStart(); } IsFacingAtTarget(target) { if(!isDefined(target)) { return false; } if(distance(target.origin, self.origin) < 150) return true; dirToTarget = VectorNormalize(target.origin-self.origin); forward = AnglesToForward(self GetPlayerAngles()); dot = vectordot(dirToTarget, forward); if(dot > self.pers["bot"]["view"]) { return true; } return false; } AttackedMe(attacker) { found = false; if(isDefined(self.attackers)) { foreach(rat in self.attackers) { if(isDefined(rat) && rat == attacker) { found = true; break; } } } return found; } AttackedHim(victim) { found = false; if(isDefined(victim.attackers)) { foreach(player in victim.attackers) { if(isDefined(player) && player == self) { found = true; break; } } } return found; } getTurned(target) { if(self.pers["bot"]["skill"] > 1 && ((((target AdsButtonPressed() && isSubStr(target getCurrentWeapon(), "akimbo") == true) || (target AttackButtonPressed())) && ((isSubStr(target getCurrentWeapon(), "silencer") == false && self.pers["bot"]["skill"] < 3) || self.pers["bot"]["skill"] > 2)) || self AttackedMe(target) || self AttackedHim(target))) { wait ( 0.1 * self.pers["bot"]["acc"] ); return true; } else { return false; } } isRadarShooting(target) { if(((target AdsButtonPressed() && isSubStr(target getCurrentWeapon(), "akimbo") == true) || (target AttackButtonPressed())) && (isSubStr(target getCurrentWeapon(), "silencer") == false) && (!bots\includes::hasPerkk(target, "specialty_localjammer"))) { if(level.teamBased) { if(level.activeCounterUAVs[level.otherTeam[self.pers["team"]]] == 0) { return true; } else { return false; } } else { if(self notRadarBlocked()) { return true; } else { return false; } } } else { return false; } } hasUAV(target) { if(self.pers["bot"]["skill"] > 1 && !bots\includes::hasPerkk(target, "specialty_coldblooded")) { if(level.teamBased) { if(level.activeUAVs[self.pers["team"]] > 0 && level.activeCounterUAVs[level.otherTeam[self.pers["team"]]] == 0) { return true; } else { return false; } } else { if(level.activeUAVs[self.guid] > 0 && self notRadarBlocked()) { return true; } else { return false; } } } else { return false; } } notRadarBlocked() { self endon("bot_reset"); self endon("death"); self endon("disconnect"); self.CheckForCounterUAV = false; foreach(player in level.players) { if(!isdefined(player)) continue; if(player == self) continue; if(level.activeCounterUAVs[player.guid] > 0) self.CheckForCounterUAV = true; } if(self.CheckForCounterUAV == false) return true; else return false; } hasSound(target) { if(!bots\includes::hasPerkk(target, "specialty_quieter")) return true; return false; } isStunned() { if(isdefined(self.concussionEndTime) && self.concussionEndTime > gettime()) { return true; } else { return false; } } botPace() { self endon("bot_reset"); self endon("death"); self endon("disconnect"); boredofwalking = 0; for(;;) { if(self.sprintaniminprogress == true) { self.tiredfromsprint++; boredofwalking = 0; } else { if(self.walkaniminprogress == true) { boredofwalking++; if((self.pers["bot"]["skill"] == 4 && boredofwalking >= 3) || (self.pers["bot"]["skill"] == 3 && boredofwalking >= 4) || (self.pers["bot"]["skill"] < 3 && boredofwalking >= 5)) self.tiredfromsprint = 0; } } wait 2.5; } } botScan() { self endon("bot_reset"); self endon("death"); self endon("disconnect"); while(!bots\includes::_gameFlag( "prematch_done" )) // wait for match to start wait 1; for(;;) { if(isDefined(self.tempwp) && (self.type == "wait" || self.atObjectivePos == true) && !isDefined( self.aimat )) { angles = VectorToAngles( ( (self.tempwp-self.origin+(randomintrange(-100,100),randomintrange(-100,100),0))-(anglesToForward(self getplayerangles())) )); self notify("bot_set_player_angles"); self thread setPlayerAnglesReal(angles, 8); } wait randomintrange(2, 10); } } setStanceSpeed() { self endon("bot_reset"); self endon("death"); self endon("disconnect"); if((bots\includes::_isReallyAlive(self)) && (self.shooting == false) && (self.meleeaniminprogress == false) && (self.atObjectivePos == false) && (self.standingongoal == false) && (self.equipmentinprogress == false) && (self.using == false) && (self.usingksremote == false) && (isDefined( self.vObjectivePos )) && (self getCurrentWeapon() != "stinger_mp") && (self.DistractedByKillstreak == false) && (!self maps\mp\_flashgrenades::isFlashbanged()) && (!self isStunned()) && (!isDefined( self.lastStand )) && (level.gameEnded == false)) { switch(self.type) { case "stand": if(self.pers["bot"]["skill"] > 1 && ((self.tiredfromsprint < 3 && self.pers["bot"]["pickperk"]["mara"] == 0) || (self.tiredfromsprint < 4 && self.pers["bot"]["pickperk"]["mara"] > 0))) { self.fMoveSpeed = 9; // sprint speed if(self.walkaniminprogress == true || self.crouchaniminprogress == true || self.deathaniminprogress == true) self bots\includes::endBotAnim(); if(self.sprintaniminprogress == false) self bots\includes::doBotSprintAnim(); } else { if(self getCurrentWeapon() == "riotshield_mp") self.fMoveSpeed = 7; // riot shield speed else self.fMoveSpeed = 6; // walk speed if(self.sprintaniminprogress == true || self.crouchaniminprogress == true || self.deathaniminprogress == true) self bots\includes::endBotAnim(); if(self.walkaniminprogress == false) self bots\includes::doBotWalkAnim(); } break; case "crouch": self.fMoveSpeed = 4; // crouch walk speed if(self.sprintaniminprogress == true || self.walkaniminprogress == true || self.deathaniminprogress == true) self bots\includes::endBotAnim(); if(self.crouchaniminprogress == false) self bots\includes::doBotCrouchAnim(); break; case "wait": self.fMoveSpeed = 0; if(self.animinprogress == true) self bots\includes::endBotAnim(); break; } } else { self.fMoveSpeed = 0; if(self.animinprogress == true && self.meleeaniminprogress == false && self.deathaniminprogress == false) self bots\includes::endBotAnim(); } if(self.pers["bot"]["pickperk"]["speed"] > 0) self.fMoveSpeed = self.fMoveSpeed * 1.1; } tracking() { self endon("bot_reset"); self endon("death"); self endon("disconnect"); for(;;) { wait 4; // performance saving measure if( bots\includes::_isReallyAlive(self) && self.usingksremote == false ) { foreach(player in level.players) { if(player == self) continue; if(!bots\includes::_isReallyAlive(player)) { if( isDefined(self.tracking) && self.tracking == player ) { self.tracking = undefined; } continue; } if(level.teamBased && self.pers["team"] == player.pers["team"]) continue; if( !isdefined(self.tracking) && self.vObjectivePos == level.waypoints[self.e].origin && self.pers["bot"]["CamperRate"] != 1 ) { if( self hasUAV(player) ) { self.tracking = player; // track from uav //self sayall("TRACK UAV"); // for bug testing } else if( (isRadarShooting(player)) && (distance(self.origin,player.origin) < (1000 + (self.pers["bot"]["skill"] * 200))) ) { self.tracking = player; // track from shooting on radar //self sayall("TRACK SHOOT"); } else if( (hasSound(player)) && (distance(self.origin,player.origin) < (400 + (self.pers["bot"]["skill"] * 100))) ) { self.tracking = player; // track from ambient sounds //self sayall("TRACK SOUND"); } } } } } } footsteps() { self endon("bot_reset"); self endon("death"); self endon("disconnect"); for(;;) { if(self.animinprogress == true) { origin = self getOrigin(); trace = bullettrace( origin, origin + (0.0, 0.0, -5.0), false, self ); switch( self.type ) { case "stand": if(self.sprintaniminprogress == true) self playSound( "step_sprint_" + trace[ "surfacetype" ] ); else { self playSound( "step_run_" + trace[ "surfacetype" ] ); wait 0.15; } break; case "crouch": self playSound( "step_walk_" + trace[ "surfacetype" ] ); wait 0.15; break; } } wait 0.25; } } aiming() { self endon("bot_reset"); self endon("disconnect"); for(;;) { wait 0.5; // performance saving measure aimat = undefined; if( bots\includes::_isReallyAlive(self) || self.usingksremote == true ) { foreach(player in level.players) { if(player == self) continue; if(!bots\includes::_isReallyAlive(player)) continue; if(level.teamBased && self.pers["team"] == player.pers["team"]) continue; if( Distance(self.origin, player.origin) > self.pers["bot"]["range"] && self.usingksremote == false ) { continue; } if(!SmokeTrace(self getEye(), player.origin) && Distance(self geteye(), player.origin) > 125) { continue; } if( !bulletTracePassed( self getEye(), player getTagOrigin( "j_ankle_le" ), false, self ) && !bulletTracePassed( self getEye(), player getTagOrigin( "j_ankle_ri" ), false, self ) && !bulletTracePassed( self getEye(), player getTagOrigin( "j_head" ), false, self ) ) { continue; } if( !self IsFacingAtTarget(player) && !self getTurned(player) ) continue; if( isDefined(aimat) ) { if( closer( self getEye(), player getTagOrigin( "j_mainroot" ), aimat getTagOrigin( "j_mainroot" ) ) && self.DistractedByKillstreak == false ) { aimat = player; } } else { if( self.DistractedByKillstreak == false ) { aimat = player; if( !isDefined(self.aimat) ) { self.aimat = aimat; if(level.teamBased) self thread bots\talk::doMessage(); } } } } if( !isDefined(aimat) ) self.aimat = undefined; else self.aimat = aimat; } } } playerAim() { self endon("bot_reset"); self endon("disconnect"); while(!bots\includes::_gameFlag( "prematch_done" )) // wait for match to start wait 0.2; wait ( 0.2 * randomint(10) ); for(;;) { wait 0.1; if(getdvar("scr_game_hardpoints") == "1") { if(self.pers["bot"]["ks"] < self.pers["cur_kill_streak"]) { self.pers["bot"]["ks"]++; self thread giveKillstreak(); } else { if(self.pers["bot"]["ks"] > self.pers["cur_kill_streak"]) self.pers["bot"]["ks"]--; } } if( (bots\includes::_isReallyAlive(self) && self.using == false && self.DistractedByKillstreak == false) || self.usingksremote == true ) { if(isDefined( self.aimat )) { aimatdis = Distance(self.origin, self.aimat.origin); if(self.usingksremote == false) { if(self maps\mp\_flashgrenades::isFlashbanged() || self isStunned()) { self thread setStanceSpeed(); wait ( 0.1 * ( 6 - self.pers["bot"]["skill"] ) ); continue; } if((aimatdis < 400) && (self.type != "wait") && (self.atObjectivePos == false) && (self.usingksremote == false) && (self.UsedKnife == false) && ((self.shooting == false && self.pers["bot"]["MeleeKamikazeRate"] == 1 && self.didMeleeKamikaze == false && self.aimat getCurrentWeapon() != "riotshield_mp") || (self getCurrentWeapon() == "riotshield_mp"))) { if(self.doingMeleeKamikaze == false) { self.doingMeleeKamikaze = true; if(self getCurrentWeapon() != "riotshield_mp") { self thread bots\talk::BotTalkKamikaze(); self thread CheckKamikaze(self.aimat); } } self.vObjectivePos = self.aimat.origin; } else self.doingMeleeKamikaze = false; if(self.nadesinprogress == false && self.equipmentinprogress == false && aimatdis > 400 && self.using == false && self.doingMeleeKamikaze == false) self thread nades(); if( (((aimatdis < (75 + randomint(25))) && (self.pers["bot"]["pickperk"]["melee"] == 0)) || ((aimatdis < (100 + randomint(25)) && (self.pers["bot"]["pickperk"]["melee"] > 0)))) && (self.meleeinprogress == false) && (self.UsedKnife == false) && (self.using == false) && (((self getCurrentWeapon() != "riotshield_mp") && (self.aimat getCurrentWeapon() != "riotshield_mp")) || (self getCurrentWeapon() == "riotshield_mp")) ) { angles = VectorToAngles( ( self.aimat gettagorigin("j_spineupper") ) - ( self gettagorigin("j_spineupper") ) ); self notify("bot_set_player_angles"); self setplayerangles(angles); self thread botmelee(); } else { if(self.doingMeleeKamikaze == false) self notify( "BotMovementComplete" ); } if((self getCurrentWeapon() == "m79_mp") || (isSubStr(self getCurrentWeapon(), "gl_") && !isSubStr(self getCurrentWeapon(), "_gl"))) { dist = (aimatdis*(aimatdis/400))/40; angles = VectorToAngles( ( self.aimat getTagOrigin( "j_knee_ri" ) ) - ( self getEye() ) + (0,0,dist) ); } else { if((self getCurrentWeapon() == "frag_grenade_mp") || (self getCurrentWeapon() == "semtex_mp") || (self getCurrentWeapon() == "flash_grenade_mp") || (self getCurrentWeapon() == "concussion_grenade_mp") || (self.throwingknife == true)) { if(self.throwingknife == true) dist = (aimatdis*(aimatdis/300))/25; else dist = (aimatdis*(aimatdis/200))/15; angles = VectorToAngles( ( self.aimat getTagOrigin( "j_spineupper" ) ) - ( self getEye() ) + (0,0,dist) ); } else angles = VectorToAngles( ( self.aimat gettagorigin("j_spineupper") ) - ( self getEye() ) ); } } else angles = VectorToAngles( ( self.aimat gettagorigin("j_spineupper") ) - ( self getEye() ) ); self notify("bot_set_player_angles"); self thread setPlayerAnglesReal(angles, (4 + self.pers["bot"]["acc"])); if(((self.shooting == false) && (aimatdis <= self.pers["bot"]["range"]) && (self.meleeinprogress == false) && (self.doingMeleeKamikaze == false) && (ClampToGroundtest()) && (self getCurrentWeapon() != "riotshield_mp")) || (self.usingksremote == true)) { self thread ShootWeapon(); } else { self thread setStanceSpeed(); } } else { if(self.shooting == true) { self thread StopShooting(); } self thread setStanceSpeed(); self.doingMeleeKamikaze = false; if((self.type != "wait") && (self.shooting == false) && (self.atObjectivePos == false) && (self.botgoalreach == false)) { angles = VectorToAngles( ( (self.tempwp-self.origin)-(anglesToForward(self getplayerangles())) )); self notify("bot_set_player_angles"); self thread setPlayerAnglesReal(angles, 8); } } } } } vehicleAim() { self endon("bot_reset"); self endon("disconnect"); while(!bots\includes::_gameFlag( "prematch_done" )) // wait for match to start wait 1; for(;;) { wait 0.2; if(self.using == false && self.usingksremote == false) { if(level.ac130InUse && isDefined(level.ac130player) && level.ac130player == self && self bots\includes::_isUsingRemote()) self thread ac130(); if(isDefined( level.chopper ) && level.chopper.heliType == "minigun" && isDefined(level.chopper.owner) && level.chopper.owner == self && self bots\includes::_isUsingRemote()) self thread chopper(); if( bots\includes::_isReallyAlive(self) ) { if(level.teambased) { if((isDefined( level.chopper )) && (level.chopper.team != self.team) && (self GetStance() == "stand") && (self.AttemptedVehicleKill == false) && ((distance(level.chopper.origin, self.origin) < 5000) || (self.pers["bot"]["skill"] > 2)) && (((self.pers["bot"]["DislikeVehicles"] == 1) && (self.pers["bot"]["skill"] < 3)) || ((self.pers["bot"]["HateVehicles"] == 1) && (self.pers["bot"]["skill"] > 2)) || (self.pers["cur_death_streak"] > 3)) && (bulletTracePassed( self getEye() + (0, 0, 50), level.chopper.origin, false, level.chopper))) { self.doingMeleeKamikaze = false; angles = VectorToAngles( ( (level.chopper.origin-self.origin)-(anglesToForward(self getplayerangles())) )); self notify("bot_set_player_angles"); self thread setPlayerAnglesReal(angles, (4 + self.pers["bot"]["acc"])); if(self.DistractedByKillstreak == false && self.AttemptedVehicleKill == false) { self.DistractedByKillstreak = true; self thread VehicleMustDie(); } } else if( isDefined( level.harriers ) && level.harriers.size > 0 ) { foreach( harrier in level.harriers ) { if((isDefined( harrier )) && (harrier.team != self.team) && (self GetStance() == "stand") && (self.AttemptedVehicleKill == false) && ((distance(harrier.origin, self.origin) < 6000) || (self.pers["bot"]["skill"] > 2)) && (((self.pers["bot"]["DislikeVehicles"] == 1) && (self.pers["bot"]["skill"] < 3)) || ((self.pers["bot"]["HateVehicles"] == 1) && (self.pers["bot"]["skill"] > 2)) || (self.pers["cur_death_streak"] > 3)) && (bulletTracePassed( self getEye() + (0, 0, 50), harrier.origin, false, harrier))) { self.doingMeleeKamikaze = false; angles = VectorToAngles( ( (harrier.origin-self.origin)-(anglesToForward(self getplayerangles())) )); self notify("bot_set_player_angles"); self thread setPlayerAnglesReal(angles, (4 + self.pers["bot"]["acc"])); if(self.DistractedByKillstreak == false && self.AttemptedVehicleKill == false) { self.DistractedByKillstreak = true; self thread VehicleMustDie(); } } } } else if((isDefined( level.ac130player )) && (level.ac130player.team != self.team) && (self GetStance() == "stand") && (self.AttemptedVehicleKill == false) && (((self.pers["bot"]["HateVehicles"] == 1) && (self.pers["bot"]["skill"] > 2)) || (self.pers["cur_death_streak"] > 3)) && (bulletTracePassed( self getEye() + (0, 0, 50), level.ac130.planemodel.origin, false, level.ac130.planemodel))) { self.DistractedByKillstreak = true; self.doingMeleeKamikaze = false; angles = VectorToAngles( ( (level.ac130.planemodel.origin-self.origin)-(anglesToForward(self getplayerangles())) )); self notify("bot_set_player_angles"); self thread setPlayerAnglesReal(angles, (4 + self.pers["bot"]["acc"])); self.newweap = "stinger_mp"; self notify("weapchange"); self thread setStanceSpeed(); wait 5; if(self getCurrentWeapon() == "stinger_mp") { if(bulletTracePassed( self getEye() + (0, 0, 50), level.ac130.planemodel.origin, false, level.ac130.planemodel)) { rocket = MagicBullet( "stinger_mp", self getEye() + (0, 0, 50), level.ac130.planemodel.origin, self ); rocket Missile_SetTargetEnt( level.ac130.planemodel ); wait 0.1; level notify( "stinger_fired", self, rocket, level.ac130.planemodel ); wait 1; } self endweapon(); } self thread StopShooting(); self.AttemptedVehicleKill = true; self.DistractedByKillstreak = false; } else if( isDefined( level.UAVModels[level.otherTeam[self.team]].size ) && level.UAVModels[level.otherTeam[self.team]].size > 0 ) { foreach ( UAV in level.UAVModels[level.otherTeam[self.team]] ) { if((isDefined( UAV )) && (self GetStance() == "stand") && (self.AttemptedVehicleKill == false) && (self.pers["bot"]["HateSmallVehicles"] == 1) && (self.pers["bot"]["skill"] > 2) && (bulletTracePassed( self getEye() + (0, 0, 50), UAV.origin, false, UAV))) { self.DistractedByKillstreak = true; self.doingMeleeKamikaze = false; angles = VectorToAngles( ( (UAV.origin-self.origin)-(anglesToForward(self getplayerangles())) )); self notify("bot_set_player_angles"); self thread setPlayerAnglesReal(angles, (4 + self.pers["bot"]["acc"])); self.newweap = "stinger_mp"; self notify("weapchange"); self thread setStanceSpeed(); wait 5; if(self getCurrentWeapon() == "stinger_mp") { if(bulletTracePassed( self getEye() + (0, 0, 50), UAV.origin, false, UAV)) { rocket = MagicBullet( "stinger_mp", self getEye() + (0, 0, 50), UAV.origin, self ); rocket Missile_SetTargetEnt( UAV ); wait 0.1; level notify( "stinger_fired", self, rocket, UAV ); wait 1; } self endweapon(); } self thread StopShooting(); self.AttemptedVehicleKill = true; self.DistractedByKillstreak = false; } } } else if(self.DistractedByKillstreak == true && self.pers["bot"]["skill"] < 3) { self notify("bot_end_vehicle_kill"); self endweapon(); self thread StopShooting(); self.AttemptedVehicleKill = true; self.DistractedByKillstreak = false; } } else { if((isDefined( level.chopper )) && (level.chopper.owner != self) && (self GetStance() == "stand") && (self.AttemptedVehicleKill == false) && ((distance(level.chopper.origin, self.origin) < 5000) || (self.pers["bot"]["skill"] > 2)) && (((self.pers["bot"]["DislikeVehicles"] == 1) && (self.pers["bot"]["skill"] < 3)) || ((self.pers["bot"]["HateVehicles"] == 1) && (self.pers["bot"]["skill"] > 2)) || (self.pers["cur_death_streak"] > 3)) && (bulletTracePassed( self getEye() + (0, 0, 50), level.chopper.origin, false, level.chopper))) { self.doingMeleeKamikaze = false; angles = VectorToAngles( ( (level.chopper.origin-self.origin)-(anglesToForward(self getplayerangles())) )); self notify("bot_set_player_angles"); self thread setPlayerAnglesReal(angles, (4 + self.pers["bot"]["acc"])); if(self.DistractedByKillstreak == false && self.AttemptedVehicleKill == false) { self.DistractedByKillstreak = true; self thread VehicleMustDie(); } } else if( isDefined( level.harriers ) && level.harriers.size > 0 ) { foreach( harrier in level.harriers ) { if((isDefined( harrier )) && (harrier.owner != self) && (self GetStance() == "stand") && (self.AttemptedVehicleKill == false) && ((distance(harrier.origin, self.origin) < 6000) || (self.pers["bot"]["skill"] > 2)) && (((self.pers["bot"]["DislikeVehicles"] == 1) && (self.pers["bot"]["skill"] < 3)) || ((self.pers["bot"]["HateVehicles"] == 1) && (self.pers["bot"]["skill"] > 2)) || (self.pers["cur_death_streak"] > 3)) && (bulletTracePassed( self getEye() + (0, 0, 50), harrier.origin, false, harrier))) { self.doingMeleeKamikaze = false; angles = VectorToAngles( ( (harrier.origin-self.origin)-(anglesToForward(self getplayerangles())) )); self notify("bot_set_player_angles"); self thread setPlayerAnglesReal(angles, (4 + self.pers["bot"]["acc"])); if(self.DistractedByKillstreak == false && self.AttemptedVehicleKill == false) { self.DistractedByKillstreak = true; self thread VehicleMustDie(); } } } } else if((isDefined( level.ac130player )) && (self GetStance() == "stand") && (self.AttemptedVehicleKill == false) && (((self.pers["bot"]["HateVehicles"] == 1) && (self.pers["bot"]["skill"] > 2)) || (self.pers["cur_death_streak"] > 3)) && (bulletTracePassed( self getEye() + (0, 0, 50), level.ac130.planemodel.origin, false, level.ac130.planemodel))) { self.DistractedByKillstreak = true; self.doingMeleeKamikaze = false; angles = VectorToAngles( ( (level.ac130.planemodel.origin-self.origin)-(anglesToForward(self getplayerangles())) )); self notify("bot_set_player_angles"); self thread setPlayerAnglesReal(angles, (4 + self.pers["bot"]["acc"])); self.newweap = "stinger_mp"; self notify("weapchange"); self thread setStanceSpeed(); wait 5; if(self getCurrentWeapon() == "stinger_mp") { if(bulletTracePassed( self getEye() + (0, 0, 50), level.ac130.planemodel.origin, false, level.ac130.planemodel)) { rocket = MagicBullet( "stinger_mp", self getEye() + (0, 0, 50), level.ac130.planemodel.origin, self ); rocket Missile_SetTargetEnt( level.ac130.planemodel ); wait 0.1; level notify( "stinger_fired", self, rocket, level.ac130.planemodel ); wait 1; } self endweapon(); } self thread StopShooting(); self.AttemptedVehicleKill = true; self.DistractedByKillstreak = false; } else if( isDefined( level.UAVModels.size ) && level.UAVModels.size > 0 ) { foreach( ownerGuid, UAV in level.UAVModels ) { if( isDefined( UAV.owner ) && UAV.owner == self ) continue; if((isDefined( UAV )) && (self GetStance() == "stand") && (self.AttemptedVehicleKill == false) && (self.pers["bot"]["HateSmallVehicles"] == 1) && (self.pers["bot"]["skill"] > 2) && (bulletTracePassed( self getEye() + (0, 0, 50), UAV.origin, false, UAV))) { self.DistractedByKillstreak = true; self.doingMeleeKamikaze = false; angles = VectorToAngles( ( (UAV.origin-self.origin)-(anglesToForward(self getplayerangles())) )); self notify("bot_set_player_angles"); self thread setPlayerAnglesReal(angles, (4 + self.pers["bot"]["acc"])); self.newweap = "stinger_mp"; self notify("weapchange"); self thread setStanceSpeed(); wait 5; if(self getCurrentWeapon() == "stinger_mp") { if(bulletTracePassed( self getEye() + (0, 0, 50), UAV.origin, false, UAV)) { rocket = MagicBullet( "stinger_mp", self getEye() + (0, 0, 50), UAV.origin, self ); rocket Missile_SetTargetEnt( UAV ); wait 0.1; level notify( "stinger_fired", self, rocket, UAV ); wait 1; } self endweapon(); } self thread StopShooting(); self.AttemptedVehicleKill = true; self.DistractedByKillstreak = false; } } } else if(self.DistractedByKillstreak == true && self.pers["bot"]["skill"] < 3) { self notify("bot_end_vehicle_kill"); self endweapon(); self thread StopShooting(); self.AttemptedVehicleKill = true; self.DistractedByKillstreak = false; } } } } } } setPlayerAnglesReal(Angle,Steps) { self endon("bot_reset"); self endon("death"); self endon("disconnect"); self endon("bot_set_player_angles"); myAngle=self getPlayerAngles(); X=(Angle[0]-myAngle[0]); while(X > 170.0) X=X-360.0; while(X < -170.0) X=X+360.0; X=X/Steps; Y=(Angle[1]-myAngle[1]); while(Y > 180.0) Y=Y-360.0; while(Y < -180.0) Y=Y+360.0; Y=Y/Steps; for(i=0;i distance1) // if you are getting further away from your target { self.didMeleeKamikaze = true; self.doingMeleeKamikaze = false; } } } VehicleMustDie() { self endon("bot_reset"); self endon("death"); self endon("disconnect"); self endon("bot_end_vehicle_kill"); wait 0.2; self thread bots\talk::BotTalkAntiAir(); if(self.pers["bot"]["skill"] > 2) { self.newweap = "stinger_mp"; self notify("weapchange"); self thread setStanceSpeed(); self doStingerKill(); wait 1; } else { if(self.pers["bot"]["skill"] == 2) { self.newweap = "rpg_mp"; self notify("weapchange"); self thread ShootWeapon(); wait ( 3 + ( 0.5 * randomint(3) ) ); } else { self.newweap = "at4_mp"; self notify("weapchange"); self thread ShootWeapon(); wait ( 2 + ( 0.5 * randomint(3) ) ); } } self StopShooting(); self endweapon(); self.AttemptedVehicleKill = true; self.DistractedByKillstreak = false; } doStingerKill() { self endon("bot_reset"); self endon("death"); self endon("disconnect"); if(isDefined( level.chopper )) { if(bulletTracePassed( self getEye() + (0, 0, 50), level.chopper.origin, false, level.chopper ) ) { wait 5; if(self getCurrentWeapon() == "stinger_mp") { if(bulletTracePassed( self getEye() + (0, 0, 50), level.chopper.origin, false, level.chopper )) { rocket = MagicBullet( "stinger_mp", self getEye() + (0, 0, 50), level.chopper.origin, self ); rocket Missile_SetTargetEnt( level.chopper ); wait 0.1; level notify( "stinger_fired", self, rocket, level.chopper ); } } } } else { if( isDefined( level.harriers ) ) { foreach( harrier in level.harriers ) { if(isDefined( harrier )) { if(bulletTracePassed( self getEye() + (0, 0, 50), harrier.origin, false, harrier ) ) { wait 5; if(self getCurrentWeapon() == "stinger_mp") { if(bulletTracePassed( self getEye() + (0, 0, 50), harrier.origin, false, harrier )) { rocket = MagicBullet( "stinger_mp", self getEye() + (0, 0, 50), harrier.origin, self ); rocket Missile_SetTargetEnt( harrier ); wait 0.1; level notify( "stinger_fired", self, rocket, harrier ); } } } } } } } } botmelee() { self endon("bot_reset"); self endon("death"); self endon("disconnect"); self.meleeinprogress = true; self.fmoveSpeed = 0; self.atObjectivePos = true; if(self.animinprogress == true) self bots\includes::endBotAnim(); if(self.shooting == true) self thread StopShooting(); wait ( 0.1 * ( 5 - self.pers["bot"]["skill"] ) ); if( (bots\includes::_isReallyAlive(self)) && (bots\includes::_isReallyAlive(self.aimat)) && ((self.pers["bot"]["pickperk"]["melee"] == 0 && Distance(self.origin, self.aimat.origin) < 100) || (self.pers["bot"]["pickperk"]["melee"] > 0 && Distance(self.origin, self.aimat.origin) < 125)) ) { self SetOrigin( (self.origin + self.aimat.origin) / 2 ); // knife lunge if(self getCurrentWeapon() == "riotshield_mp") self.aimat thread [[level.callbackPlayerDamage]] ( self, self, 75, 8, "MOD_MELEE", self getCurrentWeapon(), (0,0,0), (0,0,0), "torso_lower", 0 ); else { self bots\includes::doBotMeleeKillAnim(); self playsound("melee_knife_stab"); self.aimat thread [[level.callbackPlayerDamage]] ( self, self, 150, 8, "MOD_MELEE", self getCurrentWeapon(), (0,0,0), (0,0,0), "torso_lower", 0 ); } } else { if(self getCurrentWeapon() != "riotshield_mp") { self.UsedKnife = true; self bots\includes::doBotMeleeMissAnim(); } } wait 1; if(self.animinprogress == true) self bots\includes::endBotAnim(); self.atObjectivePos = false; self.meleeinprogress = false; self.didMeleeKamikaze = true; self.doingMeleeKamikaze = false; self notify( "BotMovementComplete" ); } turretmelee(turret) { self endon("bot_reset"); self endon("death"); self endon("disconnect"); self.meleeinprogress = true; self.fmoveSpeed = 0; self.atObjectivePos = true; if(self.animinprogress == true) self bots\includes::endBotAnim(); if(self.shooting == true) self thread StopShooting(); wait ( 0.1 * ( 5 - self.pers["bot"]["skill"] ) ); self SetOrigin( (self.origin + self.turret.origin) / 2 ); // knife lunge if(self getCurrentWeapon() != "riotshield_mp") { self bots\includes::doBotMeleeKillAnim(); self playsound("melee_knife_stab"); } turret notify( "damage", 103, self, self.angles, self.origin, "MOD_MELEE" ); wait 1; if(self.animinprogress == true) self bots\includes::endBotAnim(); self.atObjectivePos = false; self.meleeinprogress = false; self notify( "BotMovementComplete" ); } equipment() { self endon("bot_reset"); self endon("death"); self endon("disconnect"); self endon("bot_placed_equipment"); while(!bots\includes::_gameFlag( "prematch_done" )) // wait for match to start wait 1; for(;;) { equip = randomint(45); if((equip == 15 || equip == 20) && self.shooting == false && self.equipmentinprogress == false && self.nadesinprogress == false && self.using == false && self.pers["bot"]["pickperk"]["clay"] == 1 && self.placedclaymore == false) { self.equipmentinprogress = true; self freezecontrols(false); self.newweap = "claymore_mp"; self notify("weapchange"); self waittill( "grenade_fire" ); wait 0.3; self endweapon(); if(self.shooting == false) self freezecontrols(true); wait 1; self.equipmentinprogress = false; self.placedclaymore = true; } if(equip == 30 && self.shooting == false && self.equipmentinprogress == false && self.nadesinprogress == false && self.using == false && level.gametype != "sd" && self.pers["bot"]["pickperk"]["insert"] == 1 && self.placedflare == false) { self.equipmentinprogress = true; self freezecontrols(false); self.newweap = "flare_mp"; self notify("weapchange"); self waittill( "grenade_fire" ); wait 0.3; self endweapon(); if(self.shooting == false) self freezecontrols(true); wait 1; self.equipmentinprogress = false; self.placedflare = true; } if(((self.placedclaymore == true) || (self.pers["bot"]["pickperk"]["clay"] == 0)) && ((self.placedflare == true) || (self.pers["bot"]["pickperk"]["insert"] == 0) || (level.gametype == "sd"))) self notify("bot_placed_equipment"); wait 2; } } nades() { self endon("bot_reset"); self endon("death"); self endon("disconnect"); nade = randomint(20); if(nade == 0 && self.ThrewEquipment == false) { self.nadesinprogress = true; self freezecontrols(false); switch(randomint(3)) { case 0: if(self.pers["bot"]["pickperk"]["frag"] == 1) { self.newweap = "frag_grenade_mp"; self notify("weapchange"); self waittill( "grenade_fire" ); wait 0.3; self endweapon(); self.ThrewEquipment = true; } break; case 1: if(self.pers["bot"]["pickperk"]["semtex"] == 1) { self.newweap = "semtex_mp"; self notify("weapchange"); self waittill( "grenade_fire" ); wait 0.3; self endweapon(); self.ThrewEquipment = true; } break; case 2: if(self.pers["bot"]["pickperk"]["knife"] == 1) { self.throwingknife = true; wait 0.6; self.newweap = "throwingknife_mp"; self notify("weapchange"); self waittill( "grenade_fire" ); wait 0.3; self endweapon(); self.throwingknife = false; self.ThrewEquipment = true; } break; } } if(nade == 4 && self.ThrewSpecGrenade < 2) { self.nadesinprogress = true; self freezecontrols(false); switch(randomint(6)) { case 0: if(self.pers["bot"]["pickperk"]["stun"] == 1) { self.newweap = "concussion_grenade_mp"; self notify("weapchange"); self waittill( "grenade_fire" ); wait 0.3; self endweapon(); self.ThrewSpecGrenade++; } break; case 1: if(self.pers["bot"]["pickperk"]["flash"] == 1) { self.newweap = "flash_grenade_mp"; self notify("weapchange"); self waittill( "grenade_fire" ); wait 0.3; self endweapon(); self.ThrewSpecGrenade++; } break; case 2: if(self.pers["bot"]["pickperk"]["smoke"] == 1) { self.newweap = "smoke_grenade_mp"; self notify("weapchange"); self waittill( "grenade_fire" ); wait 0.3; self endweapon(); self.ThrewSpecGrenade = 2; } break; } } if((nade == 8) && (isSubStr(self getCurrentWeapon(), "shotgun_") || isSubStr(self getCurrentWeapon(), "_gl"))) { self.nadesinprogress = true; if(isSubStr(self getCurrentWeapon(), "_gl")) { self.newweap = self bots\includes::_getWeaponGL(); self notify("weapchange"); wait 2 + randomint(3); self endweapon(); } if(isSubStr(self getCurrentWeapon(), "shotgun_") && Distance(self.origin, self.aimat.origin) < 600) { self.newweap = self bots\includes::_getWeaponSL(); self notify("weapchange"); wait 2 + randomint(3); self endweapon(); } } if(nade == 12 && self.pers["bot"]["Rocketeer"] != "none") { self.nadesinprogress = true; if(self.pers["bot"]["Rocketeer"] == "rpg") { self.newweap = "rpg_mp"; self notify("weapchange"); wait 2.5 + randomint(2); self endweapon(); } else { if(self.pers["bot"]["Rocketeer"] == "at4") { self.newweap = "at4_mp"; self notify("weapchange"); wait 2.5 + randomint(2); self endweapon(); } else { self.newweap = "m79_mp"; self notify("weapchange"); wait 2.5 + randomint(2); self endweapon(); } } } self.nadesinprogress = false; if(self.shooting == false) self freezecontrols(true); } weaponswitch() { self endon("bot_reset"); self endon("death"); self endon("disconnect"); for(;;) { self waittill("weapchange"); self.pers["weapon"] = self.newweap; self giveweapon(self.pers["weapon"]); self setspawnweapon(self.pers["weapon"]); self switchtoweapon(self.pers["weapon"]); wait 0.1; } } endweapon() { self.newweap = self.oldweap; self notify("weapchange"); } useKillstreak() { self endon("bot_reset"); self endon("death"); self endon("disconnect"); level endon("game_ended"); wait 1 + randomint(4); if(bots\includes::_isReallyAlive(self) && self.shooting == false && self.nadesinprogress == false && self.equipmentinprogress == false && self.using == false && self.doingMeleeKamikaze == false) { switch(self.pers["killstreaks"][0].streakName) { case "uav": case "counter_uav": case "helicopter": case "helicopter_flares": case "emp": case "nuke": if((level.teamBased && level.teamEMPed[self.team]) || (!level.teamBased && isDefined( level.empPlayer ) && level.empPlayer != self) || (self getCurrentWeapon() == "killstreak_predator_missile_mp") || (isDefined( level.chopper ) && level.chopper.heliType == "minigun" && isDefined(level.chopper.owner) && level.chopper.owner == self && self bots\includes::_isUsingRemote()) || (level.ac130InUse && isDefined(level.ac130player) && level.ac130player == self && self bots\includes::_isUsingRemote()) ) { wait 0.1; } else { self maps\mp\killstreaks\_killstreaks::killstreakUsePressed(); } break; case "predator_missile": if((level.teamBased && level.teamEMPed[self.team]) || (!level.teamBased && isDefined( level.empPlayer ) && level.empPlayer != self) || (self getCurrentWeapon() == "killstreak_predator_missile_mp") || (isDefined( level.chopper ) && level.chopper.heliType == "minigun" && isDefined(level.chopper.owner) && level.chopper.owner == self && self bots\includes::_isUsingRemote()) || (level.ac130InUse && isDefined(level.ac130player) && level.ac130player == self && self bots\includes::_isUsingRemote())) { wait 0.1; } else { target = undefined; targets = []; foreach(player in level.players) { if(!isDefined(player)) continue; if(player == self) continue; if(!bots\includes::_isReallyAlive(player)) continue; if(level.teamBased && self.pers["team"] == player.pers["team"]) continue; if(Distance(self.origin, player.origin) > 800 && bulletTracePassed(player getTagOrigin( "j_head" ), player getTagOrigin( "j_head" )+(0,0,255), false, player)) targets[targets.size] = player; wait 0.1; } if(targets.size > 0) target = targets[randomint(targets.size)]; if( isDefined( target ) && self.using == false ) { self maps\mp\killstreaks\_killstreaks::shuffleKillStreaksFILO( "predator_missile" ); self thread predator(target); } } break; case "harrier_airstrike": case "precision_airstrike": case "stealth_airstrike": if((level.harriers.size > 2 && self.pers["killstreaks"][0].streakName == "harrier_airstrike") ||(level.teamBased && level.teamEMPed[self.team]) || (!level.teamBased && isDefined( level.empPlayer ) && level.empPlayer != self) || (self getCurrentWeapon() == "killstreak_predator_missile_mp") || (isDefined( level.chopper ) && level.chopper.heliType == "minigun" && isDefined(level.chopper.owner) && level.chopper.owner == self && self bots\includes::_isUsingRemote()) || (level.ac130InUse && isDefined(level.ac130player) && level.ac130player == self && self bots\includes::_isUsingRemote()) ) { wait 0.1; } else { target = undefined; targets = []; foreach(player in level.players) { if(!isDefined(player)) continue; if(player == self) continue; if(!bots\includes::_isReallyAlive(player)) continue; if(level.teamBased && self.pers["team"] == player.pers["team"]) continue; if(bots\includes::hasPerkk(player, "specialty_coldblooded")) continue; if(Distance(self.origin, player.origin) > 800 && bulletTracePassed(player getTagOrigin( "j_head" ), player getTagOrigin( "j_head" )+(0,0,255), false, player)) targets[targets.size] = player; wait 0.1; } if(targets.size > 0) target = targets[randomint(targets.size)]; if( isDefined( target ) ) { self thread maps\mp\killstreaks\_killstreaks::killstreakUsePressed(); wait 0.5; self notify( "confirm_location", target.origin, randomint(360) ); } } break; case "airdrop": if((level.teamBased && level.teamEMPed[self.team]) || (!level.teamBased && isDefined( level.empPlayer ) && level.empPlayer != self) || (self getCurrentWeapon() == "killstreak_predator_missile_mp") || (isDefined( level.chopper ) && level.chopper.heliType == "minigun" && isDefined(level.chopper.owner) && level.chopper.owner == self && self bots\includes::_isUsingRemote()) || (level.ac130InUse && isDefined(level.ac130player) && level.ac130player == self && self bots\includes::_isUsingRemote()) ) { wait 0.1; } else { if( level.littleBirds < 3 && bulletTracePassed(self getTagOrigin( "j_head" ), self getTagOrigin( "j_head" )+(0,0,255), false, self) ) { self thread airdrop(); } } break; case "airdrop_sentry_minigun": if((level.teamBased && level.teamEMPed[self.team]) || (!level.teamBased && isDefined( level.empPlayer ) && level.empPlayer != self) || (self getCurrentWeapon() == "killstreak_predator_missile_mp") || (isDefined( level.chopper ) && level.chopper.heliType == "minigun" && isDefined(level.chopper.owner) && level.chopper.owner == self && self bots\includes::_isUsingRemote()) || (level.ac130InUse && isDefined(level.ac130player) && level.ac130player == self && self bots\includes::_isUsingRemote()) ) { wait 0.1; } else { if( level.littleBirds < 3 && bulletTracePassed(self getTagOrigin( "j_head" ), self getTagOrigin( "j_head" )+(0,0,255), false, self) ) { self thread airdrop_sentry_minigun(); } } break; case "sentry": if((level.teamBased && level.teamEMPed[self.team]) || (!level.teamBased && isDefined( level.empPlayer ) && level.empPlayer != self) || (self getCurrentWeapon() == "killstreak_predator_missile_mp") || (isDefined( level.chopper ) && level.chopper.heliType == "minigun" && isDefined(level.chopper.owner) && level.chopper.owner == self && self bots\includes::_isUsingRemote()) || (level.ac130InUse && isDefined(level.ac130player) && level.ac130player == self && self bots\includes::_isUsingRemote()) ) { wait 0.1; } else { self maps\mp\killstreaks\_killstreaks::shuffleKillStreaksFILO( "sentry" ); self thread sentry(); } break; case "airdrop_mega": if( bulletTracePassed(self getTagOrigin( "j_head" ), self getTagOrigin( "j_head" )+(0,0,255), false, self) ) self thread airdrop_mega(); // this works during an EMP? break; case "ac130": if ( (level.ac130InUse) || (level.teamBased && level.teamEMPed[self.team]) || (!level.teamBased && isDefined( level.empPlayer ) && level.empPlayer != self) || (self getCurrentWeapon() == "killstreak_predator_missile_mp") || (isDefined( level.chopper ) && level.chopper.heliType == "minigun" && isDefined(level.chopper.owner) && level.chopper.owner == self && self bots\includes::_isUsingRemote()) ) { wait 0.1; } else { // force bots to use ac130, client bug? self thread maps\mp\killstreaks\_ac130::tryUseAC130( 100 ); self maps\mp\killstreaks\_killstreaks::usedKillstreak( "ac130", 100 ); self maps\mp\killstreaks\_killstreaks::shuffleKillStreaksFILO( "ac130" ); self maps\mp\killstreaks\_killstreaks::giveOwnedKillstreakItem(); } break; case "helicopter_minigun": if((isDefined( level.chopper )) || (level.teamBased && level.teamEMPed[self.team]) || (!level.teamBased && isDefined( level.empPlayer ) && level.empPlayer != self) || (self getCurrentWeapon() == "killstreak_predator_missile_mp") || (level.ac130InUse && isDefined(level.ac130player) && level.ac130player == self && self bots\includes::_isUsingRemote())) { wait 0.1; } else { // force bots to use chopper gunner, client bug? self thread maps\mp\killstreaks\_helicopter::tryUseHelicopter( 100, "minigun" ); self maps\mp\killstreaks\_killstreaks::usedKillstreak( "helicopter_minigun", 100 ); self maps\mp\killstreaks\_killstreaks::shuffleKillStreaksFILO( "helicopter_minigun" ); self maps\mp\killstreaks\_killstreaks::giveOwnedKillstreakItem(); } break; } } } predator(target) { self endon("bot_reset"); self endon("death"); self endon("disconnect"); self.atObjectivePos = true; self.fMoveSpeed = 0; if(self.animinprogress == true) self bots\includes::endBotAnim(); self.using = true; self.newweap = "killstreak_predator_missile_mp"; self notify("weapchange"); wait 1; rocket = MagicBullet( "remotemissile_projectile_mp", self.origin + (0,0,7000 - (self.pers["bot"]["skill"] * 400)), target.origin, self ); rocket thread maps\mp\gametypes\_weapons::AddMissileToSightTraces( self.pers["team"] ); rocket thread maps\mp\killstreaks\_remotemissile::handleDamage(); maps\mp\killstreaks\_remotemissile::MissileEyes( self, rocket ); while(isdefined( rocket )) wait 0.1; wait 1; self.atObjectivePos = false; self.using = false; self endweapon(); if(self.shooting == false) self freezecontrols(true); self thread setStanceSpeed(); } airdrop() { self endon("bot_reset"); self endon("bot_end_package"); self endon("disconnect"); self thread watchPackage(); for(;;) { self.equipmentinprogress = true; self freezecontrols(false); self.newweap = "airdrop_marker_mp"; self.pers["weapon"] = self.newweap; self giveweapon(self.pers["weapon"]); self setspawnweapon(self.pers["weapon"]); self switchtoweapon(self.pers["weapon"]); wait 5; } } airdrop_sentry_minigun() { self endon("bot_reset"); self endon("bot_end_package"); self endon("disconnect"); self thread watchPackage(); for(;;) { self.equipmentinprogress = true; self freezecontrols(false); self.newweap = "airdrop_sentry_marker_mp"; self.pers["weapon"] = self.newweap; self giveweapon(self.pers["weapon"]); self setspawnweapon(self.pers["weapon"]); self switchtoweapon(self.pers["weapon"]); wait 5; } } sentry() { self endon("bot_reset"); self endon("disconnect"); self.using = true; sentryGun = maps\mp\killstreaks\_autosentry::createSentryForPlayer( "sentry_minigun", self ); wait 0.1; sentryGun maps\mp\killstreaks\_autosentry::sentry_setPlaced(); self.using = false; } airdrop_mega() { self endon("bot_reset"); self endon("bot_end_package"); self endon("disconnect"); self thread watchPackage(); for(;;) { self.equipmentinprogress = true; self freezecontrols(false); self.newweap = "airdrop_mega_marker_mp"; self.pers["weapon"] = self.newweap; self giveweapon(self.pers["weapon"]); self setspawnweapon(self.pers["weapon"]); self switchtoweapon(self.pers["weapon"]); wait 5; } } watchPackage() { self endon("bot_reset"); self endon("disconnect"); self waittill( "grenade_fire" ); wait 0.3; self notify("bot_end_package"); self endweapon(); if(self.shooting == false) self freezecontrols(true); wait 0.3; self.equipmentinprogress = false; } chopper() { self endon("bot_reset"); self endon("bot_end_streak"); self endon("disconnect"); self.atObjectivePos = true; self.fMoveSpeed = 0; if(self.animinprogress == true) self bots\includes::endBotAnim(); self thread watchChopper(); for(;;) { wait 0.1; if(isDefined( level.chopper ) && level.chopper.heliType == "minigun" && isDefined(level.chopper.owner) && level.chopper.owner == self && self bots\includes::_isUsingRemote()) { if(self getCurrentWeapon() != "heli_remote_mp") { self.newweap = "heli_remote_mp"; self.pers["weapon"] = self.newweap; self giveweapon(self.pers["weapon"]); self setspawnweapon(self.pers["weapon"]); self switchtoweapon(self.pers["weapon"]); } } } } watchChopper() { self endon("bot_reset"); self endon("disconnect"); self.usingksremote = true; if(self getCurrentWeapon() != "heli_remote_mp") { self.newweap = "heli_remote_mp"; self.pers["weapon"] = self.newweap; self giveweapon(self.pers["weapon"]); self setspawnweapon(self.pers["weapon"]); self switchtoweapon(self.pers["weapon"]); } self waittill("heliPlayer_removed"); self notify("bot_end_streak"); self thread StopShooting(); self endweapon(); self.usingksremote = false; self.atObjectivePos = false; if(self.shooting == false) self freezecontrols(true); self notify( "BotMovementComplete" ); self thread setStanceSpeed(); } ac130() { self endon("bot_reset"); self endon("bot_end_streak"); self endon("disconnect"); self.atObjectivePos = true; self.fMoveSpeed = 0; if(self.animinprogress == true) self bots\includes::endBotAnim(); self thread watch130(); using25mm = false; using40mm = false; using105mm = false; for(;;) { wait 0.1; if(level.ac130InUse && isDefined(level.ac130player) && level.ac130player == self && self bots\includes::_isUsingRemote()) { switch(randomint(3)) { case 0: if(using25mm == false) { using25mm = true; using40mm = false; using105mm = false; self.newweap = "ac130_25mm_mp"; self.pers["weapon"] = self.newweap; self giveweapon(self.pers["weapon"]); self setspawnweapon(self.pers["weapon"]); self switchtoweapon(self.pers["weapon"]); wait 2 + (randomint(4)); } break; case 1: if(using40mm == false) { using25mm = false; using40mm = true; using105mm = false; self.newweap = "ac130_40mm_mp"; self.pers["weapon"] = self.newweap; self giveweapon(self.pers["weapon"]); self setspawnweapon(self.pers["weapon"]); self switchtoweapon(self.pers["weapon"]); wait 2 + (randomint(4)); } break; case 2: if(using105mm == false) { using25mm = false; using40mm = false; using105mm = true; self.newweap = "ac130_105mm_mp"; self.pers["weapon"] = self.newweap; self giveweapon(self.pers["weapon"]); self setspawnweapon(self.pers["weapon"]); self switchtoweapon(self.pers["weapon"]); wait 2 + (randomint(3)); } break; } } } } watch130() { self endon("bot_reset"); self endon("disconnect"); self.usingksremote = true; self waittill("ac130player_removed"); self notify("bot_end_streak"); self thread StopShooting(); self endweapon(); self.usingksremote = false; self.atObjectivePos = false; if(self.shooting == false) self freezecontrols(true); self notify( "BotMovementComplete" ); self thread setStanceSpeed(); } giveKillstreak() { self endon("bot_reset"); self endon("death"); self endon("disconnect"); hard = 0; if(self.pers["bot"]["pickperk"]["hard"] == 1) { self.pers["bot"]["ks"]++; hard = 1; } switch(self.pers["bot"]["ks"]) { case 3: if(self.pers["bot"]["pickks"]["uav"] == 1) self maps\mp\killstreaks\_killstreaks::tryGiveKillstreak( "uav", 3 - hard ); break; case 4: if(self.pers["bot"]["pickks"]["counteruav"] == 1) self maps\mp\killstreaks\_killstreaks::tryGiveKillstreak( "counter_uav", 4 - hard ); if(self.pers["bot"]["pickks"]["airdrop"] == 1) self maps\mp\killstreaks\_killstreaks::tryGiveKillstreak( "airdrop", 4 ); break; case 5: if(self.pers["bot"]["pickks"]["predator"] == 1) self maps\mp\killstreaks\_killstreaks::tryGiveKillstreak( "predator_missile", 5 - hard ); if(self.pers["bot"]["pickks"]["sentry"] == 1) self maps\mp\killstreaks\_killstreaks::tryGiveKillstreak( "airdrop_sentry_minigun", 5 - hard ); break; case 6: if(self.pers["bot"]["pickks"]["airstrike"] == 1) self maps\mp\killstreaks\_killstreaks::tryGiveKillstreak( "precision_airstrike", 6 - hard ); break; case 7: if(self.pers["bot"]["pickks"]["helicopter"] == 1) self maps\mp\killstreaks\_killstreaks::tryGiveKillstreak( "helicopter", 7 - hard ); if(self.pers["bot"]["pickks"]["harrier"] == 1) self maps\mp\killstreaks\_killstreaks::tryGiveKillstreak( "harrier_airstrike", 7 - hard ); break; case 8: if(self.pers["bot"]["pickks"]["mega"] == 1) self maps\mp\killstreaks\_killstreaks::tryGiveKillstreak( "airdrop_mega", 8 - hard ); break; case 9: if(self.pers["bot"]["pickks"]["pavelow"] == 1) self maps\mp\killstreaks\_killstreaks::tryGiveKillstreak( "helicopter_flares", 9 - hard ); if(self.pers["bot"]["pickks"]["stealth"] == 1) self maps\mp\killstreaks\_killstreaks::tryGiveKillstreak( "stealth_airstrike", 9 - hard ); break; case 11: if(self.pers["bot"]["pickks"]["chopper"] == 1) { self maps\mp\killstreaks\_killstreaks::tryGiveKillstreak( "helicopter_minigun", 11 - hard ); self thread bots\talk::BotTalkChopper(); } if(self.pers["bot"]["pickks"]["130"] == 1) { self maps\mp\killstreaks\_killstreaks::tryGiveKillstreak( "ac130", 11 - hard ); self thread bots\talk::BotTalk130(); } break; case 15: if(self.pers["bot"]["pickks"]["emp"] == 1) self maps\mp\killstreaks\_killstreaks::tryGiveKillstreak( "emp", 15 - hard ); break; case 25: if(self.pers["bot"]["pickks"]["nuke"] == 1) { if(self.pers["bot"]["nuke"] == 1) { self maps\mp\killstreaks\_killstreaks::tryGiveKillstreak( "nuke", 25 - hard ); self thread bots\talk::BotTalkNuke(); } } else self thread bots\talk::BotTalkNukeStreak(); break; } if(self.pers["bot"]["pickperk"]["hard"] == 1) self.pers["bot"]["ks"]--; self thread useKillstreak(); } AmmoCheck() { self endon("bot_reset"); self endon("death"); self endon("disconnect"); self endon("StopShooting"); for(;;) { wait 2; if(self getWeaponAmmoClip( self getcurrentWeapon() ) == 0 && self getWeaponAmmoStock( self getcurrentWeapon() ) == 0) self thread doAmmo(); } } doAmmo() { self.ammostock = randomintrange(10, 100); if(self.pers["bot"]["pickperk"]["scav"] > 1) self.ammostock = self.ammostock * 2; if(self.pers["bot"]["weapontype"] == 3) { self SetWeaponAmmoClip(self getcurrentweapon(), 100, "left" ); self SetWeaponAmmoClip(self getcurrentweapon(), 100, "right" ); self SetWeaponAmmoStock(self getcurrentweapon(), self.ammostock); } else { self SetWeaponAmmoClip(self getcurrentweapon(), 100); self SetWeaponAmmoStock(self getcurrentweapon(), self.ammostock); } } ShootWeapon() { self endon("bot_reset"); self endon("death"); self endon("disconnect"); self endon("StopShooting"); self notify("ShootWeapon"); self.fMoveSpeed = 0; if(self.animinprogress == true) self bots\includes::endBotAnim(); if(self.usingksremote == false) { wait ( 0.4 * ( 4 - self.pers["bot"]["skill"] ) ); if(!isdefined(self.shootpos)) { self.shootpos = self.origin; self thread keepShootPos(); } } self.shooting = true; if(self UsingSemiAutoSniper()) self thread IntervalRounds(); else self freezecontrols(false); // allow bot to shoot self thread AmmoCheck(); } keepShootPos() { self endon("bot_reset"); self endon("death"); self endon("disconnect"); self endon("bot_continue_moving"); while(Distance(self.origin, self.shootpos) < 25) wait 0.1; self.shootpos = self.origin; for(;;) { wait 0.05; self SetOrigin( self.shootpos ); } } StopShooting() { self endon("bot_reset"); self endon("death"); self endon("disconnect"); self endon("ShootWeapon"); self.shooting = false; self notify("StopShooting"); if(self.meleeinprogress != true) wait 0.1; if(self.nadesinprogress == false) self freezecontrols(true); self.shootpos = undefined; self notify("bot_continue_moving"); if(self.type == "crouch") self setStance("crouch"); else if(self.meleeinprogress != true) self thread setStanceSpeed(); if(self.meleeinprogress != true && self.UsedKnife == true) { self.UsedKnife = false; self.didMeleeKamikaze = false; } self.equipmentinprogress = false; if(self.pers["bot"]["skill"] > 2) self thread ReloadCheck(); } ReloadCheck() { self endon("bot_reset"); self endon("death"); self endon("disconnect"); self endon("ShootWeapon"); if(self.pers["bot"]["skill"] == 4) wait 4; else wait 6; if( !isDefined(self.aimat) ) { if(self.pers["bot"]["weapontype"] == 3) { self SetWeaponAmmoClip(self getcurrentweapon(), 100, "left" ); self SetWeaponAmmoClip(self getcurrentweapon(), 100, "right" ); } else { self SetWeaponAmmoClip(self getcurrentweapon(), 100); } } } UsingSemiAutoSniper() { if( self.pers["bot"]["weapontype"] == 2 && isSubStr(self getCurrentWeapon(), "cheytac") == false ) return true; else return false; } IntervalRounds() { self endon("bot_reset"); self endon("death"); self endon("disconnect"); self endon("StopShooting"); for(;;) { self freezecontrols(false); // allow bot to shoot wait 0.25; self freezecontrols(true); // pause between rounds wait ( 1 + ( 0.5 + randomint(5) ) ); } } getFlagTeam() { return self.useObj maps\mp\gametypes\_gameobjects::getOwnerTeam(); } Spreadout() { self endon("bot_reset"); self endon("goalreach"); self endon("death"); self endon("disconnect"); while(1) { if(self.vObjectivePos != self.origin) { p = randomint(level.waypointcount); dist = Distance(level.waypoints[p].origin, self.origin); if(dist < 500 || dist > 2000) { wait 0.1; } else { self.vObjectivePos = level.waypoints[p].origin; self waittill("goalreach"); } } wait 0.1; } } isGangbanger() { self endon("bot_reset"); self endon("death"); self endon("disconnect"); g = 0; foreach(player in level.players) { if(player == self) continue; if(!bots\includes::_isReallyAlive(player)) continue; if(self.pers["team"] != player.pers["team"]) continue; dist = Distance(self.origin, player.origin); if(dist < 250) g++; wait 0.1; } if(g >= 2) { if(randomint(4) == 1) self spreadout(); } } tdm() { self endon("bot_reset"); self endon("death"); self endon("disconnect"); if(self.pers["bot"]["CamperRate"] < 2) { self camp(); } else { if((Distance(self.vObjectivePos, self.origin) < 100)) { if(self.doingMeleeKamikaze == true) { self.vObjectivePos = self.aimat.origin; } else { for(;;) { self endon("wp"); self.e = randomint(level.waypointcount); dist = Distance(level.waypoints[self.e].origin, self.origin); if(dist > 900) { self.vObjectivePos = level.waypoints[self.e].origin; self notify("wp"); } wait 0.1; } } } } } camp() { self endon("bot_reset"); self endon("death"); self endon("disconnect"); self endon("bot_end_camp"); camptime = 0; camptimer = randomintrange(30, 90); if(randomint(2) == 1) // thanks ineedbots, get campspot using children was a great idea campspot = getNearestCampSpot(); else campspot = getRandomCampSpot(); for(;;) { timeLeft = maps\mp\gametypes\_gamelogic::getTimeRemaining() / 1000; if((isDefined(level.bombPlanted) && level.bombPlanted == true) || (isDefined(level.bombsplanted) && level.bombsplanted > 0) || (timeLeft <= 60 && level.gametype != "dom")) self notify("bot_end_camp"); if(distance(level.waypoints[campspot].origin, self.origin) < 100) { self.type = "wait"; self thread bots\talk::BotTalkCamp(); for(;;) { wait 1; camptime++; timeLeft = maps\mp\gametypes\_gamelogic::getTimeRemaining() / 1000; if(camptime >= camptimer || (isDefined(level.bombPlanted) && level.bombPlanted == true) || (isDefined(level.bombsplanted) && level.bombsplanted > 0) || (timeLeft <= 60 && level.gametype != "dom")) { self.type = "stand"; self notify("bot_end_camp"); } } } else self.vObjectivePos = level.waypoints[campspot].origin; wait 1; } } getNearestCampSpot() { camppoints = getCampingWaypointArray(); campspot = -1; if(camppoints.size) { for(i=0;i (100 + randomint(200))) ObjectivePos = level.capZones[team].trigger ; else { if(self.atObjectivePos == false) self thread doCapZonesWait(); // wait for your flag to return } } else { if( isDefined( otherhasflag ) ) ObjectivePos = otherhasflag; else ObjectivePos = level.teamFlags[team].trigger ; } } else ObjectivePos = level.capZones[team].trigger ; } else { if( isDefined( hasflag ) ) { if( !level.teamFlags[ team ] maps\mp\gametypes\_gameobjects::isHome() ) { if( isDefined( otherhasflag ) ) ObjectivePos = otherhasflag; else ObjectivePos = level.teamFlags[team].trigger ; } else if(distance(hasflag.origin, self.origin > 200) ) ObjectivePos = hasflag; } else { if( !level.teamFlags[ team ] maps\mp\gametypes\_gameobjects::isHome() ) { if(level.teamFlags[ otherTeam ] maps\mp\gametypes\_gameobjects::isHome()) { if( isDefined( otherhasflag ) ) { if(distance(level.teamFlags[otherTeam].trigger.origin, self.origin ) < distance(otherhasflag.origin, self.origin )) ObjectivePos = level.teamFlags[otherTeam].trigger ; else ObjectivePos = otherhasflag; } else ObjectivePos = level.teamFlags[team].trigger ; } else { if( isDefined( otherhasflag ) ) ObjectivePos = otherhasflag; else ObjectivePos = level.teamFlags[team].trigger ; } } else { if(self.pers["bot"]["ObjTrait"] == 1) { if(distance(level.capZones[team].trigger.origin, self.origin ) > (100 + randomint(200))) ObjectivePos = level.capZones[team].trigger ; else { if(self.atObjectivePos == false) self thread doCapZonesWait(); // defend your flag } } else ObjectivePos = level.teamFlags[otherTeam].trigger ; } } } } if(level.gametype == "sd") { if(isdefined(level.bombZones) && (isdefined(level.sdBomb) || level.multiBomb)) { timeLeft = maps\mp\gametypes\_gamelogic::getTimeRemaining() / 1000; // if i am an attacker if(self.pers["team"] == game["attackers"]) { // if bomb is planted, attack nearest enemy if(level.bombPlanted == true) { if(self.pers["bot"]["ObjTrait"] > 3) { if(isDefined(level.sdBombModel)) { if(distance(level.sdBombModel.origin, self.origin) > (100 + randomint(200))) { ObjectivePos = level.sdBombModel; } else { // defend bombsite if(self.atObjectivePos == false) self thread doSdBombModelWait(); // defend bombsite } } } else self tdm(); } else // if i have the bomb, go to nearest bombsite and plant { if((isdefined(self.isBombCarrier) && self.isBombCarrier == true) || level.multiBomb) { if(timeLeft <= 60 || self.pers["bot"]["ObjTrait"] < 6) { // find closest bombzone nearestDistance = 9999999999; nearestBombZone = undefined; for(b = 0; b < level.bombZones.size; b++) { distance = distance(level.bombZones[b].trigger.origin, self.origin); if(distance < nearestDistance) { nearestBombZone = level.bombZones[b]; nearestDistance = distance; } } if(isDefined(nearestBombZone)) { // close enough so plant if(nearestDistance < 100) { if(level.using == false) { // planting self.atObjectivePos = true; self.fMoveSpeed = 0; if(self.animinprogress == true) self bots\includes::endBotAnim(); level.using = true; self.using = true; ObjectivePos = nearestBombZone.trigger; nearestBombZone maps\mp\gametypes\sd::onBeginUse(self); self.newweap = "briefcase_bomb_defuse_mp"; self notify("weapchange"); wait(getdvarint("scr_sd_planttime")); nearestBombZone maps\mp\gametypes\sd::onUsePlantObject(self); nearestBombZone maps\mp\gametypes\sd::onEndUse(self.pers["team"], self, true); self endweapon(); self.using = false; level.using = false; self.atObjectivePos = false; self thread setStanceSpeed(); } } else // too far away, go to bombsite { ObjectivePos = nearestBombZone.trigger; } } } } else // find bomb { // check if any of my team members has the bomb protectTarget = undefined; for(f = 0; f < level.players.size; f++) { if(!self IsEnemy(level.players[f]) && isdefined(level.players[f].isBombCarrier) && level.players[f].isBombCarrier == true) { protectTarget = level.players[f]; break; } wait 0.1; } // if one of my team members has the bomb, protect them if(isDefined(protectTarget) && bots\includes::_isReallyAlive(protectTarget)) { if(distance(protectTarget.origin, self.origin) < 200 || self.pers["bot"]["ObjTrait"] < 4) self tdm(); else ObjectivePos = protectTarget; } else // none of my team has the bomb, find the bomb { if(timeLeft <= 60 || self.pers["bot"]["ObjTrait"] > 3) { ObjectivePos = level.sdBomb.trigger; } } } } } else // defender { if(level.bombPlanted == true) { // close enough defuse if(distance(level.defuseObject.trigger.origin, self.origin) < 100 && bots\includes::_isReallyAlive(self)) { if(level.using == false) { self.atObjectivePos = true; self.fMoveSpeed = 0; if(self.animinprogress == true) self bots\includes::endBotAnim(); level.using = true; self.using = true; ObjectivePos = level.defuseObject.trigger; level.defuseObject maps\mp\gametypes\sd::onBeginUse(self); self.newweap = "briefcase_bomb_defuse_mp"; self notify("weapchange"); wait(getdvarint("scr_sd_defusetime")); level.defuseObject maps\mp\gametypes\sd::onUseDefuseObject(self); level.defuseObject maps\mp\gametypes\sd::onEndUse(self.pers["team"], self, true); self endweapon(); self.using = false; level.using = false; self.atObjectivePos = false; self thread setStanceSpeed(); } } else // go to bomb { ObjectivePos = level.defuseObject.trigger; } } else // not planted { if(self.pers["bot"]["ObjTrait"] > 5) { //get nearest bombzone nearestDistance = 9999999999; nearestBombZone = undefined; for(b = 0; b < level.bombZones.size; b++) { distance = distance(level.bombZones[b].trigger.origin, self.origin); if(distance < nearestDistance) { nearestBombZone = level.bombZones[b]; nearestDistance = distance; } } if(isDefined(nearestBombZone)) // if found bombzone { if(distance(nearestBombZone.trigger.origin, self.origin) > (100 + randomint(200))) { ObjectivePos = nearestBombZone.trigger; } else { // defend bombsite if(self.atObjectivePos == false) self thread doNearestBombZoneWait(); } } } else self tdm(); } } } } if((level.gametype == "dd") && (self.pers["bot"]["ObjTrait"] < 6)) // if gametype is demo { if(isdefined(level.bombZones)) // if all nessesary demo things are defined { nearestDistance = 9999999999; nearestBombZone = undefined; timeLeft = maps\mp\gametypes\_gamelogic::getTimeRemaining() / 1000; if(self.pers["team"] == game["attackers"]) // if on attack bombsite team { if((level.bombExploded == 1 && level.bombsplanted == 1) || (level.bombsplanted == 2) || (self.pers["bot"]["ObjTrait"] == 1) || (timeleft <= 60) || (self.pers["bot"]["ObjTrait"] == 3 && level.bombsplanted == 1)) // bomb planted { if(self.pers["bot"]["ObjTrait"] < 3) // if bot is willing to attempt objective { // get bombzone to protect for(b = 0; b < level.bombZones.size; b++) { distance = distance(level.bombZones[b].trigger.origin, self.origin); if(level.bombZones[b].label == "_a" && level.aPlanted == true) { if(distance < nearestDistance) { nearestBombZone = level.bombZones[b]; nearestDistance = distance; } } else { if(level.bombZones[b].label == "_b" && level.bPlanted == true) { if(distance < nearestDistance) { nearestBombZone = level.bombZones[b]; nearestDistance = distance; } } } } if(isDefined(nearestBombZone)) // if bombsite found { // go to protect if(distance(nearestBombZone.trigger.origin, self.origin) > (100 + randomint(200))) { ObjectivePos = nearestBombZone.trigger; } else { if(self.atObjectivePos == false) self thread doNearestBombZoneWait(); } } } } else // no bomb planted { // get bombzone for(b = 0; b < level.bombZones.size; b++) { distance = distance(level.bombZones[b].trigger.origin, self.origin); if(level.bombZones[b].label == "_a" && level.aPlanted == false) { if(distance < nearestDistance) { nearestBombZone = level.bombZones[b]; nearestDistance = distance; } } else { if(level.bombZones[b].label == "_b" && level.bPlanted == false) { if(distance < nearestDistance) { nearestBombZone = level.bombZones[b]; nearestDistance = distance; } } } } if(isDefined(nearestBombZone)) // if found bombsite { // close enough so plant if((nearestDistance < 100 && bots\includes::_isReallyAlive(self) && nearestBombZone.label == "_a" && level.aPlanted == false) || (nearestDistance < 100 && bots\includes::_isReallyAlive(self) && nearestBombZone.label == "_b" && level.bPlanted == false)) { if(level.using == false) { // planting self.atObjectivePos = true; self.fMoveSpeed = 0; if(self.animinprogress == true) self bots\includes::endBotAnim(); level.using = true; ObjectivePos = nearestBombZone.trigger; nearestBombZone maps\mp\gametypes\dd::onBeginUse(self); self.newweap = "briefcase_bomb_defuse_mp"; self notify("weapchange"); self.using = true; self thread bots\talk::BotTalkPlant(); wait(getdvarint("scr_dd_planttime") + 1); // bug check if(nearestDistance < 100 && bots\includes::_isReallyAlive(self) && ((nearestBombZone.label == "_a" && level.aPlanted == false) || (nearestBombZone.label == "_b" && level.bPlanted == false))) { // planted nearestBombZone maps\mp\gametypes\dd::onUseObject(self); nearestBombZone maps\mp\gametypes\dd::onEndUse(self.pers["team"], self, true); } // plant end self.using = false; self endweapon(); level.using = false; self.atObjectivePos = false; self thread setStanceSpeed(); } } else // too far away, go to bombsite { ObjectivePos = nearestBombZone.trigger; } } } } else // defender if(self.pers["bot"]["ObjTrait"] < 4) { if(level.bombsplanted >= 1) // if bomb is planted { // get bombzone for(b = 0; b < level.bombZones.size; b++) { distance = distance(level.bombZones[b].trigger.origin, self.origin); if(level.bombZones[b].label == "_a" && level.aPlanted == true) { if(distance < nearestDistance) { nearestBombZone = level.bombZones[b]; nearestDistance = distance; } } else { if(level.bombZones[b].label == "_b" && level.bPlanted == true) { if(distance < nearestDistance) { nearestBombZone = level.bombZones[b]; nearestDistance = distance; } } } } if(isDefined(nearestBombZone)) // found bombzone { // close enough if(nearestDistance < 100 && bots\includes::_isReallyAlive(self) && ((nearestBombZone.label == "_a" && level.aPlanted == true) || (nearestBombZone.label == "_b" && level.bPlanted == true))) { if(level.using == false) { self.atObjectivePos = true; self.fMoveSpeed = 0; if(self.animinprogress == true) self bots\includes::endBotAnim(); level.using = true; ObjectivePos = nearestBombZone.trigger; nearestBombZone maps\mp\gametypes\dd::onBeginUse(self); self.newweap = "briefcase_bomb_defuse_mp"; self notify("weapchange"); self.using = true; self thread bots\talk::BotTalkDefuse(); wait(getdvarint("scr_dd_defusetime") + 1); // bug check if(nearestDistance < 100 && bots\includes::_isReallyAlive(self) && ((nearestBombZone.label == "_a" && level.aPlanted == true) || (nearestBombZone.label == "_b" && level.bPlanted == true))) { // defusing nearestBombZone maps\mp\gametypes\dd::onUseObject(self); nearestBombZone maps\mp\gametypes\dd::onEndUse(self.pers["team"], self, true); } // end defuse self.using = false; self endweapon(); level.using = false; self.atObjectivePos = false; self thread setStanceSpeed(); } } else // go to bomb { ObjectivePos = nearestBombZone.trigger; } } } else // if not bomb planted { if(self.pers["bot"]["ObjTrait"] < 3) // if bot is willing to defend objective { // get bombzone for(b = 0; b < level.bombZones.size; b++) { distance = distance(level.bombZones[b].trigger.origin, self.origin); if(level.bombZones[b].label == "_a" && level.aPlanted == false) { if(distance < nearestDistance) { nearestBombZone = level.bombZones[b]; nearestDistance = distance; } } else { if(level.bombZones[b].label == "_b" && level.bPlanted == false) { if(distance < nearestDistance) { nearestBombZone = level.bombZones[b]; nearestDistance = distance; } } } } if(isDefined(nearestBombZone)) // if found bombzone { // go to protect if(distance(nearestBombZone.trigger.origin, self.origin) > (100 + randomint(200))) { ObjectivePos = nearestBombZone.trigger; } else { if(self.atObjectivePos == false) self thread doNearestBombZoneWait(); } } } } } } } if((level.gametype == "sab") && (self.pers["bot"]["ObjTrait"] < 6)) { otherTeam = "axis"; if(self.pers["team"] == "axis") { otherTeam = "allies"; } // we either own the bomb or have planted the bomb if(self.pers["team"] == level.sabBomb maps\mp\gametypes\_gameobjects::getOwnerTeam() && self.pers["bot"]["ObjTrait"] < 4) { // if bomb is planted, attack nearest enemy if(level.bombPlanted == true) { self tdm(); } else // if i have the bomb, go to nearest bombsite and plant if(isdefined(self.isBombCarrier) && self.isBombCarrier == true) { // get bombzone nearestBombZone = level.bombZones[otherTeam]; if(isDefined(nearestBombZone)) { // close enough so plant if(distance(nearestBombZone.trigger.origin, self.origin) < 100) { self.atObjectivePos = true; self.fMoveSpeed = 0; if(self.animinprogress == true) self bots\includes::endBotAnim(); self.using = true; ObjectivePos = nearestBombZone.trigger; nearestBombZone maps\mp\gametypes\sab::onBeginUse(self); self.newweap = "briefcase_bomb_defuse_mp"; self notify("weapchange"); wait(getdvarint("scr_sab_planttime")); nearestBombZone maps\mp\gametypes\sab::onUse(self); nearestBombZone maps\mp\gametypes\sab::onEndUse(self.pers["team"], self, true); self endweapon(); self.using = false; self.atObjectivePos = false; self thread setStanceSpeed(); } else // too far away, go to bombsite { ObjectivePos = nearestBombZone.trigger; } } } else // check if any of my team members has the bomb { protectTarget = undefined; for(f = 0; f < level.players.size; f++) { if(!self IsEnemy(level.players[f]) && isdefined(level.players[f].isBombCarrier) && level.players[f].isBombCarrier == true) { protectTarget = level.players[f]; break; } wait 0.1; } if(isDefined(protectTarget)) { if(distance(protectTarget.origin, self.origin) < 200) self tdm(); else ObjectivePos = protectTarget; } } } else // other team owns the bomb if(otherTeam == level.sabBomb maps\mp\gametypes\_gameobjects::getOwnerTeam()) { if(level.bombPlanted == true) { // get bombzone nearestBombZone = level.bombZones[self.pers["team"]]; // close enough defuse if(distance(nearestBombZone.trigger.origin, self.origin) < 100) { if(level.using == false) { self.atObjectivePos = true; self.fMoveSpeed = 0; if(self.animinprogress == true) self bots\includes::endBotAnim(); level.using = true; self.using = true; ObjectivePos = nearestBombZone.trigger; nearestBombZone maps\mp\gametypes\sab::onBeginUse(self); self.newweap = "briefcase_bomb_defuse_mp"; self notify("weapchange"); wait(getdvarint("scr_sab_defusetime")); if(level.bombPlanted == true) // bug fix if teammates defuse first { nearestBombZone maps\mp\gametypes\sab::onUse(self); nearestBombZone maps\mp\gametypes\sab::onEndUse(self.pers["team"], self, true); } self endweapon(); self.using = false; level.using = false; self.atObjectivePos = false; self thread setStanceSpeed(); } } else // go to planted bomb { if(level.using == false) ObjectivePos = nearestBombZone.trigger; } } else // bomb not planted, attack enemies so they die before they can plant { self tdm(); } } else // nobody has the bomb, go get it if(self.pers["bot"]["ObjTrait"] < 4) { ObjectivePos = level.sabBomb.trigger; } } if(level.gametype == "koth" && self.pers["bot"]["ObjTrait"] < 6 && isDefined(level.radioObject) && level.radioObject maps\mp\gametypes\_gameobjects::getOwnerTeam() != self.pers["team"]) { distance = Distance(self.origin, level.radioObject.trigger.origin); if(getdvar("mapname")=="mp_underpass") { distance2 = Distance(level.fixedhq.origin, level.radioObject.trigger.origin); distance3 = Distance(self.origin, level.fixedhq.origin); if(distance2 < 500) { if(distance3 > (75 + randomint(100))) { ObjectivePos = level.fixedhq; } else { if(self.atObjectivePos == false) self thread doRadioObjectWaitFixed(); } } else { if(distance > (75 + randomint(100))) { ObjectivePos = level.radioObject.trigger; } else { if(self.atObjectivePos == false) self thread doRadioObjectWait(); } } } else { if(distance > (75 + randomint(100))) { ObjectivePos = level.radioObject.trigger; } else { if(self.atObjectivePos == false) self thread doRadioObjectWait(); } } } if((level.gametype == "gtnw") && (self.pers["bot"]["ObjTrait"] < 6) && (isDefined(level.nukeSite))) { distance = Distance(self.origin, level.nukeSite.trigger.origin); if(distance > (50 + randomint(50))) { ObjectivePos = level.nukeSite.trigger; } else { if(self.atObjectivePos == false) self thread doNukeSiteWait(); } } if((level.gametype == "dom") && (self.pers["bot"]["ObjTrait"] < 4)) { closestFlag = -1; closestFlagDistance = 9999999999; for(i = 0; i < level.flags.size; i++) { team = level.flags[i] getFlagTeam(); if(team != self.pers["team"]) { distance = Distance(self.origin, level.flags[i].origin); if(distance < closestFlagDistance) { closestFlag = i; closestFlagDistance = distance; } } } if(closestFlag != -1) { if(distance(level.flags[closestFlag].origin, self.origin) > (75 + randomint(100))) { ObjectivePos = level.flags[closestFlag]; } else { if(self.atObjectivePos == false) self thread doFlagsWait(); } } } if(self.pers["bot"]["skill"] > 1 && self.pers["bot"]["Vengeful"] == 1 && self.pers["cur_death_streak"] > 2 && self.using == false) { if(isdefined(self.pers["bot"]["gotkilled"]) && bots\includes::_isReallyAlive(self.pers["bot"]["gotkilled"])) { ObjectivePos = self.pers["bot"]["gotkilled"]; } } if(self.pers["bot"]["LovePackages"] == 0 || self.pers["bot"]["LovePackages"] == 1) { dropCrate = getEntArray( "care_package", "targetname" ); if(dropCrate.size > 0) // if any carepackages exist { if(self.pers["bot"]["LovePackages"] == 0) { // get nearest carepackage airDrop = undefined; airDropDis = 99999999; foreach(crate in dropCrate) { distance = distance(self.origin, crate.origin); if(distance < airDropDis) { airDropDis = distance(self.origin, crate.origin); airDrop = crate; } wait 0.1; } } else { airDrop = undefined; foreach(crate in dropCrate) { if(isDefined(airDrop)) { if(maps\mp\killstreaks\_killstreaks::getStreakCost(airDrop.crateType) < maps\mp\killstreaks\_killstreaks::getStreakCost(crate.crateType)) { airDrop = crate; } } else { airDrop = crate; } wait 0.1; } } if(isdefined(airDrop)) // if found carepackage { heightToPackage = airDrop.origin[2] - self.origin[2]; if(heightToPackage < 50 && heightToPackage > -50) // if package can be reached { ObjectivePos = airDrop; // go to the carepackage distToPackage = Distance(airDrop.origin, self.origin); if(distToPackage < 100) // if close enough to take { self.atObjectivePos = true; self.fMoveSpeed = 0; if(self.animinprogress == true) self bots\includes::endBotAnim(); if(airDrop.owner == self) { wait 1; } else { wait 4; } if(isdefined(airDrop) && distToPackage < 120 && bots\includes::_isReallyAlive(self)) { if(airDrop.owner == self) { self thread bots\talk::BotTalkEarnedPackage(); } else { self thread bots\talk::BotTalkStolePackage(airDrop.owner); } airDrop notify ( "captured", self ); // capture it self thread useKillstreak(); } wait 0.2; self.atObjectivePos = false; self thread setStanceSpeed(); } } } } } sentry = undefined; turrets = GetEntArray("misc_turret","classname"); if(turrets.size > 0) // if there are any sentries { foreach(turret in turrets) { if(!isdefined(turret)) continue; if(turret.health > 20000) { if(level.teambased) { if(turret.team != self.team) { if(distance(self.origin,turret.origin) < 600) { ObjectivePos = turret; sentry = turret; } } } else { if(turret.owner != self) { if(distance(self.origin,turret.origin) < 600) { ObjectivePos = turret; sentry = turret; } } } } wait 0.1; } } if(isdefined(sentry) && ObjectivePos == sentry) { if(distance(self.origin,sentry.origin) < 125) { if(self.meleeinprogress == false) self thread turretmelee(sentry); } } if( isDefined( ObjectivePos ) && self.doingMeleeKamikaze == false) { self.vObjectivePos = ObjectivePos.origin; } else { self tdm(); } self waittill( "BotMovementComplete" ); wait 1; } } doCapZonesWait() { self endon("bot_reset"); self endon("death"); self endon("disconnect"); team = self.pers["team"]; self.atObjectivePos = true; self.fMoveSpeed = 0; if(self.animinprogress == true) self bots\includes::endBotAnim(); while(distance(self.origin,level.capZones[team].trigger.origin) < 300) wait 1; self.atObjectivePos = false; self notify( "BotMovementComplete" ); self thread setStanceSpeed(); } doSdBombModelWait() { self endon("bot_reset"); self endon("death"); self endon("disconnect"); self.atObjectivePos = true; self.fMoveSpeed = 0; if(self.animinprogress == true) self bots\includes::endBotAnim(); while(distance(self.origin,level.sdBombModel.origin) < 300) wait 1; self.atObjectivePos = false; self notify( "BotMovementComplete" ); self thread setStanceSpeed(); } doNearestBombZoneWait() { self endon("bot_reset"); self endon("death"); self endon("disconnect"); self.atObjectivePos = true; self.fMoveSpeed = 0; if(self.animinprogress == true) self bots\includes::endBotAnim(); for(w = 0; w < 1;) { wait 1; nearestDistance = 9999999999; nearestBombZone = undefined; for(b = 0; b < level.bombZones.size; b++) { distance = distance(level.bombZones[b].trigger.origin, self.origin); if(distance < nearestDistance) { nearestBombZone = level.bombZones[b]; nearestDistance = distance; } } if(isDefined(nearestBombZone)) { if(distance(self.origin,nearestBombZone.trigger.origin) > 300) w = 1; } } self.atObjectivePos = false; self notify( "BotMovementComplete" ); self thread setStanceSpeed(); } doRadioObjectWait() { self endon("bot_reset"); self endon("death"); self endon("disconnect"); self.atObjectivePos = true; self.fMoveSpeed = 0; if(self.animinprogress == true) self bots\includes::endBotAnim(); while(distance(self.origin,level.radioObject.trigger.origin) < 300) wait 1; self.atObjectivePos = false; self notify( "BotMovementComplete" ); self thread setStanceSpeed(); } doRadioObjectWaitFixed() { self endon("bot_reset"); self endon("death"); self endon("disconnect"); self.atObjectivePos = true; self.fMoveSpeed = 0; if(self.animinprogress == true) self bots\includes::endBotAnim(); while(distance(self.origin,level.fixedhq.origin) < 300 && distance(level.fixedhq.origin,level.radioObject.trigger.origin) < 500) wait 1; self.atObjectivePos = false; self notify( "BotMovementComplete" ); self thread setStanceSpeed(); } doNukeSiteWait() { self endon("bot_reset"); self endon("death"); self endon("disconnect"); self.atObjectivePos = true; self.fMoveSpeed = 0; if(self.animinprogress == true) self bots\includes::endBotAnim(); while(distance(self.origin,level.nukeSite.trigger.origin) < 300) wait 1; self.atObjectivePos = false; self notify( "BotMovementComplete" ); self thread setStanceSpeed(); } doFlagsWait() { self endon("bot_reset"); self endon("death"); self endon("disconnect"); self.atObjectivePos = true; self.fMoveSpeed = 0; if(self.animinprogress == true) self bots\includes::endBotAnim(); for(w = 0; w < 1;) { wait 1; closestFlag = -1; closestFlagDistance = 9999999999; for(i = 0; i < level.flags.size; i++) { team = level.flags[i] getFlagTeam(); if(team != self.pers["team"]) { distance = Distance(self.origin, level.flags[i].origin); if(distance < closestFlagDistance) { closestFlag = i; closestFlagDistance = distance; } } } if(closestFlag != -1) { if(distance(self.origin,level.flags[closestFlag].origin) > 300) w = 1; } } self.atObjectivePos = false; self notify( "BotMovementComplete" ); self thread setStanceSpeed(); } nadeDev() { self endon("disconnect"); for(;;) { self waittill ( "grenade_fire", grenade, weaponName ); if(weaponName == "smoke_grenade_mp") { grenade AddToSmokeList(); } } } SmokeTrace(start, end) { for(g = 0; g < level.smokeListCount; g++) { if(level.smokeList[g].state == "smoking") { if(RaySphereIntersect(start, end, level.smokeList[g].origin, self.pers["bot"]["smokeRad"])) { //line(start, end, (1,0,0)); return false; } } } //line(start, end, (0,1,0)); return true; } AddToSmokeList() { if(level.smokeListCount+1 > level.smokeList.size) { level.smokelist[level.smokelist.size] = spawnstruct(); } level.smokeList[level.smokeListCount].grenade = self; level.smokeList[level.smokeListCount].state = "moving"; level.smokeList[level.smokeListCount].stateTimer = gettime(); level.smokeList[level.smokeListCount].origin = self.origin; level.smokeListCount++; } RemoveFromSmokeList(index) { if(level.smokeListCount <= 0 || index >= level.smokeListCount || index < 0) { return; } for(i = index; i < level.smokeListCount-1; i++) { level.smokeList[i] = level.smokeList[i+1]; } level.smokeListCount--; } UpdateSmokeList() { while(1) { for(g = 0; g < level.smokeListCount; g++) { bGrenadeFound = false; grenades = getentarray("grenade", "classname"); // search grenade list for matching grenade entity for(i = 0; i < grenades.size; i++) { grenade = grenades[i]; if(level.smokeList[g].grenade == grenade) { level.smokeList[g].origin = grenade.origin; bGrenadeFound = true; break; } } // grenade not found, so must be smoking or just exploded if(!bGrenadeFound) { switch(level.smokeList[g].state) { case "moving": { level.smokeList[g].state = "smoking"; level.smokeList[g].stateTime = gettime(); break; } case "smoking": { if((gettime()-level.smokeList[g].stateTime) > 11000) { RemoveFromSmokeList(g); } /* else { print3d(level.smokeList[g].origin, "SMOKING", (1,0,0), 2); line(level.smokeList[g].origin, level.smokeList[g].origin + (0,0,300.0), (1,0,0)); } */ break; } } } } wait 1; } } RaySphereIntersect(start, end, spherePos, radius) { 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) if(bb4ac < 0) { //*mu1 = 0; //*mu2 = 0; return false; } //*mu1 = (-b + sqrt(bb4ac)) / (2 * a); //*mu2 = (-b - sqrt(bb4ac)) / (2 * a); return true; } BotMove(_vMoveTarget) { // cancel any previous moves self notify( "BotMovementComplete" ); if(self.using != true && !isDefined( self.lastStand )) { if(isDefined( self.vObjectivePos ) && self.fMoveSpeed > 0) self.botgoalreach = false; // regular cheap movement self.vMoveTarget = _vMoveTarget; // start move thread self thread BotMovethread(); } } BotMoveThread() { self endon("bot_reset"); self endon("BotMovementComplete"); self endon("death"); self endon("killed_player"); self endon("disconnect"); while(1) { if(ClampToGroundtest()) moveTarget = (self.vMoveTarget[0], self.vMoveTarget[1], self.origin[2]); else moveTarget = self.vMoveTarget; distance = DistanceSquared(moveTarget, self.origin); if(distance <= (self.fMoveSpeed*self.fMoveSpeed)) { self SetOrigin(self.vMoveTarget); self.fMoveSpeed = 0; if(self.animinprogress == true) self bots\includes::endBotAnim(); self notify( "BotMovementComplete" ); } else { if(self.fMoveSpeed > 0) // normal move { // move self SetOrigin(self.origin + (VectorNormalize(moveTarget-self.origin) * (self.fMoveSpeed))); } } wait 0.05; } } ClampToGroundtest() { trace = bulletTrace( self.origin + ( 0, 0, 50 ), self.origin + ( 0, 0, -50 ), false, self ); if(trace["fraction"] < 1 && !isdefined(trace["entity"])) { self SetOrigin(trace["position"]); return true; } return false; } GetNearestStaticWaypoint(pos) { self endon("bot_reset"); self endon("death"); self endon("disconnect"); if(isDefined(self.e) && pos == self.e) return self.e; nearestWaypoint = -1; nearestDistance = 9999999999; truewpcount = level.waypointCount - 1; if(isDefined(self.lastwp)) { if(self.lastwp < 5) range1 = 0; else range1 = self.lastwp - 5; if((self.lastwp + 5) > truewpcount) range2 = truewpcount; else range2 = self.lastwp + 5; for(i = range1; i < range2; i++) { distance = Distance(pos, level.waypoints[i].origin); if(distance < nearestDistance) { nearestDistance = distance; nearestWaypoint = i; } } diffvert = pos[2] - level.waypoints[nearestWaypoint].origin[2]; if(nearestDistance < 600 && diffvert < 50 && diffvert > -50 && bulletTracePassed( pos, level.waypoints[nearestWaypoint].origin, false, level.waypoints[nearestWaypoint])) { self.lastwp = nearestWaypoint; return nearestWaypoint; } } else { range1 = int(level.waypointCount*0.5); range2 = range1; } wait 0.1; for(i = 0; i < range1; i++) { distance = Distance(pos, level.waypoints[i].origin); if(distance < nearestDistance) { nearestDistance = distance; nearestWaypoint = i; } } diffvert = pos[2] - level.waypoints[nearestWaypoint].origin[2]; if(nearestDistance < 600 && diffvert < 50 && diffvert > -50 && bulletTracePassed( pos, level.waypoints[nearestWaypoint].origin, false, level.waypoints[nearestWaypoint])) { self.lastwp = nearestWaypoint; return nearestWaypoint; } wait 0.1; for(i = range2; i < level.waypointCount; i++) { distance = Distance(pos, level.waypoints[i].origin); if(distance < nearestDistance) { nearestDistance = distance; nearestWaypoint = i; } } self.lastwp = nearestWaypoint; return nearestWaypoint; } BotGoal_StaticWaypointFollowGoal() { self endon("bot_reset"); self endon("death"); self endon("disconnect"); wait 0.2; // spawn delay before move targetWpIdx = -1; // get waypoint nearest to ourselves currentStaticWp = GetNearestStaticWaypoint(self.origin); self.type = "stand"; for(;;) { // get waypoint pos self.tempwp = level.waypoints[currentStaticWp].origin; // stand and crouch logic if((level.waypoints[currentStaticWp].type == "stand") && (self.type == "crouch") && (self.shooting == false)) { self.type = "stand"; self setStance("stand"); } else { if((level.waypoints[currentStaticWp].type == "crouch") && (self.type != "crouch") && (self.shooting == false)) { self.type = "crouch"; self setStance("crouch"); } } if(!isDefined( self.vObjectivePos ) || !isDefined( self.vMoveTarget ) || (isDefined( self.vObjectivePos ) && ((isDefined( self.vMoveTarget ) && self.vMoveTarget != self.vObjectivePos && Distance(self.origin, self.vMoveTarget) >= 25) || Distance(self.origin, self.vObjectivePos) >= 600))) self BotMove(self.tempwp); else { self.tempwp = self.vObjectivePos; self BotMove(self.tempwp); } // clamp to xz plane distToWp = Distance((self.tempwp[0], self.tempwp[1], self.origin[2]), self.origin); if(distToWp < 150) self.botgoalreach = true; else self.botgoalreach = false; if(distToWp < 25) self.standingongoal = true; else self.standingongoal = false; // pick next waypoint or end if(distToWp < 50 || self.doingMeleeKamikaze == true) { // if our current waypoint is close enough, then end our goal if(WaypointCloseEnough(self.vObjectivePos, currentStaticWp) || self.doingMeleeKamikaze == true) { self notify("goalreach"); if((Distance(self.origin, self.vObjectivePos) > 25 || self.doingMeleeKamikaze == true) && self.tempwp != self.vObjectivePos) { self.tempwp = self.vObjectivePos; self BotMove(self.tempwp); } } else { // get waypoint nearest our target if(targetWpIdx != -1) { distance = Distance(self.vObjectivePos, level.waypoints[targetWpIdx].origin); diffvert = self.vObjectivePos[2] - level.waypoints[targetWpIdx].origin[2]; if(distance >= 600 || diffvert >= 50 || diffvert <= -50 || !bulletTracePassed( self.vObjectivePos, level.waypoints[targetWpIdx].origin, false, level.waypoints[targetWpIdx])) targetWpIdx = GetNearestStaticWaypoint(self.vObjectivePos); } else targetWpIdx = GetNearestStaticWaypoint(self.vObjectivePos); // find shortest path to our destination currentStaticWp = AStarSearch(currentStaticWp, targetWpIdx); self.tempwp = level.waypoints[currentStaticWp].origin; self BotMove(self.tempwp); } } wait 0.1; } } WaypointCloseEnough(pos, wpIndex) { distance = Distance(pos, level.waypoints[wpIndex].origin); diffvert = pos[2] - level.waypoints[wpIndex].origin[2]; if(distance < 600 && diffvert < 50 && diffvert > -50 && bulletTracePassed( pos, level.waypoints[wpIndex].origin, false, level.waypoints[wpIndex])) return true; else return false; } AStarSearch(startWp, goalWp) // algorithm for the general searching of optimal paths { self endon("bot_reset"); self endon("death"); self endon("disconnect"); pQOpen = []; pQSize = 0; closedList = []; listSize = 0; s = spawnstruct(); s.g = 0; //start node s.h = distance(level.waypoints[startWp].origin, level.waypoints[goalWp].origin); s.f = s.g + s.h; s.wpIdx = startWp; s.parent = spawnstruct(); s.parent.wpIdx = -1; // PQPush(pQOpen, s, pQSize); // push s on Open pQOpen[pQSize] = spawnstruct(); pQOpen[pQSize] = s; // push s on Open pQSize++; // while Open is not empty while(!PQIsEmpty(pQOpen, pQSize)) { // pop node n from Open // n has the lowest f // n = PQPop(pQOpen, pQSize); // pQSize--; n = pQOpen[0]; highestPriority = 9999999999; bestNode = -1; for(i = 0; i < pQSize; i++) { if(pQOpen[i].f < highestPriority) { bestNode = i; highestPriority = pQOpen[i].f; } } if(bestNode != -1) { n = pQOpen[bestNode]; //remove node from queue for(i = bestNode; i < pQSize-1; i++) { pQOpen[i] = pQOpen[i+1]; } pQSize--; } else { return; } // if n is a goal node; construct path, return success if(n.wpIdx == goalWp) { x = n; for(z = 0; z < 1000; z++) { parent = x.parent; if(parent.parent.wpIdx == -1) { return x.wpIdx; } // line(level.waypoints[x.wpIdx].origin, level.waypoints[parent.wpIdx].origin, (0,1,0)); x = parent; } return; } // for each successor nc of n for(i = 0; i < level.waypoints[n.wpIdx].childCount; i++) { // newg = n.g + cost(n,nc) newg = n.g + distance(level.waypoints[n.wpIdx].origin, level.waypoints[level.waypoints[n.wpIdx].children[i]].origin); // if nc is in Open or Closed, and nc.g <= newg then skip if(PQExists(pQOpen, level.waypoints[n.wpIdx].children[i], pQSize)) { // nc = PQGet(pQOpen, level.waypoints[n.wpIdx].children[i], pQSize); nc = spawnstruct(); for(p = 0; p < pQSize; p++) { if(pQOpen[p].wpIdx == level.waypoints[n.wpIdx].children[i]) { nc = pQOpen[p]; break; } } if(nc.g <= newg) { continue; } } else if(ListExists(closedList, level.waypoints[n.wpIdx].children[i], listSize)) { // nc = ListGet(closedList, level.waypoints[n.wpIdx].children[i], listSize); nc = spawnstruct(); for(p = 0; p < listSize; p++) { if(closedList[p].wpIdx == level.waypoints[n.wpIdx].children[i]) { nc = closedList[p]; break; } } if(nc.g <= newg) { continue; } } // nc.parent = n // nc.g = newg // nc.h = GoalDistEstimate( nc ) // nc.f = nc.g + nc.h nc = spawnstruct(); nc.parent = spawnstruct(); nc.parent = n; nc.g = newg; nc.h = distance(level.waypoints[level.waypoints[n.wpIdx].children[i]].origin, level.waypoints[goalWp].origin); nc.f = nc.g + nc.h; nc.wpIdx = level.waypoints[n.wpIdx].children[i]; // if nc is in Closed if(ListExists(closedList, nc.wpIdx, listSize)) { // remove it from Closed // ListRemove(closedList, nc.wpIdx, listSize); deleted = false; for(p = 0; p < listSize; p++) { if(closedList[p].wpIdx == nc.wpIdx) { for(x = p; x < listSize-1; x++) { closedList[x] = closedList[x+1]; } deleted = true; break; } if(deleted) { break; } } listSize--; } // if nc is not yet in Open, if(!PQExists(pQOpen, nc.wpIdx, pQSize)) { // push nc on Open // PQPush(pQOpen, nc, pQSize); pQOpen[pQSize] = spawnstruct(); pQOpen[pQSize] = nc; pQSize++; } } // Done with children, push n onto Closed if(!ListExists(closedList, n.wpIdx, listSize)) { // ListAdd(closedList, n, listSize); closedList[listSize] = spawnstruct(); closedList[listSize] = n; listSize++; } } } PQPush(Q, n, QSize) // priority queue push function { Q[QSize] = spawnstruct(); Q[QSize] = n; } // (highest priority is actually smallest value because priority is actually a distance) PQPop(Q, QSize) // priority queue pop function { rVal = spawnstruct(); rVal.wpIdx = -1; highestPriority = 9999999999; bestNode = -1; for(i = 0; i < QSize; i++) { if(Q[i].f < highestPriority) { bestNode = i; highestPriority = Q[i].f; } } if(bestNode != -1) { rVal = Q[bestNode]; // remove node from queue for(i = bestNode; i < QSize-1; i++) { Q[i] = Q[i+1]; } return rVal; } return rVal; } PQIsEmpty(Q, QSize) // returns true if empty { if(QSize <= 0) { return true; } return false; } PQGet(Q, n, QSize) { for(i = 0; i < QSize; i++) { if(Q[i].wpIdx == n) { return Q[i]; } } rVal = spawnstruct(); rVal.wpIdx = -1; return rVal; } PQExists(Q, n, QSize) // returns true if n exists in the pQ { for(i = 0; i < QSize; i++) { if(Q[i].wpIdx == n) { return true; } } return false; } ListAdd(list, n, listSize) { list[listSize] = spawnstruct(); list[listSize] = n; } ListRemove(list, n, listSize) { for(i = 0; i < listSize; i++) { if(list[i].wpIdx == n.wpIdx) { for(x = i; x < listSize-1; x++) { list[x] = list[x+1]; } return; } } } ListExists(list, n, listSize) // returns true if n exists in the list { for(i = 0; i < listSize; i++) { if(list[i].wpIdx == n) { return true; } } return false; } ListGet(list, n, listSize) { for(i = 0; i < listSize; i++) { if(list[i].wpIdx == n) { return list[i]; } } rVal = spawnstruct(); rVal.wpIdx = -1; return rVal; }