pathfinding.asm 4.0 KB

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