/** If this global exists, only functions with spawnfunc_ name prefix qualify as spawn functions */
noref bool require_spawnfunc_prefix;
.bool spawnfunc_checked;
+/** Not for production use, provides access to a dump of the entity's fields when it is parsed from map data */
+noref string __fullspawndata;
+.string fullspawndata;
// Optional type checking; increases compile time too much to be enabled by default
#if 0
void __spawnfunc_spawn(entity prototype)
{
entity e = new(clone);
- copyentity(prototype, e);
+ copyentity_qc(prototype, e);
IL_PUSH(g_map_entities, e);
#define X(T, fld, def) { e.fld = e.__spawnfunc_##fld; e.__spawnfunc_##fld = def; }
SPAWNFUNC_INTERNAL_FIELDS(X);
e.__spawnfunc_constructor(e);
}
- #define FIELD_SCALAR(fld, n) \
- fld(n)
- #define FIELD_VEC(fld, n) \
- fld(n) \
- fld(n##_x) \
- fld(n##_y) \
- fld(n##_z)
-
- #define FIELDS_NONE(fld)
- #define FIELDS_ALL(fld) if (false)
-
- #define FIELDS_COMMON(fld) \
- FIELD_SCALAR(fld, classname) \
- FIELD_SCALAR(fld, sourceLoc) \
- FIELD_SCALAR(fld, spawnfunc_checked) \
- FIELD_VEC(fld, origin) \
- /**/
-
- #define FIELDS_UNION(fld) \
- FIELD_SCALAR(fld, Version) \
- FIELD_SCALAR(fld, ammo_cells) \
- FIELD_SCALAR(fld, ammo_nails) \
- FIELD_SCALAR(fld, ammo_rockets) \
- FIELD_SCALAR(fld, antiwall_flag) \
- FIELD_SCALAR(fld, armorvalue) \
- FIELD_SCALAR(fld, atten) \
- FIELD_SCALAR(fld, bgmscriptdecay) \
- FIELD_SCALAR(fld, bgmscriptsustain) \
- FIELD_SCALAR(fld, bgmscript) \
- FIELD_SCALAR(fld, button0) \
- FIELD_SCALAR(fld, chmap) \
- FIELD_SCALAR(fld, cnt) \
- FIELD_SCALAR(fld, colormap) \
- FIELD_SCALAR(fld, count) \
- FIELD_SCALAR(fld, curvetarget) \
- FIELD_SCALAR(fld, cvarfilter) \
- FIELD_SCALAR(fld, debrisdamageforcescale) \
- FIELD_SCALAR(fld, debrisfadetime) \
- FIELD_SCALAR(fld, debrismovetype) \
- FIELD_SCALAR(fld, debrisskin) \
- FIELD_SCALAR(fld, debristimejitter) \
- FIELD_SCALAR(fld, debristime) \
- FIELD_SCALAR(fld, debris) \
- FIELD_SCALAR(fld, delay) \
- FIELD_SCALAR(fld, dmgtime) \
- FIELD_SCALAR(fld, dmg) \
- FIELD_SCALAR(fld, dmg_edge) \
- FIELD_SCALAR(fld, dmg_force) \
- FIELD_SCALAR(fld, dmg_radius) \
- FIELD_SCALAR(fld, effects) \
- FIELD_SCALAR(fld, falloff) \
- FIELD_SCALAR(fld, flags) \
- FIELD_SCALAR(fld, fog) \
- FIELD_SCALAR(fld, frags) \
- FIELD_SCALAR(fld, frame) \
- FIELD_SCALAR(fld, gametype) \
- FIELD_SCALAR(fld, gametypefilter) \
- FIELD_SCALAR(fld, geomtype) \
- FIELD_SCALAR(fld, gravity) \
- FIELD_SCALAR(fld, health) \
- FIELD_SCALAR(fld, height) \
- FIELD_SCALAR(fld, impulse) \
- FIELD_SCALAR(fld, invincible_finished) \
- FIELD_SCALAR(fld, item_pickupsound) \
- FIELD_SCALAR(fld, killtarget) \
- FIELD_SCALAR(fld, lerpfrac) \
- FIELD_SCALAR(fld, light_lev) \
- FIELD_SCALAR(fld, lip) \
- FIELD_SCALAR(fld, loddistance1) \
- FIELD_SCALAR(fld, lodmodel1) \
- FIELD_SCALAR(fld, lodmodel2) \
- FIELD_SCALAR(fld, ltime) \
- FIELD_SCALAR(fld, map) \
- FIELD_SCALAR(fld, max_health) \
- FIELD_SCALAR(fld, mdl) \
- FIELD_SCALAR(fld, message2) \
- FIELD_SCALAR(fld, message) \
- FIELD_SCALAR(fld, modelindex) \
- FIELD_SCALAR(fld, modelscale) \
- FIELD_SCALAR(fld, model) \
- FIELD_SCALAR(fld, monsterid) \
- FIELD_SCALAR(fld, monster_moveflags) \
- FIELD_SCALAR(fld, monster_name) \
- FIELD_SCALAR(fld, movetype) \
- FIELD_SCALAR(fld, move_movetype) \
- FIELD_SCALAR(fld, netname) \
- FIELD_SCALAR(fld, nextthink) \
- FIELD_SCALAR(fld, noalign) \
- FIELD_SCALAR(fld, noise1) \
- FIELD_SCALAR(fld, noise2) \
- FIELD_SCALAR(fld, noise3) \
- FIELD_SCALAR(fld, noise) \
- FIELD_SCALAR(fld, notcpm) \
- FIELD_SCALAR(fld, notfree) \
- FIELD_SCALAR(fld, notta) \
- FIELD_SCALAR(fld, notteam) \
- FIELD_SCALAR(fld, notvq3) \
- FIELD_SCALAR(fld, phase) \
- FIELD_SCALAR(fld, platmovetype) \
- FIELD_SCALAR(fld, race_place) \
- FIELD_SCALAR(fld, strength_finished) \
- FIELD_SCALAR(fld, radius) \
- FIELD_SCALAR(fld, respawntimestart) \
- FIELD_SCALAR(fld, respawntimejitter) \
- FIELD_SCALAR(fld, respawntime) \
- FIELD_SCALAR(fld, restriction) \
- FIELD_SCALAR(fld, scale) \
- FIELD_SCALAR(fld, skin) \
- FIELD_SCALAR(fld, solid) \
- FIELD_SCALAR(fld, sound1) \
- FIELD_SCALAR(fld, sounds) \
- FIELD_SCALAR(fld, spawnflags) \
- FIELD_SCALAR(fld, spawnmob) \
- FIELD_SCALAR(fld, speed) \
- FIELD_SCALAR(fld, strength) \
- FIELD_SCALAR(fld, style) \
- FIELD_SCALAR(fld, target2) \
- FIELD_SCALAR(fld, target3) \
- FIELD_SCALAR(fld, target4) \
- FIELD_SCALAR(fld, targetname) \
- FIELD_SCALAR(fld, target) \
- FIELD_SCALAR(fld, target_random) \
- FIELD_SCALAR(fld, target_range) \
- FIELD_SCALAR(fld, team) \
- FIELD_SCALAR(fld, trigger_reverse) \
- FIELD_SCALAR(fld, turret_scale_aim) \
- FIELD_SCALAR(fld, turret_scale_ammo) \
- FIELD_SCALAR(fld, turret_scale_damage) \
- FIELD_SCALAR(fld, turret_scale_health) \
- FIELD_SCALAR(fld, turret_scale_range) \
- FIELD_SCALAR(fld, turret_scale_refire) \
- FIELD_SCALAR(fld, turret_scale_respawn) \
- FIELD_SCALAR(fld, volume) \
- FIELD_SCALAR(fld, wait) \
- FIELD_SCALAR(fld, warpzone_fadeend) \
- FIELD_SCALAR(fld, warpzone_fadestart) \
- FIELD_SCALAR(fld, weapon) \
- FIELD_SCALAR(fld, worldtype) \
- FIELD_VEC(fld, absmax) \
- FIELD_VEC(fld, absmin) \
- FIELD_VEC(fld, angles) \
- FIELD_VEC(fld, avelocity) \
- FIELD_VEC(fld, beam_color)\
- FIELD_VEC(fld, debrisavelocityjitter) \
- FIELD_VEC(fld, debrisvelocity) \
- FIELD_VEC(fld, debrisvelocityjitter) \
- FIELD_VEC(fld, color) \
- FIELD_VEC(fld, mangle) \
- FIELD_VEC(fld, maxs) \
- FIELD_VEC(fld, mins) \
- FIELD_VEC(fld, modelscale_vec) \
- FIELD_VEC(fld, velocity) \
- /**/
-
-ERASEABLE
-void _checkWhitelisted(entity this, string id)
-{
- for (int i = 0, n = numentityfields(); i < n; ++i)
- {
- string value = getentityfieldstring(i, this);
- string s = entityfieldname(i);
- FIELDS_UNION(_spawnfunc_checktypes)
- if (value == "") continue;
- if (s == "") continue;
- FIELDS_COMMON(_spawnfunc_check)
- FIELDS_UNION(_spawnfunc_check)
- LOG_WARNF(_("Entity field %s.%s (%s) is not whitelisted. If you believe this is an error, please file an issue."), id, s, value);
- }
-}
+// this function simply avoids expanding IL_NEW during compilation
+// for each spawning entity
+void g_spawn_queue_spawn() { g_spawn_queue = IL_NEW(); }
noref bool __spawnfunc_first;
if (__spawnfunc_expecting > 1) { __spawnfunc_expecting = 0; } \
else if (__spawnfunc_expecting) { \
/* engine call */ \
- if (!g_spawn_queue) { g_spawn_queue = IL_NEW(); } \
+ if (!g_spawn_queue) g_spawn_queue_spawn(); \
__spawnfunc_expecting = 0; \
this = __spawnfunc_expect; \
__spawnfunc_expect = NULL; \
if (!this.sourceLoc) { \
this.sourceLoc = __FILE__":"STR(__LINE__); \
} \
+ this.classname = #id; \
if (!this.spawnfunc_checked) { \
- _checkWhitelisted(this, #id); \
+ if (__fullspawndata) { \
+ /* not supported in old DP */ \
+ /* must be read inside the real spawnfunc */ \
+ this.fullspawndata = __fullspawndata; \
+ } \
this.spawnfunc_checked = true; \
if (this) { \
/* not worldspawn, delay spawn */ \
+ /* clear some dangerous fields (TODO: properly support these in the map!) */ \
+ this.think = func_null; \
+ this.nextthink = 0; \
__spawnfunc_defer(this, __spawnfunc_##id); \
} else { \
/* world might not be "worldspawn" */ \