ref: ac78dda7d8a4a6cf9af95f601bdac9fc348c65a6
parent: 7b676f5851a2b6fe0001f259afde6e9918b93683
author: YamaArashi <shadow962@live.com>
date: Wed Jul 15 09:58:21 EDT 2015
more movement stuff
--- a/engine/overworld/movement.asm
+++ b/engine/overworld/movement.asm
@@ -188,7 +188,7 @@
call LoadDEPlusA ; a = [wNPCMovementDirections + $fe] (?)
jr .determineDirection
.randomMovement
- call getTileSpriteStandsOn
+ call GetTileSpriteStandsOn
call Random
.determineDirection
ld b, a
@@ -504,7 +504,7 @@
.skipXVisibilityTest
; make the sprite invisible if a text box is in front of it
; $5F is the maximum number for map tiles
- call getTileSpriteStandsOn
+ call GetTileSpriteStandsOn
ld d, $60
ld a, [hli]
cp d
@@ -685,7 +685,7 @@
; calculates the tile pointer pointing to the tile the current sprite stancs on
; this is always the lower left tile of the 2x2 tile blocks all sprites are snapped to
; hl: output pointer
-getTileSpriteStandsOn: ; 5207 (1:5207)
+GetTileSpriteStandsOn: ; 5207 (1:5207)
ld h, $c1
ld a, [H_CURRENTSPRITEOFFSET]
add $4
@@ -724,6 +724,10 @@
ret
DoScriptedNPCMovement: ; 5236 (1:5236)
+; This is an alternative method of scripting an NPC's movement and is only used
+; a few times in the game. It is used when the NPC and player must walk together
+; in sync, such as when the player is following the NPC somewhere. An NPC can't
+; be moved in sync with the player using the other method.
ld a, [wd730]
bit 7, a
ret z
@@ -740,7 +744,7 @@
.noCarry
ld a, [hl]
; check if moving up
- cp $40
+ cp NPC_MOVEMENT_UP
jr nz, .checkIfMovingDown
call GetSpriteScreenYPointer
ld c, SPRITE_FACING_UP
@@ -747,7 +751,7 @@
ld a, -2
jr .move
.checkIfMovingDown
- cp $0
+ cp NPC_MOVEMENT_DOWN
jr nz, .checkIfMovingLeft
call GetSpriteScreenYPointer
ld c, SPRITE_FACING_DOWN
@@ -754,7 +758,7 @@
ld a, 2
jr .move
.checkIfMovingLeft
- cp $80
+ cp NPC_MOVEMENT_LEFT
jr nz, .checkIfMovingRight
call GetSpriteScreenXPointer
ld c, SPRITE_FACING_LEFT
@@ -761,7 +765,7 @@
ld a, -2
jr .move
.checkIfMovingRight
- cp $c0
+ cp NPC_MOVEMENT_RIGHT
jr nz, .noMatch
call GetSpriteScreenXPointer
ld c, SPRITE_FACING_RIGHT
@@ -781,11 +785,11 @@
ld a, c
ld [hl], a ; facing direction
call AnimScriptedNPCMovement
- ld hl, wcf18
+ ld hl, wScriptedNPCWalkCounter
dec [hl]
ret nz
- ld a, $8
- ld [wcf18], a
+ ld a, 8
+ ld [wScriptedNPCWalkCounter], a
ld hl, wNPCMovementDirections2Index
inc [hl]
ret
@@ -793,8 +797,8 @@
InitScriptedNPCMovement: ; 52a6 (1:52a6)
xor a
ld [wNPCMovementDirections2Index], a
- ld a, $8
- ld [wcf18], a
+ ld a, 8
+ ld [wScriptedNPCWalkCounter], a
jp AnimScriptedNPCMovement
GetSpriteScreenYPointer: ; 52b2 (1:52b2)
--- a/engine/overworld/npc_movement.asm
+++ b/engine/overworld/npc_movement.asm
@@ -44,22 +44,25 @@
ld [wSimulatedJoypadStatesEnd], a
ret
-ProfOakMovementScriptPointerTable: ; 1a442 (6:6442)
- dw Func_1a44c
- dw Func_1a485
- dw Func_1a4a1
- dw Func_1a4a6
- dw Func_1a4f4
+PalletMovementScriptPointerTable: ; 1a442 (6:6442)
+ dw PalletMovementScript_OakMoveLeft
+ dw PalletMovementScript_PlayerMoveLeft
+ dw PalletMovementScript_WaitAndWalkToLab
+ dw PalletMovementScript_WalkToLab
+ dw PalletMovementScript_Done
-Func_1a44c: ; 1a44c (6:644c)
+PalletMovementScript_OakMoveLeft: ; 1a44c (6:644c)
ld a, [W_XCOORD]
sub $a
- ld [wcca1], a
- jr z, .asm_1a475
- ld b, $0
+ ld [wNumStepsToTake], a
+ jr z, .playerOnLeftTile
+; The player is on the right tile of the northern path out of Pallet Town and
+; Prof. Oak is below.
+; Make Prof. Oak step to the left.
+ ld b, 0
ld c, a
ld hl, wNPCMovementDirections2
- ld a, $80
+ ld a, NPC_MOVEMENT_LEFT
call FillMemory
ld [hl], $ff
ld a, [wSpriteIndex]
@@ -68,11 +71,14 @@
call MoveSprite
ld a, $1
ld [wNPCMovementScriptFunctionNum], a
- jr .asm_1a47a
-.asm_1a475
+ jr .done
+; The player is on the left tile of the northern path out of Pallet Town and
+; Prof. Oak is below.
+; Prof. Oak is already on the right tile.
+.playerOnLeftTile
ld a, $3
ld [wNPCMovementScriptFunctionNum], a
-.asm_1a47a
+.done
ld hl, W_FLAGS_D733
set 1, [hl]
ld a, $fc
@@ -79,13 +85,13 @@
ld [wJoyIgnore], a
ret
-Func_1a485: ; 1a485 (6:6485)
+PalletMovementScript_PlayerMoveLeft: ; 1a485 (6:6485)
ld a, [wd730]
- bit 0, a
- ret nz
- ld a, [wcca1]
+ bit 0, a ; is an NPC being moved by a script?
+ ret nz ; return if Oak is still moving
+ ld a, [wNumStepsToTake]
ld [wSimulatedJoypadStatesIndex], a
- ld [$ff95], a
+ ld [hNPCMovementDirections2Index], a
predef ConvertNPCMovementDirectionsToJoypadMasks
call StartSimulatingJoypadStates
ld a, $2
@@ -92,12 +98,12 @@
ld [wNPCMovementScriptFunctionNum], a
ret
-Func_1a4a1: ; 1a4a1 (6:64a1)
+PalletMovementScript_WaitAndWalkToLab: ; 1a4a1 (6:64a1)
ld a, [wSimulatedJoypadStatesIndex]
- and a
+ and a ; is the player done moving left yet?
ret nz
-Func_1a4a6: ; 1a4a6 (6:64a6)
+PalletMovementScript_WalkToLab: ; 1a4a6 (6:64a6)
xor a
ld [wOverrideSimulatedJoypadStatesMask], a
ld a, [wSpriteIndex]
@@ -122,12 +128,12 @@
ret
RLEList_ProfOakWalkToLab: ; 1a4dc (6:64dc)
- db $00, $05
- db $80, $01
- db $00, $05
- db $C0, $03
- db $40, $01
- db $E0, $01
+ db NPC_MOVEMENT_DOWN, $05
+ db NPC_MOVEMENT_LEFT, $01
+ db NPC_MOVEMENT_DOWN, $05
+ db NPC_MOVEMENT_RIGHT, $03
+ db NPC_MOVEMENT_UP, $01
+ db $E0, $01 ; stand still
db $FF
RLEList_PlayerWalkToLab: ; 1a4e9 (6:64e9)
@@ -138,7 +144,7 @@
db D_DOWN, $06
db $FF
-Func_1a4f4: ; 1a4f4 (6:64f4)
+PalletMovementScript_Done: ; 1a4f4 (6:64f4)
ld a, [wSimulatedJoypadStatesIndex]
and a
ret nz
@@ -152,10 +158,10 @@
jp EndNPCMovementScript
PewterMuseumGuyMovementScriptPointerTable: ; 1a510 (6:6510)
- dw Func_1a514
- dw PewterMovementScriptDone
+ dw PewterMovementScript_WalkToMuseum
+ dw PewterMovementScript_Done
-Func_1a514: ; 1a514 (6:6514)
+PewterMovementScript_WalkToMuseum: ; 1a514 (6:6514)
ld a, BANK(Music_MuseumGuy)
ld [wc0ef], a
ld [wc0f0], a
@@ -191,13 +197,13 @@
db $FF
RLEList_PewterMuseumGuy: ; 1a562 (6:6562)
- db $40, $06
- db $80, $0D
- db $40, $03
- db $80, $01
+ db NPC_MOVEMENT_UP, $06
+ db NPC_MOVEMENT_LEFT, $0D
+ db NPC_MOVEMENT_UP, $03
+ db NPC_MOVEMENT_LEFT, $01
db $FF
-PewterMovementScriptDone: ; 1a56b (6:656b)
+PewterMovementScript_Done: ; 1a56b (6:656b)
ld a, [wSimulatedJoypadStatesIndex]
and a
ret nz
@@ -208,10 +214,10 @@
jp EndNPCMovementScript
PewterGymGuyMovementScriptPointerTable: ; 1a57d (6:657d)
- dw Func_1a581
- dw PewterMovementScriptDone
+ dw PewterMovementScript_WalkToGym
+ dw PewterMovementScript_Done
-Func_1a581: ; 1a581 (6:6581)
+PewterMovementScript_WalkToGym: ; 1a581 (6:6581)
ld a, BANK(Music_MuseumGuy)
ld [wc0ef], a
ld [wc0f0], a
@@ -252,12 +258,12 @@
db $FF
RLEList_PewterGymGuy: ; 1a5da (6:65da)
- db $00, $02
- db $80, $0F
- db $40, $05
- db $80, $0B
- db $00, $05
- db $C0, $03
+ db NPC_MOVEMENT_DOWN, $02
+ db NPC_MOVEMENT_LEFT, $0F
+ db NPC_MOVEMENT_UP, $05
+ db NPC_MOVEMENT_LEFT, $0B
+ db NPC_MOVEMENT_DOWN, $05
+ db NPC_MOVEMENT_RIGHT, $03
db $FF
FreezeEnemyTrainerSprite: ; 1a5e7 (6:65e7)
--- a/engine/overworld/oam.asm
+++ b/engine/overworld/oam.asm
@@ -16,10 +16,10 @@
ld [hOAMBufferOffset], a
.spriteLoop
- ld [hSpriteDataOffset2], a
+ ld [hSpriteOffset2], a
ld d, wSpriteStateData1 / $100
- ld a, [hSpriteDataOffset2]
+ ld a, [hSpriteOffset2]
ld e, a
ld a, [de] ; c1x0
and a
@@ -139,7 +139,7 @@
ld [hOAMBufferOffset], a
.nextSprite
- ld a, [hSpriteDataOffset2]
+ ld a, [hSpriteOffset2]
add $10
cp $100 % $100
jp nz, .spriteLoop
--- a/home.asm
+++ b/home.asm
@@ -2195,7 +2195,7 @@
ld [MBC1RomBank], a
ret
.NPCMovementScriptPointerTables
- dw ProfOakMovementScriptPointerTable
+ dw PalletMovementScriptPointerTable
dw PewterMuseumGuyMovementScriptPointerTable
dw PewterGymGuyMovementScriptPointerTable
.playerStepOutFromDoor
@@ -3078,7 +3078,7 @@
ld [wWastedByteCD3A],a
ret
-; divides [$ffe5] by [$ffe6] and stores the quotient in [$ffe7]
+; divides [hDividend2] by [hDivisor2] and stores the quotient in [hQuotient2]
DivideBytes:: ; 366b (0:366b)
push hl
ld hl, $ffe7
--- a/hram.asm
+++ b/hram.asm
@@ -28,7 +28,7 @@
hHalveItemPrices EQU $FF8E
-hSpriteDataOffset2 EQU $FF8F
+hSpriteOffset2 EQU $FF8F
hOAMBufferOffset EQU $FF90
@@ -39,6 +39,11 @@
hSpritePriority EQU $FF94
+hNPCMovementDirections2Index EQU $FF95
+
+; CalcPositionOfPlayerRelativeToNPC
+hNPCSpriteOffset EQU $FF95
+
; Multiplcation and division variables are meant
; to overlap for back-to-back usage. Big endian.
@@ -57,6 +62,33 @@
H_POWEROFTEN EQU $FF99 ; 3 bytes
H_SAVEDNUMTOPRINT EQU $FF9C ; 3 bytes
+; distance in steps between NPC and player
+hNPCPlayerYDistance EQU $FF95
+hNPCPlayerXDistance EQU $FF96
+
+hFindPathNumSteps EQU $FF97
+
+; bit 0: set when the end of the path's Y coordinate matches the target's
+; bit 1: set when the end of the path's X coordinate matches the target's
+; When both bits are set, the end of the path is at the target's position
+; (i.e. the path has been found).
+hFindPathFlags EQU $FF98
+
+hFindPathYProgress EQU $FF99
+hFindPathXProgress EQU $FF9A
+
+; 0 = from player to NPC
+; 1 = from NPC to player
+hNPCPlayerRelativePosPerspective EQU $FF9B
+
+; bit 0:
+; 0 = target is to the south or aligned
+; 1 = target is to the north
+; bit 1:
+; 0 = target is to the east or aligned
+; 1 = target is to the west
+hNPCPlayerRelativePosFlags EQU $FF9D
+
hSerialReceivedNewData EQU $FFA9
; $01 = using external clock
@@ -165,6 +197,10 @@
hTilesetType EQU $FFD7
H_CURRENTSPRITEOFFSET EQU $FFDA ; multiple of $10
+
+hDividend2 EQU $FFE5
+hDivisor2 EQU $FFE6
+hQuotient2 EQU $FFE7
hSpriteVRAMSlotAndFacing EQU $FFE9
--- a/main.asm
+++ b/main.asm
@@ -4521,72 +4521,75 @@
FindPathToPlayer: ; f8ba (3:78ba)
xor a
- ld hl, $ff97
- ld [hli], a
- ld [hli], a
- ld [hli], a
- ld [hl], a
+ ld hl, hFindPathNumSteps
+ ld [hli], a ; hFindPathNumSteps
+ ld [hli], a ; hFindPathFlags
+ ld [hli], a ; hFindPathYProgress
+ ld [hl], a ; hFindPathXProgress
ld hl, wNPCMovementDirections2
ld de, $0
.loop
- ld a, [$ff99]
+ ld a, [hFindPathYProgress]
ld b, a
- ld a, [$ff95] ; Y distance in steps
+ ld a, [hNPCPlayerYDistance] ; Y distance in steps
call CalcDifference
ld d, a
and a
jr nz, .asm_f8da
- ld a, [$ff98]
- set 0, a
- ld [$ff98], a
+ ld a, [hFindPathFlags]
+ set 0, a ; current end of path matches the player's Y coordinate
+ ld [hFindPathFlags], a
.asm_f8da
- ld a, [$ff9a]
+ ld a, [hFindPathXProgress]
ld b, a
- ld a, [$ff96] ; X distance in steps
+ ld a, [hNPCPlayerXDistance] ; X distance in steps
call CalcDifference
ld e, a
and a
jr nz, .asm_f8ec
- ld a, [$ff98]
- set 1, a
- ld [$ff98], a
+ ld a, [hFindPathFlags]
+ set 1, a ; current end of path matches the player's X coordinate
+ ld [hFindPathFlags], a
.asm_f8ec
- ld a, [$ff98]
- cp $3
+ ld a, [hFindPathFlags]
+ cp $3 ; has the end of the path reached the player's position?
jr z, .done
+; Compare whether the X distance between the player and the current of the path
+; is greater or if the Y distance is. Then, try to reduce whichever is greater.
ld a, e
cp d
- jr c, .asm_f90a
- ld a, [$ff9d]
+ jr c, .yDistanceGreater
+; x distance is greater
+ ld a, [hNPCPlayerRelativePosFlags]
bit 1, a
- jr nz, .asm_f900
+ jr nz, .playerIsLeftOfNPC
ld d, NPC_MOVEMENT_RIGHT
- jr .asm_f902
-.asm_f900
+ jr .next1
+.playerIsLeftOfNPC
ld d, NPC_MOVEMENT_LEFT
-.asm_f902
- ld a, [$ff9a]
- add $1
- ld [$ff9a], a
- jr .asm_f91c
-.asm_f90a
- ld a, [$ff9d]
+.next1
+ ld a, [hFindPathXProgress]
+ add 1
+ ld [hFindPathXProgress], a
+ jr .storeDirection
+.yDistanceGreater
+ ld a, [hNPCPlayerRelativePosFlags]
bit 0, a
- jr nz, .asm_f914
+ jr nz, .playerIsAboveNPC
ld d, NPC_MOVEMENT_DOWN
- jr .asm_f916
-.asm_f914
+ jr .next2
+.playerIsAboveNPC
ld d, NPC_MOVEMENT_UP
-.asm_f916
- ld a, [$ff99]
- add $1
- ld [$ff99], a
-.asm_f91c
+.next2
+ ld a, [hFindPathYProgress]
+ add 1
+ ld [hFindPathYProgress], a
+.storeDirection
ld a, d
ld [hli], a
- ld a, [$ff97]
+ ld a, [hFindPathNumSteps]
inc a
- ld [$ff97], a
+ ld [hFindPathNumSteps], a
jp .loop
.done
ld [hl], $ff
@@ -4594,13 +4597,13 @@
CalcPositionOfPlayerRelativeToNPC: ; f929 (3:7929)
xor a
- ld [$ff9d], a
+ ld [hNPCPlayerRelativePosFlags], a
ld a, [wSpriteStateData1 + 4] ; player's sprite screen Y position in pixels
ld d, a
ld a, [wSpriteStateData1 + 6] ; player's sprite screen X position in pixels
ld e, a
ld hl, wSpriteStateData1
- ld a, [$ff95] ; sprite offset
+ ld a, [hNPCSpriteOffset]
add l
add $4
ld l, a
@@ -4614,7 +4617,7 @@
jr nc, .NPCSouthOfOrAlignedWithPlayer
.NPCNorthOfPlayer
push hl
- ld hl, $ff9d
+ ld hl, hNPCPlayerRelativePosFlags
bit 0, [hl]
set 0, [hl]
pop hl
@@ -4621,19 +4624,19 @@
jr .divideYDistance
.NPCSouthOfOrAlignedWithPlayer
push hl
- ld hl, $ff9d
+ ld hl, hNPCPlayerRelativePosFlags
bit 0, [hl]
res 0, [hl]
pop hl
.divideYDistance
push hl
- ld hl, $ffe5
+ ld hl, hDividend2
ld [hli], a
ld a, 16
ld [hli], a
call DivideBytes ; divide Y absolute distance by 16
ld a, [hl] ; quotient
- ld [$ff95], a
+ ld [hNPCPlayerYDistance], a
pop hl
inc hl
ld b, e
@@ -4642,7 +4645,7 @@
jr nc, .NPCEastOfOrAlignedWithPlayer
.NPCWestOfPlayer
push hl
- ld hl, $ff9d
+ ld hl, hNPCPlayerRelativePosFlags
bit 1, [hl]
set 1, [hl]
pop hl
@@ -4649,28 +4652,28 @@
jr .divideXDistance
.NPCEastOfOrAlignedWithPlayer
push hl
- ld hl, $ff9d
+ ld hl, hNPCPlayerRelativePosFlags
bit 1, [hl]
res 1, [hl]
pop hl
.divideXDistance
- ld [$ffe5], a
+ ld [hDividend2], a
ld a, 16
- ld [$ffe6], a
+ ld [hDivisor2], a
call DivideBytes ; divide X absolute distance by 16
- ld a, [$ffe7] ; quotient
- ld [$ff96], a
- ld a, [$ff9b]
+ ld a, [hQuotient2]
+ ld [hNPCPlayerXDistance], a
+ ld a, [hNPCPlayerRelativePosPerspective]
and a
ret z
- ld a, [$ff9d]
+ ld a, [hNPCPlayerRelativePosFlags]
cpl
and $3
- ld [$ff9d], a
+ ld [hNPCPlayerRelativePosFlags], a
ret
ConvertNPCMovementDirectionsToJoypadMasks: ; f9a0 (3:79a0)
- ld a, [$ff95]
+ ld a, [hNPCMovementDirections2Index]
ld [wNPCMovementDirections2Index], a
dec a
ld de, wSimulatedJoypadStatesEnd
@@ -4684,9 +4687,9 @@
call ConvertNPCMovementDirectionToJoypadMask
ld [de], a
inc de
- ld a, [$ff95]
+ ld a, [hNPCMovementDirections2Index]
dec a
- ld [$ff95], a
+ ld [hNPCMovementDirections2Index], a
jr nz, .loop
ret
--- a/scripts/oakslab.asm
+++ b/scripts/oakslab.asm
@@ -333,14 +333,14 @@
ld [$ff8c], a
call DisplayTextID
ld a, $1
- ld [$ff9b], a
+ ld [hNPCPlayerRelativePosPerspective], a
ld a, $1
swap a
- ld [$ff95], a
+ ld [hNPCSpriteOffset], a
predef CalcPositionOfPlayerRelativeToNPC
- ld a, [$ff95]
+ ld a, [hNPCPlayerYDistance]
dec a
- ld [$ff95], a
+ ld [hNPCPlayerYDistance], a
predef FindPathToPlayer
ld de, wNPCMovementDirections2
ld a, $1
--- a/scripts/pallettown.asm
+++ b/scripts/pallettown.asm
@@ -33,7 +33,7 @@
ld a,$FF
call PlaySound ; stop music
ld a, BANK(Music_MeetProfOak)
- ld c,a ; song bank
+ ld c,a
ld a, MUSIC_MEET_PROF_OAK ; “oak appears” music
call PlayMusic
ld a,$FC
@@ -50,7 +50,7 @@
xor a
ld [wcf0d],a
ld a,1
- ld [$FF8C],a
+ ld [hSpriteIndexOrTextID],a
call DisplayTextID
ld a,$FF
ld [wJoyIgnore],a
@@ -65,8 +65,8 @@
PalletTownScript2: ; 18ed2 (6:4ed2)
ld a,1
- ld [$FF8C],a
- ld a,4
+ ld [H_SPRITEINDEX],a
+ ld a,SPRITE_FACING_UP
ld [$FF8D],a
call SetSpriteFacingDirectionAndDelay
call Delay3
@@ -73,17 +73,17 @@
ld a,1
ld [W_YCOORD],a
ld a,1
- ld [$FF9B],a
+ ld [hNPCPlayerRelativePosPerspective],a
ld a,1
swap a
- ld [$FF95],a
+ ld [hNPCSpriteOffset],a
predef CalcPositionOfPlayerRelativeToNPC
- ld hl,$FF95
+ ld hl,hNPCPlayerYDistance
dec [hl]
predef FindPathToPlayer ; load Oak’s movement into wNPCMovementDirections2
ld de,wNPCMovementDirections2
ld a,1 ; oak
- ld [$FF8C],a
+ ld [H_SPRITEINDEX],a
call MoveSprite
ld a,$FF
ld [wJoyIgnore],a
@@ -104,8 +104,9 @@
ld a,$FC
ld [wJoyIgnore],a
ld a,1
- ld [$FF8C],a
+ ld [hSpriteIndexOrTextID],a
call DisplayTextID
+; set up movement script that causes the player to follow Oak to his lab
ld a,$FF
ld [wJoyIgnore],a
ld a,1
@@ -124,7 +125,7 @@
PalletTownScript4: ; 18f4b (6:4f4b)
ld a,[wNPCMovementScriptPointerTableNum]
- and a
+ and a ; is the movement script over?
ret nz
; trigger the next script
--- a/wram.asm
+++ b/wram.asm
@@ -390,7 +390,9 @@
; temporary buffer when swapping party mon data
ds 10
-wcca1:: ds 49 ; used in overworld npc movement
+wNumStepsToTake:: ; cca1
+; used in Pallet Town scripted movement
+ ds 49
wRLEByteCount:: ; ccd2
ds 1
@@ -988,7 +990,10 @@
; sprite offset of sprite being controlled by NPC movement script
ds 1
-wcf18:: ds 2 ; used with overworld movement
+wScriptedNPCWalkCounter:: ; cf18
+ ds 1
+
+ ds 1
wGBC:: ; cf1a
ds 1