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

Creating a Battle Series and Condensing Multiple Events Into 1

Started by Jumza, June 03, 2021, 11:31:18 am

Jumza

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!)
Go subscribe to this man on Twitch ASAP.

Here is a link to the pastebin of the event.txt, which I will also be attaching below. Feel free to use it as reference for creating your own Battle Series events!

The Setup
Here are images showing how I set up the ENTD, World Map Conditionals for triggering the event, Attack.Out, and Event conditionals.
AttackOut1.png
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).

AttackOut2.png
Just one slot?? That's right!

ENTD.png
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.

Event Conditionals1.png
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.

Event Conditionals2.png
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.

World Conditionals.png
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 Times
If 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 Back
When 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 Back
ChangeMap 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 Up
Thank 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
  • Modding version: PSX
Nyzer: Alma teleports out of her own possessed body.
Raijinili: Remember that you're telling a modding community that the game they love could use some fixing.

Nyzer

Jumza Hack'n Dis Madness

Also, thanks for the detailed tutorial, Jumza. I started using Switch today and it helps to be able to look at this and know I'm doing it right!
  • Modding version: PSX & WotL
  • Discord username: Nyzer

Jumza

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!
  • Modding version: PSX
Nyzer: Alma teleports out of her own possessed body.
Raijinili: Remember that you're telling a modding community that the game they love could use some fixing.

Jumza

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 :)
  • Modding version: PSX
Nyzer: Alma teleports out of her own possessed body.
Raijinili: Remember that you're telling a modding community that the game they love could use some fixing.

Nyzer

Quote from: Jumza on August 25, 2021, 09:13:41 pmSmall 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.

Holy shit, that's amazing!
  • Modding version: PSX & WotL
  • Discord username: Nyzer

Xifanie

Won't this also affect the player's units though?
Or does changing map after the victory screen keep all permanent changes and restore their HP/MP/status/etc.?
  • Modding version: PSX
Love what you're seeing? https://supportus.ffhacktics.com/ 💜 it's really appreciated

Anything is possible as long as it is within the hardware's limits. (ie. disc space, RAM, Video RAM, processor, etc.)
<R999> My target market is not FFT mod players
<Raijinili> remember that? it was awful

Jumza

Quote from: Xifanie on August 25, 2021, 11:42:15 pmWon't this also affect the player's units though?
Or does changing map after the victory screen keep all permanent changes and restore their HP/MP/status/etc.?

What I do in this event is basically rely on the fact that the players data in Battle Stats is not overwritten on ChangeMap, all it does is write xFF to 0x0001 in their data. As long as you rewrite it to match your units position in the battle unit array (units stats table) and then AddUnit them back in, you're in business! As far as I can tell, it preserves everything for your units
  • Modding version: PSX
Nyzer: Alma teleports out of her own possessed body.
Raijinili: Remember that you're telling a modding community that the game they love could use some fixing.

Xifanie

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.
  • Modding version: PSX
Love what you're seeing? https://supportus.ffhacktics.com/ 💜 it's really appreciated

Anything is possible as long as it is within the hardware's limits. (ie. disc space, RAM, Video RAM, processor, etc.)
<R999> My target market is not FFT mod players
<Raijinili> remember that? it was awful

Jumza

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
  • Modding version: PSX
Nyzer: Alma teleports out of her own possessed body.
Raijinili: Remember that you're telling a modding community that the game they love could use some fixing.