Sme’s ASM and Miscellany

I think I may have found a bug with fatigue, but I am not sure how best to replicate it.

From the best that I can observe, when you are recruiting a unit who was once a red or green unit after a certain amount of turns have passed, the unit in question will not join with 0 fatigue to start. Somewhere it seems that a value of some kind is getting written to byte 0x3B. I’m not sure from where or how this is happening.

It’s entirely possible that something in my own hack is causing a value to be written here, but to the best of my knowledge nothing writes to that byte in the character struct.

The best solution, if possible, in my opinion would be to update the turn ally routine to set a units fatigue to 0 as part of that change. I would try and do this myself, however I don’t have enough knowledge about how to exactly read the event assembler code to find where the routine is in the rom. Of course, you could always use a different BYTE if one is available.

Writing an ASMC to set that value sounds rather simple

2 Likes

I’ll look into this, as a temp solution you can use an ASMC to reset fatigue just after they’re recruited

2 Likes

I’m going to try and look into how exactly to do this. Directly changing a unit’s RAM like that isn’t something I’m very familiar or skilled at doing when it comes to doing so in chapter.

I can provide a patch with some .sgm/save states that show that the issue can happen, but the one thing I can’t provide is how to trigger as I haven’t found a consistent way to do so. All I can say is that at some point, some value gets put into byte 0x3b.

EDIT: Modifying one of Venno’s scripts (the status setter) I was able to solve the issue.

How to use (copied from Venno):
-incbin “fatigueReset.dmp” within your buildfile somewhere, preferably with a label.
-In your events, do this:
TurnAlly(character ID)
SVAL 0x1 (character ID)
SVAL 0x2 (fatigue byte)
ASMC (YourLabel|1)

Modified ASM

@Set a status effect to a unit
@S1 = unit ID to target; first unit with this ID will be affected
@S2 = Fatigue Byte

.thumb

push {r4,r5,r14}
ldr r4, MemorySlots
ldr r2,[r4,#0x4]
mov r1,#0x0
sub r1,#0x1
cmp r2,r1
bne SearchStart @If char ID not -1, assume it’s a normal character ID
ldr r0,ActiveUnit
ldr r0,[r0]
cmp r0,#0x0 @Make sure we have a unit in this
ble End
ldr r1,[r0]
b MatchFound

SearchStart:
cmp r2,#0x0
ble End
ldr r5,DeploymentOffsList
mov r3,#0x1 @r3 is loop counter
UnitSearchLoop:
lsl r0,r3,#0x2
ldr r0,[r5,r0]
cmp r0,#0x0
beq SearchLoopCount
ldr r1,[r0] @Loading character data pointer
cmp r1,#0x0
beq SearchLoopCount
ldrb r1,[r1,#0x4]
cmp r1,r2 @Is this the character we’re looking for?
beq MatchFound
SearchLoopCount:
add r3,#0x1
cmp r3,#0x55 @Searches through all player/NPC units
bhs End_false
b UnitSearchLoop

MatchFound:
ldr r1,MemorySlots
ldr r1,[r1,#0x8] @Load the fatigue byte
mov r3,#0x0
strb r3,[r0,r1]
End:
pop {r4,r5}
pop {r0}
bx r0

.align 2
MemorySlots:
.long 0x030004B8
DeploymentOffsList:
.long 0x0859A5D0
MinusOne:
ActiveUnit:
.long 0x03004E50

1 Like

[ASM] More Shop Music (FE8)

An extension of my previous Unique Shop Music hack to coincide with shop type expansion. This allows you to set shop music per-shop type, per-chapter. Using this, you can have individual songs for 256 shop types for 256 chapters.

Download

To use, #include "MoreShopMusic.event". Within this file are the chapter pointer table and an example shop song table, as well as macros to write to each. Use the macro SetSongChapterPointer(chapterID,songTable) with the desired chapter and label for shop song table to set a table to a chapter. To make a new shop song table, make a label and follow it with InitializeShopSongTable. Then, use the SetShopSong(songTable,shopType,songID) macro to set the song to the given shop type (definitions are included for the 3 vanilla types).

14 Likes

[ASM] Laguz Bars (FE8)

The Tellius mechanic, though it works slightly differently than it does in either FE9 or FE10.

The transformation bar runs from 0-30, like in FE10. Unlike in FE10 and like in FE9, you can set a starting position for the bar per-unit on a table. The bar will be initialized to this value at the start of each chapter.
A unit’s bar fills by a set amount every turn and a separate set amount every battle the unit participates in. This amount can be set on a table per-class for increase in either scenario, as well as decrease in the same scenarios when transformed. Note that the transformed class’s decrease values and the untransformed class’s increase values will be used in their respective scenarios; this is set up such that you can have a class that is the transformed version of another, but itself an untransformed class in another class pair.
When the bar is full, you gain the option to Transform; doing so does not consume your action, but you cannot untransform manually. While you are transformed, you get stat boosts; these are configurable per-class, per-stat, based on the transformed class.

Your bar depletes in the same scenarios as it increased in when untransformed. Once the bar hits 0, you automatically untransform back into your previous class.

But, this is not just limited to player units. Enemy and NPC units that are laguz classes will gain bar at the start of their phases, and if this is enough to transform them (or if they already have enough to transform) they will automatically do so. Their bar mechanics are otherwise identical to player units, including automatically untransforming when the bar reaches 0.

Download

Included is a file containing the MSS code for getting the bar to display as seen in the above gifs, as well as installation instructions.

To designate a laguz untransformed/transformed class pair, in LaguzBars.event there is a list for this purpose. Each entry is BYTE UntransformedClassID TransformedClassID, and the end of the list is designated with BYTE 0 0.

There is nothing included with this hack for laguz weapons, as they can be accomplished by disallowing trading/removal of the weapon and giving it a class lock to the transformed class (as was done in the above gifs).

you can also use it to do things like this

IJOZSJ2wE9
vOQsvQlnVE

32 Likes

one step closer to a tellius demake…

2 Likes

where yo ledges at

4 Likes

I was playing fe9 and started thinking about this. You’re amazing sme, keep it up!

One question though, is the charge time universal or can it be different for each class pairing?

1 Like

Did you know that I was just thinking about how useful this would be?
Good job, this looks great!

1 Like

Charge times are all set per-class

1 Like

[ASM Addon] Laguz Bars - Skills (FE8)

This is a bit different from the way I normally do things, but this is an addon to Laguz Bars that implements the skills Wildheart and Formshift from Radiant Dawn. Wildheart has a laguz unit halfshifted; they are always transformed, but only gain half the stat boosts. Formshift has a laguz unit always transformed with full stat boosts.

y2U26VugD9

Download

To install, overwrite the files in the base package with the respective files in this package. You’ll also need to define Wildheart and Formshift as skills.

I’ve got a few bigger things in the pipelines atm, hopefully I’ll be able to share those with you soon
20 Likes

all we need is map affinity and bonus exp and we’re set for life for a tellius demake

4 Likes

Now this is Epic

2 Likes

what about biorhythm?

2 Likes

bruh

5 Likes

holy shit

5 Likes

[ASM] Trap Rework & Tellius Torches (FE8)

Trap Rework makes a modular system for adding new traps and letting them display map sprites. The intention is to be user-friendly without needing to touch assembly to define new traps, and as such comes shipped with a number of general-use functions that themselves can be used as a basis for more complex trap cases.

Shipped alongside Trap Rework are conversions of Dragon Veins by Crazycolorz5 and circleseverywhere and Heal Tiles by Snakey1 to use this system, as it is otherwise incompatible with previous versions of these. This also separates the two from one another, as so they don’t have to both be present. It also ships with a new hack, Tellius Torches, for which this system was created. Note that with default settings you will create errors by removing Heal Tiles or Tellius Torches due to the presence of more complex map sprite display checks for each, but Dragon Veins should be entirely removable.

qi5logvbVU

Download

Tellius Torches provide a configurable amount of fog vision and can be toggled on or off by an adjacent unit. They display a map sprite depending on their state (IDs are configurable) and cannot be stood upon. To designate a torch in events, use TelliusTorchOff(x,y,visionRange) for a torch that starts in the off position or TelliusTorchOn(x,y,visionRange) for a torch that starts in the on position. The vision range is retained per-torch when toggled on and off. You can canto out of using a torch, but you cannot use a torch while cantoing. Note that placing torches horizontally, vertically, or diagonally adjacent or along the outside edge of the map is liable to issues. Included torch graphics were made by L95.

Using just EA, you can set up new map sprite traps for purposes such as map indicators, or anything else you so desire. To do so, you just need to use these 3 macros:

SetTrapEventInit(trapID,TrapRework_GenericInitializer) will set a generic function for initialization of the trap from events to memory, allowing you to define your new traps in your events.
SetTrapMapSprite(trapID,mapSpriteID) will set the map sprite to display for your trap at its position on the map. Note that 32x32 map sprites tend not to work well with traps.
SetTrapMapSpritePalette(trapID,paletteWord) will set the palette for the map sprite to use. Don’t worry about the palette word, as you also have the following definitions for each palette:

  • LightRuneTrapPaletteWord will use the Light Rune palette.
  • PlayerTrapPaletteWord will use the player unit palette.
  • EnemyTrapPaletteWord will use the enemy unit palette.
  • NPCTrapPaletteWord will use the NPC unit palette.
  • GreyTrapPaletteWord or GrayTrapPaletteWord will use the greyed out unit palette.

To place a trap on your map, you can use the macro MapSpriteTrap(trapID,x,y) in event trap data to define a trap of the given ID at the given coordinates. Note that trap IDs in use in vanilla run through 0xD, and with default settings here through 0xF

Trap Rework also contains a small library of ASMCs that may be used to manipulate traps mid-chapter. Note that when adding traps through this method, the total limit is 64 at a time, including map changes & breakable walls/snags towards this total. Exceeding this amount is a bad idea, so be wary with how many traps you create. In all cases these macros use memory slot 1 for trap ID, memory slot B for coordinates, and memory slot C for returning values. If you use a macro with these parameters, the previous value in the relevant memory slots WILL be overwritten.

AddTrap(trapID,x,y) will create a new trap of the given ID at the given coordinates.
RemoveTrapAtCoords(x,y) will remove the first trap found at the given coordinates.
GetTrapIDAt(x,y) will return the ID of the trap at the given coordinates.
GetTrapExt1At(x,y) will return the first value of the trap at the given coordinates. What this value is depends on the type of trap, and map sprite traps do not use it at all.

20 Likes

Very very cool! A trap data rework like this has been needed for a while. :+1:

2 Likes

So if we are using the skills system, all we should need to do is disable the dragon veins hack to include this?