# GriffonStudios WC3 Reforged Plugin — Changelog
Fixed and updated by DennisH
Special Thanks to GhostHeroine for testing and finding bugs
---
## Modified Files
| File | Lines before → after | Description |
|------|---------------------|-------------|
|
Parser.ms | 1497 → 2678 | Major rewrite: animation export, InverseRemap, CLID, BPOS, GEOA, RIBB, TEXS |
|
Write.ms | 1141 → 1806 | Animation write functions, variant dedup, KMTA/KMTE, CAMS, CORN, RIBB, CLID |
|
Build.ms | 1429 → 2256 | BPOS matrix, KGTR/KGRT/KGSC rewrites, CLID, import fixes, progress calls |
|
Exporter.ms | 111 → 160 | Chunk order, installation system, progress bar integration |
|
Import.ms | ~105 → ~115 | Auto-key bleed, ATCH/EVTS parenting, texture paths, progress bar integration |
|
Progress.ms | — (new) | Progress bar utility with countdown timer |
|
Plugins_Material.ms | 209 → 218 | Original texture path storage |
|
Helpers.ms | +20 lines | FrameToOrigMS function |
|
Read.ms | ~+50 lines | UserProperty storage during import |
---
## Feature: Installation System (Exporter.ms)
- New menu-based installation system via 3ds Max Macros
- Automatic registration in the 3ds Max menu
---
## Feature: Inverse Remap System (Parser.ms, Helpers.ms, Write.ms)
Complete system for exact reverse conversion of 3ds Max frame numbers back to original MDX milliseconds.
- FrameToOrigMS (Helpers.ms): Converts frame → original MS via RemapTable
- InverseRemapKeys (Parser.ms): Remaps all animation tracks after export collection
- Variant sequence detection: Identical MS ranges are deduplicated
- Set-based dedup: Catches non-adjacent duplicates after remap
- origStartMS/origEndMS storage in NoteTrack notes during import
---
## Feature: Progress Bar with Countdown Timer (Progress.ms, Import.ms, Exporter.ms, Build.ms)
Visual progress dialog showing real-time status during import and export operations.
- New file
Progress.ms: Standalone utility struct WC3Ref_ProgressStruct with Start, Update, End methods
- Modeless dialog: 380×80px toolwindow positioned at mouse cursor, shows step name + progress bar + percentage
- Countdown timer: Calculates average time per step and estimates remaining time (e.g.
~8s left, ~1m 23s left)
- Completion summary: Shows total elapsed time on finish (e.g.
Finished in 12s)
- Export tracking: 35 steps — 13 parse steps + 1 remap step + 21 write steps
- Import tracking: Dynamic step count —
mdx.TAGS.count + 20 (variable chunk count + 20 build steps)
- UI refresh:
windows.processPostedMessages() after each step to force repaint in single-threaded MaxScript
- No startup overhead: Loaded via
fileIn at runtime, not registered in PackageContents.xml
---
## Bugfixes — Animation Export
### 1. Animation Key Sorting (Parser.ms, Write.ms)
Problem: After FrameToOrigMS, keys were not in chronological order because sequences are not stored chronologically (e.g. "Stand First" at 118233ms is seq#2, "Stand Ready 1" at 3367ms is seq#4).
Fix: 9 insertion sort blocks after every FrameToOrigMS conversion:
remapAnimBlock (.Key) — BONE/CLID/PRE2/RIBB/LITE KGTR/KGRT/KGSC
remapAnimBlockLower (.key) — CAMS KCTR/KTTR/KCRL, TXAN KTAT/KTAR/KTAS
- GEOA KGAO/KGAC (.Time)
- KMTA/KMTE (.ms) in WriteLAYS
- KATV (.key) in WriteATCH
- CORN KPPV/KPPA (.key) in WriteCORN
### 2. Sequence Rarity (Write.ms → WriteSEQS)
Problem: Rarity value was not being exported.
Fix: Added
writeFloat mdx.stream s.rarity.
### 3. Frame-to-MS Rounding Error (Helpers.ms)
Problem: Integer division
(frame - 10) * 1000 / 30 lost precision.
Fix: (((frame - 10) * 1000 + 15) / 30) for correct rounding.
### 4. Quaternion Sign Flips (Parser.ms → GetKGRT)
Problem: Consecutive quaternion keys could have opposite signs, causing 360° rotations.
Fix: Dot product check and sign flip for shortest path interpolation.
### 5. Spurious Translation Tracks (Parser.ms → GetKGTR)
Problem: Bones without actual translation exported keys with near-zero values.
Fix: hasNonZero check: If all keys are [0,0,0], the track is skipped.
### 6. Constant-Value Track Detection (Parser.ms → GetKGTR)
Problem: PRE2/CORN objects received spurious position tracks from auto-keying.
Fix: Detection: If all keys are within 1e-3 tolerance of each other → skip track.
### 7. Frame-0 Skip for Non-GLBS (Parser.ms → GetKGTR/GetKGRT/GetKGSC)
Problem: Rest-pose frame 0 was written into normal animation tracks.
Fix: if (not isGlbs and t < 10) then continue
### 8. GLBS Detection via ORT (Parser.ms → GetKGTR/GetKGRT/GetKGSC)
Problem: Global sequences were not detected.
Fix: if getAfterORT cntrl == #cycle then isGlbs = true
### 9. Rest-Pose Rotation Bug (Parser.ms → GetKGRT)
Problem: inverse obj.rotation was evaluated at the wrong time (dependent on time slider position).
Fix: Explicit
at time 0f for rest-pose evaluation.
### 10. Variant Sequence Duplication (Parser.ms → InverseRemapKeys)
Problem: Variant sequences (same MS range) produced duplicate keys.
Fix: SkipRange system skips variant frames, set-based dedup after remap.
### 11. KMTA/KMTE Duplication (Write.ms → WriteLAYS)
Problem: Material alpha and emissive tracks were quadrupled by variant sequences.
Fix: Inline MS conversion with FrameToOrigMS + SeenMS dedup directly during writing.
---
## Bugfixes — Chunk Format & Order
### 12. Chunk Write Order (Exporter.ms)
Problem: CAMS was written before RIBB. WC3 Previewer read 124KB of CAMS data where it expected 2.5KB RIBB → "Section RibbonEmitters overran remaining buffer".
Fix: Swapped
WriteRIBB before
WriteCAMS.
### 13. ShaderTypeId for Ribbon (Write.ms → WriteLAYS)
Problem: Ribbon materials were written as HD_DefaultUnit (ShaderTypeId=1) instead of SD/Ribbon (ShaderTypeId=0).
Fix: if mdx.mtls[mtlsIndex].shader == #Ribbon then shaderTypeId = 0
---
## Bugfixes — Camera Export (Write.ms, Parser.ms)
### 14. CAMS Chunk Size (Write.ms → WriteCAMS)
Problem: CAMS chunk size calculated incorrectly → corruption.
Fix: Corrected size calculation (base 120 + track sizes).
### 15. KTTR Absolute Instead of Relative Position (Write.ms → WriteCAMS)
Problem: Camera target position written as absolute instead of relative to camera pivot.
Fix: Implemented relative calculation.
### 16. Camera Bind Pose in BPOS (Write.ms → WriteBPOS)
Problem: Camera was missing from BPOS chunk → "Index 181 out of bounds" in Retera.
Fix: Camera matrix included in BPOS.
---
## Bugfixes — GEOA (Geoset Animations)
### 17. Phantom Mid-Sequence Keys (Parser.ms → GetGEOA)
Problem: On_Off controller picked up ghost keys from other objects (animate on bleed), inflating 84→160+ keys.
Fix: Post-filter: Keep only boundary keys, transition keys, and pre-transition keys.
### 18. Pre-Transition Key Loss (Parser.ms → GetGEOA)
Problem: Key at 19567:1 before transition to 19600:0 was incorrectly removed (84→83 keys).
Fix: Bidirectional filter: Keep key if value differs from previous OR from next.
---
## Bugfixes — Particle Emitters (PRE2/CORN)
### 19. PRE2 KGTR Copy-Paste Bug (Build.ms)
Problem: PRE2 position export used
obj.objRef.pos instead of correct parent-space calculation → position shift.
Fix: Correct position calculation in parent space.
### 20. PRE2 Spurious Translation Track (Parser.ms)
Problem: PRE2 exported position track despite no actual translation present.
Fix: Constant-value detection (see fix #6).
### 21. CORN Missing KPPA Alpha Track (Write.ms → WriteCORN)
Problem: Popcorn alpha animation was lost during export.
Fix: Implemented KPPA track collection and writing.
### 22. CORN KPPV Boundary Keys (Write.ms → WriteCORN)
Problem: Missing boundary keys in visibility track (430000, 510000 were absent).
Fix: NoteTrack-based boundary injection.
### 23. CORN/PRE2 Texture Path Preservation
Problem: Texture paths like "Textures/Yellow_Star_Dim.tif" were converted to local paths.
Fix: ORIG_TEX_PATH UserProperty stored during import, reused during export.
---
## Bugfixes — Ribbon Emitters (RIBB)
### 24. KGRT Rotation Track Loss (Parser.ms → GetRIBB)
Problem: Ribbon rotation (82 keys) was completely lost during export.
Fix: KGRT track collection from obj.KGRT carried into ribbon struct.
### 25. KRVS Visibility Inflation (Parser.ms → GetRIBB)
Problem: 90→163 keys due to boundary injection into ALL sequences instead of only relevant ones.
Fix: Boundary keys only injected for sequences that contain at least one controller key.
---
## Bugfixes — BPOS (Bind Pose)
### 26. GetBPOSMatrix Value-Type Bug (Build.ms)
Problem: All BPOS matrices exported as identity due to MaxScript value-type error.
Fix: Correct matrix extraction from node transform.
### 27. BPOS Order (Parser.ms, Import.ms)
Problem: 137/182 bones in wrong order after re-export.
Fix: ORIG_OBJECT_ID stored during import, stable sort by origId during export.
---
## Bugfixes — CLID (Collision Objects)
### 28. CLID Vertices in Wrong Coordinate Space (Build.ms → WriteCLID)
Problem: Collision vertices exported in world space instead of BPOS space.
Fix: Transformation into BPOS coordinate system.
### 29. CLID Rotation as Delta Instead of Absolute (Parser.ms → GetKGRT)
Problem: Collision rotations computed as delta-from-rest instead of absolute BPOS-space quaternions.
Fix: Separate CLID path:
in coordsys bposMtrx obj.rotation reads absolute rotation.
### 30. BPOS_MATRIX Storage (Import.ms → Read.ms)
Problem: BPOS matrix not stored during import, therefore unavailable for CLID export.
Fix: BPOS_MATRIX stored as comma-separated string in UserProperty.
---
## Bugfixes — Texture Paths
### 31. Texture Path Corruption (Parser.ms → GetTEXS, Plugins_Material.ms)
Problem: Paths like "Textures/RibbonBlur1.tif" or "Textures/Yellow_Star_Dim.tif" were converted to "units/human/arthas/...".
Fix: Original paths stored in material properties (
origDiffusePath,
origNormalPath,
origOrmPath,
origEmissivePath,
origReflectionPath) and prioritized during export.
### 32. .dds → .tif Conversion (Parser.ms → GetTEXS)
Problem: WC3 Reforged MDX references .tif, but local files are .dds.
Fix: Automatic extension conversion during export.
---
## Bugfixes — EVTS (Events)
### 33. NumEvents Loss (Parser.ms → InverseRemapKeys)
Problem: 13→8 events because variant skip ranges collided with event keys that happened to be in the same frame range.
Fix: EVTS keys converted directly via frame→MS instead of through skip ranges.
---
## Bugfixes — FaceFX
### 34. FAFX Path Extension Stripping (Write.ms → WriteFAFX)
Problem: ".facefx" extension was stripped during export.
Fix: Extension preservation.
---
## Bugfixes — Import
### 35. PRE2/CORN/RIBB Auto-Key Bleed (Import.ms)
Problem: During KGRT rotation import,
animate on also created KGTR position keys (auto-key bleed).
Fix: animate off for position tracks during rotation import.
### 36. ATCH Parent Position Override (Import.ms)
Problem: Attachment position was set in world space, destroying the local offset.
Fix: Position calculated relative to parent.
### 37. EVTS Parenting Loss (Import.ms)
Problem: Event objects lost their parent assignment during import → parentId=0 instead of correct value.
Fix: Parent assignment after object creation.
### 38. GLBS EndFrame Storage (Import.ms)
Problem: Global sequence end frame not stored during import.
Fix: GLBS_ENDFRAME_KGTR/KGRT/KGSC/KGAO/KGAC/KATV UserProperties stored during import.