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
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. 
First | Previous | Next | Last
You must be logged in to post in this thread.
Website copyright © 2002-2024 John Fitzgibbons. All posts are copyright their respective authors.