--[[ | This file was obtained through the combined efforts | of Madbluntz & Plymouth Antiquarian Society. | | Credits: lifestorm, Gregory Wayne Rossel JR., | Maloy, DrPepper10 @ RIP, Atle! | | Visit for more: https://plymouth.thetwilightzone.ru/ --]] include("autorun/pac_core_init.lua") pace = pace or {} pace.luadata = include("pac3/libraries/luadata.lua") include("language.lua") include("icons.lua") include("util.lua") include("wear.lua") include("select.lua") include("view.lua") include("parts.lua") include("saved_parts.lua") include("logic.lua") include("undo.lua") include("fonts.lua") include("settings.lua") include("shortcuts.lua") include("asset_browser.lua") include("menu_bar.lua") include("mctrl.lua") include("panels.lua") include("tools.lua") include("spawnmenu.lua") include("wiki.lua") include("examples.lua") include("about.lua") include("animation_timeline.lua") include("render_scores.lua") 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 pace.ActivePanels = pace.ActivePanels or {} pace.Editor = NULL local remember = CreateConVar("pac_editor_remember_position", "1", {FCVAR_ARCHIVE}, "Remember PAC3 editor position on screen") local positionMode = CreateConVar("pac_editor_position_mode", "0", {FCVAR_ARCHIVE}, "Editor position mode. 0 - Left, 1 - middle, 2 - Right. Has no effect if pac_editor_remember_position is true") local showCameras = CreateConVar("pac_show_cameras", "1", {FCVAR_ARCHIVE}, "Show the PAC cameras of players using the editor") local showInEditor = CreateConVar("pac_show_in_editor", "1", {FCVAR_ARCHIVE}, "Show the 'In PAC3 Editor' text above players using the editor") pace.pac_show_uniqueid = CreateConVar("pac_show_uniqueid", "0", {FCVAR_ARCHIVE}, "Show uniqueids of parts inside editor") function pace.OpenEditor() pace.CloseEditor() if hook.Run("PrePACEditorOpen", pac.LocalPlayer) == false then return end pac.Enable() pace.RefreshFiles() pace.SetLanguage() local editor = pace.CreatePanel("editor") editor:SetSize(240, ScrH()) editor:MakePopup() --editor:SetPos(0, 0) editor.Close = function() --editor:OnRemove() -- ??? This is called by the engine --editor.__OnClosed = true pace.CloseEditor() end pace.Editor = editor pace.Active = true if remember:GetBool() then local x = cookie.GetNumber("pac_editor_x", 0) if x < 0 or x + 240 > ScrW() then x = 0 end editor:SetPos(x, 0) cookie.Set("pac_editor_x", tostring(x)) else local mode = positionMode:GetInt() if mode == 1 then editor:SetPos(ScrW() / 2 - 120, 0) elseif mode == 2 then editor:SetPos(ScrW() - 240, 0) else editor:SetPos(0, 0) end end if ctp and ctp.Disable then ctp:Disable() end RunConsoleCommand("pac_enable", "1") RunConsoleCommand("pac_in_editor", "1") pace.SetInPAC3Editor(true) pace.DisableExternalHooks() vgui.GetWorldPanel():SetWorldClicker(false) pace.Call("OpenEditor") end function pace.CloseEditor() pace.RestoreExternalHooks() if pace.Editor:IsValid() then local x = pace.Editor:GetPos() cookie.Set("pac_editor_x", tostring(x)) --if not editor.__OnClosed then --pace.Editor:OnRemove() -- ??? This is called by the engine --end pace.Editor:Remove() pace.Active = false pace.Focused = false pace.Call("CloseEditor") if pace.timeline.IsActive() then pace.timeline.Close() end end RunConsoleCommand("pac_in_editor", "0") pace.SetInPAC3Editor(false) end function pace.HasFocus() return pace.Editor:IsValid() and pace.Editor:HasFocus() end pac.AddHook("pac_Disable", "pac_editor_disable", function() pace.CloseEditor() end) function pace.RefreshFiles() pace.CachedFiles = nil if pace.Editor:IsValid() then pace.Editor:MakeBar() end if pace.SpawnlistBrowser:IsValid() then pace.SpawnlistBrowser:PopulateFromClient() end end function pace.Panic() pace.CloseEditor() for key, pnl in pairs(pace.ActivePanels) do if pnl:IsValid() then pnl:Remove() table.remove(pace.ActivePanels, key) end end pace.SafeRemoveSpecialPanel() for i, ent in ipairs(ents.GetAll()) do if ent:IsValid() then ent.pac_onuse_only = nil ent.pac_onuse_only_check = nil hook.Remove('pace_OnUseOnlyUpdates', ent) end end end do -- forcing hooks pace.ExternalHooks = { "CalcView", "ShouldDrawLocalPlayer", } function pace.DisableExternalHooks() if DLib or ULib then return end -- hook with priority for _, event in pairs(pace.ExternalHooks) do local hooks = hook.GetTable()[event] if hooks then pace.OldHooks = pace.OldHooks or {} pace.OldHooks[event] = pace.OldHooks[event] or {} pace.OldHooks[event] = table.Copy(hooks) for name in pairs(hooks) do if isstring(name) and name:sub(1, 4) ~= "pace_" then hook.Remove(event, name) end end end end end function pace.RestoreExternalHooks() if DLib or ULib then return end -- hook with priority if pace.OldHooks then for event, hooks in pairs(pace.OldHooks) do for name, func in pairs(hooks) do if isstring(name) and name:sub(1, 4) ~= "pace_" then hook.Add(event, name, func) end end end end pace.OldHooks = nil end end function pace.IsActive() return pace.Active == true end concommand.Add("pac_editor_panic", function() pace.Panic() timer.Simple(0.1, function() pace.OpenEditor() end) end) concommand.Add("pac_editor", function(_, _, args) if args[1] == "toggle" then if pace.IsActive() then pace.CloseEditor() else pace.OpenEditor() end else pace.OpenEditor() end end) concommand.Add("pac_reset_eye_angles", function() pace.ResetEyeAngles() end) concommand.Add("pac_toggle_tpose", function() pace.SetTPose(not pace.GetTPose()) end) function pace.Call(str, ...) if pace["On" .. str] then if hook.Run("pace_On" .. str, ...) ~= false then return pace["On" .. str](...) end else ErrorNoHalt("missing function pace.On" .. str .. "!\n") end end do function pace.SetInPAC3Editor(b) net.Start("pac_in_editor") net.WriteBit(b) net.SendToServer() end local up = Vector(0,0,10000) hook.Add("HUDPaint", "pac_in_editor", function() for _, ply in ipairs(player.GetAll()) do if ply ~= pac.LocalPlayer and ply:GetNW2Bool("pac_in_editor") then if showCameras:GetInt() == 1 then if ply.pac_editor_cam_pos then if not IsValid(ply.pac_editor_camera) then ply.pac_editor_camera = ClientsideModel("models/tools/camera/camera.mdl") ply.pac_editor_camera:SetModelScale(0.25,0) local ent = ply.pac_editor_camera ply:CallOnRemove("pac_editor_camera", function() SafeRemoveEntity(ent) end) end local ent = ply.pac_editor_camera local dt = math.Clamp(FrameTime() * 5, 0.0001, 0.5) ent:SetPos(LerpVector(dt, ent:GetPos(), ply.pac_editor_cam_pos)) ent:SetAngles(LerpAngle(dt, ent:GetAngles(), ply.pac_editor_cam_ang)) local pos_3d = ent:GetPos() local dist = pos_3d:Distance(EyePos()) if dist > 10 then local pos_2d = pos_3d:ToScreen() if pos_2d.visible then local alpha = math.Clamp(pos_3d:Distance(EyePos()) * -1 + 500, 0, 500)/500 if alpha > 0 then draw.DrawText(ply:Nick() .. "'s PAC3 camera", "ChatFont", pos_2d.x, pos_2d.y, Color(255,255,255,alpha*255), 1) if not ply.pac_editor_part_pos:IsZero() then surface.SetDrawColor(255, 255, 255, alpha*100) local endpos = ply.pac_editor_part_pos:ToScreen() if endpos.visible then surface.DrawLine(pos_2d.x, pos_2d.y, endpos.x, endpos.y) end end end end end end else if ply.pac_editor_camera then SafeRemoveEntity(ply.pac_editor_camera) ply.pac_editor_camera = nil end end if showInEditor:GetInt() == 1 then local pos_3d = ply:NearestPoint(ply:EyePos() + up) + 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() draw.DrawText("In PAC3 Editor", "ChatFont", pos_2d.x, pos_2d.y, Color(255,255,255,alpha*255), 1) end end else if ply.pac_editor_camera then SafeRemoveEntity(ply.pac_editor_camera) ply.pac_editor_camera = nil end end end end) do local lastViewPos, lastViewAngle, lastTargetPos timer.Create("pac_in_editor", 0.25, 0, function() if not pace.Active then return end if not pace.current_part:IsValid() then return end local pos, ang = pace.GetViewPos(), pace.GetViewAngles() local target_pos = pace.mctrl.GetWorldPosition() if not target_pos then return end if lastViewPos == pos and lastViewAngle == ang and lastTargetPos == target_pos then return end lastViewPos, lastViewAngle, lastTargetPos = pos, ang, target_pos net.Start("pac_in_editor_posang", true) net.WriteVector(pos) net.WriteAngle(ang) net.WriteVector(target_pos) net.SendToServer() end) end net.Receive("pac_in_editor_posang", function() local ply = net.ReadEntity() if not IsValid( ply ) then return end local pos = net.ReadVector() local ang = net.ReadAngle() local part_pos = net.ReadVector() ply.pac_editor_cam_pos = pos ply.pac_editor_cam_ang = ang ply.pac_editor_part_pos = part_pos end) end pace.RegisterPanels()