Users browsing this thread: 1 Guest(s)
Espers teaching Stat gains
09-09-2020, 04:28 PM
Hi again everyone! I've got a live one for you here. Been staring at it for a couple of days, but my coding level is too low to get there. I know just enough about hacking this game to dive headfirst into the wrong thing for a few hours and get nowhere. Lol.
I'm working on a hack in which I'd like Espers to do something new. Instead of teaching magic, I'd like for them to permanently increase a given stat, i.e. Ramuh teaches Stamina+1....x10, Stamina+3....x2, etc. No magic. Just stat gains. Everything else about the process can stay the same: Growth rate, AP gain from battles, etc. Physically increasing the stat shouldn't be too difficult. Espers already give you stat boosts at level-up (at C26198, with pointers from C2614E). I can hijack that code to do all of the math for me. The issue is getting the game to recognize this new set of instructions. How can I accomplish this?
First, I looked at C2 in the code where we progress towards learning spells taught by Espers (C2602A-C2606C), but nothing there looked particularly useful. Then, I looked at the Esper data, but they just have one byte of info for each spell slot corresponding to the spell index. I thought about creating my own index of stat gains similar to the spell index where 00 would be Stamina+1 instead of Fire, etc. and this seems promising, but how can I get the game to recognize that list as the target? I can't find any pointers that associate Espers with spells. I tell ya, it's tricky!
Any suggestions? All help is appreciated.
I'm working on a hack in which I'd like Espers to do something new. Instead of teaching magic, I'd like for them to permanently increase a given stat, i.e. Ramuh teaches Stamina+1....x10, Stamina+3....x2, etc. No magic. Just stat gains. Everything else about the process can stay the same: Growth rate, AP gain from battles, etc. Physically increasing the stat shouldn't be too difficult. Espers already give you stat boosts at level-up (at C26198, with pointers from C2614E). I can hijack that code to do all of the math for me. The issue is getting the game to recognize this new set of instructions. How can I accomplish this?
First, I looked at C2 in the code where we progress towards learning spells taught by Espers (C2602A-C2606C), but nothing there looked particularly useful. Then, I looked at the Esper data, but they just have one byte of info for each spell slot corresponding to the spell index. I thought about creating my own index of stat gains similar to the spell index where 00 would be Stamina+1 instead of Fire, etc. and this seems promising, but how can I get the game to recognize that list as the target? I can't find any pointers that associate Espers with spells. I tell ya, it's tricky!
Any suggestions? All help is appreciated.
09-17-2020, 12:42 AM
(This post was last modified: 09-17-2020, 01:29 AM by Turbotastic.
Edit Reason: Mobile browsers are awful to me today.
)
(09-09-2020, 04:28 PM)Morendo Wrote: Hi again everyone! I've got a live one for you here. Been staring at it for a couple of days, but my coding level is too low to get there. I know just enough about hacking this game to dive headfirst into the wrong thing for a few hours and get nowhere. Lol.
I'm working on a hack in which I'd like Espers to do something new. Instead of teaching magic, I'd like for them to permanently increase a given stat, i.e. Ramuh teaches Stamina+1....x10, Stamina+3....x2, etc. No magic. Just stat gains. Everything else about the process can stay the same: Growth rate, AP gain from battles, etc. Physically increasing the stat shouldn't be too difficult. Espers already give you stat boosts at level-up (at C26198, with pointers from C2614E). I can hijack that code to do all of the math for me. The issue is getting the game to recognize this new set of instructions. How can I accomplish this?
First, I looked at C2 in the code where we progress towards learning spells taught by Espers (C2602A-C2606C), but nothing there looked particularly useful. Then, I looked at the Esper data, but they just have one byte of info for each spell slot corresponding to the spell index. I thought about creating my own index of stat gains similar to the spell index where 00 would be Stamina+1 instead of Fire, etc. and this seems promising, but how can I get the game to recognize that list as the target? I can't find any pointers that associate Espers with spells. I tell ya, it's tricky!
Any suggestions? All help is appreciated.
I'm surprised no one has replied to this thread until now.
Unfortunately, you won't be able to hijack the existing code in order to do what you seek. Stat gains are limited to one at a time and although they can stack, the code is designed to increase one attribute per character upon levelling up. By contrast the varying nested subroutines concerning learning a spell are designed to work with the spell index to first skip a spell if it is learned, then mark a spell as just learned and to mark the spell as unhidden/accessible. There is no mechanism for learning a spell over and over again, so the subroutine you would eventually create would have to be completely new.
Creating your own stat gain index is an interesting work around but you would have to reconfigure every single loop concerning learning magic from Espers to account for that index. At the bare minimum you would have to replace the called subroutine at C2/6020. That still doesn't address certain problems such as how to apply gains of multiple types.
Thinking about this made my head hurt. That's probably because I'm at too low of a coding level myself to explain.
Cool! I was hoping somebody would respond. Thanks! I think what might be happening is that I know just barely enough about romhacking this game to misunderstand everything about romhacking this game. LOL.
Oh, I didn't have any interest in increasing an attribute multiple times or learning the attribute over and over again. It would work exactly the same as learning spells. Once you've gotten Shiva's "Speed+2...x4" or whatever the skill is to 100%, that's it. It's at 100%. You'd get Speed+2 permanently, but it wouldn't start over.
Regardless, you're still totally right that I'd need to build a new subroutine. The tantalizing part is that so much of the existing code is already doing what I want! The only part I'm looking to change is the result. If I better understood the moment the code says: "Alright. They got to 100%. Go flick the on/off switch in the RAM to make that spell available", I could potentially intercept it and push it to a new subroutine that goes to the stat gain formula instead. At the moment, I don't understand how to do that. I mean, aren't the percentage points just a value stored in the RAM that's counting to 100? How "tied-in" is that number to the spell index?
To put it in FF terms, my coding level is also "too weak to be worthwhile". I suppose I'm not doing a great job of explaining my confusion.
This was my idea for a second option if the above "intercept the moment of spell learning" was functionally impossible or just straight-up dumb. We know the Espers have spell index values in the Esper data at $D86E00. I thought maybe creating a new index for stat gains (a ton of additional work) might be a good Plan B.
Quote:Stat gains are limited to one at a time and although they can stack, the code is designed to increase one attribute per character upon levelling up. By contrast the varying nested subroutines concerning learning a spell are designed to work with the spell index to first skip a spell if it is learned, then mark a spell as just learned and to mark the spell as unhidden/accessible. There is no mechanism for learning a spell over and over again, so the subroutine you would eventually create would have to be completely new.
Oh, I didn't have any interest in increasing an attribute multiple times or learning the attribute over and over again. It would work exactly the same as learning spells. Once you've gotten Shiva's "Speed+2...x4" or whatever the skill is to 100%, that's it. It's at 100%. You'd get Speed+2 permanently, but it wouldn't start over.
Regardless, you're still totally right that I'd need to build a new subroutine. The tantalizing part is that so much of the existing code is already doing what I want! The only part I'm looking to change is the result. If I better understood the moment the code says: "Alright. They got to 100%. Go flick the on/off switch in the RAM to make that spell available", I could potentially intercept it and push it to a new subroutine that goes to the stat gain formula instead. At the moment, I don't understand how to do that. I mean, aren't the percentage points just a value stored in the RAM that's counting to 100? How "tied-in" is that number to the spell index?
To put it in FF terms, my coding level is also "too weak to be worthwhile". I suppose I'm not doing a great job of explaining my confusion.
Quote:Creating your own stat gain index is an interesting work around but you would have to reconfigure every single loop concerning learning magic from Espers to account for that index.
This was my idea for a second option if the above "intercept the moment of spell learning" was functionally impossible or just straight-up dumb. We know the Espers have spell index values in the Esper data at $D86E00. I thought maybe creating a new index for stat gains (a ton of additional work) might be a good Plan B.
I think I might be making some headway on how I might be able to do this. Here's what I've got. I'll try and explain it as best I can. I'm still new to this, and I probably misunderstand and misexplain a lot!
In the vanilla game, Ramuh looks like this:
Ramuh
Bolt x10
Bolt2 x2
Poison x5
At level up ... Stamina +1
In my romhack, I plan to make Ramuh look like this:
Ramuh
Vigor+1 x10
Speed+2 x2
Stam+1 x5
No level-up bonus
- Everything else is vanilla.
- Right now, each character has RAM assigned to which spells they've learned. ($1A6E-$1CF4 Spells Known (12 characters, 54 spells each, 1 byte per spell)
- My romhack will only use 24 spells. The other 30 spots in RAM can be devoted exclusively to these skill-ups.
- This way I need to touch as little code as possible from the vanilla game. You fight monsters. Monsters give Magic Point(s). They calculate the exact same way. They save to the exact same RAM. Everything is the same.
- I set Ramuh to teach Slow x10 instead of Bolt x10. Easy. FFusME can do that with no trouble.
- Slow is spell index 25.
- When you learn a "spell" from an Esper (which will now actually be our skill-up), it checks to see if the spell you've learned reaches 100% ($C2604B). I can add a subroutine here. (see below)
- All I need this subroutine to do is to turn my spell index (25) into a value between $00 and $10. (Incidentally, the correct value for Vigor+1 is $09. You can see this here: https://www.ff6hacking.com/wiki/doku.php...fmt:espers)
- Why a number between $00 and $10? Because I can run a number between $00 and $10 through the Level-Up bonus subroutine at $C260C2. The vanilla game already knows what to do once I give it the correct value.
- So now I just need to turn the number 25 into $09.
- I... don't know how to do this... Moreover, if I plan on turning all spell indexes from 25-54 into these skill-ups, it would be more complex than just turning 25 into $09. I'd need 25, 26, 27 to turn into $09; 28, 29, 30 to turn into $0A, etc. This way Ramuh could teach Vigor+1, and Shiva could teach a *different* Vigor+1. Using spell index 25 on both Espers would just cause both Espers to teach the same bonus.
I suppose it would look something like this:
Sorry about the formatting. My typing got eaten somehow. Also, there might be more to it after the bonus is calculated. I honestly haven't gotten that far just in case the first part doesn't work.
Am I crazy? Misinformed? Misunderstanding how life works? Not explaining it well? Please let me know! Any help would be appreciated.
In the vanilla game, Ramuh looks like this:
Ramuh
Bolt x10
Bolt2 x2
Poison x5
At level up ... Stamina +1
In my romhack, I plan to make Ramuh look like this:
Ramuh
Vigor+1 x10
Speed+2 x2
Stam+1 x5
No level-up bonus
- Everything else is vanilla.
- Right now, each character has RAM assigned to which spells they've learned. ($1A6E-$1CF4 Spells Known (12 characters, 54 spells each, 1 byte per spell)
- My romhack will only use 24 spells. The other 30 spots in RAM can be devoted exclusively to these skill-ups.
- This way I need to touch as little code as possible from the vanilla game. You fight monsters. Monsters give Magic Point(s). They calculate the exact same way. They save to the exact same RAM. Everything is the same.
- I set Ramuh to teach Slow x10 instead of Bolt x10. Easy. FFusME can do that with no trouble.
- Slow is spell index 25.
- When you learn a "spell" from an Esper (which will now actually be our skill-up), it checks to see if the spell you've learned reaches 100% ($C2604B). I can add a subroutine here. (see below)
- All I need this subroutine to do is to turn my spell index (25) into a value between $00 and $10. (Incidentally, the correct value for Vigor+1 is $09. You can see this here: https://www.ff6hacking.com/wiki/doku.php...fmt:espers)
- Why a number between $00 and $10? Because I can run a number between $00 and $10 through the Level-Up bonus subroutine at $C260C2. The vanilla game already knows what to do once I give it the correct value.
- So now I just need to turn the number 25 into $09.
- I... don't know how to do this... Moreover, if I plan on turning all spell indexes from 25-54 into these skill-ups, it would be more complex than just turning 25 into $09. I'd need 25, 26, 27 to turn into $09; 28, 29, 30 to turn into $0A, etc. This way Ramuh could teach Vigor+1, and Shiva could teach a *different* Vigor+1. Using spell index 25 on both Espers would just cause both Espers to teach the same bonus.
I suppose it would look something like this:
Code:
C2604B: BEQ C2606C ;branch if no learn rate, i.e. no spell to learn - This first part is vanilla code
XBA
LDA $FB ;Magic points gained from the battle
JSR C24781 ;Multiply by spell learn rate
STA $EE ;Store this amount in $EE
LDA ($F4),Y ;what % of spell is known
CMP #$FF
BEQ C2606C ;Branch if spell already known
CLC
ADC $EE ;Add amount learned to % known for spell
BCS C26064
CMP #$64
BCC C26066 ;branch if % known didn't reach 100 - Vanilla Code interrupted here by my skill1 subroutine
JSR skill1 ;new skill-up subroutine - this is the only line of code I'm adding
C26064: LDA #$80 ;this is vanilla code again
C26066: STA ($F4),Y ;if it did, mark spell as just learned - this is also vanilla code
skill1: PHA
PHY
LDA $D86E01,X ; Find out which skill-up we just leveled up to 100% (X from earlier code helps us find this)
; Skill-ups and spells come from a shared index. This will load the result to the Accumulator.
CMP #$25 ; Compare it to #$25. Anything lower than #$25 is a spell and not a skill-up.
; Maybe unneeded, but I've added this in case we get here by accident.
BCC C261B0 ; If it IS less than #$25, pop everything back where we found it and RTS the heck outta here.
; Now the accumulator has our spell index in it (25 if it's the slow spell from our example above)
PHX
::Turn 25 into $09 somehow::
ASL ; the level-up bonus code does this to prepare the bonus for calculation
TAX ; Transfer Accumulator to X
JSR (C2614E,X) ; Calculate Skill-up as if we had leveled up while equipped with an esper that gives Vigor+1 as a level-up bonus
PLX
PLY
PLA
RTS
Sorry about the formatting. My typing got eaten somehow. Also, there might be more to it after the bonus is calculated. I honestly haven't gotten that far just in case the first part doesn't work.
Am I crazy? Misinformed? Misunderstanding how life works? Not explaining it well? Please let me know! Any help would be appreciated.
11-12-2020, 03:28 PM
If I understand correctly, I think you can do this with a lookup table. Put your spell index in the accumulator, subtract $25 then transfer to x and load from the lookup table. Your lookup table will be an array of bytes, one for each skill-up value. You can put the table anywhere that you have free space.
Alternatively, if the conversion from spell index to skill-up id is a simple mathematical function (i.e. skill-up = 9 + (spell - $25) * 3) you could write an algorithm to convert it. This might save a few bytes but it won't be as flexible.
Code:
; turn $25 into $09, etc.
sec
sbc #$25
tax
lda lookup_table,x
; somewhere in free space
lookup_table:
.db $09,$09,$09,$0a,$0a,$0a,...
Alternatively, if the conversion from spell index to skill-up id is a simple mathematical function (i.e. skill-up = 9 + (spell - $25) * 3) you could write an algorithm to convert it. This might save a few bytes but it won't be as flexible.
12-10-2020, 05:38 PM
Hey, not sure if this would help, but I wrote this code to replace the vanilla stat-gain routine to make it easier to update and work with. It fits in the same space, and may have room for a large lookup table, if you want.
What you might do is replace the spell IDs in the esper learning data with bytes that represent the exact stat gains you want to give. The hard part is dynamically generating the boost text inside the esper menu. I do have some code that does this, but it might be tricky to implement it in a different context. Let me know if you'd like it.
What you might do is replace the spell IDs in the esper learning data with bytes that represent the exact stat gains you want to give. The hard part is dynamically generating the boost text inside the esper menu. I do have some code that does this, but it might be tricky to implement it in a different context. Let me know if you'd like it.
Code:
hirom
; header
; BNW - Simplified Esper Levels
; Bropedio (April 26, 2019)
; Last modified: June 11, 2019
;
; This overhauls the handling of esper boosts to enable faster changes:
; * Use a table of data rather than pointers to subroutines
; * Encode each bonus into a single byte (bits: 76543210)
; * Bit 0 indicates stat versus HP/MP
; * If stat, bits 2 and 1 provide stat index (7-3 are zero)
; * If stat, assume change of 1 (could support more w/ unused bits)
; * If HP/MP, bit 1 indicates MP (over HP)
; * If HP/MP, bits 7-2 indicate amount to change (max 63)
;
; NOTE: This patch does not handle esper level text display, though I
; imagine it could be rewritten to programmatically determine the EL
; description based on the table below.
org $C2612C
ELJump:
REP #$20 ; 16-bit A
JMP AddEL ; handle esper levelups
NOP #2
org $C2614E
ELTable:
db $78,$78 ; 60HP - Terrato, Crusader
db $52,$52 ; 40HP - Bahamut, Ragnarok
db $78,$3E ; 30HP/15MP - Phoenix, Seraph
db $01,$50 ; 20HP/Vig - Golem
db $52,$07 ; 20MP/Mag - Zoneseek
db $01,$03 ; Vig/Spd - Palidor
db $03,$07 ; Mag/Spd - Siren
db $01,$05 ; Vig/Stm - Phantom
db $05,$07 ; Mag/Stm - Maduin
db $03,$05 ; Spd/Stm - Alexander
db $78,$05 ; 30HP/Stm - Kirin, Unicorn
db $05,$66 ; 25MP/Stm - Carbunkl
db $01,$01 ; 2Vig - Ramuh, Bismark
db $03,$03 ; 2Spd - Ifrit, Fenrir
db $05,$05 ; 2Stm - Stray, Odin, Tritoch, Starlet
db $07,$07 ; 2Mag - Shiva, Shoat
db $00,$00 ; null - Raiden?
AddEL:
LDA ELTable,X ; A = full 2-byte boost
SEP #$20 ; 8-bit A
.doone
TYX ; X = index to character stats
XBA ; swap A bytes
BNE .bonus ; if bonus, branch and handle (long-loop)
RTL ; return
.bonus
LSR
BCC .hpmp ; if bit $01 not set, use HP/MP
.loop
BEQ .stat ; if no stat index, continue
INX
DEC
BRA .loop ; add X to A
.stat
LDA $161A,X ; A = stat
CMP #$80
BEQ .fin ; if maxed already, skip increment
INC
STA $161A,X ; store updated stat
.fin
BRA .next ; finish this bonus byte
.hpmp
LSR ; remainder is amount to add
BCC .addhp ; if MP bit not set, skip INX
INX
INX
INX
INX ; X points to max MP now
CLC
.addhp
ADC $160B,X
STA $160B,X ; add HP/MP bonus
BCC .next ; if no overflow, continue
INC $160C,X ; carry to hi byte
.next
LDA #$00 ; clear finished bonus
BRA .doone ; loop for second bonus byte
padbyte $FF
pad $C261E9
« Next Oldest | Next Newest »
Users browsing this thread: 1 Guest(s)