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 | Previous | Next | Last
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. 
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:

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'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;

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

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) ) {



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 {




//Find next path_corner from
void () traintech_next = {

local entity targ;

targ = find (world,targetname,; =;
if ( targ.speed ) {

self.speed = targ.speed;

if ( ! ) {

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 and setorigin to it
void () traintech_find = {

local entity targ;

targ = find (world,targetname,; =;
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 ( ! ) {

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

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:

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 

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. 
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! 
.iqm is a good format as well and also supported by dark places as well. 
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? 
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 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? 
First | Previous | Next | Last
Post A Reply:
Website copyright © 2002-2022 John Fitzgibbons. All posts are copyright their respective authors.