Files
wnsrc/lua/pac3/core/client/parts/physics.lua
lifestorm 94063e4369 Upload
2024-08-04 22:55:00 +03:00

238 lines
4.8 KiB
Lua

--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
local BUILDER, PART = pac.PartTemplate("base")
PART.ThinkTime = 0
PART.ClassName = "physics"
PART.Group = 'model'
PART.Icon = 'icon16/shape_handles.png'
BUILDER:StartStorableVars()
BUILDER:GetSet("Box", true)
BUILDER:GetSet("Radius", 1)
BUILDER:GetSet("SelfCollision", false)
BUILDER:GetSet("Gravity", true)
BUILDER:GetSet("Collisions", true)
BUILDER:GetSet("Mass", 100)
BUILDER:GetSet("Follow", false)
BUILDER:GetSet("SecondsToArrive", 0.1)
BUILDER:GetSet("MaxSpeed", 10000)
BUILDER:GetSet("MaxAngular", 3600)
BUILDER:GetSet("MaxSpeedDamp", 1000)
BUILDER:GetSet("MaxAngularDamp", 1000)
BUILDER:GetSet("DampFactor", 1)
BUILDER:GetSet("ConstrainSphere", 0)
BUILDER:EndStorableVars()
local function IsInvalidParent(self)
return self.Parent.ClassName ~= "model" and self.Parent.ClassName ~= "model2"
end
PART.phys = NULL
function PART:SetBox(b)
self.Box = b
self:SetRadius(self.Radius)
end
function PART:SetCollisions(b)
self.Collisions = b
if self.phys:IsValid() then
self.phys:EnableCollisions(b)
end
end
function PART:SetMass(n)
self.Mass = n
if self.phys:IsValid() then
self.phys:SetMass(math.Clamp(n, 0.001, 50000))
end
end
function PART:SetRadius(n)
self.Radius = n
if IsInvalidParent(self) then return end
local ent = self.Parent:GetOwner()
if n <= 0 then n = ent:BoundingRadius()/2 end
ent:SetNoDraw(false)
if self.Box then
ent:PhysicsInitBox(Vector(1,1,1) * -n, Vector(1,1,1) * n)
else
ent:PhysicsInitSphere(n)
end
self.phys = ent:GetPhysicsObject()
if self.Gravity ~= nil then
self.phys:EnableGravity(self.Gravity)
end
end
function PART:SetGravity(b)
self.Gravity = b
if self.phys:IsValid() then
self.phys:EnableGravity(b)
end
end
function PART:SetSelfCollision(b)
self.SelfCollision = b
if IsInvalidParent(self) then return end
local ent = self.Parent:GetOwner()
if b then
ent:SetCollisionGroup(COLLISION_GROUP_NONE)
else
ent:SetCollisionGroup(COLLISION_GROUP_DEBRIS)
end
end
local params = {}
function PART:OnThink()
if self.Parent.GetWorldPosition then
if self.disabled then
self:Enable()
end
else
if not self.disabled then
self:Disable()
end
end
local phys = self.phys
if phys:IsValid() then
phys:Wake()
if self.Follow then
params.pos = self.Parent:GetWorldPosition()
params.angle = self.Parent:GetWorldAngles()
params.secondstoarrive = math.max(self.SecondsToArrive, 0.0001)
params.maxangular = self.MaxAngular
params.maxangulardamp = self.MaxAngularDamp
params.maxspeed = self.MaxSpeed
params.maxspeeddamp = self.MaxSpeedDamp
params.dampfactor = self.DampFactor
params.teleportdistance = 0
phys:ComputeShadowControl(params)
-- this is nicer i think
if self.ConstrainSphere ~= 0 and phys:GetPos():Distance(self.Parent:GetWorldPosition()) > self.ConstrainSphere then
phys:SetPos(self.Parent:GetWorldPosition() + (self.Parent:GetWorldPosition() - phys:GetPos()):GetNormalized() * -self.ConstrainSphere)
end
else
if self.ConstrainSphere ~= 0 then
local offset = self.Parent:GetWorldPosition() - phys:GetPos()
if offset:Length() > self.ConstrainSphere then
phys:SetPos(self.Parent:GetWorldPosition() - offset:GetNormalized() * self.ConstrainSphere)
phys:SetVelocity(Vector())
end
end
end
end
end
function PART:OnParent(part)
timer.Simple(0, function() self:Enable() end)
end
function PART:OnUnParent(part)
timer.Simple(0, function() self:Disable() end)
end
function PART:OnShow()
timer.Simple(0, function() self:Enable() end)
end
function PART:OnHide()
timer.Simple(0, function() self:Disable() end)
end
function PART:Enable()
if IsInvalidParent(self) then return end
local part = self:GetParent()
part.skip_orient = true
local ent = part:GetOwner()
ent:SetNoDraw(false)
self:SetRadius(self.Radius)
for key, val in pairs(self.StorableVars) do
if pac.registered_parts.base.StorableVars[key] then goto CONTINUE end
self["Set" .. key](self, self[key])
::CONTINUE::
end
self.disabled = false
end
function PART:Disable()
if IsInvalidParent(self) then return end
local part = self:GetParent()
local ent = part:GetOwner()
if ent:IsValid() then
-- SetNoDraw does not care of validity but PhysicsInit does?
ent:SetNoDraw(true)
ent:PhysicsInit(SOLID_NONE)
end
part.skip_orient = false
self.disabled = true
end
function PART:SetPositionDamping(num)
self.PositionDamping = num
if self.phys:IsValid() then
self.phys:SetDamping(self.PositionDamping, self.AngleDamping)
end
end
function PART:SetAngleDamping(num)
self.AngleDamping = num
if self.phys:IsValid() then
self.phys:SetDamping(self.PositionDamping, self.AngleDamping)
end
end
BUILDER:Register()