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
You are definitely doing (or missing) something wrong with the cutscene progression variable (VAR_GlobInt16_47), but without further indications, I can't guess what.

2
I don't know why nothing is working anymore, but the cutscene didn't resume simply because you forgot to add a line "set VAR_GlobInt16_47 = 50" in that "case 143". You need to put that variable back on the track of the normal cutscene.

3
At the top of the function, in the "switchex" line, you need to increment the 1st number by 1.
Like "switchex X ( VAR_GlobInt16_47 ) {" -> "switchex X+1 ( VAR_GlobInt16_47 ) {".

The need of specifying the number of switch cases is bothering... I planned to make it optional at some point (and also make sure that the operation priorities are taken into account when parsing) but I never did in the end.

4
2 solutions:

- The simplest, you don't add any case and you just add a "WindowSyncEx" line right after Kuja's line. With the "Ex" variant, you can choose the speaker so you don't need to have that line in a function of Zidane. There are a few things that can't be done with that solution thoug (I think there's no "RunAnimationEx" for instance).

- The cleanest, you add a case 142 indeed with your extra line and whatever happens at that time. You may add a case 142 to the other characters too (if people are reacting with an animation at the same time for instance). Then, you need to reroute the cutscene progression flow that is handled by a variable (surely "VAR_GlobInt16_47" in this case):
1) You want the new reaction to come right after Kuja's "case 49" script, so replace the "set VAR_GlobInt16_47 = 50" by "set VAR_GlobInt16_47 = 142",
2) In your new reaction case (142 but in only one character's script, Zidane's in this case), make it so the cutscene gets back on track after the added dialog by using "set VAR_GlobInt16_47 = 50".
That way, the cutscene's progression counter does not increase linearly but does something like "... 47, 48, 49, 142, 50, 51...". That's not optimal but that's less tedious than inserting a case and shift all the others. There *might* be side-effects because of that but I don't think there is (I've never seen a cutscene's script where it could be a problem).

5
You can't add new battles unfortunatly.
However, there are a few dummied battles (that's what I've used to add the 4 extra bosses):
- 2 dummy vices that have nonsensical names (the names are actually raw japanese glyphs),
- 1 Zorn/Thorn battle that is dummied (it doesn't have the "Marthym" dialogs and only dummy attacks).
Also, you may delete a few redundant battles (Grand Dragons...) and replace them in the World maps battle lists. The two Ozma battles are also nearly the same as the only difference is the "Out of reach" flag, etc...

You can copy/paste single enemies and single attacks with a right-click (so right-clicking "Kuja" -> copy -> go to a dummied battle -> right-click -> paste).

6
You need to use the Unity Assets Viewer for that.
Open the resources.assets archive, search for the file "BtlEncountBgmMetaData.txt", export it, modify it and then re-import it.
Inside that file, there's a list of field IDs (so the Queen's Chamber in which you fight Beatrix is 1223) and for each field, a list of battles that can trigger in that field with the music ID of the battle ran. If a battle is missing there, the ambiant music doesn't stop when entering a battle.

So just find the field (1223), the battle (73) and put the correct music ID for it (117, "The Wavering Blade").

Here's a list of music IDs. I don't think that you can actually see it in Hades Workshop (only in the UAV when you open the music archive p0data62).
Code: [Select]
34: Zidane's Theme
70: Unrequited Love
9: Vivi's Theme
82: Black Mage Village
76: Fleeting Life
10: Steiner's Theme
62: Steiner's Delusion
29: Garnet's Theme
113: Melodies of Life
69: Over the Hill
77: Awaking Song // A Song from Her Memory, probably sung in Dali
115: Zidane and Dagger's Song
106: A Song from Her Memory
59: Distant Memory
124: Light of Destiny
32: Freya's Theme
68: Burmecia
50: Unforgettable Silhouette
15: Quina's Theme
88: Eiko's Theme
139: Girl of Madain Sari
2: Amarant's Theme
116: Roses of May
117: The Wavering Blade
125: Protecting My Devotion
30: The Evil Within
53: Court Jesters
133: Cid's Theme
118: Master of Time
84: Pandemonium
95: Kuja's Theme
96: Desert Palace // Kuja's Theme, played during the exploration of the Desert Palace
97: Devil's Ambition
98: Bahamut is Summoned
94: Wicked Melody
134: Dark Messenger
73: Moogle's Theme
4: Danger in the Forest
60: Ice Cavern
3: Village of Dali
67: Beyond the Twilight
74: Lindblum
49: Out of the Frying Pan
57: Qu's Marsh
108: South Gate
85: Dark City Treno
92: Cleyra's Trunk
80: Cleyra Settlement
91: Gargan Roo
79: Fossil Roo
90: Conde Petie
99: Before the Altar
130: Ruins of Madain Sari
81: Eidolon Wall
109: Iifa, the Ancient Tree of Life
112: Aboard the Hilda Garde
144: Esto Gaza
110: Mount Gulug
129: Daguerreo, the Hermit's Library
87: Bran Bal, the Soulless Village
132: Memoria
121: Crystal World
24: Aloha De Chocobo
100: Ukulele de Chocobo
22: Vamo Alla Flamenco
58: A Place to Call Home
36: Oeilvert
105: Chamber of a Thousand Faces
103: Ipsen's Castle
101: The Four Mirrors
131: Terra
44: Outlaws
138: Peaceful City // Outlaws, when controlling Vivi early disc 3
18: Swords of Fury
27: Find the Princess
20: Eye to Eye
17: The Fateful Hour
33: Thy Warmth
25: Tragic Love
143: Star-Crossed Lovers
41: Kiss of Betrayal
145: I Want to be Your Canary
142: Inseparable Hearts
65: Prima Vista Orchestra
75: Rufus' Welcoming Ceremony
12: The Meeting
140: The Black Waltz
83: Eternal Harvest
7: The Extraction
141: Foolproof Love Letter Scheme
86: Look Back, See the Frog!
146: Broken Spell, Healed Hearts
72: Guardians
48: You're Not Alone
147: Assault of the Silver Dragons
1: Unforgettable Sorrow
89: Mourning in the Sky
45: Another Nightmare
52: RUN!
111: Hunter's Chance
66: Tetra Master
0: Battle
35: Boss Battle
61: Faerie Battle
71: Final Battle
5: Victory Fanfare
6: Game Over
156: Prelude
148: Doga and Une

7
Yes. In the script of "Environment -> Fields -> A. Castle/East Tower", there are these lines near the 2 thirds of the function "Zidane_Loop":
Code: [Select]
        ChangeTimerTime( 1801 )
        ShowTimer( 1 )
        RunTimer( 1 )
1800 seconds = 30 x 60 seconds = 30 minutes. Just put any number you want there to change the initial time limit.
Then, while it is running, you may use a line like "ChangeTimerTime( GetTimerTime + 60 )" to give a time bonus or whatever, for instance after defeating Tantarian in the Library.

Tip: this kind of setting, done in a cutscene, is usually either in the "Main_Loop" function of the cutscene's field or inside a function of the character doing the action at the same time the setup occurs. There, Zidane is the one speaking ("Yeah! We've got 30 minutes...") when the timer shows up, so that's in his function.

8
Still, if you link Beatrix's commands, it saves up space for adding more spells to another command.

9
You can't use HW after doing that modification; that's something you have to do last.
Well, actually, I'm not sure of what are the consequences of using HW after doing that engine modification... But the limit is hardcoded in HW and the program can't catch that the limit was increased with dnSpy.

If her White Magic and her trance command use the same spells, you can avoid using dnSpy though. Simply select either one of these commands and link it to the other: doing this saves up spell slots.

10
You can't add many spells inside commands in HW. Using dnSpy and the guide you linked is meant to bypass the limit in HW. Since you're using the Beatrix mod, I guess, that limit is already reached and that's why you need to use dnSpy.

11
You didn't show the error.
Maybe that's a missing comma.
Maybe that's caused by a non-automatic type conversion: dnSpy does that a lot, you need to add type conversion to many places, like:
Code: [Select]
varshort = something + 16; // Error
varshort = (short)(something + 16); // Use this instead if the compiler complains: write the required converted type and wrap the computation inside parentheses

12
He's surely not defeated by the battle ending script (there's surely a line like "RunBattleCode( EndBattle, VICTORY )") so the reward specific to Baku is not given, only the reward of the group.
Make sure to flag him as defeated right before that line ending the battle:
Code: [Select]
set SV_FunctionEnemy[DEFEATED_ON] =$ 1You could also kill him for good with "set SV_FunctionEnemy[HP] =$ 0" but that would trigger other things like his death cry (I don't think he has one though), his death animation and fading... so that's a less good option.

13
Maybe there is some protection against this spell?
Yes.

Well, actually, there are several protections. Of course, you can jump with Freya to avoid it, Auto-Life to survive to it and also it doesn't target all the party in this fight but *only* 3 characters. It can't be avoided with magic evasion though.
But then, I'm saying that there is yet another protection.

Congrats nonetheless! It sure is meant to be an harder fight than Ozma.
I don't know how much of that fight you've seen actually, because it's also meant to have some replay value ^^

14
It requires a lot of script writing. It's better if you are familiar with programing but in any case, you should read a bit about how to do simple things with scripts here, here and here for instance.

In order to add a character to the party without asking the player's opinion (like when Vivi joins in the Prima Vista), it's this line:
Code: [Select]
set AddParty(8)"8" is an ID for Beatrix's character slot (0 is for Zidane, etc... Marcus shares Eiko's character slot).
It works only if there are less than 4 characters already. You can remove a character beforehand using this:
Code: [Select]
RemoveParty(0)
In order to enable Beatrix in the party selection menu, you must add her in party's reserve:
Code: [Select]
set Setting_PartyReserve = 511
SetPartyReserve(Setting_PartyReserve)
Note that it's a bit flag list (it works just like SV_Target in battle scripts). Usually, this party reserve is set to 255 for all the eight normal characters, so adding 256 to that value adds Beatrix.
Party reserve is reseted at different points during the game (when characters are temporarily splitted apart, etc...) so you need to take that into account.
To display the party selection menu, it's this:
Code: [Select]
if ( IsInParty(0) ) {
    Party( 4, 1 ) // Form a party of 4 characters and lock Zidane inside
} else {
    Party( 4, 0 ) // Form a party of 4 characters without locking any character inside
}

15
I translated everything that was required so you can play in any language, yes (the mod even unlocks the japanese language that is not available by default).

16
You are correct.

The p0data2.bin contains both datas of the enemies (AF) and textures of the battle scenes (Fraggoso's NPC mod).
You can't use AF without the datas of the enemies; there won't be obvious bugs for some time (except that enemies are not changed from vanilla) but it would eventually crash on some key fights.

2 solutions:
• Just use the p0data2.bin of AF and play with non-upscaled battle scene textures,
• Merge the two p0data2.bin. You can do that using just the "Unity Assets Viewer" tool that is included in Hades Workshop:
1) Install the p0data2.bin of Fragosso's NPC mod (the other files are irrelevant during the whole merging),
2) Open the Unity Assets Viewer (in HW's "tools") and open the game with it (selecting the FF9_Launcher.exe),
3) Open the archive p0data2 inside the UAV and sort the files by their type,
4) In the UAV's options, make sure that the "Automatically convert images" is deactivated ("Don't convert"), it makes things go better,
5) Select all the files of type "Texture2D", right-click and "Export selection"; that's the files upscaled by Fragosso,
6) Verify that a folder "HadesWorkshopAssets" has been created in FF9's folder, containing all the exported files (you shouldn't be able to see the images as they are not converted),
7) Close everything, install the p0data2.bin of the AF mod, reopen the UAV, reopen the game with it, reopen the p0data2, sort the files by type,
8‍) Select all the files of type "Texture2D" again, right-click and "Import selection". It should print a success message.

Once that's done, you have a p0data2.bin that contains both Fragosso's HD battle scenes and AF's enemy modifications.

I didn't do it myself because, as you said, that makes huge files to upload and I didn't want to multiply the versions "AF + Fragosso's HD backgrounds" / "AF + Fragosso's HD backgrounds + Fragosso's NPC" / "AF + Fragosso's NPC"...

17
About the frogs, it's in the scripts of the ponds:
1) In the "SpeakBTN" functions of the catchable frogs (Baby, Male, Female, Gold), there's a switch for the appearance of Quale:
Code: [Select]
            switchex 8 ( GetFrogAmount ) {
            case 2 ; 5 ; 9 ; 15 ; 23 ; 33 ; 45 ; 99:
                set VAR_GlobUInt8_64 = 2
                break
            default:
                break
            }
2) In the "Main_Loop", there's most of the cutscene's code, in particular the line "if ( GetFrogAmount == 99 ) {" triggering the battle.
The other rewards are also there, a bit after that line (in the "else" branch).

About the enemy targeting only Zombie characters, you can use that in an enemy script (the ATB function typically):
Code: [Select]
if ( ((GetRandom % 100) < 50) && ( FirstOf(SV_FunctionEnemy[MP]) >= 18 ) ) { // Example: 50% of chances to cast Life if there's a Zombie character and if the enemy has 18 MP or more
    set SV_Target = Matching( SV_PlayerTeam[STATUS_CURRENT_A], 64 ) // All the Zombie characters
    if ( #SV_Target ) { // Same as "if ( SV_Target ) {" or "if ( (#SV_Target) != 0 ) {"
        set SV_Target = RandomInTeam(SV_Target) // Pick only one of them
        Attack( ... ) // Cast Life
        return
    }
}
// etc... do something else if Life is not chosen for any reason

18
So? Have you tried doing that?
But it can't be done for the PSX version. It's a modification of the game's engine, so it's for PC.

19
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.

20
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

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

22
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.

23
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.

24
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.

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

Pages: [1] 2 3 ... 25