SCRMaps
/
Sign in

scdata: game data by name, not by address

Units, weapons, upgrades and a player's own resources all read and write as objects. There is no longer a reason to do the bitmask arithmetic by hand.

7 min read

Nearly every older source is written in addresses - wwrite(0x666160 + 2*spriteId, ...) and the like. euddraft ships a named layer over all of it, and the name is scdata. It arrived in 0.9.11.0 and has been extended in almost every release since.

TrgUnit("Zerg Mutalisk").flingy = "Kakaru";
Image("Firebat Shadow").drawingFunction = "EMPShockwave";
Weapon("Gauss Rifle").damage = 30;
The same write, but readable - and a typo becomes a compile error rather than silent memory corruption.

Members chain: one that names another table hands you that table's object.

unit.armor += 1;
unit.groundWeapon.damage += 1;               // Weapon을 거쳐서 / through Weapon
unit.groundWeapon = Weapon("Gauss Rifle");   // 무기 자체를 교체 / or replace it outright

A player is an object too: resources read as fields, and the read is a condition.

P1.ore += 1;
if (P1.ore >= 100) printAll("빨강이 미네랄 100 이상");

And the current level of an upgrade or a tech is indexed by player, which replaces every piece of code that computed an upgrade-level address by hand.

const infantryWeapon = Upgrade("Terran Infantry Weapon");
foreach(player : EUDLoopPlayer()) { infantryWeapon[player] = 1; }
printAll("1피 레벨: {}", infantryWeapon[P1]);

var spiderMines: Tech = "Spider Mines";
spiderMines[P1] = 1;
once (Tech("Stim Pack")[P1]) { printAll("빨강이 스팀팩을 업그레이드했습니다."); }
A tech level reads as 1 when it is non-zero, so it goes straight into a condition.

One caution. TrgUnit, Weapon, Upgrade and the rest address tables, so they change the whole map. To change one unit you want CUnit - the same distinction the structure-offsets lesson is about.

A variable can be given an scdata type, and knowing that the implementation caches derived values is what makes the cost predictable.

What a variable scdata instance costs
4바이트 멤버Accessed directly, with no cache check.
1·2바이트 멤버Each access adds a cache-check condition and recomputes the derived values if the variable changed.
인스턴스 += 1Special-cased to update the cache in place, so no invalidation happens. Prefer it to re-assignment when walking a table.
캐시는 변수에 붙습니다The cache belongs to the variable: cast one variable to two types and the bitmask widens to the larger, so one type's cost shows up in the other's accesses.

One behaviour change to know when reading older code: cast no longer copies the value, it reinterprets in place. Code written before 0.10.0.0 that relied on a cast producing a separate variable is wrong now.

Structure offsetsdat writes do not stay written
Sign in to track your progress