@rbxts/vfx-forge 2.2.2

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.
Files changed (38) hide show
  1. package/LICENSE +82 -0
  2. package/README.md +39 -0
  3. package/out/effects/beam.luau +312 -0
  4. package/out/effects/bezier.luau +392 -0
  5. package/out/effects/camera_shake.luau +200 -0
  6. package/out/effects/lightning.luau +1183 -0
  7. package/out/effects/mesh.luau +466 -0
  8. package/out/effects/particle.luau +64 -0
  9. package/out/effects/randomizer.luau +110 -0
  10. package/out/effects/screen.luau +61 -0
  11. package/out/effects/shockwave_debris.luau +277 -0
  12. package/out/effects/shockwave_line.luau +356 -0
  13. package/out/effects/shockwave_ring.luau +252 -0
  14. package/out/effects/sound.luau +311 -0
  15. package/out/effects/spin.luau +88 -0
  16. package/out/effects/tweener.luau +122 -0
  17. package/out/emitters.luau +387 -0
  18. package/out/index.d.ts +341 -0
  19. package/out/init.luau +279 -0
  20. package/out/mod/attributes.luau +227 -0
  21. package/out/mod/color/Oklab.luau +93 -0
  22. package/out/mod/color/sRGB.luau +71 -0
  23. package/out/mod/common/bezier.luau +372 -0
  24. package/out/mod/common/flipbook.luau +102 -0
  25. package/out/mod/lerp.luau +210 -0
  26. package/out/mod/logger.luau +20 -0
  27. package/out/mod/shape.luau +207 -0
  28. package/out/mod/tween.luau +161 -0
  29. package/out/mod/utility.luau +707 -0
  30. package/out/obj/Bezier.luau +268 -0
  31. package/out/obj/ObjectCache.luau +289 -0
  32. package/out/services/caches.luau +62 -0
  33. package/out/services/effects.luau +234 -0
  34. package/out/services/enabled_effects.luau +120 -0
  35. package/out/services/texture_loader.luau +174 -0
  36. package/out/tsconfig.tsbuildinfo +1 -0
  37. package/out/types.luau +43 -0
  38. package/package.json +63 -0
@@ -0,0 +1,207 @@
1
+ --!native
2
+ --!optimize 2
3
+ local utility = require("@mod/utility")
4
+
5
+ local shape = {}
6
+
7
+ function shape.getSurfaceCFrame(cf: CFrame, n: Vector3, pos: Vector3)
8
+ local up = math.abs(n:Dot(Vector3.yAxis)) > 0.99 and Vector3.zAxis or Vector3.yAxis
9
+ local rot = CFrame.lookAt(Vector3.zero, n, up)
10
+ return cf * CFrame.new(pos) * rot
11
+ end
12
+
13
+ function shape.getPointWithinBox(seed: number, cframe: CFrame, size: Vector3, normal: Enum.NormalId)
14
+ debug.profilebegin("getPointWithinBox")
15
+
16
+ local rng = Random.new(seed)
17
+
18
+ local half = size / 2
19
+
20
+ -- stylua: ignore
21
+ local pos = Vector3.new(
22
+ rng:NextNumber(-1, 1),
23
+ rng:NextNumber(-1, 1),
24
+ rng:NextNumber(-1, 1)
25
+ ) * half
26
+
27
+ local cf = shape.getSurfaceCFrame(cframe, Vector3.FromNormalId(normal), pos)
28
+
29
+ debug.profileend()
30
+
31
+ return cf
32
+ end
33
+
34
+ function shape.getPointOnBox(seed: number, cframe: CFrame, size: Vector3, normal: Enum.NormalId)
35
+ debug.profilebegin("getPointOnBox")
36
+
37
+ local rng = Random.new(seed)
38
+
39
+ local n = Vector3.FromNormalId(normal)
40
+
41
+ local half = size / 2
42
+ local axes = Vector3.one - n:Abs()
43
+
44
+ -- stylua: ignore
45
+ local s = Vector3.new(
46
+ rng:NextNumber(-1, 1),
47
+ rng:NextNumber(-1, 1),
48
+ rng:NextNumber(-1, 1)
49
+ ) * half * axes
50
+
51
+ local cf = shape.getSurfaceCFrame(cframe, n, s + n * half)
52
+
53
+ debug.profileend()
54
+
55
+ return cf
56
+ end
57
+
58
+ function shape.getPointWithinCylinder(
59
+ seed: number,
60
+ min_radius: number,
61
+ partial: number,
62
+ cframe: CFrame,
63
+ size: Vector3,
64
+ normal: Enum.NormalId
65
+ )
66
+ debug.profilebegin("getPointWithinCylinder")
67
+
68
+ local rng = Random.new(seed)
69
+
70
+ local r = math.sqrt(rng:NextNumber(min_radius, 1))
71
+ local theta = rng:NextNumber(0, 2 * math.pi)
72
+
73
+ if normal == Enum.NormalId.Left or normal == Enum.NormalId.Right then
74
+ cframe *= CFrame.fromOrientation(0, math.pi / 2 * (normal == Enum.NormalId.Right and -1 or 1), 0)
75
+ size = Vector3.new(size.Z, size.Y, size.X)
76
+ elseif normal == Enum.NormalId.Front or normal == Enum.NormalId.Back then
77
+ cframe *= CFrame.fromOrientation(0, math.pi, 0)
78
+ end
79
+
80
+ local z = rng:NextNumber()
81
+ local t = 1 - z ^ utility.lerp(0.5, 1, math.sqrt(partial))
82
+
83
+ local width = utility.lerp(1, partial, t)
84
+
85
+ -- stylua: ignore
86
+ local pos = Vector3.new(
87
+ t * 2 - 1,
88
+ r * math.sin(theta) * width,
89
+ r * math.cos(theta) * width
90
+ ) * size / 2
91
+
92
+ -- stylua: ignore
93
+ local pos2 = Vector3.new(
94
+ 0,
95
+ math.sin(theta) * width,
96
+ math.cos(theta) * width
97
+ ) * size / 2
98
+
99
+ local tangent = Vector3.new(0, math.cos(theta) * width, -math.sin(theta) * width) * size / 2
100
+ local up = tangent.Magnitude > 0.001 and tangent.Unit or cframe.UpVector
101
+ local res = cframe * CFrame.new(pos) * CFrame.lookAt(Vector3.zero, pos2, up)
102
+
103
+ debug.profileend()
104
+
105
+ return res
106
+ end
107
+
108
+ function shape.getPointWithinSphere(
109
+ seed: number,
110
+ min_radius: number,
111
+ partial: number,
112
+ cframe: CFrame,
113
+ size: Vector3,
114
+ normal: Enum.NormalId
115
+ )
116
+ debug.profilebegin("getPointWithinSphere")
117
+
118
+ local rng = Random.new(seed)
119
+
120
+ local u = rng:NextNumber()
121
+ local v = rng:NextNumber()
122
+
123
+ local theta = u * 2 * math.pi
124
+ local phi = math.acos(2 * v - 1) * partial
125
+ local r = rng:NextNumber(min_radius, 1) ^ (1 / 3)
126
+
127
+ local sinTheta = math.sin(theta)
128
+ local cosTheta = math.cos(theta)
129
+ local sinPhi = math.sin(phi)
130
+ local cosPhi = math.cos(phi)
131
+
132
+ local n = Vector3.FromNormalId(normal)
133
+
134
+ if normal == Enum.NormalId.Left or normal == Enum.NormalId.Right then
135
+ size = Vector3.new(size.Z, size.Y, size.X)
136
+ elseif normal == Enum.NormalId.Top or normal == Enum.NormalId.Bottom then
137
+ size = Vector3.new(size.X, size.Z, size.Y)
138
+ end
139
+
140
+ local half = size / 2
141
+ local cf = shape.getSurfaceCFrame(cframe, n, Vector3.zero)
142
+
143
+ -- stylua: ignore
144
+ local pos = Vector3.new(
145
+ r * sinPhi * cosTheta,
146
+ r * sinPhi * sinTheta,
147
+ r * cosPhi
148
+ ) * half
149
+
150
+ local tangent = Vector3.new(-sinPhi * sinTheta, sinPhi * cosTheta, 0) * half
151
+
152
+ local up = if tangent.Magnitude > 0.001 then tangent.Unit else Vector3.new(1, 0, 0)
153
+ local res = cf * CFrame.Angles(0, math.pi, 0) * CFrame.new(pos) * CFrame.lookAt(Vector3.zero, pos, up)
154
+
155
+ debug.profileend()
156
+
157
+ return res
158
+ end
159
+
160
+ function shape.getPointWithinDisc(
161
+ seed: number,
162
+ min_depth: number,
163
+ partial: number,
164
+ cframe: CFrame,
165
+ size: Vector3,
166
+ normal: Enum.NormalId
167
+ )
168
+ debug.profilebegin("getPointWithinDisc")
169
+
170
+ local rng = Random.new(seed)
171
+
172
+ local n = Vector3.FromNormalId(normal)
173
+ local axes = Vector3.one - n:Abs() * min_depth
174
+
175
+ local half = size / 2
176
+
177
+ local z = rng:NextNumber(min_depth, 1)
178
+ local d = utility.lerp(1, 0.5, partial ^ 4)
179
+
180
+ local t = z
181
+
182
+ local r = rng:NextNumber(1 - partial, 1) ^ d
183
+ local theta = rng:NextNumber(0, 2 * math.pi)
184
+
185
+ -- stylua: ignore
186
+ local s = Vector3.new(
187
+ t * 2 - 1,
188
+ r * math.sin(theta),
189
+ r * math.cos(theta)
190
+ )
191
+
192
+ if normal == Enum.NormalId.Bottom or normal == Enum.NormalId.Top then
193
+ s = Vector3.new(s.Z, s.X, s.Y)
194
+ elseif normal == Enum.NormalId.Front or normal == Enum.NormalId.Back then
195
+ s = Vector3.new(s.Y, s.Z, s.X)
196
+ end
197
+
198
+ s *= half * axes
199
+
200
+ local cf = shape.getSurfaceCFrame(cframe, n, s + n * min_depth * half)
201
+
202
+ debug.profileend()
203
+
204
+ return cf
205
+ end
206
+
207
+ return shape
@@ -0,0 +1,161 @@
1
+ local RunService = game:GetService("RunService")
2
+
3
+ local logger = require("@mod/logger")
4
+ local utility = require("@mod/utility")
5
+
6
+ local Bezier = require("@obj/Bezier")
7
+
8
+ local tween = {}
9
+
10
+ tween.bezier_cache = {} :: { [string]: Bezier.Bezier }
11
+
12
+ function tween.fromParams(
13
+ params: string,
14
+ duration: number,
15
+ animator: (alpha: number, deltaTime: number, elapsed: number) -> number?,
16
+ awaitTween: RBXScriptConnection?,
17
+ onFinish: ((organic: boolean) -> ())?,
18
+ startAtZero: boolean?,
19
+ stepAtPriority: number?
20
+ )
21
+ local bezier = tween.bezier_cache[params]
22
+
23
+ if not bezier then
24
+ local success, points = pcall(function()
25
+ return utility.deserializePath(params)
26
+ end)
27
+
28
+ if not success then
29
+ logger.error(`failed to decode bezier path data with error: {points}`)
30
+ end
31
+
32
+ -- use 0 accuracy as it saves performance because there is no need to calculate the length
33
+ bezier = Bezier.new(points, 0)
34
+ tween.bezier_cache[params] = bezier
35
+ end
36
+
37
+ local elapsed = 0
38
+
39
+ local cleanupStepper
40
+
41
+ local function step(deltaTime)
42
+ -- roblox tweens apparently don't start from alpha=0
43
+ if not startAtZero and elapsed == 0 then
44
+ elapsed = math.clamp(elapsed + deltaTime, 0, math.max(duration, 0))
45
+ end
46
+
47
+ local t = math.clamp(elapsed / duration, 0, 1)
48
+ local alpha = 1 - bezier:getEase(t).y
49
+
50
+ local result = animator(alpha, deltaTime, elapsed)
51
+
52
+ if
53
+ (result == nil or (if duration ~= 0 then elapsed >= duration else elapsed > duration))
54
+ and (not awaitTween or not awaitTween.Connected)
55
+ then
56
+ cleanupStepper()
57
+
58
+ if onFinish then
59
+ onFinish(true)
60
+ end
61
+
62
+ return
63
+ end
64
+
65
+ if result then
66
+ elapsed = math.clamp(elapsed + result, 0, math.max(duration, 0.001))
67
+ end
68
+ end
69
+
70
+ if not stepAtPriority then
71
+ local connection: RBXScriptConnection
72
+ connection = RunService.RenderStepped:Connect(step)
73
+
74
+ cleanupStepper = function()
75
+ connection:Disconnect()
76
+ end
77
+
78
+ return connection
79
+ else
80
+ local id = utility.getRandomId()
81
+
82
+ RunService:BindToRenderStep(id, stepAtPriority, step)
83
+
84
+ local bound = true
85
+
86
+ cleanupStepper = function()
87
+ if not bound then
88
+ return
89
+ end
90
+
91
+ bound = false
92
+
93
+ RunService:UnbindFromRenderStep(id)
94
+ end
95
+
96
+ return cleanupStepper
97
+ end
98
+ end
99
+
100
+ function tween.timer(
101
+ duration: number,
102
+ counter: (deltaTime: number, elapsed: number) -> number,
103
+ awaitTween: RBXScriptConnection?,
104
+ scope: {}?,
105
+ stepAtPriority: number?
106
+ )
107
+ local main = coroutine.running()
108
+
109
+ local elapsed = 0
110
+
111
+ local cleanupStepper
112
+
113
+ local function step(deltaTime)
114
+ local result = counter(deltaTime, elapsed)
115
+
116
+ if
117
+ (result == nil or (if duration ~= 0 then elapsed >= duration else elapsed > duration))
118
+ and (not awaitTween or not awaitTween.Connected)
119
+ then
120
+ cleanupStepper()
121
+ task.spawn(main)
122
+ return
123
+ end
124
+
125
+ if result then
126
+ elapsed = math.clamp(elapsed + result, 0, math.max(duration, 0.001))
127
+ end
128
+ end
129
+
130
+ if not stepAtPriority then
131
+ local connection = RunService.RenderStepped:Connect(step)
132
+
133
+ cleanupStepper = function()
134
+ connection:Disconnect()
135
+ end
136
+ else
137
+ local id = utility.getRandomId()
138
+
139
+ RunService:BindToRenderStep(id, stepAtPriority, step)
140
+
141
+ local bound = true
142
+
143
+ cleanupStepper = function()
144
+ if not bound then
145
+ return
146
+ end
147
+
148
+ bound = false
149
+
150
+ RunService:UnbindFromRenderStep(id)
151
+ end
152
+ end
153
+
154
+ if scope then
155
+ table.insert(scope, cleanupStepper)
156
+ end
157
+
158
+ coroutine.yield()
159
+ end
160
+
161
+ return tween