• Welcome to Final Fantasy Hacktics. Please login or sign up.
 

ATTACK.OUT Battle Event Conditionals Editing Tutorial.

Started by RavenOfRazgriz, February 10, 2011, 08:26:40 pm

RavenOfRazgriz

February 10, 2011, 08:26:40 pm Last Edit: July 02, 2011, 02:56:50 am by RavenOfRazgriz
Why an ATTACK.OUT editing tutorial?  Because one is sorely needed, I say.  This Tutorial will cover the basics of editing these events and which tools are needed to easily do so.  Something to remember is that events are basically coded with Lego bricks - so you as long as you conform to the very general constraints of the commands here, you can usually get the victory conditions you want.  You add this code to the game using a handy spreadsheet made by Xifanie and edited by myself to remove excess code, though I will instruct on its use after telling how the code itself actually works.  Also needed will be a Hex Editor that has the Write function.  Most have this, but a few do not or are really annoying in allowing you to access it, so make sure your current one has it and that you can access it easily before continuing.

First, however, it's time to learn the code.  The easiest way to do so is just to have it thrown at you at once then systematically disassembled in my experience, so that's how I'll be handling this Tutorial.  Don't be afraid at what you're about to be shown, kids.  To preface, all numbers are in hex, remember this.

180003000800020000002500000001000100000001006800020001006500040001007E00010001007F000000
010080000000040003000500030001000600050000000800050009000B000300160019000300

[NOTE - This line was broken up in order to remove a horizontal scrolling issue.  There should be no break in it normally.]

...You'll never see a monster this bad even in Vanilla's base code, but it's something you could throw together.  So, let's break this thing down.

The first piece of code we'll look at is one that appears five times in this string of numbers, 0100XX00##00.  This is the variable check command.  It takes the variable XX and checks to see if the number it contains is equal to ##, and if it finds this condition to be true, will allow the event to proceed to the next check.  Most often, this is used as a true/false trigger, looking to see if something's occurred earlier during the battle or event, or checking to see which choice was made on a conditional event.  (Think: choosing whether or not to save Algus at Mandalia Plains.)  However, these variables can hold more than just 0 or 1, so creative use can allow you to further track things about events the player has or hasn't triggered.  It's also worth noting, obviously, that these variables are indeed saved and tracked by the game over the course of a playthrough - meaning you should reset a variable when done with it to avoid errors, but also meaning full on branched-paths are indeed supported by the game if you can allocate the space to them.  Note that variables themselves are not incremented by ATTACK.OUT, but in the events themselves located in TEST.EVT.

There are some special variable calls listed here though, specifically 65, 68, and 80.  65 and 68 are very rarely used - their only purpose in Vanilla is to track how far the player has traversed into the Deep Dungeon and which floor tile is currently the active exit tile during that particular battle.  As such, they are only listed here for completion.  The one that will be used more often is 80 - this is the game's "end of battle" variable, which does what it says on the tin, making sure the battle hasn't ended before playing the event.  The note here, though, is that this check is rarely needed, as most conditions to make an event play cannot be completed while ending the battle simultaneously.  It *can* be needed sometimes, so remember it exists, but it is not a necessary check in most cases.

Tl;dr - Use 0100XX00##00 to check variable XX for value ##, which is set by the Event and not ATTACK.OUT, remember they carry over, remember that 65, 68, and 80 are reserved for special game functions, though 65 and 68 can be used if you intend not to use the Deep Dungeon in Vanilla's form.

1800030008000200000025000000010001000000040003000500030001000600050000000800050009000B000300160019000300

This leaves us with this, already much more acceptable.  Since I've covered one of the key functions of Deep Dungeon, I'll cover the other, along with a very similar feature only used once in the whole game.  First, let's cover 1800ID00XC00YC000000, the command used at Bethla Sluice for opening the flood gates and at Lionel Castle for lowering the gate.  This checks for Unit ID based on the ENTD, then checks to see that the unit being looked for is on the square specified by XC (X-Coordinate) and YC (Y-Coordinate).  Anyone who has touched an ENTD or remembers the most basic of basics from Geometry class should see how this is applied.  Use the maps on the front page of the site to get an accurate top-down view of each map and set the correct X and Y coordinates.  25000000XC00YC000000 is the other, similar command used in Deep Dungeon - it functions exactly the same, but doesn't require a Unit ID field, meaning any player-controlled unit can trigger the event in question.  Knowing both exists can be a life-saver for anyone wishing to use this command, since it gives the choice as to whether or not a specific unit is required to trigger the event in question.

Tl;dr - use 1800ID00XC00YC000000 or 25000000XC00YC000000 to create events that run based on units that step on specific tiles, the former if a specific unit is needed and the latter if not.

040003000500030001000600050000000800050009000B000300160019000300

Look at that code peel away!  Now we can knock out three simple commands in quick succession!

0400ID00 is a simple command - it checks to see if the Unit based on Unit ID in ENTD exists on the map.  Mostly useless since oftentimes you want to check if the unit is also alive, or dead, or other various things about it, but it's good for the rare situations where all that info actually doesn't matter, such as Delita's infamous cutscene-powered get-back-up at Fort Zeakden.  The next two commands we'll be discussing are far more universally useful.  0500ID000100 checks to see if the unit is alive.  The uses of this command are obvious - it stops a unit called by its ID in the ENTD from speaking if all other circumstances needed to trigger an event are true and said unit died somehow.  You will usually want this unless you intend for that scene to include a dramatic Delita get-back-up, or are using the next command I'll be discussing.  This command is 0600ID000000, which is the unit dead check.  This command is most often used during Assassination Missions where your goal is to actually murder your target, and as the defeat condition trigger for situations such as "Save Rafa!" at the top of Riovanes Castle.  As per usual, ID is the Unit's ID in the ENTD.  All simple commands whose uses are fairly obvious, I hope.

Tl;dr - 0400ID00 checks to see if the unit exists and is usually unneeded, 0500ID000100 checks to see if the unit is alive, 0600ID000000 checks to see if the unit is dead, three simple but useful commands.

0800050009000B000300160019000300

Just a few more commands left now!  0800ID00%%00 is another useful command, often seen on those pseudo-Assassination Missions where the goal is to really get a target below X% health, which is exactly what this command checks for - Unit ID by ENTD at less than or equal to %% hex-percent health.  Very simple and easy to use.  0B00ID00 is another simple command to use, as it checks to see that the Unit by ID in ENTD has active turn.  This is useful for things like the Bethla Sluice "help" hint, where Ramza mentions the floodgates during his first turn, and other, similar scenarios.  It can be combined with clever variable usage to create back-and-forth conversations between units each time one of them has active turns, or to have an event trigger on a certain unit's Nth turn, though the latter especially requires some high-end critical thinking to be done effectively and efficiently.

Tl;dr - 0800ID00%%00 checks for a unit's health percent to be equal to or lower than the input value in hex, 0B00ID00 checks for the unit to have active turn.

160019000300

This is all we have left, the most primitive and common commands.  1600 takes no input, and needs no input - it checks to see that all units on all existing teams besides the player team have been defeated.  1900#### is the process run if all conditions before it return true - 1900 here is the command, and when all conditions are true, will play the event located at Event Script ####.  While events are usually in sequence, this *does* mean you can call events out of sequence if you have a reason to do so.  This is an odd quirk that most people shouldn't need, but can easily be put to work as necessary.  However, remember that the bytes here are inverted.  So, trying to run Event Script 01EA would be input as 1900EA01.  This can seriously screw you up if you forget this and send you bug hunting for errors that don't exist, so take care to always make sure you are using the proper coding convention here.

Tl;dr - 1600 is the "killed everything" flag, 1900 tells the game to run next event if all things before it return True, #### tells the game which event is the "next event."

So, to say, apply this knowledge... let's make a quick event.  01007F000100050003000100080003000F000B00030019008F01.  What does this event do?

Go on.

For those who didn't figure it out, it checks to see if variable 7F is equal to 1, likely meaning a previous event in the fight must be triggered before this one.  Then, it looks to see if Ramza (Chapter 4 variant specifically) is alive, at 16% health or less, and has active turn.  Then, if all these factors are true, it plays Event Script x018F.  If even one of these conditions returns false, the event does not play.  Simple and Lego-like just as I said, right?

However... there is one more small piece of code to remember.  0100FD0101001900####.  This is special initializer code for the very first event in the battle or cutscene, telling the game to play the Event Script after 1900 without any checks.  Use it basically always as the code for the first event of every cutscene or battle situation you create.  Nothing more, nothing less.

Tl;dr - 0100FD0101001900#### should be the entire conditional code for the first event of every battle or cutscene you create.

"But Raven, the Spreadsheet!  What the frell is that?!"  You cry!  Well fear not, for despite this long tutorial, I have not forgotten!

It will be attached to the bottom of this post, and can be opened in either Microsoft Excel or OpenOffice.  It contains the hex code for all the battle conditionals.  However, since this is my version of it, all redundant code checks have been removed, making this far easier to read and edit for someone not familiar with the code, and far easier to add more expansive events to without hitting the code ceiling.  Put simply, when the Spreadsheet is open, Column A will list exactly how to use it - when you're done editing code, click the blue bar (Column B), copy, and *write* to the offset in ATTACK.OUT referred to by Column A using your Hex Editor of choice.  Note that you *must* use the Write command and not the Paste command, or serious errors will occur.  To edit a particular battle, simply find its header in the Spreadsheet, click the line of code you want to modify, and go to town.  A little bit of playing around will make how it works fairly obvious now that you have the knowledge of what those numbers actually mean at your disposal.  And yes, for those who didn't know, that's how the game is organized in Vanilla, incredibly sloppily and slapdash.  The bar that says "Safe" in green with a fraction above it tells how many bytes of ATTACK.OUT you are currently using vs the maximum you are able to.  When adding a lot of content, it is good to be wary of this fraction.  The Spreadsheet I am supplying you with only uses 7294/8636, so there is plenty of space to play, and yes, someone was payed to code that badly.  Funny world, eh?

Hopefully, this tutorial will help people having problems getting their ATTACK.OUT battle conditionals to work how they want them to overcome those problems with ease, while also teaching how to use every single bit of code at their fingertips to maximum effect and efficiency.  If there are questions or suggestions for improving this tutorial, feel free to leave them.

pokeytax

This looks good, but right now I'm reading it from the topic summary in the "post reply" page because the long hex strings induce horizontal scroll - please break 'em up!
  • Modding version: PSX


fluke84

February 10, 2011, 09:16:51 pm #3 Last Edit: February 10, 2011, 09:17:40 pm by fluke84
yay :D

I appreciate the tutorial, with this and kokojo's I think I can start piecing together my battle/event chain.
  • Modding version: PSX
I'm back...

Eternal

Get your butt on IRC, Fluke. We miss you!
  • Modding version: PSX & WotL
"You, no less human than we? Ha! Now there's a beastly thought. You've been less than we from the moment your baseborn father fell upon your mother in whatever gutter saw you sired! You've been chattel since you came into the world drenched in common blood!"
  • Discord username: eternal248#1817


Cheetah

I'm surprised I never noticed this topic before. I have a tutorial on the same stuff, I just did it two years earlier. The compliment eachother well and I believe Raven has a better understanding of the underlining mechanics, but mine might be easier for some to read and has more resources.

http://ffhacktics.com/smf/index.php?topic=1961.0
Current Projects:

RavenOfRazgriz

That's what got me started on ATTACK.OUT editing, hah.

I ended up writing this because this is exactly how I was teaching people how to edit ATTACK.OUT privately, and everyone seemed to be able to understand this style, so I literally just took some chat logs, reformatted them, and fleshed them out into this.

Anything you can't find here should be in that topic though, yeah, and seeing two ways to break down the same thing is always good for learning purposes.

LastingDawn

I... did not even know this spreadsheet existed. Great refresher course as well Raven, but it does leave some unanswered questions... well, only one I can think of at the moment.

Is there any way to have the game look for a certain status that isn't Dead to activate an event?
"Moment's anger can revert to joy,
sadness can be turned to delight.
A nation destroyed cannot be restored,
the dead brought back to life."

Art of War

Beta & Gretchen Forever!!!!

Cheetah

There are a lot of unused values. I would assume that there is a way, but since it is never used in any events I couldn't tell you what it is. You could always try trial and error, or maybe there is some ASM approach.
Current Projects: