Snake's Pit of ASM (and Other Stuff)


#1

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://www.dropbox.com/sh/8zsppvxz34nrkuu/AACRsWnIErTWmsDhw8-s2Rsla?dl=0


Anima Magic Triangle

This works much like the the Tellius anima triangle.

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

#inctext lyn "AnimaTriangle/AnimaTriangle.elf" "AnimaTriangle/Definitions.elf"
// Example lists:
FireList:
BYTE Fire Elfire Arcfire Bolganone Meteor 0x00

ThunderList:
BYTE Thunder Elthunder Arcthunder Thoron 0x00

WindList:
BYTE Wind Elwind Arcwind Tornado Aircalibur WindSword 0x00

Pretty straightforward. This goes in your .event file.
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.

Just fill out those lists and stick the AnimaTriangle folder in the folder containing the .event file, and you’re good to go!

Level Up ASM

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.

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].

Raid
FE7 Stairs
FE8 Stairs
Conditionally Loading Portraits
Modular EXP
Poison Rework

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

Also, I almost forgot: Shoutouts to the helpful wizards who helped me along!


#2

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…
Download and #include normally, but delete everything in Raid.event except the lyn installer.
Then in the skill system, go to Engine Hacks/_MasterHackInstaller.event.
At the bottom, you will see stuff like UM_Exit and UM_Pick. Weird? Nah. This is the action menu table. We’re going to add raid to this list. Just put UM_Raid right below UM_Visit.
Then, in _UnitMenuDefs.txt, add the following (It doesn’t really matter where):

#define UM_Raid       "BYTE $28 $7E $0D $08 ; SHORT RaidNameText RaidDescText ; BYTE $00 $5C $00 $00 ; POIN RaidUsability|1 ; BYTE $00 $00 $00 $00 ; POIN RaidEffect|1 ; BYTE $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00"

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:

#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!


#3

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 have the skill system installed or some other patch that repoints the action menu…

Add “MenuCommand(StairsNameText,StairsDescText,GreenText,StairsUsability,StairsEffect)” to wherever you’re installing the action menu like how it is in “Stairs.event” (The skill system’s is at the bottom of “Engine Hacks/_MasterHackInstaller.event”.) Then, delete everything under “//Repoint Unit Menu” in “Stairs.event”

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.
Part of this installer gets put into bl range.


#4

Great job Snake! Doing cool asm as always


#5

Nice stuff!


#6

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


#7

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


#8

@Snakey1 pretty please with sugar on top?


#9

: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.


#10

Holy fuck so awesome


#11

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: ).


#12

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!


#13

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.


#14

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.


#15

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


#16

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.

(Another) wizard's warning

Switches are mean, and the one that sets a unit’s status bit after they end their turn forced me to use a bl call, just like in the FE8 version. FE7’s free bl range is very small, and FEDitor rudely takes most of it.

ORG $2F320 // GOOD FOR FE7
BL($CB660) // REEEE NO OTHER JUMPS WILL WORK HERE REEEE
ORG $CB660
jumpToHack(UnsetMoveDebuff) // Trampoline oof

This bls to a trampoline that goes to normal free space, so if you’re using the little bit of bl range immediately after the FEDitor autopatches at $CB660, you’ll need to find somewhere else to put the trampoline. :frowning_face:

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


#17

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.

Wow the spoiler also actually worked in the OP. Weird.
: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.

No .event installer is necessary for this one, so paste this into your buildfile.

#define PortraitSelectionEntry(TruePortraitID,FalsePortraitID,EventIDPointerList,ControlCode) "POIN EventIDPointerList ; SHORT ControlCode TruePortraitID FalsePortraitID 0"
#inctext lyn "PortraitSelectASM/SelectPortrait.elf" "PortraitSelectASM/Definitions.elf"
PortraitSelectionTable:
SHORT 0x0 0x0 0x0 0x0 0x0 0x0

Great, 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!


#18

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.


#19

This has some pretty great stuff.

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


#20

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