summaryrefslogtreecommitdiff
path: root/engine/items
diff options
context:
space:
mode:
Diffstat (limited to 'engine/items')
-rwxr-xr-xengine/items/items.asm5744
1 files changed, 2872 insertions, 2872 deletions
diff --git a/engine/items/items.asm b/engine/items/items.asm
index beb85cde..c6f098dc 100755
--- a/engine/items/items.asm
+++ b/engine/items/items.asm
@@ -1,2872 +1,2872 @@
-UseItem_: ; d5c7 (3:55c7)
- ld a,1
- ld [wcd6a],a
- 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: ; d5e1 (3:55e1)
- 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 OldRodCode ; OLD_ROD
- dw GoodRodCode ; GOOD_ROD
- dw SuperRodCode ; SUPER_ROD
- dw ItemUsePPUp ; PP_UP (real one)
- dw ItemUsePPRestore ; ETHER
- dw ItemUsePPRestore ; MAX_ETHER
- dw ItemUsePPRestore ; ELIXER
- dw ItemUsePPRestore ; MAX_ELIXER
-
-ItemUseBall: ; d687 (3:5687)
- ld a,[W_ISINBATTLE]
- and a
- jp z,ItemUseNotTime ; not in battle
- dec a
- jp nz,ThrowBallAtTrainerMon
- ld a,[W_BATTLETYPE]
- dec a
- jr z,.UseBall
- ld a,[wPartyCount] ;is Party full?
- cp a,PARTY_LENGTH
- jr nz,.UseBall
- ld a,[W_NUMINBOX] ;is Box full?
- cp a,MONS_PER_BOX
- jp z,BoxFullCannotThrowBall
-.UseBall ;$56a7
-;ok, you can use a ball
- xor a
- ld [wd11c],a
- ld a,[W_BATTLETYPE]
- cp a,2 ;SafariBattle
- jr nz,.skipSafariZoneCode
-.safariZone
- ; remove a Safari Ball from inventory
- ld hl,W_NUMSAFARIBALLS
- dec [hl]
-.skipSafariZoneCode ;$56b6
- call GoPAL_SET_CF1C
- 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,[W_BATTLETYPE]
- dec a
- jr nz,.notOldManBattle
-.oldManBattle
- ld hl,W_GRASSRATE
- ld de,wPlayerName
- ld bc,11
- call CopyData ; save the player's name in the Wild Monster data (part of the Cinnabar Island Missingno glitch)
- jp .BallSuccess ;$578b
-.notOldManBattle ;$56e9
- ld a,[W_CURMAP]
- 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 ;$56fa
- call Random
- ld b,a
- ld hl,wcf91
- ld a,[hl]
- cp a,MASTER_BALL
- jp z,.BallSuccess ;$578b
- 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 ;$571a
-; 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 ;$5728
- ld a,b
- sub c
- jp c,.BallSuccess ;$578b
- ld b,a
-.noAilments ;$572e
- 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 a,GREAT_BALL
- ld a,12 ;any other BallFactor
- jr nz,.next7
- ld a,8
-.next7 ;$574d
- 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 ;$5766
- 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 ;$5776
- 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 ;$578b
- jr .BallSuccess2
-.next10 ;$578d
- 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 a,POKE_BALL
- jr z,.next11
- ld b,200
- cp a,GREAT_BALL
- jr z,.next11
- ld b,150
- cp a,ULTRA_BALL
- jr z,.next11
-.next11 ;$57b8
- 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 a, 1 << FRZ | SLP
- ld b,5
- jr z,.next14
- ld b,10
-.next14 ;$57e6
- ld a,[H_QUOTIENT + 3]
- add b
- ld [H_QUOTIENT + 3],a
-.next13 ;$57eb
- 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 ;$5801
- ld a,b
- ld [wd11e],a
-.BallSuccess2 ;$5805
- ld c,20
- call DelayFrames
- ld a,TOSS_ANIM
- ld [W_ANIMATIONID],a
- xor a
- ld [$fff3],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,[wd11e]
- 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,W_ENEMYBATTSTATUS3
- bit Transformed,[hl]
- jr z,.next15
- ld a,$4c
- ld [wEnemyMonSpecies2],a
- jr .next16
-.next15 ;$5871
- set Transformed,[hl]
- ld hl,wcceb
- ld a,[wEnemyMonDVs]
- ld [hli],a
- ld a,[wEnemyMonDVs + 1]
- ld [hl],a
-.next16 ;$587e
- ld a,[wcf91]
- push af
- ld a,[wEnemyMonSpecies2]
- ld [wcf91],a
- ld a,[wEnemyMonLevel]
- ld [W_CURENEMYLVL],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 [wd11c],a
- ld [wcf91],a
- ld [wd11e],a
- ld a,[W_BATTLETYPE]
- dec a
- jr z,.printText1
- ld hl,ItemUseBallText05
- call PrintText
- predef IndexToPokedex
- ld a,[wd11e]
- dec a
- ld c,a
- ld b,2
- ld hl,wPokedexOwned ;Dex_own_flags (pokemon)
- predef FlagActionPredef
- ld a,c
- push af
- ld a,[wd11e]
- dec a
- ld c,a
- ld b,1
- 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 ;$58f4
- ld a,[wPartyCount]
- cp a,PARTY_LENGTH ;is party full?
- jr z,.sendToBox
- xor a
- ld [wcc49],a
- call ClearSprites
- call AddPartyMon ;add mon to Party
- jr .End
-.sendToBox ;$5907
- call ClearSprites
- call SendNewMonToBox
- ld hl,ItemUseBallText07
- ld a,[wd7f1]
- bit 0,a ;already met Bill?
- jr nz,.sendToBox2
- ld hl,ItemUseBallText08
-.sendToBox2 ;$591a
- call PrintText
- jr .End
-.printText1 ;$591f
- ld hl,ItemUseBallText05
-.printText0 ;$5922
- call PrintText
- call ClearSprites
-.End ;$5928
- ld a,[W_BATTLETYPE]
- and a
- ret nz
- ld hl,wNumBagItems
- inc a
- ld [wcf96],a
- jp RemoveItemFromInventory ;remove ITEM (XXX)
-ItemUseBallText00: ; d937 (3:5937)
-;"It dodged the thrown ball!"
-;"This pokemon can't be caught"
- TX_FAR _ItemUseBallText00
- db "@"
-ItemUseBallText01: ; d93c (3:593c)
-;"You missed the pokemon!"
- TX_FAR _ItemUseBallText01
- db "@"
-ItemUseBallText02: ; d941 (3:5941)
-;"Darn! The pokemon broke free!"
- TX_FAR _ItemUseBallText02
- db "@"
-ItemUseBallText03: ; d946 (3:5946)
-;"Aww! It appeared to be caught!"
- TX_FAR _ItemUseBallText03
- db "@"
-ItemUseBallText04: ; d94b (3:594b)
-;"Shoot! It was so close too!"
- TX_FAR _ItemUseBallText04
- db "@"
-ItemUseBallText05: ; d950 (3:5950)
-;"All right! {MonName} was caught!"
-;play sound
- TX_FAR _ItemUseBallText05
- db $12,$06
- db "@"
-ItemUseBallText07: ; d957 (3:5957)
-;"X was transferred to Bill's PC"
- TX_FAR _ItemUseBallText07
- db "@"
-ItemUseBallText08: ; d95c (3:595c)
-;"X was transferred to someone's PC"
- TX_FAR _ItemUseBallText08
- db "@"
-
-ItemUseBallText06: ; d961 (3:5961)
-;"New DEX data will be added..."
-;play sound
- TX_FAR _ItemUseBallText06
- db $13,$06
- db "@"
-
-ItemUseTownMap: ; d968 (3:5968)
- ld a,[W_ISINBATTLE]
- and a
- jp nz,ItemUseNotTime
- ld b, BANK(DisplayTownMap)
- ld hl, DisplayTownMap
- jp Bankswitch ; display Town Map
-
-ItemUseBicycle: ; d977 (3:5977)
- ld a,[W_ISINBATTLE]
- 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
- call PlayDefaultMusic ; play walking music
- ld hl,GotOffBicycleText
- jr .printText
-.tryToGetOnBike
- call IsBikeRidingAllowed
- jp nc,NoCyclingAllowedHere
- call ItemUseReloadOverworldData
- xor a ; no keys pressed
- ld [hJoyHeld],a ; current joypad state
- inc a
- ld [wWalkBikeSurfState],a ; change player state to bicycling
- ld hl,GotOnBicycleText
- call PlayDefaultMusic ; play bike riding music
-.printText
- jp PrintText
-
-; used for Surf out-of-battle effect
-ItemUseSurfboard: ; d9b4 (3:59b4)
- ld a,[wWalkBikeSurfState]
- ld [wWalkBikeSurfStateCopy],a
- cp a,2 ; is the player already surfing?
- jr z,.tryToStopSurfing
-.tryToSurf
- call IsNextTileShoreOrWater
- jp c,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 [$ff8c],a
- ld d,16 ; talking range in pixels (normal range)
- call IsSpriteInFrontOfPlayer2
- res 7,[hl]
- ld a,[$ff8c]
- and a ; is there a sprite in the way?
- jr nz,.cannotStopSurfing
- ld hl,TilePairCollisionsWater
- call CheckForTilePairCollisions
- jr c,.cannotStopSurfing
- ld hl,W_TILESETCOLLISIONPTR ; pointer to list of passable tiles
- ld a,[hli]
- ld h,[hl]
- ld l,a ; hl now points to passable tiles
- ld a,[wTileInFrontOfPlayer] ; tile in front of the player
- ld b,a
-.passableTileLoop
- ld a,[hli]
- cp b
- jr z,.stopSurfing
- cp a,$ff
- jr nz,.passableTileLoop
-.cannotStopSurfing
- ld hl,SurfingNoPlaceToGetOffText
- jp PrintText
-.stopSurfing
- call .makePlayerMoveForward
- 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
- jp LoadWalkingPlayerSpriteGraphics
-; uses a simulated button press to make the player move forward
-.makePlayerMoveForward
- ld a,[wd52a] ; direction the player is going
- bit 3,a
- ld b,D_UP
- jr nz,.storeSimulatedButtonPress
- bit 2,a
- ld b,D_DOWN
- jr nz,.storeSimulatedButtonPress
- bit 1,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: ; da4c (3:5a4c)
- TX_FAR _SurfingGotOnText
- db "@"
-
-SurfingNoPlaceToGetOffText: ; da51 (3:5a51)
- TX_FAR _SurfingNoPlaceToGetOffText
- db "@"
-
-ItemUsePokedex: ; da56 (3:5a56)
- predef_jump ShowPokedexMenu
-
-ItemUseEvoStone: ; da5b (3:5a5b)
- ld a,[W_ISINBATTLE]
- and a
- jp nz,ItemUseNotTime
- ld a,[wWhichPokemon]
- push af
- ld a,[wcf91]
- ld [wd156],a
- push af
- ld a,$05 ; evolution stone party menu
- ld [wd07d],a
- ld a,$ff
- ld [wUpdateSpritesEnabled],a
- call DisplayPartyMenu
- pop bc
- jr c,.canceledItemUse
- ld a,b
- ld [wcf91],a
- ld a,$01
- ld [wccd4],a
- ld a,(SFX_02_3e - SFX_Headers_02) / 3
- call PlaySoundWaitForCurrent ; play sound
- call WaitForSoundToFinish ; wait for sound to end
- callab TryEvolvingMon ; try to evolve pokemon
- ld a,[wd121]
- and a
- jr z,.noEffect
- pop af
- ld [wWhichPokemon],a
- ld hl,wNumBagItems
- ld a,1 ; remove 1 stone
- ld [wcf96],a
- jp RemoveItemFromInventory
-.noEffect
- call ItemUseNoEffect
-.canceledItemUse
- xor a
- ld [wcd6a],a
- pop af
- ret
-
-ItemUseVitamin: ; dab4 (3:5ab4)
- ld a,[W_ISINBATTLE]
- and a
- jp nz,ItemUseNotTime
-
-ItemUseMedicine: ; dabb (3:5abb)
- ld a,[wPartyCount]
- and a
- jp z,.emptyParty
- ld a,[wWhichPokemon]
- push af
- ld a,[wcf91]
- push af
- ld a,$01
- ld [wd07d],a ; item use party menu
- ld a,$ff
- ld [wUpdateSpritesEnabled],a
- ld a,[wd152]
- and a ; using Softboiled?
- jr z,.notUsingSoftboiled
-; if using softboiled
- call GoBackToPartyMenu
- jr .getPartyMonDataAddress
-.emptyParty
- ld hl,.emptyPartyText
- xor a
- ld [wcd6a],a ; item use failed
- jp PrintText
-.emptyPartyText
- text "You don't have"
- line "any #MON!"
- prompt
-.notUsingSoftboiled
- call DisplayPartyMenu
-.getPartyMonDataAddress
- jp c,.canceledItemUse
- ld hl,wPartyMons
- ld bc,wPartyMon2 - wPartyMon1
- ld a,[wWhichPokemon]
- call AddNTimes
- ld a,[wWhichPokemon]
- ld [wcf06],a
- ld d,a
- ld a,[wcf91]
- ld e,a
- ld [wd0b5],a
- pop af
- ld [wcf91],a
- pop af
- ld [wWhichPokemon],a
- ld a,[wd152]
- 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]
- ld bc,$f008
- cp a,ANTIDOTE
- jr z,.checkMonStatus
- ld bc,$f110
- cp a,BURN_HEAL
- jr z,.checkMonStatus
- ld bc,$f220
- cp a,ICE_HEAL
- jr z,.checkMonStatus
- ld bc,$f307
- cp a,AWAKENING
- jr z,.checkMonStatus
- ld bc,$f440
- cp a,PARLYZ_HEAL
- jr z,.checkMonStatus
- ld bc,$f6ff ; 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 [wd07d],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,W_PLAYERBATTSTATUS3
- 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,[W_ISINBATTLE]
- and a
- jr z,.compareCurrentHPToMaxHP
- push hl
- push de
- push bc
- ld a,[wcf06]
- ld c,a
- ld hl,wPartyFoughtCurrentEnemyFlags
- ld b,$02
- predef FlagActionPredef
- ld a,c
- and a
- jr z,.next
- ld a,[wcf06]
- ld c,a
- ld hl,wPartyGainExpFlags
- ld b,$01
- 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 [wc02a],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,[wd152]
- 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
- hlCoord 4, 1
- ld a,[wWhichPokemon]
- ld bc,2 * 20
- call AddNTimes ; calculate coordinates of HP bar of pokemon that used Softboiled
- ld a,(SFX_02_3d - SFX_Headers_02) / 3
- call PlaySoundWaitForCurrent ; play sound
- ld a,[hFlags_0xFFF6]
- set 0,a
- ld [hFlags_0xFFF6],a
- ld a,$02
- ld [wHPBarType],a
- predef UpdateHPBar2 ; animate HP bar decrease of pokemon that used Softboiled
- ld a,[hFlags_0xFFF6]
- res 0,a
- ld [hFlags_0xFFF6],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,[wd152]
- 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_02_3d - SFX_Headers_02) / 3 ; HP healing sound
- call PlaySoundWaitForCurrent ; play sound
- ld a,[hFlags_0xFFF6]
- set 0,a
- ld [hFlags_0xFFF6],a
- ld a,$02
- ld [wHPBarType],a
- predef UpdateHPBar2 ; animate the HP bar lengthening
- ld a,[hFlags_0xFFF6]
- res 0,a
- ld [hFlags_0xFFF6],a
- ld a,$f7 ; revived message
- ld [wd07d],a
- ld a,[wcf91]
- cp a,REVIVE
- jr z,.showHealingItemMessage
- cp a,MAX_REVIVE
- jr z,.showHealingItemMessage
- ld a,$f5 ; standard HP healed message
- ld [wd07d],a
- jr .showHealingItemMessage
-.playStatusAilmentCuringSound
- ld a,(SFX_02_3e - SFX_Headers_02) / 3 ; status ailment curing sound
- 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 [wcd6a],a ; item use failed
- pop af
- pop af
-.done
- ld a,[wd152]
- and a ; using Softboiled?
- ret nz ; if so, return
- call GBPalWhiteOut
- call z,GoPAL_SET_CF1C
- ld a,[W_ISINBATTLE]
- 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 [W_CURENEMYLVL],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_02_3e - SFX_Headers_02) / 3
- call PlaySound ; play sound
- 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 [W_CURENEMYLVL],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,[$ff96]
- ld [hli],a
- ld a,[$ff97]
- ld [hli],a
- ld a,[$ff98]
- 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,$f8 ; level up message
- ld [wd07d],a
- call RedrawPartyMenu
- pop de
- ld a,d
- ld [wWhichPokemon],a
- ld a,e
- ld [wd11e],a
- xor a
- ld [wcc49],a ; load from player's party
- call LoadMonData
- ld d,$01
- callab PrintStatsBox ; display new stats text box
- call WaitForTextScrollButtonPress ; wait for button press
- xor a
- ld [wcc49],a
- predef LearnMoveFromLevelUp ; learn level up move, if any
- xor a
- ld [wccd4],a
- callab TryEvolvingMon ; evolve pokemon, if appropriate
- ld a,$01
- ld [wUpdateSpritesEnabled],a
- pop af
- ld [wcf91],a
- pop af
- ld [wWhichPokemon],a
- jp RemoveUsedItem
-
-VitaminStatRoseText: ; df24 (3:5f24)
- TX_FAR _VitaminStatRoseText
- db "@"
-
-VitaminNoEffectText: ; df29 (3:5f29)
- TX_FAR _VitaminNoEffectText
- db "@"
-
-VitaminText: ; df2e (3:5f2e)
- db "HEALTH@"
- db "ATTACK@"
- db "DEFENSE@"
- db "SPEED@"
- db "SPECIAL@"
-
-ItemUseBait: ; df52 (3:5f52)
- 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: ; df67 (3:5f67)
- 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: ; df7f (3:5f7f)
- ld [W_ANIMATIONID],a
- xor a
- ld [wcc5b],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: ; dfa5 (3:5fa5)
- TX_FAR _ThrewBaitText
- db "@"
-
-ThrewRockText: ; dfaa (3:5faa)
- TX_FAR _ThrewRockText
- db "@"
-
-; also used for Dig out-of-battle effect
-ItemUseEscapeRope: ; dfaf (3:5faf)
- ld a,[W_ISINBATTLE]
- and a
- jr nz,.notUsable
- ld a,[W_CURMAP]
- cp a,AGATHAS_ROOM
- jr z,.notUsable
- ld a,[W_CURMAPTILESET]
- 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]
- ld hl,wd72e
- res 4,[hl]
- ld hl,wd790
- res 7,[hl] ; unset Safari Zone bit
- xor a
- ld [W_NUMSAFARIBALLS],a
- ld [W_SAFARIZONEENTRANCECURSCRIPT],a
- inc a
- ld [wEscapedFromBattle],a
- ld [wcd6a],a ; item used
- ld a,[wd152]
- and a ; using Dig?
- ret nz ; if so, return
- call ItemUseReloadOverworldData
- ld c,30
- call DelayFrames
- jp RemoveUsedItem
-.notUsable
- jp ItemUseNotTime
-
-EscapeRopeTilesets: ; dffd (3:5ffd)
- db FOREST, CEMETERY, CAVERN, FACILITY, INTERIOR
- db $ff ; terminator
-
-ItemUseRepel: ; e003 (3:6003)
- ld b,100
-
-ItemUseRepelCommon: ; e005 (3:6005)
- ld a,[W_ISINBATTLE]
- and a
- jp nz,ItemUseNotTime
- ld a,b
- ld [wRepelRemainingSteps],a
- jp PrintItemUseTextAndRemoveItem
-
-; handles X Accuracy item
-ItemUseXAccuracy: ; e013 (3:6013)
- ld a,[W_ISINBATTLE]
- and a
- jp z,ItemUseNotTime
- ld hl,W_PLAYERBATTSTATUS2
- set UsingXAccuracy,[hl] ; X Accuracy bit
- jp PrintItemUseTextAndRemoveItem
-
-; This function is bugged and never works. It always jumps to ItemUseNotTime.
-; The Card Key is handled in a different way.
-ItemUseCardKey: ; e022 (3:6022)
- xor a
- ld [wd71f],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,[W_CURMAP]
- 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 [wd71f],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: ; e072 (3:6072)
- 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: ; e09b (3:609b)
- 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: ; e0c4 (3:60c4)
- db SILPH_CO_11F,$08,$09,$14
- db SILPH_CO_11F,$09,$09,$15
- db $ff
-
-ItemUsePokedoll: ; e0cd (3:60cd)
- ld a,[W_ISINBATTLE]
- dec a
- jp nz,ItemUseNotTime
- ld a,$01
- ld [wEscapedFromBattle],a
- jp PrintItemUseTextAndRemoveItem
-
-ItemUseGuardSpec: ; e0dc (3:60dc)
- ld a,[W_ISINBATTLE]
- and a
- jp z,ItemUseNotTime
- ld hl,W_PLAYERBATTSTATUS2
- set ProtectedByMist,[hl] ; Mist bit
- jp PrintItemUseTextAndRemoveItem
-
-ItemUseSuperRepel: ; e0eb (3:60eb)
- ld b,200
- jp ItemUseRepelCommon
-
-ItemUseMaxRepel: ; e0f0 (3:60f0)
- ld b,250
- jp ItemUseRepelCommon
-
-ItemUseDireHit: ; e0f5 (3:60f5)
- ld a,[W_ISINBATTLE]
- and a
- jp z,ItemUseNotTime
- ld hl,W_PLAYERBATTSTATUS2
- set GettingPumped,[hl] ; Focus Energy bit
- jp PrintItemUseTextAndRemoveItem
-
-ItemUseXStat: ; e104 (3:6104)
- ld a,[W_ISINBATTLE]
- and a
- jr nz,.inBattle
- call ItemUseNotTime
- ld a,2
- ld [wcd6a],a ; item not used
- ret
-.inBattle
- ld hl,W_PLAYERMOVENUM
- ld a,[hli]
- push af ; save [W_PLAYERMOVENUM]
- ld a,[hl]
- push af ; save [W_PLAYERMOVEEFFECT]
- 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 [W_PLAYERMOVENUM],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
- pop hl
- pop af
- ld [hld],a ; restore [W_PLAYERMOVEEFFECT]
- pop af
- ld [hl],a ; restore [W_PLAYERMOVENUM]
- ret
-
-ItemUsePokeflute: ; e140 (3:6140)
- ld a,[W_ISINBATTLE]
- and a
- jr nz,.inBattle
-; if not in battle
- call ItemUseReloadOverworldData
- ld a,[W_CURMAP]
- cp a,ROUTE_12
- jr nz,.notRoute12
- ld a,[wd7d8]
- bit 7,a ; has the player beaten Route 12 Snorlax yet?
- jr nz,.noSnorlaxToWakeUp
-; if the player hasn't beaten Route 12 Snorlax
- ld hl,Route12SnorlaxFluteCoords
- call ArePlayerCoordsInArray
- jr nc,.noSnorlaxToWakeUp
- ld hl,PlayedFluteHadEffectText
- call PrintText
- ld hl,wd7d8
- set 6,[hl] ; trigger Snorlax fight (handled by map script)
- ret
-.notRoute12
- cp a,ROUTE_16
- jr nz,.noSnorlaxToWakeUp
- ld a,[wd7e0]
- bit 1,a ; has the player beaten Route 16 Snorlax yet?
- jr nz,.noSnorlaxToWakeUp
-; if the player hasn't beaten Route 16 Snorlax
- ld hl,Route16SnorlaxFluteCoords
- call ArePlayerCoordsInArray
- jr nc,.noSnorlaxToWakeUp
- ld hl,PlayedFluteHadEffectText
- call PrintText
- ld hl,wd7e0
- set 0,[hl] ; trigger Snorlax fight (handled by map script)
- ret
-.noSnorlaxToWakeUp
- ld hl,PlayedFluteNoEffectText
- jp PrintText
-.inBattle
- xor a
- ld [wWhichTrade],a ; initialize variable that indicates if any pokemon were woken up to zero
- ld b,~SLP & $FF
- ld hl,wPartyMon1Status
- call WakeUpEntireParty
- ld a,[W_ISINBATTLE]
- 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]
- and b ; remove Sleep status
- ld [hl],a
- call LoadScreenTilesFromBuffer2 ; restore saved screen
- ld a,[wWhichTrade]
- 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,[wc02c]
- 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
-; [wWhichTrade] should be initialized to 0
-; OUTPUT:
-; [wWhichTrade]: set to 1 if any pokemon were asleep
-WakeUpEntireParty: ; e1e5 (3:61e5)
- 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 [wWhichTrade],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: ; e1fd (3:61fd)
- 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: ; e206 (3:6206)
- db 10,27 ; one space East of Snorlax
- db 10,25 ; one space West of Snorlax
- db $ff ; terminator
-
-PlayedFluteNoEffectText: ; e20b (3:620b)
- TX_FAR _PlayedFluteNoEffectText
- db "@"
-
-FluteWokeUpText: ; e210 (3:6210)
- TX_FAR _FluteWokeUpText
- db "@"
-
-PlayedFluteHadEffectText: ; e215 (3:6215)
- TX_FAR _PlayedFluteHadEffectText
- db $06
- db $08
- ld a,[W_ISINBATTLE]
- and a
- jr nz,.done
-; play out-of-battle pokeflute music
- ld a,$ff
- call PlaySound ; turn off music
- ld a, (SFX_02_5e - SFX_Headers_02) / 3
- ld c, BANK(SFX_02_5e)
- call PlayMusic ; play music
-.musicWaitLoop ; wait for music to finish playing
- ld a,[wc028]
- cp a,$b8
- jr z,.musicWaitLoop
- call PlayDefaultMusic ; start playing normal music again
-.done
- jp TextScriptEnd ; end text
-
-ItemUseCoinCase: ; e23a (3:623a)
- ld a,[W_ISINBATTLE]
- and a
- jp nz,ItemUseNotTime
- ld hl,CoinCaseNumCoinsText
- jp PrintText
-
-CoinCaseNumCoinsText: ; e247 (3:6247)
- TX_FAR _CoinCaseNumCoinsText
- db "@"
-
-OldRodCode: ; e24c (3:624c)
- call FishingInit
- jp c, ItemUseNotTime
- ld bc, (5 << 8) | MAGIKARP
- ld a, $1 ; set bite
- jr RodResponse ; 0xe257 $34
-
-GoodRodCode: ; e259 (3:6259)
- 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,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"
-
-SuperRodCode: ; e283 (3:6283)
- call FishingInit
- jp c, ItemUseNotTime
- call ReadSuperRodData ; 0xe8ea
- ld a, e
-RodResponse: ; e28d (3:628d)
- ld [wWhichTrade], a
-
- dec a ; is there a bite?
- jr nz, .next
- ; if yes, store level and species data
- ld a, 1
- ld [W_MOVEMISSED], a
- ld a, b ; level
- ld [W_CURENEMYLVL], a
- ld a, c ; species
- ld [W_CUROPPONENT], a
-
-.next
- ld hl, wWalkBikeSurfState
- ld a, [hl] ; store the value in a
- push af
- push hl
- ld [hl], 0
- callba Func_707b6
- 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: ; e2b4 (3:62b4)
- ld a,[W_ISINBATTLE]
- and a
- jr z,.notInBattle
- scf ; can't fish during battle
- ret
-.notInBattle
- call IsNextTileShoreOrWater
- ret c
- ld a,[wWalkBikeSurfState]
- cp a,2 ; Surfing?
- jr z,.surfing
- call ItemUseReloadOverworldData
- ld hl,ItemUseText00
- call PrintText
- ld a,(SFX_02_3e - SFX_Headers_02) / 3
- call PlaySound ; play sound
- ld c,80
- call DelayFrames
- and a
- ret
-.surfing
- scf ; can't fish when surfing
- ret
-
-ItemUseOaksParcel: ; e2de (3:62de)
- jp ItemUseNotYoursToUse
-
-ItemUseItemfinder: ; e2e1 (3:62e1)
- ld a,[W_ISINBATTLE]
- 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_02_4a - SFX_Headers_02) / 3
- call PlaySoundWaitForCurrent ; play sound
- ld a,(SFX_02_5a - SFX_Headers_02) / 3
- call PlaySoundWaitForCurrent ; play sound
- dec c
- jr nz,.loop
- ld hl,ItemfinderFoundItemText
-.printText
- jp PrintText
-
-ItemfinderFoundItemText: ; e30d (3:630d)
- TX_FAR _ItemfinderFoundItemText
- db "@"
-
-ItemfinderFoundNothingText: ; e312 (3:6312)
- TX_FAR _ItemfinderFoundNothingText
- db "@"
-
-ItemUsePPUp: ; e317 (3:6317)
- ld a,[W_ISINBATTLE]
- and a
- jp nz,ItemUseNotTime
-
-ItemUsePPRestore: ; e31e (3:631e)
- ld a,[wWhichPokemon]
- push af
- ld a,[wcf91]
- ld [wWhichTrade],a
-.chooseMon
- xor a
- ld [wUpdateSpritesEnabled],a
- ld a,$01 ; item use party menu
- ld [wd07d],a
- call DisplayPartyMenu
- jr nc,.chooseMove
- jp .itemNotUsed
-.chooseMove
- ld a,[wWhichTrade]
- cp a,ELIXER
- jp nc,.useElixir ; if Elixir or Max Elixir
- ld a,$02
- ld [wMoveMenuType],a
- ld hl,RaisePPWhichTechniqueText
- ld a,[wWhichTrade]
- 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,44
- call GetSelectedMoveOffset
- push hl
- ld a,[hl]
- ld [wd11e],a
- call GetMoveName
- call CopyStringToCF4B ; copy name to wcf4b
- pop hl
- ld a,[wWhichTrade]
- 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 hl,PPIncreasedText
- call PrintText
-.done
- pop af
- ld [wWhichPokemon],a
- call GBPalWhiteOut
- call GoPAL_SET_CF1C
- 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,44
- call AddNTimes
- ld de,wBattleMonPP
- ld bc,4
- call CopyData ; copy party data to in-battle data
-.skipUpdatingInBattleData
- ld a,(SFX_02_3e - SFX_Headers_02) / 3
- 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
- ld [wcc49],a ; party pokemon
- call GetMaxPP
- ld hl,wPartyMon1Moves
- ld bc,44
- call GetSelectedMoveOffset
- ld bc,21
- add hl,bc ; hl now points to move's PP
- ld a,[wd11e]
- ld b,a ; b = max PP
- ld a,[wWhichTrade]
- 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,wWhichTrade
- 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,44
- 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 GoPAL_SET_CF1C
- pop af
- xor a
- ld [wcd6a],a ; item use failed
- ret
-
-RaisePPWhichTechniqueText: ; e45d (3:645d)
- TX_FAR _RaisePPWhichTechniqueText
- db "@"
-
-RestorePPWhichTechniqueText: ; e462 (3:6462)
- TX_FAR _RestorePPWhichTechniqueText
- db "@"
-
-PPMaxedOutText: ; e467 (3:6467)
- TX_FAR _PPMaxedOutText
- db "@"
-
-PPIncreasedText: ; e46c (3:646c)
- TX_FAR _PPIncreasedText
- db "@"
-
-PPRestoredText: ; e471 (3:6471)
- TX_FAR _PPRestoredText
- db "@"
-
-; for items that can't be used from the Item menu
-UnusableItem: ; e476 (3:6476)
- jp ItemUseNotTime
-
-ItemUseTMHM: ; e479 (3:6479)
- ld a,[W_ISINBATTLE]
- 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
- hlCoord 14, 7
- ld bc,$080f
- 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 [wcd6a],a ; item not used
- ret
-.useMachine
- ld a,[wWhichPokemon]
- push af
- ld a,[wcf91]
- push af
-.chooseMon
- ld hl,wcf4b
- ld de,wd036
- ld bc,14
- call CopyData
- ld a,$ff
- ld [wUpdateSpritesEnabled],a
- ld a,$03 ; teach TM/HM party menu
- ld [wd07d],a
- call DisplayPartyMenu
- push af
- ld hl,wd036
- 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 GoPAL_SET_CF1C
- 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_02_51 - SFX_Headers_02) / 3
- call PlaySoundWaitForCurrent ; play sound
- 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
- pop af
- ld [wcf91],a
- pop af
- ld [wWhichPokemon],a
- ld a,b
- and a
- ret z
- ld a,[wcf91]
- call IsItemHM
- ret c
- jp RemoveUsedItem
-
-BootedUpTMText: ; e54f (3:654f)
- TX_FAR _BootedUpTMText
- db "@"
-
-BootedUpHMText: ; e554 (3:6554)
- TX_FAR _BootedUpHMText
- db "@"
-
-TeachMachineMoveText: ; e559 (3:6559)
- TX_FAR _TeachMachineMoveText
- db "@"
-
-MonCannotLearnMachineMoveText: ; e55e (3:655e)
- TX_FAR _MonCannotLearnMachineMoveText
- db "@"
-
-PrintItemUseTextAndRemoveItem: ; e563 (3:6563)
- ld hl,ItemUseText00
- call PrintText
- ld a,(SFX_02_3e - SFX_Headers_02) / 3
- call PlaySound ; play sound
- call WaitForTextScrollButtonPress ; wait for button press
-
-RemoveUsedItem: ; e571 (3:6571)
- ld hl,wNumBagItems
- ld a,1 ; one item
- ld [wcf96],a ; store quantity
- jp RemoveItemFromInventory
-
-ItemUseNoEffect: ; e57c (3:657c)
- ld hl,ItemUseNoEffectText
- jr ItemUseFailed
-
-ItemUseNotTime: ; e581 (3:6581)
- ld hl,ItemUseNotTimeText
- jr ItemUseFailed
-
-ItemUseNotYoursToUse: ; e586 (3:6586)
- ld hl,ItemUseNotYoursToUseText
- jr ItemUseFailed
-
-ThrowBallAtTrainerMon: ; e58b (3:658b)
- call GoPAL_SET_CF1C
- call LoadScreenTilesFromBuffer1 ; restore saved screen
- call Delay3
- ld a,TOSS_ANIM
- ld [W_ANIMATIONID],a
- predef MoveAnimation ; do animation
- ld hl,ThrowBallAtTrainerMonText1
- call PrintText
- ld hl,ThrowBallAtTrainerMonText2
- call PrintText
- jr RemoveUsedItem
-
-NoCyclingAllowedHere: ; e5ac (3:65ac)
- ld hl,NoCyclingAllowedHereText
- jr ItemUseFailed
-
-BoxFullCannotThrowBall: ; e5b1 (3:65b1)
- ld hl,BoxFullCannotThrowBallText
- jr ItemUseFailed
-
-SurfingAttemptFailed: ; e5b6 (3:65b6)
- ld hl,NoSurfingHereText
-
-ItemUseFailed: ; e5b9 (3:65b9)
- xor a
- ld [wcd6a],a ; item use failed
- jp PrintText
-
-ItemUseNotTimeText: ; e5c0 (3:65c0)
- TX_FAR _ItemUseNotTimeText
- db "@"
-
-ItemUseNotYoursToUseText: ; e5c5 (3:65c5)
- TX_FAR _ItemUseNotYoursToUseText
- db "@"
-
-ItemUseNoEffectText: ; e5ca (3:65ca)
- TX_FAR _ItemUseNoEffectText
- db "@"
-
-ThrowBallAtTrainerMonText1: ; e5cf (3:65cf)
- TX_FAR _ThrowBallAtTrainerMonText1
- db "@"
-
-ThrowBallAtTrainerMonText2: ; e5d4 (3:65d4)
- TX_FAR _ThrowBallAtTrainerMonText2
- db "@"
-
-NoCyclingAllowedHereText: ; e5d9 (3:65d9)
- TX_FAR _NoCyclingAllowedHereText
- db "@"
-
-NoSurfingHereText: ; e5de (3:65de)
- TX_FAR _NoSurfingHereText
- db "@"
-
-BoxFullCannotThrowBallText: ; e5e3 (3:65e3)
- TX_FAR _BoxFullCannotThrowBallText
- db "@"
-
-ItemUseText00: ; e5e8 (3:65e8)
- TX_FAR _ItemUseText001
- db $05
- TX_FAR _ItemUseText002
- db "@"
-
-GotOnBicycleText: ; e5f2 (3:65f2)
- TX_FAR _GotOnBicycleText1
- db $05
- TX_FAR _GotOnBicycleText2
- db "@"
-
-GotOffBicycleText: ; e5fc (3:65fc)
- 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
-; [wd11e] = mode
-; 0: Pokemon Center healing
-; 1: using a PP Up
-; [wCurrentMenuItem] = index of move (when using a PP Up)
-RestoreBonusPP: ; e606 (3:6606)
- ld hl,wPartyMon1Moves
- ld bc,44
- ld a,[wWhichPokemon]
- call AddNTimes
- push hl
- ld de,wcd78 - 1
- predef LoadMovePPs ; loads the normal max PP of each of the pokemon's moves to wcd78
- pop hl
- ld c,21
- ld b,0
- add hl,bc ; hl now points to move 1 PP
- ld de,wcd78
- 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,[wd11e]
- 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
-; [wd11e] = max number of times to add bonus
-; set to 1 when using a PP Up, set to 255 otherwise
-AddBonusPP: ; e642 (3:6642)
- 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,%00001111
- 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,[wd11e]
- dec a
- jr z,.done
- 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
-; [wcc49] = 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:
-; [wd11e] = max PP
-GetMaxPP: ; e677 (3:6677)
- ld a,[wcc49]
- 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,6
- call AddNTimes
- ld de,wcd6d
- ld a,BANK(Moves)
- call FarCopyData
- ld de,wcd72
- ld a,[de]
- ld b,a ; b = normal max PP
- pop hl
- push bc
- ld bc,21 ; PP offset if not player's in-battle pokemon data
- ld a,[wcc49]
- cp a,4 ; player's in-battle pokemon?
- jr nz,.addPPOffset
- ld bc,17 ; 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
- ld [wd11e],a ; no limit on PP Up amount
- call AddBonusPP ; add bonus PP from PP Ups
- ld a,[hl]
- and a,%00111111 ; mask out the PP Up count
- ld [wd11e],a ; store max PP
- ret
-
-GetSelectedMoveOffset: ; e6e3 (3:66e3)
- ld a,[wWhichPokemon]
- call AddNTimes
-
-GetSelectedMoveOffset2: ; e6e9 (3:66e9)
- 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
-; [wcf96] = quantity to toss
-; OUTPUT:
-; clears carry flag if the item is tossed, sets carry flag if not
-TossItem_: ; e6f1 (3:66f1)
- push hl
- ld a,[wcf91]
- call IsItemHM
- pop hl
- jr c,.tooImportantToToss
- push hl
- call IsKeyItem_
- ld a,[wd124]
- 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
- hlCoord 14, 7
- ld bc,$080f
- ld a,TWO_OPTION_MENU
- ld [wTextBoxID],a
- call DisplayTextBoxID ; yes/no menu
- ld a,[wd12e]
- cp a,2
- pop hl
- scf
- ret z
-; 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: ; e755 (3:6755)
- TX_FAR _ThrewAwayItemText
- db "@"
-
-IsItOKToTossItemText: ; e75a (3:675a)
- TX_FAR _IsItOKToTossItemText
- db "@"
-
-TooImportantToTossText: ; e75f (3:675f)
- TX_FAR _TooImportantToTossText
- db "@"
-
-; checks if an item is a key item
-; INPUT:
-; [wcf91] = item ID
-; OUTPUT:
-; [wd124] = result
-; 00: item is not key item
-; 01: item is key item
-IsKeyItem_: ; e764 (3:6764)
- ld a,$01
- ld [wd124],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,wHPBarMaxHP
- ld bc,15 ; only 11 bytes are actually used
- call CopyData
- pop af
- dec a
- ld c,a
- ld hl,wHPBarMaxHP
- ld b,$02 ; test bit
- predef FlagActionPredef ; bitfield operation function
- ld a,c
- and a
- ret nz
-.checkIfItemIsHM
- ld a,[wcf91]
- call IsItemHM
- ret c
- xor a
- ld [wd124],a
- ret
-
-INCLUDE "data/key_items.asm"
-
-SendNewMonToBox: ; e7a4 (3:67a4)
- ld de, W_NUMINBOX ; wda80
- ld a, [de]
- inc a
- ld [de], a
- ld a, [wcf91]
- ld [wd0b5], a
- ld c, a
-.asm_e7b1
- inc de
- ld a, [de]
- ld b, a
- ld a, c
- ld c, b
- ld [de], a
- cp $ff
- jr nz, .asm_e7b1
- call GetMonHeader
- ld hl, wBoxMonOT
- ld bc, $b
- ld a, [W_NUMINBOX] ; wda80
- dec a
- jr z, .asm_e7ee
- dec a
- call AddNTimes
- push hl
- ld bc, $b
- add hl, bc
- ld d, h
- ld e, l
- pop hl
- ld a, [W_NUMINBOX] ; wda80
- dec a
- ld b, a
-.asm_e7db
- push bc
- push hl
- ld bc, $b
- call CopyData
- pop hl
- ld d, h
- ld e, l
- ld bc, $fff5
- add hl, bc
- pop bc
- dec b
- jr nz, .asm_e7db
-.asm_e7ee
- ld hl, wPlayerName ; wd158
- ld de, wBoxMonOT
- ld bc, $b
- call CopyData
- ld a, [W_NUMINBOX] ; wda80
- dec a
- jr z, .asm_e82a
- ld hl, wBoxMonNicks
- ld bc, $b
- dec a
- call AddNTimes
- push hl
- ld bc, $b
- add hl, bc
- ld d, h
- ld e, l
- pop hl
- ld a, [W_NUMINBOX] ; wda80
- dec a
- ld b, a
-.asm_e817
- push bc
- push hl
- ld bc, $b
- call CopyData
- pop hl
- ld d, h
- ld e, l
- ld bc, $fff5
- add hl, bc
- pop bc
- dec b
- jr nz, .asm_e817
-.asm_e82a
- ld hl, wBoxMonNicks
- ld a, $2
- ld [wd07d], a
- predef AskName
- ld a, [W_NUMINBOX] ; wda80
- dec a
- jr z, .asm_e867
- 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, [W_NUMINBOX] ; wda80
- dec a
- ld b, a
-.asm_e854
- push bc
- push hl
- ld bc, wBoxMon2 - wBoxMon1
- call CopyData
- pop hl
- ld d, h
- ld e, l
- ld bc, $ffdf
- add hl, bc
- pop bc
- dec b
- jr nz, .asm_e854
-.asm_e867
- ld a, [wEnemyMonLevel] ; wEnemyMonLevel
- ld [wEnemyMonBoxLevel], a
- ld hl, wEnemyMon
- ld de, wBoxMon1
- ld bc, $c
- call CopyData
- ld hl, wPlayerID ; wPlayerID
- ld a, [hli]
- ld [de], a
- inc de
- ld a, [hl]
- ld [de], a
- inc de
- push de
- ld a, [W_CURENEMYLVL] ; W_CURENEMYLVL
- ld d, a
- callab CalcExperience
- pop de
- ld a, [H_NUMTOPRINT] ; $ff96 (aliases: H_MULTIPLICAND)
- ld [de], a
- inc de
- ld a, [$ff97]
- ld [de], a
- inc de
- ld a, [$ff98]
- ld [de], a
- inc de
- xor a
- ld b, $a
-.asm_e89f
- ld [de], a
- inc de
- dec b
- jr nz, .asm_e89f
- ld hl, wEnemyMonDVs
- ld a, [hli]
- ld [de], a
- inc de
- ld a, [hli]
- ld [de], a
- ld hl, wEnemyMonPP ; wcffe
- ld b, $4
-.asm_e8b1
- ld a, [hli]
- inc de
- ld [de], a
- dec b
- jr nz, .asm_e8b1
- 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: ; e8b8 (3:68b8)
- ld a, [W_CURMAPTILESET]
- ld hl, WaterTilesets
- ld de,1
- call IsInArray ; does the current map allow surfing?
- ret nc ; if not, return
- ld hl,WaterTile
- ld a, [W_CURMAPTILESET]
- 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
-
-ReadSuperRodData: ; e8ea (3:68ea)
-; return e = 2 if no fish on this map
-; return e = 1 if a bite, bc = level,species
-; return e = 0 if no bite
- ld a, [W_CURMAP]
- ld de, 3 ; each fishing group is three bytes wide
- ld hl, SuperRodData
- call IsInArray
- jr c, .ReadFishingGroup
- ld e, $2 ; $2 if no fishing groups found
- ret
-
-.ReadFishingGroup ; 0xe8f6
-; hl points to the fishing group entry in the index
- inc hl ; skip map id
-
- ; read fishing group address
- ld a, [hli]
- ld h, [hl]
- ld l, a
-
- ld b, [hl] ; how many mons in group
- inc hl ; point to data
- ld e, $0 ; no bite yet
-
-.RandomLoop ; 0xe90c
- call Random
- srl a
- ret c ; 50% chance of no battle
-
- and %11 ; 2-bit random number
- cp b
- jr nc, .RandomLoop ; if a is greater than the number of mons, regenerate
-
- ; get the mon
- add a
- ld c, a
- ld b, $0
- add hl, bc
- ld b, [hl] ; level
- inc hl
- ld c, [hl] ; species
- ld e, $1 ; $1 if there's a bite
- ret
-
-INCLUDE "data/super_rod.asm"
-
-; reloads map view and processes sprite data
-; for items that cause the overworld to be displayed
-ItemUseReloadOverworldData: ; e9c5 (3:69c5)
- 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: ; e9cb (3:69cb)
- 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: ; e9f0 (3:69f0)
- 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
+UseItem_: ; d5c7 (3:55c7)
+ ld a,1
+ ld [wcd6a],a
+ 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: ; d5e1 (3:55e1)
+ 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 OldRodCode ; OLD_ROD
+ dw GoodRodCode ; GOOD_ROD
+ dw SuperRodCode ; SUPER_ROD
+ dw ItemUsePPUp ; PP_UP (real one)
+ dw ItemUsePPRestore ; ETHER
+ dw ItemUsePPRestore ; MAX_ETHER
+ dw ItemUsePPRestore ; ELIXER
+ dw ItemUsePPRestore ; MAX_ELIXER
+
+ItemUseBall: ; d687 (3:5687)
+ ld a,[W_ISINBATTLE]
+ and a
+ jp z,ItemUseNotTime ; not in battle
+ dec a
+ jp nz,ThrowBallAtTrainerMon
+ ld a,[W_BATTLETYPE]
+ dec a
+ jr z,.UseBall
+ ld a,[wPartyCount] ;is Party full?
+ cp a,PARTY_LENGTH
+ jr nz,.UseBall
+ ld a,[W_NUMINBOX] ;is Box full?
+ cp a,MONS_PER_BOX
+ jp z,BoxFullCannotThrowBall
+.UseBall ;$56a7
+;ok, you can use a ball
+ xor a
+ ld [wd11c],a
+ ld a,[W_BATTLETYPE]
+ cp a,2 ;SafariBattle
+ jr nz,.skipSafariZoneCode
+.safariZone
+ ; remove a Safari Ball from inventory
+ ld hl,W_NUMSAFARIBALLS
+ dec [hl]
+.skipSafariZoneCode ;$56b6
+ call GoPAL_SET_CF1C
+ 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,[W_BATTLETYPE]
+ dec a
+ jr nz,.notOldManBattle
+.oldManBattle
+ ld hl,W_GRASSRATE
+ ld de,wPlayerName
+ ld bc,11
+ call CopyData ; save the player's name in the Wild Monster data (part of the Cinnabar Island Missingno glitch)
+ jp .BallSuccess ;$578b
+.notOldManBattle ;$56e9
+ ld a,[W_CURMAP]
+ 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 ;$56fa
+ call Random
+ ld b,a
+ ld hl,wcf91
+ ld a,[hl]
+ cp a,MASTER_BALL
+ jp z,.BallSuccess ;$578b
+ 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 ;$571a
+; 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 ;$5728
+ ld a,b
+ sub c
+ jp c,.BallSuccess ;$578b
+ ld b,a
+.noAilments ;$572e
+ 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 a,GREAT_BALL
+ ld a,12 ;any other BallFactor
+ jr nz,.next7
+ ld a,8
+.next7 ;$574d
+ 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 ;$5766
+ 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 ;$5776
+ 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 ;$578b
+ jr .BallSuccess2
+.next10 ;$578d
+ 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 a,POKE_BALL
+ jr z,.next11
+ ld b,200
+ cp a,GREAT_BALL
+ jr z,.next11
+ ld b,150
+ cp a,ULTRA_BALL
+ jr z,.next11
+.next11 ;$57b8
+ 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 a, 1 << FRZ | SLP
+ ld b,5
+ jr z,.next14
+ ld b,10
+.next14 ;$57e6
+ ld a,[H_QUOTIENT + 3]
+ add b
+ ld [H_QUOTIENT + 3],a
+.next13 ;$57eb
+ 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 ;$5801
+ ld a,b
+ ld [wd11e],a
+.BallSuccess2 ;$5805
+ ld c,20
+ call DelayFrames
+ ld a,TOSS_ANIM
+ ld [W_ANIMATIONID],a
+ xor a
+ ld [$fff3],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,[wd11e]
+ 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,W_ENEMYBATTSTATUS3
+ bit Transformed,[hl]
+ jr z,.next15
+ ld a,$4c
+ ld [wEnemyMonSpecies2],a
+ jr .next16
+.next15 ;$5871
+ set Transformed,[hl]
+ ld hl,wcceb
+ ld a,[wEnemyMonDVs]
+ ld [hli],a
+ ld a,[wEnemyMonDVs + 1]
+ ld [hl],a
+.next16 ;$587e
+ ld a,[wcf91]
+ push af
+ ld a,[wEnemyMonSpecies2]
+ ld [wcf91],a
+ ld a,[wEnemyMonLevel]
+ ld [W_CURENEMYLVL],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 [wd11c],a
+ ld [wcf91],a
+ ld [wd11e],a
+ ld a,[W_BATTLETYPE]
+ dec a
+ jr z,.printText1
+ ld hl,ItemUseBallText05
+ call PrintText
+ predef IndexToPokedex
+ ld a,[wd11e]
+ dec a
+ ld c,a
+ ld b,2
+ ld hl,wPokedexOwned ;Dex_own_flags (pokemon)
+ predef FlagActionPredef
+ ld a,c
+ push af
+ ld a,[wd11e]
+ dec a
+ ld c,a
+ ld b,1
+ 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 ;$58f4
+ ld a,[wPartyCount]
+ cp a,PARTY_LENGTH ;is party full?
+ jr z,.sendToBox
+ xor a
+ ld [wcc49],a
+ call ClearSprites
+ call AddPartyMon ;add mon to Party
+ jr .End
+.sendToBox ;$5907
+ call ClearSprites
+ call SendNewMonToBox
+ ld hl,ItemUseBallText07
+ ld a,[wd7f1]
+ bit 0,a ;already met Bill?
+ jr nz,.sendToBox2
+ ld hl,ItemUseBallText08
+.sendToBox2 ;$591a
+ call PrintText
+ jr .End
+.printText1 ;$591f
+ ld hl,ItemUseBallText05
+.printText0 ;$5922
+ call PrintText
+ call ClearSprites
+.End ;$5928
+ ld a,[W_BATTLETYPE]
+ and a
+ ret nz
+ ld hl,wNumBagItems
+ inc a
+ ld [wcf96],a
+ jp RemoveItemFromInventory ;remove ITEM (XXX)
+ItemUseBallText00: ; d937 (3:5937)
+;"It dodged the thrown ball!"
+;"This pokemon can't be caught"
+ TX_FAR _ItemUseBallText00
+ db "@"
+ItemUseBallText01: ; d93c (3:593c)
+;"You missed the pokemon!"
+ TX_FAR _ItemUseBallText01
+ db "@"
+ItemUseBallText02: ; d941 (3:5941)
+;"Darn! The pokemon broke free!"
+ TX_FAR _ItemUseBallText02
+ db "@"
+ItemUseBallText03: ; d946 (3:5946)
+;"Aww! It appeared to be caught!"
+ TX_FAR _ItemUseBallText03
+ db "@"
+ItemUseBallText04: ; d94b (3:594b)
+;"Shoot! It was so close too!"
+ TX_FAR _ItemUseBallText04
+ db "@"
+ItemUseBallText05: ; d950 (3:5950)
+;"All right! {MonName} was caught!"
+;play sound
+ TX_FAR _ItemUseBallText05
+ db $12,$06
+ db "@"
+ItemUseBallText07: ; d957 (3:5957)
+;"X was transferred to Bill's PC"
+ TX_FAR _ItemUseBallText07
+ db "@"
+ItemUseBallText08: ; d95c (3:595c)
+;"X was transferred to someone's PC"
+ TX_FAR _ItemUseBallText08
+ db "@"
+
+ItemUseBallText06: ; d961 (3:5961)
+;"New DEX data will be added..."
+;play sound
+ TX_FAR _ItemUseBallText06
+ db $13,$06
+ db "@"
+
+ItemUseTownMap: ; d968 (3:5968)
+ ld a,[W_ISINBATTLE]
+ and a
+ jp nz,ItemUseNotTime
+ ld b, BANK(DisplayTownMap)
+ ld hl, DisplayTownMap
+ jp Bankswitch ; display Town Map
+
+ItemUseBicycle: ; d977 (3:5977)
+ ld a,[W_ISINBATTLE]
+ 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
+ call PlayDefaultMusic ; play walking music
+ ld hl,GotOffBicycleText
+ jr .printText
+.tryToGetOnBike
+ call IsBikeRidingAllowed
+ jp nc,NoCyclingAllowedHere
+ call ItemUseReloadOverworldData
+ xor a ; no keys pressed
+ ld [hJoyHeld],a ; current joypad state
+ inc a
+ ld [wWalkBikeSurfState],a ; change player state to bicycling
+ ld hl,GotOnBicycleText
+ call PlayDefaultMusic ; play bike riding music
+.printText
+ jp PrintText
+
+; used for Surf out-of-battle effect
+ItemUseSurfboard: ; d9b4 (3:59b4)
+ ld a,[wWalkBikeSurfState]
+ ld [wWalkBikeSurfStateCopy],a
+ cp a,2 ; is the player already surfing?
+ jr z,.tryToStopSurfing
+.tryToSurf
+ call IsNextTileShoreOrWater
+ jp c,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 [$ff8c],a
+ ld d,16 ; talking range in pixels (normal range)
+ call IsSpriteInFrontOfPlayer2
+ res 7,[hl]
+ ld a,[$ff8c]
+ and a ; is there a sprite in the way?
+ jr nz,.cannotStopSurfing
+ ld hl,TilePairCollisionsWater
+ call CheckForTilePairCollisions
+ jr c,.cannotStopSurfing
+ ld hl,W_TILESETCOLLISIONPTR ; pointer to list of passable tiles
+ ld a,[hli]
+ ld h,[hl]
+ ld l,a ; hl now points to passable tiles
+ ld a,[wTileInFrontOfPlayer] ; tile in front of the player
+ ld b,a
+.passableTileLoop
+ ld a,[hli]
+ cp b
+ jr z,.stopSurfing
+ cp a,$ff
+ jr nz,.passableTileLoop
+.cannotStopSurfing
+ ld hl,SurfingNoPlaceToGetOffText
+ jp PrintText
+.stopSurfing
+ call .makePlayerMoveForward
+ 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
+ jp LoadWalkingPlayerSpriteGraphics
+; uses a simulated button press to make the player move forward
+.makePlayerMoveForward
+ ld a,[wd52a] ; direction the player is going
+ bit 3,a
+ ld b,D_UP
+ jr nz,.storeSimulatedButtonPress
+ bit 2,a
+ ld b,D_DOWN
+ jr nz,.storeSimulatedButtonPress
+ bit 1,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: ; da4c (3:5a4c)
+ TX_FAR _SurfingGotOnText
+ db "@"
+
+SurfingNoPlaceToGetOffText: ; da51 (3:5a51)
+ TX_FAR _SurfingNoPlaceToGetOffText
+ db "@"
+
+ItemUsePokedex: ; da56 (3:5a56)
+ predef_jump ShowPokedexMenu
+
+ItemUseEvoStone: ; da5b (3:5a5b)
+ ld a,[W_ISINBATTLE]
+ and a
+ jp nz,ItemUseNotTime
+ ld a,[wWhichPokemon]
+ push af
+ ld a,[wcf91]
+ ld [wd156],a
+ push af
+ ld a,$05 ; evolution stone party menu
+ ld [wd07d],a
+ ld a,$ff
+ ld [wUpdateSpritesEnabled],a
+ call DisplayPartyMenu
+ pop bc
+ jr c,.canceledItemUse
+ ld a,b
+ ld [wcf91],a
+ ld a,$01
+ ld [wccd4],a
+ ld a,(SFX_02_3e - SFX_Headers_02) / 3
+ call PlaySoundWaitForCurrent ; play sound
+ call WaitForSoundToFinish ; wait for sound to end
+ callab TryEvolvingMon ; try to evolve pokemon
+ ld a,[wd121]
+ and a
+ jr z,.noEffect
+ pop af
+ ld [wWhichPokemon],a
+ ld hl,wNumBagItems
+ ld a,1 ; remove 1 stone
+ ld [wcf96],a
+ jp RemoveItemFromInventory
+.noEffect
+ call ItemUseNoEffect
+.canceledItemUse
+ xor a
+ ld [wcd6a],a
+ pop af
+ ret
+
+ItemUseVitamin: ; dab4 (3:5ab4)
+ ld a,[W_ISINBATTLE]
+ and a
+ jp nz,ItemUseNotTime
+
+ItemUseMedicine: ; dabb (3:5abb)
+ ld a,[wPartyCount]
+ and a
+ jp z,.emptyParty
+ ld a,[wWhichPokemon]
+ push af
+ ld a,[wcf91]
+ push af
+ ld a,$01
+ ld [wd07d],a ; item use party menu
+ ld a,$ff
+ ld [wUpdateSpritesEnabled],a
+ ld a,[wd152]
+ and a ; using Softboiled?
+ jr z,.notUsingSoftboiled
+; if using softboiled
+ call GoBackToPartyMenu
+ jr .getPartyMonDataAddress
+.emptyParty
+ ld hl,.emptyPartyText
+ xor a
+ ld [wcd6a],a ; item use failed
+ jp PrintText
+.emptyPartyText
+ text "You don't have"
+ line "any #MON!"
+ prompt
+.notUsingSoftboiled
+ call DisplayPartyMenu
+.getPartyMonDataAddress
+ jp c,.canceledItemUse
+ ld hl,wPartyMons
+ ld bc,wPartyMon2 - wPartyMon1
+ ld a,[wWhichPokemon]
+ call AddNTimes
+ ld a,[wWhichPokemon]
+ ld [wcf06],a
+ ld d,a
+ ld a,[wcf91]
+ ld e,a
+ ld [wd0b5],a
+ pop af
+ ld [wcf91],a
+ pop af
+ ld [wWhichPokemon],a
+ ld a,[wd152]
+ 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]
+ ld bc,$f008
+ cp a,ANTIDOTE
+ jr z,.checkMonStatus
+ ld bc,$f110
+ cp a,BURN_HEAL
+ jr z,.checkMonStatus
+ ld bc,$f220
+ cp a,ICE_HEAL
+ jr z,.checkMonStatus
+ ld bc,$f307
+ cp a,AWAKENING
+ jr z,.checkMonStatus
+ ld bc,$f440
+ cp a,PARLYZ_HEAL
+ jr z,.checkMonStatus
+ ld bc,$f6ff ; 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 [wd07d],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,W_PLAYERBATTSTATUS3
+ 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,[W_ISINBATTLE]
+ and a
+ jr z,.compareCurrentHPToMaxHP
+ push hl
+ push de
+ push bc
+ ld a,[wcf06]
+ ld c,a
+ ld hl,wPartyFoughtCurrentEnemyFlags
+ ld b,$02
+ predef FlagActionPredef
+ ld a,c
+ and a
+ jr z,.next
+ ld a,[wcf06]
+ ld c,a
+ ld hl,wPartyGainExpFlags
+ ld b,$01
+ 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 [wc02a],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,[wd152]
+ 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
+ hlCoord 4, 1
+ ld a,[wWhichPokemon]
+ ld bc,2 * 20
+ call AddNTimes ; calculate coordinates of HP bar of pokemon that used Softboiled
+ ld a,(SFX_02_3d - SFX_Headers_02) / 3
+ call PlaySoundWaitForCurrent ; play sound
+ ld a,[hFlags_0xFFF6]
+ set 0,a
+ ld [hFlags_0xFFF6],a
+ ld a,$02
+ ld [wHPBarType],a
+ predef UpdateHPBar2 ; animate HP bar decrease of pokemon that used Softboiled
+ ld a,[hFlags_0xFFF6]
+ res 0,a
+ ld [hFlags_0xFFF6],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,[wd152]
+ 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_02_3d - SFX_Headers_02) / 3 ; HP healing sound
+ call PlaySoundWaitForCurrent ; play sound
+ ld a,[hFlags_0xFFF6]
+ set 0,a
+ ld [hFlags_0xFFF6],a
+ ld a,$02
+ ld [wHPBarType],a
+ predef UpdateHPBar2 ; animate the HP bar lengthening
+ ld a,[hFlags_0xFFF6]
+ res 0,a
+ ld [hFlags_0xFFF6],a
+ ld a,$f7 ; revived message
+ ld [wd07d],a
+ ld a,[wcf91]
+ cp a,REVIVE
+ jr z,.showHealingItemMessage
+ cp a,MAX_REVIVE
+ jr z,.showHealingItemMessage
+ ld a,$f5 ; standard HP healed message
+ ld [wd07d],a
+ jr .showHealingItemMessage
+.playStatusAilmentCuringSound
+ ld a,(SFX_02_3e - SFX_Headers_02) / 3 ; status ailment curing sound
+ 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 [wcd6a],a ; item use failed
+ pop af
+ pop af
+.done
+ ld a,[wd152]
+ and a ; using Softboiled?
+ ret nz ; if so, return
+ call GBPalWhiteOut
+ call z,GoPAL_SET_CF1C
+ ld a,[W_ISINBATTLE]
+ 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 [W_CURENEMYLVL],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_02_3e - SFX_Headers_02) / 3
+ call PlaySound ; play sound
+ 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 [W_CURENEMYLVL],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,[$ff96]
+ ld [hli],a
+ ld a,[$ff97]
+ ld [hli],a
+ ld a,[$ff98]
+ 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,$f8 ; level up message
+ ld [wd07d],a
+ call RedrawPartyMenu
+ pop de
+ ld a,d
+ ld [wWhichPokemon],a
+ ld a,e
+ ld [wd11e],a
+ xor a
+ ld [wcc49],a ; load from player's party
+ call LoadMonData
+ ld d,$01
+ callab PrintStatsBox ; display new stats text box
+ call WaitForTextScrollButtonPress ; wait for button press
+ xor a
+ ld [wcc49],a
+ predef LearnMoveFromLevelUp ; learn level up move, if any
+ xor a
+ ld [wccd4],a
+ callab TryEvolvingMon ; evolve pokemon, if appropriate
+ ld a,$01
+ ld [wUpdateSpritesEnabled],a
+ pop af
+ ld [wcf91],a
+ pop af
+ ld [wWhichPokemon],a
+ jp RemoveUsedItem
+
+VitaminStatRoseText: ; df24 (3:5f24)
+ TX_FAR _VitaminStatRoseText
+ db "@"
+
+VitaminNoEffectText: ; df29 (3:5f29)
+ TX_FAR _VitaminNoEffectText
+ db "@"
+
+VitaminText: ; df2e (3:5f2e)
+ db "HEALTH@"
+ db "ATTACK@"
+ db "DEFENSE@"
+ db "SPEED@"
+ db "SPECIAL@"
+
+ItemUseBait: ; df52 (3:5f52)
+ 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: ; df67 (3:5f67)
+ 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: ; df7f (3:5f7f)
+ ld [W_ANIMATIONID],a
+ xor a
+ ld [wcc5b],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: ; dfa5 (3:5fa5)
+ TX_FAR _ThrewBaitText
+ db "@"
+
+ThrewRockText: ; dfaa (3:5faa)
+ TX_FAR _ThrewRockText
+ db "@"
+
+; also used for Dig out-of-battle effect
+ItemUseEscapeRope: ; dfaf (3:5faf)
+ ld a,[W_ISINBATTLE]
+ and a
+ jr nz,.notUsable
+ ld a,[W_CURMAP]
+ cp a,AGATHAS_ROOM
+ jr z,.notUsable
+ ld a,[W_CURMAPTILESET]
+ 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]
+ ld hl,wd72e
+ res 4,[hl]
+ ld hl,wd790
+ res 7,[hl] ; unset Safari Zone bit
+ xor a
+ ld [W_NUMSAFARIBALLS],a
+ ld [W_SAFARIZONEENTRANCECURSCRIPT],a
+ inc a
+ ld [wEscapedFromBattle],a
+ ld [wcd6a],a ; item used
+ ld a,[wd152]
+ and a ; using Dig?
+ ret nz ; if so, return
+ call ItemUseReloadOverworldData
+ ld c,30
+ call DelayFrames
+ jp RemoveUsedItem
+.notUsable
+ jp ItemUseNotTime
+
+EscapeRopeTilesets: ; dffd (3:5ffd)
+ db FOREST, CEMETERY, CAVERN, FACILITY, INTERIOR
+ db $ff ; terminator
+
+ItemUseRepel: ; e003 (3:6003)
+ ld b,100
+
+ItemUseRepelCommon: ; e005 (3:6005)
+ ld a,[W_ISINBATTLE]
+ and a
+ jp nz,ItemUseNotTime
+ ld a,b
+ ld [wRepelRemainingSteps],a
+ jp PrintItemUseTextAndRemoveItem
+
+; handles X Accuracy item
+ItemUseXAccuracy: ; e013 (3:6013)
+ ld a,[W_ISINBATTLE]
+ and a
+ jp z,ItemUseNotTime
+ ld hl,W_PLAYERBATTSTATUS2
+ set UsingXAccuracy,[hl] ; X Accuracy bit
+ jp PrintItemUseTextAndRemoveItem
+
+; This function is bugged and never works. It always jumps to ItemUseNotTime.
+; The Card Key is handled in a different way.
+ItemUseCardKey: ; e022 (3:6022)
+ xor a
+ ld [wd71f],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,[W_CURMAP]
+ 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 [wd71f],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: ; e072 (3:6072)
+ 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: ; e09b (3:609b)
+ 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: ; e0c4 (3:60c4)
+ db SILPH_CO_11F,$08,$09,$14
+ db SILPH_CO_11F,$09,$09,$15
+ db $ff
+
+ItemUsePokedoll: ; e0cd (3:60cd)
+ ld a,[W_ISINBATTLE]
+ dec a
+ jp nz,ItemUseNotTime
+ ld a,$01
+ ld [wEscapedFromBattle],a
+ jp PrintItemUseTextAndRemoveItem
+
+ItemUseGuardSpec: ; e0dc (3:60dc)
+ ld a,[W_ISINBATTLE]
+ and a
+ jp z,ItemUseNotTime
+ ld hl,W_PLAYERBATTSTATUS2
+ set ProtectedByMist,[hl] ; Mist bit
+ jp PrintItemUseTextAndRemoveItem
+
+ItemUseSuperRepel: ; e0eb (3:60eb)
+ ld b,200
+ jp ItemUseRepelCommon
+
+ItemUseMaxRepel: ; e0f0 (3:60f0)
+ ld b,250
+ jp ItemUseRepelCommon
+
+ItemUseDireHit: ; e0f5 (3:60f5)
+ ld a,[W_ISINBATTLE]
+ and a
+ jp z,ItemUseNotTime
+ ld hl,W_PLAYERBATTSTATUS2
+ set GettingPumped,[hl] ; Focus Energy bit
+ jp PrintItemUseTextAndRemoveItem
+
+ItemUseXStat: ; e104 (3:6104)
+ ld a,[W_ISINBATTLE]
+ and a
+ jr nz,.inBattle
+ call ItemUseNotTime
+ ld a,2
+ ld [wcd6a],a ; item not used
+ ret
+.inBattle
+ ld hl,W_PLAYERMOVENUM
+ ld a,[hli]
+ push af ; save [W_PLAYERMOVENUM]
+ ld a,[hl]
+ push af ; save [W_PLAYERMOVEEFFECT]
+ 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 [W_PLAYERMOVENUM],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
+ pop hl
+ pop af
+ ld [hld],a ; restore [W_PLAYERMOVEEFFECT]
+ pop af
+ ld [hl],a ; restore [W_PLAYERMOVENUM]
+ ret
+
+ItemUsePokeflute: ; e140 (3:6140)
+ ld a,[W_ISINBATTLE]
+ and a
+ jr nz,.inBattle
+; if not in battle
+ call ItemUseReloadOverworldData
+ ld a,[W_CURMAP]
+ cp a,ROUTE_12
+ jr nz,.notRoute12
+ ld a,[wd7d8]
+ bit 7,a ; has the player beaten Route 12 Snorlax yet?
+ jr nz,.noSnorlaxToWakeUp
+; if the player hasn't beaten Route 12 Snorlax
+ ld hl,Route12SnorlaxFluteCoords
+ call ArePlayerCoordsInArray
+ jr nc,.noSnorlaxToWakeUp
+ ld hl,PlayedFluteHadEffectText
+ call PrintText
+ ld hl,wd7d8
+ set 6,[hl] ; trigger Snorlax fight (handled by map script)
+ ret
+.notRoute12
+ cp a,ROUTE_16
+ jr nz,.noSnorlaxToWakeUp
+ ld a,[wd7e0]
+ bit 1,a ; has the player beaten Route 16 Snorlax yet?
+ jr nz,.noSnorlaxToWakeUp
+; if the player hasn't beaten Route 16 Snorlax
+ ld hl,Route16SnorlaxFluteCoords
+ call ArePlayerCoordsInArray
+ jr nc,.noSnorlaxToWakeUp
+ ld hl,PlayedFluteHadEffectText
+ call PrintText
+ ld hl,wd7e0
+ set 0,[hl] ; trigger Snorlax fight (handled by map script)
+ ret
+.noSnorlaxToWakeUp
+ ld hl,PlayedFluteNoEffectText
+ jp PrintText
+.inBattle
+ xor a
+ ld [wWhichTrade],a ; initialize variable that indicates if any pokemon were woken up to zero
+ ld b,~SLP & $FF
+ ld hl,wPartyMon1Status
+ call WakeUpEntireParty
+ ld a,[W_ISINBATTLE]
+ 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]
+ and b ; remove Sleep status
+ ld [hl],a
+ call LoadScreenTilesFromBuffer2 ; restore saved screen
+ ld a,[wWhichTrade]
+ 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,[wc02c]
+ 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
+; [wWhichTrade] should be initialized to 0
+; OUTPUT:
+; [wWhichTrade]: set to 1 if any pokemon were asleep
+WakeUpEntireParty: ; e1e5 (3:61e5)
+ 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 [wWhichTrade],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: ; e1fd (3:61fd)
+ 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: ; e206 (3:6206)
+ db 10,27 ; one space East of Snorlax
+ db 10,25 ; one space West of Snorlax
+ db $ff ; terminator
+
+PlayedFluteNoEffectText: ; e20b (3:620b)
+ TX_FAR _PlayedFluteNoEffectText
+ db "@"
+
+FluteWokeUpText: ; e210 (3:6210)
+ TX_FAR _FluteWokeUpText
+ db "@"
+
+PlayedFluteHadEffectText: ; e215 (3:6215)
+ TX_FAR _PlayedFluteHadEffectText
+ db $06
+ db $08
+ ld a,[W_ISINBATTLE]
+ and a
+ jr nz,.done
+; play out-of-battle pokeflute music
+ ld a,$ff
+ call PlaySound ; turn off music
+ ld a, (SFX_02_5e - SFX_Headers_02) / 3
+ ld c, BANK(SFX_02_5e)
+ call PlayMusic ; play music
+.musicWaitLoop ; wait for music to finish playing
+ ld a,[wc028]
+ cp a,$b8
+ jr z,.musicWaitLoop
+ call PlayDefaultMusic ; start playing normal music again
+.done
+ jp TextScriptEnd ; end text
+
+ItemUseCoinCase: ; e23a (3:623a)
+ ld a,[W_ISINBATTLE]
+ and a
+ jp nz,ItemUseNotTime
+ ld hl,CoinCaseNumCoinsText
+ jp PrintText
+
+CoinCaseNumCoinsText: ; e247 (3:6247)
+ TX_FAR _CoinCaseNumCoinsText
+ db "@"
+
+OldRodCode: ; e24c (3:624c)
+ call FishingInit
+ jp c, ItemUseNotTime
+ ld bc, (5 << 8) | MAGIKARP
+ ld a, $1 ; set bite
+ jr RodResponse ; 0xe257 $34
+
+GoodRodCode: ; e259 (3:6259)
+ 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,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"
+
+SuperRodCode: ; e283 (3:6283)
+ call FishingInit
+ jp c, ItemUseNotTime
+ call ReadSuperRodData ; 0xe8ea
+ ld a, e
+RodResponse: ; e28d (3:628d)
+ ld [wWhichTrade], a
+
+ dec a ; is there a bite?
+ jr nz, .next
+ ; if yes, store level and species data
+ ld a, 1
+ ld [W_MOVEMISSED], a
+ ld a, b ; level
+ ld [W_CURENEMYLVL], a
+ ld a, c ; species
+ ld [W_CUROPPONENT], a
+
+.next
+ ld hl, wWalkBikeSurfState
+ ld a, [hl] ; store the value in a
+ push af
+ push hl
+ ld [hl], 0
+ callba Func_707b6
+ 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: ; e2b4 (3:62b4)
+ ld a,[W_ISINBATTLE]
+ and a
+ jr z,.notInBattle
+ scf ; can't fish during battle
+ ret
+.notInBattle
+ call IsNextTileShoreOrWater
+ ret c
+ ld a,[wWalkBikeSurfState]
+ cp a,2 ; Surfing?
+ jr z,.surfing
+ call ItemUseReloadOverworldData
+ ld hl,ItemUseText00
+ call PrintText
+ ld a,(SFX_02_3e - SFX_Headers_02) / 3
+ call PlaySound ; play sound
+ ld c,80
+ call DelayFrames
+ and a
+ ret
+.surfing
+ scf ; can't fish when surfing
+ ret
+
+ItemUseOaksParcel: ; e2de (3:62de)
+ jp ItemUseNotYoursToUse
+
+ItemUseItemfinder: ; e2e1 (3:62e1)
+ ld a,[W_ISINBATTLE]
+ 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_02_4a - SFX_Headers_02) / 3
+ call PlaySoundWaitForCurrent ; play sound
+ ld a,(SFX_02_5a - SFX_Headers_02) / 3
+ call PlaySoundWaitForCurrent ; play sound
+ dec c
+ jr nz,.loop
+ ld hl,ItemfinderFoundItemText
+.printText
+ jp PrintText
+
+ItemfinderFoundItemText: ; e30d (3:630d)
+ TX_FAR _ItemfinderFoundItemText
+ db "@"
+
+ItemfinderFoundNothingText: ; e312 (3:6312)
+ TX_FAR _ItemfinderFoundNothingText
+ db "@"
+
+ItemUsePPUp: ; e317 (3:6317)
+ ld a,[W_ISINBATTLE]
+ and a
+ jp nz,ItemUseNotTime
+
+ItemUsePPRestore: ; e31e (3:631e)
+ ld a,[wWhichPokemon]
+ push af
+ ld a,[wcf91]
+ ld [wWhichTrade],a
+.chooseMon
+ xor a
+ ld [wUpdateSpritesEnabled],a
+ ld a,$01 ; item use party menu
+ ld [wd07d],a
+ call DisplayPartyMenu
+ jr nc,.chooseMove
+ jp .itemNotUsed
+.chooseMove
+ ld a,[wWhichTrade]
+ cp a,ELIXER
+ jp nc,.useElixir ; if Elixir or Max Elixir
+ ld a,$02
+ ld [wMoveMenuType],a
+ ld hl,RaisePPWhichTechniqueText
+ ld a,[wWhichTrade]
+ 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,44
+ call GetSelectedMoveOffset
+ push hl
+ ld a,[hl]
+ ld [wd11e],a
+ call GetMoveName
+ call CopyStringToCF4B ; copy name to wcf4b
+ pop hl
+ ld a,[wWhichTrade]
+ 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 hl,PPIncreasedText
+ call PrintText
+.done
+ pop af
+ ld [wWhichPokemon],a
+ call GBPalWhiteOut
+ call GoPAL_SET_CF1C
+ 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,44
+ call AddNTimes
+ ld de,wBattleMonPP
+ ld bc,4
+ call CopyData ; copy party data to in-battle data
+.skipUpdatingInBattleData
+ ld a,(SFX_02_3e - SFX_Headers_02) / 3
+ 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
+ ld [wcc49],a ; party pokemon
+ call GetMaxPP
+ ld hl,wPartyMon1Moves
+ ld bc,44
+ call GetSelectedMoveOffset
+ ld bc,21
+ add hl,bc ; hl now points to move's PP
+ ld a,[wd11e]
+ ld b,a ; b = max PP
+ ld a,[wWhichTrade]
+ 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,wWhichTrade
+ 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,44
+ 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 GoPAL_SET_CF1C
+ pop af
+ xor a
+ ld [wcd6a],a ; item use failed
+ ret
+
+RaisePPWhichTechniqueText: ; e45d (3:645d)
+ TX_FAR _RaisePPWhichTechniqueText
+ db "@"
+
+RestorePPWhichTechniqueText: ; e462 (3:6462)
+ TX_FAR _RestorePPWhichTechniqueText
+ db "@"
+
+PPMaxedOutText: ; e467 (3:6467)
+ TX_FAR _PPMaxedOutText
+ db "@"
+
+PPIncreasedText: ; e46c (3:646c)
+ TX_FAR _PPIncreasedText
+ db "@"
+
+PPRestoredText: ; e471 (3:6471)
+ TX_FAR _PPRestoredText
+ db "@"
+
+; for items that can't be used from the Item menu
+UnusableItem: ; e476 (3:6476)
+ jp ItemUseNotTime
+
+ItemUseTMHM: ; e479 (3:6479)
+ ld a,[W_ISINBATTLE]
+ 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
+ hlCoord 14, 7
+ ld bc,$080f
+ 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 [wcd6a],a ; item not used
+ ret
+.useMachine
+ ld a,[wWhichPokemon]
+ push af
+ ld a,[wcf91]
+ push af
+.chooseMon
+ ld hl,wcf4b
+ ld de,wd036
+ ld bc,14
+ call CopyData
+ ld a,$ff
+ ld [wUpdateSpritesEnabled],a
+ ld a,$03 ; teach TM/HM party menu
+ ld [wd07d],a
+ call DisplayPartyMenu
+ push af
+ ld hl,wd036
+ 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 GoPAL_SET_CF1C
+ 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_02_51 - SFX_Headers_02) / 3
+ call PlaySoundWaitForCurrent ; play sound
+ 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
+ pop af
+ ld [wcf91],a
+ pop af
+ ld [wWhichPokemon],a
+ ld a,b
+ and a
+ ret z
+ ld a,[wcf91]
+ call IsItemHM
+ ret c
+ jp RemoveUsedItem
+
+BootedUpTMText: ; e54f (3:654f)
+ TX_FAR _BootedUpTMText
+ db "@"
+
+BootedUpHMText: ; e554 (3:6554)
+ TX_FAR _BootedUpHMText
+ db "@"
+
+TeachMachineMoveText: ; e559 (3:6559)
+ TX_FAR _TeachMachineMoveText
+ db "@"
+
+MonCannotLearnMachineMoveText: ; e55e (3:655e)
+ TX_FAR _MonCannotLearnMachineMoveText
+ db "@"
+
+PrintItemUseTextAndRemoveItem: ; e563 (3:6563)
+ ld hl,ItemUseText00
+ call PrintText
+ ld a,(SFX_02_3e - SFX_Headers_02) / 3
+ call PlaySound ; play sound
+ call WaitForTextScrollButtonPress ; wait for button press
+
+RemoveUsedItem: ; e571 (3:6571)
+ ld hl,wNumBagItems
+ ld a,1 ; one item
+ ld [wcf96],a ; store quantity
+ jp RemoveItemFromInventory
+
+ItemUseNoEffect: ; e57c (3:657c)
+ ld hl,ItemUseNoEffectText
+ jr ItemUseFailed
+
+ItemUseNotTime: ; e581 (3:6581)
+ ld hl,ItemUseNotTimeText
+ jr ItemUseFailed
+
+ItemUseNotYoursToUse: ; e586 (3:6586)
+ ld hl,ItemUseNotYoursToUseText
+ jr ItemUseFailed
+
+ThrowBallAtTrainerMon: ; e58b (3:658b)
+ call GoPAL_SET_CF1C
+ call LoadScreenTilesFromBuffer1 ; restore saved screen
+ call Delay3
+ ld a,TOSS_ANIM
+ ld [W_ANIMATIONID],a
+ predef MoveAnimation ; do animation
+ ld hl,ThrowBallAtTrainerMonText1
+ call PrintText
+ ld hl,ThrowBallAtTrainerMonText2
+ call PrintText
+ jr RemoveUsedItem
+
+NoCyclingAllowedHere: ; e5ac (3:65ac)
+ ld hl,NoCyclingAllowedHereText
+ jr ItemUseFailed
+
+BoxFullCannotThrowBall: ; e5b1 (3:65b1)
+ ld hl,BoxFullCannotThrowBallText
+ jr ItemUseFailed
+
+SurfingAttemptFailed: ; e5b6 (3:65b6)
+ ld hl,NoSurfingHereText
+
+ItemUseFailed: ; e5b9 (3:65b9)
+ xor a
+ ld [wcd6a],a ; item use failed
+ jp PrintText
+
+ItemUseNotTimeText: ; e5c0 (3:65c0)
+ TX_FAR _ItemUseNotTimeText
+ db "@"
+
+ItemUseNotYoursToUseText: ; e5c5 (3:65c5)
+ TX_FAR _ItemUseNotYoursToUseText
+ db "@"
+
+ItemUseNoEffectText: ; e5ca (3:65ca)
+ TX_FAR _ItemUseNoEffectText
+ db "@"
+
+ThrowBallAtTrainerMonText1: ; e5cf (3:65cf)
+ TX_FAR _ThrowBallAtTrainerMonText1
+ db "@"
+
+ThrowBallAtTrainerMonText2: ; e5d4 (3:65d4)
+ TX_FAR _ThrowBallAtTrainerMonText2
+ db "@"
+
+NoCyclingAllowedHereText: ; e5d9 (3:65d9)
+ TX_FAR _NoCyclingAllowedHereText
+ db "@"
+
+NoSurfingHereText: ; e5de (3:65de)
+ TX_FAR _NoSurfingHereText
+ db "@"
+
+BoxFullCannotThrowBallText: ; e5e3 (3:65e3)
+ TX_FAR _BoxFullCannotThrowBallText
+ db "@"
+
+ItemUseText00: ; e5e8 (3:65e8)
+ TX_FAR _ItemUseText001
+ db $05
+ TX_FAR _ItemUseText002
+ db "@"
+
+GotOnBicycleText: ; e5f2 (3:65f2)
+ TX_FAR _GotOnBicycleText1
+ db $05
+ TX_FAR _GotOnBicycleText2
+ db "@"
+
+GotOffBicycleText: ; e5fc (3:65fc)
+ 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
+; [wd11e] = mode
+; 0: Pokemon Center healing
+; 1: using a PP Up
+; [wCurrentMenuItem] = index of move (when using a PP Up)
+RestoreBonusPP: ; e606 (3:6606)
+ ld hl,wPartyMon1Moves
+ ld bc,44
+ ld a,[wWhichPokemon]
+ call AddNTimes
+ push hl
+ ld de,wcd78 - 1
+ predef LoadMovePPs ; loads the normal max PP of each of the pokemon's moves to wcd78
+ pop hl
+ ld c,21
+ ld b,0
+ add hl,bc ; hl now points to move 1 PP
+ ld de,wcd78
+ 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,[wd11e]
+ 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
+; [wd11e] = max number of times to add bonus
+; set to 1 when using a PP Up, set to 255 otherwise
+AddBonusPP: ; e642 (3:6642)
+ 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,%00001111
+ 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,[wd11e]
+ dec a
+ jr z,.done
+ 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
+; [wcc49] = 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:
+; [wd11e] = max PP
+GetMaxPP: ; e677 (3:6677)
+ ld a,[wcc49]
+ 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,6
+ call AddNTimes
+ ld de,wcd6d
+ ld a,BANK(Moves)
+ call FarCopyData
+ ld de,wcd72
+ ld a,[de]
+ ld b,a ; b = normal max PP
+ pop hl
+ push bc
+ ld bc,21 ; PP offset if not player's in-battle pokemon data
+ ld a,[wcc49]
+ cp a,4 ; player's in-battle pokemon?
+ jr nz,.addPPOffset
+ ld bc,17 ; 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
+ ld [wd11e],a ; no limit on PP Up amount
+ call AddBonusPP ; add bonus PP from PP Ups
+ ld a,[hl]
+ and a,%00111111 ; mask out the PP Up count
+ ld [wd11e],a ; store max PP
+ ret
+
+GetSelectedMoveOffset: ; e6e3 (3:66e3)
+ ld a,[wWhichPokemon]
+ call AddNTimes
+
+GetSelectedMoveOffset2: ; e6e9 (3:66e9)
+ 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
+; [wcf96] = quantity to toss
+; OUTPUT:
+; clears carry flag if the item is tossed, sets carry flag if not
+TossItem_: ; e6f1 (3:66f1)
+ push hl
+ ld a,[wcf91]
+ call IsItemHM
+ pop hl
+ jr c,.tooImportantToToss
+ push hl
+ call IsKeyItem_
+ ld a,[wd124]
+ 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
+ hlCoord 14, 7
+ ld bc,$080f
+ ld a,TWO_OPTION_MENU
+ ld [wTextBoxID],a
+ call DisplayTextBoxID ; yes/no menu
+ ld a,[wd12e]
+ cp a,2
+ pop hl
+ scf
+ ret z
+; 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: ; e755 (3:6755)
+ TX_FAR _ThrewAwayItemText
+ db "@"
+
+IsItOKToTossItemText: ; e75a (3:675a)
+ TX_FAR _IsItOKToTossItemText
+ db "@"
+
+TooImportantToTossText: ; e75f (3:675f)
+ TX_FAR _TooImportantToTossText
+ db "@"
+
+; checks if an item is a key item
+; INPUT:
+; [wcf91] = item ID
+; OUTPUT:
+; [wd124] = result
+; 00: item is not key item
+; 01: item is key item
+IsKeyItem_: ; e764 (3:6764)
+ ld a,$01
+ ld [wd124],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,wHPBarMaxHP
+ ld bc,15 ; only 11 bytes are actually used
+ call CopyData
+ pop af
+ dec a
+ ld c,a
+ ld hl,wHPBarMaxHP
+ ld b,$02 ; test bit
+ predef FlagActionPredef ; bitfield operation function
+ ld a,c
+ and a
+ ret nz
+.checkIfItemIsHM
+ ld a,[wcf91]
+ call IsItemHM
+ ret c
+ xor a
+ ld [wd124],a
+ ret
+
+INCLUDE "data/key_items.asm"
+
+SendNewMonToBox: ; e7a4 (3:67a4)
+ ld de, W_NUMINBOX ; wda80
+ ld a, [de]
+ inc a
+ ld [de], a
+ ld a, [wcf91]
+ ld [wd0b5], a
+ ld c, a
+.asm_e7b1
+ inc de
+ ld a, [de]
+ ld b, a
+ ld a, c
+ ld c, b
+ ld [de], a
+ cp $ff
+ jr nz, .asm_e7b1
+ call GetMonHeader
+ ld hl, wBoxMonOT
+ ld bc, $b
+ ld a, [W_NUMINBOX] ; wda80
+ dec a
+ jr z, .asm_e7ee
+ dec a
+ call AddNTimes
+ push hl
+ ld bc, $b
+ add hl, bc
+ ld d, h
+ ld e, l
+ pop hl
+ ld a, [W_NUMINBOX] ; wda80
+ dec a
+ ld b, a
+.asm_e7db
+ push bc
+ push hl
+ ld bc, $b
+ call CopyData
+ pop hl
+ ld d, h
+ ld e, l
+ ld bc, $fff5
+ add hl, bc
+ pop bc
+ dec b
+ jr nz, .asm_e7db
+.asm_e7ee
+ ld hl, wPlayerName ; wd158
+ ld de, wBoxMonOT
+ ld bc, $b
+ call CopyData
+ ld a, [W_NUMINBOX] ; wda80
+ dec a
+ jr z, .asm_e82a
+ ld hl, wBoxMonNicks
+ ld bc, $b
+ dec a
+ call AddNTimes
+ push hl
+ ld bc, $b
+ add hl, bc
+ ld d, h
+ ld e, l
+ pop hl
+ ld a, [W_NUMINBOX] ; wda80
+ dec a
+ ld b, a
+.asm_e817
+ push bc
+ push hl
+ ld bc, $b
+ call CopyData
+ pop hl
+ ld d, h
+ ld e, l
+ ld bc, $fff5
+ add hl, bc
+ pop bc
+ dec b
+ jr nz, .asm_e817
+.asm_e82a
+ ld hl, wBoxMonNicks
+ ld a, $2
+ ld [wd07d], a
+ predef AskName
+ ld a, [W_NUMINBOX] ; wda80
+ dec a
+ jr z, .asm_e867
+ 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, [W_NUMINBOX] ; wda80
+ dec a
+ ld b, a
+.asm_e854
+ push bc
+ push hl
+ ld bc, wBoxMon2 - wBoxMon1
+ call CopyData
+ pop hl
+ ld d, h
+ ld e, l
+ ld bc, $ffdf
+ add hl, bc
+ pop bc
+ dec b
+ jr nz, .asm_e854
+.asm_e867
+ ld a, [wEnemyMonLevel] ; wEnemyMonLevel
+ ld [wEnemyMonBoxLevel], a
+ ld hl, wEnemyMon
+ ld de, wBoxMon1
+ ld bc, $c
+ call CopyData
+ ld hl, wPlayerID ; wPlayerID
+ ld a, [hli]
+ ld [de], a
+ inc de
+ ld a, [hl]
+ ld [de], a
+ inc de
+ push de
+ ld a, [W_CURENEMYLVL] ; W_CURENEMYLVL
+ ld d, a
+ callab CalcExperience
+ pop de
+ ld a, [H_NUMTOPRINT] ; $ff96 (aliases: H_MULTIPLICAND)
+ ld [de], a
+ inc de
+ ld a, [$ff97]
+ ld [de], a
+ inc de
+ ld a, [$ff98]
+ ld [de], a
+ inc de
+ xor a
+ ld b, $a
+.asm_e89f
+ ld [de], a
+ inc de
+ dec b
+ jr nz, .asm_e89f
+ ld hl, wEnemyMonDVs
+ ld a, [hli]
+ ld [de], a
+ inc de
+ ld a, [hli]
+ ld [de], a
+ ld hl, wEnemyMonPP ; wcffe
+ ld b, $4
+.asm_e8b1
+ ld a, [hli]
+ inc de
+ ld [de], a
+ dec b
+ jr nz, .asm_e8b1
+ 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: ; e8b8 (3:68b8)
+ ld a, [W_CURMAPTILESET]
+ ld hl, WaterTilesets
+ ld de,1
+ call IsInArray ; does the current map allow surfing?
+ ret nc ; if not, return
+ ld hl,WaterTile
+ ld a, [W_CURMAPTILESET]
+ 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
+
+ReadSuperRodData: ; e8ea (3:68ea)
+; return e = 2 if no fish on this map
+; return e = 1 if a bite, bc = level,species
+; return e = 0 if no bite
+ ld a, [W_CURMAP]
+ ld de, 3 ; each fishing group is three bytes wide
+ ld hl, SuperRodData
+ call IsInArray
+ jr c, .ReadFishingGroup
+ ld e, $2 ; $2 if no fishing groups found
+ ret
+
+.ReadFishingGroup ; 0xe8f6
+; hl points to the fishing group entry in the index
+ inc hl ; skip map id
+
+ ; read fishing group address
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+
+ ld b, [hl] ; how many mons in group
+ inc hl ; point to data
+ ld e, $0 ; no bite yet
+
+.RandomLoop ; 0xe90c
+ call Random
+ srl a
+ ret c ; 50% chance of no battle
+
+ and %11 ; 2-bit random number
+ cp b
+ jr nc, .RandomLoop ; if a is greater than the number of mons, regenerate
+
+ ; get the mon
+ add a
+ ld c, a
+ ld b, $0
+ add hl, bc
+ ld b, [hl] ; level
+ inc hl
+ ld c, [hl] ; species
+ ld e, $1 ; $1 if there's a bite
+ ret
+
+INCLUDE "data/super_rod.asm"
+
+; reloads map view and processes sprite data
+; for items that cause the overworld to be displayed
+ItemUseReloadOverworldData: ; e9c5 (3:69c5)
+ 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: ; e9cb (3:69cb)
+ 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: ; e9f0 (3:69f0)
+ 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