; try to evolve the mon in [wWhichPokemon] TryEvolvingMon: 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: ldh a, [hTileAnimations] 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: ; 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, [hli] ld b, a ; evolution item ld a, [wcf91] ; this is supposed to be the last item used, but it is also used to hold species numbers 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 CopyToStringBuffer ld hl, IsEvolvingText call PrintText ld c, 50 call DelayFrames xor a ldh [hAutoBGTransferEnabled], a hlcoord 0, 0 lb bc, 12, 20 call ClearScreenArea ld a, $1 ldh [hAutoBGTransferEnabled], a ld a, $ff ld [wUpdateSpritesEnabled], a call ClearSprites callfar 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(TrainerNames) ; 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, BASE_DATA_SIZE 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 ldh [hTileAnimations], 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: ; 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, wStringBuffer .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: ld hl, StoppedEvolvingText call PrintText call ClearScreen pop hl call Evolution_ReloadTilesetTilePatterns jp Evolution_PartyMonLoop EvolvedText: text_far _EvolvedText text_end IntoText: text_far _IntoText text_end StoppedEvolvingText: text_far _StoppedEvolvingText text_end IsEvolvingText: text_far _IsEvolvingText text_end Evolution_ReloadTilesetTilePatterns: ld a, [wLinkState] cp LINK_STATE_TRADING ret z jp ReloadTilesetTilePatterns LearnMoveFromLevelUp: ld hl, EvosMovesPointerTable ld a, [wd11e] ; species ld [wcf91], a dec a ld bc, 0 ld hl, EvosMovesPointerTable add a rl b ld c, a 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 .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 CopyToStringBuffer predef LearnMove .done ld a, [wcf91] ld [wd11e], a 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: call GetPredefRegisters push hl push de push bc ld hl, EvosMovesPointerTable ld b, 0 ld a, [wcf91] ; cur mon ID dec a add a rl b ld c, a add hl, bc ld a, [hli] ld h, [hl] ld l, a .skipEvoEntriesLoop ld a, [hli] and a jr nz, .skipEvoEntriesLoop 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, MOVE_LENGTH 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: ld c, NUM_MOVES - 1 .loop inc de ld a, [de] ld [hli], a dec c jr nz, .loop ret Evolution_FlagAction: predef_jump FlagActionPredef ; From here, Move Relearner-related code -PvK ;joenote - custom function by Mateo for move relearner PrepareRelearnableMoveList:: ; I don't know how the fuck you're a single colon in shin pokered but it sure as shit doesn't work here - PvK ; Loads relearnable move list to wRelearnableMoves. ; Input: party mon index = [wWhichPokemon] ; Get mon id. ld a, [wWhichPokemon] ld c, a ld b, 0 ld hl, wPartySpecies add hl, bc ld a, [hl] ; a = mon id ld [wd0b5], a ;joenote - put mon id into wram for potential later usage of GetMonHeader ; Get pointer to evos moves data. dec a ld c, a ld b, 0 ld hl, EvosMovesPointerTable add hl, bc add hl, bc ld a, [hli] ld h, [hl] ld l, a ; hl = pointer to evos moves data for our mon push hl ; Get pointer to mon's currently-known moves. ld a, [wWhichPokemon] ld hl, wPartyMon1Level ld bc, wPartyMon2 - wPartyMon1 call AddNTimes ld a, [hl] ld b, a push bc ld a, [wWhichPokemon] ld hl, wPartyMon1Moves ld bc, wPartyMon2 - wPartyMon1 call AddNTimes pop bc ld d, h ld e, l pop hl ; Skip over evolution data. .skipEvoEntriesLoop ld a, [hli] and a jr nz, .skipEvoEntriesLoop ; Write list of relearnable moves, while keeping count along the way. ; de = pointer to mon's currently-known moves ; hl = pointer to moves data for our mon ; b = mon's level ld c, 0 ; c = count of relearnable moves .loop ld a, [hli] and a jr z, .done cp b jr c, .addMove jr nz, .done .addMove push bc ld a, [hli] ; move id ld b, a ; Check if move is already known by our mon. push de ld a, [de] cp b jr z, .knowsMove inc de ld a, [de] cp b jr z, .knowsMove inc de ld a, [de] cp b jr z, .knowsMove inc de ld a, [de] cp b jr z, .knowsMove .relearnableMove pop de push hl ; Add move to the list, and update the running count. ld a, b ld b, 0 ld hl, wMoveBuffer + 1 add hl, bc ld [hl], a pop hl pop bc inc c jr .loop .knowsMove pop de pop bc jr .loop .done ;joenote - start checking for level-0 moves xor a ld b, a ;b will act as a counter, as there can only be up to 4 level-0 moves call GetMonHeader ;mon id already stored earlier in wd0b5 ld hl, wMonHMoves .loop2 ld a, b ;get the current loop counter into a cp $4 jr nc, .done2 ;if gone through 4 moves already, reached the end of the list. move to done2. ld a, [hl] ;load move and a jr z, .done2 ;if move has id 0, list has reached the end early. move to done2. ;check if the move is already in the learnable move list push bc push hl ;c = buffer length .buffer_loop ld hl, wMoveBuffer ld b, 0 add hl, bc ;move to buffer at current c value ld b, a ;b = move id ld a, [hl] ; move id at buffer point cp b ld a, b ;a = move id jr z, .move_in_buffer inc c dec c jr z, .end_buffer_loop ;jump out if start of buffer is reached dec c ;else decrement c and loop again jr .buffer_loop .move_in_buffer pop hl pop bc inc hl ;increment to the next level-0 move inc b ;increment the loop counter jr .loop2 .end_buffer_loop pop hl pop bc ;Check if move is already known by our mon. push bc ld a, [hl] ; move id ld b, a push de ld a, [de] cp b jr z, .knowsMove2 inc de ld a, [de] cp b jr z, .knowsMove2 inc de ld a, [de] cp b jr z, .knowsMove2 inc de ld a, [de] cp b jr z, .knowsMove2 ;if the move is not already known, add it to the learnable move list pop de push hl ; Add move to the list, and update the running count. ld a, b ld b, 0 ld hl, wMoveBuffer + 1 add hl, bc ld [hl], a pop hl pop bc inc c inc hl ;increment to the next level-0 move inc b ;increment the loop counter jr .loop2 .knowsMove2 pop de pop bc inc hl ;increment to the next level-0 move inc b ;increment the loop counter jr .loop2 .done2 ld b, 0 ld hl, wMoveBuffer + 1 add hl, bc ld a, $ff ld [hl], a ld hl, wMoveBuffer ld [hl], c ret ; Modified Mateo/jojobear13 code for a Tradeback Move Tutor PrepareTradebackMoveList:: ; I still don't know how the fuck you're a single colon in shin pokered but it sure as shit doesn't work here - PvK ; Loads Tradeback move list to wRelearnableMoves - we can reuse this variable. ; Input: party mon index = [wWhichPokemon] ; Get mon id. ld a, [wWhichPokemon] ld c, a ld b, 0 ld hl, wPartySpecies add hl, bc ld a, [hl] ; a = mon id ld [wd0b5], a ;joenote - put mon id into wram for potential later usage of GetMonHeader ; Get pointer to evos moves data. dec a ld c, a ld b, 0 ld hl, TradebackMovesPointerTable add hl, bc add hl, bc ld a, [hli] ld h, [hl] ld l, a ; hl = pointer to evos moves data for our mon push hl ; Get pointer to mon's currently-known moves. ld a, [wWhichPokemon] ld hl, wPartyMon1Level ld bc, wPartyMon2 - wPartyMon1 call AddNTimes ld a, [hl] ld b, a push bc ld a, [wWhichPokemon] ld hl, wPartyMon1Moves ld bc, wPartyMon2 - wPartyMon1 call AddNTimes pop bc ld d, h ld e, l pop hl ; Skip over evolution data. ;.skipEvoEntriesLoop ; ld a, [hli] ; and a ; jr nz, .skipEvoEntriesLoop ; Write list of relearnable moves, while keeping count along the way. ; de = pointer to mon's currently-known moves ; hl = pointer to moves data for our mon ; b = mon's level ld c, 0 ; c = count of relearnable moves .loop ld a, [hli] and a jr z, .done cp b jr c, .addMove jr nz, .done .addMove push bc ld a, [hli] ; move id ld b, a ; Check if move is already known by our mon. push de ld a, [de] cp b jr z, .knowsMove inc de ld a, [de] cp b jr z, .knowsMove inc de ld a, [de] cp b jr z, .knowsMove inc de ld a, [de] cp b jr z, .knowsMove .tradebackMove pop de push hl ; Add move to the list, and update the running count. ld a, b ld b, 0 ld hl, wMoveBuffer + 1 add hl, bc ld [hl], a pop hl pop bc inc c jr .loop .knowsMove pop de pop bc jr .loop .done ld b, 0 ld hl, wMoveBuffer + 1 add hl, bc ld a, $ff ld [hl], a ld hl, wMoveBuffer ld [hl], c ret INCLUDE "data/pokemon/evos_moves.asm" INCLUDE "data/pokemon/tradeback_moves.asm"