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
- Status Effects
- Type Effectiveness System
- Special Abilities
- Move Mechanics
- Turn Execution Flow
- 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
- Base Calculation: In
Cmd_typecalc()
function - Ability Checks: Levitate grants immunity to Ground moves
- Item Effects: Type-enhancing items modify damage
- 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 calculationCheckWonderGuardAndLevitate()
- For ability-specific immunity- Move target validation
Ability Processing Points
Abilities can trigger at:
- Switch-in: Intimidate, Drizzle, Drought, Sand Stream
- Before Move: Truant preventing action
- Damage Calculation: Thick Fat, Filter, Solid Rock
- After Damage: Rough Skin, Iron Barbs, Aftermath
- Status Application: Immunity preventing poison
- 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
Success Rate Calculation:
- First use: 100% success
- Consecutive uses: Success rate halves each time
- Stored in
sProtectSuccessRates[]
array
Protection State:
gProtectStructs[battler].protected = 1; // For Protect/Detect gProtectStructs[battler].endured = 1; // For Endure
Move Blocking:
- Checked in
Cmd_attackcanceler()
viaDEFENDER_IS_PROTECTED
macro - Only moves with
FLAG_PROTECT_AFFECTED
are blocked - Some moves bypass Protect (Feint, Shadow Force, etc.)
- Checked in
Multi-Target Move Mechanics
Target selection types:
MOVE_TARGET_SELECTED
: Single target chosen by playerMOVE_TARGET_BOTH
: Hits both opponents in double battlesMOVE_TARGET_FOES_AND_ALLY
: Hits all Pokémon except userMOVE_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:
- Pursuit (if target is switching)
- Switching Pokémon
- Using Items
- Quick Claw activation (20% chance to go first)
- Move Priority (-7 to +5, higher goes first)
- Speed Stat (higher goes first, with Speed ties being random)
Arrays populated:
gActionsByTurnOrder[]
- What action each slot will performgBattlerByTurnOrder[]
- 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:
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
Accuracy Check (
Cmd_accuracycheck
)- Base accuracy calculation
- Accuracy/Evasion stat stages
- Ability modifications (Compound Eyes, Sand Veil)
- Weather effects (Thunder in rain)
Attack String (
Cmd_attackstring
)- Display "[Pokémon] used [Move]!"
PP Reduction (
Cmd_ppreduce
)- Deduct PP from move (affected by Pressure)
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
Damage Calculation (
Cmd_damagecalc
)Damage = ((2 × Level / 5 + 2) × Power × Attack / Defense / 50 + 2) × STAB × Type × Random(85-100)/100
Type Effectiveness (
Cmd_typecalc
)- Apply type chart multipliers
- Check abilities (Levitate, Wonder Guard)
- Display effectiveness messages
Attack Animation (
Cmd_attackanimation
)- Play move animation and sound effects
HP Update (
Cmd_healthbarupdate
)- Animate HP bar decrease
- Apply Substitute damage if applicable
Result Messages (
Cmd_resultmessage
)- "It's super effective!"
- "It's not very effective..."
- Critical hit notification
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:
- Future Sight/Doom Desire damage
- Wish healing
- Weather damage (Sandstorm, Hail)
- Status damage (Burn, Poison, Toxic)
- Leech Seed HP drain
- Nightmare damage
- Curse damage
- Wrap/Bind damage
- Uproar wake-up and prevention
- Perish Song counter
- Reflect/Light Screen duration
- Safeguard/Mist duration
- Trick Room duration (Gen 4+ feature)
- Gravity duration (Gen 4+ feature)
- Item effects (Leftovers, Black Sludge)
- 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 battleTryDoEventsBeforeFirstTurn
- Entry hazards, weatherHandleTurnActionSelectionState
- Action selectionSetActionsAndBattlersTurnOrder
- Sort actionsRunTurnActionsFunctions
- Execute turnHandleEndTurn_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