@quenty/ragdoll 5.2.0 → 5.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,25 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [5.3.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/ragdoll@5.2.1...@quenty/ragdoll@5.3.0) (2022-01-17)
7
+
8
+
9
+ ### Features
10
+
11
+ * Add RagdollService and suppress initialization race condition warnings in deferred mode ([480a089](https://github.com/Quenty/NevermoreEngine/commit/480a0892f47fd5acbcb4e846bfb2dd93e207e681))
12
+
13
+
14
+
15
+
16
+
17
+ ## [5.2.1](https://github.com/Quenty/NevermoreEngine/compare/@quenty/ragdoll@5.2.0...@quenty/ragdoll@5.2.1) (2022-01-16)
18
+
19
+ **Note:** Version bump only for package @quenty/ragdoll
20
+
21
+
22
+
23
+
24
+
6
25
  # [5.2.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/ragdoll@5.1.2...@quenty/ragdoll@5.2.0) (2022-01-07)
7
26
 
8
27
  **Note:** Version bump only for package @quenty/ragdoll
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quenty/ragdoll",
3
- "version": "5.2.0",
3
+ "version": "5.3.0",
4
4
  "description": "Quenty's Ragdoll system for Roblox - Floppy fun ragdolls",
5
5
  "keywords": [
6
6
  "Roblox",
@@ -25,23 +25,23 @@
25
25
  "Quenty"
26
26
  ],
27
27
  "dependencies": {
28
- "@quenty/baseobject": "^3.4.0",
29
- "@quenty/binder": "^4.7.0",
30
- "@quenty/camera": "^5.2.0",
31
- "@quenty/characterutils": "^3.5.0",
28
+ "@quenty/baseobject": "^3.5.0",
29
+ "@quenty/binder": "^4.8.0",
30
+ "@quenty/camera": "^5.3.0",
31
+ "@quenty/characterutils": "^3.6.0",
32
32
  "@quenty/hapticfeedbackutils": "^2.1.1",
33
33
  "@quenty/humanoidanimatorutils": "^2.0.1",
34
- "@quenty/loader": "^3.3.0",
35
- "@quenty/maid": "^2.0.2",
36
- "@quenty/playerhumanoidbinder": "^4.7.0",
37
- "@quenty/promise": "^3.5.0",
38
- "@quenty/remoting": "^3.5.0",
39
- "@quenty/rx": "^3.7.0",
34
+ "@quenty/loader": "^3.4.0",
35
+ "@quenty/maid": "^2.1.0",
36
+ "@quenty/playerhumanoidbinder": "^4.8.0",
37
+ "@quenty/promise": "^3.6.0",
38
+ "@quenty/remoting": "^3.6.0",
39
+ "@quenty/rx": "^3.8.0",
40
40
  "@quenty/table": "^2.1.1",
41
- "@quenty/valuebaseutils": "^3.7.0"
41
+ "@quenty/valuebaseutils": "^3.8.0"
42
42
  },
43
43
  "publishConfig": {
44
44
  "access": "public"
45
45
  },
46
- "gitHead": "5a3f3fb6c908fd3874f5ceacc70b404780275119"
46
+ "gitHead": "c094ba8f4e128cdff08919d89de226d3d65247ce"
47
47
  }
@@ -17,6 +17,7 @@ local BaseObject = require("BaseObject")
17
17
  local CameraStackService = require("CameraStackService")
18
18
  local CharacterUtils = require("CharacterUtils")
19
19
  local HapticFeedbackUtils = require("HapticFeedbackUtils")
20
+ local RagdollServiceClient = require("RagdollServiceClient")
20
21
 
21
22
  local RagdollClient = setmetatable({}, BaseObject)
22
23
  RagdollClient.ClassName = "RagdollClient"
@@ -31,7 +32,9 @@ RagdollClient.__index = RagdollClient
31
32
  function RagdollClient.new(humanoid, serviceBag)
32
33
  local self = setmetatable(BaseObject.new(humanoid), RagdollClient)
33
34
 
34
- self._cameraStackService = serviceBag:GetService(CameraStackService)
35
+ self._serviceBag = assert(serviceBag, "No serviceBag")
36
+ self._ragdollServiceClient = self._serviceBag:GetService(RagdollServiceClient)
37
+ self._cameraStackService = self._serviceBag:GetService(CameraStackService)
35
38
 
36
39
  local player = CharacterUtils.getPlayerFromCharacter(self._obj)
37
40
  if player == Players.LocalPlayer then
@@ -56,7 +59,9 @@ function RagdollClient:_setupCameraShake(impulseCamera)
56
59
  local velocity = head.Velocity
57
60
  local dVelocity = velocity - lastVelocity
58
61
  if dVelocity.magnitude >= 0 then
59
- impulseCamera:Impulse(cameraCFrame:vectorToObjectSpace(-0.1*cameraCFrame.lookVector:Cross(dVelocity)))
62
+ if self._ragdollServiceClient:GetScreenShakeEnabled() then
63
+ impulseCamera:Impulse(cameraCFrame:vectorToObjectSpace(-0.1*cameraCFrame.lookVector:Cross(dVelocity)))
64
+ end
60
65
  end
61
66
 
62
67
  lastVelocity = velocity
@@ -83,8 +83,9 @@ function RagdollableClient:_ragdollLocal()
83
83
 
84
84
  -- Really hard to infer whether or not we're the network owner, so we just try to do this for every single one.
85
85
 
86
- -- Hopefully these are already created. Intent here is to reset friction.
87
- RagdollRigging.createRagdollJoints(self._obj.Parent, self._obj.RigType)
86
+ -- Hopefully these are already created. Intent here is to reset friction. If not, the friction
87
+ -- should be good.
88
+ RagdollRigging.configureRagdollJoints(false, self._obj.Parent, self._obj.RigType)
88
89
 
89
90
  maid:GiveTask(RagdollUtils.setupState(self._obj))
90
91
  maid:GiveTask(RagdollUtils.setupMotors(self._obj))
@@ -0,0 +1,49 @@
1
+ --[=[
2
+ @client
3
+ @class RagdollServiceClient
4
+ ]=]
5
+
6
+ local require = require(script.Parent.loader).load(script)
7
+
8
+ local AttributeUtils = require("AttributeUtils")
9
+ local RagdollServiceConstants = require("RagdollServiceConstants")
10
+
11
+ local Players = game:GetService("Players")
12
+
13
+ local RagdollServiceClient = {}
14
+
15
+ --[=[
16
+ Initializes the ragdoll service on the client. Should be done via [ServiceBag].
17
+ @param serviceBag ServiceBag
18
+ ]=]
19
+ function RagdollServiceClient:Init(serviceBag)
20
+ assert(not self._serviceBag, "Already initialized")
21
+ self._serviceBag = assert(serviceBag, "No serviceBag")
22
+
23
+ self._serviceBag:GetService(require("RagdollBindersClient"))
24
+
25
+ self._screenShakeEnabled = true
26
+ end
27
+
28
+ --[=[
29
+ Sets screen shake enabled for the local player
30
+ @param value boolelan
31
+ ]=]
32
+ function RagdollServiceClient:SetScreenShakeEnabled(value)
33
+ assert(type(value) == "boolean", "Bad value")
34
+ Players.LocalPlayer:SetAttribute(RagdollServiceConstants.SCREEN_SHAKE_ENABLED_ATTRIBUTE)
35
+ end
36
+
37
+ --[=[
38
+ Returns wheher screenshake is enabled.
39
+ @return boolean
40
+ ]=]
41
+ function RagdollServiceClient:GetScreenShakeEnabled()
42
+ assert(self._serviceBag, "Not initialized")
43
+
44
+
45
+ return AttributeUtils.getAttribute(Players.LocalPlayer, RagdollServiceConstants.SCREEN_SHAKE_ENABLED_ATTRIBUTE, true)
46
+ end
47
+
48
+
49
+ return RagdollServiceClient
@@ -32,7 +32,7 @@ function Ragdollable.new(humanoid, serviceBag)
32
32
  self._ragdollBinder = serviceBag:GetService(RagdollBindersServer).Ragdoll
33
33
 
34
34
  self._obj.BreakJointsOnDeath = false
35
- RagdollRigging.createRagdollJoints(self._obj.Parent, humanoid.RigType)
35
+ RagdollRigging.configureRagdollJoints(true, self._obj.Parent, humanoid.RigType)
36
36
 
37
37
  local player = CharacterUtils.getPlayerFromCharacter(self._obj)
38
38
  if player then
@@ -97,7 +97,7 @@ function Ragdollable:_enableServer()
97
97
  local maid = Maid.new()
98
98
 
99
99
  -- This will reset friction too
100
- RagdollRigging.createRagdollJoints(self._obj.Parent, self._obj.RigType)
100
+ RagdollRigging.configureRagdollJoints(true, self._obj.Parent, self._obj.RigType)
101
101
 
102
102
  maid:GiveTask(RagdollUtils.setupState(self._obj))
103
103
  maid:GiveTask(RagdollUtils.setupMotors(self._obj))
@@ -0,0 +1,32 @@
1
+ --[=[
2
+ @server
3
+ @class RagdollService
4
+ ]=]
5
+
6
+ local require = require(script.Parent.loader).load(script)
7
+
8
+ local RagdollService = {}
9
+
10
+ --[=[
11
+ Initializes the ragdoll service on the server. Should be done via [ServiceBag].
12
+ @param serviceBag ServiceBag
13
+ ]=]
14
+ function RagdollService:Init(serviceBag)
15
+ assert(not self._serviceBag, "Already initialized")
16
+ self._serviceBag = assert(serviceBag, "No serviceBag")
17
+
18
+ self._binders = self._serviceBag:GetService(require("RagdollBindersServer"))
19
+ end
20
+
21
+ --[=[
22
+ Sets whether ragdolls should unragdoll automatically.
23
+ @param unragdollAutomatically boolean
24
+ ]=]
25
+ function RagdollService:SetUnragdollAutomatically(unragdollAutomatically)
26
+ assert(self._serviceBag, "Not initialized")
27
+ assert(type(unragdollAutomatically) == "boolean", "Bad unragdollAutomatically")
28
+
29
+ self._binders.UnragdollAutomatically:SetAutomaticTagging(unragdollAutomatically)
30
+ end
31
+
32
+ return RagdollService
@@ -243,7 +243,7 @@ local function indexParts(model)
243
243
  return parts
244
244
  end
245
245
 
246
- local function createRigJoints(parts, rig)
246
+ local function configureRigJoints(create, parts, rig)
247
247
  for _, params in ipairs(rig) do
248
248
  local part0Name, part1Name, attachmentName, limits = unpack(params)
249
249
  local part0 = parts[part0Name]
@@ -255,35 +255,34 @@ local function createRigJoints(parts, rig)
255
255
  -- Our rigs only have one joint per part (connecting each part to it's parent part), so
256
256
  -- we can re-use it if we have to re-rig that part again.
257
257
  local constraint = part1:FindFirstChild(BALL_SOCKET_NAME)
258
- if not constraint then
258
+ if constraint == nil and create then
259
259
  constraint = Instance.new("BallSocketConstraint")
260
260
  constraint.Name = BALL_SOCKET_NAME
261
+ end
261
262
 
262
- if RunService:IsClient() then
263
- warn(("[RagdollRigging] - Creating BallSocketConstraint %q"))
264
- end
263
+ if constraint then
264
+ constraint.Attachment0 = a0
265
+ constraint.Attachment1 = a1
266
+ constraint.LimitsEnabled = true
267
+ constraint.UpperAngle = limits.UpperAngle
268
+ constraint.TwistLimitsEnabled = true
269
+ constraint.TwistLowerAngle = limits.TwistLowerAngle
270
+ constraint.TwistUpperAngle = limits.TwistUpperAngle
271
+ -- Scale constant torque limit for joint friction relative to gravity and the mass of
272
+ -- the body part.
273
+ local gravityScale = workspace.Gravity / REFERENCE_GRAVITY
274
+ local referenceMass = limits.ReferenceMass
275
+ local massScale = referenceMass and (part1:GetMass() / referenceMass) or 1
276
+ local maxTorque = limits.FrictionTorque or DEFAULT_MAX_FRICTION_TORQUE
277
+ constraint.MaxFrictionTorque = maxTorque * massScale * gravityScale
278
+ constraint.Parent = part1
265
279
  end
266
- constraint.Attachment0 = a0
267
- constraint.Attachment1 = a1
268
- constraint.LimitsEnabled = true
269
- constraint.UpperAngle = limits.UpperAngle
270
- constraint.TwistLimitsEnabled = true
271
- constraint.TwistLowerAngle = limits.TwistLowerAngle
272
- constraint.TwistUpperAngle = limits.TwistUpperAngle
273
- -- Scale constant torque limit for joint friction relative to gravity and the mass of
274
- -- the body part.
275
- local gravityScale = workspace.Gravity / REFERENCE_GRAVITY
276
- local referenceMass = limits.ReferenceMass
277
- local massScale = referenceMass and (part1:GetMass() / referenceMass) or 1
278
- local maxTorque = limits.FrictionTorque or DEFAULT_MAX_FRICTION_TORQUE
279
- constraint.MaxFrictionTorque = maxTorque * massScale * gravityScale
280
- constraint.Parent = part1
281
280
  end
282
281
  end
283
282
  end
284
283
  end
285
284
 
286
- local function createAdditionalAttachments(parts, attachments)
285
+ local function configureAdditionalAttachments(create, parts, attachments)
287
286
  for _, attachmentParams in ipairs(attachments) do
288
287
  local partName, attachmentName, cframe, baseAttachmentName = unpack(attachmentParams)
289
288
  local part = parts[partName]
@@ -299,13 +298,11 @@ local function createAdditionalAttachments(parts, attachments)
299
298
  end
300
299
  -- The attachment names are unique within a part, so we can re-use
301
300
  if not attachment then
302
- attachment = Instance.new("Attachment")
303
- attachment.Name = attachmentName
304
- attachment.CFrame = cframe
305
- attachment.Parent = part
306
-
307
- if RunService:IsClient() then
308
- warn(("[RagdollRigging] - Creating attachment %q"):format(attachmentName))
301
+ if create then
302
+ attachment = Instance.new("Attachment")
303
+ attachment.Name = attachmentName
304
+ attachment.CFrame = cframe
305
+ attachment.Parent = part
309
306
  end
310
307
  else
311
308
  attachment.CFrame = cframe
@@ -315,7 +312,7 @@ local function createAdditionalAttachments(parts, attachments)
315
312
  end
316
313
  end
317
314
 
318
- local function createNoCollides(parts, noCollides)
315
+ local function configureNoCollides(create, parts, noCollides)
319
316
  -- This one's trickier to handle for an already rigged character since a part will have multiple
320
317
  -- NoCollide children with the same name. Having fewer unique names is better for
321
318
  -- replication so we suck it up and deal with the complexity here.
@@ -363,16 +360,16 @@ local function createNoCollides(parts, noCollides)
363
360
  local reusables = reusableNoCollides[part1]
364
361
  for part0, _ in pairs(neededPart0s) do
365
362
  local constraint = table.remove(reusables)
366
- if not constraint then
363
+ if constraint == nil and create then
367
364
  constraint = Instance.new("NoCollisionConstraint")
368
- if RunService:IsClient() then
369
- warn(("[RagdollRigging] - Creating NoCollisionConstraint %q"))
370
- end
371
365
  end
372
- constraint.Name = NO_COLLIDE_NAME
373
- constraint.Part0 = part0
374
- constraint.Part1 = part1
375
- constraint.Parent = part1
366
+
367
+ if constraint then
368
+ constraint.Name = NO_COLLIDE_NAME
369
+ constraint.Part0 = part0
370
+ constraint.Part1 = part1
371
+ constraint.Parent = part1
372
+ end
376
373
  end
377
374
  end
378
375
  end
@@ -396,19 +393,20 @@ end
396
393
 
397
394
  --[=[
398
395
  Creates joints on a model for a given rig type.
396
+ @param create boolean -- True if we create the joints, false if we just configure.
399
397
  @param model Model
400
398
  @param rigType HumanoidRigType
401
399
  ]=]
402
- function RagdollRigging.createRagdollJoints(model, rigType)
400
+ function RagdollRigging.configureRagdollJoints(create, model, rigType)
403
401
  local parts = indexParts(model)
404
402
  if rigType == Enum.HumanoidRigType.R6 then
405
- createAdditionalAttachments(parts, R6_ADDITIONAL_ATTACHMENTS)
406
- createRigJoints(parts, R6_RAGDOLL_RIG)
407
- createNoCollides(parts, R6_NO_COLLIDES)
403
+ configureAdditionalAttachments(create, parts, R6_ADDITIONAL_ATTACHMENTS)
404
+ configureRigJoints(create, parts, R6_RAGDOLL_RIG)
405
+ configureNoCollides(create, parts, R6_NO_COLLIDES)
408
406
  elseif rigType == Enum.HumanoidRigType.R15 then
409
- createAdditionalAttachments(parts, R15_ADDITIONAL_ATTACHMENTS)
410
- createRigJoints(parts, R15_RAGDOLL_RIG)
411
- createNoCollides(parts, R15_NO_COLLIDES)
407
+ configureAdditionalAttachments(create, parts, R15_ADDITIONAL_ATTACHMENTS)
408
+ configureRigJoints(create, parts, R15_RAGDOLL_RIG)
409
+ configureNoCollides(create, parts, R15_NO_COLLIDES)
412
410
  else
413
411
  error("unknown rig type", 2)
414
412
  end
@@ -0,0 +1,11 @@
1
+ --[=[
2
+ @class RagdollServiceConstants
3
+ ]=]
4
+
5
+ local require = require(script.Parent.loader).load(script)
6
+
7
+ local Table = require("Table")
8
+
9
+ return Table.readonly({
10
+ SCREEN_SHAKE_ENABLED_ATTRIBUTE = "RagdollScreenShakeEnabled"
11
+ })