[FE8U] Stan's ASM Stuff

All of my stuff here is for some variant of EA buildfiles, unless specified otherwise.

Important Links


Modular (Stat) Getters

NOTE: MG2 is also included with the latest version of circles’ Skill System. You do not have any installation to do if you are using it.

The doc is outdated (will updated :soon:)! ask me about MSG here or on the discord if you want to know more about what you can do.

Modular Stat Getters allows you to easily edit the stat getter “routines” so that you do not have to manually rewrite them each time you want to add some mechanic that modifies a stat (such as a skill).

This hack supports (in fact, includes) @Tequila’s Con & Mov Getters, along with the vanilla Current HP, Max HP, Power, Speed, Skill, Luck, Defense, Resistance & Aid getters. The StatGetters folder contains definitions for Stat Getters that intend to replicate vanilla behavior (If there’s any error, feel free to ping me here on the Discord).

As of Version 2, this hack also support hooking into a BattleCalcLoop and modify battle stats (Hit, Crit, Avoid, AS etc) the same way as standard stats. Feel free to ask for details.

Credits: @Tequila for the con & mov getters, @circleseverywhere for the skill system that inspired this.


Class & Range-based Alternative Spell Animations

This is a simple hack that allows you to specify substitutions to spell animations depending on class. This is essentially an extension to the vanilla hard-coded check for javelin animations (some classes have different animations to fit their battle sprite). For example, you could have Fire animate as Elfire for Promoted classes like Sage.

Now you can also add animation substitutes for close-ranged spells (At range, the standard animation will play). The check for range happens before the check for class, so if you want a class to have different close-ranged spell animation for one animation, you’ll have to substitute the global close-ranged one first.

To Install, simply assemble the event file having added the substitutes you want in it (hopefully the way to do it is obvious enough because I am bad at explaining things). Remember to specify an offset if you are not assembling with the buildfile method.


“Evil RN”


SHOVE


Range Display Fix, Heroes Movement & “LolStats”


Dance AI


Lazberian Turn Flow


Custom Game Speed & Per Chapter Battle/Death Quotes & Modular and Expanded Save


Lazberian Mercenaries


For more information on how to use the buildfile method to build a GBAFE hack, check this guide.
Feel free to ping me here or on the Discord if you have any questions/found any bug.

10 Likes

This is pretty awesome.
Is it possible however to assign a different animation to a critical hit? That’s something that always kinda bugged me in FE.

That would be kinda more difficult to do, because the animations seem to be determined on a per-round basis (as opposed to a per-hit, which would allow to check for a crit to change it).

Or the other hand, I updated this by adding a way to change animation for close ranged combat (because apparently animating spells for both is hard because battle tile alignment or something).

Added Modular Stat Getters. Mainly intended to be used by advanced users & wizards that want to patch various asm hacks together/make their hack more compatible with others.

3 Likes

Will definitely be using this in the big assembly conglomerate I’m building. Cheers!

3 Likes

Small bugfix update to Modular Stat Getters (there was an error in the hp cap check, thanks to @circleseverywhere for the report :slight_smile: ).

Edit: another bugfix update :sweat_smile:, this time fixing adjusting aid for mounted units (female units weren’t recognized properly gdi y I no hex)

Big update to MSG, now it includes a bunch of macros & definitions that allows you to create simple modifiers using only EA.

Examples:

prCelerityModifier: // skill checker helper for circles skill system is included
    rIfHasSkill(CelerityID); rAdd; rConst(2)

// ...

pMovGetterModifiers:
    POIN [...] prCelerityModifer 0
// this one is included, but I'm putting it here for the sake of demonstration
prNullifyIfGuardAI:
	rIfHasGuardAI; rNullify
prHalveIfPoisoned: // 0x1 is poison status id
    rIfHasStatus(0x01); rHalveStat

// ...

pPowGetterModifiers:
	POIN [...] prHalveIfPoisoned 0

pDefGetterModifiers:
	POIN [...] prHalveIfPoisoned 0

I’m planning on writing a proper doc for those in the following hours. I will probably be adding new macros in the next releases, along maybe with support for other “stats”.

Here, have a big good old doc. It covers pretty much everything you can do with MSG as of now.

Updated ModularStatGetters again: fixed con bug, renamed stuff (I made sure to list the changes this time), and added quite a few new routine macros.

The doc is not up to date yet but I’m working on it. Updated.

CHANGELOG
Modular Stat Getters, Version 1.1:
	CHANGED:
		- rAddFull[stat] renamed to rAddFinal[stat]
		- rNullify renamed to rNullified
		- rHalveStat renamed to rHalved
		- rShift[Left/Right] renamed to rShiftedRight[Left/Right]
		- rGetCharByte and rAddCharByte renamed to rGetCharUByte and rAddCharUByte
	
	FIXED:
		- Potential negative char con bonus not taken into account

	IMPROVED:
		- rIf is now more space efficient
		- rIf with no arguments calls condition without modifying r2, allowing for one extra passed argument
		- prAddUnitBaseCon, prAddUnitBaseMov, prAddUnitBarrierModifier and prAdjustAidIfMounted make use of macro routines instead of external asm bin
	
	ADDED:
		MSGDefinitions.event:
		- rCallSequence(seq): calls a list of routines in order (arg: list of pointers to routines, SPACE-SEPARATED)
		- rCall(rptr, arg): new variant to rCall, calls routine with r2 = arg
		- rNegated: returns (-stat)
		- rSwitchConst(trueConst, falseConst): calls following routine, then returns a constant based on that routines result
		- rGetCharSByte(offset): returns signed byte at [offset] in char struct (char struct passed through r1)
		- rGetCharWord(offset): returns word at [offset] in char struct (must be 4-aligned, useful for getting pointers)
		- rGetCharLowerHalfByte(offset): returns ((byte) [char, offset]) & 0xF
		- rGetCharUpperHalfByte(offset): returns (((byte) [char, offset])>>4) & 0xF
		- rGetSByteFrom, rGetUByteFrom, rGetWordFrom, rGetLowerHalfByteFrom, rGetUpperHalfByteFrom: same as their Char couterparts, but takes the result of following routine as struct pointer (useful for getting data from ROM Char & Class structs)
		- rGetROMChar[U/S]Byte(offset): rGet[U/S]ByteFrom(offset); rGetCharWord(0x00)
		- rGetROMClass[U/S]Byte(offset): rGet[U/S]ByteFrom(offset); rGetCharWord(0x04)
		- rAddCharSByte(offset): rAdd; rGetCharSByte(offset)
		- rNOP: Returns with doing anything (bx lr; nop)
		
		MSGConditionsRoutines.event:
		- prNot[Cond]: returns not([Cond])
		
		MSGModifierRoutines.event:
		- prAddFinal[Stat]: (used to be only for mov & con) calls the corresponding getter and adds it to the stat
	
	REMOVED:
		- prAdjustMountedAid: Obsoleted, the modification now occurs within prAdjustAidIfMounted
	
	TODO:
		- prHasGuardAI and prCheckForHPCap still use external asm bin, so there is still some stuff to be made to allow them to be macro-ified.
		- modular getters for even more stuff

@SEVA came up with this "Evil RN" system yesterday on the discord, and I felt like implementing it into FE8. So here it is.

Description

You may know that the “True Hit” system makes higher hitrates more likely to hit, and lower hitrates more likely to miss. This system does essentially the opposite: Higher hitrates (>50) are actually lower that displayed, while lower hitrates (<50) are actually higher. 0 is still 0, 100 is still 100, and 50 is still 50.

View Graphic (credit to SEVA again) (gdi details tag not working)

Graphic

Formulas

FE1-5 Hit: TrueRN = A
FE6-13 TrueHit: TrueRN = (A+B)/2
EvilRN: TrueRN*100 = (3*(A^2)) - ((2*(A^3))/100))
with A (and B) being 0-99 ranged random integers.

Download (with nice EA Installer and all)

Source is included (so this also works as template for anyone interested in messing with the “True Hit” system).

Bonus: apply this (or any custom RN modification system) to any chance-based event

This would include crit rates, staff hit rates, growth rates, Arena opponents, some AI related shenanigans, and probably more.

Currently, this system is only applied to hitrates. This was done by replacing the routine located at 0x00CB8 (This is the routine that rolls 2RN chances).

The routine that rolls 1RN chances is located at 0x00CA0, so in the EA installer you’d simply add in this:

PUSH; ORG 0x00CA0
    // substitute _prEvilRN with a label pointing to wherever your RN roll routine is located
    replaceWithHack(_prEvilRN)
POP
3 Likes

You sure you got the formula right? Admittedly, I probably explained it in a confusing way.

Essentially, the reason I started saying other things after the formula is that, generally, calculations on probabilities are done with all probabilities in the range 0-1, and this is the case here too, but of course at the end you’ll want to multiply whatever you get by 100 to compare it against the hitrate. As it happens, for 2RN it doesn’t make a difference, but I think it does for this.

The formula is simply this:

But the input RN ‘a’ and the output RN ‘b’ are in the range 0-1. So if your input RNs are actually 0-100 (I don’t actually know how it works in the game, but I assume they are) you’ll want to divide them by 100 before plugging them into the formula as ‘a’, and multiply the resulting ‘b’ by 100.

1 Like

Ye don’t worry, I accounted for that.
Here is how I got from b = -2*(a^3) + 3*(a^2) to TrueRN*100 = (3*(A^2)) - ((2*(A^3))/100))

C = f(A) = (3*(A^2)) - (2*(A^3))

let B = A*100; A = B/100
let Perc = C*100; C = Perc/100

We want Perc = g(B)

Perc/100 = (3*((B/100)^2)) - (2*((B/100)^3))
Perc     = 100*((3*((B/100)^2)) - (2*((B/100)^3)))
Perc     = 100*(3 * (B^2) / (100^2)) - 100*(2 * (B^3) / (100^3))
Perc     = 3 * (B^2) / 100 - 2 * (B^3) / (100^2)
Perc*100 = 3 * (B^2) - 2 * (B^3) / 100
1 Like

Still no fancy things yet (I will get there, e v e n t u a l l y). But here’s some obscure wizardy for the initiated:

  • Re:BattleCalcLoop: Rewritten version of @circleseverywhere’s BattleCalcLoop. The main change is that instead of forcing a thumb call it defaults to a thumb call (I don’t know why you’d want to call arm with that but now you can). Also optimizations and it’s more clean overall (imo).
  • Unit Action Rework: Rewritten version of the vanilla routine that manages execution of an action from the Action Struct. Now it loads a routine from an actual routine table instead of being a semi-hardcoded/switch table mess. It therefore makes it easier to add new unit actions by Id.

MSG (Modular Stat Getters) will also get an official update :soon:, but for now I still have to figure out how it managed to break the Skill System’s MSS (Modular Stat Screen)… but stay tuned!

Also my stuff is now on the Unified FE Hacking Dropbox.

If you followed a bit what I was doing on the Discord, you may know that I have put quite a bit of work into researching the infamous 6C Struct among other things: My notes about those and other related stuff are on the dropbox too, if you care.

2 Likes

Hay! Look! Actual fancy stuff! Shove

Include Shove/Shove.event somewhere in free space in your buildfile (if you are not using buildfiles, then please do).

You will need all the other files and folder too, so be careful.

This version is simple as it allows every non-mounted units to shove any other non-mounted units.

Also, the Shove command is yellow and has priority over any other command. But you can simply change that by changing the command order (and color parameter) in the Shove/Shove.event file.

Skill System version :soon: Now also included in circles’ Skill System.

4 Likes

Modular (Stat) Getters got an update!

A pretty big update in fact. TL;DR Everything changed.

“What’s new” do you ask?

  • Fancy stuff: A bunch of new helpers that allow you to do pretty crazy stuff, like checking for units in some wierdly shaped range (see my example request thread for examples, feel free to also ask for more!)

  • Convenient stuff: No need for installing anything in bl-range anymore, the few routines that needed that (Namely, the mov & con getter trampolines) have been moved in fixed leftover space from the vanilla getters (thank @circleseverywhere because he did that first)

  • Also convenient: The MSG core and the Stat Getter have been essentially separated: that means that you should be able to update MSG in the future without having to carefully extract whatever modifiers you wrote beforehand.

  • Also fancy: You can now hook into a BattleCalcLoop and edit Battle Stats (Hit, Crit, AS and the like) the same way you’d edit “regular” stats. Along with the new range-based helpers that were added, it allows pretty easy making of “aura skills”.

  • Wizard stuff: helper asm routines follow stricter conventions: for example, the meaning of passed and returned registers should now always be the same. Any routine that do not should be wrapped by another.

  • And probably more because holy hell that was a lot of stuff to update.

MSG2 is now also included into the latest version of circles’ Skill System.

3 Likes

Ok new-ish stuff

DISCLAIMER: YOU NEED ALL THE FILES PROVIDED AND THE EXACT SAME FOLDER STRUCTURE TOO (you can delete the .s (asm sources) if you really want to but still)

Range Display Fix

I know Icecube already made one but there’s no source available as far as I can tell so to me it might as well not exist =p

Doesn’t need any setup or anything, either include the file in your buildfile project or assemble it directly with EA (you may want to change the offset of FreeSpace in the file if you do that tho)


Also since I did some stuff that I never properly released here it is I guess

Heroes Movement Skills

Shove, Smite, Pivot, Reposition & Swap all-in-one package. You may want to tinker with the HeroesMovement/HeroesMovement.event (which is, btw, the only file you should #include) file to make it install the way you want, but am too lazy to do any in depth explanation rn so if you have questions just ask me on the the Discord.

Also those have been included in the Skill System for a while now (read: a few weeks).

“LOL Stats”

Really quick modification (took ~20min iirc), it makes level ups even more random, as you can now get +2, +3 or even +12 stat levels if you’re really lucky without needing any 100+ growth (+2 stats will become common for higher growths like hp).

How it works? The base game does stat ups like this: rolls one RN, compares it to growth, if the RN is lower, then +1, else +0. Here we actually will continue checking after the initial “RN is below growth” thing, like so (C pseudocode):

int getStatIncrease(int growth) {
	int stat = 0;
	
	while ((growth -= nextRN100()) >= 0)
		stat++;
	
	return stat;
}

TL;DR: you can get +3 stats with a 40% growth if you’re lucky.

2019-09-18 update: this now actually written in C and also this doesn’t cause autolevelled stat variance to be turbo wack anymore (hopefully).


That’s it for now. You can find me on the FEU discord if you have any questions.

4 Likes

:wave:

Hey, it’s been a while I made a thing!

Dance AI

“Restores” the ability for the AI to dance while escaping (vanilla can actually already do the decision making, but not the actual dancing).

Also adds the ability for the AI to decide to dance without the need to be in “escape mode” (more specifically, it will try to dance after trying to use staves). The AI will choose which unit to dance for based on base stat total (pow + skl + spd + def + res + lck + curHP; Without taking any modifiers into account) (this is just to make the potential dance target reasonably predictable).

For example, if an AI-controlled dancer has AI1 0 (AttackInRange, or ActionInRange would maybe be a better alias), It will dance for units it can reach. If it also can use staves, staves will have priority. If it also can initiate combat, dance will have priority.

Other misc info: Dancers won’t dance for other dancers. Dancers have a significant priority penalty (so they will most likely move after all the other units) (this is vanilla behaviour). Danced units move last, and in the order they were danced for.

The hack is for FE8U, install using Event Assembler 10+ while in free space.


If you have found any bug or have any questions, feel free to ask me on Discord.

Have fun being evil! -Stan

14 Likes

I mean, it sounds perhaps weird, having dancers as enemies, but incredible at the same time. Well whatever, that isn’t the point, the point is how amazing that is, praise StanH!!

:wave:

Lazberian Turn Flow (LTF)

Do any of you guys know about Berwick Saga? If you don’t, you should check it out! It’s a very interesting game. But if you do know about it, you probably know that in the land of Lazberia; turns flow fairly differently there than in your average Fire Emblem setting. This hack tries to implement the Berwick Saga “dynamic” turn system in FE8(U).

(Source included, but can also be found in the CHAX GitHub Repository. Note that you won’t be able to build the source without the CHAX setup or something like it).

#include "LazberianTurnFlow/LazberianTurnFlow.event" in your buildfile and you should be good to go.

2019-09-22 Update: LTF is now toggleable! By default, it is done on a per-chapter basis (the hack maker would define a list of chapter ids LTF is enabled in), but if you don’t mind for a bit of asm you could change the check for which LTF would be enabled. This is notable as previous versions would just force LTF globally. See installer for details.

This version may still have some issues, In terms of features this is basically done, but due to the scale of the changes this hack introduces it would require a lot of testing (both with LTF enabled and disabled) to be 100% sure there isn’t any bugs with it.

Detailed Feature List

  • Lazberian Turn Flow
    • Each time a move is made, a phase switch occurs.
      • “End Turn” will gray out all your units, preventing you from getting a move before every other (AI) unit has moved.
    • When every unit has moved, a turn switch occurs.
      • This is where stuff that normally occur for vanilla phase switches will execute (status depletion, trap checks, terrain healing, etc…)
      • Most notably, TURN events are executed at turn switch, and now ignore the phase part of the code/definition.
    • Berserk phase has been accounted for
      • all berserked units are pooled into the same “faction”, and have a dedicated phase
    • Some factions are biased towards having their (first) move before others
      • Blue > Red > Green > Berserked
  • Phase Prediction Display (up to 5 moves ahead; configurable if building from source)
    • Can be toggled with the “Display Help Subtitles” option; which, if you use HP Bars, will probably be replaced by the “HP Bars” option. (This may change in the future).
  • Reworked AI to fit the flow better
    • It’s a bit complicated. See AiThePlan.txt and src/LTFAi.c for notes and details I guess
  • Hold R at any point (when not hovering a unit, because that will open the stat screen) to disable map sprites being “grayed out” (since now units of all factions can be grayed out simultaneously, I wanted to give quick access to a way of distinguishing them)
  • A replacement for the PLAYER PHASE screen where it displays the turn number on turn change.
    • Note that the default graphics for this are probably not suitable for use in serious projects. You should however be able to edit those easily.

Known shortcomings

  • AI decision making take a while when many units have to move. This is more of an unfortunate side effect of the AI changes than a bug.
  • The cursor is reset after each move, even if the next phase is the same as the previous one.
  • Phase prediction display is probably active more often than it should be (even during events/menus/stuff like that). Planning on maybe polishing that eventually.
    • Mostly fine now, I think.
  • There is no big “PLAYER PHASE”/“ENEMY PHASE” screen message anymore. This is actually probably a good thing considering phase switches now occur way more often than in vanilla. However, the plan was to “replace” that with a “TURN {X}” message that happens during turn switch; and that isn’t done yet.

Reporting bugs and feedback

This hack is quite big and changes a lot of things. Some things will maybe end up being weird or broken. So if you find anything, or just have suggestions on improving this, or even just questions, or just want to say hi, you can do so by posting here, by finding me on discord, or by adding an issue on the CHAX GitHub repository.

8 Likes

:wave:

Have a bunch of misc small hacks that don’t actually do anything.


Easy Custom Game Speed Config

This is a very simple hack that allows you to define the game’s behaviour when it comes to what speed option means what. This means setting a base speed, whether the “slow movement” byte in the class table should be accounted for, and whether pressing A speeds up movement.

The default setup mostly mimics vanilla; with fast speed also allowing you to press A to speed up movement (using this hack renders the part in essential fixes that does this obsolete).

Usage

Include the installer from somewhere within your buildfile. You can either edit the definitions in the installer itself or copy/paste the definitions block in an earlier definition file and edit there.


Per Chapter Battle/Death Quote Lists

This hack is purely organization-oriented (it doesn’t really add anything to the game).

What this allows you to do is to declare “per chapter” battle quote and death quote lists. The idea is that this allows you to not have to maintain a single huge Battle Quote/Death Quote table; and instead can move chapter-specific quote entries to your chapter events (those quote could be important to the chapter logic so it seems natural that they would be located with the rest of it).

This also makes sharing chapters as self contained modules (which is done relatively commonly for Blitz-inspired projects) easier.

Usage

#include "PerChapterBattleQuote/PerChapterBattleQuote.event"

And then, anywhere after you include the hack (but maybe preferably somewhere chapter-specific) you can do the following:

SetChapterBattleQuoteList(ChapterId, BattleQuoteList)
SetChapterDeathQuoteList(ChapterId, DeathQuoteList)

With BattleQuoteList and DeathQuoteList being labels to Battle Quote/Death Quote “tables” following the exact same format as the one you’d define without the hack.

For convenience, I have also included a series of macros you can use to define your tables within events (as opposed to by using a csv), like so:

ALIGN 4
DeathQuoteList:
	DeathQuoteEid(Bazba, TextBazbaDeath, 2) // sets defeat boss eid
	DeathQuoteEnd

You can also use those to define the main table if you, like me, prefer to do it this way.

See PerChapterBattleQuote.event for the complete macro list (there’s quite a few).


Expanded and Modular Save (Game and Suspend) System

(Note: Kirb was also working on something like this, and may have had it done already (I don’t think so but I could be wrong); but here’s my take on it anyway).

This may need further testing, but as far as I can see it seems to work fine.

This is mainly targeted towards my fellow Wizards. This allows you to reallocate game save and suspend save blocks; And add/remove/replace data “chunks” within them in a modular way (see the files, especially the main installer, for details).

The default block allocation setup is based off @Crazycolorz5’s old plan for a similar hack (big thanks to him for his work). The default game save and suspend save chunk layouts mimic vanilla.

See here for an example setup that “expands” saved unit data, saves all 20 green units, and supports Colorz’s “legacy” expansion (used by debuffs) (this one also probably needs more testing, but again it seems to do fine at a glance).

Usage

See installer, it includes a handful of (hopefully helpful) explanatory comments.


Note: Those hacks may require you to have included “EAstdlib.event” before them; because I’m apparently too lazy to do it in the hack itself.

As usual (?), All sources are available in the “CHAX” GitHub repository. Report bugs or request feature by submitting an issue there or by contacting me directly here or on discord etc

13 Likes