Append /\
#745 posted by necros on 2012/04/04 20:45:43
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
#746 posted by sock on 2012/04/04 21:32:26
@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
#747 posted by Kinn on 2012/04/04 21:33:41
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
#748 posted by Preach on 2012/04/04 22:17:44
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
#749 posted by sock on 2012/04/04 23:12:09
@Preach, that is awesome what you have done, but I can't get the link to work?
Arrgh
#750 posted by Preach on 2012/04/04 23:55:24
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
#751 posted by sock on 2012/04/05 00:09:00
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...
#752 posted by necros on 2012/04/06 05:08:59
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. :(
#753 posted by necros on 2012/04/06 05:10:48
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
#754 posted by Preach on 2012/04/06 10:47:13
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!
#755 posted by necros on 2012/04/06 18:30:14
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
#756 posted by Mike Woodham on 2012/04/06 19:33:51
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:
#757 posted by metlslime on 2012/04/06 19:48:19
instead of "self" in that sound call, use the name of another entity.
#758 posted by metlslime on 2012/04/06 19:48:42
(i.e. the entity that you want to silence)
#759 posted by necros on 2012/04/06 20:10:50
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
#760 posted by Mike Woodham on 2012/04/06 21:13:10
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)
#761 posted by necros on 2012/04/07 05:07:34
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...
#762 posted by necros on 2012/04/07 05:08:46
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...
#763 posted by necros on 2012/04/07 05:49:28
yeah, that didn't work that well. :P
Holy Lmaps Batman!
#764 posted by Kinn on 2012/04/07 14:11:21
Out of interest - what are the performance implications of using styled lights on that sort of scale?
Basically None
#765 posted by Preach on 2012/04/07 14:42:30
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
#766 posted by Kinn on 2012/04/07 14:57:37
I know what I'm gonna be doing now!
Cheers.
#767 posted by necros on 2012/04/07 18:46:36
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.
#768 posted by necros on 2012/04/07 18:46:42
awwww
#769 posted by metlslime on 2012/04/07 20:59:21
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.
|