1. Purpose and Ground Rules
Dungeon should use conditions.json for game logic and tuning. The goal is to keep runtime behavior data-driven, testable, and adjustable without hiding rules inside scattered event handlers, render loops, or one-off branches in Dungeon.js.
- Use
conditions.jsonfor tunable gameplay rules, thresholds, priorities, and action routing. - Use actor terminology everywhere. Do not add new
NPClabels, comments, file names, or conditions. - Route GE input through resolved aliases, chords, combos, and GE HUD exceptions. Do not sample raw browser gamepads from gameplay logic.
- Normalize conditions once at boot, then let
Dungeon.jsconsume the normalized table. - Patch shared GE code when the behavior belongs to every GE-supported game.
- Ship path-preserving changes with Windows newlines, tabs in source patches, and no stubs.
2. Mental Model
A Dungeon condition is a named rule object that answers one of three questions: when is something true?, what value should the runtime use?, or what action should be allowed next? Conditions are not a second game engine. They are the declarative contract that keeps the engine from hardcoding rules.
Dungeon.js still performs movement, transfer, rendering, and battle execution. Conditions tell it which rule applies.
3. Files, Roots, and Merge Order
Conditions should be loaded through the same GE-supported game path discipline as the rest of Dungeon. Avoid obsolete ink.php paths for GE-supported game scripts, assets, maps, bundles, or game loading.
| Layer | Example path | Purpose |
|---|---|---|
| Shared GE defaults | /Gamepad-Enforcer/GE/conditions.json |
Rules that are common across GE-supported games, such as modal input capture vocabulary and HUD priority names. |
| Dungeon game-local rules | /alpha/Dungeon/GE/conditions.json |
Dungeon-specific movement, battle, shop, actor, inventory, rendering, and panel rules. |
| Active project/save rules | /<flavor>-private/users/<username>/Dungeon/saves/<save name>/... |
Selected active-save overrides. These may explain behavior that is not visible in original public files. |
| Runtime debug overrides | Developer-only memory state | Temporary testing values only. Never ship hidden debug overrides as the permanent rule source. |
Recommended merge rule
Use a deterministic deep merge by condition id. Later layers may override scalar fields, extend arrays only when explicitly marked, and replace arrays by default. Every resolved rule should retain a source trace for GE Dump.
{
"merge": {
"key": "id",
"objects": "deep",
"arrays": "replace",
"traceSources": true
}
}
4. Recommended Schema
Keep the file simple enough for hand editing, strict enough for validation, and expressive enough to replace hardcoded branches.
{
"version": 1,
"meta": {
"project": "Dungeon",
"owner": "GE",
"description": "Dungeon GE condition rules"
},
"defaults": {
"enabled": true,
"priority": 100,
"consume": false,
"trace": true
},
"groups": {
"Input": { "priority": 1000 },
"Battle": { "priority": 800 },
"Actor": { "priority": 600 },
"Inventory": { "priority": 500 },
"Render": { "priority": 400 }
},
"conditions": [
{
"id": "Input: Modal Capture",
"group": "Input",
"enabled": true,
"priority": 1000,
"when": { "anyPanelActive": ["Party Panel", "Battle Mode"] },
"then": [
{ "op": "allow", "inputClass": "GE HUD" },
{ "op": "consume", "inputClass": "mouse,keyboard,gamepad" }
]
}
]
}
| Field | Required? | Meaning |
|---|---|---|
id | Yes | Stable name used by code, GE Dump, tests, and patch notes. |
group | Recommended | Broad owner such as Input, Battle, Actor, Inventory, Shop, Render, or Audio. |
enabled | Defaultable | Boolean switch. Disabled rules remain visible to diagnostics but do not apply. |
priority | Defaultable | Higher priority rules win when multiple rules match the same decision point. |
when | Decision rules | Predicate block using normalized runtime context, not raw DOM/gamepad data. |
then | Decision rules | Ordered operations or values applied by the owning runtime subsystem. |
trace | Recommended | Controls whether the rule appears in GE Dump condition traces. |
5. Naming Standards
Condition names must read like implementation contracts. Use title-case namespace prefixes, stable punctuation, and current Dungeon vocabulary.
NPC: condition namespaces, npc.json references, or user-facing “NPC” wording. Use Actor: and actor.json.
| Use | Avoid | Reason |
|---|---|---|
Actor: Guard Hunt Active | NPC: Guard Hunt Active | Dungeon terminology is actor, not NPC. |
Input: Battle Mode Capture | battleInputHack | Conditions should be searchable and diagnostic-friendly. |
Shop: Purge Free Transfer | freeShopThing | Names should reveal the flag and behavior. |
Render: Door Hitbox ZIndex | doorClickFix | The actual rule is hitbox priority, not just a click symptom. |
Condition ID format
<Group>: <Specific Runtime Rule>
Examples:
Input: Modal Capture
Input: GE HUD Exception
Battle: Target Resolution
Battle: Team Phase Order
Actor: Receiver Trait Merge
Actor: Guard Return Oscillation Prevented
Inventory: Float Amount Preservation
Shop: Trade Bidirectional Transfer
Render: Hitbox ZIndex Priority
Audio: Actor BGM Crossfade
6. Evaluation Contract
The runtime should evaluate conditions at named decision points. A decision point asks for the highest-priority matching rule or for a merged list of matching settings, depending on the subsystem.
Decision point shape
const result = DungeonConditions.evaluate("Battle: Target Resolution", {
mode: "battle",
phase: "Player Unit",
actor,
ability,
availableUnits,
pendingDepletion,
ge: window.ge
});
Rules
- Predicates read normalized context only. They do not inspect DOM events, raw gamepad indexes, or raw axes directly.
- Evaluation must be deterministic for the same context. Random rolls should go through the preexisting GE-equivalent dice/random system.
- Rules should be idempotent. Evaluating a condition must not perform the gameplay mutation by itself unless the operation is explicitly an action operation owned by the subsystem.
- Failures must be safe. Missing or malformed conditions fall back to validated defaults, and GE Dump should report the fallback.
- Do not silently invent new flags. Unknown flags should be surfaced in diagnostics.
7. GE Input Conditions
Dungeon consumes GE-resolved input. Raw button indexes, raw axes, and controller-family assumptions belong in GE, not in Dungeon gameplay conditions.
{
"id": "Input: Modal Capture",
"group": "Input",
"priority": 1000,
"when": {
"any": [
{ "panel": "Party Panel", "state": "open" },
{ "mode": "Battle Mode" }
]
},
"then": [
{ "op": "allow", "target": "GE HUD" },
{ "op": "consume", "target": "gameplay" },
{ "op": "consume", "target": "panel-background" }
]
}
GE HUD first
HUD hitboxes should receive their press/release activation before modal gameplay input consumption. This prevents GE Overlay, Rankings, GE Dump, and other HUD items from being swallowed by Party Panel or Battle Mode capture.
Alias-first action binding
{
"id": "Input: Action A",
"group": "Input",
"when": {
"geAlias": "Action A",
"edge": "pressed"
},
"then": [
{ "op": "route", "decision": "current-mode-action" }
]
}
- Face buttons map through GE aliases and controller-family display rules.
- 8BitDo/Nintendo-style controllers must not be treated as fixed Xbox raw indexes.
- Raw
A,B,X,Ylabels are Xbox-style by default unless config/device data identifies Nintendo/Switch/Joy-Con/8BitDo Nintendo-style layout. - When a gamepad slot timestamp freezes, GE should maintain the last known raw input state for that slot; Dungeon should still read resolved GE state.
8. GE Overlay, Cursor, HUD, and Dump Conditions
GE-owned features are not ordinary gameplay widgets. Conditions should document the integration points and exceptions that allow GE to stay consistent across all GE-supported games.
| Feature | Condition responsibility | Dungeon responsibility |
|---|---|---|
| GE Overlay | Toggle routing, active outline, press/bump feedback, face-button display family, and shared overlay activation rules. | Do not block overlay toggles during Party Panel or Battle Mode except through GE-owned rules. |
| GE HUD | Hitbox ZIndex, first-click activation, click/release feedback, active outline, and modal-capture exception. | Let HUD actions execute before gameplay input capture. |
| GE Cursor | Gamepad cursor axes, alias mapping, magnitude-based throttling/gain, and shared cursor state. | Provide hover targets, panel hitboxes, and game-specific cursor rendering effects only where required. |
| GE Dump | Report raw state, resolved state, loaded condition sources, matched rules, consumed inputs, and fallbacks. | Expose safe diagnostics: active mode, active panel, selected actor, selected ability, and last condition decisions. |
{
"id": "Input: GE HUD Exception",
"group": "Input",
"priority": 1100,
"when": {
"hitboxOwner": "GE HUD",
"event": ["pointerdown", "pointerup", "gamepad-activate"]
},
"then": [
{ "op": "bypassModalCapture", "value": true },
{ "op": "activateHudItem" }
]
}
9. Battle Conditions
Battle Mode should be condition-defined: team phase order, selected action, manual targeting, target expression parsing, depletion, and input capture.
Team phase model
Battle turns run as team phases: Player Unit phase first, then Opposition Unit phase. Player units may use manual targeting per selected ability. Opposition units take turns one at a time.
{
"id": "Battle: Team Phase Order",
"group": "Battle",
"priority": 800,
"when": { "mode": "Battle Mode" },
"then": [
{ "op": "phaseOrder", "value": ["Player Unit", "Opposition Unit"] },
{ "op": "oppositionTurnMode", "value": "one-at-a-time" }
]
}
Target resolution expressions
Battle target expressions should be parsed from conditions rather than hardcoded in action handlers. Both compact and explicit target forms are valid:
target:solo,cluster
target=solo:1,1..3;cluster:1,1
{
"id": "Battle: Target Resolution",
"group": "Battle",
"priority": 850,
"when": {
"mode": "Battle Mode",
"ability.hasTargetExpression": true
},
"then": [
{ "op": "parseTargetExpression", "from": "ability.target" },
{ "op": "enableManualTargeting", "team": "Player Unit" },
{ "op": "resolveAvailableUnits" },
{ "op": "respectPendingDepletion", "value": true }
]
}
Runtime condition data for targeting
- Target rule and target mode.
- Available units by team and cluster.
- Pending depletion before final commit.
- Ability units available after float amount checks.
- Key-driven target controls from GE aliases, not raw key/button values.
Action choice application
Action selection bugs should be fixed by validating the condition path from GE input to current battle mode selection to ability execution. Do not create a separate hardcoded path for mouse, keyboard, and gamepad.
10. Actor Conditions
Actors are the runtime entity model for characters, shops, chests, granters, body bags, doors, BGM carriers, hidden logic objects, masked reveal objects, and other interactive map objects.
Actor schema areas that conditions may read
| Area | Examples | Condition use |
|---|---|---|
| Identity | Name, Unique Name, Type, Mood, Base, Action | Stable references, team grouping, behavior selection. |
| Vitals | Health, Stamina, Mana with Current, Min, Max, Regen, Enchanted, Undead | Battle eligibility, regeneration, depletion, death/body bag logic. |
| Economy | Essence, Level | Appraisal, cost display, shop availability. |
| Flags / visibility | Blocking, Hidden, Mask, Trade, Purge, Receiver | Movement, rendering, visibility filtering, shop behavior, trait merging. |
| Inventory | 15-slot action inventory | Battle actions, transfer rules, depletion, display counts. |
Granter and Receiver merge
Granters are actors that define inheritable traits. A Receiver should merge referenced Granter traits before runtime behavior evaluation, so conditions read final normalized actor data rather than manually chasing inheritance every time.
{
"id": "Actor: Receiver Trait Merge",
"group": "Actor",
"priority": 650,
"when": { "actor.hasProperty": "Receiver" },
"then": [
{ "op": "mergeGranterTraits", "from": "actor.Receiver" },
{ "op": "evaluateWithMergedActor", "value": true }
]
}
Mask actor visibility
Mask is an actor visibility flag/property, not an actor-removal rule. When a Player unit has a populated Mask, actors with the same Mask value are hidden from view by default. The actor remains present, keeps its state, keeps its logic, keeps its collision behavior unless another rule changes it, and keeps its normal ZIndex for when it becomes visible again.
Mask should not silently disable actor logic, inventory, collision, persistence, BGM behavior, Receiver inheritance, or battle/shop eligibility. Any input/hitbox suppression for masked actors should be a separate, explicit condition.
{
"Name": "Player",
"Mask": "darkness"
}
{
"Name": "Hidden Trap",
"Mask": "darkness"
}
In the default hide-matching mode, the Player unit above hides the Hidden Trap from rendering because both actors carry the same darkness mask. Conditions must also support invertible behavior, such as reveal-matching, only-matching, or other reveal-through-mask modes, without hardcoding a single visibility interpretation into Dungeon.js.
{
"id": "Actor: Mask Visibility Filter",
"group": "Actor",
"priority": 610,
"when": {
"player.hasProperty": "Mask",
"actor.hasProperty": "Mask"
},
"then": [
{ "op": "compareMask", "left": "player.Mask", "right": "actor.Mask" },
{ "op": "setMaskMode", "default": "hide-matching", "allowed": ["hide-matching", "reveal-matching", "only-matching"] },
{ "op": "applyVisibilityFilter", "scope": "render-only" },
{ "op": "preserveActorLogic", "value": true },
{ "op": "preserveZIndex", "value": true }
]
}
Optional float mask values, such as Mask Radius, Mask Alpha, or Mask Falloff, should be condition-defined when Dungeon needs softer effects like torchlight, fog-of-war, reveal radius, or partial transparency. A Receiver-inherited Mask must behave exactly like a directly authored Mask because Granter traits are merged before runtime behavior evaluation.
Guard and follower behavior
Guard hunt, retarget, return, cluster, disband, follow spacing, and oscillation prevention values should be named actor conditions. Migrate any old NPC: condition names to Actor: equivalents.
11. Movement, Auto-Walk, Doors, Keys, and Locks
Movement conditions should define gating, step timing, collision, blocking, lock/key depletion, door priority, Auto-Walk cadence, and stall recovery.
Auto-Walk stall prevention
{
"id": "Movement: Auto-Walk Stall Prevention",
"group": "Movement",
"priority": 700,
"when": {
"mode": "map",
"autoWalk": true
},
"then": [
{ "op": "requireFreshStepDecision", "value": true },
{ "op": "preventDuplicateRelativeStep", "value": true },
{ "op": "retryAfterBlockedStep", "value": false },
{ "op": "traceStallReason", "value": true }
]
}
Keys and locks use the same depletion system
Keys, locks, ordinary items, ability charges, shop transfers, chests, and purge containers must share the same float amount/depletion logic. Do not add an integer-only key path.
{
"id": "Inventory: Keys And Locks Float Depletion",
"group": "Inventory",
"when": { "interaction": "lock" },
"then": [
{ "op": "useFloatAmount", "value": true },
{ "op": "depleteMatchingSlot", "amountFrom": "lock.requiredAmount" },
{ "op": "purgeZeroUnitSlots", "scope": "all-actors" }
]
}
Doors and hitbox priority
Doors must not accidentally use a lower ZIndex than other actors when their intended interaction priority is higher. Visual ZIndex and hitbox ZIndex both matter.
12. Abilities and Inventory Conditions
Abilities, items, appraisal values, action inventory slots, depletion, display counts, and sprites should be normalized before condition evaluation.
stored amount: 0.25
shown count: 1
stored amount: 1.10
shown count: 2
{
"id": "Inventory: Float Amount Preservation",
"group": "Inventory",
"priority": 520,
"when": { "slot.hasAmount": true },
"then": [
{ "op": "storeAmountAs", "type": "float" },
{ "op": "displayCountAs", "method": "ceil" },
{ "op": "purgeWhenAmountLessOrEqual", "value": 0 }
]
}
Ability sprites
- Every listed ability should display its animated sprite before its name.
- In the Dungeon Editor, missing/no ability animation should display the Empty animation.
- In the live game, missing/no ability animation should display a grey placeholder box.
- The live grey placeholder applies only to listed abilities without animations, not to every missing/non-ability sprite context.
Ability data authority
abilities.csv should own ability definitions, sprite-frame assignments, slot picker entries, and item appraisal values. Conditions may consume normalized ability data but should not duplicate the ability database.
13. Shop, Chest, Trade, and Purge Conditions
Shop conditions should cover normal merchants, chests, body bags, free purge containers, and bidirectional trade behavior through the same transfer engine.
| Flag / Actor | Default behavior | Condition notes |
|---|---|---|
Trade: 1 | Actor allows shop-panel item transfer in both directions. | Use slot matching/reserve, empty-slot fallback, float preservation, and zero-unit purge. |
| Chest | Chests have Trade by default. | Player can take items from a Chest and deposit items into a Chest. |
Purge: 1 | Actor hosts a free shop/container source. | Zero-Ess transfers, slot transfer behavior, and zero-unit purge handling. |
| Body Bag | Body Bags have Purge by default. | Use the same free shop/container transfer path. |
{
"id": "Shop: Trade Bidirectional Transfer",
"group": "Shop",
"priority": 620,
"when": {
"actor.flag": "Trade",
"panel": "Shop"
},
"then": [
{ "op": "allowDirection", "value": ["actor-to-player", "player-to-actor"] },
{ "op": "useSlotMatchingReserve", "value": true },
{ "op": "allowEmptySlotFallback", "value": true },
{ "op": "preserveFloatAmounts", "value": true },
{ "op": "purgeZeroUnitSlots", "scope": "all-actors" }
]
}
{
"id": "Shop: Purge Free Transfer",
"group": "Shop",
"priority": 625,
"when": { "actor.flag": "Purge" },
"then": [
{ "op": "setEssenceCost", "value": 0 },
{ "op": "hostFreeShop", "value": true },
{ "op": "purgeZeroUnitSlots", "scope": "all-actors" }
]
}
Essence/appraisal displays should include a space between the number and unit, such as 12 Ess, not 12Ess.
14. Rendering, ZIndex, and Hitbox Conditions
Rendering order and hitbox priority must be explicit enough that click/input targeting matches what the player sees.
{
"id": "Render: Hitbox ZIndex Priority",
"group": "Render",
"priority": 430,
"when": { "hitbox.overlaps": true },
"then": [
{ "op": "sortHitboxesBy", "value": ["ZIndex", "panelZ", "createdOrder"] },
{ "op": "preferFrontMostInteractive", "value": true }
]
}
Required rendering rules
- Doors must not be assigned a lower interaction ZIndex than actors they must outrank.
- Hitboxes need explicit ZIndex priority when visual layers overlap.
- Hidden actors should not visually render, but gameplay logic may still participate where intended.
Maskvisibility filtering is render-only by default; masked actors keep logic, collision behavior, persistence, andZIndexunless another explicit condition changes them.- HUD hitboxes must outrank panel/gameplay input when the activation belongs to GE HUD.
- Grey ability placeholders are for live listed abilities without animations only.
15. Audio and BGM Conditions
BGM is an actor property/behavior generally, not simply a Hexdot feature. Any actor may carry BGM behavior/properties, with looping crossfade support.
{
"id": "Audio: Actor BGM Crossfade",
"group": "Audio",
"priority": 300,
"when": { "actor.hasProperty": "BGM" },
"then": [
{ "op": "resolveTrackPath", "root": "/assets/sounds/" },
{ "op": "loop", "value": true },
{ "op": "crossfade", "seconds": 3 }
]
}
Audio tracks for BGM/sounds should be stored under /assets/sounds/<track>.mp3 and identified by "<track>". Logged-in persistent sound assets should store under the active private save asset path.
16. Diagnostics and GE Dump
GE Dump should make conditions observable. A condition-driven system is only maintainable when a developer can see which rules loaded, which rules matched, and which fallback fired.
Minimum condition trace
{
"decision": "Battle: Target Resolution",
"context": {
"mode": "Battle Mode",
"phase": "Player Unit",
"ability": "Dart"
},
"matched": [
{
"id": "Battle: Target Resolution",
"priority": 850,
"source": "/alpha/Dungeon/GE/conditions.json"
}
],
"result": {
"targetModes": ["solo", "cluster"],
"manualTargeting": true
}
}
GE Dump checklist
- Loaded condition files and merge order.
- Validation errors and unknown fields.
- Active mode, active panel, selected actor, selected ability, selected target, and active save slot.
- Last GE raw state and resolved alias state.
- Last input capture decision and whether GE HUD bypassed modal capture.
- Last battle target expression, parsed target modes, available units, pending depletion, and final result.
- Last shop transfer decision, source/destination slots, float amounts, and purge actions.
- Last mask visibility decision, active Player unit mask value, matched actor masks, mask mode, radius/alpha values, and whether the result was render-only.
- Fallback values used when a condition was missing or disabled.
17. Validation Rules
Condition files should fail loudly in diagnostics and safely in gameplay. The player should get stable defaults; the developer should get enough information to fix the file.
| Problem | Runtime behavior | Diagnostic behavior |
|---|---|---|
Duplicate id in same layer | Use the last valid entry only if deterministic ordering is guaranteed. | Warn with both source locations. |
Unknown op | Ignore the operation and continue safe defaults. | Error with condition ID and operation name. |
| Unknown flag | Do not invent behavior. | Warn and show actor/ability context. |
| Malformed target expression | Disable that ability selection or fall back to solo safe targeting. | Error with raw expression and parser location. |
Unknown Mask mode | Use the validated default, usually hide-matching. | Warn with condition ID, actor name, Player unit mask, and requested mode. |
| Missing shared file | Use game-local defaults if available. | Warn that shared GE conditions were unavailable. |
| Missing game-local file | Use embedded minimal defaults only as a last resort. | Error unless intentionally disabled for a test harness. |
18. Migration and Obsoletion
Conditions are a natural place to finish terminology and behavior migrations, but they must not preserve obsolete names forever.
Required migrations
- Replace
NPCwording withactorwording in condition IDs, comments, UI labels, docs, tests, and diagnostics. - Replace
npc.jsonreferences withactor.json. - Provide an obsoletion PowerShell script for old names when packaging source changes.
- Remove any reference to the never-created
C2-53M Delta. - Keep GE-supported games off obsolete
ink.phploading paths.
Compatibility aliases
During a short transition, a loader may recognize old condition IDs only to emit a warning and map them to the new Actor: names. Do not author new rules with obsolete IDs.
{
"obsolete": {
"NPC: Guard Hunt Active": "Actor: Guard Hunt Active",
"NPC: Guard Return Oscillation Prevented": "Actor: Guard Return Oscillation Prevented"
}
}
19. Testing Checklist
Every condition patch should include functional checks for the exact decision point that changed and regression checks for the shared systems it touches.
- Load Dungeon with public assets, then with an active server-side save slot, and confirm condition source tracing is correct.
- Open Party Panel and Battle Mode; confirm gameplay inputs are consumed while GE HUD items still activate.
- Toggle GE Overlay and Rankings from HUD on the first click; confirm press/bump and active outline behavior are consistent.
- Move GE Cursor by mouse and gamepad; confirm aliases, magnitude behavior, hover targets, and panel hitboxes work.
- Run Battle Mode action selection by mouse, keyboard, and gamepad; confirm the desired selection applies.
- Test
target:solo,clusterandtarget=solo:1,1..3;cluster:1,1ability targeting. - Verify Player Unit phase occurs before Opposition Unit phase and opponents act one at a time.
- Test fractional ability/item amounts, rounded-up display counts, keys, locks, depletion, and zero-unit purge.
- Test Trade and Purge actors, including Chests and Body Bags, for bidirectional/free transfers.
- Confirm doors and overlapping actors use correct visual ZIndex and hitbox ZIndex.
- Test Player unit
Maskvalues against same-masked actors; confirm default hide, inverted reveal modes, optional float radius/alpha behavior, and render-only preservation of actor logic. - Run GE Dump and confirm matched conditions, fallback conditions, and consumed-input traces are visible.
20. Condition Example Pack
This example pack is intentionally small. It demonstrates the pattern without pretending to replace the full Dungeon rule table.
{
"version": 1,
"meta": {
"project": "Dungeon",
"title": "Dungeon GE Conditions",
"date": "2026-07-03"
},
"defaults": {
"enabled": true,
"priority": 100,
"trace": true
},
"conditions": [
{
"id": "Input: GE HUD Exception",
"group": "Input",
"priority": 1100,
"when": { "hitboxOwner": "GE HUD" },
"then": [
{ "op": "bypassModalCapture", "value": true },
{ "op": "activateHudItem" }
]
},
{
"id": "Input: Modal Capture",
"group": "Input",
"priority": 1000,
"when": {
"any": [
{ "panel": "Party Panel", "state": "open" },
{ "mode": "Battle Mode" }
]
},
"then": [
{ "op": "allow", "target": "GE HUD" },
{ "op": "consume", "target": "mouse,keyboard,gamepad" }
]
},
{
"id": "Battle: Team Phase Order",
"group": "Battle",
"priority": 800,
"when": { "mode": "Battle Mode" },
"then": [
{ "op": "phaseOrder", "value": ["Player Unit", "Opposition Unit"] },
{ "op": "oppositionTurnMode", "value": "one-at-a-time" }
]
},
{
"id": "Battle: Target Resolution",
"group": "Battle",
"priority": 850,
"when": { "ability.hasTargetExpression": true },
"then": [
{ "op": "parseTargetExpression", "from": "ability.target" },
{ "op": "enableManualTargeting", "team": "Player Unit" },
{ "op": "respectPendingDepletion", "value": true }
]
},
{
"id": "Actor: Mask Visibility Filter",
"group": "Actor",
"priority": 610,
"when": {
"player.hasProperty": "Mask",
"actor.hasProperty": "Mask"
},
"then": [
{ "op": "compareMask", "left": "player.Mask", "right": "actor.Mask" },
{ "op": "setMaskMode", "default": "hide-matching", "allowed": ["hide-matching", "reveal-matching", "only-matching"] },
{ "op": "applyVisibilityFilter", "scope": "render-only" },
{ "op": "preserveActorLogic", "value": true },
{ "op": "preserveZIndex", "value": true }
]
},
{
"id": "Inventory: Float Amount Preservation",
"group": "Inventory",
"priority": 520,
"then": [
{ "op": "storeAmountAs", "type": "float" },
{ "op": "displayCountAs", "method": "ceil" },
{ "op": "purgeWhenAmountLessOrEqual", "value": 0 }
]
},
{
"id": "Shop: Trade Bidirectional Transfer",
"group": "Shop",
"priority": 620,
"when": { "actor.flag": "Trade" },
"then": [
{ "op": "allowDirection", "value": ["actor-to-player", "player-to-actor"] },
{ "op": "useSlotMatchingReserve", "value": true },
{ "op": "allowEmptySlotFallback", "value": true },
{ "op": "preserveFloatAmounts", "value": true },
{ "op": "purgeZeroUnitSlots", "scope": "all-actors" }
]
},
{
"id": "Shop: Purge Free Transfer",
"group": "Shop",
"priority": 625,
"when": { "actor.flag": "Purge" },
"then": [
{ "op": "setEssenceCost", "value": 0 },
{ "op": "hostFreeShop", "value": true },
{ "op": "purgeZeroUnitSlots", "scope": "all-actors" }
]
},
{
"id": "Render: Hitbox ZIndex Priority",
"group": "Render",
"priority": 430,
"when": { "hitbox.overlaps": true },
"then": [
{ "op": "sortHitboxesBy", "value": ["ZIndex", "panelZ", "createdOrder"] },
{ "op": "preferFrontMostInteractive", "value": true }
]
}
]
}
21. Quick Reference
| Need | Put it in conditions? | Notes |
|---|---|---|
| Battle target expression parsing | Yes | Use Battle: Target Resolution. |
| GE raw axis mapping | No | GE owns raw mapping; Dungeon reads resolved aliases. |
| Modal input capture | Yes | Allow GE HUD exception first. |
| GE Overlay visual feedback | Shared GE condition / code | Keep consistent across all GE-supported games. |
| Actor movement tuning | Yes | Use Actor: or Movement: IDs. |
| Actor Mask visibility | Yes | Use Actor: Mask Visibility Filter; default behavior hides same-masked actors from the active Player unit while preserving actor logic and ZIndex. |
| Ability database fields | No | Use abilities.csv; conditions consume normalized ability data. |
| Item/key/lock depletion | Yes | Same float amount path for all. |
| Door hitbox priority | Yes | Visual ZIndex and hitbox ZIndex must agree. |
| BGM track storage | Data + condition | Actor BGM behavior can be condition-routed; tracks live under sounds assets. |
Obsolete NPC names | No | Migrate to Actor; warn only during transition. |
conditions.json. If the answer is yes, name it, validate it, trace it, and test it.