| # Defining Attacks in pokeemerald | |
| This document analyzes how pokeemerald defines battle actions (moves/attacks) and their effects, providing a clear system architecture for implementing similar battle mechanics in Pokemon-style games. | |
| ## Architecture Overview | |
| pokeemerald uses a **multi-layered, data-driven approach** to define attacks: | |
| 1. **Move Constants** - Unique IDs for each move | |
| 2. **Move Data Structure** - Statistical properties and effect assignments | |
| 3. **Effect Constants** - Categorization of move behaviors | |
| 4. **Battle Scripts** - Implementation logic for each effect | |
| 5. **Script Commands** - Low-level operations for battle mechanics | |
| ## Layer 1: Move Constants (`include/constants/moves.h`) | |
| Each move gets a unique constant identifier: | |
| ```c | |
| #define MOVE_NONE 0 | |
| #define MOVE_POUND 1 | |
| #define MOVE_KARATE_CHOP 2 | |
| #define MOVE_DOUBLE_SLAP 3 | |
| // ... continues for all moves | |
| ``` | |
| **Key Benefits:** | |
| - Type-safe move references throughout codebase | |
| - Easy to add new moves without conflicts | |
| - Clear naming convention | |
| ## Layer 2: Move Data Structure (`src/data/battle_moves.h`) | |
| Each move is defined using the `BattleMove` struct: | |
| ```c | |
| [MOVE_POUND] = { | |
| .effect = EFFECT_HIT, // What the move does | |
| .power = 40, // Base damage | |
| .type = TYPE_NORMAL, // Move type (Normal, Fire, etc.) | |
| .accuracy = 100, // Hit chance (0-100) | |
| .pp = 35, // Power Points (usage count) | |
| .secondaryEffectChance = 0, // Chance of secondary effect | |
| .target = MOVE_TARGET_SELECTED, // Who can be targeted | |
| .priority = 0, // Move speed priority | |
| .flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_KINGS_ROCK_AFFECTED, | |
| }, | |
| ``` | |
| **Key Features:** | |
| - **Separation of Concerns**: Stats vs. behavior logic | |
| - **Flag System**: Modular properties (contact, protection, etc.) | |
| - **Secondary Effects**: Built-in chance system for additional effects | |
| - **Targeting System**: Flexible target selection | |
| ## Layer 3: Effect Constants (`include/constants/battle_move_effects.h`) | |
| Effects categorize move behaviors into reusable types: | |
| ```c | |
| #define EFFECT_HIT 0 // Basic damage | |
| #define EFFECT_SLEEP 1 // Status effect | |
| #define EFFECT_POISON_HIT 2 // Damage + poison | |
| #define EFFECT_ABSORB 3 // Drain HP | |
| #define EFFECT_BURN_HIT 4 // Damage + burn | |
| #define EFFECT_MULTI_HIT 29 // Multiple strikes | |
| #define EFFECT_HIGH_CRITICAL 43 // Increased crit chance | |
| // ... 200+ different effects | |
| ``` | |
| **Benefits:** | |
| - **Reusability**: Multiple moves can share the same effect | |
| - **Extensibility**: New effects can be added without changing existing moves | |
| - **Organization**: Related behaviors grouped together | |
| ## Layer 4: Battle Scripts (`data/battle_scripts_1.s`) | |
| Each effect maps to a battle script that defines the actual implementation: | |
| ```assembly | |
| gBattleScriptsForMoveEffects:: | |
| .4byte BattleScript_EffectHit @ EFFECT_HIT | |
| .4byte BattleScript_EffectSleep @ EFFECT_SLEEP | |
| .4byte BattleScript_EffectPoisonHit @ EFFECT_POISON_HIT | |
| // ... maps all effects to their scripts | |
| ``` | |
| ### Example Battle Scripts: | |
| **Basic Hit:** | |
| ```assembly | |
| BattleScript_EffectHit:: | |
| attackcanceler # Check if attack can proceed | |
| accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE | |
| attackstring # Display move name | |
| ppreduce # Consume PP | |
| critcalc # Calculate critical hits | |
| damagecalc # Calculate damage | |
| typecalc # Apply type effectiveness | |
| adjustnormaldamage # Apply damage modifications | |
| attackanimation # Play visual effects | |
| waitanimation # Wait for animation | |
| effectivenesssound # Play sound effects | |
| # ... continues with damage application | |
| ``` | |
| **Poison Hit (Damage + Status):** | |
| ```assembly | |
| BattleScript_EffectPoisonHit:: | |
| setmoveeffect MOVE_EFFECT_POISON # Set secondary effect | |
| goto BattleScript_EffectHit # Use standard hit logic | |
| ``` | |
| **Multi-Hit:** | |
| ```assembly | |
| BattleScript_EffectMultiHit:: | |
| attackcanceler | |
| accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE | |
| attackstring | |
| ppreduce | |
| setmultihitcounter 0 # Initialize hit counter | |
| initmultihitstring # Setup hit count display | |
| BattleScript_MultiHitLoop:: | |
| jumpifhasnohp BS_ATTACKER, BattleScript_MultiHitEnd | |
| jumpifhasnohp BS_TARGET, BattleScript_MultiHitPrintStrings | |
| # ... hit logic with loop control | |
| ``` | |
| ## Layer 5: Script Commands (`src/battle_script_commands.c`) | |
| Low-level commands that scripts use: | |
| - **Flow Control**: `jumpif*`, `goto`, `call`, `return` | |
| - **Battle Mechanics**: `accuracycheck`, `critcalc`, `damagecalc` | |
| - **Status Effects**: `setmoveeffect`, `seteffectprimary` | |
| - **Animation**: `attackanimation`, `waitanimation` | |
| - **State Management**: `attackcanceler`, `movevaluescleanup` | |
| ## Complex Effect Patterns | |
| ### 1. **Composite Effects** (Hit + Status) | |
| ```c | |
| // Move data specifies base effect | |
| .effect = EFFECT_BURN_HIT, | |
| // Script combines damage with status | |
| BattleScript_EffectBurnHit:: | |
| setmoveeffect MOVE_EFFECT_BURN # Add burn chance | |
| goto BattleScript_EffectHit # Execute standard damage | |
| ``` | |
| ### 2. **Multi-Stage Effects** (Charging moves) | |
| ```c | |
| // Sky Attack: charge turn, then hit | |
| .effect = EFFECT_SKY_ATTACK, | |
| BattleScript_EffectSkyAttack:: | |
| jumpifstatus2 BS_ATTACKER, STATUS2_MULTIPLETURNS, BattleScript_TwoTurnMovesSecondTurn | |
| jumpifword CMP_COMMON_BITS, gHitMarker, HITMARKER_NO_ATTACKSTRING, BattleScript_TwoTurnMovesSecondTurn | |
| # First turn: charge up | |
| # Second turn: attack | |
| ``` | |
| ### 3. **Variable Effects** (Power/behavior changes) | |
| ```c | |
| // Moves that change behavior based on conditions | |
| jumpifnotmove MOVE_SURF, BattleScript_HitFromAtkCanceler | |
| jumpifnostatus3 BS_TARGET, STATUS3_UNDERWATER, BattleScript_HitFromAtkCanceler | |
| orword gHitMarker, HITMARKER_IGNORE_UNDERWATER | |
| setbyte sDMG_MULTIPLIER, 2 # Double damage underwater | |
| ``` | |
| ## Key Design Principles | |
| ### 1. **Separation of Data and Logic** | |
| - Move stats (power, accuracy, PP) separate from behavior logic | |
| - Enables easy balancing without code changes | |
| - Clear data-driven approach | |
| ### 2. **Effect Reusability** | |
| - Many moves share the same effect type | |
| - New moves can reuse existing effects | |
| - Reduces code duplication | |
| ### 3. **Modular Flag System** | |
| ```c | |
| .flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | |
| ``` | |
| - Each flag represents an independent property | |
| - Easy to combine properties | |
| - Consistent interaction rules | |
| ### 4. **Script-Based Flexibility** | |
| - Complex logic implemented in battle scripts | |
| - Scripts can call other scripts (`goto`, `call`) | |
| - Allows for sophisticated move interactions | |
| ### 5. **Centralized Effect Handling** | |
| - All effect implementations in one location | |
| - Easy to debug and maintain | |
| - Consistent patterns across similar effects | |
| ## Implementation Recommendations | |
| For a Pokemon-style battle system: | |
| ### 1. **Start with Core Structure** | |
| ```c | |
| struct Move { | |
| u16 effect; // Links to effect implementation | |
| u8 power; // Base damage | |
| u8 type; // Element type | |
| u8 accuracy; // Hit chance | |
| u8 pp; // Usage count | |
| u8 secondaryChance; // Secondary effect probability | |
| u8 target; // Targeting rules | |
| s8 priority; // Speed priority | |
| u32 flags; // Behavior flags | |
| }; | |
| ``` | |
| ### 2. **Define Effect Categories** | |
| - Start with basic effects (HIT, SLEEP, POISON_HIT, ABSORB) | |
| - Add complex effects as needed | |
| - Group related effects together | |
| ### 3. **Implement Script System** | |
| - Use command-based scripts for flexibility | |
| - Implement basic commands first (damage, accuracy, animation) | |
| - Add advanced commands for complex interactions | |
| ### 4. **Use Flag-Based Properties** | |
| ```c | |
| #define FLAG_CONTACT (1 << 0) | |
| #define FLAG_PROTECTABLE (1 << 1) | |
| #define FLAG_REFLECTABLE (1 << 2) | |
| #define FLAG_KINGS_ROCK (1 << 3) | |
| ``` | |
| ### 5. **Design for Extensibility** | |
| - Keep effect constants sequential for easy addition | |
| - Use lookup tables for effect-to-script mapping | |
| - Design script commands to be composable | |
| ## Special Effects Implementation | |
| ### Status Effects | |
| ```c | |
| // In move data: | |
| .effect = EFFECT_POISON_HIT, | |
| .secondaryEffectChance = 30, | |
| // In script: | |
| setmoveeffect MOVE_EFFECT_POISON // What status to apply | |
| goto BattleScript_EffectHit // How to apply it | |
| ``` | |
| ### Multi-Hit Moves | |
| ```c | |
| // Requires special counter management | |
| setmultihitcounter 0 // Initialize | |
| BattleScript_MultiHitLoop:: // Loop label | |
| // Hit logic here | |
| decrementmultihit // Reduce counter | |
| jumpifnotdone BattleScript_MultiHitLoop // Continue if more hits | |
| ``` | |
| ### Priority System | |
| ```c | |
| // In move data: | |
| .priority = 1, // +1 priority (Quick Attack) | |
| .priority = -6, // -6 priority (Counter) | |
| // Processed during move selection phase | |
| ``` | |
| This architecture allows for clean separation between move definitions, their statistical properties, and their complex behavioral implementations, making it easy to add new moves while maintaining code organization and reusability. |