/* * Author: Needles * https://steamcommunity.com/profiles/76561198026257137/ */ ::Debug.Print("*** UTILS"); ::Utils <- {}; ::Utils.CREATION_TIME_SCOPE_KEY <- UniqueString(); /* * Prints the contents of the specified table to console. */ function Utils::PrintTable(table) { foreach(k, v in table) ::Debug.Print(k + " = " + v); } /* * Returns an array containing all entities with the given classname. */ function Utils::FindAllByClassname(classname) { local entList = []; local ent = null; while (ent = Entities.FindByClassname(ent, classname)) entList.append(ent); return entList; } /* * Returns an array containing all of the values within the specified table. */ function Utils::TableToArray(table) { local array = []; foreach(key, value in table) array.append(value); return array; } /* * Turns a QAngle into a vector with the same values */ function Utils::QAngleToVector(angles) { return Vector(angles.x, angles.y, angles.z); } /* * Print all of an entity's netprops to console */ function Utils::DumpNetProps(ent) { if (!ent || !ent.IsValid()) return; ::Debug.Print("=== NETPROP DUMP : " + ent.GetClassname() + " ==="); local sendprops = {}; local datamaps = {}; NetProps.GetTable(ent, 0, sendprops); NetProps.GetTable(ent, 1, datamaps); ::Debug.Print("=== Sendprops ===="); foreach (k, v in sendprops) ::Debug.Print(k + " = " + v) ::Debug.Print("=== Datamaps ===="); foreach (k, v in datamaps) ::Debug.Print(k + " = " + v); } /* * If red, returns blue. If blue, returns red. */ function Utils::OpposingTeam(team) { if (team == Constants.ETFTeam.TF_TEAM_RED) return Constants.ETFTeam.TF_TEAM_BLUE; if (team == Constants.ETFTeam.TF_TEAM_BLUE) return Constants.ETFTeam.TF_TEAM_RED; return team; } /* * Damage all entities within the specified sphere */ function Utils::DamageArea(classnameList, origin, radius, damage, damageType, attacker) { foreach(classname in classnameList) { local ent = null; while (ent = Entities.FindByClassname(ent, classname)) { if ((ent.GetOrigin() - origin).LengthSqr() > radius*radius) continue; if (ent.GetTeam() == attacker.GetTeam()) continue; local trace = { start = origin, end = origin + ent.GetOrigin(), mask = Constants.FContents.CONTENTS_SOLID | Constants.FContents.CONTENTS_WINDOW | Constants.FContents.CONTENTS_GRATE | Constants.FContents.CONTENTS_MOVEABLE, ignore = null, }; TraceLineEx(trace); if (trace.hit == false) continue; ent.TakeDamage(damage, damageType, attacker); } } } /* * Ignite a player for the specified duration */ function Utils::IgnitePlayerEx(player, duration) { if (!::Players.IsPlayerValid(player)) return; local trigger = SpawnEntityFromTable("trigger_ignite", { spawnflags = 64, burn_duration = duration, damage = 0.0, }); EntFireByHandle(trigger, "StartTouch", "!activator", 0.0, player, player); EntFireByHandle(trigger, "Kill", "", 0.0, null, null); } /* * Forecefully start the wave */ function Utils::ForceStartWave() { NetProps.SetPropFloat(Entities.FindByClassname(null, "tf_gamerules"), "m_flRestartRoundTime", Time()); } /* * Create a dispenser that doesn't function as a dispenser */ function Utils::BuildEmptyDispenser(origin, angles, team) { local ent_dispenser = SpawnEntityFromTable("obj_dispenser", { targetname = "helper_sap_target_" + UniqueString(), origin = origin, angles = angles, teamnum = team, SolidToPlayer = 0, }); // Find and destroy dispenser entity dependencies local ent_vgui = null; while (ent_vgui = Entities.FindByClassname(ent_vgui, "vgui_screen")) { if (ent_vgui.GetMoveParent() == ent_dispenser) ent_vgui.Destroy(); } // Stop the dispenser from functioning as a dispenser ent_dispenser.SetSolid(Constants.ESolidType.SOLID_NONE); EntFireByHandle(ent_dispenser, "Disable", "", -1.0, null, null); return ent_dispenser; } /* * Creates a temporary ambient_generic entity and uses it to play a sound */ function Utils::TempAmbientGeneric(path, origin, radius, volume, pitch, destroyDelay = 2.0) { local ent_sound = SpawnEntityFromTable("ambient_generic", { origin = origin, message = path, radius = radius, health = volume, pitch = pitch, }); EntFireByHandle(ent_sound, "PlaySound", "", -1.0, null, null); EntFireByHandle(ent_sound, "Kill", "", destroyDelay, null, null); } /* * Call a function at the end of the current frame */ function Utils::DoOnEndOfFrame(callback) { local scopeKey = UniqueString(); local worldspawn = Entities.First(); if (worldspawn.ValidateScriptScope() == false) return; worldspawn.GetScriptScope()[scopeKey] <- callback; EntFireByHandle(worldspawn, "runscriptcode", "" + scopeKey + "(); self.GetScriptScope().rawdelete(" + scopeKey + ");", -1.0, null, null); } // @TODO - Move this into its own module lelkekw function Utils::ValidateCreationTime(entity) { if (entity == null || entity.IsValid() == false || entity.ValidateScriptScope() == false) return null; if (::Utils.CREATION_TIME_SCOPE_KEY in entity.GetScriptScope()) return entity.GetScriptScope()[::Utils.CREATION_TIME_SCOPE_KEY]; entity.GetScriptScope()[::Utils.CREATION_TIME_SCOPE_KEY] <- Time(); return Time(); }