Staredit Network > Forums > SC1 UMS Theory and Ideas > Topic: [EUD] A Mapmaker's Guide for Creating EUDs
[EUD] A Mapmaker's Guide for Creating EUDs
Aug 14 2011, 8:00 pm
By: Roy
Pages: 1 2 34 >
 

Aug 14 2011, 8:00 pm Roy Post #1

An artist's depiction of an Extended Unit Death

EUDs/EPDs are a concept that a lot of mappers are curious about, but only a handful of people actually know how to handle them. In this tutorial, I hope to educate readers to a point where not only do they understand EUD triggers, but they are able to create EUDs/EPDs whenever they need to. This guide is meant to be used to build a foundation of knowledge on EUDs.

Contents:

     Section 1: Introduction
              1.1: What Is an EUD?
              1.2: What's the Difference Between an EUD and EPD?
              1.3: Why Should I Use an EUD?

     Section 2: Getting Started
              2.1: Tools of the Trade
              2.2: Getting an Editor
              2.3: Getting a Memory Scanner
              2.4: Calculation Tools

     Section 3: Making Your First EUD
              3.1: Getting an Address
              3.2: Converting the Address
              3.3: Creating the Trigger

     Section 4: Variations in EUD Creation
              4.1: Manually vs Automatically Finding an Address
              4.2: Finding the Correct Value of an Address
              4.3: EUDs Checking For a Range of Values

     Section 5: Synchronization
              5.1: Why Desynchronization Happens
              5.2: Global VS Local Data
              5.3: Macs VS PC

     Section 6: Unit-Specific EUDs
              6.1: Unit Index IDs
              6.2: Calculating an EUD Based on Unit Index ID
              6.3: Uniquely Identifying a Unit

     Section 7: Text-Based EUDs
              7.1: Calculating the Value of Text
              7.2: The 11 Addresses
              7.3: The Null Character
              7.4: Detecting Player Chat

     Section 8: Closing
              8.1: Other Useful Resources
              8.2: Credits and Acknowledgements
              8.3: Frequently Asked Questions

     Appendices
              Appendix A: Unit HP


If you find anything that is phrased awkwardly or needs more clarity, feel free to PM me or post in the topic. If you find typos and/or mistakes, please send me a PM.

Post has been edited 11 time(s), last time on Dec 15 2017, 9:46 pm by Roy.




Aug 14 2011, 8:06 pm Roy Post #2

An artist's depiction of an Extended Unit Death

Section 1: Introduction

StarCraft's editor is an incredibly simplistic tool used to create a new type of game on an existing game engine. However, with simplicity comes limitations. Mapmakers created elaborate workarounds and compromises because the editor wouldn't allow them to do many things it doesn't have direct support for. Since the discovery of Extended Unit Deaths, mappers can extend these capabilities to accomplish things that were once not known to be possible.


Section 1.1: What Is an EUD?

An Extended Unit Death (EUD) is a term used to describe overflowing the unit data field in a trigger condition or action. Overflowing means entering a number larger than the maximum value. Doing this causes StarCraft to look in a different area when looking for information. For example, instead of looking at how many Marines have died for a player, the overflow makes SC check how much HP a unit on the map has.


Section 1.2: What's the Difference Between an EUD and EPD?

You may be unfamiliar to the acronym EPD (Extended Player Death) and are more used to hearing about the wonders of EUDs. EUDs and EPDs are basically the same thing: they are just different methods of accomplishing the task. As you may have guessed, EUDs overflow the unit field, whereas EPDs overflow the player field. I haven't found a useful address one method can access where the other one cannot (although EPDs have a larger range, so in theory, they would be the better choice). EPDs are commonly referred to as EUDs due to their conceptual equivalency.

For the purpose of this tutorial, I will be using the EPD method of creating triggers, because the user interface input for it is simpler than it is for EUDs. For simplicity, I will refer to both methods as the more-established term "EUD."


Section 1.3: Why Should I Use an EUD?

You've probably gone this far as a mapper without ever needing to use an EUD, so why start? To be honest, there's no reason to start until you need to do something that cannot be done without EUDs, or when using EUDs would significantly improve your game. They can be used to detect HP, unit selection, screen position, game speed, text on the screen, if a player is hacking (in theory), keys pressed on a keyboard, and more!

EUDs can be used to improve current systems implemented in maps, such as dialog or shopping interfaces. It can be used to recreate games in a brand new way (see my Fireball map, which recreates Dodgeball using the facing direction of a unit to determine which way to shoot).


Section 1 Quiz
Quote from Question 1
What does EPD stand for?
Answer
Quote from Question 2
True or False: EUDs and EPDs do different things.
Answer


Post has been edited 9 time(s), last time on May 17 2014, 6:34 pm by Roy.




Aug 14 2011, 8:06 pm Roy Post #3

An artist's depiction of an Extended Unit Death

Section 2: Getting Started

So at this point, hopefully you're pumped to write giant numbers into your editor. Unfortunately, getting these numbers into the map isn't an effortless task. Fortunately, there are tools available to ease this pain.


Section 2.1: Tools of the Trade

At a minimum, you need an editor that supports entering EUD/EPD data. Unless you're going to rely purely on the EUD Database (which is not necessarily a bad option), you're going to need a program to find the address (i.e., the location in StarCraft's memory) with the data you're trying to read. Finally, you're going to need some way to convert this information into numbers you can put into your trigger.


Section 2.2: Getting an Editor

So, what editor do you have? (Xtra Editor users, it's time for you to use a real editor.)

I am an advocate for SCMDraft 2, and that is the editor I will be using for this tutorial. You can get the latest version here. This version supports both EUD and EPD input, and even has a "Memory" condition to make the experience all the more enjoyable. (Of course, SCMD2 is not your only choice; Starforge will support this functionality if you modify one of its data files. Other third party programs like ProTRG support EUDs as well... and you might be able to work with Xtra Editor if you really want to cripple yourself; EUDTrig supports exporting .trg files, after all.)


Section 2.3: Getting a Memory Scanner

PLEASE NOTE: This guide was written for Brood War 1.16.1; StarCraft: Remastered will not work correctly with this guide, and your account will get banned if you attach a memory scanner to StarCraft: Remastered. If you're going to follow the steps in this guide, use an offline copy of StarCraft version 1.16.1!

You might be wondering what a memory scanner is and why you need it. Well, as I explained earlier, EUDs are used to read data in StarCraft that you can't normally get to. The first step to making an EUD is figuring out where this data is. This is where a memory scanner comes in. Using this handy tool, you can get any address you want, which you can use to create your EUD.

Again, you have a choice as to what program you want to use. The two that seem to be most popular for finding EUD values are Cheat Engine (CE) and ArtMoney. I use CE, but ArtMoney or any other memory scanner will work just as well; it's all up to your personal preference. Keep in mind that this tutorial will be using screenshots for CE.


Section 2.4: Calculation Tools

Oh yes, you better believe there's going to be some maths in here. You can get by with a calculator and a few equations, but why squander the efforts of others?

FaRTy1billion made a program called EUDTrig which converts an address to the necessary EUD/EPD value you want. You can download this here: http://www.staredit.net/topic/3585/.

If you fancy some assistance in calculating text with EUDs, you can either check out http://www.staredit.net/topic/14174/ or use Farty's online calculator.


Section 2 Quiz
Quote from Question 1
What editor should you use for EUDs?
Answer
Quote from Question 2
How does a memory scanner help us make EUDs?
Answer
Quote from Question 3
Are calculation tools required to make EUDs?
Answer


Post has been edited 12 time(s), last time on Jun 5 2020, 10:29 am by Roy.




Aug 14 2011, 8:06 pm Roy Post #4

An artist's depiction of an Extended Unit Death

Section 3: Making Your First EUD

If you've made it this far, you're probably ready to write your very own EUD. This section is essentially going to be an equivalent of a "Hello World" exercise commonly used when learning a new programming language. The things you want to learn from this are: how to find an address, how to convert the address you find, and how to put this information into a trigger. For the purpose of this exercise, please use this map: EUD_Basic_Test_Map.scx.


Section 3.1: Getting an Address

PLEASE NOTE: This guide was written for Brood War 1.16.1; StarCraft: Remastered will not work correctly with this guide, and your account will get banned if you attach a memory scanner to StarCraft: Remastered. If you're going to follow the steps in this guide, use an offline copy of StarCraft version 1.16.1!

Let's say you want to make an EUD address that does something when Player 1 has 5 units (or more specifically, "men") on the map. To accomplish this, we want to find where SC stores the address that keeps track of Player 1's unit count.

Start up both SC (StarCraft) and CE (Cheat Engine). In CE, you'll notice a glowing button located at the top-left of the window. Click on this button and a dialog will appear. In the list of processes, you want to find StarCraft. When you find it, double click on it (or click on it and press the "Open" button). This connects the memory scanner (CE) to the program you want to be reading (SC).



Next, get on SC and create a new game using EUD_Basic_Test_Map. On the map, you'll notice that you currently have 0 units. Let's make this a new search in Cheat Engine. Type "0" into the value field and hit the "First Scan" button.



You'll get a giant list of over a million potential addresses on the left. This does us no good, and we need to narrow it down until we can find an address truly associated with the unit count. Make a Terran Marine in your map, and the unit count will increase to 1. Search for this value in CE again by using the "Next Scan" button.



Now the list of addresses has dropped to about 300, which is much better, but we want to narrow it down to ideally less than 10 addresses. Continue making or killing units to change the unit count, and keep scanning these new numbers to narrow down the list of addresses. I decided to create 6 more units before scanning again for the new value (7):



As you can see, the list has dropped to only two remaining addresses (if you have three, try killing off a unit or two and scanning the new value again). When you create and kill units to change your unit count, the values of these addresses change with it. From this observation, we can assert that these addresses are linked with Player 1's unit count. It doesn't matter which one you choose, but pick one of the addresses and write it down. I'll pick address 00581DE4.


Section 3.2: Converting the Address

Once you have the address, you can feel free to close SC and/or CE, because we won't need them for the remainder of creating the EUD. Open up Farty's EUDTrig program. Here, we can enter the address and convert it to a number we can use in the trigger editor.



You may have noticed I put a "0x" in front of my address. This is required because the address is in hexadecimal, and the way you tell the program that it's in hexadecimal is to precede the number with a "0x" notation.

Since we are making an Extended Player Death, check the check box labeled "Use Extended Player Deaths." Now, hit the button pointing downward, and the program will spit out a number for the address.



You may notice that this number is sometimes negative, such as in this case. This is completely fine and should not alarm you. Since we are using EUDs, we do not need to worry about the "Unit ID" field.

That's all you need to do to convert the address. You're almost done making your EUD!


Section 3.3: Creating the Trigger

Alright, so our address was converted to -8544. Now we can write our condition.

Open up SCMDraft 2 and open the map. Navigate your way over to the classic trigger editor and make a new trigger. You can make this owned by Player 1. For the condition, choose "Memory." There are three fields to enter data for this condition. The first field is for the address value (which we figured out was -8544). The second two fields are used to compare the value at the address.

If you recall when finding the address, the value was the unit count of Player 1. Since we want a trigger to run when Player 1 has 5 units, this should be filled out to be "exactly 5."



That's it! Any actions you make for this trigger will happen when Player 1 has 5 men. Try putting in something like a Display Text Message, or killing all men owned by player 2.

If you wanted it to happen when Player 1 has 10 units, just change the "5" in the condition to "10." If you had a map where something happens if Player 1 drops below 20 units, change the condition to read "at most 19."

Now I know what you're thinking: "There's already the Command condition that can do this for us! Why waste our time?!" My answer to that is that this exercise was meant to teach you the fundamentals of creating an EUD, and it is not necessary for it to be a practical condition.


Section 3 Quiz
Quote from Question 1
True or False: In order to enter a hexadecimal value in EUDTrig, you must put "x0" at the end of the value.
Answer
Quote from Question 2
Say I have the address 006CDFE0, which represents music volume. The value at this address is represented by the percent it is set to (between 0 and 100). I converted this address using EUDTrig and got the number 331551. I want to write an EUD checking if the player has their music on full blast (100%). Write the memory condition to check for this.
Answer


Post has been edited 16 time(s), last time on Jun 5 2020, 10:28 am by Roy.




Aug 14 2011, 8:07 pm Roy Post #5

An artist's depiction of an Extended Unit Death

Section 4: Variations in EUD Creation

Well, you've seen a nice, simple way to detect something using EUDs. Section 3 shouldn't have been overwhelming, and if you didn't understand it, you shouldn't continue until you have. Not all EUDs are this nice and straightforward; there are many factors and issues that can arise, such as byte offsets. Also, not all EUDs need to be calculated manually; the EUDDB has many, many addresses recorded and described.


Section 4.1: Manually vs Automatically Finding an Address

As I mentioned above, it is not mandatory to find an address manually. You can use Google to search the EUDDB (just replace "Text" in the search query with what you want to find, such as "Game Speed").

Take the Game Speed entry as an example. It gives you the Player ID (the value of the address for a Memory condition) and a list of what the values mean. If you wanted to check if a game was running on fastest, you could take this information and instantly make the trigger condition:

     Memory at Death Table + 331548 is exactly 6

It is very rare that you would need to calculate an address yourself. However, if you cannot find the data you want in the EUDDB, you can attempt to find it yourself manually, as described in Section 3.1. There are a few things to note from this approach:

1) The value type is not always going to be "4 bytes," which is what we used when searching for an address in Section 3.1. There are different types of values, as you can see by clicking the dropdown in CE:
Code
Byte          Values between 0 and 255. Used for small numbers, like player number.
2 Bytes       Values between 0 and 65535. This is not commonly used.
4 Bytes       Values between 0 and 4294967295. This is very commonly used.

It's not very likely that you will use the other types. Binary is a bit (i.e., true/false), floats and doubles are decimal values, and text is rather arbitrary, as we can't use it to detect in-game messages and names (because we have to put a number in the EUD condition, not a word).

2) Some values are stored at a different scale than what they appear to be in SC. For example, the game may say you have 30 used supply, but the stored value is actually twice as much (60). Therefore, searching for exact values can be unreliable. Often times you'll have to search for "Unknown Initial Value" and then use "Value increased" or "Value decreased," or just "Value Changed" if you're unsure about even that.

Detecting Hacks



Section 4.2: Finding the Correct Value of an Address

As I mentioned earlier, not all values are what you would expect from an address. You may notice strange values and wonder, "How do I write an EUD to check for a specific value?" Fear not! I will give you everything you need to do just that.

Depending on the offset of the address, you're going to need to multiply the value by a certain amount. This all can be easily determined by looking at the last character of the address. Refer to this awesome chart:

Code
0 1 2 3
4 5 6 7
8 9 A B
C D E F

If your address ends with a character from the first column (0, 4, 8, C), you do not need to multiply the value. (i.e. If you're looking for the value 10, you just enter 10)
If your address ends with a character from the second column (1, 5, 9, D), you need to check the range between X*256 and (X*256)+255. (i.e. If you're looking for the value 10, you should check between 10*256=2560 and (10*256)+255=2815)
If your address ends with a character from the third column (2, 6, A, E), you need to check the range between X*65536 and (X*65536)+65535. (i.e. If you're looking for the value 10, you should check between 10*65536=655360 and (10*65536)+65535=720895)
If your address ends with a character from the fourth column (3, 7, B, F), you need to check the range between X*16777216 and (X*16777216)+16777215. (i.e. If you're looking for the value 10, you should check between 10*16777216=167772160 and (10*16777216)+16777215=184549375)

So say your address ends in a D (second column). You would have two conditions to check if the value of the address is 10:
     Memory at Death Table + XXXXXXX is at least 2560
     Memory at Death Table + XXXXXXX is at most 2815

Now, that's checking if the value is EXACTLY 10. Strange that we have to use at least and at most to check one value, right? In fact, all values between 2560 and 2815 are equal to 10 for this address, so you should include them all.


Section 4.3: EUDs Checking For a Range of Values

Well, you thought this section was going to be a piece of cake until you read that last bit, didn't you? Yes, for calculating a range of values, you just need to say "at least" with the minimum, and "at most" with the maximum. It's a piece of cake for values that don't need to be multiplied. For values that do need to be multiplied, it's not actually that bad if you just follow the formulas.

From the previous section, we determined that to calculate one value for an address with an offset, we calculate a range. Well, all you have to do to calculate a range of values is plug in the numbers for the upper and lower bounds into the equation. Here's the awesome chart for reference:

Code
0 1 2 3
4 5 6 7
8 9 A B
C D E F

If your address ends with a character from the first column (0, 4, 8, C), you do not need to multiply the values. (i.e. If you're looking between 5 and 10, you enter at least 5 and at most 10)
If your address ends with a character from the second column (1, 5, 9, D), you need to check the range between X*256 and (Y*256)+255. (i.e. If you're looking between 5 and 10, you check at least 5*256=1280 and at most (10*256)+255=2815)
If your address ends with a character from the third column (2, 6, A, E), you need to check the range between X*65536 and (Y*65536)+65535. (i.e. If you're looking between 5 and 10, you check at least 5*65536=327680 and at most (10*65536)+65535=720895)
If your address ends with a character from the fourth column (3, 7, B, F), you need to check the range between X*16777216 and (Y*16777216)+16777215. (i.e. If you're looking between 5 and 10, you check at least 5*16777216=83886080 and at most (10*16777216)+16777215=184549375)

So say your address ends in an F (fourth column). You would have two conditions to check if the value of the address is between 5 and 10:
     Memory at Death Table + XXXXXXX is at least 83886080
     Memory at Death Table + XXXXXXX is at most 184549375

That checks for anything that's between 5 and 10. See, it's not so bad when you have the equations at hand.


Section 4 Quiz
Quote from Question 1
True or False: Most values are 4 bytes, so that's a good value to try first when searching for an address using a memory scanner.
Answer
Quote from Question 2
I have the address 006CA934, which is the address for the HP display of a selected unit. I want to check if the value is equal to 40. What will the condition(s) for the trigger look like? (Hint: The EUD value of the address is 328058).
Answer
Quote from Question 3
I have the address 006D5BBE, which is the address for minimap states. I want to check if the value is equal to 2. What will the condition(s) for the trigger look like? (Hint: The EUD value of the address is 339478).
Answer
Quote from Question 4
I have the address 006CDFD4, which is the address for game speed. I want to check if the game speed is at or below Normal speed (3 or less). What will the condition(s) for the trigger look like? (Hint: The EUD value of the address is 331548).
Answer


Post has been edited 13 time(s), last time on Dec 15 2017, 9:47 pm by Roy.




Aug 14 2011, 8:07 pm Roy Post #6

An artist's depiction of an Extended Unit Death

Section 5: Synchronization

There's a lot of talk about how EUDs work. A lot of people want to say that EUDs do not work for multiplayer. These people are liars! Well, not all the time. You know when you see "Player has dropped from the game"? This happens because that player desynchronized from the game. There are some addresses that can explicitly cause such synchronization issues if handled improperly. In this section, you will learn how to handle EUD synchronization properly.


Section 5.1: Why Desynchronization Happens

Let's say you have two players in a game. That game must be identical on both computers. When Player 1 builds a Marine on his computer, Player 2's computer also recognizes that the Marine is building.

So what happens if there's a communication error? Suddenly Player 1's game thinks there's a Marine, and Player 2's game thinks there isn't one. StarCraft doesn't like quantum states, so it splits the one game into two different games. Player 1 goes into Game 1, and Player 2 goes into Game 2. To each other, it appears as though the other player "dropped" from their game. Now, this kind of thing doesn't happen very often, but it can happen easily if an EUD fires on one player's machine and not the other.

Say there's an EUD for screen position. When a player has their screen at the top-left corner, a Marine is created for the player. StarCraft has a screen X position address that all players use, and the value of that address is specific to the player's instance of StarCraft. It is therefore entirely possible for Player 1 to run the trigger without Player 2's game knowing it should run. Player 1 moves his screen to the top left, so the trigger is going to run for him. However, in Player 2's game, Player 2 did NOT move his screen to the top-left, so the trigger does not run for him. When this happens, Player 1's game creates a Marine, but Player 2's game does not. Suddenly, these two games lose synchronization, and StarCraft decides to split them into two separate games; both players drop from each other.

This issue is because an EUD is using a local address and applying a global action.


Section 5.2: Global VS Local Data

Reading a global address is completely safe for multiplayer. Reading a local address and performing only localized actions is also completely safe for multiplayer. The only time a desynchronization can happen is when an EUD is reading a local address and performing a global action. Refer to this matrix:

  • EUDs reading global memory (such as Unit HP) will not cause the game to lose synchronization regardless of the actions. The exception to this is PC and Mac users, as StarCraft's memory is allocated differently between the two platforms.
  • EUDs reading local memory (such as Screen Position) and using local actions (such as Display Text) will not cause the game to lose synchronization, so no players will drop.
  • EUDs reading local memory (such as Key Press) and using global actions (such as Create Unit) will cause the game to lose synchronization, so all players that the EUD ran for will desync from all players that the EUD did not execute for, essentially branching them into two separate games.

So, how do you determine if an address is local data? Well, most global data regarding players will have an address for each player. For example, selection detection is global because there is an address for each of the eight players. However, screen position only has two addresses (for the X and Y position of the screen). Since there isn't separately defined addresses for each player, this is local data. This usually just requires you to look it up or experiment for many ambiguous values, but here are some general guidelines you can follow:

1) All data regarding units (such as HP, Energy, Position, etc.) is global data.
2) All game settings that have to be the same for all players (such as Game Speed, Latency, etc.) can be treated as global data.
3) All game settings that are customizable for all players (such as Game Volume, various UI pieces like portraits, etc.) are local data.
4) All data (the EUDDB usually states this) that has an address for each player is global data.
5) All data in the EUDDB that states it is not shared is local data.

Now how about determining if an action is global or local? Well, if the action causes a physical change in gameplay, it is global. Here is a list of global and local actions:

Global and Local Actions (Credit to FaRTy1billion)

From this list, you should generally understand what it means for an action to be local.


Section 5.3: Macs VS PC

As you may have noticed in 5.2, I threw in a clause about Mac and PC users. An EUD/EPD written for a PC game of StarCraft is not going to work the same for a Mac user playing the same game. This is because the addresses for the PC version and the addresses for the Mac version are not one in the same. An EUD written to check a unit's HP for a PC could very well be checking a display text message for a Mac. This instantly raises the issue of desynchronization.

Hilarious Simulation


A solution to this would be to detect the platform the player is using at the beginning of the game. This could be done by asking the player, "Hey, are you using PC or Mac?" and allow them to step on a beacon for their choice, or, more subtly, use EUDs to check what OS they're using. To do this with EUDs, you just need to check an address where the PC version of the game is guaranteed to have a different value than a Mac. I don't have a particular address in mind, but you could probably use almost any specific address. Try this one:

Trigger
Players
  • All Players
  • Conditions
  • Elapsed scenario time is at most 1 game seconds.
  • Memory at Death Table + -141977 is exactly 1953718604
  • Actions
  • Set Switch 1.


  • The idea is that if Switch 1 is set, the player is using a PC. If Switch 1 is clear, the player is using a Mac. Now you can write platform-specific EUDs: one for Windows, and one for Mac. For example, if you had an EUD checking for a unit's HP, you would have one trigger using the Windows EUD condition along with "Switch 1 is Set," and you would have one trigger using the Mac EUD condition along with "Switch 1 is Cleared." (Good luck writing the Mac trigger if you don't have a Mac, though; the EUDDB currently only has PC addresses).

    Additional explanation: Normally, switches are global game variables, meaning they can ONLY be set or ONLY be cleared for any one game. However, with an EUD like the one above, the game is now technically in different states for PCs and Macs: one that thinks the switch is set (PC), and one that thinks the switch is clear (Mac). If you attempted to make a trigger that creates a unit when Switch 1 is set, it will desync the Mac and PC players when that particular trigger runs. This is exactly why you need to have an EUD for PC players and an EUD for Mac players, so that both games will be in the same physical state, despite having a desynchronization on a particular switch (which won't desync the game on its own, since it is a local action).


    Section 5 Quiz
    Quote from Question 1
    True or False: EUDs do not work for multiplayer.
    Answer
    Quote from Question 2
    True or False: If using a global address along with local actions, players may desync from the game.
    Answer
    Quote from Question 3
    True or False: Creating a unit is a global action.
    Answer
    Quote from Question 4
    True or False: An EUD checking the HP on a Marine owned by Player 1 is reading a local address.
    Answer
    Quote from Question 5
    True or False: An EUD checking a player's screen position is reading a local address.
    Answer
    Quote from Question 6
    True or False: A trigger that creates a unit based on a player's screen position will cause desynchronization.
    Answer
    Quote from Question 7
    True or False: A trigger that displays a text message if a player's music volume is maxed will cause desynchronization.
    Answer


    Post has been edited 24 time(s), last time on May 17 2020, 7:17 pm by Roy.




    Aug 14 2011, 8:07 pm Roy Post #7

    An artist's depiction of an Extended Unit Death

    Section 6: Unit-Specific EUDs

    As you may have deduced at this point, there are a lot of things EUDs can detect in regards to units. But there can be so many units! How can you possibly calculate an EUD for one particular unit on the map? What can be detected? This section will answer those questions.


    Section 6.1: Unit Index IDs

    Each unit placed on a map is assigned an index ID. This ID is purely based on the placement order of units, and has nothing to do with the type of unit, position of the unit, etc. This Index ID, it turns out, is very important when creating EUDs, as we can calculate the position of the address following a formula.

    To figure out the Index ID of any unit on the map, just right-click the unit in SCMDraft and open the properties window. In this window, you'll see the unit highlighted in the table. The last column, labeled "Index," is the Index ID we want. However, it's not always this simple. Here's a couple ways the index value can be incorrect in SCMDraft:
    • SCMDraft assigns an index ID to Start Locations, but the actual game does not. This means if a Start Location was at index 0 and a Marine was at index 1, the Marine's actual index in-game would be Index 0.
    • Any doodad units placed on the map (e.g., a floor gun trap) that is placed as a doodad will not show in SCMDraft's list of units, but it will also be assigned an index ID. Doodad units are assigned IDs before preplaced units are, regardless of whether the doodad was placed before or after the unit(s). For example, if you first place a Marine (shown as index 0), a Floor Gun Trap doodad, and then a Firebat (shown as index 1), the Floor Gun Trap will receive index 0, the Marine will receive index 1, and the Firebat will receive index 2.

    Another thing to remember is that players that are not in the game will not have their units placed. This again alters the actual indexes of preplaced units. For example, if you had placed a Zergling for Players 1-8 as the first units on the map, it would look something like this on the editor:

    Code
    Player 1 Zergling     Index 0
    Player 2 Zergling     Index 1
    Player 3 Zergling     Index 2
    Player 4 Zergling     Index 3
    Player 5 Zergling     Index 4
    Player 6 Zergling     Index 5
    Player 7 Zergling     Index 6
    Player 8 Zergling     Index 7

    But if only Player 3 and Player 7 are in the game when it starts, Player 3's Zergling will have Index 0, and Player 7's Zergling will have Index 1. A way to prevent this issue from occurring is to preplace all of the units for a computer player, and when the game starts, give the units to the players that should actually own them. This preserves the index as seen in the editor and has virtually no effect in gameplay.

    Theoretically, if you can create units in a predictable pattern on the map, units do not have to be preplaced to write EUDs for them. However, I find this practice risky, impractical, and frustrating, and I would advise that you just preplace any units you want to check with EUDs.

    Please note when I refer to "the first unit index," I am talking about unit index 0.


    Section 6.2: Calculating an EUD Based on Unit Index ID

    Once you have the Index ID, you have a starting point to many addresses associated with your particular unit. An excellent resource for this data and equations can be found here: http://www.staredit.net/topic/10471/. In that thread, the addresses and EUD values for the first unit (index 0) are listed. You may notice there are offsets for a lot of the values, even though all addresses end with a 0, 4, 8, or C. Don't think the awesome chart is broken! The addresses are merely separated by lengths of 4, but the values associated with it may actually be an address in between. Take for example this line:
    Code
    59CCB0 19027  HEALTH POINTS: AtLeast 256(x), AtMost 256(x) + 255

    The address for Health Points (HP) is clearly from the second column of the awesome chart since we are multiplying by 256. This means the actual position of HP is the address 59CCB1. But when this address, as well as 59CCB2 and 59CCB3 are converted to an EUD number, they all say the address is equal to 19027. The only notable difference is the byte offset (a.k.a. which column on the awesome chart it falls in). Don't let this topic's choice of displaying data befuddle you.

    Way down at the bottom of the original post, there are some conversion values that I will reiterate here. If your unit's index is 0, you can just look at the values provided in the post (i.e. if you wanted to check the HP of a unit at index 0, just plug in 19027). If you want to calculate a specific EUD for any other unit, here are the steps to take:

    1) Figure out how far from the start of the index your value is. (y = x - 19025)
    2) Calculate the starting EUD value by performing the equation "y = 161825 - 84x," where x is your unit index number.
    3) Add the two numbers from steps 1 and 2 together.

    Well, let's do an example. Let's check when a unit's shield points value is 10 or less. The unit's index ID is 1337. Following the three steps:

    Code
    59CCA8 19025  START OF UNIT INDEX 0 (A.K.A. FIRST UNIT INDEX)
    .
    .
    .
    59CD08 19049  SHIELD POINTS: AtLeast 256(x), AtMost 256(x) + 255


    1) Shield points are at EUD 19049 for unit index 0. The starting point of unit index 0 is 19025.
         y = 19049 - 19025
         y = 24

    2) We use the equation "y = 161825 - 84x" to find the starting point of unit index 1337.
         y = 161825 - 84(1337)
         y = 161825 - 112308
         y = 49517

    3) We add the answers from steps 1 and 2 together.
         y = 24 + 49517
         y = 49541

    Our final answer for the EUD address number is 49541. Now all we need to do is calculate the value; the formula is kindly provided to us from the http://www.staredit.net/topic/10471/ thread. Since we are only concerned with at most 10, we just need one memory condition for at most (10*256)+255 = 2815:
         Memory at Death Table + 49541 is at most 2815

    Now we have our memory condition checking if the unit at index 1337 has shields equal to or below 10.


    Section 6.3: Uniquely Identifying a Unit

    When using EUDs/EPDs, you may notice that you can get a unit's information easily, but what happens if you want to do something to that unit? For example, if your unit's HP is below 10, you want to reset it to full health. The action for this requires a unit type and location. Well, the EUD tells you neither of those things. Hopefully, when you write this EUD, you have a specific, preplaced unit in mind. This takes care of the type. But how do you find this unit in the middle of a game?

    If the unit is in an enclosed area, you can get it knowing it won't leave that location. For example, if you have a Marine that is restricted to a small square box, you can just put a location on that box and say "Set HP of all Terran Marine in SmallBox to 100%."

    If the unit is the only unit type of its kind for the player on the entire map, you can simple specify the "Anywhere" location, the type of unit and the player owner. This will also safely grab the unit.

    But what if you have many Marines owned by one player roaming the map? Your EUD fires because unit index 0 is below 10 HP, but there's no way to be able to pick out that specific Marine in your actions. You'd have to heal every Marine, which is not practical. In this case, you need an artificial system to uniquely identify each Marine you want to check with EUDs. You can read up on http://www.staredit.net/topic/11454/ to see how this is done. With a system like LID, you can associate a specific location with a specific EUD, solving the issue of being unable to find a unit in your actions.


    Section 6 Quiz
    Quote from Question 1
    True or False: A unit's index is based on the x and y coordinates of where that unit is placed.
    Answer
    Quote from Question 2
    True or False: The awesome chart doesn't work for unit addresses.
    Answer
    Quote from Question 3
    I'm writing an EUD to check a unit's kill count. I know the EUD value for the kill count at unit index 0 is 19060, but my unit's index is 42. What is the EUD value for the kill count at unit index 42?
    Answer


    Post has been edited 17 time(s), last time on Dec 15 2017, 9:48 pm by Roy.




    Aug 14 2011, 8:07 pm Roy Post #8

    An artist's depiction of an Extended Unit Death

    Section 7: Text-Based EUDs

    I'm sure some of you have thought, "How cool would it be to have a StarCraft game where players can type commands and things would happen?" If your plan is to make a text-input game using EUDs, this next section is going to be full of anguish and disappointment for you. I really do not see any practical implementation of Display Text EUDs, and this section is primarily just an educational resource. Don't get me wrong: you can still do some very useful things using text detection. Checking to see if a particular player is in the game, for example, is not too difficult to implement. (Oh, the hilarity of writing an EUD that drops/defeats certain usernames each time they try to play!)


    Section 7.1: Calculating the Value of Text

    The original resource I used to first learn text calculation is no longer existent. But! Since then, there have been programs written that will do this tedious calculation for you. If you already acquired or looked at the text resources from Section 2, you may have read how text detection works. For those who did not see it and/or like to read:
    Manual Calculation


    Also, for those of you crazy enough to dream, yoonkwun wrote a program that will generate universal triggers for player chat. You can find this here: http://www.staredit.net/topic/11426/. I will lightly touch on this in a bit more detail in segment 7.4.


    Section 7.2: The 11 Addresses

    Assuming you want to read from "Display Text Message" type text, you will require 11 triggers to check for one string. That's right. If you want to read when "Hello there" is on the screen, you have to write 11 triggers for it. Why? Because each of the 11 chat rows in SC has its own address, and in order to ensure that the message will not be missed, each address needs to check for the message.

    From the EUDDB entry, we can see that this madness starts at EUD 186879. The following EUD values are +55 values apart from each other. Here is a list of all EUD values for display text:

    Code
    186879     ROW 1
    186934     ROW 2
    186988     ROW 3
    187043     ROW 4
    187097     ROW 5
    187152     ROW 6
    187206     ROW 7
    187261     ROW 8
    187315     ROW 9
    187370     ROW 10
    187424     ROW 11


    An interesting thing to note is that the very first line in-game is actually ROW 11, and the second chat line is in fact ROW 1. This won't be a concern if you write triggers for all rows, though.

    Now, how do these rows work? Well, say a player named "Ike" types "Hello" right when the map starts. ROW 11 gets populated with the text "Ike: Hello" immediately, and ROW 1 becomes the next chat line that will be populated. If Ike is a bit of a spammer and says "World," "How," "Goes," and "It?" afterward, then ROW 1 will have "Ike: World," ROW 2 will have "Ike: How," ROW 3 will have "Ike: Goes," ROW 4 will have "Ike: It?," and ROW 5 will be the next chat line that will be populated. The next chat line is always determined by the number of messages that have occurred, not by where they are displayed on the screen. (For those interested, the address 0x640B58 / EUD 186877 will store the value of which row will be the next chat line.)

    There's an additional thing to note here: every even row (2, 4, 6, 8, 10) is offset by two characters. This means if you were reading the string "Hello there," these rows would be reading "llo there."

    So, what can we take from this? It's really annoying to make these kinds of EUDs. But hey, if your Display Text Message action just spams the same thing on all 11 rows, you'd only need to check one row for the value. So there's that.

    Well, how would we write EUDs to check the text "Hello there"? We have the EUD values, and we have converters to convert the text into a number to evaluate. Let's get to it. Using a text converter, we get:

    Code
    ODD ROWS:
    "Hell" -> 1819043144
    "o th" -> 1752440943
    "ere" -> 6648421

    EVEN ROWS:
    "llo " -> 544173164
    "ther" -> 1919248500
    "e" -> 101


    Now, for each group of four letters after the first, we add one to the memory value we're using. For example, if we were reading from ROW 1, we would check:

    186879 for "Hell"
    186880 for "o th"
    186881 for "ere"

    Do you want to see what the complete trigger set looks like to check "Hello there"? Do you really? ... Alright, but you've been warned:

    Detecting "Hello there"

    When Switch 1 is set, you'll know that your text appeared. Do you see why hardly anyone uses Display Text for practical applications? It's bulky, annoying, error-prone, inefficient, and messy.

    More Advanced Stuff


    Section 7.3: The Null Character

    If you're ready for some more punishment, I have good news. StarCraft does not reset the text at addresses for Display Text, but rather just overwrites what it needs to. Say, for example, someone typed something like this:

    Code
    Roy: Seriously, text detection is the worst thing ever.

    Now say, 11 chat lines later, someone named Marth says "Ugh." in chat. Here's what StarCraft will do:

    Code
    Marth: Ugh.�ly, text detection is the worst thing ever.


    See what happened? StarCraft wrote over the beginning of the row, but left the rest of it there! You may notice a strange symbol after Marth's message before Roy's old message appears. This represents the null character; all chat lines in SC terminate with a null character, which has a value of 0. If SC completely wiped the row with null characters, Roy's old text wouldn't exist, and we wouldn't have any concern about it. However, this is not the case, and issues immediately arise. (P.S.: text detection is "Ughly" :awesome:)

    Now you have a problem. If you were checking a one or two letter phrase, you have to check a range of values, because some leftover text from another chat line may change the exact value. Or, as an easier alternative, you can just create padding at the end of each Display Text (i.e. putting a few spaces at the end of it), and then just calculate the end of your phrase with spare spaces to fit the last group into an even size of 4 characters. For example, if you were checking for the phrase "Hello," it splits into two groups: "Hell" and "o"; adding three spaces will make the last group turn into "o   " to bring it to an even size of 4 characters. Now, there is no possible way this will have a variance in value, regardless of leftover text from older chat.


    Section 7.4: Detecting Player Chat

    If you still haven't lost hope on making a player chat trigger system, you are either very brave or very stupid; regardless, this segment should be the final blow.

    Say you want to be picky, for simplicity's sake: you want a map that only checks for a command given by you. For example, I want an extra life when I type "1up" into chat. Well, the first thing I have to do is detect my name (Roy), followed by the characters in between my name and my text, and finally my text (1up). But what are the characters in between? It looks like a colon and a space, which it is, but there is another key element hidden in there: a color character.

    So, what is the color character? It depends. For the person who typed it, it is green. For the other players in the game, it is blue. You know what this means? You actually need 22 triggers for each phrase you're trying to detect! I shit you not. You need 11 triggers for you, the player typing the message, because your text shows up as green to you. You also need 11 triggers for all the other players, because your text shows up as blue for them. So, for the person typing the text, there needs to be a trigger reading:

    Code
    Roy: 1up

    And for the other players, there needs to be a trigger reading:

    Code
    Roy: 1up

    (Don't let your eyes fool you; these are not the same phrase)
    The first trigger phrase has the character , which in SCMDraft, equates to <07>, or green.
    The second trigger phrase has the character , which in SCMDraft, equates to <02>, or cyan.

    (Note: EUD Text To Value doesn't support entering these characters; you can use Farty's Calculator for these calculations, however.)

    This is the procedure you would use for making an EUD for a specific username (don't forget about padding!). Now what if you just want to check if anyone types "1up"? Well, this brings us down another level of Dante's Inferno. Please refer back to yoonkwun's program for general info on this feat. As this is intended to be a beginner's guide, I am not going to go into this advanced subject.


    Section 7 Quiz
    Quote from Question 1
    True or False: In order to perfectly detect text from a one-line Display Text Message, 11 triggers are required.
    Answer
    Quote from Question 2
    I have the string "Hello World!" and I want to detect it on Row 5 (which starts at EUD 186927). I have the values 1819043144 for "Hell," 1867980911 for "o Wo," and 560229490 for "rld!." What will my conditions look like?
    Answer
    Quote from Question 3
    True or False: Padding is when you add spaces to the end of the display text to prevent the EUD from not working when it should.
    Answer


    Post has been edited 15 time(s), last time on Apr 26 2014, 5:32 pm by Roy.




    Aug 14 2011, 8:07 pm Roy Post #9

    An artist's depiction of an Extended Unit Death

    Section 8: Closing

    Well, that just about covers all the information you need for understanding EUDs/EPDs. Remember that stumbling across issues is common, and that hilarity may or may not ensue if you've miscalculated something.


    Section 8.1: Other Useful Resources

    Riddled throughout this tutorial, I mentioned some resources that you will find invaluable. Here is a short list of links that you may need at some point in time:


    Section 8.2: Credits and Acknowledgements

    The content here was all written by me unless otherwise stated, but I didn't come all this way by myself, you know. SEN is where I began to learn and understand EUDs, and I'd like to acknowledge individuals that directly or indirectly helped me:
    • FaRTy1billion, for building an incredible database for EUD addresses, and writing many helpful tools (EUDTrig, EUD Action Enabler, String Chunk Calculator, etc.). His drop-ban system was one of the first EUDs I've seen.
    • rockz, for providing immense amount of information in the UMS Assistance topics; he was usually the first to respond to any EUD-related topics in the past. He has explained many concepts in a clear and understandable manner to me, and I would not have gone far without this information.
    • yoonkwun, for creating and organizing the EUD Reference topic in addition to helpful, specific EUD topics, and for writing the Text Detection Application for player chat. I found his Unit Direction Detection topic invaluable in particular when making my Fireball map.
    • Heinermann, for understanding memory allocation and SC in general more than I probably ever will.
    • All my StarCraft friends, for helping me test and experiment with EUDs.
    • All authors cited (either directly or indirectly) within this tutorial.


    Section 8.3: Frequently Asked Questions

    Since I've had the audacity to quiz you guys after every section, I think it's only fair if I leave a segment where you can ask me questions. Here's a list of questions I've seen asked on occasion. I will likely add any general questions that may pop up as time progresses.

    Quote
    I wrote the EUD but it doesn't work!
    First off, that's not a question. Secondly, you likely made a mistake somewhere down the line of converting values. The first and easiest check would be to open up SC and Cheat Engine (or your preferred memory scanner) and actually check that the address you added is correct and providing the expected output. Farty's EUDTrig can convert an EUD value back into an address (just be sure to set the output to hex under "Options"), which you can then add into Cheat Engine. If the address is not giving the expected value when you're playing your game, there's two possibilities:

    1) It's the wrong address
    2) You're not calculating the value correctly

    If you pulled the address from the EUDDB, it is most likely the second issue. If you found the address yourself, try checking the EUDDB to see if the address is already documented.

    Quote
    Why does my game crash me when I try using this EUD/EPD?
    Why does my game crash other players when I try using this EUD/EPD?
    On occasion, you may stumble across an address that causes SC to crash you or other players when trying to read the conditions for the trigger. This would be the only time an EUD/EPD crashes SC (as opposed to just desynchronizing, which is covered in Section 5). This issue here is that you're trying to read an address where memory is allocated dynamically, meaning its location can be different per game/per instance/per computer. If your address is not between the range of 0x00401000 and 0x006DD694 (thanks to Heinermann for the approximate range), then it is very likely that the address cannot be used safely as an EPD.

    All I can say is that you have to pick a different address, as the one you're trying to use is not going to work.

    Quote
    Why do my friends drop when I try using this EUD/EPD?
    As covered in Section 5, players desync from EUDs/EPDs when a local address is being evaluated to do a global action. Check your condition; is it a local address (this is pretty much guaranteed in this kind of scenario)? Now check your actions; are there any actions that affect the game state, even indirectly? If you're pausing a countdown timer, that alone doesn't cause a desync, but look at what that countdown timer does. If when it expires, it creates a unit or something, then that's an issue: one player will still have some time on the timer, while the other players have the timer expired. Therefore, the unit is created for everyone except the one player, making the player drop from the others.

    Post has been edited 15 time(s), last time on Apr 26 2014, 5:34 pm by Roy.




    Aug 14 2011, 8:10 pm xAngelSpiritx Post #10

    eternal lurker

    First :bleh: .

    Impressive reference and guide! I haven't finished looking through it all yet (since it was posted about 30 seconds ago) but I nominate this topic to be pinned, or at least added to the EUD resources links.



    None.

    Aug 14 2011, 8:17 pm FoxWolf1 Post #11



    Given how many people ask EUD-related questions, this should probably be stickied at the top of the SC1 map-making assistance forum.



    None.

    Aug 14 2011, 8:24 pm Sacrieur Post #12

    Still Napping

    Best. Thing. Ever.



    None.

    Aug 14 2011, 8:39 pm iCCup.xboi209 Post #13



    Section 4 goes off the website and creates a horizontal scroll bar



    None.

    Aug 14 2011, 8:51 pm Sacrieur Post #14

    Still Napping

    Quote from name:xboi209
    Section 4 goes off the website and creates a horizontal scroll bar

    Yeah, someone needs to fix that link =P



    None.

    Aug 14 2011, 9:03 pm samsizzle Post #15



    This is so badass... seriously Roy, terrific job.



    None.

    Aug 15 2011, 1:32 am Oh_Man Post #16

    Find Me On Discord (Brood War UMS Community & Staredit Network)

    Sticky this NOW!!




    Aug 15 2011, 1:46 am Roy Post #17

    An artist's depiction of an Extended Unit Death

    Quote from xAngelSpiritx
    I haven't finished looking through it all yet (since it was posted about 30 seconds ago) but I nominate this topic to be pinned, or at least added to the EUD resources links.
    Quote from FoxWolf1
    Given how many people ask EUD-related questions, this should probably be stickied at the top of the SC1 map-making assistance forum.
    Quote from Oh_Man
    Sticky this NOW!!
    I don't know how SEN regards pinning topics, but I've always followed a "don't sticky your own work" ideology. Also, FoxWolf, I feel that tutorials and explanations are more suited for this section, even if it would prove invaluable to some related Assistance topics.

    I appreciate the support, though. ^^ And don't forget that I am willing to update this tutorial if you guys need more clarification on a particular topic covered here. Suggestions are welcome.

    Quote from name:xboi209
    Section 4 goes off the website and creates a horizontal scroll bar
    That doesn't happen in the Epic skin. I assume it was the link as Sacrieur mentioned, and it should be fixed now.




    Aug 15 2011, 3:28 am TiKels Post #18



    How many minerals did you get for this? It's pretty impressive and will make 90% of EUD topics a breeze to troubleshoot.



    "If a topic that clearly interest noone needs to be closed to underline the "we don't want this here" message, is up to debate."

    -NudeRaider

    Aug 15 2011, 5:14 am xAngelSpiritx Post #19

    eternal lurker

    Roy mentioned somewhere that he got around 150 minerals. But now that I look, I can't find the post in question...



    None.

    Aug 15 2011, 5:28 am Roy Post #20

    An artist's depiction of an Extended Unit Death

    Quote from TiKels
    How many minerals did you get for this? It's pretty impressive and will make 90% of EUD topics a breeze to troubleshoot.
    Quote from xAngelSpiritx
    Roy mentioned somewhere that he got around 150 minerals. But now that I look, I can't find the post in question...
    It was a shout. I got between 100-150 for the post, but most of it came from kind donators (Sacrieur and Devourer).

    But please try to keep the discussion on the tutorial itself. ^^




    Options
    Pages: 1 2 34 >
      Back to forum
    Please log in to reply to this topic or to report it.
    Members in this topic: None.
    [11:50 pm]
    O)FaRTy1billion[MM] -- nice, now i have more than enough
    [11:49 pm]
    O)FaRTy1billion[MM] -- if i don't gamble them away first
    [11:49 pm]
    O)FaRTy1billion[MM] -- o, due to a donation i now have enough minerals to send you minerals
    [03:26 am]
    O)FaRTy1billion[MM] -- i have to ask for minerals first tho cuz i don't have enough to send
    [2024-4-17. : 1:53 am]
    Vrael -- bet u'll ask for my minerals first and then just send me some lousy vespene gas instead
    [2024-4-17. : 1:52 am]
    Vrael -- hah do you think I was born yesterday?
    [2024-4-17. : 1:08 am]
    O)FaRTy1billion[MM] -- i'll trade you mineral counts
    [2024-4-16. : 5:05 pm]
    Vrael -- Its simple, just send all minerals to Vrael until you have 0 minerals then your account is gone
    [2024-4-16. : 4:31 pm]
    Zoan -- where's the option to delete my account
    [2024-4-16. : 4:30 pm]
    Zoan -- goodbye forever
    Please log in to shout.


    Members Online: Roy, Ultraviolet, RIVE