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
You don't need to modify the sprite, you just need to remove the animations you coded in the QC code.

If you don't use makestatic() in your torches, they will consume more network bandwidth and can generate packet overflows. And if you use makestatic(), your QC animation code will not work. Framegroups solves this problem, by making their animations client-side.

Also, from Fimg's help:
The sprite format used by Quake is the first game sprite format supported by Fimg. However, some of the design ideals of Fimg and a few aspects of the Quake Sprite Format are in conflict. As a result there may be a few things you need to know about Quake sprites before you use Fimg to edit them.

Quake sprites are composed of a number of frames. Each frame either consists of a single, unpaletted image or can be in a 'framegroup' where it is then composed of 1 or more unpaletted images. If the sprite contains no framegroups, Fimg will load the sprite as a simple animation sequence under a Fimg group titled "[no group]".

Fimg was designed to support a more general method of grouping frames where each group is an named animation sequence composed of a number of frames. As a result, if a Quake sprite has any framegroups, it will be loaded differently than previously described, where each 'frame' of the image is treated as a seperate animation sequence group. Each frame will in turn be named "Group X". where X represents the original frame number of the animation.

If Fimg loaded the sprite as a simple animation sequence, the only group will be named "[no group]". The Quake sprite saving routines look for the name "[no group]", and if found and it is the only group present, the animation will not be grouped. Therefore, if you'd like to group the frames for the animation, simply choose Groups->Rename from the menu.

When in a framegroup, each frame has a "Duration" key that indicates the delay for the frame. See the Properties Editor for more details. In addition, all frames have Origin values. See the origin tool for more details about this.

In addition, there are global properties for the file. For clarification, they are:
· Beamlength = Appears to be unused within the engine and is related to Doom style upright sprites.
· Radius = Is normally auto-calculated. If the size of the sprite changes, it is recommended you delete this property so Fimg will auto-regenerate it.
· Synchronous = When auto animating in a grouped frame, should the engine synchronize all instances of this sprite? If, for example the sprite is a fire, having all fire sprites start on the same frame would look ugly and obvious.
· Orientation = How the sprite will orient in game. The only two modes supported by GLQuake are "Oriented" which means the sprite will obey it's orientation and will appear as a flat plane, and VP Parallel, which means the sprite will appear as always facing the viewport.

These can be found by clicking the File Properties button or by clicking File->File Properties.
That clears up a lot. I'll see through it.

I exported all frames from the sprite back into FimG and it was declared as (nogroups).
All flames turn into one frame, but no warnings,
Hello, I would like to make flight physics for player in quake. I mean gliding in the air while player is falling, so it shouldn’t be just slowing down while falling, it should be something like paraplane or paraglider physics.
What I want to realise:
How it can be done in games:

I use sv_player.qc for working with player physics. Also, I am using dpextensions.qc as I am trying to make that on darkplaces engine.

I found some information and documentation about QuakeC on insideqc but still nothing helped me.

Does anybody knows how to realize gliding physics on quake? 
Maybe one chance for something similar is to find Zerstorer QuakeC devkit and see what the "wings" powerup does.

I tried it once but can't remember what it was like to use it. Is it in any of the Zersteror single player maps? I can't recall, but I'm not too much of a "find every secret" type. 
There are Parachutes and Skateboards in the Malice code.
Maybe a good chance to start.

Wrong Link 
i think basically, every frame the player is airborne you want to reduce negative z velocity to a target falling speed, and accelerate forwards up to a max forwards speed.

if you look at the ladder code in rubicon 2 you can see that i'm modifying player velocity whenever player is on a ladder. You can remove the ladder check and add check for onground, and then do your velocity modifications the same way. 
Sure, I heard of Parachute in Malice, but that is not really what I need. I also should work with horizontal velocity and vertical velocity to make dependence between them like in real glider. I don’t need just to “slow down falling” 
I Thought Wings 
...thought wings were in Nehahra. Every time you tapped jump you lurched up a bit and you slowly drifted back down. Kind of like an infinite double jump. 
You could also set player .gravity to something like 0.4 or 0.5. 
What you want is a MOVETYPE_FLY that's slightly affected by gravity, and with lower friction.

I don't know if sv_friction affects MOVETYPE_FLY, or if the aerial friction is hardcoded. 
I thought about things that should be realized so it could work:
1. I should make flight vector. This vector should follow view angle vector but with a small delay. That makes our flight more realistic. Also it allows to set maneuvering.
2. When player falls down he accelerate, when he looks forward he slows down.

I have some suggestions how it can be done:
1. vector fly_direction, float m;
if(fly_direction != self.v_angle)
if(fly_direction_x != self.v_angle_x)
fly_direction_x += (self.v_angle_x - fly_direction_x)/m;
if(fly_direction_y != self.v_angle_y)
fly_direction_y += (self.v_angle_y - fly_direction_x)/m;

float coef;
//fly acceleration coefficient
coef = ((self.v_angle_x-45)/90);
Please help me to translate that into quakeC properly 
Possible Version 
Here's what I'd do, roughly:

//convert current velocity into speed and direction
speed = vlen(self.velocity);
olddir = normalise(self.velocity);

//convert angles into a normalised heading

//add a small amount of the heading to the current direction of travel
newdir = normalise( v_forward*frametime + olddir*(1-frametime));

//preserve the speed we had, but change the direction
self.velocity = newdir * speed;

//reduce the strength of gravity based on how level we are currently flying
self.gravity = 0.1 + 0.9*abs(v_forward*'0 0 1');

Some of the values might need tuning here and there, but that should get you started. Player movetype should be left as default, because we want gravity to apply (subject to the last line reducing how fast we fall. Haven't tested this, so it may be rubbish... 

should of course be

use dotproducts:
upspeed = self.velocity * v_up;
fwdspeed = self.velocity * v_forward;
rightspeed = self.velocity * v_right;
(vec*vec is a dotproduct).

You can then get back to the original velocity vector with:
self.velocity = v_up*upspeed + v_forward*fwdspeed + v_right*rightspeed;

Of course, if you change some fraction of the force exerted on the underside of your glider before reforming the velocity then you'll reduce the effects of gravity while horizontal, and return to normal when facing vertically down.
Of course, that energy should normally go somewhere - if you add to fwdspeed anything you subtract from upspeed then you should get something a bit glidery.
you'll also need to include some friction somewhere, in order to get some terminal velocity. and yeah, the conversion should probably also not be 100% efficient either, nor should it convert ALL the energy.

but yeah, dotproducts are great if you want to compare two directions. trying to do stuff like this without using them is just going to leave it feeling really hacky.
Unfortunately there's no real way to control the camera from ssqc, but csqc can override the camera angles without changing the client's 'desired' angles. you should be able to implement roll that way, somehow. 
Notes After Testing The Suggested Code 
Had a go with the code from my post on Saturday, it worked pretty well for a first attempt. I did find that it wasn't responsive enough until I doubled frametime everywhere it appeared. One big tip for testing it - use e1m8. Firstly because its one of the few ID maps with enough vertical and horizontal space to glide in properly, secondly because it's low gravity so it's much more fun!

It's got most of the effects you'd want to see in glider physics - you can dive down to gain speed then level off and carry the momentum forward, and if you look up you'll gain height but bleed forward speed. You can look straight up, and you'll quickly stall then crash to the ground. Also if you collide with walls etc your speed is lost which tends to end the flight pretty quick.

One advanced trick: you can accelerate in Quake while in the air. If you're gliding, strafe left while turning in an anticlockwise circle and you'll gain speed (same principle as bunnyhopping works on). You can use this to offset the loss of speed while climbing, and gain height by moving in a big spiral. 
Preach’s Code Test 
Hi Preach, yesterday I arrived to my PC and I got an error after compiling your code. May be I have done something wrong. Could you please post a full file with your code so I could test it out? I think that would be useful for all the community. 
Maybe if you post the error you're getting we can help you out ... 
Skeleton Code 
I tried to post it as skeleton code so that you'd get some practice hooking it up. One thing I did unintentionally was to misspell (well, anglicize) a built-in function name, so make sure you change the spelling to normalize. If that wasn't the error that's stopped you, post it like c0burn says and we can suggest fixes. 
Still no result. I try to use this code if no flag on_ground is false but nothing works. 
New Issue 
Hi Reyond. It sounds like it's a bit further on if the compiler error has gone away. What function are you running the code in? I ran it in PlayerPreThink so that it would happen every frame. You're right to disable the code when the player is on the ground, but from your description I don't know whether the code you have is right.

I used: if(self.flags & FL_ONGROUND) to see if the player was on the ground. I also turned the code off while the player was in water using the check if(self.waterlevel) (although that's a detail to add once the basics work.

If that doesn't help, post the whole text of the code you're using and maybe we can spot what else it could be... 
Tut From InsideQc 
Found an old tutorial from Legion with an Xman version of a FlySimulator. Maybe helpfull as a guide. 
Allright, I found an error. Here is how I use the code:
else // airborn
vector fly_direction; vector new_dir; float fly_speed;
float fly_velocity; '
float koef;
if (wishspeed < 30)
f = wishspeed - (self.velocity * wishdir);
f = 30 - (self.velocity * wishdir);
if (f > 0)
self.velocity - self.velocity + wishdir * (min(f, sv_accelerate) * wishspeed * frametime);
fly_speed = vlen(self.velocity);
fly_direction = normalize(self.velocity);
new_dir = normalize(v_forward*frametime +fly_direction*(1-frametime)); self.velocity = new_dir * speed;
Yes, actually it looks a little bit like gliding but I can’t understand how the code works. Why do I use frametime if this function works every frame? How this code affects the gravity (in-game gravity is 100 now). And how can I improve this code to make it work better?

Also, I would like to make it works without changing the standart “800” value of the sv_gravity variable. Is that possible?

Also, thanks to Preach and to everyone who helps me in making player gliding in quake. 
Try It Out 
Have a go with the second-to-last line changed to

new_dir = v_forward;

This leaves out the bits with frametime. What you should notice is that while gliding, you instantly start moving in exactly the direction you are facing. It's very easy to control, but it's not very realistic for a glider - you can 180 turn instantly at any time.

The idea behind the frametime code is to add the v_forward part more slowly, so that your direction of travel doesn't change instantly. Instead we add the v_forward in a bit at a time. Because the function runs every frame, we need the pieces we add to be smaller when the framerate is higher, otherwise people with higher framerates could execute tighter turns, which would be unfair.

I found that in practice the rate of change was too slow, and that it was better to change that line to:

new_dir = normalize(v_forward*2*frametime +fly_direction*(1-2*frametime));

By making the piece we add each frame twice as large, we get a better trade-off between smooth turning and reaction time.

In terms of making the glider float, I noticed that you don't have the last line from the code I posted:

self.gravity = 0.1 + 0.9*abs(v_forward*'0 0 1');

I expect you were getting a compiler error from this line that you didn't know how to fix. The secret is to add the following to the bottom of defs.qc:

.float gravity;

This warns the compiler that you'd like to be able to store a float called "gravity" on all the entities. The engine uses this to change the gravity just for that entity. So if you are flying in normal 800 strength gravity, but the player has self.gravity = 0.1, for that player gravity will be 80 instead (because 800 * 0.1 = 80). All other entities are unaffected, try firing a grenade while gliding and notice that it falls normally.

Give it a go, see what comes of it! Any more questions, just ask... 
Error: unknown value “abs”. 
To Reyond 
its fabs i think 
Teach me to copy-paste from the sketchy untested post rather than the working code, use fabs and it'll work. 
Finally, we have a nice result!

Watch this:

Thanks to Preach for the code and to st1x51, Baker, madfox, metlslime, Qmaster, Spike, mankrip, c0burn and to all who helped me with this.

Here you can get progs.dat file to check it out:

And here is the source code (use dpextensions.qc or fteextensions.qc to compile it and add .float gravity in to the defs.qc): 
Tried in on E1M7 in FTE and it works nice.

Improving The Code 
Is there any way to slow down flight? I have to make huge maps to make flight works properly.

And is there any way to change the value of horizontal speed loss?

Is there any way to make this work in standard quake without ising fork engines extensions? 
Improving The Code 
Is there any way to slow down flight? I have to make huge maps to make flight works properly.

And is there any way to change the value of horizontal speed loss?

Is there any way to make this work in standard quake without ising fork engines extensions? 
Generic Engines 
In theory, if you set the player's movetype to movetype_none in PlayerPostThink, and back to movetype_walk in PlayerPreThink, then you can insert a call to your (renamed) SV_PlayerPhysics at the start of PlayerPreThink and get a similar result.

In practice, doing so would leave you with no way to determine the user's intents (read: the .movement extension). You can work around this by using movetype_noclip instead of the movetype_none above, and to then try to guess the intents according to how the player's velocity accelerated between postthink->prethink (hint: dotproducts, see my earlier post). You'll also need to unwind those noclip-based velocity changes which will require some kind of shadow field, and clearing the velocity field in playerpostthink will make your .movement guessing logic more reliable.
Either way, it'll screw over prediction and get confused by knockbacks.

.gravity exists in all quake engines since hipnotic. You should be able to knock up a min/max function easily enough. I don't think there's anything else in there that's a problem. 
Engine Neutral 
My code runs fine in standard quake engines (once you define the .gravity field to enable that feature). You just run it in playerprethink, it uses standard player physics but then just rewrites the velocity each frame.

To slow it down, I guess you could do a number of things. One thing would be to reduce gravity further, even while facing down, so that you can't build up speed so well. Another would be to add a cap to fly_velocity after you calculate it:

if(fly_velocity > MAX_FLY_VELOCITY)
fly_velocity = MAX_FLY_VELOCITY;

Without this, the player can achieve speeds up to the global maximum speed an entity can reach, which defaults to 2000! 
On Quake Wiki I read the Trivial of the HellKnight.
The intention was to let Rangers spawn when the Hellknight is hit.

The same applies to the Axe_Ogre, which I managed to give some extra postures.
In this case, the Ogre should laugh when someone dies.
A more peculiar fact was pissing on the player's body.

If I were to start coding ... where should I start?
Something like pissing on the player would mean something to the player.qc and ai.qc.
Laughing when someone dies is a more general topic. 
Take A Leak 
PlayerDeathThink in client.qc, add a while loop that use

spot = find (world,classname,"monster_ogreaxe");
if ( spot ) {

spot.think = ai_leak1;
spot.leakentity = self;


Then set goalentity to the leakentity in ai_leak1 and self.enemy to self.leakentity. Do some ai_run()s inside your ai_leak1, 2, 3, etc. check for distance using vlen and start ai_leaking1 when close to player. In ai_leaking1, 2, 3 do your leak anim frames and play a sound effect maybe. 
Of Course 
You may need to add a .float to act as a bool so that you only check for axeogres in PlayerDeathThink once, something like

if(!foundleakers) {
foundkeakers = 1;
//while loop in here

And then in respawn() maybe add a foundleakers = 0; call. You might need to get fancy with coop though. 
...assumed the idea was that if the ogre killed the player then just that particular ogre would piss on the player, however...

Qmaster is making me think that if the player dies then all the ogres in the map would start making their way over to the player's corpse for a great big ogre gang-corpse-piss-party, and if I'm being totally honest with myself, that idea is too compelling to just pass up. 
Laughing Is A More General Topic. 
Let's assume the idea that if the ogre killed the player then all ogres would laugh.
The same a strange way when they're fighting between themselves and all start laughing when the player dies..

So these extra poses would concern the player only.

If I take PlayerDeathThink, and start adding code exact above respawn();
and under the self.button2 = 0;
the new code looks like:
self.button2 = 0;


spot = find (world,classname,"monster_ogreaxe");
if ( spot ) {

spot.think = ai_leak1;
spot.leakentity = self;



client.qc:805: error: unknown value "spot".
I know I'm a geek what coding concerns,
no idea how to make a spot statement.

laughing Axe_Ogre
lapaz Axe_Ogre 
Christ On A Bike. 
Playing The Fiddle Onehanded 
Make some minor changes to the micturating ogre model to give it a more ejaculatory flavour, and boom - cool new projectile attack. 
local .entity spot; 
That Was A Bit Disturbing Actually 
The way the ogre's balls rhythmically scrunch up on each cycle suggests we're getting something a little bit extra, not just urine. 
Make It Happen Madfox 
I Regret Having Been A Part Of This. 
Don't forget to do a particle(self.leakentity.origin,'0 0 0',60,18); for added effect 
I Screwed Myself Almost Geek On Those Fucking Flies! 
I could have suspect these intimate subroutines would lead to hillaric reactions, but..,

my bike had a leak last christ, and I wonder who'll pay the fiddler off.
I suggest kinn giving it a good smile sound.

Thanks Qmaster, I didn't warn you before I asked your help with my q1test. But you're welcome. I tried your email, but it didn't work.
Right, so I'll start with
local .entity spot;
The extra effects, it's like knowing the name of the statement, but not where to paist it in. 
I Changed 
in PlayerDeathThink after the buttons:

self.button2 = 0;

//===new code===

local float entity spot;

local .entity spot;

spot = find (world,classname,"monster_ogreaxe");
if ( spot ) {find (world,classname,"monster_ogreaxe");

spot.think = ai_leak1;
spot.leakentity = self;


//===end code===

error: no spot value.

then I added to defs qc line 139 :

.float skin;
.float effects;

//===new code==
.float spot;
//===end code==

Client.qc:812: error: type mismatch = (FIELDTYPE and entity) 
local entity spot;
no extra dot
(you want an entity, and not a field reference[of sub-type entity]) 
my bike had a leak last christ, and I wonder who'll pay the fiddler off.
I suggest kinn giving it a good smile sound.

Stumbling Is A Kind Of Laugh 
Appoligize my passionated reaktion, as I'm stupid enough to write down my nonsense before my smart conclusion starts reasoning.:P

Thanks Spike. Now I'm back at start with:

//=========new code===========
local float entity spot;
local entity spot;

spot = find (world,classname,"monster_xogre");
if ( spot ) {find (world,classname,"monster_xogre");

spot.think = ai_leak1;
spot.leakentity = self;

//====================end code==

client.qc:808: error: local not a type
client.qc:808: error: spot not a type
client.qc:808: error: if not a type
client.qc:808: error: self not a type 
local entity spot;
just that.
not 'local float entity spot;' - that's meaningless conflicting keywords. 
yes, but as soon as I add a line in client.qc before ClientObituary I receive the error "local" and "spot not a type".
How do I make them to a right statement? 
I changed some parms

void() ai_leak =
local entity spot;
spot = find (world,classname,"monster_xogre");
if ( spot ) {find (world,classname,"monster_xogre");
spot.think = xogre_leak1;
// spot.leakentity = self;

if I exclude spot.leakentity it compiles well,
warning that "Local "spot" not defined with a name of a global"

Wow, I've got an ai_leak!
What should be the next step? 
if ( spot ) {find (world,classname,"monster_xogre");
local entity pissee;
spot.think = xogre_leak1;
if ( pissee ) {find (world,classname,"monster_donaldjtrump")
spot.enemy = pissee; 
QuakeC Locals And Globals 
local makes that variable only work within the function--inside {} and ONLY after it has been declared (pretty sure about this second part).

Globals are any variable defined outside, e.g. in defs.qc (at the bottom of defs.qc anyways)

You need to define a .entity leakentity; somewhere outside a function and before you use it in client.qc.


.entity leakentity; // entity to remember for later so the monster knows where to go take a leak

void ClientObituary() {
local entity spot; // entity to hold our axe ogre

//your find down here

I'll let you figure out how to make the monster hunt down the player location and then begin the actual taking a leak. 
I'm back in PlayerDeathThink.

spot.think = xogre_leak1;

error: xogre_leak1 unknown value.

I can make a "void() xogre_leak;" at the top of the client.qc list,
but it keeps the error. 
There is something I need to explain first. As I mentioned before I am working in the Q1Test environnement. Also I added the Dragon code, rubicon.qc as some other feathers. I also wanted to add a catapult in stead of an axe.

One thing I would like to keep original to the Q1test mod.
Sounds, conback, weapons, and monsters. Reason I add the Axe ogre and Serpent, Vormitus, as the Shalrath's queer apearance is, because that were the trivial things that were not implemented. The dragon form Megalol had a solution, but the mod from Patrick Martin I included has a more sensitive way.

So I started with the "poor" q1test src, and slowly tried to find a way through the queer qc that was forehand. No Axe, nowammu_cells plz, and other butheads, like no change_level, just the stripped down qc to deathmatch.

Now I'm at the point that I'm testing the monsters, but it gets a little tricky , when I would assume the errors I get involved in are not the ones that apear in normal vqcc106.

Enough, I've got ai_leak that compiles.

After ClientObituary:

local float rnum;
local string deathstring,deathstring2;

local entity spot; // entity to hold our axe ogre

if ( spot ) {find (world,classname,"monster_xogre");
local entity leak;
spot.think = xogre_leak1;

rnum = random();

if (targ.classname == "player")

I had to add a new statement at the top for xogre_leak1 as it was not a value.

How do I make it aware for the player's death? 
Queer Or Queen 
Um, Compile With Fteqccgui? 
I use fteccgui as fteqccgui. I can compile the client.qc but I have no idea how to make it correspond the player's death. I think it needs some more code.

local entity spot; // entity to hold our axe ogre
if ( spot ) {find (world,classname,"player");
local entity leak;
spot.think = xogre_leak1;

I tried your email, but it faints. 
gimmy a hint! 
Set spot.goalentity to player perhaps. 
that does nothing. spot isn't initialised yet. if this was C you'd crash. As this is QC, it'll just always evaluate to false and do absolutely nothing.

find (world,classname,"player");
this does nothing. you're calling the function and finding a player, but as you're throwing away the result you're not getting anything out of it.
Of course, seeing as the player has just died, the return value is probably going to be equal to 'targ' anyway. You probably meant to look for a different classname, like your ogre's classname.

local entity leak;
Variable not referenced: leak
the weirdly named 'spot' variable is used, but leak totally unused...

spot.think = xogre_leak1;
You didn't check that 'spot' is actually alive.
Your dead ogre will suddenly resurrect purely to take a leak!
Lets hope its not a gibbed head. :D
Note that there's no loop, so only one entity could possibly start pissing (except that spot is always world so you're probably just going to crash the server with your assignment to world, if the if statement wasn't there).

Imho, you should shove the check somewhere in ai_run.
When a monster's enemy has died, that function decides whether the monster should resume attacking its oldenemy or whether it should resume walking/standing instead.
So when the enemy dies, delay the standing and switch to the pissy animation instead (make sure its an 'xogre' that's doing the ai_running first, and make sure it doesn't forget its enemy just yet).
That way you don't risk waking monsters from the other side of the map (which might get quite crowded, and really awkward in coop).
and then you can dupe the walking animations to have the monster walk to the player's corpse and then start to pee only when its close.
then once its done pissing, you can have it start to play some point+laugh loop, or just have a constant stream of pee until something else wakes it up by shooting it (or make the looping part call ai_stand to have it wake up if another player gets close). 
Id1 Source Code Circa 2018 
I've taken the plunge into cut and pasting QC. What's the "state of the art" clean id1 source code I should be using in 2018? 
The vanilla source code (version 1.06) can be found at least here:

C0burn had also linked Ultimate Regular Quake Patch's source code to me. It has a lot of fixes/workarounds for problems that may arise with the vanilla code. I borrowed some code from it for one of my maps.

Good luck to your plunge! :) 
Looks like a lot of MP focus in that second link. Thank you! 
Also FWIW: 
For my own purposes I put some QuakeC onto github a while back. There's various places to get these same things, but:

For the original 1.06 QuakeC you can browse it here:

or download a zip of it from here:

For Preach's cleaned-up 1.06 you can browse here:

or download here:

And you can see the differences between them here: 
Eh, one caveat that just occurred to me about those zipfile downloads. If you get the code that way then all the files will use Unix-style line endings. Might cause you issues depending on what text editor you're using. 
The URQP package is neat. I didn't know that that was where the Quake Info Pool fixes ended up. 
Bug Zapping 
I've updated the QuakeWiki with a list of bugs I know about in the 1.06 code.

It's most of the URQP stuff, plus other bits and bobs.

Please amend or ask me to amend if anything is missing! 
What About Solid Fiends? 
Quote from your list:

Rotfish does not become non-solid until the final frame of it's death animation * this is not in line with other monsters, so it is considered a bug

Correct me if I'm wrong, but don't fiends exhibit similar behaviour, too? 
They become non-solid on frame 6/9!

Glancing at some others quickly, hellknight is frame 3, as is the grunt.

I think it should be harmonised. 
Some More Thoughts 
Should we class unused content, such as the death knight grunt sound and unused animations and unused shub sounds, as a "bug"? There's other bits and pieces as well, including unused animations in the knight, soldier and ogre. Can we introduce these in a non gameplay changing manner? Should they be an optional spawnflag/worldspawn flag? 
In the ai.qc i took the ai_run part.

void(float dist) ai_run =
local vector delta;
local float axis;
local float direct, ang_rint, ang_floor, ang_ceil;
local entity spot; //xogre_leak code
movedist = dist;
// see if the enemy is dead
if ( <= 0)
self.enemy = world;
spot = find (world,classname,"monster_xogre");

if ( spot ) {find (world,classname,"monster_xogre");
spot.think = xogre_leak1;
spot.leakentity = self;

and the bastard lays it's blame on me!

Thanks Spike, that was right on target!
Now see if I can switch leak with laughing. 
A Few Other Notes 
Thunderbolt bugs relating to the "three beams"

I assume this bug isn't related to lightning attacks (both thunderbolt and shambler) being able to damage entities through walls? Also, hitchecks with the thunderbolt are kinda weird. (You probably know what I mean with that, but if you don't, just tell me, and I can explain in a reply.)

multiple megahealth rots down too quickly (double rot)

I had learned about this actually, when I tried to make a custom Doom-like health bonus item. My health would rot down super fast after having picked up like ten of those items! @~@ I actually thought that it was a feature, to make supercharged players less OP, or something. :D

targets not fired if the player doesn't take the item (e.g. already has max armour, touching armour should trigger a monster/something, but doesn't)

This is even more so arguable, whether it's a bug or not. I actually prefer it the current way. If I wanted to make 100 % sure about the targets being triggered when touching the item, I'd add a trigger_once brush or something.

(Also there are minor typos here and there in the list.) 
@Johnny Law 
Thanks. I wasn;t aware Preach had a version of his own. I'll most likely use Preach's 106 code when I dive back in. I am using FTEQCCGUI and Notepad++ 
Last year muk0r put together a "clean QC source"... but the readme doesn't say if there is any bugfixes :(

but maybe (i said maybe because i don't know if you want these features) you should start with custents?
It seems to be a mix of all the cool features of the two official mission-packs, like: rotating brushes, earthquakes, particle fields, breakable walls, etc 
Thanks for these links. I am looking at adding some of the custents features for sure. 
I think the "same name texture" crash mentioned on that page is only in GLQuake and derived engines. 
I agree about the item not triggering it's targets if it hasn't been picked up, that is definitely not a bug, it makes total sense for an item to not do anything if the player touches it but can't interact with it for whatever reason, like if their ammo is full or they have full armor or they already have that type of key in their inventory. Not to mention that a vast majority of maps are designed around this mechanic one way or another, like key traps triggering when the player, you know, picks up the key or encounters that get triggered when you pick up a particular weapon or powerup like quad damage

Now if we're talking about keeping the player from picking something up if they already have enough of it that's another story, it would definitely be nice sometimes if some things like ammo or health only gave themselves to you if you actually needed that much, it would definitely help prevent wastefulness by picking them up on accident when you don't really need that much yet 
I agree about the item not triggering it's targets if it hasn't been picked up, that is definitely not a bug, it makes total sense for an item to not do anything if the player touches it but can't interact with it for whatever reason, like if their ammo is full or they have full armor or they already have that type of key in their inventory. Not to mention that a vast majority of maps are designed around this mechanic one way or another, like key traps triggering when the player, you know, picks up the key or encounters that get triggered when you pick up a particular weapon or powerup like quad damage

Now if we're talking about keeping the player from picking something up if they already have enough of it that's another story, it would definitely be nice sometimes if some things like ammo or health only gave themselves to you if you actually needed that much, it would definitely help prevent wastefulness by picking them up on accident when you don't really need that much yet 
Cleaned Up Code 
I should mention that the changes in the cleaned up code are only to eliminate compiler warnings, there aren't any bug fixes or behaviour changes. Just wanted to set the right expectations for it. 
Thanks for the clarification. I am still very much in the copy and paste fingers crossed stage of qc. I believe c0burn wants to release a bug smashed version of the code eventually. That's a great project IMO. 
Result is that a player in fight with an Axe_ogre will get pissed. If player is shot from distance, the ogre won't walk to the player's body. 
the point of doing it in ai_run is that:
a) self is the ogre that should do the widdle. there is absolutely no need to call find (because you can just use self). there is no need to loop etc (each monster will call the function at some point anyway).
however, you really ought to only do that logic if self.classname is actually what you expect. you don't really want scrags trying to widdle.
b) the player that its trying to urinate on is already stored inside self.enemy. This means that you don't need a seperate leakentity field - just use self.enemy! (do note that you'll want to avoid the self.enemy=world line if the ogre is meant to start widdling.) 
Thanks for your answer. Sorry I'm such a noob at coding.
If I use the self argument, how do I make it fit in?

As it is an experimental src, so maybe it is better to show an example
of what I am trying to do.
here's a demo of Qtest

the main problem, the "new" monsters seem too much overpowered (especially vomitus)

noticed a couple of issues, check the demo 
Queer Queen 
Just finished a nice trick to change the serpent into a quaddam.
But don't touch it, cause it lives.., a bit husling with the skin file.

Yes, the src has a MISSILE weaponcode for each monster,
wizard is also much too strong. Number code for weapons won't work. Still beta.

Thanks for the demo, I'll look at it! 
You made your way quiet advanced on hard skill. Spy.
The missing sounds are qc depended.
I turned a bit strayed with the qtest.qc. adding the monsters,
especially the dragons, caused a lot of changes.

I assume the forced demo end had something to do with crashing,
it is still beta version, already glad it runs.

Thanks for taking your time. 
Partial Cross Post 
I am just getting started "cutting and pasting" QuakeC. I followed Preach's revised tutorial on monster spawning here:

I'd like to add a small random delay automatically to each teleporting monster as you can do in Quoth. I am using custents multiple triggers to trigger these delays spawns. Similar to Quoth, it would be nice to have a little variation on the timing if the monsters all share a targetname.

I've tried a few things already, being exceedingly cautious not to mess up this code I can barely comprehend. I'm wondering if anyone would like to give me a hint of how to approach this little addition. 
Add a new function:
void monster_teleport_delay () {
self.think = monster_teleport_go;
self.nextthink =time + self.wait; // or self.delay if you prefer that

Then in your monster_teleport() function change self.use to be monster_teleport_delay; instead of monster_teleport_go.

DISCLAIMER: Untested. 
thank you for the help... I will try this after work this evening! 
Newb question: would this mean I need to add a wait or delay key value to the entities? I don't mind setting it manually but wanted to know if this is how this method works. 
If you don't want to set a wait value manually, instead of using self.wait in that code you can generate a random number between 0 and 1 using random() instead.

Can you see how to adapt the code to use random to create a delay of between 0 and 1 seconds?

How about a delay between 0 and 2 seconds?

What about between 0.5 and 1 seconds? 
Obviously I posted that before reading the other thread. 
No worries thanks for the great tutorials. I am enjoying messing around with QC finally. Next, I am going to try and figure out a silent spawn without the tfog and audio next. I think I can do it. 
Decision Made! 
After trying to implement random timings I felt it better to go with self.delay. More work but more control for the mapper. Thanks everyone! 
Te_lightning, Etc 
void(vector v1, vector v2) te_lightning =
WriteEntity (MSG_BROADCAST, world);
WriteCoord (MSG_BROADCAST, v1_x);
WriteCoord (MSG_BROADCAST, v1_y);
WriteCoord (MSG_BROADCAST, v1_z);
WriteCoord (MSG_BROADCAST, v2_x);
WriteCoord (MSG_BROADCAST, v2_y);
WriteCoord (MSG_BROADCAST, v2_z);

Writing some TE_ helper functions has gotten me curious. WHY is there an entity parameter needed for the lightning, beam, etc? Is it safe to just write world? 
I figured it out. It uses the entity as the start point regardless of the co-ordinates passed. And this is why the lightning beam starts at the origin of the player, regardless of anything else. 
beams last 0.2 seconds. QC respawns them every 0.1 seconds.

the entity argument is just there to avoid the resulting double-beams issue (trying to depend upon precise timing would be too unreliable with network latency etc, hence why they last longer).
Using world would break when you have two players firing beams, although some engines do understand world to mean 'don't replace any beams'.
tbh 99% of the time that entity arg will be self.

ignoring the startpoint and using the player's position is just to smooth things out so that the player doesn't leave the beam behind when moving sideways etc.

note that there's already an engine extension to provide those as builtins (with that name), so beware of potential conflicts if a modder uses *extensions.qc. 
W_FireLightning Start Origin Incorrect On Players? 
original code has

LightningDamage (self.origin, trace_endpos + v_forward*4, self, 30);

(even URQP has it that way)

But i had long changed it to

LightningDamage (org, (trace_endpos + (v_forward * 4)), self, 30);

this is especially obvious when shooting from RL window on DM3 and aiming at someone on the lower bridge.
this is because:

org = self.origin + '0 0 16';
traceline (org, org + v_forward*600, TRUE, self); 
The original is "waist lightning". Darkplaces has specific settings to let you pick which style you prefer, waist or gunpoint. 
That only fixes the position of the bolt VISUALLY, which is what Spike was explaining. The above fixes the tracelines/damage as well. 
ya the original deals damage from the gun but visially it came from the hip
i keep confusing myself that sel.origin is the bottom of the model
where the feet touch the floor 
Trigger_push Project 
Still taking baby steps into QC with very little coding background. Wanted to check with experienced coders. This bit of code makes a trigger_push silent with a spawnflag. It appears to be working fine in game and no errors in FTEQCC but I feel like the syntax is still wrong.

Next steps will be to learn how to toggle it and add custom sounds.


float PUSH_ONCE = 1;
float PUSH_SHHH = 2; //DMS push silently

void() trigger_push_touch =
if (other.classname == "grenade")
other.velocity = self.speed * self.movedir * 10;
else if ( > 0)
other.velocity = self.speed * self.movedir * 10;
if (other.classname == "player")
if (!(self.spawnflags & PUSH_SHHH)) //DMS
if (other.fly_sound < time)
other.fly_sound = time + 1.5;
sound (other, CHAN_AUTO, "ambience/windfly.wav", 1, ATTN_NORM);
if (self.spawnflags & PUSH_ONCE)

/*QUAKED trigger_push (.5 .5 .5) ? PUSH_ONCE
Pushes the player
void() trigger_push =
InitTrigger ();
precache_sound ("ambience/windfly.wav");
self.touch = trigger_push_touch;
if (!self.speed)
self.speed = 1000;

You could also check the spawnflags in the spawn function and only precache the sound if needed. 
Quakedroid would be about the only reason not to just precache everything. 
What does this mean?

if ( (rand()&3)==1 
if ( (rand()&3)==1
rand() returns a number between 0 and RAND_MAX.
&3 truncates all but the lowest 3 bits (so a random number between 0 and 3 inclusive).
==1 gives you a 1-in-4 chance of being true.
and there's no closing bracket, so the entire thing is a syntax error and won't even compile.

of course, rand's randomized bits are generally least reliable in the lower bits, so the above might be quite predictable, but it depends upon the rand implementation. 
Truncatorial bitwise AND. Mkay.

So 25%ish chance in movetogoal to "bump around" using the wall following code if the monster can't step in the direction of its .enemy

I guess that makes (rand()&1) evaluate to 50%ish chance. 
lowest 2 bits, sorry. and yeah, bitwise and.

movetogoal is just all kinds of screwed tbh. its very much an attempt to replicate doom's monsters, but in a way that's 5+ times as expensive due to all the floor checks etc. it can't slide along walls so can't deal with narrow passageways, etc. it works well enough, but its far from ideal. 
Its strung out multi-function calling madness yes. Trying to recreate it. 
Which Coordinates Do I Use For ReMStud? 
So I got the save file and the console output, but I can't seem to find the correct coordinates for putting the camera in one place and a place to view it. What set of coordinates do I use for the 3 sets I'm given from the console output? 
Not sure it is what you're aiming, but in a mapeditor with a viewscreen it is easy to turn the view camera and the info_camera aligned.
Just make sure the arrow of both viewpoints are the same. 

Here is a rotfish fix I knocked up for otp. It fixes the fish count, makes fish gibbable, makes them non-solid straight away when dead, and includes a fixed fish.mdl due to the bugged head size in the death frames.

It's all combined in a pak2.pak so it can be used as an id1 fix if you drop it in there.

Source is included, only fish.qc and monsters.qc have been modified however. 

This is a command line based tool which will read a QuakeC progs.src and all .qc source files listed within, and output a .DEF file compatible with a map editor such as TrenchBroom.

This assumes your QuakeC source files contain /*QUAKED*/ style definitions such as those found in the original id software QuakeC sources, as used by the original QuakeEd. For example, from items.qc in the original source:

/*QUAKED item_armor1 (0 .5 .8) (-16 -16 0) (16 16 32)

This makes the laborious task of hand creating a .DEF file a thing of the past, as long as you include the relevant entries in your QuakeC sources when adding or amending entities. While not as powerful as .FGD files, .DEF files have a place and can be a quick way to add map editor support for your new mod!

Source code is included as a simple .c file, which should build on any C99 compiler. 
Oh!! That's what those hideous comment blocks are. I figured it was just a way for someone to copy and paste it over into some wierd editor definition in case they lost it. It sounds cool but I still don't understand the use case.

What other formats are there other than .def and .fgd? 
The use case is that the original QuakeEd (that id developed and used on NextSTEP to make the original maps) parsed the .qc files and used those definitions to display what entities were available.

The modern use is that all the entries can be stuffed in a .def file and trenchboom (etc) can use them to populate the entity list.

I'm not aware of anything other than .def and .fgd, but maybe there are other formats in use in some of the more esoteric editors. 
Not Convinced 
This makes the laborious task of hand creating a .DEF file a thing of the past, as long as you include the relevant entries in your QuakeC sources when adding or amending entities. While not as powerful as .FGD files, .DEF files have a place and can be a quick way to add map editor support for your new mod!

This is a bit of a tautology - the reason those comment blocks were there was so that ID could write the .def file inline, and then extract it into a single file using a command line tool. The comments don't do anything for the QuakeC processing of the file. You're basically saying you can take all the effort out of writing the .def file, so long as you've already written the .def file. 
Thats true however I think the original QuakeEd read the QC files directly at launch and there never was a tool to pull the definitions out into a .DEF. I may be wrong though. 
That's True 
quakeEd already supported cleanly ignoring anything that wasn't contained in a /*QUAKED */ comment block, and when I discovered I could just point qe3 at lunsp2/src/*.qc instead of maintaining a separate .def file an angel got its wings

(the other clue to this is that the comment blocks start with /*QUAKED in the first place ...) 
Would Be Nice If 
There could be a utility that generates a list of all functions in the qc like so:
Function(float arg1, vector arg2),called 0 times, precache Yes
W_Attack(),called 1 times,
weapon_blaster(), called 0 times, precache Yes
SUB_Remove Edicts Piling Up 
I have a problem with edicts piling up that have no information other than Think = SUB_Remove and Time = -1. I'm not sure where to look in the qc to find what's causing it. Do TE_STREAM_* ents look like this in the edicts dump? 
Code Request 
Hi Shanjaq. TE_STREAM_ things aren't using up your entity slots, "temporary entity" is just a bad name for them. So the problem must be elsewhere.

Think = SUB_Remove and Time = -1

Can you post the full lines of code that these quoted parts come from? It's hard to tell if they're right or wrong from what you posted. 
ent.nextthink <= 0 means the entity will never think, and thus never get removed. use 0.1 instead, or something.

note that the remove builtin will also set nextthink=-1, clear classname+model, but not clear the remove builtin.
those removed ents will be reused later (no sooner than 0.5 secs). so if you're spawning+removing within the same frame then you're going to have at least 0.5 seconds worth of them building up.
qc can still read+write removed ents (unfortunately), but nextent+find+findradius won't find them, and saved games shouldn't list them so I've no idea if this is what's causing them or what - how are you seeing this list of useless ents? 
Edicts Anonymous 
Thanks all for your insights! I'm wondering if there's a leak somewhere in the edict de-allocation, as I sometimes see models/sprites frozen in mid-animation which have no clipping and findradius can't see them. Here is a snippet from edicts.txt after a crash. note the last two, which I'm seeing in the hundreds:

Fte Quake C Dev 
While changing from ftcq to fte dev compiler I found some small errors. And before get passed with an unknown punctuation, I see for all monsters:

warning F307 type mismatch void entity_pain to void (entity_attacker, float dammage) self.th_pain

What is the statement to catch this error? 
You need to pass inflictor as well:

void (entity attacker, entity inflictor, float damage) th_pain; 
Usually just self. This is used to differentiate between the projectile inflictor (e.g. the rocket, self) and the attacker (self.owner). 
Just add "(entity attacker, entity inflicter, float damage)" to each monster's pain functuon. Example:
void () ogre_pain = {

void (entity attacker, entity inflicter, float damage) ogre_pain = {

WAIT WAIT...just attacker and damage. AD adds inflictor. 
Yes, Thanks! 
Most errors are fading, when I changed it in an addon monster, but it still keeps errors.
They're not major but when I try to change athe Vore's pain it loops back to the self.th_pain string. And for Shub's error I can't find a pain function, but SUB_Null.

The error starts in client.qc (line 552) PutClientIntoServerclient.qc at the statement for
self.th_pain = player_pain; 
I had changed my defs.qc into .void(entity attacker, float damage) th.pain!
Me donkey. 
It needs to be that way, so it's the other way around.
I think fte looks for more loose ends than I thought, while it still passes the progs.dat.
Strange that doors.qc with its self_pain error. 
if you just want to silence the warning, you can do:
self.th_pain = (void(entity,float)) foo_notquitepain;
Such casts are generally not recommended as they'll not catch any future changes to your 'foo_notquitepain' function, and you should only ever ADD arguments to the rhs when casting functions (removing/changing args results in the function getting gibberish for the args that were not passed, or passed as the wrong type).
Such explicit casts should always be seen as a claim by the programmer that they know that the result will be safe despite its inconsistencies.

The vanilla qcc just saw function types, and didn't bother to validate the return types nor parameters. whereas fteqcc is somewhat annoying and warns about any inconsistent code that it sees.
Its worth noting that the vanilla qc code is inconsistent but not otherwise buggy. You could fix it purely using casts if you wanted to, but its cleaner to just add the extra args.
And yes, there is some door or trigger or something entity that mixes up touch functions and pain. You can fix that occurrence with a wrapper, but a cast will perform better - not that its significant enough to matter at all. 
Thanks for the info, that keeps me going! 
New Monster Qc 
I'm trying to make a new monster, that shots nails and launches rockets. When I run the qc the monster shoot nails and launches rockets at a low angle, half from bottom.
Also the two actions bump at the same time and I have no idea where to look.

Where is the statement that give more time between the actions? 
Rabbid Fire 
As long as the player is running the relation between missiles and nails is almost even, but when it is tricked into a corner the thing blasts missiles every 0.5 second.

That's no way of surviving, I know it is called Terminator, but unlimited charge is no fight. 
...half from bottom... try changing the offset amount from '0 0 10' in TermMissile to higher amount such as missile.origin = self.origin + '0 0 24'; or try copying the value you used for org in LaunchZhaser if you want the missiles to fore from the same place as zhasers do.

missiles every 0.5 seconds you have melee set to fire missiles. If you stay back away then he will only shoot zhasers.

Maybe if you want more delay add more frames or add an attack_finished check. 
Or do
self.th_missile = sknt_atk1;
self.th_melee = sknt_atka1;
To switch it. 
What do you mean bump? 
The Enforcer.qc has a code for setting the laser
org = self.origin + v_forward * 30 + v_right * 8.5 + '0 0 16';
and as far as I can see the v_foreward sets the space that messures the armlength foreward, and v_right is the distance from the entity to the right sideways.

I'm looking for the space upward, as a terminator that launches from under the belt is a bit odd. In game it is not so pronounced as with testing.

I will try your statements in the hope they lead to a better result. For sofar here is the map as far as I have finished it. The scr file is included. I've played the map myself only, and I think the gamepath isn't realy clear.

Vector Upwards 
Hi madfox, have you tried using v_up? That's the "upward" vector I think you're after. 
Belt Blaster 
@-Qmaster Changing the self.th_melee = atka1; worked for splitting the attack in two different shapes. Although I don't see the reason why self.th_melee = sknt_melee won't work.
It is defined as sknt_melee = sknt_atka1; (?!)

@-Preach : sure, but I can't find the place for the statement.
Whatever I add or change it seems 7up for the compiler.
missile.origin = self.origin + '0 0 10'; is the place to look I think? 
That's The Correct Line 
That's the right line to modify, keep playing with it until you get an effect you like. 
Algebra Dabra 
the only way I can make the missile launch higher is when I exclude
//missile.origin = self.origin - normalize(self.velocity);
missile.nextthink = flytime + time;.
Then the changes seem to have effect, although I get an eyeheight missile launching and ending on
missile.origin = self.origin + v_forward * 8 + v_right * 1 + v_up * 10; 
Changing The Order 
Yeah, that would be the problem. Notice how both lines are setting the value of the same thing - missile.origin. The second line completely overrides the first one, like changing your order in a restaurant - you don't get two meals, you just get the second one. 
Right, Uhm Wrong 
missile.origin = self.origin + v_forward * 8 + v_right * -16 + '0 0 24';
returns a launcher that shoots from the launching point left above the player.

missile.origin = self.origin + v_forward * 8 + v_right * -16 + v_up * 16;
returns a missile that explodes left of the player.

I'm thinking I'm changing the end point of the missile hitting the player. It launches from the right point, but it ends up blind. Also the negative parm comes out strange. It's not left handed? 
In TermHome,
dir = normalize(vtemp - self.origin);

I used the enforcer_laser methode to launch the missile.
This way it is the simpelest way to compile for the wanted use.
The code was from the Orb, and I had a hard job on coding the weapon.

Thanks for the hints!
They were helpfull. 
Rubicon 2 question:

You have IT_NO_WEAPON replacing IT_EXTRA_WEAPON in the code. However, I'm not sure how to implement this in a map. Not seeing a spawnflag or other way to enable it. 
Trace Volume? 
Is there a way to trace a volume similar to traceline? I need to find a volume that is not occupied by players or monsters of any size. maybe something like traceline? 
any decent engine will have a tracebox builtin for things like that.

failing that, you can also exploit quirks of droptofloor or walkmove(typically with FL_FLY?), but these are much more limited and may have additional engine-specific quirks that break your mod (at least in DP). 
Something I wrote before on how you might write a tracebox function using the method Spike suggests. His caveats stand 
Spawning with no weapons works but was never used in any of the maps so I didn't finish the part where an info player start can opt in to it. Right now it's just hard coded so to only happen if mapmame == test.bsp

So you would have to make some quakec change to complete the feature, or just change the hard coded string it's looking for -- or name your map test.bsp :) 
Is there any way to attach colored lights to projectiles or explosions via QC?

I would like to make the vore's ball glow with a purple light, make the tarbaby's explosion blue, this sort of thing...

I'm using quakespasm-spiked btw. 
a trail particle effect with 'lightrgb' and 'lightradius' set should be able to provide coloured dynamic lights, but it might only be with flashblends. I don't think I actually got around to testing it properly.

point effects will additionally need lighttime, and probably want at least one of lightrgbfade+lightradiusfade.

there are additional light properties, but those are specific to rtlights, which are definitely not supported in qss. 
Thanks! I'll try that =D 
3 posts not shown on this page because they were spam
First | Previous | Next | Last
Post A Reply:
Website copyright © 2002-2019 John Fitzgibbons. All posts are copyright their respective authors.