@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.
- package/LICENSE +82 -0
- package/README.md +39 -0
- package/out/effects/beam.luau +312 -0
- package/out/effects/bezier.luau +392 -0
- package/out/effects/camera_shake.luau +200 -0
- package/out/effects/lightning.luau +1183 -0
- package/out/effects/mesh.luau +466 -0
- package/out/effects/particle.luau +64 -0
- package/out/effects/randomizer.luau +110 -0
- package/out/effects/screen.luau +61 -0
- package/out/effects/shockwave_debris.luau +277 -0
- package/out/effects/shockwave_line.luau +356 -0
- package/out/effects/shockwave_ring.luau +252 -0
- package/out/effects/sound.luau +311 -0
- package/out/effects/spin.luau +88 -0
- package/out/effects/tweener.luau +122 -0
- package/out/emitters.luau +387 -0
- package/out/index.d.ts +341 -0
- package/out/init.luau +279 -0
- package/out/mod/attributes.luau +227 -0
- package/out/mod/color/Oklab.luau +93 -0
- package/out/mod/color/sRGB.luau +71 -0
- package/out/mod/common/bezier.luau +372 -0
- package/out/mod/common/flipbook.luau +102 -0
- package/out/mod/lerp.luau +210 -0
- package/out/mod/logger.luau +20 -0
- package/out/mod/shape.luau +207 -0
- package/out/mod/tween.luau +161 -0
- package/out/mod/utility.luau +707 -0
- package/out/obj/Bezier.luau +268 -0
- package/out/obj/ObjectCache.luau +289 -0
- package/out/services/caches.luau +62 -0
- package/out/services/effects.luau +234 -0
- package/out/services/enabled_effects.luau +120 -0
- package/out/services/texture_loader.luau +174 -0
- package/out/tsconfig.tsbuildinfo +1 -0
- package/out/types.luau +43 -0
- package/package.json +63 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
SPDX-License-Identifier: VFX-DL-1.1
|
|
2
|
+
|
|
3
|
+
Preamble.
|
|
4
|
+
Disclaimer: nothing stated in this preamble is legal advice.
|
|
5
|
+
|
|
6
|
+
This is a simple license that allows anyone to use the emit module in their Roblox games.
|
|
7
|
+
|
|
8
|
+
1. You cannot use the module in anything that isn't a Roblox game. For example, it means
|
|
9
|
+
that you cannot create a plugin using this module.
|
|
10
|
+
|
|
11
|
+
2. You are allowed to use the module commercially in your games.
|
|
12
|
+
|
|
13
|
+
3. You are free to share the module with other developers so they can use it in their games,
|
|
14
|
+
as long as the license is retained.
|
|
15
|
+
|
|
16
|
+
4. You can modify and share the module as long as you follow the terms of the license. All
|
|
17
|
+
derivates of the module must have the same license.
|
|
18
|
+
|
|
19
|
+
5. If you break the terms and conditions of the license, you are required to stop the use and
|
|
20
|
+
distribution of the module immediately.
|
|
21
|
+
|
|
22
|
+
End of preamble.
|
|
23
|
+
|
|
24
|
+
VFX Forge Developer License (VFX-DL) Version 1.1
|
|
25
|
+
|
|
26
|
+
Copyright (c) 2025 zilibobi
|
|
27
|
+
|
|
28
|
+
1. Definitions.
|
|
29
|
+
- "Module" means the source code and any compiled form of the Emit Module.
|
|
30
|
+
- "You" means any individual or organization exercising the rights granted herein.
|
|
31
|
+
- "Derivative Work" means any work based upon or incorporating the Module.
|
|
32
|
+
- "Roblox Experience" means a user-facing game or simulation that runs on the
|
|
33
|
+
Roblox platform, created using Roblox Studio and played via the Roblox client.
|
|
34
|
+
|
|
35
|
+
2. Grant of Rights.
|
|
36
|
+
Permission is hereby granted, free of charge, to You to use, reproduce,
|
|
37
|
+
prepare Derivative Works of, publicly display, publicly perform, sublicense,
|
|
38
|
+
and distribute the Module, **solely when embedded in the runtime environment of
|
|
39
|
+
a Roblox Experience** (including playtesting in Roblox Studio), and **not** when
|
|
40
|
+
loaded by any Roblox Studio plugin or other developer tool, running in any context
|
|
41
|
+
that has access to API methods or permissions unavailable to runtime scripts within
|
|
42
|
+
Roblox Experiences (excluding the Roblox Studio command bar feature, when used for
|
|
43
|
+
the purpose of viewing finished effects). You may distribute the Module or Derivative
|
|
44
|
+
Work to other developers, provided they use it only within the permitted runtime
|
|
45
|
+
context described above.
|
|
46
|
+
|
|
47
|
+
3. Conditions.
|
|
48
|
+
a. Copyleft.
|
|
49
|
+
Any Derivative Work, including modified or extended versions of the Module, that
|
|
50
|
+
You distribute must be licensed under the exact same terms as this VFX-DL.
|
|
51
|
+
b. Redistribution.
|
|
52
|
+
You must include a copy of this license text with any distribution of the Module or Derivative Work.
|
|
53
|
+
c. No Other Contexts.
|
|
54
|
+
You may not embed, load, or distribute the Module within any Roblox Studio
|
|
55
|
+
plugin, editor extension, command-line tool, test harness, or any code running
|
|
56
|
+
under Studio outside of normal game runtime.
|
|
57
|
+
|
|
58
|
+
4. Disclaimer of Warranty.
|
|
59
|
+
The Module is provided "AS IS," without warranty of any kind, express or implied,
|
|
60
|
+
including but not limited to the warranties of merchantability, fitness for a
|
|
61
|
+
particular purpose, and noninfringement.
|
|
62
|
+
|
|
63
|
+
5. Limitation of Liability.
|
|
64
|
+
In no event shall the authors or copyright holders be liable for any claim,
|
|
65
|
+
damages, or other liability arising from, out of, or in connection with the
|
|
66
|
+
Module or the use or other dealings in the Module.
|
|
67
|
+
|
|
68
|
+
6. Termination.
|
|
69
|
+
If You violate the terms of this License, Your rights under this VFX-DL will
|
|
70
|
+
terminate automatically. Upon termination, You must cease all use and distribution
|
|
71
|
+
of the Module and any Derivative Works.
|
|
72
|
+
|
|
73
|
+
7. Versioning.
|
|
74
|
+
This license applies to Version 1.0 of the VFX-DL. Future versions may be published
|
|
75
|
+
by the copyright holder.
|
|
76
|
+
|
|
77
|
+
8. Commercial use.
|
|
78
|
+
This License permits commercial use within the scope defined in Section 2.
|
|
79
|
+
|
|
80
|
+
9. Trademarks and branding.
|
|
81
|
+
Nothing in this License grants permission to use the trade names, trademarks, service marks,
|
|
82
|
+
or product names of the Licensor.
|
package/README.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+

|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
<a href="https://docs.zilibobi.dev/vfx-forge"><img alt="View Documentation" src="https://img.shields.io/badge/Documentation-View?style=for-the-badge&label=View&color=c4a7e7"></a>
|
|
5
|
+
<a href="https://discord.gg/Qme9KPN3pF"><img alt="Join Discord" src="https://img.shields.io/discord/1401872327162986626?logo=discord&style=for-the-badge&color=c4a7e7&logoColor=ffffff&label=Join%20Discord"></a>
|
|
6
|
+
</div>
|
|
7
|
+
|
|
8
|
+
# Emit Module
|
|
9
|
+
|
|
10
|
+
The is the official repository for the emit module provided by the <a href="https://devforum.roblox.com/t/3867553">VFX Forge</a> Roblox plugin.
|
|
11
|
+
|
|
12
|
+
## License
|
|
13
|
+
The emit module is licensed under a custom source-available copyleft license which **<mark>only allows usage within Roblox games</mark>**. That said, feel free to contribute and report bugs.
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
#### Using Wally
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
ForgeVFX = "zilibobi/forge-vfx@2.2.2"
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
#### Manual
|
|
24
|
+
|
|
25
|
+
Check the [releases page](https://github.com/zilibobi/forge-vfx/releases/latest) for prebuilt .rbxm files.
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
The module needs to be initialized before emitting any effects.
|
|
30
|
+
After that it is also exposed inside `shared.vfx`.
|
|
31
|
+
|
|
32
|
+
```luau
|
|
33
|
+
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
|
34
|
+
|
|
35
|
+
local vfx = require(ReplicatedStorage.ForgeVFX)
|
|
36
|
+
|
|
37
|
+
vfx.init()
|
|
38
|
+
vfx.emit(workspace.Effect)
|
|
39
|
+
```
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
--!nolint LocalShadow
|
|
2
|
+
local attr = require("@mod/attributes")
|
|
3
|
+
local tween = require("@mod/tween")
|
|
4
|
+
local types = require("@root/types")
|
|
5
|
+
local utility = require("@mod/utility")
|
|
6
|
+
local flipbook_common = require("@mod/common/flipbook")
|
|
7
|
+
|
|
8
|
+
local Promise = require("@pkg/Promise")
|
|
9
|
+
|
|
10
|
+
local rng = Random.new()
|
|
11
|
+
|
|
12
|
+
local function getLegacyWidths(obj: Beam, scale: number)
|
|
13
|
+
local w0 = attr.get(obj, "Width0", obj.Width0, true) * scale
|
|
14
|
+
local w1 = attr.get(obj, "Width1", obj.Width1, true) * scale
|
|
15
|
+
|
|
16
|
+
local s_w0 = attr.get(obj, "StartWidth0", obj.Width0, true) * scale
|
|
17
|
+
local s_w1 = attr.get(obj, "StartWidth1", obj.Width1, true) * scale
|
|
18
|
+
|
|
19
|
+
return w0, w1, s_w0, s_w1
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
local beam = {}
|
|
23
|
+
|
|
24
|
+
function beam.emit(ref: Beam, obj: Beam, scope: types.scope, scale: number)
|
|
25
|
+
local emitOnFinish = scope.effects.prepareEmitOnFinish(obj, scope)
|
|
26
|
+
|
|
27
|
+
local a1, a2, a3, a4 = getLegacyWidths(ref, scale)
|
|
28
|
+
|
|
29
|
+
local w1 = attr.get(ref, "Width0_Start", a3)
|
|
30
|
+
local w2 = attr.get(ref, "Width0_End", a1)
|
|
31
|
+
local w3 = attr.get(ref, "Width1_Start", a4)
|
|
32
|
+
local w4 = attr.get(ref, "Width1_End", a2)
|
|
33
|
+
|
|
34
|
+
local c1 = attr.get(ref, "CurveSize0_Start", obj.CurveSize0)
|
|
35
|
+
local c2 = attr.get(ref, "CurveSize0_End", obj.CurveSize0)
|
|
36
|
+
local c3 = attr.get(ref, "CurveSize1_Start", obj.CurveSize1)
|
|
37
|
+
local c4 = attr.get(ref, "CurveSize1_End", obj.CurveSize1)
|
|
38
|
+
|
|
39
|
+
local emitDelay = attr.get(ref, "EmitDelay", 0)
|
|
40
|
+
|
|
41
|
+
local legacy_duration = attr.get(ref, "Duration", 1, true)
|
|
42
|
+
local legacy_tpScale = attr.get(ref, "EndTransparencyScale", 1, true)
|
|
43
|
+
|
|
44
|
+
local durationRange = attr.getRange(
|
|
45
|
+
ref,
|
|
46
|
+
"EffectDuration",
|
|
47
|
+
NumberRange.new(legacy_duration, legacy_duration),
|
|
48
|
+
NumberRange.new(0, math.huge)
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
local lengthScaleRangeStart = attr.get(ref, "Length_Scale_Start", NumberRange.new(1, 1))
|
|
52
|
+
local lengthScaleRangeEnd = attr.get(ref, "Length_Scale_End", NumberRange.new(1, 1))
|
|
53
|
+
|
|
54
|
+
local texLengthStart = attr.get(ref, "Length_Texture_Start", ref.TextureLength)
|
|
55
|
+
local textLengthEnd = attr.get(ref, "Length_Texture_End", ref.TextureLength)
|
|
56
|
+
|
|
57
|
+
local duration = rng:NextNumber(durationRange.Min, durationRange.Max)
|
|
58
|
+
|
|
59
|
+
local lengthScaleEnd = rng:NextNumber(lengthScaleRangeEnd.Min, lengthScaleRangeEnd.Max)
|
|
60
|
+
local lengthScaleStart = rng:NextNumber(lengthScaleRangeStart.Min, lengthScaleRangeStart.Max)
|
|
61
|
+
|
|
62
|
+
local tStart, tEnd =
|
|
63
|
+
attr.get(ref, "Transparency_Scale_Start", 1), attr.get(ref, "Transparency_Scale_End", legacy_tpScale)
|
|
64
|
+
|
|
65
|
+
local texSpeedStart = attr.get(ref, "Speed_Texture_Start", ref.TextureSpeed)
|
|
66
|
+
local texSpeedEnd = attr.get(ref, "Speed_Texture_End", ref.TextureSpeed)
|
|
67
|
+
|
|
68
|
+
local speedStart = attr.get(ref, "Speed_Start", 1)
|
|
69
|
+
local speedEnd = attr.get(ref, "Speed_End", 1)
|
|
70
|
+
|
|
71
|
+
local baseTexSpeed = obj.TextureSpeed
|
|
72
|
+
|
|
73
|
+
task.wait(emitDelay)
|
|
74
|
+
|
|
75
|
+
obj.Enabled = true
|
|
76
|
+
|
|
77
|
+
local promises = {}
|
|
78
|
+
local currentSpeed = 1
|
|
79
|
+
|
|
80
|
+
local speedTween
|
|
81
|
+
|
|
82
|
+
local env = scope.effects.emitNested(obj, scope.depth + 1)
|
|
83
|
+
table.insert(promises, env.Finished)
|
|
84
|
+
|
|
85
|
+
if texSpeedStart ~= texSpeedEnd then
|
|
86
|
+
tween.fromParams(attr.get(ref, "Speed_Texture_Curve", utility.default_bezier), duration, function(alpha, deltaTime)
|
|
87
|
+
baseTexSpeed = utility.lerp(texSpeedStart, texSpeedEnd, alpha)
|
|
88
|
+
obj.TextureSpeed = baseTexSpeed * currentSpeed
|
|
89
|
+
|
|
90
|
+
return deltaTime
|
|
91
|
+
end)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
if speedStart ~= speedEnd then
|
|
95
|
+
speedTween = tween.fromParams(
|
|
96
|
+
attr.get(ref, "Speed_Curve", utility.default_bezier),
|
|
97
|
+
attr.get(obj, "Speed_Duration", 0.1),
|
|
98
|
+
function(alpha, deltaTime)
|
|
99
|
+
currentSpeed = utility.lerp(speedStart, speedEnd, alpha)
|
|
100
|
+
|
|
101
|
+
obj.TextureSpeed = baseTexSpeed * currentSpeed
|
|
102
|
+
|
|
103
|
+
return deltaTime
|
|
104
|
+
end
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
table.insert(scope, speedTween)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
local refTpKp = ref.Transparency.Keypoints
|
|
111
|
+
|
|
112
|
+
local numKeypoints = #refTpKp
|
|
113
|
+
local scaledKeypoints = table.create(numKeypoints)
|
|
114
|
+
|
|
115
|
+
local keypointData = table.create(numKeypoints)
|
|
116
|
+
|
|
117
|
+
for i, kp in refTpKp do
|
|
118
|
+
keypointData[i] = {
|
|
119
|
+
time = kp.Time,
|
|
120
|
+
value = kp.Value,
|
|
121
|
+
envelope = kp.Envelope,
|
|
122
|
+
}
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
local lastTScale = nil
|
|
126
|
+
|
|
127
|
+
local function setTScale(tscale: number)
|
|
128
|
+
if lastTScale and math.abs(tscale - lastTScale) < 0.001 then
|
|
129
|
+
return
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
lastTScale = tscale
|
|
133
|
+
|
|
134
|
+
local offset = tscale > 1 and tscale - 1 or 1 - tscale
|
|
135
|
+
|
|
136
|
+
for i, kd in keypointData do
|
|
137
|
+
local value = kd.value
|
|
138
|
+
local base = tscale > 1 and (1 - value) or -value
|
|
139
|
+
|
|
140
|
+
scaledKeypoints[i] = NumberSequenceKeypoint.new(kd.time, value + base * offset, kd.envelope)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
obj.Transparency = NumberSequence.new(scaledKeypoints)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
local att0, att1 = obj.Attachment0, obj.Attachment1
|
|
147
|
+
local cf0, cf1 = att0 and att0.CFrame, att1 and att1.CFrame
|
|
148
|
+
|
|
149
|
+
local function setLengthScale(scale: number)
|
|
150
|
+
if not cf0 or not cf1 then
|
|
151
|
+
return
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
-- calculate the original offset vector from att0 to att1
|
|
155
|
+
local offset = cf1.Position - cf0.Position
|
|
156
|
+
local halfOffset = offset * 0.5
|
|
157
|
+
|
|
158
|
+
-- calculate center point
|
|
159
|
+
local center = cf0.Position + halfOffset
|
|
160
|
+
|
|
161
|
+
-- scale the half-offsets and apply from center
|
|
162
|
+
local scaledHalfOffset = halfOffset * scale
|
|
163
|
+
|
|
164
|
+
att0.CFrame = CFrame.new(center - scaledHalfOffset) * (cf0 - cf0.Position)
|
|
165
|
+
att1.CFrame = CFrame.new(center + scaledHalfOffset) * (cf1 - cf1.Position)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
table.insert(scope, function()
|
|
169
|
+
setLengthScale(1)
|
|
170
|
+
end)
|
|
171
|
+
|
|
172
|
+
if tStart ~= tEnd then
|
|
173
|
+
table.insert(
|
|
174
|
+
scope,
|
|
175
|
+
tween.fromParams(
|
|
176
|
+
attr.get(ref, "Transparency_Scale_Curve", utility.default_bezier),
|
|
177
|
+
duration,
|
|
178
|
+
function(alpha, deltaTime)
|
|
179
|
+
setTScale(utility.lerp(tStart, tEnd, alpha))
|
|
180
|
+
return deltaTime * currentSpeed
|
|
181
|
+
end,
|
|
182
|
+
speedTween
|
|
183
|
+
)
|
|
184
|
+
)
|
|
185
|
+
elseif tStart ~= 1 then
|
|
186
|
+
setTScale(tStart)
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
if texLengthStart ~= textLengthEnd then
|
|
190
|
+
table.insert(
|
|
191
|
+
scope,
|
|
192
|
+
tween.fromParams(
|
|
193
|
+
attr.get(ref, "Length_Texture_Curve", utility.default_bezier),
|
|
194
|
+
duration,
|
|
195
|
+
function(alpha, deltaTime)
|
|
196
|
+
obj.TextureLength = utility.lerp(texLengthStart, textLengthEnd, alpha)
|
|
197
|
+
return deltaTime * currentSpeed
|
|
198
|
+
end,
|
|
199
|
+
speedTween
|
|
200
|
+
)
|
|
201
|
+
)
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
if lengthScaleStart ~= lengthScaleEnd then
|
|
205
|
+
table.insert(
|
|
206
|
+
scope,
|
|
207
|
+
tween.fromParams(attr.get(ref, "Length_Scale_Curve", utility.default_bezier), duration, function(alpha, deltaTime)
|
|
208
|
+
local x = utility.lerp(lengthScaleStart, lengthScaleEnd, alpha)
|
|
209
|
+
|
|
210
|
+
setLengthScale(x)
|
|
211
|
+
|
|
212
|
+
return deltaTime * currentSpeed
|
|
213
|
+
end, speedTween)
|
|
214
|
+
)
|
|
215
|
+
elseif texLengthStart ~= 1 then
|
|
216
|
+
setLengthScale(lengthScaleStart)
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
if w1 ~= w2 then
|
|
220
|
+
table.insert(
|
|
221
|
+
scope,
|
|
222
|
+
tween.fromParams(attr.get(ref, "Width0_Curve", utility.default_bezier), duration, function(alpha, deltaTime)
|
|
223
|
+
obj.Width0 = utility.lerp(w1, w2, alpha)
|
|
224
|
+
return deltaTime * currentSpeed
|
|
225
|
+
end, speedTween)
|
|
226
|
+
)
|
|
227
|
+
else
|
|
228
|
+
obj.Width0 = w1
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
if w3 ~= w4 then
|
|
232
|
+
table.insert(
|
|
233
|
+
scope,
|
|
234
|
+
tween.fromParams(attr.get(ref, "Width1_Curve", utility.default_bezier), duration, function(alpha, deltaTime)
|
|
235
|
+
obj.Width1 = utility.lerp(w3, w4, alpha)
|
|
236
|
+
return deltaTime * currentSpeed
|
|
237
|
+
end, speedTween)
|
|
238
|
+
)
|
|
239
|
+
else
|
|
240
|
+
obj.Width1 = w3
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
if c1 ~= c2 then
|
|
244
|
+
table.insert(
|
|
245
|
+
scope,
|
|
246
|
+
tween.fromParams(attr.get(ref, "CurveSize0_Curve", utility.default_bezier), duration, function(alpha, deltaTime)
|
|
247
|
+
obj.CurveSize0 = utility.lerp(c1, c2, alpha)
|
|
248
|
+
return deltaTime * currentSpeed
|
|
249
|
+
end, speedTween)
|
|
250
|
+
)
|
|
251
|
+
else
|
|
252
|
+
obj.Width0 = w1
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
if c3 ~= c4 then
|
|
256
|
+
table.insert(
|
|
257
|
+
scope,
|
|
258
|
+
tween.fromParams(attr.get(ref, "CurveSize1_Curve", utility.default_bezier), duration, function(alpha, deltaTime)
|
|
259
|
+
obj.CurveSize1 = utility.lerp(c3, c4, alpha)
|
|
260
|
+
return deltaTime * currentSpeed
|
|
261
|
+
end, speedTween)
|
|
262
|
+
)
|
|
263
|
+
else
|
|
264
|
+
obj.Width1 = w3
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
-- flipbook support
|
|
268
|
+
local flipbookDuration = 0
|
|
269
|
+
local flipbook = flipbook_common.getFlipbookData(ref)
|
|
270
|
+
|
|
271
|
+
if flipbook then
|
|
272
|
+
local config = {
|
|
273
|
+
ref = ref,
|
|
274
|
+
frames = flipbook,
|
|
275
|
+
speedTween = speedTween,
|
|
276
|
+
effectDuration = duration,
|
|
277
|
+
|
|
278
|
+
curve = attr.get(ref, "Flipbook_Change_Curve", utility.linear_bezier),
|
|
279
|
+
duration = attr.get(ref, "Flipbook_Change_Duration", duration),
|
|
280
|
+
|
|
281
|
+
getSpeed = function()
|
|
282
|
+
return currentSpeed
|
|
283
|
+
end,
|
|
284
|
+
|
|
285
|
+
setTexture = function(texture)
|
|
286
|
+
obj.Texture = texture
|
|
287
|
+
end,
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
flipbookDuration = flipbook_common.getChangeDuration(config)
|
|
291
|
+
|
|
292
|
+
table.insert(
|
|
293
|
+
scope,
|
|
294
|
+
tween.fromParams(config.curve, flipbookDuration, flipbook_common.createUpdateCallback(config), speedTween)
|
|
295
|
+
)
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
tween.timer(math.max(duration, flipbookDuration), function(deltaTime, elapsed)
|
|
299
|
+
return if currentSpeed > 0 or (elapsed > 0 and speedTween and speedTween.Connected)
|
|
300
|
+
then deltaTime * currentSpeed
|
|
301
|
+
else nil
|
|
302
|
+
end, speedTween, scope)
|
|
303
|
+
|
|
304
|
+
if emitOnFinish then
|
|
305
|
+
local env = scope.effects.emitOnFinish(emitOnFinish, obj.Parent or workspace.Terrain, scope.depth + 1)
|
|
306
|
+
table.insert(promises, env.Finished)
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
Promise.all(promises):await()
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
return beam
|