Benvenuto Visitatore!  / Create an account

Valutazione discussione:
  • 0 voto(i) - 0 media
  • 1
  • 2
  • 3
  • 4
  • 5
[Gb] Overhaul Sistema HM "Post-HM"
#1
Lightbulb 

Attenzione: questo NON è un tutorial! E' una ricerca / teoria sullo sviluppo di una modifica sull'utilizzo delle TM / HM in Pokemon Red / Blue / Yellow.

Notare che, a livello puramente concettuale, molte delle riflessioni e proposte qui contenute sarebbero applicabili anche in Gen3, previo restante il fatto che ci si adopera di un'architettura ASM differente e di un hardware 16bit (il GBA) alquanto diverso dal Game Boy Color (il quale si adopera di una ASM z80 modificata). (Essendo un linguaggio macchina, è inevitabile che esso sia fortemente dipendente dalla macchina in questione).

Attenzione 2: Thread di ricerca ASM sperimentale, per Gen1 ed in parte Gen2. Pertanto incomprensibile alla maggior parte dei lettori.

Quanto è stato ottenuto fino ad ora:
Essendo una ricerca specialistica che include ASM (per giunta su Red / Blue / Yellow) non mi aspetto che tra qui a 10 anni ci siano molte persone che capiscano quanto stia scrivendo (a meno che non accada una qualche specie di miracolo).

Nota Bene: Le espansioni e le modifiche "sperimentali" che sono riuscito effettivamente a scritturare sono indicizzate, all'inizio del rispettivo paragrafo, da suddetta Icona: Heart
I progetti sperimentali ed i sistemi rimasti a piano teorico sono indicizzati con l'icona: Idea


Pokéball Premessa: Pokéball
Negli ultimi 5 anni (ossia dal 2017 in poi) si è spesso discusso in rete tra gli specialisti GBC e GBA l'eventualità (e, forse, necessità) di rinnovare il sistema delle Mosse HM in modo da renderlo più indipendente dai limiti precedentemente posti dai giochi originari.

Grazie all'ausilio dell'ASM e delle disassembly, oggi è diventato possibile e fattibile creare delle nuove espansioni di funzionalità in modo da rendere la gestione delle HM e delle mosse fuori dalla lotta completamente indipendente dai sistemi congegnati in R/B/Y.

Un primo esempio in tal senso venne raggiunto prima nel 2012 ad opera di Miksy91 ed in seguito nel 2020 circa dal team di sviluppo di Pokemon Coral:
  1. Rendere l'utilizzo delle Mosse fuori dalla lotta indipendente dall'aver conseguito medaglie -- ossia quello che avviene in Pokemon Dark Energy, dove per utilizzare le mosse MN basta aver preso possesso della HM corrispondente, e
  2. fare sì che certi Pokemon possano utilizzare mosse MN indipendentemente dalla conoscenza della mossa MN in questione (come avviene in parte in Pokemon Coral).

Fino ad oggi, queste modifiche hanno riguardato la ben più gestibile Seconda Generazione.
In questo documento, invece, proporrò un overhaul del sistema HM per i giochi di prima generazione ben più radicale di quello proposto fino ad oggi nei giochi Pokemon.
Non appena ne avrò le possibilità, vi fornirò estratti di codice di esempio ed elencherò le modifiche da aggiungere per poter realizzare questa "visione".
Ma procediamo con ordine-

Pokéball IL SISTEMA DI COMPATIBILITA' TM E HM IN GEN1 Pokéball

In Gen.1 l'utilizzo delle HM è gestito principalmente da due routines: una serie di routines nel Bank04 che definiscono le mosse utilizzabili al di fuori della lotta -- StartMenu_Pokemon: ; 130a9 (4:70a9) .
Codice:
StartMenu_Pokemon: ; 130a9 (4:70a9)
; [...]
.choseOutOfBattleMove
    push hl
    ld a,[$cf92]
    ld hl,W_PARTYMON1NAME
    call GetPartyMonName
    pop hl
    ld a,[hl]
    dec a
    add a
    ld b,0
    ld c,a
    ld hl,.outOfBattleMovePointers
    add hl,bc
    ld a,[hli]
    ld h,[hl]
    ld l,a
    ld a,[W_OBTAINEDBADGES] ; badges obtained
    jp [hl]
.outOfBattleMovePointers
    dw .cut
    dw .fly
    dw .surf
    dw .surf
    dw .strength
    dw .flash
    dw .dig
    dw .teleport
    dw .softboiled
.fly
; [...] etc. etc.

Un altra importante serie di funzioni sono le routines di utilizzo delle HM e TM nel Bank3 (a loro volta interconnesse da una serie di routines ASM poste nel Bank0 che definiscono l'utilizzo delle HM, l'uso degli oggetti nello zaino, e così via).
Codice:
ItemUseTMHM: ; e479 (3:6479)
    ld a,[W_ISINBATTLE]
    and a
    jp nz,ItemUseNotTime
    ld a,[$cf91]  ; ID temporaneo oggetto in uso
    sub a,TM_01   ; ID - $c4
    push af   ; push
    jr nc,.skipAdding
    add a,55 ; if item is an HM, add 55
.skipAdding
    inc a
    ld [$d11e],a
    ld a,$44
    call Predef ; get move ID from TM/HM ID
    ld a,[$d11e]
    ld [$d0e0],a
    call GetMoveName
    call CopyStringToCF4B ; copy name to $cf4b
    pop af
    ld hl,BootedUpTMText
    jr nc,.printBootedUpMachineText
    ld hl,BootedUpHMText
.printBootedUpMachineText
    call PrintText
    ld hl,TeachMachineMoveText
    call PrintText
    FuncCoord 14,7
    ld hl,Coord
    ld bc,$080f
    ld a,$14
    ld [$d125],a
    call DisplayTextBoxID ; yes/no menu
    ld a,[wCurrentMenuItem]
    and a
    jr z,.useMachine
    ld a,2
    ld [$cd6a],a ; item not used
    ret
.useMachine
    ld a,[$cf92]
    push af
    ld a,[$cf91]
    push af
.chooseMon
    ld hl,$cf4b
    ld de,$d036
    ld bc,14
    call CopyData
    ld a,$ff
    ld [$cfcb],a
    ld a,$03 ; teach TM/HM party menu
    ld [$d07d],a
    call DisplayPartyMenu
    push af
    ld hl,$d036
    ld de,$cf4b
    ld bc,14
    call CopyData
    pop af
    jr nc,.checkIfAbleToLearnMove
; if the player canceled teaching the move
    pop af
    pop af
    call GBPalWhiteOutWithDelay3
    call CleanLCD_OAM
    call GoPAL_SET_CF1C
    jp LoadScreenTilesFromBuffer1 ; restore saved screen
.checkIfAbleToLearnMove
    ld a,$43
    call Predef ; check if the pokemon can learn the move
    push bc
    ld a,[$cf92]
    ld hl,W_PARTYMON1NAME
    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,$a5
    call PlaySoundWaitForCurrent ; play sound
    ld hl,MonCannotLearnMachineMoveText
    call PrintText
    jr .chooseMon
.checkIfAlreadyLearnedMove
    ld hl, Func_2fe18
    ld b, BANK(Func_2fe18)
    call Bankswitch ; check if the pokemon already knows the move
    jr c,.chooseMon
    ld a,$1b
    call Predef ; teach move
    pop af
    ld [$cf91],a
    pop af
    ld [$cf92],a
    ld a,b
    and a
    ret z
    ld a,[$cf91]
    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 "@"

Quando una TM o MN viene utilizzata, ecco cosa succede:
  • Il numero dell'oggetto TM o HM viene "convertito" ed adattato in un numero che va dal 01 al 55. 01-50: Mosse TM, 51-55: Mosse MN.
    Notare che in Gen1 esistono 5 oggetti di Debug (le TM51, TM52 etc fino alla TM55) che, sebbene insegnino mosse MN, si comportano effettivamente come Mosse TM in quanto oggetti (ovvero: si possono buttare via, e si consumano dopo l'uso);
  • Ciascun Pokemon contiene uno Header di 0x1C bytes RAM, dei quali i 7 bytes dal al byte 0x15 al byte 0x1B contengono un "bit-mask" di zeri ed uno (in totale: 56 bits) che specificano quali tra le possibili 56 (su 55) TM/HM possono essere apprese dal pokemon, in ordine dalla TM01 alla MN05.
    Bit = 0 : Non può apprendere la mossa. Bit = 1 : Il Pokemon può apprendere la mossa TM / HM;
    Codice:
    ; tests if mon [$cf91] can learn move [$d0e0]
    TestMonMoveCompatibility: ; 1373e (4:773e)
        ld a, [$cf91]
        ld [$d0b5], a
        call GetMonHeader
        ld hl, W_MONHLEARNSET
        push hl
        ld a, [$d0e0]
        ld b, a
        ld c, $0
        ld hl, TechnicalMachines
    .findTMloop
        ld a, [hli]
        cp b
        jr z, .TMfoundLoop
        inc c
        jr .findTMloop
    .TMfoundLoop
        pop hl
        ld b, $2  ; read corresponding bit from TM compatibility array
        ld a, $10
        jp Predef ; indirect jump to HandleBitArray (f666 (3:7666))
  • Il numero "convertito" della TM / HM in uso si ricollega ad una lista di mosse contenuta in un altro Bank che contiene l'identità / costante ID sotto forma di numero esadecimale corrispondente alla lista interna di mosse;
    Codice:
    ; converts TM/HM number in $d11e into move number
    ; HMs start at 51
    TMToMove: ; 13763 (4:7763)
        ld a, [$d11e]
        dec a
        ld hl, TechnicalMachines
        ld b, $0
        ld c, a
        add hl, bc
        ld a, [hl]
        ld [$d11e], a
        ret

    TechnicalMachines: ; 13773 (4:7773)
        db MEGA_PUNCH
        db RAZOR_WIND
        db SWORDS_DANCE
        db WHIRLWIND
        db MEGA_KICK
        db TOXIC
        db HORN_DRILL
        db BODY_SLAM
        db TAKE_DOWN
        db DOUBLE_EDGE
        db BUBBLEBEAM
        db WATER_GUN
        db ICE_BEAM
        db BLIZZARD
        db HYPER_BEAM
        db PAY_DAY
        db SUBMISSION
        db COUNTER
        db SEISMIC_TOSS
        db RAGE
        db MEGA_DRAIN
        db SOLARBEAM
        db DRAGON_RAGE
        db THUNDERBOLT
        db THUNDER
        db EARTHQUAKE
        db FISSURE
        db DIG
        db PSYCHIC_M
        db TELEPORT
        db MIMIC
        db DOUBLE_TEAM
        db REFLECT
        db BIDE
        db METRONOME
        db SELFDESTRUCT
        db EGG_BOMB
        db FIRE_BLAST
        db SWIFT
        db SKULL_BASH
        db SOFTBOILED
        db DREAM_EATER
        db SKY_ATTACK
        db REST
        db THUNDER_WAVE
        db PSYWAVE
        db EXPLOSION
        db ROCK_SLIDE
        db TRI_ATTACK
        db SUBSTITUTE
        db CUT
        db FLY
        db SURF
        db STRENGTH
        db FLASH
  • la mossa viene identificata e "prelevata" e posta in un'unità di memoria WRAM temporanea (vedasi primo estratto ASM: ItemUseTMHM);
  • Si procede all'ASM di insegnamento delle mosse ad un Pokemon, utilizzando come mossa da apprendere la mossa salvata temporaneamente nella WRAM, previ i checks per verificare che il Pokemon non abbia già appreso la mossa, etc. (in fondo alla funzione ItemUseTMHM).

Questo comporta ovvi limiti:
  1. Un massimo di 56 tra mosse TM e HM -- che significa, tradotto in soldoni, che si può al massimo aggiungere una HM al massimo, oppure una TM sebbene con difficoltà;
  2. Un numero limitato di TM e HM ben specifico;
  3. Un numero limitato di mosse che il pokemon può apprendere tramite HM;
  4. Un sistema di utilizzo di HM alquanto deleterio per gli standard dei giocatori moderni;
  5. L'uso di HM è limitato all'acquisizione di medaglie, il che limita il design di gioco;
  6. Peggio ancora, e la limitazione di base del mondo dei Pokemon, è di avere la piaga degli HM slave e di mosse sprecate;

In questo topic vedrò di analizzare possibili risposte ed ampliamenti a tali limiti tramite asm.



Idea MOVE-POOL TM E HM ILLIMITATI Idea

Questa modifica farebbe sì che i 7 bytes dei move pool TM e HM per ciascun pokemon diventino superflui: i bitmask verrebbero utilizzati ed inclusi direttamente nell'utilizzo delle TM e HM
nelle routines contenuti nel bank03 (nello specifico, nelle routines dell'uso degli oggetti).

Assumendo che il numero di Pokemon rimanga limitato entro i 255 esemplari (M'Block/MissingNO 0x00 escluso), il bitmask in questione indicherà invece quali specie di Pokemon da 0x01 a 0xFF (secondo la lista di ID Interni in uso in Pokemon R/B/Y, che NON segue l'ordine del Pokedex) possono apprendere la TM / HM in uso, mediante una semplice aggiunta ASM tramite compare:
  • Ciascuna TM / HM nella tabella dell'utilizzo degli oggetti utilizza un utilizzo diverso, specifico per ciascuna TM / HM ;
  • L'utilizzo di una TM / HM fa sì che venga caricata una lista / array di bytes, ciascuno contenente l'ID interno del Pokemon in questione. Non conviene affatto indicizzare le specie di Pokemon disponibili secondo il byte: l'unica soluzione fattibile in termini di spazio è l'utilizzo di array di bitmask.
    Ciascuna TM / HM ha assegnata nell'utilizzo un array di bitmask di 0x20 bytes, cui ciascun bit indicizza una specie di Pokemon dal 0x01 al 0xFF secondo l'ID interno: 0x20 bytes per 55 tra TM e HM sono 0x6E0 bytes, quindi bisogna tenere in conto lo spazio.
  • L' ID del pokemon selezionato su cui si vuole utilizzare la TM / MN (contenuto nel byte WRAM 0xcf92 (wWhichMon), temporaneamente) viene posto nel registro a e poi comparato alla lista di bytes caricati nell'array (tramite funzione di comparazione degli array, nel Bank0) che è stato in precedenza stabilito/creato dalla funzione ddi utilizzo della TM / HM. In caso di bitmask, la funzione di comparazione da eseguirsi utilizza una funzione diversa (quando posso vi rimando alla disassembly, in questo momento non ce l'ho sotto mano);
  • Se la comparazione ha esito positivo (flag nz attivata), si procede come di consueto alla funzionalità di apprendimento della mossa, altrimenti (jr z, oppure jp z) si passa al caso di utilizzo fallimentare di TM / HM;

Le parti da sostituire riguardano dunque:
  • la comparazione con i bitmask delle mosse TM / HM che possono essere apprese dal pokemon selezionato contenuti nelle statistiche del Pokemon selezionato (per l'appunto) -- da rimuovere e sostituire con la comparazione dei bytes e/o bitmask caricati dall'uso della TM / HM stessa;
  • i bytes contenuti nella tabella di pointers dell'utilizzo delle TM e/o HM. In merito a ciò, si necessita di un'ulteriore modifica per fare sì che l'utilizzo di tali oggetti TM e HM non rimandino ad un utilizzo comune (la funzione " UseTMHM " come definita nella Disassembly) sebbene alla lista dei pointer di utilizzo degli oggetti -- ossia, rimuovendo quel compare nella funzione UseItems (cp $C4 (TM01) // jp nc UseTMHM ). Inoltre, si necessita di un'ulteriore seconda modifica per correggere un bug della GameFreak che fa sì che gli oggetti con ID interno oltre 0x7F ri-utilizzinpo gli utilizzi/funzioni a partire dalla MasterBall (ID = 0x01). Per ulteriori informazioni, consultare il mio Item Hacking Tutorial.

Pokéball VANTAGGI
  • Risparmio di 7 bytes nelle statistiche dei Pokemon, ri-utilizzabili per utilizzi ASM completamente nuovi -- es: strumenti tenuti, difesa speciale, secondo strumento tenuto, ID abilità, ID Natura, ID Pokemon Mega-Evoluzione, etc. etc. etc. in base a quanta ASM nuova e funzionalità ASM si è disposti ad implementare. Liberare quei 7 bytes aprirebbe ad orizzonti e possibilità nuove;
  • Move-Pool TM e HM customizzabili per ciascun Pokemon in base alla singola TM e HM e non più in base a quei 7 bytes assegnati a ciascun Pokemon -- ergo, più di 50 TM e più di 6 MN possibili;

Pokéball SVANTAGGI
  • Aggiungere un sacco di modifiche ASM e di correzioni di bug della GF, oltre che riscrivere l'utilizzo delle TM / HM -- facilmente superabile col disassembly, sebbene richieda tempo;
  • Consuma spazio: minimo 0x6E0 bytes in caso di bitmask per 255 Pokemon e 55 TM / HM -- se il numero di specie è inferiore a 255, o se è limitato, o se si trova il modo di trasferire l'utilizzo delle TM / HM e questa funzione in un altro bank, è un problema meno gravoso;

Ad oggi la routine ASM per questa funzione non è ancora pubblicata; lo sarà quando avrò modo di testarla.


Idea AUTO - FIELD MOVE Idea

Una modifica avanzata e proposta recentemente (2021, Pokemon Coral --
) consisterebbe nel fare sì che le mosse Field Moves utilizzabili fuori dalla lotta non siano più dipendenti dalle mosse apprese dai Pokemon quanto da delle bitmask che i Pokemon posseggono -- o i famosi 7 bytes per TM / HM, oppure mediante dei bytes nuovi.

L'utilizzo delle mosse avverrebbe dunque unicamente tramite menù squadra Pokemon, che includerebbe le mosse HM automaticamente in base ai famosi bitmask move-pools TM e HM in odtazione ai pokemon.
Nel caso specifico di R / B / Y, ciò richiederebbe solo 1 byte di spazio: il byte 0x1B di ciascuna statistica base di Pokemon -- il byte andrebbe confrontato come bitmask e, se uno degli 8 bit risultasse == 1, la mossa MN corrispondente verrebbe immessa nel menù.

Una proposta audace, che però (come osservato dall'utenza), pone diversi problemi:
  • Come gestire le mosse non MN utilizzabili fuori dalla lotta (es: Fossa) -- si può risolvere comparando tutti e 7 i bytes dei move-pool (ipotesi più in voga)
  • Essendoci più di 4 mosse in uso fuori dalla lotta, come gestire tutte queste mosse in un menù contestuale -- soluzione di gen2: creare un menù contestuale apposito (soluzione rimasta irrisolta).
    Soluzione mia avanzata da 80C per Gen1 (e, possibilmente, Gen2): creare un menù contestuale apposito con un'opzione dedicata ("Field Move") alla cui selezione si apre un sotto-menù contestuale di selezione tipo quello del Market che, anziché elencare oggetti, esso elenca mosse, caricando in WRAM la costante ID 0x02 (Menù di Mosse) nell apposita WRAM temporanea (wListType, se non erro la dicitura).
    Anzichè creare un ID di oggetti si crea una lista i cui componenti selezionabili sono Mosse.
    L'array in questione (ossia, i 0x20 oggetti del sotto-menù in questione) verrebbe creato per l'appunto comparando i famosi 7 bytes dei move-pools TM e HM, ed estraendo la mossa TM / HM in questione se il bit della bitmask assegnata alle mosse TM HM apprendibili è ==1. La lista andrebbe terminata dal byte 0xFF.

Pokéball VANTAGGI
  • Niente più corrispondenza mosse apprese / field moves utilizzabili fuori dalla lotta: dipenderebbe dalla specie di pokemon selezionato, e non dal moveset. Addio HM Slaves.
  • Più di 4 mosse utilizzabili fuori dalla lotta. Addio HM slaves per sempre -- basterebbe avere un Mew o anche solo un Meowth per utilizzare tutti i field moves possibili immaginabili.

Pokéball SVANTAGGI
  • L'ASM per il menù contestuale sarebbe difficile da inserire: Gen.1 ha un modo tedioso di utilizzare i sotto-menu nel menu pokemon (garantisco io: aggiungere gli strumenti tenuti in Grape ed il menu di assegnazione degli strumenti ai Pokemon come in gen2 è stato tedioso, specie per come le varie ASM di sotto-menu sono spezzettate in banks diversi). In Gen2 dovrebbe essere un pochino più semplice, data la migliore organizzazione del menù di squadra pokemon.
  • L'ASM di creazione del menù field move è un tedio di programmazione ASM. Buona fortuna ad utilizzare tutti quei bitmask e a scervellarsi con le operazioni di rotazioni e spostamento di bit.



Heart FIELD MOVES UTILIZZABILI SENZA MEDAGLIE Heart

Questa è l'unica modifica semplice, addirittura da essere realizzabile tramite hex editor per i disperati senza disassembler.

Nel Bank04 di R / B / Y sono contenuti gli utilizzi delle field moves fuori dalla lotta.
Esiste un pointer contenente gli indirizzi in cui sono raggruppate le routines ASM che portano alle field moves (e, badate bene, è possibile aggiungerne delle altre, come fatto in hacks come Grape, Maize, TRE2, etc. etc. etc.); ciascuna routine delle field moves delle TM contiene un compare con il byte WRAM in cui vengono salvate le medaglie acquisite dal giocatore (1 byte = 8 bit = 8 medaglie. 0 = medaglia non ottenuta, 1 = medaglia ottenuta).
Codice:
StartMenu_Pokemon: ; 130a9 (4:70a9)
; [...]
.choseOutOfBattleMove
    push hl
    ld a,[$cf92]
    ld hl,W_PARTYMON1NAME
    call GetPartyMonName
    pop hl
    ld a,[hl]
    dec a
    add a
    ld b,0
    ld c,a
    ld hl,.outOfBattleMovePointers
    add hl,bc
    ld a,[hli]
    ld h,[hl]
    ld l,a
    ld a,[W_OBTAINEDBADGES] ; badges obtained
    jp [hl]
.outOfBattleMovePointers
    dw .cut
    dw .fly
    dw .surf
    dw .surf
    dw .strength
    dw .flash
    dw .dig
    dw .teleport
    dw .softboiled

Basta eliminare (o, alla Carlona, "azzerare" con dei bytes 0x00, se proprio siete disperati e non disponete di disassembly) quelle famose linee di bit-testing contenute in ciascuna delle ASM in uso per le field moves per eliminare la compatibilità medaglie / mosse.
Vediamo un esempio con la mossa Volo utilizzata fuori dalla lotta:
Codice:
.fly
-    ; bit 2,a ; does the player have the Thunder Badge?
-    ; jp z,.newBadgeRequired
    call CheckIfInOutsideMap
    jr z,.canFly
    ld a,[$cf92]
    ld hl,W_PARTYMON1NAME
    call GetPartyMonName
    ld hl,.cannotFlyHereText
    call PrintText
    jp .loop
.canFly
; [...]

Ciò tornerebbe utile in caso di hacks tipo Snakewood, Climax, ed altre per cui non c'è bisogno di avere palestre e/o medaglie.



Heart TM INFINITE Heart
Rendere le TM ad utilizzo infinito (senza che esse siano uno strumento chiave) è alquanto semplice: basta eliminare la stringa di codice nell'ASM relativa all'utilizzo delle TM che fa sì che l'oggetto venga rimosso dopo l'utilizzo.
(La modifica è in fondo al codice di esempio, secondo il formato di editing "GitHub" secondo il quale il " - " all'inizio indica le linee da commentare via con un " ; " ad inizio rigo, mentre " + " indica le linee di codice da aggiungere).
Codice:
ItemUseTMHM: ; e479 (3:6479)
; [...]
.checkIfAlreadyLearnedMove
    ld hl, Func_2fe18
    ld b, BANK(Func_2fe18)
    call Bankswitch ; check if the pokemon already knows the move
    jr c,.chooseMon
    ld a,$1b
    call Predef ; teach move
    pop af
    ld [$cf91],a
    pop af
    ld [$cf92],a
    ld a,b
    and a
    ret z
; TM infinite: la distinzione TM / HM è dunque superflua qui, rimuovere
-    ; ld a,[$cf91]    
-    ; call IsItemHM
-    ; ret c
-    ; jp RemoveUsedItem
+     ret  ; return, non consumare la TM dopo l'uso.
L'unico svantaggio è l'avere a che fare con 50 TM e poco spazio nello zaino / PC.


Idea TM COME LISTA DI BIT ANZICHE' OGGETTI Idea
Una soluzione radicale al problema di gestione e conservazione delle TM Infinite sarebbe snaturare l'utilizzo delle TM / HM in quanto oggetti dello zaino: servirebbe che, a ciascuna TM o HM collezionata, un bit corrispondente entro 7 bytes di memoria WRAM da salvarsi a parte venga settato. Fatto ciò, in un menù contestuale speciale dello Zaino, si potrebbe accedere ad una lista TM e/o HM per cui, in base ai bit settati, si crea una lista di Mosse (quindi, un sotto-menu contestuale) che possono essere insegnate. Tale configurazione è possibile, seppur tediosa da scrivere in codice.
Ciò risolverebbe il problema delle TM e HM come oggetti dello zaino che occupano spazio: se le TM sono infinite e riutilizzabili, la quantità non ha più senso, e dunque basterebbe avere 7 bytes (56 bits) per le 50 TM e 5 HM in uso nel gioco (naturalmente, apiù TM e HM servirebbero più bytes e bit da settare).

Problema: come fare sì che anzichè ricevere l'oggetto venga settato il bit della TM / HM in questione.
Risposta: Naturalmente facendo sì che in ciascuna istanza del gioco in cui si riceve una HM o TM si abbia un caso del tipo:
Codice:
ld hl,(wTmMoves01) ; nuova flag. 1 bit per mossa TM / HM
set 0,(hl)  ; "0" è il primo bit della mia flag, può essere da 0 a 7, questo è solo un esempio

Resta il problema delle PokeBall che si raccolgono sul terreno nelle mappe...
Esso è potenzialmente risolvibile andando a modificare radicalmente la ASM sugli oggetti raccolti sul terreno, assegnando all'NPC della PokeBall un tipo di movimento diverso, la cui flag verrebbe comparata con un caso/biforcazione speciale nella nostra ASM: se compatibile, il numero dell'oggetto contenuto nella PokeBall/Evento-NPC (tra 0x00 e 0xFF) andrebbe "convertito" in uno dei bit della nostra bitmask delle nostre TM e HM possedute.
Con questo sistema, sarebbe possibile indicizzare un massimo di 255 tra TM e HM (in 0x20 bytes di memoria WRAM in totale).


 Mi Piace Ricevuti: 
Flygon, Blakeishitta, Bonnox, Half shadow, IvanFGK like this post
Cita messaggio
#2
Per la mia hack 2.0 volevo aggiungere il "prototipo" che in Cristallo 2.0 si trova nelle rovine di Villa Pokémon (basato su una copia dello script del MOVE TUTOR che però non chiede gettoni) per insegnare Lanciafiamme, Geloraggio e Fulmine.

Solo che da Skeetendo mi dissero che per poterlo inserire anche in Oro e Argento, dovevo aggiungere le MT per farlo perché anche se era uno script che le insegnava sfruttava comunque 3 MT non assegnate comunque a nessuno strumento e che inoltre in Oro e Argento ci fosse spazio per almeno altre 3 MT, dovevo fare una cosa molto particolare che non avevo capito, considera poi che ovviamente adesso considerando che sono hack fatte sulle rom italiane oltre che inglesi e ormai terminate, sicuramente non ho altra scelta se non continuarle in binario, di certo non mi metto a farle con la disassembly per doverle poi tradurre e rifare anche tutto da capo.

Però il punto è che non ho capito intanto come aggiungerle, prima ancora di dover aggiungere poi la compatibilità dei vari pokémon...
 Mi Piace Ricevuti: 
Cita messaggio
#3
(03-10-2023, 01:06 PM)Half shadow Ha scritto: Per la mia hack 2.0 volevo aggiungere il "prototipo" che in Cristallo 2.0 si trova nelle rovine di Villa Pokémon (basato su una copia dello script del MOVE TUTOR che però non chiede gettoni) per insegnare Lanciafiamme, Geloraggio e Fulmine.

Solo che da Skeetendo mi dissero che per poterlo inserire anche in Oro e Argento, dovevo aggiungere le MT per farlo perché anche se era uno script che le insegnava sfruttava comunque 3 MT non assegnate comunque a nessuno strumento e che inoltre in Oro e Argento ci fosse spazio per almeno altre 3 MT, dovevo fare una cosa molto particolare che non avevo capito, considera poi che ovviamente adesso considerando che sono hack fatte sulle rom italiane oltre che inglesi e ormai terminate, sicuramente non ho altra scelta se non continuarle in binario, di certo non mi metto a farle con la disassembly per doverle poi tradurre e rifare anche tutto da capo.

Però il punto è che non ho capito intanto come aggiungerle, prima ancora di dover aggiungere poi la compatibilità dei vari pokémon...

Da quel (poco) che so, in Gen2 ci sono diverse slot inutilizzate che normalmente avrebbero dovuto essere assegnate alle MT ma che non lo sono per via della compatibilità tra strumenti tenuti da R/B e Yellow, quindi ci sono almeno 2 spazi per MT inutilizzate in mezzo agli ID utilizzati per le MT (se non erro, una dovrebbe essere la 0xc8, potrei sbagliarmi, non ho la lista sottomano 0xC3 e 0xDC sono oggetti dummy non utilizzati posti in mezzo alle TM). Infine, se non vado errato, ci sono almeno 5 spazi inutilizzati in fondo dopo le MN, ossia le 5 costanti fino ad arrivare all'oggetto 0xFE (0xFF è utilizzato per terminare le liste e dunque è un byte speciale che non può essere utilizzato previe modifiche veramemnte estensive).
Questo significa che almeno 7 TM o HM possono essere aggiunte in Gen2 senza dover compiere stravolgimenti (al contrario di gen1 dove, senza dover fare stravolgimenti asm e con i bitmask delle statistiche dei Pokemon, solo una tm o hm può essere aggiunta, preferibilmente una HM data la locazione in fondo ai bytes).

In generale, aggiungere TM e MN in gen2 è più "facile" che non in Gen1, dove lo spazio disponibile per allocare nuovi bitmask per la gestione della compatibilità TM è alquanto esiguo (a meno che non si decida di utilizzare il byte 0x1c delle statistiche di base, ossia il cosiddetto byte "padding" che in gen1 rimane inutilizzato).
Infine, G/S/C hanno più dati inutilizzati delle statistiche di base "non-modificabili" rispetto gen1, sebbene teoricamente ambedue le generazioni utilizzino lo stesso identico numero di "dati personali" per Pokemon (per un totale di 0x2c se non vado errato).

Aggiungere le TM di per sè in Gen2 non è affatto complicato, quanto alle flag, bisogna verificare se effettivamente ci siano dei bit inutilizzati già nelle statistiche di base dei Pokemon; se le cose non stanno così, allora bisogna fare sì che venga utilizzato uno di quei famosi bytes inutilizzati nelle statistiche di base, aggiustando poi le routines per fare sì che quei bytes e quei bit corrispondano alle flag impiegate per la compatibilità pokemon/TM.


PS: (cosa a malapena citata sul web)
La cosa stranissima in Gen1 è che esistono "leftovers" che indicano abbastanza chiaramente che almeno una mossa HM aggiuntiva venne pianificata e scartata:
1) La lista delle mosse utilizzabili fuori dalla lotta include un pointer duplicato inutilizzato per la mossa surf, come se un pointer fosse stato corretto all'ultimo momento anziché essere "tolto";
2) Il già citato bit inutilizzato per una mossa numero 56. Forse è una pura coincidenza visto che si tratta di 8bit per flag di 1 byte, ma considerando il punto #1 non credo;
3) Esiste un testo inutilizzato collocato esattamente tra il testo utilizzato per Surf (HM03) e quello utilizzato per Forza (HM04): "ground rose up somewhere". È probabile che suddetta mossa fosse stata pensata per Capsule Monsters e poi scartata, considerando che avrebbero dovuto esserci almeno 20 mosse in più rispetto quelle che conosciamo (l'ultima è "scontro", aggiunta per ultima).

Notare infine che questi dati beta sono "sopravvissuti" nel gioco finale sia dal passaggio di sviluppo tra Rosso/Verde e Blu (che introduce modifiche abbstanza notevoli, tra l'altro) sia agli adattamenti internazionali basati su Blu Giapponese (dunque Pokemon Rosso internazionale è in realtà la prima hack pokemon di sempre essendo in realtà Blu sotto mentite spoglie: 1 byte di differenza nella schermata dei titoli di coda sul totale impiegato, il resto sono aggiustamenti estetici... Red è un restyle di Blu!).
L'archeologia informatica non è ancora una disciplina, sebbene esistano già abbastanza spunti per cominciare a parlarne.
 Mi Piace Ricevuti: 
Half shadow likes this post
Cita messaggio
#4
Quella cosa del terreno di cui parli è persino tradotta nelle rom italiane, ma siccome dice che il terreno si è sollevato da qualche parte, mi fa venire in mente che potesse essere relativo a FOSSA.

In ogni caso a me piacerebbe davvero mettere quelle 3 mosse imparabili anche in Oro e Argento e fare una routine identica... Pensi davvero sia semplice? Anche metterle dopo le MN non sarebbe un problema, considerando che tanto non si avranno nello zaino, ma verranno solo usate per essere selezionate da un MENU per essere insegnate...

In pratica mi piacerebbe incollare il Move tutor di Cristallo in O/A, con le relative mosse... Poi però sarebbe senza gettoni, non scomparirebbe per ricomparire il Mercoledì/Sabato successivo e sarebbe utilizzabile all'infinito, infatti in Cristallo 2.0 il prototipo nei sotterranei di Villa Pokémon l'ho usato come anello di congiunzione tra le MT infinite che verranno poi introdotte in 5° generazione.
 Mi Piace Ricevuti: 
80C likes this post
Cita messaggio
#5
(03-10-2023, 10:30 PM)Half shadow Ha scritto: Quella cosa del terreno di cui parli è persino tradotta nelle rom italiane, ma siccome dice che il terreno si è sollevato da qualche parte, mi fa venire in mente che potesse essere relativo a FOSSA.

In ogni caso a me piacerebbe davvero mettere quelle 3 mosse imparabili anche in Oro e Argento e fare una routine identica... Pensi davvero sia semplice? Anche metterle dopo le MN non sarebbe un problema, considerando che tanto non si avranno nello zaino, ma verranno solo usate per essere selezionate da un MENU per essere insegnate...

In pratica mi piacerebbe incollare il Move tutor di Cristallo in O/A, con le relative mosse... Poi però sarebbe senza gettoni, non scomparirebbe per ricomparire il Mercoledì/Sabato successivo e sarebbe utilizzabile all'infinito, infatti in Cristallo 2.0 il prototipo nei sotterranei di Villa Pokémon l'ho usato come anello di congiunzione tra le MT infinite che verranno poi introdotte in 5° generazione.

Con l'ASM è possibile praticamente tutto. Forse la strada giusta sarebbe quella di riadattare l'evento di Cristallo eliminando le stringhe di codice che fanno sì che l'evento sia gestito in base a tali condizioni, anche se confesso la mia profonda ignoranza dell'interno di Gen2: Gen1 ha delle modalità astruse di gestione dei menù, e non ha un sistema di scripting interno paragonabile a quello invece in uso in Gen2.

Quanto alle MT "dummy", non credo sia un problema se vengono "aggiunte" dopo le MN, d'altro canto si tratterebbe solo di oggetti inutilizzati di debug (la stessa tavola da surf in Gen1 è un oggetto dummy utilizzato dalla mossa surf). Resta da vedere come viene gestita la compatibilità delle TM tra TM e Pokemon in Gen2 (che confesso che non conosco), da quel poco che so in Cristallo il "Move Tutor" utilizza delle aggiunte specifiche che non ci sono in G\S (Cristallo a dispetto delle apparenze non è un semplice restyle di Oro e Argento: è davvero un gioco a sé stante).


@Half shadow
addenda: ASM del move tutor in cristallo:
Codice:
MoveTutor:
    call FadeToMenu
    call ClearBGPalettes
    call ClearScreen
    call DelayFrame
    ld b, SCGB_PACKPALS
    call GetSGBLayout
    xor a
    ld [wItemAttributeValue], a
    call .GetMoveTutorMove
    ld [wNamedObjectIndex], a
    ld [wPutativeTMHMMove], a
    call GetMoveName
    call CopyName1
    farcall ChooseMonToLearnTMHM
    jr c, .cancel
    jr .enter_loop

.loop
    farcall ChooseMonToLearnTMHM_NoRefresh
    jr c, .cancel
.enter_loop
    call CheckCanLearnMoveTutorMove
    jr nc, .loop
    xor a ; FALSE
    ld [wScriptVar], a
    jr .quit

.cancel
    ld a, -1
    ld [wScriptVar], a
.quit
    call CloseSubmenu
    ret

.GetMoveTutorMove:
    ld a, [wScriptVar]
    cp MOVETUTOR_FLAMETHROWER
    jr z, .flamethrower
    cp MOVETUTOR_THUNDERBOLT
    jr z, .thunderbolt
    ; MOVETUTOR_ICE_BEAM
    ld a, MT03_MOVE ; ICE_BEAM
    ret

.flamethrower
    ld a, MT01_MOVE ; FLAMETHROWER
    ret

.thunderbolt
    ld a, MT02_MOVE ; THUNDERBOLT
    ret

CheckCanLearnMoveTutorMove:
    ld hl, .MenuHeader
    call LoadMenuHeader

    predef CanLearnTMHMMove

    push bc
    ld a, [wCurPartyMon]
    ld hl, wPartyMonNicknames
    call GetNickname
    pop bc

    ld a, c
    and a
    jr nz, .can_learn
    push de
    ld de, SFX_WRONG
    call PlaySFX
    pop de
    ld a, BANK(TMHMNotCompatibleText)
    ld hl, TMHMNotCompatibleText
    call FarPrintText
    jr .didnt_learn

.can_learn
    callfar KnowsMove
    jr c, .didnt_learn

    predef LearnMove
    ld a, b
    and a
    jr z, .didnt_learn

    ld c, HAPPINESS_LEARNMOVE
    callfar ChangeHappiness
    jr .learned

.didnt_learn
    call ExitMenu
    and a
    ret

.learned
    call ExitMenu
    scf
    ret

.MenuHeader:
    db MENU_BACKUP_TILES ; flags
    menu_coords 0, 12, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1

ASM impiegata per il controllo se e possibile apprendere una mossa, in cristallo.

Codice:
CanLearnTMHMMove:
    ld a, [wCurPartySpecies]
    ld [wCurSpecies], a
    call GetBaseData
    ld hl, wBaseTMHM
    push hl

    ld a, [wPutativeTMHMMove]
    ld b, a
    ld c, 0
    ld hl, TMHMMoves
.loop
    ld a, [hli]
    and a
    jr z, .end
    cp b
    jr z, .found
    inc c
    jr .loop

.found
    pop hl
    ld b, CHECK_FLAG
    push de
    ld d, 0
    predef SmallFarFlagAction
    pop de
    ret

.end
    pop hl
    ld c, 0
    ret

GetTMHMMove:
    ld a, [wTempTMHM]
    dec a
    ld hl, TMHMMoves
    ld b, 0
    ld c, a
    add hl, bc
    ld a, [hl]
    ld [wTempTMHM], a
    ret

INCLUDE "data/moves/tmhm_moves.asm"

Infine, Effettivamente Crystal aggiunge tre mosse "dummy" dopo le mosse HM, se non ho capito male tre oggetti TM "dummy" con ID interno dopo 0xFA (non ho idea se l'oggetto 0xFA di per sé sia quello utilizzato o se esso sia a sua volta un ulteriore oggetto inutilizzato).
 Mi Piace Ricevuti: 
Cita messaggio




Utenti che stanno guardando questa discussione: 1 Ospite(i)