Snake's Pit of ASM (and Other Stuff)

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.

1 Like

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

I forgot to update this, but I’ve made a couple changes to generic base convos. There’s a new eventID field that you may add to each base conversation. I’ve phased out the old janky system that would try to store which convos you’ve viewed in RAM that was just outright bad. I’ve tested this a lot, and it seems completely stable. Behavior with the event ID works as if it was just a chapter talk convo. I’ve also fixed a bug with returning to the prep screen theme upon exit. Get the new version from my download link in the OP!

I’ve finally finished my “Support Rework Rework” that enhances Support Rework and splits it from base conversations instead using a sort of plug-in system. I’ve actually had it finished for a while, but I’ve been sitting on it idly waiting for bugs to crop up. I’ll be releasing that pretty soon.

7 Likes

Debug Character Viewer

How’s a QoL debug ASM C hack sound today?
Avenir
Loop through character IDs, viewing their default classes and potential classes from the promotion branch table! Also includes the option to try to read from the triple promotion hack list. This is intended to make debugging animations and palettes a whole lot easier.
Down press increments the character ID, and up press decrements. (There’s an optional MaxCharacterID definition to prevent reading bad character data.)
Right press first loops through usable weapon animations (including the unarmed animation), then tries to read other potential classes.
B press ends the viewer. (I know that there’s weirdness with the active unit upon return, but don’t- don’t worry 'bout it.)
This is what I added to my unit menu:

MenuCommand(ClassDisplayNameText, 0, GreenText, 0x4F449, ClassDisplayUMEffect)

Get the hack from the link in the OP. Just add your unit menu entry and #include ClassDisplay.event. I’ve had a weird things happen with the platform not sliding in on VBA, but it seems to work fine on mGBA for me.

EDIT: Oops mixed up MaxClassID with MaxCharacterID. Definition has been changed to be MaxCharacterID as it should be since we’re iterating through characters. Sorry about that.

Have a good day!

20 Likes

I found a minor bug with the Base Conversations patch.

I have set the opening event like this:

BeginningScene:
-Some Events-
CALL $591FD8//Call the prep screen
SETVAL 0x2 0x35//Black BG
CALL $9EE2E8
CenterTutorialTextBox
TUTORIALTEXTBOXSTART
TEXTSHOW 0xB55//Yes/No Text
TEXTEND
-Conditional Event-
CALL $9EE2C4//Remove BG
EVBIT_T 0x7
ENDA

So, the events after the prep screen call should run after you press start in the prep screen. If you don’t check a base conversation the events work as intended:
1

But after you check a conversation the game proceeds to run the events after the prep screen over the prep screen.
2

Alternatively I could put the events in a Turn 1 event, but after the prep screen it fades to the map, and I want to avoid that.
3

And I don’t know why those random tiles appear in the black screen.

2 Likes

Huh yeah I’ve only tried putting events in a turn 1 event to achieve what you’re trying to. Can I see the parameters for your specific conversation?

It happens with any conversation.

Chapter(Ch9)
	Entry
		bg(0x10)
		music(EncountersAndReunions)
		name(JugdralInheritorsTitle)
		text(JugdralInheritorsText)
		importance(1)
		eventID(0x21)
	Entry
		bg(0x0A)
		music(Sorrow)
		name(KnightVowTitle)
		text(KnightVowText)
		importance(1)
		eventID(0x22)
	Entry
		bg(0x12)
		music(OneHeart)
		name(PheraeLineageTitle)
		text(PheraeLineageText)
		importance(1)
		eventID(0x23)
	Entry
		bg(0x10)
		music(CatsAtPlay)
		name(WhateverForTheCommanderTitle)
		text(WhateverForTheCommanderText)
		importance(1)
		eventID(0x24)
1 Like

Huh I’ll look into that for you.

1 Like

Today I’m proud to release something I’ve been teasing unreleased for far too long out of fear of it being buggy, but today I’m confident enough for a casual release.

TableManager

TableManager.exe is a new CSV assembler for EA buildfiles. Although similar in functionality to c2ea, TableManager is more versatile and friendlier. Download the exe and source code from my link in the OP!

Features and details

The primary feature of TableManager over c2ea is being able to combine multiple “ROM tables” that are indexed together into a single CSV file. Distinguishing where everything needs to be written to is accomplished by linking Nightmare modules to CSVs similarly to c2ea.

While c2ea assumes that you want to write the data in your table into the ROM just as it appears to you, TableManager allows you to organize rows and columns as you see fit in your CSV without necessarily affecting what you write to the ROM.

  • Sort columns in any way you like! TableManager compares the string found in the top cell of a column to a field found in a Nightmare module linked to the table in order to figure out where it needs to be written to. This means that column order is completely arbitrary, and you can even mix columns from multiple “ROM tables” together in a single CSV! I think the best example of this is the magic tables with the FE8 str/mag split. Isn’t it annoying having to have separate CSVs for those? Now you can have magic data right alongside other character/class data as if it was a vanilla stat, and TableManager sorts out where you want it all to be written! You may also leave empty columns.
  • Sort rows in any way you like! Or not if you want that! TableManager allows for writing each ow sequentially to ROM just like c2ea does, but it also offers a feature that treats the far left cell of any row to act as an index that you want that row to represent. This can be a value or an EA definition. With this option turned on, you would expect each row to be written with an ORG TableLabel + (FarLeftCellOfRow)*(EntrySize) format. The ultimate implications of this are that you don’t need to know the values of custom indices to work with them in CSVs, and you can reorder rows in any way you like! You may also leave empty rows.

Run the .exe with the -h flag for more info on command line parameters.
To use, you must pass in a table options file and an intended output file like so:

echo: | (TableManager.exe TableOptions.s TableInstaller.event --error_on_missing)

This is the command I use in my batch to assemble my CSVs. (The extra flag is something I like to use. Again use -h in the command line for more flags.)

So what is this table options file I refer to?

This file is a file that TableManager reads in order to understand how you want each CSV to behave. Here’s how it works.

  • Each CSV that you want to be assembled needs to be referenced by a CSV (FilepathToCSV) header.
  • Within each CSV header, you may link an arbitrary number of Nightmare modules with TABLE (LabelForThisROMTable) (FilepathToNMM) (OptionalAddingOffset) (Optional INLINE or FIXED to override the CSV INLINE setting for this TABLE only). The optional adding offset is to allow tables that are indexed together but with an offset to be combined into a single CSV file. This is most specifically included for the item usability/effect/target switch case tables. For example, I use TABLE ItemUsabilityTable Items/ItemUsabilityTable.nmm -0x4B for the item usability table because each index in the ItemUsabilityTable is 0x4B behind the ItemTable.
  • State whether you want this table to be written to freespace or not with INLINE (True or False) If False, the assembler will try to write to the vanilla offset in the Nightmare module.
  • For behavior in writing all rows sequentially ignoring the far left column, use WRITE_SEQUENTIALLY (True or False). If not writing sequentially, 0-space will be allocated using FILL in EA for the entire table, and entries will be filled in as the CSV describes them.
  • MAX_ENTRIES (MaxNumEntries) declares how much space you want to allocate for a table if you’re not writing sequentially. This is ignored if sequential writing is enabled.

Check the .py source code for a more detailed explanation on what each code does.

A few other notes:

  • TableManager supports negative numbers!
  • TableManager also supports data sizes that are not 1 byte, 2 bytes, or 4 bytes. Simply put the size of your data as you like in the NMM field, and TableManager will handle it. Note that this data is still little-endianed!
  • If TableManager doesn’t think you’re trying to write data to some offset (say you never reference ItemTable+0x35 in your NMM. This is unknown data off the top of my head I think), 0 will be written. The previous feature was included in order for easier writing of unknown data of irregular length.
  • TableManager has no automatic repointing feature. I recommend using my Repointers helper file here.
  • A cell left blank is assumed to be 0. TableManager will attempt to not write data and allow FILL to 0 out data if it thinks that 0 will be written for an entire row if it exists. This is done for the item usability/effect/target/etc tables being weird and any other tables with an adding offset.
  • Any table with an adding offset has an innate ASSERT when writing each row to ensure that every index that’s being written to exists. For example, if you try to give an iron sword (item ID 0 or 1 or something?) an item usability pointer, EA will give you an error because this assertion will fail because that entry in that switch table doesn’t exist. You probably don’t need to worry about this, and it should never cause problems for you. It’s just a failsafe.
  • For each cell in the far left column, only the first “chunk” of data when separating by whitespace is read. This means if I have 0x0A Manakete in the left cell of my row, TableManager reads this as 0x0A. This can be used to have sorts of comments on what a row is if you’d like to use hex indices.
  • In the table options file, make comments with @.

Rather than have BORING examples here, I invite you to check out working examples of TableManager in my Avenir Github: https://github.com/Snakey11/Legends-of-Avenir/tree/master/CSV/Tables

I don’t pretend to be a good Python programmer, so I probably made plenty of mistakes. I thiiiink I handled most errors I would expect, but please please let me know if you encounter weird traceback errors, if you see unintended behavior, if you have suggestions, or if something was confusing!

Have a happy Halloween! :skull:

11 Likes

Made a quick QoL hack for dialogue for all you avatar hacks out there. :fist:

Gendered Text

This hack lets you add some text control codes (definable in textprocess definitions) that inject gendered pronouns into text (i.e. He, She, Him, Her, His, Hers, he, she, him, her, his, hers). Each control code is associated with a pronoun pair, and an event ID is used to determine which to inject. (I kinda hijacked how [Tact] works.)

This isn’t entirely necessary for doing this since you could just have separate text IDs for different cases or use TEXTSHOW2 shenanigans but ew. This should be cleaner and quicker.

This isn’t limited to gendered pronouns really. I intentionally made the system modular for more general use.

Download from the link in the OP!
Lemme know if you encounter any issues. I don’t think this should conflict with anything.

13 Likes

By request, I’ve updated TableManager to be able to handle specific vanilla tables being considered inline or fixed, overriding the pattern of the CSV declaration. For example, say you wanted your vanilla character tables to be written to their original offsets but your custom character-indexed tables to be written to free space. You could do the following:

CSV Characters/CharacterTable.csv @ Things indexed by character.
	TABLE CharacterTable Characters/CharacterTable.nmm
	TABLE MagCharTable Characters/CharacterMagicTable.nmm INLINE
	TABLE CharLevelUpSkillTable Characters/CharacterLevelUpTable.nmm INLINE
	TABLE PersonalSkillTable Characters/PersonalSkillTable.nmm INLINE
	TABLE EscapeQuoteTable Characters/EscapeQuoteTable.nmm INLINE
	INLINE False @ The default inlining is false here.
	WRITE_SEQUENTIALLY False
	MAX_ENTRIES 256

You can accomplish the exact same thing with:

CSV Characters/CharacterTable.csv @ Things indexed by character.
	TABLE CharacterTable Characters/CharacterTable.nmm FIXED
	TABLE MagCharTable Characters/CharacterMagicTable.nmm
	TABLE CharLevelUpSkillTable Characters/CharacterLevelUpTable.nmm
	TABLE PersonalSkillTable Characters/PersonalSkillTable.nmm
	TABLE EscapeQuoteTable Characters/EscapeQuoteTable.nmm
	INLINE True @ The default here is inline.
	WRITE_SEQUENTIALLY False
	MAX_ENTRIES 256

So to use this new functionality, just optionally append either INLINE or FIXED to make an exception to the CSV INLINE setting. I’m updating the original post’s documentation, and let me know if there are any issues!

4 Likes

I’ve been sitting on this for way too long, but I’m finally putting a little time to releasing it.

Support Rework Rework

That’s right. My own Support Rework from about 2 years ago is such a mess of me sneezing asm code around that I felt it necessary to rewrite it in C. While the older version was a little buggy, the new version has been behaving nicely in my own working project. Anyway, I’m proud to finally release it.

Features include all from the original version plus:

  • EIGHT unique support levels. That’s right. Eight. Should anyone use eight support levels? I don’t know I’m gonna wizard’s creed my way out of that one. If you don’t want that many you can have fewer. (I only use three lmao)
  • Enhanced stat screen drawing. I’ve gotten better at custom drawing routines, and I’ve made the stat screen look nicer. This also includes @HyperGammaSpaces’s chadly support R text system which looks GREAT. Thank you, Gamma, for developing that!
  • This is a C hack! Old support rework was all written in thumb, making it pretty error prone. This source should look much cleaner.
  • The hack is fairly separate from base conversations now. They work well together, and if you want base conversations, use the version that comes with Support Rework Rework. Otherwise, no sweat!
  • The utility macros (for modifying unit support data via events) should be easier to use now.
  • There is support for the Skill System talk bubble to appear if there is a viewable support convo in a chapter.
  • Probably more stuff? tbh I “finished” this a while ago and just now touched it up for release. Shoutouts to @Alaric for nudging me to release this!
I suppose that the instructions for using this hack will be similar to before, but I'll reiterate them

So you wanna use Support Rework Rework. Great! These instructions are going to be long not because the system should be difficult to use but moreso because I want to provide as much documentation on how to use it as I can.
You’re going to want to download the entire Support Rework Rework folder from my link in the OP and include SupportRework.event in your buildfile.
The first thing that this file does is include SupportReworkDefinitions.event, a file that defines various macros and such. Some of these macros are used in events to control support data. If necessary depending on the layout of your buildfile, you can include this file earlier in your buildfile.
This definitions file defines values for your various support levels. The example levels given are

#define CSupport 0
#define CPSupport 1
#define BMSupport 2
#define BSupport 3
#define BPSupport 4
#define AMSupport 5
#define ASupport 6
#define APSupport 7

representing C support, C+ support, B- support, etcetera. Change these as you see fit. These are just silly examples. Just make the IDs between 0 and MaxSupportLevelVal inclusive and unique. Speaking of MaxSupportLevelVal, define that to be your highest support level. I’ll get to the rest of the things in this file later. You don’t need to touch them.
Back in SupportRework.event, the SupportLevelNameTable is a table indexed by support level (remember the definitions we just discussed?) with each entry as a pointer to a string that represents that support level. You shouldn’t need to touch anything else in this file.

I’ll talk about externalish hacks next.
Firstly, Support Rework Rework supports easy integration with Base Convos. Refer to my post about that hack for instructions on how to use it. SupportReworkDefinitions.event defines a single additional base conversation macro, baseSupport(Character1,Character2,Level), where the first two parameters are the character IDs of the two supporters, and Level is the support level the conversation should try to raise to. If the current support level is not one less than the current level (or nonexistent if the level to raise to is 0), then the conversation will not be viewable. If you DON’T want to use base convos, that’s perfectly fine. Just comment out the #include "CBaseConvos/BaseConvos.event" line in SupportRework.event.
The next external hack that’s relevant is my prep screen hack which makes editing the prep screen main menu a lot less painful. I discuss what needs to be done there in the base conversation hack post. (It’s just incorporating a CSV and making an edit iirc). This is only relevant if you are using base conversations. Otherwise just ignore this.
Finally, a small hack to the CHARASM event handler is included that makes CharacterBasedEvents-based support conversations work. It just makes it such that a character event usability routine returning 2 makes the conversation usable without making any other checks.

Support Rework Rework supports support-by-support defining of stat bonuses just like the older version but hopefully in a cleaner way. You’ll define the values you want in SupportReworkBonusTable.event.
This is a (nonindexed) list of support entries. Start an entry with the entry(char1,char2) macro, then fill in your support level bonuses with the support(level,... stats) macro. There are a couple examples in the file to start you off.

Uh what else… all that’s left is controlling supports via events I think.
Okay there are three ways to control support data:

  • Adding base conversations to prep screens to allow players to increase supports there
  • Adding “talk conversation-like” support conversations to allow players to increase support levels mid-chapter
  • Manually changing support data via events

For base conversations, you can simply use the aforementioned baseSupport macro, and a default event will be used. This is the simplest way to do this. If you’d like, you can also use a custom event for extra modularity. Writing custom base conversation events is discussed in that hack’s post. To make it a “support” convo, you can just call one of the event macros that I will discuss shortly. For the usability of the conversation to match generic support convos, use usability(SupportBaseConvoUsability|1), characters(Character1,Character2), and supportLevel(Level). You’ll also likely want textGetter(SupportBaseConvoMenuTextGetter|1). If you know what you’re doing, feel free to make your own custom alternatives to these generic functions!
Next, talk conversations. I’ve designed the system to make support conversations function just like mid-chapter talk conversations. Whenever you want the player to be able to increase a support, use one of the SupportConvo macros defined in SupportReworkDefinitions.event in CharacterBasedEvents. If you provide just a text ID for the last parameter, a generic event will be used to play the text then increase the support level. If you choose to pass in an event, it will play that event instead. This should be pretty straightforward.
Finally, you can pretty easily change support data. Macros to do so are also in SupportReworkDefinitions.event for use in event scripts with descriptions. I think these are pretty straightforward as well. I think these should work pretty well, but let me know if you hit unexpected behavior with these. IncreaseSupport and SetSupport will make a new support if one doesn’t already exist. If you try to add a support with max supports or if you try to increase a max level support, nothing should happen.

Small note: Any character ID of 0xFF is interpreted by the system as representing whoever is in the first character struct. This was useful to me, and I left it in because why not.

Oh. Last thing is stat screen stuff. I’ve hooked into the vanilla function that draws supports to… well draw the new supports. In your modular stat screen, you should just need to call that vanilla function (it should be in MSS defs) to draw supports. What I use for page 4 RText is included. (Thanks again to gamma for the support RText system!)

That should be about it I think. Let me know if anything weird happens, and have a nice day!

18 Likes