pokeyellow/engine/items/items.asm

3121 lines
63 KiB
NASM
Executable File

UseItem_: ; d2ed (3:52ed)
ld a, 1
ld [wActionResultOrTookBattleTurn], a ; initialise to success value
ld a, [wcf91] ;contains item_ID
cp a, HM_01
jp nc, ItemUseTMHM
ld hl, ItemUsePtrTable
dec a
add a
ld c, a
ld b, 0
add hl, bc
ld a, [hli]
ld h, [hl]
ld l, a
jp [hl]
ItemUsePtrTable: ; d307 (3:5307)
dw ItemUseBall ; MASTER_BALL
dw ItemUseBall ; ULTRA_BALL
dw ItemUseBall ; GREAT_BALL
dw ItemUseBall ; POKE_BALL
dw ItemUseTownMap ; TOWN_MAP
dw ItemUseBicycle ; BICYCLE
dw ItemUseSurfboard ; out-of-battle Surf effect
dw ItemUseBall ; SAFARI_BALL
dw ItemUsePokedex ; POKEDEX
dw ItemUseEvoStone ; MOON_STONE
dw ItemUseMedicine ; ANTIDOTE
dw ItemUseMedicine ; BURN_HEAL
dw ItemUseMedicine ; ICE_HEAL
dw ItemUseMedicine ; AWAKENING
dw ItemUseMedicine ; PARLYZ_HEAL
dw ItemUseMedicine ; FULL_RESTORE
dw ItemUseMedicine ; MAX_POTION
dw ItemUseMedicine ; HYPER_POTION
dw ItemUseMedicine ; SUPER_POTION
dw ItemUseMedicine ; POTION
dw ItemUseBait ; BOULDERBADGE
dw ItemUseRock ; CASCADEBADGE
dw UnusableItem ; THUNDERBADGE
dw UnusableItem ; RAINBOWBADGE
dw UnusableItem ; SOULBADGE
dw UnusableItem ; MARSHBADGE
dw UnusableItem ; VOLCANOBADGE
dw UnusableItem ; EARTHBADGE
dw ItemUseEscapeRope ; ESCAPE_ROPE
dw ItemUseRepel ; REPEL
dw UnusableItem ; OLD_AMBER
dw ItemUseEvoStone ; FIRE_STONE
dw ItemUseEvoStone ; THUNDER_STONE
dw ItemUseEvoStone ; WATER_STONE
dw ItemUseVitamin ; HP_UP
dw ItemUseVitamin ; PROTEIN
dw ItemUseVitamin ; IRON
dw ItemUseVitamin ; CARBOS
dw ItemUseVitamin ; CALCIUM
dw ItemUseVitamin ; RARE_CANDY
dw UnusableItem ; DOME_FOSSIL
dw UnusableItem ; HELIX_FOSSIL
dw UnusableItem ; SECRET_KEY
dw UnusableItem
dw UnusableItem ; BIKE_VOUCHER
dw ItemUseXAccuracy ; X_ACCURACY
dw ItemUseEvoStone ; LEAF_STONE
dw ItemUseCardKey ; CARD_KEY
dw UnusableItem ; NUGGET
dw UnusableItem ; ??? PP_UP
dw ItemUsePokedoll ; POKE_DOLL
dw ItemUseMedicine ; FULL_HEAL
dw ItemUseMedicine ; REVIVE
dw ItemUseMedicine ; MAX_REVIVE
dw ItemUseGuardSpec ; GUARD_SPEC
dw ItemUseSuperRepel ; SUPER_REPL
dw ItemUseMaxRepel ; MAX_REPEL
dw ItemUseDireHit ; DIRE_HIT
dw UnusableItem ; COIN
dw ItemUseMedicine ; FRESH_WATER
dw ItemUseMedicine ; SODA_POP
dw ItemUseMedicine ; LEMONADE
dw UnusableItem ; S_S_TICKET
dw UnusableItem ; GOLD_TEETH
dw ItemUseXStat ; X_ATTACK
dw ItemUseXStat ; X_DEFEND
dw ItemUseXStat ; X_SPEED
dw ItemUseXStat ; X_SPECIAL
dw ItemUseCoinCase ; COIN_CASE
dw ItemUseOaksParcel ; OAKS_PARCEL
dw ItemUseItemfinder ; ITEMFINDER
dw UnusableItem ; SILPH_SCOPE
dw ItemUsePokeflute ; POKE_FLUTE
dw UnusableItem ; LIFT_KEY
dw UnusableItem ; EXP_ALL
dw ItemUseOldRod ; OLD_ROD
dw ItemUseGoodRod ; GOOD_ROD
dw ItemUseSuperRod ; SUPER_ROD
dw ItemUsePPUp ; PP_UP (real one)
dw ItemUsePPRestore ; ETHER
dw ItemUsePPRestore ; MAX_ETHER
dw ItemUsePPRestore ; ELIXER
dw ItemUsePPRestore ; MAX_ELIXER
ItemUseBall: ; d3ad (3:53ad)
ld a, [wIsInBattle]
and a
jp z, ItemUseNotTime ; not in battle
dec a
jp nz, ThrowBallAtTrainerMon
ld a, [wBattleType]
cp $1
jr z, .UseBall
cp $4 ; pikachu battle?
jr z, .UseBall
ld a, [wPartyCount] ;is Party full?
cp a, PARTY_LENGTH
jr nz, .UseBall
ld a, [wNumInBox] ;is Box full?
cp a, MONS_PER_BOX
jp z, BoxFullCannotThrowBall
.UseBall
;ok, you can use a ball
xor a
ld [wCapturedMonSpecies], a
ld a, [wBattleType]
cp a, 2 ;SafariBattle
jr nz, .skipSafariZoneCode
.safariZone
; remove a Safari Ball from inventory
ld hl, wNumSafariBalls
dec [hl]
.skipSafariZoneCode
call RunDefaultPaletteCommand
ld a, $43
ld [wd11e], a
call LoadScreenTilesFromBuffer1 ;restore screenBuffer from Backup
ld hl, ItemUseText00
call PrintText
callab IsGhostBattle
ld b, $10
jp z, .next12
ld a, [wBattleType]
cp $1
jr z, .oldManBattle
cp $4
jr z, .oldManBattle ; pikachu battle technically old man battle
jr .notOldManBattle
.oldManBattle
ld hl, wGrassRate
ld de, wPlayerName
ld bc, NAME_LENGTH
call CopyData ; save the player's name in the Wild Monster data
ld a, [wBattleType]
cp $1
jp nz, .BallSuccess
ld a, $1
ld [wCapturedMonSpecies], a
ld a, [wd74c]
bit 7, a
ld b, $63
jp nz, .next12
jp .BallSuccess
.notOldManBattle
ld a, [wCurMap]
cp a, POKEMONTOWER_6
jr nz, .loop
ld a, [wEnemyMonSpecies2]
cp a, MAROWAK
ld b, $10
jp z, .next12
; if not fighting ghost Marowak, loop until a random number in the current
; pokeball's allowed range is found
.loop
call Random
ld b, a
ld hl, wcf91
.asm_d54a
ld a, [hl]
cp a, MASTER_BALL
jp z, .BallSuccess
cp a, POKE_BALL
jr z, .checkForAilments
ld a, 200
cp b
jr c, .loop ;get only numbers <= 200 for Great Ball
ld a, [hl]
cp a, GREAT_BALL
jr z, .checkForAilments
ld a, 150 ;get only numbers <= 150 for Ultra Ball
cp b
jr c, .loop
.checkForAilments
; pokemon can be caught more easily with any (primary) status ailment
; Frozen/Asleep pokemon are relatively even easier to catch
; for Frozen/Asleep pokemon, any random number from 0-24 ensures a catch.
; for the others, a random number from 0-11 ensures a catch.
ld a, [wEnemyMonStatus] ;status ailments
and a
jr z, .noAilments
and a, 1 << FRZ | SLP ;is frozen and/or asleep?
ld c, 12
jr z, .notFrozenOrAsleep
ld c, 25
.notFrozenOrAsleep
ld a, b
sub c
jp c, .BallSuccess
ld b, a
.noAilments
push bc ;save RANDOM number
xor a
ld [H_MULTIPLICAND], a
ld hl, wEnemyMonMaxHP
ld a, [hli]
ld [H_MULTIPLICAND + 1], a
ld a, [hl]
ld [H_MULTIPLICAND + 2], a
ld a, 255
ld [H_MULTIPLIER], a
call Multiply ; MaxHP * 255
ld a, [wcf91]
cp GREAT_BALL
ld a, 12 ;any other BallFactor
jr nz, .next7
ld a, 8
.next7
ld [H_DIVISOR], a
ld b, 4 ; number of bytes in dividend
call Divide
ld hl, wEnemyMonHP
ld a, [hli]
ld b, a
ld a, [hl]
; explanation: we have a 16-bit value equal to [b << 8 | a].
; This number is divided by 4. The result is 8 bit (reg. a).
; Always bigger than zero.
srl b
rr a
srl b
rr a ; a = current HP / 4
and a
jr nz, .next8
inc a
.next8
ld [H_DIVISOR], a
ld b, 4
call Divide ; ((MaxHP * 255) / BallFactor) / (CurHP / 4)
ld a, [H_QUOTIENT + 2]
and a
jr z, .next9
ld a, 255
ld [H_QUOTIENT + 3], a
.next9
pop bc
ld a, [wEnemyMonCatchRate] ;enemy: Catch Rate
cp b
jr c, .next10
ld a, [H_QUOTIENT + 2]
and a
jr nz, .BallSuccess ; if ((MaxHP * 255) / BallFactor) / (CurHP / 4) > 0x255, automatic success
call Random
ld b, a
ld a, [H_QUOTIENT + 3]
cp b
jr c, .next10
.BallSuccess
jr .BallSuccess2
.next10
ld a, [H_QUOTIENT + 3]
ld [wd11e], a
xor a
ld [H_MULTIPLICAND], a
ld [H_MULTIPLICAND + 1], a
ld a, [wEnemyMonCatchRate] ;enemy: Catch Rate
ld [H_MULTIPLICAND + 2], a
ld a, 100
ld [H_MULTIPLIER], a
call Multiply ; CatchRate * 100
ld a, [wcf91]
ld b, 255
cp POKE_BALL
jr z, .next11
ld b, 200
cp GREAT_BALL
jr z, .next11
ld b, 150
cp ULTRA_BALL
jr z, .next11
.next11
ld a, b
ld [H_DIVISOR], a
ld b, 4
call Divide
ld a, [H_QUOTIENT + 2]
and a
ld b, $63
jr nz, .next12
ld a, [wd11e]
ld [H_MULTIPLIER], a
call Multiply
ld a, 255
ld [H_DIVISOR], a
ld b, 4
call Divide
ld a, [wEnemyMonStatus] ;status ailments
and a
jr z, .next13
and 1 << FRZ | SLP
ld b, 5
jr z, .next14
ld b, 10
.next14
ld a, [H_QUOTIENT + 3]
add b
ld [H_QUOTIENT + 3], a
.next13
ld a, [H_QUOTIENT + 3]
cp a, 10
ld b, $20
jr c, .next12
cp a, 30
ld b, $61
jr c, .next12
cp a, 70
ld b, $62
jr c, .next12
ld b, $63
.next12
ld a, b
ld [wPokeBallAnimData], a
.BallSuccess2
ld c, 20
call DelayFrames
ld a, TOSS_ANIM
ld [wAnimationID], a
xor a
ld [H_WHOSETURN], a
ld [wAnimationType], a
ld [wDamageMultipliers], a
ld a, [wWhichPokemon]
push af
ld a, [wcf91]
push af
predef MoveAnimation
pop af
ld [wcf91], a
pop af
ld [wWhichPokemon], a
ld a, [wPokeBallAnimData]
cp a, $10
ld hl, ItemUseBallText00
jp z, .printText0
cp a, $20
ld hl, ItemUseBallText01
jp z, .printText0
cp a, $61
ld hl, ItemUseBallText02
jp z, .printText0
cp a, $62
ld hl, ItemUseBallText03
jp z, .printText0
cp a, $63
ld hl, ItemUseBallText04
jp z, .printText0
ld hl, wEnemyMonHP ;current HP
ld a, [hli]
push af
ld a, [hli]
push af ;backup currentHP...
inc hl
ld a, [hl]
push af ;...and status ailments
push hl
ld hl, wEnemyBattleStatus3
bit Transformed, [hl]
jr z, .next15
ld a, $4c
ld [wEnemyMonSpecies2], a
jr .next16
.next15
set Transformed, [hl]
ld hl, wTransformedEnemyMonOriginalDVs
ld a, [wEnemyMonDVs]
ld [hli], a
ld a, [wEnemyMonDVs + 1]
ld [hl], a
.next16
ld a, [wcf91]
push af
ld a, [wEnemyMonSpecies2]
ld [wcf91], a
ld a, [wEnemyMonLevel]
ld [wCurEnemyLVL], a
callab LoadEnemyMonData
pop af
ld [wcf91], a
pop hl
pop af
ld [hld], a
dec hl
pop af
ld [hld], a
pop af
ld [hl], a
ld a, [wEnemyMonSpecies] ;enemy
ld [wCapturedMonSpecies], a
ld [wcf91], a
ld [wd11e], a
ld a, [wBattleType]
cp $1
jp z, .printText1 ; just barely out of reach for a relative jump
cp $4
jr z, .printText1
ld hl, ItemUseBallText05
call PrintText
predef IndexToPokedex
ld a, [wd11e]
dec a
ld c, a
ld b, FLAG_TEST
ld hl, wPokedexOwned
predef FlagActionPredef
ld a, c
push af
ld a, [wd11e]
dec a
ld c, a
ld b, FLAG_SET
predef FlagActionPredef
pop af
and a
jr nz, .checkParty
ld hl, ItemUseBallText06
call PrintText
call ClearSprites
ld a, [wEnemyMonSpecies] ;caught mon_ID
ld [wd11e], a
predef ShowPokedexData
.checkParty
ld a, $1
ld [wd49c], a
ld a, $85
ld [wPikachuMood], a
ld a, [wPartyCount]
cp PARTY_LENGTH ;is party full?
jr z, .sendToBox
xor a ; PLAYER_PARTY_DATA
ld [wMonDataLocation], a
call ClearSprites
ld hl, .emptyString
call PrintText
call AddPartyMon ;add mon to Party
jr .End
.sendToBox
call ClearSprites
call SendNewMonToBox
ld hl, ItemUseBallText07
ld a, [wd7f1]
bit 0, a
jr nz, .sendToBox2
ld hl, ItemUseBallText08
.sendToBox2
call PrintText
jr .End
.printText1
ld hl, ItemUseBallText05
.printText0
call PrintText
call ClearSprites
.End
ld a, [wBattleType]
and a
ret nz
ld hl, wNumBagItems
inc a
ld [wItemQuantity], a
jp RemoveItemFromInventory
.emptyString
db "@"
ItemUseBallText00: ; d697 (3:5697)
;"It dodged the thrown ball!"
;"This pokemon can't be caught"
TX_FAR _ItemUseBallText00
db "@"
ItemUseBallText01: ; d69c (3:569c)
;"You missed the pokemon!"
TX_FAR _ItemUseBallText01
db "@"
ItemUseBallText02: ; d6a1 (3:56a1)
;"Darn! The pokemon broke free!"
TX_FAR _ItemUseBallText02
db "@"
ItemUseBallText03: ; d6a6 (3:56a6)
;"Aww! It appeared to be caught!"
TX_FAR _ItemUseBallText03
db "@"
ItemUseBallText04: ; d6ab (3:56ab)
;"Shoot! It was so close too!"
TX_FAR _ItemUseBallText04
db "@"
ItemUseBallText05: ; d6b0 (3:56b0)
;"All right! {MonName} was caught!"
;play sound
TX_FAR _ItemUseBallText05
db $12, $06
db "@"
ItemUseBallText07: ; d6b7 (3:59b7)
;"X was transferred to Bill's PC"
TX_FAR _ItemUseBallText07
db "@"
ItemUseBallText08: ; d6bc (3:56bc)
;"X was transferred to someone's PC"
TX_FAR _ItemUseBallText08
db "@"
ItemUseBallText06: ; d6c1 (3:56c1)
;"New DEX data will be added..."
;play sound
TX_FAR _ItemUseBallText06
db $13, $06
db "@"
ItemUseTownMap: ; d6c8 (3:56c8)
ld a, [wIsInBattle]
and a
jp nz, ItemUseNotTime
jpba DisplayTownMap
ItemUseBicycle: ; d6d7 (3:56d7)
ld a, [wIsInBattle]
and a
jp nz, ItemUseNotTime
ld a, [wWalkBikeSurfState]
ld [wWalkBikeSurfStateCopy], a
cp a, 2 ; is the player surfing?
jp z, ItemUseNotTime
dec a ; is player already bicycling?
jr nz, .tryToGetOnBike
.getOffBike
call ItemUseReloadOverworldData
xor a
ld [wWalkBikeSurfState], a ; change player state to walking
ld a, $00
ld [wPikachuSpawnState], a
call PlayDefaultMusic ; play walking music
ld hl, GotOffBicycleText
jp PrintText
.tryToGetOnBike
call IsBikeRidingAllowed
jp nc, NoCyclingAllowedHere
call ItemUseReloadOverworldData
xor a ; no keys pressed
ld [hJoyHeld], a ; current joypad state
ld a, $1
ld [wWalkBikeSurfState], a ; change player state to bicycling
call PlayDefaultMusic ; play bike riding music
xor a
ld [wWalkBikeSurfState], a
ld hl, GotOnBicycleText
call PrintText
ld a, $1
ld [wWalkBikeSurfState], a
ret
; used for Surf out-of-battle effect
ItemUseSurfboard: ; d725 (3:5725)
ld a, [wWalkBikeSurfState]
ld [wWalkBikeSurfStateCopy], a
cp a, 2 ; is the player already surfing?
jr z, .tryToStopSurfing
.tryToSurf
call IsNextTileShoreOrWater
jp nc, SurfingAttemptFailed
ld hl, TilePairCollisionsWater
call CheckForTilePairCollisions
jp c, SurfingAttemptFailed
.surf
call .makePlayerMoveForward
ld hl, wd730
set 7, [hl]
ld a, 2
ld [wWalkBikeSurfState], a ; change player state to surfing
call PlayDefaultMusic ; play surfing music
ld hl, SurfingGotOnText
jp PrintText
.tryToStopSurfing
xor a
ld [hSpriteIndexOrTextID], a
ld d, 16 ; talking range in pixels (normal range)
call IsSpriteInFrontOfPlayer2
res 7, [hl]
ld a, [hSpriteIndexOrTextID]
and a ; is there a sprite in the way?
jr nz, .cannotStopSurfing
ld hl, TilePairCollisionsWater
call CheckForTilePairCollisions
jr c, .cannotStopSurfing
ld a, [wTileInFrontOfPlayer]
ld c, a
call IsTilePassable
jr nc, .stopSurfing
.cannotStopSurfing
ld hl, SurfingNoPlaceToGetOffText
jp PrintText
.stopSurfing
call .makePlayerMoveForward
ld a, $3
ld [wPikachuSpawnState], a
ld hl, wPikachuOverworldStateFlags
set 5, [hl]
ld hl, wd730
set 7, [hl]
xor a
ld [wWalkBikeSurfState], a ; change player state to walking
dec a
ld [wJoyIgnore], a
call PlayDefaultMusic ; play walking music
call GBPalWhiteOutWithDelay3
jp LoadWalkingPlayerSpriteGraphics
; uses a simulated button press to make the player move forward
.makePlayerMoveForward
ld a, [wPlayerDirection] ; direction the player is going
bit PLAYER_DIR_BIT_UP, a
ld b, D_UP
jr nz, .storeSimulatedButtonPress
bit PLAYER_DIR_BIT_DOWN, a
ld b, D_DOWN
jr nz, .storeSimulatedButtonPress
bit PLAYER_DIR_BIT_LEFT, a
ld b, D_LEFT
jr nz, .storeSimulatedButtonPress
ld b, D_RIGHT
.storeSimulatedButtonPress
ld a, b
ld [wSimulatedJoypadStatesEnd], a
xor a
ld [wWastedByteCD39], a
inc a
ld [wSimulatedJoypadStatesIndex], a
ret
SurfingGotOnText: ; d7c1 (3:57c1)
TX_FAR _SurfingGotOnText
db "@"
SurfingNoPlaceToGetOffText: ; d7c6 (3:57c6)
TX_FAR _SurfingNoPlaceToGetOffText
db "@"
ItemUsePokedex: ; d7cb (3:57cb)
predef_jump ShowPokedexMenu
ItemUseEvoStone: ; d7d0 (3:57d0)
ld a, [wIsInBattle]
and a
jp nz, ItemUseNotTime
ld a, [wWhichPokemon]
push af
ld a, [wcf91]
ld [wEvoStoneItemID], a
push af
ld a, EVO_STONE_PARTY_MENU
ld [wPartyMenuTypeOrMessageID], a
ld a, $ff
ld [wUpdateSpritesEnabled], a
call DisplayPartyMenu
ld a, [wcf91]
ld [wLoadedMon], a
pop bc
jr c, .canceledItemUse
ld a, b
ld [wcf91], a
call Func_d85d
jr nc, .noEffect
callab IsThisPartymonStarterPikachu_Party
jr nc, .notPlayerPikachu
ld e, $1b
callab PlayPikachuSoundClip
ld a, [wWhichPokemon]
ld hl, wPartyMonNicks
call GetPartyMonName
ld hl, RefusingText
call PrintText
ld a, $4
ld [wd49c], a
ld a, $82
ld [wPikachuMood], a
jr .canceledItemUse
.notPlayerPikachu
ld a, SFX_HEAL_AILMENT
call PlaySoundWaitForCurrent
call WaitForSoundToFinish
ld a, $01
ld [wForceEvolution], a
callab TryEvolvingMon ; try to evolve pokemon
pop af
ld [wWhichPokemon], a
ld hl, wNumBagItems
ld a, 1 ; remove 1 stone
ld [wItemQuantity], a
jp RemoveItemFromInventory
.noEffect
call ItemUseNoEffect
.canceledItemUse
xor a
ld [wActionResultOrTookBattleTurn], a ; item not used
pop af
ret
Func_d85d: ; d85d (3:585d)
ld hl, EvosMovesPointerTable
ld a, [wLoadedMon]
dec a
ld c, a
ld b, $0
add hl, bc
add hl, bc
ld de, wcd6d
ld a, BANK(TryEvolvingMon)
ld bc, $2
call FarCopyData
ld hl, wcd6d
ld a, [hli]
ld h, [hl]
ld l, a
ld de, wcd6d
ld a, BANK(TryEvolvingMon)
ld bc, 13
call FarCopyData
ld hl, wcd6d
.loop
ld a, [hli]
and a
jr z, .cannotEvolveWithUsedStone
inc hl
inc hl
cp EV_ITEM
jr nz, .loop
dec hl
dec hl
ld b, [hl]
ld a, [wcf91]
inc hl
inc hl
inc hl
cp b
jr nz, .loop
scf
ret
.cannotEvolveWithUsedStone
and a
ret
RefusingText: ; d8a2 (3:58a2)
TX_FAR _RefusingText
db "@"
ItemUseVitamin: ; d8a7 (3:58a7)
ld a, [wIsInBattle]
and a
jp nz, ItemUseNotTime
ItemUseMedicine: ; d8ae (3:58ae)
ld a, [wPartyCount]
and a
jp z, Func_e4bf
ld a, [wWhichPokemon]
push af
ld a, [wcf91]
push af
ld a, USE_ITEM_PARTY_MENU
ld [wPartyMenuTypeOrMessageID], a
ld a, $ff
ld [wUpdateSpritesEnabled], a
ld a, [wPseudoItemID]
and a ; using Softboiled?
jr z, .notUsingSoftboiled
; if using softboiled
call GoBackToPartyMenu
jr .getPartyMonDataAddress
.notUsingSoftboiled
call DisplayPartyMenu
.getPartyMonDataAddress
jp c, .canceledItemUse
ld hl, wPartyMons
ld bc, wPartyMon2 - wPartyMon1
ld a, [wWhichPokemon]
call AddNTimes
ld a, [wWhichPokemon]
ld [wUsedItemOnWhichPokemon], a
ld d, a
ld a, [wcf91]
ld e, a
ld [wd0b5], a
pop af
push af
cp $28
jr nc, .asm_d906
push hl
push de
callabd_ModifyPikachuHappiness PIKAHAPPY_USEDITEM
pop de
pop hl
.asm_d906
pop af
ld [wcf91], a
pop af
ld [wWhichPokemon], a
ld a, [wPseudoItemID]
and a ; using Softboiled?
jr z, .checkItemType
; if using softboiled
ld a, [wWhichPokemon]
cp d ; is the pokemon trying to use softboiled on itself?
jr z, ItemUseMedicine ; if so, force another choice
.checkItemType
ld a, [wcf91]
cp a, REVIVE
jr nc, .healHP ; if it's a Revive or Max Revive
cp a, FULL_HEAL
jr z, .cureStatusAilment ; if it's a Full Heal
cp a, HP_UP
jp nc, .useVitamin ; if it's a vitamin or Rare Candy
cp a, FULL_RESTORE
jr nc, .healHP ; if it's a Full Restore or one of the potions
; fall through if it's one of the status-specifc healing items
.cureStatusAilment
ld bc, 4
add hl, bc ; hl now points to status
ld a, [wcf91]
lb bc, ANTIDOTE_MSG, 1 << PSN
cp a, ANTIDOTE
jr z, .checkMonStatus
lb bc, BURN_HEAL_MSG, 1 << BRN
cp a, BURN_HEAL
jr z, .checkMonStatus
lb bc, ICE_HEAL_MSG, 1 << FRZ
cp a, ICE_HEAL
jr z, .checkMonStatus
lb bc, AWAKENING_MSG, SLP
cp a, AWAKENING
jr z, .checkMonStatus
lb bc, PARALYZ_HEAL_MSG, 1 << PAR
cp a, PARLYZ_HEAL
jr z, .checkMonStatus
lb bc, FULL_HEAL_MSG, $ff ; Full Heal
.checkMonStatus
ld a, [hl] ; pokemon's status
and c ; does the pokemon have a status ailment the item can cure?
jp z, .healingItemNoEffect
; if the pokemon has a status the item can heal
xor a
ld [hl], a ; remove the status ailment in the party data
ld a, b
ld [wPartyMenuTypeOrMessageID], a ; the message to display for the item used
ld a, [wPlayerMonNumber]
cp d ; is pokemon the item was used on active in battle?
jp nz, .doneHealing
; if it is active in battle
xor a
ld [wBattleMonStatus], a ; remove the status ailment in the in-battle pokemon data
push hl
ld hl, wPlayerBattleStatus3
res BadlyPoisoned, [hl] ; heal Toxic status
pop hl
ld bc, 30
add hl, bc ; hl now points to party stats
ld de, wBattleMonMaxHP
ld bc, 10
call CopyData ; copy party stats to in-battle stat data
predef DoubleOrHalveSelectedStats
jp .doneHealing
.healHP
inc hl ; hl = address of current HP
ld a, [hli]
ld b, a
ld [wHPBarOldHP+1], a
ld a, [hl]
ld c, a
ld [wHPBarOldHP], a ; current HP stored at wHPBarOldHP (2 bytes, big-endian)
or b
jr nz, .notFainted
.fainted
ld a, [wcf91]
cp a, REVIVE
jr z, .updateInBattleFaintedData
cp a, MAX_REVIVE
jr z, .updateInBattleFaintedData
jp .healingItemNoEffect
.updateInBattleFaintedData
ld a, [wWhichPokemon]
push af
ld a, [wUsedItemOnWhichPokemon]
ld [wWhichPokemon], a
push hl
push de
push bc
callab Func_2fd6a
pop bc
pop de
pop hl
pop af
ld [wWhichPokemon], a
ld a, [wIsInBattle]
and a
jr z, .compareCurrentHPToMaxHP
push hl
push de
push bc
ld a, [wUsedItemOnWhichPokemon]
ld c, a
ld hl, wPartyFoughtCurrentEnemyFlags
ld b, FLAG_TEST
predef FlagActionPredef
ld a, c
and a
jr z, .next
ld a, [wUsedItemOnWhichPokemon]
ld c, a
ld hl, wPartyGainExpFlags
ld b, FLAG_SET
predef FlagActionPredef
.next
pop bc
pop de
pop hl
jr .compareCurrentHPToMaxHP
.notFainted
ld a, [wcf91]
cp a, REVIVE
jp z, .healingItemNoEffect
cp a, MAX_REVIVE
jp z, .healingItemNoEffect
.compareCurrentHPToMaxHP
push hl
push bc
ld bc, 32
add hl, bc ; hl now points to max HP
pop bc
ld a, [hli]
cp b
jr nz, .skipComparingLSB ; no need to compare the LSB's if the MSB's don't match
ld a, [hl]
cp c
.skipComparingLSB
pop hl
jr nz, .notFullHP
.fullHP ; if the pokemon's current HP equals its max HP
ld a, [wcf91]
cp a, FULL_RESTORE
jp nz, .healingItemNoEffect
inc hl
inc hl
ld a, [hld] ; status ailment
and a ; does the pokemon have a status ailment?
jp z, .healingItemNoEffect
ld a, FULL_HEAL
ld [wcf91], a
dec hl
dec hl
dec hl
jp .cureStatusAilment
.notFullHP ; if the pokemon's current HP doesn't equal its max HP
xor a
ld [wLowHealthAlarm], a ;disable low health alarm
ld [wChannelSoundIDs + CH4], a
push hl
push de
ld bc, 32
add hl, bc ; hl now points to max HP
ld a, [hli]
ld [wHPBarMaxHP+1], a
ld a, [hl]
ld [wHPBarMaxHP], a ; max HP stored at wHPBarMaxHP (2 bytes, big-endian)
ld a, [wPseudoItemID]
and a ; using Softboiled?
jp z, .notUsingSoftboiled2
; if using softboiled
ld hl, wHPBarMaxHP
ld a, [hli]
push af
ld a, [hli]
push af
ld a, [hli]
push af
ld a, [hl]
push af
ld hl, wPartyMon1MaxHP
ld a, [wWhichPokemon]
ld bc, wPartyMon2 - wPartyMon1
call AddNTimes
ld a, [hli]
ld [wHPBarMaxHP + 1], a
ld [H_DIVIDEND], a
ld a, [hl]
ld [wHPBarMaxHP], a
ld [H_DIVIDEND + 1], a
ld a, 5
ld [H_DIVISOR], a
ld b, 2 ; number of bytes
call Divide ; get 1/5 of max HP of pokemon that used Softboiled
ld bc, wPartyMon1HP - wPartyMon1MaxHP
add hl, bc ; hl now points to LSB of current HP of pokemon that used Softboiled
; subtract 1/5 of max HP from current HP of pokemon that used Softboiled
ld a, [H_QUOTIENT + 3]
push af
ld b, a
ld a, [hl]
ld [wHPBarOldHP], a
sub b
ld [hld], a
ld [wHPBarNewHP], a
ld a, [H_QUOTIENT + 2]
ld b, a
ld a, [hl]
ld [wHPBarOldHP+1], a
sbc b
ld [hl], a
ld [wHPBarNewHP+1], a
coord hl, 4, 1
ld a, [wWhichPokemon]
ld bc, 2 * SCREEN_WIDTH
call AddNTimes ; calculate coordinates of HP bar of pokemon that used Softboiled
ld a, SFX_HEAL_HP
call PlaySoundWaitForCurrent
ld a, [hFlags_0xFFFA]
set 0, a
ld [hFlags_0xFFFA], a
ld a, $02
ld [wHPBarType], a
predef UpdateHPBar2 ; animate HP bar decrease of pokemon that used Softboiled
ld a, [hFlags_0xFFFA]
res 0, a
ld [hFlags_0xFFFA], a
pop af
ld b, a ; store heal amount (1/5 of max HP)
ld hl, wHPBarOldHP + 1
pop af
ld [hld], a
pop af
ld [hld], a
pop af
ld [hld], a
pop af
ld [hl], a
jr .addHealAmount
.notUsingSoftboiled2
ld a, [wcf91]
cp a, SODA_POP
ld b, 60 ; Soda Pop heal amount
jr z, .addHealAmount
ld b, 80 ; Lemonade heal amount
jr nc, .addHealAmount
cp a, FRESH_WATER
ld b, 50 ; Fresh Water heal amount
jr z, .addHealAmount
cp a, SUPER_POTION
ld b, 200 ; Hyper Potion heal amount
jr c, .addHealAmount
ld b, 50 ; Super Potion heal amount
jr z, .addHealAmount
ld b, 20 ; Potion heal amount
.addHealAmount
pop de
pop hl
ld a, [hl]
add b
ld [hld], a
ld [wHPBarNewHP], a
ld a, [hl]
ld [wHPBarNewHP+1], a
jr nc, .noCarry
inc [hl]
ld a, [hl]
ld [wHPBarNewHP + 1], a
.noCarry
push de
inc hl
ld d, h
ld e, l ; de now points to current HP
ld hl, 33
add hl, de ; hl now points to max HP
ld a, [wcf91]
cp a, REVIVE
jr z, .setCurrentHPToHalfMaxHP
ld a, [hld]
ld b, a
ld a, [de]
sub b
dec de
ld b, [hl]
ld a, [de]
sbc b
jr nc, .setCurrentHPToMaxHp ; if current HP exceeds max HP after healing
ld a, [wcf91]
cp a, HYPER_POTION
jr c, .setCurrentHPToMaxHp ; if using a Full Restore or Max Potion
cp a, MAX_REVIVE
jr z, .setCurrentHPToMaxHp ; if using a Max Revive
jr .updateInBattleData
.setCurrentHPToHalfMaxHP
dec hl
dec de
ld a, [hli]
srl a
ld [de], a
ld [wHPBarNewHP+1], a
ld a, [hl]
rr a
inc de
ld [de], a
ld [wHPBarNewHP], a
dec de
jr .doneHealingPartyHP
.setCurrentHPToMaxHp
ld a, [hli]
ld [de], a
ld [wHPBarNewHP+1], a
inc de
ld a, [hl]
ld [de], a
ld [wHPBarNewHP], a
dec de
.doneHealingPartyHP ; done updating the pokemon's current HP in the party data structure
ld a, [wcf91]
cp a, FULL_RESTORE
jr nz, .updateInBattleData
ld bc, -31
add hl, bc
xor a
ld [hl], a ; remove the status ailment in the party data
.updateInBattleData
ld h, d
ld l, e
pop de
ld a, [wPlayerMonNumber]
cp d ; is pokemon the item was used on active in battle?
jr nz, .calculateHPBarCoords
; copy party HP to in-battle HP
ld a, [hli]
ld [wBattleMonHP], a
ld a, [hld]
ld [wBattleMonHP + 1], a
ld a, [wcf91]
cp a, FULL_RESTORE
jr nz, .calculateHPBarCoords
xor a
ld [wBattleMonStatus], a ; remove the status ailment in the in-battle pokemon data
.calculateHPBarCoords
ld hl, wOAMBuffer + $90
ld bc, 2 * 20
inc d
.calculateHPBarCoordsLoop
add hl, bc
dec d
jr nz, .calculateHPBarCoordsLoop
jr .doneHealing
.healingItemNoEffect
call ItemUseNoEffect
jp .done
.doneHealing
ld a, [wPseudoItemID]
and a ; using Softboiled?
jr nz, .skipRemovingItem ; no item to remove if using Softboiled
push hl
call RemoveUsedItem
pop hl
.skipRemovingItem
ld a, [wcf91]
cp a, FULL_RESTORE
jr c, .playStatusAilmentCuringSound
cp a, FULL_HEAL
jr z, .playStatusAilmentCuringSound
ld a, SFX_HEAL_HP
call PlaySoundWaitForCurrent
ld a, [hFlags_0xFFFA]
set 0, a
ld [hFlags_0xFFFA], a
ld a, $02
ld [wHPBarType], a
predef UpdateHPBar2 ; animate the HP bar lengthening
ld a, [hFlags_0xFFFA]
res 0, a
ld [hFlags_0xFFFA], a
ld a, REVIVE_MSG
ld [wPartyMenuTypeOrMessageID], a
ld a, [wcf91]
cp a, REVIVE
jr z, .showHealingItemMessage
cp a, MAX_REVIVE
jr z, .showHealingItemMessage
ld a, POTION_MSG
ld [wPartyMenuTypeOrMessageID], a
jr .showHealingItemMessage
.playStatusAilmentCuringSound
ld a, SFX_HEAL_AILMENT
call PlaySoundWaitForCurrent
.showHealingItemMessage
xor a
ld [H_AUTOBGTRANSFERENABLED], a
call ClearScreen
dec a
ld [wUpdateSpritesEnabled], a
call RedrawPartyMenu ; redraws the party menu and displays the message
ld a, 1
ld [H_AUTOBGTRANSFERENABLED], a
ld c, 50
call DelayFrames
call WaitForTextScrollButtonPress
jr .done
.canceledItemUse
xor a
ld [wActionResultOrTookBattleTurn], a ; item use failed
pop af
pop af
.done
ld a, [wPseudoItemID]
and a ; using Softboiled?
ret nz ; if so, return
call GBPalWhiteOut
call z, RunDefaultPaletteCommand
ld a, [wIsInBattle]
and a
ret nz
jp ReloadMapData
.useVitamin
push hl
ld a, [hl]
ld [wd0b5], a
ld [wd11e], a
ld bc, 33
add hl, bc ; hl now points to level
ld a, [hl] ; a = level
ld [wCurEnemyLVL], a ; store level
call GetMonHeader
push de
ld a, d
ld hl, wPartyMonNicks
call GetPartyMonName
pop de
pop hl
ld a, [wcf91]
cp a, RARE_CANDY
jp z, .useRareCandy
push hl
sub a, HP_UP
add a
ld bc, 17
add hl, bc
add l
ld l, a
jr nc, .noCarry2
inc h
.noCarry2
ld a, 10
ld b, a
ld a, [hl] ; a = MSB of stat experience of the appropriate stat
cp a, 100 ; is there already at least 25600 (256 * 100) stat experience?
jr nc, .vitaminNoEffect ; if so, vitamins can't add any more
add b ; add 2560 (256 * 10) stat experience
jr nc, .noCarry3 ; a carry should be impossible here, so this will always jump
ld a, 255
.noCarry3
ld [hl], a
pop hl
call .recalculateStats
ld hl, VitaminText
ld a, [wcf91]
sub a, HP_UP - 1
ld c, a
.statNameLoop ; loop to get the address of the name of the stat the vitamin increases
dec c
jr z, .gotStatName
.statNameInnerLoop
ld a, [hli]
ld b, a
ld a, $50
cp b
jr nz, .statNameInnerLoop
jr .statNameLoop
.gotStatName
ld de, wcf4b
ld bc, 10
call CopyData ; copy the stat's name to wcf4b
ld a, SFX_HEAL_AILMENT
call PlaySound
ld hl, VitaminStatRoseText
call PrintText
jp RemoveUsedItem
.vitaminNoEffect
pop hl
ld hl, VitaminNoEffectText
call PrintText
jp GBPalWhiteOut
.recalculateStats
ld bc, 34
add hl, bc
ld d, h
ld e, l ; de now points to stats
ld bc, -18
add hl, bc ; hl now points to byte 3 of experience
ld b, 1
jp CalcStats ; recalculate stats
.useRareCandy
push hl
ld bc, 33
add hl, bc ; hl now points to level
ld a, [hl] ; a = level
cp a, MAX_LEVEL
jr z, .vitaminNoEffect ; can't raise level above 100
inc a
ld [hl], a ; store incremented level
ld [wCurEnemyLVL], a
push hl
push de
ld d, a
callab CalcExperience ; calculate experience for next level and store it at $ff96
pop de
pop hl
ld bc, -19
add hl, bc ; hl now points to experience
; update experience to minimum for new level
ld a, [hExperience]
ld [hli], a
ld a, [hExperience + 1]
ld [hli], a
ld a, [hExperience + 2]
ld [hl], a
pop hl
ld a, [wWhichPokemon]
push af
ld a, [wcf91]
push af
push de
push hl
ld bc, 34
add hl, bc ; hl now points to MSB of max HP
ld a, [hli]
ld b, a
ld c, [hl]
pop hl
push bc
push hl
call .recalculateStats
pop hl
ld bc, 35 ; hl now points to LSB of max HP
add hl, bc
pop bc
ld a, [hld]
sub c
ld c, a
ld a, [hl]
sbc b
ld b, a ; bc = the amount of max HP gained from leveling up
; add the amount gained to the current HP
ld de, -32
add hl, de ; hl now points to MSB of current HP
ld a, [hl]
add c
ld [hld], a
ld a, [hl]
adc b
ld [hl], a
ld a, RARE_CANDY_MSG
ld [wPartyMenuTypeOrMessageID], a
call RedrawPartyMenu
pop de
ld a, d
ld [wWhichPokemon], a
ld a, e
ld [wd11e], a
xor a ; PLAYER_PARTY_DATA
ld [wMonDataLocation], a
call LoadMonData
ld d, $01
callab PrintStatsBox ; display new stats text box
call WaitForTextScrollButtonPress ; wait for button press
xor a ; PLAYER_PARTY_DATA
ld [wMonDataLocation], a
predef LearnMoveFromLevelUp ; learn level up move, if any
xor a
ld [wForceEvolution], a
callabd_ModifyPikachuHappiness PIKAHAPPY_LEVELUP
ld a, [wWhichPokemon]
push af
ld a, [wUsedItemOnWhichPokemon]
ld [wWhichPokemon], a
callab Func_2fd6a ; evolve pokemon, if appropriate
pop af
ld [wWhichPokemon], a
callab TryEvolvingMon
ld a, $01
ld [wUpdateSpritesEnabled], a
pop af
ld [wcf91], a
pop af
ld [wWhichPokemon], a
jp RemoveUsedItem
VitaminStatRoseText: ; dd44 (3:5d44)
TX_FAR _VitaminStatRoseText
db "@"
VitaminNoEffectText: ; dd49 (3:5d49)
TX_FAR _VitaminNoEffectText
db "@"
VitaminText: ; dd4e (3:5d4e)
db "HEALTH@"
db "ATTACK@"
db "DEFENSE@"
db "SPEED@"
db "SPECIAL@"
ItemUseBait: ; dd72 (3:5d72)
ld hl, ThrewBaitText
call PrintText
ld hl, wEnemyMonCatchRate ; catch rate
srl [hl] ; halve catch rate
ld a, BAIT_ANIM
ld hl, wSafariBaitFactor ; bait factor
ld de, wSafariEscapeFactor ; escape factor
jr BaitRockCommon
ItemUseRock: ; dd87 (3:5d87)
ld hl, ThrewRockText
call PrintText
ld hl, wEnemyMonCatchRate ; catch rate
ld a, [hl]
add a ; double catch rate
jr nc, .noCarry
ld a, $ff
.noCarry
ld [hl], a
ld a, ROCK_ANIM
ld hl, wSafariEscapeFactor ; escape factor
ld de, wSafariBaitFactor ; bait factor
BaitRockCommon: ; dd9f (3:5d9f)
ld [wAnimationID], a
xor a
ld [wAnimationType], a
ld [H_WHOSETURN], a
ld [de], a ; zero escape factor (for bait), zero bait factor (for rock)
.randomLoop ; loop until a random number less than 5 is generated
call Random
and a, 7
cp a, 5
jr nc, .randomLoop
inc a ; increment the random number, giving a range from 1 to 5 inclusive
ld b, a
ld a, [hl]
add b ; increase bait factor (for bait), increase escape factor (for rock)
jr nc, .noCarry
ld a, $ff
.noCarry
ld [hl], a
predef MoveAnimation ; do animation
ld c, 70
jp DelayFrames
ThrewBaitText: ; ddc6 (3:5dc6)
TX_FAR _ThrewBaitText
db "@"
ThrewRockText: ; ddca (3:5dca)
TX_FAR _ThrewRockText
db "@"
; also used for Dig out-of-battle effect
ItemUseEscapeRope: ; ddcf (3:5dcf)
ld a, [wIsInBattle]
and a
jr nz, .notUsable
ld a, [wCurMap]
cp a, AGATHAS_ROOM
jr z, .notUsable
cp a, BILLS_HOUSE
jr z, .notUsable
cp a, POKEMON_FAN_CLUB
jr z, .notUsable
ld a, [wCurMapTileset]
ld b, a
ld hl, EscapeRopeTilesets
.loop
ld a, [hli]
cp a, $ff
jr z, .notUsable
cp b
jr nz, .loop
ld hl, wd732
set 3, [hl]
set 6, [hl]
call Func_1510
ld hl, wd72e
res 4, [hl]
ld hl, wd790
res 7, [hl]
xor a
ld [wNumSafariBalls], a
ld [wSafariZoneEntranceCurScript], a
inc a
ld [wEscapedFromBattle], a
ld [wActionResultOrTookBattleTurn], a ; item used
ld a, [wPseudoItemID]
and a ; using Dig?
ret nz ; if so, return
call ItemUseReloadOverworldData
ld c, 30
call DelayFrames
jp RemoveUsedItem
.notUsable
jp ItemUseNotTime
EscapeRopeTilesets: ; de28 (3:5e28)
db FOREST, CEMETERY, CAVERN, FACILITY, INTERIOR
db $ff ; terminator
ItemUseRepel: ; de2e (3:5e2e)
ld b, 100
ItemUseRepelCommon: ; e005 (3:6005)
ld a, [wIsInBattle]
and a
jp nz, ItemUseNotTime
ld a, b
ld [wRepelRemainingSteps], a
jp PrintItemUseTextAndRemoveItem
; handles X Accuracy item
ItemUseXAccuracy: ; de3e (3:5e3e)
ld a, [wIsInBattle]
and a
jp z, ItemUseNotTime
ld hl, wPlayerBattleStatus2
set UsingXAccuracy, [hl] ; X Accuracy bit
callabd_ModifyPikachuHappiness PIKAHAPPY_USEDXITEM
jp PrintItemUseTextAndRemoveItem
; This function is bugged and never works. It always jumps to ItemUseNotTime.
; The Card Key is handled in a different way.
ItemUseCardKey: ; de57 (3:de57)
xor a
ld [wUnusedD71F], a
call GetTileAndCoordsInFrontOfPlayer
ld a, [GetTileAndCoordsInFrontOfPlayer] ; $4586
cp a, $18
jr nz, .next0
ld hl, CardKeyTable1
jr .next1
.next0
cp a, $24
jr nz, .next2
ld hl, CardKeyTable2
jr .next1
.next2
cp a, $5e
jp nz, ItemUseNotTime
ld hl, CardKeyTable3
.next1
ld a, [wCurMap]
ld b, a
.loop
ld a, [hli]
cp a, $ff
jp z, ItemUseNotTime
cp b
jr nz, .nextEntry1
ld a, [hli]
cp d
jr nz, .nextEntry2
ld a, [hli]
cp e
jr nz, .nextEntry3
ld a, [hl]
ld [wUnusedD71F], a
jr .done
.nextEntry1
inc hl
.nextEntry2
inc hl
.nextEntry3
inc hl
jr .loop
.done
ld hl, ItemUseText00
call PrintText
ld hl, wd728
set 7, [hl]
ret
; These tables are probably supposed to be door locations in Silph Co.,
; but they are unused.
; The reason there are 3 tables is unknown.
; Format:
; 00: Map ID
; 01: Y
; 02: X
; 03: ID?
CardKeyTable1: ; dea7 (3:5ea7)
db SILPH_CO_2F, $04, $04, $00
db SILPH_CO_2F, $04, $05, $01
db SILPH_CO_4F, $0C, $04, $02
db SILPH_CO_4F, $0C, $05, $03
db SILPH_CO_7F, $06, $0A, $04
db SILPH_CO_7F, $06, $0B, $05
db SILPH_CO_9F, $04, $12, $06
db SILPH_CO_9F, $04, $13, $07
db SILPH_CO_10F, $08, $0A, $08
db SILPH_CO_10F, $08, $0B, $09
db $ff
CardKeyTable2: ; ded0 (3:5ed0)
db SILPH_CO_3F, $08, $09, $0A
db SILPH_CO_3F, $09, $09, $0B
db SILPH_CO_5F, $04, $07, $0C
db SILPH_CO_5F, $05, $07, $0D
db SILPH_CO_6F, $0C, $05, $0E
db SILPH_CO_6F, $0D, $05, $0F
db SILPH_CO_8F, $08, $07, $10
db SILPH_CO_8F, $09, $07, $11
db SILPH_CO_9F, $08, $03, $12
db SILPH_CO_9F, $09, $03, $13
db $ff
CardKeyTable3: ; def9 (3:5ef9)
db SILPH_CO_11F, $08, $09, $14
db SILPH_CO_11F, $09, $09, $15
db $ff
ItemUsePokedoll: ; df02 (3:5f02)
ld a, [wIsInBattle]
dec a
jp nz, ItemUseNotTime
ld a, $01
ld [wEscapedFromBattle], a
jp PrintItemUseTextAndRemoveItem
ItemUseGuardSpec: ; df11 (3:5f11)
ld a, [wIsInBattle]
and a
jp z, ItemUseNotTime
ld a, [wWhichPokemon]
push af
ld a, [wPlayerMonNumber]
ld [wWhichPokemon], a
callabd_ModifyPikachuHappiness PIKAHAPPY_USEDXITEM
pop af
ld [wWhichPokemon], a
ld hl, wPlayerBattleStatus2
set ProtectedByMist, [hl] ; Mist bit
jp PrintItemUseTextAndRemoveItem
ItemUseSuperRepel: ; df38 (3:5f38)
ld b, 200
jp ItemUseRepelCommon
ItemUseMaxRepel: ; df3d (3:5f3d)
ld b, 250
jp ItemUseRepelCommon
ItemUseDireHit: ; df42 (3:5f42)
ld a, [wIsInBattle]
and a
jp z, ItemUseNotTime
ld a, [wWhichPokemon]
push af
ld a, [wPlayerMonNumber]
ld [wWhichPokemon], a
callabd_ModifyPikachuHappiness PIKAHAPPY_USEDXITEM
pop af
ld [wWhichPokemon], a
ld hl, wPlayerBattleStatus2
set GettingPumped, [hl] ; Focus Energy bit
jp PrintItemUseTextAndRemoveItem
ItemUseXStat: ; df69 (3:df69)
ld a, [wIsInBattle]
and a
jr nz, .inBattle
call ItemUseNotTime
ld a, 2
ld [wActionResultOrTookBattleTurn], a ; item not used
ret
.inBattle
ld hl, wPlayerMoveNum
ld a, [hli]
push af ; save [wPlayerMoveNum]
ld a, [hl]
push af ; save [wPlayerMoveEffect]
push hl
ld a, [wcf91]
sub a, X_ATTACK - ATTACK_UP1_EFFECT
ld [hl], a ; store player move effect
call PrintItemUseTextAndRemoveItem
ld a, XSTATITEM_ANIM ; X stat item animation ID
ld [wPlayerMoveNum], a
call LoadScreenTilesFromBuffer1 ; restore saved screen
call Delay3
xor a
ld [H_WHOSETURN], a ; set turn to player's turn
callba StatModifierUpEffect ; do stat increase move
ld a, [wWhichPokemon]
push af
ld a, [wPlayerMonNumber]
ld [wWhichPokemon], a
callabd_ModifyPikachuHappiness PIKAHAPPY_USEDXITEM
pop af
ld [wWhichPokemon], a
pop hl
pop af
ld [hld], a ; restore [wPlayerMoveEffect]
pop af
ld [hl], a ; restore [wPlayerMoveNum]
ret
ItemUsePokeflute: ; dfbd (3:5fbd)
ld a, [wIsInBattle]
and a
jr nz, .inBattle
; if not in battle
call ItemUseReloadOverworldData
ld a, [wCurMap]
cp a, ROUTE_12
jr nz, .notRoute12
ld a, [wd7d8]
bit 7, a
jr nz, .noSnorlaxOrPikachuToWakeUp
; if the player hasn't beaten Route 12 Snorlax
ld hl, Route12SnorlaxFluteCoords
call ArePlayerCoordsInArray
jr nc, .noSnorlaxOrPikachuToWakeUp
ld hl, PlayedFluteHadEffectText
call PrintText
ld hl, wd7d8
set 6, [hl]
ret
.notRoute12
cp a, ROUTE_16
jr nz, .notRoute16
ld a, [wd7e0]
bit 1, a
jr nz, .noSnorlaxOrPikachuToWakeUp
; if the player hasn't beaten Route 16 Snorlax
ld hl, Route16SnorlaxFluteCoords
call ArePlayerCoordsInArray
jr nc, .noSnorlaxOrPikachuToWakeUp
ld hl, PlayedFluteHadEffectText
call PrintText
ld hl, wd7e0
set 0, [hl]
ret
.notRoute16
cp a, PEWTER_POKECENTER
jr nz, .noSnorlaxOrPikachuToWakeUp
call CheckPikachuFollowingPlayer
jr z, .noSnorlaxOrPikachuToWakeUp
callab IsPikachuRightNextToPlayer
jr nc, .noSnorlaxOrPikachuToWakeUp
ld hl, PlayedFluteHadEffectText
call PrintText
call ItemUseReloadOverworldData
ld e, $1a
callab Func_fd001
ret
.noSnorlaxOrPikachuToWakeUp
ld hl, PlayedFluteNoEffectText
jp PrintText
.inBattle
xor a
ld [wWereAnyMonsAsleep], a
ld b, $ff ^ SLP
ld hl, wPartyMon1Status
call WakeUpEntireParty
ld a, [wIsInBattle]
dec a ; is it a trainer battle?
jr z, .skipWakingUpEnemyParty
; if it's a trainer battle
ld hl, wEnemyMon1Status
call WakeUpEntireParty
.skipWakingUpEnemyParty
ld hl, wBattleMonStatus
ld a, [hl]
and b ; remove Sleep status
ld [hl], a
ld hl, wEnemyMonStatus
ld a, [hl]
ld c, a
and b ; remove Sleep status
ld [hl], a
ld a, c
and a, SLP
jr z, .asm_e063
ld a, $1
ld [wWereAnyMonsAsleep], a
.asm_e063
call LoadScreenTilesFromBuffer2 ; restore saved screen
ld a, [wWereAnyMonsAsleep]
and a ; were any pokemon asleep before playing the flute?
ld hl, PlayedFluteNoEffectText
jp z, PrintText ; if no pokemon were asleep
; if some pokemon were asleep
ld hl, PlayedFluteHadEffectText
call PrintText
ld a, [wLowHealthAlarm]
and a, $80
jr nz, .skipMusic
call WaitForSoundToFinish ; wait for sound to end
callba Music_PokeFluteInBattle ; play in-battle pokeflute music
.musicWaitLoop ; wait for music to finish playing
ld a, [wChannelSoundIDs + CH6]
and a ; music off?
jr nz, .musicWaitLoop
.skipMusic
ld hl, FluteWokeUpText
jp PrintText
; wakes up all party pokemon
; INPUT:
; hl must point to status of first pokemon in party (player's or enemy's)
; b must equal ~SLP
; [wWereAnyMonsAsleep] should be initialized to 0
; OUTPUT:
; [wWereAnyMonsAsleep]: set to 1 if any pokemon were asleep
WakeUpEntireParty: ; e094 (3:6094)
ld de, 44
ld c, 6
.loop
ld a, [hl]
push af
and a, SLP ; is pokemon asleep?
jr z, .notAsleep
ld a, 1
ld [wWereAnyMonsAsleep], a ; indicate that a pokemon had to be woken up
.notAsleep
pop af
and b ; remove Sleep status
ld [hl], a
add hl, de
dec c
jr nz, .loop
ret
; Format:
; 00: Y
; 01: X
Route12SnorlaxFluteCoords: ; e0ac (3:60ac)
db 62, 9 ; one space West of Snorlax
db 61, 10 ; one space North of Snorlax
db 63, 10 ; one space South of Snorlax
db 62, 11 ; one space East of Snorlax
db $ff ; terminator
; Format:
; 00: Y
; 01: X
Route16SnorlaxFluteCoords: ; e0b5 (3:60b5)
db 10, 27 ; one space East of Snorlax
db 10, 25 ; one space West of Snorlax
db $ff ; terminator
PlayedFluteNoEffectText: ; e0ba (3:60ba)
TX_FAR _PlayedFluteNoEffectText
db "@"
FluteWokeUpText: ; e0bf (3:60bf)
TX_FAR _FluteWokeUpText
db "@"
PlayedFluteHadEffectText: ; e0c4 (3:60c4)
TX_FAR _PlayedFluteHadEffectText
db $06
TX_ASM
ld a, [wIsInBattle]
and a
jr nz, .done
; play out-of-battle pokeflute music
call StopAllMusic ; turn off music
ld a, SFX_POKEFLUTE
ld c, BANK(SFX_Pokeflute)
call PlayMusic
.musicWaitLoop ; wait for music to finish playing
ld a, [wChannelSoundIDs + CH2]
cp a, SFX_POKEFLUTE
jr z, .musicWaitLoop
call PlayDefaultMusic ; start playing normal music again
.done
jp TextScriptEnd ; end text
ItemUseCoinCase: ; e0e7 (3:60e7)
ld a, [wIsInBattle]
and a
jp nz, ItemUseNotTime
ld hl, CoinCaseNumCoinsText
jp PrintText
CoinCaseNumCoinsText: ; e0f1 (3:60f1)
TX_FAR _CoinCaseNumCoinsText
db "@"
ItemUseOldRod: ; e0f9 (3:60f9)
call FishingInit
jp c, ItemUseNotTime
lb bc, 5, MAGIKARP
ld a, $1 ; set bite
jr RodResponse
ItemUseGoodRod: ; e106 (3:6106)
call FishingInit
jp c, ItemUseNotTime
.RandomLoop
call Random
srl a
jr c, .SetBite
and %11
cp 2
jr nc, .RandomLoop
; choose which monster appears
ld hl, GoodRodMons
add a
ld c, a
ld b, 0
add hl, bc
ld b, [hl]
inc hl
ld c, [hl]
and a
.SetBite
ld a, 0
rla
xor 1
jr RodResponse
INCLUDE "data/good_rod.asm"
ItemUseSuperRod: ; e130 (3:6130)
call FishingInit
jp c, ItemUseNotTime
callab ReadSuperRodData
ld c, e
ld b, d
ld a, $2
ld [wRodResponse], a
ld a, c
and a ; are there fish in the map?
jr z, DoNotGenerateFishingEncounter ; if not, do not generate an encounter
ld a, $1
ld [wRodResponse], a
call Random
and $1
jr nz, RodResponse
xor a
ld [wRodResponse], a
jr DoNotGenerateFishingEncounter
RodResponse: ; e15b (3:615b)
ld [wRodResponse], a
dec a ; is there a bite?
jr nz, DoNotGenerateFishingEncounter
; if yes, store level and species data
ld a, 1
ld [wMoveMissed], a
ld a, b ; level
ld [wCurEnemyLVL], a
ld a, c ; species
ld [wCurOpponent], a
DoNotGenerateFishingEncounter: ; e16e (3:616e)
ld hl, wWalkBikeSurfState
ld a, [hl] ; store the value in a
push af
push hl
ld [hl], 0
callba FishingAnim
pop hl
pop af
ld [hl], a
ret
; checks if fishing is possible and if so, runs initialization code common to all rods
; unsets carry if fishing is possible, sets carry if not
FishingInit: ; e182 (3:6182)
ld a, [wIsInBattle]
and a
jr z, .notInBattle
scf ; can't fish during battle
ret
.notInBattle
call IsNextTileShoreOrWater
jr nc, .cannotFish
ld a, [wWalkBikeSurfState]
cp a, 2 ; Surfing?
jr z, .cannotFish
call ItemUseReloadOverworldData
ld hl, ItemUseText00
call PrintText
ld a, SFX_HEAL_AILMENT
call PlaySound
ld a, $2
ld [wd49c], a
ld a, $81
ld [wPikachuMood], a
ld c, 80
call DelayFrames
and a
ret
.cannotFish
scf ; can't fish when surfing
ret
ItemUseOaksParcel: ; e1b7 (3:61b7)
jp ItemUseNotYoursToUse
ItemUseItemfinder: ; e1ba (3:61ba)
ld a, [wIsInBattle]
and a
jp nz, ItemUseNotTime
call ItemUseReloadOverworldData
callba HiddenItemNear ; check for hidden items
ld hl, ItemfinderFoundNothingText
jr nc, .printText ; if no hidden items
ld c, 4
.loop
ld a, SFX_HEALING_MACHINE
call PlaySoundWaitForCurrent
ld a, SFX_PURCHASE
call PlaySoundWaitForCurrent
dec c
jr nz, .loop
ld hl, ItemfinderFoundItemText
.printText
jp PrintText
ItemfinderFoundItemText: ; e1e6 (3:61e6)
TX_FAR _ItemfinderFoundItemText
db "@"
ItemfinderFoundNothingText: ; e1eb (3:61eb)
TX_FAR _ItemfinderFoundNothingText
db "@"
ItemUsePPUp: ; e1f0 (3:61f0)
ld a, [wIsInBattle]
and a
jp nz, ItemUseNotTime
ItemUsePPRestore: ; e1f7 (3:61f7)
ld a, [wWhichPokemon]
push af
ld a, [wcf91]
ld [wPPRestoreItem], a
.chooseMon
xor a
ld [wUpdateSpritesEnabled], a
ld a, USE_ITEM_PARTY_MENU
ld [wPartyMenuTypeOrMessageID], a
call DisplayPartyMenu
jr nc, .chooseMove
jp .itemNotUsed
.chooseMove
ld a, [wIsInBattle]
and a
jr z, .usePPItem
ld a, [wWhichPokemon]
ld b, a
ld a, [wPlayerMonNumber]
cp b
jr nz, .usePPItem
ld a, [wPlayerBattleStatus3]
bit Transformed, a
jr z, .usePPItem
call ItemUseNotTime
jp .itemNotUsed
.usePPItem
ld a, [wPPRestoreItem]
cp a, ELIXER
jp nc, .useElixir ; if Elixir or Max Elixir
ld a, $02
ld [wMoveMenuType], a
ld hl, RaisePPWhichTechniqueText
ld a, [wPPRestoreItem]
cp a, ETHER ; is it a PP Up?
jr c, .printWhichTechniqueMessage ; if so, print the raise PP message
ld hl, RestorePPWhichTechniqueText ; otherwise, print the restore PP message
.printWhichTechniqueMessage
call PrintText
xor a
ld [wPlayerMoveListIndex], a
callab MoveSelectionMenu ; move selection menu
ld a, 0
ld [wPlayerMoveListIndex], a
jr nz, .chooseMon
ld hl, wPartyMon1Moves
ld bc, wPartyMon2 - wPartyMon1
call GetSelectedMoveOffset
push hl
ld a, [hl]
ld [wd11e], a
call GetMoveName
call CopyStringToCF4B ; copy name to wcf4b
pop hl
ld a, [wPPRestoreItem]
cp a, ETHER
jr nc, .useEther ; if Ether or Max Ether
.usePPUp
ld bc, 21
add hl, bc
ld a, [hl] ; move PP
cp a, 3 << 6 ; have 3 PP Ups already been used?
jr c, .PPNotMaxedOut
ld hl, PPMaxedOutText
call PrintText
jr .chooseMove
.PPNotMaxedOut
ld a, [hl]
add a, 1 << 6 ; increase PP Up count by 1
ld [hl], a
ld a, 1 ; 1 PP Up used
ld [wd11e], a
call RestoreBonusPP ; add the bonus PP to current PP
ld a, SFX_HEAL_AILMENT
call PlaySound
ld hl, PPIncreasedText
call PrintText
.done
pop af
ld [wWhichPokemon], a
call GBPalWhiteOut
call RunDefaultPaletteCommand
jp RemoveUsedItem
.afterRestoringPP ; after using a (Max) Ether/Elixir
ld a, [wWhichPokemon]
ld b, a
ld a, [wPlayerMonNumber]
cp b ; is the pokemon whose PP was restored active in battle?
jr nz, .skipUpdatingInBattleData
ld hl, wPartyMon1PP
ld bc, wPartyMon2 - wPartyMon1
call AddNTimes
ld de, wBattleMonPP
ld bc, 4
call CopyData ; copy party data to in-battle data
.skipUpdatingInBattleData
ld a, SFX_HEAL_AILMENT
call PlaySound
ld hl, PPRestoredText
call PrintText
jr .done
.useEther
call .restorePP
jr nz, .afterRestoringPP
jp .noEffect
; unsets zero flag if PP was restored, sets zero flag if not
; however, this is bugged for Max Ethers and Max Elixirs (see below)
.restorePP
xor a ; PLAYER_PARTY_DATA
ld [wMonDataLocation], a
call GetMaxPP
ld hl, wPartyMon1Moves
ld bc, wPartyMon2 - wPartyMon1
call GetSelectedMoveOffset
ld bc, wPartyMon1PP - wPartyMon1Moves
add hl, bc ; hl now points to move's PP
ld a, [wMaxPP]
ld b, a
ld a, [wPPRestoreItem]
cp a, MAX_ETHER
jr z, .fullyRestorePP
ld a, [hl] ; move PP
and a, %00111111 ; lower 6 bit bits store current PP
cp b ; does current PP equal max PP?
ret z ; if so, return
add a, 10 ; increase current PP by 10
; b holds the max PP amount and b will hold the new PP amount.
; So, if the new amount meets or exceeds the max amount,
; cap the amount to the max amount by leaving b unchanged.
; Otherwise, store the new amount in b.
cp b ; does the new amount meet or exceed the maximum?
jr nc, .storeNewAmount
ld b, a
.storeNewAmount
ld a, [hl] ; move PP
and a, %11000000 ; PP Up counter bits
add b
ld [hl], a
ret
.fullyRestorePP
ld a, [hl] ; move PP
; Note that this code has a bug. It doesn't mask out the upper two bits, which
; are used to count how many PP Ups have been used on the move. So, Max Ethers
; and Max Elixirs will not be detected as having no effect on a move with full
; PP if the move has had any PP Ups used on it.
cp b ; does current PP equal max PP?
ret z
jr .storeNewAmount
.useElixir
; decrement the item ID so that ELIXER becomes ETHER and MAX_ELIXER becomes MAX_ETHER
ld hl, wPPRestoreItem
dec [hl]
dec [hl]
xor a
ld hl, wCurrentMenuItem
ld [hli], a
ld [hl], a ; zero the counter for number of moves that had their PP restored
ld b, 4
; loop through each move and restore PP
.elixirLoop
push bc
ld hl, wPartyMon1Moves
ld bc, wPartyMon2 - wPartyMon1
call GetSelectedMoveOffset
ld a, [hl]
and a ; does the current slot have a move?
jr z, .nextMove
call .restorePP
jr z, .nextMove
; if some PP was restored
ld hl, wTileBehindCursor ; counter for number of moves that had their PP restored
inc [hl]
.nextMove
ld hl, wCurrentMenuItem
inc [hl]
pop bc
dec b
jr nz, .elixirLoop
ld a, [wTileBehindCursor]
and a ; did any moves have their PP restored?
jp nz, .afterRestoringPP
.noEffect
call ItemUseNoEffect
.itemNotUsed
call GBPalWhiteOut
call RunDefaultPaletteCommand
pop af
xor a
ld [wActionResultOrTookBattleTurn], a ; item use failed
ret
RaisePPWhichTechniqueText: ; e358 (3:6358)
TX_FAR _RaisePPWhichTechniqueText
db "@"
RestorePPWhichTechniqueText: ; e35d (3:635d)
TX_FAR _RestorePPWhichTechniqueText
db "@"
PPMaxedOutText: ; e362 (3:6362)
TX_FAR _PPMaxedOutText
db "@"
PPIncreasedText: ; e367 (3:6367)
TX_FAR _PPIncreasedText
db "@"
PPRestoredText: ; e36c (3:636c)
TX_FAR _PPRestoredText
db "@"
; for items that can't be used from the Item menu
UnusableItem: ; e371 (3:6371)
jp ItemUseNotTime
ItemUseTMHM: ; e374 (3:6374)
ld a, [wIsInBattle]
and a
jp nz, ItemUseNotTime
ld a, [wcf91]
sub a, TM_01
push af
jr nc, .skipAdding
add a, 55 ; if item is an HM, add 55
.skipAdding
inc a
ld [wd11e], a
predef TMToMove ; get move ID from TM/HM ID
ld a, [wd11e]
ld [wMoveNum], a
call GetMoveName
call CopyStringToCF4B ; copy name to wcf4b
pop af
ld hl, BootedUpTMText
jr nc, .printBootedUpMachineText
ld hl, BootedUpHMText
.printBootedUpMachineText
call PrintText
ld hl, TeachMachineMoveText
call PrintText
coord hl, 14, 7
lb bc, 8, 15
ld a, TWO_OPTION_MENU
ld [wTextBoxID], a
call DisplayTextBoxID ; yes/no menu
ld a, [wCurrentMenuItem]
and a
jr z, .useMachine
ld a, 2
ld [wActionResultOrTookBattleTurn], a ; item not used
ret
.useMachine
ld a, [wWhichPokemon]
push af
ld a, [wcf91]
push af
.chooseMon
ld hl, wcf4b
ld de, wTempMoveNameBuffer
ld bc, 14
call CopyData ; save the move name because DisplayPartyMenu will overwrite it
ld a, $ff
ld [wUpdateSpritesEnabled], a
ld a, TMHM_PARTY_MENU
ld [wPartyMenuTypeOrMessageID], a
call DisplayPartyMenu
push af
ld hl, wTempMoveNameBuffer
ld de, wcf4b
ld bc, 14
call CopyData
pop af
jr nc, .checkIfAbleToLearnMove
; if the player canceled teaching the move
pop af
pop af
call GBPalWhiteOutWithDelay3
call ClearSprites
call RunDefaultPaletteCommand
jp LoadScreenTilesFromBuffer1 ; restore saved screen
.checkIfAbleToLearnMove
predef CanLearnTM ; check if the pokemon can learn the move
push bc
ld a, [wWhichPokemon]
ld hl, wPartyMonNicks
call GetPartyMonName
pop bc
ld a, c
and a ; can the pokemon learn the move?
jr nz, .checkIfAlreadyLearnedMove
; if the pokemon can't learn the move
ld a, SFX_DENIED
call PlaySoundWaitForCurrent
ld hl, MonCannotLearnMachineMoveText
call PrintText
jr .chooseMon
.checkIfAlreadyLearnedMove
callab CheckIfMoveIsKnown ; check if the pokemon already knows the move
jr c, .chooseMon
predef LearnMove ; teach move
ld a, [wWhichPokemon]
ld d, a
pop af
ld [wcf91], a
pop af
ld [wWhichPokemon], a
ld a, b
and a
ret z
ld a, [wWhichPokemon]
push af
ld a, d
ld [wWhichPokemon], a
callabd_ModifyPikachuHappiness PIKAHAPPY_USEDTMHM
callab IsThisPartymonStarterPikachu_Party
jr nc, .notTeachingThunderboltOrThunderToPikachu
ld a, [wcf91]
cp a, TM_24 ; are we teaching thunderbolt to the player pikachu?
jr z, .teachingThunderboltOrThunderToPlayerPikachu
cp a, TM_25 ; are we teaching thunder then?
jr nz, .notTeachingThunderboltOrThunderToPikachu
.teachingThunderboltOrThunderToPlayerPikachu
ld a, $5
ld [wd49c], a
ld a, $85
ld [wPikachuMood], a
.notTeachingThunderboltOrThunderToPikachu
pop af
ld [wWhichPokemon], a
ld a, [wcf91]
call IsItemHM
ret c
jp RemoveUsedItem
BootedUpTMText: ; e483 (3:6483)
TX_FAR _BootedUpTMText
db "@"
BootedUpHMText: ; e488 (3:6488)
TX_FAR _BootedUpHMText
db "@"
TeachMachineMoveText: ; e48d (3:648d)
TX_FAR _TeachMachineMoveText
db "@"
MonCannotLearnMachineMoveText: ; e492 (3:6492)
TX_FAR _MonCannotLearnMachineMoveText
db "@"
PrintItemUseTextAndRemoveItem: ; e497 (3:6497)
ld hl, ItemUseText00
call PrintText
ld a, SFX_HEAL_AILMENT
call PlaySound
call WaitForTextScrollButtonPress ; wait for button press
RemoveUsedItem: ; e4a5 (3:64a5)
ld hl, wNumBagItems
ld a, 1 ; one item
ld [wItemQuantity], a
jp RemoveItemFromInventory
ItemUseNoEffect: ; e4b0 (3:64b0)
ld hl, ItemUseNoEffectText
jr ItemUseFailed
ItemUseNotTime: ; e4b5 (3:64b5)
ld hl, ItemUseNotTimeText
jr ItemUseFailed
ItemUseNotYoursToUse: ; e4ba (3:64ba)
ld hl, ItemUseNotYoursToUseText
jr ItemUseFailed
Func_e4bf: ; e4bf (3:64bf)
ld a, $2
ld [wActionResultOrTookBattleTurn], a
ld hl, DontHavePokemonText
jp PrintText
ThrowBallAtTrainerMon: ; e4ca (3:64ca)
call RunDefaultPaletteCommand
call LoadScreenTilesFromBuffer1 ; restore saved screen
call Delay3
ld a, TOSS_ANIM
ld [wAnimationID], a
predef MoveAnimation ; do animation
ld hl, ThrowBallAtTrainerMonText1
call PrintText
ld hl, ThrowBallAtTrainerMonText2
call PrintText
jr RemoveUsedItem
NoCyclingAllowedHere: ; e4eb (3:64eb)
ld hl, NoCyclingAllowedHereText
jr ItemUseFailed
BoxFullCannotThrowBall: ; e4f0 (3:64f0)
ld hl, BoxFullCannotThrowBallText
jr ItemUseFailed
SurfingAttemptFailed: ; e4f5 (3:64f5)
ld hl, NoSurfingHereText
ItemUseFailed: ; e4f8 (3:64f8)
xor a
ld [wActionResultOrTookBattleTurn], a ; item use failed
jp PrintText
ItemUseNotTimeText: ; e4ff (3:64ff)
TX_FAR _ItemUseNotTimeText
db "@"
ItemUseNotYoursToUseText: ; e504 (3:6504)
TX_FAR _ItemUseNotYoursToUseText
db "@"
ItemUseNoEffectText: ; e509 (3:6509)
TX_FAR _ItemUseNoEffectText
db "@"
ThrowBallAtTrainerMonText1: ; e50e (3:650e)
TX_FAR _ThrowBallAtTrainerMonText1
db "@"
ThrowBallAtTrainerMonText2: ; e513 (3:6513)
TX_FAR _ThrowBallAtTrainerMonText2
db "@"
NoCyclingAllowedHereText: ; e518 (3:6518)
TX_FAR _NoCyclingAllowedHereText
db "@"
NoSurfingHereText: ; e51d (3:651d)
TX_FAR _NoSurfingHereText
db "@"
BoxFullCannotThrowBallText: ; e522 (3:6522)
TX_FAR _BoxFullCannotThrowBallText
db "@"
DontHavePokemonText: ; e527 (3:6527)
TX_FAR _DontHavePokemonText
db "@"
ItemUseText00: ; e52c (3:652c)
TX_FAR _ItemUseText001
db $05
TX_FAR _ItemUseText002
db "@"
GotOnBicycleText: ; e536 (3:6536)
TX_FAR _GotOnBicycleText1
db $05
TX_FAR _GotOnBicycleText2
db "@"
GotOffBicycleText: ; e540 (3:6540)
TX_FAR _GotOffBicycleText1
db $05
TX_FAR _GotOffBicycleText2
db "@"
; restores bonus PP (from PP Ups) when healing at a pokemon center
; also, when a PP Up is used, it increases the current PP by one PP Up bonus
; INPUT:
; [wWhichPokemon] = index of pokemon in party
; [wCurrentMenuItem] = index of move (when using a PP Up)
RestoreBonusPP: ; e54a (3:654a)
ld hl, wPartyMon1Moves
ld bc, wPartyMon2 - wPartyMon1
ld a, [wWhichPokemon]
call AddNTimes
push hl
ld de, wNormalMaxPPList - 1
predef LoadMovePPs ; loads the normal max PP of each of the pokemon's moves to wNormalMaxPPList
pop hl
ld c, wPartyMon1PP - wPartyMon1Moves
ld b, 0
add hl, bc ; hl now points to move 1 PP
ld de, wNormalMaxPPList
ld b, 0 ; initialize move counter to zero
; loop through the pokemon's moves
.loop
inc b
ld a, b
cp a, 5 ; reached the end of the pokemon's moves?
ret z ; if so, return
ld a, [wUsingPPUp]
dec a ; using a PP Up?
jr nz, .skipMenuItemIDCheck
; if using a PP Up, check if this is the move it's being used on
ld a, [wCurrentMenuItem]
inc a
cp b
jr nz, .nextMove
.skipMenuItemIDCheck
ld a, [hl]
and a, %11000000 ; have any PP Ups been used?
call nz, AddBonusPP ; if so, add bonus PP
.nextMove
inc hl
inc de
jr .loop
; adds bonus PP from PP Ups to current PP
; 1/5 of normal max PP (capped at 7) is added for each PP Up
; INPUT:
; [de] = normal max PP
; [hl] = move PP
AddBonusPP: ; e586 (3:6586)
push bc
ld a, [de] ; normal max PP of move
ld [H_DIVIDEND + 3], a
xor a
ld [H_DIVIDEND], a
ld [H_DIVIDEND + 1], a
ld [H_DIVIDEND + 2], a
ld a, 5
ld [H_DIVISOR], a
ld b, 4
call Divide
ld a, [hl] ; move PP
ld b, a
swap a
and a, %1111
srl a
srl a
ld c, a ; c = number of PP Ups used
.loop
ld a, [H_QUOTIENT + 3]
cp a, 8 ; is the amount greater than or equal to 8?
jr c, .addAmount
ld a, 7 ; cap the amount at 7
.addAmount
add b
ld b, a
ld a, [wUsingPPUp]
dec a ; is the player using a PP Up right now?
jr z, .done ; if so, only add the bonus once
dec c
jr nz, .loop
.done
ld [hl], b
pop bc
ret
; gets max PP of a pokemon's move (including PP from PP Ups)
; INPUT:
; [wWhichPokemon] = index of pokemon within party/box
; [wMonDataLocation] = pokemon source
; 00: player's party
; 01: enemy's party
; 02: current box
; 03: daycare
; 04: player's in-battle pokemon
; [wCurrentMenuItem] = move index
; OUTPUT:
; [wMaxPP] = max PP
GetMaxPP: ; e5bb (3:65bb)
ld a, [wMonDataLocation]
and a
ld hl, wPartyMon1Moves
ld bc, wPartyMon2 - wPartyMon1
jr z, .sourceWithMultipleMon
ld hl, wEnemyMon1Moves
dec a
jr z, .sourceWithMultipleMon
ld hl, wBoxMon1Moves
ld bc, wBoxMon2 - wBoxMon1
dec a
jr z, .sourceWithMultipleMon
ld hl, wDayCareMonMoves
dec a
jr z, .sourceWithOneMon
ld hl, wBattleMonMoves ; player's in-battle pokemon
.sourceWithOneMon
call GetSelectedMoveOffset2
jr .next
.sourceWithMultipleMon
call GetSelectedMoveOffset
.next
ld a, [hl]
dec a
push hl
ld hl, Moves
ld bc, MoveEnd - Moves
call AddNTimes
ld de, wcd6d
ld a, BANK(Moves)
call FarCopyData
ld de, wcd6d + 5 ; PP is byte 5 of move data
ld a, [de]
ld b, a ; b = normal max PP
pop hl
push bc
ld bc, wPartyMon1PP - wPartyMon1Moves ; PP offset if not player's in-battle pokemon data
ld a, [wMonDataLocation]
cp a, 4 ; player's in-battle pokemon?
jr nz, .addPPOffset
ld bc, wBattleMonPP - wBattleMonMoves ; PP offset if player's in-battle pokemon data
.addPPOffset
add hl, bc
ld a, [hl] ; a = current PP
and a, %11000000 ; get PP Up count
pop bc
or b ; place normal max PP in 6 lower bits of a
ld h, d
ld l, e
inc hl ; hl = wcd73
ld [hl], a
xor a ; add the bonus for the existing PP Up count
ld [wUsingPPUp], a
call AddBonusPP ; add bonus PP from PP Ups
ld a, [hl]
and a, %00111111 ; mask out the PP Up count
ld [wMaxPP], a ; store max PP
ret
GetSelectedMoveOffset: ; e627 (3:6627)
ld a, [wWhichPokemon]
call AddNTimes
GetSelectedMoveOffset2: ; e62d (3:662d)
ld a, [wCurrentMenuItem]
ld c, a
ld b, 0
add hl, bc
ret
; confirms the item toss and then tosses the item
; INPUT:
; hl = address of inventory (either wNumBagItems or wNumBoxItems)
; [wcf91] = item ID
; [wWhichPokemon] = index of item within inventory
; [wItemQuantity] = quantity to toss
; OUTPUT:
; clears carry flag if the item is tossed, sets carry flag if not
TossItem_: ; e635 (3:6635)
push hl
ld a, [wcf91]
call IsItemHM
pop hl
jr c, .tooImportantToToss
push hl
call IsKeyItem_
ld a, [wIsKeyItem]
pop hl
and a
jr nz, .tooImportantToToss
push hl
ld a, [wcf91]
ld [wd11e], a
call GetItemName
call CopyStringToCF4B ; copy name to wcf4b
ld hl, IsItOKToTossItemText
call PrintText
coord hl, 14, 7
lb bc, 8, 15
ld a, TWO_OPTION_MENU
ld [wTextBoxID], a
call DisplayTextBoxID ; yes/no menu
ld a, [wMenuExitMethod]
cp a, CHOSE_SECOND_ITEM
pop hl
scf
ret z ; return if the player chose No
; if the player chose Yes
push hl
ld a, [wWhichPokemon]
call RemoveItemFromInventory
ld a, [wcf91]
ld [wd11e], a
call GetItemName
call CopyStringToCF4B ; copy name to wcf4b
ld hl, ThrewAwayItemText
call PrintText
pop hl
and a
ret
.tooImportantToToss
push hl
ld hl, TooImportantToTossText
call PrintText
pop hl
scf
ret
ThrewAwayItemText: ; e699 (3:6699)
TX_FAR _ThrewAwayItemText
db "@"
IsItOKToTossItemText: ; e69e (3:669e)
TX_FAR _IsItOKToTossItemText
db "@"
TooImportantToTossText: ; e6a3 (3:66a3)
TX_FAR _TooImportantToTossText
db "@"
; checks if an item is a key item
; INPUT:
; [wcf91] = item ID
; OUTPUT:
; [wIsKeyItem] = result
; 00: item is not key item
; 01: item is key item
IsKeyItem_: ; e6a8 (3:66a8)
ld a, $01
ld [wIsKeyItem], a
ld a, [wcf91]
cp a, HM_01 ; is the item an HM or TM?
jr nc, .checkIfItemIsHM
; if the item is not an HM or TM
push af
ld hl, KeyItemBitfield
ld de, wBuffer
ld bc, 15 ; only 11 bytes are actually used
call CopyData
pop af
dec a
ld c, a
ld hl, wBuffer
ld b, FLAG_TEST
predef FlagActionPredef
ld a, c
and a
ret nz
.checkIfItemIsHM
ld a, [wcf91]
call IsItemHM
ret c
xor a
ld [wIsKeyItem], a
ret
INCLUDE "data/key_items.asm"
SendNewMonToBox: ; e6e8 (3:66e8)
ld de, wNumInBox
ld a, [de]
inc a
ld [de], a
ld a, [wcf91]
ld [wd0b5], a
ld c, a
.asm_e6f5
inc de
ld a, [de]
ld b, a
ld a, c
ld c, b
ld [de], a
cp $ff
jr nz, .asm_e6f5
call GetMonHeader
ld hl, wBoxMonOT
ld bc, NAME_LENGTH
ld a, [wNumInBox]
dec a
jr z, .asm_e732
dec a
call AddNTimes
push hl
ld bc, NAME_LENGTH
add hl, bc
ld d, h
ld e, l
pop hl
ld a, [wNumInBox]
dec a
ld b, a
.asm_e71f
push bc
push hl
ld bc, NAME_LENGTH
call CopyData
pop hl
ld d, h
ld e, l
ld bc, -NAME_LENGTH
add hl, bc
pop bc
dec b
jr nz, .asm_e71f
.asm_e732
ld hl, wPlayerName
ld de, wBoxMonOT
ld bc, NAME_LENGTH
call CopyData
ld a, [wNumInBox]
dec a
jr z, .asm_e76e
ld hl, wBoxMonNicks
ld bc, NAME_LENGTH
dec a
call AddNTimes
push hl
ld bc, NAME_LENGTH
add hl, bc
ld d, h
ld e, l
pop hl
ld a, [wNumInBox]
dec a
ld b, a
.asm_e75b
push bc
push hl
ld bc, NAME_LENGTH
call CopyData
pop hl
ld d, h
ld e, l
ld bc, -NAME_LENGTH
add hl, bc
pop bc
dec b
jr nz, .asm_e75b
.asm_e76e
ld hl, wBoxMonNicks
ld a, NAME_MON_SCREEN
ld [wNamingScreenType], a
predef AskName
ld a, [wNumInBox]
dec a
jr z, .asm_e7ab
ld hl, wBoxMons
ld bc, wBoxMon2 - wBoxMon1
dec a
call AddNTimes
push hl
ld bc, wBoxMon2 - wBoxMon1
add hl, bc
ld d, h
ld e, l
pop hl
ld a, [wNumInBox]
dec a
ld b, a
.asm_e798
push bc
push hl
ld bc, wBoxMon2 - wBoxMon1
call CopyData
pop hl
ld d, h
ld e, l
ld bc, wBoxMon1 - wBoxMon2
add hl, bc
pop bc
dec b
jr nz, .asm_e798
.asm_e7ab
ld a, [wEnemyMonLevel]
ld [wEnemyMonBoxLevel], a
ld hl, wEnemyMon
ld de, wBoxMon1
ld bc, wEnemyMonDVs - wEnemyMon
call CopyData
ld hl, wPlayerID
ld a, [hli]
ld [de], a
inc de
ld a, [hl]
ld [de], a
inc de
push de
ld a, [wCurEnemyLVL]
ld d, a
callab CalcExperience
pop de
ld a, [hExperience]
ld [de], a
inc de
ld a, [hExperience + 1]
ld [de], a
inc de
ld a, [hExperience + 2]
ld [de], a
inc de
xor a
ld b, NUM_STATS * 2
.asm_e7e3
ld [de], a
inc de
dec b
jr nz, .asm_e7e3
ld hl, wEnemyMonDVs
ld a, [hli]
ld [de], a
inc de
ld a, [hli]
ld [de], a
ld hl, wEnemyMonPP
ld b, NUM_MOVES
.asm_e7f5
ld a, [hli]
inc de
ld [de], a
dec b
jr nz, .asm_e7f5
ld a, [wcf91]
cp KADABRA
jr nz, .notKadabra
ld a, $60 ; twistedspoon in gsc
ld [wBoxMon1CatchRate], a
.notKadabra
ret
; checks if the tile in front of the player is a shore or water tile
; used for surfing and fishing
; unsets carry if it is, sets carry if not
IsNextTileShoreOrWater: ; e808 (3:6808)
ld a, [wCurMapTileset]
ld hl, WaterTilesets
ld de, 1
call IsInArray ; does the current map allow surfing?
ret nc ; if not, return
ld hl, WaterTile
ld a, [wCurMapTileset]
cp SHIP_PORT ; Vermilion Dock tileset
jr z, .skipShoreTiles ; if it's the Vermilion Dock tileset
cp GYM ; eastern shore tile in Safari Zone
jr z, .skipShoreTiles
cp DOJO ; usual eastern shore tile
jr z, .skipShoreTiles
ld hl, ShoreTiles
.skipShoreTiles
ld a, [wTileInFrontOfPlayer]
ld de, $1
call IsInArray
ret
; tilesets with water
WaterTilesets: ; e834 (3:6834)
db OVERWORLD, FOREST, DOJO, GYM, SHIP, SHIP_PORT, CAVERN, FACILITY, PLATEAU
db $ff ; terminator
; shore tiles
ShoreTiles: ; e83e (3:683e)
db $48, $32
WaterTile: ; e840 (3:6840)
db $14
db $ff ; terminator
; reloads map view and processes sprite data
; for items that cause the overworld to be displayed
ItemUseReloadOverworldData: ; e842 (3:6842)
call LoadCurrentMapView
jp UpdateSprites
; creates a list at wBuffer of maps where the mon in [wd11e] can be found.
; this is used by the pokedex to display locations the mon can be found on the map.
FindWildLocationsOfMon: ; e848 (3:6848)
ld hl, WildDataPointers
ld de, wBuffer
ld c, $0
.loop
inc hl
ld a, [hld]
inc a
jr z, .done
push hl
ld a, [hli]
ld h, [hl]
ld l, a
ld a, [hli]
and a
call nz, CheckMapForMon ; land
ld a, [hli]
and a
call nz, CheckMapForMon ; water
pop hl
inc hl
inc hl
inc c
jr .loop
.done
ld a, $ff ; list terminator
ld [de], a
ret
CheckMapForMon: ; e86d (3:686d)
inc hl
ld b, $a
.loop
ld a, [wd11e]
cp [hl]
jr nz, .nextEntry
ld a, c
ld [de], a
inc de
.nextEntry
inc hl
inc hl
dec b
jr nz, .loop
dec hl
ret