@quenty/ik 15.34.3 → 15.34.4

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,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
+ ## [15.34.4](https://github.com/Quenty/NevermoreEngine/compare/@quenty/ik@15.34.3...@quenty/ik@15.34.4) (2025-12-28)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * Retrieve priority ([ade11b6](https://github.com/Quenty/NevermoreEngine/commit/ade11b6743f9d9dc7ad2324bcbb31d58669f048e))
12
+ * Typecheck some more things ([41eaaa6](https://github.com/Quenty/NevermoreEngine/commit/41eaaa6d053c469f7548810da72d05dfbf997b26))
13
+
14
+
15
+
16
+
17
+
6
18
  ## [15.34.3](https://github.com/Quenty/NevermoreEngine/compare/@quenty/ik@15.34.2...@quenty/ik@15.34.3) (2025-12-13)
7
19
 
8
20
  **Note:** Version bump only for package @quenty/ik
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quenty/ik",
3
- "version": "15.34.3",
3
+ "version": "15.34.4",
4
4
  "description": "Inverse Kinematics for characters on Roblox",
5
5
  "keywords": [
6
6
  "Roblox",
@@ -28,28 +28,28 @@
28
28
  "dependencies": {
29
29
  "@quenty/acceltween": "^2.5.3",
30
30
  "@quenty/baseobject": "^10.9.0",
31
- "@quenty/binder": "^14.25.2",
31
+ "@quenty/binder": "^14.25.3",
32
32
  "@quenty/brio": "^14.20.1",
33
- "@quenty/camera": "^14.26.2",
33
+ "@quenty/camera": "^14.26.3",
34
34
  "@quenty/characterutils": "^12.22.2",
35
- "@quenty/humanoidtracker": "^13.21.2",
35
+ "@quenty/humanoidtracker": "^13.21.3",
36
36
  "@quenty/instanceutils": "^13.20.2",
37
37
  "@quenty/loader": "^10.9.0",
38
38
  "@quenty/maid": "^3.5.0",
39
39
  "@quenty/math": "^2.7.3",
40
- "@quenty/motor6d": "^7.28.2",
40
+ "@quenty/motor6d": "^7.28.3",
41
41
  "@quenty/optional": "^11.9.0",
42
42
  "@quenty/promise": "^10.12.0",
43
43
  "@quenty/qframe": "^10.12.1",
44
44
  "@quenty/r15utils": "^13.21.2",
45
- "@quenty/ragdoll": "^15.33.2",
45
+ "@quenty/ragdoll": "^15.33.3",
46
46
  "@quenty/remoting": "^12.21.2",
47
47
  "@quenty/rx": "^13.20.0",
48
- "@quenty/servicebag": "^11.13.1",
48
+ "@quenty/servicebag": "^11.13.2",
49
49
  "@quenty/signal": "^7.11.1",
50
50
  "@quenty/table": "^3.8.0",
51
- "@quenty/tie": "^10.26.2",
52
- "@quenty/valueobject": "^13.21.2"
51
+ "@quenty/tie": "^10.26.3",
52
+ "@quenty/valueobject": "^13.21.3"
53
53
  },
54
54
  "devDependencies": {
55
55
  "@quenty/rigbuilderutils": "^10.22.3"
@@ -57,5 +57,5 @@
57
57
  "publishConfig": {
58
58
  "access": "public"
59
59
  },
60
- "gitHead": "08c1d0559af2bbcece6d586897c91a630dfb3f51"
60
+ "gitHead": "821c9336020dfbcf5cd2f67f2dfe61624233ee06"
61
61
  }
@@ -1,3 +1,4 @@
1
+ --!nonstrict
1
2
  --[=[
2
3
  Provides IK for a given arm
3
4
  @class ArmIKBase
@@ -1,3 +1,4 @@
1
+ --!strict
1
2
  --[=[
2
3
  @class ArmIKUtils
3
4
  ]=]
@@ -10,7 +11,9 @@ local RxR15Utils = require("RxR15Utils")
10
11
 
11
12
  local ArmIKUtils = {}
12
13
 
13
- function ArmIKUtils.ensureMotorAnimated(character: Model, armName)
14
+ export type ArmName = "Left" | "Right"
15
+
16
+ function ArmIKUtils.ensureMotorAnimated(character: Model, armName: ArmName): Maid.Maid
14
17
  local topMaid = Maid.new()
15
18
 
16
19
  local function disable(brio)
@@ -1,3 +1,4 @@
1
+ --!strict
1
2
  --[=[
2
3
  Meant to be used with a binder
3
4
  @class IKGripBase
@@ -16,11 +17,23 @@ local IKGripBase = setmetatable({}, BaseObject)
16
17
  IKGripBase.ClassName = "IKGripBase"
17
18
  IKGripBase.__index = IKGripBase
18
19
 
19
- function IKGripBase.new(objectValue: ObjectValue, serviceBag: ServiceBag.ServiceBag)
20
- local self = setmetatable(BaseObject.new(objectValue), IKGripBase)
20
+ export type IKGripBase =
21
+ typeof(setmetatable(
22
+ {} :: {
23
+ _obj: Instance,
24
+ _serviceBag: ServiceBag.ServiceBag,
25
+ _attachment: Attachment,
26
+ _ikRigPromise: Promise.Promise<any>,
27
+ },
28
+ {} :: typeof({ __index = IKGripBase })
29
+ ))
30
+ & BaseObject.BaseObject
31
+
32
+ function IKGripBase.new(objectValue: ObjectValue, serviceBag: ServiceBag.ServiceBag): IKGripBase
33
+ local self: IKGripBase = setmetatable(BaseObject.new(objectValue) :: any, IKGripBase)
21
34
 
22
35
  self._serviceBag = assert(serviceBag, "No serviceBag")
23
- self._attachment = self._obj.Parent
36
+ self._attachment = self._obj.Parent :: any
24
37
 
25
38
  assert(self._obj:IsA("ObjectValue"), "Not an object value")
26
39
  assert(self._attachment:IsA("Attachment"), "Not parented to an attachment")
@@ -28,15 +41,15 @@ function IKGripBase.new(objectValue: ObjectValue, serviceBag: ServiceBag.Service
28
41
  return self
29
42
  end
30
43
 
31
- function IKGripBase:GetPriority(): number
44
+ function IKGripBase.GetPriority(_self: IKGripBase): number
32
45
  return 1
33
46
  end
34
47
 
35
- function IKGripBase:GetAttachment(): Attachment?
36
- return self._obj.Parent
48
+ function IKGripBase.GetAttachment(self: IKGripBase): Attachment?
49
+ return self._attachment
37
50
  end
38
51
 
39
- function IKGripBase:PromiseIKRig()
52
+ function IKGripBase.PromiseIKRig(self: IKGripBase): Promise.Promise<any>
40
53
  if self._ikRigPromise then
41
54
  return self._ikRigPromise
42
55
  end
@@ -48,10 +61,7 @@ function IKGripBase:PromiseIKRig()
48
61
  ikService = self._serviceBag:GetService((require :: any)("IKServiceClient"))
49
62
  end
50
63
 
51
- local promise = promisePropertyValue(self._obj, "Value")
52
- self._maid:GiveTask(promise)
53
-
54
- self._ikRigPromise = promise:Then(function(humanoid)
64
+ self._ikRigPromise = self._maid:Add(promisePropertyValue(self._obj, "Value")):Then(function(humanoid)
55
65
  if not humanoid:IsA("Humanoid") then
56
66
  warn("[IKGripBase.PromiseIKRig] - Humanoid in link is not a humanoid")
57
67
  return Promise.rejected()
@@ -60,7 +70,7 @@ function IKGripBase:PromiseIKRig()
60
70
  return self._maid:GivePromise(ikService:PromiseRig(humanoid))
61
71
  end)
62
72
 
63
- return self._ikRigPromise
73
+ return self._ikRigPromise :: any
64
74
  end
65
75
 
66
76
  return IKGripBase
@@ -1,3 +1,4 @@
1
+ --!strict
1
2
  --[=[
2
3
  @class IKDataService
3
4
  ]=]
@@ -6,6 +6,14 @@
6
6
 
7
7
  local IKUtils = {}
8
8
 
9
+ --[=[
10
+ Returns a function that dampens angles approaching maxAngle.
11
+
12
+ @param maxAngle number -- The maximum angle allowed
13
+ @param dampenAreaAngle number -- The area over which to dampen
14
+ @param dampenAreaFactor number? -- The factor to use for dampening. Defaults to dampenAreaAngle.
15
+ @return (number) -> number -- A function that takes an angle and returns a dampened angle
16
+ ]=]
9
17
  function IKUtils.getDampenedAngleClamp(
10
18
  maxAngle: number,
11
19
  dampenAreaAngle: number,
@@ -1,3 +1,4 @@
1
+ --!strict
1
2
  --[=[
2
3
  @class IKResource
3
4
  ]=]
@@ -5,29 +6,46 @@
5
6
  local require = require(script.Parent.loader).load(script)
6
7
 
7
8
  local BaseObject = require("BaseObject")
9
+ local IKResourceUtils = require("IKResourceUtils")
8
10
  local Maid = require("Maid")
11
+ local Signal = require("Signal")
9
12
  local ValueObject = require("ValueObject")
10
13
 
11
14
  local IKResource = setmetatable({}, BaseObject)
12
15
  IKResource.ClassName = "IKResource"
13
16
  IKResource.__index = IKResource
14
17
 
15
- function IKResource.new(data)
16
- local self = setmetatable(BaseObject.new(), IKResource)
18
+ export type IKResource =
19
+ typeof(setmetatable(
20
+ {} :: {
21
+ _data: IKResourceUtils.IKResourceData,
22
+ _instance: Instance?,
23
+ _childResourceMap: { [string]: IKResource },
24
+ _descendantLookupMap: { [string]: IKResource },
25
+ _ready: ValueObject.ValueObject<boolean>,
26
+
27
+ ReadyChanged: Signal.Signal<boolean>,
28
+ },
29
+ {} :: typeof({ __index = IKResource })
30
+ ))
31
+ & BaseObject.BaseObject
32
+
33
+ function IKResource.new(data: IKResourceUtils.IKResourceData): IKResource
34
+ local self: IKResource = setmetatable(BaseObject.new() :: any, IKResource)
17
35
 
18
36
  self._data = assert(data, "Bad data")
19
37
  assert(data.name, "Bad data.name")
20
38
  assert(data.robloxName, "Bad data.robloxName")
21
39
 
22
40
  self._instance = nil
23
- self._childResourceMap = {} -- [robloxName] = { data = data; ikResource = ikResource }
41
+ self._childResourceMap = {} -- [robloxName] = IKResource
24
42
  self._descendantLookupMap = {
25
43
  [data.name] = self,
26
44
  }
27
45
 
28
46
  self._ready = self._maid:Add(ValueObject.new(false, "boolean"))
29
47
 
30
- self.ReadyChanged = self._ready.Changed
48
+ self.ReadyChanged = self._ready.Changed :: any
31
49
 
32
50
  if self._data.children then
33
51
  for _, childData in self._data.children do
@@ -38,15 +56,15 @@ function IKResource.new(data)
38
56
  return self
39
57
  end
40
58
 
41
- function IKResource:GetData()
59
+ function IKResource.GetData(self: IKResource): IKResourceUtils.IKResourceData
42
60
  return self._data
43
61
  end
44
62
 
45
- function IKResource:IsReady(): boolean
63
+ function IKResource.IsReady(self: IKResource): boolean
46
64
  return self._ready.Value
47
65
  end
48
66
 
49
- function IKResource:Get(descendantName: string)
67
+ function IKResource.Get(self: IKResource, descendantName: string)
50
68
  local resource = self._descendantLookupMap[descendantName]
51
69
  if not resource then
52
70
  error(string.format("[IKResource.Get] - Resource %q does not exist", tostring(descendantName)))
@@ -60,9 +78,9 @@ function IKResource:Get(descendantName: string)
60
78
  return result
61
79
  end
62
80
 
63
- function IKResource:GetInstance(): Instance?
81
+ function IKResource.GetInstance(self: IKResource): Instance?
64
82
  if self._data.isLink then
65
- if self._instance then
83
+ if self._instance and self._instance:IsA("ObjectValue") then
66
84
  return self._instance.Value
67
85
  else
68
86
  return nil
@@ -72,7 +90,7 @@ function IKResource:GetInstance(): Instance?
72
90
  return self._instance
73
91
  end
74
92
 
75
- function IKResource:SetInstance(instance: Instance?)
93
+ function IKResource.SetInstance(self: IKResource, instance: Instance?)
76
94
  if self._instance == instance then
77
95
  return
78
96
  end
@@ -91,7 +109,7 @@ function IKResource:SetInstance(instance: Instance?)
91
109
  end
92
110
 
93
111
  if instance and self._data.isLink then
94
- assert(instance:IsA("ObjectValue"))
112
+ assert(instance:IsA("ObjectValue"), "Bad instance for link IKResource")
95
113
 
96
114
  self._maid:GiveTask(instance.Changed:Connect(function()
97
115
  self:_updateReady()
@@ -102,11 +120,11 @@ function IKResource:SetInstance(instance: Instance?)
102
120
  self:_updateReady()
103
121
  end
104
122
 
105
- function IKResource:GetLookupTable()
123
+ function IKResource.GetLookupTable(self: IKResource)
106
124
  return self._descendantLookupMap
107
125
  end
108
126
 
109
- function IKResource:_startListening(maid, instance)
127
+ function IKResource._startListening(self: IKResource, maid, instance)
110
128
  for _, child in instance:GetChildren() do
111
129
  self:_handleChildAdded(child)
112
130
  end
@@ -119,7 +137,7 @@ function IKResource:_startListening(maid, instance)
119
137
  end))
120
138
  end
121
139
 
122
- function IKResource:_addResource(ikResource)
140
+ function IKResource._addResource(self: IKResource, ikResource: IKResource)
123
141
  local data = ikResource:GetData()
124
142
  assert(data.name, "Bad data.name")
125
143
  assert(data.robloxName, "Bad data.robloxName")
@@ -144,7 +162,7 @@ function IKResource:_addResource(ikResource)
144
162
  end
145
163
  end
146
164
 
147
- function IKResource:_handleChildAdded(child)
165
+ function IKResource._handleChildAdded(self: IKResource, child)
148
166
  local resource = self._childResourceMap[child.Name]
149
167
  if not resource then
150
168
  return
@@ -153,7 +171,7 @@ function IKResource:_handleChildAdded(child)
153
171
  resource:SetInstance(child)
154
172
  end
155
173
 
156
- function IKResource:_handleChildRemoved(child)
174
+ function IKResource._handleChildRemoved(self: IKResource, child)
157
175
  local resource = self._childResourceMap[child.Name]
158
176
  if not resource then
159
177
  return
@@ -164,28 +182,28 @@ function IKResource:_handleChildRemoved(child)
164
182
  end
165
183
  end
166
184
 
167
- function IKResource:_clearChildren()
168
- for _, child in self._childResourceMap do
185
+ function IKResource._clearChildren(self: IKResource)
186
+ for _, child: any in self._childResourceMap do
169
187
  child:SetInstance(nil)
170
188
  end
171
189
  end
172
190
 
173
- function IKResource:_updateReady()
191
+ function IKResource._updateReady(self: IKResource)
174
192
  self._ready.Value = self:_calculateIsReady()
175
193
  end
176
194
 
177
- function IKResource:_calculateIsReady()
195
+ function IKResource._calculateIsReady(self: IKResource)
178
196
  if not self._instance then
179
197
  return false
180
198
  end
181
199
 
182
200
  if self._data.isLink then
183
- if not self._instance.Value then
201
+ if self._instance and self._instance:IsA("ObjectValue") and not self._instance.Value then
184
202
  return false
185
203
  end
186
204
  end
187
205
 
188
- for _, child in self._childResourceMap do
206
+ for _, child: any in self._childResourceMap do
189
207
  if not child:IsReady() then
190
208
  return false
191
209
  end
@@ -1,10 +1,18 @@
1
+ --!strict
1
2
  --[=[
2
3
  @class IKResourceUtils
3
4
  ]=]
4
5
 
5
6
  local IKResourceUtils = {}
6
7
 
7
- function IKResourceUtils.createResource(data)
8
+ export type IKResourceData = {
9
+ name: string,
10
+ isLink: boolean?,
11
+ robloxName: string,
12
+ children: { IKResourceData }?,
13
+ }
14
+
15
+ function IKResourceUtils.createResource(data: IKResourceData): IKResourceData
8
16
  assert(type(data) == "table", "Bad data")
9
17
  assert(data.name, "Bad data.name")
10
18
  assert(data.robloxName, "Bad data.robloxName")
@@ -16,8 +16,38 @@ local TorsoIKBase = setmetatable({}, BaseObject)
16
16
  TorsoIKBase.__index = TorsoIKBase
17
17
  TorsoIKBase.ClassName = "TorsoIKBase"
18
18
 
19
+ export type TorsoIKBase =
20
+ typeof(setmetatable(
21
+ {} :: {
22
+ _humanoid: Humanoid,
23
+ _resources: IKResource.IKResource,
24
+ _waistY: AccelTween.AccelTween,
25
+ _waistZ: AccelTween.AccelTween,
26
+ _headY: AccelTween.AccelTween,
27
+ _headZ: AccelTween.AccelTween,
28
+ _relWaistTransform: CFrame?,
29
+ _relNeckTransform: CFrame?,
30
+ _lastValidWaistTransform: CFrame,
31
+ _lastWaistTransform: CFrame,
32
+ _lastValidNeckTransform: CFrame,
33
+ _lastNeckTransform: CFrame,
34
+ _target: Vector3?,
35
+
36
+ Pointed: Signal.Signal<Vector3?>,
37
+
38
+ Update: (self: TorsoIKBase) -> (),
39
+ UpdateTransformOnly: (self: TorsoIKBase) -> (),
40
+ Point: (self: TorsoIKBase, position: Vector3?) -> (),
41
+ GetAimPosition: (self: TorsoIKBase) -> Vector3?,
42
+ GetTargetUpperTorsoCFrame: (self: TorsoIKBase) -> CFrame?,
43
+ GetUpperTorsoCFrame: (self: TorsoIKBase) -> CFrame?,
44
+ },
45
+ {} :: typeof({ __index = TorsoIKBase })
46
+ ))
47
+ & BaseObject.BaseObject
48
+
19
49
  function TorsoIKBase.new(humanoid: Humanoid)
20
- local self = setmetatable(BaseObject.new(), TorsoIKBase)
50
+ local self: TorsoIKBase = setmetatable(BaseObject.new() :: any, TorsoIKBase)
21
51
 
22
52
  self._humanoid = humanoid or error("No humanoid")
23
53
 
@@ -25,7 +55,8 @@ function TorsoIKBase.new(humanoid: Humanoid)
25
55
 
26
56
  self._resources = IKResource.new(IKResourceUtils.createResource({
27
57
  name = "Character",
28
- robloxName = self._humanoid.Parent.Name,
58
+ -- TODO: Fix this potentail error
59
+ robloxName = (self._humanoid :: any).Parent.Name,
29
60
  children = {
30
61
  IKResourceUtils.createResource({
31
62
  name = "RootPart",