1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
|
FindPathToPlayer:
xor 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, [hFindPathYProgress]
ld b, a
ld a, [hNPCPlayerYDistance] ; Y distance in steps
call CalcDifference
ld d, a
and a
jr nz, .asm_f8da
ld a, [hFindPathFlags]
set 0, a ; current end of path matches the player's Y coordinate
ld [hFindPathFlags], a
.asm_f8da
ld a, [hFindPathXProgress]
ld b, a
ld a, [hNPCPlayerXDistance] ; X distance in steps
call CalcDifference
ld e, a
and a
jr nz, .asm_f8ec
ld a, [hFindPathFlags]
set 1, a ; current end of path matches the player's X coordinate
ld [hFindPathFlags], a
.asm_f8ec
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, .yDistanceGreater
; x distance is greater
ld a, [hNPCPlayerRelativePosFlags]
bit 1, a
jr nz, .playerIsLeftOfNPC
ld d, NPC_MOVEMENT_RIGHT
jr .next1
.playerIsLeftOfNPC
ld d, NPC_MOVEMENT_LEFT
.next1
ld a, [hFindPathXProgress]
add 1
ld [hFindPathXProgress], a
jr .storeDirection
.yDistanceGreater
ld a, [hNPCPlayerRelativePosFlags]
bit 0, a
jr nz, .playerIsAboveNPC
ld d, NPC_MOVEMENT_DOWN
jr .next2
.playerIsAboveNPC
ld d, NPC_MOVEMENT_UP
.next2
ld a, [hFindPathYProgress]
add 1
ld [hFindPathYProgress], a
.storeDirection
ld a, d
ld [hli], a
ld a, [hFindPathNumSteps]
inc a
ld [hFindPathNumSteps], a
jp .loop
.done
ld [hl], $ff
ret
CalcPositionOfPlayerRelativeToNPC:
xor 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, [hNPCSpriteOffset]
add l
add $4
ld l, a
jr nc, .noCarry
inc h
.noCarry
ld a, d
ld b, a
ld a, [hli] ; NPC sprite screen Y position in pixels
call CalcDifference
jr nc, .NPCSouthOfOrAlignedWithPlayer
.NPCNorthOfPlayer
push hl
ld hl, hNPCPlayerRelativePosFlags
bit 0, [hl]
set 0, [hl]
pop hl
jr .divideYDistance
.NPCSouthOfOrAlignedWithPlayer
push hl
ld hl, hNPCPlayerRelativePosFlags
bit 0, [hl]
res 0, [hl]
pop hl
.divideYDistance
push hl
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 [hNPCPlayerYDistance], a
pop hl
inc hl
ld b, e
ld a, [hl] ; NPC sprite screen X position in pixels
call CalcDifference
jr nc, .NPCEastOfOrAlignedWithPlayer
.NPCWestOfPlayer
push hl
ld hl, hNPCPlayerRelativePosFlags
bit 1, [hl]
set 1, [hl]
pop hl
jr .divideXDistance
.NPCEastOfOrAlignedWithPlayer
push hl
ld hl, hNPCPlayerRelativePosFlags
bit 1, [hl]
res 1, [hl]
pop hl
.divideXDistance
ld [hDividend2], a
ld a, 16
ld [hDivisor2], a
call DivideBytes ; divide X absolute distance by 16
ld a, [hQuotient2]
ld [hNPCPlayerXDistance], a
ld a, [hNPCPlayerRelativePosPerspective]
and a
ret z
ld a, [hNPCPlayerRelativePosFlags]
cpl
and $3
ld [hNPCPlayerRelativePosFlags], a
ret
ConvertNPCMovementDirectionsToJoypadMasks:
ld a, [hNPCMovementDirections2Index]
ld [wNPCMovementDirections2Index], a
dec a
ld de, wSimulatedJoypadStatesEnd
ld hl, wNPCMovementDirections2
add l
ld l, a
jr nc, .loop
inc h
.loop
ld a, [hld]
call ConvertNPCMovementDirectionToJoypadMask
ld [de], a
inc de
ld a, [hNPCMovementDirections2Index]
dec a
ld [hNPCMovementDirections2Index], a
jr nz, .loop
ret
ConvertNPCMovementDirectionToJoypadMask:
push hl
ld b, a
ld hl, NPCMovementDirectionsToJoypadMasksTable
.loop
ld a, [hli]
cp $ff
jr z, .done
cp b
jr z, .loadJoypadMask
inc hl
jr .loop
.loadJoypadMask
ld a, [hl]
.done
pop hl
ret
NPCMovementDirectionsToJoypadMasksTable:
db NPC_MOVEMENT_UP, D_UP
db NPC_MOVEMENT_DOWN, D_DOWN
db NPC_MOVEMENT_LEFT, D_LEFT
db NPC_MOVEMENT_RIGHT, D_RIGHT
db $ff
; unreferenced
ret
|