Snake's Pit of ASM (and Other Stuff)

Free to use, modify, redistribute, etc, but give credit as you always should.
Please let me know of any glitches you find, and I will fix them ASAP.

I use lyn for my hooks. Learn more here. Just make sure you have lyn.exe in your “Tools” folder of EA, place the folder of the ASM you want in the folder of the .event file, and use the installers I provide. :slightly_smiling_face:

Download here. :arrow_down: Keep reading for detailed descriptions.
https://github.com/Snakey11/SnekASM

After very brief consideration, I’ve decided to finally start organizing these wow!

Buildfile tools

TableManager.exe - My take on a CSV assembler
Enumerate.exe - Helping with EA defs
tmx2tsa.exe - Using Tiled to make custom TSA
Predictor.exe - Buildfile-friendly average statter taking stats from CSVs

New mechanics

Anima Magic Triangle (FE7 & FE8)

This works much like the the Tellius anima triangle.

Fire beats wind.
Wind beats thunder.
Thunder beats fire.

To install, include “AnimaTriangle.event”. Inside that file, you’ll find the following:

       ALIGN 4 // Be sure to terminate each list with an 0x00!
	FireList:
	BYTE Fire Elfire /* Other tomes to be considered fire */ 0x00

	ALIGN 4
	ThunderList:
	BYTE Thunder Bolting /* Other tomes to be considered thunder */ 0x00

	ALIGN 4
	WindList:
	BYTE Fimbulvetr WindSword /* Other tomes to be considered wind */ 0x00

Pretty straightforward. These are lists of item IDs that you want to be affiliated with each magic type.
Under FireList, make a list of all items you want to be included in the triangle as fire. Complete ThunderList and WindList except with thunder and wind items. Terminate each list with an 0x00.

For FEB users: There is a patch for this in FEB. Just install the patch and fill out the fire, wind, and thunder lists to your liking.

If you are using the Skill System, simply uncomment the installer in _MasterHackInstaller.event and fill out your tome lists in the AnimaTriangle folder.

Level Up ASM - pretty old

Does anyone like empty level ups? No one? Okay good. This ASM prevents those!

Including this will ensure at least one stat growth in a randomly selected stat if no level up stat growths are detected.
If a stat is maxed, it will not choose that one. If all stats are maxed, no growth will occur, so, I guess empty level ups are still possible… :man_shrugging:

#inctext lyn "LevelUP/LevelUP.elf" "LevelUp/Definitions.elf"

This one could use a little more testing, but it would be very tedious to test it as extensively as I would like. If anything happens that’s weird with this included, please let me know. I think it should work without a hitch.

Raid - New unit menu command to be mean to villages
Fates-style stairs FE7 and FE8!
Poison Rework - It’s Slay the Spire poison if you’re familiar with it
Summon EXP - Summoners gain EXP from their phantoms’ battles
Support Rework is OLD use Support Rework Rework instead - Completely overhauls the vanilla support system
Generic Base Conversations - Tellius-style base conversations in prep screens
HP Bar Palettes - Custom palettes by allegiance for HP bars

Development-side hacks

REDA Helpers

Hopefully, this should make unit placement easier in buildfiles. It certainly does for me. Just #include it somewhere.
What this does is it writes all basic REDA data for moving to coordinates between 0-30 for X and Y.

For example…

UNIT Haedrican Fighter Leon Level(7,Enemy,True) [0,11] 0x00 0x00 0x01 REDA8R15 [HandAxe] NoAI

This unit will spawn at [0,11], then will move to [8,15].
In each UNIT code you need a REDA in, put 0x01 REDA(X)R(Y). For (# of REDA's to read) and (Pointer to REDA data).

REDA8R15 is included in my file with REDA data to move the unit to [8,15].

Conditionally Loading Portraits - Load different portraits in cutscenes by event ID
Modular EXP - Apply EXP multipliers and divisors by class, character, etc
Prep Screen Menu Editor - Edit the menu options of the prep screen main menu
Repointers - List of ORG/POIN edits to make to repoint common tables
Modular Supply - Change supply usability by chapter
Scripted Battle Numbers - For scripted battles, set the numbers independent from combatant stats
Modular Event Parameters - Make changes to the special event parameter codes (0xFFFF as active unit, etc)
Modular Door and Chest Openers - Helps in defining custom items that can open doors and chests
New Anti-huffman Patch - Less hacky antihuffman hack
Debug Character/Class Viewer - View animations with palettes for all your characters from the unit menu
Gendered Pronouns - Makes displaying gendered pronouns in conversations conditionally much easier

I hope to have some new projects coming out :soon:. Find me on Discord if you have any questions or suggestions!

Shoutouts to the helpful wizards who helped me along!

26 Likes

Raid

This is a custom location event that will allow you to do basically the same thing as visit, but it will show the custom name and description in the action menu, separate from the visit command.

How to: Be the bandit within you that you've always wanted to be.

Find it in the dropbox. :arrow_up:

You will need RaidNameText and RaidDescText defined as text IDs containing " Raid[X]" and whatever you want to be in the text bubble that shows up when you hit info on “Raid” respectively.

Download the folder, Raid, and just #include Raid/Raid.event.
If you DO NOT have the skills system installed…
That’s all you have to do. :thumbsup:

If you DO have the skills system installed…
Go to _MasterHackInstaller.event and uncomment Raid. That’s it.

With that, you should be set!

Now to actually use it, here’s the macro (Goes under LocationBasedEvents like any other), and I think you’ll find this tile change macro useful too for tile changing to destroyed houses/villages: :wink: (These should already be defined for you).

#define Raid(EventID,Pointer,X,Y) "LOCA EventID Pointer [X,Y] 0x21"
#define TileChange(X,Y) "SETVAL 0xB Coords(X,Y) ; TILECHANGE 0xFFFF"
#define Coords(xcoord,ycoord) "(ycoord<<16)|xcoord"

You will need to manually do the tile changes, but it’s easy with the macro. You will not have to set the event ID manually.

Now have at it: Strike fear in the hearts of our favorite FE8 villagers.

Except actually write raid convos… I’m too lazy

As always, please let me know if you find any bugs!

8 Likes

Stairs
This is another custom location event that allows you to take a staircase to a connecting end.
I suppose you could change the text and make it something like “Teleport” but sshhhhh.

Features:

After taking the stairs, units may finish their turn.
Units have as much movement after taking the stairs as they would to finish their turn
This is reset with any action taken to end the turn or when using the "End" turn button.
Units may not use this command twice in one turn.
A unit may not use the staircase if a unit is on the connecting end.
Staircase ends are definded in location events.

How to: Teach units how to not be befuddled by staircases.

Firstly, add the “Stairs” folder to your project and #include "Stairs/Stairs.event".
Find it all in my master dropbox folder at the top of the thread.
If you are using the Skill System, just uncomment the installer in _MasterHackInstaller.event, and the addition to the unit menu will be handled automatically.

Great. Also, be sure in your text assembler that you have this somewhere:

## StairsNameText
Stairs[X]

## StairsDescText
Take this staircase to[NL]
the connecting end.[X]

## StairsBlockedText
The staircase is blocked[NL]
from the other side.[X]

(Feel free to change these as you wish.)

Lastly, you need to know how to use them in events. They’re not linked to the stair tiles, they’re location events.

#define Stairs(StairID,X1,Y1,X2,Y2) "LOCA StairID [X1,Y1] 0x22 ; LOCA StairID [X2,Y2] 0x22"

Just use the Stairs macro under LocationBasedEvents where (X1,Y1) are the coordinates of one end of the staircase and where (X2,Y2) are the coordinates of the other end. StairID is the ID of this staircase. Never reuse IDs between multiple staircases!

That’s it!

Have a nice day, and please report any bugs you find!

Wizard's Warning

This uses byte 0x3A of the character struct to hold the temporary movement debuff after the stairs are used. This will interfere with other patches that use byte.
EDIT: This can now be changed in the Stairs.event installer. Feel free to change that byte to any other free byte of the character struct.

11 Likes

Great job Snake! Doing cool asm as always

1 Like

Nice stuff!

1 Like

That… is Amazing!!!
Such feature could create interesting and unique level design.

2 Likes

This is neat!

Maybe @Arch can get this adapted for FE7 so he can finally get Stair traversal in Eliwood’s Tale (if it’s still even there) to not be delayed

3 Likes

@Snakey1 pretty please with sugar on top?

2 Likes

:thinking: It probably wouldn’t be too hard to port to FE7. It would probably just be a matter of changing a few offsets of some hooks and other things’ offsets. I could do it if there’s enough demand.

3 Likes

Holy fuck so awesome

1 Like

Fixed a bug in Anima Triangle where affected magic would have advantage or disadvantage with some physical weapons if the physical weapon cannot retaliate. Funnily enough, we found this bug in our FEE3 recording…

Also regarding StairASM, if anyone really wants to port it to FE7, I have no objections. Does anyone want me to do it? It would have to be after the Legends of Avenir demo is out (which is :soon: :tm: ).

3 Likes

I like how I’m just now seeing this awesome post.

But hey this whole fun idea of actually using the stairs and anima having triangle advantage just goes to show that the GBA has some really fun advantages of just making it even better than before.

I be all for it to see it being ported to FE7, wouldn’t matter how long it takes. If its possible than woohoo!

2 Likes

Please please please please please?

I made something similar to this by using events years ago in Eliwood’s Tale, but having the real deal would be amazing.

5 Likes

Adds to list of ASM things to do.
It shouldn’t be too difficult to pull off. I can have the FE7 version done fairly soon.

1 Like

So, considering that StairASM is not FE7, does that mean none of the others are FE7 either?

Well this is a coincidence, because I come bearing FE7 stairs.

Assume everything is for FE8 (though if you need something for FE7, I’d probably be happy to adapt it. :slightly_smiling_face:)

Anyway, FE7 stairs work very similarly to FE8 stairs...

I suppose I can safely assume we won’t need to worry about interference with any skill system.
Firstly, this assumes that you have the following defined.

## StairNameText
Stairs[X]
## StairDescText
Take the stairs[NL]
to the other side.[X]
## StairsBlockedText
The stairs are blocked[NL]
from the other side.[X]

Next, the action menu. Assuming you haven’t already screwed with it, this is handled with “FE7 Unit Menu.csv”. If PFinder doesn’t work (which it never does for me), here’s where you need to repoint.

//Repoint Unit Menu
PUSH
ORG $B95Ab4
POIN UnitMenuTable
POP

Then, just #include “Stairs.event”.

Using the stairs is exactly the same in FE8.

#define Stairs(StairID,X1,Y1,X2,Y2) "LOCA StairID [X1,Y1] 0x22 ; LOCA StairID [X2,Y2] 0x22"

Don’t reuse StairIDs. X1 and Y1 are the coordinates of one end of the stairs. X2 and Y2 are, big surprise, the coordinates of the stairs on the other end. This macro command goes under location events.

Let me know if you encounter any problems, something needs clarification, or if I forgot something.

1 Like

Portrait Selection

Remember when I had this in the OP?

Conditionally Loading Portraits

As in, load this portrait if event ID X is triggered. Load this one if not.

Okay. I can’t provide a download for this one. I wrote this for Legends of Avenir (shameless self-promotion lol), but the ASM would be so dependent on your needs (event IDs to check, number of event IDs to check, text control code, etc. ) that any source I post would be useless except as documentation. If you’re interested, find me on Discord and I’ll help you out.


:disappointed: That’s pretty dumb, so I made a version that is not hardcoded and is hopefully easy to use.

How to: Teach your characters to consider event IDs before showing their ugly faces.

Simply include “PortraitSelectionASM.event” found in the Dropbox folder.
If you’re using the Skill System, uncomment then installer in _MasterHackInstaller.event.
You’ll see the following when you enter the installer file in the container ASM folder:

PortraitSelectionTable:
SHORT 0x0 0x0 0x0 0x0 0x0 0x0

Now you need to fill out the Portrait Selection Table. All this does is it relates a control code, mugs to potentially show, and a list of event IDs to check. Use the macro, PortraitSelectionEntry, to fill this out. For example…

PortraitSelectionTable:
PortraitSelectionEntry(GoodFaceID,BadFaceID,Face1List,0xE0E0)
SHORT 0x0 0x0 0x0 0x0 0x0 0x0
Face1List:
BYTE 0x6E True  0x11 True  0x00 0x00

How will this be interpreted by my function? Any time that 0xE0E0 as the control code is detected, it will load GoodFaceID if both event IDs 0x6E and 0x11 return true. Otherwise, BadFaceID will be loaded.
Each unique event ID list that you make can be as long as you like. Each one to check should have the event ID followed by whether you want it to be true or false. This list must also terminate with 0x00 0x00.

PortraitSelectionTable:
PortraitSelectionEntry(GoodFaceID,0x00,Face1List,0xE0E0)
PortraitSelectionEntry(NeutralFaceID,BadFaceID,Face2List,0xE0E0)
PortraitSelectionEntry(SomeOtherPortrait,SomeOtherOtherPortrait,Face3List,0xF0F0)
... // Other control codes and stuff idk
SHORT 0x0 0x0 0x0 0x0 0x0 0x0
Face1List:
BYTE 0x6E True  0x11 True  0x00 0x00
Face2List:
BYTE 0x6E False 0x11 True  0x00 0x00
Face3List:
BYTE 0x72 True  0x21 True  0x14 False 0x00 0x00

You can have as many entries and different control codes in the Portrait Selection Table as you like, and control codes CAN repeat. If you put 0x00 in the FalsePortraitID slot, then upon returning false, my function will continue checking the list for valid portraits to load instead of trying to load a false one.
This previous example will check Face1List upon hitting 0xE0E0. If Both 0x6E and 0x11 are true, then it will load GoodFaceID. Otherwise, it will proceed down the list because the false (or else, if you prefer) entry was 0x00. It tries the next entry, and if it finds 0x6E to be false and 0x11 to be true, then it loads NeutralFaceID. Otherwise, it loads BadFaceID.

It may be more intuitive to think of this as…

PortraitSelectionEntry(IfTruePortrait,ElsePortrait...)

In case you’re wondering about the control codes themselves, they’re arbitrary shorts. You don’t need to do anything extra to use them except use them in the Portrait Selection Table. To my knowledge, you should not use 0xFFFF (since that’s for loading the current character’s), and you should not use 0x01XX or 0x02XX (since that’s used to normally loading portraits). Just go ahead and [LoadFace][0xE0][0xE0] (in my case, at least) away.

As always, I’d be happy to clarify something, and let me know if you encounter any issues!

4 Likes

Okay then. Would you be able to convert the Anima Magic Triangle to FE7? I want to use it in a mod I’m doing.

This has some pretty great stuff.

I ought to learn how to ASM as well one of these days

1 Like

Sure. I’m not sure when I may get around to it, but I’ll definitely add it to my to-do list.

1 Like