|
# 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](#status-effects) |
|
2. [Type Effectiveness System](#type-effectiveness-system) |
|
3. [Special Abilities](#special-abilities) |
|
4. [Move Mechanics](#move-mechanics) |
|
5. [Turn Execution Flow](#turn-execution-flow) |
|
6. [Battle State Management](#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` |
|
|
|
```c |
|
#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` |
|
|
|
```c |
|
#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` |
|
|
|
```c |
|
#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: |
|
|
|
```c |
|
[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: |
|
```c |
|
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 |
|
|
|
```c |
|
#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`: |
|
|
|
```c |
|
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`: |
|
|
|
```c |
|
#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**: |
|
```c |
|
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: |
|
|
|
```c |
|
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: |
|
```c |
|
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 |