Hey everyone! All of you that caught Kori's most recent map making stream saw him play through an event / battle series that I created for the map pack. This battle series included 7 battles that the player party went through where they didn't recover HP/MP/Statuses/other stuff between battles, and although it looked to be about 9 event slots, it was actually only using 1. This post is to explain how the magic happens!
Here is the video for reference (Thank you ArmoredKori!) (https://www.twitch.tv/videos/1044234167)
Go subscribe to this man on Twitch ASAP.
Here is a link to the pastebin of the event.txt (https://pastebin.com/2yqGCw0b), which I will also be attaching below. Feel free to use it as reference for creating your own Battle Series events!
The SetupHere are images showing how I set up the ENTD, World Map Conditionals for triggering the event, Attack.Out, and Event conditionals.
I had to adjust the Orbonne event to make space for my event! I also moved the Orbonne event from its original spot (offset 4000) to its setup event slot (offset 2000).
Just one slot?? That's right!
As you can see, all units except for Worker 7 are set not to be present at all. This meant for me that every time I ChangeMap'd and the ENTD data was reloaded, I only had to RemoveUnit Worker 7 and could AddUnit in the enemies I wanted for the fight.
Again, I had to modify Orbonne's event conditionals to make space for my event. RIP Vanilla, everyone please use TLW as a base (or make a totally custom mod) instead.
I appended my new events conditionals to the end of Vanilla's list. You can see how I got the event to be called over and over again, each time the player wins the fight the event is called again. In the event you can see that I only tell it to go back to the world map if the player beats every fight or if they refuse the challenge.
The world conditionals. This fight is only available in Chapters 2 and 3 because I can control Ramza with his unit ID 02 in those chapters, and I didn't want to put in the effort to check what his unit id was and swap it in if you tried it in chapters 1 or 4 (where his unit id is 01 and 03 respectively). The variable I am using for the check here is actually what background the shops are currently set to!
The Same Event Multiple TimesIf you've opened up the event.txt you'll see that it starts with a switch statement.
//Var x0070 will be used to track what part of the event to run
Switch(x70)
Case(x0001) //PART 2
JumpForward(x02)
Break()
Case(x0002) //PART 3
JumpForward(x03)
Break()
Case(x0003) //PART 4
JumpForward(x04)
Break()
Case(x0004) //PART 5
JumpForward(x05)
Break()
Case(x0005) //PART 6
JumpForward(x06)
Break()
Case(x0006) //PART 7
JumpForward(x07)
Break()
Case(x0007) //PART 8 (FINAL)
JumpForward(x08)
Break()
Default() //First part no jump, run part 1 below
Break()
EndSwitch()
Every time this event starts, this Switch checks Var x70, if its value matches a Case, it will run that section. Each of those sections has a JumpForward that brings it to the appropriate part of the event. At the end of every 'PART' of the event, I use JumpForward(x01) to go to ForwardTarget(x01), which is right before the end of the event so I can skip over the parts we haven't gotten to yet. This allows us to create an event that is itself its own Pre-battle, Mid-battle, and Post-Battle events. At the end I use the PostEvent(x80,x0000) command to bring the player back to the world map.
A single event can be quite large, this event has a ton of instructions in it but only uses 5952 bytes out of a possible 8192. If you wanted to create an even longer battle series you could write events that have better looping logic to save space, or use more than one event slot. I just wanted to show that if you really wanted to, you could significantly reduce the amount of space required for multiple events (so don't ever say that FFT doesn't give you enough space!). SOMETIMES using a little more space to keep yourself organized might be the best way to go, especially because condensing things down to this level can make it confusing. Be mindful of why you would do something like this :lol:
Bringing The Team BackWhen you load in your party into an event with a battle formation screen and then ChangeMap, they are wiped away like the units in the ENTD that are not flagged Always / Randomly present. I tried AddUnit-ing them back in, but that presented a strange graphical glitch: Units would take hits from enemies and not react, and no damage would show up even though their health would actually change, unless they had taken a turn first. I discovered the fix for this by looking around in pSX's memory editor, here is the excerpt from the event.txt where I talk about it:
//Battle Stats x0001 has to be the same as what it was at the start of the event,
//otherwise when units are hit before they get their turn they will not react
//(But still take damage). This is just a graphical glitch, but an important one to take care of to make things looks good
//It gets set to FF on ChangeMap, so it must be assigned
SET(x0070,x0010)
UnitAddress(x02,x71)
SaveAddress(x70,x0001,x71,001)
SET(x0070,x0011)
UnitAddress(x78,x71)
SaveAddress(x70,x0001,x71,001)
SET(x0070,x0012)
UnitAddress(x79,x71)
SaveAddress(x70,x0001,x71,001)
SET(x0070,x0013)
UnitAddress(x7A,x71)
SaveAddress(x70,x0001,x71,001)
SET(x0070,x0014)
UnitAddress(x7B,x71)
SaveAddress(x70,x0001,x71,001)
I run this code block every time I ChangeMap. I believe that the numbers are correlated to the fact that in battle stats the player party are stored in those slots (The 16th (0x10) to the 20th (0x14)). The event will still run fine if the player brings less than the full party.
Bringing the Enemies BackChangeMap seems to reset ENTD data to a certain point, when I AddUnit enemies in that have previously been defeated / crystal / treasure'd after a ChangeMap, they appear with full HP and MP. I have to do more testing to see what happens with things such as Inviting an enemy and broken gear.
Wrap UpThank you to ArmoredKori for creating the Map Pack and inspiring me to do this event for you! It was fun :)
If anyone has any questions about anything I've done here in the event, that I talked about here or otherwise, please respond to this topic or message me on Discord! I hope that we can work out all the kinks of the battle series system and have it included in lots of mods in the future :o
I think that at some point in the future I'm going to do a deep dive into that video and try and figure out where things went wrong! A few notables are Ramza riding his chocobo ally at the start of one of the battles (oops, I wasn't thinking enough about walk commands in regards to that) and whatever happened to that one chocobo who couldn't be targeted and then turned one tile on all the maps into infinite crystal activations.
And no problem Nyzer! Definitely useful to have a reference for some of the newer instructions that are available to us now, and I thought this was the perfect opportunity!
Small Update: changing the variable for the current ENTD entry in memory (var x0032) and then using ChangeMap will cause the game to load up that new data into BattleStats! This means changing enemies between fights will be even easier than what I did in the example above.
I am eventually going to write a few extra instructions for the event to wipe units who are crystallized, treasured, and invite'd at the end of the fights to clear away any issues that cropped up as a result of that, and will post updated instructions for that when I do! So that people can reference it for their own mod work :)
Hmm, how can you tell if a unit didn't permanently die or if the player didn't actually add a 5th/4th/3rd/2nd member in the squad? The latter is easy I guess, since the Main/Sprite ID will be 0x00. But for permanently dead units... does anything remain to point as such? Especially if you picked up the crystal/treasure.
So there are bugs related to units perma-dying, in the stream vod link that Nyzer posted above you can see at one point a Black Chocobo on the players team dying, turning into a crystal, and then that tile on all maps just becomes a hp/mp refill spot that never goes away.
Hopefully that's easy to scrub by checking on each of the players units battle stats between map changes, but I haven't tried it yet.
EDIT: So my tests continue, ChangeMap will change the units sprite, job, name, it's max stat values (like max HP), but I noticed that two of the units that overwrote enemies from the previous map had more HP than their max, and a Black Goblin that was in a slot previously taken up by Worker 8 had the Innocent status. So it seems like ChangeMap doesn't correctly adjust temporary stats