Built-in Functions
- Conditions and Actions
- Normal Condition Functions
- Extended Condition Functions
- Normal Action Functions
- CenterView
- CreateUnit
- Defeat/Victory/Draw
- DisplayText
- GiveUnits
- KillUnit
- LeaderBoard
- MinimapPing
- ModifyUnit
- MoveLocation
- MoveUnit
- MuteUnitSpeech/UnMuteUnitSpeech
- Order
- PauseGame/UnpauseGame
- PauseTimer/UnpauseTimer
- PlayWAV
PreserveTrigger- RemoveUnit
- RunAIScript
- SetAllianceStatus
- SetCountdownTimer
- SetDeaths
- SetMemory
- SetDoodadState
- SetInvincibility
- SetMissionObjectives
- SetNextScenario
- SetResources
- SetScore
- SetSwitch
- TalkingPortrait
- Transmission
Wait
- Extended Action Functions
- Extended Functions
- Compile Time
- Compile-time Python Macros
- Compile-time Bytes Conversion
- General Functions
- Trigger Construction Functions
- Runtime Iterators
- Display Text Functions
- Players Functions
- Location Functions
- Memory Operation Functions
- Math Functions
- Bitwise Operation Functions
- QueueGameCommand Functions
- QueueGameCommand
- QueueGameCommand_MinimapPing
- QueueGameCommand_QueuedRightClick
- QueueGameCommand_Select
- QueueGameCommand_PauseGame
- QueueGameCommand_ResumeGame
- QueueGameCommand_RestartGame
- QueueGameCommand_UseCheat
- QueueGameCommand_TrainUnit
- QueueGameCommand_MergeDarkArchon
- QueueGameCommand_MergeArchon
Conditions and Actions
-
Normal Condition Functions
Normal condition functions are functions encapsulated based on the conditions in classical triggers, just like the trigger conditions in ScmDraft2.
Any normal condition function will return a trigger condition expression constant (not a logical value). The concepts ofcondition expressionandcondition expression resultneed to be distinguished clearly.
If you need to use a variable to store the condition expression result, you should pass it into the condition list of a trigger or as an if syntax parameter. You can also use l2v to get the runtime result of the condition expression. See the following example:var vc0 = Accumulate(P1, AtLeast, 500, Ore); // This is wrong!!! It does not return a logical value.
const c1 = Accumulate(P1, AtLeast, 500, Ore); // This is ok, it returns a constant condition expression, which can be used as RawTrigger or Trigger conditions parameter
// Use a variable to store the logical value returned by the condition
var vc1 = 0;
Trigger(
conditions = Accumulate(P1, AtLeast, 500, Ore),
actions = vc1.SetNumber(1),
);
var vc2 = l2v(Accumulate(P1, AtLeast, 500, Ore));
-
Accumulate
Accumulate(player : TrgPlayer, AtLeast/AtMost/Exactly : TrgComparison, value, resourceType : TrgResource) : Condition
Compare whether the [resourceType] collected by [player] is [AtLeast/AtMost/Exactly] [value]
Example
if ( Accumulate(P1, AtLeast, 500, Ore) ) {
// If player 1 accumulate at least 500 ore minerals
}
-
Bring
-
Bring(player : TrgPlayer, AtLeast/AtMost/Exactly : TrgComparison, value, unitType : TrgUnit, location : TrgLocation) : Condition
Compare whether the number of [unitType] of [player] in [location] is [AtLeast/AtMost/Exactly] [value]When the second parameter of Bring is AtMost, it will detect unfinished buildings, incubating creep tumors; it will not detect loaded units or units still in training; it will ignore the height setting of [location].
When the second parameter of Bring is AtLeast/Exactly, it will detect loaded units; it will not detect units still in training, unfinished buildings, or incubating creep tumors.
Bring cannot detect Scanner Sweep units or Map Revealers.
Units killed using KillUnit or KillUnitAt can still be detected by the Bring condition in the current frame; units removed using RemoveUnit or RemoveUnitAt can no longer be detected by the Bring condition in the current frame, and units previously killed using KillUnit or KillUnitAt will also no longer be detected by Bring.
Example
KillUnitAt(All, "Terran Marine", $L("Location 1"), P1); // Kill all Terran Marines of player 1 at Location 1. After this action, Bring can still detect player 1's Terran Marines at Location 1 in the current frame.
RemoveUnitAt(1, "Map Revealer", "Anywhere", P1); // This action does not remove any units, but it refreshes all units previously killed using KillUnit or KillUnitAt in the current frame to ensure Bring no longer detects units killed in the current frame.
if (Bring(P1, AtLeast, 15, "Terran Marine", $L("Location 1"))) {
// If the number of Terran Marines of player 1 at Location 1 is at least 15
} -
-
Command
-
Command(player : TrgPlayer, AtLeast/AtMost/Exactly : TrgComparison, value, unitType : TrgUnit) : Condition
Compare whether the number of [unitType] under the control of [player] on the map is [AtLeast/AtMost/Exactly] [value]When the second parameter of Command is AtMost, it will detect loaded units, units still in training, unfinished buildings, incubating creep tumors.
When the second parameter of Command is AtLeast/Exactly, it will detect loaded units; it will not detect units still in training, unfinished buildings, or incubating creep tumors.
Command can detect Scanner Sweep units and Map Revealers.
Units killed or removed using KillUnit, KillUnitAt, RemoveUnit, RemoveUnitAt can still be detected by the Command condition in the current frame. -
CommandMost(unitType : TrgUnit) : Condition
Compare whether the [unitType] under the control of the current player on the map is more than any other player (including neutral players). -
CommandLeast(unitType : TrgUnit) : Condition
Compare whether the [unitType] under the control of the current player on the map is less than any other player (including neutral players). -
CommandMostAt(unitType : TrgUnit, location : TrgLocation) : Condition
Compare whether the [unitType] under the control of the current player at [location] is more than any other player (including neutral players). -
CommandLeastAt(unitType : TrgUnit, location : TrgLocation) : Condition
Compare whether the [unitType] under the control of the current player at [location] is less than any other player (including neutral players).
Example
const cp = getcurpl();
foreach (p: EUDLoopPlayer()) {
setcurpl(p);
if (Command(CurrentPlayer, AtMost, 0, "(buildings)")) { // When the second parameter of Command is AtMost, the statistics will include unfinished units/buildings
Defeat(); // If the number of buildings of the current player is at most 0, it is judged as defeat
}
if (CommandMost("Terran Marine")) {
println("Player {} has the most Terran Marines", p);
}
if (CommandLeast("Terran Marine")) {
println("Player {} has the least Terran Marines", p);
}
if (CommandMostAt("Terran Marine", $L("Location 1"))) {
println("Player {} has the most Terran Marines at Location 1", p);
}
if (CommandLeastAt("Terran Marine", $L("Location 1"))) {
println("Player {} has the least Terran Marines at Location 1", p);
}
}
setcurpl(cp); -
-
CountdownTimer
CountdownTimer(AtLeast/AtMost/Exactly : TrgComparison, seconds) : Condition
Compare whether the remaining seconds of the countdown timer are [AtLeast/AtMost/Exactly] [seconds] game seconds
This condition should not use Exactly to compare because trigger polling does not occur every game second. One game second is 16 game frames, not equal to one real second.
Example
if ( CountdownTimer(AtMost, 1) ) {
PauseTimer();
}
-
Deaths
-
Deaths(player : TrgPlayer, AtLeast/AtMost/Exactly : TrgComparison, value, unitType : TrgUnit) : Condition
Compare whether the death count of [unitType] of [player] is [AtLeast/AtMost/Exactly] [value]When [player] or [unitType] is out of range
It is an EUD condition that compares whether the 32-bit unsigned integer stored at
0x58A364 + ([player] * 4 + [unitType] * 48)is [AtLeast/AtMost/Exactly] [value].
Its synchronization depends on the synchronization of the data stored at0x58A364 + ([player] * 4 + [unitType] * 48). -
DeathsX(player: TrgPlayer, AtLeast/AtMost/Exactly: TrgComparison, value, unitType: TrgUnit, mask) : ConditionThis condition is usually not used to compare player unit deaths
It is usually used to compare whether the 32-bit (unsigned integer value & [mask]) stored at
0x58A364 + ([player] * 4 + [unitType] * 48)is [AtLeast/AtMost/Exactly] [value].
Its synchronization depends on the synchronization of the data stored at0x58A364 + ([player] * 4 + [unitType] * 48).
Note Units killed or removed using trigger actions are not counted in the death count (Deaths);
Suicidal units (Zerg Scourge, Infested Terran, Vulture Spider Mine) that successfully detonate are not counted in the death count (Deaths), but are counted if killed by other units (without successful detonation);
Units killed by allies are also counted in the death count (Deaths).Example
if ( Deaths(P1, AtLeast, 15, "Terran Marine") ) {
// If player 1 has at least 15 Terran Marines deaths
} -
-
Memory
-
Memory(memoryAddress, AtLeast/AtMost/Exactly : TrgComparison, value) : Condition
Compare whether the 32-bit unsigned integer stored at [memoryAddress] is [AtLeast/AtMost/Exactly] [value].
Its synchronization depends on the synchronization of the data stored at [memoryAddress]. -
MemoryX(memoryAddress, AtLeast/AtMost/Exactly : TrgComparison, value, mask) : Condition
Compare whether the 32-bit (unsigned integer value & [mask]) stored at [memoryAddress] is [AtLeast/AtMost/Exactly] [value]
Its synchronization depends on the synchronization of the data stored at [memoryAddress]. -
MemoryEPD(epd, AtLeast/AtMost/Exactly : TrgComparison, value) : Condition
Compare whether the 32-bit unsigned integer stored at0x58A364 + ([epd] * 4)is [AtLeast/AtMost/Exactly] [value]
Its synchronization depends on the synchronization of the data stored at0x58A364 + ([epd] * 4). -
MemoryXEPD(epd, AtLeast/AtMost/Exactly : TrgComparison, value, mask) : Condition
Compare whether the 32-bit (unsigned integer value & [mask]) stored at0x58A364 + ([epd] * 4)is [AtLeast/AtMost/Exactly] [value]
Its synchronization depends on the synchronization of the data stored at0x58A364 + ([epd] * 4).
Example
function MorphLarvaEPD(epd, newUnit: TrgUnit) {
if (MemoryXEPD(epd + 0x64/4, Exactly, 35, 0xFFFF)) {
SetMemoryXEPD(epd + 0x4D/4, SetTo, 42 << 8, 0xFFFF00);
SetMemoryXEPD(epd + 0x98/4, SetTo, newUnit, 0xFFFF);
}
} -
-
Kills
-
Kills(player : TrgPlayer, AtLeast/AtMost/Exactly : TrgComparison, value, unitType : TrgUnit) : Condition
Compare whether the kills of [unitType] of [player] is [AtLeast/AtMost/Exactly] [value]Kills is not kill score, note the difference
Killing own units is not counted in the Kills
Example
if ( Kills(P1, AtLeast, 15, "Terran Marine") ) {
// If player 1 killed at least 15 Terran Marines
} -
-
ElapsedTime
ElapsedTime(AtLeast/AtMost/Exactly : TrgComparison, game seconds) : Condition
Compare whether the elapsed game time is [AtLeast/AtMost/Exactly] [value] game seconds
This condition should not use Exactly to compare because trigger polling does not occur every game second. One game second is 16 game frames, not equal to one real second.
Example
if ( ElapsedTime(AtLeast, 5) ) {
// The elapsed game time exceeds 5 game seconds
}
-
LeastKills/MostKills
-
LeastKills(unitType : TrgUnit) : Condition
Compare whether thecurrent player's kill count of [unitType] is the least on the map -
MostKills(unitType : TrgUnit) : Condition
Compare whether thecurrent player's kill count of [unitType] is the most on the map
Example
if (LeastKills("Terran Marine")) {
// The current player killed the least Terran Marines
}
if (MostKills("Terran Marine")) {
// The current player killed the most Terran Marines
} -
-
LeastResources/MostResources
-
LeastResources(resourceType : TrgResource) : Condition
Compare whether thecurrent player's [resourceType] is the least on the map -
MostResources(resourceType : TrgResource) : Condition
Compare whether thecurrent player's [resourceType] is the most on the map
Example
if ( LeastResources(Ore) ) {
// The current player has the least ore
}
if ( MostResources(Gas) ) {
// The current player has the most gas
} -
-
Opponents
Opponents(player : TrgPlayer, AtLeast/AtMost/Exactly : TrgComparison, value) : Condition
Compare whether the number of opponents of [player] in the current game is [AtLeast/AtMost/Exactly] [value]
Example
if ( Opponents(P1, AtMost, 2) ) {
// Player 1 has at most 2 opponents
}
-
Score
-
Score(player : TrgPlayer, score type : TrgScore, AtLeast/AtMost/Exactly : TrgComparison, value) : Condition
Compare whether the [score type] score of [player] is [AtLeast/AtMost/Exactly] [value] points -
LowestScore(score type : TrgScore) : Condition
Compare whether the current player's current [score type] is the lowest score -
HighestScore(score type : TrgScore) : Condition
Compare whether the current player's current [score type] is the highest score
Example
if (Score(P1, Kills, AtLeast, 10000)) {
// Player 1's kill score is at least 10000 points. Kill score is not kills, note the difference.
}
if (LowestScore(Buildings)) {
// If the current player's building score is now the lowest
}
if (HighestScore(Kills)) {
// If the current player's kill score is now the highest
} -
-
Switch
Switch(switch : TrgSwitch, state : TrgSwitchState) : Condition
Compare whether the state of [switch] is [state]
Example
if ( Switch($S("Switch 1"), Set) ) {
// Switch 1 is Set
}
if ( Switch($S("Switch 1"), Cleared) ) {
// Switch 1 is Cleared
}
-
Always/Never-
Always() : Condition
Always executes unconditionally, useless in epScript -
Never() : Condition
Never executes, In most cases, this function is useless in epScript.
-
-
-
Extended Condition Functions
-
IsUserCP
IsUserCP(): Condition
Desync condition used to check if the local player is the current player
-
Is64BitWireframe
Is64BitWireframe(): Condition
Desync condition used to check if the local Starcraft client is 64-bit
-
-
Normal Action Functions
Normal action functions are functions encapsulated based on classical triggers in ScmDraft 2.
Any trigger action function (including extended trigger functions) returns an action expression constant. The concepts ofaction expressionandexecuting action expressionneed to be clearly distinguished.
If the non-comment code between two semicolons is only a call to an action function, epScript will pass it to an unconditional trigger DoActions for execution. Refer to the example:const a1 = CenterView($L("Location 1")); // This declares an action expression constant and does not execute it
CenterView($L("Location 1")); // This means executing an action, equivalent to DoActions(CenterView($L("Location 1")));
DoActions(a1); // The a1 declared in the first line is executed at this time
-
CenterView
CenterView(location : TrgLocation) : Action
Allows desync execution and sets thecurrent player's camera to the [location]
Example
setcurpl(P1);
CenterView($L("Location 1"));
-
CreateUnit
-
CreateUnit(number, unitType : TrgUnit, location : TrgLocation, player : TrgPlayer) : Action
Create [number] of [unitType] for [player] at [location]. The moment a unit is created, the supply used by the unit will immediately (in the current frame) increase. -
CreateUnitWithProperties(number, unitType : TrgUnit, Where : location : TrgLocation, player : TrgPlayer, properties : TrgProperty) : Action
Create [number] of [unitType] with [properties] for [player] at [location]. The moment a unit is created, the supply used by the unit will immediately (in the current frame) increase.
Example
CreateUnit(2, "Terran Siege Tank", $L("Location 1"), P1);
CreateUnitWithProperties(1, "Terran Marine", $L("Location 1"), P1, UnitProperty(
hitpoint = 100, // Health percentage
shield = 100, // Shield percentage
energy = 100, // Energy percentage
hanger = 0, //
resource = 0, //
cloaked = False, // Whether invisible
burrowed = False, // Whether burrowed
intransit = False, // Whether being transported
hallucinated = False, // Whether hallucinated
invincible = False) // Whether invincible
); -
-
Defeat/Victory/Draw
-
Defeat(): Action
The current player loses and ends the game -
Victory(): Action
The current player wins and ends the game -
Draw(): Action
All players draw and end the game
-
-
DisplayText
-
DisplayText(text : TrgString) : Action
Allows desync execution and displays [text] on the next line of the text area on the current player's screenThe argument [text] of this action is actually the number of this text entry in the map string table. If this entry does not exist in the map string table, epScript will first insert [text] into the map string table and then use its ID as its argument.
Example
const idx = $T("Hello StarCraft!");
dbstr_print(GetMapStringAddr(idx), "WTF StarCraft!");
DisplayText("Hello StarCraft!"); // Outputs WTF StarCraft! -
-
GiveUnits
-
GiveUnits(number : TrgCount, unitType : TrgUnit, owner : TrgPlayer, area : TrgLocation, recipient : TrgPlayer) : Action
Give up to [number] [unitType] units of [owner] player in [area] to [recipient] player. [number] = 0 represents all units.This action will cause the rally points of the given units to be lost.
Example
// Give up to 3 Marines of Player 2 in Location 1 to Player 1
GiveUnits(3, "Terran Marine", P2, $L("Location 1"), P1); -
-
KillUnit
-
KillUnit(unitType : TrgUnit, player : TrgPlayer) : Action
Kill all [unitType] units of [player], including units still in the build queue and nuclear missiles not yet launched in nuclear silos. -
KillUnitAt(number : TrgCount, unitType : TrgUnit, specified area : TrgLocation, player : TrgPlayer) : Action
Kill up to [number] [unitType] units of [player] in [specified area]. [number] = 0 represents all units. Does not include units still in the build queue or nuclear missiles not yet launched in nuclear silos.KillUnitAt(All, "Scanner Sweep", "Anywhere", P1) cannot kill Scanner Sweeps.
KillUnitAt(All, "Map Revealer", "Anywhere", P1) cannot kill Map Revealers.Warning
This action has a bug:
If this action kills any unit inside a transporter (Dropship/Bunker, etc.), then all units of the same type inside that transporter (Dropship/Bunker, etc.) will be killed, and these killed units will not be counted within the [number] parameter specified.
For example, if executing KillUnitAt(1, "Terran Marine", "Location 1", P1) kills a marine inside a bunker in Location 1, then all marines in that bunker will be killed, and if there are more marines outside the bunker in that area, one more will be killed.
Example
KillUnit("Terran Marine", P1); // Kill all Marines of Player 1
KillUnitAt(3, "Terran Siege Tank", $L("Location 1"), P1) // Kill up to 3 Tanks of Player 1 in Location 1 -
-
LeaderBoard
-
LeaderBoardComputerPlayers(state : TrgPropState) : Action
Set the enabled state of the LeaderBoard for computer players. -
LeaderBoardControl(unitType : TrgUnit, label : TrgString) : Action
Display a LeaderBoard in descending order of all players' [unitType] control counts described as [label]. -
LeaderBoardControlAt(unitType : TrgUnit, area : TrgLocation, label : TrgString) : Action
Display a LeaderBoard in descending order of all players' [unitType] control counts in [area] described as [label]. -
LeaderBoardGoalControl(goal, unitType : TrgUnit, label : TrgString) : Action
Display a LeaderBoard in descending order of all players' [unitType] control counts closest to [goal] described as [label]. -
LeaderBoardGoalControlAt(goal, unitType : TrgUnit, area : TrgLocation, label : TrgString) : Action
Display a LeaderBoard in descending order of all players' [unitType] control counts in [area] closest to [goal] described as [label]. -
LeaderBoardGoalKills(goal, unitType : TrgUnit, label : TrgString) : Action
Display a LeaderBoard in descending order of all players' kills of [unitType] closest to [goal] described as [label]. -
LeaderBoardGoalResources(goal, resourceType : TrgResource, label : TrgString) : Action
Display a LeaderBoard in descending order of all players' collections of [resourceType] closest to [goal] described as [label]. -
LeaderBoardGoalScore(goal, scoreType : TrgScore, label : TrgString) : Action
Display a LeaderBoard in descending order of all players' [scoreType] scores closest to [goal] described as [label]. -
LeaderBoardGreed(goal) : Action
Display a LeaderBoard in descending order of all players' collections of crystal and gas mines closest to [goal]. -
LeaderBoardKills(unitType : TrgUnit, label : TrgString) : Action
Display a LeaderBoard in descending order of all players' kills of [unitType] described as [label]. -
LeaderBoardResources(resourceType : TrgResource, label : TrgString) : Action
Display a LeaderBoard in descending order of all players' collections of [resourceType] described as [label]. -
LeaderBoardScore(scoreType : TrgScore, label : TrgString) : Action
Display a LeaderBoard in descending order of all players' [scoreType] scores described as [label].
Example
LeaderBoardGoalControlAt(10, "Terran Marine", $L("Destination"), "Marines reaching destination"); -
-
MinimapPing
MinimapPing(location : TrgLocation) : Action
Allow desync execution. Display a Ping on the minimap at [specified location] for the current player.
Example
// Display Ping at Location 1 on Minimap for Player 1
setcurpl(P1);
MinimapPing($("Location 1"));
-
ModifyUnit
-
ModifyUnitEnergy(number : TrgCount, unitType : TrgUnit, player : TrgPlayer, area : TrgLocation, percentage) : Action
Change the energy of up to [number] [unitType] units of [player] in [area] to [percentage] percent. [number] = 0 represents all (All) units. -
ModifyUnitHangarCount(added, number : TrgCount, unitType : TrgUnit, player : TrgPlayer, area : TrgLocation) : Action
Add up to [added] loaded units to up to [number] [unitType] units of [player] in [area]. [number] = 0 represents all (All) units.For example, Interceptors in Carriers, Scarabs in Reavers. Note that this action cannot add Spider Mines to Vultures.
-
ModifyUnitHitPoints(number : TrgCount, unitType : TrgUnit, player : TrgPlayer, area : TrgLocation, percentage) : Action
Change the hit points of up to [number] [unitType] units of [player] in [area] to [percentage] percent. [number] = 0 represents all (All) units. -
ModifyUnitResourceAmount(number : TrgCount, player : TrgPlayer, area : TrgLocation, new value) : Action
Change the resource value of up to [number] units of [player] in [area] to [new value]. [number] = 0 represents all (All) units. -
ModifyUnitShields(number : TrgCount, unitType : TrgUnit, player : TrgPlayer, area : TrgLocation, percentage) : Action
Change the shields of up to [number] [unitType] units of [player] in [area] to [percentage] percent. [number] = 0 represents all (All) units.
Example
// Change the hit points of up to 100 Marines of Player 1 in Location 1 to 100%
ModifyUnitHitPoints(100, "Terran Marine", P1, $L("Location 1"), 100); -
-
MoveLocation
MoveLocation(location : TrgLocation, unitType : TrgUnit, player : TrgPlayer, area : TrgLocation) : Action
Move the center of [location] onto one of the [unitType] units of [player] in [area].
Example
// Move the center of Location 1 onto one of Player 1's Marines anywhere on the map
MoveLocation($L("Location 1"), "Terran Marine", P1, $L("AnyWhere"));
-
MoveUnit
MoveUnit(number : TrgCount, unitType : TrgUnit, player : TrgPlayer, startArea : TrgLocation, targetLocation : TrgLocation) : Action
Instantly move up to [number] [unitType] units of [player] in [startArea] to [targetLocation]. [number] = 0 represents all (All) units.
Example
// Instantly move up to 10 Marines of Player 1 in Location 1 to Location 2
MoveUnit(10, "Terran Marine", P1, $L("Location 1"), $L("Location 2"));
-
MuteUnitSpeech/UnMuteUnitSpeech
-
MuteUnitSpeech(): Action
Allow desynchronized execution. Mute all speeches of the current player's units (except trigger units' speeches). -
UnMuteUnitSpeech(): Action
Allow desynchronized execution. Unmute all speeches of the current player's units (except trigger units' speeches).
-
-
Order
Order(unitType : TrgUnit, player : TrgPlayer, startArea : TrgLocation, order : TrgOrder, targetLocation : TrgLocation) : Action
Issue an [order] for [player]'s [unitType] units in [startArea] towards the center of [targetLocation].
Example
// Order all Marines of Player 1 in Location 1 to attack-move to the center of Location 2
Order("Terran Marine", P1, $L("Location 1"), Attack, $L("Location 2"))
-
PauseGame/UnpauseGame
-
PauseGame(): Action
Pause the game for all players. -
UnpauseGame(): Action
Unpause the game for all players.
-
-
PauseTimer/UnpauseTimer
-
PauseTimer(): Action
Pause the countdown timer for all players. -
UnpauseTimer(): Action
Unpause the countdown timer for all players.
-
-
PlayWAV
PlayWAV(WAVName : TrgString) : Action
Allow desynchronized execution. Play a WAV file named [WAVName] for the current player.
-
PreserveTriggerPreserveTrigger() : Action
Preserve the trigger. Because classical triggers become disabled after executing once, this action is needed to repeatedly trigger. Useless in epScript.
-
RemoveUnit
-
RemoveUnit(unitType : TrgUnit, player : TrgPlayer) : Action
Remove all [unitType] units of [player] from the map, including units still in the production queue. Can remove nuclear missiles that have not been launched in Nuclear Silos. The supply used by the removed units will decrease in the next frame. -
RemoveUnitAt(number : TrgCount, unitType : TrgUnit, area : TrgLocation, player : TrgPlayer) : Action
Remove up to [number] [unitType] units of [player] in [area] from the map, [number] = 0 represents all (All) units. Does not include units still in the production queue. Will not remove nuclear missiles that have not been launched in Nuclear Silos. The supply used by the removed units will decrease in the next frame.RemoveUnitAt(All, "Scanner Sweep", "Anywhere", P1) cannot remove Scanner Sweeps.
RemoveUnitAt(All, "Map Revealer", "Anywhere", P1) cannot remove Map Revealers.Warning
This action has a bug:
If this action removes any unit inside a transporter (Dropship/Bunker, etc.), then all units of the same type inside that transporter (Dropship/Bunker, etc.) will be removed, and these removed units will not be counted within the [number] parameter specified.
For example, if executing RemoveUnitAt(1, "Terran Marine", "Location 1", P1) removes a marine inside a bunker in Location 1, then all marines in that bunker will be removed, and if there are more marines outside the bunker in that area, one more will be removed.
-
-
RunAIScript
-
RunAIScript(Script : TrgAIScript) : Action
Run AI script [Script] for the current player. -
RunAIScriptAt(Script : TrgAIScript, area : TrgLocation) : Action
Run AI script [Script] for the current player in [area].Example
RunAIScriptAt("Terran Custom Level", $L("Location 1"));
-
-
SetAllianceStatus
-
SetAllianceStatus(targetPlayer : TrgPlayer, status : TrgAllyStatus) : Action
Set the alliance status of the current player towards [targetPlayer] to [status].Example
// Set Player 1 allied towards Player 2, Player 2 enemy towards Player 1
setcurpl(P1);
SetAllianceStatus(P2, Ally);
setcurpl(P2);
SetAllianceStatus(P1, Enemy);
-
-
SetCountdownTimer
-
SetCountdownTimer(SetTo/Add/Subtract : TrgModifier, number) : Action
Set countdown timer to [SetTo/Add/Subtract] [number] game seconds. 1 game second = 16 frames.Example
SetCountdownTimer(SetTo, 100); // Set countdown timer to 100 game seconds
SetCountdownTimer(Add, 5); // Add 5 game seconds to countdown timer
SetCountdownTimer(Subtract, 3); // Subtract 3 game seconds from countdown timer
-
-
SetDeaths
-
SetDeaths(player : TrgPlayer, SetTo/Add/Subtract : TrgModifier, value, unitType : TrgUnit) : Action
Set the number of deaths of [player]'s [unitType] units to [SetTo/Add/Subtract] [value].When [player] or [unitType] is out of range
It will be an EUD action to set the current value stored at memory address
0x58A364 + ([player] * 4 + [unitType] * 48)to [SetTo/Add/Subtract] [value].
Whether desynchronized execution is allowed depends on the synchronicity of the data stored at memory address0x58A364 + ([player] * 4 + [unitType] * 48). -
SetDeathsX(player : TrgPlayer, SetTo/Add/Subtract: TrgModifier, value, unitType: TrgUnit, mask) : ActionThis function is not usually used to set player unit death counts.
SetTo : Set the current value stored at memory address `0x58A364 + ([player] * 4 + [unitType] * 48)` to `current value - (current value & mask) + (value & mask)`
Add : Set the current value stored at memory address `0x58A364 + ([player] * 4 + [unitType] * 48)` to `current value - (current value & mask) + ( ((current value & mask) + (value & mask)) & mask )`
Subtract: Set the current value stored at memory address `0x58A364 + ([player] * 4 + [unitType] * 48)` to `current value - (current value & mask) + ( ((current value & mask) - (value & mask)) & mask )` (the subtraction in the formula can subtract to a minimum of 0)Whether desynchronized execution is allowed depends on the synchronicity of the data stored at memory address
0x58A364 + ([player] * 4 + [unitType] * 48)Example
SetDeaths(P1, Add, 10, "Terran Marine"); // Add 10 to the number of deaths of Player 1's Marines
-
-
SetMemory
-
SetMemory(memoryAddress, SetTo/Add/Subtract : TrgModifier, value) : Action
Set the 32-bit positive integer value stored at [memoryAddress] to [SetTo/Add/Subtract] [value].
Whether desynchronized execution is allowed depends on the synchronicity of the data stored at [memoryAddress]. -
SetMemoryX(memoryAddress, SetTo/Add/Subtract : TrgModifier, value, mask) : ActionSetMemory that supports mask access, can modify any one or more bits of 32 bits.
SetTo : Set the current value stored at [memoryAddress] to `current value - (current value & mask) + (value & mask)`
Add : Set the current value stored at [memoryAddress] to `current value - (current value & mask) + ( ((current value & mask) + (value & mask)) & mask )`
Subtract: Set the current value stored at [memoryAddress] to `current value - (current value & mask) + ( ((current value & mask) - (value & mask)) & mask )` (the subtraction in the formula can subtract to a minimum of 0)Whether desynchronized execution is allowed depends on the synchronicity of the data stored at [memoryAddress].
-
SetMemoryEPD(epd : TrgPlayer, SetTo/Add/Subtract : TrgModifier, value) : Action
Set the 32-bit positive integer value stored at memory address0x58A364 + ([epd] * 4)to [SetTo/Add/Subtract] [value].
Whether desynchronized execution is allowed depends on the synchronicity of the data stored at memory address0x58A364 + ([epd] * 4). -
SetMemoryXEPD(epd : TrgPlayer, SetTo/Add/Subtract : TrgModifier, value, mask) : ActionSetMemoryEPD that supports mask access, can modify any one or more bits of 32 bits.
SetTo : Set the current value stored at memory address `0x58A364 + ([epd] * 4)` to `current value - (current value & mask) + (value & mask)`
Add : Set the current value stored at memory address `0x58A364 + ([epd] * 4)` to `current value - (current value & mask) + ( ((current value & mask) + (value & mask)) & mask )`
Subtract: Set the current value stored at memory address `0x58A364 + ([epd] * 4)` to `current value - (current value & mask) + ( ((current value & mask) - (value & mask)) & mask )` (the subtraction in the formula can subtract to a minimum of 0)Whether desynchronized execution is allowed depends on the synchronicity of the data stored at memory address
0x58A364 + ([epd] * 4).
Example
function MorphLarvaEPD(epd, newUnit: TrgUnit) {
if (MemoryXEPD(epd + 0x64/4, Exactly, 35, 0xFFFF)) {
SetMemoryXEPD(epd + 0x4D/4, SetTo, 42 << 8, 0xFFFF00);
SetMemoryXEPD(epd + 0x98/4, SetTo, newUnit, 0xFFFF);
}
} -
-
SetDoodadState
SetDoodadState(state : TrgPropState, unitType : TrgUnit, player : TrgPlayer, area : TrgLocation) : Action
Set the Doodad state of [player]'s [unitType] units in [area] to [state].
Example
SetDoodadState(Enable, "Terran Marine", P1, $L("Location 1"));
-
SetInvincibility
SetInvincibility(state : TrgPropState, unitType : TrgUnit, player : TrgPlayer, area : TrgLocation) : Action
Set the invincibility state of [player]'s [unitType] units in [area] to [state].
Example
SetInvincibility(Enable, "Terran Marine", P1, $L("Location 1")); // Set the invincibility state of Player 1's Marines in Location 1 to Enable
SetInvincibility(Disable, "Terran Marine", P1, $L("Location 1")); // Set the invincibility state of Player 1's Marines in Location 1 to Disable
-
SetMissionObjectives
-
SetMissionObjectives(text : TrgString) : Action
Allows desynchronized execution. Set the current player's mission objectives description to [text].The argument [text] of this action is actually the ID of this text entry in the Map String Table. If this entry does not exist in the Map String Table, epScript will first insert this [text] into the Map String Table and then use its ID as the argument.
Example
SetMissionObjectives("Our objectives are:\nNo cavities!"); -
-
SetNextScenario-
SetNextScenario(text : TrgString) : Action
Set the name of the next map to load after the current game ends to [text]. Must be in the same directory.Note
SetNextScenariois singleplayer-only and currently does not work on EUD maps (useless at the moment).
-
-
SetResources
SetResources(player : TrgPlayer, SetTo/Add/Subtract : TrgModifier, value, resourceType : TrgResource) : Action
Set [player]'s [resourceType] resources to [SetTo/Add/Subtract] [value].
Example
SetResources(P1, Add, 1000, Ore); // Give Player 1 1000 Ore
SetResources(P1, Substract, 1000, Gas); // Take 1000 Gas from Player 1
SetResources(P1, SetTo, 5000, OreAndGas); // Set Player 1's Ore and Gas resources to 5000
-
SetScore
SetScore(player : TrgPlayer, SetTo/Add/Subtract : TrgModifier, value, scoreType : TrgScore) : Action
Set [player]'s [scoreType] score to [SetTo/Add/Subtract] [value].
Example
SetScore(P1, Add, 1000, Kills); // Give Player 1 1000 Kills score
-
SetSwitch
SetSwitch(switchName : TrgSwitch, switchAction : TrgSwitchAction) : Action
Set the state of switch [switchName] to [switchAction].
Example
SetSwitch($S("Switch 1"), Set); // Set Switch 1 state to Set
SetSwitch($S("Switch 1"), Clear); // Set Switch 1 state to Cleared
SetSwitch($S("Switch 1"), Toggle); // Toggle Switch 1 state, if it was originally Set it will be switched to Cleared, if it was originally Cleared it will be switched to Set
SetSwitch($S("Switch 1"), Random); // Set Switch 1 to a random state, after using it Switch 1's state may be Set or may be Cleared
-
TalkingPortrait
TalkingPortrait(unitType : TrgUnit, milliseconds) : Action
Allows desynchronized execution. Display the portrait of [unitType] at the current player's unit portrait for [milliseconds] game milliseconds.
Example
// Have the Marine give instructions to Player 1
setcurpl(P1);
TalkingPortrait("Terran Marine", 5000);
-
Transmission
-
Transmission(unitType : TrgUnit, area : TrgLocation, WAVName : TrgString, SetTo/Add/Subtract : TrgModifier, time, text : TrgString) : Action
Allows desynchronized execution. Play a sound [WAVName] for the current player and display the portrait of [unitType] units in [area] at the player's unit portrait for [SetTo/Add/Subtract] [time] game milliseconds, while pinging the unit on the minimap and outputting the text information [text].Note This function will affect trigger control flow, it is not recommended to use in epScript.
Example
Transmission("Terran Marine", $L("Location 3"), "sound\\Zerg\\Advisor\\ZAdUpd00.WAV", Add, 5000, "Our objectives are:\nNo cavities!"); -
-
Wait-
Wait(milliseconds) : ActionNote This function will affect trigger control flow, it is not recommended to use in epScript.
-
-
-
Extended Action Functions
Extended action functions are functions that cannot be found in classical triggers but can still be regarded as trigger actions. They will return action constant expressions or expression lists. They can be added to RawTrigger or DoActions action lists, and may no longer be a single trigger action.
-
SetKills
SetKills(player : TrgPlayer, SetTo/Add/Subtract : TrgModifier, value, unitType : TrgUnit) : Action | [Action]
Set [player]'s kills against [unitType] to [SetTo/Add/Subtract] [value].
Kills are not kill scores, note the difference.
Composed of one or three classical trigger actions, depending on whether the player number is CurrentPlayer.
Example
// https://armoha.github.io/eud-book/offsets/KilledUnitCountsTable.html
// In fact, there is no SetKills action in classical triggers, it is simulated by EUD.
// If the player number is not CurrentPlayer (13), its internal implementation is probably like this, returning a constant expression
SetDeaths(player number - 2736, SetTo/Add/Subtract, value, unitType);
// If the player number is CurrentPlayer (13), its internal implementation is probably like this, returning a tuple containing three constant expressions
DoActions(
SetDeaths(EPD(0x6509B0), Add, -2736, 0),
SetDeaths(CurrentPlayer, SetTo/Add/Subtract, value, unitType),
SetDeaths(EPD(0x6509B0), Add, 2736, 0),
);
-
SetCurrentPlayer
SetCurrentPlayer(playerID : TrgPlayer) : [Action]
Allows desynchronized execution. SetCurrentPlayerand cpcache to [playerID].
Composed of three classical trigger actions.
Example
RawTrigger(actions = list(
SetCurrentPlayer(P1),
DisplayText("Content displayed to Player 1"),
SetCurrentPlayer(P2),
DisplayText("Content displayed to Player 2"),
SetCurrentPlayer(P3),
DisplayText("Content displayed to Player 3"),
));
-
AddCurrentPlayer
AddCurrentPlayer(playerid : TrgPlayer) : [Action]
Allows desynchronized execution. SetCurrentPlayerand cpcache to [playerID].
Composed of three classical trigger actions.
Example
RawTrigger(actions = list(
SetCurrentPlayer(P3),
DisplayText("Content displayed to Player 3"),
AddCurrentPlayer(-1),
DisplayText("Content displayed to Player 2"),
AddCurrentPlayer(-1),
DisplayText("Content displayed to Player 1"),
));
// https://armoha.github.io/eud-book/offsets/GameSpeedRefreshRate.html
// Set all game speeds from Slowest to Fastest to 200%
RawTrigger(actions = list(
SetCurrentPlayer(EPD(0x5124D8)),
SetDeaths(CurrentPlayer, SetTo, 21, 0),
AddCurrentPlayer(1),
SetDeaths(CurrentPlayer, SetTo, 21, 0),
AddCurrentPlayer(1),
SetDeaths(CurrentPlayer, SetTo, 21, 0),
AddCurrentPlayer(1),
SetDeaths(CurrentPlayer, SetTo, 21, 0),
AddCurrentPlayer(1),
SetDeaths(CurrentPlayer, SetTo, 21, 0),
AddCurrentPlayer(1),
SetDeaths(CurrentPlayer, SetTo, 21, 0),
AddCurrentPlayer(1),
SetDeaths(CurrentPlayer, SetTo, 21, 0),
));
-
DisplayTextAll
DisplayTextAll(text : TrgString) : [Action]
Display [text] on the next line of the text area for all players (including observers).
Composed of two classical trigger actions.
-
PlayWAVAll
PlayWAVAll(WAVName) : [Action]
Play the sound [WAVName] for all players (including observers).
Composed of two classical trigger actions.
-
MinimapPingAll
MinimapPingAll(location) : [Action]
Issue a ping at [location] on the minimap for all players (including observers).
Composed of two classical trigger actions.
-
CenterViewAll
CenterViewAll(location) : [Action]
Center the camera on [location] for all players (including observers).
Composed of two classical trigger actions.
-
SetMissionObjectivesAll
SetMissionObjectivesAll(text : TrgString) : [Action]
Set the mission objectives text to [text] for all players (including observers).
Composed of two classical trigger actions.
-
TalkingPortraitAll
TalkingPortraitAll(unitType, milliseconds) : [Action]
Display the portrait of [unitType] at all players' (including observers) unit portraits for [milliseconds] game milliseconds.
Composed of two classical trigger actions.
-
SetNextPtr
SetNextPtr(trg, dest) : Action
Set the next trigger pointer of trigger [trg] to [dest].
It is essentially a SetDeaths actionSetDeaths(EPD(trg + 4), SetTo, dest, 0)
Example
// The .getDestAddr() method of a variable can obtain the destination address in the variable trigger at compile time.
// The .getValueAddr() method of a variable can obtain the value address in the variable trigger at compile time.
// The .GetVTable() method of a variable can obtain the virtual trigger address of the variable at compile time.
// The .SetModifier(method) method of a variable sets the numeric modification method of the variable trigger to method.
// The SetNextPtr(trg, ptr) function is used to set the next trigger of trg to ptr.
function afterTriggerExec() {
var a, b = 3, 5;
const next = Forward();
RawTrigger(
actions = list(
SetMemory(b.getValueAddr(), Add, 1),
SetMemory(a.getValueAddr(), Add, 1),
SetMemory(b.getDestAddr(), SetTo, EPD(a.getValueAddr())),
b.SetModifier(Add), // Internally it is probably implemented as SetMemoryX(b.getValueAddr() + 4, SetTo, (Add << 24), 0xFF000000)
SetNextPtr(b.GetVTable(), next), // Set the next trigger of b to next, the internal implementation may be like this: SetMemory(b.GetVTable() + 4, SetTo, next)
),
nextptr = b.GetVTable(), // The next trigger of this trigger is b
);
next.__lshift__(NextTrigger()); // The essence of this is to point next, the Forward, to the next Trigger
// The result is a:10 b:6
}
-
Extended Functions
-
Compile Time
-
Get Index
-
$L(areaName : literal) : py_int -
GetLocationIndex(areaName : py_str) : py_int -
EncodeLocation(areaName : py_str) : py_int
Gets the [areaName] defined in the map editor (usually SCMD) converted to the corresponding area ID. All functions with TrgLocation type parameters will automatically use this macro. -
$T(text : literal) : py_int -
GetStringIndex(text : py_str) : py_int -
EncodeString(text : py_str) : py_int
Gets the ID of an [text] entry in the map string table (Map String Table). All functions with TrgString type parameters will automatically use this macro, that is, functions that accept TrgString type parameters actually accept the ID of the string entry in the map string table.This macro can arbitrarily provide [text] keys. If the map string table already contains the [text] entry, the ID of the entry in the map string table is returned. If the map string does not have a [text] entry, a new ID→text key-value pair is inserted into the map string table and the ID is returned.
For example, $T("Force 1") will return 4 because it already exists. And $T("\x03Pool farmer") may return 3 (and at the same time create a new item 3: "\x03Pool farmer" in the map string dictionary).
-
$S(switchName : literal) : py_int -
GetSwitchIndex(switchName : py_str) : py_int -
EncodeSwitch(switchName : py_str) : py_int
Gets the [switchName] defined in the map editor (usually SCMD) converted to the corresponding switch ID. All functions with TrgSwitch type parameters will automatically use this macro. -
$U(unitType : literal) : py_int -
GetUnitIndex(unitType : py_str) : py_int -
EncodeUnit(unitType : py_str) : py_int
Gets the [unitType] in the map unit.dat converted to the corresponding unitTypeID. All functions with TrgUnit type parameters will automatically use this macro. -
$B(TBLKey : literal) : py_int -
EncodeTBL(TBLKey : py_str) : py_int
Gets the index ID corresponding to [TBLKey] in the map TBL dictionary. All functions with StatText type parameters will automatically use this macro. -
EncodeWeapon(weaponName : py_str) : py_int
Gets the [weaponName] in the map weapon.dat converted to the corresponding weapon name ID. All functions with Weapon type parameters will automatically use this macro. -
EncodeTech(techName : py_str) : py_int
Gets the [techName] in the map tech.dat converted to the corresponding technology name ID. All functions with Tech type parameters will automatically use this macro.
All $ syntax macros ($L, $T, $S, $U, $B) only support literal strings as parameters.
Example
const l1 = $L("Location 1");
const s2 = $S("Switch 2");
const ut = $U("Terran Marine"); // Returns 0
const aiid = $B("AI Harass Here"); // Returns 1538
// Change the string ID of the SCV unit name. $T("\x03Pool farmer") will insert a new string into the map during compilation and return the ID of this string here.
// https://armoha.github.io/eud-book/offsets/Units.dat-MapString.html
wwrite(0x660260 + 2 * $U("Terran SCV"), $T("\x03Pool farmer"));
// You can directly use $ syntax constants
// EncodePlayer
if (EncodePlayer(P1) == $P1) { py_print($P1, $P2, $CurrentPlayer, $AllPlayers, $Force1, $NonAlliedVictoryPlayers); }
// EncodeModifier
if (EncodeModifier(SetTo) == $SetTo) { py_print($SetTo, $Add, $Subtract); }
// EncodeComparison
if (EncodeComparison(AtLeast) == $AtLeast) { py_print($Exactly, $AtLeast, $AtMost); }
// EncodeResource
if (EncodeResource(OreAndGas) == $OreAndGas) { py_print($Ore, $Gas, $OreAndGas); }
// EncodeSwitchAction
if (EncodeSwitchAction(Set) == $Set) { py_print($Set, $Clear, $Toggle, $Random); } // $Set == EncodeSwitchAction(Set)
// EncodeSwitchState
if (EncodeSwitchState(Set) != $Set) { py_print($Cleared); } // Note this!!! $Set != EncodeSwitchState(Set)
// EncodeAllyStatus
if (EncodeAllyStatus(Ally) == $Ally) { py_print($Enemy, $Ally, $AlliedVictory); }
// EncodeOrder
if (EncodeOrder(Move) == $Move) { py_print($Move, $Patrol, $Attack); }
// EncodePropState
if (EncodePropState(Enable) == $Enable) { py_print($Enable, $Disable, $Toggle); }
// EncodeScore
if (EncodeScore(Total) == $Total) { py_print($Total, $Units, $Buildings, $UnitsAndBuildings, $Razings, $KillsAndRazings, $Custom); } // There is no $Kills, EncodeScore(Kills) == 4
// EncodeCount
if (EncodeCount(All) == 0) { py_print(EncodeCount(All)); } // EncodeCount(All) is 0, EncodeCount any positive integer is equal to that positive integer itself
// Some less commonly used ones, I didn't write the documentation and examples, the usage is consistent, refer to the constants reference
// EncodeAIScript
// EncodeFlingy
// EncodeIcon
// EncodeImage
// EncodeIscript
// EncodePortrait
// EncodeProperty
// EncodeSprite
// EncodeUnitOrder
// EncodeUpgrade -
-
list
list(*args) : py_list
Creates and returns a flat compile-time Python list. It requires at least one argument. This function will automatically flatten lists and cannot create multi-dimensional lists.
If you want to create an empty compile-time list, use the py_list function.
Compile-time lists can be iterated at compile time using foreach syntax, and their indices can only be constants.
Example
var a, b, c, d;
const list1 = list(a, b, c, d); // list is a compile-time container, it just references a/b/c/d here, not the values of a/b/c/d
const list2 = list(15, 4, list(99, 47)); // The list will be flattened, no multi-dimensional list will be created, this is equivalent to list(15, 4, 99, 47)
foreach(i, v : py_enumerate(list2)) {
list1[i] = v;
}
println("{}, {}, {}, {}", a, b, c, d); // 15, 4, 99, 47
-
EUDCreateVariables
EUDCreateVariables(count) : py_list[EUDVariable]
Creates [count] variables at compile time and returns a compile-time list containing references to the created variables.
Compile-time lists can be iterated at compile time using foreach syntax, and their indices can only be constants.
Example
const vs = EUDCreateVariables(3);
vs[0] = 1;
vs[1] = 2;
vs[2] = 3;
// vs[0], vs[1], and vs[2] are three variables. vs does not exist at runtime, so the index of vs must be a compile-time constant.
-
SetVariables
SetVariables(varList : py_list, number : py_list, opList : py_list)
Uses at least one trigger to set all variables in [varList] to [number] values according to the corresponding operators in [opList]. This macro is used to optimize.
Even if the target value is a variable, it will not take effect dynamically before the action is completed. It will only keep the target value as the state when it started executing.
Example
var a, b, c = 10, 10, 10;
SetVariables(
list( a, b, c ),
list( 3, 2, 4 ),
list(SetTo, Add, Subtract),
);
// The above code is equivalent to
const op1 = list(a, SetTo, 3),
list(b, Add, 2),
list(c, Subtract, 4);
SeqCompute(op1);
-
SCMD2Text
SCMD2Text(text) : py_str
Compile-time converts the hexadecimal numeric values <XX> in the text [text] to the corresponding ASCII characters.
Example
// The following two lines are equivalent
simpleprint(SCMD2Text("<03>Haha<02>")); // Print yellow Haha
simpleprint("\x03Haha\x02"); // Print yellow Haha
-
unProxy
unProxy(x) : duck
Compile-time gets the pointer value of the reference type x.
Example
const a = EUDArray(list(9, 8, 7));
var b = unProxy(a);
const c = EUDArray.cast(b + 4); // c is actually a reference to a[1]
c[0] = 888888;
println("b:{} a:{} c:{} a[1]:{} c[0]:{}", b, a, c, a[1], c[1]); // b:421156492 a:421156492 c:421156496 a[1]:888888 c[1]:7
-
UnitProperty
UnitProperty(...) : CUWP
Compile-time inserts aCreate Unit with Propertiesinto the map and returns it. You can use GetPropertyIndex to get its number. See the example for field explanations.
Example
// All fields are optional
const prop = UnitProperty(
hitpoint = 100, // HP percentage 0~100
shield = 100, // Shield percentage 0~100
energy = 100, // Energy percentage 0~100
hanger = 0, // 0~4294967295
resource = 0, // 0~65536 (Count)
cloaked = False, // Is invisible True/False
burrowed = False, // Is burrowed True/False
intransit = False, // Is being transported True/False
hallucinated = False, // Is a hallucination True/False
invincible = False // Is invincible True/False
);
CreateUnitWithProperties(1, "Terran Marine", $L("Location 3"), P1, prop);
-
GetPropertyIndex
GetPropertyIndex(property : CUWP) : py_int
Compile-time gets the number of a CUWP [property] in the map CUWP list.
Example
// All fields are optional
const prop = UnitProperty(
hitpoint = 100, // HP percentage 0~100
);
py_print(GetPropertyIndex(prop));
-
GetPlayerInfo
GetPlayerInfo(player: TrgPlayer) : py_struct
Compile-time gets the information of player [player] in the map information.[player] only supports constants. The information obtained is the information set in the map, not the runtime information.
Example
const pinfo = GetPlayerInfo(0);
setcurpl(0);
printAt(9, "Player 1 type:{}({}) race:{}({}) force:{}", pinfo.typestr, pinfo.type, pinfo.racestr, pinfo.race, pinfo.force);
-
EUDRegisterObjectToNamespace
EUDRegisterObjectToNamespace(funcname, obj) : duck
Registers an object to the global namespace, mainly used for parameter passing between modules.
Example
const menuSel = PVariable();
EUDRegisterObjectToNamespace("menuSel", menuSel);
-
GetEUDNamespace
GetEUDNamespace(): py_dict[str, duck]
Gets the global namespace dictionary, which records the objects registered in EUDRegisterObjectToNamespace.
Example
function afterTriggerExec() {
setcurpl(P1);
const menuSel2 = GetEUDNamespace().get("menuSel");
println(9, "{}", menuSel2[0]);
}
-
MPQAddFile
MPQAddFile(fname, contents, isWave = false)
Adds a file named [fname] with byte content [contents] to the output map set by output. If [isWave] is set to true, it will be compressed using Wave lossy compression before importing.
Example
MPQAddFile("1.txt", py_open("C:/1.txt", "rb").read());
-
MPQAddWave
MPQAddWave(fname, content)
It is equivalent to MPQAddFile(fname, contents, true).
Example
MPQAddWave("1.wav", py_open("C:/1.wav", "rb").read());
-
-
Compile-time Python Macros
In epScript, you can call all built-in functions of Python 3 with the py_ prefix. Here are some common ones.
-
py_print
-
py_print(*args)Compile-time uses Python's print function to print output content to the compile log interface for debugging output.
Example
py_print("This will only output to the CLI during compilation and has nothing to do with the map.");
-
-
py_list
py_list(iter) : py_list
Creates and returns a compile-time Python list.
Compile-time lists can be iterated at compile time using foreach syntax, and their indices can only be constants.
Example
const lst = py_list();
lst.append(DisplayText("11111"));
lst.append(DisplayText("22222"));
lst.append(DisplayText("33333"));
DoActions(lst);
-
py_open
py_open(filename, mode) : py_file
Compile-time opens the file [filename] in [mode] mode and returns a Python file object.
Example
function onPluginStart() {
MPQAddWave("1.wav", py_open("C:/1.wav", "rb").read()); // Import an external file into the map
}
-
py_eval
py_eval(str) : duck
Simple Python code execution at compile time, returning the result.
Example
import py_datetime;
function is_map_expired() {
static var expired = false;
once {
const expire_date = py_str('2024-01-01 00:00:00');
const expire_date_stamp = py_eval("int(datetime.datetime.strptime(expire_date, '%Y-%m-%d %H:%M:%S').timestamp())");
if (Memory(0x6D0F38, AtLeast, expire_date_stamp)) {
expired = true;
}
}
return expired;
}
function onPluginStart() {
if (is_map_expired()) {
DisplayTextAll("This map has expired.");
} else {
DisplayTextAll("Have fun.");
}
}
-
py_str
py_str(val) : py_str
Compile string wrapping conversion at compile time.
Example
const actions = py_list();
foreach(i : py_range(0, 3)) {
actions.append(CreateUnit(1, "Terran Marine", py_str("Location ") + py_str(i + 1), P1)); // Add an action to the list
}
DoActions(actions); // Execute all actions in the list at once
-
py_len
py_len(gconstant) : py_int
Gets the length of global constants at the compile-time Python level.
Example
const lst = py_list();
lst.append(DisplayText("11111"));
lst.append(DisplayText("22222"));
lst.append(DisplayText("33333"));
foreach(i : py_range(0, py_len(lst))) {
DoActions(lst[i]);
}
-
py_enumerate
py_enumerate(vlist) : py_iter
Compile-time enumeration iterator to enumerate and expand items in compile-time containers.
Example
var a, b, c, d;
const list1 = list(a, b, c, d); // list is a compile-time container. Here it just puts the references of a/b/c/d together instead of the values of a/b/c/d.
const list2 = list(15, 4, 99, 47);
foreach(i, v : py_enumerate(list2)) {
list1[i] = v;
}
println("{}, {}, {}, {}", a, b, c, d); // 15, 4, 99, 47
-
py_range
py_range(start, end, step) : py_iter
Compile-time counting iterator to iterate from [start] to [end] in steps of [step] and expand the code block. Includes [start] but excludes [end].
Example
// https://armoha.github.io/eud-book/offsets/MouseCoordinateX.html
// https://armoha.github.io/eud-book/offsets/MouseCoordinateY.html
// The principle of reading memory values is to use 32 triggers to compare the value of each bit in 32 bits. If the i-th bit is greater than 0, the variable is appended with 2 to the power of i-1.
function GetMouseXY() {
var x, y;
RawTrigger(actions = list(
SetDeaths(EPD(x.getValueAddr()), SetTo, 0, 0),
SetDeaths(EPD(y.getValueAddr()), SetTo, 0, 0),
));
foreach(i : py_range(32)) { /* Use 64 triggers here to read mouse X Y values */
RawTrigger(
conditions = DeathsX(EPD(0x6CDDC4), AtLeast, 1, 0, py_pow(2,i)),
actions = SetDeaths(EPD(x.getValueAddr()), Add, py_pow(2,i), 0),
);
RawTrigger(
conditions = DeathsX(EPD(0x6CDDC8), AtLeast, 1, 0, py_pow(2,i)),
actions = SetDeaths(EPD(y.getValueAddr()), Add, py_pow(2,i), 0),
);
}
return x, y;
}
// The above GetMouseXY function is actually equivalent to the following
function GetMouseXY() {
return dwread(0x6CDDC4), dwread(0x6CDDC8);
}
-
-
Compile-time Bytes Conversion
-
b2i
b2i1(content, index) : py_intb2i1(content, index) : py_intb2i4(content, index) : py_int
Converts the byte, word, or dword at position [index] in the literal byte string [content] to a positive integer constant using little endian.
Example
printAt(2, "0x{:x},0x{:x},0x{:x},0x{:x}", b2i1(b"fuck"), b2i1(b"fuck",1), b2i1(b"fuck",2), b2i1(b"fuck",3)); // 0x66, 0x75, 0x63, 0x6B
printAt(3, "0x{:x},0x{:x},0x{:x}", b2i2(b"fuck"), b2i2(b"fuck",1), b2i2(b"fuck",2)); // 0x7566, 0x6375, 0x6B63
printAt(4, "0x{:x}", b2i4(b"fuck")); // 0x6B637566
-
i2b
i2b1(i) : py_bytei2b2(i) : [py_byte]i2b4(i) : [py_byte]
Converts the integer constant [i] to one, two or four byte constants using little endian.
Example
printAt(4, "{}", i2b4(0x6B637566));
-
u2b/b2u
u2b(s) : [py_byte]b2u(b) : py_str
Converts between byte literal and string literal.
Example
printAt(5, "{}", u2b("fuck")); // b'fuck'
printAt(6, "{}", b2u(b"fuck")); // fuck
-
UTF8 Encode/Decode
-
b2utf8(str) : [py_byte]
Decodes [str] using UTF-8. -
u2utf8(str) : py_str
Encodes [str] using UTF-8.
Example
printAt(5, "{}", b2utf8("fuck")); // b'fuck'
printAt(6, "{}", u2utf8(b"fuck")); // fuck -
-
-
General Functions
-
EPD
EPD(ptr) : py_int | EUDVariable
Converts the specified pointer [ptr] to an EPD offset. In memory, the player number occupies 4 bytes (32-bit integer). It actually subtracts [ptr] from 0x58A364 and then divides by 4.
If the argument is a constant, the result can be returned at compile time.
Example
// https://armoha.github.io/eud-book/offsets/GameSpeedRefreshRate.html
const epd = EPD(0x5124D8); // (0x5124D8-0x58A364)/4 = -0x1DFA3 = -122787
-
l2v
l2v(conditionalExpression) : EUDVariable
Uses a trigger at runtime to get the logical value false or true of [conditionalExpression].
Example
var isP1MarineDeaths100 = l2v(Deaths(P1, AtLeast, 100, "Terran Marine"));
-
parse
parse(address, radix=10) : py_list[EUDVariable, EUDVariable]
Parses a string at memory [address] into a number using [radix] notation.
Returns: number, digits
Returns 0, 0 on parse failure
Example
const numstr = Db("102a\r\r\r\r\r\r\r\r\r\r\r\0");
var num, digits;
num, digits = parse(numstr, 8);
println("0x{:x}, {}, 8 radix digits:{}", num, num, digits); // 0x00000042, 66, 8 radix digits:3
num, digits = parse(numstr, 10);
println("0x{:x}, {}, 10 radix digits:{}", num, num, digits); // 0x00000066, 102, 10 radix digits:3
num, digits = parse(numstr, 16);
println("0x{:x}, {}, 16 radix digits:{}", num, num, digits); // 0x0000102A, 4138, 16 radix digits:4
-
EUDFuncPtr
-
EUDFuncPtr(argn, retn) : py_int
Declares a pointer to a closure function with [argn] arguments and [retn] return values. -
EUDTypedFuncPtr(argtypes, rettypes) : py_int
Declares a pointer to a closure function with an argument type list of [argtypes] and a return value type list of [rettypes].
Example
function GetMouseMapXY() {
const screenX, screenY = dwread_epd(EPD(0x62848C)), dwread_epd(EPD(0x6284A8));
const mouseX, mouseY = dwread_epd(EPD(0x6CDDC4)), dwread_epd(EPD(0x6CDDC8));
const x, y = screenX + mouseX, screenY + mouseY;
return x, y;
}
var funcptr = 0;
function beforeTriggerExec() {
static var x, y = 0, 0;
once (funcptr == 0) {
funcptr = EUDFuncPtr(0, 2)(function() {
x, y = GetMouseMapXY();
return x, y;
});
}
setcurpl(P1);
printAt(9, "before x = {}, y = {}", x, y);
}
function afterTriggerExec() {
const x, y = EUDFuncPtr(0, 2).cast(funcptr)();
setcurpl(P1);
printAt(10, "after funcptr returns {}, {}", x, y);
} -
-
getgametick
getgametick(): EUDVariable
Gets the number of game frames elapsed. At theFastestgame speed, it is 42 milliseconds per frame.
Example
var tick = getgametick();
-
-
Trigger Construction Functions
Trigger construction functions can be used to construct triggers with custom properties.
-
RawTrigger
RawTrigger(conditions = list(...), actions = list(...), preserved = true/false) : RawTrigger
Inserts a static classical trigger and cannot pass variables. Returns a trigger pointer.
The conditions field passes a list of constant conditional expressions with a maximum of 16 classical trigger conditions.
The actions field passes a list of constant action expressions with a maximum of 64 classical trigger actions.
The preserved field defaults to true, indicating that it will execute each time it is called. If set to false, it will execute once after the condition is met and will never execute again.
Example
// https://armoha.github.io/eud-book/offsets/MouseCoordinateX.html
// https://armoha.github.io/eud-book/offsets/MouseCoordinateY.html
// The principle of reading memory values is to use 32 triggers to compare the value of each bit in 32 bits. If the i-th bit is greater than 0, the variable is appended with 2 to the power of i-1.
function GetMouseXY() {
var x, y;
RawTrigger(actions = list(
SetDeaths(EPD(x.getValueAddr()), SetTo, 0, 0),
SetDeaths(EPD(y.getValueAddr()), SetTo, 0, 0),
));
foreach(i : py_range(32)) { /* Use 64 triggers here to read mouse X Y values */
RawTrigger(
conditions = DeathsX(EPD(0x6CDDC4), AtLeast, 1, 0, py_pow(2,i)),
actions = SetDeaths(EPD(x.getValueAddr()), Add, py_pow(2,i), 0),
);
RawTrigger(
conditions = DeathsX(EPD(0x6CDDC8), AtLeast, 1, 0, py_pow(2,i)),
actions = SetDeaths(EPD(y.getValueAddr()), Add, py_pow(2,i), 0),
);
}
return x, y;
}
// The above GetMouseXY function is actually equivalent to the following
function GetMouseXY() {
return dwread(0x6CDDC4), dwread(0x6CDDC8);
}
-
Trigger
Trigger(conditions = list(...), actions = list(...), preserved = true/false)
Inserts an extended trigger, which may be split into many classical triggers. It is not limited to 16 conditions and 64 actions, and variables can be passed in, but no return value is returned.
Passing variables will not take effect dynamically before the actions are completed, and will only maintain the state of the variables when the trigger starts executing.
For clarity of code, it is generally recommended not to use Trigger and instead use if conditions to complete dynamic conditional comparisons.
The conditions field passes a list of conditional expressions.
The actions field passes a list of action expressions.
The preserved field defaults to true, indicating that it will execute each time it is called. If set to false, it will execute once after the condition is met and will never execute again.
Example
Trigger(
conditions = list(
Bring(P1, AtMost, 0, "Zerg Cerebrate", "Location 1")
),
actions = list(
KillUnitAt(All, "Terran Medic", "Location 1", P1)
),
preserved = false,
);
-
PTrigger
PTrigger(players, conditions = list(...), actions = list(...))
Inserts a trigger that matches the current player. When thecurrent playeris any of the players in [players], it will execute. There is no preserved field, and the other fields are used in the same way as Trigger.
Example
setcurpl(P8);
PTrigger(list(P3, P8),
conditions = ElapsedTime(AtLeast, 3),
actions = KillUnit($U("Terran Medic"), P1),
);
-
DoActions
DoActions(actions, preserved = true/false)
A Trigger function that executes actions unconditionally.
In epScript, any non-comment code between two semicolons is automatically wrapped in this function as a trigger.
actions is a list of action expressions.
The preserved field defaults to true, indicating that it will execute each time it is called. If set to false, it will execute once after the condition is met and will never execute again.
Example
Order("Zerg Hydralisk", P8, $L("UpArea"), Patrol, "Player1Home"); // If a line of code is only a trigger action function call, it will be wrapped in a DoActions after compilation.
DoActions(Order("Zerg Hydralisk", P8, $L("UpArea"), Patrol, "Player1Home"));
DoActions(list(// To be more explicit, you can add list
Order("Zerg Hydralisk", P8, $L("UpArea"), Patrol, "Player1Home"),
));
Trigger(actions = list(
Order("Zerg Hydralisk", P8, $L("UpArea"), Patrol, "Player1Home"),
));
// The above four usages are completely equivalent
const a = Order("Zerg Hydralisk", P8, $L("UpArea"), Patrol, "Player1Home"); // This line of code is not equivalent to the above usages. It is used to declare an action expression constant named a, which will not be automatically wrapped in DoActions.
DoActions(
Order("Zerg Guardian", P8, $L("UpArea"), Patrol, "Player1Home"),
Order("Zerg Guardian", P8, $L("MiddleArea"), Patrol, "Player1Home"),
Order("Zerg Devourer", P8, $L("UpArea"), Patrol, "Player1Home"),
Order("Zerg Devourer", P8, $L("MiddleArea"), Patrol, "Player1Home"),
preserved = false, // The preserved parameter must be a named parameter
);
// Static Feature Demo
// The variables passed to the actions of DoActions will be replaced with a static constant value when DoActions starts executing. No matter how many times the variable is modified during the execution of DoActions, the passed in value is determined before execution.
var c = 0;
c.AddNumber(1);
DoActions(
c.AddNumber(100),
CreateUnit(c, "Terran SCV", "Location 2", P1),
);
printAt(10, "You would expect to create {} SCVs, but only 1 was actually created", c); // You would expect to create 100 SCVs here, but only 1 was actually created
-
VProc
-
VProc(vars, actions) : RawTrigger | [RawTrigger]
The action list [actions] can only pass constant action expression lists. VProc will execute all the virtual triggers of the variables in [vars] in order after executing all the actions in [actions] in order.
This means that the virtual triggers of some variables can first be modified in [actions], and then the modified virtual triggers of these variables will be executed by VProc after the actions are completed.
It is usually used to optimize the overhead of serial assignment or bitwise operations on variables. Its overhead is slightly higher than RawTrigger but lower than DoActions or Trigger.
A virtual trigger of a variable can only have one SetDeathsX action. If multiple actions are queued to the variable queue, the last one is taken.
Example
var unrelatedVariable = 0;
var c, d = 0, 0;
c = 1;
RawTrigger(actions = list(
c.AddNumber(100),
c.QueueAssignTo(d),
));
println("After RawTrigger process c:{} d:{}", c, d); // c:101 d:0
c = 1;
VProc(c, list(
c.AddNumber(100),
c.QueueAssignTo(d),
));
println("After VProc(c) process c:{} d:{}", c, d); // c:101 d:101
c = 1;
VProc(list(c, d), list(
c.AddNumber(100),
c.QueueAssignTo(d),
d.QueueAddTo(c),
));
println("After VProc(c,d) process c:{} d:{}", c, d); // c:202 d:101
c = 1;
VProc(list(d, c), list(
c.AddNumber(100),
c.QueueAssignTo(d),
d.QueueAddTo(c),
));
println("After VProc(d,c) process c:{} d:{}", c, d); // c:202 d:202 -
-
-
Runtime Iterators
Runtime iterators can be used with the compile-time loop syntax foreach to construct a runtime loop. The number of times it executes is controlled by the internal flow control logic of the iterator.
break and continue can be used in the foreach code block belonging to the runtime iterator, and they will be compiled into EUDContinue() and EUDBreak().
Let's explain the principle of runtime iterators in an equivalent code way. For example, there is the following code:foreach (cu : EUDLoopNewCUnit()) {
py_print(cu);
println("{}", cu);
continue;
}It is roughly equivalent to:
{
const it = EUDLoopNewCUnit();
const cu = py_next(it); // The first compile-time iteration gets the storage location of the iteration result and sets the start of the EUD runtime loop code block, equivalent to an EUDWhile()(the runtime it has a next item)
py_print(cu); // Compile-time output, will only execute once
println("{}", cu);
EUDContinue();
py_next(it, 0); // The second compile-time iteration sets the end position of the EUD runtime loop code block, equivalent to an EUDEndWhile()
}
-
EUDLoopPlayer
EUDLoopPlayer(ptype, force, race) : EUDIterator
Iterates over active players of type [ptype], force [force] and race [race]. Internally uses playerexist to detect.
Active players do not include vacant or leaving players.
Example
// ptype is an optional parameter, can be "Human" or "Computer"
// force is an optional parameter, can be Force1 Force2 Force3 Force4
// race is an optional parameter, can be "Zerg" "Terran" "Protoss"
foreach (p: EUDLoopPlayer("Human", Force1, "Zerg")) {
setcurpl(p);
println("You are Zerg");
}
-
EUDLoopRange
EUDLoopRange(start, end=None) : EUDIterator
Iterates over values from [start] to [end] - 1.
Example
// Print 1 to 4
foreach (i : EUDLoopRange(1, 5)) {
simpleprint(i);
}
// The above code is roughly equivalent to
for (var i = 1; i < 5; i++) {
simpleprint(i);
}
-
EUDLoopUnit
EUDLoopUnit(): EUDIterator
Iterates over the ptr and epd of all units on the main chain. Does not include subunits, Scanner Sweep, Map Revealer, etc.
Example
foreach (ptr, epd : EUDLoopUnit()) {
const u = CUnit(epd);
if (u.unitID == $U("Terran Marine")) {
u.hp = 0x100 * 10;
}
}
EUDLoopUnit2(): EUDIterator
Iterates over the ptr and epd of all units.
Does not include subunits, Scanner Sweep, Map Revealer, etc.
Example
// The Unit Node Table is a doubly linked list with a main chain and branch chains.
// FirstUnitPointer -> Unit1 <-> Unit2 <-> "Terran Siege Tank" <-> Unit4 -> Null
// |
// "Tank Turret"
// The main chain and branch chains both occupy memory space. For example, in the above example, Bring will determine that there are a total of 4 units, but in fact 5 of the 1700 unit spaces are occupied.
// EUDLoopUnit() will only loop the units on the main chain, so it will ignore "Tank Turret" - the tank turret.
// EUDLoopUnit2() will loop all units occupying the Unit Node Table space, because it does not loop in the order of the linked list, but in the order of memory.
// EUDLoopUnit(): Loop along the main chain unit, unable to loop to sub unit and map revealer, etc.
// EUDLoopUnit2(): Loop along the Memory index to loop all units.
foreach (ptr, epd : EUDLoopUnit2()) {
const u = CUnit(epd);
if (u.unitID == $U("Terran Marine")) {
u.hp = 0x100 * 10;
}
}
EUDLoopCUnit(): EUDIterator
It uses EUDLoopUnit2 to traverse and wraps the traversed pointers into CUnit objects.
Does not include subunits, Scanner Sweep, Map Revealer, etc.
Example
foreach (u : EUDLoopCUnit()) {
if (u.unitID == $U("Terran Marine")) {
u.hp = 0x100 * 10;
}
}
-
EUDLoopNewUnit(allowance = 2) : EUDIterator
Iterates over up to [allowance] ptr and epd of new units that have appeared since the last timecurrent framecalled EUDLoopNewUnit or EUDLoopNewCUnit.
Does not include subunits, Scanner Sweep, Map Revealer, etc. -
EUDLoopNewCUnit(allowance = 2) : EUDIterator
Iterates over up to [allowance] new units that have appeared since the last timecurrent framecalled EUDLoopNewUnit or EUDLoopNewCUnit and wraps the traversed pointers into CUnit objects.
Does not include subunits, Scanner Sweep, Map Revealer, etc.
Warning
Calling EUDLoopNewUnit or EUDLoopNewCUnit multiple times in the same frame will traverse the same units.
Zerg peculiarity: New units are only larvae, cancelled Zerg Extractor drones, the second unit of twin units (zergling, scourges, Nydus canal), and any units created out of thin air using the CreateUnit function.Note
The hatching process of Zerg eggs will use the address of the larva. The hatched unit will continue to use this address. If it is hatching a dog, one of the dogs will continue to use the larva's address and the other will be a new unit. Scourges are similar.
Buildings hatched by Zerg drones will use the drone's address. Cancelling the hatch will turn back into a drone with the same address and will not produce a new unit.
For an instant when a drone hatches into a Zerg Extractor, it will inherit the address of the Vespene Geyser unit (the Vespene Geyser itself is a unit). The drone is considered dead. If the construction is cancelled, a new drone is returned. This drone can be traversed.
Units queued in the barracks: they are only detected when they walk out after completion.
Buildings: Can be detected as soon as construction starts (unfinished construction).
Archons and Dark Archons: After Templars merge, the Archon will use the address of one of the Templars. The other Templar is considered dead and will not produce a new unit. Dark Archons are similar.Example
foreach (ptr, epd : EUDLoopNewUnit(1700)) {
const u = CUnit(epd);
if (u.unitID == $U("Terran Marine")) {
u.hp = 0x100 * 10;
}
}
foreach (u : EUDLoopNewCUnit(1700)) {
if (u.unitID == $U("Terran Marine")) {
u.hp = 0x100 * 10;
}
}
// The following code is a complete traversal of new units, the code comes from: GGRush
const NewUnits = UnitGroup(1000);
const ChangeableUnits = EUDDeque(1000)();
function onPluginStart() {
GetGlobalStringBuffer();
}
function beforeTriggerExec() {
foreach(cunit: EUDLoopNewCUnit()) {
NewUnits.add(cunit);
}
ChangeableUnits.append(-1);
var uid, value;
while(True) {
value = ChangeableUnits.popleft();
if(value == -1) break;
else if(value < 228) uid = value;
else if(value >= EPD(0x59CCA8)) {
const epd = value;
if(!MemoryXEPD(epd + 0x64/4, Exactly, prev, 0xFFFF)) NewUnits.add(value);
else {
ChangeableUnits.append(uid);
ChangeableUnits.append(epd);
}
}
}
foreach(unit: NewUnits.cploop) {
foreach(dead: unit.dying) {} // Existence check: living units continue to execute code, dead units continue
unit.move_cp(0x64/4);
if(DeathsX(CurrentPlayer, Exactly, $U("Zerg Larva"), 0, 0xFFFF)
|| DeathsX(CurrentPlayer, Exactly, $U("Zerg Egg"), 0, 0xFFFF)
|| DeathsX(CurrentPlayer, Exactly, $U("Zerg Drone"), 0, 0xFFFF)
|| DeathsX(CurrentPlayer, Exactly, $U("Zerg Hydralisk"), 0, 0xFFFF)
|| DeathsX(CurrentPlayer, Exactly, $U("Zerg Lurker Egg"), 0, 0xFFFF)
|| DeathsX(CurrentPlayer, Exactly, $U("Zerg Mutalisk"), 0, 0xFFFF)
|| DeathsX(CurrentPlayer, Exactly, $U("Mutalisk Cocoon"), 0, 0xFFFF)
|| DeathsX(CurrentPlayer, Exactly, $U("Zerg Hatchery"), 0, 0xFFFF)
|| DeathsX(CurrentPlayer, Exactly, $U("Zerg Lair"), 0, 0xFFFF)
|| DeathsX(CurrentPlayer, Exactly, $U("Zerg Creep Colony"), 0, 0xFFFF)
|| DeathsX(CurrentPlayer, Exactly, $U("Zerg Spire"), 0, 0xFFFF)
|| DeathsX(CurrentPlayer, Exactly, $U("Protoss High Templar"), 0, 0xFFFF)
|| DeathsX(CurrentPlayer, Exactly, $U("Protoss Dark Templar (Unit)"), 0, 0xFFFF)
) {
const uid = wread_cp(0, 0);
ChangeableUnits.append(uid);
ChangeableUnits.append(unit.epd);
}
// start
// Your codes
// end
unit.remove(); //This code is necessary!!!Don't skip it
}
}
-
EUDLoopPlayerUnit(player: TrgPlayer) : EUDIterator
Iterates over all units of player [player] ptr and epd. -
EUDLoopPlayerCUnit(player: TrgPlayer) : EUDIterator
Iterates over all units of player [player] and wraps the traversed pointers into CUnit objects.
Example
foreach (ptr, epd : EUDLoopPlayerUnit(P1)) {
const u = CUnit(epd);
if (u.unitID == $U("Terran Marine")) {
u.hp = 0x100 * 10;
}
}
foreach (u : EUDLoopPlayerCUnit(P1)) {
if (u.unitID == $U("Terran Marine")) {
u.hp = 0x100 * 10;
}
}
// Change all Marines of Owner player to NewOwner player
// Using cunit.give will affect the iteration of EUDLoopPlayerCUnit, so you need to first add all cunits to a queue container
// and then change the owner of each cunit from the container
const givequeue = EUDQueue(100);
foreach(cunit: EUDLoopPlayerCUnit(Owner)) {
if(cunit.unitType != $U("Terran Marine")) continue;
givequeue.append(cunit);
}
while (!givequeue.empty()) {
const cunit = CUnit(givequeue.pop());
cunit.cgive(NewOwner);
}
-
-
Display Text Functions
-
DisplayTextAt
-
DisplayTextAt(line, text : TrgString)
Displays [text] on line [line] of theLocal Player == Current Playerscreen
It is different from DisplayText and does not return a trigger action expression -
DisplayTextAllAt(line, text : TrgString)
Displays [text] on line [line] for all players (including observers) It is different from DisplayTextAll and does not return a trigger action expression
Example
var text_10 = $T("_10");
var text_09 = $T("_09");
var line = 10;
DisplayTextAllAt(line, text_10);
line -= 1;
DisplayTextAllAt(line, text_09);
line -= 1;
setcurpl(P1);
DisplayTextAt(line, "Only displayed to P1"); -
-
print
-
simpleprint(*args, spaced=true)
Prints multiple arguments [*args] in order on the next line of theLocal Player == Current Playerscreen scroll information. The named argument spaced indicates whether to separate each printed argument with spaces, the default is true. -
println(format_string : py_str, *args)
Prints multiple arguments [*args] formatted according to [format_string] on the next line of theLocal Player == Current Playerscreen scroll information. -
printAt(line, format_string : py_str, *args)
Prints multiple arguments [*args] formatted according to [format_string] on line [line] from top to bottom (range 0~10) of theLocal Player == Current Playerscreen scroll information. -
printAll(format_string : py_str, *args)
Prints multiple arguments [*args] formatted according to [format_string] on the next line of all player screen scroll information. -
printAllAt(line, format_string : py_str, *args)
Prints multiple arguments [*args] formatted according to [format_string] on line [line] from top to bottom (range 0~10) of all player screen scroll information.
Formatting placeholders
{}: Generic placeholder used to output the value or constant pointer of a variable{{}}: Outputs{}itself{:c}: Outputs the value at the position as the player ID in the corresponding player color code, like PColor(the value at the position){:n}: Outputs the value at the position as the player ID in the corresponding player name, like PName(the value at the position){:s}: Outputs the value at the position as a string pointer to the string it points to, like ptr2s(the value at the position){:t}: Outputs the value at the position as an EPD string pointer to the string it points to, like epd2s(the value at the position){:x}: Outputs the numeric value at the position as an 8-digit hexadecimal number left-padded with 0's, like hptr(the numeric value at the position)
Example
// simpleprint(*args, spaced=true)
simpleprint("Hello", "Starcraft"); // Prints "Hello Starcraft" on the next line of the current player's screen scroll information.
simpleprint("Hello", "Starcraft", spaced = false); // Prints "HelloStarcraft" on the next line of the current player's screen scroll information.
// println(format_string, *args)
println("{} {}", "Hello", "Starcraft"); // Prints "Hello Starcraft" on the next line of the current player's screen scroll information.
// printAt(line, format_string, *args)
printAt( 0, "{} {}", "Hello", "Starcraft"); // Prints "Hello Starcraft" on the top line of the current player's screen scroll information.
printAt(10, "{} {}", "Hello", "Starcraft"); // Prints "Hello Starcraft" on the bottom line of the current player's screen scroll information.
// printAll(format_string, *args)
printAll("{} {}", "Hello", "Starcraft"); // Prints "Hello Starcraft" on the next line of all players' screen scroll information.
// printAllAt(line, format_string, *args)
printAllAt( 0, "{} {}", "Hello", "Starcraft"); // Prints "Hello Starcraft" on the top line of all players' screen scroll information.
printAllAt(10, "{} {}", "Hello", "Starcraft"); // Prints "Hello Starcraft" on the bottom line of all players' screen scroll information. -
-
GetGlobalStringBuffer
GetGlobalStringBuffer(): StringBuffer
Gets the StringBuffer used internally by the print series functions ofLocal Player == Current Player. Its capacity is 1023 bytes.
Example
// The following two lines of code are equivalent
printAt( 0, "{} {}", "Hello", "Starcraft");
GetGlobalStringBuffer().printfAt(0, "{} {}", "Hello", "Starcraft");
-
eprint
-
eprintln(*args)
Prints multiple arguments [*args] in order to the error message below the center of thecurrent player's screen. Printing more than 218 bytes of content (including color code string endings, etc.) will cause an error. -
eprintf(format_string, *args)
Prints multiple arguments [*args] formatted according to the literal string [format_string] to the error message below the center of thecurrent player's screen. Printing more than 218 bytes of content (including color code string endings, etc.) will cause an error. -
eprintAll(format_string, *args)
Prints multiple arguments [*args] formatted according to the literal string [format_string] to the error message below the center of all players' screens. Printing more than 218 bytes of content (including color code string endings, etc.) will cause an error. -
eprintln2(*args)
Prints multiple arguments [*args] in order to the error message below the center of thecurrent player's screen.
Replaces stat_txt.tbl[871]: "Unit's waypoint list is full." This error message, then coordinates with QueueGameCommand_QueuedRightClick(xy) can output more than 218 bytes of content in the error message.
Formatting placeholders
{}: Generic placeholder used to output the value or constant pointer of a variable{{}}: Outputs{}itself{:c}: Outputs the value at the position as the player ID in the corresponding player color code, like PColor(the value at the position){:n}: Outputs the value at the position as the player ID in the corresponding player name, like PName(the value at the position){:s}: Outputs the value at the position as a string pointer to the string it points to, like ptr2s(the value at the position){:t}: Outputs the value at the position as an EPD string pointer to the string it points to, like epd2s(the value at the position){:x}: Outputs the numeric value at the position as an 8-digit hexadecimal number left-padded with 0's, like hptr(the numeric value at the position)
Example
eprintln("Hello", "Starcraft"); // Prints "HelloStarcraft" to the error message below the center of the current player's screen.
eprintf("{}-{}", "Hello", "Starcraft"); // Prints "Hello-Starcraft" to the error message below the center of the current player's screen.
eprintAll("{}-{}", "Hello", "Starcraft"); // Prints "Hello-Starcraft" to the error message below the center of all players' screens. -
-
TextFX
-
TextFX_FadeIn(*args, color=None, wait=1, reset=True, tag=None, encoding="UTF-8")
Fade in text effect -
TextFX_FadeOut(*args, color=None, wait=1, reset=True, tag=None, encoding="UTF-8")
Fade out text effect -
TextFX_Remove(tag)
Removes the text effect with the local tag [tag] -
TextFX_SetTimer(tag, SetTo/Add/Subtract : TrgModifier, value)
Sets the timer of the text effect with the local tag [tag] to [SetTo/Add/Subtract] [value]
-
-
-
Players Functions
-
getuserplayerid
getuserplayerid(): EUDVariable
Gets the local player ID. The local player is not thecurrent player. The local player ID obtained on each player's computer is different. It returnsdesync-data
Example
setcurpl(getuserplayerid());
println("The ID of the current player: {}", getuserplayerid());
-
playerexist
playerexist(player) : EUDVariable
Checks if player [player] still exists in the game. Computer players are also players.
Example
if (playerexist(P1)) {
// Player 1 exists
}
-
Current Player
-
getcurpl(): EUDVariable
Gets the value of cpcache. If cpcache has no value or cpcache's value is different from thecurrent player, the value of thecurrent playeris cached in cpcache and returned. -
setcurpl(cp)
Sets the value of thecurrent playerto [cp] and caches it in cpcache. -
addcurpl(n)
Increments the value of thecurrent playerby [n] and caches it in cpcache. -
setcurpl2cpcache()
Restores the value of thecurrent playerto the cached value in cpcache.
The
current playercan be thought of as a global variable. Specifying the player ID as CurrentPlayer(13) in trigger conditions or actions that require a specific player ID will use it. Some trigger actions internally use it. Thecurrent playermay not even refer to a player and may store any value.Actions that only take effect on the machine where current player == local player (allow desync use, can be used separately on some player machines)
- DisplayText
- CenterView
- PlayWAV
- MinimapPing
- TalkingPortrait
- Transmission
- SetMissionObjectives
Actions that use current player as a parameter (must be synchronized on all player machines, otherwise disconnected)
- SetAllianceStatus
- RunAIScript
- RunAIScriptAt
- Draw
- Defeat
- Victory
Example
const cp = getcurpl();
setcurpl(P1);
println("Hello Player 1");
setcurpl(cp);
// CurrentPlayer is the constant number 13, which can cause some player-related conditions or actions to access the value of the current player
// CurrentPlayer != getcurpl()
// https://armoha.github.io/eud-book/offsets/GameSpeedRefreshRate.html
setcurpl(-122787); // PlayerID offset for game speed level 1
addcurpl(6); // Game speed level 7
SetDeaths(CurrentPlayer, SetTo, 21, 0); // Game speed x2
// https://armoha.github.io/eud-book/offsets/TriggerCurrentPlayerakaCPTrick.html
// https://armoha.github.io/eud-book/offsets/GameBrightness.html
SetMemory(0x6509B0, SetTo, 210382); // Change the current player to 210382 (game brightness level 0~31)
SetDeaths(CurrentPlayer, SetTo, 15, 0); // Set brightness to 15
setcurpl2cpcache(); // Restore the current player to cpcache to prevent interference with getcurpl and other functions -
-
PColor
PColor(player: TrgPlayer) : Db*
Returns player [player]'s color code in the game. Using the formatting placeholder{:c}in formatted text is equivalent.
-
PName
PName(player: TrgPlayer) : Db*
Returns player [player]'s name in the game. Using the formatting placeholder{:n}in formatted text is equivalent.
Example
println("Player 1: {}{}", PColor(P1), PName(P1)); // If Player 1 is named Soze and the color is red, this output will print the red Soze
println("Player 1: {:c}{:n}", P1, P1); // Equivalent to the above
-
SetPName
-
SetPName(player : TrgPlayer, *args)
Sets [player]'s name to the text composed of multiple arguments [*args]. -
SetPNamef(player: TrgPlayer, format_string, *args)
Sets [player]'s name to the text formatted by multiple arguments [*args] using [format_string].
Both functions do not affect the name obtained by the PName function. They only affect the name displayed in player chat, and only valid for the current frame. They need to be re-run every frame.
Example
// The following two usages are equivalent
SetPName(cp, epd2s(title), " \x07level: \x04", level, " ", PColor(cp), PName(cp));
SetPNamef(cp, "{:t} \x07level: \x04{} {:c}{:n}", title, level, cp, cp); -
-
EUDPlayerLoop
EUDPlayerLoop()()EUDEndPlayerLoop()
These two are a pair. It will sequentially set thecurrent playerto each active player (including computer players). After completion, the value of the current player will be the value before the Loop started.
Example
// Give all players 1000 ore minerals, including computer players
EUDPlayerLoop()();
SetResources(CurrentPlayer, Add, 1000, Ore);
EUDEndPlayerLoop();
-
-
Location Functions
-
setloc
-
setloc(loc : TrgLocation, x, y)
Sets the upper left and lower right coordinates of location [loc] to [x], [y], [x], [y] respectively (that is, set the location to a point). -
setloc(loc : TrgLocation, left, top, right, bottom)
Sets the upper left and lower right coordinates of location [loc] to [left], [top], [right], [bottom] respectively.
Example
setloc($L("Location 1"), 1234, 2345);
setloc($L("Location 1"), 1234, 1234, 2345, 2345); -
-
addloc
-
addloc(loc : TrgLocation, x, y)
Sets the left and right coordinates of location [loc] to add [x] and the up and down coordinates to add [y] (the actual size remains unchanged, the center moves to another position). -
addloc(loc : TrgLocation, left, top, right, bottom)
Sets the upper left, upper right, lower left and lower right of location [loc] to add [left], [top], [right], [bottom] respectively.
Example
addloc($L("Location 1"), 123, 234);
addloc($L("Location 1"), 123, 234, 345, 456);
// Used with lengthdir
addloc($L("Location 1"), lengthdir_256(888, 73)); // Move Location 1 area 888 coordinates in the 73 degree (256 degree system) direction
addloc($L("Location 1"), lengthdir(888, 102)); // Move Location 1 area 888 coordinates in the 102 degree direction -
-
dilateloc
-
dilateloc(loc : TrgLocation, x, y)
Sets the upper left, upper right, lower left and lower right of location [loc] to add -[x], -[y], [x], [y] respectively (the center remains unchanged, the area expands). -
dilateloc(loc : TrgLocation, left, top, right, bottom)
Sets the upper left, upper right, lower left and lower right of location [loc] to add -[left], -[top], [right], [bottom] respectively.
Example
dilateloc($L("Location 1"), 5, 5);
dilateloc($L("Location 1"), 1, 2, 3, 4); -
-
getlocTL
getlocTL(loc : TrgLocation) : py_tuple[EUDVariable, EUDVariable]
Gets the upper left coordinate of a location.
Example
const left, top = getlocTL($L("Location 1"));
-
setloc_epd
setloc_epd(loc : TrgLocation, epd)
Sets the coordinates of location [loc] to the value stored at local memory address0x58A364 + [epd] * 4.
Example
// It is same as the following function
function setloc_epd(loc : TrgLocation, epd) {
const x, y = posread_epd(epd);
setloc(loc, x, y);
}
-
-
Memory Operation Functions
-
dwbreak
dwbreak(number) : py_tuple[EUDVariable, EUDVariable, EUDVariable, EUDVariable, EUDVariable, EUDVariable]
Splits a dword value [number] into word and byte forms.
Example
const w1, w2, b1, b2, b3, b4 = dwbreak(1234 + 0x10000 * 5678)[[0,1,2,3,4,5]];
println("w1:{} w2:{} b1:{} b2:{} b3:{} b4:{}", w1, w2, b1, b2, b3, b4);
-
read/write
-
dwread(ptr) : EUDVariable -
wread(ptr) : EUDVariable -
bread(ptr) : EUDVariableReads the dword/word/byte value at the specified local memory address [ptr].
-
dwwrite(ptr, dw) -
wwrite(ptr, w) -
bwrite(ptr, b)Writes dword/word/byte values to local memory address [ptr].
Example
// 0x582144: https://armoha.github.io/eud-book/offsets/ZergControlAvailable.html
const SUP_RACE_ZERG = 0;
const SUP_RACE_TERRAN = 1;
const SUP_RACE_PROTOSS = 2;
const SUP_TYPE_AVAILABLE = 0;
const SUP_TYPE_USED = 1;
const SUP_TYPE_MAX = 2;
function SetPlayerSupply(player: TrgPlayer, race, type, amount) {
dwwrite(0x582144 + (race) * 36 * 4 + (type) * 12 * 4 + (player) * 4, amount);
}
function GetPlayerSupply(player: TrgPlayer, race, type) {
return dwread(0x582144 + (race) * 36 * 4 + (type) * 12 * 4 + (player) * 4);
}
SetPlayerSupply(P1, SUP_RACE_ZERG, SUP_TYPE_MAX, 800); // Set player 1's Zerg supply maximum to 400 -
-
read_epd/write_epd
-
dwread_epd(epd) : EUDVariable
Reads the dword value at local memory address0x58A364 + [epd] * 4. -
dwwrite_epd(epd, value)
Writes a dword value to local memory address0x58A364 + [epd] * 4. -
wread_epd(epd, subp) : EUDVariable -
bread_epd(epd, subp) : EUDVariableReads the word/byte value at local memory address
0x58A364 + [epd] * 4 + [subp],[subp] < 4. -
wwrite_epd(epd, subp, value) -
bwrite_epd(epd, subp, value)Writes a word/byte value to local memory address
0x58A364 + [epd] * 4 + [subp],[subp] < 4. -
maskread_epd(epd, mask) : EUDVariable
Uses [mask] as a mask to read the dword value at local memory address0x58A364 + [epd] * 4.
Example
// Much like the read/write example, the _epd family of functions differs from the memory offset reference, and the EPD function can be used to convert a memory address into an epd offset
function SetPlayerSupply(player: TrgPlayer, race, type, amount) {
dwwrite_epd(EPD(0x582144) + (race) * 36 + (type) * 12 + (player), amount);
}
function GetPlayerSupply(player: TrgPlayer, race, type) {
return dwread_epd(EPD(0x582144) + (race) * 36 + (type) * 12 + (player));
}
const oe, os = div(EncodeWeapon("C-10 Concussion Rifle"), 4);
println("bread_epd Ghost weapon interval {}", bread_epd(EPD(0x656FB8) + oe, os));
println("maskread_epd Ghost weapon interval {}", bitrshift(maskread_epd(EPD(0x656FB8) + 1 + oe, 0xFF000000), 24));
bwrite_epd(EPD(0x656FB8) + oe, os, 1); // Modify Ghost weapon attack interval to 1 -
-
add_epd/subtract_epd
-
dwadd_epd(epd, value)
Increments the dword value at local memory address0x58A364 + [epd] * 4by [value]. -
dwsubtract_epd(epd, value)
Decrements the dword value at local memory address0x58A364 + [epd] * 4by [value]. -
wadd_epd(epd, subp, value) -
badd_epd(epd, subp, value)Increments the word/byte value at local memory address
0x58A364 + [epd] * 4 + [subp]by [value],[subp] < 4. -
wsubtract_epd(epd, subp, value) -
bsubtract_epd(epd, subp, value)Decrements the word/byte value at local memory address
0x58A364 + [epd] * 4 + [subp]by [value],[subp] < 4.
-
-
repmovsd_epd
repmovsd_epd(dstepdp, srcepdp, copydwn)
Copies[copydwn] * 4bytes of content from local memory address0x58A364 + [srcepdp] * 4to memory address0x58A364 + [dstepdp] * 4.
Example
const src = Db(b"___1___2___3___4___5");
const dst = Db(20);
repmovsd_epd(EPD(src), EPD(dst), 5);
// dst will be Db(b"___1___2___3___4___5")
-
dwepdread_epd
-
dwepdread_epd(epd) : py_tuple[EUDVariable, EUDVariable]
Reads a pointer from local memory address0x58A364 + [epd] * 4and returns the pointer and its EPD value. -
epdread_epd(epd) : EUDVariable
Reads a pointer from local memory address0x58A364 + [epd] * 4and returns its EPD value.
Example
// Create a Marine and get its pointer and EPD value
CreateUnit(1, "Terran Marine", $L("Location 1"), P1);
const lastUnitEPD = EPD(0x628438);
const ptr1, epd1 = dwepdread_epd(lastUnitEPD);
var epd2 = epdread_epd(lastUnitEPD); -
-
cunitread_epd
-
cunitread_epd(epd) : EUDVariable
Reads a cunit pointer from local memory address0x58A364 + [epd] * 4. This function is optimized for reading cunit pointers and returns a pointer. -
cunitepdread_epd(epd) : py_tuple[EUDVariable, EUDVariable]
Reads a cunit pointer from local memory address0x58A364 + [epd] * 4. This function is optimized for reading cunit pointers and returns the pointer and its EPD value.
Example
// Create a Marine and get its pointer and EPD value
CreateUnit(1, "Terran Marine", $L("Location 1"), P1);
const lastUnitEPD = EPD(0x628438);
const ptr1, epd1 = cunitepdread_epd(lastUnitEPD);
var ptr2 = cunitread_epd(lastUnitEPD); -
-
posread_epd
posread_epd(epd) : py_tuple[EUDVariable, EUDVariable]
Reads a pos (location) from local memory address0x58A364 + [epd] * 4.
Example
const screenTilePosEPD = EPD(0x57F1D0);
const x, y = posread_epd(screenTilePosEPD);
println("The current screen coordinates on the map: ({}, {})", x, y);
-
_cp Series
dwread_cp(cpoffset) : EUDVariabledwwrite_cp(cpoffset, value)dwadd_cp(cpoffset, value)dwsubtract_cp(cpoffset, value)wread_cp(cpoffset, subp) : EUDVariablebread_cp(cpoffset, subp) : EUDVariablewwrite_cp(cpoffset, subp, w)bwrite_cp(cpoffset, subp, b)maskread_cp(cpoffset, mask) : EUDVariablemaskwrite_cp(cpoffset, mask, value)dwepdread_cp(cpoffset) : py_tuple[EUDVariable, EUDVariable]epdread_cp(cpoffset) : EUDVariablecunitread_cp(cpoffset) : EUDVariablecunitepdread_cp(cpoffset) : py_tuple[EUDVariable, EUDVariable]posread_cp(cpoffset) : py_tuple[EUDVariable, EUDVariable]
The usage of all functions in the _cp series can refer to the _epd series. The _cp series will use
Current Player + [cpoffset]as epd.
They are usually used to improve code running efficiency and reduce the final number of triggers generated.Example
// The following code is just to demonstrate the usage of _cp, not to improve efficiency. To improve efficiency, you may need to think for yourself.
const screenTilePosEPD = EPD(0x57F1D0);
setcurpl(screenTilePosEPD); // Set Current Player to screenTilePosEPD
const x, y = posread_cp(0); // Read the value at the relative offset 0 bytes from Current Player, which actually reads the value at screenTilePosEPD
setcurpl(P1); // Set Current Player to P1 to output information to Player 1
println("Current screen coordinates on the map: ({}, {})", x, y);
-
readgen
-
readgen_epd(mask, args) : duck -
readgen_cp(mask, args) : duckCan be used to create custom local memory read functions.
Example
// 256 grids = 8192 pixels = x and y are within 0 ~ 8191 (0x1FFF)
// Compile-time functions can only be defined using py_eval
const posread_epd = readgen_epd(
0x1FFF1FFF,
list(0, py_eval('lambda x: x if x < 65536 else 0')),
list(0, py_eval('lambda y: y // 65536 if y >= 65536 else 0')),
);
const x, y = posread_epd(epd_address); -
-
memcpy
memcpy(dst, src, copylen)
Copies [copylen] bytes of content from local memory address [src] to memory address [dst].
-
memcmp
memcmp(buf1, buf2, count) : EUDVariable
Compares [count] bytes of content between local [buf1] and [buf2] memory blocks.
If the two memory blocks are exactly the same, returns 0.
Otherwise, compares the first different byte and returns a result greater than or less than 0.
-
strcpy
strcpy(dst, src)
Copies the string (terminated by\x00) from local memory address [src] to memory address [dst].
-
strcmp
strcmp(s1, s2) : EUDVariable
Compares the strings (terminated by \x00) between local [s1] and [s2] memory blocks.
If the two memory blocks are exactly the same, returns 0.
Otherwise, compares the first different byte and returns a result greater than or less than 0.
-
strlen
-
strlen(ptr) : EUDVariable
Gets the number of ASCII characters in the string (terminated by \x00) pointed to by the local pointer [ptr]. -
strlen_epd(epd) : EUDVariable
Gets the number of ASCII characters in the string (terminated by \x00) pointed to by the local [epd] offset pointer.
-
-
strnstr
strnstr(ptr, substr, count) : EUDVariable
Searches for another string [substr] within the first [count] ASCII characters of the string pointed to by the local pointer [ptr].
Returns the pointer if found, otherwise returns 0.
-
dbstr
-
dbstr_addstr(dst, src) : EUDVariable
Copies the local string [src] to memory address [dst], returns address [dst] + strlen([src]). -
dbstr_addstr_epd(dst, srcepd) : EUDVariable
Copies the string at local memory address0x58A364 + [srcepd] * 4to memory address [dst], returns address [dst] + strlen_epd([srcepd]). -
dbstr_adddw(dst, number) : EUDVariable
Converts a numeric value to text output at local memory address [dst], returns address [dst] + strlen(itoa([number])). -
dbstr_addptr(dst, ptr) : EUDVariable
Converts a numeric value to hexadecimal digit text output at local memory address [dst], returns address [dst] + strlen(itox([number])). -
dbstr_print(dst, *args, EOS=true, encoding="UTF-8")
Combines multiple parameters [*args] into a string output at local memory address [dst].
Named parameter [EOS] specifies whether to append a string termination symbol at the end of the string, default true.
Named parameter [encoding] specifies the encoding, default UTF-8. -
sprintf(dst, format_string : py_str, *args, EOS=true, encoding="UTF-8")
Formats multiple parameters [*args] according to [format_string] and outputs them to local memory address [dst].
Named parameter [EOS] specifies whether to append a string termination symbol at the end of the string, default true.
Named parameter [encoding] specifies the encoding, default UTF-8.
Example
const s = Db(100);
var addr = unProxy(s);
addr = dbstr_addstr(addr, Db("0123"));
addr = dbstr_adddw(addr, 4567);
addr = dbstr_addptr(addr, 0x89ABCDEF);
simpleprint(s); // 0123456789ABCDEF
dbstr_print(s, "0123", 4567, hptr(0x89ABCDEF));
simpleprint(s); // 0123456789ABCDEF
sprintf(s, "{}{}{:x}", "0123", 4567, 0x89ABCDEF);
simpleprint(s); // 0123456789ABCDEF -
-
ptr2s/epd2s
-
ptr2s(ptr) : Db*
Reads the string at local memory address [ptr], equivalent to using{:s}placeholder in formatted text. -
epd2s(epd) : Db*
Reads the string at local memory address0x58A364 + [srcepd] * 4, equivalent to using{:t}placeholder in formatted text.
-
-
hptr
hptr(value) : Db*
Converts [value] to hexadecimal output, equivalent to using{:x}placeholder in formatted text.
Example
println("{}, {}", 0xAABBCC, hptr(0xAABBCC)); // 11189196, 00AABBCC
println("{}, {:x}", 0xAABBCC, 0xAABBCC); // 11189196, 00AABBCC
-
gettextptr
gettextptr(): EUDVariable
Gets the local screen text pointer for the next line displayed on the screen.
-
dwpatch_epd
dwpatch_epd(dstepd, value)
Patches the local memory address0x58A364 + [dstepd] * 4by [value].
-
GetMapStringAddr
GetMapStringAddr(strID : TrgString) : EUDVariable
Gets the memory address of a local map string or string ID [strID].
Example
// It supports using strings and IDs to get, the following usages are equivalent
const addr = GetMapStringAddr(6);
const addr = GetMapStringAddr("Force 3");
-
GetTBLAddr
-
GetTBLAddr(TBLKey : StatText) : EUDVariable
Gets the memory address of a TBL table Key/ID [TBLKey].It is worth mentioning that the TBLKey string itself may not actually exist in memory.
For example, there is no "Terran Siege Tank (Tank Mode)" string in memory.
The string corresponding to the TBLKey "Terran Siege Tank (Tank Mode)" (located in the stat_txt.tbl string section) prints out as "Terran Siege Tank"
Example
// It supports using TBLKey or TBL ID to get, the following usages are equivalent
const addr = GetTBLAddr(4);
const addr = GetTBLAddr("Terran Goliath");
const addr = wread(dwread_epd(EPD(0x6D1238)) + $B("Terran Goliath")); -
-
settbl
-
settbl(tblID : StatText, offset, *args, encoding="cp949") -
settbl2(tblID : StatText, offset, *args, encoding="cp949")Sets the local memory string value of the specified [tblID] in the TBL table at offset [offset] to *args. The difference between settbl and settbl2 is that settbl will add an EOS character at the end of the set string, while settbl2 will not.
-
settblf(tblID : StatText, offset, format_string, *args, encoding="cp949") -
settblf2(tblID : StatText, offset, format_string, *args, encoding="cp949")Sets the local memory string value of the specified [tblID] in the TBL table at offset [offset] to a formatted string. The difference between settblf and settblf2 is that settblf will add an EOS character at the end of the set string, while settblf2 will not.
// The following code is equivalent
settbl("Terran Goliath", 1, "1234");
settbl2("Terran Goliath", 1, "1234\0");
dbstr_print(GetTBLAddr("Terran Goliath") + 1, "1234\0", EOS = false); // Rename Terran Goliath to T1234 -
-
-
Math Functions
-
atan2
-
atan2(y, x) : EUDVariable
Arctangent function of two arguments, returns the polar angle of the point (x, y), i.e. the angle with the x-axis. -
atan2_256(x, y) : EUDVariable
The difference from atan2 is that in processing angles, it divides a circumference into 256 equal parts, and the angle is in 256 degrees, not 360 degrees.
StarCraft units use angles stored in one byte, so they use the 256 degree system.
0 degrees faces up, 0 to 256 increments clockwise.
64 degrees faces right, 128 degrees faces down, 192 degrees faces left.Warning
In euddraft version 0.9.9.7 and earlier, atan2_256 uses the mathematical coordinate system.
In euddraft version 0.9.9.8 and above, atan2_256 is changed to use the StarCraft coordinate system.Example
function _0998_above() {
static var is0998above = false;
once is0998above = l2v(atan2_256(10, 10) >= 90);
return is0998above;
}
function angleBetween_256(x1, y1, x2, y2) {
if (_0998_above()) {
return atan2_256(y2 - y1, x2 - x1);
}
return atan2_256(x2 - x1, y1 - y2);
}
println("The angle from (131, 33) to (765, 546) is {}", angleBetween_256(131, 33, 765, 546)); -
-
sqrt
sqrt(x) : py_int | EUDVariable
Calculates the square root of [x].
Example
function distanceBetween(x1, y1, x2, y2) {
const x = x2 - x1;
const y = y2 - y1;
return sqrt(x*x + y*y);
}
println("The distance from (131, 33) to (765, 546) is {}", distanceBetween(131, 33, 765, 546));
-
lengthdir
-
lengthdir(length, angle) : tuple[EUDVariable, EUDVariable]
Calculates the coordinates of another point by traveling [length] distance from (0, 0) in the direction of [angle] degrees. -
lengthdir_256(length, angle) : tuple[EUDVariable, EUDVariable]
The difference from lengthdir is that in processing angles, it divides a circumference into 256 equal parts, and the angle is in 256 degrees, not 360 degrees.
StarCraft units use angles stored in one byte, so they use the 256 degree system.
0 degrees faces up, 0 to 256 increments clockwise.
64 degrees faces right, 128 degrees faces down, 192 degrees faces left.Warning
In euddraft version 0.9.9.7 and earlier, lengthdir_256 uses the mathematical coordinate system.
In euddraft version 0.9.9.8 and above, lengthdir_256 is changed to use the StarCraft coordinate system.Example
function _0998_above() {
static var is0998above = false;
once is0998above = l2v(atan2_256(10, 10) >= 90);
return is0998above;
}
function polarProjection_256(x0, y0, length, angle) {
var dx, dy;
if (_0998_above()) {
dx, dy = lengthdir_256(length, angle);
return x0 + dx, y0 + dy;
} else {
dx, dy = lengthdir_256(length, 320 - angle);
return x0 + dx, y0 - dy;
}
}
const x, y = polarProjection_256(1264, 880, 888, 73);
println("Traveling 888 distance from (1264, 880) in the direction of 73 degrees (256 degrees) arrives at ({}, {})", x, y); -
-
pow
pow(x, y) : py_int | EUDVariable
Calculates [x] to the power of [y]. If both arguments are compile-time constants, it can return a constant at compile time.
Example
println("2^10 = {}", pow(2, 10));
-
div
-
div(a, b) : py_tuple[EUDVariable, EUDVariable]
Unsigned integer division [a] divided by [b], supports only positive integers, returns quotient and remainder. -
div_towards_zero(a, b) : py_tuple[EUDVariable, EUDVariable]
Added in euddraft 0.9.9.8. Signed integer division, calculates the quotient and remainder of (a ÷ b), rounding the quotient towards zero. -
div_floor(a, b) : py_tuple[EUDVariable, EUDVariable]
Added in euddraft 0.9.9.8. Signed integer division, calculates the quotient and remainder of (a ÷ b), rounding the quotient towards negative infinity. -
div_euclid(a, b) : py_tuple[EUDVariable, EUDVariable]
Added in euddraft 0.9.9.8. Signed integer division, calculates the quotient and remainder of Euclidean division of a by b.
This computes the quotient such thata = quotient * b + remainder, and0 <= remainder < abs(b).
In other words, the result is a ÷ b rounded to the quotient such thata >= quotient * b.
Ifa > 0, this is equal to round towards zero; ifa < 0, this is equal to round towards +/- infinity (away from zero).
Example
var a, b, quotient, remainder;
a, b = 17, 3;
quotient, remainder = div(a, b);
println("div(17, 3) returns {}, {}", quotient, remainder); // div(17, 3) returns 5, 2
a, b = 17, -3;
quotient, remainder = div_towards_zero(a, b);
println("div_towards_zero(17, -3) returns -{}, {}", -quotient, remainder); // div_towards_zero(17, -3) returns -5, 2
quotient, remainder = div_floor(a, b);
println("div_floor(17, -3) returns -{}, -{}", -quotient, -remainder); // div_floor(17, -3) returns -6, -1
quotient, remainder = div_euclid(a, b);
println("div_euclid(17, -3) returns -{}, {}", -quotient, remainder); // div_euclid(17, -3) returns -5, 2
a, b = -17, -3;
quotient, remainder = div_towards_zero(a, b);
println("div_towards_zero(-17, -3) returns {}, -{}", quotient, -remainder); // div_towards_zero(-17, -3) returns 5, -2
quotient, remainder = div_floor(a, b);
println("div_floor(-17, -3) returns {}, -{}", quotient, -remainder); // div_floor(-17, -3) returns 6, -1
quotient, remainder = div_euclid(a, b);
println("div_euclid(-17, -3) returns {}, {}", quotient, remainder); // div_euclid(-17, -3) returns 6, 1 -
-
rand
-
rand(): EUDVariable
Generates a random integer in the range of 0~0xFFFF. -
dwrand(): EUDVariable
Generates a random integer in the range of 0~0xFFFFFFFF.
Note Do not use random functions in desync conditions.
Example
const r = rand(); -
-
seed
-
srand(seed)
Sets the random seed to [seed]. -
getseed(): EUDVariable
Gets the set random seed.
Note Do not use random functions in desync conditions.
Example
var seed = getseed();
srand(seed + 1); -
-
randomize
randomize(): EUDVariable
Initializes the random seed.
Note Do not use random functions in desync conditions.
Example
function onPluginStart() {
randomize();
}
-
-
Bitwise Operation Functions
-
bitand
bitand(a, b) : py_int | EUDVariable
Bitwise AND operation [a] & [b]
Example
var a = 0b0011; // 3
var b = 0b1100; // 12
println("{}", bitand(a, b)); // 0 (binary 0b0000)
-
bitor
bitor(a, b) : py_int | EUDVariable
Bitwise OR operation [a] | [b]
Example
var a = 0b0011; // 3
var b = 0b1100; // 12
println("{}", bitor(a, b)); // 15 (binary 0b1111)
-
bitnot
bitnot(a) : py_int | EUDVariable
Bitwise NOT operation ~[a]
Example
var a = 0b0011; // 3
var b = 0b1100; // 12
println("{}, {}", bitnot(a), b); // 12, 12 (binary 0b1100, 0b1100)
-
bitxor
bitxor(a, b) : py_int | EUDVariable
Bitwise XOR operation [a] ^ [b]
Example
var a = 0b0111; // 7
var b = 0b1110; // 14
println("{}", bitxor(a, b)); // 9 (binary 0b1001)
-
bitnand
bitnand(a, b) : py_int | EUDVariable
Bitwise NAND operation ~([a] & [b])
Example
var a = 0b0011; // 3
var b = 0b1100; // 12
println("{}", bitnand(a, b)); // 15 (binary 0b1111)
-
bitnor
bitnor(a, b) : py_int | EUDVariable
Bitwise NOR operation ~([a] | [b])
Example
var a = 0b0011; // 3
var b = 0b1100; // 12
println("{}", bitnor(a, b)); // 0 (binary 0b0000)
-
bitnxor
bitnxor(a, b) : py_int | EUDVariable
Bitwise XNOR operation~([a] ^ [b])
Example
var a = 0b0111;
var b = 0b1110;
println("{}", bitnxor(a, b)); // 6 (binary 0b0110)
-
bitlshift
bitlshift(a, b) : py_int | EUDVariable
Bitwise Left shift operation[a] << [b]
Example
var a = 0b0111; // 7
var b = 1;
println("{}", bitlshift(a, b)); // 14 (binary 0b1110)
-
bitrshift
bitrshift(a, b) : py_int | EUDVariable
Bitwise Right shift operation [a] >> [b]
Example
var a = 0b0111; // 7
var b = 1;
println("{}", bitrshift(a, b)); // 3 (binary 0b0011)
-
-
QueueGameCommand Functions
Queue game command to packet queue.
Starcraft periodically broadcasts game packets to other player. Game packets are stored to queue, and this function add data to that queue, so that SC can broadcast it.
The QueueGameCommand functions are all for the local player rather than the current player, and cannot be used for players not in the game or computer players.
Note If packet queue is full, this function fails. This behavior is silent without any warning or error, since this behavior shouldn't happen in common situations. So Don't use this function too much in a frame.
-
QueueGameCommand
QueueGameCommand(data, size)
Adds a data packet of size [size] [data] to the local broadcast queue. All functions in this section are wrappers for sending specific data packets to this function.
-
QueueGameCommand_MinimapPing
QueueGameCommand_MinimapPing(xy)
Adds a data packet to the local broadcast queue to ping at coordinates [xy] on the minimap. The xy calculation method is x + y * 65536.
Example
// Ping at coordinates 1234, 2345
QueueGameCommand_MinimapPing(1234 + 2345 * 65536);
-
QueueGameCommand_QueuedRightClick
QueueGameCommand_QueuedRightClick(xy)
Adds a data packet to the local broadcast queue for a right click at coordinates [xy]. The xy calculation method is x + y * 65536.
Example
// Right click at coordinates 1234, 2345. If units are selected, they will move there.
QueueGameCommand_QueuedRightClick(1234 + 2345 * 65536);
-
QueueGameCommand_Select
-
QueueGameCommand_Select(n, ptrList: EUDArray)
Adds a data packet to the local broadcast queue to select some units. [n] is the number of units, [ptrList] is the cunit pointer list, not the epd list.Note This only sends a "units selected" data packet locally, it does not actually select units on the local screen. It only tells other online players that the local player has selected these units. If RightClick data packets are sent immediately after, these units will move to the target location.
Example
const uar = EUDArray(12);
if (playerexist(P1) && GetPlayerInfo(P1).type == 0x06) { // Check if player 1 is an online human player
foreach(i : py_range(3)) {
uar[i] = dwread_epd(EPD(0x628438));
CreateUnitWithProperties(1, "Zerg Overlord", "Location 1", P1, UnitProperty(invincible = true));
}
}
if (getuserplayerid() == $P1) { // Check if the local player is player 1
QueueGameCommand_Select(3, uar);
QueueGameCommand_QueuedRightClick(1234 + 2345 * 65536);
} -
-
QueueGameCommand_PauseGame
QueueGameCommand_PauseGame()
Adds a pause game data packet to the local broadcast queue.
-
QueueGameCommand_ResumeGame
QueueGameCommand_ResumeGame()
Adds a resume game data packet to the local broadcast queue.
-
QueueGameCommand_RestartGame
QueueGameCommand_RestartGame()
Adds a restart game data packet to the local broadcast queue.
-
QueueGameCommand_UseCheat
QueueGameCommand_UseCheat(cheats)
Use [cheats] locally, invalid for multiplayer games.
Cheat code list
0x00000001 Black Sheep Wall
0x00000002 Operation CWAL
0x00000004 Power Overwhelming
0x00000008 Something For Nothing
0x00000010 Show me the Money
0x00000020
0x00000040 Game Over Man
0x00000080 There is no Cow Level
0x00000100 Staying Alive
0x00000200 Ophelia
0x00000400
0x00000800 The Gathering
0x00001000 Medieval Man
0x00002000 Modify the Phase Variance
0x00004000 War Aint What It Used To Be
0x00008000
0x00010000
0x00020000 Food For Thought
0x00040000 Whats Mine Is Mine
0x00080000 Breathe Deep
0x20000000 NogluesExample
QueueGameCommand_UseCheat(0x00000001 | 0x00000002 | 0x00000010); // Enable Black Sheep Wall + Operation CWAL + Show me the Money
QueueGameCommand_UseCheat(0x00000002); // Disable Operation CWAL
QueueGameCommand_UseCheat(0); // Disable all cheats
-
QueueGameCommand_TrainUnit
QueueGameCommand_TrainUnit(unit: TrgUnit)
Adds a train specified unitType data packet to the local broadcast queue. Use with QueueGameCommand_Select to select units.
Example
once {
const uar = EUDArray(12);
if (playerexist(P1) && GetPlayerInfo(P1).type == 0x06) { // Check if player 1 is an online human player
SetResources(P1, Add, 10000, OreAndGas);
uar[0] = dwread_epd(EPD(0x628438));
CreateUnitWithProperties(1, "Terran Command Center", "Location 1", P1, UnitProperty(invincible = true));
}
if (getuserplayerid() == $P1) { // Check if the local player is player 1
QueueGameCommand_Select(1, uar); // Check if the local player is player 1
QueueGameCommand_QueuedRightClick(1234 + 2345 * 65536); /* Set the rally point to 1234, 2345 */
QueueGameCommand_TrainUnit("Terran SCV"); /* Train an SCV */
}
}
-
QueueGameCommand_MergeDarkArchon
QueueGameCommand_MergeDarkArchon()
Adds a merge dark archon data packet to the local broadcast queue. Use with QueueGameCommand_Select to select units.
Example
once {
const uar = EUDArray(12);
if (playerexist(P1) && GetPlayerInfo(P1).type == 0x06) { // Check if player 1 is an online human player
foreach(i : py_range(6)) {
uar[i] = dwread_epd(EPD(0x628438));
CreateUnitWithProperties(1, "Protoss Dark Templar", "Location 1", P1, UnitProperty(invincible = true));
}
}
if (getuserplayerid() == $P1) { // Check if the local player is player 1
QueueGameCommand_Select(6, uar);
QueueGameCommand_MergeDarkArchon();
}
}
-
QueueGameCommand_MergeArchon
QueueGameCommand_MergeArchon()
Adds a merge archon data packet to the local broadcast queue. Use with QueueGameCommand_Select to select units.
Example
once {
const uar = EUDArray(12);
if (playerexist(P1) && GetPlayerInfo(P1).type == 0x06) { // Check if player 1 is an online human player
foreach(i : py_range(6)) {
uar[i] = dwread_epd(EPD(0x628438));
CreateUnitWithProperties(1, "Protoss High Templar", "Location 1", P1, UnitProperty(invincible = true));
}
}
if (getuserplayerid() == $P1) { // Check if the local player is player 1
QueueGameCommand_Select(6, uar);
QueueGameCommand_MergeArchon();
}
}
-