@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,122 @@
|
|
|
1
|
+
local attr = require(script.Parent.Parent.mod.attributes)
|
|
2
|
+
local lerp = require(script.Parent.Parent.mod.lerp)
|
|
3
|
+
local tween = require(script.Parent.Parent.mod.tween)
|
|
4
|
+
local types = require(script.Parent.Parent.types)
|
|
5
|
+
local utility = require(script.Parent.Parent.mod.utility)
|
|
6
|
+
|
|
7
|
+
local rng = Random.new()
|
|
8
|
+
|
|
9
|
+
local tweener = {}
|
|
10
|
+
|
|
11
|
+
function tweener.emit(obj: RayValue, scope: types.scope, isAttribute: boolean)
|
|
12
|
+
local target = utility.getTarget(obj)
|
|
13
|
+
|
|
14
|
+
if not target then
|
|
15
|
+
return
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
local name = obj.Name
|
|
19
|
+
|
|
20
|
+
local emitDelay = attr.get(obj, "EmitDelay", 0)
|
|
21
|
+
local resetOnFinish = attr.get(obj, "ResetOnFinish", true)
|
|
22
|
+
|
|
23
|
+
local durationRange = attr.getRange(obj, "Duration", NumberRange.new(1, 1), NumberRange.new(0, math.huge))
|
|
24
|
+
|
|
25
|
+
if emitDelay > 0 then
|
|
26
|
+
task.wait(emitDelay)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
local endValue = attr.get(obj, "_END_VALUE", nil)
|
|
30
|
+
local overrideStartValue = attr.get(obj, "_START_VALUE", nil)
|
|
31
|
+
|
|
32
|
+
local startValue
|
|
33
|
+
|
|
34
|
+
if isAttribute then
|
|
35
|
+
startValue = attr.get(target, name, nil)
|
|
36
|
+
else
|
|
37
|
+
local ok, val = pcall(function()
|
|
38
|
+
return target[name]
|
|
39
|
+
end)
|
|
40
|
+
|
|
41
|
+
if not ok then
|
|
42
|
+
return
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
startValue = val
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
if overrideStartValue then
|
|
49
|
+
startValue = overrideStartValue
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
local typeName = typeof(startValue)
|
|
53
|
+
|
|
54
|
+
if typeName ~= typeof(endValue) then
|
|
55
|
+
return
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
local duration = rng:NextNumber(durationRange.Min, durationRange.Max)
|
|
59
|
+
|
|
60
|
+
local speedStart = attr.get(obj, "Speed_Start", 1)
|
|
61
|
+
local speedEnd = attr.get(obj, "Speed_End", 1)
|
|
62
|
+
|
|
63
|
+
local currentSpeed = speedStart
|
|
64
|
+
|
|
65
|
+
local speedTween
|
|
66
|
+
|
|
67
|
+
if speedStart ~= speedEnd then
|
|
68
|
+
speedTween = tween.fromParams(
|
|
69
|
+
attr.get(obj, "Speed_Curve", utility.default_bezier),
|
|
70
|
+
attr.get(obj, "Speed_Duration", 0.1),
|
|
71
|
+
function(alpha, deltaTime)
|
|
72
|
+
currentSpeed = utility.lerp(speedStart, speedEnd, alpha)
|
|
73
|
+
return deltaTime
|
|
74
|
+
end
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
table.insert(scope, speedTween)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
local lfunc = lerp[typeName] or lerp.Other
|
|
81
|
+
|
|
82
|
+
local animator = if isAttribute
|
|
83
|
+
then function(alpha, deltaTime)
|
|
84
|
+
attr.set(target, name, lfunc(startValue, endValue, alpha))
|
|
85
|
+
return deltaTime * currentSpeed
|
|
86
|
+
end
|
|
87
|
+
else function(alpha, deltaTime)
|
|
88
|
+
target[name] = lfunc(startValue, endValue, alpha)
|
|
89
|
+
return deltaTime * currentSpeed
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
table.insert(
|
|
93
|
+
scope,
|
|
94
|
+
tween.fromParams(
|
|
95
|
+
attr.get(obj, "Easing_Curve", utility.linear_bezier),
|
|
96
|
+
duration,
|
|
97
|
+
animator,
|
|
98
|
+
speedTween,
|
|
99
|
+
nil,
|
|
100
|
+
nil,
|
|
101
|
+
utility.RENDER_PRIORITY + scope.depth
|
|
102
|
+
)
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
if resetOnFinish then
|
|
106
|
+
table.insert(scope, function()
|
|
107
|
+
if isAttribute then
|
|
108
|
+
attr.set(target, name, startValue)
|
|
109
|
+
else
|
|
110
|
+
target[name] = startValue
|
|
111
|
+
end
|
|
112
|
+
end)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
tween.timer(duration, function(deltaTime, elapsed)
|
|
116
|
+
return if currentSpeed > 0 or (elapsed > 0 and speedTween and speedTween.Connected)
|
|
117
|
+
then deltaTime * currentSpeed
|
|
118
|
+
else nil
|
|
119
|
+
end, speedTween, scope)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
return tweener
|
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
local TS = _G[script.Parent.Parent]
|
|
2
|
+
local Beam = require(script.Parent.effects.beam)
|
|
3
|
+
local Spin = require(script.Parent.effects.spin)
|
|
4
|
+
local Mesh = require(script.Parent.effects.mesh)
|
|
5
|
+
local Sound = require(script.Parent.effects.sound)
|
|
6
|
+
local Bezier = require(script.Parent.effects.bezier)
|
|
7
|
+
local Screen = require(script.Parent.effects.screen)
|
|
8
|
+
local Particle = require(script.Parent.effects.particle)
|
|
9
|
+
local Lightning = require(script.Parent.effects.lightning)
|
|
10
|
+
local CameraShake = require(script.Parent.effects.camera_shake)
|
|
11
|
+
local Tweener = require(script.Parent.effects.tweener)
|
|
12
|
+
local Randomizer = require(script.Parent.effects.randomizer)
|
|
13
|
+
local ShockwaveRing = require(script.Parent.effects.shockwave_ring)
|
|
14
|
+
local ShockwaveLine = require(script.Parent.effects.shockwave_line)
|
|
15
|
+
local ShockwaveDebris = require(script.Parent.effects.shockwave_debris)
|
|
16
|
+
|
|
17
|
+
local attr = require(script.Parent.mod.attributes)
|
|
18
|
+
local types = require(script.Parent.types)
|
|
19
|
+
local utility = require(script.Parent.mod.utility)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
local emitters = {}
|
|
23
|
+
|
|
24
|
+
local function processRandomizers(obj: Instance, scope: types.scope)
|
|
25
|
+
local r_prop = obj:QueryDescendants(`> RayValue.{utility.PROPERTY_RANDOMIZER_TAG}`)
|
|
26
|
+
local r_attr = obj:QueryDescendants(`> RayValue.{utility.ATTRIBUTE_RANDOMIZER_TAG}`)
|
|
27
|
+
|
|
28
|
+
-- allow emitting the randomizer directly
|
|
29
|
+
if obj:IsA("RayValue") then
|
|
30
|
+
if obj:HasTag(utility.PROPERTY_RANDOMIZER_TAG) then
|
|
31
|
+
table.insert(r_prop, obj)
|
|
32
|
+
elseif obj:HasTag(utility.ATTRIBUTE_RANDOMIZER_TAG) then
|
|
33
|
+
table.insert(r_attr, obj)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
for _, obj in r_prop do
|
|
38
|
+
utility.try(`failed to emit property randomizer with error: %s`, Randomizer.emit, obj, scope, false)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
for _, obj in r_attr do
|
|
42
|
+
utility.try(`failed to emit attribute randomizer with error: %s`, Randomizer.emit, obj, scope, true)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
function emitters.particle(
|
|
47
|
+
obj: ParticleEmitter,
|
|
48
|
+
scope: types.scope,
|
|
49
|
+
sharedUncMap: { [Instance]: number },
|
|
50
|
+
sharedRefMap: { [Instance]: Instance },
|
|
51
|
+
legacyScale: number
|
|
52
|
+
)
|
|
53
|
+
local count = attr.get(obj, "EmitCount", 1, true)
|
|
54
|
+
local duration = attr.get(obj, "EmitDuration", 0, true)
|
|
55
|
+
|
|
56
|
+
if count <= 0 and duration <= 0 then
|
|
57
|
+
return
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
if not obj:IsDescendantOf(workspace) then
|
|
61
|
+
local parent, ancestor = utility.cloneParticleAncestry(obj, sharedRefMap)
|
|
62
|
+
|
|
63
|
+
if not parent then
|
|
64
|
+
return
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
local clone = obj:Clone()
|
|
68
|
+
clone.Archivable = false
|
|
69
|
+
clone.Parent = parent
|
|
70
|
+
|
|
71
|
+
if not sharedUncMap[ancestor] then
|
|
72
|
+
ancestor.Parent = workspace.Terrain
|
|
73
|
+
sharedUncMap[ancestor] = 1
|
|
74
|
+
else
|
|
75
|
+
sharedUncMap[ancestor] += 1
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
table.insert(scope, function()
|
|
79
|
+
sharedUncMap[ancestor] -= 1
|
|
80
|
+
|
|
81
|
+
if sharedUncMap[ancestor] <= 0 then
|
|
82
|
+
ancestor:Destroy()
|
|
83
|
+
end
|
|
84
|
+
end)
|
|
85
|
+
|
|
86
|
+
utility.try(`failed to emit particle with error: %s`, Particle.emit, obj, clone, scope, legacyScale)
|
|
87
|
+
else
|
|
88
|
+
utility.try(`failed to emit particle with error: %s`, Particle.emit, obj, obj, scope, legacyScale)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
function emitters.beam(obj: Beam, scope: types.scope, legacyScale: number)
|
|
93
|
+
local att0, att1 = obj.Attachment0, obj.Attachment1
|
|
94
|
+
|
|
95
|
+
if not att0 or not att1 then
|
|
96
|
+
return
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
local clone = obj:Clone()
|
|
100
|
+
clone.Archivable = false
|
|
101
|
+
clone.Parent = workspace.Terrain
|
|
102
|
+
|
|
103
|
+
-- clone attachments for beams with scaled length
|
|
104
|
+
local unscaled = NumberRange.new(1, 1)
|
|
105
|
+
|
|
106
|
+
if
|
|
107
|
+
attr.get(obj, "Length_Scale_Start", unscaled, true) ~= unscaled
|
|
108
|
+
or attr.get(obj, "Length_Scale_End", unscaled, true) ~= unscaled
|
|
109
|
+
then
|
|
110
|
+
local a, b = att0:Clone(), att1:Clone()
|
|
111
|
+
|
|
112
|
+
table.insert(scope, a)
|
|
113
|
+
table.insert(scope, b)
|
|
114
|
+
|
|
115
|
+
a.Name = "_ForgeTempAttachment"
|
|
116
|
+
b.Name = "_ForgeTempAttachment"
|
|
117
|
+
|
|
118
|
+
a:AddTag(utility.EMIT_EXCLUDE_TAG)
|
|
119
|
+
b:AddTag(utility.EMIT_EXCLUDE_TAG)
|
|
120
|
+
|
|
121
|
+
clone.Attachment0 = a
|
|
122
|
+
clone.Attachment1 = b
|
|
123
|
+
|
|
124
|
+
a.Parent = att0.Parent
|
|
125
|
+
b.Parent = att1.Parent
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
table.insert(scope, clone)
|
|
129
|
+
|
|
130
|
+
utility.try(`failed to emit beam with error: %s`, Beam.emit, obj, clone, scope, legacyScale)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
function emitters.trail(obj: Trail)
|
|
134
|
+
obj.Enabled = true
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
function emitters.bezier(obj: Instance, scope: types.scope, skipEnabledCheck: boolean?)
|
|
138
|
+
local part = obj:FindFirstChildOfClass("Part")
|
|
139
|
+
|
|
140
|
+
if not part then
|
|
141
|
+
return
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
if not skipEnabledCheck and obj:GetAttribute("Enabled") then
|
|
145
|
+
obj:SetAttribute("Enabled", false)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
local clone = part:Clone()
|
|
149
|
+
clone.Locked = true
|
|
150
|
+
|
|
151
|
+
table.insert(scope, clone)
|
|
152
|
+
|
|
153
|
+
utility.try(`failed to emit bezier with error: %s`, Bezier.emit, obj, clone, scope, skipEnabledCheck)
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
function emitters.lightning(obj: Instance, scope: types.scope, skipEnabledCheck: boolean?)
|
|
157
|
+
local part = obj:FindFirstChildOfClass("Part")
|
|
158
|
+
|
|
159
|
+
if not part then
|
|
160
|
+
return
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
if not skipEnabledCheck and obj:GetAttribute("Enabled") then
|
|
164
|
+
obj:SetAttribute("Enabled", false)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
local clone = part:Clone()
|
|
168
|
+
clone.Locked = true
|
|
169
|
+
|
|
170
|
+
table.insert(scope, clone)
|
|
171
|
+
|
|
172
|
+
utility.try(`failed to emit lightning with error: %s`, Lightning.emit, obj, clone, scope, skipEnabledCheck)
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
function emitters.mesh(
|
|
176
|
+
obj: Instance,
|
|
177
|
+
scope: types.scope,
|
|
178
|
+
shared_part_cache: any,
|
|
179
|
+
legacyScale: number,
|
|
180
|
+
skipEnabledCheck: boolean?
|
|
181
|
+
)
|
|
182
|
+
local start = obj:FindFirstChild("Start")
|
|
183
|
+
|
|
184
|
+
if not start then
|
|
185
|
+
return
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
if not skipEnabledCheck and obj:GetAttribute("Enabled") then
|
|
189
|
+
obj:SetAttribute("Enabled", false)
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
local tasks = {}
|
|
193
|
+
|
|
194
|
+
for i = 1, attr.get(obj, "EmitCount", 1) do
|
|
195
|
+
table.insert(
|
|
196
|
+
tasks,
|
|
197
|
+
TS.Promise.new(function(resolve)
|
|
198
|
+
utility.try(
|
|
199
|
+
`failed to emit mesh with error: %s`,
|
|
200
|
+
Mesh.emit,
|
|
201
|
+
obj,
|
|
202
|
+
utility.assembleMeshVFX(start, scope, shared_part_cache),
|
|
203
|
+
scope,
|
|
204
|
+
legacyScale,
|
|
205
|
+
skipEnabledCheck
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
resolve()
|
|
209
|
+
end)
|
|
210
|
+
)
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
TS.Promise.all(tasks):await()
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
function emitters.spin(obj: Model, scope: types.scope)
|
|
217
|
+
if utility.lock(obj) then
|
|
218
|
+
return
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
utility.try(`failed to emit spinning model with error: %s`, Spin.emit, obj, scope)
|
|
222
|
+
utility.unlock(obj)
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
function emitters.camera_shake(obj: RayValue, scope: types.scope)
|
|
226
|
+
utility.try(`failed to emit camera shake with error: %s`, CameraShake.emit, obj, scope)
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
function emitters.property_tweener(obj: RayValue, scope: types.scope)
|
|
230
|
+
if not obj.Parent or utility.lock(obj) then
|
|
231
|
+
return
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
utility.try(`failed to emit property tweener with error: %s`, Tweener.emit, obj, scope, false)
|
|
235
|
+
utility.unlock(obj)
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
function emitters.attribute_tweener(obj: RayValue, scope: types.scope)
|
|
239
|
+
if not obj.Parent or utility.lock(obj) then
|
|
240
|
+
return
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
utility.try(`failed to emit attribute tweener with error: %s`, Tweener.emit, obj.Parent, obj, scope, true)
|
|
244
|
+
utility.unlock(obj)
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
function emitters.screen(obj: BasePart, scope: types.scope)
|
|
248
|
+
local ok, result = utility.try(`failed to emit screen effect with error: %s`, Screen.emit, obj, scope)
|
|
249
|
+
|
|
250
|
+
return if ok then result else false
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
function emitters.shockwave_ring(att: Attachment, obj: Part, scope: types.scope)
|
|
254
|
+
utility.try(`failed to emit shockwave ring with error: %s`, ShockwaveRing.emit, att, obj, scope)
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
function emitters.shockwave_debris(att: Attachment, obj: Part, scope: types.scope)
|
|
258
|
+
utility.try(`failed to emit shockwave debris with error: %s`, ShockwaveDebris.emit, att, obj, scope)
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
function emitters.shockwave_line(att: Attachment, obj: Part, scope: types.scope)
|
|
262
|
+
utility.try(`failed to emit shockwave line with error: %s`, ShockwaveLine.emit, att, obj, scope)
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
function emitters.sound(obj: Sound, scope: types.scope)
|
|
266
|
+
local emitCount = attr.get(obj, "EmitCount", 1, true)
|
|
267
|
+
|
|
268
|
+
if emitCount <= 0 then
|
|
269
|
+
return
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
utility.try(`failed to emit sound with error: %s`, Sound.emit, obj, scope)
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
-- Dispatch function to determine which emitter to use and call it
|
|
276
|
+
function emitters.dispatch(
|
|
277
|
+
obj: any, -- since we don't use IsA(...), we don't get type narrowing
|
|
278
|
+
scope: types.scope,
|
|
279
|
+
sharedUncMap: { [Instance]: number },
|
|
280
|
+
sharedRefMap: { [Instance]: Instance },
|
|
281
|
+
shared_part_cache: any,
|
|
282
|
+
legacyScale: number
|
|
283
|
+
)
|
|
284
|
+
local className = obj.ClassName
|
|
285
|
+
|
|
286
|
+
processRandomizers(obj, scope)
|
|
287
|
+
|
|
288
|
+
if className == "ParticleEmitter" then
|
|
289
|
+
emitters.particle(obj, scope, sharedUncMap, sharedRefMap, legacyScale)
|
|
290
|
+
return
|
|
291
|
+
elseif className == "Beam" then
|
|
292
|
+
emitters.beam(obj, scope, legacyScale)
|
|
293
|
+
return
|
|
294
|
+
elseif className == "Trail" then
|
|
295
|
+
emitters.trail(obj)
|
|
296
|
+
return
|
|
297
|
+
elseif className == "Sound" then
|
|
298
|
+
emitters.sound(obj, scope)
|
|
299
|
+
return
|
|
300
|
+
elseif className == "RayValue" then
|
|
301
|
+
if obj:HasTag(utility.SCREENSHAKE_TAG) then
|
|
302
|
+
emitters.camera_shake(obj, scope)
|
|
303
|
+
elseif obj:HasTag(utility.ATTRIBUTE_TWEENER_TAG) then
|
|
304
|
+
emitters.attribute_tweener(obj, scope)
|
|
305
|
+
elseif obj:HasTag(utility.PROPERTY_RANDOMIZER_TAG) or obj:HasTag(utility.ATTRIBUTE_RANDOMIZER_TAG) then
|
|
306
|
+
-- skip randomizer effects because they have already been emitted
|
|
307
|
+
else
|
|
308
|
+
-- fall back to property tweens for backwards compatibility
|
|
309
|
+
emitters.property_tweener(obj, scope)
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
return
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
if obj:HasTag(utility.BEZIER_TAG) then
|
|
316
|
+
emitters.bezier(obj, scope)
|
|
317
|
+
return
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
if obj:HasTag(utility.LIGHTNING_TAG) then
|
|
321
|
+
emitters.lightning(obj, scope)
|
|
322
|
+
return
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
if className == "Model" then
|
|
326
|
+
if utility.isMeshVFX(obj) then
|
|
327
|
+
emitters.mesh(obj, scope, shared_part_cache, legacyScale)
|
|
328
|
+
else
|
|
329
|
+
emitters.spin(obj, scope)
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
return
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
if className == "Part" then
|
|
336
|
+
local att = utility.findFirstClassWithTag(obj, "Attachment", utility.SHOCKWAVE_TAG)
|
|
337
|
+
|
|
338
|
+
if att then
|
|
339
|
+
local name = obj.Parent and obj.Parent.Name or ""
|
|
340
|
+
|
|
341
|
+
if name == "Rings" then
|
|
342
|
+
emitters.shockwave_ring(att, obj, scope)
|
|
343
|
+
elseif name == "Debris" then
|
|
344
|
+
emitters.shockwave_debris(att, obj, scope)
|
|
345
|
+
elseif name == "Lines" then
|
|
346
|
+
emitters.shockwave_line(att, obj, scope)
|
|
347
|
+
end
|
|
348
|
+
end
|
|
349
|
+
end
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
-- Registry for enabled effects (effects that emit continuously)
|
|
353
|
+
type EnabledEffectConfig = {
|
|
354
|
+
check: (obj: Instance) -> boolean,
|
|
355
|
+
emit: (obj: Instance, scope: types.scope, shared_part_cache: any) -> (),
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
emitters.enabled_registry = {
|
|
359
|
+
mesh = {
|
|
360
|
+
check = function(obj: Instance)
|
|
361
|
+
return utility.isMeshVFX(obj)
|
|
362
|
+
end,
|
|
363
|
+
emit = function(obj: Instance, scope: types.scope, shared_part_cache: any)
|
|
364
|
+
emitters.mesh(obj, scope, shared_part_cache, 1, true)
|
|
365
|
+
end,
|
|
366
|
+
},
|
|
367
|
+
|
|
368
|
+
bezier = {
|
|
369
|
+
check = function(obj: Instance)
|
|
370
|
+
return obj:HasTag(utility.BEZIER_TAG)
|
|
371
|
+
end,
|
|
372
|
+
emit = function(obj: Instance, scope: types.scope, shared_part_cache: any)
|
|
373
|
+
emitters.bezier(obj, scope, true)
|
|
374
|
+
end,
|
|
375
|
+
},
|
|
376
|
+
|
|
377
|
+
lightning = {
|
|
378
|
+
check = function(obj: Instance)
|
|
379
|
+
return obj:HasTag(utility.LIGHTNING_TAG)
|
|
380
|
+
end,
|
|
381
|
+
emit = function(obj: Instance, scope: types.scope, shared_part_cache: any)
|
|
382
|
+
emitters.lightning(obj, scope, true)
|
|
383
|
+
end,
|
|
384
|
+
},
|
|
385
|
+
} :: { [string]: EnabledEffectConfig }
|
|
386
|
+
|
|
387
|
+
return emitters
|