-// #define PROP(public, fld, set, sv, cl)
-#define ENTCS_NETPROPS(ent, PROP) PROP(false, sv_entnum, ENTCS_SET_NORMAL, {}, {}) /* sentinel */ \
- PROP(false, origin, ENTCS_SET_NORMAL, \
- { WriteCoord(chan, ent.origin.x); WriteCoord(chan, ent.origin.y); \
- WriteCoord(chan, ent.origin.z); }, \
- { ent.has_sv_origin = true; vector v; v.x = ReadCoord(); v.y = ReadCoord(); v.z = ReadCoord(); setorigin(ent, v); }) \
- \
- PROP(false, angles_y, ENTCS_SET_NORMAL, \
- { WriteByte(chan, ent.angles.y / 360 * 256); }, \
- { vector v = '0 0 0'; v.y = ReadByte() / 256 * 360; ent.angles = v; }) \
- \
- PROP(false, health, ENTCS_SET_NORMAL, \
- { WriteByte(chan, bound(0, ent.health / 10, 255)); /* FIXME: use a better scale? */ }, \
- { ent.healthvalue = ReadByte() * 10; }) \
- \
- PROP(false, armorvalue, ENTCS_SET_NORMAL, \
- { WriteByte(chan, bound(0, ent.armorvalue / 10, 255)); /* FIXME: use a better scale? */ }, \
- { ent.armorvalue = ReadByte() * 10; }) \
- \
- PROP(true, netname, ENTCS_SET_MUTABLE_STRING, \
- { WriteString(chan, ent.netname); }, \
- { if (ent.netname) strunzone(ent.netname); ent.netname = strzone(ReadString()); }) \
- \
- PROP(true, model, ENTCS_SET_NORMAL, \
- { WriteString(chan, ent.model); }, \
- { if (ent.model) strunzone(ent.model); ent.model = strzone(ReadString()); }) \
- \
- PROP(true, skin, ENTCS_SET_NORMAL, \
- { WriteByte(chan, ent.skin); }, \
- { ent.skin = ReadByte(); }) \
- \
- PROP(true, clientcolors, ENTCS_SET_NORMAL, \
- { WriteByte(chan, ent.clientcolors); }, \
- { ent.colormap = ReadByte(); }) \
- \
- PROP(true, frags, ENTCS_SET_NORMAL, \
- { WriteShort(chan, ent.frags); }, \
- { ent.frags = ReadShort(); }) \
- \
- ENTCS_EXTRAPROPS \
- \
- /**/
+ENTCS_PROP(ENTNUM, false, sv_entnum, sv_entnum, ENTCS_SET_NORMAL, {}, {}) /* sentinel */
+
+ENTCS_PROP(ORIGIN, false, origin, origin, ENTCS_SET_NORMAL,
+ { WriteVector(chan, ent.origin); },
+ { ent.has_sv_origin = true; vector v = ReadVector(); setorigin(ent, v); })
+
+#define DEC_FACTOR (360 / 32)
+ENTCS_PROP_CODED(ANGLES, false, angles_y, angles_y, ENTCS_SET_NORMAL, DEC_FACTOR,
+ { WriteByte(chan, ent.angles.y / DEC_FACTOR); },
+ { vector v = '0 0 0'; v.y = ReadByte() * DEC_FACTOR; ent.angles = v; })
+#undef DEC_FACTOR
+
+// FIXME: use a better scale?
+#define DEC_FACTOR 10
+ENTCS_PROP_RESOURCE(HEALTH, false, RES_HEALTH, ENTCS_SET_NORMAL, DEC_FACTOR,
+ { WriteByte(chan, bound(0, GetResource(ent, RES_HEALTH) / DEC_FACTOR, 255)); },
+ { ent.healthvalue = ReadByte() * DEC_FACTOR; })
+
+ENTCS_PROP_RESOURCE(ARMOR, false, RES_ARMOR, ENTCS_SET_NORMAL, DEC_FACTOR,
+ { WriteByte(chan, bound(0, GetResource(ent, RES_ARMOR) / DEC_FACTOR, 255)); },
+ { SetResourceExplicit(ent, RES_ARMOR, ReadByte() * DEC_FACTOR); })
+#undef DEC_FACTOR
+
+ENTCS_PROP(NAME, true, netname, netname, ENTCS_SET_MUTABLE_STRING,
+ { WriteString(chan, ent.netname); },
+ { strcpy(ent.netname, ReadString()); })
+
+ENTCS_PROP(MODEL, true, model, model, ENTCS_SET_NORMAL,
+ { WriteString(chan, ent.model); },
+ { strcpy(ent.model, ReadString()); })
+
+ENTCS_PROP(SKIN, true, skin, skin, ENTCS_SET_NORMAL,
+ { WriteByte(chan, ent.skin); },
+ { ent.skin = ReadByte(); })
+
+ENTCS_PROP(CLIENTCOLORS, true, clientcolors, clientcolors, ENTCS_SET_NORMAL,
+ { WriteByte(chan, ent.clientcolors); },
+ { ent.colormap = ReadByte(); })
+
+ENTCS_PROP(FRAGS, true, frags, frags, ENTCS_SET_NORMAL,
+ { WriteShort(chan, ent.frags); },
+ { ent.frags = ReadShort(); })
+
+// use sv_solid to avoid changing solidity state of entcs entities
+ENTCS_PROP(SOLID, true, sv_solid, solid, ENTCS_SET_NORMAL,
+ { WriteByte(chan, ent.sv_solid); },
+ { ent.sv_solid = ReadByte(); })