| # Pictuary Battle System Design Document | |
| ## Overview | |
| This document defines a new programmatic battle system for Pictuary that replaces the current description-based approach with executable building blocks. The design is inspired by Pokemon Emerald's sophisticated battle mechanics while being simplified for our use case. | |
| ## Core Philosophy | |
| The battle system is built on **composable building blocks** that can be combined to create unique and dynamic effects. Each action and ability is defined using simple, atomic operations that can be chained together to create complex behaviors. | |
| ## JSON Schema for `generateStats` | |
| ### Monster Definition | |
| ```json | |
| { | |
| "name": "Zephyr Sprite", | |
| "description": "A mysterious floating creature that manipulates wind currents", | |
| "tier": "medium", | |
| "primaryType": "wind", | |
| "secondaryType": null, | |
| "baseStats": { | |
| "hp": 65, | |
| "attack": 50, | |
| "defense": 40, | |
| "fieldAttack": 85, | |
| "fieldDefense": 70, | |
| "speed": 90 | |
| }, | |
| "nature": "hasty", | |
| "specialAbility": { | |
| "name": "Wind Currents", | |
| "description": "Gains +25% speed when opponent uses a contact move", | |
| "trigger": "onOpponentContactMove", | |
| "effects": [ | |
| { | |
| "type": "modifyStats", | |
| "target": "self", | |
| "stats": { "speed": "increase" } | |
| } | |
| ] | |
| }, | |
| "movepool": [ | |
| { | |
| "name": "Gust Strike", | |
| "type": "wind", | |
| "category": "physical", | |
| "power": 65, | |
| "accuracy": 95, | |
| "pp": 20, | |
| "priority": 0, | |
| "flags": ["contact"], | |
| "effects": [ | |
| { | |
| "type": "damage", | |
| "target": "opponent", | |
| "formula": "standard" | |
| } | |
| ] | |
| }, | |
| { | |
| "name": "Piercing Gale", | |
| "type": "wind", | |
| "category": "special", | |
| "power": 80, | |
| "accuracy": 85, | |
| "pp": 15, | |
| "priority": 0, | |
| "flags": [], | |
| "effects": [ | |
| { | |
| "type": "damage", | |
| "target": "opponent", | |
| "formula": "standard" | |
| }, | |
| { | |
| "type": "modifyStats", | |
| "target": "self", | |
| "stats": { "accuracy": "decrease" }, | |
| "condition": "afterUse" | |
| } | |
| ] | |
| }, | |
| { | |
| "name": "Tailwind Boost", | |
| "type": "wind", | |
| "category": "status", | |
| "power": 0, | |
| "accuracy": 100, | |
| "pp": 10, | |
| "priority": 1, | |
| "flags": [], | |
| "effects": [ | |
| { | |
| "type": "modifyStats", | |
| "target": "self", | |
| "stats": { "speed": "greatly_increase" } | |
| } | |
| ] | |
| }, | |
| { | |
| "name": "Reckless Dive", | |
| "type": "wind", | |
| "category": "physical", | |
| "power": 120, | |
| "accuracy": 80, | |
| "pp": 5, | |
| "priority": 0, | |
| "flags": ["contact", "reckless"], | |
| "effects": [ | |
| { | |
| "type": "damage", | |
| "target": "opponent", | |
| "formula": "standard" | |
| }, | |
| { | |
| "type": "damage", | |
| "target": "self", | |
| "formula": "recoil", | |
| "value": 0.25 | |
| } | |
| ] | |
| } | |
| ] | |
| } | |
| ``` | |
| ## Building Blocks System | |
| ### Effect Types | |
| All battle effects are built from these atomic operations: | |
| #### 1. **damage** | |
| ```json | |
| { | |
| "type": "damage", | |
| "target": "opponent" | "self" | "all" | "allies", | |
| "formula": "standard" | "fixed" | "recoil" | "drain" | "custom", | |
| "value": 80, // Fixed damage amount or percentage for recoil/drain | |
| "multiplier": 1.0, // Damage multiplier | |
| "condition": "always" | "ifLowHp" | "ifHighHp" | "afterKO" | "custom" | |
| } | |
| ``` | |
| #### 2. **modifyStats** | |
| ```json | |
| { | |
| "type": "modifyStats", | |
| "target": "self" | "opponent" | "all", | |
| "stats": { | |
| "attack": "increase", // "increase" | "decrease" | "greatly_increase" | "greatly_decrease" | |
| "defense": "decrease", | |
| "speed": "greatly_increase", | |
| "accuracy": "decrease" | |
| }, | |
| "condition": "always" | "onHit" | "afterUse" | "ifCritical" | |
| } | |
| ``` | |
| **Standard Stat Modification Levels:** | |
| - **increase**: +25% (1.25x multiplier) | |
| - **decrease**: -25% (0.75x multiplier) | |
| - **greatly_increase**: +50% (1.5x multiplier) | |
| - **greatly_decrease**: -50% (0.5x multiplier) | |
| #### 3. **applyStatus** | |
| ```json | |
| { | |
| "type": "applyStatus", | |
| "target": "opponent" | "self", | |
| "status": "burn" | "freeze" | "paralyze" | "poison" | "sleep" | "confuse", | |
| "chance": 30, // Percentage chance | |
| "condition": "onHit" | "always" | |
| } | |
| ``` | |
| #### 4. **heal** | |
| ```json | |
| { | |
| "type": "heal", | |
| "target": "self" | "ally", | |
| "amount": "percentage" | "fixed", | |
| "value": 50, // 50% of max HP or 50 fixed HP | |
| "condition": "always" | "ifLowHp" | "endOfTurn" | |
| } | |
| ``` | |
| #### 5. **manipulatePP** | |
| ```json | |
| { | |
| "type": "manipulatePP", | |
| "target": "opponent", | |
| "action": "drain" | "restore" | "disable", | |
| "amount": 3, // PP to drain/restore | |
| "targetMove": "last" | "random" | "strongest" | |
| } | |
| ``` | |
| #### 6. **fieldEffect** | |
| ```json | |
| { | |
| "type": "fieldEffect", | |
| "effect": "reflect" | "lightScreen" | "spikes" | "healingMist" | "toxicSpikes", | |
| "target": "playerSide" | "opponentSide" | "field", | |
| "stackable": false | |
| } | |
| ``` | |
| #### 7. **counter** | |
| ```json | |
| { | |
| "type": "counter", | |
| "counterType": "physical" | "special" | "any", | |
| "multiplier": 2.0, // Damage multiplier when countering | |
| "condition": "ifDamagedThisTurn" | |
| } | |
| ``` | |
| #### 8. **priority** | |
| ```json | |
| { | |
| "type": "priority", | |
| "target": "self", | |
| "value": 1, // Priority bracket (-5 to +5) | |
| "condition": "ifLowHp" | "always" | |
| } | |
| ``` | |
| #### 9. **removeStatus** | |
| ```json | |
| { | |
| "type": "removeStatus", | |
| "target": "self" | "opponent" | "allies" | "all", | |
| "status": "burn" | "freeze" | "paralyze" | "poison" | "sleep" | "confuse" | "all", | |
| "condition": "always" | "onSwitchIn" | "endOfTurn" | |
| } | |
| ``` | |
| ### Triggers and Conditions | |
| Effects can be triggered by various battle events: | |
| - **always**: Effect always applies when move is used | |
| - **onHit**: Effect applies only if the move hits | |
| - **afterUse**: Effect applies after move execution regardless of hit/miss | |
| - **onCritical**: Effect applies only on critical hits | |
| - **ifLowHp**: Effect applies if user's HP < 25% | |
| - **ifHighHp**: Effect applies if user's HP > 75% | |
| - **onOpponentContactMove**: Trigger when opponent uses a contact move | |
| - **endOfTurn**: Effect applies at the end of each turn | |
| - **onSwitchIn**: Effect applies when Piclet enters battle | |
| - **afterKO**: Effect applies after knocking out an opponent | |
| ### Target Specification | |
| - **self**: The move user | |
| - **opponent**: The target opponent | |
| - **all**: All Piclets in battle | |
| - **allies**: All allied Piclets (in team battles) | |
| - **playerSide**: Player's side of the field | |
| - **opponentSide**: Opponent's side of the field | |
| - **field**: Entire battlefield | |
| ## Special Abilities | |
| Special abilities are passive traits that can fundamentally alter battle mechanics. They can use standard effect building blocks OR modify core game mechanics directly. | |
| ### Mechanic Modifications | |
| Special abilities can override or alter fundamental battle mechanics: | |
| #### 9. **mechanicOverride** | |
| ```json | |
| { | |
| "type": "mechanicOverride", | |
| "mechanic": "criticalHits" | "statusImmunity" | "damageReflection" | "healingInversion" | "priorityOverride" | "accuracyBypass" | "typeImmunity" | "contactDamage" | "drainInversion" | "weatherImmunity", | |
| "condition": "always" | "ifLowHp" | "whenStatusAfflicted" | "vsPhysical" | "vsSpecial", | |
| "value": true | false | "invert" | "double" | "absorb" | "reflect" | |
| } | |
| ``` | |
| **Mechanic Types:** | |
| - **criticalHits**: `false` = cannot be crit, `true` = always crit, `"double"` = 2x crit rate | |
| - **statusImmunity**: Array of status types to be immune to | |
| - **damageReflection**: Reflects % of damage back to attacker | |
| - **healingInversion**: Healing effects cause damage instead | |
| - **priorityOverride**: Always goes first/last regardless of speed | |
| - **accuracyBypass**: Moves cannot miss this Piclet | |
| - **typeImmunity**: Immune to specific damage types | |
| - **contactDamage**: Attackers take damage when using contact moves | |
| - **drainInversion**: HP draining moves heal the target instead | |
| - **weatherImmunity**: Unaffected by weather damage/effects | |
| ### Advanced Ability Examples | |
| #### 1. **Shell Armor** - Cannot be critically hit | |
| ```json | |
| { | |
| "name": "Shell Armor", | |
| "description": "Hard shell prevents critical hits", | |
| "effects": [ | |
| { | |
| "type": "mechanicOverride", | |
| "mechanic": "criticalHits", | |
| "condition": "always", | |
| "value": false | |
| } | |
| ] | |
| } | |
| ``` | |
| #### 2. **Rough Skin** - Contact moves damage attacker | |
| ```json | |
| { | |
| "name": "Rough Skin", | |
| "description": "Rough skin damages attackers on contact", | |
| "triggers": [ | |
| { | |
| "event": "onContactDamage", | |
| "effects": [ | |
| { | |
| "type": "damage", | |
| "target": "attacker", | |
| "formula": "fixed", | |
| "value": 12 | |
| } | |
| ] | |
| } | |
| ] | |
| } | |
| ``` | |
| #### 3. **Sap Sipper** - Healed by nature-type moves | |
| ```json | |
| { | |
| "name": "Sap Sipper", | |
| "description": "Absorbs nature-type moves to restore HP", | |
| "triggers": [ | |
| { | |
| "event": "onDamageTaken", | |
| "condition": "ifMoveType:nature", | |
| "effects": [ | |
| { | |
| "type": "mechanicOverride", | |
| "mechanic": "damageAbsorption", | |
| "value": "absorb" | |
| }, | |
| { | |
| "type": "heal", | |
| "target": "self", | |
| "amount": "percentage", | |
| "value": 25 | |
| } | |
| ] | |
| } | |
| ] | |
| } | |
| ``` | |
| #### 4. **Poison Heal** - Healed by poison instead of damaged | |
| ```json | |
| { | |
| "name": "Poison Heal", | |
| "description": "Poison heals instead of damages", | |
| "effects": [ | |
| { | |
| "type": "mechanicOverride", | |
| "mechanic": "statusEffect:poison", | |
| "value": "invert" | |
| } | |
| ] | |
| } | |
| ``` | |
| #### 5. **Wonder Guard** - Only super-effective moves can hit | |
| ```json | |
| { | |
| "name": "Wonder Guard", | |
| "description": "Only super-effective moves deal damage", | |
| "effects": [ | |
| { | |
| "type": "mechanicOverride", | |
| "mechanic": "damageCalculation", | |
| "condition": "ifNotSuperEffective", | |
| "value": false | |
| } | |
| ] | |
| } | |
| ``` | |
| #### 6. **Levitate** - Immune to ground-type moves | |
| ```json | |
| { | |
| "name": "Levitate", | |
| "description": "Floating ability makes ground moves miss", | |
| "effects": [ | |
| { | |
| "type": "mechanicOverride", | |
| "mechanic": "typeImmunity", | |
| "value": ["ground"] | |
| } | |
| ] | |
| } | |
| ``` | |
| #### 7. **Vampiric** - Drain moves damage the drainer | |
| ```json | |
| { | |
| "name": "Vampiric", | |
| "description": "Cursed blood damages those who try to drain it", | |
| "triggers": [ | |
| { | |
| "event": "onHPDrained", | |
| "effects": [ | |
| { | |
| "type": "mechanicOverride", | |
| "mechanic": "drainInversion", | |
| "value": true | |
| }, | |
| { | |
| "type": "damage", | |
| "target": "attacker", | |
| "formula": "fixed", | |
| "value": 20 | |
| } | |
| ] | |
| } | |
| ] | |
| } | |
| ``` | |
| #### 8. **Insomnia** - Cannot be put to sleep | |
| ```json | |
| { | |
| "name": "Insomnia", | |
| "description": "Prevents sleep status", | |
| "effects": [ | |
| { | |
| "type": "mechanicOverride", | |
| "mechanic": "statusImmunity", | |
| "value": ["sleep"] | |
| } | |
| ] | |
| } | |
| ``` | |
| #### 9. **Prankster** - Status moves have +1 priority | |
| ```json | |
| { | |
| "name": "Prankster", | |
| "description": "Status moves gain priority", | |
| "effects": [ | |
| { | |
| "type": "mechanicOverride", | |
| "mechanic": "priorityOverride", | |
| "condition": "ifStatusMove", | |
| "value": 1 | |
| } | |
| ] | |
| } | |
| ``` | |
| #### 10. **Magic Bounce** - Reflects status moves | |
| ```json | |
| { | |
| "name": "Magic Bounce", | |
| "description": "Reflects status moves back at the user", | |
| "triggers": [ | |
| { | |
| "event": "onStatusMoveTargeted", | |
| "effects": [ | |
| { | |
| "type": "mechanicOverride", | |
| "mechanic": "targetRedirection", | |
| "value": "reflect" | |
| } | |
| ] | |
| } | |
| ] | |
| } | |
| ``` | |
| ### Complex Multi-Mechanic Abilities | |
| #### **Protean** - Changes type to match moves used | |
| ```json | |
| { | |
| "name": "Protean", | |
| "description": "Changes type to match the move being used", | |
| "triggers": [ | |
| { | |
| "event": "beforeMoveUse", | |
| "effects": [ | |
| { | |
| "type": "mechanicOverride", | |
| "mechanic": "typeChange", | |
| "value": "matchMoveType" | |
| } | |
| ] | |
| } | |
| ] | |
| } | |
| ``` | |
| #### **Contrary** - Stat changes are reversed | |
| ```json | |
| { | |
| "name": "Contrary", | |
| "description": "Stat changes have the opposite effect", | |
| "effects": [ | |
| { | |
| "type": "mechanicOverride", | |
| "mechanic": "statModification", | |
| "value": "invert" | |
| } | |
| ] | |
| } | |
| ``` | |
| ### Status-Specific Abilities | |
| #### **Frost Walker** - Heal when frozen | |
| ```json | |
| { | |
| "name": "Frost Walker", | |
| "description": "Thrives in frozen conditions, healing instead of being immobilized", | |
| "effects": [ | |
| { | |
| "type": "mechanicOverride", | |
| "mechanic": "statusEffect:freeze", | |
| "value": "invert" | |
| } | |
| ], | |
| "triggers": [ | |
| { | |
| "event": "onStatusInflicted", | |
| "condition": "ifStatus:freeze", | |
| "effects": [ | |
| { | |
| "type": "heal", | |
| "target": "self", | |
| "amount": "percentage", | |
| "value": 12 | |
| } | |
| ] | |
| } | |
| ] | |
| } | |
| ``` | |
| #### **Glacial Birth** - Starts battle frozen | |
| ```json | |
| { | |
| "name": "Glacial Birth", | |
| "description": "Enters battle in a frozen state but gains defensive bonuses", | |
| "triggers": [ | |
| { | |
| "event": "onSwitchIn", | |
| "effects": [ | |
| { | |
| "type": "applyStatus", | |
| "target": "self", | |
| "status": "freeze", | |
| "chance": 100 | |
| }, | |
| { | |
| "type": "modifyStats", | |
| "target": "self", | |
| "stats": { "defense": "greatly_increase" }, | |
| "condition": "whileFrozen" | |
| } | |
| ] | |
| } | |
| ] | |
| } | |
| ``` | |
| #### **Cryogenic Touch** - Freezes enemy on contact | |
| ```json | |
| { | |
| "name": "Cryogenic Touch", | |
| "description": "Contact moves have a chance to freeze the attacker", | |
| "triggers": [ | |
| { | |
| "event": "onContactDamage", | |
| "effects": [ | |
| { | |
| "type": "applyStatus", | |
| "target": "attacker", | |
| "status": "freeze", | |
| "chance": 30 | |
| } | |
| ] | |
| } | |
| ] | |
| } | |
| ``` | |
| #### **Slumber Heal** - Heal when asleep | |
| ```json | |
| { | |
| "name": "Slumber Heal", | |
| "description": "Restores HP while sleeping instead of being unable to act", | |
| "triggers": [ | |
| { | |
| "event": "endOfTurn", | |
| "condition": "ifStatus:sleep", | |
| "effects": [ | |
| { | |
| "type": "heal", | |
| "target": "self", | |
| "amount": "percentage", | |
| "value": 15 | |
| } | |
| ] | |
| } | |
| ] | |
| } | |
| ``` | |
| #### **Toxic Skin** - Poisons on contact | |
| ```json | |
| { | |
| "name": "Toxic Skin", | |
| "description": "Physical contact poisons the attacker", | |
| "triggers": [ | |
| { | |
| "event": "onContactDamage", | |
| "effects": [ | |
| { | |
| "type": "applyStatus", | |
| "target": "attacker", | |
| "status": "poison", | |
| "chance": 50 | |
| } | |
| ] | |
| } | |
| ] | |
| } | |
| ``` | |
| #### **Paralytic Aura** - Starts battle with paralyzed enemy | |
| ```json | |
| { | |
| "name": "Paralytic Aura", | |
| "description": "Intimidating presence paralyzes the opponent upon entry", | |
| "triggers": [ | |
| { | |
| "event": "onSwitchIn", | |
| "effects": [ | |
| { | |
| "type": "applyStatus", | |
| "target": "opponent", | |
| "status": "paralyze", | |
| "chance": 75 | |
| } | |
| ] | |
| } | |
| ] | |
| } | |
| ``` | |
| #### **Burn Boost** - Powered up when burned | |
| ```json | |
| { | |
| "name": "Burn Boost", | |
| "description": "Fire damage energizes this Piclet, increasing attack power", | |
| "triggers": [ | |
| { | |
| "event": "onStatusInflicted", | |
| "condition": "ifStatus:burn", | |
| "effects": [ | |
| { | |
| "type": "modifyStats", | |
| "target": "self", | |
| "stats": { "attack": "greatly_increase" } | |
| } | |
| ] | |
| } | |
| ] | |
| } | |
| ``` | |
| #### **Confusion Clarity** - Cannot be confused, clears team confusion | |
| ```json | |
| { | |
| "name": "Confusion Clarity", | |
| "description": "Clear mind prevents confusion and helps allies focus", | |
| "effects": [ | |
| { | |
| "type": "mechanicOverride", | |
| "mechanic": "statusImmunity", | |
| "value": ["confuse"] | |
| } | |
| ], | |
| "triggers": [ | |
| { | |
| "event": "onSwitchIn", | |
| "effects": [ | |
| { | |
| "type": "removeStatus", | |
| "target": "allies", | |
| "status": "confuse" | |
| } | |
| ] | |
| } | |
| ] | |
| } | |
| ``` | |
| ### Event Triggers for Abilities | |
| Extended list of trigger events: | |
| - **onDamageTaken**: When this Piclet takes damage | |
| - **onDamageDealt**: When this Piclet deals damage | |
| - **onContactDamage**: When hit by a contact move | |
| - **onStatusInflicted**: When a status is applied to this Piclet | |
| - **onStatusMove**: When targeted by a status move | |
| - **onCriticalHit**: When this Piclet lands/receives a critical hit | |
| - **onHPDrained**: When HP is drained from this Piclet | |
| - **onKO**: When this Piclet knocks out an opponent | |
| - **onSwitchIn**: When this Piclet enters battle | |
| - **onSwitchOut**: When this Piclet leaves battle | |
| - **onWeatherChange**: When battlefield weather changes | |
| - **beforeMoveUse**: Just before this Piclet uses a move | |
| - **afterMoveUse**: Just after this Piclet uses a move | |
| - **onLowHP**: When HP drops below 25% | |
| - **onFullHP**: When HP is at 100% | |
| ## Move Categories and Interactions | |
| ### Physical vs Special Attacks | |
| - **Physical**: Use attack vs defense stats, affected by contact abilities | |
| - **Special**: Use fieldAttack vs fieldDefense stats, no contact interactions | |
| - **Status**: No damage, focus on effects and stat manipulation | |
| ### Move Flags | |
| Moves can have flags that affect interactions: | |
| - **contact**: Triggers contact-based abilities (like Rough Skin) | |
| - **sound**: Affects sound-based interactions | |
| - **bite**: Triggers bite-specific abilities | |
| - **punch**: Triggers punch-specific abilities | |
| - **reckless**: Increased power but with drawbacks | |
| - **priority**: Natural priority moves | |
| - **multiHit**: Hits multiple times | |
| - **charging**: Requires charging turn | |
| ## Dynamic Combinations | |
| ### Power vs Risk Tradeoffs | |
| 1. **High Power, Self-Debuff** | |
| ```json | |
| { | |
| "name": "Berserker Strike", | |
| "power": 130, | |
| "effects": [ | |
| { | |
| "type": "damage", | |
| "target": "opponent", | |
| "formula": "standard" | |
| }, | |
| { | |
| "type": "modifyStats", | |
| "target": "self", | |
| "stats": { "defense": "greatly_decrease" }, | |
| "condition": "afterUse" | |
| } | |
| ] | |
| } | |
| ``` | |
| 2. **Accuracy Trade for Power** | |
| ```json | |
| { | |
| "name": "Wild Swing", | |
| "power": 100, | |
| "accuracy": 70, | |
| "effects": [ | |
| { | |
| "type": "damage", | |
| "target": "opponent", | |
| "formula": "standard" | |
| }, | |
| { | |
| "type": "modifyStats", | |
| "target": "self", | |
| "stats": { "accuracy": "decrease" }, | |
| "condition": "afterUse" | |
| } | |
| ] | |
| } | |
| ``` | |
| 3. **Conditional Power Scaling** | |
| ```json | |
| { | |
| "name": "Revenge Strike", | |
| "power": 60, | |
| "effects": [ | |
| { | |
| "type": "damage", | |
| "target": "opponent", | |
| "formula": "standard", | |
| "multiplier": 1.0, | |
| "condition": "always" | |
| }, | |
| { | |
| "type": "damage", | |
| "target": "opponent", | |
| "formula": "standard", | |
| "multiplier": 2.0, | |
| "condition": "ifDamagedThisTurn" | |
| } | |
| ] | |
| } | |
| ``` | |
| ### Extreme Risk-Reward Moves | |
| Powerful moves with dramatic sacrifices create high-stakes decision making: | |
| #### **Self Destruct** - Ultimate sacrifice for massive damage | |
| ```json | |
| { | |
| "name": "Self Destruct", | |
| "category": "physical", | |
| "power": 200, | |
| "accuracy": 100, | |
| "pp": 1, | |
| "priority": 0, | |
| "flags": ["explosive", "contact"], | |
| "effects": [ | |
| { | |
| "type": "damage", | |
| "target": "all", | |
| "formula": "standard", | |
| "multiplier": 1.5 | |
| }, | |
| { | |
| "type": "damage", | |
| "target": "self", | |
| "formula": "fixed", | |
| "value": 9999, | |
| "condition": "afterUse" | |
| } | |
| ] | |
| } | |
| ``` | |
| #### **Life Drain Overload** - Heal massively but lose stats permanently | |
| ```json | |
| { | |
| "name": "Life Drain Overload", | |
| "category": "special", | |
| "power": 0, | |
| "accuracy": 100, | |
| "pp": 3, | |
| "priority": 0, | |
| "flags": ["draining"], | |
| "effects": [ | |
| { | |
| "type": "heal", | |
| "target": "self", | |
| "amount": "percentage", | |
| "value": 75 | |
| }, | |
| { | |
| "type": "modifyStats", | |
| "target": "self", | |
| "stats": { "attack": "greatly_decrease", "fieldAttack": "greatly_decrease" }, | |
| "condition": "afterUse" | |
| } | |
| ] | |
| } | |
| ``` | |
| #### **Berserker's End** - More damage as HP gets lower, but can't heal | |
| ```json | |
| { | |
| "name": "Berserker's End", | |
| "category": "physical", | |
| "power": 80, | |
| "accuracy": 95, | |
| "pp": 10, | |
| "priority": 0, | |
| "flags": ["contact", "reckless"], | |
| "effects": [ | |
| { | |
| "type": "damage", | |
| "target": "opponent", | |
| "formula": "standard", | |
| "multiplier": 1.0, | |
| "condition": "ifHighHp" | |
| }, | |
| { | |
| "type": "damage", | |
| "target": "opponent", | |
| "formula": "standard", | |
| "multiplier": 2.0, | |
| "condition": "ifLowHp" | |
| }, | |
| { | |
| "type": "mechanicOverride", | |
| "target": "self", | |
| "mechanic": "healingBlocked", | |
| "value": true, | |
| "condition": "afterUse" | |
| } | |
| ] | |
| } | |
| ``` | |
| #### **Mirror Shatter** - Reflect all damage taken this turn back doubled | |
| ```json | |
| { | |
| "name": "Mirror Shatter", | |
| "category": "status", | |
| "power": 0, | |
| "accuracy": 100, | |
| "pp": 5, | |
| "priority": 4, | |
| "flags": ["priority"], | |
| "effects": [ | |
| { | |
| "type": "mechanicOverride", | |
| "target": "self", | |
| "mechanic": "damageReflection", | |
| "value": "double", | |
| "condition": "thisTurn" | |
| }, | |
| { | |
| "type": "modifyStats", | |
| "target": "self", | |
| "stats": { "defense": "greatly_decrease", "fieldDefense": "greatly_decrease" }, | |
| "condition": "afterUse" | |
| } | |
| ] | |
| } | |
| ``` | |
| #### **Temporal Overload** - Act twice next turn, skip following turn | |
| ```json | |
| { | |
| "name": "Temporal Overload", | |
| "category": "status", | |
| "power": 0, | |
| "accuracy": 100, | |
| "pp": 2, | |
| "priority": 0, | |
| "flags": ["temporal"], | |
| "effects": [ | |
| { | |
| "type": "mechanicOverride", | |
| "target": "self", | |
| "mechanic": "extraTurn", | |
| "value": true, | |
| "condition": "nextTurn" | |
| }, | |
| { | |
| "type": "applyStatus", | |
| "target": "self", | |
| "status": "paralyzed", | |
| "chance": 100, | |
| "condition": "turnAfterNext" | |
| } | |
| ] | |
| } | |
| ``` | |
| #### **Blood Pact** - Sacrifice HP to double all damage dealt | |
| ```json | |
| { | |
| "name": "Blood Pact", | |
| "category": "status", | |
| "power": 0, | |
| "accuracy": 100, | |
| "pp": 3, | |
| "priority": 0, | |
| "flags": ["sacrifice"], | |
| "effects": [ | |
| { | |
| "type": "damage", | |
| "target": "self", | |
| "formula": "percentage", | |
| "value": 50 | |
| }, | |
| { | |
| "type": "mechanicOverride", | |
| "target": "self", | |
| "mechanic": "damageMultiplier", | |
| "value": 2.0, | |
| "condition": "restOfBattle" | |
| } | |
| ] | |
| } | |
| ``` | |
| #### **Soul Burn** - Massive special attack that burns user's PP | |
| ```json | |
| { | |
| "name": "Soul Burn", | |
| "category": "special", | |
| "power": 150, | |
| "accuracy": 90, | |
| "pp": 5, | |
| "priority": 0, | |
| "flags": ["burning"], | |
| "effects": [ | |
| { | |
| "type": "damage", | |
| "target": "opponent", | |
| "formula": "standard" | |
| }, | |
| { | |
| "type": "manipulatePP", | |
| "target": "self", | |
| "action": "drain", | |
| "amount": 3, | |
| "targetMove": "random", | |
| "condition": "afterUse" | |
| } | |
| ] | |
| } | |
| ``` | |
| #### **Cursed Gambit** - Random effect: heal fully OR faint instantly | |
| ```json | |
| { | |
| "name": "Cursed Gambit", | |
| "category": "status", | |
| "power": 0, | |
| "accuracy": 100, | |
| "pp": 1, | |
| "priority": 0, | |
| "flags": ["gambling", "cursed"], | |
| "effects": [ | |
| { | |
| "type": "heal", | |
| "target": "self", | |
| "amount": "percentage", | |
| "value": 100, | |
| "condition": "ifLucky50" | |
| }, | |
| { | |
| "type": "damage", | |
| "target": "self", | |
| "formula": "fixed", | |
| "value": 9999, | |
| "condition": "ifUnlucky50" | |
| } | |
| ] | |
| } | |
| ``` | |
| #### **Apocalypse Strike** - Massive damage to all, but user becomes vulnerable | |
| ```json | |
| { | |
| "name": "Apocalypse Strike", | |
| "category": "special", | |
| "power": 120, | |
| "accuracy": 85, | |
| "pp": 1, | |
| "priority": 0, | |
| "flags": ["apocalyptic"], | |
| "effects": [ | |
| { | |
| "type": "damage", | |
| "target": "all", | |
| "formula": "standard", | |
| "multiplier": 1.3 | |
| }, | |
| { | |
| "type": "mechanicOverride", | |
| "target": "self", | |
| "mechanic": "criticalHits", | |
| "value": "alwaysReceive", | |
| "condition": "restOfBattle" | |
| }, | |
| { | |
| "type": "modifyStats", | |
| "target": "self", | |
| "stats": { "defense": "greatly_decrease", "fieldDefense": "greatly_decrease" } | |
| } | |
| ] | |
| } | |
| ``` | |
| ### Multi-Stage Effects | |
| Complex moves can have multiple phases: | |
| ```json | |
| { | |
| "name": "Charging Blast", | |
| "category": "special", | |
| "power": 120, | |
| "accuracy": 90, | |
| "pp": 5, | |
| "flags": ["charging"], | |
| "effects": [ | |
| { | |
| "type": "modifyStats", | |
| "target": "self", | |
| "stats": { "defense": "increase" }, | |
| "condition": "onCharging" | |
| }, | |
| { | |
| "type": "damage", | |
| "target": "opponent", | |
| "formula": "standard", | |
| "condition": "afterCharging" | |
| }, | |
| { | |
| "type": "applyStatus", | |
| "target": "self", | |
| "status": "vulnerable", | |
| "condition": "afterCharging" | |
| } | |
| ] | |
| } | |
| ``` | |
| ## Implementation Benefits | |
| ### 1. **Programmatic Execution** | |
| - All effects are defined as data structures | |
| - Battle engine can execute any combination of effects | |
| - No hardcoded move implementations needed | |
| ### 2. **Infinite Variety** | |
| - Mix and match building blocks for unique moves | |
| - Same building blocks create vastly different strategies | |
| - Easy to balance by adjusting values | |
| ### 3. **Clear Tradeoffs** | |
| - Every powerful effect has a drawback | |
| - Players must weigh risk vs reward | |
| - Multiple viable strategies emerge | |
| ### 4. **Emergent Complexity** | |
| - Simple rules create complex interactions | |
| - Abilities interact with moves in unexpected ways | |
| - Meta-game develops naturally | |
| ### 5. **Easy Extension** | |
| - New effect types can be added seamlessly | |
| - New conditions and triggers expand possibilities | |
| - Backward compatible with existing definitions | |
| ## Battle Flow Integration | |
| The battle system processes effects in this order: | |
| 1. **Pre-Move Phase**: Priority calculation, ability triggers | |
| 2. **Move Execution**: Damage calculation, hit/miss determination | |
| 3. **Effect Application**: Apply all move effects based on conditions | |
| 4. **Post-Move Phase**: End-of-turn abilities, status effects | |
| 5. **Turn Cleanup**: Duration decrements, expired effect removal | |
| This ensures predictable interaction resolution while allowing for complex chains of effects. | |
| ## Balancing Philosophy | |
| The system encourages diverse strategies through: | |
| - **No "strictly better" moves**: Every powerful move has meaningful drawbacks | |
| - **Type diversity matters**: Different types offer different utility patterns | |
| - **Timing is crucial**: When to use high-risk moves becomes strategic | |
| - **Adaptation required**: Static strategies are punishable by counter-play | |
| This creates a dynamic battle system where player skill and strategic thinking matter more than raw stat advantages. | |
| ## Complete Example: Tempest Wraith | |
| Here's a full example of a Piclet using the complete schema with advanced abilities and dramatic moves: | |
| ```json | |
| { | |
| "name": "Tempest Wraith", | |
| "description": "A ghostly creature born from violent storms, wielding lightning and shadow in equal measure", | |
| "tier": "high", | |
| "primaryType": "storm", | |
| "secondaryType": "shadow", | |
| "baseStats": { | |
| "hp": 75, | |
| "attack": 60, | |
| "defense": 45, | |
| "fieldAttack": 95, | |
| "fieldDefense": 80, | |
| "speed": 85 | |
| }, | |
| "nature": "timid", | |
| "specialAbility": { | |
| "name": "Storm Caller", | |
| "description": "When HP drops below 25%, gains immunity to status effects and +50% speed", | |
| "triggers": [ | |
| { | |
| "event": "onLowHP", | |
| "effects": [ | |
| { | |
| "type": "mechanicOverride", | |
| "mechanic": "statusImmunity", | |
| "value": ["burn", "freeze", "paralyze", "poison", "sleep", "confuse"] | |
| }, | |
| { | |
| "type": "modifyStats", | |
| "target": "self", | |
| "stats": { "speed": "greatly_increase" } | |
| } | |
| ] | |
| }, | |
| { | |
| "event": "onSwitchIn", | |
| "condition": "ifWeather:storm", | |
| "effects": [ | |
| { | |
| "type": "modifyStats", | |
| "target": "self", | |
| "stats": { "fieldAttack": "increase" } | |
| } | |
| ] | |
| } | |
| ] | |
| }, | |
| "movepool": [ | |
| { | |
| "name": "Shadow Pulse", | |
| "type": "shadow", | |
| "category": "special", | |
| "power": 70, | |
| "accuracy": 100, | |
| "pp": 15, | |
| "priority": 0, | |
| "flags": [], | |
| "effects": [ | |
| { | |
| "type": "damage", | |
| "target": "opponent", | |
| "formula": "standard" | |
| }, | |
| { | |
| "type": "applyStatus", | |
| "target": "opponent", | |
| "status": "confuse", | |
| "chance": 20, | |
| "condition": "onHit" | |
| } | |
| ] | |
| }, | |
| { | |
| "name": "Lightning Strike", | |
| "type": "storm", | |
| "category": "special", | |
| "power": 85, | |
| "accuracy": 90, | |
| "pp": 10, | |
| "priority": 0, | |
| "flags": [], | |
| "effects": [ | |
| { | |
| "type": "damage", | |
| "target": "opponent", | |
| "formula": "standard" | |
| }, | |
| { | |
| "type": "applyStatus", | |
| "target": "opponent", | |
| "status": "paralyze", | |
| "chance": 15, | |
| "condition": "onHit" | |
| } | |
| ] | |
| }, | |
| { | |
| "name": "Spectral Drain", | |
| "type": "shadow", | |
| "category": "special", | |
| "power": 60, | |
| "accuracy": 95, | |
| "pp": 12, | |
| "priority": 0, | |
| "flags": ["draining"], | |
| "effects": [ | |
| { | |
| "type": "damage", | |
| "target": "opponent", | |
| "formula": "drain", | |
| "value": 0.5 | |
| }, | |
| { | |
| "type": "heal", | |
| "target": "self", | |
| "amount": "percentage", | |
| "value": 50, | |
| "condition": "onHit" | |
| } | |
| ] | |
| }, | |
| { | |
| "name": "Storm's Sacrifice", | |
| "type": "storm", | |
| "category": "special", | |
| "power": 130, | |
| "accuracy": 85, | |
| "pp": 1, | |
| "priority": 0, | |
| "flags": ["sacrifice", "explosive"], | |
| "effects": [ | |
| { | |
| "type": "damage", | |
| "target": "all", | |
| "formula": "standard", | |
| "multiplier": 1.2 | |
| }, | |
| { | |
| "type": "damage", | |
| "target": "self", | |
| "formula": "percentage", | |
| "value": 75, | |
| "condition": "afterUse" | |
| }, | |
| { | |
| "type": "fieldEffect", | |
| "effect": "electricStorm", | |
| "target": "field", | |
| "stackable": false, | |
| "condition": "afterUse" | |
| } | |
| ] | |
| } | |
| ] | |
| } | |
| ``` | |
| This example demonstrates: | |
| ### **Advanced Special Ability** | |
| - **Conditional Triggers**: Different effects based on HP and weather | |
| - **Multiple Mechanics**: Status immunity + stat boosts + weather interactions | |
| - **Strategic Depth**: Becomes more dangerous when near defeat | |
| ### **Diverse Movepool** | |
| - **Standard Attack**: Shadow Pulse with minor status chance | |
| - **Type Coverage**: Storm and Shadow moves for different matchups | |
| - **Utility Move**: Spectral Drain for sustainability | |
| - **Ultimate Move**: Storm's Sacrifice - massive AoE damage with severe self-harm | |
| ### **Meaningful Tradeoffs** | |
| - **Spectral Drain**: Healing requires hitting the opponent | |
| - **Storm's Sacrifice**: Incredible power (130 base + 20% bonus to all) but costs 75% of user's HP | |
| - **Low defenses**: High speed/special attack but vulnerable to physical moves | |
| ### **Emergent Strategy** | |
| - Use standard moves early while healthy | |
| - Spectral Drain for sustain in mid-game | |
| - When low on HP, ability kicks in for immunity and speed boost | |
| - Storm's Sacrifice as desperate finisher or when opponent is also low | |
| This creates a Piclet that plays differently throughout the battle, rewards risk-taking, and offers multiple viable strategies depending on the situation! | 
