jep-hack/engine/pokemon/evolve.asm
2024-08-26 03:00:23 -04:00

734 lines
12 KiB
NASM

EvolvePokemon:
ld hl, wEvolvableFlags
xor a
ld [hl], a
ld a, [wCurPartyMon]
ld c, a
ld b, SET_FLAG
call EvoFlagAction
EvolveAfterBattle:
xor a
ld [wMonTriedToEvolve], a
dec a
ld [wCurPartyMon], a
push hl
push bc
push de
ld hl, wPartyCount
push hl
EvolveAfterBattle_MasterLoop:
ld hl, wCurPartyMon
inc [hl]
pop hl
inc hl
ld a, [hl]
cp $ff
jp z, .ReturnToMap
ld [wEvolutionOldSpecies], a
push hl
ld a, [wCurPartyMon]
ld c, a
ld hl, wEvolvableFlags
ld b, CHECK_FLAG
call EvoFlagAction
ld a, c
and a
jp z, EvolveAfterBattle_MasterLoop
ld a, [wEvolutionOldSpecies]
call GetPokemonIndexFromID
ld b, h
ld c, l
ld hl, EvosAttacksPointers
ld a, BANK(EvosAttacksPointers)
call LoadDoubleIndirectPointer
ldh [hTemp], a
push hl
xor a
ld [wMonType], a
predef CopyMonToTempMon
pop hl
.loop
call GetNextEvoAttackByte
and a
jr z, EvolveAfterBattle_MasterLoop
ld b, a
cp EVOLVE_TRADE
jr z, .trade
ld a, [wLinkMode]
and a
jp nz, .dont_evolve_check
ld a, b
cp EVOLVE_ITEM
jp z, .item
ld a, [wForceEvolution]
and a
jp nz, .dont_evolve_check
ld a, b
cp EVOLVE_LEVEL
jp z, .level
cp EVOLVE_HAPPINESS
jr z, .happiness
; EVOLVE_STAT
call GetNextEvoAttackByte
ld c, a
ld a, [wTempMonLevel]
cp c
jp c, .skip_evolution_species_parameter
call IsMonHoldingEverstone
jp z, .skip_evolution_species_parameter
push hl
ld de, wTempMonAttack
ld hl, wTempMonDefense
ld c, 2
call CompareBytes
ld c, ATK_EQ_DEF
jr z, .got_tyrogue_evo
ld c, ATK_LT_DEF
jr c, .got_tyrogue_evo
ld c, ATK_GT_DEF
.got_tyrogue_evo
pop hl
call GetNextEvoAttackByte
cp c
jp nz, .skip_evolution_species
jp .proceed
.happiness
ld a, [wTempMonHappiness]
cp HAPPINESS_TO_EVOLVE
jp c, .skip_evolution_species_parameter
call IsMonHoldingEverstone
jp z, .skip_evolution_species_parameter
call GetNextEvoAttackByte
cp TR_ANYTIME
jr z, .proceed
cp TR_MORNDAY
jr z, .happiness_daylight
; TR_NITE
ld a, [wTimeOfDay]
cp NITE_F
jp nz, .skip_evolution_species
jr .proceed
.happiness_daylight
ld a, [wTimeOfDay]
cp NITE_F
jp z, .skip_evolution_species
jr .proceed
.trade
ld a, [wLinkMode]
and a
jp z, .skip_evolution_species_parameter
call IsMonHoldingEverstone
jp z, .skip_evolution_species_parameter
call GetNextEvoAttackByte
ld b, a
inc a
jr z, .proceed
ld a, [wLinkMode]
cp LINK_TIMECAPSULE
jp z, .skip_evolution_species
ld a, [wTempMonItem]
cp b
jp nz, .skip_evolution_species
xor a
ld [wTempMonItem], a
jr .proceed
.item
call GetNextEvoAttackByte
ld b, a
ld a, [wCurItem]
cp b
jp nz, .skip_evolution_species
ld a, [wForceEvolution]
and a
jp z, .skip_evolution_species
ld a, [wLinkMode]
and a
jp nz, .skip_evolution_species
jr .proceed
.level
call GetNextEvoAttackByte
ld b, a
ld a, [wTempMonLevel]
cp b
jp c, .skip_evolution_species
call IsMonHoldingEverstone
jp z, .skip_evolution_species
.proceed
ld a, [wTempMonLevel]
ld [wCurPartyLevel], a
ld a, $1
ld [wMonTriedToEvolve], a
ldh a, [hTemp]
call GetFarWord
call GetPokemonIDFromIndex
ld [wEvolutionNewSpecies], a
ld a, [wCurPartyMon]
ld hl, wPartyMonNicknames
call GetNickname
call CopyName1
ld hl, EvolvingText
call PrintText
ld c, 50
call DelayFrames
xor a
ldh [hBGMapMode], a
hlcoord 0, 0
lb bc, 12, 20
call ClearBox
ld a, $1
ldh [hBGMapMode], a
call ClearSprites
farcall EvolutionAnimation
push af
call ClearSprites
pop af
jp c, CancelEvolution
ld hl, CongratulationsYourPokemonText
call PrintText
ld a, [wEvolutionNewSpecies]
ld [wCurSpecies], a
ld [wTempMonSpecies], a
ld [wNamedObjectIndex], a
call GetPokemonName
push hl
ld hl, EvolvedIntoText
call PrintTextboxText
farcall StubbedTrainerRankings_MonsEvolved
ld de, MUSIC_NONE
call PlayMusic
ld de, SFX_CAUGHT_MON
call PlaySFX
call WaitSFX
ld c, 40
call DelayFrames
call ClearTilemap
call UpdateSpeciesNameIfNotNicknamed
call GetBaseData
ld hl, wTempMonExp + 2
ld de, wTempMonMaxHP
ld b, TRUE
predef CalcMonStats
ld a, [wCurPartyMon]
ld hl, wPartyMons
ld bc, PARTYMON_STRUCT_LENGTH
call AddNTimes
ld e, l
ld d, h
ld bc, MON_MAXHP
add hl, bc
ld a, [hli]
ld b, a
ld c, [hl]
ld hl, wTempMonMaxHP + 1
ld a, [hld]
sub c
ld c, a
ld a, [hl]
sbc b
ld b, a
ld hl, wTempMonHP + 1
ld a, [hl]
add c
ld [hld], a
ld a, [hl]
adc b
ld [hl], a
ld hl, wTempMonSpecies
ld bc, PARTYMON_STRUCT_LENGTH
call CopyBytes
ld a, [wCurSpecies]
ld [wTempSpecies], a
xor a
ld [wMonType], a
; call LearnEvolutionMove
call LearnLevelMoves
ld a, [wTempSpecies]
call SetSeenAndCaughtMon
ld a, [wTempSpecies]
call GetPokemonIndexFromID
ld a, l
sub LOW(UNOWN)
if HIGH(UNOWN) == 0
or h
else
jr nz, .skip_unown
if HIGH(UNOWN) == 1
dec h
else
ld a, h
cp HIGH(UNOWN)
endc
endc
jr nz, .skip_unown
ld hl, wTempMonDVs
predef GetUnownLetter
callfar UpdateUnownDex
.skip_unown
pop de
pop hl
ld a, [wTempMonSpecies]
ld [hl], a
push hl
ld l, e
ld h, d
jp EvolveAfterBattle_MasterLoop
.dont_evolve_check
ld a, b
cp EVOLVE_STAT
jr nz, .skip_evolution_species_parameter
inc hl
.skip_evolution_species_parameter
inc hl
.skip_evolution_species
inc hl
inc hl
jp .loop
.UnusedReturnToMap: ; unreferenced
pop hl
.ReturnToMap:
pop de
pop bc
pop hl
ld a, [wLinkMode]
and a
ret nz
ld a, [wBattleMode]
and a
ret nz
ld a, [wMonTriedToEvolve]
and a
call nz, RestartMapMusic
ret
; BUG: Does not take in the designated move correctly, resulting in strange behaviour usually seen when GetMoveIDFromIndex takes an 8-bit index.
; Comments proceeding
; LearnEvolutionMove:
; ld a, [wTempSpecies]
; ld [wCurPartySpecies], a
; call GetPokemonIndexFromID
; ld b, h
; ld c, l
; ld hl, EvolutionMoves
; add hl, bc
; add hl, bc
; dec hl
; dec hl
; ld a, [hli]
; ld h, [hl]
; ld l, a ; Moves through the table by going up according to the Pokemon's ID, storing the equivalent move in hl. This is fine.
; or h ; hl == 0?
; ret z
; call GetMoveIDFromIndex ; grabs what's in hl (the move) and converts it to 8-bit...or something like that. anyway, it should return in register a.
; push hl ; I don't actually know why it does this. Removing it produces manmade horrors beyond my comprehension, so it isn't part of the current problem.
; ld d, a ; preserve a
; ld hl, wPartyMon1Moves
; ld a, [wCurPartyMon]
; ld bc, PARTYMON_STRUCT_LENGTH
; call AddNTimes
; ld b, NUM_MOVES
; .check_move
; ld a, [hli]
; cp d ; use preserved a to check if a move is there
; jr z, .has_move
; dec b
; jr nz, .check_move
; ld a, d ; take the preserved a and reload
; ld [wPutativeTMHMMove], a ; proceed to learn the move with adequate preprep
; ld [wNamedObjectIndex], a
; call GetMoveName
; call CopyName1
; predef LearnMove
; ld a, [wCurPartySpecies]
; ld [wTempSpecies], a
; .has_move
; pop hl
; ret
; so wtf is going on
UpdateSpeciesNameIfNotNicknamed:
ld a, [wCurSpecies]
push af
ld a, [wBaseSpecies]
ld [wNamedObjectIndex], a
call GetPokemonName
pop af
ld [wCurSpecies], a
ld hl, wStringBuffer1
ld de, wStringBuffer2
.loop
ld a, [de]
inc de
cp [hl]
inc hl
ret nz
cp "@"
jr nz, .loop
ld a, [wCurPartyMon]
ld bc, MON_NAME_LENGTH
ld hl, wPartyMonNicknames
call AddNTimes
push hl
ld a, [wCurSpecies]
ld [wNamedObjectIndex], a
call GetPokemonName
ld hl, wStringBuffer1
pop de
ld bc, MON_NAME_LENGTH
jp CopyBytes
CancelEvolution:
ld hl, StoppedEvolvingText
call PrintText
call ClearTilemap
jp EvolveAfterBattle_MasterLoop
IsMonHoldingEverstone:
push hl
ld a, [wCurPartyMon]
ld hl, wPartyMon1Item
ld bc, PARTYMON_STRUCT_LENGTH
call AddNTimes
ld a, [hl]
cp EVERSTONE
pop hl
ret
CongratulationsYourPokemonText:
text_far _CongratulationsYourPokemonText
text_end
EvolvedIntoText:
text_far _EvolvedIntoText
text_end
StoppedEvolvingText:
text_far _StoppedEvolvingText
text_end
EvolvingText:
text_far _EvolvingText
text_end
LearnLevelMoves:
ld a, [wTempSpecies]
ld [wCurPartySpecies], a
call GetPokemonIndexFromID
ld b, h
ld c, l
ld hl, EvosAttacksPointers
ld a, BANK(EvosAttacksPointers)
call LoadDoubleIndirectPointer
ldh [hTemp], a
call SkipEvolutions
.find_move
call GetNextEvoAttackByte
and a
jr z, .done
ld b, a
ld a, [wCurPartyLevel]
cp b
call GetNextEvoAttackByte
ld e, a
call GetNextEvoAttackByte
ld d, a
jr nz, .find_move
push hl
ld h, d
ld l, e
call GetMoveIDFromIndex
ld d, a
ld hl, wPartyMon1Moves
ld a, [wCurPartyMon]
ld bc, PARTYMON_STRUCT_LENGTH
call AddNTimes
ld b, NUM_MOVES
.check_move
call GetNextEvoAttackByte
cp d
jr z, .has_move
dec b
jr nz, .check_move
jr .learn
.has_move
pop hl
jr .find_move
.learn
ld a, d
ld [wPutativeTMHMMove], a
ld [wNamedObjectIndex], a
call GetMoveName
call CopyName1
predef LearnMove
pop hl
jr .find_move
.done
ld a, [wCurPartySpecies]
ld [wTempSpecies], a
ret
FillMoves:
; Fill in moves at de for wCurPartySpecies at wCurPartyLevel
push hl
push de
push bc
ld a, [wCurPartySpecies]
call GetPokemonIndexFromID
ld b, h
ld c, l
ld hl, EvosAttacksPointers
ld a, BANK(EvosAttacksPointers)
call LoadDoubleIndirectPointer
ldh [hTemp], a
call SkipEvolutions
jr .GetLevel
.NextMove:
pop de
.GetMove:
inc hl
inc hl
.GetLevel:
call GetNextEvoAttackByte
and a
jp z, .done
ld b, a
ld a, [wCurPartyLevel]
cp b
jp c, .done
ld a, [wSkipMovesBeforeLevelUp]
and a
jr z, .CheckMove
ld a, [wPrevPartyLevel]
cp b
jr nc, .GetMove
.CheckMove:
push de
ld c, NUM_MOVES
ldh a, [hTemp]
push hl
call GetFarWord
call GetMoveIDFromIndex
pop hl
ld b, a
.CheckRepeat:
ld a, [de]
inc de
cp b
jr z, .NextMove
dec c
jr nz, .CheckRepeat
pop de
push de
ld c, NUM_MOVES
.CheckSlot:
ld a, [de]
and a
jr z, .LearnMove
inc de
dec c
jr nz, .CheckSlot
pop de
push de
push hl
ld h, d
ld l, e
call ShiftMoves
ld a, [wEvolutionOldSpecies]
and a
jr z, .ShiftedMove
push de
ld bc, wPartyMon1PP - (wPartyMon1Moves + NUM_MOVES - 1)
add hl, bc
ld d, h
ld e, l
call ShiftMoves
pop de
.ShiftedMove:
pop hl
.LearnMove:
ldh a, [hTemp]
push hl
call GetFarWord
call GetMoveIDFromIndex
pop hl
ld b, a
ld [de], a
ld a, [wEvolutionOldSpecies]
and a
jr z, .NextMove
push hl
ld a, b
ld hl, MON_PP - MON_MOVES
add hl, de
push hl
ld l, a
ld a, MOVE_PP
call GetMoveAttribute
pop hl
ld [hl], a
pop hl
jp .NextMove
.done
pop bc
pop de
pop hl
ret
ShiftMoves:
ld c, NUM_MOVES - 1
.loop
inc de
ld a, [de]
ld [hli], a
dec c
jr nz, .loop
ret
EvoFlagAction:
push de
ld d, $0
predef SmallFarFlagAction
pop de
ret
GetLowestEvolutionStage:
; Return the first mon to evolve into wCurPartySpecies.
; Instead of looking it up, we just load it from a table. This is a lot more efficient.
ld a, [wCurPartySpecies]
call GetPokemonIndexFromID
ld bc, FirstEvoStages - 2
add hl, hl
add hl, bc
ld a, BANK(FirstEvoStages)
call GetFarWord
call GetPokemonIDFromIndex
ld [wCurPartySpecies], a
ret
SkipEvolutions::
; Receives a pointer to the evos and attacks for a mon in b:hl, and skips to the attacks.
ld a, b
call GetFarByte
inc hl
and a
ret z
cp EVOLVE_STAT
jr nz, .no_extra_skip
inc hl
.no_extra_skip
inc hl
inc hl
inc hl
jr SkipEvolutions
DetermineEvolutionItemResults::
; in: b:de: pointer to evos and attacks struct, wCurItem: item
; out: de: species ID or zero; a, b, hl: clobbered
ld h, d
ld l, e
ld de, 0
ld a, b
ldh [hTemp], a
.loop
call GetNextEvoAttackByte
and a
ret z
cp EVOLVE_STAT
jr z, .skip_species_two_parameters
cp EVOLVE_ITEM
jr nz, .skip_species_parameter
call GetNextEvoAttackByte
ld b, a
ld a, [wCurItem]
cp b
jr nz, .skip_species
ldh a, [hTemp]
call GetFarWord
ld d, h
ld e, l
ret
.skip_species_two_parameters
inc hl
.skip_species_parameter
inc hl
.skip_species
inc hl
inc hl
jr .loop
GetNextEvoAttackByte:
ldh a, [hTemp]
call GetFarByte
inc hl
ret