//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// LOCALS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////// DEBUGGING /////////////////////////////////// local debug = false /////////////////////////////////// DEBUGGING /////////////////////////////////// /////////////////////////////////// GLOBAL ENTITIES /////////////////////////////////// local gamerules_entity; gamerules_entity = Entities.FindByName(gamerules_entity, "gamerules") local objective_resource_entity; objective_resource_entity = Entities.FindByClassname(objective_resource_entity, "tf_objective_resource") local wave_start_relay_entity; wave_start_relay_entity = Entities.FindByName(wave_start_relay_entity, "wave_start_relay") local intel_entity; intel_entity = Entities.FindByName(intel_entity, "intel") /////////////////////////////////// GLOBAL ENTITIES /////////////////////////////////// /////////////////////////////////// CALLBACKS /////////////////////////////////// self.ValidateScriptScope() ::CALLBACKS <- {} ClearGameEventCallbacks() for (local i = 1; i <= Constants.Server.MAX_PLAYERS; i++) // run this for when the first player connects to the server and the callback hasn't loaded yet { local player = PlayerInstanceFromIndex(i) if (player == null) continue if (IsPlayerABot(player)) continue player.ValidateScriptScope() local scope = player.GetScriptScope() if (!("saw_mission_info" in scope)) { scope.saw_mission_info <- true ClientPrint(player, 4, "For the duration of this mission, certain robots will be spawning from several different locations marked on this map.") ClientPrint(player, 3, "\x07FFD700For the duration of this mission, certain robots will be spawning from several different locations marked on this map.") } } ::CALLBACKS.OnGameEvent_post_inventory_application <- function(params) { local spawned_player = GetPlayerFromUserID(params.userid); if (spawned_player.IsFakeClient()) return spawned_player.ValidateScriptScope() local scope = spawned_player.GetScriptScope() if (!("saw_mission_info" in scope)) { scope.saw_mission_info <- true ClientPrint(spawned_player, 4, "For the duration of this mission, certain robots will be spawning from several different locations marked on this map.") ClientPrint(spawned_player, 3, "\x07FFD700For the duration of this mission, certain robots will be spawning from several different locations marked on this map.") } } ::CALLBACKS.OnGameEvent_player_spawn <- function(params) // it takes an extra short while for the populator to fill in all of a bot's data when it spawns in, so "onspawn" callbacks need to be delayed { local bot = GetPlayerFromUserID(params.userid); if (!bot.IsFakeClient()) return EntFireByHandle(bot, "RunScriptCode", "BotTagCheck()", -1.0, null, null) } ::ignite_player <- Entities.CreateByClassname("tf_weapon_flamethrower") ignite_player.AddAttribute("Set DamageType Ignite", 1, -1.0) Entities.DispatchSpawn(ignite_player) ::CALLBACKS.OnScriptHook_OnTakeDamage <- function(params) { if (params.attacker == boss_entity || params.attacker == phase2_rocket) { if (params.damage_type == 2359360 || params.damage_type == 3407936 && params.const_entity != boss_entity && params.const_entity != phase2_rocket) params.const_entity.TakeDamageEx(params.inflictor, params.attacker, ignite_player, Vector(0, 0, 0), params.const_entity.GetOrigin(), 0.01, 8) } } /////////////////////////////////// CALLBACKS /////////////////////////////////// /////////////////////////////////// TELEPORTERS /////////////////////////////////// for (local ent; ent = Entities.FindByName(ent, "tele_*"); ) ent.Kill() ::teledestination_array <- [] ::teledestination_array_giant <- [] ::tele_spot_b1 <- SpawnEntityFromTable("prop_dynamic", { targetname = "tele_spot_b1" origin = Vector(-630, -430, 255) angles = QAngle(0, -90, 0) model = "models/props_mvm/robot_spawnpoint.mdl" DefaultAnim = "idle" }) ::tele_spot_b2 <- SpawnEntityFromTable("prop_dynamic", { targetname = "tele_spot_b2" origin = Vector(-1150, -1120, 255) angles = QAngle(0, 90, 0) model = "models/props_mvm/robot_spawnpoint.mdl" DefaultAnim = "idle" }) ::tele_spot_b3 <- SpawnEntityFromTable("prop_dynamic", { targetname = "tele_spot_b3" origin = Vector(-1850, -700, 255) angles = QAngle(0, 0, 0) model = "models/props_mvm/robot_spawnpoint.mdl" DefaultAnim = "idle" }) ::tele_spot_b4 <- SpawnEntityFromTable("prop_dynamic", { targetname = "tele_spot_b4" origin = Vector(450, -450, 205) angles = QAngle(0, 180, 0) model = "models/props_mvm/robot_spawnpoint.mdl" DefaultAnim = "idle" }) ::tele_spot_b5 <- SpawnEntityFromTable("prop_dynamic", { targetname = "tele_spot_b5" origin = Vector(180, -1120, 320) angles = QAngle(0, 180, 0) model = "models/props_mvm/robot_spawnpoint.mdl" DefaultAnim = "idle" }) ::tele_spot_f1 <- SpawnEntityFromTable("prop_dynamic", { targetname = "tele_spot_f1" origin = Vector(-1500, 1600, 180) angles = QAngle(0, -90, 0) model = "models/props_mvm/robot_spawnpoint.mdl" DefaultAnim = "idle" }) ::tele_spot_f2 <- SpawnEntityFromTable("prop_dynamic", { targetname = "tele_spot_f2" origin = Vector(-450, 1500, 40) angles = QAngle(0, -90, 0) model = "models/props_mvm/robot_spawnpoint.mdl" DefaultAnim = "idle" }) ::tele_spot_f3 <- SpawnEntityFromTable("prop_dynamic", { targetname = "tele_spot_f3" origin = Vector(450, 600, 80) angles = QAngle(0, 180, 0) model = "models/props_mvm/robot_spawnpoint.mdl" DefaultAnim = "idle" }) ::tele_spot_f4 <- SpawnEntityFromTable("prop_dynamic", { targetname = "tele_spot_f4" origin = Vector(-1950, -100, 255) angles = QAngle(0, 0, 0) model = "models/props_mvm/robot_spawnpoint.mdl" DefaultAnim = "idle" }) ::tele_spot_b1_skyparticle <- SpawnEntityFromTable("info_particle_system", { targetname = "skyparticle_tele_spot_b1" origin = Vector(-630, -430, 255) angles = QAngle(0, 90, 0) start_active = 0, effect_name = "teleporter_mvm_bot_persist" }) ::tele_spot_b2_skyparticle <- SpawnEntityFromTable("info_particle_system", { targetname = "skyparticle_tele_spot_b2" origin = Vector(-1150, -1120, 255) angles = QAngle(0, 90, 0) start_active = 0, effect_name = "teleporter_mvm_bot_persist" }) ::tele_spot_b3_skyparticle <- SpawnEntityFromTable("info_particle_system", { targetname = "skyparticle_tele_spot_b3" origin = Vector(-1850, -700, 255) angles = QAngle(0, 90, 0) start_active = 0, effect_name = "teleporter_mvm_bot_persist" }) ::tele_spot_b4_skyparticle <- SpawnEntityFromTable("info_particle_system", { targetname = "skyparticle_tele_spot_b4" origin = Vector(450, -450, 205) angles = QAngle(0, 90, 0) start_active = 0, effect_name = "teleporter_mvm_bot_persist" }) ::tele_spot_b5_skyparticle <- SpawnEntityFromTable("info_particle_system", { targetname = "skyparticle_tele_spot_b5" origin = Vector(180, -1120, 320) angles = QAngle(0, 90, 0) start_active = 0, effect_name = "teleporter_mvm_bot_persist" }) ::tele_spot_f1_skyparticle <- SpawnEntityFromTable("info_particle_system", { targetname = "skyparticle_tele_spot_f1" origin = Vector(-1500, 1600, 180) angles = QAngle(0, 90, 0) start_active = 0, effect_name = "teleporter_mvm_bot_persist" }) ::tele_spot_f2_skyparticle <- SpawnEntityFromTable("info_particle_system", { targetname = "skyparticle_tele_spot_f2" origin = Vector(-450, 1500, 40) angles = QAngle(0, 90, 0) start_active = 0, effect_name = "teleporter_mvm_bot_persist" }) ::tele_spot_f3_skyparticle <- SpawnEntityFromTable("info_particle_system", { targetname = "skyparticle_tele_spot_f3" origin = Vector(450, 600, 80) angles = QAngle(0, 90, 0) start_active = 0, effect_name = "teleporter_mvm_bot_persist" }) ::tele_spot_f4_skyparticle <- SpawnEntityFromTable("info_particle_system", { targetname = "skyparticle_tele_spot_f4" origin = Vector(-1950, -100, 285) angles = QAngle(0, 90, 0) start_active = 0, effect_name = "teleporter_mvm_bot_persist" }) ::teleports_active <- false ::current_squad_leader <- null ::bomb_placement_adjusted <- false /////////////////////////////////// TELEPORTERS /////////////////////////////////// ::aoe_medic_counter <- 1 ::boss_entity <- null ::boss_stage_threshold_reached <- false ::after_boss_phase_transition <- false ::firefist_rockets_fired <- 0 ::phase2_rocket <- null //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// AUTOEXECUTE //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////// EVERY WAVE /////////////////////////////////// ::current_bombpath <- null NetProps.SetPropString(gamerules_entity, "m_iszScriptThinkFunction", ""); if (!("onetimeactions_performed" in getroottable())) { ::onetimeactions_performed <- true PrecacheSound("mvm/mvm_tele_deliver.wav") local a39 = NavMesh.GetNavAreaByID(39) local a83 = NavMesh.GetNavAreaByID(83) local a143 = NavMesh.GetNavAreaByID(143) local a203 = NavMesh.GetNavAreaByID(203) local a292 = NavMesh.GetNavAreaByID(292) local a352 = NavMesh.GetNavAreaByID(352) local a354 = NavMesh.GetNavAreaByID(354) local a446 = NavMesh.GetNavAreaByID(446) local a663 = NavMesh.GetNavAreaByID(663) local a682 = NavMesh.GetNavAreaByID(682) local a687 = NavMesh.GetNavAreaByID(687) local a1018 = NavMesh.GetNavAreaByID(1018) local a1022 = NavMesh.GetNavAreaByID(1022) local a1573 = NavMesh.GetNavAreaByID(1573) local a2358 = NavMesh.GetNavAreaByID(2358) local a2385 = NavMesh.GetNavAreaByID(2385) local a2937 = NavMesh.GetNavAreaByID(2937) local a2938 = NavMesh.GetNavAreaByID(2938) local a2939 = NavMesh.GetNavAreaByID(2939) local a2940 = NavMesh.GetNavAreaByID(2940) a143.Disconnect(a292) a352.Disconnect(a663) a446.Disconnect(a39) a1018.Disconnect(a682) a1022.Disconnect(a687) a2358.Disconnect(a292) a2385.Disconnect(a354) a2937.Disconnect(a1573) a2938.Disconnect(a203) a2939.Disconnect(a203) a2939.Disconnect(a83) a2940.Disconnect(a83) } EntFire("spawnbot_single_flag", "Disable") for (local ent; ent = Entities.FindByName(ent, "bombpath_left_*"); ) { EntityOutputs.RemoveOutput(ent, "OnTrigger", "gamerules", "RunScriptCode", "current_bombpath = `left`") EntityOutputs.AddOutput(ent, "OnTrigger", "gamerules", "RunScriptCode", "current_bombpath = `left`", -1.0, -1) } for (local ent; ent = Entities.FindByName(ent, "bombpath_right_*"); ) { EntityOutputs.RemoveOutput(ent, "OnTrigger", "gamerules", "RunScriptCode", "current_bombpath = `right`") EntityOutputs.AddOutput(ent, "OnTrigger", "gamerules", "RunScriptCode", "current_bombpath = `right`", -1.0, -1) } if (Entities.FindByName(null, "defenderspushedcheck") == null) { local nav_avoid_giant = SpawnEntityFromTable("func_nav_avoid", { targetname = "nav_avoid_giant" origin = Vector(-700, -350, 0) tags = "bot_giant" }) nav_avoid_giant.KeyValueFromInt("solid", 2) nav_avoid_giant.KeyValueFromString("mins", "-300 -300 -1000") nav_avoid_giant.KeyValueFromString("maxs", "300 300 1000") local nav_avoid_giant2 = SpawnEntityFromTable("func_nav_avoid", { targetname = "nav_avoid_giant" origin = Vector(-800, 200, 200) tags = "bot_giant" }) nav_avoid_giant2.KeyValueFromInt("solid", 2) nav_avoid_giant2.KeyValueFromString("mins", "-200 -200 -1000") nav_avoid_giant2.KeyValueFromString("maxs", "200 200 1000") ::PreventBadPathing <- function() { local nav_avoid_telebot = SpawnEntityFromTable("func_nav_avoid", { targetname = "nav_avoid_telebot" origin = Vector(-500, -1500, 0) tags = "telebot" }) nav_avoid_telebot.KeyValueFromInt("solid", 2) nav_avoid_telebot.KeyValueFromString("mins", "-2000 -1500 -1000") nav_avoid_telebot.KeyValueFromString("maxs", "2000 250 1000") } ::PreventBadPathing(); ::PreventBadPathing(); ::PreventBadPathing(); ::PreventBadPathing() // needs to be run this many times to ensure the telebot nav paths win the attention of telebots over all the default nav funcs local nav_avoid_bossbot = SpawnEntityFromTable("func_nav_avoid", { targetname = "nav_avoid_bossbot" origin = Vector(-100, 650, 0) tags = "boss_bot" }) nav_avoid_bossbot.KeyValueFromInt("solid", 2) nav_avoid_bossbot.KeyValueFromString("mins", "-300 -300 -1000") nav_avoid_bossbot.KeyValueFromString("maxs", "300 250 1000") local think_havedefendersbeenpushed = SpawnEntityFromTable("logic_relay", {targetname = "defenderspushedcheck"}) AddThinkToEnt(think_havedefendersbeenpushed, "HaveDefendersBeenPushed_Think") local think_bombcarrierspawnspeedup = SpawnEntityFromTable("logic_relay", {targetname = "bombcarrierspawnspeedup"}) AddThinkToEnt(think_bombcarrierspawnspeedup, "BombCarrierSpawnSpeedUp_Think") } ::SetIcons <- function(type) { if (type == "w5_remove") { NetProps.SetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassFlags", 0, 9) NetProps.SetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassFlags", 0, 10) NetProps.SetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassFlags", 0, 11) } if (type == "w5_add") { NetProps.SetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassFlags", 25, 8) NetProps.SetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassFlags", 4, 9) NetProps.SetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassFlags", 4, 10) NetProps.SetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassFlags", 4, 11) } } if (NetProps.GetPropInt(objective_resource_entity, "m_nMannVsMachineWaveCount") == 5) { ::SetIcons("w5_remove") EntityOutputs.RemoveOutput(wave_start_relay_entity, "OnTrigger", "gamerules", "RunScriptCode", "SetIcons(`w5_remove`)") EntityOutputs.AddOutput(wave_start_relay_entity, "OnTrigger", "gamerules", "RunScriptCode", "SetIcons(`w5_remove`)", -1.0, -1) EntFire("spawnbot_invasion", "Disable") } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// AUTOEXECUTE //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// FUNCTIONS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////// TELEPORTERS /////////////////////////////////// ::Teles_StatusChange <- function(action) { if (action == "begin") { EntFireByHandle(gamerules_entity, "PlayVO", "mvm/mvm_tele_activate.wav", 0.0, null, null) for (local i = 1; i <= Constants.Server.MAX_PLAYERS; i++) { local player = PlayerInstanceFromIndex(i) if (player == null) continue if (IsPlayerABot(player)) continue player.ValidateScriptScope() local scope = player.GetScriptScope() if (!("saw_teleport_overlay" in scope)) { scope.saw_teleport_overlay <- true EntFireByHandle(player, "SetScriptOverlayMaterial", "teleport_warning_overlay", 0.0, null, null); EntFireByHandle(player, "SetScriptOverlayMaterial", "", 8.0, null, null); } } teleports_active = true } if (action == "end") { EntFireByHandle(gamerules_entity, "PlayVO", "weapons/teleporter_explode.wav", 0.0, null, null) teleports_active = false } } ::BotTagCheck <- function() { if (self.HasBotTag("disband_squad")) self.DisbandCurrentSquad() if (self.HasBotTag("aoe_medic")) EntFireByHandle(self, "RunScriptCode", "SetUpAoEUber()", -1.0, null, null) if (self.HasBotTag("boss_bot")) EntFireByHandle(self, "RunScriptCode", "SetUpBossEnts()", -1.0, null, null) if (!(self.HasBotTag("telebot")) && !(self.HasBotTag("telebot_ignorenavfunc"))) return if (!(self.HasBotTag("telebot_squadmember")) || !(self.HasBotTag("telebot_w3d")) || !(self.HasBotTag("telebot_w5a")) || !(self.HasBotTag("telebot_bosshelper"))) { try { if (!(self.HasBotAttribute(32768))) self.Teleport(true, teledestination_array[RandomInt(0, teledestination_array.len() - 1)] + Vector(0, 0, 10), false, QAngle(0, 0, 0), false, Vector(0, 0, 0)) else self.Teleport(true, teledestination_array_giant[RandomInt(0, teledestination_array_giant.len() - 1)] + Vector(0, 0, 10), false, QAngle(0, 0, 0), false, Vector(0, 0, 0)) } catch (e) {} // vscript complains about not finding any tele locations even when the "if" condition is not met } if (self.HasBotTag("telebot_w3d")) self.Teleport(true, Vector(-800, -2050, 235), false, QAngle(0, 0, 0), false, Vector(0, 0, 0)) if (self.HasBotTag("telebot_w5a")) self.Teleport(true, Vector(-1850, -700, 285), false, QAngle(0, 0, 0), false, Vector(0, 0, 0)) if (self.HasBotTag("telebot_bosshelper") && boss_entity != null) self.Teleport(true, boss_entity.GetOrigin() + Vector(0, 0, 50), false, QAngle(0, 0, 0), true, Vector(RandomInt(-500, 500), RandomInt(-500, 500), 600)) if (self.HasBotTag("telebot_squadleader")) { current_squad_leader = self EntFireByHandle(gamerules_entity, "RunScriptCode", "current_squad_leader = null", 0.5, null, null) } if (self.HasBotTag("telebot_squadmember")) self.Teleport(true, current_squad_leader.GetOrigin(), false, QAngle(0, 0, 0), false, Vector(0, 0, 0)) if (!(self.HasBotAttribute(32768))) { self.AddCustomAttribute("force distribute currency on death", 1, -1) for (local i = 1; i <= Constants.Server.MAX_PLAYERS; i++) { local player_to_alert = PlayerInstanceFromIndex(i) if (player_to_alert == null || IsPlayerABot(player_to_alert)) continue if (!(self.HasBotTag("telebot_squadmember"))) EmitSoundEx({sound_name = "mvm/mvm_tele_deliver.wav", channel = 6, entity = player_to_alert, pitch = 100, filter_type = 4, volume = 0.2}) } } if (self.HasBotAttribute(32768)) { NetProps.SetPropBool(self, "m_bGlowEnabled", true) if (!(self.HasBotTag("telebot_squadmember"))) EntFireByHandle(gamerules_entity, "PlayVO", "mvm/giant_heavy/giant_heavy_entrance.wav", 0.0, null, null) } EntFireByHandle(self, "RunScriptCode", "Telefrag()", 0.2, null, null) // smallest comfortable amount of time required by the populator to fill in all of the bot's identity without issues // self.GenerateAndWearItem("Lo-Fi Longwave") // do not use, causes server stutters, put hat in pop instead } ::Telefrag <- function() { if (!self.HasBotTag("telebot") && !(self.HasBotTag("telebot_ignorenavfunc"))) return local teletext = NetProps.GetPropString(self, "m_szNetname") + "\nhas teleported in!" if (self.HasBotTag("telebot_w3d")) teletext = "Surprise attack!" if (self.HasBotTag("telebot_w5a")) teletext = "Giant Pyro and Giant Medic\nhave teleported in!" if (self.HasBotAttribute(32768) && !self.HasBotTag("telebot_squadmember")) { SendGlobalGameEvent("show_annotation", { text = teletext worldPosX = self.GetOrigin().x worldPosY = self.GetOrigin().y worldPosZ = self.GetOrigin().z play_sound = "misc/null.wav" show_distance = false show_effect = true lifetime = 5 }) } if (!self.HasBotTag("telebot_bosshelper")) { for (local entity_to_telefrag; entity_to_telefrag = Entities.FindInSphere(entity_to_telefrag, self.GetOrigin(), 100); ) { if (entity_to_telefrag.GetTeam() == 2) { entity_to_telefrag.TakeDamage(1000.0, 64, self) } } } } /////////////////////////////////// TELEPORTERS /////////////////////////////////// /////////////////////////////////// MISCELLANEOUS /////////////////////////////////// ::ControlTeleSpot <- function(action, ent_to_effect) { ent_to_effect.KeyValueFromInt("rendermode", 0) if (action == "enable") { NetProps.SetPropInt(ent_to_effect, "m_nSkin", 1) NetProps.SetPropFloat(ent_to_effect, "m_flPlaybackRate", 1.0) EntFire("skyparticle_" + ent_to_effect.GetName(), "Start") } if (action == "disable") { NetProps.SetPropInt(ent_to_effect, "m_nSkin", 2) NetProps.SetPropFloat(ent_to_effect, "m_flPlaybackRate", 0.0) EntFire("skyparticle_" + ent_to_effect.GetName(), "Stop") } if (NetProps.GetPropBool(objective_resource_entity, "m_bMannVsMachineBetweenWaves") == true) { ent_to_effect.KeyValueFromInt("rendermode", 1) ent_to_effect.KeyValueFromInt("renderamt", 90) EntFire("skyparticle_" + ent_to_effect.GetName(), "Stop") } } ::HaveDefendersBeenPushed_Think <- function() { if (!teleports_active) { if (NetProps.GetPropBool(objective_resource_entity, "m_bMannVsMachineBetweenWaves") == true) { for (local telespot; telespot = Entities.FindByName(telespot, "tele_spot_b*"); ) ::ControlTeleSpot("enable", telespot) for (local telespot; telespot = Entities.FindByName(telespot, "tele_spot_f*"); ) ::ControlTeleSpot("disable", telespot) } else for (local telespot; telespot = Entities.FindByName(telespot, "tele_spot_*"); ) ::ControlTeleSpot("disable", telespot) } if (teleports_active) { if (intel_entity.GetOrigin().y < -300.0) EntFire("nav_avoid_telebot", "Disable") else EntFire("nav_avoid_telebot", "Enable") if (current_bombpath == "left") { if (intel_entity.GetOrigin().y <= 850.0) {::ControlTeleSpot("disable", tele_spot_b4); ::ControlTeleSpot("disable", tele_spot_b5)} else {::ControlTeleSpot("enable", tele_spot_b4); ::ControlTeleSpot("enable", tele_spot_b5)} if (intel_entity.GetOrigin().y <= 100.0) {::ControlTeleSpot("disable", tele_spot_b1); ::ControlTeleSpot("disable", tele_spot_b2); ::ControlTeleSpot("disable", tele_spot_b3); ::ControlTeleSpot("enable", tele_spot_f1); ::ControlTeleSpot("enable", tele_spot_f2); ::ControlTeleSpot("enable", tele_spot_f3)} else {::ControlTeleSpot("enable", tele_spot_b1); ::ControlTeleSpot("enable", tele_spot_b2); ::ControlTeleSpot("enable", tele_spot_b3); ::ControlTeleSpot("disable", tele_spot_f1); ::ControlTeleSpot("disable", tele_spot_f2); ::ControlTeleSpot("disable", tele_spot_f3)} if (intel_entity.GetOrigin().y <= -600.0) ::ControlTeleSpot("enable", tele_spot_f4) else ::ControlTeleSpot("disable", tele_spot_f4) } if (current_bombpath == "right") { if (intel_entity.GetOrigin().y <= 700.0) {::ControlTeleSpot("disable", tele_spot_b1); ::ControlTeleSpot("disable", tele_spot_b2); ::ControlTeleSpot("disable", tele_spot_b3)} else {::ControlTeleSpot("enable", tele_spot_b1); ::ControlTeleSpot("enable", tele_spot_b2); ::ControlTeleSpot("enable", tele_spot_b3)} if (intel_entity.GetOrigin().y <= 0.0) {::ControlTeleSpot("disable", tele_spot_b4); ::ControlTeleSpot("disable", tele_spot_b5); ::ControlTeleSpot("enable", tele_spot_f1); ::ControlTeleSpot("enable", tele_spot_f2); ::ControlTeleSpot("enable", tele_spot_f3)} else {::ControlTeleSpot("enable", tele_spot_b4); ::ControlTeleSpot("enable", tele_spot_b5); ::ControlTeleSpot("disable", tele_spot_f1); ::ControlTeleSpot("disable", tele_spot_f2); ::ControlTeleSpot("disable", tele_spot_f3)} if (intel_entity.GetOrigin().y <= -650.0) ::ControlTeleSpot("enable", tele_spot_f4) else ::ControlTeleSpot("disable", tele_spot_f4) } } teledestination_array.clear() teledestination_array_giant.clear() for (local telespot; telespot = Entities.FindByName(telespot, "tele_spot_*"); ) { if (NetProps.GetPropInt(telespot, "m_nSkin") == 2) continue teledestination_array.append(telespot.GetOrigin()) if (telespot.GetName() == "tele_spot_b1" || telespot.GetName() == "tele_spot_b2" || telespot.GetName() == "tele_spot_b5") continue teledestination_array_giant.append(telespot.GetOrigin()) } return } ::ParentParticleToRocket <- function() // can only parent entities via entfire but entfire is delayed and this really sucks so this has to be done { local particle_id = self.GetName().slice(14) for (local ent; ent = Entities.FindByClassname(ent, "tf_projectile_rocket"); ) { if (ent.GetName().find(particle_id) != null) return } self.Kill() } ::BombCarrierSpawnSpeedUp_Think <- function() { if (NetProps.GetPropBool(objective_resource_entity, "m_bMannVsMachineBetweenWaves") == false) { for (local i = 1; i <= Constants.Server.MAX_PLAYERS; i++) { local player = PlayerInstanceFromIndex(i) if (player == null) continue if (player.GetTeam() != 3) continue if (player.HasItem()) { if (player.InCond(130) && !player.HasBotAttribute(32768)) player.AddCustomAttribute("CARD: move speed bonus", 10, -1) else player.RemoveCustomAttribute("CARD: move speed bonus") if (!bomb_placement_adjusted) { if (current_bombpath == "right") player.Teleport(true, Vector(-1056, 3312, 96), false, QAngle(0, 0, 0), false, Vector(0, 0, 0)) // bots will disobey bomb path if they don't spawn from spawnbot_right bomb_placement_adjusted = true } } } } return } ::SetUpAoEUber <- function() { self.KeyValueFromString("targetname", "aoe_medic_" + aoe_medic_counter) local uber_beam_1 = SpawnEntityFromTable("dispenser_touch_trigger", { targetname = "dispenser_trigger" + aoe_medic_counter origin = self.GetOrigin() spawnflags = 1 }) local uber_beam_2 = SpawnEntityFromTable("mapobj_cart_dispenser", { targetname = "dispenser_mapobj" + aoe_medic_counter origin = self.GetOrigin() TeamNum = 3, spawnflags = 12 touch_trigger = "dispenser_trigger" + aoe_medic_counter }) uber_beam_1.KeyValueFromInt("solid", 2) uber_beam_1.KeyValueFromString("mins", "-250 -250 -250") uber_beam_1.KeyValueFromString("maxs", "250 250 250") EntFire("dispenser_trigger" + aoe_medic_counter, "SetParent", "aoe_medic_" + aoe_medic_counter) // can only parent entities to other entities with valid targetnames EntFire("dispenser_mapobj" + aoe_medic_counter, "SetParent", "aoe_medic_" + aoe_medic_counter) self.AddCond(55) AddThinkToEnt(self, "AoEUber_Think") aoe_medic_counter = aoe_medic_counter + 1 EntFireByHandle(self, "RunScriptCode", "self.KeyValueFromString(`targetname`, null)", 0.1, null, null) // has to be done because custom targetnames persist across bot deaths } ::AoEUber_Think <- function() { if (NetProps.GetPropInt(self, "m_lifeState") != 0) { for (local ent; ent = Entities.FindByName(ent, "dispenser_*"); ) if (ent.GetRootMoveParent() == self) ent.Kill() NetProps.SetPropString(self, "m_iszScriptThinkFunction", "") return } for (local player_to_shield; player_to_shield = Entities.FindByClassnameWithin(player_to_shield, "player", self.GetOrigin(), 250); ) { if (player_to_shield == null) continue if (player_to_shield.GetTeam() == 3 && !player_to_shield.HasBotTag("aoe_medic")) player_to_shield.AddCondEx(52, 0.5, self) } return } ::SetUpBossEnts <- function() { boss_entity = self self.KeyValueFromString("targetname", "firefist_boss") PrecacheSound("misc/rd_finale_beep01.wav") PrecacheSound("ambient/explosions/explode_2.wav") PrecacheSound("vo/mvm/mght/heavy_mvm_m_battlecry06.mp3") local firefist_gun = Entities.CreateByClassname("tf_weapon_rocketlauncher") NetProps.SetPropInt(firefist_gun, "m_AttributeManager.m_Item.m_iItemDefinitionIndex", 18) NetProps.SetPropBool(firefist_gun, "m_AttributeManager.m_Item.m_bInitialized", true) NetProps.SetPropBool(firefist_gun, "m_bValidatedAttachedEntity", true) NetProps.SetPropInt(firefist_gun, "m_nModelIndexOverrides", PrecacheModel("models/weapons/c_models/c_boxing_gloves/c_boxing_gloves_xmas.mdl")) firefist_gun.SetTeam(self.GetTeam()) firefist_gun.AddAttribute("clip size bonus", 9999, -1.0) Entities.DispatchSpawn(firefist_gun) self.Weapon_Equip(firefist_gun) NetProps.GetPropEntityArray(self, "m_hMyWeapons", 0).Destroy() NetProps.SetPropEntityArray(self, "m_hMyWeapons", firefist_gun, 0) self.Weapon_Switch(firefist_gun) local phase2_skybeam = SpawnEntityFromTable("info_particle_system", { targetname = "phase2_skybeam" origin = self.GetOrigin() angles = QAngle(0, 90, 0) start_active = 0, effect_name = "teleporter_mvm_bot_persist" }) EntFire("phase2_skybeam", "SetParent", "firefist_boss") self.AddCond(30) AddThinkToEnt(self, "BossState_Think") SpawnEntityFromTable("point_populator_interface", {targetname = "behavior_control"}) local think_fieryrockets = SpawnEntityFromTable("logic_relay", {targetname = "fieryrockets"}) AddThinkToEnt(think_fieryrockets, "FieryRockets_Think") } ::BossState_Think <- function() { if (NetProps.GetPropInt(self, "m_lifeState") != 0) { EntFire("phase2_skybeam", "Stop") EntFire("phase2_skybeam", "Kill") boss_entity = null EntFireByHandle(self, "RunScriptCode", "self.KeyValueFromString(`targetname`, null)", -1.0, null, null) NetProps.SetPropString(self, "m_iszScriptThinkFunction", "") return } if (self.GetHealth() < 40000.0 && !boss_stage_threshold_reached) { boss_stage_threshold_reached = true self.AddCondEx(71, 5.0, self) self.AddCustomAttribute("dmg taken increased", 0.1, -1) for (local i = 1; i <= Constants.Server.MAX_PLAYERS; i++) { local player = PlayerInstanceFromIndex(i) if (player == null) continue; if (IsPlayerABot(player)) continue; EntFireByHandle(player, "RunScriptCode", "EmitAmbientSoundOn(`misc/rd_finale_beep01.wav`, 300.0, 0, 100, self)", 0.0, null, null) EntFireByHandle(player, "RunScriptCode", "EmitAmbientSoundOn(`misc/rd_finale_beep01.wav`, 300.0, 0, 125, self)", 1.0, null, null) EntFireByHandle(player, "RunScriptCode", "EmitAmbientSoundOn(`misc/rd_finale_beep01.wav`, 300.0, 0, 150, self)", 2.0, null, null) EntFireByHandle(player, "RunScriptCode", "EmitAmbientSoundOn(`misc/rd_finale_beep01.wav`, 300.0, 0, 175, self)", 3.0, null, null) EntFireByHandle(player, "RunScriptCode", "EmitAmbientSoundOn(`misc/rd_finale_beep01.wav`, 300.0, 0, 200, self)", 4.0, null, null) EntFireByHandle(player, "RunScriptCode", "EmitAmbientSoundOn(`misc/rd_finale_beep01.wav`, 300.0, 0, 225, self)", 5.0, null, null) EntFireByHandle(player, "RunScriptCode", "EmitAmbientSoundOn(`ambient/explosions/explode_2.wav`, 300.0, 0, 100, self)", 5.0, null, null) EntFireByHandle(player, "RunScriptCode", "EmitAmbientSoundOn(`vo/mvm/mght/heavy_mvm_m_battlecry06.mp3`, 300.0, 0, 100, self)", 5.0, null, null) player.KeyValueFromString("targetname", "ignite_me") } for (local player_to_hurt; player_to_hurt = Entities.FindInSphere(player_to_hurt, self.GetOrigin(), 450); ) { if (player_to_hurt.GetTeam() == 2) { EntFireByHandle(player_to_hurt, "RunScriptCode", "self.SetOrigin(self.GetOrigin() + Vector(0, 0, 64))", 5.0, null, null) EntFireByHandle(player_to_hurt, "RunScriptCode", "self.TakeDamage(100.0, 64, boss_entity)", 5.0, null, null) } } self.SetMoveType(0, 0) // prevent explosion from pushing boss local phase_change_explosion_push = SpawnEntityFromTable("point_push", { targetname = "phase_change_explosion_push" origin = self.GetOrigin() radius = 450 magnitude = 1250 StartDisabled = 1 spawnflags = 11 }) EntFire("phase_change_explosion_push", "Enable", null, 5.0) EntFire("phase_change_explosion_push", "Disable", null, 5.1) EntFire("phase_change_explosion_push", "Kill", null, 5.2) EntFireByHandle(self, "RunScriptCode", "DispatchParticleEffect(`fireSmoke_Collumn_mvmAcres`, self.GetOrigin(), Vector(0, 90, 0))", 5.0, null, null) EntFireByHandle(self, "RunScriptCode", "self.SetMoveType(2, 0)", 5.1, null, null) EntFireByHandle(self, "RunScriptCode", "self.RemoveCustomAttribute(`dmg taken increased`)", 5.0, null, null) EntFire("behavior_control", "ChangeBotAttributes", "Phase2", 5.0) EntFireByHandle(gamerules_entity, "PlayVO", "mvm/mvm_tele_activate.wav", 7.5, null, null) EntFireByHandle(gamerules_entity, "RunScriptCode", "after_boss_phase_transition = true", 9.0, null, null) EntFire("spawnbot_single_flag", "Enable", null, 9.0) EntFireByHandle(gamerules_entity, "RunScriptCode", "SetIcons(`w5_add`)", 9.0, null, null) EntFire("phase2_skybeam", "Start", null, 9.0) } if (after_boss_phase_transition) { if (Entities.FindByName(null, "phase2_rockets") == null) { phase2_rocket = SpawnEntityFromTable("tf_point_weapon_mimic", { targetname = "phase2_rockets" origin = self.GetOrigin() + Vector(0, 0, 150) angles = QAngle(0, 0, 0) TeamNum = 3 speedmin = 1100 speedmax = 1100 WeaponType = 0 SplashRadius = 250 Damage = 40 crits = 1 }) EntFire("phase2_rockets", "SetParent", "firefist_boss") phase2_rocket.SetOwner(self) } else { phase2_rocket.SetLocalAngles(QAngle(25, RandomInt(-180, 180), 0)) EntFireByHandle(phase2_rocket, "FireOnce", null, -1.0, self, self) } return 0.5 } return } ::FieryRockets_Think <- function() { for (local ent; ent = Entities.FindByClassname(ent, "tf_projectile_rocket"); ) { if (ent.GetOwner() == boss_entity || ent.GetOwner() == phase2_rocket) { ent.ValidateScriptScope() local scope = ent.GetScriptScope() if (!("fixed" in scope)) { scope.fixed <- true firefist_rockets_fired = firefist_rockets_fired + 1 ent.KeyValueFromString("targetname", "rocket" + firefist_rockets_fired) ent.SetModelSimple("models/weapons/w_models/w_drg_ball.mdl") local fireparticle = SpawnEntityFromTable("info_particle_system", { targetname = "proj_particle_" + firefist_rockets_fired origin = ent.GetOrigin() start_active = 1, effect_name = "lava_fireball" }) EntFireByHandle(fireparticle, "SetParent", "rocket" + firefist_rockets_fired, -1.0, null, null) EntFireByHandle(fireparticle, "RunScriptCode", "ParentParticleToRocket()", -1.0, ent, ent) } } } return -1 } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// FUNCTIONS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// DEBUGGING //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// if (debug) { SpawnEntityFromTable("point_worldtext", { textsize = 40 message = "B1" font = 1 orientation = 1 origin = tele_spot_b1.GetOrigin() + Vector(0, 0, 100) rendermode = 3 }) SpawnEntityFromTable("point_worldtext", { textsize = 40 message = "B2" font = 1 orientation = 1 origin = tele_spot_b2.GetOrigin() + Vector(0, 0, 100) rendermode = 3 }) SpawnEntityFromTable("point_worldtext", { textsize = 40 message = "B3" font = 1 orientation = 1 origin = tele_spot_b3.GetOrigin() + Vector(0, 0, 100) rendermode = 3 }) SpawnEntityFromTable("point_worldtext", { textsize = 40 message = "B4" font = 1 orientation = 1 origin = tele_spot_b4.GetOrigin() + Vector(0, 0, 100) rendermode = 3 }) SpawnEntityFromTable("point_worldtext", { textsize = 40 message = "B5" font = 1 orientation = 1 origin = tele_spot_b5.GetOrigin() + Vector(0, 0, 100) rendermode = 3 }) SpawnEntityFromTable("point_worldtext", { textsize = 40 message = "F1" font = 1 orientation = 1 origin = tele_spot_f1.GetOrigin() + Vector(0, 0, 100) rendermode = 3 }) SpawnEntityFromTable("point_worldtext", { textsize = 40 message = "F2" font = 1 orientation = 1 origin = tele_spot_f2.GetOrigin() + Vector(0, 0, 100) rendermode = 3 }) SpawnEntityFromTable("point_worldtext", { textsize = 40 message = "F3" font = 1 orientation = 1 origin = tele_spot_f3.GetOrigin() + Vector(0, 0, 100) rendermode = 3 }) SpawnEntityFromTable("point_worldtext", { textsize = 40 message = "F4" font = 1 orientation = 1 origin = tele_spot_f4.GetOrigin() + Vector(0, 0, 100) rendermode = 3 }) ::CALLBACKS.OnGameEvent_player_say <- function(params) { local player = GetPlayerFromUserID(params.userid) if (params.text == "1") { for (local ent; ent = Entities.FindByName(ent, "nav_avoid_telebot"); ) ClientPrint(null,3, "" + ent) } } for (local i = 1; i <= Constants.Server.MAX_PLAYERS; i++) { local player = PlayerInstanceFromIndex(i) if (NetProps.GetPropString(player, "m_szNetworkIDString") == "[U:1:95064912]") { player.SetHealth(90000) player.SetMoveType(8, 0) player.AddCurrency(10000) // player.EmitSound("MVM.TankExplodes") // EntFireByHandle(player, "SetScriptOverlayMaterial", "airraid_warning_overlay", 0.0, null, null); // EntFireByHandle(player, "SetScriptOverlayMaterial","supplydrop_tele_warning_overlay", 0.0, null, null); // EntFireByHandle(player, "SetScriptOverlayMaterial","supplydrop_crate_warning_overlay", 0.0, null, null); // DispatchParticleEffect("fireSmokeExplosion3", player.GetOrigin() + Vector(-700, 0, 150), Vector(0, 0, 0)) } // ClientPrint(null,3,"current self y:" + player.GetOrigin().y); // EntFireByHandle(player, "SetScriptOverlayMaterial", "", 0.0, null, null); } // EntFireByHandle(gamerules_entity, "RunScriptCode", "AirRaid_Start(1)", 0.0, null, null) // EntFireByHandle(gamerules_entity, "RunScriptCode", "SupplyDropTeles_Start()", 0.0, null, null) // EntFireByHandle(gamerules_entity, "RunScriptCode", "SupplyDropCrates_Start()", 0.0, null, null) } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// DEBUGGING //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// __CollectGameEventCallbacks(::CALLBACKS)