[PSX/PC] General editor - Hades Workshop (0.50b)

  • Thread starter Thread starter Tirlititi
  • Start date Start date
Status
Not open for further replies.
This is what i came up with for Jump. A physical strike (thinking of atk mul of 1.3) that is boosted by Trance, Berserk, and by High jump (by 1.5 just like throw) and takes the element of the weapon. Funny how Freya's Jump actually became weaker with Trance despite being its main focus.

Code: [Select]
Code:
  case 48:  case 83:   btl_calc.CalcSub_13A(calc_VAR);   btl_calc.CalcSub_141(calc_VAR);   btl_calc.CalcSub_143(calc_VAR);   btl_calc.CalcSub_151(calc_VAR);   if ((caster.sa[0] & 2097152U) != 0U)   {    calc_VAR.at_num = (short)(calc_VAR.at_num * 3 >> 1);   }   if (prog_no == 48)   {    if (btl_calc.CalcSub_152(calc_VAR))    {     btl_calc.CalcSub_203(calc_VAR);    }   }   else   {    if (btl_calc.CalcSub_152(calc_VAR))    {     int num14;     if ((num14 = (int)(calc_VAR.at_pow - calc_VAR.df_pow)) <= 0)     {      num14 = 1;     }     CALC_VAR calc_VAR33 = calc_VAR;     calc_VAR33.tg_flags |= 1;     if (calc_VAR.at_num < 4)     {      calc_VAR.at_num = 4;     }     int num15 = (int)((long)(num14 * (int)calc_VAR.at_num) / (long)((ulong)btl_util.SumOfTarget(0U)));     if (num15 > 9999)     {      num15 = 9999;     }     if ((calc_VAR.flags & 8) != 0)     {      calc_VAR.tg_flags |= 2;     }     calc_VAR.tg_hp = (short)num15;    }   }   break;
Also i want you to look at this 2 lines of case 19, Physical Strike:
Code: [Select]
Code:
   btl_calc.ApplySpellElementBoost(calc_VAR);   if (btl_calc.ApplyWeapElement(calc_VAR))   { [...] }
Dunno if elemental physical strikes exist, but doesn't this mean that the spell uses the element of the weapon for the sake of weaknesses/freeze/heat whatever and the element of the SPELL (not the weapon) for the sake of elm. boost alone?

Aka, an Excalibur II powered Shock will deal improved damage agains enemies weak to holy, BUT non-boosted damage if Steiner is equipped to boost Holy. But if we make Shock, dunno... Fire-elemental, Shock will deal improved damage against enemies weak to Holy (Excalibur II) AND if equipped to boost Fire.

Sounds like an oversight to me, like the first line should be ApplyWeapElementBoost instead of ApplySpellElementBoost.
 
Last edited:
Dunno if elemental physical strikes exist, but doesn't this mean that the spell uses the element of the weapon for the sake of weaknesses/freeze/heat whatever and the element of the SPELL (not the weapon) for the sake of elm. boost alone?
Yes exactly. Not sure if it's an oversight or anything, but that's indeed how it works.
 
https://imgur.com/a/WvbXtHI

I've noticed this minor issue in the equipment UI. With dnSpy i found the code portion that handles this section (EquipUI, mostly within DisplayParameter), but there's code for everything bar positioning (the ones that activate it, ArrowTween for the flashing of the arrow, colors...).

Dunno if a vector with absolute values exists somewhere or if there's an iterator that's supposed to align those numbers either.
 
The positions of UI elements are stored in one of the archives (I don't remember which one though) as Unity serialized objects ("Transform", "GameObject", etc...). I don't know of any tool that would display/mod them nicely but it may exist since it's Unity's format.

Inside the code, you can use lines like that one to change things.
Code: [Select]
Code:
// I think this was a working example for BattleUIthis.CommandPanel.GetComponent<UIWidget>().GetChild(0).GetComponent<UIWidget>().SetRect( X, Y, W, H );// ... or lines like thisthis.CommandPanel.transform.localPosition = new Vector3( X, Y, this.CommandPanel.transform.localPosition.z );
But ask TehMighty because he worked a lot on UI and succeeded in having great results.
 
Thanks again Tirlititi!

The transform.localPosition worked somehow, but the best result i managed to achieve is fixing the position every time but one: the very first time it's displayed after a reset it's in the wrong position (x=288 instead of 292). I asked TehMighty just now cause maybe a more permanent solution (finding the actual transform file related to that) is needed.
 
It's not currently possible Xenogears, unfortunatly. That's indeed a problem with the widescreen mode: background pictures have a size adjusted to the screen mode used in the PSX version. These backgrounds have not been extended for the PC port (it would have been a huge work).

What might be done to fix some of these problems is to reduce the camera bounds. It can be done in HW for each field script 1 by 1 but it would be much better to do it with dnSpy/source code modding.

It wouldn't fix many fields, like Observatory Mountain's fields.
 
Reporting back after talking with TehMighty, in case you're interested.

The "Spirit value x position bug" is fixed by creating a new class inside EquipUI, like this.

Code: [Select]
Code:
    public class FixSpiritSkillNumberLabelPos : MonoBehaviour    {        void Start()        {            transform.localPosition = Vector2.right * 292;        }        void OnEnable()        {            transform.localPosition = Vector2.right * 292;        }    }
And using it inside ParameterDetailCompareHUD, like this:

Code: [Select]
Code:
public class ParameterDetailCompareHUD    {        public ParameterDetailCompareHUD(GameObject go)        {            this.Self = go;            Int32 i = 0;            Int32 num = 0;            while (i < 10)            {                if (i != 4)                {                    this.ParameterLabel[num] = go.GetChild(i).GetChild(1).GetComponent<UILabel>();                    this.NewParameterLabel[num] = go.GetChild(i).GetChild(3).GetComponent<UILabel>();                    this.ArrowSprite[num] = go.GetChild(i).GetChild(2).GetComponent<UISprite>();                    this.ArrowTween[num] = go.GetChild(i).GetChild(2).GetComponent<TweenAlpha>();                    num++;                }                i++;            }            //This is the added line of code            NewParameterLabel[3].gameObject.AddComponent<FixSpiritSkillNumberLabelPos>();        }        public GameObject Self;        [...]    }
Another minor graphical bug i discovered involves the "Remove Equipment" submenu. Parameter changes aren't displayed for the very first piece of equipment the arrow points to, but only after to press up or down to switch to another one. Fixed by adding this.DisplayParameter() here:

Code: [Select]
Code:
 public override bool OnKeyConfirm(GameObject go) {  bool flag2 = base.OnKeyConfirm(go);  if (flag2)  {   bool flag3 = ButtonGroupState.ActiveGroup == EquipUI.SubMenuGroupButton;   if (flag3)   {    this.currentMenu = this.GetSubMenuFromGameObject(go);    switch (this.currentMenu)    {    case EquipUI.SubMenu.Equip:    case EquipUI.SubMenu.Off:     FF9Sfx.FF9SFX_Play(103);     ButtonGroupState.ActiveGroup = EquipUI.EquipmentGroupButton;     ButtonGroupState.SetSecondaryOnGroup(EquipUI.SubMenuGroupButton);     ButtonGroupState.HoldActiveStateOnGroup(EquipUI.SubMenuGroupButton);     this.DisplaySubMenuArrow(false);     this.DisplayEquiptmentInfo();     // Line added here     this.DisplayParameter();     break;    case EquipUI.SubMenu.Optimize:    [...]
 
It's not currently possible Xenogears, unfortunatly. That's indeed a problem with the widescreen mode: background pictures have a size adjusted to the screen mode used in the PSX version. These backgrounds have not been extended for the PC port (it would have been a huge work).

What might be done to fix some of these problems is to reduce the camera bounds. It can be done in HW for each field script 1 by 1 but it would be much better to do it with dnSpy/source code modding.

It wouldn't fix many fields, like Observatory Mountain's fields.
Hi, I already used the dnSpy program somehow, but I still need to find where to write all this. Albeoris told me that somewhere there are lines

public static Boolean IsNarrowMap()
    {
        switch (FF9StateSystem.Common.FF9.fldMapNo)
        {
            case 0052: // Prima Vista - Meeting Room
            case 0455: // Mountain - Base
            case 1507: // Conde Petie - Pathway
            case 1605: // Madain Sari - Eidolon Wall
            case 1606: // Madain Sari - Chamber
            case 1607: // Madain Sari - Kitchen
            case 1807: // Alexandira Castle - Hallway
            case 1823: // Alexandira Castle - Hallway
            case 2000: // Hilda Garde 2 - Deck
            case 2007: // Alexandira Castle - Altar
            case 2204: // Desert Palace - Odessey
            case 2208: // Desert Palace - Hallway
            case 2261: // Oeilvert - Bridge
            case 2363: // Gulug - Path
            case 2510: // Iifa Tree - Silver Dragon
            //case 3009: // Ending - TH
            //case 3010: // Ending - TH
            //case 3011: // Ending - TH
                return true;
        }
        return false;
    }

I managed. But now I do not know how to return the location to its original state after their conversation.
 
Last edited:
Thanks Caledor.

@Xenogears: I don't understand what you mean. What did Albeoris tell you about these lines? What conversation (conversion?) are you talking about? What did you managed to do?
 
Hello everyone !

I am very curious how work modding with FFIX and that's why i decide to test HW !
However... i am big newbie with it  :roll: (never use C# on my life lol but i can learn... i think)

For my first experience, i add BigDragon on Evil Forest first zone (light clearing).... yeah, pretty brutal.

I follow theses steps on "Properly adding a new enemy to a battle (Steam)"
Dragon is present with Goblin and Fang, can attack Zidane but i have two issues :

- Dragon is called "Lame" (mean Knife in FR)
- All attacks from Dragon, Goblin and Fang display wrongly : sometimes there's is nothing (text box is empty), or None (EN)/Rien (FR) showed or EnnemyDummy for Dragon



As i said, i follow all steps from Tirlititi, use simply IA for Dragon (with 2/3 DragonClaw and 1/3 Thundaga), compare with other battles....
I didn't edit attacks and IA from Goblin and Fang and i copy all Dragon attacks from his original battle.
After few hours of testing... i am lost.

I am asking your help... i think i am dumb to find why it's broken ;D


Function Main_Init
    switch 2 ( GetBattleGroupId ) from 0 {
    case +0:
        InitObject( 2, 128 )
        InitObject( 3, 129 )
        break
    case +1:
        InitObject( 1, 128 )
        InitObject( 3, 129 )
        break
    }
    return


Function Big_Dragon_Init
    return


Function Big_Dragon_ATB
    if ( GetRandom % 3 ) {
        set SV_Target = RandomInTeam(SV_PlayerTeam)
        Attack( 6 )
        return
    }
    set SV_Target = SV_PlayerTeam
    Attack( 9 )
    return
 
Last edited:
Hello everyone !

I am very curious how work modding with FFIX and that's why i decide to test HW !
However... i am big newbie with it  :roll: (never use C# on my life lol but i can learn... i think)

For my first experience, i add BigDragon on Evil Forest first zone (light clearing).... yeah, pretty brutal.

I follow theses steps on "Properly adding a new enemy to a battle (Steam)"
Dragon is present with Goblin and Fang, can attack Zidane but i have two issues :

- Dragon is called "Lame" (mean Knife in FR)
- All attacks from Dragon, Goblin and Fang display wrongly : sometimes there's is nothing (text box is empty), or None (EN)/Rien (FR) showed or EnnemyDummy for Dragon



As i said, i follow all steps from Tirlititi, use simply IA for Dragon (with 2/3 DragonClaw and 1/3 Thundaga), compare with other battles....
I didn't edit attacks and IA from Goblin and Fang and i copy all Dragon attacks from his original battle.
After few hours of testing... i am lost.

I am asking your help... i think i am dumb to find why it's broken ;D


Function Main_Init
    switch 2 ( GetBattleGroupId ) from 0 {
    case +0:
        InitObject( 2, 128 )
        InitObject( 3, 129 )
        break
    case +1:
        InitObject( 1, 128 )
        InitObject( 3, 129 )
        break
    }
    return


Function Big_Dragon_Init
    return


Function Big_Dragon_ATB
    if ( GetRandom % 3 ) {
        set SV_Target = RandomInTeam(SV_PlayerTeam)
        Attack( 6 )
        return
    }
    set SV_Target = SV_PlayerTeam
    Attack( 9 )
    return
EDIT : Ok so i found why that didn't work.
1) I am dumb
2) I forget to copy ressources.assets from HW... I thought only p0data files store data combat but i was wrong...

Sorry for this useless post :D
 
Fiou, thank you for telling me that you fixed it. I was thinking that there would be a bug with the copy/paste of enemies or abilities (there used the be some bugs with the same kind of effect as you had but I think it is fixed now).

Indeed, the resources.assets contains pretty much all the texts of the game among other things.
 
hello could you tell me why it doesn't open the p0data2.bin file of the mogouri mod?
 
Hi everyone,

I want to edit completely Focus and i see you can edit that with CIL or dnSpy... but i have 2 questions :

- First, with Tirlititi's files on dropbox, i find some informations about Focus on Source_btlCalc.cs.
So i found this code on btlCalc with dnSpy

Code: [Select]
Code:
case 44:  {   ELEMENT elem2 = target.elem;   if ((elem2.mgc += target.elem.mgc / cmd.aa.Ref.power) > 99)   {    target.elem.mgc = 99;   }   break;  }
But this code only prevent to exceed 99 of magic... no ? If i need to totally change how works Focus, i need to edit this or something else ?

- I never use DnSpy before : i want to edit btl_calc for example but when i compile files, i get a lot of error about some missing method System.UIInt16, System.Object, System.Byte, System.Void, ect...


1587265834-dnspy.png


How fix that ? ...  :-[

Thanks you in advance !
 
Hello DV,
Well, for your first question: this code actually adds magic to the targets and is not only about capping it to 99, although that's not so obvious (even for people that are a bit used to coding).
Code: [Select]
Code:
if ((elem2.mgc += target.elem.mgc / cmd.aa.Ref.power) > 99)
There's a "+=" operation there, which adds things but also return the value of "elem2.mgc" after it was updated for a comparison with "99".
You can read that line as this instead, for clarity:
Code: [Select]
Code:
elem2.mgc += target.elem.mgc / cmd.aa.Ref.power;if (elem2.mgc > 99)
The errors you get with dnSpy means that, for some reason, dnSpy doesn't have access to a proper "System.dll"... which is strange because it should be right there, next to the "Assembly-CSharp.dll" that you opened.
Check the list of DLLs that dnSpy opened on the left of the window, it might be that dnSpy opened automatically two different "System.dll", one of which being so dull that it doesn't even define basic types... if that's the case, right-click on the duplicate(s) (the one(s) that are not located inside FF9's game folder) and remove them ("Remove System.dll"; don't worry, it only removes it from dnSpy, it doesn't delete the file from the disc).

That being said, you'll surely have more errors when that one will be fixed. A tedious error that dnSpy gives is "Cannot implicitly convert type '[Type A]' to '[Type B]'. An explicit conversion exists (are you missing a cast?)". Everytime this error appears, you need to add explicitly a cast to [Type B]... and dnSpy just immediatly forgets about it after compilation, such that when you edit the method/class a second time, these errors reappear.

I just updated the class "blt_calc" in my dropbox in order to have a proper compilable code in dnSpy (and added readability things). You can copy/paste the whole class from there and do the changes on that copy: it won't trigger the conversion errors described above.
 
Last edited:
Thank you again for his answer Tirlititi !

....
*after few hours*
Me :
doing.jpg


I can now compile new code with your btl_calc class... but i didn't understand something : which Assembly-CSharp.dll I need to edit ?

Maybe i forget to mention that but i use Moguri Mod : when i patch it, Assembly-CSharp.dll is totally different from NMM used with HW : i can't find btl_calc on this .dll patched by Moguri...

Btl_calc is available on Assembly-CSharp.dll from NMM but how i can replace modifications added ? (can't replace .dll otherwise, game have some troubles lol)

I am a little lost ^^
 
Sorry for double post, i can't edit my previous message (don't know why  :-\).

After an entire night searching about that, i finally find : i complety forget Memoria use scripts to edit various things.

But Memoria.compiler didn't work on my side (can't find files location, something like else). What a pain lol

So, i use Dnspy to edit Memoria.scripts.dll directly and finally, i can modify Focus and all !

Thanks again Tirlititi for pointing me in the right direction : I hope I hold all the cards this time :)
 
Ah, indeed, sorry ^^"

The Moguri mod changes that part of the DLL a lot, yes.
So, you need to modify the Assembly-CSharp.dll that is used by the game, which should be Moguri's DLL. But then, you also need to change C# code that is externalized inside simple text files.
The content of the class "btl_calc" in Memoria is splitted at two places:

(1) Pretty much all the methods except "CalcMain" were transported to the following classes that you can access using dnSpy: "Memoria.BattleCalculator" (ie. "BattleCalculator" inside the folder "Memoria"), "Memoria.BattleUnit", "Memoria.BattleTarget" and "Memoria.BattleEnemy". They have different names and are reorganized, but they serve the same purposes (for instance, the method "Memoria.BattleCalculator.WeaponPhisicalParams" (sic) in Moguri's DLL is similar to "btl_calc.SetupBaseAttack8" in the "Source_BtlCalc.cs" that I provided).

(2) What should have most interest for you: the main method, "CalcMain", that contains the bone structure of spell effects, is written in the .cs files that are inside the folder "StreamingAssets\Scripts\Sources\Battle". The names of the files start with the same numbers as the "case" number inside the "Source_BtlCalc.cs" that I provided (for instance, the "case 9: // Magic Attack" is in the file "0009_MagicAttackScript.cs"; Albeoris and I didn't always use the same names but it shouldn't be to hard to go from one to the other).

For these other files, you don't need dnSpy a priori. Albeoris made it so you can simply change the scripts using a text editor but it comes with costs...
- It's not obvious of what methods you can use in these text files. If it's not something too complicated, you can copy/paste things from different scripts to get what you want. For a complete list of methods, you have to check the methods in (1) using dnSpy though.
- Editing the script files is not enough: you need to compile them afterwards in order to generate a "Memoria.Scripts.dll". That can be done, hopefully with no error, by running the program "Memoria.Compiler.exe" that is found inside "StreamingAssets\Scripts\Compiler". Running that program either generate a "Memoria.Scripts.dll" or display errors.
- Now, with the Moguri mod, there's a new layer of difficulty: you see, the program "Memoria.Compiler.exe" will read the scripts that are inside the folder "..\Sources\Battle" relative to the compiler's path and also need the DLLs from the folder "..\..\..\x64\FF9_Data\Managed" relative to the compiler's path. That means that you need to do the changes on "Assembly-CSharp.dll" before running the Memoria compiler in order to have compatible DLLs, change the script text files and run the Memoria compiler that are inside the game's folder. But once this is done and you have a proper "Memoria.Scripts.dll", you need to move that DLL to the Moguri's folder where there are a lot of duplicates and where the game modded by the Moguri mod go fetch the files inside a "StreamingAssets" subfolder.

This last difficulty, I think, comes from the fact that Albeoris did something quite obscure for making battle scripts more easily moddable when he did his tool "Memoria". But then, Ze_PilOt used the tool "Memoria" to do his Moguri mod and didn't get what that "Memoria.Scripts.dll" was and thus his mod duplicates it and moves it to another folder without realising that it doesn't fit Albeoris's way of doing things.

Congrats if you've read and understood this far!
I guess that HW is not such a difficult tool to use, right? :p


EDIT: One last things. Albeoris also added a "Spell rate" feature: apart from the method "Perform" that you can find in the battle scripts, you sometimes have a method "RateTarget" that returns a Single (number) and is added when the class derivates from "IEstimateBattleScript". This method is meant to somehow measure the usefulness of an ability in a given situation. I am not sure if that feature is working (maybe it is used when the player turns Auto-battle on?) though, and you can ignore it if you don't care.
 
Last edited:
Status
Not open for further replies.
Back
Top