@quenty/ik 6.2.1-canary.256.edbbcfc.0 → 7.0.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,7 +3,18 @@
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
- ## [6.2.1-canary.256.edbbcfc.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/ik@6.2.0...@quenty/ik@6.2.1-canary.256.edbbcfc.0) (2022-03-27)
6
+ # [7.0.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/ik@6.3.0...@quenty/ik@7.0.0) (2022-05-21)
7
+
8
+
9
+ ### Features
10
+
11
+ * Add new IK (without actual math for now), and improve replication rates among other things ([766f358](https://github.com/Quenty/NevermoreEngine/commit/766f35801576f56cc3b1372ee88e8bb9525058ff))
12
+
13
+
14
+
15
+
16
+
17
+ # [6.3.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/ik@6.2.0...@quenty/ik@6.3.0) (2022-03-27)
7
18
 
8
19
  **Note:** Version bump only for package @quenty/ik
9
20
 
package/LICENSE.md CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2014-2021 Quenty
3
+ Copyright (c) 2014-2022 Quenty
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quenty/ik",
3
- "version": "6.2.1-canary.256.edbbcfc.0",
3
+ "version": "7.0.0",
4
4
  "description": "Inverse Kinematics for characters on Roblox",
5
5
  "keywords": [
6
6
  "Roblox",
@@ -26,27 +26,28 @@
26
26
  "Quenty"
27
27
  ],
28
28
  "dependencies": {
29
- "@quenty/acceltween": "2.1.1-canary.256.edbbcfc.0",
30
- "@quenty/baseobject": "4.1.1-canary.256.edbbcfc.0",
31
- "@quenty/binder": "5.1.1-canary.256.edbbcfc.0",
32
- "@quenty/camera": "6.2.1-canary.256.edbbcfc.0",
33
- "@quenty/characterutils": "4.1.1-canary.256.edbbcfc.0",
34
- "@quenty/humanoidtracker": "4.1.1-canary.256.edbbcfc.0",
35
- "@quenty/loader": "4.0.1-canary.256.edbbcfc.0",
36
- "@quenty/maid": "2.2.1-canary.256.edbbcfc.0",
37
- "@quenty/math": "2.1.1-canary.256.edbbcfc.0",
38
- "@quenty/promise": "4.1.1-canary.256.edbbcfc.0",
39
- "@quenty/ragdoll": "6.2.1-canary.256.edbbcfc.0",
40
- "@quenty/remoting": "4.1.1-canary.256.edbbcfc.0",
41
- "@quenty/servicebag": "4.1.1-canary.256.edbbcfc.0",
42
- "@quenty/signal": "2.1.1-canary.256.edbbcfc.0",
43
- "@quenty/table": "2.1.2-canary.256.edbbcfc.0"
29
+ "@quenty/acceltween": "^2.2.0",
30
+ "@quenty/baseobject": "^5.0.0",
31
+ "@quenty/binder": "^6.0.0",
32
+ "@quenty/camera": "^7.0.0",
33
+ "@quenty/characterutils": "^5.0.0",
34
+ "@quenty/humanoidtracker": "^5.0.0",
35
+ "@quenty/loader": "^5.0.0",
36
+ "@quenty/maid": "^2.3.0",
37
+ "@quenty/math": "^2.2.0",
38
+ "@quenty/promise": "^5.0.0",
39
+ "@quenty/qframe": "^5.0.0",
40
+ "@quenty/ragdoll": "^7.0.0",
41
+ "@quenty/remoting": "^5.0.0",
42
+ "@quenty/servicebag": "^5.0.0",
43
+ "@quenty/signal": "^2.2.0",
44
+ "@quenty/table": "^3.0.0"
44
45
  },
45
46
  "devDependencies": {
46
- "@quenty/rigbuilderutils": "4.2.1-canary.256.edbbcfc.0"
47
+ "@quenty/rigbuilderutils": "^5.0.0"
47
48
  },
48
49
  "publishConfig": {
49
50
  "access": "public"
50
51
  },
51
- "gitHead": "edbbcfc38516772a791d50dc43cd6b304ffc4aff"
52
+ "gitHead": "9f7eaea7543c33c89d2e32c38491b13f9271f4f7"
52
53
  }
@@ -13,7 +13,7 @@ local CameraStackService = require("CameraStackService")
13
13
  local IKAimPositionPriorites = require("IKAimPositionPriorites")
14
14
 
15
15
  local MAX_AGE_FOR_AIM_DATA = 0.2
16
- local REPLICATION_RATE = 1.3
16
+ local DEFAULT_REPLICATION_RATE = 1.3
17
17
 
18
18
  local IKRigAimerLocalPlayer = setmetatable({}, BaseObject)
19
19
  IKRigAimerLocalPlayer.ClassName = "IKRigAimerLocalPlayer"
@@ -25,24 +25,37 @@ IKRigAimerLocalPlayer.__index = IKRigAimerLocalPlayer
25
25
 
26
26
  @param serviceBag ServiceBag
27
27
  @param ikRig IKRigClient
28
- @param remoteEvent RemoteEvent
29
28
  @return IKRigAimerLocalPlayer
30
29
  ]=]
31
- function IKRigAimerLocalPlayer.new(serviceBag, ikRig, remoteEvent)
30
+ function IKRigAimerLocalPlayer.new(serviceBag, ikRig)
32
31
  local self = setmetatable(BaseObject.new(), IKRigAimerLocalPlayer)
33
32
 
34
33
  self._cameraStackService = serviceBag:GetService(CameraStackService)
35
- self._remoteEvent = remoteEvent or error("No remoteEvent")
36
34
  self._ikRig = ikRig or error("No ikRig")
37
35
 
38
36
  self._lastUpdate = 0
39
37
  self._lastReplication = 0
40
- self._aimData = nil
41
38
  self._lookAround = true
42
39
 
40
+ self._aimData = nil
41
+
42
+ self._replicationRate = DEFAULT_REPLICATION_RATE
43
+ self._replicationRates = {}
44
+
43
45
  return self
44
46
  end
45
47
 
48
+ --[=[
49
+ Sets the remote event for replication
50
+
51
+ @param remoteEvent RemoteEvent
52
+ ]=]
53
+ function IKRigAimerLocalPlayer:SetRemoteEvent(remoteEvent)
54
+ assert(not self._remoteEvent, "Already have remoteEvent")
55
+
56
+ self._remoteEvent = assert(remoteEvent, "No remoteEvent")
57
+ end
58
+
46
59
  --[=[
47
60
  Sets whether the local player should look around automatically.
48
61
  @param lookAround boolean
@@ -75,11 +88,46 @@ function IKRigAimerLocalPlayer:SetAimPosition(position, optionalPriority)
75
88
  }
76
89
  end
77
90
 
91
+ function IKRigAimerLocalPlayer:PushReplicationRate(replicateRate)
92
+ assert(type(replicateRate) == "number", "Bad replicateRate")
93
+
94
+ local data = {
95
+ replicateRate = replicateRate;
96
+ }
97
+
98
+ table.insert(self._replicationRates, data)
99
+ self:_updateReplicationRate()
100
+
101
+ if #self._replicationRates >= 10 then
102
+ warn("[IKRigAimerLocalPlayer] - More than 10 replication rates stored, memory leak possible")
103
+ end
104
+
105
+ return function()
106
+ local index = table.find(self._replicationRates, data)
107
+ if index then
108
+ table.remove(self._replicationRates, index)
109
+ self:_updateReplicationRate()
110
+ end
111
+ end
112
+ end
113
+
114
+ function IKRigAimerLocalPlayer:_updateReplicationRate()
115
+ local best = nil
116
+ for _, rateData in pairs(self._replicationRates) do
117
+ local rate = rateData.replicateRate
118
+ if not best or rate < best then
119
+ best = rate
120
+ end
121
+ end
122
+
123
+ self._replicationRate = best or DEFAULT_REPLICATION_RATE
124
+ end
125
+
78
126
  --[=[
79
- Gets the current aim direction.
127
+ Gets the current aim position.
80
128
  @return Vector3?
81
129
  ]=]
82
- function IKRigAimerLocalPlayer:GetAimDirection()
130
+ function IKRigAimerLocalPlayer:GetAimPosition()
83
131
  if self._aimData and (os.clock() - self._aimData.timeStamp) < MAX_AGE_FOR_AIM_DATA then
84
132
  -- If we have aim data within the last 0.2 seconds start pointing at that
85
133
  return self._aimData.position -- May be nil
@@ -121,18 +169,18 @@ function IKRigAimerLocalPlayer:UpdateStepped()
121
169
  return
122
170
  end
123
171
 
124
- local aimDirection = self:GetAimDirection()
172
+ local aimPosition = self:GetAimPosition()
125
173
 
126
174
  self._lastUpdate = os.clock()
127
175
  local torso = self._ikRig:GetTorso()
128
176
  if torso then
129
- torso:Point(aimDirection)
177
+ torso:Point(aimPosition)
130
178
  end
131
179
 
132
180
  -- Filter replicate
133
- if (os.clock() - self._lastReplication) > REPLICATION_RATE then
181
+ if self._remoteEvent and (os.clock() - self._lastReplication) > self._replicationRate then
134
182
  self._lastReplication = os.clock()
135
- self._remoteEvent:FireServer(aimDirection)
183
+ self._remoteEvent:FireServer(aimPosition)
136
184
  end
137
185
  end
138
186
 
@@ -22,14 +22,19 @@ function IKRigClient.new(humanoid, serviceBag)
22
22
 
23
23
  self._serviceBag = assert(serviceBag, "No serviceBag")
24
24
 
25
+ if self:GetPlayer() == Players.LocalPlayer then
26
+ self:_setupLocalPlayer(self._remoteEvent)
27
+ end
28
+
25
29
  self:PromiseRemoteEvent():Then(function(remoteEvent)
26
- self._remoteEvent = remoteEvent or error("No remoteEvent")
30
+ self._remoteEvent = assert(remoteEvent, "No remoteEvent")
31
+
27
32
  self._maid:GiveTask(self._remoteEvent.OnClientEvent:Connect(function(...)
28
33
  self:_handleRemoteEventClient(...)
29
34
  end))
30
35
 
31
- if self:GetPlayer() == Players.LocalPlayer then
32
- self:_setupLocalPlayer(self._remoteEvent)
36
+ if self._localPlayerAimer then
37
+ self._localPlayerAimer:SetRemoteEvent(self._remoteEvent)
33
38
  end
34
39
  end)
35
40
 
@@ -56,9 +61,23 @@ end
56
61
  @return IKRigAimerLocalPlayer?
57
62
  ]=]
58
63
  function IKRigClient:GetLocalPlayerAimer()
59
- return self._aimer
64
+ return self._localPlayerAimer
60
65
  end
61
66
 
67
+ --[=[
68
+ Returns where the rig is looking at
69
+
70
+ @return Vector3?
71
+ ]=]
72
+ function IKRigClient:GetTarget()
73
+ if self._localPlayerAimer then
74
+ return self._localPlayerAimer:GetAimPosition()
75
+ end
76
+
77
+ return self._target
78
+ end
79
+
80
+
62
81
  function IKRigClient:_handleRemoteEventClient(newTarget)
63
82
  assert(typeof(newTarget) == "Vector3" or newTarget == nil, "Bad newTarget")
64
83
 
@@ -67,11 +86,13 @@ function IKRigClient:_handleRemoteEventClient(newTarget)
67
86
  if torso then
68
87
  torso:Point(newTarget)
69
88
  end
89
+
90
+ self._target = newTarget
70
91
  end
71
92
 
72
93
  function IKRigClient:_setupLocalPlayer(remoteEvent)
73
- self._aimer = IKRigAimerLocalPlayer.new(self._serviceBag, self, remoteEvent)
74
- self._maid:GiveTask(self._aimer)
94
+ self._localPlayerAimer = IKRigAimerLocalPlayer.new(self._serviceBag, self, remoteEvent)
95
+ self._maid:GiveTask(self._localPlayerAimer)
75
96
  end
76
97
 
77
98
  return IKRigClient
@@ -21,6 +21,7 @@ function IKRig.new(humanoid)
21
21
 
22
22
  self._remoteEvent = Instance.new("RemoteEvent")
23
23
  self._remoteEvent.Name = IKConstants.REMOTE_EVENT_NAME
24
+ self._remoteEvent.Archivable = false
24
25
  self._remoteEvent.Parent = self._obj
25
26
  self._maid:GiveTask(self._remoteEvent)
26
27
 
@@ -5,6 +5,8 @@
5
5
 
6
6
  local require = require(script.Parent.loader).load(script)
7
7
 
8
+ local RunService = game:GetService("RunService")
9
+
8
10
  local BaseObject = require("BaseObject")
9
11
  local IKAimPositionPriorites = require("IKAimPositionPriorites")
10
12
  local IKResource = require("IKResource")
@@ -12,8 +14,11 @@ local IKResourceUtils = require("IKResourceUtils")
12
14
  local Maid = require("Maid")
13
15
  local Math = require("Math")
14
16
  local RagdollConstants = require("RagdollConstants")
17
+ local LimbIKUtils = require("LimbIKUtils")
18
+ local QFrame = require("QFrame")
15
19
 
16
20
  local CFA_90X = CFrame.Angles(math.pi/2, 0, 0)
21
+ local USE_OLD_IK_SYSTEM = false
17
22
 
18
23
  local ArmIKBase = setmetatable({}, BaseObject)
19
24
  ArmIKBase.ClassName = "ArmIKBase"
@@ -26,10 +31,28 @@ function ArmIKBase.new(humanoid, armName)
26
31
 
27
32
  self._grips = {}
28
33
 
34
+ if armName == "Left" then
35
+ self._direction = 1
36
+ elseif armName == "Right" then
37
+ self._direction = -1
38
+ else
39
+ error("Bad arm")
40
+ end
41
+
29
42
  self._resources = IKResource.new(IKResourceUtils.createResource({
30
43
  name = "Character";
31
44
  robloxName = self._humanoid.Parent.Name;
32
45
  children = {
46
+ IKResourceUtils.createResource({
47
+ name = "UpperTorso";
48
+ robloxName = "UpperTorso";
49
+ children = {
50
+ IKResourceUtils.createResource({
51
+ name = "UpperTorsoShoulderRigAttachment";
52
+ robloxName = armName .. "ShoulderRigAttachment";
53
+ });
54
+ };
55
+ });
33
56
  IKResourceUtils.createResource({
34
57
  name = "UpperArm";
35
58
  robloxName = armName .. "UpperArm";
@@ -38,6 +61,14 @@ function ArmIKBase.new(humanoid, armName)
38
61
  name = "Shoulder";
39
62
  robloxName = armName .. "Shoulder";
40
63
  });
64
+ IKResourceUtils.createResource({
65
+ name = "UpperArmShoulderRigAttachment";
66
+ robloxName = armName .. "ShoulderRigAttachment";
67
+ });
68
+ IKResourceUtils.createResource({
69
+ name = "UpperArmElbowRigAttachment";
70
+ robloxName = armName .. "ElbowRigAttachment";
71
+ });
41
72
  };
42
73
  });
43
74
  IKResourceUtils.createResource({
@@ -48,6 +79,14 @@ function ArmIKBase.new(humanoid, armName)
48
79
  name = "Elbow";
49
80
  robloxName = armName .. "Elbow";
50
81
  });
82
+ IKResourceUtils.createResource({
83
+ name = "LowerArmElbowRigAttachment";
84
+ robloxName = armName .. "ElbowRigAttachment";
85
+ });
86
+ IKResourceUtils.createResource({
87
+ name = "LowerArmWristRigAttachment";
88
+ robloxName = armName .. "WristRigAttachment";
89
+ });
51
90
  };
52
91
  });
53
92
  IKResourceUtils.createResource({
@@ -58,6 +97,10 @@ function ArmIKBase.new(humanoid, armName)
58
97
  name = "Wrist";
59
98
  robloxName = armName .. "Wrist";
60
99
  });
100
+ IKResourceUtils.createResource({
101
+ name = "HandWristRigAttachment";
102
+ robloxName = armName .. "WristRigAttachment";
103
+ });
61
104
  IKResourceUtils.createResource({
62
105
  name = "HandGripAttachment";
63
106
  robloxName = armName .. "GripAttachment";
@@ -66,6 +109,7 @@ function ArmIKBase.new(humanoid, armName)
66
109
  });
67
110
  }
68
111
  }))
112
+
69
113
  self._maid:GiveTask(self._resources)
70
114
  self._resources:SetInstance(self._humanoid.Parent or error("No humanoid.Parent"))
71
115
 
@@ -120,7 +164,7 @@ function ArmIKBase:UpdateTransformOnly()
120
164
  if not self._grips[1] then
121
165
  return
122
166
  end
123
- if not self._shoulderTransform or not self._elbowTransform then
167
+ if not (self._shoulderTransform and self._elbowTransform and self._wristTransform) then
124
168
  return
125
169
  end
126
170
  if not self._resources:IsReady() then
@@ -129,33 +173,56 @@ function ArmIKBase:UpdateTransformOnly()
129
173
 
130
174
  local shoulder = self._resources:Get("Shoulder")
131
175
  local elbow = self._resources:Get("Elbow")
176
+ local wrist = self._resources:Get("Wrist")
132
177
 
133
- shoulder.Transform = self._shoulderTransform
134
- elbow.Transform = self._elbowTransform
178
+ if RunService:IsRunning() then
179
+ shoulder.Transform = self._shoulderTransform
180
+ elbow.Transform = self._elbowTransform
181
+ wrist.Transform = self._wristTransform
182
+ else
183
+ -- Test mode/story mode
184
+ if not self._initTest then
185
+ self._initTest = true
186
+ self._testDefaultShoulderC0 = shoulder.C0
187
+ self._testDefaultElbowC0 = elbow.C0
188
+ self._testDefaultWristC0 = wrist.C0
189
+ end
190
+
191
+ shoulder.C0 = self._testDefaultShoulderC0 * self._shoulderTransform
192
+ elbow.C0 = self._testDefaultElbowC0 * self._elbowTransform
193
+ wrist.C0 = self._testDefaultWristC0 * self._wristTransform
194
+ end
135
195
  end
136
196
 
137
197
  function ArmIKBase:Update()
138
- if self:_updatePoint() then
139
- local shoulderXAngle = self._shoulderXAngle
140
- local elbowXAngle = self._elbowXAngle
198
+ if USE_OLD_IK_SYSTEM then
199
+ if self:_oldUpdatePoint() then
200
+ local shoulderXAngle = self._shoulderXAngle
201
+ local elbowXAngle = self._elbowXAngle
141
202
 
142
- local yrot = CFrame.new(Vector3.new(), self._offset)
203
+ local yrot = CFrame.new(Vector3.new(), self._offset)
143
204
 
144
- self._shoulderTransform = (yrot * CFA_90X * CFrame.Angles(shoulderXAngle, 0, 0)) --:inverse()
145
- self._elbowTransform = CFrame.Angles(elbowXAngle, 0, 0)
205
+ self._shoulderTransform = (yrot * CFA_90X * CFrame.Angles(shoulderXAngle, 0, 0)) --:inverse()
206
+ self._elbowTransform = CFrame.Angles(elbowXAngle, 0, 0)
207
+ self._wristTransform = CFrame.new()
146
208
 
147
- self:UpdateTransformOnly()
209
+ self:UpdateTransformOnly()
210
+ end
211
+ else
212
+ if self:_newUpdate() then
213
+ self:UpdateTransformOnly()
214
+ end
148
215
  end
149
216
  end
150
217
 
151
- function ArmIKBase:_updatePoint()
218
+ function ArmIKBase:_oldUpdatePoint()
152
219
  local grip = self._grips[1]
153
220
  if not grip then
154
221
  self:_clear()
155
222
  return false
156
223
  end
157
224
 
158
- if not self:_calculatePoint(grip.attachment.WorldPosition) then
225
+ if not self:_oldCalculatePoint(grip.attachment.WorldPosition) then
159
226
  self:_clear()
160
227
  return false
161
228
  end
@@ -167,9 +234,50 @@ function ArmIKBase:_clear()
167
234
  self._offset = nil
168
235
  self._elbowTransform = nil
169
236
  self._shoulderTransform = nil
237
+ self._wristTransform = nil
170
238
  end
171
239
 
172
- function ArmIKBase:_calculatePoint(targetPositionWorld)
240
+ function ArmIKBase:_newUpdate()
241
+ local grip = self._grips[1]
242
+ if not (grip and self._resources:IsReady()) then
243
+ self._elbowTransform = nil
244
+ self._shoulderTransform = nil
245
+ self._wristTransform = nil
246
+ return false
247
+ end
248
+
249
+ local targetCFrame = grip.attachment.WorldCFrame
250
+
251
+ local upperTorsoShoulderRigAttachment = self._resources:Get("UpperTorsoShoulderRigAttachment")
252
+
253
+ local upperArmShoulderRigAttachment = self._resources:Get("UpperArmShoulderRigAttachment")
254
+ local upperArmElbowRigAttachment = self._resources:Get("UpperArmElbowRigAttachment")
255
+ local elbowOffset = upperArmElbowRigAttachment.Position - upperArmShoulderRigAttachment.Position
256
+
257
+ local lowerArmElbowRigAttachment = self._resources:Get("LowerArmElbowRigAttachment")
258
+ local lowerArmWristRigAttachment = self._resources:Get("LowerArmWristRigAttachment")
259
+ local wristOffset = lowerArmWristRigAttachment.Position - lowerArmElbowRigAttachment.Position
260
+
261
+ local handWristRigAttachment = self._resources:Get("HandWristRigAttachment")
262
+ local handGripAttachment = self._resources:Get("HandGripAttachment")
263
+ local handOffset = handGripAttachment.Position - handWristRigAttachment.Position
264
+
265
+ -- TODO: Cache config
266
+ local config = LimbIKUtils.createConfig(elbowOffset, wristOffset + handOffset, 1)
267
+ local relTargetCFrame = upperTorsoShoulderRigAttachment.WorldCFrame:toObjectSpace(targetCFrame)
268
+
269
+ -- TODO: Allow configuration
270
+ local ELBOW_ANGLE = math.rad(20)
271
+ local shoulderQFrame, elbowQFrame, wristQFrame = LimbIKUtils.solveLimb(config, QFrame.fromCFrameClosestTo(relTargetCFrame, QFrame.new()), self._direction*ELBOW_ANGLE)
272
+
273
+ self._shoulderTransform = QFrame.toCFrame(shoulderQFrame)
274
+ self._elbowTransform = QFrame.toCFrame(elbowQFrame)
275
+ self._wristTransform = QFrame.toCFrame(wristQFrame)
276
+
277
+ return true
278
+ end
279
+
280
+ function ArmIKBase:_oldCalculatePoint(targetPositionWorld)
173
281
  if not self._resources:IsReady() then
174
282
  return false
175
283
  end
@@ -182,9 +290,9 @@ function ArmIKBase:_calculatePoint(targetPositionWorld)
182
290
  return false
183
291
  end
184
292
 
185
- local base = shoulder.Part0.CFrame * shoulder.C0
186
- local elbowCFrame = elbow.Part0.CFrame * elbow.C0
187
- local wristCFrame = elbow.Part1.CFrame * wrist.C0
293
+ local base = shoulder.Part0.CFrame * (self._testDefaultShoulderC0 or shoulder.C0)
294
+ local elbowCFrame = elbow.Part0.CFrame * (self._testDefaultElbowC0 or elbow.C0)
295
+ local wristCFrame = elbow.Part1.CFrame * (self._testDefaultWristC0 or wrist.C0)
188
296
 
189
297
  local r0 = (base.Position - elbowCFrame.Position).Magnitude
190
298
  local r1 = (elbowCFrame.Position - wristCFrame.Position).Magnitude
@@ -216,7 +324,6 @@ function ArmIKBase:_calculatePoint(targetPositionWorld)
216
324
 
217
325
  self._shoulderXAngle = -baseAngle
218
326
  self._elbowXAngle = -elbowAngle
219
-
220
327
  self._offset = offset.unit * d
221
328
 
222
329
  return true
@@ -0,0 +1,47 @@
1
+ --[[
2
+ @class ArmIKBase.story
3
+ ]]
4
+
5
+ local require = require(game:GetService("ServerScriptService"):FindFirstChild("LoaderUtils", true).Parent).load(script)
6
+
7
+ local Workspace = game:GetService("Workspace")
8
+ local RunService = game:GetService("RunService")
9
+
10
+ local Maid = require("Maid")
11
+ local RigBuilderUtils = require("RigBuilderUtils")
12
+ local ArmIKBase = require("ArmIKBase")
13
+
14
+ return function(_target)
15
+ local maid = Maid.new()
16
+
17
+ maid:GivePromise(RigBuilderUtils.promisePlayerRig(4397833)):Then(function(character)
18
+ maid:GiveTask(character)
19
+
20
+ local humanoid = character.Humanoid
21
+ local position = Workspace.CurrentCamera.CFrame:pointToWorldSpace(Vector3.new(0, 0, -10))
22
+
23
+ local armIKBase = ArmIKBase.new(humanoid, "Right")
24
+ maid:GiveTask(armIKBase)
25
+
26
+ local attachment = Instance.new("Attachment")
27
+ attachment.Name = "IKRigStoryTarget"
28
+ attachment.Parent = workspace.Terrain
29
+ attachment.WorldPosition = position + Workspace.CurrentCamera.CFrame:vectorToWorldSpace(Vector3.new(2, 0, 1))
30
+ maid:GiveTask(attachment)
31
+
32
+ armIKBase:Grip(attachment)
33
+
34
+ humanoid.RootPart.CFrame = CFrame.new(position)
35
+ character.Parent = workspace
36
+ humanoid.RootPart.CFrame = CFrame.new(position)
37
+
38
+ maid:GiveTask(RunService.RenderStepped:Connect(function()
39
+ armIKBase:Update()
40
+ end))
41
+ end)
42
+
43
+
44
+ return function()
45
+ maid:DoCleaning()
46
+ end
47
+ end
@@ -69,6 +69,10 @@ function IKRigBase:GetTorso()
69
69
  end
70
70
 
71
71
  function IKRigBase:PromiseLeftArm()
72
+ if self._obj.RigType ~= Enum.HumanoidRigType.R15 then
73
+ return Promise.rejected("Rig is not HumanoidRigType.R15")
74
+ end
75
+
72
76
  return Promise.resolved(self:GetLeftArm())
73
77
  end
74
78
 
@@ -81,6 +85,10 @@ function IKRigBase:GetLeftArm()
81
85
  end
82
86
 
83
87
  function IKRigBase:PromiseRightArm()
88
+ if self._obj.RigType ~= Enum.HumanoidRigType.R15 then
89
+ return Promise.rejected("Rig is not HumanoidRigType.R15")
90
+ end
91
+
84
92
  return Promise.resolved(self:GetRightArm())
85
93
  end
86
94
 
@@ -96,7 +104,7 @@ function IKRigBase:_getNewArm(armName)
96
104
  assert(armName == "Left" or armName == "Right", "Bad armName")
97
105
 
98
106
  if self._obj.RigType ~= Enum.HumanoidRigType.R15 then
99
- return Promise.rejected("Rig is not HumanoidRigType.R15")
107
+ return nil
100
108
  end
101
109
 
102
110
  local newIk = ArmIKBase.new(self._obj, armName)
@@ -1,18 +1,10 @@
1
1
  {
2
- "name": "iktest",
2
+ "name": "IKTest",
3
3
  "tree": {
4
4
  "$className": "DataModel",
5
- "ReplicatedStorage": {
6
- "Nevermore": {
7
- "$path": "../node_modules/@quenty/loader"
8
- }
9
- },
10
5
  "ServerScriptService": {
11
- "Nevermore": {
12
- "$className": "folder",
13
- "IK": {
14
- "$path": ".."
15
- }
6
+ "ik": {
7
+ "$path": ".."
16
8
  },
17
9
  "Script": {
18
10
  "$path": "scripts/Server"
@@ -2,13 +2,13 @@
2
2
  @class ClientMain
3
3
  ]]
4
4
 
5
- local require = require(script.Parent.loader).load(script)
5
+ local packages = game:GetService("ReplicatedStorage"):WaitForChild("Packages")
6
6
 
7
- local serviceBag = require("ServiceBag").new()
8
- serviceBag:GetService(require("IKServiceClient"))
7
+ local serviceBag = require(packages.ServiceBag).new()
8
+ local ikServiceClient = serviceBag:GetService(packages.IKServiceClient)
9
9
 
10
10
  serviceBag:Init()
11
11
  serviceBag:Start()
12
12
 
13
13
  -- Configure
14
- serviceBag:GetService(require("IKServiceClient")):SetLookAround(true)
14
+ ikServiceClient:SetLookAround(true)
@@ -2,16 +2,22 @@
2
2
  @class ServerMain
3
3
  ]]
4
4
 
5
- local require = require(script.Parent.loader).load(script)
5
+ local ServerScriptService = game:GetService("ServerScriptService")
6
+ local RunService = game:GetService("RunService")
6
7
 
7
- local serviceBag = require("ServiceBag").new()
8
- serviceBag:GetService(require("IKService"))
8
+ local loader = ServerScriptService:FindFirstChild("LoaderUtils", true).Parent
9
+ local packages = require(loader).bootstrapGame(ServerScriptService.ik)
9
10
 
11
+ local serviceBag = require(packages.ServiceBag).new()
12
+ local ikService = serviceBag:GetService(packages.IKService)
13
+
14
+ -- Start game
10
15
  serviceBag:Init()
11
16
  serviceBag:Start()
12
17
 
18
+
13
19
  -- Build test NPC rigs
14
- local RigBuilderUtils = require("RigBuilderUtils")
20
+ local RigBuilderUtils = require(packages.RigBuilderUtils)
15
21
  RigBuilderUtils.promiseR15MeshRig()
16
22
  :Then(function(character)
17
23
  local humanoid = character.Humanoid
@@ -21,6 +27,8 @@ RigBuilderUtils.promiseR15MeshRig()
21
27
  character.Parent = workspace
22
28
  humanoid.RootPart.CFrame = CFrame.new(0, 25, 0)
23
29
 
24
- -- look down
25
- serviceBag:GetService(require("IKService")):UpdateServerRigTarget(humanoid, Vector3.new(0, 0, 0))
30
+ -- look at origin
31
+ RunService.Stepped:Connect(function()
32
+ ikService:UpdateServerRigTarget(humanoid, Vector3.new(0, 0, 0))
33
+ end)
26
34
  end)