[ASM Request/Suggestion] Get unit distance

Hi, I think having a “get unit distance” event might be really useful.
Something that evaluates the distance between a unit and another unit, a unit and a point or a unit and a type of unit.

First one of the type: “check the distance between these 2 units IDs”, second one that works like “this unit and this point (x,y)” and third/fourth one maybe something like min and max distance between a unit and a certain type of unit (defined by id, class, affiliation etc…).

4 Likes

@7743 has previously made a patch that might help.

Count number of units in a specific range

You could technically use this to check if a specific unit is within x tiles of sB, you would just need to repeatly call the function for each distance until you can discern what that distance is.

For example, when operating unit stops anywhere, check if unit #3 is holding item F6, is an NPC, and is within 1 tile. If not, check 2 tiles. If so, you now know it’s specifically 2 tiles away.
This is rather cumbersome, but I’ve written an event before that simply checks if there are specific types of units within 4 tiles and if so, change their AI2 to 23 and give them +5 movement.

Screenshot of febuilder event

.event
SVAL 0x2 0x0
CALL 0x9EE1B8
WORD 0x10000D4F 0x8F00915
SADD 0xC1
SVAL 0x7 0x4
BLE 0x9000 0xC 0x7
SVAL 0x3 0x4
SSUB 0x311
GOTO 0x9001
LABEL 0x9000
SVAL 0x1 0x0
LABEL 0x9001
WORD 0x11000D4F 0x8F00915
SADD 0xC2
SVAL 0x7 0x4
BLE 0x9002 0xC 0x7
SVAL 0x3 0x4
SSUB 0x322
GOTO 0x9003
LABEL 0x9002
SVAL 0x2 0x0
LABEL 0x9003
SVAL 0x3 0x10000
SMUL 0x232
SADD 0x125
WORD 0x10000D4F 0x8F00915
SADD 0xC1
SVAL 0x3 0x4
SADD 0x136
WORD 0x11000D4F 0x8F00915
SADD 0xC1
SVAL 0x3 0x10000
SMUL 0x131
SADD 0x166
SVAL 0x3 0x40000
SADD 0x366
GOTO 0x9010
ASMC 0xF007CD
LABEL 0x9010
SVAL 0x1 0x0
SVAL 0x2 0x0
SVAL 0x3 0xF6
SVAL 0x4 0x2
ASMC 0x175ADD
SVAL 0x7 0x0
BLE 0x9050 0xC 0x7
SVAL 0x1 0x0
SVAL 0x2 0x0
SVAL 0x3 0xF6
SVAL 0x4 0x2
SVAL 0xA 0x44
SVAL 0xB 0x17
ASMC 0x175BC1
SVAL 0xA 0x1D
SVAL 0xB 0x5
ASMC 0x175BC1
STAL 1
ASMC2 0x175D81
CAM1 0x1
SET_ACTIVE 0x0
ENUT 0x67
ASMC 0x225F9
LABEL 0x9050
EVBIT_T 0x7
ENDA

I did this to have a generalized way to check if units are nearby, rather than creating a range event every time.

Gif

5Cex5heoip

The event I shared above is what happens right before you see “enemy phase” in order to check if these monsters are going to initiate a battle with you. The rest of it is much more complicated.

Perhaps someone else can offer an actual ASM solution. Just thought I’d share about how powerful the event engine has become with all the patches made for it.

I too would appreciate the requested scripts! :slight_smile: They would be a more elegant method than some of my grotesque hackery.

2 Likes

Wow, this is majestic.
Also, I have 2 little off topic questions, sorry to bother you.

How do you insert comments in Event Editor? I thought it wasn’t possible.

Why do you use such big numbers for the IDs like 9000 etc… instead of smaller numbers like 1,2,3…?

1 Like

While you have a command selected, double click it or press enter to edit the command, change it, insert a new one, or add a comment to it.

20200708_053919
Comment space is right below what you see in this picture. Sorry, just grabbed the pic from a guide I’d made.

I use such big numbers for labels because I am a product of febuilder’s event templates. I learned how to write events in the last few months by repurposing the templates provided to do what I want. 7743 made them default to 9000, 9001, then 9002, etc.

I suppose I could use much smaller numbers now. It just kinda stuck with me.

Thanks.

Oh ok thanks, I wanted to know if there was a more practical motivation.
What made me curious was the fact that 7743 also used big numbers, so maybe there was something behind it.

Untested (though I made sure it assembles), but this is how I would solve the problem with a quick ASM routine. I didn’t handle units not existing sue me

.thumb
.macro blh to, reg
    ldr \reg, =\to
    mov lr, \reg
    .short 0xF800
.endm
.equ GetUnitStructFromEventParameter, 0x800BC51
.equ gEventSlot, 0x30004B8
.global GetUnitDistance
.type GetUnitDistance, %function
GetUnitDistance: @ ASMCed. Memory slots 0x1 and 0x2 are character IDs to check (supporting event parameters), returns in slot 0xC.
push { r4 - r6, lr }
ldr r6, =#gEventSlot
ldr r0, [ r6, #0x04 ] @ Memory slot 0x1.
blh GetUnitStructFromEventParameter, r1
mov r4, r0 @ Store the first unit struct in r4.
ldr r0, [ r6, #0x08 ] @ Memory slot 0x2.
blh GetUnitStructFromEventParameter, r1
mov r5, r0 @ Store the second unit struct in r5.
ldrb r0, [ r4, #0x10 ] @ X coords.
ldrb r1, [ r5, #0x10 ]
sub r3, r0, r1 @ Take the difference between the X coords.
cmp r3, #0x00
bge NotNegative1
	neg r3, r3
NotNegative1:
ldrb r0, [ r4, #0x11 ] @ Y coords.
ldrb r1, [ r5, #0x11 ]
sub r2, r0, r1
cmp r2, #0x00
bge NotNegative2
	neg r2, r2
NotNegative2:
add r2, r2, r3 @ Add the X and Y differences.
str r2, [ r6, #0x30 ] @ Memory slot 0xC.
pop { r4 - r6 }
pop { r0 }
bx r0
3 Likes

I made two versions based on the source code of Snakey1.

ASMC_GetUnitDistance.s
Distance between Units.
Added error handling to the Snakey1 code.

ASMC_GetUnitDistanceCoord.s
Coordinate and unit distance.

ASMC_GetUnitDistance.s

.thumb
.macro blh to, reg
    ldr \reg, =\to
    mov lr, \reg
    .short 0xF800
.endm

.equ GetUnitStructFromEventParameter, 0x800BC51
.equ gEventSlot, 0x30004B8
.global GetUnitDistance
.type GetUnitDistance, %function
GetUnitDistance: @ ASMCed. Memory slots 0x1 and 0x2 are character IDs to check (supporting event parameters), returns in slot 0xC.

push { r4 - r6, lr }
ldr r6, =#gEventSlot
ldr r0, [ r6, #0x01 * 4 ] @ Memory slot 0x1.
blh GetUnitStructFromEventParameter, r1
cmp r0, #0x0
beq Error
mov r4, r0 @ Store the first unit struct in r4.

ldr r0, [ r6, #0x02 * 4 ] @ Memory slot 0x2.
blh GetUnitStructFromEventParameter, r1
cmp r0, #0x0
beq Error
mov r5, r0 @ Store the second unit struct in r5.

ldrb r0, [ r4, #0x10 ] @ X coords.
ldrb r1, [ r5, #0x10 ]
sub r3, r0, r1 @ Take the difference between the X coords.
cmp r3, #0x00
bge NotNegative1
	neg r3, r3
NotNegative1:
ldrb r0, [ r4, #0x11 ] @ Y coords.
ldrb r1, [ r5, #0x11 ]
sub r2, r0, r1
cmp r2, #0x00
bge NotNegative2
	neg r2, r2
NotNegative2:
add r2, r2, r3 @ Add the X and Y differences.
b   Exit

Error:
mov r2, #0x0   @ Error

Exit:
str r2, [ r6, #0xC * 4 ] @ Memory slot 0xC.

pop { r4 - r6 }
pop { r0 }
bx r0

ASMC_GetUnitDistanceCoord.s

.thumb
.macro blh to, reg
    ldr \reg, =\to
    mov lr, \reg
    .short 0xF800
.endm

.equ GetUnitStructFromEventParameter, 0x800BC51
.equ gEventSlot, 0x30004B8
.global GetUnitDistance
.type GetUnitDistance, %function
GetUnitDistance: @ ASMCed. Memory slots 0x1 and 0x2 are character IDs to check (supporting event parameters), returns in slot 0xC.

push { r4 - r6, lr }
ldr r6, =#gEventSlot
ldr r0, [ r6, #0x01 * 4 ] @ Memory slot 0x1.
blh GetUnitStructFromEventParameter, r1
cmp r0, #0x0
beq Error
mov r4, r0 @ Store the first unit struct in r4.


ldrb r0, [ r4, #0x10 ] @ X coords.

mov r1, #0x0B * 4 + 0
ldrh r1, [ r6, r1 ] @ Memory slot 0xB->X

sub r3, r0, r1 @ Take the difference between the X coords.
cmp r3, #0x00
bge NotNegative1
	neg r3, r3
NotNegative1:
ldrb r0, [ r4, #0x11 ] @ Y coords.

mov r1, #0x0B * 4 + 2
ldrh r1, [ r6, r1 ] @ Memory slot 0xB->Y

sub r2, r0, r1
cmp r2, #0x00
bge NotNegative2
	neg r2, r2
NotNegative2:
add r2, r2, r3 @ Add the X and Y differences.
b   Exit

Error:
mov r2, #0x0   @ Error

Exit:
str r2, [ r6, #0xC * 4 ] @ Memory slot 0xC.

pop { r4 - r6 }
pop { r0 }
bx r0
3 Likes

Thank you both very much! I always love playing with all the addevent asm hacks to see what craziness I can come up with.

I especially appreciate it when they take accept inputs from a memory slot (LOW commands) - it’s really helpul when I can use a command with variables.

Thank you.

I seem to have accidentally posted it on the FEBuilderGBA thread.

I made a patch.

Add Event: GetUnitDistance
It provides you with the following instructions.

EVENTSCRIPT:1.en=400D0000{$L1:ASMC_GetUnitDistance.dmp}	Get Distance between Units in Slot1 and Slot2(LOW)	@STOREC	{COND}
EVENTSCRIPT:2.en=40050100XXXXXXXX40050200YYYYYYYY400D0000{$L1:ASMC_GetUnitDistance.dmp}	Get Distance between Units in [XX:UNIT:Unit1] and [YY:UNIT:Unit2]	@STOREC	{COND}
EVENTSCRIPT:3.en=40050100FFFFFFFF40050200YYYYYYYY400D0000{$L1:ASMC_GetUnitDistance.dmp}	Get Distance between Units in CurrentUnit and [YY:UNIT:Unit]	@STOREC	{COND}
EVENTSCRIPT:11.en=400D0000{$L1:ASMC_GetUnitDistanceCoord.dmp}	Get Distance between Unit of Slot1 and Coordinates of SlotB(LOW)	@STOREC	{COND}
EVENTSCRIPT:12.en=40050100ZZZZZZZZ40050B00XXXXYYYY400D0000{$L1:ASMC_GetUnitDistanceCoord.dmp}	Get Distance between [ZZ:UNIT:Unit] and Coordinates of [XX:MAPX:X][YY:MAPY:Y]	@STOREC	{COND}

EVENTSCRIPT:13.en=40050100FFFFFFFF40050B00XXXXYYYY400D0000{$L1:ASMC_GetUnitDistanceCoord.dmp}	Get Distance between CurrentUnit and Coordinates of [XX:MAPX:X][YY:MAPY:Y]	@STOREC	{COND}
sample

As a measure against covid-19, we will carry out a social distance between the ally.
Please leave at least 2 spaces between player units.
If the units approach each other, Zeth will get angry when they wait.
In addition, only the prologue is made.

ups
https://cdn.discordapp.com/attachments/145137778710151168/730744205302956182/GetUnitDistanceSample.7z

3 Likes