# **Effect Processor Specification: The Game Logic Engine** This document defines the architecture for the **Effect Processor**, the central system responsible for executing all changes to the game state (Damage, Healing, Movement, Spawning). ## **1. System Overview** The EffectProcessor is a stateless logic engine. It takes a **Definition** (What to do) and a **Context** (Who is doing it to whom), and applies the necessary mutations to the UnitManager or VoxelGrid. ### **Architectural Role** - **Input:** EffectDefinition (JSON), Source (Unit), Target (Unit/Tile). - **Output:** State Mutation (HP changed, Unit moved) + EffectResult (Log data). - **Pattern:** Strategy Pattern. Each effect_type maps to a specific Handler Function. ## **2. Integration Points** ### **A. Calling the Processor** The Processor is never called directly by the UI. It is invoked by: 1. **SkillManager:** When an Active Skill is executed. 2. **EventSystem:** When a Passive Item triggers (e.g., "On Hit -> Apply Burn"). 3. **Environmental Hazard:** When a unit starts their turn on Fire/Acid. ### **B. Dependencies** The Processor requires injection of: - VoxelGrid: To check collision, modify terrain, or move units. - UnitManager: To find neighbors (Chain Lightning) or spawn tokens (Turrets). - RNG: A seeded random number generator for damage variance and status chances. ## **3. Data Structure (JSON Schema)** Every effect in the game must adhere to this structure. ```typescript interface EffectDefinition { type: EffectType; // -- Magnitude -- power?: number; // Base amount (Damage/Heal) attribute?: string; // Stat to scale off (e.g., "strength", "magic") scaling?: number; // Multiplier for attribute (Default: 1.0) // -- Flavour -- element?: "PHYSICAL" | "FIRE" | "ICE" | "SHOCK" | "VOID" | "TECH"; // -- Status/Buffs -- status_id?: string; // For APPLY_STATUS duration?: number; // Turns chance?: number; // 0.0 to 1.0 // -- Movement/Physics -- force?: number; // Distance for Push/Pull destination?: "TARGET" | "BEHIND_TARGET"; // For Teleport // -- Conditionals -- condition?: { target_tag?: string; // e.g. "MECHANICAL" target_status?: string; // e.g. "WET" hp_threshold?: number; // e.g. 0.3 (30%) }; } type EffectType = | "DAMAGE" | "HEAL" | "APPLY_STATUS" | "REMOVE_STATUS" | "TELEPORT" | "PUSH" | "PULL" | "SPAWN_UNIT" | "MODIFY_TERRAIN" // Destroy walls, create hazards | "CHAIN_DAMAGE"; // Bouncing projectiles ``` ## 4. Handler Specifications ### Handler: `DAMAGE` - **Logic:** `FinalDamage = (BasePower + (Source[Attribute] * Scaling)) - Target.Defense`. - **Element Check:** If Target has Resistance/Weakness to `element`, modify FinalDamage. - **Result:** `Target.currentHP -= FinalDamage`. ### Handler: `CHAIN_DAMAGE` - **Logic:** Apply `DAMAGE` to primary target. Then, scan for N nearest enemies within Range R. Apply `DAMAGE * Decay` to them. - **Synergy:** If `condition.target_status` is present on a target, the chain may branch or deal double damage. ### Handler: `TELEPORT` - **Logic:** Validate destination tile (must be Air and Unoccupied). Update `Unit.position` and `VoxelGrid.unitMap`. - **Visuals:** Trigger "Vanish" VFX at old pos, "Appear" VFX at new pos. ### Handler: `MODIFY_TERRAIN` - **Logic:** Update `VoxelGrid` ID at Target coordinates. - **Use Case:** Sapper's "Breach Charge" turns `ID_WALL` into `ID_AIR`. - **Safety:** Check `VoxelGrid.isDestructible()`. Do not destroy bedrock. --- ## 5. Conditions of Acceptance (CoA) **CoA 1: Attribute Scaling** - Given a Damage Effect with `power: 10` and `attribute: "magic"`, if Source has `magic: 5`, the output damage must be 15. **CoA 2: Conditional Logic** - Given an Effect with `condition: { target_status: "WET" }`, if the target does _not_ have the "WET" status, the effect must **not** execute (return early). **CoA 3: State Mutation** - When `APPLY_STATUS` is executed, the Target unit's `statusEffects` array must contain the new ID with the correct duration. **CoA 4: Physics Safety** - When `PUSH` is executed, the system must check `VoxelGrid.isSolid()` behind the target. If a wall exists, the unit must **not** move into the wall (optionally take "Smash" damage instead). --- ## 6. Prompt for Coding Agent > "Create `src/systems/EffectProcessor.js`. > > 1. **Constructor:** Accept `VoxelGrid` and `UnitManager`. Initialize a map of `handlers`. > 2. **Process Method:** `process(effectDef, source, target)`. Look up handler by `effectDef.type`. Verify `checkConditions()`. Execute handler. Return `ResultObject`. > 3. **Handlers:** Implement `handleDamage`, `handleHeal`, `handleStatus`, `handleMove`. > 4. **Helper:** Implement `calculatePower(def, source)` to handle attribute scaling logic centrally."