Snake's Pit of ASM (and Other Stuff)

I understand, figure I’d ask

Modular Supply
This is pretty straightforward. This hack allows you to define a list of characters who can use the supply for each chapter. This also considers whether the armory man lets you send items to the supply or whether you discard items when getting an item with full inventory.

How to: Pull a chapter 5x and surprise players by making them drop the elixirs they worked so hard to get.

Go ahead and download the whole ModularSupply folder from my Dropbox in the OP. Include ModularSupply.event and integrate the csv you find there. This is the csv indexed by chapter, and each entry is a pointer. A null entry means no one can use the supply.

	ALIGN 4
	NormalSupplyList:
	BYTE Eirika Ephraim 0x00

Each pointer is a list of character IDs who can use the supply. This is a sample list. Don’t forget to terminate with 0!

That’s kind of it. There are no known conflicts, and this was made with CHAX. (Shoutouts to everyone helping me out with C. :wave: Thank you!)

In other news, my hacks that conflict with the Skill System have been integrated into the Skill Sytem buildfile, resolving the conflicts. If you are using it and wish to also use my hacks, please update the Skill System, go to _MasterHackInstaller.event, and uncomment the hacks you wish to use. My installation directions in previous posts have been updated accordingly.
This includes:

Anima Triangle (conflict with Tri-Adept)
ModularEXP (conflict with Paragon)
Conditionally Loading Portraits (conflict with RandomMugs3)
Stairs (mov debuff incorporated into MSG and unit menu incorporation)
Raid (unit menu incorporation)

In other other news, a small yet important fix has been made to Support Rework where bonus stats wouldn’t be gotten correctly from the bonus table.
And in other other other news, coming soon is support for dancing and summoning EXP modification in ModularEXP and defining item gets from base support convos in Support Rework.

Please let me know of any bugs with the supply stuff or Skill System things that probably were may have been may fault!

6 Likes

It’s been a while, but I’ve got a small little hack.
Set Scripted Battle Number Display
Tired of scripted battles having more or less damage dealt than the number displays in the battle screen? Or 100 hits missing? Or 0 crits? All from battle units having variable stats or being too lazy to set the characters’ stats? No more!
ScriptedBattes
Had a fun testing environment here
All the numbers you see here are set in my events while setting up the scripted battle rounds using the following macro (defined in the installer for you):

SetScriptedBattle(AtkHit,AtkDmg,AtkCrt,DefHit,DefDmg,DefCrt)

To make a number appear as --, use 0xFF in the macro.
To clarify: this does NOT affect the results of the scripted battle. This only changes the display.

Just get everything from the Dropbox in the OP, include “ScriptedBattles.event”, and you’re good to go!

Next on my plate in terms of big ASM is stuff with Support Rework to make base supports more versatile and maybe not necessarily tied to supports themselves. Could use some optimization as well.

Ability to define an event to play instead of a text ID being shown in a generic event
Add an optional ASM condition slot for event conversation
Add an optional text ID to show for the menu text instead of autogenerating if defined
Add a bitfield saved somewhere (prep screen proc state?) that says whether a convo has been seen or not
Disallow repeating viewing convos with this bitfield
Maybe allow them to define an optional music change in the base support table for the base convo?
Let the user define conversations that have an icon (usually to denote which give items or w/e they want)

As well as some MSS stuff for displaying support data on the stat screen spookily. :ghost:
I’m open to suggestions here, so let me know what you’d like to see in Support Rework if you’re interested. I’m looking for feedback!

6 Likes

Doesn’t Ability to define an event to play instead of a text ID being shown in a generic event cover Maybe allow them to define an optional music change in the base support table for the base convo, as you can just play the music with the support event?

That’s what I was thinking, but it may be a lot of trouble to make a new event if someone frequently wants to do a music change. This is the generic event.

CallBaseConvoEvents: // This is called assuming the text ID to show is in memory slot 0x2
		EVBIT_T 0x4
		CALL $9EE2E8 // Sets the background of index in slot 0x2. Set by BaseSupportConvoX.
		MUSI	
		SADD 0x032 // Move slot 0x3 into 0x2
		TEXTSTART
		TEXTSHOW -1 // Shows text in slot 0x2. Set into slot 0x3 by BaseSupportConvoX.
		TEXTEND
		REMA
		ASMC BaseSupportIncreaseSupport|1
		MUNO
		FADI 0x5
		CLEAN
		SVAL 0x5 0x1 // Used by the base support proc to see if the events are finished running.
		NoFade
		ENDA

So I was hoping to avoid a small edit like that requiring rewriting a new event.
I’m also thinking using an event file to contain the base support convo table would be superior to a CSV. Actually I’m pretty certain I’m gonna make that transition.

1 Like

Generic Base Conversations
So I’ve had a functional base conversation system integrated with Support Rework, but there was no way to have base conversations without messing with support levels and having Support Rework installed. For the past… couple weeks or so, I’ve been completely rewriting the base conversation system and splitting it from Support Rework.


Do the titles text, music, etc. seem random to you? That’s because they pretty much are. Head into the “How to” > Example section to see how I pulled this off!

Supported features:

  • A base conversation table that’s easy to use. Not a disgustingly massive CSV anymore!
  • Displaying a specified background (Required with the generic event)
  • Defining an optional ASM usability pointer for each menu item
  • Defining a title for each base conversation
  • Defining an ASM text getter if no title is detected
  • Having music to play during the conversation. If none is specified, MUSI/MUNO will be used
  • Showing text during the event (the conversation itself, also required for the generic event)
  • Giving an item to a character (if the character doesn’t exist, no effect)
  • Loading units into your party (define a pointer to UNIT data)
  • As a catch-all, defining a custom event to play instead of the generic event (more advanced conversation techniques, i.e. TEXTCONT, multiple text IDs/backgrounds, etc.)
  • Defining an importance value for each conversation (number of exclamation points on the far right to show for the menu item similar to stars in Tellius)
  • B press handling on the menu to go back to the prep screen
  • Specify an event ID to use with similar behavior to chapter talk events
  • No known hack conflicts including the Skill System!

How to: Uh I don't have a joke for this one; you guys write the text not me.

As always, you’ll find all materials you need in the folder link in the OP.

This comes with my Prep Screen Hack installed. It’s required for making the prep screen usability function properly.

You’ll need to integrate the CSV with that hack. This hack replaces the support viewer handler proc, so you don’t need to change the effect pointer. You’ll need to make the “greyed out” usability BaseConvoUsability|IsPointer. You can change the text to whatever you like with the other fields.
Doing this makes sure that the player can’t enter the convo viewer screen if none are viewable.

Now that that’s out of the way, you’re going to want BaseConvos.event included in your buildfile.
There’s pretty much nothing you need to worry about from this file unless you don’t want text IDs 0x2D through 0x34 consumed. These are used by default, but you can use any other text IDs by having those text IDs defined in your text buildfile.

For allocating those text IDs:
## BaseConvoTextID1
[X]
## BaseConvoTextID2
[X]
## BaseConvoTextID3
[X]
## BaseConvoTextID4
[X]
## BaseConvoTextID5
[X]
## BaseConvoTextID6
[X]
## BaseConvoTextID7
[X]
## BaseConvoTextID8
[X]

What you really need to concern yourself with is BaseConvoTable.event. This is where you’ll define the behavior of your conversations.

Example behavior shown in the video (don't mind my nonsensical debug text):
Chapter(MilitaryAccept3)
	Entry
		bg(0x30)
		name(Military3AcceptNameText)
		text(Support1Text)
		music(Aquatic_Ruin)
	Entry
		bg(0x2F)
		name(Military4AcceptRetreatNameText)
		text(Support2Text)
		item(SilverSword,Zaheva)
		music(Venus_Lighthouse)
		importance(2)
	Entry
		name(Military5AcceptRetreatLeaveNameText)
		event(BaseConvoTestEvent)
	Entry
		bg(0x2D)
		name(Military6AcceptRetreatLeaveNameText)
		text(Military1BeginningText)
		item(Elixir,0xFF)
		music(Derris_Kharlan_Appear)
		importance(2)
	Entry
		bg(0x2C)
		name(Military7AcceptRetreatLeaveNameText)
		text(Military1SylvaineBriefingText)
		importance(1)
	Entry
		bg(0x2B)
		name(Merc1NameText)
		text(Military1EndingBeginningText)
		music(Last_Battle_Decision)
		unit(LoadBaseConvoSylvaine)
		importance(3)
	Entry
		bg(0x2A)
		name(Merc2BanditNameText)
		text(Military1ForrestBattleText)
		item(SteelBlade,Madeleine)
		music(Green_Emerald)
		importance(1)
	Entry
		bg(0x29)
		name(Merc3BanditNameText)
		text(Military1ChristinaBattleText)
		music(Oil_Ocean)
		unit(LoadBaseConvoChristinaForrest)
		importance(3)
Chapter(MilitaryAcceptRetreat4)
	Entry
		bg(0x10)
		name(Military6AcceptRetreatLeaveNameText)
		text(Support3Text)
		music(Casino_Night)
	Entry
		bg(0x13)
		name(Military7AcceptRetreatLeaveNameText)
		text(Support1Text)
		music(Heavens_Gate)
...
// Later at the bottom of the file...
ALIGN 4
BaseConvoTestEvent: // Refer to the generic event in BaeConvos.event.
EVBIT_T 0x4
SetBackground(0x10) // REQUIRED, Load a background!
MUSC A_Tragic_Decision
TEXTSTART
TEXTSHOW Military4AcceptRetreatTactDecisionText // Example usage of a custom event: TEXTCONT with music changes.
TEXTEND
MUSC Emergency
TEXTCONT
TEXTEND
REMA
FADI 0x5 // This fade is highly recommended.
CLEAN // This is REQUIRED.
SVAL 0xB 0x1 // REQUIRED to mark when events are finished running.
NoFade
ENDA


LoadBaseConvoSylvaine:
UNIT Sylvaine ArmoredWyvernLord Sylvaine Level(9,Ally,True) [0xFF,0] 0x00 0x00 0x00 0x00 [SilverLongbow] NoAI
UNIT

LoadBaseConvoChristinaForrest:
UNIT Christina Cavalier_F Sylvaine Level(9,Ally,True) [0xFF,0] 0x00 0x00 0x00 0x00 [SteelBlade] NoAI
UNIT Forrest Cavalier Sylvaine Level(9,Ally,True) [0xFF,0] 0x00 0x00 0x00 0x00 [ShortSpear] NoAI
UNIT

I’ve tried to make this as easy to use as possible with macros. Start writing convos for a chapter with the Chapter(chapter) macro. Head each individual new entry with the Entry command.
The two required components of each base conversation are the bg and text components. Bad things will happen if you don’t define these. All other fields are optional (though the name field for the title of the base convo is required unless you have a text getter).
Visit ConvoTableDefs.event for all available macros! Any others not mentioned here are optional. These macros can go in any order you like within a single entry. The order in which the entries are written are the order in which they will appear in the conversation viewer.

Quick note on custom events:

You may have noticed the event field which allows you to play a custom event instead of the generic event. This is a “catch-all” in case these macros don’t suit your needs (TEXTCONT, multiple items given, multiple text IDs, etc.). This is extremely versatile, though there are a few requirements to make your event run properly.

  • EVBIT_T 0x4 is needed at the beginning of the event.
  • Loading a background is necessary at the beginning of the event.
  • Fading before exit is highly recommended.
  • After the fade, the commands CLEAN and SVAL 0x1 0xB are necessary before exit.

There can be no more than 8 base conversations per chapter! This is due to graphical limitations.
Finally, you’re going to want this defined somewhere in your text buildfile. This is the text that displays at the bottom of the base conversation screen.

## BaseConvoSelectConvoText
Select a conversation.[X]

This is completely independent from Support Rework, but that doesn’t mean I haven’t designed parts of it to play nicely with that future integration. Like the text getter for titles as well as allocating some of the convo entry space for future use there. Support Rework acting as an extension of this (or maybe the other way around idk yet) will be coming in the future.

I’m open to suggestions for whatever you may want to see in the generic event. The code for this was written in C, so let me know if you have questions about that or about the system in general. (Shoutouts to @StanH for the pretty amazing CHAX system that made this revision way less painful than it would have been with handwritten asm again!)

(Also while I’m here, I may as well mention I fixed the bug with the prep screen hack where the greyed out description text would not be gotten properly. I’ve also updated Repointers.event with a couple fixes/aditions.)

16 Likes

I guess the joke would be “How to: have normal conversations before you go out to fight.”

2 Likes

Awesome work there! Making conversations that much more fun.

Also just wanna say this, Christina is hot damn.

1 Like

Ya God damn right.

1 Like

So basicly, can the support rework and generic baseconvos coexist? And can one change parameters after applying or do I have to be sure from the get go what I want to do with it?

It is really complicated for me(Reason I usually stay away from build files unless I have to use it), but it will surely help me in a hack I want to make this year that is supposed to be a retelling of FE4 in a…“weird way”.

Base convos and support rework do not go well together in their current forms, but I am working on rewriting support rework for many reasons. One of the goals is to have it integrate nicely with base convos. (The others involve splitting the features of it into toggleable parts.)

The system is designed for a buildfile, so it’s easy to apply the hack early on and make changes (add and modify individual base conversations as you go) if you’re using a buildfile from the start. If you’re mainly using FEB, this is more tricky. You could make changes to your base convos and reinstall the entire hack every time, but that would be a waste of space. Alternatively, you could install the hack once, find the location of the BaseConvoTable, then only install your new table each time you want to make changes to it.

I do use FEBuilder, so rip me I guess

HP Bar Palettes

Gifs

ByqTuyAJgW
VKPs3wEpU4
g92u6W6lnl
Supports mid-battle palette changes!
teq
@Tequila told me to do it blame him for this one, but make any colors you like!

Think you can do better than these palettes? You probably can, so try out your own!

Firstly, shoutouts to @anon30371999 and @anon686116 for the initial research and finding out this curiosity!
It turns out in vanilla FE8, there are actually different palettes allocated in ROM for different allegiances. They’re just all the same. You may have noticed 2 palettes are cycled through: a darker one, and a lighter one. (If you look even closer, there are a at least one more generated intermediate palette which appears to be an “in-between” for the 2 extreme palettes.)

What else is interesting is there are palette banks in RAM for both sides’ palettes. This means one unit can have an HP bar palette independent of the other unit. These palettes are almost always the same with the exception of excessive HP units (like the demon king) which have a bluer HP bar (which should still be supported in this hack).

So what this hack does is allow you to define default palettes by allegiance and by ASM usability via a small table as well as change the palette as it updates (like during losing HP, etc).

How to: Be flashy with your HP bars!

As always, download from the OP.

This hack should be pretty straightforward. You’ll mainly concern yourself with the HPBarTable. this is a terminated list the hack uses to get what palette to show. It uses the first valid hit it finds. If none is found, it uses vanilla default.
You’ll see in the example included:

ALIGN 4
HPBarTable:
HPBarEntry(0,BlueDarkHPPalette,RedDarkHPPalette,HPBarIsLowHP)
HPBarEntry(0,BlueDarkHPPalette,BlueLightHPPalette,0)
HPBarEntry(1,RedDarkHPPalette,RedLightHPPalette,0)
HPBarEntry(0xFF,0,0,0)

The first parameter is the allegiance (0 = blue, 1 = red, 2 = green, 3 = grey). The next 2 parameters are pointers to the dark and light palettes to show respectively. The last parameter is an optional ASM usability pointer that only allows this palette if it returns true. In the example, I check if the unit’s HP is below 50%. If so, then I allow the entry that replaces the light palette for that dark red palette.

More on the ASM usability

The environment in which the function is called is always after all rounds are rolled and the battle structs are updated. This means the battle structs contain all of the stats after the battle. If you’re trying to check current displayed HP, you’ll only get post-battle HP if you try the battle struct.

.global HPBarIsLowHP
.type HPBarIsLowHP, %function
HPBarIsLowHP: @ r0 = battle struct. r1 = which side they're on. Return a boolean.
ldrb r2, [ r0, #0x12 ] @ Max HP.
@ ldrb r1, [ r0, #0x13 ] @ Current HP. @ THIS DOESN'T WORK BECAUSE THIS IS ACTUALLY HP AFTER THE BATTLE.
ldr r0, =BattleHPDisplayedValue
lsl r1, r1, #0x01
ldrh r1, [ r0, r1 ] @ This method should get the HP that's being displayed.
lsr r2, r2, #0x01
mov r0, #0x00
cmp r1, r2
bge HPBarLowHPFalse
	mov r0, #0x01
HPBarLowHPFalse:
bx lr

You can get the HP bar images via FEBuilder export (or steal the examples), then edit the palettes to your heart’s content. Fair warning! These palettes are shared among other things in the battle screen like displayed numbers and the “Hit, Atk” etc text. Only edit the colors you need to!

Have fun, and please let me know of any issues that arise! I’m not super familiar with how palettes are handled, so I’m probably doing something wrong in here, but hey it seems to work.

17 Likes

all in a days work ;D

2 Likes

Funnily enough, @Runa and I simultaneously found an issue with my hack for setting scripted battle number display when explicitly defining an item with FIG1. That should be taken care of now. No functionality/utility changes. Just redownload from the same link in the OP if you’d like to update.

1 Like

Modular Event Parameters

I’ve been hanging on to this for a while because it just seems so niche, but eh may as well release it.

You know in FE8 events how almost (?) anywhere you can use a character ID as an event parameter, you can use certain key values instead?

If you use 0 (0x0000), it gets the leader character.
If you use -1 (0xFFFF), it gets the active character.
If you use -2 (0xFFFE), it gets the character at coordinates stored in memory slot 0xB.
If you use -3 (0xFFFD), it gets the character stored in memory slot 0x2.
If none of these keys are detected, it tries to get the character struct by character ID.

Do you ever wish you could define your own custom event parameter functions? This hack is for you! By default, this hack should reproduce vanilla behavior except that as a side feature, recursive event parameters are supported. By that I mean…

SVAL 0x2 0x0000
CHECK_EXISTS 0xFFFD

This should check if the leader character exists (which it always should now that I think about it…? Maybe this is a bad example lol)

Anyway,

How to: Make use of this extremely niche hack that I hope someone uses.

This should be pretty straightforward. Basically, this hack un-hardocdes the GetUnitStructFromEventParameter (0x0800BC50) function and instead searches a list of keys and function pointers to run for each key.
Go into EventParameters.event, and you should be greeted by a small list:

ALIGN 4
EventParameterTable:
// These mimick vanilla behavior.
EventParameter(0,EventParametersGetLeader) // Gets the party leader via $33258.
EventParameter(-1,EventParameterGetActive) // Get current unit.
EventParameter(-2,EventParameterGetCoordsInSlotB) // Get unit at coordinates in memory slot 0xB.
EventParameter(-3,EventParameterGetUnitInSlot2) // Get unit in memory slot 0x2.

// Custom ones can go here.
// EventParameter(-4,EventParameterGetFirstUnit) // Get the first character struct. Uncomment for this functional test entry.

WORD 0 0 // Terminator.

The first four entries in the list just mimic vanilla behavior. The -4 entry was mainly used for testing. If you’d like to add your own entries, they can go anywhere in the list, but the handler function will find the first key that matches. Otherwise, it will try to get the character struct by character ID. It’s up to you to write your own ASM (or C) function that handles each custom key. Each function takes the key as the only parameter and should return a character struct pointer (or null if none is found). Don’t place any entries after the terminator.

I think that’s it? EventParameters.event is the only file you need to include. As always, download is in the link in the OP.

That’s all for now. Stay healthy, friends!

7 Likes

I have absolutely no idea if I’ll ever need to use this but uhh

Cool work!

I may be wrong, but I believe it’ll come in handy for warping units or if you wanted custom village visit events, among others?

Now, I know what you’re thinking. Can I still rely on my hardcoded items that open doors and chests and all that nonsense? Sure, sure. Or… you could use… Modular Door and Chest Openers! Huh? Huh? Didn’t see that coming, did you?

Okay maybe not that exciting, but it’s about time for something that unhardcodes door keys, chest keys, and lockpicks.

Modular Door and Chest Openers

Let’s say you wanted to make a 5-use door key without affecting the 1-use door key in vanilla. Here’s how you could do it.

You know the drill... vanilla implementation is hardcoded nonsense... I'm here to unhardcode it with a nice EA installer.

Download the files from my download link in the OP and include DoorsAndChests.event.
You’ll see a new list, gTerrainUses, which links terrain IDs, an item to “open” that terrain ID, and a usability routine (like for thieves and lockpicks). By default, it mimics vanilla behavior, and an example implementation of a 5-use door key is included.

Note that this will affect opening a door or chest from the unit menu only. For creating behavior of opening a door or chest from the item use menu, be sure to update your item usability and item effect tables accordingly. (For the 5-use door key example, copying those pointers from the 1-use door key was sufficient.)

For a bit more in depth on how this function works, it would seem that the unit menu door and chest routines both share a function (0x08018A9C, what this hack hooks into) to get an item ID from the unit’s inventory that can open that terrain. If you wanted, you could make custom terrain-opening actions that use this hack and its modularity.

Also thanks to @anon686116 for reporting this one, but in my stairs hack, if a unit died on some stairs, it would disallow using the other end of that staircase to get there. That should be fixed in my independent installer, and I’ll have a PR to the Skill System version soon.

As always, lemme know if anything borks, and stay safe!

4 Likes

New Anti-huffman Patch

I noticed something the other day that was VERY naughty…
image
Seemingly due to a mistake in overwriting a bit of the vanilla pool here, you’ll see that the old anti-huffman patch does illegal reads and writes! (Not only is it an invalid address, it’s not even aligned. :roll_eyes:) In vanilla, these are supposed to reference gCurrentTextIndex presumably for optimization to avoid decompressing text more than is necessary.

This shouldn’t affect any functionality. Though I wouldn’t want to leave a loose end like that lying around, so I’ve whipped up a quick and more modern version of the Anti-huffman patch. (Credit Hexator and Nintenlord for the original version.)

I don’t even need a spoiler for this. Just downaload the files from my link in the OP and include Antihuffman.event. That’s all.

Quick note: This still uses the bit of space at 0x464470 just like the older version to preserve functionality with Autonewline.

9 Likes