Introduce the HubScreen as the main interface for managing resources, units, and mission selection, integrating with the GameStateManager for dynamic data binding. Implement the MissionBoard component to display and select available missions, enhancing user interaction with mission details and selection logic. Update the GameStateManager to handle transitions between game states, ensuring a seamless experience for players. Add tests for HubScreen and MissionBoard to validate functionality and integration with the overall game architecture.
174 lines
5.6 KiB
Markdown
174 lines
5.6 KiB
Markdown
---
|
|
description: Effect Processor architecture - the central system for executing all game state changes
|
|
globs: src/systems/EffectProcessor.js, src/systems/EffectProcessor.ts, src/types/Effects.ts
|
|
alwaysApply: false
|
|
---
|
|
|
|
# **Effect Processor Rule**
|
|
|
|
The EffectProcessor is the central system responsible for executing all changes to the game state (Damage, Healing, Movement, Spawning). It is a stateless logic engine that 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.
|
|
|
|
## **1. System Overview**
|
|
|
|
### **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. See `src/types/Effects.ts` for full TypeScript definitions.
|
|
|
|
### **Effect Types**
|
|
|
|
```typescript
|
|
export type EffectType =
|
|
// Combat
|
|
| "DAMAGE"
|
|
| "HEAL"
|
|
| "CHAIN_DAMAGE"
|
|
| "REDIRECT_DAMAGE"
|
|
| "PREVENT_DEATH"
|
|
// Status & Stats
|
|
| "APPLY_STATUS"
|
|
| "REMOVE_STATUS"
|
|
| "REMOVE_ALL_DEBUFFS"
|
|
| "APPLY_BUFF"
|
|
| "GIVE_AP"
|
|
| "ADD_CHARGE"
|
|
| "ADD_SHIELD"
|
|
| "CONVERT_DAMAGE_TO_HEAL"
|
|
| "DYNAMIC_BUFF"
|
|
// Movement & Physics
|
|
| "TELEPORT"
|
|
| "MOVE_TO_TARGET"
|
|
| "SWAP_POSITIONS"
|
|
| "PHYSICS_PULL"
|
|
| "PUSH"
|
|
// World & Spawning
|
|
| "SPAWN_OBJECT"
|
|
| "SPAWN_HAZARD"
|
|
| "SPAWN_LOOT"
|
|
| "MODIFY_TERRAIN"
|
|
| "DESTROY_VOXEL"
|
|
| "DESTROY_OBJECTS"
|
|
| "REVEAL_OBJECTS"
|
|
| "COLLECT_LOOT"
|
|
// Meta / Logic
|
|
| "REPEAT_SKILL"
|
|
| "CANCEL_EVENT"
|
|
| "REDUCE_COST"
|
|
| "BUFF_SPAWN"
|
|
| "MODIFY_AOE";
|
|
```
|
|
|
|
### **Effect Parameters**
|
|
|
|
```typescript
|
|
export interface EffectParams {
|
|
// Combat 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)
|
|
element?: "PHYSICAL" | "FIRE" | "ICE" | "SHOCK" | "VOID" | "TECH";
|
|
|
|
// Chaining
|
|
bounces?: number;
|
|
decay?: number;
|
|
synergy_trigger?: string; // Status ID that triggers bonus effect
|
|
|
|
// Status/Buffs
|
|
status_id?: string;
|
|
duration?: number;
|
|
stat?: string; // For Buffs
|
|
value?: number; // For Buffs/Mods
|
|
chance?: number; // 0.0 to 1.0 (Proc chance)
|
|
|
|
// Physics
|
|
force?: number; // Distance
|
|
destination?: "TARGET" | "BEHIND_TARGET" | "ADJACENT_TO_TARGET";
|
|
|
|
// World
|
|
object_id?: string; // Unit ID to spawn
|
|
hazard_id?: string;
|
|
tag?: string; // Filter for objects (e.g. "COVER")
|
|
range?: number; // AoE radius
|
|
|
|
// Logic
|
|
percentage?: number; // 0.0 - 1.0
|
|
amount?: number; // Flat amount (AP/Charge)
|
|
amount_range?: [number, number]; // [min, max]
|
|
set_hp?: number; // Hard set HP value
|
|
shape?: "CIRCLE" | "LINE" | "CONE" | "SINGLE";
|
|
size?: number;
|
|
multiplier?: number;
|
|
}
|
|
```
|
|
|
|
## **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. Implementation Requirements**
|
|
|
|
- **Statelessness:** The processor should not hold state. It acts on the Unit and Grid passed to it
|
|
- **Schema:** Effects must adhere to the EffectDefinition interface (Type + Params)
|
|
- **All game state mutations** (Damage, Move, Spawn) **MUST** go through `EffectProcessor.process()`
|
|
|