pokecrystal-board/engine/overworld/player_movement.asm

1014 lines
16 KiB
NASM
Raw Permalink Normal View History

2018-06-24 07:09:41 -07:00
DoPlayerMovement::
2015-12-29 10:15:58 -08:00
call .GetDPad
2016-05-14 09:28:00 -07:00
ld a, movement_step_sleep
2018-01-23 14:39:09 -08:00
ld [wMovementAnimation], a
2015-12-29 10:15:58 -08:00
xor a
ld [wWalkingIntoEdgeWarp], a
2015-12-29 10:15:58 -08:00
call .TranslateIntoMovement
ld c, a
2018-01-23 14:39:09 -08:00
ld a, [wMovementAnimation]
2015-12-29 10:15:58 -08:00
ld [wPlayerNextMovement], a
ret
.GetDPad:
ldh a, [hCurBoardEvent]
cp BOARDEVENT_HANDLE_BOARD
jr nz, .not_auto_in_board
; compute direction according to space layout and save to wCurInput
farcall StepTowardsNextSpace
ret
.not_auto_in_board
ldh a, [hJoyDown]
2018-01-23 14:39:09 -08:00
ld [wCurInput], a
2015-12-29 10:15:58 -08:00
; ignore standing downhill if in View Map mode
ldh a, [hCurBoardEvent]
cp BOARDEVENT_VIEW_MAP_MODE
ret z
; Otherwise, standing downhill instead moves down.
ld hl, wBikeFlags
2018-01-22 10:57:44 -08:00
bit BIKEFLAGS_DOWNHILL_F, [hl]
2015-12-29 10:15:58 -08:00
ret z
ld c, a
and D_PAD
ret nz
ld a, c
or D_DOWN
2018-01-23 14:39:09 -08:00
ld [wCurInput], a
2015-12-29 10:15:58 -08:00
ret
.TranslateIntoMovement:
ldh a, [hCurBoardEvent]
cp BOARDEVENT_VIEW_MAP_MODE
jp z, .ViewMapMode
2018-01-23 14:39:09 -08:00
ld a, [wPlayerState]
2015-12-29 10:15:58 -08:00
cp PLAYER_NORMAL
jr z, .Normal
cp PLAYER_SURF
jr z, .Surf
cp PLAYER_SURF_PIKA
jr z, .Surf
cp PLAYER_BIKE
jr z, .Normal
cp PLAYER_SKATE
2015-12-29 10:15:58 -08:00
jr z, .Ice
.Normal:
2015-12-29 10:15:58 -08:00
call .CheckForced
call .GetAction
call .CheckTile
ret c
call .CheckTurning
ret c
call .TryStep
ret c
call .TryJump
ret c
call .CheckWarp
ret c
jr .NotMoving
.Surf:
2015-12-29 10:15:58 -08:00
call .CheckForced
call .GetAction
call .CheckTile
ret c
call .CheckTurning
ret c
call .TrySurf
ret c
jr .NotMoving
.Ice:
2015-12-29 10:15:58 -08:00
call .CheckForced
call .GetAction
call .CheckTile
ret c
call .CheckTurning
ret c
call .TryStep
ret c
call .TryJump
ret c
call .CheckWarp
ret c
2018-01-23 14:39:09 -08:00
ld a, [wWalkingDirection]
2015-12-29 10:15:58 -08:00
cp STANDING
jr z, .HitWall
call .BumpSound
.HitWall:
2015-12-29 10:15:58 -08:00
call .StandInPlace
xor a
ret
.NotMoving:
2018-01-23 14:39:09 -08:00
ld a, [wWalkingDirection]
2015-12-29 10:15:58 -08:00
cp STANDING
jr z, .Standing
; Walking into an edge warp won't bump.
ld a, [wWalkingIntoEdgeWarp]
2015-12-29 10:15:58 -08:00
and a
jr nz, .CantMove
call .BumpSound
.CantMove:
2015-12-29 10:15:58 -08:00
call ._WalkInPlace
xor a
ret
.Standing:
2015-12-29 10:15:58 -08:00
call .StandInPlace
xor a
ret
.BumpSound:
call CheckSFX
ret c
ld de, SFX_BUMP
call PlaySFX
ret
.ViewMapMode:
; if View Map mode, ignore regular collisions but account for going off-limits or off-range
call .GetAction
call .ViewMapMode_CheckCollision
; perform a normal step (Stand in place if wWalkingDirection is STANDING)
ld a, STEP_WALK
call .DoStep
scf
ret
.ViewMapMode_CheckCollision:
; return STANDING into wWalkingDirection if trying to walk off-limits or off-range
; wTileDown, wTileUp, wTileLeft, and wTileRight are borrowed in this mode
; to signal valid directions to InitSecondarySprites.
xor a
ld hl, wTileDown
ld [hli], a ; wTileDown
ld [hli], a ; wTileUp
ld [hli], a ; wTileLeft
ld [hl], a ; wTileRight
; for each direction, check if next tile is COLL_OUT_OF_BOUNDS, which is the only impassable collision in View Map mode
xor a
ld [wTilePermissions], a
ld a, [wPlayerMapX]
ld d, a
ld a, [wPlayerMapY]
ld e, a
push de
inc e
call GetCoordTileCollision
cp COLL_OUT_OF_BOUNDS
jr nz, .next1
ld [wTileDown], a
.next1
pop de
dec e
call GetCoordTileCollision
cp COLL_OUT_OF_BOUNDS
jr nz, .next2
ld [wTileUp], a
.next2
ld a, [wPlayerMapX]
ld d, a
ld a, [wPlayerMapY]
ld e, a
push de
dec d
call GetCoordTileCollision
cp COLL_OUT_OF_BOUNDS
jr nz, .next3
ld [wTileLeft], a
.next3
pop de
inc d
call GetCoordTileCollision
cp COLL_OUT_OF_BOUNDS
jr nz, .next4
ld [wTileRight], a
.next4
; for each direction, check if trying to go off-limits
ld hl, wYCoord
ld de, wMapHeight
ld bc, wSouthConnectedMapGroup
ld a, DOWN
call .ViewMapMode_CheckDirectionOffLimits
ld hl, wYCoord
ld de, .TopLimit
ld bc, wNorthConnectedMapGroup
ld a, UP
call .ViewMapMode_CheckDirectionOffLimits
ld hl, wXCoord
ld de, wMapWidth
ld bc, wEastConnectedMapGroup
ld a, RIGHT
call .ViewMapMode_CheckDirectionOffLimits
ld hl, wXCoord
ld de, .LeftLimit
ld bc, wWestConnectedMapGroup
ld a, LEFT
call .ViewMapMode_CheckDirectionOffLimits
; for each direction, check if trying to go off-range
ld hl, wViewMapModeRange
ld de, wViewMapModeDisplacementY
ld bc, wTileDown
ld a, [de]
cp [hl]
jr nz, .next5
ld a, COLL_OUT_OF_BOUNDS
ld [bc], a
.next5
inc bc ; wTileUp
ld a, [de]
xor $ff
inc a
cp [hl]
jr nz, .next6
ld a, COLL_OUT_OF_BOUNDS
ld [bc], a
.next6
ld de, wViewMapModeDisplacementX
inc bc ; wTileLeft
ld a, [de]
xor $ff
inc a
cp [hl]
jr nz, .next7
ld a, COLL_OUT_OF_BOUNDS
ld [bc], a
.next7
inc bc ; wTileRight
ld a, [de]
cp [hl]
jr nz, .next8
ld a, COLL_OUT_OF_BOUNDS
ld [bc], a
.next8
; finally return STANDING into wWalkingDirection in the current direction at
; wWalkingDirection has had its corresponding wTile* address set to $ff.
ld a, [wWalkingDirection]
cp STANDING
ret z
ld hl, wTileDown
ld c, a
ld b, 0
add hl, bc
ld a, [hl]
cp COLL_OUT_OF_BOUNDS
ret nz
ld a, STANDING
ld [wWalkingDirection], a
ret
.TopLimit:
.LeftLimit:
db 0
; check if player would be walking off-limits in this direction
.ViewMapMode_CheckDirectionOffLimits:
push af
; connection strips that aren't as large as the map height/width are not accounted for.
; to avoid viewing map off-limits when there is a partial map connection,
; use COLL_OUT_OF_BOUNDS in out of bound tiles.
ld a, [bc] ; connected map group
inc a
jr nz, .valid ; it's ok if there's any connected map in this direction
ld a, [de] ; map dimension size (in metatiles), or 0 if moving up/left
add a
and a
jr z, .ok
dec a ; if e.g. size is 0x10, limit is at coord=0x1f
.ok
cp [hl] ; player coord (in half-metatiles)
jr nz, .valid
; not valid: set wTile* to $ff
pop af
ld hl, wTileDown
ld c, a
ld b, 0
add hl, bc
ld [hl], $ff
ret
.valid
pop af
ret
2018-06-24 07:09:41 -07:00
.CheckTile:
2015-12-29 10:15:58 -08:00
; Tiles such as waterfalls and warps move the player
; in a given direction, overriding input.
ld a, [wPlayerTileCollision]
2015-12-29 10:15:58 -08:00
ld c, a
call CheckWhirlpoolTile
2016-03-01 19:31:21 -08:00
jr c, .not_whirlpool
2019-11-03 11:30:33 -08:00
ld a, PLAYERMOVEMENT_FORCE_TURN
2015-12-29 10:15:58 -08:00
scf
ret
2016-03-01 19:31:21 -08:00
.not_whirlpool
2015-12-29 10:15:58 -08:00
and $f0
2017-12-12 13:15:58 -08:00
cp HI_NYBBLE_CURRENT
2015-12-29 10:15:58 -08:00
jr z, .water
2017-12-12 13:15:58 -08:00
cp HI_NYBBLE_WALK
2015-12-29 10:15:58 -08:00
jr z, .land1
2017-12-12 13:15:58 -08:00
cp HI_NYBBLE_WALK_ALT
2015-12-29 10:15:58 -08:00
jr z, .land2
2017-12-12 13:15:58 -08:00
cp HI_NYBBLE_WARPS
2015-12-29 10:15:58 -08:00
jr z, .warps
2016-01-17 21:39:01 -08:00
jr .no_walk
2015-12-29 10:15:58 -08:00
.water
ld a, c
2018-01-16 14:27:50 -08:00
maskbits NUM_DIRECTIONS
2015-12-29 10:15:58 -08:00
ld c, a
ld b, 0
ld hl, .water_table
add hl, bc
ld a, [hl]
2018-01-23 14:39:09 -08:00
ld [wWalkingDirection], a
2023-12-31 04:39:00 -08:00
jr .continue_fast_slide
2015-12-29 10:15:58 -08:00
.water_table
2017-12-12 13:15:58 -08:00
db RIGHT ; COLL_WATERFALL_RIGHT
db LEFT ; COLL_WATERFALL_LEFT
db UP ; COLL_WATERFALL_UP
db DOWN ; COLL_WATERFALL
2015-12-29 10:15:58 -08:00
.land1
ld a, c
and 7
ld c, a
ld b, 0
ld hl, .land1_table
add hl, bc
ld a, [hl]
cp STANDING
2016-01-17 21:39:01 -08:00
jr z, .no_walk
2018-01-23 14:39:09 -08:00
ld [wWalkingDirection], a
2016-01-17 21:39:01 -08:00
jr .continue_walk
2015-12-29 10:15:58 -08:00
.land1_table
2017-12-12 13:15:58 -08:00
db STANDING ; COLL_BRAKE
db RIGHT ; COLL_WALK_RIGHT
db LEFT ; COLL_WALK_LEFT
db UP ; COLL_WALK_UP
db DOWN ; COLL_WALK_DOWN
db STANDING ; COLL_BRAKE_45
db STANDING ; COLL_BRAKE_46
db STANDING ; COLL_BRAKE_47
2015-12-29 10:15:58 -08:00
.land2
ld a, c
and 7
ld c, a
ld b, 0
ld hl, .land2_table
add hl, bc
ld a, [hl]
cp STANDING
2016-01-17 21:39:01 -08:00
jr z, .no_walk
2018-01-23 14:39:09 -08:00
ld [wWalkingDirection], a
2016-01-17 21:39:01 -08:00
jr .continue_walk
2015-12-29 10:15:58 -08:00
.land2_table
2017-12-12 13:15:58 -08:00
db RIGHT ; COLL_WALK_RIGHT_ALT
db LEFT ; COLL_WALK_LEFT_ALT
db UP ; COLL_WALK_UP_ALT
db DOWN ; COLL_WALK_DOWN_ALT
db STANDING ; COLL_BRAKE_ALT
db STANDING ; COLL_BRAKE_55
db STANDING ; COLL_BRAKE_56
db STANDING ; COLL_BRAKE_57
2015-12-29 10:15:58 -08:00
.warps
ld a, c
2017-12-12 13:15:58 -08:00
cp COLL_DOOR
2015-12-29 10:15:58 -08:00
jr z, .down
2017-12-12 13:15:58 -08:00
cp COLL_DOOR_79
2015-12-29 10:15:58 -08:00
jr z, .down
2017-12-12 13:15:58 -08:00
cp COLL_STAIRCASE
2015-12-29 10:15:58 -08:00
jr z, .down
2017-12-12 13:15:58 -08:00
cp COLL_CAVE
2016-01-17 21:39:01 -08:00
jr nz, .no_walk
2015-12-29 10:15:58 -08:00
.down
ld a, DOWN
2018-01-23 14:39:09 -08:00
ld [wWalkingDirection], a
2016-01-17 21:39:01 -08:00
jr .continue_walk
2015-12-29 10:15:58 -08:00
2016-01-17 21:39:01 -08:00
.no_walk
2015-12-29 10:15:58 -08:00
xor a
ret
2023-12-31 04:39:00 -08:00
.continue_fast_slide
ld a, STEP_ICE
jr .continue_step
2016-01-17 21:39:01 -08:00
.continue_walk
2015-12-29 10:15:58 -08:00
ld a, STEP_WALK
2023-12-31 04:39:00 -08:00
; fallthrough
.continue_step
2015-12-29 10:15:58 -08:00
call .DoStep
2019-11-03 11:30:33 -08:00
ld a, PLAYERMOVEMENT_CONTINUE
2015-12-29 10:15:58 -08:00
scf
ret
2018-06-24 07:09:41 -07:00
.CheckTurning:
2015-12-29 10:15:58 -08:00
; If the player is turning, change direction first. This also lets
; the player change facing without moving by tapping a direction.
2016-05-14 10:46:14 -07:00
ld a, [wPlayerTurningDirection]
2015-12-29 10:15:58 -08:00
cp 0
2016-05-14 10:46:14 -07:00
jr nz, .not_turning
2018-01-23 14:39:09 -08:00
ld a, [wWalkingDirection]
2015-12-29 10:15:58 -08:00
cp STANDING
2016-05-14 10:46:14 -07:00
jr z, .not_turning
2015-12-29 10:15:58 -08:00
ld e, a
2018-01-23 14:39:09 -08:00
ld a, [wPlayerDirection]
2015-12-29 10:15:58 -08:00
rrca
rrca
2018-01-16 14:27:50 -08:00
maskbits NUM_DIRECTIONS
2015-12-29 10:15:58 -08:00
cp e
2016-05-14 10:46:14 -07:00
jr z, .not_turning
2015-12-29 10:15:58 -08:00
ld a, STEP_TURN
call .DoStep
2019-11-03 11:30:33 -08:00
ld a, PLAYERMOVEMENT_TURN
2015-12-29 10:15:58 -08:00
scf
ret
2016-05-14 10:46:14 -07:00
.not_turning
2015-12-29 10:15:58 -08:00
xor a
ret
2018-06-24 07:09:41 -07:00
.TryStep:
2015-12-29 10:15:58 -08:00
; Surfing actually calls .TrySurf directly instead of passing through here.
2018-01-23 14:39:09 -08:00
ld a, [wPlayerState]
2015-12-29 10:15:58 -08:00
cp PLAYER_SURF
jr z, .TrySurf
cp PLAYER_SURF_PIKA
jr z, .TrySurf
call .CheckLandPerms
jr c, .bump
call .CheckNPC
and a
jr z, .bump
cp 2
jr z, .bump
ld a, [wPlayerTileCollision]
2015-12-29 10:15:58 -08:00
call CheckIceTile
jr nc, .ice
; Downhill riding is slower when not moving down.
call .BikeCheck
jr nz, .walk
ld hl, wBikeFlags
2018-01-22 10:57:44 -08:00
bit BIKEFLAGS_DOWNHILL_F, [hl]
2015-12-29 10:15:58 -08:00
jr z, .fast
2018-01-23 14:39:09 -08:00
ld a, [wWalkingDirection]
2015-12-29 10:15:58 -08:00
cp DOWN
jr z, .fast
ld a, STEP_WALK
call .DoStep
scf
ret
.fast
ld a, STEP_BIKE
call .DoStep
scf
ret
.walk
ld a, STEP_WALK
call .DoStep
scf
ret
.ice
ld a, STEP_ICE
call .DoStep
scf
ret
.bump
xor a
ret
2018-06-24 07:09:41 -07:00
.TrySurf:
2015-12-29 10:15:58 -08:00
call .CheckSurfPerms
ld [wWalkingIntoLand], a
2015-12-29 10:15:58 -08:00
jr c, .surf_bump
call .CheckNPC
ld [wWalkingIntoNPC], a
2015-12-29 10:15:58 -08:00
and a
jr z, .surf_bump
cp 2
jr z, .surf_bump
ld a, [wWalkingIntoLand]
2015-12-29 10:15:58 -08:00
and a
jr nz, .ExitWater
ld a, STEP_WALK
call .DoStep
scf
ret
.ExitWater:
2015-12-29 10:15:58 -08:00
call .GetOutOfWater
call PlayMapMusic
ld a, STEP_WALK
call .DoStep
2019-11-03 11:30:33 -08:00
ld a, PLAYERMOVEMENT_EXIT_WATER
2015-12-29 10:15:58 -08:00
scf
ret
.surf_bump
xor a
ret
2018-06-24 07:09:41 -07:00
.TryJump:
ld a, [wPlayerTileCollision]
2015-12-29 10:15:58 -08:00
ld e, a
and $f0
2017-12-12 13:15:58 -08:00
cp HI_NYBBLE_LEDGES
2015-12-29 10:15:58 -08:00
jr nz, .DontJump
ld a, e
and 7
ld e, a
ld d, 0
2020-10-04 16:43:28 -07:00
ld hl, .ledge_table
2015-12-29 10:15:58 -08:00
add hl, de
2018-01-23 14:39:09 -08:00
ld a, [wFacingDirection]
2015-12-29 10:15:58 -08:00
and [hl]
jr z, .DontJump
ld de, SFX_JUMP_OVER_LEDGE
call PlaySFX
ld a, STEP_LEDGE
call .DoStep
2019-11-03 11:30:33 -08:00
ld a, PLAYERMOVEMENT_JUMP
2015-12-29 10:15:58 -08:00
scf
ret
.DontJump:
2015-12-29 10:15:58 -08:00
xor a
ret
2020-10-04 16:43:28 -07:00
.ledge_table
2017-12-12 13:15:58 -08:00
db FACE_RIGHT ; COLL_HOP_RIGHT
db FACE_LEFT ; COLL_HOP_LEFT
db FACE_UP ; COLL_HOP_UP
db FACE_DOWN ; COLL_HOP_DOWN
db FACE_RIGHT | FACE_DOWN ; COLL_HOP_DOWN_RIGHT
db FACE_DOWN | FACE_LEFT ; COLL_HOP_DOWN_LEFT
db FACE_UP | FACE_RIGHT ; COLL_HOP_UP_RIGHT
db FACE_UP | FACE_LEFT ; COLL_HOP_UP_LEFT
2015-12-29 10:15:58 -08:00
2018-06-24 07:09:41 -07:00
.CheckWarp:
2018-01-23 14:39:09 -08:00
ld a, [wWalkingDirection]
cp STANDING
jr z, .not_warp
2015-12-29 10:15:58 -08:00
ld e, a
ld d, 0
ld hl, .EdgeWarps
add hl, de
ld a, [wPlayerTileCollision]
2015-12-29 10:15:58 -08:00
cp [hl]
jr nz, .not_warp
ld a, TRUE
ld [wWalkingIntoEdgeWarp], a
2018-01-23 14:39:09 -08:00
ld a, [wWalkingDirection]
2015-12-29 10:15:58 -08:00
ld e, a
2018-01-23 14:39:09 -08:00
ld a, [wPlayerDirection]
2015-12-29 10:15:58 -08:00
rrca
rrca
2018-01-16 14:27:50 -08:00
maskbits NUM_DIRECTIONS
2015-12-29 10:15:58 -08:00
cp e
jr nz, .not_warp
call WarpCheck
jr nc, .not_warp
call .StandInPlace
scf
2019-11-03 11:30:33 -08:00
ld a, PLAYERMOVEMENT_WARP
2015-12-29 10:15:58 -08:00
ret
.not_warp
2019-11-03 11:30:33 -08:00
xor a ; PLAYERMOVEMENT_NORMAL
2015-12-29 10:15:58 -08:00
ret
.EdgeWarps:
2017-12-12 13:15:58 -08:00
db COLL_WARP_CARPET_DOWN
db COLL_WARP_CARPET_UP
db COLL_WARP_CARPET_LEFT
db COLL_WARP_CARPET_RIGHT
2015-12-29 10:15:58 -08:00
.DoStep:
2015-12-29 10:15:58 -08:00
ld e, a
ld d, 0
ld hl, .Steps
add hl, de
add hl, de
ld a, [hli]
ld h, [hl]
ld l, a
2018-01-23 14:39:09 -08:00
ld a, [wWalkingDirection]
2015-12-29 10:15:58 -08:00
ld e, a
cp STANDING
jp z, .StandInPlace
add hl, de
ld a, [hl]
2018-01-23 14:39:09 -08:00
ld [wMovementAnimation], a
2015-12-29 10:15:58 -08:00
2016-05-14 10:46:14 -07:00
ld hl, .FinishFacing
2015-12-29 10:15:58 -08:00
add hl, de
ld a, [hl]
2016-05-14 10:46:14 -07:00
ld [wPlayerTurningDirection], a
2015-12-29 10:15:58 -08:00
2019-11-03 11:30:33 -08:00
ld a, PLAYERMOVEMENT_FINISH
2015-12-29 10:15:58 -08:00
ret
.Steps:
; entries correspond to STEP_* constants (see constants/map_object_constants.asm)
table_width 2, DoPlayerMovement.Steps
2015-12-29 10:15:58 -08:00
dw .SlowStep
dw .NormalStep
dw .FastStep
dw .JumpStep
dw .SlideStep
dw .TurningStep
dw .BackJumpStep
2016-05-14 10:46:14 -07:00
dw .FinishFacing
assert_table_length NUM_STEPS
2015-12-29 10:15:58 -08:00
.SlowStep:
2016-05-14 10:46:14 -07:00
slow_step DOWN
slow_step UP
slow_step LEFT
slow_step RIGHT
.NormalStep:
2016-05-14 10:46:14 -07:00
step DOWN
step UP
step LEFT
step RIGHT
.FastStep:
2016-05-14 10:46:14 -07:00
big_step DOWN
big_step UP
big_step LEFT
big_step RIGHT
.JumpStep:
2016-05-14 10:46:14 -07:00
jump_step DOWN
jump_step UP
jump_step LEFT
jump_step RIGHT
.SlideStep:
2016-05-14 10:46:14 -07:00
fast_slide_step DOWN
fast_slide_step UP
fast_slide_step LEFT
fast_slide_step RIGHT
.BackJumpStep:
2016-05-14 10:46:14 -07:00
jump_step UP
jump_step DOWN
jump_step RIGHT
jump_step LEFT
.TurningStep:
2016-05-14 10:46:14 -07:00
turn_step DOWN
turn_step UP
turn_step LEFT
turn_step RIGHT
.FinishFacing:
2018-12-09 15:13:37 -08:00
db $80 | DOWN
db $80 | UP
db $80 | LEFT
db $80 | RIGHT
2015-12-29 10:15:58 -08:00
2018-06-24 07:09:41 -07:00
.StandInPlace:
2015-12-29 10:15:58 -08:00
ld a, 0
2016-05-14 10:46:14 -07:00
ld [wPlayerTurningDirection], a
2016-05-14 09:28:00 -07:00
ld a, movement_step_sleep
2018-01-23 14:39:09 -08:00
ld [wMovementAnimation], a
2015-12-29 10:15:58 -08:00
xor a
ret
2018-06-24 07:09:41 -07:00
._WalkInPlace:
2015-12-29 10:15:58 -08:00
ld a, 0
2016-05-14 10:46:14 -07:00
ld [wPlayerTurningDirection], a
2015-12-29 10:15:58 -08:00
ld a, movement_step_bump
2018-01-23 14:39:09 -08:00
ld [wMovementAnimation], a
2015-12-29 10:15:58 -08:00
xor a
ret
2018-06-24 07:09:41 -07:00
.CheckForced:
2015-12-29 10:15:58 -08:00
; When sliding on ice, input is forced to remain in the same direction.
call CheckStandingOnIce
ret nc
2016-05-14 10:46:14 -07:00
ld a, [wPlayerTurningDirection]
2015-12-29 10:15:58 -08:00
cp 0
ret z
2018-01-16 14:27:50 -08:00
maskbits NUM_DIRECTIONS
2015-12-29 10:15:58 -08:00
ld e, a
ld d, 0
ld hl, .forced_dpad
add hl, de
2018-01-23 14:39:09 -08:00
ld a, [wCurInput]
2015-12-29 10:15:58 -08:00
and BUTTONS
or [hl]
2018-01-23 14:39:09 -08:00
ld [wCurInput], a
2015-12-29 10:15:58 -08:00
ret
.forced_dpad
db D_DOWN, D_UP, D_LEFT, D_RIGHT
2018-06-24 07:09:41 -07:00
.GetAction:
2015-12-29 10:15:58 -08:00
; Poll player input and update movement info.
ld hl, .action_table
ld de, .action_table_1_end - .action_table_1
2018-01-23 14:39:09 -08:00
ld a, [wCurInput]
2015-12-29 10:15:58 -08:00
bit D_DOWN_F, a
jr nz, .d_down
bit D_UP_F, a
jr nz, .d_up
bit D_LEFT_F, a
jr nz, .d_left
bit D_RIGHT_F, a
jr nz, .d_right
; Standing
jr .update
.d_down
add hl, de
.d_up
add hl, de
.d_left
add hl, de
.d_right
add hl, de
2015-12-29 10:15:58 -08:00
.update
ld a, [hli]
2018-01-23 14:39:09 -08:00
ld [wWalkingDirection], a
2015-12-29 10:15:58 -08:00
ld a, [hli]
2018-01-23 14:39:09 -08:00
ld [wFacingDirection], a
2015-12-29 10:15:58 -08:00
ld a, [hli]
2018-01-23 14:39:09 -08:00
ld [wWalkingX], a
2015-12-29 10:15:58 -08:00
ld a, [hli]
2018-01-23 14:39:09 -08:00
ld [wWalkingY], a
2015-12-29 10:15:58 -08:00
ld a, [hli]
ld h, [hl]
ld l, a
ld a, [hl]
ld [wWalkingTileCollision], a
2015-12-29 10:15:58 -08:00
ret
MACRO player_action
; walk direction, facing, x movement, y movement, tile collision pointer
db \1, \2, \3, \4
dw \5
ENDM
.action_table:
.action_table_1
player_action STANDING, FACE_CURRENT, 0, 0, wPlayerTileCollision
.action_table_1_end
player_action RIGHT, FACE_RIGHT, 1, 0, wTileRight
player_action LEFT, FACE_LEFT, -1, 0, wTileLeft
player_action UP, FACE_UP, 0, -1, wTileUp
player_action DOWN, FACE_DOWN, 0, 1, wTileDown
2015-12-29 10:15:58 -08:00
2018-06-24 07:09:41 -07:00
.CheckNPC:
2015-12-29 10:15:58 -08:00
; Returns 0 if there is an NPC in front that you can't move
; Returns 1 if there is no NPC in front
; Returns 2 if there is a movable NPC in front. The game actually treats
; this the same as an NPC in front (bump).
2015-12-29 10:15:58 -08:00
ld a, 0
ldh [hMapObjectIndex], a
2015-12-29 10:15:58 -08:00
; Load the next X coordinate into d
ld a, [wPlayerMapX]
2015-12-29 10:15:58 -08:00
ld d, a
2018-01-23 14:39:09 -08:00
ld a, [wWalkingX]
2015-12-29 10:15:58 -08:00
add d
ld d, a
; Load the next Y coordinate into e
ld a, [wPlayerMapY]
2015-12-29 10:15:58 -08:00
ld e, a
2018-01-23 14:39:09 -08:00
ld a, [wWalkingY]
2015-12-29 10:15:58 -08:00
add e
ld e, a
; Find an object struct with coordinates equal to d,e
2018-01-23 14:39:09 -08:00
ld bc, wObjectStructs ; redundant
2017-12-24 09:47:30 -08:00
farcall IsNPCAtCoord
jr nc, .no_npc
2015-12-29 10:15:58 -08:00
call .CheckStrengthBoulder
jr c, .no_bump
xor a ; bump
2015-12-29 10:15:58 -08:00
ret
.no_npc
2015-12-29 10:15:58 -08:00
ld a, 1
ret
.no_bump
ld a, 2
ret
2018-06-24 07:09:41 -07:00
.CheckStrengthBoulder:
ld hl, wBikeFlags
2018-01-22 10:57:44 -08:00
bit BIKEFLAGS_STRENGTH_ACTIVE_F, [hl]
2015-12-29 10:15:58 -08:00
jr z, .not_boulder
ld hl, OBJECT_WALKING
2015-12-29 10:15:58 -08:00
add hl, bc
ld a, [hl]
cp STANDING
jr nz, .not_boulder
ld hl, OBJECT_PALETTE
add hl, bc
bit STRENGTH_BOULDER_F, [hl]
2015-12-29 10:15:58 -08:00
jr z, .not_boulder
ld hl, OBJECT_FLAGS2
add hl, bc
set 2, [hl]
2018-01-23 14:39:09 -08:00
ld a, [wWalkingDirection]
2015-12-29 10:15:58 -08:00
ld d, a
ld hl, OBJECT_RANGE
add hl, bc
ld a, [hl]
and %11111100
2015-12-29 10:15:58 -08:00
or d
ld [hl], a
scf
ret
.not_boulder
xor a
ret
2018-06-24 07:09:41 -07:00
.CheckLandPerms:
2015-12-29 10:15:58 -08:00
; Return 0 if walking onto land and tile permissions allow it.
; Otherwise, return carry.
2018-01-23 14:39:09 -08:00
ld a, [wTilePermissions]
2015-12-29 10:15:58 -08:00
ld d, a
2018-01-23 14:39:09 -08:00
ld a, [wFacingDirection]
2015-12-29 10:15:58 -08:00
and d
jr nz, .NotWalkable
ld a, [wWalkingTileCollision]
2015-12-29 10:15:58 -08:00
call .CheckWalkable
jr c, .NotWalkable
xor a
ret
.NotWalkable:
2015-12-29 10:15:58 -08:00
scf
ret
2018-06-24 07:09:41 -07:00
.CheckSurfPerms:
2015-12-29 10:15:58 -08:00
; Return 0 if moving in water, or 1 if moving onto land.
; Otherwise, return carry.
2018-01-23 14:39:09 -08:00
ld a, [wTilePermissions]
2015-12-29 10:15:58 -08:00
ld d, a
2018-01-23 14:39:09 -08:00
ld a, [wFacingDirection]
2015-12-29 10:15:58 -08:00
and d
jr nz, .NotSurfable
ld a, [wWalkingTileCollision]
2015-12-29 10:15:58 -08:00
call .CheckSurfable
jr c, .NotSurfable
and a
ret
.NotSurfable:
2015-12-29 10:15:58 -08:00
scf
ret
2018-06-24 07:09:41 -07:00
.BikeCheck:
2018-01-23 14:39:09 -08:00
ld a, [wPlayerState]
2015-12-29 10:15:58 -08:00
cp PLAYER_BIKE
ret z
cp PLAYER_SKATE
2015-12-29 10:15:58 -08:00
ret
2018-06-24 07:09:41 -07:00
.CheckWalkable:
2015-12-29 10:15:58 -08:00
; Return 0 if tile a is land. Otherwise, return carry.
call GetTilePermission
and a ; LAND_TILE
2015-12-29 10:15:58 -08:00
ret z
cp SPACE_TILE
ret z
2015-12-29 10:15:58 -08:00
scf
ret
2018-06-24 07:09:41 -07:00
.CheckSurfable:
2015-12-29 10:15:58 -08:00
; Return 0 if tile a is water, or 1 if land.
; Otherwise, return carry.
call GetTilePermission
cp WATER_TILE
2015-12-29 10:15:58 -08:00
jr z, .Water
; because this is called during PLAYER_SURF or PLAYER_SURF_PIKA state,
; SPACE_TILE is considered still water. Do not stop surfing on a space tile.
cp SPACE_TILE
jr z, .Water
2015-12-29 10:15:58 -08:00
; Can walk back onto land from water.
and a ; LAND_TILE
2015-12-29 10:15:58 -08:00
jr z, .Land
jr .Neither
.Water:
2015-12-29 10:15:58 -08:00
xor a
ret
.Land:
2015-12-29 10:15:58 -08:00
ld a, 1
and a
ret
.Neither:
2015-12-29 10:15:58 -08:00
scf
ret
2018-06-24 07:09:41 -07:00
.GetOutOfWater:
2015-12-29 10:15:58 -08:00
push bc
ld a, PLAYER_NORMAL
2018-01-23 14:39:09 -08:00
ld [wPlayerState], a
call UpdatePlayerSprite ; UpdateSprites
2015-12-29 10:15:58 -08:00
pop bc
ret
2018-06-24 07:09:41 -07:00
CheckStandingOnIce::
2016-05-14 10:46:14 -07:00
ld a, [wPlayerTurningDirection]
2015-12-29 10:15:58 -08:00
cp 0
jr z, .not_ice
cp $f0
jr z, .not_ice
ld a, [wPlayerTileCollision]
2015-12-29 10:15:58 -08:00
call CheckIceTile
jr nc, .yep
2018-01-23 14:39:09 -08:00
ld a, [wPlayerState]
cp PLAYER_SKATE
2015-12-29 10:15:58 -08:00
jr nz, .not_ice
.yep
scf
ret
.not_ice
and a
ret
2018-06-24 07:09:41 -07:00
StopPlayerForEvent::
2015-12-29 10:15:58 -08:00
ld hl, wPlayerNextMovement
2016-05-14 09:28:00 -07:00
ld a, movement_step_sleep
2015-12-29 10:15:58 -08:00
cp [hl]
ret z
ld [hl], a
ld a, 0
2016-05-14 10:46:14 -07:00
ld [wPlayerTurningDirection], a
2015-12-29 10:15:58 -08:00
ret