::PEA_GLOBAL <- { debug = ("debug" in PEA) ? PEA.debug : false sigmod = Convars.GetInt("sig_color_console") != null ? true : false countdown_skipped = false strip_romevision_items = false thinkertick = 1 mission = NetProps.GetPropString(Entities.FindByClassname(null, "tf_objective_resource"), "m_iszMvMPopfileName") Wave = NetProps.GetPropInt(Entities.FindByClassname(null, "tf_objective_resource"), "m_nMannVsMachineWaveCount") InSetup = function() { return NetProps.GetPropBool(objective_resource_entity, "m_bMannVsMachineBetweenWaves") == true } moneydrop = Vector() // funcoverrides = // [ // [ // "CBaseEntity", // [ // ["Kill", "LegacyKill"] // ] // ] // ] customfuncs = [ ["CBaseCombatWeapon", ["GetOwner"]], ["CBaseEntity", ["Enable", "Disable", "LegacyKill"]], ["CTFBot", ["IsGrounded", "GetWeapon", "GetWearable", "GetWearableItem", "Zombify", "IsInFieldOfView", "GetWeaponInSlot", "CreateRagdoll" ]], ["CTFPlayer", ["IsGrounded", "GetWeapon", "GetWearable", "GetWearableItem", "IsInFieldOfView", "GetWeaponInSlot", "CreateRagdoll" ]] ] zombieitems = [5617, 5625, 5618, 5620, 5622, 5619, 5624, 5623, 5621] playerlog_limit = 16250 // playerlog_limit = 40 tanks_in_wave = 0 blimps_in_wave = 0 class_integers = ["", "scout", "sniper", "soldier", "demo", "medic", "heavy", "pyro", "spy", "engineer", "civilian"] ignite_player = Entities.CreateByClassname("tf_weapon_flamethrower") action_funcs = [] action_classes = [] active_actions = [] actiontemplate = class { name = null function ClassStart(data) { name = data.name getroottable()[name] = this active_actions.append(this) if ("Start" in this) Start(data) } function ClassEnd() { if ("End" in this) End() getroottable()[name] = false active_actions.remove(active_actions.find(this)) } } GLOBAL_CALLBACKS = { OnGameEvent_recalculate_holidays = function(params) // do cleanup after mission switch { foreach (player in GetAllPlayers(false, false, false)) { player.ValidateScriptScope() if (player.IsFakeClient()) { if (!sigmod) { NetProps.SetPropBool(player, "m_bForcedSkin", false) NetProps.SetPropInt(player, "m_nForcedSkin", 0) NetProps.SetPropInt(player, "m_iPlayerSkinOverride", 0) } local scope = player.GetScriptScope() NetProps.SetPropString(player, "m_iszScriptThinkFunction", "") for (local child = player.FirstMoveChild(); child != null; child = child.NextMovePeer()) { if ("custom_wearable" in child.GetScriptScope()) { EntFireByHandle(child, "Kill", null, -1.0, null, null); continue } child.DisableDraw() continue } foreach (thing in player.GetScriptScope()) { try { thing.GetClassname() } catch (e) { continue } if (!thing.IsPlayer()) thing.Kill() } player.TerminateScriptScope() } } if (GetRoundState() == 3 && NetProps.GetPropString(objective_resource_entity, "m_iszMvMPopfileName") != mission) { if ("MapCleanup" in PEA) ::MapCleanup() for (local ent; ent = Entities.FindByClassname(ent, "entity_sign"); ) ent.Kill() // foreach (entgroup in funcoverrides) { foreach (func in entgroup[1]) getroottable()[entgroup[0]][func] <- function() {} } foreach (entgroup in customfuncs) { foreach (func in entgroup[1]) getroottable()[entgroup[0]][func] <- function() {} } foreach (thing, var in PEA) if (thing in getroottable()) delete getroottable()[thing] if ("PEA_ONETIME" in getroottable()) { foreach (thing, var in PEA_ONETIME) if (thing in getroottable()) delete getroottable()[thing] } for (local i = 1; i <= Constants.Server.MAX_PLAYERS; i++) { local player = PlayerInstanceFromIndex(i) if (player == null) continue if (player.GetScriptScope() != null) { foreach (thing in player.GetScriptScope()) { try { thing.GetClassname() } catch (e) { continue } if (!thing.IsPlayer()) thing.Kill() } } player.TerminateScriptScope() } delete ::PEA delete ::PEA_GLOBAL_ONETIME if ("PEA_ONETIME" in getroottable()) delete ::PEA_ONETIME return } if (strip_romevision_items) { for (local ent; ent = Entities.FindByModel(ent, "models/bots/boss_bot/carrier.mdl"); ) { NetProps.SetPropIntArray(ent, "m_nModelIndexOverrides", PrecacheModel("models/bots/boss_bot/carrier.mdl"), 0) NetProps.SetPropIntArray(ent, "m_nModelIndexOverrides", PrecacheModel("models/bots/boss_bot/carrier.mdl"), 1) NetProps.SetPropIntArray(ent, "m_nModelIndexOverrides", PrecacheModel("models/bots/boss_bot/carrier.mdl"), 2) NetProps.SetPropIntArray(ent, "m_nModelIndexOverrides", PrecacheModel("models/bots/boss_bot/carrier.mdl"), 3) } for (local ent; ent = Entities.FindByModel(ent, "models/bots/boss_bot/carrier_parts.mdl"); ) { NetProps.SetPropIntArray(ent, "m_nModelIndexOverrides", PrecacheModel("models/bots/boss_bot/carrier_parts.mdl"), 0) NetProps.SetPropIntArray(ent, "m_nModelIndexOverrides", PrecacheModel("models/bots/boss_bot/carrier_parts.mdl"), 1) NetProps.SetPropIntArray(ent, "m_nModelIndexOverrides", PrecacheModel("models/bots/boss_bot/carrier_parts.mdl"), 2) NetProps.SetPropIntArray(ent, "m_nModelIndexOverrides", PrecacheModel("models/bots/boss_bot/carrier_parts.mdl"), 3) } } } OnGameEvent_player_spawn = function(params) { local bot = GetPlayerFromUserID(params.userid) if (!bot.IsFakeClient()) return EntFireByHandle(bot, "CallScriptFunction", "GlobalBotTagCheck", -1.0, null, null) } OnGameEvent_player_death = function(params) { local dead_player = GetPlayerFromUserID(params.userid) if (dead_player.IsFakeClient()) { for (local cash; cash = Entities.FindByClassname(cash, "item_currencypack_custom"); ) AddThinkToEnt(cash, "ImprovedCashCollection_Think") local projectiles_leftbehind = false for (local ent; ent = Entities.FindByClassname(ent, "tf_projectile_*"); ) { if (ent.GetOwner() == dead_player || NetProps.GetPropEntity(ent, "m_hThrower") == dead_player) { projectiles_leftbehind = true; break } } EntFireByHandle(dead_player, "RunScriptCode", "self.SetUseBossHealthBar(false)", -1.0, null, null) for (local child = dead_player.FirstMoveChild(); child != null; child = child.NextMovePeer()) { if (child.GetClassname() == "tf_wearable" && child.GetScriptScope() != null) EntFireByHandle(child, "Kill", null, 0.1, null, null) // needs extra delay to allow wearables to remain on ragdolls } foreach (thing in dead_player.GetScriptScope()) { try { thing.GetClassname() } catch (e) { continue } if (!thing.IsPlayer()) thing.Kill() } if (!projectiles_leftbehind) EntFireByHandle(dead_player, "RunScriptCode", "self.ForceChangeTeam(1, true)", 0.1, null, null) NetProps.SetPropString(dead_player, "m_iszScriptThinkFunction", "") dead_player.TerminateScriptScope() } } OnGameEvent_mvm_begin_wave = function(params) { if (firstload) NetProps.SetPropFloat(gamerules_entity, "m_flRestartRoundTime", Time()) HideIcon("noicon") if (WaveHasIcon("blimp2_lite")) UnhideIcon("blimp2_lite", 8) } OnGameEvent_mvm_wave_complete = function(params) { wavewon = true } } StartAction = function(action, data) { if (getroottable()[action]) return data.name <- action getroottable()[action] = action_classes[action_funcs.find(action)]() getroottable()[action].ClassStart(data) } CreateAction = function(classobj, funcname) { action_classes.append(classobj) action_funcs.append(funcname) } CustomAnnotation = function() { if (!("annotdata" in this)) return local unique = UniqueString() SendGlobalGameEvent("show_annotation", { id = unique text = annotdata.a_txt follow_entindex = annotdata.a_fol.entindex() visibilityBitfield = (1 << self.entindex()) play_sound = "misc/null.wav" show_distance = false show_effect = false lifetime = annotdata.a_lif }) } BotTutorial = function(id, txt, dur = 7.5) { local MakeGlow = function() { if ("tutglow" in this) return tutglow <- AttachGlow("125 168 196 255") tutglow.ValidateScriptScope() tutglow.GetScriptScope().curglowcolor <- "125 168 196 255" tutglow.GetScriptScope().FlashThink <- function() { if (curglowcolor == "125 168 196 255") curglowcolor = "184 56 59 255" else curglowcolor = "125 168 196 255" this.AcceptInput("SetGlowColor", curglowcolor, null, null) return 0.5 } AddThinkToEnt(tutglow, "FlashThink") EntFireByHandle(tutglow, "Kill", null, 7.5, null, null) } foreach (player in GetAllPlayers(2)) { if (TraceLine(this.EyePosition(), player.EyePosition(), this) == 1.0) { if (!(id in player.GetScriptScope())) { MakeGlow() player.GetScriptScope()[id] <- true player.GetScriptScope().annotdata <- { a_txt = txt a_fol = tutglow a_lif = dur } EntFireByHandle(player, "CallScriptFunction", "CustomAnnotation", 0.03, null, null) } } } } EnableSpawn = function(...) { foreach (name in vargv) Entities.FindByName(null, "spawnbot_" + name).Enable() } DisableSpawn = function(...) { foreach (name in vargv) Entities.FindByName(null, "spawnbot_" + name).Disable() } ShovePlayer = function(player, radius) { local vradius = Vector(radius, radius, radius) local selfmins = self.GetBoundingMins() + self.GetOrigin() - vradius local selfmaxs = self.GetBoundingMaxs() + self.GetOrigin() + vradius local playermins = player.GetBoundingMins() + player.GetOrigin() local playermaxs = player.GetBoundingMaxs() + player.GetOrigin() if (playermins.x > selfmaxs.x || playermaxs.x < selfmins.x || playermins.y > selfmaxs.y || playermaxs.y < selfmins.y || playermaxs.y < selfmins.y || playermaxs.y < selfmins.y || playermaxs.y < selfmins.y || playermins.z > selfmaxs.z || playermaxs.z < selfmins.z) return local pushforce = player.GetOrigin() - self.GetOrigin() pushforce.Norm() pushforce.z = 1.0 pushforce = pushforce * 270 if (player.IsGrounded()) player.SetOrigin(player.GetOrigin() + Vector(0, 0, 24)) player.RemoveFlag(1) player.AddCond(115) player.ApplyAbsVelocityImpulse(pushforce) } PrecacheArray = function(array) { foreach (thing in array) { if (thing.find(".mdl") != null) PrecacheModel(thing) else PrecacheSound(thing) } } NormalizeAngle = function(ang) { foreach (k in ang) { k %= 360.0 if (k > 180.0) k -= 360.0 else if (k < -180.0) k += 360.0 } return ang } VectorAngles = function(forward) { local yaw, pitch; if (forward.y == 0.0 && forward.x == 0.0) { yaw = 0.0 if (forward.z > 0.0) pitch = 270.0 else pitch = 90.0 } else { yaw = (atan2(forward.y, forward.x) * 180.0 / Constants.Math.Pi) if (yaw < 0.0) yaw += 360.0 pitch = (atan2(-forward.z, forward.Length2D()) * 180.0 / Constants.Math.Pi) if (pitch < 0.0) pitch += 360.0 } return QAngle(pitch, yaw, 0.0); } GetAllPlayers = function(team = false, radius = false, alive = true) { local resultarray = [] if (!(!radius)) { for (local player; player = Entities.FindByClassnameWithin(player, "player", radius[0], radius[1]); ) { if (!(!team)) { if (player.GetTeam() != team) continue } if (alive) { if (!player.IsAlive()) continue } resultarray.append(player) } } else { local maxclients = MaxClients().tointeger() for (local i = 1; i <= maxclients; i++) { local player = PlayerInstanceFromIndex(i) if (player == null) continue if (!(!team)) { if (player.GetTeam() != team) continue } if (alive) { if (!player.IsAlive()) continue } resultarray.append(player) } } return resultarray } SpawnNavBrush = function(name, pos, xyz1, xyz2, tagname = false) { if (!tagname) tagname = name.slice(4) local navbrush = SpawnEntityFromTable("func_nav_avoid", { targetname = name, origin = pos, tags = tagname }) navbrush.KeyValueFromInt("solid", 2) navbrush.KeyValueFromString("mins", xyz1) navbrush.KeyValueFromString("maxs", xyz2) local navbrush2 = SpawnEntityFromTable("func_nav_avoid", { targetname = name, origin = pos, tags = tagname }) // do it twice just to make sure navbrush2.KeyValueFromInt("solid", 2) navbrush2.KeyValueFromString("mins", xyz1) navbrush2.KeyValueFromString("maxs", xyz2) } SnapVectorToGround = function(pos, offset = false) { local tracetable = { start = pos end = pos - Vector(0, 0, 5000) mask = -1 } TraceLineEx(tracetable) if (!offset) return tracetable.pos else return (tracetable.pos + Vector(0, 0, offset)) } CreatePathHologram = function(where, angle) { local projector = SpawnEntityFromTable("prop_dynamic", { origin = SnapVectorToGround(where) model = "models/props_mvm/hologram_projector.mdl" shadowcastdist = 0 }) local hologram = SpawnEntityFromTable("prop_dynamic", { origin = SnapVectorToGround(where, 5.0) angles = angle model = "models/props_mvm/robot_hologram.mdl" rendercolor = "138 187 247" disableshadows = 1 }) } GiveNavAvoidToNavArea = function(name, area, tag = "", height = 500.0) { // local mins = (0 - (area.GetSizeX() / 2.0)).tostring() + " " + (0 - (area.GetSizeY() / 2.0)).tostring() + " " + (0 - (height / 2.0)).tostring() // local maxs = (area.GetSizeX() / 2.0).tostring() + " " + (area.GetSizeY() / 2.0).tostring() + " " + (height / 2.0).tostring() local avoid = SpawnEntityFromTable("func_nav_avoid", { origin = area.GetCenter() tags = tag }) avoid.KeyValueFromInt("solid", 2) avoid.KeyValueFromString("mins", "-1 -1 -1") avoid.KeyValueFromString("maxs", "1 1 1") } // ChangeNavBrushTags = function(entlist, input, type = 0) // { // local fixedlist = [] // local brushlist = [] // for (local ent; ent = Entities.FindB // local method = (typeof(item[0]) == "string") ? 0 : 1 // switch (method) // { // case 0: // { // fixedlist.append(Entities.FindByName(null, item)); break // } // case 1: // { // for (local ent; ent = Entities.FindByName(ent, "func_nav_*"); ) // { // if (NetProps.GetPropInt(ent, "m_iHammerID") == entity) fixedlist.append(ent) // } // break // } // } // foreach (item in entlist) // { // } // switch (type) // 0 = append input to existing tags, 1 = overwrite tag list with input // { // case 0: { NetProps.SetPropString(entity, "m_iszTags", NetProps.GetPropString(ent, "m_iszTags") + " " + input); break } // case 1: { NetProps.SetPropString(entity, "m_iszTags", input); break } // } // } ConnectNavAreas = function(navarray) { foreach (pair in navarray) NavMesh.GetNavAreaByID(pair[0]).ConnectTo(NavMesh.GetNavAreaByID(pair[1]), NavMesh.GetNavAreaByID(pair[0]).ComputeDirection(NavMesh.GetNavAreaByID(pair[1]).GetCenter())) } DisconnectNavAreas = function(navarray) { foreach (pair in navarray) NavMesh.GetNavAreaByID(pair[0]).Disconnect(NavMesh.GetNavAreaByID(pair[1])) } UnblockNavAreas = function(navarray) { foreach (nav in navarray) NavMesh.GetNavAreaByID(nav).UnblockArea() } EmitGlobalSound = function(sound) { SendGlobalGameEvent("teamplay_broadcast_audio", { team = -1, sound = sound additional_flags = 0 player = -1 }) } StopGlobalSound = function(sound) { SendGlobalGameEvent("teamplay_broadcast_audio", { team = -1, sound = sound, additional_flags = 4, player = -1 }) } ImprovedCashCollection_Think = function() { try // tends to throw harmless errors about collecting player becoming null { for (local player_to_collect; player_to_collect = Entities.FindByClassnameWithin(player_to_collect, "player", self.GetOrigin(), 288); ) { if (player_to_collect != null && player_to_collect.GetTeam() == 2 && !player_to_collect.IsFakeClient() && NetProps.GetPropInt(player_to_collect, "m_lifeState") == 0 && NetProps.GetPropInt(player_to_collect, "m_PlayerClass") == Constants.ETFClass.TF_CLASS_SCOUT) { self.Teleport(true, player_to_collect.GetOrigin(), false, QAngle(0, 0, 0), false, Vector(0, 0, 0)) self.DisableDraw() return 1 // stop reiterating after the teleport } } } catch (e) { return } return -1 } AttachGlow = function(color) { self.KeyValueFromString("targetname", "glow_target") glow <- SpawnEntityFromTable("tf_glow", { origin = self.EyePosition() target = "glow_target" GlowColor = color }) self.KeyValueFromString("targetname", "") glow.AcceptInput("SetParent", "!activator", self, self) // parenting a tf_glow fixes issues where it doesn't render if it's too far from you return glow } Clamp = function(val, minVal, maxVal) { if (maxVal < minVal) return maxVal else if (val < minVal) return minVal else if (val > maxVal) return maxVal else return val } RemapValClamped = function(val, A, B, C, D) { if (A == B) return ((val >= B) ? D : C) local cVal = (val - A) / (B - A) cVal = Clamp(cVal, 0.0, 1.0) return (C + (D - C) * cVal) } SetDestroyCallback = function(entity, callback) // credit goes to ficool2 for function code { entity.ValidateScriptScope() local scope = entity.GetScriptScope() scope.setdelegate ( {}.setdelegate ( { parent = scope.getdelegate() id = entity.GetScriptId() index = entity.entindex() callback = callback _get = function(keytofetch) { return parent[keytofetch] } _delslot = function(keytodelete) { if (keytodelete == id) { entity = EntIndexToHScript(index) local scope = entity.GetScriptScope() scope.self <- entity callback.pcall(scope) } delete parent[keytodelete] } } ) ) } CameraFix = function() // credit goes to ficool2 for function code { if (!("SetInputHook" in getroottable())) { ::_PostInputScope <- null; ::_PostInputFunc <- null; ::SetInputHook <- function(entity, input, pre_func, post_func) { entity.ValidateScriptScope(); local scope = entity.GetScriptScope(); if (post_func) { local wrapper_func = function() { _PostInputScope = scope; _PostInputFunc = post_func; if (pre_func) return pre_func.call(scope); return true; }; scope["Input" + input] <- wrapper_func; scope["Input" + input.tolower()] <- wrapper_func; } else if (pre_func) { scope["Input" + input] <- pre_func; scope["Input" + input.tolower()] <- pre_func; } } getroottable().setdelegate( { _delslot = function(k) { if (_PostInputScope && k == "activator" && "activator" in this) { _PostInputFunc.call(_PostInputScope); _PostInputFunc = null; } rawdelete(k); } }); } if (!("CameraFixer" in getroottable())) { ::_CameraFixLifestate <- 0; ::CameraFixPre <- function() { if (activator) { _CameraFixLifestate = NetProps.GetPropInt(activator, "m_lifeState"); NetProps.SetPropInt(activator, "m_lifeState", 0); NetProps.SetPropEntity(self, "m_hPlayer", activator); } return true; } ::CameraFixPost <- function() { if (activator) { NetProps.SetPropInt(activator, "m_lifeState", _CameraFixLifestate); NetProps.SetPropInt(activator, "m_takedamage", 2); } } ::CameraDisableAll <- function() { for (local player; player = Entities.FindByClassname(player, "player");) EntFireByHandle(CameraFixer, "Disable", "", -1, player, player); EntFireByHandle(CameraFixer, "Kill", "", 1, null, null); } ::CameraFixer <- Entities.CreateByClassname("point_viewcontrol"); ::CameraFixer.KeyValueFromString("classname", "camera_fixer"); ::CameraFixer.AddEFlags(1); SetInputHook(CameraFixer, "Disable", CameraFixPre, CameraFixPost); SpawnEntityFromTable("logic_eventlistener", { classname = "move_rope", eventname = "teamplay_round_start", IsEnabled = true, OnEventFired = "worldspawn,CallScriptFunction,CameraDisableAll,-1,-1", }); SpawnEntityFromTable("logic_eventlistener", { classname = "move_rope", eventname = "recalculate_holidays", IsEnabled = true, OnEventFired = "worldspawn,RunScriptCode,if (GetRoundState() == 8) CameraDisableAll(),0.1,-1", }); } function Precache() { SetInputHook(self, "Disable", CameraFixPre, CameraFixPost); } } IsInside = function(vector, min, max) { return vector.x >= min.x && vector.x <= max.x && vector.y >= min.y && vector.y <= max.y && vector.z >= min.z && vector.z <= max.z } FreeUpRobotSlots = function(amount) { // collect all bots first to determine who deserves death local slotstoclear local botarray = [] local deathpriority = [] for (local i = 1; i <= MaxClients().tointeger(); i++) { local player = PlayerInstanceFromIndex(i) if (player == null) continue if (player.GetTeam() != 3) continue if (!player.IsAlive()) continue botarray.append(player) ClientPrint(null,3,"" + NetProps.GetPropString(player, "m_szNetname") + " " + player.GetPlayerClass()) } slotstoclear = (botarray.len() + amount) - 22 if (slotstoclear < 0) return // no need to free up slots when there is still room botarray = botarray.filter(function(index, bot) { return (!bot.IsMiniBoss() && bot != null) }) ClientPrint(null,3,"origslotstoclear: " + slotstoclear) foreach (bot in botarray) { if (bot.IsOnAnyMission()) deathpriority.append(bot) } // prioritize mission support foreach (bot in botarray) { if (!bot.IsOnAnyMission()) deathpriority.append(bot) } for (local i = slotstoclear; i > 0; i--) { ClientPrint(null,3,"slotstoclear: " + i) if (i > 0) // destroy a random robot to make room for another { deathpriority[0].Teleport(true, Vector(0, 0, -3000), false, QAngle(), false, Vector()) deathpriority[0].TakeDamage(10000.0, 64, null) deathpriority[0].ForceChangeTeam(1, true) ClientPrint(null,3,"destroyed: " + NetProps.GetPropString(deathpriority[0], "m_szNetname") + " to make room") deathpriority.remove(0) } } } DisableRomevision = function() { for (local ent; ent = Entities.FindByModel(ent, "models/bots/boss_bot/carrier.mdl"); ) { NetProps.SetPropIntArray(ent, "m_nModelIndexOverrides", PrecacheModel("models/bots/boss_bot/carrier.mdl"), 0) NetProps.SetPropIntArray(ent, "m_nModelIndexOverrides", PrecacheModel("models/bots/boss_bot/carrier.mdl"), 1) NetProps.SetPropIntArray(ent, "m_nModelIndexOverrides", PrecacheModel("models/bots/boss_bot/carrier.mdl"), 2) NetProps.SetPropIntArray(ent, "m_nModelIndexOverrides", PrecacheModel("models/bots/boss_bot/carrier.mdl"), 3) } for (local ent; ent = Entities.FindByModel(ent, "models/bots/boss_bot/carrier_parts.mdl"); ) { NetProps.SetPropIntArray(ent, "m_nModelIndexOverrides", PrecacheModel("models/bots/boss_bot/carrier_parts.mdl"), 0) NetProps.SetPropIntArray(ent, "m_nModelIndexOverrides", PrecacheModel("models/bots/boss_bot/carrier_parts.mdl"), 1) NetProps.SetPropIntArray(ent, "m_nModelIndexOverrides", PrecacheModel("models/bots/boss_bot/carrier_parts.mdl"), 2) NetProps.SetPropIntArray(ent, "m_nModelIndexOverrides", PrecacheModel("models/bots/boss_bot/carrier_parts.mdl"), 3) } strip_romevision_items = true } GlobalBotTagCheck = function() { if (!sigmod) { if (NetProps.GetPropBool(self, "m_bForcedSkin")) { NetProps.SetPropBool(self, "m_bForcedSkin", false) NetProps.SetPropInt(self, "m_nForcedSkin", 0) NetProps.SetPropInt(self, "m_iPlayerSkinOverride", 0) } } if (strip_romevision_items) { for (local child = self.FirstMoveChild(); child != null; child = child.NextMovePeer()) { if (child.GetClassname() == "tf_wearable" && child.GetModelName().find("tw_") != null) EntFireByHandle(child, "RunScriptCode", "self.DisableDraw()", -1.0, null, null) } } if (self.HasBotTag("disband_squad")) self.DisbandCurrentSquad() if (self.HasBotTag("leave_squad")) self.LeaveSquad() if (self.HasBotTag("shuffle")) BotShuffler() if (self.HasBotTag("blimp")) AddThinkToEnt(self, "BlimpSetup_Think") if (self.HasBotTag("money")) { self.Teleport(true, moneydrop, false, QAngle(), false, Vector()) self.TakeDamage(10000.0, 64, null) self.ForceChangeTeam(1, true) } } BombCarrierSpawnSpeedUp_Think = function() { // if (thinkertick % 7 != 0) return if (NetProps.GetPropBool(objective_resource_entity, "m_bMannVsMachineBetweenWaves")) return foreach (player in GetAllPlayers(3)) { if (player.HasItem()) { if (player.InCond(51) && !player.IsMiniBoss() && NetProps.GetPropFloat(player, "m_flMaxspeed") < 320.0) NetProps.SetPropFloat(player, "m_flMaxspeed", 320.0) // player.AddCustomAttribute("CARD: move speed bonus", 10, -1) // else player.RemoveCustomAttribute("CARD: move speed bonus") if (GetMapName() == "mvm_powerplant_rc1") { 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 } } } } } IsFlanker = function() { local tagtable = {} self.GetAllBotTags(tagtable) foreach (index, tag in tagtable) { if (tag.find("flank") != null) return true } return false } BotShuffler = function() { if (self.HasBotTag("shuffle")) { self.RemoveBotTag("shuffle") local maxchance = 0 local order_array = [] local name_array = [] local wavespawn foreach (tag, entries in shuffle_wavespawn_table) { if (!self.HasBotTag(tag)) continue for (local i = 0; i <= entries.amounts.len() - 1; i++) { maxchance = maxchance + entries.amounts[i] order_array.append(entries.amounts[i]) } for (local i = 0; i <= entries.names.len() - 1; i++) name_array.append(entries.names[i]) wavespawn = tag } for (local i = 1; i <= order_array.len() - 1; i++) order_array[i] = order_array[i - 1] + order_array[i] local choice = RandomInt(1, maxchance) for (local i = 0; i <= order_array.len() - 1; i++) { if (choice <= order_array[i]) { BotTransformer(name_array[i]) foreach (tag, entries in shuffle_wavespawn_table) { if (tag != wavespawn) continue entries.amounts[i]-- } break } } } } TankFinder_Think = function() { for (local tank; tank = Entities.FindByName(tank, "tankboss"); ) { if (strip_romevision_items) { if (tank.GetModelName() == "models/bots/boss_bot/boss_tank.mdl") NetProps.SetPropIntArray(tank, "m_nModelIndexOverrides", PrecacheModel("models/bots/boss_bot/boss_tank.mdl"), 3) if (tank.GetModelName() == "models/bots/boss_bot/boss_tank_damage1.mdl") NetProps.SetPropIntArray(tank, "m_nModelIndexOverrides", PrecacheModel("models/bots/boss_bot/boss_tank_damage1.mdl"), 3) if (tank.GetModelName() == "models/bots/boss_bot/boss_tank_damage2.mdl") NetProps.SetPropIntArray(tank, "m_nModelIndexOverrides", PrecacheModel("models/bots/boss_bot/boss_tank_damage2.mdl"), 3) if (tank.GetModelName() == "models/bots/boss_bot/boss_tank_damage3.mdl") NetProps.SetPropIntArray(tank, "m_nModelIndexOverrides", PrecacheModel("models/bots/boss_bot/boss_tank_damage3.mdl"), 3) local child_array = [] for (local child = tank.FirstMoveChild(); child != null; child = child.NextMovePeer()) child_array.append(child) foreach (child in child_array) NetProps.SetPropIntArray(child, "m_nModelIndexOverrides", NetProps.GetPropIntArray(child, "m_nModelIndexOverrides", 0), 3) } if (EntityOutputs.HasAction(tank, "OnKilled")) continue else EntityOutputs.AddOutput(tank, "OnKilled", "gamerules", "CallScriptFunction", "CleanUpTank", -1.0, -1.0) } // for (local blimp; blimp = Entities.FindByName(blimp, "blimpboss"); ) // { // if (blimp.GetScriptScope() != null) continue // else SetUpBlimp(blimp) // } } CleanUpTank = function() { tanks_in_wave = tanks_in_wave - 1 for (local cash; cash = Entities.FindByClassname(cash, "item_currencypack_custom"); ) AddThinkToEnt(cash, "ImprovedCashCollection_Think") } WaveHasIcon = function(name) { for (local i = 0; i <= 11; i++) { if (NetProps.GetPropStringArray(objective_resource_entity, "m_iszMannVsMachineWaveClassNames.", i) == name) return true if (NetProps.GetPropStringArray(objective_resource_entity, "m_iszMannVsMachineWaveClassNames2.", i) == name) return true } return false } GetIconType = function(name) { for (local i = 0; i <= 11; i++) { if (NetProps.GetPropStringArray(objective_resource_entity, "m_iszMannVsMachineWaveClassNames.", i) == name) return NetProps.GetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassFlags.", i) if (NetProps.GetPropStringArray(objective_resource_entity, "m_iszMannVsMachineWaveClassNames2.", i) == name) return NetProps.GetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassFlags2.", i) } } GetIconCount = function(name) { for (local i = 0; i <= 11; i++) { if (NetProps.GetPropStringArray(objective_resource_entity, "m_iszMannVsMachineWaveClassNames.", i) == name) return NetProps.GetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassCounts.", i) if (NetProps.GetPropStringArray(objective_resource_entity, "m_iszMannVsMachineWaveClassNames2.", i) == name) return NetProps.GetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassCounts2.", i) } } GetTotalEnemyCount = function() { return NetProps.GetPropInt(objective_resource_entity, "m_nMannVsMachineWaveEnemyCount") } SetTotalEnemyCount = function(amount) { NetProps.SetPropInt(objective_resource_entity, "m_nMannVsMachineWaveEnemyCount", amount) } HideIcon = function(name) // IMPORTANT: adding the dot to netprop names here will fix issues where the third element in the array is inaccessible! { for (local i = 0; i <= 11; i++) { if (NetProps.GetPropStringArray(objective_resource_entity, "m_iszMannVsMachineWaveClassNames.", i) == name) { if (GetIconType(name) == 1) SetTotalEnemyCount(GetTotalEnemyCount() - GetIconCount(name)) NetProps.SetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassFlags.", 0, i) } if (NetProps.GetPropStringArray(objective_resource_entity, "m_iszMannVsMachineWaveClassNames2.", i) == name) { if (GetIconType(name) == 1) SetTotalEnemyCount(GetTotalEnemyCount() - GetIconCount(name)) NetProps.SetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassFlags2.", 0, i) } } } UnhideIcon = function(name, flag) { for (local i = 0; i <= 11; i++) { if (NetProps.GetPropStringArray(objective_resource_entity, "m_iszMannVsMachineWaveClassNames.", i) == name) NetProps.SetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassFlags.", flag, i) if (NetProps.GetPropStringArray(objective_resource_entity, "m_iszMannVsMachineWaveClassNames2.", i) == name) NetProps.SetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassFlags2.", flag, i) } } AddIcon = function(name, flag, amount) { for (local i = 11; i >= 0; i--) { if (NetProps.GetPropStringArray(objective_resource_entity, "m_iszMannVsMachineWaveClassNames2.", i) == "") { NetProps.SetPropStringArray(objective_resource_entity, "m_iszMannVsMachineWaveClassNames2.", name, i) NetProps.SetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassFlags2.", flag, i) NetProps.SetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassCounts2.", amount, i) break } if (NetProps.GetPropStringArray(objective_resource_entity, "m_iszMannVsMachineWaveClassNames.", i) == "") { NetProps.SetPropStringArray(objective_resource_entity, "m_iszMannVsMachineWaveClassNames.", name, i) NetProps.SetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassFlags.", flag, i) NetProps.SetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassCounts.", amount, i) break } } } AddToIcon = function (name, amount, changetotalcount = true) { for (local i = 0; i <= 11; i++) { local count = NetProps.GetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassCounts.", i) if (NetProps.GetPropStringArray(objective_resource_entity, "m_iszMannVsMachineWaveClassNames.", i) == name) { // if ((GetIconType(name) & 1) > 0) SetTotalEnemyCount(GetTotalEnemyCount() + amount) if (changetotalcount) SetTotalEnemyCount(GetTotalEnemyCount() + amount) NetProps.SetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassCounts.", count + amount, i) } if (NetProps.GetPropStringArray(objective_resource_entity, "m_iszMannVsMachineWaveClassNames2.", i) == name) { // if ((GetIconType(name) & 1) > 0) SetTotalEnemyCount(GetTotalEnemyCount() + amount) if (changetotalcount) SetTotalEnemyCount(GetTotalEnemyCount() + amount) NetProps.SetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassCounts2.", count + amount, i) } } // local totalcount = NetProps.GetPropInt(objective_resource_entity, "m_nMannVsMachineWaveEnemyCount") // NetProps.SetPropInt(objective_resource_entity, "m_nMannVsMachineWaveEnemyCount", totalcount + amount) } HideErrors = function() { ClientPrint(null,3,"\x07FF3F3FThe errors about missing spawn entities are harmless, please ignore them.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n") if ("MissionInitMessage" in PEA) MissionInitMessage() firstload = false } ConvertTankIconsToBlimp = function(convertall, amount = 1) { if (convertall) { for (local i = 0; i <= 11; i++) { if (NetProps.GetPropStringArray(objective_resource_entity, "m_iszMannVsMachineWaveClassNames", i) == "tank") { NetProps.SetPropStringArray(objective_resource_entity, "m_iszMannVsMachineWaveClassNames", "blimp2_lite", i) blimps_in_wave = NetProps.GetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassCounts", i) } if (NetProps.GetPropStringArray(objective_resource_entity, "m_iszMannVsMachineWaveClassNames2", i) == "tank") { NetProps.SetPropStringArray(objective_resource_entity, "m_iszMannVsMachineWaveClassNames2", "blimp2_lite", i) blimps_in_wave = NetProps.GetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassCounts2", i) } } } else { for (local i = 0; i <= 11; i++) { if (NetProps.GetPropStringArray(objective_resource_entity, "m_iszMannVsMachineWaveClassNames", i) == "blimp2_lite") { NetProps.SetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassFlags", 9, i) NetProps.SetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassCounts", amount, i) blimps_in_wave = NetProps.GetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassCounts", i) } if (NetProps.GetPropStringArray(objective_resource_entity, "m_iszMannVsMachineWaveClassNames2", i) == "blimp2_lite") { NetProps.SetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassFlags2", 9, i) NetProps.SetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassCounts2", amount, i) blimps_in_wave = NetProps.GetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassCounts2", i) } if (NetProps.GetPropStringArray(objective_resource_entity, "m_iszMannVsMachineWaveClassNames", i) == "tank") { NetProps.SetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassCounts", NetProps.GetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassCounts", i) - amount, i) tanks_in_wave = NetProps.GetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassCounts", i) } if (NetProps.GetPropStringArray(objective_resource_entity, "m_iszMannVsMachineWaveClassNames2", i) == "tank") { NetProps.SetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassCounts2", NetProps.GetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassCounts2", i) - amount, i) tanks_in_wave = NetProps.GetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassCounts2", i) } } } } InstantReady_Think = function() { if (NetProps.GetPropBoolArray(gamerules_entity, "m_bPlayerReady", 1) && !countdown_skipped) { NetProps.SetPropFloat(gamerules_entity, "m_flRestartRoundTime", Time()) countdown_skipped = true } } ThinksTable = {} GlobalThinker = function() { thinkertick++ foreach (func in ThinksTable) func() foreach (action in active_actions) action.Update() return -1 } AssignThinkToThinksTable = function(think) { if (!(think in getroottable()["ThinksTable"])) getroottable()["ThinksTable"][think] <- getroottable()[think] } RemoveThinkFromThinksTable = function(think) { if (think in getroottable()["ThinksTable"]) delete getroottable()["ThinksTable"][think] } BlimpSetup_Think = function() { local scope = self.GetScriptScope() if (!("train" in scope)) { self.SetMoveType(0, 0) scope.train <- SpawnEntityFromTable("func_tracktrain", { targetname = "blimp_train" target = "blimp_path1" startspeed = 75 speed = 75 origin = Entities.FindByName(null, "blimp_path1").GetOrigin() orientationtype = 1 spawnflags = 136 volume = 10 model = "*2" rendermode = 1 renderamt = 0 solid = 0 }) scope.blimp <- SpawnEntityFromTable("base_boss", { targetname = "blimpboss" origin = train.GetOrigin() model = "models/bots/boss_bot/boss_blimp.mdl" skin = 1 teamnum = 3 solid = 6 health = 50000 + self.GetHealth() }) blimp.ResetSequence(2) if (sigmod) blimp.SetPlaybackRate(0.015) NetProps.SetPropInt(blimp, "m_bloodColor", -1.0) train.ValidateScriptScope() train.GetScriptScope().parented_blimp <- blimp blimp.ValidateScriptScope() blimp.GetScriptScope().pathtrain <- train AttachGlow.call(blimp.GetScriptScope(), "125 168 196 255") EmitGlobalSound("MVM.TankStart") EmitGlobalSound("Announcer.MVM_Tank_Alert_Spawn") blimp.SetModelScale(("blimp_scale" in PEA) ? blimp_scale : 1, -1) AddThinkToEnt(blimp, "Blimp_Think") scope.blimpcallbacks <- { OnGameEvent_player_death = function(params) { local dead_player = GetPlayerFromUserID(params.userid) if (dead_player == self) { moneydrop = blimp.GetOrigin() DispatchParticleEffect("explosionTrail_seeds_mvm", blimp.GetOrigin(), Vector(0, 90, 0)) DispatchParticleEffect("fluidSmokeExpl_ring_mvm", blimp.GetOrigin(), Vector(0, 90, 0)) ScreenShake(blimp.GetOrigin(), 25.0, 5.0, 5.0, 1000.0, 0, true) EmitGlobalSound("MVM.TankExplodes") EmitGlobalSound("MVM.TankEnd") EmitGlobalSound("Announcer.MVM_General_Destruction") AddToIcon("blimp2_lite", -1) delete blimpcallbacks } } } foreach (name, callback in blimpcallbacks) blimpcallbacks[name] = callback.bindenv(scope) __CollectGameEventCallbacks(blimpcallbacks) } self.SetHealth(self.GetMaxHealth() - (blimp.GetMaxHealth() - blimp.GetHealth())) if (self.GetHealth() <= 0) { self.Teleport(true, blimp.GetOrigin(), false, QAngle(), false, Vector()) self.TakeDamage(10000.0, 64, null) } } CleanUpBlimp = function() { if (NetProps.GetPropBool(objective_resource_entity, "m_bMannVsMachineBetweenWaves") == true) return // don't do cleanup if the blimp was the last enemy in the wave blimps_in_wave = blimps_in_wave - 1 for (local i = 0; i <= 11; i++) { if (NetProps.GetPropStringArray(objective_resource_entity, "m_iszMannVsMachineWaveClassNames", i) == "blimp2_lite") NetProps.SetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassCounts", blimps_in_wave, i) if (NetProps.GetPropStringArray(objective_resource_entity, "m_iszMannVsMachineWaveClassNames2", i) == "blimp2_lite") NetProps.SetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassCounts2", blimps_in_wave, i) if (NetProps.GetPropStringArray(objective_resource_entity, "m_iszMannVsMachineWaveClassNames", i) == "tank") NetProps.SetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassCounts", tanks_in_wave, i) if (NetProps.GetPropStringArray(objective_resource_entity, "m_iszMannVsMachineWaveClassNames2", i) == "tank") NetProps.SetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassCounts2", tanks_in_wave, i) } for (local train; train = Entities.FindByName(train, "blimp_train"); ) if (!train.GetScriptScope().parented_blimp.IsValid()) train.Kill() for (local cash; cash = Entities.FindByClassname(cash, "item_currencypack_custom"); ) AddThinkToEnt(cash, "ImprovedCashCollection_Think") } Blimp_Think = function() { local scope = self.GetScriptScope() if (!("DeployBomb" in scope)) { PrecacheSound("npc/combine_gunship/ping_search.wav") scope.nextpingtime <- Time() + 5.0 scope.deployed <- false scope.DeployBomb <- function() { self.ResetSequence(1) if (sigmod) self.SetPlaybackRate(0.013) EmitSoundEx( { sound_name = "MVM.TankDeploy", filter = 5, entity = self, volume = 1, soundlevel = 150, flags = 1, channel = 6 }) } } self.SetOrigin(scope.pathtrain.GetOrigin()) self.SetAbsAngles(QAngle(0, scope.pathtrain.GetAbsAngles().y, 0)) self.GetLocomotionInterface().Reset() if (self.GetModelName() == "models/bots/boss_bot/boss_tank.mdl" || self.GetModelName() == "models/bots/tw2/boss_bot/boss_tank.mdl") NetProps.SetPropIntArray(self, "m_nModelIndexOverrides", PrecacheModel("models/bots/boss_bot/boss_blimp.mdl"), 0) if (self.GetModelName() == "models/bots/boss_bot/boss_tank_damage1.mdl" || self.GetModelName() == "models/bots/tw2/boss_bot/boss_tank_damage1.mdl") NetProps.SetPropIntArray(self, "m_nModelIndexOverrides", PrecacheModel("models/bots/boss_bot/boss_blimp_damage1.mdl"), 0) if (self.GetModelName() == "models/bots/boss_bot/boss_tank_damage2.mdl" || self.GetModelName() == "models/bots/tw2/boss_bot/boss_tank_damage2.mdl") NetProps.SetPropIntArray(self, "m_nModelIndexOverrides", PrecacheModel("models/bots/boss_bot/boss_blimp_damage2.mdl"), 0) if (self.GetModelName() == "models/bots/boss_bot/boss_tank_damage3.mdl" || self.GetModelName() == "models/bots/tw2/boss_bot/boss_tank_damage3.mdl") NetProps.SetPropIntArray(self, "m_nModelIndexOverrides", PrecacheModel("models/bots/boss_bot/boss_blimp_damage3.mdl"), 0) if (self.GetModelName() == "models/bots/boss_bot/boss_tank.mdl" || self.GetModelName() == "models/bots/tw2/boss_bot/boss_tank.mdl") NetProps.SetPropIntArray(self, "m_nModelIndexOverrides", PrecacheModel("models/bots/boss_bot/boss_blimp.mdl"), 3) if (self.GetModelName() == "models/bots/boss_bot/boss_tank_damage1.mdl" || self.GetModelName() == "models/bots/tw2/boss_bot/boss_tank_damage1.mdl") NetProps.SetPropIntArray(self, "m_nModelIndexOverrides", PrecacheModel("models/bots/boss_bot/boss_blimp_damage1.mdl"), 3) if (self.GetModelName() == "models/bots/boss_bot/boss_tank_damage2.mdl" || self.GetModelName() == "models/bots/tw2/boss_bot/boss_tank_damage2.mdl") NetProps.SetPropIntArray(self, "m_nModelIndexOverrides", PrecacheModel("models/bots/boss_bot/boss_blimp_damage2.mdl"), 3) if (self.GetModelName() == "models/bots/boss_bot/boss_tank_damage3.mdl" || self.GetModelName() == "models/bots/tw2/boss_bot/boss_tank_damage3.mdl") NetProps.SetPropIntArray(self, "m_nModelIndexOverrides", PrecacheModel("models/bots/boss_bot/boss_blimp_damage3.mdl"), 3) self.StudioFrameAdvance() self.DispatchAnimEvents(self) if (deployed) return -1 if (Time() > nextpingtime) { EmitSoundEx( { sound_name = "npc/combine_gunship/ping_search.wav", filter = 5, entity = self, volume = 1, soundlevel = 150, flags = 0, channel = 6 }) nextpingtime = Time() + 5.0 } if (self.GetCycle() == 1.0) { if (self.GetSequence() == 2) self.SetCycle(0) else { deployed = true switch (GetMapName()) { case "mvm_hanami_rc1": { EntFire("win_bots", "RoundWin") EntFire("hatch_destroy_relay", "Trigger") break } case "mvm_null_b9c": { soldier_statue.Kill() EntFire("bots_win", "RoundWin") EntFire("end_pit_destroy_particle", "Start") EntFire("pit_explosion_wav", "PlaySound") EntFire("hatch_explo_kill_players", "Enable") EntFire("hatch_explo_kill_players", "Disable", null, 0.5) EntFire("hatch_magnet_pit", "Enable") EntFire("trigger_hurt_hatch_fire", "Enable") break } case "mvm_quetzal_rc5": EntFire("boss_deploy_relay", "Trigger"); break } } } return -1 } PerformAnim = function(data) { if (!("mdl1" in data) || !("anim" in data)) return local mdl1 = data.mdl1 local anim = data.anim local mdl2 = ("mdl2" in data) ? data.mdl2 : false local s = ("s" in data) ? data.s : 0.0 local e = ("e" in data) ? data.e : 0.99 local dur = ("dur" in data) ? data.dur : false local events = ("events" in data) ? data.events : [] local endevents = ("endevents" in data) ? data.endevents : [] local allowmove = ("allowmove" in data) ? data.allowmove : false self.SetCustomModelOffset(Vector(0, 0, -9000)) if (!allowmove) self.SetMoveType(0, 0) local id = UniqueString() local dummy_model = SpawnEntityFromTable("prop_dynamic", { targetname = id origin = self.GetOrigin() angles = self.GetAbsAngles() skin = 1 modelscale = self.GetModelScale() model = mdl1 defaultanim = anim disablebonefollowers = 1 rendermode = mdl2 ? 1 : 0 renderamt = mdl2 ? 0 : 255 }) local dummy_model2 if (!(!mdl2)) { dummy_model2 = SpawnEntityFromTable("prop_dynamic_ornament", { model = mdl2 skin = 1 modelscale = self.GetModelScale() disablebonefollowers = 1 initialowner = id }) } NetProps.SetPropBool(dummy_model, "m_bClientSideAnimation", false) dummy_model.ValidateScriptScope() local d = dummy_model.GetScriptScope() d.owner <- self d.o <- self.GetScriptScope() d.start <- s d.end <- e d.plyback <- null d.animat <- data.anim d.dead <- false d.eventarray <- [] d.eventarray.extend(events) d.endeventarray <- [] d.endeventarray.extend(endevents) d.DummyModelEvent <- function(num) { eventarray[num][1].call(this) if (num in eventarray) eventarray.remove(num) } if (s > 0.0) dummy_model.SetCycle(s) if (dur) { if (dur >= 0.0) { local time = dummy_model.GetSequenceDuration(dummy_model.LookupSequence(anim)) local totcyc = e - s time *= totcyc d.plyback = (time / dur) } else d.plyback = (dur * -1.0) dummy_model.SetPlaybackRate(d.plyback) } d.Anim_Think <- function() { if (!self.IsValid()) return self.SetOrigin(d.owner.GetOrigin()) for (local i = 0; i < eventarray.len(); i++) { if (self.GetCycle() >= eventarray[i][0]) DummyModelEvent(i) } if (!self.IsValid()) return if (self.GetCycle() >= end) { NetProps.SetPropString(self, "m_iszScriptThinkFunction", "") AddThinkToEnt(self, null) self.Kill() return } self.StudioFrameAdvance() return -1 } AddThinkToEnt(dummy_model, "Anim_Think") SetDestroyCallback(dummy_model, function() { if (dead) return owner.SetCustomModelOffset(Vector()) owner.SetMoveType(2, 0) foreach (event in endeventarray) event() }) return [dummy_model, dummy_model2] } ChangeAbsTrajectory = @(input) self.SetAbsVelocity(self.GetAbsVelocity() + DynamicVal(input)) MultiplyAbsVelocity = @(input) self.SetAbsVelocity(self.GetAbsVelocity() * DynamicVal(input)) RemoveVerticalVelocity = @() self.SetAbsVelocity(Vector(self.GetAbsVelocity().x, self.GetAbsVelocity().y, 0)) MatchAnglesWithVelocity = @() self.SetAbsAngles(VectorAngles(self.GetAbsVelocity())) DispatchTimedParticleEffect = function(particle, where, angle, time) { local particle = SpawnEntityFromTable("info_particle_system", { origin = where angles = angle start_active = 1, effect_name = particle }) EntFireByHandle(particle, "Kill", null, time, null, null) } CreateBeam = function(start_ent, end, dur = 0.25) { local startid = UniqueString() local dest = SpawnEntityFromTable("info_teleport_destination", { targetname = "dest2", origin = end }) start_ent.KeyValueFromString("targetname", startid) local beam = SpawnEntityFromTable("env_beam", { life = 0 boltwidth = 1 LightningStart = startid LightningEnd = "dest2" NoiseAmplitude = 1 rendercolor = "153 194 216" texture = "sprites/laserbeam.spr" spawnflags = 1 }) NetProps.SetPropBool(beam, "m_bForcePurgeFixedupStrings", true) start_ent.KeyValueFromString("targetname", "") EntFireByHandle(beam, "Kill", null, dur, null, null) dest.Kill() } _RemoveAllItems = function() { for (local next, current = this.FirstMoveChild(); current != null; current = next) { NetProps.SetPropBool(current, "m_bForcePurgeFixedupStrings", true) next = current.NextMovePeer() if (current instanceof CEconEntity) current.Destroy() } } SetDestroy = function(ply) { owner <- ply Delete <- function() { self.Kill(); delete ent_callbacks } ent_callbacks <- { OnGameEvent_recalculate_holidays = function(params) Delete() OnGameEvent_player_spawn = function(params) { if (GetPlayerFromUserID(params.userid) == owner) Delete() } OnGameEvent_player_death = function(params) { if (GetPlayerFromUserID(params.userid) == owner) Delete() } } foreach (name, callback in ent_callbacks) ent_callbacks[name] = callback.bindenv(self.GetScriptScope()) __CollectGameEventCallbacks(ent_callbacks) } RoundTimeToTicks = @(time) (time / 0.015).tointeger() * 0.015 ConvertTimeToTicks = @(time) format("%.0f", (time * 66.66)).tointeger() ConvertTicksToTime = @(ticks) FrameTime() * ticks RandomPlusMinus = @() (RandomInt(0, 1) == 0) ? 1.0 : -1.0 DynamicVal = function(val, scope = false) { if (typeof(val) != "function") return val else return (scope) ? val.call(scope) : val() } CountdownTimer = class { duration = 0.0 timestamp = -1.0 Reset = @() timestamp = Time() + duration Start = function(length) { timestamp = Time() + length duration = length } Invalidate = @() timestamp = -1.0 HasStarted = @() timestamp > 0.0 IsElapsed = function(cont = false, contdur = 1.0) { local result = (HasStarted() && Time() > timestamp) if (result) { if (cont) Start(contdur) else Invalidate() } return result } GetElapsedTime = @() Time() - timestamp + duration GetRemainingTime = @() timestamp - Time() GetCountdownDuration = @() (timestamp > 0.0) ? duration : 0.0 function constructor(d = -1.0) { timestamp = -1.0 duration = 0.0 if (d > -1.0) Start(d) } } EventQueue = class { owner = null eventqueue = [] function constructor(ply, initevents = []) { owner = ply eventqueue.extend(initevents) } Resolve = function() { while (NextEventIsValid()) { local outcome = eventqueue[0][0].call(owner.GetScriptScope()) if (!outcome) { eventqueue.remove(0) } else { eventqueue[0][1] = Time() + outcome Sort() } // eventqueue[0][0].call(owner.GetScriptScope()) // eventqueue.remove(0) } } Add = function(...) { vargv[1] = Time() + vargv[1] eventqueue.append(vargv) Sort() } Sort = @() eventqueue.sort(@(a, b) a[1] <=> b[1]) NextEventIsValid = function() { if (eventqueue.len() > 0) { if (eventqueue[0][1] <= Time()) return true } return false } } DeclVarFromTab = function(var, tab, val) { this[var] = (var in tab) ? tab[var] : val } DEBUG_CALLBACKS = { OnGameEvent_player_say = function(params) { local player = GetPlayerFromUserID(params.userid) if (params.text == "1") { foreach (player in GetAllPlayers(3)) player.TakeDamageCustom(player, player, null, Vector(), Vector(), 9999999.9, 1024, 0) // PrecacheModel("models/player/pyro.mdl") // player.SetCustomModelWithClassAnimations("models/player/pyro.mdl") // local wearable = SpawnEntityFromTable("tf_wearable", // { // origin = player.GetOrigin() // model = "models/bots/pyro/bot_pyro.mdl" // skin = 0 // effects = 129 // }) // EntFireByHandle(wearable, "SetParent", "!activator", -1, player, null) // NetProps.SetPropInt(wearable, "m_fEffects", 129) } } } } CBaseEntity.Enable <- function() { this.AcceptInput("Enable", null, null, null) } CBaseEntity.Disable <- function() { this.AcceptInput("Disable", null, null, null) } CTFPlayer.IsGrounded <- function() { return NetProps.GetPropEntity(this, "m_hGroundEntity") != null } CTFBot.IsGrounded <- function() { return NetProps.GetPropEntity(this, "m_hGroundEntity") != null } CTFBot.Zombify <- function() { if (!strip_romevision_items) // we want to remove romevision from zombies even if we normally accept it { for (local child = this.FirstMoveChild(); child != null; child = child.NextMovePeer()) { if (child.GetClassname() == "tf_wearable" && child.GetModelName().find("tw_") != null) EntFireByHandle(child, "Kill", null, -1.0, null, null) } } NetProps.SetPropBool(this, "m_bForcedSkin", true) NetProps.SetPropInt(this, "m_nForcedSkin", 5) NetProps.SetPropInt(this, "m_iPlayerSkinOverride", 1) this.GetWearableItem(zombieitems[this.GetPlayerClass() - 1]) // this.GetWearable(format("models/player/items/%s/%s_zombie.mdl", class_integers[this.GetPlayerClass()], class_integers[this.GetPlayerClass()])) this.SetCustomModelWithClassAnimations(format("models/player/%s.mdl", class_integers[this.GetPlayerClass()])) if (sigmod) { this.AddCustomAttribute("use human voice", 1, -1.0) this.AddCustomAttribute("voice pitch scale", 0.65, -1.0) } else this.AddCustomAttribute("voice pitch scale", 0, -1.0) } // CTFBot.IsFlanker <- function() // { // local tagtable = {} // this.GetAllBotTags(tagtable) // foreach (index, tag in tagtable) { if (tag.find("flank") != null) return true } // return false // } CTFPlayer.GetWeapon <- function(className, itemID) { local weapon = Entities.CreateByClassname(className) NetProps.SetPropInt(weapon, "m_AttributeManager.m_Item.m_iItemDefinitionIndex", itemID) NetProps.SetPropBool(weapon, "m_AttributeManager.m_Item.m_bInitialized", true) NetProps.SetPropBool(weapon, "m_bValidatedAttachedEntity", true) weapon.SetTeam(this.GetTeam()) Entities.DispatchSpawn(weapon) for (local i = 0; i < 8; i++) { local heldWeapon = NetProps.GetPropEntityArray(this, "m_hMyWeapons", i) if (heldWeapon == null) continue if (heldWeapon.GetSlot() != weapon.GetSlot()) continue heldWeapon.Destroy() NetProps.SetPropEntityArray(this, "m_hMyWeapons", null, i) break } if (itemID == 28) { NetProps.SetPropInt(weapon, "m_iObjectType", 0) NetProps.SetPropInt(weapon, "m_iSubType", 0) NetProps.SetPropBoolArray(weapon, "m_aBuildableObjectTypes", true, 0) NetProps.SetPropBoolArray(weapon, "m_aBuildableObjectTypes", true, 1) NetProps.SetPropBoolArray(weapon, "m_aBuildableObjectTypes", true, 2) } this.Weapon_Equip(weapon) this.Weapon_Switch(weapon) return weapon } CTFBot.GetWeapon <- CTFPlayer.GetWeapon CTFPlayer.GetWearable <- function(model, bonemerge = true, attachment = null, offsets = null) { local modelIndex = GetModelIndex(model) if (modelIndex == -1) modelIndex = ::PrecacheModel(model) local wearable = Entities.CreateByClassname("tf_wearable") NetProps.SetPropInt(wearable, "m_nModelIndex", modelIndex) wearable.SetSkin(this.GetTeam()) wearable.SetTeam(this.GetTeam()) wearable.SetSolidFlags(4) wearable.SetCollisionGroup(11) wearable.SetOwner(this) Entities.DispatchSpawn(wearable) NetProps.SetPropInt(wearable, "m_fEffects", bonemerge ? 129 : 0) wearable.AcceptInput("SetParent", "!activator", this, this) if (attachment != null) wearable.AcceptInput("SetParentAttachment", attachment, null, null) if (offsets != null) { EntFireByHandle(wearable, "RunScriptCode", "self.SetLocalOrigin(Vector(" + offsets[0].x + ", " + offsets[0].y + ", " + offsets[0].z + "))", 0.1, null, null) EntFireByHandle(wearable, "RunScriptCode", "self.SetLocalAngles(QAngle(" + offsets[1].x + ", " + offsets[1].y + ", " + offsets[1].z + "))", 0.1, null, null) } else { EntFireByHandle(wearable, "RunScriptCode", "self.SetLocalOrigin(Vector(0, 0, 0))", 0.1, null, null) EntFireByHandle(wearable, "RunScriptCode", "self.SetLocalAngles(QAngle(0, 0, 0))", 0.1, null, null) } wearable.ValidateScriptScope() wearable.GetScriptScope().custom_wearable <- true NetProps.SetPropBool(wearable, "m_bClientSideAnimation", false) SetDestroy.call(wearable.GetScriptScope(), this) return wearable } CTFPlayer.GetWearableItem <- function(id) { local dummy_Weapon = Entities.CreateByClassname("tf_weapon_parachute") NetProps.SetPropInt(dummy_Weapon, "m_AttributeManager.m_Item.m_iItemDefinitionIndex", 1101) NetProps.SetPropBool(dummy_Weapon, "m_AttributeManager.m_Item.m_bInitialized", true) dummy_Weapon.SetTeam(this.GetTeam()) dummy_Weapon.DispatchSpawn() this.Weapon_Equip(dummy_Weapon) local wearable = NetProps.GetPropEntity(dummy_Weapon, "m_hExtraWearable") dummy_Weapon.Kill() NetProps.SetPropInt(wearable, "m_AttributeManager.m_Item.m_iItemDefinitionIndex", id) NetProps.SetPropBool(wearable, "m_AttributeManager.m_Item.m_bInitialized", true) wearable.DispatchSpawn() wearable.ValidateScriptScope() wearable.GetScriptScope().custom_wearable <- true SetDestroy.call(wearable.GetScriptScope(), this) return wearable } CTFPlayer.CreateRagdoll <- function(mode = 0) { local c = @(num) ((mode & num) > 0) local ragdoll = Entities.CreateByClassname("tf_ragdoll") NetProps.SetPropVector(ragdoll, "m_vecRagdollOrigin", this.GetOrigin()) NetProps.SetPropVector(ragdoll, "m_vecRagdollVelocity", this.GetAbsVelocity()) NetProps.SetPropVector(ragdoll, "m_vecForce", NetProps.GetPropVector(this, "m_vecForce")) NetProps.SetPropVector(ragdoll, "m_nForceBone", NetProps.GetPropVector(this, "m_nForceBone")) NetProps.SetPropEntity(ragdoll, "m_hPlayer", this) NetProps.SetPropBool(ragdoll, "m_bGib", c(1)) NetProps.SetPropBool(ragdoll, "m_bBurning", c(2)) NetProps.SetPropBool(ragdoll, "m_bElectrocuted", c(4)) NetProps.SetPropBool(ragdoll, "m_bOnGround", c(8)) NetProps.SetPropInt(ragdoll, "m_iTeam", this.GetTeam()) NetProps.SetPropInt(ragdoll, "m_iClass", this.GetPlayerClass()) NetProps.SetPropBool(ragdoll, "m_bGoldRagdoll", c(16)) NetProps.SetPropBool(ragdoll, "m_bIceRagdoll", c(32)) NetProps.SetPropBool(ragdoll, "m_bBecomeAsh", c(64)) NetProps.SetPropBool(ragdoll, "m_bCritOnHardHit", c(128)) NetProps.SetPropFloat(ragdoll, "m_flHeadScale", NetProps.GetPropFloat(this, "m_flHeadScale")) NetProps.SetPropFloat(ragdoll, "m_flTorsoScale", NetProps.GetPropFloat(this, "m_flTorsoScale")) NetProps.SetPropFloat(ragdoll, "m_flHandScale", NetProps.GetPropFloat(this, "m_flHandScale")) NetProps.SetPropString(ragdoll, "m_ModelName", this.GetModelName()) NetProps.SetPropInt(ragdoll, "m_nModelIndex", GetModelIndex(this.GetModelName())) NetProps.SetPropIntArray(ragdoll, "m_nModelIndexOverrides", GetModelIndex(this.GetModelName()), 0) NetProps.SetPropIntArray(ragdoll, "m_nModelIndexOverrides",GetModelIndex(this.GetModelName()), 1) NetProps.SetPropIntArray(ragdoll, "m_nModelIndexOverrides", GetModelIndex(this.GetModelName()), 2) NetProps.SetPropIntArray(ragdoll, "m_nModelIndexOverrides", GetModelIndex(this.GetModelName()), 3) ragdoll.SetModelSimple(this.GetModelName()) ragdoll.DispatchSpawn() return ragdoll } // CTFPlayer.EnableDraw <- function() // { // NetProps.SetPropInt(this, "m_fEffects", NetProps.GetPropInt(this, "m_fEffects") - 48) // for (local next, current = this.FirstMoveChild(); current != null; current = next) // { // next = current.NextMovePeer() // if ((NetProps.GetPropInt(current, "m_fEffects") & 48) == 0) continue // NetProps.SetPropInt(current, "m_fEffects", NetProps.GetPropInt(current, "m_fEffects") - 48) // } // } // CTFPlayer.DisableDraw <- function() // { // NetProps.SetPropInt(this, "m_fEffects", NetProps.GetPropInt(this, "m_fEffects") + 48) // for (local next, current = this.FirstMoveChild(); current != null; current = next) // { // next = current.NextMovePeer() // if ((NetProps.GetPropInt(current, "m_fEffects") & 48) == 1) continue // NetProps.SetPropInt(current, "m_fEffects", NetProps.GetPropInt(current, "m_fEffects") + 48) // } // } CTFBot.GetWearable <- CTFPlayer.GetWearable CTFBot.GetWearableItem <- CTFPlayer.GetWearableItem CTFBot.CreateRagdoll <- CTFPlayer.CreateRagdoll // CTFBot.EnableDraw <- CTFPlayer.EnableDraw // CTFBot.DisableDraw <- CTFPlayer.DisableDraw CBaseCombatWeapon.GetOwner <- function() { return NetProps.GetPropEntity(this, "m_hOwner") } CTFPlayer.IsInFieldOfView <- function(target) // credit goes to creators of popextensions for providing the code { local delta delta = target.GetOrigin() - this.EyePosition() delta.Norm() if (this.EyeAngles().Forward().Dot(target) >= 0.5736) return true delta = target.GetCenter() - this.EyePosition() delta.Norm if (this.EyeAngles().Forward().Dot(delta) >= 0.5736) return true delta = target.EyePosition() - this.EyePosition() delta.Norm() return (this.EyeAngles().Forward().Dot(delta) >= 0.5736) } CTFBot.IsInFieldOfView <- CTFPlayer.IsInFieldOfView CTFPlayer.GetWeaponInSlot <- function(num) { return NetProps.GetPropEntityArray(this, "m_hMyWeapons", num) } CTFBot.GetWeaponInSlot <- CTFPlayer.GetWeaponInSlot if (!("PEA" in getroottable())) ::PEA <- {} if (!("PLAYERLOG" in getroottable())) ::PLAYERLOG <- {} foreach (thing, var in PEA_GLOBAL) getroottable()["PEA"][thing] <- getroottable()["PEA_GLOBAL"][thing] foreach (thing, var in PLAYERLOG) getroottable()["PEA"][thing] <- getroottable()["PLAYERLOG"][thing] foreach (thing, var in PEA) getroottable()[thing] <- getroottable()["PEA"][thing] delete ::PLAYERLOG delete ::PEA_GLOBAL if (!("PEA_GLOBAL_ONETIME" in getroottable())) // declare these variables only once on initial load, don't update them on any future loads { ::PEA_GLOBAL_ONETIME <- { gamerules_entity = Entities.FindByClassname(null, "tf_gamerules") objective_resource_entity = Entities.FindByClassname(null, "tf_objective_resource") debugger = null wavewon = false firstload = ("custom_spawns" in PEA) ? true : false } if (!sigmod) Convars.SetValue("tf_mvm_max_invaders", 90) CBaseEntity.LegacyKill <- CBaseEntity.Kill CBaseEntity.Kill <- function() { NetProps.SetPropString(this, "m_iszScriptThinkFunction", "") AddThinkToEnt(this, null) this.LegacyKill() } foreach (thing, var in PEA_GLOBAL_ONETIME) getroottable()[thing] <- getroottable()["PEA_GLOBAL_ONETIME"][thing] 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 player.ValidateScriptScope() if (!player.IsFakeClient()) player.ForceRespawn() } if ("custom_spawns" in PEA) { foreach (spawn in custom_spawns) { local s = SpawnEntityFromTable("info_player_teamspawn", { origin = spawn[0] targetname = spawn[1] TeamNum = 3 spawnflags = 511 StartDisabled = spawn[2] }) } for (local ent; ent = Entities.FindByClassname(ent, "info_player_teamspawn"); ) { if (NetProps.GetPropInt(ent, "m_iHammerID") == 0) ent.KeyValueFromString("classname", "entity_sign") } NetProps.SetPropFloat(gamerules_entity, "m_flRestartRoundTime", Time()) foreach (name, callback in PEA.GLOBAL_CALLBACKS) PEA.GLOBAL_CALLBACKS[name] = callback.bindenv(gamerules_entity.GetScriptScope()) __CollectGameEventCallbacks(PEA.GLOBAL_CALLBACKS) return } } else if (firstload) EntFireByHandle(gamerules_entity, "CallScriptFunction", "HideErrors", 0.1, null, null) if ("ClassRegister" in PEA) ClassRegister() HideIcon("noicon") foreach (think in getroottable()["ThinksTable"]) delete getroottable()["ThinksTable"][think] ignite_player.AddAttribute("Set DamageType Ignite", 1, -1.0) Entities.DispatchSpawn(ignite_player) for (local ent; ent = Entities.FindByName(ent, "blimp_path*"); ) if (NetProps.GetPropEntity(ent, "m_pnext") == null) EntityOutputs.AddOutput(ent, "OnPass", "!activator", "RunScriptCode", "self.GetScriptScope().parented_blimp.GetScriptScope().DeployBomb()", -1.0, -1.0) switch (GetMapName()) { case "mvm_sequoia_rc4": DisableRomevision(); break case "mvm_meltdown_rc5": break case "mvm_spacepost_rc1": break case "mvm_derelict_rc2": DisableRomevision(); break case "mvm_hanami_rc1": break case "mvm_hideout_b3": DisableRomevision(); break case "mvm_hoovydam_b10": DisableRomevision(); EntFire("initMain_roadside", "Trigger"); break case "mvm_null_b9a": DisableRomevision(); break case "mvm_decay_rc1": DisableRomevision(); break case "mvm_quetzal_rc5": DisableRomevision(); break case "mvm_powerplant_rc1": DisableRomevision(); AssignThinkToThinksTable("BombCarrierSpawnSpeedUp_Think"); break case "mvm_underworld_rc2": DisableRomevision(); break case "mvm_bogland_rc9c": DisableRomevision(); break } AssignThinkToThinksTable("TankFinder_Think") if ("CALLBACKS" in PEA) { foreach (name, callback in PEA.CALLBACKS) PEA.CALLBACKS[name] = callback.bindenv(gamerules_entity.GetScriptScope()) // this will let us use local functions inside callbacks __CollectGameEventCallbacks(PEA.CALLBACKS) } foreach (name, callback in PEA.GLOBAL_CALLBACKS) PEA.GLOBAL_CALLBACKS[name] = callback.bindenv(gamerules_entity.GetScriptScope()) __CollectGameEventCallbacks(PEA.GLOBAL_CALLBACKS) for (local ent; ent = Entities.FindByClassname(ent, "script_wearable"); ) ent.Kill() if (WaveHasIcon("blimp2_lite")) UnhideIcon("blimp2_lite", 8) foreach (player in GetAllPlayers(false, false, false)) { player.ValidateScriptScope() if (player.IsFakeClient()) { if (!sigmod) { NetProps.SetPropBool(player, "m_bForcedSkin", false) NetProps.SetPropInt(player, "m_nForcedSkin", 0) NetProps.SetPropInt(player, "m_iPlayerSkinOverride", 0) } local scope = player.GetScriptScope() NetProps.SetPropString(player, "m_iszScriptThinkFunction", "") for (local child = player.FirstMoveChild(); child != null; child = child.NextMovePeer()) { if ("custom_wearable" in child.GetScriptScope()) { EntFireByHandle(child, "Kill", null, -1.0, null, null); continue } child.DisableDraw() continue } foreach (thing in player.GetScriptScope()) { try { thing.GetClassname() } catch (e) { continue } if (!thing.IsPlayer()) thing.Kill() } player.TerminateScriptScope() } } if (debug) { 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) } } AssignThinkToThinksTable("InstantReady_Think") __CollectGameEventCallbacks(PEA.DEBUG_CALLBACKS) } AddThinkToEnt(gamerules_entity, "GlobalThinker") seterrorhandler(function(e) { for (local player; player = Entities.FindByClassname(player, "player");) { if (NetProps.GetPropString(player, "m_szNetworkIDString") == "[U:1:95064912]") { local Chat = @(m) (printl(m), ClientPrint(player, 2, m)) ClientPrint(player, 3, format("\x07FF0000AN ERROR HAS OCCURRED [%s].\nCheck console for details", e)) Chat(format("\n====== TIMESTAMP: %g ======\nAN ERROR HAS OCCURRED [%s]", Time(), e)) Chat("CALLSTACK") local s, l = 2 while (s = getstackinfos(l++)) Chat(format("*FUNCTION [%s()] %s line [%d]", s.func, s.src, s.line)) Chat("LOCALS") if (s = getstackinfos(2)) { foreach (n, v in s.locals) { local t = type(v) t == "null" ? Chat(format("[%s] NULL" , n)) : t == "integer" ? Chat(format("[%s] %d" , n, v)) : t == "float" ? Chat(format("[%s] %.14g" , n, v)) : t == "string" ? Chat(format("[%s] \"%s\"", n, v)) : Chat(format("[%s] %s %s" , n, t, v.tostring())) } } return } } }) EntFireByHandle(gamerules_entity, "RunScriptCode", "wavewon = false", -1.0, null, null)