diff options
-rw-r--r-- | Puddles-that-splash-when-you-walk.md | 4 | ||||
-rw-r--r-- | Rock-Climb.md | 405 | ||||
-rw-r--r-- | Tutorials.md | 5 | ||||
-rw-r--r-- | screenshots/polished-map-rock-climb.png | bin | 0 -> 29626 bytes | |||
-rw-r--r-- | screenshots/rock-climb.png | bin | 0 -> 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: + +[](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! + + 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 Binary files differnew file mode 100644 index 0000000..ae0429f --- /dev/null +++ b/screenshots/polished-map-rock-climb.png diff --git a/screenshots/rock-climb.png b/screenshots/rock-climb.png Binary files differnew file mode 100644 index 0000000..c88e2f2 --- /dev/null +++ b/screenshots/rock-climb.png |