A third, mercifully brief post on an alternate way to fix the EndFrame – upgrade the compiler! Spike posted that the daily builds of fteqcc fix this issue, and they’ve been hidden away at:
http://triptohell.info/moodles/fteqcc/
Apart from fixing the assign to field issues from the last post there seem to be some new features like type checking on function assignments, so go check it out. This lets us get rid of a lot of the workarounds from the bug investigation post, but since one of the bugs was in my code, the full working EndFrame code follows…
We have to modify existing code to implement all of this so it ends up spread out between files. Firstly replace the definition of spawn in defs.qc with
entity() spawn_builtin = #14; entity() spawn; //to be defined later
Then in world.qc add the following to the top
entity backstop;
void() EndFrame =
{
// set ourselves up to think again next frame
self.nextthink = 0.05;
// prevent accidental modification of the backstop
self = world;
// demonstrate the function
bprint("EndFrame call at time ");
bprint(ftos(time));
bprint("\n&");
}
entity() spawn =
{
local entity e;
e = spawn_builtin();
if(nextent(e) != world)
return e;
// e is now the last entity on the list
// so we need to swap it with the backstop
local entity f;
f = backstop;
f.think = e.think;
f.nextthink = e.nextthink;
f.classname = e.classname;
e.think = EndFrame;
e.nextthink = 0.05;
e.classname = "backstop";
backstop = e;
return f;
}
void() CreateBackstop =
{
local entity e, f, head;
//begin our list with the temp backstop
e = f = head = backstop;
// spawn() already contains the code to make a backstop
// so we just burn off enough entities that one appears
// at the back
do
{
f = spawn();
e.chain = f;
e = e.chain;
}
while(nextent(backstop) != world);
while(head != f)
{
e = head;
head = e.chain;
remove(e);
};
}
Two modifications need to be made to existing functions. Firstly, at the very top of worldspawn() add backstop = spawn_builtin();. Because spawn() modifies the current backstop entity while initializing a new one, we will cause a crash if backstop is the world entity. Note that we haven’t yet initialized the backstop, because all of the map loaded entities are yet to spawn – we’re just preventing the crash if one of the spawnfunctions calls spawn() immediately. To perform the initialisation, add the following to the bottom of StartFrame():
if(framecount == 1)
CreateBackstop();
bprint("StartFrame call at time ");
bprint(ftos(time));
bprint("\n");
[…] the Endframe function to see the investigation of the bug and learn a bit about bytecode, or read Easily fixing the EndFrame function to get a fixed version of the compiler and the bug-fixed version of this […]
[…] ← Creating the EndFrame function Easily fixing the EndFrame function → […]