Questo Forum utilizza i Cookies
Questo Forum fa uso di Cookies per memorizzare le informazioni di login se sei registrato o sulla tua ultima visita se non siete registrati. I Cookies sono piccoli documenti di testo memorizzati sul vostro computer; i Cookies impostati dal Forum possono essere utilizzati solo su questo sito e non costituiscono rischio per la sicurezza. I Cookies su questo forum servono anche a monitorare gli argomenti specifici che hai letto. Si prega di confermare se accettare o rifiutare i Cookies impostati.

Un cookie verrà memorizzato nel browser indipendentemente dalla scelta, per evitare che il Forum faccia nuovamente questa domanda. Sarete in grado di modificare le impostazioni dei cookies in qualsiasi momento tramite il link a piè di pagina

Rispondi 
[Gb] Item Hacking Tutorial - Strumenti
80C
['e…™t…™ s…™:]
******
Assente

Messaggi: 1,973
Registrato: 12-06-2014
Reputazione: 34
Mi Piace Ricevuti: 1577
PH Points: 3,666.00
Messaggio: #1
Lightbulb Item Hacking Tutorial - Strumenti

Addenda 1: Leggere attentamente questo thread per mettere a posto un piccolo bug del gioco originale nel caso di utilizzo di strumenti il cui ID interno va oltre 0x7F.

Addenda 2: Istruzioni per il Disassembler.
Il file della Repository da modificare è engine\items\items.asm.

Di seguito la versione Italiana del mio Tutorial del 2013:

Questo non è un tutorial per chi non ha basi minime di competenze con un Hex Editor, bisogna sapere almeno come copiare ed incollare i dati senza corrompere la ROM e come fare i repoint.

Bene, ecco questo nuovo Tutorial di Hacking fatto da me e pensato per gli hacker novizi che vogliono hackerare Red\Blue con l' HexEditing poiché non ci sono dei programmi decenti (o almeno, non ancora) per la generazione 1 che sono in grado di fare cambiamenti profondi.
In R\B (e anche Y & G) tutti i dati relativi agli strumenti sono suddivisi in 3 parti: Nomi, Utilizzo e Prezzi.

Ecco ciò di cui avrete bisogno:
*0: (ESSENZIALE): La tua ROM, un buon hex editor e competenze base col programma;
*1: La lista degli oggetti per indice interno:

Codice:
MASTER BALL    $01
ULTRA BALL     $02
GREAT BALL     $03
POKE BALL      $04
TOWN MAP       $05
BICYCLE        $06
SURFBOARD      $07 ; Unused and glitchy, it corrupts the Hall Of Fame data.
SAFARI BALL    $08
POKEDEX        $09
MOON STONE     $0A
ANTIDOTE       $0B
BURN HEAL      $0C
ICE HEAL       $0D
AWAKENING      $0E
PARLYZ HEAL    $0F
FULL RESTORE   $10
MAX POTION     $11
HYPER POTION   $12
SUPER POTION   $13
POTION         $14
BOULDERBADGE   $15 ; unused, used only for Badge List in Cerulean House.
CASCADEBADGE   $16 ; unused, used only for Badge List in Cerulean House.
THUNDERBADGE   $17 ; unused, used only for Badge List in Cerulean House.
RAINBOWBADGE   $18 ; unused, used only for Badge List in Cerulean House.
SOULBADGE      $19 ; unused, used only for Badge List in Cerulean House.
MARSHBADGE     $1A ; unused, used only for Badge List in Cerulean House.
VOLCANOBADGE   $1B ; unused, used only for Badge List in Cerulean House.
EARTHBADGE     $1C ; unused, used only for Badge List in Cerulean House.
ESCAPE ROPE    $1D
REPEL          $1E
OLD AMBER      $1F
FIRE STONE     $20
THUNDER STONE  $21
WATER STONE    $22
HP UP          $23
PROTEIN        $24
IRON           $25
CARBOS         $26
CALCIUM        $27
RARE CANDY     $28
DOME FOSSIL    $29
HELIX FOSSIL   $2A
SECRET KEY     $2B
;?????         $2C ; Supposed to be a Key Item then removed.
BIKE VOUCHER   $2D
X ACCURACY     $2E
LEAF STONE     $2F
CARD KEY       $30
NUGGET         $31
;FAKE PP UP    $32 ; It has no use.
POKE DOLL      $33
FULL HEAL      $34
REVIVE         $35
MAX REVIVE     $36
GUARD SPEC     $37
SUPER REPEL    $38
MAX REPEL      $39
DIRE HIT       $3A
COIN           $3B ; It has no use, replaced by Casino Coins in Coin Case.
FRESH WATER    $3C
SODA POP       $3D
LEMONADE       $3E
S S  TICKET    $3F
GOLD TEETH     $40
X ATTACK       $41
X DEFEND       $42
X SPEED        $43
X SPECIAL      $44
COIN CASE      $45
OAKS PARCEL    $46
ITEMFINDER     $47
SILPH SCOPE    $48
POKE FLUTE     $49
LIFT KEY       $4A
EXP  ALL       $4B
OLD ROD        $4C
GOOD ROD       $4D
SUPER ROD      $4E
PP UP          $4F
ETHER          $50
MAX ETHER      $51
ELIXER         $52
MAX ELIXER     $53
; After $53 There are glitchy items used only for the Elevators
; such as 1F, 8F, etc.
; Most of those items are glitchy and corrupts the game.
;
;---------
;
; HM\TM Items List.
;Begins with HM 01 with index number $C4.
;
HM 01          $C4
HM 02          $C5
HM 03          $C6
HM 04          $C7
HM 05          $C8
TM 01          $C9
TM 02          $CA
TM 03          $CB
TM 04          $CC
TM 05          $CD
TM 06          $CE
TM 07          $CF
TM 08          $D0
TM 09          $D1
TM 10          $D2
TM 11          $D3
TM 12          $D4
TM 13          $D5
TM 14          $D6
TM 15          $D7
TM 16          $D8
TM 17          $D9
TM 18          $DA
TM 19          $DB
TM 20          $DC
TM 21          $DD
TM 22          $DE
TM 23          $DF
TM 24          $E0
TM 25          $E1
TM 26          $E2
TM 27          $E3
TM 28          $E4
TM 29          $E5
TM 30          $E6
TM 31          $E7
TM 32          $E8
TM 33          $E9
TM 34          $EA
TM 35          $EB
TM 36          $EC
TM 37          $ED
TM 38          $EE
TM 39          $EF
TM 40          $F0
TM 41          $F1
TM 42          $F2
TM 43          $F3
TM 44          $F4
TM 45          $F5
TM 46          $F6
TM 47          $F7
TM 48          $F8
TM 49          $F9
TM 50          $FA
;
;end of Item Data.


*2: Molto tempo;
*3: Molta pazienza;
*4: Molta Ginger Soda per contrastare la disidratazione conseguente all' hacking;
*5: Seguire i prossimi step accuratamente:
-------------
STEP 01: NOMI DEGLI STRUMENTI

La tabella che contiene i nomi degli oggetti è situata a 0x472B (01:472B).
Se si desidera utilizzare un nome pi√Ļ largo dovrete spostare i nomi seguenti di qualche byte pi√Ļ avanti (senza sovrascrivere dati importanti salvati oltre la tabella), inserire il nuovo nome e poi reincollare i nomi precedentemente copiati ma ricordate: MAI usare taglia-incolla in un hex editor, solo copia-incolla sullo stesso numero di byte selezionati (se ho selezionato 700 bytes e poi devo sovrascrivere quando far√≤ incolla dovr√≤ aver selezionato sempre altri 700 bytes).
Tenete a mente che il numero massimo di caratteri consentito per il nome di un oggetto è 12.
Non dimenticate inoltre che se avete troppo spazio dovrete fare il repoint della tabella in uno spazio libero all' interno dello stesso bank.

In tal caso, i due pointer per la tabella dei nomi degli oggetti si trovano in:
*0x39CB
*0x39C14

Questo viene dal Disassembly project:
Codice:
ItemNames: ; 472b (1:472b)
    db "MASTER BALL@"
    db "ULTRA BALL@"
    db "GREAT BALL@"
    db "POK√ɬ© BALL@"
    db "TOWN MAP@"
    db "BICYCLE@"
    db "?????@"
    db "SAFARI BALL@"
    db "POK√ɬ©DEX@"
    db "MOON STONE@"
    db "ANTIDOTE@"
    db "BURN HEAL@"
    db "ICE HEAL@"
    db "AWAKENING@"
    db "PARLYZ HEAL@"
    db "FULL RESTORE@"
    db "MAX POTION@"
    db "HYPER POTION@"
    db "SUPER POTION@"
    db "POTION@"
    db "BOULDERBADGE@"
    db "CASCADEBADGE@"
    db "THUNDERBADGE@"
    db "RAINBOWBADGE@"
    db "SOULBADGE@"
    db "MARSHBADGE@"
    db "VOLCANOBADGE@"
    db "EARTHBADGE@"
    db "ESCAPE ROPE@"
    db "REPEL@"
    db "OLD AMBER@"
    db "FIRE STONE@"
    db "THUNDERSTONE@"
    db "WATER STONE@"
    db "HP UP@"
    db "PROTEIN@"
    db "IRON@"
    db "CARBOS@"
    db "CALCIUM@"
    db "RARE CANDY@"
    db "DOME FOSSIL@"
    db "HELIX FOSSIL@"
    db "SECRET KEY@"
    db "?????@"
    db "BIKE VOUCHER@"
    db "X ACCURACY@"
    db "LEAF STONE@"
    db "CARD KEY@"
    db "NUGGET@"
    db "PP UP@"
    db "POK√ɬ© DOLL@"
    db "FULL HEAL@"
    db "REVIVE@"
    db "MAX REVIVE@"
    db "GUARD SPEC.@"
    db "SUPER REPEL@"
    db "MAX REPEL@"
    db "DIRE HIT@"
    db "COIN@"
    db "FRESH WATER@"
    db "SODA POP@"
    db "LEMONADE@"
    db "S.S.TICKET@"
    db "GOLD TEETH@"
    db "X ATTACK@"
    db "X DEFEND@"
    db "X SPEED@"
    db "X SPECIAL@"
    db "COIN CASE@"
    db "OAK's PARCEL@"
    db "ITEMFINDER@"
    db "SILPH SCOPE@"
    db "POK√ɬ© FLUTE@"
    db "LIFT KEY@"
    db "EXP.ALL@"
    db "OLD ROD@"
    db "GOOD ROD@"
    db "SUPER ROD@"
    db "PP UP@"
    db "ETHER@"
    db "MAX ETHER@"
    db "ELIXER@"
    db "MAX ELIXER@"
    db "B2F@"
    db "B1F@"
    db "1F@"
    db "2F@"
    db "3F@"
    db "4F@"
    db "5F@"
    db "6F@"
    db "7F@"
    db "8F@"
    db "9F@"
    db "10F@"
    db "11F@"
    db "B4F@"

UnusedNames: ; 4a92 (1:4a92)

I nomi inutilizzati sono attualmente... nomi inutilizzati in formato ingarbugliato perché vengono dalla versione giapponese e ci sono solo nomi beta di oggetti che non sono neppure di Pokemon ma del gioco che è stato usato come base per crearlo, Earthbound.
Attualmente non ho idea se azzerare questi nomi inutilizzati sia un rischio o no.

-------------
STEP 02: PREZZI DEGLI STRUMENTI

Ci sono già dei programmi per la modifica prezzi degli oggetti ma quello che i programmi non sanno fare è cambiare i prezzi se i dati sono stati spostati ;P
In realtà si può repointare la tabella nel caso in cui avete bisogno di nuovi prezzi per dei nuovi oggetti che avete aggiunto, in poche parole si possono aggiungere nuovi prezzi.


Se vuoi fare il repoint di quei dati il pointer si trova a:
*39C2C

La Tabella stessa dei Prezzi degli Oggetti è originariamente situata a 0x4608 (01:4608).
Ogni 3 byte un prezzo è indicato.

esempio: UltraBall price: $00,$12,$00.

Questo accade semplicemente perché i valori esadecimali in un singolo byte possono coprire un raggio di 00-FF (0 - 255), ma i prezzi sono spesso superiori a 255.
In ogni caso prestate attenzione perché in questo caso i byte vengono scritti in un formato pseudo-decimale, quindi se il costo di un oggetto è "1200", allora i suoi byte saranno "00, 12, 00".

-------------
STEP 03: HACK ITEM USE

Ora la parte pi√Ļ importante di dati: l'uso degli oggetti.
C'è una tabella situata a 0xD5E1 (03:55E1) che contiene un elenco di pointer per l'utilizzo degli strumenti.
Ogni strumento ha 1 pointer (formato da 2 byte in Little Endian), che punta ad una particolare routine nello stesso Bank.
Ciò significa che, se per qualche motivo si è spostato uno di quelli in precedenza allora dovrete fare il repoint di ogni elemento associato al suo utilizzo.

Questo viene dal Disassembly Project:

Codice:
ItemUsePtrTable: ; d5e1 (3:55e1)
    dw ItemUseBall       ; MASTER_BALL
    dw ItemUseBall       ; ULTRA_BALL
    dw ItemUseBall       ; GREAT_BALL
    dw ItemUseBall       ; POKE_BALL
    dw ItemUseTownMap    ; TOWN_MAP
    dw ItemUseBicycle    ; BICYCLE
    dw ItemUseSurfboard  ; out-of-battle Surf effect
    dw ItemUseBall       ; SAFARI_BALL
    dw ItemUsePokedex    ; POKEDEX
    dw ItemUseEvoStone   ; MOON_STONE
    dw ItemUseMedicine   ; ANTIDOTE
    dw ItemUseMedicine   ; BURN_HEAL
    dw ItemUseMedicine   ; ICE_HEAL
    dw ItemUseMedicine   ; AWAKENING
    dw ItemUseMedicine   ; PARLYZ_HEAL
    dw ItemUseMedicine   ; FULL_RESTORE
    dw ItemUseMedicine   ; MAX_POTION
    dw ItemUseMedicine   ; HYPER_POTION
    dw ItemUseMedicine   ; SUPER_POTION
    dw ItemUseMedicine   ; POTION
    dw ItemUseBait       ; BOULDERBADGE
    dw ItemUseRock       ; CASCADEBADGE
    dw UnusableItem      ; THUNDERBADGE
    dw UnusableItem      ; RAINBOWBADGE
    dw UnusableItem      ; SOULBADGE
    dw UnusableItem      ; MARSHBADGE
    dw UnusableItem      ; VOLCANOBADGE
    dw UnusableItem      ; EARTHBADGE
    dw ItemUseEscapeRope ; ESCAPE_ROPE
    dw ItemUseRepel      ; REPEL
    dw UnusableItem      ; OLD_AMBER
    dw ItemUseEvoStone   ; FIRE_STONE
    dw ItemUseEvoStone   ; THUNDER_STONE
    dw ItemUseEvoStone   ; WATER_STONE
    dw ItemUseVitamin    ; HP_UP
    dw ItemUseVitamin    ; PROTEIN
    dw ItemUseVitamin    ; IRON
    dw ItemUseVitamin    ; CARBOS
    dw ItemUseVitamin    ; CALCIUM
    dw ItemUseVitamin    ; RARE_CANDY
    dw UnusableItem      ; DOME_FOSSIL
    dw UnusableItem      ; HELIX_FOSSIL
    dw UnusableItem      ; SECRET_KEY
    dw UnusableItem
    dw UnusableItem      ; BIKE_VOUCHER
    dw ItemUseXAccuracy  ; X_ACCURACY
    dw ItemUseEvoStone   ; LEAF_STONE
    dw ItemUseCardKey    ; CARD_KEY
    dw UnusableItem      ; NUGGET
    dw UnusableItem      ; ??? PP_UP
    dw ItemUsePokedoll   ; POKE_DOLL
    dw ItemUseMedicine   ; FULL_HEAL
    dw ItemUseMedicine   ; REVIVE
    dw ItemUseMedicine   ; MAX_REVIVE
    dw ItemUseGuardSpec  ; GUARD_SPEC_
    dw ItemUseSuperRepel ; SUPER_REPL
    dw ItemUseMaxRepel   ; MAX_REPEL
    dw ItemUseDireHit    ; DIRE_HIT
    dw UnusableItem      ; COIN
    dw ItemUseMedicine   ; FRESH_WATER
    dw ItemUseMedicine   ; SODA_POP
    dw ItemUseMedicine   ; LEMONADE
    dw UnusableItem      ; S_S__TICKET
    dw UnusableItem      ; GOLD_TEETH
    dw ItemUseXStat      ; X_ATTACK
    dw ItemUseXStat      ; X_DEFEND
    dw ItemUseXStat      ; X_SPEED
    dw ItemUseXStat      ; X_SPECIAL
    dw ItemUseCoinCase   ; COIN_CASE
    dw ItemUseOaksParcel ; OAKS_PARCEL
    dw ItemUseItemfinder ; ITEMFINDER
    dw UnusableItem      ; SILPH_SCOPE
    dw ItemUsePokeflute  ; POKE_FLUTE
    dw UnusableItem      ; LIFT_KEY
    dw UnusableItem      ; EXP__ALL
    dw OldRodCode        ; OLD_ROD
    dw GoodRodCode       ; GOOD_ROD
    dw SuperRodCode      ; SUPER_ROD
    dw ItemUsePPUp       ; PP_UP (real one)
    dw ItemUsePPRestore  ; ETHER
    dw ItemUsePPRestore  ; MAX_ETHER
    dw ItemUsePPRestore  ; ELIXER
    dw ItemUsePPRestore  ; MAX_ELIXER

Se si desidera cambiare l'uso di un oggetto semplicemente cambiate il suo pointer all' indirizzo di un altra routine asm associata ad un altro uso.

Questo significa che in realtà si potrebbe essere in grado di creare nuove routine asm per poi indirizzarne l'utilizzo di uno strumento su questa nuova routine permettendo, difatti, di creare oggetti con nuovi utilizzi (come ho fatto in precedenza in alcuni delle mie hack).

-------
STEP 04: OPZIONALE
Aka: Ultima parte opzionale per quegli strumenti il cui utilizzo √® inteso per il men√Ļ Squadra Pokemon:

C'è una tabella per questo tipo di problema, è situata a 0x13434 (04:7434)
Probabilmente è necessario fare un repoint nello spazio libero se hai aggiunto strumenti di evoluzione (o anche nuovi elementi di guarigione).

Purtroppo non conosco esattamente l' indirizzo del pointer dato che personalmente me l'ero segnato una volta e poi a modifica finita ho smarrito il foglietto con su scritto quell' indirizzo... imbarazzante dirlo ma ad ogni modo se ripesco quell' indirizzo lo aggiungo.
Comunque per fortuna c'è solo quel pointer lì che si trova un po' di bytes prima dell' indirizzo 0x1342A (04:742A).

Codice:
db MOON_STONE
    db ANTIDOTE
    db BURN_HEAL
    db ICE_HEAL
    db AWAKENING
    db PARLYZ_HEAL
    db FULL_RESTORE
    db MAX_POTION
    db HYPER_POTION
    db SUPER_POTION
    db POTION
    db FIRE_STONE
    db THUNDER_STONE
    db WATER_STONE
    db HP_UP
    db PROTEIN
    db IRON
    db CARBOS
    db CALCIUM
    db RARE_CANDY
    db LEAF_STONE
    db FULL_HEAL
    db REVIVE
    db MAX_REVIVE
    db FRESH_WATER
    db SODA_POP
    db LEMONADE
    db X_ATTACK
    db X_DEFEND
    db X_SPEED
    db X_SPECIAL
    db PP_UP
    db ETHER
    db MAX_ETHER
    db ELIXER
    db MAX_ELIXER
    db $ff

E c'è un altra tabella (Opzionale) se alla fine si aggiungono nuovi strumenti base il cui uso è pensato per l'esterno:
Questi sono strumenti che chiudono la voce di menu quando viene utilizzato.

Codice:
UsableItems_CloseMenu: ; 13459 (4:7459)
    db ESCAPE_ROPE
    db ITEMFINDER
    db POKE_FLUTE
    db OLD_ROD
    db GOOD_ROD
    db SUPER_ROD
    db $ff

Se stai cercando di costruire la tua hack di Red\Blue o creare lo strumento ideale per gli hacker pigri, questo thread è un MUST per voi.

--------------------------
CREDITS:

*Solo io (80C), il tutorial originale inglese è stato scritto interamente da me.
Altro piccolo credito va al gruppo Pret per il documento del Disassembly di Red\Blue a cui faccio referenza nella mia guida.

(Questo messaggio è stato modificato l'ultima volta il: 20-07-2022 07:37 PM da 80C.)
12-06-2014 07:33 PM
Sito Web Cerca Cita
80C
['e…™t…™ s…™:]
******
Assente

Messaggi: 1,973
Registrato: 12-06-2014
Reputazione: 34
Mi Piace Ricevuti: 1577
PH Points: 3,666.00
Messaggio: #2
RE: Item Hacking Tutorial - Strumenti
Uppo per la nuova generazione di Hackers GB che utilizzano il Disassembly:

Il file della Repository da modificare è engine\items\items.asm.
Nella stessa Directory sono presenti altri file .asm che possono gestire altre funzioni adoperate da altri oggetti ( tms.asm, tmhm.asm, tm_prices.asm, itemfinder.asm)
Sebbene le modalit√† di applicazione di questo Tutorial siano oggi obsolete (il Tutorial lo scrissi nel 2013...) le istruzioni di questo Tutorial sono tutt'ora valide e sono facilmente applicabili anche alla Disassembly e, con l'ausilio dell'ASM, √® pi√Ļ che facile aggiungere nuovi utilizzi per oggetti.
Potete avere un esempio di ciò qui.

Per comodità e riferimento, posto qui un facsimile dell'originale tratto dalla Repository di Pokémon Red/Blue affinché vi possa essere una consulta completa delle funzionalità degli oggetti mentre si mette in pratica gli insegnamenti di questo (antico) tutorial:
Codice:
UseItem_: ; d5c7 (3:55c7)
    ld a,1
    ld [wcd6a],a
    ld a,[wcf91]    ;contains item_ID
    cp a,HM_01
    jp nc,ItemUseTMHM
    ld hl,ItemUsePtrTable
    dec a
    add a
    ld c,a
    ld b,0
    add hl,bc
    ld a,[hli]
    ld h,[hl]
    ld l,a
    jp [hl]

ItemUsePtrTable: ; d5e1 (3:55e1)
    dw ItemUseBall       ; MASTER_BALL
    dw ItemUseBall       ; ULTRA_BALL
    dw ItemUseBall       ; GREAT_BALL
    dw ItemUseBall       ; POKE_BALL
    dw ItemUseTownMap    ; TOWN_MAP
    dw ItemUseBicycle    ; BICYCLE
    dw ItemUseSurfboard  ; out-of-battle Surf effect
    dw ItemUseBall       ; SAFARI_BALL
    dw ItemUsePokedex    ; POKEDEX
    dw ItemUseEvoStone   ; MOON_STONE
    dw ItemUseMedicine   ; ANTIDOTE
    dw ItemUseMedicine   ; BURN_HEAL
    dw ItemUseMedicine   ; ICE_HEAL
    dw ItemUseMedicine   ; AWAKENING
    dw ItemUseMedicine   ; PARLYZ_HEAL
    dw ItemUseMedicine   ; FULL_RESTORE
    dw ItemUseMedicine   ; MAX_POTION
    dw ItemUseMedicine   ; HYPER_POTION
    dw ItemUseMedicine   ; SUPER_POTION
    dw ItemUseMedicine   ; POTION
    dw ItemUseBait       ; BOULDERBADGE
    dw ItemUseRock       ; CASCADEBADGE
    dw UnusableItem      ; THUNDERBADGE
    dw UnusableItem      ; RAINBOWBADGE
    dw UnusableItem      ; SOULBADGE
    dw UnusableItem      ; MARSHBADGE
    dw UnusableItem      ; VOLCANOBADGE
    dw UnusableItem      ; EARTHBADGE
    dw ItemUseEscapeRope ; ESCAPE_ROPE
    dw ItemUseRepel      ; REPEL
    dw UnusableItem      ; OLD_AMBER
    dw ItemUseEvoStone   ; FIRE_STONE
    dw ItemUseEvoStone   ; THUNDER_STONE
    dw ItemUseEvoStone   ; WATER_STONE
    dw ItemUseVitamin    ; HP_UP
    dw ItemUseVitamin    ; PROTEIN
    dw ItemUseVitamin    ; IRON
    dw ItemUseVitamin    ; CARBOS
    dw ItemUseVitamin    ; CALCIUM
    dw ItemUseVitamin    ; RARE_CANDY
    dw UnusableItem      ; DOME_FOSSIL
    dw UnusableItem      ; HELIX_FOSSIL
    dw UnusableItem      ; SECRET_KEY
    dw UnusableItem
    dw UnusableItem      ; BIKE_VOUCHER
    dw ItemUseXAccuracy  ; X_ACCURACY
    dw ItemUseEvoStone   ; LEAF_STONE
    dw ItemUseCardKey    ; CARD_KEY
    dw UnusableItem      ; NUGGET
    dw UnusableItem      ; ??? PP_UP
    dw ItemUsePokedoll   ; POKE_DOLL
    dw ItemUseMedicine   ; FULL_HEAL
    dw ItemUseMedicine   ; REVIVE
    dw ItemUseMedicine   ; MAX_REVIVE
    dw ItemUseGuardSpec  ; GUARD_SPEC_
    dw ItemUseSuperRepel ; SUPER_REPL
    dw ItemUseMaxRepel   ; MAX_REPEL
    dw ItemUseDireHit    ; DIRE_HIT
    dw UnusableItem      ; COIN
    dw ItemUseMedicine   ; FRESH_WATER
    dw ItemUseMedicine   ; SODA_POP
    dw ItemUseMedicine   ; LEMONADE
    dw UnusableItem      ; S_S__TICKET
    dw UnusableItem      ; GOLD_TEETH
    dw ItemUseXStat      ; X_ATTACK
    dw ItemUseXStat      ; X_DEFEND
    dw ItemUseXStat      ; X_SPEED
    dw ItemUseXStat      ; X_SPECIAL
    dw ItemUseCoinCase   ; COIN_CASE
    dw ItemUseOaksParcel ; OAKS_PARCEL
    dw ItemUseItemfinder ; ITEMFINDER
    dw UnusableItem      ; SILPH_SCOPE
    dw ItemUsePokeflute  ; POKE_FLUTE
    dw UnusableItem      ; LIFT_KEY
    dw UnusableItem      ; EXP__ALL
    dw OldRodCode        ; OLD_ROD
    dw GoodRodCode       ; GOOD_ROD
    dw SuperRodCode      ; SUPER_ROD
    dw ItemUsePPUp       ; PP_UP (real one)
    dw ItemUsePPRestore  ; ETHER
    dw ItemUsePPRestore  ; MAX_ETHER
    dw ItemUsePPRestore  ; ELIXER
    dw ItemUsePPRestore  ; MAX_ELIXER

ItemUseBall: ; d687 (3:5687)
    ld a,[W_ISINBATTLE]
    and a
    jp z,ItemUseNotTime ; not in battle
    dec a
    jp nz,ThrowBallAtTrainerMon
    ld a,[W_BATTLETYPE]
    dec a
    jr z,.UseBall
    ld a,[wPartyCount]    ;is Party full?
    cp a,PARTY_LENGTH
    jr nz,.UseBall
    ld a,[W_NUMINBOX]    ;is Box full?
    cp a,MONS_PER_BOX
    jp z,BoxFullCannotThrowBall
.UseBall    ;$56a7
;ok, you can use a ball
    xor a
    ld [wd11c],a
    ld a,[W_BATTLETYPE]
    cp a,2        ;SafariBattle
    jr nz,.skipSafariZoneCode
.safariZone
    ; remove a Safari Ball from inventory
    ld hl,W_NUMSAFARIBALLS
    dec [hl]
.skipSafariZoneCode    ;$56b6
    call GoPAL_SET_CF1C
    ld a,$43
    ld [wd11e],a
    call LoadScreenTilesFromBuffer1    ;restore screenBuffer from Backup
    ld hl,ItemUseText00
    call PrintText
    callab IsGhostBattle
    ld b,$10
    jp z,.next12
    ld a,[W_BATTLETYPE]
    dec a
    jr nz,.notOldManBattle
.oldManBattle
    ld hl,W_GRASSRATE
    ld de,wPlayerName
    ld bc,11
    call CopyData ; save the player's name in the Wild Monster data (part of the Cinnabar Island Missingno glitch)
    jp .BallSuccess    ;$578b
.notOldManBattle    ;$56e9
    ld a,[W_CURMAP]
    cp a,POKEMONTOWER_6
    jr nz,.loop
    ld a,[wEnemyMonSpecies2]
    cp a,MAROWAK
    ld b,$10
    jp z,.next12
; if not fighting ghost Marowak, loop until a random number in the current
; pokeball's allowed range is found
.loop    ;$56fa
    call Random
    ld b,a
    ld hl,wcf91
    ld a,[hl]
    cp a,MASTER_BALL
    jp z,.BallSuccess    ;$578b
    cp a,POKE_BALL
    jr z,.checkForAilments
    ld a,200
    cp b
    jr c,.loop    ;get only numbers <= 200 for Great Ball
    ld a,[hl]
    cp a,GREAT_BALL
    jr z,.checkForAilments
    ld a,150    ;get only numbers <= 150 for Ultra Ball
    cp b
    jr c,.loop
.checkForAilments    ;$571a
; pokemon can be caught more easily with any (primary) status ailment
; Frozen/Asleep pokemon are relatively even easier to catch
; for Frozen/Asleep pokemon, any random number from 0-24 ensures a catch.
; for the others, a random number from 0-11 ensures a catch.
    ld a,[wEnemyMonStatus]    ;status ailments
    and a
    jr z,.noAilments
    and a, 1 << FRZ | SLP    ;is frozen and/or asleep?
    ld c,12
    jr z,.notFrozenOrAsleep
    ld c,25
.notFrozenOrAsleep    ;$5728
    ld a,b
    sub c
    jp c,.BallSuccess    ;$578b
    ld b,a
.noAilments    ;$572e
    push bc        ;save RANDOM number
    xor a
    ld [H_MULTIPLICAND],a
    ld hl,wEnemyMonMaxHP
    ld a,[hli]
    ld [H_MULTIPLICAND + 1],a
    ld a,[hl]
    ld [H_MULTIPLICAND + 2],a
    ld a,255
    ld [H_MULTIPLIER],a
    call Multiply    ; MaxHP * 255
    ld a,[wcf91]
    cp a,GREAT_BALL
    ld a,12        ;any other BallFactor
    jr nz,.next7
    ld a,8
.next7    ;$574d
    ld [H_DIVISOR],a
    ld b,4        ; number of bytes in dividend
    call Divide
    ld hl,wEnemyMonHP
    ld a,[hli]
    ld b,a
    ld a,[hl]

; explanation: we have a 16-bit value equal to [b << 8 | a].
; This number is divided by 4. The result is 8 bit (reg. a).
; Always bigger than zero.
    srl b
    rr a
    srl b
    rr a ; a = current HP / 4
    and a
    jr nz,.next8
    inc a
.next8    ;$5766
    ld [H_DIVISOR],a
    ld b,4
    call Divide    ; ((MaxHP * 255) / BallFactor) / (CurHP / 4)
    ld a,[H_QUOTIENT + 2]
    and a
    jr z,.next9
    ld a,255
    ld [H_QUOTIENT + 3],a
.next9    ;$5776
    pop bc
    ld a,[wEnemyMonCatchRate]    ;enemy: Catch Rate
    cp b
    jr c,.next10
    ld a,[H_QUOTIENT + 2]
    and a
    jr nz,.BallSuccess ; if ((MaxHP * 255) / BallFactor) / (CurHP / 4) > 0x255, automatic success
    call Random
    ld b,a
    ld a,[H_QUOTIENT + 3]
    cp b
    jr c,.next10
.BallSuccess    ;$578b
    jr .BallSuccess2
.next10    ;$578d
    ld a,[H_QUOTIENT + 3]
    ld [wd11e],a
    xor a
    ld [H_MULTIPLICAND],a
    ld [H_MULTIPLICAND + 1],a
    ld a,[wEnemyMonCatchRate]    ;enemy: Catch Rate
    ld [H_MULTIPLICAND + 2],a
    ld a,100
    ld [H_MULTIPLIER],a
    call Multiply    ; CatchRate * 100
    ld a,[wcf91]
    ld b,255
    cp a,POKE_BALL
    jr z,.next11
    ld b,200
    cp a,GREAT_BALL
    jr z,.next11
    ld b,150
    cp a,ULTRA_BALL
    jr z,.next11
.next11    ;$57b8
    ld a,b
    ld [H_DIVISOR],a
    ld b,4
    call Divide
    ld a,[H_QUOTIENT + 2]
    and a
    ld b,$63
    jr nz,.next12
    ld a,[wd11e]
    ld [H_MULTIPLIER],a
    call Multiply
    ld a,255
    ld [H_DIVISOR],a
    ld b,4
    call Divide
    ld a,[wEnemyMonStatus]    ;status ailments
    and a
    jr z,.next13
    and a, 1 << FRZ | SLP
    ld b,5
    jr z,.next14
    ld b,10
.next14    ;$57e6
    ld a,[H_QUOTIENT + 3]
    add b
    ld [H_QUOTIENT + 3],a
.next13    ;$57eb
    ld a,[H_QUOTIENT + 3]
    cp a,10
    ld b,$20
    jr c,.next12
    cp a,30
    ld b,$61
    jr c,.next12
    cp a,70
    ld b,$62
    jr c,.next12
    ld b,$63
.next12    ;$5801
    ld a,b
    ld [wd11e],a
.BallSuccess2    ;$5805
    ld c,20
    call DelayFrames
    ld a,TOSS_ANIM
    ld [W_ANIMATIONID],a
    xor a
    ld [$fff3],a
    ld [wAnimationType],a
    ld [wDamageMultipliers],a
    ld a,[wWhichPokemon]
    push af
    ld a,[wcf91]
    push af
    predef MoveAnimation
    pop af
    ld [wcf91],a
    pop af
    ld [wWhichPokemon],a
    ld a,[wd11e]
    cp a,$10
    ld hl,ItemUseBallText00
    jp z,.printText0
    cp a,$20
    ld hl,ItemUseBallText01
    jp z,.printText0
    cp a,$61
    ld hl,ItemUseBallText02
    jp z,.printText0
    cp a,$62
    ld hl,ItemUseBallText03
    jp z,.printText0
    cp a,$63
    ld hl,ItemUseBallText04
    jp z,.printText0
    ld hl,wEnemyMonHP    ;current HP
    ld a,[hli]
    push af
    ld a,[hli]
    push af        ;backup currentHP...
    inc hl
    ld a,[hl]
    push af        ;...and status ailments
    push hl
    ld hl,W_ENEMYBATTSTATUS3
    bit Transformed,[hl]
    jr z,.next15
    ld a,$4c
    ld [wEnemyMonSpecies2],a
    jr .next16
.next15    ;$5871
    set Transformed,[hl]
    ld hl,wcceb
    ld a,[wEnemyMonDVs]
    ld [hli],a
    ld a,[wEnemyMonDVs + 1]
    ld [hl],a
.next16    ;$587e
    ld a,[wcf91]
    push af
    ld a,[wEnemyMonSpecies2]
    ld [wcf91],a
    ld a,[wEnemyMonLevel]
    ld [W_CURENEMYLVL],a
    callab LoadEnemyMonData
    pop af
    ld [wcf91],a
    pop hl
    pop af
    ld [hld],a
    dec hl
    pop af
    ld [hld],a
    pop af
    ld [hl],a
    ld a,[wEnemyMonSpecies]    ;enemy
    ld [wd11c],a
    ld [wcf91],a
    ld [wd11e],a
    ld a,[W_BATTLETYPE]
    dec a
    jr z,.printText1
    ld hl,ItemUseBallText05
    call PrintText
    predef IndexToPokedex
    ld a,[wd11e]
    dec a
    ld c,a
    ld b,2
    ld hl,wPokedexOwned    ;Dex_own_flags (pokemon)
    predef FlagActionPredef
    ld a,c
    push af
    ld a,[wd11e]
    dec a
    ld c,a
    ld b,1
    predef FlagActionPredef
    pop af
    and a
    jr nz,.checkParty
    ld hl,ItemUseBallText06
    call PrintText
    call ClearSprites
    ld a,[wEnemyMonSpecies]    ;caught mon_ID
    ld [wd11e],a
    predef ShowPokedexData
.checkParty    ;$58f4
    ld a,[wPartyCount]
    cp a,PARTY_LENGTH        ;is party full?
    jr z,.sendToBox
    xor a
    ld [wcc49],a
    call ClearSprites
    call AddPartyMon    ;add mon to Party
    jr .End
.sendToBox    ;$5907
    call ClearSprites
    call SendNewMonToBox
    ld hl,ItemUseBallText07
    ld a,[wd7f1]
    bit 0,a        ;already met Bill?
    jr nz,.sendToBox2
    ld hl,ItemUseBallText08
.sendToBox2    ;$591a
    call PrintText
    jr .End
.printText1    ;$591f
    ld hl,ItemUseBallText05
.printText0    ;$5922
    call PrintText
    call ClearSprites
.End    ;$5928
    ld a,[W_BATTLETYPE]
    and a
    ret nz
    ld hl,wNumBagItems
    inc a
    ld [wcf96],a
    jp RemoveItemFromInventory    ;remove ITEM (XXX)
ItemUseBallText00: ; d937 (3:5937)
;"It dodged the thrown ball!"
;"This pokemon can't be caught"
    TX_FAR _ItemUseBallText00
    db "@"
ItemUseBallText01: ; d93c (3:593c)
;"You missed the pokemon!"
    TX_FAR _ItemUseBallText01
    db "@"
ItemUseBallText02: ; d941 (3:5941)
;"Darn! The pokemon broke free!"
    TX_FAR _ItemUseBallText02
    db "@"
ItemUseBallText03: ; d946 (3:5946)
;"Aww! It appeared to be caught!"
    TX_FAR _ItemUseBallText03
    db "@"
ItemUseBallText04: ; d94b (3:594b)
;"Shoot! It was so close too!"
    TX_FAR _ItemUseBallText04
    db "@"
ItemUseBallText05: ; d950 (3:5950)
;"All right! {MonName} was caught!"
;play sound
    TX_FAR _ItemUseBallText05
    db $12,$06
    db "@"
ItemUseBallText07: ; d957 (3:5957)
;"X was transferred to Bill's PC"
    TX_FAR _ItemUseBallText07
    db "@"
ItemUseBallText08: ; d95c (3:595c)
;"X was transferred to someone's PC"
    TX_FAR _ItemUseBallText08
    db "@"

ItemUseBallText06: ; d961 (3:5961)
;"New DEX data will be added..."
;play sound
    TX_FAR _ItemUseBallText06
    db $13,$06
    db "@"

ItemUseTownMap: ; d968 (3:5968)
    ld a,[W_ISINBATTLE]
    and a
    jp nz,ItemUseNotTime
    ld b, BANK(DisplayTownMap)
    ld hl, DisplayTownMap
    jp Bankswitch ; display Town Map

ItemUseBicycle: ; d977 (3:5977)
    ld a,[W_ISINBATTLE]
    and a
    jp nz,ItemUseNotTime
    ld a,[wWalkBikeSurfState]
    ld [wWalkBikeSurfStateCopy],a
    cp a,2 ; is the player surfing?
    jp z,ItemUseNotTime
    dec a ; is player already bicycling?
    jr nz,.tryToGetOnBike
.getOffBike
    call ItemUseReloadOverworldData
    xor a
    ld [wWalkBikeSurfState],a ; change player state to walking
    call PlayDefaultMusic ; play walking music
    ld hl,GotOffBicycleText
    jr .printText
.tryToGetOnBike
    call IsBikeRidingAllowed
    jp nc,NoCyclingAllowedHere
    call ItemUseReloadOverworldData
    xor a ; no keys pressed
    ld [hJoyHeld],a ; current joypad state
    inc a
    ld [wWalkBikeSurfState],a ; change player state to bicycling
    ld hl,GotOnBicycleText
    call PlayDefaultMusic ; play bike riding music
.printText
    jp PrintText

; used for Surf out-of-battle effect
ItemUseSurfboard: ; d9b4 (3:59b4)
    ld a,[wWalkBikeSurfState]
    ld [wWalkBikeSurfStateCopy],a
    cp a,2 ; is the player already surfing?
    jr z,.tryToStopSurfing
.tryToSurf
    call IsNextTileShoreOrWater
    jp c,SurfingAttemptFailed
    ld hl,TilePairCollisionsWater
    call CheckForTilePairCollisions
    jp c,SurfingAttemptFailed
.surf
    call .makePlayerMoveForward
    ld hl,wd730
    set 7,[hl]
    ld a,2
    ld [wWalkBikeSurfState],a ; change player state to surfing
    call PlayDefaultMusic ; play surfing music
    ld hl,SurfingGotOnText
    jp PrintText
.tryToStopSurfing
    xor a
    ld [$ff8c],a
    ld d,16 ; talking range in pixels (normal range)
    call IsSpriteInFrontOfPlayer2
    res 7,[hl]
    ld a,[$ff8c]
    and a ; is there a sprite in the way?
    jr nz,.cannotStopSurfing
    ld hl,TilePairCollisionsWater
    call CheckForTilePairCollisions
    jr c,.cannotStopSurfing
    ld hl,W_TILESETCOLLISIONPTR ; pointer to list of passable tiles
    ld a,[hli]
    ld h,[hl]
    ld l,a ; hl now points to passable tiles
    ld a,[wTileInFrontOfPlayer] ; tile in front of the player
    ld b,a
.passableTileLoop
    ld a,[hli]
    cp b
    jr z,.stopSurfing
    cp a,$ff
    jr nz,.passableTileLoop
.cannotStopSurfing
    ld hl,SurfingNoPlaceToGetOffText
    jp PrintText
.stopSurfing
    call .makePlayerMoveForward
    ld hl,wd730
    set 7,[hl]
    xor a
    ld [wWalkBikeSurfState],a ; change player state to walking
    dec a
    ld [wJoyIgnore],a
    call PlayDefaultMusic ; play walking music
    jp LoadWalkingPlayerSpriteGraphics
; uses a simulated button press to make the player move forward
.makePlayerMoveForward
    ld a,[wd52a] ; direction the player is going
    bit 3,a
    ld b,D_UP
    jr nz,.storeSimulatedButtonPress
    bit 2,a
    ld b,D_DOWN
    jr nz,.storeSimulatedButtonPress
    bit 1,a
    ld b,D_LEFT
    jr nz,.storeSimulatedButtonPress
    ld b,D_RIGHT
.storeSimulatedButtonPress
    ld a,b
    ld [wSimulatedJoypadStatesEnd],a
    xor a
    ld [wWastedByteCD39],a
    inc a
    ld [wSimulatedJoypadStatesIndex],a
    ret

SurfingGotOnText: ; da4c (3:5a4c)
    TX_FAR _SurfingGotOnText
    db "@"

SurfingNoPlaceToGetOffText: ; da51 (3:5a51)
    TX_FAR _SurfingNoPlaceToGetOffText
    db "@"

ItemUsePokedex: ; da56 (3:5a56)
    predef_jump ShowPokedexMenu

ItemUseEvoStone: ; da5b (3:5a5b)
    ld a,[W_ISINBATTLE]
    and a
    jp nz,ItemUseNotTime
    ld a,[wWhichPokemon]
    push af
    ld a,[wcf91]
    ld [wd156],a
    push af
    ld a,$05 ; evolution stone party menu
    ld [wd07d],a
    ld a,$ff
    ld [wUpdateSpritesEnabled],a
    call DisplayPartyMenu
    pop bc
    jr c,.canceledItemUse
    ld a,b
    ld [wcf91],a
    ld a,$01
    ld [wccd4],a
    ld a,(SFX_02_3e - SFX_Headers_02) / 3
    call PlaySoundWaitForCurrent ; play sound
    call WaitForSoundToFinish ; wait for sound to end
    callab TryEvolvingMon ; try to evolve pokemon
    ld a,[wd121]
    and a
    jr z,.noEffect
    pop af
    ld [wWhichPokemon],a
    ld hl,wNumBagItems
    ld a,1 ; remove 1 stone
    ld [wcf96],a
    jp RemoveItemFromInventory
.noEffect
    call ItemUseNoEffect
.canceledItemUse
    xor a
    ld [wcd6a],a
    pop af
    ret

ItemUseVitamin: ; dab4 (3:5ab4)
    ld a,[W_ISINBATTLE]
    and a
    jp nz,ItemUseNotTime

ItemUseMedicine: ; dabb (3:5abb)
    ld a,[wPartyCount]
    and a
    jp z,.emptyParty
    ld a,[wWhichPokemon]
    push af
    ld a,[wcf91]
    push af
    ld a,$01
    ld [wd07d],a ; item use party menu
    ld a,$ff
    ld [wUpdateSpritesEnabled],a
    ld a,[wd152]
    and a ; using Softboiled?
    jr z,.notUsingSoftboiled
; if using softboiled
    call GoBackToPartyMenu
    jr .getPartyMonDataAddress
.emptyParty
    ld hl,.emptyPartyText
    xor a
    ld [wcd6a],a ; item use failed
    jp PrintText
.emptyPartyText
    text "You don't have"
    line "any #MON!"
    prompt
.notUsingSoftboiled
    call DisplayPartyMenu
.getPartyMonDataAddress
    jp c,.canceledItemUse
    ld hl,wPartyMons
    ld bc,wPartyMon2 - wPartyMon1
    ld a,[wWhichPokemon]
    call AddNTimes
    ld a,[wWhichPokemon]
    ld [wcf06],a
    ld d,a
    ld a,[wcf91]
    ld e,a
    ld [wd0b5],a
    pop af
    ld [wcf91],a
    pop af
    ld [wWhichPokemon],a
    ld a,[wd152]
    and a ; using Softboiled?
    jr z,.checkItemType
; if using softboiled
    ld a,[wWhichPokemon]
    cp d ; is the pokemon trying to use softboiled on itself?
    jr z,ItemUseMedicine ; if so, force another choice
.checkItemType
    ld a,[wcf91]
    cp a,REVIVE
    jr nc,.healHP ; if it's a Revive or Max Revive
    cp a,FULL_HEAL
    jr z,.cureStatusAilment ; if it's a Full Heal
    cp a,HP_UP
    jp nc,.useVitamin ; if it's a vitamin or Rare Candy
    cp a,FULL_RESTORE
    jr nc,.healHP ; if it's a Full Restore or one of the potions
; fall through if it's one of the status-specifc healing items
.cureStatusAilment
    ld bc,4
    add hl,bc ; hl now points to status
    ld a,[wcf91]
    ld bc,$f008
    cp a,ANTIDOTE
    jr z,.checkMonStatus
    ld bc,$f110
    cp a,BURN_HEAL
    jr z,.checkMonStatus
    ld bc,$f220
    cp a,ICE_HEAL
    jr z,.checkMonStatus
    ld bc,$f307
    cp a,AWAKENING
    jr z,.checkMonStatus
    ld bc,$f440
    cp a,PARLYZ_HEAL
    jr z,.checkMonStatus
    ld bc,$f6ff ; Full Heal
.checkMonStatus
    ld a,[hl] ; pokemon's status
    and c ; does the pokemon have a status ailment the item can cure?
    jp z,.healingItemNoEffect
; if the pokemon has a status the item can heal
    xor a
    ld [hl],a ; remove the status ailment in the party data
    ld a,b
    ld [wd07d],a ; the message to display for the item used
    ld a,[wPlayerMonNumber]
    cp d ; is pokemon the item was used on active in battle?
    jp nz,.doneHealing
; if it is active in battle
    xor a
    ld [wBattleMonStatus],a ; remove the status ailment in the in-battle pokemon data
    push hl
    ld hl,W_PLAYERBATTSTATUS3
    res BadlyPoisoned,[hl] ; heal Toxic status
    pop hl
    ld bc,30
    add hl,bc ; hl now points to party stats
    ld de,wBattleMonMaxHP
    ld bc,10
    call CopyData ; copy party stats to in-battle stat data
    predef DoubleOrHalveSelectedStats
    jp .doneHealing
.healHP
    inc hl ; hl = address of current HP
    ld a,[hli]
    ld b,a
    ld [wHPBarOldHP+1],a
    ld a,[hl]
    ld c,a
    ld [wHPBarOldHP],a ; current HP stored at wHPBarOldHP (2 bytes, big-endian)
    or b
    jr nz,.notFainted
.fainted
    ld a,[wcf91]
    cp a,REVIVE
    jr z,.updateInBattleFaintedData
    cp a,MAX_REVIVE
    jr z,.updateInBattleFaintedData
    jp .healingItemNoEffect
.updateInBattleFaintedData
    ld a,[W_ISINBATTLE]
    and a
    jr z,.compareCurrentHPToMaxHP
    push hl
    push de
    push bc
    ld a,[wcf06]
    ld c,a
    ld hl,wPartyFoughtCurrentEnemyFlags
    ld b,$02
    predef FlagActionPredef
    ld a,c
    and a
    jr z,.next
    ld a,[wcf06]
    ld c,a
    ld hl,wPartyGainExpFlags
    ld b,$01
    predef FlagActionPredef
.next
    pop bc
    pop de
    pop hl
    jr .compareCurrentHPToMaxHP
.notFainted
    ld a,[wcf91]
    cp a,REVIVE
    jp z,.healingItemNoEffect
    cp a,MAX_REVIVE
    jp z,.healingItemNoEffect
.compareCurrentHPToMaxHP
    push hl
    push bc
    ld bc,32
    add hl,bc ; hl now points to max HP
    pop bc
    ld a,[hli]
    cp b
    jr nz,.skipComparingLSB ; no need to compare the LSB's if the MSB's don't match
    ld a,[hl]
    cp c
.skipComparingLSB
    pop hl
    jr nz,.notFullHP
.fullHP ; if the pokemon's current HP equals its max HP
    ld a,[wcf91]
    cp a,FULL_RESTORE
    jp nz,.healingItemNoEffect
    inc hl
    inc hl
    ld a,[hld] ; status ailment
    and a ; does the pokemon have a status ailment?
    jp z,.healingItemNoEffect
    ld a,FULL_HEAL
    ld [wcf91],a
    dec hl
    dec hl
    dec hl
    jp .cureStatusAilment
.notFullHP ; if the pokemon's current HP doesn't equal its max HP
    xor a
    ld [wLowHealthAlarm],a ;disable low health alarm
    ld [wc02a],a
    push hl
    push de
    ld bc,32
    add hl,bc ; hl now points to max HP
    ld a,[hli]
    ld [wHPBarMaxHP+1],a
    ld a,[hl]
    ld [wHPBarMaxHP],a ; max HP stored at wHPBarMaxHP (2 bytes, big-endian)
    ld a,[wd152]
    and a ; using Softboiled?
    jp z,.notUsingSoftboiled2
; if using softboiled
    ld hl,wHPBarMaxHP
    ld a,[hli]
    push af
    ld a,[hli]
    push af
    ld a,[hli]
    push af
    ld a,[hl]
    push af
    ld hl,wPartyMon1MaxHP
    ld a,[wWhichPokemon]
    ld bc,wPartyMon2 - wPartyMon1
    call AddNTimes
    ld a,[hli]
    ld [wHPBarMaxHP + 1],a
    ld [H_DIVIDEND],a
    ld a,[hl]
    ld [wHPBarMaxHP],a
    ld [H_DIVIDEND + 1],a
    ld a,5
    ld [H_DIVISOR],a
    ld b,2 ; number of bytes
    call Divide ; get 1/5 of max HP of pokemon that used Softboiled
    ld bc,wPartyMon1HP - wPartyMon1MaxHP
    add hl,bc ; hl now points to LSB of current HP of pokemon that used Softboiled
; subtract 1/5 of max HP from current HP of pokemon that used Softboiled
    ld a,[H_QUOTIENT + 3]
    push af
    ld b,a
    ld a,[hl]
    ld [wHPBarOldHP],a
    sub b
    ld [hld],a
    ld [wHPBarNewHP],a
    ld a,[H_QUOTIENT + 2]
    ld b,a
    ld a,[hl]
    ld [wHPBarOldHP+1],a
    sbc b
    ld [hl],a
    ld [wHPBarNewHP+1],a
    hlCoord 4, 1
    ld a,[wWhichPokemon]
    ld bc,2 * 20
    call AddNTimes ; calculate coordinates of HP bar of pokemon that used Softboiled
    ld a,(SFX_02_3d - SFX_Headers_02) / 3
    call PlaySoundWaitForCurrent ; play sound
    ld a,[hFlags_0xFFF6]
    set 0,a
    ld [hFlags_0xFFF6],a
    ld a,$02
    ld [wHPBarType],a
    predef UpdateHPBar2 ; animate HP bar decrease of pokemon that used Softboiled
    ld a,[hFlags_0xFFF6]
    res 0,a
    ld [hFlags_0xFFF6],a
    pop af
    ld b,a ; store heal amount (1/5 of max HP)
    ld hl,wHPBarOldHP + 1
    pop af
    ld [hld],a
    pop af
    ld [hld],a
    pop af
    ld [hld],a
    pop af
    ld [hl],a
    jr .addHealAmount
.notUsingSoftboiled2
    ld a,[wcf91]
    cp a,SODA_POP
    ld b,60 ; Soda Pop heal amount
    jr z,.addHealAmount
    ld b,80 ; Lemonade heal amount
    jr nc,.addHealAmount
    cp a,FRESH_WATER
    ld b,50 ; Fresh Water heal amount
    jr z,.addHealAmount
    cp a,SUPER_POTION
    ld b,200 ; Hyper Potion heal amount
    jr c,.addHealAmount
    ld b,50 ; Super Potion heal amount
    jr z,.addHealAmount
    ld b,20 ; Potion heal amount
.addHealAmount
    pop de
    pop hl
    ld a,[hl]
    add b
    ld [hld],a
    ld [wHPBarNewHP],a
    ld a,[hl]
    ld [wHPBarNewHP+1],a
    jr nc,.noCarry
    inc [hl]
    ld a,[hl]
    ld [wHPBarNewHP + 1],a
.noCarry
    push de
    inc hl
    ld d,h
    ld e,l ; de now points to current HP
    ld hl,33
    add hl,de ; hl now points to max HP
    ld a,[wcf91]
    cp a,REVIVE
    jr z,.setCurrentHPToHalfMaxHP
    ld a,[hld]
    ld b,a
    ld a,[de]
    sub b
    dec de
    ld b,[hl]
    ld a,[de]
    sbc b
    jr nc,.setCurrentHPToMaxHp ; if current HP exceeds max HP after healing
    ld a,[wcf91]
    cp a,HYPER_POTION
    jr c,.setCurrentHPToMaxHp ; if using a Full Restore or Max Potion
    cp a,MAX_REVIVE
    jr z,.setCurrentHPToMaxHp ; if using a Max Revive
    jr .updateInBattleData
.setCurrentHPToHalfMaxHP
    dec hl
    dec de
    ld a,[hli]
    srl a
    ld [de],a
    ld [wHPBarNewHP+1],a
    ld a,[hl]
    rr a
    inc de
    ld [de],a
    ld [wHPBarNewHP],a
    dec de
    jr .doneHealingPartyHP
.setCurrentHPToMaxHp
    ld a,[hli]
    ld [de],a
    ld [wHPBarNewHP+1],a
    inc de
    ld a,[hl]
    ld [de],a
    ld [wHPBarNewHP],a
    dec de
.doneHealingPartyHP ; done updating the pokemon's current HP in the party data structure
    ld a,[wcf91]
    cp a,FULL_RESTORE
    jr nz,.updateInBattleData
    ld bc,-31
    add hl,bc
    xor a
    ld [hl],a ; remove the status ailment in the party data
.updateInBattleData
    ld h,d
    ld l,e
    pop de
    ld a,[wPlayerMonNumber]
    cp d ; is pokemon the item was used on active in battle?
    jr nz,.calculateHPBarCoords
; copy party HP to in-battle HP
    ld a,[hli]
    ld [wBattleMonHP],a
    ld a,[hld]
    ld [wBattleMonHP + 1],a
    ld a,[wcf91]
    cp a,FULL_RESTORE
    jr nz,.calculateHPBarCoords
    xor a
    ld [wBattleMonStatus],a ; remove the status ailment in the in-battle pokemon data
.calculateHPBarCoords
    ld hl,wOAMBuffer + $90
    ld bc,2 * 20
    inc d
.calculateHPBarCoordsLoop
    add hl,bc
    dec d
    jr nz,.calculateHPBarCoordsLoop
    jr .doneHealing
.healingItemNoEffect
    call ItemUseNoEffect
    jp .done
.doneHealing
    ld a,[wd152]
    and a ; using Softboiled?
    jr nz,.skipRemovingItem ; no item to remove if using Softboiled
    push hl
    call RemoveUsedItem
    pop hl
.skipRemovingItem
    ld a,[wcf91]
    cp a,FULL_RESTORE
    jr c,.playStatusAilmentCuringSound
    cp a,FULL_HEAL
    jr z,.playStatusAilmentCuringSound
    ld a,(SFX_02_3d - SFX_Headers_02) / 3 ; HP healing sound
    call PlaySoundWaitForCurrent ; play sound
    ld a,[hFlags_0xFFF6]
    set 0,a
    ld [hFlags_0xFFF6],a
    ld a,$02
    ld [wHPBarType],a
    predef UpdateHPBar2 ; animate the HP bar lengthening
    ld a,[hFlags_0xFFF6]
    res 0,a
    ld [hFlags_0xFFF6],a
    ld a,$f7 ; revived message
    ld [wd07d],a
    ld a,[wcf91]
    cp a,REVIVE
    jr z,.showHealingItemMessage
    cp a,MAX_REVIVE
    jr z,.showHealingItemMessage
    ld a,$f5 ; standard HP healed message
    ld [wd07d],a
    jr .showHealingItemMessage
.playStatusAilmentCuringSound
    ld a,(SFX_02_3e - SFX_Headers_02) / 3 ; status ailment curing sound
    call PlaySoundWaitForCurrent
.showHealingItemMessage
    xor a
    ld [H_AUTOBGTRANSFERENABLED],a
    call ClearScreen
    dec a
    ld [wUpdateSpritesEnabled],a
    call RedrawPartyMenu ; redraws the party menu and displays the message
    ld a,1
    ld [H_AUTOBGTRANSFERENABLED],a
    ld c,50
    call DelayFrames
    call WaitForTextScrollButtonPress
    jr .done
.canceledItemUse
    xor a
    ld [wcd6a],a ; item use failed
    pop af
    pop af
.done
    ld a,[wd152]
    and a ; using Softboiled?
    ret nz ; if so, return
    call GBPalWhiteOut
    call z,GoPAL_SET_CF1C
    ld a,[W_ISINBATTLE]
    and a
    ret nz
    jp ReloadMapData
.useVitamin
    push hl
    ld a,[hl]
    ld [wd0b5],a
    ld [wd11e],a
    ld bc,33
    add hl,bc ; hl now points to level
    ld a,[hl] ; a = level
    ld [W_CURENEMYLVL],a ; store level
    call GetMonHeader
    push de
    ld a,d
    ld hl,wPartyMonNicks
    call GetPartyMonName
    pop de
    pop hl
    ld a,[wcf91]
    cp a,RARE_CANDY
    jp z,.useRareCandy
    push hl
    sub a,HP_UP
    add a
    ld bc,17
    add hl,bc
    add l
    ld l,a
    jr nc,.noCarry2
    inc h
.noCarry2
    ld a,10
    ld b,a
    ld a,[hl] ; a = MSB of stat experience of the appropriate stat
    cp a,100 ; is there already at least 25600 (256 * 100) stat experience?
    jr nc,.vitaminNoEffect ; if so, vitamins can't add any more
    add b ; add 2560 (256 * 10) stat experience
    jr nc,.noCarry3 ; a carry should be impossible here, so this will always jump
    ld a,255
.noCarry3
    ld [hl],a
    pop hl
    call .recalculateStats
    ld hl,VitaminText
    ld a,[wcf91]
    sub a,HP_UP - 1
    ld c,a
.statNameLoop ; loop to get the address of the name of the stat the vitamin increases
    dec c
    jr z,.gotStatName
.statNameInnerLoop
    ld a,[hli]
    ld b,a
    ld a,$50
    cp b
    jr nz,.statNameInnerLoop
    jr .statNameLoop
.gotStatName
    ld de,wcf4b
    ld bc,10
    call CopyData ; copy the stat's name to wcf4b
    ld a,(SFX_02_3e - SFX_Headers_02) / 3
    call PlaySound ; play sound
    ld hl,VitaminStatRoseText
    call PrintText
    jp RemoveUsedItem
.vitaminNoEffect
    pop hl
    ld hl,VitaminNoEffectText
    call PrintText
    jp GBPalWhiteOut
.recalculateStats
    ld bc,34
    add hl,bc
    ld d,h
    ld e,l ; de now points to stats
    ld bc,-18
    add hl,bc ; hl now points to byte 3 of experience
    ld b,1
    jp CalcStats ; recalculate stats
.useRareCandy
    push hl
    ld bc,33
    add hl,bc ; hl now points to level
    ld a,[hl] ; a = level
    cp a, MAX_LEVEL
    jr z,.vitaminNoEffect ; can't raise level above 100
    inc a
    ld [hl],a ; store incremented level
    ld [W_CURENEMYLVL],a
    push hl
    push de
    ld d,a
    callab CalcExperience ; calculate experience for next level and store it at $ff96
    pop de
    pop hl
    ld bc,-19
    add hl,bc ; hl now points to experience
; update experience to minimum for new level
    ld a,[$ff96]
    ld [hli],a
    ld a,[$ff97]
    ld [hli],a
    ld a,[$ff98]
    ld [hl],a
    pop hl
    ld a,[wWhichPokemon]
    push af
    ld a,[wcf91]
    push af
    push de
    push hl
    ld bc,34
    add hl,bc ; hl now points to MSB of max HP
    ld a,[hli]
    ld b,a
    ld c,[hl]
    pop hl
    push bc
    push hl
    call .recalculateStats
    pop hl
    ld bc,35 ; hl now points to LSB of max HP
    add hl,bc
    pop bc
    ld a,[hld]
    sub c
    ld c,a
    ld a,[hl]
    sbc b
    ld b,a ; bc = the amount of max HP gained from leveling up
; add the amount gained to the current HP
    ld de,-32
    add hl,de ; hl now points to MSB of current HP
    ld a,[hl]
    add c
    ld [hld],a
    ld a,[hl]
    adc b
    ld [hl],a
    ld a,$f8 ; level up message
    ld [wd07d],a
    call RedrawPartyMenu
    pop de
    ld a,d
    ld [wWhichPokemon],a
    ld a,e
    ld [wd11e],a
    xor a
    ld [wcc49],a ; load from player's party
    call LoadMonData
    ld d,$01
    callab PrintStatsBox ; display new stats text box
    call WaitForTextScrollButtonPress ; wait for button press
    xor a
    ld [wcc49],a
    predef LearnMoveFromLevelUp ; learn level up move, if any
    xor a
    ld [wccd4],a
    callab TryEvolvingMon ; evolve pokemon, if appropriate
    ld a,$01
    ld [wUpdateSpritesEnabled],a
    pop af
    ld [wcf91],a
    pop af
    ld [wWhichPokemon],a
    jp RemoveUsedItem

VitaminStatRoseText: ; df24 (3:5f24)
    TX_FAR _VitaminStatRoseText
    db "@"

VitaminNoEffectText: ; df29 (3:5f29)
    TX_FAR _VitaminNoEffectText
    db "@"

VitaminText: ; df2e (3:5f2e)
    db "HEALTH@"
    db "ATTACK@"
    db "DEFENSE@"
    db "SPEED@"
    db "SPECIAL@"

ItemUseBait: ; df52 (3:5f52)
    ld hl,ThrewBaitText
    call PrintText
    ld hl,wEnemyMonCatchRate ; catch rate
    srl [hl] ; halve catch rate
    ld a,BAIT_ANIM
    ld hl,wSafariBaitFactor ; bait factor
    ld de,wSafariEscapeFactor ; escape factor
    jr BaitRockCommon

ItemUseRock: ; df67 (3:5f67)
    ld hl,ThrewRockText
    call PrintText
    ld hl,wEnemyMonCatchRate ; catch rate
    ld a,[hl]
    add a ; double catch rate
    jr nc,.noCarry
    ld a,$ff
.noCarry
    ld [hl],a
    ld a,ROCK_ANIM
    ld hl,wSafariEscapeFactor ; escape factor
    ld de,wSafariBaitFactor ; bait factor

BaitRockCommon: ; df7f (3:5f7f)
    ld [W_ANIMATIONID],a
    xor a
    ld [wcc5b],a
    ld [H_WHOSETURN],a
    ld [de],a ; zero escape factor (for bait), zero bait factor (for rock)
.randomLoop ; loop until a random number less than 5 is generated
    call Random
    and a,7
    cp a,5
    jr nc,.randomLoop
    inc a ; increment the random number, giving a range from 1 to 5 inclusive
    ld b,a
    ld a,[hl]
    add b ; increase bait factor (for bait), increase escape factor (for rock)
    jr nc,.noCarry
    ld a,$ff
.noCarry
    ld [hl],a
    predef MoveAnimation ; do animation
    ld c,70
    jp DelayFrames

ThrewBaitText: ; dfa5 (3:5fa5)
    TX_FAR _ThrewBaitText
    db "@"

ThrewRockText: ; dfaa (3:5faa)
    TX_FAR _ThrewRockText
    db "@"

; also used for Dig out-of-battle effect
ItemUseEscapeRope: ; dfaf (3:5faf)
    ld a,[W_ISINBATTLE]
    and a
    jr nz,.notUsable
    ld a,[W_CURMAP]
    cp a,AGATHAS_ROOM
    jr z,.notUsable
    ld a,[W_CURMAPTILESET]
    ld b,a
    ld hl,EscapeRopeTilesets
.loop
    ld a,[hli]
    cp a,$ff
    jr z,.notUsable
    cp b
    jr nz,.loop
    ld hl,wd732
    set 3,[hl]
    set 6,[hl]
    ld hl,wd72e
    res 4,[hl]
    ld hl,wd790
    res 7,[hl] ; unset Safari Zone bit
    xor a
    ld [W_NUMSAFARIBALLS],a
    ld [W_SAFARIZONEENTRANCECURSCRIPT],a
    inc a
    ld [wEscapedFromBattle],a
    ld [wcd6a],a ; item used
    ld a,[wd152]
    and a ; using Dig?
    ret nz ; if so, return
    call ItemUseReloadOverworldData
    ld c,30
    call DelayFrames
    jp RemoveUsedItem
.notUsable
    jp ItemUseNotTime

EscapeRopeTilesets: ; dffd (3:5ffd)
    db FOREST, CEMETERY, CAVERN, FACILITY, INTERIOR
    db $ff ; terminator

ItemUseRepel: ; e003 (3:6003)
    ld b,100

ItemUseRepelCommon: ; e005 (3:6005)
    ld a,[W_ISINBATTLE]
    and a
    jp nz,ItemUseNotTime
    ld a,b
    ld [wRepelRemainingSteps],a
    jp PrintItemUseTextAndRemoveItem

; handles X Accuracy item
ItemUseXAccuracy: ; e013 (3:6013)
    ld a,[W_ISINBATTLE]
    and a
    jp z,ItemUseNotTime
    ld hl,W_PLAYERBATTSTATUS2
    set UsingXAccuracy,[hl] ; X Accuracy bit
    jp PrintItemUseTextAndRemoveItem

; This function is bugged and never works. It always jumps to ItemUseNotTime.
; The Card Key is handled in a different way.
ItemUseCardKey: ; e022 (3:6022)
    xor a
    ld [wd71f],a
    call GetTileAndCoordsInFrontOfPlayer
    ld a,[GetTileAndCoordsInFrontOfPlayer] ; $4586
    cp a,$18
    jr nz,.next0
    ld hl,CardKeyTable1
    jr .next1
.next0
    cp a,$24
    jr nz,.next2
    ld hl,CardKeyTable2
    jr .next1
.next2
    cp a,$5e
    jp nz,ItemUseNotTime
    ld hl,CardKeyTable3
.next1
    ld a,[W_CURMAP]
    ld b,a
.loop
    ld a,[hli]
    cp a,$ff
    jp z,ItemUseNotTime
    cp b
    jr nz,.nextEntry1
    ld a,[hli]
    cp d
    jr nz,.nextEntry2
    ld a,[hli]
    cp e
    jr nz,.nextEntry3
    ld a,[hl]
    ld [wd71f],a
    jr .done
.nextEntry1
    inc hl
.nextEntry2
    inc hl
.nextEntry3
    inc hl
    jr .loop
.done
    ld hl,ItemUseText00
    call PrintText
    ld hl,wd728
    set 7,[hl]
    ret

; These tables are probably supposed to be door locations in Silph Co.,
; but they are unused.
; The reason there are 3 tables is unknown.

; Format:
; 00: Map ID
; 01: Y
; 02: X
; 03: ID?

CardKeyTable1: ; e072 (3:6072)
    db  SILPH_CO_2F,$04,$04,$00
    db  SILPH_CO_2F,$04,$05,$01
    db  SILPH_CO_4F,$0C,$04,$02
    db  SILPH_CO_4F,$0C,$05,$03
    db  SILPH_CO_7F,$06,$0A,$04
    db  SILPH_CO_7F,$06,$0B,$05
    db  SILPH_CO_9F,$04,$12,$06
    db  SILPH_CO_9F,$04,$13,$07
    db SILPH_CO_10F,$08,$0A,$08
    db SILPH_CO_10F,$08,$0B,$09
    db $ff

CardKeyTable2: ; e09b (3:609b)
    db SILPH_CO_3F,$08,$09,$0A
    db SILPH_CO_3F,$09,$09,$0B
    db SILPH_CO_5F,$04,$07,$0C
    db SILPH_CO_5F,$05,$07,$0D
    db SILPH_CO_6F,$0C,$05,$0E
    db SILPH_CO_6F,$0D,$05,$0F
    db SILPH_CO_8F,$08,$07,$10
    db SILPH_CO_8F,$09,$07,$11
    db SILPH_CO_9F,$08,$03,$12
    db SILPH_CO_9F,$09,$03,$13
    db $ff

CardKeyTable3: ; e0c4 (3:60c4)
    db SILPH_CO_11F,$08,$09,$14
    db SILPH_CO_11F,$09,$09,$15
    db $ff

ItemUsePokedoll: ; e0cd (3:60cd)
    ld a,[W_ISINBATTLE]
    dec a
    jp nz,ItemUseNotTime
    ld a,$01
    ld [wEscapedFromBattle],a
    jp PrintItemUseTextAndRemoveItem

ItemUseGuardSpec: ; e0dc (3:60dc)
    ld a,[W_ISINBATTLE]
    and a
    jp z,ItemUseNotTime
    ld hl,W_PLAYERBATTSTATUS2
    set ProtectedByMist,[hl] ; Mist bit
    jp PrintItemUseTextAndRemoveItem

ItemUseSuperRepel: ; e0eb (3:60eb)
    ld b,200
    jp ItemUseRepelCommon

ItemUseMaxRepel: ; e0f0 (3:60f0)
    ld b,250
    jp ItemUseRepelCommon

ItemUseDireHit: ; e0f5 (3:60f5)
    ld a,[W_ISINBATTLE]
    and a
    jp z,ItemUseNotTime
    ld hl,W_PLAYERBATTSTATUS2
    set GettingPumped,[hl] ; Focus Energy bit
    jp PrintItemUseTextAndRemoveItem

ItemUseXStat: ; e104 (3:6104)
    ld a,[W_ISINBATTLE]
    and a
    jr nz,.inBattle
    call ItemUseNotTime
    ld a,2
    ld [wcd6a],a ; item not used
    ret
.inBattle
    ld hl,W_PLAYERMOVENUM
    ld a,[hli]
    push af ; save [W_PLAYERMOVENUM]
    ld a,[hl]
    push af ; save [W_PLAYERMOVEEFFECT]
    push hl
    ld a,[wcf91]
    sub a,X_ATTACK - ATTACK_UP1_EFFECT
    ld [hl],a ; store player move effect
    call PrintItemUseTextAndRemoveItem
    ld a,XSTATITEM_ANIM ; X stat item animation ID
    ld [W_PLAYERMOVENUM],a
    call LoadScreenTilesFromBuffer1 ; restore saved screen
    call Delay3
    xor a
    ld [H_WHOSETURN],a ; set turn to player's turn
    callba StatModifierUpEffect ; do stat increase move
    pop hl
    pop af
    ld [hld],a ; restore [W_PLAYERMOVEEFFECT]
    pop af
    ld [hl],a ; restore [W_PLAYERMOVENUM]
    ret

ItemUsePokeflute: ; e140 (3:6140)
    ld a,[W_ISINBATTLE]
    and a
    jr nz,.inBattle
; if not in battle
    call ItemUseReloadOverworldData
    ld a,[W_CURMAP]
    cp a,ROUTE_12
    jr nz,.notRoute12
    ld a,[wd7d8]
    bit 7,a ; has the player beaten Route 12 Snorlax yet?
    jr nz,.noSnorlaxToWakeUp
; if the player hasn't beaten Route 12 Snorlax
    ld hl,Route12SnorlaxFluteCoords
    call ArePlayerCoordsInArray
    jr nc,.noSnorlaxToWakeUp
    ld hl,PlayedFluteHadEffectText
    call PrintText
    ld hl,wd7d8
    set 6,[hl] ; trigger Snorlax fight (handled by map script)
    ret
.notRoute12
    cp a,ROUTE_16
    jr nz,.noSnorlaxToWakeUp
    ld a,[wd7e0]
    bit 1,a ; has the player beaten Route 16 Snorlax yet?
    jr nz,.noSnorlaxToWakeUp
; if the player hasn't beaten Route 16 Snorlax
    ld hl,Route16SnorlaxFluteCoords
    call ArePlayerCoordsInArray
    jr nc,.noSnorlaxToWakeUp
    ld hl,PlayedFluteHadEffectText
    call PrintText
    ld hl,wd7e0
    set 0,[hl] ; trigger Snorlax fight (handled by map script)
    ret
.noSnorlaxToWakeUp
    ld hl,PlayedFluteNoEffectText
    jp PrintText
.inBattle
    xor a
    ld [wWhichTrade],a ; initialize variable that indicates if any pokemon were woken up to zero
    ld b,~SLP & $FF
    ld hl,wPartyMon1Status
    call WakeUpEntireParty
    ld a,[W_ISINBATTLE]
    dec a ; is it a trainer battle?
    jr z,.skipWakingUpEnemyParty
; if it's a trainer battle
    ld hl,wEnemyMon1Status
    call WakeUpEntireParty
.skipWakingUpEnemyParty
    ld hl,wBattleMonStatus
    ld a,[hl]
    and b ; remove Sleep status
    ld [hl],a
    ld hl,wEnemyMonStatus
    ld a,[hl]
    and b ; remove Sleep status
    ld [hl],a
    call LoadScreenTilesFromBuffer2 ; restore saved screen
    ld a,[wWhichTrade]
    and a ; were any pokemon asleep before playing the flute?
    ld hl,PlayedFluteNoEffectText
    jp z,PrintText ; if no pokemon were asleep
; if some pokemon were asleep
    ld hl,PlayedFluteHadEffectText
    call PrintText
    ld a,[wLowHealthAlarm]
    and a,$80
    jr nz,.skipMusic
    call WaitForSoundToFinish ; wait for sound to end
    callba Music_PokeFluteInBattle ; play in-battle pokeflute music
.musicWaitLoop ; wait for music to finish playing
    ld a,[wc02c]
    and a ; music off?
    jr nz,.musicWaitLoop
.skipMusic
    ld hl,FluteWokeUpText
    jp PrintText

; wakes up all party pokemon
; INPUT:
; hl must point to status of first pokemon in party (player's or enemy's)
; b must equal ~SLP
; [wWhichTrade] should be initialized to 0
; OUTPUT:
; [wWhichTrade]: set to 1 if any pokemon were asleep
WakeUpEntireParty: ; e1e5 (3:61e5)
    ld de,44
    ld c,6
.loop
    ld a,[hl]
    push af
    and a,SLP ; is pokemon asleep?
    jr z,.notAsleep
    ld a,1
    ld [wWhichTrade],a ; indicate that a pokemon had to be woken up
.notAsleep
    pop af
    and b ; remove Sleep status
    ld [hl],a
    add hl,de
    dec c
    jr nz,.loop
    ret

; Format:
; 00: Y
; 01: X
Route12SnorlaxFluteCoords: ; e1fd (3:61fd)
    db 62,9  ; one space West of Snorlax
    db 61,10 ; one space North of Snorlax
    db 63,10 ; one space South of Snorlax
    db 62,11 ; one space East of Snorlax
    db $ff ; terminator

; Format:
; 00: Y
; 01: X
Route16SnorlaxFluteCoords: ; e206 (3:6206)
    db 10,27 ; one space East of Snorlax
    db 10,25 ; one space West of Snorlax
    db $ff ; terminator

PlayedFluteNoEffectText: ; e20b (3:620b)
    TX_FAR _PlayedFluteNoEffectText
    db "@"

FluteWokeUpText: ; e210 (3:6210)
    TX_FAR _FluteWokeUpText
    db "@"

PlayedFluteHadEffectText: ; e215 (3:6215)
    TX_FAR _PlayedFluteHadEffectText
    db $06
    db $08
    ld a,[W_ISINBATTLE]
    and a
    jr nz,.done
; play out-of-battle pokeflute music
    ld a,$ff
    call PlaySound ; turn off music
    ld a, (SFX_02_5e - SFX_Headers_02) / 3
    ld c, BANK(SFX_02_5e)
    call PlayMusic ; play music
.musicWaitLoop ; wait for music to finish playing
    ld a,[wc028]
    cp a,$b8
    jr z,.musicWaitLoop
    call PlayDefaultMusic ; start playing normal music again
.done
    jp TextScriptEnd ; end text

ItemUseCoinCase: ; e23a (3:623a)
    ld a,[W_ISINBATTLE]
    and a
    jp nz,ItemUseNotTime
    ld hl,CoinCaseNumCoinsText
    jp PrintText

CoinCaseNumCoinsText: ; e247 (3:6247)
    TX_FAR _CoinCaseNumCoinsText
    db "@"

OldRodCode: ; e24c (3:624c)
    call FishingInit
    jp c, ItemUseNotTime
    ld bc, (5 << 8) | MAGIKARP
    ld a, $1 ; set bite
    jr RodResponse ; 0xe257 $34

GoodRodCode: ; e259 (3:6259)
    call FishingInit
    jp c,ItemUseNotTime
.RandomLoop
    call Random
    srl a
    jr c, .SetBite
    and %11
    cp 2
    jr nc, .RandomLoop
    ; choose which monster appears
    ld hl,GoodRodMons
    add a,a
    ld c,a
    ld b,0
    add hl,bc
    ld b,[hl]
    inc hl
    ld c,[hl]
    and a
.SetBite
    ld a,0
    rla
    xor 1
    jr RodResponse

INCLUDE "data/good_rod.asm"

SuperRodCode: ; e283 (3:6283)
    call FishingInit
    jp c, ItemUseNotTime
    call ReadSuperRodData ; 0xe8ea
    ld a, e
RodResponse: ; e28d (3:628d)
    ld [wWhichTrade], a

    dec a ; is there a bite?
    jr nz, .next
    ; if yes, store level and species data
    ld a, 1
    ld [W_MOVEMISSED], a
    ld a, b ; level
    ld [W_CURENEMYLVL], a
    ld a, c ; species
    ld [W_CUROPPONENT], a

.next
    ld hl, wWalkBikeSurfState
    ld a, [hl] ; store the value in a
    push af
    push hl
    ld [hl], 0
    callba Func_707b6
    pop hl
    pop af
    ld [hl], a
    ret

; checks if fishing is possible and if so, runs initialization code common to all rods
; unsets carry if fishing is possible, sets carry if not
FishingInit: ; e2b4 (3:62b4)
    ld a,[W_ISINBATTLE]
    and a
    jr z,.notInBattle
    scf ; can't fish during battle
    ret
.notInBattle
    call IsNextTileShoreOrWater
    ret c
    ld a,[wWalkBikeSurfState]
    cp a,2 ; Surfing?
    jr z,.surfing
    call ItemUseReloadOverworldData
    ld hl,ItemUseText00
    call PrintText
    ld a,(SFX_02_3e - SFX_Headers_02) / 3
    call PlaySound ; play sound
    ld c,80
    call DelayFrames
    and a
    ret
.surfing
    scf ; can't fish when surfing
    ret

ItemUseOaksParcel: ; e2de (3:62de)
    jp ItemUseNotYoursToUse

ItemUseItemfinder: ; e2e1 (3:62e1)
    ld a,[W_ISINBATTLE]
    and a
    jp nz,ItemUseNotTime
    call ItemUseReloadOverworldData
    callba HiddenItemNear ; check for hidden items
    ld hl,ItemfinderFoundNothingText
    jr nc,.printText ; if no hidden items
    ld c,4
.loop
    ld a,(SFX_02_4a - SFX_Headers_02) / 3
    call PlaySoundWaitForCurrent ; play sound
    ld a,(SFX_02_5a - SFX_Headers_02) / 3
    call PlaySoundWaitForCurrent ; play sound
    dec c
    jr nz,.loop
    ld hl,ItemfinderFoundItemText
.printText
    jp PrintText

ItemfinderFoundItemText: ; e30d (3:630d)
    TX_FAR _ItemfinderFoundItemText
    db "@"

ItemfinderFoundNothingText: ; e312 (3:6312)
    TX_FAR _ItemfinderFoundNothingText
    db "@"

ItemUsePPUp: ; e317 (3:6317)
    ld a,[W_ISINBATTLE]
    and a
    jp nz,ItemUseNotTime

ItemUsePPRestore: ; e31e (3:631e)
    ld a,[wWhichPokemon]
    push af
    ld a,[wcf91]
    ld [wWhichTrade],a
.chooseMon
    xor a
    ld [wUpdateSpritesEnabled],a
    ld a,$01 ; item use party menu
    ld [wd07d],a
    call DisplayPartyMenu
    jr nc,.chooseMove
    jp .itemNotUsed
.chooseMove
    ld a,[wWhichTrade]
    cp a,ELIXER
    jp nc,.useElixir ; if Elixir or Max Elixir
    ld a,$02
    ld [wMoveMenuType],a
    ld hl,RaisePPWhichTechniqueText
    ld a,[wWhichTrade]
    cp a,ETHER ; is it a PP Up?
    jr c,.printWhichTechniqueMessage ; if so, print the raise PP message
    ld hl,RestorePPWhichTechniqueText ; otherwise, print the restore PP message
.printWhichTechniqueMessage
    call PrintText
    xor a
    ld [wPlayerMoveListIndex],a
    callab MoveSelectionMenu ; move selection menu
    ld a,0
    ld [wPlayerMoveListIndex],a
    jr nz,.chooseMon
    ld hl,wPartyMon1Moves
    ld bc,44
    call GetSelectedMoveOffset
    push hl
    ld a,[hl]
    ld [wd11e],a
    call GetMoveName
    call CopyStringToCF4B ; copy name to wcf4b
    pop hl
    ld a,[wWhichTrade]
    cp a,ETHER
    jr nc,.useEther ; if Ether or Max Ether
.usePPUp
    ld bc,21
    add hl,bc
    ld a,[hl] ; move PP
    cp a,3 << 6 ; have 3 PP Ups already been used?
    jr c,.PPNotMaxedOut
    ld hl,PPMaxedOutText
    call PrintText
    jr .chooseMove
.PPNotMaxedOut
    ld a,[hl]
    add a,1 << 6 ; increase PP Up count by 1
    ld [hl],a
    ld a,1 ; 1 PP Up used
    ld [wd11e],a
    call RestoreBonusPP ; add the bonus PP to current PP
    ld hl,PPIncreasedText
    call PrintText
.done
    pop af
    ld [wWhichPokemon],a
    call GBPalWhiteOut
    call GoPAL_SET_CF1C
    jp RemoveUsedItem
.afterRestoringPP ; after using a (Max) Ether/Elixir
    ld a,[wWhichPokemon]
    ld b,a
    ld a,[wPlayerMonNumber]
    cp b ; is the pokemon whose PP was restored active in battle?
    jr nz,.skipUpdatingInBattleData
    ld hl,wPartyMon1PP
    ld bc,44
    call AddNTimes
    ld de,wBattleMonPP
    ld bc,4
    call CopyData ; copy party data to in-battle data
.skipUpdatingInBattleData
    ld a,(SFX_02_3e - SFX_Headers_02) / 3
    call PlaySound
    ld hl,PPRestoredText
    call PrintText
    jr .done
.useEther
    call .restorePP
    jr nz,.afterRestoringPP
    jp .noEffect
; unsets zero flag if PP was restored, sets zero flag if not
; however, this is bugged for Max Ethers and Max Elixirs (see below)
.restorePP
    xor a
    ld [wcc49],a ; party pokemon
    call GetMaxPP
    ld hl,wPartyMon1Moves
    ld bc,44
    call GetSelectedMoveOffset
    ld bc,21
    add hl,bc ; hl now points to move's PP
    ld a,[wd11e]
    ld b,a ; b = max PP
    ld a,[wWhichTrade]
    cp a,MAX_ETHER
    jr z,.fullyRestorePP
    ld a,[hl] ; move PP
    and a,%00111111 ; lower 6 bit bits store current PP
    cp b ; does current PP equal max PP?
    ret z ; if so, return
    add a,10 ; increase current PP by 10
; b holds the max PP amount and b will hold the new PP amount.
; So, if the new amount meets or exceeds the max amount,
; cap the amount to the max amount by leaving b unchanged.
; Otherwise, store the new amount in b.
    cp b ; does the new amount meet or exceed the maximum?
    jr nc,.storeNewAmount
    ld b,a
.storeNewAmount
    ld a,[hl] ; move PP
    and a,%11000000 ; PP Up counter bits
    add b
    ld [hl],a
    ret
.fullyRestorePP
    ld a,[hl] ; move PP
; Note that this code has a bug. It doesn't mask out the upper two bits, which
; are used to count how many PP Ups have been used on the move. So, Max Ethers
; and Max Elixirs will not be detected as having no effect on a move with full
; PP if the move has had any PP Ups used on it.
    cp b ; does current PP equal max PP?
    ret z
    jr .storeNewAmount
.useElixir
; decrement the item ID so that ELIXER becomes ETHER and MAX_ELIXER becomes MAX_ETHER
    ld hl,wWhichTrade
    dec [hl]
    dec [hl]
    xor a
    ld hl,wCurrentMenuItem
    ld [hli],a
    ld [hl],a ; zero the counter for number of moves that had their PP restored
    ld b,4
; loop through each move and restore PP
.elixirLoop
    push bc
    ld hl,wPartyMon1Moves
    ld bc,44
    call GetSelectedMoveOffset
    ld a,[hl]
    and a ; does the current slot have a move?
    jr z,.nextMove
    call .restorePP
    jr z,.nextMove
; if some PP was restored
    ld hl,wTileBehindCursor ; counter for number of moves that had their PP restored
    inc [hl]
.nextMove
    ld hl,wCurrentMenuItem
    inc [hl]
    pop bc
    dec b
    jr nz,.elixirLoop
    ld a,[wTileBehindCursor]
    and a ; did any moves have their PP restored?
    jp nz,.afterRestoringPP
.noEffect
    call ItemUseNoEffect
.itemNotUsed
    call GBPalWhiteOut
    call GoPAL_SET_CF1C
    pop af
    xor a
    ld [wcd6a],a ; item use failed
    ret

RaisePPWhichTechniqueText: ; e45d (3:645d)
    TX_FAR _RaisePPWhichTechniqueText
    db "@"

RestorePPWhichTechniqueText: ; e462 (3:6462)
    TX_FAR _RestorePPWhichTechniqueText
    db "@"

PPMaxedOutText: ; e467 (3:6467)
    TX_FAR _PPMaxedOutText
    db "@"

PPIncreasedText: ; e46c (3:646c)
    TX_FAR _PPIncreasedText
    db "@"

PPRestoredText: ; e471 (3:6471)
    TX_FAR _PPRestoredText
    db "@"

; for items that can't be used from the Item menu
UnusableItem: ; e476 (3:6476)
    jp ItemUseNotTime

ItemUseTMHM: ; e479 (3:6479)
    ld a,[W_ISINBATTLE]
    and a
    jp nz,ItemUseNotTime
    ld a,[wcf91]
    sub a,TM_01
    push af
    jr nc,.skipAdding
    add a,55 ; if item is an HM, add 55
.skipAdding
    inc a
    ld [wd11e],a
    predef TMToMove ; get move ID from TM/HM ID
    ld a,[wd11e]
    ld [wMoveNum],a
    call GetMoveName
    call CopyStringToCF4B ; copy name to wcf4b
    pop af
    ld hl,BootedUpTMText
    jr nc,.printBootedUpMachineText
    ld hl,BootedUpHMText
.printBootedUpMachineText
    call PrintText
    ld hl,TeachMachineMoveText
    call PrintText
    hlCoord 14, 7
    ld bc,$080f
    ld a,TWO_OPTION_MENU
    ld [wTextBoxID],a
    call DisplayTextBoxID ; yes/no menu
    ld a,[wCurrentMenuItem]
    and a
    jr z,.useMachine
    ld a,2
    ld [wcd6a],a ; item not used
    ret
.useMachine
    ld a,[wWhichPokemon]
    push af
    ld a,[wcf91]
    push af
.chooseMon
    ld hl,wcf4b
    ld de,wd036
    ld bc,14
    call CopyData
    ld a,$ff
    ld [wUpdateSpritesEnabled],a
    ld a,$03 ; teach TM/HM party menu
    ld [wd07d],a
    call DisplayPartyMenu
    push af
    ld hl,wd036
    ld de,wcf4b
    ld bc,14
    call CopyData
    pop af
    jr nc,.checkIfAbleToLearnMove
; if the player canceled teaching the move
    pop af
    pop af
    call GBPalWhiteOutWithDelay3
    call ClearSprites
    call GoPAL_SET_CF1C
    jp LoadScreenTilesFromBuffer1 ; restore saved screen
.checkIfAbleToLearnMove
    predef CanLearnTM ; check if the pokemon can learn the move
    push bc
    ld a,[wWhichPokemon]
    ld hl,wPartyMonNicks
    call GetPartyMonName
    pop bc
    ld a,c
    and a ; can the pokemon learn the move?
    jr nz,.checkIfAlreadyLearnedMove
; if the pokemon can't learn the move
    ld a,(SFX_02_51 - SFX_Headers_02) / 3
    call PlaySoundWaitForCurrent ; play sound
    ld hl,MonCannotLearnMachineMoveText
    call PrintText
    jr .chooseMon
.checkIfAlreadyLearnedMove
    callab CheckIfMoveIsKnown ; check if the pokemon already knows the move
    jr c,.chooseMon
    predef LearnMove ; teach move
    pop af
    ld [wcf91],a
    pop af
    ld [wWhichPokemon],a
    ld a,b
    and a
    ret z
    ld a,[wcf91]
    call IsItemHM
    ret c
    jp RemoveUsedItem

BootedUpTMText: ; e54f (3:654f)
    TX_FAR _BootedUpTMText
    db "@"

BootedUpHMText: ; e554 (3:6554)
    TX_FAR _BootedUpHMText
    db "@"

TeachMachineMoveText: ; e559 (3:6559)
    TX_FAR _TeachMachineMoveText
    db "@"

MonCannotLearnMachineMoveText: ; e55e (3:655e)
    TX_FAR _MonCannotLearnMachineMoveText
    db "@"

PrintItemUseTextAndRemoveItem: ; e563 (3:6563)
    ld hl,ItemUseText00
    call PrintText
    ld a,(SFX_02_3e - SFX_Headers_02) / 3
    call PlaySound ; play sound
    call WaitForTextScrollButtonPress ; wait for button press

RemoveUsedItem: ; e571 (3:6571)
    ld hl,wNumBagItems
    ld a,1 ; one item
    ld [wcf96],a ; store quantity
    jp RemoveItemFromInventory

ItemUseNoEffect: ; e57c (3:657c)
    ld hl,ItemUseNoEffectText
    jr ItemUseFailed

ItemUseNotTime: ; e581 (3:6581)
    ld hl,ItemUseNotTimeText
    jr ItemUseFailed

ItemUseNotYoursToUse: ; e586 (3:6586)
    ld hl,ItemUseNotYoursToUseText
    jr ItemUseFailed

ThrowBallAtTrainerMon: ; e58b (3:658b)
    call GoPAL_SET_CF1C
    call LoadScreenTilesFromBuffer1 ; restore saved screen
    call Delay3
    ld a,TOSS_ANIM
    ld [W_ANIMATIONID],a
    predef MoveAnimation ; do animation
    ld hl,ThrowBallAtTrainerMonText1
    call PrintText
    ld hl,ThrowBallAtTrainerMonText2
    call PrintText
    jr RemoveUsedItem

NoCyclingAllowedHere: ; e5ac (3:65ac)
    ld hl,NoCyclingAllowedHereText
    jr ItemUseFailed

BoxFullCannotThrowBall: ; e5b1 (3:65b1)
    ld hl,BoxFullCannotThrowBallText
    jr ItemUseFailed

SurfingAttemptFailed: ; e5b6 (3:65b6)
    ld hl,NoSurfingHereText

ItemUseFailed: ; e5b9 (3:65b9)
    xor a
    ld [wcd6a],a ; item use failed
    jp PrintText

ItemUseNotTimeText: ; e5c0 (3:65c0)
    TX_FAR _ItemUseNotTimeText
    db "@"

ItemUseNotYoursToUseText: ; e5c5 (3:65c5)
    TX_FAR _ItemUseNotYoursToUseText
    db "@"

ItemUseNoEffectText: ; e5ca (3:65ca)
    TX_FAR _ItemUseNoEffectText
    db "@"

ThrowBallAtTrainerMonText1: ; e5cf (3:65cf)
    TX_FAR _ThrowBallAtTrainerMonText1
    db "@"

ThrowBallAtTrainerMonText2: ; e5d4 (3:65d4)
    TX_FAR _ThrowBallAtTrainerMonText2
    db "@"

NoCyclingAllowedHereText: ; e5d9 (3:65d9)
    TX_FAR _NoCyclingAllowedHereText
    db "@"

NoSurfingHereText: ; e5de (3:65de)
    TX_FAR _NoSurfingHereText
    db "@"

BoxFullCannotThrowBallText: ; e5e3 (3:65e3)
    TX_FAR _BoxFullCannotThrowBallText
    db "@"

ItemUseText00: ; e5e8 (3:65e8)
    TX_FAR _ItemUseText001
    db $05
    TX_FAR _ItemUseText002
    db "@"

GotOnBicycleText: ; e5f2 (3:65f2)
    TX_FAR _GotOnBicycleText1
    db $05
    TX_FAR _GotOnBicycleText2
    db "@"

GotOffBicycleText: ; e5fc (3:65fc)
    TX_FAR _GotOffBicycleText1
    db $05
    TX_FAR _GotOffBicycleText2
    db "@"

; restores bonus PP (from PP Ups) when healing at a pokemon center
; also, when a PP Up is used, it increases the current PP by one PP Up bonus
; INPUT:
; [wWhichPokemon] = index of pokemon in party
; [wd11e] = mode
; 0: Pokemon Center healing
; 1: using a PP Up
; [wCurrentMenuItem] = index of move (when using a PP Up)
RestoreBonusPP: ; e606 (3:6606)
    ld hl,wPartyMon1Moves
    ld bc,44
    ld a,[wWhichPokemon]
    call AddNTimes
    push hl
    ld de,wcd78 - 1
    predef LoadMovePPs ; loads the normal max PP of each of the pokemon's moves to wcd78
    pop hl
    ld c,21
    ld b,0
    add hl,bc ; hl now points to move 1 PP
    ld de,wcd78
    ld b,0 ; initialize move counter to zero
; loop through the pokemon's moves
.loop
    inc b
    ld a,b
    cp a,5 ; reached the end of the pokemon's moves?
    ret z ; if so, return
    ld a,[wd11e]
    dec a ; using a PP Up?
    jr nz,.skipMenuItemIDCheck
; if using a PP Up, check if this is the move it's being used on
    ld a,[wCurrentMenuItem]
    inc a
    cp b
    jr nz,.nextMove
.skipMenuItemIDCheck
    ld a,[hl]
    and a,%11000000 ; have any PP Ups been used?
    call nz,AddBonusPP ; if so, add bonus PP
.nextMove
    inc hl
    inc de
    jr .loop

; adds bonus PP from PP Ups to current PP
; 1/5 of normal max PP (capped at 7) is added for each PP Up
; INPUT:
; [de] = normal max PP
; [hl] = move PP
; [wd11e] = max number of times to add bonus
; set to 1 when using a PP Up, set to 255 otherwise
AddBonusPP: ; e642 (3:6642)
    push bc
    ld a,[de] ; normal max PP of move
    ld [H_DIVIDEND + 3],a
    xor a
    ld [H_DIVIDEND],a
    ld [H_DIVIDEND + 1],a
    ld [H_DIVIDEND + 2],a
    ld a,5
    ld [H_DIVISOR],a
    ld b,4
    call Divide
    ld a,[hl] ; move PP
    ld b,a
    swap a
    and a,%00001111
    srl a
    srl a
    ld c,a ; c = number of PP Ups used
.loop
    ld a,[H_QUOTIENT + 3]
    cp a,8 ; is the amount greater than or equal to 8?
    jr c,.addAmount
    ld a,7 ; cap the amount at 7
.addAmount
    add b
    ld b,a
    ld a,[wd11e]
    dec a
    jr z,.done
    dec c
    jr nz,.loop
.done
    ld [hl],b
    pop bc
    ret

; gets max PP of a pokemon's move (including PP from PP Ups)
; INPUT:
; [wWhichPokemon] = index of pokemon within party/box
; [wcc49] = pokemon source
; 00: player's party
; 01: enemy's party
; 02: current box
; 03: daycare
; 04: player's in-battle pokemon
; [wCurrentMenuItem] = move index
; OUTPUT:
; [wd11e] = max PP
GetMaxPP: ; e677 (3:6677)
    ld a,[wcc49]
    and a
    ld hl,wPartyMon1Moves
    ld bc,wPartyMon2 - wPartyMon1
    jr z,.sourceWithMultipleMon
    ld hl,wEnemyMon1Moves
    dec a
    jr z,.sourceWithMultipleMon
    ld hl,wBoxMon1Moves
    ld bc,wBoxMon2 - wBoxMon1
    dec a
    jr z,.sourceWithMultipleMon
    ld hl,wDayCareMonMoves
    dec a
    jr z,.sourceWithOneMon
    ld hl,wBattleMonMoves ; player's in-battle pokemon
.sourceWithOneMon
    call GetSelectedMoveOffset2
    jr .next
.sourceWithMultipleMon
    call GetSelectedMoveOffset
.next
    ld a,[hl]
    dec a
    push hl
    ld hl,Moves
    ld bc,6
    call AddNTimes
    ld de,wcd6d
    ld a,BANK(Moves)
    call FarCopyData
    ld de,wcd72
    ld a,[de]
    ld b,a ; b = normal max PP
    pop hl
    push bc
    ld bc,21 ; PP offset if not player's in-battle pokemon data
    ld a,[wcc49]
    cp a,4 ; player's in-battle pokemon?
    jr nz,.addPPOffset
    ld bc,17 ; PP offset if player's in-battle pokemon data
.addPPOffset
    add hl,bc
    ld a,[hl] ; a = current PP
    and a,%11000000 ; get PP Up count
    pop bc
    or b ; place normal max PP in 6 lower bits of a
    ld h,d
    ld l,e
    inc hl ; hl = wcd73
    ld [hl],a
    xor a
    ld [wd11e],a ; no limit on PP Up amount
    call AddBonusPP ; add bonus PP from PP Ups
    ld a,[hl]
    and a,%00111111 ; mask out the PP Up count
    ld [wd11e],a ; store max PP
    ret

GetSelectedMoveOffset: ; e6e3 (3:66e3)
    ld a,[wWhichPokemon]
    call AddNTimes

GetSelectedMoveOffset2: ; e6e9 (3:66e9)
    ld a,[wCurrentMenuItem]
    ld c,a
    ld b,0
    add hl,bc
    ret

; confirms the item toss and then tosses the item
; INPUT:
; hl = address of inventory (either wNumBagItems or wNumBoxItems)
; [wcf91] = item ID
; [wWhichPokemon] = index of item within inventory
; [wcf96] = quantity to toss
; OUTPUT:
; clears carry flag if the item is tossed, sets carry flag if not
TossItem_: ; e6f1 (3:66f1)
    push hl
    ld a,[wcf91]
    call IsItemHM
    pop hl
    jr c,.tooImportantToToss
    push hl
    call IsKeyItem_
    ld a,[wd124]
    pop hl
    and a
    jr nz,.tooImportantToToss
    push hl
    ld a,[wcf91]
    ld [wd11e],a
    call GetItemName
    call CopyStringToCF4B ; copy name to wcf4b
    ld hl,IsItOKToTossItemText
    call PrintText
    hlCoord 14, 7
    ld bc,$080f
    ld a,TWO_OPTION_MENU
    ld [wTextBoxID],a
    call DisplayTextBoxID ; yes/no menu
    ld a,[wd12e]
    cp a,2
    pop hl
    scf
    ret z
; if the player chose Yes
    push hl
    ld a,[wWhichPokemon]
    call RemoveItemFromInventory
    ld a,[wcf91]
    ld [wd11e],a
    call GetItemName
    call CopyStringToCF4B ; copy name to wcf4b
    ld hl,ThrewAwayItemText
    call PrintText
    pop hl
    and a
    ret
.tooImportantToToss
    push hl
    ld hl,TooImportantToTossText
    call PrintText
    pop hl
    scf
    ret

ThrewAwayItemText: ; e755 (3:6755)
    TX_FAR _ThrewAwayItemText
    db "@"

IsItOKToTossItemText: ; e75a (3:675a)
    TX_FAR _IsItOKToTossItemText
    db "@"

TooImportantToTossText: ; e75f (3:675f)
    TX_FAR _TooImportantToTossText
    db "@"

; checks if an item is a key item
; INPUT:
; [wcf91] = item ID
; OUTPUT:
; [wd124] = result
; 00: item is not key item
; 01: item is key item
IsKeyItem_: ; e764 (3:6764)
    ld a,$01
    ld [wd124],a
    ld a,[wcf91]
    cp a,HM_01 ; is the item an HM or TM?
    jr nc,.checkIfItemIsHM
; if the item is not an HM or TM
    push af
    ld hl,KeyItemBitfield
    ld de,wHPBarMaxHP
    ld bc,15 ; only 11 bytes are actually used
    call CopyData
    pop af
    dec a
    ld c,a
    ld hl,wHPBarMaxHP
    ld b,$02 ; test bit
    predef FlagActionPredef ; bitfield operation function
    ld a,c
    and a
    ret nz
.checkIfItemIsHM
    ld a,[wcf91]
    call IsItemHM
    ret c
    xor a
    ld [wd124],a
    ret

INCLUDE "data/key_items.asm"

SendNewMonToBox: ; e7a4 (3:67a4)
    ld de, W_NUMINBOX ; wda80
    ld a, [de]
    inc a
    ld [de], a
    ld a, [wcf91]
    ld [wd0b5], a
    ld c, a
.asm_e7b1
    inc de
    ld a, [de]
    ld b, a
    ld a, c
    ld c, b
    ld [de], a
    cp $ff
    jr nz, .asm_e7b1
    call GetMonHeader
    ld hl, wBoxMonOT
    ld bc, $b
    ld a, [W_NUMINBOX] ; wda80
    dec a
    jr z, .asm_e7ee
    dec a
    call AddNTimes
    push hl
    ld bc, $b
    add hl, bc
    ld d, h
    ld e, l
    pop hl
    ld a, [W_NUMINBOX] ; wda80
    dec a
    ld b, a
.asm_e7db
    push bc
    push hl
    ld bc, $b
    call CopyData
    pop hl
    ld d, h
    ld e, l
    ld bc, $fff5
    add hl, bc
    pop bc
    dec b
    jr nz, .asm_e7db
.asm_e7ee
    ld hl, wPlayerName ; wd158
    ld de, wBoxMonOT
    ld bc, $b
    call CopyData
    ld a, [W_NUMINBOX] ; wda80
    dec a
    jr z, .asm_e82a
    ld hl, wBoxMonNicks
    ld bc, $b
    dec a
    call AddNTimes
    push hl
    ld bc, $b
    add hl, bc
    ld d, h
    ld e, l
    pop hl
    ld a, [W_NUMINBOX] ; wda80
    dec a
    ld b, a
.asm_e817
    push bc
    push hl
    ld bc, $b
    call CopyData
    pop hl
    ld d, h
    ld e, l
    ld bc, $fff5
    add hl, bc
    pop bc
    dec b
    jr nz, .asm_e817
.asm_e82a
    ld hl, wBoxMonNicks
    ld a, $2
    ld [wd07d], a
    predef AskName
    ld a, [W_NUMINBOX] ; wda80
    dec a
    jr z, .asm_e867
    ld hl, wBoxMons
    ld bc, wBoxMon2 - wBoxMon1
    dec a
    call AddNTimes
    push hl
    ld bc, wBoxMon2 - wBoxMon1
    add hl, bc
    ld d, h
    ld e, l
    pop hl
    ld a, [W_NUMINBOX] ; wda80
    dec a
    ld b, a
.asm_e854
    push bc
    push hl
    ld bc, wBoxMon2 - wBoxMon1
    call CopyData
    pop hl
    ld d, h
    ld e, l
    ld bc, $ffdf
    add hl, bc
    pop bc
    dec b
    jr nz, .asm_e854
.asm_e867
    ld a, [wEnemyMonLevel] ; wEnemyMonLevel
    ld [wEnemyMonBoxLevel], a
    ld hl, wEnemyMon
    ld de, wBoxMon1
    ld bc, $c
    call CopyData
    ld hl, wPlayerID ; wPlayerID
    ld a, [hli]
    ld [de], a
    inc de
    ld a, [hl]
    ld [de], a
    inc de
    push de
    ld a, [W_CURENEMYLVL] ; W_CURENEMYLVL
    ld d, a
    callab CalcExperience
    pop de
    ld a, [H_NUMTOPRINT] ; $ff96 (aliases: H_MULTIPLICAND)
    ld [de], a
    inc de
    ld a, [$ff97]
    ld [de], a
    inc de
    ld a, [$ff98]
    ld [de], a
    inc de
    xor a
    ld b, $a
.asm_e89f
    ld [de], a
    inc de
    dec b
    jr nz, .asm_e89f
    ld hl, wEnemyMonDVs
    ld a, [hli]
    ld [de], a
    inc de
    ld a, [hli]
    ld [de], a
    ld hl, wEnemyMonPP ; wcffe
    ld b, $4
.asm_e8b1
    ld a, [hli]
    inc de
    ld [de], a
    dec b
    jr nz, .asm_e8b1
    ret

; checks if the tile in front of the player is a shore or water tile
; used for surfing and fishing
; unsets carry if it is, sets carry if not
IsNextTileShoreOrWater: ; e8b8 (3:68b8)
    ld a, [W_CURMAPTILESET]
    ld hl, WaterTilesets
    ld de,1
    call IsInArray
    jr nc, .notShoreOrWater
    ld a, [W_CURMAPTILESET]
    cp SHIP_PORT ; Vermilion Dock tileset
    ld a, [wTileInFrontOfPlayer] ; tile in front of player
    jr z, .skipShoreTiles ; if it's the Vermilion Dock tileset
    cp $48 ; eastern shore tile in Safari Zone
    jr z, .shoreOrWater
    cp $32 ; usual eastern shore tile
    jr z, .shoreOrWater
.skipShoreTiles
    cp $14 ; water tile
    jr z, .shoreOrWater
.notShoreOrWater
    scf
    ret
.shoreOrWater
    and a
    ret

; tilesets with water
WaterTilesets: ; e8e0 (3:68e0)
    db OVERWORLD, FOREST, DOJO, GYM, SHIP, SHIP_PORT, CAVERN, FACILITY, PLATEAU
    db $ff ; terminator

ReadSuperRodData: ; e8ea (3:68ea)
; return e = 2 if no fish on this map
; return e = 1 if a bite, bc = level,species
; return e = 0 if no bite
    ld a, [W_CURMAP]
    ld de, 3 ; each fishing group is three bytes wide
    ld hl, SuperRodData
    call IsInArray
    jr c, .ReadFishingGroup
    ld e, $2 ; $2 if no fishing groups found
    ret

.ReadFishingGroup ; 0xe8f6
; hl points to the fishing group entry in the index
    inc hl ; skip map id

    ; read fishing group address
    ld a, [hli]
    ld h, [hl]
    ld l, a

    ld b, [hl] ; how many mons in group
    inc hl ; point to data
    ld e, $0 ; no bite yet

.RandomLoop ; 0xe90c
    call Random
    srl a
    ret c ; 50% chance of no battle

    and %11 ; 2-bit random number
    cp b
    jr nc, .RandomLoop ; if a is greater than the number of mons, regenerate

    ; get the mon
    add a
    ld c, a
    ld b, $0
    add hl, bc
    ld b, [hl] ; level
    inc hl
    ld c, [hl] ; species
    ld e, $1 ; $1 if there's a bite
    ret

INCLUDE "data/super_rod.asm"

; reloads map view and processes sprite data
; for items that cause the overworld to be displayed
ItemUseReloadOverworldData: ; e9c5 (3:69c5)
    call LoadCurrentMapView
    jp UpdateSprites

; creates a list at wBuffer of maps where the mon in [wd11e] can be found.
; this is used by the pokedex to display locations the mon can be found on the map.
FindWildLocationsOfMon: ; e9cb (3:69cb)
    ld hl, WildDataPointers
    ld de, wBuffer
    ld c, $0
.loop
    inc hl
    ld a, [hld]
    inc a
    jr z, .done
    push hl
    ld a, [hli]
    ld h, [hl]
    ld l, a
    ld a, [hli]
    and a
    call nz, CheckMapForMon ; land
    ld a, [hli]
    and a
    call nz, CheckMapForMon ; water
    pop hl
    inc hl
    inc hl
    inc c
    jr .loop
.done
    ld a, $ff ; list terminator
    ld [de], a
    ret

CheckMapForMon: ; e9f0 (3:69f0)
    inc hl
    ld b, $a
.loop
    ld a, [wd11e]
    cp [hl]
    jr nz, .nextEntry
    ld a, c
    ld [de], a
    inc de
.nextEntry
    inc hl
    inc hl
    dec b
    jr nz, .loop
    dec hl
    ret

(Questo messaggio è stato modificato l'ultima volta il: 20-07-2022 07:39 PM da 80C.)
08-04-2020 12:10 AM
Sito Web Cerca Cita
Rispondi 




Utente(i) che stanno guardando questa discussione: 1 Ospite(i)
Powered by MyBB, © 2002-2022 MyBB Group. Copyright ¬© | 2022 Pok√©mon Hacking