Forum

Calling function on a specific entity

Discuss programming in the QuakeC language.

Moderator: InsideQC Admins

Calling function on a specific entity

Postby Willem » Thu Feb 14, 2008 3:52 pm

So I'm hacking around with some stuff and have a question. I know QuakeC isn't object oriented so you can't call methods within entities but at the same ... man, that would be handy.

I find myself setting up stuff like changing an entities think function to point to a function where I can do something to the entity and then it changes it back to it's regular think. This works but it feels ... hacky and smells bad.

Is there a more elegant way to call functions on an entity that you've just spawned (for example) than this, or is this the only way and I'm wasting time benig annoying about it?

For example, say I have an entity that spawns a monster_army. I then want to call a function on that entity. This is how I currently do it:

myentity = spawn();
myentity.think = monster_army_myinitfunction;
myentity.nextthink = time + 0.01;

And then monster_army_myinitfunction will get called next frame. Which works. But it smells bad. Is there a better way?
Willem
 
Posts: 73
Joined: Wed Jan 23, 2008 10:58 am

Postby Wazat » Thu Feb 14, 2008 5:19 pm

Well, there's:

myentity = spawn();
// call init function with self pointing to the new entity
oldself = self;
self = myentity;
monster_army_myinitfunction();
self = oldself; // get self back to what it used to be

That's the standard way of doing it in QC. I hope it helps.
When my computer inevitably explodes and kills me, my cat inherits everything I own. He may be the only one capable of continuing my work.
Wazat
 
Posts: 771
Joined: Fri Oct 15, 2004 9:50 pm
Location: Middle 'o the desert, USA

Postby FrikaC » Thu Feb 14, 2008 5:24 pm

The more common way to do it is:
Code: Select all
local entity oself;
...

oself = self;
self = spawn();
monster_army_myinitfunction();
self = oself;


This has the advantage that it's done immediately, not when the engine gets around to calling thinks on your new entity, so if there's any setup you're reliant upon it will be done right away.

Prydon Gate encapsulated this behavior in a function because I found myself doing it a lot. This requires fteqcc/frikqcc to be properly parsed however.

Code: Select all
void(entity e, void() func) call =
{
   local entity oself;
   oself = self;
   self = e;
   func();
   self = oself;
};


With this function, you can then simplify the above code to:

Code: Select all
call (spawn(), monster_army_myinitfunction);


Additional versions of call can be created taking more parameters for the function & offering back return values. It's not totally ideal, but it really helps clean up code on occasion. [/code]
FrikaC
Site Admin
 
Posts: 1026
Joined: Fri Oct 08, 2004 11:19 pm

Postby Willem » Thu Feb 14, 2008 5:55 pm

Thanks guys! It never occured to me that "self" would be writable. Nice!
Willem
 
Posts: 73
Joined: Wed Jan 23, 2008 10:58 am

Postby Urre » Fri Feb 15, 2008 8:51 am

One should also note that as long as you're using NetQuake (that is, not QuakeWorld) you can do
Code: Select all
myentity.nextthink = time;

which makes it call the think function the very next server frame, no matter the framerate, whereas time + 0.01 wouldn't be called the next frame if the fps is above 100, which isn't that uncommon in a singleplayer game for example. This is especially useful when you want to do funky things like physics in QC, which require execution every frame, and advanced AI like bots often use this as well.
I was once a Quake modder
User avatar
Urre
 
Posts: 1109
Joined: Fri Nov 05, 2004 2:36 am
Location: Moon


Return to QuakeC Programming

Who is online

Users browsing this forum: Bing [Bot] and 1 guest