[EUD] A Mapmaker's Guide for Creating EPDs, The thread for all your EUD needs
Post #1
Roy
Aug 14 2011, 8:00 pm
|
Everything green is safe to eat.
|
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 EPD triggers, but they are able to create EPDs whenever they need to. This guide is meant to be used to build a foundation of knowledge on EPDs.
Contents: Section 1: Introduction 1.1: What Is an EPD? 1.2: What's the Difference Between an EUD and EPD? 1.3: Why Should I Use an EPD? 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 EPD 3.1: Getting an Address 3.2: Converting the Address 3.3: Creating the Trigger Section 4: Variations in EPD Creation 4.1: Manually vs Automatically Finding an Address 4.2: Finding the Correct Value of an Address 4.3: EPDs 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 EPDs 6.1: Unit Index IDs 6.2: Calculating an EPD Based on Unit Index ID 6.3: Uniquely Identifying a Unit Section 7: Text-Based EPDs 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. This post was edited 4 times, last edit by Roy: Aug 27 2011, 10:21 pm. ![]() ![]() ![]() ![]() ![]() ![]() Learn how to make EUDs: [EUD] A Mapmaker's Guide for Creating EPDs
Don't like learning? [EUD] EUD Generator Other stuff: [EUD] Text to Value Converter Bound Maker SC1 Maps: Dash: 1 2 3 4 5 6 7 8 9 X Jog: Original Warp Other: Super Mario SC Fireball Guard Your Civilian Strength Contest Interceptor Arena |
Post #2
Roy
Aug 14 2011, 8:06 pm
|
Everything green is safe to eat.
|
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 compromise because the editor wouldn't allow them to do many things it doesn't have direct support for. After the discovery of Extended Unit Deaths, mappers can extend these capabilities to accomplish things that were once not possible. Section 1.1: What Is an EPD? An Extended Player Death (EPD) is a term used to describe overflowing the player 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 times a Marine has died, 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 and are more used to hearing about the wonders of EUDs (Extended Unit Deaths). 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). 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. You can consider these two terms interchangeable here. Section 1.3: Why Should I Use an EPD? You've probably gone this far as a mapper without ever needing to use an EPD, so why start? To be honest, there's no reason to start until you need to do something that cannot be done without EPDs, or when using EPDs would significantly improve your game. They can be used to detect HP, selection, screen position, game speed, text on the screen, if a player is hacking, keys pressed on a keyboard, and more! EPDs 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 This post was edited 5 times, last edit by Roy: May 5 2012, 3:20 pm. ![]() ![]() ![]() ![]() ![]() ![]() Learn how to make EUDs: [EUD] A Mapmaker's Guide for Creating EPDs
Don't like learning? [EUD] EUD Generator Other stuff: [EUD] Text to Value Converter Bound Maker SC1 Maps: Dash: 1 2 3 4 5 6 7 8 9 X Jog: Original Warp Other: Super Mario SC Fireball Guard Your Civilian Strength Contest Interceptor Arena |
Post #3
Roy
Aug 14 2011, 8:06 pm
|
Everything green is safe to eat.
|
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 (a.k.a. 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 grow up.) 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 You might be wondering what a memory scanner is and why you need it. Well, as I explained earlier, EPDs are used to read data in StarCraft that you can't normally get to. The first step to making an EPD 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 EPD. 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. If you fancy some assistance in calculating text with EUDs, you can either check out [EUD] Text to Value Converter or use Farty's online calculator. Section 2 Quiz This post was edited 7 times, last edit by Roy: Aug 15 2011, 4:40 pm. ![]() ![]() ![]() ![]() ![]() ![]() Learn how to make EUDs: [EUD] A Mapmaker's Guide for Creating EPDs
Don't like learning? [EUD] EUD Generator Other stuff: [EUD] Text to Value Converter Bound Maker SC1 Maps: Dash: 1 2 3 4 5 6 7 8 9 X Jog: Original Warp Other: Super Mario SC Fireball Guard Your Civilian Strength Contest Interceptor Arena |
Post #4
Roy
Aug 14 2011, 8:06 pm
|
Everything green is safe to eat.
|
Section 3: Making Your First EPD If you've made it this far, you're probably ready to write your very own EPD. 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. Section 3.1: Getting an Address 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 start up "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 EPD. 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 EPDs, 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 EPD! 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 EPD, and it is not necessary for it to be a practical condition. Section 3 Quiz This post was edited 11 times, last edit by Roy: Jan 1 2012, 4:52 am. ![]() ![]() ![]() ![]() ![]() ![]() Learn how to make EUDs: [EUD] A Mapmaker's Guide for Creating EPDs
Don't like learning? [EUD] EUD Generator Other stuff: [EUD] Text to Value Converter Bound Maker SC1 Maps: Dash: 1 2 3 4 5 6 7 8 9 X Jog: Original Warp Other: Super Mario SC Fireball Guard Your Civilian Strength Contest Interceptor Arena |
Post #5
Roy
Aug 14 2011, 8:07 pm
|
Everything green is safe to eat.
|
Section 4: Variations in EPD Creation Well, you've seen a nice, simple way to detect something using EPDs. Section 3 shouldn't have been overwhelming, and if you didn't understand it, you shouldn't continue until you have. Not all EPDs are this nice and straightforward; there are many factors and issues that can arise, such as byte offsets. Also, not all EPDs 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: CodeByte 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 EPD 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. 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: Code0 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: EPDs 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: Code0 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 This post was edited 11 times, last edit by Roy: Apr 4 2012, 5:50 am. ![]() ![]() ![]() ![]() ![]() ![]() Learn how to make EUDs: [EUD] A Mapmaker's Guide for Creating EPDs
Don't like learning? [EUD] EUD Generator Other stuff: [EUD] Text to Value Converter Bound Maker SC1 Maps: Dash: 1 2 3 4 5 6 7 8 9 X Jog: Original Warp Other: Super Mario SC Fireball Guard Your Civilian Strength Contest Interceptor Arena |
Post #6
Roy
Aug 14 2011, 8:07 pm
|
Everything green is safe to eat.
|
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 EPD 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 EPD 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 EPD is reading a local address and performing a global action. Refer to this matrix: ![]()
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.) are 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: 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 EPD 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. 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 EPDs to check what OS they're using. To do this with EPDs, 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:
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 EPDs: one for Windows, and one for Mac. For example, if you had an EPD checking for a unit's HP, you would have one trigger using the Windows EPD condition along with "Switch 1 is Set," and you would have one trigger using the Mac EPD 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 EPD 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 EPD for PC players and an EPD 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 This post was edited 19 times, last edit by Roy: Mar 22 2012, 1:37 am. ![]() ![]() ![]() ![]() ![]() ![]() Learn how to make EUDs: [EUD] A Mapmaker's Guide for Creating EPDs
Don't like learning? [EUD] EUD Generator Other stuff: [EUD] Text to Value Converter Bound Maker SC1 Maps: Dash: 1 2 3 4 5 6 7 8 9 X Jog: Original Warp Other: Super Mario SC Fireball Guard Your Civilian Strength Contest Interceptor Arena |
Post #7
Roy
Aug 14 2011, 8:07 pm
|
Everything green is safe to eat.
|
Section 6: Unit-Specific EPDs As you may have deduced at this point, there are a lot of things EPDs can detect in regards to units. But there can be so many units! How can you possibly calculate an EPD 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 EPDs, 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:
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: CodePlayer 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 affect in gameplay. Theoretically, if you can create units in a predictable pattern on the map, units do not have to be preplaced to write EPDs 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 EPDs. Please note when I refer to "the first unit index," I am talking about unit index 0. Section 6.2: Calculating an EPD 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: Useful EUD Reference. In that thread, the addresses and EPD 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: Code59CCB0 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 EPD 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 EPD 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 EPD 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: Code59CCA8 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 EPD 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 EPD address number is 49541. Now all we need to do is calculate the value; the formula is kindly provided to us from the Useful EUD Reference 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 EPD tells you neither of those things. Hopefully, when you write this EPD, 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 EPD 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 EPDs. You can read up on Location Identification (LID) to see how this is done. With a system like LID, you can associate a specific location with a specific EPD, solving the issue of being unable to find a unit in your actions. Section 6 Quiz This post was edited 14 times, last edit by Roy: Apr 11 2012, 1:50 am. Reason given: Added details regarding doodad units ![]() ![]() ![]() ![]() ![]() ![]() Learn how to make EUDs: [EUD] A Mapmaker's Guide for Creating EPDs
Don't like learning? [EUD] EUD Generator Other stuff: [EUD] Text to Value Converter Bound Maker SC1 Maps: Dash: 1 2 3 4 5 6 7 8 9 X Jog: Original Warp Other: Super Mario SC Fireball Guard Your Civilian Strength Contest Interceptor Arena |
Post #8
Roy
Aug 14 2011, 8:07 pm
|
Everything green is safe to eat.
|
Section 7: Text-Based EPDs 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 EPDs, 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 education 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 EPD 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: 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: Text Detection Application. 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 EPD 186879. The following EPD values are +55 values apart from each other. Here is a list of all EPD values for display text: Code186879 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. 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 EPDs. 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 EPDs to check the text "Hello there"? We have the EPD 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: CodeODD 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: 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. 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: CodeRoy: 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: CodeMarth: 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" )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: CodeRoy: 1up And for the other players, there needs to be a trigger reading: CodeRoy: 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 EPD 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 This post was edited 8 times, last edit by Roy: Oct 14 2011, 12:57 pm. ![]() ![]() ![]() ![]() ![]() ![]() Learn how to make EUDs: [EUD] A Mapmaker's Guide for Creating EPDs
Don't like learning? [EUD] EUD Generator Other stuff: [EUD] Text to Value Converter Bound Maker SC1 Maps: Dash: 1 2 3 4 5 6 7 8 9 X Jog: Original Warp Other: Super Mario SC Fireball Guard Your Civilian Strength Contest Interceptor Arena |
Post #9
Roy
Aug 14 2011, 8:07 pm
|
Everything green is safe to eat.
|
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:
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. 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 EPD 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. 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. 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. This post was edited 13 times, last edit by Roy: May 6 2012, 5:43 pm. ![]() ![]() ![]() ![]() ![]() ![]() Learn how to make EUDs: [EUD] A Mapmaker's Guide for Creating EPDs
Don't like learning? [EUD] EUD Generator Other stuff: [EUD] Text to Value Converter Bound Maker SC1 Maps: Dash: 1 2 3 4 5 6 7 8 9 X Jog: Original Warp Other: Super Mario SC Fireball Guard Your Civilian Strength Contest Interceptor Arena |
Post #10
xAngelSpiritx
Aug 14 2011, 8:10 pm
Post #17
Roy
Aug 15 2011, 1:46 am
|
Everything green is safe to eat.
|
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.That doesn't happen in the Epic skin. I assume it was the link as Sacrieur mentioned, and it should be fixed now. ![]() ![]() ![]() ![]() ![]() ![]() Learn how to make EUDs: [EUD] A Mapmaker's Guide for Creating EPDs
Don't like learning? [EUD] EUD Generator Other stuff: [EUD] Text to Value Converter Bound Maker SC1 Maps: Dash: 1 2 3 4 5 6 7 8 9 X Jog: Original Warp Other: Super Mario SC Fireball Guard Your Civilian Strength Contest Interceptor Arena |
Post #19
xAngelSpiritx
Aug 15 2011, 5:14 am
Post #20
Roy
Aug 15 2011, 5:28 am
|
Everything green is safe to eat.
|
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. ![]() ![]() ![]() ![]() ![]() ![]() Learn how to make EUDs: [EUD] A Mapmaker's Guide for Creating EPDs
Don't like learning? [EUD] EUD Generator Other stuff: [EUD] Text to Value Converter Bound Maker SC1 Maps: Dash: 1 2 3 4 5 6 7 8 9 X Jog: Original Warp Other: Super Mario SC Fireball Guard Your Civilian Strength Contest Interceptor Arena |
0 members in this topic (italic members are currently writing a reply): None
+ guest(s)
+ guest(s)
Please log in to shout.













)
.
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.
![[close]](/images/up.gif)