diff --git a/lua/autorun/pac_core_init.lua b/lua/autorun/pac_core_init.lua index ae8e5634f..27055dddc 100644 --- a/lua/autorun/pac_core_init.lua +++ b/lua/autorun/pac_core_init.lua @@ -5,12 +5,12 @@ if SERVER then local function add_files(dir) local files, folders = file.Find(dir .. "*", "LUA") - for key, file_name in pairs(files) do - AddCSLuaFile(dir .. file_name) + for i = 1, #files do + AddCSLuaFile(dir .. files[i]) end - for key, folder_name in pairs(folders) do - add_files(dir .. folder_name .. "/") + for i = 1, #folders do + add_files(dir .. folders[i] .. "/") end end @@ -27,5 +27,4 @@ if CLIENT then end include("pac3/core/client/init.lua") -end - +end \ No newline at end of file diff --git a/lua/autorun/pac_editor_init.lua b/lua/autorun/pac_editor_init.lua index 1cf849850..3d5a30f69 100644 --- a/lua/autorun/pac_editor_init.lua +++ b/lua/autorun/pac_editor_init.lua @@ -13,12 +13,12 @@ if SERVER then local function add_files(dir) local files, folders = file.Find(dir .. "*", "LUA") - for key, file_name in pairs(files) do - AddCSLuaFile(dir .. file_name) + for i = 1, #files do + AddCSLuaFile(dir .. files[i]) end - for key, folder_name in pairs(folders) do - add_files(dir .. folder_name .. "/") + for i = 1, #folders do + add_files(dir .. folders[i] .. "/") end end diff --git a/lua/autorun/pac_extra_init.lua b/lua/autorun/pac_extra_init.lua index ad03f354e..bf5ea07fc 100644 --- a/lua/autorun/pac_extra_init.lua +++ b/lua/autorun/pac_extra_init.lua @@ -13,12 +13,12 @@ if SERVER then local function add_files(dir) local files, folders = file.Find(dir .. "*", "LUA") - for key, file_name in pairs(files) do - AddCSLuaFile(dir .. file_name) + for i = 1, #files do + AddCSLuaFile(dir .. files[i]) end - for key, folder_name in pairs(folders) do - add_files(dir .. folder_name .. "/") + for i = 1, #folders do + add_files(dir .. folders[i] .. "/") end end diff --git a/lua/autorun/pac_restart.lua b/lua/autorun/pac_restart.lua index 40eba4f1c..3111f094e 100644 --- a/lua/autorun/pac_restart.lua +++ b/lua/autorun/pac_restart.lua @@ -1,8 +1,10 @@ AddCSLuaFile() -if SERVER then - return -end +if SERVER then return end + +local file_Find = file.Find +local file_Exists = file.Exists +local file_Read = file.Read local sv_allowcslua = GetConVar("sv_allowcslua") local prefer_local_version = CreateClientConVar("pac_restart_prefer_local_version", "0") @@ -10,25 +12,32 @@ local prefer_local_version = CreateClientConVar("pac_restart_prefer_local_versio function _G.pac_ReloadParts() local pacLocal = _G.pac - local _, dirs = file.Find("addons/*", "MOD") - for _, dir in ipairs(dirs) do - if file.Exists("addons/" .. dir .. "/lua/autorun/pac_editor_init.lua", "MOD") then + local _, dirs = file_Find("addons/*", "MOD") + + for i = 1, #dirs do + local dir = dirs[i] + + if file_Exists("addons/" .. dir .. "/lua/autorun/pac_editor_init.lua", "MOD") then pacLocal.Message("found PAC3 in garrysmod/addons/" .. dir) + local old_include = _G.include local function include(path, ...) local new_path = path - if not file.Exists("addons/" .. dir .. "/lua/" .. path, "MOD") then + + if not file_Exists("addons/" .. dir .. "/lua/" .. path, "MOD") then local src = debug.getinfo(2).source local lua_dir = src:sub(2):match("(.+/)") + if lua_dir:StartWith("addons/" .. dir) then lua_dir = lua_dir:match("addons/.-/lua/(.+)") end + new_path = lua_dir .. path end - if file.Exists("addons/" .. dir .. "/lua/" .. new_path, "MOD") then - local str = file.Read("addons/" .. dir .. "/lua/" .. new_path, "MOD") + if file_Exists("addons/" .. dir .. "/lua/" .. new_path, "MOD") then + local str = file_Read("addons/" .. dir .. "/lua/" .. new_path, "MOD") if str then local func = CompileString(str, "addons/" .. dir .. "/lua/" .. new_path) if isfunction(func) then @@ -53,6 +62,7 @@ function _G.pac_ReloadParts() pac.LoadParts() end) _G.include = old_include + break end end @@ -100,7 +110,7 @@ function _G.pac_Restart() pace.Panic() end - for _, ent in pairs(ents.GetAll()) do + for _, ent in ents.Iterator() do for k in pairs(ent:GetTable()) do if k:sub(0, 4) == "pac_" then ent[k] = nil @@ -133,12 +143,15 @@ function _G.pac_Restart() if not prefer_local_version:GetBool() then pacLocal.Message("pac_restart: not reloading from local version") - for _, path in ipairs((file.Find("autorun/pac*", "LUA"))) do + local files = file_Find("autorun/pac*", "LUA") + + for i = 1, #files do + local path = files[i] + if path:EndsWith("_init.lua") and path ~= "pac_init.lua" then include("autorun/" .. path) end end - elseif sv_allowcslua:GetBool() or LocalPlayer():IsSuperAdmin() then local loadingHit = false @@ -150,25 +163,32 @@ function _G.pac_Restart() pacLocal.Message("pac_restart: LocalPlayer() is superadmin, looking for PAC3 addon..") end - local _, dirs = file.Find("addons/*", "MOD") - for _, dir in ipairs(dirs) do - if file.Exists("addons/" .. dir .. "/lua/autorun/pac_editor_init.lua", "MOD") then + local _, dirs = file_Find("addons/*", "MOD") + + for i = 1, #dirs do + local dir = dirs[i] + + if file_Exists("addons/" .. dir .. "/lua/autorun/pac_editor_init.lua", "MOD") then pacLocal.Message("found PAC3 in garrysmod/addons/" .. dir) + local old_include = _G.include local function include(path, ...) local new_path = path - if not file.Exists("addons/" .. dir .. "/lua/" .. path, "MOD") then + + if not file_Exists("addons/" .. dir .. "/lua/" .. path, "MOD") then local src = debug.getinfo(2).source local lua_dir = src:sub(2):match("(.+/)") + if lua_dir:StartWith("addons/" .. dir) then lua_dir = lua_dir:match("addons/.-/lua/(.+)") end + new_path = lua_dir .. path end - if file.Exists("addons/" .. dir .. "/lua/" .. new_path, "MOD") then - local str = file.Read("addons/" .. dir .. "/lua/" .. new_path, "MOD") + if file_Exists("addons/" .. dir .. "/lua/" .. new_path, "MOD") then + local str = file_Read("addons/" .. dir .. "/lua/" .. new_path, "MOD") if str then local func = CompileString(str, "addons/" .. dir .. "/lua/" .. new_path) if isfunction(func) then @@ -192,7 +212,11 @@ function _G.pac_Restart() _G.include = include - for _, path in ipairs((file.Find("autorun/pac_*", "LUA"))) do + local init_files = file_Find("autorun/pac_*", "LUA") + + for i = 1, #init_files do + local path = init_files[i] + if path:EndsWith("_init.lua") and path ~= "pac_init.lua" then pacLocal.Message("pac_restart: including autorun/" .. path .. "...") @@ -213,11 +237,14 @@ function _G.pac_Restart() end end - if not loadingHit then pacLocal.Message("sv_allowcslua is not enabled or unable to find PAC3 in addons/, loading PAC3 again from server lua") - for _, path in ipairs((file.Find("autorun/pac*", "LUA"))) do + local init_files = file_Find("autorun/pac_*", "LUA") + + for i = 1, #init_files do + local path = init_files[i] + if path:EndsWith("_init.lua") and path ~= "pac_init.lua" then include("autorun/" .. path) end diff --git a/lua/autorun/pac_version.lua b/lua/autorun/pac_version.lua index bb10abe9f..810651170 100644 --- a/lua/autorun/pac_version.lua +++ b/lua/autorun/pac_version.lua @@ -4,17 +4,22 @@ if SERVER then local function pacVersion() local addonFound = false - for k,v in pairs(select(2, file.Find( "addons/*", "GAME" ))) do - if file.Exists("addons/"..v.."/lua/autorun/pac_init.lua", "GAME") then + local _, dirs = file.Find("addons/*", "GAME") + + for i = 1, #dirs do + local v = dirs[i] + + if file.Exists("addons/" .. v .. "/lua/autorun/pac_init.lua", "GAME") then addonFound = true - local dir = "addons/"..v.."/.git/" - local head = file.Read(dir.."HEAD", "GAME") -- Where head points to + + local dir = "addons/" .. v .. "/.git/" + local head = file.Read(dir .. "HEAD", "GAME") -- Where head points to if not head then break end head = string.match(head, "ref:%s+(%S+)") if not head then break end - local lastCommit = string.match(file.Read( dir..head, "GAME") or "", "%S+") + local lastCommit = string.match(file.Read(dir..head, "GAME") or "", "%S+") if not lastCommit then break end return "Git: " .. string.GetFileFromFilename(head) .. " (" .. lastCommit .. ")" @@ -37,15 +42,15 @@ end concommand.Add("pac_version", function() print(PAC_VERSION()) + if CLIENT and PAC_VERSION() == "workshop" then print("Fetching workshop info...") - steamworks.FileInfo( "104691717", function(result) + steamworks.FileInfo("104691717", function(result) print("Updated: " .. os.date("%x %X", result.updated)) end) end end) - --accessed in the editor under pac-help-version function pac.OpenMOTD(mode) local pnl = vgui.Create("DFrame") diff --git a/lua/pac3/core/client/base_drawable.lua b/lua/pac3/core/client/base_drawable.lua index d80722366..9425a8773 100644 --- a/lua/pac3/core/client/base_drawable.lua +++ b/lua/pac3/core/client/base_drawable.lua @@ -1,11 +1,12 @@ +local pac = pac + +local table_insert = table.insert +local table_remove = table.remove local render_OverrideAlphaWriteEnable = render.OverrideAlphaWriteEnable local render_OverrideColorWriteEnable = render.OverrideColorWriteEnable local render_OverrideBlendFunc = render.OverrideBlendFunc local ProtectedCall = ProtectedCall local cam_IgnoreZ = cam.IgnoreZ -local pac = pac -local ipairs = ipairs -local table = table local TEXFILTER_POINT = TEXFILTER.POINT local render_PopFilterMag = render.PopFilterMag local render_PopFilterMin = render.PopFilterMin @@ -111,13 +112,13 @@ do -- modifiers function PART:AddModifier(part) self:RemoveModifier(part) - table.insert(self.modifiers, part) + table_insert(self.modifiers, part) end function PART:RemoveModifier(part) - for i, v in ipairs(self.modifiers) do - if v == part then - table.remove(self.modifiers, i) + for i = 1, #self.modifiers do + if self.modifiers[i] == part then + table_remove(self.modifiers, i) break end end @@ -126,9 +127,10 @@ do -- modifiers function PART:ModifiersPreEvent(event) if not self.modifiers[1] then return end - for _, part in ipairs(self.modifiers) do - if not part:IsHidden() then + for i = 1, #self.modifiers do + local part = self.modifiers[i] + if not part:IsHidden() then if not part.pre_draw_events then part.pre_draw_events = {} end if not part.pre_draw_events[event] then part.pre_draw_events[event] = "Pre" .. event end @@ -142,9 +144,10 @@ do -- modifiers function PART:ModifiersPostEvent(event) if not self.modifiers[1] then return end - for _, part in ipairs(self.modifiers) do - if not part:IsHidden() then + for i = 1, #self.modifiers do + local part = self.modifiers[i] + if not part:IsHidden() then if not part.post_draw_events then part.post_draw_events = {} end if not part.post_draw_events[event] then part.post_draw_events[event] = "Post" .. event end @@ -167,15 +170,19 @@ local function call_draw() _self:OnDraw() end +local type_opaque = "opaque" +local type_translucent = "translucent" +local type_viewmodel = "viewmodel" +local type_hands = "hands" + function PART:Draw(draw_type) if not self.OnDraw or not self.Enabled or self:IsHiddenCached() then return end - if - draw_type == "viewmodel" or draw_type == "hands" or - ((self.Translucent == true or self.force_translucent == true) and draw_type == "translucent") or - ((self.Translucent == false or self.force_translucent == false) and draw_type == "opaque") + if ((self.Translucent == false or self.force_translucent == false) and draw_type == type_opaque) + or ((self.Translucent == true or self.force_translucent == true) and draw_type == type_translucent) + or draw_type == type_viewmodel or draw_type == type_hands then - if not self.HandleModifiersManually then self:ModifiersPreEvent('OnDraw', draw_type) end + if not self.HandleModifiersManually then self:ModifiersPreEvent("OnDraw", draw_type) end if self.IgnoreZ then cam_IgnoreZ(true) end @@ -199,7 +206,7 @@ function PART:Draw(draw_type) if self.IgnoreZ then cam_IgnoreZ(false) end - if not self.HandleModifiersManually then self:ModifiersPostEvent('OnDraw', draw_type) end + if not self.HandleModifiersManually then self:ModifiersPostEvent("OnDraw", draw_type) end end end diff --git a/lua/pac3/core/client/base_movable.lua b/lua/pac3/core/client/base_movable.lua index aa81d9112..523cc8e41 100644 --- a/lua/pac3/core/client/base_movable.lua +++ b/lua/pac3/core/client/base_movable.lua @@ -195,7 +195,10 @@ function PART:CalcAngles(ang, wpos) local nearest_dist = math.huge local owner_ent = part:GetRootPart():GetOwner() - for _,ent in pairs(ents.FindInSphere(wpos, 5000)) do + local ents_in_sphere = ents.FindInSphere(wpos, 5000) + + for i = 1, #ents_in_sphere do + local ent = ents_in_sphere[i] if (ent:IsNPC() or ent:IsPlayer()) and ent ~= owner_ent then local dist = (wpos - ent:GetPos()):LengthSqr() if dist < nearest_dist then diff --git a/lua/pac3/core/client/base_part.lua b/lua/pac3/core/client/base_part.lua index 598db302a..65b1df9d4 100644 --- a/lua/pac3/core/client/base_part.lua +++ b/lua/pac3/core/client/base_part.lua @@ -1,17 +1,26 @@ -local string_format = string.format -local tostring = tostring +local pac = pac local pace = pace -local assert = assert + local debug_traceback = debug.traceback +local string_format = string.format local math_random = math.random +local table_insert = table.insert +local table_copy = table.Copy +local tostring = tostring +local assert = assert local xpcall = xpcall -local pac = pac local pairs = pairs local ipairs = ipairs local table = table local Color = Color local NULL = NULL -local table_insert = table.insert + +local classname_event = "event" +local prefix_get = "Get" +local prefix_set = "Set" + +local pac_editor_scale = GetConVar("pac_editor_scale") +local pac_popups_preferred_location = GetConVar("pac_popups_preferred_location") local BUILDER, PART = pac.PartTemplate() @@ -53,6 +62,18 @@ function PART:IsValid() return self.is_valid end +local pac_enable_convars = {} +local function get_enable_convar(classname) + local convar = pac_enable_convars[classname] + + if not convar then + convar = GetConVar("pac_enable_" .. string.Replace(classname, " ", "_"):lower()) + pac_enable_convars[classname] = convar + end + + return convar +end + function PART:PreInitialize() self.Children = {} self.ChildrenMap = {} @@ -62,8 +83,9 @@ function PART:PreInitialize() self.hide_disturbing = false self.active_events = {} self.active_events_ref_count = 0 - local cvarName = "pac_enable_" .. string.Replace(self.ClassName, " ", "_"):lower() - if not GetConVar(cvarName):GetBool() then self:SetWarning("This part class is disabled! Enable it with " .. cvarName .. " 1") end + + local convar = get_enable_convar(self.ClassName) + if not convar:GetBool() then self:SetWarning("This part class is disabled! Enable it with " .. convar:GetName() .. " 1") end end function PART:Initialize() end @@ -81,7 +103,6 @@ end function PART:GetName() if self.Name == "" then - -- recursive call guard if self.last_nice_name_frame and self.last_nice_name_frame == pac.FrameNumber then return self.last_nice_name @@ -94,11 +115,14 @@ function PART:GetName() local count = 0 if self:HasParent() then - for _, val in ipairs(self:GetParent():GetChildren()) do - if val:GetNiceName() == nice then + local children = self:GetParent():GetChildren() + for i = 1, #children do + local ent = children[i] + + if ent:GetNiceName() == nice then count = count + 1 - if val == self then + if ent == self then num = count end end @@ -203,16 +227,16 @@ do -- owner end function PART:GetParentOwner() - if self.TargetEntity:IsValid() and self.TargetEntity ~= self then return self.TargetEntity:GetOwner() end - - for _, parent in ipairs(self:GetParentList()) do + local parents = self:GetParentList() + for i = 1, #parents do + local parent = parents[i] -- legacy behavior - if parent.ClassName == "event" and not parent.RootOwner then + if parent.ClassName == classname_event and not parent.RootOwner then local parent = parent:GetParent() if parent:IsValid() then local parent = parent:GetParent() @@ -241,7 +265,6 @@ do -- owner end do -- scene graph - function PART:OnParent() end function PART:OnChildAdd() end function PART:OnUnParent() end @@ -253,7 +276,7 @@ do -- scene graph -- this will handle cases like if a part is removed and added again for _, key in pairs(self.PartReferenceKeys) do if self[key] and self[key].UniqueID == part.UniqueID then - self["Set" .. key](self, part) + self[prefix_set .. key](self, part) end end @@ -265,7 +288,7 @@ do -- scene graph if not keys then return end for _, key in pairs(keys) do - self["Set" .. key](self, part) + self[prefix_set .. key](self, part) end end end @@ -316,8 +339,9 @@ do -- scene graph function PART:InvalidateChildrenList() self.children_list = nil - for _, parent in ipairs(self:GetParentList()) do - parent.children_list = nil + local parents = self:GetParentList() + for i = 1, #parents do + parents[i].children_list = nil end end end @@ -354,8 +378,9 @@ do -- scene graph function PART:InvalidateParentList() self.parent_list = nil - for _, child in ipairs(self:GetChildrenList()) do - child.parent_list = nil + local children = self:GetChildrenList() + for i = 1, #children do + children[i].parent_list = nil end end @@ -363,8 +388,9 @@ do -- scene graph self.parent_list = quick_copy(parent_list) self.parent_list[1] = parent - for _, child in ipairs(self:GetChildren()) do - child:InvalidateParentListPartial(self.parent_list, self) + local children = self:GetChildren() + for i = 1, #children do + children[i]:InvalidateParentListPartial(self.parent_list, self) end end end @@ -445,8 +471,9 @@ do -- scene graph function PART:RemoveChild(part) self.ChildrenMap[part] = nil - for i, val in ipairs(self:GetChildren()) do - if val == part then + local children = self:GetChildren() + for i = 1, #children do + if children[i] == part then self:InvalidateChildrenList() table.remove(self.Children, i) part:OnUnParent(self) @@ -461,27 +488,35 @@ do -- scene graph return self end - function PART:CallRecursive(func, a,b,c) + function PART:CallRecursive(func, a, b, c) assert(c == nil, "EXTEND ME") + if self[func] then - self[func](self, a,b,c) + self[func](self, a, b, c) end - for _, child in ipairs(self:GetChildrenList()) do + local children = self:GetChildrenList() + for i = 1, #children do + local child = children[i] + if child[func] then - child[func](child, a,b,c) + child[func](child, a, b, c) end end end - function PART:CallRecursiveOnClassName(class_name, func, a,b,c) + function PART:CallRecursiveOnClassName(class_name, func, a, b, c) assert(c == nil, "EXTEND ME") + if self[func] and self.ClassName == class_name then self[func](self, a,b,c) end - for _, child in ipairs(self:GetChildrenList()) do - if child[func] and self.ClassName == class_name then + local children = self:GetChildrenList() + for i = 1, #children do + local child = children[i] + + if child[func] and child.ClassName == class_name then child[func](child, a,b,c) end end @@ -490,19 +525,22 @@ do -- scene graph function PART:SetKeyValueRecursive(key, val) self[key] = val - for _, child in ipairs(self:GetChildrenList()) do - child[key] = val + local children = self:GetChildrenList() + for i = 1, #children do + children[i][key] = val end end - function PART:RemoveChildren() self:InvalidateChildrenList() - for i, part in ipairs(self:GetChildren()) do + local children = self:GetChildren() + for i = 1, #children do + local part = children[i] + part:Remove(true) - self.Children[i] = nil self.ChildrenMap[part] = nil + self.Children[i] = nil end end @@ -553,7 +591,9 @@ do -- scene graph self:InvalidateChildrenList() - for _, part in ipairs(self:GetChildren()) do + local children = self:GetChildren() + for i = 1, #children do + local part = children[i] local owner_id = part:GetPlayerOwnerId() if owner_id then @@ -565,16 +605,22 @@ do -- scene graph end function PART:SetSmallIcon(str) - if str == "event" then str = "icon16/clock_red.png" end + if str == classname_event then str = "icon16/clock_red.png" end + if self.pace_tree_node then if self.pace_tree_node.Icon then if not self.pace_tree_node.Icon.event_icon then + pac_editor_scale = pac_editor_scale or GetConVar("pac_editor_scale") + local pnl = vgui.Create("DImage", self.pace_tree_node.Icon) + self.pace_tree_node.Icon.event_icon_alt = true self.pace_tree_node.Icon.event_icon = pnl - pnl:SetSize(8*(1 + 0.5*(GetConVar("pac_editor_scale"):GetFloat()-1)), 8*(1 + 0.5*(GetConVar("pac_editor_scale"):GetFloat()-1))) - pnl:SetPos(8*(1 + 0.5*(GetConVar("pac_editor_scale"):GetFloat()-1)), 8*(1 + 0.5*(GetConVar("pac_editor_scale"):GetFloat()-1))) + + pnl:SetSize(8 * (1 + 0.5 * (pac_editor_scale:GetFloat() - 1)), 8 * (1 + 0.5 * (pac_editor_scale:GetFloat() - 1))) + pnl:SetPos(8 * (1 + 0.5 * (pac_editor_scale:GetFloat() - 1)), 8 * (1 + 0.5 * (pac_editor_scale:GetFloat() - 1))) end + self.pace_tree_node.Icon.event_icon_alt = true self.pace_tree_node.Icon.event_icon:SetImage(str) self.pace_tree_node.Icon.event_icon:SetVisible(true) @@ -656,7 +702,10 @@ do -- hidden / events self:OnShow(true) end - for _, child in ipairs(self:GetChildrenList()) do + local children = self:GetChildrenList() + for i = 1, #children do + local child = children[i] + child:SetDrawHidden(false) if not child:IsHidden() then @@ -683,8 +732,9 @@ do -- hidden / events return true end - for _, parent in ipairs(self:GetParentList()) do - if is_hidden(parent) then + local parents = self:GetParentList() + for i = 1, #parents do + if is_hidden(parents[i]) then return true end end @@ -727,11 +777,15 @@ do -- hidden / events return "pac_hide_disturbing is set to 1" end - for i,part in ipairs(self:GetParentList()) do + local parents = self:GetParentList() + for i = 1, #parents do + local part = parents[i] + if part:IsHidden() then table_insert(found, tostring(part) .. " is parent hiding") end end + if found[1] then return table.concat(found, "\n") end @@ -758,7 +812,10 @@ do -- hidden / events end end - for i,part in ipairs(self:GetParentList()) do + local parents = self:GetParentList() + for i = 1, #parents do + local part = parents[i] + if not found[part] then if part:IsHidden() then found[part] = "parent hidden" @@ -842,7 +899,7 @@ do -- serializing do function PART:GetProperty(name) - local val = self["Get" .. name] + local val = self[prefix_get .. name] if val == nil then if self.GetDynamicProperties then @@ -857,9 +914,11 @@ do -- serializing end function PART:SetProperty(key, val) - if self["Set" .. key] ~= nil then - if self["Get" .. key](self) ~= val then - self["Set" .. key](self, val) + local setFunc = self[prefix_set .. key] + + if setFunc ~= nil then + if self[prefix_get .. key](self) ~= val then + setFunc(self, val) end elseif self.GetDynamicProperties then local info = self:GetDynamicProperties()[key] @@ -879,8 +938,8 @@ do -- serializing table_insert(out, { key = key, - set = function(v) self["Set" .. key](self, v) end, - get = function() return self["Get" .. key](self) end, + set = function(v) self[prefix_set .. key](self, v) end, + get = function() return self[prefix_get .. key](self) end, udata = pac.GetPropertyUserdata(self, key) or {}, }) @@ -963,12 +1022,14 @@ do -- serializing for key, value in next, tbl.self do if key == "UniqueID" then goto CONTINUE end + local setFunc = self[prefix_set .. key] - if self["Set" .. key] then + if setFunc then if key == "Material" then table_insert(self.delayed_variables, {key = key, val = value}) end - self["Set" .. key](self, value) + + setFunc(self, value) elseif key ~= "ClassName" then pac.dprint("settable: unhandled key [%q] = %q", key, tostring(value)) end @@ -1017,7 +1078,7 @@ do -- serializing if copy_id then local pepper, uid_list - tbl, pepper, uid_list = make_copy(table.Copy(tbl), copy_id) + tbl, pepper, uid_list = make_copy(table_copy(tbl), copy_id) update_uids(uid_list, pepper) end @@ -1038,7 +1099,7 @@ do -- serializing local tbl = {self = {ClassName = self.ClassName}, children = {}} for _, key in pairs(self:GetStorableVars()) do - local var = self[key] and self["Get" .. key](self) or self[key] + local var = self[key] and self[prefix_get .. key](self) or self[key] var = pac.CopyValue(var) or var if make_copy_name and var ~= "" and (key == "UniqueID" or key:sub(-3) == "UID") then @@ -1055,11 +1116,10 @@ do -- serializing end end - for _, part in ipairs(self:GetChildren()) do - if not self.is_valid or self.is_deattached then - - else - table_insert(tbl.children, part:ToTable()) + local children = self:GetChildren() + for i = 1, #children do + if self.is_valid and not self.is_deattached then + table_insert(tbl.children, children[i]:ToTable()) end end @@ -1072,7 +1132,7 @@ do -- serializing local tbl = {self = {ClassName = self.ClassName}, children = {}} for _, key in pairs(self:GetStorableVars()) do - local var = self[key] and self["Get" .. key](self) or self[key] + local var = self[key] and self[prefix_get .. key](self) or self[key] var = pac.CopyValue(var) or var if key == "Name" and self[key] == "" then @@ -1085,11 +1145,10 @@ do -- serializing end end - for _, part in ipairs(self:GetChildren()) do - if not self.is_valid or self.is_deattached then - - else - table_insert(tbl.children, part:ToSaveTable()) + local children = self:GetChildren() + for i = 1, #children do + if self.is_valid and not self.is_deattached then + table_insert(tbl.children, children[i]:ToSaveTable()) end end @@ -1104,12 +1163,14 @@ do -- serializing for key, value in pairs(tbl.self) do if key == "UniqueID" then goto CONTINUE end + local setFunc = self[prefix_set .. key] - if self["Set" .. key] then + if setFunc then if key == "Material" then table_insert(self.delayed_variables, {key = key, val = value}) end - self["Set" .. key](self, value) + + setFunc(self, value) elseif key ~= "ClassName" then pac.dprint("settable: unhandled key [%q] = %q", key, tostring(value)) end @@ -1143,15 +1204,14 @@ do -- serializing goto CONTINUE end - tbl.self[key] = pac.CopyValue(self["Get" .. key](self)) + tbl.self[key] = pac.CopyValue(self[prefix_get .. key](self)) ::CONTINUE:: end - for _, part in ipairs(self:GetChildren()) do - if not self.is_valid or self.is_deattached then - - else - table_insert(tbl.children, part:ToUndoTable()) + local children = self:GetChildren() + for i = 1, #children do + if self.is_valid and not self.is_deattached then + table_insert(tbl.children, children[i]:ToUndoTable()) end end @@ -1201,10 +1261,13 @@ do return end - if self.delayed_variables then + local delayedVars = self.delayed_variables + + if delayedVars then + for i = 1, #delayedVars do + local data = delayedVars[i] - for _, data in ipairs(self.delayed_variables) do - self["Set" .. data.key](self, data.val) + self[prefix_set .. data.key](self, data.val) end self.delayed_variables = nil @@ -1223,25 +1286,33 @@ end --the popup system function PART:SetupEditorPopup(str, force_open, tbl) local legacy_help_popup_hack = false + if not tbl then legacy_help_popup_hack = false elseif tbl.from_legacy then legacy_help_popup_hack = true end + if not IsValid(self) then return end + pac_popups_preferred_location = pac_popups_preferred_location or GetConVar("pac_popups_preferred_location") + local popup_config_table = tbl or { - pac_part = self, obj_type = GetConVar("pac_popups_preferred_location"):GetString(), + pac_part = self, + obj_type = pac_popups_preferred_location:GetString(), hoverfunc = function() end, doclickfunc = function() end, - panel_exp_width = 900, panel_exp_height = 400 + panel_exp_width = 900, + panel_exp_height = 400 } local default_state = str == nil or str == "" local info_string - if self.ClassName == "event" and default_state then + + if self.ClassName == classname_event and default_state then info_string = self:GetEventTutorialText() end + info_string = info_string or str or self.ClassName .. "\nno special information available" if default_state and pace then @@ -1265,7 +1336,7 @@ function PART:SetupEditorPopup(str, force_open, tbl) function tree_node:Think() --if not part.killpopup and ((self.Label:IsHovered() and GetConVar("pac_popups_preferred_location"):GetString() == "pac tree label") or input.IsButtonDown(KEY_F1) or force_open) then - if not part.killpopup and ((self.Label:IsHovered() and GetConVar("pac_popups_preferred_location"):GetString() == "pac tree label") or force_open) then + if not part.killpopup and ((self.Label:IsHovered() and pac_popups_preferred_location:GetString() == "pac tree label") or force_open) then if not self.popuppnl_is_up and not IsValid(self.popupinfopnl) and not part.killpopup and not legacy_help_popup_hack then self.popupinfopnl = pac.InfoPopup( info_string, diff --git a/lua/pac3/core/client/bones.lua b/lua/pac3/core/client/bones.lua index 71f3aab04..f6090fc72 100644 --- a/lua/pac3/core/client/bones.lua +++ b/lua/pac3/core/client/bones.lua @@ -1,18 +1,19 @@ +local pac = pac local pairs = pairs -local IsValid = IsValid local unpack = unpack +local IsValid = IsValid local LocalToWorld = LocalToWorld -local math_sin = math.sin local RealTime = RealTime local Entity = Entity -local ipairs = ipairs -local NULL = NULL local LerpVector = LerpVector local LerpAngle = LerpAngle local Angle = Angle local Vector = Vector +local NULL = NULL + +local math_sin = math.sin local util_QuickTrace = util.QuickTrace -local pac = pac + local pac_isCameraAllowed = pac.CreateClientConVarFast("pac_enable_camera_as_bone", "1", true, "boolean") pac.BoneNameReplacements = @@ -35,7 +36,9 @@ pac.BoneNameReplacements = } function pac.GetAllBones(ent) - ent = ent or NULL + if not ent then + ent = NULL + end local tbl = {} @@ -45,12 +48,15 @@ function pac.GetAllBones(ent) local count = ent:GetBoneCount() or 0 + local boneNameReplacements = pac.BoneNameReplacements + for bone = 0, count do local name = ent:GetBoneName(bone) local friendly = name if name then - for _, value in pairs(pac.BoneNameReplacements) do + for i = 1, #boneNameReplacements do + local value = boneNameReplacements[i] friendly = friendly:gsub(value[1], value[2]) end @@ -77,11 +83,14 @@ function pac.GetAllBones(ent) local attachments = ent:GetAttachments() if attachments then - for _, data in pairs(attachments) do + for i = 1, #attachments do + local data = attachments[i] + local parent_i = ent:GetParentAttachment(data.id) if parent_i == -1 then parent_i = nil end + local friendly = data.name or "????" friendly = friendly @@ -207,15 +216,14 @@ local function GetBonePosition(ent, id) return pos, ang end -local angle_origin = Angle(0,0,0) -local UP = Vector(0,0,1):Angle() +local angle_origin = Angle(0, 0, 0) +local UP = Vector(0, 0, 1):Angle() function pac.GetBonePosAng(ent, id, parent) if not ent:IsValid() then return Vector(), Angle() end if id == "physgun_beam_endpos" then if ent.pac_drawphysgun_event then - local ply, wep, enabled, target, bone, hitpos = unpack(ent.pac_drawphysgun_event) local endpos @@ -236,7 +244,7 @@ function pac.GetBonePosAng(ent, id, parent) endpos = target:LocalToWorld(hitpos) end else - endpos = ply.pac_traceres and ply.pac_traceres.HitPos or util_QuickTrace(ply:EyePos(), ply:EyeAngles():Forward() * 16000, {ply, ply:GetParent()}).HitPos + endpos = ply.pac_traceres and ply.pac_traceres.HitPos or util_QuickTrace(ply:EyePos(), ply:GetAimVector() * 16000, {ply, ply:GetParent()}).HitPos end end @@ -250,7 +258,8 @@ function pac.GetBonePosAng(ent, id, parent) end elseif id == "player_eyes" then local oldEnt = ent -- Track reference to the original entity in case we aren't allowed to draw here - local ent = ent.pac_traceres and ent.pac_traceres.Entity or util_QuickTrace(ent:EyePos(), ent:EyeAngles():Forward() * 16000, {ent, ent:GetParent()}).Entity + + local ent = ent.pac_traceres and ent.pac_traceres.Entity or util_QuickTrace(ent:EyePos(), ent:GetAimVector() * 16000, {ent, ent:GetParent()}).Entity local allowed = pac_isCameraAllowed() if ent:IsValid() and (allowed or ent ~= pac.LocalPlayer) then -- Make sure we don't draw on viewer's screen if we aren't allowed to @@ -273,17 +282,17 @@ function pac.GetBonePosAng(ent, id, parent) elseif id == "eyepos_ang" then return ent:EyePos(), ent:GetAngles() elseif id == "hitpos_world_props" then - local res = util_QuickTrace(ent:EyePos(), ent:EyeAngles():Forward() * 16000, function(ent) + local res = util_QuickTrace(ent:EyePos(), ent:GetAimVector() * 16000, function(ent) return ent:GetClass() == "prop_physics" end) return res.HitPos, res.HitNormal:Angle() elseif id == "hitpos_world" then - local res = util_QuickTrace(ent:EyePos(), ent:EyeAngles():Forward() * 16000, function(ent) + local res = util_QuickTrace(ent:EyePos(), ent:GetAimVector() * 16000, function(ent) return ent:IsWorld() end) return res.HitPos, res.HitNormal:Angle() elseif id == "hitpos_world_noang" then - local res = util_QuickTrace(ent:EyePos(), ent:EyeAngles():Forward() * 16000, function(ent) + local res = util_QuickTrace(ent:EyePos(), ent:GetAimVector() * 16000, function(ent) return ent:IsWorld() end) return res.HitPos, angle_origin @@ -291,7 +300,7 @@ function pac.GetBonePosAng(ent, id, parent) if ent.pac_traceres then return ent.pac_traceres.HitPos, ent.pac_traceres.HitNormal:Angle() else - local res = util_QuickTrace(ent:EyePos(), ent:EyeAngles():Forward() * 16000, {ent, ent:GetOwner()}) + local res = util_QuickTrace(ent:EyePos(), ent:GetAimVector() * 16000, {ent, ent:GetOwner()}) return res.HitPos, res.HitNormal:Angle() end @@ -299,7 +308,7 @@ function pac.GetBonePosAng(ent, id, parent) if ent.pac_traceres then return ent.pac_traceres.HitPos, ent:EyeAngles() else - local res = util_QuickTrace(ent:EyePos(), ent:EyeAngles():Forward() * 16000, {ent, ent:GetOwner()}) + local res = util_QuickTrace(ent:EyePos(), ent:GetAimVector() * 16000, {ent, ent:GetOwner()}) return res.HitPos, ent:EyeAngles() end @@ -309,7 +318,7 @@ function pac.GetBonePosAng(ent, id, parent) ang.p = 0 return ent.pac_traceres.HitPos, ang else - local res = util_QuickTrace(ent:EyePos(), ent:EyeAngles():Forward() * 16000, {ent, ent:GetOwner()}) + local res = util_QuickTrace(ent:EyePos(), ent:GetAimVector() * 16000, {ent, ent:GetOwner()}) return res.HitPos, ent:EyeAngles() end @@ -398,6 +407,9 @@ do -- bone manipulation for boneanimlib local ManipulateBonePosition = entmeta.ManipulateBonePosition local ManipulateBoneAngles = entmeta.ManipulateBoneAngles local ManipulateBoneJiggle = entmeta.ManipulateBoneJiggle + local SetFlexScale = entmeta.SetFlexScale + local SetFlexWeight = entmeta.SetFlexWeight + local GetFlexWeight = entmeta.GetFlexWeight function pac.ResetBones(ent) ent.pac_bones_once = true @@ -430,18 +442,15 @@ do -- bone manipulation for boneanimlib if ent.pac_touching_flexes then local reset_scale = false for id, time in pairs(ent.pac_touching_flexes) do - if not reset_scale then - ent:SetFlexScale(1) + SetFlexScale(ent, 1) reset_scale = true end if time < pac.RealTime then - ent:SetFlexWeight(id, 0) - else - if ent:GetFlexWeight(id) == 0 then - ent.pac_touching_flexes[id] = nil - end + SetFlexWeight(ent, id, 0) + elseif GetFlexWeight(ent, id) == 0 then + ent.pac_touching_flexes[id] = nil end end end @@ -449,41 +458,60 @@ do -- bone manipulation for boneanimlib hook.Call("PAC3ResetBones", nil, ent) end - function pac.SetEntityBoneMatrix(ent, i, matrix) - pac.ManipulateBonePosition(ent, i, matrix:GetTranslation()) - pac.ManipulateBoneAngles(ent, i, matrix:GetAngles()) - end + local function pacManipulateBonePosition(ent, entTbl, id, var) + if not entTbl.pac_boneanim then + entTbl.pac_boneanim = {positions = {}, angles = {}} + end + entTbl.pac_boneanim.positions[id] = var - function pac.ResetEntityBoneMatrix(ent, i) - pac.ManipulateBoneAngles(ent, i, angle_zero) - pac.ManipulateBonePosition(ent, i, vector_origin) + if not entTbl.pac_has_parts then + ManipulateBonePosition(ent, id, var) + end end - function pac.ManipulateBonePosition(ply, id, var) - ply.pac_boneanim = ply.pac_boneanim or {positions = {}, angles = {}} + local function pacManipulateBoneAngles(ent, entTbl, id, var) + if not entTbl.pac_boneanim then + entTbl.pac_boneanim = {positions = {}, angles = {}} + end - ply.pac_boneanim.positions[id] = var + entTbl.pac_boneanim.angles[id] = var - if not ply.pac_has_parts then - ply:ManipulateBonePosition(id, var) + if not entTbl.pac_has_parts then + ManipulateBoneAngles(ent, id, var) end end - function pac.ManipulateBoneAngles(ply, id, var) - ply.pac_boneanim = ply.pac_boneanim or {positions = {}, angles = {}} + function pac.SetEntityBoneMatrix(ent, i, matrix, entTbl) + if not entTbl then + entTbl = ent:GetTable() + end + + if not entTbl.pac_boneanim then + entTbl.pac_boneanim = {positions = {}, angles = {}} + end - ply.pac_boneanim.angles[id] = var + pacManipulateBonePosition(ent, entTbl, i, matrix:GetTranslation()) + pacManipulateBoneAngles(ent, entTbl, i, matrix:GetAngles()) + end - if not ply.pac_has_parts then - ply:ManipulateBoneAngles(id, var) + function pac.ResetEntityBoneMatrix(ent, i, entTbl) + if not entTbl then + entTbl = ent:GetTable() end + + if not entTbl.pac_boneanim then + entTbl.pac_boneanim = {positions = {}, angles = {}} + end + + pacManipulateBonePosition(ent, entTbl, i, vector_origin) + pacManipulateBoneAngles(ent, entTbl, i, angle_zero) end end if Entity(1):IsPlayer() and not PAC_RESTART then timer.Simple(0, function() - for _, v in ipairs(ents.GetAll()) do + for _, v in ents.Iterator() do pac.ResetBoneCache(v) end end) diff --git a/lua/pac3/core/client/class.lua b/lua/pac3/core/client/class.lua index cd013ea6c..62596cec0 100644 --- a/lua/pac3/core/client/class.lua +++ b/lua/pac3/core/client/class.lua @@ -1,13 +1,16 @@ -local ipairs = ipairs -local table_insert = table.insert +local pac = pac local isnumber = isnumber -local tonumber = tonumber +local istable = istable local isstring = isstring +local tonumber = tonumber local tostring = tostring -local table_Merge = table.Merge -local istable = istable -local pac = pac local setmetatable = setmetatable +local table_insert = table.insert +local table_Merge = table.Merge + +local prefix_get = "Get" +local prefix_set = "Set" +local suffix_uid = "UID" pac.PartTemplates = pac.PartTemplates or {} pac.VariableOrder = {} @@ -57,8 +60,8 @@ do end local function insert_key(tbl, key) - for _, k in ipairs(tbl) do - if k == key then + for i = 1, #tbl do + if tbl[i] == key then return end end @@ -67,7 +70,6 @@ do end function META:SetPropertyGroup(name) - local tbl = self.PART self.group = name @@ -102,15 +104,18 @@ do pac.VariableOrder[tbl.ClassName] = pac.VariableOrder[tbl.ClassName] or {} insert_key(pac.VariableOrder[tbl.ClassName], key) + local setKey = prefix_set .. key + local getKey = prefix_get .. key + if isnumber(def) then - tbl["Set" .. key] = tbl["Set" .. key] or function(self, var) self[key] = tonumber(var) end - tbl["Get" .. key] = tbl["Get" .. key] or function(self) return tonumber(self[key]) end + tbl[setKey] = tbl[setKey] or function(self, var) self[key] = tonumber(var) end + tbl[getKey] = tbl[getKey] or function(self) return tonumber(self[key]) end elseif isstring(def) then - tbl["Set" .. key] = tbl["Set" .. key] or function(self, var) self[key] = tostring(var) end - tbl["Get" .. key] = tbl["Get" .. key] or function(self) return tostring(self[key]) end + tbl[setKey] = tbl[setKey] or function(self, var) self[key] = tostring(var) end + tbl[getKey] = tbl[getKey] or function(self) return tostring(self[key]) end else - tbl["Set" .. key] = tbl["Set" .. key] or function(self, var) self[key] = var end - tbl["Get" .. key] = tbl["Get" .. key] or function(self) return self[key] end + tbl[setKey] = tbl[setKey] or function(self, var) self[key] = var end + tbl[getKey] = tbl[getKey] or function(self) return self[key] end end tbl[key] = def @@ -137,12 +142,16 @@ do local PART = self.PART - self:GetSet(key .. "UID", "", udata) + local setKey = prefix_set .. key + local getKey = prefix_get .. key + local uidKey = key .. suffix_uid + + self:GetSet(uidKey, "", udata) - PART["Set" .. key .. "UID"] = function(self, uid) + PART[setKey .. suffix_uid] = function(self, uid) if uid == "" or not uid then - self["Set" .. key](self, NULL) - self[key.."UID"] = "" + self[setKey](self, NULL) + self[uidKey] = "" return end @@ -150,7 +159,7 @@ do uid = uid.UniqueID end - self[key.."UID"] = uid + self[uidKey] = uid local owner_id = self:GetPlayerOwnerId() local part = pac.GetPartFromUniqueID(owner_id, uid) @@ -158,10 +167,10 @@ do if part:IsValid() then if part == self then part = NULL - self[key.."UID"] = "" + self[uidKey] = "" end - self["Set" .. key](self, part) + self[setKey](self, part) elseif uid ~= "" then self.unresolved_uid_parts = self.unresolved_uid_parts or {} self.unresolved_uid_parts[owner_id] = self.unresolved_uid_parts[owner_id] or {} @@ -170,15 +179,15 @@ do end end - PART["Set" .. key] = PART["Set" .. key] or function(self, var) + PART[setKey] = PART[setKey] or function(self, var) self[key] = var if var and var:IsValid() then - self[key.."UID"] = var:GetUniqueID() + self[uidKey] = var:GetUniqueID() else - self[key.."UID"] = "" + self[uidKey] = "" end end - PART["Get" .. key] = PART["Get" .. key] or function(self) return self[key] end + PART[getKey] = PART[getKey] or function(self) return self[key] end PART[key] = NULL PART.PartReferenceKeys = PART.PartReferenceKeys or {} @@ -188,8 +197,8 @@ do end function META:RemoveProperty(key) - self.PART["Set" .. key] = nil - self.PART["Get" .. key] = nil + self.PART[prefix_set .. key] = nil + self.PART[prefix_get .. key] = nil self.PART["Is" .. key] = nil self.PART[key] = nil diff --git a/lua/pac3/core/client/hooks.lua b/lua/pac3/core/client/hooks.lua index 49cb5e2ab..b12a2fa31 100644 --- a/lua/pac3/core/client/hooks.lua +++ b/lua/pac3/core/client/hooks.lua @@ -1,6 +1,14 @@ -local pairs = pairs -local IsEntity = IsEntity +local MOVETYPE_NOCLIP = MOVETYPE_NOCLIP local next = next +local IsEntity = IsEntity + +local entMeta = FindMetaTable("Entity") +local IsEntValid = entMeta.IsValid +local GetTable = entMeta.GetTable +local SetCycle = entMeta.SetCycle +local SetPoseParameter = entMeta.SetPoseParameter + +local classname_prisoner_pod = "prop_vehicle_prisoner_pod" pac.AddHook("RenderScene", "eyeangles_eyepos", function(pos, ang) pac.EyePos = pos @@ -8,7 +16,6 @@ pac.AddHook("RenderScene", "eyeangles_eyepos", function(pos, ang) end) pac.AddHook("DrawPhysgunBeam", "physgun_event", function(ply, wep, enabled, target, bone, hitpos) - if enabled then ply.pac_drawphysgun_event = {ply, wep, enabled, target, bone, hitpos} else @@ -17,7 +24,7 @@ pac.AddHook("DrawPhysgunBeam", "physgun_event", function(ply, wep, enabled, targ local pac_drawphysgun_event_part = ply.pac_drawphysgun_event_part if pac_drawphysgun_event_part then - for event in pairs(pac_drawphysgun_event_part) do + for event in next, pac_drawphysgun_event_part do if event:IsValid() then event:OnThink() else @@ -26,7 +33,6 @@ pac.AddHook("DrawPhysgunBeam", "physgun_event", function(ply, wep, enabled, targ end end - if ply.pac_hide_physgun_beam then return false end @@ -34,65 +40,66 @@ end) do pac.AddHook("UpdateAnimation", "event_part", function(ply) - if not IsEntity(ply) or not ply:IsValid() then return end + if not IsEntity(ply) or not IsEntValid(ply) then return end + local plyTbl = GetTable(ply) - if ply.pac_death_physics_parts and ply:Alive() and ply.pac_physics_died then + if plyTbl.pac_death_physics_parts and ply:Alive() and plyTbl.pac_physics_died then pac.CallRecursiveOnOwnedParts(ply, "OnBecomePhysics") - ply.pac_physics_died = false + plyTbl.pac_physics_died = false end do - local tbl = ply.pac_pose_params + local tbl = plyTbl.pac_pose_params if tbl then - for _, data in pairs(tbl) do - ply:SetPoseParameter(data.key, data.val) + for _, data in next, tbl do + SetPoseParameter(ply, data.key, data.val) end end end local animrate = 1 - if ply.pac_global_animation_rate and ply.pac_global_animation_rate ~= 1 then - if ply.pac_global_animation_rate == 0 then + if plyTbl.pac_global_animation_rate and plyTbl.pac_global_animation_rate ~= 1 then + if plyTbl.pac_global_animation_rate == 0 then animrate = ply:GetModelScale() * 2 - elseif ply.pac_global_animation_rate ~= 1 then - ply:SetCycle((pac.RealTime * ply.pac_global_animation_rate)%1) - animrate = ply.pac_global_animation_rate + elseif plyTbl.pac_global_animation_rate ~= 1 then + SetCycle(ply, (pac.RealTime * plyTbl.pac_global_animation_rate) % 1) + + animrate = plyTbl.pac_global_animation_rate end end - if ply.pac_animation_sequences then - local part, thing = next(ply.pac_animation_sequences) + if plyTbl.pac_animation_sequences then + local part, thing = next(plyTbl.pac_animation_sequences) if part and part:IsValid() then - if part.OwnerCycle then if part.Rate == 0 then animrate = 1 - ply:SetCycle(part.Offset % 1) + SetCycle(ply, part.Offset % 1) else animrate = animrate * part.Rate end end elseif part and not part:IsValid() then - ply.pac_animation_sequences[part] = nil + plyTbl.pac_animation_sequences[part] = nil end end if animrate ~= 1 then - ply:SetCycle((pac.RealTime * animrate) % 1) + SetCycle(ply, (pac.RealTime * animrate) % 1) return true end - if ply.pac_holdtype_alternative_animation_rate then - local length = ply:GetVelocity():Dot(ply:EyeAngles():Forward()) > 0 and 1 or -1 + if plyTbl.pac_holdtype_alternative_animation_rate then + local length = ply:GetVelocity():Dot(ply:GetAimVector()) > 0 and 1 or -1 local scale = ply:GetModelScale() * 2 if scale ~= 0 then - ply:SetCycle(pac.RealTime / scale * length) + SetCycle(ply, pac.RealTime / scale * length) else - ply:SetCycle(0) + SetCycle(ply, 0) end return true @@ -100,65 +107,64 @@ do local vehicle = ply:GetVehicle() - if ply.pac_last_vehicle ~= vehicle then - if ply.pac_last_vehicle ~= nil then + if plyTbl.pac_last_vehicle ~= vehicle then + if plyTbl.pac_last_vehicle ~= nil then pac.CallRecursiveOnAllParts("OnVehicleChanged", ply, vehicle) end - ply.pac_last_vehicle = vehicle + plyTbl.pac_last_vehicle = vehicle end end) end -local MOVETYPE_NOCLIP = MOVETYPE_NOCLIP - pac.AddHook("TranslateActivity", "events", function(ply, act) - if IsEntity(ply) and ply:IsValid() then + if not IsEntity(ply) or not IsEntValid(ply) then return end + local plyTbl = GetTable(ply) - -- animation part - if ply.pac_animation_sequences and next(ply.pac_animation_sequences) then - -- dont do any holdtype stuff if theres a sequence - return - end + -- animation part + if plyTbl.pac_animation_sequences and next(plyTbl.pac_animation_sequences) then + -- dont do any holdtype stuff if theres a sequence + return + end - if ply.pac_animation_holdtypes then - local key, val = next(ply.pac_animation_holdtypes) - if key then - if not val.part:IsValid() then - ply.pac_animation_holdtypes[key] = nil - else - return val[act] - end + if plyTbl.pac_animation_holdtypes then + local key, val = next(plyTbl.pac_animation_holdtypes) + if key then + if not val.part:IsValid() then + plyTbl.pac_animation_holdtypes[key] = nil + else + return val[act] end end + end - -- holdtype part - if ply.pac_holdtypes then - local key, act_table = next(ply.pac_holdtypes) + -- holdtype part + if plyTbl.pac_holdtypes then + local key, act_table = next(plyTbl.pac_holdtypes) - if key then - if not act_table.part:IsValid() then - ply.pac_holdtypes[key] = nil - else + if key then + if not act_table.part:IsValid() then + plyTbl.pac_holdtypes[key] = nil + else + if act_table[act] and act_table[act] ~= -1 then + return act_table[act] + end - if act_table[act] and act_table[act] ~= -1 then - return act_table[act] - end + local vehicle = ply:GetVehicle() - if ply:GetVehicle():IsValid() and ply:GetVehicle():GetClass() == "prop_vehicle_prisoner_pod" then - return act_table.sitting - end + if IsEntValid(vehicle) and vehicle:GetClass() == classname_prisoner_pod then + return act_table.sitting + end - if act_table.noclip ~= -1 and ply:GetMoveType() == MOVETYPE_NOCLIP then - return act_table.noclip - end + if act_table.noclip ~= -1 and ply:GetMoveType() == MOVETYPE_NOCLIP then + return act_table.noclip + end - if act_table.air ~= -1 and ply:GetMoveType() ~= MOVETYPE_NOCLIP and not ply:IsOnGround() then - return act_table.air - end + if act_table.air ~= -1 and ply:GetMoveType() ~= MOVETYPE_NOCLIP and not ply:IsOnGround() then + return act_table.air + end - if act_table.fallback ~= -1 then - return act_table.fallback - end + if act_table.fallback ~= -1 then + return act_table.fallback end end end @@ -166,13 +172,16 @@ pac.AddHook("TranslateActivity", "events", function(ply, act) end) pac.AddHook("CalcMainActivity", "events", function(ply, act) - if IsEntity(ply) and ply:IsValid() and ply.pac_animation_sequences then - local key, val = next(ply.pac_animation_sequences) + if not IsEntity(ply) or not IsEntValid(ply) then return end + local plyTbl = GetTable(ply) + + if plyTbl.pac_animation_sequences then + local key, val = next(plyTbl.pac_animation_sequences) if not key then return end if not val.part:IsValid() then - ply.pac_animation_sequences[key] = nil + plyTbl.pac_animation_sequences[key] = nil return end @@ -184,7 +193,7 @@ pac.AddHook("pac_PlayerFootstep", "events", function(ply, pos, snd, vol) ply.pac_last_footstep_pos = pos if ply.pac_footstep_override then - for _, part in pairs(ply.pac_footstep_override) do + for _, part in next, ply.pac_footstep_override do if not part:IsHidden() then part:PlaySound(snd, vol) end diff --git a/lua/pac3/core/client/integration_tools.lua b/lua/pac3/core/client/integration_tools.lua index 380266e15..c876d6d0e 100644 --- a/lua/pac3/core/client/integration_tools.lua +++ b/lua/pac3/core/client/integration_tools.lua @@ -69,7 +69,9 @@ function pac.SetupENT(ENT, owner) ENT.pac_owner = ENT.pac_owner or owner or "self" local function find(parent, name) - for _, part in ipairs(parent:GetChildren()) do + local children = parent:GetChildren() + for i = 1, #children do + local part = children[i] if part:GetName():lower():find(name) then return part @@ -81,7 +83,6 @@ function pac.SetupENT(ENT, owner) end function ENT:FindPACPart(outfit, name) - name = name:lower() if not outfit.self then @@ -106,7 +107,6 @@ function pac.SetupENT(ENT, owner) part = find(part, name) - if part then self.pac_part_find_cache[name] = part @@ -118,7 +118,6 @@ function pac.SetupENT(ENT, owner) end function ENT:AttachPACPart(outfit, owner, keep_uniqueid) - if not outfit.self then return self:AttachPACSession(outfit, owner) end @@ -236,7 +235,6 @@ function pac.SetupSWEP(SWEP, owner) end function pac.AddEntityClassListener(class, session, check_func, draw_dist) - if session.self then session = {session} end @@ -298,7 +296,7 @@ function pac.AddEntityClassListener(class, session, check_func, draw_dist) end end - for _, ent in pairs(ents.GetAll()) do + for _, ent in ents.Iterator() do created(ent) end @@ -313,7 +311,7 @@ function pac.RemoveEntityClassListener(class, session, check_func) check_func = check_func or function(ent) return ent:GetClass() == class end - for _, ent in pairs(ents.GetAll()) do + for _, ent in ents.Iterator() do if check_func(ent) and ent.pac_outfits then ent:RemovePACSession(session) end diff --git a/lua/pac3/core/client/max_render_time.lua b/lua/pac3/core/client/max_render_time.lua index cbf574184..71cf1fcbe 100644 --- a/lua/pac3/core/client/max_render_time.lua +++ b/lua/pac3/core/client/max_render_time.lua @@ -2,23 +2,24 @@ local SysTime = SysTime local pairs = pairs local Color = Color local tostring = tostring +local Vector = Vector +local EyePos = EyePos +local ScrW = ScrW +local ScrH = ScrH local cam_Start2D = cam.Start2D local cam_IgnoreZ = cam.IgnoreZ -local Vector = Vector +local cam_End2D = cam.End2D local math_Clamp = math.Clamp -local EyePos = EyePos local surface_SetFont = surface.SetFont local surface_GetTextSize = surface.GetTextSize local draw_DrawText = draw.DrawText local string_format = string.format local input_GetCursorPos = input.GetCursorPos -local vgui_CursorVisible = vgui.CursorVisible -local ScrW = ScrW -local ScrH = ScrH local input_LookupBinding = input.LookupBinding -local LocalPlayer = LocalPlayer local input_IsMouseDown = input.IsMouseDown -local cam_End2D = cam.End2D +local vgui_CursorVisible = vgui.CursorVisible + +local white = Color(255, 255, 255) --its alpha will be temporarily tampered with, don't risk breaking color_white local max_render_time_cvar = CreateClientConVar("pac_max_render_time", 0) @@ -60,13 +61,18 @@ end function pac.DrawRenderTimeExceeded(ent) cam_Start2D() cam_IgnoreZ(true) - local pos_3d = ent:NearestPoint(ent:EyePos() + ent:GetUp()) + Vector(0,0,5) + + local pos_3d = ent:NearestPoint(ent:EyePos() + ent:GetUp()) + Vector(0, 0, 5) local alpha = math_Clamp(pos_3d:Distance(EyePos()) * -1 + 500, 0, 500) / 500 + if alpha > 0 then local pos_2d = pos_3d:ToScreen() + surface_SetFont("ChatFont") local _, h = surface_GetTextSize("|") + white.a = alpha * 255 + draw_DrawText( string_format( "pac3 outfit took %.2f/%i ms to render", @@ -76,23 +82,27 @@ function pac.DrawRenderTimeExceeded(ent) "ChatFont", pos_2d.x, pos_2d.y, - Color(255,255,255,alpha * 255), + white, 1 ) + local x, y = pos_2d.x, pos_2d.y + h local mx, my = input_GetCursorPos() if not vgui_CursorVisible() then - mx = ScrW() / 2 - my = ScrH() / 2 + mx = ScrW() * 0.5 + my = ScrH() * 0.5 end local dist = 200 local hovering = mx > x - dist and mx < x + dist and my > y - dist and my < y + dist local button = vgui_CursorVisible() and "click" or ("press " .. input_LookupBinding("+use")) - draw_DrawText(button .. " here to try again", "ChatFont", x, y, Color(255,255,255,alpha * (hovering and 255 or 100) ), 1) - if hovering and LocalPlayer():KeyDown(IN_USE) or (vgui_CursorVisible() and input_IsMouseDown(MOUSE_LEFT)) then + white.a = alpha * (hovering and 255 or 100) + + draw_DrawText(button .. " here to try again", "ChatFont", x, y, white, 1) + + if hovering and pac.LocalPlayer:KeyDown(IN_USE) or (vgui_CursorVisible() and input_IsMouseDown(MOUSE_LEFT)) then ent.pac_render_time_exceeded = nil end end diff --git a/lua/pac3/core/client/owner_name.lua b/lua/pac3/core/client/owner_name.lua index a405f5e21..9a04c494e 100644 --- a/lua/pac3/core/client/owner_name.lua +++ b/lua/pac3/core/client/owner_name.lua @@ -121,7 +121,7 @@ function pac.HandleOwnerName(owner, name, ent, part, check_func) return ent end - for _, val in pairs(ents.GetAll()) do + for _, val in ents.Iterator()do if val:IsValid() and (not check_func or check_func(val)) and check_owner(val, owner) and find_ent(val, name) then return val end @@ -130,7 +130,7 @@ function pac.HandleOwnerName(owner, name, ent, part, check_func) if name:find("persist ", nil, true) then local crc = name:match("persist (.+)") - for _, val in pairs(ents.GetAll()) do + for _, val in ents.Iterator() do if val.GetPersistent and val:GetModel() and val:GetPersistent() and crc == calc_entity_crc(val) then return val end diff --git a/lua/pac3/core/client/part_pool.lua b/lua/pac3/core/client/part_pool.lua index 04146425a..d23f564cb 100644 --- a/lua/pac3/core/client/part_pool.lua +++ b/lua/pac3/core/client/part_pool.lua @@ -5,17 +5,26 @@ local render_SetBlend = render.SetBlend local render_ModelMaterialOverride = render.ModelMaterialOverride local render_MaterialOverride = render.MaterialOverride local SysTime = SysTime -local NULL = NULL -local pairs = pairs -local force_rendering = false -local forced_rendering = false local IsEntity = IsEntity local next = next +local pairs = pairs +local NULL = NULL -local entMeta = FindMetaTable('Entity') -local plyMeta = FindMetaTable('Player') +local entMeta = FindMetaTable("Entity") +local plyMeta = FindMetaTable("Player") local IsValid = entMeta.IsValid +local IsPlayer = entMeta.IsPlayer +local IsDormant = entMeta.IsDormant +local GetEyePos = entMeta.EyePos +local GetTable = entMeta.GetTable local Alive = plyMeta.Alive +local GetViewModel = plyMeta.GetViewModel +local GetHands = plyMeta.GetHands +local GetRagdollEntity = plyMeta.GetRagdollEntity +local ShouldDrawLocalPlayer = plyMeta.ShouldDrawLocalPlayer + +local force_rendering = false +local forced_rendering = false local function IsActuallyValid(ent) return IsEntity(ent) and pcall(ent.GetPos, ent) @@ -27,7 +36,7 @@ end local function IsActuallyRemoved(ent, cb) timer.Simple(0, function() - if not ent:IsValid() then + if not IsValid(ent) then cb() end end) @@ -44,7 +53,6 @@ local ent_parts = _G.pac_local_parts or {} local all_parts = _G.pac_all_parts or {} local uid_parts = _G.pac_uid_parts or {} - if game.SinglePlayer() or (player.GetCount() == 1 and LocalPlayer():IsSuperAdmin()) then _G.pac_local_parts = ent_parts _G.pac_all_parts = all_parts @@ -60,6 +68,9 @@ local function parts_from_ent(ent) return uid_parts[owner_id] or {} end +local classtype_viewmodel = "viewmodel" +local classtype_hands = "hands" + do local function render_override(ent, type) local parts = ent_parts[ent] @@ -94,16 +105,13 @@ do else for key, part in next, parts do if part:IsValid() then - if not part:HasParent() then - if - part.OwnerName == "viewmodel" and type == "viewmodel" or - part.OwnerName == "hands" and type == "hands" or - part.OwnerName ~= "viewmodel" and part.OwnerName ~= "hands" and type ~= "viewmodel" and type ~= "hands" - then - if not part:IsDrawHidden() then - part:CallRecursive("Draw", type) - end - end + if not part:IsDrawHidden() + and not part:HasParent() + and ((part.OwnerName == classtype_viewmodel and type == classtype_viewmodel) + or (part.OwnerName == classtype_hands and type == classtype_hands) + or (part.OwnerName ~= classtype_viewmodel and part.OwnerName ~= classtype_hands and type ~= classtype_viewmodel and type ~= classtype_hands)) + then + part:CallRecursive("Draw", type) end else parts[key] = nil @@ -193,7 +201,7 @@ end function pac.EnableDrawnEntities(bool) for ent in next, pac.drawn_entities do - if ent:IsValid() then + if IsValid(ent) then if bool then pac.ShowEntityParts(ent) else @@ -252,49 +260,51 @@ end pac.AddHook("Think", "events", function() for _, ply in player.Iterator() do - if not ent_parts[ply] then continue end - if pac.IsEntityIgnored(ply) then continue end + if not ent_parts[ply] or pac.IsEntityIgnored(ply) then continue end + + local plyTbl = GetTable(ply) if Alive(ply) then - if ply.pac_revert_ragdoll then - ply.pac_revert_ragdoll() - ply.pac_revert_ragdoll = nil + if plyTbl.pac_revert_ragdoll then + plyTbl.pac_revert_ragdoll() + plyTbl.pac_revert_ragdoll = nil end continue end - local rag = ply:GetRagdollEntity() + local rag = GetRagdollEntity(ply) if not IsValid(rag) then pac.HideEntityParts(ply) continue end -- so it only runs once - if ply.pac_ragdoll == rag then continue end - ply.pac_ragdoll = rag + if plyTbl.pac_ragdoll == rag then continue end + plyTbl.pac_ragdoll = rag + rag.pac_ragdoll_owner = ply rag = hook.Run("PACChooseDeathRagdoll", ply, rag) or rag - if ply.pac_death_physics_parts then - if ply.pac_physics_died then return end + if plyTbl.pac_death_physics_parts then + if plyTbl.pac_physics_died then return end - for _, part in pairs(parts_from_uid(pac.Hash(ply))) do + for _, part in next, parts_from_uid(pac.Hash(ply)) do if part.is_model_part then local ent = part:GetOwner() - if ent:IsValid() then + if IsValid(ent) then rag:SetNoDraw(true) part.skip_orient = true ent:SetParent(NULL) ent:SetNoDraw(true) - ent:PhysicsInitBox(Vector(1,1,1) * -5, Vector(1,1,1) * 5) + ent:PhysicsInitBox(Vector(1, 1, 1) * -5, Vector(1, 1, 1) * 5) ent:SetCollisionGroup(COLLISION_GROUP_DEBRIS) local phys = ent:GetPhysicsObject() phys:AddAngleVelocity(VectorRand() * 1000) - phys:AddVelocity(ply:GetVelocity() + VectorRand() * 30) + phys:AddVelocity(ply:GetVelocity() + VectorRand() * 30) phys:Wake() function ent.RenderOverride() @@ -311,25 +321,25 @@ pac.AddHook("Think", "events", function() end end end - ply.pac_physics_died = true - elseif ply.pac_death_ragdollize or ply.pac_death_ragdollize == nil then - + plyTbl.pac_physics_died = true + elseif plyTbl.pac_death_ragdollize or plyTbl.pac_death_ragdollize == nil then pac.HideEntityParts(ply) - for _, part in pairs(ent_parts[ply]) do + for _, part in next, ent_parts[ply] do part:SetOwner(rag) end + rag:SetOwner(ply) pac.ShowEntityParts(rag) - ply.pac_revert_ragdoll = function() + plyTbl.pac_revert_ragdoll = function() ply.pac_ragdoll = nil if not ent_parts[ply] then return end pac.HideEntityParts(rag) - for _, part in pairs(ent_parts[ply]) do + for _, part in next, ent_parts[ply] do part:SetOwner(ply) end @@ -341,12 +351,12 @@ pac.AddHook("Think", "events", function() if pac.last_flashlight_on ~= pac.LocalPlayer:FlashlightIsOn() then local lamp = ProjectedTexture() - lamp:SetTexture( "effects/flashlight001" ) - lamp:SetFarZ( 5000 ) - lamp:SetColor(Color(0,0,0,255)) + lamp:SetTexture("effects/flashlight001") + lamp:SetFarZ(5000) + lamp:SetColor(Color(0, 0, 0, 255)) - lamp:SetPos( pac.LocalPlayer:EyePos() - pac.LocalPlayer:GetAimVector()*400 ) - lamp:SetAngles( pac.LocalPlayer:EyeAngles() ) + lamp:SetPos(GetEyePos(pac.LocalPlayer) - pac.LocalPlayer:GetAimVector() * 400) + lamp:SetAngles(pac.LocalPlayer:EyeAngles()) lamp:Update() pac.AddHook("PostRender", "flashlight_stuck_fix", function() @@ -359,11 +369,9 @@ pac.AddHook("Think", "events", function() for ent in next, pac.drawn_entities do if IsValid(ent) then - if ent.pac_drawing and ent:IsPlayer() then - - ent.pac_traceres = util.QuickTrace(ent:EyePos(), ent:GetAimVector() * 32000, {ent, ent:GetVehicle(), ent:GetOwner()}) + if ent.pac_drawing and IsPlayer(ent) then + ent.pac_traceres = util.QuickTrace(GetEyePos(ent), ent:GetAimVector() * 32000, {ent, ent:GetVehicle(), ent:GetOwner()}) ent.pac_hitpos = ent.pac_traceres.HitPos - end else pac.drawn_entities[ent] = nil @@ -371,20 +379,21 @@ pac.AddHook("Think", "events", function() end if pac.next_frame_funcs then - for k, fcall in pairs(pac.next_frame_funcs) do + for _, fcall in next, pac.next_frame_funcs do fcall() end -- table.Empty is also based on undefined behavior -- god damnit - for i, key in ipairs(table.GetKeys(pac.next_frame_funcs)) do - pac.next_frame_funcs[key] = nil + local func_keys = table.GetKeys(pac.next_frame_funcs) + for i = 1, #func_keys do + pac.next_frame_funcs[func_keys[i]] = nil end end - if pac.next_frame_funcs_simple and #pac.next_frame_funcs_simple ~= 0 then - for i, fcall in ipairs(pac.next_frame_funcs_simple) do - fcall() + if pac.next_frame_funcs_simple and pac.next_frame_funcs_simple[1] then + for i = 1, #pac.next_frame_funcs_simple do + pac.next_frame_funcs_simple[i]() end for i = #pac.next_frame_funcs_simple, 1, -1 do @@ -414,7 +423,7 @@ pac.AddHook("EntityRemoved", "change_owner", function(ent) IsActuallyRemoved(ent, function() for _, part in pairs(parts) do if part.ClassName == "group" then - if part:GetOwnerName() == "hands" then + if part:GetOwnerName() == classtype_hands then part:UpdateOwnerName() end part:HideInvalidOwners() @@ -432,7 +441,7 @@ pac.AddHook("OnEntityCreated", "change_owner", function(ent) local owner = ent:GetOwner() - if IsActuallyValid(owner) and (not owner:IsPlayer() or IsActuallyPlayer(owner)) then + if IsActuallyValid(owner) and (not IsPlayer(owner) or IsActuallyPlayer(owner)) then for _, part in pairs(parts_from_ent(owner)) do if part.ClassName == "group" then part:UpdateOwnerName(ent, false) @@ -694,7 +703,6 @@ do -- drawing local FrameNumber = FrameNumber local RealTime = RealTime - local GetConVar = GetConVar local EF_BONEMERGE = EF_BONEMERGE local RENDERMODE_TRANSALPHA = RENDERMODE_TRANSALPHA @@ -707,7 +715,7 @@ do -- drawing pac.RealTime = 0 pac.FrameNumber = 0 - local skip_frames = CreateConVar('pac_optimization_render_once_per_frame', '0', {FCVAR_ARCHIVE}, 'render only once per frame (will break water reflections and vr)') + local skip_frames = CreateConVar("pac_optimization_render_once_per_frame", "0", {FCVAR_ARCHIVE}, "render only once per frame (will break water reflections and vr)") local function setup_suppress() local last_framenumber = 0 @@ -715,9 +723,8 @@ do -- drawing local current_frame_count = 0 return function(force) - if not force then - if force_rendering then return end - if not skip_frames:GetBool() then return end + if not force and (force_rendering or not skip_frames:GetBool()) then + return end local frame_number = FrameNumber() @@ -741,22 +748,29 @@ do -- drawing do local draw_dist = 0 local sv_draw_dist = 0 - local radius = 0 local dst = 0 + + local localplayer local pac_sv_draw_distance pac.AddHook("Think", "update_parts", function() + if not localplayer then + localplayer = LocalPlayer() -- LocalPlayer never changes once its valid, right? + end + -- commonly used variables - pac.LocalPlayer = LocalPlayer() - pac.LocalViewModel = pac.LocalPlayer:GetViewModel() - pac.LocalHands = pac.LocalPlayer:GetHands() + pac.LocalPlayer = localplayer + pac.LocalViewModel = GetViewModel(localplayer) + pac.LocalHands = GetHands(localplayer) pac.RealTime = RealTime() pac.FrameNumber = pac.FrameNumber + 1 + if not pac_sv_draw_distance then + pac_sv_draw_distance = GetConVar("pac_sv_draw_distance") + end + draw_dist = cvar_distance:GetInt() - pac_sv_draw_distance = pac_sv_draw_distance or GetConVar("pac_sv_draw_distance") sv_draw_dist = pac_sv_draw_distance:GetFloat() - radius = 0 if draw_dist <= 0 then draw_dist = 32768 @@ -766,7 +780,13 @@ do -- drawing sv_draw_dist = 32768 end - draw_dist = math.min(sv_draw_dist, draw_dist) + -- square the dist vars to fit with dst which uses DistToSqr for efficiency + sv_draw_dist = sv_draw_dist ^ 2 + draw_dist = draw_dist ^ 2 + + if draw_dist > sv_draw_dist then + draw_dist = sv_draw_dist + end for ent in next, pac.drawn_entities do if not IsValid(ent) then @@ -774,14 +794,13 @@ do -- drawing goto CONTINUE end - if ent:IsDormant() then goto CONTINUE end + if IsDormant(ent) then goto CONTINUE end pac.ResetRenderTime(ent) - dst = ent:EyePos():Distance(pac.EyePos) - radius = ent:BoundingRadius() * 3 * (ent:GetModelScale() or 1) + dst = GetEyePos(ent):DistToSqr(pac.EyePos) - if ent:IsPlayer() or IsValid(ent.pac_ragdoll_owner) then + if IsPlayer(ent) or IsValid(ent.pac_ragdoll_owner) then local ply = ent.pac_ragdoll_owner or ent local rag = ply.pac_ragdoll @@ -790,8 +809,10 @@ do -- drawing local c = rag:GetColor() c.a = 0 + rag:SetColor(c) rag:SetNoDraw(true) + if rag:GetParent() ~= ply then rag:SetParent(ent) rag:AddEffects(EF_BONEMERGE) @@ -801,25 +822,19 @@ do -- drawing ply:DrawModel() end end - - if radius < 32 then - radius = 128 - end - elseif not ent:IsNPC() then - radius = radius * 4 end -- if it's a world entity always draw local cond = ent.IsPACWorldEntity -- if the entity is the hands, check if we should not draw the localplayer - if (ent == pac.LocalHands or ent == pac.LocalViewModel) and not pac.LocalPlayer:ShouldDrawLocalPlayer() then + if (ent == pac.LocalHands or ent == pac.LocalViewModel) and not ShouldDrawLocalPlayer(localplayer) then cond = true end -- if it's a player, draw if we can see them - if not cond and ent == pac.LocalPlayer then - cond = ent:ShouldDrawLocalPlayer() + if not cond and ent == localplayer then + cond = ShouldDrawLocalPlayer(ent) end -- if the entity has a camera part, draw if it's valid @@ -828,17 +843,16 @@ do -- drawing end -- if the condition is not satisified, check draw distance - if not cond and ent ~= pac.LocalPlayer then + if not cond and ent ~= localplayer then if ent.pac_draw_distance then - -- custom draw distance - cond = ent.pac_draw_distance <= 0 or dst <= ent.pac_draw_distance + -- custom draw distance - is it 0 for infinite range, or under the custom distance (squared to fit with DistToSqr) + cond = ent.pac_draw_distance <= 0 or dst <= (ent.pac_draw_distance ^ 2) else -- otherwise check the cvar cond = dst <= draw_dist end end - ent.pac_is_drawing = cond if cond then @@ -872,6 +886,8 @@ do -- drawing if not ok then error(err) end end + local skybox_nwkey = "pac_in_skybox" + do local should_suppress = setup_suppress() @@ -879,7 +895,10 @@ do -- drawing if should_suppress(true) then return end for ent in next, pac.drawn_entities do - if ent.pac_is_drawing and ent_parts[ent] and not ent:IsDormant() then + if ent.pac_is_drawing + and ent_parts[ent] -- accessing table of NULL doesn't do anything + and not IsDormant(ent) + then pac.RenderOverride(ent, "update_legacy_bones") end end @@ -891,12 +910,11 @@ do -- drawing if should_suppress() then return end for ent in next, pac.drawn_entities do - if ent.pac_is_drawing and ent_parts[ent] and not ent:IsDormant() then - - if isDraw3DSkybox and not ent:GetNW2Bool("pac_in_skybox") then - continue - end - + if ent.pac_is_drawing + and ent_parts[ent] -- accessing table of NULL doesn't do anything + and not IsDormant(ent) + and (not isDraw3DSkybox or ent:GetNW2Bool(skybox_nwkey)) + then pac.RenderOverride(ent, "opaque") end end @@ -910,12 +928,11 @@ do -- drawing if should_suppress() then return end for ent in next, pac.drawn_entities do - if ent.pac_is_drawing and ent_parts[ent] and not ent:IsDormant() then -- accessing table of NULL doesn't do anything - - if isDraw3DSkybox and not ent:GetNW2Bool("pac_in_skybox") then - continue - end - + if ent.pac_is_drawing + and ent_parts[ent] -- accessing table of NULL doesn't do anything + and not IsDormant(ent) + and (not isDraw3DSkybox or ent:GetNW2Bool(skybox_nwkey)) + then pac.RenderOverride(ent, "translucent") end end @@ -925,22 +942,22 @@ do -- drawing pac.AddHook("UpdateAnimation", "update_animation_parts", function(ply) if ply.pac_is_drawing and ent_parts[ply] then -- accessing table of NULL doesn't do anything local parts = ent_parts[ply] - for _, part in pairs(parts) do + for _, part in next, parts do part:CallRecursive("OnUpdateAnimation", ply) end end end) local drawing_viewmodel = false - pac.AddHook("PostDrawViewModel", "draw_firstperson", function(viewmodelIn, playerIn, weaponIn) if drawing_viewmodel then return end + for ent in next, pac.drawn_entities do if IsValid(ent) then if ent.pac_drawing and ent_parts[ent] then - drawing_viewmodel=true - pac.RenderOverride(ent, "viewmodel") - drawing_viewmodel=false + drawing_viewmodel = true + pac.RenderOverride(ent, classtype_viewmodel) + drawing_viewmodel = false end else pac.drawn_entities[ent] = nil @@ -951,11 +968,12 @@ do -- drawing local drawing_hands = false pac.AddHook("PostDrawPlayerHands", "draw_firstperson_hands", function(handsIn, viewmodelIn, playerIn, weaponIn) if drawing_hands then return end + for ent in next, pac.drawn_entities do if IsValid(ent) then if ent.pac_drawing and ent_parts[ent] then drawing_hands = true - pac.RenderOverride(ent, "hands") + pac.RenderOverride(ent, classtype_hands) drawing_hands = false end else diff --git a/lua/pac3/core/client/parts.lua b/lua/pac3/core/client/parts.lua index 3fc9157b8..377ea2153 100644 --- a/lua/pac3/core/client/parts.lua +++ b/lua/pac3/core/client/parts.lua @@ -134,18 +134,16 @@ function pac.LoadParts() include("base_drawable.lua") local files = file.Find("pac3/core/client/parts/*.lua", "LUA") - for _, name in pairs(files) do - include("pac3/core/client/parts/" .. name) + for i = 1, #files do + include("pac3/core/client/parts/" .. files[i]) end - local files = file.Find("pac3/core/client/parts/legacy/*.lua", "LUA") - for _, name in pairs(files) do - include("pac3/core/client/parts/legacy/" .. name) + files = file.Find("pac3/core/client/parts/legacy/*.lua", "LUA") + for i = 1, #files do + include("pac3/core/client/parts/legacy/" .. files[i]) end end function pac.GetRegisteredParts() return pac.registered_parts -end - - +end \ No newline at end of file diff --git a/lua/pac3/core/client/parts/animation.lua b/lua/pac3/core/client/parts/animation.lua index 9c2e973e5..1606f81d6 100644 --- a/lua/pac3/core/client/parts/animation.lua +++ b/lua/pac3/core/client/parts/animation.lua @@ -8,7 +8,7 @@ AnimStack = { push = function(self, part) local stack = self.stack - if #stack == 0 then + if stack[1] == nil then -- Empty stack table.insert(stack, part) else @@ -65,8 +65,8 @@ setmetatable(AnimStack, AnimStack) PART.ClassName = "animation" PART.ThinkTime = 0 -PART.Groups = {'entity', 'model', 'modifiers'} -PART.Icon = 'icon16/eye.png' +PART.Groups = {"entity", "model", "modifiers"} +PART.Icon = "icon16/eye.png" PART.frame = 0 @@ -74,7 +74,7 @@ BUILDER :StartStorableVars() :GetSet("Loop", true) :GetSet("PingPongLoop", false) - :GetSet("SequenceName", "", {enums = function(part) local tbl = {} for k,v in pairs(part:GetSequenceList()) do tbl[v] = v end return tbl end}) + :GetSet("SequenceName", "", {enums = function(part) local tbl = {} local list = part:GetSequenceList() for i = 1, #list do tbl[v] = v end return tbl end}) :GetSet("Rate", 1, {editor_sensitivity = 0.1}) :GetSet("Offset", 0) :GetSet("Min", 0) @@ -177,7 +177,9 @@ PART.random_seqname = "" function PART:SetSequenceName(name) self.SequenceName = name - self.random_seqname = table.Random(name:Split(";")) + + local split = name:Split(";") + self.random_seqname = split[math.random(#split)] if not self:IsHidden() then self:OnShow() @@ -191,7 +193,9 @@ function PART:OnStackStart() if ent:IsValid() then self.prevSequence = ent:GetSequence() - self.random_seqname = table.Random(self.SequenceName:Split(";")) + + local split = self.SequenceName:Split(";") + self.random_seqname = split[math.random(#split)] if self.random_seqname ~= "" then local seq = ent:LookupSequence(self.random_seqname) or 0 diff --git a/lua/pac3/core/client/parts/bone.lua b/lua/pac3/core/client/parts/bone.lua index e3414b447..a17b145b3 100644 --- a/lua/pac3/core/client/parts/bone.lua +++ b/lua/pac3/core/client/parts/bone.lua @@ -5,7 +5,7 @@ local vector_origin = vector_origin local Vector = Vector local Angle = Angle -for _, v in pairs(ents.GetAll()) do +for _, v in ents.Iterator() do v.pac_bone_setup_data = nil end @@ -13,8 +13,8 @@ local BUILDER, PART = pac.PartTemplate("base_movable") PART.FriendlyName = "bone" PART.ClassName = "bone3" -PART.Groups = {'entity', 'model'} -PART.Icon = 'icon16/connect.png' +PART.Groups = {"entity", "model"} +PART.Icon = "icon16/connect.png" PART.is_bone_part = true BUILDER:StartStorableVars() @@ -36,7 +36,7 @@ BUILDER:StartStorableVars() BUILDER:PropertyOrder("Angles") BUILDER:PropertyOrder("EyeAngles") BUILDER:GetSet("Size", 1, {editor_sensitivity = 0.25}) - BUILDER:GetSet("Scale", Vector(1,1,1), {editor_sensitivity = 0.25}) + BUILDER:GetSet("Scale", Vector(1, 1, 1), {editor_sensitivity = 0.25}) BUILDER:PropertyOrder("PositionOffset") BUILDER:PropertyOrder("AngleOffset") diff --git a/lua/pac3/core/client/parts/camera.lua b/lua/pac3/core/client/parts/camera.lua index 828c95690..e242709eb 100644 --- a/lua/pac3/core/client/parts/camera.lua +++ b/lua/pac3/core/client/parts/camera.lua @@ -15,7 +15,7 @@ BUILDER:StartStorableVars() BUILDER:GetSet("FOV", -1) BUILDER:EndStorableVars() -for i, ply in ipairs(player.GetAll()) do +for _, ply in player.Iterator() do ply.pac_cameras = nil end diff --git a/lua/pac3/core/client/parts/damage_zone.lua b/lua/pac3/core/client/parts/damage_zone.lua index 156961d32..e399a415a 100644 --- a/lua/pac3/core/client/parts/damage_zone.lua +++ b/lua/pac3/core/client/parts/damage_zone.lua @@ -411,29 +411,38 @@ function PART:AssignFloatingPartToEntity(part, owner, ent, parent_ent, template_ end +local damage_zone_class = PART.ClassName + local function RecursedHitmarker(part) if part.HitMarkerPart == part or part.KillMarkerPart == part then return true end + + local children + if IsValid(part.HitMarkerPart) then - for i,child in pairs(part.HitMarkerPart:GetChildrenList()) do - if child.ClassName == "damage_zone" then - if child.HitMarkerPart == part or child.KillMarkerPart == part then - return true - end + children = part.HitMarkerPart:GetChildrenList() + + for i = 1, #children do + local child = children[i] + + if child.ClassName == damage_zone_class and (child.HitMarkerPart == part or child.KillMarkerPart == part) then + return true end end end + if IsValid(part.KillMarkerPart) then - for i,child in pairs(part.KillMarkerPart:GetChildrenList()) do - if child.ClassName == "damage_zone" then - if child.HitMarkerPart == part or child.KillMarkerPart == part then - return true - end + children = part.KillMarkerPart:GetChildrenList() + + for i = 1, #children do + local child = children[i] + + if child.ClassName == damage_zone_class and (child.HitMarkerPart == part or child.KillMarkerPart == part) then + return true end end end - end diff --git a/lua/pac3/core/client/parts/decal.lua b/lua/pac3/core/client/parts/decal.lua index 922919bd7..a90acd199 100644 --- a/lua/pac3/core/client/parts/decal.lua +++ b/lua/pac3/core/client/parts/decal.lua @@ -3,8 +3,8 @@ local BUILDER, PART = pac.PartTemplate("base_movable") PART.ClassName = "decal" -PART.Group = 'effects' -PART.Icon = 'icon16/paintbrush.png' +PART.Group = "effects" +PART.Icon = "icon16/paintbrush.png" BUILDER:StartStorableVars() BUILDER:GetSet("Color", Vector(255, 255, 255), {editor_panel = "color"}) diff --git a/lua/pac3/core/client/parts/effect.lua b/lua/pac3/core/client/parts/effect.lua index 6e50bd192..7153afaeb 100644 --- a/lua/pac3/core/client/parts/effect.lua +++ b/lua/pac3/core/client/parts/effect.lua @@ -64,12 +64,16 @@ PART.last_spew = 0 if not pac_loaded_particle_effects then pac_loaded_particle_effects = {} - for _, file_name in pairs(file.Find("particles/*.pcf", "GAME")) do - if not pac_loaded_particle_effects[file_name] and not pac.BlacklistedParticleSystems[file_name:lower()] then - game.AddParticles("particles/" .. file_name) + local files = file.Find("particles/*.pcf", "GAME") + + for i = 1, #files do + local path = files[i] + + if not pac_loaded_particle_effects[path] and not pac.BlacklistedParticleSystems[path:lower()] then + game.AddParticles("particles/" .. path) end - pac_loaded_particle_effects[file_name] = true + pac_loaded_particle_effects[path] = true end end @@ -78,7 +82,9 @@ local alreadyServer = {} local function pac_request_precache(name) if already[name] then return end already[name] = true + PrecacheParticleSystem(name) + net.Start("pac_request_precache") net.WriteString(name) net.SendToServer() @@ -99,7 +105,9 @@ end pac.AddHook("pac_EffectPrecached", "pac_Effects", function(name) if alreadyServer[name] then return end alreadyServer[name] = true + pac.dprint("effect %q precached!", name) + pac.CallRecursiveOnAllParts("OnEffectPrecached", name) end) diff --git a/lua/pac3/core/client/parts/event.lua b/lua/pac3/core/client/parts/event.lua index 50eccf7df..a6ec32ed2 100644 --- a/lua/pac3/core/client/parts/event.lua +++ b/lua/pac3/core/client/parts/event.lua @@ -7,7 +7,7 @@ local NULL = NULL local Vector = Vector local util = util local SysTime = SysTime - +local table_insert = table.insert local BUILDER, PART = pac.PartTemplate("base") @@ -15,7 +15,7 @@ PART.ClassName = "event" PART.ThinkTime = 0 PART.AlwaysThink = true -PART.Icon = 'icon16/clock.png' +PART.Icon = "icon16/clock.png" BUILDER:StartStorableVars() BUILDER:GetSet("Event", "", {enums = function(part) @@ -763,12 +763,19 @@ PART.OldEvents = { callback = function(self, ent, extra_radius, require_line_of_sight) extra_radius = extra_radius or 0 self.nextcheck = self.nextcheck or CurTime() + 0.1 + if CurTime() > self.nextcheck then - for _,v in ipairs(player.GetAll()) do + local local_center, min_radius, max_radius + + for _, v in player.Iterator() do if v == ent then continue end local eyetrace = v:GetEyeTrace() - if util.IntersectRayWithOBB(eyetrace.StartPos, eyetrace.HitPos - eyetrace.StartPos, LocalPlayer():GetPos() + LocalPlayer():OBBCenter(), Angle(0,0,0), Vector(-extra_radius,-extra_radius,-extra_radius), Vector(extra_radius,extra_radius,extra_radius)) then + local_center = local_center or pac.LocalPlayer:GetPos() + pac.LocalPlayer:OBBCenter() + min_radius = min_radius or Vector(-extra_radius, -extra_radius, -extra_radius) + max_radius = max_radius or Vector(extra_radius, extra_radius, extra_radius) + + if util.IntersectRayWithOBB(eyetrace.StartPos, eyetrace.HitPos - eyetrace.StartPos, local_center, angle_zero, min_radius, max_radius) then self.trace_success = true self.trace_success_ply = v self.nextcheck = CurTime() + 0.1 @@ -1061,10 +1068,12 @@ PART.OldEvents = { local b = false local ents_hits = ents.FindInBox(mins, maxs) - for _,ent2 in pairs(ents_hits) do + + for i = 1, #ents_hits do + local ent2 = ents_hits[i] if (ent2 ~= ent and ent2 ~= self:GetRootPart():GetOwner()) and (ent2:IsNPC() or ent2:IsPlayer()) and - not ( (no_npc and ent2:IsNPC()) or (no_players and ent2:IsPlayer()) ) + not ((no_npc and ent2:IsNPC()) or (no_players and ent2:IsPlayer())) then b = true end end @@ -1115,19 +1124,18 @@ PART.OldEvents = { radius = math.max(radius + extra_radius + 1, 1) - local mins = Vector(-x_stretch,-y_stretch,-z_stretch) - local maxs = Vector(x_stretch,y_stretch,z_stretch) + local mins = Vector(-x_stretch, -y_stretch, -z_stretch) + local maxs = Vector(x_stretch, y_stretch, z_stretch) local startpos = ent:WorldSpaceCenter() mins = startpos + mins * radius maxs = startpos + maxs * radius - local ents_hits = ents.FindInBox(mins, maxs) local b = false - for _,ent2 in pairs(ents_hits) do - if IsValid(ent2) and (ent2 ~= ent and ent2 ~= self:GetRootPart():GetOwner()) and - (ent2:IsNPC() or ent2:IsPlayer()) + local ents_hits = ents.FindInBox(mins, maxs) - then + for i = 1, #ents_hits do + local ent2 = ents_hits[i] + if IsValid(ent2) and (ent2 ~= ent and ent2 ~= self:GetRootPart():GetOwner()) and (ent2:IsNPC() or ent2:IsPlayer()) then b = true if ent2:IsNPC() and no_npc then b = false @@ -1571,7 +1579,7 @@ PART.OldEvents = { ent = try_viewmodel(ent) if all_players then - for _, ply in ipairs(player.GetAll()) do + for _, ply in player.Iterator() do local data = ply.pac_say_event if data and self:StringOperator(data.str, find) and data.time + time > pac.RealTime then @@ -2433,7 +2441,7 @@ do --TODO: Rate limit!!! net.Receive("pac.BroadcastPlayerButton", function() - local ply = net.ReadEntity() + local ply = net.ReadPlayer() if not ply:IsValid() then return end @@ -2473,8 +2481,6 @@ do --outsource the part pool operations pac.UpdateButtonEvents(ply, key, down) - - end) PART.OldEvents.button = { @@ -2490,7 +2496,7 @@ do if ply.pac_buttons then for k,v in pairs(ply.pac_buttons) do if v then - table.insert(active, "\"" .. tostring(k) .. "\"") + table_insert(active, "\"" .. tostring(k) .. "\"") end end end @@ -2503,7 +2509,6 @@ do return self:GetOperator() .. " \"" .. button .. "\"" .. " in (" .. active .. ")" end, callback = function(self, ent, button, holdtime, toggle) - local holdtime = holdtime or 0 local toggle = toggle or false @@ -2518,13 +2523,10 @@ do self.toggleimpulsekey[button] = false end - --print(button, "hold" ,self.holdtime) local ply = self:GetPlayerOwner() self.pac_broadcasted_buttons_holduntil = self.pac_broadcasted_buttons_holduntil or {} - if ply == pac.LocalPlayer then - ply.pac_broadcast_buttons = ply.pac_broadcast_buttons or {} if not ply.pac_broadcast_buttons[button] then @@ -2536,19 +2538,13 @@ do end ply.pac_broadcast_buttons[button] = true end - - --print(button, ply.pac_broadcasted_buttons_holduntil[button], ply.pac_broadcast_buttons[button]) - --PrintTable(ply.pac_broadcast_buttons) - --PrintTable(self.pac_broadcasted_buttons_holduntil) end local buttons = ply.pac_buttons self.pac_broadcasted_buttons_holduntil[button] = self.pac_broadcasted_buttons_holduntil[button] or SysTime() - --print(button, self.toggle, self.togglestate) - --print(button,"until",self.pac_broadcasted_buttons_holduntil[button]) + if buttons then - --print("trying to compare " .. SysTime() .. " > " .. self.pac_broadcasted_buttons_holduntil[button] - 0.05) if self.toggle then return self.togglestate elseif self.holdtime > 0 then @@ -2556,11 +2552,9 @@ do else return buttons[button] end - end - end, + end } - end do @@ -2586,27 +2580,29 @@ do function eventMeta:AppendArgument(keyName, keyType, userdata) self.__registeredArguments = self.__registeredArguments or {} + if not keyType then - error('No Type of argument was specified!') + error("No Type of argument was specified!") end - if keyType ~= 'number' and keyType ~= 'string' and keyType ~= 'boolean' then - error('Invalid Type of argument was passed. Valids are number, string or boolean') + if keyType ~= "number" and keyType ~= "string" and keyType ~= "boolean" then + error("Invalid Type of argument was passed. Valids are number, string or boolean") end - for i, data in ipairs(self.__registeredArguments) do - if data[1] == keyName then - error('Argument with key ' .. keyName .. ' already exists!') + for i = 1, #self.__registeredArguments do + if self.__registeredArguments[i][1] == keyName then + error("Argument with key " .. keyName .. " already exists!") end end - self.__registeredArguments = self.__registeredArguments or {} - table.insert(self.__registeredArguments, {keyName, keyType, userdata}) + table_insert(self.__registeredArguments, {keyName, keyType, userdata}) end function eventMeta:PopArgument(keyName) - for i, data in ipairs(self.__registeredArguments) do - if data[1] == keyName then + self.__registeredArguments = self.__registeredArguments or {} + + for i = 1, #self.__registeredArguments do + if self.__registeredArguments[i][1] == keyName then return true, i, table.remove(self.__registeredArguments, i) end end @@ -2631,9 +2627,10 @@ do end local str = part:GetEvent() + local args = part:GetArguments() - if part:GetArguments() ~= "" then - local args = part:GetArguments():gsub(";", " or ") + if args ~= "" then + args = args:gsub(";", " or ") if not tonumber(args) then args = [["]] .. args .. [["]] @@ -2646,8 +2643,8 @@ do local eventMetaTable = { __index = function(self, key) - if key == '__class' or key == '__classname' then - return rawget(getmetatable(self), '__classname') + if key == "__class" or key == "__classname" then + return rawget(getmetatable(self), "__classname") end if rawget(self, key) ~= nil then @@ -2681,7 +2678,7 @@ do end function pac.CreateEvent(nClassName, defArguments) - if not nClassName then error('No classname was specified!') end + if not nClassName then error("No classname was specified!") end local newObj = setmetatable({}, { __index = eventMetaTable.__index, @@ -2705,7 +2702,7 @@ do local classname = nRegister:GetClass() if PART.Events[classname] then - pac.Message('WARN: Registering event with already existing classname!: '.. classname) + pac.Message("WARN: Registering event with already existing classname!: " .. classname) end PART.Events[classname] = nRegister @@ -2740,7 +2737,7 @@ do end timer.Simple(0, function() -- After all addons has loaded - hook.Call('PAC3RegisterEvents', nil, pac.CreateEvent, pac.RegisterEvent) + hook.Call("PAC3RegisterEvents", nil, pac.CreateEvent, pac.RegisterEvent) end) end @@ -2826,13 +2823,13 @@ end -- DarkRP default events do - local plyMeta = FindMetaTable('Player') + local plyMeta = FindMetaTable("Player") local gamemode = engine.ActiveGamemode - local isDarkRP = function() return gamemode() == 'darkrp' end + local isDarkRP = function() return gamemode() == "darkrp" end local events = { { - name = 'is_arrested', + name = "is_arrested", args = {}, available = function() return plyMeta.isArrested ~= nil end, func = function(self, eventPart, ent) @@ -2842,7 +2839,7 @@ do }, { - name = 'is_wanted', + name = "is_wanted", args = {}, available = function() return plyMeta.isWanted ~= nil end, func = function(self, eventPart, ent) @@ -2852,7 +2849,7 @@ do }, { - name = 'is_police', + name = "is_police", args = {}, available = function() return plyMeta.isCP ~= nil end, func = function(self, eventPart, ent) @@ -2862,17 +2859,17 @@ do }, { - name = 'wanted_reason', - args = {{'find', 'string'}}, + name = "wanted_reason", + args = {{"find", "string"}}, available = function() return plyMeta.getWantedReason ~= nil and plyMeta.isWanted ~= nil end, func = function(self, eventPart, ent, find) ent = try_viewmodel(ent) - return eventPart:StringOperator(ent.isWanted and ent.getWantedReason and ent:isWanted() and ent:getWantedReason() or '', find) + return eventPart:StringOperator(ent.isWanted and ent.getWantedReason and ent:isWanted() and ent:getWantedReason() or "", find) end }, { - name = 'is_cook', + name = "is_cook", args = {}, available = function() return plyMeta.isCook ~= nil end, func = function(self, eventPart, ent) @@ -2882,7 +2879,7 @@ do }, { - name = 'is_hitman', + name = "is_hitman", args = {}, available = function() return plyMeta.isHitman ~= nil end, func = function(self, eventPart, ent) @@ -2892,7 +2889,7 @@ do }, { - name = 'has_hit', + name = "has_hit", args = {}, available = function() return plyMeta.hasHit ~= nil end, func = function(self, eventPart, ent) @@ -2902,8 +2899,8 @@ do }, { - name = 'hit_price', - args = {{'amount', 'number'}}, + name = "hit_price", + args = {{"amount", "number"}}, available = function() return plyMeta.getHitPrice ~= nil end, func = function(self, eventPart, ent, amount) ent = try_viewmodel(ent) @@ -2965,8 +2962,9 @@ function PART:IsHiddenBySomethingElse(only_self) if only_self then return false end - for _, parent in ipairs(self:GetParentList()) do - if is_hidden_by_something_else(parent, self) then + local parents = self:GetParentList() + for i = 1, #parents do + if is_hidden_by_something_else(parents[i], self) then return true end end @@ -3070,7 +3068,9 @@ function PART:SetAffectChildrenOnly(b) if parent:IsValid() then parent:SetEventTrigger(self, b) - for _, child in ipairs(self:GetChildren()) do + local children = self:GetChildren() + for i = 1, #children do + local child = children[i] if child.active_events[self] then child.active_events[self] = nil child.active_events_ref_count = child.active_events_ref_count - 1 @@ -3080,23 +3080,22 @@ function PART:SetAffectChildrenOnly(b) end else - for _, child in ipairs(self:GetChildren()) do - child:SetEventTrigger(self, b) - end - if self:GetParent():IsValid() then - local parent = self:GetParent() - if parent.active_events[self] then - parent.active_events[self] = nil - parent.active_events_ref_count = parent.active_events_ref_count - 1 - parent:CallRecursive("CalcShowHide", false) - end + local children = self:GetChildren() + for i = 1, #children do + children[i]:SetEventTrigger(self, b) end + local parent = self:GetParent() + if parent:IsValid() and parent.active_events[self] then + parent.active_events[self] = nil + parent.active_events_ref_count = parent.active_events_ref_count - 1 + parent:CallRecursive("CalcShowHide", false) + end end end end - self.AffectChildrenOnly = b + self.AffectChildrenOnly = b end function PART:OnRemove() @@ -3108,6 +3107,7 @@ function PART:OnRemove() parent:CalcShowHide() end end + if IsValid(self.DestinationPart) then self.DestinationPart.active_events[self] = nil self.DestinationPart.active_events_ref_count = self.DestinationPart.active_events_ref_count - 1 @@ -3119,8 +3119,9 @@ function PART:TriggerEvent(b) self.event_triggered = b -- event_triggered is just used for the editor if self.AffectChildrenOnly then - for _, child in ipairs(self:GetChildren()) do - child:SetEventTrigger(self, b) + local children = self:GetChildren() + for i = 1, #children do + children[i]:SetEventTrigger(self, b) end else local parent = self:GetParent() @@ -3128,6 +3129,7 @@ function PART:TriggerEvent(b) parent:SetEventTrigger(self, b) end end + if IsValid(self.DestinationPart) then --target part. the proper one. if IsValid(self.previousdestinationpart) then if self.DestinationPart ~= self.previousdestinationpart then --once we change the destination part we need to reset the old one @@ -3206,9 +3208,10 @@ function PART:GetParsedArgumentsForObject(eventObject) end local args = line:Split("@@") + local event_args = eventObject:GetArguments() - for i, argData in pairs(eventObject:GetArguments()) do - local typ = argData[2] + for i = 1, #event_args do + local typ = event_args[i][2] if args[i] ~= nil then if typ == "boolean" then @@ -3396,7 +3399,7 @@ pac.camera_linked_command_events = {} local initially_check_camera_linked_command_events = true net.Receive("pac_event", function(umr) - local ply = net.ReadEntity() + local ply = net.ReadPlayer() local str = net.ReadString() local on = net.ReadInt(8) @@ -3717,14 +3720,14 @@ do for k,v in pairs(available) do if uncolored_events[k] then - table.insert(uncolored_sublist,available[k]) + table_insert(uncolored_sublist,available[k]) end end table.sort(uncolored_sublist, function(a, b) return a.trigger < b.trigger end) for k,v in ipairs(uncolored_sublist) do - table.insert(list, v) + table_insert(list, v) end --[[legacy behavior @@ -3732,7 +3735,7 @@ do for k,v in pairs(available) do if k == names[k].name then v.trigger = k - table.insert(list, v) + table_insert(list, v) end end diff --git a/lua/pac3/core/client/parts/fog.lua b/lua/pac3/core/client/parts/fog.lua index 7748b3f42..f97f1732e 100644 --- a/lua/pac3/core/client/parts/fog.lua +++ b/lua/pac3/core/client/parts/fog.lua @@ -11,8 +11,8 @@ local BUILDER, PART = pac.PartTemplate("base_drawable") PART.ClassName = "fog" -PART.Group = 'modifiers' -PART.Icon = 'icon16/weather_clouds.png' +PART.Group = "modifiers" +PART.Icon = "icon16/weather_clouds.png" BUILDER:StartStorableVars() BUILDER:GetSet("Color", Vector(255, 255, 255), {editor_panel = "color"}) diff --git a/lua/pac3/core/client/parts/halo.lua b/lua/pac3/core/client/parts/halo.lua index 18db023da..f5a49f2ab 100644 --- a/lua/pac3/core/client/parts/halo.lua +++ b/lua/pac3/core/client/parts/halo.lua @@ -1,13 +1,14 @@ local Color = Color local Vector = Vector +local table_insert = table.insert local BUILDER, PART = pac.PartTemplate("base") PART.ClassName = "halo" PART.ThinkTime = 0 -PART.Group = {'effects', 'model'} -PART.Icon = 'icon16/shading.png' +PART.Group = {"effects", "model"} +PART.Icon = "icon16/shading.png" BUILDER:StartStorableVars() BUILDER:SetPropertyGroup("generic") @@ -27,7 +28,6 @@ BUILDER:EndStorableVars() function PART:GetNiceName() local h = pac.ColorToNames(self:GetColor()) - return h .. " halo" end @@ -39,6 +39,16 @@ function PART:SetPasses(n) self.Passes = math.min(n, 50) end +function PART:SetColor(v) + self.ColorC = self.ColorC or Color(255, 255, 255, 255) + + self.ColorC.r = v.r + self.ColorC.g = v.g + self.ColorC.b = v.b + + self.Color = v +end + function PART:GetTarget() local parent = self:GetTargetEntity() @@ -50,7 +60,6 @@ function PART:GetTarget() end function PART:OnThink() - local tbl = {} local ent = self:GetOwner() @@ -60,25 +69,37 @@ function PART:OnThink() local target = self:GetTarget() + local children + if self.AffectTargetChildren and target:IsValid() then - for _, part in ipairs(target:GetChildrenList()) do + children = target:GetChildrenList() + for i = 1, #children do + local part = children[i] local ent = part:GetOwner() + if ent:IsValid() and not part:IsHiddenCached() then - table.insert(tbl, ent) + table_insert(tbl, ent) end end end if self.AffectChildren then - for _, part in ipairs(self:GetChildrenList()) do + children = self:GetChildrenList() + for i = 1, #children do + local part = children[i] local ent = part:GetOwner() + if ent:IsValid() and not part:IsHiddenCached() then - table.insert(tbl, ent) + table_insert(tbl, ent) end end end - pac.haloex.Add(tbl, Color(self.Color.r, self.Color.g, self.Color.b), self.BlurX, self.BlurY, self.Passes, self.Additive, self.IgnoreZ, self.Amount, self.SphericalSize, self.Shape) + if not self.ColorC then + self.ColorC = Color(self.Color.r, self.Color.g, self.Color.b) + end + + pac.haloex.Add(tbl, self.ColorC, self.BlurX, self.BlurY, self.Passes, self.Additive, self.IgnoreZ, self.Amount, self.SphericalSize, self.Shape) end BUILDER:Register() \ No newline at end of file diff --git a/lua/pac3/core/client/parts/jiggle.lua b/lua/pac3/core/client/parts/jiggle.lua index ec5585a27..7dc9f51db 100644 --- a/lua/pac3/core/client/parts/jiggle.lua +++ b/lua/pac3/core/client/parts/jiggle.lua @@ -1,15 +1,16 @@ -local FrameTime = FrameTime +local physenv_GetGravity = physenv.GetGravity local util_QuickTrace = util.QuickTrace +local math_AngleDifference = math.AngleDifference +local FrameTime = FrameTime local VectorRand = VectorRand local Vector = Vector local Angle = Angle -local physenv_GetGravity = physenv.GetGravity local BUILDER, PART = pac.PartTemplate("base_drawable") PART.ClassName = "jiggle" -PART.Group = 'model' -PART.Icon = 'icon16/chart_line.png' +PART.Group = "model" +PART.Icon = "icon16/chart_line.png" BUILDER:StartStorableVars() BUILDER:GetSet("Strain", 0.5, {editor_onchange = function(self, num) @@ -37,8 +38,6 @@ BUILDER:StartStorableVars() BUILDER:GetSet("ResetOnHide", false) BUILDER:EndStorableVars() -local math_AngleDifference = math.AngleDifference - function PART:Reset() local pos, ang = self:GetDrawPosition() @@ -83,17 +82,21 @@ function PART:OnDraw() self.first_time_reset = false end - local delta = FrameTime() - local speed = self.Speed * delta - - self.vel = self.vel or VectorRand() - self.pos = self.pos or pos * 1 + if not self.pos then + self.pos = pos * 1 + end - if self.StopRadius ~= 0 and self.pos and self.pos:Distance(pos) < self.StopRadius then + if self.StopRadius ~= 0 and self.pos:DistToSqr(pos) < (self.StopRadius ^ 2) then self.vel = Vector() return end + if not self.vel then + self.vel = VectorRand() + end + + local speed = self.Speed * FrameTime() + if self.JigglePosition then if not self.ConstrainX then self.vel.x = self.vel.x + (pos.x - self.pos.x) @@ -148,9 +151,9 @@ function PART:OnDraw() end if self.ConstrainSphere > 0 then - local len = math.min(self.pos:Distance(pos), self.ConstrainSphere) + local diff = self.pos - pos - self.pos = pos + (self.pos - pos):GetNormalized() * len + self.pos = pos + (diff:GetNormalized() * math.min(diff:Length(), self.ConstrainSphere)) end if self.JiggleAngle then diff --git a/lua/pac3/core/client/parts/legacy/bone.lua b/lua/pac3/core/client/parts/legacy/bone.lua index 137d53851..571d27e6c 100644 --- a/lua/pac3/core/client/parts/legacy/bone.lua +++ b/lua/pac3/core/client/parts/legacy/bone.lua @@ -1,7 +1,21 @@ local NULL = NULL local pairs = pairs -for _, v in pairs(ents.GetAll()) do +local entMeta = FindMetaTable("Entity") +local IsEntValid = entMeta.IsValid +local GetTable = entMeta.GetTable +local GetBoneCount = entMeta.GetBoneCount +local GetBoneMatrix = entMeta.GetBoneMatrix +local SetBoneMatrix = entMeta.SetBoneMatrix +local ManipulateBonePosition = entMeta.ManipulateBonePosition +local ManipulateBoneAngles = entMeta.ManipulateBoneAngles +local ManipulateBoneScale = entMeta.ManipulateBoneScale +local ManipulateBoneJiggle = entMeta.ManipulateBoneJiggle +local GetManipulateBonePosition = entMeta.GetManipulateBonePosition +local GetManipulateBoneAngles = entMeta.GetManipulateBoneAngles +local GetManipulateBoneScale = entMeta.GetManipulateBoneScale + +for _, v in ents.Iterator() do v.pac_bone_setup_data = nil end @@ -12,7 +26,7 @@ PART.ClassName = "bone" PART.Group = "legacy" PART.is_bone_part = true -PART.Icon = 'icon16/connect.png' +PART.Icon = "icon16/connect.png" BUILDER:StartStorableVars() BUILDER:SetPropertyGroup("generic") @@ -67,7 +81,7 @@ PART.OnParent = PART.OnShow function PART:OnThink() -- this is to setup the cached values - if not self.first_getbpos and self:GetOwner():IsValid() then + if not self.first_getbpos and IsEntValid(self:GetOwner()) then self:GetBonePosition() self.first_getbpos = true end @@ -76,7 +90,7 @@ end function PART:OnHide() local owner = self:GetOwner() - if owner:IsValid() then + if IsEntValid(owner) then owner.pac_bone_setup_data = owner.pac_bone_setup_data or {} owner.pac_bone_setup_data[self.UniqueID] = nil end @@ -91,46 +105,45 @@ function PART:GetBonePosition() return pos, ang end -local function manpos(ent, id, pos, part) +local function manpos(ent, entTbl, id, pos, part) if part.AlternativeBones then - ent.pac_bone_setup_data[part.UniqueID].pos = part.Position + part.PositionOffset + entTbl.pac_bone_setup_data[part.UniqueID].pos = part.Position + part.PositionOffset else - ent:ManipulateBonePosition(id, ent:GetManipulateBonePosition(id) + pos) + ManipulateBonePosition(ent, id, GetManipulateBonePosition(ent, id) + pos) part.modified_bones = true end end -local function manang(ent, id, ang, part) +local function manang(ent, entTbl, id, ang, part) if part.AlternativeBones then - ent.pac_bone_setup_data[part.UniqueID].ang = part.Angles + part.AngleOffset + entTbl.pac_bone_setup_data[part.UniqueID].ang = part.Angles + part.AngleOffset else - ent:ManipulateBoneAngles(id, ent:GetManipulateBoneAngles(id) + ang) + ManipulateBoneAngles(ent, id, GetManipulateBoneAngles(ent, id) + ang) part.modified_bones = true end end local inf_scale = Vector(math.huge, math.huge, math.huge) -local inf_scale_tempcrashfix = Vector(1,1,1)*0.001 +local inf_scale_tempcrashfix = Vector(1, 1, 1) * 0.001 -local function manscale(ent, id, scale, part) +local function manscale(ent, entTbl, id, scale, part) if part.AlternativeBones then - ent.pac_bone_setup_data[part.UniqueID].scale = scale + entTbl.pac_bone_setup_data[part.UniqueID].scale = scale else - ent:ManipulateBoneScale(id, ent:GetManipulateBoneScale(id) * scale) + ManipulateBoneScale(ent, id, GetManipulateBoneScale(ent, id) * scale) part.modified_bones = true end end local function scale_children(owner, id, scale, origin, ownerScale) - local count = owner:GetBoneCount() - ownerScale = ownerScale or owner.pac3_Scale or 1 + local count = GetBoneCount(owner) if count == 0 or count < id then return end for i = 0, count - 1 do if owner:GetBoneParent(i) ~= id then goto CONTINUE end - local mat = owner:GetBoneMatrix(i) + local mat = GetBoneMatrix(owner, i) if mat then if origin then @@ -138,7 +151,8 @@ local function scale_children(owner, id, scale, origin, ownerScale) end mat:Scale(mat:GetScale() * scale / ownerScale) - owner:SetBoneMatrix(i, mat) + + SetBoneMatrix(owner, i, mat) end scale_children(owner, i, scale, origin, ownerScale) @@ -149,17 +163,22 @@ local in_build = false function pac.build_bone_callback(ent) if in_build then return end + local entTbl = GetTable(ent) + in_build = true - if ent.pac_matrixhack then + if entTbl.pac_matrixhack then pac.LegacyScale(ent) end - if ent.pac_bone_setup_data then - for uid, data in pairs(ent.pac_bone_setup_data) do + if entTbl.pac_bone_setup_data then + local entScale = entTbl.pac3_Scale or 1 + + for uid, data in pairs(entTbl.pac_bone_setup_data) do local part = data.part or NULL if part:IsValid() then - local mat = ent:GetBoneMatrix(data.bone) + local mat = GetBoneMatrix(ent, data.bone) + if mat then if part.FollowPart:IsValid() and part.FollowPart.GetWorldAngles and part.FollowPart.GetWorldPosition then if part.FollowAnglesOnly then @@ -185,24 +204,25 @@ function pac.build_bone_callback(ent) end if part.ScaleChildren then - local scale = part.Scale * part.Size - scale_children(ent, data.bone, scale, data.origin) + scale_children(ent, data.bone, part.Scale * part.Size, data.origin, entScale) end - ent:SetBoneMatrix(data.bone, mat) + SetBoneMatrix(ent, data.bone, mat) end else - ent.pac_bone_setup_data[uid] = nil + entTbl.pac_bone_setup_data[uid] = nil end end end + in_build = false end function PART:OnBuildBonePositions() local owner = self:GetOwner() + if not IsEntValid(owner) then return end - if not owner:IsValid() then return end + local ownerTbl = GetTable(owner) local index = self:GetModelBoneIndex() @@ -210,26 +230,34 @@ function PART:OnBuildBonePositions() index = 0 end - owner.pac_bone_setup_data = owner.pac_bone_setup_data or {} + if not ownerTbl.pac_bone_setup_data then + ownerTbl.pac_bone_setup_data = {} + end if self.AlternativeBones or self.ScaleChildren or self.FollowPart:IsValid() then - owner.pac_bone_setup_data[self.UniqueID] = owner.pac_bone_setup_data[self.UniqueID] or {} - owner.pac_bone_setup_data[self.UniqueID].bone = index - owner.pac_bone_setup_data[self.UniqueID].part = self + if not ownerTbl.pac_bone_setup_data[self.UniqueID] then + ownerTbl.pac_bone_setup_data[self.UniqueID] = {} + end + + ownerTbl.pac_bone_setup_data[self.UniqueID].bone = index + ownerTbl.pac_bone_setup_data[self.UniqueID].part = self else - owner.pac_bone_setup_data[self.UniqueID] = nil + ownerTbl.pac_bone_setup_data[self.UniqueID] = nil end local ang = self:CalcAngles(self.Angles) or self.Angles - if not owner.pac_follow_bones_function then - owner.pac_follow_bones_function = pac.build_bone_callback + if not ownerTbl.pac_follow_bones_function then + ownerTbl.pac_follow_bones_function = pac.build_bone_callback + local id + id = owner:AddCallback("BuildBonePositions", function(ent) if not self:IsValid() then owner:RemoveCallback("BuildBonePositions", id) return end + pac.build_bone_callback(ent) end) end @@ -240,48 +268,48 @@ function PART:OnBuildBonePositions() ang.y = -ang.p end - manpos(owner, index, self.Position + self.PositionOffset, self) - manang(owner, index, ang + self.AngleOffset, self) + manpos(owner, ownerTbl, index, self.Position + self.PositionOffset, self) + manang(owner, ownerTbl, index, ang + self.AngleOffset, self) end - if owner.pac_bone_setup_data[self.UniqueID] then + if ownerTbl.pac_bone_setup_data[self.UniqueID] then if self.MoveChildrenToOrigin then - owner.pac_bone_setup_data[self.UniqueID].origin = self:GetBonePosition() + ownerTbl.pac_bone_setup_data[self.UniqueID].origin = self:GetBonePosition() else - owner.pac_bone_setup_data[self.UniqueID].origin = nil + ownerTbl.pac_bone_setup_data[self.UniqueID].origin = nil end end - owner:ManipulateBoneJiggle(index, isnumber(self.Jiggle) and self.Jiggle or (self.Jiggle and 1 or 0)) -- afaik anything but 1 is not doing anything at all + -- afaik anything but 1 is not doing anything at all + ManipulateBoneJiggle(owner, index, isnumber(self.Jiggle) and self.Jiggle or (self.Jiggle and 1 or 0)) local scale if self.HideMesh then scale = inf_scale - owner.pac_inf_scale = true + ownerTbl.pac_inf_scale = true if self.InvertHideMesh then - local count = owner:GetBoneCount() + local count = GetBoneCount(owner) for i = 0, count - 1 do if i ~= index then - manscale(owner, i, inf_scale, self) + manscale(owner, ownerTbl, i, inf_scale, self) end end return end else - - owner.pac_inf_scale = false + ownerTbl.pac_inf_scale = false scale = self.Scale * self.Size end - manscale(owner, index, scale, self) + manscale(owner, ownerTbl, index, scale, self) - owner.needs_setupbones_from_legacy_bone_parts = true + ownerTbl.needs_setupbones_from_legacy_bone_parts = true end BUILDER:Register() diff --git a/lua/pac3/core/client/parts/legacy/bone2.lua b/lua/pac3/core/client/parts/legacy/bone2.lua index a70c9ffd8..4b7ed6652 100644 --- a/lua/pac3/core/client/parts/legacy/bone2.lua +++ b/lua/pac3/core/client/parts/legacy/bone2.lua @@ -1,7 +1,7 @@ local NULL = NULL local pairs = pairs -for _, v in pairs(ents.GetAll()) do +for _, v in ents.Iterator() do v.pac_bone_setup_data = nil end @@ -10,7 +10,7 @@ local BUILDER, PART = pac.PartTemplate("base_movable") PART.FriendlyName = "legacy experimental bone" PART.ClassName = "bone2" PART.Group = "legacy" -PART.Icon = 'icon16/connect.png' +PART.Icon = "icon16/connect.png" PART.is_bone_part = true BUILDER:StartStorableVars() diff --git a/lua/pac3/core/client/parts/legacy/entity.lua b/lua/pac3/core/client/parts/legacy/entity.lua index f46778e9b..3eb1686d4 100644 --- a/lua/pac3/core/client/parts/legacy/entity.lua +++ b/lua/pac3/core/client/parts/legacy/entity.lua @@ -404,8 +404,9 @@ function PART:SetModel(path) pac.ResetBoneCache(ent) - for _, child in ipairs(self:GetChildrenList()) do - child:OnShow(true) + local children = self:GetChildrenList() + for i = 1, #children do + children[i]:OnShow(true) end end, function(err) pac.Message(err) @@ -417,7 +418,7 @@ function PART:SetModel(path) local msg = reason2 or reason or "mdl is not allowed" self.loading = msg self:SetError(msg) - pac.Message(self:GetPlayerOwner(), ' - mdl files are not allowed') + pac.Message(self:GetPlayerOwner(), " - mdl files are not allowed") end elseif self.Model ~= "" then diff --git a/lua/pac3/core/client/parts/legacy/light.lua b/lua/pac3/core/client/parts/legacy/light.lua index 69a274866..785449302 100644 --- a/lua/pac3/core/client/parts/legacy/light.lua +++ b/lua/pac3/core/client/parts/legacy/light.lua @@ -4,7 +4,7 @@ PART.FriendlyName = "legacy light" PART.ClassName = "light" PART.Group = "legacy" -PART.Icon = 'icon16/lightbulb.png' +PART.Icon = "icon16/lightbulb.png" BUILDER:StartStorableVars() BUILDER:GetSet("Brightness", 1) diff --git a/lua/pac3/core/client/parts/light.lua b/lua/pac3/core/client/parts/light.lua index 89fc0408f..68d03831f 100644 --- a/lua/pac3/core/client/parts/light.lua +++ b/lua/pac3/core/client/parts/light.lua @@ -4,8 +4,8 @@ local BUILDER, PART = pac.PartTemplate("base_drawable") PART.FriendlyName = "light" PART.ClassName = "light2" -PART.Group = 'effects' -PART.Icon = 'icon16/lightbulb.png' +PART.Group = "effects" +PART.Icon = "icon16/lightbulb.png" PART.ProperColorRange = true BUILDER:StartStorableVars() @@ -37,8 +37,9 @@ BUILDER:EndStorableVars() function PART:GetLight() if not self.light then - self.light = DynamicLight(tonumber(string.sub(self:GetPrintUniqueID(),1,7), 16)) + self.light = DynamicLight(tonumber(string.sub(self:GetPrintUniqueID(), 1, 7), 16)) end + self.light.decay = 0 self.light.dietime = math.huge @@ -47,8 +48,10 @@ end function PART:RemoveLight() if not self.light then return end + local light = self.light self.light = nil + -- this prevents fade out when removing the light light.pos = Vector(9999, 9999, 9999) timer.Simple(0, function() @@ -57,8 +60,7 @@ function PART:RemoveLight() end function PART:GetNiceName() - local color = self:GetColor() - local hue = pac.ColorToNames({r = color[1] * 255, g = color[2] * 255, b = color[3] * 255}) + local hue = pac.VectorColorToNames(self:GetColor()) return hue .. " light" end @@ -83,6 +85,7 @@ function PART:OnDraw() self:GetLight().pos = pos self:GetLight().dir = ang:Forward() end + function PART:SetStyle(val) self.Style = val self:GetLight().Style = self.Style diff --git a/lua/pac3/core/client/parts/lock.lua b/lua/pac3/core/client/parts/lock.lua index 7fe0b53eb..42d043e93 100644 --- a/lua/pac3/core/client/parts/lock.lua +++ b/lua/pac3/core/client/parts/lock.lua @@ -7,6 +7,7 @@ local Matrix = Matrix local physics_point_ent_classes = { ["prop_physics"] = true, ["prop_physics_multiplayer"] = true, + ["prop_physics_respawnable"] = true, ["prop_ragdoll"] = true, ["weapon_striderbuster"] = true, ["item_item_crate"] = true, @@ -15,6 +16,11 @@ local physics_point_ent_classes = { ["physics_cannister"] = true } +local convar_lock = GetConVar("pac_sv_lock") +local convar_lock_grab = GetConVar("pac_sv_lock_grab") +local convar_lock_max_grab_radius = GetConVar("pac_sv_lock_max_grab_radius") +local convar_lock_teleport = GetConVar("pac_sv_lock_teleport") +local convar_combat_enforce_netrate = GetConVar("pac_sv_combat_enforce_netrate_monitor_serverside") local BUILDER, PART = pac.PartTemplate("base_movable") @@ -22,7 +28,6 @@ PART.ClassName = "lock" PART.Group = "combat" PART.Icon = "icon16/lock.png" - BUILDER:StartStorableVars() :SetPropertyGroup("Behaviour") :GetSet("Mode", "None", {enums = {["None"] = "None", ["Grab"] = "Grab", ["Teleport"] = "Teleport"}}) @@ -54,13 +59,11 @@ BUILDER:StartStorableVars() :GetSet("PhysicsProps", false) :GetSet("NPC", false) - BUILDER:EndStorableVars() function PART:OnThink() - - if not GetConVar('pac_sv_lock'):GetBool() then return end - if util.NetworkStringToID( "pac_request_position_override_on_entity_grab" ) == 0 then self:SetError("This part is deactivated on the server") return end + if not convar_lock:GetBool() then return end + if util.NetworkStringToID("pac_request_position_override_on_entity_grab") == 0 then self:SetError("This part is deactivated on the server") return end pac.Blocked_Combat_Parts = pac.Blocked_Combat_Parts or {} if pac.Blocked_Combat_Parts then if pac.Blocked_Combat_Parts[self.ClassName] then return end @@ -79,7 +82,7 @@ function PART:OnThink() end if self.Mode == "Grab" then - if not GetConVar('pac_sv_lock_grab'):GetBool() then return end + if not convar_lock_grab:GetBool() then return end if pac.Blocked_Combat_Parts then if pac.Blocked_Combat_Parts[self.ClassName] then return @@ -90,7 +93,7 @@ function PART:OnThink() end self:CheckEntValidity() if self.valid_ent then - local final_ang = Angle(0,0,0) + local final_ang = Angle(0, 0, 0) if self.OverrideAngles then --if overriding angles if self.is_first_time then self.default_ang = self.target_ent:GetAngles() --record the initial ent angles @@ -120,8 +123,10 @@ function PART:OnThink() local relative_offset_pos = offset_matrix:GetTranslation() local relative_offset_ang = offset_matrix:GetAngles() - if pac.LocalPlayer == self:GetPlayerOwner() then - if not GetConVar("pac_sv_combat_enforce_netrate_monitor_serverside"):GetBool() then + local ply_owner = self:GetPlayerOwner() + + if pac.LocalPlayer == ply_owner then + if not convar_combat_enforce_netrate:GetBool() then if not pac.CountNetMessage() then self:SetInfo("Went beyond the allowance") return end end net.Start("pac_request_position_override_on_entity_grab") @@ -140,7 +145,8 @@ function PART:OnThink() if self.target_ent:IsPlayer() then if self.OverrideEyeAngles then try_override_eyeang = true end end - if pac.LocalPlayer == self:GetPlayerOwner() then + + if pac.LocalPlayer == ply_owner then net.WriteBool(self.OverrideAngles) net.WriteBool(try_override_eyeang) net.WriteBool(self.NoCollide) @@ -164,6 +170,7 @@ function PART:OnThink() net.WriteBool(self.DrawLocalPlayer) net.SendToServer() end + --print(self:GetRootPart():GetOwner()) if self.Players and self.target_ent:IsPlayer() and self.OverrideAngles then local mat = Matrix() @@ -184,18 +191,18 @@ function PART:OnThink() local eyeang = self.target_ent:EyeAngles() --print("eyeang", eyeang) - eyeang.p = 0*eyeang.p + + eyeang.p = 0 eyeang.y = eyeang.y - eyeang.r = 0*eyeang.r + eyeang.r = 0 + mat:Rotate(final_ang - eyeang) --this works --mat:Rotate(eyeang) --print("transform ang", final_ang) --print("part's angles", self:GetWorldAngles()) --mat:Rotate(self:GetWorldAngles()) - self.target_ent:EnableMatrix("RenderMultiply", mat) - end self.grabbing = true @@ -245,10 +252,8 @@ do if part then if part.ClassName == "lock" then part:BreakLock(target_to_release) - end end - else MsgC(Color(200, 200, 200), "NOW! WE SEARCH YOUR LOCAL PARTS!\n") for i,part in pairs(pac.GetLocalParts()) do @@ -265,7 +270,6 @@ do end) net.Receive("pac_mark_grabbed_ent", function(len) - local target_to_mark = net.ReadEntity() local successful_grab = net.ReadBool() local uid = net.ReadString() @@ -285,7 +289,7 @@ end function PART:SetRadius(val) self.Radius = val - local sv_dist = GetConVar("pac_sv_lock_max_grab_radius"):GetInt() + local sv_dist = convar_lock_max_grab_radius:GetInt() if self.Radius > sv_dist then self:SetInfo("Your radius is beyond the server's maximum permitted! Server max is " .. sv_dist) else @@ -294,64 +298,76 @@ function PART:SetRadius(val) end function PART:OnShow() - if util.NetworkStringToID( "pac_request_position_override_on_entity_grab" ) == 0 then self:SetError("This part is deactivated on the server") return end + if util.NetworkStringToID("pac_request_position_override_on_entity_grab") == 0 then self:SetError("This part is deactivated on the server") return end + local origin_part + self.is_first_time = true + if self.resetting_condition or self.forcebreak then if self.next_allowed_grab < CurTime() then self.forcebreak = false self.resetting_condition = false end end - pac.AddHook("PostDrawOpaqueRenderables", "pace_draw_lockpart_preview"..self.UniqueID, function() + + pac.AddHook("PostDrawOpaqueRenderables", "pace_draw_lockpart_preview" .. self.UniqueID, function() if self.TargetPart:IsValid() then origin_part = self.TargetPart else origin_part = self end if origin_part == nil or not self.Preview or pac.LocalPlayer ~= self:GetPlayerOwner() then return end - local sv_dist = GetConVar("pac_sv_lock_max_grab_radius"):GetInt() + local sv_dist = convar_lock_max_grab_radius:GetInt() - render.DrawLine(origin_part:GetWorldPosition(),origin_part:GetWorldPosition() + Vector(0,0,-self.OffsetDownAmount),Color(255,255,255)) + render.DrawLine(origin_part:GetWorldPosition(), origin_part:GetWorldPosition() + Vector(0, 0, -self.OffsetDownAmount), Color(255, 255, 255)) if self.Radius < sv_dist then self:SetInfo(nil) - render.DrawWireframeSphere(origin_part:GetWorldPosition() + Vector(0,0,-self.OffsetDownAmount), sv_dist, 30, 30, Color(50,50,150),true) - render.DrawWireframeSphere(origin_part:GetWorldPosition() + Vector(0,0,-self.OffsetDownAmount), self.Radius, 30, 30, Color(255,255,255),true) + render.DrawWireframeSphere(origin_part:GetWorldPosition() + Vector(0, 0, -self.OffsetDownAmount), sv_dist, 30, 30, Color(50, 50, 150), true) + render.DrawWireframeSphere(origin_part:GetWorldPosition() + Vector(0, 0, -self.OffsetDownAmount), self.Radius, 30, 30, Color(255, 255, 255), true) else self:SetInfo("Your radius is beyond the server max! Active max is " .. sv_dist) - render.DrawWireframeSphere(origin_part:GetWorldPosition() + Vector(0,0,-self.OffsetDownAmount), sv_dist, 30, 30, Color(0,255,255),true) - render.DrawWireframeSphere(origin_part:GetWorldPosition() + Vector(0,0,-self.OffsetDownAmount), self.Radius, 30, 30, Color(100,100,100),true) + render.DrawWireframeSphere(origin_part:GetWorldPosition() + Vector(0, 0, -self.OffsetDownAmount), sv_dist, 30, 30, Color(0, 255,255), true) + render.DrawWireframeSphere(origin_part:GetWorldPosition() + Vector(0, 0, -self.OffsetDownAmount), self.Radius, 30, 30, Color(100, 100, 100), true) end - end) + if self.Mode == "Teleport" then - if not GetConVar('pac_sv_lock_teleport'):GetBool() or pac.Blocked_Combat_Parts[self.ClassName] then return end + if not convar_lock_teleport:GetBool() or pac.Blocked_Combat_Parts[self.ClassName] then return end if pace.still_loading_wearing then return end + self.target_ent = nil local ang_yaw_only = self:GetWorldAngles() ang_yaw_only.p = 0 ang_yaw_only.r = 0 - if pac.LocalPlayer == self:GetPlayerOwner() then + if pac.LocalPlayer == self:GetPlayerOwner() then local teleport_pos_final = self:GetWorldPosition() if self.ClampDistance then local ply_pos = self:GetPlayerOwner():GetPos() local pos = self:GetWorldPosition() - if pos:Distance(ply_pos) > self.Radius then - local clamped_pos = ply_pos + (pos - ply_pos):GetNormalized()*self.Radius + if pos:DistToSqr(ply_pos) > (self.Radius ^ 2) then + local clamped_pos = ply_pos + (pos - ply_pos):GetNormalized() * self.Radius teleport_pos_final = clamped_pos end end - if self.SlopeSafety then teleport_pos_final = teleport_pos_final + Vector(0,0,30) end - if not GetConVar("pac_sv_combat_enforce_netrate_monitor_serverside"):GetBool() then - if not pac.CountNetMessage() then self:SetInfo("Went beyond the allowance") return end + + if self.SlopeSafety then + teleport_pos_final = teleport_pos_final + Vector(0, 0, 30) end + + if not convar_combat_enforce_netrate:GetBool() and not pac.CountNetMessage() then + self:SetInfo("Went beyond the allowance") + return + end + timer.Simple(0, function() if self:IsHidden() or self:IsDrawHidden() then return end + net.Start("pac_request_position_override_on_entity_teleport") net.WriteString(self.UniqueID) net.WriteVector(teleport_pos_final) @@ -359,8 +375,8 @@ function PART:OnShow() net.WriteBool(self.OverrideAngles) net.SendToServer() end) - end + self.grabbing = false elseif self.Mode == "Grab" then self:DecideTarget() @@ -369,81 +385,97 @@ function PART:OnShow() end function PART:OnHide() - pac.RemoveHook("PostDrawOpaqueRenderables", "pace_draw_lockpart_preview"..self.UniqueID) + pac.RemoveHook("PostDrawOpaqueRenderables", "pace_draw_lockpart_preview" .. self.UniqueID) + self.teleported = false self.grabbing = false - if self.target_ent == nil then return - else self.target_ent.IsGrabbed = false self.target_ent.IsGrabbedID = nil end - if util.NetworkStringToID( "pac_request_position_override_on_entity_grab" ) == 0 then self:SetError("This part is deactivated on the server") return end + + if self.target_ent == nil then + return + else + self.target_ent.IsGrabbed = false + self.target_ent.IsGrabbedID = nil + end + + if util.NetworkStringToID("pac_request_position_override_on_entity_grab") == 0 then + self:SetError("This part is deactivated on the server") + return + end + self:reset_ent_ang() end function PART:reset_ent_ang() - if self.target_ent == nil then return end - local reset_ent = self.target_ent + if not IsValid(self.target_ent) then return end - if reset_ent:IsValid() then - timer.Simple(math.min(self.RestoreDelay,5), function() - if pac.LocalPlayer == self:GetPlayerOwner() then - if not GetConVar("pac_sv_combat_enforce_netrate_monitor_serverside"):GetBool() then - if not pac.CountNetMessage() then self:SetInfo("Went beyond the allowance") return end - end - net.Start("pac_request_angle_reset_on_entity") - net.WriteAngle(Angle(0,0,0)) - net.WriteFloat(self.RestoreDelay) - net.WriteEntity(reset_ent) - net.WriteEntity(self:GetPlayerOwner()) - net.SendToServer() - end - if self.Players and reset_ent:IsPlayer() then - reset_ent:DisableMatrix("RenderMultiply") + timer.Simple(math.min(self.RestoreDelay, 5), function() + if pac.LocalPlayer == self:GetPlayerOwner() then + if not convar_combat_enforce_netrate:GetBool() and not pac.CountNetMessage() then + self:SetInfo("Went beyond the allowance") + return end - end) - end + + net.Start("pac_request_angle_reset_on_entity") + net.WriteAngle(angle_zero) + net.WriteFloat(self.RestoreDelay) + net.WriteEntity(self.target_ent) + net.WriteEntity(self:GetPlayerOwner()) + net.SendToServer() + end + if self.Players and self.target_ent:IsPlayer() then + self.target_ent:DisableMatrix("RenderMultiply") + end + end) end function PART:OnRemove() end function PART:DecideTarget() + local radius_sqr = math.Clamp(self.Radius, 0, convar_lock_max_grab_radius:GetInt()) + radius_sqr = radius_sqr * radius_sqr - local RADIUS = math.Clamp(self.Radius,0,GetConVar("pac_sv_lock_max_grab_radius"):GetInt()) local ents_candidates = {} local chosen_ent = nil local target_part = self.TargetPart local origin - if self.TargetPart and (self.TargetPart):IsValid() then - origin = (self.TargetPart):GetWorldPosition() + if target_part and target_part:IsValid() then + origin = target_part:GetWorldPosition() else origin = self:GetWorldPosition() end - origin:Add(Vector(0,0,-self.OffsetDownAmount)) - for i, ent_candidate in ipairs(ents.GetAll()) do + origin:Add(Vector(0, 0, -self.OffsetDownAmount)) + + local root_owner = self:GetRootPart():GetOwner() + local player_owner = self:GetPlayerOwner() + for i, ent_candidate in ents.Iterator() do if IsValid(ent_candidate) then local check_further = true if ent_candidate.pac_recently_broken_free_from_lock then if ent_candidate.pac_recently_broken_free_from_lock + 10 > CurTime() then check_further = false end - else check_further = true end + else + check_further = true + end if check_further then - if ent_candidate:GetPos():Distance( origin ) < RADIUS then + if ent_candidate:GetPos():DistToSqr(origin) < radius_sqr then if self.Players and ent_candidate:IsPlayer() then --we don't want to grab ourselves - if (ent_candidate ~= self:GetRootPart():GetOwner()) or (self.AffectPlayerOwner and ent_candidate == self:GetPlayerOwner()) then - if not (not self.AffectPlayerOwner and ent_candidate == self:GetPlayerOwner()) then + if ent_candidate ~= root_owner or (self.AffectPlayerOwner and ent_candidate == player_owner) then + if not (not self.AffectPlayerOwner and ent_candidate == player_owner) then chosen_ent = ent_candidate table.insert(ents_candidates, ent_candidate) end - elseif (self:GetPlayerOwner() ~= ent_candidate) then --if it's another player, good + elseif ent_candidate ~= player_owner then --if it's another player, good chosen_ent = ent_candidate table.insert(ents_candidates, ent_candidate) end - elseif self.PhysicsProps and (physics_point_ent_classes[ent_candidate:GetClass()] or string.find(ent_candidate:GetClass(),"item_") or string.find(ent_candidate:GetClass(),"ammo_")) then + elseif self.PhysicsProps and (physics_point_ent_classes[ent_candidate:GetClass()] or string.find(ent_candidate:GetClass(), "item_") or string.find(ent_candidate:GetClass(), "ammo_")) then chosen_ent = ent_candidate table.insert(ents_candidates, ent_candidate) elseif self.NPC and (ent_candidate:IsNPC() or ent_candidate.IsDrGEntity or ent_candidate.IsVJBaseSNPC) then @@ -454,12 +486,16 @@ function PART:DecideTarget() end end end - local closest_distance = math.huge + + local worldpos = self:GetWorldPosition() --sort for the closest - for i,ent_candidate in ipairs(ents_candidates) do - local test_distance = (ent_candidate:GetPos()):Distance( self:GetWorldPosition()) - if (test_distance < closest_distance) then + local closest_distance = math.huge + + for i, ent_candidate in ipairs(ents_candidates) do + local test_distance = ent_candidate:GetPos():DistToSqr(worldpos) + + if test_distance < closest_distance then closest_distance = test_distance chosen_ent = ent_candidate end @@ -467,20 +503,18 @@ function PART:DecideTarget() if chosen_ent ~= nil then self.target_ent = chosen_ent - if pac.LocalPlayer == self:GetPlayerOwner() then - print("selected ", chosen_ent, "dist ", (chosen_ent:GetPos()):Distance( self:GetWorldPosition() )) - end self.valid_ent = true + + if pac.LocalPlayer == player_owner then + print("selected ", chosen_ent) + end else self.target_ent = nil self.valid_ent = false end end - - function PART:CheckEntValidity() - if self.target_ent == nil then self.valid_ent = false elseif self.target_ent:EntIndex() == 0 then @@ -488,15 +522,21 @@ function PART:CheckEntValidity() elseif IsValid(self.target_ent) then self.valid_ent = true end - if self.target_ent ~= nil then - if self.target_ent.IsGrabbedID and self.target_ent.IsGrabbedID ~= self.UniqueID then self.valid_ent = false end + + if self.target_ent ~= nil and self.target_ent.IsGrabbedID and self.target_ent.IsGrabbedID ~= self.UniqueID then + self.valid_ent = false end + if not self.valid_ent then self.target_ent = nil end --print("ent check:",self.valid_ent) end function PART:CalculateRelativeOffset() - if self.target_ent == nil or not IsValid(self.target_ent) then self.relative_transform_matrix = Matrix() return end + if not IsValid(self.target_ent) then + self.relative_transform_matrix = Matrix() + return + end + self.relative_transform_matrix = Matrix() self.relative_transform_matrix:Rotate(self.target_ent:GetAngles() - self:GetWorldAngles()) self.relative_transform_matrix:Translate(self.target_ent:GetPos() - self:GetWorldPosition()) @@ -504,23 +544,27 @@ function PART:CalculateRelativeOffset() end function PART:Initialize() - self.default_ang = Angle(0,0,0) - if not GetConVar('pac_sv_lock_grab'):GetBool() then - if not GetConVar('pac_sv_lock_teleport'):GetBool() then + self.default_ang = Angle(0, 0, 0) + + if not convar_lock_grab:GetBool() then + if not convar_lock_teleport:GetBool() then self:SetWarning("lock part grabs and teleports are disabled on this server!") else self:SetWarning("lock part grabs are disabled on this server!") end end - if not GetConVar('pac_sv_lock_teleport'):GetBool() then - if not GetConVar('pac_sv_lock_grab'):GetBool() then + + if not convar_lock_teleport:GetBool() then + if not convar_lock_grab:GetBool() then self:SetWarning("lock part grabs and teleports are disabled on this server!") else self:SetWarning("lock part teleports are disabled on this server!") end end - if not GetConVar('pac_sv_lock'):GetBool() then self:SetError("lock parts are disabled on this server!") end -end + if not convar_lock:GetBool() then + self:SetError("lock parts are disabled on this server!") + end +end BUILDER:Register() diff --git a/lua/pac3/core/client/parts/material.lua b/lua/pac3/core/client/parts/material.lua index 0d49d2a02..610f0ba5e 100644 --- a/lua/pac3/core/client/parts/material.lua +++ b/lua/pac3/core/client/parts/material.lua @@ -1,3 +1,7 @@ +local table_insert = table.insert +local table_remove = table.remove +local table_sort = table.sort + local shader_params = include("pac3/libraries/shader_params.lua") local mat_hdr_level = GetConVar("mat_hdr_level") @@ -58,7 +62,6 @@ local function TableToFlags(flags, valid_flags) end local function FlagsToTable(flags, valid_flags) - if not flags then return valid_flags.default_valid_flag end local out = {} @@ -104,7 +107,7 @@ for shader_name, groups in pairs(shader_params.shaders) do if shader_name == "vertexlitgeneric" then PART.FriendlyName = "material" - PART.Group = {'modifiers', 'model', 'entity'} + PART.Group = {"modifiers", "model", "entity"} else PART.FriendlyName = "material " .. shader_name PART.Group = "advanced" @@ -118,6 +121,7 @@ for shader_name, groups in pairs(shader_params.shaders) do -- move this to tools or something BUILDER:GetSet("LoadVmt", "", {editor_panel = "material"}) + function PART:SetLoadVmt(path) if not path or path == "" then return end @@ -128,7 +132,6 @@ for shader_name, groups in pairs(shader_params.shaders) do local vmt = util.KeyValuesToTable(str) local shader = str:match("^(.-)%{"):gsub("%p", ""):Trim() - for k,v in pairs(self:GetVars()) do local param = PART.ShaderParams[k] if param and param.default ~= nil then @@ -181,14 +184,13 @@ for shader_name, groups in pairs(shader_params.shaders) do end BUILDER:GetSet("MaterialOverride", "all", {enums = function(self, str) - local materials = {} if pace.current_part:GetOwner():IsValid() then materials = pace.current_part:GetOwner():GetMaterials() end - table.insert(materials, "all") + table_insert(materials, "all") local tbl = {} @@ -205,10 +207,14 @@ for shader_name, groups in pairs(shader_params.shaders) do if not IsValid(self) and not remove then return end local name = self:GetName() - for _, part in ipairs(self:GetRootPart():GetChildrenList()) do + local children = self:GetRootPart():GetChildrenList() + for i = 1, #children do + local part = children[i] + if part.GetMaterials then - for _, path in ipairs(part.Materials:Split(";")) do - if path == name then + local materials = part.Materials:Split(";") + for x = 1, #materials do + if materials[x] == name then part:SetMaterials(part.Materials) break end @@ -225,7 +231,10 @@ for shader_name, groups in pairs(shader_params.shaders) do if tonumber(str) then num = tonumber(str) elseif str ~= "all" and parent:GetOwner():IsValid() then - for i, v in ipairs(parent:GetOwner():GetMaterials()) do + local materials = parent:GetOwner():GetMaterials() + for i = 1, #materials do + local v = materials[i] + if (v:match(".+/(.+)") or v):lower() == str:lower() then num = i break @@ -239,14 +248,14 @@ for shader_name, groups in pairs(shader_params.shaders) do for _, stack in pairs(parent.material_override) do for i, v in ipairs(stack) do if v == self then - table.remove(stack, i) + table_remove(stack, i) break end end end if not remove then - table.insert(parent.material_override[num], self) + table_insert(parent.material_override[num], self) end end @@ -258,7 +267,6 @@ for shader_name, groups in pairs(shader_params.shaders) do self.rotation_angle = Angle(0, 0, 0) end - function PART:GetNiceName() local path = "" @@ -290,8 +298,9 @@ for shader_name, groups in pairs(shader_params.shaders) do end function PART:OnThink() - if self:GetOwner():IsValid() then - local materials = self:GetOwner():GetMaterials() + local owner = self:GetOwner() + if owner:IsValid() then + local materials = owner:GetMaterials() if materials and #materials ~= self.last_material_count then update_submaterial(self) self.last_material_count = #materials @@ -302,23 +311,27 @@ for shader_name, groups in pairs(shader_params.shaders) do PART.ShaderParams = {} PART.TransformVars = {} + local vector_one = Vector(1, 1, 1) + local sorted_groups = {} for k, v in pairs(groups) do - table.insert(sorted_groups, {k = k, v = v}) + table_insert(sorted_groups, {k = k, v = v}) end - table.sort(sorted_groups, function(a, b) return a.k:lower() < b.k:lower() end) + table_sort(sorted_groups, function(a, b) return a.k:lower() < b.k:lower() end) - for _, v in ipairs(sorted_groups) do - local group, params = v.k, v.v + for i = 1, #sorted_groups do + local g = sorted_groups[i] + local group, params = g.k, g.v local sorted_params = {} for k, v in pairs(params) do - table.insert(sorted_params, {k = k, v = v}) + table_insert(sorted_params, {k = k, v = v}) end - table.sort(sorted_params, function(a, b) return a.k:lower() < b.k:lower() end) + table_sort(sorted_params, function(a, b) return a.k:lower() < b.k:lower() end) - for _, v in ipairs(sorted_params) do - local key, info = v.k, v.v + for x = 1, #sorted_params do + local p = sorted_params[x] + local key, info = p.k, p.v PART.ShaderParams[key] = info @@ -330,9 +343,9 @@ for shader_name, groups in pairs(shader_params.shaders) do if info.default == nil then if info.type == "vec3" then - info.default = Vector(0,0,0) + info.default = Vector(0, 0, 0) elseif info.type == "color" then - info.default = Vector(1,1,1) + info.default = Vector(1, 1, 1) elseif info.type == "float" then info.default = 0 elseif info.type == "vec2" then @@ -379,7 +392,6 @@ for shader_name, groups in pairs(shader_params.shaders) do PART["Set" .. position_key] = function(self, vec) self[position_key] = vec - self.translation_vector.x = self[position_key].x self.translation_vector.y = self[position_key].y @@ -398,7 +410,7 @@ for shader_name, groups in pairs(shader_params.shaders) do PART["Set" .. angle_key] = function(self, num) self[angle_key] = num - self.rotation_angle.y = self[angle_key]*360 + self.rotation_angle.y = self[angle_key] * 360 setup_matrix(self) @@ -442,8 +454,9 @@ for shader_name, groups in pairs(shader_params.shaders) do self[property_name] = val if val == "" or info.partial_hdr and mat_hdr_level:GetInt() > 0 and self[getnohdr](self) then - self:GetRawMaterial():SetUndefined(key) - self:GetRawMaterial():Recompute() + local mat = self:GetRawMaterial() + mat:SetUndefined(key) + mat:Recompute() else if not pac.resource.DownloadTexture(val, function(tex, frames) if frames then @@ -479,8 +492,10 @@ for shader_name, groups in pairs(shader_params.shaders) do if isnumber(info.default) then PART["Set" .. property_name] = function(self, val) self[property_name] = val + local mat = self:GetRawMaterial() mat:SetFloat(key, val) + if info.recompute then mat:Recompute() end @@ -511,47 +526,62 @@ for shader_name, groups in pairs(shader_params.shaders) do else PART["Set" .. property_name] = function(self, val) if isvector(val) then - val = (val == Vector(1,1,1)) and true or false + val = val == vector_one end self[property_name] = val - local mat = self:GetRawMaterial() + local mat = self:GetRawMaterial() mat:SetInt(key, val and 1 or 0) - if info.recompute then mat:Recompute() end + + if info.recompute then + mat:Recompute() + end end end elseif isvector(info.default) or info.type == "vec3" or info.type == "vec2" then PART["Set" .. property_name] = function(self, val) - if isstring(val) then val = Vector() end + if isstring(val) then + val = Vector() + end + self[property_name] = val + local mat = self:GetRawMaterial() mat:SetVector(key, val) - if info.recompute then mat:Recompute() end + + if info.recompute then + mat:Recompute() + end end elseif info.type == "vec4" then -- need vec4 type PART["Set" .. property_name] = function(self, val) + local x, y, z, w - local x,y,z,w if isstring(val) then - x,y,z,w = unpack(val:Split(" ")) + x, y, z, w = unpack(val:Split(" ")) x = tonumber(x) or 0 y = tonumber(y) or 0 z = tonumber(z) or 0 w = tonumber(w) or 0 elseif isvector(val) then - x,y,z = val.x, val.y, val.z + x, y, z = val.x, val.y, val.z w = 0 else x, y, z, w = 0, 0, 0, 0 end - self[property_name] = ("%f %f %f %f"):format(x, y, z, w) + local vec4_str = ("%f %f %f %f"):format(x, y, z, w) + + self[property_name] = vec4_str + local mat = self:GetRawMaterial() - mat:SetString(key, ("[%f %f %f %f]"):format(x,y,z,w)) + mat:SetString(key, vec4_str) - if info.recompute then mat:Recompute() end + if info.recompute then + mat:Recompute() + end end end end @@ -563,6 +593,7 @@ for shader_name, groups in pairs(shader_params.shaders) do function PART:GetRawMaterial() if not self.Materialm then self.material_name = tostring({}) + local mat = pac.CreateMaterial(self.material_name, shader_name, {}) self.Materialm = mat @@ -572,6 +603,7 @@ for shader_name, groups in pairs(shader_params.shaders) do end end end + return self.Materialm end diff --git a/lua/pac3/core/client/parts/model.lua b/lua/pac3/core/client/parts/model.lua index 420a73c7f..6fa2ddc1a 100644 --- a/lua/pac3/core/client/parts/model.lua +++ b/lua/pac3/core/client/parts/model.lua @@ -1,20 +1,12 @@ -CreateConVar( "pac_model_max_scales", "10000", FCVAR_ARCHIVE, "Maximum scales model can have") - - - - local pac = pac -local cam = cam -local cam_PopModelMatrix = cam.PopModelMatrix -local cam_PushModelMatrix = cam.PushModelMatrix -local Color = Color local EF_BONEMERGE = EF_BONEMERGE local MATERIAL_CULLMODE_CCW = MATERIAL_CULLMODE_CCW local MATERIAL_CULLMODE_CW = MATERIAL_CULLMODE_CW -local Matrix = Matrix -local NULL = NULL -local render = render +local cam = cam +local surface = surface +local cam_PopModelMatrix = cam.PopModelMatrix +local cam_PushModelMatrix = cam.PushModelMatrix local render_CullMode = render.CullMode local render_MaterialOverride = render.ModelMaterialOverride local render_MaterialOverrideByIndex = render.MaterialOverrideByIndex @@ -22,9 +14,19 @@ local render_RenderFlashlights = render.RenderFlashlights local render_SetBlend = render.SetBlend local render_SetColorModulation = render.SetColorModulation local render_SuppressEngineLighting = render.SuppressEngineLighting -local surface = surface +local math_abs = math.abs +local math_Clamp = math.Clamp +local Color = Color local Vector = Vector +local Matrix = Matrix +local ProtectedCall = ProtectedCall local vector_origin = vector_origin +local NULL = NULL + +local entMeta = FindMetaTable("Entity") +local IsEntValid = entMeta.IsValid +local IsPlayer = entMeta.IsPlayer +local GetBoneCount = entMeta.GetBoneCount local BUILDER, PART = pac.PartTemplate("base_drawable") @@ -62,12 +64,14 @@ BUILDER:StartStorableVars() :GetSet("ModelModifiers", "", {hidden = true}) :GetSet("Material", "", {editor_panel = "material"}) :GetSet("Materials", "", {hidden = true}) - :GetSet("Skin", 0, {editor_onchange = function(self, num) return math.Round(math.Clamp(tonumber(num), 0, pace.current_part:GetOwner():SkinCount())) end}) + :GetSet("Skin", 0, {editor_onchange = function(self, num) return math.Round(math_Clamp(tonumber(num), 0, pace.current_part:GetOwner():SkinCount())) end}) :GetSet("LevelOfDetail", 0, {editor_clamp = {-1, 8}, editor_round = true}) :GetSetPart("EyeTarget") :EndStorableVars() +local model_max_scales = CreateConVar("pac_model_max_scales", "10000", FCVAR_ARCHIVE, "Maximum scales model can have") + PART.Owner = NULL function PART:GetNiceName() @@ -78,7 +82,7 @@ end function PART:GetDynamicProperties() local ent = self:GetOwner() - if not ent:IsValid() or not ent:GetBodyGroups() then return end + if not IsEntValid(ent) or not ent:GetBodyGroups() then return end local tbl = {} @@ -93,7 +97,7 @@ function PART:GetDynamicProperties() get = function() return self:ModelModifiersToTable(self:GetModelModifiers()).skin end, - udata = {editor_onchange = function(self, num) return math.Clamp(math.Round(num), 0, ent:SkinCount() - 1) end}, + udata = {editor_onchange = function(self, num) return math_Clamp(math.Round(num), 0, ent:SkinCount() - 1) end}, } end @@ -109,13 +113,15 @@ function PART:GetDynamicProperties() get = function() return self:ModelModifiersToTable(self:GetModelModifiers())[info.name] or 0 end, - udata = {editor_onchange = function(self, num) return math.Clamp(math.Round(num), 0, info.num - 1) end, group = "bodygroups"}, + udata = {editor_onchange = function(self, num) return math_Clamp(math.Round(num), 0, info.num - 1) end, group = "bodygroups"}, } end end - if ent:GetMaterials() and #ent:GetMaterials() > 1 then - for i, name in ipairs(ent:GetMaterials()) do + local materials = ent:GetMaterials() + + if materials[2] then -- more than 1 + for i, name in ipairs(materials) do name = name:match(".+/(.+)") or name tbl[name] = { key = name, @@ -127,7 +133,7 @@ function PART:GetDynamicProperties() local tbl = self.Materials:Split(";") tbl[i] = val - for i, name in ipairs(ent:GetMaterials()) do + for i, name in ipairs(materials) do tbl[i] = tbl[i] or "" end @@ -143,18 +149,21 @@ end function PART:SetLevelOfDetail(val) self.LevelOfDetail = val + local ent = self:GetOwner() - if ent:IsValid() then + + if IsEntValid(ent) then ent:SetLOD(val) end end -function PART:SetSkin(var) - self.Skin = var - local owner = self:GetOwner() +function PART:SetSkin(val) + self.Skin = val - if owner:IsValid() then - owner:SetSkin(var) + local ent = self:GetOwner() + + if IsEntValid(ent) then + ent:SetSkin(val) end end @@ -177,17 +186,19 @@ end function PART:ModelModifiersToString(tbl) local str = "" + for k, v in pairs(tbl) do str = str .. k .. "=" .. v .. ";" end + return str end function PART:SetModelModifiers(str) self.ModelModifiers = str - local owner = self:GetOwner() + local ent = self:GetOwner() - if not owner:IsValid() then return end + if not IsEntValid(ent) then return end local tbl = self:ModelModifiersToTable(str) @@ -196,12 +207,13 @@ function PART:SetModelModifiers(str) tbl.skin = nil end - if not owner:GetBodyGroups() then return end - self.draw_bodygroups = {} - for i, info in ipairs(owner:GetBodyGroups()) do + local bodygroups = ent:GetBodyGroups() + for i = 1, #bodygroups do + local info = bodygroups[i] local val = tbl[info.name] + if val then table.insert(self.draw_bodygroups, {info.id, val}) end @@ -234,7 +246,9 @@ end function PART:SetMaterials(str) self.Materials = str - local materials = self:GetOwner():IsValid() and self:GetOwner():GetMaterials() + local ent = self:GetOwner() + + local materials = IsEntValid(ent) and ent:GetMaterials() if not materials then return end @@ -266,17 +280,20 @@ end function PART:Reset() self:Initialize() + for _, key in pairs(self:GetStorableVars()) do if PART[key] then self["Set" .. key](self, self["Get" .. key](self)) end end + self.cached_dynamic_props = nil end function PART:OnBecomePhysics() local ent = self:GetOwner() - if not ent:IsValid() then return end + if not IsEntValid(ent) then return end + ent:PhysicsInit(SOLID_NONE) ent:SetMoveType(MOVETYPE_NONE) ent:SetNoDraw(true) @@ -293,10 +310,10 @@ function PART:Initialize() end function PART:OnShow() - local owner = self:GetParentOwner() local ent = self:GetOwner() + local owner = self:GetParentOwner() - if ent:IsValid() and owner:IsValid() and owner ~= ent then + if IsEntValid(ent) and IsEntValid(owner) and owner ~= ent then ent:SetPos(owner:EyePos()) ent:SetLegacyTransform(self.LegacyTransform) self:SetBone(self:GetBone()) @@ -327,9 +344,9 @@ function PART:BindMaterials(ent) local mat = materials[i] if mat then - render_MaterialOverrideByIndex(i-1, mat) + render_MaterialOverrideByIndex(i - 1, mat) else - render_MaterialOverrideByIndex(i-1, nil) + render_MaterialOverrideByIndex(i - 1, nil) end end elseif self.material_override then @@ -344,9 +361,9 @@ function PART:BindMaterials(ent) local mat = stack[1] if mat then - render_MaterialOverrideByIndex(i-1, mat:GetRawMaterial()) + render_MaterialOverrideByIndex(i - 1, mat:GetRawMaterial()) else - render_MaterialOverrideByIndex(i-1, nil) + render_MaterialOverrideByIndex(i - 1, nil) end end end @@ -360,7 +377,7 @@ function PART:BindMaterials(ent) end function PART:PreEntityDraw(ent, pos, ang) - if not ent:IsPlayer() and pos and ang then + if not IsPlayer(ent) and pos and ang then if not self.skip_orient then ent:SetPos(pos) ent:SetAngles(ang) @@ -374,7 +391,8 @@ function PART:PreEntityDraw(ent, pos, ang) local brightness = self.Brightness -- render.SetColorModulation and render.SetAlpha set the material $color and $alpha. - render_SetColorModulation(r*brightness, g*brightness, b*brightness) + render_SetColorModulation(r * brightness, g * brightness, b * brightness) + if not pac.drawing_motionblur_alpha then render_SetBlend(self.Alpha) end @@ -412,7 +430,7 @@ end function PART:OnDraw() local ent = self:GetOwner() - if not ent:IsValid() then + if not IsEntValid(ent) then self:Reset() ent = self:GetOwner() end @@ -424,7 +442,6 @@ function PART:OnDraw() return end - self:PreEntityDraw(ent, pos, ang) self:DrawModel(ent, pos, ang) self:PostEntityDraw(ent, pos, ang) @@ -465,10 +482,11 @@ end function PART:DrawModel(ent, pos, ang) if self.loading then self:DrawLoadingText(ent, pos) + + if not self.obj_mesh then return end end if self.Alpha == 0 or self.Size == 0 then return end - if self.loading and not self.obj_mesh then return end if self.NoCulling or self.Invert then render_CullMode(MATERIAL_CULLMODE_CW) @@ -543,7 +561,7 @@ function PART:RefreshModel() local ent = self:GetOwner() - if ent:IsValid() then + if IsEntValid(ent) then pac.ResetBoneCache(ent) end @@ -600,7 +618,8 @@ end function PART:ProcessModelChange() local owner = self:GetOwner() - if not owner:IsValid() then return end + if not IsEntValid(owner) then return end + local path = self.Model if path:find("://", nil, true) then @@ -610,7 +629,6 @@ function PART:ProcessModelChange() pac.urlobj.GetObjFromURL(path, false, false, function(meshes, err) - local function set_mesh(part, mesh) local owner = part:GetOwner() part.obj_mesh = mesh @@ -714,28 +732,29 @@ function PART:SetModel(path) self.Model = path local owner = self:GetOwner() - if not owner:IsValid() then return end + if not IsEntValid(owner) then return end self.old_model = path self:ProcessModelChange() end -local NORMAL = Vector(1, 1, 1) +local vec_one = Vector(1, 1, 1) function PART:CheckScale() - local owner = self:GetOwner() - if not owner:IsValid() then return end - -- RenderMultiply doesn't work with this.. - if self.BoneMerge and owner:GetBoneCount() and owner:GetBoneCount() > 1 then - if self.Scale * self.Size ~= NORMAL then - if not self.requires_bone_model_scale then - self.requires_bone_model_scale = true + if self.BoneMerge then + local owner = self:GetOwner() + + if IsEntValid(owner) and GetBoneCount(owner) > 1 then + if self.Scale * self.Size ~= vec_one then + if not self.requires_bone_model_scale then + self.requires_bone_model_scale = true + end + return true end - return true - end - self.requires_bone_model_scale = false + self.requires_bone_model_scale = false + end end end @@ -745,16 +764,24 @@ function PART:SetAlternativeScaling(b) end function PART:SetScale(vec) - local max_scale = GetConVar("pac_model_max_scales"):GetFloat() - local largest_scale = math.max(math.abs(vec.x), math.abs(vec.y), math.abs(vec.z)) + local max_scale = model_max_scales:GetFloat() + local largest_scale = math.max(math_abs(vec.x), math_abs(vec.y), math_abs(vec.z)) - if vec and max_scale > 0 and (LocalPlayer() ~= self:GetPlayerOwner()) then --clamp for other players if they have pac_model_max_scales convar more than 0 - vec = Vector(math.Clamp(vec.x, -max_scale, max_scale), math.Clamp(vec.y, -max_scale, max_scale), math.Clamp(vec.z, -max_scale, max_scale)) + if vec and max_scale > 0 and pac.LocalPlayer ~= self:GetPlayerOwner() then --clamp for other players if they have pac_model_max_scales convar more than 0 + vec = Vector(math_Clamp(vec.x, -max_scale, max_scale), math_Clamp(vec.y, -max_scale, max_scale), math_Clamp(vec.z, -max_scale, max_scale)) end - if largest_scale > 10000 then --warn about the default max scale + + if largest_scale > 10000 then + --warn about the default max scale self:SetError("Scale is being limited due to having an excessive component. Default maximum values are 10000") - else self:SetError() end --if ok, clear the warning - vec = vec or Vector(1, 1, 1) + else + --if ok, clear the warning + self:SetError() + end + + if not vec then + vec = Vector(1, 1, 1) + end self.Scale = vec @@ -763,11 +790,9 @@ function PART:SetScale(vec) end end -local vec_one = Vector(1, 1, 1) - function PART:ApplyMatrix() local ent = self:GetOwner() - if not ent:IsValid() then return end + if not IsEntValid(ent) then return end local mat = Matrix() @@ -776,7 +801,7 @@ function PART:ApplyMatrix() mat:Rotate(self.Angles + self.AngleOffset) end - if ent:IsPlayer() or ent:IsNPC() then + if IsPlayer(ent) or ent:IsNPC() then pac.emut.MutateEntity(self:GetPlayerOwner(), "size", ent, self.Size, { StandingHullHeight = self.StandingHullHeight, CrouchingHullHeight = self.CrouchingHullHeight, @@ -820,13 +845,16 @@ function PART:SetSize(var) end function PART:CheckBoneMerge() - local ent = self:GetOwner() - - if ent == pac.LocalHands or ent == pac.LocalViewModel then return end - if self.skip_orient then return end - if ent:IsValid() and not ent:IsPlayer() and ent:GetModel() then + local ent = self:GetOwner() + + if ent ~= pac.LocalViewModel + and ent ~= pac.LocalHands + and IsEntValid(ent) + and not IsPlayer(ent) + and ent:GetModel() + then if self.BoneMerge then local owner = self:GetParentOwner() @@ -835,8 +863,10 @@ function PART:CheckBoneMerge() if not ent:IsEffectActive(EF_BONEMERGE) then ent:AddEffects(EF_BONEMERGE) + owner.pac_bonemerged = owner.pac_bonemerged or {} table.insert(owner.pac_bonemerged, ent) + ent.RenderOverride = function() ent.pac_drawing_model = true ent:DrawModel() @@ -845,21 +875,21 @@ function PART:CheckBoneMerge() end end else - if ent:GetParent():IsValid() then - local owner = ent:GetParent() + local owner = ent:GetParent() + + if IsEntValid(owner) then ent:SetParent(NULL) if ent:IsEffectActive(EF_BONEMERGE) then ent:RemoveEffects(EF_BONEMERGE) ent.RenderOverride = nil - if owner:IsValid() then - owner.pac_bonemerged = owner.pac_bonemerged or {} - for i, v in ipairs(owner.pac_bonemerged) do - if v == ent then - table.remove(owner.pac_bonemerged, i) - break - end + owner.pac_bonemerged = owner.pac_bonemerged or {} + + for i = 1, #owner.pac_bonemerged do + if owner.pac_bonemerged[i] == ent then + table.remove(owner.pac_bonemerged, i) + break end end end @@ -871,21 +901,23 @@ function PART:CheckBoneMerge() end function PART:OnBuildBonePositions() - if self.AlternativeScaling then return end - - local ent = self:GetOwner() - local owner = self:GetParentOwner() - - if not ent:IsValid() or not owner:IsValid() or not ent:GetBoneCount() or ent:GetBoneCount() < 1 then return end + if not self.AlternativeScaling and self.requires_bone_model_scale then + local ent = self:GetOwner() + + if not IsEntValid(ent) + or GetBoneCount(ent) < 1 + or not IsEntValid(self:GetParentOwner()) + then + return + end - if self.requires_bone_model_scale then local scale = self.Scale * self.Size - for i = 0, ent:GetBoneCount() - 1 do + for i = 0, GetBoneCount(ent) - 1 do if i == 0 then ent:ManipulateBoneScale(i, ent:GetManipulateBoneScale(i) * Vector(scale.x ^ 0.25, scale.y ^ 0.25, scale.z ^ 0.25)) else - ent:ManipulateBonePosition(i, ent:GetManipulateBonePosition(i) + Vector((scale.x-1) ^ 4, 0, 0)) + ent:ManipulateBonePosition(i, ent:GetManipulateBonePosition(i) + Vector((scale.x - 1) ^ 4, 0, 0)) ent:ManipulateBoneScale(i, ent:GetManipulateBoneScale(i) * scale) end end diff --git a/lua/pac3/core/client/parts/physics.lua b/lua/pac3/core/client/parts/physics.lua index d6562de06..442b2f8ed 100644 --- a/lua/pac3/core/client/parts/physics.lua +++ b/lua/pac3/core/client/parts/physics.lua @@ -1,6 +1,11 @@ +local RealFrameTime = RealFrameTime +local Mesh = Mesh +local Matrix = Matrix + local physprop_enums = {} local physprop_indices = {} -for i=0,500,1 do + +for i = 0, 500, 1 do local name = util.GetSurfacePropName(i) if name ~= "" then physprop_enums[name] = name @@ -8,15 +13,13 @@ for i=0,500,1 do end end - - local BUILDER, PART = pac.PartTemplate("base") PART.ThinkTime = 0 PART.ClassName = "physics" -PART.Group = 'model' -PART.Icon = 'icon16/shape_handles.png' +PART.Group = "model" +PART.Icon = "icon16/shape_handles.png" BUILDER:StartStorableVars() @@ -38,9 +41,9 @@ BUILDER:StartStorableVars() :GetSet("MaxSpeedDamp", 1000) :GetSet("MaxAngularDamp", 1000) :GetSet("DampFactor", 1) - BUILDER:SetPropertyGroup("Speeds") - :GetSet("ConstantVelocity", Vector(0,0,0)) + BUILDER:SetPropertyGroup("Speeds") + :GetSet("ConstantVelocity", Vector(0, 0, 0)) BUILDER:SetPropertyGroup("Shape") :GetSet("BoxScale",Vector(1,1,1)) @@ -52,11 +55,10 @@ BUILDER:StartStorableVars() BUILDER:SetPropertyGroup("InitialVelocity") :GetSet("AddOwnerSpeed", false) - :GetSet("InitialVelocityVector", Vector(0,0,0)) + :GetSet("InitialVelocityVector", Vector(0, 0, 0)) :GetSetPart("InitialVelocityPart") :GetSet("OverrideInitialPosition", false, {description = "Whether the initial velocity part should be used as an initial position, otherwise it'll just be for the initial velocity's angle"}) - BUILDER:EndStorableVars() local function IsInvalidParent(self) @@ -86,6 +88,8 @@ function PART:SetMass(n) end end +local mat_wireframe + function PART:MeshDraw() if not IsValid(self.phys) then return end @@ -93,15 +97,21 @@ function PART:MeshDraw() local drawmesh = Mesh() if mesh == nil or not self.Box then - render.DrawWireframeSphere( self.phys:GetPos(), self.Radius, 10, 10, Color( 255, 255, 255 ) ) + render.DrawWireframeSphere(self.phys:GetPos(), self.Radius, 10, 10, color_white) else drawmesh:BuildFromTriangles(mesh) - render.SetMaterial( Material( "models/wireframe" ) ) + if not mat_wireframe then + mat_wireframe = Material("models/wireframe") + end + + render.SetMaterial(mat_wireframe) + local mat = Matrix() mat:Translate(self.phys:GetPos()) mat:Rotate(self.phys:GetAngles()) - cam.PushModelMatrix( mat ) + + cam.PushModelMatrix(mat) drawmesh:Draw() cam.PopModelMatrix() end @@ -109,6 +119,7 @@ end function PART:SetPreview(b) self.Preview = b + if self.Preview then hook.Add("PostDrawTranslucentRenderables", "pac_physics_preview"..self.UniqueID, function() self:MeshDraw() @@ -181,7 +192,6 @@ end local params = {} function PART:OnThink() - if self.Parent.GetWorldPosition then if self.disabled then self:Enable() @@ -192,7 +202,6 @@ function PART:OnThink() end end - local phys = self.phys if phys:IsValid() then @@ -216,7 +225,7 @@ function PART:OnThink() end -- this is nicer i think - if self.ConstrainSphere ~= 0 and phys:GetPos():Distance(self.Parent:GetWorldPosition()) > self.ConstrainSphere then + if self.ConstrainSphere ~= 0 and phys:GetPos():DistToSqr(self.Parent:GetWorldPosition()) > (self.ConstrainSphere ^ 2) then if not self.PushFollow then phys:SetPos(self.Parent:GetWorldPosition() + (self.Parent:GetWorldPosition() - phys:GetPos()):GetNormalized() * -self.ConstrainSphere) --new push mode @@ -224,16 +233,16 @@ function PART:OnThink() local vec = (self.Parent:GetWorldPosition() - phys:GetPos()) local current_dist = vec:Length() local extra_dist = current_dist - self.ConstrainSphere - phys:AddVelocity(0.5 * vec:GetNormalized() * extra_dist / math.Clamp(self.SecondsToArrive,0.05,10)) + phys:AddVelocity(0.5 * vec:GetNormalized() * extra_dist / math.Clamp(self.SecondsToArrive, 0.05, 10)) end end else if self.ConstrainSphere ~= 0 then local offset = self.Parent:GetWorldPosition() - phys:GetPos() - if offset:Length() > self.ConstrainSphere then + if offset:LengthSqr() > (self.ConstrainSphere * self.ConstrainSphere) then phys:SetPos(self.Parent:GetWorldPosition() - offset:GetNormalized() * self.ConstrainSphere) - phys:SetVelocity(Vector()) + phys:SetVelocity(vector_origin) end end end @@ -257,18 +266,27 @@ function PART:OnHide() timer.Simple(0.4, function() self:GetRootPart():OnShow() self.Parent:OnShow() - for _,part in pairs(self:GetParent():GetChildrenList()) do - part:OnShow() + local siblings = self:GetParent():GetChildrenList() + for i = 1, #siblings do + siblings[i]:OnShow() end end) return end + timer.Simple(0, function() self:Disable() end) - hook.Remove("PostDrawTranslucentRenderables", "pac_physics_preview"..self.UniqueID) + hook.Remove("PostDrawTranslucentRenderables", "pac_physics_preview" .. self.UniqueID) end +local valid_phys_pusher_list = { + ["prop_physics"] = true, + ["prop_physics_multiplayer"] = true, + ["prop_physics_respawnable"] = true, + ["prop_ragdoll"] = true +} + function PART:Enable() if IsInvalidParent(self) then return end @@ -310,36 +328,44 @@ function PART:Enable() self.phys:AddVelocity(self:GetRootPart():GetOwner():GetVelocity()) end - timer.Simple(self.ThinkDelay, function() hook.Add("Tick", "pac_phys_repulsionthink"..self.UniqueID, function() - if not IsValid(self.phys) then hook.Remove("Tick", "pac_phys_repulsionthink"..self.UniqueID) return end - self.phys:AddVelocity(self.ConstantVelocity * RealFrameTime()) - - if self.Pushable then - local pushvec = Vector(0,0,0) - local pos = self.phys:GetPos() - local ents_tbl = ents.FindInSphere(pos, self.Radius) - local valid_phys_pushers = 0 - for i,ent in pairs(ents_tbl) do - if ent.GetPhysicsObject or ent:IsPlayer() then - if ent:IsPlayer() or ent:GetClass() == "prop_physics" or ent:GetClass() == "prop_ragdoll" then + timer.Simple(self.ThinkDelay, function() + hook.Add("Tick", "pac_phys_repulsionthink" .. self.UniqueID, function() + if not IsValid(self.phys) then + hook.Remove("Tick", "pac_phys_repulsionthink" .. self.UniqueID) + return + end + + self.phys:AddVelocity(self.ConstantVelocity * RealFrameTime()) + + if self.Pushable then + local pushvec = Vector(0, 0, 0) + local pos = self.phys:GetPos() + local valid_phys_pushers = 0 + + local ents_tbl = ents.FindInSphere(pos, self.Radius) + for i = 1, #ents_tbl do + local ent = ents_tbl[i] + + if ent:IsPlayer() or (ent.GetPhysicsObject and valid_phys_pusher_list[ent:GetClass()]) then valid_phys_pushers = valid_phys_pushers + 1 pushvec = pushvec + (pos - ent:GetPos()):GetNormalized() * 20 end end - end - if valid_phys_pushers > 0 then self.phys:AddVelocity(pushvec / valid_phys_pushers) end - end - - end) end) + if valid_phys_pushers > 0 then + self.phys:AddVelocity(pushvec / valid_phys_pushers) + end + end + end) + end) end function PART:Disable() - hook.Remove("Tick", "pac_phys_repulsionthink"..self.UniqueID) + hook.Remove("Tick", "pac_phys_repulsionthink" .. self.UniqueID) + if IsInvalidParent(self) then return end local part = self:GetParent() - local ent = part:GetOwner() if ent:IsValid() then diff --git a/lua/pac3/core/client/parts/projected_texture.lua b/lua/pac3/core/client/parts/projected_texture.lua index dd5a78f65..238bb42d9 100644 --- a/lua/pac3/core/client/parts/projected_texture.lua +++ b/lua/pac3/core/client/parts/projected_texture.lua @@ -2,7 +2,7 @@ local BUILDER, PART = pac.PartTemplate("base_drawable") PART.ClassName = "projected_texture" PART.Group = "effects" -PART.Icon = 'icon16/lightbulb.png' +PART.Icon = "icon16/lightbulb.png" PART.ProperColorRange = true BUILDER:StartStorableVars() @@ -32,7 +32,7 @@ function PART:GetProjectedTexture() end function PART:GetNiceName() - local hue = pac.ColorToNames(self:GetColor()) + local hue = pac.VectorColorToNames(self:GetColor()) return hue .. " projected texture" end @@ -69,10 +69,9 @@ function PART:OnDraw() ptex:Update() end - function PART:SetColor(val) self.Color = val - self:GetProjectedTexture():SetColor(Color(val.x*255, val.y*255, val.z*255, 1)) + self:GetProjectedTexture():SetColor(Color(val.x * 255, val.y * 255, val.z * 255, 1)) end function PART:SetBrightness(val) @@ -95,7 +94,6 @@ function PART:SetHorizontalFOV(val) self:GetProjectedTexture():SetHorizontalFOV(val) end - function PART:SetFOV(val) self.FOV = val self:GetProjectedTexture():SetFOV(val) @@ -119,7 +117,7 @@ end function PART:SetTextureFrame(val) self.TextureFrame = val if self.vtf_frame_limit then - self:GetProjectedTexture():SetTextureFrame(math.abs(val)%self.vtf_frame_limit) + self:GetProjectedTexture():SetTextureFrame(math.abs(val) % self.vtf_frame_limit) else self:GetProjectedTexture():SetTextureFrame(math.abs(val)) end @@ -144,14 +142,17 @@ end function PART:OnHide() local tex = self:GetProjectedTexture() + tex:SetBrightness(0) tex:Update() + -- give it one frame to update timer.Simple(0, function() if tex:IsValid() then tex:Remove() end end) + self.ptex = nil end diff --git a/lua/pac3/core/client/parts/projectile.lua b/lua/pac3/core/client/parts/projectile.lua index 7d3cb704d..35e26e626 100644 --- a/lua/pac3/core/client/parts/projectile.lua +++ b/lua/pac3/core/client/parts/projectile.lua @@ -1,6 +1,6 @@ local physprop_enums = {} local physprop_indices = {} -for i=0,200,1 do +for i=0, 200, 1 do local name = util.GetSurfacePropName(i) if name ~= "" then physprop_enums[name] = name @@ -10,8 +10,6 @@ end language.Add("pac_projectile", "Projectile") - - local BUILDER, PART = pac.PartTemplate("base_movable") PART.ClassName = "projectile" @@ -123,6 +121,7 @@ function PART:OnShow(from_rendering) -- it should instead be using what pac considers to be the position --self:GetRootPart():CallRecursive("Draw", "opaque") local parents = self:GetParentList() + -- call draw from root to the current part only on direct parents to update the position hiearchy for i = #parents, 1, -1 do local part = parents[i] @@ -130,11 +129,15 @@ function PART:OnShow(from_rendering) part:Draw("opaque") end end + if self.NumberProjectiles <= 0 then self.NumberProjectiles = 0 end + if self.NumberProjectiles <= 50 then - local pos,ang = self:GetDrawPosition() - self:Shoot(pos,ang,self.NumberProjectiles) - else chat.AddText(Color(255,0,0),"[PAC3] Trying to spawn too many projectiles! The limit is " .. 50) end + local pos, ang = self:GetDrawPosition() + self:Shoot(pos, ang, self.NumberProjectiles) + else + chat.AddText(Color(255, 0, 0), "[PAC3] Trying to spawn too many projectiles! The limit is " .. 50) + end end end @@ -526,8 +529,8 @@ end]] do -- physical local Entity = Entity local projectiles = {} - pac.AddHook("Think", "pac_projectile", function() + pac.AddHook("Think", "pac_projectile", function() for key, data in pairs(projectiles) do if not data.ply:IsValid() then projectiles[key] = nil @@ -549,7 +552,7 @@ do -- physical end) net.Receive("pac_projectile_attach", function() - local ply = net.ReadEntity() + local ply = net.ReadPlayer() local ent_id = net.ReadInt(16) local partuid = net.ReadString() local surfprop = net.ReadString() @@ -564,6 +567,7 @@ do -- physical if ent.pac_projectile_part then local tbl = ent.pac_projectile_part:GetChildren() local partchild = tbl[next(tbl)] --ent.pac_projectile_part is the root group, but outfit part is the first child + if IsValid(partchild) then if partchild:IsHidden() then if ent.pac_projectile.RemoveOnHide and not ent.markedforremove then @@ -571,11 +575,9 @@ do -- physical net.Start("pac_projectile_remove") net.WriteInt(ent_id, 16) net.SendToServer() - end end end - end end end) diff --git a/lua/pac3/core/client/parts/proxy.lua b/lua/pac3/core/client/parts/proxy.lua index e51e7746f..a57aa6878 100644 --- a/lua/pac3/core/client/parts/proxy.lua +++ b/lua/pac3/core/client/parts/proxy.lua @@ -1157,13 +1157,28 @@ PART.Inputs.flat_dot_right = function(self) end -PART.Inputs.server_maxplayers = function(self) - return game.MaxPlayers() +PART.Inputs.server_maxplayers = function(self) return game.MaxPlayers() end +PART.Inputs.server_playercount = function(self) + local count = 0 + for _, ply in player.Iterator() do count = count + 1 end + return count end -PART.Inputs.server_playercount = function(self) return #player.GetAll() end PART.Inputs.server_population = PART.Inputs.server_playercount -PART.Inputs.server_botcount = function(self) return #player.GetBots() end -PART.Inputs.server_humancount = function(self) return #player.GetHumans() end + +PART.Inputs.server_botcount = function(self) + local count = 0 + for _, ply in player.Iterator() do + if ply:IsBot() then count = count + 1 end + end + return count +end +PART.Inputs.server_humancount = function(self) + local count = 0 + for _, ply in player.Iterator() do + if not ply:IsBot() then count = count + 1 end + end + return count +end PART.Inputs.pac_healthbars_total = function(self) @@ -1235,7 +1250,7 @@ PART.Inputs.healthmod_bar_remaining_bars = PART.Inputs.pac_healthbar_remaining_b net.Receive("pac_proxy", function() - local ply = net.ReadEntity() + local ply = net.ReadPlayer() local str = net.ReadString() local x = net.ReadFloat() @@ -1245,7 +1260,7 @@ net.Receive("pac_proxy", function() if ply:IsValid() then ply.pac_proxy_events = ply.pac_proxy_events or {} ply.pac_proxy_events[str] = {name = str, x = x, y = y, z = z} - if LocalPlayer() == ply then + if pac.LocalPlayer == ply then pac.Message("pac_proxy -> command(\""..str.."\") is " .. x .. "," .. y .. "," .. z) end end @@ -1378,9 +1393,11 @@ function PART:OnHide() -- cleanup event triggers on hide local part = self:GetTarget() if self.AffectChildren then - for _, part in ipairs(self:GetChildren()) do - part:SetEventTrigger(self, false) - part.proxy_hide = nil + local children = self:GetChildren() + for i = 1, #children do + local child = children[i] + child:SetEventTrigger(self, false) + child.proxy_hide = nil end elseif part:IsValid() then part:SetEventTrigger(self, false) @@ -1409,12 +1426,9 @@ local function set(self, part, x, y, z, children) x = x or val == true and 1 or 0 local b = tonumber(x) > 0 - -- special case for hide to make it behave like events if self.VariableName == "Hide" then - if part.proxy_hide ~= b then - -- in case parts start as hidden if b == false then part:SetKeyValueRecursive("Hide", b) @@ -1459,14 +1473,15 @@ local function set(self, part, x, y, z, children) end if children then - for _, part in ipairs(part:GetChildren()) do - set(self, part, x, y, z, true) + local children_list = part:GetChildren() + for i = 1, #children_list do + set(self, children_list[i], x, y, z, true) end end end function PART:RunExpression(ExpressionFunc) - if ExpressionFunc==true then + if ExpressionFunc == true then return false,self.ExpressionError end return pcall(ExpressionFunc) @@ -1523,7 +1538,7 @@ end function PART:OnThink(to_hide) local part = self:GetTarget() if not part:IsValid() then return end - if part.ClassName == 'woohoo' then --why a part hardcode exclusion?? + if part.ClassName == "woohoo" then --why a part hardcode exclusion?? --ok fine I guess it's because it's super expensive, but at least we can be selective about it, the other parameters are safe if self.VariableName == "Resolution" or self.VariableName == "BlurFiltering" and self.touched then return @@ -1542,9 +1557,9 @@ function PART:OnThink(to_hide) self:CalcVelocity() if self.has_extras then --pre-calculate the extra expressions if needed - for i=1,5,1 do + for i = 1, 5, 1 do if self["Extra" .. i] ~= "" then - local ok, x,y,z = self:RunExpression(self["Extra" .. i .. "Func"]) + local ok, x, y, z = self:RunExpression(self["Extra" .. i .. "Func"]) if ok then self["feedback_extra" .. i] = x end @@ -1561,12 +1576,11 @@ function PART:OnThink(to_hide) end if ExpressionFunc then - - local ok, x,y,z = self:RunExpression(ExpressionFunc) + local ok, x, y, z = self:RunExpression(ExpressionFunc) if not ok then if self:GetPlayerOwner() == pac.LocalPlayer and self.Expression ~= self.LastBadExpression then - chat.AddText(Color(255,180,180),"============\n[ERR] PAC Proxy error on "..tostring(self)..":\n"..x.."\n============\n") + chat.AddText(Color(255, 180, 180), "============\n[ERR] PAC Proxy error on " .. tostring(self) .. ":\n" .. x .. "\n============\n") self.LastBadExpression = self.Expression end return @@ -1576,7 +1590,6 @@ function PART:OnThink(to_hide) if y and not isnumber(y) then y = 0 end if z and not isnumber(z) then z = 0 end - if self.Additive then if x then self.vec_additive[1] = (self.vec_additive[1] or 0) + x @@ -1600,15 +1613,15 @@ function PART:OnThink(to_hide) self.feedback[3] = z if self.AffectChildren then - for _, part in ipairs(self:GetChildren()) do - set(self, part, x, y, z, true) + local children = self:GetChildren() + for i = 1, #children do + set(self, children[i], x, y, z, true) end else set(self, part, x, y, z) end if pace and pace.IsActive() then - local str = "" if x then str = str .. math.Round(x, 3) end @@ -1633,7 +1646,6 @@ function PART:OnThink(to_hide) end end else - local post_function = self.Functions[self.Function] local input_function = self.Inputs[self.Input] @@ -1658,8 +1670,9 @@ function PART:OnThink(to_hide) end if self.AffectChildren then - for _, part in ipairs(self:GetChildren()) do - set(self, part, num, nil, nil, true) + local children = self:GetChildren() + for i = 1, #children do + set(self, children[i], num, nil, nil, true) end else set(self, part, num) diff --git a/lua/pac3/core/client/parts/script.lua b/lua/pac3/core/client/parts/script.lua index c7ac1d080..51706388c 100644 --- a/lua/pac3/core/client/parts/script.lua +++ b/lua/pac3/core/client/parts/script.lua @@ -3,8 +3,8 @@ local BUILDER, PART = pac.PartTemplate("base") PART.ClassName = "script" PART.ThinkTime = 0 -PART.Group = 'advanced' -PART.Icon = 'icon16/page_white_gear.png' +PART.Group = "advanced" +PART.Icon = "icon16/page_white_gear.png" BUILDER:StartStorableVars() BUILDER:GetSet("Code", "") @@ -59,14 +59,12 @@ local lib = local function translate_xyz(x, y, z, T, def) if T == "Vector" then - def.x = x or def.x def.y = y or def.y def.z = z or def.z return def elseif T == "Angle" then - def.p = x or def.p def.y = y or def.y def.r = z or def.r @@ -90,7 +88,6 @@ local function translate_value(val, T) end local function CreateDummies(parts) - local obj = { SetProperty = function(_, key, x, y, z) if not key then return end diff --git a/lua/pac3/core/client/parts/sound.lua b/lua/pac3/core/client/parts/sound.lua index 23ca2dccc..6a6661958 100644 --- a/lua/pac3/core/client/parts/sound.lua +++ b/lua/pac3/core/client/parts/sound.lua @@ -5,9 +5,8 @@ local BUILDER, PART = pac.PartTemplate("base_movable") PART.FriendlyName = "web sound" PART.ClassName = "sound2" -PART.Icon = 'icon16/music.png' -PART.Group = 'effects' - +PART.Icon = "icon16/music.png" +PART.Group = "effects" BUILDER:StartStorableVars() BUILDER:SetPropertyGroup("generic") diff --git a/lua/pac3/core/client/parts/text.lua b/lua/pac3/core/client/parts/text.lua index 865113758..b45f9f900 100644 --- a/lua/pac3/core/client/parts/text.lua +++ b/lua/pac3/core/client/parts/text.lua @@ -15,10 +15,9 @@ local BUILDER, PART = pac.PartTemplate("base_drawable") local draw_distance = CreateClientConVar("pac_limit_text_2d_draw_distance", "1000", true, false, "How far to see other players' text parts using 2D modes. They will start fading out 200 units before this distance.") - net.Receive("pac_chat_typing_mirror_broadcast", function(len) local text = net.ReadString() - local ply = net.ReadEntity() + local ply = net.ReadPlayer() ply.pac_mirrored_chat_text = text end) @@ -88,7 +87,6 @@ local default_fonts = { "treb_small" } - PART.ClassName = "text" PART.Group = "effects" PART.Icon = "icon16/text_align_center.png" @@ -364,7 +362,9 @@ function PART:OnDraw() elseif diff == 2 then DisplayText = "Normal" elseif diff == 3 then DisplayText = "Hard" end elseif self.TextOverride == "Players" then - DisplayText = #player.GetAll() + local count = 0 + for _, v in player.Iterator() do count = count + 1 end + DisplayText = count elseif self.TextOverride == "MaxPlayers" then DisplayText = game.MaxPlayers() elseif self.TextOverride == "Weapon" then diff --git a/lua/pac3/core/client/parts/trail.lua b/lua/pac3/core/client/parts/trail.lua index 41089745d..ffa057306 100644 --- a/lua/pac3/core/client/parts/trail.lua +++ b/lua/pac3/core/client/parts/trail.lua @@ -28,7 +28,7 @@ function pac.DrawTrail(self, len, spc, pos, ang, mat, scr,scg,scb,sca, ecr,ecg,e local time = RealTime() - if not points[1] or points[#points].pos:Distance(pos) > spc then + if not points[1] or points[#points].pos:DistToSqr(pos) > (spc ^ 2) then table_insert(points, {pos = pos * 1, life_time = time + len}) end @@ -40,9 +40,9 @@ function pac.DrawTrail(self, len, spc, pos, ang, mat, scr,scg,scb,sca, ecr,ecg,e for i = #points, 1, -1 do local data = points[i] - local f = (data.life_time - time)/len + local f = (data.life_time - time) / len local f2 = f - f = -f+1 + f = -f + 1 local coord = (1 / count) * (i - 1) @@ -61,12 +61,17 @@ function pac.DrawTrail(self, len, spc, pos, ang, mat, scr,scg,scb,sca, ecr,ecg,e if self.CenterAttraction ~= 0 then local attraction = FrameTime() * self.CenterAttraction - local center = Vector(0,0,0) - for _, data in ipairs(points) do + local center = Vector(0, 0, 0) + + for i = 1, #points do + local data = points[i] + center:Zero() - for _, data in ipairs(points) do - center:Add(data.pos) + + for x = 1, #points do + center:Add(points[x].pos) end + center:Mul(1 / #points) center:Sub(data.pos) center:Mul(attraction) @@ -77,9 +82,11 @@ function pac.DrawTrail(self, len, spc, pos, ang, mat, scr,scg,scb,sca, ecr,ecg,e if not self.Gravity:IsZero() then local gravity = self.Gravity * FrameTime() + gravity:Rotate(ang) - for _, data in ipairs(points) do - data.pos:Add(gravity) + + for i = 1, #points do + points[i].pos:Add(gravity) end end end @@ -88,8 +95,8 @@ local BUILDER, PART = pac.PartTemplate("base_drawable") PART.FriendlyName = "trail" PART.ClassName = "trail2" -PART.Icon = 'icon16/arrow_undo.png' -PART.Group = 'effects' +PART.Icon = "icon16/arrow_undo.png" +PART.Group = "effects" PART.ProperColorRange = true BUILDER:StartStorableVars() @@ -164,21 +171,23 @@ end function PART:OnDraw() local pos, ang = self:GetDrawPosition() local mat = self.material_override and self.material_override[0][1] and self.material_override[0][1]:GetRawMaterial() or self.Materialm + if not mat then return end + pac.DrawTrail( self, math.min(self.Duration, 10), - self.Spacing + (self.StartSize/10), + self.Spacing + (self.StartSize / 10), pos, ang, mat, - self.StartColor.x*255, self.StartColor.y*255, self.StartColor.z*255,self.StartAlpha*255, - self.EndColor.x*255, self.EndColor.y*255, self.EndColor.z*255,self.EndAlpha*255, + self.StartColor.x * 255, self.StartColor.y * 255, self.StartColor.z * 255, self.StartAlpha * 255, + self.EndColor.x * 255, self.EndColor.y * 255, self.EndColor.z * 255, self.EndAlpha * 255, self.StartSize, self.EndSize, - 1/self.Stretch + 1 / self.Stretch ) end diff --git a/lua/pac3/core/client/tests/smoke.lua b/lua/pac3/core/client/tests/smoke.lua index ee388b0f9..b1fe30b27 100644 --- a/lua/pac3/core/client/tests/smoke.lua +++ b/lua/pac3/core/client/tests/smoke.lua @@ -1,7 +1,7 @@ function test.Run(done) local function find_part_in_entities(part) - for k,v in pairs(ents.GetAll()) do + for _, v in ents.Iterator() do if v.PACPart == part then return v.PACPart end diff --git a/lua/pac3/core/client/util.lua b/lua/pac3/core/client/util.lua index b032a2df3..1cf66efda 100644 --- a/lua/pac3/core/client/util.lua +++ b/lua/pac3/core/client/util.lua @@ -81,7 +81,7 @@ end do --dev util function pac.RemoveAllPACEntities() - for _, ent in pairs(ents.GetAll()) do + for _, ent in ents.Iterator() do pac.UnhookEntityRender(ent) if ent.IsPACEntity then @@ -100,7 +100,7 @@ do --dev util pac.RemoveAllParts() pac.RemoveAllPACEntities() - for i, ent in ipairs(ents.GetAll()) do + for i, ent in ents.Iterator() do ent.pac_ignored = nil ent.pac_ignored_data = nil ent.pac_drawing = nil @@ -142,7 +142,6 @@ do --dev util pac.convarcache = {} function pac.CreateClientConVarFast(cvar,initial,save,t,server) - local cached = pac.convarcache[cvar] if cached then return cached[1],cached[2] end @@ -183,8 +182,8 @@ do --dev util local function GetConVarValue() return val end - pac.convarcache[cvar]={GetConVarValue,c} - return GetConVarValue,c + pac.convarcache[cvar] = {GetConVarValue, c} + return GetConVarValue, c end end @@ -215,19 +214,44 @@ do "bright" } - function pac.HSVToNames(h,s,v) + local color_obj = Color(0, 0, 0) + + 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] + 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 + --color can mean a color object or a vector using the range 0-255 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))) + + if c.ToHSV then + --is a color object, pass it straight to ColorToHSV + return pac.HSVToNames(ColorToHSV(c)) + else + --is a vector pretending to be a color, convert to color for ColorToHSV + color_obj.r = c.r + color_obj.g = c.g + color_obj.b = c.b + + return pac.HSVToNames(ColorToHSV(color_obj)) + end end + --vector color means a vector using the range 0-1 + function pac.VectorColorToNames(c) + if c.r == 1 and c.g == 1 and c.b == 1 then return "white", "", "bright" end + if c.r == 0 and c.g == 0 and c.b == 0 then return "black", "", "bright" end + + color_obj.r = c.r * 255 + color_obj.g = c.g * 255 + color_obj.b = c.b * 255 + + return pac.HSVToNames(ColorToHSV(color_obj)) + end function pac.PrettifyName(str) if not str then return end @@ -235,11 +259,10 @@ do 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 pac_error_mdl = CreateClientConVar("pac_error_mdl", "1", true, false, "0 = default error, 1 = custom error model, models/yourmodel.mdl") local tc local invalidCache = {} @@ -466,7 +489,7 @@ end local mat -for _, ent in pairs(ents.GetAll()) do +for _, ent in ents.Iterator() do ent.pac_can_legacy_scale = nil end diff --git a/lua/pac3/core/server/effects.lua b/lua/pac3/core/server/effects.lua index cff75842a..734dddeb0 100644 --- a/lua/pac3/core/server/effects.lua +++ b/lua/pac3/core/server/effects.lua @@ -11,17 +11,20 @@ pac.EffectsBlackList = if not pac_loaded_particle_effects then pac_loaded_particle_effects = {} + local files = file.Find("particles/*.pcf", "GAME") - for key, file_name in pairs(files) do - if not pac_loaded_particle_effects[file_name] and not pac.BlacklistedParticleSystems[file_name:lower()] then - game.AddParticles("particles/" .. file_name) + for i = 1, #files do + local path = files[i] + + if not pac_loaded_particle_effects[path] and not pac.BlacklistedParticleSystems[path:lower()] then + game.AddParticles("particles/" .. path) end - pac_loaded_particle_effects[file_name] = true + pac_loaded_particle_effects[path] = true end - pac.Message('Loaded total ', #files, ' particle systems') + pac.Message("Loaded total ", #files, " particle systems") end util.AddNetworkString("pac_effect_precached") @@ -29,6 +32,7 @@ util.AddNetworkString("pac_request_precache") function pac.PrecacheEffect(name) PrecacheParticleSystem(name) + net.Start("pac_effect_precached") net.WriteString(name) net.Broadcast() @@ -42,18 +46,22 @@ net.Receive("pac_request_precache", function(len, pl) -- Each player gets a 50 length queue local plqueue = queue[pl] if plqueue then - if #plqueue<50 then plqueue[#plqueue+1] = name end + if #plqueue < 50 then + plqueue[#plqueue + 1] = name + end else plqueue = {name} queue[pl] = plqueue + local function processQueue() - if #plqueue == 0 then - queue[pl] = nil - else + if plqueue[1] ~= nil then timer.Simple(0.5, processQueue) - pac.PrecacheEffect(table.remove(plqueue,1)) + pac.PrecacheEffect(table.remove(plqueue, 1)) + else + queue[pl] = nil end end + processQueue() end end) diff --git a/lua/pac3/core/server/event.lua b/lua/pac3/core/server/event.lua index ba156128a..cb271b0d3 100644 --- a/lua/pac3/core/server/event.lua +++ b/lua/pac3/core/server/event.lua @@ -1,4 +1,3 @@ - util.AddNetworkString("pac_proxy") util.AddNetworkString("pac_event") util.AddNetworkString("pac_event_set_sequence") @@ -6,11 +5,18 @@ util.AddNetworkString("pac_event_set_sequence") net.Receive("pac_event_set_sequence", function(len, ply) local event = net.ReadString() local num = net.ReadUInt(8) - ply.pac_command_events = ply.pac_command_events or {} - for i=1,100,1 do - ply.pac_command_events[event..i] = nil + + local plyTbl = ply:GetTable() + + if not plyTbl.pac_command_events then + plyTbl.pac_command_events = {} + else + for i = 1, 100 do + plyTbl.pac_command_events[event .. i] = nil + end end - ply.pac_command_events[event..num] = {name = event, time = pac.RealTime, on = 1} + + plyTbl.pac_command_events[event .. num] = {name = event, time = pac.RealTime, on = 1} end) -- event @@ -20,21 +26,29 @@ concommand.Add("pac_event", function(ply, _, args) local event = args[1] local extra = tonumber(args[2]) or 0 + local plyTbl = ply:GetTable() + if extra == 2 or args[2] == "toggle" then - ply.pac_event_toggles = ply.pac_event_toggles or {} - ply.pac_event_toggles[event] = not ply.pac_event_toggles[event] + if not plyTbl.pac_event_toggles then + plyTbl.pac_event_toggles = {} + end + + plyTbl.pac_event_toggles[event] = not plyTbl.pac_event_toggles[event] - extra = ply.pac_event_toggles[event] and 1 or 0 + extra = plyTbl.pac_event_toggles[event] and 1 or 0 end net.Start("pac_event", true) - net.WriteEntity(ply) + net.WritePlayer(ply) net.WriteString(event) net.WriteInt(extra, 8) net.Broadcast() - ply.pac_command_events = ply.pac_command_events or {} - ply.pac_command_events[event] = ply.pac_command_events[event] or {} - ply.pac_command_events[event] = {name = event, time = pac.RealTime, on = extra} + + if not plyTbl.pac_command_events then + plyTbl.pac_command_events = {} + end + + plyTbl.pac_command_events[event] = {name = event, time = pac.RealTime, on = extra} end) concommand.Add("+pac_event", function(ply, _, args) @@ -42,17 +56,23 @@ concommand.Add("+pac_event", function(ply, _, args) if args[2] == "2" or args[2] == "toggle" then local event = args[1] - ply.pac_event_toggles = ply.pac_event_toggles or {} - ply.pac_event_toggles[event] = true + + local plyTbl = ply:GetTable() + + if not plyTbl.pac_event_toggles then + plyTbl.pac_event_toggles = {} + end + + plyTbl.pac_event_toggles[event] = true net.Start("pac_event", true) - net.WriteEntity(ply) + net.WritePlayer(ply) net.WriteString(event) net.WriteInt(1, 8) net.Broadcast() else net.Start("pac_event", true) - net.WriteEntity(ply) + net.WritePlayer(ply) net.WriteString(args[1] .. "_on") net.Broadcast() end @@ -63,16 +83,23 @@ concommand.Add("-pac_event", function(ply, _, args) if args[2] == "2" or args[2] == "toggle" then local event = args[1] - ply.pac_event_toggles = ply.pac_event_toggles or {} - ply.pac_event_toggles[event] = false + + local plyTbl = ply:GetTable() + + if not plyTbl.pac_event_toggles then + plyTbl.pac_event_toggles = {} + end + + plyTbl.pac_event_toggles[event] = false + net.Start("pac_event", true) - net.WriteEntity(ply) + net.WritePlayer(ply) net.WriteString(event) net.WriteInt(0, 8) net.Broadcast() else net.Start("pac_event", true) - net.WriteEntity(ply) + net.WritePlayer(ply) net.WriteString(args[1] .. "_off") net.Broadcast() end @@ -82,30 +109,38 @@ end) concommand.Add("pac_proxy", function(ply, _, args) str = args[1] - if ply:IsValid() then - ply.pac_proxy_events = ply.pac_proxy_events or {} + local plyTbl = ply:GetTable() + + if not plyTbl.pac_proxy_events then + plyTbl.pac_proxy_events = {} end - local x - local y - local z - if ply.pac_proxy_events[str] ~= nil then + + local x, y, z + + if plyTbl.pac_proxy_events[str] ~= nil then if args[2] then - if string.sub(args[2],1,2) == "++" or string.sub(args[2],1,2) == "--" then - x = ply.pac_proxy_events[str].x + tonumber(string.sub(args[2],2,#args[2])) - else x = tonumber(args[2]) or ply.pac_proxy_events[str].x or 0 end + if string.sub(args[2], 1, 2) == "++" or string.sub(args[2], 1, 2) == "--" then + x = plyTbl.pac_proxy_events[str].x + tonumber(string.sub(args[2], 2, #args[2])) + else + x = tonumber(args[2]) or plyTbl.pac_proxy_events[str].x or 0 + end end if args[3] then - if string.sub(args[3],1,2) == "++" or string.sub(args[3],1,2) == "--" then - y = ply.pac_proxy_events[str].y + tonumber(string.sub(args[3],2,#args[3])) - else y = tonumber(args[3]) or ply.pac_proxy_events[str].y or 0 end + if string.sub(args[3], 1, 2) == "++" or string.sub(args[3], 1, 2) == "--" then + y = plyTbl.pac_proxy_events[str].y + tonumber(string.sub(args[3], 2, #args[3])) + else + y = tonumber(args[3]) or plyTbl.pac_proxy_events[str].y or 0 + end end if not args[3] then y = 0 end if args[4] then - if string.sub(args[4],1,2) == "++" or string.sub(args[4],1,2) == "--" then - z = ply.pac_proxy_events[str].z + tonumber(string.sub(args[4],2,#args[4])) - else z = tonumber(args[4]) or ply.pac_proxy_events[str].z or 0 end + if string.sub(args[4], 1, 2) == "++" or string.sub(args[4], 1, 2) == "--" then + z = plyTbl.pac_proxy_events[str].z + tonumber(string.sub(args[4], 2, #args[4])) + else + z = tonumber(args[4]) or plyTbl.pac_proxy_events[str].z or 0 + end end if not args[4] then z = 0 end else @@ -113,16 +148,15 @@ concommand.Add("pac_proxy", function(ply, _, args) y = tonumber(args[3]) or 0 z = tonumber(args[4]) or 0 end - ply.pac_proxy_events[str] = {name = str, x = x, y = y, z = z} + + plyTbl.pac_proxy_events[str] = {name = str, x = x, y = y, z = z} net.Start("pac_proxy", true) - net.WriteEntity(ply) + net.WritePlayer(ply) net.WriteString(args[1]) net.WriteFloat(x or 0) net.WriteFloat(y or 0) net.WriteFloat(z or 0) net.Broadcast() - - --PrintTable(ply.pac_proxy_events[str]) end) diff --git a/lua/pac3/core/server/in_skybox.lua b/lua/pac3/core/server/in_skybox.lua index 01f214272..72d8c87b2 100644 --- a/lua/pac3/core/server/in_skybox.lua +++ b/lua/pac3/core/server/in_skybox.lua @@ -1,5 +1,6 @@ pac.AddHook("InitPostEntity", "get_sky_camera", function() local sky_camera = ents.FindByClass("sky_camera")[1] + if sky_camera then local nwVarName = "pac_in_skybox" local in_skybox = {} @@ -8,15 +9,23 @@ pac.AddHook("InitPostEntity", "get_sky_camera", function() if not IsValid(sky_camera) then sky_camera = ents.FindByClass("sky_camera")[1] end + local new_in_skybox = {} - for _, ent in ipairs(ents.FindInPVS(sky_camera:GetPos())) do + + local ents_pvs = ents.FindInPVS(sky_camera:GetPos()) + + for i = 1, #ents_pvs do + local ent = ents_pvs[i] + if not in_skybox[ent] then ent:SetNW2Bool(nwVarName, true) end new_in_skybox[ent] = true end - for ent in pairs(in_skybox) do + for i = 1, #in_skybox do + local ent = in_skybox[i] + if not new_in_skybox[ent] and ent:IsValid() then ent:SetNW2Bool(nwVarName, false) end diff --git a/lua/pac3/core/server/net_messages.lua b/lua/pac3/core/server/net_messages.lua index 2f37bc6b4..954ff67c7 100644 --- a/lua/pac3/core/server/net_messages.lua +++ b/lua/pac3/core/server/net_messages.lua @@ -17,7 +17,7 @@ do -- button event if not ply.pac_broadcast_buttons[key] then return end net.Start("pac.BroadcastPlayerButton") - net.WriteEntity(ply) + net.WritePlayer(ply) net.WriteUInt(key, 8) net.WriteBool(down) net.Broadcast() @@ -36,6 +36,6 @@ net.Receive("pac_chat_typing_mirror", function(len, ply) local str = net.ReadString() net.Start("pac_chat_typing_mirror_broadcast") net.WriteString(str) - net.WriteEntity(ply) + net.WritePlayer(ply) net.Broadcast() end) diff --git a/lua/pac3/core/shared/entity_mutator.lua b/lua/pac3/core/shared/entity_mutator.lua index 6b03d57f6..a56defea5 100644 --- a/lua/pac3/core/shared/entity_mutator.lua +++ b/lua/pac3/core/shared/entity_mutator.lua @@ -4,7 +4,7 @@ local CLIENT = CLIENT local SERVER = SERVER if pac.emut then - for _, ent in ipairs(ents.GetAll()) do + for _, ent in ents.Iterator() do if ent.pac_mutations then for _, mutator in pairs(ent.pac_mutations) do xpcall(pac.emut.RestoreMutations, function() end, mutator.Owner, mutator.ClassName, mutator.Entity) @@ -173,7 +173,7 @@ end function emut.Register(meta) if Entity(1):IsValid() then - for _, ent in ipairs(ents.GetAll()) do + for _, ent in ents.Iterator() do if ent.pac_mutations then for class_name, mutator in pairs(ent.pac_mutations) do if class_name == meta.ClassName then @@ -338,6 +338,7 @@ if CLIENT then net.Receive("pac_entity_mutator", function(len) local ply = net.ReadEntity() if not ply:IsValid() then return end + local class_name = net.ReadString() local ent = net.ReadEntity() if not ent:IsValid() then return end @@ -359,8 +360,8 @@ end function emut.LoadMutators() local files = file.Find("pac3/core/shared/entity_mutators/*.lua", "LUA") - for _, name in pairs(files) do - include("pac3/core/shared/entity_mutators/" .. name) + for i = 1, #files do + include("pac3/core/shared/entity_mutators/" .. files[i]) end end diff --git a/lua/pac3/core/shared/footsteps_fix.lua b/lua/pac3/core/shared/footsteps_fix.lua index c38ac2382..f2519f146 100644 --- a/lua/pac3/core/shared/footsteps_fix.lua +++ b/lua/pac3/core/shared/footsteps_fix.lua @@ -1,4 +1,3 @@ - if game.SinglePlayer() then if SERVER then util.AddNetworkString("pac_footstep") @@ -10,7 +9,7 @@ if game.SinglePlayer() then net.Send(ply) net.Start("pac_footstep") - net.WriteEntity(ply) + net.WritePlayer(ply) net.WriteVector(pos) net.WriteString(snd) net.WriteFloat(vol) @@ -26,13 +25,11 @@ if game.SinglePlayer() then end) else pac.RemoveHook("PlayerFootstep", "footstep_silence") end end) - - end if CLIENT then net.Receive("pac_footstep", function(len) - local ply = net.ReadEntity() + local ply = net.ReadPlayer() local pos = net.ReadVector() local snd = net.ReadString() local vol = net.ReadFloat() @@ -41,6 +38,7 @@ if game.SinglePlayer() then hook.Run("pac_PlayerFootstep", ply, pos, snd, vol) end end) + net.Receive("pac_footstep_request_state_update", function() net.Start("pac_signal_mute_footstep") net.WriteBool(LocalPlayer().pac_mute_footsteps) diff --git a/lua/pac3/core/shared/movement.lua b/lua/pac3/core/shared/movement.lua index 6967b8f56..cdc7c85cd 100644 --- a/lua/pac3/core/shared/movement.lua +++ b/lua/pac3/core/shared/movement.lua @@ -169,12 +169,11 @@ pac.AddHook("Move", "custom_movement", function(ply, mv) end pac.AddHook("EntityTakeDamage", "PAC3MassDamageScale", function(target, dmginfo) - if (target:IsPlayer() and dmginfo:IsDamageType(DMG_CRUSH or DMG_VEHICLE)) then + if target:IsPlayer() and dmginfo:IsDamageType(DMG_CRUSH or DMG_VEHICLE) then dmginfo:ScaleDamage(target.scale_mass or 1) end end) - if self.Noclip then ply:SetMoveType(MOVETYPE_NONE) else @@ -265,7 +264,6 @@ pac.AddHook("Move", "custom_movement", function(ply, mv) -- todo: don't allow adding more velocity to existing velocity if it exceeds -- but allow decreasing if not on_ground then - if ply:WaterLevel() >= 2 then local ground_speed = self.RunSpeed @@ -354,41 +352,40 @@ pac.AddHook("Move", "custom_movement", function(ply, mv) if self.FinEfficiency > 0 then -- fin local curvel = vel local curup = ang:Forward() + local curspeed = curvel:Length() local vec1 = curvel local vec2 = curup - vec1 = vec1 - 2*(vec1:Dot(vec2))*vec2 - local sped = vec1:Length() + vec1 = vec1 - 2 * (vec1:Dot(vec2)) * vec2 local finalvec = curvel local modf = math.abs(curup:Dot(curvel:GetNormalized())) - local nvec = (curup:Dot(curvel:GetNormalized())) + local nvec = curup:Dot(curvel:GetNormalized()) if (self.pln == 1) then - if nvec > 0 then vec1 = vec1 + (curup * 10) else vec1 = vec1 + (curup * -10) end - finalvec = vec1:GetNormalized() * (math.pow(sped, modf) - 1) + finalvec = vec1:GetNormalized() * (math.pow(curspeed, modf) - 1) finalvec = finalvec:GetNormalized() finalvec = (finalvec * self.FinEfficiency) + curvel end - if (self.FinLiftMode ~= "none") then - if (self.FinLiftMode == "normal") then + if self.FinLiftMode ~= "none" then + if self.FinLiftMode == "normal" then local liftmul = 1 - math.abs(nvec) - finalvec = finalvec + (curup * liftmul * curvel:Length() * self.FinEfficiency) / 700 + finalvec = finalvec + (curup * liftmul * curspeed * self.FinEfficiency) / 700 else local liftmul = (nvec / math.abs(nvec)) - nvec - finalvec = finalvec + (curup * curvel:Length() * self.FinEfficiency * liftmul) / 700 + finalvec = finalvec + (curup * curspeed * self.FinEfficiency * liftmul) / 700 end end finalvec = finalvec:GetNormalized() - finalvec = finalvec * curvel:Length() + finalvec = finalvec * curspeed if self.FinCline then local trace = { @@ -396,13 +393,14 @@ pac.AddHook("Move", "custom_movement", function(ply, mv) endpos = mv:GetOrigin() + Vector(0, 0, -1000000), mask = 131083 } + local trc = util.TraceLine(trace) local MatType = trc.MatType - if (MatType == 67 or MatType == 77) then + if MatType == 67 or MatType == 77 then local heatvec = Vector(0, 0, 100) - local cline = ((2 * (heatvec:Dot(curup)) * curup - heatvec)) * (math.abs(heatvec:Dot(curup)) / 1000) + local cline = (2 * (heatvec:Dot(curup)) * curup - heatvec) * (math.abs(heatvec:Dot(curup)) / 1000) finalvec = finalvec + (cline * (self.FinEfficiency / 50)) end end diff --git a/lua/pac3/core/shared/util.lua b/lua/pac3/core/shared/util.lua index 36c1e79ba..2d4d472e5 100644 --- a/lua/pac3/core/shared/util.lua +++ b/lua/pac3/core/shared/util.lua @@ -1,3 +1,4 @@ +local table_insert = table.insert local PREFIX = '[PAC3] ' local PREFIX_COLOR = Color(255, 255, 0) @@ -16,10 +17,10 @@ function pac.RepackMessage(strIn) for line in string.gmatch(strIn, '([^ ]+)') do if #output ~= 0 then - table.insert(output, ' ') + table_insert(output, ' ') end - table.insert(output, line) + table_insert(output, line) end return output @@ -33,55 +34,55 @@ local function FormatMessage(tabIn) local valType = type(val) if valType == 'number' then - table.insert(output, NUMBER_COLOR) - table.insert(output, tostring(val)) - table.insert(output, prevColor) + table_insert(output, NUMBER_COLOR) + table_insert(output, tostring(val)) + table_insert(output, prevColor) elseif valType == 'string' then if val:find('^https?://') then - table.insert(output, URL_COLOR) - table.insert(output, val) - table.insert(output, prevColor) + table_insert(output, URL_COLOR) + table_insert(output, val) + table_insert(output, prevColor) else - table.insert(output, val) + table_insert(output, val) end elseif valType == 'Player' then if team then - table.insert(output, team.GetColor(val:Team()) or ENTITY_COLOR) + table_insert(output, team.GetColor(val:Team()) or ENTITY_COLOR) else - table.insert(output, ENTITY_COLOR) + table_insert(output, ENTITY_COLOR) end - table.insert(output, val:Nick()) + table_insert(output, val:Nick()) if val.SteamName and val:SteamName() ~= val:Nick() then - table.insert(output, ' (' .. val:SteamName() .. ')') + table_insert(output, ' (' .. val:SteamName() .. ')') end - table.insert(output, '<') - table.insert(output, val:SteamID()) - table.insert(output, '>') - table.insert(output, prevColor) + table_insert(output, '<') + table_insert(output, val:SteamID()) + table_insert(output, '>') + table_insert(output, prevColor) elseif valType == 'Entity' or valType == 'NPC' or valType == 'Vehicle' then - table.insert(output, ENTITY_COLOR) - table.insert(output, tostring(val)) - table.insert(output, prevColor) + table_insert(output, ENTITY_COLOR) + table_insert(output, tostring(val)) + table_insert(output, prevColor) elseif IsColor(val) then - table.insert(output, val) + table_insert(output, val) prevColor = val elseif valType == 'table' then - table.insert(output, TABLE_COLOR) - table.insert(output, tostring(val)) - table.insert(output, prevColor) + table_insert(output, TABLE_COLOR) + table_insert(output, tostring(val)) + table_insert(output, prevColor) elseif valType == 'function' then - table.insert(output, FUNCTION_COLOR) - table.insert(output, string.format('function - %p', val)) - table.insert(output, prevColor) + table_insert(output, FUNCTION_COLOR) + table_insert(output, string.format('function - %p', val)) + table_insert(output, prevColor) elseif valType == 'boolean' then - table.insert(output, BOOLEAN_COLOR) - table.insert(output, tostring(val)) - table.insert(output, prevColor) + table_insert(output, BOOLEAN_COLOR) + table_insert(output, tostring(val)) + table_insert(output, prevColor) else - table.insert(output, tostring(val)) + table_insert(output, tostring(val)) end end @@ -114,6 +115,7 @@ end local DEBUG_MDL = false local VERBOSE = false +-- build texture_keys table (setting as keys avoids duplicate entries) local shader_params = include("pac3/libraries/shader_params.lua") local texture_keys = {} @@ -121,7 +123,7 @@ for _, shader in pairs(shader_params.shaders) do for _, params in pairs(shader) do for key, info in pairs(params) do if info.type == "texture" then - texture_keys[key] = key + texture_keys[key] = true end end end @@ -130,13 +132,19 @@ end for _, params in pairs(shader_params.base) do for key, info in pairs(params) do if info.type == "texture" then - texture_keys[key] = key + texture_keys[key] = true end end end texture_keys["include"] = "include" +-- build texture_keys_seq for sequential table reads of texture_keys +local texture_keys_seq = {} +for k in pairs(texture_keys) do + texture_keys_seq[#texture_keys_seq + 1] = k +end + -- for pac_restart PAC_MDL_SALT = PAC_MDL_SALT or 0 @@ -176,7 +184,8 @@ function pac.DownloadMDL(url, callback, onfail, ply) id = util.CRC(id .. os.clock()) end - if skip_cache or not file.Exists("pac3_cache/downloads/"..id..".dat", "DATA") then + if skip_cache or not file.Exists("pac3_cache/downloads/" .. id .. ".dat", "DATA") then + local is_localplayer = ply == pac.LocalPlayer local dir = "pac3_cache/" .. id .. "/" @@ -194,12 +203,12 @@ function pac.DownloadMDL(url, callback, onfail, ply) assert(sig == 0x04034b50, "bad zip signature (file is not a zip?)") - f:Seek(pos+6) local bitflag = f:ReadShort() - f:Seek(pos+8) local compression_method = f:ReadShort() - f:Seek(pos+14) local crc = f:ReadShort() - f:Seek(pos+18) local size2 = f:ReadLong() - f:Seek(pos+22) local size = f:ReadLong() - f:Seek(pos+26) local file_name_length = f:ReadShort() + f:Seek(pos + 6) local bitflag = f:ReadShort() + f:Seek(pos + 8) local compression_method = f:ReadShort() + f:Seek(pos + 14) local crc = f:ReadShort() + f:Seek(pos + 18) local size2 = f:ReadLong() + f:Seek(pos + 22) local size = f:ReadLong() + f:Seek(pos + 26) local file_name_length = f:ReadShort() local extra_field_length = f:ReadShort() local name = f:Read(file_name_length):lower() @@ -221,17 +230,22 @@ function pac.DownloadMDL(url, callback, onfail, ply) end else local ok = true - for i,v in ipairs(files) do + + for i = 1, #files do + local v = files[i] + if v.file_name == name then - if ply == pac.LocalPlayer then - pac.Message(Color(255, 50,50), file_path .. " is already a file at " .. v.file_path) + if is_localplayer then + pac.Message(Color(255, 50, 50), file_path .. " is already a file at " .. v.file_path) end + ok = false break end end + if ok then - table.insert(files, {file_name = name, buffer = buffer, crc = crc, file_path = file_path}) + table_insert(files, {file_name = name, buffer = buffer, crc = crc, file_path = file_path}) end end end @@ -245,25 +259,31 @@ function pac.DownloadMDL(url, callback, onfail, ply) table.sort(files, function(a, b) return #a.buffer > #b.buffer end) - for i, v in ipairs(files) do + for i = 1, #files do + local v = files[i] + if v.file_name:EndsWith(".mdl") then local name = v.file_name:match("(.+)%.mdl") - for _, v2 in ipairs(files) do + + for i = 1, #files do + local v2 = files[i] + if v2.file_name:EndsWith(name .. ".ani") then v.ani = v2 break end end + if v.ani then - v.file_name = v.file_name:gsub(".-(%..+)", "i"..count.."%1"):lower() - v.ani.file_name = v.ani.file_name:gsub(".-(%..+)", "i"..count.."%1"):lower() + v.file_name = v.file_name:gsub(".-(%..+)", "i" .. count .. "%1"):lower() + v.ani.file_name = v.ani.file_name:gsub(".-(%..+)", "i" .. count .. "%1"):lower() count = count + 1 else if not model_found or v.file_name:StartWith(model_found) then model_found = v.file_name:match("(.-)%.") v.file_name = v.file_name:gsub(".-(%..+)", "model%1"):lower() else - table.insert(other_models, v.file_name) + table_insert(other_models, v.file_name) end end elseif v.file_name:EndsWith(".vtx") or v.file_name:EndsWith(".vvd") or v.file_name:EndsWith(".phy") then @@ -271,12 +291,12 @@ function pac.DownloadMDL(url, callback, onfail, ply) model_found = v.file_name:match("(.-)%.") v.file_name = v.file_name:gsub(".-(%..+)", "model%1"):lower() else - table.insert(other_models, v.file_name) + table_insert(other_models, v.file_name) end end end - if other_models[1] and ply == pac.LocalPlayer then + if other_models[1] and is_localplayer then pac.Message(Color(255, 200, 50), url, ": the archive contains more than one model.") pac.Message(Color(255, 200, 50), url, ": " .. model_found .. " was selected.") pac.Message(Color(255, 200, 50), url, ": these are ignored:") @@ -295,8 +315,8 @@ function pac.DownloadMDL(url, callback, onfail, ply) local str = file.Read(path) file.Delete(path) - pac.Message(Color(255, 50,50), err) - pac.Message(Color(255, 50,50), "the zip archive downloaded (", string.NiceSize(#str) ,") could not be parsed") + pac.Message(Color(255, 50, 50), err) + pac.Message(Color(255, 50, 50), "the zip archive downloaded (", string.NiceSize(#str) ,") could not be parsed") local is_binary = false for i = 1, #str do @@ -308,9 +328,9 @@ function pac.DownloadMDL(url, callback, onfail, ply) end if not is_binary then - pac.Message(Color(255, 50,50), "the url isn't a binary zip archive. Is it a html website? here's the content:") + pac.Message(Color(255, 50, 50), "the url isn't a binary zip archive. Is it a html website? here's the content:") print(str) - elseif ply == pac.LocalPlayer then + elseif is_localplayer then file.Write("pac3_cache/failed_zip_download.dat", str) pac.Message("the zip archive was stored to garrysmod/data/pac3_cache/failed_zip_download.dat (rename extension to .zip) if you want to inspect it") end @@ -318,26 +338,34 @@ function pac.DownloadMDL(url, callback, onfail, ply) end local required = { - ".mdl", - ".vvd", - ".dx90.vtx", + {".mdl", false}, + {".vvd", false}, + {".dx90.vtx", false}, } - local found = {} - for k,v in pairs(files) do - for _, ext in ipairs(required) do - if v.file_name:EndsWith(ext) then - table.insert(found, ext) + + local foundCount = 0 + for i = 1, #files do + local v = files[i] + + for i = 1, #required do + local ext = required[i] + + if v.file_name:EndsWith(ext[1]) then + ext[2] = true + foundCount = foundCount + 1 break end end end - if #found < #required then + if foundCount < #required then local str = {} - for _, ext in ipairs(required) do - if not table.HasValue(found, ext) then - table.insert(str, ext) + for i = 1, #required do + local ext = required[i] + + if not ext[2] then + table_insert(str, ext[1]) end end @@ -349,7 +377,9 @@ function pac.DownloadMDL(url, callback, onfail, ply) do -- hex models local found_vmt_directories = {} - for i, data in ipairs(files) do + for i = 1, #files do + local data = files[i] + if data.file_name:EndsWith(".mdl") then local found_materials = {} local found_materialdirs = {} @@ -407,7 +437,9 @@ function pac.DownloadMDL(url, callback, onfail, ply) local material_name = (f:readString() .. ".vmt"):lower() local found = false - for i, v in pairs(files) do + for i = 1, #files do + local v = files[i] + if v.file_name == material_name then found = v.file_path break @@ -419,9 +451,11 @@ function pac.DownloadMDL(url, callback, onfail, ply) end if not found then - for i, v in pairs(files) do + for i = 1, #files do + local v = files[i] + if string.find(v.file_path, material_name, 1, true) or string.find(material_name, v.file_name, 1, true) then - table.insert(files, {file_name = material_name, buffer = v.buffer, crc = v.crc, file_path = v.file_path}) + table_insert(files, {file_name = material_name, buffer = v.buffer, crc = v.crc, file_path = v.file_path}) found = v.file_path break end @@ -429,31 +463,32 @@ function pac.DownloadMDL(url, callback, onfail, ply) end if not found then - if ply == pac.LocalPlayer then + if is_localplayer then pac.Message(Color(255, 50,50), url, " the model wants to find ", material_name , " but it was not found in the zip archive") end + local dummy = "VertexLitGeneric\n{\n\t$basetexture \"error\"\n}" - table.insert(files, {file_name = material_name, buffer = dummy, crc = util.CRC(dummy), file_path = material_name}) + table_insert(files, {file_name = material_name, buffer = dummy, crc = util.CRC(dummy), file_path = material_name}) end - table.insert(found_materials, {name = material_name, offset = material_name_pos}) + table_insert(found_materials, {name = material_name, offset = material_name_pos}) f:seek(material_end) end - if ply == pac.LocalPlayer and #found_materials == 0 then + if is_localplayer and found_materials[1] == nil then pac.Message(Color(255, 200, 50), url, ": could not find any materials in this model") end f:seek(old_pos) end - do vtf_dir_count = f:readUInt32() vtf_dir_offset = f:readUInt32() + 1 -- +1 to convert 0 indexed to 1 indexed local old_pos = f:tell() f:seek(vtf_dir_offset) + for i = 1, vtf_dir_count do local offset_pos = f:tell() local offset = f:readUInt32() + 1 -- +1 to convert 0 indexed to 1 indexed @@ -461,11 +496,12 @@ function pac.DownloadMDL(url, callback, onfail, ply) local old_pos = f:tell() f:seek(offset) local dir = f:readString() - table.insert(found_materialdirs, {offset_pos = offset_pos, offset = offset, dir = dir}) - table.insert(found_vmt_directories, {dir = dir}) + table_insert(found_materialdirs, {offset_pos = offset_pos, offset = offset, dir = dir}) + table_insert(found_vmt_directories, {dir = dir}) f:seek(old_pos) end - table.sort(found_vmt_directories, function(a,b) return #a.dir>#b.dir end) + + table.sort(found_vmt_directories, function(a, b) return #a.dir > #b.dir end) f:seek(old_pos) end @@ -498,8 +534,9 @@ function pac.DownloadMDL(url, callback, onfail, ply) local file_name_offset = f:readUInt32() local old_pos = f:tell() - f:seek(base_pos + file_name_offset) - table.insert(found_mdl_includes, {base_pos = base_pos, path = f:readString()}) + f:seek(base_pos + file_name_offset) + table_insert(found_mdl_includes, {base_pos = base_pos, path = f:readString()}) + f:seek(old_pos) end @@ -528,11 +565,15 @@ function pac.DownloadMDL(url, callback, onfail, ply) f:write(newname .. string.rep("\0", 64-#newname)) end - for i,v in ipairs(found_mdl_includes) do - local file_name = (v.path:match(".+/(.+)") or v.path) + for i = 1, #found_mdl_includes do + local v = found_mdl_includes[i] + + local file_name = v.path:match(".+/(.+)") or v.path local found = false - for _, info in ipairs(files) do + for i = 1, #files do + local info = files[i] + if info.file_path == file_name then file_name = info.file_name found = true @@ -543,22 +584,23 @@ function pac.DownloadMDL(url, callback, onfail, ply) if found then local path = "models/" .. dir .. file_name local newoffset = f:size() + 1 + f:seek(newoffset) f:writeString(path) f:seek(v.base_pos + 4) f:writeInt32(newoffset - v.base_pos) - elseif ply == pac.LocalPlayer and not file.Exists(v.path, "GAME") then + elseif is_localplayer and not file.Exists(v.path, "GAME") then pac.Message(Color(255, 50, 50), "the model want to include ", v.path, " but it doesn't exist") end end -- if we extend the mdl file with vmt directories we don't have to change any offsets cause nothing else comes after it if data.file_name == "model.mdl" then - for i,v in ipairs(found_materialdirs) do + for i = 1, #found_materialdirs do local newoffset = f:size() + 1 f:seek(newoffset) f:writeString(dir) - f:seek(v.offset_pos) + f:seek(found_materialdirs[i].offset_pos) f:writeInt32(newoffset - 1) -- -1 to convert 1 indexed to 0 indexed end else @@ -573,10 +615,10 @@ function pac.DownloadMDL(url, callback, onfail, ply) local cursize = f:size() -- Add nulls to align to 4 bytes - local padding = 4-cursize%4 - if padding<4 then - f:seek(cursize+1) - f:write(string.rep("\0",padding)) + local padding = 4 - cursize % 4 + if padding < 4 then + f:seek(cursize + 1) + f:write(string.rep("\0", padding)) cursize = cursize + padding end @@ -586,7 +628,7 @@ function pac.DownloadMDL(url, callback, onfail, ply) data.buffer = f:getString() if DEBUG_MDL then - file.Write(data.file_name..".debug.new.dat", data.buffer) + file.Write(data.file_name .. ".debug.new.dat", data.buffer) end local crc = pac.StringStream() @@ -595,7 +637,9 @@ function pac.DownloadMDL(url, callback, onfail, ply) end end - for i, data in ipairs(files) do + for i = 1, #files do + local data = files[i] + if data.file_name:EndsWith(".vmt") then local proxies = data.buffer:match('("?%f[%w_]P?p?roxies%f[^%w_]"?%s*%b{})') data.buffer = data.buffer:lower():gsub("\\", "/") @@ -608,14 +652,17 @@ function pac.DownloadMDL(url, callback, onfail, ply) print(data.file_name .. ":") end - for shader_param in pairs(texture_keys) do + for i = 1, #texture_keys_seq do + local shader_param = texture_keys_seq[i] + data.buffer = data.buffer:gsub('("?%$?%f[%w_]' .. shader_param .. '%f[^%w_]"?%s+"?)([^"%c]+)("?%s?)', function(l, vtf_path, r) if vtf_path == "env_cubemap" then return end local new_path - for _, info in ipairs(found_vmt_directories) do + for i = 1, #found_vmt_directories do + local info = found_vmt_directories[i] if info.dir == "" then continue end new_path, count = vtf_path:gsub("^" .. info.dir:gsub("\\", "/"):lower(), dir) @@ -627,8 +674,10 @@ function pac.DownloadMDL(url, callback, onfail, ply) end if not new_path then - for _, info in ipairs(files) do + for i = 1, #files do + local info = files[i] local vtf_name = (vtf_path:match(".+/(.+)") or vtf_path) + if info.file_name:EndsWith(".vtf") then if info.file_name == vtf_name .. ".vtf" or info.file_name == vtf_name then new_path = dir .. vtf_name @@ -644,12 +693,11 @@ function pac.DownloadMDL(url, callback, onfail, ply) end if not new_path then - if not file.Exists("materials/" .. vtf_path .. ".vtf", "GAME") then - if ply == pac.LocalPlayer then - pac.Message(Color(255, 50, 50), "vmt ", data.file_name, " wants to find texture materials/", vtf_path, ".vtf for $", shader_param ," but it doesn't exist") - print(data.buffer) - end + if is_localplayer and not file.Exists("materials/" .. vtf_path .. ".vtf", "GAME") then + pac.Message(Color(255, 50, 50), "vmt ", data.file_name, " wants to find texture materials/", vtf_path, ".vtf for $", shader_param, " but it doesn't exist") + print(data.buffer) end + new_path = vtf_path -- maybe it's a special texture? in that case i need to it end @@ -699,21 +747,28 @@ function pac.DownloadMDL(url, callback, onfail, ply) f:Write("author here")f:WriteByte(0) f:WriteLong(1) - for i, data in ipairs(files) do + for i = 1, #files do + local data = files[i] + f:WriteLong(i) + if data.file_name:EndsWith(".vtf") or data.file_name:EndsWith(".vmt") then - f:Write("materials/" .. dir .. data.file_name:lower())f:WriteByte(0) + f:Write("materials/" .. dir .. data.file_name:lower()) + f:WriteByte(0) else - f:Write("models/" .. dir .. data.file_name:lower())f:WriteByte(0) + f:Write("models/" .. dir .. data.file_name:lower()) + f:WriteByte(0) end - f:WriteLong(#data.buffer)f:WriteLong(0) + + f:WriteLong(#data.buffer) + f:WriteLong(0) f:WriteLong(data.crc) end f:WriteLong(0) - for i, data in ipairs(files) do - f:Write(data.buffer) + for i = 1, #files do + f:Write(files[i].buffer) end f:Flush() @@ -730,7 +785,10 @@ function pac.DownloadMDL(url, callback, onfail, ply) return end - for k,v in pairs(tbl) do + -- tbl from game.MountGMA is a sequential list of file paths + for i = 1, #tbl do + local v = tbl[i] + if v:EndsWith("model.mdl") then if VERBOSE and not DEBUG_MDL then print("util.IsValidModel: ", tostring(util.IsValidModel(v))) diff --git a/lua/pac3/editor/client/animation_timeline.lua b/lua/pac3/editor/client/animation_timeline.lua index 687feabb7..f713a182f 100644 --- a/lua/pac3/editor/client/animation_timeline.lua +++ b/lua/pac3/editor/client/animation_timeline.lua @@ -484,13 +484,21 @@ do local menu = DermaMenu() menu:SetPos(load:LocalToScreen()) - for _, name in pairs(file.Find("animations/*.txt", "DATA")) do + local files = file.Find("animations/*.txt", "DATA") + + for i = 1, #files do + local name = files[i] + menu:AddOption(name:match("(.+)%.txt"), function() timeline.Load(util.JSONToTable(file.Read("animations/" .. name))) end) end - for _, name in pairs(file.Find("pac3/__animations/*.txt", "DATA")) do + files = file.Find("animations/*.txt", "DATA") + + for i = 1, #files do + local name = files[i] + menu:AddOption(name:match("(.+)%.txt"), function() timeline.Load(util.JSONToTable(file.Read("pac3/__animations/" .. name))) end) @@ -500,10 +508,10 @@ do local x, y = bottom:LocalToScreen(0, 0) x = x + bottom:GetWide() + menu:SetPos(x - menu:GetWide(), y - menu:GetTall()) end end - end do -- keyframes @@ -529,16 +537,23 @@ do function pnl.PerformLayout() old(pnl) + local canvas = pnl:GetCanvas() local h = self:GetTall() - 45 - pnl:GetCanvas():SetTall(h) + + canvas:SetTall(h) if self.moving then return end local x = 0 - for k, v in ipairs(pnl:GetCanvas():GetChildren()) do - v:SetWide(math.max(1/v:GetData().FrameRate * secondDistance, 4)) + + local children = canvas:GetChildren() + for i = 1, #children do + local v = children[i] + + v:SetWide(math.max(1 / v:GetData().FrameRate * secondDistance, 4)) v:SetTall(h) v:SetPos(x, 0) + x = x + v:GetWide() end end @@ -579,7 +594,8 @@ do local restart = Material("icon16/control_repeat_blue.png") local estyle = Material("icon16/arrow_branch.png") pnl.Paint = function(s, w, h) - local offset = -self.keyframe_scroll:GetCanvas():GetPos() + local scroll_canvas = self.keyframe_scroll:GetCanvas() + local offset = -scroll_canvas:GetPos() self:GetSkin().tex.Tab_Control( 0, 0, w, h ) self:GetSkin().tex.CategoryList.Header( 0, 0, w, h ) @@ -608,45 +624,51 @@ do end end - for i = previousSecond, previousSecond+s:GetWide(), secondDistance/8 do - if i-offset > 0 and i-offset < ScrW() then - local x = i-offset + for i = previousSecond, previousSecond + s:GetWide(), secondDistance / 8 do + local x = i - offset + if x > 0 and x < ScrW() then surface.SetDrawColor(0, 0, 0, 100) - surface.DrawLine(x+1, 1+1, x+1, pnl:GetTall()/2+1) + surface.DrawLine(x + 1, 1 + 1, x + 1, pnl:GetTall() / 2 + 1) surface.SetDrawColor(self:GetSkin().Colours.Category.Header) - surface.DrawLine(x, 1, x, pnl:GetTall()/2) + surface.DrawLine(x, 1, x, pnl:GetTall() / 2) end end - local h = self.keyframe_scroll:GetCanvas():GetTall() + pnl:GetTall() + local h = scroll_canvas:GetTall() + pnl:GetTall() + if self.keyframe_scroll:GetVBar():IsVisible() then h = h - self.keyframe_scroll:GetVBar():GetTall() + 5 end - for i, v in ipairs(self.keyframe_scroll:GetCanvas():GetChildren()) do + local children = scroll_canvas:GetChildren() + for i = 1, #children do + local v = children[i] + local mat = v.restart and restart or v.start and start or false local esmat = v.estyle and estyle or false if mat then local x = v:GetPos() - offset if x > s:GetWide() - 10 then continue end + surface.SetDrawColor(255, 255, 255, 200) - surface.DrawLine(x, -mat:Height()/2 - 5, x, h) + surface.DrawLine(x, -mat:Height() / 2 - 5, x, h) surface.SetDrawColor(255, 255, 255, 255) surface.SetMaterial(mat) - surface.DrawTexturedRect(1+x, mat:Height() - 5, mat:Width(), mat:Height()) - + surface.DrawTexturedRect(1 + x, mat:Height() - 5, mat:Width(), mat:Height()) end if esmat then local ps = v:GetSize() local x = v:GetPos() - offset + (ps * 0.5) if x > s:GetWide() - 10 then continue end + surface.SetDrawColor(255, 255, 255, 255) surface.SetMaterial(esmat) - surface.DrawTexturedRect(1+x - (esmat:Width() * 0.5), esmat:Height(), esmat:Width(), esmat:Height()) + surface.DrawTexturedRect(1 + x - (esmat:Width() * 0.5), esmat:Height(), esmat:Width(), esmat:Height()) + if ps >= 65 then draw.SimpleText( v.estyle, pace.CurrentFont, x, esmat:Height() * 2, self:GetSkin().Colours.Label.Dark, TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP ) else @@ -657,7 +679,7 @@ do if not timeline.animation_part then return end - local x = timeline.GetCycle() * self.keyframe_scroll:GetCanvas():GetWide() + local x = timeline.GetCycle() * scroll_canvas:GetWide() x = x - offset surface.SetDrawColor(255, 0, 0, 200) @@ -665,24 +687,24 @@ do surface.SetDrawColor(255, 0, 0, 255) surface.SetMaterial(scrub) - surface.DrawTexturedRect(1 + x - scrub:Width()/2, -11, scrub:Width(), scrub:Height()) + surface.DrawTexturedRect(1 + x - scrub:Width() * 0.5, -11, scrub:Width(), scrub:Height()) end end end function TIMELINE:Paint(w, h) - self:GetSkin().tex.Tab_Control(0, 35, w, h-35) + self:GetSkin().tex.Tab_Control(0, 35, w, h - 35) end function TIMELINE:Think() DFrame.Think(self) if pace.Editor:GetPos() + pace.Editor:GetWide() / 2 < ScrW() / 2 then - self:SetSize(ScrW()-(pace.Editor.x+pace.Editor:GetWide()), 93) - self:SetPos(pace.Editor.x+pace.Editor:GetWide(), ScrH()-self:GetTall()) + self:SetSize(ScrW() - (pace.Editor.x + pace.Editor:GetWide()), 93) + self:SetPos(pace.Editor.x + pace.Editor:GetWide(), ScrH() - self:GetTall()) else - self:SetSize(ScrW()-(ScrW()-pace.Editor.x), 93) - self:SetPos(0, ScrH()-self:GetTall()) + self:SetSize(ScrW() - (ScrW() - pace.Editor.x), 93) + self:SetPos(0, ScrH() - self:GetTall()) end if input.IsKeyDown(KEY_SPACE) then @@ -739,9 +761,11 @@ do end function TIMELINE:Clear() - for i, v in pairs(self.keyframe_scroll:GetCanvas():GetChildren()) do - v:Remove() + local children = self.keyframe_scroll:GetCanvas():GetChildren() + for i = 1, #children do + children[i]:Remove() end + self.add_keyframe_button:SetDisabled(false) end @@ -749,9 +773,9 @@ do local total = 0 if timeline.data and timeline.data.FrameData then - for i=1, #timeline.data.FrameData do + for i = 1, #timeline.data.FrameData do local v = timeline.data.FrameData[i] - total = total+(1/(v.FrameRate or 1)) + total = total + (1 / (v.FrameRate or 1)) end end @@ -764,9 +788,11 @@ do local restartFrame = timeline.data.RestartFrame if not restartFrame then return 0 end --no restart pos? start at the start - for i, v in ipairs(timeline.data.FrameData) do + for i = 1, #timeline.data.FrameData do if i == restartFrame then return timeInSeconds end - timeInSeconds = timeInSeconds+(1/(v.FrameRate or 1)) + + local v = timeline.data.FrameData[i] + timeInSeconds = timeInSeconds + (1 / (v.FrameRate or 1)) end return 0 @@ -778,9 +804,11 @@ do local startFrame = timeline.data.StartFrame if not startFrame then return 0 end --no restart pos? start at the start - for i, v in ipairs(timeline.data.FrameData) do + for i = 1, #timeline.data.FrameData do if i == startFrame then return timeInSeconds end - timeInSeconds = timeInSeconds+(1/(v.FrameRate or 1)) + + local v = timeline.data.FrameData[i] + timeInSeconds = timeInSeconds + (1 / (v.FrameRate or 1)) end return 0 @@ -799,7 +827,7 @@ do keyframe:SetParent(self.keyframe_scroll) self.keyframe_scroll:InvalidateLayout() - keyframe.Alternate = #timeline.frame.keyframe_scroll:GetCanvas():GetChildren()%2 == 1 + keyframe.Alternate = #timeline.frame.keyframe_scroll:GetCanvas():GetChildren() % 2 == 1 return keyframe end @@ -899,24 +927,29 @@ do local panels = {} local frames = {} - for k, v in pairs(timeline.frame.keyframe_scroll:GetCanvas():GetChildren()) do + local canvas_children = timeline.frame.keyframe_scroll:GetCanvas():GetChildren() + for i = 1, #canvas_children do + local v = canvas_children[i] + table.insert(panels, v) v:SetParent() end table.sort(panels, function(a, b) - return (a:GetPos() + a:GetWide() / 2) < (b:GetPos() + b:GetWide() / 2) + return (a:GetPos() + a:GetWide() * 0.5) < (b:GetPos() + b:GetWide() * 0.5) end) - for i, v in ipairs(panels) do + for i = 1, #panels do + local v = panels[i] + v:SetParent(timeline.frame.keyframe_scroll) - v.Alternate = #timeline.frame.keyframe_scroll:GetCanvas():GetChildren()%2 == 1 + v.Alternate = #canvas_children % 2 == 1 frames[i] = timeline.data.FrameData[v:GetAnimationIndex()] end - for i, v in ipairs(frames) do - timeline.data.FrameData[i] = v + for i = 1, #frames do + timeline.data.FrameData[i] = frames[i] panels[i].AnimationKeyIndex = i end @@ -924,6 +957,7 @@ do self:SetCursor("hand") self.move = nil self.move_x = nil + timeline.frame.moving = false end end @@ -975,30 +1009,38 @@ do if not self:GetRestart() then menu:AddOption(L"set restart", function() - for _, v in pairs(timeline.frame.keyframe_scroll:GetCanvas():GetChildren()) do - v:SetRestart(false) + local children = timeline.frame.keyframe_scroll:GetCanvas():GetChildren() + for i = 1, #children do + children[i]:SetRestart(false) end + self:SetRestart(true) + timeline.data.RestartFrame = self:GetAnimationIndex() end):SetImage("icon16/control_repeat_blue.png") else menu:AddOption(L"unset restart", function() self:SetRestart(false) + timeline.data.StartFrame = nil end):SetImage("icon16/control_repeat.png") end if not self:GetStart() then menu:AddOption(L"set start", function() - for _, v in pairs(timeline.frame.keyframe_scroll:GetCanvas():GetChildren()) do - v:SetStart(false) + local children = timeline.frame.keyframe_scroll:GetCanvas():GetChildren() + for i = 1, #children do + children[i]:SetStart(false) end + self:SetStart(true) + timeline.data.StartFrame = self:GetAnimationIndex() end):SetImage("icon16/control_play_blue.png") else menu:AddOption(L"unset start", function() self:SetStart(false) + timeline.data.StartFrame = nil end):SetImage("icon16/control_play.png") end @@ -1039,11 +1081,17 @@ do menu:AddOption(L"remove", function() local frameNum = self:GetAnimationIndex() if frameNum == 1 and not timeline.data.FrameData[2] then return end + table.remove(timeline.data.FrameData, frameNum) local remove_i - for i, v in pairs(timeline.frame.keyframe_scroll:GetCanvas():GetChildren()) do + local scroll_canvas = timeline.frame.keyframe_scroll:GetCanvas() + local children = scroll_canvas:GetChildren() + + for i = 1, #children do + local v = children[i] + if v == self then remove_i = i elseif v:GetAnimationIndex() > frameNum then @@ -1052,15 +1100,18 @@ do end end - table.remove(timeline.frame.keyframe_scroll:GetCanvas():GetChildren(), remove_i) + table.remove(scroll_canvas:GetChildren(), remove_i) timeline.frame.keyframe_scroll:InvalidateLayout() self:Remove() - local count = #timeline.frame.keyframe_scroll:GetCanvas():GetChildren() + children = scroll_canvas:GetChildren() + + local count = #children local offset = remove_i >= count and count - 1 or remove_i + 1 - timeline.SelectKeyframe(timeline.frame.keyframe_scroll:GetCanvas():GetChildren()[offset]) + + timeline.SelectKeyframe(children[offset]) end):SetImage("icon16/page_delete.png") menu:AddOption(L"set easing style", function() diff --git a/lua/pac3/editor/client/asset_browser.lua b/lua/pac3/editor/client/asset_browser.lua index 7e9542acc..bca065889 100644 --- a/lua/pac3/editor/client/asset_browser.lua +++ b/lua/pac3/editor/client/asset_browser.lua @@ -586,19 +586,19 @@ do self.ZoomText:SetText(math.Round(num, 1) .. "%") end - vgui.Register( "pac_AssetBrowser_ZoomControls", PANEL, "DPanel" ) + vgui.Register("pac_AssetBrowser_ZoomControls", PANEL, "DPanel") end do local PANEL = {} - local BaseClass = baseclass.Get( "DScrollPanel" ) + local BaseClass = baseclass.Get("DScrollPanel") function PANEL:Init() - self:SetPaintBackground( false ) + self:SetPaintBackground(false) - self.IconList = vgui.Create( "DPanel", self:GetCanvas()) - self.IconList:Dock( TOP ) + self.IconList = vgui.Create("DPanel", self:GetCanvas()) + self.IconList:Dock(TOP) function self.IconList:PerformLayout() if not self.invalidate then return end @@ -609,7 +609,10 @@ do local total_width - for _, child in ipairs(self:GetChildren()) do + local children = self:GetChildren() + for i = 1, #children do + local child = children[i] + height = math.max(height, child:GetTall()) if x + child:GetWide() > max_width then @@ -625,9 +628,11 @@ do end if total_width then - for _, child in ipairs(self:GetChildren()) do + for i = 1, #children do + local child = children[i] + local x, y = child:GetPos() - child:SetPos(x - total_width/2, y) + child:SetPos(x - total_width * 0.5, y) end end @@ -637,7 +642,7 @@ do function PANEL:Add(pnl) pnl.ready_to_draw = true - pnl.original_size = {w=pnl:GetWide(),h=pnl:GetTall()} + pnl.original_size = {w = pnl:GetWide(), h = pnl:GetTall()} if self.ZoomControls then pnl:SetSize(pnl.original_size.w * self.ZoomControls.zoom * 0.01, pnl.original_size.h * self.ZoomControls.zoom * 0.01) end @@ -652,7 +657,9 @@ do function PANEL:CalcZoom() if self.ZoomControls then - for i,v in ipairs(self.IconList:GetChildren()) do + local children = self.IconList:GetChildren() + for i = 1, #children do + local v = children[i] v:SetSize(v.original_size.w * self.ZoomControls.zoom * 0.01, v.original_size.h * self.ZoomControls.zoom * 0.01) end self.IconList.invalidate = true @@ -668,12 +675,13 @@ do end function PANEL:Clear() - for k,v in ipairs(self.IconList:GetChildren()) do - v:Remove() + local children = self.IconList:GetChildren() + for i = 1, #children do + children[i]:Remove() end end - vgui.Register( "pac_AssetBrowser_ContentContainer", PANEL, "DScrollPanel" ) + vgui.Register("pac_AssetBrowser_ContentContainer", PANEL, "DScrollPanel") end function pace.AssetBrowser(callback, browse_types_str, part_key) @@ -1213,12 +1221,13 @@ function pace.AssetBrowser(callback, browse_types_str, part_key) local count = 0 local function find_recursive(path, pathid) if count >= 500 then return end - local files_, folders_ = file.Find(path .. "/*", pathid) - if files_ then - for i,v in ipairs(files_) do + + local files, folders = file.Find(path .. "/*", pathid) + if files then + for i = 1, #files do count = count + 1 - local path = path .. "/" .. v + local path = path .. "/" .. files[i] path = path:gsub("^.-(" .. browse_types[1] .. "/.+)$", "%1") @@ -1238,11 +1247,13 @@ function pace.AssetBrowser(callback, browse_types_str, part_key) sound_list:AddSound(path, pathid) end end - for i,v in ipairs(folders_) do - find_recursive(path .. "/" .. v, pathid) + + for i = 1, #folders do + find_recursive(path .. "/" .. folders[i], pathid) end end end + find_recursive(path .. browse_types[1], node:GetPathID()) else local files, folders = file.Find(searchString .. "/*", node:GetPathID()) @@ -1275,8 +1286,8 @@ function pace.AssetBrowser(callback, browse_types_str, part_key) end ]] if self.dir == "models" then - for k, v in pairs(files) do - local path = node:GetFolder() .. "/" .. v + for i = 1, #files do + local path = node:GetFolder() .. "/" .. files[i] if not path:StartWith("models/pac3_cache/") then if not IsUselessModel(path) then @@ -1285,7 +1296,8 @@ function pace.AssetBrowser(callback, browse_types_str, part_key) end end elseif self.dir == "materials" then - for k, v in pairs(files) do + for i = 1, #files do + local v = files[i] local path = node:GetFolder() .. "/" .. v if v:find("%.vmt$") then @@ -1298,8 +1310,8 @@ function pace.AssetBrowser(callback, browse_types_str, part_key) end elseif self.dir == "sound" then - for k, v in pairs(files) do - local path = node:GetFolder() .. "/" .. v + for i = 1, #files do + local path = node:GetFolder() .. "/" .. files[i] sound_list:AddSound(path, pathid) end end @@ -1377,7 +1389,8 @@ function pace.AssetBrowser(callback, browse_types_str, part_key) }, } - for _, info in ipairs(special) do + for i = 1, #special do + local info = special[i] addBrowseContent(viewPanel, root_node, info.title, info.icon, "", info.folder) end end @@ -1415,7 +1428,9 @@ function pace.AssetBrowser(callback, browse_types_str, part_key) local _, folders = file.Find("addons/*", "MOD") - for _, path in ipairs(folders) do + for i = 1, #folders do + local path = folders[i] + if file.IsDir("addons/" .. path .. "/materials", "MOD") or file.IsDir("addons/" .. path .. "/sound", "MOD") or @@ -1489,7 +1504,6 @@ function pace.AssetBrowser(callback, browse_types_str, part_key) end function search:StartSearch(search_text, folder, extensions, pathid, cb) - cancel:SetVisible(true) local files, folders = find(folder .. "*", pathid) @@ -1499,18 +1513,23 @@ function pace.AssetBrowser(callback, browse_types_str, part_key) if files then update_title(table.Count(self.delay_functions) .. " directories left - " .. folder .. "*") - for k, v in ipairs(files) do + for i = 1, #files do + local v = files[i] local file = folder .. v + for _, ext in ipairs(extensions) do if v:EndsWith(ext) and file:find(search_text, nil, true) then local func = function() return cb(file, pathid) end self.delay_functions[func] = func + break end end end - for k, v in ipairs(folders) do + for i = 1, #folders do + local v = folders[i] + if v ~= "pac3_cache" then local func = function() self:StartSearch(search_text, folder .. v .. "/", extensions, pathid, cb) @@ -1557,6 +1576,7 @@ function pace.AssetBrowser(callback, browse_types_str, part_key) self:Cancel(reason) return end + self.delay_functions[func] = nil if i > 50 then break end end diff --git a/lua/pac3/editor/client/init.lua b/lua/pac3/editor/client/init.lua index 7de793b69..80f99e550 100644 --- a/lua/pac3/editor/client/init.lua +++ b/lua/pac3/editor/client/init.lua @@ -36,48 +36,6 @@ include("wires.lua") include("wear_filter.lua") include("show_outfit_on_use.lua") -do - local hue = - { - "red", - "orange", - "yellow", - "green", - "turquoise", - "blue", - "purple", - "magenta", - } - - local sat = - { - "pale", - "", - "strong", - } - - local val = - { - "dark", - "", - "bright" - } - - function pace.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 pace.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 pace.HSVToNames(ColorToHSV(Color(c.r, c.g, c.b))) - end - -end - function pace.CallHook(str, ...) return hook.Call("pace_" .. str, GAMEMODE, ...) end @@ -217,7 +175,7 @@ function pace.Panic() pace.SafeRemoveSpecialPanel() - for i, ent in ipairs(ents.GetAll()) do + for _, ent in ents.Iterator() do if ent:IsValid() then ent.pac_onuse_only = nil ent.pac_onuse_only_check = nil @@ -403,8 +361,8 @@ do end net.Receive("pac_in_editor_posang", function() - local ply = net.ReadEntity() - if not IsValid( ply ) then return end + local ply = net.ReadPlayer() + if not IsValid(ply) then return end local pos = net.ReadVector() local ang = net.ReadAngle() diff --git a/lua/pac3/editor/client/language.lua b/lua/pac3/editor/client/language.lua index d9d214be5..f2c36dfc2 100644 --- a/lua/pac3/editor/client/language.lua +++ b/lua/pac3/editor/client/language.lua @@ -15,16 +15,22 @@ local L = pace.LanguageString function pace.AddLanguagesToMenu(menu) local menu, pnl = menu:AddSubMenu(L"language") + pnl:SetImage("icon16/world_edit.png") + menu.GetDeleteSelf = function() return false end menu:AddOption("english", function() pace.SetLanguage("english") end) - for key, val in pairs(file.Find("pac3/editor/client/translations/*", "LUA")) do - val = val:gsub("%.lua", "") - menu:AddOption(val, function() - pace.SetLanguage(val) + local files = file.Find("pac3/editor/client/translations/*", "LUA") + + for i = 1, #files do + local path = files[i] + + path = path:gsub("%.lua", "") + menu:AddOption(path, function() + pace.SetLanguage(path) end) end @@ -56,11 +62,12 @@ function pace.ShowLanguageEditor() table.Merge(strings, pace.CurrentTranslation) for english, other in pairs(strings) do - local line = list:AddLine(english, other) + line.OnRightClick = function() local menu = DermaMenu() menu:SetPos(input.GetCursorPos()) + menu:AddOption(L"edit", function() local window = Derma_StringRequest( L"translate", @@ -73,16 +80,24 @@ function pace.ShowLanguageEditor() pace.SaveCurrentTranslation() end ) - for _, pnl in pairs(window:GetChildren()) do + + local window_children = window:GetChildren() + for i = 1, #window_children do + local pnl = window_children[i] + if pnl.ClassName == "DPanel" then - for key, pnl in pairs(pnl:GetChildren()) do - if pnl.ClassName == "DTextEntry" then - pnl:SetAllowNonAsciiCharacters(true) + local pnl_children = pnl:GetChildren() + for x = 1, #pnl_children do + local pnl2 = pnl_children[x] + + if pnl2.ClassName == "DTextEntry" then + pnl2:SetAllowNonAsciiCharacters(true) end end end end end):SetImage(pace.MiscIcons.edit) + menu:AddOption(L"revert", function() local new = CompileFile("pac3/editor/client/translations/"..lang..".lua")()[english] pace.CurrentTranslation[english] = new diff --git a/lua/pac3/editor/client/panels.lua b/lua/pac3/editor/client/panels.lua index 73c16baaf..b18fd9b1b 100644 --- a/lua/pac3/editor/client/panels.lua +++ b/lua/pac3/editor/client/panels.lua @@ -44,7 +44,7 @@ function pace.RegisterPanels() files = file.Find("pac3/editor/client/panels/*.lua", "LUA") end - for _, name in pairs(files) do - include("pac3/editor/client/panels/" .. name) + for i = 1, #files do + include("pac3/editor/client/panels/" .. files[i]) end end diff --git a/lua/pac3/editor/client/panels/browser.lua b/lua/pac3/editor/client/panels/browser.lua index ef8f8d519..e51938928 100644 --- a/lua/pac3/editor/client/panels/browser.lua +++ b/lua/pac3/editor/client/panels/browser.lua @@ -30,7 +30,10 @@ local function OnMousePressed(self, mcode) end function PANEL:AddOutfits(folder, callback) - for i, name in pairs(file.Find(folder.."*", "DATA")) do + local files = file.Find(folder .. "*", "DATA") + for i = 1, #files do + local name = files[i] + if name:find("%.txt") then local outfit = folder .. name if file.Exists(outfit, "DATA") then @@ -39,6 +42,7 @@ function PANEL:AddOutfits(folder, callback) string.NiceSize(file.Size(outfit, "DATA")), os.date("%m/%d/%Y %H:%M", file.Time(outfit, "DATA")) ) + filenode.FileName = name filenode.OnSelect = callback filenode.OnMousePressed = OnMousePressed diff --git a/lua/pac3/editor/client/panels/extra_properties.lua b/lua/pac3/editor/client/panels/extra_properties.lua index 65f04b10d..7ac0a07a0 100644 --- a/lua/pac3/editor/client/panels/extra_properties.lua +++ b/lua/pac3/editor/client/panels/extra_properties.lua @@ -8,8 +8,9 @@ local function populate_part_menu(menu, part, func) pnl:SetImage(part.Icon) - for key, part in ipairs(part:GetChildren()) do - populate_part_menu(menu, part, func) + local children = part:GetChildren() + for i = 1, #children do + populate_part_menu(menu, children[i], func) end else menu:AddOption(pace.pac_show_uniqueid:GetBool() and string.format("%s (%s)", part:GetName(), part:GetPrintUniqueID()) or part:GetName(), function() @@ -18,7 +19,6 @@ local function populate_part_menu(menu, part, func) end end - local function get_friendly_name(ent) if not IsValid(ent) then return "NULL" end local name = ent.GetName and ent:GetName() @@ -27,7 +27,6 @@ local function get_friendly_name(ent) end if ent:EntIndex() == -1 then - if name == "10C_BaseFlex" then return "csentity - " .. ent:GetModel() end @@ -66,7 +65,7 @@ do -- bone menu:MakePopup() local list = {} - for k,v in pairs(bones) do + for k, v in pairs(bones) do table.insert(list, v.friendly) end @@ -109,7 +108,6 @@ do -- part end function PANEL:DecodeEdit(name) - if name:Trim() ~= "" then local part = pac.FindPartByName(pac.Hash(pac.LocalPlayer), name, pace.current_part) if part:IsValid() then @@ -126,7 +124,6 @@ do -- part if IsValid(self.Icon) then self.Icon:Remove() end - if not part:IsValid() then if self.CurrentKey == "TargetEntityUID" then local owner = pace.current_part:GetOwner() @@ -311,7 +308,7 @@ do -- owner local entities = menu:AddSubMenu(L"entities", function() end) entities.GetDeleteSelf = function() return false end - for _, ent in pairs(ents.GetAll()) do + for _, ent in ents.Iterator() do if ent:EntIndex() > 0 then entities:AddOption(get_friendly_name(ent), function() pace.current_part:SetOwnerName(ent:EntIndex()) @@ -827,8 +824,8 @@ do -- event is_touching elseif part:GetEvent() == "is_touching_life" then local found = false local ents_hits = ents.FindInBox(startpos + mins, startpos + maxs) - for _,ent2 in pairs(ents_hits) do - + for i = 1, #ents_hits do + local ent2 = ents_hits[i] if IsValid(ent2) and (ent2 ~= ent and ent2 ~= part:GetRootPart():GetOwner()) and (ent2:IsNPC() or ent2:IsPlayer()) then @@ -843,16 +840,17 @@ do -- event is_touching end elseif part:GetEvent() == "is_touching_filter" then local ents_hits = ents.FindInBox(startpos + mins, startpos + maxs) - for _,ent2 in pairs(ents_hits) do + for i = 1, #ents_hits do + local ent2 = ents_hits[i] if (ent2 ~= ent and ent2 ~= part:GetRootPart():GetOwner()) and (ent2:IsNPC() or ent2:IsPlayer()) and - not ( (no_npc and ent2:IsNPC()) or (no_players and ent2:IsPlayer()) ) + not ((no_npc and ent2:IsNPC()) or (no_players and ent2:IsPlayer())) then b = true end end end if self.udata then - render.DrawWireframeBox( startpos, Angle( 0, 0, 0 ), mins, maxs, b and Color(255,0,0) or Color(255,255,255), true ) + render.DrawWireframeBox(startpos, angle_zero, mins, maxs, b and Color(255,0,0) or color_white, true) end end) end @@ -891,17 +889,19 @@ do -- event seen_by_player if not IsValid(ent) then stop() return end - local mins = Vector(-extra_radius,-extra_radius,-extra_radius) - local maxs = Vector(extra_radius,extra_radius,extra_radius) + local local_center + local min_radius, max_radius = Vector(-extra_radius, -extra_radius, -extra_radius), Vector(extra_radius, extra_radius, extra_radius) local b = false local players_see = {} - for _,v in ipairs(player.GetAll()) do + for _, v in player.Iterator() do if v == ent then continue end local eyetrace = v:GetEyeTrace() + local_center = local_center or pac.LocalPlayer:GetPos() + pac.LocalPlayer:OBBCenter() + local this_player_sees = false - if util.IntersectRayWithOBB(eyetrace.StartPos, eyetrace.HitPos - eyetrace.StartPos, LocalPlayer():GetPos() + LocalPlayer():OBBCenter(), Angle(0,0,0), Vector(-extra_radius,-extra_radius,-extra_radius), Vector(extra_radius,extra_radius,extra_radius)) then + if util.IntersectRayWithOBB(eyetrace.StartPos, eyetrace.HitPos - eyetrace.StartPos, local_center, angle_zero, min_radius, max_radius) then b = true this_player_sees = true end @@ -909,11 +909,11 @@ do -- event seen_by_player b = true this_player_sees = true end - render.DrawLine(eyetrace.StartPos, eyetrace.HitPos, this_player_sees and Color(255, 0,0) or Color(255,255,255), true) + render.DrawLine(eyetrace.StartPos, eyetrace.HitPos, this_player_sees and Color(255, 0,0) or color_white, true) end ::CHECKOUT:: if self.udata then - render.DrawWireframeBox( ent:GetPos() + ent:OBBCenter(), Angle( 0, 0, 0 ), mins, maxs, b and Color(255,0,0) or Color(255,255,255), true ) + render.DrawWireframeBox(ent:GetPos() + ent:OBBCenter(), angle_zero, min_radius, max_radius, b and Color(255,0,0) or color_white, true) end end) end @@ -942,13 +942,13 @@ do --projectile radius if pace.current_part.ClassName ~= "projectile" then stop() return end if self.udata then if last_part.Sphere then - render.DrawWireframeSphere( last_part:GetWorldPosition(), last_part.Radius, 10, 10, Color(255,255,255), true ) - render.DrawWireframeSphere( last_part:GetWorldPosition(), last_part.DamageRadius, 10, 10, Color(255,0,0), true ) + render.DrawWireframeSphere(last_part:GetWorldPosition(), last_part.Radius, 10, 10, color_white, true) + render.DrawWireframeSphere(last_part:GetWorldPosition(), last_part.DamageRadius, 10, 10, Color(255,0,0), true) else local mins_ph = Vector(last_part.Radius,last_part.Radius,last_part.Radius) local mins_dm = Vector(last_part.DamageRadius,last_part.DamageRadius,last_part.DamageRadius) - render.DrawWireframeBox( last_part:GetWorldPosition(), last_part:GetWorldAngles(), -mins_ph, mins_ph, Color(255,255,255), true ) - render.DrawWireframeBox( last_part:GetWorldPosition(), last_part:GetWorldAngles(), -mins_dm, mins_dm, Color(255,0,0), true ) + render.DrawWireframeBox(last_part:GetWorldPosition(), last_part:GetWorldAngles(), -mins_ph, mins_ph, color_white, true) + render.DrawWireframeBox(last_part:GetWorldPosition(), last_part:GetWorldAngles(), -mins_dm, mins_dm, Color(255,0,0), true) end end diff --git a/lua/pac3/editor/client/panels/pac_tree.lua b/lua/pac3/editor/client/panels/pac_tree.lua index 994497cc0..650f66650 100644 --- a/lua/pac3/editor/client/panels/pac_tree.lua +++ b/lua/pac3/editor/client/panels/pac_tree.lua @@ -317,9 +317,11 @@ end function PANEL:DoChildrenOrder() if not self.ChildNodes then return end - local last = table.Count(self.ChildNodes:GetChildren()) - for k, Child in pairs(self.ChildNodes:GetChildren()) do - Child:SetLastChild(k == last) + local children = self.ChildNodes:GetChildren() + local last = #children + + for i = 1, last do + children[i]:SetLastChild(i == last) end end @@ -530,15 +532,16 @@ end function PANEL:Copy() local copy = vgui.Create("pac_dtree_node", self:GetParent()) + copy:SetText(self:GetText()) copy:SetIcon(self:GetIcon()) copy:SetRoot(self:GetRoot()) copy:SetParentNode(self:GetParentNode()) if self.ChildNodes then - for k, v in pairs(self.ChildNodes:GetChildren()) do - local childcopy = v:Copy() - copy:InsertNode(childcopy) + local children = self.ChildNodes:GetChildren() + for i = 1, #children do + copy:InsertNode(children[i]:Copy()) end end diff --git a/lua/pac3/editor/client/panels/tree.lua b/lua/pac3/editor/client/panels/tree.lua index 2fd6dff24..ec91ac685 100644 --- a/lua/pac3/editor/client/panels/tree.lua +++ b/lua/pac3/editor/client/panels/tree.lua @@ -1,6 +1,7 @@ -CreateClientConVar("pac_editor_scale","1", true, false) local L = pace.LanguageString +local pac_editor_scale = CreateClientConVar("pac_editor_scale", "1", true, false) + local PANEL = {} PANEL.ClassName = "tree" @@ -9,7 +10,7 @@ PANEL.Base = "pac_dtree" function PANEL:Init() pace.pac_dtree.Init(self) - self:SetLineHeight(18 * GetConVar("pac_editor_scale"):GetFloat()) + self:SetLineHeight(18 * pac_editor_scale:GetFloat()) self:SetIndentSize(10) self.parts = {} @@ -20,14 +21,14 @@ function PANEL:Init() end do - local function get_added_nodes(self) local added_nodes = {} - for i,v in ipairs(self.added_nodes) do + for i, v in ipairs(self.added_nodes) do if v.part and v:IsVisible() and v:IsExpanded() then table.insert(added_nodes, v) end end + table.sort(added_nodes, function(a, b) return select(2, a:LocalToScreen()) < select(2, b:LocalToScreen()) end) return added_nodes end @@ -160,8 +161,8 @@ do if not node.Icon.event_icon then local pnl = vgui.Create("DImage", node.Icon) pnl:SetImage("icon16/clock_red.png") - pnl:SetSize(8*(1 + 0.5*(GetConVar("pac_editor_scale"):GetFloat()-1)), 8*(1 + 0.5*(GetConVar("pac_editor_scale"):GetFloat()-1))) - pnl:SetPos(8*(1 + 0.5*(GetConVar("pac_editor_scale"):GetFloat()-1)), 8*(1 + 0.5*(GetConVar("pac_editor_scale"):GetFloat()-1))) + pnl:SetSize(8 * (1 + 0.5 * (pac_editor_scale:GetFloat() - 1)), 8 * (1 + 0.5 * (pac_editor_scale:GetFloat() - 1))) + pnl:SetPos(8 * (1 + 0.5 * (pac_editor_scale:GetFloat() - 1)), 8 * (1 + 0.5 * (pac_editor_scale:GetFloat() - 1))) pnl:SetVisible(false) node.Icon.event_icon = pnl end @@ -258,12 +259,8 @@ do function pace.DoScrollControls(action) DoScrollControl(pace.tree, action) end - end - - - function PANEL:OnMouseReleased(mc) if mc == MOUSE_RIGHT then pace.Call("PartMenu") @@ -333,7 +330,6 @@ local function install_drag(node) end function node:DroppedOn(child) - if not child.part then child = child:GetParent() end @@ -349,7 +345,6 @@ local function install_drag(node) pace.RecordUndoHistory() end end - end end @@ -423,7 +418,6 @@ end -- a hack, because creating a new node button will mess up the layout function PANEL:AddNode(...) - if self.RootNode then install_drag(self.RootNode) end @@ -434,7 +428,7 @@ function PANEL:AddNode(...) local add_button = node:Add("DImageButton") add_button:SetImage(pace.MiscIcons.new) - add_button:SetSize(16*GetConVar("pac_editor_scale"):GetFloat(), 16*GetConVar("pac_editor_scale"):GetFloat()) + add_button:SetSize(16 * pac_editor_scale:GetFloat(), 16 * pac_editor_scale:GetFloat()) add_button:SetVisible(false) add_button.DoClick = function() add_parts_menu(node) pace.Call("PartSelected", node.part) end add_button.DoRightClick = function() node:DoRightClick() end @@ -483,8 +477,9 @@ function PANEL:PopulateParts(node, parts, children) end end - for key, part in pairs(tbl) do - key = part.Id + for i = 1, #tbl do + local part = tbl[i] + local key = part.Id if not part:GetShowInEditor() then goto CONTINUE end @@ -536,7 +531,7 @@ function PANEL:PopulateParts(node, parts, children) elseif isstring(part.Icon) then part_node.Icon:SetImage(part.Icon) end - part_node.Icon:SetSize(16 * GetConVar("pac_editor_scale"):GetFloat(),16 * GetConVar("pac_editor_scale"):GetFloat()) + part_node.Icon:SetSize(16 * pac_editor_scale:GetFloat(), 16 * pac_editor_scale:GetFloat()) self:PopulateParts(part_node, part:GetChildren(), true) @@ -581,8 +576,7 @@ function PANEL:SelectPart(part) end function PANEL:Populate(reset) - - self:SetLineHeight(18 * (1 + (GetConVar("pac_editor_scale"):GetFloat()-1))) + self:SetLineHeight(18 * (1 + (pac_editor_scale:GetFloat() - 1))) self:SetIndentSize(10) for key, node in pairs(self.parts) do @@ -613,7 +607,6 @@ local function remove_node(part) part.pace_tree_node:GetRoot().m_pSelectedItem = nil part.pace_tree_node:Remove() pace.RefreshTree() - end end @@ -624,7 +617,6 @@ local function refresh(part) if last_refresh > SysTime() then return end if not part:GetShowInEditor() then return end - last_refresh = SysTime() + 0.1 timer.Simple(0, function() if not part:IsValid() then return end @@ -649,36 +641,43 @@ end) pace.allowed_event_refresh = 0 - function pace.RefreshEvents() --spam preventer, (load parts' initializes gets called) - if pace.allowed_event_refresh > CurTime() then return else pace.allowed_event_refresh = CurTime() + 0.1 end + if pace.allowed_event_refresh > CurTime() then + return + else + pace.allowed_event_refresh = CurTime() + 0.1 + end + + local parts = pac.GetLocalParts() local events = {} - for _, part in pairs(pac.GetLocalParts()) do + for _, part in pairs(parts) do if part.ClassName == "event" then events[part] = part end end + local no_events = table.Count(events) == 0 - for _, child in pairs(pac.GetLocalParts()) do + for _, child in pairs(parts) do child.active_events = {} child.active_events_ref_count = 0 + if not no_events then - for _,event in pairs(events) do + for _, event in pairs(events) do event:OnThink() end end + child:CallRecursive("CalcShowHide", false) end - end function pace.RefreshTree(reset) --print("pace.RefreshTree("..tostring(reset)..")") if pace.tree:IsValid() then - timer.Create("pace_refresh_tree", 0.01, 1, function() + timer.Create("pace_refresh_tree", 0.01, 1, function() if pace.tree:IsValid() then pace.tree:Populate(reset) pace.tree.RootNode:SetExpanded(true, true) -- why do I have to do this? diff --git a/lua/pac3/editor/client/parts.lua b/lua/pac3/editor/client/parts.lua index e334e2dd8..3f46ad820 100644 --- a/lua/pac3/editor/client/parts.lua +++ b/lua/pac3/editor/client/parts.lua @@ -62,18 +62,21 @@ end local function BulkSelectRefreshFadedNodes(part_trace) if refresh_halo_hook then return end if part_trace then - for _,v in ipairs(part_trace:GetRootPart():GetChildrenList()) do + local children = part_trace:GetRootPart():GetChildrenList() + for i = 1, #children do + local v = children[i] + if IsValid(v.pace_tree_node) then - v.pace_tree_node:SetAlpha( 255 ) + v.pace_tree_node:SetAlpha(255) end - end end - for _,v in ipairs(pace.BulkSelectList) do - if not v:IsValid() then table.RemoveByValue(pace.BulkSelectList, v) + for _, v in ipairs(pace.BulkSelectList) do + if not v:IsValid() then + table.RemoveByValue(pace.BulkSelectList, v) elseif IsValid(v.pace_tree_node) then - v.pace_tree_node:SetAlpha( 150 ) + v.pace_tree_node:SetAlpha(150) end end end @@ -85,35 +88,38 @@ local function RebuildBulkHighlight() local ent = {} --get potential entities and part-children from each parent in the bulk list - for _,v in pairs(pace.BulkSelectList) do --this will get parts - - if (v == v:GetRootPart()) then --if this is the root part, send the entity - table.insert(ents_tbl,v:GetRootPart():GetOwner()) - table.insert(parts_tbl,v) + for _, v in pairs(pace.BulkSelectList) do --this will get parts + if v == v:GetRootPart() then --if this is the root part, send the entity + table.insert(ents_tbl, v:GetRootPart():GetOwner()) + table.insert(parts_tbl, v) else - table.insert(parts_tbl,v) + table.insert(parts_tbl, v) end - for _,child in ipairs(v:GetChildrenList()) do --now do its children - table.insert(parts_tbl,child) + local children = v:GetChildrenList() + for i = 1, #children do --now do its children + table.insert(parts_tbl, children[i]) end end --check what parts are candidates we can give to halo - for _,v in ipairs(parts_tbl) do + for i = 1, #parts_tbl do + local v = parts_tbl[i] local can_add = false - if (v.ClassName == "model" or v.ClassName == "model2") then + + if v.ClassName == "model" or v.ClassName == "model2" then can_add = true end - if (v.ClassName == "group") or (v.Hide == true) or (v.Size == 0) or (v.Alpha == 0) or (v:IsHidden()) then + if v.ClassName == "group" or v.Hide == true or v.Size == 0 or v.Alpha == 0 or v:IsHidden() then can_add = false end + if can_add then table.insert(hover_tbl, v:GetOwner()) end end - table.Add(hover_tbl,ents_tbl) + table.Add(hover_tbl, ents_tbl) --TestPrintTable(hover_tbl, "hover_tbl") last_bulk_select_tbl = hover_tbl @@ -128,7 +134,7 @@ local function TestPrintTable(tbl, tbl_name) end local function DrawHaloHighlight(tbl) - if (type(tbl) ~= "table") then return end + if type(tbl) ~= "table" then return end if not pace.Active then pac.RemoveHook("PreDrawHalos", "BulkSelectHighlights") end @@ -138,32 +144,34 @@ local function DrawHaloHighlight(tbl) local pulse_rate = math.min(math.abs(GetConVar("pac_hover_pulserate"):GetFloat()), 100) local pulse = math.sin(SysTime() * pulse_rate) * 0.5 + 0.5 if pulse_rate == 0 then pulse = 1 end - local pulseamount - local halo_color = Color(255,255,255) + local pulseamount + local halo_color = Color(255, 255, 255) if color_string == "rave" then - halo_color = Color(255*((0.33 + SysTime() * pulse_rate/20)%1), 255*((0.66 + SysTime() * pulse_rate/20)%1), 255*((SysTime() * pulse_rate/20)%1), 255) + halo_color = Color(255 * ((0.33 + SysTime() * pulse_rate / 20) % 1), 255 * ((0.66 + SysTime() * pulse_rate / 20) % 1), 255 * ((SysTime() * pulse_rate / 20) % 1), 255) pulseamount = 8 elseif color_string == "funky" then - halo_color = Color(255*((0.33 + SysTime() * pulse_rate/10)%1), 255*((0.2 + SysTime() * pulse_rate/15)%1), 255*((SysTime() * pulse_rate/15)%1), 255) + halo_color = Color(255 * ((0.33 + SysTime() * pulse_rate/10) % 1), 255 * ((0.2 + SysTime() * pulse_rate / 15) % 1), 255 * ((SysTime() * pulse_rate / 15) % 1), 255) pulseamount = 5 elseif color_string == "ocean" then - halo_color = Color(0, 80 + 30*(pulse), 200 + 50*(pulse) * 0.5 + 0.5, 255) + halo_color = Color(0, 80 + 30 * pulse, 200 + 50 * pulse * 0.5 + 0.5, 255) pulseamount = 4 elseif color_string == "rainbow" then --halo_color = Color(255*(0.5 + 0.5*math.sin(pac.RealTime * pulse_rate/20)),255*(0.5 + 0.5*-math.cos(pac.RealTime * pulse_rate/20)),255*(0.5 + 0.5*math.sin(1 + pac.RealTime * pulse_rate/20)), 255) - halo_color = HSVToColor(SysTime() * 360 * pulse_rate/20, 1, 1) + halo_color = HSVToColor(SysTime() * 360 * pulse_rate / 20, 1, 1) pulseamount = 4 elseif #string.Split(color_string, " ") == 3 then - halo_color_tbl = string.Split( color_string, " " ) - for i,v in ipairs(halo_color_tbl) do - if not isnumber(tonumber(halo_color_tbl[i])) then halo_color_tbl[i] = 0 end + halo_color_tbl = string.Split(color_string, " ") + for i = 1, #halo_color_tbl do + if not isnumber(tonumber(halo_color_tbl[i])) then + halo_color_tbl[i] = 0 + end end - halo_color = Color(pulse*halo_color_tbl[1],pulse*halo_color_tbl[2],pulse*halo_color_tbl[3],255) + halo_color = Color(pulse * halo_color_tbl[1], pulse * halo_color_tbl[2], pulse * halo_color_tbl[3], 255) pulseamount = 4 else - halo_color = Color(255,255,255,255) + halo_color = Color(255, 255, 255) pulseamount = 2 end --print("using", halo_color, "blurs=" .. 2, "amount=" .. pulseamount) @@ -182,7 +190,6 @@ end function pace.WearParts(temp_wear_filter) - local allowed, reason = pac.CallHook("CanWearParts", pac.LocalPlayer) if allowed == false then @@ -262,7 +269,7 @@ function pace.OnCreatePart(class_name, name, mdl, no_parent) if parent.GetDrawPosition and parent:IsValid() and not parent:HasParent() and parent.OwnerName == "world" and part:GetPlayerOwner() == ply then local data = ply:GetEyeTrace() - if data.HitPos:Distance(ply:GetPos()) < 1000 then + if data.HitPos:DistToSqr(ply:GetPos()) < 1000000 then --1000hu part:SetPosition(data.HitPos) else part:SetPosition(ply:GetPos()) @@ -1281,8 +1288,9 @@ do -- menu newObj:SetParent(obj.Parent) obj:SetParent(newObj) - for i,v in pairs(obj:GetChildren()) do - v:SetParent(newObj) + local children = obj:GetChildren() + for i = 1, #children do + children[i]:SetParent(newObj) end newObj:SetPosition(obj.Position) @@ -1326,7 +1334,6 @@ do -- menu pace.RefreshTree() end - obj.ClassName = str timer.Simple(0, function() @@ -1335,7 +1342,6 @@ do -- menu obj = pac.GetPartFromUniqueID(pac.Hash(pac.LocalPlayer), uid) obj:SetModel("models/pac/default.mdl") end - end) end) end @@ -1355,28 +1361,33 @@ do -- menu obj = obj or pace.current_part refresh_halo_hook = false --print(obj.pace_tree_node, "color", obj.pace_tree_node:GetFGColor().r .. " " .. obj.pace_tree_node:GetFGColor().g .. " " .. obj.pace_tree_node:GetFGColor().b) + if obj.ClassName == "timeline_dummy_bone" then return end local selected_part_added = false --to decide the sound to play afterward + local obj_children = obj:GetChildrenList() + pace.BulkSelectList = pace.BulkSelectList or {} - if (table.HasValue(pace.BulkSelectList, obj)) then + + if table.HasValue(pace.BulkSelectList, obj) then pace.RemoveFromBulkSelect(obj) selected_part_added = false - elseif (pace.BulkSelectList[obj] == nil) then + elseif pace.BulkSelectList[obj] == nil then pace.AddToBulkSelect(obj) selected_part_added = true - for _,v in ipairs(obj:GetChildrenList()) do - pace.RemoveFromBulkSelect(v) + + for i = 1, #obj_children do + pace.RemoveFromBulkSelect(obj_children[i]) end end --check parents and children - for _,v in ipairs(pace.BulkSelectList) do + for _, v in ipairs(pace.BulkSelectList) do if table.HasValue(v:GetChildrenList(), obj) then --print("selected part is already child to a bulk-selected part!") pace.RemoveFromBulkSelect(obj) selected_part_added = false - elseif table.HasValue(obj:GetChildrenList(), v) then + elseif table.HasValue(obj_children, v) then --print("selected part is already parent to a bulk-selected part!") pace.RemoveFromBulkSelect(v) selected_part_added = false @@ -1384,11 +1395,13 @@ do -- menu end RebuildBulkHighlight() + if not silent then if selected_part_added then surface.PlaySound("buttons/button1.wav") - - else surface.PlaySound("buttons/button16.wav") end + else + surface.PlaySound("buttons/button16.wav") + end end if table.IsEmpty(pace.BulkSelectList) then @@ -1407,7 +1420,6 @@ do -- menu end end) end - end function pace.RemoveFromBulkSelect(obj) @@ -1489,13 +1501,14 @@ do -- menu for _,prop in pairs(basepart:GetProperties()) do local shared = true - for _,part2 in pairs(pace.BulkSelectList) do + for _, part2 in pairs(pace.BulkSelectList) do if basepart ~= part2 and basepart.ClassName ~= part2.ClassName then if part2["Get" .. prop["key"]] == nil then if policy == "harsh" then shared = false end end end end + if shared and not prop.udata.editor_friendly and basepart["Get" .. prop["key"]] ~= nil then shared_properties[#shared_properties + 1] = prop["key"] elseif shared and prop.udata.editor_friendly and basepart["Get" .. prop["key"]] == nil then @@ -1508,8 +1521,9 @@ do -- menu if policy == "lenient" then local initial_shared_properties = table.Copy(shared_properties) local initial_shared_udata_properties = table.Copy(shared_udata_properties) - for _,part2 in pairs(pace.BulkSelectList) do - for _,prop in ipairs(part2:GetProperties()) do + + for _, part2 in pairs(pace.BulkSelectList) do + for _, prop in ipairs(part2:GetProperties()) do if not (table.HasValue(shared_properties, prop["key"]) or table.HasValue(shared_udata_properties, "event_udata_"..prop["key"])) then if part2["Get" .. prop["key"]] ~= nil then initial_shared_properties[#initial_shared_properties + 1] = prop["key"] @@ -1521,26 +1535,30 @@ do -- menu end end end + shared_properties = initial_shared_properties shared_udata_properties = initial_shared_udata_properties end - for i,v in ipairs(shared_properties) do + for i, v in ipairs(shared_properties) do if excluded_vars[v] then table.remove(shared_properties,i) end end --populate panels for standard GetSet part properties - for i,v in pairs(shared_properties) do + for i, v in pairs(shared_properties) do local VAR_PANEL = vgui.Create("DFrame") - VAR_PANEL:SetSize(500,30) - VAR_PANEL:SetPos(0,0) - VAR_PANEL:ShowCloseButton( false ) + VAR_PANEL:SetSize(500, 30) + VAR_PANEL:SetPos(0, 0) + VAR_PANEL:ShowCloseButton(false) + local VAR_PANEL_BUTTON = VAR_PANEL:Add("DButton") VAR_PANEL_BUTTON:SetSize(80,30) VAR_PANEL_BUTTON:SetPos(400,0) + local VAR_PANEL_EDITZONE local var_type - for _,testpart in ipairs(pace.BulkSelectList) do + + for _, testpart in ipairs(pace.BulkSelectList) do if testpart["Get" .. v] ~= nil then @@ -1551,33 +1569,34 @@ do -- menu if var_type == "number" then VAR_PANEL_EDITZONE = vgui.Create("DTextEntry", VAR_PANEL) - VAR_PANEL_EDITZONE:SetSize(200,30) + VAR_PANEL_EDITZONE:SetSize(200, 30) elseif var_type == "boolean" then VAR_PANEL_EDITZONE = vgui.Create("DCheckBox", VAR_PANEL) - VAR_PANEL_EDITZONE:SetSize(30,30) + VAR_PANEL_EDITZONE:SetSize(30, 30) elseif var_type == "string" then VAR_PANEL_EDITZONE = vgui.Create("DTextEntry", VAR_PANEL) - VAR_PANEL_EDITZONE:SetSize(200,30) + VAR_PANEL_EDITZONE:SetSize(200, 30) elseif var_type == "Vector" then VAR_PANEL_EDITZONE = vgui.Create("DTextEntry", VAR_PANEL) - VAR_PANEL_EDITZONE:SetSize(200,30) + VAR_PANEL_EDITZONE:SetSize(200, 30) elseif var_type == "Angle" then VAR_PANEL_EDITZONE = vgui.Create("DTextEntry", VAR_PANEL) - VAR_PANEL_EDITZONE:SetSize(200,30) + VAR_PANEL_EDITZONE:SetSize(200, 30) else VAR_PANEL_EDITZONE = vgui.Create("DTextEntry", VAR_PANEL) - VAR_PANEL_EDITZONE:SetSize(200,30) + VAR_PANEL_EDITZONE:SetSize(200, 30) end - VAR_PANEL_EDITZONE:SetPos(200,0) + VAR_PANEL_EDITZONE:SetPos(200, 0) VAR_PANEL_BUTTON:SetText("APPLY") VAR_PANEL:SetTitle("[" .. i .. "] "..v.." "..var_type) - VAR_PANEL:Dock( TOP ) - VAR_PANEL:DockMargin( 5, 0, 0, 5 ) + VAR_PANEL:Dock(TOP) + VAR_PANEL:DockMargin(5, 0, 0, 5) + VAR_PANEL_BUTTON.DoClick = function() - for i,part in pairs(pace.BulkSelectList) do + for i, part in pairs(pace.BulkSelectList) do local sent_var if var_type == "number" then sent_var = VAR_PANEL_EDITZONE:GetValue() @@ -1600,23 +1619,30 @@ do -- menu sent_var.x = tonumber(str[1]) or 1 sent_var.y = tonumber(str[2]) or 1 sent_var.z = tonumber(str[3]) or 1 - if v == "Color" and not part.ProperColorRange then sent_var = sent_var*255 end + if v == "Color" and not part.ProperColorRange then sent_var = sent_var * 255 end elseif var_type == "Angle" then local str = string.Split(VAR_PANEL_EDITZONE:GetValue(), ",") sent_var = Angle() sent_var.p = tonumber(str[1]) or 1 sent_var.y = tonumber(str[2]) or 1 sent_var.r = tonumber(str[3]) or 1 - else sent_var = VAR_PANEL_EDITZONE:GetValue() end - + else + sent_var = VAR_PANEL_EDITZONE:GetValue() + end - if policy == "harsh" then part["Set" .. v](part, sent_var) + if policy == "harsh" then + part["Set" .. v](part, sent_var) elseif policy == "lenient" then if part["Get" .. v] ~= nil then part["Set" .. v](part, sent_var) end end + if thoroughness_tickbox:GetChecked() then - for _,child in pairs(part:GetChildrenList()) do - if part["Get" .. v] ~= nil then child["Set" .. v](child, sent_var) end + local children = part:GetChildrenList() + for x = 1, #children do + if part["Get" .. v] ~= nil then + local child = children[x] + child["Set" .. v](child, sent_var) + end end end end @@ -1624,13 +1650,15 @@ do -- menu pace.RefreshTree(true) timer.Simple(0.3, function() BulkSelectRefreshFadedNodes() end) end - scroll_panel:AddItem( VAR_PANEL ) + + scroll_panel:AddItem(VAR_PANEL) end --populate panels for event "userdata" packaged into arguments if #shared_udata_properties > 0 then local fallback_event_types = {} local fallback_event + for i,v in ipairs(pace.BulkSelectList) do if v.ClassName == "event" then table.Add(fallback_event_types,v.Event) @@ -1650,13 +1678,15 @@ do -- menu local function GetEventArgType(part, str) if not part.Events then return "string" end - for argn,arg in ipairs(part.Events[part.Event].__registeredArguments) do + + for argn, arg in ipairs(part.Events[part.Event].__registeredArguments) do if arg[1] == str then return arg[2] end end + if fallback_event then - for i,e in ipairs(fallback_event_types) do + for i, e in ipairs(fallback_event_types) do for argn,arg in ipairs(fallback_event.Events[e].__registeredArguments) do if arg[1] == str then return arg[2] @@ -1664,6 +1694,7 @@ do -- menu end end end + return "string" end @@ -1675,6 +1706,7 @@ do -- menu return argn end end + return 1 end @@ -1685,7 +1717,6 @@ do -- menu end for i,v in ipairs(shared_udata_properties) do - local udata_val_name = string.gsub(v, "event_udata_", "") local var_type = GetEventArgType(obj, udata_val_name) @@ -1693,43 +1724,44 @@ do -- menu local VAR_PANEL = vgui.Create("DFrame") - VAR_PANEL:SetSize(500,30) - VAR_PANEL:SetPos(0,0) - VAR_PANEL:ShowCloseButton( false ) + VAR_PANEL:SetSize(500, 30) + VAR_PANEL:SetPos(0, 0) + VAR_PANEL:ShowCloseButton(false) + local VAR_PANEL_BUTTON = VAR_PANEL:Add("DButton") - VAR_PANEL_BUTTON:SetSize(80,30) - VAR_PANEL_BUTTON:SetPos(400,0) + VAR_PANEL_BUTTON:SetSize(80, 30) + VAR_PANEL_BUTTON:SetPos(400, 0) + local VAR_PANEL_EDITZONE if var_type == "number" then VAR_PANEL_EDITZONE = vgui.Create("DTextEntry", VAR_PANEL) - VAR_PANEL_EDITZONE:SetSize(200,30) + VAR_PANEL_EDITZONE:SetSize(200, 30) elseif var_type == "boolean" then VAR_PANEL_EDITZONE = vgui.Create("DCheckBox", VAR_PANEL) - VAR_PANEL_EDITZONE:SetSize(30,30) + VAR_PANEL_EDITZONE:SetSize(30, 30) elseif var_type == "string" then VAR_PANEL_EDITZONE = vgui.Create("DTextEntry", VAR_PANEL) - VAR_PANEL_EDITZONE:SetSize(200,30) + VAR_PANEL_EDITZONE:SetSize(200, 30) elseif var_type == "Vector" then VAR_PANEL_EDITZONE = vgui.Create("DTextEntry", VAR_PANEL) - VAR_PANEL_EDITZONE:SetSize(200,30) + VAR_PANEL_EDITZONE:SetSize(200, 30) elseif var_type == "Angle" then VAR_PANEL_EDITZONE = vgui.Create("DTextEntry", VAR_PANEL) - VAR_PANEL_EDITZONE:SetSize(200,30) + VAR_PANEL_EDITZONE:SetSize(200, 30) else VAR_PANEL_EDITZONE = vgui.Create("DTextEntry", VAR_PANEL) - VAR_PANEL_EDITZONE:SetSize(200,30) + VAR_PANEL_EDITZONE:SetSize(200, 30) end - VAR_PANEL_EDITZONE:SetPos(200,0) + VAR_PANEL_EDITZONE:SetPos(200, 0) VAR_PANEL:SetTitle("[" .. i .. "] "..udata_val_name.." "..var_type) VAR_PANEL_BUTTON:SetText("APPLY") + VAR_PANEL:Dock(TOP) + VAR_PANEL:DockMargin(5, 0, 0, 5) - VAR_PANEL:Dock( TOP ) - VAR_PANEL:DockMargin( 5, 0, 0, 5 ) VAR_PANEL_BUTTON.DoClick = function() - - for i,part in ipairs(pace.BulkSelectList) do + for i, part in ipairs(pace.BulkSelectList) do --PrintTable(part.Events[part.Event].__registeredArguments) local sent_var if var_type == "number" then @@ -1749,7 +1781,10 @@ do -- menu if v == "Name" and sent_var ~= "" then sent_var = sent_var..i end - else sent_var = VAR_PANEL_EDITZONE:GetValue() end + else + sent_var = VAR_PANEL_EDITZONE:GetValue() + end + if part.ClassName == "event" and part.Event == basepart.Event then part:SetArguments(ApplyArgToIndex(part:GetArguments(), sent_var, GetEventArgIndex(part,v))) else @@ -1757,7 +1792,10 @@ do -- menu end if thoroughness_tickbox:GetChecked() then - for _,child in pairs(part:GetChildrenList()) do + local children = part:GetChildrenList() + for x = 1, #children do + local child = children[x] + if child.ClassName == "event" and child.Event == basepart.Event then local sent_var if var_type == "number" then @@ -1777,9 +1815,11 @@ do -- menu if v == "Name" and sent_var ~= "" then sent_var = sent_var..i end - else sent_var = VAR_PANEL_EDITZONE:GetValue() end + else + sent_var = VAR_PANEL_EDITZONE:GetValue() + end - child:SetArguments(ApplyArgToIndex(child:GetArguments(), sent_var, GetEventArgIndex(child,v))) + child:SetArguments(ApplyArgToIndex(child:GetArguments(), sent_var, GetEventArgIndex(child, v))) end end end @@ -1788,17 +1828,20 @@ do -- menu pace.RefreshTree(true) timer.Simple(0.3, function() BulkSelectRefreshFadedNodes() end) end - scroll_panel:AddItem( VAR_PANEL ) + + scroll_panel:AddItem(VAR_PANEL) end end end function pace.BulkCutPaste(obj) pace.RecordUndoHistory() - for _,v in ipairs(pace.BulkSelectList) do + + for _, v in ipairs(pace.BulkSelectList) do --if a part is inserted onto itself, it should instead serve as a parent if v ~= obj then v:SetParent(obj) end end + pace.RecordUndoHistory() pace.RefreshTree() end @@ -2673,7 +2716,7 @@ function pace.UltraCleanup(obj) if IsSafe(part) or Important(part) then return elseif IsMildlyRisky(part) then - if table.Count(part:GetChildren()) == 0 then + if #part:GetChildren() == 0 then part:Remove() end end @@ -2690,11 +2733,15 @@ function pace.UltraCleanup(obj) local function Move_contents_up(part) --this will be the powerhouse recursor local parent = FindNearestSafeParent(part) --print(part, "nearest parent is", parent) - for _,child in pairs(part:GetChildren()) do + + local children = part:GetChildren() + for i = 1, #children do + local child = children[i] + if child:IsHidden() or child.Hide then --hidden = delete marked_for_deletion[child] = child else --visible = possible container = check - if table.Count(child:GetChildren()) == 0 then --dead end = immediate action + if #child:GetChildren() == 0 then --dead end = immediate action if IsSafe(child) then --safe = keep but now extract it child:SetParent(parent) --print(child, "moved to", parent) @@ -2709,27 +2756,30 @@ function pace.UltraCleanup(obj) safe_parts[child] = child Move_contents_up(child) --recurse end - end - end end --find parts to delete --first pass: absolute unsafes: hidden parts - for i,v in pairs(root:GetChildrenList()) do + local root_children = root:GetChildrenList() + for i = 1, #root_children do + local v = root_children[i] + if v:IsHidden() or v.Hide then if not FoundImportantMarkedParent(v) then v:Remove() end - end end - --second pass: - --A: mark safe parts - --B: extract children in remaining unsafes (i.e. break the chain of an event) - for i,v in pairs(root:GetChildrenList()) do + --second pass: + --A: mark safe parts + --B: extract children in remaining unsafes (i.e. break the chain of an event) + root_children = root:GetChildrenList() + for i = 1, #root_children do + local v = root_children[i] + if IsSafe(v) then safe_parts[v] = v CheckPartWithLinkedParts(v) @@ -2740,23 +2790,25 @@ function pace.UltraCleanup(obj) Move_contents_up(v) marked_for_deletion[v] = v end - end - --after that, the remaining events etc are marked - for i,v in pairs(root:GetChildrenList()) do + + --after that, the remaining events etc are marked + root_children = root:GetChildrenList() + for i = 1, #root_children do + local v = root_children[i] + if IsMildlyRisky(v) then marked_for_deletion[v] = v end end pace.RefreshTree() - --go through delete tables except when marked as important or those protected by these - for i,v in pairs(marked_for_deletion) do + --go through delete tables except when marked as important or those protected by these + for i, v in pairs(marked_for_deletion) do local delete = false if not safe_parts[v] then - if v:IsValid() then delete = true end @@ -2768,8 +2820,11 @@ function pace.UltraCleanup(obj) if delete then SafeRemove(v) end end - --third pass: cleanup the last remaining unwanted parts - for i,v in pairs(root:GetChildrenList()) do + --third pass: cleanup the last remaining unwanted parts + root_children = root:GetChildrenList() + for i = 1, #root_children do + local v = root_children[i] + --remove remaining events after their children have been freed, and delete parts that don't have durable use, like sounds that aren't looping if IsMildlyRisky(v) or IsHangingPart(v) then if not Important(v) then @@ -2778,20 +2833,26 @@ function pace.UltraCleanup(obj) end end - --fourth pass: delete bare containing nothing left - for i,v in pairs(root:GetChildrenList()) do + --fourth pass: delete bare containing nothing left + root_children = root:GetChildrenList() + for i = 1, #root_children do + local v = root_children[i] + if v.ClassName == "group" then local bare = true - for i2,v2 in pairs(v:GetChildrenList()) do - if v2.ClassName ~= "group" then + + local v_children = v:GetChildrenList() + for x = 1, #v_children do + if v_children[x].ClassName ~= "group" then bare = false end end + if bare then v:Remove() end end end - pace.RefreshTree() + pace.RefreshTree() end do --hover highlight halo @@ -2815,51 +2876,54 @@ do --hover highlight halo local tbl = {} local ent = self:GetOwner() - local is_root = ent == self:GetRootPart():GetOwner() + local root_ent = self:GetRootPart():GetOwner() + local is_root = ent == root_ent --decide whether to skip --it will skip the part-search loop if we already checked the part recently if self.UniqueID == last_checked_partUID then skip = true - if is_root and last_root_ent ~= self:GetRootPart():GetOwner() then + + if is_root and last_root_ent ~= root_ent then table.RemoveByValue(last_tbl, last_root_ent) - table.insert(last_tbl, self:GetRootPart():GetOwner()) + table.insert(last_tbl, root_ent) end + tbl = last_tbl end --operations : search the part and look for entity-candidates to halo if not skip then --start with entity, which could be part or entity - if (is_root and ent:IsValid()) then + if is_root and ent:IsValid() then + table.insert(tbl, ent) + elseif not (self.ClassName == "group" or self.ClassName == "jiggle" or self.Hide == true or self.Size == 0 or self.Alpha == 0) then table.insert(tbl, ent) - else - if not ((self.ClassName == "group" or self.ClassName == "jiggle") or (self.Hide == true) or (self.Size == 0) or (self.Alpha == 0)) then - table.insert(tbl, ent) - end end --get the children if any if self:HasChildren() then - for _,v in ipairs(self:GetChildrenList()) do - local can_add = false - local ent = v:GetOwner() + local children = self:GetChildrenList() + for i = 1, #children do + local v = children[i] --we're not gonna add parts that don't have a specific reason to be haloed or that don't at least group up some haloable models --because the table.insert function has a processing load on the memory, and so is halo-drawing - if (v.ClassName == "model" or v.ClassName == "model2" or v.ClassName == "jiggle") then - can_add = true - else can_add = false end - if (v.Hide == true) or (v.Size == 0) or (v.Alpha == 0) or (v:IsHidden()) then + local can_add = v.ClassName == "model" or v.ClassName == "model2" or v.ClassName == "jiggle" + + if v.Hide == true or v.Size == 0 or v.Alpha == 0 or v:IsHidden() then can_add = false end - if can_add then table.insert(tbl, ent) end + + if can_add then + table.insert(tbl, v:GetOwner()) + end end end end last_tbl = tbl - last_root_ent = self:GetRootPart():GetOwner() + last_root_ent = root_ent last_checked_partUID = self.UniqueID DrawHaloHighlight(tbl) diff --git a/lua/pac3/editor/client/render_scores.lua b/lua/pac3/editor/client/render_scores.lua index 7404165b4..f2611b579 100644 --- a/lua/pac3/editor/client/render_scores.lua +++ b/lua/pac3/editor/client/render_scores.lua @@ -27,7 +27,9 @@ end timer.Create("pac_render_times", 0.1, 0, function() if not pac.IsEnabled() then return end - for key, ply in pairs(player.GetHumans()) do + for _, ply in player.Iterator() do + if ply:IsBot() then continue end + local data = pace.GetProfilingData(ply) if data then @@ -44,19 +46,20 @@ timer.Create("pac_render_times", 0.1, 0, function() end end) +local maxDist = 100 ^ 2 + pac.AddHook("HUDPaint", "pac_show_render_times", function() if not pace.IsActive() or not pace.IsFocused() or not enable:GetBool() then return end - for key, ply in pairs(player.GetHumans()) do - if ply == pac.LocalPlayer then goto CONTINUE end + for _, ply in player.Iterator() do + if ply == pac.LocalPlayer or ply:IsBot() then goto CONTINUE end local pos = ply:EyePos() - if pos:Distance(pac.EyePos) < 100 then + if pos:DistToSqr(pac.EyePos) < maxDist then local pos = pos:ToScreen() if pos.visible then - surface.SetFont(font) surface.SetTextColor(255, 255, 255, 255) diff --git a/lua/pac3/editor/client/saved_parts.lua b/lua/pac3/editor/client/saved_parts.lua index 6a2004298..c53266fcd 100644 --- a/lua/pac3/editor/client/saved_parts.lua +++ b/lua/pac3/editor/client/saved_parts.lua @@ -1,8 +1,12 @@ local L = pace.LanguageString +local file_Find = file.Find +local file_Exists = file.Exists +local file_Time = file.Time +local file_Size = file.Size +local table_insert = table.insert -- load only when hovered above local function add_expensive_submenu_load(pnl, callback, subdir) - local old = pnl.OnCursorEntered pnl.OnCursorEntered = function(...) callback(subdir) @@ -21,7 +25,6 @@ function pace.SaveParts(name, prompt_name, override_part, overrideAsUsual) L"save parts", L"filename:", prompt_name or pace.LastSaveName or "autoload", - function(name) pace.LastSaveName = name pace.SaveParts(name, nil, override_part, overrideAsUsual) @@ -46,36 +49,39 @@ function pace.SaveParts(name, prompt_name, override_part, overrideAsUsual) data = override_part:ToSaveTable() end elseif override_part then - table.insert(data, override_part:ToSaveTable()) + table_insert(data, override_part:ToSaveTable()) override_part = nil end - if #data == 0 then + if data[1] == nil then for key, part in pairs(pac.GetLocalParts()) do if not part:HasParent() and part:GetShowInEditor() then - table.insert(data, part:ToSaveTable()) + table_insert(data, part:ToSaveTable()) end end end data = pac.CallHook("pace.SaveParts", data) or data - if not override_part and #file.Find("pac3/sessions/*", "DATA") > 0 and not name:find("/") then + if not override_part and file_Find("pac3/sessions/*", "DATA")[1] ~= nil and not name:find("/") then pace.luadata.WriteFile("pac3/sessions/" .. name .. ".txt", data) else - if file.Exists("pac3/" .. name .. ".txt", "DATA") then + if file_Exists("pac3/" .. name .. ".txt", "DATA") then local date = os.date("%y-%m-%d-%H_%M_%S") local read = file.Read("pac3/" .. name .. ".txt", "DATA") + file.Write("pac3/__backup_save/" .. name .. "_" .. date .. ".txt", read) - local files, folders = file.Find("pac3/__backup_save/*", "DATA") + local files, folders = file_Find("pac3/__backup_save/*", "DATA") if #files > 30 then local targetFiles = {} - for i, filename in ipairs(files) do - local time = file.Time("pac3/__backup_save/" .. filename, "DATA") - table.insert(targetFiles, {"pac3/__backup_save/" .. filename, time}) + for i = 1, #files do + local filename = files[i] + local time = file_Time("pac3/__backup_save/" .. filename, "DATA") + + table_insert(targetFiles, {"pac3/__backup_save/" .. filename, time}) end table.sort(targetFiles, function(a, b) @@ -100,28 +106,27 @@ local autoload_prompt = CreateConVar("pac_prompt_for_autoload", "1", {FCVAR_ARCH local auto_spawn_prop = CreateConVar("pac_autoload_preferred_prop", "2", {FCVAR_ARCHIVE}, "When loading a pac with an owner name suggesting a prop, notify you and then wait before auto-applying the outfit next time you spawn a prop.\n" .. "0 : do not check\n1 : check if only 1 such group is present\n2 : check if multiple such groups are present and queue one group at a time") - function pace.Backup(data, name) name = name or "" if not data then data = {} - for key, part in pairs(pac.GetLocalParts()) do + for key, part in next, pac.GetLocalParts() do if not part:HasParent() and part:GetShowInEditor() then - table.insert(data, part:ToSaveTable()) + table_insert(data, part:ToSaveTable()) end end end - if #data > 0 then - - local files, folders = file.Find("pac3/__backup/*", "DATA") + if data[1] ~= nil then + local files, folders = file_Find("pac3/__backup/*", "DATA") if #files > maxBackups:GetInt() then local temp = {} - for key, name in pairs(files) do - local time = file.Time("pac3/__backup/" .. name, "DATA") - table.insert(temp, {path = "pac3/__backup/" .. name, time = time}) + for i = 1, #files do + local filename = files[i] + + table_insert(temp, {path = "pac3/__backup/" .. filename, time = file_Time("pac3/__backup/" .. filename, "DATA")}) end table.sort(temp, function(a, b) @@ -164,7 +169,6 @@ end function pace.LoadParts(name, clear, override_part) - if not name then local frm = vgui.Create("DFrame") frm:SetTitle(L"parts") @@ -174,7 +178,7 @@ function pace.LoadParts(name, clear, override_part) pace.LoadParts(node.FileName, clear, override_part) end - if #file.Find("pac3/sessions/*", "DATA") > 0 then + if #file_Find("pac3/sessions/*", "DATA") > 0 then pnl:SetDir("sessions/") else pnl:SetDir("") @@ -202,7 +206,7 @@ function pace.LoadParts(name, clear, override_part) else if name ~= "autoload.txt" and not string.find(name, "pac3/__backup") then - if file.Exists("pac3/" .. name .. ".txt", "DATA") then + if file_Exists("pac3/" .. name .. ".txt", "DATA") then cookie.Set( "pac_last_loaded_outfit", name .. ".txt" ) end end @@ -213,7 +217,6 @@ function pace.LoadParts(name, clear, override_part) pac.dprint("loading Parts %s", name) if name:find("https?://") then - local ext = name:match("/.+%.(%a+)[%?&]?.-") if ext == "txt" then local function callback(str) @@ -279,7 +282,6 @@ function pace.LoadParts(name, clear, override_part) pace.LoadPartsFromTable(part, false, false) end end - else if name == "autoload" and (not data or not next(data)) then data, err = pace.luadata.ReadFile("pac3/sessions/" .. name .. ".txt", nil, true) @@ -335,14 +337,14 @@ function pace.LoadPartsFromTable(data, clear, override_part) part = override_part or pac.CreatePart(data.self.ClassName, nil, data, pac.GetPartFromUniqueID(pac.Hash(pac.LocalPlayer), data.self.UniqueID):IsValid() and copy_id) end - table.insert(partsLoaded, part) + table_insert(partsLoaded, part) else data = pace.FixBadGrouping(data) data = pace.FixUniqueIDs(data) for key, tbl in pairs(data) do local part = pac.CreatePart(tbl.self.ClassName, nil, tbl, pac.GetPartFromUniqueID(pac.Hash(pac.LocalPlayer), tbl.self.UniqueID):IsValid() and copy_id) - table.insert(partsLoaded, part) + table_insert(partsLoaded, part) end end @@ -359,42 +361,47 @@ function pace.LoadPartsFromTable(data, clear, override_part) end local function add_files(tbl, dir) - local files, folders = file.Find("pac3/" .. dir .. "/*", "DATA") + local files, folders = file_Find("pac3/" .. dir .. "/*", "DATA") if folders then - for key, folder in pairs(folders) do + for i = 1, #folders do + local folder = folders[i] + if folder == "__backup" or folder == "objcache" or folder == "__animations" or folder == "__backup_save" then continue end + tbl[folder] = {} add_files(tbl[folder], dir .. "/" .. folder) end end if files then - for i, name in pairs(files) do + for i = 1, #files do + local name = files[i] + if name:find("%.txt") then local path = "pac3/" .. dir .. "/" .. name - if file.Exists(path, "DATA") then + if file_Exists(path, "DATA") then + local time = file_Time(path, "DATA") + local data = {} - data.Name = name:gsub("%.txt", "") - data.FileName = name - data.Size = string.NiceSize(file.Size(path, "DATA")) - local time = file.Time(path, "DATA") - data.LastModified = os.date("%m/%d/%Y %H:%M", time) - data.Time = file.Time(path, "DATA") - data.Path = path - data.RelativePath = (dir .. "/" .. data.Name):sub(2) + data.Name = name:gsub("%.txt", "") + data.FileName = name + data.Size = string.NiceSize(file_Size(path, "DATA")) + data.LastModified = os.date("%m/%d/%Y %H:%M", time) + data.Time = time + data.Path = path + data.RelativePath = (dir .. "/" .. data.Name):sub(2) local dat, err = pace.luadata.ReadFile(path) data.Content = dat if dat then - table.insert(tbl, data) + table_insert(tbl, data) else pac.dprint(("Decoding %s failed: %s\n"):format(path, err)) chat.AddText(("Could not load: %s\n"):format(path)) end - end end end @@ -510,22 +517,27 @@ function pace.AddOneDirectorySavedPartsToMenu(menu, subdir, nicename) if nicename then exp_submenu:SetText(nicename) end add_expensive_submenu_load(pnl, function(subdir) - local files = file.Find(subdir .. "/*", "DATA") + local files = file_Find(subdir .. "/*", "DATA") local files2 = {} --PrintTable(files) - for i, filename in ipairs(files) do - table.insert(files2, {filename, file.Time(subdir .. filename, "DATA")}) + + for i = 1, #files do + local name = files[i] + table_insert(files2, {filename, file_Time(subdir .. filename, "DATA")}) end table.sort(files2, function(a, b) return a[2] > b[2] end) - for _, data in pairs(files2) do + for i = 1, #files2 do + local data = files2[i] local name = data[1] local full_path = subdir .. "/" .. name --print(full_path) - local friendly_name = name .. " " .. string.NiceSize(file.Size(full_path, "DATA")) + + local friendly_name = name .. " " .. string.NiceSize(file_Size(full_path, "DATA")) + exp_submenu:AddOption(friendly_name, function() pace.LoadParts(subdir_head .. name, true) end) :SetImage(pace.MiscIcons.outfit) end @@ -591,22 +603,26 @@ function pace.AddSavedPartsToMenu(menu, clear, override_part) local subdir = "pac3/__backup/*" add_expensive_submenu_load(pnl, function(subdir) - - local files = file.Find("pac3/__backup/*", "DATA") + local files = file_Find("pac3/__backup/*", "DATA") local files2 = {} - for i, filename in ipairs(files) do - table.insert(files2, {filename, file.Time("pac3/__backup/" .. filename, "DATA")}) + for i = 1, #files do + local name = files[i] + + table_insert(files2, {name, file_Time("pac3/__backup/" .. name, "DATA")}) end table.sort(files2, function(a, b) return a[2] > b[2] end) - for _, data in pairs(files2) do + for i = 1, #files2 do + local data = files2[i] local name = data[1] local full_path = "pac3/__backup/" .. name - local friendly_name = os.date("%m/%d/%Y %H:%M:%S ", file.Time(full_path, "DATA")) .. string.NiceSize(file.Size(full_path, "DATA")) + + local friendly_name = os.date("%m/%d/%Y %H:%M:%S ", file_Time(full_path, "DATA")) .. string.NiceSize(file_Size(full_path, "DATA")) + backups:AddOption(friendly_name, function() pace.LoadParts("__backup/" .. name, true) end) :SetImage(pace.MiscIcons.outfit) end @@ -618,18 +634,21 @@ function pace.AddSavedPartsToMenu(menu, clear, override_part) subdir = "pac3/__backup_save/*" add_expensive_submenu_load(pnl, function() - local files = file.Find(subdir, "DATA") + local files = file_Find(subdir, "DATA") local files2 = {} - for i, filename in ipairs(files) do - table.insert(files2, {filename, file.Time("pac3/__backup_save/" .. filename, "DATA")}) + for i = 1, #files do + local name = files[i] + + table_insert(files2, {name, file_Time("pac3/__backup_save/" .. name, "DATA")}) end table.sort(files2, function(a, b) return a[2] > b[2] end) - for _, data in pairs(files2) do + for i = 1, #files2 do + local data = files2[i] local name = data[1] local stamp = data[2] local nicename = name @@ -639,7 +658,7 @@ function pace.AddSavedPartsToMenu(menu, clear, override_part) nicename = nicename:Replace(date, os.date(" %m/%d/%Y %H:%M:%S", stamp)) end - backups:AddOption(nicename:Replace(".txt", "") .. " (" .. string.NiceSize(file.Size("pac3/__backup_save/" .. name, "DATA")) .. ")", + backups:AddOption(nicename:Replace(".txt", "") .. " (" .. string.NiceSize(file_Size("pac3/__backup_save/" .. name, "DATA")) .. ")", function() pace.LoadParts("__backup_save/" .. name, true) end) @@ -671,7 +690,7 @@ local function populate_parts(menu, tbl, dir, override_part) local data = {} for key, part in pairs(pac.GetLocalParts()) do if not part:HasParent() and part:GetShowInEditor() then - table.insert(data, part:ToSaveTable()) + table_insert(data, part:ToSaveTable()) end end SetClipboardText(pace.luadata.Encode(data):sub(1, -1)) @@ -716,29 +735,27 @@ local function populate_parts(menu, tbl, dir, override_part) L"yes", function() local function delete_directory(dir) - local files, folders = file.Find(dir .. "*", "DATA") + local files, folders = file_Find(dir .. "*", "DATA") - for k, v in ipairs(files) do - file.Delete(dir .. v) + for i = 1, #files do + file.Delete(dir .. files[i]) end - for k, v in ipairs(folders) do - delete_directory(dir .. v .. "/") + for i = 1, #folders do + delete_directory(dir .. folders[i] .. "/") end - if file.Find(dir .. "*", "DATA")[1] then + if file_Find(dir .. "*", "DATA")[1] then Derma_Message("Cannot remove the directory.\nMaybe it contains hidden files?", "unable to remove directory", L"ok") else file.Delete(dir) end end + delete_directory("pac3/" .. dir .. "/") pace.RefreshFiles() end, - - L"no", function() - - end + L"no", function() end ) end):SetImage("icon16/folder_delete.png") end @@ -767,7 +784,7 @@ function pace.FixUniqueIDs(data) local function iterate(part) ids[part.self.UniqueID] = ids[part.self.UniqueID] or {} - table.insert(ids[part.self.UniqueID], part) + table_insert(ids[part.self.UniqueID], part) for key, part in pairs(part.children) do iterate(part) @@ -798,9 +815,9 @@ function pace.FixBadGrouping(data) for key, part in pairs(data) do if part.self.ClassName ~= "group" then - table.insert(parts, part) + table_insert(parts, part) else - table.insert(other, part) + table_insert(other, part) end end @@ -819,7 +836,7 @@ function pace.FixBadGrouping(data) } for k, v in pairs(other) do - table.insert(out, v) + table_insert(out, v) end return out diff --git a/lua/pac3/editor/client/settings.lua b/lua/pac3/editor/client/settings.lua index d6272efe6..552955dd0 100644 --- a/lua/pac3/editor/client/settings.lua +++ b/lua/pac3/editor/client/settings.lua @@ -736,7 +736,7 @@ function pace.FillBanPanel(pnl) ban_list:AddColumn("SteamID") ban_list:AddColumn("State") ban_list:SetSortable(false) - for _,ply in pairs(player.GetAll()) do + for _, ply in player.Iterator() do --print(ply, pace.IsBanned(ply)) ban_list:AddLine(ply:Name(),ply:SteamID(),player_ban_list[ply] or "Allowed") end @@ -808,7 +808,7 @@ function pace.FillCombatBanPanel(pnl) local combat_bans_temp_merger = {} - for _,ply in pairs(player.GetAll()) do + for _, ply in player.Iterator() do combat_bans_temp_merger[ply:SteamID()] = pac.global_combat_whitelist[ply:SteamID()]-- or {nick = ply:Nick(), steamid = ply:SteamID(), permission = "Default"} end @@ -861,7 +861,7 @@ function pace.FillCombatBanPanel(pnl) ban_list:Clear() local combat_bans_temp_merger = {} - for _,ply in pairs(player.GetAll()) do + for _, ply in player.Iterator() do combat_bans_temp_merger[ply:SteamID()] = pac.global_combat_whitelist[ply:SteamID()]-- or {nick = ply:Nick(), steamid = ply:SteamID(), permission = "Default"} end diff --git a/lua/pac3/editor/client/show_outfit_on_use.lua b/lua/pac3/editor/client/show_outfit_on_use.lua index 56eee8f57..d3e2d4fff 100644 --- a/lua/pac3/editor/client/show_outfit_on_use.lua +++ b/lua/pac3/editor/client/show_outfit_on_use.lua @@ -67,7 +67,7 @@ do local alpha = (lastDisplayLabel - RealTime()) / 2 local key = string_upper( input_LookupBinding( "use" ) or "use" ) local text = "Press " .. key .. " to reveal this persons PAC3 outfit" - draw.DrawText(L(text), "pac_onuse_only_hint", ScrW() / 2, ScrH() * 0.3, Color(255, 255, 255, alpha * 255), TEXT_ALIGN_CENTER) + draw.DrawText(L(text), "pac_onuse_only_hint", ScrW() * 0.5, ScrH() * 0.3, Color(255, 255, 255, alpha * 255), TEXT_ALIGN_CENTER) end) end @@ -78,14 +78,14 @@ end cvars.AddChangeCallback("pac_onuse_only", pace.OnUseOnlyUpdates, "PAC3") concommand.Add("pac_onuse_reset", function() - for i, ent in ipairs(ents.GetAll()) do + for _, ent in ents.Iterator() do if ent.pac_onuse_only then ent.pac_onuse_only_check = true if pac_IsPacOnUseOnly() then - pac.ToggleIgnoreEntity(ent, ent.pac_onuse_only_check, 'pac_onuse_only') + pac.ToggleIgnoreEntity(ent, ent.pac_onuse_only_check, "pac_onuse_only") else - pac.ToggleIgnoreEntity(ent, false, 'pac_onuse_only') + pac.ToggleIgnoreEntity(ent, false, "pac_onuse_only") end end end @@ -93,7 +93,7 @@ end) local transmissions = {} -timer.Create('pac3_transmissions_ttl', 1, 0, function() +timer.Create("pac3_transmissions_ttl", 1, 0, function() local time = RealTime() for transmissionID, data in pairs(transmissions) do diff --git a/lua/pac3/editor/client/spawnmenu.lua b/lua/pac3/editor/client/spawnmenu.lua index e5e35ca2c..4b8af88bf 100644 --- a/lua/pac3/editor/client/spawnmenu.lua +++ b/lua/pac3/editor/client/spawnmenu.lua @@ -104,9 +104,9 @@ end CreateClientConVar("pac_limit_sounds_draw_distance", 20000, true, false, "Overall multiplier for PAC3 sounds") cvars.AddChangeCallback("pac_limit_sounds_draw_distance", function(_,_,val) if not isnumber(val) then val = 0 end - pac.sounds_draw_dist_sqr = val * val + pac.sounds_draw_dist_sqr = val ^ 2 end) -pac.sounds_draw_dist_sqr = math.pow(GetConVar("pac_limit_sounds_draw_distance"):GetInt(), 2) +pac.sounds_draw_dist_sqr = GetConVar("pac_limit_sounds_draw_distance"):GetInt() ^ 2 CreateClientConVar("pac_volume", 1, true, false, "Overall multiplier for PAC3 sounds",0,1) cvars.AddChangeCallback("pac_volume", function(_,_,val) diff --git a/lua/pac3/editor/client/tools.lua b/lua/pac3/editor/client/tools.lua index 0445d31b1..459eca071 100644 --- a/lua/pac3/editor/client/tools.lua +++ b/lua/pac3/editor/client/tools.lua @@ -255,8 +255,9 @@ pace.AddTool(L"replace ogg with webaudio", function(part, suboption) audio:SetStopOnHide(not part:GetStopOnHide()) audio:SetPauseOnHide(part:GetPauseOnHide()) - for k,v in ipairs(part:GetChildren()) do - v:SetParent(audio) + local children = part:GetChildren() + for i = 1, #children do + children[i]:SetParent(audio) end part:Remove() @@ -291,8 +292,9 @@ pace.AddTool(L"scale this and children", function(part, suboption) part:SetSize(part:GetSize() * scale) end - for _, part in ipairs(part:GetChildren()) do - scale_parts(part, scale) + local children = part:GetChildren() + for i = 1, #children do + scale_parts(children[i], scale) end end @@ -314,14 +316,18 @@ pace.AddTool(L"free children from part" ,function(part, suboption) if grandparent == NULL then grandparent = part:GetRootPart() end + local parent = part - for _, child in ipairs(children) do + for i = 1, #children do + local child = children[i] + if child.BaseName ~= "base" and parent.BaseName ~= "base" then child:SetAngles(child.Angles + parent.Angles) child:SetPosition(child.Position + parent.Position) child:SetAngleOffset(child.AngleOffset + parent.AngleOffset) child:SetPositionOffset(child.PositionOffset + parent.PositionOffset) end + child:SetParent(grandparent) end end, L"no", function() end) @@ -341,7 +347,8 @@ pace.AddTool(L"square model scales...", function(part, suboption) part:SetScale(part:GetScale() * part:GetScale()) end end - if string.find(part:GetModel(),model) then + + if string.find(part:GetModel(), model) then square_scale(part) end end @@ -364,7 +371,6 @@ pace.AddTool(L"show only with active weapon", function(part, suboption) event:SetRootOwner(true) event:ParseArguments(class_name, suboption == 1) - end, L"hide weapon", L"show weapon") pace.AddTool(L"import editor tool from file...", function() @@ -423,67 +429,21 @@ pace.AddTool(L"round numbers", function(part) end end - for _, part in ipairs(part:GetChildren()) do - ify_parts(part) + local children = part:GetChildren() + for i = 1, #children do + ify_parts(children[i]) end end ify_parts(part) end) -do - - local function fix_name(str) - str = str:lower() - str = str:gsub("_", " ") - return str - end - - local hue = - { - "red", - "orange", - "yellow", - "green", - "turquoise", - "blue", - "purple", - "magenta", - } - - local sat = - { - "pale", - "", - "strong", - } - - local val = - { - "dark", - "", - "bright" - } - - local function 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] +pace.AddTool(L"clear names", function(part, suboptions) + for k,v in pairs(pac.GetLocalParts()) do + v:SetName("") end - - local function ColorToNames(c) - return HSVToNames(ColorToHSV(Color(c.r, c.g, c.b))) - end - - pace.AddTool(L"clear names", function(part, suboptions) - for k,v in pairs(pac.GetLocalParts()) do - v:SetName("") - end - pace.RefreshTree(true) - end) - -end + pace.RefreshTree(true) +end) pace.AddTool(L"Convert group of models to Expression 2 holograms", function(part) @@ -647,16 +607,19 @@ elseif (CoreStatus == "RunThisCode") { local function part_to_holo(part) local str_holo = str_ref - for CI, clip in ipairs(part:GetChildren()) do + local children = part:GetChildren() + for i = 1, #children do + local clip = children[i] + if not clip:IsHidden() then if clip.ClassName == "clip" then local pos, ang = clip.Position, clip:CalcAngles(clip.Angles) local normal = ang:Forward() - str_holo = str_holo .. " CN++, CT[CN,table] = table(I, " .. CI .. ", vec(" .. tovec(pos + normal) .. "), vec(" .. tovec(normal) .. "))\n" + str_holo = str_holo .. " CN++, CT[CN,table] = table(I, " .. i .. ", vec(" .. tovec(pos + normal) .. "), vec(" .. tovec(normal) .. "))\n" elseif clip.ClassName == "clip2" then local pos, ang = clip.Position, clip:CalcAngles(clip.Angles) local normal = ang:Forward() - str_holo = str_holo .. " CN++, CT[CN,table] = table(I, " .. CI .. ", vec(" .. tovec(pos) .. "), vec(" .. tovec(normal) .. "))\n" + str_holo = str_holo .. " CN++, CT[CN,table] = table(I, " .. i .. ", vec(" .. tovec(pos) .. "), vec(" .. tovec(normal) .. "))\n" end end end @@ -669,7 +632,7 @@ elseif (CoreStatus == "RunThisCode") { local holo = str_holo:gsub("[A-Z]+",{ ALPHA = math.Round(part:GetAlpha() * 255, 4), - COLOR = tovec((part.ProperColorRange and part:GetColor()*255) or part:GetColor()), + COLOR = tovec((part.ProperColorRange and part:GetColor() * 255) or part:GetColor()), SCALE = "vec(" .. tovec(Vector(scale.x, scale.y, scale.z)) .. ")", ANGLES = "ang(" .. toang(ang) .. ")", POSITION = "vec(" .. tovec(pos) .. ")", @@ -689,13 +652,18 @@ elseif (CoreStatus == "RunThisCode") { local function recursiveConvert(parent) if completed[parent] then return end completed[parent] = true - for key, part in ipairs(parent:GetChildren()) do - if part.is_model_part and not part:IsHidden() then - out[#out + 1] = part_to_holo(part) - recursiveConvert(part) + + local children = parent:GetChildren() + for i = 1, #children do + local child = children[i] + + if child.is_model_part and not child:IsHidden() then + out[#out + 1] = part_to_holo(child) + recursiveConvert(child) end end end + recursiveConvert(part) out[#out + 1] = str_footer @@ -718,7 +686,11 @@ pace.AddTool(L"record surrounding props to pac", function(part) origin:SetBone("none") origin:SetModel("models/dav0r/hoverball.mdl") - for key, ent in pairs(ents.FindInSphere(pac.EyePos, 1000)) do + local ents_tbl = ents.FindInSphere(pac.EyePos, 1000) + + for i = 1, #ents_tbl do + local ent = ents_tbl[i] + if not ent:IsPlayer() and not ent:IsNPC() and @@ -795,8 +767,10 @@ pace.AddTool(L"proxy/event: Engrave targets", function(part) local function reassign(part) if part.ClassName == "proxy" then if not IsValid(part.TargetPart) then - if part.AffectChildren and table.Count(part:GetChildren()) == 1 then - part:SetTargetPart(part:GetChildren()[1]) + local children = part:GetChildren() + + if part.AffectChildren and #children == 1 then + part:SetTargetPart(children[1]) part:SetAffectChildren(nil) else part:SetTargetPart(part:GetParent()) @@ -804,14 +778,17 @@ pace.AddTool(L"proxy/event: Engrave targets", function(part) end elseif part.ClassName == "event" then if not IsValid(part.DestinationPart) then - if part.AffectChildrenOnly == true and table.Count(part:GetChildren()) == 1 then - part:SetDestinationPart(part:GetChildren()[1]) + local children = part:GetChildren() + + if part.AffectChildrenOnly == true and #children == 1 then + part:SetDestinationPart(children[1]) elseif part.AffectChildrenOnly == false then part:SetDestinationPart(part:GetParent()) end end end end + if part ~= part:GetRootPart() then reassign(part) else @@ -823,16 +800,15 @@ end) --aka pace.UltraCleanup pace.AddTool(L"Destroy hidden parts, proxies and events", function(part) - if not part then part = pace.current_part end root = part:GetRootPart() pnl = Derma_Query("Only do this if you know what you're doing!\nMark parts as important in their notes to protect them.", "Warning", - "Destroy!", function() pace.UltraCleanup( root ) end, + "Destroy!", function() pace.UltraCleanup(root) end, "cancel", nil ) - pnl:SetWidth(300) + pnl:SetWidth(300) end) pace.AddTool(L"stop all custom animations", function() diff --git a/lua/pac3/editor/client/view.lua b/lua/pac3/editor/client/view.lua index 1d36dab55..dc3b57b70 100644 --- a/lua/pac3/editor/client/view.lua +++ b/lua/pac3/editor/client/view.lua @@ -192,7 +192,10 @@ local function CalcDrag() origin = owner:GetPos() if owner == pac.WorldEntity then if part:HasChildren() then - for key, child in ipairs(part:GetChildren()) do + local children = part:GetChildren() + for i = 1, #children do + local child = children[i] + if child.GetDrawPosition then part = child break @@ -237,7 +240,6 @@ local function CalcDrag() end end - if pace.delaymovement < RealTime() then if MovementBindDown("forward") then pace.ViewPos = pace.ViewPos + pace.ViewAngles:Forward() * mult * ftime @@ -261,7 +263,6 @@ local function CalcDrag() end end end - end local follow_entity = CreateClientConVar("pac_camera_follow_entity", "0", true) diff --git a/lua/pac3/editor/client/wear.lua b/lua/pac3/editor/client/wear.lua index 038b8123e..6c426ce0d 100644 --- a/lua/pac3/editor/client/wear.lua +++ b/lua/pac3/editor/client/wear.lua @@ -406,10 +406,13 @@ do end end) + local min_velocity_sqr = 50 + min_velocity_sqr = min_velocity_sqr * min_velocity_sqr + pac.AddHook("KeyRelease", "request_outfits", function() local me = pac.LocalPlayer - if me:IsValid() and me:GetVelocity():Length() > 50 then + if me:IsValid() and me:GetVelocity():LengthSqr() > min_velocity_sqr then frames = frames + 200 if frames > 400 then diff --git a/lua/pac3/editor/client/wear_filter.lua b/lua/pac3/editor/client/wear_filter.lua index 7fa9b805b..9c118ec91 100644 --- a/lua/pac3/editor/client/wear_filter.lua +++ b/lua/pac3/editor/client/wear_filter.lua @@ -52,7 +52,8 @@ local function jsonid(ply) end local function update_ignore() - for _, ply in ipairs(player.GetHumans()) do + for _, ply in player.Iterator() do + if ply:IsBot() then continue end pac.ToggleIgnoreEntity(ply, pace.ShouldIgnorePlayer(ply), "wear_filter") end end @@ -171,11 +172,11 @@ do end end -CreateClientConVar("pace_wear_filter_mode", "disabled") -CreateClientConVar("pace_outfit_filter_mode", "disabled") +local pace_wear_filter_mode = CreateClientConVar("pace_wear_filter_mode", "disabled") +local pace_outfit_filter_mode = CreateClientConVar("pace_outfit_filter_mode", "disabled") function pace.ShouldIgnorePlayer(ply) - local mode = GetConVar("pace_outfit_filter_mode"):GetString() + local mode = pace_outfit_filter_mode:GetString() if mode == "steam_friends" then return ply:GetFriendStatus() ~= "friend" @@ -189,12 +190,12 @@ function pace.ShouldIgnorePlayer(ply) end function pace.CreateWearFilter() - local mode = GetConVar("pace_wear_filter_mode"):GetString() + local mode = pace_wear_filter_mode:GetString() local tbl = {} - for _, ply in ipairs(player.GetHumans()) do - if ply == pac.LocalPlayer then continue end + for _, ply in player.Iterator() do + if ply == pac.LocalPlayer or ply:IsBot() then continue end if mode == "steam_friends" then if ply:GetFriendStatus() == "friend" then @@ -249,8 +250,9 @@ local function player_list_form(name, id, help) local blacklist = cache[id] local tbl = {} - for _, ply in ipairs(player.GetHumans()) do - if ply == pac.LocalPlayer then continue end + for _, ply in player.Iterator() do + if ply == pac.LocalPlayer or ply:IsBot() then continue end + if not blacklist[jsonid(ply)] then table.insert(tbl, { name = ply:Nick(), @@ -319,8 +321,8 @@ do end) function pace.PopulateWearMenu(menu) - for _, ply in ipairs(player.GetHumans()) do - if ply == pac.LocalPlayer then continue end + for _, ply in player.Iterator() do + if ply == pac.LocalPlayer or ply:IsBot() then continue end local icon = menu:AddOption(L "wear only for " .. ply:Nick(), function() pace.WearParts(ply) @@ -366,12 +368,12 @@ function pace.FillWearSettings(pnl) mode.form = generic_form(L "Everyone can see your worn outfit.") end - GetConVar("pace_wear_filter_mode"):SetString(value:gsub(" ", "_")) + pace_wear_filter_mode:SetString(value:gsub(" ", "_")) mode.form:SetParent(list) end - local mode_str = GetConVar("pace_wear_filter_mode"):GetString():gsub("_", " ") + local mode_str = pace_wear_filter_mode:GetString():gsub("_", " ") mode:ChooseOption(mode_str) mode:OnSelect(nil, mode_str) end @@ -408,14 +410,14 @@ function pace.FillWearSettings(pnl) mode.form = generic_form(L "You will see everyone's outfits.") end - GetConVar("pace_outfit_filter_mode"):SetString(value:gsub(" ", "_")) + pace_outfit_filter_mode:SetString(value:gsub(" ", "_")) mode.form:SetParent(list) update_ignore() end - local mode_str = GetConVar("pace_outfit_filter_mode"):GetString():gsub("_", " ") + local mode_str = pace_outfit_filter_mode:GetString():gsub("_", " ") mode:ChooseOption(mode_str) mode:OnSelect(nil, mode_str) end diff --git a/lua/pac3/editor/server/bans.lua b/lua/pac3/editor/server/bans.lua index f686c523b..5fb359cde 100644 --- a/lua/pac3/editor/server/bans.lua +++ b/lua/pac3/editor/server/bans.lua @@ -75,7 +75,7 @@ function pace.Unban(ply) end local function GetPlayer(target) - for key, ply in pairs(player.GetAll()) do + for _, ply in player.Iterator() do if ply:SteamID() == target or ply:UniqueID() == target or ply:Nick():lower():find(target:lower()) then return ply end @@ -118,7 +118,7 @@ end net.Receive("pac.BanUpdate", function(len, ply) pac.Message("Received ban list update operation from : ", ply) - pac.Message("Time : ", os.date( "%a %X %x", os.time() )) + pac.Message("Time : ", os.date("%a %X %x", os.time())) local playerlist = net.ReadTable() for i,v in pairs(playerlist) do if playerlist[i] == "Allowed" then @@ -130,12 +130,12 @@ net.Receive("pac.BanUpdate", function(len, ply) end end) -net.Receive("pac.RequestBanStates", function(len,ply) +net.Receive("pac.RequestBanStates", function(len, ply) local archive = net.ReadBool() pac.Message("Received ban list request from : ", ply) - pac.Message("Time : ", os.date( "%a %X %x", os.time() )) + pac.Message("Time : ", os.date("%a %X %x", os.time())) local players = {} - for _,v in pairs(player.GetAll()) do + for _, v in player.Iterator() do players[v] = false end if not pace.Bans then diff --git a/lua/pac3/editor/server/init.lua b/lua/pac3/editor/server/init.lua index 32512077d..ff89c6a9e 100644 --- a/lua/pac3/editor/server/init.lua +++ b/lua/pac3/editor/server/init.lua @@ -22,7 +22,7 @@ do end end -CreateConVar("pac_sv_prop_outfits", "0", CLIENT and {FCVAR_REPLICATED} or {FCVAR_ARCHIVE, FCVAR_REPLICATED}, "Allow applying parts on other entities serverside\n0=don't\n1=allow on props but not players\n2=allow on other players") +local pac_sv_prop_outfits = CreateConVar("pac_sv_prop_outfits", "0", CLIENT and {FCVAR_REPLICATED} or {FCVAR_ARCHIVE, FCVAR_REPLICATED}, "Allow applying parts on other entities serverside\n0=don't\n1=allow on props but not players\n2=allow on other players") function pace.CanPlayerModify(ply, ent) if not IsValid(ply) or not IsValid(ent) then @@ -45,10 +45,10 @@ function pace.CanPlayerModify(ply, ent) return true end - if GetConVar("pac_sv_prop_outfits"):GetInt() ~= 0 then - if GetConVar("pac_sv_prop_outfits"):GetInt() == 1 then + if pac_sv_prop_outfits:GetInt() ~= 0 then + if pac_sv_prop_outfits:GetInt() == 1 then return not (ply ~= ent and ent:IsPlayer()) - elseif GetConVar("pac_sv_prop_outfits"):GetInt() == 2 then + elseif pac_sv_prop_outfits:GetInt() == 2 then return true end @@ -61,8 +61,6 @@ function pace.CanPlayerModify(ply, ent) end end - - return false end @@ -87,6 +85,7 @@ do if not ply.pac_last_editor_message then ply.pac_last_editor_message = 0 end + if ply.pac_last_editor_message > CurTime() then return end ply.pac_last_editor_message = CurTime() + 0.2 @@ -95,7 +94,7 @@ do local part_pos = net.ReadVector() net.Start("pac_in_editor_posang", true) - net.WriteEntity(ply) + net.WritePlayer(ply) net.WriteVector(pos) net.WriteAngle(ang) net.WriteVector(part_pos) @@ -103,7 +102,6 @@ do end) end - CreateConVar("has_pac3_editor", "1", {FCVAR_NOTIFY}) resource.AddSingleFile("materials/icon64/new pac icon.png") diff --git a/lua/pac3/extra/client/contraption.lua b/lua/pac3/extra/client/contraption.lua index 28c7cb429..2cefc9c3a 100644 --- a/lua/pac3/extra/client/contraption.lua +++ b/lua/pac3/extra/client/contraption.lua @@ -36,9 +36,12 @@ function pacx.PartToContraptionData(part, tbl) table.insert(tbl, data) end - for key, part in ipairs(part:GetChildren()) do - if part.is_model_part then - pacx.PartToContraptionData(part, tbl) + local children = part:GetChildren() + for i = 1, #children do + local child = children[i] + + if child.is_model_part then + pacx.PartToContraptionData(child, tbl) end end diff --git a/lua/pac3/extra/shared/init.lua b/lua/pac3/extra/shared/init.lua index 5381081a1..5b59a4936 100644 --- a/lua/pac3/extra/shared/init.lua +++ b/lua/pac3/extra/shared/init.lua @@ -1,4 +1,3 @@ - include("hands.lua") include("pac_weapon.lua") include("projectiles.lua") @@ -7,19 +6,30 @@ include("net_combat.lua") local cvar = CreateConVar("pac_restrictions", "0", FCVAR_REPLICATED) if CLIENT then + local mins, maxs = Vector(-8, -8, -8), Vector(8, 8, 8) + pac.AddHook("pac_EditorCalcView", "restrictions", function() - if cvar:GetInt() > 0 and not pac.LocalPlayer:IsAdmin() then + if cvar:GetBool() and not pac.LocalPlayer:IsAdmin() then local ent = pace.GetViewEntity() + local dir = pace.ViewPos - ent:EyePos() - local dist = ent:BoundingRadius() * ent:GetModelScale() * 4 + local dist = ent:BoundingRadius() * (5 + ent:GetModelScale()) + local filter = player.GetAll() table.insert(filter, ent) - if dir:Length() > dist then + if dir:LengthSqr() > (dist * dist) then pace.ViewPos = ent:EyePos() + (dir:GetNormalized() * dist) end - local res = util.TraceHull({start = ent:EyePos(), endpos = pace.ViewPos, filter = filter, mins = Vector(1,1,1)*-8, maxs = Vector(1,1,1)*8}) + local res = util.TraceHull({ + start = ent:EyePos(), + endpos = pace.ViewPos, + filter = filter, + mins = mins, + maxs = maxs + }) + if res.Hit then return res.HitPos end diff --git a/lua/pac3/extra/shared/net_combat.lua b/lua/pac3/extra/shared/net_combat.lua index a81418816..2dbfb18b5 100644 --- a/lua/pac3/extra/shared/net_combat.lua +++ b/lua/pac3/extra/shared/net_combat.lua @@ -347,9 +347,16 @@ if SERVER then return true end + --counts all players (faster than player.GetCount) + local function PlayerCount() + local count = 0 + for _, v in player.Iterator() do count = count + 1 end + return count + end + --stopping condition to stop force or damage operation if too many entities, because net impact is proportional to players local function TooManyEnts(count) - local playercount = player.GetCount() + local playercount = PlayerCount() local hard_limit = raw_ent_limit:GetInt() local per_ply = per_ply_limit:GetInt() --print(count .. " compared against hard limit " .. hard_limit .. " and " .. playercount .. " players*" .. per_ply .. " limit (" .. count*playercount .. " | " .. playercount*per_ply .. ")") @@ -429,7 +436,7 @@ if SERVER then end if bool == nil then - for i,ply in pairs(player.GetAll()) do + for _, ply in player.Iterator() do if ply.grabbed_ents[ent] then ply.grabbed_ents[ent] = nil print(ent , "no longer grabbed by", ply) @@ -737,8 +744,10 @@ if SERVER then end) local function MergeTargetsByID(tbl1, tbl2) - for i,v in ipairs(tbl2) do - tbl1[v:EntIndex()] = v + --tbl2 is always a ents.Find* results table + for i = 1, #tbl2 do + local ent = tbl2[i] + tbl1[ent:EntIndex()] = ent end end @@ -747,6 +756,7 @@ if SERVER then local ent_count = 0 local ply_count = 0 local ply_prog_count = 0 + for i,v in pairs(ents_hits) do if not (v:IsPlayer() or Is_NPC(v)) and not tbl.PointEntities then ents_hits[i] = nil end if v.CPPICanDamage and not v:CPPICanDamage(ply) then ents_hits[i] = nil end --CPPI check on the player @@ -764,7 +774,7 @@ if SERVER then end --dangerous conditions: absurd amounts of entities, damaging a large percentage of the server's players beyond a certain point - if TooManyEnts(ent_count) or ((ply_count) > 12 and (ply_count > player_fraction:GetFloat() * player.GetCount())) then + if TooManyEnts(ent_count) or ((ply_count) > 12 and (ply_count > player_fraction:GetFloat() * PlayerCount())) then print("early exit") return false,false,nil,{},{} end @@ -1164,7 +1174,7 @@ if SERVER then --second stage of force: apply local function ProcessForcesList(ents_hits, tbl, pos, ang, ply) local ent_count = 0 - for i,v in pairs(ents_hits) do + for i, v in pairs(ents_hits) do if v.CPPICanPickup and not v:CPPICanPickup(ply) then ents_hits[i] = nil end if v.CPPICanPunt and not v:CPPICanPunt(ply) then ents_hits[i] = nil end if v:IsConstraint() then ents_hits[i] = nil end @@ -1177,10 +1187,9 @@ if SERVER then local ent_getphysobj = ent:GetPhysicsObject() local owner = Try_CPPIGetOwner(ent) local is_player = ent:IsPlayer() - local is_physics = (physics_point_ent_classes[ent:GetClass()] or string.find(ent:GetClass(),"item_") or string.find(ent:GetClass(),"ammo_") or (ent:IsWeapon() and not IsValid(ent:GetOwner()))) + local is_physics = (physics_point_ent_classes[ent:GetClass()] or string.find(ent:GetClass(), "item_") or string.find(ent:GetClass(), "ammo_") or (ent:IsWeapon() and not IsValid(ent:GetOwner()))) local is_npc = Is_NPC(ent) - if (ent ~= tbl.RootPartOwner or (tbl.AffectSelf and ent == tbl.RootPartOwner)) and ( is_player @@ -1205,12 +1214,11 @@ if SERVER then if IsValid(phys_ent) then oldvel = phys_ent:GetVelocity() else - oldvel = Vector(0,0,0) + oldvel = Vector(0, 0, 0) end - - local addvel = Vector(0,0,0) - local add_angvel = Vector(0,0,0) + local addvel = Vector(0, 0, 0) + local add_angvel = Vector(0, 0, 0) local ent_center = ent:WorldSpaceCenter() or ent:GetPos() @@ -1229,7 +1237,7 @@ if SERVER then --clamp the delta to the ratio levitation height if tbl.Levitation then - up_mult = math.Clamp(height_delta / (5 + math.abs(tbl.LevitationHeight)),-1,1) + up_mult = math.Clamp(height_delta / (5 + math.abs(tbl.LevitationHeight)), -1, 1) end if tbl.BaseForceAngleMode == "Radial" then --radial on self @@ -1244,34 +1252,34 @@ if SERVER then addvel = addvel + tbl.AddedVectorForce elseif tbl.VectorForceAngleMode == "Local" then --local on self addvel = addvel - +ang:Forward()*tbl.AddedVectorForce.x - +ang:Right()*tbl.AddedVectorForce.y - +ang:Up()*tbl.AddedVectorForce.z + + ang:Forward() * tbl.AddedVectorForce.x + + ang:Right() * tbl.AddedVectorForce.y + + ang:Up() * tbl.AddedVectorForce.z elseif tbl.VectorForceAngleMode == "Radial" then --relative to locus or self ang2 = dir:Angle() addvel = addvel - +ang2:Forward()*tbl.AddedVectorForce.x - +ang2:Right()*tbl.AddedVectorForce.y - +ang2:Up()*tbl.AddedVectorForce.z + + ang2:Forward() * tbl.AddedVectorForce.x + + ang2:Right() * tbl.AddedVectorForce.y + + ang2:Up() * tbl.AddedVectorForce.z elseif tbl.VectorForceAngleMode == "RadialNoPitch" then --relative to locus or self dir.z = 0 ang2 = dir:Angle() addvel = addvel - +ang2:Forward()*tbl.AddedVectorForce.x - +ang2:Right()*tbl.AddedVectorForce.y - +ang2:Up()*tbl.AddedVectorForce.z + + ang2:Forward() * tbl.AddedVectorForce.x + + ang2:Right() * tbl.AddedVectorForce.y + + ang2:Up() * tbl.AddedVectorForce.z end if tbl.TorqueMode == "Global" then add_angvel = tbl.Torque elseif tbl.TorqueMode == "Local" then - add_angvel = ang:Forward()*tbl.Torque.x + ang:Right()*tbl.Torque.y + ang:Up()*tbl.Torque.z + add_angvel = ang:Forward() * tbl.Torque.x + ang:Right() * tbl.Torque.y + ang:Up() * tbl.Torque.z elseif tbl.TorqueMode == "TargetLocal" then add_angvel = tbl.Torque elseif tbl.TorqueMode == "Radial" then ang2 = dir:Angle() - addvel = ang2:Forward()*tbl.Torque.x + ang2:Right()*tbl.Torque.y + ang2:Up()*tbl.Torque.z + addvel = ang2:Forward() * tbl.Torque.x + ang2:Right() * tbl.Torque.y + ang2:Up() * tbl.Torque.z end local islocaltorque = tbl.TorqueMode == "TargetLocal" @@ -1284,15 +1292,15 @@ if SERVER then end if is_phys and tbl.AccountMass then if not is_npc then - addvel = addvel * (1 / math.max(mass,0.1)) + addvel = addvel * (1 / math.max(mass, 0.1)) else addvel = addvel end - add_angvel = add_angvel * (1 / math.max(mass,0.1)) + add_angvel = add_angvel * (1 / math.max(mass, 0.1)) end if tbl.Falloff then - dist_multiplier = math.Clamp(1 - distance / math.max(tbl.Radius, tbl.Length),0,1) + dist_multiplier = math.Clamp(1 - distance / math.max(tbl.Radius, tbl.Length), 0, 1) end if tbl.ReverseFalloff then dist_multiplier = 1 - math.Clamp(1 - distance / math.max(tbl.Radius, tbl.Length),0,1) @@ -1405,41 +1413,45 @@ if SERVER then local ents_hits = {} if tbl.Length ~= 0 and tbl.Radius ~= 0 then local counter = 0 - MergeTargetsByID(ents_hits,ents.FindInSphere(pos, tbl.Radius)) - for i=0,1,1/(math.abs(tbl.Length/tbl.Radius)) do - MergeTargetsByID(ents_hits,ents.FindInSphere(pos + ang:Forward()*tbl.Length*i, tbl.Radius)) + MergeTargetsByID(ents_hits, ents.FindInSphere(pos, tbl.Radius)) + for i = 0, 1, 1 / math.abs(tbl.Length/tbl.Radius) do + MergeTargetsByID(ents_hits, ents.FindInSphere(pos + ang:Forward() * tbl.Length * i, tbl.Radius)) if counter == 200 then break end counter = counter + 1 end - MergeTargetsByID(ents_hits,ents.FindInSphere(pos + ang:Forward()*tbl.Length, tbl.Radius)) + MergeTargetsByID(ents_hits, ents.FindInSphere(pos + ang:Forward() * tbl.Length, tbl.Radius)) --render.DrawWireframeSphere( self:GetWorldPosition() + self:GetWorldAngles():Forward()*(self.Length - 0.5*self.Radius), 0.5*self.Radius, 10, 10, Color( 255, 255, 255 ) ) - elseif tbl.Radius == 0 then MergeTargetsByID(ents_hits,ents.FindAlongRay(pos, pos + ang:Forward()*tbl.Length)) end + elseif tbl.Radius == 0 then + MergeTargetsByID(ents_hits, ents.FindAlongRay(pos, pos + ang:Forward() * tbl.Length)) + end ProcessForcesList(ents_hits, tbl, pos, ang, ply) elseif tbl.HitboxMode == "Cone" then local ents_hits = {} local steps - steps = math.Clamp(4*math.ceil(tbl.Length / (tbl.Radius or 1)),1,50) - for i = 1,0,-1/steps do - MergeTargetsByID(ents_hits,ents.FindInSphere(pos + ang:Forward()*tbl.Length*i, i * tbl.Radius)) + steps = math.Clamp(4 * math.ceil(tbl.Length / (tbl.Radius or 1)), 1, 50) + for i = 1, 0, -1 / steps do + MergeTargetsByID(ents_hits, ents.FindInSphere(pos + ang:Forward() * tbl.Length * i, i * tbl.Radius)) end steps = math.Clamp(math.ceil(tbl.Length / (tbl.Radius or 1)),1,4) - if tbl.Radius == 0 then MergeTargetsByID(ents_hits,ents.FindAlongRay(pos, pos + ang:Forward()*tbl.Length)) end + if tbl.Radius == 0 then MergeTargetsByID(ents_hits, ents.FindAlongRay(pos, pos + ang:Forward() * tbl.Length)) end ProcessForcesList(ents_hits, tbl, pos, ang, ply) - elseif tbl.HitboxMode =="Ray" then - local startpos = pos + Vector(0,0,0) - local endpos = pos + ang:Forward()*tbl.Length + elseif tbl.HitboxMode == "Ray" then + local startpos = pos + vector_origin + local endpos = pos + ang:Forward() * tbl.Length + ents_hits = ents.FindAlongRay(startpos, endpos) ProcessForcesList(ents_hits, tbl, pos, ang, ply) if tbl.Bullet then local bullet = {} bullet.Src = pos + ang:Forward() - bullet.Dir = ang:Forward()*50000 + bullet.Dir = ang:Forward() * 50000 bullet.Damage = -1 bullet.Force = 0 bullet.Entity = dmg_info:GetAttacker() + dmg_info:GetInflictor():FireBullets(bullet) end end @@ -1464,7 +1476,7 @@ if SERVER then --lock break order from client net.Receive("pac_signal_stop_lock", function(len,ply) - if not pac.RatelimitPlayer( ply, "pac_signal_stop_lock", 3, 5, {"Player ", ply, " is spamming pac_signal_stop_lock!"} ) then + if not pac.RatelimitPlayer(ply, "pac_signal_stop_lock", 3, 5, {"Player ", ply, " is spamming pac_signal_stop_lock!"}) then return end ApplyLockState(ply, false) @@ -1481,9 +1493,9 @@ if SERVER then net.Send(ply.grabbed_by) end --What if there's more? try to find it AMONG US SUS! - for _,ent in pairs(player.GetAll()) do + for _, ent in player.Iterator() do if ent.grabbed_ents and ent ~= ply.grabbed_by then --a player! time to inspect! but skip the already found grabber - for _,grabbed in pairs(ent.grabbed_ents) do --check all her entities + for _, grabbed in pairs(ent.grabbed_ents) do --check all her entities if ply == grabbed then --that's us! net.Start("pac_request_lock_break") net.WriteEntity(ply) @@ -1782,47 +1794,47 @@ if SERVER then end steps = math.max(steps + math.abs(tbl.ExtraSteps),1) - for ringnumber=1,0,-1/steps do --concentric circles go smaller and smaller by lowering the i multiplier + for ringnumber = 1, 0, -1 / steps do --concentric circles go smaller and smaller by lowering the i multiplier phase = math.random() - local ray_thickness = math.Clamp(0.5*math.log(tbl.Radius) + 0.05*tbl.Radius,0,10)*(1 - 0.7*ringnumber) - for i=1,0,-1/sides do + local ray_thickness = math.Clamp(0.5 * math.log(tbl.Radius) + 0.05 * tbl.Radius, 0, 10) * (1 - 0.7 * ringnumber) + for i = 1, 0, -1 / sides do if ringnumber == 0 then i = 0 end - x = ang:Right()*math.cos(2 * math.pi * i + phase * tbl.PhaseRandomize)*tbl.Radius*ringnumber*(1 - math.random() * (ringnumber) * tbl.RadialRandomize) - y = ang:Up() *math.sin(2 * math.pi * i + phase * tbl.PhaseRandomize)*tbl.Radius*ringnumber*(1 - math.random() * (ringnumber) * tbl.RadialRandomize) + x = ang:Right() * math.cos(2 * math.pi * i + phase * tbl.PhaseRandomize) * tbl.Radius * ringnumber * (1 - math.random() * (ringnumber) * tbl.RadialRandomize) + y = ang:Up() * math.sin(2 * math.pi * i + phase * tbl.PhaseRandomize) * tbl.Radius * ringnumber * (1 - math.random() * (ringnumber) * tbl.RadialRandomize) local startpos = pos + x + y - local endpos = pos + ang:Forward()*tbl.Length + x + y - MergeTargetsByID(ents_hits, ents.FindAlongRay(startpos, endpos, maximized_ray_mins_maxs(startpos,endpos,ray_thickness))) + local endpos = pos + ang:Forward() * tbl.Length + x + y + MergeTargetsByID(ents_hits, ents.FindAlongRay(startpos, endpos, maximized_ray_mins_maxs(startpos, endpos, ray_thickness))) end end if tbl.HitboxMode == "CylinderHybrid" and tbl.Length ~= 0 then --fast sphere check on the wide end if tbl.Length/tbl.Radius >= 2 then - MergeTargetsByID(ents_hits,ents.FindInSphere(pos + ang:Forward()*(tbl.Length - tbl.Radius), tbl.Radius)) - MergeTargetsByID(ents_hits,ents.FindInSphere(pos + ang:Forward()*tbl.Radius, tbl.Radius)) + MergeTargetsByID(ents_hits, ents.FindInSphere(pos + ang:Forward()*(tbl.Length - tbl.Radius), tbl.Radius)) + MergeTargetsByID(ents_hits, ents.FindInSphere(pos + ang:Forward()*tbl.Radius, tbl.Radius)) if tbl.Radius ~= 0 then local counter = 0 - for i=math.floor(tbl.Length / tbl.Radius) - 1,1,-1 do - MergeTargetsByID(ents_hits,ents.FindInSphere(pos + ang:Forward()*(tbl.Radius*i), tbl.Radius)) + for i = math.floor(tbl.Length / tbl.Radius) - 1, 1, -1 do + MergeTargetsByID(ents_hits, ents.FindInSphere(pos + ang:Forward() * (tbl.Radius * i), tbl.Radius)) if counter == 100 then break end counter = counter + 1 end end end end - elseif tbl.Radius == 0 then MergeTargetsByID(ents_hits,ents.FindAlongRay(pos, pos + ang:Forward()*tbl.Length)) end + elseif tbl.Radius == 0 then MergeTargetsByID(ents_hits, ents.FindAlongRay(pos, pos + ang:Forward() * tbl.Length)) end elseif tbl.HitboxMode == "CylinderSpheres" then ents_hits = {} if tbl.Length ~= 0 and tbl.Radius ~= 0 then local counter = 0 - MergeTargetsByID(ents_hits,ents.FindInSphere(pos, tbl.Radius)) - for i=0,1,1/(math.abs(tbl.Length/tbl.Radius)) do - MergeTargetsByID(ents_hits,ents.FindInSphere(pos + ang:Forward()*tbl.Length*i, tbl.Radius)) + MergeTargetsByID(ents_hits, ents.FindInSphere(pos, tbl.Radius)) + for i = 0, 1, 1 / math.abs(tbl.Length / tbl.Radius) do + MergeTargetsByID(ents_hits, ents.FindInSphere(pos + ang:Forward() * tbl.Length * i, tbl.Radius)) if counter == 200 then break end counter = counter + 1 end - MergeTargetsByID(ents_hits,ents.FindInSphere(pos + ang:Forward()*tbl.Length, tbl.Radius)) - elseif tbl.Radius == 0 then MergeTargetsByID(ents_hits,ents.FindAlongRay(pos, pos + ang:Forward()*tbl.Length)) end + MergeTargetsByID(ents_hits, ents.FindInSphere(pos + ang:Forward() * tbl.Length, tbl.Radius)) + elseif tbl.Radius == 0 then MergeTargetsByID(ents_hits, ents.FindAlongRay(pos, pos + ang:Forward() * tbl.Length)) end elseif tbl.HitboxMode == "Cone" or tbl.HitboxMode == "ConeHybrid" then ents_hits = {} @@ -1830,25 +1842,25 @@ if SERVER then local sides = tbl.Detail if tbl.Detail < 1 then sides = 1 end local startpos = pos-- + Vector(0, self.Radius,self.Radius) - local area_factor = tbl.Radius*tbl.Radius / (400 + 100*tbl.Length/math.max(tbl.Radius,0.1)) --bigger radius means more rays needed to cast to approximate the cylinder detection - local steps = 3 + math.ceil(4*(area_factor / ((4 + tbl.Length/4) / (20 / math.max(tbl.Detail,1))))) + local area_factor = tbl.Radius * tbl.Radius / (400 + 100 * tbl.Length / math.max(tbl.Radius, 0.1)) --bigger radius means more rays needed to cast to approximate the cylinder detection + local steps = 3 + math.ceil(4 * (area_factor / ((4 + tbl.Length / 4) / (20 / math.max(tbl.Detail, 1))))) if tbl.HitboxMode == "ConeHybrid" and tbl.Length ~= 0 then - area_factor = 0.15*area_factor - steps = 1 + math.ceil(4*(area_factor / ((4 + tbl.Length/4) / (20 / math.max(tbl.Detail,1))))) + area_factor = 0.15 * area_factor + steps = 1 + math.ceil(4 * (area_factor / ((4 + tbl.Length / 4) / (20 / math.max(tbl.Detail, 1))))) end - steps = math.max(steps + math.abs(tbl.ExtraSteps),1) + steps = math.max(steps + math.abs(tbl.ExtraSteps), 1) local timestart = SysTime() local casts = 0 - for ringnumber=1,0,-1/steps do --concentric circles go smaller and smaller by lowering the ringnumber multiplier + for ringnumber = 1, 0, -1 / steps do --concentric circles go smaller and smaller by lowering the ringnumber multiplier phase = math.random() local ray_thickness = 5 * (2 - ringnumber) - for i=1,0,-1/sides do + for i = 1, 0, -1 / sides do if ringnumber == 0 then i = 0 end - x = ang:Right()*math.cos(2 * math.pi * i + phase * tbl.PhaseRandomize)*tbl.Radius*ringnumber*(1 - math.random() * (ringnumber) * tbl.RadialRandomize) - y = ang:Up() *math.sin(2 * math.pi * i + phase * tbl.PhaseRandomize)*tbl.Radius*ringnumber*(1 - math.random() * (ringnumber) * tbl.RadialRandomize) - local endpos = pos + ang:Forward()*tbl.Length + x + y - MergeTargetsByID(ents_hits,ents.FindAlongRay(startpos, endpos, maximized_ray_mins_maxs(startpos,endpos,ray_thickness))) + x = ang:Right() * math.cos(2 * math.pi * i + phase * tbl.PhaseRandomize) * tbl.Radius * ringnumber * (1 - math.random() * (ringnumber) * tbl.RadialRandomize) + y = ang:Up() * math.sin(2 * math.pi * i + phase * tbl.PhaseRandomize) * tbl.Radius * ringnumber * (1 - math.random() * (ringnumber) * tbl.RadialRandomize) + local endpos = pos + ang:Forward() * tbl.Length + x + y + MergeTargetsByID(ents_hits, ents.FindAlongRay(startpos, endpos, maximized_ray_mins_maxs(startpos, endpos, ray_thickness))) casts = casts + 1 end end @@ -1856,39 +1868,40 @@ if SERVER then --fast sphere check on the wide end local radius_multiplier = math.atan(math.abs(ratio)) / (1.5 + 0.1*math.sqrt(ratio)) if ratio > 0.5 then - MergeTargetsByID(ents_hits,ents.FindInSphere(pos + ang:Forward()*(tbl.Length - tbl.Radius * radius_multiplier), tbl.Radius * radius_multiplier)) + MergeTargetsByID(ents_hits, ents.FindInSphere(pos + ang:Forward() * (tbl.Length - tbl.Radius * radius_multiplier), tbl.Radius * radius_multiplier)) end end - elseif tbl.Radius == 0 then MergeTargetsByID(ents_hits,ents.FindAlongRay(pos, pos + ang:Forward()*tbl.Length)) end + elseif tbl.Radius == 0 then MergeTargetsByID(ents_hits, ents.FindAlongRay(pos, pos + ang:Forward() * tbl.Length)) end elseif tbl.HitboxMode == "ConeSpheres" then ents_hits = {} local steps - steps = math.Clamp(4*math.ceil(tbl.Length / (tbl.Radius or 1)),1,50) + steps = math.Clamp(4 * math.ceil(tbl.Length / (tbl.Radius or 1)), 1, 50) for i = 1,0,-1/steps do - MergeTargetsByID(ents_hits,ents.FindInSphere(pos + ang:Forward()*tbl.Length*i, i * tbl.Radius)) + MergeTargetsByID(ents_hits, ents.FindInSphere(pos + ang:Forward() * tbl.Length * i, i * tbl.Radius)) end - steps = math.Clamp(math.ceil(tbl.Length / (tbl.Radius or 1)),1,4) + steps = math.Clamp(math.ceil(tbl.Length / (tbl.Radius or 1)), 1, 4) - if tbl.Radius == 0 then MergeTargetsByID(ents_hits,ents.FindAlongRay(pos, pos + ang:Forward()*tbl.Length)) end + if tbl.Radius == 0 then MergeTargetsByID(ents_hits, ents.FindAlongRay(pos, pos + ang:Forward() * tbl.Length)) end elseif tbl.HitboxMode =="Ray" then - local startpos = pos + Vector(0,0,0) - local endpos = pos + ang:Forward()*tbl.Length + local startpos = pos + Vector(0, 0, 0) + local endpos = pos + ang:Forward() * tbl.Length ents_hits = ents.FindAlongRay(startpos, endpos) if tbl.Bullet then local bullet = {} bullet.Src = pos + ang:Forward() - bullet.Dir = ang:Forward()*50000 + bullet.Dir = ang:Forward() * 50000 bullet.Damage = -1 bullet.Force = 0 bullet.Entity = dmg_info:GetAttacker() + dmg_info:GetInflictor():FireBullets(bullet) end end - hit,kill,highest_dmg,successful_hit_ents,successful_kill_ents = ProcessDamagesList(ents_hits, dmg_info, tbl, pos, ang, ply) + hit,kill, highest_dmg, successful_hit_ents, successful_kill_ents = ProcessDamagesList(ents_hits, dmg_info, tbl, pos, ang, ply) highest_dmg = highest_dmg or 0 net.Start("pac_hit_results", true) net.WriteBool(hit) @@ -1963,7 +1976,6 @@ if SERVER then local owner = Try_CPPIGetOwner(targ_ent) - local unconsenting_owner = owner ~= ply and (grab_consents[owner] == false or (targ_ent:IsPlayer() and grab_consents[targ_ent] == false)) local calcview_unconsenting = owner ~= ply and (calcview_consents[owner] == false or (targ_ent:IsPlayer() and calcview_consents[targ_ent] == false)) @@ -2078,7 +2090,7 @@ if SERVER then if targ_ent.IsDrGEntity then targ_ent.loco:SetVelocity(Vector(0,0,0)) --counter gravity speed buildup end - if targ_ent:GetClass() == "prop_ragdoll" then targ_ent:GetPhysicsObject():SetPos(pos) end + if targ_ent:IsRagdoll() then targ_ent:GetPhysicsObject():SetPos(pos) end --@@note lock assignation! IMPORTANT if is_first_time then --successful, first @@ -2101,7 +2113,6 @@ if SERVER then net.WriteString(lockpart_UID) net.WriteString(breakup_condition) net.Send(auth_ent_owner) - else if is_first_time and did_grab then net.Start("pac_mark_grabbed_ent") diff --git a/lua/pac3/extra/shared/projectiles.lua b/lua/pac3/extra/shared/projectiles.lua index a4e46fa1b..d8d7075a6 100644 --- a/lua/pac3/extra/shared/projectiles.lua +++ b/lua/pac3/extra/shared/projectiles.lua @@ -62,16 +62,17 @@ do -- projectile entity end function ENT:SetData(ply, pos, ang, part) - self.projectile_owner = ply local radius = math.Clamp(part.Radius, 1, pac_sv_projectile_max_phys_radius:GetFloat()) + if part.Sphere then self:PhysicsInitSphere(radius, part.SurfaceProperties) else local valid_fallback = util.IsValidModel( part.FallbackSurfpropModel ) and not IsUselessModel(part.FallbackSurfpropModel) and pac_sv_projectile_allow_custom_collision_mesh:GetBool() --print("valid fallback? " .. part.FallbackSurfpropModel , valid_fallback) - self:PhysicsInitBox(Vector(1,1,1) * - radius, Vector(1,1,1) * radius, part.SurfaceProperties) + + self:PhysicsInitBox(Vector(-radius, -radius, -radius), Vector(radius, radius, radius), part.SurfaceProperties) if part.OverridePhysMesh and valid_fallback then self:SetModel(part.FallbackSurfpropModel) @@ -81,29 +82,29 @@ do -- projectile entity if valid_fallback and part.RescalePhysMesh then local physmesh = self:GetPhysicsObject():GetMeshConvexes() + --hack from prop resizer - for convexkey, convex in pairs( physmesh ) do - for poskey, postab in pairs( convex ) do - convex[ poskey ] = postab.pos * radius + for i = 1, #physmesh do + local convex = physmesh[i] + + for poskey = 1, #convex do + convex[poskey] = convex[poskey].pos * radius end end - self:PhysicsInitMultiConvex( physmesh, part.SurfaceProperties) - self:EnableCustomCollisions( true ) + self:PhysicsInitMultiConvex(physmesh, part.SurfaceProperties) + self:EnableCustomCollisions(true) elseif not valid_fallback then - self:PhysicsInitBox(Vector(1,1,1) * - radius, Vector(1,1,1) * radius, part.SurfaceProperties) + self:PhysicsInitBox(Vector(-radius, -radius, -radius), Vector(radius, radius, radius), part.SurfaceProperties) end - end - local phys = self:GetPhysicsObject() phys:SetMaterial(part.SurfaceProperties) - phys:EnableGravity(part.Gravity) phys:AddVelocity((ang:Forward() + (VectorRand():Angle():Forward() * part.Spread)) * part.Speed * 1000) - phys:AddAngleVelocity(Vector(part.RandomAngleVelocity.x * math.Rand(-1,1), part.RandomAngleVelocity.y * math.Rand(-1,1), part.RandomAngleVelocity.z * math.Rand(-1,1))) + phys:AddAngleVelocity(Vector(part.RandomAngleVelocity.x * math.Rand(-1, 1), part.RandomAngleVelocity.y * math.Rand(-1, 1), part.RandomAngleVelocity.z * math.Rand(-1,1))) phys:AddAngleVelocity(part.LocalAngleVelocity) @@ -121,7 +122,6 @@ do -- projectile entity phys:EnableCollisions(false) end - phys:SetMass(math.Clamp(part.Mass, 0.001, pac_sv_projectile_max_mass:GetFloat())) phys:SetDamping(0, 0) @@ -232,7 +232,9 @@ do -- projectile entity local closest_1 = {} local closest_2 = {} - for _, ent in ipairs(ents.FindInSphere(pos, radius)) do + local ents_tbl = ents.FindInSphere(pos, radius) + for i = 1, #ents_tbl do + local ent = ents_tbl[i] if ent ~= self and ent ~= ply and @@ -357,7 +359,9 @@ do -- projectile entity if self.part_data.Damage > 0 then if self.part_data.DamageType == "heal" then if damage_radius > 0 then - for _, ent in ipairs(ents.FindInSphere(data.HitPos, damage_radius)) do + local ents_tbl = ents.FindInSphere(data.HitPos, damage_radius) + for i = 1, #ents_tbl do + local ent = ents_tbl[i] if (ent ~= ply or self.part_data.CollideWithOwner) and ent:Health() < ent:GetMaxHealth() then ent:SetHealth(math.min(ent:Health() + self.part_data.Damage, ent:GetMaxHealth())) end @@ -367,7 +371,9 @@ do -- projectile entity end elseif self.part_data.DamageType == "armor" then if damage_radius > 0 then - for _, ent in ipairs(ents.FindInSphere(data.HitPos, damage_radius)) do + local ents_tbl = ents.FindInSphere(data.HitPos, damage_radius) + for i = 1, #ents_tbl do + local ent = ents_tbl[i] if ent.SetArmor and ent.Armor then local maxArmor = ent.GetMaxArmor and ent:GetMaxArmor() or 100 if (ent ~= ply or self.part_data.CollideWithOwner) and ent:Armor() < maxArmor then @@ -388,7 +394,9 @@ do -- projectile entity local ent = data.HitEntity if damage_radius > 0 then -- this should also use blast damage to find which entities it can damage - for _, ent in ipairs(ents.FindInSphere(data.HitPos, damage_radius)) do + local ents_tbl = ents.FindInSphere(data.HitPos, damage_radius) + for i = 1, #ents_tbl do + local ent = ents_tbl[i] if ent ~= self and ent:IsSolid() and hook.Run("CanProperty", ply, "ignite", ent) ~= false and (ent ~= ply or self.part_data.CollideWithOwner) then ent:Ignite(math.min(self.part_data.Damage, 5)) end @@ -407,7 +415,9 @@ do -- projectile entity info:SetDamageType(damage_types[self.part_data.DamageType] or damage_types.generic) if damage_radius > 0 then - for _, ent in ipairs(ents.FindInSphere(data.HitPos, damage_radius)) do + local ents_tbl = ents.FindInSphere(data.HitPos, damage_radius) + for i = 1, #ents_tbl do + local ent = ents_tbl[i] if ent ~= ply or self.part_data.CollideWithOwner then ent:TakeDamageInfo(info) end @@ -560,11 +570,14 @@ if SERVER then part.Bounce = net.ReadInt(8) / 100 local radius_limit = 2000 + local radius_limit_scaled_sqr = (radius_limit * ply:GetModelScale()) ^ 2 - if pos:Distance(ply:EyePos()) > radius_limit * ply:GetModelScale() then + if pos:DistToSqr(ply:EyePos()) > radius_limit_scaled_sqr then local ok = false - for _, ent in ipairs(ents.FindInSphere(pos, radius_limit)) do + local ents_tbl = ents.FindInSphere(pos, radius_limit) + for i = 1, #ents_tbl do + local ent = ents_tbl[i] if (ent.CPPIGetOwner and ent:CPPIGetOwner() == ply) or ent.projectile_owner == ply or ent:GetOwner() == ply then ok = true break @@ -624,7 +637,7 @@ if SERVER then end net.Start("pac_projectile_attach") - net.WriteEntity(ply) + net.WritePlayer(ply) net.WriteInt(ent:EntIndex(), 16) net.WriteString(part.UniqueID) net.WriteString(part.SurfaceProperties) diff --git a/lua/pac3/libraries/animations.lua b/lua/pac3/libraries/animations.lua index 23b1495e0..607d64ebf 100644 --- a/lua/pac3/libraries/animations.lua +++ b/lua/pac3/libraries/animations.lua @@ -1,3 +1,5 @@ +local ipairs = ipairs + local animations = pac.animations or {} animations.playing = {} @@ -310,7 +312,11 @@ local function GetFrameBoneInfo(ent, tGestureTable, iFrame, iBoneID) end local function ProcessAnimations(ent) - for name, tbl in pairs(ent.pac_animations) do + local entTbl = ent:GetTable() + + if not entTbl.pac_animations then return end + + for name, tbl in pairs(entTbl.pac_animations) do local frame = tbl.Frame local frame_data = tbl.FrameData[frame] local frame_delta = tbl.FrameDelta @@ -344,11 +350,11 @@ local function ProcessAnimations(ent) animations.ResetEntityBoneMatrix(ent) - if not ent.pac_animations then return end + if not entTbl.pac_animations then return end local tBuffer = {} - for _, tbl in pairs(ent.pac_animations) do + for _, tbl in pairs(entTbl.pac_animations) do local iCurFrame = tbl.Frame local tFrameData = tbl.FrameData[iCurFrame] local fFrameDelta = tbl.FrameDelta @@ -444,14 +450,17 @@ local function ProcessAnimations(ent) end for iBoneID, mMatrix in pairs(tBuffer) do - pac.SetEntityBoneMatrix(ent, iBoneID, mMatrix) + pac.SetEntityBoneMatrix(ent, iBoneID, mMatrix, entTbl) end end +function animations.ResetEntityBoneMatrix(ent, entTbl) + if not entTbl then + entTbl = ent:GetTable() + end -function animations.ResetEntityBoneMatrix(ent) - for i=0, ent:GetBoneCount() - 1 do - pac.ResetEntityBoneMatrix(ent, i) + for i = 0, ent:GetBoneCount() - 1 do + pac.ResetEntityBoneMatrix(ent, i, entTbl) end end @@ -654,10 +663,8 @@ function animations.StopAllEntityAnimations(ent, time) end hook.Add("Think", "pac_custom_animations", function() - for i,v in ipairs(animations.playing) do - if v.pac_animations then - ProcessAnimations(v) - end + for _, v in ipairs(animations.playing) do + ProcessAnimations(v) end end)