diff options
Diffstat (limited to 'engine/items')
-rw-r--r-- | engine/items/buy_sell_toss.asm | 218 | ||||
-rwxr-xr-x | engine/items/item_effects.asm | 2891 | ||||
-rwxr-xr-x | engine/items/items.asm | 581 | ||||
-rw-r--r-- | engine/items/mart.asm | 811 | ||||
-rwxr-xr-x | engine/items/pack.asm | 1584 | ||||
-rw-r--r-- | engine/items/print_item_description.asm | 32 | ||||
-rw-r--r-- | engine/items/switch_items.asm | 272 | ||||
-rw-r--r-- | engine/items/tmhm.asm | 552 | ||||
-rwxr-xr-x | engine/items/tmhm2.asm | 46 | ||||
-rw-r--r-- | engine/items/update_item_description.asm | 13 |
10 files changed, 7000 insertions, 0 deletions
diff --git a/engine/items/buy_sell_toss.asm b/engine/items/buy_sell_toss.asm new file mode 100644 index 00000000..45c3dfcf --- /dev/null +++ b/engine/items/buy_sell_toss.asm @@ -0,0 +1,218 @@ +SelectQuantityToToss: + ld hl, TossItem_MenuHeader + call LoadMenuHeader + call Toss_Sell_Loop + ret + +SelectQuantityToBuy: + farcall GetItemPrice + ld a, d + ld [wBuffer1], a + ld a, e + ld [wBuffer2], a + ld hl, BuyItem_MenuHeader + call LoadMenuHeader + call Toss_Sell_Loop + ret + +SelectQuantityToSell: + farcall GetItemPrice + ld a, d + ld [wBuffer1], a + ld a, e + ld [wBuffer2], a + ld hl, SellItem_MenuHeader + call LoadMenuHeader + call Toss_Sell_Loop + ret + +Toss_Sell_Loop: + ld a, 1 + ld [wItemQuantityChangeBuffer], a +.loop + call BuySellToss_UpdateQuantityDisplay ; update display + call BuySellToss_InterpretJoypad ; joy action + jr nc, .loop + cp -1 + jr nz, .nope ; pressed B + scf + ret + +.nope + and a + ret + +BuySellToss_InterpretJoypad: + call JoyTextDelay_ForcehJoyDown ; get joypad + bit B_BUTTON_F, c + jr nz, .b + bit A_BUTTON_F, c + jr nz, .a + bit D_DOWN_F, c + jr nz, .down + bit D_UP_F, c + jr nz, .up + bit D_LEFT_F, c + jr nz, .left + bit D_RIGHT_F, c + jr nz, .right + and a + ret + +.b + ld a, -1 + scf + ret + +.a + ld a, 0 + scf + ret + +.down + ld hl, wItemQuantityChangeBuffer + dec [hl] + jr nz, .finish_down + ld a, [wItemQuantityBuffer] + ld [hl], a + +.finish_down + and a + ret + +.up + ld hl, wItemQuantityChangeBuffer + inc [hl] + ld a, [wItemQuantityBuffer] + cp [hl] + jr nc, .finish_up + ld [hl], 1 + +.finish_up + and a + ret + +.left + ld a, [wItemQuantityChangeBuffer] + sub 10 + jr c, .load_1 + jr z, .load_1 + jr .finish_left + +.load_1 + ld a, 1 + +.finish_left + ld [wItemQuantityChangeBuffer], a + and a + ret + +.right + ld a, [wItemQuantityChangeBuffer] + add 10 + ld b, a + ld a, [wItemQuantityBuffer] + cp b + jr nc, .finish_right + ld b, a + +.finish_right + ld a, b + ld [wItemQuantityChangeBuffer], a + and a + ret + +BuySellToss_UpdateQuantityDisplay: + call MenuBox + call MenuBoxCoord2Tile + ld de, SCREEN_WIDTH + 1 + add hl, de + ld [hl], "×" + inc hl + ld de, wItemQuantityChangeBuffer + lb bc, PRINTNUM_LEADINGZEROS | 1, 2 + call PrintNum + ld a, [wMenuDataPointer] + ld e, a + ld a, [wMenuDataPointer + 1] + ld d, a + push de + ret + +ret_24ff3: + ret + +DisplayPurchasePrice: + call BuySell_MultiplyPrice + call BuySell_DisplaySubtotal + ret + +DisplaySellingPrice: + call BuySell_MultiplyPrice + call Sell_HalvePrice + call BuySell_DisplaySubtotal + ret + +BuySell_MultiplyPrice: + xor a + ldh [hMultiplicand + 0], a + ld a, [wBuffer1] + ldh [hMultiplicand + 1], a + ld a, [wBuffer2] + ldh [hMultiplicand + 2], a + ld a, [wItemQuantityChangeBuffer] + ldh [hMultiplier], a + push hl + call Multiply + pop hl + ret + +Sell_HalvePrice: + push hl + ld hl, hProduct + 1 + ld a, [hl] + srl a + ld [hli], a + ld a, [hl] + rra + ld [hli], a + ld a, [hl] + rra + ld [hl], a + pop hl + ret + +BuySell_DisplaySubtotal: + push hl + ld hl, hMoneyTemp + ldh a, [hProduct + 1] + ld [hli], a + ldh a, [hProduct + 2] + ld [hli], a + ldh a, [hProduct + 3] + ld [hl], a + pop hl + inc hl + ld de, hMoneyTemp + lb bc, PRINTNUM_MONEY | 3, 6 + call PrintNum + call WaitBGMap + ret + +TossItem_MenuHeader: + db MENU_BACKUP_TILES ; flags + menu_coords 15, 9, SCREEN_WIDTH - 1, TEXTBOX_Y - 1 + dw ret_24ff3 + db 0 ; default option + +BuyItem_MenuHeader: + db MENU_BACKUP_TILES ; flags + menu_coords 7, 15, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1 + dw DisplayPurchasePrice + db -1 ; default option + +SellItem_MenuHeader: + db MENU_BACKUP_TILES ; flags + menu_coords 7, 15, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1 + dw DisplaySellingPrice + db 0 ; default option diff --git a/engine/items/item_effects.asm b/engine/items/item_effects.asm new file mode 100755 index 00000000..35a7cd6c --- /dev/null +++ b/engine/items/item_effects.asm @@ -0,0 +1,2891 @@ +_DoItemEffect:: + ld a, [wCurItem] + ld [wNamedObjectIndexBuffer], a + call GetItemName + call CopyName1 + ld a, 1 + ld [wItemEffectSucceeded], a + ld a, [wCurItem] + dec a + ld hl, ItemEffects + rst JumpTable + ret + +ItemEffects: +; entries correspond to item ids + dw PokeBallEffect ; MASTER_BALL + dw PokeBallEffect ; ULTRA_BALL + dw NoEffect ; BRIGHTPOWDER + dw PokeBallEffect ; GREAT_BALL + dw PokeBallEffect ; POKE_BALL + dw TownMapEffect ; TOWN_MAP + dw BicycleEffect ; BICYCLE + dw EvoStoneEffect ; MOON_STONE + dw StatusHealingEffect ; ANTIDOTE + dw StatusHealingEffect ; BURN_HEAL + dw StatusHealingEffect ; ICE_HEAL + dw StatusHealingEffect ; AWAKENING + dw StatusHealingEffect ; PARLYZ_HEAL + dw FullRestoreEffect ; FULL_RESTORE + dw RestoreHPEffect ; MAX_POTION + dw RestoreHPEffect ; HYPER_POTION + dw RestoreHPEffect ; SUPER_POTION + dw RestoreHPEffect ; POTION + dw EscapeRopeEffect ; ESCAPE_ROPE + dw RepelEffect ; REPEL + dw RestorePPEffect ; MAX_ELIXER + dw EvoStoneEffect ; FIRE_STONE + dw EvoStoneEffect ; THUNDERSTONE + dw EvoStoneEffect ; WATER_STONE + dw NoEffect ; ITEM_19 + dw VitaminEffect ; HP_UP + dw VitaminEffect ; PROTEIN + dw VitaminEffect ; IRON + dw VitaminEffect ; CARBOS + dw NoEffect ; LUCKY_PUNCH + dw VitaminEffect ; CALCIUM + dw RareCandyEffect ; RARE_CANDY + dw XAccuracyEffect ; X_ACCURACY + dw EvoStoneEffect ; LEAF_STONE + dw NoEffect ; METAL_POWDER + dw NoEffect ; NUGGET + dw PokeDollEffect ; POKE_DOLL + dw StatusHealingEffect ; FULL_HEAL + dw ReviveEffect ; REVIVE + dw ReviveEffect ; MAX_REVIVE + dw GuardSpecEffect ; GUARD_SPEC + dw SuperRepelEffect ; SUPER_REPEL + dw MaxRepelEffect ; MAX_REPEL + dw DireHitEffect ; DIRE_HIT + dw NoEffect ; ITEM_2D + dw RestoreHPEffect ; FRESH_WATER + dw RestoreHPEffect ; SODA_POP + dw RestoreHPEffect ; LEMONADE + dw XItemEffect ; X_ATTACK + dw NoEffect ; ITEM_32 + dw XItemEffect ; X_DEFEND + dw XItemEffect ; X_SPEED + dw XItemEffect ; X_SPECIAL + dw CoinCaseEffect ; COIN_CASE + dw ItemfinderEffect ; ITEMFINDER + dw PokeFluteEffect ; POKE_FLUTE + dw NoEffect ; EXP_SHARE + dw OldRodEffect ; OLD_ROD + dw GoodRodEffect ; GOOD_ROD + dw NoEffect ; SILVER_LEAF + dw SuperRodEffect ; SUPER_ROD + dw RestorePPEffect ; PP_UP + dw RestorePPEffect ; ETHER + dw RestorePPEffect ; MAX_ETHER + dw RestorePPEffect ; ELIXER + dw NoEffect ; RED_SCALE + dw NoEffect ; SECRETPOTION + dw NoEffect ; S_S_TICKET + dw NoEffect ; MYSTERY_EGG + dw NoEffect ; ITEM_46 + dw NoEffect ; SILVER_WING + dw RestoreHPEffect ; MOOMOO_MILK + dw NoEffect ; QUICK_CLAW + dw StatusHealingEffect ; PSNCUREBERRY + dw NoEffect ; GOLD_LEAF + dw NoEffect ; SOFT_SAND + dw NoEffect ; SHARP_BEAK + dw StatusHealingEffect ; PRZCUREBERRY + dw StatusHealingEffect ; BURNT_BERRY + dw StatusHealingEffect ; ICE_BERRY + dw NoEffect ; POISON_BARB + dw NoEffect ; KINGS_ROCK + dw BitterBerryEffect ; BITTER_BERRY + dw StatusHealingEffect ; MINT_BERRY + dw NoEffect ; RED_APRICORN + dw NoEffect ; TINYMUSHROOM + dw NoEffect ; BIG_MUSHROOM + dw NoEffect ; SILVERPOWDER + dw NoEffect ; BLU_APRICORN + dw NoEffect ; ITEM_5A + dw NoEffect ; AMULET_COIN + dw NoEffect ; YLW_APRICORN + dw NoEffect ; GRN_APRICORN + dw NoEffect ; CLEANSE_TAG + dw NoEffect ; MYSTIC_WATER + dw NoEffect ; TWISTEDSPOON + dw NoEffect ; WHT_APRICORN + dw NoEffect ; BLACKBELT_I + dw NoEffect ; BLK_APRICORN + dw NoEffect ; ITEM_64 + dw NoEffect ; PNK_APRICORN + dw NoEffect ; BLACKGLASSES + dw NoEffect ; SLOWPOKETAIL + dw NoEffect ; PINK_BOW + dw NoEffect ; STICK + dw NoEffect ; SMOKE_BALL + dw NoEffect ; NEVERMELTICE + dw NoEffect ; MAGNET + dw StatusHealingEffect ; MIRACLEBERRY + dw NoEffect ; PEARL + dw NoEffect ; BIG_PEARL + dw NoEffect ; EVERSTONE + dw NoEffect ; SPELL_TAG + dw RestoreHPEffect ; RAGECANDYBAR + dw NoEffect ; ITEM_73 + dw NoEffect ; ITEM_74 + dw NoEffect ; MIRACLE_SEED + dw NoEffect ; THICK_CLUB + dw NoEffect ; FOCUS_BAND + dw NoEffect ; ITEM_78 + dw EnergypowderEffect ; ENERGYPOWDER + dw EnergyRootEffect ; ENERGY_ROOT + dw HealPowderEffect ; HEAL_POWDER + dw RevivalHerbEffect ; REVIVAL_HERB + dw NoEffect ; HARD_STONE + dw NoEffect ; LUCKY_EGG + dw CardKeyEffect ; CARD_KEY + dw NoEffect ; MACHINE_PART + dw NoEffect ; ITEM_81 + dw NoEffect ; LOST_ITEM + dw NoEffect ; STARDUST + dw NoEffect ; STAR_PIECE + dw BasementKeyEffect ; BASEMENT_KEY + dw NoEffect ; PASS + dw NoEffect ; ITEM_87 + dw NoEffect ; ITEM_88 + dw NoEffect ; ITEM_89 + dw NoEffect ; CHARCOAL + dw RestoreHPEffect ; BERRY_JUICE + dw NoEffect ; SCOPE_LENS + dw NoEffect ; ITEM_8D + dw NoEffect ; ITEM_8E + dw NoEffect ; METAL_COAT + dw NoEffect ; DRAGON_FANG + dw NoEffect ; ITEM_91 + dw NoEffect ; LEFTOVERS + dw NoEffect ; ITEM_93 + dw NoEffect ; ITEM_94 + dw NoEffect ; ITEM_95 + dw RestorePPEffect ; MYSTERYBERRY + dw NoEffect ; DRAGON_SCALE + dw NoEffect ; BERSERK_GENE + dw NoEffect ; ITEM_99 + dw NoEffect ; ITEM_9A + dw NoEffect ; ITEM_9B + dw SacredAshEffect ; SACRED_ASH + dw PokeBallEffect ; HEAVY_BALL + dw NoEffect ; FLOWER_MAIL + dw PokeBallEffect ; LEVEL_BALL + dw PokeBallEffect ; LURE_BALL + dw PokeBallEffect ; FAST_BALL + dw NoEffect ; ITEM_A2 + dw NoEffect ; LIGHT_BALL + dw PokeBallEffect ; FRIEND_BALL + dw PokeBallEffect ; MOON_BALL + dw PokeBallEffect ; LOVE_BALL + dw NormalBoxEffect ; NORMAL_BOX + dw GorgeousBoxEffect ; GORGEOUS_BOX + dw EvoStoneEffect ; SUN_STONE + dw NoEffect ; POLKADOT_BOW + dw NoEffect ; ITEM_AB + dw NoEffect ; UP_GRADE + dw RestoreHPEffect ; BERRY + dw RestoreHPEffect ; GOLD_BERRY + dw SquirtbottleEffect ; SQUIRTBOTTLE + dw NoEffect ; ITEM_B0 + dw PokeBallEffect ; PARK_BALL + dw NoEffect ; RAINBOW_WING + dw NoEffect ; ITEM_B3 + +PokeBallEffect: + ld a, [wBattleMode] + dec a + jp nz, UseBallInTrainerBattle + + ld a, [wPartyCount] + cp PARTY_LENGTH + jr nz, .room_in_party + + ld a, BANK(sBoxCount) + call OpenSRAM + ld a, [sBoxCount] + cp MONS_PER_BOX + call CloseSRAM + jp z, Ball_BoxIsFullMessage + +.room_in_party + xor a + ld [wWildMon], a + ld a, [wCurItem] + cp PARK_BALL + call nz, ReturnToBattle_UseBall + + ld hl, wOptions + res NO_TEXT_SCROLL, [hl] + ld hl, ItemUsedText + call PrintText + + ld a, [wEnemyMonCatchRate] + ld b, a + ld a, [wBattleType] + cp BATTLETYPE_TUTORIAL + jp z, .catch_without_fail + ld a, [wCurItem] + cp MASTER_BALL + jp z, .catch_without_fail + ld a, [wCurItem] + ld c, a + ld hl, BallMultiplierFunctionTable + +.get_multiplier_loop + ld a, [hli] + cp $ff + jr z, .skip_or_return_from_ball_fn + cp c + jr z, .call_ball_function + inc hl + inc hl + jr .get_multiplier_loop + +.call_ball_function + ld a, [hli] + ld h, [hl] + ld l, a + ld de, .skip_or_return_from_ball_fn + push de + jp hl + +.skip_or_return_from_ball_fn + ld a, [wCurItem] + cp LEVEL_BALL + ld a, b + jp z, .skip_hp_calc + + ld a, b + ldh [hMultiplicand + 2], a + + ld hl, wEnemyMonHP + ld b, [hl] + inc hl + ld c, [hl] + inc hl + ld d, [hl] + inc hl + ld e, [hl] + sla c + rl b + + ld h, d + ld l, e + add hl, de + add hl, de + ld d, h + ld e, l + ld a, d + and a + jr z, .okay_1 + + srl d + rr e + srl d + rr e + srl b + rr c + srl b + rr c + + ld a, c + and a + jr nz, .okay_1 + ld c, $1 +.okay_1 + ld b, e + + push bc + ld a, b + sub c + ldh [hMultiplier], a + xor a + ldh [hDividend + 0], a + ldh [hMultiplicand + 0], a + ldh [hMultiplicand + 1], a + call Multiply + pop bc + + ld a, b + ldh [hDivisor], a + ld b, 4 + call Divide + + ldh a, [hQuotient + 3] + and a + jr nz, .statuscheck + ld a, 1 +.statuscheck +; This routine is buggy. It was intended that SLP and FRZ provide a higher +; catch rate than BRN/PSN/PAR, which in turn provide a higher catch rate than +; no status effect at all. But instead, it makes BRN/PSN/PAR provide no +; benefit. +; Uncomment the line below to fix this. + ld b, a + ld a, [wEnemyMonStatus] + and 1 << FRZ | SLP + ld c, 10 + jr nz, .addstatus + ; ld a, [wEnemyMonStatus] + and a + ld c, 5 + jr nz, .addstatus + ld c, 0 +.addstatus + ld a, b + add c + jr nc, .max_1 + ld a, $ff +.max_1 + + ; BUG: farcall overwrites a, and GetItemHeldEffect takes b anyway. + ; This is probably the reason the HELD_CATCH_CHANCE effect is never used. + ; Uncomment the line below to fix. + ld d, a + push de + ld a, [wBattleMonItem] + ; ld b, a + farcall GetItemHeldEffect + ld a, b + cp HELD_CATCH_CHANCE + pop de + ld a, d + jr nz, .max_2 + add c + jr nc, .max_2 + ld a, $ff +.max_2 + +.skip_hp_calc + ld b, a + ld [wBuffer1], a + call Random + + cp b + ld a, 0 + jr z, .catch_without_fail + jr nc, .fail_to_catch + +.catch_without_fail + ld a, [wEnemyMonSpecies] + +.fail_to_catch + ld [wWildMon], a + ld c, 20 + call DelayFrames + + ld a, [wCurItem] + cp POKE_BALL + 1 ; Assumes Master/Ultra/Great come before + jr c, .not_kurt_ball + ld a, POKE_BALL +.not_kurt_ball + ld [wBattleAnimParam], a + + ld de, ANIM_THROW_POKE_BALL + ld a, e + ld [wFXAnimID], a + ld a, d + ld [wFXAnimID + 1], a + xor a + ldh [hBattleTurn], a + ld [wBuffer2], a + ld [wNumHits], a + predef PlayBattleAnim + + ld a, [wWildMon] + and a + jr nz, .caught + ld a, [wBuffer2] + cp $1 + ld hl, BallBrokeFreeText + jp z, .shake_and_break_free + cp $2 + ld hl, BallAppearedCaughtText + jp z, .shake_and_break_free + cp $3 + ld hl, BallAlmostHadItText + jp z, .shake_and_break_free + cp $4 + ld hl, BallSoCloseText + jp z, .shake_and_break_free +.caught + + ld hl, wEnemyMonStatus + ld a, [hli] + push af + inc hl + ld a, [hli] + push af + ld a, [hl] + push af + push hl + ld hl, wEnemyMonItem + ld a, [hl] + push af + push hl + ld hl, wEnemySubStatus5 + ld a, [hl] + push af + set SUBSTATUS_TRANSFORMED, [hl] + +; This code is buggy. Any wild Pokémon that has Transformed will be +; caught as a Ditto, even if it was something else like Mew. +; To fix, do not set [wTempEnemyMonSpecies] to DITTO. + bit SUBSTATUS_TRANSFORMED, a + jr nz, .ditto + jr .not_ditto + +.ditto + ld a, DITTO + ld [wTempEnemyMonSpecies], a + jr .load_data + +.not_ditto + set SUBSTATUS_TRANSFORMED, [hl] + ld hl, wEnemyBackupDVs + ld a, [wEnemyMonDVs] + ld [hli], a + ld a, [wEnemyMonDVs + 1] + ld [hl], a + +.load_data + ld a, [wTempEnemyMonSpecies] + ld [wCurPartySpecies], a + ld a, [wEnemyMonLevel] + ld [wCurPartyLevel], a + farcall LoadEnemyMon + + pop af + ld [wEnemySubStatus5], a + + pop hl + pop af + ld [hl], a + pop hl + pop af + ld [hld], a + pop af + ld [hld], a + dec hl + pop af + ld [hl], a + + ld hl, wEnemySubStatus5 + bit SUBSTATUS_TRANSFORMED, [hl] + jr nz, .Transformed + ld hl, wWildMonMoves + ld de, wEnemyMonMoves + ld bc, NUM_MOVES + call CopyBytes + + ld hl, wWildMonPP + ld de, wEnemyMonPP + ld bc, NUM_MOVES + call CopyBytes + +.Transformed: + ld a, [wEnemyMonSpecies] + ld [wWildMon], a + ld [wCurPartySpecies], a + ld [wTempSpecies], a + ld a, [wBattleType] + cp BATTLETYPE_TUTORIAL + jp z, .FinishTutorial + + ld hl, Text_GotchaMonWasCaught + call PrintText + + call ClearSprites + + ld a, [wTempSpecies] + dec a + call CheckCaughtMon + + ld a, c + push af + ld a, [wTempSpecies] + dec a + call SetSeenAndCaughtMon + pop af + and a + jr nz, .skip_pokedex + + call CheckReceivedDex + jr z, .skip_pokedex + + ld hl, NewDexDataText + call PrintText + + call ClearSprites + + ld a, [wEnemyMonSpecies] + ld [wTempSpecies], a + predef NewPokedexEntry + +.skip_pokedex + ld a, [wBattleType] + cp BATTLETYPE_CONTEST + jp z, .catch_bug_contest_mon + ld a, [wPartyCount] + cp PARTY_LENGTH + jr z, .SendToPC + + xor a ; PARTYMON + ld [wMonType], a + call ClearSprites + + predef TryAddMonToParty + + ld a, [wCurItem] + cp FRIEND_BALL + jr nz, .SkipPartyMonFriendBall + + ld a, [wPartyCount] + dec a + ld hl, wPartyMon1Happiness + ld bc, PARTYMON_STRUCT_LENGTH + call AddNTimes + + ld a, FRIEND_BALL_HAPPINESS + ld [hl], a + +.SkipPartyMonFriendBall: + ld hl, AskGiveNicknameText + call PrintText + + ld a, [wCurPartySpecies] + ld [wNamedObjectIndexBuffer], a + call GetPokemonName + + call YesNoBox + jp c, .return_from_capture + + ld a, [wPartyCount] + dec a + ld [wCurPartyMon], a + ld hl, wPartyMonNicknames + ld bc, MON_NAME_LENGTH + call AddNTimes + + ld d, h + ld e, l + push de + xor a ; PARTYMON + ld [wMonType], a + ld b, NAME_MON + farcall NamingScreen + + call RotateThreePalettesRight + + call LoadStandardFont + + pop hl + ld de, wStringBuffer1 + call InitName + + jp .return_from_capture + +.SendToPC: + call ClearSprites + + predef SendMonIntoBox + + ld a, BANK(sBoxCount) + call OpenSRAM + + ld a, [sBoxCount] + cp MONS_PER_BOX + jr nz, .BoxNotFullYet + ld hl, wBattleResult + set BATTLERESULT_BOX_FULL, [hl] +.BoxNotFullYet: + ld a, [wCurItem] + cp FRIEND_BALL + jr nz, .SkipBoxMonFriendBall + ; The captured mon is now first in the box + ld a, FRIEND_BALL_HAPPINESS + ld [sBoxMon1Happiness], a +.SkipBoxMonFriendBall: + call CloseSRAM + + ld hl, AskGiveNicknameText + call PrintText + + ld a, [wCurPartySpecies] + ld [wNamedObjectIndexBuffer], a + call GetPokemonName + + call YesNoBox + jr c, .SkipBoxMonNickname + + xor a + ld [wCurPartyMon], a + ld a, BOXMON + ld [wMonType], a + ld de, wMonOrItemNameBuffer + ld b, NAME_MON + farcall NamingScreen + + ld a, BANK(sBoxMonNicknames) + call OpenSRAM + + ld hl, wMonOrItemNameBuffer + ld de, sBoxMonNicknames + ld bc, MON_NAME_LENGTH + call CopyBytes + + ld hl, sBoxMonNicknames + ld de, wStringBuffer1 + call InitName + + call CloseSRAM + +.SkipBoxMonNickname: + ld a, BANK(sBoxMonNicknames) + call OpenSRAM + + ld hl, sBoxMonNicknames + ld de, wMonOrItemNameBuffer + ld bc, MON_NAME_LENGTH + call CopyBytes + + call CloseSRAM + + ld hl, BallSentToPCText + call PrintText + + call RotateThreePalettesRight + call LoadStandardFont + jr .return_from_capture + +.catch_bug_contest_mon + farcall BugContest_SetCaughtContestMon + jr .return_from_capture + +.FinishTutorial: + ld hl, Text_GotchaMonWasCaught + +.shake_and_break_free + call PrintText + call ClearSprites + +.return_from_capture + ld a, [wBattleType] + cp BATTLETYPE_TUTORIAL + ret z + cp BATTLETYPE_DEBUG + ret z + cp BATTLETYPE_CONTEST + jr z, .used_park_ball + + ld a, [wWildMon] + and a + jr z, .toss + + call ClearBGPalettes + call ClearTilemap + +.toss + ld hl, wNumItems + inc a + ld [wItemQuantityChangeBuffer], a + jp TossItem + +.used_park_ball + ld hl, wParkBallsRemaining + dec [hl] + ret + +BallMultiplierFunctionTable: +; table of routines that increase or decrease the catch rate based on +; which ball is used in a certain situation. + dbw ULTRA_BALL, UltraBallMultiplier + dbw GREAT_BALL, GreatBallMultiplier + dbw SAFARI_BALL, SafariBallMultiplier ; Safari Ball, leftover from RBY + dbw HEAVY_BALL, HeavyBallMultiplier + dbw LEVEL_BALL, LevelBallMultiplier + dbw LURE_BALL, LureBallMultiplier + dbw FAST_BALL, FastBallMultiplier + dbw MOON_BALL, MoonBallMultiplier + dbw LOVE_BALL, LoveBallMultiplier + dbw PARK_BALL, ParkBallMultiplier + db -1 ; end + +UltraBallMultiplier: +; multiply catch rate by 2 + sla b + ret nc + ld b, $ff + ret + +SafariBallMultiplier: +GreatBallMultiplier: +ParkBallMultiplier: +; multiply catch rate by 1.5 + ld a, b + srl a + add b + ld b, a + ret nc + ld b, $ff + ret + +HeavyBallMultiplier: +; subtract 20 from catch rate if weight < 102.4 kg +; else add 0 to catch rate if weight < 204.8 kg +; else add 20 to catch rate if weight < 307.2 kg +; else add 30 to catch rate if weight < 409.6 kg +; else add 40 to catch rate (never happens) + ld a, [wEnemyMonSpecies] + dec a + ld hl, PokedexDataPointerTable + ld e, a + ld d, 0 + add hl, de + add hl, de + rlca + rlca + and %11 + add BANK("Pokedex Entries 001-064") + ld d, a + ld a, BANK(PokedexDataPointerTable) + call GetFarHalfword + +.SkipText: + ld a, d + call GetFarByte + inc hl + cp "@" + jr nz, .SkipText + + ld a, d + push bc + inc hl + inc hl + call GetFarHalfword + + srl h + rr l + ld b, h + ld c, l + +rept 4 + srl b + rr c +endr + call .subbc + + srl b + rr c + call .subbc + + ld a, h + pop bc + jr .compare + +.subbc + ; subtract bc from hl + push bc + ld a, b + cpl + ld b, a + ld a, c + cpl + ld c, a + inc bc + add hl, bc + pop bc + ret + +.compare + ld c, a + cp HIGH(1024) ; 102.4 kg + jr c, .lightmon + + ld hl, .WeightsTable +.lookup + ld a, c + cp [hl] + jr c, .heavymon + inc hl + inc hl + jr .lookup + +.heavymon + inc hl + ld a, b + add [hl] + ld b, a + ret nc + ld b, $ff + ret + +.lightmon + ld a, b + sub 20 + ld b, a + ret nc + ld b, $1 + ret + +.WeightsTable: +; weight factor, boost + db HIGH(2048), 0 + db HIGH(3072), 20 + db HIGH(4096), 30 + db HIGH(65280), 40 + +LureBallMultiplier: +; multiply catch rate by 3 if this is a fishing rod battle + ld a, [wBattleType] + cp BATTLETYPE_FISH + ret nz + + ld a, b + add a + jr c, .max + + add b + jr nc, .done +.max + ld a, $ff +.done + ld b, a + ret + +MoonBallMultiplier: +; This function is buggy. +; Intent: multiply catch rate by 4 if mon evolves with moon stone +; Reality: no boost + push bc + ld a, [wTempEnemyMonSpecies] + dec a + ld c, a + ld b, 0 + ld hl, EvosAttacksPointers + add hl, bc + add hl, bc + ld a, BANK(EvosAttacksPointers) + call GetFarHalfword + pop bc + + push bc + ld a, BANK("Evolutions and Attacks") + call GetFarByte + cp EVOLVE_ITEM + pop bc + ret nz + + inc hl + inc hl + inc hl + +; Moon Stone's constant from Pokémon Red is used. +; No Pokémon evolve with Burn Heal, +; so Moon Balls always have a catch rate of 1×. + push bc + ld a, BANK("Evolutions and Attacks") + call GetFarByte + cp MOON_STONE_RED ; BURN_HEAL + pop bc + ret nz + + sla b + jr c, .max + sla b + jr nc, .done +.max + ld b, $ff +.done + ret + +LoveBallMultiplier: +; This function is buggy. +; Intent: multiply catch rate by 8 if mons are of same species, different sex +; Reality: multiply catch rate by 8 if mons are of same species, same sex + + ; does species match? + ld a, [wTempEnemyMonSpecies] + ld c, a + ld a, [wTempBattleMonSpecies] + cp c + ret nz + + ; check player mon species + push bc + ld a, [wTempBattleMonSpecies] + ld [wCurPartySpecies], a + xor a ; PARTYMON + ld [wMonType], a + ld a, [wCurBattleMon] + ld [wCurPartyMon], a + farcall GetGender + jr c, .done1 ; no effect on genderless + + ld d, 0 ; male + jr nz, .playermale + inc d ; female +.playermale + + ; check wild mon species + push de + ld a, [wTempEnemyMonSpecies] + ld [wCurPartySpecies], a + ld a, WILDMON + ld [wMonType], a + farcall GetGender + jr c, .done2 ; no effect on genderless + + ld d, 0 ; male + jr nz, .wildmale + inc d ; female +.wildmale + + ld a, d + pop de + cp d + pop bc + ret nz ; for the intended effect, this should be "ret z" + + sla b + jr c, .max + sla b + jr c, .max + sla b + ret nc +.max + ld b, $ff + ret + +.done2 + pop de + +.done1 + pop bc + ret + +FastBallMultiplier: +; This function is buggy. +; Intent: multiply catch rate by 4 if enemy mon is in one of the three +; FleeMons tables. +; Reality: multiply catch rate by 4 if enemy mon is one of the first three in +; the first FleeMons table. + ld a, [wTempEnemyMonSpecies] + ld c, a + ld hl, FleeMons + ld d, 3 + +.loop + ld a, BANK(FleeMons) + call GetFarByte + + inc hl + cp -1 + jr z, .next + cp c + jr nz, .next ; for the intended effect, this should be "jr nz, .loop" + sla b + jr c, .max + + sla b + ret nc + +.max + ld b, $ff + ret + +.next + dec d + jr nz, .loop + ret + +LevelBallMultiplier: +; multiply catch rate by 8 if player mon level / 4 > enemy mon level +; multiply catch rate by 4 if player mon level / 2 > enemy mon level +; multiply catch rate by 2 if player mon level > enemy mon level + ld a, [wBattleMonLevel] + ld c, a + ld a, [wEnemyMonLevel] + cp c + ret nc ; if player is lower level, we're done here + sla b + jr c, .max + + srl c + cp c + ret nc ; if player/2 is lower level, we're done here + sla b + jr c, .max + + srl c + cp c + ret nc ; if player/4 is lower level, we're done here + sla b + ret nc + +.max + ld b, $ff + ret + +; These two texts were carried over from gen 1. +; They are not used in gen 2, and are dummied out. + +BallDodgedText: + text_far _BallDodgedText + text_end + +BallMissedText: + text_far _BallMissedText + text_end + +BallBrokeFreeText: + text_far _BallBrokeFreeText + text_end + +BallAppearedCaughtText: + text_far _BallAppearedCaughtText + text_end + +BallAlmostHadItText: + text_far _BallAlmostHadItText + text_end + +BallSoCloseText: + text_far _BallSoCloseText + text_end + +Text_GotchaMonWasCaught: + ; Gotcha! @ was caught!@ @ + text_far Text_BallCaught + text_asm + call WaitSFX + push bc + ld de, MUSIC_NONE + call PlayMusic + call DelayFrame + ld de, MUSIC_CAPTURE + call PlayMusic + pop bc + ld hl, WaitButtonText + ret + +WaitButtonText: + text_far _WaitButtonText + text_end + +BallSentToPCText: + text_far _BallSentToPCText + text_end + +NewDexDataText: + text_far _NewDexDataText + text_end + +AskGiveNicknameText: + text_far _AskGiveNicknameText + text_end + +ReturnToBattle_UseBall: + farcall _ReturnToBattle_UseBall + ret + +TownMapEffect: + farcall PokegearMap + ret + +BicycleEffect: + farcall BikeFunction + ret + +EvoStoneEffect: + ld b, PARTYMENUACTION_EVO_STONE + call UseItem_SelectMon + + jp c, .DecidedNotToUse + + ld a, MON_ITEM + call GetPartyParamLocation + + ld a, [hl] + cp EVERSTONE + jr z, .NoEffect + + ld a, $1 + ld [wForceEvolution], a + farcall EvolvePokemon + + ld a, [wMonTriedToEvolve] + and a + jr z, .NoEffect + + jp UseDisposableItem + +.NoEffect: + call WontHaveAnyEffectMessage + +.DecidedNotToUse: + xor a + ld [wItemEffectSucceeded], a + ret + +VitaminEffect: + ld b, PARTYMENUACTION_HEALING_ITEM + call UseItem_SelectMon + + jp c, RareCandy_StatBooster_ExitMenu + + call RareCandy_StatBooster_GetParameters + + call GetStatExpRelativePointer + + ld a, MON_STAT_EXP + call GetPartyParamLocation + + add hl, bc + ld a, [hl] + cp 100 + jr nc, NoEffectMessage + + add 10 + ld [hl], a + call UpdateStatsAfterItem + + call GetStatExpRelativePointer + + ld hl, StatStrings + add hl, bc + ld a, [hli] + ld h, [hl] + ld l, a + ld de, wStringBuffer2 + ld bc, ITEM_NAME_LENGTH + call CopyBytes + + call Play_SFX_FULL_HEAL + + ld hl, ItemStatRoseText + call PrintText + + ld c, HAPPINESS_USEDITEM + farcall ChangeHappiness + + jp UseDisposableItem + +NoEffectMessage: + ld hl, ItemWontHaveEffectText + call PrintText + jp ClearPalettes + +UpdateStatsAfterItem: + ld a, MON_MAXHP + call GetPartyParamLocation + ld d, h + ld e, l + ld a, MON_STAT_EXP - 1 + call GetPartyParamLocation + ld b, TRUE + predef_jump CalcMonStats + +RareCandy_StatBooster_ExitMenu: + xor a + ld [wItemEffectSucceeded], a + jp ClearPalettes + +ItemStatRoseText: + text_far _ItemStatRoseText + text_end + +StatStrings: + dw .health + dw .attack + dw .defense + dw .speed + dw .special + +.health db "HEALTH@" +.attack db "ATTACK@" +.defense db "DEFENSE@" +.speed db "SPEED@" +.special db "SPECIAL@" + +GetStatExpRelativePointer: + ld a, [wCurItem] + ld hl, Table_eeeb +.next + cp [hl] + inc hl + jr z, .got_it + inc hl + jr .next + +.got_it + ld a, [hl] + ld c, a + ld b, 0 + ret + +Table_eeeb: + db HP_UP, MON_HP_EXP - MON_STAT_EXP + db PROTEIN, MON_ATK_EXP - MON_STAT_EXP + db IRON, MON_DEF_EXP - MON_STAT_EXP + db CARBOS, MON_SPD_EXP - MON_STAT_EXP + db CALCIUM, MON_SPC_EXP - MON_STAT_EXP + +RareCandy_StatBooster_GetParameters: + ld a, [wCurPartySpecies] + ld [wCurSpecies], a + ld [wTempSpecies], a + ld a, MON_LEVEL + call GetPartyParamLocation + ld a, [hl] + ld [wCurPartyLevel], a + call GetBaseData + ld a, [wCurPartyMon] + ld hl, wPartyMonNicknames + call GetNick + ret + +RareCandyEffect: + ld b, PARTYMENUACTION_HEALING_ITEM + call UseItem_SelectMon + + jp c, RareCandy_StatBooster_ExitMenu + + call RareCandy_StatBooster_GetParameters + + ld a, MON_LEVEL + call GetPartyParamLocation + + ld a, [hl] + cp MAX_LEVEL + jp nc, NoEffectMessage + + inc a + ld [hl], a + ld [wCurPartyLevel], a + push de + ld d, a + farcall CalcExpAtLevel + + pop de + ld a, MON_EXP + call GetPartyParamLocation + + ldh a, [hMultiplicand + 0] + ld [hli], a + ldh a, [hMultiplicand + 1] + ld [hli], a + ldh a, [hMultiplicand + 2] + ld [hl], a + + ld a, MON_MAXHP + call GetPartyParamLocation + ld a, [hli] + ld b, a + ld c, [hl] + push bc + call UpdateStatsAfterItem + + ld a, MON_MAXHP + 1 + call GetPartyParamLocation + + pop bc + ld a, [hld] + sub c + ld c, a + ld a, [hl] + sbc b + ld b, a + dec hl + ld a, [hl] + add c + ld [hld], a + ld a, [hl] + adc b + ld [hl], a + ld c, 1 + farcall ChangeHappiness + + ld a, PARTYMENUTEXT_LEVEL_UP + call ItemActionText + + xor a ; PARTYMON + ld [wMonType], a + predef CopyMonToTempMon + + hlcoord 9, 0 + ld b, 10 + ld c, 9 + call Textbox + + hlcoord 11, 1 + ld bc, 4 + predef PrintTempMonStats + + call WaitPressAorB_BlinkCursor + + xor a ; PARTYMON + ld [wMonType], a + ld a, [wCurPartySpecies] + ld [wTempSpecies], a + predef LearnLevelMoves + + xor a + ld [wForceEvolution], a + farcall EvolvePokemon + + jp UseDisposableItem + +HealPowderEffect: + ld b, PARTYMENUACTION_HEALING_ITEM + call UseItem_SelectMon + + jp c, StatusHealer_ExitMenu + + call UseStatusHealer + + cp $0 + jr nz, .asm_efc9 + ld c, HAPPINESS_BITTERPOWDER + farcall ChangeHappiness + + call LooksBitterMessage + + ld a, $0 + +.asm_efc9 + jp StatusHealer_Jumptable + +StatusHealingEffect: + ld b, PARTYMENUACTION_HEALING_ITEM + call UseItem_SelectMon + jp c, StatusHealer_ExitMenu + +FullyHealStatus: + call UseStatusHealer + jp StatusHealer_Jumptable + +UseStatusHealer: + call IsMonFainted + ld a, $1 + ret z + call GetItemHealingAction + ld a, MON_STATUS + call GetPartyParamLocation + ld a, [hl] + and c + jr nz, .good + call IsItemUsedOnConfusedMon + ld a, $1 + ret nc + ld b, PARTYMENUTEXT_HEAL_CONFUSION +.good + xor a + ld [hl], a + ld a, b + ld [wPartyMenuActionText], a + call HealStatus + call Play_SFX_FULL_HEAL + call ItemActionTextWaitButton + call UseDisposableItem + ld a, $0 + ret + +IsItemUsedOnConfusedMon: + call IsItemUsedOnBattleMon + jr nc, .nope + ld a, [wPlayerSubStatus3] + bit SUBSTATUS_CONFUSED, a + jr z, .nope + ld a, c + cp $ff + jr nz, .nope + scf + ret + +.nope + and a + ret + +BattlemonRestoreHealth: + call IsItemUsedOnBattleMon + ret nc + ld a, MON_HP + call GetPartyParamLocation + ld a, [hli] + ld [wBattleMonHP], a + ld a, [hld] + ld [wBattleMonHP + 1], a + ret + +HealStatus: + call IsItemUsedOnBattleMon + ret nc + xor a + ld [wBattleMonStatus], a + ld hl, wPlayerSubStatus5 + res SUBSTATUS_TOXIC, [hl] + ld hl, wPlayerSubStatus1 + res SUBSTATUS_NIGHTMARE, [hl] + call GetItemHealingAction + ld a, c + cp %11111111 + jr nz, .not_full_heal + ld hl, wPlayerSubStatus3 + res SUBSTATUS_CONFUSED, [hl] +.not_full_heal + push bc + farcall CalcPlayerStats + pop bc + ret + +GetItemHealingAction: + push hl + ld a, [wCurItem] + ld hl, StatusHealingActions + ld bc, 3 +.next + cp [hl] + jr z, .found_it + add hl, bc + jr .next + +.found_it + inc hl + ld b, [hl] + inc hl + ld a, [hl] + ld c, a + cp %11111111 + pop hl + ret + +INCLUDE "data/items/heal_status.asm" + +StatusHealer_Jumptable: + ld hl, .dw + rst JumpTable + ret + +.dw + dw StatusHealer_ClearPalettes + dw StatusHealer_NoEffect + dw StatusHealer_ExitMenu + +RevivalHerbEffect: + ld b, PARTYMENUACTION_HEALING_ITEM + call UseItem_SelectMon + jp c, StatusHealer_ExitMenu + + call RevivePokemon + cp 0 + jr nz, .asm_f0c5 + + ld c, HAPPINESS_REVIVALHERB + farcall ChangeHappiness + call LooksBitterMessage + ld a, 0 + +.asm_f0c5 + jp StatusHealer_Jumptable + +ReviveEffect: + ld b, PARTYMENUACTION_HEALING_ITEM + call UseItem_SelectMon + jp c, StatusHealer_ExitMenu + + call RevivePokemon + jp StatusHealer_Jumptable + +RevivePokemon: + call IsMonFainted + ld a, 1 + ret nz + ld a, [wBattleMode] + and a + jr z, .skip_to_revive + + ld a, [wCurPartyMon] + ld c, a + ld d, 0 + ld hl, wBattleParticipantsIncludingFainted + ld b, CHECK_FLAG + predef SmallFarFlagAction + ld a, c + and a + jr z, .skip_to_revive + + ld a, [wCurPartyMon] + ld c, a + ld hl, wBattleParticipantsNotFainted + ld b, SET_FLAG + predef SmallFarFlagAction + +.skip_to_revive + xor a + ld [wLowHealthAlarm], a + ld a, [wCurItem] + cp REVIVE + jr z, .revive_half_hp + + call ReviveFullHP + jr .finish_revive + +.revive_half_hp + call ReviveHalfHP + +.finish_revive + call HealHP_SFX_GFX + ld a, PARTYMENUTEXT_REVIVE + ld [wPartyMenuActionText], a + call ItemActionTextWaitButton + call UseDisposableItem + ld a, 0 + ret + +FullRestoreEffect: + ld b, PARTYMENUACTION_HEALING_ITEM + call UseItem_SelectMon + jp c, StatusHealer_ExitMenu + + call IsMonFainted + jp z, StatusHealer_NoEffect + + call IsMonAtFullHealth + jr c, .NotAtFullHealth + + jp FullyHealStatus + +.NotAtFullHealth: + call .FullRestore + jp StatusHealer_Jumptable + +.FullRestore: + xor a + ld [wLowHealthAlarm], a + call ReviveFullHP + ld a, MON_STATUS + call GetPartyParamLocation + xor a + ld [hli], a + ld [hl], a + call HealStatus + call BattlemonRestoreHealth + call HealHP_SFX_GFX + ld a, PARTYMENUTEXT_HEAL_HP + ld [wPartyMenuActionText], a + call ItemActionTextWaitButton + call UseDisposableItem + ld a, 0 + ret + +BitterBerryEffect: + ld hl, wPlayerSubStatus3 + bit SUBSTATUS_CONFUSED, [hl] + ld a, 1 + jr z, .done + + res SUBSTATUS_CONFUSED, [hl] + xor a + ldh [hBattleTurn], a + call UseItemText + + ld hl, ConfusedNoMoreText + call StdBattleTextbox + + ld a, 0 + +.done + jp StatusHealer_Jumptable + +RestoreHPEffect: + call ItemRestoreHP + jp StatusHealer_Jumptable + +EnergypowderEffect: + ld c, HAPPINESS_BITTERPOWDER + jr EnergypowderEnergyRootCommon + +EnergyRootEffect: + ld c, HAPPINESS_ENERGYROOT + +EnergypowderEnergyRootCommon: + push bc + call ItemRestoreHP + pop bc + cp 0 + jr nz, .skip_happiness + + farcall ChangeHappiness + call LooksBitterMessage + ld a, 0 + +.skip_happiness + jp StatusHealer_Jumptable + +ItemRestoreHP: + ld b, PARTYMENUACTION_HEALING_ITEM + call UseItem_SelectMon + ld a, 2 + ret c + + call IsMonFainted + ld a, 1 + ret z + + call IsMonAtFullHealth + ld a, 1 + ret nc + + xor a + ld [wLowHealthAlarm], a + call GetHealingItemAmount + call RestoreHealth + call BattlemonRestoreHealth + call HealHP_SFX_GFX + ld a, PARTYMENUTEXT_HEAL_HP + ld [wPartyMenuActionText], a + call ItemActionTextWaitButton + call UseDisposableItem + ld a, 0 + ret + +HealHP_SFX_GFX: + push de + ld de, SFX_POTION + call WaitPlaySFX + pop de + ld a, [wCurPartyMon] + hlcoord 11, 0 + ld bc, SCREEN_WIDTH * 2 + call AddNTimes + ld a, $2 + ld [wWhichHPBar], a + predef_jump AnimateHPBar + +UseItem_SelectMon: + call .SelectMon + ret c + + ld a, [wCurPartySpecies] + cp EGG + jr nz, .not_egg + + call CantUseOnEggMessage + scf + ret + +.not_egg + and a + ret + +.SelectMon: + ld a, b + ld [wPartyMenuActionText], a + push hl + push de + push bc + call ClearBGPalettes + call ChooseMonToUseItemOn + pop bc + pop de + pop hl + ret + +ChooseMonToUseItemOn: + farcall LoadPartyMenuGFX + farcall InitPartyMenuWithCancel + farcall InitPartyMenuGFX + farcall WritePartyMenuTilemap + farcall PrintPartyMenuText + call WaitBGMap + call SetPalettes + call DelayFrame + farcall PartyMenuSelect + ret + +ItemActionText: + ld [wPartyMenuActionText], a + ld a, [wCurPartySpecies] + push af + ld a, [wCurPartyMon] + push af + push hl + push de + push bc + farcall WritePartyMenuTilemap + farcall PrintPartyMenuActionText + call WaitBGMap + call SetPalettes + call DelayFrame + pop bc + pop de + pop hl + pop af + ld [wCurPartyMon], a + pop af + ld [wCurPartySpecies], a + ret + +ItemActionTextWaitButton: + xor a + ldh [hBGMapMode], a + hlcoord 0, 0 + ld bc, wTilemapEnd - wTilemap + ld a, " " + call ByteFill + ld a, [wPartyMenuActionText] + call ItemActionText + ld a, $1 + ldh [hBGMapMode], a + ld c, 50 + call DelayFrames + jp WaitPressAorB_BlinkCursor + +StatusHealer_NoEffect: + call WontHaveAnyEffectMessage + jr StatusHealer_ClearPalettes + +StatusHealer_ExitMenu: + xor a + ld [wItemEffectSucceeded], a +StatusHealer_ClearPalettes: + call ClearPalettes + ret + +IsItemUsedOnBattleMon: + ld a, [wBattleMode] + and a + ret z + ld a, [wCurPartyMon] + push hl + ld hl, wCurBattleMon + cp [hl] + pop hl + jr nz, .nope + scf + ret + +.nope + xor a + ret + +ReviveHalfHP: + call LoadHPFromBuffer1 + srl d + rr e + jr ContinueRevive + +ReviveFullHP: + call LoadHPFromBuffer1 +ContinueRevive: + ld a, MON_HP + call GetPartyParamLocation + ld [hl], d + inc hl + ld [hl], e + jp LoadCurHPIntoBuffer5 + +RestoreHealth: + ld a, MON_HP + 1 + call GetPartyParamLocation + ld a, [hl] + add e + ld [hld], a + ld a, [hl] + adc d + ld [hl], a + jr c, .full_hp + call LoadCurHPIntoBuffer5 + ld a, MON_HP + 1 + call GetPartyParamLocation + ld d, h + ld e, l + ld a, MON_MAXHP + 1 + call GetPartyParamLocation + ld a, [de] + sub [hl] + dec de + dec hl + ld a, [de] + sbc [hl] + jr c, .finish +.full_hp + call ReviveFullHP +.finish + ret + +RemoveHP: + ld a, MON_HP + 1 + call GetPartyParamLocation + ld a, [hl] + sub e + ld [hld], a + ld a, [hl] + sbc d + ld [hl], a + jr nc, .okay + xor a + ld [hld], a + ld [hl], a +.okay + call LoadCurHPIntoBuffer5 + ret + +IsMonFainted: + push de + call LoadMaxHPToBuffer1 + call LoadCurHPToBuffer3 + call LoadHPFromBuffer3 + ld a, d + or e + pop de + ret + +IsMonAtFullHealth: + call LoadHPFromBuffer3 + ld h, d + ld l, e + call LoadHPFromBuffer1 + ld a, l + sub e + ld a, h + sbc d + ret + +LoadCurHPIntoBuffer5: + ld a, MON_HP + call GetPartyParamLocation + ld a, [hli] + ld [wBuffer6], a + ld a, [hl] + ld [wBuffer5], a + ret + +LoadHPIntoBuffer5: + ld a, d + ld [wBuffer6], a + ld a, e + ld [wBuffer5], a + ret + +LoadHPFromBuffer5: + ld a, [wBuffer6] + ld d, a + ld a, [wBuffer5] + ld e, a + ret + +LoadCurHPToBuffer3: + ld a, MON_HP + call GetPartyParamLocation + ld a, [hli] + ld [wBuffer4], a + ld a, [hl] + ld [wBuffer3], a + ret + +LoadHPFromBuffer3: + ld a, [wBuffer4] + ld d, a + ld a, [wBuffer3] + ld e, a + ret + +LoadMaxHPToBuffer1: + push hl + ld a, MON_MAXHP + call GetPartyParamLocation + ld a, [hli] + ld [wBuffer2], a + ld a, [hl] + ld [wBuffer1], a + pop hl + ret + +LoadHPFromBuffer1: + ld a, [wBuffer2] + ld d, a + ld a, [wBuffer1] + ld e, a + ret + +GetOneFifthMaxHP: + push bc + ld a, MON_MAXHP + call GetPartyParamLocation + ld a, [hli] + ldh [hDividend + 0], a + ld a, [hl] + ldh [hDividend + 1], a + ld a, 5 + ldh [hDivisor], a + ld b, 2 + call Divide + ldh a, [hQuotient + 2] + ld d, a + ldh a, [hQuotient + 3] + ld e, a + pop bc + ret + +GetHealingItemAmount: + push hl + ld a, [wCurItem] + ld hl, HealingHPAmounts + ld d, a +.next + ld a, [hli] + cp -1 + jr z, .NotFound + cp d + jr z, .done + inc hl + inc hl + jr .next + +.NotFound: + scf +.done + ld e, [hl] + inc hl + ld d, [hl] + pop hl + ret + +INCLUDE "data/items/heal_hp.asm" + +Softboiled_MilkDrinkFunction: +; Softboiled/Milk Drink in the field + ld a, [wPartyMenuCursor] + dec a + ld b, a + call .SelectMilkDrinkRecipient ; select pokemon + jr c, .skip + ld a, b + ld [wCurPartyMon], a + call IsMonFainted + call GetOneFifthMaxHP + call RemoveHP + push bc + call HealHP_SFX_GFX + pop bc + call GetOneFifthMaxHP + ld a, c + ld [wCurPartyMon], a + call IsMonFainted + call RestoreHealth + call HealHP_SFX_GFX + ld a, PARTYMENUTEXT_HEAL_HP + call ItemActionText + call JoyWaitAorB +.skip + ld a, b + inc a + ld [wPartyMenuCursor], a + ret + +.SelectMilkDrinkRecipient: +.loop + push bc + ld a, PARTYMENUACTION_HEALING_ITEM + ld [wPartyMenuActionText], a + call ChooseMonToUseItemOn + pop bc + jr c, .set_carry + ld a, [wPartyMenuCursor] + dec a + ld c, a + ld a, b + cp c + jr z, .cant_use ; chose the same mon as user + ld a, c + ld [wCurPartyMon], a + call IsMonFainted + jr z, .cant_use + call IsMonAtFullHealth + jr nc, .cant_use + xor a + ret + +.set_carry + scf + ret + +.cant_use + push bc + ld hl, .ItemCantUseOnMonText + call MenuTextboxBackup + pop bc + jr .loop + +.ItemCantUseOnMonText: + text_far _ItemCantUseOnMonText + text_end + +EscapeRopeEffect: + xor a + ld [wItemEffectSucceeded], a + farcall EscapeRopeFunction + + ld a, [wItemEffectSucceeded] + cp 1 + call z, UseDisposableItem + ret + +SuperRepelEffect: + ld b, 200 + jr UseRepel + +MaxRepelEffect: + ld b, 250 + jr UseRepel + +RepelEffect: + ld b, 100 + +UseRepel: + ld a, [wRepelEffect] + and a + ld hl, RepelUsedEarlierIsStillInEffectText + jp nz, PrintText + + ld a, b + ld [wRepelEffect], a + jp UseItemText + +RepelUsedEarlierIsStillInEffectText: + text_far _RepelUsedEarlierIsStillInEffectText + text_end + +XAccuracyEffect: + ld hl, wPlayerSubStatus4 + bit SUBSTATUS_X_ACCURACY, [hl] + jp nz, WontHaveAnyEffect_NotUsedMessage + set SUBSTATUS_X_ACCURACY, [hl] + jp UseItemText + +PokeDollEffect: + ld a, [wBattleMode] + dec a + jr nz, .asm_f4f6 + inc a + ld [wForcedSwitch], a + ; set battle draw + inc a + ld [wBattleResult], a + jp UseItemText + +.asm_f4f6 + xor a + ld [wItemEffectSucceeded], a + ret + +GuardSpecEffect: + ld hl, wPlayerSubStatus4 + bit SUBSTATUS_MIST, [hl] + jp nz, WontHaveAnyEffect_NotUsedMessage + set SUBSTATUS_MIST, [hl] + jp UseItemText + +DireHitEffect: + ld hl, wPlayerSubStatus4 + bit SUBSTATUS_FOCUS_ENERGY, [hl] + jp nz, WontHaveAnyEffect_NotUsedMessage + set SUBSTATUS_FOCUS_ENERGY, [hl] + jp UseItemText + +XItemEffect: + call UseItemText + + ld a, [wCurItem] + ld hl, XItemStats + +.loop + cp [hl] + jr z, .got_it + inc hl + inc hl + jr .loop + +.got_it + inc hl + ld b, [hl] + xor a + ldh [hBattleTurn], a + ld [wAttackMissed], a + ld [wEffectFailed], a + farcall RaiseStat + call WaitSFX + + farcall BattleCommand_StatUpMessage + farcall BattleCommand_StatUpFailText + + ld a, [wCurBattleMon] + ld [wCurPartyMon], a + ld c, HAPPINESS_USEDXITEM + farcall ChangeHappiness + ret + +INCLUDE "data/items/x_stats.asm" + +PokeFluteEffect: + ld a, [wBattleMode] + and a + jr nz, .dummy +.dummy + + xor a + ld [wceed], a + + ld b, $ff ^ SLP + + ld hl, wPartyMon1Status + call .CureSleep + + ld a, [wBattleMode] + cp WILD_BATTLE + jr z, .skip_otrainer + ld hl, wOTPartyMon1Status + call .CureSleep +.skip_otrainer + + ld hl, wBattleMonStatus + ld a, [hl] + and b + ld [hl], a + ld hl, wEnemyMonStatus + ld a, [hl] + and b + ld [hl], a + + ld a, [wceed] + and a + ld hl, .PlayedFluteText + jp z, PrintText + ld hl, .PlayedTheFlute + call PrintText + + ld a, [wLowHealthAlarm] + and 1 << DANGER_ON_F + jr nz, .dummy2 +.dummy2 + ld hl, .FluteWakeUpText + jp PrintText + +.CureSleep: + ld de, PARTYMON_STRUCT_LENGTH + ld c, PARTY_LENGTH + +.loop + ld a, [hl] + push af + and SLP + jr z, .not_asleep + ld a, 1 + ld [wceed], a +.not_asleep + pop af + and b + ld [hl], a + add hl, de + dec c + jr nz, .loop + ret + +.PlayedFluteText: + text_far _PlayedFluteText + text_end + +.FluteWakeUpText: + text_far _FluteWakeUpText + text_end + +.PlayedTheFlute: + ; played the # FLUTE.@ @ + text_far Text_PlayedPokeFlute + text_asm + ld a, [wBattleMode] + and a + jr nz, .battle + + push de + ld de, SFX_POKEFLUTE + call WaitPlaySFX + call WaitSFX + pop de + +.battle + ld hl, .terminator + ret + +.terminator + db "@" + +CoinCaseEffect: + ld hl, .CoinCaseCountText + jp MenuTextboxWaitButton + +.CoinCaseCountText: + text_far _CoinCaseCountText + text_end + +OldRodEffect: + ld e, $0 + jr UseRod + +GoodRodEffect: + ld e, $1 + jr UseRod + +SuperRodEffect: + ld e, $2 + jr UseRod + +UseRod: + farcall FishFunction + ret + +ItemfinderEffect: + farcall ItemFinder + ret + +RestorePPEffect: + ld a, [wCurItem] + ld [wceed], a + +.loop + ; Party Screen opens to choose on which mon to use the Item + ld b, PARTYMENUACTION_HEALING_ITEM + call UseItem_SelectMon + jp c, PPRestoreItem_Cancel + +.loop2 + ld a, [wceed] + cp MAX_ELIXER + jp z, Elixer_RestorePPofAllMoves + cp ELIXER + jp z, Elixer_RestorePPofAllMoves + + ld hl, RaiseThePPOfWhichMoveText + ld a, [wceed] + cp PP_UP + jr z, .ppup + ld hl, RestoreThePPOfWhichMoveText + +.ppup + call PrintText + + ld a, [wCurMoveNum] + push af + xor a + ld [wCurMoveNum], a + ld a, $2 + ld [wMoveSelectionMenuType], a + farcall MoveSelectionScreen + pop bc + + ld a, b + ld [wCurMoveNum], a + jr nz, .loop + ld hl, wPartyMon1Moves + ld bc, PARTYMON_STRUCT_LENGTH + call GetMthMoveOfNthPartymon + + push hl + ld a, [hl] + ld [wNamedObjectIndexBuffer], a + call GetMoveName + call CopyName1 + pop hl + + ld a, [wceed] + cp PP_UP + jp nz, Not_PP_Up + + ld a, [hl] + cp SKETCH + jr z, .CantUsePPUpOnSketch + + ld bc, MON_PP - MON_MOVES + add hl, bc + ld a, [hl] + cp PP_UP_MASK + jr c, .do_ppup + +.CantUsePPUpOnSketch: +.pp_is_maxed_out + ld hl, PPIsMaxedOutText + call PrintText + jr .loop2 + +.do_ppup + ld a, [hl] + add PP_UP_ONE + ld [hl], a + ld a, TRUE + ld [wUsePPUp], a + call ApplyPPUp + call Play_SFX_FULL_HEAL + + ld hl, PPsIncreasedText + call PrintText + +FinishPPRestore: + call ClearPalettes + jp UseDisposableItem + +BattleRestorePP: + ld a, [wBattleMode] + and a + jr z, .not_in_battle + ld a, [wCurPartyMon] + ld b, a + ld a, [wCurBattleMon] + cp b + jr nz, .not_in_battle + ld a, [wPlayerSubStatus5] + bit SUBSTATUS_TRANSFORMED, a + jr nz, .not_in_battle + call .UpdateBattleMonPP + +.not_in_battle + call Play_SFX_FULL_HEAL + ld hl, PPRestoredText + call PrintText + jr FinishPPRestore + +.UpdateBattleMonPP: + ld a, [wCurPartyMon] + ld hl, wPartyMon1Moves + ld bc, PARTYMON_STRUCT_LENGTH + call AddNTimes + ld de, wBattleMonMoves + ld b, NUM_MOVES +.loop + ld a, [de] + and a + jr z, .done + cp [hl] + jr nz, .next + push hl + push de + push bc +rept NUM_MOVES + 2 ; wBattleMonPP - wBattleMonMoves + inc de +endr + ld bc, MON_PP - MON_MOVES + add hl, bc + ld a, [hl] + ld [de], a + pop bc + pop de + pop hl + +.next + inc hl + inc de + dec b + jr nz, .loop + +.done + ret + +Not_PP_Up: + call RestorePP + jr nz, BattleRestorePP + jp PPRestoreItem_NoEffect + +Elixer_RestorePPofAllMoves: + xor a + ld hl, wMenuCursorY + ld [hli], a + ld [hl], a + ld b, NUM_MOVES +.moveLoop + push bc + ld hl, wPartyMon1Moves + ld bc, PARTYMON_STRUCT_LENGTH + call GetMthMoveOfNthPartymon + ld a, [hl] + and a + jr z, .next + + call RestorePP + jr z, .next + ld hl, wMenuCursorX + inc [hl] + +.next + ld hl, wMenuCursorY + inc [hl] + pop bc + dec b + jr nz, .moveLoop + ld a, [wMenuCursorX] + and a + jp nz, BattleRestorePP + +PPRestoreItem_NoEffect: + call WontHaveAnyEffectMessage + +PPRestoreItem_Cancel: + call ClearPalettes + xor a + ld [wItemEffectSucceeded], a + ret + +RestorePP: + xor a ; PARTYMON + ld [wMonType], a + call GetMaxPPOfMove + ld hl, wPartyMon1PP + ld bc, PARTYMON_STRUCT_LENGTH + call GetMthMoveOfNthPartymon + ld a, [wTempPP] + ld b, a + ld a, [hl] + and PP_MASK + cp b + jr nc, .dont_restore + + ld a, [wceed] + cp MAX_ELIXER + jr z, .restore_all + cp MAX_ETHER + jr z, .restore_all + + ld c, 5 + cp MYSTERYBERRY + jr z, .restore_some + + ld c, 10 + +.restore_some + ld a, [hl] + and PP_MASK + add c + cp b + jr nc, .restore_all + ld b, a + +.restore_all + ld a, [hl] + and PP_UP_MASK + or b + ld [hl], a + ret + +.dont_restore + xor a + ret + +RaiseThePPOfWhichMoveText: + text_far _RaiseThePPOfWhichMoveText + text_end + +RestoreThePPOfWhichMoveText: + text_far _RestoreThePPOfWhichMoveText + text_end + +PPIsMaxedOutText: + text_far _PPIsMaxedOutText + text_end + +PPsIncreasedText: + text_far _PPsIncreasedText + text_end + +PPRestoredText: + text_far _PPRestoredText + text_end + +SquirtbottleEffect: + farcall _Squirtbottle + ret + +CardKeyEffect: + farcall _CardKey + ret + +BasementKeyEffect: + farcall _BasementKey + ret + +SacredAshEffect: + farcall _SacredAsh + ld a, [wItemEffectSucceeded] + cp $1 + ret nz + call UseDisposableItem + ret + +NormalBoxEffect: + ld c, DECOFLAG_SILVER_TROPHY_DOLL + jr OpenBox + +GorgeousBoxEffect: + ld c, DECOFLAG_GOLD_TROPHY_DOLL +OpenBox: + farcall SetSpecificDecorationFlag + + ld hl, .SentTrophyHomeText + call PrintText + + jp UseDisposableItem + +.SentTrophyHomeText: + text_far _SentTrophyHomeText + text_end + +NoEffect: + jp IsntTheTimeMessage + +Play_SFX_FULL_HEAL: + push de + ld de, SFX_FULL_HEAL + call WaitPlaySFX + pop de + ret + +UseItemText: + ld hl, ItemUsedText + call PrintText + call Play_SFX_FULL_HEAL + call WaitPressAorB_BlinkCursor +UseDisposableItem: + ld hl, wNumItems + ld a, 1 + ld [wItemQuantityChangeBuffer], a + jp TossItem + +UseBallInTrainerBattle: + call ReturnToBattle_UseBall + ld de, ANIM_THROW_POKE_BALL + ld a, e + ld [wFXAnimID], a + ld a, d + ld [wFXAnimID + 1], a + xor a + ld [wBattleAnimParam], a + ldh [hBattleTurn], a + ld [wNumHits], a + predef PlayBattleAnim + ld hl, BallBlockedText + call PrintText + ld hl, BallDontBeAThiefText + call PrintText + jr UseDisposableItem + +WontHaveAnyEffect_NotUsedMessage: + ld hl, ItemWontHaveEffectText + call PrintText + + ; Item wasn't used. + ld a, $2 + ld [wItemEffectSucceeded], a + ret + +LooksBitterMessage: + ld hl, ItemLooksBitterText + jp PrintText + +Ball_BoxIsFullMessage: + ld hl, BallBoxFullText + call PrintText + + ; Item wasn't used. + ld a, $2 + ld [wItemEffectSucceeded], a + ret + +CantUseOnEggMessage: + ld hl, ItemCantUseOnEggText + jr CantUseItemMessage + +IsntTheTimeMessage: + ld hl, ItemOakWarningText + jr CantUseItemMessage + +WontHaveAnyEffectMessage: + ld hl, ItemWontHaveEffectText + jr CantUseItemMessage + +BelongsToSomeoneElseMessage: + ld hl, ItemBelongsToSomeoneElseText + jr CantUseItemMessage + +CyclingIsntAllowedMessage: + ld hl, NoCyclingText + jr CantUseItemMessage + +CantGetOnYourBikeMessage: + ld hl, ItemCantGetOnText + +CantUseItemMessage: +; Item couldn't be used. + xor a + ld [wItemEffectSucceeded], a + jp PrintText + +ItemLooksBitterText: + text_far _ItemLooksBitterText + text_end + +ItemCantUseOnEggText: + text_far _ItemCantUseOnEggText + text_end + +ItemOakWarningText: + text_far _ItemOakWarningText + text_end + +ItemBelongsToSomeoneElseText: + text_far _ItemBelongsToSomeoneElseText + text_end + +ItemWontHaveEffectText: + text_far _ItemWontHaveEffectText + text_end + +BallBlockedText: + text_far _BallBlockedText + text_end + +BallDontBeAThiefText: + text_far _BallDontBeAThiefText + text_end + +NoCyclingText: + text_far _NoCyclingText + text_end + +ItemCantGetOnText: + text_far _ItemCantGetOnText + text_end + +BallBoxFullText: + text_far _BallBoxFullText + text_end + +ItemUsedText: + text_far _ItemUsedText + text_end + +ItemGotOnText: + text_far _ItemGotOnText + text_end + +ItemGotOffText: + text_far _ItemGotOffText + text_end + +ApplyPPUp: + ld a, MON_MOVES + call GetPartyParamLocation + push hl + ld de, wBuffer1 + predef FillPP + pop hl + ld bc, MON_PP - MON_MOVES + add hl, bc + ld de, wBuffer1 + ld b, 0 +.loop + inc b + ld a, b + cp NUM_MOVES + 1 + ret z + ld a, [wUsePPUp] + dec a ; FALSE? + jr nz, .use + ld a, [wMenuCursorY] + inc a + cp b + jr nz, .skip + +.use + ld a, [hl] + and PP_UP_MASK + ld a, [de] ; wasted cycle + call nz, ComputeMaxPP + +.skip + inc hl + inc de + jr .loop + +ComputeMaxPP: + push bc + ; Divide the base PP by 5. + ld a, [de] + ldh [hDividend + 3], a + xor a + ldh [hDividend], a + ldh [hDividend + 1], a + ldh [hDividend + 2], a + ld a, 5 + ldh [hDivisor], a + ld b, 4 + call Divide + ; Get the number of PP, which are bits 6 and 7 of the PP value stored in RAM. + ld a, [hl] + ld b, a + swap a + and $f + srl a + srl a + ld c, a + ; If this value is 0, we are done + and a + jr z, .NoPPUp + +.loop + ; Normally, a move with 40 PP would have 64 PP with three PP Ups. + ; Since this would overflow into bit 6, we prevent that from happening + ; by decreasing the extra amount of PP each PP Up provides, resulting + ; in a maximum of 61. + ldh a, [hQuotient + 3] + cp $8 + jr c, .okay + ld a, $7 + +.okay + add b + ld b, a + ld a, [wTempPP] + dec a + jr z, .NoPPUp + dec c + jr nz, .loop + +.NoPPUp: + ld [hl], b + pop bc + ret + +RestoreAllPP: + ld a, MON_PP + call GetPartyParamLocation + push hl + ld a, MON_MOVES + call GetPartyParamLocation + pop de + xor a ; PARTYMON + ld [wMenuCursorY], a + ld [wMonType], a + ld c, NUM_MOVES +.loop + ld a, [hli] + and a + ret z + push hl + push de + push bc + call GetMaxPPOfMove + pop bc + pop de + ld a, [de] + and PP_UP_MASK + ld b, a + ld a, [wTempPP] + add b + ld [de], a + inc de + ld hl, wMenuCursorY + inc [hl] + pop hl + dec c + jr nz, .loop + ret + +GetMaxPPOfMove: + ld a, [wStringBuffer1 + 0] + push af + ld a, [wStringBuffer1 + 1] + push af + + ld a, [wMonType] + and a + + ld hl, wPartyMon1Moves + ld bc, PARTYMON_STRUCT_LENGTH + jr z, .got_partymon ; PARTYMON + + ld hl, wOTPartyMon1Moves + dec a + jr z, .got_partymon ; OTPARTYMON + + ld hl, wTempMonMoves + dec a + jr z, .got_nonpartymon ; BOXMON + + ld hl, wTempMonMoves ; Wasted cycles + dec a + jr z, .got_nonpartymon ; TEMPMON + + ld hl, wBattleMonMoves ; WILDMON + +.got_nonpartymon ; BOXMON, TEMPMON, WILDMON + call GetMthMoveOfCurrentMon + jr .gotdatmove + +.got_partymon ; PARTYMON, OTPARTYMON + call GetMthMoveOfNthPartymon + +.gotdatmove + ld a, [hl] + dec a + + push hl + ld hl, Moves + MOVE_PP + ld bc, MOVE_LENGTH + call AddNTimes + ld a, BANK(Moves) + call GetFarByte + ld b, a + ld de, wStringBuffer1 + ld [de], a + pop hl + + push bc + ld bc, MON_PP - MON_MOVES + ld a, [wMonType] + cp WILDMON + jr nz, .notwild + ld bc, wEnemyMonPP - wEnemyMonMoves +.notwild + add hl, bc + ld a, [hl] + and PP_UP_MASK + pop bc + + or b + ld hl, wStringBuffer1 + 1 + ld [hl], a + xor a + ld [wTempPP], a + ld a, b ; this gets lost anyway + call ComputeMaxPP + ld a, [hl] + and PP_MASK + ld [wTempPP], a + + pop af + ld [wStringBuffer1 + 1], a + pop af + ld [wStringBuffer1 + 0], a + ret + +GetMthMoveOfNthPartymon: + ld a, [wCurPartyMon] + call AddNTimes + +GetMthMoveOfCurrentMon: + ld a, [wMenuCursorY] + ld c, a + ld b, 0 + add hl, bc + ret diff --git a/engine/items/items.asm b/engine/items/items.asm new file mode 100755 index 00000000..ef0f10dd --- /dev/null +++ b/engine/items/items.asm @@ -0,0 +1,581 @@ +_ReceiveItem:: + call DoesHLEqualNumItems + jp nz, PutItemInPocket + push hl + call CheckItemPocket + pop de + ld a, [wItemAttributeParamBuffer] + dec a + ld hl, .Pockets + rst JumpTable + ret + +.Pockets: +; entries correspond to item types + dw .Item + dw .KeyItem + dw .Ball + dw .TMHM + +.Item: + ld h, d + ld l, e + jp PutItemInPocket + +.KeyItem: + ld h, d + ld l, e + jp ReceiveKeyItem + +.Ball: + ld hl, wNumBalls + jp PutItemInPocket + +.TMHM: + ld h, d + ld l, e + ld a, [wCurItem] + ld c, a + call GetTMHMNumber + jp ReceiveTMHM + +_TossItem:: + call DoesHLEqualNumItems + jr nz, .remove + push hl + call CheckItemPocket + pop de + ld a, [wItemAttributeParamBuffer] + dec a + ld hl, .Pockets + rst JumpTable + ret + +.Pockets: +; entries correspond to item types + dw .Item + dw .KeyItem + dw .Ball + dw .TMHM + +.Ball: + ld hl, wNumBalls + jp RemoveItemFromPocket + +.TMHM: + ld h, d + ld l, e + ld a, [wCurItem] + ld c, a + call GetTMHMNumber + jp TossTMHM + +.KeyItem: + ld h, d + ld l, e + jp TossKeyItem + +.Item: + ld h, d + ld l, e + +.remove + jp RemoveItemFromPocket + +_CheckItem:: + call DoesHLEqualNumItems + jr nz, .nope + push hl + call CheckItemPocket + pop de + ld a, [wItemAttributeParamBuffer] + dec a + ld hl, .Pockets + rst JumpTable + ret + +.Pockets: +; entries correspond to item types + dw .Item + dw .KeyItem + dw .Ball + dw .TMHM + +.Ball: + ld hl, wNumBalls + jp CheckTheItem + +.TMHM: + ld h, d + ld l, e + ld a, [wCurItem] + ld c, a + call GetTMHMNumber + jp CheckTMHM + +.KeyItem: + ld h, d + ld l, e + jp CheckKeyItems + +.Item: + ld h, d + ld l, e + +.nope + jp CheckTheItem + +DoesHLEqualNumItems: + ld a, l + cp LOW(wNumItems) + ret nz + ld a, h + cp HIGH(wNumItems) + ret + +GetPocketCapacity: + ld c, MAX_ITEMS + ld a, e + cp LOW(wNumItems) + jr nz, .not_bag + ld a, d + cp HIGH(wNumItems) + ret z + +.not_bag + ld c, MAX_PC_ITEMS + ld a, e + cp LOW(wNumPCItems) + jr nz, .not_pc + ld a, d + cp HIGH(wNumPCItems) + ret z + +.not_pc + ld c, MAX_BALLS + ret + +PutItemInPocket: + ld d, h + ld e, l + inc hl + ld a, [wCurItem] + ld c, a + ld b, 0 +.loop + ld a, [hli] + cp -1 + jr z, .terminator + cp c + jr nz, .next + ld a, 99 + sub [hl] + add b + ld b, a + ld a, [wItemQuantityChangeBuffer] + cp b + jr z, .ok + jr c, .ok + +.next + inc hl + jr .loop + +.terminator + call GetPocketCapacity + ld a, [de] + cp c + jr c, .ok + and a + ret + +.ok + ld h, d + ld l, e + ld a, [wCurItem] + ld c, a + ld a, [wItemQuantityChangeBuffer] + ld [wItemQuantityBuffer], a +.loop2 + inc hl + ld a, [hli] + cp -1 + jr z, .terminator2 + cp c + jr nz, .loop2 + ld a, [wItemQuantityBuffer] + add [hl] + cp 100 + jr nc, .newstack + ld [hl], a + jr .done + +.newstack + ld [hl], 99 + sub 99 + ld [wItemQuantityBuffer], a + jr .loop2 + +.terminator2 + dec hl + ld a, [wCurItem] + ld [hli], a + ld a, [wItemQuantityBuffer] + ld [hli], a + ld [hl], -1 + ld h, d + ld l, e + inc [hl] + +.done + scf + ret + +RemoveItemFromPocket: + ld d, h + ld e, l + ld a, [hli] + ld c, a + ld a, [wCurItemQuantity] + cp c + jr nc, .ok ; memory + ld c, a + ld b, $0 + add hl, bc + add hl, bc + ld a, [wCurItem] + cp [hl] + inc hl + jr z, .skip + ld h, d + ld l, e + inc hl + +.ok + ld a, [wCurItem] + ld b, a +.loop + ld a, [hli] + cp b + jr z, .skip + cp -1 + jr z, .nope + inc hl + jr .loop + +.skip + ld a, [wItemQuantityChangeBuffer] + ld b, a + ld a, [hl] + sub b + jr c, .nope + ld [hl], a + ld [wItemQuantityBuffer], a + and a + jr nz, .yup + dec hl + ld b, h + ld c, l + inc hl + inc hl +.loop2 + ld a, [hli] + ld [bc], a + inc bc + cp -1 + jr nz, .loop2 + ld h, d + ld l, e + dec [hl] + +.yup + scf + ret + +.nope + and a + ret + +CheckTheItem: + ld a, [wCurItem] + ld c, a +.loop + inc hl + ld a, [hli] + cp -1 + jr z, .done + cp c + jr nz, .loop + scf + ret + +.done + and a + ret + +ReceiveKeyItem: + ld hl, wNumKeyItems + ld a, [hli] + cp MAX_KEY_ITEMS + jr nc, .nope + ld c, a + ld b, 0 + add hl, bc + ld a, [wCurItem] + ld [hli], a + ld [hl], -1 + ld hl, wNumKeyItems + inc [hl] + scf + ret + +.nope + and a + ret + +TossKeyItem: + ld a, [wCurItemQuantity] + ld e, a + ld d, 0 + ld hl, wNumKeyItems + ld a, [hl] + cp e + jr nc, .ok + call .Toss + ret nc + jr .ok2 + +.ok + dec [hl] + inc hl + add hl, de + +.ok2 + ld d, h + ld e, l + inc hl +.loop + ld a, [hli] + ld [de], a + inc de + cp -1 + jr nz, .loop + scf + ret + +.Toss: + ld hl, wNumKeyItems + ld a, [wCurItem] + ld c, a +.loop3 + inc hl + ld a, [hl] + cp c + jr z, .ok3 + cp -1 + jr nz, .loop3 + xor a + ret + +.ok3 + ld a, [wNumKeyItems] + dec a + ld [wNumKeyItems], a + scf + ret + +CheckKeyItems: + ld a, [wCurItem] + ld c, a + ld hl, wKeyItems +.loop + ld a, [hli] + cp c + jr z, .done + cp -1 + jr nz, .loop + and a + ret + +.done + scf + ret + +ReceiveTMHM: + dec c + ld b, 0 + ld hl, wTMsHMs + add hl, bc + ld a, [wItemQuantityChangeBuffer] + add [hl] + cp 100 + jr nc, .toomany + ld [hl], a + scf + ret + +.toomany + and a + ret + +TossTMHM: + dec c + ld b, 0 + ld hl, wTMsHMs + add hl, bc + ld a, [wItemQuantityChangeBuffer] + ld b, a + ld a, [hl] + sub b + jr c, .nope + ld [hl], a + ld [wItemQuantityBuffer], a + jr nz, .yup + ld a, [wTMHMPocketScrollPosition] + and a + jr z, .yup + dec a + ld [wTMHMPocketScrollPosition], a + +.yup + scf + ret + +.nope + and a + ret + +CheckTMHM: + dec c + ld b, $0 + ld hl, wTMsHMs + add hl, bc + ld a, [hl] + and a + ret z + scf + ret + +GetTMHMNumber:: +; Return the number of a TM/HM by item id c. + ld a, c +; Skip any dummy items. + cp ITEM_C3 ; TM04-05 + jr c, .done + cp ITEM_DC ; TM28-29 + jr c, .skip + dec a +.skip + dec a +.done + sub TM01 + inc a + ld c, a + ret + +GetNumberedTMHM: +; Return the item id of a TM/HM by number c. + ld a, c +; Skip any gaps. + cp ITEM_C3 - (TM01 - 1) + jr c, .done + cp ITEM_DC - (TM01 - 1) - 1 + jr c, .skip_one +.skip_two + inc a +.skip_one + inc a +.done + add TM01 + dec a + ld c, a + ret + +_CheckTossableItem:: +; Return 1 in wItemAttributeParamBuffer and carry if wCurItem can't be removed from the bag. + ld a, ITEMATTR_PERMISSIONS + call GetItemAttr + bit CANT_TOSS_F, a + jr nz, ItemAttr_ReturnCarry + and a + ret + +CheckSelectableItem: +; Return 1 in wItemAttributeParamBuffer and carry if wCurItem can't be selected. + ld a, ITEMATTR_PERMISSIONS + call GetItemAttr + bit CANT_SELECT_F, a + jr nz, ItemAttr_ReturnCarry + and a + ret + +CheckItemPocket:: +; Return the pocket for wCurItem in wItemAttributeParamBuffer. + ld a, ITEMATTR_POCKET + call GetItemAttr + and $f + ld [wItemAttributeParamBuffer], a + ret + +CheckItemContext: +; Return the context for wCurItem in wItemAttributeParamBuffer. + ld a, ITEMATTR_HELP + call GetItemAttr + and $f + ld [wItemAttributeParamBuffer], a + ret + +CheckItemMenu: +; Return the menu for wCurItem in wItemAttributeParamBuffer. + ld a, ITEMATTR_HELP + call GetItemAttr + swap a + and $f + ld [wItemAttributeParamBuffer], a + ret + +GetItemAttr: +; Get attribute a of wCurItem. + + push hl + push bc + + ld hl, ItemAttributes + ld c, a + ld b, 0 + add hl, bc + + xor a + ld [wItemAttributeParamBuffer], a + + ld a, [wCurItem] + dec a + ld c, a + ld a, ITEMATTR_STRUCT_LENGTH + call AddNTimes + ld a, BANK(ItemAttributes) + call GetFarByte + + pop bc + pop hl + ret + +ItemAttr_ReturnCarry: + ld a, 1 + ld [wItemAttributeParamBuffer], a + scf + ret + +GetItemPrice: +; Return the price of wCurItem in de. + push hl + push bc + ld a, ITEMATTR_PRICE + call GetItemAttr + ld e, a + ld a, ITEMATTR_PRICE_HI + call GetItemAttr + ld d, a + pop bc + pop hl + ret diff --git a/engine/items/mart.asm b/engine/items/mart.asm new file mode 100644 index 00000000..3978ef33 --- /dev/null +++ b/engine/items/mart.asm @@ -0,0 +1,811 @@ + const_def + const MARTTEXT_HOW_MANY + const MARTTEXT_COSTS_THIS_MUCH + const MARTTEXT_NOT_ENOUGH_MONEY + const MARTTEXT_BAG_FULL + const MARTTEXT_HERE_YOU_GO + const MARTTEXT_SOLD_OUT + +GetMart: + ld a, e + cp (Marts.End - Marts) / 2 + jr c, .IsAMart + ld b, BANK(DefaultMart) + ld de, DefaultMart + ret + +.IsAMart: + ld hl, Marts + add hl, de + add hl, de + ld e, [hl] + inc hl + ld d, [hl] + ld b, BANK(Marts) + ret + +OpenMartDialog:: + call GetMart + ld a, c + ld [wMartType], a + call LoadMartPointer + ld a, [wMartType] + ld hl, .dialogs + rst JumpTable + ret + +.dialogs + dw MartDialog + dw HerbShop + dw BargainShop + dw Pharmacist + +MartDialog: + ld a, MARTTYPE_STANDARD + ld [wMartType], a + xor a ; STANDARDMART_HOWMAYIHELPYOU + ld [wMartJumptableIndex], a + call StandardMart + ret + +HerbShop: + call FarReadMart + call LoadStandardMenuHeader + ld hl, HerbShopLadyIntroText + call MartTextbox + call BuyMenu + ld hl, HerbalLadyComeAgainText + call MartTextbox + ret + +BargainShop: + ld b, BANK(BargainShopData) + ld de, BargainShopData + call LoadMartPointer + call ReadMart + call LoadStandardMenuHeader + ld hl, BargainShopIntroText + call MartTextbox + call BuyMenu + ld hl, wBargainShopFlags + ld a, [hli] + or [hl] + jr z, .skip_set + ld hl, wDailyFlags1 + set DAILYFLAGS1_GOLDENROD_UNDERGROUND_BARGAIN_F, [hl] + +.skip_set + ld hl, BargainShopComeAgainText + call MartTextbox + ret + +Pharmacist: + call FarReadMart + call LoadStandardMenuHeader + ld hl, PharmacyIntroText + call MartTextbox + call BuyMenu + ld hl, PharmacyComeAgainText + call MartTextbox + ret + +LoadMartPointer: + ld a, b + ld [wMartPointerBank], a + ld a, e + ld [wMartPointer], a + ld a, d + ld [wMartPointer + 1], a + ld hl, wCurMart + xor a + ld bc, wCurMartEnd - wCurMart + call ByteFill + xor a ; STANDARDMART_HOWMAYIHELPYOU + ld [wMartJumptableIndex], a + ld [wBargainShopFlags], a + ld [wFacingDirection], a + ret + +; StandardMart.MartFunctions indexes + const_def + const STANDARDMART_HOWMAYIHELPYOU ; 0 + const STANDARDMART_TOPMENU ; 1 + const STANDARDMART_BUY ; 2 + const STANDARDMART_SELL ; 3 + const STANDARDMART_QUIT ; 4 + const STANDARDMART_ANYTHINGELSE ; 5 + +STANDARDMART_EXIT EQU -1 + +StandardMart: +.loop + ld a, [wMartJumptableIndex] + ld hl, .MartFunctions + rst JumpTable + ld [wMartJumptableIndex], a + cp STANDARDMART_EXIT + jr nz, .loop + ret + +.MartFunctions: +; entries correspond to STANDARDMART_* constants + dw .HowMayIHelpYou + dw .TopMenu + dw .Buy + dw .Sell + dw .Quit + dw .AnythingElse + +.HowMayIHelpYou: + call LoadStandardMenuHeader + ld hl, MartWelcomeText + call PrintText + ld a, STANDARDMART_TOPMENU + ret + +.TopMenu: + ld hl, MenuHeader_BuySell + call CopyMenuHeader + call VerticalMenu + jr c, .quit + ld a, [wMenuCursorY] + cp $1 + jr z, .buy + cp $2 + jr z, .sell +.quit + ld a, STANDARDMART_QUIT + ret +.buy + ld a, STANDARDMART_BUY + ret +.sell + ld a, STANDARDMART_SELL + ret + +.Buy: + call ExitMenu + call FarReadMart + call BuyMenu + and a + ld a, STANDARDMART_ANYTHINGELSE + ret + +.Sell: + call ExitMenu + call SellMenu + ld a, STANDARDMART_ANYTHINGELSE + ret + +.Quit: + call ExitMenu + ld hl, MartComeAgainText + call MartTextbox + ld a, STANDARDMART_EXIT + ret + +.AnythingElse: + call LoadStandardMenuHeader + ld hl, MartAskMoreText + call PrintText + ld a, STANDARDMART_TOPMENU + ret + +FarReadMart: + ld hl, wMartPointer + ld a, [hli] + ld h, [hl] + ld l, a + ld de, wCurMart +.CopyMart: + ld a, [wMartPointerBank] + call GetFarByte + ld [de], a + inc hl + inc de + cp -1 + jr nz, .CopyMart + ld hl, wMartItem1BCD + ld de, wCurMart + 1 +.ReadMartItem: + ld a, [de] + inc de + cp -1 + jr z, .done + push de + call GetMartItemPrice + pop de + jr .ReadMartItem + +.done + ret + +GetMartItemPrice: +; Return the price of item a in BCD at hl and in tiles at wStringBuffer1. + push hl + ld [wCurItem], a + farcall GetItemPrice + pop hl + +GetMartPrice: +; Return price de in BCD at hl and in tiles at wStringBuffer1. + push hl + ld a, d + ld [wStringBuffer2], a + ld a, e + ld [wStringBuffer2 + 1], a + ld hl, wStringBuffer1 + ld de, wStringBuffer2 + lb bc, PRINTNUM_LEADINGZEROS | 2, 6 ; 6 digits + call PrintNum + pop hl + + ld de, wStringBuffer1 + ld c, 6 / 2 ; 6 digits +.loop + call .CharToNybble + swap a + ld b, a + call .CharToNybble + or b + ld [hli], a + dec c + jr nz, .loop + ret + +.CharToNybble: + ld a, [de] + inc de + cp " " + jr nz, .not_space + ld a, "0" + +.not_space + sub "0" + ret + +ReadMart: +; Load the mart pointer. Mart data is local (no need for bank). + ld hl, wMartPointer + ld a, [hli] + ld h, [hl] + ld l, a + push hl +; set hl to the first item + inc hl + ld bc, wMartItem1BCD + ld de, wCurMart + 1 +.loop +; copy the item to wCurMart + (ItemIndex) + ld a, [hli] + ld [de], a + inc de +; -1 is the terminator + cp -1 + jr z, .done + + push de +; copy the price to de + ld a, [hli] + ld e, a + ld a, [hli] + ld d, a +; convert the price to 3-byte BCD at [bc] + push hl + ld h, b + ld l, c + call GetMartPrice + ld b, h + ld c, l + pop hl + + pop de + jr .loop + +.done + pop hl + ld a, [hl] + ld [wCurMart], a + ret + +INCLUDE "data/items/bargain_shop.asm" + +BuyMenu: + call FadeToMenu + farcall BlankScreen + xor a + ld [wMenuScrollPositionBackup], a + ld a, 1 + ld [wMenuCursorBufferBackup], a +.loop + call BuyMenuLoop ; menu loop + jr nc, .loop + call CloseSubmenu + ret + +LoadBuyMenuText: +; load text from a nested table +; which table is in wMartType +; which entry is in register a + push af + call GetMartDialogGroup ; gets a pointer from GetMartDialogGroup.MartTextFunctionPointers + ld a, [hli] + ld h, [hl] + ld l, a + pop af + ld e, a + ld d, 0 + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + call PrintText + ret + +MartAskPurchaseQuantity: + call GetMartDialogGroup ; gets a pointer from GetMartDialogGroup.MartTextFunctionPointers + inc hl + inc hl + ld a, [hl] + and a + jp z, StandardMartAskPurchaseQuantity + jp BargainShopAskPurchaseQuantity + +GetMartDialogGroup: + ld a, [wMartType] + ld e, a + ld d, 0 + ld hl, .MartTextFunctionPointers + add hl, de + add hl, de + add hl, de + ret + +.MartTextFunctionPointers: + dwb .StandardMartPointers, 0 + dwb .HerbShopPointers, 0 + dwb .BargainShopPointers, 1 + dwb .PharmacyPointers, 0 + +.StandardMartPointers: + dw MartHowManyText + dw MartFinalPriceText + dw MartNoMoneyText + dw MartPackFullText + dw MartThanksText + dw BuyMenuLoop + +.HerbShopPointers: + dw HerbalLadyHowManyText + dw HerbalLadyFinalPriceText + dw HerbalLadyNoMoneyText + dw HerbalLadyPackFullText + dw HerbalLadyThanksText + dw BuyMenuLoop + +.BargainShopPointers: + dw BuyMenuLoop + dw BargainShopFinalPriceText + dw BargainShopNoFundsText + dw BargainShopPackFullText + dw BargainShopThanksText + dw BargainShopSoldOutText + +.PharmacyPointers: + dw PharmacyHowManyText + dw PharmacyFinalPriceText + dw PharmacyNoMoneyText + dw PharmacyPackFullText + dw PharmacyThanksText + dw BuyMenuLoop + +BuyMenuLoop: + farcall PlaceMoneyTopRight + call UpdateSprites + ld hl, MenuHeader_Buy + call CopyMenuHeader + ld a, [wMenuCursorBufferBackup] + ld [wMenuCursorBuffer], a + ld a, [wMenuScrollPositionBackup] + ld [wMenuScrollPosition], a + call ScrollingMenu + ld a, [wMenuScrollPosition] + ld [wMenuScrollPositionBackup], a + ld a, [wMenuCursorY] + ld [wMenuCursorBufferBackup], a + call SpeechTextbox + ld a, [wMenuJoypad] + cp B_BUTTON + jr z, .set_carry + cp A_BUTTON + jr z, .useless_pointer + +.useless_pointer + call MartAskPurchaseQuantity + jr c, .cancel + call MartConfirmPurchase + jr c, .cancel + ld de, wMoney + ld bc, hMoneyTemp + ld a, 3 ; useless load + call CompareMoney + jr c, .insufficient_funds + ld hl, wNumItems + call ReceiveItem + jr nc, .insufficient_bag_space + ld a, [wMartItemID] + ld e, a + ld d, 0 + ld b, SET_FLAG + ld hl, wBargainShopFlags + call FlagAction + call PlayTransactionSound + ld de, wMoney + ld bc, hMoneyTemp + call TakeMoney + ld a, MARTTEXT_HERE_YOU_GO + call LoadBuyMenuText + call JoyWaitAorB + +.cancel + call SpeechTextbox + and a + ret + +.set_carry + scf + ret + +.insufficient_bag_space + ld a, MARTTEXT_BAG_FULL + call LoadBuyMenuText + call JoyWaitAorB + and a + ret + +.insufficient_funds + ld a, MARTTEXT_NOT_ENOUGH_MONEY + call LoadBuyMenuText + call JoyWaitAorB + and a + ret + +StandardMartAskPurchaseQuantity: + ld a, 99 + ld [wItemQuantityBuffer], a + ld a, MARTTEXT_HOW_MANY + call LoadBuyMenuText + farcall SelectQuantityToBuy + call ExitMenu + ret + +MartConfirmPurchase: + predef PartyMonItemName + ld a, MARTTEXT_COSTS_THIS_MUCH + call LoadBuyMenuText + call YesNoBox + ret + +BargainShopAskPurchaseQuantity: + ld a, 1 + ld [wItemQuantityChangeBuffer], a + ld a, [wMartItemID] + ld e, a + ld d, 0 + ld b, CHECK_FLAG + ld hl, wBargainShopFlags + call FlagAction + ld a, c + and a + jr nz, .SoldOut + ld a, [wMartItemID] + ld e, a + ld d, 0 + ld hl, wMartPointer + ld a, [hli] + ld h, [hl] + ld l, a + inc hl + add hl, de + add hl, de + add hl, de + inc hl + ld a, [hli] + ldh [hMoneyTemp + 2], a + ld a, [hl] + ldh [hMoneyTemp + 1], a + xor a + ldh [hMoneyTemp], a + and a + ret + +.SoldOut: + ld a, MARTTEXT_SOLD_OUT + call LoadBuyMenuText + call JoyWaitAorB + scf + ret + +MartHowManyText: + text_far _MartHowManyText + text_end + +MartFinalPriceText: + text_far _MartFinalPriceText + text_end + +MenuHeader_Buy: + db MENU_BACKUP_TILES ; flags + menu_coords 1, 3, SCREEN_WIDTH - 1, TEXTBOX_Y - 1 + dw .MenuData + db 1 ; default option + +.MenuData + db SCROLLINGMENU_DISPLAY_ARROWS | SCROLLINGMENU_ENABLE_FUNCTION3 ; flags + db 4, 8 ; rows, columns + db SCROLLINGMENU_ITEMS_NORMAL ; item format + dbw 0, wCurMart + dba PlaceMenuItemName + dba .PrintBCDPrices + dba UpdateItemDescription + +.PrintBCDPrices: + ld a, [wScrollingMenuCursorPosition] + ld c, a + ld b, 0 + ld hl, wMartItem1BCD + add hl, bc + add hl, bc + add hl, bc + push de + ld d, h + ld e, l + pop hl + ld bc, SCREEN_WIDTH + add hl, bc + ld c, PRINTNUM_LEADINGZEROS | PRINTNUM_MONEY | 3 + call PrintBCDNumber + ret + +HerbShopLadyIntroText: + text_far _HerbShopLadyIntroText + text_end + +HerbalLadyHowManyText: + text_far _HerbalLadyHowManyText + text_end + +HerbalLadyFinalPriceText: + text_far _HerbalLadyFinalPriceText + text_end + +HerbalLadyThanksText: + text_far _HerbalLadyThanksText + text_end + +HerbalLadyPackFullText: + text_far _HerbalLadyPackFullText + text_end + +HerbalLadyNoMoneyText: + text_far _HerbalLadyNoMoneyText + text_end + +HerbalLadyComeAgainText: + text_far _HerbalLadyComeAgainText + text_end + +BargainShopIntroText: + text_far _BargainShopIntroText + text_end + +BargainShopFinalPriceText: + text_far _BargainShopFinalPriceText + text_end + +BargainShopThanksText: + text_far _BargainShopThanksText + text_end + +BargainShopPackFullText: + text_far _BargainShopPackFullText + text_end + +BargainShopSoldOutText: + text_far _BargainShopSoldOutText + text_end + +BargainShopNoFundsText: + text_far _BargainShopNoFundsText + text_end + +BargainShopComeAgainText: + text_far _BargainShopComeAgainText + text_end + +PharmacyIntroText: + text_far _PharmacyIntroText + text_end + +PharmacyHowManyText: + text_far _PharmacyHowManyText + text_end + +PharmacyFinalPriceText: + text_far _PharmacyFinalPriceText + text_end + +PharmacyThanksText: + text_far _PharmacyThanksText + text_end + +PharmacyPackFullText: + text_far _PharmacyPackFullText + text_end + +PharmacyNoMoneyText: + text_far _PharmacyNoMoneyText + text_end + +PharmacyComeAgainText: + text_far _PharmacyComeAgainText + text_end + +SellMenu: + call DisableSpriteUpdates + farcall DepositSellInitPackBuffers +.loop + farcall DepositSellPack + ld a, [wPackUsedItem] + and a + jp z, .quit + call .TryToSellItem + jr .loop + +.quit + call ReturnToMapWithSpeechTextbox + and a + ret + +.Unreferenced_NothingToSell: + ld hl, .NothingToSellText + call MenuTextboxBackup + and a + ret + +.NothingToSellText: + text_far _NothingToSellText + text_end + +.TryToSellItem: + farcall CheckItemMenu + ld a, [wItemAttributeParamBuffer] + ld hl, .dw + rst JumpTable + ret + +.dw + dw .try_sell + dw .cant_buy + dw .cant_buy + dw .cant_buy + dw .try_sell + dw .try_sell + dw .try_sell + +.cant_buy + ret + +.try_sell + farcall _CheckTossableItem + ld a, [wItemAttributeParamBuffer] + and a + jr z, .okay_to_sell + ld hl, MartCantBuyText + call PrintText + and a + ret + +.okay_to_sell + ld hl, MartSellHowManyText + call PrintText + farcall PlaceMoneyAtTopLeftOfTextbox + farcall SelectQuantityToSell + call ExitMenu + jr c, .declined + hlcoord 1, 14 + lb bc, 3, 18 + call ClearBox + ld hl, MartSellPriceText + call PrintTextboxText + call YesNoBox + jr c, .declined + ld de, wMoney + ld bc, hMoneyTemp + call GiveMoney + ld a, [wMartItemID] + ld hl, wNumItems + call TossItem + predef PartyMonItemName + hlcoord 1, 14 + lb bc, 3, 18 + call ClearBox + ld hl, MartBoughtText + call PrintTextboxText + call PlayTransactionSound + farcall PlaceMoneyBottomLeft + call JoyWaitAorB + +.declined + call ExitMenu + and a + ret + +MartSellHowManyText: + text_far _MartSellHowManyText + text_end + +MartSellPriceText: + text_far _MartSellPriceText + text_end + +.UnusedString161d2: + db "!ダミー!@" + +MartWelcomeText: + text_far _MartWelcomeText + text_end + +MenuHeader_BuySell: + db MENU_BACKUP_TILES ; flags + menu_coords 0, 0, 11, 8 + dw .MenuData + db 1 ; default option + +.MenuData + db STATICMENU_CURSOR ; strings + db 3 ; items + db "BUY@" + db "SELL@" + db "QUIT@" + +MartThanksText: + text_far _MartThanksText + text_end + +MartNoMoneyText: + text_far _MartNoMoneyText + text_end + +MartPackFullText: + text_far _MartPackFullText + text_end + +MartCantBuyText: + text_far _MartCantBuyText + text_end + +MartComeAgainText: + text_far _MartComeAgainText + text_end + +MartAskMoreText: + text_far _MartAskMoreText + text_end + +MartBoughtText: + text_far _MartBoughtText + text_end + +PlayTransactionSound: + call WaitSFX + ld de, SFX_TRANSACTION + call PlaySFX + ret + +MartTextbox: + call MenuTextbox + call JoyWaitAorB + call ExitMenu + ret diff --git a/engine/items/pack.asm b/engine/items/pack.asm new file mode 100755 index 00000000..e7caceca --- /dev/null +++ b/engine/items/pack.asm @@ -0,0 +1,1584 @@ +; Pack.Jumptable and BattlePack.Jumptable indexes + const_def + const PACKSTATE_INITGFX ; 0 + const PACKSTATE_INITITEMSPOCKET ; 1 + const PACKSTATE_ITEMSPOCKETMENU ; 2 + const PACKSTATE_INITBALLSPOCKET ; 3 + const PACKSTATE_BALLSPOCKETMENU ; 4 + const PACKSTATE_INITKEYITEMSPOCKET ; 5 + const PACKSTATE_KEYITEMSPOCKETMENU ; 6 + const PACKSTATE_INITTMHMPOCKET ; 7 + const PACKSTATE_TMHMPOCKETMENU ; 8 + const PACKSTATE_QUITNOSCRIPT ; 9 + const PACKSTATE_QUITRUNSCRIPT ; 10 + +Pack: + ld hl, wOptions + set NO_TEXT_SCROLL, [hl] + call InitPackBuffers +.loop + call JoyTextDelay + ld a, [wJumptableIndex] + bit 7, a + jr nz, .done + call .RunJumptable + call DelayFrame + jr .loop + +.done + ld a, [wCurPocket] + ld [wLastPocket], a + ld hl, wOptions + res NO_TEXT_SCROLL, [hl] + ret + +.RunJumptable: + ld a, [wJumptableIndex] + ld hl, .Jumptable + call Pack_GetJumptablePointer + jp hl + +.Jumptable: +; entries correspond to PACKSTATE_* constants + dw .InitGFX ; 0 + dw .InitItemsPocket ; 1 + dw .ItemsPocketMenu ; 2 + dw .InitBallsPocket ; 3 + dw .BallsPocketMenu ; 4 + dw .InitKeyItemsPocket ; 5 + dw .KeyItemsPocketMenu ; 6 + dw .InitTMHMPocket ; 7 + dw .TMHMPocketMenu ; 8 + dw Pack_QuitNoScript ; 9 + dw Pack_QuitRunScript ; 10 + +.InitGFX: + xor a + ldh [hBGMapMode], a + call Pack_InitGFX + ld a, [wPackJumptableIndex] + ld [wJumptableIndex], a + call Pack_InitColors + ret + +.InitItemsPocket: + xor a ; ITEM_POCKET + ld [wCurPocket], a + call ClearPocketList + call DrawPocketName + call WaitBGMap_DrawPackGFX + call Pack_JumptableNext + ret + +.ItemsPocketMenu: + ld hl, ItemsPocketMenuHeader + call CopyMenuHeader + ld a, [wItemsPocketCursor] + ld [wMenuCursorBuffer], a + ld a, [wItemsPocketScrollPosition] + ld [wMenuScrollPosition], a + call ScrollingMenu + ld a, [wMenuScrollPosition] + ld [wItemsPocketScrollPosition], a + ld a, [wMenuCursorY] + ld [wItemsPocketCursor], a + ld b, PACKSTATE_INITTMHMPOCKET ; left + ld c, PACKSTATE_INITBALLSPOCKET ; right + call Pack_InterpretJoypad + ret c + call .ItemBallsKey_LoadSubmenu + ret + +.InitKeyItemsPocket: + ld a, KEY_ITEM_POCKET + ld [wCurPocket], a + call ClearPocketList + call DrawPocketName + call WaitBGMap_DrawPackGFX + call Pack_JumptableNext + ret + +.KeyItemsPocketMenu: + ld hl, KeyItemsPocketMenuHeader + call CopyMenuHeader + ld a, [wKeyItemsPocketCursor] + ld [wMenuCursorBuffer], a + ld a, [wKeyItemsPocketScrollPosition] + ld [wMenuScrollPosition], a + call ScrollingMenu + ld a, [wMenuScrollPosition] + ld [wKeyItemsPocketScrollPosition], a + ld a, [wMenuCursorY] + ld [wKeyItemsPocketCursor], a + ld b, PACKSTATE_INITBALLSPOCKET ; left + ld c, PACKSTATE_INITTMHMPOCKET ; right + call Pack_InterpretJoypad + ret c + call .ItemBallsKey_LoadSubmenu + ret + +.InitTMHMPocket: + ld a, TM_HM_POCKET + ld [wCurPocket], a + call ClearPocketList + call DrawPocketName + xor a + ldh [hBGMapMode], a + call WaitBGMap_DrawPackGFX + call Pack_JumptableNext + ret + +.TMHMPocketMenu: + farcall TMHMPocket + ld b, PACKSTATE_INITKEYITEMSPOCKET ; left + ld c, PACKSTATE_INITITEMSPOCKET ; right + call Pack_InterpretJoypad + ret c + farcall _CheckTossableItem + ld a, [wItemAttributeParamBuffer] + and a + jr nz, .use_quit + ld hl, .MenuHeader2 + ld de, .Jumptable2 + jr .load_jump + +.use_quit + ld hl, .MenuHeader1 + ld de, .Jumptable1 +.load_jump + push de + call LoadMenuHeader + call VerticalMenu + call ExitMenu + pop hl + ret c + ld a, [wMenuCursorY] + dec a + call Pack_GetJumptablePointer + jp hl + +.MenuHeader1: + db MENU_BACKUP_TILES ; flags + menu_coords 0, 7, SCREEN_WIDTH - 14, TEXTBOX_Y - 1 + dw .MenuData_1 + db 1 ; default option + +.MenuData_1: + db STATICMENU_CURSOR | STATICMENU_NO_TOP_SPACING ; flags + db 2 ; items + db "USE@" + db "QUIT@" + +.Jumptable1: + dw .UseItem + dw QuitItemSubmenu + +.MenuHeader2: + db MENU_BACKUP_TILES ; flags + menu_coords 0, 5, SCREEN_WIDTH - 14, TEXTBOX_Y - 1 + dw .MenuData_2 + db 1 ; default option + +.MenuData_2: + db STATICMENU_CURSOR | STATICMENU_NO_TOP_SPACING ; flags + db 3 ; items + db "USE@" + db "GIVE@" + db "QUIT@" + +.Jumptable2: + dw .UseItem + dw GiveItem + dw QuitItemSubmenu + +.UseItem: + farcall AskTeachTMHM + ret c + farcall ChooseMonToLearnTMHM + jr c, .declined + ld hl, wOptions + ld a, [hl] + push af + res NO_TEXT_SCROLL, [hl] + farcall TeachTMHM + pop af + ld [wOptions], a +.declined + xor a + ldh [hBGMapMode], a + call Pack_InitGFX + call WaitBGMap_DrawPackGFX + call Pack_InitColors + ret + +.InitBallsPocket: + ld a, BALL_POCKET + ld [wCurPocket], a + call ClearPocketList + call DrawPocketName + call WaitBGMap_DrawPackGFX + call Pack_JumptableNext + ret + +.BallsPocketMenu: + ld hl, BallsPocketMenuHeader + call CopyMenuHeader + ld a, [wBallsPocketCursor] + ld [wMenuCursorBuffer], a + ld a, [wBallsPocketScrollPosition] + ld [wMenuScrollPosition], a + call ScrollingMenu + ld a, [wMenuScrollPosition] + ld [wBallsPocketScrollPosition], a + ld a, [wMenuCursorY] + ld [wBallsPocketCursor], a + ld b, PACKSTATE_INITITEMSPOCKET ; left + ld c, PACKSTATE_INITKEYITEMSPOCKET ; right + call Pack_InterpretJoypad + ret c + call .ItemBallsKey_LoadSubmenu + ret + +.ItemBallsKey_LoadSubmenu: + farcall _CheckTossableItem + ld a, [wItemAttributeParamBuffer] + and a + jr nz, .tossable + farcall CheckSelectableItem + ld a, [wItemAttributeParamBuffer] + and a + jr nz, .selectable + farcall CheckItemMenu + ld a, [wItemAttributeParamBuffer] + and a + jr nz, .usable + jr .unusable + +.selectable + farcall CheckItemMenu + ld a, [wItemAttributeParamBuffer] + and a + jr nz, .selectable_usable + jr .selectable_unusable + +.tossable + farcall CheckSelectableItem + ld a, [wItemAttributeParamBuffer] + and a + jr nz, .tossable_selectable + jr .tossable_unselectable + +.usable + ld hl, MenuHeader_UsableKeyItem + ld de, Jumptable_UseGiveTossRegisterQuit + jr .build_menu + +.selectable_usable + ld hl, MenuHeader_UsableItem + ld de, Jumptable_UseGiveTossQuit + jr .build_menu + +.tossable_selectable + ld hl, MenuHeader_UnusableItem + ld de, Jumptable_UseQuit + jr .build_menu + +.tossable_unselectable + ld hl, MenuHeader_UnusableKeyItem + ld de, Jumptable_UseRegisterQuit + jr .build_menu + +.unusable + ld hl, MenuHeader_HoldableKeyItem + ld de, Jumptable_GiveTossRegisterQuit + jr .build_menu + +.selectable_unusable + ld hl, MenuHeader_HoldableItem + ld de, Jumptable_GiveTossQuit +.build_menu + push de + call LoadMenuHeader + call VerticalMenu + call ExitMenu + pop hl + ret c + ld a, [wMenuCursorY] + dec a + call Pack_GetJumptablePointer + jp hl + +MenuHeader_UsableKeyItem: + db MENU_BACKUP_TILES ; flags + menu_coords 0, 2, SCREEN_WIDTH - 14, TEXTBOX_Y + dw .MenuData + db 1 ; default option + +.MenuData: + db STATICMENU_CURSOR | STATICMENU_NO_TOP_SPACING ; flags + db 5 ; items + db "USE@" + db "GIVE@" + db "TOSS@" + db "SEL@" + db "QUIT@" + +Jumptable_UseGiveTossRegisterQuit: + dw UseItem + dw GiveItem + dw TossMenu + dw RegisterItem + dw QuitItemSubmenu + +MenuHeader_UsableItem: + db MENU_BACKUP_TILES ; flags + menu_coords 0, 3, SCREEN_WIDTH - 14, TEXTBOX_Y - 1 + dw .MenuData + db 1 ; default option + +.MenuData: + db STATICMENU_CURSOR | STATICMENU_NO_TOP_SPACING ; flags + db 4 ; items + db "USE@" + db "GIVE@" + db "TOSS@" + db "QUIT@" + +Jumptable_UseGiveTossQuit: + dw UseItem + dw GiveItem + dw TossMenu + dw QuitItemSubmenu + +MenuHeader_UnusableItem: + db MENU_BACKUP_TILES ; flags + menu_coords 0, 7, SCREEN_WIDTH - 14, TEXTBOX_Y - 1 + dw .MenuData + db 1 ; default option + +.MenuData: + db STATICMENU_CURSOR | STATICMENU_NO_TOP_SPACING ; flags + db 2 ; items + db "USE@" + db "QUIT@" + +Jumptable_UseQuit: + dw UseItem + dw QuitItemSubmenu + +MenuHeader_UnusableKeyItem: + db MENU_BACKUP_TILES ; flags + menu_coords 0, 5, SCREEN_WIDTH - 14, TEXTBOX_Y - 1 + dw .MenuData + db 1 ; default option + +.MenuData: + db STATICMENU_CURSOR | STATICMENU_NO_TOP_SPACING ; flags + db 3 ; items + db "USE@" + db "SEL@" + db "QUIT@" + +Jumptable_UseRegisterQuit: + dw UseItem + dw RegisterItem + dw QuitItemSubmenu + +MenuHeader_HoldableKeyItem: + db MENU_BACKUP_TILES ; flags + menu_coords 0, 3, SCREEN_WIDTH - 14, TEXTBOX_Y - 1 + dw .MenuData + db 1 ; default option + +.MenuData: + db STATICMENU_CURSOR | STATICMENU_NO_TOP_SPACING ; flags + db 4 ; items + db "GIVE@" + db "TOSS@" + db "SEL@" + db "QUIT@" + +Jumptable_GiveTossRegisterQuit: + dw GiveItem + dw TossMenu + dw RegisterItem + dw QuitItemSubmenu + +MenuHeader_HoldableItem: + db MENU_BACKUP_TILES ; flags + menu_coords 0, 5, SCREEN_WIDTH - 14, TEXTBOX_Y - 1 + dw .MenuData + db 1 ; default option + +.MenuData: + db STATICMENU_CURSOR | STATICMENU_NO_TOP_SPACING ; flags + db 3 ; items + db "GIVE@" + db "TOSS@" + db "QUIT@" + +Jumptable_GiveTossQuit: + dw GiveItem + dw TossMenu + dw QuitItemSubmenu + +UseItem: + farcall CheckItemMenu + ld a, [wItemAttributeParamBuffer] + ld hl, .dw + rst JumpTable + ret + +.dw +; entries correspond to ITEMMENU_* constants + dw .Oak ; ITEMMENU_NOUSE + dw .Oak + dw .Oak + dw .Oak + dw .Current ; ITEMMENU_CURRENT + dw .Party ; ITEMMENU_PARTY + dw .Field ; ITEMMENU_CLOSE + +.Oak: + ld hl, OakThisIsntTheTimeText + call Pack_PrintTextNoScroll + ret + +.Current: + call DoItemEffect + ret + +.Party: + ld a, [wPartyCount] + and a + jr z, .NoPokemon + call DoItemEffect + xor a + ldh [hBGMapMode], a + call Pack_InitGFX + call WaitBGMap_DrawPackGFX + call Pack_InitColors + ret + +.NoPokemon: + ld hl, YouDontHaveAMonText + call Pack_PrintTextNoScroll + ret + +.Field: + call DoItemEffect + ld a, [wItemEffectSucceeded] + and a + jr z, .Oak + ld a, PACKSTATE_QUITRUNSCRIPT + ld [wJumptableIndex], a + ret + +TossMenu: + ld hl, AskThrowAwayText + call Pack_PrintTextNoScroll + farcall SelectQuantityToToss + push af + call ExitMenu + pop af + jr c, .finish + call Pack_GetItemName + ld hl, AskQuantityThrowAwayText + call MenuTextbox + call YesNoBox + push af + call ExitMenu + pop af + jr c, .finish + ld hl, wNumItems + ld a, [wCurItemQuantity] + call TossItem + call Pack_GetItemName + ld hl, ThrewAwayText + call Pack_PrintTextNoScroll +.finish + ret + +Unreferenced_ResetPocketCursorPositions: + ld a, [wCurPocket] + and a ; ITEM_POCKET + jr z, .items + dec a ; BALL_POCKET + jr z, .balls + dec a ; KEY_ITEM_POCKET + jr z, .key + ret + +.balls + xor a + ld [wBallsPocketCursor], a + ld [wBallsPocketScrollPosition], a + ret + +.items + xor a + ld [wItemsPocketCursor], a + ld [wItemsPocketScrollPosition], a + ret + +.key + xor a + ld [wKeyItemsPocketCursor], a + ld [wKeyItemsPocketScrollPosition], a + ret + +RegisterItem: + farcall CheckSelectableItem + ld a, [wItemAttributeParamBuffer] + and a + jr nz, .cant_register + ld a, [wCurPocket] + rrca + rrca + and REGISTERED_POCKET + ld b, a + ld a, [wCurItemQuantity] + inc a + and REGISTERED_NUMBER + or b + ld [wWhichRegisteredItem], a + ld a, [wCurItem] + ld [wRegisteredItem], a + call Pack_GetItemName + ld de, SFX_FULL_HEAL + call WaitPlaySFX + ld hl, RegisteredItemText + call Pack_PrintTextNoScroll + ret + +.cant_register + ld hl, CantRegisterText + call Pack_PrintTextNoScroll + ret + +GiveItem: + ld a, [wPartyCount] + and a + jp z, .NoPokemon + ld a, [wOptions] + push af + res NO_TEXT_SCROLL, a + ld [wOptions], a + ld a, PARTYMENUACTION_GIVE_ITEM + ld [wPartyMenuActionText], a + call ClearBGPalettes + farcall LoadPartyMenuGFX + farcall InitPartyMenuWithCancel + farcall InitPartyMenuGFX +.loop + farcall WritePartyMenuTilemap + farcall PrintPartyMenuText + call WaitBGMap + call SetPalettes + call DelayFrame + farcall PartyMenuSelect + jr c, .finish + ld a, [wCurPartySpecies] + cp EGG + jr nz, .give + ld hl, .AnEggCantHoldAnItemText + call PrintText + jr .loop + +.give + ld a, [wJumptableIndex] + push af + ld a, [wPackJumptableIndex] + push af + call GetCurNick + ld hl, wStringBuffer1 + ld de, wMonOrItemNameBuffer + ld bc, MON_NAME_LENGTH + call CopyBytes + call TryGiveItemToPartymon + pop af + ld [wPackJumptableIndex], a + pop af + ld [wJumptableIndex], a +.finish + pop af + ld [wOptions], a + xor a + ldh [hBGMapMode], a + call Pack_InitGFX + call WaitBGMap_DrawPackGFX + call Pack_InitColors + ret + +.NoPokemon: + ld hl, YouDontHaveAMonText + call Pack_PrintTextNoScroll + ret +.AnEggCantHoldAnItemText: + text_far _AnEggCantHoldAnItemText + text_end + +QuitItemSubmenu: + ret + +BattlePack: + ld hl, wOptions + set NO_TEXT_SCROLL, [hl] + call InitPackBuffers +.loop + call JoyTextDelay + ld a, [wJumptableIndex] + bit 7, a + jr nz, .end + call .RunJumptable + call DelayFrame + jr .loop + +.end + ld a, [wCurPocket] + ld [wLastPocket], a + ld hl, wOptions + res NO_TEXT_SCROLL, [hl] + ret + +.RunJumptable: + ld a, [wJumptableIndex] + ld hl, .Jumptable + call Pack_GetJumptablePointer + jp hl + +.Jumptable: +; entries correspond to PACKSTATE_* constants + dw .InitGFX ; 0 + dw .InitItemsPocket ; 1 + dw .ItemsPocketMenu ; 2 + dw .InitBallsPocket ; 3 + dw .BallsPocketMenu ; 4 + dw .InitKeyItemsPocket ; 5 + dw .KeyItemsPocketMenu ; 6 + dw .InitTMHMPocket ; 7 + dw .TMHMPocketMenu ; 8 + dw Pack_QuitNoScript ; 9 + dw Pack_QuitRunScript ; 10 + +.InitGFX: + xor a + ldh [hBGMapMode], a + call Pack_InitGFX + ld a, [wPackJumptableIndex] + ld [wJumptableIndex], a + call Pack_InitColors + ret + +.InitItemsPocket: + xor a ; ITEM_POCKET + ld [wCurPocket], a + call ClearPocketList + call DrawPocketName + call WaitBGMap_DrawPackGFX + call Pack_JumptableNext + ret + +.ItemsPocketMenu: + ld hl, ItemsPocketMenuHeader + call CopyMenuHeader + ld a, [wItemsPocketCursor] + ld [wMenuCursorBuffer], a + ld a, [wItemsPocketScrollPosition] + ld [wMenuScrollPosition], a + call ScrollingMenu + ld a, [wMenuScrollPosition] + ld [wItemsPocketScrollPosition], a + ld a, [wMenuCursorY] + ld [wItemsPocketCursor], a + ld b, PACKSTATE_INITTMHMPOCKET ; left + ld c, PACKSTATE_INITBALLSPOCKET ; right + call Pack_InterpretJoypad + ret c + call ItemSubmenu + ret + +.InitKeyItemsPocket: + ld a, KEY_ITEM_POCKET + ld [wCurPocket], a + call ClearPocketList + call DrawPocketName + call WaitBGMap_DrawPackGFX + call Pack_JumptableNext + ret + +.KeyItemsPocketMenu: + ld hl, KeyItemsPocketMenuHeader + call CopyMenuHeader + ld a, [wKeyItemsPocketCursor] + ld [wMenuCursorBuffer], a + ld a, [wKeyItemsPocketScrollPosition] + ld [wMenuScrollPosition], a + call ScrollingMenu + ld a, [wMenuScrollPosition] + ld [wKeyItemsPocketScrollPosition], a + ld a, [wMenuCursorY] + ld [wKeyItemsPocketCursor], a + ld b, PACKSTATE_INITBALLSPOCKET ; left + ld c, PACKSTATE_INITTMHMPOCKET ; right + call Pack_InterpretJoypad + ret c + call ItemSubmenu + ret + +.InitTMHMPocket: + ld a, TM_HM_POCKET + ld [wCurPocket], a + call ClearPocketList + call DrawPocketName + xor a + ldh [hBGMapMode], a + call WaitBGMap_DrawPackGFX + ld hl, PackEmptyText + call Pack_PrintTextNoScroll + call Pack_JumptableNext + ret + +.TMHMPocketMenu: + farcall TMHMPocket + ld b, PACKSTATE_INITKEYITEMSPOCKET ; left + ld c, PACKSTATE_INITITEMSPOCKET ; right + call Pack_InterpretJoypad + ret c + xor a + call TMHMSubmenu + ret + +.InitBallsPocket: + ld a, BALL_POCKET + ld [wCurPocket], a + call ClearPocketList + call DrawPocketName + call WaitBGMap_DrawPackGFX + call Pack_JumptableNext + ret + +.BallsPocketMenu: + ld hl, BallsPocketMenuHeader + call CopyMenuHeader + ld a, [wBallsPocketCursor] + ld [wMenuCursorBuffer], a + ld a, [wBallsPocketScrollPosition] + ld [wMenuScrollPosition], a + call ScrollingMenu + ld a, [wMenuScrollPosition] + ld [wBallsPocketScrollPosition], a + ld a, [wMenuCursorY] + ld [wBallsPocketCursor], a + ld b, PACKSTATE_INITITEMSPOCKET ; left + ld c, PACKSTATE_INITKEYITEMSPOCKET ; right + call Pack_InterpretJoypad + ret c + call ItemSubmenu + ret + +ItemSubmenu: + farcall CheckItemContext + ld a, [wItemAttributeParamBuffer] +TMHMSubmenu: + and a + jr z, .NoUse + ld hl, .UsableMenuHeader + ld de, .UsableJumptable + jr .proceed + +.NoUse: + ld hl, .UnusableMenuHeader + ld de, .UnusableJumptable +.proceed + push de + call LoadMenuHeader + call VerticalMenu + call ExitMenu + pop hl + ret c + ld a, [wMenuCursorY] + dec a + call Pack_GetJumptablePointer + jp hl + +.UsableMenuHeader: + db MENU_BACKUP_TILES ; flags + menu_coords 0, 7, TEXTBOX_HEIGHT, TEXTBOX_Y - 1 + dw .UsableMenuData + db 1 ; default option + +.UsableMenuData: + db STATICMENU_CURSOR | STATICMENU_NO_TOP_SPACING ; flags + db 2 ; items + db "USE@" + db "QUIT@" + +.UsableJumptable: + dw .Use + dw .Quit + +.UnusableMenuHeader: + db MENU_BACKUP_TILES ; flags + menu_coords 0, 9, SCREEN_WIDTH - 14, TEXTBOX_Y - 1 + dw .UnusableMenuData + db 1 ; default option + +.UnusableMenuData: + db STATICMENU_CURSOR | STATICMENU_NO_TOP_SPACING ; flags + db 1 ; items + db "QUIT@" + +.UnusableJumptable: + dw .Quit + +.Use: + farcall CheckItemContext + ld a, [wItemAttributeParamBuffer] + ld hl, .ItemFunctionJumptable + rst JumpTable + ret + +.ItemFunctionJumptable: +; entries correspond to ITEMMENU_* constants + dw .Oak ; ITEMMENU_NOUSE + dw .Oak + dw .Oak + dw .Oak + dw .Unused ; ITEMMENU_CURRENT + dw .BattleField ; ITEMMENU_PARTY + dw .BattleOnly ; ITEMMENU_CLOSE + +.Oak: + ld hl, OakThisIsntTheTimeText + call Pack_PrintTextNoScroll + ret + +.Unused: + call DoItemEffect + ld a, [wItemEffectSucceeded] + and a + jr nz, .ReturnToBattle + ret + +.BattleField: + call DoItemEffect + ld a, [wItemEffectSucceeded] + and a + jr nz, .quit_run_script + xor a + ldh [hBGMapMode], a + call Pack_InitGFX + call WaitBGMap_DrawPackGFX + call Pack_InitColors + ret + +.ReturnToBattle: + call ClearBGPalettes + jr .quit_run_script + +.BattleOnly: + call DoItemEffect + ld a, [wItemEffectSucceeded] + and a + jr z, .Oak + cp $2 + jr z, .didnt_use_item +.quit_run_script + ld a, PACKSTATE_QUITRUNSCRIPT + ld [wJumptableIndex], a + ret + +.didnt_use_item + xor a + ld [wItemEffectSucceeded], a + ret +.Quit: + ret + +InitPackBuffers: + xor a + ld [wJumptableIndex], a + ; pocket id -> jumptable index + ld a, [wLastPocket] + maskbits NUM_POCKETS + ld [wCurPocket], a + inc a + add a + dec a + ld [wPackJumptableIndex], a + xor a ; FALSE + ld [wPackUsedItem], a + xor a + ld [wSwitchItem], a + ret + +DepositSellInitPackBuffers: + xor a + ldh [hBGMapMode], a + ld [wJumptableIndex], a ; PACKSTATE_INITGFX + ld [wPackJumptableIndex], a ; PACKSTATE_INITGFX + ld [wCurPocket], a ; ITEM_POCKET + ld [wPackUsedItem], a + ld [wSwitchItem], a + call Pack_InitGFX + call Pack_InitColors + ret + +DepositSellPack: +.loop + call .RunJumptable + call DepositSellTutorial_InterpretJoypad + jr c, .loop + ret + +.RunJumptable: + ld a, [wJumptableIndex] + ld hl, .Jumptable + call Pack_GetJumptablePointer + jp hl + +.Jumptable: +; entries correspond to *_POCKET constants + dw .ItemsPocket + dw .BallsPocket + dw .KeyItemsPocket + dw .TMHMPocket + +.ItemsPocket: + xor a ; ITEM_POCKET + call InitPocket + ld hl, PC_Mart_ItemsPocketMenuHeader + call CopyMenuHeader + ld a, [wItemsPocketCursor] + ld [wMenuCursorBuffer], a + ld a, [wItemsPocketScrollPosition] + ld [wMenuScrollPosition], a + call ScrollingMenu + ld a, [wMenuScrollPosition] + ld [wItemsPocketScrollPosition], a + ld a, [wMenuCursorY] + ld [wItemsPocketCursor], a + ret + +.KeyItemsPocket: + ld a, KEY_ITEM_POCKET + call InitPocket + ld hl, PC_Mart_KeyItemsPocketMenuHeader + call CopyMenuHeader + ld a, [wKeyItemsPocketCursor] + ld [wMenuCursorBuffer], a + ld a, [wKeyItemsPocketScrollPosition] + ld [wMenuScrollPosition], a + call ScrollingMenu + ld a, [wMenuScrollPosition] + ld [wKeyItemsPocketScrollPosition], a + ld a, [wMenuCursorY] + ld [wKeyItemsPocketCursor], a + ret + +.TMHMPocket: + ld a, TM_HM_POCKET + call InitPocket + call WaitBGMap_DrawPackGFX + farcall TMHMPocket + ld a, [wCurItem] + ld [wCurItem], a + ret + +.BallsPocket: + ld a, BALL_POCKET + call InitPocket + ld hl, PC_Mart_BallsPocketMenuHeader + call CopyMenuHeader + ld a, [wBallsPocketCursor] + ld [wMenuCursorBuffer], a + ld a, [wBallsPocketScrollPosition] + ld [wMenuScrollPosition], a + call ScrollingMenu + ld a, [wMenuScrollPosition] + ld [wBallsPocketScrollPosition], a + ld a, [wMenuCursorY] + ld [wBallsPocketCursor], a + ret + +InitPocket: + ld [wCurPocket], a + call ClearPocketList + call DrawPocketName + call WaitBGMap_DrawPackGFX + ret + +DepositSellTutorial_InterpretJoypad: + ld hl, wMenuJoypad + ld a, [hl] + and A_BUTTON + jr nz, .a_button + ld a, [hl] + and B_BUTTON + jr nz, .b_button + ld a, [hl] + and D_LEFT + jr nz, .d_left + ld a, [hl] + and D_RIGHT + jr nz, .d_right + scf + ret + +.a_button + ld a, TRUE + ld [wPackUsedItem], a + and a + ret + +.b_button + xor a ; FALSE + ld [wPackUsedItem], a + and a + ret + +.d_left + ld a, [wJumptableIndex] + dec a + maskbits NUM_POCKETS + ld [wJumptableIndex], a + push de + ld de, SFX_SWITCH_POCKETS + call PlaySFX + pop de + scf + ret + +.d_right + ld a, [wJumptableIndex] + inc a + maskbits NUM_POCKETS + ld [wJumptableIndex], a + push de + ld de, SFX_SWITCH_POCKETS + call PlaySFX + pop de + scf + ret + +TutorialPack: + call DepositSellInitPackBuffers + ld a, [wInputType] + or a + jr z, .loop + farcall _DudeAutoInput_RightA +.loop + call .RunJumptable + call DepositSellTutorial_InterpretJoypad + jr c, .loop + xor a ; FALSE + ld [wPackUsedItem], a + ret + +.RunJumptable: + ld a, [wJumptableIndex] + ld hl, .dw + call Pack_GetJumptablePointer + jp hl + +.dw +; entries correspond to *_POCKET constants + dw .Items + dw .Balls + dw .KeyItems + dw .TMHM + +.Items: + xor a ; ITEM_POCKET + ld hl, .ItemsMenuHeader + jr .DisplayPocket + +.ItemsMenuHeader: + db MENU_BACKUP_TILES ; flags + menu_coords 7, 1, SCREEN_WIDTH - 1, TEXTBOX_Y - 1 + dw .ItemsMenuData + db 1 ; default option + +.ItemsMenuData: + db STATICMENU_ENABLE_SELECT | STATICMENU_ENABLE_LEFT_RIGHT | STATICMENU_ENABLE_START | STATICMENU_WRAP | STATICMENU_CURSOR ; flags + db 5, 8 ; rows, columns + db 2 ; horizontal spacing + dbw 0, wDudeNumItems + dba PlaceMenuItemName + dba PlaceMenuItemQuantity + dba UpdateItemDescription + +.KeyItems: + ld a, KEY_ITEM_POCKET + ld hl, .KeyItemsMenuHeader + jr .DisplayPocket + +.KeyItemsMenuHeader: + db MENU_BACKUP_TILES ; flags + menu_coords 7, 1, SCREEN_WIDTH - 1, TEXTBOX_Y - 1 + dw .KeyItemsMenuData + db 1 ; default option + +.KeyItemsMenuData: + db STATICMENU_ENABLE_SELECT | STATICMENU_ENABLE_LEFT_RIGHT | STATICMENU_ENABLE_START | STATICMENU_WRAP | STATICMENU_CURSOR ; flags + db 5, 8 ; rows, columns + db 1 ; horizontal spacing + dbw 0, wDudeNumKeyItems + dba PlaceMenuItemName + dba PlaceMenuItemQuantity + dba UpdateItemDescription + +.TMHM: + ld a, TM_HM_POCKET + call InitPocket + call WaitBGMap_DrawPackGFX + farcall TMHMPocket + ld a, [wCurItem] + ld [wCurItem], a + ret + +.Balls: + ld a, BALL_POCKET + ld hl, .BallsMenuHeader + jr .DisplayPocket + +.BallsMenuHeader: + db MENU_BACKUP_TILES ; flags + menu_coords 7, 1, SCREEN_WIDTH - 1, TEXTBOX_Y - 1 + dw .BallsMenuData + db 1 ; default option + +.BallsMenuData: + db STATICMENU_ENABLE_SELECT | STATICMENU_ENABLE_LEFT_RIGHT | STATICMENU_ENABLE_START | STATICMENU_WRAP | STATICMENU_CURSOR ; flags + db 5, 8 ; rows, columns + db 2 ; horizontal spacing + dbw 0, wDudeNumBalls + dba PlaceMenuItemName + dba PlaceMenuItemQuantity + dba UpdateItemDescription + +.DisplayPocket: + push hl + call InitPocket + pop hl + call CopyMenuHeader + call ScrollingMenu + ret + +Pack_JumptableNext: + ld hl, wJumptableIndex + inc [hl] + ret + +Pack_GetJumptablePointer: + ld e, a + ld d, 0 + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + ret + +Pack_QuitNoScript: + ld hl, wJumptableIndex + set 7, [hl] + xor a ; FALSE + ld [wPackUsedItem], a + ret + +Pack_QuitRunScript: + ld hl, wJumptableIndex + set 7, [hl] + ld a, TRUE + ld [wPackUsedItem], a + ret + +Pack_PrintTextNoScroll: + ld a, [wOptions] + push af + set NO_TEXT_SCROLL, a + ld [wOptions], a + call PrintText + pop af + ld [wOptions], a + ret + +WaitBGMap_DrawPackGFX: + call WaitBGMap +DrawPackGFX: + ld a, [wCurPocket] + maskbits NUM_POCKETS + ld e, a + ld d, 0 + ld hl, PackGFXPointers + add hl, de + add hl, de + ld a, [hli] + ld e, a + ld d, [hl] + ld hl, vTiles2 tile $50 + lb bc, BANK(PackGFX), 15 + call Request2bpp + ret + +PackGFXPointers: + dw PackGFX + (15 tiles) * 1 ; ITEM_POCKET + dw PackGFX + (15 tiles) * 3 ; BALL_POCKET + dw PackGFX + (15 tiles) * 0 ; KEY_ITEM_POCKET + dw PackGFX + (15 tiles) * 2 ; TM_HM_POCKET + +Pack_InterpretJoypad: + ld hl, wMenuJoypad + ld a, [wSwitchItem] + and a + jr nz, .switching_item + ld a, [hl] + and A_BUTTON + jr nz, .a_button + ld a, [hl] + and B_BUTTON + jr nz, .b_button + ld a, [hl] + and D_LEFT + jr nz, .d_left + ld a, [hl] + and D_RIGHT + jr nz, .d_right + ld a, [hl] + and SELECT + jr nz, .select + scf + ret + +.a_button + and a + ret + +.b_button + ld a, PACKSTATE_QUITNOSCRIPT + ld [wJumptableIndex], a + scf + ret + +.d_left + ld a, b + ld [wJumptableIndex], a + ld [wPackJumptableIndex], a + push de + ld de, SFX_SWITCH_POCKETS + call PlaySFX + pop de + scf + ret + +.d_right + ld a, c + ld [wJumptableIndex], a + ld [wPackJumptableIndex], a + push de + ld de, SFX_SWITCH_POCKETS + call PlaySFX + pop de + scf + ret + +.select + farcall SwitchItemsInBag + ld hl, AskItemMoveText + call Pack_PrintTextNoScroll + scf + ret + +.switching_item + ld a, [hl] + and A_BUTTON | SELECT + jr nz, .place_insert + ld a, [hl] + and B_BUTTON + jr nz, .end_switch + scf + ret + +.place_insert + farcall SwitchItemsInBag + ld de, SFX_SWITCH_POKEMON + call WaitPlaySFX + ld de, SFX_SWITCH_POKEMON + call WaitPlaySFX +.end_switch + xor a + ld [wSwitchItem], a + scf + ret + +Pack_InitGFX: + call ClearBGPalettes + call ClearTilemap + call ClearSprites + call DisableLCD + ld hl, PackMenuGFX + ld de, vTiles2 + ld bc, $60 tiles + ld a, BANK(PackMenuGFX) + call FarCopyBytes +; Background + hlcoord 0, 1 + ld bc, 11 * SCREEN_WIDTH + ld a, $24 + call ByteFill +; This is where the items themselves will be listed. + hlcoord 5, 1 + lb bc, 11, 15 + call ClearBox +; ◀▶ POCKET ▼▲ ITEMS + hlcoord 0, 0 + ld a, $28 + ld c, SCREEN_WIDTH +.loop + ld [hli], a + inc a + dec c + jr nz, .loop + call DrawPocketName + call PlacePackGFX +; Place the textbox for displaying the item description + hlcoord 0, SCREEN_HEIGHT - 4 - 2 + lb bc, 4, SCREEN_WIDTH - 2 + call Textbox + call EnableLCD + call DrawPackGFX + ret + +PlacePackGFX: + hlcoord 0, 3 + ld a, $50 + ld de, SCREEN_WIDTH - 5 + ld b, 3 +.row + ld c, 5 +.column + ld [hli], a + inc a + dec c + jr nz, .column + add hl, de + dec b + jr nz, .row + ret + +DrawPocketName: + ld a, [wCurPocket] + ; * 15 + ld d, a + swap a + sub d + ld d, 0 + ld e, a + ld hl, .tilemap + add hl, de + ld d, h + ld e, l + hlcoord 0, 7 + ld c, 3 +.row + ld b, 5 +.col + ld a, [de] + inc de + ld [hli], a + dec b + jr nz, .col + ld a, c + ld c, SCREEN_WIDTH - 5 + add hl, bc + ld c, a + dec c + jr nz, .row + ret + +.tilemap +; ITEM_POCKET + db $00, $04, $04, $04, $01 ; top border + db $06, $07, $08, $09, $0a ; Items + db $02, $05, $05, $05, $03 ; bottom border +; BALL_POCKET + db $00, $04, $04, $04, $01 ; top border + db $15, $16, $17, $18, $19 ; Balls + db $02, $05, $05, $05, $03 ; bottom border +; KEY_ITEM_POCKET + db $00, $04, $04, $04, $01 ; top border + db $0b, $0c, $0d, $0e, $0f ; Key Items + db $02, $05, $05, $05, $03 ; bottom border +; TM_HM_POCKET + db $00, $04, $04, $04, $01 ; top border + db $10, $11, $12, $13, $14 ; TM/HM + db $02, $05, $05, $05, $03 ; bottom border + +Pack_GetItemName: + ld a, [wCurItem] + ld [wNamedObjectIndexBuffer], a + call GetItemName + call CopyName1 + ret + +Unreferenced_Pack_ClearTilemap: + hlcoord 0, 0 + ld bc, SCREEN_WIDTH * SCREEN_HEIGHT + ld a, " " + call ByteFill + ret + +ClearPocketList: + hlcoord 5, 2 + lb bc, 10, SCREEN_WIDTH - 5 + call ClearBox + ret + +Pack_InitColors: + call WaitBGMap + ld b, SCGB_PACKPALS + call GetSGBLayout + call SetPalettes + call DelayFrame + ret + +ItemsPocketMenuHeader: + db MENU_BACKUP_TILES ; flags + menu_coords 7, 1, SCREEN_WIDTH - 1, TEXTBOX_Y - 1 + dw .MenuData + db 1 ; default option + +.MenuData: + db STATICMENU_ENABLE_SELECT | STATICMENU_ENABLE_LEFT_RIGHT | STATICMENU_ENABLE_START | STATICMENU_WRAP | STATICMENU_CURSOR ; flags + db 5, 8 ; rows, columns + db SCROLLINGMENU_ITEMS_QUANTITY ; item format + dbw 0, wNumItems + dba PlaceMenuItemName + dba PlaceMenuItemQuantity + dba UpdateItemDescription + +PC_Mart_ItemsPocketMenuHeader: + db MENU_BACKUP_TILES ; flags + menu_coords 7, 1, SCREEN_WIDTH - 1, TEXTBOX_Y - 1 + dw .MenuData + db 1 ; default option + +.MenuData: + db STATICMENU_ENABLE_SELECT | STATICMENU_ENABLE_LEFT_RIGHT | STATICMENU_ENABLE_START | STATICMENU_WRAP ; flags + db 5, 8 ; rows, columns + db SCROLLINGMENU_ITEMS_QUANTITY ; item format + dbw 0, wNumItems + dba PlaceMenuItemName + dba PlaceMenuItemQuantity + dba UpdateItemDescription + +KeyItemsPocketMenuHeader: + db MENU_BACKUP_TILES ; flags + menu_coords 7, 1, SCREEN_WIDTH - 1, TEXTBOX_Y - 1 + dw .MenuData + db 1 ; default option + +.MenuData: + db STATICMENU_ENABLE_SELECT | STATICMENU_ENABLE_LEFT_RIGHT | STATICMENU_ENABLE_START | STATICMENU_WRAP | STATICMENU_CURSOR ; flags + db 5, 8 ; rows, columns + db SCROLLINGMENU_ITEMS_NORMAL ; item format + dbw 0, wNumKeyItems + dba PlaceMenuItemName + dba PlaceMenuItemQuantity + dba UpdateItemDescription + +PC_Mart_KeyItemsPocketMenuHeader: + db MENU_BACKUP_TILES ; flags + menu_coords 7, 1, SCREEN_WIDTH - 1, TEXTBOX_Y - 1 + dw .MenuData + db 1 ; default option + +.MenuData: + db STATICMENU_ENABLE_SELECT | STATICMENU_ENABLE_LEFT_RIGHT | STATICMENU_ENABLE_START | STATICMENU_WRAP ; flags + db 5, 8 ; rows, columns + db SCROLLINGMENU_ITEMS_NORMAL ; item format + dbw 0, wNumKeyItems + dba PlaceMenuItemName + dba PlaceMenuItemQuantity + dba UpdateItemDescription + +BallsPocketMenuHeader: + db MENU_BACKUP_TILES ; flags + menu_coords 7, 1, SCREEN_WIDTH - 1, TEXTBOX_Y - 1 + dw .MenuData + db 1 ; default option + +.MenuData: + db STATICMENU_ENABLE_SELECT | STATICMENU_ENABLE_LEFT_RIGHT | STATICMENU_ENABLE_START | STATICMENU_WRAP | STATICMENU_CURSOR ; flags + db 5, 8 ; rows, columns + db SCROLLINGMENU_ITEMS_QUANTITY ; item format + dbw 0, wNumBalls + dba PlaceMenuItemName + dba PlaceMenuItemQuantity + dba UpdateItemDescription + +PC_Mart_BallsPocketMenuHeader: + db MENU_BACKUP_TILES ; flags + menu_coords 7, 1, SCREEN_WIDTH - 1, TEXTBOX_Y - 1 + dw .MenuData + db 1 ; default option + +.MenuData: + db STATICMENU_ENABLE_SELECT | STATICMENU_ENABLE_LEFT_RIGHT | STATICMENU_ENABLE_START | STATICMENU_WRAP ; flags + db 5, 8 ; rows, columns + db SCROLLINGMENU_ITEMS_QUANTITY ; item format + dbw 0, wNumBalls + dba PlaceMenuItemName + dba PlaceMenuItemQuantity + dba UpdateItemDescription + +PackNoItemText: + text_far _PackNoItemText + text_end + +AskThrowAwayText: + text_far _AskThrowAwayText + text_end + +AskQuantityThrowAwayText: + text_far _AskQuantityThrowAwayText + text_end + +ThrewAwayText: + text_far _ThrewAwayText + text_end + +OakThisIsntTheTimeText: + text_far _OakThisIsntTheTimeText + text_end + +YouDontHaveAMonText: + text_far _YouDontHaveAMonText + text_end + +RegisteredItemText: + text_far _RegisteredItemText + text_end + +CantRegisterText: + text_far _CantRegisterText + text_end + +AskItemMoveText: + text_far _AskItemMoveText + text_end + +PackEmptyText: + text_far _PackEmptyText + text_end + +YouCantUseItInABattleText: + text_far _YouCantUseItInABattleText + text_end + +PackMenuGFX: +INCBIN "gfx/pack/pack_menu.2bpp" +PackGFX: +INCBIN "gfx/pack/pack.2bpp" diff --git a/engine/items/print_item_description.asm b/engine/items/print_item_description.asm new file mode 100644 index 00000000..89a949ad --- /dev/null +++ b/engine/items/print_item_description.asm @@ -0,0 +1,32 @@ +PrintItemDescription: +; Print the description for item [wCurSpecies] at de. + + ld a, [wCurSpecies] + cp TM01 + jr c, .not_a_tm + + ld [wCurItem], a + push de + call GetTMHMItemMove + pop hl + ld a, [wTempTMHM] + ld [wCurSpecies], a + call PrintMoveDesc + ret + +.not_a_tm + push de + ld hl, ItemDescriptions + ld a, [wCurSpecies] + dec a + ld c, a + ld b, 0 + add hl, bc + add hl, bc + ld a, BANK(ItemDescriptions) + call GetFarHalfword + ld d, h + ld e, l + pop hl + ld a, BANK(ItemDescriptions) + jp FarString diff --git a/engine/items/switch_items.asm b/engine/items/switch_items.asm new file mode 100644 index 00000000..cb1554d7 --- /dev/null +++ b/engine/items/switch_items.asm @@ -0,0 +1,272 @@ +SwitchItemsInBag: + ld a, [wSwitchItem] + and a + jr z, .init + ld b, a + ld a, [wScrollingMenuCursorPosition] + inc a + cp b + jr z, .trivial + ld a, [wScrollingMenuCursorPosition] + call ItemSwitch_GetNthItem + ld a, [hl] + cp -1 + ret z + ld a, [wSwitchItem] + dec a + ld [wSwitchItem], a + call Function248cf + jp c, Function248f9 + ld a, [wScrollingMenuCursorPosition] + ld c, a + ld a, [wSwitchItem] + cp c + jr c, .asm_248a2 + jr .asm_24872 + +.init + ld a, [wScrollingMenuCursorPosition] + inc a + ld [wSwitchItem], a + ret + +.trivial + xor a + ld [wSwitchItem], a + ret + +.asm_24872 + ld a, [wSwitchItem] + call Function24968 + ld a, [wScrollingMenuCursorPosition] + ld d, a + ld a, [wSwitchItem] + ld e, a + call Function24994 + push bc + ld a, [wSwitchItem] + call ItemSwitch_GetNthItem + dec hl + push hl + call ItemSwitch_ConvertItemFormatToDW + add hl, bc + ld d, h + ld e, l + pop hl + pop bc + call Function249d3 + ld a, [wScrollingMenuCursorPosition] + call Function24975 + xor a + ld [wSwitchItem], a + ret + +.asm_248a2 + ld a, [wSwitchItem] + call Function24968 + ld a, [wScrollingMenuCursorPosition] + ld d, a + ld a, [wSwitchItem] + ld e, a + call Function24994 + push bc + ld a, [wSwitchItem] + call ItemSwitch_GetNthItem + ld d, h + ld e, l + call ItemSwitch_ConvertItemFormatToDW + add hl, bc + pop bc + call CopyBytes + ld a, [wScrollingMenuCursorPosition] + call Function24975 + xor a + ld [wSwitchItem], a + ret + +Function248cf: + ld a, [wSwitchItem] + call ItemSwitch_GetNthItem + ld d, h + ld e, l + ld a, [wScrollingMenuCursorPosition] + call ItemSwitch_GetNthItem + ld a, [de] + cp [hl] + jr nz, .asm_248f5 + ld a, [wScrollingMenuCursorPosition] + call Function249bf + cp 99 + jr z, .asm_248f5 + ld a, [wSwitchItem] + call Function249bf + cp 99 + jr nz, .asm_248f7 +.asm_248f5 + and a + ret + +.asm_248f7 + scf + ret + +Function248f9: + ld a, [wSwitchItem] + call ItemSwitch_GetNthItem + inc hl + push hl + ld a, [wScrollingMenuCursorPosition] + call ItemSwitch_GetNthItem + inc hl + ld a, [hl] + pop hl + add [hl] + cp 100 + jr c, .asm_24929 + sub 99 + push af + ld a, [wScrollingMenuCursorPosition] + call ItemSwitch_GetNthItem + inc hl + ld [hl], 99 + ld a, [wSwitchItem] + call ItemSwitch_GetNthItem + inc hl + pop af + ld [hl], a + xor a + ld [wSwitchItem], a + ret + +.asm_24929 + push af + ld a, [wScrollingMenuCursorPosition] + call ItemSwitch_GetNthItem + inc hl + pop af + ld [hl], a + ld hl, wMenuData_ItemsPointerAddr + ld a, [hli] + ld h, [hl] + ld l, a + ld a, [wSwitchItem] + cp [hl] + jr nz, .asm_2494d + dec [hl] + ld a, [wSwitchItem] + call ItemSwitch_GetNthItem + ld [hl], $ff + xor a + ld [wSwitchItem], a + ret + +.asm_2494d + dec [hl] + call ItemSwitch_ConvertItemFormatToDW + push bc + ld a, [wSwitchItem] + call ItemSwitch_GetNthItem + pop bc + push hl + add hl, bc + pop de +.asm_2495c + ld a, [hli] + ld [de], a + inc de + cp $ff + jr nz, .asm_2495c + xor a + ld [wSwitchItem], a + ret + +Function24968: + call ItemSwitch_GetNthItem + ld de, wceed + call ItemSwitch_ConvertItemFormatToDW + call CopyBytes + ret + +Function24975: + call ItemSwitch_GetNthItem + ld d, h + ld e, l + ld hl, wceed + call ItemSwitch_ConvertItemFormatToDW + call CopyBytes + ret + +ItemSwitch_GetNthItem: + push af + call ItemSwitch_ConvertItemFormatToDW + ld hl, wMenuData_ItemsPointerAddr + ld a, [hli] + ld h, [hl] + ld l, a + inc hl + pop af + call AddNTimes + ret + +Function24994: + push hl + call ItemSwitch_ConvertItemFormatToDW + ld a, d + sub e + jr nc, .dont_negate + dec a + cpl +.dont_negate + ld hl, 0 + call AddNTimes + ld b, h + ld c, l + pop hl + ret + +ItemSwitch_ConvertItemFormatToDW: + push hl + ld a, [wMenuData_ScrollingMenuItemFormat] + ld c, a + ld b, 0 + ld hl, .format_dws + add hl, bc + add hl, bc + ld c, [hl] + inc hl + ld b, [hl] + pop hl + ret + +.format_dws + dw 0 + dw 1 + dw 2 + +Function249bf: + push af + call ItemSwitch_ConvertItemFormatToDW + ld a, c + cp 2 + jr nz, .not_2 + pop af + call ItemSwitch_GetNthItem + inc hl + ld a, [hl] + ret + +.not_2 + pop af + ld a, $1 + ret + +Function249d3: +.loop + ld a, [hld] + ld [de], a + dec de + dec bc + ld a, b + or c + jr nz, .loop + ret diff --git a/engine/items/tmhm.asm b/engine/items/tmhm.asm new file mode 100644 index 00000000..f5261123 --- /dev/null +++ b/engine/items/tmhm.asm @@ -0,0 +1,552 @@ +TMHMPocket: + ld a, $1 + ldh [hInMenu], a + call TMHM_PocketLoop + ld a, $0 + ldh [hInMenu], a + ret nc + call PlaceHollowCursor + call WaitBGMap + ld a, [wCurItem] + dec a + ld [wCurItemQuantity], a + ld hl, wTMsHMs + ld c, a + ld b, 0 + add hl, bc + ld a, [hl] + ld [wItemQuantityBuffer], a + call .ConvertItemToTMHMNumber + scf + ret + +.ConvertItemToTMHMNumber: + ld a, [wCurItem] + ld c, a + callfar GetNumberedTMHM + ld a, c + ld [wCurItem], a + ret + +ConvertCurItemIntoCurTMHM: + ld a, [wCurItem] + ld c, a + callfar GetTMHMNumber + ld a, c + ld [wTempTMHM], a + ret + +GetTMHMItemMove: + call ConvertCurItemIntoCurTMHM + predef GetTMHMMove + ret + +AskTeachTMHM: + ld hl, wOptions + ld a, [hl] + push af + res NO_TEXT_SCROLL, [hl] + ld a, [wCurItem] + cp TM01 + jr c, .NotTMHM + call GetTMHMItemMove + ld a, [wTempTMHM] + ld [wPutativeTMHMMove], a + call GetMoveName + call CopyName1 + ld hl, BootedTMText ; Booted up a TM + ld a, [wCurItem] + cp HM01 + jr c, .TM + ld hl, BootedHMText ; Booted up an HM +.TM: + call PrintText + ld hl, ContainedMoveText + call PrintText + call YesNoBox +.NotTMHM: + pop bc + ld a, b + ld [wOptions], a + ret + +ChooseMonToLearnTMHM: + ld hl, wStringBuffer2 + ld de, wTMHMMoveNameBackup + ld bc, 12 + call CopyBytes + call ClearBGPalettes +ChooseMonToLearnTMHM_NoRefresh: + farcall LoadPartyMenuGFX + farcall InitPartyMenuWithCancel + farcall InitPartyMenuGFX + ld a, PARTYMENUACTION_TEACH_TMHM + ld [wPartyMenuActionText], a +.loopback + farcall WritePartyMenuTilemap + farcall PrintPartyMenuText + call WaitBGMap + call SetPalettes + call DelayFrame + farcall PartyMenuSelect + push af + ld a, [wCurPartySpecies] + cp EGG + pop bc ; now contains the former contents of af + jr z, .egg + push bc + ld hl, wTMHMMoveNameBackup + ld de, wStringBuffer2 + ld bc, 12 + call CopyBytes + pop af ; now contains the original contents of af + ret + +.egg + push hl + push de + push bc + push af + ld de, SFX_WRONG + call PlaySFX + call WaitSFX + pop af + pop bc + pop de + pop hl + jr .loopback + +TeachTMHM: + predef CanLearnTMHMMove + + push bc + ld a, [wCurPartyMon] + ld hl, wPartyMonNicknames + call GetNick + pop bc + + ld a, c + and a + jr nz, .compatible + push de + ld de, SFX_WRONG + call PlaySFX + pop de + ld hl, TMHMNotCompatibleText + call PrintText + jr .nope + +.compatible + callfar KnowsMove + jr c, .nope + + predef LearnMove + ld a, b + and a + jr z, .nope + + ld a, [wCurItem] + call IsHM + ret c + + ld c, HAPPINESS_LEARNMOVE + callfar ChangeHappiness + call ConsumeTM + jr .learned_move + +.nope + and a + ret + +.unused + ld a, 2 + ld [wItemEffectSucceeded], a +.learned_move + scf + ret + +BootedTMText: + text_far _BootedTMText + text_end + +BootedHMText: + text_far _BootedHMText + text_end + +ContainedMoveText: + text_far _ContainedMoveText + text_end + +TMHMNotCompatibleText: + text_far _TMHMNotCompatibleText + text_end + +TMHM_PocketLoop: + xor a + ldh [hBGMapMode], a + call TMHM_DisplayPocketItems + ld a, 2 + ld [w2DMenuCursorInitY], a + ld a, 7 + ld [w2DMenuCursorInitX], a + ld a, 1 + ld [w2DMenuNumCols], a + ld a, 5 + sub d + inc a + cp 6 + jr nz, .okay + dec a +.okay + ld [w2DMenuNumRows], a + ld a, $c + ld [w2DMenuFlags1], a + xor a + ld [w2DMenuFlags2], a + ld a, $20 + ld [w2DMenuCursorOffsets], a + ld a, A_BUTTON | B_BUTTON | D_UP | D_DOWN | D_LEFT | D_RIGHT + ld [wMenuJoypadFilter], a + ld a, [wTMHMPocketCursor] + inc a + ld [wMenuCursorY], a + ld a, $1 + ld [wMenuCursorX], a + jr TMHM_ShowTMMoveDescription + +TMHM_JoypadLoop: + call TMHM_DisplayPocketItems + call StaticMenuJoypad + ld b, a + ld a, [wMenuCursorY] + dec a + ld [wTMHMPocketCursor], a + xor a + ldh [hBGMapMode], a + ld a, [w2DMenuFlags2] + bit 7, a + jp nz, TMHM_ScrollPocket + ld a, b + ld [wMenuJoypad], a + bit A_BUTTON_F, a + jp nz, TMHM_ChooseTMorHM + bit B_BUTTON_F, a + jp nz, TMHM_ExitPack + bit D_RIGHT_F, a + jp nz, TMHM_ExitPocket + bit D_LEFT_F, a + jp nz, TMHM_ExitPocket +TMHM_ShowTMMoveDescription: + call TMHM_CheckHoveringOverCancel + jp nc, TMHM_ExitPocket + hlcoord 0, 12 + ld b, 4 + ld c, SCREEN_WIDTH - 2 + call Textbox + ld a, [wCurItem] + cp NUM_TMS + NUM_HMS + 1 + jr nc, TMHM_JoypadLoop + ld [wTempTMHM], a + predef GetTMHMMove + ld a, [wTempTMHM] + ld [wCurSpecies], a + hlcoord 1, 14 + call PrintMoveDesc + jp TMHM_JoypadLoop + +TMHM_ChooseTMorHM: + call TMHM_PlaySFX_ReadText2 + call CountTMsHMs ; This stores the count to wTempTMHM. + ld a, [wMenuCursorY] + dec a + ld b, a + ld a, [wTMHMPocketScrollPosition] + add b + ld b, a + ld a, [wTempTMHM] + cp b + jr z, _TMHM_ExitPack ; our cursor was hovering over CANCEL +TMHM_CheckHoveringOverCancel: + call TMHM_GetCurrentPocketPosition + ld a, [wMenuCursorY] + ld b, a +.loop + inc c + ld a, c + cp NUM_TMS + NUM_HMS + 1 + jr nc, .okay + ld a, [hli] + and a + jr z, .loop + dec b + jr nz, .loop + ld a, c +.okay + ld [wCurItem], a + cp -1 + ret + +TMHM_ExitPack: + call TMHM_PlaySFX_ReadText2 +_TMHM_ExitPack: + ld a, $2 + ld [wMenuJoypad], a + and a + ret + +TMHM_ExitPocket: + and a + ret + +TMHM_ScrollPocket: + ld a, b + bit 7, a + jr nz, .skip + ld hl, wTMHMPocketScrollPosition + ld a, [hl] + and a + jp z, TMHM_JoypadLoop + dec [hl] + call TMHM_DisplayPocketItems + jp TMHM_ShowTMMoveDescription + +.skip + call TMHM_GetCurrentPocketPosition + ld b, 5 +.loop + inc c + ld a, c + cp NUM_TMS + NUM_HMS + 1 + jp nc, TMHM_JoypadLoop + ld a, [hli] + and a + jr z, .loop + dec b + jr nz, .loop + ld hl, wTMHMPocketScrollPosition + inc [hl] + call TMHM_DisplayPocketItems + jp TMHM_ShowTMMoveDescription + +TMHM_DisplayPocketItems: + ld a, [wBattleType] + cp BATTLETYPE_TUTORIAL + jp z, Tutorial_TMHMPocket + + hlcoord 5, 2 + lb bc, 10, 15 + ld a, " " + call ClearBox + call TMHM_GetCurrentPocketPosition + ld d, $5 +.loop2 + inc c + ld a, c + cp NUM_TMS + NUM_HMS + 1 + jr nc, .NotTMHM + ld a, [hli] + and a + jr z, .loop2 + ld b, a + ld a, c + ld [wTempTMHM], a + push hl + push de + push bc + call TMHMPocket_GetCurrentLineCoord + push hl + ld a, [wTempTMHM] + cp NUM_TMS + 1 + jr nc, .HM + ld de, wTempTMHM + lb bc, PRINTNUM_LEADINGZEROS | 1, 2 + call PrintNum + jr .okay + +.HM: + push af + sub NUM_TMS + ld [wTempTMHM], a + ld [hl], "H" + inc hl + ld de, wTempTMHM + lb bc, PRINTNUM_LEFTALIGN | 1, 2 + call PrintNum + pop af + ld [wTempTMHM], a +.okay + predef GetTMHMMove + ld a, [wNamedObjectIndexBuffer] + ld [wPutativeTMHMMove], a + call GetMoveName + pop hl + ld bc, 3 + add hl, bc + push hl + call PlaceString + pop hl + pop bc + ld a, c + push bc + cp NUM_TMS + 1 + jr nc, .hm2 + ld bc, SCREEN_WIDTH + 9 + add hl, bc + ld [hl], "×" + inc hl + ld a, "0" ; why are we doing this? + pop bc + push bc + ld a, b + ld [wTempTMHM], a + ld de, wTempTMHM + lb bc, 1, 2 + call PrintNum +.hm2 + pop bc + pop de + pop hl + dec d + jr nz, .loop2 + jr .done + +.NotTMHM: + call TMHMPocket_GetCurrentLineCoord + inc hl + inc hl + inc hl + push de + ld de, TMHM_String_Cancel + call PlaceString + pop de +.done + ret + +TMHMPocket_GetCurrentLineCoord: + hlcoord 5, 0 + ld bc, 2 * SCREEN_WIDTH + ld a, 6 + sub d + ld e, a + ; AddNTimes +.loop + add hl, bc + dec e + jr nz, .loop + ret + +Unreferenced_Function2c89a: + pop hl + ld bc, 3 + add hl, bc + predef GetTMHMMove + ld a, [wTempTMHM] + ld [wPutativeTMHMMove], a + call GetMoveName + push hl + call PlaceString + pop hl + ret + +TMHM_String_Cancel: + db "CANCEL@" + +TMHM_GetCurrentPocketPosition: + ld hl, wTMsHMs + ld a, [wTMHMPocketScrollPosition] + ld b, a + inc b + ld c, 0 +.loop + inc c + ld a, [hli] + and a + jr z, .loop + dec b + jr nz, .loop + dec hl + dec c + ret + +Tutorial_TMHMPocket: + hlcoord 9, 3 + push de + ld de, TMHM_String_Cancel + call PlaceString + pop de + ret + +TMHM_PlaySFX_ReadText2: + push de + ld de, SFX_READ_TEXT_2 + call PlaySFX + pop de + ret + +Unreferenced_Function2c8e4: + call ConvertCurItemIntoCurTMHM + call .CheckHaveRoomForTMHM + ld hl, .NoRoomTMHMText + jr nc, .print + ld hl, .ReceivedTMHMText +.print + jp PrintText + +.NoRoomTMHMText: + text_far _NoRoomTMHMText + text_end + +.ReceivedTMHMText: + text_far _ReceivedTMHMText + text_end + +.CheckHaveRoomForTMHM: + ld a, [wTempTMHM] + dec a + ld hl, wTMsHMs + ld b, 0 + ld c, a + add hl, bc + ld a, [hl] + inc a + cp NUM_TMS * 2 + ret nc + ld [hl], a + ret + +ConsumeTM: + call ConvertCurItemIntoCurTMHM + ld a, [wTempTMHM] + dec a + ld hl, wTMsHMs + ld b, 0 + ld c, a + add hl, bc + ld a, [hl] + and a + ret z + dec a + ld [hl], a + ret nz + ld a, [wTMHMPocketScrollPosition] + and a + ret z + dec a + ld [wTMHMPocketScrollPosition], a + ret + +CountTMsHMs: + ld b, 0 + ld c, NUM_TMS + NUM_HMS + ld hl, wTMsHMs +.loop + ld a, [hli] + and a + jr z, .skip + inc b +.skip + dec c + jr nz, .loop + ld a, b + ld [wTempTMHM], a + ret diff --git a/engine/items/tmhm2.asm b/engine/items/tmhm2.asm new file mode 100755 index 00000000..eb3eb58e --- /dev/null +++ b/engine/items/tmhm2.asm @@ -0,0 +1,46 @@ +CanLearnTMHMMove: + ld a, [wCurPartySpecies] + ld [wCurSpecies], a + call GetBaseData + ld hl, wBaseTMHM + push hl + + ld a, [wPutativeTMHMMove] + ld b, a + ld c, 0 + ld hl, TMHMMoves +.loop + ld a, [hli] + and a + jr z, .end + cp b + jr z, .asm_11a45 + inc c + jr .loop + +.asm_11a45 + pop hl + ld b, CHECK_FLAG + push de + ld d, 0 + predef SmallFarFlagAction + pop de + ret + +.end + pop hl + ld c, 0 + ret + +GetTMHMMove: + ld a, [wTempTMHM] + dec a + ld hl, TMHMMoves + ld b, 0 + ld c, a + add hl, bc + ld a, [hl] + ld [wTempTMHM], a + ret + +INCLUDE "data/moves/tmhm_moves.asm" diff --git a/engine/items/update_item_description.asm b/engine/items/update_item_description.asm new file mode 100644 index 00000000..da56732a --- /dev/null +++ b/engine/items/update_item_description.asm @@ -0,0 +1,13 @@ +UpdateItemDescription: + ld a, [wMenuSelection] + ld [wCurSpecies], a + hlcoord 0, 12 + ld b, 4 + ld c, SCREEN_WIDTH - 2 + call Textbox + ld a, [wMenuSelection] + cp -1 + ret z + decoord 1, 14 + farcall PrintItemDescription + ret |