diff --git a/lua/entities/gmod_wire_buoyancy.lua b/lua/entities/gmod_wire_buoyancy.lua new file mode 100644 index 0000000000..99369fa00f --- /dev/null +++ b/lua/entities/gmod_wire_buoyancy.lua @@ -0,0 +1,153 @@ +AddCSLuaFile() + +DEFINE_BASECLASS("base_wire_entity") +ENT.PrintName = "Wire Buoyancy" +ENT.RenderGroup = RENDERGROUP_BOTH +ENT.WireDebugName = "Buoyancy" + +if CLIENT then return end + +function ENT:Initialize() + self:PhysicsInit(SOLID_VPHYSICS) + self.Marks = {} + + WireLib.CreateInputs(self, { "Percent" }) +end + +function ENT:UpdateOverlay() + self:SetOverlayText(string.format("Buoyancy ratio: %.2f\nNumber of entities linked: %i", self.Percent, #self.Marks)) +end + +function ENT:UpdateOutputs() + self:UpdateOverlay() + WireLib.SendMarks(self) +end + +local function SetBuoyancy(ent, controller) + local phys = ent:GetPhysicsObject() + + if phys:IsValid() then + phys:SetBuoyancyRatio(controller.Percent) + phys:Wake() + end +end + +function ENT:Setup(percent) + self.Percent = math.Clamp(percent, -10, 10) + + for _, ent in ipairs(self.Marks) do + SetBuoyancy(ent, self) + end + + self:UpdateOverlay() +end + +function ENT:TriggerInput(name, value) + if name == "Percent" then + self.Percent = math.Clamp(value, -10, 10) + + for _, ent in ipairs(self.Marks) do + SetBuoyancy(ent, self) + end + + self:UpdateOverlay() + end +end + +-- Buoyancy is reset by the physgun and gravgun +local function RestoreBuoyancy(ply, ent) + if ent.WireBuoyancyController then + timer.Simple(0 , function() + if not ent:IsValid() or not ent.WireBuoyancyController then return end + SetBuoyancy(ent, ent.WireBuoyancyController) + end) + end +end + +hook.Add("PhysgunDrop", "WireBuoyancy", RestoreBuoyancy) +hook.Add("GravGunOnDropped", "WireBuoyancy", RestoreBuoyancy) + +function ENT:CheckEnt(checkent) + for index, ent in ipairs(self.Marks) do + if checkent == ent then + return true, index + end + end + + return false, 0 +end + +function ENT:LinkEnt(ent) + if self:CheckEnt(ent) then return false end + + table.insert(self.Marks, ent) + SetBuoyancy(ent, self) + + ent:CallOnRemove("Buoyancy.Unlink" .. self:EntIndex(), function(ent) + self:UnlinkEnt(ent) + end) + + ent.WireBuoyancyController = self + self:UpdateOutputs() + + return true +end + +function ENT:UnlinkEnt(ent) + local bool, index = self:CheckEnt(ent) + + if bool then + table.remove(self.Marks, index) + ent:RemoveCallOnRemove("Buoyancy.Unlink" .. self:EntIndex()) + ent.WireBuoyancyController = nil + self:UpdateOutputs() + end + + return bool +end + +function ENT:ClearEntities() + for index, ent in ipairs(self.Marks) do + ent:RemoveCallOnRemove("Buoyancy.Unlink" .. self:EntIndex()) + ent.WireBuoyancyController = nil + end + + self.Marks = {} + self:UpdateOutputs() +end + +function ENT:OnRemove() + self:ClearEntities() +end + +function ENT:BuildDupeInfo() + local info = BaseClass.BuildDupeInfo(self) + + if #self.Marks > 0 then + local tab = {} + + for index, ent in ipairs(self.Marks) do + tab[index] = ent:EntIndex() + end + + info.marks = tab + end + + return info +end + +function ENT:ApplyDupeInfo(ply, ent, info, GetEntByID) + BaseClass.ApplyDupeInfo(self, ply, ent, info, GetEntByID) + + if info.marks then + for index, entid in ipairs(info.marks) do + local ent = GetEntByID(entid) + + if ent:IsValid() then + self:LinkEnt(ent) + end + end + end +end + +duplicator.RegisterEntityClass("gmod_wire_buoyancy", WireLib.MakeWireEnt, "Data", "Percent") diff --git a/lua/wire/server/sents_registry.lua b/lua/wire/server/sents_registry.lua index 3306eab2d5..9fefaec6d7 100644 --- a/lua/wire/server/sents_registry.lua +++ b/lua/wire/server/sents_registry.lua @@ -44,7 +44,7 @@ -- TIP: To return a strict-only error in _preFactory, or _postFactory, just return a string, which contains the error message. -- (If you return a string to non-strict E2, obv it will also stop spawning the entity) --- Supported types (to which can WireLib.castE2ValueToLuaValue cast E2 values): +-- Supported types (to which can WireLib.castE2ValueToLuaValue cast E2 values): -- TYPE_STRING, TYPE_NUMBER, TYPE_BOOL, TYPE_ENTITY, TYPE_VECTOR, -- TYPE_COLOR, TYPE_TABLE, TYPE_USERDATA, TYPE_ANGLE, TYPE_DAMAGEINFO, -- TYPE_MATERIAL, TYPE_EFFECTDATA, TYPE_MATRIX @@ -1317,3 +1317,8 @@ register("gmod_wire_materializer", { ["Material"] = {TYPE_STRING, "debug/env_cubemap_model", "Default material"}, ["Range"] = {TYPE_NUMBER, 2048, "Length of the materializer beam"}, }) + +register("gmod_wire_buoyancy", { + ["Model"] = {TYPE_STRING, "models/jaanus/wiretool/wiretool_siren.mdl", "Path to model"}, + ["Percent"] = {TYPE_NUMBER, 1, "Buoyancy coefficient"}, +}) diff --git a/lua/wire/stools/buoyancy.lua b/lua/wire/stools/buoyancy.lua new file mode 100644 index 0000000000..786c4ca556 --- /dev/null +++ b/lua/wire/stools/buoyancy.lua @@ -0,0 +1,29 @@ +WireToolSetup.setCategory("Physics/Force") +WireToolSetup.open("buoyancy", "Buoyancy", "gmod_wire_buoyancy", nil, "Buoyancys") + +if CLIENT then + language.Add("tool.wire_buoyancy.name", "Buoyancy Tool (Wire)") + language.Add("tool.wire_buoyancy.desc", "Spawns a Buoyancy Controller for use with the wire system.") +end + +WireToolSetup.BaseLang() +WireToolSetup.SetupMax(10) + +if SERVER then + function TOOL:GetConVars() + return self:GetClientNumber("percent"), self:GetClientInfo("model") + end +end + +TOOL.ClientConVar = { + percent = 1, + model = "models/jaanus/wiretool/wiretool_siren.mdl" +} + +WireToolSetup.SetupLinking() + +function TOOL.BuildCPanel(panel) + WireToolHelpers.MakePresetControl(panel, "wire_buoyancy") + WireDermaExts.ModelSelect(panel, "wire_buoyancy_model", list.Get("Wire_Laser_Tools_Models"), 1, true) + panel:NumSlider("Percent", "wire_buoyancy_percent", -10, 10) +end