@rbxts/vfx-forge 2.2.2-ts.1
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/LICENSE +82 -0
- package/README.md +39 -0
- package/out/forge-vfx/effects/beam.luau +312 -0
- package/out/forge-vfx/effects/bezier.luau +392 -0
- package/out/forge-vfx/effects/camera_shake.luau +200 -0
- package/out/forge-vfx/effects/lightning.luau +1183 -0
- package/out/forge-vfx/effects/mesh.luau +466 -0
- package/out/forge-vfx/effects/particle.luau +64 -0
- package/out/forge-vfx/effects/randomizer.luau +110 -0
- package/out/forge-vfx/effects/screen.luau +61 -0
- package/out/forge-vfx/effects/shockwave_debris.luau +277 -0
- package/out/forge-vfx/effects/shockwave_line.luau +356 -0
- package/out/forge-vfx/effects/shockwave_ring.luau +252 -0
- package/out/forge-vfx/effects/sound.luau +311 -0
- package/out/forge-vfx/effects/spin.luau +88 -0
- package/out/forge-vfx/effects/tweener.luau +122 -0
- package/out/forge-vfx/emitters.luau +387 -0
- package/out/forge-vfx/index.d.ts +356 -0
- package/out/forge-vfx/init.luau +279 -0
- package/out/forge-vfx/mod/attributes.luau +227 -0
- package/out/forge-vfx/mod/color/Oklab.luau +93 -0
- package/out/forge-vfx/mod/color/sRGB.luau +71 -0
- package/out/forge-vfx/mod/common/bezier.luau +372 -0
- package/out/forge-vfx/mod/common/flipbook.luau +102 -0
- package/out/forge-vfx/mod/lerp.luau +210 -0
- package/out/forge-vfx/mod/logger.luau +20 -0
- package/out/forge-vfx/mod/shape.luau +207 -0
- package/out/forge-vfx/mod/tween.luau +161 -0
- package/out/forge-vfx/mod/utility.luau +707 -0
- package/out/forge-vfx/obj/Bezier.luau +268 -0
- package/out/forge-vfx/obj/ObjectCache.luau +289 -0
- package/out/forge-vfx/services/caches.luau +62 -0
- package/out/forge-vfx/services/effects.luau +234 -0
- package/out/forge-vfx/services/enabled_effects.luau +120 -0
- package/out/forge-vfx/services/texture_loader.luau +174 -0
- package/out/forge-vfx/types.luau +43 -0
- package/out/index.d.ts +3 -0
- package/out/init.luau +5 -0
- package/out/shake.d.ts +2 -0
- package/out/shake.luau +6 -0
- package/out/tsconfig.tsbuildinfo +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1,466 @@
|
|
|
1
|
+
local TS = _G[script.Parent.Parent.Parent]
|
|
2
|
+
--!nolint LocalShadow
|
|
3
|
+
local RunService = game:GetService("RunService")
|
|
4
|
+
|
|
5
|
+
local attr = require(script.Parent.Parent.mod.attributes)
|
|
6
|
+
local tween = require(script.Parent.Parent.mod.tween)
|
|
7
|
+
local types = require(script.Parent.Parent.types)
|
|
8
|
+
local utility = require(script.Parent.Parent.mod.utility)
|
|
9
|
+
local flipbook_common = require(script.Parent.Parent.mod.common.flipbook)
|
|
10
|
+
|
|
11
|
+
local Oklab = require(script.Parent.Parent.mod.color.Oklab)
|
|
12
|
+
|
|
13
|
+
local rng = Random.new()
|
|
14
|
+
|
|
15
|
+
local mesh = {}
|
|
16
|
+
|
|
17
|
+
function mesh.emit(ref: Model, obj: BasePart, scope: types.scope, scale: number, mustEmit: boolean?)
|
|
18
|
+
local start = ref:FindFirstChild("Start")
|
|
19
|
+
local goal = ref:FindFirstChild("End")
|
|
20
|
+
|
|
21
|
+
if
|
|
22
|
+
not start
|
|
23
|
+
or not goal
|
|
24
|
+
or not start:IsA("BasePart")
|
|
25
|
+
or not goal:IsA("BasePart")
|
|
26
|
+
or (ref:GetAttribute("Enabled") and not mustEmit)
|
|
27
|
+
then
|
|
28
|
+
return
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
local legacy_duration = attr.get(ref, "Duration", 1, true)
|
|
32
|
+
|
|
33
|
+
local durationRange = attr.getRange(
|
|
34
|
+
ref,
|
|
35
|
+
"EffectDuration",
|
|
36
|
+
NumberRange.new(legacy_duration, legacy_duration),
|
|
37
|
+
NumberRange.new(0, math.huge)
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
local duration = rng:NextNumber(durationRange.Min, durationRange.Max)
|
|
41
|
+
|
|
42
|
+
local emitDelay = attr.get(ref, "EmitDelay", 0)
|
|
43
|
+
local destroyDelay = attr.get(ref, "DestroyDelay", 0)
|
|
44
|
+
local emitDuration = attr.get(ref, "EmitDuration", 0)
|
|
45
|
+
|
|
46
|
+
local legacy_isFlipbook = attr.get(ref, "Flipbook", false, true)
|
|
47
|
+
local legacy_flipbookFadeOffset = attr.get(ref, "FlipbookFadeOffset", 0, true)
|
|
48
|
+
|
|
49
|
+
-- stone age compatibility
|
|
50
|
+
do
|
|
51
|
+
local prefix
|
|
52
|
+
|
|
53
|
+
if legacy_isFlipbook or not start:FindFirstChildOfClass("Decal") then
|
|
54
|
+
prefix = "Mesh_"
|
|
55
|
+
else
|
|
56
|
+
prefix = "Decal_"
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
local ts = ref:GetAttribute("StartTransparency")
|
|
60
|
+
|
|
61
|
+
if ts ~= nil then
|
|
62
|
+
ref:SetAttribute(prefix .. "StartTransparency", ts)
|
|
63
|
+
ref:SetAttribute("StartTransparency", nil)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
local te = ref:GetAttribute("EndTransparency")
|
|
67
|
+
|
|
68
|
+
if te ~= nil then
|
|
69
|
+
ref:SetAttribute(prefix .. "EndTransparency", te)
|
|
70
|
+
ref:SetAttribute("EndTransparency", nil)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
local useEmitDuration = ref:GetAttribute("Enabled") ~= nil and ref:HasTag(utility.ENABLED_VFX_TAG) and duration > 0
|
|
75
|
+
|
|
76
|
+
local legacy_decalST = attr.get(ref, "Decal_StartTransparency", 0, true)
|
|
77
|
+
local legacy_decalET = attr.get(ref, "Decal_EndTransparency", 0, true)
|
|
78
|
+
|
|
79
|
+
local partDefaultTp = 0
|
|
80
|
+
|
|
81
|
+
do
|
|
82
|
+
local decal = start and start:FindFirstChildOfClass("Decal")
|
|
83
|
+
|
|
84
|
+
if decal then
|
|
85
|
+
partDefaultTp = 1
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
local legacy_meshST = attr.get(ref, "Mesh_StartTransparency", partDefaultTp, true)
|
|
90
|
+
local legacy_meshET = attr.get(ref, "Mesh_EndTransparency", partDefaultTp, true)
|
|
91
|
+
|
|
92
|
+
local sync = attr.get(ref, "SyncPosition", false)
|
|
93
|
+
|
|
94
|
+
local speedStart = attr.get(ref, "Speed_Start", 1)
|
|
95
|
+
local speedEnd = attr.get(ref, "Speed_End", 1)
|
|
96
|
+
|
|
97
|
+
local tpStart = attr.get(ref, "Part_Transparency_Start", legacy_meshST)
|
|
98
|
+
local tpEnd = attr.get(ref, "Part_Transparency_End", legacy_meshET)
|
|
99
|
+
|
|
100
|
+
local spreadAngle = attr.get(ref, "SpreadAngle", vector.zero)
|
|
101
|
+
|
|
102
|
+
local rotSpeedStartRange = attr.getRange(ref, "Part_RotSpeed_Start", NumberRange.new(0, 0))
|
|
103
|
+
local rotSpeedEndRange = attr.getRange(ref, "Part_RotSpeed_End", NumberRange.new(0, 0))
|
|
104
|
+
|
|
105
|
+
local rotAroundOrigin = attr.get(ref, "RotAroundOrigin", false)
|
|
106
|
+
|
|
107
|
+
local minInitRot = attr.get(ref, "MinInitRot", vector.zero)
|
|
108
|
+
local maxInitRot = attr.get(ref, "MaxInitRot", vector.zero)
|
|
109
|
+
|
|
110
|
+
local rotSpeedStart = rng:NextNumber(rotSpeedStartRange.Min, rotSpeedStartRange.Max)
|
|
111
|
+
local rotSpeedEnd = rng:NextNumber(rotSpeedEndRange.Min, rotSpeedEndRange.Max)
|
|
112
|
+
|
|
113
|
+
local initRot = vector.create(
|
|
114
|
+
rng:NextNumber(minInitRot.x, maxInitRot.x),
|
|
115
|
+
rng:NextNumber(minInitRot.y, maxInitRot.y),
|
|
116
|
+
rng:NextNumber(minInitRot.z, maxInitRot.z)
|
|
117
|
+
) * utility.DEG_TO_RAD
|
|
118
|
+
|
|
119
|
+
task.wait(emitDelay)
|
|
120
|
+
|
|
121
|
+
if useEmitDuration and not mustEmit then
|
|
122
|
+
attr.trigger(ref, "Enabled", true)
|
|
123
|
+
|
|
124
|
+
if speedStart ~= speedEnd then
|
|
125
|
+
attr.setState(ref, "SpeedTweening", true)
|
|
126
|
+
|
|
127
|
+
table.insert(
|
|
128
|
+
scope,
|
|
129
|
+
tween.fromParams(
|
|
130
|
+
attr.get(ref, "Speed_Curve", utility.default_bezier),
|
|
131
|
+
attr.get(ref, "Speed_Duration", 0.1),
|
|
132
|
+
function(alpha, deltaTime)
|
|
133
|
+
attr.setState(ref, "SpeedOverride", utility.lerp(speedStart, speedEnd, alpha))
|
|
134
|
+
return deltaTime
|
|
135
|
+
end,
|
|
136
|
+
nil,
|
|
137
|
+
function()
|
|
138
|
+
attr.setState(ref, "SpeedTweening", nil)
|
|
139
|
+
end
|
|
140
|
+
)
|
|
141
|
+
)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
task.wait(emitDuration)
|
|
145
|
+
|
|
146
|
+
attr.trigger(ref, "Enabled", false)
|
|
147
|
+
attr.clearState(ref)
|
|
148
|
+
|
|
149
|
+
return
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
local parent = ref:FindFirstAncestorOfClass("Attachment") or start
|
|
153
|
+
local realObj = typeof(obj) == "table" and obj._getReal() or obj
|
|
154
|
+
|
|
155
|
+
local origin = utility.getTransformedOriginExtents(parent)
|
|
156
|
+
local goalCFrameOffset = start.CFrame:ToObjectSpace(goal.CFrame)
|
|
157
|
+
|
|
158
|
+
local currentSpeed = speedStart
|
|
159
|
+
local currentRotSpeed = rotSpeedStart
|
|
160
|
+
|
|
161
|
+
local currentRot = CFrame.fromOrientation(initRot.x, initRot.y, initRot.z)
|
|
162
|
+
local currentCFrame = CFrame.identity
|
|
163
|
+
|
|
164
|
+
local spread = CFrame.fromOrientation(
|
|
165
|
+
math.rad(rng:NextNumber(-spreadAngle.x, spreadAngle.x)),
|
|
166
|
+
math.rad(rng:NextNumber(-spreadAngle.y, spreadAngle.y)),
|
|
167
|
+
0
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
local function updatePos(deltaTime: number)
|
|
171
|
+
local o = sync and utility.getTransformedOriginExtents(parent) or origin
|
|
172
|
+
local add = initRot:Sign() * currentRotSpeed * deltaTime
|
|
173
|
+
|
|
174
|
+
currentRot *= CFrame.fromOrientation(add.x, add.y, add.z)
|
|
175
|
+
|
|
176
|
+
local cf
|
|
177
|
+
|
|
178
|
+
if rotAroundOrigin then
|
|
179
|
+
cf = o * spread * currentRot * currentCFrame
|
|
180
|
+
else
|
|
181
|
+
cf = o * spread * currentCFrame * currentRot
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
cf *= currentRot
|
|
185
|
+
|
|
186
|
+
obj.CFrame = cf
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
updatePos(0)
|
|
190
|
+
|
|
191
|
+
do
|
|
192
|
+
local id = utility.getRandomId()
|
|
193
|
+
|
|
194
|
+
RunService:BindToRenderStep(id, utility.RENDER_PRIORITY + scope.depth, updatePos)
|
|
195
|
+
|
|
196
|
+
table.insert(scope, function()
|
|
197
|
+
RunService:UnbindFromRenderStep(id)
|
|
198
|
+
end)
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
local promises = {}
|
|
202
|
+
|
|
203
|
+
local emitOnFinish = scope.effects.prepareEmitOnFinish(obj, scope)
|
|
204
|
+
|
|
205
|
+
local env = scope.effects.emitNested(obj, scope.depth + 1)
|
|
206
|
+
table.insert(promises, env.Finished)
|
|
207
|
+
|
|
208
|
+
local speedTween
|
|
209
|
+
|
|
210
|
+
if speedStart ~= speedEnd and not attr.getState(ref, "SpeedOverride", nil) then
|
|
211
|
+
speedTween = tween.fromParams(
|
|
212
|
+
attr.get(ref, "Speed_Curve", utility.default_bezier),
|
|
213
|
+
attr.get(ref, "Speed_Duration", 0.1),
|
|
214
|
+
function(alpha, deltaTime)
|
|
215
|
+
currentSpeed = utility.lerp(speedStart, speedEnd, alpha)
|
|
216
|
+
return deltaTime
|
|
217
|
+
end
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
table.insert(scope, speedTween)
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
if goalCFrameOffset ~= CFrame.identity then
|
|
224
|
+
table.insert(
|
|
225
|
+
scope,
|
|
226
|
+
tween.fromParams(attr.get(ref, "Part_CFrame_Curve", utility.default_bezier), duration, function(alpha, deltaTime)
|
|
227
|
+
currentCFrame = CFrame.identity:Lerp(goalCFrameOffset, alpha)
|
|
228
|
+
return deltaTime * (attr.getState(ref, "SpeedOverride", currentSpeed))
|
|
229
|
+
end, speedTween)
|
|
230
|
+
)
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
if rotSpeedStart ~= rotSpeedEnd then
|
|
234
|
+
table.insert(
|
|
235
|
+
scope,
|
|
236
|
+
tween.fromParams(
|
|
237
|
+
attr.get(ref, "Part_RotSpeed_Curve", utility.default_bezier),
|
|
238
|
+
duration,
|
|
239
|
+
function(alpha, deltaTime)
|
|
240
|
+
currentRotSpeed = utility.lerp(rotSpeedStart, rotSpeedEnd, alpha)
|
|
241
|
+
return deltaTime * (attr.getState(ref, "SpeedOverride", currentSpeed))
|
|
242
|
+
end,
|
|
243
|
+
speedTween
|
|
244
|
+
)
|
|
245
|
+
)
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
if tpStart ~= tpEnd then
|
|
249
|
+
table.insert(
|
|
250
|
+
scope,
|
|
251
|
+
tween.fromParams(
|
|
252
|
+
attr.get(ref, "Part_Transparency_Curve", utility.default_bezier),
|
|
253
|
+
duration,
|
|
254
|
+
function(alpha, deltaTime)
|
|
255
|
+
obj.Transparency = utility.lerp(tpStart, tpEnd, alpha)
|
|
256
|
+
return deltaTime * (attr.getState(ref, "SpeedOverride", currentSpeed))
|
|
257
|
+
end,
|
|
258
|
+
speedTween
|
|
259
|
+
)
|
|
260
|
+
)
|
|
261
|
+
else
|
|
262
|
+
obj.Transparency = tpStart
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
local sizeStart, sizeEnd = start.Size * scale, goal.Size * scale
|
|
266
|
+
|
|
267
|
+
if sizeStart ~= sizeEnd then
|
|
268
|
+
local lastSizeAlpha = -1
|
|
269
|
+
|
|
270
|
+
table.insert(
|
|
271
|
+
scope,
|
|
272
|
+
tween.fromParams(attr.get(ref, "Part_Size_Curve", utility.default_bezier), duration, function(alpha, deltaTime)
|
|
273
|
+
local speed = attr.getState(ref, "SpeedOverride", currentSpeed)
|
|
274
|
+
|
|
275
|
+
-- reduce size writes
|
|
276
|
+
if math.abs(alpha - lastSizeAlpha) < 0.005 then
|
|
277
|
+
return deltaTime * speed
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
lastSizeAlpha = alpha
|
|
281
|
+
obj.Size = sizeStart:Lerp(sizeEnd, alpha)
|
|
282
|
+
|
|
283
|
+
return deltaTime * speed
|
|
284
|
+
end, speedTween)
|
|
285
|
+
)
|
|
286
|
+
else
|
|
287
|
+
obj.Size = sizeStart
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
local startMesh = start:FindFirstChildOfClass("SpecialMesh")
|
|
291
|
+
local goalMesh = goal:FindFirstChildOfClass("SpecialMesh")
|
|
292
|
+
|
|
293
|
+
local objMesh = obj:FindFirstChildOfClass("SpecialMesh")
|
|
294
|
+
|
|
295
|
+
if objMesh then
|
|
296
|
+
if startMesh and goalMesh then
|
|
297
|
+
local scaleStart, scaleEnd = startMesh.Scale * scale, goalMesh.Scale * scale
|
|
298
|
+
|
|
299
|
+
if scaleStart ~= scaleEnd then
|
|
300
|
+
table.insert(
|
|
301
|
+
scope,
|
|
302
|
+
tween.fromParams(
|
|
303
|
+
attr.get(ref, "Mesh_Scale_Curve", utility.default_bezier),
|
|
304
|
+
duration,
|
|
305
|
+
function(alpha, deltaTime)
|
|
306
|
+
objMesh.Scale = utility.lerp(scaleStart, scaleEnd, alpha)
|
|
307
|
+
return deltaTime * (attr.getState(ref, "SpeedOverride", currentSpeed))
|
|
308
|
+
end,
|
|
309
|
+
speedTween
|
|
310
|
+
)
|
|
311
|
+
)
|
|
312
|
+
end
|
|
313
|
+
else
|
|
314
|
+
objMesh.Parent = nil
|
|
315
|
+
|
|
316
|
+
table.insert(scope, function()
|
|
317
|
+
objMesh.Parent = realObj
|
|
318
|
+
end)
|
|
319
|
+
end
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
local decals, flipbooks, fromToMap = utility.getMeshDecals(ref, obj)
|
|
323
|
+
|
|
324
|
+
local longestFlipbookDuration = 0
|
|
325
|
+
|
|
326
|
+
if legacy_isFlipbook then
|
|
327
|
+
table.sort(decals, function(a, b)
|
|
328
|
+
local x = a.Name:match("%d+") or 0
|
|
329
|
+
local y = b.Name:match("%d+") or 0
|
|
330
|
+
|
|
331
|
+
return tonumber(x) < tonumber(y)
|
|
332
|
+
end)
|
|
333
|
+
|
|
334
|
+
local displayDecal = Instance.new("Decal")
|
|
335
|
+
displayDecal.Parent = realObj
|
|
336
|
+
|
|
337
|
+
table.insert(scope, displayDecal)
|
|
338
|
+
|
|
339
|
+
if legacy_flipbookFadeOffset > 0 then
|
|
340
|
+
if legacy_decalST ~= legacy_decalET then
|
|
341
|
+
table.insert(
|
|
342
|
+
scope,
|
|
343
|
+
tween.fromParams(utility.default_bezier, duration + legacy_flipbookFadeOffset, function(alpha, deltaTime)
|
|
344
|
+
displayDecal.Transparency = utility.lerp(legacy_decalST, legacy_decalET, alpha)
|
|
345
|
+
return deltaTime * (attr.getState(ref, "SpeedOverride", currentSpeed))
|
|
346
|
+
end, speedTween)
|
|
347
|
+
)
|
|
348
|
+
end
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
table.insert(
|
|
352
|
+
scope,
|
|
353
|
+
tween.fromParams(utility.default_bezier, duration, function(alpha, deltaTime)
|
|
354
|
+
local index = math.max(math.round(#decals * alpha), 1)
|
|
355
|
+
local target = decals[index]
|
|
356
|
+
|
|
357
|
+
displayDecal.Texture = target.Texture
|
|
358
|
+
|
|
359
|
+
displayDecal.Color3 = target.Color3
|
|
360
|
+
displayDecal.ZIndex = target.ZIndex
|
|
361
|
+
|
|
362
|
+
if legacy_flipbookFadeOffset == 0 then
|
|
363
|
+
displayDecal.Transparency = utility.lerp(legacy_decalST, legacy_decalET, alpha)
|
|
364
|
+
displayDecal.ZIndex = target.ZIndex
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
return deltaTime * (attr.getState(ref, "SpeedOverride", currentSpeed))
|
|
368
|
+
end, speedTween)
|
|
369
|
+
)
|
|
370
|
+
else
|
|
371
|
+
for _, decal in decals do
|
|
372
|
+
local from = decal
|
|
373
|
+
local to = fromToMap[from]
|
|
374
|
+
|
|
375
|
+
local decal_tpStart = attr.get(from, "Transparency_Start", legacy_decalST)
|
|
376
|
+
local decal_tpEnd = attr.get(from, "Transparency_End", legacy_decalET)
|
|
377
|
+
|
|
378
|
+
if decal_tpStart ~= decal_tpEnd then
|
|
379
|
+
table.insert(
|
|
380
|
+
scope,
|
|
381
|
+
tween.fromParams(
|
|
382
|
+
attr.get(from, "Transparency_Curve", utility.default_bezier),
|
|
383
|
+
duration,
|
|
384
|
+
function(alpha, deltaTime)
|
|
385
|
+
decal.Transparency = utility.lerp(decal_tpStart, decal_tpEnd, alpha)
|
|
386
|
+
return deltaTime * (attr.getState(ref, "SpeedOverride", currentSpeed))
|
|
387
|
+
end,
|
|
388
|
+
speedTween
|
|
389
|
+
)
|
|
390
|
+
)
|
|
391
|
+
else
|
|
392
|
+
decal.Transparency = decal_tpStart
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
if from.Color3 ~= to.Color3 then
|
|
396
|
+
table.insert(
|
|
397
|
+
scope,
|
|
398
|
+
tween.fromParams(attr.get(from, "Color_Curve", utility.default_bezier), duration, function(alpha, deltaTime)
|
|
399
|
+
local a = Oklab.fromSRGB(from.Color3)
|
|
400
|
+
local b = Oklab.fromSRGB(to.Color3)
|
|
401
|
+
|
|
402
|
+
decal.Color3 = Oklab.toSRGB(a:Lerp(b, alpha), true)
|
|
403
|
+
|
|
404
|
+
return deltaTime * (attr.getState(ref, "SpeedOverride", currentSpeed))
|
|
405
|
+
end, speedTween)
|
|
406
|
+
)
|
|
407
|
+
end
|
|
408
|
+
|
|
409
|
+
local flipbook = flipbooks[from]
|
|
410
|
+
|
|
411
|
+
if flipbook then
|
|
412
|
+
local config = {
|
|
413
|
+
ref = from,
|
|
414
|
+
frames = flipbook,
|
|
415
|
+
speedTween = speedTween,
|
|
416
|
+
effectDuration = duration,
|
|
417
|
+
|
|
418
|
+
curve = attr.get(from, "Flipbook_Change_Curve", utility.linear_bezier),
|
|
419
|
+
duration = attr.get(from, "Flipbook_Change_Duration", duration),
|
|
420
|
+
|
|
421
|
+
getSpeed = function()
|
|
422
|
+
return attr.getState(ref, "SpeedOverride", currentSpeed)
|
|
423
|
+
end,
|
|
424
|
+
|
|
425
|
+
setTexture = function(texture)
|
|
426
|
+
decal.Texture = texture
|
|
427
|
+
end,
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
local changeDuration = flipbook_common.getChangeDuration(config)
|
|
431
|
+
|
|
432
|
+
if changeDuration > longestFlipbookDuration then
|
|
433
|
+
longestFlipbookDuration = changeDuration
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
table.insert(
|
|
437
|
+
scope,
|
|
438
|
+
tween.fromParams(config.curve, changeDuration, flipbook_common.createUpdateCallback(config), speedTween)
|
|
439
|
+
)
|
|
440
|
+
end
|
|
441
|
+
end
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
tween.timer(
|
|
445
|
+
math.max(duration, longestFlipbookDuration) + legacy_flipbookFadeOffset + destroyDelay,
|
|
446
|
+
function(deltaTime, elapsed)
|
|
447
|
+
local speed = attr.getState(ref, "SpeedOverride", currentSpeed)
|
|
448
|
+
|
|
449
|
+
currentSpeed = speed
|
|
450
|
+
|
|
451
|
+
return if speed > 0
|
|
452
|
+
or (elapsed > 0 and if speedTween then speedTween.Connected else attr.getState(ref, "SpeedTweening", false))
|
|
453
|
+
then deltaTime * speed
|
|
454
|
+
else nil
|
|
455
|
+
end,
|
|
456
|
+
speedTween,
|
|
457
|
+
scope
|
|
458
|
+
)
|
|
459
|
+
|
|
460
|
+
TS.Promise.all(promises):await()
|
|
461
|
+
|
|
462
|
+
local env = scope.effects.emitOnFinish(emitOnFinish, realObj, scope.depth + 1)
|
|
463
|
+
env.Finished:await()
|
|
464
|
+
end
|
|
465
|
+
|
|
466
|
+
return mesh
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
local attr = require(script.Parent.Parent.mod.attributes)
|
|
2
|
+
local tween = require(script.Parent.Parent.mod.tween)
|
|
3
|
+
local types = require(script.Parent.Parent.types)
|
|
4
|
+
local utility = require(script.Parent.Parent.mod.utility)
|
|
5
|
+
|
|
6
|
+
local particle = {}
|
|
7
|
+
|
|
8
|
+
function particle.emit(ref: ParticleEmitter, obj: ParticleEmitter, scope: types.scope)
|
|
9
|
+
if ref.Enabled then
|
|
10
|
+
ref.Enabled = false
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
local delay = attr.get(ref, "EmitDelay", 0)
|
|
14
|
+
local count = attr.get(ref, "EmitCount", 1)
|
|
15
|
+
local duration = attr.get(ref, "EmitDuration", 0)
|
|
16
|
+
|
|
17
|
+
local useDuration = duration > 0
|
|
18
|
+
|
|
19
|
+
task.wait(delay)
|
|
20
|
+
|
|
21
|
+
if useDuration then
|
|
22
|
+
obj.Enabled = true
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
local timeScaleDuration = attr.get(ref, "TimeScale_Duration", 0.1)
|
|
26
|
+
|
|
27
|
+
local timeScaleStart = attr.get(ref, "TimeScale_Start", obj.TimeScale, true)
|
|
28
|
+
local timeScaleEnd = attr.get(ref, "TimeScale_End", obj.TimeScale, true)
|
|
29
|
+
|
|
30
|
+
local speedTween
|
|
31
|
+
|
|
32
|
+
if timeScaleStart ~= timeScaleEnd then
|
|
33
|
+
speedTween = tween.fromParams(
|
|
34
|
+
attr.get(ref, "TimeScale_Curve", utility.default_bezier),
|
|
35
|
+
timeScaleDuration,
|
|
36
|
+
function(alpha, deltaTime)
|
|
37
|
+
local speed = utility.lerp(timeScaleStart, timeScaleEnd, math.clamp(alpha, 0, 1))
|
|
38
|
+
|
|
39
|
+
obj.TimeScale = speed
|
|
40
|
+
|
|
41
|
+
return deltaTime
|
|
42
|
+
end
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
table.insert(scope, speedTween)
|
|
46
|
+
elseif timeScaleStart ~= obj.TimeScale then
|
|
47
|
+
obj.TimeScale = timeScaleStart
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
obj:Emit(count)
|
|
51
|
+
|
|
52
|
+
if useDuration then
|
|
53
|
+
task.wait(duration)
|
|
54
|
+
obj.Enabled = false
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
tween.timer(ref.Lifetime.Max, function(deltaTime, elapsed)
|
|
58
|
+
return if ref.TimeScale > 0 or (elapsed > 0 and speedTween and speedTween.Connected)
|
|
59
|
+
then deltaTime * ref.TimeScale
|
|
60
|
+
else nil
|
|
61
|
+
end, speedTween, scope)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
return particle
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
local attr = require(script.Parent.Parent.mod.attributes)
|
|
2
|
+
|
|
3
|
+
local lerp = require(script.Parent.Parent.mod.lerp)
|
|
4
|
+
local tween = require(script.Parent.Parent.mod.tween)
|
|
5
|
+
local types = require(script.Parent.Parent.types)
|
|
6
|
+
local utility = require(script.Parent.Parent.mod.utility)
|
|
7
|
+
|
|
8
|
+
local Bezier = require(script.Parent.Parent.obj.Bezier)
|
|
9
|
+
|
|
10
|
+
local rng = Random.new()
|
|
11
|
+
|
|
12
|
+
local randomizer = {}
|
|
13
|
+
|
|
14
|
+
local function getBezier(params: string): Bezier.Bezier?
|
|
15
|
+
local bezier = tween.bezier_cache[params]
|
|
16
|
+
|
|
17
|
+
if not bezier then
|
|
18
|
+
local success, points = pcall(function()
|
|
19
|
+
return utility.deserializePath(params)
|
|
20
|
+
end)
|
|
21
|
+
|
|
22
|
+
if not success then
|
|
23
|
+
return nil
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
bezier = Bezier.new(points, 0)
|
|
27
|
+
tween.bezier_cache[params] = bezier
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
return bezier
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
local function sampleWeighted(bezier: Bezier.Bezier): number
|
|
34
|
+
local t = rng:NextNumber()
|
|
35
|
+
local weight = 1 - bezier:getEase(t).y
|
|
36
|
+
|
|
37
|
+
return weight
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
function randomizer.emit(obj: RayValue, scope: types.scope, isAttribute: boolean)
|
|
41
|
+
local target = utility.getTarget(obj)
|
|
42
|
+
|
|
43
|
+
if not target then
|
|
44
|
+
return
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
local name = obj.Name
|
|
48
|
+
|
|
49
|
+
local startValue = attr.get(obj, "_START_VALUE", nil)
|
|
50
|
+
local endValue = attr.get(obj, "_END_VALUE", nil)
|
|
51
|
+
|
|
52
|
+
if startValue == nil or endValue == nil then
|
|
53
|
+
return
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
local typeName = typeof(startValue)
|
|
57
|
+
|
|
58
|
+
if typeName ~= typeof(endValue) then
|
|
59
|
+
return
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
local weightCurve = attr.get(obj, "Weight_Curve", utility.linear_bezier)
|
|
63
|
+
local bezier = getBezier(weightCurve)
|
|
64
|
+
|
|
65
|
+
if not bezier then
|
|
66
|
+
return
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
local originalValue
|
|
70
|
+
|
|
71
|
+
if isAttribute then
|
|
72
|
+
originalValue = attr.get(target, name, nil)
|
|
73
|
+
else
|
|
74
|
+
local ok, val = pcall(function()
|
|
75
|
+
return target[name]
|
|
76
|
+
end)
|
|
77
|
+
|
|
78
|
+
if not ok then
|
|
79
|
+
return
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
originalValue = val
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
local lfunc = lerp[typeName] or lerp.Other
|
|
86
|
+
|
|
87
|
+
local alpha = sampleWeighted(bezier)
|
|
88
|
+
local newValue = lfunc(startValue, endValue, alpha)
|
|
89
|
+
|
|
90
|
+
local resetOnFinish = attr.get(obj, "ResetOnFinish", true)
|
|
91
|
+
|
|
92
|
+
if isAttribute then
|
|
93
|
+
attr.set(target, name, newValue)
|
|
94
|
+
else
|
|
95
|
+
target[name] = newValue
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
if resetOnFinish then
|
|
99
|
+
-- reset on next frame (after the target effects are emitted)
|
|
100
|
+
task.defer(function()
|
|
101
|
+
if isAttribute then
|
|
102
|
+
attr.set(target, name, originalValue)
|
|
103
|
+
else
|
|
104
|
+
target[name] = originalValue
|
|
105
|
+
end
|
|
106
|
+
end)
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
return randomizer
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
local RunService = game:GetService("RunService")
|
|
2
|
+
|
|
3
|
+
local attr = require(script.Parent.Parent.mod.attributes)
|
|
4
|
+
local types = require(script.Parent.Parent.types)
|
|
5
|
+
local utility = require(script.Parent.Parent.mod.utility)
|
|
6
|
+
|
|
7
|
+
local screen = {}
|
|
8
|
+
|
|
9
|
+
function screen.emit(ref: BasePart, scope: types.scope)
|
|
10
|
+
if not ref:GetAttribute("Enabled") then
|
|
11
|
+
return
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
local scale = attr.get(ref, "PartScale", vector.one)
|
|
15
|
+
local distance = attr.get(ref, "PartDistance", 1.5)
|
|
16
|
+
|
|
17
|
+
local pos = attr.get(ref, "OffsetPosition", vector.zero)
|
|
18
|
+
local rot = attr.get(ref, "OffsetRotation", vector.zero) * utility.DEG_TO_RAD
|
|
19
|
+
|
|
20
|
+
local originalCF = ref.CFrame
|
|
21
|
+
local originalSize = ref.Size
|
|
22
|
+
local originalColGroup = ref.CollisionGroup
|
|
23
|
+
|
|
24
|
+
ref.CollisionGroup = "ForgeMouseIgnore"
|
|
25
|
+
|
|
26
|
+
table.insert(scope, function()
|
|
27
|
+
ref.Size = originalSize
|
|
28
|
+
ref.CFrame = originalCF
|
|
29
|
+
ref.CollisionGroup = originalColGroup ~= "" and originalColGroup or "Default"
|
|
30
|
+
end)
|
|
31
|
+
|
|
32
|
+
-- crazy how BindToRenderStep will always run before RenderStepped in studio
|
|
33
|
+
local function frame()
|
|
34
|
+
local camera = workspace.CurrentCamera
|
|
35
|
+
|
|
36
|
+
local halfFovRad = math.rad(camera.FieldOfView / 2)
|
|
37
|
+
local height = math.tan(halfFovRad) * distance * 2
|
|
38
|
+
local width = (camera.ViewportSize.X / camera.ViewportSize.Y) * height
|
|
39
|
+
|
|
40
|
+
local cf = camera.CFrame * CFrame.new(0, 0, -distance)
|
|
41
|
+
|
|
42
|
+
ref.Size = Vector3.new(width, height, ref.Size.Z) * scale
|
|
43
|
+
ref.CFrame = cf * CFrame.new(pos) * CFrame.fromOrientation(rot.x, rot.y, rot.z)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
if not RunService:IsRunning() then
|
|
47
|
+
table.insert(scope, RunService.RenderStepped:Connect(frame))
|
|
48
|
+
else
|
|
49
|
+
local id = utility.getRandomId()
|
|
50
|
+
|
|
51
|
+
RunService:BindToRenderStep(id, Enum.RenderPriority.Last.Value + 2 + scope.depth, frame)
|
|
52
|
+
|
|
53
|
+
table.insert(scope, function()
|
|
54
|
+
RunService:UnbindFromRenderStep(id)
|
|
55
|
+
end)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
return true
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
return screen
|