News: 11 March 2016 - Forum Rules
Current Moderators - DarkSol, KingMike, MathOnNapkins, Azkadellia, Danke

Author Topic: FF1 MMC5 Disassembly Updates  (Read 212936 times)

Disch

  • Hero Member
  • *****
  • Posts: 2814
  • NES Junkie
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #540 on: May 10, 2020, 11:52:21 am »
Well that's what I mean when I say "scaling the number down".

If you want a power-of-2 range, that's easy to do, as you can just use AND to chop off the high bits.  For example, 0-15 is easy:

Code: [Select]
JSR PutARandomNumberInA
AND #$0F
; A is now random between 0-15

The idea is to (as evenly as possible) map out-of-range values to numbers in your desired range.  By dropping the high bits, we effectively create this mapping:
Code: [Select]
00, 10, 20, 30, etc  -> mapped to 00
01, 11, 21, 31, etc  -> mapped to 01
...
0F, 1F, 2F, 3F, etc  -> mapped to 0F

etc

For non-power of 2 ranges, simply masking bits doesn't really work, so you gotta get craftier.  One way (which FF1 uses) is to multiply the number by a scalar and then divide down.  IE:

Code: [Select]
result = (random_number * desired_range) / 256
We use 256 here since that's the effective range of 'random_number'.. ie: 0-255 is 256 possible values.  It also works out nicely that dividing by 256 is the same as just dropping the low byte, which is effortless to do.

So if you want, say, a number between 0-2 (a range of 3, which is not a power of 2), you could do:
Code: [Select]
result = (random_number * 3) / 256
This effectively has the below mapping (copy/pasted from another post I made on this somewhat recently):

Code: [Select]
(all numbers in hex)
                                   ( result )
RNG output    |  multiply by 3  |  drop low byte   |  odds of result
---------------------------------------------------------------------
00 to 55      |  0000 to 00FF   |  00              |  56 / 100
56 to AA      |  0102 to 01FE   |  01              |  55 / 100
AB to FF      |  0201 to 02FD   |  02              |  55 / 100

Multiplication on the 6502 is non-trivial, but it can still be done relatively quickly.

Cyneprepou4uk

  • Sr. Member
  • ****
  • Posts: 469
  • I am the baldest romhacker
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #541 on: May 10, 2020, 08:16:20 pm »
unless you are looking EXTREMELY CLOSELY

Are we supposed to see a pattern in that picture?  :huh:
iromhacker.ru - NES ROM hacking tutorials for beginners. Please use Google Translate browser extension

Disch

  • Hero Member
  • *****
  • Posts: 2814
  • NES Junkie
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #542 on: May 10, 2020, 09:17:46 pm »
Are we supposed to see a pattern in that picture?  :huh:

Well the pattern is that it's a 256 byte sequence that repeats itself.  IE, if you go in blind, you'll be able to start reliably predicting what comes next after only 257 observations.  Which again for these purposes is fine.

The only reason I put an asterisk on that is because for something where randomness is far more critical (like security encryption) a 256-length sequence is extremely weak and people looking to crack security would absolutely spot the pattern relatively quick.  But we don't care about that for an NES game, so whatever.


I find this stuff absolutely fascinating, but again my knowledge in this area is relatively limited as random number generation is an entire field of study that I've only barely dipped my toes into.  I also feel like we might be derailing the thread here so I'm going to try to cool it.   :laugh: :thumbsup:
« Last Edit: May 10, 2020, 09:23:32 pm by Disch »

Jiggers

  • Sr. Member
  • ****
  • Posts: 405
    • View Profile
    • My Ko-Fi Page
Re: FF1 MMC5 Disassembly Updates
« Reply #543 on: May 11, 2020, 01:06:59 am »
Its interesting, but also still way over my head. How would you feel about writing a bit of code to put in to replace the RNG? I can take care of the ChaosDeath problem (even if it means just copying the current RNG to another bank specifically for that!)

Also wondering, now that several people have eyes on this again: Should equipping weapons and armor cap stats or let them go over a bit?

With leveling up, stats are capped like so:
Hit Rate: 200
Magic Evasion: 200
Damage: 200
Evasion: 200

As these are increased on level up, I assume they're meant to ignore the extra boost weapons give. So these caps are "without equipment" caps. But should equipment caps be the same, or 255?
I know exactly what I'm doing. I just don't know what effect it's going to have.

I wrote some NES music! Its a legal ROM file. - I got a Ko-Fi page too.

Vanya

  • Hero Member
  • *****
  • Posts: 1750
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #544 on: May 11, 2020, 01:32:22 am »
Very interesting stuff about RNG.
I think I have a much better understanding of what is going on now.
Thanks a lot, Disch.

I share the same sentiment about derailing the thread, so I shall cool it too.



Those stat caps from leveling up are for the base values you get from your class.
I believe these stats are not meant to universally cap at 200.

However, don't the formulas in battle already cap these stats o prevent overflow issues?

Disch

  • Hero Member
  • *****
  • Posts: 2814
  • NES Junkie
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #545 on: May 11, 2020, 02:25:12 am »
Its interesting, but also still way over my head. How would you feel about writing a bit of code to put in to replace the RNG? I can take care of the ChaosDeath problem (even if it means just copying the current RNG to another bank specifically for that!)

Honestly I'm not sure what benefit you'd get from replacing the existing RNG.  As long as it's got a decently long period and a uniform distribution (which FF1 has) then it's "good enough" for what you'd need.  Adding in a higher-than-8-bit-number RNG would be more work than it's worth, IMO.  Unless you frequently need 2-byte random numbers.

Though I just realized that since this is an MMC5 hack, you have the MMC5 multiplication regs at your disposal.  Which means a larger RNG might be a lot more feasible than I first thought.

But still... seems a little excessive.

If I were to do it, I'd probably go for like a 1K range and just have a big lookup table of all numbers between 0-1K shuffled up with Python or something.  A higher range means more uniform distribution for larger numbers.  But this would only really pay off if you're frequently getting numbers in the 200+ range (which I guess FF1 does?)

Anyway a condensed 1K table would take... umm... 1K + 1K/4 ... so 1.25K of ROM just for the LUT, and maybe ~200 or so bytes for all the code (wild guess on code size, dunno how big it'd actually be).  Is there space for that?  And would this even be worth it?


Quote
As these are increased on level up, I assume they're meant to ignore the extra boost weapons give.

I always thought it was absurd the way FF1 handled stat increases on level ups.  It does some weird thing where it tries to modify dependent stats like evade and whatnot in-place rather than compute them based on your primary stats.


If it were up to me, I'd rip ALL that out, have level up code modify ONLY your primary stats (and give each character 2 extra bytes for a 'base HP' primary stat that is independent of their Vit bonus).

Then have one single routine recalculate HP and all your substats based on current equipment and primary stats.

Call this routine after any battle that ended with a level up, AND after you exit the equip menu.  Since those are both fade-to-black moments the routine can be slow as balls and it won't matter.  And it ensures your stats are always "correct" without having to have separate logic for equip/level-up.  That also eliminates things like the black belt armor bug.


That said... I don't see any reason why stats should be capped before equipment bonuses.  Frankly I don't think your stats should be getting anywhere NEAR the cap without equipment bonuses.  I guess maybe the black belt/master because they're supposedly experts in unarmed combat... but still....

Jiggers

  • Sr. Member
  • ****
  • Posts: 405
    • View Profile
    • My Ko-Fi Page
Re: FF1 MMC5 Disassembly Updates
« Reply #546 on: May 11, 2020, 02:54:24 pm »
Oh gosh no! I was hoping there would be a way to do RNG without a table at all. Still keep it at 8 bytes, but do something fancy with shifting and pulling from a seed or whatnot, so I could save 200 bytes or so in the fixed bank. FF1 already has its frame counter, and I added another one that rolls over at 60 frames to work as part of the game clock. The clock is tied to the music engine, so if no music is playing, the timer doesn't count up. And cycle stuff isn't as important during the parts where RNG is used, so long as its not using up more than a whole scanline.

If the current RNG table is small as can work, I'm fine with that. With Long jumps and still like a dozen unused banks, its not hurting for space.

Quote
If it were up to me, I'd rip ALL that out, have level up code modify ONLY your primary stats (and give each character 2 extra bytes for a 'base HP' primary stat that is independent of their Vit bonus).

I was gonna do that, but didn't think about the base HP stat... hm. I guess weapon graphic and palette doesn't REALLY need to be with other character stats. Looks like I got some more RAM shuffling to do.

Quote
However, don't the formulas in battle already cap these stats o prevent overflow issues?

Battle calculations cap stuff, probably... but menus don't, and the act of equipping doesn't. So if you somehow had 200 damage and equipped something with 60+... you'd end up with like 4-5 damage displaying in the menus and before you go into battle...

So, I will cap equipping things at 255, and clean up the level up code, after shuffling ch_stats around a bit more, adjusting the weapon swing routine to get the right colors and sprites, and while I'm at it--because this was literally haunting my dreams last night--work up another way to load stats into btl_defender/btl_attacker stats.

At this point its like I'm trying to avoid fixing existing bugs...
« Last Edit: May 11, 2020, 03:14:13 pm by Jiggers »
I know exactly what I'm doing. I just don't know what effect it's going to have.

I wrote some NES music! Its a legal ROM file. - I got a Ko-Fi page too.

Disch

  • Hero Member
  • *****
  • Posts: 2814
  • NES Junkie
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #547 on: May 11, 2020, 03:39:22 pm »
Oh gosh no! I was hoping there would be a way to do RNG without a table at all. Still keep it at 8 bytes, but do something fancy with shifting and pulling from a seed or whatnot, so I could save 200 bytes or so in the fixed bank.

Oh, yeah that could probably be done easily enough.

A basic RNG could be as simple as something like
Code: [Select]
val = (val * Q) + R where Q and R are prime numbers chosen to give decent randomization and a full period.  MMC5's multiplication regs make that pretty easy to do.

LUTs are FAST though.  So the tradeoff here is speed vs. space.

Would you want more than 8 bits?

Pros:
- Wider range (don't have to do the weird shift-trick you're doing)
- Better uniform distribution of larger ranges (8-bit RNG shows heavy bias towards lower numbers once you start getting ranges higher than 64 or 128)
- Longer period (RNG output doesn't loop as quickly)

Cons:
- Need a few more bytes of RAM
- Slower RNG computation

Quote
FF1 already has its frame counter,

You only really need the frame counter for seeding the RNG (giving it a starting point).  And that's only to ensure you don't get the same numerical sequence each time you start the game.  I suppose you could work the frame counter into the RNG calculation itself somehow, but that would add some complexity and would probably hurt your distribution.

Quote
And cycle stuff isn't as important during the parts where RNG is used, so long as its not using up more than a whole scanline.

I'd have to whip something up so I can see how slow it is, but I think you could get a 16-bit RNG (with proper scaling down to a desired range) in less than a scanline with MMC5's help.  Maybe 1/2 to 2/3 scanline.  But that's kind of a VERY ROUGH guess.


But an 8-bit RNG with no lookup table could be wicked fast.  All you need is one multiplication and an ADC -- that takes practically no time at all.  Still slower than a LUT, though.

I dunno I might whip up something later for funsies.  Lemme know what you're most interested in.

Jiggers

  • Sr. Member
  • ****
  • Posts: 405
    • View Profile
    • My Ko-Fi Page
Re: FF1 MMC5 Disassembly Updates
« Reply #548 on: May 11, 2020, 07:19:50 pm »
The shifting thing was to get a random number within a defined range, "RandAX" in bank 1F. I don't know how that would be different with a 16-bit or 9-bit RNG... Calling it would require a lot more extra effort if it had to have two 16-bit ranges set in advance. Which would mess up a lot of code, probably. Backing up registers, setting extra variables, and the only place that I've seen that even needs to do this with a number higher than 8 bits is the healing/damage calculations for spells... I struggle to think what it COULD be used for!

So I think just 8-bit stuff is fine still!
I know exactly what I'm doing. I just don't know what effect it's going to have.

I wrote some NES music! Its a legal ROM file. - I got a Ko-Fi page too.

Disch

  • Hero Member
  • *****
  • Posts: 2814
  • NES Junkie
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #549 on: May 11, 2020, 07:38:04 pm »
The shifting thing was to get a random number within a defined range, "RandAX" in bank 1F. I don't know how that would be different with a 16-bit or 9-bit RNG... Calling it would require a lot more extra effort if it had to have two 16-bit ranges set in advance. Which would mess up a lot of code, probably.

I would keep RandAX there so it could be easily used for 8-bit values, but I'd give a separate routine for 16-bit values.  The 16-bit routine would be a bit clunkier, but it'd be less clunky than the shift trick.  But yeah if you want to stick to 8-bit that's fine.


I can't say when I'll get around to it, but I'll try to see if I can find some time this week.  Might be a fun little thing to work on.

Vanya

  • Hero Member
  • *****
  • Posts: 1750
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #550 on: May 12, 2020, 02:16:56 am »
On the subject of the level up system:

I totally agree with Disch's sentiment there.
I'm not 100% sure in regards to FF3, but I'm pretty sure the rest of the games after it all use formulas to calculate your "derived stats" such as evade, hit rate, crit, etc.
And their level up systems use algorithms for stat growth that exclusively handle the "primary stats".

So I'm all for overhauling this part of the game as long as the numbers can stay relatively close to the original.

Jiggers

  • Sr. Member
  • ****
  • Posts: 405
    • View Profile
    • My Ko-Fi Page
Re: FF1 MMC5 Disassembly Updates
« Reply #551 on: May 12, 2020, 03:00:48 am »
I can't say when I'll get around to it, but I'll try to see if I can find some time this week.  Might be a fun little thing to work on.

No worries, and thanks if/when you get around to it! So long as its fun, that's the main requirement!

I overhauled a few things today. In order to free up those 2 stats for base HP... Weapon sprites and palettes are calculated before battle and stored in the same way other flags like Stone and Cover and such are. While loading stats for magic and physical attacks, instead of doing every stat one by one--and having my dumb self try to save a byte by doing INY whenever possible, which always mucks up everything when I re-arrange ch_stat RAM at all--it now reads from a table of "byte to read, byte to save" and does a loop. This is pretty space-efficient for magic loading/saving, but probably not that much better for physical attacks. Still, it keeps things tidy and makes editing WAY easier!

Short version is: Need to test a party of Black Belts with different sprites out again to make sure their fists are loading right. Don't think I got around to making sure the attack cloud was white for their attacks.

Then after re-organizing ch_stats some, I figured why not tackle how stats are drawn, too? Which resulted in some nice clean up of stat printing. (I think I forgot to update the alternative name display byte used for "X learns the spell!" in the magic menu though.) While doing this I stumbled on a few other bugs I hadn't run into before. Like, the Elixir use menu only displayed 7 levels of MP. So I adjusted that.

And while I was in there I re-did the boxes for shops to use the main menu's box loading, so I had to hunt down and change all the IDs after cutting out all unused box dimensions...

Shops and menus seem to work just fine still, from my quick glances.

Oh and while adjusting stat loading for physical attacks, I set thieves to have a straight up 2x damage boost for being hidden. This might be too much? I thought 1.5x wasn't enough, but I forgot it also boosts critical hit rate on top of that... Still, Hiding is riskier than Focus, since you still have to avoid being hit until the next turn, and then your action on top of that. I put all these cool things into the battle engine and when I play I just mash attack still, because its still faster than doing the new things! :I New things need to be awesome! Grr!

I updated everything on GitHub, its a messy update, I'll be checking things closer tomorrow!

May 13, 2020, 01:47:10 am - (Auto Merged - Double Posts are not allowed before 7 days.)
Something I just noticed.

The FF Bytes document shows that enemies have an "ailment chance" for their attacks. R.Goyle has 2, but no ailment set. Sorcerers, well known for their instant-death hits, have 0--the only enemy with an ailment attack and no ailment chance?

I can't find where in the original disassembly that this stat is used. Constants has it listed as ENROMSTAT_UNKNOWN_E. Physical attacks just have a base chance of #100 for any enemy that has an ailment to inflict.

So--what to do with this unused enemy stat? Do I set it up to do an actual "ailment chance" as what was maybe intended, or do I re-purpose it? I do still have 1 extra unused enemy ROM stat that can be pre-loaded as something. What I was doing when I found this out was fixing up the Counter/Parry status for enemies. I was going to see if I could set some enemies to counter physical attacks by default.

If I do set up this stat for ailment chance, how should I go about it? Its either 0, 1, or 2. Do you think the 1 might have been planned to be converted into #100 and 2 meant #200?



@Vanya: Looking at the hoops I jumped through to get characters posing in the shops for equipping stuff... at the moment, doing that for magic is a bit too much of a headache for me and I don't know if there is enough space in the bank to do the necessary checks all over the place for it.

To make up for that, I added in the alternative Ruined Castle melody you requested ages ago! Give it a listen in the sound test menu!
« Last Edit: May 13, 2020, 04:12:56 am by Jiggers »
I know exactly what I'm doing. I just don't know what effect it's going to have.

I wrote some NES music! Its a legal ROM file. - I got a Ko-Fi page too.

Vanya

  • Hero Member
  • *****
  • Posts: 1750
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #552 on: May 13, 2020, 08:01:36 am »
Thank you!  Can't wait to give it a listen.
If there is anything I can do to help with hoop-jumping of a tedious nature, please let me know.



As for the chance to inflict ailment stat for enemies, I'd like it to be restored to a working state.
Not sure how to handle the actual meaning of the stat though.
It could be a multiplier, I suppose.
0 = no chance to succeed.
1 = normal chance to succeed.
2 = 2x chance to succeed.
Without some indication of what it should do, your guess is as good as mine.

I do know this, the base chance to cause a status ailment is about 50%.
And there is a bug that causes subsequent misses after the first hit to still have a chance to inflict.
Don't know if it was correct in the initial disassembly.

Also, enemies do not have any way to increase their chance to cause a status ailment, so as the game progresses, their chances to inflict drop more and more due to your "M.Def." steadily increasing.
So maybe, that 2 value above increasing the chance to inflict might make more sense.

Upon further reflection, it might be a good idea to repurpose that status infliction stat to be directly added to the chance to inflict an ailment instead of being a multiplier or something.
That way we can finetune status infliction rates.

I also think that it doesn't make sense for physical status infliction to be defended with Magic Evade.
On the one hand, it makes sense in the context of the game mechanics because it makes the martial characters more vulnerable to status effects that the spellcasters don't have to worry as much about.
However, changing it to be defended by Evade would change the game's dynamic to be more like D&D.
Given that FF is based heavily on D&D, that actually makes more sense to me.

Ooh! Maybe instead of using Evade to defend against status attacks, it works off the defender's constitution score directly? That would give the Constitution stat another thing to do.

OK.
Yeah.
That is my opinion.
Make physical status attacks be directly increased by the status attack stat and decreased by (maybe 1/2) the defender's Constitution stat instead of their M. Evade stat.
We can work out the exact values for the staus attack stat later with playtesting.

Thoughts?



On the subject of status ailments, did we ever talk about separating status effects from elemental effects?
It would be nice to be able to have all 8 elements available for use as elements.
Though, I'm sure that would bring on a number of complications like needing to add a way to defend against status effects that are not tied up with elemental defenses or making a way to have status immunities.
Is there even any space for a status defense byte in armor?
And then there's what to do about the spells that have effects that defend against the status effect elements.
Should they grant full immunity instead?

What do you think?

Disch

  • Hero Member
  • *****
  • Posts: 2814
  • NES Junkie
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #553 on: May 13, 2020, 11:29:42 am »
The FF Bytes document shows that enemies have an "ailment chance" for their attacks. R.Goyle has 2, but no ailment set. Sorcerers, well known for their instant-death hits, have 0--the only enemy with an ailment attack and no ailment chance?

I can't find where in the original disassembly that this stat is used. Constants has it listed as ENROMSTAT_UNKNOWN_E. Physical attacks just have a base chance of #100 for any enemy that has an ailment to inflict.

I don't think it does.  FFBytes probably has it mislabeled.

Searching for "ENROMSTAT_" across all files shows references speckled all across bank C, notably the '@lut_RomRamMapping:' table which determines how (and which) enemy stats get copied to RAM upon battle entry.  ENSTATROM_UNKNOWN_E is not listed there.  So either it's read directly from ROM when it's used or it just isn't used.  I'd bet money on the latter.


If you want to be sure, you could try setting a breakpoint on that area in ROM for some enemies and try running through a few battles to see if they ever trip.  I kind of doubt they will.

Quote
If I do set up this stat for ailment chance, how should I go about it? Its either 0, 1, or 2. Do you think the 1 might have been planned to be converted into #100 and 2 meant #200?

I don't see any reason to assume that's what it was originally intended for.  I think YDD probably just got this one wrong.  If you want to use it for this, I'd say you're free to define it however you want.

Jiggers

  • Sr. Member
  • ****
  • Posts: 405
    • View Profile
    • My Ko-Fi Page
Re: FF1 MMC5 Disassembly Updates
« Reply #554 on: May 13, 2020, 06:00:50 pm »
Hard to say if FF Bytes has it mislabeled. R.Goyle and Sorcerers are the only 2 enemies who have one or the other, but not both. So it seems to me that this stat was meant to be used in relation with ailment infliction attacks.

I've been all over Bank C before, changed just about everything to do with enemy stats (in my effort to make them all readable from RAM and simplify things) and it never, ever came up. So that's just... huh. Slipped through the cracks that this stat byte just wasn't used? I can't find any reference to it anywhere else so far... http://jeffludwig.com/finalfantasy/hacking/bestiary Aha. Cond? bytes... Weird, instead of taking it out, they ADDED another byte?? Looks like we'll have to go digging in the GBA port to see how its used!

Edit: So https://www.romhacking.net/documents/750/ explained it in "Nightmare Modules/Monster Editor/Monster Editor.nmm".

Looks like its meant to be the ailment's ELEMENT. So that would be Sorcerers using an element-less physical attack to inflict the Death ailment... The other byte on that previous link is Crit Rate. So every poison afflicting enemy is using the same element for RUB, QAKE, BANE (poison... makes sense there.) And every other ailment is using the status effect element. This byte was SUPPOSED to be loaded up as btl_attacker_element, but the original game was using ENROMSTAT_ELEMWEAK. Mystery solved!

Now to think about what I should do with it... (I did add a proper attack element stat, after all...) Original post thoughts after the break:



My first thought was just to set it to $64 if its 1, and $96 if its 2. So a #100 base chance, and then a #150 base chance. Or, really, anything in between that you want. So if I have Kraken doing 4 physical attacks with his 8 tentacles, I could cut the base chance for the blind ailment to 50... Or whatever works best. Then its more in line with player weapons, which now have an ailment chance and an ailment byte.

I did fix the bug, so enemies only have 1 chance to inflict an ailment per hit, no more free chances for misses.

And status resistance is in effect. Enemies have it, armor has it! Its just a one off immunity check. If you resist death, then it doesn't bother doing a minimum ailment chance of 1.

I don't know about replacing Magic Evade with Vitality on its own here, but... what if Magic Evade was calculated based on Vitality+Intelligence? That gives both those stats something more to do! (I also thought it made more sense that BBelt/Master was more immune to ailments, because of his, well, mastery of his body. He's so anti-magic that he shrugs attacks off better?) Its also an armor stat now, so it can be boosted with the right gear.

Actually, we can stop calling it Magic Evade with physical attacks, because it doesn't have to be that stat at all. Physical and Magical attacks are completely separated and whatever stat is contested vs. enemy ailment chance could be anything we dream up. Vitality+Evasion? Vitality+Mag.Evade/2?

Quote
And then there's what to do about the spells that have effects that defend against the status effect elements.
Should they grant full immunity instead?

Hm... you mean ARUB? Easy enough to put in another spell effect to make that set the party's status resistance. I think that was my plan...

I'm a little embarrassed how much half-baked ideas are in this already... I'm way too ADD to keep track of what I'm doing one day to the next without people to remind me. XD

I also want spell effects to imbue weapons with elements and ailments... Even if I don't put the spells in, having the code there will be nice for anyone who wants to make Red Mage a Mystic Knight or something.



Saw this earlier: "FF1: DoS - Unrunnable Battle Notification" -- ... that's a good idea, gonna see if I can do that too!

Other idea: Make poison work more like Pokemon games when walking out of battle? Random number between 4-15, that's how many steps you take before you get the hit. Then make it 1-3 HP when it happens. Flash the screen red on that step.
« Last Edit: May 13, 2020, 07:07:50 pm by Jiggers »
I know exactly what I'm doing. I just don't know what effect it's going to have.

I wrote some NES music! Its a legal ROM file. - I got a Ko-Fi page too.

abw

  • Hero Member
  • *****
  • Posts: 521
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #555 on: May 13, 2020, 07:33:42 pm »
I don't know about replacing Magic Evade with Vitality on its own here, but... what if Magic Evade was calculated based on Vitality+Intelligence? That gives both those stats something more to do!
As a point of possible interest, FF2 calculates Magic Resist % as (Stamina + Magic Power) / 2 + armour boni, has a separate stat for Magic Resist level (a.k.a. number of attempts), and in addition to providing resistance against actual magic, Magic Resist is also used when checking for resistance to physically-inflicted status ailments.

I also want spell effects to imbue weapons with elements and ailments... Even if I don't put the spells in, having the code there will be nice for anyone who wants to make Red Mage a Mystic Knight or something.
As it happens, FF2 sort of has this too via its Aura spell, except Aura imbues a weapon with power against various monster families rather than adding elements or ailments.

Jiggers

  • Sr. Member
  • ****
  • Posts: 405
    • View Profile
    • My Ko-Fi Page
Re: FF1 MMC5 Disassembly Updates
« Reply #556 on: May 13, 2020, 07:51:53 pm »
That's good info.

Easy enough to do both an Aura-type spell and an element-type spell. Spell Element = Weapon Element, Spell Effectivity = Weapon Category , Spell Hit Rate = Could boost Weapon Hit Rate, Damage, or Critical Hit Rate. All in one spell routine, just have the things you don't want to boost be 0 in the spell data!

So with Elements, I had set up the "Death, Time, Stone, Stun" bits to be "Water, Wind, Holy, Dark". Two are a little redundant with Lightning and Ice already being elements. I like Holy and Dark. I'm open to suggestions.

Attack element also only effects hit chance at the moment, and +4 to damage. Should it effect damage differently?

For anyone who wants to hear the thing without downloading the latest build and all that: https://cdn.discordapp.com/attachments/505736168659353601/710043252190871562/FF1_Ruined_Castle_Alt_Melody.mp3
« Last Edit: May 13, 2020, 09:01:47 pm by Jiggers »
I know exactly what I'm doing. I just don't know what effect it's going to have.

I wrote some NES music! Its a legal ROM file. - I got a Ko-Fi page too.

abw

  • Hero Member
  • *****
  • Posts: 521
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #557 on: May 13, 2020, 09:14:42 pm »
Attack element also only effects hit chance at the moment, and +4 to damage. Should it effect damage differently?
FF2 increases weapon base damage by 20 if the weapon hits any of the target's family or elemental weaknesses (does not stack); each hit inflicts (base damage * random(1..2) - defense) + 5% chance for + (base damage). Monsters in FF2 have higher HP than in FF1, though, so +20 might be OP for FF1.

Jiggers

  • Sr. Member
  • ****
  • Posts: 405
    • View Profile
    • My Ko-Fi Page
Re: FF1 MMC5 Disassembly Updates
« Reply #558 on: May 14, 2020, 02:55:57 am »
I think when I'm done editing battle stuff and everything is in place that I'm able to put together, I'm going to go through it and find every instance of where a number could be tweaked, and put it in Constants. That way if someone wants to edit how much damage a weapon does, or how much base HP a heal potion uses, they can just edit those numbers there without searching through the whole thing. I can't do this for EVERY adjustable value, but for the more obscure ones, I hope it will help with balancing.

I did a neat thing with poison just now. Every couple steps (between 4 and 10 it seems) it will turn the screen red and play a scrapey noise sound, then decrease HP for each poisoned person by a randomized amount (same amount for everyone--unless it would kill them, then it decreases the amount by 1 until it won't. If HP is already at 1, it skips them.)

So overall, this could do more damage, or less damage, than the vanilla effect of 1 damage per step. But mostly less. And be a lot less annoying--though I already killed off that awful square SFX.
I know exactly what I'm doing. I just don't know what effect it's going to have.

I wrote some NES music! Its a legal ROM file. - I got a Ko-Fi page too.

Vanya

  • Hero Member
  • *****
  • Posts: 1750
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #559 on: May 14, 2020, 04:56:22 am »
Quote from: Jiggers
Edit: So https://www.romhacking.net/documents/750/ explained it in "Nightmare Modules/Monster Editor/Monster Editor.nmm".

Looks like its meant to be the ailment's ELEMENT. So that would be Sorcerers using an element-less physical attack to inflict the Death ailment... The other byte on that previous link is Crit Rate. So every poison afflicting enemy is using the same element for RUB, QAKE, BANE (poison... makes sense there.) And every other ailment is using the status effect element. This byte was SUPPOSED to be loaded up as btl_attacker_element, but the original game was using ENROMSTAT_ELEMWEAK. Mystery solved!

Yeah, I saw a similar explanation here:
https://guides.gamercorner.net/ff/walkthrough/game-systems


Quote from: Jiggers
My first thought was just to set it to $64 if its 1, and $96 if its 2. So a #100 base chance, and then a #150 base chance. Or, really, anything in between that you want. So if I have Kraken doing 4 physical attacks with his 8 tentacles, I could cut the base chance for the blind ailment to 50... Or whatever works best. Then its more in line with player weapons, which now have an ailment chance and an ailment byte.

Wait so enemies have a proper elemental attack and status attack byte?
And now this byte in question which was supposed to be attack element is not used?
If so...
Why not use it to directly set the base status attack hit rate?
That way we have way more options.

Quote from: abw
As a point of possible interest, FF2 calculates Magic Resist % as (Stamina + Magic Power) / 2 + armour boni, has a separate stat for Magic Resist level (a.k.a. number of attempts), and in addition to providing resistance against actual magic, Magic Resist is also used when checking for resistance to physically-inflicted status ailments.

Neat! I should have thought to look that up myself.


Quote from: Jiggers
I don't know about replacing Magic Evade with Vitality on its own here, but... what if Magic Evade was calculated based on Vitality+Intelligence? That gives both those stats something more to do! (I also thought it made more sense that BBelt/Master was more immune to ailments, because of his, well, mastery of his body. He's so anti-magic that he shrugs attacks off better?) Its also an armor stat now, so it can be boosted with the right gear.

Actually, we can stop calling it Magic Evade with physical attacks, because it doesn't have to be that stat at all. Physical and Magical attacks are completely separated and whatever stat is contested vs. enemy ailment chance could be anything we dream up. Vitality+Evasion? Vitality+Mag.Evade/2?

!!...I just had a realization.

The M.Evade stat is the saving throw mechanic from D&D condensed down to a single stat.
So really, M.Evade is your Saving Throw Bonus!

Since we want to swap out M. Evade, we need to replace it in a way that matches up with how M. Evade works in general so we don't have to recalculate a ton of other factors.

M.Evade has a base value and a fixed growth, so we should factor in the defender's level.
Let's call it Status Evade or SEvd for now.

SEvd = VIT + (Defender's Level * Growth) will keep things pretty comparable to M.Evade and give the Fighter, Thief, and Monk higher defense against status attacks.

Here are some numbers for comparison including what MEvd would look like using a similar formula:
Code: [Select]
1. FIGHTER/KNIGHT

Starting Stats                 Minimum L50 Stats             Mean    L50 Stats[b]
MEvd: 15 (+3 Per Level up)     MEvd: 162                     MEvd: 162[/b]
INT:   1                       INT:   15                     INT:   32
MEvd:  2 (INT + Level*1)       MEvd:  65                     MEvd:  82
VIT:  10                       VIT:   35                     VIT:   47
SEvd: 13 (VIT + Level*3)       SEvd: 185                     SEvd: 197


2. THIEF/NINJA

Starting Stats                 Minimum L50 Stats             Mean    L50 Stats
[b]MEvd: 15 (+2 Per Level up)     MEvd: 113                     MEvd: 113[/b]
INT:   5                       INT:   22                     INT:   38
MEvd:  7 (INT + Level*2)       MEvd: 122                     MEvd: 138
VIT:   5                       VIT:   21                     VIT:   37
SEvd:  7 (VIT + Level*2)       SEvd: 121                     SEvd: 137


3. BLACK BELT/MASTER

Starting Stats                 Minimum L50 Stats             Mean    L50 Stats[b]
MEvd: 10 (+1 Per Level up)     MEvd:  59*                    MEvd: 146*[/b]
INT:   5                       INT:   29                     INT:   41
MEvd:  7 (INT + Level*2)       MEvd: 129                     MEvd: 141
VIT:  20                       VIT:   69                     VIT:   69
SEvd: 22 (VIT + Level*2)       SEvd: 169                     SEvd: 169

*  Assuming class change is at level 50 for the minimum values and level 21 for the mean values.
   Also assuming MEvd growth was swapped to +1 for BB and +4 for MA.

4. RED MAGE/RED WIZARD

Starting Stats                 Minimum L50 Stats             Mean    L50 Stats[b]
MEvd: 20 (+2 Per Level up)     MEvd: 118                     MEvd: 118[/b]
INT:  10                       INT:   34                     INT:   46
MEvd: 12 (INT + Level*2)       MEvd: 134                     MEvd: 146
VIT:   5                       VIT:   27                     VIT:   40
SEvd:  7 (VIT + Level*2)       SEvd: 127                     SEvd: 140


5. WHITE MAGE/WHITE WIZARD

Starting Stats                 Minimum L50 Stats             Mean    L50 Stats[b]
MEvd: 20 (+2 Per Level up)     MEvd: 118                     MEvd: 118[/b]
INT:  15                       INT:   44                     INT:   54
MEvd: 17 (INT + Level*2)       MEvd: 138                     MEvd: 154
VIT:  10                       VIT:   29                     VIT:   44
SEvd: 11 (VIT + Level*1)       SEvd:  79                     SEvd:  94


6. BLACK MAGE/BLACK WIZARD

Starting Stats                 Minimum L50 Stats             Mean    L50 Stats[b]
MEvd: 20 (+2 Per Level up)     MEvd: 118                     MEvd: 118[/b]
INT:  20                       INT:   69                     INT:   69
MEvd: 22 (INT + Level*2)       MEvd: 169                     MEvd: 169
VIT:   1                       VIT:   15                     VIT:   32
SEvd:  2 (VIT + Level*1)       SEvd:  65                     SEvd:  82

I think something like this would work out pretty well.
Especially if you use that leftover enemy stat as a status attack accuracy bonus to bring things more in line with the way status spells work.

PS- so much more to comment on, but I already spend a good chunk of time with the above! :P