00c9be13541f25f842018dd58a1ea5fda0732152
[xonotic/xonotic-data.pk3dir.git] / qcsrc / lib / spawnfunc.qh
1 #ifndef SPAWNFUNC_H
2 #define SPAWNFUNC_H
3
4 /** If this global exists, only functions with spawnfunc_ name prefix qualify as spawn functions */
5 noref bool require_spawnfunc_prefix;
6 .bool spawnfunc_checked;
7
8 // Optional type checking; increases compile time too much to be enabled by default
9 #if 0
10 bool entityfieldassignablefromeditor(int i) {
11     switch (entityfieldtype(i)) {
12         case FIELD_STRING:
13         case FIELD_FLOAT:
14         case FIELD_VECTOR:
15             return true;
16     }
17     return false;
18 }
19
20 #define _spawnfunc_checktypes(fld) if (fieldname == #fld) \
21     if (!entityfieldassignablefromeditor(i)) LOG_FATALF("Entity field '%s' cannot be whitelisted\n", fieldname);
22 #else
23 #define _spawnfunc_checktypes(fld)
24 #endif
25 #define _spawnfunc_check(fld) if (fieldname == #fld) \
26     continue;
27
28 #define spawnfunc_1(id, whitelist) spawnfunc_2(id, whitelist)
29 #define spawnfunc_2(id, whitelist) void spawnfunc_##id(entity this) { \
30     this = self; \
31     if (!this.spawnfunc_checked) { \
32         for (int i = 0, n = numentityfields(); i < n; ++i) { \
33             string value = getentityfieldstring(i, this); \
34             string fieldname = entityfieldname(i); \
35             whitelist(_spawnfunc_checktypes) \
36             if (value == "") continue; \
37             if (fieldname == "") continue; \
38             FIELDS_COMMON(_spawnfunc_check) \
39             whitelist(_spawnfunc_check) \
40             LOG_WARNINGF(_("Entity field %s.%s (%s) is not whitelisted. If you believe this is an error, please file an issue.\n"), #id, fieldname, value); \
41         } \
42         this.spawnfunc_checked = true; \
43     } \
44 } \
45 [[accumulate]] void spawnfunc_##id(entity this)
46
47 #define FIELD_SCALAR(fld, n) \
48     fld(n)
49 #define FIELD_VEC(fld, n) \
50     fld(n) \
51     fld(n##_x) \
52     fld(n##_y) \
53     fld(n##_z)
54
55 #define FIELDS_NONE(fld)
56 #define FIELDS_ALL(fld) if (false)
57
58 #define FIELDS_COMMON(fld) \
59     FIELD_SCALAR(fld, classname) \
60     FIELD_SCALAR(fld, spawnfunc_checked) \
61     /**/
62
63 #define FIELDS_UNION(fld) \
64     FIELD_SCALAR(fld, Version) \
65     FIELD_SCALAR(fld, ammo_cells) \
66     FIELD_SCALAR(fld, ammo_nails) \
67     FIELD_SCALAR(fld, ammo_rockets) \
68     FIELD_SCALAR(fld, armorvalue) \
69     FIELD_SCALAR(fld, atten) \
70     FIELD_SCALAR(fld, bgmscriptdecay) \
71     FIELD_SCALAR(fld, bgmscriptsustain) \
72     FIELD_SCALAR(fld, bgmscript) \
73     FIELD_SCALAR(fld, button0) \
74     FIELD_SCALAR(fld, cnt) \
75     FIELD_SCALAR(fld, colormap) \
76     FIELD_SCALAR(fld, count) \
77     FIELD_SCALAR(fld, debrisdamageforcescale) \
78     FIELD_SCALAR(fld, debrisfadetime) \
79     FIELD_SCALAR(fld, debristimejitter) \
80     FIELD_SCALAR(fld, debristime) \
81     FIELD_SCALAR(fld, debris) \
82     FIELD_SCALAR(fld, delay) \
83     FIELD_SCALAR(fld, dmg) \
84     FIELD_SCALAR(fld, dmg_edge) \
85     FIELD_SCALAR(fld, dmg_force) \
86     FIELD_SCALAR(fld, dmg_radius) \
87     FIELD_SCALAR(fld, effects) \
88     FIELD_SCALAR(fld, flags) \
89     FIELD_SCALAR(fld, fog) \
90     FIELD_SCALAR(fld, frame) \
91     FIELD_SCALAR(fld, gametypefilter) \
92     FIELD_SCALAR(fld, gravity) \
93     FIELD_SCALAR(fld, health) \
94     FIELD_SCALAR(fld, height) \
95     FIELD_SCALAR(fld, impulse) \
96     FIELD_SCALAR(fld, killtarget) \
97     FIELD_SCALAR(fld, lerpfrac) \
98     FIELD_SCALAR(fld, light_lev) \
99     FIELD_SCALAR(fld, lip) \
100     FIELD_SCALAR(fld, loddistance1) \
101     FIELD_SCALAR(fld, lodmodel1) \
102     FIELD_SCALAR(fld, ltime) \
103     FIELD_SCALAR(fld, mdl) \
104     FIELD_SCALAR(fld, message2) \
105     FIELD_SCALAR(fld, message) \
106     FIELD_SCALAR(fld, modelindex) \
107     FIELD_SCALAR(fld, modelscale) \
108     FIELD_SCALAR(fld, model) \
109     FIELD_SCALAR(fld, movetype) \
110     FIELD_SCALAR(fld, netname) \
111     FIELD_SCALAR(fld, nextthink) \
112     FIELD_SCALAR(fld, noalign) \
113     FIELD_SCALAR(fld, noise1) \
114     FIELD_SCALAR(fld, noise2) \
115     FIELD_SCALAR(fld, noise) \
116     FIELD_SCALAR(fld, phase) \
117     FIELD_SCALAR(fld, race_place) \
118     FIELD_SCALAR(fld, radius) \
119     FIELD_SCALAR(fld, respawntimejitter) \
120     FIELD_SCALAR(fld, respawntime) \
121     FIELD_SCALAR(fld, restriction) \
122     FIELD_SCALAR(fld, scale) \
123     FIELD_SCALAR(fld, skin) \
124     FIELD_SCALAR(fld, solid) \
125     FIELD_SCALAR(fld, sound1) \
126     FIELD_SCALAR(fld, sounds) \
127     FIELD_SCALAR(fld, spawnflags) \
128     FIELD_SCALAR(fld, speed) \
129     FIELD_SCALAR(fld, strength) \
130     FIELD_SCALAR(fld, target2) \
131     FIELD_SCALAR(fld, target3) \
132     FIELD_SCALAR(fld, target4) \
133     FIELD_SCALAR(fld, targetname) \
134     FIELD_SCALAR(fld, target) \
135     FIELD_SCALAR(fld, target_random) \
136     FIELD_SCALAR(fld, team) \
137     FIELD_SCALAR(fld, turret_scale_health) \
138     FIELD_SCALAR(fld, turret_scale_range) \
139     FIELD_SCALAR(fld, turret_scale_respawn) \
140     FIELD_SCALAR(fld, volume) \
141     FIELD_SCALAR(fld, wait) \
142     FIELD_SCALAR(fld, warpzone_fadeend) \
143     FIELD_SCALAR(fld, warpzone_fadestart) \
144     FIELD_VEC(fld, absmax) \
145     FIELD_VEC(fld, absmin) \
146     FIELD_VEC(fld, angles) \
147     FIELD_VEC(fld, avelocity) \
148     FIELD_VEC(fld, maxs) \
149     FIELD_VEC(fld, maxs) \
150     FIELD_VEC(fld, mins) \
151     FIELD_VEC(fld, modelscale_vec) \
152     FIELD_VEC(fld, origin) \
153     FIELD_VEC(fld, velocity) \
154     /**/
155
156 #define spawnfunc(...) EVAL(OVERLOAD(spawnfunc, __VA_ARGS__, FIELDS_UNION))
157
158 #endif