Skip to content

EUD Tutorial: Extended Animations

Ar3sgice edited this page Oct 2, 2020 · 6 revisions

Orders.dat Animation

There is a field called "Animation" in Orders.dat. It controls the animation that runs when a unit uses the order.

It only works for the spell-casting orders such as "Use Ability (Stasis Field)". Normally, it is set to "Cast Spell" (7).

Some spells don't use those orders, e.g. ScannerSweep, DefensiveMatrix and StimPacks. These spells can be given to any unit without worrying about castspell animations.

Extended Animations

In fact, this value is not limited to regular animations (0-27). We can set the value to up to 255.

When the value is above the regular limit, its iscript will overflow the regular header and enter the unknown region, and play animation scripts normally impossible to reach.

Check here for decompiled code for those extended animations: https://ar3sgice.github.io/eudtools/Include/IceDC.html

Protip: you can press up and down arrows in the input field to comfortably go through codes.

But if the animation has no castspell command the unit won't cast the spell! What's the point of doing this!?

Incorrect. It still drains mana and enters spell cooldown, so if we detect the changes via CUnit we can let it trigger a spell.

Also sometimes there are animation codes that get lucky enough to run into a 0x27 castspell, albeit really rare.

Examples

Masked MemoryAddr(6704592, Set To, 1241513984, -16777216);

This changes Stasis Field order animation to 74.

Whenever an arbiter casts stasis field, the script adds an archon being and an archon swirl to the arbiter.

playfram	0x12	# frame set 1
wait	1
nobrkcodestart
wait	1
playfram	0x13	# frame set 1
wait	2
playfram	0x14	# frame set 1
wait	2
playfram	0x15	# frame set 1
wait	2
playfram	0x16	# frame set 1
wait	2
playfram	0x17	# frame set 1
wait	2
playfram	0x18	# frame set 1
wait	2
playfram	0x19	# frame set 1
wait	2
playfram	0x1a	# frame set 1
wait	2
imgol	135 0 0
imgol	136 0 0
sigorder	4
nobrkcodeend
wait	2
playfram	0x00	# frame set 0
wait	1
playfram	0x01	# frame set 0
wait	1
playfram	0x02	# frame set 0
wait	1
playfram	0x03	# frame set 0
wait	1
playfram	0x04	# frame set 0
wait	1
playfram	0x05	# frame set 0
wait	1
playfram	0x06	# frame set 0
wait	1
playfram	0x07	# frame set 0
wait	1
playfram	0x08	# frame set 0
wait	1
playfram	0x09	# frame set 0
wait	1
playfram	0x08	# frame set 0
wait	1
playfram	0x07	# frame set 0
wait	1
playfram	0x06	# frame set 0
wait	1
playfram	0x05	# frame set 0
wait	1
playfram	0x04	# frame set 0
wait	1
playfram	0x03	# frame set 0
wait	1
playfram	0x02	# frame set 0
wait	1
playfram	0x01	# frame set 0
wait	1
goto	9826

The archon beings can use attacks together with the arbiter main image, doubling every attack with an archon beam.

If it casts another stasis field, another pair of archon being and swirl will be added.

Set Doodad State

SetDoodadState trigger is one of the cases Starcraft will try to play iscripts regardless of their existence.

Disable Doodad State plays Disable animation. Enable Doodad State plays Enable animation but it only works if it's already disabled.

However, this does not always lead to iscript 0, because the iscript headers are of variable length, and Disable (+0x38) often overflows into the actual script area.

For example, the iscript header for Marine is

53 43 50 45 // "SCPE"
0C 00 00 00 // 12 = 14 Animations
F8 70       // MarineInit
7F 71       // MarineDeath
F8 71       // MarineGndAttkInit
F8 71       // MarineGndAttkInit (Air)
00 00
05 72       // MarineGndAttkRpt
05 72       // MarineGndAttkRpt (Air)
00 00
2E 72       // MarineGndAttkToIdle
2E 72       // MarineGndAttkToIdle (Air)
00 00
B6 71       // MarineWalking
FD 70       // MarineWalkingToIdle
00 00

After this is the next header (MarineDeath)

53 43 50 45 // "SCPE"
01 00 00 00 // 1 = 2 Animations
84 71       // MarineDeathInit
20 79       // long01

Then the actual script

09 F0 00 00 00 // imgul 240 0 0
00 44 00       // playfram 0x44
06 3F 4B       // waitrand 63 75
1E 19 24 71    // randcondjmp 25 MarineLocal00
1E             // randcondjmp 128 MarineLocal01
80 0E          // "Disable" animation overflows to here
71
07 00 71       // goto MarineLocal02

The "Disable" animation overflows into the actual script area, and points to 0x0E80. It decompiles like this:

EnsnareOverlayInit:
	tmprmgraphicstart	
	waitrand       	1 3
	tmprmgraphicend	
MarineLocal05:
	playfram       	0
	wait           	2
	playfram       	1
	wait           	2
	playfram       	2
	wait           	2
MarineDisabled:
	playfram       	3
	waitrand       	2 3
	goto           	MarineLocal05

It jumps into the Ensnare scripts, which is why a marine turns around when it gets disabled.