@@ -252,12 +252,21 @@ public record EffectEntry(string Name, string Category, string? BasedOn = null)
252252 // whichever they're building an effect for.
253253 new ( "Hunter's Ring — Howling Blade (M8)" , "[RAID] Presets" ) ,
254254 new ( "Hunter's Ring — Howling Blade (M8S)" , "[RAID] Presets" ) ,
255+ // Cruiserweight tier (M9-M11)
256+ new ( "Ring Noir (M9)" , "[RAID] Presets" ) ,
257+ new ( "The X-Ring (M10)" , "[RAID] Presets" ) ,
258+ new ( "The Crown (M11)" , "[RAID] Presets" ) ,
255259 // Arcadia (M12/M12S) runs a scripted three-beat choreography in-game.
256260 // Each beat is its own preset; the harness cannot replay the per-layer
257261 // state machine, so each one is previewable in isolation.
258262 new ( "Arcadia P1 Effect 1 — Intro" , "[RAID] Presets" ) ,
259263 new ( "Arcadia P1 Effect 2 — Post-Flash" , "[RAID] Presets" ) ,
260264 new ( "Arcadia P2 (M12)" , "[RAID] Presets" ) ,
265+ // Other zones with raid effects
266+ new ( "Hell on Rails" , "[RAID] Presets" ) ,
267+ new ( "The Ageless Necropolis / Lightless Abyss" , "[RAID] Presets" ) ,
268+ new ( "Recollection" , "[RAID] Presets" ) ,
269+ new ( "The Unmaking" , "[RAID] Presets" ) ,
261270 ] ;
262271
263272 public static EffectEntry [ ] WeatherPresets { get ; } =
@@ -275,6 +284,15 @@ public record EffectEntry(string Name, string Category, string? BasedOn = null)
275284 new ( "Astromagnetic Storm" , "[WEATHER] Presets" ) ,
276285 new ( "Umbral Static" , "[WEATHER] Presets" ) ,
277286 new ( "Everlasting Light" , "[WEATHER] Presets" ) ,
287+ // 7.x weather animations
288+ new ( "Atmospheric Phantasms" , "[WEATHER] Presets" ) ,
289+ new ( "Illusory Disturbances" , "[WEATHER] Presets" ) ,
290+ new ( "Gravitational Flux" , "[WEATHER] Presets" ) ,
291+ new ( "Meteor Showers" , "[WEATHER] Presets" ) ,
292+ new ( "Sporing Mist" , "[WEATHER] Presets" ) ,
293+ new ( "Annealing Winds" , "[WEATHER] Presets" ) ,
294+ new ( "Glass Storms" , "[WEATHER] Presets" ) ,
295+ new ( "Bubble Bloom" , "[WEATHER] Presets" ) ,
278296 ] ;
279297
280298 public ObservableCollection < EffectEntry > AllEffects { get ; } = new (
@@ -743,6 +761,45 @@ private void ApplyDefaults(EffectEntry effect)
743761 ColorBase = AvColors . Black ;
744762 SetColors ( ToAv ( 255 , 0 , 4 ) , ToAv ( 93 , 0 , 255 ) , ToAv ( 255 , 117 , 0 ) , ToAv ( 249 , 255 , 0 ) ) ;
745763 break ;
764+ // Cruiserweight tier (M9-M11) — defaults mirror RaidEffectProcessor.ApplyRaidEffect
765+ case "Ring Noir (M9)" :
766+ ParamBpm = 47 ; ParamBeamWidth = 2.0 ;
767+ ColorBase = AvColors . Black ;
768+ SetColors ( ToAv ( 220 , 20 , 60 ) , ToAv ( 120 , 0 , 30 ) ) ;
769+ break ;
770+ case "The X-Ring (M10)" :
771+ ParamBpm = 180 ; ParamBpmSpeed = "/4" ; ParamPulseRadius = 6.0 ; ParamFadeWidth = 2.0 ;
772+ ColorBase = AvColors . Black ;
773+ SetColors ( ToAv ( 255 , 200 , 0 ) , ToAv ( 255 , 255 , 255 ) ) ;
774+ break ;
775+ case "The Crown (M11)" :
776+ ParamBpm = 135 ; ParamBpmSpeed = "/4" ; ParamWedgeDegrees = 180 ;
777+ ColorBase = AvColors . Black ;
778+ SetColors ( ToAv ( 255 , 215 , 0 ) , ToAv ( 255 , 80 , 0 ) , ToAv ( 255 , 0 , 120 ) , ToAv ( 180 , 0 , 255 ) ) ;
779+ break ;
780+ // Other raid zones
781+ case "Hell on Rails" :
782+ ParamBpm = 110 ; ParamBpmSpeed = "/2" ; ParamFlickerOpacity = 0.5 ; ParamFlickerSpeed = 8 ;
783+ ParamMatrixDir = "Left" ;
784+ ColorBase = AvColors . Black ;
785+ SetColors ( ToAv ( 0 , 255 , 120 ) , ToAv ( 0 , 200 , 80 ) ) ;
786+ break ;
787+ case "The Ageless Necropolis / Lightless Abyss" :
788+ ParamBpm = 160 ; ParamBpmSpeed = "/8" ; ParamBeamWidth = 3.5 ;
789+ ParamLaserDir = "RandomDiagonal" ;
790+ ColorBase = AvColors . Black ;
791+ SetColors ( ToAv ( 180 , 180 , 220 ) , ToAv ( 120 , 80 , 200 ) , ToAv ( 80 , 200 , 200 ) , ToAv ( 220 , 220 , 255 ) ) ;
792+ break ;
793+ case "Recollection" :
794+ ParamBpm = 27 ; ParamDiagonalDir = "Random" ; ParamTextureType = "Conical" ;
795+ ColorBase = AvColors . Black ;
796+ SetColors ( ToAv ( 120 , 200 , 255 ) , ToAv ( 255 , 220 , 180 ) , ToAv ( 180 , 120 , 255 ) ) ;
797+ break ;
798+ case "The Unmaking" :
799+ ParamBpm = 175 ; ParamAccentEvery = 4 ; ParamDecay = 0.5 ;
800+ ColorBase = AvColors . Black ;
801+ SetColors ( ToAv ( 255 , 60 , 60 ) , ToAv ( 255 , 200 , 100 ) , ToAv ( 255 , 255 , 255 ) ) ;
802+ break ;
746803 case "Moon Dust (Mare Lamentorum)" :
747804 ParamInterval = 20 ; ParamFadeSpeed = 900 ;
748805 ColorBase = ToAv ( 0 , 0 , 0 ) ;
@@ -808,6 +865,47 @@ private void ApplyDefaults(EffectEntry effect)
808865 ColorBase = ToAv ( 255 , 248 , 220 ) ;
809866 SetColors ( ToAv ( 255 , 255 , 0 ) ) ;
810867 break ;
868+ // 7.x weather animations — defaults mirror ReactiveWeather.cs effect cases
869+ case "Atmospheric Phantasms" :
870+ ParamRippleSpeed = 6.0 ; ParamPulseRadius = 12.0 ; ParamSpawnInterval = 0.5 ; ParamFadeWidth = 2.0 ;
871+ ColorBase = AvColors . Black ;
872+ SetColors ( ToAv ( 80 , 200 , 255 ) , ToAv ( 180 , 120 , 255 ) ) ;
873+ break ;
874+ case "Illusory Disturbances" :
875+ ParamRippleSpeed = 6.0 ; ParamPulseRadius = 12.0 ; ParamSpawnInterval = 0.5 ; ParamFadeWidth = 2.0 ;
876+ ColorBase = AvColors . Black ;
877+ SetColors ( ToAv ( 255 , 200 , 80 ) , ToAv ( 255 , 80 , 200 ) , ToAv ( 120 , 200 , 255 ) ) ;
878+ break ;
879+ case "Gravitational Flux" :
880+ ParamBpm = 36 ; ParamBeamWidth = 2.0 ;
881+ ColorBase = AvColors . Black ;
882+ SetColors ( ToAv ( 180 , 80 , 255 ) , ToAv ( 80 , 40 , 180 ) ) ;
883+ break ;
884+ case "Meteor Showers" :
885+ ParamInterval = 20 ; ParamFadeSpeed = 900 ; ParamNumberOfLeds = 10 ;
886+ ColorBase = ToAv ( 20 , 10 , 40 ) ;
887+ SetColors ( ToAv ( 255 , 200 , 80 ) , ToAv ( 255 , 120 , 40 ) ) ;
888+ break ;
889+ case "Sporing Mist" :
890+ ParamInterval = 20 ; ParamFadeSpeed = 900 ; ParamNumberOfLeds = 10 ;
891+ ColorBase = ToAv ( 20 , 60 , 30 ) ;
892+ SetColors ( ToAv ( 180 , 255 , 120 ) , ToAv ( 120 , 200 , 80 ) ) ;
893+ break ;
894+ case "Annealing Winds" :
895+ ParamSpeed = 200 ; ParamDirection = true ;
896+ ColorBase = ToAv ( 180 , 80 , 40 ) ;
897+ SetColors ( ToAv ( 255 , 180 , 80 ) ) ;
898+ break ;
899+ case "Glass Storms" :
900+ ParamInterval = 20 ; ParamFadeSpeed = 900 ; ParamNumberOfLeds = 10 ;
901+ ColorBase = ToAv ( 120 , 140 , 160 ) ;
902+ SetColors ( ToAv ( 220 , 230 , 240 ) ) ;
903+ break ;
904+ case "Bubble Bloom" :
905+ ParamBpm = 32 ; ParamBpmSpeed = "Sync" ; ParamWedgeDegrees = 180 ;
906+ ColorBase = ToAv ( 20 , 60 , 80 ) ;
907+ SetColors ( ToAv ( 180 , 220 , 255 ) ) ;
908+ break ;
811909
812910 // Raw decorators — sensible defaults
813911 case "StarfieldDecorator" :
@@ -1271,12 +1369,79 @@ private string BuildCodeSnippet(EffectEntry effect)
12711369 $ "var pulse = new BPMCircularPulseEffect(layer, { ParamBpm } , { ResolveBeatsPerCycle ( ) } , { ParamPulseRadius } , { ParamFadeWidth } , colors, surface, baseCol);\n \n " +
12721370 "layer.Brush = new SolidColorBrush(baseCol);\n SetEffect(pulse, layer, runningEffects);" ,
12731371
1274- "Arcadia P1 Effect 2 — Post-Flash" =>
1372+ "Arcadia P1 Effect 2 — Post-Flash" or "The Unmaking" =>
12751373 $ "var baseCol = { bS } ;\n " +
12761374 $ "var colors = { arr } ;\n " +
12771375 $ "var strike = new BPMThunderstrikeEffect(layer, { ParamBpm } , { ParamAccentEvery } , { ParamDecay } , colors, surface, baseCol);\n \n " +
12781376 "layer.Brush = new SolidColorBrush(baseCol);\n SetEffect(strike, layer, runningEffects);" ,
12791377
1378+ "Ring Noir (M9)" =>
1379+ $ "var baseCol = { bS } ;\n " +
1380+ $ "var colors = { arr } ;\n " +
1381+ $ "var heartbeat = new BPMHeartbeatEffect(layer, { ParamBpm } , { ParamBeamWidth } , colors, surface, baseCol);\n \n " +
1382+ "SetEffect(heartbeat, layer, runningEffects);" ,
1383+
1384+ "The X-Ring (M10)" =>
1385+ $ "var baseCol = { bS } ;\n " +
1386+ $ "var colors = { arr } ;\n " +
1387+ $ "var pulse = new BPMCircularPulseEffect(layer, { ParamBpm } , { ResolveBeatsPerCycle ( ) } , { ParamPulseRadius } , { ParamFadeWidth } , colors, surface, baseCol);\n \n " +
1388+ "SetEffect(pulse, layer, runningEffects);" ,
1389+
1390+ "The Crown (M11)" =>
1391+ $ "var baseCol = { bS } ;\n " +
1392+ $ "var colors = { arr } ;\n " +
1393+ $ "var spinner = new BPMSpinnerEffect(layer, { ParamBpm } , { ResolveBeatsPerCycle ( ) } , { ParamWedgeDegrees } , colors, surface, baseCol);\n \n " +
1394+ "SetEffect(spinner, layer, runningEffects);" ,
1395+
1396+ "Hell on Rails" =>
1397+ $ "var baseCol = { bS } ;\n " +
1398+ $ "var colors = { arr } ;\n " +
1399+ $ "var matrix = new BPMMatrixEffect(layer, { ParamBpm } , { ResolveBeatsPerCycle ( ) } , { ParamFlickerOpacity } , { ParamFlickerSpeed } , colors, surface, MatrixEffect.MatrixDirection.{ ParamMatrixDir } , baseCol);\n \n " +
1400+ "SetEffect(matrix, layer, runningEffects);" ,
1401+
1402+ "The Ageless Necropolis / Lightless Abyss" =>
1403+ $ "var baseCol = { bS } ;\n " +
1404+ $ "var colors = { arr } ;\n " +
1405+ $ "var laser = new BPMLaserEffect(layer, { ParamBpm } , { ResolveBeatsPerCycle ( ) } , { ParamBeamWidth } , colors, surface, LaserEffect.LaserDirection.{ ParamLaserDir } , baseCol);\n \n " +
1406+ "SetEffect(laser, layer, runningEffects);" ,
1407+
1408+ "Recollection" =>
1409+ $ "var animationCol1 = { s0 } ;\n var animationCol2 = { s1 } ;\n var animationCol3 = { s2 } ;\n \n " +
1410+ "var animationGradient = new LinearGradient(\n " +
1411+ " new GradientStop(0f, animationCol1), new GradientStop(0.33f, animationCol2), new GradientStop(0.66f, animationCol3));\n \n " +
1412+ $ "var gradientMove = new MoveBPMDiagonalGradientDecorator(surface, { ParamBpm } , DiagonalDirection.{ ParamDiagonalDir } );\n \n " +
1413+ "SetRadialGradientEffect(animationGradient, gradientMove, layer, new Size(100, 100), runningEffects, masterlayer.layerID);" ,
1414+
1415+ "Atmospheric Phantasms" or "Illusory Disturbances" =>
1416+ $ "var baseCol = { bS } ;\n " +
1417+ $ "var colors = { arr } ;\n " +
1418+ $ "var pulse = new CircularPulseEffect(layer, { ParamRippleSpeed } , { ParamPulseRadius } , { ParamSpawnInterval } , { ParamFadeWidth } , colors, surface, baseCol);\n \n " +
1419+ "SetEffect(pulse, layer, runningEffects);" ,
1420+
1421+ "Gravitational Flux" =>
1422+ $ "var baseCol = { bS } ;\n " +
1423+ $ "var colors = { arr } ;\n " +
1424+ $ "var heartbeat = new BPMHeartbeatEffect(layer, { ParamBpm } , { ParamBeamWidth } , colors, surface, baseCol);\n \n " +
1425+ "SetEffect(heartbeat, layer, runningEffects);" ,
1426+
1427+ "Meteor Showers" or "Sporing Mist" or "Glass Storms" =>
1428+ $ "var baseCol = { bS } ;\n " +
1429+ $ "var animationCol = { arr } ;\n " +
1430+ $ "var starfield = new StarfieldDecorator(layer, { ParamNumberOfLeds } , { ParamInterval } , { ParamFadeSpeed } , animationCol, surface, false, baseCol);\n \n " +
1431+ "layer.Brush = new SolidColorBrush(baseCol);\n SetEffect(starfield, layer, runningEffects);" ,
1432+
1433+ "Annealing Winds" =>
1434+ $ "var baseCol = { bS } ;\n var animationCol = { s0 } ;\n \n " +
1435+ "var animationGradient = new LinearGradient(new GradientStop(0f, baseCol), new GradientStop(0.25f, animationCol), new GradientStop(0.75f, baseCol), new GradientStop(1f, animationCol));\n " +
1436+ $ "var gradientMove = new MoveGradientDecorator(surface, { ParamSpeed } , true);\n \n " +
1437+ "SetLinearGradientEffect(animationGradient, gradientMove, layer, new Size(100, 100), runningEffects, _gradientEffects);" ,
1438+
1439+ "Bubble Bloom" =>
1440+ $ "var baseCol = { bS } ;\n " +
1441+ $ "var colors = { arr } ;\n " +
1442+ $ "var spinner = new BPMSpinnerEffect(layer, { ParamBpm } , { ResolveBeatsPerCycle ( ) } , { ParamWedgeDegrees } , colors, surface, baseCol);\n \n " +
1443+ "SetEffect(spinner, layer, runningEffects);" ,
1444+
12801445 "Blasting Ring (Brute Bomber)" =>
12811446 $ "var baseCol = { bS } ;\n " +
12821447 $ "var animationCol1 = { s0 } ;\n var animationCol2 = { s1 } ;\n var animationCol3 = { s2 } ;\n \n " +
@@ -1668,25 +1833,112 @@ private Action BuildEffect(EffectEntry effect, ListLedGroup group)
16681833 return ( ) => group . RemoveDecorator ( dec ) ;
16691834 }
16701835 case "Arcadia P1 Effect 2 — Post-Flash" :
1836+ case "The Unmaking" :
16711837 {
16721838 group . Brush = new SolidColorBrush ( baseCol ) ;
16731839 var dec = new BPMThunderstrikeEffect ( group , ParamBpm , ParamAccentEvery , ParamDecay , colors , _surface , baseCol ) ;
16741840 group . AddDecorator ( dec ) ;
16751841 return ( ) => group . RemoveDecorator ( dec ) ;
16761842 }
1843+ case "Ring Noir (M9)" :
1844+ {
1845+ group . Brush = new SolidColorBrush ( baseCol ) ;
1846+ var dec = new BPMHeartbeatEffect ( group , ParamBpm , ParamBeamWidth , colors , _surface , baseCol ) ;
1847+ group . AddDecorator ( dec ) ;
1848+ return ( ) => group . RemoveDecorator ( dec ) ;
1849+ }
1850+ case "The X-Ring (M10)" :
1851+ {
1852+ group . Brush = new SolidColorBrush ( baseCol ) ;
1853+ var dec = new BPMCircularPulseEffect ( group , ParamBpm , ResolveBeatsPerCycle ( ) , ParamPulseRadius , ParamFadeWidth , colors , _surface , baseCol ) ;
1854+ group . AddDecorator ( dec ) ;
1855+ return ( ) => group . RemoveDecorator ( dec ) ;
1856+ }
1857+ case "The Crown (M11)" :
1858+ {
1859+ group . Brush = new SolidColorBrush ( baseCol ) ;
1860+ var dec = new BPMSpinnerEffect ( group , ParamBpm , ResolveBeatsPerCycle ( ) , ParamWedgeDegrees , colors , _surface , baseCol ) ;
1861+ group . AddDecorator ( dec ) ;
1862+ return ( ) => group . RemoveDecorator ( dec ) ;
1863+ }
1864+ case "Hell on Rails" :
1865+ {
1866+ group . Brush = new SolidColorBrush ( baseCol ) ;
1867+ var dir = Enum . Parse < MatrixEffect . MatrixDirection > ( ParamMatrixDir ) ;
1868+ var dec = new BPMMatrixEffect ( group , ParamBpm , ResolveBeatsPerCycle ( ) , ParamFlickerOpacity , ParamFlickerSpeed , colors , _surface , dir , baseCol ) ;
1869+ group . AddDecorator ( dec ) ;
1870+ return ( ) => group . RemoveDecorator ( dec ) ;
1871+ }
1872+ case "The Ageless Necropolis / Lightless Abyss" :
1873+ {
1874+ group . Brush = new SolidColorBrush ( baseCol ) ;
1875+ var dir = Enum . Parse < LaserEffect . LaserDirection > ( ParamLaserDir ) ;
1876+ var dec = new BPMLaserEffect ( group , ParamBpm , ResolveBeatsPerCycle ( ) , ParamBeamWidth , colors , _surface , dir , baseCol ) ;
1877+ group . AddDecorator ( dec ) ;
1878+ return ( ) => group . RemoveDecorator ( dec ) ;
1879+ }
1880+ case "Recollection" :
1881+ {
1882+ // Diagonal-gradient effect — mirrors RaidEffectProcessor's
1883+ // SetRadialGradientEffect path with three colour stops, no
1884+ // base-colour stop (hence Build3StopGradient over only the
1885+ // animation colours, the same shape Recollection uses
1886+ // in-game).
1887+ var g = new LinearGradient (
1888+ new GradientStop ( 0f , s0 ) ,
1889+ new GradientStop ( 0.33f , s1 ) ,
1890+ new GradientStop ( 0.66f , s2 ) ) ;
1891+ var dec = new MoveBPMDiagonalGradientDecorator ( _surface , ParamBpm , Enum . Parse < DiagonalDirection > ( ParamDiagonalDir ) ) ;
1892+ g . AddDecorator ( dec ) ;
1893+ group . Brush = new TextureBrush ( new ConicalGradientTexture ( new Size ( 100 , 100 ) , g ) ) ;
1894+ return ( ) => g . RemoveDecorator ( dec ) ;
1895+ }
16771896
16781897 // ── Weather presets (starfield-based) ──
16791898 case "Moon Dust (Mare Lamentorum)" :
16801899 case "Rain" :
16811900 case "Showers" :
16821901 case "Snow" :
16831902 case "Blizzards" :
1903+ case "Meteor Showers" :
1904+ case "Sporing Mist" :
1905+ case "Glass Storms" :
16841906 {
16851907 group . Brush = new SolidColorBrush ( baseCol ) ;
16861908 var dec = new StarfieldDecorator ( group , Math . Max ( 4 , group . Count ( ) / 4 ) , ParamInterval , ParamFadeSpeed , colors , _surface , false , baseCol ) ;
16871909 group . AddDecorator ( dec ) ;
16881910 return ( ) => group . RemoveDecorator ( dec ) ;
16891911 }
1912+ case "Atmospheric Phantasms" :
1913+ case "Illusory Disturbances" :
1914+ {
1915+ group . Brush = new SolidColorBrush ( baseCol ) ;
1916+ var dec = new CircularPulseEffect ( group , ParamRippleSpeed , ParamPulseRadius , ParamSpawnInterval , ParamFadeWidth , colors , _surface , baseCol ) ;
1917+ group . AddDecorator ( dec ) ;
1918+ return ( ) => group . RemoveDecorator ( dec ) ;
1919+ }
1920+ case "Gravitational Flux" :
1921+ {
1922+ group . Brush = new SolidColorBrush ( baseCol ) ;
1923+ var dec = new BPMHeartbeatEffect ( group , ParamBpm , ParamBeamWidth , colors , _surface , baseCol ) ;
1924+ group . AddDecorator ( dec ) ;
1925+ return ( ) => group . RemoveDecorator ( dec ) ;
1926+ }
1927+ case "Annealing Winds" :
1928+ {
1929+ var g = Build2ColorOscGradient ( baseCol , s0 ) ; g . WrapGradient = true ;
1930+ var dec = new MoveGradientDecorator ( _surface , ParamSpeed , ParamDirection ) ;
1931+ g . AddDecorator ( dec ) ;
1932+ group . Brush = new TextureBrush ( new LinearGradientTexture ( new Size ( 100 , 100 ) , g ) ) ;
1933+ return ( ) => g . RemoveDecorator ( dec ) ;
1934+ }
1935+ case "Bubble Bloom" :
1936+ {
1937+ group . Brush = new SolidColorBrush ( baseCol ) ;
1938+ var dec = new BPMSpinnerEffect ( group , ParamBpm , ResolveBeatsPerCycle ( ) , ParamWedgeDegrees , colors , _surface , baseCol ) ;
1939+ group . AddDecorator ( dec ) ;
1940+ return ( ) => group . RemoveDecorator ( dec ) ;
1941+ }
16901942 // ── Weather presets (strobe) ──
16911943 case "Thunder / Thunderstorms" :
16921944 {
0 commit comments