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

Pokémon Emerald Battle System Mechanics

This document provides an in-depth technical reference for the underlying mechanics of the Pokémon Emerald battle system, including status effects, abilities, move mechanics, and turn execution flow.

Table of Contents

  1. Status Effects
  2. Type Effectiveness System
  3. Special Abilities
  4. Move Mechanics
  5. Turn Execution Flow
  6. Battle State Management

Status Effects

Overview

Status effects in Pokémon Emerald are divided into three categories, each stored in separate bit fields within the BattlePokemon structure:

  • STATUS1: Non-volatile status conditions that persist outside of battle
  • STATUS2: Volatile status conditions that are removed when switching
  • STATUS3: Additional volatile effects and special states

Non-Volatile Status (STATUS1)

Defined in include/constants/battle.h:114-125

#define STATUS1_SLEEP            (1 << 0 | 1 << 1 | 1 << 2)  // 3 bits for turn count
#define STATUS1_POISON           (1 << 3)
#define STATUS1_BURN             (1 << 4)
#define STATUS1_FREEZE           (1 << 5)
#define STATUS1_PARALYSIS        (1 << 6)
#define STATUS1_TOXIC_POISON     (1 << 7)
#define STATUS1_TOXIC_COUNTER    (1 << 8 | 1 << 9 | 1 << 10 | 1 << 11)  // 4 bits for toxic counter

Sleep

  • Duration: 2-5 turns (stored in first 3 bits)
  • Effect: Prevents most actions except Snore and Sleep Talk
  • Wake-up: Checked at the start of the turn before action

Poison

  • Damage: 1/8 of max HP at end of turn
  • Field Effect: Takes damage every 4 steps in overworld

Burn

  • Damage: 1/8 of max HP at end of turn
  • Attack Reduction: Physical attack reduced to 50%
  • Immunity: Fire-type Pokémon cannot be burned

Freeze

  • Thaw Chance: 20% at the start of each turn
  • Instant Thaw: Fire-type moves, Scald, or being hit by a Fire move
  • Immunity: Ice-type Pokémon cannot be frozen

Paralysis

  • Speed Reduction: Speed reduced to 25% of normal
  • Full Paralysis: 25% chance to be unable to move
  • Immunity: Electric-type Pokémon cannot be paralyzed

Toxic Poison

  • Progressive Damage: 1/16 HP on turn 1, 2/16 on turn 2, etc.
  • Counter Storage: Uses bits 8-11 to track damage progression

Volatile Status (STATUS2)

Defined in include/constants/battle.h:129-155

#define STATUS2_CONFUSION        (1 << 0 | 1 << 1 | 1 << 2)  // 3 bits for turn count
#define STATUS2_FLINCHED         (1 << 3)
#define STATUS2_UPROAR           (1 << 4 | 1 << 5 | 1 << 6)  // 3 bits for turn count
#define STATUS2_BIDE             (1 << 8 | 1 << 9)           // 2 bits for turn count
#define STATUS2_LOCK_CONFUSE     (1 << 10 | 1 << 11)        // Thrash/Outrage confusion
#define STATUS2_MULTIPLETURNS    (1 << 12)
#define STATUS2_WRAPPED          (1 << 13 | 1 << 14 | 1 << 15)  // 3 bits for turn count
#define STATUS2_INFATUATION      (1 << 16 | 1 << 17 | 1 << 18 | 1 << 19)  // 4 bits, one per battler
#define STATUS2_FOCUS_ENERGY     (1 << 20)
#define STATUS2_TRANSFORMED      (1 << 21)
#define STATUS2_RECHARGE         (1 << 22)
#define STATUS2_RAGE             (1 << 23)
#define STATUS2_SUBSTITUTE       (1 << 24)
#define STATUS2_DESTINY_BOND     (1 << 25)
#define STATUS2_ESCAPE_PREVENTION (1 << 26)
#define STATUS2_NIGHTMARE        (1 << 27)
#define STATUS2_CURSED           (1 << 28)
#define STATUS2_FORESIGHT        (1 << 29)
#define STATUS2_DEFENSE_CURL     (1 << 30)
#define STATUS2_TORMENT          (1 << 31)

Key Volatile Effects

Confusion

  • Duration: 2-5 turns
  • Effect: 50% chance to hit self with 40 power typeless physical attack
  • Self-damage Calculation: Uses attack stat against defense stat

Substitute

  • HP Cost: 25% of max HP to create
  • Effect: Blocks most status moves and damage
  • Breaking: Substitute breaks when its HP reaches 0

Infatuation

  • Effect: 50% chance to be immobilized by love
  • Requirement: Opposite gender (or same gender with certain abilities)
  • Storage: Uses 4 bits to track which battler caused infatuation

Additional Status (STATUS3)

Defined in include/constants/battle.h:158-178

#define STATUS3_LEECHSEED        (1 << 2)
#define STATUS3_ALWAYS_HITS      (1 << 3 | 1 << 4)  // Lock-On/Mind Reader
#define STATUS3_PERISH_SONG      (1 << 5)
#define STATUS3_ON_AIR           (1 << 6)            // Fly/Bounce
#define STATUS3_UNDERGROUND      (1 << 7)            // Dig
#define STATUS3_MINIMIZED        (1 << 8)
#define STATUS3_CHARGED_UP       (1 << 9)            // Charge
#define STATUS3_ROOTED           (1 << 10)           // Ingrain
#define STATUS3_YAWN             (1 << 11 | 1 << 12) // Turn counter
#define STATUS3_IMPRISONED_OTHERS (1 << 13)
#define STATUS3_GRUDGE           (1 << 14)
#define STATUS3_UNDERWATER       (1 << 18)           // Dive
#define STATUS3_SEMI_INVULNERABLE (STATUS3_UNDERGROUND | STATUS3_ON_AIR | STATUS3_UNDERWATER)

Type Effectiveness System

Type Chart Implementation

Type effectiveness is stored in gTypeEffectiveness[] array in src/battle_main.c. The format is:

[Attacking Type, Defending Type, Multiplier, ...]

Multiplier values:

  • TYPE_MUL_NO_EFFECT (0): No damage (0x multiplier)
  • TYPE_MUL_NOT_EFFECTIVE (5): Not very effective (0.5x multiplier)
  • TYPE_MUL_NORMAL (10): Normal damage (1x multiplier)
  • TYPE_MUL_SUPER_EFFECTIVE (20): Super effective (2x multiplier)

Ground vs Flying Interaction

The type chart includes:

TYPE_GROUND, TYPE_FLYING, TYPE_MUL_NO_EFFECT

This is why Earthquake and other Ground-type moves don't affect Flying-type Pokémon - they receive a 0x damage multiplier.

Type Calculation Process

  1. Base Calculation: In Cmd_typecalc() function
  2. Ability Checks: Levitate grants immunity to Ground moves
  3. Item Effects: Type-enhancing items modify damage
  4. STAB Calculation: Same Type Attack Bonus (1.5x) if move type matches user type

Special Abilities

Ability System Overview

Abilities are passive effects that can trigger at various points during battle. They are defined in include/constants/abilities.h and processed by AbilityBattleEffects() in src/battle_util.c.

Key Ability: Levitate

#define ABILITY_LEVITATE 26

Effect: Grants immunity to Ground-type moves Implementation: Checked in multiple locations:

  • Cmd_typecalc() - During damage calculation
  • CheckWonderGuardAndLevitate() - For ability-specific immunity
  • Move target validation

Ability Processing Points

Abilities can trigger at:

  1. Switch-in: Intimidate, Drizzle, Drought, Sand Stream
  2. Before Move: Truant preventing action
  3. Damage Calculation: Thick Fat, Filter, Solid Rock
  4. After Damage: Rough Skin, Iron Barbs, Aftermath
  5. Status Application: Immunity preventing poison
  6. End of Turn: Speed Boost, Poison Heal

Move Mechanics

Move Data Structure

From include/pokemon.h:327-338:

struct BattleMove
{
    u8 effect;          // Move effect ID
    u8 power;           // Base power
    u8 type;            // Move type
    u8 accuracy;        // Accuracy (0-100)
    u8 pp;              // Base PP
    u8 secondaryEffectChance;  // % chance for secondary effect
    u8 target;          // Target selection
    s8 priority;        // Priority bracket (-7 to +5)
    u8 flags;           // Move properties flags
};

Move Flags

From include/constants/pokemon.h:208-213:

#define FLAG_MAKES_CONTACT       (1 << 0)  // Triggers contact abilities
#define FLAG_PROTECT_AFFECTED    (1 << 1)  // Blocked by Protect/Detect
#define FLAG_MAGIC_COAT_AFFECTED (1 << 2)  // Reflected by Magic Coat
#define FLAG_SNATCH_AFFECTED     (1 << 3)  // Stolen by Snatch
#define FLAG_MIRROR_MOVE_AFFECTED (1 << 4) // Copyable by Mirror Move
#define FLAG_KINGS_ROCK_AFFECTED (1 << 5)  // Can cause flinch with King's Rock

Protect/Detect Mechanics

Implementation: Cmd_setprotectlike() in src/battle_script_commands.c

  1. Success Rate Calculation:

    • First use: 100% success
    • Consecutive uses: Success rate halves each time
    • Stored in sProtectSuccessRates[] array
  2. Protection State:

    gProtectStructs[battler].protected = 1;  // For Protect/Detect
    gProtectStructs[battler].endured = 1;    // For Endure
    
  3. Move Blocking:

    • Checked in Cmd_attackcanceler() via DEFENDER_IS_PROTECTED macro
    • Only moves with FLAG_PROTECT_AFFECTED are blocked
    • Some moves bypass Protect (Feint, Shadow Force, etc.)

Multi-Target Move Mechanics

Target selection types:

  • MOVE_TARGET_SELECTED: Single target chosen by player
  • MOVE_TARGET_BOTH: Hits both opponents in double battles
  • MOVE_TARGET_FOES_AND_ALLY: Hits all Pokémon except user
  • MOVE_TARGET_ALL_BATTLERS: Hits all Pokémon including user

Damage reduction in multi-battles:

  • Moves hitting multiple targets deal 75% damage to each

Turn Execution Flow

Complete Turn Sequence

The battle system executes turns through a series of carefully ordered phases:

1. Action Selection Phase

Function: HandleTurnActionSelectionState()

  • Players and AI select actions (Fight/Pokémon/Bag/Run)
  • Move and target selection for Fight actions
  • All selections stored in gChosenActionByBattler[]

2. Turn Order Determination

Function: SetActionsAndBattlersTurnOrder()

Order priority:

  1. Pursuit (if target is switching)
  2. Switching Pokémon
  3. Using Items
  4. Quick Claw activation (20% chance to go first)
  5. Move Priority (-7 to +5, higher goes first)
  6. Speed Stat (higher goes first, with Speed ties being random)

Arrays populated:

  • gActionsByTurnOrder[] - What action each slot will perform
  • gBattlerByTurnOrder[] - Which battler occupies each slot

3. Pre-Turn Checks

Function: CheckFocusPunch_ClearVarsBeforeTurnStarts()

  • Focus Punch charging message
  • Clear temporary battle variables
  • Initialize turn counters

4. Action Execution

Function: RunTurnActionsFunctions()

For each action in turn order:

Move Execution Pipeline

When B_ACTION_USE_MOVE is processed:

  1. Attack Canceler (Cmd_attackcanceler)

    • Sleep check (can only use Snore/Sleep Talk)
    • Freeze check (20% thaw chance)
    • Paralysis check (25% full paralysis)
    • Confusion check (50% self-hit)
    • Flinch check
    • Disable/Taunt/Imprison checks
    • Protect check (for protected targets)
    • Pressure PP deduction
  2. Accuracy Check (Cmd_accuracycheck)

    • Base accuracy calculation
    • Accuracy/Evasion stat stages
    • Ability modifications (Compound Eyes, Sand Veil)
    • Weather effects (Thunder in rain)
  3. Attack String (Cmd_attackstring)

    • Display "[Pokémon] used [Move]!"
  4. PP Reduction (Cmd_ppreduce)

    • Deduct PP from move (affected by Pressure)
  5. Critical Hit Calculation (Cmd_critcalc)

    • Base 1/16 chance (6.25%)
    • Increased by Focus Energy, high crit moves, items
    • Cannot crit if target has Battle Armor/Shell Armor
  6. Damage Calculation (Cmd_damagecalc)

    Damage = ((2 × Level / 5 + 2) × Power × Attack / Defense / 50 + 2)
             × STAB × Type × Random(85-100)/100
    
  7. Type Effectiveness (Cmd_typecalc)

    • Apply type chart multipliers
    • Check abilities (Levitate, Wonder Guard)
    • Display effectiveness messages
  8. Attack Animation (Cmd_attackanimation)

    • Play move animation and sound effects
  9. HP Update (Cmd_healthbarupdate)

    • Animate HP bar decrease
    • Apply Substitute damage if applicable
  10. Result Messages (Cmd_resultmessage)

    • "It's super effective!"
    • "It's not very effective..."
    • Critical hit notification
  11. Secondary Effects (Cmd_moveend)

    • Status conditions
    • Stat changes
    • Additional effects
Other Action Types

B_ACTION_SWITCH:

  • Pursuit check and execution
  • Return Pokémon
  • Send out new Pokémon
  • Entry hazard damage
  • Switch-in abilities

B_ACTION_USE_ITEM:

  • Item effect application
  • Item consumption
  • Bag pocket update

B_ACTION_RUN:

  • Escape attempt calculation
  • Battle end if successful

5. End of Turn Phase

Function: HandleEndTurn_BattleTerrain()

Processes in order:

  1. Future Sight/Doom Desire damage
  2. Wish healing
  3. Weather damage (Sandstorm, Hail)
  4. Status damage (Burn, Poison, Toxic)
  5. Leech Seed HP drain
  6. Nightmare damage
  7. Curse damage
  8. Wrap/Bind damage
  9. Uproar wake-up and prevention
  10. Perish Song counter
  11. Reflect/Light Screen duration
  12. Safeguard/Mist duration
  13. Trick Room duration (Gen 4+ feature)
  14. Gravity duration (Gen 4+ feature)
  15. Item effects (Leftovers, Black Sludge)
  16. Ability effects (Speed Boost, Moody)

6. Faint Handling

Function: HandleFaintedMonActions()

  • Check for fainted Pokémon
  • Experience gain calculation
  • EVs distribution
  • Display faint messages
  • Force switches if needed

7. Turn Wrap-up

  • Increment turn counter
  • Check win/loss conditions
  • Return to Action Selection or end battle

Battle State Machine

The entire battle flow is controlled by function pointers:

void (*gBattleMainFunc)(void);  // Main battle state

Key states:

  • HandleNewBattleRamData - Initialize battle
  • TryDoEventsBeforeFirstTurn - Entry hazards, weather
  • HandleTurnActionSelectionState - Action selection
  • SetActionsAndBattlersTurnOrder - Sort actions
  • RunTurnActionsFunctions - Execute turn
  • HandleEndTurn_FinishBattle - Battle cleanup

Battle State Management

Core Data Structures

BattlePokemon - Active Pokémon data:

struct BattlePokemon {
    u16 species;
    u16 attack, defense, speed, spAttack, spDefense;
    u16 moves[MAX_MON_MOVES];
    u32 hp, maxHP;
    u32 status1;  // Non-volatile status
    u32 status2;  // Volatile status
    u32 status3;  // Additional effects
    u8 ability;
    u8 type1, type2;
    // ... more fields
};

BattleStruct - Global battle state:

  • Turn counters and trackers
  • Move history
  • Field effects
  • Battle mode flags
  • AI data

Memory Layout

Battle data is organized into:

  • EWRAM: Fast access for frequently used data
  • Battle Resources: Dynamically allocated at battle start
  • Sprite Data: Separate allocation for graphics

Save State Integration

During battle:

  • Party Pokémon are copied to battle structures
  • Changes applied to battle copies only
  • On battle end, sync back to party (HP, PP, status, etc.)

This architecture ensures battle calculations don't corrupt party data and allows for move preview without committing changes.

Summary

The Pokémon Emerald battle system is a sophisticated state machine that processes turns through clearly defined phases. Its modular architecture separates concerns between controllers (input), scripts (logic), animations (presentation), and data management. The extensive use of bit flags for status conditions and move properties allows for complex interactions while maintaining performance on GBA hardware.

Key design principles:

  • Deterministic: Same inputs produce same results (except RNG)
  • Modular: Each phase has clear responsibilities
  • Extensible: New effects can be added via scripts
  • Efficient: Bit manipulation and careful memory management
  • Faithful: Accurately replicates original game mechanics