@Kefka: I don't know if you did it already, but you can add a "Stona-kill" like this:
case 12:
if (FF9StateSystem.Battle.FF9Battle.add_status[(int)cALC_VAR.cmd.aa.AddNo]==2147483649u && btl_util.CheckEnemyCategory(target, CATEGORY_STONE))
{
if (btl_calc.CalcSub_12A(cALC_VAR)) // CheckPetrifyDeathMiss
{
btl_calc.SetEnforceHP0(target);
UIManager.Battle.SetBattleFollowMessage(25, new object[0]); // "Became too soft to live."
}
} else {
btl_calc.CalcSub_302(cALC_VAR); // DoRemoveSpellStatus
}
With this, spells that cure exactly the statuses Petrify and Gradual Petrify will also kill stone enemies. Esuna will not.
For the duration of statuses, it's in the method "btl_stat::AlterStatus". Near the end of the method, you have this block:
if ((status & 4026466304u) != 0u)
{
short num6;
if ((status & 2601713664u) != 0u)
{
num6 = (short)(60 - btl.elem.wpr << 3);
}
else if ((status & 619446272u) != 0u)
{
num6 = (short)(btl.elem.wpr << 3);
}
else
{
num6 = (short)(60 - btl.elem.wpr << 2);
}
btl.stat.cnt.conti[(int)((UIntPtr)(num - 16u))] = (short)(status_data[(int)((UIntPtr)num)].conti_cnt * (ushort)num6);
}
That's the formulae to change for the duration. The first formula is for negative statuses, the second is for good ones and the last is the default (I think it's used for Berserk only). You can of course split the internal "if" blocks to have a formula specific to each status.
Congrats for modifying the damage formula of these other spells
Thanks for the reply, tirlititi! Your suggestion for the Stona spell works like a charm! I didn't know that it was possible to add checks for which statuses are cured exactly, so I hesitated about altering the Cure Status formula for fear of screwing up other status curing spells like Esuna or Antidote.
But concerning the status duration formulas, I still got a few questions:
1) Why does Berserk have a separate duration formula? For all I know, Berserk is a permanent status, isn't it?
2) About the last line from that code you posted:
btl.stat.cnt.conti[(int)((UIntPtr)(num - 16u))] = (short)(status_data[(int)((UIntPtr)num)].conti_cnt * (ushort)num6);
At first I wasn't sure how to read this exactly, but then I found an older post from you from last year when we were first talking about this topic (it was on page 40 of this thread). There you posted the following (back then we didn't have DnSpy so I tried to do it via Hades Workshop's Cil code instead):
However, for the durations of the statuses, they are in 2 spots and it is not possible to edit either of them :/
- In "btl_stat::AlterStatus", a page before the end, there are 3 similar formulas "Duration = (60 - spirit) << 3" (for bad statuses and jump), "Duration = spirit << 3" for good ones and "Duration = spirit << 2" by default (it doesn't seem to be used). You can't edit this method because it's too big and CIL editing tends to bug with big methods.
- In FF9BattleDB (.ctor), there is the setup of "STAT_DATA", a class for status informations, including a multiplier used after the formulas I gave above. You can't modify the method because it's too big and anyway it is one of the few methods that are specially handled by HW and modified by other means.
I've looked into this FF9BattleDB::status_data with DnSpy, and there's a list of 32 statuses. Unfortunately they aren't labeled, so I don't know for sure which order they are in, but I noticed that the third byte is 0 for the first 16 statuses, and then has a value for the following 16 statuses. Not sure about the other bytes, but I'm guessing that this third byte is that multiplier you were referring to, and that would mean that the first 16 statuses in that list are the permanent status effects and the following 16 statuses are the temporary ones, right?
So the complete formula for calculating status duration should be:
Status-specific multiplier * that "num6" value from above (the one that uses the Spirit stat)
And that is the number of frames (or "ticks") that have to pass before the status wears off.
Are my assumptions correct so far? I've already playtested a bit and successfully increased the duration of both positive and negative statuses, now it's only a matter of finding a fair balance for each.
3) Onto my last question: it bugged me a bit when I re-read in your older post that Jump was also a "status effect", that might be a bit annoying. I wanted to increase the usefulness of spells like Protect and Shell, but I don't want jumping to take forever so I'd like to lower the multiplier of that one. You don't happen to know which of these statuses in the list in FF9BattleDB::status_data refers to the Jump status, do you? I guess I could find out through trial and error, though. Anyway, many thanks for guiding me so far, you've been a great help!