From 5bfd3a4df8b00548c9ab0c711783a264267077d3 Mon Sep 17 00:00:00 2001 From: div0 Date: Thu, 28 Aug 2008 07:39:24 +0000 Subject: [PATCH] - get rid of delayed init where I found it and replace it by something that runs BEFORE think (in the very first StartFrame); makes sure misc_follow can work right (as all entities are on their INITIAL location then) - make misc_laser work with misc_follow git-svn-id: svn://svn.icculus.org/nexuiz/trunk@4216 f962a42d-fe04-0410-a3ab-8c8b0445ebaa --- data/qcsrc/server/ctf.qc | 8 +--- data/qcsrc/server/defs.qh | 1 + data/qcsrc/server/domination.qc | 7 +-- data/qcsrc/server/g_lights.qc | 38 +++++++++------- data/qcsrc/server/g_triggers.qc | 27 ++++++------ data/qcsrc/server/miscfunctions.qc | 70 ++++++++++++++++++++++++++++++ data/qcsrc/server/sv_main.qc | 2 + data/qcsrc/server/t_jumppads.qc | 3 +- data/qcsrc/server/t_plats.qc | 8 ++-- data/qcsrc/server/t_teleporters.qc | 4 +- data/qcsrc/server/teamplay.qc | 16 +------ 11 files changed, 120 insertions(+), 64 deletions(-) diff --git a/data/qcsrc/server/ctf.qc b/data/qcsrc/server/ctf.qc index f2d1690c6..471baa2ee 100644 --- a/data/qcsrc/server/ctf.qc +++ b/data/qcsrc/server/ctf.qc @@ -662,8 +662,6 @@ void ctf_spawnteams() void ctf_delayedinit() { - self.think = SUB_Remove; - self.nextthink = time; // if no teams are found, spawn defaults if (find(world, classname, "ctf_team") == world) ctf_spawnteams(); @@ -673,11 +671,7 @@ void ctf_delayedinit() void ctf_init() { - local entity e; - - e = spawn(); - e.think = ctf_delayedinit; - e.nextthink = time + 0.1; + InitializeEntity(world, ctf_delayedinit, INITPRIO_GAMETYPE); flagcaptimerecord = stof(db_get(ServerProgsDB, strcat(GetMapname(), "/captimerecord/time"))); }; diff --git a/data/qcsrc/server/defs.qh b/data/qcsrc/server/defs.qh index 8add124c5..070c870ff 100644 --- a/data/qcsrc/server/defs.qh +++ b/data/qcsrc/server/defs.qh @@ -28,6 +28,7 @@ float sv_foginterval; entity activator; string string_null; +const var void(void) func_null; float player_count; float currentbots; diff --git a/data/qcsrc/server/domination.qc b/data/qcsrc/server/domination.qc index 714f9b60e..9d210052f 100644 --- a/data/qcsrc/server/domination.qc +++ b/data/qcsrc/server/domination.qc @@ -560,8 +560,6 @@ void dom_delayedinit() { local entity head; - self.think = SUB_Remove; - self.nextthink = time; // if no teams are found, spawn defaults if (find(world, classname, "dom_team") == world) dom_spawnteams(); @@ -592,7 +590,6 @@ void dom_delayedinit() void dom_init() { - local entity e; // we have to precache default models/sounds even if they might not be // used because spawnfunc_worldspawn is executed before any other entities are read, // so we don't even know yet if this map is set up for domination... @@ -602,9 +599,7 @@ void dom_init() precache_model("models/domination/dom_pink.md3"); precache_model("models/domination/dom_unclaimed.md3"); precache_sound("domination/claim.wav"); - e = spawn(); - e.think = dom_delayedinit; - e.nextthink = time + 0.1; + InitializeEntity(world, dom_delayedinit, INITPRIO_GAMETYPE); // teamplay is always on in domination, defaults to hurt self but not teammates //if(!cvar("teamplay")) diff --git a/data/qcsrc/server/g_lights.qc b/data/qcsrc/server/g_lights.qc index 9af723115..ce4acc620 100644 --- a/data/qcsrc/server/g_lights.qc +++ b/data/qcsrc/server/g_lights.qc @@ -33,11 +33,13 @@ void dynlight_think() if(!self.owner) remove(self); - self.nextthink = 0.1; + self.nextthink = time + 0.1; }; void dynlight_find_aiment() { local entity targ; + if (!self.target) + objerror ("dynlight: no target to follow"); targ = find(world, targetname, self.target); self.movetype = MOVETYPE_FOLLOW; @@ -46,19 +48,33 @@ void dynlight_find_aiment() self.punchangle = targ.angles; self.view_ofs = self.origin - targ.origin; self.v_angle = self.angles - targ.angles; - self.nextthink = 0.1; self.think = dynlight_think; + self.nextthink = time + 0.1; }; void dynlight_find_path() { local entity targ; + if (!self.target) + objerror ("dynlight: no target to follow"); targ = find(world, targetname, self.target); self.target = targ.target; setorigin (self, targ.origin); - self.nextthink = self.ltime + 0.1; self.think = train_next; + self.nextthink = time + 0.1; }; +void dynlight_find_target() +{ + local entity targ; + if (!self.target) + objerror ("dynlight: no target to follow"); + + targ = find(world, targetname, self.target); + setattachment(self, targ, self.dtagname); + self.owner = targ; + self.think = dynlight_think; + self.nextthink = time + 0.1; +} void dynlight_use() { if (self.light_lev == 0) @@ -89,22 +105,14 @@ void spawnfunc_dynlight() //tag attaching if (self.dtagname) { - if (!self.target) - objerror ("dynlight: no target to follow"); - targ = find(world, targetname, self.target); - setattachment(self, targ, self.dtagname); - self.owner = targ; - self.think = dynlight_think; + InitializeEntity(self, dynlight_find_target, INITPRIO_FINDTARGET); return; } // entity following if (self.spawnflags & DFOLLOW) { - if (!self.target) - objerror ("dynlight: no target to follow"); - self.nextthink = time + 0.1; - self.think = dynlight_find_aiment; + InitializeEntity(self, dynlight_find_aiment, INITPRIO_FINDTARGET); return; } // path following @@ -114,7 +122,7 @@ void spawnfunc_dynlight() self.movetype = MOVETYPE_PUSH; if (!self.speed) self.speed = 100; - self.nextthink = self.ltime + 0.1; - self.think = dynlight_find_path; + InitializeEntity(self, dynlight_find_path, INITPRIO_FINDTARGET); + return; } }; diff --git a/data/qcsrc/server/g_triggers.qc b/data/qcsrc/server/g_triggers.qc index 39e82b528..fd325cb31 100644 --- a/data/qcsrc/server/g_triggers.qc +++ b/data/qcsrc/server/g_triggers.qc @@ -712,9 +712,9 @@ void misc_laser_aim() { a = vectoangles(self.enemy.origin - self.origin); a_x = -a_x; - if(a != self.angles) + if(a != self.mangle) { - self.angles = a; + self.mangle = a; self.SendFlags |= 2; } } @@ -725,24 +725,23 @@ void misc_laser_aim() } } +void misc_laser_init() +{ + self.enemy = find(world, targetname, self.target); +} + void misc_laser_think() { vector o; self.nextthink = time; - if(!self.count) - { - self.enemy = find(world, targetname, self.target); - self.count = 1; - } - if(!self.state) return; misc_laser_aim(); - makevectors(self.angles); + makevectors(self.mangle); o = self.origin + 32768 * v_forward; if(self.dmg) @@ -773,8 +772,8 @@ float laser_SendEntity(entity to, float fl) } if(fl & 2) { - WriteCoord(MSG_ENTITY, self.angles_x); - WriteCoord(MSG_ENTITY, self.angles_y); + WriteCoord(MSG_ENTITY, self.mangle_x); + WriteCoord(MSG_ENTITY, self.mangle_y); } if(fl & 4) WriteByte(MSG_ENTITY, self.state); @@ -818,6 +817,7 @@ void spawnfunc_misc_laser() self.message = "saw the light"; self.think = misc_laser_think; self.nextthink = time; + InitializeEntity(self, misc_laser_init, INITPRIO_FINDTARGET); self.effects = EF_NODEPTHTEST; self.SendEntity = laser_SendEntity; @@ -1069,7 +1069,7 @@ void spawnfunc_trigger_monoflop() self.state = 0; } -void follow_think() +void follow_init() { entity src, dst; src = find(world, targetname, self.killtarget); @@ -1092,6 +1092,5 @@ void follow_think() void spawnfunc_misc_follow() { - self.think = follow_think; - self.nextthink = time; + InitializeEntity(self, follow_init, INITPRIO_FINDTARGET); } diff --git a/data/qcsrc/server/miscfunctions.qc b/data/qcsrc/server/miscfunctions.qc index 8c0be7967..f621f05f4 100644 --- a/data/qcsrc/server/miscfunctions.qc +++ b/data/qcsrc/server/miscfunctions.qc @@ -1190,3 +1190,73 @@ float ExactTriggerHit() // WARNING: this kills the trace globals #define EXACTTRIGGER_TOUCH if not(ExactTriggerHit()) return #define EXACTTRIGGER_INIT InitSolidBSPTrigger(); self.solid = SOLID_TRIGGER + +#define INITPRIO_FIRST 0 +#define INITPRIO_GAMETYPE 0 +#define INITPRIO_GAMETYPE_FALLBACK 1 +#define INITPRIO_FINDTARGET 10 +#define INITPRIO_SETLOCATION 90 +#define INITPRIO_LAST 99 + +.void(void) initialize_entity; +.float initialize_entity_order; +.entity initialize_entity_next; +entity initialize_entity_first; +void InitializeEntity(entity e, void(void) func, float order) +{ + entity prev, cur; + + if(!e || e.initialize_entity) + { + // make a proxy initializer entity + entity e_old; + e_old = e; + e = spawn(); + e.classname = "initialize_entity"; + e.enemy = e_old; + } + + e.initialize_entity = func; + e.initialize_entity_order = order; + + cur = initialize_entity_first; + for(;;) + { + if(!cur || cur.initialize_entity_order > order) + { + // insert between prev and cur + if(prev) + prev.initialize_entity_next = e; + else + initialize_entity_first = e; + e.initialize_entity_next = cur; + return; + } + prev = cur; + cur = cur.initialize_entity_next; + } +} +void InitializeEntitiesRun() +{ + for(self = initialize_entity_first; self; ) + { + entity e; + var void(void) func; + e = self.initialize_entity_next; + func = self.initialize_entity; + self.initialize_entity_order = 0; + self.initialize_entity = func_null; + self.initialize_entity_next = world; + if(self.classname == "initialize_entity") + { + entity e_old; + e_old = self.enemy; + remove(self); + self = e_old; + } + dprint("Delayed initialization: ", self.classname, "\n"); + func(); + self = e; + } + initialize_entity_first = world; +} diff --git a/data/qcsrc/server/sv_main.qc b/data/qcsrc/server/sv_main.qc index d547be831..ff980a4ff 100644 --- a/data/qcsrc/server/sv_main.qc +++ b/data/qcsrc/server/sv_main.qc @@ -136,6 +136,8 @@ void StartFrame (void) if(RedirectionThink()) return; + InitializeEntitiesRun(); + sv_maxairspeed = cvar("sv_maxairspeed"); sv_maxspeed = cvar ("sv_maxspeed"); sv_friction = cvar ("sv_friction"); diff --git a/data/qcsrc/server/t_jumppads.qc b/data/qcsrc/server/t_jumppads.qc index ada452bdb..c50afb1b6 100644 --- a/data/qcsrc/server/t_jumppads.qc +++ b/data/qcsrc/server/t_jumppads.qc @@ -255,8 +255,7 @@ void spawnfunc_trigger_push() precache_sound (self.noise); // this must be called to spawn the teleport waypoints for bots - self.think = trigger_push_findtarget; - self.nextthink = time + 0.2; + InitializeEntity(self, trigger_push_findtarget, INITPRIO_FINDTARGET); }; void spawnfunc_target_push() {}; diff --git a/data/qcsrc/server/t_plats.qc b/data/qcsrc/server/t_plats.qc index e95215be2..3bcaf46a5 100644 --- a/data/qcsrc/server/t_plats.qc +++ b/data/qcsrc/server/t_plats.qc @@ -344,6 +344,8 @@ void func_train_find() local entity targ; targ = find(world, targetname, self.target); self.target = targ.target; + if (!self.target) + objerror("func_train_find: no next target"); setorigin(self, targ.origin - self.mins); self.nextthink = self.ltime + 1; self.think = train_next; @@ -365,8 +367,7 @@ void spawnfunc_func_train() self.effects |= EF_LOWPRECISION; // wait for targets to spawn - self.nextthink = self.ltime + 0.1; - self.think = func_train_find; + InitializeEntity(self, func_train_find, INITPRIO_SETLOCATION); }; @@ -1126,8 +1127,7 @@ void spawnfunc_func_door() // LinkDoors can't be done until all of the doors have been spawned, so // the sizes can be detected properly. - self.think = LinkDoors; - self.nextthink = self.ltime + 0.1; + InitializeEntity(self, LinkDoors, INITPRIO_FINDTARGET); }; /* diff --git a/data/qcsrc/server/t_teleporters.qc b/data/qcsrc/server/t_teleporters.qc index a063efcf2..c3441b2d7 100644 --- a/data/qcsrc/server/t_teleporters.qc +++ b/data/qcsrc/server/t_teleporters.qc @@ -129,8 +129,8 @@ void spawnfunc_trigger_teleport (void) EXACTTRIGGER_INIT; - self.think = teleport_findtarget; - self.nextthink = time + 0.2; + // this must be called to spawn the teleport waypoints for bots + InitializeEntity(self, teleport_findtarget, INITPRIO_FINDTARGET); if (!self.target) objerror ("Teleporter with no target"); diff --git a/data/qcsrc/server/teamplay.qc b/data/qcsrc/server/teamplay.qc index f70a7ccb3..33e1fbd57 100644 --- a/data/qcsrc/server/teamplay.qc +++ b/data/qcsrc/server/teamplay.qc @@ -142,8 +142,6 @@ void ReadGameCvars() void default_delayedinit() { - remove(self); - if(!scores_initialized) ScoreRules_generic(); } @@ -333,10 +331,7 @@ void InitGameplayMode() cvar_set("fraglimit", "0"); } - entity e; - e = spawn(); - e.nextthink = time + 0.3; // MUST be after all other delayed inits! - e.think = default_delayedinit; + InitializeEntity(world, default_delayedinit, INITPRIO_GAMETYPE_FALLBACK); } string GetClientVersionMessage() { @@ -1323,8 +1318,6 @@ void tdm_spawnteams() void tdm_delayedinit() { - self.think = SUB_Remove; - self.nextthink = time; // if no teams are found, spawn defaults if (find(world, classname, "tdm_team") == world) tdm_spawnteams(); @@ -1332,10 +1325,5 @@ void tdm_delayedinit() void tdm_init() { - local entity e; - e = spawn(); - e.think = tdm_delayedinit; - e.nextthink = time + 0.1; + InitializeEntity(world, tdm_delayedinit, INITPRIO_GAMETYPE); }; - - -- 2.39.2