diff options
-rw-r--r-- | Add-spinner-tiles-from-Generation-I-Rocket-Hideout.md | 245 |
1 files changed, 245 insertions, 0 deletions
diff --git a/Add-spinner-tiles-from-Generation-I-Rocket-Hideout.md b/Add-spinner-tiles-from-Generation-I-Rocket-Hideout.md new file mode 100644 index 0000000..11e574e --- /dev/null +++ b/Add-spinner-tiles-from-Generation-I-Rocket-Hideout.md @@ -0,0 +1,245 @@ +This tutorial will cover adding new collision types for spinner tiles in all four cardinal directions as well as a stopper tile to stop the player from spinning. Credit to Rangi42 for implementing this in Pokemon Polished Crystal + +## Contents + +1. [Create Constants for the New Collision Types](#1-create-constants-for-the-new-collision-types) +2. [Implement New Movement Functionality](#2-implement-new-movement-functionality) +3. [Prevent Oddities When Losing Battles]() + + +## 1. Create Constants for the New Collision Types + +In order to add new collision types to use on maps, we'll have to define constants for them. + +Edit [constants/collision_constants.asm](../blob/master/constants/collision_constants.asm) + +```diff + COLL_DOOR_7D EQU $7d ; unused + COLL_WARP_CARPET_RIGHT EQU $7e + COLL_WARP_7F EQU $7f ; unused ++COLL_STOP_SPIN EQU $80 ++COLL_SPIN_UP EQU $81 ++COLL_SPIN_DOWN EQU $82 ++COLL_SPIN_LEFT EQU $83 ++COLL_SPIN_RIGHT EQU $84 + COLL_COUNTER EQU $90 + COLL_BOOKSHELF EQU $91 + COLL_PC EQU $93 +``` + +Edit [constants/map_object_constants.asm](../blob/master/constants/map_object_constants.asm) + +```diff + const STEP_TURN ; 5 + const STEP_BACK_LEDGE ; 6 + const STEP_WALK_IN_PLACE ; 7 ++ const STEP_SPIN ; 8 +``` + +Edit [data/collision_permissions.asm](../blob/master/data/collision_permissions.asm) + +```diff + db LAND_TILE ; COLL_DOOR_7D + db LAND_TILE ; COLL_WARP_CARPET_RIGHT + db LAND_TILE ; COLL_WARP_7F +- db WALL_TILE ; 80 +- db WALL_TILE ; 81 +- db WALL_TILE ; 82 +- db WALL_TILE ; 83 +- db WALL_TILE ; 84 ++ db LAND_TILE ; COLL_STOP_SPIN ++ db LAND_TILE ; COLL_SPIN_UP ++ db LAND_TILE ; COLL_SPIN_DOWN ++ db LAND_TILE ; COLL_SPIN_LEFT ++ db LAND_TILE ; COLL_SPIN_RIGHT + db LAND_TILE ; 85 + db LAND_TILE ; 86 + db LAND_TILE ; 87 +``` + +We'll need to add a flag in WRAM to denote whether we are currently spinning. + +Edit [wram.asm](../blob/master/wram.asm) +```diff + wScrollingMenuListSize:: db + +- ds 1 +- + ; used when following a map warp + wNextWarp:: db + wNextMapGroup:: db + + ... + + wPlayerStepFlags:: db + wPlayerStepDirection:: db + ++wSpinning:: db ++ + wBGMapAnchor:: dw + + UNION +``` + +## 2. Implement New Movement Functionality + +Now that we have our constants in order, we have to add functionality specific to these tiles. + +Edit [engine/overworld/player_movement.asm](../blob/master/engine/overworld/player_movement.asm) +```diff +DoPlayerMovement:: + jr z, .bump + cp 2 + jr z, .bump ++ ++ ld a, [wSpinning] ++ and a ++ jr nz, .spin + + ld a, [wPlayerStandingTile] + call CheckIceTile + + ... + + DoPlayerMovement:: + xor a + ret + ++.spin ++ ld de, SFX_SQUEAK ++ call PlaySFX ++ ld a, STEP_SPIN ++ call .DoStep ++ scf ++ ret ++ + .bump + xor a ++ ld [wSpinning], a + ret + + .TrySurf: + + ... + + DoPlayerMovement:: + dw .TurningStep + dw .BackJumpStep + dw .FinishFacing ++ dw .SpinStep + + .SlowStep: + slow_step DOWN + + ... + + DoPlayerMovement:: + db $80 | UP + db $80 | LEFT + db $80 | RIGHT ++.SpinStep ++ turn_in_down ++ turn_in_up ++ turn_in_left ++ turn_in_right + + .StandInPlace: + ld a, 0 + + ... + + DoPlayerMovement:: + ret + + .CheckForced: +-; When sliding on ice, input is forced to remain in the same direction. ++; When sliding on ice or spinning, input is forced to remain in the same direction. + ++ call CheckSpinning ++ jr z, .not_spinning ++ dec a ++ jr .force ++ ++.not_spinning + call CheckStandingOnIce + ret nc + + ... + + DoPlayerMovement:: + cp 0 + ret z + ++.force + maskbits NUM_DIRECTIONS + ld e, a + ld d, 0 + + ... + + CheckStandingOnIce:: + and a + ret + ++CheckSpinning:: ++ ld a, [wPlayerStandingTile] ++ cp COLL_STOP_SPIN ++ jr z, .stop_spin ++ call CheckSpinTile ++ jr z, .start_spin ++ ld a, [wSpinning] ++ and a ++ ret ++ ++.start_spin ++ ld a, c ++ inc a ++ ld [wSpinning], a ++ and a ++ ret ++ ++.stop_spin ++ xor a ++ ld [wSpinning], a ++ ret ++ ++CheckSpinTile: ++ cp COLL_SPIN_UP ++ ld c, UP ++ ret z ++ cp COLL_SPIN_DOWN ++ ld c, DOWN ++ ret z ++ cp COLL_SPIN_LEFT ++ ld c, LEFT ++ ret z ++ cp COLL_SPIN_RIGHT ++ ld c, RIGHT ++ ret z ++ ld c, STANDING ++ ret ++ + StopPlayerForEvent:: + ld hl, wPlayerNextMovement + ld a, movement_step_sleep +``` + +## 3. Prevent Oddities When Losing Battles + +Since it is possible for battles to begin if trainers spot you while you are spinning, a slight addition must be made to the whiteout engine event script to account for a scenario where the player would never stop spinning. + +Edit [engine/events/whiteout.asm](../blob/master/engine/events/whiteout.asm) + +```diff + HalveMoney: + farcall StubbedTrainerRankings_WhiteOuts + + ; Halve the player's money. ++ xor a ++ ld [wSpinning], a + ld hl, wMoney + ld a, [hl] + srl a +``` + +This edit can still be made if you've adjusted the money reduction function, just add the two new lines before loading wMoney into hl.
\ No newline at end of file |