CustomItemVisual.xml
Defines everything the client needs to render a custom item without a client recompile: body glow, name label color, model folder and .bmd file name, inventory-view rotation / position / scale, ground-drop rotation / scale, trailing arrow effect, an extra tooltip description line with its own colour — and, for capes, a complete per-mesh rendering system that combines physics-simulated cloth with rigid ornament pieces. The server sends the whole table to the client at login; only items listed here receive custom visuals, every other item uses the client's hardcoded defaults.
File Location#
Data/Plugins/Items/CustomItemVisual.xml
Loaded once at GameServer startup. Supports hot reload via plugin admin command.
Schema#
<CustomItemVisuals>
<Item Type="..." Index="..."
R="..." G="..." B="..." Color="..."
Folder="..." BMD="..."
InvRotX="..." InvRotY="..." InvRotZ="..."
InvPosX="..." InvPosY="..." InvScale="..."
GroundRotX="..." GroundRotY="..." GroundRotZ="..." GroundScale="..."
ArrowEffect="..."
CapeTexture="..." CapeTextureFolder="..."
RenderAs="..."
Ornaments="..." OrnamentOffset="..." OrnamentRot="..." OrnamentScale="..." OrnamentMeshes="..."
BodyMesh="..." SideMeshes="..." CapeSize="..." CapeOffset="..."
BlendMesh="..." EffectSpeed="..."
Description="..." DescColor="..." />
</CustomItemVisuals>
Attributes#
Identity#
| Attribute | Range | Effect |
|---|---|---|
Type | 0-15 | Item category |
Index | 0-511 | Sub-index within the category |
Entries with out-of-range Type or Index are skipped at load time.
Body glow + name color#
| Attribute | Range | Effect |
|---|---|---|
R / G / B | 0-255 | Body chrome glow color. All three zero = no glow |
Color | 0-45 | Name label color enum. See table below |
R="255" G="153" B="26" produces a golden glow similar to Golden Monster chrome.
Model override#
| Attribute | Default | Values | Effect |
|---|---|---|---|
Folder | 0 | 0 = Data\Item, 1 = Data\Player, 2 = Data\Custom\Item, 3 = Data\Custom\Player | Client asset folder the custom .bmd lives in. Values above 3 are clamped to 0 and logged as a warning |
BMD | (empty) | up to 31 chars | Mesh file name (no extension) inside Folder. Empty = keep the item's default mesh |
Inventory-view pose#
| Attribute | Default | Effect |
|---|---|---|
InvRotX / InvRotY / InvRotZ | 0.0 | Rotation applied when the item is shown inside the inventory grid, in degrees |
InvPosX / InvPosY | 0.0 | Translation applied in inventory view |
InvScale | 0.0 | Inventory-view scale override. 0 keeps the client default |
FitScale | 0.0 | Multiplies the automatic bounding-box fit used for the cash-shop and equipment-slot 3D previews. 0 = off (plain auto-fit) |
FitOffX / FitOffY | 0.0 | Shift the auto-centring target by a fraction of the slot rectangle |
InvScale and InvPos* affect inventory-cell framing only and are ignored under the auto-fit used by the cash shop and equipment slots; FitScale and FitOff* tune that path instead.
Summoner book attributes#
| Attribute | Default | Effect |
|---|---|---|
BookEffect | sahamutt (0) | Which orbiting spectral head the book shows: sahamutt / 0 (fire garnish), neil / 1 (light sparkles), lagul / 2 (purple spirit) |
The value is ignored unless RenderAs="summoner_book". An out-of-range number falls back to sahamutt and logs a warning in the GameServer console.
Ground-drop pose#
| Attribute | Default | Effect |
|---|---|---|
GroundRotX / GroundRotY | 0.0 | Rotation applied to the dropped item on the map |
GroundRotZ | -45.0 | Default ground yaw (negative = leaning away from the camera) |
GroundScale | 0.0 | Ground-drop scale override. 0 keeps the client default |
Trail effect + tooltip text#
| Attribute | Default | Effect |
|---|---|---|
ArrowEffect | (empty) | Symbolic arrow effect name. Empty/absent = default client arrow. See Arrow effect names for the full list. Numeric values are not accepted (the client's effect enum is not stable across builds, so names are synced and resolved client-side) |
Description | (empty) | Extra line appended to the item tooltip (up to 127 chars). Empty = no extra line |
DescColor | 0 | Color enum for the extra tooltip line; same palette as Color |
Glow pages#
| Attribute | Default | Effect |
|---|---|---|
BlendMesh | -3 | Controls which mesh pages of a custom BMD render as an additive, scrolling glow instead of showing a solid black background. -3 = AUTO (default): the largest mesh page stays opaque, every other page is additive and scrolls. -1 = OFF: no page is additive (use on plain multi-mesh props whose secondary meshes wrongly go translucent under AUTO, and on decorated capes). N (0, 1, 2, ...) = only page N is additive and scrolls. -2 = all pages additive, diagnostic only. Single-mesh items are unaffected by AUTO. For per-page control (a different glow per page: own colour, own scale, static or scrolling), see ItemPageEffects.xml |
EffectSpeed | 0.5 | Scroll speed multiplier for the glow animation. 1.0 = original speed, 0.25 = slower, 0 = static (no scroll). Frame-rate independent. Applied to every custom item effect when absent |
Name color enum#
| Value | Color |
|---|---|
0 / 5 | White |
1 | Red-Orange |
2 | Blue |
4 / 20 | Green |
7 | Light Purple |
9 | Purple |
16 | Copper |
19 | Bright Blue |
24 | Gold |
25 | Silver |
29 | Emerald |
30 | Red |
33 | Pink |
40 | Crimson |
41 | Magenta |
42 | Amber |
45 | Cyan |
The full enum spans 0-45 and mirrors the client's name-color palette.
Worn-render templates#
RenderAs lets a custom item dispatch through a class-specific worn-render path. Empty/absent uses the default render path (BMD swap only — the model draws with its own baked animation).
| Name | Effect |
|---|---|
rf_glove_small | Render as a Rage Fighter glove. Equipping the item enables Dragon Slasher / Chain Drive / Dragon Roar client-side. The item attaches to both fists automatically; the attachment points are fixed by the template and cannot be overridden. If <BMD>_L.bmd and <BMD>_R.bmd are present alongside <BMD>.bmd they are loaded automatically and each hand draws its matching variant - same convention vanilla MU uses for Sword33L.bmd / Sword33R.bmd. If a variant is missing, that hand falls back to the main BMD |
cape_cloth | The full custom-cape pipeline: physics-simulated drape (plus optional side banners and a rigid ornament prop). See Custom capes below. DL/RF only - Wizard/Knight/Elf/MG/Summoner have no cloth pipeline |
rf_glove_phoenix | Currently aliases rf_glove_small; reserved for a future wing-tail variant. If you want a Phoenix-style wing-tail, include that mesh in your custom BMD |
summoner_book | Render as a Summoner book. The model is never drawn in the hand; instead the client shows the wrist-orb effect (colour follows item level, like native books) plus an orbiting spectral head selected by BookEffect. BMD / Folder may be left empty. Requires the item to equip into the left-hand slot and the wearer to be a Summoner |
Server-side validation for the RF skills above only checks character class and strength/dexterity, not the equipped item's class flags, so client-side registration alone is sufficient for the skills to fire.
Custom capes (cape_cloth)#
A cape imported from a later MU season is one BMD containing several mesh pages: the big cape panel, sometimes long side banners, and solid ornament pieces (pauldrons, feathers, crowns, sigils). Rendering that BMD as-is fails — it was animated for a different skeleton. The cape_cloth pipeline instead splits the BMD by mesh role and rebuilds the cape the same way the game builds Cape of Emperor:
- Body — one mesh page is chosen as the cape panel. Its texture (and exact texture region) is painted onto a physics-simulated cloth sheet that drapes, collides and reacts to movement. The sheet is sized from the panel's real dimensions automatically.
- Sides (optional) — listed mesh pages become narrow simulated side strips at the shoulders, exactly like Cape of Emperor's hanging side banners, each wearing its own page texture.
- Ornaments (optional) — listed mesh pages render as a rigid prop pinned to the cape bone, tracking the body through every animation. This is how the vanilla Emperor pauldrons work.
- Any page not assigned a role is hidden — a free way to drop baked-in glow planes you do not want.
Alternatively, skip the BMD entirely and paint a plain CapeTexture image onto the drape.
Cape attributes#
| Attribute | Default | Effect |
|---|---|---|
CapeTexture | (empty) | Explicit cloth texture (e.g. my_cape.tga) painted onto the drape instead of the BMD body-mesh texture. Empty = use the BMD's body-mesh texture |
CapeTextureFolder | 2 | Folder for CapeTexture. Same enum as Folder |
BodyMesh | auto | Explicit cape body/panel mesh page. Auto picks the mesh with the longest dimension, which mis-picks on capes with long banner streamers — if the drape wears the wrong texture, set this to the true panel page |
SideMeshes | none | Comma list of mesh pages rendered as side cloth strips (Emperor-style). One index = both strips share its texture; two = right strip uses the first, left the second. Listed pages are hidden from the ornament prop |
Ornaments | 0 | 1 = render the remaining mesh pages as a rigid prop pinned to the cape bone |
OrnamentMeshes | auto | Comma list of pages that ARE ornaments. Auto = every page except body and sides. Any page not listed is hidden — use this to drop glow/effect planes |
OrnamentRot | 0,90,0 | Prop rotation in degrees (vanilla Emperor value). First knob to touch when the prop lies sideways/horizontal — foreign capes use different model axes |
OrnamentOffset | -47,-7,0 | Prop position (vanilla Emperor value). With the default rotation, the second number is the distance from the character's back — raise it to close a gap between pauldrons and body, e.g. -47,15,0 |
OrnamentScale | 1.0 | Uniform prop scale, 0.1–10 |
CapeSize | auto | Drape sheet size "width,height". Auto sizes the sheet from the body panel's real dimensions (fixes overly wide shoulders on narrow panels). Set explicitly only when auto looks wrong, e.g. CapeSize="100,160" |
CapeOffset | 0,0,0 | "x,y,z" delta added to every cloth anchor (drape and side strips move together). Pulls the cloth closer to the back, e.g. CapeOffset="0,-4,0". Does not move the ornament prop — that is OrnamentOffset |
Finding mesh page roles#
Open the cape's .bmd in the MU Online BMD Viewer — it lists mesh pages in the same order the game uses. Assign roles by shape:
- the big flat sheet carrying the main cape art →
BodyMesh - long thin streamers/banners →
SideMeshes - solid sculpted pieces (pauldrons, feathers, crowns) →
OrnamentMeshes - glow/effect planes → leave unlisted (hidden)
Examples#
Wings of Control (Wing405.bmd, 6 mesh pages): page 1 is the blue cape panel, page 2 the striped rune banners, pages 0/3/4 the shoulder cap, silver feathers and gold frame, page 5 an eye-glow plane we do not want.
<Item Type="12" Index="418" Folder="2" BMD="Wing405" BlendMesh="-1" RenderAs="cape_cloth" Ornaments="1"
BodyMesh="1" SideMeshes="2" OrnamentMeshes="0,3,4"
OrnamentOffset="-47,15,0" OrnamentScale="1.0" OrnamentRot="0,90,0" />
<!-- Control Wings: body=blue panel(1), sides=rune banners(2),
ornaments=shoulder cap/feathers/gold frame(0,3,4), eye glow(5) hidden -->
Result: the blue panel drapes with real physics at its true size, the rune banners hang and sway at the shoulders, the gold crown and feathers sit rigid on the back (OrnamentOffset second value raised from the default -7 to 15 to close the gap to the body), and the glow plane is gone. BlendMesh="-1" keeps the ornament pages solid.
A cape BMD with no worthwhile ornaments — the whole model is just used as a texture source for the drape:
<Item Type="12" Index="154" Folder="2" BMD="PureWhiteCape" RenderAs="cape_cloth" BlendMesh="-1" />
The body panel is auto-detected, its texture and exact texture region go onto the simulated drape, and the sheet is auto-sized from the panel. Nothing else renders.
No BMD at all — paint an image straight onto the vanilla drape:
<Item Type="12" Index="501" Folder="2" CapeTexture="guild_cape.tga" CapeTextureFolder="2" RenderAs="cape_cloth" />
Cape tuning guide#
Tune in this order, re-logging after each XML change (the table syncs at login):
| Symptom | Fix |
|---|---|
| Whole prop lies horizontal / rotated wrong | OrnamentRot (foreign model axes) |
| Gap between pauldrons/ornaments and the back | OrnamentOffset — with default rotation, raise/lower the second value |
| Ornaments too large / small | OrnamentScale |
| Drape wears the wrong texture (e.g. the banner stripes) | BodyMesh — auto picked the wrong page |
| Side banners render rigid, or not at all | SideMeshes with the banner page(s) |
| Drape too wide at the shoulders / wrong proportions | usually fixed by auto sizing; override with CapeSize |
| Cloth floats too far behind the back | CapeOffset |
| A glow plane renders as a black/solid sheet | leave that page out of OrnamentMeshes (hidden), and set BlendMesh="-1" |
Arrow effect names#
ArrowEffect accepts the following symbolic names. Anything else (including numeric values) is logged client-side and treated as no override.
| Name | Visual |
|---|---|
MODEL_ARROW | Default wood arrow |
MODEL_ARROW_STEEL | Steel crossbow bolt |
MODEL_ARROW_THUNDER | Lightning arrow |
MODEL_ARROW_LASER | Energy beam arrow |
MODEL_ARROW_V | V-shaped fan arrow |
MODEL_ARROW_SAW | Saw / sawblade arrow |
MODEL_ARROW_NATURE | Nature / leaf arrow |
MODEL_ARROW_BOMB | Bomb arrow |
MODEL_ARROW_WING | Wing / angel arrow |
MODEL_ARROW_TANKER | Heavy tanker arrow |
MODEL_ARROW_DOUBLE | Double crossbow bolt |
MODEL_ARROW_HOLY | Holy / blessed arrow |
MODEL_ARROW_SPARK | Bolt-bow spark trail |
MODEL_ARROW_RING | Sylph ring arrow |
MODEL_ARROW_DARKSTINGER | Dark Stinger arrow |
MODEL_ARROW_BEST_CROSSBOW | Great Reign crossbow bolt |
MODEL_ARROW_DRILL | Drill arrow |
MODEL_ARROW_IMPACT | Star-Fall / Deep Impact rain arrow |
MODEL_ARROW_GAMBLE | Arrow Viper bow trail |
MODEL_LACEARROW | Albatross lace arrow |
Cross-File Dependencies#
| Attribute | Related in |
|---|---|
Type / Index | Item.xml |
BlendMesh | ItemPageEffects.xml overrides BlendMesh per mesh page for the items it lists (own colour / scale / static-or-scrolling per page, plus spin and bob geometric animation) |
| Sync channel | Pushed to the client through the game data sync stream after login |
Important Behavior#
- The
cape_clothpipeline only drapes on Dark Lord and Rage Fighter — the classes with a cloth simulator. Other classes render nothing from it - Cape cloth is rebuilt when the wing changes and re-synced at login; after editing cape attributes, restart the GameServer (or hot-reload the plugin) and re-login to see the change — including at character select, which shows the same cape as in-world
- A cape BMD that has good baked animations and matches this client's skeleton can also be rendered as a plain model (leave
RenderAsempty) — that preserves its own flap animation but gets no physics, no per-mesh roles and no placement knobs - Custom wings (including small wings) do not draw the item-level upgrade glow that normal wings show at higher +levels. The custom mesh and any
BlendMeshglow pages render on their own; the level glow is suppressed - Custom wings keep rendering at distance and stay visible when the camera would otherwise cull them, so they do not pop out at range
- Glow mesh pages animate by default (AUTO
BlendMeshat half speed). SetEffectSpeed="0"to make an effect static, orBlendMesh="-1"to turn additive glow off entirely for plain multi-mesh items and decorated capes
Common Issues#
- Custom glow not visible -
R=G=B=0means no glow - Name color unchanged -
Colorvalue above 45 falls back to default - Visual appears only for some players - other players need to re-login to get the updated sync
- Client crashes on an item -
Folder/BMDpoint at a file that is not shipped with the client; either install the asset or clear the override - Inventory icon looks tiny / gigantic -
InvScaletoo low / high; leave at0to fall back to the client's default - Ground drop floats or clips into the ground - adjust
GroundRotX/GroundRotYrather thanGroundRotZ; yaw rarely fixes pose issues - Extra tooltip line missing -
Descriptionis empty, or the client is an older build that does not render the extra line - Cape drapes with the wrong art - the auto body pick chose a banner/streamer page; set
BodyMeshexplicitly (see the cape tuning guide) - Cape shows but no ornaments -
Ornaments="1"missing, or every non-body page ended up inSideMeshes/hidden CapeOffset"does nothing" - it moves the cloth only; a gap at the static pieces isOrnamentOffset