Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - ste459

Pages: [1]
1
Thanks for your kind reply.
(and your math expression is written way better than mine ;D )

For some reason I can't made this code to work, I entered it and at the beginning and called it with the line: CommonScript.TryCriticalHitAdjusted(_v); but I always get an error from Compiler because commonscript.cs does not contain a definition for TryCriticalHitAdjusted.

My commonscript.cs file looks like that (but I tried to insert the code in different positions with the same result):

Code: [Select]
using System;
using Memoria.Data;

namespace Memoria.Scripts.Battle
{
public static class CommonScript
{
public const String InfoMessageColor = "[00FFFF]";
public const String GoodMessageColor = "[00FFFF]";
public const String BadMessageColor = "[FF4040]";
}


public abstract class BaseWeaponScript : IBattleScript
{
private readonly BattleCalculator _v;
private readonly CalcAttackBonus _bonus;
private readonly Boolean _drain;

public static void TryCriticalHitAdjusted(BattleCalculator _v)
{
Int32 quarterWill = _v.Caster.Data.elem.wpr >> 2;
if (quarterWill != 0 && (GameRandom.Next16() % quarterWill) + _v.Caster.Data.critical_rate_deal_bonus + _v.Target.Data.critical_rate_receive_bonus > GameRandom.Next16() % 100)
{
_v.Target.HpDamage = (Int32)(_v.Target.HpDamage / 4f + Math.Min(15000, _v.Target.HpDamage) / 4f + Math.Min(10000, _v.Target.HpDamage) / 2f);
// Do the same for "_v.Target.MpDamage"; apparently you don't use "_v.Context.Attack" in your situation when the critical strike triggers
_v.Target.Flags |= CalcFlag.Critical;
}
}


protected BaseWeaponScript(BattleCalculator v, CalcAttackBonus bonus, Boolean drain = false)
{
_v = v;
_bonus = bonus;
_drain = drain;
}


public virtual void Perform()
{

if (_drain && (!_v.IsCasterNotTarget() || !_v.Target.CanBeAttacked()))
return;

_v.PhysicalAccuracy();
if (!_v.TryPhysicalHit())
return;

if (_bonus != CalcAttackBonus.Level)
_v.WeaponPhysicalParams(_bonus);
else
{
Int32 baseDamage = GameRandom.Next16() % (1 + (_v.Caster.Level + _v.Caster.Strength >> 3));
_v.Context.AttackPower = _v.Caster.WeaponPower;
_v.Target.SetPhysicalDefense();
if (_v.Caster.Weapon == (RegularItem)256)
{
_v.Context.AttackPower += 3 * _v.Caster.Level / 4;
if (_v.Target.IsPlayer && _v.Target.PlayerIndex == CharacterId.Garnet)
_v.Target.Flags |= CalcFlag.HpRecovery;
}
else
{
_v.Context.AttackPower += _v.Caster.Level / 2;
}
_v.Context.Attack = _v.Caster.Strength + baseDamage;
}

if (_v.Caster.IsUnderAnyStatus(BattleStatus.Mini))
_v.Context.Attack = 1;
if (_v.Caster.IsUnderAnyStatus(BattleStatus.Berserk))
++_v.Context.DamageModifierCount;
if (_v.Caster.IsUnderAnyStatus(BattleStatus.Trance))
++_v.Context.DamageModifierCount;
if (_v.Target.IsUnderAnyStatus(BattleStatus.Defend))
--_v.Context.DamageModifierCount;
if (_v.Target.IsUnderAnyStatus(BattleStatus.Protect))
--_v.Context.DamageModifierCount;
if (_v.Target.IsUnderAnyStatus(BattleStatus.Sleep))
++_v.Context.DamageModifierCount;
if (_v.Target.IsUnderAnyStatus(BattleStatus.Mini))
++_v.Context.DamageModifierCount;

if (_drain)
_v.PrepareHpDraining();

CommonScript.TryCriticalHitAdjusted(_v);

if (_v.Caster.Weapon == (RegularItem)15)
{
          _v.CalcDamageCommon();

          _v.Target.HpDamage = _v.Context.EnsureAttack * _v.Context.EnsurePowerDifference;

                  if (_v.Target.Flags != 0)
                  {
                    Single modifier_factor = 1.0f;
                    Single modifier_bonus = 0.5f;
                    Byte modifier_index = 0;

                        if (_v.Caster.IsUnderAnyStatus(BattleStatus.Trance) && _v.Caster.PlayerIndex == CharacterId.Steiner)
                            modifier_bonus = 1.0f;
                        while (_v.Context.DamageModifierCount > 0)
                        {
                            modifier_factor += modifier_bonus;
                            modifier_index++;
                            if (modifier_index >= 2)
                            {
                                modifier_bonus *= 0.5f;
                                modifier_index = 0;
                            }
                            --_v.Context.DamageModifierCount;
                        }

                    while (_v.Context.DamageModifierCount < 0)
                    {
                        modifier_factor *= 0.5f;
                        ++_v.Context.DamageModifierCount;
                    }

                     if ((_v.Target.Flags & CalcFlag.HpAlteration) != 0)
                     {
                        _v.Target.HpDamage = (Int32)Math.Round(modifier_factor * _v.Target.HpDamage);

if ((_v.Target.HpDamage > 9999) && (_v.Target.HpDamage < 15001))
_v.Target.HpDamage = 9999 + (_v.Target.HpDamage - 9999) / 2;
if (_v.Target.HpDamage > 15000)
_v.Target.HpDamage = 12500 + (_v.Target.HpDamage - 15000) / 4;

                        if ((_v.Target.Flags & CalcFlag.HpRecovery) != 0)
                        {
                        _v.Target.HpDamage = btl_para.SetRecover(_v.Target, (UInt32)_v.Target.HpDamage);
            _v.Target.FaceTheEnemy();
                        }
                     }
      }
     }
else
{
_v.CalcPhysicalHpDamage();
}
if (_drain)
_v.Caster.HpDamage = _v.Target.HpDamage;
}
}
}

Sorry if I bother you again, I have no programming experience and maybe I got lost in a trivial problem.

Another question, does this code replaces the "standard" critical hit function? I already tried before to emulate the critical hit function (in a much more basic manner) and I ended with 2 different kind of criticals, one triggered by my function plus the standard *2 one

Thanks again!!

2
Hey Tirlititi,
sorry if I ask your help again.
I'm exploring the possibilities offered by Memoria engine and trying to mod Alternate Fantasy to allow summons + normal attacks with ultimate weapons to break the damage limit, using support abilities as described here: https://github.com/Albeoris/Memoria/wiki/Supporting-ability-features

However, in order to keep some balance I would like to reduce the damage exceeding 9999, actually I used this formula to halve damage between 10.000-15.000 and reduce to 1/4 the damage above 15.000:
Code: [Select]
if ((_v.Target.HpDamage > 9999) && (_v.Target.HpDamage < 15001))
_v.Target.HpDamage = 9999 + (_v.Target.HpDamage - 9999) / 2;
if (_v.Target.HpDamage > 15000)
_v.Target.HpDamage = 12500 + (_v.Target.HpDamage - 15000) / 4;

I made this work by rewriting a part of Memoria SBattlecalculator.cs in Alternate Fantasy Commonscript.cs to bypass the normal CalcPhysicalHpDamage() function. The result is not very linear (I actually haven't a 100% awareness of what I copy-pasted) but actually seems to work as intended without major bugs:

Code: [Select]
using System;
using Memoria.Data;

namespace Memoria.Scripts.Battle
{
public static class CommonScript
{
public const String InfoMessageColor = "[00FFFF]";
public const String GoodMessageColor = "[00FFFF]";
public const String BadMessageColor = "[FF4040]";
}

public abstract class BaseWeaponScript : IBattleScript
{
private readonly BattleCalculator _v;
private readonly CalcAttackBonus _bonus;
private readonly Boolean _drain;

protected BaseWeaponScript(BattleCalculator v, CalcAttackBonus bonus, Boolean drain = false)
{
_v = v;
_bonus = bonus;
_drain = drain;
}

public virtual void Perform()
{
if (_drain && (!_v.IsCasterNotTarget() || !_v.Target.CanBeAttacked()))
return;

_v.PhysicalAccuracy();
if (!_v.TryPhysicalHit())
return;

if (_bonus != CalcAttackBonus.Level)
_v.WeaponPhysicalParams(_bonus);
else
{
Int32 baseDamage = GameRandom.Next16() % (1 + (_v.Caster.Level + _v.Caster.Strength >> 3));
_v.Context.AttackPower = _v.Caster.WeaponPower;
_v.Target.SetPhysicalDefense();
if (_v.Caster.Weapon == (RegularItem)256)
{
_v.Context.AttackPower += 3 * _v.Caster.Level / 4;
if (_v.Target.IsPlayer && _v.Target.PlayerIndex == CharacterId.Garnet)
_v.Target.Flags |= CalcFlag.HpRecovery;
}
else
{
_v.Context.AttackPower += _v.Caster.Level / 2;
}
_v.Context.Attack = _v.Caster.Strength + baseDamage;
}

if (_v.Caster.IsUnderAnyStatus(BattleStatus.Mini))
_v.Context.Attack = 1;
if (_v.Caster.IsUnderAnyStatus(BattleStatus.Berserk))
++_v.Context.DamageModifierCount;
if (_v.Caster.IsUnderAnyStatus(BattleStatus.Trance))
++_v.Context.DamageModifierCount;
if (_v.Target.IsUnderAnyStatus(BattleStatus.Defend))
--_v.Context.DamageModifierCount;
if (_v.Target.IsUnderAnyStatus(BattleStatus.Protect))
--_v.Context.DamageModifierCount;
if (_v.Target.IsUnderAnyStatus(BattleStatus.Sleep))
++_v.Context.DamageModifierCount;
if (_v.Target.IsUnderAnyStatus(BattleStatus.Mini))
++_v.Context.DamageModifierCount;

if (_drain)
_v.PrepareHpDraining();

if (_v.Caster.Weapon == (RegularItem)15) //I still have to add other final weapons
{
          _v.CalcDamageCommon();

          _v.Target.HpDamage = _v.Context.EnsureAttack * _v.Context.EnsurePowerDifference;

                  if (_v.Target.Flags != 0)
                  {
                    Single modifier_factor = 1.0f;
                    Single modifier_bonus = 0.5f;
                    Byte modifier_index = 0;

                        if (_v.Caster.IsUnderAnyStatus(BattleStatus.Trance) && _v.Caster.PlayerIndex == CharacterId.Steiner)
                            modifier_bonus = 1.0f;
                        while (_v.Context.DamageModifierCount > 0)
                        {
                            modifier_factor += modifier_bonus;
                            modifier_index++;
                            if (modifier_index >= 2)
                            {
                                modifier_bonus *= 0.5f;
                                modifier_index = 0;
                            }
                            --_v.Context.DamageModifierCount;
                        }

                    while (_v.Context.DamageModifierCount < 0)
                    {
                        modifier_factor *= 0.5f;
                        ++_v.Context.DamageModifierCount;
                    }

                     if ((_v.Target.Flags & CalcFlag.HpAlteration) != 0)
                     {
                        _v.Target.HpDamage = (Int32)Math.Round(modifier_factor * _v.Target.HpDamage);

if ((_v.Target.HpDamage > 9999) && (_v.Target.HpDamage < 15001))
_v.Target.HpDamage = 9999 + (_v.Target.HpDamage - 9999) / 2;
if (_v.Target.HpDamage > 15000)
_v.Target.HpDamage = 12500 + (_v.Target.HpDamage - 15000) / 4;

                        if ((_v.Target.Flags & CalcFlag.HpRecovery) != 0)
                        {
                        _v.Target.HpDamage = btl_para.SetRecover(_v.Target, (UInt32)_v.Target.HpDamage);
            _v.Target.FaceTheEnemy();
                        }
                     }
      }
     }
else
{
_v.CalcPhysicalHpDamage();
}
if (_drain)
_v.Caster.HpDamage = _v.Target.HpDamage;
}
}
}


However I couldn't find a way to handle critical strikes, which double the final damage regardless of my efforts.
Commonscript.cs of Alternate fantasy doesn't contain a call for the "_v.TryCriticalHit()" function, unlike vanilla "baseweaponscript.cs", that is only coded in SBattleCalculator.cs and seems to be applied after the damage calculation (if I end my function setting targethpdamage to a fix "100", a critical strike inflicts "200" damage).
What I would like to do is to calculate the *2 damage of critical hits before my damage reduction formula, so that a 5000x2 critical is handled normally but a 10000x2 one deals way lesser damage.

There is any way to do this?
A BIG thank you in advance  :)

3
Ok, I'm happy if it is not a known issue, maybe I only messed up something while modding, I'll do some check.

Thanks again Tirliti!!

4
Thanks!!! Works great
I used your code to make a double-hit, multi target ability for Steiner. I added a check to prevent him from hitting again an enemy already killed by the first strike, and made minor tweaks like playing the victory animation at start.
The result is quite funny, especially when using custom flags to allow criticals  8)


Code: [Select]
WaitAnimation: Char=Caster
Message: Text=[CastName] ; Priority=1 ; Title=True ; Reflect=True
SetupReflect: Delay=SFXLoaded
SetBackgroundIntensity: Intensity=0.5 ; Time=4 ; HoldDuration=50
Wait: Time=30
PlayAnimation: Char=Caster ; Anim=MP_WIN
WaitAnimation: Char=Caster
WaitTurn: Char=Caster
StartThread: TargetLoop ; Chain ; Sync
LoadSFX: SFX=Iai_Strike_1 ; Target=AllTargets ; Reflect=True ; UseCamera=False
MoveToTarget: Char=Caster ; Target=AllTargets ; Distance=670 ; UseCollisionRadius=True ; Anim=MP_RUN
Turn: Char=Caster ; BaseAngle=AllTargets ; Time=4
WaitMove: Char=Caster
MoveToTarget: Char=Caster ; Target=AllTargets ; Distance=400 ; UseCollisionRadius=True ; Anim=MP_RUN_TO_ATTACK
WaitMove: Char=Caster
StartThread
Wait: Time=4
WaitSFXLoaded: SFX=Iai_Strike_1
PlaySFX: SFX=Iai_Strike_1
WaitSFXDone: SFX=Iai_Strike_1
EndThread
PlayAnimation: Char=Caster ; Anim=MP_ATTACK
WaitAnimation: Char=Caster
MoveToTarget: Char=Caster ; Target=AllTargets ; Distance=-200 ; UseCollisionRadius=True ; Time=0
MoveToTarget: Char=Caster ; Target=AllTargets ; Distance=500 ; UseCollisionRadius=True ; Anim=MP_STEP_BACK
WaitMove: Char=Caster
EndThread
StartThread: TargetLoop ; Chain ; Sync
StartThread: Condition=TargetHP != 0 ; Sync
LoadSFX: SFX=Iai_Strike_1 ; Target=AllTargets ; Reflect=True ; UseCamera=False
MoveToTarget: Char=Caster ; Target=AllTargets ; Distance=670 ; UseCollisionRadius=True ; Anim=MP_RUN
Turn: Char=Caster ; BaseAngle=AllTargets ; Time=4
WaitMove: Char=Caster
MoveToTarget: Char=Caster ; Target=AllTargets ; Distance=400 ; UseCollisionRadius=True ; Anim=MP_RUN_TO_ATTACK
WaitMove: Char=Caster
StartThread
Wait: Time=4
WaitSFXLoaded: SFX=Iai_Strike_1
PlaySFX: SFX=Iai_Strike_1
WaitSFXDone: SFX=Iai_Strike_1
EndThread
PlayAnimation: Char=Caster ; Anim=MP_ATTACK
WaitAnimation: Char=Caster
MoveToTarget: Char=Caster ; Target=AllTargets ; Distance=-200 ; UseCollisionRadius=True ; Time=0
MoveToTarget: Char=Caster ; Target=AllTargets ; Distance=500 ; UseCollisionRadius=True ; Anim=MP_STEP_BACK
WaitMove: Char=Caster
EndThread
EndThread
SetBackgroundIntensity: Intensity=1 ; Time=8
MoveToPosition: Char=Caster ; AbsolutePosition=Default ; Anim=MP_BACK
Turn: Char=Caster ; BaseAngle=Default ; Time=4
WaitMove: Caster
PlayAnimation: Char=Caster ; Anim=Idle
WaitTurn: Char=Caster
ActivateReflect
WaitReflect


There is just an issue. I tested this spell against Yans and noticed that after getting hit twice they countered with Float against themselves. I remember that this bug may happen when an enemy able to counterattack gets hit by a double damaging spell, right? There is now a way to fix that, other than disabling counterattacks for the specific spell I made?
I tried to activate CountersBetterTarget in Memoria.ini with no result

5
Thanks! Yes, this is very similar to what I had in mind (even the same animation!).

I tested and worked perfectly for a single target. I'm trying now to edit the sequence to make a multi-target spell, in my intentions the character should be able to hit once (or maybe twice) every enemy, one-by-one. The main obstacle is that I have zero programming knowledge  ;D
I tried to edit the sequence as follows:

Code: [Select]
/ Player sequence of SFX Iai_Strike_2
// Used by Zidane (Windfall with a dagger)

WaitAnimation: Char=Caster
Message: Text=[CastName] ; Priority=1 ; Title=True ; Reflect=True
SetupReflect: Delay=SFXLoaded
LoadSFX: SFX=Iai_Strike_1 ; Reflect=True ; UseCamera=False
PlayAnimation: Char=Caster ; Anim=MP_SET
WaitAnimation: Char=Caster
MoveToTarget: Char=Caster ; Target=FirstTarget ; Distance=670 ; UseCollisionRadius=True ; Anim=MP_RUN
Turn: Char=Caster ; BaseAngle=FirstTarget ; Time=4
WaitMove: Char=Caster
MoveToTarget: Char=Caster ; Target=FirstTarget ; Distance=400 ; UseCollisionRadius=True ; Anim=MP_RUN_TO_ATTACK
WaitMove: Char=Caster
StartThread
Wait: Time=4
WaitSFXLoaded: SFX=Iai_Strike_1
PlaySFX: SFX=Iai_Strike_1
WaitSFXDone: SFX=Iai_Strike_1
EndThread
PlayAnimation: Char=Caster ; Anim=MP_ATTACK
WaitAnimation: Char=Caster
MoveToTarget: Char=Caster ; Target=FirstTarget ; Distance=-200 ; UseCollisionRadius=True ; Time=0
MoveToTarget: Char=Caster ; Target=FirstTarget ; Distance=1100 ; UseCollisionRadius=True ; Anim=MP_STEP_BACK
WaitMove: Char=Caster
MoveToTarget: Char=Caster ; Target=SecondTarget ; Distance=670 ; UseCollisionRadius=True ; Anim=MP_RUN
Turn: Char=Caster ; BaseAngle=SecondTarget ; Time=4
WaitMove: Char=Caster
MoveToTarget: Char=Caster ; Target=SecondTarget ; Distance=400 ; UseCollisionRadius=True ; Anim=MP_RUN_TO_ATTACK
WaitMove: Char=Caster
StartThread
Wait: Time=4
WaitSFXLoaded: SFX=Iai_Strike_1
PlaySFX: SFX=Iai_Strike_1
WaitSFXDone: SFX=Iai_Strike_1
EndThread
PlayAnimation: Char=Caster ; Anim=MP_ATTACK
WaitAnimation: Char=Caster
MoveToTarget: Char=Caster ; Target=SecondTarget ; Distance=-200 ; UseCollisionRadius=True ; Time=0
MoveToTarget: Char=Caster ; Target=SecondTarget ; Distance=1100 ; UseCollisionRadius=True ; Anim=MP_STEP_BACK
WaitMove: Char=Caster
MoveToTarget: Char=Caster ; Target=ThirdTarget ; Distance=670 ; UseCollisionRadius=True ; Anim=MP_RUN
Turn: Char=Caster ; BaseAngle=ThirdTarget ; Time=4
WaitMove: Char=Caster
MoveToTarget: Char=Caster ; Target=ThirdTarget ; Distance=400 ; UseCollisionRadius=True ; Anim=MP_RUN_TO_ATTACK
WaitMove: Char=Caster
StartThread
Wait: Time=4
WaitSFXLoaded: SFX=Iai_Strike_1
PlaySFX: SFX=Iai_Strike_1
WaitSFXDone: SFX=Iai_Strike_1
EndThread
PlayAnimation: Char=Caster ; Anim=MP_ATTACK
WaitAnimation: Char=Caster
MoveToTarget: Char=Caster ; Target=ThirdTarget ; Distance=-200 ; UseCollisionRadius=True ; Time=0
MoveToTarget: Char=Caster ; Target=ThirdTarget ; Distance=1100 ; UseCollisionRadius=True ; Anim=MP_STEP_BACK
WaitMove: Char=Caster
MoveToTarget: Char=Caster ; Target=FourthTarget ; Distance=670 ; UseCollisionRadius=True ; Anim=MP_RUN
Turn: Char=Caster ; BaseAngle=FourthTarget ; Time=4
WaitMove: Char=Caster
MoveToTarget: Char=Caster ; Target=FourthTarget ; Distance=400 ; UseCollisionRadius=True ; Anim=MP_RUN_TO_ATTACK
WaitMove: Char=Caster
StartThread
Wait: Time=4
WaitSFXLoaded: SFX=Iai_Strike_1
PlaySFX: SFX=Iai_Strike_1
WaitSFXDone: SFX=Iai_Strike_1
EndThread
PlayAnimation: Char=Caster ; Anim=MP_ATTACK
WaitAnimation: Char=Caster
MoveToPosition: Char=Caster ; AbsolutePosition=Default ; Anim=MP_BACK
Turn: Char=Caster ; BaseAngle=Default ; Time=4
WaitMove: Caster
PlayAnimation: Char=Caster ; Anim=Idle
WaitTurn: Char=Caster
ActivateReflect
WaitReflect

However this code makes Steiner hit always 4 times (even if there are <4 enemies), furthermore the damage is dealt to all the enemies with every hit. I've checked the Memoria's wiki u linked, but I'm still not sure of how can I fix this (maybe I need a target loop thread?).

Thanks in advance for your suggestions and your time!!

6
Back to Hades Workshop after a long time  :) Nice to see that FF9 modding is still active!
Congratulations Tirlititi for your wonderful work!

If it were possible I would like to ask for an help. My goal is to create a multi-hit skill for Steiner or Zidane, inspired from limit breaks of previous FF games. The character shoud run towards target (or targets), hit with multiple sword attacks (dealing and displaying damage with every single hit) and then come back. I tried to edit the spell sequencing using Iai strike for animations, but the result was a mess. I am not able to make Steiner run towards the 2nd target after the first damage point and before jumping back (maybe I need to insert some of the unknow instructions like 0x50., 0x71?). It is possible to make a skill like what I intend to do? Is it the only way to do that?
Thanks in advance!

7
Thanks! I didn't realized that != is "not equal to.." sorry    :-D I've seen Gizamaluke AI, now is a bit more clear for me how counter system works.

Another question, what exactly is the function of the "Short" flag in the AI attack forms?

8
Tirlititi, I have some more questions, this time about AI script:

Some enemies, for example Yans, can counterattack to many different kind of attacks (simple physical attacks, black/white/blue magics, steal...) but, in their counter function, only the following party command/attack are checked:

    if ( ( GetAttackCommandId == 25 ) && ( GetAttackId == 103 ) ) {
        return
    }

Which should be Zidane "skill" command  and "what's that?!" ability, according to description. However Yans can counter also to normal attacks (for example) which should be the not mentioned "commandid = 1" .
For example, Nova Dragon counters to "attack" command and this is the relative script:
    if ( GetAttackCommandId != 1 ) {
        return
    }
    set #( SV_Target = GetAttacker )
    Attack( 0 )
    return

I am missing something? To make an enemy counterattack to many different party action is it not necessary to list them all, one by one?



Another question: can I declare a completely new local variable without replacing an existing one?
I want to make an enemy cast the "A" attack only if the "B" attack has already been executed, so I need to declare a variable which turns to 1 after "B" is selected, and if this variable is not 1  and "A" is selected, "B" is casted in place of "A".
But if I  simple write "set isBexecuted == 0" at the beginning of the function the system doesn't recognize the variable.

How can I fix that? What is the right way to declare a new variable? And if replacing an already existing variable is mandatory, is there a list of completely unused variables?

Thanks in advance!

9
However it is indeed possible to increase the Regen frequency, with both HW and Memoria. In HW, you go to CIL Code, search for the method "btl_stat -> SetOprStatusCount" and remove that part of the code:
Code: [Select]
ldarg.0
ldfld 0x400022A // BTL_DATA::elem
ldfld 0x400080F // ELEMENT::wpr
sub
It's the four lines under a "ldc.i4.s 60". The Regen frequency formula is indeed "Frames to wait = (60 - wpr) << 2", which is, in a more standard writing, "(60 - Spirit) * 4". Removing these four lines will remove the spirit part so you will always regen with the same frequency (the overall duration is something else and will still increase though). You may change the number in "ldc.i4.s 60" to adjust it if you think it's too slow (or too fast).

Got Steam version and tested, it worked perfectly! Thanks, as usual.
Do you know if changing this CIL code entry could mess up something else? Or this lines affects only the Regen effect?
I have made a bit of testing but didn't seen any other alteration for now.

10
I've just googled around and it seems no one knows the reason for the indeed much lower encounter rate of the steam version. Damn, that's an even bigger bummer to my plans. So the only option is to manually go through each field and increase the encounter rate to somehow restore the battle frequency of the original PSX game (more or less)? That'll be quite tedious, but I guess there's no way around it if I don't want to remain constantly underleveled.


Hi Tirliti, I have the same question of Kefka. Actually the only way to increase random battle encounter is to manually edit all fields with a random battle?

I've seen the code you posted on GameFaqs:

if (sMoveKey && !IsNearlyZero(DistanceFromLastFramePos)) {
. . sEncountTimer += DistanceFromLastFramePos * FieldWorldMapFactor;
. . if (!Cheat.IsNoEncounter && usercontrol != 0 && sEncountTimer > 960) {
. . . . sEncountTimer = 0f;
. . . . sEncountBase += encratio;
. . . . if (random8() < sEncountBase/8) {
. . . . . . sEncountBase = 0;
. . . . . . TriggerRandomBattle();
. . . . }
. . }
}

Could the problem be fixed by editing this code? And if so, how I can do this?

11
Thanks Tirlititi. I use PSX version of FF9, no way to edit this script for psx? I know that CIL code editing is available only for Steam Version.

Another question, is it possibile to increase enemies speed above 50 (for more competitive fights when 4 vs 1 enemy)? Or bugs may occurr, as you said above regarding Spirit?

12
Hi!

Still no way to stop ATB filling during animations? Actually the system the ATB work causes all status to be quite ineffective (too short duration) with high Spirit, and Regen to be horribly overpowered. No Way to fix this?

If fixing this is not possibile, it is possibile at least to manually increase the Regen healing interval?

Thanks in advance

13
Great!! Now i'll test it. Thank you for your detailed answer.

I'm planning to do some balance changes to make the game more challenging. The only defect of this game is that's too easy, in particular in the late game.


14
Hello!!  :)

First of all: thank you for your awesome work. FF9 is my favourite game, and I always dreamed the possibility to mod it!
When I firt saw this post, I can't believe it. Thanks

I really would ask a question to modders more experienced than me: it's possible to make a script that allows a boss to refill his Health Point when they are low? I know that the HP hard limit of 65535 cannot be exceeded. But if it were possible to make a script that refill (for example) Kuja Trance HP when they go under 10.000, and to do this thing for a limited number of time, the problem of max HP can be bypassed.

For example, we can declare a variable X. X start value (at the beginning of the fight) has to be 1.
When during the battle the boss HP go lower than 10.000, the boss refill his HP to the full value and X becomes 2.
And so on, until X reach a default value (for example 10) and the script interrupts.

I have no experience in programming except very little of Visual Basic 6. So I may wrote only stupid things.

I ask the question to coders more skilled than me. Is it possible? We can have a Kuja Trance, Ozma, Hades with virtually unlimited HP, for very challenging fights!

Pages: [1]