piclets / pokemon_emerald_docs /DEFINING_ATTACKS.md
Fraser's picture
Remove problematic public/assets/logo.PNG to fix deployment
50135bd

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:

#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:

[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:

#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:

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:

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):

BattleScript_EffectPoisonHit::
    setmoveeffect MOVE_EFFECT_POISON    # Set secondary effect
    goto BattleScript_EffectHit         # Use standard hit logic

Multi-Hit:

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)

// 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)

// 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)

// 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

.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

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

#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

// 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

// 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

// 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.