Add subdirectories to engine/ similar to pokecrystal

This commit is contained in:
Rangi 2020-07-02 23:30:21 -04:00
parent 5559d51c86
commit f275790aec
124 changed files with 342 additions and 346 deletions

516
engine/pokemon/add_mon.asm Normal file
View file

@ -0,0 +1,516 @@
_AddPartyMon::
; Adds a new mon to the player's or enemy's party.
; [wMonDataLocation] is used in an unusual way in this function.
; If the lower nybble is 0, the mon is added to the player's party, else the enemy's.
; If the entire value is 0, then the player is allowed to name the mon.
ld de, wPartyCount
ld a, [wMonDataLocation]
and $f
jr z, .next
ld de, wEnemyPartyCount
.next
ld a, [de]
inc a
cp PARTY_LENGTH + 1
ret nc ; return if the party is already full
ld [de], a
ld a, [de]
ld [hNewPartyLength], a
add e
ld e, a
jr nc, .noCarry
inc d
.noCarry
ld a, [wcf91]
ld [de], a ; write species of new mon in party list
inc de
ld a, $ff ; terminator
ld [de], a
ld hl, wPartyMonOT
ld a, [wMonDataLocation]
and $f
jr z, .next2
ld hl, wEnemyMonOT
.next2
ld a, [hNewPartyLength]
dec a
call SkipFixedLengthTextEntries
ld d, h
ld e, l
ld hl, wPlayerName
ld bc, NAME_LENGTH
call CopyData
ld a, [wMonDataLocation]
and a
jr nz, .skipNaming
ld hl, wPartyMonNicks
ld a, [hNewPartyLength]
dec a
call SkipFixedLengthTextEntries
ld a, NAME_MON_SCREEN
ld [wNamingScreenType], a
predef AskName
.skipNaming
ld hl, wPartyMons
ld a, [wMonDataLocation]
and $f
jr z, .next3
ld hl, wEnemyMons
.next3
ld a, [hNewPartyLength]
dec a
ld bc, wPartyMon2 - wPartyMon1
call AddNTimes
ld e, l
ld d, h
push hl
ld a, [wcf91]
ld [wd0b5], a
call GetMonHeader
ld hl, wMonHeader
ld a, [hli]
ld [de], a ; species
inc de
pop hl
push hl
ld a, [wMonDataLocation]
and $f
ld a, $98 ; set enemy trainer mon IVs to fixed average values
ld b, $88
jr nz, .next4
; If the mon is being added to the player's party, update the pokedex.
ld a, [wcf91]
ld [wd11e], a
push de
predef IndexToPokedex
pop de
ld a, [wd11e]
dec a
ld c, a
ld b, FLAG_TEST
ld hl, wPokedexOwned
call FlagAction
ld a, c ; whether the mon was already flagged as owned
ld [wUnusedD153], a ; not read
ld a, [wd11e]
dec a
ld c, a
ld b, FLAG_SET
push bc
call FlagAction
pop bc
ld hl, wPokedexSeen
call FlagAction
pop hl
push hl
ld a, [wIsInBattle]
and a ; is this a wild mon caught in battle?
jr nz, .copyEnemyMonData
; Not wild.
call Random ; generate random IVs
ld b, a
call Random
.next4
push bc
ld bc, wPartyMon1DVs - wPartyMon1
add hl, bc
pop bc
ld [hli], a
ld [hl], b ; write IVs
ld bc, (wPartyMon1HPExp - 1) - (wPartyMon1DVs + 1)
add hl, bc
ld a, 1
ld c, a
xor a
ld b, a
call CalcStat ; calc HP stat (set cur Hp to max HP)
ld a, [H_MULTIPLICAND+1]
ld [de], a
inc de
ld a, [H_MULTIPLICAND+2]
ld [de], a
inc de
xor a
ld [de], a ; box level
inc de
ld [de], a ; status ailments
inc de
jr .copyMonTypesAndMoves
.copyEnemyMonData
ld bc, wEnemyMon1DVs - wEnemyMon1
add hl, bc
ld a, [wEnemyMonDVs] ; copy IVs from cur enemy mon
ld [hli], a
ld a, [wEnemyMonDVs + 1]
ld [hl], a
ld a, [wEnemyMonHP] ; copy HP from cur enemy mon
ld [de], a
inc de
ld a, [wEnemyMonHP+1]
ld [de], a
inc de
xor a
ld [de], a ; box level
inc de
ld a, [wEnemyMonStatus] ; copy status ailments from cur enemy mon
ld [de], a
inc de
.copyMonTypesAndMoves
ld hl, wMonHTypes
ld a, [hli] ; type 1
ld [de], a
inc de
ld a, [hli] ; type 2
ld [de], a
inc de
ld a, [hli] ; catch rate (held item in gen 2)
ld [de], a
ld hl, wMonHMoves
ld a, [hli]
inc de
push de
ld [de], a
ld a, [hli]
inc de
ld [de], a
ld a, [hli]
inc de
ld [de], a
ld a, [hli]
inc de
ld [de], a
push de
dec de
dec de
dec de
xor a
ld [wLearningMovesFromDayCare], a
predef WriteMonMoves
pop de
ld a, [wPlayerID] ; set trainer ID to player ID
inc de
ld [de], a
ld a, [wPlayerID + 1]
inc de
ld [de], a
push de
ld a, [wCurEnemyLVL]
ld d, a
callab CalcExperience
pop de
inc de
ld a, [hExperience] ; write experience
ld [de], a
inc de
ld a, [hExperience + 1]
ld [de], a
inc de
ld a, [hExperience + 2]
ld [de], a
xor a
ld b, NUM_STATS * 2
.writeEVsLoop ; set all EVs to 0
inc de
ld [de], a
dec b
jr nz, .writeEVsLoop
inc de
inc de
pop hl
call AddPartyMon_WriteMovePP
inc de
ld a, [wCurEnemyLVL]
ld [de], a
inc de
ld a, [wIsInBattle]
dec a
jr nz, .calcFreshStats
ld hl, wEnemyMonMaxHP
ld bc, $a
call CopyData ; copy stats of cur enemy mon
pop hl
jr .done
.calcFreshStats
pop hl
ld bc, wPartyMon1HPExp - 1 - wPartyMon1
add hl, bc
ld b, $0
call CalcStats ; calculate fresh set of stats
.done
scf
ret
LoadMovePPs:
call GetPredefRegisters
; fallthrough
AddPartyMon_WriteMovePP:
ld b, NUM_MOVES
.pploop
ld a, [hli] ; read move ID
and a
jr z, .empty
dec a
push hl
push de
push bc
ld hl, Moves
ld bc, MoveEnd - Moves
call AddNTimes
ld de, wcd6d
ld a, BANK(Moves)
call FarCopyData
pop bc
pop de
pop hl
ld a, [wcd6d + 5] ; PP is byte 5 of move data
.empty
inc de
ld [de], a
dec b
jr nz, .pploop ; there are still moves to read
ret
; adds enemy mon [wcf91] (at position [wWhichPokemon] in enemy list) to own party
; used in the cable club trade center
_AddEnemyMonToPlayerParty::
ld hl, wPartyCount
ld a, [hl]
cp PARTY_LENGTH
scf
ret z ; party full, return failure
inc a
ld [hl], a ; add 1 to party members
ld c, a
ld b, $0
add hl, bc
ld a, [wcf91]
ld [hli], a ; add mon as last list entry
ld [hl], $ff ; write new sentinel
ld hl, wPartyMons
ld a, [wPartyCount]
dec a
ld bc, wPartyMon2 - wPartyMon1
call AddNTimes
ld e, l
ld d, h
ld hl, wLoadedMon
call CopyData ; write new mon's data (from wLoadedMon)
ld hl, wPartyMonOT
ld a, [wPartyCount]
dec a
call SkipFixedLengthTextEntries
ld d, h
ld e, l
ld hl, wEnemyMonOT
ld a, [wWhichPokemon]
call SkipFixedLengthTextEntries
ld bc, NAME_LENGTH
call CopyData ; write new mon's OT name (from an enemy mon)
ld hl, wPartyMonNicks
ld a, [wPartyCount]
dec a
call SkipFixedLengthTextEntries
ld d, h
ld e, l
ld hl, wEnemyMonNicks
ld a, [wWhichPokemon]
call SkipFixedLengthTextEntries
ld bc, NAME_LENGTH
call CopyData ; write new mon's nickname (from an enemy mon)
ld a, [wcf91]
ld [wd11e], a
predef IndexToPokedex
ld a, [wd11e]
dec a
ld c, a
ld b, FLAG_SET
ld hl, wPokedexOwned
push bc
call FlagAction ; add to owned pokemon
pop bc
ld hl, wPokedexSeen
call FlagAction ; add to seen pokemon
and a
ret ; return success
_MoveMon::
ld a, [wMoveMonType]
and a ; BOX_TO_PARTY
jr z, .checkPartyMonSlots
cp DAYCARE_TO_PARTY
jr z, .checkPartyMonSlots
cp PARTY_TO_DAYCARE
ld hl, wDayCareMon
jr z, .findMonDataSrc
; else it's PARTY_TO_BOX
ld hl, wNumInBox
ld a, [hl]
cp MONS_PER_BOX
jr nz, .partyOrBoxNotFull
jr .boxFull
.checkPartyMonSlots
ld hl, wPartyCount
ld a, [hl]
cp PARTY_LENGTH
jr nz, .partyOrBoxNotFull
.boxFull
scf
ret
.partyOrBoxNotFull
inc a
ld [hl], a ; increment number of mons in party/box
ld c, a
ld b, 0
add hl, bc
ld a, [wMoveMonType]
cp DAYCARE_TO_PARTY
ld a, [wDayCareMon]
jr z, .copySpecies
ld a, [wcf91]
.copySpecies
ld [hli], a ; write new mon ID
ld [hl], $ff ; write new sentinel
.findMonDataDest
ld a, [wMoveMonType]
dec a
ld hl, wPartyMons
ld bc, wPartyMon2 - wPartyMon1 ; $2c
ld a, [wPartyCount]
jr nz, .addMonOffset
; if it's PARTY_TO_BOX
ld hl, wBoxMons
ld bc, wBoxMon2 - wBoxMon1 ; $21
ld a, [wNumInBox]
.addMonOffset
dec a
call AddNTimes
.findMonDataSrc
push hl
ld e, l
ld d, h
ld a, [wMoveMonType]
and a
ld hl, wBoxMons
ld bc, wBoxMon2 - wBoxMon1 ; $21
jr z, .addMonOffset2
cp DAYCARE_TO_PARTY
ld hl, wDayCareMon
jr z, .copyMonData
ld hl, wPartyMons
ld bc, wPartyMon2 - wPartyMon1 ; $2c
.addMonOffset2
ld a, [wWhichPokemon]
call AddNTimes
.copyMonData
push hl
push de
ld bc, wBoxMon2 - wBoxMon1
call CopyData
pop de
pop hl
ld a, [wMoveMonType]
and a ; BOX_TO_PARTY
jr z, .findOTdest
cp DAYCARE_TO_PARTY
jr z, .findOTdest
ld bc, wBoxMon2 - wBoxMon1
add hl, bc
ld a, [hl] ; hl = Level
inc de
inc de
inc de
ld [de], a ; de = BoxLevel
.findOTdest
ld a, [wMoveMonType]
cp PARTY_TO_DAYCARE
ld de, wDayCareMonOT
jr z, .findOTsrc
dec a
ld hl, wPartyMonOT
ld a, [wPartyCount]
jr nz, .addOToffset
ld hl, wBoxMonOT
ld a, [wNumInBox]
.addOToffset
dec a
call SkipFixedLengthTextEntries
ld d, h
ld e, l
.findOTsrc
ld hl, wBoxMonOT
ld a, [wMoveMonType]
and a
jr z, .addOToffset2
ld hl, wDayCareMonOT
cp DAYCARE_TO_PARTY
jr z, .copyOT
ld hl, wPartyMonOT
.addOToffset2
ld a, [wWhichPokemon]
call SkipFixedLengthTextEntries
.copyOT
ld bc, NAME_LENGTH
call CopyData
ld a, [wMoveMonType]
.findNickDest
cp PARTY_TO_DAYCARE
ld de, wDayCareMonName
jr z, .findNickSrc
dec a
ld hl, wPartyMonNicks
ld a, [wPartyCount]
jr nz, .addNickOffset
ld hl, wBoxMonNicks
ld a, [wNumInBox]
.addNickOffset
dec a
call SkipFixedLengthTextEntries
ld d, h
ld e, l
.findNickSrc
ld hl, wBoxMonNicks
ld a, [wMoveMonType]
and a
jr z, .addNickOffset2
ld hl, wDayCareMonName
cp DAYCARE_TO_PARTY
jr z, .copyNick
ld hl, wPartyMonNicks
.addNickOffset2
ld a, [wWhichPokemon]
call SkipFixedLengthTextEntries
.copyNick
ld bc, NAME_LENGTH
call CopyData
pop hl
ld a, [wMoveMonType]
cp PARTY_TO_BOX
jr z, .done
cp PARTY_TO_DAYCARE
jr z, .done
push hl
srl a
add $2
ld [wMonDataLocation], a
call LoadMonData
callba CalcLevelFromExperience
ld a, d
ld [wCurEnemyLVL], a
pop hl
ld bc, wBoxMon2 - wBoxMon1
add hl, bc
ld [hli], a
ld d, h
ld e, l
ld bc, -18
add hl, bc
ld b, $1
call CalcStats
.done
and a
ret

548
engine/pokemon/bills_pc.asm Normal file
View file

@ -0,0 +1,548 @@
DisplayPCMainMenu::
xor a
ld [H_AUTOBGTRANSFERENABLED], a
call SaveScreenTilesToBuffer2
ld a, [wNumHoFTeams]
and a
jr nz, .leaguePCAvailable
CheckEvent EVENT_GOT_POKEDEX
jr z, .noOaksPC
ld a, [wNumHoFTeams]
and a
jr nz, .leaguePCAvailable
coord hl, 0, 0
ld b, 8
ld c, 14
jr .next
.noOaksPC
coord hl, 0, 0
ld b, 6
ld c, 14
jr .next
.leaguePCAvailable
coord hl, 0, 0
ld b, 10
ld c, 14
.next
call TextBoxBorder
call UpdateSprites
ld a, 3
ld [wMaxMenuItem], a
CheckEvent EVENT_MET_BILL
jr nz, .metBill
coord hl, 2, 2
ld de, SomeonesPCText
jr .next2
.metBill
coord hl, 2, 2
ld de, BillsPCText
.next2
call PlaceString
coord hl, 2, 4
ld de, wPlayerName
call PlaceString
ld l, c
ld h, b
ld de, PlayersPCText
call PlaceString
CheckEvent EVENT_GOT_POKEDEX
jr z, .noOaksPC2
coord hl, 2, 6
ld de, OaksPCText
call PlaceString
ld a, [wNumHoFTeams]
and a
jr z, .noLeaguePC
ld a, 4
ld [wMaxMenuItem], a
coord hl, 2, 8
ld de, PKMNLeaguePCText
call PlaceString
coord hl, 2, 10
ld de, LogOffPCText
jr .next3
.noLeaguePC
coord hl, 2, 8
ld de, LogOffPCText
jr .next3
.noOaksPC2
ld a, $2
ld [wMaxMenuItem], a
coord hl, 2, 6
ld de, LogOffPCText
.next3
call PlaceString
ld a, A_BUTTON | B_BUTTON
ld [wMenuWatchedKeys], a
ld a, 2
ld [wTopMenuItemY], a
ld a, 1
ld [wTopMenuItemX], a
xor a
ld [wCurrentMenuItem], a
ld [wLastMenuItem], a
ld a, 1
ld [H_AUTOBGTRANSFERENABLED], a
ret
SomeonesPCText: db "SOMEONE's PC@"
BillsPCText: db "BILL's PC@"
PlayersPCText: db "'s PC@"
OaksPCText: db "PROF.OAK's PC@"
PKMNLeaguePCText: db "<pkmn>LEAGUE@"
LogOffPCText: db "LOG OFF@"
BillsPC_::
ld hl, wd730
set 6, [hl]
xor a
ld [wParentMenuItem], a
inc a ; MONSTER_NAME
ld [wNameListType], a
call LoadHpBarAndStatusTilePatterns
ld a, [wListScrollOffset]
push af
ld a, [wFlags_0xcd60]
bit 3, a ; accessing Bill's PC through another PC?
jr nz, BillsPCMenu
; accessing it directly
ld a, SFX_TURN_ON_PC
call PlaySound
ld hl, SwitchOnText
call PrintText
BillsPCMenu:
ld a, [wParentMenuItem]
ld [wCurrentMenuItem], a
ld hl, vChars2 + $780
ld de, PokeballTileGraphics
lb bc, BANK(PokeballTileGraphics), $01
call CopyVideoData
call LoadScreenTilesFromBuffer2DisableBGTransfer
coord hl, 0, 0
ld b, 10
ld c, 12
call TextBoxBorder
coord hl, 2, 2
ld de, BillsPCMenuText
call PlaceString
ld hl, wTopMenuItemY
ld a, 2
ld [hli], a ; wTopMenuItemY
dec a
ld [hli], a ; wTopMenuItemX
inc hl
inc hl
ld a, 4
ld [hli], a ; wMaxMenuItem
ld a, A_BUTTON | B_BUTTON
ld [hli], a ; wMenuWatchedKeys
xor a
ld [hli], a ; wLastMenuItem
ld [hli], a ; wPartyAndBillsPCSavedMenuItem
ld hl, wListScrollOffset
ld [hli], a ; wListScrollOffset
ld [hl], a ; wMenuWatchMovingOutOfBounds
ld [wPlayerMonNumber], a
ld hl, WhatText
call PrintText
coord hl, 9, 14
ld b, 2
ld c, 9
call TextBoxBorder
ld a, [wCurrentBoxNum]
and $7f
cp 9
jr c, .singleDigitBoxNum
; two digit box num
sub 9
coord hl, 17, 16
ld [hl], "1"
add "0"
jr .next
.singleDigitBoxNum
add "1"
.next
Coorda 18, 16
coord hl, 10, 16
ld de, BoxNoPCText
call PlaceString
ld a, 1
ld [H_AUTOBGTRANSFERENABLED], a
call Delay3
call HandleMenuInput
bit 1, a
jp nz, ExitBillsPC ; b button
call PlaceUnfilledArrowMenuCursor
ld a, [wCurrentMenuItem]
ld [wParentMenuItem], a
and a
jp z, BillsPCWithdraw ; withdraw
cp $1
jp z, BillsPCDeposit ; deposit
cp $2
jp z, BillsPCRelease ; release
cp $3
jp z, BillsPCChangeBox ; change box
ExitBillsPC:
ld a, [wFlags_0xcd60]
bit 3, a ; accessing Bill's PC through another PC?
jr nz, .next
; accessing it directly
call LoadTextBoxTilePatterns
ld a, SFX_TURN_OFF_PC
call PlaySound
call WaitForSoundToFinish
.next
ld hl, wFlags_0xcd60
res 5, [hl]
call LoadScreenTilesFromBuffer2
pop af
ld [wListScrollOffset], a
ld hl, wd730
res 6, [hl]
ret
BillsPCDeposit:
ld a, [wPartyCount]
dec a
jr nz, .partyLargeEnough
ld hl, CantDepositLastMonText
call PrintText
jp BillsPCMenu
.partyLargeEnough
ld a, [wNumInBox]
cp MONS_PER_BOX
jr nz, .boxNotFull
ld hl, BoxFullText
call PrintText
jp BillsPCMenu
.boxNotFull
ld hl, wPartyCount
call DisplayMonListMenu
jp c, BillsPCMenu
call DisplayDepositWithdrawMenu
jp nc, BillsPCMenu
ld a, [wcf91]
call GetCryData
call PlaySoundWaitForCurrent
ld a, PARTY_TO_BOX
ld [wMoveMonType], a
call MoveMon
xor a
ld [wRemoveMonFromBox], a
call RemovePokemon
call WaitForSoundToFinish
ld hl, wBoxNumString
ld a, [wCurrentBoxNum]
and $7f
cp 9
jr c, .singleDigitBoxNum
sub 9
ld [hl], "1"
inc hl
add "0"
jr .next
.singleDigitBoxNum
add "1"
.next
ld [hli], a
ld [hl], "@"
ld hl, MonWasStoredText
call PrintText
jp BillsPCMenu
BillsPCWithdraw:
ld a, [wNumInBox]
and a
jr nz, .boxNotEmpty
ld hl, NoMonText
call PrintText
jp BillsPCMenu
.boxNotEmpty
ld a, [wPartyCount]
cp PARTY_LENGTH
jr nz, .partyNotFull
ld hl, CantTakeMonText
call PrintText
jp BillsPCMenu
.partyNotFull
ld hl, wNumInBox
call DisplayMonListMenu
jp c, BillsPCMenu
call DisplayDepositWithdrawMenu
jp nc, BillsPCMenu
ld a, [wWhichPokemon]
ld hl, wBoxMonNicks
call GetPartyMonName
ld a, [wcf91]
call GetCryData
call PlaySoundWaitForCurrent
xor a ; BOX_TO_PARTY
ld [wMoveMonType], a
call MoveMon
ld a, 1
ld [wRemoveMonFromBox], a
call RemovePokemon
call WaitForSoundToFinish
ld hl, MonIsTakenOutText
call PrintText
jp BillsPCMenu
BillsPCRelease:
ld a, [wNumInBox]
and a
jr nz, .loop
ld hl, NoMonText
call PrintText
jp BillsPCMenu
.loop
ld hl, wNumInBox
call DisplayMonListMenu
jp c, BillsPCMenu
ld hl, OnceReleasedText
call PrintText
call YesNoChoice
ld a, [wCurrentMenuItem]
and a
jr nz, .loop
inc a
ld [wRemoveMonFromBox], a
call RemovePokemon
call WaitForSoundToFinish
ld a, [wcf91]
call PlayCry
ld hl, MonWasReleasedText
call PrintText
jp BillsPCMenu
BillsPCChangeBox:
callba ChangeBox
jp BillsPCMenu
DisplayMonListMenu:
ld a, l
ld [wListPointer], a
ld a, h
ld [wListPointer + 1], a
xor a
ld [wPrintItemPrices], a
ld [wListMenuID], a
inc a ; MONSTER_NAME
ld [wNameListType], a
ld a, [wPartyAndBillsPCSavedMenuItem]
ld [wCurrentMenuItem], a
call DisplayListMenuID
ld a, [wCurrentMenuItem]
ld [wPartyAndBillsPCSavedMenuItem], a
ret
BillsPCMenuText:
db "WITHDRAW <pkmn>"
next "DEPOSIT <pkmn>"
next "RELEASE <pkmn>"
next "CHANGE BOX"
next "SEE YA!"
db "@"
BoxNoPCText:
db "BOX No.@"
KnowsHMMove::
; returns whether mon with party index [wWhichPokemon] knows an HM move
ld hl, wPartyMon1Moves
ld bc, wPartyMon2 - wPartyMon1
jr .next
; unreachable
ld hl, wBoxMon1Moves
ld bc, wBoxMon2 - wBoxMon1
.next
ld a, [wWhichPokemon]
call AddNTimes
ld b, NUM_MOVES
.loop
ld a, [hli]
push hl
push bc
ld hl, HMMoveArray
ld de, 1
call IsInArray
pop bc
pop hl
ret c
dec b
jr nz, .loop
and a
ret
INCLUDE "data/hm_moves.asm"
DisplayDepositWithdrawMenu:
coord hl, 9, 10
ld b, 6
ld c, 9
call TextBoxBorder
ld a, [wParentMenuItem]
and a ; was the Deposit or Withdraw item selected in the parent menu?
ld de, DepositPCText
jr nz, .next
ld de, WithdrawPCText
.next
coord hl, 11, 12
call PlaceString
coord hl, 11, 14
ld de, StatsCancelPCText
call PlaceString
ld hl, wTopMenuItemY
ld a, 12
ld [hli], a ; wTopMenuItemY
ld a, 10
ld [hli], a ; wTopMenuItemX
xor a
ld [hli], a ; wCurrentMenuItem
inc hl
ld a, 2
ld [hli], a ; wMaxMenuItem
ld a, A_BUTTON | B_BUTTON
ld [hli], a ; wMenuWatchedKeys
xor a
ld [hl], a ; wLastMenuItem
ld hl, wListScrollOffset
ld [hli], a ; wListScrollOffset
ld [hl], a ; wMenuWatchMovingOutOfBounds
ld [wPlayerMonNumber], a
ld [wPartyAndBillsPCSavedMenuItem], a
.loop
call HandleMenuInput
bit 1, a ; pressed B?
jr nz, .exit
ld a, [wCurrentMenuItem]
and a
jr z, .choseDepositWithdraw
dec a
jr z, .viewStats
.exit
and a
ret
.choseDepositWithdraw
scf
ret
.viewStats
call SaveScreenTilesToBuffer1
ld a, [wParentMenuItem]
and a
ld a, PLAYER_PARTY_DATA
jr nz, .next2
ld a, BOX_DATA
.next2
ld [wMonDataLocation], a
predef StatusScreen
predef StatusScreen2
call LoadScreenTilesFromBuffer1
call ReloadTilesetTilePatterns
call RunDefaultPaletteCommand
call LoadGBPal
jr .loop
DepositPCText: db "DEPOSIT@"
WithdrawPCText: db "WITHDRAW@"
StatsCancelPCText:
db "STATS"
next "CANCEL@"
SwitchOnText:
TX_FAR _SwitchOnText
db "@"
WhatText:
TX_FAR _WhatText
db "@"
DepositWhichMonText:
TX_FAR _DepositWhichMonText
db "@"
MonWasStoredText:
TX_FAR _MonWasStoredText
db "@"
CantDepositLastMonText:
TX_FAR _CantDepositLastMonText
db "@"
BoxFullText:
TX_FAR _BoxFullText
db "@"
MonIsTakenOutText:
TX_FAR _MonIsTakenOutText
db "@"
NoMonText:
TX_FAR _NoMonText
db "@"
CantTakeMonText:
TX_FAR _CantTakeMonText
db "@"
ReleaseWhichMonText:
TX_FAR _ReleaseWhichMonText
db "@"
OnceReleasedText:
TX_FAR _OnceReleasedText
db "@"
MonWasReleasedText:
TX_FAR _MonWasReleasedText
db "@"
CableClubLeftGameboy::
ld a, [hSerialConnectionStatus]
cp USING_EXTERNAL_CLOCK
ret z
ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction
cp SPRITE_FACING_RIGHT
ret nz
ld a, [wCurMap]
cp TRADE_CENTER
ld a, LINK_STATE_START_TRADE
jr z, .next
inc a ; LINK_STATE_START_BATTLE
.next
ld [wLinkState], a
call EnableAutoTextBoxDrawing
tx_pre_jump JustAMomentText
CableClubRightGameboy::
ld a, [hSerialConnectionStatus]
cp USING_INTERNAL_CLOCK
ret z
ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction
cp SPRITE_FACING_LEFT
ret nz
ld a, [wCurMap]
cp TRADE_CENTER
ld a, LINK_STATE_START_TRADE
jr z, .next
inc a ; LINK_STATE_START_BATTLE
.next
ld [wLinkState], a
call EnableAutoTextBoxDrawing
tx_pre_jump JustAMomentText
JustAMomentText::
TX_FAR _JustAMomentText
db "@"
ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction
cp SPRITE_FACING_UP
ret nz
call EnableAutoTextBoxDrawing
tx_pre_jump OpenBillsPCText
OpenBillsPCText::
TX_BILLS_PC

513
engine/pokemon/evos_moves.asm Executable file
View file

@ -0,0 +1,513 @@
; 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:
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: ; 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 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(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, 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:
; 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:
ld hl, StoppedEvolvingText
call PrintText
call ClearScreen
pop hl
call Evolution_ReloadTilesetTilePatterns
jp Evolution_PartyMonLoop
EvolvedText:
TX_FAR _EvolvedText
db "@"
IntoText:
TX_FAR _IntoText
db "@"
StoppedEvolvingText:
TX_FAR _StoppedEvolvingText
db "@"
IsEvolvingText:
TX_FAR _IsEvolvingText
db "@"
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 CopyStringToCF4B
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, 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:
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
INCLUDE "data/evos_moves.asm"

149
engine/pokemon/experience.asm Executable file
View file

@ -0,0 +1,149 @@
; calculates the level a mon should be based on its current exp
CalcLevelFromExperience::
ld a, [wLoadedMonSpecies]
ld [wd0b5], a
call GetMonHeader
ld d, $1 ; init level to 1
.loop
inc d ; increment level
call CalcExperience
push hl
ld hl, wLoadedMonExp + 2 ; current exp
; compare exp needed for level d with current exp
ld a, [hExperience + 2]
ld c, a
ld a, [hld]
sub c
ld a, [hExperience + 1]
ld c, a
ld a, [hld]
sbc c
ld a, [hExperience]
ld c, a
ld a, [hl]
sbc c
pop hl
jr nc, .loop ; if exp needed for level d is not greater than exp, try the next level
dec d ; since the exp was too high on the last loop iteration, go back to the previous value and return
ret
; calculates the amount of experience needed for level d
CalcExperience::
ld a, [wMonHGrowthRate]
add a
add a
ld c, a
ld b, 0
ld hl, GrowthRateTable
add hl, bc
call CalcDSquared
ld a, d
ld [H_MULTIPLIER], a
call Multiply
ld a, [hl]
and $f0
swap a
ld [H_MULTIPLIER], a
call Multiply
ld a, [hli]
and $f
ld [H_DIVISOR], a
ld b, $4
call Divide
ld a, [H_QUOTIENT + 1]
push af
ld a, [H_QUOTIENT + 2]
push af
ld a, [H_QUOTIENT + 3]
push af
call CalcDSquared
ld a, [hl]
and $7f
ld [H_MULTIPLIER], a
call Multiply
ld a, [H_PRODUCT + 1]
push af
ld a, [H_PRODUCT + 2]
push af
ld a, [H_PRODUCT + 3]
push af
ld a, [hli]
push af
xor a
ld [H_MULTIPLICAND], a
ld [H_MULTIPLICAND + 1], a
ld a, d
ld [H_MULTIPLICAND + 2], a
ld a, [hli]
ld [H_MULTIPLIER], a
call Multiply
ld b, [hl]
ld a, [H_PRODUCT + 3]
sub b
ld [H_PRODUCT + 3], a
ld b, $0
ld a, [H_PRODUCT + 2]
sbc b
ld [H_PRODUCT + 2], a
ld a, [H_PRODUCT + 1]
sbc b
ld [H_PRODUCT + 1], a
; The difference of the linear term and the constant term consists of 3 bytes
; starting at H_PRODUCT + 1. Below, hExperience (an alias of that address) will
; be used instead for the further work of adding or subtracting the squared
; term and adding the cubed term.
pop af
and $80
jr nz, .subtractSquaredTerm ; check sign
pop bc
ld a, [hExperience + 2]
add b
ld [hExperience + 2], a
pop bc
ld a, [hExperience + 1]
adc b
ld [hExperience + 1], a
pop bc
ld a, [hExperience]
adc b
ld [hExperience], a
jr .addCubedTerm
.subtractSquaredTerm
pop bc
ld a, [hExperience + 2]
sub b
ld [hExperience + 2], a
pop bc
ld a, [hExperience + 1]
sbc b
ld [hExperience + 1], a
pop bc
ld a, [hExperience]
sbc b
ld [hExperience], a
.addCubedTerm
pop bc
ld a, [hExperience + 2]
add b
ld [hExperience + 2], a
pop bc
ld a, [hExperience + 1]
adc b
ld [hExperience + 1], a
pop bc
ld a, [hExperience]
adc b
ld [hExperience], a
ret
; calculates d*d
CalcDSquared:
xor a
ld [H_MULTIPLICAND], a
ld [H_MULTIPLICAND + 1], a
ld a, d
ld [H_MULTIPLICAND + 2], a
ld [H_MULTIPLIER], a
jp Multiply
INCLUDE "data/growth_rates.asm"

226
engine/pokemon/learn_move.asm Executable file
View file

@ -0,0 +1,226 @@
LearnMove:
call SaveScreenTilesToBuffer1
ld a, [wWhichPokemon]
ld hl, wPartyMonNicks
call GetPartyMonName
ld hl, wcd6d
ld de, wLearnMoveMonName
ld bc, NAME_LENGTH
call CopyData
DontAbandonLearning:
ld hl, wPartyMon1Moves
ld bc, wPartyMon2Moves - wPartyMon1Moves
ld a, [wWhichPokemon]
call AddNTimes
ld d, h
ld e, l
ld b, NUM_MOVES
.findEmptyMoveSlotLoop
ld a, [hl]
and a
jr z, .next
inc hl
dec b
jr nz, .findEmptyMoveSlotLoop
push de
call TryingToLearn
pop de
jp c, AbandonLearning
push hl
push de
ld [wd11e], a
call GetMoveName
ld hl, OneTwoAndText
call PrintText
pop de
pop hl
.next
ld a, [wMoveNum]
ld [hl], a
ld bc, wPartyMon1PP - wPartyMon1Moves
add hl, bc
push hl
push de
dec a
ld hl, Moves
ld bc, MoveEnd - Moves
call AddNTimes
ld de, wBuffer
ld a, BANK(Moves)
call FarCopyData
ld a, [wBuffer + 5] ; a = move's max PP
pop de
pop hl
ld [hl], a
ld a, [wIsInBattle]
and a
jp z, PrintLearnedMove
ld a, [wWhichPokemon]
ld b, a
ld a, [wPlayerMonNumber]
cp b
jp nz, PrintLearnedMove
ld h, d
ld l, e
ld de, wBattleMonMoves
ld bc, NUM_MOVES
call CopyData
ld bc, wPartyMon1PP - wPartyMon1OTID
add hl, bc
ld de, wBattleMonPP
ld bc, NUM_MOVES
call CopyData
jp PrintLearnedMove
AbandonLearning:
ld hl, AbandonLearningText
call PrintText
coord hl, 14, 7
lb bc, 8, 15
ld a, TWO_OPTION_MENU
ld [wTextBoxID], a
call DisplayTextBoxID ; yes/no menu
ld a, [wCurrentMenuItem]
and a
jp nz, DontAbandonLearning
ld hl, DidNotLearnText
call PrintText
ld b, 0
ret
PrintLearnedMove:
ld hl, LearnedMove1Text
call PrintText
ld b, 1
ret
TryingToLearn:
push hl
ld hl, TryingToLearnText
call PrintText
coord hl, 14, 7
lb bc, 8, 15
ld a, TWO_OPTION_MENU
ld [wTextBoxID], a
call DisplayTextBoxID ; yes/no menu
pop hl
ld a, [wCurrentMenuItem]
rra
ret c
ld bc, -NUM_MOVES
add hl, bc
push hl
ld de, wMoves
ld bc, NUM_MOVES
call CopyData
callab FormatMovesString
pop hl
.loop
push hl
ld hl, WhichMoveToForgetText
call PrintText
coord hl, 4, 7
ld b, 4
ld c, 14
call TextBoxBorder
coord hl, 6, 8
ld de, wMovesString
ld a, [hFlags_0xFFF6]
set 2, a
ld [hFlags_0xFFF6], a
call PlaceString
ld a, [hFlags_0xFFF6]
res 2, a
ld [hFlags_0xFFF6], a
ld hl, wTopMenuItemY
ld a, 8
ld [hli], a ; wTopMenuItemY
ld a, 5
ld [hli], a ; wTopMenuItemX
xor a
ld [hli], a ; wCurrentMenuItem
inc hl
ld a, [wNumMovesMinusOne]
ld [hli], a ; wMaxMenuItem
ld a, A_BUTTON | B_BUTTON
ld [hli], a ; wMenuWatchedKeys
ld [hl], 0 ; wLastMenuItem
ld hl, hFlags_0xFFF6
set 1, [hl]
call HandleMenuInput
ld hl, hFlags_0xFFF6
res 1, [hl]
push af
call LoadScreenTilesFromBuffer1
pop af
pop hl
bit 1, a ; pressed b
jr nz, .cancel
push hl
ld a, [wCurrentMenuItem]
ld c, a
ld b, 0
add hl, bc
ld a, [hl]
push af
push bc
call IsMoveHM
pop bc
pop de
ld a, d
jr c, .hm
pop hl
add hl, bc
and a
ret
.hm
ld hl, HMCantDeleteText
call PrintText
pop hl
jr .loop
.cancel
scf
ret
LearnedMove1Text:
TX_FAR _LearnedMove1Text
TX_SFX_ITEM_1 ; plays SFX_GET_ITEM_1 in the party menu (rare candy) and plays SFX_LEVEL_UP in battle
TX_BLINK
db "@"
WhichMoveToForgetText:
TX_FAR _WhichMoveToForgetText
db "@"
AbandonLearningText:
TX_FAR _AbandonLearningText
db "@"
DidNotLearnText:
TX_FAR _DidNotLearnText
db "@"
TryingToLearnText:
TX_FAR _TryingToLearnText
db "@"
OneTwoAndText:
TX_FAR _OneTwoAndText
TX_DELAY
TX_ASM
ld a, SFX_SWAP
call PlaySoundWaitForCurrent
ld hl, PoofText
ret
PoofText:
TX_FAR _PoofText
TX_DELAY
ForgotAndText:
TX_FAR _ForgotAndText
db "@"
HMCantDeleteText:
TX_FAR _HMCantDeleteText
db "@"

View file

@ -0,0 +1,49 @@
LoadMonData_::
; Load monster [wWhichPokemon] from list [wMonDataLocation]:
; 0: partymon
; 1: enemymon
; 2: boxmon
; 3: daycaremon
; Return monster id at wcf91 and its data at wLoadedMon.
; Also load base stats at wMonHeader for convenience.
ld a, [wDayCareMonSpecies]
ld [wcf91], a
ld a, [wMonDataLocation]
cp DAYCARE_DATA
jr z, .GetMonHeader
ld a, [wWhichPokemon]
ld e, a
callab GetMonSpecies
.GetMonHeader
ld a, [wcf91]
ld [wd0b5], a ; input for GetMonHeader
call GetMonHeader
ld hl, wPartyMons
ld bc, wPartyMon2 - wPartyMon1
ld a, [wMonDataLocation]
cp ENEMY_PARTY_DATA
jr c, .getMonEntry
ld hl, wEnemyMons
jr z, .getMonEntry
cp 2
ld hl, wBoxMons
ld bc, wBoxMon2 - wBoxMon1
jr z, .getMonEntry
ld hl, wDayCareMon
jr .copyMonData
.getMonEntry
ld a, [wWhichPokemon]
call AddNTimes
.copyMonData
ld de, wLoadedMon
ld bc, wPartyMon2 - wPartyMon1
jp CopyData

View file

@ -0,0 +1,95 @@
_RemovePokemon::
ld hl, wPartyCount
ld a, [wRemoveMonFromBox]
and a
jr z, .asm_7b74
ld hl, wNumInBox
.asm_7b74
ld a, [hl]
dec a
ld [hli], a
ld a, [wWhichPokemon]
ld c, a
ld b, $0
add hl, bc
ld e, l
ld d, h
inc de
.asm_7b81
ld a, [de]
inc de
ld [hli], a
inc a
jr nz, .asm_7b81
ld hl, wPartyMonOT
ld d, $5
ld a, [wRemoveMonFromBox]
and a
jr z, .asm_7b97
ld hl, wBoxMonOT
ld d, $13
.asm_7b97
ld a, [wWhichPokemon]
call SkipFixedLengthTextEntries
ld a, [wWhichPokemon]
cp d
jr nz, .asm_7ba6
ld [hl], $ff
ret
.asm_7ba6
ld d, h
ld e, l
ld bc, NAME_LENGTH
add hl, bc
ld bc, wPartyMonNicks
ld a, [wRemoveMonFromBox]
and a
jr z, .asm_7bb8
ld bc, wBoxMonNicks
.asm_7bb8
call CopyDataUntil
ld hl, wPartyMons
ld bc, wPartyMon2 - wPartyMon1
ld a, [wRemoveMonFromBox]
and a
jr z, .asm_7bcd
ld hl, wBoxMons
ld bc, wBoxMon2 - wBoxMon1
.asm_7bcd
ld a, [wWhichPokemon]
call AddNTimes
ld d, h
ld e, l
ld a, [wRemoveMonFromBox]
and a
jr z, .asm_7be4
ld bc, wBoxMon2 - wBoxMon1
add hl, bc
ld bc, wBoxMonOT
jr .asm_7beb
.asm_7be4
ld bc, wPartyMon2 - wPartyMon1
add hl, bc
ld bc, wPartyMonOT
.asm_7beb
call CopyDataUntil
ld hl, wPartyMonNicks
ld a, [wRemoveMonFromBox]
and a
jr z, .asm_7bfa
ld hl, wBoxMonNicks
.asm_7bfa
ld bc, NAME_LENGTH
ld a, [wWhichPokemon]
call AddNTimes
ld d, h
ld e, l
ld bc, NAME_LENGTH
add hl, bc
ld bc, wPokedexOwned
ld a, [wRemoveMonFromBox]
and a
jr z, .asm_7c15
ld bc, wBoxMonNicksEnd
.asm_7c15
jp CopyDataUntil

15
engine/pokemon/set_types.asm Executable file
View file

@ -0,0 +1,15 @@
; updates the types of a party mon (pointed to in hl) to the ones of the mon specified in wd11e
SetPartyMonTypes:
call GetPredefRegisters
ld bc, wPartyMon1Type - wPartyMon1 ; $5
add hl, bc
ld a, [wd11e]
ld [wd0b5], a
push hl
call GetMonHeader
pop hl
ld a, [wMonHType1]
ld [hli], a
ld a, [wMonHType2]
ld [hl], a
ret

View file

@ -0,0 +1,46 @@
PrintStatusAilment::
ld a, [de]
bit PSN, a
jr nz, .psn
bit BRN, a
jr nz, .brn
bit FRZ, a
jr nz, .frz
bit PAR, a
jr nz, .par
and SLP
ret z
ld a, "S"
ld [hli], a
ld a, "L"
ld [hli], a
ld [hl], "P"
ret
.psn
ld a, "P"
ld [hli], a
ld a, "S"
ld [hli], a
ld [hl], "N"
ret
.brn
ld a, "B"
ld [hli], a
ld a, "R"
ld [hli], a
ld [hl], "N"
ret
.frz
ld a, "F"
ld [hli], a
ld a, "R"
ld [hli], a
ld [hl], "Z"
ret
.par
ld a, "P"
ld [hli], a
ld a, "A"
ld [hli], a
ld [hl], "R"
ret

481
engine/pokemon/status_screen.asm Executable file
View file

@ -0,0 +1,481 @@
DrawHP:
; Draws the HP bar in the stats screen
call GetPredefRegisters
ld a, $1
jr DrawHP_
DrawHP2:
; Draws the HP bar in the party screen
call GetPredefRegisters
ld a, $2
DrawHP_:
ld [wHPBarType], a
push hl
ld a, [wLoadedMonHP]
ld b, a
ld a, [wLoadedMonHP + 1]
ld c, a
or b
jr nz, .nonzeroHP
xor a
ld c, a
ld e, a
ld a, $6
ld d, a
jp .drawHPBarAndPrintFraction
.nonzeroHP
ld a, [wLoadedMonMaxHP]
ld d, a
ld a, [wLoadedMonMaxHP + 1]
ld e, a
predef HPBarLength
ld a, $6
ld d, a
ld c, a
.drawHPBarAndPrintFraction
pop hl
push de
push hl
push hl
call DrawHPBar
pop hl
ld a, [hFlags_0xFFF6]
bit 0, a
jr z, .printFractionBelowBar
ld bc, $9 ; right of bar
jr .printFraction
.printFractionBelowBar
ld bc, SCREEN_WIDTH + 1 ; below bar
.printFraction
add hl, bc
ld de, wLoadedMonHP
lb bc, 2, 3
call PrintNumber
ld a, "/"
ld [hli], a
ld de, wLoadedMonMaxHP
lb bc, 2, 3
call PrintNumber
pop hl
pop de
ret
; Predef 0x37
StatusScreen:
call LoadMonData
ld a, [wMonDataLocation]
cp BOX_DATA
jr c, .DontRecalculate
; mon is in a box or daycare
ld a, [wLoadedMonBoxLevel]
ld [wLoadedMonLevel], a
ld [wCurEnemyLVL], a
ld hl, wLoadedMonHPExp - 1
ld de, wLoadedMonStats
ld b, $1
call CalcStats ; Recalculate stats
.DontRecalculate
ld hl, wd72c
set 1, [hl]
ld a, $33
ld [rNR50], a ; Reduce the volume
call GBPalWhiteOutWithDelay3
call ClearScreen
call UpdateSprites
call LoadHpBarAndStatusTilePatterns
ld de, BattleHudTiles1 ; source
ld hl, vChars2 + $6d0 ; dest
lb bc, BANK(BattleHudTiles1), $03
call CopyVideoDataDouble ; ·│ :L and halfarrow line end
ld de, BattleHudTiles2
ld hl, vChars2 + $780
lb bc, BANK(BattleHudTiles2), $01
call CopyVideoDataDouble ; │
ld de, BattleHudTiles3
ld hl, vChars2 + $760
lb bc, BANK(BattleHudTiles3), $02
call CopyVideoDataDouble ; ─┘
ld de, PTile
ld hl, vChars2 + $720
lb bc, BANK(PTile), (PTileEnd - PTile) / $8
call CopyVideoDataDouble ; P (for PP), inline
ld a, [hTilesetType]
push af
xor a
ld [hTilesetType], a
coord hl, 19, 1
lb bc, 6, 10
call DrawLineBox ; Draws the box around name, HP and status
ld de, -6
add hl, de
ld [hl], "⠄" ; . after No ("." is a different one)
dec hl
ld [hl], "№"
coord hl, 19, 9
lb bc, 8, 6
call DrawLineBox ; Draws the box around types, ID No. and OT
coord hl, 10, 9
ld de, Type1Text
call PlaceString ; "TYPE1/"
coord hl, 11, 3
predef DrawHP
ld hl, wStatusScreenHPBarColor
call GetHealthBarColor
ld b, SET_PAL_STATUS_SCREEN
call RunPaletteCommand
coord hl, 16, 6
ld de, wLoadedMonStatus
call PrintStatusCondition
jr nz, .StatusWritten
coord hl, 16, 6
ld de, OKText
call PlaceString ; "OK"
.StatusWritten
coord hl, 9, 6
ld de, StatusText
call PlaceString ; "STATUS/"
coord hl, 14, 2
call PrintLevel ; Pokémon level
ld a, [wMonHIndex]
ld [wd11e], a
ld [wd0b5], a
predef IndexToPokedex
coord hl, 3, 7
ld de, wd11e
lb bc, LEADING_ZEROES | 1, 3
call PrintNumber ; Pokémon no.
coord hl, 11, 10
predef PrintMonType
ld hl, NamePointers2
call .GetStringPointer
ld d, h
ld e, l
coord hl, 9, 1
call PlaceString ; Pokémon name
ld hl, OTPointers
call .GetStringPointer
ld d, h
ld e, l
coord hl, 12, 16
call PlaceString ; OT
coord hl, 12, 14
ld de, wLoadedMonOTID
lb bc, LEADING_ZEROES | 2, 5
call PrintNumber ; ID Number
ld d, $0
call PrintStatsBox
call Delay3
call GBPalNormal
coord hl, 1, 0
call LoadFlippedFrontSpriteByMonIndex ; draw Pokémon picture
ld a, [wcf91]
call PlayCry ; play Pokémon cry
call WaitForTextScrollButtonPress ; wait for button
pop af
ld [hTilesetType], a
ret
.GetStringPointer
ld a, [wMonDataLocation]
add a
ld c, a
ld b, 0
add hl, bc
ld a, [hli]
ld h, [hl]
ld l, a
ld a, [wMonDataLocation]
cp DAYCARE_DATA
ret z
ld a, [wWhichPokemon]
jp SkipFixedLengthTextEntries
OTPointers:
dw wPartyMonOT
dw wEnemyMonOT
dw wBoxMonOT
dw wDayCareMonOT
NamePointers2:
dw wPartyMonNicks
dw wEnemyMonNicks
dw wBoxMonNicks
dw wDayCareMonName
Type1Text:
db "TYPE1/", $4e
Type2Text:
db "TYPE2/", $4e
IDNoText:
db $73, "№/", $4e
OTText:
db "OT/"
next "@"
StatusText:
db "STATUS/@"
OKText:
db "OK@"
; Draws a line starting from hl high b and wide c
DrawLineBox:
ld de, SCREEN_WIDTH ; New line
.PrintVerticalLine
ld [hl], $78 ; │
add hl, de
dec b
jr nz, .PrintVerticalLine
ld [hl], $77 ; ┘
dec hl
.PrintHorizLine
ld [hl], $76 ; ─
dec hl
dec c
jr nz, .PrintHorizLine
ld [hl], $6f ; ← (halfarrow ending)
ret
PTile:
INCBIN "gfx/font/P.1bpp"
PTileEnd:
PrintStatsBox:
ld a, d
and a ; a is 0 from the status screen
jr nz, .DifferentBox
coord hl, 0, 8
ld b, 8
ld c, 8
call TextBoxBorder ; Draws the box
coord hl, 1, 9 ; Start printing stats from here
ld bc, $0019 ; Number offset
jr .PrintStats
.DifferentBox
coord hl, 9, 2
ld b, 8
ld c, 9
call TextBoxBorder
coord hl, 11, 3
ld bc, $0018
.PrintStats
push bc
push hl
ld de, StatsText
call PlaceString
pop hl
pop bc
add hl, bc
ld de, wLoadedMonAttack
lb bc, 2, 3
call PrintStat
ld de, wLoadedMonDefense
call PrintStat
ld de, wLoadedMonSpeed
call PrintStat
ld de, wLoadedMonSpecial
jp PrintNumber
PrintStat:
push hl
call PrintNumber
pop hl
ld de, SCREEN_WIDTH * 2
add hl, de
ret
StatsText:
db "ATTACK"
next "DEFENSE"
next "SPEED"
next "SPECIAL@"
StatusScreen2:
ld a, [hTilesetType]
push af
xor a
ld [hTilesetType], a
ld [H_AUTOBGTRANSFERENABLED], a
ld bc, NUM_MOVES + 1
ld hl, wMoves
call FillMemory
ld hl, wLoadedMonMoves
ld de, wMoves
ld bc, NUM_MOVES
call CopyData
callab FormatMovesString
coord hl, 9, 2
lb bc, 5, 10
call ClearScreenArea ; Clear under name
coord hl, 19, 3
ld [hl], $78
coord hl, 0, 8
ld b, 8
ld c, 18
call TextBoxBorder ; Draw move container
coord hl, 2, 9
ld de, wMovesString
call PlaceString ; Print moves
ld a, [wNumMovesMinusOne]
inc a
ld c, a
ld a, $4
sub c
ld b, a ; Number of moves ?
coord hl, 11, 10
ld de, SCREEN_WIDTH * 2
ld a, $72 ; special P tile id
call StatusScreen_PrintPP ; Print "PP"
ld a, b
and a
jr z, .InitPP
ld c, a
ld a, "-"
call StatusScreen_PrintPP ; Fill the rest with --
.InitPP
ld hl, wLoadedMonMoves
coord de, 14, 10
ld b, 0
.PrintPP
ld a, [hli]
and a
jr z, .PPDone
push bc
push hl
push de
ld hl, wCurrentMenuItem
ld a, [hl]
push af
ld a, b
ld [hl], a
push hl
callab GetMaxPP
pop hl
pop af
ld [hl], a
pop de
pop hl
push hl
ld bc, wPartyMon1PP - wPartyMon1Moves - 1
add hl, bc
ld a, [hl]
and $3f
ld [wStatusScreenCurrentPP], a
ld h, d
ld l, e
push hl
ld de, wStatusScreenCurrentPP
lb bc, 1, 2
call PrintNumber
ld a, "/"
ld [hli], a
ld de, wMaxPP
lb bc, 1, 2
call PrintNumber
pop hl
ld de, SCREEN_WIDTH * 2
add hl, de
ld d, h
ld e, l
pop hl
pop bc
inc b
ld a, b
cp $4
jr nz, .PrintPP
.PPDone
coord hl, 9, 3
ld de, StatusScreenExpText
call PlaceString
ld a, [wLoadedMonLevel]
push af
cp MAX_LEVEL
jr z, .Level100
inc a
ld [wLoadedMonLevel], a ; Increase temporarily if not 100
.Level100
coord hl, 14, 6
ld [hl], $70 ; 1-tile "to"
inc hl
inc hl
call PrintLevel
pop af
ld [wLoadedMonLevel], a
ld de, wLoadedMonExp
coord hl, 12, 4
lb bc, 3, 7
call PrintNumber ; exp
call CalcExpToLevelUp
ld de, wLoadedMonExp
coord hl, 7, 6
lb bc, 3, 7
call PrintNumber ; exp needed to level up
coord hl, 9, 0
call StatusScreen_ClearName
coord hl, 9, 1
call StatusScreen_ClearName
ld a, [wMonHIndex]
ld [wd11e], a
call GetMonName
coord hl, 9, 1
call PlaceString
ld a, $1
ld [H_AUTOBGTRANSFERENABLED], a
call Delay3
call WaitForTextScrollButtonPress ; wait for button
pop af
ld [hTilesetType], a
ld hl, wd72c
res 1, [hl]
ld a, $77
ld [rNR50], a
call GBPalWhiteOut
jp ClearScreen
CalcExpToLevelUp:
ld a, [wLoadedMonLevel]
cp MAX_LEVEL
jr z, .atMaxLevel
inc a
ld d, a
callab CalcExperience
ld hl, wLoadedMonExp + 2
ld a, [hExperience + 2]
sub [hl]
ld [hld], a
ld a, [hExperience + 1]
sbc [hl]
ld [hld], a
ld a, [hExperience]
sbc [hl]
ld [hld], a
ret
.atMaxLevel
ld hl, wLoadedMonExp
xor a
ld [hli], a
ld [hli], a
ld [hl], a
ret
StatusScreenExpText:
db "EXP POINTS"
next "LEVEL UP@"
StatusScreen_ClearName:
ld bc, 10
ld a, " "
jp FillMemory
StatusScreen_PrintPP:
; print PP or -- c times, going down two rows each time
ld [hli], a
ld [hld], a
add hl, de
dec c
jr nz, StatusScreen_PrintPP
ret