summaryrefslogtreecommitdiff
path: root/engine/items
diff options
context:
space:
mode:
Diffstat (limited to 'engine/items')
-rw-r--r--engine/items/inventory.asm9
-rwxr-xr-xengine/items/items.asm588
-rwxr-xr-xengine/items/tms.asm6
3 files changed, 428 insertions, 175 deletions
diff --git a/engine/items/inventory.asm b/engine/items/inventory.asm
index d07f64eb..58bcf7e9 100644
--- a/engine/items/inventory.asm
+++ b/engine/items/inventory.asm
@@ -27,16 +27,17 @@ AddItemToInventory_:
ld a, [hli]
and a
jr z, .addNewItem
-.loop
+.notAtEndOfInventory
ld a, [hli]
ld b, a ; b = ID of current item in table
ld a, [wcf91] ; a = ID of item being added
cp b ; does the current item in the table match the item being added?
jp z, .increaseItemQuantity ; if so, increase the item's quantity
inc hl
+.loop
ld a, [hl]
- cp $ff ; is it the end of the table?
- jr nz, .loop
+ cp a, $ff ; is it the end of the table?
+ jr nz, .notAtEndOfInventory
.addNewItem ; add an item not yet in the inventory
pop hl
ld a, d
@@ -101,7 +102,7 @@ RemoveItemFromInventory_:
push hl
inc hl
ld a, [wWhichPokemon] ; index (within the inventory) of the item being removed
- sla a
+ add a
add l
ld l, a
jr nc, .noCarry
diff --git a/engine/items/items.asm b/engine/items/items.asm
index ec51a0d4..15c7c24f 100755
--- a/engine/items/items.asm
+++ b/engine/items/items.asm
@@ -113,7 +113,9 @@ ItemUseBall:
; If this is for the old man battle, skip checking if the party & box are full.
ld a, [wBattleType]
- dec a
+ cp BATTLE_TYPE_OLD_MAN
+ jr z, .canUseBall
+ cp BATTLE_TYPE_PIKACHU
jr z, .canUseBall
ld a, [wPartyCount] ; is party full?
@@ -152,16 +154,26 @@ ItemUseBall:
jp z, .setAnimData
ld a, [wBattleType]
- dec a
- jr nz, .notOldManBattle
+ cp BATTLE_TYPE_OLD_MAN
+ jr z, .oldManBattle
+ cp BATTLE_TYPE_PIKACHU
+ jr z, .oldManBattle ; pikachu battle technically old man battle
+ jr .notOldManBattle
.oldManBattle
ld hl, wGrassRate
ld de, wPlayerName
ld bc, NAME_LENGTH
call CopyData ; save the player's name in the Wild Monster data (part of the Cinnabar Island Missingno. glitch)
+ ld a, [wBattleType]
+ cp BATTLE_TYPE_OLD_MAN
+ jp nz,.captured
+ ld a,$1
+ ld [wCapturedMonSpecies], a
+ CheckEvent EVENT_02F
+ ld b, $63
+ jp nz,.setAnimData
jp .captured
-
.notOldManBattle
; If the player is fighting the ghost Marowak, set the value that indicates the
; Pokémon can't be caught and skip the capture calculations.
@@ -280,6 +292,7 @@ ItemUseBall:
inc a
.skip2
+
; Let W = ((MaxHP * 255) / BallFactor) / max(HP / 4, 1). Calculate W.
ld [H_DIVISOR], a
ld b, 4
@@ -347,6 +360,7 @@ ItemUseBall:
jr z, .skip4
.skip4
+
; Let Y = (CatchRate * 100) / BallFactor2. Calculate Y.
ld a, b
ld [H_DIVISOR], a
@@ -371,7 +385,7 @@ ItemUseBall:
ld [H_DIVISOR], a
ld b, 4
call Divide
-
+
; Determine Status2.
; no status ailment: Status2 = 0
; Burn/Paralysis/Poison: Status2 = 5
@@ -511,9 +525,10 @@ ItemUseBall:
ld [wcf91], a
ld [wd11e], a
ld a, [wBattleType]
- dec a ; is this the old man battle?
- jr z, .oldManCaughtMon ; if so, don't give the player the caught Pokémon
-
+ cp BATTLE_TYPE_OLD_MAN ; is this the old man battle?
+ jp z, .oldManCaughtMon ; if so, don't give the player the caught Pokémon
+ cp BATTLE_TYPE_PIKACHU
+ jr z, .oldManCaughtMon ; same with Pikachu battle
ld hl, ItemUseBallText05
call PrintText
@@ -545,12 +560,18 @@ ItemUseBall:
predef ShowPokedexData
.skipShowingPokedexData
+ ld a, $1
+ ld [wd49c], a
+ ld a, $85
+ ld [wPikachuMood], a
ld a, [wPartyCount]
cp PARTY_LENGTH ; is party full?
jr z, .sendToBox
xor a ; PLAYER_PARTY_DATA
ld [wMonDataLocation], a
call ClearSprites
+ ld hl, .emptyString
+ call PrintText
call AddPartyMon
jr .done
@@ -583,6 +604,9 @@ ItemUseBall:
ld [wItemQuantity], a
jp RemoveItemFromInventory
+.emptyString
+ db "@"
+
ItemUseBallText00:
;"It dodged the thrown ball!"
;"This pokemon can't be caught"
@@ -648,21 +672,28 @@ ItemUseBicycle:
call ItemUseReloadOverworldData
xor a
ld [wWalkBikeSurfState], a ; change player state to walking
+ ld a, $00
+ ld [wPikachuSpawnState], a
call PlayDefaultMusic ; play walking music
ld hl, GotOffBicycleText
- jr .printText
+ jp PrintText
+
.tryToGetOnBike
call IsBikeRidingAllowed
jp nc, NoCyclingAllowedHere
call ItemUseReloadOverworldData
xor a ; no keys pressed
ld [hJoyHeld], a ; current joypad state
- inc a
+ ld a, $1
ld [wWalkBikeSurfState], a ; change player state to bicycling
- ld hl, GotOnBicycleText
call PlayDefaultMusic ; play bike riding music
-.printText
- jp PrintText
+ xor a
+ ld [wWalkBikeSurfState], a
+ ld hl, GotOnBicycleText
+ call PrintText
+ ld a, $1
+ ld [wWalkBikeSurfState], a
+ ret
; used for Surf out-of-battle effect
ItemUseSurfboard:
@@ -672,7 +703,7 @@ ItemUseSurfboard:
jr z, .tryToStopSurfing
.tryToSurf
call IsNextTileShoreOrWater
- jp c, SurfingAttemptFailed
+ jp nc, SurfingAttemptFailed
ld hl, TilePairCollisionsWater
call CheckForTilePairCollisions
jp c, SurfingAttemptFailed
@@ -685,6 +716,7 @@ ItemUseSurfboard:
call PlayDefaultMusic ; play surfing music
ld hl, SurfingGotOnText
jp PrintText
+
.tryToStopSurfing
xor a
ld [hSpriteIndexOrTextID], a
@@ -697,23 +729,20 @@ ItemUseSurfboard:
ld hl, TilePairCollisionsWater
call CheckForTilePairCollisions
jr c, .cannotStopSurfing
- ld hl, wTilesetCollisionPtr ; pointer to list of passable tiles
- ld a, [hli]
- ld h, [hl]
- ld l, a ; hl now points to passable tiles
- ld a, [wTileInFrontOfPlayer] ; tile in front of the player
- ld b, a
-.passableTileLoop
- ld a, [hli]
- cp b
- jr z, .stopSurfing
- cp $ff
- jr nz, .passableTileLoop
+ ld a, [wTileInFrontOfPlayer]
+ ld c, a
+ call IsTilePassable
+ jr nc, .stopSurfing
.cannotStopSurfing
ld hl, SurfingNoPlaceToGetOffText
jp PrintText
+
.stopSurfing
call .makePlayerMoveForward
+ ld a, $3
+ ld [wPikachuSpawnState], a
+ ld hl, wPikachuOverworldStateFlags
+ set 5, [hl]
ld hl, wd730
set 7, [hl]
xor a
@@ -721,7 +750,9 @@ ItemUseSurfboard:
dec a
ld [wJoyIgnore], a
call PlayDefaultMusic ; play walking music
+ call GBPalWhiteOutWithDelay3
jp LoadWalkingPlayerSpriteGraphics
+
; uses a simulated button press to make the player move forward
.makePlayerMoveForward
ld a, [wPlayerDirection] ; direction the player is going
@@ -769,25 +800,43 @@ ItemUseEvoStone:
ld a, $ff
ld [wUpdateSpritesEnabled], a
call DisplayPartyMenu
+ ld a, [wcf91]
+ ld [wLoadedMon], a
pop bc
jr c, .canceledItemUse
ld a, b
ld [wcf91], a
- ld a, $01
- ld [wForceEvolution], a
+ call Func_d85d
+ jr nc, .noEffect
+ callab IsThisPartymonStarterPikachu_Party
+ jr nc, .notPlayerPikachu
+ ld e, $1b
+ callab PlayPikachuSoundClip
+ ld a, [wWhichPokemon]
+ ld hl, wPartyMonNicks
+ call GetPartyMonName
+ ld hl, RefusingText
+ call PrintText
+ ld a, $4
+ ld [wd49c], a
+ ld a, $82
+ ld [wPikachuMood], a
+ jr .canceledItemUse
+
+.notPlayerPikachu
ld a, SFX_HEAL_AILMENT
call PlaySoundWaitForCurrent
call WaitForSoundToFinish
+ ld a, $01
+ ld [wForceEvolution], a
callab TryEvolvingMon ; try to evolve pokemon
- ld a, [wEvolutionOccurred]
- and a
- jr z, .noEffect
pop af
ld [wWhichPokemon], a
ld hl, wNumBagItems
ld a, 1 ; remove 1 stone
ld [wItemQuantity], a
jp RemoveItemFromInventory
+
.noEffect
call ItemUseNoEffect
.canceledItemUse
@@ -796,6 +845,55 @@ ItemUseEvoStone:
pop af
ret
+Func_d85d:
+ ld hl, EvosMovesPointerTable
+ ld a, [wLoadedMon]
+ dec a
+ ld c, a
+ ld b, $0
+ add hl, bc
+ add hl, bc
+ ld de, wcd6d
+ ld a, BANK(TryEvolvingMon)
+ ld bc, $2
+ call FarCopyData
+ ld hl, wcd6d
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld de, wcd6d
+ ld a, BANK(TryEvolvingMon)
+ ld bc, 13
+ call FarCopyData
+ ld hl, wcd6d
+.loop
+ ld a, [hli]
+ and a
+ jr z, .cannotEvolveWithUsedStone
+ inc hl
+ inc hl
+ cp EV_ITEM
+ jr nz, .loop
+ dec hl
+ dec hl
+ ld b, [hl]
+ ld a, [wcf91]
+ inc hl
+ inc hl
+ inc hl
+ cp b
+ jr nz, .loop
+ scf
+ ret
+
+.cannotEvolveWithUsedStone
+ and a
+ ret
+
+RefusingText:
+ TX_FAR _RefusingText
+ db "@"
+
ItemUseVitamin:
ld a, [wIsInBattle]
and a
@@ -804,7 +902,7 @@ ItemUseVitamin:
ItemUseMedicine:
ld a, [wPartyCount]
and a
- jp z, .emptyParty
+ jp z, Func_e4bf
ld a, [wWhichPokemon]
push af
ld a, [wcf91]
@@ -819,15 +917,6 @@ ItemUseMedicine:
; if using softboiled
call GoBackToPartyMenu
jr .getPartyMonDataAddress
-.emptyParty
- ld hl, .emptyPartyText
- xor a
- ld [wActionResultOrTookBattleTurn], a ; item use failed
- jp PrintText
-.emptyPartyText
- text "You don't have"
- line "any #MON!"
- prompt
.notUsingSoftboiled
call DisplayPartyMenu
.getPartyMonDataAddress
@@ -843,6 +932,16 @@ ItemUseMedicine:
ld e, a
ld [wd0b5], a
pop af
+ push af
+ cp $28
+ jr nc, .asm_d906
+ push hl
+ push de
+ callabd_ModifyPikachuHappiness PIKAHAPPY_USEDITEM
+ pop de
+ pop hl
+.asm_d906
+ pop af
ld [wcf91], a
pop af
ld [wWhichPokemon], a
@@ -910,6 +1009,7 @@ ItemUseMedicine:
call CopyData ; copy party stats to in-battle stat data
predef DoubleOrHalveSelectedStats
jp .doneHealing
+
.healHP
inc hl ; hl = address of current HP
ld a, [hli]
@@ -927,7 +1027,22 @@ ItemUseMedicine:
cp MAX_REVIVE
jr z, .updateInBattleFaintedData
jp .healingItemNoEffect
+
.updateInBattleFaintedData
+ ld a, [wWhichPokemon]
+ push af
+ ld a, [wUsedItemOnWhichPokemon]
+ ld [wWhichPokemon], a
+ push hl
+ push de
+ push bc
+ callab Func_2fd6a
+ pop bc
+ pop de
+ pop hl
+ pop af
+ ld [wWhichPokemon], a
+
ld a, [wIsInBattle]
and a
jr z, .compareCurrentHPToMaxHP
@@ -952,6 +1067,7 @@ ItemUseMedicine:
pop de
pop hl
jr .compareCurrentHPToMaxHP
+
.notFainted
ld a, [wcf91]
cp REVIVE
@@ -987,6 +1103,7 @@ ItemUseMedicine:
dec hl
dec hl
jp .cureStatusAilment
+
.notFullHP ; if the pokemon's current HP doesn't equal its max HP
xor a
ld [wLowHealthAlarm], a ;disable low health alarm
@@ -1050,15 +1167,15 @@ ItemUseMedicine:
call AddNTimes ; calculate coordinates of HP bar of pokemon that used Softboiled
ld a, SFX_HEAL_HP
call PlaySoundWaitForCurrent
- ld a, [hFlags_0xFFF6]
+ ld a, [hFlags_0xFFFA]
set 0, a
- ld [hFlags_0xFFF6], a
+ ld [hFlags_0xFFFA], a
ld a, $02
ld [wHPBarType], a
predef UpdateHPBar2 ; animate HP bar decrease of pokemon that used Softboiled
- ld a, [hFlags_0xFFF6]
+ ld a, [hFlags_0xFFFA]
res 0, a
- ld [hFlags_0xFFF6], a
+ ld [hFlags_0xFFFA], a
pop af
ld b, a ; store heal amount (1/5 of max HP)
ld hl, wHPBarOldHP + 1
@@ -1071,6 +1188,7 @@ ItemUseMedicine:
pop af
ld [hl], a
jr .addHealAmount
+
.notUsingSoftboiled2
ld a, [wcf91]
cp SODA_POP
@@ -1125,6 +1243,7 @@ ItemUseMedicine:
cp MAX_REVIVE
jr z, .setCurrentHPToMaxHp ; if using a Max Revive
jr .updateInBattleData
+
.setCurrentHPToHalfMaxHP
dec hl
dec de
@@ -1139,6 +1258,7 @@ ItemUseMedicine:
ld [wHPBarNewHP], a
dec de
jr .doneHealingPartyHP
+
.setCurrentHPToMaxHp
ld a, [hli]
ld [de], a
@@ -1182,9 +1302,11 @@ ItemUseMedicine:
dec d
jr nz, .calculateHPBarCoordsLoop
jr .doneHealing
+
.healingItemNoEffect
call ItemUseNoEffect
jp .done
+
.doneHealing
ld a, [wPseudoItemID]
and a ; using Softboiled?
@@ -1200,15 +1322,15 @@ ItemUseMedicine:
jr z, .playStatusAilmentCuringSound
ld a, SFX_HEAL_HP
call PlaySoundWaitForCurrent
- ld a, [hFlags_0xFFF6]
+ ld a, [hFlags_0xFFFA]
set 0, a
- ld [hFlags_0xFFF6], a
+ ld [hFlags_0xFFFA], a
ld a, $02
ld [wHPBarType], a
predef UpdateHPBar2 ; animate the HP bar lengthening
- ld a, [hFlags_0xFFF6]
+ ld a, [hFlags_0xFFFA]
res 0, a
- ld [hFlags_0xFFF6], a
+ ld [hFlags_0xFFFA], a
ld a, REVIVE_MSG
ld [wPartyMenuTypeOrMessageID], a
ld a, [wcf91]
@@ -1219,6 +1341,7 @@ ItemUseMedicine:
ld a, POTION_MSG
ld [wPartyMenuTypeOrMessageID], a
jr .showHealingItemMessage
+
.playStatusAilmentCuringSound
ld a, SFX_HEAL_AILMENT
call PlaySoundWaitForCurrent
@@ -1235,6 +1358,7 @@ ItemUseMedicine:
call DelayFrames
call WaitForTextScrollButtonPress
jr .done
+
.canceledItemUse
xor a
ld [wActionResultOrTookBattleTurn], a ; item use failed
@@ -1250,6 +1374,7 @@ ItemUseMedicine:
and a
ret nz
jp ReloadMapData
+
.useVitamin
push hl
ld a, [hl]
@@ -1305,6 +1430,7 @@ ItemUseMedicine:
cp b
jr nz, .statNameInnerLoop
jr .statNameLoop
+
.gotStatName
ld de, wcf4b
ld bc, 10
@@ -1314,11 +1440,13 @@ ItemUseMedicine:
ld hl, VitaminStatRoseText
call PrintText
jp RemoveUsedItem
+
.vitaminNoEffect
pop hl
ld hl, VitaminNoEffectText
call PrintText
jp GBPalWhiteOut
+
.recalculateStats
ld bc, wPartyMon1Stats - wPartyMon1
add hl, bc
@@ -1405,9 +1533,19 @@ ItemUseMedicine:
xor a ; PLAYER_PARTY_DATA
ld [wMonDataLocation], a
predef LearnMoveFromLevelUp ; learn level up move, if any
+
xor a
ld [wForceEvolution], a
- callab TryEvolvingMon ; evolve pokemon, if appropriate
+ callabd_ModifyPikachuHappiness PIKAHAPPY_LEVELUP
+ ld a, [wWhichPokemon]
+ push af
+ ld a, [wUsedItemOnWhichPokemon]
+ ld [wWhichPokemon], a
+ callab Func_2fd6a ; evolve pokemon, if appropriate
+ pop af
+ ld [wWhichPokemon], a
+
+ callab TryEvolvingMon
ld a, $01
ld [wUpdateSpritesEnabled], a
pop af
@@ -1494,6 +1632,10 @@ ItemUseEscapeRope:
ld a, [wCurMap]
cp AGATHAS_ROOM
jr z, .notUsable
+ cp BILLS_HOUSE
+ jr z, .notUsable
+ cp POKEMON_FAN_CLUB
+ jr z, .notUsable
ld a, [wCurMapTileset]
ld b, a
ld hl, EscapeRopeTilesets
@@ -1506,6 +1648,7 @@ ItemUseEscapeRope:
ld hl, wd732
set 3, [hl]
set 6, [hl]
+ call Func_1510
ld hl, wd72e
res 4, [hl]
ResetEvent EVENT_IN_SAFARI_ZONE
@@ -1522,6 +1665,7 @@ ItemUseEscapeRope:
ld c, 30
call DelayFrames
jp RemoveUsedItem
+
.notUsable
jp ItemUseNotTime
@@ -1547,6 +1691,7 @@ ItemUseXAccuracy:
jp z, ItemUseNotTime
ld hl, wPlayerBattleStatus2
set USING_X_ACCURACY, [hl] ; X Accuracy bit
+ callabd_ModifyPikachuHappiness PIKAHAPPY_USEDXITEM
jp PrintItemUseTextAndRemoveItem
; This function is bugged and never works. It always jumps to ItemUseNotTime.
@@ -1560,11 +1705,13 @@ ItemUseCardKey:
jr nz, .next0
ld hl, CardKeyTable1
jr .next1
+
.next0
cp $24
jr nz, .next2
ld hl, CardKeyTable2
jr .next1
+
.next2
cp $5e
jp nz, ItemUseNotTime
@@ -1587,6 +1734,7 @@ ItemUseCardKey:
ld a, [hl]
ld [wUnusedD71F], a
jr .done
+
.nextEntry1
inc hl
.nextEntry2
@@ -1594,6 +1742,7 @@ ItemUseCardKey:
.nextEntry3
inc hl
jr .loop
+
.done
ld hl, ItemUseText00
call PrintText
@@ -1612,34 +1761,34 @@ ItemUseCardKey:
; 03: ID?
CardKeyTable1:
- db SILPH_CO_2F,$04,$04,$00
- db SILPH_CO_2F,$04,$05,$01
- db SILPH_CO_4F,$0C,$04,$02
- db SILPH_CO_4F,$0C,$05,$03
- db SILPH_CO_7F,$06,$0A,$04
- db SILPH_CO_7F,$06,$0B,$05
- db SILPH_CO_9F,$04,$12,$06
- db SILPH_CO_9F,$04,$13,$07
- db SILPH_CO_10F,$08,$0A,$08
- db SILPH_CO_10F,$08,$0B,$09
+ db SILPH_CO_2F, $04, $04, $00
+ db SILPH_CO_2F, $04, $05, $01
+ db SILPH_CO_4F, $0C, $04, $02
+ db SILPH_CO_4F, $0C, $05, $03
+ db SILPH_CO_7F, $06, $0A, $04
+ db SILPH_CO_7F, $06, $0B, $05
+ db SILPH_CO_9F, $04, $12, $06
+ db SILPH_CO_9F, $04, $13, $07
+ db SILPH_CO_10F, $08, $0A, $08
+ db SILPH_CO_10F, $08, $0B, $09
db $ff
CardKeyTable2:
- db SILPH_CO_3F,$08,$09,$0A
- db SILPH_CO_3F,$09,$09,$0B
- db SILPH_CO_5F,$04,$07,$0C
- db SILPH_CO_5F,$05,$07,$0D
- db SILPH_CO_6F,$0C,$05,$0E
- db SILPH_CO_6F,$0D,$05,$0F
- db SILPH_CO_8F,$08,$07,$10
- db SILPH_CO_8F,$09,$07,$11
- db SILPH_CO_9F,$08,$03,$12
- db SILPH_CO_9F,$09,$03,$13
+ db SILPH_CO_3F, $08, $09, $0A
+ db SILPH_CO_3F, $09, $09, $0B
+ db SILPH_CO_5F, $04, $07, $0C
+ db SILPH_CO_5F, $05, $07, $0D
+ db SILPH_CO_6F, $0C, $05, $0E
+ db SILPH_CO_6F, $0D, $05, $0F
+ db SILPH_CO_8F, $08, $07, $10
+ db SILPH_CO_8F, $09, $07, $11
+ db SILPH_CO_9F, $08, $03, $12
+ db SILPH_CO_9F, $09, $03, $13
db $ff
CardKeyTable3:
- db SILPH_CO_11F,$08,$09,$14
- db SILPH_CO_11F,$09,$09,$15
+ db SILPH_CO_11F, $08, $09, $14
+ db SILPH_CO_11F, $09, $09, $15
db $ff
ItemUsePokedoll:
@@ -1654,6 +1803,15 @@ ItemUseGuardSpec:
ld a, [wIsInBattle]
and a
jp z, ItemUseNotTime
+
+ ld a, [wWhichPokemon]
+ push af
+ ld a, [wPlayerMonNumber]
+ ld [wWhichPokemon], a
+ callabd_ModifyPikachuHappiness PIKAHAPPY_USEDXITEM
+ pop af
+ ld [wWhichPokemon], a
+
ld hl, wPlayerBattleStatus2
set PROTECTED_BY_MIST, [hl] ; Mist bit
jp PrintItemUseTextAndRemoveItem
@@ -1670,6 +1828,15 @@ ItemUseDireHit:
ld a, [wIsInBattle]
and a
jp z, ItemUseNotTime
+
+ ld a, [wWhichPokemon]
+ push af
+ ld a, [wPlayerMonNumber]
+ ld [wWhichPokemon], a
+ callabd_ModifyPikachuHappiness PIKAHAPPY_USEDXITEM
+ pop af
+ ld [wWhichPokemon], a
+
ld hl, wPlayerBattleStatus2
set GETTING_PUMPED, [hl] ; Focus Energy bit
jp PrintItemUseTextAndRemoveItem
@@ -1682,6 +1849,7 @@ ItemUseXStat:
ld a, 2
ld [wActionResultOrTookBattleTurn], a ; item not used
ret
+
.inBattle
ld hl, wPlayerMoveNum
ld a, [hli]
@@ -1700,6 +1868,15 @@ ItemUseXStat:
xor a
ld [H_WHOSETURN], a ; set turn to player's turn
callba StatModifierUpEffect ; do stat increase move
+
+ ld a, [wWhichPokemon]
+ push af
+ ld a, [wPlayerMonNumber]
+ ld [wWhichPokemon], a
+ callabd_ModifyPikachuHappiness PIKAHAPPY_USEDXITEM
+ pop af
+ ld [wWhichPokemon], a
+
pop hl
pop af
ld [hld], a ; restore [wPlayerMoveEffect]
@@ -1717,31 +1894,48 @@ ItemUsePokeflute:
cp ROUTE_12
jr nz, .notRoute12
CheckEvent EVENT_BEAT_ROUTE12_SNORLAX
- jr nz, .noSnorlaxToWakeUp
+ jr nz, .noSnorlaxOrPikachuToWakeUp
; if the player hasn't beaten Route 12 Snorlax
ld hl, Route12SnorlaxFluteCoords
call ArePlayerCoordsInArray
- jr nc, .noSnorlaxToWakeUp
+ jr nc, .noSnorlaxOrPikachuToWakeUp
ld hl, PlayedFluteHadEffectText
call PrintText
SetEvent EVENT_FIGHT_ROUTE12_SNORLAX
ret
+
.notRoute12
cp ROUTE_16
- jr nz, .noSnorlaxToWakeUp
+ jr nz, .notRoute16
CheckEvent EVENT_BEAT_ROUTE16_SNORLAX
- jr nz, .noSnorlaxToWakeUp
+ jr nz, .noSnorlaxOrPikachuToWakeUp
; if the player hasn't beaten Route 16 Snorlax
ld hl, Route16SnorlaxFluteCoords
call ArePlayerCoordsInArray
- jr nc, .noSnorlaxToWakeUp
+ jr nc, .noSnorlaxOrPikachuToWakeUp
ld hl, PlayedFluteHadEffectText
call PrintText
SetEvent EVENT_FIGHT_ROUTE16_SNORLAX
ret
-.noSnorlaxToWakeUp
+
+.notRoute16
+ cp PEWTER_POKECENTER
+ jr nz, .noSnorlaxOrPikachuToWakeUp
+ call CheckPikachuFollowingPlayer
+ jr z, .noSnorlaxOrPikachuToWakeUp
+ callab IsPikachuRightNextToPlayer
+ jr nc, .noSnorlaxOrPikachuToWakeUp
+ ld hl, PlayedFluteHadEffectText
+ call PrintText
+ call ItemUseReloadOverworldData
+ ldpikaemotion e, PikachuEmotion26
+ callab PlaySpecificPikachuEmotion
+ ret
+
+.noSnorlaxOrPikachuToWakeUp
ld hl, PlayedFluteNoEffectText
jp PrintText
+
.inBattle
xor a
ld [wWereAnyMonsAsleep], a
@@ -1761,8 +1955,15 @@ ItemUsePokeflute:
ld [hl], a
ld hl, wEnemyMonStatus
ld a, [hl]
+ ld c, a
and b ; remove Sleep status
ld [hl], a
+ ld a, c
+ and SLP
+ jr z, .asm_e063
+ ld a, $1
+ ld [wWereAnyMonsAsleep], a
+.asm_e063
call LoadScreenTilesFromBuffer2 ; restore saved screen
ld a, [wWereAnyMonsAsleep]
and a ; were any pokemon asleep before playing the flute?
@@ -1814,18 +2015,18 @@ WakeUpEntireParty:
; 00: Y
; 01: X
Route12SnorlaxFluteCoords:
- db 62,9 ; one space West of Snorlax
- db 61,10 ; one space North of Snorlax
- db 63,10 ; one space South of Snorlax
- db 62,11 ; one space East of Snorlax
+ db 62, 9 ; one space West of Snorlax
+ db 61, 10 ; one space North of Snorlax
+ db 63, 10 ; one space South of Snorlax
+ db 62, 11 ; one space East of Snorlax
db $ff ; terminator
; Format:
; 00: Y
; 01: X
Route16SnorlaxFluteCoords:
- db 10,27 ; one space East of Snorlax
- db 10,25 ; one space West of Snorlax
+ db 10, 27 ; one space East of Snorlax
+ db 10, 25 ; one space West of Snorlax
db $ff ; terminator
PlayedFluteNoEffectText:
@@ -1844,8 +2045,7 @@ PlayedFluteHadEffectText:
and a
jr nz, .done
; play out-of-battle pokeflute music
- ld a, $ff
- call PlaySound ; turn off music
+ call StopAllMusic ; turn off music
ld a, SFX_POKEFLUTE
ld c, BANK(SFX_Pokeflute)
call PlayMusic
@@ -1906,13 +2106,28 @@ INCLUDE "data/good_rod.asm"
ItemUseSuperRod:
call FishingInit
jp c, ItemUseNotTime
- call ReadSuperRodData
- ld a, e
+ callab ReadSuperRodData
+ ld c, e
+ ld b, d
+ ld a, $2
+ ld [wRodResponse], a
+ ld a, c
+ and a ; are there fish in the map?
+ jr z, DoNotGenerateFishingEncounter ; if not, do not generate an encounter
+ ld a, $1
+ ld [wRodResponse], a
+ call Random
+ and $1
+ jr nz, RodResponse
+ xor a
+ ld [wRodResponse], a
+ jr DoNotGenerateFishingEncounter
+
RodResponse:
ld [wRodResponse], a
dec a ; is there a bite?
- jr nz, .next
+ jr nz, DoNotGenerateFishingEncounter
; if yes, store level and species data
ld a, 1
ld [wMoveMissed], a
@@ -1921,7 +2136,7 @@ RodResponse:
ld a, c ; species
ld [wCurOpponent], a
-.next
+DoNotGenerateFishingEncounter:
ld hl, wWalkBikeSurfState
ld a, [hl] ; store the value in a
push af
@@ -1941,22 +2156,28 @@ FishingInit:
jr z, .notInBattle
scf ; can't fish during battle
ret
+
.notInBattle
call IsNextTileShoreOrWater
- ret c
+ jr nc, .cannotFish
ld a, [wWalkBikeSurfState]
cp 2 ; Surfing?
- jr z, .surfing
+ jr z, .cannotFish
call ItemUseReloadOverworldData
ld hl, ItemUseText00
call PrintText
ld a, SFX_HEAL_AILMENT
call PlaySound
+ ld a, $2
+ ld [wd49c], a
+ ld a, $81
+ ld [wPikachuMood], a
ld c, 80
call DelayFrames
and a
ret
-.surfing
+
+.cannotFish
scf ; can't fish when surfing
ret
@@ -2009,7 +2230,23 @@ ItemUsePPRestore:
call DisplayPartyMenu
jr nc, .chooseMove
jp .itemNotUsed
+
.chooseMove
+ ld a, [wIsInBattle]
+ and a
+ jr z, .usePPItem
+ ld a, [wWhichPokemon]
+ ld b, a
+ ld a, [wPlayerMonNumber]
+ cp b
+ jr nz, .usePPItem
+ ld a, [wPlayerBattleStatus3]
+ bit TRANSFORMED, a
+ jr z, .usePPItem
+ call ItemUseNotTime
+ jp .itemNotUsed
+
+.usePPItem
ld a, [wPPRestoreItem]
cp ELIXER
jp nc, .useElixir ; if Elixir or Max Elixir
@@ -2049,6 +2286,7 @@ ItemUsePPRestore:
ld hl, PPMaxedOutText
call PrintText
jr .chooseMove
+
.PPNotMaxedOut
ld a, [hl]
add 1 << 6 ; increase PP Up count by 1
@@ -2056,6 +2294,8 @@ ItemUsePPRestore:
ld a, 1 ; 1 PP Up used
ld [wd11e], a
call RestoreBonusPP ; add the bonus PP to current PP
+ ld a, SFX_HEAL_AILMENT
+ call PlaySound
ld hl, PPIncreasedText
call PrintText
.done
@@ -2064,6 +2304,7 @@ ItemUsePPRestore:
call GBPalWhiteOut
call RunDefaultPaletteCommand
jp RemoveUsedItem
+
.afterRestoringPP ; after using a (Max) Ether/Elixir
ld a, [wWhichPokemon]
ld b, a
@@ -2082,10 +2323,12 @@ ItemUsePPRestore:
ld hl, PPRestoredText
call PrintText
jr .done
+
.useEther
call .restorePP
jr nz, .afterRestoringPP
jp .noEffect
+
; unsets zero flag if PP was restored, sets zero flag if not
; however, this is bugged for Max Ethers and Max Elixirs (see below)
.restorePP
@@ -2120,6 +2363,7 @@ ItemUsePPRestore:
add b
ld [hl], a
ret
+
.fullyRestorePP
ld a, [hl] ; move PP
; Note that this code has a bug. It doesn't mask out the upper two bits, which
@@ -2129,6 +2373,7 @@ ItemUsePPRestore:
cp b ; does current PP equal max PP?
ret z
jr .storeNewAmount
+
.useElixir
; decrement the item ID so that ELIXER becomes ETHER and MAX_ELIXER becomes MAX_ETHER
ld hl, wPPRestoreItem
@@ -2232,6 +2477,7 @@ ItemUseTMHM:
ld a, 2
ld [wActionResultOrTookBattleTurn], a ; item not used
ret
+
.useMachine
ld a, [wWhichPokemon]
push af
@@ -2277,10 +2523,13 @@ ItemUseTMHM:
ld hl, MonCannotLearnMachineMoveText
call PrintText
jr .chooseMon
+
.checkIfAlreadyLearnedMove
callab CheckIfMoveIsKnown ; check if the pokemon already knows the move
jr c, .chooseMon
predef LearnMove ; teach move
+ ld a, [wWhichPokemon]
+ ld d, a
pop af
ld [wcf91], a
pop af
@@ -2288,6 +2537,28 @@ ItemUseTMHM:
ld a, b
and a
ret z
+
+ ld a, [wWhichPokemon]
+ push af
+ ld a, d
+ ld [wWhichPokemon], a
+ callabd_ModifyPikachuHappiness PIKAHAPPY_USEDTMHM
+ callab IsThisPartymonStarterPikachu_Party
+ jr nc, .notTeachingThunderboltOrThunderToPikachu
+ ld a, [wcf91]
+ cp TM_24 ; are we teaching thunderbolt to the player pikachu?
+ jr z, .teachingThunderboltOrThunderToPlayerPikachu
+ cp TM_25 ; are we teaching thunder then?
+ jr nz, .notTeachingThunderboltOrThunderToPikachu
+.teachingThunderboltOrThunderToPlayerPikachu
+ ld a, $5
+ ld [wd49c], a
+ ld a, $85
+ ld [wPikachuMood], a
+.notTeachingThunderboltOrThunderToPikachu
+ pop af
+ ld [wWhichPokemon], a
+
ld a, [wcf91]
call IsItemHM
ret c
@@ -2334,6 +2605,12 @@ ItemUseNotYoursToUse:
ld hl, ItemUseNotYoursToUseText
jr ItemUseFailed
+Func_e4bf:
+ ld a, $2
+ ld [wActionResultOrTookBattleTurn], a
+ ld hl, DontHavePokemonText
+ jp PrintText
+
ThrowBallAtTrainerMon:
call RunDefaultPaletteCommand
call LoadScreenTilesFromBuffer1 ; restore saved screen
@@ -2395,6 +2672,10 @@ BoxFullCannotThrowBallText:
TX_FAR _BoxFullCannotThrowBallText
db "@"
+DontHavePokemonText:
+ TX_FAR _DontHavePokemonText
+ db "@"
+
ItemUseText00:
TX_FAR _ItemUseText001
TX_LINE
@@ -2529,6 +2810,7 @@ GetMaxPP:
.sourceWithOneMon
call GetSelectedMoveOffset2
jr .next
+
.sourceWithMultipleMon
call GetSelectedMoveOffset
.next
@@ -2630,6 +2912,7 @@ TossItem_:
pop hl
and a
ret
+
.tooImportantToToss
push hl
ld hl, TooImportantToTossText
@@ -2696,7 +2979,7 @@ SendNewMonToBox:
ld a, [wcf91]
ld [wd0b5], a
ld c, a
-.asm_e7b1
+.asm_e6f5
inc de
ld a, [de]
ld b, a
@@ -2704,13 +2987,13 @@ SendNewMonToBox:
ld c, b
ld [de], a
cp $ff
- jr nz, .asm_e7b1
+ jr nz, .asm_e6f5
call GetMonHeader
ld hl, wBoxMonOT
ld bc, NAME_LENGTH
ld a, [wNumInBox]
dec a
- jr z, .asm_e7ee
+ jr z, .asm_e732
dec a
call AddNTimes
push hl
@@ -2722,7 +3005,7 @@ SendNewMonToBox:
ld a, [wNumInBox]
dec a
ld b, a
-.asm_e7db
+.asm_e71f
push bc
push hl
ld bc, NAME_LENGTH
@@ -2734,15 +3017,15 @@ SendNewMonToBox:
add hl, bc
pop bc
dec b
- jr nz, .asm_e7db
-.asm_e7ee
+ jr nz, .asm_e71f
+.asm_e732
ld hl, wPlayerName
ld de, wBoxMonOT
ld bc, NAME_LENGTH
call CopyData
ld a, [wNumInBox]
dec a
- jr z, .asm_e82a
+ jr z, .asm_e76e
ld hl, wBoxMonNicks
ld bc, NAME_LENGTH
dec a
@@ -2756,7 +3039,7 @@ SendNewMonToBox:
ld a, [wNumInBox]
dec a
ld b, a
-.asm_e817
+.asm_e75b
push bc
push hl
ld bc, NAME_LENGTH
@@ -2768,15 +3051,15 @@ SendNewMonToBox:
add hl, bc
pop bc
dec b
- jr nz, .asm_e817
-.asm_e82a
+ jr nz, .asm_e75b
+.asm_e76e
ld hl, wBoxMonNicks
ld a, NAME_MON_SCREEN
ld [wNamingScreenType], a
predef AskName
ld a, [wNumInBox]
dec a
- jr z, .asm_e867
+ jr z, .asm_e7ab
ld hl, wBoxMons
ld bc, wBoxMon2 - wBoxMon1
dec a
@@ -2790,7 +3073,7 @@ SendNewMonToBox:
ld a, [wNumInBox]
dec a
ld b, a
-.asm_e854
+.asm_e798
push bc
push hl
ld bc, wBoxMon2 - wBoxMon1
@@ -2802,8 +3085,8 @@ SendNewMonToBox:
add hl, bc
pop bc
dec b
- jr nz, .asm_e854
-.asm_e867
+ jr nz, .asm_e798
+.asm_e7ab
ld a, [wEnemyMonLevel]
ld [wEnemyMonBoxLevel], a
ld hl, wEnemyMon
@@ -2833,11 +3116,11 @@ SendNewMonToBox:
inc de
xor a
ld b, NUM_STATS * 2
-.asm_e89f
+.asm_e7e3
ld [de], a
inc de
dec b
- jr nz, .asm_e89f
+ jr nz, .asm_e7e3
ld hl, wEnemyMonDVs
ld a, [hli]
ld [de], a
@@ -2846,12 +3129,18 @@ SendNewMonToBox:
ld [de], a
ld hl, wEnemyMonPP
ld b, NUM_MOVES
-.asm_e8b1
+.asm_e7f5
ld a, [hli]
inc de
ld [de], a
dec b
- jr nz, .asm_e8b1
+ jr nz, .asm_e7f5
+ ld a, [wcf91]
+ cp KADABRA
+ jr nz, .notKadabra
+ ld a, $60 ; twistedspoon in gsc
+ ld [wBoxMon1CatchRate], a
+.notKadabra
ret
; checks if the tile in front of the player is a shore or water tile
@@ -2861,24 +3150,21 @@ IsNextTileShoreOrWater:
ld a, [wCurMapTileset]
ld hl, WaterTilesets
ld de, 1
- call IsInArray
- jr nc, .notShoreOrWater
+ call IsInArray ; does the current map allow surfing?
+ ret nc ; if not, return
+ ld hl, WaterTile
ld a, [wCurMapTileset]
cp SHIP_PORT ; Vermilion Dock tileset
- ld a, [wTileInFrontOfPlayer] ; tile in front of player
jr z, .skipShoreTiles ; if it's the Vermilion Dock tileset
- cp $48 ; eastern shore tile in Safari Zone
- jr z, .shoreOrWater
- cp $32 ; usual eastern shore tile
- jr z, .shoreOrWater
+ cp GYM ; eastern shore tile in Safari Zone
+ jr z, .skipShoreTiles
+ cp DOJO ; usual eastern shore tile
+ jr z, .skipShoreTiles
+ ld hl, ShoreTiles
.skipShoreTiles
- cp $14 ; water tile
- jr z, .shoreOrWater
-.notShoreOrWater
- scf
- ret
-.shoreOrWater
- and a
+ ld a, [wTileInFrontOfPlayer]
+ ld de, $1
+ call IsInArray
ret
; tilesets with water
@@ -2886,52 +3172,12 @@ WaterTilesets:
db OVERWORLD, FOREST, DOJO, GYM, SHIP, SHIP_PORT, CAVERN, FACILITY, PLATEAU
db $ff ; terminator
-ReadSuperRodData:
-; return e = 2 if no fish on this map
-; return e = 1 if a bite, bc = level,species
-; return e = 0 if no bite
- ld a, [wCurMap]
- ld de, 3 ; each fishing group is three bytes wide
- ld hl, SuperRodData
- call IsInArray
- jr c, .ReadFishingGroup
- ld e, $2 ; $2 if no fishing groups found
- ret
-
-.ReadFishingGroup
-; hl points to the fishing group entry in the index
- inc hl ; skip map id
-
- ; read fishing group address
- ld a, [hli]
- ld h, [hl]
- ld l, a
-
- ld b, [hl] ; how many mons in group
- inc hl ; point to data
- ld e, $0 ; no bite yet
-
-.RandomLoop
- call Random
- srl a
- ret c ; 50% chance of no battle
-
- and %11 ; 2-bit random number
- cp b
- jr nc, .RandomLoop ; if a is greater than the number of mons, regenerate
-
- ; get the mon
- add a
- ld c, a
- ld b, $0
- add hl, bc
- ld b, [hl] ; level
- inc hl
- ld c, [hl] ; species
- ld e, $1 ; $1 if there's a bite
- ret
-
-INCLUDE "data/super_rod.asm"
+; shore tiles
+ShoreTiles:
+ db $48, $32
+WaterTile:
+ db $14
+ db $ff ; terminator
; reloads map view and processes sprite data
; for items that cause the overworld to be displayed
diff --git a/engine/items/tms.asm b/engine/items/tms.asm
index da1b5e72..84770747 100755
--- a/engine/items/tms.asm
+++ b/engine/items/tms.asm
@@ -11,6 +11,8 @@ CanLearnTM:
ld hl, TechnicalMachines
.findTMloop
ld a, [hli]
+ cp $ff ; reached terminator?
+ jr z, .done
cp b
jr z, .TMfoundLoop
inc c
@@ -19,6 +21,10 @@ CanLearnTM:
pop hl
ld b, FLAG_TEST
predef_jump FlagActionPredef
+.done
+ pop hl
+ ld c, 0
+ ret
; converts TM/HM number in wd11e into move number
; HMs start at 51