-#ifndef SPAWNFUNC_H
-#define SPAWNFUNC_H
+#pragma once
/** If this global exists, only functions with spawnfunc_ name prefix qualify as spawn functions */
noref bool require_spawnfunc_prefix;
#define _spawnfunc_checktypes(fld) \
if (fieldname == #fld) \
- if (!entityfieldassignablefromeditor(i)) LOG_FATALF("Entity field '%s' cannot be whitelisted\n", fieldname);
+ if (!entityfieldassignablefromeditor(i)) LOG_FATALF("Entity field '%s' cannot be whitelisted", fieldname);
#else
#define _spawnfunc_checktypes(fld)
#endif
#define _spawnfunc_check(fld) \
if (fieldname == #fld) continue;
- #define spawnfunc_1(id, whitelist) spawnfunc_2(id, whitelist)
+ noref bool __spawnfunc_expecting;
+ noref entity __spawnfunc_expect;
+ noref bool __spawnfunc_unreachable_workaround = true;
+
+ #define spawnfunc_1(id) spawnfunc_2(id, FIELDS_UNION)
#define spawnfunc_2(id, whitelist) \
- void spawnfunc_##id(entity this) \
+ void __spawnfunc_##id(entity this); \
+ [[accumulate]] void spawnfunc_##id(entity this) \
{ \
- this = self; \
+ if (__spawnfunc_expecting) \
+ { \
+ /* engine call */ \
+ __spawnfunc_expecting = false; \
+ this = __spawnfunc_expect; \
+ __spawnfunc_expect = NULL; \
+ } \
+ else \
+ { \
+ assert(this); \
+ } \
+ if (!this.sourceLoc) \
+ { \
+ this.sourceLoc = __FILE__ ":" STR(__LINE__); \
+ } \
if (!this.spawnfunc_checked) \
{ \
for (int i = 0, n = numentityfields(); i < n; ++i) \
if (fieldname == "") continue; \
FIELDS_COMMON(_spawnfunc_check) \
whitelist(_spawnfunc_check) \
- 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); \
+ LOG_WARNF(_("Entity field %s.%s (%s) is not whitelisted. If you believe this is an error, please file an issue."), #id, fieldname, value); \
} \
this.spawnfunc_checked = true; \
} \
+ __spawnfunc_##id(this); \
+ if (__spawnfunc_unreachable_workaround) return; \
} \
- [[accumulate]] void spawnfunc_##id(entity this)
+ void __spawnfunc_##id(entity this)
#define FIELD_SCALAR(fld, n) \
fld(n)
#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, 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, platmovetype) \
FIELD_SCALAR(fld, race_place) \
FIELD_SCALAR(fld, radius) \
+ FIELD_SCALAR(fld, respawntimestart) \
FIELD_SCALAR(fld, respawntimejitter) \
FIELD_SCALAR(fld, respawntime) \
FIELD_SCALAR(fld, restriction) \
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, target2) \
FIELD_VEC(fld, maxs) \
FIELD_VEC(fld, mins) \
FIELD_VEC(fld, modelscale_vec) \
- FIELD_VEC(fld, origin) \
FIELD_VEC(fld, velocity) \
/**/
- #define spawnfunc(...) EVAL(OVERLOAD(spawnfunc, __VA_ARGS__, FIELDS_UNION))
-
-#endif
+ #define spawnfunc(...) EVAL_spawnfunc(OVERLOAD(spawnfunc, __VA_ARGS__))
+ #define EVAL_spawnfunc(...) __VA_ARGS__