pokeyellow/engine/evos_moves.asm
luckytyphlosion f0915e2b66 More BankF documentation
Also introduce bit direction constants and setpal macros
2015-12-29 14:53:57 -05:00

670 lines
12 KiB
NASM
Executable File

; try to evolve the mon in [wWhichPokemon]
TryEvolvingMon: ; 3adb8 (e:6db8)
EvolveTradeMon:
ld hl, wCanEvolveFlags
xor a
ld [hl], a
ld a, [wWhichPokemon]
ld c, a
ld b, FLAG_SET
call Evolution_FlagAction
; this is only called after battle
; it is supposed to do level up evolutions, though there is a bug that allows item evolutions to occur
EvolutionAfterBattle: ; 3adc6 (e:6dc6)
ld a, [hTilesetType]
push af
xor a
ld [wEvolutionOccurred], a
dec a
ld [wWhichPokemon], a
push hl
push bc
push de
ld hl, wPartyCount
push hl
Evolution_PartyMonLoop: ; 3add8 (e:6dd8)
; loop over party mons
ld hl, wWhichPokemon
inc [hl]
pop hl
inc hl
ld a, [hl]
cp $ff ; have we reached the end of the party?
jp z, .done
ld [wEvoOldSpecies], a
push hl
ld a, [wWhichPokemon]
ld c, a
ld hl, wCanEvolveFlags
ld b, FLAG_TEST
call Evolution_FlagAction
ld a, c
and a ; is the mon's bit set?
jp z, Evolution_PartyMonLoop ; if not, go to the next mon
ld a, [wEvoOldSpecies]
dec a
ld b, 0
ld hl, EvosMovesPointerTable
add a
rl b
ld c, a
add hl, bc
ld a, [hli]
ld h, [hl]
ld l, a
push hl
ld a, [wcf91]
push af
xor a ; PLAYER_PARTY_DATA
ld [wMonDataLocation], a
call LoadMonData
pop af
ld [wcf91], a
pop hl
.evoEntryLoop ; loop over evolution entries
ld a, [hli]
and a ; have we reached the end of the evolution data?
jr z, Evolution_PartyMonLoop
ld b, a ; evolution type
cp EV_TRADE
jr z, .checkTradeEvo
; not trade evolution
ld a, [wLinkState]
cp LINK_STATE_TRADING
jr z, Evolution_PartyMonLoop ; if trading, go the next mon
ld a, b
cp EV_ITEM
jr z, .checkItemEvo
ld a, [wForceEvolution]
and a
jr nz, Evolution_PartyMonLoop
ld a, b
cp EV_LEVEL
jr z, .checkLevel
.checkTradeEvo
ld a, [wLinkState]
cp LINK_STATE_TRADING
jp nz, .nextEvoEntry1 ; if not trading, go to the next evolution entry
ld a, [hli] ; level requirement
ld b, a
ld a, [wLoadedMonLevel]
cp b ; is the mon's level greater than the evolution requirement?
jp c, Evolution_PartyMonLoop ; if so, go the next mon
jr .doEvolution
.checkItemEvo
ld a, [wIsInBattle] ; are we in battle?
and a
ld a, [hli]
jp nz, .nextEvoEntry1 ; don't evolve if we're in a battle as wcf91 could be holding the last mon sent out
ld b, a ; evolution item
ld a, [wcf91] ; last item used
cp b ; was the evolution item in this entry used?
jp nz, .nextEvoEntry1 ; if not, go to the next evolution entry
.checkLevel
ld a, [hli] ; level requirement
ld b, a
ld a, [wLoadedMonLevel]
cp b ; is the mon's level greater than the evolution requirement?
jp c, .nextEvoEntry2 ; if so, go the next evolution entry
.doEvolution
ld [wCurEnemyLVL], a
ld a, 1
ld [wEvolutionOccurred], a
push hl
ld a, [hl]
ld [wEvoNewSpecies], a
ld a, [wWhichPokemon]
ld hl, wPartyMonNicks
call GetPartyMonName
call CopyStringToCF4B
ld hl, IsEvolvingText
call PrintText
ld c, 50
call DelayFrames
xor a
ld [H_AUTOBGTRANSFERENABLED], a
coord hl, 0, 0
lb bc, 12, 20
call ClearScreenArea
ld a, $1
ld [H_AUTOBGTRANSFERENABLED], a
ld a, $ff
ld [wUpdateSpritesEnabled], a
call ClearSprites
callab EvolveMon
jp c, CancelledEvolution
ld hl, EvolvedText
call PrintText
pop hl
ld a, [hl]
ld [wd0b5], a
ld [wLoadedMonSpecies], a
ld [wEvoNewSpecies], a
ld a, MONSTER_NAME
ld [wNameListType], a
ld a, BANK(MonsterNames) ; bank is not used for monster names
ld [wPredefBank], a
call GetName
push hl
ld hl, IntoText
call PrintText_NoCreatingTextBox
ld a, SFX_GET_ITEM_2
call PlaySoundWaitForCurrent
call WaitForSoundToFinish
ld c, 40
call DelayFrames
call ClearScreen
call RenameEvolvedMon
ld a, [wd11e]
push af
ld a, [wd0b5]
ld [wd11e], a
predef IndexToPokedex
ld a, [wd11e]
dec a
ld hl, BaseStats
ld bc, MonBaseStatsEnd - MonBaseStats
call AddNTimes
ld de, wMonHeader
call CopyData
ld a, [wd0b5]
ld [wMonHIndex], a
pop af
ld [wd11e], a
ld hl, wLoadedMonHPExp - 1
ld de, wLoadedMonStats
ld b, $1
call CalcStats
ld a, [wWhichPokemon]
ld hl, wPartyMon1
ld bc, wPartyMon2 - wPartyMon1
call AddNTimes
ld e, l
ld d, h
push hl
push bc
ld bc, wPartyMon1MaxHP - wPartyMon1
add hl, bc
ld a, [hli]
ld b, a
ld c, [hl]
ld hl, wLoadedMonMaxHP + 1
ld a, [hld]
sub c
ld c, a
ld a, [hl]
sbc b
ld b, a
ld hl, wLoadedMonHP + 1
ld a, [hl]
add c
ld [hld], a
ld a, [hl]
adc b
ld [hl], a
dec hl
pop bc
call CopyData
ld a, [wd0b5]
ld [wd11e], a
xor a
ld [wMonDataLocation], a
call LearnMoveFromLevelUp
pop hl
predef SetPartyMonTypes
ld a, [wIsInBattle]
and a
call z, Evolution_ReloadTilesetTilePatterns
predef IndexToPokedex
ld a, [wd11e]
dec a
ld c, a
ld b, FLAG_SET
ld hl, wPokedexOwned
push bc
call Evolution_FlagAction
pop bc
ld hl, wPokedexSeen
call Evolution_FlagAction
pop de
pop hl
ld a, [wLoadedMonSpecies]
ld [hl], a
push hl
ld l, e
ld h, d
jr .nextEvoEntry2
.nextEvoEntry1
inc hl
.nextEvoEntry2
inc hl
jp .evoEntryLoop
.done
pop de
pop bc
pop hl
pop af
ld [hTilesetType], a
ld a, [wLinkState]
cp LINK_STATE_TRADING
ret z
ld a, [wIsInBattle]
and a
ret nz
ld a, [wEvolutionOccurred]
and a
call nz, PlayDefaultMusic
ret
RenameEvolvedMon: ; 3afa8 (e:6fa8)
; Renames the mon to its new, evolved form's standard name unless it had a
; nickname, in which case the nickname is kept.
ld a, [wd0b5]
push af
ld a, [wMonHIndex]
ld [wd0b5], a
call GetName
pop af
ld [wd0b5], a
ld hl, wcd6d
ld de, wcf4b
.compareNamesLoop
ld a, [de]
inc de
cp [hl]
inc hl
ret nz
cp "@"
jr nz, .compareNamesLoop
ld a, [wWhichPokemon]
ld bc, NAME_LENGTH
ld hl, wPartyMonNicks
call AddNTimes
push hl
call GetName
ld hl, wcd6d
pop de
jp CopyData
CancelledEvolution: ; 3afdf (e:6fdf)
ld hl, StoppedEvolvingText
call PrintText
call ClearScreen
pop hl
call Evolution_ReloadTilesetTilePatterns
jp Evolution_PartyMonLoop
EvolvedText: ; 3afef (e:6fef)
TX_FAR _EvolvedText
db "@"
IntoText: ; 3aff4 (e:6ff4)
TX_FAR _IntoText
db "@"
StoppedEvolvingText: ; 3aff9 (e:6ff9)
TX_FAR _StoppedEvolvingText
db "@"
IsEvolvingText: ; 3affe (e:6ffes)
TX_FAR _IsEvolvingText
db "@"
Evolution_ReloadTilesetTilePatterns: ; 3b003 (e:7003)
ld a, [wLinkState]
cp LINK_STATE_TRADING
ret z
jp ReloadTilesetTilePatterns
LearnMoveFromLevelUp: ; 3b00c (e:700c)
ld a, [wd11e] ; species
ld [wcf91], a
call GetMonLearnset
.learnSetLoop ; loop over the learn set until we reach a move that is learnt at the current level or the end of the list
ld a, [hli]
and a ; have we reached the end of the learn set?
jr z, .done ; if we've reached the end of the learn set, jump
ld b, a ; level the move is learnt at
ld a, [wCurEnemyLVL]
cp b ; is the move learnt at the mon's current level?
ld a, [hli] ; move ID
jr nz, .learnSetLoop
ld d, a ; ID of move to learn
ld a, [wMonDataLocation]
and a
jr nz, .next
; If [wMonDataLocation] is 0 (PLAYER_PARTY_DATA), get the address of the mon's
; current moves in party data. Every call to this function sets
; [wMonDataLocation] to 0 because other data locations are not supported.
; If it is not 0, this function will not work properly.
ld hl, wPartyMon1Moves
ld a, [wWhichPokemon]
ld bc, wPartyMon2 - wPartyMon1
call AddNTimes
.next
ld b, NUM_MOVES
.checkCurrentMovesLoop ; check if the move to learn is already known
ld a, [hli]
cp d
jr z, .done ; if already known, jump
dec b
jr nz, .checkCurrentMovesLoop
ld a, d
ld [wMoveNum], a
ld [wd11e], a
call GetMoveName
call CopyStringToCF4B
predef LearnMove
ld a, b
and a
jr z, .done
callab IsThisPartymonStarterPikachu_Party
jr nc, .done
ld a, [wMoveNum]
cp THUNDERBOLT
jr z, .foundThunderOrThunderbolt
cp THUNDER
jr nz, .done
.foundThunderOrThunderbolt
ld a, $5
ld [wd49c], a
ld a, $85
ld [wPikachuMood], a
.done
ld a, [wcf91]
ld [wd11e], a
ret
Func_3b079: ; 3b079 (e:7079)
ld a, [wcf91]
push af
call Func_3b0a2
jr c, .asm_3b09c
call Func_3b10f
jr nc, .asm_3b096
call Func_3b0a2
jr c, .asm_3b09c
call Func_3b10f
jr nc, .asm_3b096
call Func_3b0a2
jr c, .asm_3b09c
.asm_3b096
pop af
ld [wcf91], a
and a
ret
.asm_3b09c
pop af
ld [wcf91], a
scf
ret
Func_3b0a2: ; 3b0a2 (e:70a2)
; XXX what is wcf91 entering this function?
ld a, [wd11e]
ld [wMoveNum], a
predef CanLearnTM
ld a, c
and a
jr nz, .asm_3b0ec
ld hl, Pointer_3b0ee
ld a, [wcf91]
ld de, $1
call IsInArray
jr c, .asm_3b0d2
ld a, $ff
ld [wMonHGrowthRate], a
ld a, [wd11e]
ld hl, wMonHMoves
ld de, $1
call IsInArray
jr c, .asm_3b0ec
.asm_3b0d2
ld a, [wd11e]
ld d, a
call GetMonLearnset
.loop
ld a, [hli]
and a
jr z, .asm_3b0ea
ld b, a
ld a, [wCurEnemyLVL]
cp b
jr c, .asm_3b0ea
ld a, [hli]
cp d
jr z, .asm_3b0ec
jr .loop
.asm_3b0ea
and a
ret
.asm_3b0ec
scf
ret
Pointer_3b0ee: ; 3b0ee (e:70ee)
db NIDOKING
db IVYSAUR
db EXEGGUTOR
db GENGAR
db NIDOQUEEN
db ARCANINE
db GYARADOS
db BLASTOISE
db GOLEM
db DRAGONITE
db NINETALES
db DRAGONAIR
db KABUTOPS
db OMASTAR
db JIGGLYPUFF
db FLAREON
db JOLTEON
db VAPOREON
db BEEDRILL
db BUTTERFREE
db MACHAMP
db CLOYSTER
db CLEFABLE
db ALAKAZAM
db STARMIE
db VENUSAUR
db TENTACRUEL
db CHARMELEON
db WARTORTLE
db CHARIZARD
db VILEPLUME
db VICTREEBEL
db $ff
Func_3b10f: ; 3b10f (e:710f)
ld c, $0
.asm_3b111
ld hl, EvosMovesPointerTable
ld b, $0
add hl, bc
add hl, bc
ld a, [hli]
ld h, [hl]
ld l, a
.asm_3b11b
ld a, [hli]
and a
jr z, .asm_3b130
cp $2
jr nz, .asm_3b124
inc hl
.asm_3b124
inc hl
ld a, [wcf91]
cp [hl]
jr z, .asm_3b138
inc hl
ld a, [hl]
and a
jr nz, .asm_3b11b
.asm_3b130
inc c
ld a, c
cp VICTREEBEL
jr c, .asm_3b111
and a
ret
.asm_3b138
inc c
ld a, c
ld [wcf91], a
scf
ret
; writes the moves a mon has at level [wCurEnemyLVL] to [de]
; move slots are being filled up sequentially and shifted if all slots are full
WriteMonMoves: ; 3113f (e:713f)
call GetPredefRegisters
push hl
push de
push bc
call GetMonLearnset
jr .firstMove
.nextMove
pop de
.nextMove2
inc hl
.firstMove
ld a, [hli] ; read level of next move in learnset
and a
jp z, .done ; end of list
ld b, a
ld a, [wCurEnemyLVL]
cp b
jp c, .done ; mon level < move level (assumption: learnset is sorted by level)
ld a, [wLearningMovesFromDayCare]
and a
jr z, .skipMinLevelCheck
ld a, [wDayCareStartLevel]
cp b
jr nc, .nextMove2 ; min level >= move level
.skipMinLevelCheck
; check if the move is already known
push de
ld c, NUM_MOVES
.alreadyKnowsCheckLoop
ld a, [de]
inc de
cp [hl]
jr z, .nextMove
dec c
jr nz, .alreadyKnowsCheckLoop
; try to find an empty move slot
pop de
push de
ld c, NUM_MOVES
.findEmptySlotLoop
ld a, [de]
and a
jr z, .writeMoveToSlot2
inc de
dec c
jr nz, .findEmptySlotLoop
; no empty move slots found
pop de
push de
push hl
ld h, d
ld l, e
call WriteMonMoves_ShiftMoveData ; shift all moves one up (deleting move 1)
ld a, [wLearningMovesFromDayCare]
and a
jr z, .writeMoveToSlot
; shift PP as well if learning moves from day care
push de
ld bc, wPartyMon1PP - (wPartyMon1Moves + 3)
add hl, bc
ld d, h
ld e, l
call WriteMonMoves_ShiftMoveData ; shift all move PP data one up
pop de
.writeMoveToSlot
pop hl
.writeMoveToSlot2
ld a, [hl]
ld [de], a
ld a, [wLearningMovesFromDayCare]
and a
jr z, .nextMove
; write move PP value if learning moves from day care
push hl
ld a, [hl]
ld hl, wPartyMon1PP - wPartyMon1Moves
add hl, de
push hl
dec a
ld hl, Moves
ld bc, MoveEnd - Moves
call AddNTimes
ld de, wBuffer
ld a, BANK(Moves)
call FarCopyData
ld a, [wBuffer + 5]
pop hl
ld [hl], a
pop hl
jr .nextMove
.done
pop bc
pop de
pop hl
ret
; shifts all move data one up (freeing 4th move slot)
WriteMonMoves_ShiftMoveData: ; 3b1c3 (e:71c3)
ld c, NUM_MOVES - 1
.loop
inc de
ld a, [de]
ld [hli], a
dec c
jr nz, .loop
ret
Evolution_FlagAction: ; 3b1cc (e:71cc)
predef_jump FlagActionPredef
GetMonLearnset: ; 3b1d1 (e:71d1)
ld hl, EvosMovesPointerTable
ld b, 0
ld a, [wcf91]
dec a
ld c, a
add hl, bc
add hl, bc
ld a, [hli]
ld h, [hl]
ld l, a
.skipEvolutionDataLoop ; loop to skip past the evolution data, which comes before the move data
ld a, [hli]
and a ; have we reached the end of the evolution data?
jr nz, .skipEvolutionDataLoop ; if not, jump back up
ret
INCLUDE "data/evos_moves.asm"