UseItem_: ld a, 1 ld [wActionResultOrTookBattleTurn], a ; initialise to success value ld a, [wcf91] ;contains item_ID cp 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: dw ItemUseBall ; MASTER_BALL dw ItemUseBall ; ULTRA_BALL dw ItemUseBall ; GREAT_BALL dw ItemUseBall ; POKE_BALL dw ItemUseTownMap ; TOWN_MAP dw ItemUseBicycle ; BICYCLE dw ItemUseSurfboard ; out-of-battle Surf effect dw ItemUseBall ; SAFARI_BALL dw ItemUsePokedex ; POKEDEX dw ItemUseEvoStone ; MOON_STONE dw ItemUseMedicine ; ANTIDOTE dw ItemUseMedicine ; BURN_HEAL dw ItemUseMedicine ; ICE_HEAL dw ItemUseMedicine ; AWAKENING dw ItemUseMedicine ; PARLYZ_HEAL dw ItemUseMedicine ; FULL_RESTORE dw ItemUseMedicine ; MAX_POTION dw ItemUseMedicine ; HYPER_POTION dw ItemUseMedicine ; SUPER_POTION dw ItemUseMedicine ; POTION dw ItemUseBait ; BOULDERBADGE dw ItemUseRock ; CASCADEBADGE dw UnusableItem ; THUNDERBADGE dw UnusableItem ; RAINBOWBADGE dw UnusableItem ; SOULBADGE dw UnusableItem ; MARSHBADGE dw UnusableItem ; VOLCANOBADGE dw UnusableItem ; EARTHBADGE dw ItemUseEscapeRope ; ESCAPE_ROPE dw ItemUseRepel ; REPEL dw UnusableItem ; OLD_AMBER dw ItemUseEvoStone ; FIRE_STONE dw ItemUseEvoStone ; THUNDER_STONE dw ItemUseEvoStone ; WATER_STONE dw ItemUseVitamin ; HP_UP dw ItemUseVitamin ; PROTEIN dw ItemUseVitamin ; IRON dw ItemUseVitamin ; CARBOS dw ItemUseVitamin ; CALCIUM dw ItemUseVitamin ; RARE_CANDY dw UnusableItem ; DOME_FOSSIL dw UnusableItem ; HELIX_FOSSIL dw UnusableItem ; SECRET_KEY dw UnusableItem dw UnusableItem ; BIKE_VOUCHER dw ItemUseXAccuracy ; X_ACCURACY dw ItemUseEvoStone ; LEAF_STONE dw ItemUseCardKey ; CARD_KEY dw UnusableItem ; NUGGET dw UnusableItem ; ??? PP_UP dw ItemUsePokedoll ; POKE_DOLL dw ItemUseMedicine ; FULL_HEAL dw ItemUseMedicine ; REVIVE dw ItemUseMedicine ; MAX_REVIVE dw ItemUseGuardSpec ; GUARD_SPEC dw ItemUseSuperRepel ; SUPER_REPL dw ItemUseMaxRepel ; MAX_REPEL dw ItemUseDireHit ; DIRE_HIT dw UnusableItem ; COIN dw ItemUseMedicine ; FRESH_WATER dw ItemUseMedicine ; SODA_POP dw ItemUseMedicine ; LEMONADE dw UnusableItem ; S_S_TICKET dw UnusableItem ; GOLD_TEETH dw ItemUseXStat ; X_ATTACK dw ItemUseXStat ; X_DEFEND dw ItemUseXStat ; X_SPEED dw ItemUseXStat ; X_SPECIAL dw ItemUseCoinCase ; COIN_CASE dw ItemUseOaksParcel ; OAKS_PARCEL dw ItemUseItemfinder ; ITEMFINDER dw UnusableItem ; SILPH_SCOPE dw ItemUsePokeflute ; POKE_FLUTE dw UnusableItem ; LIFT_KEY dw UnusableItem ; EXP_ALL dw ItemUseOldRod ; OLD_ROD dw ItemUseGoodRod ; GOOD_ROD dw ItemUseSuperRod ; SUPER_ROD dw ItemUsePPUp ; PP_UP (real one) dw ItemUsePPRestore ; ETHER dw ItemUsePPRestore ; MAX_ETHER dw ItemUsePPRestore ; ELIXER dw ItemUsePPRestore ; MAX_ELIXER ItemUseBall: ; Balls can't be used out of battle. ld a,[wIsInBattle] and a jp z,ItemUseNotTime ; Balls can't catch trainers' Pokémon. dec a jp nz,ThrowBallAtTrainerMon ; If this is for the old man battle, skip checking if the party & box are full. ld a,[wBattleType] cp BATTLE_TYPE_OLD_MAN jr z,.canUseBall cp BATTLE_TYPE_PIKACHU jr z,.canUseBall ld a,[wPartyCount] ; is party full? cp a,PARTY_LENGTH jr nz,.canUseBall ld a,[wNumInBox] ; is box full? cp a,MONS_PER_BOX jp z,BoxFullCannotThrowBall .canUseBall xor a ld [wCapturedMonSpecies],a ld a,[wBattleType] cp a,BATTLE_TYPE_SAFARI jr nz,.skipSafariZoneCode .safariZone ld hl,wNumSafariBalls dec [hl] ; remove a Safari Ball .skipSafariZoneCode call RunDefaultPaletteCommand ld a,$43 ; successful capture value ld [wPokeBallAnimData],a call LoadScreenTilesFromBuffer1 ld hl,ItemUseText00 call PrintText ; If the player is fighting an unidentified ghost, set the value that indicates ; the Pokémon can't be caught and skip the capture calculations. callab IsGhostBattle ld b,$10 ; can't be caught value jp z,.setAnimData ld a,[wBattleType] cp BATTLE_TYPE_OLD_MAN jr z,.oldManBattle cp BATTLE_TYPE_PIKACHU jr z,.oldManBattle ; pikachu battle technically old man battle jr .notOldManBattle .oldManBattle ld hl,wGrassRate ld de,wPlayerName ld bc,NAME_LENGTH call CopyData ; save the player's name in the Wild Monster data (part of the Cinnabar Island Missingno. glitch) ld a, [wBattleType] cp BATTLE_TYPE_OLD_MAN jp nz,.captured ld a,$1 ld [wCapturedMonSpecies], a CheckEvent EVENT_02F ld b, $63 jp nz,.setAnimData jp .captured .notOldManBattle ; If the player is fighting the ghost Marowak, set the value that indicates the ; Pokémon can't be caught and skip the capture calculations. ld a,[wCurMap] cp a,POKEMONTOWER_6 jr nz,.loop ld a,[wEnemyMonSpecies2] cp a,MAROWAK ld b,$10 ; can't be caught value jp z,.setAnimData ; Get the first random number. Let it be called Rand1. ; Rand1 must be within a certain range according the kind of ball being thrown. ; The ranges are as follows. ; Poké Ball: [0, 255] ; Great Ball: [0, 200] ; Ultra/Safari Ball: [0, 150] ; Loop until an acceptable number is found. .loop call Random ld b,a ; Get the item ID. ld hl,wcf91 .asm_d54a ld a,[hl] ; The Master Ball always succeeds. cp a,MASTER_BALL jp z,.captured ; Anything will do for the basic Poké Ball. cp a,POKE_BALL jr z,.checkForAilments ; If it's a Great/Ultra/Safari Ball and Rand1 is greater than 200, try again. ld a,200 cp b jr c,.loop ; Less than or equal to 200 is good enough for a Great Ball. ld a,[hl] cp a,GREAT_BALL jr z,.checkForAilments ; If it's an Ultra/Safari Ball and Rand1 is greater than 150, try again. ld a,150 cp b jr c,.loop .checkForAilments ; Pokémon can be caught more easily with a status ailment. ; Depending on the status ailment, a certain value will be subtracted from ; Rand1. Let this value be called Status. ; The larger Status is, the more easily the Pokémon can be caught. ; no status ailment: Status = 0 ; Burn/Paralysis/Poison: Status = 12 ; Freeze/Sleep: Status = 25 ; If Status is greater than Rand1, the Pokémon will be caught for sure. ld a,[wEnemyMonStatus] and a jr z,.skipAilmentValueSubtraction ; no ailments and a, 1 << FRZ | SLP ld c,12 jr z,.notFrozenOrAsleep ld c,25 .notFrozenOrAsleep ld a, b sub c jp c,.captured ld b,a .skipAilmentValueSubtraction push bc ; save (Rand1 - Status) ; Calculate MaxHP * 255. 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 ; Determine BallFactor. It's 8 for Great Balls and 12 for the others. ld a,[wcf91] cp GREAT_BALL ld a,12 jr nz,.skip1 ld a,8 .skip1 ; Note that the results of all division operations are floored. ; Calculate (MaxHP * 255) / BallFactor. ld [H_DIVISOR],a ld b,4 ; number of bytes in dividend call Divide ; Divide the enemy's current HP by 4. HP is not supposed to exceed 999 so ; the result should fit in a. If the division results in a quotient of 0, ; change it to 1. ld hl,wEnemyMonHP ld a,[hli] ld b,a ld a,[hl] srl b rr a srl b rr a and a jr nz,.skip2 inc a .skip2 ; Let W = ((MaxHP * 255) / BallFactor) / max(HP / 4, 1). Calculate W. ld [H_DIVISOR],a ld b,4 call Divide ; If W > 255, store 255 in [H_QUOTIENT + 3]. ; Let X = min(W, 255) = [H_QUOTIENT + 3]. ld a,[H_QUOTIENT + 2] and a jr z,.skip3 ld a,255 ld [H_QUOTIENT + 3],a .skip3 pop bc ; b = Rand1 - Status ; If Rand1 - Status > CatchRate, the ball fails to capture the Pokémon. ld a,[wEnemyMonCatchRate] cp b jr c,.failedToCapture ; If W > 255, the ball captures the Pokémon. ld a,[H_QUOTIENT + 2] and a jr nz,.captured call Random ; Let this random number be called Rand2. ; If Rand2 > X, the ball fails to capture the Pokémon. ld b,a ld a,[H_QUOTIENT + 3] cp b jr c,.failedToCapture .captured jr .skipShakeCalculations .failedToCapture ld a,[H_QUOTIENT + 3] ld [wPokeBallCaptureCalcTemp],a ; Save X. ; Calculate CatchRate * 100. xor a ld [H_MULTIPLICAND],a ld [H_MULTIPLICAND + 1],a ld a,[wEnemyMonCatchRate] ld [H_MULTIPLICAND + 2],a ld a,100 ld [H_MULTIPLIER],a call Multiply ; Determine BallFactor2. ; Poké Ball: BallFactor2 = 255 ; Great Ball: BallFactor2 = 200 ; Ultra/Safari Ball: BallFactor2 = 150 ld a,[wcf91] ld b,255 cp POKE_BALL jr z,.skip4 ld b,200 cp GREAT_BALL jr z,.skip4 ld b,150 cp ULTRA_BALL jr z,.skip4 .skip4 ; Let Y = (CatchRate * 100) / BallFactor2. Calculate Y. ld a,b ld [H_DIVISOR],a ld b,4 call Divide ; If Y > 255, there are 3 shakes. ; Note that this shouldn't be possible. ; The maximum value of Y is (255 * 100) / 150 = 170. ld a,[H_QUOTIENT + 2] and a ld b,$63 ; 3 shakes jr nz,.setAnimData ; Calculate X * Y. ld a,[wPokeBallCaptureCalcTemp] ld [H_MULTIPLIER],a call Multiply ; Calculate (X * Y) / 255. ld a,255 ld [H_DIVISOR],a ld b,4 call Divide ; Determine Status2. ; no status ailment: Status2 = 0 ; Burn/Paralysis/Poison: Status2 = 5 ; Freeze/Sleep: Status2 = 10 ld a,[wEnemyMonStatus] and a jr z,.skip5 and 1 << FRZ | SLP ld b,5 jr z,.addAilmentValue ld b,10 .addAilmentValue ; If the Pokémon has a status ailment, add Status2. ld a,[H_QUOTIENT + 3] add b ld [H_QUOTIENT + 3],a .skip5 ; Finally determine the number of shakes. ; Let Z = ((X * Y) / 255) + Status2 = [H_QUOTIENT + 3]. ; The number of shakes depend on the range Z is in. ; 0 ≤ Z < 10: 0 shakes (the ball misses) ; 10 ≤ Z < 30: 1 shake ; 30 ≤ Z < 70: 2 shakes ; 70 ≤ Z: 3 shakes ld a,[H_QUOTIENT + 3] cp a,10 ld b,$20 jr c,.setAnimData cp a,30 ld b,$61 jr c,.setAnimData cp a,70 ld b,$62 jr c,.setAnimData ld b,$63 .setAnimData ld a,b ld [wPokeBallAnimData],a .skipShakeCalculations ld c,20 call DelayFrames ; Do the animation. ld a,TOSS_ANIM ld [wAnimationID],a xor a ld [H_WHOSETURN], a ld [wAnimationType], a ld [wDamageMultipliers], a ld a, [wWhichPokemon] push af ld a, [wcf91] push af predef MoveAnimation pop af ld [wcf91], a pop af ld [wWhichPokemon],a ; Determine the message to display from the animation. ld a,[wPokeBallAnimData] cp a,$10 ld hl,ItemUseBallText00 jp z,.printMessage cp a,$20 ld hl,ItemUseBallText01 jp z,.printMessage cp a,$61 ld hl,ItemUseBallText02 jp z,.printMessage cp a,$62 ld hl,ItemUseBallText03 jp z,.printMessage cp a,$63 ld hl,ItemUseBallText04 jp z,.printMessage ; Save current HP. ld hl,wEnemyMonHP ld a,[hli] push af ld a,[hli] push af ; Save status ailment. inc hl ld a,[hl] push af push hl ; If the Pokémon is transformed, the Pokémon is assumed to be a Ditto. ; This is a bug because a wild Pokémon could have used Transform via ; Mirror Move even though the only wild Pokémon that knows Transform is Ditto. ld hl,wEnemyBattleStatus3 bit Transformed,[hl] jr z,.notTransformed ld a,DITTO ld [wEnemyMonSpecies2],a jr .skip6 .notTransformed ; If the Pokémon is not transformed, set the transformed bit and copy the ; DVs to wTransformedEnemyMonOriginalDVs so that LoadEnemyMonData won't generate ; new DVs. set Transformed,[hl] ld hl,wTransformedEnemyMonOriginalDVs ld a,[wEnemyMonDVs] ld [hli],a ld a,[wEnemyMonDVs + 1] ld [hl],a .skip6 ld a,[wcf91] push af ld a, [wEnemyMonSpecies2] ld [wcf91], a ld a, [wEnemyMonLevel] ld [wCurEnemyLVL], a callab LoadEnemyMonData pop af ld [wcf91], a pop hl pop af ld [hld], a dec hl pop af ld [hld], a pop af ld [hl],a ld a,[wEnemyMonSpecies] ld [wCapturedMonSpecies],a ld [wcf91],a ld [wd11e],a ld a,[wBattleType] cp BATTLE_TYPE_OLD_MAN ; is this the old man battle? jp z,.oldManCaughtMon ; if so, don't give the player the caught Pokémon cp BATTLE_TYPE_PIKACHU jr z,.oldManCaughtMon ; same with Pikachu battle ld hl,ItemUseBallText05 call PrintText ; Add the caught Pokémon to the Pokédex. predef IndexToPokedex ld a, [wd11e] dec a ld c, a ld b, FLAG_TEST ld hl, wPokedexOwned predef FlagActionPredef ld a, c push af ld a, [wd11e] dec a ld c, a ld b, FLAG_SET predef FlagActionPredef pop af and a ; was the Pokémon already in the Pokédex? jr nz,.skipShowingPokedexData ; if so, don't show the Pokédex data ld hl,ItemUseBallText06 call PrintText call ClearSprites ld a,[wEnemyMonSpecies] ld [wd11e],a predef ShowPokedexData .skipShowingPokedexData ld a, $1 ld [wd49c], a ld a, $85 ld [wPikachuMood], a ld a,[wPartyCount] cp PARTY_LENGTH ; is party full? jr z,.sendToBox xor a ; PLAYER_PARTY_DATA ld [wMonDataLocation], a call ClearSprites ld hl, .emptyString call PrintText call AddPartyMon jr .done .sendToBox call ClearSprites call SendNewMonToBox ld hl,ItemUseBallText07 CheckEvent EVENT_MET_BILL jr nz,.printTransferredToPCText ld hl,ItemUseBallText08 .printTransferredToPCText call PrintText jr .done .oldManCaughtMon ld hl,ItemUseBallText05 .printMessage call PrintText call ClearSprites .done ld a,[wBattleType] and a ; is this the old man battle? ret nz ; if so, don't remove a ball from the bag ; Remove a ball from the bag. ld hl,wNumBagItems inc a ld [wItemQuantity], a jp RemoveItemFromInventory .emptyString db "@" ItemUseBallText00: ;"It dodged the thrown ball!" ;"This pokemon can't be caught" TX_FAR _ItemUseBallText00 db "@" ItemUseBallText01: ;"You missed the pokemon!" TX_FAR _ItemUseBallText01 db "@" ItemUseBallText02: ;"Darn! The pokemon broke free!" TX_FAR _ItemUseBallText02 db "@" ItemUseBallText03: ;"Aww! It appeared to be caught!" TX_FAR _ItemUseBallText03 db "@" ItemUseBallText04: ;"Shoot! It was so close too!" TX_FAR _ItemUseBallText04 db "@" ItemUseBallText05: ;"All right! {MonName} was caught!" ;play sound TX_FAR _ItemUseBallText05 db $12, $06 db "@" ItemUseBallText07: ;"X was transferred to Bill's PC" TX_FAR _ItemUseBallText07 db "@" ItemUseBallText08: ;"X was transferred to someone's PC" TX_FAR _ItemUseBallText08 db "@" ItemUseBallText06: ;"New DEX data will be added..." ;play sound TX_FAR _ItemUseBallText06 db $13, $06 db "@" ItemUseTownMap: ld a, [wIsInBattle] and a jp nz, ItemUseNotTime jpba DisplayTownMap ItemUseBicycle: ld a, [wIsInBattle] and a jp nz, ItemUseNotTime ld a, [wWalkBikeSurfState] ld [wWalkBikeSurfStateCopy], a cp 2 ; is the player surfing? jp z, ItemUseNotTime dec a ; is player already bicycling? jr nz, .tryToGetOnBike .getOffBike call ItemUseReloadOverworldData xor a ld [wWalkBikeSurfState], a ; change player state to walking ld a, $00 ld [wPikachuSpawnState], a call PlayDefaultMusic ; play walking music ld hl, GotOffBicycleText jp PrintText .tryToGetOnBike call IsBikeRidingAllowed jp nc, NoCyclingAllowedHere call ItemUseReloadOverworldData xor a ; no keys pressed ld [hJoyHeld], a ; current joypad state ld a, $1 ld [wWalkBikeSurfState], a ; change player state to bicycling call PlayDefaultMusic ; play bike riding music xor a ld [wWalkBikeSurfState], a ld hl, GotOnBicycleText call PrintText ld a, $1 ld [wWalkBikeSurfState], a ret ; used for Surf out-of-battle effect ItemUseSurfboard: ld a, [wWalkBikeSurfState] ld [wWalkBikeSurfStateCopy], a cp 2 ; is the player already surfing? jr z, .tryToStopSurfing .tryToSurf call IsNextTileShoreOrWater jp nc, SurfingAttemptFailed ld hl, TilePairCollisionsWater call CheckForTilePairCollisions jp c, SurfingAttemptFailed .surf call .makePlayerMoveForward ld hl, wd730 set 7, [hl] ld a, 2 ld [wWalkBikeSurfState], a ; change player state to surfing call PlayDefaultMusic ; play surfing music ld hl, SurfingGotOnText jp PrintText .tryToStopSurfing xor a ld [hSpriteIndexOrTextID], a ld d, 16 ; talking range in pixels (normal range) call IsSpriteInFrontOfPlayer2 res 7, [hl] ld a, [hSpriteIndexOrTextID] and a ; is there a sprite in the way? jr nz, .cannotStopSurfing ld hl, TilePairCollisionsWater call CheckForTilePairCollisions jr c, .cannotStopSurfing ld a, [wTileInFrontOfPlayer] ld c, a call IsTilePassable jr nc, .stopSurfing .cannotStopSurfing ld hl, SurfingNoPlaceToGetOffText jp PrintText .stopSurfing call .makePlayerMoveForward ld a, $3 ld [wPikachuSpawnState], a ld hl, wPikachuOverworldStateFlags set 5, [hl] ld hl, wd730 set 7, [hl] xor a ld [wWalkBikeSurfState], a ; change player state to walking dec a ld [wJoyIgnore], a call PlayDefaultMusic ; play walking music call GBPalWhiteOutWithDelay3 jp LoadWalkingPlayerSpriteGraphics ; uses a simulated button press to make the player move forward .makePlayerMoveForward ld a, [wPlayerDirection] ; direction the player is going bit PLAYER_DIR_BIT_UP, a ld b, D_UP jr nz, .storeSimulatedButtonPress bit PLAYER_DIR_BIT_DOWN, a ld b, D_DOWN jr nz, .storeSimulatedButtonPress bit PLAYER_DIR_BIT_LEFT, a ld b, D_LEFT jr nz, .storeSimulatedButtonPress ld b, D_RIGHT .storeSimulatedButtonPress ld a, b ld [wSimulatedJoypadStatesEnd], a xor a ld [wWastedByteCD39], a inc a ld [wSimulatedJoypadStatesIndex], a ret SurfingGotOnText: TX_FAR _SurfingGotOnText db "@" SurfingNoPlaceToGetOffText: TX_FAR _SurfingNoPlaceToGetOffText db "@" ItemUsePokedex: predef_jump ShowPokedexMenu ItemUseEvoStone: ld a, [wIsInBattle] and a jp nz, ItemUseNotTime ld a, [wWhichPokemon] push af ld a, [wcf91] ld [wEvoStoneItemID], a push af ld a, EVO_STONE_PARTY_MENU ld [wPartyMenuTypeOrMessageID], a ld a, $ff ld [wUpdateSpritesEnabled], a call DisplayPartyMenu ld a, [wcf91] ld [wLoadedMon], a pop bc jr c, .canceledItemUse ld a, b ld [wcf91], a call Func_d85d jr nc, .noEffect callab IsThisPartymonStarterPikachu_Party jr nc, .notPlayerPikachu ld e, $1b callab PlayPikachuSoundClip ld a, [wWhichPokemon] ld hl, wPartyMonNicks call GetPartyMonName ld hl, RefusingText call PrintText ld a, $4 ld [wd49c], a ld a, $82 ld [wPikachuMood], a jr .canceledItemUse .notPlayerPikachu ld a, SFX_HEAL_AILMENT call PlaySoundWaitForCurrent call WaitForSoundToFinish ld a, $01 ld [wForceEvolution], a callab TryEvolvingMon ; try to evolve pokemon pop af ld [wWhichPokemon], a ld hl, wNumBagItems ld a, 1 ; remove 1 stone ld [wItemQuantity], a jp RemoveItemFromInventory .noEffect call ItemUseNoEffect .canceledItemUse xor a ld [wActionResultOrTookBattleTurn], a ; item not used pop af ret Func_d85d: ld hl, EvosMovesPointerTable ld a, [wLoadedMon] dec a ld c, a ld b, $0 add hl, bc add hl, bc ld de, wcd6d ld a, BANK(TryEvolvingMon) ld bc, $2 call FarCopyData ld hl, wcd6d ld a, [hli] ld h, [hl] ld l, a ld de, wcd6d ld a, BANK(TryEvolvingMon) ld bc, 13 call FarCopyData ld hl, wcd6d .loop ld a, [hli] and a jr z, .cannotEvolveWithUsedStone inc hl inc hl cp EV_ITEM jr nz, .loop dec hl dec hl ld b, [hl] ld a, [wcf91] inc hl inc hl inc hl cp b jr nz, .loop scf ret .cannotEvolveWithUsedStone and a ret RefusingText: TX_FAR _RefusingText db "@" ItemUseVitamin: ld a, [wIsInBattle] and a jp nz, ItemUseNotTime ItemUseMedicine: ld a, [wPartyCount] and a jp z, Func_e4bf ld a, [wWhichPokemon] push af ld a, [wcf91] push af ld a, USE_ITEM_PARTY_MENU ld [wPartyMenuTypeOrMessageID], a ld a, $ff ld [wUpdateSpritesEnabled], a ld a, [wPseudoItemID] and a ; using Softboiled? jr z, .notUsingSoftboiled ; if using softboiled call GoBackToPartyMenu jr .getPartyMonDataAddress .notUsingSoftboiled call DisplayPartyMenu .getPartyMonDataAddress jp c, .canceledItemUse ld hl, wPartyMons ld bc, wPartyMon2 - wPartyMon1 ld a, [wWhichPokemon] call AddNTimes ld a, [wWhichPokemon] ld [wUsedItemOnWhichPokemon], a ld d, a ld a, [wcf91] ld e, a ld [wd0b5], a pop af push af cp $28 jr nc, .asm_d906 push hl push de callabd_ModifyPikachuHappiness PIKAHAPPY_USEDITEM pop de pop hl .asm_d906 pop af ld [wcf91], a pop af ld [wWhichPokemon], a ld a, [wPseudoItemID] and a ; using Softboiled? jr z, .checkItemType ; if using softboiled ld a, [wWhichPokemon] cp d ; is the pokemon trying to use softboiled on itself? jr z, ItemUseMedicine ; if so, force another choice .checkItemType ld a, [wcf91] cp REVIVE jr nc, .healHP ; if it's a Revive or Max Revive cp FULL_HEAL jr z, .cureStatusAilment ; if it's a Full Heal cp HP_UP jp nc, .useVitamin ; if it's a vitamin or Rare Candy cp 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,wPartyMon1Status - wPartyMon1 add hl,bc ; hl now points to status ld a,[wcf91] lb bc, ANTIDOTE_MSG, 1 << PSN cp ANTIDOTE jr z, .checkMonStatus lb bc, BURN_HEAL_MSG, 1 << BRN cp BURN_HEAL jr z, .checkMonStatus lb bc, ICE_HEAL_MSG, 1 << FRZ cp ICE_HEAL jr z, .checkMonStatus lb bc, AWAKENING_MSG, SLP cp AWAKENING jr z, .checkMonStatus lb bc, PARALYZ_HEAL_MSG, 1 << PAR cp PARLYZ_HEAL jr z, .checkMonStatus lb bc, FULL_HEAL_MSG, $ff ; Full Heal .checkMonStatus ld a, [hl] ; pokemon's status and c ; does the pokemon have a status ailment the item can cure? jp z, .healingItemNoEffect ; if the pokemon has a status the item can heal xor a ld [hl], a ; remove the status ailment in the party data ld a, b ld [wPartyMenuTypeOrMessageID], a ; the message to display for the item used ld a, [wPlayerMonNumber] cp d ; is pokemon the item was used on active in battle? jp nz, .doneHealing ; if it is active in battle xor a ld [wBattleMonStatus], a ; remove the status ailment in the in-battle pokemon data push hl ld hl, wPlayerBattleStatus3 res BadlyPoisoned, [hl] ; heal Toxic status pop hl ld bc,wPartyMon1Stats - wPartyMon1Status add hl,bc ; hl now points to party stats ld de,wBattleMonStats ld bc,NUM_STATS * 2 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 REVIVE jr z, .updateInBattleFaintedData cp MAX_REVIVE jr z, .updateInBattleFaintedData jp .healingItemNoEffect .updateInBattleFaintedData ld a, [wWhichPokemon] push af ld a, [wUsedItemOnWhichPokemon] ld [wWhichPokemon], a push hl push de push bc callab Func_2fd6a pop bc pop de pop hl pop af ld [wWhichPokemon], a ld a, [wIsInBattle] and a jr z, .compareCurrentHPToMaxHP push hl push de push bc ld a, [wUsedItemOnWhichPokemon] ld c, a ld hl, wPartyFoughtCurrentEnemyFlags ld b, FLAG_TEST predef FlagActionPredef ld a, c and a jr z, .next ld a, [wUsedItemOnWhichPokemon] ld c, a ld hl, wPartyGainExpFlags ld b, FLAG_SET predef FlagActionPredef .next pop bc pop de pop hl jr .compareCurrentHPToMaxHP .notFainted ld a, [wcf91] cp REVIVE jp z, .healingItemNoEffect cp MAX_REVIVE jp z, .healingItemNoEffect .compareCurrentHPToMaxHP push hl push bc ld bc,wPartyMon1MaxHP - (wPartyMon1HP + 1) 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 FULL_RESTORE jp nz, .healingItemNoEffect inc hl inc hl ld a, [hld] ; status ailment and a ; does the pokemon have a status ailment? jp z, .healingItemNoEffect ld a, FULL_HEAL ld [wcf91], a dec hl dec hl dec hl jp .cureStatusAilment .notFullHP ; if the pokemon's current HP doesn't equal its max HP xor a ld [wLowHealthAlarm], a ;disable low health alarm ld [wChannelSoundIDs + CH4], a push hl push de ld bc,wPartyMon1MaxHP - (wPartyMon1HP + 1) add hl,bc ; hl now points to max HP ld a,[hli] ld [wHPBarMaxHP+1],a ld a,[hl] ld [wHPBarMaxHP],a ; max HP stored at wHPBarMaxHP (2 bytes, big-endian) ld a,[wPseudoItemID] and a ; using Softboiled? jp z, .notUsingSoftboiled2 ; if using softboiled ld hl, wHPBarMaxHP ld a, [hli] push af ld a, [hli] push af ld a, [hli] push af ld a, [hl] push af ld hl, wPartyMon1MaxHP ld a, [wWhichPokemon] ld bc, wPartyMon2 - wPartyMon1 call AddNTimes ld a, [hli] ld [wHPBarMaxHP + 1], a ld [H_DIVIDEND], a ld a, [hl] ld [wHPBarMaxHP], a ld [H_DIVIDEND + 1], a ld a, 5 ld [H_DIVISOR], a ld b, 2 ; number of bytes call Divide ; get 1/5 of max HP of pokemon that used Softboiled ld bc,(wPartyMon1HP + 1) - (wPartyMon1MaxHP + 1) add hl,bc ; hl now points to LSB of current HP of pokemon that used Softboiled ; subtract 1/5 of max HP from current HP of pokemon that used Softboiled ld a, [H_QUOTIENT + 3] push af ld b, a ld a, [hl] ld [wHPBarOldHP], a sub b ld [hld], a ld [wHPBarNewHP], a ld a, [H_QUOTIENT + 2] ld b, a ld a, [hl] ld [wHPBarOldHP+1], a sbc b ld [hl], a ld [wHPBarNewHP+1], a coord hl, 4, 1 ld a, [wWhichPokemon] ld bc, 2 * SCREEN_WIDTH call AddNTimes ; calculate coordinates of HP bar of pokemon that used Softboiled ld a, SFX_HEAL_HP call PlaySoundWaitForCurrent ld a, [hFlags_0xFFFA] set 0, a ld [hFlags_0xFFFA], a ld a, $02 ld [wHPBarType], a predef UpdateHPBar2 ; animate HP bar decrease of pokemon that used Softboiled ld a, [hFlags_0xFFFA] res 0, a ld [hFlags_0xFFFA], a pop af ld b, a ; store heal amount (1/5 of max HP) ld hl, wHPBarOldHP + 1 pop af ld [hld], a pop af ld [hld], a pop af ld [hld], a pop af ld [hl], a jr .addHealAmount .notUsingSoftboiled2 ld a, [wcf91] cp SODA_POP ld b, 60 ; Soda Pop heal amount jr z, .addHealAmount ld b, 80 ; Lemonade heal amount jr nc, .addHealAmount cp FRESH_WATER ld b, 50 ; Fresh Water heal amount jr z, .addHealAmount cp 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,(wPartyMon1MaxHP + 1) - (wPartyMon1HP + 1) 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 HYPER_POTION jr c, .setCurrentHPToMaxHp ; if using a Full Restore or Max Potion cp 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,wPartyMon1Status - (wPartyMon1MaxHP + 1) 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 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 * SCREEN_WIDTH inc d .calculateHPBarCoordsLoop add hl, bc dec d jr nz, .calculateHPBarCoordsLoop jr .doneHealing .healingItemNoEffect call ItemUseNoEffect jp .done .doneHealing ld a, [wPseudoItemID] and a ; using Softboiled? jr nz, .skipRemovingItem ; no item to remove if using Softboiled push hl call RemoveUsedItem pop hl .skipRemovingItem ld a, [wcf91] cp FULL_RESTORE jr c, .playStatusAilmentCuringSound cp FULL_HEAL jr z, .playStatusAilmentCuringSound ld a, SFX_HEAL_HP call PlaySoundWaitForCurrent ld a, [hFlags_0xFFFA] set 0, a ld [hFlags_0xFFFA], a ld a, $02 ld [wHPBarType], a predef UpdateHPBar2 ; animate the HP bar lengthening ld a, [hFlags_0xFFFA] res 0, a ld [hFlags_0xFFFA], a ld a, REVIVE_MSG ld [wPartyMenuTypeOrMessageID], a ld a, [wcf91] cp REVIVE jr z, .showHealingItemMessage cp MAX_REVIVE jr z, .showHealingItemMessage ld a, POTION_MSG ld [wPartyMenuTypeOrMessageID], a jr .showHealingItemMessage .playStatusAilmentCuringSound ld a, SFX_HEAL_AILMENT call PlaySoundWaitForCurrent .showHealingItemMessage xor a ld [H_AUTOBGTRANSFERENABLED], a call ClearScreen dec a ld [wUpdateSpritesEnabled], a call RedrawPartyMenu ; redraws the party menu and displays the message ld a, 1 ld [H_AUTOBGTRANSFERENABLED], a ld c, 50 call DelayFrames call WaitForTextScrollButtonPress jr .done .canceledItemUse xor a ld [wActionResultOrTookBattleTurn], a ; item use failed pop af pop af .done ld a, [wPseudoItemID] and a ; using Softboiled? ret nz ; if so, return call GBPalWhiteOut call z, RunDefaultPaletteCommand ld a, [wIsInBattle] and a ret nz jp ReloadMapData .useVitamin push hl ld a,[hl] ld [wd0b5],a ld [wd11e],a ld bc,wPartyMon1Level - wPartyMon1 add hl,bc ; hl now points to level ld a,[hl] ; a = level ld [wCurEnemyLVL],a ; store level call GetMonHeader push de ld a, d ld hl, wPartyMonNicks call GetPartyMonName pop de pop hl ld a, [wcf91] cp RARE_CANDY jp z, .useRareCandy push hl sub HP_UP add a ld bc,wPartyMon1HPExp - wPartyMon1 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 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 HP_UP - 1 ld c, a .statNameLoop ; loop to get the address of the name of the stat the vitamin increases dec c jr z, .gotStatName .statNameInnerLoop ld a, [hli] ld b, a ld a, $50 cp b jr nz, .statNameInnerLoop jr .statNameLoop .gotStatName ld de, wcf4b ld bc, 10 call CopyData ; copy the stat's name to wcf4b ld a, SFX_HEAL_AILMENT call PlaySound ld hl, VitaminStatRoseText call PrintText jp RemoveUsedItem .vitaminNoEffect pop hl ld hl, VitaminNoEffectText call PrintText jp GBPalWhiteOut .recalculateStats ld bc,wPartyMon1Stats - wPartyMon1 add hl,bc ld d,h ld e,l ; de now points to stats ld bc,(wPartyMon1Exp + 2) - wPartyMon1Stats add hl,bc ; hl now points to LSB of experience ld b,1 jp CalcStats ; recalculate stats .useRareCandy push hl ld bc,wPartyMon1Level - wPartyMon1 add hl,bc ; hl now points to level ld a,[hl] ; a = level cp a, MAX_LEVEL jr z,.vitaminNoEffect ; can't raise level above 100 inc a ld [hl], a ; store incremented level ld [wCurEnemyLVL], a push hl push de ld d, a callab CalcExperience ; calculate experience for next level and store it at $ff96 pop de pop hl ld bc,wPartyMon1Exp - wPartyMon1Level add hl,bc ; hl now points to MSB of experience ; update experience to minimum for new level ld a, [hExperience] ld [hli], a ld a, [hExperience + 1] ld [hli], a ld a, [hExperience + 2] ld [hl], a pop hl ld a, [wWhichPokemon] push af ld a, [wcf91] push af push de push hl ld bc,wPartyMon1MaxHP - wPartyMon1 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,(wPartyMon1MaxHP + 1) - wPartyMon1 add hl,bc ; hl now points to LSB of max HP 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,(wPartyMon1HP + 1) - wPartyMon1MaxHP add hl,de ; hl now points to LSB of current HP ld a,[hl] add c ld [hld], a ld a, [hl] adc b ld [hl], a ld a, RARE_CANDY_MSG ld [wPartyMenuTypeOrMessageID], a call RedrawPartyMenu pop de ld a, d ld [wWhichPokemon], a ld a, e ld [wd11e], a xor a ; PLAYER_PARTY_DATA ld [wMonDataLocation], a call LoadMonData ld d, $01 callab PrintStatsBox ; display new stats text box call WaitForTextScrollButtonPress ; wait for button press xor a ; PLAYER_PARTY_DATA ld [wMonDataLocation], a predef LearnMoveFromLevelUp ; learn level up move, if any xor a ld [wForceEvolution], a callabd_ModifyPikachuHappiness PIKAHAPPY_LEVELUP ld a, [wWhichPokemon] push af ld a, [wUsedItemOnWhichPokemon] ld [wWhichPokemon], a callab Func_2fd6a ; evolve pokemon, if appropriate pop af ld [wWhichPokemon], a callab TryEvolvingMon ld a, $01 ld [wUpdateSpritesEnabled], a pop af ld [wcf91], a pop af ld [wWhichPokemon], a jp RemoveUsedItem VitaminStatRoseText: TX_FAR _VitaminStatRoseText db "@" VitaminNoEffectText: TX_FAR _VitaminNoEffectText db "@" VitaminText: db "HEALTH@" db "ATTACK@" db "DEFENSE@" db "SPEED@" db "SPECIAL@" ItemUseBait: 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: 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: ld [wAnimationID], a xor a ld [wAnimationType], a ld [H_WHOSETURN], a ld [de], a ; zero escape factor (for bait), zero bait factor (for rock) .randomLoop ; loop until a random number less than 5 is generated call Random and 7 cp 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: TX_FAR _ThrewBaitText db "@" ThrewRockText: TX_FAR _ThrewRockText db "@" ; also used for Dig out-of-battle effect ItemUseEscapeRope: ld a, [wIsInBattle] and a jr nz, .notUsable ld a, [wCurMap] cp AGATHAS_ROOM jr z, .notUsable cp BILLS_HOUSE jr z, .notUsable cp POKEMON_FAN_CLUB jr z, .notUsable ld a, [wCurMapTileset] ld b, a ld hl, EscapeRopeTilesets .loop ld a, [hli] cp $ff jr z, .notUsable cp b jr nz, .loop ld hl, wd732 set 3, [hl] set 6, [hl] call Func_1510 ld hl, wd72e res 4, [hl] ResetEvent EVENT_IN_SAFARI_ZONE xor a ld [wNumSafariBalls], a ld [wSafariZoneEntranceCurScript], a inc a ld [wEscapedFromBattle], a ld [wActionResultOrTookBattleTurn], a ; item used ld a, [wPseudoItemID] and a ; using Dig? ret nz ; if so, return call ItemUseReloadOverworldData ld c, 30 call DelayFrames jp RemoveUsedItem .notUsable jp ItemUseNotTime EscapeRopeTilesets: db FOREST, CEMETERY, CAVERN, FACILITY, INTERIOR db $ff ; terminator ItemUseRepel: ld b, 100 ItemUseRepelCommon: ld a, [wIsInBattle] and a jp nz, ItemUseNotTime ld a, b ld [wRepelRemainingSteps], a jp PrintItemUseTextAndRemoveItem ; handles X Accuracy item ItemUseXAccuracy: ld a, [wIsInBattle] and a jp z, ItemUseNotTime ld hl, wPlayerBattleStatus2 set UsingXAccuracy, [hl] ; X Accuracy bit callabd_ModifyPikachuHappiness PIKAHAPPY_USEDXITEM jp PrintItemUseTextAndRemoveItem ; This function is bugged and never works. It always jumps to ItemUseNotTime. ; The Card Key is handled in a different way. ItemUseCardKey: xor a ld [wUnusedD71F], a call GetTileAndCoordsInFrontOfPlayer ld a,[GetTileAndCoordsInFrontOfPlayer] cp a,$18 jr nz,.next0 ld hl,CardKeyTable1 jr .next1 .next0 cp $24 jr nz, .next2 ld hl, CardKeyTable2 jr .next1 .next2 cp $5e jp nz, ItemUseNotTime ld hl, CardKeyTable3 .next1 ld a, [wCurMap] ld b, a .loop ld a, [hli] cp $ff jp z, ItemUseNotTime cp b jr nz, .nextEntry1 ld a, [hli] cp d jr nz, .nextEntry2 ld a, [hli] cp e jr nz, .nextEntry3 ld a, [hl] ld [wUnusedD71F], a jr .done .nextEntry1 inc hl .nextEntry2 inc hl .nextEntry3 inc hl jr .loop .done ld hl, ItemUseText00 call PrintText ld hl, wd728 set 7, [hl] ret ; These tables are probably supposed to be door locations in Silph Co., ; but they are unused. ; The reason there are 3 tables is unknown. ; Format: ; 00: Map ID ; 01: Y ; 02: X ; 03: ID? CardKeyTable1: 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: 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: db SILPH_CO_11F, $08, $09, $14 db SILPH_CO_11F, $09, $09, $15 db $ff ItemUsePokedoll: ld a, [wIsInBattle] dec a jp nz, ItemUseNotTime ld a, $01 ld [wEscapedFromBattle], a jp PrintItemUseTextAndRemoveItem ItemUseGuardSpec: ld a, [wIsInBattle] and a jp z, ItemUseNotTime ld a, [wWhichPokemon] push af ld a, [wPlayerMonNumber] ld [wWhichPokemon], a callabd_ModifyPikachuHappiness PIKAHAPPY_USEDXITEM pop af ld [wWhichPokemon], a ld hl, wPlayerBattleStatus2 set ProtectedByMist, [hl] ; Mist bit jp PrintItemUseTextAndRemoveItem ItemUseSuperRepel: ld b, 200 jp ItemUseRepelCommon ItemUseMaxRepel: ld b, 250 jp ItemUseRepelCommon ItemUseDireHit: ld a, [wIsInBattle] and a jp z, ItemUseNotTime ld a, [wWhichPokemon] push af ld a, [wPlayerMonNumber] ld [wWhichPokemon], a callabd_ModifyPikachuHappiness PIKAHAPPY_USEDXITEM pop af ld [wWhichPokemon], a ld hl, wPlayerBattleStatus2 set GettingPumped, [hl] ; Focus Energy bit jp PrintItemUseTextAndRemoveItem ItemUseXStat: ld a, [wIsInBattle] and a jr nz, .inBattle call ItemUseNotTime ld a, 2 ld [wActionResultOrTookBattleTurn], a ; item not used ret .inBattle ld hl, wPlayerMoveNum ld a, [hli] push af ; save [wPlayerMoveNum] ld a, [hl] push af ; save [wPlayerMoveEffect] push hl ld a, [wcf91] sub X_ATTACK - ATTACK_UP1_EFFECT ld [hl], a ; store player move effect call PrintItemUseTextAndRemoveItem ld a, XSTATITEM_ANIM ; X stat item animation ID ld [wPlayerMoveNum], a call LoadScreenTilesFromBuffer1 ; restore saved screen call Delay3 xor a ld [H_WHOSETURN], a ; set turn to player's turn callba StatModifierUpEffect ; do stat increase move ld a, [wWhichPokemon] push af ld a, [wPlayerMonNumber] ld [wWhichPokemon], a callabd_ModifyPikachuHappiness PIKAHAPPY_USEDXITEM pop af ld [wWhichPokemon], a pop hl pop af ld [hld], a ; restore [wPlayerMoveEffect] pop af ld [hl], a ; restore [wPlayerMoveNum] ret ItemUsePokeflute: ld a, [wIsInBattle] and a jr nz, .inBattle ; if not in battle call ItemUseReloadOverworldData ld a, [wCurMap] cp ROUTE_12 jr nz, .notRoute12 CheckEvent EVENT_BEAT_ROUTE12_SNORLAX jr nz, .noSnorlaxOrPikachuToWakeUp ; if the player hasn't beaten Route 12 Snorlax ld hl, Route12SnorlaxFluteCoords call ArePlayerCoordsInArray jr nc, .noSnorlaxOrPikachuToWakeUp ld hl, PlayedFluteHadEffectText call PrintText SetEvent EVENT_FIGHT_ROUTE12_SNORLAX ret .notRoute12 cp ROUTE_16 jr nz, .notRoute16 CheckEvent EVENT_BEAT_ROUTE16_SNORLAX jr nz, .noSnorlaxOrPikachuToWakeUp ; if the player hasn't beaten Route 16 Snorlax ld hl, Route16SnorlaxFluteCoords call ArePlayerCoordsInArray jr nc, .noSnorlaxOrPikachuToWakeUp ld hl, PlayedFluteHadEffectText call PrintText SetEvent EVENT_FIGHT_ROUTE16_SNORLAX ret .notRoute16 cp PEWTER_POKECENTER jr nz, .noSnorlaxOrPikachuToWakeUp call CheckPikachuFollowingPlayer jr z, .noSnorlaxOrPikachuToWakeUp callab IsPikachuRightNextToPlayer jr nc, .noSnorlaxOrPikachuToWakeUp ld hl, PlayedFluteHadEffectText call PrintText call ItemUseReloadOverworldData ldpikaemotion e, PikachuEmotion26 callab PlaySpecificPikachuEmotion ret .noSnorlaxOrPikachuToWakeUp ld hl, PlayedFluteNoEffectText jp PrintText .inBattle xor a ld [wWereAnyMonsAsleep], a ld b, $ff ^ SLP ld hl, wPartyMon1Status call WakeUpEntireParty ld a, [wIsInBattle] dec a ; is it a trainer battle? jr z, .skipWakingUpEnemyParty ; if it's a trainer battle ld hl, wEnemyMon1Status call WakeUpEntireParty .skipWakingUpEnemyParty ld hl, wBattleMonStatus ld a, [hl] and b ; remove Sleep status ld [hl], a ld hl, wEnemyMonStatus ld a, [hl] ld c, a and b ; remove Sleep status ld [hl], a ld a, c and SLP jr z, .asm_e063 ld a, $1 ld [wWereAnyMonsAsleep], a .asm_e063 call LoadScreenTilesFromBuffer2 ; restore saved screen ld a, [wWereAnyMonsAsleep] and a ; were any pokemon asleep before playing the flute? ld hl, PlayedFluteNoEffectText jp z, PrintText ; if no pokemon were asleep ; if some pokemon were asleep ld hl, PlayedFluteHadEffectText call PrintText ld a, [wLowHealthAlarm] and $80 jr nz, .skipMusic call WaitForSoundToFinish ; wait for sound to end callba Music_PokeFluteInBattle ; play in-battle pokeflute music .musicWaitLoop ; wait for music to finish playing ld a, [wChannelSoundIDs + CH6] and a ; music off? jr nz, .musicWaitLoop .skipMusic ld hl, FluteWokeUpText jp PrintText ; wakes up all party pokemon ; INPUT: ; hl must point to status of first pokemon in party (player's or enemy's) ; b must equal ~SLP ; [wWereAnyMonsAsleep] should be initialized to 0 ; OUTPUT: ; [wWereAnyMonsAsleep]: set to 1 if any pokemon were asleep WakeUpEntireParty: ld de, 44 ld c, 6 .loop ld a, [hl] push af and SLP ; is pokemon asleep? jr z, .notAsleep ld a, 1 ld [wWereAnyMonsAsleep], a ; indicate that a pokemon had to be woken up .notAsleep pop af and b ; remove Sleep status ld [hl], a add hl, de dec c jr nz, .loop ret ; Format: ; 00: Y ; 01: X Route12SnorlaxFluteCoords: 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: db 10, 27 ; one space East of Snorlax db 10, 25 ; one space West of Snorlax db $ff ; terminator PlayedFluteNoEffectText: TX_FAR _PlayedFluteNoEffectText db "@" FluteWokeUpText: TX_FAR _FluteWokeUpText db "@" PlayedFluteHadEffectText: TX_FAR _PlayedFluteHadEffectText db $06 TX_ASM ld a, [wIsInBattle] and a jr nz, .done ; play out-of-battle pokeflute music call StopAllMusic ; turn off music ld a, SFX_POKEFLUTE ld c, BANK(SFX_Pokeflute) call PlayMusic .musicWaitLoop ; wait for music to finish playing ld a, [wChannelSoundIDs + CH2] cp SFX_POKEFLUTE jr z, .musicWaitLoop call PlayDefaultMusic ; start playing normal music again .done jp TextScriptEnd ; end text ItemUseCoinCase: ld a, [wIsInBattle] and a jp nz, ItemUseNotTime ld hl, CoinCaseNumCoinsText jp PrintText CoinCaseNumCoinsText: TX_FAR _CoinCaseNumCoinsText db "@" ItemUseOldRod: call FishingInit jp c, ItemUseNotTime lb bc, 5, MAGIKARP ld a, $1 ; set bite jr RodResponse ItemUseGoodRod: call FishingInit jp c, ItemUseNotTime .RandomLoop call Random srl a jr c, .SetBite and %11 cp 2 jr nc, .RandomLoop ; choose which monster appears ld hl, GoodRodMons add a ld c, a ld b, 0 add hl, bc ld b, [hl] inc hl ld c, [hl] and a .SetBite ld a, 0 rla xor 1 jr RodResponse INCLUDE "data/good_rod.asm" ItemUseSuperRod: call FishingInit jp c, ItemUseNotTime callab ReadSuperRodData ld c, e ld b, d ld a, $2 ld [wRodResponse], a ld a, c and a ; are there fish in the map? jr z, DoNotGenerateFishingEncounter ; if not, do not generate an encounter ld a, $1 ld [wRodResponse], a call Random and $1 jr nz, RodResponse xor a ld [wRodResponse], a jr DoNotGenerateFishingEncounter RodResponse: ld [wRodResponse], a dec a ; is there a bite? jr nz, DoNotGenerateFishingEncounter ; if yes, store level and species data ld a, 1 ld [wMoveMissed], a ld a, b ; level ld [wCurEnemyLVL], a ld a, c ; species ld [wCurOpponent], a DoNotGenerateFishingEncounter: ld hl, wWalkBikeSurfState ld a, [hl] ; store the value in a push af push hl ld [hl], 0 callba FishingAnim pop hl pop af ld [hl], a ret ; checks if fishing is possible and if so, runs initialization code common to all rods ; unsets carry if fishing is possible, sets carry if not FishingInit: ld a, [wIsInBattle] and a jr z, .notInBattle scf ; can't fish during battle ret .notInBattle call IsNextTileShoreOrWater jr nc, .cannotFish ld a, [wWalkBikeSurfState] cp 2 ; Surfing? jr z, .cannotFish call ItemUseReloadOverworldData ld hl, ItemUseText00 call PrintText ld a, SFX_HEAL_AILMENT call PlaySound ld a, $2 ld [wd49c], a ld a, $81 ld [wPikachuMood], a ld c, 80 call DelayFrames and a ret .cannotFish scf ; can't fish when surfing ret ItemUseOaksParcel: jp ItemUseNotYoursToUse ItemUseItemfinder: ld a, [wIsInBattle] and a jp nz, ItemUseNotTime call ItemUseReloadOverworldData callba HiddenItemNear ; check for hidden items ld hl, ItemfinderFoundNothingText jr nc, .printText ; if no hidden items ld c, 4 .loop ld a, SFX_HEALING_MACHINE call PlaySoundWaitForCurrent ld a, SFX_PURCHASE call PlaySoundWaitForCurrent dec c jr nz, .loop ld hl, ItemfinderFoundItemText .printText jp PrintText ItemfinderFoundItemText: TX_FAR _ItemfinderFoundItemText db "@" ItemfinderFoundNothingText: TX_FAR _ItemfinderFoundNothingText db "@" ItemUsePPUp: ld a, [wIsInBattle] and a jp nz, ItemUseNotTime ItemUsePPRestore: ld a, [wWhichPokemon] push af ld a, [wcf91] ld [wPPRestoreItem], a .chooseMon xor a ld [wUpdateSpritesEnabled], a ld a, USE_ITEM_PARTY_MENU ld [wPartyMenuTypeOrMessageID], a call DisplayPartyMenu jr nc, .chooseMove jp .itemNotUsed .chooseMove ld a, [wIsInBattle] and a jr z, .usePPItem ld a, [wWhichPokemon] ld b, a ld a, [wPlayerMonNumber] cp b jr nz, .usePPItem ld a, [wPlayerBattleStatus3] bit Transformed, a jr z, .usePPItem call ItemUseNotTime jp .itemNotUsed .usePPItem ld a, [wPPRestoreItem] cp ELIXER jp nc, .useElixir ; if Elixir or Max Elixir ld a, $02 ld [wMoveMenuType], a ld hl, RaisePPWhichTechniqueText ld a, [wPPRestoreItem] cp ETHER ; is it a PP Up? jr c, .printWhichTechniqueMessage ; if so, print the raise PP message ld hl, RestorePPWhichTechniqueText ; otherwise, print the restore PP message .printWhichTechniqueMessage call PrintText xor a ld [wPlayerMoveListIndex], a callab MoveSelectionMenu ; move selection menu ld a, 0 ld [wPlayerMoveListIndex], a jr nz, .chooseMon ld hl, wPartyMon1Moves ld bc, wPartyMon2 - wPartyMon1 call GetSelectedMoveOffset push hl ld a, [hl] ld [wd11e], a call GetMoveName call CopyStringToCF4B ; copy name to wcf4b pop hl ld a, [wPPRestoreItem] cp ETHER jr nc, .useEther ; if Ether or Max Ether .usePPUp ld bc,wPartyMon1PP - wPartyMon1Moves 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 1 << 6 ; increase PP Up count by 1 ld [hl], a ld a, 1 ; 1 PP Up used ld [wd11e], a call RestoreBonusPP ; add the bonus PP to current PP ld a, SFX_HEAL_AILMENT call PlaySound ld hl, PPIncreasedText call PrintText .done pop af ld [wWhichPokemon], a call GBPalWhiteOut call RunDefaultPaletteCommand jp RemoveUsedItem .afterRestoringPP ; after using a (Max) Ether/Elixir ld a, [wWhichPokemon] ld b, a ld a, [wPlayerMonNumber] cp b ; is the pokemon whose PP was restored active in battle? jr nz, .skipUpdatingInBattleData ld hl, wPartyMon1PP ld bc, wPartyMon2 - wPartyMon1 call AddNTimes ld de, wBattleMonPP ld bc, 4 call CopyData ; copy party data to in-battle data .skipUpdatingInBattleData ld a, SFX_HEAL_AILMENT call PlaySound ld hl, PPRestoredText call PrintText jr .done .useEther call .restorePP jr nz, .afterRestoringPP jp .noEffect ; unsets zero flag if PP was restored, sets zero flag if not ; however, this is bugged for Max Ethers and Max Elixirs (see below) .restorePP xor a ; PLAYER_PARTY_DATA ld [wMonDataLocation], a call GetMaxPP ld hl, wPartyMon1Moves ld bc, wPartyMon2 - wPartyMon1 call GetSelectedMoveOffset ld bc, wPartyMon1PP - wPartyMon1Moves add hl, bc ; hl now points to move's PP ld a, [wMaxPP] ld b, a ld a, [wPPRestoreItem] cp MAX_ETHER jr z, .fullyRestorePP ld a, [hl] ; move PP and %00111111 ; lower 6 bit bits store current PP cp b ; does current PP equal max PP? ret z ; if so, return add 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 %11000000 ; PP Up counter bits add b ld [hl], a ret .fullyRestorePP ld a, [hl] ; move PP ; Note that this code has a bug. It doesn't mask out the upper two bits, which ; are used to count how many PP Ups have been used on the move. So, Max Ethers ; and Max Elixirs will not be detected as having no effect on a move with full ; PP if the move has had any PP Ups used on it. cp b ; does current PP equal max PP? ret z jr .storeNewAmount .useElixir ; decrement the item ID so that ELIXER becomes ETHER and MAX_ELIXER becomes MAX_ETHER ld hl, wPPRestoreItem dec [hl] dec [hl] xor a ld hl, wCurrentMenuItem ld [hli], a ld [hl], a ; zero the counter for number of moves that had their PP restored ld b, 4 ; loop through each move and restore PP .elixirLoop push bc ld hl, wPartyMon1Moves ld bc, wPartyMon2 - wPartyMon1 call GetSelectedMoveOffset ld a, [hl] and a ; does the current slot have a move? jr z, .nextMove call .restorePP jr z, .nextMove ; if some PP was restored ld hl, wTileBehindCursor ; counter for number of moves that had their PP restored inc [hl] .nextMove ld hl, wCurrentMenuItem inc [hl] pop bc dec b jr nz, .elixirLoop ld a, [wTileBehindCursor] and a ; did any moves have their PP restored? jp nz, .afterRestoringPP .noEffect call ItemUseNoEffect .itemNotUsed call GBPalWhiteOut call RunDefaultPaletteCommand pop af xor a ld [wActionResultOrTookBattleTurn], a ; item use failed ret RaisePPWhichTechniqueText: TX_FAR _RaisePPWhichTechniqueText db "@" RestorePPWhichTechniqueText: TX_FAR _RestorePPWhichTechniqueText db "@" PPMaxedOutText: TX_FAR _PPMaxedOutText db "@" PPIncreasedText: TX_FAR _PPIncreasedText db "@" PPRestoredText: TX_FAR _PPRestoredText db "@" ; for items that can't be used from the Item menu UnusableItem: jp ItemUseNotTime ItemUseTMHM: ld a, [wIsInBattle] and a jp nz, ItemUseNotTime ld a, [wcf91] sub TM_01 push af jr nc, .skipAdding add 55 ; if item is an HM, add 55 .skipAdding inc a ld [wd11e], a predef TMToMove ; get move ID from TM/HM ID ld a, [wd11e] ld [wMoveNum], a call GetMoveName call CopyStringToCF4B ; copy name to wcf4b pop af ld hl, BootedUpTMText jr nc, .printBootedUpMachineText ld hl, BootedUpHMText .printBootedUpMachineText call PrintText ld hl, TeachMachineMoveText call PrintText coord hl, 14, 7 lb bc, 8, 15 ld a, TWO_OPTION_MENU ld [wTextBoxID], a call DisplayTextBoxID ; yes/no menu ld a, [wCurrentMenuItem] and a jr z, .useMachine ld a, 2 ld [wActionResultOrTookBattleTurn], a ; item not used ret .useMachine ld a, [wWhichPokemon] push af ld a, [wcf91] push af .chooseMon ld hl, wcf4b ld de, wTempMoveNameBuffer ld bc, 14 call CopyData ; save the move name because DisplayPartyMenu will overwrite it ld a, $ff ld [wUpdateSpritesEnabled], a ld a, TMHM_PARTY_MENU ld [wPartyMenuTypeOrMessageID], a call DisplayPartyMenu push af ld hl, wTempMoveNameBuffer ld de, wcf4b ld bc, 14 call CopyData pop af jr nc, .checkIfAbleToLearnMove ; if the player canceled teaching the move pop af pop af call GBPalWhiteOutWithDelay3 call ClearSprites call RunDefaultPaletteCommand jp LoadScreenTilesFromBuffer1 ; restore saved screen .checkIfAbleToLearnMove predef CanLearnTM ; check if the pokemon can learn the move push bc ld a, [wWhichPokemon] ld hl, wPartyMonNicks call GetPartyMonName pop bc ld a, c and a ; can the pokemon learn the move? jr nz, .checkIfAlreadyLearnedMove ; if the pokemon can't learn the move ld a, SFX_DENIED call PlaySoundWaitForCurrent ld hl, MonCannotLearnMachineMoveText call PrintText jr .chooseMon .checkIfAlreadyLearnedMove callab CheckIfMoveIsKnown ; check if the pokemon already knows the move jr c, .chooseMon predef LearnMove ; teach move ld a, [wWhichPokemon] ld d, a pop af ld [wcf91], a pop af ld [wWhichPokemon], a ld a, b and a ret z ld a, [wWhichPokemon] push af ld a, d ld [wWhichPokemon], a callabd_ModifyPikachuHappiness PIKAHAPPY_USEDTMHM callab IsThisPartymonStarterPikachu_Party jr nc, .notTeachingThunderboltOrThunderToPikachu ld a, [wcf91] cp TM_24 ; are we teaching thunderbolt to the player pikachu? jr z, .teachingThunderboltOrThunderToPlayerPikachu cp TM_25 ; are we teaching thunder then? jr nz, .notTeachingThunderboltOrThunderToPikachu .teachingThunderboltOrThunderToPlayerPikachu ld a, $5 ld [wd49c], a ld a, $85 ld [wPikachuMood], a .notTeachingThunderboltOrThunderToPikachu pop af ld [wWhichPokemon], a ld a, [wcf91] call IsItemHM ret c jp RemoveUsedItem BootedUpTMText: TX_FAR _BootedUpTMText db "@" BootedUpHMText: TX_FAR _BootedUpHMText db "@" TeachMachineMoveText: TX_FAR _TeachMachineMoveText db "@" MonCannotLearnMachineMoveText: TX_FAR _MonCannotLearnMachineMoveText db "@" PrintItemUseTextAndRemoveItem: ld hl, ItemUseText00 call PrintText ld a, SFX_HEAL_AILMENT call PlaySound call WaitForTextScrollButtonPress ; wait for button press RemoveUsedItem: ld hl, wNumBagItems ld a, 1 ; one item ld [wItemQuantity], a jp RemoveItemFromInventory ItemUseNoEffect: ld hl, ItemUseNoEffectText jr ItemUseFailed ItemUseNotTime: ld hl, ItemUseNotTimeText jr ItemUseFailed ItemUseNotYoursToUse: ld hl, ItemUseNotYoursToUseText jr ItemUseFailed Func_e4bf: ld a, $2 ld [wActionResultOrTookBattleTurn], a ld hl, DontHavePokemonText jp PrintText ThrowBallAtTrainerMon: call RunDefaultPaletteCommand call LoadScreenTilesFromBuffer1 ; restore saved screen call Delay3 ld a, TOSS_ANIM ld [wAnimationID], a predef MoveAnimation ; do animation ld hl, ThrowBallAtTrainerMonText1 call PrintText ld hl, ThrowBallAtTrainerMonText2 call PrintText jr RemoveUsedItem NoCyclingAllowedHere: ld hl, NoCyclingAllowedHereText jr ItemUseFailed BoxFullCannotThrowBall: ld hl, BoxFullCannotThrowBallText jr ItemUseFailed SurfingAttemptFailed: ld hl, NoSurfingHereText ItemUseFailed: xor a ld [wActionResultOrTookBattleTurn], a ; item use failed jp PrintText ItemUseNotTimeText: TX_FAR _ItemUseNotTimeText db "@" ItemUseNotYoursToUseText: TX_FAR _ItemUseNotYoursToUseText db "@" ItemUseNoEffectText: TX_FAR _ItemUseNoEffectText db "@" ThrowBallAtTrainerMonText1: TX_FAR _ThrowBallAtTrainerMonText1 db "@" ThrowBallAtTrainerMonText2: TX_FAR _ThrowBallAtTrainerMonText2 db "@" NoCyclingAllowedHereText: TX_FAR _NoCyclingAllowedHereText db "@" NoSurfingHereText: TX_FAR _NoSurfingHereText db "@" BoxFullCannotThrowBallText: TX_FAR _BoxFullCannotThrowBallText db "@" DontHavePokemonText: TX_FAR _DontHavePokemonText db "@" ItemUseText00: TX_FAR _ItemUseText001 db $05 TX_FAR _ItemUseText002 db "@" GotOnBicycleText: TX_FAR _GotOnBicycleText1 db $05 TX_FAR _GotOnBicycleText2 db "@" GotOffBicycleText: TX_FAR _GotOffBicycleText1 db $05 TX_FAR _GotOffBicycleText2 db "@" ; restores bonus PP (from PP Ups) when healing at a pokemon center ; also, when a PP Up is used, it increases the current PP by one PP Up bonus ; INPUT: ; [wWhichPokemon] = index of pokemon in party ; [wCurrentMenuItem] = index of move (when using a PP Up) RestoreBonusPP: ld hl, wPartyMon1Moves ld bc, wPartyMon2 - wPartyMon1 ld a, [wWhichPokemon] call AddNTimes push hl ld de, wNormalMaxPPList - 1 predef LoadMovePPs ; loads the normal max PP of each of the pokemon's moves to wNormalMaxPPList pop hl ld c, wPartyMon1PP - wPartyMon1Moves ld b, 0 add hl, bc ; hl now points to move 1 PP ld de, wNormalMaxPPList ld b, 0 ; initialize move counter to zero ; loop through the pokemon's moves .loop inc b ld a, b cp 5 ; reached the end of the pokemon's moves? ret z ; if so, return ld a, [wUsingPPUp] dec a ; using a PP Up? jr nz, .skipMenuItemIDCheck ; if using a PP Up, check if this is the move it's being used on ld a, [wCurrentMenuItem] inc a cp b jr nz, .nextMove .skipMenuItemIDCheck ld a, [hl] and %11000000 ; have any PP Ups been used? call nz, AddBonusPP ; if so, add bonus PP .nextMove inc hl inc de jr .loop ; adds bonus PP from PP Ups to current PP ; 1/5 of normal max PP (capped at 7) is added for each PP Up ; INPUT: ; [de] = normal max PP ; [hl] = move PP AddBonusPP: 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 %1111 srl a srl a ld c, a ; c = number of PP Ups used .loop ld a, [H_QUOTIENT + 3] cp 8 ; is the amount greater than or equal to 8? jr c, .addAmount ld a, 7 ; cap the amount at 7 .addAmount add b ld b, a ld a, [wUsingPPUp] dec a ; is the player using a PP Up right now? jr z, .done ; if so, only add the bonus once dec c jr nz, .loop .done ld [hl], b pop bc ret ; gets max PP of a pokemon's move (including PP from PP Ups) ; INPUT: ; [wWhichPokemon] = index of pokemon within party/box ; [wMonDataLocation] = pokemon source ; 00: player's party ; 01: enemy's party ; 02: current box ; 03: daycare ; 04: player's in-battle pokemon ; [wCurrentMenuItem] = move index ; OUTPUT: ; [wMaxPP] = max PP GetMaxPP: ld a, [wMonDataLocation] and a ld hl, wPartyMon1Moves ld bc, wPartyMon2 - wPartyMon1 jr z, .sourceWithMultipleMon ld hl, wEnemyMon1Moves dec a jr z, .sourceWithMultipleMon ld hl, wBoxMon1Moves ld bc, wBoxMon2 - wBoxMon1 dec a jr z, .sourceWithMultipleMon ld hl, wDayCareMonMoves dec a jr z, .sourceWithOneMon ld hl, wBattleMonMoves ; player's in-battle pokemon .sourceWithOneMon call GetSelectedMoveOffset2 jr .next .sourceWithMultipleMon call GetSelectedMoveOffset .next ld a, [hl] dec a push hl ld hl, Moves ld bc, MoveEnd - Moves call AddNTimes ld de, wcd6d ld a, BANK(Moves) call FarCopyData ld de, wcd6d + 5 ; PP is byte 5 of move data ld a, [de] ld b, a ; b = normal max PP pop hl push bc ld bc, wPartyMon1PP - wPartyMon1Moves ; PP offset if not player's in-battle pokemon data ld a, [wMonDataLocation] cp 4 ; player's in-battle pokemon? jr nz, .addPPOffset ld bc, wBattleMonPP - wBattleMonMoves ; PP offset if player's in-battle pokemon data .addPPOffset add hl, bc ld a, [hl] ; a = current PP and %11000000 ; get PP Up count pop bc or b ; place normal max PP in 6 lower bits of a ld h, d ld l, e inc hl ; hl = wcd73 ld [hl], a xor a ; add the bonus for the existing PP Up count ld [wUsingPPUp], a call AddBonusPP ; add bonus PP from PP Ups ld a, [hl] and %00111111 ; mask out the PP Up count ld [wMaxPP], a ; store max PP ret GetSelectedMoveOffset: ld a, [wWhichPokemon] call AddNTimes GetSelectedMoveOffset2: ld a, [wCurrentMenuItem] ld c, a ld b, 0 add hl, bc ret ; confirms the item toss and then tosses the item ; INPUT: ; hl = address of inventory (either wNumBagItems or wNumBoxItems) ; [wcf91] = item ID ; [wWhichPokemon] = index of item within inventory ; [wItemQuantity] = quantity to toss ; OUTPUT: ; clears carry flag if the item is tossed, sets carry flag if not TossItem_: push hl ld a, [wcf91] call IsItemHM pop hl jr c, .tooImportantToToss push hl call IsKeyItem_ ld a, [wIsKeyItem] pop hl and a jr nz, .tooImportantToToss push hl ld a, [wcf91] ld [wd11e], a call GetItemName call CopyStringToCF4B ; copy name to wcf4b ld hl, IsItOKToTossItemText call PrintText coord hl, 14, 7 lb bc, 8, 15 ld a, TWO_OPTION_MENU ld [wTextBoxID], a call DisplayTextBoxID ; yes/no menu ld a, [wMenuExitMethod] cp CHOSE_SECOND_ITEM pop hl scf ret z ; return if the player chose No ; if the player chose Yes push hl ld a, [wWhichPokemon] call RemoveItemFromInventory ld a, [wcf91] ld [wd11e], a call GetItemName call CopyStringToCF4B ; copy name to wcf4b ld hl, ThrewAwayItemText call PrintText pop hl and a ret .tooImportantToToss push hl ld hl, TooImportantToTossText call PrintText pop hl scf ret ThrewAwayItemText: TX_FAR _ThrewAwayItemText db "@" IsItOKToTossItemText: TX_FAR _IsItOKToTossItemText db "@" TooImportantToTossText: TX_FAR _TooImportantToTossText db "@" ; checks if an item is a key item ; INPUT: ; [wcf91] = item ID ; OUTPUT: ; [wIsKeyItem] = result ; 00: item is not key item ; 01: item is key item IsKeyItem_: ld a, $01 ld [wIsKeyItem], a ld a, [wcf91] cp HM_01 ; is the item an HM or TM? jr nc, .checkIfItemIsHM ; if the item is not an HM or TM push af ld hl, KeyItemBitfield ld de, wBuffer ld bc, 15 ; only 11 bytes are actually used call CopyData pop af dec a ld c, a ld hl, wBuffer ld b, FLAG_TEST predef FlagActionPredef ld a, c and a ret nz .checkIfItemIsHM ld a, [wcf91] call IsItemHM ret c xor a ld [wIsKeyItem], a ret INCLUDE "data/key_items.asm" SendNewMonToBox: ld de, wNumInBox ld a, [de] inc a ld [de], a ld a, [wcf91] ld [wd0b5], a ld c, a .asm_e6f5 inc de ld a, [de] ld b, a ld a, c ld c, b ld [de], a cp $ff jr nz, .asm_e6f5 call GetMonHeader ld hl, wBoxMonOT ld bc, NAME_LENGTH ld a, [wNumInBox] dec a jr z, .asm_e732 dec a call AddNTimes push hl ld bc, NAME_LENGTH add hl, bc ld d, h ld e, l pop hl ld a, [wNumInBox] dec a ld b, a .asm_e71f push bc push hl ld bc, NAME_LENGTH call CopyData pop hl ld d, h ld e, l ld bc, -NAME_LENGTH add hl, bc pop bc dec b jr nz, .asm_e71f .asm_e732 ld hl, wPlayerName ld de, wBoxMonOT ld bc, NAME_LENGTH call CopyData ld a, [wNumInBox] dec a jr z, .asm_e76e ld hl, wBoxMonNicks ld bc, NAME_LENGTH dec a call AddNTimes push hl ld bc, NAME_LENGTH add hl, bc ld d, h ld e, l pop hl ld a, [wNumInBox] dec a ld b, a .asm_e75b push bc push hl ld bc, NAME_LENGTH call CopyData pop hl ld d, h ld e, l ld bc, -NAME_LENGTH add hl, bc pop bc dec b jr nz, .asm_e75b .asm_e76e ld hl, wBoxMonNicks ld a, NAME_MON_SCREEN ld [wNamingScreenType], a predef AskName ld a, [wNumInBox] dec a jr z, .asm_e7ab ld hl, wBoxMons ld bc, wBoxMon2 - wBoxMon1 dec a call AddNTimes push hl ld bc, wBoxMon2 - wBoxMon1 add hl, bc ld d, h ld e, l pop hl ld a, [wNumInBox] dec a ld b, a .asm_e798 push bc push hl ld bc, wBoxMon2 - wBoxMon1 call CopyData pop hl ld d, h ld e, l ld bc, wBoxMon1 - wBoxMon2 add hl, bc pop bc dec b jr nz, .asm_e798 .asm_e7ab ld a, [wEnemyMonLevel] ld [wEnemyMonBoxLevel], a ld hl, wEnemyMon ld de, wBoxMon1 ld bc, wEnemyMonDVs - wEnemyMon call CopyData ld hl, wPlayerID ld a, [hli] ld [de], a inc de ld a, [hl] ld [de], a inc de push de ld a, [wCurEnemyLVL] ld d, a callab CalcExperience pop de ld a, [hExperience] ld [de], a inc de ld a, [hExperience + 1] ld [de], a inc de ld a, [hExperience + 2] ld [de], a inc de xor a ld b, NUM_STATS * 2 .asm_e7e3 ld [de], a inc de dec b jr nz, .asm_e7e3 ld hl, wEnemyMonDVs ld a, [hli] ld [de], a inc de ld a, [hli] ld [de], a ld hl, wEnemyMonPP ld b, NUM_MOVES .asm_e7f5 ld a, [hli] inc de ld [de], a dec b jr nz, .asm_e7f5 ld a, [wcf91] cp KADABRA jr nz, .notKadabra ld a, $60 ; twistedspoon in gsc ld [wBoxMon1CatchRate], a .notKadabra ret ; checks if the tile in front of the player is a shore or water tile ; used for surfing and fishing ; unsets carry if it is, sets carry if not IsNextTileShoreOrWater: ld a, [wCurMapTileset] ld hl, WaterTilesets ld de, 1 call IsInArray ; does the current map allow surfing? ret nc ; if not, return ld hl, WaterTile ld a, [wCurMapTileset] cp SHIP_PORT ; Vermilion Dock tileset jr z, .skipShoreTiles ; if it's the Vermilion Dock tileset cp GYM ; eastern shore tile in Safari Zone jr z, .skipShoreTiles cp DOJO ; usual eastern shore tile jr z, .skipShoreTiles ld hl, ShoreTiles .skipShoreTiles ld a, [wTileInFrontOfPlayer] ld de, $1 call IsInArray ret ; tilesets with water WaterTilesets: db OVERWORLD, FOREST, DOJO, GYM, SHIP, SHIP_PORT, CAVERN, FACILITY, PLATEAU db $ff ; terminator ; shore tiles ShoreTiles: db $48, $32 WaterTile: db $14 db $ff ; terminator ; reloads map view and processes sprite data ; for items that cause the overworld to be displayed ItemUseReloadOverworldData: 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: 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: 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