FX for units commands?


#1

I made this command, I’m intending to make skills like this one to be used like to commans and add various effects in combat, this skill makes the user inflicts silence in himself during 3 turns (Not having the silence effect already is a requirement to trigger it, besides, only this character can use it and it can only use magic to attack) and deals 30 points of damage to every unit in 3 radio squares, allies and enemies (including him). I’m not very good with ASM but I manage to do things like this, but I do not have any idea about how to make a graphic effect and I fell that one is needed for the skill command (i think it feels bad without the effect), does anyone have a tutorial here or in FEUniverse or another site to do it? (sorry for the long spanish introduction in the video, is for a Facebook Group)


#2

I don’t think there’s a tutorial on this, but I’ll try to explain how I do it.

If you know how to make the visual and sound effects with events you can just do that for your skills, then you can call the event in your asm routine, so:

  • Load the offset to your event in r0
  • Set r1 to 1 (I think this is what makes it so everything else waits for the event to finish)
  • Call 0x800D07C (this will make the event run)

That’s what I did for the lifetaker animation, here is the relevant part of the routine:

ldr r0,=#0x800D07C @event engine thingy
mov lr, r0
ldr r0, LifetakerEvent @this event is just “teleport animation on current character”
mov r1, #0x01 @0x01 = wait for events
.short 0xF800

.short 0xF800 will call the routine at offset r14 (also known as lr)
“LifetakerEvent” is the offset of the event to display, the event looks like this:

CAM1 0xFFFF
WARP_IN
STAL 0x32
NoFade
ENDA

There probably is a better way to do this and I highly doubt this is how staffs and other items do it (I never checked) but it does work.

I would also suggest using the skill system (unless you have reasons not to) since it will make a lot of this stuff easier, there are some functions already made that you can call to check units in range, a lot of hooks in place, it comes with a ton of skills, the modular stat screen and all that good stuff.


#3

This is my code

.thumb
.org 0x00

Initial:

push 	{r0-r7}

ldr		r4, =0x03004E50
ldr		r3, [r4]
ldrb	r6, [r3,#0x10]	@ r6 = coordenada en X
ldrb	r7, [r3,#0x11]	@ r7 = coordenada en Y
mov		r4, r3
add		r4, #0x30  @Es la posicion del estado
mov		r5, #0x33  @Silencio por 3 turnos
strb	r5, [r4]


ldr		r3, TablaAliada
Ciclo:
ldr		r4, [r3]
ldr		r5, Vacio
cmp		r4, r5
beq		FinCiclo
mov		r5, #0
ChecaX:
ldrb	r4, [r3,#0x10]
cmp		r6, r4
blo		XEsMenor
bhi		XEsMayor
XEsIgual:
b		ChecaY
XEsMenor:
sub		r4, r4, r6
add		r5, r4
b		ChecaY
XEsMayor:
sub		r4, r6, r4
add		r5, r4
ChecaY:

ldrb	r4, [r3,#0x11]
cmp		r7, r4
blo		YEsMenor
bhi		YEsMayor
YEsIgual:
b		ChecaEscribe
YEsMenor:
sub		r4, r4, r7
add		r5, r4
b		ChecaEscribe
YEsMayor:
sub		r4, r7, r4
add		r5, r4
ChecaEscribe:

cmp		r5, #03
bhi		NoEscribe
Escribe:
ldrb	r4, [r3,#0x13]
sub		r4, #30
ChecaNegativo:
cmp		r4, #121
blo		ChecaCero
mov		r4, #01
ChecaCero:
cmp		r4, #0
bhi		NoAjusta
mov		r4, #01	
NoAjusta:
strb	r4, [r3,#0x13]

NoEscribe:


add		r3, #0x48
b		Ciclo
FinCiclo:
ldr		r4, TablaEnemiga
cmp		r3, r4
blo		EditaEnemigos
ldr		r4, TablaNPC
cmp		r3, r4	
blo		EditaNPC
b		Animacion
EditaEnemigos:
ldr		r3, TablaEnemiga	
b		Ciclo
EditaNPC:
ldr		r3, TablaNPC	
b		Ciclo	

@Here start the animation part

Animacion:

mov		r3, lr
ldr		r0,	=0x0800D07C	
mov		lr, r0
ldr		r0, =0x09000700	
mov		r1, #0x01		
.short	0xF800	
mov		lr, r3
b		End

End:
pop 	{r0-r7}

ldr 	r1, =0x203A958
mov 	r0, #0x01
strb 	r0, [r1, #0x11]
mov 	r0, #0x17
bx 		r14
.align 2, 0
Vacio:
.long 0x00000000
TablaAliada:
.long 0x0202BE4C
TablaEnemiga:
.long 0x0202CFBC
TablaNPC:
.long 0x0202DDCC

and the event

ORG 0x1000700 
MUS1 0x68
STAL 200
STAL 200
STAL 200
STAL 200
STAL 200
STAL 200
ENDA

I’ve been trying to make it work for over two hours.
The game crash, then I realized that when doing the “mov lr, r0” this happened, I thought that to avoid it, move from lr to r3 and then returning it so that I can have it at the end of the routine, but it continues crashing and this it stops when I remove the “.short 0xF800” so I guess that is what causes the crash, I really do not know what is wrong.


#4

First problem I see is that you didn’t push r14 in the beginning. When you use bl (or .short 0xF800, which is just bl lr+0), r14 gets overwritten by the new function call. When it’s time to go back, since you didn’t save the address to return to, bx r14 ends up…somewhere else.

You don’t usually need to push r0-r3, those are “scratch” registers, meaning you don’t need to preserve their values.

Instead of ldr r5, Vacio, where Vacio = 0x00000000, just use mov r5,#0x0 instead.

I’d call the function at 0x19430, which takes a unit number as an argument and returns the character data pointer, rather than having Player_Table, Enemy_Table, and NPC_Table and adding 0x48 to get the next unit. That works, sure, but it’s cleaner to use the existing function.


#5

They works, thanks.


#6

Made a clearer version:

.thumb
.org 0x0

Initial:

push	{r4-r7,r14}
ldr		r4, =0x03004E50
ldr		r3, [r4]
ldrb	r6, [r3,#0x10]	@ r6 = coordenada en X
ldrb	r7, [r3,#0x11]	@ r7 = coordenada en Y
add		r3,#0x30		@Es la posicion del estado
mov		r0,#0x33		@Silencio por 3 turnos
strb	r0,[r3]

mov		r4,#1
ldr		r5,=#0x8019431	@19430 is the function that, given unit number, returns data
Loop1:
mov		r0,r4
bl		bx_r5			@puts character's data pointer in r0	
cmp		r0,#0
beq		NextUnit
ldr		r1,[r0]			@rom character data pointer, is 0 if unit doesn't exist/died
cmp		r1,#0
beq		NextUnit
ldrb	r2,[r0,#0x10]	@unit's x coordinate
sub		r1,r6,r2
cmp		r1,#0
bge		Label1
sub		r1,r2,r6
Label1:
ldrb	r2,[r0,#0x11]	@unit's y coordinate
sub		r3,r7,r2
cmp		r3,#0
bge		Label2
sub		r3,r2,r7
Label2:
add		r1,r1,r3		@r1 = distance between units
cmp		r1,#3
bgt		NextUnit
ldrb	r1,[r0,#0x13]	@unit's current hp
sub		r1,#30
cmp		r1,#1			@make sure hp is positive
bge		HpNotNegative
mov		r1,#1
HpNotNegative:
strb	r1,[r0,#0x13]

NextUnit:
add		r4,#1
cmp		r4,#0xBF		@last enemy unit ID
ble		Loop1

ldr		r5,=#0x800D07D
ldr		r0,=#0x9000700
mov		r1,#1
bl		bx_r5

ldr		r1,=#0x203A958
mov		r0,#1
strb	r0,[r1,#0x11]
mov		r0,#0x17
pop		{r4-r7}
pop		{r1}
bx		r1

bx_r5:
bx		r5

.ltorg

#7

Thanks, I’ll see what I learn by examining it