FF8/BattleStructure
By JeMaCheHi
Scene.out contains enemy placement data and flags for each of the game's battle encounters.
See the corresponding thread: http://forums.qhimm.com/index.php?topic=15816.0
Encounter list: Original encounter codes
File Structure
Scene.out contains no header. It is a raw list of 1024 encounters. Each encounter block consists of 128 bytes and has the following structure:
Offset | Length | Description |
---|---|---|
0x00 | 1 | Battle scenario. The value here corresponds to the number in the a0stg???.x files (into battle.fs file). You have to convert it to hex |
0x01 | 1 | Flags to configure some battle parameters and it works like 8 binary flags (see below) |
0x02 | 1 | Main camera animation. This is for the battle entrance animation (when the party and the monsters appear). The first nibble represents the camera number, the second one the animation number. (See below about cameras) |
0x03 | 1 | Secondary camera. Works exactly the same as the main camera, but this one will be used less frecuently.(See below about cameras) |
0x04 | 1 | Hidden enemies. Hides an enemy for each activated bit in the byte. (see below for "enemy flags") |
0x05 | 1 | Loaded enemies. Show the enemies that are been actually fought. Loaded enemies will attack you(also, refer to "enemy flags"). |
0x06 | 1 | Targetable enemies. Show the enemies which will appear in the target window. Careful with this, if you put untargetable enemies battle will never end. (see "enemy flags" too) |
0x07 | 1 | Enabled enemies. Also works like eight binary flags. Each activated flag is an enabled enemy. If the flag for a certain enemy is disabled, the three previous sections will be ignored. See below |
0x08 | 48 | Enemy coordinates. Its a set of 6x8 bytes which describes each enemy's coordinate in (x,y,z) format. So, first 6 bytes would be enemy 1's coords, next 6 enemy 2's ones, and so on. |
0x38 | 8 | Enemies. Each byte represents an enemy. To know what enemy you're working with, you can check the c0m???.dat files in battle.fs. You just have to convert it to hex and add 0x10. Be careful, if you put numbers under 0x10 as enemies, battle will crush. |
0x40 | 16 | Unknown. A certain enemy also has always the same value (f.e G-Soldier -> 0x7f70), and some of this values can be repeated between enemies. Slots with no enemies (with a dummy) always have the value 0x00C8. |
0x50 | 16 | Unknown. It always has the same value as the previous section. |
0x60 | 16 | Unknown. A certain enemy has always the same value but different from the two previous sections. Slots with no enemies always have the value 0xEA60 |
0x70 | 8 | Unknown. Once more, A certain enemy has always the same value but different from previous sections. |
0x78 | 8 | Enemy level. Each enemy level is 1 byte. Numbers from 0x0 to 0x64 are fixed levels up to 100. From 0x64 to 0xFF... Still don't know because it makes weird things... |
About flags
Each 128block can have up to 8 enemies, but if more than 4 are shown at the same time, the game will crash. This could seem stupid, but it's not. If you think about some battles, like the final battle (where we have 8 enemies), all the monsters are present, but only one or two are shown at any given time. The rest appear through scripting.
Some byte fields are just 8 flags contained in a byte. To configure it you just have to sum the values you need. Here's what I've found:
In 0x01 (battle configuration flags):
- +0x80: Not random fight. Every scripted battle has this one enabled.
- +0x40: Force back attack (you will be back attacked, not the enemy).
- +0x20: Force surprise attack (as before, you are the one surprise attacked).
- +0x10: Doesn't show exp screen at end.
- +0x08: No exp will be gained at the end of battle (like in boss battles).
- +0x04: Shows the timer on battle. Like in dollet withdraw combats, or missile base.
- +0x02: This disables victory fanfare.
- +0x01: Can't escape.
In 0x04, 0x05, 0x06, and 0x07 (hidden/loaded/targetable/enabled enemies).
- +0x80: 1st enemy flag
- +0x40: 2nd enemy flag
- +0x20: 3rd enemy flag
- +0x10: 4th enemy flag
- +0x08: 5th enemy flag
- +0x04: 6th enemy flag
- +0x02: 7th enemy flag
- +0x01: 8th enemy flag
An important note: If you put an enemy that "summons" another one (Ultimecia summoning Griever, Sphinxara summoning jelleye...) it will summon the enemy from certain slot. This means that if you put that enemy in another battle, it will still summon that slot, because (It's now confirmed) that summoning is scripted in its AI (in c9m???.dat) as an enemy ability.
About Cameras
Each encounter has two cameras, as explained above. Each camera is represented by a byte, but each byte stores two things: The camera number, and the camera animation. The camera number is stored on the most significant nibble of the byte (4 bits) and the animation is stored on the less significant nibble of the byte. I called it "Camera number" because I had to name it somehow, but I'm not even sure if they're different cameras, or just are "sets" of animations. Anyway, we'll call it that way until we find a better one.
The game engine will use one or other camera randomly, but will use the main one way more frequently (in my tests, for each 5 battles, the game used the main camera around 4 times)
Also, a few considerations about these camera parameters:
- -Camera number. It can take values from 0 to 3. The original scene.out never has greater values. Values greater than 3 will result in no camera animations, having a fixed camera. Some stages have less than 3 camera numbers. This leads me to think that this camera stuff is really stored on .x files, and this values are just pointers, or indexes, or something of the kind.
- -Camera animation. It can take values from 0 to 7. The original scene.out never has greater values. Values higher than that will result in the same as that value minus 8. This is because the last bit of the nibble is ignored (still don't know why). Sometimes the camera has less animations than 7. In that case, if you use a number greater than actual animations, taking into account that the 4th bit is ignored, will result in a fixed scene.