Staredit Network > Forums > SC1 UMS Theory and Ideas > Topic: EUDs Demystified
EUDs Demystified
Sep 19 2014, 7:15 am
By: sigsaucy2  

Sep 19 2014, 7:15 am sigsaucy2 Post #1



Whenever I've seen EUDs discussed on this forum they've always seen limited by

-only being able to modify preplaced units
-(sometimes?) requiring an eud enabler

but then i ran across the attached map on the fish server and now i know you guys were all lieing!!!!!!!!!! just look at that scv's attack! Almost every unit on this map has a changed attack and are buildable.

so what exactly is the deal?

When can EUD's be used? What exactly are their limitations? Are the Koreans ahead of us in EUD implementation?

Attachments:



None.

Sep 19 2014, 9:20 am trgk Post #2



Almost every Korean runs EUDA enabler. That's all.

Post has been edited 3 time(s), last time on Sep 19 2014, 9:32 am by trgk.



EUD

Sep 19 2014, 10:38 am Roy Post #3

An artist's depiction of an Extended Unit Death

Quote from sigsaucy2
-only being able to modify preplaced units
Nobody has made this claim, as far as I'm aware, and I'd have corrected them if they had. I mean, EUD Actions (EUDAs) can modify things other than units, so it's demonstrably untrue, but they can also modify properties on the unit type, which would change values for every unit of that type.

Quote from sigsaucy2
-(sometimes?) requiring an eud enabler
Bingo. I've been told Fish server has an enabler built into it, unlike the regular Battle.net servers. On a regular server, the SCV does a normal attack (unless you run an action enabler, in which case, the EUDA setting its attack to glave wurm runs). There's no mystification here: it works exactly how we've told you it works.

To clarify the "sometimes?", since you seem to be confused:

EUD Conditions (which we usually just refer to as EUDs) do not require an EUD Action Enabler. They will work as-is.
EUD Actions (which we sometimes shorten to EUDAs for differentiating from regular EUDs) require an EUD Action Enabler. They will not do anything otherwise.
EUPs (Extended Unit Placements) can be used to achieve the same effect as EUDAs, but they're tricky to handle. See A Practical Guide to EUPs for more info.

Quote from sigsaucy2
so what exactly is the deal?
Here's a quick dump of the EUDAs the map is using:
Code
Set Deaths("Player 3", "Int:18432", Add, 1280);
Set Deaths("Player 2", "Int:17416", Add, 768);
Set Deaths("Player 2", "Int:17475", Set To, 1);
Set Deaths("Player 4", "Int:17474", Set To, 16777216);
Set Deaths("Player 7", "Int:17474", Set To, 65536);
Set Deaths("Player 10", "Int:17474", Set To, 1);
Set Deaths("Player 4", "Int:18611", Subtract, 39);
Set Deaths("Player 10", "Int:18535", Subtract, 16);
Set Deaths("Player 5", "Int:18587", Add, 4);
Set Deaths("Player 9", "Int:18625", Add, 16777216);
Set Deaths("Player 3", "Int:18318", Add, 1310720);
Set Deaths("Player 2", "Int:18535", Add, 2560);
Set Deaths("Player 11", "Int:18535", Subtract, 8704);
Set Deaths("Player 5", "Int:18536", Subtract, 720896);
Set Deaths("Player 6", "Int:18536", Subtract, 3145728);
Set Deaths("Player 5", "Int:18536", Subtract, 40);
Set Deaths("Player 7", "Int:18536", Add, 637534208);
Set Deaths("Player 1", "Int:17472", Add, 9);
Set Deaths("Player 5", "Int:17474", Add, 1);
Set Deaths("Player 11", "Int:18587", Add, 32768);
Set Deaths("Player 6", "Int:18587", Add, 4);
Set Deaths("Player 9", "Int:18537", Subtract, 50);
Set Deaths("Player 3", "Int:18535", Add, 587202560);
Set Deaths("Player 4", "Int:18536", Add, 9999999);
Set Deaths("Player 5", "Int:18592", Set To, 402718720);
Set Deaths("Player 7", "Int:18536", Add, 458752);
Set Deaths("Player 9", "Int:18612", Subtract, 25);
Set Deaths("Player 5", "Int:18536", Subtract, 16128);
Set Deaths("Player 2", "Int:18611", Subtract, 70);
Set Deaths("Player 6", "Int:18611", Subtract, 1409286144);
Set Deaths("Player 11", "Int:18236", Add, 16777216);
Set Deaths("Player 7", "Int:18432", Add, 1280);
Set Deaths("Player 10", "Int:18625", Add, 16777216);
Set Deaths("Player 5", "Int:18318", Add, 1966080);
Set Deaths("Player 2", "Int:18611", Add, 100663296);
Set Deaths("Player 5", "Int:18611", Subtract, 33);
Set Deaths("Player 2", "Int:18535", Add, 1441792);
Set Deaths("Player 11", "Int:18535", Subtract, 369097852);
Set Deaths("Player 7", "Int:18536", Add, 25);
Set Deaths("Player 2", "Int:18535", Add, 50);
Set Deaths("Player 4", "Int:18365", Add, 50);
Set Deaths("Player 6", "Int:18538", Subtract, 3801088);
Set Deaths("Player 8", "Int:18368", Subtract, 3866624);
Set Deaths("Player 6", "Int:18535", Add, 7);
Set Deaths("Player 8", "Int:18536", Add, 402653184);
Set Deaths("Player 7", "Int:18535", Add, 14848);
Set Deaths("Player 9", "Int:18365", Add, 15104);
Set Deaths("Player 8", "Int:18365", Add, 7);
Set Deaths("Player 4", "Int:18535", Add, 4521984);
Set Deaths("Player 2", "Int:18588", Add, 32772);
Set Deaths("Player 3", "Int:18535", Add, 150994944);
Set Deaths("Player 3", "Int:18535", Subtract, 587202560);
Set Deaths("Player 3", "Int:18535", Subtract, 150994944);
Set Deaths("Player 3", "Int:18535", Add, 1140850688);
Set Deaths("Player 3", "Int:18535", Subtract, 1140850688);
Set Deaths("Player 3", "Int:18535", Add, 1610612736);
Set Deaths("Player 3", "Int:18535", Subtract, 1610612736);
Set Deaths("Player 3", "Int:18535", Add, 1375731712);
Set Deaths("Player 3", "Int:18535", Subtract, 1375731712);
Set Deaths("Player 3", "Int:18535", Add, 301989888);
Set Deaths("Player 7", "Int:17528", Set To, 3);
Set Deaths("Player 1", "Int:18593", Add, 32768);
Set Deaths("Player 11", "Int:17428", Set To, 10);
Set Deaths("Player 4", "Int:17429", Subtract, 234881024);
Set Deaths("Player 2", "Int:18590", Add, 32964);
Set Deaths("Player 7", "Int:18535", Add, 99);
Set Deaths("Player 8", "Int:17530", Set To, 3);
Set Deaths("Player 9", "Int:18365", Add, 99);
Set Deaths("Player 4", "Int:17428", Add, 5);
Set Deaths("Player 4", "Int:17428", Add, 512);
Set Deaths("Player 4", "Int:17428", Add, 786432);
Set Deaths("Player 10", "Int:18531", Subtract, 83886080);
Set Deaths("Player 6", "Int:18530", Add, 131072);
Set Deaths("Player 12", "Int:18530", Add, 65536);
Set Deaths("Player 11", "Int:27271", Add, 15000);
Set Deaths("Player 4", "Int:27287", Add, 15000);
Set Deaths("Player 3", "Int:18537", Subtract, 45);
Set Deaths("Player 5", "Int:18367", Subtract, 45);
Set Deaths("Player 3", "Int:18535", Add, 46);

As you can see, there's no magic here: regular EUDAs manipulating values. Apparently my program dump hasn't been configured to automatically convert EUDAs to their address values, but manual checks with EUDTrig suggest the majority of these are in the Unit Node table (just before the Unit Struct table in memory). It seems as though they're modifying the unit types to have different properties, as opposed to individual units.

There are a couple exceptional EUDs, though, near the bottom of the list, modifying addresses 0x653304 and 0x6535E8. The EUDDB doesn't have documentation for this area, but it's located somewhere after the trigger execution counter.

Quote from sigsaucy2
When can EUD's be used?
EUD Conditions can be used anytime, and EUD Actions can be used if you have an enabler.

Quote from sigsaucy2
What exactly are their limitations?
Short answer: EUD Conditions are limitless, and EUD Actions simply require an enabler.

Long answer: review Section 1 and Section 5 of A Mapmaker's Guide for Creating EUDs to understand the usage and limitations of EUDs.

Quote from sigsaucy2
Are the Koreans ahead of us in EUD implementation?
Depends on what you mean by "implementation": as far as testing and pushing the limits on how we can use EUDs, we've always been the pioneers. But I know China, for instance, has more sophisticated tools for building EUD systems than we do, and Korea likely has more/better documentation oriented toward EUDs than we do.




Sep 19 2014, 8:16 pm sigsaucy Post #4



just to clarify

EUD conditions- these are just conditions that check things we usually can't check right? things like unit energy, upgrade level and such?

EUD actions- these are actions we cant usually preform? like modifying upgrade levels, changing weapons etc?

EUD actions (conditions) are those preformed by setting (checking) death table values to (for) certain values

EUP's- these are actions set by placing extended units at beginning of the map, they dont require any enabler, they can be used to modify unit stats, but you are limited to units you can preplace when creating the map (although you can still preform actions by giving units from one player to another and killing them)

As far as when to choose one over the other

EUP's seem to be more suited towards preforming actions that we wouldn't be able to set otherwise (they dont require an enabler?)

EUD's are better for conditions we wouldn't be able to check otherwise, but for actions require an enabler probably making EUP's a better choice for preforming actions.


It seems like there is a fair amount of overlap when trying to preform actions between EUD and EUP, is this right? What are the pros and cons of using each one?




Sep 19 2014, 8:24 pm jjf28 Post #5

Cartography Artisan

EUD action con: they require enabler
EUD pro: everything else




Sep 19 2014, 8:24 pm Roy Post #6

An artist's depiction of an Extended Unit Death

Quote from sigsaucy
EUD conditions- these are just conditions that check things we usually can't check right? things like unit energy, upgrade level and such?

EUD actions- these are actions we cant usually preform? like modifying upgrade levels, changing weapons etc?

EUD actions (conditions) are those preformed by setting (checking) death table values to (for) certain values

EUP's- these are actions set by placing extended units at beginning of the map, they dont require any enabler, they can be used to modify unit stats, but you are limited to units you can preplace when creating the map (although you can still preform actions by giving units from one player to another and killing them)

As far as when to choose one over the other

EUP's seem to be more suited towards preforming actions that we wouldn't be able to set otherwise (they dont require an enabler?)
Yes, all of this is correct.

Quote from sigsaucy
EUD's are better for conditions we wouldn't be able to check otherwise, but for actions require an enabler probably making EUP's a better choice for preforming actions.
No, not necessarily. EUPs are only good for very specialized things and require a lot of effort and experimentation to work. Even if it does work, you can only reasonably modify 1/4th the amount of addresses you can modify with EUDAs (due to only being able to add or subtract 1 value at a time). You're also limited to doing arithmetic, whereas with EUDAs you can also set the address to a specific value.

EUPs are generally useful if you're looking to make very minor modifications to the game, but without a sophisticated and bulky system, they aren't good for making a heavily-modified game.




Sep 19 2014, 9:01 pm sigsaucy Post #7



Quote from Roy
Even if it does work, you can only reasonably modify 1/4th the amount of addresses you can modify with EUDAs (due to only being able to add or subtract 1 value at a time). You're also limited to doing arithmetic, whereas with EUDAs you can also set the address to a specific value.

What exactly do you mean by only being able to modify 1/4 of the actions you can with EUDA's?

Is it because some of the addresses are inaccessible from the formulas we have for EUP's?

I guess the big problem with EUP's is the difficulty in implementation in comparison to EUD's?




Sep 19 2014, 10:04 pm O)FaRTy1billion[MM] Post #8

👻 👾 👽 💪

Quote from sigsaucy
What exactly do you mean by only being able to modify 1/4 of the actions you can with EUDA's?

Is it because some of the addresses are inaccessible from the formulas we have for EUP's?
Basically, yes. It can only add/subtract a value of 1 to addresses aligned to 4 bytes ... so like (randomly typed address, I don't know what it is) 0x5d420, 0x4d424, 0x4d428, etc., so to write to 0x5d421 you'd need to do it 256 times, for 0x5d422 65536 times, and 0x5d423 you'd need 1677216 times-- making those addresses pretty much unreachable.



TinyMap2 - Latest in map compression! ( 7/09/14 - New build! )
EUD Action Enabler - Lightweight EUD/EPD support! (ChaosLauncher/MPQDraft support!)
EUDDB - topic - Help out by adding your EUDs! Or Submit reference files in the References tab!
MapSketch - New image->map generator!
EUDTrig - topic - Quickly and easily convert offsets to EUDs! (extended players supported)
SC2 Map Texture Mask Importer/Exporter - Edit texture placement in an image editor!
\:farty\: This page has been viewed [img]http://farty1billion.dyndns.org/Clicky.php?img.gif[/img] times!

Sep 22 2014, 8:10 am sigsaucy Post #9



sorry, im not following the numbers, can you explain a bit more?




Sep 22 2014, 12:04 pm Roy Post #10

An artist's depiction of an Extended Unit Death

Farty's really explained it the best one can; you should really look into understanding EUDs in general (hint: read the guide) to understand concise explanations like the one above. But I'll do my best.

A quick little breakdown for those unfamiliar with numeric data types:

byte: A numeric value between 0 and 255.
short: 2 bytes, ranging between [0, 0] = 0 and [255, 255] = 65535.
integer: 4 bytes, ranging between [0, 0, 0, 0] = 0 and [255, 255, 255, 255] = 4294967295.

4 bytes with values [1, 0, 0, 0] is equal to 1
4 bytes with values [0, 1, 0, 0] is equal to 256
4 bytes with values [0, 0, 1, 0] is equal to 65536
4 bytes with values [0, 0, 0, 1] is equal to 16777216

The "Deaths" condition and "Set Deaths" action both expect integer values (as all values inside the Unit Death table are integers), so they will retrieve 4 bytes in memory at the given location. The way EUDs work is that we overflow the player/unit fields, which causes the condition/action to go outside of the Unit Death table. While it thinks it's still grabbing the number of deaths for a given unit, it's actually grabbing a completely different set of 4 bytes of memory, which could be an integer, or a combination of shorts and/or bytes.

Preplaced units and units that are killed are, in the same vein, writing to various integer tables (command, kills, deaths, etc.). EUPs, therefore, are also restricted to writing at 4-byte offsets in memory. Why is this a problem? Because in the case that you're not actually dealing with a 4-byte value, the shorts/bytes that are not located at the first byte of the chunk of memory are directly inaccessible.

Here's an old post of mine talking about detecting upgrades that should illustrate the problem:
Quote from Roy
I'm going to answer this from a technical level, but if you need me to explain in more detail, let me know.

SC upgrades researched: http://farty1billion.dyndns.org/euddb/?pg=entry&addr=0x0058D298&ver=1.15.2&plat=win

Your upgrade is 0x0D away, since upgrades are 1 byte apiece; this means you're +3 players from the base Player ID (3027).

Memory at Death Table + 3030 is exactly A + (B*256) + (C*65536) + (D*16777216)
A = Zerg Flyer Attacks
B = Protoss Ground Weapons
C = Protoss Air Weapons
D = Protoss Plasma Shields

You'll need to know the values of all of these except Zerg Flyer Attacks, which you can negate by checking between A = 0 and A = 255. That is:
Memory at Death Table + 3030 is at least 0 + (B*256) + (C*65536) + (D*16777216)
Memory at Death Table + 3030 is at most 255 + (B*256) + (C*65536) + (D*16777216)

EDIT: This is only for Player 1. Player 2's upgrades are located immediately after Player 1's, and this pattern continues for all players. If you need more help for the other players, let me know.
EDIT2: If you're not interested in explanations, try this:
Upgrades for each player




Weapon damage amount: http://farty1billion.dyndns.org/euddb/?pg=entry&addr=0x00656EB0&ver=1.16.1&plat=win

Your weapon is 0x1A away, since damage amounts are 2 bytes apiece; this means you're +6 players from the base Player ID (209619).
Memory at Death Table + 209625 is exactly A + (B*65536)
A = Zerg Flyer Attacks
B = Protoss Ground Weapons

This is actually in your favor, as you can completely ignore the value of Zerg Flyer Attacks:
Memory at Death Table + 209625 is at least 0 + (B*65536)
Memory at Death Table + 209625 is at most 65535 + (B*65536)



As for checking the damage of a unit at a specific index, that's not directly (and pragmatically) possible, as the unit's damage is not stored in the unit struct; you'd have to look up its weapon's damage.
Now, ignoring the issue that odd-numbered players and even-numbered players start at different offsets, you can clearly see an issue with calculations: one EUD (address 0x58D2BC) is detecting four different upgrades. This is because an EUD is reading a chunk of 4 bytes in memory (0-4294967295), and an upgrade is only 1 byte in size (0-255).

So how do we check for a specific upgrade if we are forced to check four at a time? With a little math:
Quote from Roy
Memory at Death Table + 3030 is exactly A + (B*256) + (C*65536) + (D*16777216)
A = Zerg Flyer Attacks
B = Protoss Ground Weapons
C = Protoss Air Weapons
D = Protoss Plasma Shields
As you can see, to check, for example, the upgrade level for Protoss Plasma Shields, we have to multiply the number we're looking at by 16777216. Translating this over to an EUD Action, if we want to increase Protoss Plasma Shields by one level, we have to add 16777216 to address 0x58D2BC.
Increase Player 1 Protoss Plasma Shields
Players

  • Player 1
  • Conditions

  • Always
  • Actions

  • Set Deaths of UnitID:252 for Player 7: add 16777216.

  • Now, how would we do this with EUPs? Well, the simple approach would be to place over sixteen million extended units onto the map (because each unit only adds 1 to the address). But that's clearly a problem because you can only place at most 1700 units on a map. In fact, this approach makes it flat-out impossible to access the 3rd and 4th bytes of any 4-byte address, and it's impractical for the 2nd byte (requiring 256 preplaced extended units per increment) for anything other than the smallest of increments.

    Post has been edited 2 time(s), last time on Sep 23 2014, 1:06 pm by Roy. Reason: Correcting address




    Sep 23 2014, 5:43 am sigsaucy Post #11



    Roy, your post has explained alot but a few things are confusing me

    for Memory at Death Table + X

    In Quiz 3 you determine X by looking at the address but in the above examples you use the Player ID.

    What exactly is Player ID and are we allowed to use it interchangeably with Address?




    Does "Memory at Death Table + X" represent 2 numbers being added together or is it just referencing a single number? If "Memory at Death Table" represents a number, what number is it?





    I tried running through the calculations for the last example using the formula

    Address incremented = 48*(Dying unit’s UnitID) + 4*(Dying unit’s Owner) + 5808992

    to show that

    "add 16777216 to address 0x5168E4." is equivalent to "Set Deaths of UnitID:252 for Player 7: add 16777216."

    Using the formula we have that "Set Deaths of UnitID:252 for Player 7: add 16777216." increments address (48 * 252) + (4 * 7) + 5 808 992 = 5821116 by 16777216.


    But 0x5168E4 = 5335268 so these addresses dont match up


    What am I doing wrong?



    Thanks and sorry for all the questions.




    Sep 23 2014, 7:18 am O)FaRTy1billion[MM] Post #12

    👻 👾 👽 💪

    Quote from sigsaucy
    But 0x5168E4 = 5335268 so these addresses dont match up
    They do. You're not doing anything wrong, all you are missing is that the one on the left is in hex and the one on the right is in dec. Open Windows Calculator, go to to Programmer mode (Alt+3), and paste in 5335268 then switch to Hex and it will show 5168E4. The '0x' prefix signifies that the number is in hexadecimal notation (which is an easier form to read than binary), instead of decimal (which we typically use).

    Generally addresses are written in hex, since that is how they are found and you can see at a glance some things about them (such as if they are aligned to a 4-byte boundary -- the last digit will be 0, 4, 8 or C. C in decimal is 12).

    Post has been edited 2 time(s), last time on Sep 23 2014, 7:26 am by FaRTy1billion.



    TinyMap2 - Latest in map compression! ( 7/09/14 - New build! )
    EUD Action Enabler - Lightweight EUD/EPD support! (ChaosLauncher/MPQDraft support!)
    EUDDB - topic - Help out by adding your EUDs! Or Submit reference files in the References tab!
    MapSketch - New image->map generator!
    EUDTrig - topic - Quickly and easily convert offsets to EUDs! (extended players supported)
    SC2 Map Texture Mask Importer/Exporter - Edit texture placement in an image editor!
    \:farty\: This page has been viewed [img]http://farty1billion.dyndns.org/Clicky.php?img.gif[/img] times!

    Sep 23 2014, 12:37 pm sigsaucy Post #13



    i think you misread the problem

    0x5168E4 = 5335268, the address converted from hex to dec

    doesn't match up with

    5821116 the decimal address calculated from "Set Deaths of UnitID:252 for Player 7: add 16777216."




    Sep 23 2014, 1:04 pm Roy Post #14

    An artist's depiction of an Extended Unit Death

    Quote from sigsaucy
    for Memory at Death Table + X

    In Quiz 3 you determine X by looking at the address but in the above examples you use the Player ID.

    What exactly is Player ID and are we allowed to use it interchangeably with Address?
    The Player ID is the player number. When you say "Player 5 has suffered at least 1 deaths of Terran Ghost", Player 5 is the Player ID. It just so happens that you can use much higher player numbers to achieve overflows.

    There is a direct relationship between the Address and the Player ID: think of it like dealing with Celsius vs Fahrenheit. It's easier to just use a program like EUDTrig to do the conversion for you, though the formula for doing it manually is:

    (Address - DeathTableStart) / 4.

    Quote from sigsaucy
    Does "Memory at Death Table + X" represent 2 numbers being added together or is it just referencing a single number? If "Memory at Death Table" represents a number, what number is it?
    The Death Table starts at offset 0x58A364. You're adding to the start of that offset to get to the address you want.

    Quote from sigsaucy
    I tried running through the calculations for the last example using the formula

    Address incremented = 48*(Dying unit�s UnitID) + 4*(Dying unit�s Owner) + 5808992

    to show that

    "add 16777216 to address 0x5168E4." is equivalent to "Set Deaths of UnitID:252 for Player 7: add 16777216."

    Using the formula we have that "Set Deaths of UnitID:252 for Player 7: add 16777216." increments address (48 * 252) + (4 * 7) + 5 808 992 = 5821116 by 16777216.


    But 0x5168E4 = 5335268 so these addresses dont match up


    What am I doing wrong?
    That's actually an error on my part; I had EUDTrig pointed to an older version of SC, so I gave the incorrect address. The correct address is 0x58D2BC. The other values are correct, though, because the conversion between overflowing the player field vs the unit field is independent of the start of the death table (see below). I'll update the post using the correct address.

    Side Note





    Sep 24 2014, 6:54 am sigsaucy Post #15



    I think a visual of how the data is stored will help me out

    is it something like this?

    DATA ORGANIZATION


    ADDRESS POINT OF VIEW

    Address / Description

    0x58A364 / death table start, a value in the 4 byte storing marine deaths [a,b,c,d] for P1
    0x58A365 / b value in the 4 byte storing marine deaths [a,b,c,d] for P1
    0x58A366 / c value in the 4 byte storing marine deaths [a,b,c,d] for P1
    0x58A367 / d value in the 4 byte storing marine deaths [a,b,c,d] for P1

    0x58A368 / a value in the 4 byte storing marine deaths [a,b,c,d] for P2

    .
    .
    .

    0x00656EB0 / weapons.dat start, [a,b] value storing damage for weapon 0, gauss rifle
    0x00656EB1 / [a,b] value storing damage for weapon 1, gauss rifle raynor



    PLAYER ID POINT OF VIEW


    Player ID: 0 = [a,b,c,d] representing value of marine deaths for P1
    Player ID: 1 = [a,b,c,d] representing value of marine deaths for P2
    .
    .
    .
    Player ID: 209619 = [a,b,c,d] where a + 256*b is damage for weapon 0, c + 256*d is damage for weapon 1





    SETTING DEATHS

    if we set the memory at address 0x58A364 it gets read in as an integer, ex if we set memory at 0x58A364 to [e,f,g,h] the death tables get altered to

    Address / Player ID / Value

    0x58A364 / 0 / e
    0x58A365 / 0 / f
    0x58A366 / 0 / g
    0x58A367 / 0 / h


    if we set the memory at address 0x0058D298 it gets read in as an integer, ex if we set memory at 0x00656EB0 to [e,f,g,h] the death tables get altered to

    Address / Player ID / Value

    0x00656EB0 / 209619 / e + 256 * f
    0x00656EB1 / 209619 / g + 256 * h


    Are these above 2 examples right?


    I'm still trying to figure out why we bother using Player ID's

    Player ID seems to be a construction by us to help deal with the complications brought on by only being able to set address values to integers.

    Instead of modifying addresses at weird half way points where bytes and shorts are mixed Player ID lets us stick to basic examples like the above?

    Post has been edited 8 time(s), last time on Sep 24 2014, 7:19 am by sigsaucy.




    Sep 24 2014, 7:03 am O)FaRTy1billion[MM] Post #16

    👻 👾 👽 💪

    Quote from sigsaucy
    Are these above 2 examples right?
    They seem to be, yes.

    Quote from sigsaucy
    I'm still trying to figure out why we bother using Player ID's

    Player ID seems to be a construction by us to help deal with the complications brought on by only being able to set address values to integers.

    Instead of modifying addresses at weird half way points where bytes and shorts are mixed Player ID lets us stick to basic examples like the above?
    We use player IDs because is the simplest way to read addresses beyond the death table. We can't read off of a 4-byte alignment because we are stuck to the whims of the Deaths condition/actions, which is itself incapable of reading an address that is not a multiple of 4.

    The death condition/action itself reads/writes to DeathTableOffset + (UnitID*12 + PlayerID)*4. By leaving UnitID at 0, then every time we increment PlayerID it reads the next 4 bytes. If there was another simpler way to read/write to addresses (such as byte-aligned, or short-aligned), we'd use it.

    Post has been edited 1 time(s), last time on Sep 24 2014, 7:09 am by FaRTy1billion.



    TinyMap2 - Latest in map compression! ( 7/09/14 - New build! )
    EUD Action Enabler - Lightweight EUD/EPD support! (ChaosLauncher/MPQDraft support!)
    EUDDB - topic - Help out by adding your EUDs! Or Submit reference files in the References tab!
    MapSketch - New image->map generator!
    EUDTrig - topic - Quickly and easily convert offsets to EUDs! (extended players supported)
    SC2 Map Texture Mask Importer/Exporter - Edit texture placement in an image editor!
    \:farty\: This page has been viewed [img]http://farty1billion.dyndns.org/Clicky.php?img.gif[/img] times!

    Sep 24 2014, 9:54 am Roy Post #17

    An artist's depiction of an Extended Unit Death

    Quote from sigsaucy
    I'm still trying to figure out why we bother using Player ID's
    You're trying to figure out why we use EUDs?

    Quote from sigsaucy
    Player ID seems to be a construction by us to help deal with the complications brought on by only being able to set address values to integers.
    If by "construction by us" you mean a 32-bit data type invented in the 1980's (or earlier) and used commonly throughout programs from then on, no, we personally don't take credit for that. We're just using what Blizzard gave us to work with. If the Unit Death Table happened to be 1-byte-per-unit, we'd have that level of granularity, and if it happened to be a long (8 bytes), we'd have half of our current level of granularity.

    Quote from sigsaucy
    Instead of modifying addresses at weird half way points where bytes and shorts are mixed Player ID lets us stick to basic examples like the above?
    Quote from O)FaRTy1billion[MM]
    If there was another simpler way to read/write to addresses (such as byte-aligned, or short-aligned), we'd use it.
    As Farty says, this is the simplest and most-specific we can get with EUDs because of how the Deaths condition and Set Deaths action work. Are you suggesting there's a better way?




    Sep 25 2014, 7:33 am sigsaucy Post #18



    Roy, I've been going over the calculations over and over and it seems to me when you write

    Memory at Death Table + PlayerID is exactly [a,b,c,d]

    you really mean

    Memory at Death Table + 4*PlayerID is exactly [a,b,c,d]


    Example

    To find the zerg flyer attacks researched for p1 address there are two ways,



    via "Direct Address"



    Upgrades are located at address 0x0058D2B0 = 5821104 and zerg flyer attacks has an offset of +12 so the address is

    5821104 + 12 = 5821116






    via Player ID



    As you say in your very first example in post #10

    Your upgrade is 0x0D away, since upgrades are 1 byte apiece; this means you're +3 players from the base Player ID (3027). so player ID is = 3030

    The formula you gave was

    Memory at Death Table + 3030 is exactly [a,b,c,d]

    which plugging in DeathTableStart = 0x58A364 = 5808996 gives

    5812023 is exactly [a,b,c,d]

    which doesn't agree with the Direct Address way of finding the address but if you make it 4*PlayerID it does



    (I know you have to make sure to pick PlayerID's and Addresses that are divisible by 4, but even if i took that into account it would still be the same)




    Sep 25 2014, 11:23 am Roy Post #19

    An artist's depiction of an Extended Unit Death

    Quote from sigsaucy
    Roy, I've been going over the calculations over and over and it seems to me when you write

    Memory at Death Table + PlayerID is exactly [a,b,c,d]

    you really mean

    Memory at Death Table + 4*PlayerID is exactly [a,b,c,d]
    No, not at all. The Memory condition takes in the PlayerID (usually just called the MemoryID), not an address offset value. In this format, you're giving the PlayerID, not 4*PlayerID (which would output an incorrect value for the condition). Are you not familiar with the Memory condition, perhaps?

    Quote from sigsaucy
    Example

    To find the zerg flyer attacks researched for p1 address there are two ways,

    via "Direct Address"

    Upgrades are located at address 0x0058D2B0 = 5821104 and zerg flyer attacks has an offset of +12 so the address is

    5821104 + 12 = 5821116
    Okay, here's your problem: you're handling one value as an address and the other as an integer (a 4-byte value). You have to use one or the other. Death Table is equal to the address 0x58A364 and the MemoryID 0. Upgrades start at address 0x0058D2B0, which is equal to the MemoryID 3027. So you have either of the following to calculate Zerg Flyer Attacks:

    3027 + 3 = 3030
    0x0058D2B0 + 0xC = 0x0058D2BC

    Here are some example values to try to illustrate how things work:

    Address 0x58A364 == PlayerID 0 UnitID 0 == MemoryID 0 == Player 1's deaths of Terran Marine
    Address 0x58A368 == PlayerID 1 UnitID 0 == MemoryID 1 == Player 2's deaths of Terran Marine
    Address 0x58A36C == PlayerID 2 UnitID 0 == MemoryID 2 == Player 3's deaths of Terran Marine
    ...
    Address 0x58A394 == PlayerID 0 UnitID 1 == MemoryID 12 == Player 1's deaths of Terran Ghost
    Address 0x58A398 == PlayerID 1 UnitID 1 == MemoryID 13 == Player 2's deaths of Terran Ghost
    Address 0x58A39C == PlayerID 2 UnitID 1 == MemoryID 14 == Player 3's deaths of Terran Ghost
    ...
    Address 0x58D2BC == PlayerID 6 UnitID 252 == MemoryID 3030 == Player 1's Zerg Flyer Attacks/Protoss Ground Weapons/Protoss Air Weapons/Protoss Plasma Shields upgrades
    Address 0x58D2C0 == PlayerID 7 UnitID 252 == MemoryID 3031 == Player 1's U-238 Shells/Ion Thrusters/Burst Lasers/Titan Reactor upgrades
    Address 0x58D2C4 == PlayerID 8 UnitID 252 == MemoryID 3032 == Player 1's Ocular Implants/Moebius Reactor/Apollo Reactor/Colossus Reactor upgrades

    As you can see, incrementing a PlayerID/MemoryID by one is equivalent to moving 4 bytes (the size of an integer) in memory. Keep in mind that because you're retrieving an integer value, you're also pulling 4 bytes from memory, meaning for MemoryID 3030, you get the values for addresses 0x58D2BC, 0x58D2BD, 0x58D2BE, and 0x58D2BF, all combined as a single integer value. You do not multiply the PlayerID/MemoryID by four, unless you're just converting to an address (in which case, you shouldn't represent it in the form of a Memory condition).

    Quote from sigsaucy
    via Player ID

    As you say in your very first example in post #10

    Your upgrade is 0x0D away, since upgrades are 1 byte apiece; this means you're +3 players from the base Player ID (3027). so player ID is = 3030

    The formula you gave was

    Memory at Death Table + 3030 is exactly [a,b,c,d]

    which plugging in DeathTableStart = 0x58A364 = 5808996 gives

    5812023 is exactly [a,b,c,d]

    which doesn't agree with the Direct Address way of finding the address but if you make it 4*PlayerID it does
    The PlayerID is an integer, which is 4 bytes in size. If you're calculating the address, you have to go by the total size, not by the PlayerID number itself, which is why you're multiplying by four.

    Quote from sigsaucy
    (I know you have to make sure to pick PlayerID's and Addresses that are divisible by 4, but even if i took that into account it would still be the same)
    You do not have to make sure the PlayerID is divisible by four. A PlayerID of 3031 is completely valid, and it will get the next set of four upgrades. An Address doesn't have to be divisible by four, but the byte of interest won't be the first byte if it's not divisible by four.

    I seem to have led you astray somewhere, because your understanding of EUDs in an earlier post was all accurate, whereas this one... wasn't.

    Post has been edited 1 time(s), last time on Sep 25 2014, 11:31 am by Roy.




    Sep 27 2014, 5:19 am sigsaucy Post #20



    I think I understand now, Im away from my PC so I can't test anything but I appreciate all your help, thanks.

    Hopefully I'll have something cool to show soon!




    Options
      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
    [2024-4-17. : 3: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