summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Puddles-that-splash-when-you-walk.md4
-rw-r--r--Rock-Climb.md405
-rw-r--r--Tutorials.md5
-rw-r--r--screenshots/polished-map-rock-climb.pngbin0 -> 29626 bytes
-rw-r--r--screenshots/rock-climb.pngbin0 -> 6544 bytes
5 files changed, 409 insertions, 5 deletions
diff --git a/Puddles-that-splash-when-you-walk.md b/Puddles-that-splash-when-you-walk.md
index 9bc5d6c..ce09fea 100644
--- a/Puddles-that-splash-when-you-walk.md
+++ b/Puddles-that-splash-when-you-walk.md
@@ -28,7 +28,7 @@ Edit [constants/collision_constants.asm](../blob/master/constants/collision_cons
...
```
-Edit [data/collision_permissions.asm](../blob/master/data/collision_permissions.asm):
+And edit [data/collision_permissions.asm](../blob/master/data/collision_permissions.asm):
```diff
TileCollisionTable::
@@ -68,7 +68,7 @@ Edit [audio/sfx_pointers.asm](../blob/master/audio/sfx_pointers.asm):
+ dba Sfx_Puddle
```
-Edit [audio/sfx_crystal.asm](../blob/master/audio/sfx_crystal.asm):
+And edit [audio/sfx_crystal.asm](../blob/master/audio/sfx_crystal.asm):
```diff
+Sfx_Puddle:
diff --git a/Rock-Climb.md b/Rock-Climb.md
new file mode 100644
index 0000000..f42d82b
--- /dev/null
+++ b/Rock-Climb.md
@@ -0,0 +1,405 @@
+Gen 4 introduced Rock Climb, a field move that can scale rocky walls, as HM08. Its in-battle effect, to deal damage with a chance of confusion, already exists (for Psybeam); and its field effect is not too complex to implement.
+
+
+## Contents
+
+1. [Prepare the Rock Climb move](#1-prepare-the-rock-climb-move)
+2. [Prepare the HM08 item](#2-prepare-the-hm08-item)
+3. [Define a collision type for rocky walls](#3-define-a-collision-type-for-rocky-walls)
+4. [Start to prepare the Rock Climb field move effect](#4-start-to-prepare-the-rock-climb-field-move-effect)
+5. [Define a utility function to check for rocky walls](#5-define-a-utility-function-to-check-for-rocky-walls)
+6. [Define text related to using Rock Climb](#6-define-text-related-to-using-rock-climb)
+7. [Finish the Rock Climb field move effect](#7-finish-the-rock-climb-field-move-effect)
+8. [Talk to rocky walls to use Rock Climb](#8-talk-to-rocky-walls-to-use-rock-climb)
+9. [Explain when Rock Climb is enabled](#9-explain-when-rock-climb-is-enabled)
+10. [Add rocky walls to a map](#10-add-rocky-walls-to-a-map)
+
+
+## 1. Prepare the Rock Climb move
+
+We're going to add a field effect for climbing rocky walls; but first, we have to add the move Rock Climb, following [this tutorial](Add-a-new-move).
+
+Replace `MOVE_OR_ANIM_FC` with `ROCK_CLIMB`; give it a name, description, and battle properties (`ROCK_CLIMB, EFFECT_CONFUSE_HIT, 90, NORMAL, 85, 20, 20`); give it an animation (it can share `BattleAnim_Waterfall`); and add it to Pokémon learnsets (Sandshrew, Geodude, Onix, Rhyhorn, and Gligar learn it as an Egg move).
+
+
+## 2. Prepare the HM08 item
+
+We also have to add the item HM08, following [this tutorial](Add-a-new-TM-or-HM).
+
+Add an HM for `ROCK_CLIMB`; give it a name and attributes (`0, HELD_NONE, 0, CANT_SELECT | CANT_TOSS, TM_HM, ITEMMENU_PARTY, ITEMMENU_NOUSE`); associate it with the move `ROCK_CLIMB`; make it unforgettable; and add it to Pokémon base learnsets (48 Pokémon are compatible with it, including all three fully-evolved Johto starters).
+
+
+## 3. Define a collision type for rocky walls
+
+Edit [constants/collision_constants.asm](../blob/master/constants/collision_constants.asm):
+
+```diff
+ ; collision data types (see data/tilesets/*_collision.asm)
+ ; TileCollisionTable indexes (see data/collision_permissions.asm)
+ COLL_FLOOR EQU $00
+ COLL_01 EQU $01 ; garbage
+ COLL_03 EQU $03 ; garbage
+ COLL_04 EQU $04 ; garbage
++COLL_ROCKY_WALL EQU $06
+ COLL_WALL EQU $07
+ ...
+```
+
+And edit [data/collision_permissions.asm](../blob/master/data/collision_permissions.asm):
+
+```diff
+ TileCollisionTable::
+ ; entries correspond to COLL_* constants
+ NONTALKABLE LANDTILE ; COLL_FLOOR
+ NONTALKABLE LANDTILE ; COLL_01
+ NONTALKABLE LANDTILE ; 02
+ NONTALKABLE LANDTILE ; COLL_03
+ NONTALKABLE LANDTILE ; COLL_04
+ NONTALKABLE LANDTILE ; 05
+- NONTALKABLE LANDTILE ; 06
++ TALKABLE WALLTILE ; COLL_ROCKY_WALL
+ NONTALKABLE WALLTILE ; COLL_WALL
+ ...
+```
+
+Rocky walls will prompt to use Rock Climb when talked to, so they need to be `TALKABLE`.
+
+
+## 4. Start to prepare the Rock Climb field move effect
+
+Now we can start to add the field move effect, following [this tutorial](Add-a-new-field-move-effect).
+
+Define `MONMENUITEM_ROCKCLIMB`; associate it with the move `ROCK_CLIMB`; and implement `MonMenu_RockClimb` for its menu action (in [engine/menus/start_menu.asm](../blob/master/engine/menus/start_menu.asm)) like this:
+
+```diff
++MonMenu_RockClimb:
++ farcall RockClimbFunction
++ ld a, [wFieldMoveSucceeded]
++ cp $1
++ jr nz, .Fail
++ ld b, $4
++ ld a, $2
++ ret
++
++.Fail:
++ ld a, $3
++ ret
+```
+
+We still have to implement `RockClimbFunction`; but first, let's define some more components for it.
+
+
+## 5. Define a utility function to check for rocky walls
+
+Edit [home/map_objects.asm](../blob/master/home/map_objects.asm):
+
+```diff
+ CheckHeadbuttTreeTile::
+ cp COLL_HEADBUTT_TREE
+ ret z
+ cp COLL_HEADBUTT_TREE_1D
+ ret
++
++CheckRockyWallTile::
++ cp COLL_ROCKY_WALL
++ ret
+```
+
+This isn't strictly necessary—we could just directly use `cp COLL_ROCKY_WALL` instead of `call CheckRockyWallTile`—but it's how the other field moves work. And this approach is easier to extend, if for some reason more than one collision type should act like a rocky wall.
+
+
+## 6. Define text related to using Rock Climb
+
+Edit [data/text/common_2.asm](../blob/master/data/text/common_2.asm):
+
+```diff
++_AskRockClimbText::
++ text "The wall is very"
++ line "rocky…"
++
++ para "Want to use"
++ line "ROCK CLIMB?"
++ done
++
++_UsedRockClimbText::
++ text_from_ram wStringBuffer2
++ text " used"
++ line "ROCK CLIMB!"
++ prompt
++
++_CantRockClimbText::
++ text "The wall is very"
++ line "rocky…"
++
++ para "Will a #MON's"
++ line "move scale it?"
++ done
+```
+
+This could have gone in [common_1.asm](../blob/master/data/text/common_1.asm) or [common_3.asm](../blob/master/data/text/common_3.asm) instead, but [common_2.asm](../blob/master/data/text/common_2.asm) has text related to other HM moves already.
+
+We'll need this text, and the previous `CheckRockyWallTile` routine, when we define `RockClimbFunction` next.
+
+
+## 7. Finish the Rock Climb field move effect
+
+Edit [engine/events/overworld.asm](../blob/master/engine/events/overworld.asm):
+
+```diff
++RockClimbFunction:
++ call FieldMoveJumptableReset
++.loop
++ ld hl, .jumptable
++ call FieldMoveJumptable
++ jr nc, .loop
++ and $7f
++ ld [wFieldMoveSucceeded], a
++ ret
++
++.jumptable:
++ dw .TryRockClimb
++ dw .DoRockClimb
++ dw .FailRockClimb
++
++.TryRockClimb:
++ ld de, ENGINE_EARTHBADGE
++ farcall CheckBadge
++ jr c, .noearthbadge
++ call TryRockClimbMenu
++ jr c, .failed
++ ld a, $1
++ ret
++
++.noearthbadge
++ ld a, $80
++ ret
++
++.failed
++ ld a, $2
++ ret
++
++.DoRockClimb:
++ ld hl, RockClimbFromMenuScript
++ call QueueScript
++ ld a, $81
++ ret
++
++.FailRockClimb:
++ call FieldMoveFailed
++ ld a, $80
++ ret
++
++TryRockClimbMenu:
++ call GetFacingTileCoord
++ ld c, a
++ push de
++ call CheckRockyWallTile
++ pop de
++ jr nz, .failed
++ xor a
++ ret
++
++.failed
++ scf
++ ret
++
++TryRockClimbOW::
++ ld de, ENGINE_EARTHBADGE
++ call CheckEngineFlag
++ jr c, .cant_climb
++
++ ld d, ROCK_CLIMB
++ call CheckPartyMove
++ jr c, .cant_climb
++
++ ld a, BANK(AskRockClimbScript)
++ ld hl, AskRockClimbScript
++ call CallScript
++ scf
++ ret
++
++.cant_climb
++ ld a, BANK(CantRockClimbScript)
++ ld hl, CantRockClimbScript
++ call CallScript
++ scf
++ ret
++
++AskRockClimbScript:
++ opentext
++ writetext AskRockClimbText
++ yesorno
++ iftrue UsedRockClimbScript
++ closetext
++ end
++
++CantRockClimbScript:
++ jumptext CantRockClimbText
++
++RockClimbFromMenuScript:
++ reloadmappart
++ special UpdateTimePals
++
++UsedRockClimbScript:
++ callasm GetPartyNick
++ writetext UsedRockClimbText
++ closetext
++ waitsfx
++ playsound SFX_STRENGTH
++ checkcode VAR_FACING
++ if_equal DOWN, .Down
++.loop_up
++ applymovement PLAYER, .RockClimbUpStep
++ callasm .CheckContinueRockClimb
++ iffalse .loop_up
++ end
++
++.Down:
++ applymovement PLAYER, .RockClimbFixFacing
++.loop_down
++ applymovement PLAYER, .RockClimbDownStep
++ callasm .CheckContinueRockClimb
++ iffalse .loop_down
++ applymovement PLAYER, .RockClimbRemoveFixedFacing
++ end
++
++.CheckContinueRockClimb:
++ xor a
++ ld [wScriptVar], a
++ ld a, [wPlayerStandingTile]
++ call CheckRockyWallTile
++ ret z
++ ld a, $1
++ ld [wScriptVar], a
++ ret
++
++.RockClimbUpStep:
++ step UP
++ step_end
++
++.RockClimbDownStep:
++ step DOWN
++ step_end
++
++.RockClimbFixFacing:
++ turn_head UP
++ fix_facing
++ step_end
++
++.RockClimbRemoveFixedFacing:
++ remove_fixed_facing
++ turn_head DOWN
++ step_end
++
++AskRockClimbText:
++ text_jump _AskRockClimbText
++ db "@"
++
++UsedRockClimbText:
++ text_jump _UsedRockClimbText
++ db "@"
++
++CantRockClimbText:
++ text_jump _CantRockClimbText
++ db "@"
+```
+
+You can study how this routine works; it's similar to other field moves. Just like in HG/SS, you need the Earth Badge to use it. When you're facing up or down toward a rocky wall, you can climb it. Just like waterfalls, you'll continue moving until you reach a different type of tile.
+
+Anyway, the requisite move, HM, and field effect are all done, but we still have a few improvements to make.
+
+
+## 8. Talk to rocky walls to use Rock Climb
+
+Edit [engine/overworld/events.asm](../blob/master/engine/overworld/events.asm):
+
+```diff
+ TryTileCollisionEvent::
+ ...
+
+ .headbutt
+ ld a, [wEngineBuffer1]
+ call CheckHeadbuttTreeTile
+- jr nz, .surf
++ jr nz, .rock_climb
+ farcall TryHeadbuttOW
++ jr .done
++
++.rock_climb
++ ld a, [wEngineBuffer1]
++ call CheckRockyWallTile
++ jr nz, .surf
++ farcall TryRockClimbOW
+ jr c, .done
+ jr .noevent
+
+ .surf
+ farcall TrySurfOW
+ jr nc, .noevent
+ jr .done
+
+ .noevent
+ xor a
+ ret
+
+ .done
+ call PlayClickSFX
+ ld a, $ff
+ scf
+ ret
+```
+
+`TryTileCollisionEvent` checks for various relevant collision types, one after another, so we just add a case for rocky walls.
+
+
+## 9. Explain when Rock Climb is enabled
+
+Edit [maps/ViridianGym.asm](../blob/master/maps/ViridianGym.asm):
+
+```diff
+ LeaderBlueAfterText:
+- text "BLUE: …"
++ text "BLUE: With that"
++ line "EARTHBADGE, your"
++
++ para "#MON that know"
++ line "ROCK CLIMB can"
++ cont "use it any time."
++
++ para "…"
+```
+
+
+## 10. Add rocky walls to a map
+
+We're now completely done *implementing* Rock Climb, so now let's demonstrate it.
+
+Open [maps/Route45.blk](../blob/master/maps/Route45.blk) with [Polished Map](https://github.com/Rangi42/polished-map) and design a rocky wall block:
+
+[![Screenshot](screenshots/polished-map-rock-climb.png)](screenshots/polished-map-rock-climb.png)
+
+I replaced the unused block $12 in the `johto` tileset, and used the ledge corner tiles to make what looks like a rocky wall. You might want to create custom tiles instead.
+
+When you save the changes, Polished Map will update [data/tilesets/johto_metatiles.bin](../blob/master/data/tilesets/johto_metatiles.bin) and [maps/Route45.blk](../blob/master/maps/Route45.blk). It will *not* update collision data, so edit [data/tilesets/johto_collision.asm](../blob/master/data/tilesets/johto_collision.asm):
+
+```diff
+ ...
+ tilecoll WALL, WALL, WALL, WALL ; 11
+- tilecoll WALL, WALL, WALL, WALL ; 12
++ tilecoll FLOOR, FLOOR, WALL, ROCKY_WALL ; 12
+ tilecoll WALL, WALL, WALL, WALL ; 13
+ ...
+```
+
+Finally, edit [maps/Route45.asm](../blob/master/maps/Route45.asm):
+
+```diff
+- object_event 7, 33, SPRITE_POKE_BALL, SPRITEMOVEDATA_STILL, 0, 0, -1, -1, 0, OBJECTTYPE_ITEMBALL, 0, Route45MaxPotion, EVENT_ROUTE_45_MAX_POTION
++ object_event 8, 29, SPRITE_POKE_BALL, SPRITEMOVEDATA_STILL, 0, 0, -1, -1, 0, OBJECTTYPE_ITEMBALL, 0, Route45MaxPotion, EVENT_ROUTE_45_MAX_POTION
+```
+
+We just moved an item ball so that you need Rock Climb to get it.
+
+Now test it out!
+
+![Screenshot](screenshots/rock-climb.png)
diff --git a/Tutorials.md b/Tutorials.md
index 7893a2d..ee2af87 100644
--- a/Tutorials.md
+++ b/Tutorials.md
@@ -54,6 +54,7 @@ Tutorials may use diff syntax to show edits:
- [Infinitely reusable TMs](Infinitely-reusable-TMs)
- [Automatically reuse Repel](Automatically-reuse-Repel)
- [Running Shoes](Running-Shoes)
+- [Rock Climb](Rock-Climb)
- [Puddles that splash when you walk](Puddles-that-splash-when-you-walk)
**To do:** *(feel free to contribute one of these!)*
@@ -68,9 +69,7 @@ Tutorials may use diff syntax to show edits:
- Move effect script command
- Example map scripts (for common cases like an NPC that gives you an item)
- Scene for an existing map (aka triggers; auto-running event scripts)
-- Field moves:
- - Dive (exists in [Orange](https://github.com/PiaCarrot/pokeorange))
- - Rock Climb (exists in [Orange](https://github.com/PiaCarrot/pokeorange))
+- Dive (exists in [Orange](https://github.com/PiaCarrot/pokeorange))
- Evolution methods (location, held item, move, [etc](https://gitgud.io/pfero/axyllagame/commit/81914d43eb89195734caee724c0a40d4686a0bab))
- More daily and weekly events
- Third trainer card page for Kanto badges
diff --git a/screenshots/polished-map-rock-climb.png b/screenshots/polished-map-rock-climb.png
new file mode 100644
index 0000000..ae0429f
--- /dev/null
+++ b/screenshots/polished-map-rock-climb.png
Binary files differ
diff --git a/screenshots/rock-climb.png b/screenshots/rock-climb.png
new file mode 100644
index 0000000..c88e2f2
--- /dev/null
+++ b/screenshots/rock-climb.png
Binary files differ