News | Forum | People | FAQ | Links | Search | Register | Log in
Coding Help
This is a counterpart to the "Mapping Help" thread. If you need help with QuakeC coding, or questions about how to do some engine modification, this is the place for you! We've got a few coders here on the forum and hopefully someone knows the answer.
First Post! 
So, here's what I'm trying to do right now, and probably nobody knows the answer but here goes. What I'm trying to set up is an entity that emits a constant sound, but is also toggleable. So when you turn it off, the sound goes silent, and when you turn it on, the sound starts up again.

Problem 1: if you are out of hearing range when it turns on, the object will be silent when you get close.

Problem 2: if you save and reload the savegame, the object will be silent.

The basic cause is that sound() calls are fire-and-forget and quake assumes the sounds are short-lived so the above situations won't be much of a problem.

I've tried various solutions, the latest is various versions of "restart the sound every 1 second or so." The problems with that are first, when you approach the object its sound starts up suddenly instead of fading in, and second, you can hear obvious repetition when standing next to the object.

Increasing the frequency of sound() calls reduces the sudden start, but worsens the repetition. I'm going to try and improve this hack by having 3 or four different sounds, and playing them at random, so that you don't hear any obvious repetition of sounds. 
 
it is possible, but it's slightly hacky.

unfortunaly, i don't remember who told me about this method... it may have been lordhavoc, but i'm not sure.

anyway, the engine can only load ambient sounds (true ambient sounds that the engine keeps track of regardless of player position) properly when the map is loading up.

you can trick it by using an unused SVC (29). unfortunatly, you can't specify a filename for this, you need to actually feed in the # of the sound in the order as it was loaded into cache. �_�

the best way to do this is to precache your ambient sounds first, this way you don't have to worry about anything being precached before it and mucking up your ambient sounds.

the first sound precaches are located in weapons.qc (W_Precache). load any new ambient sounds in there at the top of the function.


float SVC_SPAWNSTATICSOUND = 29;

Define the constant for convenience, and write a little function to use it:
void(float soundnum, vector org, float ambvolume, float atten) spawnambient =
{
WriteByte(MSG_ALL, SVC_SPAWNSTATICSOUND);
WriteCoord(MSG_ALL, org_x);
WriteCoord(MSG_ALL, org_y);
WriteCoord(MSG_ALL, org_z);
WriteByte(MSG_ALL, soundnum);
WriteByte(MSG_ALL, ambvolume * 255); //translate this into a value between 0 and 255...
WriteByte(MSG_ALL, atten * 64);
};


now just call your new function with whatever sound # you want.

this will spawn a true ambient sound into the map after it was loaded, and won't stop playing when you move out of range.

you'll notice the lack of any channel specification... i'm not sure if it's possible to turn it off again after it's been turned on. i can't check right now, but i'd guess using a non-looping sound will give you that 'non-looping sound for ambient sound' error, since it's not just a normal sound call.
but you will at least be able to turn it on. :x

maybe someone else can build on this? 
Necros.... 
Interesting, it would only work if the it could be turned off again somehow. Hmm.... 
Also... 
my hack with the multiple random 0.1 sec sound effects works fairly well, but the problem is you can hear a sort of distortion/clip sound when the new sound overrides the old (the same sound you hear when a sound isn't looped correctly, meaning the waveforms don't line up and there's a sort of audio seam.) I may have to live with it. The sound effect for this has a lot of white noise in it (it's a steam jet) but I also wanted to do this for forcefields, and i'm worried that sound won't hide the clipping artifact as well. 
Savegame Function 
As it happens I was writing some code yesterday that might help you out. What it does is provides you with a function that is run once when you load a saved game, but not when the game starts first time round. Replace the StartFrame code in world.qc with the following:

nosave float loadflag;

void() LoadGame =
//runs if player has just loaded a game
{
dprint("*****new game loaded******\n");
}

void() StartFrame =
{
teamplay = cvar("teamplay");
skill = cvar("skill");
framecount = framecount + 1;


if ( framecount == 3)
loadflag = 1;//started a new game, not loaded a savegame

else if(!loadflag && framecount > 3)
{
LoadGame();
loadflag = 1;
}

};

You'll need a compiler which supports the nosave keyword for variables, frikqcc and fteqcc are the two I've tried. The idea is that the loadflag isn't saved in the savegame, and so gets reset to 0 when you load a game. The reason you have to wait until the third frame before you set it originally is because when quake loads a savegame, it runs the whole worldspawn procedure to rebuild the precache lists. The worldspawn procedure includes running two game frames, to give things a chance to droptofloor etc. So if you change a nosave variable during those frames, it'll have that value when you load savegames - which might be different to what value it had when you saved - but it's not what we want here.

So that gives you a way to restart the sound after someone loads a game, replace the dprint line in LoadGame with a function that searches for all the sounds that should play and restarts them.


As for the other problem, one possible solution would be to calculate the distance at which the sound can just be heard, assuming you started in range of the sound. Then have the entities search for a player within this radius regularly and start playing when they just enter it. Might be more difficult to make it work in coop.

If you do that, then you don't really want to use findradius for the job, it's a bit excessive to have 10 findradius calls every second per entity if you have a few of these things about. Better to loop through the first maxplayers worth of entities with the nextent command, since the players are always the first entities on the server. Then just test the distance for each of those that turns out to be a player. Whether
vlen(vec) < d
is faster than
vec_x*vec_x + vec_y*vec_y + vec_z*vec_z < d*d
is something I've been meaning to test. One is trying to calculate the square root of a quantity, but it is a builtin, so it's faster than qc code. Probably not necessary to get that kind of saving here if you're testing at most 16 entities, and most of the time just 1, it's just an interesting question. 
Preach.... 
yeah, this findradius idea is the direction i'm thinking of going next. One challenge is, the code to play a sound will not bother playing a sound if both right and left stereo channels can't hear it, and the calculation to determine the volume at each "ear" (channel) is somewhat complicated. Not sure if i'll need to recreate that in quakec or if it will suffice to estimate the radius in some other way. 
Toggleable Sound 
The music in FMB_bdg is toggleable and plays everywhere. Being a looped sound, it would play forever if not switched off by the player (by operating the music button) or when the player unwittingly moves through an off-trigger.

It doesn't play from a savegame even if it was playing when the game was saved. But the savegame must be recording the state of the entity because you have to operate the music trigger twice after a savegame if you want the music to play - the first time turns the music off even though you can't hear it, and the second time turns it back on, and you then hear it.

I created the entity following an idea by Preach.
// if the player has not touched the 'toggle-music' button then this must be
// a triggered event, which means....
if (mechanism.classname != "func_button") etc...

Could this be developed to check the state of the entity when opening a saved game and play the sound if TRUE? Or am I completely off-track understanding what you want to do? 
Mike: 
well, it sounds like preach's save game code would fix your problem, but I have a second problem that you don't have, which is that the sound won't play at all if you are too far away at the time it is first triggered. Your music is always audible, so there's no worry about being too far from the emitter at the time that it starts up. 
Model Import 
I started messing with the quake model gen source to make it parse ascii files instead of .TRI, so that I could export to text from my modeler of choice (ie maya). I got all that working fine as far as I can tell, but the .mdl that gets written out crashes Fitzquake and every model editor I've found to try. Stepping through the exporter in debug doesn't really seem to show anything wrong, as the data is all seemingly correct before it gets written.

I took a break bashing my head against this a long time ago (like the end of 2006 now that I think about it :( ), so if I started poking at it now it might become obvious to me, but does anyone have any tips or suggestions? Are there any quake ports or other bits of software that I can try to load a model in that will actually tell me what part of the file is horked rather than just pooping? 
Model Import 
A good starting place would be:
http://tfc.duke.free.fr/coding/mdl-specs-en.html

This gives you a big chunk of c code that will read a mdl file. You can skip the chunk about rendering it and just write a quick function that prints out the header data once it's loaded it, to check whether that's been written correct or not.

You might also want to look at
http://people.pwf.cam.ac.uk/~ajd70/mdl_export.py
it's an export script for blender written in python. I wish I could remember what I did to make it work though, I had the same problems as you are and spent a few hours staring at a hex editor to find out what went wrong. If anything jogs my memory I'll let you know. Shame I never got round to writing the corresponding import script, it'd probably be good for diagnosing the problem... 
Yeah 
I've looked over all that in the quake and modelgen sources, but I'm not very confident in writing a new piece of software to check why the last piece of software I wrote doesn't work, because clearly there's no guarantees the new one's not going to be fucked in some tiny significant way also, especially if they're both doing the same things to the same data structures. I'm just a simian level designer.

Part of the problem is that I had to do so much to get the thing to a testable state - .bmp import for the skin and then my ascii reader thing, because there's no program left on earth to write TRI files and there's no program left on earth that'll write whatever silly-ass image format modelgen looks for. 
Hmm 
Well, upload an example model that the tool exports and I'll take a look at it, try and figure out what's wrong with it. 
Okay... 
The steam jet sound problems seem to be solved.

First, I play the looping sound whenever the object is turned on, and the "fade out" sound whenever it is turned off. This was the original naive implementation.

Second, to deal with the problem of steam jets turning on when you're far away, I re-trigger the sound every 0.1 seconds when you are between 300 and 350 units away. The clipping sound artifact is there, but since it's so quiet at that distance, you barely hear it. When you get closer, it stops re-triggering it so you can hear a perfectly looped sound.

Third, I used Preach's loadgame callback idea to retrigger all sounds in case you are standing within 300 units when you save and reload the game.

Problem solved! Thanks for the help preach. 
Oh Wow 
thanks Preach! It might take me a bit to gather all the code and stuff back up and actually produce one, but I'll hit that this weekend. 
Pointers Anyone? 
So I thought I would try Preach's code from above and simply put a call to my music_play_tune routine for any savegame but got this super message from aguirRe's engine.

This Onion
CDAudio: drive not ready
CL_SignonReply: 1
CL_SignonReply: 2
INDIRECT 28(self)entity 0 481(distance).distance 21507(?]
STORE_V 28(self)entity 0 4(?]
STORE_V 323(CHAN_VOICE) 2.0 7(?]
STORE_V 21505(?] 10(?]
STORE_V 21506(?] 13(?]
STORE_V 21507(?] 16(?]
CALL5 489(sound)sound()
ADDRESS 28(self)entity 0 147(use).use 21508(?]
play_music.qc : music_play_tune : statement 51
world.qc : LoadGame : statement 0
world.qc : StartFrame : statement 16
PR_ExecuteProgram: assignment to world entity
Host_Error: Program error

The idea was to play whichever tune was currently set. Clearly, I am not understanding qc here. 
In 
function music_play_tune in file play_music.qc, there's an entity propery ("use" I think) that you're assigning some value at statement 51.

This entity is world (= 0) at the reported occasion and this is not allowed, you may not change the world's properties.

It's probably an un-initialized entity variable that causes this issue. If I saw the corresponding QC code, it'd be easier to explain. 
Hehe 
Does this mean you're working on "This Onion II - The Sequel"? ;) 
AguirRe 
Does that mean I would have to intialise my music sounds in world.qc instead of calling the function play_music where they are usually precached? I can get around the "use" statement.

Oh, and according to my publicist, I have to give a "no comment" to your last question :-) 
From The 
debug output above, it's a
self.use = something
statement that's run when self == world which is not allowed. It's not the precaching that's at fault here.

Since the function is called from StartFrame initially, I'd assume that the world is indeed self at that point.

Music_play_tune is normally the think function for the play_music entity, you can't call that directly from another entity's (here: world) think code. The sound calls are also invalid then.

I'd guess you'll have to trigger the play_music entity's think function somehow from StartFrame. 
Thanks 
I'll play a little more with this to see if I can figure out a workaround. 
No, I Can't Figure It Out And I'm Going Round In Circles 
I thought I could set up a flag to say whether or not the music was playing at the time of the savegame (state = TRUE/FALSE). I know the piece of music playing by tracking it with a variable (cnt = 1/3/5/7, for 4 set pieces of music). I know both of these are saved in the savegame file (actually FALSE appears not to be saved), so presumably are loaded with loadgame.

But world.qc baulks at everything I try, usually with a 'types function and field not allowed'. So I cannot figure out how to either read the entitie's 'state' and 'cnt' and make use of them; or how to call the 'music_play_tune' function from world.qc.

Do you think I am trying to do the impossible or is it just that the logic is beyond me? 
This Might Not 
be a very good idea, but just to make the music_play_tune "callable" from StartFrame, you could assign a global entity var music_entity the value of self in play_music.

In StartFrame, you'd then just set music_entity.nextthink = time to make it execute as soon as possible. You should probably add a check for music_entity being not-world, i.e.:

if (music_entity)
music_entity.nextthink = time;


Maybe someone else can suggest a better way to actually achieve whatever you're trying to do. 
Btw 
savegame files don't contain vars that are 0 (= FALSE), so that might be why it's "not saved". 
I Don't Think It's Impossible 
are you waiting long enough for all the entities to be spawned before you go searching for the music entity?

it should just be a matter of using a while loop to .chain through your entities until you find your music ent, checking the entity fields and then giving it a .nextthink and .think to call it's function.

music_play_tune likely has stuff with self in it, so that's why you'd need to do musicent.think = music_play_tune; instead of directly calling music_play_tune();.

or am i misunderstanding the problem? 
savegame files don't contain vars that are 0 (= FALSE), so that might be why it's "not saved".

false = 0, and i'm pretty sure variables in quake are automatically initialized to 0 if they have no value, so technically, they are 'saved' whether it's actually in the save file or not. 
OK 
I didn't have a problem not seeing 'state = 0' in the savegame because I would have been looking for 'state = 1' to tell me if the music was playing at the time of the savegame.

No, my "problem" is that I cannot get a compile with any statement that uses something like 'musicent.think = music_play_tune;' in world.qc as I get an error of "Types function and field not allowed". I don't know how to copy one entity into another so that the world.qc can use it.

The reason I am having difficulty is that I am only an occaisional user of QC and don't really have enough depth of knowledge about the language or protocols in use. I get by, by reading other people's code and adapting it to my use or by plain old trial and error. But I don't think we have had music in Quake in the way in which I have implemented it, so nobody has yet written the code for me to adapt, and all my trials (Lord, soon be over) have ended in failure. Well, at least I'm consistent ;-)

If someone wants to take this on, I would have no problem passing my play-music code on. It's not a work of art but it does work.

And, "at the end of the day" I am only trying to tidy up something I have already finished. 
Didn't 
my suggestion work? To copy self in play_music, you just have a new global var
entity music_entity;
and assign self to it:
music_entity = self;

Then you set
music_entity.nextthink = time;
in e.g. StartFrame. You shouldn't set the think function, that's AFAIK already set in play_music.

You only make sure music_entity's think function will be run as soon as possible (you can't control exactly when, though). 
AguirRe 
No, it didn't work.

If I place the 'entity music_entity;' outside of world.qc I get a compile error "world.qc(359):error: unknown value 'music_entity'".

Line 359 is where 'music_entity.nextthink = time;' sits.

So I place it in world.qc immediately following the line, 'nosave float loadflag;'

I've added 'music_entity = self;' inside play_music, thinking that it needs to be there otherwise the new entity doesn't know who 'self' is.

Finally, 'music_entity.nextthink = time;' is in LoadGame, which is called from StartFrame.

Ah, but... I have just re-read everything and added '+ 3' to 'music_entity.nextthink = time;' and now it works. I had written a note in play_music that the sound will not play for one second - I read that somewhere but don't know why it is so.

Cool! Lookin' good!

Thanks.

Now I can get to work on checking which piece should play (or not). Watch this space!

Thanks again. 
Long Standing Bug? 
Is this, in the eyes of those present here, a bug? (and if so, one worth fixing?)

self.th_pain (attacker, take);
// nightmare mode monsters don't go into pain frames often
if (skill == 3)
self.pain_finished = time + 5;

You might expect that this piece of code makes sure that there is a minimum 5 seconds between each pain animation on nightmare, in the same way that self.pain_finished = time + 2; in the pain function puts a minimum of two seconds gap. But this isn't quite right.

You see, most pain functions only set pain_finished times once they've already concluded that pain_finished < time. Otherwise they'd constantly set pain_finished further into the future as long as the monster kept taking damage within the pain_finished period. Nightmare mode is, in effect, doing exactly that. You have to go 5 seconds without damaging the monster at all, rather than 5 seconds since you last caused it to go into pain.

So you end up with very odd behavior. If you pour nail after nail into an ogre, it'll only go into pain on the first one, but if you spread each nail 5 seconds apart, it will go into pain from every single one. Of course, the bug doesn't manifest itself that noticably, as 5 seconds is about enough time to kill any monster if you're focusing exclusively on it. Still, it might becomes more important with new high hp enemies, like in Quoth or the like. So, thoughts? 
Mike 
The reason you get a compile error is because of the order in progs.src file. Since world.qc is before play_music.qc, the compiler needs to know what it is before you can use it.

You can get around this kind of problem by declaring the global var in defs.qc or another file that's early in progs.src.

Or just declare the var in all files that you use it in. It'll just be one var anyway, as you can't have two global vars with the same name.

Good that it works now. 
Well 
In Quake2 the enemies never went into a pain animation in NM - they just ignored the shots, feeling no pain.

And it felt right, they are cyborgs. In Quake it is a bit strange that I can always count on a Vore (for example) yowling on the first hit, and have enough time in the animation to throw four grenades (1 to cause it to go into pain, three more to kill it) without reprisal.

Is it possible to add a randfloat value to the factor for pain - with the skill number deducting from this? (Yeah, just exhausted my coding knowledge).

What I'm suggesting is recoding the monster pain sequence, which can most likely cause alot of headaches, but I can see:

Create random Variable 1-10, deduct (skill level).

Is Variable higher than 5? If yes, play pain animation.

Which should give the engine less to think about for each particular monster currently in combat, since they're not all accumulating delays. This could be useful if, for example, the player is spraying nails into a horde of Vorelings.

It could also gives an organic feel to the enemies, making them less predictable and robotic. 
Sorta 
Some of the quake monsters already do that, for instance the pain decision code for the fiend is:

if (self.touch == Demon_JumpTouch)
return;

if (self.pain_finished > time)
return;

self.pain_finished = time + 1;
sound (self, CHAN_VOICE, "demon/dpain1.wav", 1, ATTN_NORM);

if (random()*200 > damage)
return; // didn't flinch

demon1_pain1 ();

So any hit of less that 200 damage has a chance of being ignored(apart from the sound). This tends to only be done for the tougher monsters though. I imagine that the vore always goes into pain because it's a more frail thing - although it does get a 3 second gap between attacks to compensate. The wizard gets a flinch value of 70 hp because if it does stop in pain, it's probably gonna die because the player can get a bead on it. Setting it that high gives it a good chance of ignoring nails. I don't think it's something that should be applied across the board though. 
 
could make it take into account it's current health when determining whether to go into pain or not. then add a random time to it, and wait until that time expires to add more delay. 
Preach: 
do you know if that "nosave" keyword is reliable? If i sit there and spam the save and load buttons, every once in a while the sound won't be playing after I load. If i then keep loading that one save file, it will be missing the sound 100% of the time. This suggests that something is wrong with that save file (like the loadflag variable is occasionally getting saved) 
Aghhhh! 
now i'm finding that certain quakec changes are causing the level to not load, giving errors like

"couldn't spawn server maps/info_player_start.bsp"
"couldn't spawn server maps/samelevel.bsp"

almost as if strings in the progs are getting all jumbled up. Is frikgui27 a bad version to be using? Maybe it's got some bugs or something? 
Okay.... 
Anyway, i think i solved the issue; I guess i just needed to delay a bit before trying to play a sound. I guess sometimes if you try to play a sound too soon after starting a level or loading a save, the game just swallows it and you don't hear anything. I've noticed the same is true with printing messages to players in spawn functions.

As for the crazy errors in post 35, no idea what happened there but it's gone after making more changes. 
Yeah... 
I've had that string bug happen to me before, usually it goes away if you restart frikgui. Must be some kind of bug - if it keeps recurring you might want to use fteqcc instead, or mention it to frikac. I'm pretty sure that nosave is a reliable feature, although it sounds like you've fixed it anyway. 
Just To Close The Loop 
I put a flag in play_music set to true when music is playing and then read it in LoadGame. It works a treat.

Thanks. 
Loading DPM Model Files In Darkplaces 
Hi!

I posted thsi thread last week on the Inside3d forums, but I didn't get any replies, so I wnated to try my luck here, with you nice folks ;).

I'm having some trouble loading a DPM model for Darkplaces.

This is the code I have, minus the comments (added to weapons.qc)

//model precache (added at the beginning of the //file
precache_model("models/weapons/ak/v_ak47.dpm");


//Set the weapon up in players viewport
if ((self.weapon == IT_SHOTGUN))
{
self.currentammo = self.ammo_shells;
self.weaponmodel = "models/weapons/ak/v_ak47.dpm";
self.weaponframe = FALSE;
self.items = (self.items | IT_SHELLS);
}


When I try this out, the model doesnt show up, and the console reports "cant find <tex name> for mesh <tex name>, using default grey_checkerboard" (or something along those lines)

I'm using the the test v_ak47.dpm model that came with the dpm model viewer utility.

The model directory is as follows:

mygame/models/weapons/ak/v_ak47.pm

Inside the ak directory I have the following files (including the textures that the engine reports it cant find, in TGA file format):

-v_ak47.pdm
-10 of the TGA textures corresponding to the model

I would really appreciate if someone could tell me how to load and display DPM models in darkplaces.

Thanx again in advance!

-Zylyx 
Hmm 
I don't really know much about dpm models, but I guess the first thing to check would be that the filenames are correct. Can you give a specific example of one of the paths? If they came ready named with the example file then it's unlikely to be the problem. Also, see if a shorter path helps, like putting the model in mygame/progs. Again it sounds unlikely but it's worth a shot.

Otherwise I'm gonna have to pass you on to another forum again. The best place to ask/check out would be the nexuis forums. Nexuis uses dpm for all it's models IIRC, so checking out their source code/mod to see how to do it might help. If even that fails you might post on their forums and hopefully a coder there can help. 
 
thnx!

My model directory code is as follows (in the "mygame" directory in the Quake directory, coz that where my progs.dat file get's called from for my mod):

precache_model("models/weapons/ak/v_ak47.dpm");

and for the viewport setup:

self.weaponmodel = "models/weapons/ak/v_ak47.dpm";


I'll have a go at the Nexuiz forums, and I'll hopefully be able to get some info there. 
C++ Coding Help 
i was wondering if someone could give me a hand with this...

basically, i wanted to create some kind of time system in a c++ game i'm working on. well, actually, i'm working on someone else's code, and currently, there's no sense of time at all, all timing is done by frames, which, to me anyway, seems like a Bad Thing.

ideally, i'd like to have a simple counter that starts at 0 and goes up in seconds like quake's 'time' float so that i can do things similar to self.nextthink = time + 5.2; (obviously, wouldn't be identical)

btw, i'm a c++ noob. ;) 
Necros: 
you basically have a global time variable, and have the code update the value at the beginning of each frame. Probably, you'd do it in the main loop that runs your game. And the time you can get by using the appropriate system call, for example windows has one, SDL has its own, etc. See Sys_FloatTime() in the quake source for an example of how it's done.

Once you have a time variable that is available to any piece of code, you can do simple tests like: if (this.nextthink <= time) this.think(); 
Or 
you hand the last frame time delta into all your updates 
Ioh 
and, upon reading metl's answer a bit more:

you'd also have the main game loop decide when to render a frame and when to update the gamestate (ie. seperate render() and update() methods). 
Also... 
like megaman said, some functions (such as physics/movement) will want a "frametime" delta in addition or or instead of the global time. So you should have both be available. 
Well, 
i found out that clock() returns what looks like a simple integer in msec starting at 0 when the game starts, so i'm using that.

but what is this frametime delta you are talking about? like the time between frames? cause i haven't a clue on how to calculate something like that.

i realise though, that i'll eventually need something like that. i changed the movement system to work with velocity vectors but i won't be able to accurately update positions without some way to tell how much time is taking place between frames. 
Necros: 
"frametime" i.e. time "delta" i.e. time between frames is easily calculated: just currenttime - previoustime. It is useful for things like physics, for example:

entity.position += entity.velocity * frametime;
entity.velocity += entity.gravity * frametime;

note that the second line above is responsibly for jump height being framerate-dependant! 
My Understanding Is That Timing Is Messy Stuff 
Basically there are a number of ways of getting the time and some of the timers that give you the data aren't that exact.

You should be able to find some good info in the http://www.gamedev.net forums and I think I remember seeing it discussed on the http://www.shmup-dev.com/ forums too in the past. 
Thanks :) 
i think i've got it working, or at least, it seems to be.

every frame:

time_currentFrame = clock();
time_previousFrame = time_currentFrame;
time_frameDelta = (time_currentFrame - time_previousFrame) / 1000;

this gives me the fraction of time per second, and i have one function that does:

nextPosition = currentPosition + (velocity * time_frameDelta)

for all movements.

for actual velocity calculations, i capped that at 10 frames per second (every 100ms) to keep cpu usage down for needlessly precise velocities. 
Umm 
you have to reverse the order of the first two lines? 
Yeah. 
:P 
Function 
how do you call a function outside of the class you're in atm? is it even possible?

i know you can do object->doThis() but that requires you to first find the pointer for that object, and then that function usually means you want to perform the function on that object...

i wanted to do the old style C thing where you just have a function you call from anywhere (like how T_Damage and T_RadiusDamage work in quakeC).

i'm kind of shit at this whole OO stuff, so am i going about this the totally wrong way? 
Make It A Static Method 
 
 
Or just place the function outside of any class definitions. Functions at the global level work the same as C functions. 
How? 
how exactly do i make it static? or how do i declare the function outside a class definition? do i make a new cpp file or something or..? 
Static 
is another modifier, kinda like private or public.

A static thing is something you can not make instances of, kinda.

So you have classes like Moose and you can make moose1, moose2 etc... But there can be a static method in the Moose class that is not particular to any moose1 or moose2 instance.

Like double Moose.mass_of_the_sun() which then returns a static constant that is always the same no matter what you do with the moose instances.

Kinda like that. Damn it's been too long since I've coded. 
 
necros

You're asking some pretty basic questions here in all honesty. Maybe reading a primer on C/C++ would be in order here. 
Yeah 
C++ is a painful and unforgiving language. If you dive right in, you're going to hit something hard and spiky.

I would go so far as suggesting a different language, if that's practical (pygame is pretty sweet). If it isn't, then you really need to read up on the basics. 
 
C++ is fine and gets far more flack than it deserves.

C# is far superior however. FAR superior.

I guess it would help to know what specifically you're trying to code and for what platform. 
 
C++ does get treated unfairly - google Erik Naggum's usenet rants sometime for a hilarious example - but I wouldn't call it "fine".

I don't really want to get into a flamewar over C++'s fucked up design: I'm just going to note that there are plenty of better languages to choose from. 
 
at the same time, i always learnt best by doing. it's more frustrating, but it sticks better.

i've tried reading some lit on c++ but they annoy the hell out of me. i'd rather they just give me the syntax for it and give me a brief overview of how to put it in the code instead of going into all the long winded crap about stuff i never remember anyway.

otoh, the more i look at this code, the more i feel it needs to be rewritten almost from scratch. there are some things in here which i don't like at all.

ie: instead of treating ships and missiles as inheriting from the same class, they are completely different classes, and neither of them can 'see' the other.

ideally, i would have liked to override the basic 'update' function of a base entity class for specific ones (ie: for missiles and ships) and then be able to call it by just iterating down one big list of entities and calling the same function.

instead, i'm trying to hack my way around it by making a static function in a new class so that i can call it from inside one class that normally can't see the other class.

also, for, apparently no reason, missiles aren't instanciated objects, but are regular structs which is also causing other problems.

i'm going back to school next week, so i'll probably ask these questions to my instructors instead and see what they think... 
Heh 
the title for the above post should have read "that may be true, but" 
If This Is Your First C++ Program... 
you should entirely expect to have to throw it away and start again.

(Or your 10th or 100th, to be fair: "build one to throw away" is a long standing slogan of software engineering). 
 
The problem is that hardly anyone ever does that. :) That's where horrible feature bloated abominations are born. 
Unarmed Ogre 
I've been stuggling to make an Ogre variant and I'm having troubles with ai/fight/ogreb.

Basically the fat cunt keeps trying to go to th_missile when he has no grenades (crash). I must be missing something obvious here but I don't know what.

The error returned is on his run sequence (has all his own functions) but if I replace his th_missile linking it to eg.melee then I'm ok, except it takes him ages to close the distance because he's swinging chainsaws about.

NULL function

Basically I don't want him to ever th_missile - but looking over ai and other monsters sheds no light - dogs / knights / fiends all use ai_run without problem.

I'm going in circles, it seems. If anyone can shed any light on this I'd appreciate it. 
C++ For C Programmers 
http://www.4p8.com/eric.brasseur/cppcen.html

I find that documents called "X For C Programmers" tend to hit the spot. This is mainly for necros. 
Ijed 
OgreCheckAttack sets their attack state to AS_MISSILE, which leads to ai_run calling ai_run_missile, which leads to self.th_missile.. which leads to the crash.

You'll need to comment out the monster_ogre/OgreCheckAttack lines in CheckAnyAttack (so they'll use CheckAttack instead) and make sure you don't give them a .th_missile, else CheckAttack will convienently call self.th_missile for you. :) 
An Ogre By Another Name 
Have you tried changing the classname from monster_ogre to, for example, monster_ogre_unarmed? I have a feeling that might make it work.

The reason why is hidden in fight.qc and ai.qc. fight.qc is the place to start, have a look at the two functions CheckAttack and OgreCheckAttack. The former is the generic function for any monster, and it's careful enough to check whether self.th_missile is set or not before deciding to make a missile attack. OgreCheckAttack is more presumptive, it knows that an ogre has a missile attack and so goes straight ahead with setting AS_MISSILE.

This is all quite deceptive, as OgreCheckAttack never explicitly uses th_missile - it just sets AS_MISSILE and lets ai.qc do the th_missile part. ai.qc is also the place to find out how the game chooses between CheckAttack and OgreCheckAttack. The function that decides is called CheckAnyAttack, and as you can see it decides based on the classname. So if you give your melee ogres a different classname then it should use CheckAttack only, which is safe to use without th_missile set.


The downside to this method is that, like with monster_ogre_marksman, your ogres will be able to infight with each other. So you could just make the check in CheckAnyAttack more stringent:

if (self.classname == "monster_ogre" && self.th_missile)
return OgreCheckAttack ();

For neatness of code, this way is probably better, as it means you can have a single spawnfunction for both grenadiers and berserkers. This is good code sharing, as any change you make to an ogre you probably want to make for both of them.

The third solution would be to modify OgreCheckAttack to properly check for th_missile, but I don't think that's the best way to go, it could end up complicated. 
Infighting 
it's pretty easy to get around the infighting problem above when setting up a new classname. you just need to set up 'classes' (a la quoth) and modify the infighting code slightly

here's how i did it..

- add .string class; to the monster ai in defs.qc

- add self.class = "ogre"; to the different ogre classnames

- then in combat.qc under the '//react to damage' part, change this line:
if ( (self.flags & FL_MONSTER) && attacker != world)
to read this:
if ( (self.flags & FL_MONSTER) && (self.class != attacker.class) && attacker != world)

i think that was it. you can use it to group allied monster types or groups, either in the qc or simply by adding 'class' to any other monster entity (say if you had one particular battle where you wanted the monsters to focus on the player only) 
Excellent 
Thanks for all the answers, I should be able to close this issue sometime today.

I wanted to maintain the original ogres so made the new one a different classname - ogreb (berserk) already.

As to infighting, I'm thinking of modifying all Ogres to act the same as grunts. This might sound like a cheap dodge to not have to fix the issue, but I never did see the Ogres as particularly polite, and I'm a fan of chaos.

Thanks again. 
Argh 
Solved!

Turns out I was calling ogrecheckattack for the new ogres inside ai.

You live and learn. 
Monster Won't Get Killed 
While coding for a new Q1 monster I made up a little qc where I placed all args like stand walk run etc.
Having the monster standing in game all looks well, untill I try to kill the moster.
Having two monsters in game there's always one that don't die.(?!)

I hear the kill sound but the monster just goes on turning into stone to my bullits.
I have the regular death subroutine.

http://members.home.nl/gimli/Imp.qc 
 
lol...

if (random() < 0.5)
imp_die1 ();


these lines mean if random() (random number between 0 and 1) is smaller than 0.5, then it will play the animation sequence.

so half the time it will play the animation and half the time it won't. 
Well 
cll me a fool, but what should I number 0.5? 
Right 
if(me a fool)half the time < I ain't).

thanks for pointing me out. 
Impulse Command Queuing. 
impulse command queuing.

is that handled by the engine?

in ImpulseCommands there's the if statement:
if (self.attack_finished > time)
{
self.impulse = 0;
return;
}


which seems to me to mean "if attack_finished is still ticking down, do not accept ANY impulses (set to 0) and then break out of the function altogether.

yet, when you attack with say the rocket launcher and then press 8, the impulse 8 command seems to get queued up and is executed after attack_finished is done.
is there something going on behind the scenes here? i'm actually trying to stop the queuing from happening, but can't really see even where it's happening. 
Hmm 
I don't see that line in the version posted at
http://www.inside3d.com/browse.php?show=weapons.qc
I'd probably say the place to look is in W_WeaponFrame, where any call to ImpulseCommands is skipped if self.attack_finished > time. If you really wanted to block impulses, then putting self.impulse = 0 just before that return should do the trick. 
Hm... 
that's really odd. that means the if check in ImpulseCommands is completely redundant. it will never get to that point because an identical if check is done prior to even getting in that function. o.0 
Random Coding Oddities In Quake? 
Surely not!! 
Yeah, But 
Yeah, but that if() check isn't actually in the standard quake source code for ImpulseCommands, I don't know where you got it from : -p 
Fire And Switch? 
If you want to stop the queueing, then putting that the return in the if() in W_WeaponFrame would do it. If however, you want some impulses to always happen, then you need to put a separate check in, to happen before that check.

Of course, an even more intricate fix (which goes in the other direction from where you want to go) is to track what the impulses would make the weapon change to if you were not firing (setting .weapon appropriately, so the hud light shows what you will use next), and then switch to it when the player has stopped firing. Of course, there is another issue again, in that I don't think you can switch away while firing a nailgun, because the way they fire is handled differently is handled to other weapons. 
I Sorted It Out 
i just moved the self.impulse = 0 to the end of W_WeaponFrame and removed the if check with the return. i have no idea where the if check in ImpulseCommands came from but i took it out as well and it works fine after re-arranging the way firing and impulsecommands was handled. 
And I Forgot To Mention A Couple Of Things 
You should probably use else if in ImpusleCommands(), so that it can go faster, May not make that much difference these days, but it's probably a good idea to anyway.

Even more of a timesaver, though, is skipping all of the impulse checks completely if self.impulse is 0. I don't actually know when impulse gets truncated to the lower 8 bits, but I think it's before the QC sees it (and possibly it only gets sent over the network as a byte), so you don't have to check for it being anything else that resolves to 0. 
Profile 
There's a built in way to check how fast qc runs on an engine, in case you're optimising things. The command is "profile", and it lists the top 10 functions in terms of commands executed since the last profile command or server start. As an example on unpatched quake:
e1m6 at 72fps
425616 PlayerPreThink
270814 WaterMove
241542 PlayerPostThink
202689 ImpulseCommands
177480 CheckRules
165648 CheckPowerups
125843 ai_stand
94928 StartFrame
76144 door_touch

Things worth noticing:

*ImpulseCommands is certainly up there. Almost certainly the most important optimisation would be to skip everything if self.impulse is 0. I'd agree with doing that check before calling the function ImpulseCommands(calling functions costs a few operations).
Further optimisations would be the else if Lardarse suggests, and storing self.impulse in a local float at the start of the ImpulseCommands function - to avoid looking it up each time, which is more expensive if you have to go through a layer of self.something first. But optimising the very rare cases where there is a change of weapon isn't gonna yield anything like the benefit of skipping the whole thing in 99.9% of frames.

* CheckRules places highly, even though that function is entirely pointless in single player games. I think the calls to cvar are pretty expensive here.

* Results from this kind of assessment will be different at different framerates. The playerprethink type functions occur every frame, but since monsters think in 0.1 second slices, that's only 1 in 7 frames. Playing at 15fps, I'd imagine ai_stand could top the charts. 
Boy 
I've learned that if you create a new monster with a new model, the $frames still have to be named in the progs.dat urnewmonster.qc file in the same order they're in the .mdl.

I assume the compiler converts frame names to integer offsets and the names of the frames themselves are irrelevant? 
 
I assume the compiler converts frame names to integer offsets and the names of the frames themselves are irrelevant?
yup. 
And 
Is it relevant in any way how many frames there are per line? I've had no problems, but then again I haven't experimented much ie. tried to break it.

Is there anything stopping me from having, say, 20 frames on the same line in the .qc? 
I Went Up To 18 With Frikqcc 
and it didn't seem to mind 
Schnurps 
whenever i coded new monsters, i just looked up the frame number in QME and just typed the number, rather than having to list all the $frame bollox at the top of the file 
Well 
isn't that arguably more confusing? if I reexport the model with new anims in it it's kind of nice to just be able to insert them in the list at the top than have to replace all of the numbers in all of the frame functions ... 
I Grudgingly Agree 
If you're thinking about an end user for the code that's a nightmare. Also depends on having the anims in one seqeunce rather than seperated.

It's interesting hacking up all this stuff. 
Profile Is Going In The Reference Book 
and storing self.impulse in a local float at the start of the ImpulseCommands function
Probably not worth it. Except maybe for RuneQuake, or anything else that has impulse overloading...

The frame macros can be called anything you like. It's usual, though, to call them something similar to the model, as it makes using them easier. And as how how many you can fit on one line, I think your most sensible limit is the right edge of your text editor... 
Temporaries 
Yeah, I agree it's not useful in ImpulseCommands once you have the other improvements. But once you sort out the needlessly expensive functions like that, you start to notice that functions like visible() and range() begin to show up in profile. And in those, you do get (theoretical) performance improvements by using locals. This is my current optimised range function

float(entity targ) range =
{
local vector spot1;
local float r;

spot1 = self.origin + self.view_ofs - targ.origin - targ.view_ofs;
//PREACH: this only uses two temps
r = spot1 * spot1;
//
//PREACH: kept in a local since we use it twice
//PREACH: it would still be stored in a temp local float
//PREACH: but would re-evaluate each time in case spot1 had changed. We know it can't, so we save the result.
if (r < 500 * 500)
{
if (r < 120 * 120)
return RANGE_MELEE;
else
return RANGE_NEAR;
//PREACH: nesting the ifs like this takes at most 2 comparisons, down from 4 in the original
}
else
{
if (r < 1000 * 1000)
return RANGE_MID;
return RANGE_FAR;
}
}

Skips the expensive calls to vlen, and nests the ifs for a slightly shorter path to RANGE_MID or RANGE_FAR. Note that in frikqcc and fteqcc with the flatten constants optimisation on, 120 * 120 and the others are evaluated at compile time. If you're not using that optimisation, then you should work out those values ahead of time. I leave them like that to make clear where the magic numbers come from.

You can get a little more juice out of visible if you use

float (entity targ) visible =
{
traceline (self.origin + self.view_ofs, targ.origin + targ.view_ofs, TRUE, self); // see through other monsters
if (trace_inwater)
{
if (trace_inopen)
return FALSE; // sight line crossed contents
}

if (trace_fraction == 1)
return TRUE;
return FALSE;
};

In FTE, putting the arguments straight into the traceline function call is actually faster than not doing so. I also put the trace_inwater check first, as I figure that's more likely to fail most of the time, so you don't need to bother checking trace_inopen(which under the same assumptions is usually likely to succeed). Doing && in an if statement always evaluates both statements in qc, so nesting ifs can make faster executing code where it matters. 
So Why Not Just 
make the profile command show more than 10?

And of course, format things so they make sense to whoever is writing the code; for me this means not putting things on multiple lines for the hell of it :-) 
Also Visible 
Isn't this the function that you suggested changing in another thread (can't find it) to make monsters see you while in water? 
Suggested Is A Strong Word :-P 
I wouldn't say the water vision change was something that should always be changed, someone was asking how it could be done, so I posted it. Really it's a circumstantial choice, if it causes problems in a specific map then visible is the place to change things, but in general keeping water opaque is a good idea for fish if nobody else. 
Ok, Then... "mentioned" 
Selective based on monster type, though. 
Gnurps 
isn't that arguably more confusing?

hehe, well I admitted it for the comedy value really; I'm aware that it is an atrocious way of coding monsters :) 
NULL 
Did I ask this before? I don't remember, honestly.

Anyway, is there a concept of a NULL value in QuakeC? Like say I want to define a local entity variable and set it to NULL before doing some other processing and at the end do a check like:

if( myEntity == NULL) or if( !myEntity )

Is that possible? I think I'm missing something obvious because I can't get the compiler to accept null, Null, NULL or 0 (zero).

Help? 
Pointer To World 
Most things tend to use world as the "NULL pointer". find() and variants usually return world if nothing is found, or end a linked list with world. I believe traceline() sets the hit entity to world if nothing is hit (the general way to detect no hit is if(trace_fraction == 1) although sometimes testing for hitting world is acceptable).

Usually, world is entity 0 (maybe eprint() might be able to tell you), although the compiler probably doesn't accept the implicit cast from float to entity.

Other NULL values are 0, "", and '0 0 0'
Yeah 
Just to add that

if( !myEntity )

is valid qc and equivalent to

if(myEntity == world)

If world can be a valid return type you need to deal with that as a seperate case somehow. 
 
Ahh alright. Thanks! 
Removing Entities And It's Effects On Other Things 
so, say i have ent1.owner = ent2
and ent2 is removed. what happens to my pointer on ent1.owner? is it set to world or is it now corrupted junk?

can i do a check if (!ent1.owner) now and it'll pass? 
No 
The entity field continues to point to the same "slot" that the original entity occupied. Worse, after two seconds that entity slot can be reallocated when a new spawn() request is received, so the field now points to a valid entity, but an entirely unrelated one.

It's also worth noting that most of the fields on the removed entity will still be readable, and contain the same values they did before the entity was removed. The engine resets a few fields on removal, like solid, model and origin, but doesn't zero all of them until it's reused by the spawn() command. You can observe a side effect in fitzquake if you turn r_showbboxes on; a removed entity creates a bbox of that entity's size at the origin.

You could exploit the above fact to write code which can tell if an entity is removed or not:
Before removing an entity, set a float .isremoved on that entity to TRUE. The value can still be read, and will be reset when the entity is respawned as something else. You have to pinkie-swear never to modify that value outside the remove() function for it to be reliable.

I wouldn't recommend actually doing that though, because it's kinda relying on "undefined" behaviour in the engine - that removed entities can still be read. Engines which had more advanced entity management might not enforce that.

It's probably better to have a destructor function for the entity which is being removed which knows which entities will refer to it and sets them to WORLD. This would be practical if it's a master-slave kind of thing, not so much if you're worried about a monster getting removed and other monsters suddenly having an invalid .enemy... 
 
"You can observe a side effect in fitzquake if you turn r_showbboxes on; a removed entity creates a bbox of that entity's size at the origin. "

Hahaha, so THAT'S what that is. I wondered what that box at the origin of the world was. Thanks! I thought my code was doing something wacky... 
Jesus 
9_9 
Mind Melting Code 
Ok, I dug out the monster I wrote a few months back, here's some code which actually tracks all of your removed entities in a linked list. The file is pretty thoroughly commented, with a big block of text at the start describing how you might use it, and how to integrate it into a standard qc source.
http://www.btinternet.com/~chapterhonour/chaintrack.qc

The main application is a new field on entities you can read called .reused. Positive/zero values of .reused mean the entity is currently spawned, negative values mean it's currently removed. The absolute value of .reused gives you the number of times the entity has been removed previously. This gives you an index you can compare to see if a stored entity differs in number of removals from the value it used to have - i.e. it has been removed and restored.

I've tested it with fitz, bjp and dp, and it seems to function correctly in all 3. If anyone wants to know how it works, I can post that up too... 
Custents 
I was trying to add some doombirds to my map, and couldn't find the right movement for the thing. If I use a func_train it worked, only the sight of a plane flying backwards is a little queer.

So I took the custents and saw the map with the falling wall. It has a four way movement train that uses func_rotate. I integrated the doombird in it and it worked out fine again.

One thing I can't get is
why can I jump on the func_train in custents,
and why do I drop through it in my own version? 
I'm Guessing 
you mean func_rotate_train and not func_train?

in which case, you need the oft-posted czg rotation tutorial which, ironicall, i don't have the link to. :P 
Append 
that's to say, the tutorial explains how to get collision on your rotaters. it's kind of wierd and annoying. 
Thanks 
necros, the turning goes al right.
it is just that funny behaviour that when I play the map falendoor of custents I can stand on the func_train and I rotate in eyesight.

when I transponse the map coordinates of that func_rotate_train to my own the train isn't solid anymore. (?!) 
Oops 
forgot to include func_movewall. Now it's solid.

There's an odd point where the func_rotate suddenly behaves like a counter-turn in the opposite. Can't fly the thing without Doom patents. 
Just 
To throw a spanner in the works -

Would it be possible to have the plane as a model, with all it's takeoff animation (turning etc.) done in Qme?

Or would the size of the animation break the model - look in the wrong direction and the game assumes you can't see it because it's in a different visleaf. 
There's Something Worse That What You Mentioned 
about doing it that way.

the way that vertex coordinate info is stored is completely relative.

this means that no matter how big or small your model is, the only thing important is how far from the origin all the vertices are.

this has an impact on the resolution of the model.

in quake, you could make a miniscule model of a bolt and it'll look completely fine.

but if you made a huge wall with the same bolt in the middle, the bolt would be messed up.

this is because the huge wall caused the scale of the vertex 'snap' to be larger.

if you made a plane model that was fully animated to fly around in, say an area of 1024x1024, your plane's vertices would probably be so low resolution as to not even be able to make out what it was.

as an example, look at the amount of vertex dancing on the vermis model. compare it to something like the fish model (which hardly moves) to get a good idea of how it impacts vertex position. 
Another Way To Look At It. 
imagine that a vertex in a model can only be on a grid of 256x256 units. it can rest on any even number from 0 to 255.

but that this grid can be stretched in all directions.


so if your model was 1024 units tall, it's vertices could, internally, only snap to a 256 tall grid.
that is to say that in the game world, the model's vertices would fit on every 4 grid units, instead of every 1. 
 
Ahh right. I was going to call you out on that resolution thing but then I remembered Carmack's 256x256x256 cube compression stuff. Yes, quite the ugly issue. 
Ijed 
this is aa far as I have come with the the doombird and custents.
Coding a mechtech is somewhat harder, but would be better.

http://members.home.nl/gimli/dbird.dz 
Ha! 
That's pretty fun. The collision seems to go a bit nuts and just do its own thing, but even so.

Maybe some Qc to add grenade style smoke to the jets? 
As To The Model Thing 
So to do it with a model would require a func_modeltrain of some sort then, so it wouldn't just dissolve into a mess.

That explains why all the monsters seem to have Parkinsons in their idle animations though. 
 
The larger ones anyway. The Shambler has way more error in his verts than, say, a soldier. The rest of the jittering comes from the fact that, I believe, Quake only supports integer locations for vertices. 
I'm 
Used to engine side vertex interpolation so don't usually notice it so much, except when looking at the models in raw state, as it were. 
Swung 
custents support the func_rotation and the func_rotate_train.
I'm trying to understand these options to get a better flyer.

that strange swing don't seem related to the func triggers.
Haven't found out where it comes from.
Reason that in custents a part of the func_rotate is hided. 
Armor 
I succeeded to create a health bowl and give it a health strength , by adding a health function in the qc.

I thought giving it armor points would be that easy. But it isn't.
There are only three IT_ARMOR types.
By substituring one I get my extra powerup object of ten armor points.

But not as alike the health paks I can only take one at the time,
the rest stays non solid as if I have taken a full armor . 
To Clarify 
I want to check what you're trying to do here. You would like an item which gives a boost of, 10 points of armour to a player who picks it up. So far, you've managed to make an item which gives the player 10 points of armour if they pick one up, but then subsequent ones will only top the player back up to 10, and if they are already at 10, then it doesn't increase.

To me, that sounds exactly like what would happen if you rewrote the green armour to have 10 armour points rather that 100. Have I read your aim and current result right? 
Yes 
I trie to reproduce the armor powerup with skulls, like in Doom 
Items 
I was rewriting in the items.qc

+---------------------------------------------+
void() armor_touch =
{
local float type, value, bit;

if (other.health <= 0)
return;
if (other.classname != "player")
return;

if (self.classname == "item_armor1")
{
type = 0.3;
value = 100;
bit = IT_ARMOR1;
}
if (self.classname == "item_armor2")
{
type = 0.6;
value = 150;
bit = IT_ARMOR2;
}
if (self.classname == "item_armorInv")
{
type = 0.8;
value = 200;
bit = IT_ARMOR3;
}
if (self.classname == "item_skull")
{
type = 0.1;
value = 10;
bit = IT_ARMOR1;
}

if (other.armortype*other.armorvalue >= type*value)
return;
+-------------------------------------------+

};
void() item_skull =
{
self.touch = armor_touch;
precache_model ("maps/skull.bsp");
setmodel (self, "maps/skull.bsp");
self.skin = 0;
setsize (self, '-16 -16 0', '16 16 56');
StartItem ();
};

+---------------------------------------------+ 
It's The Last 2 Lines 
they skip the pickup entirely if the armor you're touching is weaker than what you have. you need to add a special exception there for skulls that add 10 armor and keep the preexisting armortype. 
Additionally 
You should check for the player having no armor, and if this is the case, set their armortype to green (0.3 and IT_ARMOR1)

You may also want to set a limit for both health and armor shards. Probably at 250 or soemthing like that. I don;t know if the 3 numbers at the bottom are limited to 8 bits, but even if they're not, you might want to not let them get out of hand... 
Addition 
There's another problem with this code, which is the way armour and health packs differ in increasing stats. A health pack adds on a certain amount of health to the amount you started with. Armour always sets the value to the same amount, regardless of how much you had, it's not adding anything on. Code like "add on 150 points to his armour, but then if the total is more than 150, cap it there" would be redundant.

So you're going to have to write something more complicated. 
This 
http://qexpo.tastyspleen.net/booth.php?id=131&page=273

Might help some, it's Dr Shadowborg's revised health system tutorial. 
Thanks For Your Explain 
I'm no coder, so the fact I get any outcome is a wonder to me.
With health it was easy, adding a new b_model with args and the code run.

With this armor code I can let the strength deplenish untill it reaches under 10 before it powers up.
But I can change to any value, only 10 counts.

Eventually I can understand the options you mention,
but I miss the ability to write them down. 
Adding New Weapons 
hey, was wanting to know if you guys knew of a good and easily understood tutorial for adding a new weapon, that also shows me how to add it to where its usable when added to a FGD "not just when you have a shot gun and enough ammo -.-) 
Ok, More Detailed Explanation 
I think the best way to do it would be to write an entirely separate touch function for your new item. It needs to:

* Do the usual checks that the other entity is a player who is not dead.
* Deal with the 4 cases: player has red/yellow/green/no armour.
* Add the correct amount to the armour total.

I'd do something like this:

void() armorboost_touch =
{
local float maxarmor;

if (other.health <= 0)
return;
if (other.classname != "player")
return;
//usual checks

if(other.items & IT_ARMOR3)
//Player has red armor
maxarmor = 200;

else if (other.items & IT_ARMOR2)
//Yellow
maxarmor = 150;

else
//deal with green and none at same time
{
other.armortype = 0.3;
other.items = other.items | IT_ARMOR1;
maxarmor = 100;
}

other.armorvalue = other.armorvalue + 10;
//add it on
if(other.armorvalue > maxarmor)
//if we're over max
other.armorvalue = maxarmor;
//set to max

self.solid = SOLID_NOT;
self.model = string_null;
if (deathmatch == 1)
self.nextthink = time + 20;
self.think = SUB_regen;
sprint(other, "You got armor\n");

sound(other, CHAN_ITEM, "items/armor1.wav", 1, ATTN_NORM);
stuffcmd (other, "bf\n");

activator = other;
SUB_UseTargets();
//fire all targets/killtargets
};

I've not tested it in game, but it should work well enough. Remember to change the line in item_skull to
self.touch = armorboost_touch; 
Hey 
that's another qup of tea Preach.

I already reminded myself to be glad with a strike of luck and leave it that way.
And yes indeed, the powerups go clearly from 0 to 100. Never thought it was possible.

Thanks! 
LIT File Format? 
Can someone point me towards what the LIT file format looks like? I've spent 20 minutes Googling with nothing to show for it. Is it documented somewhere? 
 
According to QIP LordHavoc created the format so just try getting hold of him in #darkplaces on Anynet (IRC). Otherwise you could read through the TomLite or Tyrlite sources (Hmap probably too), you seem to be able to grasp code (unlike me). 
I Emailed Him A Couple Of Weeks Ago... 
He helped me out! :-) 
Willem 
From dpextensions.qc:
//DP_LITSUPPORT
//idea: LordHavoc
//darkplaces implementation: LordHavoc
//description:
//indicates this engine loads .lit files for any quake1 format .bsp files it loads to enhance maps with colored lighting.
//implementation description: these files begin with the header QLIT followed by version number 1 (as little endian 32bit), the rest of the file is a replacement lightmaps lump, except being 3x as large as the lightmaps lump of the map it matches up with (and yes the between-lightmap padding is expanded 3x to keep this consistent), so the lightmap offset in each surface is simply multiplied by 3 during loading to properly index the lit data, and the lit file is loaded instead of the lightmap lump, other renderer changes are needed to display these of course... see the litsupport.zip sample code (almost a tutorial) at http://icculus.org/twilight/darkplaces for more information.
 
 
Excellent! Thanks, that should give me what I need... 
Coding Tip Of The Day 
Don't expect them daily though, this is just my aggravation of the moment:

if(1)
dprint("1: went down the TRUE branch\n");
else
dprint("1: went down the FALSE branch\n");

This will, as you would expect, go down the TRUE branch. The value in the if() is non-zero, which is true in boolean logic.

if('1 0 0')
dprint("2: went down the TRUE branch\n");
else
dprint("2: went down the FALSE branch\n");

This will also go down the TRUE branch, it looks like any non zero vector counts as true.

if('0 1 0')
dprint("3: went down the TRUE branch\n");
else
dprint("3: went down the FALSE branch\n");

This will go down the FALSE branch! QC only checks the first component of a vector when evaluating boolean logic on them. This is a bit of an oversight, and you should be careful. If you want to properly check if a vector is non-zero, you must do it explicitly as

if(self.angles != '0 0 0')

OK, that's the one that bugged me for tonight, venting over. But while I'm posting about QC and if() logic, here's another related bug that can catch people out:

self.noise = "";
if(self.noise)
dprint("4: went down the TRUE branch\n");
else
dprint("4: went down the FALSE branch\n");

This one goes down the TRUE branch. Why it does is a bit technical, it's because if(self.noise) is checking whether the pointer which self.noise stores is non-zero. The string constant "" is not the same thing as a null pointer, it is a string comprised solely of a null terminator, which actually gets allocated somewhere and so the pointer has a non-zero value.

There are two ways around this. One is to properly null the string pointer, like this:

self.noise = string_null;
if(self.noise)
dprint("5: went down the TRUE branch\n");
else
dprint("5: went down the FALSE branch\n");

This one evaluates to false.

Alternatively you can put

if(self.noise != "")

This will go down the false branch in either of the cases self.noise = ""; or self.noise = string_null
 
"This will go down the FALSE branch! QC only checks the first component of a vector when evaluating boolean logic on them."

I'd venture a guess that when it sees a string maybe it's just doing an atoi call on it, which would stop at the first space? I dunno. 
Assembling A Vector 
Looking at the assembler output, it looks like every time a vector is passed as a parameter to something, the instruction looks like:

STOREP_V VEC_ORIGIN_x, temp_0;

So it seems to be passing just the first component of the vector. What happens then is that the engine knows that this is a vector, and that the other two components will be in the next two entries in memory. Any operation with _V on the end does this.

The problem arises when you get to the IF operations. There isn't a separate case for vector, or indeed for any types. Every memory location which gets passed by the assembler to IF is cast to int, and then checked to see if it's non-zero.

It wouldn't be easy to fix this on the engine side, because you'd need to read what type of temporary was being stored, so that you could distinguish between
if(self.angles)
and
if(self.angles_x)
because the IF operation would look the same. You'd need to look back a few operations at least, which is basically a no-go.

On the other hand, it wouldn't be hard to write a compiler which always substitutes
if(vector != '0 0 0') for if(vector).
FTEQCC already offers a similar fix for
if(string)
It isn't on by default, because some of the engine extensions which add string concatenation etc. require actual tests for null strings instead of empty ones. 
Mdl Versus Sprite 
Well, I managed to get a sprite in Quake, but I was wondering how to add it to a monster's subroutine.

Simple fact, quake sprites are mostly just one model frame. Except for the orgue which is the only one with his grenade. If I'm looking to the qc I can't find nothing about sprites, so I consume it is engine wise.

When I change the model laser.mdl of the enforcer with a sprite I see only the first frame.

How do I add a sprite to a monster's subroutine?
Is it something you add to the statement of the laser.mdl of the enforcer? 
In Hope To Help 
void() s_explode1 = [0, s_explode2] {};
void() s_explode2 = [1, s_explode3] {};
void() s_explode3 = [2, s_explode4] {};
void() s_explode4 = [3, s_explode5] {};
void() s_explode5 = [4, s_explode6] {};
void() s_explode6 = [5, SUB_Remove] {};

void() BecomeExplosion =

i think you have to make a multi-image sprite, like the explosion?

and deal it out above like so, and give it setmodel "ursprite.spr"

or umm, heh <8* 
Well 
For creating a sprite it could work, but not when I try to make it happen in a monster's subroutine like the enforcer.

If I add something at the qc point launchlaser, I first need to declare the sprite frames. And as the enforcer already has it frames declared qc matches out. 
Madfox 
If I add something at the qc point launchlaser, I first need to declare the sprite frames.

no, you do not. like i said before, just put a number where the $frame macro would be. 
Is It Still Necessary To Use Quakeworld Progs? 
are there qw clients that can just read the normal netquake progs? 
 
zQuake can do, both as client and server (so you can serve a "netquake" progs with zquake and have other qw clients connect to it).
FTE can do too.
ezQuake I am not sure, from what I know the singleplayer is broken. 
Zquake Sounds Promising 
except i have the same problem i have with a lot of other clients with zquake...

the screen is half-filled with giant red pixels (using +gl_clear 1) like someone got decapitated right next to my screen. in other gl engines, like aguire's, the pixels are grey because i set the gl_clear colour to grey.
fuhquake has this problem, but ezquake does not though. (fitzquake doesn't have the problem either).

does anyone know what that's about? 
 
I made a sprite of the Shambler's bold, this in order to use it in a mod for temperary bold flashes.

Now I'm sofar I can import the sprite in Quake.
I need the sprite to turn on and off.
I don't know if it's possible or I'm missing the logic to understand.

I used this code as bold.qc

$frame 0 1 2 3

void() bold_stand1 =[ $0, bold_stand2 ] {};
void() bold_stand2 =[ $1, bold_stand3 ] {};
void() bold_stand3 =[ $2, bold_stand4 ] {};
void() bold_stand4 =[ $3, bold_stand1 ] {};

void() model_bold =
{
if (self.style >= 32)
{
self.use = light_use;
if (self.spawnflags & START_OFF)
lightstyle(self.style, "a");
else
lightstyle(self.style, "m");
}


precache_model ("progs/bo1.spr");
precache_sound ("ambience/buzz1.wav");

self.solid = SOLID_BBOX;
self.movetype = MOVETYPE_NONE;

setmodel (self, "progs/bo1.spr");

setsize (self, '16 16 16', '24 24 24');
self.think = bold_stand1;
self.nextthink = time + 0.1;

ambientsound (self.origin, "ambience/buzz1.wav", 0.5, ATTN_STATIC);

};


Now I have bold sprite that constantly flashes.
I used the selfuse = light_use; to turn it on or off but it don't seem to work.
Is there a way to turn it on or of with a trigger? 
Well 
the logic is probably it is a static entity that can't be moved because it is a MOVETYPE_NONE

Ohter question: I'm coding LostSoul from Doom to Quake. If I give it the normal routines like stand,walk,pain,die and give it a bite like the dog for attack with self.th.melee

all goes right so, I should be glad I can archve it.
The distance the monster reaches while biting to the player is too wide. I don't know how to make it closer.

Then I decided to try the jump scene of the dog. Adding it to the qc worked, but there are some strange sidekicks.

Because LostSoul is a flying monster this doesn't compare with a walkmonster. The lostsoul make a giant jump, but it wants to land onground. And because it is a flying monster this is strange sight.
The monster bumps undergound, than jumps up 64 units, aims to the player, moves 64 units again and then returns to its jump session.
Also the chance of hitting the player is almost harmfull.

I know this is becuase I switch a flymonster with walkmonster code, but would it be possible?
A lostSoul that excellerates its move in air, without the bounce of a walkmonster. 
 
to get a flyer to fly toward the player:

take the origin of the enemy (player)
subtract from monster's origin
normalize vector
set monster's velocity with vector * speed you want it to move at.


local vector vec

vec = normalize(self.enemy.origin - self.origin);
self.velocity = vec * 1000;


you'll need to make a touch function to set self.velocity to 0 otherwise, things will get messed up when the monster tries to move from AI. 
Great! 
I had to make some prototyping to get my SolJumpTouch run, but now it is a fast Soul!

Thanks! 
MDL Question (cross Posted From Inside3D...) 
OK, so inside the MDL file format there is support for simple frames and group frames. I'm trying to get it straight in my head which is good for what.

It looks like things like the walltorch use group frames. Is this so the engine can start animating them on a random frame? I don't see anything in the QuakeC that uses this information so it must be engine side.

Am I thinking about this the right way? Do group frames have other uses? 
Groupies 
Basically a grouped frame is a way to make a looped animation on the client side, so the animation changes frame without any input from the server/qc. The advantages are that it uses no network traffic once it starts, and can be applied to a static entity.

From a QC point of view, the entire framegroup just looks like a single frame. Suppose you had a monster with:

regular frames run1 .... run6
a framegroup [idle1 ... idle40]
more regular frames attack1 .... attack8 etc

Then to get at the run frames you'd set
self.frame = 0...self.frame = 5
To play the idle animation you'd set
self.frame = 6
And to get the attack frames
self.frame = 7...self.frame = 14

One of the disadvantages of this arrangement is that the QC has no way of reading where the animation has reached at a given time. This would make it hard to sync a sound with the animation for example.

Open question here...when you have a QC command like self.frame = 6 on a model with a framegroup at frame 6 and NO random flag set, does that command start the animation from the beginning? I suspect that if the frame was already 6 it wouldn't work, as no network update is sent out for a frame remaining the same. If you could get that to work you could do some nice long idle sequences on a monster using them, without running out of frames for important things

So basically the use of them is to cut down on the amount of QC you need to make a simple looping animation. This is vital for static entities which don't have any qc interaction once created(hence static), and can make other things easier.

Another open question paired with a technical fact...If you poke around in the mdl specs like Willem has been doing, you'll notice framegroups come with a value to control the duration of each frame in the group. From my memory of messing with these thing, I could only ever get it to obey the duration of the first frame in the group, the rest of them just automatically followed that. Is that a long standing bug/just Carmack forgetting to add (frameindex*framesize) to the pointer to retrieve it? 
 
I thought that the animations ran at 10Hz or something and that was that. I know the spec has that array of floats that are claimed to be timings, but nobody ever talks about them so I sort of assumed that they were always set to even intervals or just plain didn't work.

All the fire and stuff in Quake seems to animate at the same speed, at least to the naked eye. 
 
i could never get the framegroup animation speed thing to work from within qme3.1 :S 
 
Could someone with engine familiarity confirm or deny if that code works or not? I'll bet Preach is correct that either it's being ignored intentionally or Carmack has a bug in the engine where he doesn't read the values in correctly and never noticed. 
Well 
Admittedly when I managed to get different rate framegroups to work I was using darkplaces, so it's possible that regular engines have no support for it and darkplaces had slightly broken support for it, I will go away and check this weekend(hopefully).

As for the 10Hz thing, it isn't hardwired into quake that things animate at that speed, but there are 4 reasons why it is almost exclusively used.


1: It's the rate at which all the existing quake models are animated. So anything new usually follows that pattern.


2: The QC shorthand way to define animation functions in quake like

void() ogre_stand6 =[ $stand6, ogre_stand7 ] {ai_stand();};

implicitly assume a 10Hz rate, they insert a self.nextthink = time + 0.1; at the start of the function. You could change that in the function body:

void() ogre_stand6 =[ $stand6, ogre_stand7 ] {ai_stand();self.nextthink = time + 0.05;};

but it's awkward, and also the original nextthink remains before it.
(I think a nice fix would be a way to specify $fps in the $frame macros, and then have the compiler insert the correct nextthink time when expanding animation functions. But I've barely managed to get FTEQCC to compile, so it may never happen.)


3. It is the framerate which the game will guarantee - if the game is being so slow that it can't achieve 10 fps then it will slow down game time. You might set thinks every 0.05 seconds and have them still occur every 0.1 second in game. Of course, in the real world quake is 10 years old and so never runs slow, but it's a nice theoretical.


4. The other limits of the mdl format start to show once you start animating at higher framerates. 256 frames only gives you 12 seconds of animation at 20fps, and you have to cram all of a monster's death/pain/attacks into that length of time. Often doable, but pretty tight. Also, the compression of the vertex coordinates means you get rapidly diminishing returns on increasing the framerate. The result wobbles might be worse than keeping 10fps and letting the engine interpolate at higher precision.


I don't think any of those things is enough to completely kill working at higher framerates though. What I'd like to see is some specified use of it. Keep 10 fps on unimportant/low motion animations like idle poses. But when you have a big sweeping motion like a sword slashing, increase the framerate for that to 20. This gets around both of the problems of point 4 there.

If you do run into problems where you have too many frames to increase the framerate, it may be possible to abuse framegroups to provide the interpolation you need. This does rely on two things - that you can set custom framegroup fps, and that when you enter a non-random framegroup from a different frame, it starts animating from the beginning. 
 
OK, so in further poking around am I right to assume that an MDL will either be using simple frames OR group frames? There's no mix and match going on, correct? 
Combined Force 
You can in fact have both in the same model, it is possible to combine the zombie crucifiction frames into one framegroup and make crucified zombies static(but then you don't get the random duration of frames or the sounds, so it's not a PRO TIP or anything). Doing that doesn't affect the rest of the frames in the model, so regular zombies work as normal.

Also, changing the rate is inconsistant: in glquake engines the duration is taken from the first frame, in winquake it reads each frame duration correctly. There's an argument there that the bug should be fixed in glquake engines there, but best practice is probably to use the same rate for the entire framegroup, and set it in each frame so that winquake handles it the smae.

The bad news is that when rendering a framegroup which isn't random, the frame to render is just calculated from the world clock, rather than the time since that framegroup was set (That is assuming I've read the relevant code correctly). This means you can't abuse framegroups to provide increased interpolation with the same number of frames on the QC side. 
 
Ahh OK. Well, good to know then. i'll need to handle it all gracefully then, no shortcuts. :) Thanks... 
Framegroups 
When I tried to combine the skull of Lostsoul with the flame2.mdl I was overtaken by the fact that Quark407 in model import reakts:
can't handle framegroups.

Is there a way to break this options so I can manipulate the modelframes? 
 
open flame2.mdl in qme, remove frame groups, save, open in quark. 
 
framegroups, does this mean
the parts of vertices within a frame like the different flame parts,
or different frames?

The only way to avoid this "no framegroups supported" for me is by exporting a flame2.dxf and import it back as a new model. Then I can reimport the multiple frames, and quark can import it. 
 
Frame groups, as I've come to learn over the weekend, are basically a collection of frames that are special in that they will animate autonomously without having to tell the server about it. Each frame is a complete animation frame, just like the simple frames in other models. 
So 
the different parts in one frame make quark tell it is a framegroup.

I know nothing about servers and how it works in quake.I just wondered why one frame left in qmle after deleting all other frames in flame2.mdl still errored quark with framegroups.

It is the same error I had after decomposing a death frame to divided parts. After saving they were all melted together again. 
Animated Skins 
It looks like MDLs have support for animated skins but no MDL that I ever open has one. Can anyone recall a model that had an animated skin on it in a mod or anywhere else? 
No, 
but i believe you are refering to skingroups?

i've heard people talk about that but never found out how to do it, myself. 
 
Sorry, yes, skin groups. I see them in the spec and was just wondering if they've ever actually been used. I guess once these tools are further along I'll just test them out and see what they are. 
Have You Watched The Cutscenes 
on Nehahra? They have like facial animation as in the mouth texture has two frames. Also isn't there some blinking? 
 
Well, how are these skingroups used? I'm going to assume that it's like the frame groups - some sort of automated animation system. If that's the case, I guess they could have had a moving mouth with blinking thrown in here and there to make it work (no lip syncing at all but that's probably a given in the Quake engine). 
Ricky 
i believe the talking and blinking (not sure about the blinking, that may have just been random?) was handled via impulse commands and that the 'actor' players would do that themselves. or it just occured to me, they maybe did it in post in a demo editor. 
Hmm 
just to clarify, do you mean something like painskins (sweeeet)?

http://www.inside3d.com/showtutorial.php?id=95

Or, an animated concurrent effect? 
I Like Painskins! 
i managed to do that once when i was about 15.

Bring back painskins! 
 
HT

No, that tutorial looks like it's just bumping up to another skin index. The skingroup stuff looks like an auto animate deal.

Preach! :) 
*We* Seem To Be Going Round Twice... 
You can auto animate skins, it's pretty much the same deal as the frames, you can designate a collection of skins as a single skingroup, they autoanimate according to timings set in the model. I have no idea if the random flag works on them, or if the same glquake bug for duration exists. If you want an example of a model which does it, dig in the quoth pak1.pak for a model called pickup.mdl. The last two skins, which are for the health and megahealth, have such animations to make the lights blink.

Necros: how you do it in qme is arrange the skins in order, then right click on the first one and select "Append Skingroup To Previous Skingroup". Repeat until all the skins in the animation are combined, and then save the model again. 
Skingroups 
i'm pretty sure these are the analog to framegroups in models and sprites, basically client-side looped animation.

based on the engine code, it looks like glquake has pretty half-assed support for skin groups, for example every skin is given 4 pointers to textures, and almost all the time the 4 pointers are to the same texture, but when loading a skingroup it gives them unique pointers. If you have more than 4 skinframes, it drop some.

So effectively you can only have 1, 2, or 4 skinframes in a group in glquake. If you have 3, it will animate 1, 2, 3, 1, 1, 2, 3, 1... and if you have 5+, it will animate (e.g.) 5, 2, 3, 4, 5, 2, 3, 4...

Also, not sure if the model format supports intervals for skingroups, but glquake clearly only does 10Hz animation for them.

My guess is there's one model somewhere in the mission packs using this feature, and that required them to add this minimum of support to glquake when they wrote it. 
Mother Of God 
Christ metlslime, pull the curtain back again, that's hideous!

Informative though, cheers really. 
 
Haha, horrible! Well, good to know that supporting that can go at the bottom of the priority list at least. :P 
Well 
Blinking health items at least.

Possibly some really shitty animated soul sphere swirling is possible . . . in four frames.

Can't think of a decent monster application - glowing eyes? 
 
"Blinking health items at least. "

Huh, that's true. OK, I guess that'll be my test case for loading skin groups then. 
 
"Can't think of a decent monster application - glowing eyes?"

I think many cool ideas could be done there. Glowing demon eyes, blinking lights on enforcer armor, blinking eyes, etc. Could be neat. 
Pain Skins!!! 
pain skins!!!pain skins!!!pain skins!!!pain skins!!!pain skins!!!pain skins!!!pain skins!!!pain skins!!!pain skins!!!pain skins!!!pain skins!!!pain skins!!!pain skins!!!pain skins!!!pain skins!!!pain skins!!!pain skins!!!pain skins!!!pain skins!!!pain skins!!! 
 
To be honest, pain skins don't really excite me in Quake because how often is a monster in pain? You see the monster and it's generally dead within seconds. Would you even see the pain skin kick in? 
Its Just A Daft Thing I Wanna See Really 
Monsters are all a bit bruised/bloody anyway, but brown grunt stood up, 2 seconds later red and bloodied grunt on floor. I mean I know that the pain skins would be non-locational, but for monster like a Shambler or a Vore you could have three or four increments of pain, relative to HP, and it would show how close that Shambler you've been picking away at with an SG or SSG for five minutes is to death!

I just think it looks cool. I also wanna see a mod with pain skins and zombie-gib blood splats dribbling down walls from when mosters are shot.

I know its meant to be easy in Quake C, theres a tutorial on Inside3d. Maybe this will be my first Quake C project . . .

(I had it working once when I was about 15, but I cant remember how it worked now, and haven't tried yet) 
 
Dead skins might be a decent idea. The corpse on the ground could be all fucked up and bloody. That might make more sense... 
Ok, Pain Skins In 5 Minutes 
Lets say we work with the grunt, and give him a second skin which is bloody and beaten up. Now open up soldier.qc and look for the function
army_pain
Right at the bottom of this function, add

if(self.health < 15)
//if we are below half health
self.skin = 1;//turn on the pain skin

This will work a lot of the time, but there's a chance that the grunt goes from above 30hp to dead without going into pain. Also, if the grunt is dead, we should check if he gets gibbed, and set the skin back to 0 if so, because the grunt head only has 1 skin. So find army_die
and put

self.skin = 0;

just after

if (self.health < -35)
{


Then put

self.skin = 1;

after the closing } bracket of that gib section of the function.

You can do a similar thing with pretty much any monster, find the pain function and use that to add the pain skin. Remember that some monsters don't automatically go into pain animations, and may return near the top of the function. This means that you have to think about where to add the line. You could put it right at the top, so that it always gets checked. Or you might decide that the skin should only change if the monster goes into pain, and so put it at the bottom. 
Pain Skins 
could have a practical purpose...

assuming your were consistent and always used pain skins for, let's arbitrarily decide 50% hp.

you could make like a monster that 'heals' wounded monsters if they are below 50%. you'd have a visual indicator for what's happening and it could be a cool new mechanic.

well, maybe something more complex would be in order like 'heals the monster to 90% of maximum health.' so each time it heals, the max health goes down and you could put in a check where it wouldn't be able to heal if the current max health is less than half of the actual max health. 
 
Oh duhr ... I can't use the health packs as a test case for skin groups in MDLs because those aren't MDLs (they're BSPs). Heh. Oh well... 
After Giving It Some Thought 
I think I know what Willem's next project is: Iron Man Arena, and he needs the effects on the player models to simulate the repulsor beam socket, and the jet flames coming from the boots. Imagine hovering around firing missiles and repulsor beams at one another with Twig or Gyro2 physics to both impede and improve our navigation. Oh, this is going to be sweet.

Am I close? 
Dead Skins 
Is interesting - pain skins doesn't really do it for me since most monsters are bloody anyway, and shooting a fiend in the back for some bloody mess to appear on, say, it's face is counter to what you're trying to achieve with the effect.

You could paint a handful of skins per monster and have them directional, but that misses the point of multiple damages - you'd only be able to have one active skins since you can't apply decals.

Dead skins is more interesting idea - you have the creature vomiting blood and caked in dirt. Problem is it started bloody, will anyone notice?

You could go whole hog and have a Mancubi style death - for example the Shambler's stomach could rupture when he dies, but then it probably wouldn't look very good with a single frame change and no 3d animation.

Healing enemies is good, like a Q2 medic form, but in order to show that monsters are injured I'd prefer to have them bleeding; particles dripping from them. 
 
"Dead skins is more interesting idea - you have the creature vomiting blood and caked in dirt. Problem is it started bloody, will anyone notice?"

On some you would. You would definitely notice a change in a shambler, enforcer or grunt. Creatures like ogres would be tougher but it might still be worthwhile. 
Pins Skins Pain Skins Pain Skins 
monster <70 %

Some more blood around the chest and a little on the back, face and arms, some dripping down upper legs

monster <30 %

Big hole in chest, large exit wounds on back (i.e. gored up) more drippind down arms and legs

monster dead

Some blood particles flowing from the monsters midrift and maybe neck/face

monster -howevermuch it might be %

Gibbed!

It makes sense, you know it does. In a game so abstract that you can gib monsters in the style you can already, it would only add pleasure to my experience :D 
Dead 
You could go whole hog and have a Mancubi style death - for example the Shambler's stomach could rupture when he dies, but then it probably wouldn't look very good with a single frame change and no 3d animation.

for the zdoom md2 models, they did seperate models for the monster deaths. the 3d mancubus death looks pretty good, as does the cacodemon.

i think if someone wanted to take the time, they could revamp the old death animations in that same sort of style for quake with new models. 
Willem And Bsp 
There's a mdl version of the health box (and indeed all the ammo pickups at the same time) included in quoth, which would be suitable for your testing. You'll have to extract it from pak1.pak, and it's called pickup.mdl. 
 
Sweet, will do! Thanks for the heads up, Preach. 
 
Oh, and it just occurred to me ... so THAT'S how you supported rotated pickups then. Neat! 
Rotated Pickups 
You can rotate pickups in their regular quake form. The only problem is that the bounding box doesn't change when you do that, which is compounded by the fact that the ammo boxes rotate about one of their corners, and not their centre. If you rotate them 180 degrees, the model entirely escapes the bounding box!

The quoth fix is just to put the bounding box in the right place relative to where the model get rotated to. The advantage of using the .mdl version of the ammo is that it saves you up to 10 model precaches, which can be helpful if you're pushing the limit(Stark Monstrosity showcases this feature).

The side effect of the .mdl version is that the crate is lit according to the ground below, rather than the baked in light levels of the regular ones. In order to stop crates getting lost in the dark, we a: disabled it by default and b: added small fullbright markings to all of the ammo. The shells and nails had these already, so it was natural to extend the idea to the other ammo. 
I Drew The Line At Cutting Out Monster Head Gibs 
you can cut those out too.

I did however use the combined ammo .mdl flag at the same time as the one preach described. I like the fact that you add the two flags together, seems like a smart system. 
Heheh 
If it's a smart system, it was invented by a smarter person than myself. It is in fact the same system that spawnflags use - the spawnflag for "not in easy" is 256, "not in medium" is 512, and so "not in easy or medium" is the sum of the two.

In both cases, the values you have to set are chosen to by successive powers of 2( 1, 2 , 4, 8, 16, 32...)
These numbers are chosen because the sum of the first n-1 numbers is always 1 less than the nth number. That way, the sum of any subset of them is unique, and any number you chose corresponds to some combination of them.

There's also a connection with how binary numbers are stored as integers. So if you know about that, you can think of the nth 0 or 1 digit in the binary representation being on or off according to whether the nth option has been selected. 
Preach 
Did seeting them fullbright look bad? 
$frame Question 
OK, so I'm trying to get MDLEd fully functional and I have questions about QuakeC and MDL files...

Do you have to have a "$frame blah1 blah2 etc" for every animation frame in the MDL?

Do they have to match the internal structure of the MDL (do the frames have to be stored in the same order as the $frame lines in your QC file)?

What I'm getting at is this ... will I have to allow the user to have full control over the ordering of the frames in the MDL file or can I safely/automatically sort them alphabetically? Does it make a difference? 
Afaik 
the $frame walk1 walk2 at the beginning just macros those strings to a number, and that number starts at 0 on the first $frame declaration and increments by 1.

so walk1 actually means frame 0, so frame 0 needs to be your walk1 frame.

in other words, the order of those $frame declarations are important and so can't be re-ordered without re-ordering the frames too. 
Fullbright$ And $frames 
ijed: as far as I know, there is no standard way to make a .mdl fullbright. It's just one of the differences in the way the two types of model get rendered, bsp have their own lighting info, and mdl use the map's light levels. I do think that medpacks looks pretty cool in .mdl format when placed in dark corners, it makes the lights blinking away on them really stand out.

Willem: You must at least make sure that you don't alter the order in which the frames occur without giving the user control over it. The actual names given to the frames in the .mdl aren't used by the engine/qc. It relies entirely on the enumeration of them in the order that they occur.

The $frame macros are simply a way of defining recognisable constant names for the numbers 0....n in a quick manner which only lasts for one qc file. The qc compiler has no knowledge of what the actual model file contains, so it just substitutes a frame number for each instance of $stand4 with a 3 - assuming that $stand4 is the 4th $frame that it encounters in the header.

So if your program loaded in ogre.mdl, reordered the frames into alphabetical order and then saved them again, the animations would no longer match up, so that would be bad. As long as you ensured that frames were exported in the same order they were imported, you would probably get away with it. But I suspect it would still be a desired feature...

(As a possible side note, people making qc files don't have to define the $frame things for every frame, they can just use the numerical indexes, or a mixture of the two. But just using the numbers can mean a lot of code has to be changed if you extend your first animation loop from 6 to 8 frames, so it's not encouraged to do that for anything with multiple sequences) 
 
"You must at least make sure that you don't alter the order in which the frames occur without giving the user control over it. The actual names given to the frames in the .mdl aren't used by the engine/qc. It relies entirely on the enumeration of them in the order that they occur. "

Beautiful. OK, that settles that then! Thanks. 
Hmm 
Hey coding thread.

Very sorry about this, never post in here since I'm not a coder, so tend to skim read and leave you guys to your scary quote text fun ;p

Just wanted to bump stuff above the flame thread again (I suggest anyone else reading this does same and avoids bumping again pls ;)

Kiss 
MDL Hell... 
Man, this file format is fairly jacked up.

Anyway... Quick question:

Is the "onseam" stuff entirely necessary for texture coordinates or is that some sort of concession that was made to allow for easy skin creation back in the day? If I store all texture coordinates as full 0-1 values and set onseam to zero for them all, will Quake throw a fit? 
Onseam Bowling 
When making new skins, it's no longer really necessary. If you're trying to do anything more complicated that 2-sided planar then you pretty much have to ignore it, and just eat the extra vertices on the model. The md3tomdl converter does exactly this.

However, it's very important that you keep them for existing models, as it tells you which vertices need to be duplicated on the skin. I think if your program didn't preserve the original quake models like that, people would get confused to say the least.

If you changed models to duplicate vertices which were onseam, and then removed the onseam flag, there could problems in other editors. For example, if you saved one like that, then loaded it and saved it with QMe, then the vertex normals along the seams would be altered compared to the original, which might make the seam more obvious. 
 
Wow, so the whole purpose behind it was to save a vert or three in the mdl file? 
Hmm 
Bear in mind we're talking the first full 3D fps here.

What we now view as insane levels of optimisation was fairly necessary back then... 
 
I question some of the stuff, actually. Carmack did some crazy machinations in places to save very minimal amounts of space. 
Ijed 
We need to think about skin animations. Blinking lights on enforcers are neat, and I have a couple other cases where this could be useful.

Apart from that. Do the additional mouth/face textures often seen on id skins have something to do with this?

Were they meant for animation purposes? 
 
I think those are for the head gibs. 
Gib Faces 
Would be a perfect addition for death skins (if they get implemented somewhere) 
Maybe 
I'd guess the whole onseam system was created because at the time it seemed like an unintuitive system to have vertices occupying the same position in the model, but connected to different triangles - when they are supposed to be part of the same surface in the model. The onseam method was a fix to the problem "how do I display the same vertex in two places on the skin?". It's just unfortunate that the solution pretty much ties you to the front/back skins that quake used.

Although I usually advocate the detached vertex solution, detaching things like that can cause problems. For example when calculating the vertex normals at that vertex, you probably want to average all the surfaces meeting at the split vertices, and give that same vector to all the vertices. This is a lot harder to do once you've split the vertices. In fact, if an unrelated vertex just happens to collide then you're scuppered...

Thankfully, .mdl uses precomputed vertex normals, so as long as you're converting from a format that supports merged vertices with split UVs then you can probably get sensible smoothing groups. Also, worrying about smoothing groups isn't the most pressing concern with quake models.

Interestingly enough, I don't know that onseam actually saves memory over all, when you consider how much wasted texture space there is as a result of using it. On models with lots of frames it's probably beneficial as the extra vertices would be recorded on all those frames. But for weapon models and other simple models, onseam probably doesn't make up for the waste. 
 
I think headgibs use their own models, which use their own skins. 
I'm Aware Of That 
How difficult would it be to copypaste the faces from the head gib skins onto body skins? (I'm no modeller so I can't tell) 
Yeah 
I want blinking lights for the enforcers, that was a good suggestion, whoever made it.

It looks from the models that the head gib was originally going to come from inside the main model, but it didn't work out.

Simple as export c+p import to put the pain head onto the normal guy for a dead skin. 
 
I was replying to Willem about the additional face parts etc. on id1 skins. Those are pretty weird. 
So Was I 
It seems the extra faces are there because the head and model were originally going to be combined, until they realised that hiding the entire body inside a copied head would be more wasteful. 
Just Think.... 
how awesome it would look if they did hide the body inside the head gib, now that we have engines that do model interpolation? 
Vampires! 
Back in the day before I worked on mods that people would play, I made a quake mod where you fought vampires - aping Buffy and that kind of thing. One of the driving things behind it was to make the death sequences look cool (by quake standards), so when you staked a vampire through the heart they'd look agonised for a beat, then explode into a puff of dust.

Coming back towards relevance, when you killed them with fire the flames burnt upwards from their feet while their arms flailed. In order to make their legs disappear, the polygons were just folded up into the upper legs, then the torso, with the flame graphic concealing the interpolation which arose. I imagine the final effect is not too dissimilar to what metl's thinking of.

(ps: the head gibs are probably separate for the more mundane reason of giving them a blood trail, which is a per model effect...) 
Railgun In Quake 
is it possible?
i'd appreciate any help 
 
Sure, there were some mods with railguns I think. 
Ahem 
And I just remembered I once successfully completed this tutorial: http://www.inside3d.com/showtutorial.php?id=167 
 
Spy Parboil once change the qwprogs.dat to railmod i think... since u are russian is easy to ask in is forum :)

http://parboil.quakeworld.ru 
 
zomggg are you the spy from the old Parboil board?

hehe 
Quakec Question... 
what is the proper way to make an entity toggle between visible/solid and invisible/nonsolid?

So far, what i have tried is calling self.modelindex = 0, self.solid= SOLID_NOT to make it invisible, then doing SetModel(self, self.model), self.solid=SOLID_BBOX again to make it visible.

Visually, it works. But, once it's been invisible, it can never turn solid again.

So, is there a better way? 
Trinca 
what are you talking about?

psssst. trinca don't tell anybody that i'm russian it's a secret :))

p.s. thanks spirit for the link....... 
Zomggg 
i think i'm drukn again 
(in)Visible 
To make it invisible and non solid, the following should suffice:

self.model = "";
self.solid = SOLID_NOT;

Not sure if adding self.modelindex = 0 adds anything to that, it might stop it being sent over the network.

To restore it again, use:

setmodel(self, *modelname*);
self.solid=SOLID_BBOX;

If you don't know *modelname* at compile time(eg a func_wall where the model is loaded from the map), then you need to stash the model info somewhere safe. Put a line like

self.mdl = self.model;

somewhere in the spawn function, and then use self.mdl in place of *modelname*.

If you're still having problems, try adding a call to setsize after setmodel 
Thanks For The Help... 
i finally got it to work, and here's how.

1) to enable being solid after turning inivisible and then visible again, i only ever set the model using setmodel once, and from then on alternate between setting modelindex to 0 or the actual index.

Since setmodel is never called, the entity stays linked into the world with the original physics bounds. self.solid can be changed without issue.

2) for entities that are set to START_OFF, there was still a problem where they'd never appear at all, and never become visible. My hack solution is to wait 1 second, then make them invisible/nonsolid in a special think function, rather than in the spawn function. 
Good 
explanation to make a monster invisible.

I'm still trying to find the right colours to improve Spectre in its translude way.
And as it is a sprite it has a funny way of walking. I think more darker colours on the outside and transparant inside.

http://members.home.nl/gimli/spectr.jpg 
Can Be Shot But Doesn't Collide With Walking? 
I'm probably going to think of the solution 5 seconds after asking this but ... let's say I want a monsters corpse to be shootable but I don't want it to collide with other corpses or the player. I just want it to react to gunfire (both instant hit and missiles).

Doable? 
Look At The Corpse, It's Voodoo QC Dancing... 
It can't be done easily. I say that because darkplaces has an extension for just this purpose, where you can make an entity SOLID_CORPSE, which behaves like you say. The following is ugly, not only in itself, but also in the dark secrets about standard ID1 code it exposes. Read on if you dare...


The key thing is that you can't change the .solid status of things during touch functions, it can cause engine crashes. So, the vast majority of the time, you want your corpse to be the same .solid type as a trigger_multiple entity, which is SOLID_TRIGGER.

We're going to use the grunt as our test dummy here. This is the kind of thing you need to do in your death sequences, during the frame that usually makes the monster SOLID_NOT:

void() army_die3 =[ $death3, army_die4 ]
{
self.solid = SOLID_TRIGGER;
setmodel(self, self.model);
self.touch = corpse_touch;

self.health = 20;
self.takedamage = DAMAGE_AIM;
self.th_die = GibPlayer;
self.th_pain = SUB_Null;

self.ammo_shells = 5;
DropBackpack();
};


We make it SOLID_TRIGGER, then call setmodel in order to link it, which prevents a "trigger in clipping list" crash. We make it's touch function corpse_touch, see below. We also make it damageable again, give it 20 hp, and define both th_die AND th_pain, the latter being important if you don't want to reanimate your corpse.

So here's the deal. In this state(SOLID_TRIGGER), when a missile collides with one, you get a touch event where the trigger is self and the missile is other. You do not get one where the missile is self and the trigger is other! I'm not sure if this is an optimisation just for missiles, or that any entity touching a trigger doesn't set off its own touch function. In any case, we're about to cheat:

void() corpse_touch =
{
local entity oself;
if(other.movetype != MOVETYPE_FLYMISSILE && other.movetype != MOVETYPE_BOUNCE)
return;
oself = self;
self = other;
other = oself;
self.touch();
};


See what we're doing? The first bit of code is just so that we don't bother doing anything if we aren't hit by a missile. You might want to use a different criteria for what is a missile, I went for something that required no changes elsewhere. Then we create a touch event on the missile by the trigger, but by hand instead of from the engine.

Once you've done that, you might think we're done for missiles now, and you can give it a try by lobbing a grenade into a corpse. It'll explode on contact as desired (you can of course change the corpse's .takedamage to DAMAGE_YES if you want to prevent grenades from detonating on contact, I set it like this for illustrative purposes). However, if you fire some nails into your corpse, you might be surprised to find nothing happens.

The reason for this is due to some entirely redundant code in the original QC, which must have been moved engine-side for performance, but then remained in the QC source by mistake. Look at the start of spike_touch in weapons.qc:

void() spike_touch =
{
if (other == self.owner)
return;

if (other.solid == SOLID_TRIGGER)
return; // trigger field, do nothing
...


You'll actually notice the first line in the code for almost all quake missiles. It's totally pointless, as the engine never makes collisions between entities and their owners. Just think how many times that code has been called in a million deathmatches across the world, and not once has it been true...

As we discovered near the top of this section(and to be honest I never knew about this before I tried today), SOLID_TRIGGER entities don't generate touches on missiles either, so the next line is similarly pointless. To get things working, comment both statements out, and do the same in superspike_touch. If you're bored, get rid of the self.owner lines in the grenade and the rocket.

If all has gone to plan, at this point all the missiles will damage the corpse.

Join us after the break when we investigate the shotgun and other tracelines... 
You Can't Talk To A Man With A Shotgun In His Hand... 
Before we start the business proper, I should alter you to two bugs with the code which only became apparent once the grunts started hitting corpses with their shotguns. The first is that when monsters begin infighting, they don't realise that their target monster has died when they become a corpse. This is because they consider their enemy dead if their health is below 0, but the corpse has positive health. The fix for this is left as an exercise.

Also, if the corpse gets damaged by another monster, it will get resurrected. To prevent this, add the line

self.flags = self.flags - (self.flags & FL_MONSTER);

when creating the corpse.

~~~~~~~~~#~~~~~~~~~

Ok, so the question is, how do we deal with weapons that use a traceline. And the solution is we make the corpse solid only for long enough to perform the tracelines. We in fact toggle the solid state of all the corpses in the map. Although in theory we might end up changing the solid status of something during a touch function(if a touch caused a shotgun to fire, for example) we hopefully* put everything back before the engine can notice.

So the simplest way I could think of to change all of the corpses to solid and back was: give all of your corpses the classname "corpse", then use the following functions to toggle the solid status:

void() corpse_solid_on =
{
local entity corpse;
corpse = find(world, classname, "corpse");
while(corpse)
{
corpse.solid = SOLID_BBOX;
setmodel(corpse, corpse.model);
corpse = find(corpse, classname, "corpse");
}
}


void() corpse_solid_off =
{
local entity corpse;
corpse = find(world, classname, "corpse");
while(corpse)
{
corpse.solid = SOLID_TRIGGER;
setmodel(corpse, corpse.model);
corpse = find(corpse, classname, "corpse");
}
}


The trick is then to surround calls to traceline with these functions. The axe is very simple, just put corpse_solid_on(); on the line above the traceline and corpse_solid_off(); on the next line after it.

For the shotgun, it's worth remembering that there are lots of calls to traceline in a single blast, and since toggling the solid status is fairly expensive in terms of performance, we should do it once per blast. So sandwich the functions around the

while (shotcount > 0)
{...}

block.

The lightning gun is left as a small exercise, but it's only really worth wrapping the first traceline in the function, the other two are basically enormous bugs which speedrunners exploit to kill things through walls.

That's almost it, but there's one finishing touch. If you go up point blank to shoot a corpse, you'll find that your shot disappears, or attack does nothing. This is because the traceline starts inside an entity, and so the returns from the traceline are a bit weird. The telltale signs of this happening are:

trace_fraction == 1 (not 0 as you'd expect)
AND
trace_ent != world (if it is world, then the trace really did hit nothing)

So what we do is add a bit of extra code which can cope with this case to the various weapon attacks. As an example, add the following code just below

if (trace_fraction != 1.0 )
TraceAttack (4, direction);

in the shotgun firing code:

else if (trace_ent != world) //if so, we are stuck inside what we have hit
{
trace_endpos = src + direction*16; //set some reasonable values
trace_fraction = 16/2048;
trace_plane_normal = -1 * direction;
TraceAttack (4, direction);
}


The code for the axe/lightning gun is similar, but if people get stuck on that exercise I can supply good fixes.


Well, that wraps things up for today. I would say that this latter part is quite an ugly hack, but the code in the first post is actually fairly clean. In all cases you should ask yourself "Would I show my mother this code" before you do something you might regret.

As a final parting thought, you might want to adjust the height of the bounding box of the corpse from the default, so that shots at head height don't blow up the corpse. If you do, remember that you need to do this in both of the corpse_solid toggling functions.


*I say hopeful, but I'm pretty sure it should work. I'm just not sure how careful the engine is at checking, and it's such an awkward thing to create a test case for. So I'm gonna be cautious in my endorsement. 
 
Preach, you are fucking awesome. :) Thanks man, I'm off to digest all of that. 
 
Absolutely beautiful, that all worked. Thanks again! 
Yeah 
That's very nice, thanks for the explanations. 
Bit Of A Backtrack 
A few pages ago I said QC only checks the first component of a vector when evaluating boolean logic on them. This is not always true.

if((!'0 1 1'))

will work correctly - notice the double brackets. If you take the inner brackets away, then it stops functioning correctly on compilers which perform optimisations. Here is why:

When an if statement is compiled, it gets boiled down into an instruction to skip over the next n lines conditional on the value of an integer fed to it. QC actually supports two operations: IF and IFNOT. The former skips a number of lines when the integer is non-zero, and the latter them if it equals zero.

When the original QC compiler encountered code like:

if(!my_number)

where my_number is a float in qc, it would actually break it up into two instructions: The first one would apply the logical operator ! to my_number, and store that in a temporary. The second instruction would then feed that temporary to an IF_NOT.

One of the first created QC compilers saw a chance to optimise there, change the IF_NOT to an IF, and skip the ! instruction entirely. This sounds reasonable enough, except that you must not do it for a vector. There is a special operation for applying ! to a vector, which actually applies it to all three components. If you don't use it, then the first component of the vector gets mistaken for a single float, and you get bugs.

In conclusion, the original QC design was perfect and Carmack remains a god. The bug lies in the newer compilers, which should not optimise in the vector case.

Coming up soon is a description of the sequence in which things occur in a frame, which is the reason I was poking about in the source. 
 
Are optimizing compilers really even necessary? I mean, has Quake ever been slow when fed reasonably coded QuakeC? 
Possibly 
QC probably used to be a potential bottleneck, back in the day when r_speeds of 800 was considered unacceptable. The engine contains a "profile" command to see the 10 most demanding QC functions, so they were being optimised back in the day. Probably this is where some of the builtin functions come from, like find and findradius, which could be written in pure qc given the earlier builtins.

Nowadays modern limit-pushing maps increase the number of faces by a greater factor than they do number of monsters/entities(most of which are idle and no serious drain anyway). In addition, much of the greater rendering cost gets push onto the graphics card.

So in that sense bad QC is unlikely to cause a framerate drop or anything like that. But there are other limits that have to be fought when it comes to quake. There is a maximum size that a progs file can be, for instance, and compiler optimisations which eliminate duplicated strings in the file have helped large mods compile.

Also, the runaway loop counter in qc is 100000 instructions in a function. If you're coding some kind of loop, then any instructions you can eliminate from the inner loop section are invaluable in avoiding the runaway limit. The findradius builtin mentioned above swaps what would have been a loop through all the entities with a pass through a linked list of the relevant ones.

Of course, there's also some personal satisfaction involved with some optimisation. I've been playing a kind of "programmer's golf" with the ID1 progs, trying to get as few instructions as possible in the monster ai functions like "visible" and "range". At the moment I'm trying to resist writing them directly in assembler to eliminate another temporary variable...they're the best targets for optimisation if you'd like to make a 20,000 monster map support 25,000 instead! 
Tracebox In QC 
Nobody asked for it, but here it is anyway: A way to perform a tracebox, similar to traceline but with a full sized object, without engine extensions. Caveats: The emulation of a trace is not perfect; it can throw a false negative in the case where the trace travels through a small but non-zero vertical distance. The test has been designed to prevent false positives. In addition, it's quite expensive in QC operations, although look to the previous post to see whether you should care about that.

"Your mother's a tracer!"
So, the key to being able to trace is, strangely enough, flying monsters. Most of the box-tracing which the engine performs is during physics updates. This makes them unsuitable for testing traces "on-demand", since you have to give control back to the engine first. However, monster movement is performed in discreet steps, moving instantly from one point to another using the walkmove function. Flying monsters have the additional advantage of not being bound to the ground, so we create an entity with FL_MONSTER and FL_FLY set to perform our trace.

The carrot and the stick
It's important to understand exactly what causes a flying monster to change altitude. Every time walkmove is called, the moving monsters decides if it is at the right height, too low, or too high. Accordingly, it attempts to trace a move straight forwards, forwards and up by 8 units, or forwards and down by 8 units. It makes the decision based on the height of its enemy relative to itself. So to control which way our monster goes, we need an enemy entity whose height we can set. This is quite like the carrot on a stick you wave in front of a donkey to guide it onwards, and I shall refer to it as the "carrot". Since our donkey can fly, it will be named "pegasus".

Running the course
The first problem is that we can only climb 8 units at a time. The solution is to call walkmove repeatedly, dividing up the trace up into segments, where each segment has a z component of 8. Since it is unlikely that the trace will have a height exactly divisible by 8, we need to perform an initial run which stops less than 8 units away from the target height, then reset the origin of pegasus so that it lies on the path of the trace, 8 units from the target height. Full marks for whoever spots the tricky boundary case of this method.
Preach's Pro Tip: You can use this trick of calling walkmove more than once to get regular flying monsters to ascend/decend more rapidly!

Jumping the fences
The next problem is what happens when the movement of the pegasus gets blocked. What few people realise about walkmove is that if the trace is blocked, the monster doesn't move at all - I personally imagined it would move the monster as far as it could before being blocked. But if the movement with vertical motion is blocked, the code does attempt a move with no vertical motion before giving up. This could create false positives easily. To make sure that pegasus is properly jumping the hurdles, check that the height of the pegasus changes from one walkmove to the next. This is the simplest test, as it doesn't matter if the trace is going up or down. Of course, you shouldn't do this if the trace is truly flat!

The final straight
A big problem arises if you want a trace which isn't flat, but rises/falls less than 8 units - a shorter distance than a single walkmove. This is the corner case astute readers may have caught earlier. It might be tempting to give yourself a "run-up", to trace from a position behind the desired origin, through the desired start to the finish, so that this extended trace has the right height, and accept the false negatives that the longer trace might cause. The problem is that this might actually cause false positives!

If the pegasus starts within a solid part of the bsp (or possibly other object), then it seems to skip through without colliding. As traces get closer to 0 height, the pegasus takes a longer and longer run-up until it is exceedingly likely it will be outside the level. So instead, the best solution I could come up with for this case is: Increase the height of the pegasus by the desired height, adding it to the maximum height if the trace goes up, and the bottom if the trace goes down. Then perform a horizontal trace. If you look at the 2-D side-on view of the trace, this is effectively taking the rhombus which would be the exact trace, and replacing it with the smallest rectangle which could enclose it. 
Tracebox In QC II 
You can lead a horse to water...
Through the steps in the previous post, we've built a reliable tracebox which reports few false positives and no false negatives. So it's time for a little nicety - stopping splash noises. The splash noise occurs when the pegasus crosses a water boundary, but since the pegasus is an imaginary beast, no noise should occur. To avoid it, we test for water by performing a regular traceline from start to end. If trace_inwater i set, then we add 1000 to the height of the trace_start and trace_end, then subtract 1000 from the mins and maxs of the bounding box(thus the box remains in the correct place. Although you could construct a map where a splash would still occur, I think it's unlikely to arise in actual maps.

Photo finish
And that's it. I'm sure I can hear you saying "That's all very well in theory Preach, but it sounds like a bitch to actually implement!" Fear not, for here is a qc file with just such an implementation. In this version, the carrot and pegasus are globally allocated entities, which reduces the overhead of spawning them each time you want to use the function. This could be changed if entities are at more of a premium than function cost.
http://www.btinternet.com/~chapterhonour/tracebox.qc
As a final warning, remember that the trace results are invalid if the tracebox starts outside of the level. When determining this, you have to account for the 3 hull sizes which quake supports. Work out which hull the tracebox fits to, and fit THAT inside the level. This almost always means that you need a player sized space! 
Bloody Hell 
(You missed a trick with the post icon, btw...)

All we need now is tracetoss, and we have a much more dangerous AI waiting to happen for several monsters... 
 
you could try to approximate a toss path with a while loop. maybe in just 25% increments as you don't need a ton of precision. 
Adapting For AI 
You can use a similar, but much simpler trick for use with a monster, which would allow it to predict if it can navigate to a certain spot in the future. You again spawn an entity, and we'll call it the pegasus here for ease of comparison. Give the pegasus the same movetype, size and origin as the monster, and make the owner of pegasus the monster.

Then just perform some short distance walkmoves with the pegasus - best to do 4-5 each of a distance around the average walk speed of the monster. Then just see if they succeed or fail. The easiest way is just to see if the walkmoves return true, but you might instead want to test if the pegasus is within a certain distance of a target spot after each step.

You can also substitute walkmove with movetogoal, which attempts to navigate around obstacles. Then the question you're asking is more "will the monster be able to get near the goal if he is given a second to wander about?". I remember using this when coding the scripted death sequence for the final Travail boss, to ensure he could actually walk to a spot where the sequence would make sense(and sneakily teleport him if he was stuck!).

You can actually do this without the need for a proxy entity like the pegasus. Just save the original origin of your monster, and then walkmove it as many times as you need to test whatever it's planning. Once you've decided what the best navigational plan is, reset the monster's origin back to where it started.

(If I have the time tonight, I'll do a little post about making ogres shoot at angles without cheating by changing the overall velocity of the grenades. I'll also put tracetoss for grenades into that.) 
 
I was more thinking for fiends, so that they won't jump at you if they can't reach you. 
Ok, Some Thoughts 
The way a projectile moves in quake can be described by the increment in it's position and velocity per frame.

1. new_velocity = old_velocity + frametime * '0 0 -800'(assuming that sv_gravity is still 800).

2. new_position = old_position + frametime * new_velocity

(Maths people may recognise this as the Euler method - it's applied to each section separately though)


So if you want to trace a path up until the first contact with something, then you just need something that iterates traceline in this fashion until one collides. Here's me writing a qc function straight onto func:

void tracetoss(vector posa, vector vel, entity ignore, float nomonsters, float inc)
{
local vector posb;
local float startz;
if(inc <= 0)
inc = frametime;
startz = posa_z;
//cut off if it falls too far, like out of level
while(startz - posa_z < 1024)
{
vel = vel + inc * '0 0 -800';//lazy way to do gravity
posb = posa + vel * inc;
traceline(posa, posb, nomonsters, ignore);
if(trace_fraction != 1)
return;

vel = vel + inc * '0 0 -800';
posa = posb + vel * inc;
traceline(posb, posa, nomonsters, ignore);
if(trace_fraction != 1)
return;

}

}


Notice that you can specify the increment you want to use, with the default being the current frametime. Also, the duplicated code inside the loop is somewhere between double buffering and loop unrolling, and is solely for optimizing what could be an intensive loop. The idea is to look at trace_endpos to find where you hit. The maximum height could be made a function parameter, I was trying to keep the function simple.

Similarly, the proper way to do the gravity would be
local vector g;
g = '0 0 -1' * cvar("sv_gravity");

OUTSIDE OF THE LOOP
To make this simulate grenades best, use nomonsters = 2, this makes the trace more generous with collisions in the same way that flymissile does.


"But I didn't want grenades!" I hear you cry. What can we do about fiends? Well, you need to do something similar to this, but using tracebox. Now, the first thing I would recommend is not to just call tracebox as a function, because that might just cause you to exceed the runaway loop counter. Instead you should duplicate the qc-side tracebox code, and incorporate this new loop into that, so that you're only setting the size of the pegasus once, letting it maintain it's origin from one step to the next etc...

The other trick that I would recommend is to pick the time increment you use very carefully. In fact, I'd recommend that you pick the time increment so that at every step the z_difference you require is exactly 8 units, so that it can be done in a single call to walkmove. You have to swap the order that you do things in for that to work:

FIRST trace the new position based on the old velocity(using the old velocity to calculate the timestep)

THEN update the old velocity with gravity based on that timestep.

So the timestep you seek is abs(8 / old_velocity_z). Check for vel_z = 0 if you like. One final thing to remember is that when the sign of old_velocity_z changes from positive to negative (if it does) then you need to move the carrot from being waaaay above the pegasus to waaaay below it!


Now, here comes the gotcha. What do you do once you've performed the trace? If you hit something, you somehow need to decide whether that was the player or the world, and qc-tracebox can't do that (it's hard being a quake monster and therefore entirely blind, isn't it?). You also have to remember your ending position doesn't include the last step of the trace, as that one failed! The best suggestion I can think of right now is:

* Once you have your end position where you hit something, work out how far the player is from you ignoring the z position

* Try to tracebox horizontally towards the player to end up 64 units away from them (using the distance just calculated), again ignoring the z axis.

* Once that tracebox is ended, check if you're within, say 128 units. If so then the jump probably hits. Otherwise it probably misses.

Some of those numbers may need tweaking. I was basing it on the maximum seperation between a touching fiend and player being ~64 units (corner to corner ignoring z axis). Again, you want to trace as close as you can get, without actually colliding with the player, because then the trace fails - like going bust in blackjack. You could also split the horizontal trace into a few smaller steps, which might protect you from going bust.

And I totally ran out of time(and characters) to do anything about ogre aiming. Maybe tomorrow... 
Gremlin 
I was trying to add a gremlin to the standard qcc and of course I got a lot of errors.
When I finally had cleaned them up I started the game and reached:

progs.dat system vars have been modified.
progsdefs.h is out of date.


It might sound familiar, but is there a solution? 
Defs.qc 
Check the changes you made to defs.qc, you can't add new fields to that file until all of the system fields have been created. 
Typically 
It means you've added new stuff too high up - put your changes at the bottom of defs. 
Confirmed 
I added four strings to the defs.qc as they were the errors I recived after compiling.

float visible_distance;
.float gorging;
.float stoleweapon;
.entity lastvictim;


How can I make addittions to the defs.qc , or should I delete all functions in grem.qc that work with doe.qc 
Fixable 
Like ijed said, just move those lines right to the bottom of defs.qc, and you should be fine. 
Yes! 
that worked.
You earned your pronounciationmark back Ij!ed.

Alhough I don't see it steal my gun, it works fine. 
Hit That One 
Alot of times. When you're learning blind a molehill is everest. 
 
Gremlin 
Well I trried including a Gremlin in my map without the whole SOA pak. And as I expected was the hipgrem.qc not enough. I had to make a change to the ai.qc and defs.qc as well.
When I was done and could compile without errors the gremlin came in game.

But for some reason the weapon steal trick doesn't seem to go. I did all I thought I need to do changing the needed hipsdef into the normal def.qc but something slipped away. 
Substitute 
it was neg!ke with his pronouncion mark. 
Well 
i guess its a dubious question asking where the gremlin has left my weapon. 
Bit Masks 
i want to be sure i understand these:

Operations:

self.flags = self.flags - (self.flags & FL_ONGROUND);
this will subtract FL_ONGROUND but ONLY if FL_ONGROUND is present in self.flags.

whereas:
self.flags = self.flags - FL_SWIM;
would just blindly subtract the flag and risk breaking self.flags if FL_SWIM wasn't there when you subtracted.

likewise:

self.flags = self.flags | FL_ONGROUND;
would add FL_ONGROUND but only if FL_ONGROUND wasn't present in self.flags.

whereas:
self.flags = self.flags + FL_SWIM;
would add the flag as well, but would break if FL_SWIM was already present in self.flags.


Conditionals:

if (self.flags & FL_ONGROUND)
is the only way to check if FL_ONGROUND is present in self.flags. 
Correct 
But the safe versions are strongly preferred, because they don't break anything.

Note that you can work with multiple bits if you need to. The code for picking up armor removes all 3 armor flags before adding the correct one.

The only operation I'm not sure how to do is to toggle a flag (if off, set it; if on, clear it). 
Toggle 
The following code will toggle flags:

self.flags = (self.flags | FL_ONGROUND) - (self.flags & FL_ONGROUND);

The right hand side features two halves. In the case that FL_ONGROUND is already set, the first half does nothing, and the second half is equal to FL_ONGROUND, so the flag gets removed.

In the case that FL_ONGROUND is not set, the first half turns it on, and the second half is equal to zero, so has no effect.

There's a nice kind of symmetry going on with this formula. It combines the adding and subtracting flags, but in such a way that only one actually does anything in each case. The whole right hand side is evaluated before the result is assigned to the left hand side, you there is no risk that self.flags changes mid way through.

It's worth knowing that this can be extended to multiple flags:

float IT_TOP3WEAPONS = IT_GRENADE_LAUNCHER | IT_ROCKET_LAUNCHER | IT_LIGHTNING;
self.items = (self.items | IT_TOP3WEAPONS) - (self.items & IT_TOP3WEAPONS);

This code will toggle the most powerful weapons in the player's inventory correctly, regardless of which ones they may possess. In practice, it would be worth following up that line with a call to W_BestWeapon(), in case the player was using one of the weapons you just toggled. 
Thanks 
didn't know about the toggle one. 
That Sound Bug 
You know, the one where you pick up 2 items more-or-less simultaneously, and hear only 1 sound. I was thinking of fixing it engine-side, but then I realized this: often, 1 sound overriding another is the desired behavior.

I know of the null.wav being used to kill a playing sound, but I suspect there are other situations. Can you guys give me some examples? 
Upon Further Consideration... 
It probably makes more sense to look at it from the opposite side, ie. when don't you want one sound to override another?

So, picking up multiple, different items; using a key which causes a door to open; what else? 
There's Also The Classic 
"Quad Cancel" sound bug, where you land just after picking up the quad, and the "oof" overrides the quad pickup sound. 
 
Picking up the MH at DM4 with no sound (picking up the rockets to achieve that) is a deathmatch tactic.

I am all for it anyways. 
CHAN_VOICE 
It makes sense that anything a monster/player says overrides what they were previously saying - for example a pain sound interrupting some other noise.

If people wanted multiple pickups to sound, the fix is easy to perform in QC. Just remove the channel specification from the sound command - if set to 0, the sound plays from any available channel. 
Revised Ruleset 
The DM angle is something I hadn't thought about, so I probably should just apply the fix to sp/coop. I agree that changing the QC is the "proper" way to do it, but an engine workaround has the advantage of not requiring any effort from the user(*).

How about only applying the fix to CHAN_ITEM and the powerups on CHAN_VOICE? Or is there a case where you'd want one of these sfx to be stopped before completion? (I'll probably include a check for null.wav, which would kill all sounds on the channel)


*assuming I do eventually release this, and anyone actually uses it 
Say No 
to cheap hacks. :( 
No Cheap Hacks?! 
Quake as we know it wouldn't exist without them - interpolation, fullbrights, external textures, skyboxes, fog, extended limits, modified protocols, plus a good chunk of the id & hipnotic code.

It's a good philosophy to keep in mind, but it's never a black-and-white issue. The reality is that all code makes assumptions about the environment in which it's run. And making changes to an existing codebase is never as clean as it would be were the features part of the original design. Sometimes you have to bend the rules to get the result you want. And in the end, if it works, people are willing to overlook the messiness of the implementation.

So I take it personally when someone dismisses my attempt to fix a known bug as a "cheap hack". If you've got any particular concerns or informed criticism, I'd like to hear them. Otherwise, don't bother.

And to those who provided useful input, thank you :) 
 
except it is a cheap hack. it will cause an inconsistency in how channels work for a specific few cases which can cause confusion and annoyance later down the line for some poor bastard modder who isn't aware of one guy's attempt to 'fix' behaviour that was working as intended. a sound is expected to override the previous sound playing on a channel.

if it bothers you, fix it in qc (channels 5, 6 and 7 on the player are rarely, if never(?) used-- they could easily be used for a second item channel) because it's a qc bug. you can even play the pickup sounds on the items themselves, although the left/right won't be balanced because the sound isn't emanating from the player, but that solution is probably the most easiest to implement. 
Thank You 
That made a far better case for your point than your previous post ;)

I guess my frustration wasn't really due to you calling it a cheap hack (because I'm not disputing that); it was more the feeling that you were dismissing it outright. The truth is I respect you for all you've contributed to the Quake community, so it's people like you I need to hear from to help me see things from a mapper/modder view. So thanks for the followup.

For me, the annoying thing with a bug like this is, here we are, 13 years later, and the QC hasn't been fixed (afaik; maybe you guys did in Quoth, but that would still leave a few hundred mods that are potentially affected, plus the thousands of maps that people don't run under Quoth).

One part of your post I didn't quite get was the "play the pickup sounds on the items themselves". Were you talking about reworking the QC to call sound() in an item-specific touch function rather than the generic one? Or were you talking about the engine making use of the .noise field? 
In Any Case 
I'm not actually convinced that it is a bug, because they added the idea of specifying a channel to qc specifically so that the sounds could be overriden. Perhaps a few sounds should be split off into their own channels, like the landing sound and the item pickup playing seperately. But I can see the sense of not playing multiple "item pickup" sounds on top of each other, because it would create a pretty nasty echo effect. The current system of cutting off and resetting the sound on the same channel is probably easier to parse when you listen. 
 
sound(other, CHAN_ITEM, self.noise, 1, ATTN_NORM); from health_touch()

it plays the sound on 'other' which in this case, is the player who touched it.

if you change this (and the other items) to play the sound on 'self' instead, multiple pickups will all play sounds of the item itself, not the player.

the only problem is that if you pick up items from the side, the sound will not be centered like it is when you play sounds on the player. sounds that the player makes are always centered (they come out of the left and right channels equally).

and no, i didn't fix it in quoth (and i don't think preach did, because i don't remember noticing it when i played quoth2 stuff).

this is really a preference thing, but it never really stood out as something that really needed fixing to me. i never even noticed that it would be a problem because i always took it as a matter of course that multiple items being picked up at once results in blocking some sounds out. it's either that or, as preach mentioned, a cacophony of different pickups all at once which is just as difficult to make out.

also, be wary of using CHAN_AUTO (channel 0) because the engine just picks whatever free channel it can find. that can be the weapon channel sometimes so you'll be in the same spot with say your shotgun blocking out the quad pickup sounds now instead of the nail box. :S

this is just my opinion but i think bringing in cool stuff from more modern engines like doom3 such as proper scripting, proper rotating brushes (the rotating entity itself causes collision without needing to hack in invisible collision brushes) and hierarchical entity binding, all done engine side would be completely bad ass. you will notice i'm am avoiding things like real time lighting, bump mapping and such. to me, as a mapper, i'm less interested in those things than i am with stuff that can increase the creativity of the maps being created. 
Damn Real Life Always Interrupting... 
Anyway, I did look into the rotation stuff a bit. Would the Hexen II code be good enough? Very little change on the engine side, but the collision is quite rough (it just expands the bbox so it's big enough to contain the entity at any angle).

Regardless of the method, the tricky part might be deciding when the enhanced code should be used. Maybe a new SOLID_ or MOVETYPE_ constant? Also, there'd have to be a way to check for engine support via QC, probably via the checkextension system (just checked - DP's DP_SV_ROTATINGBMODEL extension may be the one).

The other features you mentioned sound intriguing, but right now I'm really trying to resist the urge to add new stuff, and just finish what's there (not nearly as much fun...). I'll keep it in mind for the future though.

And you don't need to worry about me adding visual fluff - my GL skills are at about a 1997 level :). Plus, I like my Quake to look like Quake, dammit! 
 
mostly the reason i suggested that stuff was because i've yet to see it done so far.

once i got into creating things, i always felt the real impressive thing about doom3 was the script engine but i imagine it's probably many times more difficult to create something like that because it means creating a compiler and interpreting as well as making syntax or whatever that's intelligent. 
Although... 
quake had quakec, which required a syntax, a compiler, and an interpreter, too :) 
Well 
the big difference here is that it's integrated into the engine and that a map doesn't need to be a mod to implement quite a range of custom scripted events.

but implementing it in a custom engine when no one else has done it (custom engine modifications for scripts) is sort of self defeating because although you may not need a mod to run it, now you need the engine. :S

i should have thought it through before mentioning it, hehe. :P 
Scripting 
Thinking about scripting and metlslime's post reminded me of an idea I posted to the Quoth 2 thread (post 347):

http://www.celephais.net/board/view_thread.php?id=60173&start=347

The examples I gave were silly one-step things, but what I envisioned was a chain of these "operation entities" used to perform a sequence of actions; in essence, a script!

Maybe add some conditional operations (if equal, if greater, etc.), and you'd have some rudimentary scripting ability. 
 
purely theoretical discussion at this point but:

what you're describing is essentially what any modder does every time they compile a progs.dat.
stuff like, for example in hipnotic with the sound playing entities or the lightning shooters.

scripting in doom3 renders all those things obsolete. you have your rudimentary entities like func_doors and trigger_multiples for stuff you reuse all the time, but if you wanted to make a lightning trap, you don't need to make a whole new entity.

it's maybe not a big distinction, but i never liked the huge amount of scripting 'entities' that you get in say, hl2. it's many times easier to plan and work on a complex scripted event when you have simple lines of code in front of you instead of 5 trigger relays and half a dozen doors and plats all connected together.

but as i think on it, i feel i'm probably in the minority here. a lot of new guys on doom3world never even touch scripting because it has a steep learning curve. 
 
necros

We evolved the UnrealEngine to use a visual scripting system, Kismet, because we were tired of trying to string together triggers and events for complicated stuff. It really is an archaic way to go these days and makes debugging and absolute nightmare. 
I Never Did Much In D3 
but the scripting did seem like the most interesting new thing to me as well 
REVIVE!!!!!!!!!! 
*godly chorus sings*

i r wins 
 
i see how a visual language makes debugging much easier :) 
Walkmove Returns 
So occasionally the navigation of quake monsters is inadequate. Although they walk entirely blind, feeling their way along walls, usually they get blown to pieces too fast for the player to even care. As people who have read through the AI Cafe tutorials will know, the monsters can either walkmove() or movetogoal(). The latter function will hug walls and attempt to navigate a bit if an obstacle is hit. This does take a bit of control of the navigation away from you.

Walkmove is more of a direct command, to move in a direction, to a distance. When a monster is blocked while trying to walkmove, it is worth knowing two things:
1. The monster does not move at all, walkmove is all or nothing.
2. The walkmove function returns FALSE, instead of TRUE.
The return value of the function would be very handy, as if it returns false, your monster would know that it is blocked, and perhaps make a decision based on that (to try and jump, or hide, or strafe from side to side maybe).

The trap here is to go and write a function which replaces ai_run, the usual function which instructs a monster to move towards their enemy. The problem being that ai_run does a lot of other important things for a monster - checking that the enemy is dead, or whether they should start attacking, and so on. You might end up copying the entire function apart from the last line, which you change to the new walkmove code (and reaction to it returning FALSE).

Then if you change ai_run in the future, you need to remember to change your copy of it too. And duplicating code is pretty wasteful too. You might try and refactor ai_run to let you choose the navigation after, but doing that is a lot of fuss.

So a fairly neat solution came to me yesterday, which is why I wrote this whole thing up. Just write a basic function which will move in the correct direction, check the return value, and react if you are stuck. It does not need to replicate the other functions of ai_run(). Then the key trick is to call it from only one of the running frames of your monster. The rest of the frames should all call ai_run() like usual. Every 6 or 8 frames your monster thinks about something else, and the rest of the time it's business as usual.

If you really wanted, you could call ai_run() and your new function from the same frame, splitting the distance to travel between them. If so, think carefully about which function you want to override which. If you would prefer for your monster to attack as normal, put the call to ai_run() last, and vice-versa.

Okay, all told. 
Interesting... 
I ran into this exact situation last night. My solution was to call ai_run(0) every frame, and then call my_walkmove() every frame to do the actual movement. 
Heh 
Glad to see I'm at least thinking about problems people care about, even if it's too late to be useful : - p 
That 
Gets cogs turning.

Ways to get the fiends more agile. 
Preach: 
there is something maybe you can help with... is there any way to prevent flying enemies from sometimes going inside solid walls? 
It's A Real Mystery 
If someone could reliably reproduce it, with a testmap and a 20% or so success rate, then it would be helpful. I'm sure it's just a check that isn't done carefully enough - and it should be really easy to spot because of the isolated nature of the code for flyers. It is something that I've wanted to crack, but I don't know yet... 
I Think 
Its to do with navigation by point as opposed to bbox - but flyers and swimmers aren't stuck to the floor in order to move.

Points to a coding can of worms though, if it is that. 
Preach... 
i might, i'm currently testing a flying monster in a room with a large crate in the middle. There was at least one test session where they consistently worked themselves inside the crate, while testing on nightmare mode.

This monster has a custom move function which calls walkmove() and if that returns false, calls movetogoal(). In order to control their vertical movement, I give them a self.enemy that is either 1000 units above them, or 1000 units below them (otherwise they will always seek the same horizontal plane as the player and stay there, which i don't think is very interesting for a flying opponent.)

Anyway, if i can get a reproducible case, I'll let you know. 
 
it's not possible to detect if the player is pressing movement buttons is it?

something that would be true if he wasn't pushing any buttons but he was sliding down a slope, for example. 
 
i may not need to worry about this after all, i just found out the player's velocity is considered 0 when standing on a platform or whatever and it's moving you. 
Chasing 
Is this is the for the same mod where you wanted to create a chasecam? If so, the usual trick is to proxy the player. To do this the actual player entity an invisible movetype_noclip entity, and in playerpostthink, keep resetting the origin to that of the camera entity(to prevent visibility problems). Then through reading the offsets of this dummy player, you should be able to deduce the key presses.

This assumes that you have an entity set up as the chasecam viewpoint, and that you're willing to make a 3rd entity which serves as the visible player. But that is usually acceptable for the kind of mod where you'd want to read the inputs. 
Correction 
To do this make the actual player entity an invisible movetype_noclip entity... 
 
that sounds interesting, but quite ugly. :P
the only reason i asked was because i was worried that when a player was on a lift it would count as if they are moving, if i checked self.velocity, but as it turned out, if a player is standing on something that's moving, his velocity is 0, so it was all good. :) 
There Is 
Kascam - AguirRe was experimenting alot with this. It basically spawns a fake client who goes into a kind of auto spectator mode, either chasecamming or snapping to interesting points from which to watch from a la Resident Evil.

Unplayable from these views, so probably not what you want. 
Special Characters 
preach, how did you do the progress bar in quoth 2 for the flashlight? 
Character Modification 
The bar was made up of 4 characters drawn onto CONCHARS in gfx.wad. The characters we replaced were 4 of the box border characters which are repeated half way down the CONCHARS image. It seems like the engine is consistent in using only the upper row copies.

To add them to a string, the qc used escape characters. FTEQCC (and frikqcc I think) supports specifying a character by number, using the format "/{137}" for character 137. From this, 9 preset strings were created, one for each stage of the progress bar.

The hacky part was getting centerprint to behave exactly as it would for normal messages(so that they would last for 2 seconds regardless of whether the flashlight got toggled during the message). For that, we needed two fields on the player, a float for storing the expiry time of the current message, and a string to store the centerprint message. A global float called centerprintcount was also added.

The centerprint builtin was wrapped to set these two fields to (time + 2) and the string it was sent respectively. It then set the centerprintcount variable to 2. It did no actual centerprinting itself. Instead in playerpostthink the function decided if the centerprint message needed to be changed, asking:

� Has the flashlight been turned on or off?
� Has the charge decreased since last frame?
� Has it been more than 1.8 seconds since we refreshed the flashlight?
� Is centerprintcount greater than zero?
� Has the centerprint time expired for the player's message?

If the last condition was true, the player's centerprint message was changed to "". Then if any of these conditions are true, a new centerprint is sent. It would take advantage of the fact that calling the builtin centerprint with two strings will see them printed one after another(in fact it can be overloaded with up to 8 strings, the maximum number of parameters a quake function can carry). The correct string for the flashlight(including no string if it has turned off) would be retrieved and set along with it.

The last detail is that centerprintcount is decreased by 1 in startframe. This works to ensure that every client will get centerprint messages updated correctly. There is actually a bit of oversend when it comes to sending these messages - when ANY client gets a centerprint, everyone gets theirs updated. Similarly if the centerprint is triggered in a playerprethink or player physics event it will get re-sent in the next frame. But this only raises additional network traffic on a few frames, the important thing is to avoid spamming the message every frame.


An alternative method would be to build a centerprint message byte by byte, the way that temporary entities for lightning or gunfire are created. Set msg_entity to the player, send an SVC_BYTE(MSG_ONE, SVC_CENTERPRINT) - SVC_CENTERPRINT can be looked up in the source. Then send the bytes corresponding to the characters making up the progress bar, followed by a SVC_STRING of the centerprint message.

Advantage: you can pick the characters to send procedurally, avoiding the hard coded strings. If you added more characters to your set, you could have sub-character progress marks.

Disadvantage: you can only send one string, because it is null terminated, which ends the centerprint. Although the quoth method I described only supports one string per centerprint, it is possible to see how it could be expanded by adding more centerprint string storage to each player, and sending all the strings. 
 
impressive, thanks for the info :)
wouldn't it have been easier to assemble the string with code instead of making presets?
like:
a = "["
b = "="
c = "-"
d = "]"
then just doing string = a + b + b + c + d? or does that not work in qc? i've never worked with strings much in qc. 
Append 
just got a chance to check and i realised that string manip isn't possible in qc :P 
String Manip 
That's why you need the trick which lets you write bytes, it's heavily practised in Prydon Gate with all those text menus. frikqcc introduced a handy addition as I recall, making it so that a single quoted character whould be translated to the numeric byte value you need for writebyte. So if you had a function

print4(float a, float b, float c, float d)

which prints the bytes a,b,c and d, you could call it as

print4('n','a','i','l');

which makes the code a bit more readable.

Now I'm gonna go away and think about the best way to formalise faked strings like that... 
 
i've got an interesting problem...

ftos(). a great feature about this stupid thing is that it seems to store the converted string into the same place in memory, so if you use the centerprint trick that concatenates strings, and you were to put multiple ftos() into it, it would print only the last ftos() that was called.

to get around this, i tried making a bunch of temp strings, and then setting each of these temp strings with ftos() before calling the centerprint, but that doesn't work because, it seems, the temp strings are only a pointer to the memory location that ftos() is using, so the end result is absolutely the same.

is there anything i can do? 
Depends 
What's the numbers that you need to centerprint?

If it's just 2 numbers that are a few digits long then you can convert one of them to strings that are a digit long and then print the other one after it.

Example here (with the functions DigitToChar and NumToString, you may want to use the search function as they're near the bottom of a long file): http://svn.quakedev.com/viewvc.cgi/rquake/trunk/source/rjs.qc?revision=68&view=markup 
 
Except that instead of strcatting the digit strings together, you print them one by one.

Please excuse the evile QCCXness that that code had back then...

(We need a barf icon...) 
Stream Of Conciousness 
When it comes to functions like dprint and sprint, the usual trick is to call the print function after each ftos call, to flush the buffered string into the console, eg:

dprint("health: ");
s = ftos(self.health)
dprint(s);
dprint(", height:");
s = ftos(self.origin_z)
dprint(s);
dprint("\n");

This works fine with prints to the console, as the messages are cumulative, written one after the next. The problem with centerprint is that each call flushes whatever was previously printed, so you need to get everything into one message.


This of course leads us down the road of byte by byte messages, where you construct a function which can convert a float to a sequence of characters, which are then sent by SVC_BYTE. So it's possible, just not pleasant.

I've been trying to think of a way to write a "library" which would make writing this kind of centerprint byte by byte more straightforward. I think the best structure would be:

� A buffer of 16(?) floats, enough to store one line-width of a centerprint message
� A function called Flush() which sends all 16 characters in the buffer with SVC_BYTE.
� The concept of a function object called a stream.
� Customisable functions can then be written which read values from streams into the line buffer.

It would be at the last level that layout could be controlled by the coder - deciding what to do if a stream is longer than the current line, whether you need to render a border on the first and last character, etc. The library would come with some examples.

The important idea is the stream. This would be a dummy object with .think set. What you set think to depends on the content of the stream, but the simplest example of a constant string would look very much like a monster animation function. For example, the sequence "hello, world" would begin:

helloworld_1 = ['h', helloworld_2 ] {};
helloworld_2 = ['e', helloworld_3 ] {};
helloworld_3 = ['l', helloworld_4 ] {};


Then reading a character from the stream self is performed by the lines

self.think();
char = self.frame;

(you need to make whatever is thinking self, that's the normal quake rules)

The advantage of this method is that then you can invent a new function which, for example, streams the digits of a float to some precision. As long as you make the interface the same - use .think() to advance the stream a character and .frame to access the current character - then the higher level functions can handle it identically.

It would probably be helpful to add one property to the stream entity: length. That way, the highest level of function can see if a stream will fit on the current line, and if not then consider moving it to the next line. It would also be easy to wrap streams around lines, simply output as much as will fit the current line, flush, then pass the partially completed stream to the next line.

You can also imagine a stream modifier, an entity which could when queried would read a second stream entity, and then either pass on the character it read, or skip that character and go to the next one - stripping out white space perhaps. 
And One More Thing 
If you only need three values, and it's ok to print them out one after another, you could use vtos() on a specially constructed vector, with the three values set to _x, _y and _z of the function. A little easier than overengineering stringstream for quake... 
Wait... What? 
two questions,

1. is the engine hard-coded to give players the axe and shotgun when they first load up a map?

2. (and this is the weirder one) if parm1-16 are global variables, how is it in COOP with more than 1 player, they can retain items and such. are parms special variables that have extra copies for each player? how does the engine know which player's parms we're talking about then? 
 
scratch the first question, i did something dumb which made it seem that way. 
A Parm And A Weave 
The engine stored parms for each player internally. I believe the way it works is that the QC globals parm1-16 are set to the values the engine saved just before it calls PutClientInServer() for that player. So the parms are only valid to read in coop for the duration of that function (and any functions it calls). Otherwise you will probably be reading the parms of the last client on the list.

If you're removing the axe from the player, make sure you handle the case where he runs out of ammo with all weapons - in the standard code it will switch to axe without checking if you have one. 
 
great, thanks for the info. :) 
 
this one's more of a math problem...

how can i align monsters with the ground plane underneath their bodies? is it even possible? vectoangles only ever sets x and y, never z, so a full parallel alignment seems impossible. 
Something Along The Lines Of 
Trace directly downwards, and compare trace_plane_normal to the vertical, then derive the angles needed from that.

You probably need 2 calls to vectoangles, with things swapping around between calls. 
Algorithm 
This is roughly what I'd do, not properly converted into qc:

//yaw is the desired facing of the monster
mapAnglesToFloor(entity mon, float yaw) =
{
//do the trace and exit early in easy cases
traceline down
if(trace_fraction == 1 || trace_plane_normal == '0 0 1')
�return '0 yaw 0'

//construct a vector perpendicular to both the desired facing of the monster and the normal from the ground, by using v_left
makevectors('0 yaw 0');

//get the actual facing out vector using the cross product
facingvec = crossproduct(v_right, trace_plane_normal);

return vectoangles(facingvec);
}


I'm not sure it actually addresses your concerns about ang_z not being set though. It is also possible that I have the handedness of the coordinate system wrong, and so you need -1*v_right for it to work.

You also might want to consider interpolation of some sort so that the monster doesn't go crazy on broken ground or trisoup terrain. In that case, it is probably best to have a field storing the old "normal", then calculate a new one with

normal = normalise(normal + trace_plane_normal);

You could scale one of the vectors to cause slower or faster interpolation. By interpolating the normal vector, you can be sure that the changes in facing by the monster are responded to directly. 
So 
I've got a point entity called a func_door_model. The idea is for the mapper to specify a .bso model in there and circumnavigate a load of issues - breaking max models, patchy lighting, messing around with texture alignment etc.

It seems to work pretty well, the whole idea is to later on extend it to other entities like trains, breakables and so on.

The first problem (of many) is that doors created this way aren't generating their trigger field.

What I have is a 'wrapper' piece of code that specifies a .mdl and replaces the model field with that value - this is a an engine fix for DP that I imported from elsewhere.

As I understand it:

cmins = self.mins;
cmaxs = self.maxs;

and

self.owner.trigger_field = spawn_field(cmins, cmaxs);

Are what create the trigger field, but the first one isn't working when an external .bsp is referenced.

I can touch the door and fire it from a trigger, so the functionality is intact apart from the trigger.

Any ideas? 
Relativity 
If you placed your func_door_model at the origin, then I expect that the trigger field would work perfectly. If you enjoy a challenge then work from that hint and ignore the rest of the post...

Otherwise, I'm hoping that the following is the fix to your problem: The assumption that the trigger field works code works on is that the entity is placed on the origin of the map. This is always true for baked-in models like a standard func_door.

For example, if you built a 64x64x64 func_door with a corner closest to the origin at '512 512 0', then door.mins = '512 512 0', door.maxs = '576 576 64' and door.origin = '0 0 0'. It's a bit strange to think about at first, because regular entities like players or monsters tend to have the origin half way between the mins and maxs. (*)

Luckily, this makes the fix very simple, and backwards compatible with a regular func_door.

cmins = self.mins + self.origin;
cmaxs = self.maxs + self.origin;

This should work with regular .mdl files too, although you'll run into another problem with them which is much harder to work around. You could also try swapping self.mins + self.origin with self.absmin, not sure if it's any better for compatibility with dp though.

(*) There is an uncommon exception to this rule, found in rotating entities. Since models can only rotate about a single axis - the origin - the bsp compiler has to play some games with them. It finds the origin of the info_rotate for the model, then moves the brushes of the model so that the origin of the map lines up with that spot.

Once it has compiled that model, it sets the origin value of the entity with the model to equal the origin of the info_rotate - thereby reversing the movement and restoring the original location of the entity. Of course, the lighting and texture alignment are likely shot to hell, but who cares! 
Hm 
You're the man.

Challenge is good but the first paragraph was a bit cryptic - I had to read the rest to get the bit about it being the world origin.

Makes perfect sense though, and the added bonus of true .mdl doors is interesting...

I've wondered about why the rotating mesh was moved to the center of the world, but docs there aren't much of.

In any case, this puts me well on the way - also going to try some stuff with trigger_once_bbox working in a similar way, the mapper setting the size of the trigger numerically.

Am I right in thinking you did something similar in Quoth2? 
Just 
Don't tell me how you did if you did - there has to be some challenge :) 
Some Bits 
We had the model-saving bounding boxes on triggers and external bsp format models. We don't have .mdl format doors yet, there's a little wrinkle with solid types which I don't think can be fixed nicely.

We also didn't fix the bug from #320 in quoth yet, although I expect it'll be in the next release... As a workaround, I suppose people will have to add the door trigger manually. 
MOVETYPE_PUSH Not Bsp 
Yeah, got that one. It also seems to do something strange to the bbox - I've seen this before where the size isn't what'd be expected.

I imagine that can be fixed by changing the movetype and putting an invisible helper in there - that's similar to our pushable solution. 
Can Anyone Confirm? 
if i set .nextthink = time + 0.001 (or any very very small number), that should guarantee it will be called on the next frame, right? 
Almost Surely 
Most of the time that will be fine. Most engines enforces a 72 fps limit on physics, because once you get into higher framerates you start to see physics glitches. I assume these arise because of floating-point errors once you start evaluating collisions with increments that small. If you want to see it, try increasing the max_fps in fitzquake to the 300-400 range before riding on a lift (I may have remembered the command wrong, but there is one that lets you change it server side).

One circumstance where you might have a problem is if someone sets host_framerate very low to create a slow motion effect. It's not too much of a concern though, because it is someone messing with console variables, and you can't always prevent people breaking stuff if they use em.

However, there's an even simpler way: set .nextthink = time, or even .nextthink = 0.01.

I used to think that quake ran think functions if the following inequality held

time - frametime < .nextthink <= time

But actually, the left hand inequality does not exist. From the engine source:

�thinktime = ent->v.nextthink;
�if (thinktime <= 0 || thinktime > sv.time + host_frametime)
����return true;
�if (thinktime < sv.time)
����thinktime = sv.time;
�ent->v.nextthink = 0;


The engine resets nextthink to zero every time it calls a think function, and so ignores think functions only if nextthink is in the future or <=0. You should be able to get things to run every frame just by setting nextthink to something <=time.

There's an interesting additional bit of info to be gained from this section of the engine code. We see that the QC value time is set by the following line

�pr_global_struct->time = thinktime;

The previously quoted source code set thinktime from the entity's original .nextthink value. So during the QC think function, time is always reported to be the moment that the entity intended to think, rather than the server time at the end of the currently processing frame. The one caveat is that time is bounded below by sv.time, so if we set self.nextthink = 0.01, we won't suddenly be miles back in the past when think is called.

Some of that explanation might be a bit garbled, I was figuring it out myself as I went. So maybe this timeline will help


We assume that at this time the server is running at 50fps.
sv.time
This is the "old time", the first point in time not processed in the last frame. Time is set to this value for the following things:
StartFrame, think functions for .nextthink <= sv.time.

sv.time + delta
As long as delta < 0.02, then the think for that entity must occur in this frame. Time is set to this value for the following things:
think functions for
sv.time < .nextthink < sv.time + 0.02


sv.time + 0.02
Anything with a think greater or equal to this is ignored, it will happen in the next frame instead.


In conclusion, I'd go with self.nextthink = 0.01, because time will be set to sv.time anyway. I've not tested if there are any side effects of that though. self.nextthink = time should also work and might look less weird. 
Thinking Without Thinking 
Personally, I prefer self.nextthink = time; although feel free to follow it with // Next frame if you want your code to be understood by others.

And note that the code checking for .nextthink being non-zero means that the think function is only run once (unless .nextthink is reset). But setting it to 0 will cause it to stop thinking. Which is what causes the statue bug in id1.

Reading that through has taught me something, though. Namely that time is relative during a think function.

I do have one question, though: What happens first: think or touch? 
 
thanks, preach. as always, very informative!
while you're here, could you tell me if i understand .ltime correctly?

it seems to basically be time, except it only counts up when a bsp model is moving.
i believe it only works when the solid is SOLID_BSP or if the movetype is MOVETYPE_PUSH.
when it stops moving (comes to rest OR is blocked), the timer stops. this is how calcmove can work with a static nextthink even if a door or train gets blocked. 
Oh, Yeah 
I should have mentioned straight off that the rules are different if the entity is MOVETYPE_PUSH. But it's worth looking at, because it also lets us explore how physics timing relates to this new QC-think timing.

You are right about how ltime works, it's "local time" for the MOVETYPE_PUSH entity. It advances at the same rate as the normal clock except if
a) The entity is blocked, in which case time is not advanced
or
b) The entity's .nextthink will occur before .ltime + host_frametime(within this frame) in which case ltime is increased only as far as .nextthink (bounded below by 0)

The latter case is important because when ltime only advances by as much time as it needs to equal nextthink, the physics run on the entity this frame are calculated so that it only travels for this amount of time, rather than for the full length of the frame.

I should add that again, this is only applied to MOVETYPE_PUSH entities. Other entities always move for the entire length of the frame, host_frametime. There is also a strange kind of time travel which can affect these entities. Think functions are calculated first, and when they are called the QC variable time might be anywhere between sv.time and sv.time + host_frametime, depending on the exact value of .nextthink. Once the think is resolved they will get moved, but if they collide then the QC time is always set back to sv.time for the .touch functions.

As a final thought, it is worth remembering that entities in quake are processed by the physics engine in sequential order, and setting the QC time variable does not interpolate any entities between their positions at the start and end of the frame. All the entities before the current entity will be at their end of frame position*. All entities afterwards will likewise be in the position they occupied at the end of last frame. Knowing how the QC time variable is set is only of interest to resolve seeming paradoxes where you are sure two events occur in the same frame, but the QC reports different times for them.

* Ok, this might not be their final position, because something might collide with them or teleport them in QC or something. But in terms of their own physics, they are done for the frame, no more moving or thinking. 
Clarification 
b) should really have read:

"The entity's .nextthink is less than .ltime + host_frametime(before the time at the end of the frame) in which case ltime is increased only as far as .nextthink (bounded below by 0) "

This would make it clear that ltime does not advance when nextthink <= ltime. 
Back To Ltime 
is there any reason why ltime would run slower than normal time?
i can't really explain it better than that, other than when i watch both ltime and time displayed next to each other (for example, bprinting both every frame), ltime counts up at a slower rate. 
Imprecision 
Only thing I can see which might account for it is that sv.time and host_frametime are both double-precision floats. Since ltime is stored in a QC field it only retains the precision of a regular float. In fact, the increment gets cast to a single-precision float before it's added to the single-precision ltime value. So my guess would be that it's a byproduct of the lower level of precision in that calculation. 
 
i tested a bit more and slow frametimes seem to slow it down a lot? o.0
if i set fitzquake's maxfps to 10, it counts extremely slowly. i don't really understand what's going on here. 
Sorry Lardarse 
I do have one question, though: What happens first: think or touch?

I totally missed this question first time round, here goes:

For a player:
PlayerPreThink always comes first.
Next is the .think function (for frame animation etc)
Then comes whatever kind of physics the player has, so if there's a collision .touch happens now
Finally PlayerPostThink is run.

If it's a MOVETYPE_BSP, it moves first (and so any .touch and .blocked calls occur), and then calls .think functions after that*.

MOVETYPE_NONE won't create collisions by itself, so it only runs .think. It's worth considering that a MOVETYPE_NONE can still be involved in collisions, and in that case the .touch may be called before or after the think, depending on whether the colliding entity is before or after this one in the list. The same is true for any entity when they are the second party in the collisions.

MOVETYPE_NOCLIP doesn't generate collsions either, it's just .think when it comes to processing.

MOVETYPE_STEP is for monsters, and they have a weird order. If they're free-falling from a jump, then that gets processed first, and any collision there produces a touch before the think. However, most of the time monsters only move during think functions. One of the two navigation builtins are called in the think, which hands control back to the engine for physics to be run on the "step". If it collides, then the touch gets called on top. So the think will begin before any touch, and finish after the touch!

Finally, all the other "projectile" movetypes run .think before moving, and thereby having a chance to .touch anything.

In conclusion, it's a mess! The entity might always be the "other" entity in a collision, so you can't really say concrete stuff about whether the touch will happen before or after a chance to think. I think the list here is still useful though, for knowing when the physics runs. This means you can always be aware of whether an entity has already moved or not while in a think function.


*There is an argument here for rewriting the hipnotic rotator code here. If you make a function which is called from StartFrame which loops through all the blocker entities and sets velocities for them, you have changed their velocity before physics runs on them, so they'll move into place this frame. The current code sets it in the think, which means they're always lagging behind the target for a frame. You would also be able to set .nextthink to (.ltime + framtime * 0.5), and use a doubled velocity to ensure exact motion.
 
 
a little bit more on SOLID_BSP and .velocity

a SOLID_BSP entity won't move unless it's .nextthink is non-zero. it doesn't matter what it's set to, although, obviously if it's less than ltime, it will be set to 0, just as long as it's set. if you set .velocity without setting .nextthink, no movement occurs (although the entity retains .velocity setting). 
Preach, Re: 332 
preach, could you correct me if i'm wrong?

in post 332, i mention that time seems to more slower on ltime than real time.

say, on your bsp entity, you set:

self.nextthink = self.ltime + 0.01;

to loop a function over and over via .think.

if your framerate was really low, like 10fps. according to what you said above: The entity's .nextthink will occur before .ltime + host_frametime(within this frame) in which case ltime is increased only as far as .nextthink

if time = 0.
one frame goes by at 10fps:

if your nextthink is 0.01, but you are getting 10fps, then .ltime will be set to 0.01 even though real time = 0.1

we get ready for the next frame and set self.nextthink = self.ltime + 0.01; //next frame
.nextthink is 0.02 now.

now more frame at 10fps:

time is 0.2, but .ltime wil only be 0.02.

and so on and so forth.

ltime is only incrementing by 0.01, even though actual time is incrementing by 0.1.

am i getting this right? 
Yup 
Yeah, that's right. Remember it will also only move for 0.01 seconds per frame, so you need to set its velocity carefully if you are relying on velocity for motion. 
 
i made accelerating/decelerating movers but i couldn't find an acceptable way to make them accurate.
from what i have seen, it seems the only way to make it 100% accurate would be to externally set velocity via a helper entity. unfortunately, this would nullify the point of .blocked and ltime as a blocked mover wouldn't pause and would risk becoming out of sync.

as such, i've just left the acceleration with ltime and accepted the inaccuracy. it unfortunately means if you are getting really bad frame rate 10-20fps, you will see a marked increase in time for movers to complete their movements.

otoh, maybe if i accepted a lower precision by setting nextthink to ltime + 0.1 (use slower refreshes), it would decrease the disparity between time and ltime...

i'll have to see how that works out i guess. :S 
Accellerated Progress 
I think that there is a way to overcome these difficulties without a helper entity, so long as you're happy with a bit of not-really-calculus behind the scenes. You can get a version with one frame lag just by using a few entity fields to store some floats(and the one frame lag could be eliminated using the trick mentioned a few posts above of pushing updates to a mover's velocity during startframe, in order to occur before physics).

The key is to increment one of the variables by frametime in every frame which you are blocked. I'm writing out the details in my notebook currently, but it's the kind of thing that would really be best served with an external page full of diagrams and equation notation rather than a hurried post on this board. Perhaps even some genuine, complete QC code to prove I'm not chatting out my arse. Watch this space... 
Lol 
well, i will definitely want to see what you are talking about, but bear in mind i'm not that much of a mathematician, so if it's as complicated as you are implying, i probably won't do it. ^_^;; 
Running Dry 
Hey Preach, did you receive my email?
I'm rather stuck in the monster toppic. 
Hmm 
Send it again, don't think I have it. 
 
I ment the Monster thread.
I'll send it again.

http://www.celephais.net/board/view_thread.php?id=60251&start=396 
 
.huntt_ime
Set to time + something when the player is in sight, but movement straight for
him is blocked. This causes the monster to use wall following code for
movement direction instead of sighting on the player.
(sic)

in ai.qc

is this true? it sounds like a lie. :P 
The Hunt Is Over 
The only instance of "hunt_time" in the qc source is in the comment about ideal_yaw. I'm guessing it's something they used to do in ai_run. It may have been taken out because movetogoal tries the direct path to the enemy before using the wall following code. This would suppose that originally the function would call walkmove if hunt_time wasn't set, set hunt_time if walkmove returned false, and called movetogoal while hunt_time was active. 
 
ah that would make sense.
one thing i noticed about the movetogoal code...
it always seemed to me that doom had much better wall following code. quake monsters often get caught in areas when trying to path to the player, but doom monsters quite often turn up in surprising places especially if you watch them in the automap. quake AI seems to 'give up' wall following very early, usually before the wall following has a chance to get around a particular corner or whatever.
mm, that was random. :P 
Well Then 
we should just see how D00M does it,
and port it to,
(_)uake :D
.| 
Monster Only Clip... 
i wonder if it would be feasible to take the func_togglewall and do this:

rename it to func_monsterclip
make it non-solid
movetogoal -> movetogoal_builtin
and then we make a new movetogoal that loops through all func_monsterclips, makes them solid, called the movetogoal_builtin and then afterwards, makes all the func_monsterclips nonsolid again. 
 
ran a little test.
instead of a generic monsterclip, i created a method to get larger bbox monsters to move correctly.

you essentially build your 'hull3' out of brushes and turn the entire thing into a single func_clipModel, and then you tie that clipModel to the monster you want to run collision with via clipModel->targetname editor key fields.
this could actually work because it won't impede smaller bbox monsters (that can use normal hull1/2 collision) since the clipModel is only every solid during that single monster's walk frame... 
Necros: 
Nice, I'd really like to see some larger monsters or bosses/minibosses (that can actually move) in quake. This could be a piece of that puzzle. 
 
yeah, works pretty decent, but of course it imposes some limitations.

you need to 'clip' any area where the monster will be, of course, and that means you have to visualize the hull expansion yourself and implement it.

also, currently how i do it is to use the same method that hipnotic did for the func_togglewall and that is to just add '8000 8000 8000' to the origin when you want to turn it off, and then subtract the same vector when you want it on.
i don't know how big a deal it is if you had a generic monsterclip entity that EVERY monster in the map would have to toggle back and forth every animation frame. that could be pretty brutal.
it's probably better to somehow localize monster clips so only the monsters most likely to actually touch them will be toggling them (hence why i opted for a clipModel->targetname method instead of just putting it in walkmove and movetogoal). (large bbox monsters use a special wrapper for ai_walk and ai_run). 
Some Problems 
quake seems to use start the hull2 bbox from the bottom left (mins) of the monster.

this means that if you use a bbox of size (for example) '-128 -128 -24' - '128 128 64' only the mins up to '-64 -64 64' is used when checking collision.

i thought that quake would start the hull2 size from the center of the monster, but this is not the case.

this creates a problem now because collision is still messed up.

if we resize the monster to hull2, call movetogoal and resize back to the new hull size, collision against the world (and func_clipModels) is fine, but the monster is now able to walk inside the player and other monsters.

i'll have to put more thought into this, i guess... 
 
Wait, how do shub and chthon work? They have large (stationery) bboxes and players seem to collide against them correctly. 
 
yeah, the collision of other bboxes is fine.
it's the collision against the world that is messed up.

and that's the big problem:
movetogoal will function correctly vs other bboxes if you set the bbox correctly. 256x256x128 or whatever.

movetogoal will function incorrectly vs world when bbox is set to 256x256x128.

if you set bbox to standard hull2 size before movetogoal and reset to 256x256x128 after, monster will move inside player.

what i've done so far is left the bbox at 256x256x128 and simply 'offset' the func_clipModel so that sides that the mins hits are smaller than sides that the maxs hits.
kind of hard to explain, when i figure everything out, i'll probably make a blog post about it with pictures to explain it properly.

also, another interesting (and annoying) side effect: because of the way the standard ai_run code is sandwiched between func_clipModel toggles such that the clipModel is active when ai_run is called, things like the visible() function fail if the player is inside the clipModel since visible uses a traceline to determine if the monster can see it (and since the clipModel is solid during that period, the trace hits the clipModel and determines the player is not visible). 
Append 
another way to look at it is this:

for the purpose of bbox vs world, only the first hull2 coordinates starting at the mins are solid.

that is to say:
if the bbox was mins: -128 -128 -24, maxs: 128 128 64

world collision is done from -128 -128 -24 to -64 -64 64 (mins + VEC_HULL2_SIZE)
because VEC_HULL2_SIZE = 64 64 88 
Oh I See... 
if you set the bbox down to standard hull2 size, it's collision against other entities is wrong. If you leave the bbox alone, its collision box is offset from the correct location.

Two ideas:

1. before moving the oversized entity, make ALL other solid entities (or at least all entities within a findradius) larger by XYZ amount, to compensate.

2. have two entities, one oversize and one normal size, and move them both. If either one is blocked, set both entities to the location of the blocked entity.

Not sure if either of these are completely workable. 
 
1. could work, except it's just (potentially) a lot of entities to enlarge.

2. this is better, but the problem is that if one is blocked, and we reset the position, nothing happens for that frame and likely movetogoal will try the same thing next frame.

currently what i've done is use bboxes on all the func_clipModels. this means each brush needs to be a seperate entity and we can't have sloped/angled faces anymore (since everything is just a box now).
it works and doesn't seem too slow, but we loose a bit of brush flexibility since we can't have any angles any more. of course, you're really just blocking out the area, so this could actually work. i'll leave it this way for now and test it out for now. 
I'm Not Compensating. Really! 
http://necros.quaddicted.com/temp/dragon.jpg

the collision stuff has been working well without any further problems so far.

the really nice thing about it is that for monstrously large monsters like the dragon in that shot where you don't necessarily want the bbox to completely cover the entire model, all you have to do is expand the clipModel entities out further from the actual walls. 
 
Is that the DOE dragon? 
Yeah 
i rerigged him and animated him for actual combat and not just flying around path corners. 
Accelerating Back 
So I've just spent about a month without internet at home, shame I missed all that stuff about large bboxes, because that's a cool idea. If you're doing a landbound monster with a tall box, then you can create maps which can be bbox-blocked with greater ease. Low walls rarely need to be boxed in this case, just obstructions which are above the head height of regular sized entities but low enough for "the boss" to collide with.

Anyway, that's a digression. In my time away, I had lots of time to get on and finish projects. A fair few of them were quake related, and I'm posting the first one now. It's the tutorial I mentioned a dozen posts up about accelerating MOVETYPE_PUSH objects. Since it involves some formulae which I've done up in LaTeX and a few graphs, I've made a web page for it rather than just copy-paste it straight onto func.

Accelerating pushers
Also means I can fix typos and other problems, so post them here! 
 
i haven't really read your above post yet as accelerating movers isn't a pressing issue anymore, but i just wanted to mention: you should compile all your coding tips you've made in this thread and put them up on a site somewhere. some of them are quite useful and others are downright golden. 
No Longer Touching 
I have created a 'trigger' entity. It covers a large portion of the map and instigates certain continuous but randomly timed actions whilst the player is inside the trigger's area. Let's call it an area_trigger.

The events are called by using the trigger's touch function, as in self.touch=do_these_things, so that when the player leaves the area, do_these_things no longer gets called. If he re-enters, the events start again. So far, so good.

I now want to 'enhance' this effect so that when the player leaves the area, a separate single event takes place, and this event takes place each and any time he leaves the area, which could be one or more times throughout the game. This event must not take place at any other time.

Is there a way to read when the player stops 'touching' the trigger so that I can call this exit event. I maybe could set up multiple triggers around the area_trigger and have them switched on by the area_trigger so that the call to the exit event is operated on a one-way basis but I am hoping there is an easier way.

Any views from the coding gurus? 
Not Easily 
A better solution is to have triggers at the entrances to the area. Two in fact, separated a little. The inside one calls the enter function, the outside one calls the exit function. The functions are coded so that they only actually do something on a state change. 
 
actually, it is easy.

on your trigger_area touch function:

self.nextthink = time + 0.1;
self.think = DO_THIS_WHEN_PLAYER_LEAVES;

since touch is called every frame, nextthink will always be set higher than time, so .think will never be called. the minute the player steps out though, and .touch isn't called anymore, nextthink will expire in the next 0.1 seconds and run the .think function.

also, since i believe .touch functions are run first (before .think functions), even if you were getting less than 10 frames per second (such that the next .touch might be AFTER 0.1 seconds) the touch will be run first, thereby resetting nextthink anyway. 
Append 
first: i forgot to mention in your .touch function, remember to store 'other' in self.enemy or somewhere so that your DO_THIS_WHEN_PLAYER_LEAVES function will know how to have as the activator (just add activator = self.enemy;)


if your trigger_area already needs to have a nextthink and think set for whatever reason, just spawn in a relay entity and do the trick on that entity instead:

if (self.owner == world)
{
self.owner = spawn();
self.owner.owner = self;
}

self.owner.nextthink = time + 0.1;
self.owner.think = DO_THIS_WHEN_PLAYER_LEAVES;


then:

void() DO_THIS_WHEN_PLAYER_LEAVES =
{
...........some code here............

self.owner = world; //break link with the relay entity and the trigger

self.nextthink = time + 0.1;
self.think = SUB_Remove; //delay remove
};


we set up .owner so we have an easy way to get access to the trigger_area's .enemy field, target and whatever else might be needed and we manually break the .owner connection when removing the entity because there's like a 2 second delay before entities are removed in quake. 
Crap 
void() DO_THIS_WHEN_PLAYER_LEAVES =
{
...........some code here............

self.owner.owner = world; //break link with the relay entity and the trigger

self.nextthink = time + 0.1;
self.think = SUB_Remove; //delay remove
};


otherwise your only erasing self's owner (the relay entity) and not the .owner belonging to the trigger. sorry. :P 
Not Sure If That Works 
Because when you're in a trigger, I don't think the touch function is called every frame. 
Two Stage 
If that is a problem(it certainly would be if you need to detect monsters)can use force_retouch to help you out there. The simplest way would be to set force_retouch = 2 in the touch function as soon as you've touched the trigger. This would end up polling the heck out of all the triggers in your map while someone touched the middle one, but it would fix that problem.

I think the above is the only way to make the trigger responsive within a single frame (assuming you shrink the nextthink time lots). If you're willing to have your trigger less responsive (a minimum of two frames, but the values we pick here will be 0.2 seconds) then we can end up only using force_retouch once in 0.2 seconds.

We need the trigger_detector to have three states:

STATE_EMPTY: no player inside
STATE_READY: detected a player recently
STATE_POLLING: checking if there is still a player

If a player comes into an empty trigger we go from STATE_EMPTY to STATE_READY and wait for 0.1 seconds. After that time expires we go into STATE_POLLING for 0.1 seconds. If a player touches the trigger within that 0.1 seconds, we go back to STATE_READY, otherwise we go to STATE_EMPTY (and trigger the leaving event).

We don't actually need to explicitly track these states, they are just to understand what is going on. We have a think function called trigger_detect_startpolling along the lines of

self.nextthink = time + 0.1;
self.think = trigger_detect_fire;
force_retouch = 2;

When our .think is trigger_detect_startpolling, we are in STATE_READY. When our think is trigger_detect_fire we are in STATE_POLLING. When we don't have a nextthink in the future, we are in STATE_EMPTY.

Finally to hook all of this up, we need the touch function to set

self.nextthink = time + 0.1;
self.think = trigger_detect_startpolling;

which both moves us from STATE_EMPTY to STATE_READY when the player first touches, and back from STATE_POLLING to STATE_READY when the player retouches.


On another topic, force_retouch has an important effect on touch/think order which I hadn't considered before. When set, players will touch things they are in contact with before their think functions run (and then possibly touch things AGAIN after physics has run). So anyone who was intending to exploit the order that functions run had better be careful.

Also, I'm gonna go see if things really can run touches multiple times in a single frame. If that is the case, then it really will be important to make touch functions idempotent. This is a wonderful term from mathematics for a function which doesn't do anything else when you keep applying it to it's output. For example rint(x) is idempotent - once you get a whole number out, applying rint to that whole number just gives you the same whole number.

I'm using idempotent in a slightly weird sense here, the idea being that one of the parameters to our touch function is the value of "time", the frame that we are in. Most of the original touch functions have if(self.nextthink > time) type guards in place to achieve this, but it's something important to think about if you're writing a trigger which can be touched every frame - does it matter if you trigger it many times a frame? 
 
i don't know why it has to be so complicated, preach... it works fine the way i said. :P no need for force_retouch or anything. 
Monsterous 
It's needed in the case of non-player entities which don't link to the world unless they move. If you were trying to detect a monster, you would need the force_retouch. It is more than what mike asked for though, the simple suffices there... 
Oh Right 
i missed that you were checking for monsters as well. 
Necros & Preach 
Thanks. 
Findradius Vs Find Vs Nextent 
are there any differences in how these three work?

ie: is findradius really just doing
nextent(e)
if (distance of e < dist), add to .chain
or is it faster?

for example, if i did a findradius(org, 64) where i'm checking only a small radius, is it faster than if i findradius(org, 1024) or is it the same speed?

and if smaller radii are faster than larger ones, at what point does it become better to use nextent rather than a large findradius?
i guess that kind of thing would also depend on the total # of entities as well... 
Finding 
ie: is findradius really just doing
nextent(e)
if (distance of e < dist), add to .chain
or is it faster?

It turns out that it does something extra I'd never known about - it skips any entity that's SOLID_NOT(*). Other than that, the algorithm is as you describe, but because it's written in c skipping to the next entity is a single instruction to increment a pointer, etc. So it does run a lot faster than the QC equivalent, but it doesn't do any culling of the entity list based on the bsp tree or anything fancy.

for example, if i did a findradius(org, 64) where i'm checking only a small radius, is it faster than if i findradius(org, 1024) or is it the same speed?

They are the same speed if they contain the same number of entities. Otherwise the cost of adding more things to the chain is incurred, although that's fairly light compared to the rest of the loop.

(*) Also worth noting: the distance is measured to
origin + (mins + max) * 0.5;
not just the origin as you might guess. 
 
It turns out that it does something extra I'd never known about - it skips any entity that's SOLID_NOT

haha yeah, i figured that out the hard way. drove me insane for a while. -_-

Also worth noting: the distance is measured to
origin + (mins + max) * 0.5;
not just the origin as you might guess.


didn't know about this bit though. wouldn't have much of an impact unless you had some kind of weird offset bbox but good to know regardless. it does make getting precise findradius distances annoying though. if i did a findradius from one monster origin looking for other monsters, the find would have been completely accurate if it was going from origins and not bbox centers. oh well. :S 
How Difficult 
is it to find out what map a given savegame file is for?

Can someone post code / relevant savegame spec? :P 
Not Difficult At All 
Information on the map and its entities is stored in the .sav file in plain text format. 
You're Like A Savegame Wizard. 
interesting that savegames store lightstyles though. one would think that's easily gettable from the progs. 
Yeah It's Plain-text Alright, 
but the locations in the files seem to change.

I want to parse it with quakeinjector to enable loading savegames for each map, so I'd need to know how to parse the header.

Host_Loadgame_f() in http://svn.icculus.org/twilight/trunk/darkplaces/host_cmd.c?revision=10262&view=markup
seems to be the right function (darkplaces), but it's quite complicated and I'm not familiar with the quake src. For example I have no idea what COM_ParseToken_Simple(&t, false, false); does ;-) It would probably take me an hour or so to get what's going on there. 
Wait 
is it always on the same line? 
 
interesting that savegames store lightstyles though. one would think that's easily gettable from the progs.

The current string for each style needs to be saved because there's no post-loadgame callback for entities to set the lightstyle strings again. 
Looks Like It's The 20th Line 
save game version, description, 16 parameters, skill and then the bsp name. 
Qc/engine Question 
if a coder specifies a file "tORch.Mdl" would the engine usually look for tORch.Mdl or torch.mdl or what? 
Different Cases? 
From what I can glean from a quick browse through the source:

Models in pak files must match capitalisation exactly or they will not be loaded.

Models in the filesystem depend on the operating system's implementation of fopen in the standard c library. I believe this means that unix type OSs will fail to find the file but DOS and windows will succeed, but I can't find any documentation which confirms this for 'fopen'. So where possible make sure the exact case is used. 
 
i have had problems with upper/lower case before.
i found it best to avoid uppercase altogether.
for example, ne_tower had a bunch of custom sounds.

when i was developing it, i had all the files loose in folders and setting keys like 'noise' 'necros/someSound.wav' worked fine. when i packed everything into a pak file, someSound could not be found, even though the filename hadn't changed. 
Preach 
i know you've posted about this before, but i can't find it again :S

basically, there was a faster way to compare distances without using vlen.

was it something like vec1*vec2 > distance*distance ?? 
Necros: 
if (vec_x * vec_x + vec_y * vec_y + vec_z * vec_z > distance * distance) {
//temp is longer than distance
 
er ...

//vec is longer than distance 
Yup 
It's almost like that. You can compare the length of a vector v to a distance d with:

v * v > d * d (notice that on both sides of the equation we have the same variable twice)

If you're testing the distance between two positions p1 and p2, you need to take the difference in positions first:
v = p2 - p1;
v * v > d * d;

It works exactly as metl says, but v * v is a single QC instruction which computes the dot product he has expanded out. 
Very Cool 
thank you!

when you say it's one instruction, i guess doing it as vec * vec is faster then? 
 
It works exactly as metl says, but v * v is a single QC instruction which computes the dot product he has expanded out.

Ah, good to know. 
Monster_boss Glitch In Progs 1.06? 
On skill 2, Chthon's aim prediction fails if the player moves towards him when he's about to throw a lavaball. The result is that he throws it backwards instead (or possibly towards worldspawn). It doesn't occur on 1.01.
Is this a known issue - why wasn't it fixed? 
 
it's just to do with the math involved to calculate the throwing vector.

because the lavaball moves so slowly (300u/s), if you jump toward chthon, you'd be behind him by the time the projectile would hit you.

i would assume that v1.01 of the progs didn't have chthon's forward projection targetting code. 
Iterative AI And Tracking 
The algorithm is:

1) work out the time it would take to hit the current player position
2) predict where the player will be at that time
3) set the target position to be that spot

There's a logical flaw in this scheme. The time it will take the projectile to reach the new spot will be different to the time it takes to reach the current spot, so there's no guarantee that the new aiming vector will be any better. This would not be significant with a fast projectile, as the two travel times would likely be very similar, and the size of the player's hitbox is a large enough margin of error.

However, the slower the projectile moves the worse the situation gets, compounding the problem necros describes. Moving towards the origin of the shot combines these two problems, and I'll try to give an example of the worst case. The player is moving towards chthon from 600 units away (2 seconds of flight time). We imagine that the player is moving at just over 300 u/s (the player's top speed is somewhere around 400 u/s). This means that in two seconds time, the player would be just behind the knuckle that the rock is thrown from. The projectile is then thrown directly backwards and misses completely.

We realise that this target point is stupid for a few reasons:
� The player will likely not run straight at chthon for two seconds
� More importantly, the player cannot run through the solid body
� Even more importantly, the rock will sail past the target point before even a fraction of a second passes. Even if the player could and did continue exactly to the predicted spot the shot would still miss!

This last problem is something we can fix with iteration! The idea is that we want to calculate a point where the time the rock will take to reach it roughly matches the time the player would take to reach it. If the player is running towards Chthon then this point will be roughly halfway between the two. The iteration is based on
� Taking the current target point
� Calculating the time to strike that
� Calculating a new target point from the predicted position the player would be in at that time
� Feeding the new target point into the top.

In our worst case scenario we described, we'd start with a target point of the player himself. Then we'd get the point right next to the knuckle with a very short flight time, so our third point would be very near to the player, but a bit closer to Chthon than point 1. After a bit of ping-pong of points that are too near to each end, we should work into the middle.

This is quite nice, and I like iteration in AI because you can do one iteration in each animation frame leading up to the shot. It creats an interesting, slightly unpredictable thought process which keeps taking on updates as the world changes. It's worth noting that this actually offers better prediction in other cases as well.

An alternate method for a more reliable forwards-travelling shot would be this: Take the offset of the new target point from the player, a vector called o.

Apply the following equation:

o = o - (o * v_forward)* v_forward;

This removes the component of o in the direction Chthon is facing. Finally, make the target point equal to the player's origin + o. Not as elegant, but perhaps slightly easier. 
<-- Chthon Lavaball 
that is... fucking cool, man. 
Heh 
I wondered why, when I go to hit the button that if I moved a step backwards and then over and than towards him as I stepped on the button I was almost always ensured not to be hit, perhaps I should have looked at him once or twice. 
 
if the original chthon fight hadn't been so gimmicky, it would have been a cool trick akin to shambler dancing or nails + fiends.
it's sad that you barely even have to look at chthon to defeat him. :\

yes, i am bitter. it's a great model and texture. yet, so poorly used. :(
the same could be said for shub. 
 
killable Chthons are en vogue lately. 
Probably A Silly Question... 
when multiple entities a touching another entity with a .touch function, each entity runs the .touch with itself as other right? 
Touching 
Yeah, although you have to be careful with entities that aren't moving. For example, monsters at rest inside a trigger don't generate touch events, since the monster only checks for collision when moving, and the trigger never does. This is where force_retouch is required. All entities use the same code for checking collisions though, and it is a combination of descending recursively down the tree of nodes intersecting the 'self' entity, along with a for loop to test all the entities within the current node. 
 
thanks yet again, preach :)

i was thinking maybe i should go through all your posts in this thread and make like a 'preach's guide to arcane quake facts' :P 
Well 
I do have a fun fact about that fun fact: it implies that in a multiple collision, the order that the collisions are resolved is essentially unpredictable - they depend on the location of the entities within the bsp tree that comprises the level.

Speculation: it might be possible to exploit this to glean some information about the bsp tree from QC - using force_retouch with a trigger and some point entities spawned in a region. Knowing that one point is in a leaf higher up the tree(or further left) than another may not be incredibly useful though... 
Path_corner Weirdness... 
void() movetarget_f =
{
if (!self.targetname)
objerror ("monster_movetarget: no targetname");

self.solid = SOLID_TRIGGER;
self.touch = t_movetarget;
setsize (self, '-8 -8 -8', '8 8 8');

};

void() path_corner =
{
movetarget_f();
};


quoted is the path_corner entity. unlike every other entity, path_corner defer's it's setup code in another function.
as i'm passing by, i frown at it, comment out movetarget_f and just paste the code into the path_corner function and grin at my cleverness.

suddenly, none of the path_corners work anymore. so i o_O and put it back the way it was. of course, i'm left with the question of why? it's just an entity with a touch function. 
Path_corner 
I couldn't reproduce this - the monsters seemed to follow their usual paths when this was the only change made to the vanilla source code. Any chance that something else changed at the same time? 
 
well... i dunno but it works now...

new comment:
//deprecated. why was it even like this to begin with? (not deprecated, it stopped working when i moved this down into the path_corner function o_O) un-not-deprecated: it ended up working now. o.o 
Hmm 
Just bumping for easier location by new users (coding scares me way to much to be in here for any other reason ;) 
Self 
if you change 'self' in a think function and forget to change it back, what happens? (beyond just the operations in the same think function)
does it mess up the engine's think iteration as it goes through the list of stuff?

what about entity links? can something cause a .entity link to get broken?

i'm having some weird problem with entities randomly getting messed up but it's so random that tracking it down is proving quite annoying. 
Selfless 
The 'self' that you can access from the qc side is not used (at least in the standard source) in any of the engine code, it always begins with it's own reference to an entity passed as a parameter, and then set in the global_qc_self variable (not it's actual name in the source). So I don't think that could be your problem.

Is it possible that some of the entity links you have run through entities which are removed? The quake engine has a 'lazy remove' paired with a 'thorough spawn' function. Only 5 or 6 entity fields are cleared on removed entities, just enough that they are no longer transmitted to clients. When the entity slot is reused, the spawn builtin goes through and zeroes all of the fields.

Although it makes sense to not go to the trouble of zeroing all of that memory until necessary from a performance point of view, it can make bugs intermittent. If your code relies on a reference to an entity which has been removed, then it will more than likely perform correctly until something uses that entity slot. The trouble is now that the cause of the bug is separated from it's first effect by an unpredictable length of time, making it very hard to diagnose. 
 
i use
if (self.someEntityLink)
{
self.someEntityLink.think = SUB_Remove;
self.someEntityLink.nextthink = 0.1;
}

which i felt was pretty safe.

the problem seems to be centered around accelerating movers.
i'm still using helper entities to control velocity but it seems as if after a few minutes a helper will just become removed (when i check the helper's edict it is either free or a new entity).

however, this also happens with a custom lightning entity. the custom lightning entity spawns a chain of models to simulate the lightning effect and cleans them up when the effect is over. somehow that master entity just dies sometimes leaving the models in the game.

both of those entity's think loops seem to be solid so i can only guess something outside of their thinks are killing them. 
The Debugging Wrap 
You could put a wrapper around the remove function to try and work out exactly what is removing them. In defs.qc rename the builtin definition #15 to

void(entity e) remove_builtin = #15;


You can then define a function called remove which has extra behaviour before calling remove_builtin. I'd probably add a boolean field to the entities you want to monitor.

.float donotremove;

void(entity e) remove =
{
�if(e.donotremove)
�{
��dprint("Entity of class '");
��dprint(e.classname);
��dprint(' was removed!);
�}
�remove_builtin(e);
}

This doesn't give you much debugging information though, it still requires you to guess what just happened. It would be better to get a stack trace, but the only way to get one of those is to crash the map. I'm not sure how much of a stacktrace you get by calling error() or objerror(e). I do know that you'll get one by creating a runaway loop though, so something like:

void(entity e) remove =
{
�if(e.donotremove)
�{
��eprint(e);
��while(0){};
�}
�remove_builtin(e);
}


That ought to give you plenty of information as soon as one of these entities gets removed. Just remember to clear the donotremove flag before actually removing them! Also, it should be obvious that this kind of code shouldn't go in a release build... 
Oops 
That of course should be while(1) in the code above, so that it loops forwever rather than not at all. 
 
that's a great idea, thanks! maybe i should create a wrapper for spawn() so that donotremove is set to true by default, or do the inverse have it as 'safetoremove' defaulting to 0.
anyway, nice idea to abuse the stack trace engine feature. ^_^
it's like teaching progs new tricks but for engines. :P 
Donotremoveanything 
I was figuring you'd only apply donotremove in the spawn functions of the two entities you were trying to debug, otherwise you've got to worry about your game crashing every time a missile hits a wall and stuff! Wrapping spawn and remove is a really great trick with lots of uses, I'm really grateful to frikbot for showing me the trick of redirecting builtins. 
More Weirdness 
you know how, when you're riding a platform that's moving upward, your viewpoint sort of sinks down a bit?

currently, console prints (like bprints or stuffcmd bf) are causing the view sink effect to reset each time. every time there's a bprint, the view height resets to the standard height and starts to sink again.

i have the feeling i've fucked something up pretty badly. :P 
Oh O.o 
apparently, the bprint thing is happening in stock quake too. this must be some setting in fitzquake because it doesn't happen in aguirre's quake.

will investigate... o.0 
Uh Oh... 
 
 
i'm still unsure exactly what's causing it... if someone wouldn't mind checking this out, an easy way to test this is to bind a key to 'god' and then load up e1m1. hit the button for the first lift and let it lower.
when it starts to raise back up, repeatedly hit the key you bound to god mode. each time the screen should reset to the normal view height before sinking back down.

this happens in fitzquake and quakespasm. 
Incidentally 
i only noticed this happening because i have some debug code that outputs a ton of text repeatedly to the screen. with that many outputs, the screen practically shakes when riding a lift up.

it's not like it's really a big deal since when you play normally outside of developer 1 mode, you don't get the outputs and so don't get the shaking.

on a possibly(?) related note, monsters riding a lift up appear to not interpolate their positions if they are walking on the platform? 
 
on a possibly(?) related note, monsters riding a lift up appear to not interpolate their positions if they are walking on the platform?

yeah, I noticed this recently. Must fix!

As for the view jerkiness on lifts... I've seen this but it didn't notice a connection to console prints. Will investigate. 
 
possibly helpful:

it is not strictly bprints that cause this. when i turn the console spam off, every so often the view will jerk rarely. 
Engine/editor/compiler Coders Please Help! 
I got this urge to try and write my own Quake map editor for fun (don't hold your breath) and I am already stuck at the first hurdle (for this reason).

I don't know why, but I thought I would try and load a wad file first. Just so I understand the format I thought I'd read about it and implement it myself. I've also got the code from the engine to look at, so it's not super difficult, but I am having a weird problem.

When trying to read the individual lumps that contain the image data for textures, if I try and read the width or height value I just get nonsense UNLESS I add a weird 16 byte offset to the pointer I am using.

example:
LUMP_t* lump = (LUMP_t*)(waddata + lumpinfos[lumpno].filepos + 16);
cout << "width: " << lump->width << ", height: " << lump->height << "\n";
will output the correct width and height, but if I remove the 16 byte offset, it doesn't work and I get gibberish.

My problem is that I have no idea why I need to add the 16 byte offset, and am worried that it might cause problems down the road if I don't understand why it's there.

Aside from that offset, everything seems to be as I expected. 
Than 
My tip: try and implement some simple editing functionality as quickly as possible because that will keep you motivated. Don't write struts code like reading wad files. Write your internal model for brushes and write a simple renderer for that. Then, improve on that code. If you have to write code that doesn't draw anything on screen for weeks, you will very likely lose your motivation quickly. 
Sleep 
thanks for the tip. I know it can be really boring to write code that doesn't draw stuff, but for some reason I like writing file loaders and figuring out how stuff works. My plan for tonight is to get wad textures displaying on screen and then I want to go onto the exciting brush stuff and improve my 3d math knowledge (I forgot most of it... oops).

I don't think I will be able to write an editor as awesome as Willem's Toetag, but if I get even 1/4 of the way there, I will have learnt a lot :) 
One Tip 
Brushes are represented in map files as the intersection of a number of half space equations (each face is such an equation). You must convert this representation into a representation that you can use to draw stuff, i.e. polygons which you send more or less directly to OpenGL. There are several techniques to do this by calculating the extreme points of the solution of the original system of (inequality) equations. These techniques are computationally optimal, but very hard to implement correctly. I suggest you don't touch that stuff for your first version.

Another very simple way of converting a brush to polygons that you can draw is to start with a cuboid polyhedron (represented by its vertices and edges) with maximum dimensions and then simply split the brush along the planes which are defined by the faces. This is easy to do because you just have to intersect all edges of the polyhedron with the splitting plane. You'll end up with a polyhedron that has the same shape as the brush, but you can easily determine the face polygons from that data structure. This is computationally inefficient, but since you are not dealing with a lot of data, it's fast enough.

Another tip is to use the vertex / edge representation only for rendering, not for manipulation of the underlying brushes. The brushes should remain in their original representation and should be manipulated in that representation as well, This way you can use the very high precision that the half equation intersection representation offers (and don't have to convert float vertices back to int). 
Sleep: No No 
implement rounding errors or some other form of sloppy calculations so it will feel just like using qoole! 
Thanks For The Tips 
I got my wad loader working ok and it renders textures from a 570 texture wad just fine. The code is a total mess and I still don't know what that weird 16 byte offset is, but I got Quake textures displaying on screen in sexy Quake colours, so I'm happy for today. Next step will be a map loader :)

I made a map compiler (not to bsp, but to a much simpler format that just uses polygons) before, so I still have some code that can create polys from brushes somewhere. I was going to use that. Pretty sure it uses the clipping method. The first solution sounds difficult :)

this?: http://en.wikipedia.org/wiki/Convex_polytope#Vertex_representation_.28Convex_hull.29


Math on wikipedia is always extremely hardcore sounding. 
Just Had A Look 
at my old brush compiler code and it appears to take a series of 3 planes to generate a vertex and then adds the generated vertex to a vertex list for the each face involved in its calculation. It iterates through this until it's done and looks very inefficient.

But if it works, I don't care :)

When editing a map, most of the brushes just sit there unselected. I would imagine the average user doesn't touch more than a handful at once, and even then most of the operations are probably moves. 
Probability Of Attack 
anyone who's studied this could answer a question?

if i've got a monster who has an 80% chance to attack when his checkAttack function is called:

if (random() < 0.8)
attack!

does that really mean he has an 80% chance to attack at all times? or is it more like 10.7% chance to attack every second? (0.8 ^ 10 since animation rate is 10fps)

probability has always been pretty impenetrable for me. :S

as a result, i tend to rely much more on 'cooldown' (attack_finished) timers to regulate monster attack rates. 
Geometric Distribution 
The code you posted means he has an 80% chance to attack each frame. One of the best ways to understand what this means is to look at the probability that the monster will start attacking before the 2nd, 3rd, 4th frames etc.

The easiest way to do the calculation is to flip the question on it's head. What is the probability that we are still not attacking on the 2nd, 3rd, 4th frame? For that to be the case, we must have failed to attack in all the previous frames, and the chance of that is 0.2 each time. Since each trial is independent, we can multiply them together, as follows:

Frame 2: 0.2 * 0.2 = 0.04. 4% chance of not attacking after the second frame

Frame 3: 0.2 * 0.04 = 0.008. A 0.8% chance of not attacking on the third frame or earlier.

Frame 4: 0.2 * 0.008 = 0.0016. Scarcely a 0.1% chance that we are not attacking 4 frames of considering it.


So it's pretty certain we'll attack within the first 3 frames, our code is largely creating variety in behaviour over a range of just 0.3 seconds. Even if we changed the probability to 0.5 we'd still expect the monster to attack quite quickly: 1 / (2^10) is the probability that we wouldn't have attacked after 1 second - which works out at > 0.1%.

Using attack_finished as a cooldown is probably the best way to to long pauses out of your monsters, if you want them to choose between attacking with a missile or closing the distance with the player. 
Yeah 
that makes a whole lot more sense. i confused myself over why the chance to attack would go down over time, which is just stupid because every time we check, we are giving a new chance to attack. 
Quick Question 
I have a feeling I could find this if I dug through the Quake source, but are the lengths of key/value pairs for map entities limited to 16 and 32 chars respectively? If not is there some other limit? Does anyone know.

On top of that, if anyone happens to know the max number of:
entities in a map
faces per brush (guess this is compiler limited)
key/value pairs per entity

I'd love to know them :) 
^^ 
Thanks 
1024 seems quite a lot. I'll just get rid of the limits I put on my map loader.

Texture names do appear to be limited to 16 chars though. 
 
Texture names do appear to be limited to 16 chars though.

15 chars unfortunately, since you need a null terminator. 
 
This is not QuakeC related. The answer is hopefully simple algebra but I am too stupid to figure it out for myself and Google is not helping.

Let's say I have these 2D coordinates:
1) 10;10
2) 54321;12345

and want to fit them into a smaller (let's say 800x800) window. How would I code that? Do I really need to make an affine transformation? If yes, no need to explain the how, I should know that. 
";" Is Not A Name 
frikqcc keeps complaining about ";" not being a name in the following function, but I can't any ;'s being used as names, or any stray ones that might being messing with things. This is just the BackpackTouch func from progs106
<code>
/* PLAYER BACKPACKS */
void() BackpackTouch =
{
local string s;
local float best, old, new;
local entity stemp;
local float acount;

if(other.classname != "player")
return;
if(other.health <= 0)
return;

acount = 0;
sprint(other, "You get ");

if(self.items)
if((other.items & self.items) == 0) {
acount = 1;
sprint(other, "the ");
sprint(other, self.netname);
}

// if the player was using his best weapon, change up to the new one if better
stemp = self;
self = other;
best = W_BestWeapon();
self = stemp;

// change weapons
other.ammo_shells = other.ammo_shells + self.ammo_shells;
other.ammo_nails = other.ammo_nails + self.ammo_nails;
other.ammo_rockets = other.ammo_rockets + self.ammo_rockets;
other.ammo_cells = other.ammo_cells + self.ammo_cells;

new = self.items;
if(!new)
new = other.weapon;
old = other.items;
other.items = other.items | new;

bound_other_ammo();

if(self.ammo_shells) {
if(acount)
sprint(other, ", ");
acount = 1;
s = ftos(self.ammo_shells);
sprint(other, s);
sprint(other, " shells");
}
if(self.ammo_nails) {
if(acount)
sprint(other, ", ");
acount = 1;
s = ftos(self.ammo_nails);
sprint(other, s);
sprint(other, " nails");
}
if(self.ammo_rockets) {
if(acount)
sprint(other, ", ");
acount = 1;
s = ftos(self.ammo_rockets);
sprint(other, s);
sprint(other, " rockets");
}
if(self.ammo_cells) {
if(acount)
sprint(other, ", ");
acount = 1;
s = ftos(self.ammo_cells);
sprint(other, s);
sprint(other, " cells");

sprint(other, "\n");
// backpack touch sound
sound(other, CHAN_ITEM, "weapons/lock4.wav", 1, ATTN_NORM);
stuffcmd(other, "bf\n");

// remove the backpack, change self to the player
remove(self);
self = other;

// change to the weapon
if(!deathmatch)
self.weapon = new;
else
Deathmatch_Weapon(old, new);

W_SetCurrentAmmo();
};</code> 
Deception 
The error message is true but unhelpful. It's trying to use a ; as a name, but what that means is that it's reading a line in a way you didn't intend. Often you get unexpected parsing errors when you leave a function earlier or later than expected. In this case you're missing the closing braces for the self.ammo_cells block, and so it's reading some further code incorrectly.

I know that func_ eats indentation(unless you're really patient with inserting nbsp character entities) so I can't say if missing indentation might have made this harder to spot. But I can recommend editing code in something that can highlight matching braces in some way - I pasted the code into notepad++ to check the matching. I will concede that knowing it could be a mismatched brace based on the error was really key, so it's not all software solutions. 
Hat Tip 
That was it, thanks Preach. In my editor (acme) everything is indented fine, but as you said func_ at them. Wish func_ has support for <code></code> tags. 
Don't Forget To Spellcheck... 
s/at/&e 
 
a preformatted tag would be nice, but that would likely break the forum width?

mind you, the forum could probably get twice as wide without bothering anyone. 
 
No, absolutely not. Apart from the colours and no-clutter, the 72-80 character line length ensures the great readability of func. Forums that spread to full-width (or anything remotely like that) are an abomination.

Use http://www.inside3d.com/pastebin.php , that even gives you syntax highlighting. Also be aware that func has a preview button. ;) 
Yeah 
No offence to Quakeone.com for example, but having like more than 12 words on a line is a bit of a no-no. Just hurts my eyes :) 
Good Point 
 
Ok... 
 
Ropes... 
so i was wondering... how hard would it be to create some kind of dynamic rope thing in QC?

i'm thinking, you would put down a func_rope and then specify the length of the rope. then target at an info_notnull.

for the code, i first thought it would be pretty easy, all you'd have to do is first spawn an entity chain and then set each of the nodes in the chain to obey quake gravity.
then, all you'd need to do is check every frame to make sure the next link hasn't moved out of range and if it has, move it back along a straight vector.

but then i started thinking that you can't just iterate forward through the chain because you would have two anchored positions with only the center moving freely and then my head exploded. :( 
Oh 
and this is the best part: i started trying to code it because i was too lazy to make brushwork wires in my map. �_� 
 
ropes are easy enough, just set up a havok-like physics system and include inverse kinematics, then set up the constraints between your rope links, and mark the two ends as unmoveable. :) 
You Have To Burn The Rope From Both Ends At Once 
With two anchor points, you have the trail of gravity come from both at once. The only tricky situation is in the middle. 
Actually.... 
if all you want is a rope that doesn't collide with anything, including itself... it's doable.

To solve the rope position for a static rope, you just set it up at spawn: guess and then iteratively refine the locations of all entities until it's within a certain tolerance.

If you want it to be dynamic, you don't need iteration, but you give the rope some elasticity and then have it accelerate to the correct position every frame. With the right values, it will look pretty good. Otherwise it will be bouncy and rubbery and go crazy. 
Of Course... 
You also need to render the rope. I guess you would use a model that represented a segment of rope X units long. Whenever the distance between segments is not X, you will see gaps or overlap. Or have a bunch of frames in the .mdl to represent a range of distances, and quakec can select the frame based on the actual distance between joints on that frame. 
Sounds Cool 
Here's one tutorial I found, not sure how easy it would be to implement in quakec though: http://freespace.virgin.net/hugo.elias/models/m_string.htm 
 
If it's static, a rope hangs in a cosh curve ( http://en.wikipedia.org/wiki/Catenary ). You can just calculate it with a scientific calculator I guess :-) 
Ropey Mechanism 
The thing I'd want the most from creating a good rope system is just frustratingly out of reach of the QC - to be able to control endpoints of a polygon independently of each other. The use would be to attach some end of a polygon to one "entity" and the other end to another, so you could create a continuous mesh that you could deform individual segments of.

Without that, I'd say you're better off just creating a static mdl prop to represent a rope. One trick that I think could work well in a map is creating a reaction to "wind", and ropes would be a great prop for displaying it. The idea is to have a global wind variable which stores a value between say 0 and 40 representing the wind force in that frame.

You'd want a slow random walk which would move the wind through these values, it's possible that adding crandom()(sic) to it every 0.1 seconds and capping the value within the range would suffice. Scaling the adjustments by frametime(and then back up with a larger constant) would allow you to recalculate the wind strength every frame which might improve the animation. It might also benefit the model to make it more likely to move the wind towards the middle values than the extremes.

You then need props through your level like ropes, "ye olde inne" signs, torches, lanterns and flags which are specially designed to react to the wind. They might be give specially designed models which have frames from 0 to 40 corresponding to the strength of the wind. Then they would only need to have think functions which regularly update the entity's frame to match the wind in that frame, maybe with some jitter.

In some cases, like the sign at the inn, you might only be going for simple rotation back and forth. Then you would be better served using .angles rotation since some engines transmit it with higher precision, and you would avoid the floating vertices rotating a sign two degrees each frame is bound to produce. You would also not need to use granular values between 0 and 40, but just use the floating point wind value directly to calculate the angle.

Then just add some howling wind and creaking timber sounds and your windswept landscape is complete! 
 
i was actually not going to bother continuing but those posts kind of encouraged me to at least try...

ended up with this:
http://necros.quaddicted.com/temp/ropes1.jpg

each segment is 16-32 units long (they contain 16 frames in 1 unit long increments).

each frame, i iterate through the chain and add a velocity vector pointing towards both the next and previous points.

this works somewhat, but you have to tweak the tension (speed multiplier of the velocity vector) or it jitters a lot.

it also doesn't really work with longer ropes because you need super high tension to keep it from falling apart but those levels of velocity cause excessive jittering.

so yeah, with the expense of iterating the chain every frame and needed many segments with 1 entity each, it just doesn't seem worth it.
if i do try to continue with ropes generated at run time, looks like i'll have to look into static ropes, probably with a cosh function like mwh posted (thanks for that).

it's a shame though because i had hoped to get the ropes to react to rockets passing by and explosions. oh well. :S 
Just Noticed Another Problem 
if your FPS drops, the required velocity to keep the segments together becomes increasingly larger. at some point around 30-45 fps, the velocity is too high and the chain breaks. 
HeLp ? 
..my idea is to have in my map many different skinned monsters per class (4 or 5 soldiers with different colors, 4 or 5 knights, ..)

Easiest way to achieve this ?

-I'd happily skip the creation of every different skinned monster in qc code(since I want to change only clothes color for each!) 
 
Store the new skins in the mdls; give the monsters a "skin" "#" field in the map (# being the index number of the respective skin). 
Ffs Don't Crosspost 
 
 
there's 2 ways to create reskin monsters.

1. Create all new .qc files for each reskin, using the same frame macros but renaming the function names (so they don't conflict at compile time).

2. Integrate all the types of monsters into the same original monster code so that at key points in the code, it checks to see what type of reskin it is and then behave different accordingly.

method 1 is the easiest to understand and and read because everything is seperated into individual files. the monsters will adhere to the standard monster coding setups.
method 2 is the easiest to code because you don't have to rewrite anything and just add in little snippets for things like different attacks or a different ai_run routine.

also of note, a lot of the behaviour is controlled by the checkattack function, so simply having a seperate one of those can help distinguish between reskins.

if you're planning on doing this much coding, you should probably check out inside3d. they are more focused on coding while this board is more focused on mapping. 
 
re 460: clairvoyant? o.0 
Oh Nm 
i see what you meant now.

also: http://www.youtube.com/watch?v=21D-21MLrAE

not sure what those 'shivers' are... i can't only guess it is a symptom of irregular framerate. a momentary dip would cause it, i suppose, although i thought i fixed that. :P

also, i obviously need to find some way of adding in damping of some sort because those things will bounce around for ever. 
Lost Chapters Src 
Does anyone have/have a link to the lost chapters src from qexpo? http://qexpo.quakedev.com/booths.php?tag=necros doesn't go to the page. I've seen it linked somewhere here, just can't find it.. 
 
Ty 
 
 
http://necros.quaddicted.com/temp/qcgui1.jpg

another program with debatable usefulness. :P 
 
is it possible to determine if the player is inside a triangular space with just the info of the 3 vertices and discounting vertical axis with QC?

making a monster that traps the player inside a triangular area but it would be awesome if the monster could tell if you were actually trapped (inside) or not. 
 
god damn it...
as usual, after thinking about it for a few minutes, i figure it out a few seconds after posting.

i can just use the dot product of normalized vectors from the origin vertex.

we need a delete button. :P 
Rapid Fire Round 
Ok, I've got an idea to share with y'all about making QC events that happen at high frequencies cope with the framerate dropping below that frequency. But in order to make it a bit different, I'm going to set a bit of a puzzle about it first, which comes as a piece of code and three questions:

void() generic_think =
{
���// do some kind of thing which needs to
���// occur rapidly

���self.nextthink = self.nextthink + 0.05;
���self.think = generic_think;
���if(self.nextthink <= time)
������self.think();
}


� For partial credit, what is this code trying to do?
� For full credit, why will it fail?
� For extra credit, what can we do to fix it? 
 
it looks like you're trying to get the think function to recursively take care of missed thinks.

i've never thought of doing it this way. usually, if i have a think function that needs to be accurate across inaccurate think times, i just use something like this:

void() thinkfunction =
{
����fraction = (time - self.ltime) / 0.05;
����self.ltime = time;

����self.nextthink = time + 0.05;
����self.think = thinkfunction;

}

and just scale whatever it is i'm doing with fraction.

doing it recursively would be easier to code, i guess, but i would think much more expensive on operations. 
Tail Recursion After This Message... 
That's exactly the point of the code, so here's what goes wrong with it:

The assumptions behind this bit of the code are that the QC global time stores the current server time, and self.nextthink stores the time we wanted the think to occur. One of these things is often not the case, and the other is always incorrect.

If you run a dprint on self.nextthink during a think function (but not an animated think function) you will find that nextthink is equal to 0! It's always reset by the engine, so that unless you explicitly call for a new nextthink, the engine can skip over thinking. Conversely, nothing happens to the think field when you run a think function, so if you're optimising QC code for a looping think function, you can remove the bit where you reset self.think in each call safely.

So that's the assumption that's always wrong, that the nextthink time you originally set is preserved in that variable when the think function eventually runs. But is the information lost forever? Not always! The QC variable time is set to either the current server time, or the actual nextthink time which WAS set - whichever is the largest. So as long as you don't ever set nextthink to be smaller than the server time + frametime (which calculates the server time for the NEXT frame), you get the information back.

Luckily never doing that is the point of this whole missed-think-avoidance code. All we need now is to find out the true server time during our think. This is easy though, as we just create a new global called servertime. We then use StartFrame to set servertime = time, and then refer to that in our calculation.

Our code then looks like:

void() generic_think =
{
���//do stuff
���self.nextthink = time + 0.05;
���if (self.nextthink < servertime + frametime)
������self.think();
}

As a closing remark, this function has tail recursion, so you don't actually have to fill up the callstack repeating it over and again. Just wrap it in a do...while loop for performance.

And there we go, a way to ensure that a given function executes 100 times in a second, regardless of the framerate of the server. 
 
clever! :) i had no idea about time being set to nextthink.

also, you could just make a new .nextthink2 var:
self.nextthink = self.nextthink2 + 0.05;
this neatly avoids the engine resetting nextthink. 
Help With Those Damn .lmp Files ! 
Hi,

how can I modify those .lmp files included in id/paks ?
my goal is to have a new hud for my mod (at least change color and quake guy face !) 
 
adquedit can import bmp and pcx (i think?) and convert them to lmp. 
Lmp2pcx 
Or is it pcx2lump..i have one of them on my laptop, i can see if i can dig it up. 
QuakeC Source Code Licensing Status 
So what's the licensing status of the quakec source code? I was planning on releasing the rubicon 2 source, but not sure what license i can put on it (e.g. GPL)

I know that the original source release was sort of an informal "you can make quake mods with it" type license, but not sure if there was a more recent GPL release of the same code. And whether it applies to hipnotic code as well (since i'm using the hipnotic rotating code.) 
Useless Qc Observation Of The Day 
It turns out that the builtins floor, ceil and rint are not as efficient as abusing the bitwise functions.

So if you're optimising a tight loop with a call to floor(x) you can instead substitute:(x | x) which does the same thing. Similarly ceil(x) can be replaced by ((x | x) + 1). rint(x) is a little more complicated to replace, it takes two statements:

x = x + 0.5;
(x | x);//is now the same as rint(x) before the first line

Note that you can't make a helper function like

float(float x) rint2 =
{
�x = x + 0.5;
�return x | x;
}

- because the efficiency saving arises from avoiding the function call overhead, and you waste that by making it a function instead. Also, reducing the number of instructions is only really worthwhile in a tight loop that might trip the runaway-loop counter. Hence this being the useless qc observation of the day... 
Except That 
((x | x) + 1) is incorrect for ceil() as if x==floor(x) then you get a number that's 1 higher. 
True Dat. 
 
Man 
i didn't understand any of that. :(

what is |? i only know it's the bitwise add operator. never heard of using it with normal numbers. 
| Is Bitwise OR 
However, since it can only work with integers, it floors each number before doing the OR. 
Doh 
Yeah, I completely fluffed that one. I guess you'd need to do something along the lines of

temp = (x|x)
(temp != x) + temp;//this ACTUALLY evaluates to ceil x

Some lovely abuse of the boolean to float conversion there. I'm not sure if that's still fewer instructions than the call to ceil though... 
More Negatives 
The "better" version of ceil still doesn't work for negative numbers, and you might not get the same results as you expect for negative numbers using the rint substitute either. So they're both limited in scope. The floor one works well though, since it does the least work... 
Is Qc Really That Slow 
That crap like that matters? :s 
In This Case 
it's not about speed at all. preach already explained that it's main usefulness comes from reducing the number of operations done, thereby increasing the amount of things you can do in a while loop before the engine complains about it. 
Well Maybe 
Someone should make the engine not complain about how many instructions are being done. That seems.like a better fix than pretty much inlining every function call. 
Rationale 
That would mean that if you ever code an infinite loop in qc then the engine would hang rather than just drop the server with a runaway loop error message. 
Good Point 
Maybe then how many instructions are needed for a runaway error to be trigger should be increased? It would seem so if the kind of optimizations that were listed earlier are needed to stop runaway. Or maybe I'm crazy. 
Been A While Since I Did QC 
but how many loops would trip the runaway loop counter? 
100000 
100000 instructions between QC programs - a program being a succession of QC functions called without control returning to the engine. In general this is a sensible limit. An example where it might be a problem is if you need to run a looping on each of a set of entities, 20 entities would leave you only 5000 instructions for each one, disregarding overhead. Whatever you set the loop limit to, you could always push the boundaries, until the computation speed becomes more of a factor.

Of course by then you have a new excuse to optimise. The profile command suggests that once upon a time qc performance was an issue, and if quake were to be popularised in mobile or flash form, it might yet matter. 
Simple Idea 
Lower it for developer 1? Or have a runtime 'reader' to let you know exactly what's going on?

Like an ingame debugger. 
Maybe Not Lower It, But 
Have it print to console every 10k, noting the current stack and position. Or maybe even 5k... 
Yeah, 
Advanced logging. 
Qc Dev Tools 
Having extra qc developing tools in engines would be a blessing, but they wouldn't help with this problem because they won't ever be universally adopted - making a mod than only works in engines that have a raised instruction limit would not be wise. By that point you might as well customise the engine to do the intensive calculation for you and add it as a qc extension. It's not the kind of thing that can be set to "progressive enhancement" either - you can't change the logic of your code to suit the capacity of the engine that is running it.

At some point I want to write down my thoughts of "progressive enhancement" - usually a web design term - and how it relates to Quake. It can explain why features like fog and skyboxes were embraced, but things like qc extensions on the whole were not. 
That'd Be Interesting 
The question is, how can QSB be made. 
Honestly 
i've never really had any problems with the 100k instruction limit and i've done all kinds of weirdo shit in while loops.

the point where you start to hit the limit, you're better off thinking about deferring operations to the next frame or something. 
Yeah 
While I've never had anything proper reach the loop limit yet, I know that it was a problem in Prydon Gate, so I guess it depends how different your mod is. The further you go from the original game, the harder you have to work in qc I guess... 
Interesting 
If I started hitting the 100k limit in QuakeC I'd probably be at the point where I need to be doing an engine mod, not a QC mod. 
 
speaking of instructions...

i've been trying to figure out a way to be able to have two huge groups of monsters fight each other without slowing down.
i'm talking like 2 or 3k monster teams here.

been experimenting with sort of deferring all ai functions to a 'group leader' but it's sort of hit and miss. you either have like a static group and when you have intermittent LOS, then some of the group can't hit their target, or you have a dynamic group and the code to figure out what group you're in eats up even more time than just running ai on all monsters like normal. :\ 
Multithread It! 
Oh wait... 
Show Of Hands 
Quick straw poll here:

If I was going to invest some time in a qc project, which would be most useful to mappers?

1) A medium-range navigation system for the AI. Where monsters now walk straight at the player over gaps they can't cross, this system would direct them around to the bridge. Basically navigation on the scale of rooms, not levels.

2) A system to create alternative shapes for triggers. For example, cylindrical, spherical, rotated rectangles, composition of multiple triggers into a single unit.

3) create an event-based system for with inputs and outputs on doors and other funcs. For instance, allowing you fire triggers on the events of a door beginning to open, reaching closed position, being blocked, etc.
On the input side rather than having just a trigger, you might be able to command a door to open (does nothing if it's already open), or shut (vice versa ), or toggle (the old behaviour). Having a system of 'filters' would allow conditional triggers like "pass this input on if door X is still moving". 
In Order (favorite Idea First): 
AI first

I/O Triggers second

trigger b-box control third.

I guess all would have their uses, but better nav AI for monsters is the coolest idea IMO :) 
Ai 
 
 
Would be neat to give monsters specific commands, ie attack this, run over there etc. :E

Being able to give things specific triggers would be great, for example, forcing a door to close only on a specific trigger, or making func_trains that can be made to reverse and go backwards through their track. :) 
I would vote 3, but I don't really *release* maps, so... 
AI 
 
3! 
Quake is a simple pattern based arcade shooter that lives from its simplistic ai. 3 would allow people to create more atmosphere rich maps. 
1! 
Actually, all three. 
 
AI 
 
1...3...2 
I can't count :) 
Thoughts 
1) sounds like it would have the most tangible impact on the gameplay, although purists might argue that it would feel wrong to have Quake monsters capable of relentlessly chasing the player from room to room.

That said, I did feel the need to mackle up a very basic system in my maps to allow the monsters to chase the player up and down some of the spiral staircases, that otherwise they would have had real problems with.

2) sounds like its use would be too limited. 90% of the time, axis-aligned boxes will do the job, although I might as well admit that in Marcher I hacked in a sort of line-segment trigger (that functioned like an arbitrarily oriented invisible tripwire) which I used in a couple of places.

3) Sounds very useful all round and is a philosophy I wish Quake's trigger system had adopted from the beginning. 
Clarification 
Without wanting to influence anyone's votes

to allow the monsters to chase the player up and down some of the spiral staircases

This is almost exactly the use case I had in mind - a system that would be capable of allowing this, or for creatures to know how to move from a balcony, down the stairs into the atrium where the player was. The trick is making a single system flexible enough to do that without being a nightmare to set up.

It wouldn't let monsters chase you from room to room, you'd have one trigger brush creating a region, and if the monster and the player were both touching the trigger then the monster would be told the direction which moves them topologically closer* to the player. Hopefully that doesn't compromise the fundamental behaviour of any monster, just allows them to deal with complex rooms as well as open spaces.

* As opposed to the direction bringing them physically closer - the current navigation method. In open spaces, the two are the same. So by reduction the gameplay is unchanged, and in a single bound I am free! 
 
i seem to remember nehahra had some improved navigation systems for monsters, but you could always specify which one to use when placing the entity. i'd favour this approach 
AI 'smell' Trail 
Was something we were pondering. It got denounced when we mentioned it here of course.

Nehahra had various layers of AI and additional flags like INTREPID (ignore hazards when leaping off stuff) and the ability to teleport at will. 
 
ai sounds like the most useful.

i've experimented with different methods but never really been satisfied.

currently, i'm using a sort of waypoint system that monsters will follow after they loose sight of your.

it has the benefit of making monsters look realistic when searching for you, but in some ways, it makes them less effective.

an interim system i have is to have the ability to flag path_corners to make monsters both not search for the player, not react to damage, and to use their run animation instead of walk when moving to them.
this is only useful for initial pathing, as once the monster is awake and not following path_corners, there's no benefit.

but yeah, a unified pathing system would be totally awesome, but i just can't see how to get it to work for all cases. :(

good luck though. i'd be really interested to see what you come up with! 
 
A simple but useful bit of AI gameplay wise would be that melee monsters that are below the player or otherwise can't find a direct path to the player will instead seek to hide from the player's LoS (whether they could hide from grenades I dunno :P ).

This could help prevent a lot of cheesing combat, if the monster hides when the player is trying to pick it off from a safe position. It's often this which easily disarms the challenge in a lot of maps, and is why the only way to really create a challenging fight is just to suddenly drop the enemies directly on top of the player in a trap. 
 
This could help prevent a lot of cheesing combat, if the monster hides when the player is trying to pick it off from a safe position. It's often this which easily disarms the challenge in a lot of maps, and is why the only way to really create a challenging fight is just to suddenly drop the enemies directly on top of the player in a trap.

i feel this is more a mapper's failing. you shouldn't really be letting melee monsters get into a position like that unless it's something you can't plan for (ie: fiend jumps off a ledge and can't reach you anymore).

but like, for example, you shouldn't really be able to 'pull' melee monsters from far away or don't provide an easy way to exploit them. 
Speaking As Primarily Not A Mapper... 
(...and no, this isn't an excuse to tell me to fuck off)

I'd contemplated re-writing the trigger system before, but I wasn't sure how best to do it. The way that makes most sense to me right now, is some sort of "message" system, that goes something like this:

"targetname" is what is being sent the message. The additional targetname entries (if present in the code) give it additional frequencies to be listening to.

"target" is what to send the message to. Again, the additional targets work like additional frequences to be broadcasting on.

And them there's an (as yet) unnamed 3rd field, which is the message to be sent. This could be something like a traditional use/activate signal, a kill signal, a change texture signal (so you can have brush entities that are doing something more useful than just being func_walls change their appearance), or maybe even something else.

This is made more interesting, of course, by being able to send a different signal to each target. Yes, this is still similar to how we have .target and .killtarget now (and yes, this would allow both to be done at the same time, as is the case in Quoth, RMQ, and other mods), but it would be more flexible than that.

The only part I'm not sure on, is if this signal should be a float or a string. And then, of course, you have to define what all of the signals mean for each object. Obviously, there would be a few common ones, but some would need additional things specified. 
 
yeah, that's an ok system. it's good because it's unified and probably easy to understand from a programming point of view.

i imagine the 'message' could be a simple bit mask where you can select what you want to change to the triggered object. so a single trigger could change, for example, both the func_door texture AND open it or whatever.

but it's just easier to code up helper or script entities instead and more intuitive in an editor (not to mention there's no support for an 'entity message' in any editors). 
 
mm, my mind apparently skipped a beat and i didn't actually explain myself on that third paragraph. o.0

i say it's easier, but it's also more flexible.
i have script entities that can change an entity's owner, change specific 'target' strings, toggle flags/spawnflags on entities.

toggling a func_walls texture is simple, but how would you put 'change targetname2 on this entity to xxxxx' in a simple one string/integer message. you'd end up with other helpers anyway. 
Collecting Sigils 
What is the code that lights the sigil's place marker on the player's GUI as each sigil is collected?

Are the lights just made in order or do the shapes relate to the actual sigil?

I do not get any lights when I use them (and collect them)in my levels - what gives? 
Sigils/rune 
an engine coder could tell you for certain, but in the qc, picking up runes sets a global variable 'serverflags' with bits 1, 2, 4 and 8, corresponding to the appropriate episode.
the runes only work if the UI is set to the default one. hipnotic and rogue game modes turn on their respective UIs which don't check the runes. so if your mod uses one of those UIs or you're using quoth which uses hipnotic UI, then the runes don't show up. 
Mmmmm... 
Yes, if I use standard progs.dat (1.06) then the UI lights up. I am not using a mod but I am using an 'enhanced' progs.dat.

However, I have checked the sigil_touch section in items.qc and it exactly the same as the 1.06 version. I cannot find any other differences related to 'serverflags'.

Strange. Must be something, but I don't know what. 
WARNING: BAD CODE AHEAD 
THIS CODE IS PURE EVIL.

YOU MIGHT FIND IT USEFUL.

BUT DON'T GET FUNNY IDEAS.

So...I was working on the winner of the straw poll, which is the navigation entity stuff. Idea 3 did attract some attention so I might put up an article about naming in QC which would contain the "clever ideas" part of the event system I had in mind, so someone else with time on their hands would be free to do the footwork implementing it. Most of the effort would be in creating useful input and output on the various func_ entities, but at least it's a chance to exercise some creativity.

Anyway, I was trying to create some beautiful code involving callback functions (been reading too much ajax stuff recently) and managed to confuse the compiler enough for it to mistake a string field for a float. As you may or may not know string fields in QC are integer offsets into a big block of strings. So I came up with the following:

float INT_1 = 0.0000000000000000000000000000000000000000000014013;
.string tempstring;

void(.float stringfield) increment_string =
{
��float increment, stringvalue;
��increment = INT_1;
��if(self.stringfield < 0)
����increment = increment * -1;
��stringvalue = self.stringfield;
��do
��{
����stringvalue = stringvalue + increment;
����increment = increment * 2;
��}
��while(stringvalue == self.stringfield);
��
��self.stringfield = stringvalue;
}

void(void(.string floatfield) dispatch, .string fieldtype) strip_fieldtype =
{
��dispatch(fieldtype);
}


//then put the following code somewhere
{
��self.tempstring = self.model;
��while(self.tempstring != "")
��{
����strip_fieldtype (increment_string, tempstring);
����dprint(self.tempstring);
����dprint("\n");
����if(self.tempstring == ".bsp")
����{
������dprint("It's a bsp file!\n");
������break;
����}
��}
}

It's so hacky I don't even want to talk about why it works. 
Shamefaced 
In time maybe I'll see this as undoing a great blessing but: a correction:

float INT_1 = 0.00000 0000000000000000000 00000000000000 00000014013; but without the spaces. 
 
increment = INT_1 o.0

mike: i was referring to the command switch you use when launching quake, not the progs. the progs can't change the UI itself, unfortunately. if you put hipnotic progs in the id1 folder, you'll get hipnotic entities, but the UI will be default quake. 
Oh Btw 
on pathfinding...

if you're gonna implement a brand new system... should just go whole hog and do a star and just let the mapper plop down some nodes. that'd be insanely badass...

i'd totally do it, but i'm too dumb. ^_^ 
Necros 
I am not sure I understand. No, I am sure I don't understand.

I have two .bat files:

fitzquake085.exe -window -heapsize 40960 +gl_clear 1 -width 1024 -bpp 32

fitzquake085.exe -window -heapsize 40960 +gl_clear 1 -width 1024 -bpp 32 -game mynewprogs +skill 2 +map This_FMB_1_8c

The first runs the iD1 folder and this has no qconsole file and the same config file as the mynewprogs folder. The mynewprogs folder does not have a qconsole file either.

As far as I can see the only difference in the two folders is the progs.dat. Yet the first bat file game shows the runes lights as you pick them up but the other bat file game doesn't.

It does not actually affect the gameplay but as you need all four runes to create a certain effect, it would be useful for the player to able to see what he has already picked up instead of having to remember.

Any hints as to what could cause mynewprogs to apply different UI settings? 
Itemized 
So do you have .float items2 defined somewhere in your code? If it is defined anywhere then the serverflags info is not sent to the client - to save bandwidth that info is replaced by the items2 info instead. 
Fakepreach 
Funny you should say that. Yes, I do have .float items2 as I have the drole and vermis from Quoth.

//quoth -- items
.float items2; // bit flags for new items -- ran out of room on items...

I am not sure why they ran out room; perhaps I'll experiment with changing it to 'items' and see what breaks. 
Runes Can Exist In .items2 
As 32, 64, 128, and 256. If you're using .items2 for your own nefarious purposes, then leave those four bits for the runes. 
Note That 
sigil_touch() will need to be adjusted for this to work. The line

serverflags = serverflags | (self.spawnflags & 15);


should be followed by

other.items2 = other.items2 | ((self.spawnflags & 15) * 32);

This won't send the update to all players, but that's only relevant in coop. Also, impulse 13 won't update the hud properly, but a similar line will work in the function that handles it. 
Ohh 
thanks fakepreach and lardarse for clearing that up! i had no idea .items2 had any bearing on serverflags!

mike, since you're only using the drole, you could do a quick find/replace and just change 'items2' to something like 'drolevar'.
that way you can just leave the old serverflags variable alone. 
Thanks Necros, Fakepreach, Lardarse 
As I am not using any Quoth items, I can do away with the code relating to items2 without any detriment. It's just a couple of If/Then statements which don't apply anyway.

Onwards and upwards... 
 
don't forget to tone down the drole damage a lot. ^_^; 
Drole Damage... 
"Do you expect me to talk?"

"No, Mr Bond. I expect you to die!" 
Bbox Sizes 
so, going in the opposite direction, it's possible to make monsters with smaller bbox sizes, however you need to offset them by whatever amount smaller than 6 that you used.

now that you're down frowning in perplexity at that terrible sentence, this is what i mean:
say you made a skinny monster, '-6 -6 -24' to '6 6 40'
you need to setorigin(self, '-10 -10 0') the monster or, if you place it close to walls, it will get stuck (even though, when you turn r_showbboxes on, the bbox clearly is not in any wall).

but other than that, it seems to work fine, really lets monsters bunch up. would have worked good for the voreling had i known about it back then. 
Heh 
not only was that sentence awful, but there's a typo too.

by whatever amount smaller than 16 that you used.  
 
I did this with Floyd, didn't do the setorigin trick but instead made the in-editor box full shambler size so there's no risk of placing it in a wall. 
Fools Echo 
I'm still perplexed in making the Doomguy crouch.
Didn't want to start it over afraid of being a fool.

But the trick me was told to lower the bouncingbox so bullits would fly over it, and then raise the model again.
I don't understand. Then it would sink in the ground, but raising it would raise the bouncing box too? 
 
i'm not sure if we've covered this but when do touch functions get run when monsters are involved via movetogoal/walkmove?

are they run at the moment movetogoal is called?

ie:

void() someTouchFunction =
{
other.happy = 0
}

void() ai_run =
{
self.happy = 1
movetogoal(1)
if (self.happy)
cheer
}

so in this retarded example, while the ai_run function will make the monster happy, it will run a touch function right after movetogoal so that the if statement will fail?

i've been observing some screwed up behaviour and i'm trying to track it down... 
Touchy Subject 
Yeah, the touch functions are respected there - only pitfall to bear in mind is that if the move fails because the monster is blocked, then they don't move at all and so the monster doesn't touch.

So that doesn't really help you track down your problem, and it sounds like you've got a pretty solid minimal test there. So I'm just gonna take a peek at somet-
OH MY!

Oh dear.

Very long standing bug in quake coming right up...

PF_walkmove, the non-navigational monster moving code, has the following code in it, which I remember noting down for possible use with that JS quake engine idea

// save program state, because SV_movestep may call other progs
oldf = pr_xfunction;
oldself = pr_global_struct->self;

G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);

// restore program state
pr_xfunction = oldf;
pr_global_struct->self = oldself;


Firstly a quick note, "PF" in front of a function in the quake source means that it's a "progs function" - a light wrapper around some C code called as a QC builtin. The snippit I quoted then calls SV_movestep - the real heavyweight movement function which other parts of the engine also use.

Around that call we have some clearly documented code which stores the current QC execution state and restores it after the call. This firstly tells us that touch functions are a possibility they have programmed for, and secondly eliminates a possible source of the buggy behaviour - that after calling the touch control never returns to the QC.

Except your QC doesn't use walkmove, it uses movetogoal. I went looking for PF_movetogoal and was surprised to find it missing. It turns out that the QC builtin in this case directly calls SV_movetogoal instead, and I'm sure some of you are ahead of the puchline here - it doesn't save the QC state.

I haven't gone away to do follow up QC tests, but worst case I can imagine is that none of the remaining QC in your function ever gets run if a touch function is encountered, and best case is that it's just self that gets obliterated. In the former case you are basically stuck with using walkmove instead. In the latter you can put the traditional

local entity oself;
oself = self;
movetogoal(1)
self = oself;

But yeah, genuine nasty bug there I think. Let me know whether it is that worst case scenario situation or what, I'd like to know... 
 
ohhh ok, yes! that explains some OTHER whacked out behaviour i've been seeing!

i've changed movetogoal into a wrapper that (among other things) does a movetogoal(1) and then calls x number of walkmove(directionItMoved, 1) to complete the amount of movement requested.
this allows a monster to continue to move forward, even if it's full movement would have failed allowing it to get through thin or cluttered areas better.

i was seeing some weird stuff where a monster would touch a trigger and then not move (it was moving by 1, but not completing the walkmoves).

i guess it never mattered before because movetogoal was solely called at the very end of a qc function.

anyway, i've added in your suggested change and will test it today. :) 
Binary Chop 
If you like, there's a trick you can apply there to only call ~log(x) steps in the worst case rather than x for moving x distance.

The trick is try to walkmove(x) first - being optimistic!

Check the return value for failure, and we can finish if we succeeded.

If we failed, replace x by with x * 0.5. We then try to walkmove(x) with the new x.

We keep repeating the above step(in italics) until x is smaller than 1.

Note that after the first iteration we don't need to check for success.

Worked example:
Suppose we want to walk forward 32 units but only have space to move 21 units.

First time through walkmove fails
x=32, moved=0

Second time through we succeed
x=16, moved=16

Third time round we fail as we are 16 forward and another 8 would take us past 21
x=8, moved=16

Fourth round we succeed
x=4, moved=20

Fifth fails
x=2, moved=20

Sixth succeeds
x=1, moved=21

Since x has reached 1 we terminate.

I'm making the numbers quite friendly by choosing x as a power of 2. It also lets me gloss over the edge cases of when to reject x and stuff. Nonetheless the method is sound and a fairly simple loop. Probably the hardest idea would be proving that it always works, I've always been fond of Proof by Single Worked Example though... 
Yeah 
i've been meaning to do that. :)

i wasn't sure if there was a point where doing it linear was faster or if it was always slower and i just haven't been in the mood to try to figure it out. ^_^;

it looks like you're saying it's always faster?
also, while we're talking about walkmove and such...
is it ok to call a walkmove/movetogoal larger than bbox size?
ie: walkmove(yaw, 256) as opposed to looping walkmove (16) 16 times.
not sure if this messes up collision if the bbox is displaced by huge amounts... 
Empirical Answers 
Yeah, the binary chop should always reduce or equal the number of calls to walkmove in the linear algorithm. The nice thing about it is getting twice as high precision only costs you 1 more call to walkmove, although I doubt anyone needs monsters THAT much more finely tuned than 1 unit.

I tried to pick through the engine code to decide if you could get away with long distance walkmoves. But it's the densest part of the engine code and although my suspicion was that collisions would get skipped I wouldn't be able to answer with confidence.

So I bashed away through the latter half of Lewis and made a test mod. The emperical conclusion: no.

You can make a monster walkmove 256 units and completely skip a 64 unit trigger. So yes, limit yourself to width of a bbox per iteration. You can be assured that you won't ever skip through walls of the game world. BSP entities don't count though... 
 
You can be assured that you won't ever skip through walls of the game world.

this is more what i was asking. mainly the use for super long walkmoves would be to check for charging/leaping abilities like fiends instead of just checking if they can see the player.

a walkmove check of even just 16 or so units will stop a fiend from doing that psycho leap 'bug' around doorways.
otoh, it will also cause it to fail more often as a jump that would hit a wall yet allow it to bounce towards the player (and hit him) would fail unlike with just plain visibility checks.

you could possibly make a 'robust' walkmove that, when failing to move, would tweak angles by a small amount and try again.

hmmm... 
Rollback 
I was about to warn you about using walkmove checks(where you want to reserve the right to rollback the movement and do something else) too freely. What if you walkmove into a rocket during a 'check'. Luckily you are largely protected from this kind of thing. This is because the only thing that monsters will collide with during a walkmove or movetogoal is SOLID_TRIGGER entities.

So really all you need is to watch your triggers which respond to monsters when you're doing that kind of thing. In standard quake that's only really telefrag and trigger_hurt - which you could guard against with a quick change of takedamage.

If you really get into that kind of thing you can go down the route of having a 'proxy' entity instead. I was trying to think about what you'd need to do to get the proxy perfect. The think you'd need to get right is .owner, which would take 3 transformations:

1)Set the owner of monster's owner to the proxy.
2)Set the owner of proxy to the the monster.
3)Set the owner of everything else in the world currently owned by monster to proxy.

You also need to store enough information to reverse all these changes.

This is of course absurd levels of effort. Just set the proxy's owner to the monster, and accept that occasionally it'll be blocked by an entity that owner settings would have let the monster walk through. Never realistically a problem. 
 
thanks, i hadn't thought about the 'premature triggering'. yeah, a proxy looks like the best bet.

when i needed a walkmove check to move through monsters, i just set all monsters to non-solid. :P 
 
or a flag on the entity you toggle on temporarily that you code into all triggers 'don't activate when this flag is on'. 
Addendum 
The takehome message of the last post is:
During a walkmove or movetogoal the monster will only collide with SOLID_TRIGGER entities.

I want to add that only the trigger's touch function is activated, the engine does not call the monster's touch function with the trigger as other. 
In Error 
So I adapted the code which I wrote last week answer that question about movetogoal. It turns out that even through touch functions, it restores the QC state correctly and doesn't overwrite self. This is admittedly run from a think function - it's possible that you could create a more complex scenario like calling movetogoal from a touch function and then causing another touch function.

But I thought I'd share it with you because it made me practice a few diagnostic tools for QC, some of which you may not be aware of.

The first is just chucking in a load of dprint statements, I'm sure most people have done that before. Don't forget that you can use ftos() and vtos() to put more information into the statements. If you need to confirm the value of an entity variable (as I wanted to with self) you can use the eprint() function instead.

The second tool is a bit of a hack. It allows you to get a stack trace. This was particularly valuable in this case because of the concern that the touch function might be trashing the stack. But it would be of use in any case where you have an interaction between think and touch functions causing a bug, and you want to know what is calling what.

There's no command or QC builtin for a stack trace, but you get one if you manage to perform an invalid operation in QC. The infinite loop is one way to do this, but personally I prefer the null function call, it's a bit quicker. Just throw something like

world.think1();

and unless the map is particularly weird you'll get your error. Of course, this does shut down the entire server, so it's not for general use.

The last trick is pretty powerful but also has the potential to spam the entire console out. The QC builtins traceon() and traceoff() allow you to enable console output of every Qasm instruction that the server reads - including the register values that were employed.

I believe Qasm is a neologism, and if so I demand it be pronounced as "chasm". It refers to the bytecode that a QC compiler creates - effectively Quake Assembly code. You can use one of the options in FTEQCC to output the assembly to a file, which is a good way to learn what the trace output means.

(As an aside FTEQCC also lets you enter segments entirely in Qasm. This is in the same way as c compilers accept asm segments - and indeed the original quake engine did just that in the renderer to get tight loops fast enough for the Pentium 75s to run the game. I believe most modern ports strip the assembly out. Even so, in quake Qasm is a great way to do naughty things that the compiler won't let you...) 
Are You Sure? 
because i distinctly remember after putting in the self restoration bit that it fixed a problem with walkmoves not being called after movetogoal. 
Yeah 
We might have to share some code here to determine why we're getting different results. If you whack an eprint(self) in before you restore self do you get the trigger entity that you touched come up? 
Heh 
yeah, i guess i could have at least tried it out to see.

you're right, self isn't being lost when touching triggers. trying to figure out now would be pointless though, because the code has change by a huge amount since last time i posted about it. 
SV_TouchLinks: Next != L->next 
is it bad to call setorigin(self) in a touch function? does that cause the touchlinks warning in fitz?

i googled the forums, but i don't think it was ever really explained what this error is, only that it used to crash in e2m2. 
Potentially 
I'm not brilliant at following how the engine handles this touch stuff, but here goes:

The following functions could cause problems with sv_touchlinks:

setorigin
setsize
droptofloor
movetogoal
walkmove

All these functions can cause the entity to be relinked, which potentially causes the issue. There are some other conditions that need to be met before the error is encountered: firstly the entity has to be part of the same areanode as the touch is coming from*. My understanding is that there are 32 areanodes in a map to reduce the number of entities considered in the collision code by approx. that factor.

The other important thing is that the entity has to actually break the chain of linked entities at exactly the point that sv_touchlinks is operating. I believe that this translates to applying any of the dangerous functions to other, but again not too sure how all the code fits together.

A final small point is that even if do apply one of the dangerous functions to other (and since we're in a touch function with other it's safe to assume by now that they share an areanode) we might still get away with it. This case would occur when other is the first entity in the areanode - relinking it will reinsert it in the same place as before. There's no safe way to exploit this though, as it's determined entirely engine-side.

The last thing to remember is that sv_touchlinks only looks through the list of triggers, so anything that's not SOLID_TRIGGER* ought to be safe. Best of luck!



*Technically that should read "that wasn't SOLID_TRIGGER last time the entity got linked into the world" but that's a bit of a mouthful. All that means is that you can't quickly set the entity to SOLID_NOT and get away with anything, it's about whether the entity is truly a trigger according to the engine at that time... 
Footnote 
That first asterisk should have been removed, the footnote is about the SOLID_TRIGGER statement - though most of you spotted that anyway I expect... 
 
yeah, this is happening with some of my code. unfortunately, i have the report from a third party and haven't been able to reproduce it myself. apparently, occasionally, it spams the console with sv_touchlinks errors in fitz085.

i noticed this tiny comment in defs.qc for setmodel:

void(entity e, string m) setmodel = #3; // set movetype and solid first

and i checked that entity and found that i was setting self.model before movetype. so i fixed that anyway, but maybe that might also have been the problem? the entity wasn't properly linked in the first place?

geez, i dunno. :P

it's supposed to be a visible solid_trigger entity that changes origin when you touch it.

i was wondering, maybe if i used to bad method of just setting self.origin in the touch function, that way, it's not breaking whatever links? 
Danger 
From what I've gleaned, that is the most dangerous thing you could do in a touch function, although I didn't post it correctly. I was talking about the danger of moving other, but I should have been talking about self. I had the two muddled up and I'm sorry about that.

The standard way to cope with this is to set up a quick think function from the touch function, and have that think reset the origin. You can put a guard into the touch function to prevent multiple touches before it moves - set up a flag on the entity and toggle it in the touch and think. 
Hm Ok 
so what i can do is just set a flag after the touch function to disallow further touches until the think function has been run. that should work i guess. a little roundabout but last thing i want to do is start causing crashes. :P 
Speed-up 
You can also use a little trick to make sure the think function runs as soon as possible (either this frame or the next). Just set self.nextthink = 0.05; - note that we are deliberately omitting time from the assignment. Since this will be in the past for every frame the engine runs (frame 1 runs at time = 0.1) it will execute the think as soon as the entity is checked by the engine.

The flag works a bit like the way that
if (self.nextthink > time) line works for a trigger_multiple, so if you don't want to use another field that approach is an option. My feeling is that the flag is simpler because you don't need the flexibility of a custom delay but it's basically a preference thing. 
Spot The Deliberate Mistake? 
(frame 1 runs at time = 0.1)

Time starts at 1, not 0. This is one of the quirks of the system, that makes very little difference, except for when it trips you up (and when it does, it hurts). For example (from the id1 code):

self.nextthink = self.nextthink + random()*0.5;

This line appears in all of the $foomonster_start functions. The original intention was for monsters to not all do their setup on the same frame, to reduce computer load. However, what actually happens, is that on a roughly 1 in 32000 chance (or, according to LordHavoc, 1 in 2 billion on Linux), self.nextthink is set to 0, which means that it never thinks again (as .nextthink is set to 0 before the think function is called), and the rest of the time, it happens on the next frame. 
Thinking About The Other One 
When a think function is being called, what is other set to? Does it get set to something predictable, or is it just left as whatever it was last time? 
 
so that bit of code doesn't actually do anything then?

might be a good idea to change to it 1 + random() * 0.5 then? because that must mean thinks are being all processed on the same frame.

also, on other, a few think functions steal other for their own uses so even if it is being reset every frame, you might get a semi-random entity if one of those thinks happened during the frame? 
I'd Say 
(1 + random()) * 0.5 
 
won't that still generate nextthinks < 1? 
Depends 
Is nextthink a float or an int, and how do conversions work in QC? If it is like in C, then yeah. I just thought it's closer to the original, but heh we don't really want that. 
<1 
It's ok to generate thinks which are less than 1 in this case, because as long as it's non-zero the think function will run, and you'll still spread the monsters out over many frames because not all of them are going to get the same random number.

And if they did, they'd all be set off on the same frame no matter what function you did...

Good catch on the server starting at 1 there though, I must remember that. Either way, as long as you don't set nextthink to 0, any value less than 1 will give you the soonest think function possible. 
However 
any value less than time will give you the soonest think function possible

As Spike has pointed out a few times, when a think function is called, for that dive into the code only, time is set to what .nextthink was before being reset. So the most reliable way for a "do this next frame" is probably self.nextthink = time; 
Well 
Only if your code depends on the value of time in some way. If all you need is for it to run in the next server frame then you can take the shortcut. If time cannot every be less than 1 then a value less than 1 is always less than time... 
 
i think it's more about successive thinks.

the less aligned monster thinks are, the less impact the ai routine has when it's run, i would think.

if you just set nextthink to 1, every monster will be thinking at the same time. 
Shadow Casting Bmodels 
could someone modify MH's Aguirre's light utility so that it casts shadows from bmodels?
and maybe a new key '_noshadows' to disable shadows on that particular bmodel?

or is it not possible? like bmodels can't be used for some reason? 
Reversal Of Fortune 
Not commenting on how it can or can't be done, but I'd recommend making it opt-in rather than opt-out. Having an entity key _castshadows which you set to 1 to enable the new function would keep the current behaviour on existing maps, which is always desirable when possible. I also think there's a good chance that the cases you don't want it on (entities which move or have little to no impact on shadow casting) outnumber the entities which would benefit. It would make it reactive - used only when the lighting looks wrong - but I don't think that's a bad thing. 
 
maybe. either way, it'd still be great if someone could haxor that in. :) 
 
we were talking about how bsp models use their bboxes to figure out collision a little while ago.

i mentioned about setting bbox in qc affecting that. i tested it out, and yes, if you manually set bbox size, you can don't need to put visible brushes at the min/max extents.

also, if there are visible parts of the bsp model but the bbox is smaller, any bits outside the bbox are nonsolid. 
Award 
also, if there are visible parts of the bsp model but the bbox is smaller, any bits outside the bbox are nonsolid.

Hack of the week right there, folks. Awesome! 
Backup Past 0 
what the heck is this anyway? :P 
Tracing Error 
It's a glitch in the trace code. It arises in the part of the code that tries to determine the exact impact point of a trace on a solid surface. The loop starts with a point at "0" which it knows is in the open, and a midpoint which it knows is in solid BSP. It then backs up from the solid point in small increments until it gets into the open, and so fixes the endpoint of the trace.

The glitch occurs because the increments don't always exactly hit the 0 point as they build towards it. It is possible for the trace to be in solid for all of the test points before 0, and for the increment to never hit exactly 0. The loop would then return the first point past 0 as the nearest point-in-open to the impact point(i.e. backup past 0). However, we already know that 0 is closer to the surface and in-open so that point is returned instead.

Phew, so basically I think this is most likely to occur on short traces where an endpoint is near a surface, as these are the traces where floating point inaccuracy is most prevalent, and I believe that makes a difference. However, there is a binary chop portion of the trace algorithm, so the circumstances that cause it to happen may just occur at random on any given surface.

Possibly also complicated or intricate BSP architecture could make this more likely, since you would have to dive down to a smaller scale to check exactly which bit of fine detail a trace collides with, but I've got no example to back that up with. 
Thanks 
that helps a lot to know at least what is causing it. 
Sounds... 
Sounds don't start until one second after worldspawn. Is this 'fixable' from qc?

My FMB_BDG map finishes with an earthquake and it would be nice, from a continuity point of view, to start the next section with the tail-end of the earthquake. 
Time Starts At 1, Not 0 
So it's probably fixable from the map(s). 
Sound Out 
Completely untested, but if you spawned a static sound which didn't loop, does that cause an error? Otherwise it might just get around the problem... 
Oh Yeah 
that helps a lot to know at least what is causing it.

Probably the most important thing to know about it is that it doesn't matter at all - there's nothing going wrong in your code and the engine has already coped with the potential inadequacy. So I'm not even sure the message is worth preserving in the engine... 
 
well, if there's no purpose to it... i just get spammed by it sometimes and it clears out the console buffer of useful debug text, which is annoying. good to know it isn't causing problems.

also, trying to spawn a static (ambient) sound that isn't looped results in that 'sound isn't looped' error we used to get with the broken ambient_thunder entity. 
 
i have a bad feeling about this but....

is there ANY way to detect if the player has either opened the menu or closed it? 
Unlikely 
I can't see how you could, no QC runs while you're in the menu (assuming you're thinking of single player - multiplayer is different but no more helpful). You'd end up trying to spot differences from frame to frame in the same way that QC detects loading from a saved game. The problem is that you could quite easily go into the menu, do nothing and then leave after a while. I don't see how this would leave anything for the QC to find... 
 
yeah, i was afraid of that. :(
oh well, thanks anyway. 
Monster_decoy 
What was this used for in SoA? 
 
cutscenes. it's a player model that will run to path_corners and wait for a few seconds, if 'wait' or 'delay' or something is set.
iirc. 
Ah, Thanks. 
 
Func_areaportals 
Has anyone ever tried porting func_areaportal from quake 2 to a quake 1 engine and related tools? Any idea on how hard it would/wouldn't be? 
 
So I've been thinking about a way to add a lot of new weapons to a mod, but I'm not sure about some things. The first issue would be how the hud handles the weapons, since there's only enough room for 9 weapons, I would need to figure out a way to make sure that weapons don't take each others spots. I was thinking of adding a precache variable to each weapon and then checking to make sure that none of them conflict with each other when the map starts. I think that would eliminate the problem of weapons taking other weapons spots. I have no idea how and for what reason they're placed on the hud the way they are, anyone have any insight on this? 
HUD Placement 
There's actually quite a lot to be said about the HUD but I'll try and get the basics into one short post.

The engine uses the QC field called items to determine which weapons to display on the HUD. If you look in defs.qc you will find the following:

// items
float IT_AXE = 4096;
float IT_SHOTGUN = 1;
float IT_SUPER_SHOTGUN = 2;
float IT_NAILGUN = 4;
float IT_SUPER_NAILGUN = 8;
float IT_GRENADE_LAUNCHER = 16;
float IT_ROCKET_LAUNCHER = 32;
float IT_LIGHTNING = 64;

To display some collection of these items on the screen simply sum the values of the icons you want displayed, and then set self.items to equal the total.

The numbers are all carefully chosen as powers of 2. This is useful because it makes any sum a unique combination of these numbers. It also means that you can use the bitwise OR function to safely add an item without checking if it is already there:

self.items = self.items | IT_SHOTGUN;

If we started with 0 items, and then blindly added IT_SHOTGUN to self.items we might get into trouble - if that line of code ran twice then self.items would equal 2 and we'd have IT_SUPER_SHOTGUN instead.

We can also use the bitwise AND function to test if an item is present:

if(self.items & IT_NAILGUN)
{
�//do something just for players with a nailgun
}

If the bitwise functions are new to you I'd advise searching for a c tutorial on them, it's probably been explained before in a clearer way than I'd invent today.

Other things to know about icons:
� Setting self.weapon to one of the IT_ values highlights that icon as the selected weapon.
� The mission packs added extra weapons which complicate the icons code somewhat, so I'll avoid that until another day.
� The engine automatically makes new items blink on the HUD when they are added to self.items
Path_corners 
I made some path_corners in a map that are different z distances (hight/lower than another path_corner) apart, thinking that my flying monster would follow them. To my surprise, it didn't. After removing the z distance from my path_corners, the monster follows the path just fine.

It seems that with flying monsters, if path_corners are different z distances apart, they 'ignore' the path_corners. From a brief look at the quakec, everything looks ok. Maybe this is a bug in PF_walkmove? Looking at the function, it looks like it ignores the z axis all together (line 28), so maybe it's not a bug, Carmack just ignored it :p.

Note: This doesn't affect walkmonsters (as much) as flying monsters. With walkmonsters, they seem to be able be able to find their next path_corner as long as the z distance between them isn't too much (I haven't found out exactly what it is).

Looking a monsters.qc at the walkmonster_start_go and flymonster_start_go functions, and more specifically at if statement testing if there's a target, walkmonsters set their .ideal_yaw to vectoyaw(self.goalentity.origin - self.origin), flymonsters don't do this. I have no idea if that statement is related to the problem, correlation does not imply causation. :)

I need to fresh up on my trig.. 
 
it is a bug with movetogoal.
movetogoal does not check z unless both .goalentity AND .enemy is set.

if .enemy is set to a path_corner, it actually will track vertically. unfortunately, this necessitates a qc change.

ALSO, if you can believe it, THIS SAME FUCKING BUG IS PRESENT IN DOOM 3. CARMACK. COME ON MAN.
you will not believe the incredulity i felt when i set up a nice path for my cacodemons only to have them not able to fly up or down to reach them, even with AAS computed. 
Oh Also 
walkmove explicitly does ignore z but it is only a simple 'step in this direction' function.
the function you want to look at is the movetogoal one, which does the random monster bumping around stuffs and probably contains the vertical adjustments for flyers when chasing enemies. 
Necros 
Upon reading your posts, I naively added ``self.enemy = self.goalentity'' right after path_corner check in *monster_start_go functions in monsters.qc, thinking that it would fix all of my problems. Now the monsters are facing towards the path_corner and are in their walking animation, bit they're not moving at all. D: I suspect this has to do with a change I made, as I've been adding a lot of new things and haven't been testing any of them :p. oops.

Now 'all' I have to do if find what the problem is.. 
 
you will need to haxor it in.

basically, in ai_walk, change:

movetogoal();

to

self.enemy = self.goalentity;
movetogoal();
self.enemy = world;


or alternatively, create a movetogoal wrapper only for walking:

void(float step) walktogoal =
{
self.enemy = self.goalentity;
movetogoal();
self.enemy = world;
}


and just replace movetogoal calls with walktogoal in ai_walk.

the wrapper method is probably cleaner and if you make new walking functions, you don't need to repeat the hack. 
Remember That 
movetogoal() also needs the distance. 
Ragged 
I'm trying the shield code for the EldenOgre, but I'm not lucky.

I found some arg in the qc I couldn't place, or I should look at the pentagram code but I couldn't trace it.

OLDONE.QC - line 271 => self.takedamage = DAMAGE_YES;
OLDONE.QC - line 138 => pl.takedamage = DAMAGE_NO;

So I thought to be smart by adding it to the shielding frames like:

void() xogre_shield4 =[ $shield4, xogre_shield5 ] { self.takedamage = DAMAGE_NO;};

This works, but now I can't stop it shielding!

Another thing is the line in Defs.QC
DEFS.QC - line 443 => .void() th_defense; // gb, need to defend against enemy fire

The oldone.qc is the only one with the th_defense in it.
Can I use it on an entity?

Maybe a weird question for someone who knows how the code DOES work, butI thought making an entity shield is something like giving it a Pentagram? 
 
It's not Quake related, but anyone up for helping me with a SAT based collision detection issue? 
Madfox 
th_defense is an RMQ specific AI extension.

Look in ai.qc under ai_defensecheck(). If a monster's self.enemy just fired a weapon, the monster does whatever is defined in its th_defense function.

In the case of the shield ogre, it does xogre_defense() which is calling the shield animation etc.

It also sets self.shielded to 1 (in the shield frames), which is checked in turn in weapons.qc. That is where the actual projectile reflection stuff is done.

xogre is the only monster with a defined defense behaviour atm; however, you can use self.th_defense on *any* monster in RMQ. Just need to make a mymonster_defense function that contains the defensive action. If the monster's defense requires some extra jazz, like projectile reflection, add that to weapons.qc.

All of this requires RMQ.

If you want to do this in your own progs.dat, just port the ai_defensecheck(), self.shielded and all related stuff to your codebase.

I'm pretty sure Supa wrote the actual projectile reflection code in weapons.qc, so ask her (on the trac) if you need help with that.

All of this is really pretty RMQ specific stuff. Monsters actually defending against attacks is something that's still work in progress. 
Thanx Gb, For Your Explaination 
I've been looking at the RMQ code, but as the normal QC.108 is already over my hat I thought to look at the normal monstercode.
The th.defense I found in Defs.qc and as I couldn't find it elsewhere I wondered where it could relay to.

I tried earlier to calculate the code in but when I used te RMQ code it started stuttering on other args. 
Ambush 
Does the engine cause monsters not to make noise when their ambush flag is set? I can't find anything about it in progs. 
 
Look in the code for an if statement looking at .spawnflags & 3 - there's a comment next to it about zombies having ambush on a different flag. 
 
no, monsters still make noise when they have ambush set.

i had to add that specifically into my progs to get silent monster wakeups. 
Then What Does The Ambush Spawn Flag Do? 
 
 
Erm, makes them not wake up when they hear something... 
 
makes them not wake up until they see you -- normally they will also wake up if a nearby monster sees you. 
 
Kind of general programming question about Quake. How does Quake handle broad-phase collision between entities. Does it store them in each BSP leaf and only collide those in the same leaf? 
Linked In 
There is a bit of a problem with that approach, which is key to understanding how the engine actually does it. The problem is that an entity might occupy more than one bsp leaf at the same time. So you would actually need a list for each entity of all the leaves that it spans.

Since this might get unwieldy the engine does something a bit simpler, and if you're interested in finding all the code behind it then the thing to search the source for is sv_areanodes*. Areanodes actually just split the space occupied by the world into a fixed depth binary tree by repeated partition along the longest axis of the previous areanode.

That last sentence is concise and accurate, so I instantly fear it's not very approachable. It's like making a new binary space partition which almost entirely ignores the geometry of the world and only uses the minimum and maximum points. It then recursive splits the space into two equally sized parts. It does this by splitting the longest side of the remaining space to try and keep the lengths of all the sides as even as possible.

An areanode is one of the dividing lines between two of these areas, or one of the areas themselves in the case of the leaves on the bottom level of the tree. If an entity straddles a division then it is stored within the list attached to that node. If it straddles many divisions then it is stored in the list belonging to the division furthest up the tree. If the entity is wholly contained in a single area, then unsurprisingly it is stored in the list belonging to that "leaf areanode".

It's then fairly simple to pare down the list of entities to collide against. Find the areanode that your collision trace belongs to (imagine the area swept out by the movement as being a big entity), then you need only test all entities in the subtree with that areanode as the root. If you go through the exact centre of the map then you will certainly be testing against all the entities in the map, but it's not often a problem in practice.

It's worth noting that quake actually has a fixed depth for this tree of just 4. This translates to 16 leaf areanodes representing volumes in the map, along with 15 splits separating them. To illustrate the size of that, if your map is 4 times wider in both x and y than it is tall, which it's easy to imagine something like Castle of the Damned might be, then there would be no areanode splits in the z axis at all, instead creating a 4x4 grid over the map.

Presumably custom engine coders who push both the extents of the bsp format and the number of entities in a map do increase these limits somewhat, either dynamically or just to a higher static cap.




*Warning: If you look too carefully in this region of the source you might find this pair of macros which make the Rune of Black Magic look tame...

#define EDICT_FROM_AREA(l) STRUCT_FROM_LINK(l,edict_t,area)
#define STRUCT_FROM_LINK(l,t,m)
������((t *)((byte *)l - (int)&(((t *)0)->m)))
 
 
ic... or at least, I think I do :P So this set up is kind of like a grid containing sub-grids kind of set up (can't remember what they're called)?

How does it manage the list of objects as it changes? ie how does it move an object from one node to another? 
 
/slaps self for awful grammar. 
Sorting 
The term used within the engine for maintaining these lists is called linking*. You might have heard the term used in QC in discussions about SetOrigin. Typically guides would mention that if you set the origin key directly then the entity will not be correctly linked in the engine. This actually means the entity you moved will still be listed in the collision list for its old position.

In the same way that we have to be responsible and call SetOrigin every time that we move things in QC, the engine code has to call the relinking function every time that it updates the origin of an entity. The nitty-gritty of the relinking is not too complicated, just run through the areanodes until you find one that intersects your entity (or reach a leaf that contains you). Then remove yourself from the old list and append yourself to the new one.



*The term linking does have quite a nice visual metaphor of tying the entities to their areas, but I think it really only arose because the entities are stored in a traditional "linked list" structure. 
 
It's worth noting that quake actually has a fixed depth for this tree of just 4. This translates to 16 leaf areanodes representing volumes in the map, along with 15 splits separating them.

this is also the thing that causes large bmodels to flicker or disappear, i believe. especially with rotaters because qbsp errs on the side of (paranoid) caution and makes the bboxes massively oversized. it also doesn't take into account the actual rotations that you will be subjecting the rotater to (this is more understandable though), so if you had like a 1024 long brush that had just a 4x4 cross section, the bbox would still be roughly 1024x1024x1024, even if it only rotated along the long axis.
this makes it get connected to tons of those leafs and and overloads the engine. i guess it just either discards the first links it made, or stops linking when it hits the limit. 
It's Weird... 
you'd think it would simply store the node of the first plane that the bbox is on both sides of. Then when testing two bboxes against each other, find out if their node pointers are related (identical nodes, or ancestor-descendant), then test bboxes directly. Maybe they did that and it wasn't fast enough on the target machines.

One thing to point out -- I attempted making a mapper-oriented console warning in fitzquake that said "entity XYZ touches too many leafs, exceeds MAX_ENT_LEAFS", but what i found was that even tiny id maps had these errors. So even e1m1 breaks the limit on a couple of entities, but you never see a symptom of it unless it goes over so much that none of the 16 leafs are in the current PVS, causing the entity to vanish. 
 
Interesting... time to go off and read some more about data structures :)

What bits of source code should I look up to take a peek at the game loop? Interested in how it sorts through objects and knows what to do with each object :E 
Explorer 
I'd say SV_Physics() in sv_phys.c is the main loop to start with. It runs once per frame, looping through all the entities, running physics and QC functions on them. It doesn't give you everything the server does in a frame, stuff like creating the updates to be sent out to the network and parsing the input from the client is elsewhere. But it is the heart of the matter.

One thing that I've found extremely helpful in tackling the quake source code is loading it into a proper IDE like Visual Studio. Being able to right click a function name or typedef and select "go to definition" allows you to focus on figuring out what the functions do, rather than having to switch your train of thought to hunting down the function manually. The history buttons are likewise important so that you can return to the original function just as easily.

Finally "Find All References" allows you to step outwards, for instance to go from Sv_Physics back out to the rest of the server code, and see where it fits in. 
So On The Subject 
of looking far too closely at the engine physics source, is this a mistake?

trace_t SV_ClipMoveToEntity (edict_t *ent, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end)
{
��trace_t���trace;
��vec3_t����offset;
��vec3_t����start_l, end_l;
��hull_t����*hull;

// fill in a default trace
��memset (&trace, 0, sizeof(trace_t));
��trace.fraction = 1;
��trace.allsolid = true;
��VectorCopy (end, trace.endpos);

// get the clipping hull
��hull = SV_HullForEntity (ent, mins, maxs, offset);

��VectorSubtract (start, offset, start_l);
��VectorSubtract (end, offset, end_l);

// trace a line through the apropriate clipping hull
��SV_RecursiveHullCheck (hull, hull->firstclipnode, 0, 1, start_l, end_l, &trace);

// fix trace up by the offset
��if (trace.fraction != 1)
����VectorAdd (trace.endpos, offset, trace.endpos);

// did we clip the move?
��if (trace.fraction < 1 || trace.startsolid )
����trace.ent = ent;

��return trace;
}

Quoting from fitzquake source but I think it's unaltered. I've bolded the references to offset, because as far as I can see it never gets initialised. It doesn't actually matter in the call to SV_HullForEntity because that function never reads the offset parameter, just uses it as a local variable for internal calculations!

Still, since it's not passed by reference there presumably the same junk sitting there from the uninitialised starting state. Is it just by fortunate placement on the stack that it always gets zero initialised or something? It looks like it should at least mess up trace_endpos if it really contained garbage, or worse the whole SV_RecursiveHullCheck call... 
It's Actually Passed By Reference! 
It's only evident when you check the definition of vec3_t in q_stdinc.h:

typedef float vec_t;
typedef vec_t vec3_t[3];

vec3_t is an array type, so it is always passed by reference in a function call. In this case, it looks like SV_HullForEntity always writes to the offset variable, so there's no problem.

That is really confusing, though - at first I though vec3_t was a type that is passed by value, like struct { float x; float y; float z}. 
Ah... 
that's what i suspected too, looking at that code. 
Preach 
Do you write about code elsewhere? 
Other Writing 
inertia: No, this is basically my one coding outlet! I've got a little article coming up on names in qc which lead me to look up this function and get confused.

ercw: Thanks! Been away from c coding too long I missed that vector thing. And I really should have seen it given the way that the VectorAdd function works, clearly taking a pass by reference in order to mutate the third parameter. Ah well... 
In C++ 
how does a for loop initialise an integer automatically?

int a;
for (a=1; a<150; a++){cout << a;}


Works, buuuut:


int a; cout << a;


throws a compiler error with


"Run-Time Check Failure #3 - The variable 'a' is being used without being initialized."


Now obviously i could start with:


int a=0;


But what gives the for loop the right to initialise the variable before it begins testing it? 
 
for (a=1; ...

The a=1 is the part that initializes the variable 
 
Hmmmmm. I kinda suspected that. I guess I'm mis-understanding the for part. I can't help but think of it as an if.

The excercise which has gotten me confused is the following:

int i, j;
bool isprime;
for(i=1; i<100; i++){
isprime = true;
// see if the number is evenly divisible
for(j=2; j<= i/2; j++)
// if it is then it is not prime
if ((i%j) == 0) isprime = false;
if (isprime) cout << i << " is prime. \n";


It's the modulus test part, and my understanding of prime numbers which has gotten me confused.

I inserted this after the second last 'if':

cout << "i=" << i << ", j=" << j << " ";


This way it shows me what the two variables are. I don't understand why the test works. 
 
cout << "i=" << i << ", j=" << j << " ";

looks suspiciously like some of the stuff i've been learning about linux and input redirection... 
 
What exactly don't you understand?
The if (isprime)? If you test a variable without explictly writing eg isprime == 42 it will test if the variable is true (or not false or something like that). 
 
%

% is what i dont understand lol.

Why is 2%3 equal to 2 ?

Why is 45%89 equal to 45 ? 
 
Yeah - I Just Read That, Incidentally. 
The most useful bit of information I could find on that page was:

^ ISO/IEC 14882:2003 : Programming languages -- C++. 5.6.4: ISO, IEC. 2003. "the binary % operator yields the remainder from the division of the first expression by the second. .... If both operands are nonnegative then the remainder is nonnegative; if not, the sign of the remainder is implementation-defined".

The word "nonnegative" scares me a bit TBH. 
 
modulus is basically the remainder. like you do long division and stop before going into decimals.

so 2%3 is 2 because 2 can't fit into 3 at all, so you have 2 as the remained.
same with 45%89.

otoh, if you had 3%2, it's 1, because 2 fits into 3 once, and you have 1 left over. 
Necros 
I'm sure you meant to say: 3 can't fit into 2 at all, that's why 2 % 3 = 2. Look at this, Ricky:

0 % 3 = 0
1 % 3 = 1
2 % 3 = 2
3 % 3 = 0
4 % 3 = 1

etc.

Just try a few examples and you'll get a feel for what the modulo operator does. 
Thanks Necros & SleepwalkR 
I also figured he meant a three, but I was pretty cross-eyed already ;)

I think I'm starting to understand it. C++ is weird though, because sometimes you get a negative short. Which is weird. BUT I'm beginning to get my head round it. Which means I'm learning :D 
Sleep 
haha, apparently math doesn't fit at all into my head. :P 
Ricky 
You're probably messing up the types (using signed short instead of unsigned or something). 
Shoutouts To Awesome Lines Of QC Code #1 
A real gem from the walkmonster_start_go code I've never noticed before today:

self.ideal_yaw = self.angles * '0 1 0';


Why not just use self.angles_y? Because that wouldn't be vectorised and involve lots of awesome multiplication! 
Why Not Just Use Self.angles_y? 
...because then self.ideal_yaw_x and self.ideal_yaw_z may not be set to 0. 
 
ideal_yaw is a float though 
Yeah 
It's the dot product, so it returns the sum of all three components once you do the componentwise multiplication. Very handy some of the time, but a bit of a waste here. 
Rocket Trails 
What is it that gives rocket (and grenades) their flight trails? 
Model Flags 
There are flags you can set on models which select which (if any) effect that applies. If you open one with QMe it gives you a nice tickbox interface if you bring up the model properties box. 
Flags 
Thanks Preach 
Just To Clarify 
This is distinct from the QC .flags field - you can't change the particle effects from QC (other than having multiple models and switching between them). 
Flags 
Understood: I found the flag on the model immediately and was able to change them as required.

Is there any effect on performance if I suddenly add lots of these 'particle' effects? 
 
i don't think you'll feel it on an engine with the original particles (or even fitz' circular ones) but DP and other engines with 'fancy' particles can start to chug. i know some players using DP found the lava splash effects in ne_ruins would just kill their framerate, for example but i wouldn't even notice it in quakespasm. 
 
I think older engines have a maximum number of particles they will show. 
 
even glquake had -particles though and i always used to use -particles 20000. these days, i use -200000, but i think modern engines don't even use that anymore? i just leave it because it's in a batch file. :P 
Five Particles 
A hell knight fires 5 projectiles with trails in a single attack. Launching 1 projectile with five trail should be within scope. 
I Forget... 
is:

val = random();
val = val + random();
val = val + random();
val = val + random();

the same as:

val = random() + random() + random() + random();

Should Be 
as long as assigning the result of random() to val doesn't lose any information.

e.g. for the first case, if the language was C, val was an int variable, and random() returned a float between 0.0 and 1.0, the right hand side of each statement would be truncated to an integer before being stored in val, so in most cases you'd end up with val as 0, unless one of the random()'s returned exactly 1.0. In the second case the floats would be added up before being truncated to an int.

I think in QuakeC they are equivalent because random returns a float and the only numeric type is float. 
 
this is purely for quakec.

my question was along the lines of ftos() vs random() and if random() has the same problem ftos does.
my head tells me it shouldn't, since floats are primitives, but my gut tells me qc may do things in a weird way. 
 
Ah. here's the implementation of random: (pr_cmds.c)


static void PF_random (void)
{
float num;

num = (rand() & 0x7fff) / ((float)0x7fff);

G_FLOAT(OFS_RETURN) = num;
}


it looks fine.. I think the "G_FLOAT(OFS_RETURN) = num;" just stores the result in the vm global for return values. so it's not using any shared buffer like ftos.

... but I'm a qc noob so maybe someone more experienced should chime in :-) 
 
i'd totally test this, except it's random. XD 
Return Value 
Yeah, it's basically about return values in C. A return value of a float is passed by value - i.e. copied to the return value and therefore to the QC. So subsequent calls to rand get different values.

The problem with ftos is that strings in C aren't primitives. Instead what gets returned is a pointer, and passing a pointer by value is effectively passing the string by reference. In the case of ftos there is only a single buffer used, so the pointer which is returned always has the same value: the address for the start of the buffer. 
 
in a way, qc is a lot like java...

thanks, preach. 
Interesting Micro-optimisation 
The idea that the pointer doesn't change means you can save valuable QC operations by not assigning the return value of subsequent calls to ftos or vtos!

local string a;
a = ftos(self.health); //store pr_string_temp in a
dprint (a);
ftos(self.max_health); //a already stores the pointer to pr_string_temp
dprint(a); //so no need for an assignment
vtos(self.origin);
dprint(a); //vtos uses the same string buffer

Remember: saving 3 QC commands in your debugging routines should be your top priority when coding.


To make it even more efficient, why not just use a global!

string pr_string_temp;

void() worldspawn
{
...
pr_string_temp = ftos(0);
...
}

Never assign to the variable again, and just use the following pattern in all ftos code:

ftos(self.health);
dprint(pr_string_temp);

Although it was born from a daft optimisation idea, there is one nice thing about this coding structure. It makes explicit the gotcha with using ftos - that internally it uses a single temporary buffer. Consequently you'd be much less likely to use it incorrectly by calling ftos twice without writing the buffer to screen or console first. 
Multiple Replies 
#653:
In theory, yes.

In practice, the original QCC has a bug where only the last of the return values is actually used if they appear in a single statement, so it becomes random()*4. Spike claims to have fixed this in FTEQCC, but I remain slightly skeptical.

#660:
Note that some engines will likely break this behaviour... 
 
In practice, the original QCC has a bug where only the last of the return values is actually used if they appear in a single statement, so it becomes random()*4. Spike claims to have fixed this in FTEQCC, but I remain slightly skeptical.

So we're back to it not working then? :( 
Depends 
Some compilers will do this wrong thing:

� call random once - store the return value
� call random again - overwrite the return
� call random yet again - overwrite the return
� call random finally - overwrite the return
� add the final return value to itself four time

The difference between this and the ftos problem is that ftos overwrites the result on the engine side, but this bug occurs on the QC side so better compilers can fix it. I'm pretty confident that FTEQCC compiles this correctly but you could test it with the following code:


float counter;

float() increment_counter =
{
counter = counter + 1;
return counter;
}

void() test_compiler =
{
local float total;
total = increment_counter() + increment_counter() + increment_counter() + increment_counter();
dprint( ftos (total));
}

Compilers with the fix should output 1 + 2 + 3 + 4 = 10, the original qcc compiler will output 16. There's no difference here between a builtin returning a float and a compiled QC function which does the same. 
 
excellent! everything is peachy, preachy! 
Wow 
you are a poet! 
 
OK, some basic QuakeC questions here...

1. I know if I set the velocity on an entity, it will start moving in that direction. I read that avelocity is a force acting on that. Does that degrade over time or something? Like, is it a temp force or is it always there?

2. Velocity moves an entity regardless of it's angles, correct?

3. Is there a quick and dirty way to tell an entity to face the direction that it's moving in? Like, say I fire a rocket from a point in space -- I want it to face the direction that it's moving in. This is escaping me for whatever reason.

Thanks! :) Hopefully these aren't too rudimentary. 
 
To expand on the rocket things, say the rocket fires from EntityA towards EntityB. So the direction is:

normalize( EntityB.origin - EntityA.origin ); (or vice versa, I can never remember that)

That gives me a unit vector I can use to calc a velocity for flying but how do I make it point at EntityB while it's doing that? 
 
1. avelocity is angular velocity and has no bearing on velocity. it does not degrade either. the engine just increments .angles by this much every second.

2. velocity moves an entity IF it's .flags does NOT contain the ON_GROUND flag.
yes, it does move it regardless of angles. to move in the direction of angles, you need to do makevectors(self.angles)
self.velocity = v_forward * someSpeed

3. yes: self.angles = vectoangles(self.velocity) turns the velocity into an angle. 
 
Excellent, thank you! Yes, what you said in #3 fixed my rockets as well. Woot! 
Contentious Quake Design Nitpicking 
I contend that the th_* style ai functions are over-engineered in the original qc code.

There is not, to my recollection, a single instance where quake monsters share a th_* function like th_melee, th_pain etc. Therefore it would be best to just have a single function

.float th_handle(float eventnum)

for each monster. The eventnum would then have EVENT_MELEE, EVENT_RUN and so on, and which handler to run would be chosen from a switch statement. There's no reason to suppose that the handling code would all go inline, most likely each statement in the switch would just call the relevant function.

The two big wins of this change would be:
Firstly to get rid of all that cruft for all the other entities in the quake universe.
Secondly to allow many more 'events' to be handled. Whack in default handling which does nothing and you can add event handling for just selected monsters. Things currently dealt with by hacky classname searching like monster waking sounds or attack decision making could be refactored into events.

Having laid out a grand vision, I would grant mercy to the special case of th_pain. Mercy is extended on the grounds that pain functions are parametrised on attacker and damage, and hacking around that would probably be worse than just letting it stay. 
 
wouldn't it be better to expand the .functions available to monsters?

for example, replacing all the sight sound checks with wake functions so each monster could have it's own method of playing sounds (some monsters might want different attenuations, other might play random sounds).

one thing i liked about doom3 monsters was that their animations and thinking were separated into two threads. that'd be interesting to do in quake, have your monster model with frame handling and some invisible thinking entity that actually animated based on events and such. 
Hierarchy 
Expanding the available functions is exactly the sort of thing that was motivating me. The feeling I have is that there's a tension between adding all the fields a monster could ever need and not burdening all the other entities in the game with stuff they don't use. This leads us to the current compromise where the most vital events get handlers and the rest get hacks.

Adding new fields is possible, but if you wanted to support 50 or 60 events it would get pretty crazy. In a world where lots of monsters shared th_melee or th_stand functions, or even where such things might change dynamically for a given entity (like an injured monster switching to a limping run) the current architecture would have more weight. But as it is, you're born with the think functions of one class, and you die by it, so why not bundle the whole package into one function for the monster to carry about? 
 
i know what you mean about the th functions...
i run into it when designing a boss monster that doesn't fit into the standard mold of 1 melee, 1 ranged.

i usually end up overriding the checkattack function for those monsters with a function that directly calls whatever attacks are needed.

still, a function field is stored as, what, an integer? or float? 32 bits is not really a big deal, even with thousands of entities.

seems like it would be more hard to deal with code where there is a single entry point for all monsters and hundreds of checks for each one.
that would be very annoying, i'd think. 
Sketching 
You could have a list of the events starting with the mandatory ones

//====MANDATORY====
float EVENT_STAND = 1;
float EVENT_RUN = 2;
float EVENT_MELEE = 3;
...
float EVENT_WAKE
float EVENT_DIE = 8;

//=====OPTIONAL====
float EVENT_OPTIONAL_START = EVENT_DIE + 1;
float EVENT_STRUCK_BY_LIGHTNING = EVENT_OPTIONAL_START;
float EVENT_SHOT_MIDAIR = EVENT_STRUCK_BY_LIGHTNING +1;
...

Then the pattern for event handling goes:

void monster_shamber_handler(float eventnum)
{
��if(eventnum < EVENT_OPTIONAL_START)
��{

��//code to handle events all monsters are expected to deal with
��//even if grunt response to EVENT_MELEE is no-op etc.
��return;
��}
��else
��{

��//handle any other selection of events with set of if..else lines
��}
}

In theory you could do some sort of jump table with the mandatory events using the event number as an index. Of course, since qc doesn't really handle integer calculations all that well you'd probably find the most efficient solution was to redefine all the event numbers to already be the desired offset into the table stored as an integer bytewise. Assuming you need 4 qc instructions per handler to call a function and return you'd be looking at

float EVENT_STAND = 0.00000000000000000000000000000000000000000000056051938;

And so on...wasn't there a compiler that let you define integer constants like %4
HUD Text Shizzles 
I've never ever looked into mucking around with the HUD before - but would like to do one thing if possible...

You know when you press tab to see your monster and secret counts? Is it possible with QC to change the text "secrets" to say something else? As well as on the end level tally screen? 
Kinn: 
the score bar (when you press "tab") is hard-coded in the engine.

The intermission screen is an image, so you could edit that image to say anything. 
Ah Ok 
hmmm, so i can change one but not the other :/ 
 
you could always make your own menu/screen.

even with stock quake exe you can make a functional menu that pauses the game. 
 
you could always make your own menu/screen.

Nah that would be huge overkill for what I'd be doing. Besides, I realised what I originally had in mind is probably just a silly gimmick anyway, I'm gonna shove it to one side for now. 
Brushmodel Texture Swapping 
So let's say I have a brushmodel and i want the texture it wears to change according to events. From what I understand, all I can do is this:

- have an (optionally) animated looping texture with frames following the +0blah, +1blah etc. convention, then change to a non-animated image with the +ablah naming convention, by setting frame = 1 on the bmodel.

What I'd like to do is have 4 different non-animated textures, and i can just swap between any one of these images.

I assume it's not possible without doing crap like having 4 seperate bmodels and hiding 3 of them (or I guess just using 2 if i abuse +0blah and +ablah).

Or is it?

Also I don't wanna use a .mdl 
 
yeah, you'd need multiple bmodels.
the frame stuff is hard coded, unfortunately and treats +0 ... +9 as a frame group, hence frame = 0 and 1 only. 
Ok Cheers 
I'll move to plan B which is to do the effect with sprites. Lighting won't be ideal, but i think i can get away with it. 
Lightning Bolts 
so, spawning a lightning bolt:

WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
WriteByte (MSG_BROADCAST, TE_LIGHTNING2);
WriteEntity (MSG_BROADCAST, self);
WriteCoord (MSG_BROADCAST, org_x);
WriteCoord (MSG_BROADCAST, org_y);
WriteCoord (MSG_BROADCAST, org_z);
WriteCoord (MSG_BROADCAST, self.enemy_pos_x);
WriteCoord (MSG_BROADCAST, self.enemy_pos_y);
WriteCoord (MSG_BROADCAST, self.enemy_pos_z);

no matter what i set the vector org to, it only spawns the bolt starting from the entity origin - basically the calls for setting the starting point are ignored - is that how quake works? 
Only If The Given Entity Is A Player, Otherwise It Works As Expected 
 
Ah I See 
sneaky, sneeaky quake :} 
 
note also that you can only have one lightning bolt per entity.

these days i build my lightning bolts manually out of edicts because every engine besides fq/qs tries to be cute and put in effects. :( 
Stealing Weapons 
What do I need to consider when trying to implement something like this:-

void() steal_weapons_use
{
other = activator;
if (self.spawnflags & SPAWNFLAG_SHOTGUN)
{
other.items = self.items - (self.items & IT_SHOTGUN);
other.ammo_shells = 0;
other.weapon = IT_AXE;
}
};

Or am I running in treacle here?

I can see it taking the weapon and the shells, but it breaks with an error in the weapon_cycle command. 
Activator's Other Self 
There seem to be three entities in this story, and I'm having to guess who is who:

self: presumed to be an entity added to the map as a trigger perhaps?
activator: if the above is correct then activator is whoever set off the trigger called self
other: known to be the same entity as activator

The first thing seems to be that other is unnecessary, which makes the function confusing. If we replace other with activator we get:

void() steal_weapons_use
{
�if (self.spawnflags & SPAWNFLAG_SHOTGUN)
�{
��activator.items = self.items - (self.items & IT_SHOTGUN);
��activator.ammo_shells = 0;
��activator.weapon = IT_AXE;
�}
};

We can then see more easily what might be dangerous. We only act if self has the spawnflag for removing shotguns. On that condition, we then set the activator's items to be equal to self's items with item shotgun removed. I'm pretty sure that this line should be referring to activator all the way through. 
Thanks Preach 
I didn't see the wood for the trees. 
 
don't know if you trimmed things out for clarity, but you should probably add a quick check:
if (!activator.flags & FL_CLIENT)
return;

just to avoid any possible problems in the case of monsters some how activating it. 
Spawn() 
is spawn() completely reliable? is there any time where it can fail and not create anything? or it creates an entity but the entity somehow gets lost? maybe if you're spawning many entities in the same think? 
Invalidation 
In the standard implementation spawn only fails if there are no free edicts, which produces a game-ending error. As long as it doesn't error out, it returns some entity and as far as I can see there's no way this entity could fail to be a clean slot. But that entity might be more familiar than it seems.

Edict slots aren't allowed to be reused with 0.5 seconds of an entity being removed from a slot*. However, if a reference to an removed entity persisted longer than that it could end up creating a reference invalidly relating to a newly spawned entity. Could a stale reference be somehow responsible for your issue?

*This is not true for the first two seconds of the map, in order to not waste lots of slots if entities are loaded from the map but removed by the qc straight away. 
 
right, i totally forgot about that! i still had that .doNotRemove trick from before and i found that the entity is indeed being removed by something else. thanks, i'm off to track that down. :P 
And 
it's done. thanks! turns out i had some sloppy linked list clean up. i was clearing out the list but forgot to clean up the head link. :P 
Not Qc... 
this is java, but it's more of a conceptual thing...

finally started working on the inheritance aspect of fgd files for my fgd<>def converter thingy...

essentially, i have multiple lists of objects which represent key/val pairs. these lists can have duplicate entries from base classes that an entity inherits from.

eg: you have 'monster_army' which inherits target/targetname fields from the base 'monster' class.

what i'd need to do is, on demand, collapse the multiple lists into a single one.
ie: when i 'get' a list element, i should iterate through a single apparent list:

monster_army has the fields: (inherits from 'monster')
0: B
1: C
2: D

monster has the fields:
0: E
1: C
2: A

should look like:
0: B
1: C
2: D
3: E
4: A

(duplicate C in 'monster' is ignored because 'monster_army' already had that field)

i can work through the logic of building a new list myself, but the problem is that there are many times where i need to iterate through the (final) list, so every time i .get(i), i'll have to rebuild this list which feels wrong.

is there maybe some more complex data structure that would work better for this? i'm thinking maybe trees due to their non-linear nature?
unfortunately, i've never really learnt data structures more complex than a simple linked list. :S

or maybe there's some absurdly easy solution and i'm just not seeing it. 
 
you should be able to get away without building the final list. I'd store the key/value pairs in a hash table instead of a list of key/value pair objects, and have an object for each "quakec class". then set up a recursive get() function which first checks the object-being-called's key/value pair mapping (e.g. Grunt), and if the requested key wasn't found, call the get() method on the superclass (e.g. Monster) (or return null if there is no superclass - so for a key requested that isn't in either Grunt or Monster).

something like this:

class EntityClass {
EntityClass superclass;
HashMap<String, Object> fields;

Object get(String key){
if (fields.containsKey(key)) {
// the requested key is stored directly in our class
return fields.get(key);
} else {
// the requested key is not in our class, try searching
// our superclass.
if (superclass != null) {
return superclass.get(key);
} else {
return null;
}
}
}

}

hope that helps..

btw here's the javadoc for HashMap.
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/HashMap.html 
 
If you're only storing the keys and no value with them, I'd recommend using a Set instead of a Map. You should read up on the Java collections framework, as in most cases it already solves a problem for you. 
To Lob Or Not To Lob, That Is The Question 
I have a Lavaman in my map (FMB_BDG) and he does a good job except I notice that there is a point where I can stand and the missiles go over my head. If I move closer, they hit me and if I move further away they hit me up to a point where they drop in front of me.

I can see that MOVETYPE_BOUNCE seems to affect the 'lobiness', and velocity_z seems to affect the height of the lob. What is affecting the gap between the hit range and the no-hit range? I am not too worried about the far distance as the missile falling short is not an issue because I can contain the player, but the over-me-'ead-john lob is not good.

If I change to MOVETYPE_MISSILE and ignore velocity_z I get a straight line missile a la roquette, but this is not good where the player is higher or lower than the Lavaman as dodging becomes too easy.

Are there any good web-sites that explain weapon behaviour (in short sentences with no long words, and mathematics that any four year old can understand)? 
Ericw++ 
This is also how I would do it. Note though that the keys will be unordered. If you need them to be sorted in some way, consider a SortedHashMap, e.g. TreeMap. 
Hash Maps 
I think everyone is right on Necros' problem that using sets/maps is the way to go, but I think that the implimentations so far have been backwards: So far we've had how to check if a specific element is a member of one or more sets, but what necros is looking for is the ability to list all the unique elements in a collection of sets, omitting duplicates.

The key to doing this is set union. Have a set of properties for the monster, a set of properties for the grunt. When it comes time to output the combined list, use the addAll method to create combined lists which omit duplicates. 
Lobbed Projectiles 
The most important mathematical idea for understanding projectiles is being able to imagine the movement in just one direction, to ignore all the other motion.

In particular imagining just how the height changes is important, but it's also the most difficult. It's also quite hard to deal with the idea of projectiles that can go north-south and east-west.

So lets just fix our boss facing north, and think about the horizontal movement of the projectile first. It turns out that the northwards movement of the projectile is exactly the same for MOVETYPE_MISSILE and MOVETYPE_BOUNCE. We fire it with some speed to the north, and it keeps going at a constant speed. Most importantly it takes the same amount of time to come in line with the player.

Now we can think about how the height changes. The MOVETYPE_BOUNCE has exactly the same behaviour as a falling player. Measure the amount of time the MOVETYPE_MISSILE takes to hit the player. If a player could fall from the height the projectile is thrown at down to the height of the target player in that time then the MOVETYPE_BOUNCE will score a hit, otherwise the shot will sail over his head.

So what can we do if it does sail over his head? Well, one trick is to start the projectile with a negative velocity_z, so it is already moving downwards. This will make it fall further during the flight and hopefully hit the player. Alternatively we can reduce the speed it travels north at. This will give a longer flight time and so longer for it to fall. We could combine these two ideas if needed.

Calculating exactly how much adjustment is needed is where you have an unavoidable level of fairly grizzly maths. I'm sure I wrote something about this particular problems but I can't remember if I finished it and ever posted it. You can probably get a good enough function by just measuring the threshold at which projectiles start going overhead, and applying one of the two above fixes when the player is that close(using trial and improvment to get values that work well). 
Thanks Preach 
So, with a zero velocity_z, does the projectile fall from the horizontal at a predetermined and constant rate i.e. no acceleration? And if so, do we (you) know what that rate is?

I'm just thinking that a series of If Thens could adjust the velocity_z and velocity to get to the target in the given time. (Not sure what the player would think of that?) 
Basically 
z is a parabolic function, depending of initial velocity, the initial direction/angle and the weight of the projectile, so to say gravity...
x and y can be linear it eases calculation, unless you want to add some wind effects, etc..

Wikipedia gives some mathematics clue for this: http://en.wikipedia.org/wiki/Trajectory

Experiment ! 
Gravity 
JPL is right that it's not a constant rate, it's an acceleration, and the easiest way to understand it is to experience it in-game. Because gravity affects players in the same way as bouncing missile, you can see exactly how it changes just by falling. In particular if you go on ziggurat vertigo then you can see the change in speed happen in slow motion, which makes it easier to gauge. The next paragraph is optional mathematical detail:

Standard quake gravity is 800 units per second per second. What that means is that after 1 second of falling (from rest) a projectile will be travelling down at a velocity of 800. After 2 seconds that speed has reached 1600 and so on until it reaches the maximum speed the engine allows (which defaults to 2000 units per second I believe). The speed increases smoothly, after 0.5 seconds the projectile has velocity 400 and so on, but this constantly increasing speed means that position changes irregularly.

Despite that, we can use approximations here. The trick is to restrict ourselves to a controlled case. Work out the distance at which the shots are missing the player, and only apply this approximation within that range.

Since we know that the shots we are correcting are close range, we can assume the flight time will be 1 second or less. We can then approximate the falling motion of the projectile as a constant speed of 400 units per second*. Based on that we can do some fairly simple calculations based on the relative height of the player and the projectile's start location. If these differ by more than 400 units then add the difference to the velocity.

The important thing is to get that typical flight time right for the shots we want to correct, detect when we're in that case and then issue appropriate corrections. If my guess at the timescale is wrong please let me know and I'll recrunch the numbers.


*This certainly looks like I just averaged the starting speed of 0 with the final speed (at 1 second) of 800. I will be belligerent and claim I actually performed an integral of the accelerated motion to discover the exact distance a projectile covers in 1 seconds, the answer being 400. 
Experimenting... 
Well, the first thing I did was to manipulate velocity_z, with so-so results. However, by just thinking a little less, and velocitising a bit more, I found a figure for velocity that covers the distance perfectly, whilst still providing an obvious 'lob' effect. The only downside is that if you get too close, you do not really have time to get out of the way.

Still, given that the player starts off x distance from the Lavaman, which IS a dodgeable distance, and given that he does not HAVE to get closer if he does not want to, I may just reduce velocity a bit according to the distance to target, and settle with what I have.

It's not that I don't want to do the maths, it's just that this is just one monster in one scenario for my final Quake map.

Thanks Preach and JPL for the guidance. 
 
wow thanks to everyone for pointing me towards those other data structures.
looking around, it seems like LinkedHashSet is the way to go as it is supposed to be only slightly slower than a HashSet (but not as slow as a TreeSet) and preserves the order based on when they were added.

I don't think the Map interface is what i need, since i'm storing more than just a relation between a key.
FGD has many extra bits for key/vals including data type (Target/TargetName/Integer/String/Choice) along with (if a choice) the individual choices as well as a default value (if any), so all that has to be in there, but i'm only interested in the key's name when building the list (as that's how i want to determine if it's a duplicate or not)

anyway, i'll throw some more code at the problem and see what happens! 
Reaction Time 
One of the interesting things about projectiles is that for a fixed launch speed there are two angles you can fire them to land at a given range*.
http://en.wikipedia.org/wiki/File:Ideal_projectile_motion_for_different_angles.svg
The above illustrates how that works, but the reason I raise it is because the high lobbed shot, which I think of as the less obvious of the two paths, has a longer flight time. The difference is greatest on the shortest ranges.

This would be a great solution to giving the player enough reaction time. It also would be good at lobbing over any cover between the player and monster, which might make the combat more interesting.

There is however a price to pay, and that price is the need for greater computation. Essentially when you fire on a low trajectory you can land a lot of hits even without getting the range very accurate, because the horizontal line of the attack will usually intersect with the player somewhere. When you go for the tall lob shot your attacking line is much more vertical, and so you need to get the horizontal spot on.

How that would go would be:
� Calculate the vertical range to target h.
� Compute the time to drop to height h:
http://chart.googleapis.com/chart?cht=tx&chl=t=\frac{600%2B\sqrt{600^2%2B2\times800h}}{800}
(here 800 is gravity and 600 is our intended upwards velocity)
� Calculate the horizontal range to our target x
� Divide x by t to get the horizontal velocity v

We now need to make a vector with length v moving towards our target in the horizontal plane:
d = self.origin - self.enemy.origin;
d_z = 0;
d = normalize(d)*v;
Finally we set d_z = 600 and off we go!


*except for maximum range where the two solutions converge on 45� 
Necros 
I seriously doubt that you need to worry about performance in your app. Or am I wrong? Also, if you have more data, you can store an object that represents that data in the hashmap with the name as the key. That's the usual approach anyway. 
 
re 707: in doom3, you can see that happen sometimes with hellknights. they usually use the more horizontal trajectory when throwing their fire balls, but occasionally, they'll toss one way up into the air.

re 708: yeah, you're probably right about performance. anyway, managed to get it working in a quick hacked up way. i store keyval lists as arraylists on the entity definitions, but when i call the get method for a keyval index, i build the linkedhashset each time out of all those arrays.
works well for now even though it feels like this is wrong... like i should be storing all the keyval lists as linkedhashsets and using .addall. 
Target Match 
I guess the main problem is not to obtain the parabolic curve, that can be even coded very simply like an exponential code (i.e x = x/2 or x = 2x). no I guess the challenge is rather to be able to obtain the projectile to perform direct hit to the player (if not moving). in order to achieve this, a reverse calculation is required: you know player position, monster position, projectile weight, hence it is possible to determine velocity and angle to apply... that could be very interesting as more realistic ;) 
 
did this a while ago.. it was supposed to be for a leaping monsters and would trace the parabolic course in increments via a while look and tracelines so check if the leap parabola was clear...

traceFraction = 0;
while(traceProjection <= 1)
{
traceProjection = traceFraction + 0.25; //project the trace. will make for 4 traces.

local vector trace_pos0, trace_pos1;

trace_pos0 = self.origin + ( (dir * (hdist * traceFraction)) + ( '0 0 1' * ( ((vtime * 400)*(vtime * traceFraction)) + (0.5 * (vtime * traceFraction) * (vtime * traceFraction) * -800) )));
trace_pos1 = self.origin + ( (dir * (hdist * traceProjection)) + ( '0 0 1' * ( ((vtime * 400)*(vtime * traceProjection)) + (0.5 * (vtime * traceProjection) * (vtime * traceProjection) * -800) )));

traceline(trace_pos0, trace_pos1, 0, self);
bprint (vtos(trace_endpos));
bprint (" -> ");

if (trace_fraction < 1)
traceProjection = 1000000; //cause a break

traceFraction = traceProjection;
}


dunno if that code is 100% correct... or even helpful. :P 
Necros 
I guess what is interesting is not that much the result, but the logical reasoning you made to obtain it ;) 
 
oh sorry yeah, should have explained it a bit. :P

you'll notice there's two vars, traceFraction and traceProjection.

these should be only values of 0 to 1.

next is trace_pos0 and trace_pos1.
we determine these points by using that physics formula that describes position relative to time with an initial velocity and taking into account gravity. (i subbed 400 in to any 'g' variables, which, sorry to say preach, i figured out totally by guessing... ^_^;)

this is where traceFraction and traceProjection come in. if you look at the first line of the loop, traceProjection is always 25% ahead of traceFraction.
trace_pos0, then, is the origin of the traceline and trace_pos1 is 25% ahead through the trajectory.
incidentally, you could increase the 'resolution' of the trace by decreasing 0.25 to 0.1 or something to get 10 iterations instead of 4.

if you can imagine a typical parabolic trajectory, what you're doing in that code is tracing a line, first, from the starting point to 25% into that trajectory.
then, from there, tracing another 25% forward to the middle of the trajectory, etc etc.
if at any point the traceline fails (trace_fraction < 1, ie: something blocked the trace)
then we break out of the loop and notify the rest of the code what happened.

basically, i turned quake into a really crappy 3d graphing calculator. :P 
 
oops, there was additional information i forgot about (i wrote this years ago so i forgot how it works! :D)

this is the start of the code (before that loop):

epos = self.enemy.origin;
//epos = self.enemy.origin + dir;

zsep = epos_z - self.origin_z;
dist = vlen(epos - self.origin);
dir = epos - self.origin;
dir_z = 0;
dir = normalize(dir);

if (zsep > 64) //player is too high, forget it.
return;

temp1 = epos;
temp1_z = 0;
temp2 = self.origin;
temp2_z = 0;
hdist = vlen(temp2 - temp1);

if (hdist > 768) //player is too far, stop
return;


if (hdist < 440)
{
hspeed = hdist; //do a 1 second jump.
vtime = 1;
}
else
{
hspeed = 440; //max out at 440 horizontal speed and jump higher to compensate.
vtime = hdist / hspeed;
}


i guess the important things is noting that dir is a flattened normalized vector towards the target and that vtime is the amount of time we want to spend in the air. 
Necros 
Oh, I see, you made it like a move forward, rotate, move forward, rotate, etc... like polar coordinates or (better) vectorized move: interesting, I was not thinking it was possible doing it this way actually ;)

And thanks for the explanations :) 
PHP Is Kicking My Ass At The Moment 
The sooner I can get my assignment finished, the sooner I can get back to mapping :)

This bloody search_array thing is kicking my ass. Trying to use php to search an array of info. Its a multi-dimensional array. I swear I have looked all over for a solution and have had no luck.

http://www.php-forum.com/phpforum/viewtopic.php?f=2&t=17353 
No Php Guru 
But the search_array func probably isn't built for multi dimensional arrays. Seems to be versions of that in the comments of the search array in the php docs:

http://php.net/manual/en/function.array-search.php 
Yeah I've Been Sifting Through That 
I dunno, it seems I'm just not getting something.
I think it's to do with the way I have my array. Which is awkward because It's just the way it comes from the XML file. Blerg. 
Oh God... 
Xml...*shudders* 
Yeah I Know 
Any sensible person would design a DB in MySQL, but we are not allowed to use MySQL (go figure?!) - which sucks because any real-world application would use MySQL or SQL or even .net + access or whatever, but 'noooooo', not my retarded course. php + XML is the recipe of the day. Fuck it, I guess I'll learn something at the end of the day ... 
Dude 
ditch array_search and iterate through the arrays manually. It's pretty simple. 
Could You Perhaps Show Me An Example Of A Loop? 
I can handle a stupified approach, I just wanna get a fucking A. I don't care if I have to re-design my data structure completely, I have been thinking about this for far to long now and my brain hurts... 
 
Hey, XML can be fun and it is quite simple if you use a good parser. seriously! 
 
I enjoy the transition from, "Stupid class, can't use a database, have to use XML, *grumble*" to "can you show me an example of a loop?"

Walk before you run, Ricky. :) 
Ricky 
If you don't know what a loop looks like, how can you expect to get an A in a programming class?

Here is an explanation of the most important loop constructs in PHP:
http://nefariousdesigns.co.uk/loopy.html 
Lol - I Do Know What A Control Loop Looks Like 
However that is a rather good reference!
Thanks :)

I don't really know that many types of loop, just while loops and for loops.

I think I'm getting somewhere with it now, I used the following bit of code to remove the extra level of array which was preventing me from being able to use the array_search function:

$b=$a['Rrestaurant'];

Dumb, huh? I thought I was going crazy!

Also - I WILL get an 'A'. I could have done the lame thing and just planned a static website. The level of the course is not so high that I have to do a PHP website, but I really want to learn some programming, so I set myself the challenge.

August last year, I had never coded anything really, since messing around with BASIC like 15 years ago.

Now I have coded a text-based version of minesweeper (which is 200KB, fuck)(the second half of the assignment will be probably a discussion of how I can use functions to simplify my code).

And this flippin XML/PHP project. You've got to start somewhere!

But seriously, thanks again. 
Success! 
OK, so now that I've figured out how to access my arrays within the array that was within an array, and started iterating through it manually with my loops, I'm having success :)


$search = 'the';

$resultsCounter = 0;

function object2array($object){return@json_decode(@json_encode($object),1);}
$xml = simplexml_load_file("places.xml");
$a = object2array($xml);
$b=$a['Rrestaurant'];
$count = count($b);
for ($x=0;$x<=($count-1);$x++){
$c = $b[$x];
$d = $c['Rinfo'];
if (strpos($d,$search)) { echo $c['Rname'] . '<br /><br />' . $c['Rinfo'] . '<br /><br />' . $c['Rindex'] . '<br /><br />'; $results[$resultsCounter] = $c['Rindex']; $resultsCounter++; }
}
$count = count($results);
for ($x=0;$x<=($count-1);$x++){
echo $results[$x] . ' ';
}


I'm sure that's probably pretty hideous, but its giving me nice search results :) :) :) 
Doh! 

$search = 'the';

$resultsCounter = 0;

function object2array($object) {return@json_decode(@json_encode ($object),1);}
$xml = simplexml_load_file ("places.xml");
$a = object2array($xml);
$b=$a['Rrestaurant'];
$count = count($b);
for ($x=0;$x<=($count-1);$x++){
$c = $b[$x];
$d = $c['Rinfo'];
if (strpos($d,$search)) { echo $c['Rname'] . '<br /><br />' . $c['Rinfo'] . '<br /><br />' . $c['Rindex'] . '<br /><br />'; $results[$resultsCounter] = $c['Rindex']; $resultsCounter++; }
}
$count = count($results);
for ($x=0;$x<=($count-1);$x++){
echo $results[$x] . ' ';
}
 
Now Try: 
some better variable names and have a look at foreach 
Yeah 
Don't call variables 'a' or 'b' - give them a name that reflects their meaning in the program. 
Ah - Good Idea. 
$wholeArray
$wholeCumbrianRD
$wholeRrestaurant
$wholeKey
 
Craving Your Indulgences Again 
I don't do much qc but whenever I do I find myself running into brick (BRICKL_0 or similar) walls.

I have a procedure that I want to run x times as selected from the editor (self.something = x). I want to say along the lines of:-

void () Proc1

do some stuff

while (self.something >0)
do this
wait random y to z seconds
self.something = selfsomething - 1
ewhile
do some other stuff

endproc

(I know I am mixing languages, I am just trying make it look obvious what I am doing)

When looking at 'think' and 'nextthink' examples, they all seem to act on an external procedure/function before returning to the calling procedure/function. I also see use of recursion i.e. a procedure/function calling itself.

Is it necessary to use 'think' and 'nextthink' for timing purposes in my ditty above or is there some other construct available. If I need to use 'think' and 'nextthink' is it therefore advisable to separate the 'while/ewhile' (or whatever loop is used) into its own proc/func? 
 
you are thinking about it the wrong way.
best to think about what gets done in a frame and what doesn't.

nextthink and think is what you need to delay over multiple frames.
doing a while loop will do everything in the same frame.

in this case, you don't want a while loop at all.

void() proc1
{
//some stuff here

self.think = proc1; //run this again
self.nextthink = time + (some random amount here);
}


the way nextthink works sort of is that the engine looks at what nextthinks are > current time and when they become < current time, the engine sets nextthink the 0 and runs the .think function with self as the 'thinking' entity. 
Necros 
So the engine is not waiting for my procedure but it will have my 'thinks' queued up? Also, do I not think of this a true recursion?

By the way, I just ovelayed the draflam2.spr with the bigexp.spr (just via an entity choice in the editor and using two entities) and it looks pretty smart. I am not sure what it will look like to a player seeing it for the first time in a game - you know how fussy Quake people are :) But it looks good enough to blow the head of a Vermis! 
 
no, it is not recursion.
recursion is when a function calls itself.
you can accomplish this in qc with the usual method:

void() proc1
{
//stuff
proc1();
}

this also does everything on the same frame, just like for and while loops.

when you use thinks, it is the engine that is calling the function when nextthink ticks by.

for the explosion, if you're feeling adventurous, you could try throwing a bunch of MOVETYPE_TOSS invisible entities out of the explosion point that spawn explosion sprites themselves. ;)
looking forward to seeing it. 
Queuing 
To add, there is no queue with think functions, you only get one. So if you have code like

self.nextthink = time + 0.5;
self.think = CleanTheDishes;

self.nextthink = time + 2;
self.think = CookDinner;

the second think function overwrites the first one and so you end up eating off dirty plates. One way to fix that is to move the code which sets up CookDinner into the CleanTheDishes function, chaining the functions one after another.

This worked because our two functions were dependent. If you need your entity to think about two independent things one solution is
to have a master think function. This should think regularly, and check timers on your entity manually. The way that playerprethink and playerpostthink handle powerups running out is an example of this pattern.

If that's too complicated, the other way is to have two separate entities, as each one has its own think function and nextthink timer. 
Preach 
Nice analogy; because we don't want to be eating off dirty plates now, do we?

It is falling into place, so thanks. 
QCC 
I have been compiling my own progs.dat file using the tools from the ID FTP. Is there a good base of .QC files? Has the community got an agreed on base? Any recommendations? Something to start from? 
All Can Be Found Here: 
Door Key Use Sound Troubadour Verily 
Ok, this is fairly what-the-christ.

So, I'm running around my mod opening doors with keys. Use a key, door opens - it just plays the door open sound. I'm thinking hang on...didn't it used to play a "use key" sound before when it opened?

I then check vanilla quake. But no, even playing vanilla quake - no mods - key doors are only making the door open sound when they open.

I look in the QC - vanilla QC - the door is *trying* to make a "use key" sound, but it's immediately getting overridden by the "door open" sound (same channel). Looks like that's how it behaves all the time. So, another id bug to fix then. But why do I have a very clear memory of hearing the use key sound in vanilla Quake??

And more creepily, why did Scampie hear it on some compiles of his map, but not on others??

What is this door devilry?? 
 
sock: and definitely use a new compiler.
you can use more c conventions like for loops and increment and decrement operations.
also removes arguably useless stuff like needing semicolons after function braces.

kinn: not sure, but maybe because czg's progs from his last map pack had a fixed variation where the key sound plays and the door opens after a short delay? 
More Door Bollox 
ok, so i've fixed the key use sound thing, and also for visual effect added a small delay between the key being used and the door actually opening. This introduced me to something that I never knew anything about before. Namely this:

in door_touch, if I replace the call to door_use(), with:


self.nextthink = time + 1;
self.think = door_use;


The door actually opens after about 10 seconds, not 1 second. (whu?)

if I write:


self.nextthink = self.ltime + 1;
self.think = door_use;


The door opens after 1 second, as expected.

do doors play by totally different rules when it comes to time and nextthink shizzle? 
Hah 
wrote that before seeing necros' post :}, didn't know czg did this but maybe that's where i'm remembering it from... 
 
preach made a fantastic post about this explaining how nextthinks work on MOVETYPE_PUSH entities:
http://celephais.net/board/view_thread.php?id=60097&start=330&end=330 
Append /\ 
also of note, setting .velocity on a MOVETYPE_PUSH entity without setting a .nextthink will do nothing.

.nextthink must be set higher than .ltime in order for the engine to update position based on .velocity 
Compilers 
@rj, thanks, I am still learning where everything is hiding! :P
@necros, I got the qcc compiler from ID and it would not work under 64win so I got hold of FTEQCC instead. The original ID files produced a ton of warnings and crap messages. I don't suppose any of that has been cleaned up and a new qc pack of files is anywhere? Or should I not worry and just add my own stuff to the pile?

Are there any QC libraries? Luckily czg released his source so I can see how he did the trigger spawn routines. Is there other things that everyone uses? 
Necros/preach 
thanks, that was useful. Preach - never stop quakeing, you are an asset.

So, from what I gather, because time was not advancing from the door's point of view, when I set self.nextthink = time + 1; it still had a self.ltime of like 0.1 or something, so the "ten second" delay i mentioned earlier was basically due to however long the game had been running up until that point + 1 second. lol.

Funny that I'm still learning new things about quake, but then again I've never dicked around with push ents before, which is why i've never come across this :} 
Sock It 
Sock: http://www.btinternet.com/~chapterhonour/clean%20source.zip ought to be handy.

It's my cleaned out copy of the qc source, only for the purpose of defeating all those warnings. I might have made some other minor tweaks but I'm pretty sure it's faithful to the basic game. The only real compromise I added to it is a pointless, vestigial function at the bottom of DummyFunction which defeats the warnings about .wad and .light_lev not being used in the progs, even though you must define the fields. 
Broken Link 
@Preach, that is awesome what you have done, but I can't get the link to work? 
Arrgh 
Forgot to test the link, turned out the ftp failed because the server dislikes filenames containing spaces. Renamed to
http://www.btinternet.com/~chapterhonour/cleansource.zip 
Awesome 
Thanks Preach that has saved me a ton of effort trying to work out what is my mistake and what is broken already. 
Not Sure If This Has Been Covered Before... 
if i have two entities, one with .nextthink = time + 0.01 and another with .nextthink = time + 0.02 will the order the thinks occur be based on nextthink or just the order the entities are stored in the list in the engine?

my gut tells me it's the latter, and that makes me sad. :( 
 
didn't say, but it should be obvious, i'm assuming the next frame will be longer than 0.02 seconds after. say 0.1 seconds after to be clear.

time = 0
->a.nextthink = time + 0.01;
->b.nextthink = time + 0.02;
time = 0.1
a fires first, guaranteed? or it might be a or b based on it's position in the list.

i should think before i post. -_- 
You Are Correct 
If the frame takes longer than 0.02 then it is strictly in the order that the entities appear in the entity list.

Interesting fact though, say that instead we start at time 17
a.nextthink = 17.01
b.nextthink = 17.02

Now at 10fps the next frame starts runs at server time 17.1. However, during the think function for "a" time will be set to 17.01, and during the think function for "b" time will be set to 17.02. This change literally applies only to the QC variable, not to anything else in the server.

Back to the original problem, a lot of the time with the think intervals that you have chosen players today will see a think before b because the cap on fps is 72, which is high enough for a frame between 0.01 and 0.02. Beware of the effect in the previous paragraph though, if you are setting the nextthink values from within individual think functions for "a" and "b" it may not be the case that
a) b.nextthink - a.nextthink = 0.01 (even accounting for floating point error!)
OR
b) that b.nextthink won't occur in the next frame!

That second one needs a bit more explanation and in particular would benefit from concrete figures. We will say that the server issues a frame every 0.014 seconds.

Frame i:
server time = 17
b.nextthink = 17.003
Frame ii:
server time = 17.014
b's think at 17.003 executes and contains the qc:
b.nextthink = time + 0.02;

Since the engine sets time = 17.003 during the think, we now have
b.nextthink = 17.023
Frame iii:
server time = 17.028
So b executes a think in consecutive frames!

If you really need execution in order you might have to concoct a "priority queue" style system, with a new fakenextthink field. That would mean a linked list of entities so that the following pattern holds:

self.fakenextthink <= self.nextent.fakenextthink

You insert into the queue by traversing the list until your fakenextthink is <= the next fakenextthink. Finally you'd need a function that runs from startframe and traverses the queue, running fakethink on all the entities which are due. Since the queue is in order of fakenextthink, they run in the desired order and as soon as you reach one which is not yet due to run, you know you can stop traversing.

Two tips: firstly don't forget to purge the entities from the queue before you fire their events! It's very likely that entities will want to reinsert themselves into the queue from their own fakethink calls, so you need to be aware of that. Secondly, I'd keep up the practice of setting time = fakethinktime for the duration of the fakethink call (then you MUST reset it to evaluate the next entity on the queue).

These two tips combine for an interesting effect: you can have multiple fakethinks occur in a single frame, since they get reinserted into the queue with a fakenextthink that might still be lower than the server time. I suppose to be sure of correctness we need to make sure the loop of execution is less traversing the linked list, so much as always looking at the head of the list and popping it if execution time has arrived.

I have another use for this priority queue in mind which is less technically involved and more generally applicable, so I might go away and write it up with some nice complete code over the weekend...until then! 
 
thanks for confirming that for me. i was looking at the engine source, and that was what it looked like, but i'm not familiar with it enough to be sure.

i do remember the bit about time being set to nextthink time on think calls. i've used your 'servertime' workaround often because of it. :)

as for making a fakethink sorted list, i thought of it, but i only have one bit of code where it would be important, and it felt like it was better to just solve the problem by working around it rather than making the whole fakethink system.

thanks! 
Sounds 
Is it possible for one entity to affect (stop) the sound of another entity e.g by forcing a null.wav to play on that other entity's channel?

I have just noticed on an old map of mine that when the player dies the music keeps playing, which seems wrong to me. I thought I might just be able to drop a 'sound' line into Player DeathSound to say kill the music, then carry on and play whichever death sound you want. But I do not know how to use the sound(self,...) parameter to point to a specific entity.

Alternatively, could I stop all sounds just before playing the Player DeathSound? 
Mike: 
instead of "self" in that sound call, use the name of another entity. 
 
(i.e. the entity that you want to silence) 
 
also of note: make sure you play that sound with 0 attenuation to make sure it is 'heard'.
if you are outside audible range, the engine won't even bother registering the sound and so won't interrupt a previous one playing on that channel. 
Sounds, Part The Second 
metlslime: thanks, once I realised that I needed to add the entity name to ALL parameters, we wuz cookin' on gas.

necros: it's in the form of:
sound (self, CHAN_VOICE, self.noise9, self.volume, self.distance);

where 'noise9' happens to be the null.wav, and everything else is already set from within the original entity's entity definitions.

It works just fine now: music stops, player does his death sound and dies gracefully, monks start chanting a dirge - I keep allowing myself to be killed because I find it ever so slightly amusing :)

(One day, I'll get the hang of this .qc stuff) 
 
concerning c++
i've been messing with that fake GI hack with MH/Aguirre's light and the main block right now is integer precision...

specifically, in order to get better results, i need to add more suns. the more suns i add, the brighter everything gets.

i'd need to use a light level of maybe 0.5 or less.

unfortunately, everything's in ints.

how hard would it be to convert everything to floats and would that markedly slow down light calculations?

is it even worth doing? :P 
Heh... 
so... i posted that and then i just thought of a better solution (albeit, one that's way more hacky).

i was thinking i could assign all sunlight a different light style and then give it a light style of z to n instead of m... 
 
yeah, that didn't work that well. :P 
Holy Lmaps Batman! 
Out of interest - what are the performance implications of using styled lights on that sort of scale? 
Basically None 
All lights in quake are styled, you can see the code which sets the styles in the worldspawn function with. Performance costs are only incurred when the style changes, either due to an animated style (multiple letters) or calls to lightstyle to alter the style.

Incidently there's a trick to making easy lightning effects relating to this. Lighting tools put all the sky lighting on style 0, but we can see that it's possible to alter the levels of style 0 in the same way as other styles. If you put all of your static, sourced lights on a different style, you can reserve style 0 exclusively for light from the sky. Then you can quickly switch the style to intensity "z" to create a flash of lightning while keeping indoor lighting constant. 
Well Damn 
I know what I'm gonna be doing now!

Cheers. 
 
Incidently there's a trick to making easy lightning effects relating to this./q>

that works ok, but tends to look a little boring because the shadows don't change. it's also annoying because you have to remember to set all your normal lights to a style other than 0. although, i guess you could code up your qc to default to another style.

i'm currently trying to haxor in mutliple 'lightning' suns so i can get fake varying lightning strike positions. i'd leave the lightning suns 'off' and then flicker them on when needed. note that you could only have max 3 of these because 4 is the max number of styles allowed. :(

sadly, i know nothing about c++, my only experience being with java which does pointers automatically and seems, overall, a lot simpler, so progress is slow for now. 
 
awwww 
 
it's also annoying because you have to remember to set all your normal lights to a style other than 0. although, i guess you could code up your qc to default to another style.

I don't think qc will help you; styles have to be set up in the map file (either "style" or "targetname" on each light entity) so that light.exe knows about them. 
 
oh that's right. ouch. 
Control 
I'd edit your fgd/def file to make other lights default to a different style. I'll admit I've not tried it, so maybe the effect isn't all that dramatic. It sounds like it's one of those things where you could get a good effect in the bsp format, but that maybe the tools for it aren't quite there yet... 
Touchy Triggers 
is there some kind of bug where triggers touching each other can cause a touch function to run on the other trigger?

ex: trigger A and trigger B are touching.
player touched trigger A, trigger A and trigger B both run touch functions. 
 
Sounds like you forgot to set the trigger_dont_link flag. 
 
you're thinking about door_dont_link.
this happens with just normal triggers. 
Joke; Didn't Work 
 
Shape 
Any chance that it can be because the trigger brushes are oddly shaped, and the resulting bbox shaped triggers end up coinciding? Never heard of an effect like this before, might have to take a look at the map to figure it out.

Another tool that I've only recently begun to use is the pair of builtins traceon and traceoff. Calling the former means that all the QCasm instructions get printed to the console until you call the latter. It's about as close as you can get to a debugger for QC, and a lot of the time it's much quicker than adding a bunch of dprint statements to nail down a bug. Putting them round the touch functions might be helpful. 
 
this actually happened in ne_ruins.
it's in that little corridor between the two maps, in the start map, there are a couple of triggers that get fired depending on flags (ie: just entered the map or returning).
except they were both firing until i spaced them 1 unit apart.

i'll have to try out those builtins... 
Re Traceon/off 
yikes... that's a LOT of output.
it'll take some time to get used to reading this.
i suspect it'll be best to turn it on and off sparingly. 
Deluge 
Yeah, it's not something that you want on functions running many times a second,it might be necessary to turn it on right after the basic touch rejection code. The thing I found it best for was when I have a function with lots of if branches, and needed to work out which ones it was taking or rejecting. 
Unsolicited Advice 
Suppose that you are writing a mod which other mappers will use, and you want mappers to be able to control a parameter. In this post I will use corpse-duration in a corpse removal system as an example. Traditionally if you wanted a global property then you would add a field to worldspawn to set it.

Apart from it being a bit of a waste to add a field to every entity which is only ever read from worldspawn, I think there is a better pattern, which is a bit more powerful. The key use-case is a property which a mapper might want to vary as well as set initially. Corpse lifetime arguably fits this criteria, for example: during a large horde combat you might want to remove corpses faster than the rest of the map.

My suggestion is to create a new entity function as follows:

float corpse_duration;
void() set_corpse_duration =
{
��corpse_duration = self.count;
��if(!self.targetname)
����remove(self);
}


Then the way to set the corpse_duration initially is adding a point entity with classname set_corpse_duration and count equal to the desired duration.

Can any of you keen entity hackers see how we change it dynamically? Well, we set up an entity with the desired count, but with "classname" "info_notnull" and "use" "set_corpse_duration". If we set a targetname then every time we trigger this entity it sets the corpse duration. If you want to codify it as less of a hack you could invent a new classname for this kind of entity like set_dynamic_property, but it doesn't need any supporting code.

The remove(self) bit of code is a bit ugly, but it makes sure that initially setting the property doesn't cost you an entity, yet the info_notnulls can be used multiple times. 
Mismatched Flags 
I am trying to query a monster to see if the current enemy has an artifact enabled. I am using (self.enemy) and I checked to see if it a player. I query the flags (self.enemy.flags) and it does not show the player flags properly. I tested this by using an artifact routine (void() powerup_touch) to print to the console what it was doing and it produced a different flags value.

I double checked the classname field and other player variables and it is certainly looking at the same entity, except the monster query will not show the content of the flags correctly.

Is there something strange about queries with the player flags? 
 
what value are you seeing? how are you querying for flags? flags must be checked via bitwise operation (self.enemy.flags & FL_CLIENT) will return 1 (true) for the player.
are you saying you do the above operation and it returns false when the monster is angry at the player?

also note that players gain and loose flags a lot during play, godmode, notarget, onground, partialground... 
Fixed 
I was mixing up .item and .flag queries. I was too tired to see the difference and could not understand why. doh! 
Ideas/tutorials For Useful Entities... 
to add to progs.dat.
I'm quite the noob when it comes to coding.
Included misc_model entity from a old tutorial, but that was just copy/paste and compile.

For example i would love to have such swinging door's/ pushable func_rotate things like in ne_ruins.
Googled, found no tutorial for that yet, and dont know what other stuff could come handy.
Suggestions? 
Inside3D Is The Place For Everything QC 
They have a forum and a set of tutorials on the site.

necros code is a different matter. I think it's part QC and part evil arcane magic, or something. 
QC Beginnings 
For example i would love to have such swinging door's/ pushable func_rotate things like in ne_ruins.

If this is your first foray into QC I would forget all that stuff and just start small. Most of the QC tutorials you can find online are the "make a grunt shoot rockets"-type stuff but they will help you learn the basics.

The sort of stuff necros does (pseudo-physics movers and whatnot) is not going to be achieved with copy and paste. 
 
this is from last year, but i haven't really done much to the pushable rotaters since then anyway.

http://necros.slipgateconstruct.com/temp/ne_rotation_pushableRotaters(17.12.11).qc

i doubt it will work by plugging in, and it should be obvious it requires the hipnotic rotation code, but you can at last see what's going on. it also needs a lot of work still-- there is no implementation for other axis of rotation because those must factor in gravity.

overall, the concept is pretty simple: the movewalls have a touch function now that takes the speed that the player touches them with and dumps it into the rotators which then decays that speed over time. there's more to it of course, like translating velocity into angular momentum and such, but i'm not going to explain the whole thing. i think i've posted about it before, but i forget where.

for coding qc:
knowing about unit vectors, dot product, normalizing vectors, reflection, etc... (but you can always google this stuff up and learn it on the spot if you are not averse to that)
if you know some physics, that can help too, but you don't need to be a rocket scientist. (wow, when will that saying get old? maybe it already has...) 
Thx Necros & Negke 
for the code & link.
Looks very complicated for me, but the concept sounds logical, hopefuly i will learn enough about qc to understand the code eventualy.

Let's see what i will find on inside3d :D 
 
um.. what is trace_plane_dist?
the name implies it's the distance to the plane it hit, but after testing, i was seeing very strange values being returned, some in the thousands from a short 80 unit trace. 
 
a bit more testing... seems to be the distance from the origin based on the axis of the plane, so a trace on a face on the y/z plane returns distance from origin along the x axis.
non-axial planes returns strange values, some kind of combination of the different axis based on the slope of the plane? 
It Is Probably The Plane Distance Using The Plane Normal 
http://mathworld.wolfram.com/HessianNormalForm.html
You can define a plane in 3D space using its normal vector and distance from origin (in the direction of the normal) 
 
thanks for clearing that up. :) 
 
is there any way to 'reset' frame aliases back to 0?
or is making a new qc file the only way? 
Compiler Extensions 
QTEQCC supports resetting the frame aliases using

$framevalue 0

(literally, the keyword is framevalue)
The need to make an extension suggests it can't be done normally. 
 
you mean fteqcc?
anyway, thanks. :) 
Centerprints 
What is the maximum centerprint length?
Does it matter if you use the extra centerprint that allows multiple arguments?

Fitzquake has a bug that allows longer centerprint strings, but Quakespasm 'fixed' this, so that strings that display fine in Fitzquake spam the console with errors and truncate the string in Quakespasm.

:( 
Centerprint Article 
http://www.inside3d.com/qip/q1/qcenhanc.htm#centerprint

From the page :
* The maximum number of characters in one string or multiple strings printed at once is around 2000.
* The maximum number of characters per screen line is 40, independent from the current resolution.
* The maximum number of lines per screen is 13, as more will cause weird problems in 320x200.

The links says max 2000 chars but 13 lines of 40 characters is 520 total. I assume Quakespasm is not liking those above limits? 
 
I brought this up before, and iirc, the 'limit' was actually higher than it should be. Apparently, the centerprint had some kind of unchecked thing which allowed strings that were too long to go through and it was only through luck that data wasn't being corrupted somehow. (and probably why it was never noticed?). 
Bizarre Problem... 
I've got a bmodel with MOVETYPE_PUSH and SOLID_TRIGGER that moves via velocity.
Normally, I can be inside this entity when it moves.
For some reason, if I touch a rotate_object (which has no touch function, is MOVETYPE_NONE and is SOLID_NOT), the moving trigger bmodel becomes blocked! (it runs it's .blocked function too).
It's the weirdest thing ever... 
Reproduction 
This sounds like it might be quite a specific problem and so hard to reproduce, can you e-mail me a map/progs that displays the behaviour? 
Solution 
This might be a little opaque for anyone outside of me and necros.

The engine code underlying this problem is quake's blocking detection system. It's crude to the point of being technically incorrect, but infrequently enough that nobody has cared - before now. When a door moves, each entity is tested against the door:

Is the entity within the bbox for the door?(i.e between its mins and maxs, not exact intersection) If not move on.
Is the entity currently stuck? If not move on.

At this point the code attempts to move the entity the same distance as the door moved, in the hope this pushes it clear.
To see if it worked, we test again if the entity is stuck.

If it is stuck, we declare the door blocked and revert all the movement for this frame.

The flaw in this system is that we only test if the entity is stuck, not if it is stuck in the door. You can test this with a map with a func door which encloses the player without touching them in any way, combined with a solid brush which impales the player inside. The door will crush you without ever making contact.

Here endeth the general lesson. Specifically for necros: Your post missed something important out, the func_pressureBolt is MOVETYPE_FLY, which apparently causes the player to count as stuck and hence block the trigger. You set MOVETYPE_NOCLIP at line 73, but change to MOVETYPE_FLY at line 95. If you delete line 95 your trigger will work again.

If you are worried this class of bug might recur in other circumstances, I can outline an alternate design which uses a static rather than moving trigger, just ask! 
 
If you hadn't found the solution, I would have done the trigger movement via setorigin (since there's no collisions to check (beyond .touch of course).

You set MOVETYPE_NOCLIP at line 73, but change to MOVETYPE_FLY at line 95

*sigh* man, one day I need to rewrite my code... that's just sad. :P

But yeah, you are a genius man. I never would have imagined the rotation controller entity was behind the problem. Both it and the accompanying rotate_objects are SOLID_NOT. Why would the engine even check collision if it's not solid? Maybe because movetype_fly was intended for use with projectiles?
Very strange!

Thanks for yet another awesome bit of quake wisdom. :) 
Motionless 
My suggestion was going to be have a trigger which starts off at full height. Then just add

��if(other.mins_z < self.owner.maxs_z)
����return;

to the touch function for that trigger. Here self.owner is the visible moving entity which marks the upper end of the trigger. If there was no visible part you could calculate the height mathematically based on the time since triggering.

I'm still not sure why MOVETYPE_FLY matters, it might also be tied up in using a bsp model for the func_pressureBolt...the physics code is pretty dense and circuitous. 
 
Is this also related to that bug where a lift moving up/down will get the player 'stuck'? I had it happen more on some lifts than others, for example, that big lift in ne_ruins with the rotaters did it so much, there is actually code that sets the blocking entity's origin 1 unit up to stop the player being crushed. 
Necros 
Can that physics issue happen in DirectQ or the RMQ Engine? Both those engines have very intricate physics fixes that essentially make sure that the physics always run at Quake normal speed.

I ask because it is an engine physics issue, that isn't something you should worry about too much because MH has the cure that needs to get into other engines. 
Sheesh Missing Word ... 
"I ask because IF it is an engine physics issue" ... [basically can you reproduce the problem in the RMQ engine or DirectQ with that lift? If not, maybe mentally mark that problem off the proverbial list ...] 
 
you can test to see if it's happening by going loading ne_ruins, turning on dev mode to 1 and riding the lift up.
It's very random and may or may not happen, but you will see "corrected bmodel collision bug." if the qc detects a block that shouldn't happen.

it doesn't happen in DP, so if the collision fixes are as extensive as it is in DP, then it probably doesn't. The collision in DP is really sweet. 
 
That's enough info then. Yeah, DarkPlaces is fixed up in that way as well (and has been for ages and ages).

I wouldn't spend any time worrying about this one.

I intend to extract the fixes from RMQ/DirectQ and more or less document how to implement them.

[I just haven't done it yet because of the things on my list, well, it's kinda boring and tedious ... ] 
Bsp Format Question 
I'd like to check something with people who are familiar with the BSP file format. Suppose we have a very simple map with one room containing a func_wall. The room has 20 faces and the func_wall has 6. Is it correct that there is just one list of 26 faces in the bsp:

0
...
19
20
...
25

then the model headers go
"world: I own 20 faces starting at face 0"
"wall: I own 6 faces starting at face 20"

The same then goes for vertices, nodes etc, that the bsp file collects all alike data types into a single list and each model in the file operates on a subset of that same list? (with exceptions like textures which are instead shared).

Why? I was thinking about the external bsp models trick - initially I was just trying to write a tool to pack them back into a single bsp for release. However, if the above is correct, it might also mean that the external file gets a new lease of life - as a limited way to help maps which exceed bsp limits  
 
interesting...

rezTarget.think =
rezTarget.nextthink = time + 0.1;


compiles fine with fteqcc, but flat out crashes quake. :P 
Is It Correct That There Is Just One List Of 26 Faces 
Yes, that's the way everything is stored, but there are subtleties.

"Faces" as you understand them in a map have little relationship to surfaces in the generated BSP file. QBSP will remove faces (facing out, never visible, overlapped, etc) and generate more from splits, so you can't really use the map file as any kind of guideline to what the BSP will contain.

Regarding use of external BSP models, you can use them to go through BSP limits, but lighting will be wrong for them. Lighting for an external BSP model doesn't take account of any geometry in the world that might occlude those lights, and they fail to get dynamic lights. That might be OK with you, but it might not be OK with someone playing your map. 
It's My Lighting Aand I'll Cry If I Want 
That's good to know.

On lighting: Although losing dynamic lights is a shame, I don't think that the static lighting is much of a obstacle.

Although I've been talking external bsps in general, the best use-case for external models is for objects that rotate or move. Static lighting of course can't get these right, so there's less worry they might be lit "wrong". Along the axis of rotation it makes more sense for the lighting to be uniform, instead of baking in a shadow which will be wrong as soon as the object moves.

For statics moved outside the BSP for limit reasons only, I suppose it's not impossible to write a version of light that applies occlusion from a base map onto an external bsp (using the code-path from the light executable which occludes lights on models 1-n based on the geometry from model 0, except loading model 0 from a different file to model 1). Think I'll stick to the bsp packer for now though... 
 
Dynamic lights can be fixed in-engine; there's a (slight) performance cost but the visual consistency is more than worth it. I have it in my current (unreleased) codebase, but I don't believe any other engine has implemented it yet (aside from those with fully real-time solutions).

Along the axis of rotation it makes more sense for the lighting to be uniform, instead of baking in a shadow which will be wrong as soon as the object moves

Definitely agree with that.

I suppose it's not impossible to write a version of light that applies occlusion from a base map onto an external bsp

It's an interesting idea. It would break if more than one entity used the same BSP model (an example would be a generic door modelled as a BSP) but for limited special cases it should work. 
 
would it be possible to make an 'fake ambient occlusion' mode in light.exe such that, when enabling it, it creates an array of suns like it does with sunlight2, except that these suns do not require sky textured brushes?

that way we could make some external brushwork and get some nice shadows that look good from all rotation angles.

heh, maybe I should do that... I'll see if I can puzzle it out. 
 
http://necros.slipgateconstruct.com/temp/sillygi.jpg

hmm, seems like it was easier than I thought it would be. o.0 
If Anyone's Interested: 
http://necros.slipgateconstruct.com/downloads/ne_ag_LightMHColourR2.zip

This is based off of mh's coloured light/multicore tweak of aguirre's light utility, so it has all the good stuff.

Two new command switches are added:

-fakeGISun2
Makes sunlight2 cast additive light in a full sphere (as opposed to a dome).

-fakeGIMode
Makes sunlight2 not require skybrushes (ie: the light comes from the void)
NOTE: REQUIRES -fakeGISun2

Also note you need to set the worldspawn keys 'sunlight' to '1' otherwise it's not activated at all and the 'sunlight2' settings should be low, 2 or 3. 4 is pretty bright.

I basically just turn off the check that requires sunlight to pass through a skybrush first, so with -fakeGIMode, the sunlight comes from the void.

Source included. Some small changes to LoadEntities() and TestSky() and maybe one or two other tiny things I've forgotten. 
Good Stuff 
The spherical illumination might also be handy for coagula style maps. 
 
not bad results on space maps with only the fake gi light enabled: http://necros.slipgateconstruct.com/temp/nesp10GI.jpg

Might be cool to do another space map one day with this lighting. The only thing is that exposed faces tend to look flat. The above screenshot is only interesting because of those high walls. 
 
That actually looks pretty cool; kinda radiosity-like. 
 
Dunno if anyone has mentioned this before (Preach maybe?) but I've been using a lot of multi-entity setups these days and cleaning up after them has become rather annoying so I used this trick to simplify things:

void(entity e) remove_builtin = #15;
.void() removeFunction;
void(entity e) remove =
{
local void() _removeFunction;
entity tempSelf;

if (e.removeFunction)
{
_removeFunction = e.removeFunction;
e.removeFunction = SUB_Null;
tempSelf = self;
self = e;
_removeFunction();
self = tempSelf;
}

remove_builtin(e);
};

Create a wrapper for the remove builtin that first checks if a .removeFunction is set, and if so, run it.
Then, I just create a unique function for each multi-entity that takes care of any child entities.

Note how we first save a reference to the .removeFunction() before clearing it. This is to prevent some recursive removeFunction running where (if you are not careful) you remove a child entity that then removes the parent, that then removes the child... etc...
This makes sure it only runs once.

ps, sorry about formatting. 
Destructive 
Works like a destructor in C++ (*), I like the recursion guard you put in there, I don't remember seeing that before.

Another place where this can be helpful is if you have some kind of linked-list structure, where removing an entity would break the chain. You can set a removeFunction which repairs the list before and after the entity which is getting removed.

* How long can it be before we get a QC++ compiler bringing the full power of object orientation and inheritance to our favourite game? 
Loading MDL Files 
Trying to load .mdl files with java following this: http://tfc.duke.free.fr/coding/mdl-specs-en.html
For the most part, I got the data in fine, but for some reason, there seems to be a few extra bytes AFTER the frames that I don't know what to do with.
The number of bytes isn't consistent either, sometimes it's 10 bytes, other times it's 9 or 8.
Obviously, this screws up the next frame from loading properly because all the bytes are offset by however many were left over.

I tried just doing the dumb thing and skipping over these extra bytes after loading a frame, but the number of extra bytes can change within the same model.

Is this a real thing (extra bytes between frames) or am I just messing something up? 
 
Extra bytes between frames isn't normal. Possible that your struct sizes are being padded out to some alignment? I don't know Java so I'm not certain if it even does that, but it's the only off-the-top-o-me-head explanation I can think of. 
 
Thanks, I was just looking for confirmation that there are no extra bytes. :)

Java doesn't have structs or any of that, so I'm just reading everything in byte and byte and converting things to big endian ints and such.
I'm sure I'm just reading something in wrong or I missed something. 
Gotchas 
One of the things to watch out for is where there are mdl_vertex_t being loaded to define the bounding boxes of the frames and the like. Make sure you're reading the vertex normal in all of those places, even though it's not used. 
 
For the first frame, the data seems to be fine up to (at least that I can easily check) the frame name.
I parse each byte as a char until I get to the first byte that is 0, then I start loading vertex objects.

The problem seems to be somewhere during the vertex loading.

I'm using a 5 frame model with 5 verts.
Looking at the file itself, I see 48 bytes between one frame name and the next, so it looks like each frame is 48 bytes long. (the frame data actually starts 12 bytes before the name, there's one int (4 bytes) and 2 mdl_vertex_t (2 * 4bytes))

The mdl_vertex_t struct has an array of 3 unsigned chars and then a single uchar, so that means each vertex should be 4 bytes long.
So with 5 verts, that should mean that all the vertex info should be 5 * 4 = 20 bytes.
Take those 12 bytes mentioned above and we have 32 bytes. The name is "POLY1" so that should be 6 bytes for the name (including \0).
So in total that's 38 bytes and then 10 bytes left over. 
 
hm.. ok, seems like typing it out helped me see the problem...

Looks like the String for the frame name is ALWAYS 16 bytes, not until the next 0 value. It loads in some junk characters but that explains the 10 byte offset (16 - 6).

That's really bizarre. 
 
actually, I guess it sort of makes sense.
c just stops reading strings when it reaches the first \0, but I guess they didn't want to bother with a dynamically allocated char array so those junk bytes are actually whatever was on the guy's memory when he saved the file... 
Yup 
You have permission to zero all of that out nicely when you export though! Also, don't forget to test your code with grouped frames and grouped skins before you're through - it always seems to be going so well until that point... 
 
I wasn't really going to bother with that for now.
Mostly, I just wanted to redo that "qcStarter" program I made so you could load a model and generate some basic monster code complete with a spawn function.
But now I'm thinking it'd be pretty cool to make a modern mdl editing program. 
 
c just stops reading strings when it reaches the first \0, but I guess they didn't want to bother with a dynamically allocated char array so those junk bytes are actually whatever was on the guy's memory when he saved the file...

Yup, that's it. The struct in the C code is defined as follows:

typedef struct {
trivertx_t bboxmin; // lightnormal isn't used
trivertx_t bboxmax; // lightnormal isn't used
char name[16]; // frame name from grabbing
} daliasframe_t;

Reason why is when loading an MDL you can just load the entire file into a single buffer, then walk through the data setting and incrementing pointers as needed. If every daliasframe_t is the same size the job becomes much easier.

Same basic principle applies to other model data that contains a string name; e.g. textures have a fixed 16 char array for their names. 
 
Makes sense, they would design the format to make it easy on themselves, not some guy digging into it 15 years later. :P

Now to see if I can draw it to screen!
I think understanding exactly what the heck is going on with the so called 'compressed coordinates' is going to be the really hard part. o.0 
Hahaha 
http://necros.slipgateconstruct.com/temp/notreallyafiend.jpg
well, it was supposed to be a fiend... 
This Is Interesting 
I always wondered what the algorithm was for drawing point to point in 3D.

Also I'm stunned that I am following this. It actually makes sense to me(!) now that I can program a little. 
 
they would design the format to make it easy on themselves

...and they even failed at that!!! http://www.team5150.com/~andrew/carmack/johnc_plan_1997.html#d19970707 (section beginning "anatomy of a mis-feature").

well, it was supposed to be a fiend...

It's real close though, and a whole ton better than my first attempt at doing this with C# 8 or so years back. 
 
http://necros.slipgateconstruct.com/temp/nowthatsafiend.jpg

Silly mistake... tried reading in verts on the frames directly. :P 
Oh Thanks For That Link 
It's nice that that .plan stuff is archived. I never had internet back then (plus I was too young) but that seems very interesting now. :) 
 
Good stuff with the fiend. You gonna take this all the way and do texturing too?

The .plan archive is essential reading, it's a great window into the thinking behind why much of Quake is the way it is, and can be very informative for decisions of the "should I add/remove/change this feature?" kind. 
Skinzz 
Good Job, Necros... 
I can see its eye in that shot :) 
Heresy! 
Fiends don't have eyes. 
Yes They Do! 
You guys don't do a whole lot of looking at things, do you?

http://www.lunaran.com/pics/fiends...

And now, shambler will argue that those aren't actually eyes:
 
Herp Derp 
http://www.lunaran.com/pics/fiendshaveeyes.jpg
ZOMG! I've been wrong all this time!!! 
 
I thought those were nipples? 
Coding-related Questions 
Now that the RMQ project has split up, what's happening with the BSP2 format? Will it still be updated? Do any engines other than the RMQ Engine support it yet?

Also, is anyone willing to do some coding for new boss monsters? PM is currently cleaning up and debugging Drake, but doesn't want to spend time adding entirely new monsters/features/etc. I totally understand this POV but it'd be nice if Drake had a unique final boss of some sort.

Looks like eyes to me. Now the Shambler, on the other hand... 
Can Someone Make Me A Demon Skin 
With no eyes? This is horrible. 
Hm 
Glases are fine, horns another question.

http://members.home.nl/gimli/gdemon.jpg 
 
maybe I'm just tired, but that was hilarious. :D 
@Tronyn 
Since I was linked here from IRC, I might as well answer to Tronyn:

FTE and Darkplaces (and Hmap2) support BSP2, but DP's version is slightly different.

I would guess that DirectQ also supports it, and Baker and Rook's engines might as well.

I have switched to Warsow's FBSP for my project, so BSP2 will get no updates from me. The Schism team would probably be the ones to maintain it now. Perhaps ask at their forum.

You should talk to MH, Spike and Lordhavoc to get the BSP2 support in those engines harmonised.

Quakespasm did not want to support BSP2 when I asked.

I don't normally read this forum anymore, but I'm willing to help where I can. Poke me per mail or IRC if someone wants to talk to me. 
OBJs + PCX! 
http://necros.slipgateconstruct.com/temp/objdrawing.jpg

Thanks to preach for his pcx loading code in the md3tomdl converter. The runlength encoding stuff was confusing the crap out of me.
Also, I had to flip the pcx data on the x axis AND reverse the pixel array order after loading it... is that normal? If it's not then I must have messed up the UVs on the OBJ... 
Heh 
actually, flipping x axis and reversing the order is basically just flipping y axis right? :P 
Triple Post 
looks like it's a thing with obj... just flipped v component when loading the obj instead of goofing with the pcx. 
Y Axis 
There is an issue to be aware of with "intuitive" coordinates and storage of data. The natural order of storing skin/image data (at least the one taken in the mdl format) comes about I think from their usual representation as a string (in the purest array of numbers sense). Since we are used to text flowing from left-to-right then step down a line and repeat (for english-speakers) we extend that idea to the order pixels should be stored in the skin.

The place where this begins to cause a conflict is when we start thinking about cartesian co-ordinates on the skin. The standard mathematical axes on a graph has the y value increase as you move upwards. So if you have something that wants to put the origin of the coordinates in the bottom-left of the skin, you need to reflect the skin in y to compensate.

Having said that, if you're actually going to render the 2d skin somewhere, you really ought to apply the reflection to the skin vertices rather than the image file itself. Otherwise you will cause a lot of confusion for the user who has an expectation on what their skin looked like. 
 
Having said that, if you're actually going to render the 2d skin somewhere, you really ought to apply the reflection to the skin vertices rather than the image file itself. Otherwise you will cause a lot of confusion for the user who has an expectation on what their skin looked like.

Yes, this is what I ended up doing. I want to be able to display the skin either for drawing on (probably not) or changing UV coordinates, so having the thing upside down is not an option.

Turns out that this is a common thing with the OBJ format as many of the loading examples I read had a bit of code involving flipping the v component of the texture coordinates. 
Woohoo 
OBJ -> MDL perfectly functional! FUCK YEAH.
Still can't import more than 1 frame, but I don't think that's going to be a big deal. 
Coding Challenge 
Suppose that we have the following functions:

is_first_player: returns true if self is the first player in the server

is_last_player: returns true if self is the last player in the server

toggle_func_playerclips: finds all func_playerclip entities in the map and toggles them between SOLID_BSP and SOLID_NOT.

Your task: comment and critique the following scheme for implementing func_playerclip entities:
1) add
if(is_first_player())
&nbsp;&nbsp;&nbsp;&nbsp;toggle_func_playerclips();
to PlayerPreThink.
2) add
if(is_last_player())
&nbsp;&nbsp;&nbsp;&nbsp;toggle_func_playerclips();
to PlayerPostThink.

The main question for consideration: is there any way for a player to become 'stuck'? Extra credit for considering the implications if is_first_player and is_last_player are not available. 
Coding Challenge Fixed 
Forgot to preview so the entities weren't encoded...

Your task: comment and critique the following scheme for implementing func_playerclip entities:
1) add
if(is_first_player())
����toggle_func_playerclips();
to PlayerPreThink.
2) add
if(is_last_player())
����toggle_func_playerclips();
to PlayerPostThink. 
 
You might not be able to change .solid like that without setting model.
Might be safer to do the func_togglewall trick where you translate the clipmodel far away when 'off' and put it back into place when 'on'.

Beyond that, at first glance, seems like it would work? 
Re: Gb 
Hey, thanks for the response - helpful stuff. What's your email / how can I contact you? PS all the stuff on your blog looks amazing. Cheers. 
Clipped Out 
You might not be able to change .solid like that without setting model.
Might be safer to do the func_togglewall trick where you translate the clipmodel far away when 'off' and put it back into place when 'on'.


Yeah, I explained myself badly. The plan was to only describe abstract functions, so you could assume they were correct without getting bogged down. I leaked too many implementation details...

There's still one case I can think of where it breaks down though - the trick is to work out when the player moves other than within the player physics code. There's also a more philosophical quandary with pointcontents I meant to bring up in the first post.

I'm glad you mentioned togglewalls, because although they seem quite hackish with the far-away trick, it has some hidden advantages. The prime one is avoiding ever toggling solid status within a touch function - which can be a fatal error. Building a monsterclip with the same broad outline would now become feasible.

You do have to bind the toggling to calls to walkmove and movetogoal, because monsters don't have the simple physics-wrapping functions that players do. This means that the monsterclip is imperfect in a way that the playerclip is not: falling or jumping monsters will pass through monsterclip. Still, better than a kick in the teeth. 
 
You do have to bind the toggling to calls to walkmove and movetogoal, because monsters don't have the simple physics-wrapping functions that players do.

This is what I do right now. To avoid toggling every monster clip, I bind specific clips to specific monsters via a target->targetname style link, that way if a monster has no monsterclips associated with it, it doesn't toggle anything otherwise, it's only toggling a single monsterclip.
I suppose you could just make one giant monster clip entity for the entire map, but I'm not sure if that's bad having an entity with collision cover such a huge area so I've left it as localized clips. 
 
I think I got a little side-tracked...

There's still one case I can think of where it breaks down though - the trick is to work out when the player moves other than within the player physics code. There's also a more philosophical quandary with pointcontents I meant to bring up in the first post.

Why would it move outside of engine physics? Feeding .velocity in still has to wait for the engine to process it.
Unless you mean setorigin()? But I think it's safe to assume using setorigin is always going to break collision.

Hm.. well, unless you are doing some funny trickery where you are using a proxy to move the player... 
 
But I think it's safe to assume using setorigin is always going to break collision.

Yeah, agreed.

Why would it move outside of engine physics?

Still inside engine physics, but outside of the player's physics pass. 
 
hm... Maybe when you're standing on a bmodel that's moving? ie: train or lift 
 
Maybe when you're standing on a bmodel that's moving? ie: train or lift

Bingo. Probably not a big deal once you know about it, because usually those things are put in for the benefit of the player and you're unlikely to intentionally clip off their route, just something that users of the entity would have to be aware of. 
 
The whole player movement on other bmodels thing is kind of fuzzy for me. It's not true movement because the minute you jump, you loose the bmodel's velocity and just get your own personal velocity back.
It's too bad because it stops things like throwing the player off a fast moving object or launching them through the air from a catapult. 
Jumping Monsters 
I want to calculate the height and speed to make a monster jump a certain distance. I know the origin of both the start and finish points but I don't know how to calculate the speed and velocity in QC.

I know there is 'trigger_monsterjump' but you have to specify or just guess the right amounts until it is right. is there a way I can do a quick QC formula to get rid of the guess work? 
Pretty Easy 
Start by picking a velocity upwards, call that v_z. Let d_z be the height of the end point minus the height of the start point.

Once your monster launches, the only thing affecting it is gravity, which accelerates at 800 units per second per second(*). We will appeal to one of the standard equations of motion (with constant acceleration)

s = ut + �at�

Where s is the distance travelled, u is the initial velocity, t is time and a is the acceleration. Substituting the values from above and rearranging:

400 t� - v_z * t + d_z = 0

with solution t = (v_z + sqrt(v_z� - 1600 d_z) )/800

On level ground this simplifies to:

t = v_z / 400

Now that we have the time t it takes to fall to the correct height, we need only divide the horizontal distance between the start and end points by t to get the required horizontal velocity. Sum the horizontal and vertical velocity vectors and you are done.

We seem to have complete freedom on how to choose v_z, but there are two things to think about. Firstly flight time is roughly proportional to v_z, so vary it according to how long you'd like the jump to last. Secondly in the case that d_z is positive (the end point is above the start point), there is a minimum requirement to v_z. The value inside the square root must be positive for the equation to work, so take care.

Please also remember that although we have solved the equations exactly, the simulation of the motion in the engine will not be exact, and in any case rounding errors will occur. Do not rely on any method to give you 100% accuracy - the landing point may even vary a small amount depending on framerate.

The really interesting case is the one where you have a fixed total velocity and still want to try and land on a particular point, but no space for that right now.

(*) 800 is the default, but in reality you should use the value of sv_gravity. It should be easy to replace the constant, but the explanation focuses on the important variables for clarity. 
 
check if some mods with "z-aware ogres" (one of the worst quake gameplay changes people like to call a bugfix) are open-source and allow copying, maybe you can use the calculation from their aim. 
Confused 
Thanks Preach for the explanation but I still don't understand what to code in QC. I know values for some stuff but not the initial velocity. Also I don't mind this is not 100% accurate, I just want something that is roughly right to the nearest 64 units.

I know the following values:
start and finish origin
(s) distance = finish_z - start_z
(a) acceleration = 800 (will use sv variable)
(t) time = s / 200 (wild guess)
(I assume objects travel 200 units forward top speed, it would be nice to know what this value is for monsters)

Things I don't know:
(u) initial velocity = ??

formula:
s = ut + �at�

Expanded out:
s = u * t + sqr ( ( a * 0.5) * t )

I don't know what 'u' is, how do I re-arrange this to find initial velocity (u)?

@spirit, z aware monsters are not all bad, the problem is players don't expect the change and get angry because things are different for no apparent reason. The best solution for z aware monsters is to link them to a high skill level and make them visually different. 
Arbitration 
u is defined in the first paragraph:

Start by picking a velocity upwards, call that v_z.

The terminology is a bit mixed up, u is the standard name for the initial velocity in that equation; the name v_z was chosen earlier to suggest a vector component style but in retrospect confuses things.

The key is that it's arbitrary, you have complete freedom to pick whatever upwards velocity you like, then you calculate a forwards velocity to match it. I say complete freedom, but there is some guidance in the paragraph 4th from the bottom. 
 
It helps to break things down a bit to understand the problem.

So first is a very basic part of the whole problem, the horizontal speed.

If velocity is 600 units/sec, then that means, in 1 second, you have a distance covered of 600 units.

Seems dumb, but the next part is what you are trying to figure out:

If you KNOW the horizontal speed you want to move at, then what you need to do is find out how high to jump so that you stay in the air for that amount of time.

At this point, it can be easier to wing it.

First find the horizontal distance:
(self is some monster)
vector vec = self.origin - self.enemy.origin;
vector vec_z = 0; //this flatten the vector
float hdist = vlen(temp2 - temp1);


next we decide how fast we want the guy to jump:
float hspeed = 600; //fiends jump this fast horizontally


at this point, we could do something like this:
float vtime = hdist / hspeed;
vtime is now distance / speed (which is units of time)
So we have the amount of time needed to stay in the air.

vector dir = normalize(vec);
self.velocity = (vtime * 400) * '0 0 1' + (dir * hspeed);


the vtime * 400 part is the winging it bit. It works well for most values below super fast velocities. 
 
also, it might be a good idea to cap some values. depending on how far the monster is from it's target, vtime can potentially be quite long, meaning the velocity needed to stay in the air will be silly high.
either that or disallow the jump completely beyond a range. 
 
ohhh, finally, this is only accurate for cases where both monster and target are on equal height. for any other case, you will need to use the physics equation. 
The Final Jump 
Thanks for the help everyone, here is my final chunk of code for my jump system. It works really well and all the jumps I have setup always go downwards so the gravity/4 looks more natural than using /2.

some constants I used:
MONAI_JUMPSPEED = 200;
DEF_GRAVITY = 800;

Code:
local vector jumporg, jumptarg, jumpdir;
local float jumpdist, jumptime;

// Calculate jump velocity towards destination node
jumporg = self.origin;
jumptarg = self.target_ainode.origin;
jumporg_z = jumptarg_z = 0; // Flatten vectors

// turn towards jump destination node
self.ideal_yaw = vectoyaw(jumptarg - jumporg);
self.angles_y = self.ideal_yaw;

// Calculate distance and time
jumpdist = vlen(jumptarg - jumporg);
jumptime = jumpdist / MONAI_JUMPSPEED;

jumpdir = normalize(jumptarg - jumporg);
self.velocity = (jumptime * (DEF_GRAVITY/4) ) * '0 0 1' + (jumpdir * MONAI_JUMPSPEED);


Hopefully it might be helpful to someone else. 
@ Tronyn 
Sorry, I only rarely read here, but I can be contacted via the e-mail in my profile. I'll gladly reply to mails.

It can be weeks before I check back here. 
Stubborn Fox 
Thanks for that bit of code, Sock.
Comes in handy for the RocketJumper I made.

I'm still experimenting with the amphibian.
I made a new model for it, but the code still won't work well.

http://members.home.nl/gimli/dwell.gif

I know it's rather a high catch to invite a monster in Quake
that runs also on land as swimming in water.

For so far I managed it to stand on land and run for the player,
follow it in water turning into a swim pose.
The pitty edge is to get it back into its walk state.
Now it jumps back on land in its swim pose, only turns back into the walk frames after it has bin shot.

The reason for this is that I made an addition in the Fight.Qc

float() HarpCheckAttack =
{
local vector spot1, spot2;
local entity targ;
local float chance;

//check we are in the water and also standing
if (self.waterlevel > 0 && self.th_stand == h_stand1)
{
dprint("standing on ground \n");
h_jive1();
harpi_to_harpo();
return TRUE;
}

//check we are in the water and also swimming
if (self.waterlevel < 2 && self.th_stand == h_dwell1)
{
dprint("shallow enough to stand\n");
h_mour1();
harpo_to_harpi();
return TRUE;
}


The first statement gives it a stand attitude on land :
if (self.waterlevel > 0
If I use another number, 2feet 3 chest 4 eyes, the monster won't go back up the land.

The impulse to do so comes in with
harpi_to_harpo();

The second statement gives it a swim pose in water :
if (self.waterlevel < 2

This impulse comes with
harpo_to_harpi();

harpi is in water
harpo is on land

So far it is clear to me.

I try to figure out what's going on when the monster comes out of the water and don't start the stand position. 
 
it's difficult to see what to change without seeing more (or all) of the code.

you could try also adding the same checks you have into the first frame of the running sequence.

so what I would do is this:

make the state check it's own function
void() HarpCheckState =
{
//check we are in the water and also standing
if (self.waterlevel > 0 && self.th_stand == h_stand1)
{
dprint("standing on ground \n");
h_jive1();
harpi_to_harpo();
return;
}

//check we are in the water and also swimming
if (self.waterlevel < 2 && self.th_stand == h_dwell1)
{
dprint("shallow enough to stand\n");
h_mour1();
harpo_to_harpi();
return;
}


then add a call to it in the first run frame:
void() harp_run1 =[ $run1, harp_run2 ] {ai_run();HarpCheckState()};

the first run frame is called whenever monsters switch targets or wake up, so it should be more reliable than waiting for it to try to attack. 
 
Right, in addition the corredsponding file only files that matter

There are two modelposes in one file.
The land state and the swim state.
Both are switched in the djive go-in-water and mour come-on-land poses.

harpio.qc


frames$

void() h_jive1 =[ $djive1, h_jive2 ] {harpi_to_harpo();};
...
void() h_jive10 =[ $djive10, h_swim1 ] {};

void() h_mour1 =[ $mour1, h_mour2 ] {harpo_to_harpi();};
...
void() h_mour10 =[ $mour10, h_run1 ] {};


void() harpo_to_harpi =
{
self.th_stand = h_stand1;
self.th_walk = h_walk1;
self.th_run = h_run1;
self.th_die = harpio_die;
self.th_pain = harpio_pain;
self.th_missile = h_attack1;
self.th_melee = harpi_melee;
self.flags = self.flags - (self.flags & FL_SWIM);
};

void() monster_harpio =
{
if (deathmatch)
{
remove(self);
return;
}
precache_model2 ("progs/harpio.mdl");
precache_model2 ("progs/slmbal.mdl");
precache_model2 ("progs/h_model.mdl");
precache_sound2 ("player/death2.wav");
precache_sound2 ("fish/bite.wav");
precache_sound2 ("fish/death.wav");
precache_sound2 ("harpi/sight.wav");
precache_sound2 ("enforcer/enfstop.wav");
precache_sound2 ("enforcer/enfire.wav");
precache_sound2 ("knight/khurt.wav");
precache_sound2 ("harpi/idle.wav");

self.solid = SOLID_SLIDEBOX;
self.movetype = MOVETYPE_STEP;

setmodel (self, "progs/harpio.mdl");

setsize (self, '-16 -16 -24', '16 16 24');
self.health = 200;
harpo_to_harpi ();
walkmonster_start ();
};

void() harpi_to_harpo =
{
self.th_stand = h_dwell1;
self.th_walk = h_swim1;
self.th_run = h_crawl1;
self.th_die = h_die1;
self.th_pain = newharpio_pain;
self.th_melee = harpo_melee;
self.th_missile = h_harp1;
self.flags = self.flags | FL_SWIM;
};



The reason it won't go back to its land state might be the start scene with harpo_to_harpi statement.

So as soon it reaches

void() h_mour10 =[ $mour10, h_run1 ] {};

its original state reminds to harpo_to_harpi
before the walk_monster_start in void()monster_harpio.(?)

I'll try the HarpCheckState(), but doesn't it need more addition to the Harp_Check_Attack? 
Madfox 
Add a line to each of the of the h_mour functions where you send out a debug message like so
void() h_mour1 =[ $mour1, h_mour2 ] {harpo_to_harpi();
bprint("I am in h_mour1! \n");
};

Then see how far through the animation sequence it gets. This should help you work out where the problem is. 
 
I don't get any messages in game although I have the bprint in calculated.
protocol 666? 
Falling Through 
It looks as if the standing on ground and shallow enough to stand cross over each other.

http://members.home.nl/gimli/frmcount.jpg 
 
if you are using Bprint then the messages should always appear. If you are using Dprint, then you need to have 'developer 1' set.

Regarding the monster itself, the one major problem you are having has to do with how swimming is handled in quake.

Walking monsters are able to move into water but swimming monsters are never allowed to move out of water, so no matter where you check, it is impossible for the check to succeed and switch back to land movement.

There are ways to get around that of course, but they are all (at least what I am thinking about in my head) somewhat complex.

The first idea I'm thinking about is changing the land->water check from self.waterlevel > 0 to something like self.waterlevel > 1
This would make it switch when it's much deeper in the water.
Next for the water->land check, I would check the distance to the ground from the monster's 4 bottom corners of the boundingbox to see if there is ground close to it's feet.
Then I would check waterlevel <= 1 and if it checks out, transition water->land.
There might need to be a cooldown timer to prevent it from switching back and forth too quickly too.

The second option would be to use FLY instead of SWIM and then manually stop the monster to rising out of the water.
The best way to do that would be to make a wrapper on the monster's movetogoal calls so that it moves to a helper entity which is set to the player's horizontal position, but who's vertical position is set in such a way to keep the monster under the water.
Using fly would give you more freedom to getting the monster to move OUT of the water, and then you original checks might work out.

Both those options would need a fair bit of code rewriting, unfortunately. :( 
Bprint 
I've started using bprint instead of dprint for debugging messages relating to coding, so that there's no way I can forget to remove them!

One way to make the monster can leave the water might be to use the ideas in this tutorial, a hybrid between movetogoal (which won't leave the water) and velocity (which will)
http://www.quaddicted.com/webarchive/minion.planetquake.gamespy.com/tutorial/speed.htm 
More Stubborn Monster 
Thanks for the advice!

I have to read the tutorial, but parms like move to goal and velocity are lucide to me.
Not that I don't understand them but the referring code doesn't fit with my knowhow.

It is almost a jack-in-the-box to me how to define a working statement.

As soon as I change the parms the monster works alright,it only comes out swimming on land and I just have to shoot it back in its walk pose.
This works and for sofar I should be glad.

That it is not the bugfree method is something I'm trying to overcome. 
Practical Problem 
OK, here's a genuine issue faced when creating the next version of Quoth. A mapper who I will not name has released a Quoth map which uses some entity hacks. In particular they've created a backpack model using the modelindex hack. The new patch precaches fewer models, and so changes which model appears for the modelindex which the hack uses. This breaks the map (from a visual point of view).

Which approach would you choose?

a) Let this entity-hack remain broken to discourage future hacks

b) Insert a piece of code which detects this particular map and fixes the models within it

c) Reorder the remaining precaches so that the backpack occupies the same precache slot in this map

d) Revert the model precache savings, as they are incompatible with existing maps


Remember, there are no right answers. Only wrong ones... 
 
create a lookup table that matches the old precache numbers to the new ones?

haha that would be painful to do. :P 
 
name it quothX.Y and tell people to state the tested quoth version(s) in their readme from now on. consider all existing maps requiring quoth2. 
Not Really Related But A Selfmade Problem: 
releasing quoth2 as quoth was annoying already (from a quaddicted viewpoint). I really do not want to replace it again and pretend comments and ratings are for the new version.

I guess one would need to add an dependency option of 'provides', so eg quoth2 provides/fulfills the dependency 'quoth'.

or how about calling them "quoth_pak1", "quoth_pak2", etc. 
Look-up Sir, Arrgggh! 
That's more or less what option c) is, except you only match this particular model to the index it once had. If you're precaching fewer models, it's obvious that you can't do that for every model, so the solution would not be sustainable if this hack was common.

I thought the backpack would be reasonably easy to fix like this because it's in that big list of guaranteed precaches in world.qc. You'd just look at the list and move the backpack precache down as many precaches as it takes. On looking at it, this might not work; unfortunately the backpack is one of the last things to be precached. The number we'd have to give it would belong to the "variable precaches region" which changes depending on which entities the map includes.

You could try to add a wrapper to the precaching function which counts the number of calls, and then precaches the backpack after the right number of entries. There's two problems: First you need to filter out multiple calls to precache the same file (which is hard given QC's lack of support for arrays). This can be done with some effort though, because we know exactly how many precaches we need to remember - the number between the guaranteed precaches and the desired precache value for the backpack.

Then you need some way of dealing with the possibility that not enough models get precached, and so the backpack is never precached either. In QC you don't have any way of telling how many more entities there are to spawn, and when the last spawn function has run, you no longer have the ability to precache models. So you can't predict ahead of time you're in the state where the backpack won't get precached. Any solution for this case would need to be based on the idea of working round the backpack model missing its precache, which is actively detrimental.

So the only proper way to get this trick to work is to sniff which map is being loaded by some other means, and fix it up then. At this stage b) is probably more attractive. 
Spirit 
There are lots of enhancments in new versions of a mod that benefit existing maps - like the rebalancing of annoying monsters, or the fixing of occasionally occuring bugs. So we need backwards compatibility. 
 
Said mapper may also have included two versions of the hack to make it work on both Quoth 1 and 2, so if a new release were to address compatibility issues, it would probably need to take care of two modelindex shifts (unless Quoth 1 didn't change anything about it). 
Yes 
I noticed that, and wondered if that might have been a hint to whoever it was not to indulge in that kind of behaviour. For the record, using a mapobject_custom is a much easier way to get the model you want (they aren't static entities by default). That would only require the hacky version in quoth 1, and then using a designed entity for other versions will be forward compatible. 
Preach 
Rebalancing monsters IS breaking backwards compatibility!

(Aaaaahh change!) 
True 
There should have been an item_custom entity to begin with.... Which new model does it display anyway?

Btw, since you're working on a new version of Quoth, do you have a list of desirable features mentioned over the years or something like that? Obvious things that Quoth is missing for no good reason. Not going for a public feature request discussion, just interested. 
The List 
To make clear, the current patch is limited in scope, and the specific limit I am sticking to is no new entities. I do have other ideas for what might go into a future version of Quoth, custom items is not on it though...It currently displays a head gib with a very weird skin.

Spirit, backwards compatibility is not the same as identical behaviour, else fixing bugs is prohibited because the new patch doesn't crash to the console. For gameplay, I take backwards compatibility to be: from any map or set of circumstances that a player could complete a map in the previous patch, they still can in the new patch with no more difficulty. As someone pointed out in the Quoth 2 thread, making monsters weaker does not affect that. Obviously there are other measures of backwards compatibility that have to be considered, and visual fidelity is one. 
 
Is the protocol 15 precache limit really that big of a problem in 2012? 
Steam 
I'd hazard a guess that the majority of people with quake installed right now use protocol 15, because they bought it bundled on Steam and don't know anything about custom engines. I'm not imagining that every mapper will create maps that run on all engines. Still, if some mappers might want to, the mod should do all it can to enable that. 
 
That's true, but if they know about custom maps in the first place, then knowing about custom engines is just a few inches away.

Unless it's not possible to run a custom engine with Quake on Steam? 
Barriers 
I think you can, but each extra barrier to running the map is gonna turn away some fraction of your audience. 
Follow-up 
If you did want to design a mod where it was clear to mappers what they were free to touch and what you were reserving for future modification, then you might be able to use some of the tricks in an article I've just posted:
http://tomeofpreach.wordpress.com/2012/12/01/whats-in-a-name/

For people who think that it's all a bit crazy and worry for the future of Quoth, don't. Firstly it's too late to do all of this for Quoth, you'd need to have done it before you release the first version and people start making maps. Secondly, Quoth probably doesn't need it because it's fairly slow moving. The private fields stuff would be more useful when you're releasing new versions each month or something, keeping new features private while you're messing with the design, like an "under construction" gif.

If you still think it's a bit paranoid, hold on, because there's a much more interesting use of these field name tricks coming up. 
 
That... Is very interesting. Would have been useful to protect stuff for sure. Although if you're going to limit things in that way then you should try to provide ways to do those things explicitely. 
 
Could someone explain mechanically how Quake's monster stun effect works? Is it like Doom's where monsters have a percentage chance to be stunned, or does it go off the amount of damage cause etc? 
 
I think it happens on specific animation frames 
(i Guess You Mean The Sudden Attack Cancelling Effect) 
 
Percentage 
It's something that varies from monster to monster, and it depends on a lot of things:

Random chance
Amount of damage
Time since last attack
Skill level

Each monster has an individual function to decide what to do, I'll explain two contrasting ones:

The grunt is on the weakest end of things. The first hit it takes will always send it into pain. At that moment one of the pain animations is selected, and it's pain_finished field is set so that it can't go into pain again for a short time. The pain_finished time for grunts is barely long enough for the pain animations to complete. Amount of damage has no effect.

The shambler is on the opposite end of things. When it takes a hit, it generates a random number between 0 and 400. If the amount of damage is less than the number generated, it ignores the hit. Otherwise it goes into pain, and sets pain_finished to 2 seconds into the future.

In between these two extremes there are lots of variations. The pain_finished time is unbreakable, but after that there is usually some amount of damage which guarantees a pain animation (e.g. we see the shambler takes 400, the death knight is only 30). Nightmare skill has a global effect - the minimum gap between pain animations is 5 seconds for everything. 
 
ic, interesting. It certainly seems somewhat random but a lot less so than Doom's...

Cheers :) 
Overlaps 
As promised, the second half of yesterday's article, with a more sensible use for private and hidden fields, after introducing overlapping fields.

http://tomeofpreach.wordpress.com/2012/12/03/overlapping-fields/ 
Re: Practical Problem 
I know this is a hack, but could you not add special consideration to 'info_notnull' that when it has a 'model', you search for other entities with the same 'model', and set it's 'modelindex' the same?

So if I have a:

"classname" "info_notnull"
"origin" "# # #"
"think" "PlaceItem"
"nextthink" "0.2"
"touch" "BackpackTouch"
"model" "progs/backpack.mdl"
"modelindex" "#"


We'd look for another entity which already was 'model' 'progs/backpack.mdl', and use it's modelindex as our info_notnull's. This means the info_notnull would have to be later than an actual backpack (or whatever we were trying to copy)... but wouldn't that make the designer setting the correct modelindex irrelevent, and all he'd need to do is set a correct model? 
Modelindex 
Yeah, there's really no need to be doing anything with the modelindex if the mod supports custom model setting. Thankfully Quoth provides that with the mapobject_custom entity - which will also precache whichever model you supply it so you aren't restricted to models the mod already uses. The mapobject_custom is basically an info_notnull in every other way, so if you were to apply other hacks to it they'd work fine.

I stopped short there of saying "go ahead and use hacks", as they can cause problems, but I do still keep them in mind when designing things. For example, one of the features I've considered for Quoth is aggressive entity optimisation. This would basically be runtime consideration of which entities don't actually need a full entity slot to themselves (yet), along with a way to let entities share slots for the time being.

The path_corner is the simplest example of how this would work. Even with all the exciting extra features added to them in Quoth, you only need about half a dozen fields to store everything relevant about a path_corner. I've written code that will take those vital fields and stash them into one of four field-sets, making an entity with a "library" of 4 path_corners. The pool of library entities also doubles as the active path_corner entities, which are dynamically generated as a monster heads towards one.

So if this is all done and working, then why isn't it going into 2.2? The reason is hacks. The logic that says you only need 6 fields to store the relevant info from a path_corner breaks down if someone performs any kind of hack on the path_corner. Because there's no limits to what might be hacked, you can't predict what extra fields you'd need to store to restore the hack to working order, and the fact that potentially you'd need to store any field means there's no space to store even a second path_corner. Even if you could, dynamically generating the path_corner is equally toxic to potential hacks, as the path_corner might not exist at the vital moment the hack is to be triggered.

I can see two ways round this: one would be to create a global opt-in flag like the model optimisation flags: the flag would mean "This map is free of hacks, so go ahead and aggressively optimise it". The alternative would be a local opt-out flag on entities, meaning "don't optimise this entity, I'm performing a hack on it!". While I'd prefer the latter, I suspect it wouldn't be backwards compatible.

Some might say that surely path_corner is a safe thing to optimise, that nobody would hack. However
1) There's already a hack involving them
2) Imagine the same principle applied to unspawned monsters

The take-home message is this: Map hackers of the world, you are being considered, but you make it hard on us! 
Is That So? 
The mapobject_custom is basically an info_notnull in every other way, so if you were to apply other hacks to it they'd work fine.

Applying the "give the player a DBS" fields from my info_notnull to my mapobject_custom made the backpack model not appear.

{
"classname" "mapobject_custom"
"origin" "320 184 -244"
"model" "progs/backpack.mdl"
"skin" "14"
"think" "InitTrigger"
"touch" "BackpackTouch"
"items" "2"
"netname" "Double-barreled Shotgun"
"nextthink" "0.2"
"targetname" "pack_dbs"
InitTrigger 
InitTrigger is to blame there, it intentionally hides the model of whatever it is run on, so that you can't see triggers. 
I See. 
Any way around it? 
 
the flag would mean "This map is free of hacks, so go ahead and aggressively optimise it"

this isn't that bad an idea... like setting a strict doctype. 
Two Replies In One 
onetruepurple: try swapping the classname and the think.

necros: yeah, I think it's what will have to happen. Maybe you can have the local opt-out flag as well. Opt-in flag means: "I will let you know when I'm hacking", opt-out means: "This is a place I am hacking" 
What Else 
Other than a missing precache, causes Quake to crash without error?

Dusting off my coding skills and this has me stumped.

No errors in the compile either.. although I am running FTEQCC. It's definitely something I've done recently though. 
Difficult 
Best advice I can offer is call traceon() in the worldspawn function, then run with -condebug on. You'll get a massive log file, but you probably only need the last few lines to find out what runs immediately before the crash. Otherwise, maybe try a few different engines, darkplaces will often tell you something that other engines don't. 
 
infinite while loop? had that a few times 
Ijed 
Another crasher: whatever's happening on e2m2 when you pass the front gate without shooting both buttons on easy skill. 
Thanks! 
Will get this figured out. 
Overlapping Fields 
Preach,

So recently, I treat QuakeC as if it were an OO language in that I ALWAYS create new .variables for all entities.
I do this mainly for readability/clarity reasons after getting burned when trying to make sense of some older code that was using things like t_width and lip all over the place.

Of course, now every entity has like an extra 100 variables attached to it. While it's unlikely to really impact the code much (it's not like we're lacking memory or processing power here) it does bug me a little in that it's not really the right thing to do for this language.

So... would the proper course of action be to declare a handful of invisible fields:

internal_float1__ ... internal_float10__
internal_vector1__ ... internal_vector5__
etc...
and then overlap the same fields with unique names? 
Yeah, I Guess 
It could work, but you've got to be really careful that you're never overlapping fields that will cause problems. You don't need to give them names like internal_ etc, you can just pick one name as the original and overlap the others on that.

Doing this kind of overlapping in monster code might be safest. Make sure each monster has its own QC file, and define the overlapped field name at the top of the monster's own QC file. Then you can make sure all use of these fields is localized to functions in the one QC file. To be doubly sure, instead of using the "var" keyword to overlap, use a #DEFINE macro to give the field its name, and then undefine it at the bottom of the file. Then you only need to watch out for other QC files calling your functions (and map-hacks).

What would be really nice would be a sort of QC++ compiler which creates the idea of a "class". It would let you subclass entities, have functions that only accept particular classes of entity, and prevent you accessing entity members which aren't defined for that class (or parent classes) at compile time. Then the compiler would overlap private fields for you safely.

This isn't quite as crazy as it sounds, the original C++ compilers were source code transformers which output C code and then called a C compiler to build it. A fun project for someone who wants to learn Lexers and Parsers... 
Wah 
After rolling back everything - models, sounds, code, maps I still got the crash on map load.

So I open up the map and clean out the values I'd added to control the enemy in question, and that solved it.

pose 0
skin -1
cnt 0

One of those was the guilty party I'm assuming the skin value - I was using -1 as 'random'.

(this is about a crash I mentioned earlier in the thread, thought it might be of passing interest) 
Yeah 
I can imagine how that might cause a crash, yeah. Setting fields to zero in a map should do nothing at all, fields are zeroed to begin with. The -1 on the skin might do it though! The engine probably uses -1 as an offset into the skins array, and reads some random memory just before the site of the model data. If you still want to live dangerously and use -1 as the "random skin signifier", you can probably do it just by altering your QC a little - handle the -1 case and randomly select a skin before any call to setmodel. 
 
With a skin of -1, MSG_WriteByte will coerce the value to a unsigned char, which I think gives it a value of 255? Then the client gets the 255 and and uses that index to look up the gltexture in an array. This array access is probably out of bounds, causing the crash. 
Aha 
So when I cleaned up the code and put setmodel / setskin in the right places it broke...

I had to delete a lot of stuff, but I don't see it as wasted time - now I can build it much quicker and better.

It's for an undead enemy that 'hatches' from dead marine corpses - the unlucky guy's own skeletal and muscular structure, minus the skin. 
OOB For Fun And Profit 
Another fun way to go out of bounds with skins is to use a skin coordinate which goes off the edges of the skin. GL engines handle this fine, they start tiling the skin which is very handy. Unfortunately software engines just do blind pointer arithmetic, and so start rendering the rest of the model data as if it were the skin... 
Well 
I understand the problem well enough now to think of a workaround. A lot of the bad practices in Quake (mapping, sounds, coding etc) aren't really documented anywhere clearly and exist as generally known knowledge, making it hard to know it all...

Thanks for the help :) 
Wicked Map 
After playing Something Wicked This Way Comes. I started thinking about the expansion of the BSP format, the VIS times involved in expansive maps, and the task of managing large maps in an editor. Has anyone tried to create an engine/QC that would allow information sharing over multiple bsp files? I think that making the BSP format larger is one way to make larger maps but the time to compile/test/compile is going to be a problem. Fixing one end of the pipeline at the expense of the other. Wicked could have been split in two, both halves in memory and the textures loaded, a transition would be almost instant. I'm not a coder but that seems better than making vis run for weeks. 
Well 
Vis doesn't need to run for weeks. What Quake is really missing is its own method for doing detail brushes.

If you look at those massive towers in something wicked, you'll see that they're both func_wall - noclip out of the world and they'll vanish.

If those had been part of the vis process then it would have taken significantly longer.

What the RMQ engine does to enable stupidly big and complex func_walls is to fix the entity flicker bug.

Normally, if you try to have a func_wall that stretches across various vis leafs, it flickers in game as the player moves between the different leafs.

With this bug fixed, you can make a func_wall that spans across practically a whole level, with lots of small details, curved surfaces or whatever and doesn't impact vis time at all.

There is of course a trade off in performance, but seeing as vis was designed to work on 1997 hardware - with 8K of ram - this point is pretty much moot.

These tools aren't automatic though, and a certain amount of technique must be learned in order for them to be used.

I'm far too impatient to vis a map for anything over an hour - and I don't want levels that are choppy either. 
 
Is work continuing on the RMQ engine? I hope it does because it's performance is so much higher than other engines like Fitz which is much more interesting to me than extra eye candy :/ 
 
I know a lot of mappers use func_wall like detail but I always have problems with their shadows when aligned to world geometry. An object which is part of a wall will cast better shadows than the object as a func_wall placed against a wall.

Personally I think the compiler tools could do with some upgrades more than allowing mappers to create long range shooting galleries.

* Consist lighting across bmodels and geometry.
* bmodels having a minlighting options so it is easier to get rid of solid black surfaces.
* Having external light maps so the lightmap density can be increase (would need engine support)
* Being able to having textures with phong shading (probably need a new compiler tool to split the surfaces off in a separate area of the BSP for the light tool to work with them.)

Some of the most radical visual/mapping upgrades to Q3 was when Yndar was working with the compiler tools. I am sure it was the same when Bengt Jardrup worked on the Q1 tools. 
External Lightmaps 
this is interesting... what exactly is it, and how does it work? ie: external vs internal, is it just upping lightmap resolution?

I am sure it was the same when Bengt Jardrup worked on the Q1 tools.

Pretty much. It was a huge loss when he moved to q2. He consolidated like a dozen different compilers together and his work on the light utility in particular was amazing, not to mention vis progress saving. 
RMQe 
Don't know - Mh was working on it.

The lack of shadows can be an issue, I tend to avoid it for large objects by placing a simplified mesh inside the func_wall - just a block usually, which won't upset vis but still give shadows.

Not perfect shadows, but the resolution of the shadowmap isn't great in any case and small details are usually lost.

For external lightmaps do you mean direct access to the lightmap texture? I think it can be extracted from the bsp, though not sure how.

And yeah, Bengt did amazing work to consolidate and improve everything. 
 
@necros, external lightmaps are large (usually tga) files which only have light data. They are external because the internal bsp format only supports small light maps. By increasing the size of the maps the lightmaps on objects can be bigger (less fragments) and high density for remapped on to the relevant compiler surface. To create this feature would require a lot of effort to include in the Q1 compiler tools.

The most linked article on external light maps! :P
http://sgq3-mapping.blogspot.com.ar/2009/01/using-hi-resolution-external-lightmap.html

Probably the most annoying thing about light maps is that they are rarely consistent across multiple object types (brushwork, models, entities) and will produce different results depending on how the compiler tools organize/sorts them. Even Quake 3 with all of its fancy features still has different compiler pipelines for models and brushwork which can cause strange lightmap errors.

Some examples of weird lightmap errors:
http://www.quake3world.com/forum/viewtopic.php?f=10&t=46294&p=901394&hilit=#p901394 
 
That looks similar to making lightmaps in doom3.

I guess the compiler would need to both export the lightmap as a texture AND output uv information for the bsp faces being mapped?

I don't know how likely someone can do that for q1... 
 
Looks very similar to what you could do in ut2k3, making entire levels out of meshes that were pre-lit in Max/Maya.

crappy screenshot

Was a gorgeous effect if used properly, fantastic lighting and such (on the environment at least), given that ut2k3 didn't have any kind of light bounce and meshes were purely vertex lit... problem was building an entire map in Max was a bastard :( 
 
Yeah, that was the same thing for d3. I found building maps in max to be much easier too, because you could make complex shapes much more easily and utilize the scripting capabilities to quickly build stuff. 
Question 
Do models have their own centre point that Quake somehow reads?

I'm trying to swap models and my enemy is getting stuff stuck in the floor. I set the bbox manually, but it seems to get confused depending on when I make the walkmove! check.

Might be better off just setting model to null until it needs to be alive and using a .entity for the other version. 
I Know 
There's an 'eye plane' or something like that, but AFAIK it's just some helper that Qme included and didn't actually do anything. 
 
There is an origin on quake models. You need to have the model's feet 24 units below the model origin in order for it to line up with the ground. 
Ok 
Need to throw more DropToFloor experiments at it.

What's 24 units in normal dimensions? I googled a bit and this: http://www.gamers.org/dEngine/quake/QDP/QPrimer.html

Tells me it's 72cm...

Feel like I should know all this stuff, but its the first time I've had this problem - or maybe just the first time I've noticed since I'm mixing legacy with new assets in the same monster. 
 
The engine bounding box plays a role in determining the position of the model as well.
eg: '-16 -16 0' '16 16 64' is not the same as '-16 -16 -24' '16 16 40' 
Aha 
That's probably it then - I've been getting odd behaviour and after the previous problem tried changing the order of where I was defining the box / changing the model asset.

Sure enough, things got free that weren't stuck before.

Weird how it was done. Especially using imperial measurements. 
 
hold on... i might be wrong on my last post... it's been a while since i've messed with models and bboxes too. :S 
Heheh 
Well, I'm going to be redoing the mesh from scratch anyway, but want to get something lashed together in the code for now anyway.

So will have to experiment and see what works.

FYI it's based off that model you sent me some time ago, although I've modified it pretty heavily into something else now, next step being an updated mesh... 
Got It 
Thanks for the help :) 
New Question 
How do I get a flyer to prefer to be higher than the standard 'eye level' fly height?

Searching around, it seems that movetogoal is the answer, but this is in the C code apparently and I want to stick to qc.

I don't exactly want a B0b vertical dodge - although that could be useful as well for when it's in hunt mode. 
 
Look at rubicon 2 source, I have a hard-coded min and max altitude that can easily be changed. The trick is using an invisible dummy entity as .enemy to trick movetogoal into seeking the desired altitude. 
 
That's how i've done it too. Here's my implementation: http://mobile.sheridanc.on.ca/~jonescor/temp/ne_q2hover(01.09.13).qc 
Great 
Thanks guys. 
Perfect 
Lots of useful stuff to learn from.

Insightful to see two different implementations that work with slightly different approaches. 
Oh Dear 
Oh no, another blog post. If you're using the hipnotic rotating entities, you might want to go grab this fix...

http://tomeofpreach.wordpress.com/2013/01/18/sub_normalizeangles-bug-squashed/ 
 
Thank you! 
Wait 
did you have an old version of hipnotic? mine already had that fix in. 
Maybe... 
I was working on Quoth when I noticed it, so that might have been out of date. 
Stack Overflow 
I'm puzzled about monster behaviour.

After setting the qc for self.th_stand, self.th_walk and self.th_run, self.th_pain and self.th_die I'm left with the self.th_melee and self.th_missile.

As long as I take the "SUB_NULL" everything goes fine, except the monster can't attack.
As soon as I give these parms a function the game returns them as

ai:CHeckAnyAttack
fight:CheckAttack
monster:monster_atk1
stack overflow.

Maybe it is my wrong assumption a monster can be added with only changing the monster's qc and leaving the ai and fight.qc aside.
Earlier I added monster with the enforcer.qc and there were no console messages.

I know I have to change things in ai.qc and fight.qc, as I did by adding a CheckAnyAttack in ai.qc and a CheckAttack in fight.qc.

Still the compiler sees no wrong but in game the console hangs on stack overflow. 
Stack Overflow 
Stack overflow often comes from two functions calling each other in a loop that cannot be escaped. CheckAttack will run any function you put in th_missile or th_melee. If monster_atk1 calls CheckAttack, then the QC just goes back and forward between the two. The fix is to make sure that you don't call CheckAttack in monster_atk1.

What can make it harder is that you might not run CheckAttack directly - you might run ai_run which runs CheckAnyAttack which runs CheckAttack. So post exactly what your monster_atk1 does and we can see how to break the loop... 
Acracadabra 
The qc is a bit long so you find it here
As i started to make changes to the ai.qc with the CheckAnyAttack and the fight.qc with CheckAttack, I tried again with a cleansource.
Proqcc asks where def.qc 699 exp ; found
Ftecqc responds with no error, but on console

The idea was a quake1 Orb, that has a melee missile attack and a jump function like the demonfiend. 
Read-only AI 
It's a good exercise to try and write a self-contained monster, which only calls the ai functions but doesn't alter them at all. It's also better for making a monster that "feels" like the originals. So stay strong, let's fix the file.

You are calling ai_run in all your attack functions, which isn't always the best plan. The problem with ai_run is that it looks like "this is the function I call to move n steps forward". It's actually more like "this is the function to look for something new to do, and run forward if I can't find anything".

So ai_run is looking for something better to do than just run, and it tries to attack. When it decides it can attack, it runs orb_jump1 to get the attack started. Then trouble: orb_jump1 calls ai_run again! So ai_run looks for something better to do that it was doing, and decides to attack...

...and the loop goes on until you crash.

If you look at demon.qc, you'll see that it doesn't use ai_run anywhere in the attack functions. When it needs to move, it uses ai_charge instead. There are other ways to get round the problem, but replacing ai_run with ai_charge in your attacks is a simple fix to start with. 
Yeah 
That's what I was looking for!

I didn't see the ai_charge. I kept changing the ai and fight.qc with the loop result.

Thanks for your clear explanation, after a few days I thought the orb could only crash. 
Grr, Arg 
Darkplaces is the Internet Explorer of custom engines - it has features that nobody else offers, but creates awkward incompatibilities at the same time. Today's bugbear: it changes findradius so that non-solid entities are included in the search results. This makes it possible to create invisible ghost monsters in Quoth with a rocket in the wrong place... 
 
yeah, i don't try to support it anymore. just too many things broken. 
Look Through The Sv_gameplayfix_* Cvars 
The one you want to disable in this case is sv_gameplayfix_blowupfallenzombies 
Total Opt-out 
Is there a cvar that says don't do anything present or future which messes with the QC? It wasn't hard to tweak the code to work around this - the cost is in spending the time testing in darkplaces for bugs that don't occur elsewhere, reproducing them reliably and working out what the engine does differently. I'd add "sv_gameplayfix_optout 1" to quake.rc in an instant. 
No Opt-out 
I have no plans for an "optout" cvar because it's like taking a sledgehammer to a nail, it isn't the right solution to the problem.

The right solution to the problem is one where users don't have to do anything.

I'm still evaluating the right solution. 
Arrays 
Is there a QC compiler that supports arrays? 
 
 
Fteqcc! 
Yes, it's great :) 
Compiler 
@Spirit, I am using that already, thanks :) 
V_angle / Mangle 
I am trying to make an object look directly at another object. I want the v_angle/mangle (Pitch/Yaw/Roll) but I can't work out how to get them.

I know about vectoyaw:
dir_float = vectoyaw(destination.origin - source.origin)
This returns the Yaw angle, but I want the Pitch angle as well.
Any clues? 
Pitched 
For some reason the pitch is reversed. I got the following to work but not sure why the pitch needs to be fixed.

vector vec = destination.origin - source.origin;
vector vec_dir = vectoangles (vec);
vec_dir_x = 360 - vec_dir_x; 
Protocol Question 
Which maps, mods, or demos use all or most of the fitzquake protocol features? I've added fitzquake support to my demo parsing code and would like to exercise it a bit for the sake of quality. 
DarkPlaces Sv_gameplayfix Cvars Are Now Opt-in, And New Build Posted 
Posted a new build of DarkPlaces today with sv_gameplay fix cvars off by default (the disruptive ones, anyway), and some bugfixes for hipnotic (hip2m3 now completable) and other maps.

I have fitzquake protocol support in the works but not the time to finish it right now, I don't understand why fitzquake uses a protocol different than the QUAKEDP protocol that it clearly borrowed several bits of code from... 
 
thank you very much! 
@LordHavoc - DarkPlaces Constructive Criticism 
Everything has to be something.

Pushing the limits of future ideas is not something to be apologized for. Especially if you are doing it for free.

Mental exercises of the future are something anyone can do. You express these in code, something few to no one can do.

You've done it, do continue to do it and everyone sensible is inspired by it, everyone talented draws insight from your work.

Everything has to be something.

More importantly, BUT ** everything has to be something. **

DarkPlaces cannot both be an engine of the re-imagined future and a conservative engine of the past.

If you try to go there, you'll fail on both fronts and lose your identity in the process.

Everything has to be something. If DarkPlaces tries to be everything to everyone --- it is going to fail more spectacularly than any engine Quake has ever seen.

It is ok to be an engine that thinks of ONLY how things should be and never of how they are.

If you try to change that thought process, it will not lead to happiness. Your head is in the idea of a yet unwritten better future.

Give that up and it will most certainly break your heart. And make the world a worse place.

Bear the slings of arrows of re-imagining how perfect QuakeC and a perfect Quake engine might look EVEN if it breaks expectations.

Every engine author can do the conservative engine thing. This isn't why DarkPlaces is interesting. Just don't expect everyone to like "interesting" --- that isn't in human nature.

/End tl;dr post 
Hey Sock 
How did you go about your particle field controls in ITS?

I've got an emission system implemented that can throw sprites, bsps and models, but was wondering about better particle controls.

The main thing I'm wondering about is movement - I can just attach particles to an otherwise invisible emission, but was wondering what method you used, and if it'd be cheaper / better / faster.

Cheers :) 
@ijed 
Posted reply in ITS mod thread. If you have anymore questions let me know, will be glad to help. 
Thanks, Just Replied There 
 
DarkPlaces 
Is there any way to detect if DP is active from QC? Is there a function I can test exists and then supply different fog parameters?

Fitz engine fog
<density> <red> <blue> <green>

DP engine fog
<density> <red> <blue> <green> <alpha> <mindist> <maxdist> <top> <fadedepth>

I can't add the extra parameters to fitz it produces an error, while in DP the DEFAULT parameters fog out the sky. /sigh
Any ideas? 
DP Cvar 
Does anyone know of a specific DP Cvar value I can check? (I tried version but it is a string which is impossible to check) 
DP Only Cvar 
Found the answer, QC example below:

float dpactive;
if ( cvar( "pr_checkextension" ) ) {
dpactive = TRUE;
}
else dpactive = FALSE;
 
Fix Your Ugly Brace Style PLEASE! 
 
But That's A Cool Snippet Tho! 
 
Feature Detection 
In theory other engines might implement checkextension at some point, so you should probably be testing for features in darkplaces, rather than for darkplaces itself. It's like "feature detection" as opposed to "browser detection" in web design - that IE analogy is working overtime today (which I'd like to add was too unfair on DP, especially given how responsive LordHavoc has been to our needs!)

I've wanted for a while to be able to detect .alpha support on engines, to create entities which fall back to safer models on engines without it. At the moment it would only be darkplaces which gets the alpha-supported version, which makes the feature a bit too niche. 
Sv_gameplayfix_ 
Can't get more DPish than that, I suppose. 
Enginer Developers 
I honestly wish ALL engine developer would decide on a standard way of implementing features. Like for example fog, engine detection etc. As much as it is cool that everyone wants to do different things, trying to make content that works on multiple engine is just frustrating.

I don't want to create a preferred list of engines that work with my Quake content but engine coders really are shooting themselves in to the foot over this.

I choose "pr_checkextension" because it is highlighted at the top of the dpextensions.qc file (had to download a 220mb DP mod to get the file) as something to detect DP by. Maybe LordHavoc can say which variable we should all check by. 
 
at least all normal engines have the same syntax but wait until you find out that the rendering of the fog itself differs... :/ 
Feature Detection - How To Really Do It 
The pr_checkextension cvar only indicates that the checkextension builtin (#99) is available, which then lets you query engine capabilities.

pr_checkextension exists in TomazQuake, DarkPlaces, FTEQW, I think FitzQuake, and I'd bet a few others too.

What I recommend adding this to defs.qc at the end:
float ext_dp_gfx_fog;

void() InitExtensions =
{
if (!cvar("pr_checkextension"))
return;
ext_dp_gfx_fog= checkextension("DP_GFX_FOG");
};

Then add this to the top of worldspawn():
InitExtensions();

Now you can check the ext_dp_gfx_fog variable at any time to see if the DP_GFX_FOG extension is supported, which describes how that fog command behaves.

This is not a general catch-all way to detect DP however as any engine can implement that extension, there is not any special way to detect a particular engine (nor any plans for one). 
@LordHavoc 
Awesome, thanks for the extra information. I only plan to check for the basic DP engine from your site, I am not interested in supporting any other version.

I plan to use the following QC:

(in defs.qc)
float dpactive;
float dpextrafog;
float(string s) checkextension = #99;

(world.qc, function - worldspawn)
dpactive = cvar( "pr_checkextension" );
if (dpactive) dpextrafog = checkextension( "DP_GFX_FOG" ); 
Standards 
Several attempts to agree on anything failed. You could probably still find threads from like 15 and 10 years ago... 
Engines 
The other engines I listed are *not* darkplaces, they are completely unrelated popular engines written by Tomaz (TomazQuake), Spoike (FTEQW), metlslime (FitzQuake), and so on.

They support the same extension mechanism to detect capabilities, they offer different sets of capabilities but with significant overlap.

Again this is not detecting an engine, this is detecting a capability, it just happens that DP_GFX_FOG is supported only by darkplaces currently.

I checked TomazQuake 1.481, Fitzquake 0.85, and FTEQW svn 4255 (current as of this moment) and it is possible for other engines to add support for this same extension depending on the whims of their maintainers, but currently only DarkPlaces offers this extension, it was added back in 2001-04-05, been there a long long time. 
 
I know about the other engines (Fitz/FTE) my problem was with DP because of the fog parameters being different. I thought if I made my MOD work with Fitz it would work with anything, but it seems DP has gone in a different direction, hence the QC hack for engine detection. 
 
feature detection only works if the features behave identically in each engine. since they do not, there should be a way to identify engines instead. 
Just A Note... 
fitzquake does not actually support the quakec extension system. I support some extensions (e.g. worldspawn fog, worldspawn sky, entity alpha), but there's no quakec mechanism to detect them.

Most of the features I added in fitzquake are mapper-centric rather than modder-centric, which is why the extension system is missing (maps can't check it anyway, they can just add keys to entities or worldspawn and hope for the best.) 
 
quite some maps do come with, or require, mods, though. The line is quite blurred tbh. 
Walking On Walls 
Hey guys,

Are you aware if there are any (engine or quakec) mods out there that allow the player to walk on walls / ceiling?

I'm interested as I'm thinking that MC Escher-esque architecture would be fun to map.

-Ben 
 
FTEQW supports that with some cvar but don't ask me which one.

There is also a map by Markus Klar I believe. 
Blog Post 1000 
(It's really just coding post 1000, it just feels like it ok...)

New post on the blog, laying the groundwork for a series on displaying text in exciting ways. This one doesn't break any new ground, it just describes the way to display text by sending it character by character. There is some more exciting stuff in the pipeline though.

http://tomeofpreach.wordpress.com/2013/03/28/text-manipulation-in-quake-i-the-basics/

Comments, questions or solutions to the "homework" all welcome. Also is there an up-to-date mirror of the ai cafe site I can link to in the post? 
 
Spirit: 
you're probably thinking of that map "The Fly" by Markus Klar. 
Cool Map 
doesn't nearly get mentioned enough 
Cheers Spirit 
Here's a second part hot on the heels of the first.

http://tomeofpreach.wordpress.com/2013/03/29/text-manipulation-in-quake-part-ii-inversion-of-control

This time we've got the exciting idea which gets around the lack of arrays in quake. We don't actually use it to do anything interesting yet...I promise that by part III the example code will produce something cool to look at. 
And Part III 
Here we actually get to the good stuff - how to make text appear like a split-flap board. Just need the sound effect...

http://tomeofpreach.wordpress.com/2013/03/30/text-manipulation-in-quake-part-iii-parameters/

Hopefully the potential of the system shows at this point. I remember seeing how great the end screen for Qonquer was. My hope is by the end something like a menu drawn with a border which animates to open and close is made easy. 
 
I just played the fly :)
it was a fun map...

I couldn't find any cvar except for wall jumping in FTEQW :( 
Preach 
just had the chance to read some of your text manip articles, very awesome. I've known about this method for a while since you originally brought it up but this lays it out really well. Thanks! 
Cheers Necros 
I've got loads more ideas lined up (eventually the print functions should be able to draw a box round arbitrary scrollable text) but now I'm back to work posts will be more spaced out. Part IV should be out by the end of the week, it's about creating persistent state.

Credit where it's due: I first saw this idea in Pyrdon Gate by Frikac, which needed lots of menus and dynamic text, and did it like
textout('h', 'a', 'l', 'b', 'e', 'r', 'd', 0);
There was also a phase of creating text based games-within-games in quake mods, like Tetris and Snake. So using WriteByte to build centerprints is not original with me. The function-as-iterator and the dynamic print functions are new ideas though, and I'm pretty excited about them (as you might have guessed!) 
Ceiling Running 
fte features:
give self.gravitydir_z=1 (-1 or 0 to revert)
gravity will now point upwards.
give self.movetype=31 (3 to revert)
gravity will change based upon the angle of the surface below you. you can run up walls by just facing upwards and walking forwards.

they're intended to be used explicitly by mods, but you can force things with the 'give' command, and its ability in fte to poke various qc fields, but note that it only really works in single player.
The current SVN build will rotate the view along with gravity but slightly older ones won't, and this will be needed if you want to run on ceilings properly. 
Double Damage 
Didn't Matrix Quake have wall-walking of some description? I'm sure that was why it needed a custom engine...

While I'm posting something almost helpful I might as well link to the next Text post.
http://tomeofpreach.wordpress.com/2013/04/06/text-manipulation-in-quake-part-iv-state/
I swear the next post does all the remaining heavy lifting, and the rest will just be 100 fun things to do with text on a screen
 
Have there been any attempts to make a more modular/extensible qc engine? Like extending a known mod's (compiled) progs.dat with some of your own stuff (for mappers, mostly new point entities or monsters)? Is it even feasible? 
 
like modifying an existing mod?
or allowing modification of existing progs without source through the engine? 
 
Actually, that wouldn't be so bad. It would be cool if a compiler was integrated into the engine so you would just distribute qc files and when the engine starts it would compile it on the fly similar to Doom3/Quake4. 
 
Yeah, without modifying the existing progs. 
 
same as with the mapping help thread, should a link to the wiki or the coding section of the wiki be added to the start of this thread? 
Aaafter Ten Thousand Years... 
Yeah, you've had enough of a rest now, time for more blogging!

http://tomeofpreach.wordpress.com/2013/04/27/text-manipulation-in-quake-part-v-coroutines/

This is the last of the heavy-lifting, high-concept bit of messing around with text in quake articles. At the end of this one all the messy stuff to do with printing text is moved into the helper functions we've defined, and code that wants to print text looks uncluttered and simple.

Future articles will just be cool things you can do with this, like how to combine this printing with conventional strings, how to compare streamed text with a quake string, printing floats to the screen, automatically creating boxes for variable text. It's gonna be fun... 
Path_corner Enemies 
How can I get my enemies to do nothing on reaching the last path_corner?

Right now they begin walking towards the player (notarget or not) after ending the path.

I know I can just clean movetogoal or force idle instead of walk, but I'm pretty sure this has been fixed in other code bases, and by map hackery.

I've tried various ways of ending the path in editor, and nothing seems to work. 
Relevant Code 
��self.goalentity = self.movetarget = find (world, targetname,
�����other.target);
��self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin);
��if (!self.movetarget)
��{
����self.pausetime = time + 999999;
����self.th_stand ();
����return;
��}

So to get to the bit which makes the monster stop we need the find call to return world. The obvious move of not setting a target on the waypoint fails, because it's almost certain that the player's targetname is also "" (the empty string). This is why the monster instead starts walking towards the player.

So how can we make sure that find returns world instead? Well, find returns world if nothing matches. So what we do is choose a target is not equal to any targetname on the map, like "this is a made up targetname which nobody in their right mind would use".

Alternatively use Quoth and "wait" "-1".

I have to admit that before the post I had an misapprehension about find. I thought that the function looped around, so when it reached the last entity it would wrap around to world and back until it reached the start entity again. It doesn't do this - once it reach the end of the entity list it just stops and returns world. 
Interesting 
Thanks.

Does the player not having a null string targetname affect anything else like this? 
Don't Think So 
There's a single central function which handles how all entities get triggered - and that has a check for an empty target before it runs. The trigger_teleport_touch function also searches for a target, but the trigger_teleport spawn function throws an error if target is not set. Note that you could use a map-hack to get around the latter check, but it's a fairly useless effect. 
 
The obvious move of not setting a target on the waypoint fails, because it's almost certain that the player's targetname is also "" (the empty string).

...oh my god... all these years, I just assumed that that functionality was broken! that's why I added the wait -1 into quoth! I never saw the correlation between find matching an empty string.

I have to admit that before the post I had an misapprehension about find. I thought that the function looped around, so when it reached the last entity it would wrap around to world and back until it reached the start entity again. It doesn't do this - once it reach the end of the entity list it just stops and returns world.

This is also important to remember if you are using find when starting in the middle of the list. You need to remember to loop back around to the start of the list to cover all the entities you've missed by starting in the middle. 
Blogosphere Time 
So a new article for the blog, this time dealing with map hacks. I look at why one dodgy-looking part of a common map-hack technique is actually not so dodgy. It's also a chance to look at how floating point works. It's deceptively titled "Infinite ammo"
http://tomeofpreach.wordpress.com/2013/05/10/infinite-ammo/

For some more interesting reading on the issues of floating point maths I recommend Raymond Chan's recent post http://blogs.msdn.com/b/oldnewthing/archive/2013/05/08/10416823.aspx 
Demo Parsing Code 
For what it's worth, I've published my demo parsing code (a c library) at github:

git clone http://github.com/mandelmassa/libdemo

Libdemo passes my test suite on x86 win32 and linux, arm, and mips, so it's theoretically endian safe. It should support standard and Fitzquake protocols but there has been minimal testing on fitz. I will accept patches but I'm new to github so I don't know for sure how it works. License is MIT - basically, do what you want with the code. I hope someone finds it useful.

The purpose of the code is to read a Quake .dem file from your file system into a linked list in memory. You can edit the linked list as you wish, and then use functions in the library to write the demo data to a file.

I've used older versions of this code to write numerous tools for Quake demo editing, mainly for QdQ movies. 
Nextthink Time 
Can I give nextthink a value of (time + FALSE); ? 
 
in qc (and c), 0 is false and all other numbers are true, so time + FALSE just means time + 0 or just time.
You can do this and it means that the think function will run on the very next frame. 
Nextthink 
On a normal entity you can do that, and even stuff like nextthink = 0.05 works as well. As long as nextthink is positive and before the server time + the current frame length, the function runs.

But since this comes after your posts about func_train, I'm guessing you want to do this on a MOVETYPE_PUSH/SOLID_BSP entity. The rules are much more complicated for them, you can read some of the detail from earlier in the thread:
http://celephais.net/board/view_thread.php?id=60097&start=325&end=354

The most important thing is to always do self.think = self.ltime + delta, never compare to time directly, or you won't get the correct behaviour when your entity is blocked. delta must be strictly greater than zero, or the think function won't run.

If you need reliable, frame by frame functions to run on your MOVETYPE_PUSH entities, I'd recommend adding a function to startframe which finds all the relevant entities by classname and run your function on them there. You get the added bonus of getting to run the "think" function before they get physics run this frame. 
 
oh whoops, I missed that it was for a bsp entity. 
Well, I'm Guessing 
Because who would think to qualify their question like that, unless they already knew?

What it has reminded me is that I must find that old article I wrote about making smoothly-moving pusher entities, rewrite the bits that were hard to follow, and post it to the new blog. That and maybe some posts which condense all that info linked about about what physics happen when and why...it's all a bit random, needs a bit of a hook to hang it from. 
Trying To Make A Perfectly Smooth Custom Func_train 
No matter what I set delta to when I add it to ltime, it always stops for 0.100 secs at path corners. I've created all new functions just for my train entity so I can isolate what is going on.

I have only changed names and ltime increment values from 0.100 to 0.0001 (overkill precision for 1500fps (1/1500). 1500fps is the highest I've seen in Darpkplaces with my nose to the wall ;) ). I'm trying to get it to just go straight to the next frame without pausing.

In my SUB_CalcMove replacement there is a line:
self.nextthink = (self.ltime + traveltime);
This is the same as in subs.qc. Is this the culprit? 
Oh And Also 
I don't care about physics or player blocking. These trains are part of the environment and can be SOLID_NOT if that helps (crazy stuff if I just change it to SOLID_NOT though :D ). 
Quick Check 
Have you removed the following
if (traveltime < 0.1)
{
self.velocity = '0 0 0';
self.nextthink = self.ltime + 0.1;
return;
}

That sets 0.1 seconds as the minimum travel time.

Also yes, do change your entity to non solid with MOVETYPE_NOCLIP and you will have a much easier time. SOLID_BSP entities are hard!

Finally, you may not need to set think functions at all if you want an instant reaction. Why not just run the function directly? 
Technoplats.qc - Not Sure What's Wrong 
//Func_train Alternate: Goal is to have no 0.100sec
//stops at path_corners (unless wait is set)
//=================================================
//by Qmaster for techno mod, specific for my base map

//Current issues:
//Train flickers back and forth along path.
// Apparently the train is moving along the path
// at the speed of frame instead of time

//Predecs
//-------
void () traintech_next;
void () traintech_find;
void () traintech_move_done;

//My version of SUB_CalcMove (see subs.qc line 142)
//-------------------------------------------------
void (vector tdest, float tspeed, void() func) techtrain_move = {

local vector vdestdelta;
local float len;
local float traveltime;

self.think1 = func;
self.finaldest = tdest;
self.think = traintech_move_done;

//Does self.origin ever reach tdest? Should I do something like len below
// and do "if ( (len < 0.001) )" for this if statment to work?
if ( (tdest == self.origin) ) {

traintech_move_done();

}

vdestdelta = (tdest - self.origin); //get vector dist to target
len = vlen (vdestdelta); //floatify distance to target
traveltime = (len / tspeed);
self.nextthink = (time + traveltime);
self.velocity = (vdestdelta * (TRUE / traveltime));

};

//My version of SUB_CalcMoveDone (see subs.qc, line 178)
//------------------------------------------------------
void () traintech_move_done = {

setorigin (self,self.finaldest);
self.velocity = VEC_ORIGIN;
self.nextthink = CONTENT_EMPTY;
if ( self.think1 ) {

self.think1 ();

}

};

//Targetname is set
//-----------------
void () traintech_use = {

if ( (self.think != traintech_find) ) {

return ;

}
traintech_next ();

};

//Path_corner has wait set, so wait
//---------------------------------
void () traintech_wait = {

if ( self.wait ) {

self.nextthink = (time + self.wait);
sound (self,CHAN_VOICE,self.noise,TRUE,ATTN_NORM);

} else {

train_next();

}

};

//Find next path_corner from self.target
//--------------------------------------
void () traintech_next = {

local entity targ;

targ = find (world,targetname,self.target);
self.target = targ.target;
if ( targ.speed ) {

self.speed = targ.speed;

}
if ( !self.target ) {

objerror ("traintech_next: no next target");

}
if ( targ.wait ) {

self.wait = targ.wait;

} else {

self.wait = FALSE;

}
sound (self,CHAN_VOICE,self.noise1,TRUE,ATTN_NORM);
techtrain_move ((targ.origin - self.mins),self.speed,train_wait);

};

//Find inital path_corner from self.target and setorigin to it
//--------------------------------------
void () traintech_find = {

local entity targ;

targ = find (world,targetname,self.target);
self.target = targ.target;
setorigin (self,(targ.origin - self.mins));
if ( !self.targetname ) {

self.nextthink = (time + 0.100);
self.think = traintech_next;

}

};

//The train entity
//-----------------
void () func_traintech = {

if ( !self.speed ) {

self.speed = 24.000;

}
if ( !self.target ) {

objerror ("func_traintech without a target");

}
if ( !self.noise ) {

self.noise = "misc/null.wav";
precache_sound ("misc/null.wav");

}
if ( !self.noise1 ) {

self.noise1 = "misc/null.wav";
precache_sound ("misc/null.wav");

}
self.solid = SOLID_NOT;
self.movetype = MOVETYPE_NOCLIP;
self.use = traintech_use;
self.classname = "train"; //I hope this doesn't set anything engine-side
setmodel (self,self.model);
setsize (self,self.mins,self.maxs);
setorigin (self,self.origin);
self.think = traintech_find; //Needed for use function
traintech_find();

};
 
Umm... 
you can ignore that previous post. I'm implementing Custents trains (with tweaks of my own haha) 
Text...or Should I Say Numbers 
So BSP things take a back seat to another Text article:

http://tomeofpreach.wordpress.com/2013/06/05/text-manipulation-in-quake-part-vi-numbers/

Today we take a look at printing out numbers, one of those things you just take for granted in normal string code. But it's really important if you're going to use this to display, say, a custom scorecard like Qonquer did using screen prints.

I actually tore through making this one, because I was excited about an esoteric application of it - creating strings like "*21" or "*87" with any number, using the text streaming. It turns out that the loopholes for turning text streams back into normal QC strings are smaller than I imagined - just a bit too hacky. So that got cut for now, but I've not totally give up hope of making it useful. 
 
just took a quick scan over the article... the expanding code box doesn't seem to work for me. it expands, but it's all on a single line (the <br /> tags are visible). 
Grr, Wordpress 
That was working a few days ago, and then the gremlins messed with it...fixed! 
Setsize With Respect To Other Vectors 
HI:

I know the only 3 valid sizes are point, shambler and player, but I am just experimenting with the superspike model, attempting to have it do things like ricochet off bsp's for example, and one problem was it was not pointing in the new direction after rebounding, but I found vectoangles of the velocity ought to fix it? However I was wondering how could we use that to look at the spikes angles, and do a setsize that takes us out of the models default point size, and give it a better bounding box, that is more shaped to the model? I did some rudimentary tests, and found that:

setsize (self, '1 -0.5 -0.5', '8 0.5 0.5');

(self being the spike)

Works , except if its first angle coordinate, which I am guessing is its yaw? ,Is the larger value of the 2? Im just curious if anyone here can see a formula where we could resize the bounding box depending on its angles , or maybe the velocity, so that its always covering the spike....? 
QuakeC To Fix Model Wiggles? 
Can I use quakeC to get rid of the wiggly darkplaces models in my game? Or do I need to switch from .mdl to .mdl3? (or whayever the extension was, just a guess my friend made)

Very curious, maybe it's something completely diffrrent. 
Typically 
It's best to use the LG on the Wiggles; they're a tough enemy and their armor wedgie ability can catch you out when you're least expecting it.

...

Give us more info on the problem you're having :) 
 
i think he's talking about vertex dancing.
in which case, yes, the only solution is to use a different model format. md3 will solve nearly all your problems. 
Vertex Dancing 
@ijed haha necros summed it up

@necros thanks for the info! 
Heh 
.iqm is a good format as well and also supported by dark places as well. 
Ijed 
Oh thanks :P 
 
Sorry, I always forget that one since I've never used it, but I believe it might be better to do IQM because it is supported and actively being maintained in blender plugins...
I think it has skeletal animation as well? 
Yep 
 
LTIME PAINS 
How is ltime calculated? In otherwords, why would this code have two separate entities start their movement at different times? It's starting essentially func_trains (they're not really but they are MOVETYPE_PUSH and move the same way)

local float eltime;

eltime = self.ltime; //force ltime to be the same?

stemp = self;
self = self.target1;
self.ltime = eltime;
self.think = qtrain_start;
self.nextthink = (self.ltime + 0.100);
self = stemp;

stemp = self;
self = self.target2;
self.ltime = eltime;
self.think = qtrain_start;
self.nextthink = (self.ltime + 0.100);
self = stemp;

...
...
...

I have already tried the servertime trick with StartFrame, but they still start at different times. Apparently they aren't starting on the same frame??!? 
Ltime 
ltime is incremented for the number of seconds the door or whatever has been moving for. If the door is blocked for whatever reason, ltime will not change and the door will freeze in place.
this ensures that the think is scheduled for when it arrives at its destination rather than in true seconds.
the whole point about ltime is that its local to the entity in question, and is allowed to freeze as required. If you want your trains to work as a pair, you'll need to ensure that if one is blocked, the other also stops moving, and take extra care to re-sync them when they start moving again.

seriously, why has noone made a map where you have to lure monsters to a certain area to block a train to desync them so you can jump from one moving platform to another? :s 
Spike Is A Genious 
That's a cool idea! Secret area maybe?

Okay. So bprint debugging has confirmed that the nextthink's are infact the same for both entities. Does this mean that they will start at the same time though? Obviously no. Still no cookies.

So I'll step it through. Preach? Correct me if I'm wrong anyone.

Function sets think for two entities regardless of targetname (entities are stored as entities not targetname, target1 and target2 are .entities)

Function sets nextthink for two entities

Nextthinks are confirmed the same, bprint to console so I know.

Entities are set to start in nextthink seconds

This frame just set the nextthink time, so these entities will get called in the same frame in ltime+x. Well, theoretically they would. What's the tolerance for time when attempting to get two entities to start on the same frame in x seconds? + or - 1 frame? 10 frames?

These entities are not moving so ltime is not increased.

They never start then theoretically. But they start anyway just to confuse me.
1st one starts after about 2.5 secs
2nd one starts after about 4 secs

So how is ltime incremented while an object like a door is NOT moving???? 
Potential Reason 
Remember that the quake engine loops through entities and applies physics to them in a sequence. It can't process them "simultaneously". Imagine that we've already run physics on target1 this frame, but that we haven't run physics on target2. If we run your function at that moment, the two will be synced when the function ends, but by the end of the frame we'll have run an extra tick of physics on target2, desynchronising them again. Could that be what's occuring? 
 
a bmodel entity must have it's nextthing greater than ltime or it will not move. 
 
its a bit clumsy, as it tries to get the maths precise so that the train stops exactly where it needs to be even if its only a fraction of a frame away.
the ramifications of this is that ltime does not increase if self.ltime>=self.nextthink.

thus if you want a bsp object to move or spin, it MUST have a valid nextthink set.

remember that the timings are precise in that the movement covers the correct distance, rather than it arrives at the projected time. this isn't some national railway with precise time keeping. Its just trying to avoid moving through walls if you've got a low framerate.

If you have some third entity clearing everything out but the velocity, one pusher can still get blocked and ltime will not update while the other starts moving around freely.

An entire second and a half in 4 is too high for any precision issues. Are you sure its not getting blocked or anything? You're sure that you're using .ltime and not time when setting nextthink, etc? 
FIXED!! 
Turns out I had forgotten to recompile with ltime and it was still using time. However, even though with ltime it was reealllly close, I still had a discrepancy of about 0.8 to 1 game unit when the two entities started from the same point.

-Edit!-
------------------
I FIGURED IT OUT!!!!!!!

There is a latency, a lag, within a frame from one object to another when the physics are calculated. The two entities had been created several dozen entities apart in the map (about 15 min of mapping on another part of the map while I was thinking about what to do). This means that several dozen entities needed to be ran before the other entity would run, causing enough time lag for a small gap in start times.

The fix?

Duplicated lagging entity. Deleted original. Placed duplicate entity back in the same spot.

Done.

And that only took me 2 months to figure out.
Wait till you see what I use it for in my new map! 
Fish! 
An obscure bug with the monster that nobody cares about.

Basically, they don't move when scraping their heads against the top of the water volume they're in.

Anyone have a fix for this? I can trade you a fish model with a normal sized head when it dies... 
 
A simple way is to use pointcontents to check a point above the fish's head and if it is out of the water, reset the monster's z origin to the previous frame so that it can still move horizotally, but won't move upwards into a position where it will be stuck.

This has the small chance of making a fish get stuck in a wall, but you'd have to make a very specific shape of wall and water edge for it to happen. 
Bait On A Hook 
Banging their heads on the surface usually occurs when they're trying to swim up to the level of an .enemy who's higher up than them. You can create a dummy entity called worm. When you want a fish to swim, stash their proper enemy in a temporary variable, and set their .enemy variable to the worm. You can then position the worm to lead them where you want - place it in the direction of the real enemy, but at an appropriate height vertically. Remember to reset .enemy once you've called the ai movement functions. 
Aha 
The issue was obvious really - like what happens to a scrag when it hits ceiling and you're above it.

Thanks guys. 
Doing Things The Bad Way 
The above post is the good way to do things. But we don't like the proper way of doing things, we want to save an entity! The bad way to do things is to instead stash the old height of the fish's enemy, move THE REAL ENEMY down, then instantly restore that enemy's position when the movement function is done. If you're breaking the rules, you should go all the way and skip the call to setorigin - that would only cause actual collsions to occur when you want to avoid that happening. God help you if the fish collides with the enemy though... 
Field Pointers 
New QC article today - on field pointers. There are two - yes TWO - reasons to read today's article! One is if you'd like to learn what a field pointer is in QC and how to use them. They help you write generic code.

Even if you don't care about the technical knowledge, the article solves a practical problem: how do you code an entity which has templates? Templates here are where a mapper can set a single value on your entity and get a bunch of default values applied, and the mapper can selectively override these defaults.

http://tomeofpreach.wordpress.com/2013/08/07/field-pointers-in-qc/ 
 
As always a good read and I learned something new about function parameters. :)

I�m going to share a snippit of code from Quoth
You should one day publish that code, I imagine it would be awesome see how you organize and structure stuff. I would love to see how you implement features. 
Gleaming Spires 
Don't be daft, I'm showing off the good bits! The rest of it is all cludged together. Bit by bit I'll try to blog the how-to behind all the good bits, so that everyone can make a mod better than Quoth. 
 
Don't be daft... all the bad bits are me. :P 
Almost Forgot 
Here's the fixed death frame fish model:

https://www.dropbox.com/s/eluwi8hwa9ot0yd/fixed_fish.7z

It's also got some 'small' frames, if anyone wanted to make, say, a school of piranha. 
 
oh btw, that's a great post about the field-as-arguments. 
Nonsense Necros... 
I was considering posting an awful bit of Quoth code for the sake of comparison - and the function that sprang to mind immediately was the coop removal function, which I wrote entirely myself! 
More Field Pointers 
So here's a more thoughtful counterpoint to the lovely beautiful code stuff above. It's a second blog post about field pointers on the surface, but it's also about the battle writing clean code and battling the technical limits. There's also an exciting cliffhanger for part III...

http://tomeofpreach.wordpress.com/2013/08/09/going-overboard-with-field-pointers/

Since this is really a mapping forum, I'll give you guys the cuttings about how this stuff relates to maps. Yes, it is possible to overflow the stack if your triggers get too complicated, even in stock Quake. You're probably doing some serious neg!ke style map hacks if you get to that point. There's a workaround if you ever do hit the limits though: give one of your triggers a delay. The stack will be reset between the triggers which precede and follow the delayed trigger. You can think of this like giving the engine a chance to catch its breath! 
Revenge Of The Field Pointers 
http://tomeofpreach.wordpress.com/2013/08/23/getting-even-with-field-pointers/

Here's an article with two ways of fixing the problems from last time - using macros and using arrays.

I was going to go further, try and create a system where you could have an arbitrarily long chain of entities using each other without overflowing the stack. The plan was to split SUB_UseTargets in two, the first half would make a global linked list of targetted entities, and the second half would work through this list and call their use functions. If one of these use functions called SUB_UseTargets recursively, it would add the entities to the global list but then return, and let the original invocation call the use functions.

There are two problems with the plan though. One is that the order of which use functions start and complete has been changed by this transformation, which could break maps in some unanticipated way. The bigger problem can be found in this discussion:
http://www.celephais.net/board/view_thread.php?id=4&start=13098&end=13108
It's possible, if maybe unlikely, for an entity to legitimately be triggered recursively. This doesn't work well with the linked list. There might be ways to fix this, possibly by letting the function recurse in these places, but I'll have to give it some more thought. 
Chainlist = Findradius(origin,radius) 
It is the subtle things in life that cause the most problems ...

The findradius QC command can work differently in Darkplaces compared to Fitz engines. It may not seem like much of a difference but it can cause serious problem if you are not aware of it.

The Fitz engine ignores all entities with .solid=SOLID_NOT when creating a chain list for the findradius command. This is a good thing because certain types of entities (particles, delay spawns) can be excluded from this function easily and included when needed.

Darkplaces (older versions) does not seem to have any exceptions, it will gladly find ANY entity within range and create a chain list. The problem is the findradius command will freely 'corrupt' the chain field and if you use it for anything else then those lists will start to fall apart.

I recently switched over to a chain list for my particle system because it was crazy to keep creating/deleting them all the time. So I cycle round a chain list and it works fine in Fitz. In Darkplaces the lists were getting corrupted and I did not know why and then I finally found the problem, Findradius was finding the particles (my system can use sprites or models) and changing the chain field.

It seems Preach has run into this problem (post#962) but I could not find any other forum links. Apparently there is a sv_gameplayfix_blowupfallenzombies to fix this but the naming of it is not easily recognizable as something to do with the findradius command.

I tried to find a way for Darkplaces to exclude entities from the Findradius command. I set the model field to an empty string or "null" (dp documentation) and setting the bbox and size to zero, but nothing seems to make a difference.

I assume the latest version of Darkplaces fixes this by disabling the fallenzombie gamefix, but not everyone using DP updates all the time. It certainly easy to code for this change, but it is frustrating to find out about this the hard way. 
Compatibility Battles 
Yeah, the more experimental engines are a bit more of a hassle to keep combatible with. Perhaps we should try and create a little community config file which restores darkplaces etc. to standard quake compatibility. Then add it to quake.rc to execute between config.cfg and autoexec.cfg. Incidentally that's the best time to aply strongly recommended cvar defaults - it replaces whatever was autosaved in the config last time, but lets people who think they know what they're doing override them in the autoexec file.

In your specific predicament, I'd recommend creating an extra entity field, perhaps:

.entity p_chain;

...and use that to replace your code's use of chain
Could Also Contact LordHavoc 
He's usually on the ball with these types of fixes and happy to help out. 
 
sv_gameplayfix_blowupfallenzombies defaults to 0 in current builds (along with other such gamecode-changing settings), but the old value might linger via configs. Probably the easiest thing to do is to detect dp at load time somehow (to avoid warning messages in other engines) and just cvar_set it to 0.
(use solid_corpse instead of solid_not if you want to be able to shoot/find zombies, I guess)

but yeah, its probably better to simply use some other field like .enemy or .owner instead of .chain 
Blogging Back 
So I took the idea I posted above, along with some other thoughts which have been coagulating for the past few months, and made a blog post. It's all about the engine config system, written mostly for someone who's writing a mod and wants to know what to do - and not do!

http://tomeofpreach.wordpress.com/2013/09/05/quake-rc-and-being-a-good-citizen/

There's a nice bit of copy-paste code at the bottom for controlling darkplaces cvars, although it covers both the opting-out and opting-in cases so users may need to tweak it slightly to suit their needs. 
Locals Conflicting With Func Args? 
Is it possible for a local to conflict with arguments to a function? I noticed that with a (clean) progs106, the SpawnMeatSpray function (maybe more) takes two vectors, org and vel; but in the function itself has a local named org. SpawnMeatSpray uses org only when calling setorigin and it seems to be using the argument org, not the local (assuming, can't check atm). 
Qc + Locals 
arguments ARE locals.
dupe defs are ignored.
initialising a dupe is an error (vanilla qc initialisers make it a constant).

qc doesn't support scoped locals, other than to the function. unlike C+Java+etc, blocks don't have private locals, and locals are still valid beyond the end of the block that they were defined in. 
Thanks, Spike 
 
Buzzsaws 
Does anyone have usable buzzsaw code? For some reason the buzzsaw.qc file I have doesn't work and the saws don't match up with path_corner's. I've tried rewriting the code to use SUBCalcMove but it starts moving off at an angle instead of following a path, but the "original" I have cause it to jump around in my map. I've tried custents buzzsaw.qc but it does the same thing. It'll follow the paths in r2m7 but be offset vertically from the actual path locations and do a kind of jiggle up jump.

What am I missing? 
... 
Okay, I found the original doe_qc.zip source code online: http://www.gamers.org/pub/idgames2/more_idstuff/doe_qc.zip

Copied buzzsaw.qc into my code and ran it. Buzz saws still hovering about 16 units above the tracks they should be in the Last Bastion (r2m7). Found doe progs.dat (dated 2008 from when I copied it off the CD, verified the same size as in the pak0 under rogue directory) and it does the SAME THING!!

Is this Darkplaces only related? 
Okay Yep. 
it's a darkplaces bug. Buzzsaws work fine in WINQUAKE.EXE. Is there a gameplay console var fix for this?? 
Okay... 
what's happening with the buzzsaws is that they behave like monsters. They change their movetarget when their bounding box touches a path_corner, not when their origin reaches the path_corner's origin. Now then...to figure out how to ignore path_corner.touch functions.... 
Buzzsaws Solved! 
No code modifications required.

Just positioned my buzzsaws outside of the tracks such that they have time to move and get inline with the path_corners. (had to bsp_to_map the r2m7 map and see what they did to make it work, the buzzsaws were about 64 units away in both x and y directions from their starting path_corner.) There are still a few glitches if the path_corner's are positioned a distance away from eachother that Quake doesn't like, or if the speed of the buzzsaw isn't just right. (10 usually works and is default) 
Sounds Good! 
 
Keeping Score 
Any mod out there that can count damage done in a level and give a total at intermission?
I think it would be fun. Make a replay of the original game interesting. Timing a quad damage would be very important I suspect. 
Stealth Damage 
I added damage done to my ITS mod, there is a stealth stats screen you can check at anytime during play of a map. 
Sock 
That's the idea. A mod that can take e1m1 and give a score at the end without modifying anything else. Vanilla Quake with a score card at the end. I'm sure it could get complex give points for health, armor and ammo and suck points off for total time. 
 
I've added damage given, and damage taken to my multiplayer mods. It's not difficult at all.

I then get a survival skill score by this
score = damage_given / (damage_taken+damage_given)

:D 
 
I kinda hope that some day more engines will support sqlite and we could use that to track and record all kinds of things locally. FTEQW supports it. 
 
sql is only really useful for single player, and even then you can often get away with frik_file instead.

when it comes to deathmatch you probably want some central server recording matches in aggregate, which would likely be programmed in something more php-ey instead of qc. naturally this avoids sql in the game server, but does require some sort of communication to said server... 
Extract Vertexes From .MAP/.BSP 
Is there an easy way to heist the vertex/mesh data from a Quake map? I'm trying to whip up some C# for using Q1 brushwork inside of Unity3D, and I'm hitting a wall.

Since I don't care about the lightmaps or vis data, I figured I'd try to divine the vertex data from the .map, but converting from the brush based geometry (calculating planar convergence) is beyond my skill. It'll probably be easier to let a compiler do the lifting on that and just read the data I want out of the resulting .BSP Are there any libraries available for working with Q1 .BSP? 
 
i think the bsp is a better choice as it is more mesh-like, and is already cleaned of things like tjunctions, overlapping polygons, etc. 
 
 
when it comes to deathmatch you probably want some central server recording matches in aggregate, which would likely be programmed in something more php-ey instead of qc. naturally this avoids sql in the game server, but does require some sort of communication to said server...

The most obvious solution is to program the central server to mimic a client connection to the game server! Sure you waste a client slot on your stats bot, but who plays 16 player deathmatch anymore anyway...Of course you'd communicate directly from the QC using SVC messages to ensure your code runs on every engine. Just write, lets say byte-by-byte UTF8 encoded JSON, wrapped up as a sprint statement to the bot.

Preach goes off to write a web server in QC and is never heard from again 
 
my inner nerd has been awakened. this sounds like such a cool idea :D 
 
@preach
I know you jest, but there are bots that connect to QuakeWorld servers to scrape scores already...
That said, QuakeWorld does at least support explicit spectators so you don't need qc code to make them non-solid to avoid interfering with the game with free frags.

@ALLCAPS
walk the surface list. each surface has a list of edge indicies (either positive or negative). each edge has two references to each vertex. if the edge index was positive, take the first vert refered to by the edge, if negative then take the second (negate the edge index so its positive, but no bias as 0 is always invalid, and -0 can thus never happen). Walk the edges to get the list of verts for each surface.
To determine texture coords, you'll need to do some maths based upon the texinfo[surf->texinfoid] stuff:
vert.s = (dotproduct(texinfo->vecs[0].normal, vert.xyz) + surf->texvec[0].dist) / texturewidth;
vert.t = (dotproduct(texinfo->vecs[1].normal, vert.xyz) + surf->texvec[1].dist) / textureheight;
where dotproduct is of course ((a.x*b.x)+(a.y*b.y)+(a.z*b.z))

the texture index used is refered to via the texinfo object, which is of course refered to by the surface object.
the texture/miptex lump inside the bsp has this form:
int32 numtextures;
int32 offsetintolump[numtextures];
the start of each actual miptex is a 16 byte name, followed by the width and height as int32s, and if you're using unity or whatever then you should probably just use replacement textures and skip parsing beyond those fields, but if you do, there's an additional 4 offsets to the 8bit paletted image data after the height, expressed as offsets from the start of the texture and not the lump, one for each of the 4 mip levels that software rendered quake supported. You can likely just use the first and ignore the others. 
Q3 BSP Header Parsing 
I decided to swap from using Q1 BSP to Q3 BSP, because there is a lot more documentation on Q3 BSP specs. I'm reading in the bytes for the header and everything looks good except for the first entry in the directory.

The length isn't a multiple of 4. At first I thought it was my code, but I checked the .bsp with a hex editor and it really isn't a multiple of four in the .bsp, and I checked multiple maps. Is this normal?

Is it because it's the entities node, and they're stored as strings/char[]? The spec says each directory's size should be a multiple of 4, and it doesn't say anything about the entities directory being exempt from that. 
Noticed 
That if I "round up" the size of the entities lump to four bytes it then matches with the beginning of another lump, so perhaps it on specifies how many single character bytes there are, instead of how many four-byte dwords it takes up? 
 
4-byte alignment, not 4-byte length. 
Figured 
I finishes up extracting and parsing entities before I passed out, and everything seems to be working! Good to have clarification, though; thank you. This is my first time ever trying to decode/parse a binary blob like this, so I'm learning as I go. 
SharpBSP Is Born 
Here it is. Not finished, but getting there.

https://github.com/mikezila/SharpBSP

Once I have it working well and maybe crank out a winforms application that shows some info about a loaded .bsp I'll make a thread/news post about it.

I use C# instead of C++ partly because Unity3D uses it, and it'll make pulling this data into a Unity game/scene very easy, and partly because I'm a scrub that can't handle C++.

Not that anybody cares, but it's free to take/use/copy/modify. 
Bezier Calculation 
I've made some pretty great strides in parsing and rendering Quake 3 maps. I've hit a snag, though, and that snag is bezier patches.

Here's a video showing what I have so far, and my issue with the patches:
http://youtu.be/8RfwLP0BrSI

Textures, texture mapping/coords are working 100%. Only textures provided by shaders are not working. Animated textures and billboards aren't implemented yet, either.

But issue is that the code to calculate bezier patches is code I lifed from an article on render Quake 3 maps, and did my best to port from what I assume is C++, to C#.

I used these two documents to parse the .bsp and to try rendering the bezier curves
http://www.mralligator.com/q3/ - Map format details
http://graphics.cs.brown.edu/games/quake/quake3.html - Details on converting the vertex systems/scale and bezier curve code

I'm really stuck, as I don't understand enough about bez curves to write my own implementation. Anyone here worked on rendering them that could lend a hand/advice? 
 
you don't need patches (they're evil), just use q3map2's -patchmeta argument when compiling maps for your game.
q3map2 will then generate trisoup instead. 
Aces 
That's great to know, and I'll use that for sure if I develop a Q3 .bsp intending to load it into uQuake instead of actual Quake, but I'm tackling the issue of rendering the patches for the sake of being able to render existing Quake 3 maps that use them. 
ALLCAPS 
why not look at the quake 3 source code to see how it tesselates bezier patches? 
 
My raw understanding of the patches (and C/C++) is very limited, but I will likely have to do that. Right now I'm working on rendering multi-patch faces without any tessellation, just the reference points. I can render single-patch faces, but I'm working on how to extract the 9 reference points from the face, and making an individual patch out of that when there is more than one patch in the face.

Once that is done and references are rendering correctly, the only piece of code that will need changing to have beziers 100% working will be the method that takes those control points and fills the patches vertex and triangle strip data. Getting closer. 
Okay.... 
well if your problem is the theory behind it, maybe i can help a little bit.

First, quake3 patches use bezier curves, which are parametric equations. This means that to generate a point on the surface you need to input a parameter. The parameter can go from zero to one, and as it moves from zero to one the point generated moves along the curve from the start to the end. The parameter is usually called "t".

Second, quake3 patches use quadratic curves, not cubic curves (which are more common i think), so that means they have 3 points to define a curve instead of 4. The three points are startpoint, control point, endpoint.

Third, how to solve a quadratic curve? First, look at this picture:

http://upload.wikimedia.org/wikipedia/commons/2/2d/Bezier_2_big.gif

P0,P1, and P2 are the three control points. Green stuff is intermediate calculations, and the red line is the final curve.

So to solve for the black point (a point on teh curve) you first find a point on the line from p0 to p1, call that A, then find a point on P1 to p2, call that B, then find a point on the (green) line from A to B, that point is your solution (black dot.) In all three cases, when you "find a point" you are finding the point using t -- if t is 0.5, find the halfway point. if t is 0.25, find the point 1 quarter of the way from the first point to the second point.

Okay, assuming you understand all that... the quake 3 patches are 2-dimentional surfaces, not just single lines. So instead of 3 points, they have 9. To solve it you need to do multiple tasks like the one above (solving a simple 3-point curve.) Since it's two-dimensional, to find a point you need two parameters instead of 1 -- instead of t, you need s & t.

Imagine the 9 points are arranged in a 3x3 grid. First row is 1,2,3, second row is 4,5,6, last row is 7,8,9. First solve three horizontal curves using s -- 123 is the first curve, 456 is the second curve, and 789 is the third. Each uses s as the input parameter. Each gives you one new point -- A,B,C. Now solve curve ABC with parameter t. Now you have found a point!

Okay, so now you can find any point on the surface of the patch using s,t coordinates. How to render a patch? What you do is divide the patch into a grid of quads. The vertexes of the quads are determined by inputting s & t. If you want N * M quads, you need (N+1) * (M+1) points. The first point is 0,0 and the last point is 1,1. Intermediate points are evenly spaced in between. 
What A Scholar 
That helped me so much, that using that info, some time and study, and some patience I have perfected parsing, tessellating, and rendering (with textures!) Quake 3's bezier patches. Huzzah!

http://imgur.com/a/i470V

Textures that are provided by shaders in Quake 3 aren't working for obvious reasons. I also need to debug lightmap ripping/application, but those are pretty minor issues. Unity's realtime and baked lights look better anyway.

Thanks a ton. 
UQuake 
Here is a link to the github of the project. It's free to do with as you please.

https://github.com/mikezila/uQuake

Don't want to keep mucking up the coding help thread, so if/when I make videos and take screenshots to show it off I'll probably make a new thread. 
 
Nice, you got it working! Glad to help. 
Neat! 
Is this a quake 1 engine?? 
Unity3D 
The engine itself is Unity3D, which is a freely available engine that you can use for almost anything. I've built a reader for .bsp files, and a "renderer" that creates the level as Unity gameobjects. It's not a "true" bsp engine because only the geometry is used, things like leafs, nodes, the bsp tree itself, and vis data is not used. Unity handles those things on its own at runtime.

Right now it only supports Quake 3 maps, but I want very much to add support for Quake 1 maps. Once I get lightmaps working on Quake 3 maps I'll set to support Quake 1 maps. My original goal was actually Quake 1 maps, but extracting the geometry from them is a little more complex than Quake 3 maps, so I did this first as a warm up and to see if it was possible. 
Very Cool 
nice work figuring it out! 
It's Time For Q1 Support To Begin! 
Alrighty, Quake 3 lightmap support is done. The colors aren't as vibrant as they should be because Unity's RGB lightmap shaders are lame, but the data is ripped and applied correctly. I also replace shader-modified textures with non-shader versions at runtime. Like on the strange flesh-spire and lava here.

http://imgur.com/tO3SSUP

But like the title says, it's time for Quake 1 support. The most comprehensive guide to the Q1 .bsp specs is here:

http://www.gamers.org/dEngine/quake/spec/quake-spec34/qkspec_4.htm#CBSPG

Is this still current? It's really old, and says it matches the .bsp version used in Quake shareware. Is there a more detailed or updated guide on the .bsps produced by modern compilers? 
Q3 Lightmaps. 
q3 has overbrighting. the lightmap scales between logical rgb values of 0 to 4 rather than 0 to 1. The lazy way to deal with that is to just multiply the values by 4 and clamp to 255. The real way to deal with it is to scale your vertex colours by 4 instead, or to put the same scaling in glsl.
This nonsense allows bright areas to oversaturate textures, thus textures which are grey colours can brighten up to become more white in bright areas.
Software vanilla Quake has a similar feature. vanilla glquake just clamps.

Check some engine's bspfile.h, like that markv_bsp2 zip I hacked together recently if you're after bsp2 support. Otherwise bsp29 is still the same bsp29 that's documented in your link. 
Trianges? 
Was studying the BSP29 document some, and I realize that nowhere is there a list of triangles for any of the faces. Is there something I'm not seeing, or does it fall to me to figure that out using sorcery? 
I Don't Think Bsp29 
Works like that. It's the .map file that has that info and that is then compiled into a scrambled file? 
Process 
When I was reading the Q3 .bsp into Unity my process was like this.

Take a face. A face has a list of vertices, and a list of triangle indexes into that faces vertex list. So to make a mesh out of a face all I had to do was make a mesh, and set it's vertex and triangle arrays to the data I pulled out of the face. Each vertex object has data about it's position, texture coords, color, and lightmap coords. The whole process was actually pretty slick.

In Quake 1 it seems like every surface has a list of edges, and each edge has two vertices. Using some simple rules and maths getting a list of verts and the texture mapping info for those verts doesn't seem too hard. So I make a mesh and add the verts and texture coords. But how do I form triangles? In Quake 3 that data was provided for me, but here it's not.

Is each face only going to be three verts? That doesn't seem right. Are the faces always going to specify their verts in the order needed to form triangles out of every three verts? 
 
Noesis can load bsp files, you might be able to find well readable code in there. http://oasis.xentax.com 
ALLCAPS: 
you have to triangulate it yourself, i think. All the faces are convex polygons, so it shouldn't be too hard to triangulate them. Only down side is there may be some degenerate triangles due to extra verts added for tjunctions. I guess you should keep these because otherwise you may get visible cracks. 
 
Dang, really? The renderer back in the day mashed out the tris for the whole map each time it loaded? That's unreal. 
 
actually the software renderer directly rasterized polygons, so it never needed triangles. Later opengl versions would use GL_POLYGON primitive type, so they didn't need triangles either. 
Well... 
I guess since every poly is going to be convex I can just ham-hand it and make tris using a pivot point and casting to each other vertex. 0-1-2, 0-2-3, 0-3-4, etc. It's the least efficient way possible, but I guess it's sure to cover the full face. Come to think of it when I r_showtris in some engines it looks like that's what it's doing. 
Efficiency 
How is this "least efficient"? I don't see a more efficient way to generate triangles from convex polygons. 
 
Honestly I just assumed it was the least efficient/elegant way since it was the first solution I thought of. Probably because it's simple. I just figured there'd be a more complex, "better" way. 
 
each edge has two sides. pick one vertex from each edge based upon the side of the edge you're using. side is determined by whether the edge index is negative or not. this will get you a convex polygon (aka: a triangle fan). more modern renderers can trivially generate triangles from that.
the whole thing is just triangle fans. software kept it like that because its easier to clip+frustum cull, which is part of how it managed to avoid all overdraw from bsps.
remember, these face polygons are never concave. there's no holes or anything. its pretty trivial because of that. 
Efficience Of Triangle Fans 
Strictly speaking there may be an inefficiency there in rendering>/i> those triangle fans. According to a half-remembered article I read a while back, long, thin triangles are slightly less efficient to render than evenly proportioned ones. I'd hazard a guess that's due to better cache-coherence properties of the latter.

I wouldn't worry about it though, primarily because it's a tiny difference. Also because almost all the polygons in quake maps will be 6 sides or less, so there's not a great deal of difference between the best and worst choices.
 
 
This is where I've had the nagging thought that I'll bet modern engines could just create large, texture sorted buckets of triangles representing the entire level and just throw it at the video card. Odds are that on even a mid-level machine, it would run fine.

Keep the BSP for collision checks and line-of-sight stuff, but in terms of raw rendering I wonder if parsing through the VIS data is actually a detriment these days. 
You Know... 
Brute forcing winning over the elegance of a BSP traversal algorithm always felt like an aesthetic unfairness to me.

Not that I mind scraping the vis times. 
Almost Reads Like A Carmack Tweet 
I need to get some sleep 
BSP 
Remember that visibility tests aren't used exclusively by rendering - they're also used by the ai as the first step of deciding if the player can be seen or not. So you will take a double hit on performance as every monster in the level starts doing traceline visibility test every frame.

Of course, it's pretty easy to test the hypothesis that vis is unnecessary - just build a map, saving a copy of the un-vised BSP file as you go. Then compare performance across the two files. You could even run vis at all the different levels and have multiple points of data. I don't know if there's any hard data on how much of a fps gain you get from making vis more accurate, it might be thaat they highest levels don't provide a good return on investment. 
TrenchBroom Does The Brute Force Thing 
It just throws texture-sorted triangles at the GPU, and it's pretty fast. The only drawback is that you have to reupload a lot of data to the GPU when the user changes the geometry, but since usually only a few brushes are selected at a time, just uploading the selected geometry is fast enough. 
 
Preach - You'd need an engine change to test it properly. If it's traversing the BSP tree to gather up the triangles every frame then it's still eating overhead that a bulk renderer wouldn't have.

I wonder about the hit there though, on your monster example. Line traces in a BSP are extremely fast. But pre-computed VIS data is always going to be faster there. The problem is that it would take a lot of work and engine coding to come up with a definitive test. :P

Sleep - That's what ToeTag did as well. I think there was a basic cull for stuff entirely behind you, but that was about it. Everything else got chucked at the card, sorted by texture. I never really saw it slow down at all... 
UQuake Performance 
uQuake leaves all that up to Unity to handle, it discards the bsp tree itself, the vis data, nodes, planes, all that jazz. Unity decides per GameObject what should be rendered and what shouldn't, and with each face/patch its own GameObject it can cull invisible regions and polys very well. In essence I'm throwing the entire level at the engine at once, but the engine is good at throwing only the parts that can be seen right now at the video card. Works well even on an Ouya/HP Touchpad, which are some Android devices with less than amazing GPUs. The Ouya version of uQuake renders and empty level faster than the proper port of OpenArena, even, which I'm pretty sure uses the vis-and-related data to do traditional bsp stuff, as it's a source port.

I am hitting some issues with parsing Quake1 .bsp, though. Perhaps my understanding of variable type and size is not correct, but the file specs I linked above say that a face is thus:

u_short plane_id;
u_short side;
long ledge_id;
u_short ledge_num;
etc...
u_shar light[2];
long lightmap;

Is an unsigned short int not two bytes? is a long not eight bytes, and a char one? I try to read the data out using that assumption and I get garbage. Looking at the offset where faces start It looks like either the specs are not right, or a short is one byte. I did notice the the BSP version in the file is 29 while the spec here is for version 28. 
.h 
comparing with Quakespasm's structs in bspfile.h it looks like they are different. The doc at gamers.org shows a different number of fields than the struct in Quakespasm, with different types as well.