noref entity __spawnfunc_expect;
noref bool __spawnfunc_unreachable_workaround = true;
- .void(entity) __spawnfunc_spawn;
+ .void(entity) __spawnfunc_constructor;
noref IntrusiveList g_spawn_queue;
+ #define SPAWNFUNC_INTERNAL_FIELDS(X) \
+ X(string, classname, "spawnfunc") \
+ X(string, target, string_null) \
+ X(string, target2, string_null) \
+ X(string, target3, string_null) \
+ X(string, target4, string_null) \
+ X(string, targetname, string_null) \
+ /**/
+
+ #define X(T, fld, def) .T fld, __spawnfunc_##fld;
+ SPAWNFUNC_INTERNAL_FIELDS(X)
+ #undef X
+
+ void __spawnfunc_defer(entity prototype, void(entity) constructor)
+ {
+ IL_PUSH(g_spawn_queue, prototype);
+ #define X(T, fld, def) { prototype.__spawnfunc_##fld = prototype.fld; prototype.fld = def; }
+ SPAWNFUNC_INTERNAL_FIELDS(X);
+ #undef X
+ prototype.__spawnfunc_constructor = constructor;
+ }
+
+ noref IntrusiveList g_map_entities;
+ #define __spawnfunc_spawn_all() MACRO_BEGIN \
+ g_map_entities = IL_NEW(); \
+ IL_EACH(g_spawn_queue, true, __spawnfunc_spawn(it)); \
+ MACRO_END
+#ifdef SVQC
+ void _SV_OnEntityPreSpawnFunction(entity this);
+#endif
+ void __spawnfunc_spawn(entity prototype)
+ {
+ entity e = new(clone);
+ copyentity(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);
+ #undef X
+#ifdef SVQC
+ _SV_OnEntityPreSpawnFunction(e);
+ if (wasfreed(e)) {
+ return;
+ }
+#endif
+ e.__spawnfunc_constructor(e);
+ }
+
+ noref bool __spawnfunc_first;
+
#define spawnfunc_1(id) spawnfunc_2(id, FIELDS_UNION)
#define spawnfunc_2(id, whitelist) \
void __spawnfunc_##id(entity this); \
[[accumulate]] void spawnfunc_##id(entity this) \
{ \
+ if (!__spawnfunc_first) { \
+ __spawnfunc_first = true; \
+ static_init_early(); \
+ } \
bool dospawn = true; \
if (__spawnfunc_expecting > 1) { __spawnfunc_expecting = false; } \
else if (__spawnfunc_expecting) { \
this.spawnfunc_checked = true; \
if (this) { \
/* not worldspawn, delay spawn */ \
- this.__spawnfunc_spawn = spawnfunc_##id; \
- IL_PUSH(g_spawn_queue, this); \
+ __spawnfunc_defer(this, __spawnfunc_##id); \
+ } else { \
+ /* world might not be "worldspawn" */ \
+ this.__spawnfunc_constructor = __spawnfunc_##id; \
} \
} \
if (dospawn) { __spawnfunc_##id(this); } \