summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Add-spinner-tiles-from-Generation-I-Rocket-Hideout.md245
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