Skip to content

Commit

Permalink
Rework Entity.setCustomPropForces and add `Entity.setCustomPropShad…
Browse files Browse the repository at this point in the history
…owForce` (#1578)

* Rework Entity.setCustomPropForces

* Add Entity.setCustomPropShadowForce

* Update error message with correct value range

* Stop automatically waking the object

* Add SIM enum and better `mode` checks

* Docs about not being able to use the two functions together

* Support 'teleportdistance', update docs, fix error stack levels

* Move MotionController logic to ENT.EnableCustomPhysics and introduce ent.customPhysicsMode to avoid metatable lookup

* Whoops, mode 4 is also a thing
  • Loading branch information
adamnejm authored Dec 30, 2023
1 parent 89ba08b commit b8a9974
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 10 deletions.
33 changes: 33 additions & 0 deletions lua/entities/starfall_prop/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,39 @@ function ENT:Initialize()
self:AddEFlags( EFL_FORCE_CHECK_TRANSMIT )
end

function ENT:EnableCustomPhysics(mode)
if mode then
self.customPhysicsMode = mode
if not self.hasMotionController then
self:StartMotionController()
self.hasMotionController = true
end
else
self.customPhysicsMode = nil
self.customForceMode = nil
self.customForceLinear = nil
self.customForceAngular = nil
self.customShadowForce = nil
if self.hasMotionController then
self:StopMotionController()
self.hasMotionController = false
end
end
end

function ENT:PhysicsSimulate(physObj, dt)
local mode = self.customPhysicsMode
if mode == 1 then
return self.customForceAngular, self.customForceLinear, self.customForceMode
elseif mode == 2 then
self.customShadowForce.deltatime = dt
physObj:ComputeShadowControl(self.customShadowForce)
return SIM_NOTHING
else
return SIM_NOTHING
end
end

function ENT:UpdateTransmitState()
return TRANSMIT_ALWAYS
end
Expand Down
16 changes: 16 additions & 0 deletions lua/starfall/libs_sh/enum.lua
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,22 @@ env.MOVETYPE = {
CUSTOM = MOVETYPE_CUSTOM,
}

--- ENUMs used by Entity.setCustomPropForces (Entity.PhysicsSimulate internally)
-- @name builtins_library.SIM
-- @class table
-- @field NOTHING
-- @field LOCAL_ACCELERATION
-- @field LOCAL_FORCE
-- @field GLOBAL_ACCELERATION
-- @field GLOBAL_FORCE
env.SIM = {
NOTHING = SIM_NOTHING,
LOCAL_ACCELERATION = SIM_LOCAL_ACCELERATION,
LOCAL_FORCE = SIM_LOCAL_FORCE,
GLOBAL_ACCELERATION = SIM_GLOBAL_ACCELERATION,
GLOBAL_FORCE = SIM_GLOBAL_FORCE,
}

--- ENUMs of in_keys for use with player:keyDown
-- @name builtins_library.IN_KEY
-- @class table
Expand Down
72 changes: 62 additions & 10 deletions lua/starfall/libs_sv/entities.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
-- Global to all starfalls
local checkluatype = SF.CheckLuaType
local registerprivilege = SF.Permissions.registerPrivilege
local haspermission = SF.Permissions.hasAccess

local huge = math.huge
local abs = math.abs
Expand Down Expand Up @@ -138,27 +139,78 @@ function ents_methods:applyDamage(amt, attacker, inflictor, dmgtype, pos)
end

--- Sets a custom prop's physics simulation forces. Thrusters and balloons use this.
-- This takes precedence over Entity.setCustomPropShadowForce and cannot be used together
-- @param Vector ang Angular Force (Torque)
-- @param Vector lin Linear Force
-- @param number mode The physics mode to use. 0 = Off, 1 = Local acceleration, 2 = Local force, 3 = Global Acceleration, 4 = Global force
-- @param number mode The physics mode to use. 0 = Off (disables custom physics entirely), 1 = Local acceleration, 2 = Local force, 3 = Global Acceleration, 4 = Global force
function ents_methods:setCustomPropForces(ang, lin, mode)
local ent = getent(self)
if ent:GetClass()~="starfall_prop" then SF.Throw("The entity isn't a custom prop", 2) end

checkpermission(instance, ent, "entities.applyForce")

ang = vunwrap(ang)
checkvector(ang)
lin = vunwrap(lin)
checkvector(lin)
if mode == 0 then
ent:EnableCustomPhysics(false)
elseif mode == 1 or mode == 2 or mode == 3 or mode == 4 then
ang = vunwrap(ang)
checkvector(ang)
lin = vunwrap(lin)
checkvector(lin)

ent.customForceMode = mode
ent.customForceLinear = lin
ent.customForceAngular = ang
ent:EnableCustomPhysics(1)
else
SF.Throw("Invalid mode, see the SIM enum", 2)
end
end

--- Sets a custom prop's shadow forces, moving the entity to the desired position and angles
-- This gets overriden by Entity.setCustomPropForces and cannot be used together
-- See available parameters here: https://wiki.facepunch.com/gmod/PhysObj:ComputeShadowControl
-- @param data table|false Shadow physics data, excluding 'deltatime'. 'teleportdistance' higher than 0 requires 'entities.setPos'. Pass a falsy value to disable custom physics entirely
function ents_methods:setCustomPropShadowForce(data)
local ent = getent(self)
if ent:GetClass()~="starfall_prop" then SF.Throw("The entity isn't a custom prop", 2) end

checkluatype(mode, TYPE_NUMBER)
if mode ~= 0 and mode ~= 1 and mode ~= 2 and mode ~= 3 and mode ~= 4 then SF.Throw("Invalid mode", 2) end
checkpermission(instance, ent, "entities.applyForce")

if not data then
ent:EnableCustomPhysics(false)
else
local pos = vunwrap(data.pos)
checkvector(pos)
local ang = aunwrap(data.angle)
checkvector(ang)

checkluatype(data.teleportdistance, TYPE_NUMBER)
if data.teleportdistance > 0 and not haspermission(instance, ent, "entities.setPos") then
SF.Throw("Shadow force property 'teleportdistance' higher than 0 requires 'entities.setPos' permission access", 2)
end

function ent:PhysicsSimulate()
return ang, lin, mode
checkluatype(data.secondstoarrive, TYPE_NUMBER)
if data.secondstoarrive < 1e-3 then SF.Throw("Shadow force property 'secondstoarrive' cannot be lower than 0.001", 2) end
checkluatype(data.dampfactor, TYPE_NUMBER)
if data.dampfactor > 1 or data.dampfactor < 0 then SF.Throw("Shadow force property 'dampfactor' cannot be higher than 1 or lower than 0", 2) end
checkluatype(data.maxangular, TYPE_NUMBER)
checkluatype(data.maxangulardamp, TYPE_NUMBER)
checkluatype(data.maxspeed, TYPE_NUMBER)
checkluatype(data.maxspeeddamp, TYPE_NUMBER)

ent.customShadowForce = {
pos = pos,
angle = ang,
secondstoarrive = data.secondstoarrive,
dampfactor = data.dampfactor,
maxangular = data.maxangular,
maxangulardamp = data.maxangulardamp,
maxspeed = data.maxspeed,
maxspeeddamp = data.maxspeeddamp,
teleportdistance = data.teleportdistance,
}
ent:EnableCustomPhysics(2)
end
ent:StartMotionController()
end

--- Set the angular velocity of an object
Expand Down

0 comments on commit b8a9974

Please sign in to comment.