summaryrefslogtreecommitdiff
path: root/main.asm
diff options
context:
space:
mode:
Diffstat (limited to 'main.asm')
-rwxr-xr-xmain.asm2698
1 files changed, 22 insertions, 2676 deletions
diff --git a/main.asm b/main.asm
index 4eeb38d3..fafd32bd 100755
--- a/main.asm
+++ b/main.asm
@@ -11,7 +11,6 @@ PICS_3 EQU $B
PICS_4 EQU $C
PICS_5 EQU $D
-
INCLUDE "home.asm"
@@ -95,2692 +94,39 @@ INCLUDE "data/map_songs.asm"
INCLUDE "data/map_header_banks.asm"
-ClearVariablesAfterLoadingMapData:
- ld a, SCREEN_HEIGHT_PIXELS
- ld [hWY], a
- ld [rWY], a
- xor a
- ld [H_AUTOBGTRANSFERENABLED], a
- ld [wStepCounter], a
- ld [wLoneAttackNo], a
- ld [hJoyPressed], a
- ld [hJoyReleased], a
- ld [hJoyHeld], a
- ld [wActionResultOrTookBattleTurn], a
- ld [wUnusedD5A3], a
- ld hl, wCardKeyDoorY
- ld [hli], a
- ld [hl], a
- ld hl, wWhichTrade
- ld bc, wStandingOnWarpPadOrHole - wWhichTrade
- call FillMemory
- ret
-
-; only used for setting bit 2 of wd736 upon entering a new map
-IsPlayerStandingOnWarp:
- ld a, [wNumberOfWarps]
- and a
- ret z
- ld c, a
- ld hl, wWarpEntries
-.loop
- ld a, [wYCoord]
- cp [hl]
- jr nz, .nextWarp1
- inc hl
- ld a, [wXCoord]
- cp [hl]
- jr nz, .nextWarp2
- inc hl
- ld a, [hli] ; target warp
- ld [wDestinationWarpID], a
- ld a, [hl] ; target map
- ld [hWarpDestinationMap], a
- ld hl, wd736
- set 2, [hl] ; standing on warp flag
- ret
-.nextWarp1
- inc hl
-.nextWarp2
- inc hl
- inc hl
- inc hl
- dec c
- jr nz, .loop
- ret
-
-CheckForceBikeOrSurf:
- ld hl, wd732
- bit 5, [hl]
- ret nz
- ld hl, ForcedBikeOrSurfMaps
- ld a, [wYCoord]
- ld b, a
- ld a, [wXCoord]
- ld c, a
- ld a, [wCurMap]
- ld d, a
-.loop
- ld a, [hli]
- cp $ff
- ret z ;if we reach FF then it's not part of the list
- cp d ;compare to current map
- jr nz, .incorrectMap
- ld a, [hli]
- cp b ;compare y-coord
- jr nz, .incorrectY
- ld a, [hli]
- cp c ;compare x-coord
- jr nz, .loop ; incorrect x-coord, check next item
- ld a, [wCurMap]
- cp SEAFOAM_ISLANDS_4
- ld a, $2
- ld [wSeafoamIslands4CurScript], a
- jr z, .forceSurfing
- ld a, [wCurMap]
- cp SEAFOAM_ISLANDS_5
- ld a, $2
- ld [wSeafoamIslands5CurScript], a
- jr z, .forceSurfing
- ;force bike riding
- ld hl, wd732
- set 5, [hl]
- ld a, $1
- ld [wWalkBikeSurfState], a
- ld [wWalkBikeSurfStateCopy], a
- jp ForceBikeOrSurf
-.incorrectMap
- inc hl
-.incorrectY
- inc hl
- jr .loop
-.forceSurfing
- ld a, $2
- ld [wWalkBikeSurfState], a
- ld [wWalkBikeSurfStateCopy], a
- jp ForceBikeOrSurf
-
-INCLUDE "data/force_bike_surf.asm"
-
-IsPlayerFacingEdgeOfMap:
- push hl
- push de
- push bc
- ld a, [wSpriteStateData1 + 9] ; player sprite's facing direction
- srl a
- ld c, a
- ld b, $0
- ld hl, .functionPointerTable
- add hl, bc
- ld a, [hli]
- ld h, [hl]
- ld l, a
- ld a, [wYCoord]
- ld b, a
- ld a, [wXCoord]
- ld c, a
- ld de, .asm_c41e
- push de
- jp [hl]
-.asm_c41e
- pop bc
- pop de
- pop hl
- ret
-
-.functionPointerTable
- dw .facingDown
- dw .facingUp
- dw .facingLeft
- dw .facingRight
-
-.facingDown
- ld a, [wCurMapHeight]
- add a
- dec a
- cp b
- jr z, .setCarry
- jr .resetCarry
-
-.facingUp
- ld a, b
- and a
- jr z, .setCarry
- jr .resetCarry
-
-.facingLeft
- ld a, c
- and a
- jr z, .setCarry
- jr .resetCarry
-
-.facingRight
- ld a, [wCurMapWidth]
- add a
- dec a
- cp c
- jr z, .setCarry
- jr .resetCarry
-.resetCarry
- and a
- ret
-.setCarry
- scf
- ret
-
-IsWarpTileInFrontOfPlayer:
- push hl
- push de
- push bc
- call _GetTileAndCoordsInFrontOfPlayer
- ld a, [wCurMap]
- cp SS_ANNE_5
- jr z, .ssAnne5
- ld a, [wSpriteStateData1 + 9] ; player sprite's facing direction
- srl a
- ld c, a
- ld b, 0
- ld hl, .warpTileListPointers
- add hl, bc
- ld a, [hli]
- ld h, [hl]
- ld l, a
- ld a, [wTileInFrontOfPlayer]
- ld de, $1
- call IsInArray
-.done
- pop bc
- pop de
- pop hl
- ret
-
-.warpTileListPointers:
- dw .facingDownWarpTiles
- dw .facingUpWarpTiles
- dw .facingLeftWarpTiles
- dw .facingRightWarpTiles
-
-.facingDownWarpTiles
- db $01,$12,$17,$3D,$04,$18,$33,$FF
-
-.facingUpWarpTiles
- db $01,$5C,$FF
-
-.facingLeftWarpTiles
- db $1A,$4B,$FF
-
-.facingRightWarpTiles
- db $0F,$4E,$FF
-
-.ssAnne5
- ld a, [wTileInFrontOfPlayer]
- cp $15
- jr nz, .notSSAnne5Warp
- scf
- jr .done
-.notSSAnne5Warp
- and a
- jr .done
-
-IsPlayerStandingOnDoorTileOrWarpTile:
- push hl
- push de
- push bc
- callba IsPlayerStandingOnDoorTile
- jr c, .done
- ld a, [wCurMapTileset]
- add a
- ld c, a
- ld b, $0
- ld hl, WarpTileIDPointers
- add hl, bc
- ld a, [hli]
- ld h, [hl]
- ld l, a
- ld de, $1
- aCoord 8, 9
- call IsInArray
- jr nc, .done
- ld hl, wd736
- res 2, [hl]
-.done
- pop bc
- pop de
- pop hl
- ret
-
-INCLUDE "data/warp_tile_ids.asm"
-
-PrintSafariZoneSteps:
- ld a, [wCurMap]
- cp SAFARI_ZONE_EAST
- ret c
- cp UNKNOWN_DUNGEON_2
- ret nc
- coord hl, 0, 0
- ld b, 3
- ld c, 7
- call TextBoxBorder
- coord hl, 1, 1
- ld de, wSafariSteps
- lb bc, 2, 3
- call PrintNumber
- coord hl, 4, 1
- ld de, SafariSteps
- call PlaceString
- coord hl, 1, 3
- ld de, SafariBallText
- call PlaceString
- ld a, [wNumSafariBalls]
- cp 10
- jr nc, .asm_c56d
- coord hl, 5, 3
- ld a, " "
- ld [hl], a
-.asm_c56d
- coord hl, 6, 3
- ld de, wNumSafariBalls
- lb bc, 1, 2
- jp PrintNumber
-
-SafariSteps:
- db "/500@"
-
-SafariBallText:
- db "BALL×× @"
-
-GetTileAndCoordsInFrontOfPlayer:
- call GetPredefRegisters
-
-_GetTileAndCoordsInFrontOfPlayer:
- ld a, [wYCoord]
- ld d, a
- ld a, [wXCoord]
- ld e, a
- ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction
- and a ; cp SPRITE_FACING_DOWN
- jr nz, .notFacingDown
-; facing down
- aCoord 8, 11
- inc d
- jr .storeTile
-.notFacingDown
- cp SPRITE_FACING_UP
- jr nz, .notFacingUp
-; facing up
- aCoord 8, 7
- dec d
- jr .storeTile
-.notFacingUp
- cp SPRITE_FACING_LEFT
- jr nz, .notFacingLeft
-; facing left
- aCoord 6, 9
- dec e
- jr .storeTile
-.notFacingLeft
- cp SPRITE_FACING_RIGHT
- jr nz, .storeTile
-; facing right
- aCoord 10, 9
- inc e
-.storeTile
- ld c, a
- ld [wTileInFrontOfPlayer], a
- ret
-
-GetTileTwoStepsInFrontOfPlayer:
- xor a
- ld [$ffdb], a
- ld hl, wYCoord
- ld a, [hli]
- ld d, a
- ld e, [hl]
- ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction
- and a ; cp SPRITE_FACING_DOWN
- jr nz, .notFacingDown
-; facing down
- ld hl, $ffdb
- set 0, [hl]
- aCoord 8, 13
- inc d
- jr .storeTile
-.notFacingDown
- cp SPRITE_FACING_UP
- jr nz, .notFacingUp
-; facing up
- ld hl, $ffdb
- set 1, [hl]
- aCoord 8, 5
- dec d
- jr .storeTile
-.notFacingUp
- cp SPRITE_FACING_LEFT
- jr nz, .notFacingLeft
-; facing left
- ld hl, $ffdb
- set 2, [hl]
- aCoord 4, 9
- dec e
- jr .storeTile
-.notFacingLeft
- cp SPRITE_FACING_RIGHT
- jr nz, .storeTile
-; facing right
- ld hl, $ffdb
- set 3, [hl]
- aCoord 12, 9
- inc e
-.storeTile
- ld c, a
- ld [wTileInFrontOfBoulderAndBoulderCollisionResult], a
- ld [wTileInFrontOfPlayer], a
- ret
-
-CheckForCollisionWhenPushingBoulder:
- call GetTileTwoStepsInFrontOfPlayer
- ld hl, wTilesetCollisionPtr
- ld a, [hli]
- ld h, [hl]
- ld l, a
-.loop
- ld a, [hli]
- cp $ff
- jr z, .done ; if the tile two steps ahead is not passable
- cp c
- jr nz, .loop
- ld hl, TilePairCollisionsLand
- call CheckForTilePairCollisions2
- ld a, $ff
- jr c, .done ; if there is an elevation difference between the current tile and the one two steps ahead
- ld a, [wTileInFrontOfBoulderAndBoulderCollisionResult]
- cp $15 ; stairs tile
- ld a, $ff
- jr z, .done ; if the tile two steps ahead is stairs
- call CheckForBoulderCollisionWithSprites
-.done
- ld [wTileInFrontOfBoulderAndBoulderCollisionResult], a
- ret
-
-; sets a to $ff if there is a collision and $00 if there is no collision
-CheckForBoulderCollisionWithSprites:
- ld a, [wBoulderSpriteIndex]
- dec a
- swap a
- ld d, 0
- ld e, a
- ld hl, wSpriteStateData2 + $14
- add hl, de
- ld a, [hli] ; map Y position
- ld [$ffdc], a
- ld a, [hl] ; map X position
- ld [$ffdd], a
- ld a, [wNumSprites]
- ld c, a
- ld de, $f
- ld hl, wSpriteStateData2 + $14
- ld a, [$ffdb]
- and $3 ; facing up or down?
- jr z, .pushingHorizontallyLoop
-.pushingVerticallyLoop
- inc hl
- ld a, [$ffdd]
- cp [hl]
- jr nz, .nextSprite1 ; if X coordinates don't match
- dec hl
- ld a, [hli]
- ld b, a
- ld a, [$ffdb]
- rrca
- jr c, .pushingDown
-; pushing up
- ld a, [$ffdc]
- dec a
- jr .compareYCoords
-.pushingDown
- ld a, [$ffdc]
- inc a
-.compareYCoords
- cp b
- jr z, .failure
-.nextSprite1
- dec c
- jr z, .success
- add hl, de
- jr .pushingVerticallyLoop
-.pushingHorizontallyLoop
- ld a, [hli]
- ld b, a
- ld a, [$ffdc]
- cp b
- jr nz, .nextSprite2
- ld b, [hl]
- ld a, [$ffdb]
- bit 2, a
- jr nz, .pushingLeft
-; pushing right
- ld a, [$ffdd]
- inc a
- jr .compareXCoords
-.pushingLeft
- ld a, [$ffdd]
- dec a
-.compareXCoords
- cp b
- jr z, .failure
-.nextSprite2
- dec c
- jr z, .success
- add hl, de
- jr .pushingHorizontallyLoop
-.failure
- ld a, $ff
- ret
-.success
- xor a
- ret
-
-ApplyOutOfBattlePoisonDamage:
- ld a, [wd730]
- add a
- jp c, .noBlackOut ; no black out if joypad states are being simulated
- ld a, [wPartyCount]
- and a
- jp z, .noBlackOut
- call IncrementDayCareMonExp
- ld a, [wStepCounter]
- and $3 ; is the counter a multiple of 4?
- jp nz, .noBlackOut ; only apply poison damage every fourth step
- ld [wWhichPokemon], a
- ld hl, wPartyMon1Status
- ld de, wPartySpecies
-.applyDamageLoop
- ld a, [hl]
- and (1 << PSN)
- jr z, .nextMon2 ; not poisoned
- dec hl
- dec hl
- ld a, [hld]
- ld b, a
- ld a, [hli]
- or b
- jr z, .nextMon ; already fainted
-; subtract 1 from HP
- ld a, [hl]
- dec a
- ld [hld], a
- inc a
- jr nz, .noBorrow
-; borrow 1 from upper byte of HP
- dec [hl]
- inc hl
- jr .nextMon
-.noBorrow
- ld a, [hli]
- or [hl]
- jr nz, .nextMon ; didn't faint from damage
-; the mon fainted from the damage
- push hl
- inc hl
- inc hl
- ld [hl], a
- ld a, [de]
- ld [wd11e], a
- push de
- ld a, [wWhichPokemon]
- ld hl, wPartyMonNicks
- call GetPartyMonName
- xor a
- ld [wJoyIgnore], a
- call EnableAutoTextBoxDrawing
- ld a, $d0
- ld [hSpriteIndexOrTextID], a
- call DisplayTextID
- pop de
- pop hl
-.nextMon
- inc hl
- inc hl
-.nextMon2
- inc de
- ld a, [de]
- inc a
- jr z, .applyDamageLoopDone
- ld bc, wPartyMon2 - wPartyMon1
- add hl, bc
- push hl
- ld hl, wWhichPokemon
- inc [hl]
- pop hl
- jr .applyDamageLoop
-.applyDamageLoopDone
- ld hl, wPartyMon1Status
- ld a, [wPartyCount]
- ld d, a
- ld e, 0
-.countPoisonedLoop
- ld a, [hl]
- and (1 << PSN)
- or e
- ld e, a
- ld bc, wPartyMon2 - wPartyMon1
- add hl, bc
- dec d
- jr nz, .countPoisonedLoop
- ld a, e
- and a ; are any party members poisoned?
- jr z, .skipPoisonEffectAndSound
- ld b, $2
- predef ChangeBGPalColor0_4Frames ; change BG white to dark grey for 4 frames
- ld a, SFX_POISONED
- call PlaySound
-.skipPoisonEffectAndSound
- predef AnyPartyAlive
- ld a, d
- and a
- jr nz, .noBlackOut
- call EnableAutoTextBoxDrawing
- ld a, $d1
- ld [hSpriteIndexOrTextID], a
- call DisplayTextID
- ld hl, wd72e
- set 5, [hl]
- ld a, $ff
- jr .done
-.noBlackOut
- xor a
-.done
- ld [wOutOfBattleBlackout], a
- ret
-
-LoadTilesetHeader:
- call GetPredefRegisters
- push hl
- ld d, 0
- ld a, [wCurMapTileset]
- add a
- add a
- ld b, a
- add a
- add b ; a = tileset * 12
- jr nc, .noCarry
- inc d
-.noCarry
- ld e, a
- ld hl, Tilesets
- add hl, de
- ld de, wTilesetBank
- ld c, $b
-.copyTilesetHeaderLoop
- ld a, [hli]
- ld [de], a
- inc de
- dec c
- jr nz, .copyTilesetHeaderLoop
- ld a, [hl]
- ld [hTilesetType], a
- xor a
- ld [$ffd8], a
- pop hl
- ld a, [wCurMapTileset]
- push hl
- push de
- ld hl, DungeonTilesets
- ld de, $1
- call IsInArray
- pop de
- pop hl
- jr c, .asm_c797
- ld a, [wCurMapTileset]
- ld b, a
- ld a, [hPreviousTileset]
- cp b
- jr z, .done
-.asm_c797
- ld a, [wDestinationWarpID]
- cp $ff
- jr z, .done
- call LoadDestinationWarpPosition
- ld a, [wYCoord]
- and $1
- ld [wYBlockCoord], a
- ld a, [wXCoord]
- and $1
- ld [wXBlockCoord], a
-.done
- ret
-
-INCLUDE "data/dungeon_tilesets.asm"
-
-INCLUDE "data/tileset_headers.asm"
-
-IncrementDayCareMonExp:
- ld a, [wDayCareInUse]
- and a
- ret z
- ld hl, wDayCareMonExp + 2
- inc [hl]
- ret nz
- dec hl
- inc [hl]
- ret nz
- dec hl
- inc [hl]
- ld a, [hl]
- cp $50
- ret c
- ld a, $50
- ld [hl], a
- ret
+INCLUDE "engine/overworld/clear_variables.asm"
+INCLUDE "engine/overworld/player_state.asm"
+INCLUDE "engine/overworld/poison.asm"
+INCLUDE "engine/overworld/tileset_header.asm"
+INCLUDE "engine/overworld/daycare_exp.asm"
INCLUDE "data/hide_show_data.asm"
-PrintStrengthTxt:
- ld hl, wd728
- set 0, [hl]
- ld hl, UsedStrengthText
- call PrintText
- ld hl, CanMoveBouldersText
- jp PrintText
-
-UsedStrengthText:
- TX_FAR _UsedStrengthText
- TX_ASM
- ld a, [wcf91]
- call PlayCry
- call Delay3
- jp TextScriptEnd
-
-CanMoveBouldersText:
- TX_FAR _CanMoveBouldersText
- db "@"
-
-IsSurfingAllowed:
-; Returns whether surfing is allowed in bit 1 of wd728.
-; Surfing isn't allowed on the Cycling Road or in the lowest level of the
-; Seafoam Islands before the current has been slowed with boulders.
- ld hl, wd728
- set 1, [hl]
- ld a, [wd732]
- bit 5, a
- jr nz, .forcedToRideBike
- ld a, [wCurMap]
- cp SEAFOAM_ISLANDS_5
- ret nz
- CheckBothEventsSet EVENT_SEAFOAM4_BOULDER1_DOWN_HOLE, EVENT_SEAFOAM4_BOULDER2_DOWN_HOLE
- ret z
- ld hl, CoordsData_cdf7
- call ArePlayerCoordsInArray
- ret nc
- ld hl, wd728
- res 1, [hl]
- ld hl, CurrentTooFastText
- jp PrintText
-.forcedToRideBike
- ld hl, wd728
- res 1, [hl]
- ld hl, CyclingIsFunText
- jp PrintText
-
-CoordsData_cdf7:
- db $0B,$07,$FF
-
-CurrentTooFastText:
- TX_FAR _CurrentTooFastText
- db "@"
-
-CyclingIsFunText:
- TX_FAR _CyclingIsFunText
- db "@"
-
-; function to add an item (in varying quantities) to the player's bag or PC box
-; INPUT:
-; hl = address of inventory (either wNumBagItems or wNumBoxItems)
-; [wcf91] = item ID
-; [wItemQuantity] = item quantity
-; sets carry flag if successful, unsets carry flag if unsuccessful
-AddItemToInventory_:
- ld a,[wItemQuantity] ; a = item quantity
- push af
- push bc
- push de
- push hl
- push hl
- ld d,PC_ITEM_CAPACITY ; how many items the PC can hold
- ld a,wNumBagItems & $FF
- cp l
- jr nz,.checkIfInventoryFull
- ld a,wNumBagItems >> 8
- cp h
- jr nz,.checkIfInventoryFull
-; if the destination is the bag
- ld d,BAG_ITEM_CAPACITY ; how many items the bag can hold
-.checkIfInventoryFull
- ld a,[hl]
- sub d
- ld d,a
- ld a,[hli]
- and a
- jr z,.addNewItem
-.loop
- ld a,[hli]
- ld b,a ; b = ID of current item in table
- ld a,[wcf91] ; a = ID of item being added
- cp b ; does the current item in the table match the item being added?
- jp z,.increaseItemQuantity ; if so, increase the item's quantity
- inc hl
- ld a,[hl]
- cp a,$ff ; is it the end of the table?
- jr nz,.loop
-.addNewItem ; add an item not yet in the inventory
- pop hl
- ld a,d
- and a ; is there room for a new item slot?
- jr z,.done
-; if there is room
- inc [hl] ; increment the number of items in the inventory
- ld a,[hl] ; the number of items will be the index of the new item
- add a
- dec a
- ld c,a
- ld b,0
- add hl,bc ; hl = address to store the item
- ld a,[wcf91]
- ld [hli],a ; store item ID
- ld a,[wItemQuantity]
- ld [hli],a ; store item quantity
- ld [hl],$ff ; store terminator
- jp .success
-.increaseItemQuantity ; increase the quantity of an item already in the inventory
- ld a,[wItemQuantity]
- ld b,a ; b = quantity to add
- ld a,[hl] ; a = existing item quantity
- add b ; a = new item quantity
- cp a,100
- jp c,.storeNewQuantity ; if the new quantity is less than 100, store it
-; if the new quantity is greater than or equal to 100,
-; try to max out the current slot and add the rest in a new slot
- sub a,99
- ld [wItemQuantity],a ; a = amount left over (to put in the new slot)
- ld a,d
- and a ; is there room for a new item slot?
- jr z,.increaseItemQuantityFailed
-; if so, store 99 in the current slot and store the rest in a new slot
- ld a,99
- ld [hli],a
- jp .loop
-.increaseItemQuantityFailed
- pop hl
- and a
- jr .done
-.storeNewQuantity
- ld [hl],a
- pop hl
-.success
- scf
-.done
- pop hl
- pop de
- pop bc
- pop bc
- ld a,b
- ld [wItemQuantity],a ; restore the initial value from when the function was called
- ret
-
-; function to remove an item (in varying quantities) from the player's bag or PC box
-; INPUT:
-; hl = address of inventory (either wNumBagItems or wNumBoxItems)
-; [wWhichPokemon] = index (within the inventory) of the item to remove
-; [wItemQuantity] = quantity to remove
-RemoveItemFromInventory_:
- push hl
- inc hl
- ld a,[wWhichPokemon] ; index (within the inventory) of the item being removed
- sla a
- add l
- ld l,a
- jr nc,.noCarry
- inc h
-.noCarry
- inc hl
- ld a,[wItemQuantity] ; quantity being removed
- ld e,a
- ld a,[hl] ; a = current quantity
- sub e
- ld [hld],a ; store new quantity
- ld [wMaxItemQuantity],a
- and a
- jr nz,.skipMovingUpSlots
-; if the remaining quantity is 0,
-; remove the emptied item slot and move up all the following item slots
-.moveSlotsUp
- ld e,l
- ld d,h
- inc de
- inc de ; de = address of the slot following the emptied one
-.loop ; loop to move up the following slots
- ld a,[de]
- inc de
- ld [hli],a
- cp a,$ff
- jr nz,.loop
-; update menu info
- xor a
- ld [wListScrollOffset],a
- ld [wCurrentMenuItem],a
- ld [wBagSavedMenuItem],a
- ld [wSavedListScrollOffset],a
- pop hl
- ld a,[hl] ; a = number of items in inventory
- dec a ; decrement the number of items
- ld [hl],a ; store new number of items
- ld [wListCount],a
- cp a,2
- jr c,.done
- ld [wMaxMenuItem],a
- jr .done
-.skipMovingUpSlots
- pop hl
-.done
- ret
-
-; wild pokemon data: from 4EB8 to 55C7
-
-LoadWildData:
- ld hl,WildDataPointers
- ld a,[wCurMap]
-
- ; get wild data for current map
- ld c,a
- ld b,0
- add hl,bc
- add hl,bc
- ld a,[hli]
- ld h,[hl]
- ld l,a ; hl now points to wild data for current map
- ld a,[hli]
- ld [wGrassRate],a
- and a
- jr z,.NoGrassData ; if no grass data, skip to surfing data
- push hl
- ld de,wGrassMons ; otherwise, load grass data
- ld bc,$0014
- call CopyData
- pop hl
- ld bc,$0014
- add hl,bc
-.NoGrassData
- ld a,[hli]
- ld [wWaterRate],a
- and a
- ret z ; if no water data, we're done
- ld de,wWaterMons ; otherwise, load surfing data
- ld bc,$0014
- jp CopyData
-
-INCLUDE "data/wild_mons.asm"
+INCLUDE "engine/overworld/field_move_messages.asm"
-INCLUDE "engine/items/items.asm"
+INCLUDE "engine/items/inventory.asm"
-DrawBadges:
-; Draw 4x2 gym leader faces, with the faces replaced by
-; badges if they are owned. Used in the player status screen.
-
-; In Japanese versions, names are displayed above faces.
-; Instead of removing relevant code, the name graphics were erased.
-
-; Tile ids for face/badge graphics.
- ld de, wBadgeOrFaceTiles
- ld hl, .FaceBadgeTiles
- ld bc, 8
- call CopyData
-
-; Booleans for each badge.
- ld hl, wTempObtainedBadgesBooleans
- ld bc, 8
- xor a
- call FillMemory
-
-; Alter these based on owned badges.
- ld de, wTempObtainedBadgesBooleans
- ld hl, wBadgeOrFaceTiles
- ld a, [wObtainedBadges]
- ld b, a
- ld c, 8
-.CheckBadge
- srl b
- jr nc, .NextBadge
- ld a, [hl]
- add 4 ; Badge graphics are after each face
- ld [hl], a
- ld a, 1
- ld [de], a
-.NextBadge
- inc hl
- inc de
- dec c
- jr nz, .CheckBadge
-
-; Draw two rows of badges.
- ld hl, wBadgeNumberTile
- ld a, $d8 ; [1]
- ld [hli], a
- ld [hl], $60 ; First name
-
- coord hl, 2, 11
- ld de, wTempObtainedBadgesBooleans
- call .DrawBadgeRow
-
- coord hl, 2, 14
- ld de, wTempObtainedBadgesBooleans + 4
-; call .DrawBadgeRow
-; ret
-
-.DrawBadgeRow
-; Draw 4 badges.
-
- ld c, 4
-.DrawBadge
- push de
- push hl
-
-; Badge no.
- ld a, [wBadgeNumberTile]
- ld [hli], a
- inc a
- ld [wBadgeNumberTile], a
-
-; Names aren't printed if the badge is owned.
- ld a, [de]
- and a
- ld a, [wBadgeNameTile]
- jr nz, .SkipName
- call .PlaceTiles
- jr .PlaceBadge
-
-.SkipName
- inc a
- inc a
- inc hl
-
-.PlaceBadge
- ld [wBadgeNameTile], a
- ld de, SCREEN_WIDTH - 1
- add hl, de
- ld a, [wBadgeOrFaceTiles]
- call .PlaceTiles
- add hl, de
- call .PlaceTiles
-
-; Shift badge array back one byte.
- push bc
- ld hl, wBadgeOrFaceTiles + 1
- ld de, wBadgeOrFaceTiles
- ld bc, 8
- call CopyData
- pop bc
-
- pop hl
- ld de, 4
- add hl, de
-
- pop de
- inc de
- dec c
- jr nz, .DrawBadge
- ret
-
-.PlaceTiles
- ld [hli], a
- inc a
- ld [hl], a
- inc a
- ret
-
-.FaceBadgeTiles
- db $20, $28, $30, $38, $40, $48, $50, $58
-
-GymLeaderFaceAndBadgeTileGraphics:
- INCBIN "gfx/badges.2bpp"
-
-; replaces a tile block with the one specified in [wNewTileBlockID]
-; and redraws the map view if necessary
-; b = Y
-; c = X
-ReplaceTileBlock:
- call GetPredefRegisters
- ld hl, wOverworldMap
- ld a, [wCurMapWidth]
- add $6
- ld e, a
- ld d, $0
- add hl, de
- add hl, de
- add hl, de
- ld e, $3
- add hl, de
- ld e, a
- ld a, b
- and a
- jr z, .addX
-; add width * Y
-.addWidthYTimesLoop
- add hl, de
- dec b
- jr nz, .addWidthYTimesLoop
-.addX
- add hl, bc ; add X
- ld a, [wNewTileBlockID]
- ld [hl], a
- ld a, [wCurrentTileBlockMapViewPointer]
- ld c, a
- ld a, [wCurrentTileBlockMapViewPointer + 1]
- ld b, a
- call CompareHLWithBC
- ret c ; return if the replaced tile block is below the map view in memory
- push hl
- ld l, e
- ld h, $0
- ld e, $6
- ld d, h
- add hl, hl
- add hl, hl
- add hl, de
- add hl, bc
- pop bc
- call CompareHLWithBC
- ret c ; return if the replaced tile block is above the map view in memory
-
-RedrawMapView:
- ld a, [wIsInBattle]
- inc a
- ret z
- ld a, [H_AUTOBGTRANSFERENABLED]
- push af
- ld a, [hTilesetType]
- push af
- xor a
- ld [H_AUTOBGTRANSFERENABLED], a
- ld [hTilesetType], a ; no flower/water BG tile animations
- call LoadCurrentMapView
- call RunDefaultPaletteCommand
- ld hl, wMapViewVRAMPointer
- ld a, [hli]
- ld h, [hl]
- ld l, a
- ld de, -2 * 32
- add hl, de
- ld a, h
- and $3
- or $98
- ld a, l
- ld [wBuffer], a
- ld a, h
- ld [wBuffer + 1], a ; this copy of the address is not used
- ld a, 2
- ld [$ffbe], a
- ld c, 9 ; number of rows of 2x2 tiles (this covers the whole screen)
-.redrawRowLoop
- push bc
- push hl
- push hl
- ld hl, wTileMap - 2 * SCREEN_WIDTH
- ld de, SCREEN_WIDTH
- ld a, [$ffbe]
-.calcWRAMAddrLoop
- add hl, de
- dec a
- jr nz, .calcWRAMAddrLoop
- call CopyToRedrawRowOrColumnSrcTiles
- pop hl
- ld de, $20
- ld a, [$ffbe]
- ld c, a
-.calcVRAMAddrLoop
- add hl, de
- ld a, h
- and $3
- or $98
- dec c
- jr nz, .calcVRAMAddrLoop
- ld [hRedrawRowOrColumnDest + 1], a
- ld a, l
- ld [hRedrawRowOrColumnDest], a
- ld a, REDRAW_ROW
- ld [hRedrawRowOrColumnMode], a
- call DelayFrame
- ld hl, $ffbe
- inc [hl]
- inc [hl]
- pop hl
- pop bc
- dec c
- jr nz, .redrawRowLoop
- pop af
- ld [hTilesetType], a
- pop af
- ld [H_AUTOBGTRANSFERENABLED], a
- ret
-
-CompareHLWithBC:
- ld a, h
- sub b
- ret nz
- ld a, l
- sub c
- ret
+INCLUDE "engine/overworld/wild_mons.asm"
-INCLUDE "engine/overworld/cut.asm"
+INCLUDE "engine/items/items.asm"
-MarkTownVisitedAndLoadMissableObjects:
- ld a, [wCurMap]
- cp ROUTE_1
- jr nc, .notInTown
- ld c, a
- ld b, FLAG_SET
- ld hl, wTownVisitedFlag ; mark town as visited (for flying)
- predef FlagActionPredef
-.notInTown
- ld hl, MapHSPointers
- ld a, [wCurMap]
- ld b, $0
- ld c, a
- add hl, bc
- add hl, bc
- ld a, [hli] ; load missable objects pointer in hl
- ld h, [hl]
- ; fall through
-
-LoadMissableObjects:
- ld l, a
- push hl
- ld de, MapHS00 ; calculate difference between out pointer and the base pointer
- ld a, l
- sub e
- jr nc, .asm_f13c
- dec h
-.asm_f13c
- ld l, a
- ld a, h
- sub d
- ld h, a
- ld a, h
- ld [H_DIVIDEND], a
- ld a, l
- ld [H_DIVIDEND+1], a
- xor a
- ld [H_DIVIDEND+2], a
- ld [H_DIVIDEND+3], a
- ld a, $3
- ld [H_DIVISOR], a
- ld b, $2
- call Divide ; divide difference by 3, resulting in the global offset (number of missable items before ours)
- ld a, [wCurMap]
- ld b, a
- ld a, [H_DIVIDEND+3]
- ld c, a ; store global offset in c
- ld de, wMissableObjectList
- pop hl
-.writeMissableObjectsListLoop
- ld a, [hli]
- cp $ff
- jr z, .done ; end of list
- cp b
- jr nz, .done ; not for current map anymore
- ld a, [hli]
- inc hl
- ld [de], a ; write (map-local) sprite ID
- inc de
- ld a, c
- inc c
- ld [de], a ; write (global) missable object index
- inc de
- jr .writeMissableObjectsListLoop
-.done
- ld a, $ff
- ld [de], a ; write sentinel
- ret
-
-InitializeMissableObjectsFlags:
- ld hl, wMissableObjectFlags
- ld bc, wMissableObjectFlagsEnd - wMissableObjectFlags
- xor a
- call FillMemory ; clear missable objects flags
- ld hl, MapHS00
- xor a
- ld [wMissableObjectCounter], a
-.missableObjectsLoop
- ld a, [hli]
- cp $ff ; end of list
- ret z
- push hl
- inc hl
- ld a, [hl]
- cp Hide
- jr nz, .skip
- ld hl, wMissableObjectFlags
- ld a, [wMissableObjectCounter]
- ld c, a
- ld b, FLAG_SET
- call MissableObjectFlagAction ; set flag if Item is hidden
-.skip
- ld hl, wMissableObjectCounter
- inc [hl]
- pop hl
- inc hl
- inc hl
- jr .missableObjectsLoop
-
-; tests if current sprite is a missable object that is hidden/has been removed
-IsObjectHidden:
- ld a, [H_CURRENTSPRITEOFFSET]
- swap a
- ld b, a
- ld hl, wMissableObjectList
-.loop
- ld a, [hli]
- cp $ff
- jr z, .notHidden ; not missable -> not hidden
- cp b
- ld a, [hli]
- jr nz, .loop
- ld c, a
- ld b, FLAG_TEST
- ld hl, wMissableObjectFlags
- call MissableObjectFlagAction
- ld a, c
- and a
- jr nz, .hidden
-.notHidden
- xor a
-.hidden
- ld [$ffe5], a
- ret
-
-; adds missable object (items, leg. pokemon, etc.) to the map
-; [wMissableObjectIndex]: index of the missable object to be added (global index)
-ShowObject:
-ShowObject2:
- ld hl, wMissableObjectFlags
- ld a, [wMissableObjectIndex]
- ld c, a
- ld b, FLAG_RESET
- call MissableObjectFlagAction ; reset "removed" flag
- jp UpdateSprites
-
-; removes missable object (items, leg. pokemon, etc.) from the map
-; [wMissableObjectIndex]: index of the missable object to be removed (global index)
-HideObject:
- ld hl, wMissableObjectFlags
- ld a, [wMissableObjectIndex]
- ld c, a
- ld b, FLAG_SET
- call MissableObjectFlagAction ; set "removed" flag
- jp UpdateSprites
-
-MissableObjectFlagAction:
-; identical to FlagAction
-
- push hl
- push de
- push bc
-
- ; bit
- ld a, c
- ld d, a
- and 7
- ld e, a
-
- ; byte
- ld a, d
- srl a
- srl a
- srl a
- add l
- ld l, a
- jr nc, .ok
- inc h
-.ok
-
- ; d = 1 << e (bitmask)
- inc e
- ld d, 1
-.shift
- dec e
- jr z, .shifted
- sla d
- jr .shift
-.shifted
-
- ld a, b
- and a
- jr z, .reset
- cp 2
- jr z, .read
-
-.set
- ld a, [hl]
- ld b, a
- ld a, d
- or b
- ld [hl], a
- jr .done
-
-.reset
- ld a, [hl]
- ld b, a
- ld a, d
- xor $ff
- and b
- ld [hl], a
- jr .done
-
-.read
- ld a, [hl]
- ld b, a
- ld a, d
- and b
-
-.done
- pop bc
- pop de
- pop hl
- ld c, a
- ret
-
-TryPushingBoulder:
- ld a, [wd728]
- bit 0, a ; using Strength?
- ret z
- ld a, [wFlags_0xcd60]
- bit 1, a ; has boulder dust animation from previous push played yet?
- ret nz
- xor a
- ld [hSpriteIndexOrTextID], a
- call IsSpriteInFrontOfPlayer
- ld a, [hSpriteIndexOrTextID]
- ld [wBoulderSpriteIndex], a
- and a
- jp z, ResetBoulderPushFlags
- ld hl, wSpriteStateData1 + 1
- ld d, $0
- ld a, [hSpriteIndexOrTextID]
- swap a
- ld e, a
- add hl, de
- res 7, [hl]
- call GetSpriteMovementByte2Pointer
- ld a, [hl]
- cp BOULDER_MOVEMENT_BYTE_2
- jp nz, ResetBoulderPushFlags
- ld hl, wFlags_0xcd60
- bit 6, [hl]
- set 6, [hl] ; indicate that the player has tried pushing
- ret z ; the player must try pushing twice before the boulder will move
- ld a, [hJoyHeld]
- and D_RIGHT | D_LEFT | D_UP | D_DOWN
- ret z
- predef CheckForCollisionWhenPushingBoulder
- ld a, [wTileInFrontOfBoulderAndBoulderCollisionResult]
- and a ; was there a collision?
- jp nz, ResetBoulderPushFlags
- ld a, [hJoyHeld]
- ld b, a
- ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction
- cp SPRITE_FACING_UP
- jr z, .pushBoulderUp
- cp SPRITE_FACING_LEFT
- jr z, .pushBoulderLeft
- cp SPRITE_FACING_RIGHT
- jr z, .pushBoulderRight
-.pushBoulderDown
- bit 7, b
- ret z
- ld de, PushBoulderDownMovementData
- jr .done
-.pushBoulderUp
- bit 6, b
- ret z
- ld de, PushBoulderUpMovementData
- jr .done
-.pushBoulderLeft
- bit 5, b
- ret z
- ld de, PushBoulderLeftMovementData
- jr .done
-.pushBoulderRight
- bit 4, b
- ret z
- ld de, PushBoulderRightMovementData
-.done
- call MoveSprite
- ld a, SFX_PUSH_BOULDER
- call PlaySound
- ld hl, wFlags_0xcd60
- set 1, [hl]
- ret
-
-PushBoulderUpMovementData:
- db NPC_MOVEMENT_UP,$FF
-
-PushBoulderDownMovementData:
- db NPC_MOVEMENT_DOWN,$FF
-
-PushBoulderLeftMovementData:
- db NPC_MOVEMENT_LEFT,$FF
-
-PushBoulderRightMovementData:
- db NPC_MOVEMENT_RIGHT,$FF
-
-DoBoulderDustAnimation:
- ld a, [wd730]
- bit 0, a
- ret nz
- callab AnimateBoulderDust
- call DiscardButtonPresses
- ld [wJoyIgnore], a
- call ResetBoulderPushFlags
- set 7, [hl]
- ld a, [wBoulderSpriteIndex]
- ld [H_SPRITEINDEX], a
- call GetSpriteMovementByte2Pointer
- ld [hl], $10
- ld a, SFX_CUT
- jp PlaySound
-
-ResetBoulderPushFlags:
- ld hl, wFlags_0xcd60
- res 1, [hl]
- res 6, [hl]
- ret
-
-_AddPartyMon:
-; Adds a new mon to the player's or enemy's party.
-; [wMonDataLocation] is used in an unusual way in this function.
-; If the lower nybble is 0, the mon is added to the player's party, else the enemy's.
-; If the entire value is 0, then the player is allowed to name the mon.
- ld de, wPartyCount
- ld a, [wMonDataLocation]
- and $f
- jr z, .next
- ld de, wEnemyPartyCount
-.next
- ld a, [de]
- inc a
- cp PARTY_LENGTH + 1
- ret nc ; return if the party is already full
- ld [de], a
- ld a, [de]
- ld [hNewPartyLength], a
- add e
- ld e, a
- jr nc, .noCarry
- inc d
-.noCarry
- ld a, [wcf91]
- ld [de], a ; write species of new mon in party list
- inc de
- ld a, $ff ; terminator
- ld [de], a
- ld hl, wPartyMonOT
- ld a, [wMonDataLocation]
- and $f
- jr z, .next2
- ld hl, wEnemyMonOT
-.next2
- ld a, [hNewPartyLength]
- dec a
- call SkipFixedLengthTextEntries
- ld d, h
- ld e, l
- ld hl, wPlayerName
- ld bc, NAME_LENGTH
- call CopyData
- ld a, [wMonDataLocation]
- and a
- jr nz, .skipNaming
- ld hl, wPartyMonNicks
- ld a, [hNewPartyLength]
- dec a
- call SkipFixedLengthTextEntries
- ld a, NAME_MON_SCREEN
- ld [wNamingScreenType], a
- predef AskName
-.skipNaming
- ld hl, wPartyMons
- ld a, [wMonDataLocation]
- and $f
- jr z, .next3
- ld hl, wEnemyMons
-.next3
- ld a, [hNewPartyLength]
- dec a
- ld bc, wPartyMon2 - wPartyMon1
- call AddNTimes
- ld e, l
- ld d, h
- push hl
- ld a, [wcf91]
- ld [wd0b5], a
- call GetMonHeader
- ld hl, wMonHeader
- ld a, [hli]
- ld [de], a ; species
- inc de
- pop hl
- push hl
- ld a, [wMonDataLocation]
- and $f
- ld a, $98 ; set enemy trainer mon IVs to fixed average values
- ld b, $88
- jr nz, .next4
-
-; If the mon is being added to the player's party, update the pokedex.
- ld a, [wcf91]
- ld [wd11e], a
- push de
- predef IndexToPokedex
- pop de
- ld a, [wd11e]
- dec a
- ld c, a
- ld b, FLAG_TEST
- ld hl, wPokedexOwned
- call FlagAction
- ld a, c ; whether the mon was already flagged as owned
- ld [wUnusedD153], a ; not read
- ld a, [wd11e]
- dec a
- ld c, a
- ld b, FLAG_SET
- push bc
- call FlagAction
- pop bc
- ld hl, wPokedexSeen
- call FlagAction
-
- pop hl
- push hl
-
- ld a, [wIsInBattle]
- and a ; is this a wild mon caught in battle?
- jr nz, .copyEnemyMonData
-
-; Not wild.
- call Random ; generate random IVs
- ld b, a
- call Random
-
-.next4
- push bc
- ld bc, wPartyMon1DVs - wPartyMon1
- add hl, bc
- pop bc
- ld [hli], a
- ld [hl], b ; write IVs
- ld bc, (wPartyMon1HPExp - 1) - (wPartyMon1DVs + 1)
- add hl, bc
- ld a, 1
- ld c, a
- xor a
- ld b, a
- call CalcStat ; calc HP stat (set cur Hp to max HP)
- ld a, [H_MULTIPLICAND+1]
- ld [de], a
- inc de
- ld a, [H_MULTIPLICAND+2]
- ld [de], a
- inc de
- xor a
- ld [de], a ; box level
- inc de
- ld [de], a ; status ailments
- inc de
- jr .copyMonTypesAndMoves
-.copyEnemyMonData
- ld bc, wEnemyMon1DVs - wEnemyMon1
- add hl, bc
- ld a, [wEnemyMonDVs] ; copy IVs from cur enemy mon
- ld [hli], a
- ld a, [wEnemyMonDVs + 1]
- ld [hl], a
- ld a, [wEnemyMonHP] ; copy HP from cur enemy mon
- ld [de], a
- inc de
- ld a, [wEnemyMonHP+1]
- ld [de], a
- inc de
- xor a
- ld [de], a ; box level
- inc de
- ld a, [wEnemyMonStatus] ; copy status ailments from cur enemy mon
- ld [de], a
- inc de
-.copyMonTypesAndMoves
- ld hl, wMonHTypes
- ld a, [hli] ; type 1
- ld [de], a
- inc de
- ld a, [hli] ; type 2
- ld [de], a
- inc de
- ld a, [hli] ; catch rate (held item in gen 2)
- ld [de], a
- ld hl, wMonHMoves
- ld a, [hli]
- inc de
- push de
- ld [de], a
- ld a, [hli]
- inc de
- ld [de], a
- ld a, [hli]
- inc de
- ld [de], a
- ld a, [hli]
- inc de
- ld [de], a
- push de
- dec de
- dec de
- dec de
- xor a
- ld [wLearningMovesFromDayCare], a
- predef WriteMonMoves
- pop de
- ld a, [wPlayerID] ; set trainer ID to player ID
- inc de
- ld [de], a
- ld a, [wPlayerID + 1]
- inc de
- ld [de], a
- push de
- ld a, [wCurEnemyLVL]
- ld d, a
- callab CalcExperience
- pop de
- inc de
- ld a, [hExperience] ; write experience
- ld [de], a
- inc de
- ld a, [hExperience + 1]
- ld [de], a
- inc de
- ld a, [hExperience + 2]
- ld [de], a
- xor a
- ld b, NUM_STATS * 2
-.writeEVsLoop ; set all EVs to 0
- inc de
- ld [de], a
- dec b
- jr nz, .writeEVsLoop
- inc de
- inc de
- pop hl
- call AddPartyMon_WriteMovePP
- inc de
- ld a, [wCurEnemyLVL]
- ld [de], a
- inc de
- ld a, [wIsInBattle]
- dec a
- jr nz, .calcFreshStats
- ld hl, wEnemyMonMaxHP
- ld bc, $a
- call CopyData ; copy stats of cur enemy mon
- pop hl
- jr .done
-.calcFreshStats
- pop hl
- ld bc, wPartyMon1HPExp - 1 - wPartyMon1
- add hl, bc
- ld b, $0
- call CalcStats ; calculate fresh set of stats
-.done
- scf
- ret
-
-LoadMovePPs:
- call GetPredefRegisters
- ; fallthrough
-AddPartyMon_WriteMovePP:
- ld b, NUM_MOVES
-.pploop
- ld a, [hli] ; read move ID
- and a
- jr z, .empty
- dec a
- push hl
- push de
- push bc
- ld hl, Moves
- ld bc, MoveEnd - Moves
- call AddNTimes
- ld de, wcd6d
- ld a, BANK(Moves)
- call FarCopyData
- pop bc
- pop de
- pop hl
- ld a, [wcd6d + 5] ; PP is byte 5 of move data
-.empty
- inc de
- ld [de], a
- dec b
- jr nz, .pploop ; there are still moves to read
- ret
-
-; adds enemy mon [wcf91] (at position [wWhichPokemon] in enemy list) to own party
-; used in the cable club trade center
-_AddEnemyMonToPlayerParty:
- ld hl, wPartyCount
- ld a, [hl]
- cp PARTY_LENGTH
- scf
- ret z ; party full, return failure
- inc a
- ld [hl], a ; add 1 to party members
- ld c, a
- ld b, $0
- add hl, bc
- ld a, [wcf91]
- ld [hli], a ; add mon as last list entry
- ld [hl], $ff ; write new sentinel
- ld hl, wPartyMons
- ld a, [wPartyCount]
- dec a
- ld bc, wPartyMon2 - wPartyMon1
- call AddNTimes
- ld e, l
- ld d, h
- ld hl, wLoadedMon
- call CopyData ; write new mon's data (from wLoadedMon)
- ld hl, wPartyMonOT
- ld a, [wPartyCount]
- dec a
- call SkipFixedLengthTextEntries
- ld d, h
- ld e, l
- ld hl, wEnemyMonOT
- ld a, [wWhichPokemon]
- call SkipFixedLengthTextEntries
- ld bc, NAME_LENGTH
- call CopyData ; write new mon's OT name (from an enemy mon)
- ld hl, wPartyMonNicks
- ld a, [wPartyCount]
- dec a
- call SkipFixedLengthTextEntries
- ld d, h
- ld e, l
- ld hl, wEnemyMonNicks
- ld a, [wWhichPokemon]
- call SkipFixedLengthTextEntries
- ld bc, NAME_LENGTH
- call CopyData ; write new mon's nickname (from an enemy mon)
- ld a, [wcf91]
- ld [wd11e], a
- predef IndexToPokedex
- ld a, [wd11e]
- dec a
- ld c, a
- ld b, FLAG_SET
- ld hl, wPokedexOwned
- push bc
- call FlagAction ; add to owned pokemon
- pop bc
- ld hl, wPokedexSeen
- call FlagAction ; add to seen pokemon
- and a
- ret ; return success
-
-_MoveMon:
- ld a, [wMoveMonType]
- and a
- jr z, .checkPartyMonSlots
- cp DAYCARE_TO_PARTY
- jr z, .checkPartyMonSlots
- cp PARTY_TO_DAYCARE
- ld hl, wDayCareMon
- jr z, .asm_f575
- ld hl, wNumInBox
- ld a, [hl]
- cp MONS_PER_BOX
- jr nz, .partyOrBoxNotFull
- jr .boxFull
-.checkPartyMonSlots
- ld hl, wPartyCount
- ld a, [hl]
- cp PARTY_LENGTH
- jr nz, .partyOrBoxNotFull
-.boxFull
- scf
- ret
-.partyOrBoxNotFull
- inc a
- ld [hl], a ; increment number of mons in party/box
- ld c, a
- ld b, 0
- add hl, bc
- ld a, [wMoveMonType]
- cp DAYCARE_TO_PARTY
- ld a, [wDayCareMon]
- jr z, .asm_f556
- ld a, [wcf91]
-.asm_f556
- ld [hli], a ; write new mon ID
- ld [hl], $ff ; write new sentinel
- ld a, [wMoveMonType]
- dec a
- ld hl, wPartyMons
- ld bc, wPartyMon2 - wPartyMon1 ; $2c
- ld a, [wPartyCount]
- jr nz, .skipToNewMonEntry
- ld hl, wBoxMons
- ld bc, wBoxMon2 - wBoxMon1 ; $21
- ld a, [wNumInBox]
-.skipToNewMonEntry
- dec a
- call AddNTimes
-.asm_f575
- push hl
- ld e, l
- ld d, h
- ld a, [wMoveMonType]
- and a
- ld hl, wBoxMons
- ld bc, wBoxMon2 - wBoxMon1 ; $21
- jr z, .asm_f591
- cp DAYCARE_TO_PARTY
- ld hl, wDayCareMon
- jr z, .asm_f597
- ld hl, wPartyMons
- ld bc, wPartyMon2 - wPartyMon1 ; $2c
-.asm_f591
- ld a, [wWhichPokemon]
- call AddNTimes
-.asm_f597
- push hl
- push de
- ld bc, wBoxMon2 - wBoxMon1
- call CopyData
- pop de
- pop hl
- ld a, [wMoveMonType]
- and a
- jr z, .asm_f5b4
- cp DAYCARE_TO_PARTY
- jr z, .asm_f5b4
- ld bc, wBoxMon2 - wBoxMon1
- add hl, bc
- ld a, [hl]
- inc de
- inc de
- inc de
- ld [de], a
-.asm_f5b4
- ld a, [wMoveMonType]
- cp PARTY_TO_DAYCARE
- ld de, wDayCareMonOT
- jr z, .asm_f5d3
- dec a
- ld hl, wPartyMonOT
- ld a, [wPartyCount]
- jr nz, .asm_f5cd
- ld hl, wBoxMonOT
- ld a, [wNumInBox]
-.asm_f5cd
- dec a
- call SkipFixedLengthTextEntries
- ld d, h
- ld e, l
-.asm_f5d3
- ld hl, wBoxMonOT
- ld a, [wMoveMonType]
- and a
- jr z, .asm_f5e6
- ld hl, wDayCareMonOT
- cp DAYCARE_TO_PARTY
- jr z, .asm_f5ec
- ld hl, wPartyMonOT
-.asm_f5e6
- ld a, [wWhichPokemon]
- call SkipFixedLengthTextEntries
-.asm_f5ec
- ld bc, NAME_LENGTH
- call CopyData
- ld a, [wMoveMonType]
- cp PARTY_TO_DAYCARE
- ld de, wDayCareMonName
- jr z, .asm_f611
- dec a
- ld hl, wPartyMonNicks
- ld a, [wPartyCount]
- jr nz, .asm_f60b
- ld hl, wBoxMonNicks
- ld a, [wNumInBox]
-.asm_f60b
- dec a
- call SkipFixedLengthTextEntries
- ld d, h
- ld e, l
-.asm_f611
- ld hl, wBoxMonNicks
- ld a, [wMoveMonType]
- and a
- jr z, .asm_f624
- ld hl, wDayCareMonName
- cp DAYCARE_TO_PARTY
- jr z, .asm_f62a
- ld hl, wPartyMonNicks
-.asm_f624
- ld a, [wWhichPokemon]
- call SkipFixedLengthTextEntries
-.asm_f62a
- ld bc, NAME_LENGTH
- call CopyData
- pop hl
- ld a, [wMoveMonType]
- cp PARTY_TO_BOX
- jr z, .asm_f664
- cp PARTY_TO_DAYCARE
- jr z, .asm_f664
- push hl
- srl a
- add $2
- ld [wMonDataLocation], a
- call LoadMonData
- callba CalcLevelFromExperience
- ld a, d
- ld [wCurEnemyLVL], a
- pop hl
- ld bc, wBoxMon2 - wBoxMon1
- add hl, bc
- ld [hli], a
- ld d, h
- ld e, l
- ld bc, -18
- add hl, bc
- ld b, $1
- call CalcStats
-.asm_f664
- and a
- ret
-
-
-FlagActionPredef:
- call GetPredefRegisters
-
-FlagAction:
-; Perform action b on bit c
-; in the bitfield at hl.
-; 0: reset
-; 1: set
-; 2: read
-; Return the result in c.
-
- push hl
- push de
- push bc
-
- ; bit
- ld a, c
- ld d, a
- and 7
- ld e, a
-
- ; byte
- ld a, d
- srl a
- srl a
- srl a
- add l
- ld l, a
- jr nc, .ok
- inc h
-.ok
-
- ; d = 1 << e (bitmask)
- inc e
- ld d, 1
-.shift
- dec e
- jr z, .shifted
- sla d
- jr .shift
-.shifted
-
- ld a, b
- and a
- jr z, .reset
- cp 2
- jr z, .read
-
-.set
- ld b, [hl]
- ld a, d
- or b
- ld [hl], a
- jr .done
-
-.reset
- ld b, [hl]
- ld a, d
- xor $ff
- and b
- ld [hl], a
- jr .done
-
-.read
- ld b, [hl]
- ld a, d
- and b
-.done
- pop bc
- pop de
- pop hl
- ld c, a
- ret
-
-
-HealParty:
-; Restore HP and PP.
-
- ld hl, wPartySpecies
- ld de, wPartyMon1HP
-.healmon
- ld a, [hli]
- cp $ff
- jr z, .done
-
- push hl
- push de
-
- ld hl, wPartyMon1Status - wPartyMon1HP
- add hl, de
- xor a
- ld [hl], a
-
- push de
- ld b, NUM_MOVES ; A Pokémon has 4 moves
-.pp
- ld hl, wPartyMon1Moves - wPartyMon1HP
- add hl, de
-
- ld a, [hl]
- and a
- jr z, .nextmove
-
- dec a
- ld hl, wPartyMon1PP - wPartyMon1HP
- add hl, de
-
- push hl
- push de
- push bc
-
- ld hl, Moves
- ld bc, MoveEnd - Moves
- call AddNTimes
- ld de, wcd6d
- ld a, BANK(Moves)
- call FarCopyData
- ld a, [wcd6d + 5] ; PP is byte 5 of move data
-
- pop bc
- pop de
- pop hl
-
- inc de
- push bc
- ld b, a
- ld a, [hl]
- and $c0
- add b
- ld [hl], a
- pop bc
-
-.nextmove
- dec b
- jr nz, .pp
- pop de
-
- ld hl, wPartyMon1MaxHP - wPartyMon1HP
- add hl, de
- ld a, [hli]
- ld [de], a
- inc de
- ld a, [hl]
- ld [de], a
-
- pop de
- pop hl
-
- push hl
- ld bc, wPartyMon2 - wPartyMon1
- ld h, d
- ld l, e
- add hl, bc
- ld d, h
- ld e, l
- pop hl
- jr .healmon
-
-.done
- xor a
- ld [wWhichPokemon], a
- ld [wd11e], a
-
- ld a, [wPartyCount]
- ld b, a
-.ppup
- push bc
- call RestoreBonusPP
- pop bc
- ld hl, wWhichPokemon
- inc [hl]
- dec b
- jr nz, .ppup
- ret
-
-
-DivideBCDPredef::
-DivideBCDPredef2::
-DivideBCDPredef3::
-DivideBCDPredef4::
- call GetPredefRegisters
-
-DivideBCD::
- xor a
- ld [$ffa5], a
- ld [$ffa6], a
- ld [$ffa7], a
- ld d, $1
-.asm_f72a
- ld a, [$ffa2]
- and $f0
- jr nz, .asm_f75b
- inc d
- ld a, [$ffa2]
- swap a
- and $f0
- ld b, a
- ld a, [$ffa3]
- swap a
- ld [$ffa3], a
- and $f
- or b
- ld [$ffa2], a
- ld a, [$ffa3]
- and $f0
- ld b, a
- ld a, [$ffa4]
- swap a
- ld [$ffa4], a
- and $f
- or b
- ld [$ffa3], a
- ld a, [$ffa4]
- and $f0
- ld [$ffa4], a
- jr .asm_f72a
-.asm_f75b
- push de
- push de
- call DivideBCD_f800
- pop de
- ld a, b
- swap a
- and $f0
- ld [$ffa5], a
- dec d
- jr z, .asm_f7bc
- push de
- call DivideBCD_f7d7
- call DivideBCD_f800
- pop de
- ld a, [$ffa5]
- or b
- ld [$ffa5], a
- dec d
- jr z, .asm_f7bc
- push de
- call DivideBCD_f7d7
- call DivideBCD_f800
- pop de
- ld a, b
- swap a
- and $f0
- ld [$ffa6], a
- dec d
- jr z, .asm_f7bc
- push de
- call DivideBCD_f7d7
- call DivideBCD_f800
- pop de
- ld a, [$ffa6]
- or b
- ld [$ffa6], a
- dec d
- jr z, .asm_f7bc
- push de
- call DivideBCD_f7d7
- call DivideBCD_f800
- pop de
- ld a, b
- swap a
- and $f0
- ld [$ffa7], a
- dec d
- jr z, .asm_f7bc
- push de
- call DivideBCD_f7d7
- call DivideBCD_f800
- pop de
- ld a, [$ffa7]
- or b
- ld [$ffa7], a
-.asm_f7bc
- ld a, [$ffa5]
- ld [$ffa2], a
- ld a, [$ffa6]
- ld [$ffa3], a
- ld a, [$ffa7]
- ld [$ffa4], a
- pop de
- ld a, $6
- sub d
- and a
- ret z
-.asm_f7ce
- push af
- call DivideBCD_f7d7
- pop af
- dec a
- jr nz, .asm_f7ce
- ret
-
-DivideBCD_f7d7:
- ld a, [$ffa4]
- swap a
- and $f
- ld b, a
- ld a, [$ffa3]
- swap a
- ld [$ffa3], a
- and $f0
- or b
- ld [$ffa4], a
- ld a, [$ffa3]
- and $f
- ld b, a
- ld a, [$ffa2]
- swap a
- ld [$ffa2], a
- and $f0
- or b
- ld [$ffa3], a
- ld a, [$ffa2]
- and $f
- ld [$ffa2], a
- ret
-
-DivideBCD_f800:
- ld bc, $3
-.asm_f803
- ld de, $ff9f
- ld hl, $ffa2
- push bc
- call StringCmp
- pop bc
- ret c
- inc b
- ld de, $ffa1
- ld hl, $ffa4
- push bc
- call SubBCD
- pop bc
- jr .asm_f803
-
-
-AddBCDPredef::
- call GetPredefRegisters
-
-AddBCD::
- and a
- ld b, c
-.add
- ld a, [de]
- adc [hl]
- daa
- ld [de], a
- dec de
- dec hl
- dec c
- jr nz, .add
- jr nc, .done
- ld a, $99
- inc de
-.fill
- ld [de], a
- inc de
- dec b
- jr nz, .fill
-.done
- ret
-
-
-SubBCDPredef::
- call GetPredefRegisters
-
-SubBCD::
- and a
- ld b, c
-.sub
- ld a, [de]
- sbc [hl]
- daa
- ld [de], a
- dec de
- dec hl
- dec c
- jr nz, .sub
- jr nc, .done
- ld a, $00
- inc de
-.fill
- ld [de], a
- inc de
- dec b
- jr nz, .fill
- scf
-.done
- ret
-
-
-InitPlayerData:
-InitPlayerData2:
-
- call Random
- ld a, [hRandomSub]
- ld [wPlayerID], a
-
- call Random
- ld a, [hRandomAdd]
- ld [wPlayerID + 1], a
-
- ld a, $ff
- ld [wUnusedD71B], a
-
- ld hl, wPartyCount
- call InitializeEmptyList
- ld hl, wNumInBox
- call InitializeEmptyList
- ld hl, wNumBagItems
- call InitializeEmptyList
- ld hl, wNumBoxItems
- call InitializeEmptyList
-
-START_MONEY EQU $3000
- ld hl, wPlayerMoney + 1
- ld a, START_MONEY / $100
- ld [hld], a
- xor a
- ld [hli], a
- inc hl
- ld [hl], a
-
- ld [wMonDataLocation], a
-
- ld hl, wObtainedBadges
- ld [hli], a
-
- ld [hl], a
-
- ld hl, wPlayerCoins
- ld [hli], a
- ld [hl], a
-
- ld hl, wGameProgressFlags
- ld bc, wGameProgressFlagsEnd - wGameProgressFlags
- call FillMemory ; clear all game progress flags
-
- jp InitializeMissableObjectsFlags
-
-InitializeEmptyList:
- xor a ; count
- ld [hli], a
- dec a ; terminator
- ld [hl], a
- ret
-
-
-GetQuantityOfItemInBag:
-; In: b = item ID
-; Out: b = how many of that item are in the bag
- call GetPredefRegisters
- ld hl, wNumBagItems
-.loop
- inc hl
- ld a, [hli]
- cp $ff
- jr z, .notInBag
- cp b
- jr nz, .loop
- ld a, [hl]
- ld b, a
- ret
-.notInBag
- ld b, 0
- ret
-
-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
+INCLUDE "engine/menu/draw_badges.asm"
+INCLUDE "engine/overworld/update_map.asm"
+INCLUDE "engine/overworld/cut.asm"
+INCLUDE "engine/overworld/missable_objects.asm"
+INCLUDE "engine/overworld/push_boulder.asm"
+
+INCLUDE "engine/add_mon.asm"
+INCLUDE "engine/flag_action.asm"
+INCLUDE "engine/heal_party.asm"
+INCLUDE "engine/bcd.asm"
+INCLUDE "engine/init_player_data.asm"
+INCLUDE "engine/get_bag_item_quantity.asm"
+INCLUDE "engine/pathfinding.asm"
INCLUDE "engine/hp_bar.asm"
-
INCLUDE "engine/hidden_object_functions3.asm"
-
SECTION "NPC Sprites 1", ROMX, BANK[NPC_SPRITES_1]
OakAideSprite: INCBIN "gfx/sprites/oak_aide.2bpp"