Puzzlum / Gamepad Enforcer / Dungeon

Dungeon GE Conditions Guide

A stand-alone implementation guide for using conditions.json as the Dungeon game-logic contract: GE input, modal capture, actor behavior, battle targeting, shops, inventory, rendering priority, diagnostics, and migration rules.

Document date2026-07-03
AudienceDungeon + GE maintainers
Primary project root/public/alpha/Dungeon/
StatusLiving rules contract
Self-contained HTML No external assets Use actor, not NPC No stubs

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.

Most important debugging rule: do not assume the original public assets are the active state. Dungeon can save current map/project changes into server-side storage, so inspect the selected active save slot when runtime behavior diverges from the original files.
  • Use conditions.json for tunable gameplay rules, thresholds, priorities, and action routing.
  • Use actor terminology everywhere. Do not add new NPC labels, 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.js consume 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.

Conditions define intent A condition should name the gameplay rule, the required context, the priority, and the resulting setting or action.
Runtime applies outcomes Dungeon.js still performs movement, transfer, rendering, and battle execution. Conditions tell it which rule applies.
GE resolves input GE owns raw gamepad sampling, alias resolution, combos, chords, cursor behavior, GE Overlay, GE HUD, and GE Dump diagnostics.
Active saves can override data Condition debugging must check active save/project data before assuming a public asset is authoritative.
Loadshared + game + save
Normalizedefaults + aliases
Evaluatecontext + priority
Applyruntime decision
ReportGE Dump trace

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.

LayerExample pathPurpose
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" }
			]
		}
	]
}
FieldRequired?Meaning
idYesStable name used by code, GE Dump, tests, and patch notes.
groupRecommendedBroad owner such as Input, Battle, Actor, Inventory, Shop, Render, or Audio.
enabledDefaultableBoolean switch. Disabled rules remain visible to diagnostics but do not apply.
priorityDefaultableHigher priority rules win when multiple rules match the same decision point.
whenDecision rulesPredicate block using normalized runtime context, not raw DOM/gamepad data.
thenDecision rulesOrdered operations or values applied by the owning runtime subsystem.
traceRecommendedControls 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.

Obsolete terminology: do not create new NPC: condition namespaces, npc.json references, or user-facing “NPC” wording. Use Actor: and actor.json.
UseAvoidReason
Actor: Guard Hunt ActiveNPC: Guard Hunt ActiveDungeon terminology is actor, not NPC.
Input: Battle Mode CapturebattleInputHackConditions should be searchable and diagnostic-friendly.
Shop: Purge Free TransferfreeShopThingNames should reveal the flag and behavior.
Render: Door Hitbox ZIndexdoorClickFixThe 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.

Modal capture rule: Party Panel and Battle Mode consume mouse, keyboard, and gamepad inputs so background gameplay cannot react while panels are active. The exception is GE HUD item activation, which must still be allowed.
{
	"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,Y labels 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.

FeatureCondition responsibilityDungeon 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

AreaExamplesCondition use
IdentityName, Unique Name, Type, Mood, Base, ActionStable references, team grouping, behavior selection.
VitalsHealth, Stamina, Mana with Current, Min, Max, Regen, Enchanted, UndeadBattle eligibility, regeneration, depletion, death/body bag logic.
EconomyEssence, LevelAppraisal, cost display, shop availability.
Flags / visibilityBlocking, Hidden, Mask, Trade, Purge, ReceiverMovement, rendering, visibility filtering, shop behavior, trait merging.
Inventory15-slot action inventoryBattle 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.

Visibility only: 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.

Amount rule: item and ability amounts are floats. Stored amounts preserve fractions. Displayed counts round up.
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 / ActorDefault behaviorCondition notes
Trade: 1Actor allows shop-panel item transfer in both directions.Use slot matching/reserve, empty-slot fallback, float preservation, and zero-unit purge.
ChestChests have Trade by default.Player can take items from a Chest and deposit items into a Chest.
Purge: 1Actor hosts a free shop/container source.Zero-Ess transfers, slot transfer behavior, and zero-unit purge handling.
Body BagBody 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.
  • Mask visibility filtering is render-only by default; masked actors keep logic, collision behavior, persistence, and ZIndex unless 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.

ProblemRuntime behaviorDiagnostic behavior
Duplicate id in same layerUse the last valid entry only if deterministic ordering is guaranteed.Warn with both source locations.
Unknown opIgnore the operation and continue safe defaults.Error with condition ID and operation name.
Unknown flagDo not invent behavior.Warn and show actor/ability context.
Malformed target expressionDisable that ability selection or fall back to solo safe targeting.Error with raw expression and parser location.
Unknown Mask modeUse the validated default, usually hide-matching.Warn with condition ID, actor name, Player unit mask, and requested mode.
Missing shared fileUse game-local defaults if available.Warn that shared GE conditions were unavailable.
Missing game-local fileUse embedded minimal defaults only as a last resort.Error unless intentionally disabled for a test harness.
No silent hardcoding: if a missing condition forces a fallback, the fallback must be named, documented, and visible in GE Dump. Do not hide “temporary” magic values in source.

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 NPC wording with actor wording in condition IDs, comments, UI labels, docs, tests, and diagnostics.
  • Replace npc.json references with actor.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.php loading 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,cluster and target=solo:1,1..3;cluster:1,1 ability 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 Mask values 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

NeedPut it in conditions?Notes
Battle target expression parsingYesUse Battle: Target Resolution.
GE raw axis mappingNoGE owns raw mapping; Dungeon reads resolved aliases.
Modal input captureYesAllow GE HUD exception first.
GE Overlay visual feedbackShared GE condition / codeKeep consistent across all GE-supported games.
Actor movement tuningYesUse Actor: or Movement: IDs.
Actor Mask visibilityYesUse Actor: Mask Visibility Filter; default behavior hides same-masked actors from the active Player unit while preserving actor logic and ZIndex.
Ability database fieldsNoUse abilities.csv; conditions consume normalized ability data.
Item/key/lock depletionYesSame float amount path for all.
Door hitbox priorityYesVisual ZIndex and hitbox ZIndex must agree.
BGM track storageData + conditionActor BGM behavior can be condition-routed; tracks live under sounds assets.
Obsolete NPC namesNoMigrate to Actor; warn only during transition.
Patch habit: when a bug fix introduces a new number, threshold, branch, timing gate, priority, or interaction exception, ask whether it belongs in conditions.json. If the answer is yes, name it, validate it, trace it, and test it.