summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Add-a-new-move-effect.md201
-rw-r--r--Tutorials.md1
-rw-r--r--screenshots/effect-hex.pngbin0 -> 3797 bytes
3 files changed, 202 insertions, 0 deletions
diff --git a/Add-a-new-move-effect.md b/Add-a-new-move-effect.md
new file mode 100644
index 0000000..5b813e7
--- /dev/null
+++ b/Add-a-new-move-effect.md
@@ -0,0 +1,201 @@
+This tutorial is for how to add a new move effect. As an example, we'll add Hex.
+
+
+## Contents
+
+1. [Prepare the move itself](#1-prepare-the-move-itself)
+2. [Define an effect constant](#2-define-an-effect-constant)
+3. [Update the effect pointer table](#3-update-the-effect-pointer-table)
+4. [Write the effect script](#4-write-the-effect-script)
+5. [Define any new battle commands](#5-define-any-new-battle-commands)
+6. [Teach the AI to use the effect well](#6-teach-the-ai-to-use-the-effect-well)
+
+
+## 1. Prepare the move itself
+
+Hex is an attack from Gen 5 that doubles in power if the target has a status condition. No effect like that existed in Gen 2, so we're going to add one; but first, we have to add the move Hex, following [this tutorial](Add-a-new-move).
+
+Replace `MOVE_OR_ANIM_FC` with `HEX`; give it a name, description, and battle properties (`HEX, EFFECT_HEX, 65, GHOST, 100, 10, 0`); give it an animation (it can share `BattleAnim_Spite`); and add it to Pokémon learnsets (Vulpix, Tentacool/Tentacruel, Gastly/Haunter/Gengar, and Misdreavus by level-up; Vulpix and Dunsparce by breeding).
+
+
+## 2. Define an effect constant
+
+`EFFECT_HEX` has not been defined yet, so we'll do that next. Edit [constants/move_effect_constants.asm](../blob/master/constants/move_effect_constants.asm):
+
+```diff
+ ; MoveEffectsPointers indexes (see data/moves/effects_pointers.asm)
+ const_def
+ const EFFECT_NORMAL_HIT
+ ...
+ const EFFECT_DEFENSE_CURL
++ const EFFECT_HEX
+```
+
+If you want to be save space, there are six `UNUSED` effects you can replace, instead of adding `EFFECT_HEX` to the end of the list.
+
+
+## 3. Update the effect pointer table
+
+Edit [data/moves/effects_pointers.asm](../blob/master/data/moves/effects_pointers.asm):
+
+```diff
+ MoveEffectsPointers: ; 271f4
+ ; entries correspond to EFFECT_* constants
+ dw NormalHit
+ ...
+ dw DefenseCurl
++ dw Hex
+```
+
+
+## 4. Write the effect script
+
+Edit [data/moves/effects.asm](../blob/master/data/moves/effects.asm):
+
+```diff
++Hex:
++ checkobedience
++ usedmovetext
++ doturn
++ critical
++ damagestats
++ damagecalc
++ stab
++ damagevariation
++ hex
++ checkhit
++ moveanim
++ failuretext
++ applydamage
++ criticaltext
++ supereffectivetext
++ checkdestinybond
++ buildopponentrage
++ kingsrock
++ endmove
+```
+
+Move effects are written in their own scripting language; see [docs/move_effect_commands.md](../blob/master/docs/move_effect_commands.md) for a list of the usable commands.
+
+If you're writing a custom effect, it's helpful to start with an existing one and modify it as needed. Here I took the `NormalHit` effect and added a `hex` command to double the damage if the target has a status condition. (No such command exists yet, so we'll have to add that next, but many new effects can be written just with the predefined commands.)
+
+
+## 5. Define any new battle commands
+
+The `Hex` move effect script needs a new `hex` battle command, so let's define that next. It's similar to the process of adding every other new thing: define `hex` as a constant, give it an entry in a pointer table, and define the thing it's pointing to.
+
+Edit [macros/scripts/battle_commands.asm](../blob/master/macros/scripts/battle_commands.asm):
+
+```diff
+ ; BattleCommandPointers indexes (see data/battle/effect_command_pointers.asm)
+ enum_start 1
+ command checkturn ; 01
+ ...
+ command curl ; af
++ command hex ; b0
+```
+
+You can replace `effect0x3c` or `effect0x5d` before adding to the end of the list, if you're like me and don't want to leave unused code lying around. ;)
+
+Anyway, edit [data/battle/effect_command_pointers.asm](../blob/master/data/battle/effect_command_pointers.asm):
+
+```diff
+ BattleCommandPointers: ; 3fd28
+ ; entries correspond to macros/scripts/battle_commands.asm
+ dw BattleCommand_CheckTurn ; 34084
+ ...
+ dw BattleCommand_Curl ; 365a7
++ dw BattleCommand_Hex
+ ; 3fe86
+```
+
+Create **engine/battle/move_effects/hex.asm**:
+
+```diff
++BattleCommand_Hex:
++; hex
++; get the opponent's status condition
++ ld a, BATTLE_VARS_STATUS_OPP
++ call GetBattleVar
++; return if it's 0 (no condition)
++ and a
++ ret z
++; it's not 0, so double damage
++ jp DoubleDamage
+```
+
+And edit [engine/battle/effect_commands.asm](../blob/master/engine/battle/effect_commands.asm):
+
+```diff
+ INCLUDE "engine/battle/move_effects/rage.asm"
++
++INCLUDE "engine/battle/move_effects/hex.asm"
+
+ BattleCommand_DoubleFlyingDamage: ; 36f25
+ ; doubleflyingdamage
+ ld a, BATTLE_VARS_SUBSTATUS3_OPP
+ call GetBattleVar
+ bit SUBSTATUS_FLYING, a
+ ret z
+ jr DoubleDamage
+```
+
+(We could have just written the `BattleCommand_Hex` code right in engine/battle/effect_commands.asm, but it's more organized to follow pokecrystal's convention of putting individual moves' unique commands in their own files.)
+
+Notice how similar `BattleCommand_Hex` is to `BattleCommand_DoubleFlyingDamage` right below it. Whether you're writing data tables, scripts, or assembly code, you don't have to start from scratch; you can find something close to what you want and modify it.
+
+
+## 6. Teach the AI to use the effect well
+
+This step is optional, but if you feel capable of writing new code, it's nice to have the enemy AI use new moves in appropriate situations.
+
+First, look at the tables of moves and effects in [data/battle/ai](../tree/master/data/battle/ai/). They all have comments at the top explaining what they're for, like "`AI_CAUTIOUS` discourages these moves after the first turn." Consider whether your new move effect should be added to any of these tables. There's nowhere we need to add `HEX` or `EFFECT_HEX`, though.
+
+Next, we'll teach `AI_SMART` to take advantage of `EFFECT_HEX` when the player has a status condition. Edit [engine/battle/ai/scoring.asm](../blob/master/engine/battle/ai/scoring.asm):
+
+```diff
+ AI_Smart: ; 386be
+ ; Context-specific scoring.
+
+ ...
+
+ .table_386f2
+ dbw EFFECT_SLEEP, AI_Smart_Sleep
+ ...
+ dbw EFFECT_FLY, AI_Smart_Fly
++ dbw EFFECT_HEX, AI_Smart_Hex
+ db -1 ; end
+ ; 387e3
+
+ ...
+
+ AI_Smart_DefrostOpponent: ; 38ccb
+ ; Greatly encourage this move if enemy is frozen.
+ ; No move has EFFECT_DEFROST_OPPONENT, so this layer is unused.
+
+ ld a, [wEnemyMonStatus]
+ and 1 << FRZ
+ ret z
+ dec [hl]
+ dec [hl]
+ dec [hl]
+ ret
+ ; 38cd5
++
++AI_Smart_Hex:
++; Greatly encourage this move if the player has a status condition.
++
++ ld a, [wBattleMonStatus]
++ and a
++ ret z
++ dec [hl]
++ dec [hl]
++ dec [hl]
++ ret
+```
+
+Pretty self-explanatory. Find the right table, add an entry for `EFFECT_HEX`, and base the new AI routine on a pre-existing one.
+
+That's all!
+
+![Screenshot](screenshots/effect-hex.png)
diff --git a/Tutorials.md b/Tutorials.md
index 010eecd..306de17 100644
--- a/Tutorials.md
+++ b/Tutorials.md
@@ -14,6 +14,7 @@ Tutorials may use diff syntax to show edits:
- [Trainer class](Add-a-new-trainer-class)
- [Type (Fairy)](Add-a-new-Fairy-type)
- [Move (up to 254)](Add-a-new-move)
+- [Move effect](Add-a-new-move-effect)
- [Item (up to 254)](Add-different-kinds-of-new-items)
- [TM (up to 120)](Add-a-new-TM)
- [Music song](Add-a-new-music-song)
diff --git a/screenshots/effect-hex.png b/screenshots/effect-hex.png
new file mode 100644
index 0000000..8635109
--- /dev/null
+++ b/screenshots/effect-hex.png
Binary files differ