Most of what the earlier lessons explain one at a time is already written. TETools.eps, which ships with EUD Editor 3's TriggerEditor, holds about sixty skill primitives. Each comes as a pair - one taking an EPD, one taking a pointer - and each carries a Korean doc comment whose @Type says whether it is an A (action) or a C (condition), which is how TriggerEditor decides where to list it.
import TriggerEditor.TETools as TE;
if (TE.BuildCheckEPD(epd, Q)) {
...
TE.BuildResetEPD(epd);
}| 스킬 감지 | Non-target and target skill detection, build-queue detection and reset. |
|---|---|
| 피해 | AttackGround, which hits a chosen point with a real weapon. |
| 명령 | Issue an arbitrary order by location, unit or coordinate; send a worker to build. |
| 기하학 | Rotate a location, move it in polar coordinates, angle and distance between two points, attach a location to a unit, count inside an area. |
| 변신·소환 | Cocoon and egg overlays, larva morph, the unit-production motion. |
| 외형·상태 | Recolour a single unit, set and clear status flags. |
| 연출 | Screen shake, and putting a unit into a control-group slot. |
The point of this lesson is not the list, though. It is that you should read the implementations rather than trusting the names, because in several of them the implementation *is* the technique and you cannot see it from outside. Non-target detection is the best example.
if (MemoryXEPD(epd + 0x4D/4, Exactly, skillOrder * 256, 0xFF00)) {
const x, y = posread_epd(epd + 0x28/4); // 영웅 위치 / where the hero is
setloc(unitLoc, x, y);
setloc_epd(targetLoc, epd + 0x58/4); // 찍은 위치 / where it was aimed
if (range > LocationDistance(unitLoc, targetLoc)) {
SetMemoryXEPD(epd + 0x4C/4, SetTo, 0x100, 0xFF00); // 명령 1 = Stop
SetMemoryEPD (epd + 0x10/4, SetTo, x + y * 65536); // 이동 목표 = 제자리
return True;
}
}
return False;The behaviour where clicking out of range makes the hero walk there and then cast is not a feature somebody added. It happens because the function does not cancel the order when the click is out of range: the stock spell order is still live, so StarCraft walks the hero over by itself. The moment it is in range the test passes, and only then does it cancel and return True. Approach, stop and fire all come out of one distance comparison, with no state to keep.
And it stops the unit twice: it writes Stop to the order and it writes the unit's own position into the move target at 0x10. Write only the order and a unit that has already started moving keeps sliding to its old waypoint. Whether you cancel with order 1 (Stop) or 2 (Guard) changes what happens afterwards - Guard re-acquires targets and keeps auto-attacking, Stop just stands there. Pick per skill.
The second example is the build-queue reset, where emptying the five queue slots is only half the job.
The empty-slot value is 228, the "None" unit id. If you fill all five slots with 228 and the unit still tries to produce, you did not write 2 into 0xA6: production runs off that secondary-order field. "I cleared the queue and it kept producing" is almost always this one line.
In the implementation all six fields are written in one block: it points the CurrentPlayer write address at the unit's 0x98 and then walks 0x6509B0 forward one slot at a time. That is the textbook use of the CP trick - sweeping consecutive fields of a struct instead of computing six addresses.
The other two show up in other lessons. AttackGround's "firing angle 255" and "check for a free unit slot first" are in the custom-damage lesson, and the reason screen shake calls rand() outside the local branch is in the desync lesson. Both are rules that still apply when you are not using those functions.
Damage and projectiles of your ownDesync, and the local playerThe CP trick