Skip to content

EUD Tutorial: Creating Triggered Spells

Ar3sgice edited this page Oct 2, 2020 · 17 revisions

Locating CUnit address of your unit

For most of the methods here to created a triggered spell, CUnit editing will be required. To do this we need to locate the CUnit address of the unit casting the spells.

For preplaced units, we can use Pure EUDs with fixed CUnit address.

For units created with triggers, we need to use dynamic CUnit EUDs with EUD Editor 3.

Static CUnit for preplaced units

In SCMDraft version 0.9.10, when you look at the unit properties, there is an "Index" property.

This Map Index converts to CUnit Index in the following formula:

If MapIndex == 0: CUnit Index = 0
If MapIndex > 0: CUnit Index = 1700 - MapIndex

Dynamic CUnit for units created with triggers

Use EUD Editor 3 for this. First create a global variable, then set the next unit pointer to it before creating the unit.

Non-targeting spells

Usually the best way is to make a button that creates units, then detect the Build Queue of the unit trying to create it.

It won't actually create the unit because Starcraft limits this ability to buildings only.

When a non-building unit tries to create unit, it puts the unit into its Build Queue, then the progress is stuck at 0% until we detect the queue and reset to empty.

Note: "Empty" queue is set to unit 228 (None) instead of unit 0 (Marine).

Trigger("Player 1"){
Conditions:
	Masked MemoryAddr(0x00623860, Exactly, 64, 0x0000ffff); // CUnit #1642 Build Queue 1

Actions:
	Move Location("Current Player", "Protoss Dark Archon", "Anywhere", "CenterLoc"); // Spell trigger to restore HP
	Create Unit with Properties("Current Player", "Protoss Observer", 1, "CenterLoc", 1);
	Kill Unit("Current Player", "Protoss Observer");
	Modify Unit Shield Points("Current Player", "Protoss Dark Archon", 100, All, "Anywhere");
	Preserve Trigger();
}

//-----------------------------------------------------------------//

Trigger("Player 1"){
Conditions:
	Always();

Actions:
	MemoryAddr(0x00623860, Set To, 14942436); // CUnit #1642 Build Queue 1 & Build Queue 2
	MemoryAddr(0x00623864, Set To, 14942436); // CUnit #1642 Build Queue 3 & Build Queue 4
	Masked MemoryAddr(0x00623868, Set To, 228, 0x0000ffff); // CUnit #1642 Build Queue 5
	Masked MemoryAddr(0x0062386c, Set To, 131072, 0x00ff0000); // CUnit #1642 Secondary Order
	Preserve Trigger();
}

Note that there was another value being set in the "Reset" trigger. This is the unit's Secondary Order.

Setting it back to 2 (Idle) will stop the unit from "trying to create" the unit. Otherwise, it may show a bugged sprite for making an empty unit.

EUD Editor 3 / Dynamic CUnit version:

"Switch 3" activates the spell using regular triggers.

Targeting spells

This is similar as above, but we use Create Building rather than Create Unit.

Creating buildings will let players input a target coordinate for the order. This coordinate is put into CUnit Order Coordinates where we can detect it easily.

The building graphic can be changed to a cursor, a dot, a beacon or like Start Location to mention it was a spell indicator.

Needs to set the order requirement for Build (Protoss) to not limit itself to probes, or it will not work.

Also note that the condition is for Main Order, not Secondary Order. The building process uses both orders, main order for sending unit to the building place, secondary order for making unit of the building. Main Order is detected so the trigger fires before the unit walks to the target.

Trigger("Player 1"){
Conditions:
	Masked MemoryAddr(0x00623814, Exactly, 7936, 0x0000ff00); // CUnit #1642 Main Order

Actions:
	Create Unit with Properties("Current Player", "Protoss Arbiter", 1, "EUDLoc", 2); // Spell trigger to kill units at EUDLoc
	Kill Unit("Current Player", "Protoss Arbiter");
	Kill Unit At Location("Player 8", "Any unit", All, "EUDLoc");
	Move Location("Current Player", "Protoss Dark Archon", "Anywhere", "CenterLoc");
	Move Unit("Current Player", "Protoss Dark Archon", All, "CenterLoc", "CenterLoc"); // Stop the unit from trying to build
	Set Resources("Current Player", Subtract, 1, ore); // Decrease resources manually as mana cost
	Preserve Trigger();
}

//-----------------------------------------------------------------//

To obtain the target location (EUDLoc), we can use a nice Binary Countoff:

Trigger("Player 1"){
Conditions:
	Masked MemoryAddr(0x00623814, Exactly, 7936, 0x0000ff00); // CUnit #1642 Main Order

Actions:
	MemoryAddr(0x0058dd28, Set To, 0); // EUDLoc Left
	MemoryAddr(0x0058dd2c, Set To, 0); // EUDLoc Top
	MemoryAddr(0x0058dd30, Set To, 0); // EUDLoc Right
	MemoryAddr(0x0058dd34, Set To, 0); // EUDLoc Bottom
	Preserve Trigger();
}

//-----------------------------------------------------------------//

// ---- DUPLICATE THIS 16 TIMES ---- //

Trigger("Player 1"){
Conditions:
	Masked MemoryAddr(0x00623820, At least, [^2147483648;0.5], 0x80000000); // CUnit #1642 Order Coordinates
	Masked MemoryAddr(0x00623814, Exactly, 7936, 0x0000ff00); // CUnit #1642 Main Order

Actions:
	MemoryAddr(0x0058dd2c, Add, [^]); // EUDLoc Top
	MemoryAddr(0x0058dd34, Add, [^]); // EUDLoc Bottom
	Preserve Trigger();
}

//-----------------------------------------------------------------//

// ---- DUPLICATE THIS 16 TIMES ---- //

Trigger("Player 1"){
Conditions:
	Masked MemoryAddr(0x00623820, At least, [^], 0x80000000); // CUnit #1642 Order Coordinates
	Masked MemoryAddr(0x00623814, Exactly, 7936, 0x0000ff00); // CUnit #1642 Main Order

Actions:
	MemoryAddr(0x0058dd28, Add, [^]); // EUDLoc Left
	MemoryAddr(0x0058dd30, Add, [^]); // EUDLoc Right
	Preserve Trigger();
}

//-----------------------------------------------------------------//

Duplicate each trigger 16 times separately and put above the trigger mentioned earlier, and it will move EUDLoc (11) to the correct place.

Targeting spells costing energy instead of resources

Creating Buildings have a comeback that it costs resources rather than energy of the unit.

We can make the triggered spell cost energy by simply using a real spell.

  • Change the Animation for the order for that spell to ReturnToIdle so it won't be actually cast.
  • Change the cooldown for the weapon of the spell to 100 so the trigger can distinguish it from other actual spells.

The triggers are almost the same as above, except we use Spell Cooldown as the condition, and reset it to 0 afterwards.

Trigger("Player 1"){
Conditions:
	Masked MemoryAddr(0x0062381c, At least, 1342177280, 0xff000000); // CUnit #1642 Spell Cooldown

Actions:
	Masked MemoryAddr(0x0062381c, Set To, 0, 0xff000000); // CUnit #1642 Spell Cooldown Set back to 0
	Create Unit with Properties("Current Player", "Terran Wraith", 1, "EUDLoc", 2); // Spell trigger to kill units at EUDLoc
	Kill Unit("Current Player", "Terran Wraith");
	Kill Unit At Location("Player 8", "Any unit", All, "EUDLoc");
	Move Location("Current Player", "Protoss Dark Archon", "Anywhere", "CenterLoc");
	Move Unit("Current Player", "Protoss Dark Archon", All, "CenterLoc", "CenterLoc"); // Stop the unit from trying to cast the spell
	Preserve Trigger();
}

//-----------------------------------------------------------------//

The binary countoff is also needed to obtain location coordinates for EUDLoc, with the condition "Main Order" changed to Spell Cooldown.

When the unit casts the spell, the energy is consumed and the trigger fires.

EUD Editor 3 / Dynamic CUnit version:

Raw Code mode is used for reading Order Coordinates to show it clearly. 0x58 is "Order Coordinate X", and 0x5A is "Order Coordinate Y".

Or...

You can simply use the disruption web...