mirror of
https://gitlab.com/xCrystal/pokecrystal-board.git
synced 2024-11-16 11:27:33 -08:00
1220 lines
20 KiB
NASM
1220 lines
20 KiB
NASM
BlankScreen:
|
|
call DisableSpriteUpdates
|
|
xor a
|
|
ldh [hBGMapMode], a
|
|
call ClearBGPalettes
|
|
call ClearSprites
|
|
hlcoord 0, 0
|
|
ld bc, wTilemapEnd - wTilemap
|
|
ld a, " "
|
|
call ByteFill
|
|
hlcoord 0, 0, wAttrmap
|
|
ld bc, wAttrmapEnd - wAttrmap
|
|
ld a, $7
|
|
call ByteFill
|
|
call WaitBGMap2
|
|
call SetPalettes
|
|
ret
|
|
|
|
SpawnPlayer:
|
|
ld a, -1
|
|
ld [wObjectFollow_Leader], a
|
|
ld [wObjectFollow_Follower], a
|
|
ld a, PLAYER
|
|
ld hl, PlayerObjectTemplate
|
|
call CopyPlayerObjectTemplate
|
|
ld b, PLAYER
|
|
call PlayerSpawn_ConvertCoords
|
|
ld a, PLAYER_OBJECT
|
|
call GetMapObject
|
|
ld hl, MAPOBJECT_PALETTE
|
|
add hl, bc
|
|
ln e, PAL_NPC_RED, OBJECTTYPE_SCRIPT
|
|
ld a, [wPlayerSpriteSetupFlags]
|
|
bit PLAYERSPRITESETUP_FEMALE_TO_MALE_F, a
|
|
jr nz, .ok
|
|
ld a, [wPlayerGender]
|
|
bit PLAYERGENDER_FEMALE_F, a
|
|
jr z, .ok
|
|
ln e, PAL_NPC_BLUE, OBJECTTYPE_SCRIPT
|
|
|
|
.ok
|
|
ld [hl], e
|
|
ld a, PLAYER_OBJECT
|
|
ldh [hMapObjectIndex], a
|
|
ld bc, wMapObjects
|
|
ld a, PLAYER_OBJECT
|
|
ldh [hObjectStructIndex], a
|
|
ld de, wObjectStructs
|
|
call CopyMapObjectToObjectStruct
|
|
ld a, PLAYER
|
|
ld [wCenteredObject], a
|
|
ret
|
|
|
|
PlayerObjectTemplate:
|
|
; A dummy map object used to initialize the player object.
|
|
; Shorter than the actual amount copied by two bytes.
|
|
; Said bytes seem to be unused.
|
|
object_event -4, -4, SPRITE_CHRIS, SPRITEMOVEDATA_PLAYER, 15, 15, -1, -1, 0, OBJECTTYPE_SCRIPT, 0, 0, -1
|
|
|
|
CopyDECoordsToMapObject::
|
|
push de
|
|
ld a, b
|
|
call GetMapObject
|
|
pop de
|
|
ld hl, MAPOBJECT_X_COORD
|
|
add hl, bc
|
|
ld [hl], d
|
|
ld hl, MAPOBJECT_Y_COORD
|
|
add hl, bc
|
|
ld [hl], e
|
|
ret
|
|
|
|
PlayerSpawn_ConvertCoords:
|
|
push bc
|
|
ld a, [wXCoord]
|
|
add 4
|
|
ld d, a
|
|
ld a, [wYCoord]
|
|
add 4
|
|
ld e, a
|
|
pop bc
|
|
call CopyDECoordsToMapObject
|
|
ret
|
|
|
|
WriteObjectXY::
|
|
ld a, b
|
|
call CheckObjectVisibility
|
|
ret c
|
|
|
|
ld hl, OBJECT_MAP_X
|
|
add hl, bc
|
|
ld d, [hl]
|
|
ld hl, OBJECT_MAP_Y
|
|
add hl, bc
|
|
ld e, [hl]
|
|
ldh a, [hMapObjectIndex]
|
|
ld b, a
|
|
call CopyDECoordsToMapObject
|
|
and a
|
|
ret
|
|
|
|
RefreshPlayerCoords::
|
|
ld a, [wXCoord]
|
|
add 4
|
|
ld d, a
|
|
ld hl, wPlayerMapX
|
|
sub [hl]
|
|
ld [hl], d
|
|
ld hl, wMapObjects + MAPOBJECT_X_COORD
|
|
ld [hl], d
|
|
ld hl, wPlayerLastMapX
|
|
ld [hl], d
|
|
ld d, a
|
|
ld a, [wYCoord]
|
|
add 4
|
|
ld e, a
|
|
ld hl, wPlayerMapY
|
|
sub [hl]
|
|
ld [hl], e
|
|
ld hl, wMapObjects + MAPOBJECT_Y_COORD
|
|
ld [hl], e
|
|
ld hl, wPlayerLastMapY
|
|
ld [hl], e
|
|
ld e, a
|
|
; the next three lines are useless
|
|
ld a, [wObjectFollow_Leader]
|
|
cp PLAYER
|
|
ret nz
|
|
ret
|
|
|
|
CopyObjectStruct::
|
|
call CheckObjectMask
|
|
and a
|
|
ret nz ; masked
|
|
|
|
ld hl, wObjectStructs + OBJECT_LENGTH * 1
|
|
ld a, 1
|
|
ld de, OBJECT_LENGTH
|
|
.loop
|
|
ldh [hObjectStructIndex], a
|
|
ld a, [hl]
|
|
and a
|
|
jr z, .done
|
|
add hl, de
|
|
ldh a, [hObjectStructIndex]
|
|
inc a
|
|
cp NUM_OBJECT_STRUCTS
|
|
jr nz, .loop
|
|
scf
|
|
ret ; overflow
|
|
|
|
.done
|
|
ld d, h
|
|
ld e, l
|
|
call CopyMapObjectToObjectStruct
|
|
ld hl, wVramState
|
|
bit 7, [hl]
|
|
ret z
|
|
|
|
ld hl, OBJECT_FLAGS2
|
|
add hl, de
|
|
set 5, [hl]
|
|
ret
|
|
|
|
CopyMapObjectToObjectStruct:
|
|
call .CopyMapObjectToTempObject
|
|
call CopyTempObjectToObjectStruct
|
|
ret
|
|
|
|
.CopyMapObjectToTempObject:
|
|
ldh a, [hObjectStructIndex]
|
|
ld hl, MAPOBJECT_OBJECT_STRUCT_ID
|
|
add hl, bc
|
|
ld [hl], a
|
|
|
|
ldh a, [hMapObjectIndex]
|
|
ld [wTempObjectCopyMapObjectIndex], a
|
|
|
|
ld hl, MAPOBJECT_SPRITE
|
|
add hl, bc
|
|
ld a, [hl]
|
|
ld [wTempObjectCopySprite], a
|
|
|
|
call GetSpriteVTile
|
|
ld [wTempObjectCopySpriteVTile], a
|
|
|
|
ld a, [hl]
|
|
call GetSpritePalette
|
|
ld [wTempObjectCopyPalette], a
|
|
|
|
ld hl, MAPOBJECT_PALETTE
|
|
add hl, bc
|
|
ld a, [hl]
|
|
and MAPOBJECT_PALETTE_MASK
|
|
jr z, .skip_color_override
|
|
swap a
|
|
and PALETTE_MASK
|
|
ld [wTempObjectCopyPalette], a
|
|
|
|
.skip_color_override
|
|
ld hl, MAPOBJECT_MOVEMENT
|
|
add hl, bc
|
|
ld a, [hl]
|
|
ld [wTempObjectCopyMovement], a
|
|
|
|
ld hl, MAPOBJECT_SIGHT_RANGE
|
|
add hl, bc
|
|
ld a, [hl]
|
|
ld [wTempObjectCopyRange], a
|
|
|
|
ld hl, MAPOBJECT_X_COORD
|
|
add hl, bc
|
|
ld a, [hl]
|
|
ld [wTempObjectCopyX], a
|
|
|
|
ld hl, MAPOBJECT_Y_COORD
|
|
add hl, bc
|
|
ld a, [hl]
|
|
ld [wTempObjectCopyY], a
|
|
|
|
ld hl, MAPOBJECT_RADIUS
|
|
add hl, bc
|
|
ld a, [hl]
|
|
ld [wTempObjectCopyRadius], a
|
|
ret
|
|
|
|
InitializeVisibleSprites:
|
|
ld bc, wMapObject1
|
|
ld a, 1
|
|
.loop
|
|
ldh [hMapObjectIndex], a
|
|
ld hl, MAPOBJECT_SPRITE
|
|
add hl, bc
|
|
ld a, [hl]
|
|
and a
|
|
jr z, .next
|
|
|
|
ld hl, MAPOBJECT_OBJECT_STRUCT_ID
|
|
add hl, bc
|
|
ld a, [hl]
|
|
cp -1
|
|
jr nz, .next
|
|
|
|
ld a, [wXCoord]
|
|
ld d, a
|
|
ld a, [wYCoord]
|
|
ld e, a
|
|
|
|
ld hl, MAPOBJECT_X_COORD
|
|
add hl, bc
|
|
ld a, [hl]
|
|
add 1
|
|
sub d
|
|
jr c, .next
|
|
|
|
cp MAPOBJECT_SCREEN_WIDTH
|
|
jr nc, .next
|
|
|
|
ld hl, MAPOBJECT_Y_COORD
|
|
add hl, bc
|
|
ld a, [hl]
|
|
add 1
|
|
sub e
|
|
jr c, .next
|
|
|
|
cp MAPOBJECT_SCREEN_HEIGHT
|
|
jr nc, .next
|
|
|
|
push bc
|
|
call CopyObjectStruct
|
|
pop bc
|
|
jp c, .ret
|
|
|
|
.next
|
|
ld hl, MAPOBJECT_LENGTH
|
|
add hl, bc
|
|
ld b, h
|
|
ld c, l
|
|
ldh a, [hMapObjectIndex]
|
|
inc a
|
|
cp NUM_OBJECTS
|
|
jr nz, .loop
|
|
ret
|
|
|
|
.ret
|
|
ret
|
|
|
|
CheckObjectEnteringVisibleRange::
|
|
nop
|
|
ld a, [wPlayerStepDirection]
|
|
cp STANDING
|
|
ret z
|
|
ld hl, .dw
|
|
rst JumpTable
|
|
ret
|
|
|
|
.dw
|
|
dw .Down
|
|
dw .Up
|
|
dw .Left
|
|
dw .Right
|
|
|
|
.Up:
|
|
ld a, [wYCoord]
|
|
sub 1
|
|
jr .Vertical
|
|
|
|
.Down:
|
|
ld a, [wYCoord]
|
|
add 9
|
|
.Vertical:
|
|
ld d, a
|
|
ld a, [wXCoord]
|
|
ld e, a
|
|
ld bc, wMapObject1
|
|
ld a, 1
|
|
.loop_v
|
|
ldh [hMapObjectIndex], a
|
|
ld hl, MAPOBJECT_SPRITE
|
|
add hl, bc
|
|
ld a, [hl]
|
|
and a
|
|
jr z, .next_v
|
|
ld hl, MAPOBJECT_Y_COORD
|
|
add hl, bc
|
|
ld a, d
|
|
cp [hl]
|
|
jr nz, .next_v
|
|
ld hl, MAPOBJECT_OBJECT_STRUCT_ID
|
|
add hl, bc
|
|
ld a, [hl]
|
|
cp -1
|
|
jr nz, .next_v
|
|
ld hl, MAPOBJECT_X_COORD
|
|
add hl, bc
|
|
ld a, [hl]
|
|
add 1
|
|
sub e
|
|
jr c, .next_v
|
|
cp MAPOBJECT_SCREEN_WIDTH
|
|
jr nc, .next_v
|
|
push de
|
|
push bc
|
|
call CopyObjectStruct
|
|
pop bc
|
|
pop de
|
|
|
|
.next_v
|
|
ld hl, MAPOBJECT_LENGTH
|
|
add hl, bc
|
|
ld b, h
|
|
ld c, l
|
|
ldh a, [hMapObjectIndex]
|
|
inc a
|
|
cp NUM_OBJECTS
|
|
jr nz, .loop_v
|
|
ret
|
|
|
|
.Left:
|
|
ld a, [wXCoord]
|
|
sub 1
|
|
jr .Horizontal
|
|
|
|
.Right:
|
|
ld a, [wXCoord]
|
|
add 10
|
|
.Horizontal:
|
|
ld e, a
|
|
ld a, [wYCoord]
|
|
ld d, a
|
|
ld bc, wMapObject1
|
|
ld a, 1
|
|
.loop_h
|
|
ldh [hMapObjectIndex], a
|
|
ld hl, MAPOBJECT_SPRITE
|
|
add hl, bc
|
|
ld a, [hl]
|
|
and a
|
|
jr z, .next_h
|
|
ld hl, MAPOBJECT_X_COORD
|
|
add hl, bc
|
|
ld a, e
|
|
cp [hl]
|
|
jr nz, .next_h
|
|
ld hl, MAPOBJECT_OBJECT_STRUCT_ID
|
|
add hl, bc
|
|
ld a, [hl]
|
|
cp -1
|
|
jr nz, .next_h
|
|
ld hl, MAPOBJECT_Y_COORD
|
|
add hl, bc
|
|
ld a, [hl]
|
|
add 1
|
|
sub d
|
|
jr c, .next_h
|
|
cp MAPOBJECT_SCREEN_HEIGHT
|
|
jr nc, .next_h
|
|
push de
|
|
push bc
|
|
call CopyObjectStruct
|
|
pop bc
|
|
pop de
|
|
|
|
.next_h
|
|
ld hl, MAPOBJECT_LENGTH
|
|
add hl, bc
|
|
ld b, h
|
|
ld c, l
|
|
ldh a, [hMapObjectIndex]
|
|
inc a
|
|
cp NUM_OBJECTS
|
|
jr nz, .loop_h
|
|
ret
|
|
|
|
CopyTempObjectToObjectStruct:
|
|
ld a, [wTempObjectCopyMapObjectIndex]
|
|
ld hl, OBJECT_MAP_OBJECT_INDEX
|
|
add hl, de
|
|
ld [hl], a
|
|
|
|
ld a, [wTempObjectCopyMovement]
|
|
call CopySpriteMovementData
|
|
|
|
ld a, [wTempObjectCopyPalette]
|
|
ld hl, OBJECT_PALETTE
|
|
add hl, de
|
|
or [hl]
|
|
ld [hl], a
|
|
|
|
ld a, [wTempObjectCopyY]
|
|
call .InitYCoord
|
|
|
|
ld a, [wTempObjectCopyX]
|
|
call .InitXCoord
|
|
|
|
ld a, [wTempObjectCopySprite]
|
|
ld hl, OBJECT_SPRITE
|
|
add hl, de
|
|
ld [hl], a
|
|
|
|
ld a, [wTempObjectCopySpriteVTile]
|
|
ld hl, OBJECT_SPRITE_TILE
|
|
add hl, de
|
|
ld [hl], a
|
|
|
|
ld hl, OBJECT_STEP_TYPE
|
|
add hl, de
|
|
ld [hl], STEP_TYPE_RESET
|
|
|
|
ld hl, OBJECT_FACING
|
|
add hl, de
|
|
ld [hl], STANDING
|
|
|
|
ld a, [wTempObjectCopyRadius]
|
|
call .InitRadius
|
|
|
|
ld a, [wTempObjectCopyRange]
|
|
ld hl, OBJECT_RANGE
|
|
add hl, de
|
|
ld [hl], a
|
|
|
|
and a
|
|
ret
|
|
|
|
.InitYCoord:
|
|
ld hl, OBJECT_INIT_Y
|
|
add hl, de
|
|
ld [hl], a
|
|
|
|
ld hl, OBJECT_MAP_Y
|
|
add hl, de
|
|
ld [hl], a
|
|
|
|
ld hl, wYCoord
|
|
sub [hl]
|
|
and $f
|
|
swap a
|
|
ld hl, wPlayerBGMapOffsetY
|
|
sub [hl]
|
|
ld hl, OBJECT_SPRITE_Y
|
|
add hl, de
|
|
ld [hl], a
|
|
ret
|
|
|
|
.InitXCoord:
|
|
ld hl, OBJECT_INIT_X
|
|
add hl, de
|
|
ld [hl], a
|
|
ld hl, OBJECT_MAP_X
|
|
add hl, de
|
|
ld [hl], a
|
|
ld hl, wXCoord
|
|
sub [hl]
|
|
and $f
|
|
swap a
|
|
ld hl, wPlayerBGMapOffsetX
|
|
sub [hl]
|
|
ld hl, OBJECT_SPRITE_X
|
|
add hl, de
|
|
ld [hl], a
|
|
ret
|
|
|
|
.InitRadius:
|
|
ld h, a
|
|
inc a
|
|
and $f
|
|
ld l, a
|
|
ld a, h
|
|
add $10
|
|
and $f0
|
|
or l
|
|
ld hl, OBJECT_RADIUS
|
|
add hl, de
|
|
ld [hl], a
|
|
ret
|
|
|
|
TrainerOrTalkerWalkToPlayer:
|
|
ldh a, [hLastTalked]
|
|
call InitMovementBuffer
|
|
ld a, movement_step_sleep
|
|
call AppendToMovementBuffer
|
|
ld a, [wSeenTrainerOrTalkerDistance]
|
|
dec a
|
|
jr z, .TerminateStep
|
|
ldh a, [hLastTalked]
|
|
ld b, a
|
|
ld c, PLAYER
|
|
ld d, 1
|
|
call .GetPathToPlayer
|
|
call DecrementMovementBufferCount
|
|
|
|
.TerminateStep:
|
|
ld a, movement_step_end
|
|
call AppendToMovementBuffer
|
|
ret
|
|
|
|
.GetPathToPlayer:
|
|
push de
|
|
push bc
|
|
; get player object struct, load to de
|
|
ld a, c
|
|
call GetMapObject
|
|
ld hl, MAPOBJECT_OBJECT_STRUCT_ID
|
|
add hl, bc
|
|
ld a, [hl]
|
|
call GetObjectStruct
|
|
ld d, b
|
|
ld e, c
|
|
|
|
; get last talked object struct, load to bc
|
|
pop bc
|
|
ld a, b
|
|
call GetMapObject
|
|
ld hl, MAPOBJECT_OBJECT_STRUCT_ID
|
|
add hl, bc
|
|
ld a, [hl]
|
|
call GetObjectStruct
|
|
|
|
; get last talked coords, load to bc
|
|
ld hl, OBJECT_MAP_X
|
|
add hl, bc
|
|
ld a, [hl]
|
|
ld hl, OBJECT_MAP_Y
|
|
add hl, bc
|
|
ld c, [hl]
|
|
ld b, a
|
|
|
|
; get player coords, load to de
|
|
ld hl, OBJECT_MAP_X
|
|
add hl, de
|
|
ld a, [hl]
|
|
ld hl, OBJECT_MAP_Y
|
|
add hl, de
|
|
ld e, [hl]
|
|
ld d, a
|
|
|
|
pop af
|
|
call ComputePathToWalkToPlayer
|
|
ret
|
|
|
|
SurfStartStep:
|
|
call InitMovementBuffer
|
|
call .GetMovementData
|
|
call AppendToMovementBuffer
|
|
ld a, movement_step_end
|
|
call AppendToMovementBuffer
|
|
ret
|
|
|
|
.GetMovementData:
|
|
ld a, [wPlayerDirection]
|
|
srl a
|
|
srl a
|
|
maskbits NUM_DIRECTIONS
|
|
ld e, a
|
|
ld d, 0
|
|
ld hl, .movement_data
|
|
add hl, de
|
|
ld a, [hl]
|
|
ret
|
|
|
|
.movement_data
|
|
slow_step DOWN
|
|
slow_step UP
|
|
slow_step LEFT
|
|
slow_step RIGHT
|
|
|
|
FollowNotExact::
|
|
push bc
|
|
ld a, c
|
|
call CheckObjectVisibility
|
|
ld d, b
|
|
ld e, c
|
|
pop bc
|
|
ret c
|
|
|
|
ld a, b
|
|
call CheckObjectVisibility
|
|
ret c
|
|
|
|
; object 2 is now in bc, object 1 is now in de
|
|
ld hl, OBJECT_MAP_X
|
|
add hl, bc
|
|
ld a, [hl]
|
|
ld hl, OBJECT_MAP_Y
|
|
add hl, bc
|
|
ld c, [hl]
|
|
ld b, a
|
|
|
|
ld hl, OBJECT_MAP_X
|
|
add hl, de
|
|
ld a, [hl]
|
|
cp b
|
|
jr z, .same_x
|
|
jr c, .to_the_left
|
|
inc b
|
|
jr .continue
|
|
|
|
.to_the_left
|
|
dec b
|
|
jr .continue
|
|
|
|
.same_x
|
|
ld hl, OBJECT_MAP_Y
|
|
add hl, de
|
|
ld a, [hl]
|
|
cp c
|
|
jr z, .continue
|
|
jr c, .below
|
|
inc c
|
|
jr .continue
|
|
|
|
.below
|
|
dec c
|
|
|
|
.continue
|
|
ld hl, OBJECT_MAP_X
|
|
add hl, de
|
|
ld [hl], b
|
|
ld a, b
|
|
ld hl, wXCoord
|
|
sub [hl]
|
|
and $f
|
|
swap a
|
|
ld hl, wPlayerBGMapOffsetX
|
|
sub [hl]
|
|
ld hl, OBJECT_SPRITE_X
|
|
add hl, de
|
|
ld [hl], a
|
|
ld hl, OBJECT_MAP_Y
|
|
add hl, de
|
|
ld [hl], c
|
|
ld a, c
|
|
ld hl, wYCoord
|
|
sub [hl]
|
|
and $f
|
|
swap a
|
|
ld hl, wPlayerBGMapOffsetY
|
|
sub [hl]
|
|
ld hl, OBJECT_SPRITE_Y
|
|
add hl, de
|
|
ld [hl], a
|
|
ldh a, [hObjectStructIndex]
|
|
ld hl, OBJECT_RANGE
|
|
add hl, de
|
|
ld [hl], a
|
|
ld hl, OBJECT_MOVEMENT_TYPE
|
|
add hl, de
|
|
ld [hl], SPRITEMOVEDATA_FOLLOWNOTEXACT
|
|
ld hl, OBJECT_STEP_TYPE
|
|
add hl, de
|
|
ld [hl], STEP_TYPE_RESET
|
|
ret
|
|
|
|
GetRelativeFacing::
|
|
; Determines which way map object e would have to turn to face map object d. Returns carry if it's impossible for whatever reason.
|
|
ld a, d
|
|
call GetMapObject
|
|
ld hl, MAPOBJECT_OBJECT_STRUCT_ID
|
|
add hl, bc
|
|
ld a, [hl]
|
|
cp NUM_OBJECT_STRUCTS
|
|
jr nc, .carry
|
|
ld d, a
|
|
ld a, e
|
|
call GetMapObject
|
|
ld hl, MAPOBJECT_OBJECT_STRUCT_ID
|
|
add hl, bc
|
|
ld a, [hl]
|
|
cp NUM_OBJECT_STRUCTS
|
|
jr nc, .carry
|
|
ld e, a
|
|
call .GetFacing_e_relativeto_d
|
|
ret
|
|
|
|
.carry
|
|
scf
|
|
ret
|
|
|
|
.GetFacing_e_relativeto_d:
|
|
; Determines which way object e would have to turn to face object d. Returns carry if it's impossible.
|
|
; load the coordinates of object d into bc
|
|
ld a, d
|
|
call GetObjectStruct
|
|
ld hl, OBJECT_MAP_X
|
|
add hl, bc
|
|
ld a, [hl]
|
|
ld hl, OBJECT_MAP_Y
|
|
add hl, bc
|
|
ld c, [hl]
|
|
ld b, a
|
|
push bc
|
|
; load the coordinates of object e into de
|
|
ld a, e
|
|
call GetObjectStruct
|
|
ld hl, OBJECT_MAP_X
|
|
add hl, bc
|
|
ld d, [hl]
|
|
ld hl, OBJECT_MAP_Y
|
|
add hl, bc
|
|
ld e, [hl]
|
|
pop bc
|
|
; |x1 - x2|
|
|
ld a, b
|
|
sub d
|
|
jr z, .same_x_1
|
|
jr nc, .b_right_of_d_1
|
|
cpl
|
|
inc a
|
|
|
|
.b_right_of_d_1
|
|
; |y1 - y2|
|
|
ld h, a
|
|
ld a, c
|
|
sub e
|
|
jr z, .same_y_1
|
|
jr nc, .c_below_e_1
|
|
cpl
|
|
inc a
|
|
|
|
.c_below_e_1
|
|
; |y1 - y2| - |x1 - x2|
|
|
sub h
|
|
jr c, .same_y_1
|
|
|
|
.same_x_1
|
|
; compare the y coordinates
|
|
ld a, c
|
|
cp e
|
|
jr z, .same_x_and_y
|
|
jr c, .c_directly_below_e
|
|
; c directly above e
|
|
ld d, DOWN
|
|
and a
|
|
ret
|
|
|
|
.c_directly_below_e
|
|
ld d, UP
|
|
and a
|
|
ret
|
|
|
|
.same_y_1
|
|
ld a, b
|
|
cp d
|
|
jr z, .same_x_and_y
|
|
jr c, .b_directly_right_of_d
|
|
; b directly left of d
|
|
ld d, RIGHT
|
|
and a
|
|
ret
|
|
|
|
.b_directly_right_of_d
|
|
ld d, LEFT
|
|
and a
|
|
ret
|
|
|
|
.same_x_and_y
|
|
scf
|
|
ret
|
|
|
|
QueueFollowerFirstStep:
|
|
call .QueueFirstStep
|
|
jr c, .same
|
|
ld [wFollowMovementQueue], a
|
|
xor a
|
|
ld [wFollowerMovementQueueLength], a
|
|
ret
|
|
|
|
.same
|
|
ld a, -1
|
|
ld [wFollowerMovementQueueLength], a
|
|
ret
|
|
|
|
.QueueFirstStep:
|
|
ld a, [wObjectFollow_Leader]
|
|
call GetObjectStruct
|
|
ld hl, OBJECT_MAP_X
|
|
add hl, bc
|
|
ld d, [hl]
|
|
ld hl, OBJECT_MAP_Y
|
|
add hl, bc
|
|
ld e, [hl]
|
|
ld a, [wObjectFollow_Follower]
|
|
call GetObjectStruct
|
|
ld hl, OBJECT_MAP_X
|
|
add hl, bc
|
|
ld a, d
|
|
cp [hl]
|
|
jr z, .check_y
|
|
jr c, .left
|
|
and a
|
|
ld a, movement_step + RIGHT
|
|
ret
|
|
|
|
.left
|
|
and a
|
|
ld a, movement_step + LEFT
|
|
ret
|
|
|
|
.check_y
|
|
ld hl, OBJECT_MAP_Y
|
|
add hl, bc
|
|
ld a, e
|
|
cp [hl]
|
|
jr z, .same_xy
|
|
jr c, .up
|
|
and a
|
|
ld a, movement_step + DOWN
|
|
ret
|
|
|
|
.up
|
|
and a
|
|
ld a, movement_step + UP
|
|
ret
|
|
|
|
.same_xy
|
|
scf
|
|
ret
|
|
|
|
RepositionMockedPlayerObject::
|
|
; map setup command called by map setup script MAPSETUP_CONNECTION after LoadBlockData,
|
|
; once the new map blocks have been loaded to wOverworldMapBlocks.
|
|
; Only applies during BOARDEVENT_VIEW_MAP_MODE
|
|
ldh a, [hCurBoardEvent]
|
|
cp BOARDEVENT_VIEW_MAP_MODE
|
|
ret nz
|
|
|
|
; if map at wBeforeViewMapMapGroup, wBeforeViewMapMapNumber is not the current map,
|
|
; or a map connected to the current map, we are done.
|
|
ld hl, wBeforeViewMapMapGroup
|
|
ld a, [hli]
|
|
ld b, a
|
|
ld c, [hl] ; wBeforeViewMapMapNumber
|
|
ld a, [wMapGroup]
|
|
cp b
|
|
jr nz, .next_map_1
|
|
ld a, [wMapNumber]
|
|
cp c
|
|
jr z, MockPlayerObject
|
|
.next_map_1
|
|
ld a, [wNorthConnectedMapGroup]
|
|
cp b
|
|
jr nz, .next_map_2
|
|
ld a, [wNorthConnectedMapNumber]
|
|
cp c
|
|
ld a, 0 ; north connected map
|
|
jr z, .is_connected_map
|
|
.next_map_2
|
|
ld a, [wSouthConnectedMapGroup]
|
|
cp b
|
|
jr nz, .next_map_3
|
|
ld a, [wSouthConnectedMapNumber]
|
|
cp c
|
|
ld a, 1 ; south connected map
|
|
jr z, .is_connected_map
|
|
.next_map_3
|
|
ld a, [wWestConnectedMapGroup]
|
|
cp b
|
|
jr nz, .next_map_4
|
|
ld a, [wWestConnectedMapNumber]
|
|
cp c
|
|
ld a, 2 ; west connected map
|
|
jr z, .is_connected_map
|
|
.next_map_4
|
|
ld a, [wEastConnectedMapGroup]
|
|
cp b
|
|
ret nz
|
|
ld a, [wEastConnectedMapNumber]
|
|
cp c
|
|
ld a, 3 ; east connected map
|
|
ret nz
|
|
|
|
.is_connected_map
|
|
ld [wTempByteValue], a
|
|
ld hl, .got_sprite_coords
|
|
push hl
|
|
ld a, [wBeforeViewMapXCoord]
|
|
ld d, a
|
|
ld a, [wBeforeViewMapYCoord]
|
|
ld e, a
|
|
jumptable_bc .Jumptable, wTempByteValue
|
|
|
|
.Jumptable:
|
|
dw GetNorthConnectedSpriteCoords
|
|
dw GetSouthConnectedSpriteCoords
|
|
dw GetWestConnectedSpriteCoords
|
|
dw GetEastConnectedSpriteCoords
|
|
|
|
.got_sprite_coords
|
|
ret nc ; return if sprite is not in visible part of connected map
|
|
jr MockPlayerObject.loaded_player_mock_coords
|
|
|
|
MockPlayerObject::
|
|
ld hl, wBeforeViewMapYCoord
|
|
ld de, wPlayerMockYCoord
|
|
ld a, [hli]
|
|
ld [de], a
|
|
inc de
|
|
ld a, [hl]
|
|
ld [de], a
|
|
|
|
.loaded_player_mock_coords
|
|
; refresh wPlayerObjectYCoord and wPlayerObjectXCoord (not strictly necessary)
|
|
farcall RefreshPlayerCoords
|
|
; copy default sprite object to the last object struct
|
|
ld hl, .DefaultPlayerObject
|
|
ld de, wMapObject{d:LAST_OBJECT}
|
|
ld bc, OBJECT_EVENT_SIZE + 1
|
|
call CopyBytes
|
|
|
|
; adjust sprite id and palette number
|
|
ld hl, .PlayerObjectFields
|
|
.loop
|
|
ld a, [wPlayerGender]
|
|
cp [hl]
|
|
inc hl
|
|
jr nz, .next1
|
|
ld a, [wPlayerState]
|
|
cp [hl]
|
|
inc hl
|
|
jr nz, .next2
|
|
; found a match
|
|
ld a, [hli] ; sprite
|
|
ld [wMapObject{d:LAST_OBJECT}Sprite], a
|
|
ld a, [hl] ; palette | objecttype
|
|
ld [wMapObject{d:LAST_OBJECT}Palette], a ; also wMapObject{d:LAST_OBJECT}Type
|
|
jr .copy_player_coords
|
|
.next1
|
|
inc hl
|
|
.next2
|
|
inc hl
|
|
inc hl
|
|
ld a, [hl]
|
|
cp -1
|
|
jr nz, .loop
|
|
|
|
.copy_player_coords
|
|
; copy player's coordinates
|
|
ld hl, wPlayerMockYCoord
|
|
ld de, wMapObject{d:LAST_OBJECT}YCoord
|
|
ld a, [hli]
|
|
add 4
|
|
ld [de], a
|
|
inc de
|
|
ld a, [hl] ; wPlayerMockXCoord
|
|
add 4
|
|
ld [de], a ; wMapObject{d:LAST_OBJECT}XCoord
|
|
; set facing direction
|
|
ld a, [wBeforeViewMapDirection]
|
|
srl a
|
|
srl a
|
|
maskbits NUM_DIRECTIONS
|
|
ld b, SPRITEMOVEDATA_STANDING_DOWN
|
|
add b
|
|
ld [wMapObject{d:LAST_OBJECT}Movement], a
|
|
|
|
; display mocked player object
|
|
; it will go to the last wMapObjects slot and to whichever wObjectStructs slot
|
|
; wObjectStructs[n][MAPOBJECT_OBJECT_STRUCT_ID] links both structs
|
|
ld a, NUM_OBJECTS - 1
|
|
call UnmaskCopyMapObjectStruct
|
|
ret
|
|
|
|
.DefaultPlayerObject:
|
|
db -1 ; MAPOBJECT_OBJECT_STRUCT_ID
|
|
object_event 0, 0, SPRITE_CHRIS, SPRITEMOVEDATA_STANDING_DOWN, 0, 0, -1, -1, PAL_NPC_RED, OBJECTTYPE_SCRIPT, 0, ObjectEvent, -1
|
|
|
|
.PlayerObjectFields:
|
|
; [wPlayerGender], [wPlayerState], sprite id, palette
|
|
db 0, PLAYER_NORMAL, SPRITE_CHRIS, PAL_NPC_RED << 4 | OBJECTTYPE_SCRIPT
|
|
db 1 << PLAYERGENDER_FEMALE_F, PLAYER_NORMAL, SPRITE_KRIS, PAL_NPC_BLUE << 4 | OBJECTTYPE_SCRIPT
|
|
db 0, PLAYER_SURF, SPRITE_SURF, PAL_NPC_RED << 4 | OBJECTTYPE_SCRIPT
|
|
db 1 << PLAYERGENDER_FEMALE_F, PLAYER_SURF, SPRITE_SURF, PAL_NPC_BLUE << 4 | OBJECTTYPE_SCRIPT
|
|
db 0, PLAYER_BIKE, SPRITE_CHRIS_BIKE, PAL_NPC_RED << 4 | OBJECTTYPE_SCRIPT
|
|
db 1 << PLAYERGENDER_FEMALE_F, PLAYER_BIKE, SPRITE_KRIS_BIKE, PAL_NPC_BLUE << 4 | OBJECTTYPE_SCRIPT
|
|
db -1
|
|
|
|
GetSouthConnectedSpriteCoords:
|
|
; ycoord / 2 <= 2
|
|
ld a, e
|
|
srl a
|
|
cp 3
|
|
ret nc
|
|
; [wSouthConnectionStripLocation]
|
|
ld hl, wSouthConnectionStripLocation
|
|
ld a, [hli]
|
|
ld h, [hl]
|
|
ld l, a
|
|
; + (xcoord / 2)
|
|
srl d
|
|
ld b, 0
|
|
ld c, d
|
|
add hl, bc
|
|
; + ([wMapWidth] + 6) * ycoord / 2
|
|
ld a, [wMapWidth]
|
|
add 6
|
|
ld c, a
|
|
ld b, 0
|
|
srl e
|
|
ld a, e
|
|
and a
|
|
jr z, .done
|
|
.loop
|
|
add hl, bc
|
|
dec a
|
|
jr nz, .loop
|
|
.done
|
|
call ConvertConnectedOverworldMapBlockAddressToXYCoords
|
|
ret
|
|
|
|
GetNorthConnectedSpriteCoords:
|
|
; wNorthConnectedMapHeight >= 3
|
|
; ycoord / 2 >= ([wNorthConnectedMapHeight] - 3)
|
|
ld a, [wNorthConnectedMapHeight]
|
|
sub 3
|
|
jr c, .nope
|
|
ld c, a
|
|
ld a, e
|
|
srl a
|
|
sub c
|
|
jr c, .nope
|
|
ld e, a ; e = ycoord / 2 - ([wNorthConnectedMapHeight] - 3)
|
|
; [wNorthConnectionStripLocation]
|
|
ld hl, wNorthConnectionStripLocation
|
|
ld a, [hli]
|
|
ld h, [hl]
|
|
ld l, a
|
|
; + (xcoord / 2)
|
|
srl d
|
|
ld b, 0
|
|
ld c, d
|
|
add hl, bc
|
|
; + ([wMapWidth] + 6) * {ycoord / 2 - ([wNorthConnectedMapHeight] - 3)} --> + ([wMapWidth] + 6) * e
|
|
ld a, [wMapWidth]
|
|
add 6
|
|
ld c, a
|
|
ld b, 0
|
|
ld a, e
|
|
and a
|
|
jr z, .done
|
|
.loop
|
|
add hl, bc
|
|
dec a
|
|
jr nz, .loop
|
|
.done
|
|
call ConvertConnectedOverworldMapBlockAddressToXYCoords
|
|
ret
|
|
.nope
|
|
xor a
|
|
ret ; nc
|
|
|
|
GetEastConnectedSpriteCoords:
|
|
; xcoord / 2 <= 2
|
|
ld a, d
|
|
srl a
|
|
cp 3
|
|
ret nc
|
|
; [wEastConnectionStripLocation]
|
|
ld hl, wEastConnectionStripLocation
|
|
ld a, [hli]
|
|
ld h, [hl]
|
|
ld l, a
|
|
; + (xcoord / 2)
|
|
srl d
|
|
ld b, 0
|
|
ld c, d
|
|
add hl, bc
|
|
; + ([wMapWidth] + 6) * ycoord / 2
|
|
ld a, [wMapWidth]
|
|
add 6
|
|
ld c, a
|
|
ld b, 0
|
|
srl e
|
|
ld a, e
|
|
and a
|
|
jr z, .done
|
|
.loop
|
|
add hl, bc
|
|
dec a
|
|
jr nz, .loop
|
|
.done
|
|
call ConvertConnectedOverworldMapBlockAddressToXYCoords
|
|
ret
|
|
|
|
GetWestConnectedSpriteCoords:
|
|
; wWestConnectedMapWidth >= 3
|
|
; xcoord / 2 >= ([wWestConnectedMapWidth] - 3)
|
|
ld a, [wWestConnectedMapWidth]
|
|
sub 3
|
|
jr c, .nope
|
|
ld c, a
|
|
ld a, d
|
|
srl a
|
|
sub c
|
|
jr c, .nope
|
|
ld d, a ; d = xcoord / 2 - ([wWestConnectedMapWidth] - 3)
|
|
; [wWestConnectionStripLocation]
|
|
ld hl, wWestConnectionStripLocation
|
|
ld a, [hli]
|
|
ld h, [hl]
|
|
ld l, a
|
|
; + xcoord / 2 - ([wWestConnectedMapWidth] - 3) --> + d
|
|
ld c, d
|
|
ld b, 0
|
|
add hl, bc
|
|
; + ([wMapWidth] + 6) * ycoord / 2
|
|
ld a, [wMapWidth]
|
|
add 6
|
|
ld c, a
|
|
ld b, 0
|
|
srl e
|
|
ld a, e
|
|
and a
|
|
jr z, .done
|
|
.loop
|
|
add hl, bc
|
|
dec a
|
|
jr nz, .loop
|
|
.done
|
|
call ConvertConnectedOverworldMapBlockAddressToXYCoords
|
|
ret
|
|
.nope
|
|
xor a
|
|
ret ; nc
|
|
|
|
; load into wPlayerMockYCoord and wPlayerMockXCoord the coordinates
|
|
; that correspond to wOverworldMapBlocks address at hl.
|
|
ConvertConnectedOverworldMapBlockAddressToXYCoords:
|
|
ld bc, -wOverworldMapBlocks + $10000
|
|
add hl, bc
|
|
ld a, [wMapWidth]
|
|
add 6
|
|
xor $ff
|
|
inc a
|
|
ld c, a
|
|
ld b, $ff
|
|
ld d, -2 ;
|
|
.calc_y_coord_loop
|
|
inc d ;
|
|
inc d ; each block in wOverworldMapBlocks occupies two half-blocks
|
|
add hl, bc
|
|
ld a, h
|
|
cp $ff
|
|
jr nz, .calc_y_coord_loop
|
|
; for X, we want the value of l in the second-to-last iteration of the previous loop,
|
|
; so undo the last iteration in l by adding [wMapWidth]+6 to it
|
|
ld a, [wMapWidth]
|
|
add 6
|
|
add l
|
|
add a ; each block in wOverworldMapBlocks occupies two half-blocks
|
|
; substract 6 tiles from y, substract 6 tiles from x.
|
|
; the '6's correspond to the 3 extra blocks in each margin of wOverworldMapBlocks.
|
|
sub 6
|
|
ld [wPlayerMockXCoord], a
|
|
ld a, d
|
|
sub 6
|
|
ld [wPlayerMockYCoord], a
|
|
call CheckPlayerMockSpriteOutOfScreen
|
|
ret ; c or nc
|
|
|
|
; return nc if either X or Y coord is too negative to be visible in the screen.
|
|
; this corresponds to half-block coords -5 and -6, which are visible by wOverworldMapBlocks,
|
|
; but not by the map sprite engine when it adds 4 to X and to Y to obtain wPlayerObject coords.
|
|
CheckPlayerMockSpriteOutOfScreen:
|
|
ld a, [wPlayerMockXCoord]
|
|
ld b, a
|
|
ld a, [wPlayerMockYCoord]
|
|
ld c, a
|
|
ld a, -5
|
|
cp b
|
|
ret z ; nc
|
|
cp c
|
|
ret z ; nc
|
|
dec a ; -6
|
|
cp b
|
|
ret z ; nc
|
|
cp c
|
|
ret z ; nc
|
|
scf
|
|
ret
|