jep-hack/engine/pokemon/evolve.asm
Llinos Evans 892e8fc6b1 Summer Beach House fixes, evo moves (bugs!)
Evo moves commit is unfinished and doesn't work properly. Script in evolve.asm has details.

Summer Beach House now teaches Pikachu Surf and has two issues; one is that backing out of teaching Pikachu causes issues (basically, it only goes a correct way if you say yes), and the teaching menu uses tiles from the overworld because I am stupid.

Are you a bad enough dude to fix these bugs?
2024-08-04 14:40:07 +01:00

733 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