Feedback & Colored Combat Text
Coordinated sound, camera shake, and colored floating combat text for every moment
Overview
Adds a single feedback layer so the big moments of play - a critical hit, a level-up, a bounty completion, a shop purchase - feel like more than a line of text. One service fans each moment out to up to five channels at once, in lockstep: floating combat text (colored where it fires), a 3D sound at the player, an optional camera shake, the corner notification feed, and an in-menu toast for actions taken from inside a UI page (for example accepting a quest from the Quests menu shows a toast over that page in addition to the shared sound cue). Everything is cosmetic, server-owner configurable, and can be turned off.
The two pieces are colored combat text (the red "CRIT!" and gold level-up popups, tuned in combat-text.json) and the broader feedback layer (the per-moment sound and camera, tuned in feedback.json). Each channel is independently guarded, so a misconfigured asset can never break combat.
Colored Combat Text
Two combat moments float colored text above an entity. The text is fully localized into every supported language and ASCII-only, so it renders cleanly everywhere.
| Moment | What you see | Color | Anchored on |
|---|---|---|---|
| Critical hit | A red CRIT! on the struck target | Red (MMO_CombatText_Red) | The target you hit |
| Skill level-up | A gold <Skill> LV <n> | Gold (MMO_CombatText_Gold) | The leveling player |
Only crits and level-ups float. Kill XP and per-action XP show in the corner notification feed instead of floating above mobs, the combo finisher keeps its bonus and notification but does not float, and lifesteal keeps its notification. One color renders per entity per instant, so a held crit color also tints that hit's damage number red - that is intended.
Critical-hit corner notifications ship off by default: the red floating "CRIT!" already marks every crit, so the separate corner toast is redundant. Anyone who wants both can re-enable the crit toggle in Settings and the choice sticks.

combat-text.json
Colored combat text lives in mods/mmoskilltree/combat-text.json. It is override-based - only the fields you change are written; everything else tracks the shipped defaults. A master enabled flag gates the whole feature, and crits and level-ups each have their own toggle.
{
"schemaVersion": 1,
"enabled": true,
"crits": true,
"levelUps": true,
"critStyle": "MMO_CombatText_Red",
"levelUpStyle": "MMO_CombatText_Gold"
}| Field | Default | Purpose |
|---|---|---|
enabled | true | Master switch for all colored combat text. Nothing floats when off. |
crits | true | Toggles the red crit popup on its own. |
levelUps | true | Toggles the gold level-up popup on its own. |
critStyle / levelUpStyle | Red / Gold | The CombatText asset id each popup renders in. Point either at any authored style; an unknown id degrades to plain white. |
The Feedback Layer
Behind the floating text, one service emits a moment and fans it out to a sound, an optional camera shake, the notification feed, and (in menus) a toast - all in lockstep, all from one call. Each moment maps to a row in feedback.json that carries the sound and camera ids for that event.
Moments that fire feedback
| Moment | When it fires | Default sound |
|---|---|---|
KILL_XP | Per-kill skill XP, anchored on the slain mob | Off (high frequency) |
CRIT | A critical hit lands | Off (high frequency) |
COMBO_FINISHER | A combo finisher triggers | Off (high frequency) |
LEVEL_UP | A skill levels up | Off (level-up plays its own reward sound) |
QUEST_ACCEPT | A quest or bounty is accepted, from any surface | SFX_Drop_Items_Paper |
QUEST_ABANDON | A quest is abandoned | SFX_Generic_Crafting_Failed |
BOUNTY_COMPLETE | All objectives on a bounty are met | SFX_Chest_Legendary_Open |
BOUNTY_REROLL | A bounty board is rerolled | SFX_Coins_Land |
SHOP_PURCHASE | A Token Shop offer is bought | SFX_Coins_Land |
Combat moments (KILL_XP, CRIT, COMBO_FINISHER, LEVEL_UP) ship with their sound off by default because they fire often and a default chime would be spammy. Quest, bounty, and shop moments ship with a sensible stock sound. Set a sound id on any row to opt a moment in.
Camera shake
Every moment can also drive a brief camera shake, written straight to the player the same way the engine drives its own damage shake. Camera shake is off by default for every moment (no shake assets ship); the channel exists for servers that want it. Set a cameraEffect id and an intensity on a row to turn it on.
feedback.json
The sound and camera channels live in mods/mmoskilltree/feedback.json. Each moment is one row; an empty sound or cameraEffect string means that channel is off for that moment.
{
"enabled": true,
"events": {
"QUEST_ACCEPT": { "sound": "SFX_Drop_Items_Paper", "cameraEffect": "", "cameraIntensity": 1.0 },
"QUEST_ABANDON": { "sound": "SFX_Generic_Crafting_Failed", "cameraEffect": "", "cameraIntensity": 1.0 },
"BOUNTY_COMPLETE": { "sound": "SFX_Chest_Legendary_Open", "cameraEffect": "", "cameraIntensity": 1.0 },
"SHOP_PURCHASE": { "sound": "SFX_Coins_Land", "cameraEffect": "", "cameraIntensity": 1.0 },
"CRIT": { "sound": "", "cameraEffect": "", "cameraIntensity": 1.0 }
}
}The top-level enabled flag gates the entire sound and camera layer; turning it off leaves colored combat text and the notification feed untouched, since those are governed separately.
Turning It Off
There are independent switches at every level, so you can keep exactly what you want.
- All colored combat text - set
enabled: falseincombat-text.json. - Just crits or just level-ups - flip
critsorlevelUpsincombat-text.json. - All sounds and camera shake - set
enabled: falseinfeedback.json, or clear a single moment'ssound/cameraEffectstring. - Corner notifications - players toggle individual notification categories (including the crit toast) in their in-game Settings, and the choice persists.
Quest accept and abandon cues are shared across every surface, so the bounty board, the NPC quest page, dialogue, and the quest log all play the identical cue. See Quests and Combo Finishers for the gameplay those moments come from.