wowlib 0.0.0
Read & write World of Warcraft client files — a C++26 core
Loading...
Searching...
No Matches
effects.hpp
Go to the documentation of this file.
1#pragma once
2
8
9#include <array>
10#include <cstdint>
11#include <string>
12#include <vector>
13
14#include <welder/vocabulary.hpp>
15
16#include <wowlib/core/lang.hpp>
21
27 struct [[
28 =welder::weld,
29 =welder::weld_as("M2Ribbon"),
31 =welder::doc(R"(
32 One ribbon emitter. Abstract over the client version; construct a concrete
33 version with M2Ribbon.ForVersion / for_version.)")
34 ]] M2RibbonBase {
35 // The concretes default operator== — the base must be comparable too.
36 bool operator==(const M2RibbonBase&) const = default;
37 };
38
39 /** The version-agnostic base of every M2Particle<V> (welded as "M2Particle").
40 Bindings-only, like every *Base: it gives the per-version classes a
41 common welded supertype, so the family surface hoists their shared
42 members and containers of them carry a base-typed live view. */
43 struct [[
44 =welder::weld,
45 =welder::weld_as("M2Particle"),
47 =welder::doc(R"(
48 One particle emitter. Abstract over the client version; construct a concrete
49 version with M2Particle.ForVersion / for_version.)")
51 // The concretes default operator== — the base must be comparable too.
52 bool operator==(const M2ParticleBase&) const = default;
53 };
55 namespace detail {
56 // The annotated era layouts; instantiate through the canonicalizing
57 // aliases below, never directly.
58 template <ClientVersion V>
59 struct [[
60 =welder::weld,
61 =welder::doc(
62 "A ribbon (trail) emitter; the priority/color-index tail exists "
63 "WotLK+.")
65 [[=welder::doc("Always -1 in known files.")]]
66 std::uint32_t ribbonId = 0xFFFFFFFF;
67 [[=welder::doc("The bone the ribbon trails from.")]]
68 std::uint32_t boneIndex = 0;
69 [[=welder::doc("Relative to that bone.")]]
71 [[=welder::doc("Into the model's textures.")]]
72 std::vector<std::uint16_t> textureIndices;
73 [[=welder::doc("Into the model's materials.")]]
74 std::vector<std::uint16_t> materialIndices;
75 [[=welder::doc("RGB multiplier for the material.")]]
77 [[=welder::doc("0 transparent .. 0x7FFF opaque.")]]
79 [[=welder::doc("Ribbon width above the bone origin.")]]
81 [[=welder::doc("Ribbon width below the bone origin; do not set equal to "
82 "height_above.")]]
84 [[=welder::doc("Quad emission rate.")]]
85 float edgesPerSecond = 0;
86 [[=welder::doc("Seconds a quad stays around.")]]
87 float edgeLifetime = 0;
88 [[=welder::doc("Sinks/rises the ribbon over time.")]]
89 float gravity = 0;
90 [[=welder::doc("Flipbook tiling.")]]
91 std::uint16_t textureRows = 0;
92 [[=welder::doc("Flipbook tiling.")]]
93 std::uint16_t textureCols = 0;
94 [[=welder::doc("Animated flipbook cell index.")]]
96 [[=welder::doc("Bool track: ribbon visible.")]]
99 [[
101 =welder::doc("Render priority plane (WotLK+).")]]
102 std::int16_t priorityPlane = 0;
103
104 [[
106 =welder::doc("ParticleColor.dbc replacement-color index (WotLK+).")]]
107 std::int8_t ribbonColorIndex = 0;
108
109 [[
111 =welder::doc("Index into the texture-transform combos, applied only "
112 "under global flag 0x20000 (WotLK+).")]]
113 std::int8_t textureTransformLookupIndex = 0;
115 bool operator==(const M2Ribbon&) const = default;
116 };
117 }
118
122 template <ClientVersion V>
123 using M2Ribbon = detail::M2Ribbon<canonicalVersion(V, M2TrackPivots, M2Versions)>;
124
126 struct [[
127 =welder::weld,
128 =welder::doc("A 2D vector of 6.9 fixed-point values (raw u16 storage).")
130 [[=welder::doc("Raw 6.9 fixed-point x component.")]]
131 std::uint16_t x = 0;
132 [[=welder::doc("Raw 6.9 fixed-point y component.")]]
133 std::uint16_t y = 0;
134
135 bool operator==(const M2Vec2FP69&) const = default;
136 };
138 static_assert(sizeof(M2Vec2FP69) == 4);
140 namespace detail {
141 // The annotated era layouts; instantiate through the canonicalizing
142 // aliases below, never directly.
143 template <ClientVersion V>
144 struct M2Particle;
146 template <ClientVersion V> requires (V < M2CompressedBones)
147 struct [[
148 =welder::weld,
149 =welder::doc(
150 "A particle emitter, vanilla layout: wide u16 blending/emitter header, "
151 "static color/scale/UV ramps, a single spin value.")
153 [[=welder::doc("Always -1 in known files.")]]
154 std::uint32_t particleId = 0xFFFFFFFF;
155 [[=welder::doc("See wowdev's particle flag table.")]]
156 std::uint32_t flags = 0;
157 [[=welder::doc("Relative to the bone.")]]
159 [[=welder::doc("The bone the emitter attaches to.")]]
160 std::uint16_t boneId = 0;
161 [[=welder::doc("Into the model's textures.")]]
162 std::uint16_t textureId = 0;
163 [[=welder::doc("Spawns model particles when set.")]]
164 std::string geometryModelFilename;
165 [[=welder::doc("Child emitters come from this model.")]]
166 std::string recursionModelFilename;
167 [[=welder::doc("Blend mode; see wowdev's blending-type table.")]]
168 std::uint16_t blendingType = 0;
169 [[=welder::doc("1 plane, 2 sphere, 3 spline, 4 bone.")]]
170 std::uint16_t emitterType = 0;
171 [[=welder::doc("Render type; in practice implied by flags and model.")]]
172 std::uint8_t particleType = 0;
173 [[=welder::doc("0 head, 1 tail, 2 both.")]]
174 std::uint8_t headOrTail = 0;
175 [[=welder::doc("Render priority plane.")]]
176 std::int16_t priorityPlane = 0;
177 [[=welder::doc("Flipbook tiling.")]]
178 std::uint16_t rows = 0;
179 [[=welder::doc("Flipbook tiling.")]]
180 std::uint16_t columns = 0;
181 [[=welder::doc("Base emission velocity.")]]
183 [[=welder::doc("Random emission-speed variation (0..1).")]]
185 [[=welder::doc("Max polar angle (0..pi): of the initial velocity for "
186 "plane, of the position for sphere emitters.")]]
188 [[=welder::doc("Max azimuth angle (0..2*pi): of the initial velocity "
189 "for plane, of the position for sphere emitters.")]]
191 [[=welder::doc("Gravity; a compressed direction vector under the "
192 "CompressedGravity flag.")]]
194 [[=welder::doc("Seconds each particle stays alive.")]]
196 [[=welder::doc("Particles emitted per second.")]]
198 [[=welder::doc("Plane: emission area width; sphere: max radius.")]]
200 [[=welder::doc("Plane: emission area length; sphere: min radius.")]]
202 [[=welder::doc("If > 0, initial velocity points from (0, 0, z_source) "
203 "to the spawn point.")]]
205 [[=welder::doc("Parametric middle of the lifespan.")]]
206 float midPoint = 0;
207 [[=welder::doc("Start/middle/end BGRA multiply.")]]
208 std::array<CImVector, 3> colorValues{};
209 [[=welder::doc("Start/middle/end scale.")]]
210 std::array<float, 3> scaleValues{};
211 [[=welder::doc("Head flipbook cells, first half of life "
212 "(start/middle/end).")]]
213 std::array<std::uint16_t, 3> lifespanUvAnim{};
214 [[=welder::doc("Head flipbook cells, second half of life "
215 "(start/middle/end).")]]
216 std::array<std::uint16_t, 3> decayUvAnim{};
217 [[=welder::doc("Tail flipbook cells, first half of life (start/end).")]]
218 std::array<std::int16_t, 2> tailUvAnim{};
219 [[=welder::doc("Tail flipbook cells, second half of life (start/end).")]]
220 std::array<std::int16_t, 2> tailDecayUvAnim{};
221 [[=welder::doc("Multiplier to the computed tail length.")]]
222 float tailLength = 0;
223 [[=welder::doc("Blinking speed.")]]
224 float twinkleSpeed = 0;
225 [[=welder::doc("Fraction of the time visible (1.0 = always).")]]
226 float twinklePercent = 0;
227 [[=welder::doc("Min/max random scale variation.")]]
229 [[=welder::doc("Scales velocity inherited from the parent particle.")]]
230 float inheritVelocityScale = 0;
231 [[=welder::doc("Speed is multiplied by exp(-drag * t).")]]
232 float drag = 0;
233 [[=welder::doc("1.0 = one full turn over the lifetime.")]]
234 float spin = 0;
235 [[=welder::doc("Angular velocity bounds (model particles).")]]
236 M2Box tumble{};
237 [[=welder::doc("Static wind, unless DynamicWind flag.")]]
238 C3Vector windVector{};
239 [[=welder::doc("Undocumented; paired with the static wind vector.")]]
240 float windTime = 0;
241 [[=welder::doc("Emitter-follow ramp: at this emitter speed particles "
242 "follow by follow_scale1.")]]
243 float followSpeed1 = 0;
244 [[=welder::doc("Fraction of emitter motion applied at follow_speed1.")]]
245 float followScale1 = 0;
246 [[=welder::doc("Second point of the emitter-follow ramp.")]]
247 float followSpeed2 = 0;
248 [[=welder::doc("Fraction of emitter motion applied at follow_speed2.")]]
249 float followScale2 = 0;
250 [[=welder::doc("Spline emitter path.")]]
251 std::vector<C3Vector> splinePoints;
252 [[=welder::doc("Bool track: emitter active.")]]
254
255 bool operator==(const M2Particle&) const = default;
256 };
257
258 template <ClientVersion V> requires (V >= M2CompressedBones && V < M2PerSequenceTimelines)
259 struct [[
260 =welder::weld,
261 =welder::doc(
262 "A particle emitter, TBC layout: byte-packed blending/emitter beside "
263 "the ParticleColor.dbc index; ramps still static.")
265 [[=welder::doc("Always -1 in known files.")]]
266 std::uint32_t particleId = 0xFFFFFFFF;
267 [[=welder::doc("See wowdev's particle flag table.")]]
268 std::uint32_t flags = 0;
269 [[=welder::doc("Relative to the bone.")]]
270 C3Vector position{};
271 [[=welder::doc("The bone the emitter attaches to.")]]
272 std::uint16_t boneId = 0;
273 [[=welder::doc("Into the model's textures.")]]
274 std::uint16_t textureId = 0;
275 [[=welder::doc("Spawns model particles when set.")]]
276 std::string geometryModelFilename;
277 [[=welder::doc("Child emitters come from this model.")]]
278 std::string recursionModelFilename;
279 [[=welder::doc("Blend mode; see wowdev's blending-type table.")]]
280 std::uint8_t blendingType = 0;
281 [[=welder::doc("1 plane, 2 sphere, 3 spline, 4 bone.")]]
282 std::uint8_t emitterType = 0;
283 [[=welder::doc("ParticleColor.dbc row selector (0/11/12/13).")]]
284 std::uint16_t particleColorIndex = 0;
285 [[=welder::doc("Render type; in practice implied by flags and model.")]]
286 std::uint8_t particleType = 0;
287 [[=welder::doc("0 head, 1 tail, 2 both.")]]
288 std::uint8_t headOrTail = 0;
289 [[=welder::doc("Render priority plane.")]]
290 std::int16_t priorityPlane = 0;
291 [[=welder::doc("Flipbook tiling.")]]
292 std::uint16_t rows = 0;
293 [[=welder::doc("Flipbook tiling.")]]
294 std::uint16_t columns = 0;
295 [[=welder::doc("Base emission velocity.")]]
296 record::M2Track<float, V> emissionSpeed{};
297 [[=welder::doc("Random emission-speed variation (0..1).")]]
298 record::M2Track<float, V> speedVariation{};
299 [[=welder::doc("Max polar angle (0..pi): of the initial velocity for "
300 "plane, of the position for sphere emitters.")]]
301 record::M2Track<float, V> verticalRange{};
302 [[=welder::doc("Max azimuth angle (0..2*pi): of the initial velocity "
303 "for plane, of the position for sphere emitters.")]]
304 record::M2Track<float, V> horizontalRange{};
305 [[=welder::doc("Gravity; a compressed direction vector under the "
306 "CompressedGravity flag.")]]
308 [[=welder::doc("Seconds each particle stays alive.")]]
309 record::M2Track<float, V> lifespan{};
310 [[=welder::doc("Particles emitted per second.")]]
311 record::M2Track<float, V> emissionRate{};
312 [[=welder::doc("Plane: emission area width; sphere: max radius.")]]
313 record::M2Track<float, V> emissionAreaWidth{};
314 [[=welder::doc("Plane: emission area length; sphere: min radius.")]]
315 record::M2Track<float, V> emissionAreaLength{};
316 [[=welder::doc("If > 0, initial velocity points from (0, 0, z_source) "
317 "to the spawn point.")]]
319 [[=welder::doc("Parametric middle of the lifespan.")]]
320 float midPoint = 0;
321 [[=welder::doc("Start/middle/end BGRA multiply.")]]
322 std::array<CImVector, 3> colorValues{};
323 [[=welder::doc("Start/middle/end scale.")]]
324 std::array<float, 3> scaleValues{};
325 [[=welder::doc("Head flipbook cells, first half of life "
326 "(start/middle/end).")]]
327 std::array<std::uint16_t, 3> lifespanUvAnim{};
328 [[=welder::doc("Head flipbook cells, second half of life "
329 "(start/middle/end).")]]
330 std::array<std::uint16_t, 3> decayUvAnim{};
331 [[=welder::doc("Tail flipbook cells, first half of life (start/end).")]]
332 std::array<std::int16_t, 2> tailUvAnim{};
333 [[=welder::doc("Tail flipbook cells, second half of life (start/end).")]]
334 std::array<std::int16_t, 2> tailDecayUvAnim{};
335 [[=welder::doc("Multiplier to the computed tail length.")]]
336 float tailLength = 0;
337 [[=welder::doc("Blinking speed.")]]
338 float twinkleSpeed = 0;
339 [[=welder::doc("Fraction of the time visible (1.0 = always).")]]
340 float twinklePercent = 0;
341 [[=welder::doc("Min/max random scale variation.")]]
342 CRange twinkleScale{};
343 [[=welder::doc("Scales velocity inherited from the parent particle.")]]
344 float inheritVelocityScale = 0;
345 [[=welder::doc("Speed is multiplied by exp(-drag * t).")]]
346 float drag = 0;
347 [[=welder::doc("1.0 = one full turn over the lifetime.")]]
348 float spin = 0;
349 [[=welder::doc("Angular velocity bounds (model particles).")]]
350 M2Box tumble{};
351 [[=welder::doc("Static wind, unless DynamicWind flag.")]]
352 C3Vector windVector{};
353 [[=welder::doc("Undocumented; paired with the static wind vector.")]]
354 float windTime = 0;
355 [[=welder::doc("Emitter-follow ramp: at this emitter speed particles "
356 "follow by follow_scale1.")]]
357 float followSpeed1 = 0;
358 [[=welder::doc("Fraction of emitter motion applied at follow_speed1.")]]
359 float followScale1 = 0;
360 [[=welder::doc("Second point of the emitter-follow ramp.")]]
361 float followSpeed2 = 0;
362 [[=welder::doc("Fraction of emitter motion applied at follow_speed2.")]]
363 float followScale2 = 0;
364 [[=welder::doc("Spline emitter path.")]]
365 std::vector<C3Vector> splinePoints;
366 [[=welder::doc("Bool track: emitter active.")]]
368
369 bool operator==(const M2Particle&) const = default;
370 };
371
372 template <ClientVersion V> requires (V >= M2PerSequenceTimelines && V < M2MultitexParticles)
373 struct [[
374 =welder::weld,
375 =welder::doc(
376 "A particle emitter, WotLK-era layout (476 bytes): FBlock ramps, "
377 "lifespan/emission variation, four spin fields.")
379 [[=welder::doc("Always -1 in known files.")]]
380 std::uint32_t particleId = 0xFFFFFFFF;
381 [[=welder::doc("See wowdev's particle flag table.")]]
382 std::uint32_t flags = 0;
383 [[=welder::doc("Relative to the bone.")]]
385 [[=welder::doc("The bone the emitter attaches to.")]]
386 std::uint16_t boneId = 0;
387 [[=welder::doc("Into the model's textures.")]]
388 std::uint16_t textureId = 0;
389 [[=welder::doc("Spawns model particles when set.")]]
390 std::string geometryModelFilename;
391 [[=welder::doc("Child emitters come from this model.")]]
392 std::string recursionModelFilename;
393 [[=welder::doc("Blend mode; see wowdev's blending-type table.")]]
394 std::uint8_t blendingType = 0;
395 [[=welder::doc("1 plane, 2 sphere, 3 spline, 4 bone.")]]
396 std::uint8_t emitterType = 0;
397 [[=welder::doc("ParticleColor.dbc row selector (0/11/12/13).")]]
398 std::uint16_t particleColorIndex = 0;
399 [[=welder::doc("Render type; in practice implied by flags and model.")]]
400 std::uint8_t particleType = 0;
401 [[=welder::doc("0 head, 1 tail, 2 both.")]]
402 std::uint8_t headOrTail = 0;
403 [[=welder::doc("Render priority plane.")]]
404 std::int16_t priorityPlane = 0;
405 [[=welder::doc("Flipbook tiling.")]]
406 std::uint16_t rows = 0;
407 [[=welder::doc("Flipbook tiling.")]]
408 std::uint16_t columns = 0;
409 [[=welder::doc("Base emission velocity.")]]
411 [[=welder::doc("Random emission-speed variation (0..1).")]]
412 record::M2Track<float, V> speedVariation{};
413 [[=welder::doc("Max polar angle (0..pi): of the initial velocity for "
414 "plane, of the position for sphere emitters.")]]
416 [[=welder::doc("Max azimuth angle (0..2*pi): of the initial velocity "
417 "for plane, of the position for sphere emitters.")]]
419 [[=welder::doc("Gravity; a compressed direction vector under the "
420 "CompressedGravity flag.")]]
422 [[=welder::doc("Seconds each particle stays alive.")]]
423 record::M2Track<float, V> lifespan{};
424 [[=welder::doc("+ lifespan_variation * random(-1, 1).")]]
425 float lifespanVariation = 0;
426 [[=welder::doc("Particles emitted per second.")]]
427 record::M2Track<float, V> emissionRate{};
428 [[=welder::doc("+ emission_rate_variation * random(-1, 1), rerolled per "
429 "update.")]]
430 float emissionRateVariation = 0;
431 [[=welder::doc("Plane: emission area width; sphere: max radius.")]]
432 record::M2Track<float, V> emissionAreaWidth{};
433 [[=welder::doc("Plane: emission area length; sphere: min radius.")]]
434 record::M2Track<float, V> emissionAreaLength{};
435 [[=welder::doc("If > 0, initial velocity points from (0, 0, z_source) "
436 "to the spawn point.")]]
438 [[=welder::doc("Usually 3 keys: start/middle/end.")]]
440 [[=welder::doc("Opacity ramp: 0 transparent .. 0x7FFF opaque.")]]
441 FBlock<fixed16> alphaTrack{};
442 [[=welder::doc("Particle size ramp.")]]
443 FBlock<C2Vector> scaleTrack{};
444 [[=welder::doc("Random per-particle scale variation.")]]
445 C2Vector scaleVary{};
446 [[=welder::doc("Head flipbook cell ramp.")]]
447 FBlock<std::uint16_t> headUvAnim{};
448 [[=welder::doc("Tail flipbook cell ramp.")]]
449 FBlock<std::uint16_t> tailUvAnim{};
450 [[=welder::doc("Multiplier to the computed tail length.")]]
451 float tailLength = 0;
452 [[=welder::doc("Blinking speed.")]]
453 float twinkleSpeed = 0;
454 [[=welder::doc("Fraction of the time visible (1.0 = always).")]]
455 float twinklePercent = 0;
456 [[=welder::doc("Min/max random scale variation.")]]
457 CRange twinkleScale{};
458 [[=welder::doc("Scales velocity inherited from the parent particle.")]]
459 float inheritVelocityScale = 0;
460 [[=welder::doc("Speed is multiplied by exp(-drag * t).")]]
461 float drag = 0;
462 [[=welder::doc("Initial quad rotation.")]]
463 float baseSpin = 0;
464 [[=welder::doc("Random variation of base_spin.")]]
465 float baseSpinVariation = 0;
466 [[=welder::doc("Quad rotation per second.")]]
467 float spinSpeed = 0;
468 [[=welder::doc("Random variation of spin_speed.")]]
469 float spinSpeedVariation = 0;
470 [[=welder::doc("Angular velocity bounds (model particles).")]]
471 M2Box tumble{};
472 [[=welder::doc("Static wind, unless DynamicWind flag.")]]
473 C3Vector windVector{};
474 [[=welder::doc("Undocumented; paired with the static wind vector.")]]
475 float windTime = 0;
476 [[=welder::doc("Emitter-follow ramp: at this emitter speed particles "
477 "follow by follow_scale1.")]]
478 float followSpeed1 = 0;
479 [[=welder::doc("Fraction of emitter motion applied at follow_speed1.")]]
480 float followScale1 = 0;
481 [[=welder::doc("Second point of the emitter-follow ramp.")]]
482 float followSpeed2 = 0;
483 [[=welder::doc("Fraction of emitter motion applied at follow_speed2.")]]
484 float followScale2 = 0;
485 [[=welder::doc("Spline emitter path.")]]
486 std::vector<C3Vector> splinePoints;
487 [[=welder::doc("Bool track: emitter active.")]]
489
490 bool operator==(const M2Particle&) const = default;
491 };
492
493 template <ClientVersion V> requires (V >= M2MultitexParticles)
494 struct [[
495 =welder::weld,
496 =welder::doc(
497 "A particle emitter (Cata+, 492 bytes): multi-textured — packed "
498 "texture ids, multiTexScale, trailing scroll parameters.")
499 ]] M2Particle<V> : M2ParticleBase {
500 [[=welder::doc("Always -1 in known files.")]]
501 std::uint32_t particleId = 0xFFFFFFFF;
502 [[=welder::doc("See wowdev's particle flag table.")]]
503 std::uint32_t flags = 0;
504 [[=welder::doc("Relative to the bone.")]]
505 C3Vector position{};
506 [[=welder::doc("The bone the emitter attaches to.")]]
507 std::uint16_t boneId = 0;
508 [[=welder::doc("3x5-bit texture ids under the MultiTexture flag.")]]
509 std::uint16_t textureId = 0;
510 [[=welder::doc("Spawns model particles when set.")]]
511 std::string geometryModelFilename;
512 [[=welder::doc("Child emitters come from this model.")]]
513 std::string recursionModelFilename;
514 [[=welder::doc("Blend mode; see wowdev's blending-type table.")]]
515 std::uint8_t blendingType = 0;
516 [[=welder::doc("1 plane, 2 sphere, 3 spline, 4 bone.")]]
517 std::uint8_t emitterType = 0;
518 [[=welder::doc("ParticleColor.dbc row selector (0/11/12/13).")]]
519 std::uint16_t particleColorIndex = 0;
520 [[=welder::doc("2.5 fixed-point per extra layer.")]]
521 std::array<std::int8_t, 2> multiTexScale{};
522 [[=welder::doc("Render priority plane.")]]
523 std::int16_t priorityPlane = 0;
524 [[=welder::doc("Flipbook tiling.")]]
525 std::uint16_t rows = 0;
526 [[=welder::doc("Flipbook tiling.")]]
527 std::uint16_t columns = 0;
528 [[=welder::doc("Base emission velocity.")]]
529 record::M2Track<float, V> emissionSpeed{};
530 [[=welder::doc("Random emission-speed variation (0..1).")]]
531 record::M2Track<float, V> speedVariation{};
532 [[=welder::doc("Max polar angle (0..pi): of the initial velocity for "
533 "plane, of the position for sphere emitters.")]]
534 record::M2Track<float, V> verticalRange{};
535 [[=welder::doc("Max azimuth angle (0..2*pi): of the initial velocity "
536 "for plane, of the position for sphere emitters.")]]
537 record::M2Track<float, V> horizontalRange{};
538 [[=welder::doc("Gravity; a compressed direction vector under the "
539 "CompressedGravity flag.")]]
541 [[=welder::doc("Seconds each particle stays alive.")]]
542 record::M2Track<float, V> lifespan{};
543 [[=welder::doc("+ lifespan_variation * random(-1, 1).")]]
544 float lifespanVariation = 0;
545 [[=welder::doc("Particles emitted per second.")]]
546 record::M2Track<float, V> emissionRate{};
547 [[=welder::doc("+ emission_rate_variation * random(-1, 1), rerolled per "
548 "update.")]]
549 float emissionRateVariation = 0;
550 [[=welder::doc("Plane: emission area width; sphere: max radius.")]]
552 [[=welder::doc("Plane: emission area length; sphere: min radius.")]]
554 [[=welder::doc("If > 0, initial velocity points from (0, 0, z_source) "
555 "to the spawn point.")]]
557 [[=welder::doc("Usually 3 keys: start/middle/end.")]]
558 FBlock<C3Vector> colorTrack{};
559 [[=welder::doc("Opacity ramp: 0 transparent .. 0x7FFF opaque.")]]
560 FBlock<fixed16> alphaTrack{};
561 [[=welder::doc("Particle size ramp.")]]
562 FBlock<C2Vector> scaleTrack{};
563 [[=welder::doc("Random per-particle scale variation.")]]
564 C2Vector scaleVary{};
565 [[=welder::doc("Head flipbook cell ramp.")]]
566 FBlock<std::uint16_t> headUvAnim{};
567 [[=welder::doc("Tail flipbook cell ramp.")]]
568 FBlock<std::uint16_t> tailUvAnim{};
569 [[=welder::doc("Multiplier to the computed tail length.")]]
570 float tailLength = 0;
571 [[=welder::doc("Blinking speed.")]]
572 float twinkleSpeed = 0;
573 [[=welder::doc("Fraction of the time visible (1.0 = always).")]]
574 float twinklePercent = 0;
575 [[=welder::doc("Min/max random scale variation.")]]
576 CRange twinkleScale{};
577 [[=welder::doc("Scales velocity inherited from the parent particle.")]]
578 float inheritVelocityScale = 0;
579 [[=welder::doc("Speed is multiplied by exp(-drag * t).")]]
580 float drag = 0;
581 [[=welder::doc("Initial quad rotation.")]]
582 float baseSpin = 0;
583 [[=welder::doc("Random variation of base_spin.")]]
584 float baseSpinVariation = 0;
585 [[=welder::doc("Quad rotation per second.")]]
586 float spinSpeed = 0;
587 [[=welder::doc("Random variation of spin_speed.")]]
588 float spinSpeedVariation = 0;
589 [[=welder::doc("Angular velocity bounds (model particles).")]]
590 M2Box tumble{};
591 [[=welder::doc("Static wind, unless DynamicWind flag.")]]
592 C3Vector windVector{};
593 [[=welder::doc("Undocumented; paired with the static wind vector.")]]
594 float windTime = 0;
595 [[=welder::doc("Emitter-follow ramp: at this emitter speed particles "
596 "follow by follow_scale1.")]]
597 float followSpeed1 = 0;
598 [[=welder::doc("Fraction of emitter motion applied at follow_speed1.")]]
599 float followScale1 = 0;
600 [[=welder::doc("Second point of the emitter-follow ramp.")]]
601 float followSpeed2 = 0;
602 [[=welder::doc("Fraction of emitter motion applied at follow_speed2.")]]
603 float followScale2 = 0;
604 [[=welder::doc("Spline emitter path.")]]
605 std::vector<C3Vector> splinePoints;
606 [[=welder::doc("Bool track: emitter active.")]]
608 [[=welder::doc("Per extra layer.")]]
609 std::array<M2Vec2FP69, 2> multiTexScrollMid{};
610 [[=welder::doc("Per extra layer.")]]
611 std::array<M2Vec2FP69, 2> multiTexScrollRange{};
612
613 bool operator==(const M2Particle&) const = default;
614 };
615 }
616
620 template <ClientVersion V>
622}
Client version identity, the flavor axis that separates a client's CONTENT version from the engine ge...
The chunk annotation vocabulary format entities declare their binary mapping with.
Binding-language identities welder's core does not name.
#define WOWLIB_CS_FAMILY_SURFACE
The C# rod's family-surface opt-in, spellable in every build.
Definition lang.hpp:44
The M2 version vocabulary: the layout pivots record/entity partial specializations key on,...
M2 body record structs (sequences, bones, tracks, textures, cameras, emitters) and their flag enums.
Definition bone.hpp:17
detail::M2Track< T, canonicalVersion(V, M2TrackPivots, M2Versions)> M2Track
An animation track for value type T — the canonicalizing face of detail::M2Track: every client versio...
Definition track.hpp:498
detail::M2Ribbon< canonicalVersion(V, M2TrackPivots, M2Versions)> M2Ribbon
A ribbon emitter — the canonicalizing face of detail::M2Ribbon (the WotLK trailing fields and the emb...
Definition effects.hpp:106
detail::M2Particle< canonicalVersion(V, M2ParticlePivots, M2Versions)> M2Particle
A particle emitter — the canonicalizing face of detail::M2Particle (M2ParticlePivots: TBC's byte-pack...
Definition effects.hpp:560
constexpr std::array M2TrackPivots
Track-shaped records (M2Track, M2TrackBase, and every record whose only version axis is the tracks it...
constexpr ClientVersion M2PerSequenceTimelines
WotLK (v264): every M2Track nests one timestamp/value array per sequence (the vanilla single timeline...
constexpr ClientVersion M2MultitexParticles
cata (v272): particles turn multi-textured (492-byte record: texture id bitfield, multiTexScale repla...
constexpr std::array M2ParticlePivots
M2Particle: byte-packed blending/emitter types at TBC, FBlock ramps and spins at WotLK,...
constexpr ClientVersion M2CompressedBones
TBC (v260+): bone rotations become compressed M2CompQuat (vanilla stored raw C4Quaternion),...
constexpr std::array M2Versions
The versions M2 is instantiated (and welded) for: every targeted last-minor-of-major release,...
constexpr ClientVersion canonicalVersion(ClientVersion v, std::span< const ClientVersion > pivots, std::span< const ClientVersion > grid)
The canonical version v collapses to: the FIRST grid version in v's range.
consteval detail::SinceSpec since(ClientVersion v)
Restrict a member to entity versions >= v (inclusive).
A 2D float vector: texture coordinates, UV animation speeds.
Definition types.hpp:29
A 3D float vector — the workhorse: positions, normals, rotations-as-Euler-degrees in placements.
Definition types.hpp:49
A float range: minimum and maximum.
Definition types.hpp:154
A model-space box: minimum and maximum corner vectors.
Definition track.hpp:115
The version-agnostic base of every M2Particle<V> (welded as "M2Particle").
Definition effects.hpp:42
bool operator==(const M2ParticleBase &) const =default
The version-agnostic base of every M2Ribbon<V> (welded as "M2Ribbon").
Definition effects.hpp:30
bool operator==(const M2RibbonBase &) const =default
A 2D vector of 6.9 fixed-point values (raw u16 storage).
Definition effects.hpp:110
bool operator==(const M2Vec2FP69 &) const =default
std::uint16_t x
Raw 6.9 fixed-point x component.
Definition effects.hpp:112
std::uint16_t y
Raw 6.9 fixed-point y component.
Definition effects.hpp:114
FBlock< C2Vector > scaleTrack
Particle size ramp.
Definition effects.hpp:393
std::uint32_t particleId
Always -1 in known files.
Definition effects.hpp:131
std::array< std::int16_t, 2 > tailDecayUvAnim
Tail flipbook cells, second half of life (start/end).
Definition effects.hpp:191
std::string geometryModelFilename
Spawns model particles when set.
Definition effects.hpp:141
std::uint8_t particleType
Render type; in practice implied by flags and model.
Definition effects.hpp:149
std::array< std::uint16_t, 3 > decayUvAnim
Head flipbook cells, second half of life (start/middle/end).
Definition effects.hpp:187
C2Vector scaleVary
Random per-particle scale variation.
Definition effects.hpp:395
float tailLength
Multiplier to the computed tail length.
Definition effects.hpp:193
std::uint16_t emitterType
1 plane, 2 sphere, 3 spline, 4 bone.
Definition effects.hpp:147
std::uint32_t flags
See wowdev's particle flag table.
Definition effects.hpp:133
C3Vector windVector
Static wind, unless DynamicWind flag.
Definition effects.hpp:209
CRange twinkleScale
Min/max random scale variation.
Definition effects.hpp:199
std::array< CImVector, 3 > colorValues
Start/middle/end BGRA multiply.
Definition effects.hpp:181
float followSpeed1
Emitter-follow ramp: at this emitter speed particles follow by follow_scale1.
Definition effects.hpp:213
FBlock< fixed16 > alphaTrack
Opacity ramp: 0 transparent .
Definition effects.hpp:391
std::vector< C3Vector > splinePoints
Spline emitter path.
Definition effects.hpp:221
std::string recursionModelFilename
Child emitters come from this model.
Definition effects.hpp:143
float followScale1
Fraction of emitter motion applied at follow_speed1.
Definition effects.hpp:215
float windTime
Undocumented; paired with the static wind vector.
Definition effects.hpp:211
float spinSpeedVariation
Random variation of spin_speed.
Definition effects.hpp:419
float drag
Speed is multiplied by exp(-drag * t).
Definition effects.hpp:203
float twinklePercent
Fraction of the time visible (1.0 = always).
Definition effects.hpp:197
record::M2Track< float, V > emissionRate
Particles emitted per second.
Definition effects.hpp:171
record::M2Track< float, V > emissionAreaWidth
Plane: emission area width; sphere: max radius.
Definition effects.hpp:173
float midPoint
Parametric middle of the lifespan.
Definition effects.hpp:179
std::array< std::int8_t, 2 > multiTexScale
2.5 fixed-point per extra layer.
Definition effects.hpp:466
std::uint8_t headOrTail
0 head, 1 tail, 2 both.
Definition effects.hpp:151
float spin
1.0 = one full turn over the lifetime.
Definition effects.hpp:205
float followScale2
Fraction of emitter motion applied at follow_speed2.
Definition effects.hpp:219
record::M2Track< float, V > lifespan
Seconds each particle stays alive.
Definition effects.hpp:169
record::M2Track< float, V > gravity
Gravity; a compressed direction vector under the CompressedGravity flag.
Definition effects.hpp:167
M2Box tumble
Angular velocity bounds (model particles).
Definition effects.hpp:207
std::int16_t priorityPlane
Render priority plane.
Definition effects.hpp:153
FBlock< C3Vector > colorTrack
Usually 3 keys: start/middle/end.
Definition effects.hpp:389
record::M2Track< float, V > emissionAreaLength
Plane: emission area length; sphere: min radius.
Definition effects.hpp:175
record::M2Track< float, V > verticalRange
Max polar angle (0..pi): of the initial velocity for plane, of the position for sphere emitters.
Definition effects.hpp:163
bool operator==(const M2Particle &) const =default
record::M2Track< float, V > zSource
If > 0, initial velocity points from (0, 0, z_source) to the spawn point.
Definition effects.hpp:177
std::uint16_t particleColorIndex
ParticleColor.dbc row selector (0/11/12/13).
Definition effects.hpp:250
std::array< std::int16_t, 2 > tailUvAnim
Tail flipbook cells, first half of life (start/end).
Definition effects.hpp:189
std::array< M2Vec2FP69, 2 > multiTexScrollRange
Per extra layer.
Definition effects.hpp:550
record::M2Track< float, V > emissionSpeed
Base emission velocity.
Definition effects.hpp:159
std::uint16_t textureId
Into the model's textures.
Definition effects.hpp:139
std::uint16_t blendingType
Blend mode; see wowdev's blending-type table.
Definition effects.hpp:145
std::uint16_t boneId
The bone the emitter attaches to.
Definition effects.hpp:137
float inheritVelocityScale
Scales velocity inherited from the parent particle.
Definition effects.hpp:201
std::array< M2Vec2FP69, 2 > multiTexScrollMid
Per extra layer.
Definition effects.hpp:548
record::M2Track< std::uint8_t, V > enabledIn
Bool track: emitter active.
Definition effects.hpp:223
FBlock< std::uint16_t > headUvAnim
Head flipbook cell ramp.
Definition effects.hpp:397
std::array< std::uint16_t, 3 > lifespanUvAnim
Head flipbook cells, first half of life (start/middle/end).
Definition effects.hpp:185
record::M2Track< float, V > speedVariation
Random emission-speed variation (0..1).
Definition effects.hpp:161
float baseSpinVariation
Random variation of base_spin.
Definition effects.hpp:415
float followSpeed2
Second point of the emitter-follow ramp.
Definition effects.hpp:217
record::M2Track< float, V > horizontalRange
Max azimuth angle (0..2*pi): of the initial velocity for plane, of the position for sphere emitters.
Definition effects.hpp:165
std::array< float, 3 > scaleValues
Start/middle/end scale.
Definition effects.hpp:183
A ribbon (trail) emitter; the priority/color-index tail exists WotLK+.
Definition effects.hpp:52
bool operator==(const M2Ribbon &) const =default
The M2 animation vocabulary (namespace wowlib::formats::m2::root::record): the small fixed-size primi...