File size: 9,334 Bytes
50135bd |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 |
# 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. |