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:
```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.