diff --git a/lua/pac3/core/client/base_movable.lua b/lua/pac3/core/client/base_movable.lua index aa81d9112..a00e1f1c6 100644 --- a/lua/pac3/core/client/base_movable.lua +++ b/lua/pac3/core/client/base_movable.lua @@ -4,6 +4,14 @@ local Angle = Angle local NULL = NULL local Matrix = Matrix +local default = "0" +if game.SinglePlayer() then default = "1" end +local allow_NL = CreateConVar("pac_sv_nearest_life", default, {FCVAR_ARCHIVE, FCVAR_REPLICATED, FCVAR_NOTIFY}, "Enables nearest_life aimparts and bones, abusable for aimbot-type setups (which would already be possible with CS lua)") +local NL_allow_sampling_anywhere = CreateConVar("pac_sv_nearest_life_allow_sampling_from_parts", "1", {FCVAR_ARCHIVE, FCVAR_REPLICATED, FCVAR_NOTIFY}, "Restricts nearest_life aimparts and bones search to the player itself to prevent sampling from arbitrary positions\n0=sampling can only start from the player itself") +local allow_NL_bone = CreateConVar("pac_sv_nearest_life_allow_bones", default, {FCVAR_ARCHIVE, FCVAR_REPLICATED, FCVAR_NOTIFY}, "Restricts nearest_life bones, preventing placement on external entities' position") +local NL_allow_target_players = CreateConVar("pac_sv_nearest_life_allow_targeting_players", "1", {FCVAR_ARCHIVE, FCVAR_REPLICATED, FCVAR_NOTIFY}, "Restricts nearest_life aimparts and bones to forbid targeting players\n0=no target players") +local NL_max_distance = CreateConVar("pac_sv_nearest_life_max_distance", "5000", {FCVAR_ARCHIVE, FCVAR_REPLICATED, FCVAR_NOTIFY}, "Restricts the radius for nearest_life aimparts and bones") + local BUILDER, PART = pac.PartTemplate("base") PART.ClassName = "base_movable" @@ -209,6 +217,7 @@ function PART:CalcAngles(ang, wpos) end if pac.StringFind(self.AimPartName, "NEAREST_LIFE_YAW", true, true) then + if not allow_NL:GetBool() then self:SetWarning("nearest_life isn't allowed in this server\npac_sv_nearest_life") return ang or Angle(0,0,0) end local nearest_ent = get_nearest_ent(self) if not IsValid(nearest_ent) then return ang or Angle(0,0,0) end local ang = (nearest_ent:GetPos() - wpos):Angle() @@ -216,12 +225,14 @@ function PART:CalcAngles(ang, wpos) end if pac.StringFind(self.AimPartName, "NEAREST_LIFE_POS", true, true) then + if not allow_NL:GetBool() then self:SetWarning("nearest_life isn't allowed in this server\npac_sv_nearest_life") return ang or Angle(0,0,0) end local nearest_ent = get_nearest_ent(self) if not IsValid(nearest_ent) then return ang or Angle(0,0,0) end return self.Angles + (nearest_ent:GetPos() - wpos):Angle() end if pac.StringFind(self.AimPartName, "NEAREST_LIFE", true, true) then + if not allow_NL:GetBool() then self:SetWarning("nearest_life isn't allowed in this server\npac_sv_nearest_life") return ang or Angle(0,0,0) end local nearest_ent = get_nearest_ent(self) if not IsValid(nearest_ent) then return ang or Angle(0,0,0) end return self.Angles + ( nearest_ent:GetPos() + Vector(0,0,(nearest_ent:WorldSpaceCenter() - nearest_ent:GetPos()).z * 1.5) - wpos):Angle() diff --git a/lua/pac3/core/client/parts/bone.lua b/lua/pac3/core/client/parts/bone.lua index e3414b447..29526e574 100644 --- a/lua/pac3/core/client/parts/bone.lua +++ b/lua/pac3/core/client/parts/bone.lua @@ -290,12 +290,12 @@ function PART:GetBonePosition() if not self.bone_index then return ent:GetPos(), ent:GetAngles() end local m = ent:GetBoneMatrix(self.bone_index) - if not m then return ent:GetPos(), ent:GetAngles() end - local pos = m:GetTranslation() - local ang = m:GetAngles() - - return pos, ang + if m then + return m:GetTranslation(), m:GetAngles() + else + return ent:GetPos(), ent:GetAngles() + end end function PART:GetBoneMatrix() @@ -306,12 +306,15 @@ BUILDER:Register() pac.AddHook("OnEntityCreated", "hide_mesh_no_crash", function(ent) local ply = ent:GetRagdollOwner() + if ply:IsPlayer() and ply.pac_inf_scale then for i = 0, ply:GetBoneCount() - 1 do local scale = ply:GetManipulateBoneScale(i) + if scale == inf_scale then - scale = Vector(0,0,0) + scale = vector_origin end + ply:ManipulateBoneScale(i, scale) end end diff --git a/lua/pac3/core/client/parts/camera.lua b/lua/pac3/core/client/parts/camera.lua index 828c95690..51c7cf6f1 100644 --- a/lua/pac3/core/client/parts/camera.lua +++ b/lua/pac3/core/client/parts/camera.lua @@ -6,6 +6,8 @@ PART.ClassName = "camera" PART.Group = 'entity' PART.Icon = 'icon16/camera.png' +PART.ImplementsDoubleClickSpecified = true + BUILDER:StartStorableVars() BUILDER:GetSet("EyeAnglesLerp", 1) BUILDER:GetSet("DrawViewModel", false) @@ -75,6 +77,12 @@ function PART:CameraTakePriority(then_view) self.priority = true end) if then_view then + pace.old_ViewAngles = pace.ViewAngles + pace.old_ViewPos = pace.ViewPos + + --it should be relative if we use camera follow entity + pace.old_ViewPos_delta = pace.ViewPos - pace.GetViewEntity():GetPos() + timer.Simple(0.2, function() pace.CameraPartSwapView(true) end) end end @@ -351,6 +359,17 @@ function pac.HandleCameraPart(ply, pos, ang, fov, nearz, farz) --until we make reversible first person a thing, letting some non-drawable parts think, this is the best solution I could come up with end +function PART:OnDoubleClickSpecified() + if self ~= pac.active_camera then + self:CameraTakePriority(true) + else + pac.active_camera = nil + self.priority = false + self:RemoveSmallIcon() + pace.CameraPartSwapView() + end +end + function pac.HasRemainingCameraPart() pac.RebuildCameras() return table.Count(pac.LocalPlayer.pac_cameras) ~= 0 diff --git a/lua/pac3/core/client/parts/clip.lua b/lua/pac3/core/client/parts/clip.lua index 7b40e4f0a..7dda463a2 100644 --- a/lua/pac3/core/client/parts/clip.lua +++ b/lua/pac3/core/client/parts/clip.lua @@ -40,6 +40,16 @@ do function PART:PreOnDraw() bclip = render_EnableClipping(true) + -- this fixes clip planes lagging behind when parented to a bone on a model part + local owner = self:GetParentOwner() + if owner:IsValid() and not owner.pac_clip_bonessetup and owner.PACPart then + -- in case there are multiple clips on one model part, only the first one needs to call SetupBones + self.pac_clip_owner = owner + owner.pac_clip_bonessetup = true + + pac.SetupBones(owner) + end + local pos, ang = LocalToWorld(self.Position + self.PositionOffset, self:CalcAngles(self.Angles + self.AngleOffset), self:GetBonePosition()) local normal = ang:Forward() @@ -49,6 +59,11 @@ do local render_PopCustomClipPlane = render.PopCustomClipPlane function PART:PostOnDraw() + if self.pac_clip_owner then + self.pac_clip_owner.pac_clip_bonessetup = nil + self.pac_clip_owner = nil + end + render_PopCustomClipPlane() render_EnableClipping(bclip) diff --git a/lua/pac3/core/client/parts/event.lua b/lua/pac3/core/client/parts/event.lua index f7afde25a..d3faed68f 100644 --- a/lua/pac3/core/client/parts/event.lua +++ b/lua/pac3/core/client/parts/event.lua @@ -138,7 +138,7 @@ function PART:fix_event_operator() end elseif event_type == "string" then - if self.Operator ~= "find" and self.Operator ~= "find simple" and self.Operator ~= "equal" then + if self.Operator ~= "find" and self.Operator ~= "find simple" and self.Operator ~= "equal" and self.Operator ~= "not equal" then self.Operator = PART.Events[self.Event].preferred_operator --find simple self:SetInfo("The operator was automatically changed to work with this event type, which handles strings (text)") end @@ -384,7 +384,6 @@ function PART:SetMultipleTargetParts(str) end self.ExtraHermites_Property = "MultipleTargetParts" end - end local function get_default(typ) @@ -2884,8 +2883,42 @@ PART.OldEvents = { end return true end, - } + }, + is_no_draw = { + operator_type = "none", + tutorial = "activates when the current entity is flagged with nodraw", + callback = function(self, ent) + return ent:GetNoDraw() + end, + }, + + viewer_steamid = { + operator_type = "string", preferred_operator = "equal", + tutorial = "activates when the local player has the steamID specified", + arguments = {{find = "string"}, {include_owner = "boolean"}}, + callback = function(self, ent, find, include_owner) + if include_owner then + find = find .. ";" .. self:GetOwner():SteamID() + end + + return self:StringOperator(pac.LocalPlayer:SteamID(), find) + end, + nice = function(self, ent, find, include_owner) + local count = #string.Split(find, ";") + + local idSumm + if count == 0 or find == "" then + idSumm = (include_owner and "owner id" or "\"\"") + elseif count == 1 then + idSumm = string.format("\"%s\"%s", find, include_owner and " + owner id" or "") + else + idSumm = string.format("1 of %d entries%s", count, include_owner and " + owner id" or "") + end + + return string.format("steamid: [%s %s]", self.Operator, idSumm) + end + }, } @@ -4732,7 +4765,7 @@ net.Receive("pac_update_healthbars", function(len) if cached_part then tbl[i][cached_part.UniqueID] = value end - + end end --PrintTable(tbl) diff --git a/lua/pac3/core/client/parts/hitscan.lua b/lua/pac3/core/client/parts/hitscan.lua index 111dc91f0..22540e9ce 100644 --- a/lua/pac3/core/client/parts/hitscan.lua +++ b/lua/pac3/core/client/parts/hitscan.lua @@ -14,7 +14,6 @@ PART.ImplementsDoubleClickSpecified = true BUILDER:StartStorableVars() :GetSet("ServerBullets", true, {description = "serverside bullets can do damage and exert a physical impact force"}) :SetPropertyGroup("bullet properties") - :GetSet("BulletImpact", false) :GetSet("Damage", 1, {editor_onchange = function (self,val) return math.floor(math.Clamp(val,0,268435455)) end}) :GetSet("Force",1000, {editor_onchange = function (self,val) return math.floor(math.Clamp(val,0,65535)) end}) :GetSet("AffectSelf", false, {description = "whether to allow to damage yourself"}) diff --git a/lua/pac3/core/client/parts/model/entity.lua b/lua/pac3/core/client/parts/model/entity.lua index ef9294719..5697b44f4 100644 --- a/lua/pac3/core/client/parts/model/entity.lua +++ b/lua/pac3/core/client/parts/model/entity.lua @@ -69,6 +69,12 @@ function PART:GetNiceName() class_name = ent:GetClass() end + if str ~= "" then + return (str and str:gsub("%d", "") or "error") .. " " .. class_name .. " model" + elseif IsValid(self:GetOwner()) then + str = "[" .. string.GetFileFromFilename(string.StripExtension(self:GetOwner():GetModel())) .. "] " + return str .. class_name .. " model" + end return (str and str:gsub("%d", "") or "error") .. " " .. class_name .. " model" end diff --git a/lua/pac3/core/server/init.lua b/lua/pac3/core/server/init.lua index eac2c9fda..28f092079 100644 --- a/lua/pac3/core/server/init.lua +++ b/lua/pac3/core/server/init.lua @@ -10,6 +10,14 @@ CreateConVar("pac_allow_blood_color", "1", {FCVAR_NOTIFY}, "Allow to use custom CreateConVar("pac_allow_mdl", "1", CLIENT and {FCVAR_REPLICATED} or {FCVAR_ARCHIVE, FCVAR_REPLICATED}, "Allow to use custom MDLs") CreateConVar("pac_allow_mdl_entity", "1", CLIENT and {FCVAR_REPLICATED} or {FCVAR_ARCHIVE, FCVAR_REPLICATED}, "Allow to use custom MDLs as Entity") +local default = "0" +if game.SinglePlayer() then default = "1" end +CreateConVar("pac_sv_nearest_life", default, {FCVAR_ARCHIVE, FCVAR_REPLICATED, FCVAR_NOTIFY}, "Enables nearest_life aimparts and bones, abusable for aimbot-type setups (which would already be possible with CS lua)") +CreateConVar("pac_sv_nearest_life_allow_sampling_from_parts", "1", {FCVAR_ARCHIVE, FCVAR_REPLICATED, FCVAR_NOTIFY}, "Restricts nearest_life aimparts and bones search to the player itself to prevent sampling from arbitrary positions\n0=sampling can only start from the player itself") +CreateConVar("pac_sv_nearest_life_allow_bones", default, {FCVAR_ARCHIVE, FCVAR_REPLICATED, FCVAR_NOTIFY}, "Restricts nearest_life bones, preventing placement on external entities' position") +CreateConVar("pac_sv_nearest_life_allow_targeting_players", "1", {FCVAR_ARCHIVE, FCVAR_REPLICATED, FCVAR_NOTIFY}, "Restricts nearest_life aimparts and bones to forbid targeting players\n0=no target players") +CreateConVar("pac_sv_nearest_life_max_distance", "5000", {FCVAR_ARCHIVE, FCVAR_REPLICATED, FCVAR_NOTIFY}, "Restricts the radius for nearest_life aimparts and bones") + include("util.lua") include("pac3/core/shared/init.lua") diff --git a/lua/pac3/core/shared/init.lua b/lua/pac3/core/shared/init.lua index 7f509860b..382905062 100644 --- a/lua/pac3/core/shared/init.lua +++ b/lua/pac3/core/shared/init.lua @@ -13,6 +13,7 @@ CreateConVar("pac_sv_draw_distance", 0, CLIENT and FCVAR_REPLICATED or bit.bor(F do local tohash = { -- Crash + 'eye_muzzle.pcf', -- E.Y.E: Divine Cybermancy effect that crashes gmod. https://github.com/CapsAdmin/pac3/issues/1410 'weapon_unusual_isotope.pcf', -- Invalid diff --git a/lua/pac3/editor/client/animation_timeline.lua b/lua/pac3/editor/client/animation_timeline.lua index 687feabb7..8ed9c3bc6 100644 --- a/lua/pac3/editor/client/animation_timeline.lua +++ b/lua/pac3/editor/client/animation_timeline.lua @@ -334,6 +334,7 @@ function timeline.Open(part) timeline.Stop() end +local editing_part pac.AddHook("pace_OnPartSelected", "pac3_timeline", function(part) if part.ClassName == "timeline_dummy_bone" then return end if part.ClassName == "custom_animation" then @@ -341,7 +342,17 @@ pac.AddHook("pace_OnPartSelected", "pac3_timeline", function(part) timeline.Close() end timeline.Open(part) + editing_part = part elseif timeline.editing then + if editing_part then + local part2 = editing_part + if part2.AnimationType ~= "gesture" and not part2:IsHidden() then + timer.Simple(0, function() + part2:OnHide() + part2:OnShow() + end) + end + end timeline.Close() end end) diff --git a/lua/pac3/editor/client/asset_browser.lua b/lua/pac3/editor/client/asset_browser.lua index fd8910a1e..a15110993 100644 --- a/lua/pac3/editor/client/asset_browser.lua +++ b/lua/pac3/editor/client/asset_browser.lua @@ -942,7 +942,7 @@ function pace.AssetBrowser(callback, browse_types_str, part_key) play:SetImage("icon16/control_stop.png") - local snd = CreateSound(pac.LocalPlayer, sound) + local snd = CreateSound(LocalPlayer(), sound) snd:Play() pace.asset_browser_snd = snd diff --git a/lua/pac3/editor/client/init.lua b/lua/pac3/editor/client/init.lua index 7de793b69..01630097d 100644 --- a/lua/pac3/editor/client/init.lua +++ b/lua/pac3/editor/client/init.lua @@ -93,6 +93,7 @@ local showInEditor = CreateConVar("pac_show_in_editor", "1", {FCVAR_ARCHIVE}, "S pace.pac_show_uniqueid = CreateConVar("pac_show_uniqueid", "0", {FCVAR_ARCHIVE}, "Show uniqueids of parts inside editor") function pace.OpenEditor() + if not pac.LocalPlayer then pac.LocalPlayer = LocalPlayer() end pace.CloseEditor() if hook.Run("PrePACEditorOpen", pac.LocalPlayer) == false then return end diff --git a/lua/pac3/editor/client/panels/editor.lua b/lua/pac3/editor/client/panels/editor.lua index 9cae0b1df..4821e2478 100644 --- a/lua/pac3/editor/client/panels/editor.lua +++ b/lua/pac3/editor/client/panels/editor.lua @@ -208,6 +208,8 @@ function PANEL:Init() if remember_width:GetBool() then self.init_w = math.max(self:GetCookieNumber("width"), 200) + else + self.init_w = 280 end if remember_divider:GetBool() then pace.vertical_div_height = self:GetCookieNumber("y_divider") diff --git a/lua/pac3/editor/client/panels/extra_properties.lua b/lua/pac3/editor/client/panels/extra_properties.lua index de6c5e955..66fd611cf 100644 --- a/lua/pac3/editor/client/panels/extra_properties.lua +++ b/lua/pac3/editor/client/panels/extra_properties.lua @@ -1257,7 +1257,10 @@ do -- script proxy pnl.Paint = function(...) if not self:IsValid() then pnl:Remove() return end local x, y = self:LocalToScreen() - y = math.Clamp(y,0,ScrH() - self:GetTall()) + local _,prop_y = pace.properties:LocalToScreen(0,0) + local overflow = y < prop_y or y > ScrH() - self:GetTall() + y = math.Clamp(y,prop_y,ScrH() - self:GetTall()) + pnl:SetPos(x + 5 + inset_x, y) surface.SetFont(pnl:GetFont()) local w = surface.GetTextSize(pnl:GetText()) + 6 @@ -1271,6 +1274,34 @@ do -- script proxy old(...) end + local skincolor = self:GetSkin().Colours.Category.Line.Button + local col = Color(skincolor.r,skincolor.g,skincolor.b, 255) + + pac.AddHook('PostRenderVGUI', hookID .. "2", function(code) + if not IsValid(self) or not IsValid(pnl) then pac.RemoveHook('Think', hookID .. "2") return end + local _,prop_y = pace.properties:LocalToScreen(0,0) + local x, y = self:LocalToScreen() + local overflow = y < prop_y or y > ScrH() - self:GetTall() + if overflow then + local str = "" + if y > ScrH() then + str = "↓↓" + else + str = "↑↑" + end + local container = self:GetParent() + y = math.Clamp(y,prop_y,ScrH() - self:GetTall()) + surface.SetFont(pnl:GetFont()) + local w2 = surface.GetTextSize(str .. " " .. self.CurrentKey .. " " .. str) + + surface.SetDrawColor(col) + surface.DrawRect(x - w2, y, w2, pnl:GetTall()) + surface.SetTextColor(self:GetSkin().Colours.Category.Line.Text) + surface.SetTextPos(x - w2, y) + surface.DrawText(str .. " " .. self.CurrentKey .. " " .. str) + end + end) + pace.BusyWithProperties = pnl end diff --git a/lua/pac3/editor/client/panels/properties.lua b/lua/pac3/editor/client/panels/properties.lua index c57489c1a..9d604c403 100644 --- a/lua/pac3/editor/client/panels/properties.lua +++ b/lua/pac3/editor/client/panels/properties.lua @@ -1747,7 +1747,26 @@ do -- base editable mat = string.gsub(mat, "^materials/", "") local mat_no_ext = string.StripExtension(mat) - if string.find(mat, "%[%d+,%d+%]") then --find the bracket notation + if string.sub(mat, 1, 7) == "folder:" then + local path = string.sub(mat, 8, #mat) + local menu3, pnl2 = menu2:AddSubMenu(string.GetFileFromFilename(path), function() + end) + pnl2:SetImage("icon16/folder.png") pnl2:SetTooltip(mat) + + local files = get_files_recursively(nil, path, {"vmt"}) + + for i,file in ipairs(files) do + local mat_no_ext = string.StripExtension(string.sub(file,11,#file)) --"materials/" + menu3:AddOption(mat_no_ext, function() + self:SetValue(mat_no_ext) + if self.CurrentKey == "Material" then + pace.current_part:SetMaterial(mat_no_ext) + elseif self.CurrentKey == "SpritePath" then + pace.current_part:SetSpritePath(mat_no_ext) + end + end):SetMaterial(mat_no_ext) + end + elseif string.find(mat, "%[%d+,%d+%]") then --find the bracket notation mat_no_ext = string.gsub(mat_no_ext, "%[%d+,%d+%]", "") pace.AddSubmenuWithBracketExpansion(menu2, function(str) str = str or "" diff --git a/lua/pac3/editor/client/parts.lua b/lua/pac3/editor/client/parts.lua index 8d8dbd265..44564e8ae 100644 --- a/lua/pac3/editor/client/parts.lua +++ b/lua/pac3/editor/client/parts.lua @@ -369,7 +369,7 @@ function pace.OnPartSelected(part, is_selecting) pace.delaybulkselect = pace.delaybulkselect or 0 --a time updated in shortcuts.lua to prevent common pac operations from triggering bulk selection local bulk_key_pressed = input.IsKeyDown(input.GetKeyCode(GetConVar("pac_bulk_select_key"):GetString())) - if (not bulk_key_pressed) and bulk_select_deselect:GetBool() then + if (not bulk_key_pressed) and bulk_select_deselect:GetBool() and not IsValid(pace.bulk_apply_properties_active) then if pace.last_mouse_code == MOUSE_LEFT then pace.ClearBulkList(true) end end @@ -1489,6 +1489,7 @@ do -- menu Panel:SetSize( 500, 600 ) Panel:Center() Panel:SetTitle("BULK SELECT PROPERTY EDIT - WARNING! EXPERIMENTAL FEATURE!") + pace.bulk_apply_properties_active = Panel Panel:MakePopup() surface.CreateFont("Font", { @@ -1543,7 +1544,7 @@ do -- menu end end end - if shared and not prop.udata.editor_friendly and basepart["Get" .. prop["key"]] ~= nil then + if shared 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 if not table.HasValue(shared_udata_properties, "event_udata_"..prop["key"]) then @@ -1575,6 +1576,7 @@ do -- menu for i,v in ipairs(shared_properties) do if excluded_vars[v] then table.remove(shared_properties,i) end end + table.sort(shared_properties) --populate panels for standard GetSet part properties for i,v in pairs(shared_properties) do @@ -1955,7 +1957,9 @@ do -- menu parts_backup_properties_values[v] = {} for _,prop in pairs(v:GetProperties()) do if not excluded_properties[prop.key] then - parts_backup_properties_values[v][prop.key] = v["Get"..prop.key](v) + if v["Get"..prop.key] then + parts_backup_properties_values[v][prop.key] = v["Get"..prop.key](v) + end end end end @@ -3098,6 +3102,15 @@ function pace.AddQuickSetupsToPartMenu(menu, obj) end) end):SetIcon("icon16/text_align_center.png") + main:AddOption("clone model inside itself", function() + local copiable_properties = { + "Model", "Size", "Scale", "Alpha", "Material", "Materials", "NoLighting", "NoCulling", "Invert", "Skin", "IgnoreZ", "Translucent", "Brightness", "BlendMode" + } + local clone = obj:CreatePart("model2") + for i,v in ipairs(copiable_properties) do + clone:SetProperty(v, obj:GetProperty(v)) + end + end):SetIcon("icon16/shape_group.png") elseif obj.ClassName == "group" then main:AddOption("Assign to viewmodel", function() obj:SetParent() diff --git a/lua/pac3/editor/client/settings.lua b/lua/pac3/editor/client/settings.lua index e2629afe2..12df1c152 100644 --- a/lua/pac3/editor/client/settings.lua +++ b/lua/pac3/editor/client/settings.lua @@ -93,6 +93,11 @@ local convar_params_misc = { {"pac_to_contraption_allow", "Allow PAC to contraption tool", "", -1, 0, 200}, {"pac_max_contraption_entities", "Entity limit for PAC to contraption", "", 0, 0, 200}, {"pac_restrictions", "restrict PAC editor camera movement", "", -1, 0, 200}, + {"pac_sv_nearest_life", "Allow nearest life aimparts or bones", "", -1, 0, 200}, + {"pac_sv_nearest_life_allow_sampling_from_parts", "Allow NL sampling from anywhere", "", -1, 0, 200}, + {"pac_sv_nearest_life_allow_bones", "Allow NL usage on bones", "", -1, 0, 200}, + {"pac_sv_nearest_life_allow_targeting_players", "Allow NL targeting players", "", -1, 0, 200}, + {"pac_sv_nearest_life_max_distance", "Max NL distance", "", 0, 0, 20000}, } pace = pace diff --git a/lua/pac3/editor/client/spawnmenu.lua b/lua/pac3/editor/client/spawnmenu.lua index 838809eba..993a4788a 100644 --- a/lua/pac3/editor/client/spawnmenu.lua +++ b/lua/pac3/editor/client/spawnmenu.lua @@ -142,6 +142,17 @@ function pace.ClientSettingsMenu(self) self:NumSlider(L"Particles max per emitter: ", "pac_limit_particles_per_emitter", 0, 10000, 0) end +local default = "0" +if game.SinglePlayer() then default = "1" end +CreateConVar("pac_sv_nearest_life", default, {FCVAR_REPLICATED}, "Enables nearest_life aimparts and bones, abusable for aimbot-type setups (which would already be possible with CS lua)") +CreateConVar("pac_sv_nearest_life_allow_sampling_from_parts", "1", {FCVAR_REPLICATED}, "Restricts nearest_life aimparts and bones search to the player itself to prevent sampling from arbitrary positions\n0=sampling can only start from the player itself") +CreateConVar("pac_sv_nearest_life_allow_bones", default, {FCVAR_REPLICATED}, "Restricts nearest_life bones, preventing placement on external entities' position") +CreateConVar("pac_sv_nearest_life_allow_targeting_players", "1", {FCVAR_REPLICATED}, "Restricts nearest_life aimparts and bones to forbid targeting players\n0=no target players") +CreateConVar("pac_sv_nearest_life_max_distance", "5000", {FCVAR_REPLICATED}, "Restricts the radius for nearest_life aimparts and bones") +CreateConVar("pac_submit_spam", "1", {FCVAR_REPLICATED}) +CreateConVar("pac_allow_blood_color", "1", {FCVAR_REPLICATED}) +CreateConVar("pac_sv_prop_outfits", "1", {FCVAR_REPLICATED}) + function pace.AdminSettingsMenu(self) if not LocalPlayer():IsAdmin() then return end if not IsValid(self) then return end @@ -162,6 +173,11 @@ function pace.AdminSettingsMenu(self) self:CheckBox(L"Allow entity size modifier", "pac_modifier_size") self:CheckBox(L"Allow blood color modifier", "pac_allow_blood_color") self:NumSlider(L"Allow prop / other player outfits", "pac_sv_prop_outfits", 0, 2, 0) + self:CheckBox(L"Allow Nearest Life", "pac_sv_nearest_life") + self:CheckBox(L"Allow NL sampling anywhere", "pac_sv_nearest_life_allow_sampling_from_parts") + self:CheckBox(L"Allow NL on bones", "pac_sv_nearest_life_allow_bones") + self:CheckBox(L"Allow NL targeting players", "pac_sv_nearest_life_allow_targeting_players") + self:NumSlider(L"Max NL distance", "pac_sv_nearest_life_max_distance", 0, 20000, 0) self:Help(""):SetFont("DermaDefaultBold")--spacers self:Help(""):SetFont("DermaDefaultBold") diff --git a/lua/pac3/editor/client/view.lua b/lua/pac3/editor/client/view.lua index 7b103ccd4..39d587831 100644 --- a/lua/pac3/editor/client/view.lua +++ b/lua/pac3/editor/client/view.lua @@ -768,7 +768,19 @@ function pace.EnableView(b) pac.AddHook("HUDShouldDraw", "editor", pace.HUDShouldDraw) pac.AddHook("PostRenderVGUI", "editor", pace.PostRenderVGUI) pace.Focused = true - pace.ResetView() + if pace.old_ViewAngles and pace.old_ViewPos and pace.old_ViewPos_delta then + if follow_entity:GetBool() then + pace.ViewPos = pace.old_ViewPos_delta + pace.GetViewEntity():GetPos() + else + pace.ViewPos = pace.old_ViewPos + end + pace.ViewAngles = pace.old_ViewAngles + pace.old_ViewAngles = nil + pace.old_ViewPos = nil + pace.old_ViewPos_delta = nil + else + pace.ResetView() + end else lastEntityPos = nil pac.RemoveHook("GUIMousePressed", "editor") diff --git a/lua/pac3/editor/server/pac_settings_manager.lua b/lua/pac3/editor/server/pac_settings_manager.lua index 900cd63bd..290709b66 100644 --- a/lua/pac3/editor/server/pac_settings_manager.lua +++ b/lua/pac3/editor/server/pac_settings_manager.lua @@ -81,6 +81,12 @@ local pac_server_cvars = { {"pac_to_contraption_allow", "Allow PAC to contraption tool", "", -1, 0, 200}, {"pac_max_contraption_entities", "Entity limit for PAC to contraption", "", 0, 0, 200}, {"pac_restrictions", "restrict PAC editor camera movement", "", -1, 0, 200}, + + {"pac_sv_nearest_life", "Allow nearest life aimparts or bones", "", -1, 0, 200}, + {"pac_sv_nearest_life_allow_sampling_from_parts", "Allow NL sampling from anywhere", "", -1, 0, 200}, + {"pac_sv_nearest_life_allow_bones", "Allow NL usage on bones", "", -1, 0, 200}, + {"pac_sv_nearest_life_allow_targeting_players", "Allow NL targeting players", "", -1, 0, 200}, + {"pac_sv_nearest_life_max_distance", "Max NL distance", "", 0, 0, 20000}, } net.Receive("pac_send_sv_cvar", function(len,ply) @@ -89,10 +95,14 @@ net.Receive("pac_send_sv_cvar", function(len,ply) local val = net.ReadString() if not cmd then return end - if GetConVar(cmd) then - GetConVar(cmd):SetString(val) + for i,v in ipairs(pac_server_cvars) do + if v[1] == cmd then + if GetConVar(cmd) then + GetConVar(cmd):SetString(val) + end + return + end end - end) net.Receive("pac_request_sv_cvars", function (len, ply)