Compare commits

...
12 Commits
Author SHA1 Message Date
phenom ab1434a3b8 Release Healer Man 0.1.59 2026-09-27 10:16:42 -04:00
phenom 11934a3979 Update Healer Man server 2026-09-26 22:02:18 -04:00
phenom 8a98797fcf Update Healer Man server 2026-09-26 20:27:07 -04:00
phenom 4957b69e86 Update Healer Man server 2026-09-26 19:55:08 -04:00
phenom 83eac6d476 Update Healer Man server 2026-09-26 18:57:44 -04:00
phenom bd073fb00f Update Healer Man server 2026-09-26 17:51:56 -04:00
phenom 9c5fb4c614 Update Healer Man server 2026-09-25 21:37:10 -04:00
phenom 48a678dcc5 Update Healer Man server 2026-09-25 18:46:09 -04:00
phenom a868401ebc Update Healer Man server 2026-09-24 18:15:45 -04:00
phenom 71246e5b75 Update Healer Man server 2026-09-24 16:42:43 -04:00
phenom a64b2cb575 Update Healer Man server 2026-09-23 22:25:39 -04:00
phenom d869d6b51c Update Healer Man server 2026-09-23 21:58:28 -04:00
879 changed files with 23350 additions and 751 deletions

No files matched your search

+267
View File
@@ -4,6 +4,21 @@ This file is the durable record of runtime behavior, regressions, and the
evidence required before calling a visual bug fixed. Update it whenever scene,
camera, input, physics, mob-rendering, or asset-loading code changes.
## 2026-09-26 RuneWaker dungeon minimap and M-key map
- Created a fresh RoM Rogue, downloaded Forsaken Abbey, entered as damage, and
waited for the boss preview to finish. The minimap displayed the extracted
client map; moving backward changed the live player-marker coordinates.
- Pressing M opened the full map with the same artwork, player heading, entrance,
and eight numbered encounters. Pressing M again closed it. No browser page
errors were reported.
- Inspected `artifacts/playtest/runewaker-maps/forsaken-minimap.png` and
`forsaken-full-map.png`. The map was readable and did not cover the normal
playfield until opened. Navigation floorplans were checked by generated-image
inspection and catalog tests, not by live dungeon entry.
- Validation: 24 focused map/UI tests, TypeScript, production build, content
publication, and release candidate check passed.
## 2026-09-15 Reported Warder Stilgiss and Zereketh issues
- Reproduced the two submitted production reports in isolated Boss Testing
@@ -3820,3 +3835,255 @@ Vite's existing large-chunk advisory remains informational.
- These level-1 screenshots do not show the later training unlocks. Focused
equipment tests verify the Knight/Scout bow at level 10, Rogue projectile at
level 12, and Scout/Rogue and Rogue off-hand weapons at level 16.
## RuneWaker sprite particle pilot (2026-09-24)
- Opened `scripts/combat-effects/rom-preview.html` in the in-app browser against
Vite and inspected frozen 250 ms frames after regenerating the archive. Knight
Charge showed a blue upward spray with orange sparks (3 layers), Whirlwind
Shield showed a small gold circular impact (3 layers), and Mage Electric Bolt
showed a blue-white projectile with streaks (3 layers). Browser console had
no errors or warnings. The preview tab is retained for inspection.
- These screenshots verify the sprite renderer and packaged textures at the
preview camera scale. A level-18 Knight and level-10 Mage were then run in
Wailing Caverns with Original visuals on using disposable local QA saves.
Whirlwind Shield's impact graph loaded at the caster position, but its
33 ms emission burst could disappear when a frame skipped past the last
rate key. Integrating the source rate over each frame restored the burst.
A 2.5 presentation scale made the gold shield ring visible around the
Knight at the dungeon camera distance during an isolated cast. Electric
Bolt cast and resolved in combat with no missing-original warning, though
the fast projectile was not visually captured in a still frame. Charge
remains to be checked in live movement. The next visual decoder target is
the Priest's holy `act_casting_c_hand.ros`: its only unsupported controller
is `CRuController_EventTrigger`, which the source uses for action callbacks.
## RuneWaker Priest holy cast (2026-09-24)
- The native exporter now records the `EventTrigger` payload. Source event 43
in holy `act_casting_c_hand.ros` requests looping 3D playback of
`sound/fx/skill/holy/act_casting_c_hand.wav`; it adds no visual layer. The
particle archive validates this exact event and marks the partial graph
renderer-ready. The shared combat manifest attaches its three sprite layers
and looped cast sound to Priest Urgent Heal, Heal, and Group Heal only.
- The in-app browser preview rendered the holy model as a gold star and swirling
particles with three loaded textures. In a disposable level-14 Priest save in
Wailing Caverns, Urgent Heal (2), Heal (6), and Group Heal (Shift+6) each
showed the gold cast effect on the isolated player during the cast. Group
Heal's longer cast kept the effect visible across successive frames. The
browser reported no original-effect load errors; its only warning was an
unrelated dependency deprecation warning. Audio loop and release/cancel
behavior passed focused unit tests, but the browser pass did not assess sound
by listening. The generated map is `docs/ROM_SPELL_MEDIA_MAPPING.md`.
## RoM Priest target and Rising Tide media (2026-09-24)
- Traced Urgent Heal's MagicObject component 501543 to ImageObject 573048 and
its target `act_benedictory_heal_t_down.ros`. Its `explode` motion requests a
one-shot 3D `act_benedictory_heal_t_down.mp3` at the healed target. The
browser graph renders two original sprite layers, the emitted 72-triangle
rune cylinder, and the animated gold ground decal with source color and
alpha tracks. It remains marked partial because the decal is placed on a
level ground plane rather than projected onto nearby terrain triangles.
- Traced Rising Tide's component 620408 to ImageObject 572062 and target
`act_riptide_t_freeze_hit.ros`. Its five-sprite target graph and the
`act_icecone01_c_hand.ros` cast and `act_icecone01_f.ros` projectile graphs
are attached to their respective phases. ROS direct-audio events identify
`act_icecone01_f.ros.mp3` on projectile release and
`act_riptide_t_freeze_hit.mp3` on target impact. Impact audio is positioned
at the target; release audio remains at the caster.
- The focused combat audio suite passed 12 tests, including distinct release
and target panning. The manifest test checked all three new MP3 paths against
the source ROS EventTrigger ID 43 payloads and packaged files.
- In the in-app RuneWaker preview, Urgent Heal's impact showed gold stars, a
green rune cylinder, and a gold target-ground ring at the frozen 250 ms frame.
Rising Tide's cast showed a blue ring, its release a bright blue flash, and
its target impact a blue and magenta burst. All four graphs loaded without
browser errors or warnings. Audio mapping was source and test verified; this
browser pass did not assess the sound by listening.
- Live Priest combat in Wailing Caverns confirmed Urgent Heal's original gold
rune circle and sparkles around the selected party target Veyra. In Boss
Testing against Verdan the Everliving, Rising Tide showed blue source
particles around the Priest during the cast, a blue projectile on release,
and a bright blue and magenta burst across Verdan's visible lower body at
arrival. The impact presentation now follows the projectile's 180–550 ms
travel time; large-target attachment uses visual bounds so the burst remains
in view. The browser reported no original-media or WebGL errors. Audio
timing and target panning are source and test verified, not listening tested.
## RoM primary-five media batch preview (2026-09-24)
- The batch now follows direct MagicCollect component ImageObjects to their
target `ExtendACT` models, packages 170 unique ROS graphs and source textures,
and attaches 74 renderer-ready graphs plus Urgent Heal's partial target graph.
The generated class audit counts 84 castable skills with at least one playable
original phase. Source audio is packaged for 125 of 129 cohort spell entries.
- In the in-app RuneWaker preview, frozen at 250 ms, Priest Ice Fog showed a
bright ice spray, Knight Holy Seal a blue sigil, Scout Snipe an orange target
ring, Rogue Sneak Attack a blue arc, and Mage Electric Explosion a layered
blue burst. All five graphs loaded and rendered; each status showed two or
three source sprite layers with matching textures.
- The first exporter pass falsely marked seven graphs ready despite emitter
geometry or sprite billboard modes the WebGL renderer rejects. The packager
now blocks those modes, and the parser test loads every ready graph. This
preview pass did not assess sound by listening or cast the five spells in
live combat; those are still needed to confirm placement and phase timing.
- A shared source alpha track rule then enabled four additional graphs whose
alpha anchor covers every sprite layer in the motion. The Mage Fireball
cast graph rendered a bright red and gold burst in the preview at 250 ms.
- RuneWaker audio phases now play all distinct packaged source cues together;
the previous weighted selector could drop one of several cast or impact
layers. A focused audio test confirms two impact files create two voices.
Listening QA is still needed for the balance of these layers.
## RoM Priest channel and stacked status icons (2026-09-25)
- In a disposable level-30 Priest/Knight Wailing Caverns run,
`scripts/playtest-rom-status-effects.cjs` cast Chain of Light at a nearby
Deviate Ravager. The cast bar showed Channeling and the rendered scene showed
a sustained white-gold beam between the Priest and target. The browser
reported no page errors. Evidence: `artifacts/playtest/rom-status-effects/chain-of-light-and-stacked-dot.png`.
- Three same-spell damage-over-time applications on that target appeared as one
icon with a small `3`; the browser assertion also checked the icon count.
This exercise checked HUD grouping, while focused combat tests checked four
separate channel damage pulses. Source audio was not assessed by listening.
## Raksha Temple collision performance (2026-09-26)
- A production-build offline playtest in headless Edge measured about 0.6 FPS
after Raksha Temple loaded. A CPU profile placed nearly all frame time in
Rapier character movement and physics. Its collision GLBs use interleaved
position buffers; passing the packed float array as XYZ vertices created
malformed trimeshes.
- After unpacking positions, the same 15-second sample recorded 600 frames at
16.67 ms average frame time (60 FPS). The entrance's WDB collision lacks a
walkable floor, so Raksha now uses its navigation mesh as physical ground.
The final browser pass retained 60 FPS, showed the party at 5/5 instead of
`ROUTE BLOCKED`, and kept the player at the entrance. An eight-second forward
movement sample explored 2 m and still held 60 FPS. Screenshots:
`playtest-artifacts/raksha-final-ground.png` and
`playtest-artifacts/raksha-moved.png`. The scene remains very dark;
this pass verified frame rate and floor support, not lighting quality.
## Scholomance rendering and population performance (2026-09-26)
- In a production-build offline run in headless Edge, Scholomance's entrance
averaged 31.78 ms per frame (about 31 FPS) over 15 seconds. A CPU profile
was dominated by Three.js render traversal and matrix updates, while the
visual asset audit counted 5,140 raw draw calls and 3,175 mesh nodes.
WebGL instrumentation saw about 867 draw calls per rendered frame before
the visual batching change.
- Scholomance had 191 static mob spawns within its former 95 m activation
radius at the entrance, across stacked indoor floors. Its 48 m radius and
global opaque instancing reduced the 15-second average to about 20.1 ms
per frame (about 50 FPS). Holding forward for 12 seconds explored 30 m;
the subsequent sample remained near 20.1 ms per frame with the party at
5/5. Entrance and movement screenshots showed intact geometry and no page
errors: `playtest-artifacts/scholomance-after.png` and
`playtest-artifacts/scholomance-moved.png`.
## Bite-Sized Dungeon Race (2026-09-26)
- `scripts/playtest-dungeon-race.cjs` used headless Edge with a fresh offline
character. Practice entered a Bite-Sized dungeon with five player-party seats,
displayed the top clock and NPC progress, and kept the game scene active
after a forced NPC win showed the “You lose” toast. The NPC roster contained
five members. Desktop and 960×540 Thor-size captures are in
`playtest-artifacts/dungeon-race/`.
- `scripts/playtest-dungeon-race-online.cjs` created two online accounts in
separate browser contexts. Both entered the same human match, dungeon, and
seed with each other as opponents. A third account queued alone and received
a five-member NPC team after the five-second fallback. Both scripts reported
no browser page errors.
- The practice screenshot check used a time jump to trigger the loss toast,
then injected a defeated boss-card fixture into the active combat store. The
normal automatic loot action added one Bazil Thredd card after the loss and
showed its reward window (`05-card-after-loss-fixture.png`). It did not
traverse and defeat the final boss through live combat. Server tests verify
that a losing clear is accepted for the dungeon time board.
## Dungeon Race exit regression (2026-09-26)
- `src/app/dungeonRaceStore.test.ts` covers immediate cleanup of active and
practice races, cancellation during an in-flight queue request, ordered
server leave before requeue, and an old preparation response after start.
- `scripts/playtest-dungeon-race-exit.cjs` used headless Edge with a fresh
online account. It left an NPC race through the pause menu, entered an
ordinary Bite-Sized dungeon without a race HUD, and requeued into a new
online match without an “already in a race” error. Screenshots are in
`playtest-artifacts/dungeon-race-exit/`. The offline practice playtest also
left after a modeled loss, confirmed the local race state cleared, and
started practice again. Browser page errors were absent in both passes.
## Bite-Sized spawn floor regression (2026-09-26)
- Fresh offline Dungeon Race practice entries in Wailing Caverns and Utgarde
Pinnacle previously settled about 0.5 m below the visible floor. During the
race start gate, Rapier physics was paused while PlayerRig accumulated
downward movement. Holding the player controller for that gate removed the
stored fall. Wailing keeps its original entrance; Utgarde now starts on the
connected Skadi wave corridor with three source first-wave guards.
- `scripts/playtest-bite-sized-spawns.cjs` entered both dungeons through the
menu, waited for content, intro, and race gate completion, then sampled five
seconds of play. Wailing was grounded at y=-31.016 from a -30.92 spawn;
Utgarde was grounded at y=104.812 from a 104.8 spawn. Both kept their entry
X/Z position, and there were no browser page errors. Before/after screenshots
and `result.json` are in `playtest-artifacts/bite-sized-spawns/`. The player
stands visibly on the floor in both after screenshots. Utgarde corridor samples
at z=370, 390, 410, 430, 445, and 460 also stood on collision in the live
client; the source guard points and boss position have collision and
navigation surfaces.
## Paused browser memory (2026-09-26)
- A fresh offline Wailing Caverns Bite-Sized run in headless Edge entered the
dungeon, opened the pause menu, and held it for 60 seconds. The paused scene
used R3F's `demand` frame loop and reported no browser page errors. Before
the classic talent lookup change, forced-GC JavaScript heap remained at
266 MiB across 0, 15, 30, and 60 seconds; DOM node count also stayed flat.
- `src/game/wow335AbilityCatalog.ts` now validates classic talent IDs through
the already loaded compact runtime talent catalog. The built classic ability
chunk fell from 41.4 MiB to 2.1 MiB, because it no longer includes the
36.6 MiB CoA source catalog. The same paused browser run measured 155, 155,
155, and 156 MiB after forced GC at 0, 15, 30, and 60 seconds. The paired
screenshots and samples are in `playtest-artifacts/pause-memory/`.
- The one-minute sample did not show a growing JavaScript heap. It does not
measure GPU allocations or rule out growth in a different dungeon or over
a longer idle period.
## Character-specific catalog loading (2026-09-26)
- The production build now imports `src/game/romBaseStatGrowth.generated.json`
(4.5 KB) for shared stat calculations. The full 1.7 MB
`romPlayerCatalog.generated.json` remains in the RoM ability chunk and is
requested only when a RoM class needs its abilities.
- `src/game/talentRuntimeCatalog.ts` loads its generated WoW/CoA talent data
after a non-RoM class requests combat catalogs. A fresh RoM Rogue main-menu
session fetched `romAbilityCatalog-*.js` without fetching either the
`wow335AbilityCatalog-*.js` or the talent-data chunk. A fresh WoW Priest
fetched the classic ability and talent-data chunks without fetching the
RoM ability chunk. Both sessions had no browser page errors.
- The RoM Rogue roster and Wailing Caverns dungeon smoke test passed with the
WoW/CoA talent data absent from the initial RoM page load. Browser request
results and menu screenshots are in `playtest-artifacts/catalog-loading/`;
dungeon screenshots are in `artifacts/playtest/rom-five/`.
## Browser memory reset at shell boundaries (2026-09-26)
- Browser ES modules cannot be unloaded individually from an active page.
Changing to a different character now reloads the page with a one-use
`sessionStorage` handoff to restore the selected character and destination.
Leaving a gameplay mode for the roster or main menu also reloads after the
run's normal save path. A live online group activity suppresses this reset
to avoid re-entering the same activity on reconnect.
- The main-menu catalog gate no longer reloads the full gameplay runtime or
retains talent art up front; it preloads those resources when gameplay starts.
- In a production Edge playtest, switching from a WoW Priest to a RoM Rogue
produced one reload and returned to the RoM main menu. The WoW talent editor
opened on demand before that switch. The new RoM page loaded
`romAbilityCatalog-*.js` without a WoW ability or `GameRuntime` chunk.
Leaving a RoM Wailing Caverns run produced a second reload and returned to
the same character's main menu without a `GameRuntime` chunk. Switching to
another RoM character also reloaded. The one-use handoffs were consumed,
and the page reported no errors. Results and screenshots are in
`playtest-artifacts/memory-reset/`.
File diff suppressed because it is too large. Load diff
+73
View File
@@ -0,0 +1,73 @@
# RuneWaker media batch plan
Generated by `npm run effects:rom:plan` from the current primary-five spell manifest and decoded ROS archive. It groups remaining controller and timing work. The manifest generator already attaches source direct audio events at supported phase boundaries.
The archive has 170 unique models: 74 ready, 1 partial original, 0 fully decoded but unverified, 95 blocked, and 0 failed. 125 of 129 source spell entries have at least one packaged audio cue.
## Shared controller blockers
Counts overlap when a model has several controller families. A family should be ported and verified once against representative models before its other users are considered for promotion.
| Controller family | Models | Source spell IDs using those models |
| --- | ---: | ---: |
| CRuController_EventTrigger | 148 | 124 |
| CRuController_GlobalAlpha | 47 | 49 |
| CRuEntity_Particle_Visualizer_Entity | 35 | 44 |
| CRuController_Particle_Visualizer_Entity | 34 | 43 |
| CRuController_GlobalColor | 26 | 26 |
| RuneWaker browser emitter geometry mode | 18 | 21 |
| CRuController_Decal | 17 | 17 |
| CRuController_GhostTrail | 11 | 15 |
| CRuController_Hierarchy | 11 | 12 |
| CRuController_Entity | 5 | 4 |
| RuneWaker browser sprite mode | 5 | 5 |
| CRuController_UVFX | 3 | 3 |
| CRuController_MaterialTexture | 1 | 1 |
| CRuController_PolyLine | 1 | 1 |
## Fully decoded models awaiting visual review
| Source model | Spell-phase references | Sprite layers | Blockers |
| --- | ---: | ---: | --- |
## Event-only models still blocked
These models have sprite data but include an event callback outside the validated visual-only set. Effect-spawning and projectile-flight callbacks require browser behavior before their visuals can be promoted.
| Source model | Spell-phase references | Sprite layers | Blockers |
| --- | ---: | ---: | --- |
| model/fx/skill/ice/act_cone01_c_hand.ros | 3 | 12 | CRuController_EventTrigger |
| model/fx/skill/fire/act_fireball02_t_hit_point.ros | 1 | 5 | CRuController_EventTrigger |
| model/fx/skill/holy/act_armorup_c_top.ros | 1 | 8 | CRuController_EventTrigger |
| model/fx/skill/physical/act_concentration_t_top.ros | 1 | 3 | CRuController_EventTrigger |
| model/fx/skill/physical/act_focus_c_top.ros | 1 | 4 | CRuController_EventTrigger |
| model/fx/skill/physical/act_fracture01_t_freeze_hit.ros | 1 | 6 | CRuController_EventTrigger |
There are 6 event-only models. The archive also exposes 3 model/phase audio-event candidates missing from the current packaged manifest. They need delayed timing or a later lifecycle phase; an ROS motion name alone is insufficient. Full per-model evidence is in `docs/ROM_MEDIA_BATCH_PLAN.json`.
## Largest blocker combinations
| Controller signature | Models | Source spell IDs | Example model |
| --- | ---: | ---: | --- |
| CRuController_EventTrigger + CRuController_Particle_Visualizer_Entity + CRuEntity_Particle_Visualizer_Entity | 13 | 20 | model/fx/skill/earth/act_casting_c_hand.ros |
| CRuController_EventTrigger | 9 | 11 | model/fx/skill/fire/act_fireball02_t_hit_point.ros |
| CRuController_Decal + CRuController_EventTrigger + CRuController_GlobalAlpha + CRuController_GlobalColor | 8 | 8 | model/fx/skill/earth/act_vriusinfection_t_freeze_down_e.ros |
| CRuController_EventTrigger + CRuController_GlobalAlpha | 6 | 7 | model/fx/skill/fire/act_fireball01_c_hand_i.ros |
| CRuController_EventTrigger + CRuController_GlobalAlpha + CRuController_Particle_Visualizer_Entity + CRuEntity_Particle_Visualizer_Entity | 5 | 6 | model/fx/skill/holy/act_chain_t_down.ros |
| CRuController_EventTrigger + CRuController_Particle_Visualizer_Entity + CRuEntity_Particle_Visualizer_Entity + RuneWaker browser emitter geometry mode | 5 | 5 | model/fx/skill/holy/act_moist_t_down.ros |
| CRuController_EventTrigger + RuneWaker browser emitter geometry mode | 5 | 8 | model/fx/skill/physical/act_deep_thought_c_down_e.ros |
| CRuController_Particle_Visualizer_Entity + CRuEntity_Particle_Visualizer_Entity | 4 | 10 | model/fx/skill/dark/act_dark_hand_wave_c_hand_e.ros |
| CRuController_Decal + CRuController_Entity + CRuController_EventTrigger + CRuController_GlobalAlpha + CRuController_GlobalColor | 2 | 1 | model/fx/skill/holy/act_scrifice_healing_c_freeze_down_e.ros |
| CRuController_Entity + CRuController_EventTrigger | 2 | 2 | model/fx/skill/holy/act_judgement_t_hit_point.ros |
| CRuController_EventTrigger + CRuController_GhostTrail + CRuController_GlobalAlpha | 2 | 4 | model/fx/skill/fire/act_fireball02_f.ros |
| CRuController_EventTrigger + CRuController_GhostTrail + CRuController_GlobalAlpha + CRuController_GlobalColor + CRuController_Hierarchy | 2 | 2 | model/fx/skill/physical/act_deflecting_shot_f.ros |
| CRuController_EventTrigger + CRuController_GhostTrail + CRuController_Particle_Visualizer_Entity + CRuEntity_Particle_Visualizer_Entity | 2 | 2 | model/fx/skill/ice/act_icearrow_f.ros |
| CRuController_EventTrigger + RuneWaker browser emitter geometry mode + RuneWaker browser sprite mode | 2 | 2 | model/fx/skill/physical/act_attackspeedup_c_down.ros |
| CRuController_Decal + CRuController_Entity + CRuController_GlobalAlpha + CRuController_GlobalColor + RuneWaker browser emitter geometry mode + RuneWaker browser sprite mode | 1 | 1 | model/fx/skill/physical/act_beckon_holy_c_freeze_down_e.ros |
## Batch workflow
1. Run `npm run effects:rom:batch` to refresh source links, package audio and ROS graphs, attach verified phases, and rebuild this plan.
2. Review the remaining event timing candidates and largest shared blocker families above.
3. Port one controller family in the exporter/WebGL runtime and add a parser check that every promoted graph is renderable.
4. Regenerate the manifest and media audit, replay representative graphs in the RuneWaker preview, then spot-check distinct motion and attachment patterns in live combat.
+206
View File
@@ -0,0 +1,206 @@
# RuneWaker primary-five spell media mapping
Generated by `node scripts/combat-effects/audit-rom-media.mjs --write` from the player catalog and combat effect manifest. The five accepted pairings follow `src/game/romFiveIdentities.ts`. Castable skills are listed; passives have no cast media event.
The effect column records original client ROS/RAS references and their cast phase. 84 castable skills have browser-playable original phases; other source visuals use the game's generated runtime effect until their controller families are supported. A `partial original` phase renders verified source layers and declares its remaining fidelity limit. The sound column lists packaged client cues on their mapped phase. A dash means the source record or matching sound file did not provide that media.
| Primary class | Skill group | Castable skills | With source effect | With packaged sound | With playable original effect |
| --- | --- | ---: | ---: | ---: | ---: |
| Priest | Base | 25 | 23 | 23 | 18 |
| Priest | Accepted elite pair | 6 | 6 | 6 | 3 |
| Knight | Base | 19 | 19 | 18 | 13 |
| Knight | Accepted elite pair | 6 | 6 | 6 | 2 |
| Scout | Base | 20 | 20 | 19 | 13 |
| Scout | Accepted elite pair | 4 | 4 | 4 | 4 |
| Rogue | Base | 20 | 20 | 18 | 15 |
| Rogue | Accepted elite pair | 4 | 4 | 4 | 2 |
| Mage | Base | 21 | 20 | 20 | 13 |
| Mage | Accepted elite pair | 5 | 5 | 5 | 1 |
## Priest — base
| Skill | Source spell IDs | Effect phase and source model | Sound phase and source cue |
| --- | --- | --- | --- |
| Soul Source | 490288 | impact: act_soulspring_t_down.ros | impact: act_soulspring_t_down.ros.mp3 |
| Wave Armor | 490273 | impact: act_holywater_armor_t_top.ros<br>aura-start: act_watershieldbuff_c_down_i.ros | impact: act_holywater_armor_t_top.mp3<br>aura-start: act_watershieldbuff_c_down_i.ros.mp3 |
| Heal | 490261 | cast-start: act_casting_c_hand.ros<br>impact: act_mainheal_t_down_e.ros | cast-start: act_casting_c_hand.wav<br>impact: act_friendly_t_down_i.mp3<br>impact: act_mainheal_t_down_e.ros 2.mp3 |
| Ice Fog | 490274 | cast-start: act_cone01_c_hand.ros<br>impact: act_icefog_t_freeze_hit_e.ros | cast-start: act_cone01_c_hand.ros.mp3<br>impact: act_icefog_t_freeze_hit_e.ros.mp3 |
| Bone Chill | 491165 | cast-start: act_ice_hand_wave_c_hand_e.ros<br>impact: act_icefog_t_freeze_hit_e.ros | cast-start: act_ice_hand_wave_c_hand_e.ros.mp3<br>impact: act_icefog_t_freeze_hit_e.ros.mp3 |
| Resurrection | 490280 | cast-start: act_casting_c_hand.ros<br>impact: act_anabiosis_t_down.ros | cast-start: act_casting_c_hand.wav<br>impact: act_anabiosis_t_down.mp3 |
| Soul Bond | 490297 | cast-start: act_casting_c_hand.ros<br>impact: act_holycross_t_top.ros | cast-start: act_casting_c_hand.wav<br>impact: act_holycross_t_top.mp3 |
| Grace of Life | 490290 | impact: act_rainpray_t_down.ros | impact: act_rainpray_t_down.mp3 |
| Group Heal | 490281 | cast-start: act_casting_c_hand.ros<br>impact: act_anima_t_name_title.ros | cast-start: act_casting_c_hand.wav<br>impact: act_anima_t_name_title.mp3 |
| Chain of Light | 491164 | cast-start: act_light_chain_c_hand_i.ros<br>impact: act_light_chain_t_down_i.ros<br>impact: act_light_chainhit_t_down_e.ros | cast-start: act_powergather_c_right_hand.mp3<br>impact: act_light_chainhit_t_down_e.ros.mp3 |
| Amplified Attack | 490491 | cast-start: act_casting_c_hand.ros<br>impact: act_power_up_t_down.ros | cast-start: act_casting_c_hand.wav<br>impact: act_power_up_t_down.mp3 |
| Ice Fog | 490275 | cast-start: act_cone01_c_hand.ros<br>impact: act_icefog_t_freeze_hit_e.ros | cast-start: act_cone01_c_hand.ros.mp3<br>impact: act_icefog_t_freeze_hit_e.ros.mp3 |
| Healing Salve | 490294 | impact: act_moist_t_down.ros | impact: act_moist_t_down.mp3 |
| Blessing of Humility | 490301 | — | — |
| Ice Fog | 490276 | cast-start: act_cone01_c_hand.ros<br>impact: act_icefog_t_freeze_hit_e.ros | cast-start: act_cone01_c_hand.ros.mp3<br>impact: act_icefog_t_freeze_hit_e.ros.mp3 |
| Holy Candle | 490304 | — | — |
| Cleanse | 491175 | impact: act_dispersion_t_freeze_hit_e.ros | impact: act_dispersion_t_freeze_hit_e.mp3 |
| Advanced Resurrection | 491176 | cast-start: act_casting_c_hand.ros<br>impact: act_anabiosis_t_down.ros | cast-start: act_casting_c_hand.wav<br>impact: act_anabiosis_t_down.mp3 |
| Supreme Resurrection | 491177 | cast-start: act_casting_c_hand.ros<br>impact: act_anabiosis_t_down.ros | cast-start: act_casting_c_hand.wav<br>impact: act_anabiosis_t_down.mp3 |
| Urgent Heal | 491147 | cast-start: act_casting_c_hand.ros<br>impact: act_benedictory_heal_t_down.ros (partial original) | cast-start: act_casting_c_hand.wav<br>impact: act_benedictory_heal_t_down.mp3 |
| Rising Tide | 490256 | cast-start: act_icecone01_c_hand.ros<br>release: act_icecone01_f.ros<br>impact: act_riptide_t_freeze_hit.ros | cast-start: act_cone01_c_hand.mp3<br>release: act_icecone01_f.ros.mp3<br>impact: act_riptide_t_freeze_hit.mp3 |
| Regenerate | 490269 | cast-start: act_casting_c_hand.ros<br>cast-start: act_holy_hand_wave_c_hand_e.ros<br>impact: act_blessed_heal_t_down.ros | cast-start: act_casting_c_hand.wav<br>impact: act_blessed_heal_t_down.mp3 |
| Holy Aura | 490300 | cast-start: act_casting_c_hand.ros<br>cast-start: act_flash_candle_c_down_e.ros<br>impact: act_flash_candle_t_freeze_hit.ros | cast-start: act_casting_c_hand.wav<br>cast-start: act_flash_candle_c_down_e.ros.mp3<br>impact: act_flash_candle_t_freeze_hit.mp3 |
| Magic Barrier | 491166 | impact: act_magicdefence_t_down_e.ros | impact: act_anima_t_name_title.mp3 |
| Blessed Spring Water | 490298 | cast-start: act_icecone01_c_hand.ros<br>impact: act_springblessing_t_top.ros | cast-start: act_cone01_c_hand.mp3<br>impact: act_springblessing_t_top.mp3 |
## Priest — accepted elite pair
| Skill | Source spell IDs | Effect phase and source model | Sound phase and source cue |
| --- | --- | --- | --- |
| Last Prayer | 491648 | impact: act_benedictory_heal_t_down.ros | impact: act_benedictory_heal_t_down.mp3 |
| Divine Incarnation | 491366 | cast-start: act_sacredincarnation_c_down.ros | cast-start: act_sacredincarnation_c_down.mp3 |
| Calm Heart | 492639 | cast-start: act_casting_c_hand.ros<br>impact: act_fearless_t_down_e.ros | cast-start: act_casting_c_hand.wav<br>impact: skill_fearless_t_down_e.mp3 |
| Sacrificial Cure | 492934 | cast-start: act_scrifice_healing_c_freeze_down_e.ros<br>impact: act_scrifice_healing_t_down_e.ros | cast-start: skill_scrifice_healing_c_freeze_down_e.mp3<br>impact: skill_scrifice_healing_t_down_e.mp3 |
| Holy Power | 493044 | cast-start: act_holyenergy_c_down_e.ros<br>cast-start: act_holyenergy_c_down_i.ros | cast-start: skill_holyenergy_c_down_e.ros.mp3<br>cast-start: skill_holyenergy_c_down_i.mp3 |
| Light Fairy | 493271 | cast-start: act_casting_c_hand.ros<br>cast-start: act_beckon_holy_c_freeze_down_e.ros | cast-start: act_casting_c_hand.wav |
## Knight — base
| Skill | Source spell IDs | Effect phase and source model | Sound phase and source cue |
| --- | --- | --- | --- |
| Holy Shield | 490495 | cast-start: act_godshield_c_down.ros | cast-start: act_godshield_c_down.mp3 |
| Holy Seal | 490149 | impact: act_sanink_c_hit_point_e.ros | impact: act_sanink_c_hit_point_e.mp3 |
| Holy Power Explosion | 490172 | cast-start: act_physical_casting_c_hand.ros<br>cast-start: act_vengeance_c_down.ros | cast-start: act_physical_casting_c_hand.mp3<br>cast-start: act_vengeance_c_down.mp3 |
| Whirlwind Shield | 490175 | cast-start: act_shieldstorm_c_down_e.ros<br>impact: act_shieldstorm_t_freeze_hit_e.ros | — |
| Shackles of Light | 490189 | cast-start: act_chain_c_shoot02.ros | cast-start: act_chain_c_shoot02.mp3 |
| Resolution | 490168 | cast-start: act_physical_casting_c_hand.ros<br>cast-start: act_responsibility_c_down.ros | cast-start: act_physical_casting_c_hand.mp3<br>cast-start: act_responsibility_c_down.mp3 |
| Charge | 490150 | cast-start: act_charge02_c_down.ros<br>impact: act_strikeback_t_hit_point.ros | cast-start: act_charge02_c_down.mp3<br>impact: act_strikeback_t_hit_point.mp3 |
| Threaten | 490153 | impact: act_intimidation_t_freeze_hit_e.ros | impact: act_intimidation_t_freeze_hit_e.mp3 |
| Shield of Valor | 490468 | cast-start: act_courage_shield_c_top.ros | cast-start: act_courage_shield_c_top.mp3 |
| Truth Shield Bash | 490186 | cast-start: act_truth_shield_c_top.ros<br>impact: act_judge_shield_t_hit_point.ros | cast-start: act_truth_shield_c_top.mp3<br>impact: act_judge_shield_t_hit_point.mp3 |
| Shock | 490154 | cast-start: act_holy_hand_wave_c_hand_e.ros<br>impact: act_shock_t_hit_point.ros | impact: act_shock_t_hit_point.mp3 |
| Holy Strength | 491321 | cast-start: act_manafreeback_c_down_e.ros | cast-start: act_manafreeback_c_down_e.mp3 |
| Hall of Dead Heroes | 495724 | aura-start: act_herosoul_buff_c_top.ros | aura-start: act_herosoul_buff_c_top.mp3 |
| Punishment | 490151 | cast-start: act_holy_hand_wave_c_hand_e.ros<br>impact: act_judgement_t_hit_point.ros | impact: act_judgement_t_hit_point.mp3 |
| Holy Strike | 490148 | impact: act_san_sword_t_down_e.ros | impact: act_san_sword_t_down_e.mp3 |
| Disarmament | 490159 | impact: act_disarm01_t_hit_point.ros | impact: act_disarm01_t_hit_point.mp3 |
| Strike of Punishment | 490179 | impact: act_brokenhit_t_hit_point.ros | impact: act_brokenhit_t_hit_point.mp3 |
| Enhanced Armor | 490152 | cast-start: act_armorup_c_top.ros | cast-start: act_armorup_c_top.mp3 |
| Shield of Discipline | 490192 | cast-start: act_discipline_shield_c_top.ros<br>impact: act_discipline_shield_t_hit_point.ros | cast-start: act_discipline_shield_c_top.mp3<br>impact: act_capacity_crash_c_freeze_hit_e.ros.mp3 |
## Knight — accepted elite pair
| Skill | Source spell IDs | Effect phase and source model | Sound phase and source cue |
| --- | --- | --- | --- |
| Arrow of Vengeance | 491616 | release: act_revengearrow_f_i.ros<br>impact: act_revengearrow_t_hit_point_e.ros | impact: act_revengearrow_t_hit_point_e.mp3 |
| Holy Chains | 491613 | impact: act_chain_t_down.ros | impact: act_chain_t_down.mp3 |
| Heavenly Arrow | 491354 | cast-start: act_holy_hand_wave_c_hand_e.ros<br>impact: act_heavenarrow_t_down_e.ros | impact: act_heavenarrow_t_down_e.mp3 |
| Sacred Resistance | 492939 | cast-start: act_holyresist_c_down_e.ros | cast-start: act_acheignore_c_down_e.mp3 |
| Sacred Protection | 493046 | cast-start: act_holyprotect_c_down_e.ros<br>impact: act_ingoreself_t_down_e.ros | cast-start: skill_holyprotect_c_down_e.mp3<br>impact: skill_ingoreself_t_down_e.mp3 |
| Disregard Danger | 493273 | cast-start: act_fire_hand_wave_c_hand_e.ros<br>impact: act_ingoreself_t_down_e.ros | cast-start: act_fire_hand_wave_c_hand_e.ros.mp3<br>impact: skill_ingoreself_t_down_e.mp3 |
## Scout — base
| Skill | Source spell IDs | Effect phase and source model | Sound phase and source cue |
| --- | --- | --- | --- |
| Arrow of Essence | 490494 | impact: act_mentalarrow_t_freeze_hit.ros | impact: act_mentalarrow_t_freeze_hit.mp3 |
| Wind Arrows | 491128 | release: act_gustwindarrow_f_hit_point_i.ros<br>impact: act_gustwindarrow_t_hit_point_e.ros<br>impact: act_icearrow_t_hit_point.ros | release: act_gustwindarrow_f_hit_point_i.ros.mp3<br>impact: act_gustwindarrow_t_hit_point_e.mp3<br>impact: act_gustwindarrow_f_hit_point_e.mp3<br>impact: act_icearrow_t_hit_point.mp3 |
| Mana Drain Shot | 490441 | release: act_sorcerersting_f.ros | release: act_sorcerersting_f.mp3 |
| Lasso | 490454 | cast-start: act_casting_c_hand.ros | cast-start: act_casting_c_hand.wav |
| Piercing Arrow | 490400 | release: act_immolatingshot_f.ros<br>impact: act_immolatingshot_t_hit_point.ros | release: act_immolatingshot_f.mp3<br>impact: act_immolatingshot_t_hit_point.mp3 |
| Snipe | 490450 | release: act_snipe_f.ros<br>impact: act_snipe_t_freeze_hit.ros | release: act_snipe_f.mp3<br>impact: act_snipe_t_freeze_hit.mp3 |
| Detection | 490463 | cast-start: act_focus_c_top.ros<br>cast-start: act_focus_c_down.ros | cast-start: act_focus_c_top.mp3 |
| Combo Shot | 490424 | release: act_arrow_f.ros<br>impact: act_arrow_t_hit_point.ros | release: act_arrow_f.mp3<br>impact: act_arrow_t_hit_point.mp3 |
| Neck Strike | 490438 | impact: act_neckattack_t_mouth.ros | impact: act_neckattack_t_mouth.mp3 |
| Reflected Shot | 490457 | release: act_deflecting_shot_f.ros<br>impact: act_deflecting_shot_t_freeze_hit.ros | release: act_deflecting_shot_f.mp3<br>impact: act_deflecting_shot_t_freeze_hit.mp3 |
| Concentration | 490460 | impact: act_concentration_t_top.ros | impact: act_concentration_t_top.mp3 |
| Target Area | 490464 | cast-start: act_physical_casting_c_hand.ros<br>cast-start: act_shooterexpert_c_down.ros | cast-start: act_physical_casting_c_hand.mp3<br>cast-start: act_shooterexpert_c_down.mp3 |
| Frost Arrow | 491163 | release: act_icearrow_f.ros<br>impact: act_icearrow_t_hit_point.ros | release: act_icearrow_f.mp3<br>impact: act_icearrow_t_hit_point.mp3 |
| Autoshot | 492589 | release: act_normalarrow_f_i.ros<br>impact: act_arrow_t_hit_point.ros | impact: act_arrow_t_hit_point.mp3 |
| Shot | 490423 | release: act_arrow_f.ros<br>impact: act_arrow_t_hit_point.ros | release: act_arrow_f.mp3<br>impact: act_arrow_t_hit_point.mp3 |
| Vampire Arrows | 491292 | release: act_bitesbloodarrow_f_hit_point_i.ros<br>impact: act_bitesbloodarrow_t_hit_point_e.ros<br>impact: act_bloodstain_t_freeze_down.ros | impact: act_bitesbloodarrow_t_hit_point_e.mp3<br>impact: act_bloodstain_t_freeze_down.mp3 |
| Joint Blow | 490420 | impact: act_jointattack_t_freeze_hit.ros | impact: act_jointattack_t_freeze_hit.mp3 |
| Blood Arrow | 490434 | cast-start: act_fear_c_hand.ros | — |
| Throat Attack | 490428 | impact: act_throatattack_t_mouth.ros | impact: act_throatattack_t_mouth.mp3 |
| Wrist Attack | 490451 | impact: act_handoff_t_freeze_hit_e.ros | impact: act_handoff_t_freeze_hit_e.mp3 |
## Scout — accepted elite pair
| Skill | Source spell IDs | Effect phase and source model | Sound phase and source cue |
| --- | --- | --- | --- |
| Weak Spot | 491493 | release: act_bitesbloodarrow_f_hit_point_i.ros<br>impact: act_lockbuff_t_top.ros | impact: act_lockbuff_t_top.mp3 |
| Blinding Powder | 491336 | impact: act_blindpowder_t_top_e.ros | impact: act_blindpowder_t_top_e.mp3 |
| Sapping Arrow | 491496 | release: act_weakarrow_f_i.ros<br>impact: act_weakarrow_t_freeze_hit_e.ros | impact: act_weakarrow_t_freeze_hit_e.mp3 |
| Deadly Poison Bite | 492621 | cast-start: act_poison_casting_c_hand.ros<br>release: act_deadlypoison_f_i.ros<br>impact: act_deadlypoison_t_hit_point_e.ros<br>impact: act_bitesbloodarrow_t_hit_point_e.ros | impact: skill_deadlypoison_t_hit_point_e.mp3<br>impact: act_bitesbloodarrow_t_hit_point_e.mp3 |
## Rogue — base
| Skill | Source spell IDs | Effect phase and source model | Sound phase and source cue |
| --- | --- | --- | --- |
| Assassins Rage | 490506 | cast-start: act_absolute_strike_c_top.ros | cast-start: act_absolute_strike_c_top.mp3 |
| Low Blow | 490323 | impact: act_crow01_t_hit_point.ros | impact: act_crow01_t_hit_point.mp3 |
| Wound Attack | 490313 | impact: act_scotch_t_freeze_hit.ros | impact: act_scotch_t_freeze_hit.mp3 |
| Blind Spot | 490311 | impact: act_fracture01_t_freeze_hit.ros | impact: act_fracture01_t_freeze_hit.mp3 |
| Numbing Dagger | 490347 | cast-start: nor_dark_casting.ros<br>release: act_throw01_f.ros | release: act_throw.mp3 |
| Poison | 490329 | cast-start: act_apply_poison_c_hand.ros | cast-start: act_apply_poison_c_hand.mp3 |
| Hide | 490312 | cast-start: act_snug_c_freeze_down.ros | cast-start: act_snug_c_freeze_down.mp3 |
| Premeditation | 490507 | cast-start: act_premeditation_c_hand.ros | cast-start: act_premeditation_c_hand.mp3 |
| Sneak Attack | 490337 | impact: act_sneak_attack_t_freeze_hit.ros | impact: act_scotch_t_freeze_hit.mp3 |
| Vanish | 490354 | cast-start: act_hiding_c_freeze_down.ros | cast-start: act_hiding_c_freeze_down.mp3 |
| Sprint | 490341 | cast-start: act_speedup01_c_down.ros | cast-start: act_speedup01_c_down.mp3 |
| Evasion | 490355 | cast-start: act_illusionmoving_c_down.ros | cast-start: act_illusionmoving_c_down.mp3 |
| Combo Throw | 490338 | release: act_throw01_f.ros<br>impact: act_throw01_t_hit_point.ros | release: act_throw.mp3<br>impact: act_throw01_t_hit_point.mp3 |
| Shadow Prison | 490346 | cast-start: act_dark_hand_wave_c_hand_e.ros | — |
| Informer | 490350 | impact: nor_hitrateup_t_down_e.ros | — |
| Fervent Attack | 490333 | cast-start: act_attackspeedup_c_down.ros | cast-start: act_attackspeedup_c_down.mp3 |
| Shadowstab | 490306 | impact: act_serpentine_t_freeze_hit.ros | impact: act_serpentine_t_freeze_hit.mp3 |
| Throw | 490309 | release: act_throw01_f.ros<br>impact: act_throw01_t_hit_point.ros | release: act_throw.mp3<br>impact: act_throw01_t_hit_point.mp3 |
| Blind Stab | 490317 | impact: act_blind01_t_freeze_hit.ros | impact: act_blind01_t_freeze_hit.mp3 |
| Shadow Step | 490344 | cast-start: act_shadowmoving_c_down.ros<br>cast-start: act_disaster_appear_c_down_e.ros | cast-start: act_shadowmoving_c_down.mp3<br>cast-start: act_disaster_appear_c_down_e.mp3 |
## Rogue — accepted elite pair
| Skill | Source spell IDs | Effect phase and source model | Sound phase and source cue |
| --- | --- | --- | --- |
| Death's Touch | 491339 | cast-start: act_dark_hand_wave_c_hand_e.ros<br>impact: act_deathtouch_t_down_e.ros<br>impact: act_serpentine_t_freeze_hit.ros | impact: act_deathtouch_t_down_e.mp3<br>impact: act_serpentine_t_freeze_hit.mp3 |
| Poisonous Infection | 492625 | impact: act_poisondot_t_down.ros | impact: act_poisondot_t_down.mp3 |
| Poison Spray | 492920 | cast-start: act_earth_hand_wave_c_hand_e.ros<br>impact: act_vriusinfection_t_freeze_down_e.ros | cast-start: act_earth_hand_wave_c_hand_e.mp3<br>impact: skill_vriusinfection_t_freeze_down_e.mp3 |
| Decay | 493017 | impact: act_rot_t_down_e.ros | impact: skill_rot_t_down_e.mp3 |
## Mage — base
| Skill | Source spell IDs | Effect phase and source model | Sound phase and source cue |
| --- | --- | --- | --- |
| Elemental Catalysis | 490238, 497971 | cast-start: act_casting_c_hand.ros<br>cast-start: act_castup01_c_down.ros | cast-start: act_casting_c_hand.mp3<br>cast-start: act_castup01_c_down.mp3 |
| Flame | 491150 | cast-start: act_fireball01_c_hand_i.ros<br>cast-start: act_fireball02_c_hand_e.ros<br>release: act_fireball01_f_i.ros<br>impact: act_fireball01_t_freeze_hit_e.ros | cast-start: act_vengeance_c_hand.mp3<br>cast-start: act_fireball02_c_hand_e.ros.mp3<br>release: act_fireball02_f.mp3<br>impact: act_fireball01_t_freeze_hit_e.ros.mp3 |
| Electrostatic Charge | 491156 | cast-start: act_casting_c_hand.ros<br>cast-start: act_electricfield_c_top.ros<br>aura-start: act_electricfieldbuff_c_down_i.ros | cast-start: act_casting_c_hand.mp3<br>cast-start: act_electricfield_c_top.mp3<br>aura-start: act_electricfieldbuff2.mp3<br>aura-start: act_electricfieldbuff_c_down_i.ros.mp3 |
| Discharge | 490242 | cast-start: act_wind_hand_wave_c_hand_e.ros<br>cast-start: act_lightningstrike_c_shoot.ros<br>cast-start: act_deep_thought_c_down_e.ros | cast-start: act_lightningstrike_c_shoot.mp3 |
| Meteor Shower | 490252 | cast-start: act_noncasting_c_hand.ros<br>impact: act_shottingstars_t_down.ros | impact: act_shottingstars_t_down.mp3 |
| Phoenix | 490239 | cast-start: act_vengeance_c_hand.ros<br>cast-start: act_phoenix_c_freeze_down.ros<br>cast-start: act_deep_thought_c_down_e.ros<br>impact: act_firedot_t_down.ros | cast-start: act_vengeance_c_hand.mp3<br>cast-start: act_phoenix_c_freeze_down.ros.mp3<br>impact: act_firedot_t_down.mp3 |
| Purgatory Fire | 491153 | cast-start: act_fireball02_c_hand_e.ros<br>impact: act_fireball01_t_freeze_hit_e.ros<br>impact: act_firedot_t_down.ros | cast-start: act_fireball02_c_hand_e.ros.mp3<br>impact: act_fireball01_t_freeze_hit_e.ros.mp3<br>impact: act_firedot_t_down.mp3 |
| Energy Influx | 490218 | aura-start: act_magebuff01_c_top.ros | aura-start: act_magebuff01_c_top.ros.mp3 |
| Energy Well | 490251 | impact: act_manareduce01_c_hit_point.ros | impact: act_manareduce01_c_hit_point.mp3 |
| Elemental Weakness | 490247, 497977 | cast-start: act_casting_c_hand.ros<br>impact: act_elementdecay_t_down.ros | cast-start: act_dark_casting_c_hand.wav<br>impact: act_elementdecay_t_down.mp3 |
| Thunderstorm | 490244 | cast-start: act_casting_c_hand.ros<br>cast-start: act_torodo_c_freeze_down.ros<br>impact: act_rushlevel_fail_c_hit.ros | cast-start: act_casting_c_hand.mp3<br>cast-start: act_torodo_c_freeze_down.ros.mp3<br>impact: act_rushlevel_fail_c_hit.ros.mp3 |
| Plasma Arrow | 491169 | cast-start: act_electric_casting_c_hand_i.ros<br>release: act_electric_arrow_f_i.ros<br>impact: act_electric_explode_t_freeze_hit_e.ros | cast-start: act_electric_casting_c_hand_i_db.mp3<br>cast-start: act_electric_casting_c_hand_ifadein.mp3<br>release: act_electric_arrow_f_i.ros.mp3<br>impact: act_electric_explode_t_freeze_hit_e.ros.mp3 |
| Electric Bolt | 491168 | cast-start: act_electric_casting_c_hand_i.ros<br>release: act_electric_ball_f_i.ros<br>impact: act_electric_ball_t_freeze_hit_e.ros<br>impact: act_electric_dot_t_down_e.ros | cast-start: act_electric_casting_c_hand_i_db.mp3<br>cast-start: act_electric_casting_c_hand_ifadein.mp3<br>impact: act_electric_dot_t_down_e.ros.mp3 |
| Electric Explosion | 491170 | cast-start: act_electric_casting_c_hand_i.ros<br>impact: act_electric_explode_f_i.ros<br>impact: act_electric_explode_t_freeze_hit_e.ros | cast-start: act_electric_casting_c_hand_i_db.mp3<br>cast-start: act_electric_casting_c_hand_ifadein.mp3<br>impact: act_electric_explode_f_i.ros.mp3<br>impact: act_electric_explode_t_freeze_hit_e.ros.mp3 |
| Electric Compression | 491171 | cast-start: act_electricnet_recharge_c_down_e.ros | cast-start: act_electricnet_recharge_c_down_e.ros.mp3 |
| Static Field | 491172 | cast-start: act_electric_casting_c_hand_i.ros<br>cast-start: act_electric_net_c_down_e.ros<br>impact: act_electric_net_t_down_i.ros | cast-start: act_electric_casting_c_hand_i_db.mp3<br>cast-start: act_electric_casting_c_hand_ifadein.mp3<br>cast-start: act_electric_net_c_down_e.ros.mp3<br>impact: act_electric_net_t_down_i.ros.mp3 |
| Fireball | 490204 | cast-start: act_fire_hand_wave_c_hand_e.ros<br>cast-start: act_deep_thought_c_down_e.ros<br>release: act_fireball02_f.ros<br>impact: act_fireball02_t_hit_point.ros | cast-start: act_fire_hand_wave_c_hand_e.ros.mp3<br>release: act_fireball02_f.mp3<br>impact: act_fireball02_t_hit_point.mp3 |
| Lightning | 490212 | cast-start: act_wind_hand_wave_c_hand_e.ros<br>cast-start: act_deep_thought_c_down_e.ros<br>impact: act_summonlighting_t_hit_point.ros | impact: act_summonlighting_t_hit_point.mp3 |
| Intensification | 490225, 497976 | — | — |
| Silence | 490296 | cast-start: act_casting_c_hand.ros<br>cast-start: act_dark_hand_wave_c_hand_e.ros | cast-start: act_dark_casting_c_hand.wav |
| Fire Ward | 490248 | cast-start: act_vengeance_c_hand.ros<br>cast-start: act_fireresistance_c_top.ros | cast-start: act_vengeance_c_hand.mp3<br>cast-start: act_fireresistance_c_top.mp3 |
## Mage — accepted elite pair
| Skill | Source spell IDs | Effect phase and source model | Sound phase and source cue |
| --- | --- | --- | --- |
| Static Resonance | 498744 | cast-start: act_electricity-field_c_down_e.ros | cast-start: act_electricity-field_c_down_e.mp3 |
| Breath Erase | 498750 | cast-start: act_hide_c_down_e.ros | cast-start: act_hide_c_down_e.mp3 |
| Soul Stepping | 498757 | cast-start: act_soul_walker_c_down_e.ros | cast-start: act_soul_walker_c_down_e.mp3 |
| Deep Inspiration | 498758 | cast-start: act_deep_open_c_down_e.ros | cast-start: act_deep_open_c_down_e.mp3 |
| Fire Lightning Burst | 498759 | cast-start: act_fireball01_c_hand_i.ros<br>cast-start: act_electric_casting_c_hand_i.ros<br>release: act_fire-thunder_f.ros<br>impact: act_fire-thunder_t_hitpoint_e.ros | cast-start: act_vengeance_c_hand.mp3<br>cast-start: act_electric_casting_c_hand_i_db.mp3<br>cast-start: act_electric_casting_c_hand_ifadein.mp3<br>release: act_fire-thunder_f02.wav<br>release: act_fire-thunder_f01.mp3<br>impact: act_fire-thunder_t_hitpoint_e.mp3 |
## Decoded particle archive
The particle archive covers 170 referenced ROS models, with 9 fully decoded models and 161 partial models. 74 models are renderer-ready and 1 has a browser-playable partial original. The Priest holy cast's remaining EventTrigger is an audio callback; Urgent Heal's target renders its source sprites, emitted rune mesh, and animated ground decal. Its terrain-triangle decal projection remains approximated by a level plane. The archive exports 668 sprite controllers and 139 distinct PNG textures. See `public/assets/game/combat-effects/original/runewaker/manifest.json` for per-model details.
## Next conversion step
The WebGL sprite renderer plays Priest Urgent Heal, Heal, and Group Heal casting; Urgent Heal's target impact with its source rune mesh and decal; Rising Tide's cast, projectile release, and target impact; Knight Charge cast and Whirlwind Shield impact; and Mage Electric Bolt projectile. Urgent Heal's holy cast EventTrigger starts a looping 3D WAV, and its target impact triggers the source benedictory heal MP3. Rising Tide retains its packaged cast WAV and now plays its ROS-linked projectile release and target impact MP3s. Impact cues use the target position. Urgent Heal's decal uses a level plane in place of the client's terrain projection. The Direct3D source and packaged ROS data remain the reference for subsequent phases.
+39
View File
@@ -0,0 +1,39 @@
# RuneWaker dungeon maps
The RuneWaker minimap shows a cropped dungeon map centered on the live player
marker. Press **M** or click the minimap to open the full map. The player marker
and heading, entrance, and numbered encounters use the same coordinate projection
in both views. The full map closes with **M**. The existing map keybind and minimap
rotation preference apply to RuneWaker dungeons too.
All 30 imported RuneWaker dungeon definitions have maps. Fifteen use calibrated
minimap tiles from the extracted RuneWaker client. Fifteen use floorplans rendered
from each dungeon's imported navigation mesh because matching client tiles are
missing or cannot be aligned confidently. The floorplans still place live markers
and encounters at their runtime coordinates. The UI labels a floorplan as such.
## Reimporting
Run `python scripts/runewaker-pipeline/import-maps.py` from the HealerMan root with
Pillow and NumPy available. `RUNEWAKER_ROOT` can point to the extracted RuneWaker
client; the default is `../Runewaker`. The importer reads DDS tiles under
`Resource/texture/minimap`, the primary WDB placement in each dungeon's
`import-metadata.json`, and the navigation GLB. It measures alignment between the
tile artwork and navigation geometry, accepts client artwork at confidence 0.65
or higher, and creates a navigation floorplan otherwise.
The generated PNGs live at `public/assets/game/dungeons/<id>/maps/runewaker-map.png`.
The runtime projection and source checksums live in
`src/game/generated/runewakerDungeonMaps.generated.json`. The map loader rejects
catalog entries when the dungeon map ID, coordinate transform, or visual checksum
no longer matches the runtime definition. Reimport after changing those inputs.
Run `npm run content:publish` after reimporting so downloadable dungeon packs
contain their map PNGs, then `npm run build` to refresh the bundled app.
## Verification
Run `node node_modules/vitest/vitest.mjs run src/game/dungeonArtworkMap.test.ts src/ui/DungeonMapGraphic.test.ts src/ui/MapPanel.test.ts`.
`node scripts/playtest-runewaker-maps.cjs` checks Forsaken Abbey in a browser,
including its downloaded artwork, minimap, M-key full map, and marker projection.
Screenshots are written to `artifacts/playtest/runewaker-maps/`.
+110
View File
@@ -0,0 +1,110 @@
# WoW bite-sized dungeon slice audit
## Scope and decision rule
This is a first-pass design audit of the 51 standard WoW dungeons already imported by Healer Man (Classic through Wrath of the Lich King). The map atlas and campaign catalog are the project source of truth for the layouts and encounter names. Three additional imported definitions are Healer Man / Ascension custom dungeons, so they are not part of this WoW pass.
A good slice should feel like a complete short outing: a clear reason to enter, one strong visual space or route, a handful of combat beats, and one satisfying final encounter. The closest existing model is **Stormwind Stockade: Cellblock Rush**: keep the original environment, retain one route, wall off the side wings, and finish on one seeded boss. Some source dungeons have a scripted event that makes an even better slice, but that event also raises implementation cost.
Ratings:
- **A — prototype first:** a distinctive, self-contained route or set piece with a natural finish.
- **B — promising:** a useful slice exists, but topology, gates, optional routes, or event handling need more design.
- **C — keep whole / no clean cut:** the full dungeon is already compact or event-led, or a cut would lose what makes the instance work.
The three first-pass candidates below are registered as derived Bite-Sized dungeons. After the first play report, the Wailing escort was replaced with Verdan’s room fight, the Deadmines entry was moved onto Mr. Smite’s source spawn, and Skadi’s hidden start interaction was replaced with a guard clear. The Skadi entrance and guards now occupy the connected source wave corridor. Companion navigation, wipes, completion, and results still need an in-game pass.
| Prototype | Implemented slice | Open playtest question |
| --- | --- | --- |
| Wailing Caverns — Verdan’s Lair | Starts inside Verdan’s chamber at a navigation-surface point. Three source cave mobs spawn in the room; defeating all three activates Verdan. Naralex and Mutanus remain only in the full dungeon. | Confirm the room population, Verdan activation, party targeting, and completion in play. |
| The Deadmines — Take the Ship | Starts at Mr. Smite’s source floor position, clears the ship population, gates VanCleef behind Captain Greenskin, then ends in the cabin. | Confirm the new start is grounded and the ship route remains walkable. |
| Utgarde Pinnacle — Skadi’s Gauntlet | Starts on the grounded source wave corridor. Defeating three first-wave guards along that corridor activates Skadi at its far end. The long waves and harpoons are omitted from this short run. | Confirm Skadi appears after the guard clear and the fight completes without an interaction. |
Each derived ID resolves to its source dungeon’s content pack and map asset directory through `dungeonContentSourceId`; the original full-length dungeon remains unchanged. The new entries are labeled Bite-Sized and beta until those playtests are recorded.
## Best first prototypes
| Rank | Dungeon slice | Why it fits | Main implementation question |
| --- | --- | --- | --- |
| 1 | **Wailing Caverns — Verdan’s Lair:** clear the chamber mobs, then fight Verdan the Everliving. | One navigable cave room and a clear boss reveal keep the run short. The Naralex escort remains a future, more complex candidate. | Verify the room floor, combat spacing, and boss activation in play. [Dungeon overview](https://warcraft.wiki.gg/wiki/Wailing_Caverns) |
| 2 | **The Deadmines — Take the Ship:** enter at Mr. Smite’s deck position, clear the ship, fight Captain Greenskin, then finish Edwin VanCleef in the cabin. | One strong visual set piece, a straightforward forward route, and a natural boss finale. The optional Cookie detour can be left out. [Classic guide](https://warcraft.wiki.gg/wiki/Deadmines_%28Classic%29) |
| 3 | **Zul’Farrak — The Staircase:** start at the pyramid event, survive Sergeant Bly’s descending waves, and finish at Chief Ukorz’s chamber. | The stair defense is already a compact wave encounter with a clear spatial progression; it could be a bite-sized run by itself or a short prelude into a boss. | Choose whether Bly and his group are protected participants or replace the event with a controlled wave sequence; the event’s outcome opens the Ukorz route. [Instance map and event guide](https://ptgmedia.pearsoncmg.com/imprint_downloads/brady/wow/zulfarrak/zulfarrak_lr.pdf) |
| 4 | **The Blood Furnace — Broggok’s Breakout:** begin at the prison cells, release the waves, then push through the final corridor to Keli’dan. | A tight industrial route with a built-in escalation and a boss payoff. The map is compact and the three encounters already form a clean progression. [Dungeon overview](https://warcraft.wiki.gg/wiki/Blood_Furnace) |
| 5 | **Utgarde Pinnacle — Skadi’s Gauntlet:** defeat the guards at Eagle’s Eye, then fight Skadi on the approach. | The short implementation gives the route an immediate, visible boss payoff. A full moving-wave and harpoon event remains a separate candidate. [Encounter guide](https://www.icy-veins.com/wotlk-classic/utgarde-pinnacle-dungeon-guide) |
| 6 | **Pit of Saron — The Quarry Breakout:** free the enslaved workers, clear the ambushes and tunnel, then confront Tyrannus. | A linear outdoor quarry gives the route space to breathe, and the rescue objective gives a strong reason to advance. The original instance already frames the final boss around freeing the slaves. [Dungeon overview](https://warcraft.wiki.gg/wiki/Pit_of_Saron) |
| 7 | **The Shattered Halls — Kargath’s Gauntlet:** start around Warbringer O’Mrogg, push through the final gauntlet, and finish in Kargath’s arena. | A direct late-dungeon route with a clear arena payoff. It works best if the final hallway pressure is the feature, not just a boss rush. |
| 8 | **Shadow Labyrinth — The Screaming Hall:** begin around Grandmaster Vorpil’s chamber and advance along the final hall to Murmur. | The project map shows a long, distinct finale corridor, and the two-boss ending provides a natural short arc without needing to reproduce the whole labyrinth. [Dungeon overview](https://warcraft.wiki.gg/wiki/Shadow_Labyrinth) |
| 9 | **Halls of Lightning — Ionar to Loken:** use the storm overlook and the route into Loken’s sanctum as the final ascent. | Strong visual progression from open storm space to titan interior; Ionar already guards the entrance to Loken’s sanctum. [Ionar’s encounter context](https://warcraft.wiki.gg/wiki/Ionar) |
**Current first batch:** Verdan’s Lair, Take the Ship, and Skadi’s Gauntlet. These now use short room and route progressions with explicit boss activation.
## Full 51-dungeon scan
| Expansion | Dungeon | Best bite-sized slice to investigate | Rating |
| --- | --- | --- | :---: |
| Classic | Shadowfang Keep | Fenrus through Wolf Master Nandos and up to Arugal’s tower. | B |
| Classic | Stormwind Stockade | The existing central Cellblock Rush is already the reference design. | C |
| Classic | The Deadmines | Mr. Smite’s ship ramp through Greenskin to VanCleef’s cabin. | A |
| Classic | Wailing Caverns | Verdan’s chamber fight now; Naralex escort is deferred. | A |
| Classic | Razorfen Kraul | The deeper boar warrens and Charlga’s area; the open, branching route needs a firm start boundary. | B |
| Classic | Blackfathom Deeps | Kelris’s altar ritual and the opened route to Aku’mai. | B |
| Classic | Uldaman | The late titan-vault approach to Archaedas. | B |
| Classic | Gnomeregan | The Clean Zone and final approach to Thermaplugg. | B |
| Classic | Sunken Temple | The lower sanctum / Avatar of Hakkar ritual through Shade of Eranikus. | B |
| Classic | Razorfen Downs | The Spiral of Thorns and Amnennar’s crypt, with the optional Belnistrasz escort kept as a variant. | B |
| Classic | Scarlet Monastery | Use the Cathedral wing as a complete bite-sized outing; it is a wing-sized instance, not a clean internal cut. | B |
| Classic | Zul’Farrak | The staircase defense, optionally continuing to Ukorz. | A |
| Classic | Blackrock Spire | The Upper Spire final ascent from Rend’s arena toward Drakkisath. Strong setting, but multiple floors and gates. | B |
| Classic | Blackrock Depths | No first choice: the instance is a large connected maze of branches, keys, and optional bosses. A later pass could define one exact route. | C |
| Classic | Scholomance | The upper-school finale from the Barov wing to Ras Frostwhisper. | B |
| Classic | Stratholme | The undead-quarter approach and final Baron fight; keep the timed Gauntlet as the main pressure beat. | B |
| Classic | Maraudon | The inner cavern / waterfall route to Princess Theradras. | B |
| Classic | Ragefire Chasm | Keep the whole short instance; cutting it further would leave too little journey. | C |
| Classic | Dire Maul | Pick one wing only—especially the West Wing route through Immol’thar to Prince Tortheldrin. The combined map has too many cross-wing choices for a casual cut. | B |
| Burning Crusade | Hellfire Ramparts | Keep the full compact instance rather than extracting one corridor. | C |
| Burning Crusade | The Blood Furnace | Broggok’s prison event through Keli’dan. | A |
| Burning Crusade | The Shattered Halls | O’Mrogg through the final gauntlet into Kargath’s arena. | A |
| Burning Crusade | The Slave Pens | The lower tunnels from Rokmar to Quagmirran; very short, so include both encounters and the water route. | B |
| Burning Crusade | The Underbog | The late fungal/swamp route from Swamplord Musel’ek to the Black Stalker. | B |
| Burning Crusade | The Steamvault | The lower waterworks and final route to Kalithresh. | B |
| Burning Crusade | The Arcatraz | The last containment section and release sequence leading to Skyriss. | B |
| Burning Crusade | The Botanica | The final greenhouse route from Laj to Warp Splinter. | B |
| Burning Crusade | The Mechanar | The upper-platform route from Sepethrea to Pathaleon; elevators and crossing routes need to be kept legible. | B |
| Burning Crusade | Shadow Labyrinth | Vorpil through the Screaming Hall to Murmur. | A |
| Burning Crusade | Sethekk Halls | Keep the whole short two-boss instance. | C |
| Burning Crusade | Mana-Tombs | Keep the full three-boss route; no internal cut improves it much. | C |
| Burning Crusade | Auchenai Crypts | Keep the full compact two-boss run. | C |
| Burning Crusade | Magisters’ Terrace | Vexallus through the final Kael’thas chamber; a viable one-boss finale if the full instance is too long. | B |
| Burning Crusade | The Black Morass | Keep the full portal-defense event; splitting it would remove the core mechanic. | C |
| Burning Crusade | The Escape from Durnholde | Keep the full escort-and-escape story; it is already a self-contained event run. | C |
| Wrath | Utgarde Keep | Keep the full short three-boss route. | C |
| Wrath | Utgarde Pinnacle | Eagle’s Eye guard clear and Skadi; the full wave and harpoon event is deferred. | A |
| Wrath | The Nexus | A single mage/arcane wing could work, but the boss route crosses a hub; map a route before choosing a cut. | B |
| Wrath | The Oculus | No first choice: drake riding and multi-level flight are the dungeon’s identity and make a small walking route misleading. | C |
| Wrath | The Culling of Stratholme | Keep the whole compact timed story run, including its city push and final encounter. | C |
| Wrath | Halls of Stone | The Tribunal event into Sjonnir is a good short encounter episode; use the full instance if event staging is too costly. | B |
| Wrath | Drak’Tharon Keep | King Dred through the upper temple to Tharon’ja. | B |
| Wrath | Azjol-Nerub | Keep the full compact three-boss descent; the instance already reads as one short journey. | C |
| Wrath | Halls of Lightning | Ionar’s overlook into Loken’s sanctum. | A |
| Wrath | Gundrak | The late temple route from Moorabi toward Gal’darah; the connected ramps and branches need a deliberate route boundary. | B |
| Wrath | Violet Hold | Keep the full prison-defense event; the wave sequence is the dungeon. | C |
| Wrath | Ahn’kahet: The Old Kingdom | The last organic/Old God passage from Jedoga toward Herald Volazj; leave the optional Amanitar branch out. | B |
| Wrath | The Forge of Souls | Keep the full two-boss instance. | C |
| Wrath | Trial of the Champion | Keep the full arena event; its staged opponent sequence is already bite-sized. | C |
| Wrath | Pit of Saron | Slave rescue, quarry ambushes, tunnel, and Tyrannus. | A |
| Wrath | Halls of Reflection | Keep the full two-boss defense and escape sequence. | C |
## Design takeaways
- Favor a starting point at a real midpoint or event trigger, then seal or ignore side routes the way the Stockades variant does.
- One boss is enough when the route has a clear event or traversal payoff. Two bosses work when both are close together, as on the Deadmines ship.
- The best slice is not always the last two bosses. The Zul’Farrak stairs and Skadi’s gauntlet are strong because the route itself is the memorable content.
- Avoid slices whose identity depends on a complex escort, vehicle, multi-floor hub, or many interactable gates unless that event is the specific feature being built.
- Use the imported maps for candidate boundaries, then confirm start position, reachable path, enemy density, and encounter state in the running game before implementation.
## Project references
- [WoW dungeon maps and import scope](WOW_DUNGEON_MAPS.md)
- [Existing bite-sized Stockades definition](../src/game/dungeons/biteSizedStockades.ts)
- [Current WoW dungeon functionality gate](../dungeon-pipeline/WOW_DUNGEON_FUNCTIONALITY_REPORT.md)
- [Generated campaign catalog and encounter order](../src/game/generated/dungeonCampaignCatalog.compressed.ts)
+3 -2
View File
@@ -12,8 +12,9 @@ the selected floor are not clamped to a misleading marker at the map edge.
The current import includes 51 standard WoW dungeons and 107 unique map images. The
custom Tinkertech Showdown, Frozen Reach, and Forgotten Mine have no matching map
records in the supplied archives and retain their survey maps. RuneWaker maps are
unchanged. Missing images also fall back to the survey projection.
records in the supplied archives and retain their survey maps. Missing images also
fall back to the survey projection. RuneWaker dungeons use the same map controls;
see [RuneWaker dungeon maps](RUNEWAKER_DUNGEON_MAPS.md).
## Reimporting
Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

+121
View File
@@ -0,0 +1,121 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="700" viewBox="0 0 1200 700">
<defs>
<linearGradient id="backdrop" x2="1" y2="1"><stop stop-color="#193628"/><stop offset="1" stop-color="#06100e"/></linearGradient>
<linearGradient id="panel" x2="1" y2="1"><stop stop-color="#27312a"/><stop offset="1" stop-color="#0c1714"/></linearGradient>
<radialGradient id="portrait"><stop stop-color="#435549"/><stop offset="1" stop-color="#111d1a"/></radialGradient>
<linearGradient id="scale" x2=".8" y2="1"><stop stop-color="#aac49b"/><stop offset=".45" stop-color="#4d8067"/><stop offset="1" stop-color="#1d4b42"/></linearGradient>
<linearGradient id="belly" x2="1" y2=".8"><stop stop-color="#eee5a5"/><stop offset="1" stop-color="#a7a474"/></linearGradient>
<linearGradient id="guardian-fill" x2=".8" y2="1"><stop stop-color="#aad36f"/><stop offset=".48" stop-color="#568d49"/><stop offset="1" stop-color="#274f37"/></linearGradient>
<filter id="shadow"><feDropShadow dx="0" dy="12" stdDeviation="17" flood-opacity=".7"/></filter>
<filter id="creature-shadow"><feDropShadow dx="0" dy="5" stdDeviation="4" flood-opacity=".7"/></filter>
<g id="serpent" filter="url(#creature-shadow)">
<path d="M24 92 C8 75 30 61 53 69 C84 79 89 55 69 45 C53 37 54 23 67 18" fill="none" stroke="#193f37" stroke-width="26" stroke-linecap="round"/>
<path d="M24 91 C12 77 36 65 55 73 C82 82 92 54 70 44 C56 36 57 23 68 18" fill="none" stroke="url(#scale)" stroke-width="19" stroke-linecap="round"/>
<path d="M27 84 C35 76 43 75 52 78 M67 73 C75 70 79 62 78 56 M67 41 C59 32 62 22 68 18" fill="none" stroke="url(#belly)" stroke-width="6" stroke-linecap="round" opacity=".85"/>
<path d="M62 25 L56 15 L64 18 L67 9 L74 17 L82 14 L79 25 Q78 35 70 36 Q61 35 62 25" fill="url(#scale)" stroke="#173d34" stroke-width="2"/>
<path d="M62 33 Q69 43 77 33 L73 48 L69 40 L64 48Z" fill="#e2cf9c"/>
<circle cx="65" cy="25" r="2.5" fill="#f8d378"/><circle cx="75" cy="25" r="2.5" fill="#f8d378"/>
</g>
<g id="guardian" filter="url(#creature-shadow)">
<path d="M40 92 L22 76 L17 47 L29 28 L43 22 L63 26 L77 43 L82 75 L65 91Z" fill="url(#guardian-fill)" stroke="#214c30" stroke-width="3"/>
<path d="M24 41 L11 20 L31 31 M72 40 L90 18 L75 50" fill="url(#guardian-fill)" stroke="#214c30" stroke-width="3"/>
<path d="M38 30 L40 15 L50 25 L60 14 L66 33 M27 58 L10 53 L25 72 M76 59 L91 54 L80 76" fill="#427d3d" stroke="#1b472b" stroke-width="3"/>
<path d="M40 43 Q50 51 61 43 L65 71 Q50 80 35 69Z" fill="#9cc372" opacity=".8"/>
<path d="M35 38 L45 42 L41 46 M65 38 L55 42 L59 46" fill="#eae99e"/>
<path d="M40 58 Q50 63 61 58" fill="none" stroke="#173e29" stroke-width="4"/>
</g>
<g id="mutant" filter="url(#creature-shadow)">
<path d="M30 90 L20 65 L30 37 L45 29 L58 31 L73 45 L80 69 L68 91Z" fill="url(#scale)" stroke="#214b3e" stroke-width="3"/>
<path d="M34 35 L21 19 L24 42 M62 36 L75 18 L75 46" fill="url(#scale)" stroke="#214b3e" stroke-width="3"/>
<path d="M21 61 L5 53 L18 80 M76 58 L92 48 L84 80" fill="none" stroke="#376b56" stroke-width="12" stroke-linecap="round"/>
<path d="M36 51 L46 54 M62 51 L55 54" stroke="#e7dc89" stroke-width="5" stroke-linecap="round"/>
<path d="M38 66 Q49 80 62 66 L58 75 L54 69 L50 79 L46 69 L42 75Z" fill="#eadfb3"/>
</g>
</defs>
<rect width="1200" height="700" fill="url(#backdrop)"/>
<path d="M0 660Q130 310 300 490T760 365T1200 470V700H0" fill="#2c5037" opacity=".24"/>
<rect x="58" y="34" width="1084" height="632" rx="16" fill="url(#panel)" stroke="#8d7d56" stroke-width="2" filter="url(#shadow)"/>
<text x="88" y="102" font-family="Georgia,serif" font-size="38" fill="#f3ead1">Wailing Caverns</text>
<text x="88" y="132" font-family="Arial,sans-serif" font-size="14" fill="#b8b5a7">6 bosses ahead · 2 collected</text>
<path d="M978 56V140" stroke="#88764f"/>
<text x="1050" y="78" text-anchor="middle" font-family="Arial,sans-serif" font-size="11" letter-spacing="2" fill="#b8b5a7">ENTERING IN</text>
<text x="1050" y="134" text-anchor="middle" font-family="Georgia,serif" font-size="60" fill="#d5b875">05</text>
<g transform="translate(88 166)">
<rect width="320" height="210" rx="9" fill="#151f1b" stroke="#69b4ff" stroke-width="2"/>
<rect x="1" y="1" width="318" height="28" rx="8" fill="#0a1410"/>
<text x="12" y="19" font-family="Arial,sans-serif" font-size="11" letter-spacing="2" fill="#efe8d7">BOSS 01</text>
<text x="307" y="19" text-anchor="end" font-family="Arial,sans-serif" font-size="10" fill="#69b4ff">COLLECTED</text>
<rect x="7" y="31" width="306" height="113" rx="3" fill="url(#portrait)"/>
<ellipse cx="160" cy="137" rx="53" ry="5" fill="#030a08" opacity=".7"/>
<use href="#serpent" transform="translate(105 30) scale(1.08)"/>
<text x="13" y="164" font-family="Georgia,serif" font-size="20" fill="#f3ead1">Lady Anacondra</text>
<text x="13" y="181" font-family="Arial,sans-serif" font-size="11" fill="#b8b5a7">3 copies owned</text>
<path d="M0 187H320" stroke="#536357" opacity=".6"/>
<g transform="translate(12 191)"><rect width="21" height="21" rx="3" fill="#2a3a3c" stroke="#ddd8ce"/><text x="10.5" y="15" text-anchor="middle" font-family="Arial,sans-serif" font-size="12" fill="#ddd8ce">N</text></g><g transform="translate(39 191)"><rect width="21" height="21" rx="3" fill="#2a3a3c" stroke="#69b4ff"/><text x="10.5" y="15" text-anchor="middle" font-family="Arial,sans-serif" font-size="12" fill="#69b4ff">R</text></g><g transform="translate(66 191)"><rect width="21" height="21" rx="3" fill="#252f2c" stroke="#5c6a60"/><text x="10.5" y="15" text-anchor="middle" font-family="Arial,sans-serif" font-size="12" fill="#79877d">E</text></g><g transform="translate(93 191)"><rect width="21" height="21" rx="3" fill="#252f2c" stroke="#5c6a60"/><text x="10.5" y="15" text-anchor="middle" font-family="Arial,sans-serif" font-size="12" fill="#79877d">L</text></g>
</g>
<g transform="translate(440 166)">
<rect width="320" height="210" rx="9" fill="#151f1b" stroke="#69756b" stroke-width="1"/>
<rect x="1" y="1" width="318" height="28" rx="8" fill="#0a1410"/>
<text x="12" y="19" font-family="Arial,sans-serif" font-size="11" letter-spacing="2" fill="#efe8d7">BOSS 02</text>
<text x="307" y="19" text-anchor="end" font-family="Arial,sans-serif" font-size="10" fill="#a5a99b">UNCOLLECTED</text>
<rect x="7" y="31" width="306" height="113" rx="3" fill="url(#portrait)"/>
<ellipse cx="160" cy="137" rx="53" ry="5" fill="#030a08" opacity=".7"/>
<use href="#serpent" transform="translate(105 30) scale(1.08)"/>
<text x="13" y="164" font-family="Georgia,serif" font-size="20" fill="#f3ead1">Lord Cobrahn</text>
<text x="13" y="181" font-family="Arial,sans-serif" font-size="11" fill="#b8b5a7">Card not collected</text>
<path d="M0 187H320" stroke="#536357" opacity=".6"/>
<g transform="translate(12 191)"><rect width="21" height="21" rx="3" fill="#252f2c" stroke="#5c6a60"/><text x="10.5" y="15" text-anchor="middle" font-family="Arial,sans-serif" font-size="12" fill="#79877d">N</text></g><g transform="translate(39 191)"><rect width="21" height="21" rx="3" fill="#252f2c" stroke="#5c6a60"/><text x="10.5" y="15" text-anchor="middle" font-family="Arial,sans-serif" font-size="12" fill="#79877d">R</text></g><g transform="translate(66 191)"><rect width="21" height="21" rx="3" fill="#252f2c" stroke="#5c6a60"/><text x="10.5" y="15" text-anchor="middle" font-family="Arial,sans-serif" font-size="12" fill="#79877d">E</text></g><g transform="translate(93 191)"><rect width="21" height="21" rx="3" fill="#252f2c" stroke="#5c6a60"/><text x="10.5" y="15" text-anchor="middle" font-family="Arial,sans-serif" font-size="12" fill="#79877d">L</text></g>
</g>
<g transform="translate(792 166)">
<rect width="320" height="210" rx="9" fill="#151f1b" stroke="#69756b" stroke-width="1"/>
<rect x="1" y="1" width="318" height="28" rx="8" fill="#0a1410"/>
<text x="12" y="19" font-family="Arial,sans-serif" font-size="11" letter-spacing="2" fill="#efe8d7">BOSS 03</text>
<text x="307" y="19" text-anchor="end" font-family="Arial,sans-serif" font-size="10" fill="#a5a99b">UNCOLLECTED</text>
<rect x="7" y="31" width="306" height="113" rx="3" fill="url(#portrait)"/>
<ellipse cx="160" cy="137" rx="53" ry="5" fill="#030a08" opacity=".7"/>
<use href="#serpent" transform="translate(105 30) scale(1.08)"/>
<text x="13" y="164" font-family="Georgia,serif" font-size="20" fill="#f3ead1">Lord Pythas</text>
<text x="13" y="181" font-family="Arial,sans-serif" font-size="11" fill="#b8b5a7">Card not collected</text>
<path d="M0 187H320" stroke="#536357" opacity=".6"/>
<g transform="translate(12 191)"><rect width="21" height="21" rx="3" fill="#252f2c" stroke="#5c6a60"/><text x="10.5" y="15" text-anchor="middle" font-family="Arial,sans-serif" font-size="12" fill="#79877d">N</text></g><g transform="translate(39 191)"><rect width="21" height="21" rx="3" fill="#252f2c" stroke="#5c6a60"/><text x="10.5" y="15" text-anchor="middle" font-family="Arial,sans-serif" font-size="12" fill="#79877d">R</text></g><g transform="translate(66 191)"><rect width="21" height="21" rx="3" fill="#252f2c" stroke="#5c6a60"/><text x="10.5" y="15" text-anchor="middle" font-family="Arial,sans-serif" font-size="12" fill="#79877d">E</text></g><g transform="translate(93 191)"><rect width="21" height="21" rx="3" fill="#252f2c" stroke="#5c6a60"/><text x="10.5" y="15" text-anchor="middle" font-family="Arial,sans-serif" font-size="12" fill="#79877d">L</text></g>
</g>
<g transform="translate(88 392)">
<rect width="320" height="210" rx="9" fill="#151f1b" stroke="#c493ff" stroke-width="2"/>
<rect x="1" y="1" width="318" height="28" rx="8" fill="#0a1410"/>
<text x="12" y="19" font-family="Arial,sans-serif" font-size="11" letter-spacing="2" fill="#efe8d7">BOSS 04</text>
<text x="307" y="19" text-anchor="end" font-family="Arial,sans-serif" font-size="10" fill="#c493ff">COLLECTED</text>
<rect x="7" y="31" width="306" height="113" rx="3" fill="url(#portrait)"/>
<ellipse cx="160" cy="137" rx="53" ry="5" fill="#030a08" opacity=".7"/>
<use href="#guardian" transform="translate(105 30) scale(1.08)"/>
<text x="13" y="164" font-family="Georgia,serif" font-size="18" fill="#f3ead1">Verdan the Everliving</text>
<text x="13" y="181" font-family="Arial,sans-serif" font-size="11" fill="#b8b5a7">5 copies owned</text>
<path d="M0 187H320" stroke="#536357" opacity=".6"/>
<g transform="translate(12 191)"><rect width="21" height="21" rx="3" fill="#2a3a3c" stroke="#ddd8ce"/><text x="10.5" y="15" text-anchor="middle" font-family="Arial,sans-serif" font-size="12" fill="#ddd8ce">N</text></g><g transform="translate(39 191)"><rect width="21" height="21" rx="3" fill="#2a3a3c" stroke="#69b4ff"/><text x="10.5" y="15" text-anchor="middle" font-family="Arial,sans-serif" font-size="12" fill="#69b4ff">R</text></g><g transform="translate(66 191)"><rect width="21" height="21" rx="3" fill="#2a3a3c" stroke="#c493ff"/><text x="10.5" y="15" text-anchor="middle" font-family="Arial,sans-serif" font-size="12" fill="#c493ff">E</text></g><g transform="translate(93 191)"><rect width="21" height="21" rx="3" fill="#252f2c" stroke="#5c6a60"/><text x="10.5" y="15" text-anchor="middle" font-family="Arial,sans-serif" font-size="12" fill="#79877d">L</text></g>
</g>
<g transform="translate(440 392)">
<rect width="320" height="210" rx="9" fill="#151f1b" stroke="#69756b" stroke-width="1"/>
<rect x="1" y="1" width="318" height="28" rx="8" fill="#0a1410"/>
<text x="12" y="19" font-family="Arial,sans-serif" font-size="11" letter-spacing="2" fill="#efe8d7">BOSS 05</text>
<text x="307" y="19" text-anchor="end" font-family="Arial,sans-serif" font-size="10" fill="#a5a99b">UNCOLLECTED</text>
<rect x="7" y="31" width="306" height="113" rx="3" fill="url(#portrait)"/>
<ellipse cx="160" cy="137" rx="53" ry="5" fill="#030a08" opacity=".7"/>
<use href="#serpent" transform="translate(105 30) scale(1.08)"/>
<text x="13" y="164" font-family="Georgia,serif" font-size="20" fill="#f3ead1">Lord Serpentis</text>
<text x="13" y="181" font-family="Arial,sans-serif" font-size="11" fill="#b8b5a7">Card not collected</text>
<path d="M0 187H320" stroke="#536357" opacity=".6"/>
<g transform="translate(12 191)"><rect width="21" height="21" rx="3" fill="#252f2c" stroke="#5c6a60"/><text x="10.5" y="15" text-anchor="middle" font-family="Arial,sans-serif" font-size="12" fill="#79877d">N</text></g><g transform="translate(39 191)"><rect width="21" height="21" rx="3" fill="#252f2c" stroke="#5c6a60"/><text x="10.5" y="15" text-anchor="middle" font-family="Arial,sans-serif" font-size="12" fill="#79877d">R</text></g><g transform="translate(66 191)"><rect width="21" height="21" rx="3" fill="#252f2c" stroke="#5c6a60"/><text x="10.5" y="15" text-anchor="middle" font-family="Arial,sans-serif" font-size="12" fill="#79877d">E</text></g><g transform="translate(93 191)"><rect width="21" height="21" rx="3" fill="#252f2c" stroke="#5c6a60"/><text x="10.5" y="15" text-anchor="middle" font-family="Arial,sans-serif" font-size="12" fill="#79877d">L</text></g>
</g>
<g transform="translate(792 392)">
<rect width="320" height="210" rx="9" fill="#151f1b" stroke="#69756b" stroke-width="1"/>
<rect x="1" y="1" width="318" height="28" rx="8" fill="#0a1410"/>
<text x="12" y="19" font-family="Arial,sans-serif" font-size="11" letter-spacing="2" fill="#efe8d7">BOSS 06</text>
<text x="307" y="19" text-anchor="end" font-family="Arial,sans-serif" font-size="10" fill="#a5a99b">UNCOLLECTED</text>
<rect x="7" y="31" width="306" height="113" rx="3" fill="url(#portrait)"/>
<ellipse cx="160" cy="137" rx="53" ry="5" fill="#030a08" opacity=".7"/>
<use href="#mutant" transform="translate(105 30) scale(1.08)"/>
<text x="13" y="164" font-family="Georgia,serif" font-size="20" fill="#f3ead1">Mutanus the Devourer</text>
<text x="13" y="181" font-family="Arial,sans-serif" font-size="11" fill="#b8b5a7">Card not collected</text>
<path d="M0 187H320" stroke="#536357" opacity=".6"/>
<g transform="translate(12 191)"><rect width="21" height="21" rx="3" fill="#252f2c" stroke="#5c6a60"/><text x="10.5" y="15" text-anchor="middle" font-family="Arial,sans-serif" font-size="12" fill="#79877d">N</text></g><g transform="translate(39 191)"><rect width="21" height="21" rx="3" fill="#252f2c" stroke="#5c6a60"/><text x="10.5" y="15" text-anchor="middle" font-family="Arial,sans-serif" font-size="12" fill="#79877d">R</text></g><g transform="translate(66 191)"><rect width="21" height="21" rx="3" fill="#252f2c" stroke="#5c6a60"/><text x="10.5" y="15" text-anchor="middle" font-family="Arial,sans-serif" font-size="12" fill="#79877d">E</text></g><g transform="translate(93 191)"><rect width="21" height="21" rx="3" fill="#252f2c" stroke="#5c6a60"/><text x="10.5" y="15" text-anchor="middle" font-family="Arial,sans-serif" font-size="12" fill="#79877d">L</text></g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

+125
View File
@@ -0,0 +1,125 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="700" viewBox="0 0 1200 700">
<defs>
<linearGradient id="backdrop" x2="1" y2="1"><stop stop-color="#193628"/><stop offset="1" stop-color="#06100e"/></linearGradient>
<linearGradient id="panel" x2="1" y2="1"><stop stop-color="#27312a"/><stop offset="1" stop-color="#0c1714"/></linearGradient>
<radialGradient id="portrait"><stop stop-color="#435549"/><stop offset="1" stop-color="#111d1a"/></radialGradient>
<linearGradient id="scale" x2=".8" y2="1"><stop stop-color="#aac49b"/><stop offset=".45" stop-color="#4d8067"/><stop offset="1" stop-color="#1d4b42"/></linearGradient>
<linearGradient id="belly" x2="1" y2=".8"><stop stop-color="#eee5a5"/><stop offset="1" stop-color="#a7a474"/></linearGradient>
<linearGradient id="guardian-fill" x2=".8" y2="1"><stop stop-color="#aad36f"/><stop offset=".48" stop-color="#568d49"/><stop offset="1" stop-color="#274f37"/></linearGradient>
<filter id="shadow"><feDropShadow dx="0" dy="12" stdDeviation="17" flood-opacity=".7"/></filter>
<filter id="creature-shadow"><feDropShadow dx="0" dy="5" stdDeviation="4" flood-opacity=".7"/></filter>
<g id="serpent" filter="url(#creature-shadow)">
<path d="M24 92 C8 75 30 61 53 69 C84 79 89 55 69 45 C53 37 54 23 67 18" fill="none" stroke="#193f37" stroke-width="26" stroke-linecap="round"/>
<path d="M24 91 C12 77 36 65 55 73 C82 82 92 54 70 44 C56 36 57 23 68 18" fill="none" stroke="url(#scale)" stroke-width="19" stroke-linecap="round"/>
<path d="M27 84 C35 76 43 75 52 78 M67 73 C75 70 79 62 78 56 M67 41 C59 32 62 22 68 18" fill="none" stroke="url(#belly)" stroke-width="6" stroke-linecap="round" opacity=".85"/>
<path d="M62 25 L56 15 L64 18 L67 9 L74 17 L82 14 L79 25 Q78 35 70 36 Q61 35 62 25" fill="url(#scale)" stroke="#173d34" stroke-width="2"/>
<path d="M62 33 Q69 43 77 33 L73 48 L69 40 L64 48Z" fill="#e2cf9c"/>
<circle cx="65" cy="25" r="2.5" fill="#f8d378"/><circle cx="75" cy="25" r="2.5" fill="#f8d378"/>
</g>
<g id="guardian" filter="url(#creature-shadow)">
<path d="M40 92 L22 76 L17 47 L29 28 L43 22 L63 26 L77 43 L82 75 L65 91Z" fill="url(#guardian-fill)" stroke="#214c30" stroke-width="3"/>
<path d="M24 41 L11 20 L31 31 M72 40 L90 18 L75 50" fill="url(#guardian-fill)" stroke="#214c30" stroke-width="3"/>
<path d="M38 30 L40 15 L50 25 L60 14 L66 33 M27 58 L10 53 L25 72 M76 59 L91 54 L80 76" fill="#427d3d" stroke="#1b472b" stroke-width="3"/>
<path d="M40 43 Q50 51 61 43 L65 71 Q50 80 35 69Z" fill="#9cc372" opacity=".8"/>
<path d="M35 38 L45 42 L41 46 M65 38 L55 42 L59 46" fill="#eae99e"/>
<path d="M40 58 Q50 63 61 58" fill="none" stroke="#173e29" stroke-width="4"/>
</g>
<g id="mutant" filter="url(#creature-shadow)">
<path d="M30 90 L20 65 L30 37 L45 29 L58 31 L73 45 L80 69 L68 91Z" fill="url(#scale)" stroke="#214b3e" stroke-width="3"/>
<path d="M34 35 L21 19 L24 42 M62 36 L75 18 L75 46" fill="url(#scale)" stroke="#214b3e" stroke-width="3"/>
<path d="M21 61 L5 53 L18 80 M76 58 L92 48 L84 80" fill="none" stroke="#376b56" stroke-width="12" stroke-linecap="round"/>
<path d="M36 51 L46 54 M62 51 L55 54" stroke="#e7dc89" stroke-width="5" stroke-linecap="round"/>
<path d="M38 66 Q49 80 62 66 L58 75 L54 69 L50 79 L46 69 L42 75Z" fill="#eadfb3"/>
</g>
</defs>
<rect width="1200" height="700" fill="url(#backdrop)"/>
<path d="M0 680Q130 370 320 520T700 390T1200 540V700H0" fill="#275137" opacity=".32"/>
<rect width="1200" height="700" fill="#020705" opacity=".58"/>
<rect x="150" y="30" width="900" height="640" rx="15" fill="url(#panel)" stroke="#8d7d56" stroke-width="2" filter="url(#shadow)"/>
<text x="180" y="80" font-family="Arial,sans-serif" font-size="24" font-weight="bold" letter-spacing="4" fill="#f3ead1">PAUSED</text>
<circle cx="779" cy="70" r="22" fill="#253a31" stroke="#b7b381"/>
<text x="779" y="78" text-anchor="middle" font-family="Georgia,serif" font-size="23" fill="#d5b875">+</text>
<text x="814" y="67" font-family="Arial,sans-serif" font-size="17" font-weight="bold" fill="#f3ead1">Aria</text>
<text x="814" y="86" font-family="Arial,sans-serif" font-size="12" fill="#b8b5a7">Level 24 · Priest / Discipline</text>
<path d="M178 105H1022" stroke="#8d7d56" opacity=".6"/>
<text x="180" y="131" font-family="Arial,sans-serif" font-size="12" font-weight="bold" letter-spacing="1" fill="#d5b875">BOSS CARDS IN THIS DUNGEON</text>
<text x="1018" y="131" text-anchor="end" font-family="Arial,sans-serif" font-size="12" fill="#b8b5a7">2 / 6 COLLECTED</text>
<g transform="translate(180 145)">
<rect width="155" height="171" rx="7" fill="#17231e" stroke="#69b4ff"/>
<rect x="1" y="1" width="153" height="20" rx="6" fill="#0a1410"/>
<text x="8" y="14" font-family="Arial,sans-serif" font-size="8" letter-spacing="1" fill="#e9e2d2">BOSS 01</text>
<text x="147" y="14" text-anchor="end" font-family="Arial,sans-serif" font-size="8" fill="#69b4ff">OWNED</text>
<rect x="4" y="23" width="147" height="79" fill="url(#portrait)"/>
<ellipse cx="78" cy="100" rx="37" ry="4" fill="#030a08" opacity=".6"/>
<use href="#serpent" transform="translate(46 22) scale(.67)"/>
<text x="7" y="120" font-family="Georgia,serif" font-size="12" fill="#f3ead1">Lady Anacondra</text>
<text x="7" y="136" font-family="Arial,sans-serif" font-size="9" fill="#b8b5a7">3 copies owned</text>
<path d="M0 143H155" stroke="#536357" opacity=".6"/>
<g transform="translate(8 148)"><rect width="15" height="15" rx="3" fill="#2a3a3c" stroke="#ddd8ce"/><text x="7.5" y="11" text-anchor="middle" font-family="Arial,sans-serif" font-size="9" fill="#ddd8ce">N</text></g><g transform="translate(27 148)"><rect width="15" height="15" rx="3" fill="#2a3a3c" stroke="#69b4ff"/><text x="7.5" y="11" text-anchor="middle" font-family="Arial,sans-serif" font-size="9" fill="#69b4ff">R</text></g><g transform="translate(46 148)"><rect width="15" height="15" rx="3" fill="#252f2c" stroke="#5c6a60"/><text x="7.5" y="11" text-anchor="middle" font-family="Arial,sans-serif" font-size="9" fill="#79877d">E</text></g><g transform="translate(65 148)"><rect width="15" height="15" rx="3" fill="#252f2c" stroke="#5c6a60"/><text x="7.5" y="11" text-anchor="middle" font-family="Arial,sans-serif" font-size="9" fill="#79877d">L</text></g>
</g>
<g transform="translate(349 145)">
<rect width="155" height="171" rx="7" fill="#17231e" stroke="#6e796d"/>
<rect x="1" y="1" width="153" height="20" rx="6" fill="#0a1410"/>
<text x="8" y="14" font-family="Arial,sans-serif" font-size="8" letter-spacing="1" fill="#e9e2d2">BOSS 02</text>
<text x="147" y="14" text-anchor="end" font-family="Arial,sans-serif" font-size="8" fill="#a5a99b">MISSING</text>
<rect x="4" y="23" width="147" height="79" fill="url(#portrait)"/>
<ellipse cx="78" cy="100" rx="37" ry="4" fill="#030a08" opacity=".6"/>
<use href="#serpent" transform="translate(46 22) scale(.67)"/>
<text x="7" y="120" font-family="Georgia,serif" font-size="12" fill="#f3ead1">Lord Cobrahn</text>
<text x="7" y="136" font-family="Arial,sans-serif" font-size="9" fill="#b8b5a7">Not collected</text>
<path d="M0 143H155" stroke="#536357" opacity=".6"/>
<g transform="translate(8 148)"><rect width="15" height="15" rx="3" fill="#252f2c" stroke="#5c6a60"/><text x="7.5" y="11" text-anchor="middle" font-family="Arial,sans-serif" font-size="9" fill="#79877d">N</text></g><g transform="translate(27 148)"><rect width="15" height="15" rx="3" fill="#252f2c" stroke="#5c6a60"/><text x="7.5" y="11" text-anchor="middle" font-family="Arial,sans-serif" font-size="9" fill="#79877d">R</text></g><g transform="translate(46 148)"><rect width="15" height="15" rx="3" fill="#252f2c" stroke="#5c6a60"/><text x="7.5" y="11" text-anchor="middle" font-family="Arial,sans-serif" font-size="9" fill="#79877d">E</text></g><g transform="translate(65 148)"><rect width="15" height="15" rx="3" fill="#252f2c" stroke="#5c6a60"/><text x="7.5" y="11" text-anchor="middle" font-family="Arial,sans-serif" font-size="9" fill="#79877d">L</text></g>
</g>
<g transform="translate(518 145)">
<rect width="155" height="171" rx="7" fill="#17231e" stroke="#6e796d"/>
<rect x="1" y="1" width="153" height="20" rx="6" fill="#0a1410"/>
<text x="8" y="14" font-family="Arial,sans-serif" font-size="8" letter-spacing="1" fill="#e9e2d2">BOSS 03</text>
<text x="147" y="14" text-anchor="end" font-family="Arial,sans-serif" font-size="8" fill="#a5a99b">MISSING</text>
<rect x="4" y="23" width="147" height="79" fill="url(#portrait)"/>
<ellipse cx="78" cy="100" rx="37" ry="4" fill="#030a08" opacity=".6"/>
<use href="#serpent" transform="translate(46 22) scale(.67)"/>
<text x="7" y="120" font-family="Georgia,serif" font-size="12" fill="#f3ead1">Lord Pythas</text>
<text x="7" y="136" font-family="Arial,sans-serif" font-size="9" fill="#b8b5a7">Not collected</text>
<path d="M0 143H155" stroke="#536357" opacity=".6"/>
<g transform="translate(8 148)"><rect width="15" height="15" rx="3" fill="#252f2c" stroke="#5c6a60"/><text x="7.5" y="11" text-anchor="middle" font-family="Arial,sans-serif" font-size="9" fill="#79877d">N</text></g><g transform="translate(27 148)"><rect width="15" height="15" rx="3" fill="#252f2c" stroke="#5c6a60"/><text x="7.5" y="11" text-anchor="middle" font-family="Arial,sans-serif" font-size="9" fill="#79877d">R</text></g><g transform="translate(46 148)"><rect width="15" height="15" rx="3" fill="#252f2c" stroke="#5c6a60"/><text x="7.5" y="11" text-anchor="middle" font-family="Arial,sans-serif" font-size="9" fill="#79877d">E</text></g><g transform="translate(65 148)"><rect width="15" height="15" rx="3" fill="#252f2c" stroke="#5c6a60"/><text x="7.5" y="11" text-anchor="middle" font-family="Arial,sans-serif" font-size="9" fill="#79877d">L</text></g>
</g>
<g transform="translate(687 145)">
<rect width="155" height="171" rx="7" fill="#17231e" stroke="#c493ff"/>
<rect x="1" y="1" width="153" height="20" rx="6" fill="#0a1410"/>
<text x="8" y="14" font-family="Arial,sans-serif" font-size="8" letter-spacing="1" fill="#e9e2d2">BOSS 04</text>
<text x="147" y="14" text-anchor="end" font-family="Arial,sans-serif" font-size="8" fill="#c493ff">OWNED</text>
<rect x="4" y="23" width="147" height="79" fill="url(#portrait)"/>
<ellipse cx="78" cy="100" rx="37" ry="4" fill="#030a08" opacity=".6"/>
<use href="#guardian" transform="translate(46 22) scale(.67)"/>
<text x="7" y="120" font-family="Georgia,serif" font-size="10" fill="#f3ead1">Verdan the Everliving</text>
<text x="7" y="136" font-family="Arial,sans-serif" font-size="9" fill="#b8b5a7">5 copies owned</text>
<path d="M0 143H155" stroke="#536357" opacity=".6"/>
<g transform="translate(8 148)"><rect width="15" height="15" rx="3" fill="#2a3a3c" stroke="#ddd8ce"/><text x="7.5" y="11" text-anchor="middle" font-family="Arial,sans-serif" font-size="9" fill="#ddd8ce">N</text></g><g transform="translate(27 148)"><rect width="15" height="15" rx="3" fill="#2a3a3c" stroke="#69b4ff"/><text x="7.5" y="11" text-anchor="middle" font-family="Arial,sans-serif" font-size="9" fill="#69b4ff">R</text></g><g transform="translate(46 148)"><rect width="15" height="15" rx="3" fill="#2a3a3c" stroke="#c493ff"/><text x="7.5" y="11" text-anchor="middle" font-family="Arial,sans-serif" font-size="9" fill="#c493ff">E</text></g><g transform="translate(65 148)"><rect width="15" height="15" rx="3" fill="#252f2c" stroke="#5c6a60"/><text x="7.5" y="11" text-anchor="middle" font-family="Arial,sans-serif" font-size="9" fill="#79877d">L</text></g>
</g>
<g transform="translate(856 145)">
<rect width="155" height="171" rx="7" fill="#17231e" stroke="#6e796d"/>
<rect x="1" y="1" width="153" height="20" rx="6" fill="#0a1410"/>
<text x="8" y="14" font-family="Arial,sans-serif" font-size="8" letter-spacing="1" fill="#e9e2d2">BOSS 05</text>
<text x="147" y="14" text-anchor="end" font-family="Arial,sans-serif" font-size="8" fill="#a5a99b">MISSING</text>
<rect x="4" y="23" width="147" height="79" fill="url(#portrait)"/>
<ellipse cx="78" cy="100" rx="37" ry="4" fill="#030a08" opacity=".6"/>
<use href="#serpent" transform="translate(46 22) scale(.67)"/>
<text x="7" y="120" font-family="Georgia,serif" font-size="12" fill="#f3ead1">Lord Serpentis</text>
<text x="7" y="136" font-family="Arial,sans-serif" font-size="9" fill="#b8b5a7">Not collected</text>
<path d="M0 143H155" stroke="#536357" opacity=".6"/>
<g transform="translate(8 148)"><rect width="15" height="15" rx="3" fill="#252f2c" stroke="#5c6a60"/><text x="7.5" y="11" text-anchor="middle" font-family="Arial,sans-serif" font-size="9" fill="#79877d">N</text></g><g transform="translate(27 148)"><rect width="15" height="15" rx="3" fill="#252f2c" stroke="#5c6a60"/><text x="7.5" y="11" text-anchor="middle" font-family="Arial,sans-serif" font-size="9" fill="#79877d">R</text></g><g transform="translate(46 148)"><rect width="15" height="15" rx="3" fill="#252f2c" stroke="#5c6a60"/><text x="7.5" y="11" text-anchor="middle" font-family="Arial,sans-serif" font-size="9" fill="#79877d">E</text></g><g transform="translate(65 148)"><rect width="15" height="15" rx="3" fill="#252f2c" stroke="#5c6a60"/><text x="7.5" y="11" text-anchor="middle" font-family="Arial,sans-serif" font-size="9" fill="#79877d">L</text></g>
</g>
<text x="1018" y="335" text-anchor="end" font-family="Arial,sans-serif" font-size="11" fill="#9fa994">SCROLL →</text>
<path d="M178 347H1022" stroke="#8d7d56" opacity=".6"/>
<rect x="440" y="364" width="320" height="45" rx="8" fill="#587348" stroke="#9bb477"/>
<text x="600" y="393" text-anchor="middle" font-family="Arial,sans-serif" font-size="16" font-weight="bold" fill="#fbfee9">Resume game</text>
<g font-family="Arial,sans-serif">
<rect x="180" y="427" width="384" height="101" rx="8" fill="#1a2621" stroke="#526153"/>
<rect x="636" y="427" width="384" height="101" rx="8" fill="#1a2621" stroke="#526153"/>
<rect x="180" y="544" width="384" height="101" rx="8" fill="#1a2621" stroke="#526153"/>
<rect x="636" y="544" width="384" height="101" rx="8" fill="#1a2621" stroke="#526153"/>
<g fill="#b8b5a7" font-size="12" font-weight="bold" letter-spacing="2"><text x="195" y="451">ADVENTURE</text><text x="651" y="451">CHARACTER</text><text x="195" y="568">SETTINGS</text><text x="651" y="568">SESSION</text></g>
<g fill="#314136" stroke="#64795d"><rect x="195" y="466" width="169" height="43" rx="6"/><rect x="379" y="466" width="169" height="43" rx="6"/><rect x="651" y="466" width="169" height="43" rx="6"/><rect x="835" y="466" width="169" height="43" rx="6"/><rect x="195" y="583" width="169" height="43" rx="6"/><rect x="379" y="583" width="169" height="43" rx="6"/><rect x="651" y="583" width="169" height="43" rx="6"/><rect x="835" y="583" width="169" height="43" rx="6"/></g>
<g fill="#eee9d9" font-size="12" text-anchor="middle"><text x="279" y="493">Party management</text><text x="463" y="493">Dungeon map</text><text x="735" y="493">Inventory</text><text x="919" y="493">Spellbook</text><text x="279" y="610">Options</text><text x="463" y="610">Keybinds</text><text x="735" y="610">Return to entrance</text><text x="919" y="610">Main menu</text></g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

@@ -0,0 +1,142 @@
import { writeFile } from "node:fs/promises";
import { fileURLToPath } from "node:url";
import { dirname, join } from "node:path";
import sharp from "sharp";
const outputDir = dirname(fileURLToPath(import.meta.url));
const bosses = [
{ name: "Lady Anacondra", copies: "3 copies owned", owned: true, accent: "#69b4ff", shape: "serpent" },
{ name: "Lord Cobrahn", copies: "Card not collected", owned: false, accent: "#a5a99b", shape: "serpent" },
{ name: "Lord Pythas", copies: "Card not collected", owned: false, accent: "#a5a99b", shape: "serpent" },
{ name: "Verdan the Everliving", copies: "5 copies owned", owned: true, accent: "#c493ff", shape: "guardian" },
{ name: "Lord Serpentis", copies: "Card not collected", owned: false, accent: "#a5a99b", shape: "serpent" },
{ name: "Mutanus the Devourer", copies: "Card not collected", owned: false, accent: "#a5a99b", shape: "mutant" },
];
const defs = `<defs>
<linearGradient id="backdrop" x2="1" y2="1"><stop stop-color="#193628"/><stop offset="1" stop-color="#06100e"/></linearGradient>
<linearGradient id="panel" x2="1" y2="1"><stop stop-color="#27312a"/><stop offset="1" stop-color="#0c1714"/></linearGradient>
<radialGradient id="portrait"><stop stop-color="#435549"/><stop offset="1" stop-color="#111d1a"/></radialGradient>
<linearGradient id="scale" x2=".8" y2="1"><stop stop-color="#aac49b"/><stop offset=".45" stop-color="#4d8067"/><stop offset="1" stop-color="#1d4b42"/></linearGradient>
<linearGradient id="belly" x2="1" y2=".8"><stop stop-color="#eee5a5"/><stop offset="1" stop-color="#a7a474"/></linearGradient>
<linearGradient id="guardian-fill" x2=".8" y2="1"><stop stop-color="#aad36f"/><stop offset=".48" stop-color="#568d49"/><stop offset="1" stop-color="#274f37"/></linearGradient>
<filter id="shadow"><feDropShadow dx="0" dy="12" stdDeviation="17" flood-opacity=".7"/></filter>
<filter id="creature-shadow"><feDropShadow dx="0" dy="5" stdDeviation="4" flood-opacity=".7"/></filter>
<g id="serpent" filter="url(#creature-shadow)">
<path d="M24 92 C8 75 30 61 53 69 C84 79 89 55 69 45 C53 37 54 23 67 18" fill="none" stroke="#193f37" stroke-width="26" stroke-linecap="round"/>
<path d="M24 91 C12 77 36 65 55 73 C82 82 92 54 70 44 C56 36 57 23 68 18" fill="none" stroke="url(#scale)" stroke-width="19" stroke-linecap="round"/>
<path d="M27 84 C35 76 43 75 52 78 M67 73 C75 70 79 62 78 56 M67 41 C59 32 62 22 68 18" fill="none" stroke="url(#belly)" stroke-width="6" stroke-linecap="round" opacity=".85"/>
<path d="M62 25 L56 15 L64 18 L67 9 L74 17 L82 14 L79 25 Q78 35 70 36 Q61 35 62 25" fill="url(#scale)" stroke="#173d34" stroke-width="2"/>
<path d="M62 33 Q69 43 77 33 L73 48 L69 40 L64 48Z" fill="#e2cf9c"/>
<circle cx="65" cy="25" r="2.5" fill="#f8d378"/><circle cx="75" cy="25" r="2.5" fill="#f8d378"/>
</g>
<g id="guardian" filter="url(#creature-shadow)">
<path d="M40 92 L22 76 L17 47 L29 28 L43 22 L63 26 L77 43 L82 75 L65 91Z" fill="url(#guardian-fill)" stroke="#214c30" stroke-width="3"/>
<path d="M24 41 L11 20 L31 31 M72 40 L90 18 L75 50" fill="url(#guardian-fill)" stroke="#214c30" stroke-width="3"/>
<path d="M38 30 L40 15 L50 25 L60 14 L66 33 M27 58 L10 53 L25 72 M76 59 L91 54 L80 76" fill="#427d3d" stroke="#1b472b" stroke-width="3"/>
<path d="M40 43 Q50 51 61 43 L65 71 Q50 80 35 69Z" fill="#9cc372" opacity=".8"/>
<path d="M35 38 L45 42 L41 46 M65 38 L55 42 L59 46" fill="#eae99e"/>
<path d="M40 58 Q50 63 61 58" fill="none" stroke="#173e29" stroke-width="4"/>
</g>
<g id="mutant" filter="url(#creature-shadow)">
<path d="M30 90 L20 65 L30 37 L45 29 L58 31 L73 45 L80 69 L68 91Z" fill="url(#scale)" stroke="#214b3e" stroke-width="3"/>
<path d="M34 35 L21 19 L24 42 M62 36 L75 18 L75 46" fill="url(#scale)" stroke="#214b3e" stroke-width="3"/>
<path d="M21 61 L5 53 L18 80 M76 58 L92 48 L84 80" fill="none" stroke="#376b56" stroke-width="12" stroke-linecap="round"/>
<path d="M36 51 L46 54 M62 51 L55 54" stroke="#e7dc89" stroke-width="5" stroke-linecap="round"/>
<path d="M38 66 Q49 80 62 66 L58 75 L54 69 L50 79 L46 69 L42 75Z" fill="#eadfb3"/>
</g>
</defs>`;
function rarityMarks(boss, x, y, compact = false) {
const size = compact ? 15 : 21;
const gap = compact ? 4 : 6;
return ["N", "R", "E", "L"].map((label, index) => {
const owned = boss.owned && (boss.name.startsWith("Verdan") ? index < 3 : index < 2);
const color = ["#ddd8ce", "#69b4ff", "#c493ff", "#e5a757"][index];
return `<g transform="translate(${x + index * (size + gap)} ${y})"><rect width="${size}" height="${size}" rx="3" fill="${owned ? "#2a3a3c" : "#252f2c"}" stroke="${owned ? color : "#5c6a60"}"/><text x="${size / 2}" y="${compact ? 11 : 15}" text-anchor="middle" font-family="Arial,sans-serif" font-size="${compact ? 9 : 12}" fill="${owned ? color : "#79877d"}">${label}</text></g>`;
}).join("");
}
function largeCard(boss, index) {
const x = 88 + index % 3 * 352;
const y = 166 + Math.floor(index / 3) * 226;
const owned = boss.owned;
return `<g transform="translate(${x} ${y})">
<rect width="320" height="210" rx="9" fill="#151f1b" stroke="${owned ? boss.accent : "#69756b"}" stroke-width="${owned ? 2 : 1}"/>
<rect x="1" y="1" width="318" height="28" rx="8" fill="#0a1410"/>
<text x="12" y="19" font-family="Arial,sans-serif" font-size="11" letter-spacing="2" fill="#efe8d7">BOSS ${String(index + 1).padStart(2, "0")}</text>
<text x="307" y="19" text-anchor="end" font-family="Arial,sans-serif" font-size="10" fill="${boss.accent}">${owned ? "COLLECTED" : "UNCOLLECTED"}</text>
<rect x="7" y="31" width="306" height="113" rx="3" fill="url(#portrait)"/>
<ellipse cx="160" cy="137" rx="53" ry="5" fill="#030a08" opacity=".7"/>
<use href="#${boss.shape}" transform="translate(105 30) scale(1.08)"/>
<text x="13" y="164" font-family="Georgia,serif" font-size="${boss.name.length > 20 ? 18 : 20}" fill="#f3ead1">${boss.name}</text>
<text x="13" y="181" font-family="Arial,sans-serif" font-size="11" fill="#b8b5a7">${boss.copies}</text>
<path d="M0 187H320" stroke="#536357" opacity=".6"/>
${rarityMarks(boss, 12, 191)}
</g>`;
}
const countdown = `<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="700" viewBox="0 0 1200 700">
${defs}
<rect width="1200" height="700" fill="url(#backdrop)"/>
<path d="M0 660Q130 310 300 490T760 365T1200 470V700H0" fill="#2c5037" opacity=".24"/>
<rect x="58" y="34" width="1084" height="632" rx="16" fill="url(#panel)" stroke="#8d7d56" stroke-width="2" filter="url(#shadow)"/>
<text x="88" y="102" font-family="Georgia,serif" font-size="38" fill="#f3ead1">Wailing Caverns</text>
<text x="88" y="132" font-family="Arial,sans-serif" font-size="14" fill="#b8b5a7">6 bosses ahead · 2 collected</text>
<path d="M978 56V140" stroke="#88764f"/>
<text x="1050" y="78" text-anchor="middle" font-family="Arial,sans-serif" font-size="11" letter-spacing="2" fill="#b8b5a7">ENTERING IN</text>
<text x="1050" y="134" text-anchor="middle" font-family="Georgia,serif" font-size="60" fill="#d5b875">05</text>
${bosses.map(largeCard).join("\n ")}
</svg>\n`;
function compactCard(boss, index) {
const x = 180 + index * 169;
return `<g transform="translate(${x} 145)">
<rect width="155" height="171" rx="7" fill="#17231e" stroke="${boss.owned ? boss.accent : "#6e796d"}"/>
<rect x="1" y="1" width="153" height="20" rx="6" fill="#0a1410"/>
<text x="8" y="14" font-family="Arial,sans-serif" font-size="8" letter-spacing="1" fill="#e9e2d2">BOSS ${String(index + 1).padStart(2, "0")}</text>
<text x="147" y="14" text-anchor="end" font-family="Arial,sans-serif" font-size="8" fill="${boss.accent}">${boss.owned ? "OWNED" : "MISSING"}</text>
<rect x="4" y="23" width="147" height="79" fill="url(#portrait)"/>
<ellipse cx="78" cy="100" rx="37" ry="4" fill="#030a08" opacity=".6"/>
<use href="#${boss.shape}" transform="translate(46 22) scale(.67)"/>
<text x="7" y="120" font-family="Georgia,serif" font-size="${boss.name.length > 19 ? 10 : 12}" fill="#f3ead1">${boss.name}</text>
<text x="7" y="136" font-family="Arial,sans-serif" font-size="9" fill="#b8b5a7">${boss.owned ? boss.copies : "Not collected"}</text>
<path d="M0 143H155" stroke="#536357" opacity=".6"/>
${rarityMarks(boss, 8, 148, true)}
</g>`;
}
const pause = `<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="700" viewBox="0 0 1200 700">
${defs}
<rect width="1200" height="700" fill="url(#backdrop)"/>
<path d="M0 680Q130 370 320 520T700 390T1200 540V700H0" fill="#275137" opacity=".32"/>
<rect width="1200" height="700" fill="#020705" opacity=".58"/>
<rect x="150" y="30" width="900" height="640" rx="15" fill="url(#panel)" stroke="#8d7d56" stroke-width="2" filter="url(#shadow)"/>
<text x="180" y="80" font-family="Arial,sans-serif" font-size="24" font-weight="bold" letter-spacing="4" fill="#f3ead1">PAUSED</text>
<circle cx="779" cy="70" r="22" fill="#253a31" stroke="#b7b381"/>
<text x="779" y="78" text-anchor="middle" font-family="Georgia,serif" font-size="23" fill="#d5b875">+</text>
<text x="814" y="67" font-family="Arial,sans-serif" font-size="17" font-weight="bold" fill="#f3ead1">Aria</text>
<text x="814" y="86" font-family="Arial,sans-serif" font-size="12" fill="#b8b5a7">Level 24 · Priest / Discipline</text>
<path d="M178 105H1022" stroke="#8d7d56" opacity=".6"/>
<text x="180" y="131" font-family="Arial,sans-serif" font-size="12" font-weight="bold" letter-spacing="1" fill="#d5b875">BOSS CARDS IN THIS DUNGEON</text>
<text x="1018" y="131" text-anchor="end" font-family="Arial,sans-serif" font-size="12" fill="#b8b5a7">2 / 6 COLLECTED</text>
${bosses.slice(0, 5).map(compactCard).join("\n ")}
<text x="1018" y="335" text-anchor="end" font-family="Arial,sans-serif" font-size="11" fill="#9fa994">SCROLL →</text>
<path d="M178 347H1022" stroke="#8d7d56" opacity=".6"/>
<rect x="440" y="364" width="320" height="45" rx="8" fill="#587348" stroke="#9bb477"/>
<text x="600" y="393" text-anchor="middle" font-family="Arial,sans-serif" font-size="16" font-weight="bold" fill="#fbfee9">Resume game</text>
<g font-family="Arial,sans-serif">
<rect x="180" y="427" width="384" height="101" rx="8" fill="#1a2621" stroke="#526153"/>
<rect x="636" y="427" width="384" height="101" rx="8" fill="#1a2621" stroke="#526153"/>
<rect x="180" y="544" width="384" height="101" rx="8" fill="#1a2621" stroke="#526153"/>
<rect x="636" y="544" width="384" height="101" rx="8" fill="#1a2621" stroke="#526153"/>
<g fill="#b8b5a7" font-size="12" font-weight="bold" letter-spacing="2"><text x="195" y="451">ADVENTURE</text><text x="651" y="451">CHARACTER</text><text x="195" y="568">SETTINGS</text><text x="651" y="568">SESSION</text></g>
<g fill="#314136" stroke="#64795d"><rect x="195" y="466" width="169" height="43" rx="6"/><rect x="379" y="466" width="169" height="43" rx="6"/><rect x="651" y="466" width="169" height="43" rx="6"/><rect x="835" y="466" width="169" height="43" rx="6"/><rect x="195" y="583" width="169" height="43" rx="6"/><rect x="379" y="583" width="169" height="43" rx="6"/><rect x="651" y="583" width="169" height="43" rx="6"/><rect x="835" y="583" width="169" height="43" rx="6"/></g>
<g fill="#eee9d9" font-size="12" text-anchor="middle"><text x="279" y="493">Party management</text><text x="463" y="493">Dungeon map</text><text x="735" y="493">Inventory</text><text x="919" y="493">Spellbook</text><text x="279" y="610">Options</text><text x="463" y="610">Keybinds</text><text x="735" y="610">Return to entrance</text><text x="919" y="610">Main menu</text></g>
</g>
</svg>\n`;
for (const [name, svg] of [["dungeon-boss-countdown", countdown], ["pause-boss-card-strip", pause]]) {
await writeFile(join(outputDir, `${name}.svg`), svg);
await sharp(Buffer.from(svg)).png().toFile(join(outputDir, `${name}.png`));
}
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "healer-man",
"version": "0.1.58",
"version": "0.1.59",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "healer-man",
"version": "0.1.58",
"version": "0.1.59",
"dependencies": {
"@capacitor/android": "8.4.1",
"@capacitor/core": "8.4.1",
+6 -1
View File
@@ -1,7 +1,7 @@
{
"name": "healer-man",
"private": true,
"version": "0.1.58",
"version": "0.1.59",
"type": "module",
"scripts": {
"dev": "vite --host 0.0.0.0",
@@ -15,6 +15,11 @@
"android:prepare": "node scripts/content/prepare-android-bootstrap.mjs",
"content:test": "node --test scripts/content/*.test.mjs",
"effects:generate": "node scripts/combat-effects/generate-manifest.mjs --package-audio && node scripts/combat-effects/package-wow-original.mjs",
"effects:rom": "node scripts/combat-effects/generate-manifest.mjs --runewaker-only --package-audio",
"effects:rom:particles": "node scripts/combat-effects/package-rom-particles.mjs",
"effects:rom:audit": "node scripts/combat-effects/audit-rom-media.mjs --write",
"effects:rom:plan": "node scripts/combat-effects/plan-rom-media.mjs --write",
"effects:rom:batch": "npm run effects:rom && npm run effects:rom:particles && npm run effects:rom && npm run effects:rom:audit && npm run effects:rom:plan",
"effects:audit": "node scripts/combat-effects/package-wow-original.mjs --audit",
"effects:wow": "node scripts/combat-effects/package-wow-original.mjs",
"effects:priest": "npm run effects:wow",
Loaded 100 of 879 files, more files were not shown because too many files have changed in this diff. Show more