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 - Tirlititi

Pages: [1] 2 3 ... 25
1
Update to v0.41c:
- Added script file batch importing: you can now write script functions with your favorite text editor and import it back when you're done,
- Fixed bugs with text and UI text batch importation; also, the text IDs now start from 0 instead of 1 in the exported batches (so they match with the text ID inside scripts),
- Added more unused/dummied datas (for enemies mainly) that can be recycled when modifying the game's source code; also added enemy attack targetting informations (they are mostly unused, except for deciding if Cover triggers if I'm not mistaken),
- Listed more script functions and general variables in the script editor,
- Fixed a bug with Qu's Marsh's dialogs (it was actually caused by a "mobile" version of the dialogs; I think it's unused),
- In the Randomizer, the Prison Cages' "Absorb" spell is not randomized anymore,
- Fixed another bug with spell animation sequencing.

I am retiring from FF9 modding (presumably definitively). I don't think that I'll update this tool any further. The code is on Github though and I'll still answer questions, so here you go.

2
At some point, I wanted to register the local variables of the Hot & Cold scripts but it is quite a big system and that work went on standby...
The main function (the one deciding the reward at least) is "Barrel_41" in the Chocobo Forest, "Barrel_38" in the Lagoon and "Barrel_46" in Air Garden. It's always the same. Here is that function with most of variables given a name.

The part you're interested in is close to the top of the function:
Code: [Select]
            switch 3 ( Chocobo_ChocoColor ) from 1 {
            case +0:
                if ( Hot&ColdField == 1 ) {
                    set ChocographAvailableList |= 8 // 4th Chocograph (Yellow to Light Blue)
                    set ChocographLastAvailableFlag = 1
                }
                break
            case +1:
                if ( ( Hot&ColdField == 2 ) && ( Global_ScenarioCounter >= 9400 ) ) {
                    set ChocographAvailableList |= 2048 // 12th Chocograph (Light Blue to Red)
                    set ChocographLastAvailableFlag = 1
                }
                break
            case +2:
                if ( ( Hot&ColdField == 1 ) && ( Global_ScenarioCounter >= 9400 ) ) {
                    set ChocographAvailableList |= 8192 // 14th Chocograph (Red to Deep Blue)
                    set ChocographLastAvailableFlag = 1
                }
                break
            default:
                set ChocographLastAvailableFlag = 0
                break
            }
Without renamed variables (as it appears in Hades Workshop), it's this part:
Code: [Select]
            switch 3 ( Chocobo_ChocoColor ) from 1 {
            case +0:
                if ( Chocobo_CurrentField == 1 ) {
                    set VAR_GenInt24_172 |= 8
                    set VAR_LocUInt8_8 = 1
                }
                break
            case +1:
                if ( ( Chocobo_CurrentField == 2 ) && ( General_ScenarioCounter >= 9400 ) ) {
                    set VAR_GenInt24_172 |= 2048
                    set VAR_LocUInt8_8 = 1
                }
                break
            case +2:
                if ( ( Chocobo_CurrentField == 1 ) && ( General_ScenarioCounter >= 9400 ) ) {
                    set VAR_GenInt24_172 |= 8192
                    set VAR_LocUInt8_8 = 1
                }
                break
            default:
                set VAR_LocUInt8_8 = 0
                break
            }
So you see, you only need to increase the scenario counter lower bound for this special chocograph availability. Here are a few key scenario counter values (the first ones are named in the game's source code and I'm not always sure of the meaning, the last ones are values I searched myself in different field scripts):
Code: [Select]
SC_COUNTER_ARMOR_BLANK_START = 1500
SC_COUNTER_ARMOR_BLANK_END = 1600
SC_COUNTER_WMTITLE_BUNMEI_ON = 2400
SC_COUNTER_SGATE_DESTROYED = 2990
SC_COUNTER_CLAY_DESTROYED = 4990
SC_COUNTER_LIND_DESTROYED = 5598
SC_COUNTER_FOG_END = 5990
SC_COUNTER_KUROMA_APPEAR = 6200
SC_COUNTER_DAGGER_AWAKE = 6875
SC_COUNTER_SGATE_RECOVER = 6990
SC_COUNTER_ALEX_DESTROYED = 8800
SC_COUNTER_SUNA_MAKYU_ON = 9450
SC_COUNTER_WMTITLE_NEW_ON = 9600
SC_COUNTER_SUNA_MAKYU_OFF = 9890
SC_COUNTER_CUT_HAIR = 10300
SC_COUNTER_GET_HILDA3 = 10400
SC_COUNTER_HOKORA_START = 10600
SC_COUNTER_HOKORA_END = 10700
SC_COUNTER_LAST_WORLD = 11090

Hilda Garde obtained = 10400
Ipsen Castle entered = 10500
Ipsen Castle done = 10600
Eiko+Dagger gone to Shrine = 10620
Amarant+Freya gone to Shrine = 10640
Steiner+Vivi gone to Shrine = 10660
Shrines done = 10700
Disc 4 = 11100

3
Yes, it's Moguri.
Alt+Space switches between 16:9 and 4:3.

4
The command that allows you to trance manually over 50% of trance gauge is Zidane's last skill. It gets available at the end of disc 2, so around the Iifa Tree sections.

5
It has been done with a previous version of the mod. I am not sure whether it's still possible (in particular, Necron is harder than when it was first done and it was already a bag of pain) but I am sure that Sealion is not a wall.

By the way, Number 1 has Protect, so he's very resistant to physical attacks but weak to magic attacks.
Sealion has Shell so it's the other way around.

6
The Moguri folder is setup when installing the mod (the installer asks for a folder).
You can also see what it is from the game's folder ("FINAL FANTASY IX"): there should be a file "Memoria.ini". Open that file with a text editor (eg. notepad) and look at the field "MoguriFolder" in the "[System]" section.

7
Yes, you only need to enable that option when installing the Moguri mod.

8
Well, there's a link in the mod's topic.
It is very recent indeed (I'm still working on adding a "Beatrix only" and "Moguri + Beatrix only" version).

9
@levantine: Have you tried the latest release? I specifically made a "Moguri Mod + Alternate Fantasy" version.

10
It's not possible to make it look nice, unfortunatly :/
The spell animations are the biggest black box of the game now because it's delegated to an external DLL in the Steam version and I can't access its source code, either to see how it works or to modify them (all the possibilities and informations for that section were obtained the old way: guessing and testing).

You may however make Shell's animation hit all the targets in effectivity. For that, you simply need to change the line "Effect Point: 1st target" to "Effect Point: all targets" in its Spell Animation sequence. It will only display the effect on the 1st character though... so I guess that Mighty Guard's animation is still a better choice anyway.

11
No, the .hws wouldn't hold that change.
That's a real problem for me as well as I would largely prefer to have only 1 file for the mod, but the nature of the change is just not embeddable in a .hws... so I decided that I would distribute the C# code as well (generating the mod then requires Memoria or dnSpy in addition to HW).
Using Memoria, it's simply a .cs file to share in addition to the .hws (and then I think that you need to run Memoria's script compiler, but that's easy).

In any case, the default way to share a mod is not to share the .hws (+ maybe C# code) but to share the generated Steam files (p0data, DLL...).
Even if it creates mod compatibility problems, that's the easiest way to do it, both for the modder and the user.

12
Hello Clem Fandango. Sorry I didn't see your message before.

It is not possible to do that without modding the battle engine. It can be done either with Albeoris's Memoria tool or with dnSpy, but not directly with HW (or only with added difficulties for no reason). In both case, it's a bit of C# coding.

Using Memoria, you need to change the script of Phoenix Downs (inside "Scripts/Sources/Battle/0072_ItemPhoenixScript.cs"):
Code: [Select]
public void Perform()
{
if (!_v.Target.CanBeRevived())
return;

if (_v.Target.IsZombie)
{
_v.Context.Flags |= BattleCalcFlags.Miss; // Add this line
return; // Add this line
// if ((_v.Target.CurrentHp = (UInt16)(GameRandom.Next8() % 10)) == 0) // Remove this line
// _v.Target.Kill(); // Remove this line
}
else if (_v.Target.CheckIsPlayer())
{
if (_v.Target.IsUnderStatus(BattleStatus.Death))
_v.Target.CurrentHp = (UInt16)(1 + GameRandom.Next8() % 10);

_v.TargetCommand.TryRemoveItemStatuses();
}
}

Using dnSpy, you need to change the method "btl_calc::CalcMain" and more specifically the "case 72":
Code: [Select]
if (Status.checkCurStat(target, 64u) || btl_util.CheckEnemyCategory(target, ENEMY.ENEMY_CATEGORY_UNDEAD))
{
calc_VAR.flags |= 1; // Add this line
// Remove the following lines, "if ((target.cur.hp = (ushort)(Comn.random8() % 10)) == 0)" and "SetEnforceHP0"
}
else if (btl_calc.CheckNotPlayerMiss(calc_VAR))
// etc... no change there

13
No it's not. If it misses, that surely means that you don't have any more ethers :o
It's not a free MP recovery.

14
No, sorry.

15
Unfortunatly, this is mainly hard-coded. You can change it using the tool dnSpy but not Hades Workshop only.
In dnSpy, open the Assembly-CSharp.dll, search for the following classes and methods and edit a few lines:

1) In the class "ModelFactory" and its method "CreateModel", there's this block:
Code: [Select]
if (ModelFactory.garnetShortHairTable.Contains(text))
{
ushort num = BitConverter.ToUInt16(FF9StateSystem.EventState.gEventGlobal, 0);
bool flag = num >= 10300;
if (flag)
{
// etc... Disable "long_hair" components
}
else
{
// etc... Disable "short_hair" components
}
}
Replace the "if (flag)" line by "if (flag && isBattle)".

2) In the class "EventEngine" and its method "DoEventCode" (that's a very long one), there is a "case EBin.event_code_binary.MODEL":
Code: [Select]
case EBin.event_code_binary.MODEL:
{
posObj.model = (ushort)this.getv2();
Obj expr_1EA4 = this.gExec;
expr_1EA4.flags |= 1;
posObj.eye = (short)(-4 * this.getv1());
if (this.gMode == 1)
{
string text = FF9BattleDB.GEO[(int)posObj.model];
posObj.go = ModelFactory.CreateModel(text, false);
GeoTexAnim.addTexAnim(posObj.go, text);
if (ModelFactory.garnetShortHairTable.Contains(text))
{
posObj.garnet = true;
ushort num7 = BitConverter.ToUInt16(FF9StateSystem.EventState.gEventGlobal, 0);
posObj.shortHair = (num7 >= 10300);
}
// etc...
Change the line "posObj.shortHair = (num7 >= 10300);" to "posObj.shortHair = false;".

There might be a third method to change, the method "addTexAnim" of the class "GeoTexAnim", but I am not sure if it is important or if it would mess up with the battle model.
And there would be a 4th one, "ff9play::FF9Play_GetSerialID", if you wanted to change her model in battles as well.

16
First: that's absolutly impossible.
If the loading bar is not showing for the World Maps, it means that HW has bugs while loading the WM datas from the game. As long as the datas required are not loaded, the .hws file is barely checked (it's only checked to see the available sections, which works fine since you see them before confirming).
So either the loading bar shows up, or you have a file modded without you knowing it (most probable). The WM datas are mainly in the p0data3.bin archive.

Second: You should be able to open HW on the Moguri Mod except for the DLL changes.
In order to do that, you need a folder with:
1) A "FF9_Launcher.exe", whichever one (even a dummy file of 0kb would work as long as it's correctly named),
2) The archive files of the Moguri Mod (all the p0dataX.bin, the "mainData", "resources.assets" and all the "sharedassetsX.assets", the "levelX" shouldn't be needed except if you want to use the Unity Assets Viewer tool),
3) The "Assembly-CSharp.dll" of the normal game, unmodded (at least not modded by Memoria or the Moguri Mod).

Put all these files in sub-folders mimicking the directory of the game, select the "FF9_Launcher.exe" with HW and it should be alright.
When saving, choose the options "Spreadsheets" + "Unity Archives": the archives of Moguri should be generated correctly and there will be .csv files that can be read by Memoria.
The p0dataX.bin should go in the Moguri Mod's folder (that's where the modded archives are), something like "C:\Program Files\Moguri Mod\StreamingAssets".
The .csv files should also go in a Moguri Mod's subfolder, like "C:\Program Files\Moguri Mod\StreamingAssets\Data\Battle\Actions.csv".
The resources/sharedassets should go in the Steam's file folder, as usual.

I hope that it helps. Tell me if I'm wrong somewhere ^^'

17
SV_Target does not work like that.

"set SV_Target = 1" -> Only the 1st player's character is targeted (usually Zidane).
"set SV_Target = 2" -> Only the 2nd player's character is targeted.
"set SV_Target = 4" -> Only the 3rd player's character is targeted.
"set SV_Target = 8" -> Only the 4th player's character is targeted.
"set SV_Target = 16" -> Only the 1st enemy is targeted.
"set SV_Target = 32" -> Only the 2nd enemy is targeted.
"set SV_Target = 64" -> Only the 3rd enemy is targeted.
"set SV_Target = 128" -> Only the 4th enemy is targeted.
And then, you add numbers to have multiple targets. The whole player's party is thus targeted with "set SV_Target = 15" and not 5 (if you watch more carefully, you'll see that only two characters are affected when you use 5).
However, because the number of characters/enemies may vary, it is very unusual to use the numbers directly; oftentimes, "SV_PlayerTeam" or "SV_EnemyTeam" are used instead of "15" or "240" respectively. The "NotMatching" or "Matching" rules out characters not matching some conditions (the "32" means "Reflect": again, select that number and see how it converts to the "Status List B" which can be seen on the left of the window, inside the "Battle" panel). For single-targeted spells, a "RandomInTeam" is used.

The number used as an argument for the "Attack" corresponds to the attack in the attack list. Look at what's displayed on the right.

18
I am the one who put the AI script on ffwikia. They are indeed a bit reworked there to make it more clear.

Firstly, the example you gave do not compare the same things. You are not in the same function or at the same point of the function.
Secondly, "VAR_LocInt24_9" is a variable but since it has no name inside the game's code, it is given an obtruse name by default. "Loc" specifies that it's a local variable, "Int24" specifies that it's a signed number using 24 bits (it can represent large numbers, unlike "Int8" that can represent only numbers from -128 to 127; that's binary computation stuff but it's not mandatory to understand it though it makes things easier).
You should totally use "File -> Open Mod -> LocalVariableSettings.hws" as it will give names to these variables according to their usage inside the AI scripts (the work is not done yet with the Field scripts).

Finally, I suggest to see first another AI script to understand how things are done. Necron's AI is not the simplest by a large margin (I mean, Necron's AI is simple but not the AI of his dummies who actually do most of the job).
I recommend looking at the AI script of Tantarian: you should be able to grab how things work and it also uses a feature shared with Necron, the "Stand Animation" alternative.

And don't hesitate to look around; there's a list of function codes available and ~60% of the screen is dedicated to give more information than the raw script text (in particular, the "257" that you spotted should be read as a "Status List A" value and means "Petrify | Death", Petrify or Death).

19
For the PSX version, it is always safe to open a non-modded version of the game, save mods as .hws and then overwrite binary files.

Here is how it works:
- Save Mod (.hws files) registers the modifications done with the tool since you opened the .bin file; it doesn't know anything about previous modifications you could have done before.
- Export as PPF does a comparison between the file on your hard drive and the modifications done with the tool since you opened the .bin file; it produces a patch that is only good for the file you had on your hard drive at the time you created it (hence the need to use that on non-modded versions).
- Overwrite binary files changes the file on your hard drive but also resets the modification track (if I remember correctly... it may not be the case anymore), that's why it should be used after saving a .hws, or else you'll lost the capability to update your mod after closing the tool.

Also, .hws files can be used to move your mod from a disc to another (instead of repeating the same modifications 4 times).

There can be bugs when opening a modded PSX game file and even if there is no bug by chance, the tool has no way to remember what were the modifications you did on a file before, so it won't mark some parts as modified (for exporting PPF for instance) even though they are not the vanilla (non-modded) datas anymore.

20
Hold everything!
I found a bug when loading HWS files containing Spell Animations. It corrupts the saves done after that.

If you loaded HWS files containing Spell Animations and then saved HWS again with the version 0.41, you must do that, using the version 0.41b:
- Open the HWS with your latest changes (saved with v0.41) without the Spell Animations (it should crash anyway if you load them),
- Open a previous HWS with Spell Animations changes (saved with <= v040b) if you have a backup or do the Spell Animations changes again.
- Save as HWS; that's fine.

If you don't have a backup, you can also send me your (corrupted) HWS file and I will fix it.

Sorry for the troubles...

21
Update to v0.41:
- Added a Randomizer tool, including the slightly modified features of Meteor On FFIX (which was only working on the PSX US version) and a way to randomize the enemies' spells (unfairness is guaranteed),
- Added more flexibility and compatibility with other mods or modding tools:
--- You should now be able to open and append changes to Assembly-CSharp.dll mods created by other means (Sound Fix, dnSpy-edited DLL, etc...) as long as they don't change the structure of some key things (the datas read by Hades Workshop, such as the spells (AA_DATA)...),
--- Since Albeoris's Memoria change the structure of these key things, you still can't open the Memoria-modded DLL; however, you can now generate .csv files that are suitable to Memoria for most of the modifications. There's a couple of modifications that requires a bit of dnSpy hacking to complete the merging of the mod though: the Magic Sword requirement spells and the Battles' battleground changes (both of them are not editable yet using only Memoria),
--- You may directly generate the assets instead of the full-fledged archive files; this way, assets can be imported into archives modded in different manners and easily merge mods as long as they don't change the same assets (but do change the same archives),
--- Fixed different bugs with the PSX versions of the game; Hades Workshop should fully work on them again (also, the Randomizer works on the PSX version, minus the possibility to have non-updated spell names or descriptions due to the lack of space),
- Fixed a few other bugs (the one pointed by DavidBest1996, the very large numbers bugging in the Script editor, a "switch case + do-while loop" decompilation error...) and improved a few things.

I am still on a break with FF9 modding. I will surely just update my mod Alternate Fantasy to have compatibility with other mods, but then I'll return to not making things.

Note that Gael-Honorez-sb added CMake files to generate Hades Workshop projects using CMake on GitHub. I always have troubles with CMake (but with Visual Studio as well anyway) but it will surely ease the work of people trying to use the tool's source code. Let him be thanked for that.


@ToraCarol: Maybe it has something to do with the dialog itself? What text opcodes are you using?

22
Sorry for not answering. I am working back a bit on HW in view of releasing a new version. I'll mainly try to fix compatibility issues (Albeoris's Memoria, Moguri Mod, Audio fix and other DLL editing mods...). I'll use the occasion to fix a couple of bugs too.

Thanks a bunch DavidBest1996 for telling me about that one; it's fixed and the next version will be working better on PSX files again.

Good job so far TheHobgoblin ^^
You can see examples of NPC scripts here, there and there. The important steps are: add an NPC entry (or use one of the free "player" entries that are after all the others and usually have no functions at first), add an "Init" and a "SpeakBTN" function, setup the model+position in the "Init" and use "SetPartyReserve( xxx )" and "Party( 4, 0 )" in the "SpeakBTN".

23
@masagrator: Yes, that's a problem happening because of the Steam version.
Basically, they used a weird alpha channel for rendering the edges of the tiles while it was a "completly opaque/completly transparent" alternative in the PSX format.
The shift on the carpet (wow, I had a hard time seeing it even with your mark...) surely comes from the way they upscaled the images for the Steam version (because it's not a tile edge).
Fragosso knows better than me this kind of things...

@ToraCarol: There should not be any "return" line if the first "if" block that you show.
The problem with the jump animation is more likely to be the one described here. You need to use this jump animation before in the script to let the game load it (using "SetRightAnimation( 5041 )" just before "SetRightAnimation( 5224 )" is enough).
Emulating a "Change disc" screen requires modding the C# code and adding new assets (textures) to the game. I don't know if it can work, sorry.
You may more easily add a "Would you like to save?" screen, as it can simply be emulated with a dialog box... but I can understand that it's not what you want.

24
I don't see the problem with your screenshot.
Which kind of image do you want to "generate" (= extract from the game?) ?

25
What is the current script that you got?
There are two possibilities: either the loop enters a case where the script "returns" (which stops for good the script making her following Zidane) or you forget to set the safety variable back to its normal state (that's if the cutscene safety relies on a variable).

Pages: [1] 2 3 ... 25