X-Git-Url: https://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=blobdiff_plain;f=qcsrc%2Flib%2Fspawnfunc.qh;h=d3198b3ce4c7666bf986564916b9d9678b3dc097;hp=e0605c93840599e8f928f359ce1f6b02cccd7016;hb=7e5268799e95d0dd6f2b77ed4e097b0adc755f2b;hpb=2183056a5b6e75d2e025aa6c718eeb6f87de31b6 diff --git a/qcsrc/lib/spawnfunc.qh b/qcsrc/lib/spawnfunc.qh index e0605c938..d3198b3ce 100644 --- a/qcsrc/lib/spawnfunc.qh +++ b/qcsrc/lib/spawnfunc.qh @@ -19,54 +19,116 @@ noref bool require_spawnfunc_prefix; } #define _spawnfunc_checktypes(fld) \ - if (fieldname == #fld) \ - if (!entityfieldassignablefromeditor(i)) LOG_FATALF("Entity field '%s' cannot be whitelisted", fieldname); + if (s == #fld) \ + if (!entityfieldassignablefromeditor(i)) LOG_FATALF("Entity field '%s' cannot be whitelisted", s); #else #define _spawnfunc_checktypes(fld) #endif #define _spawnfunc_check(fld) \ - if (fieldname == #fld) continue; + if (s == #fld) continue; - noref bool __spawnfunc_expecting; + noref int __spawnfunc_expecting; noref entity __spawnfunc_expect; noref bool __spawnfunc_unreachable_workaround = true; + .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) \ + ACCUMULATE void spawnfunc_##id(entity this) \ { \ - if (__spawnfunc_expecting) \ - { \ + if (!__spawnfunc_first) { \ + __spawnfunc_first = true; \ + static_init_early(); \ + } \ + bool dospawn = true; \ + if (__spawnfunc_expecting > 1) { __spawnfunc_expecting = false; } \ + else if (__spawnfunc_expecting) { \ /* engine call */ \ + if (!g_spawn_queue) { g_spawn_queue = IL_NEW(); } \ __spawnfunc_expecting = false; \ this = __spawnfunc_expect; \ __spawnfunc_expect = NULL; \ - } \ - else \ - { \ + dospawn = false; \ + } else { \ + /* userland call */ \ assert(this); \ } \ - if (!this.sourceLoc) \ - { \ + if (!this.sourceLoc) { \ this.sourceLoc = __FILE__ ":" STR(__LINE__); \ } \ - if (!this.spawnfunc_checked) \ - { \ - for (int i = 0, n = numentityfields(); i < n; ++i) \ - { \ + if (!this.spawnfunc_checked) { \ + for (int i = 0, n = numentityfields(); i < n; ++i) { \ string value = getentityfieldstring(i, this); \ - string fieldname = entityfieldname(i); \ + string s = entityfieldname(i); \ whitelist(_spawnfunc_checktypes) \ if (value == "") continue; \ - if (fieldname == "") continue; \ + if (s == "") continue; \ FIELDS_COMMON(_spawnfunc_check) \ whitelist(_spawnfunc_check) \ - LOG_WARNF(_("Entity field %s.%s (%s) is not whitelisted. If you believe this is an error, please file an issue."), #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, s, value); \ } \ this.spawnfunc_checked = true; \ + if (this) { \ + /* not worldspawn, delay spawn */ \ + __spawnfunc_defer(this, __spawnfunc_##id); \ + } else { \ + /* world might not be "worldspawn" */ \ + this.__spawnfunc_constructor = __spawnfunc_##id; \ + } \ } \ - __spawnfunc_##id(this); \ + if (dospawn) { __spawnfunc_##id(this); } \ if (__spawnfunc_unreachable_workaround) return; \ } \ void __spawnfunc_##id(entity this) @@ -94,12 +156,14 @@ noref bool require_spawnfunc_prefix; 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) \ @@ -107,6 +171,8 @@ noref bool require_spawnfunc_prefix; 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) \ @@ -117,10 +183,12 @@ noref bool require_spawnfunc_prefix; 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) \ @@ -151,6 +219,7 @@ noref bool require_spawnfunc_prefix; FIELD_SCALAR(fld, noalign) \ FIELD_SCALAR(fld, noise1) \ FIELD_SCALAR(fld, noise2) \ + FIELD_SCALAR(fld, noise3) \ FIELD_SCALAR(fld, noise) \ FIELD_SCALAR(fld, phase) \ FIELD_SCALAR(fld, platmovetype) \ @@ -178,6 +247,7 @@ noref bool require_spawnfunc_prefix; FIELD_SCALAR(fld, target_random) \ FIELD_SCALAR(fld, target_range) \ FIELD_SCALAR(fld, team) \ + FIELD_SCALAR(fld, trigger_reverse) \ FIELD_SCALAR(fld, turret_scale_health) \ FIELD_SCALAR(fld, turret_scale_range) \ FIELD_SCALAR(fld, turret_scale_respawn) \ @@ -191,10 +261,13 @@ noref bool require_spawnfunc_prefix; 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, maxs) \ FIELD_VEC(fld, mins) \ FIELD_VEC(fld, modelscale_vec) \ FIELD_VEC(fld, velocity) \