mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-17 21:53:46 +03:00
Upload
This commit is contained in:
587
lua/pac3/core/client/util.lua
Normal file
587
lua/pac3/core/client/util.lua
Normal file
@@ -0,0 +1,587 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
local Vector = Vector
|
||||
local Matrix = Matrix
|
||||
local isstring = isstring
|
||||
|
||||
do -- table copy
|
||||
local lookup_table
|
||||
|
||||
local function copy(obj, skip_meta)
|
||||
local t = type(obj)
|
||||
|
||||
if t == "number" or t == "string" or t == "function" or t == "boolean" then
|
||||
return obj
|
||||
end
|
||||
|
||||
if t == "Vector" or t == "Angle" then
|
||||
return obj * 1
|
||||
elseif lookup_table[obj] then
|
||||
return lookup_table[obj]
|
||||
elseif t == "table" then
|
||||
local new_table = {}
|
||||
|
||||
lookup_table[obj] = new_table
|
||||
|
||||
for key, val in pairs(obj) do
|
||||
new_table[copy(key, skip_meta)] = copy(val, skip_meta)
|
||||
end
|
||||
|
||||
return skip_meta and new_table or setmetatable(new_table, getmetatable(obj))
|
||||
end
|
||||
|
||||
return obj
|
||||
end
|
||||
|
||||
function pac.CopyValue(obj, skip_meta)
|
||||
lookup_table = {}
|
||||
return copy(obj, skip_meta)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function pac.MakeMaterialUnlitGeneric(mat, id)
|
||||
local tex_path = mat:GetString("$basetexture")
|
||||
|
||||
if tex_path then
|
||||
local params = {}
|
||||
|
||||
params["$basetexture"] = tex_path
|
||||
params["$vertexcolor"] = 1
|
||||
params["$vertexalpha"] = 1
|
||||
|
||||
return pac.CreateMaterial(pac.uid("pac_fixmat_") .. id, "UnlitGeneric", params)
|
||||
end
|
||||
|
||||
return mat
|
||||
end
|
||||
|
||||
do
|
||||
local inf, ninf = math.huge, -math.huge
|
||||
|
||||
function pac.IsNumberValid(num)
|
||||
return
|
||||
num and
|
||||
num ~= inf and
|
||||
num ~= ninf and
|
||||
(num >= 0 or num <= 0)
|
||||
end
|
||||
end
|
||||
|
||||
do
|
||||
pac.next_frame_funcs = pac.next_frame_funcs or {}
|
||||
pac.next_frame_funcs_simple = pac.next_frame_funcs_simple or {}
|
||||
|
||||
function pac.RunNextFrame(id, func)
|
||||
pac.next_frame_funcs[id] = func
|
||||
end
|
||||
|
||||
function pac.RunNextFrameSimple(func)
|
||||
table.insert(pac.next_frame_funcs_simple, func)
|
||||
end
|
||||
end
|
||||
|
||||
do --dev util
|
||||
function pac.RemoveAllPACEntities()
|
||||
for _, ent in pairs(ents.GetAll()) do
|
||||
pac.UnhookEntityRender(ent)
|
||||
|
||||
if ent.IsPACEntity then
|
||||
ent:Remove()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local _part
|
||||
|
||||
local function nuke_part()
|
||||
_part:Remove()
|
||||
end
|
||||
|
||||
function pac.Panic()
|
||||
pac.RemoveAllParts()
|
||||
pac.RemoveAllPACEntities()
|
||||
|
||||
for i, ent in ipairs(ents.GetAll()) do
|
||||
ent.pac_ignored = nil
|
||||
ent.pac_ignored_data = nil
|
||||
ent.pac_drawing = nil
|
||||
ent.pac_shouldnotdraw = nil
|
||||
ent.pac_onuse_only = nil
|
||||
ent.pac_onuse_only_check = nil
|
||||
ent.pac_ignored_callbacks = nil
|
||||
|
||||
if ent.pac_bones_once then
|
||||
pac.ResetBones(ent)
|
||||
ent.pac_bones_once = nil
|
||||
end
|
||||
|
||||
if istable(ent.pac_animation_sequences) then
|
||||
for part in next, ent.pac_animation_sequences do
|
||||
if part:IsValid() then
|
||||
_part = part
|
||||
ProtectedCall(nuke_part)
|
||||
end
|
||||
end
|
||||
|
||||
ent.pac_animation_sequences = nil
|
||||
end
|
||||
|
||||
if istable(ent.pac_bone_parts) then
|
||||
for part in next, ent.pac_bone_parts do
|
||||
if part:IsValid() then
|
||||
_part = part
|
||||
ProtectedCall(nuke_part)
|
||||
end
|
||||
end
|
||||
|
||||
ent.pac_bone_parts = nil
|
||||
end
|
||||
|
||||
ent.pac_animation_stack = nil
|
||||
end
|
||||
end
|
||||
|
||||
pac.convarcache = {}
|
||||
function pac.CreateClientConVarFast(cvar,initial,save,t,server)
|
||||
|
||||
local cached = pac.convarcache[cvar]
|
||||
if cached then return cached[1],cached[2] end
|
||||
|
||||
local val
|
||||
local c = CreateClientConVar(cvar,initial,save,server)
|
||||
|
||||
local ConVarChanged
|
||||
|
||||
if t == "string" or t == "str" then
|
||||
ConVarChanged = function( cvar, old, new )
|
||||
val = new
|
||||
end
|
||||
elseif t == "boolean" or t == "bool" then
|
||||
ConVarChanged = function( cvar, old, new )
|
||||
if new == "0" then
|
||||
val = false
|
||||
elseif new == "1" then
|
||||
val = true
|
||||
else
|
||||
val = (tonumber(new) or 0)>=1
|
||||
end
|
||||
end
|
||||
|
||||
elseif t == "number" or t == "num" then
|
||||
ConVarChanged = function( cvar, old, new )
|
||||
val= tonumber( new ) or 0
|
||||
end
|
||||
|
||||
elseif t == "integer" or t == "int" then
|
||||
ConVarChanged = function( cvar, old, new )
|
||||
val= math.floor(tonumber( new ) or 0)
|
||||
end
|
||||
end
|
||||
|
||||
if not ConVarChanged then error("Invalid type: " .. tostring(t)) end
|
||||
cvars.AddChangeCallback(cvar, ConVarChanged)
|
||||
ConVarChanged(cvar, nil, c:GetString())
|
||||
|
||||
local function GetConVarValue() return val end
|
||||
|
||||
pac.convarcache[cvar]={GetConVarValue,c}
|
||||
return GetConVarValue,c
|
||||
end
|
||||
end
|
||||
|
||||
do
|
||||
local hue =
|
||||
{
|
||||
"red",
|
||||
"orange",
|
||||
"yellow",
|
||||
"green",
|
||||
"turquoise",
|
||||
"blue",
|
||||
"purple",
|
||||
"magenta",
|
||||
}
|
||||
|
||||
local sat =
|
||||
{
|
||||
"pale",
|
||||
"",
|
||||
"strong",
|
||||
}
|
||||
|
||||
local val =
|
||||
{
|
||||
"dark",
|
||||
"",
|
||||
"bright"
|
||||
}
|
||||
|
||||
function pac.HSVToNames(h,s,v)
|
||||
return
|
||||
hue[math.Round((1+(h/360)*#hue))] or hue[1],
|
||||
sat[math.ceil(s*#sat)] or sat[1],
|
||||
val[math.ceil(v*#val)] or val[1]
|
||||
end
|
||||
|
||||
function pac.ColorToNames(c)
|
||||
if c.r == 255 and c.g == 255 and c.b == 255 then return "white", "", "bright" end
|
||||
if c.r == 0 and c.g == 0 and c.b == 0 then return "black", "", "bright" end
|
||||
return pac.HSVToNames(ColorToHSV(Color(c.r, c.g, c.b)))
|
||||
end
|
||||
|
||||
|
||||
function pac.PrettifyName(str)
|
||||
if not str then return end
|
||||
str = str:lower()
|
||||
str = str:gsub("_", " ")
|
||||
return str
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
do
|
||||
local pac_error_mdl = CreateClientConVar("pac_error_mdl","1",true,false,"0 = default error, 1=custom error model, models/yourmodel.mdl")
|
||||
local tc
|
||||
local invalidCache = {}
|
||||
|
||||
function pac.FilterInvalidModel(mdl, fallback)
|
||||
if not isstring(mdl) then
|
||||
mdl = ""
|
||||
end
|
||||
|
||||
if util.IsValidModel(mdl) then
|
||||
invalidCache[mdl] = nil
|
||||
return mdl
|
||||
end
|
||||
|
||||
mdl = mdl:lower():Trim()
|
||||
|
||||
if mdl == "" then
|
||||
return "models/error.mdl"
|
||||
end
|
||||
|
||||
if invalidCache[mdl] then
|
||||
return invalidCache[mdl]
|
||||
end
|
||||
|
||||
-- IsValidModel doesn't always return true... this is expensive though :(
|
||||
if string.GetExtensionFromFilename(mdl) == "mdl" and file.Exists(mdl, "GAME") then
|
||||
return mdl
|
||||
end
|
||||
|
||||
if fallback and fallback:len() > 0 and (util.IsValidModel(fallback) or file.Exists(fallback , "GAME")) then
|
||||
return fallback
|
||||
end
|
||||
|
||||
pac.Message("Invalid model - ", mdl)
|
||||
|
||||
local str = pac_error_mdl:GetString()
|
||||
|
||||
if str == "1" or str == "" then
|
||||
--passthrough
|
||||
elseif str == "0" then
|
||||
invalidCache[mdl] = mdl
|
||||
return mdl
|
||||
elseif util.IsValidModel(str) then
|
||||
invalidCache[mdl] = str
|
||||
return str
|
||||
end
|
||||
|
||||
if tc == nil then
|
||||
if util.IsValidModel("models/props_junk/PopCan01a.mdl") then
|
||||
tc = "models/props_junk/PopCan01a.mdl"
|
||||
else
|
||||
tc = "models/props_junk/popcan01a.mdl"
|
||||
end
|
||||
end
|
||||
|
||||
invalidCache[mdl] = tc
|
||||
return tc
|
||||
end
|
||||
end
|
||||
|
||||
local pac_debug_clmdl = CreateClientConVar("pac_debug_clmdl", "0", true)
|
||||
RunConsoleCommand("pac_debug_clmdl", "0")
|
||||
|
||||
local matsalt = '_' .. (os.time() - 0x40000000)
|
||||
|
||||
function pac.CreateMaterial(name, ...)
|
||||
return CreateMaterial(name .. matsalt, ...)
|
||||
end
|
||||
|
||||
function pac.CreateEntity(model)
|
||||
model = pac.FilterInvalidModel(model, fallback)
|
||||
|
||||
local ent = NULL
|
||||
|
||||
local type = pac_debug_clmdl:GetInt()
|
||||
if type == 0 then
|
||||
ent = ClientsideModel(model) or ent
|
||||
elseif type == 1 then
|
||||
local rag = ClientsideRagdoll(model) or NULL
|
||||
if not rag:IsValid() then
|
||||
ent = ClientsideModel(model) or ent
|
||||
else
|
||||
ent = rag
|
||||
end
|
||||
elseif type == 2 then
|
||||
ent = ents.CreateClientProp(model) or ent -- doesn't render properly
|
||||
if ent:IsValid() then
|
||||
ent:PhysicsDestroy()
|
||||
end
|
||||
elseif type == 3 then
|
||||
|
||||
effects.Register(
|
||||
{
|
||||
Init = function(self, p)
|
||||
self:SetModel(model)
|
||||
ent = self
|
||||
end,
|
||||
|
||||
Think = function()
|
||||
return true
|
||||
end,
|
||||
|
||||
Render = function(self)
|
||||
if self.Draw then self:Draw() else self:DrawModel() end
|
||||
end
|
||||
},
|
||||
|
||||
"pac_model"
|
||||
)
|
||||
|
||||
util.Effect("pac_model", EffectData())
|
||||
end
|
||||
|
||||
if not ent:IsValid() then
|
||||
pac.Message("Failed to create entity with model: ", model)
|
||||
end
|
||||
|
||||
return ent
|
||||
end
|
||||
|
||||
|
||||
do -- hook helpers
|
||||
pac.added_hooks = pac.added_hooks or {}
|
||||
|
||||
function pac.AddHook(event_name, id, func, priority)
|
||||
id = "pac_" .. id
|
||||
|
||||
if not DLib and not ULib then
|
||||
priority = nil
|
||||
end
|
||||
|
||||
if pac.IsEnabled() then
|
||||
hook.Add(event_name, id, func, priority)
|
||||
end
|
||||
|
||||
pac.added_hooks[event_name .. id] = {event_name = event_name, id = id, func = func, priority = priority}
|
||||
end
|
||||
|
||||
function pac.RemoveHook(event_name, id)
|
||||
id = "pac_" .. id
|
||||
|
||||
local data = pac.added_hooks[event_name .. id]
|
||||
|
||||
if data then
|
||||
hook.Remove(data.event_name, data.id)
|
||||
|
||||
pac.added_hooks[event_name .. id] = nil
|
||||
end
|
||||
end
|
||||
|
||||
function pac.CallHook(str, ...)
|
||||
return hook.Run("pac_" .. str, ...)
|
||||
end
|
||||
|
||||
function pac.EnableAddedHooks()
|
||||
for _, data in pairs(pac.added_hooks) do
|
||||
hook.Add(data.event_name, data.id, data.func, data.priority)
|
||||
end
|
||||
end
|
||||
|
||||
function pac.DisableAddedHooks()
|
||||
for _, data in pairs(pac.added_hooks) do
|
||||
hook.Remove(data.event_name, data.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function pac.Material(str, part)
|
||||
if str == "" then return end
|
||||
|
||||
local ply_owner = part:GetPlayerOwner()
|
||||
|
||||
return pac.GetPropertyFromName("GetRawMaterial", str, ply_owner) or Material(str)
|
||||
end
|
||||
|
||||
do
|
||||
--TODO: Table keeping id -> idx mapping
|
||||
local idx = math.random(0x1000)
|
||||
function pac.uid(id)
|
||||
idx = idx + 1
|
||||
if idx>=2^53 then
|
||||
ErrorNoHalt("?????BUG???? Pac UIDs exhausted\n")
|
||||
idx = 0
|
||||
end
|
||||
|
||||
return ("%s%d"):format(id, idx)
|
||||
end
|
||||
end
|
||||
|
||||
function pac.Handleurltex(part, url, callback, shader, additionalData)
|
||||
if not url or not pac.urltex or not url:find("http") then return false end
|
||||
local skip_cache = url:sub(1,1) == "_"
|
||||
|
||||
if not url:match("https?://.+/%S*") then return false end
|
||||
|
||||
pac.urltex.GetMaterialFromURL(
|
||||
pac.FixUrl(url),
|
||||
|
||||
function(mat, tex)
|
||||
if not part:IsValid() then return end
|
||||
|
||||
if callback then
|
||||
callback(mat, tex)
|
||||
else
|
||||
part.Materialm = mat
|
||||
part:CallRecursive("OnMaterialChanged")
|
||||
end
|
||||
|
||||
pac.dprint("set custom material texture %q to %s", url, part:GetName())
|
||||
end,
|
||||
|
||||
skip_cache,
|
||||
shader,
|
||||
nil,
|
||||
nil,
|
||||
additionalData
|
||||
)
|
||||
return true
|
||||
end
|
||||
|
||||
local mat
|
||||
|
||||
for _, ent in pairs(ents.GetAll()) do
|
||||
ent.pac_can_legacy_scale = nil
|
||||
end
|
||||
|
||||
function pac.LegacyScale(ent)
|
||||
local mat0 = ent:GetBoneMatrix(0)
|
||||
if mat0 then
|
||||
local mat = Matrix()
|
||||
mat:Scale(ent.pac_model_scale)
|
||||
ent:SetBoneMatrix(0, mat0 * mat)
|
||||
ent.pac_can_legacy_scale = true
|
||||
end
|
||||
end
|
||||
|
||||
function pac.SetModelScale(ent, scale, size, legacy_scale)
|
||||
if not ent:IsValid() then return end
|
||||
|
||||
if scale and size then
|
||||
ent.pac_model_scale = scale * size
|
||||
end
|
||||
|
||||
if scale and not size then
|
||||
ent.pac_model_scale = scale
|
||||
end
|
||||
|
||||
if not scale and size then
|
||||
ent.pac_model_scale = Vector(size, size, size)
|
||||
end
|
||||
|
||||
if legacy_scale and (ent.pac_can_legacy_scale == nil or ent.pac_can_legacy_scale == true) then
|
||||
ent.pac_matrixhack = true
|
||||
|
||||
if not ent.pac_follow_bones_function then
|
||||
ent.pac_follow_bones_function = pac.build_bone_callback
|
||||
ent:AddCallback("BuildBonePositions", function(ent) pac.build_bone_callback(ent) end)
|
||||
end
|
||||
|
||||
ent:DisableMatrix("RenderMultiply")
|
||||
else
|
||||
ent.pac_matrixhack = false
|
||||
|
||||
if scale then
|
||||
mat = Matrix()
|
||||
|
||||
local x,y,z = scale.x, scale.y, scale.z
|
||||
--local x,y,z = ent.pac_model_scale.x, ent.pac_model_scale.y, ent.pac_model_scale.z
|
||||
|
||||
mat:Scale(Vector(x,y,z))
|
||||
if mat:IsIdentity() then
|
||||
ent:DisableMatrix("RenderMultiply")
|
||||
else
|
||||
ent:EnableMatrix("RenderMultiply", mat)
|
||||
end
|
||||
end
|
||||
|
||||
if size then
|
||||
if ent.pac_enable_ik then
|
||||
ent:SetIK(true)
|
||||
ent:SetModelScale(1, 0)
|
||||
else
|
||||
ent:SetIK(false)
|
||||
ent:SetModelScale(size == 1 and 1.000001 or size, 0)
|
||||
end
|
||||
end
|
||||
|
||||
if not scale and not size then
|
||||
ent:DisableMatrix("RenderMultiply")
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
-- no need to rematch the same pattern
|
||||
local pattern_cache = {{}}
|
||||
|
||||
function pac.StringFind(a, b, simple, case_sensitive)
|
||||
if not a or not b then return end
|
||||
|
||||
if simple and not case_sensitive then
|
||||
a = a:lower()
|
||||
b = b:lower()
|
||||
end
|
||||
|
||||
pattern_cache[a] = pattern_cache[a] or {}
|
||||
|
||||
if pattern_cache[a][b] ~= nil then
|
||||
return pattern_cache[a][b]
|
||||
end
|
||||
|
||||
if simple and a:find(b, nil, true) or not simple and a:find(b) then
|
||||
pattern_cache[a][b] = true
|
||||
return true
|
||||
else
|
||||
pattern_cache[a][b] = false
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function pac.TogglePartDrawing(ent, b)
|
||||
if b then
|
||||
ent.pac_drawing = false
|
||||
pac.ShowEntityParts(ent)
|
||||
ent.pac_shouldnotdraw = false
|
||||
else
|
||||
ent.pac_drawing = true
|
||||
pac.HideEntityParts(ent)
|
||||
ent.pac_shouldnotdraw = true
|
||||
end
|
||||
end
|
||||
|
||||
-- disable pop/push flashlight modes (used for stability in 2D context)
|
||||
function pac.FlashlightDisable(b)
|
||||
pac.flashlight_disabled = b
|
||||
end
|
||||
Reference in New Issue
Block a user