Author Topic: [PSX/PC] General editor - Hades Workshop (0.50b)  (Read 844484 times)

resinate

  • *
  • Posts: 96
    • View Profile
Re: [FF9] General editor - Hades Workshop (0.30)
« Reply #375 on: 2015-12-07 14:37:29 »
RIP my mod to pieces :( soo much work to make that stat system i did lol

Tirlititi

  • *
  • Posts: 874
    • View Profile
Re: [FF9] General editor - Hades Workshop (0.30)
« Reply #376 on: 2015-12-07 17:47:27 »
If that's too much of a work, you can send me you .hws file (or even one that contains only the corrupted "Stats" modifications) and I should be able to fix it pretty easily by hand.
I'm overly busy these few days, but it'd most likely be done by the end of the week.

Tirlititi

  • *
  • Posts: 874
    • View Profile
Re: [FF9] General editor - Hades Workshop (0.31)
« Reply #377 on: 2015-12-19 20:57:25 »
Update to 0.31 :
- You can now fully choose which statuses are inflicted (or healed) by spells,
- World Maps have 2 more sub-panels : they allow to modify the name of the different places and modify the random encounters in the different areas. However, you can only use random encounters with the proper battle scene or the game will crash. Also, you can't see where are placed those areas on the World Map yet.
- Improved the script edition a lot :
--- Added a way to declare and use local variables. More details below.
--- Added a list of different known functions and variables, with their descriptions.
--- You now easily generate the value corresponding to different things, such as an attack list for enemy IA, or a button list to get the player's inputs.
--- Added a preview of the field walkmesh when editing a field script. The positions in the code are viewed on this preview.
--- Same thing for the world map. The preview can't be zoomed tough.
--- Improved the argument helpers for several data types, such as positions or colors.

About the local variables, the syntax is this one :
Code: [Select]
local [type] [name] [Default Name]

// example
local uint8 foo VAR_LocUInt8_10

EDIT: You can now use global variable as well: they are shared by the other entries of the script and are declared using the keyword "global" insteal of "local".

[type] can be one of the following : Bool, SBool (same as Bool), Int8, UInt8, Int16, UInt16, Int24, UInt24 and Null (dummied).
For integers (int) and positive integers (uint), the number is the size in bits, so Int16 is 16 bits (= 2 bytes) long.

[name] is the name you want for your local variable.

[Default Name] is optional and is the name of the variable you want to replace. It should have a compatible size. Note that this default name can still be used to refer to your variable.
If you don't specify it, a default one will be attributed. However, it will likely mess with the local variables already used in the script and not declared.

Usually,
int8 are of the form VAR_LocInt8_##
int16 are of the form VAR_LocInt16_##
uint16 are of the form VAR_LocUInt16_##
etc...

Local variable settings can be saved in .hws files independantly of the rest.
I'm planning to create a .hws file containing all the local variables used by the game by default. Once it'll be done, you can import it and declare local variables without fear of collision with the ones existing (not to mention it will largely increase the readability).

A local variable declaration needs to be parsed to take effect. It can't throw an error but if there's a problem, you'll get a warning and the problematic line will be ignored.


The most immediate and practical use is that you can rename a variable once you understood the purpose :
- Check that the variable is local or global by looking at its name.
- If it's a general variable instead, you may declare it global and still use it as a global variable provided you use the right [Default Name].
- Declare the variable anyway ; the only thing left is to choose its name, which should be feasible since you understood its purpose.
- Parse, close the script window and open it back. The cryptic variable's name has been replaced by the name you've chosen.

Example : for some treasures, the variables "VAR_GenInt16_220" to "VAR_GenInt16_224" serve as settings the treasure's position and item.
If you find a script looking like this :
Code: [Select]
Function Zidane_12
    TimedTurn( Angle(VAR_GenInt16_220, VAR_GenInt16_222), 16 )
    WaitTurn(  )
    if ( VAR_GenUInt8_226 == 0 ) {
        if ( VAR_GenInt16_224 == 29999 ) {
            WindowSync( 7, 0, 6 )
        } else {
            if ( VAR_GenInt16_224 >= 1000 ) {
                RunSoundCode3( 53248, 108, 0, -128, 125 )
                set VAR_GenInt16_228 = ( VAR_GenInt16_224 - 1000 )
                if ( ( VAR_GenInt16_228 + GetGil ) > 9999999L ) {
                    set VAR_GenInt16_228 = ( 9999999L - GetGil )
                }
                AddGil( VAR_GenInt16_228 )
                SetTextVariable( 0, VAR_GenInt16_228 )
                WindowSync( 7, 0, 6 )
                set VAR_GenUInt8_226 = 1
            } else {
                if ( ( GetItemCount(VAR_GenInt16_224) < 99 ) && ( VAR_GenInt16_224 < 512 ) ) {
                    RunSoundCode3( 53248, 108, 0, -128, 125 )
                    set VAR_GenUInt8_226 = 1
                    SetTextVariable( 0, VAR_GenInt16_224 )
                    AddItem( VAR_GenInt16_224, 1 )
                    WindowSync( 7, 0, 4 )
                } else {
                    if ( ( VAR_GenInt16_224 >= 512 ) && ( GetCardAmount < 100 ) ) {
                        RunSoundCode3( 53248, 108, 0, -128, 125 )
                        set VAR_GenUInt8_226 = 1
                        SetTextVariable( 0, VAR_GenInt16_224 )
                        AddItem( VAR_GenInt16_224, 1 )
                        WindowSync( 7, 0, 5 )
                    } else {
                        SetTextVariable( 0, VAR_GenInt16_224 )
                        if ( VAR_GenInt16_224 < 512 ) {
                            WindowSync( 7, 0, 8 )
                        } else {
                            WindowSync( 7, 0, 9 )
                        }
                    }
                }
            }
        }
    }
    return
Then you can declare these :
Code: [Select]
global int16 TreasurePositionX VAR_GenInt16_220
global int16 TreasurePositionY VAR_GenInt16_222
global int16 TreasureItem VAR_GenInt16_224
global uint8 TreasureTaken VAR_GenInt16_226
Parse, close and reopen and find this instead :
Code: [Select]
Function Zidane_12
    TimedTurn( Angle(TreasurePositionX, TreasurePositionY), 16 )
    WaitTurn(  )
    if ( VAR_GenUInt8_226 == 0 ) {
        if ( TreasureItem == 29999 ) {
            WindowSync( 7, 0, 6 )
        } else {
            if ( TreasureItem >= 1000 ) {
                RunSoundCode3( 53248, 108, 0, -128, 125 )
                set VAR_GenInt16_228 = ( TreasureItem - 1000 )
                if ( ( VAR_GenInt16_228 + GetGil ) > 9999999L ) {
                    set VAR_GenInt16_228 = ( 9999999L - GetGil )
                }
                AddGil( VAR_GenInt16_228 )
                SetTextVariable( 0, VAR_GenInt16_228 )
                WindowSync( 7, 0, 6 )
                set VAR_GenUInt8_226 = 1
            } else {
                if ( ( GetItemCount(TreasureItem) < 99 ) && ( TreasureItem < 512 ) ) {
                    RunSoundCode3( 53248, 108, 0, -128, 125 )
                    set VAR_GenUInt8_226 = 1
                    SetTextVariable( 0, TreasureItem )
                    AddItem( TreasureItem, 1 )
                    WindowSync( 7, 0, 4 )
                } else {
                    if ( ( TreasureItem >= 512 ) && ( GetCardAmount < 100 ) ) {
                        RunSoundCode3( 53248, 108, 0, -128, 125 )
                        set VAR_GenUInt8_226 = 1
                        SetTextVariable( 0, TreasureItem )
                        AddItem( TreasureItem, 1 )
                        WindowSync( 7, 0, 5 )
                    } else {
                        SetTextVariable( 0, TreasureItem )
                        if ( TreasureItem < 512 ) {
                            WindowSync( 7, 0, 8 )
                        } else {
                            WindowSync( 7, 0, 9 )
                        }
                    }
                }
            }
        }
    }
    return



I hope you enjoy the changes  ;)
« Last Edit: 2017-10-12 20:02:46 by Tirlititi »

Dogshrapnel

  • *
  • Posts: 16
    • View Profile
Re: [FF9] General editor - Hades Workshop (0.31)
« Reply #378 on: 2015-12-20 18:49:44 »
Ugh, I don't know why but after editing a ton of monster data to balance their stats better and saving it, it seems like most of it is gone, which considering how long it took sucks. The really weird thing is that some of that data did get saved, but only the basic stats it seems, all of the status effects and HP/MP stats don't seem to exist. Is that a problem or did I just mess something up somehow?

Tirlititi

  • *
  • Posts: 874
    • View Profile
Re: [FF9] General editor - Hades Workshop (0.31)
« Reply #379 on: 2015-12-20 19:26:15 »
That bites :/
I just tried few tests and it seems to work fine for me. Can you tell me :
1) which datas were saved and which datas were not saved exactly,
2) the save process you had (if you saved as mod, then overwrote the binary data or things like that).

I did change a tiny bit of the saving routine in this version, but I can't see how it would have affect that.

Kefka

  • *
  • Posts: 202
    • View Profile
Re: [FF9] General editor - Hades Workshop (0.31)
« Reply #380 on: 2015-12-20 20:48:28 »
I downloaded the new version, but when I try to start it I get the message that I'm missing the following dll:

wxmsw30u_gl_gcc471TDM.dll

It's not included in the zip folder.

Tirlititi

  • *
  • Posts: 874
    • View Profile
Re: [FF9] General editor - Hades Workshop (0.31)
« Reply #381 on: 2015-12-20 21:29:32 »
Fixed, thx for warning Kefka.
Here is also a temporary link for the .dll only.

You'd also need glu32.dll and opengl32.dll. They are much more standard but if I don't know if they are included in Windows by default.
If that's not the case and most of people need them, please let me know so I'll also put them in the archive.

Dogshrapnel

  • *
  • Posts: 16
    • View Profile
Re: [FF9] General editor - Hades Workshop (0.31)
« Reply #382 on: 2015-12-20 21:46:07 »
As far as I can tell, I would save as a mod mostly, only saving directly to the file when I was testing. It seems like the monster stats were saved as many defense values are different from the originals. It's weird since everything else is still changed, I remember running into this problem before too, so I don't know what the heck I'm doing that's causing this.

Edit* Now I'm noticing that a few enemies DID have their proper stats saved, usually the ones at the start of the list, but the majority didn't, why would it save some but not all?
« Last Edit: 2015-12-20 22:03:15 by Dogshrapnel »

Tirlititi

  • *
  • Posts: 874
    • View Profile
Re: [FF9] General editor - Hades Workshop (0.31)
« Reply #383 on: 2015-12-20 22:06:49 »
When you save directly to the file, the modifications are cleared and won't be saved by further "Save Mod" calls.

Now that I think about it... it's a really bad choice that I made it work this way... It's been so long that I don't remember why I've chosen it in the first place. Making the modifications persistents would also bring problems though.

Anyway, when you begin to overwrite the binary file, you should keep doing exclusively it and then create a .ppf file using makeppf or something like that.
Or you do like I do : you use 1 file for which you save only using "Save Mod" and another one for which you import the changes and apply them directly.
I also sometimes use only 1 file and create an undoable PPF patch when I want to test. You need to be careful to unapply this patch before creating a new one though. The first method is safer.

In the next version, I'll add a feature that allow to choose which datas exactly you want to save in .hws files, alongside file batching. This way you'll be able to get a .hws file even if you used the "Overwrite binary" feature before.
« Last Edit: 2015-12-20 22:10:11 by Tirlititi »

Dogshrapnel

  • *
  • Posts: 16
    • View Profile
Re: [FF9] General editor - Hades Workshop (0.31)
« Reply #384 on: 2015-12-20 23:05:26 »
That's unfortunate, it seems I'll have to redo all that work I did due to some problems that caused my binary files to become unusable. Thanks anyways.

Kefka

  • *
  • Posts: 202
    • View Profile
Re: [FF9] General editor - Hades Workshop (0.31)
« Reply #385 on: 2015-12-21 14:19:48 »
Fixed, thx for warning Kefka.
Here is also a temporary link for the .dll only.

Thanks a lot, it's working fine now.

Edit: the possibility to modify and create entirely new sets of status effects seems very promising. Am I right in assuming that the various ''No Status'' sets at the end of the list are currently unused? Because all abilities that don't inflict a status use the ''No Status'' set at the top.
« Last Edit: 2015-12-21 14:28:35 by Kefka »

Tirlititi

  • *
  • Posts: 874
    • View Profile
Re: [FF9] General editor - Hades Workshop (0.31)
« Reply #386 on: 2015-12-21 14:46:08 »
Yes you're right by assuming that.

I didn't test all the possibilities it offers yet. I can tell that :
• "Curing the Trance status" is possible. It empties the Trance gauge and turn the character back to normal (no effect if the character was not in Trance),
• "Curing the Low HP status" doesn't work. At least it doesn't increase the HP nor it writes the HP figure in white.

I guess there are rooms for discovers here.

R51

  • *
  • Posts: 8
    • View Profile
Re: [FF9] General editor - Hades Workshop (0.31)
« Reply #387 on: 2016-01-05 16:25:46 »
This newest version looks pretty great. I've messed around with it some in the past but I was way out of date with my version. :)

I just downloaded 0.31 to play with the world map a bit, but I don't see anything populating in any of the World Map tabs. See the screenshot below:



Is this something I've done wrong?

Tirlititi

  • *
  • Posts: 874
    • View Profile
Re: [FF9] General editor - Hades Workshop (0.31)
« Reply #388 on: 2016-01-05 17:31:13 »
Hum... I'm able to reproduce the bug with the japanese version (the World Map panel doesn't work perfectly with that version, though it shouldn't bug like this). I'm not sure, but I think I failed there : I should have make the .hwf file update itself for this version.

Anyway, try deleting the ".hwf" file in your game's folder and force Hades Workshop to scan the file again (you must scan a non-modified version, always). It fixed the thing for me.

Everyone should check if the World Map panel works correctly and do the same if it doesn't. It won't be a problem if you never access to that panel, but it may loose your modifications if you go to it and it bugs and you didn't save.

Thanks for warning, R51. And sorry for the problem.

R51

  • *
  • Posts: 8
    • View Profile
Re: [FF9] General editor - Hades Workshop (0.31)
« Reply #389 on: 2016-01-05 17:48:26 »
That helps a lot, though the Global Map panel no longer has a preview. Does the current version actually show the Global Map visually or did I misunderstand what it's meant to be doing? Thanks for the fast reply.


Tirlititi

  • *
  • Posts: 874
    • View Profile
Re: [FF9] General editor - Hades Workshop (0.31)
« Reply #390 on: 2016-01-05 19:04:04 »
The world map preview is for the script edition. It's just the minimap but it may show the position when it is explicitely written.



That's nowhere as nice as tasior's viewer, but that's a first ^^"

R51

  • *
  • Posts: 8
    • View Profile
Re: [FF9] General editor - Hades Workshop (0.31)
« Reply #391 on: 2016-01-05 19:15:20 »
Yep, that's why I was checking this out, was for an alternative to tasior's viewer. Looks like this one won't do what I was wanting to look at, but HadesWorkshop is still flippin' awesome. Thanks again for all the hard work on it. :)

Kefka

  • *
  • Posts: 202
    • View Profile
Re: [FF9] General editor - Hades Workshop (0.31)
« Reply #392 on: 2016-01-10 20:04:29 »
I've got another question about enemy AI, and was curious whether you, tirlititi, or someone else could help me out here:

Is there a way for an enemy to check if a specific character is in your current party? Because I've been playing with the thought of making Trance-Kuja use Reflect only if either Eiko or Vivi (or both) are in the current party, since they are the only two characters that have reflectable spells. Reflect doesn't bother any of the other six party members, so if Kuja uses it if neither of the two is in your party, he is essentially just wasting a turn.

I've only found one enemy that uses a party member's MODEL_TYPE when targeting, and that's the Doppelgangers created by Epitaph who always use their 9999 damage attack against their corresponding counterpart. However I'm unsure how to incorporate the Model Type check in an 'if condition' (I'm assuming that's what I'd need for Trance Kuja; to check if model type Vivi or Eiko is present, then use reflect, otherwise use a different attack). Could you give me a hint on how to write such a condition properly? My first attempt has been unsuccessful and lead to a crash.

Tirlititi

  • *
  • Posts: 874
    • View Profile
Re: [FF9] General editor - Hades Workshop (0.31)
« Reply #393 on: 2016-01-10 20:19:10 »
It would be this :
Code: [Select]
if (#(SV_PlayerTeam[MODEL_TYPE] ==$ 2)) {
  // Vivi is in the team
}
if (#((SV_PlayerTeam[MODEL_TYPE] ==$ 10) | (SV_PlayerTeam[MODEL_TYPE] ==$ 11))) {
  // Eiko is in the team
}
The list for model types is this one (I don't think I've included it in the help yet, I should do it) :
Code: [Select]
Zidane 0 or 1
Vivi 2
Dagger 3, 4, 5 or 6
Steiner 7 or 8
Quina 9
Eiko 10 or 11
Freya 12
Amarant 13
Cinna 14
Marcus 15
Blank 16 or 17
Beatrix 18

That's strange you got a crash though. What was your try?

froggy25

  • *
  • Posts: 6
    • View Profile
    • PokéPlayer
Re: [FF9] General editor - Hades Workshop (0.31)
« Reply #394 on: 2016-01-11 11:27:07 »
Is there a way for an enemy to check if a specific character is in your current party? Because I've been playing with the thought of making Trance-Kuja use Reflect only if either Eiko or Vivi (or both) are in the current party, since they are the only two characters that have reflectable spells. Reflect doesn't bother any of the other six party members, so if Kuja uses it if neither of the two is in your party, he is essentially just wasting a turn.
The AI also uses it to circumvent auto-Reflect, by casting offensive spells on its own Reflect.
There is a quirk with this subroutine: if the reflected spell doesn't find any valid target, it will reflect the spell on the caster.

Kefka

  • *
  • Posts: 202
    • View Profile
Re: [FF9] General editor - Hades Workshop (0.31)
« Reply #395 on: 2016-01-11 18:19:49 »
It would be this :
Code: [Select]
if (#(SV_PlayerTeam[MODEL_TYPE] ==$ 2)) {
  // Vivi is in the team
}
if (#((SV_PlayerTeam[MODEL_TYPE] ==$ 10) | (SV_PlayerTeam[MODEL_TYPE] ==$ 11))) {
  // Eiko is in the team
}
The list for model types is this one (I don't think I've included it in the help yet, I should do it) :
Code: [Select]
Zidane 0 or 1
Vivi 2
Dagger 3, 4, 5 or 6
Steiner 7 or 8
Quina 9
Eiko 10 or 11
Freya 12
Amarant 13
Cinna 14
Marcus 15
Blank 16 or 17
Beatrix 18

That's strange you got a crash though. What was your try?

That was a while ago already, but I believe I made it way more complicated than it needed to be. I remember I was looking at Ozma’s AI for comparison, because Ozma uses Lv4 Holy and Lv5 Death only if they hit at least one party member, and that’s a condition similar to what I want for Trance-Kuja and Reflect. Since Ozma has these checks in his looping function, I figured I’d put it in the same place in`Kuja’s AI, and then change his ATB function accordingly, but I guess I messed something up during this (seemingly unnecessary) huge change. Afterwards I suspected that maybe including it in the ATB function as an ‘if condition’ instead might be a better choice.

So what do you suggest would be the best place to insert this in Trance-Kuja’s AI?

The AI also uses it to circumvent auto-Reflect, by casting offensive spells on its own Reflect.
There is a quirk with this subroutine: if the reflected spell doesn't find any valid target, it will reflect the spell on the caster.

That's a nice video, never knew about this bug. And you're right, I forgot completely about auto-reflect! I guess Trance-Kuja's use of Reflect does still make some sense afterall, even without Vvi or Eiko. Then I'd need to make it so he checks for auto-reflect in addition to those two little mages.

Tirlititi

  • *
  • Posts: 874
    • View Profile
Re: [FF9] General editor - Hades Workshop (0.31)
« Reply #396 on: 2016-01-11 20:18:28 »
Well yes, Ozma has some checkings in his "loop" function, but that's a bit different. The "loop" function really often serves as a secondary "Init" function that only init things that needs player's and enemy's datas to be loaded.
The game can't check party's level too soon in the fight, because the party is not loaded yet ("SV_PlayerTeam" and "SV_EnemyTeam" are 0 before they are loaded). Hence the checks for party's level is delayed until everything is loaded.

However, besides the fact you can't check for party's level or status or whatever too soon, you can decide to put those checks wherever you want. Here are some possibilities :

1) Put the check in the ATB function : I'd say that's the default choice. When Kuja's ATB bar is full, he checks if it is relevant to cast Reflect on himself. Devs tended to use an additionnal variables here, like "CuragaTarget" (see one of Necron's dummy for this example, but there are a lot of them, starting with Ozma's LV spells target which use a slight variation of that system).
However, nothing prevents you to do the check in the "set SV_Target" line :
Code: [Select]
        case +2:
            if (#(SV_PlayerTeam[MODEL_TYPE] ==$ 2)) {
                set #( SV_Target = SV_PlayerTeam )
            } else {
                set #( SV_Target = 0 )
            }
            break

2) Put it in the "loop" function, in the initializing part of the function. That's what Ozma does for the checks of the party's level. Since those lvls won't change during the fight, you can perform the check once and keep the result all over the fight. That's a good way to do it for things like lvl, model type or auto-status, but that's kinda irrelevant for current statuses, HP and such. Note that you always need at least an additionnal variable here for storing the result, and maybe another one if there is no "initializing part" of the function (that's not so common though). It could look like this :
Code: [Select]
    if ( !initflag ) {
        set initflag = 1
        while ( !( GetBattleLoadState & 16 ) ) {
            Wait( 1 )
            set VAR_GenUInt8_206 = GetRandom
        }
        // you can do it with a boolean like this :
        set myreflectflag = (#(SV_PlayerTeam[MODEL_TYPE] ==$ 2))
        // or, more like what devs usually did :
        if (#(SV_PlayerTeam[MODEL_TYPE] ==$ 2)) {
            set myreflecttarget = SV_FunctionEnemy
        } else {
            set myreflecttarget = 0
        }
        while ( GetBattleState != 4 ) {
            Wait( 1 )
        }
    }
Then, in the ATB function (or Counter function if you want to use Reflect as a counter), you use "myreflecttarget" as your target when casting Reflect, or check the "myreflectflag".

3) Put it at the top-level of the "loop" function (out of any "if" block). This way you can perform the check every frame and add the ability to cancel the casting if it's not relevant anymore at that point. That's more complicated and I won't give an example here, but that's a system used by Black Waltz 2 or Steiner, for instance : if their target dies before the attack is performed, they cancel it and choose another valid (non-Dagger) target. That way they don't take the risk to redirect their attack on Dagger.

I'll make a small update soon. I'll fix that bug with the World Map and improve a bit script readability. I'll also join a file for the naming of variables in all the AI scripts.
« Last Edit: 2017-10-12 20:09:32 by Tirlititi »

Kefka

  • *
  • Posts: 202
    • View Profile
Re: [FF9] General editor - Hades Workshop (0.31)
« Reply #397 on: 2016-01-12 18:51:48 »
I see, I'll try out your suggestions. Thanks again for your help.

Tirlititi

  • *
  • Posts: 874
    • View Profile
Re: [FF9] General editor - Hades Workshop (0.31)
« Reply #398 on: 2016-01-16 13:48:31 »
Update to 0.31b :
- Fixed that World Map bug ; the config file will update consequently.
- Enabled script edition of World Maps for the japanese version but for the two dummied World Maps.
- You can now declare "global" variables the same way you declare "local". There is no need to allocate them but, by default, they are initialized to 0 at the beginning of the script's execution (when entering a Battle, a World Map or a Field).
- Added a .hws file containing names for all the variables used in the battles. Use "Open Mod" to import it ; it won't mess with any of your modifications besides your own variable naming if you had one.
« Last Edit: 2016-01-16 13:50:47 by Tirlititi »

gledson999

  • *
  • Posts: 71
  • Listem to my Story, this maybe our last chance ♪
    • View Profile
Re: [FF9] General editor - Hades Workshop (0.31b)
« Reply #399 on: 2016-01-17 00:46:44 »
I'm on a project with a translation with friends to portuguese, and was separated by cities using the "Extract Script Dialog" option being that is already 80% completed, and my question is "Do you have plans to implement the Import Script Dialog option?"


Note: you tool is very precious, congratulation