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
An Unnecessary WIP 
you shouldnt need to do any ammo checks with melee weapons, unless you're building a melee weapon that uses ammo, which would be pretty cool too. 
Sorry For Multi-post 
QMaster,I have a problem.
I'm using the AD Shadaxe model for jazzaxe.
FTEQCCGUI compiled without error,but when I try to select the weapon (after picking up) it just switches to the shotgun.The model appears for a split-second then the shotgun appears.I cant use it.

Then I tried (using an InsideQC tut) to make the weapon switchable by selecting axe twice.
Problem is still there.

I've ran into that before...might be a conflict with whichever bitflag value you used for IT_JAZZAXE. Can you upload a zip of your qc files? I might be able to take a look at it. 

This one has a few changes from standard id1,including the code which seems to be wrong for the Jazz Axe and some AD-inspired health model changes (.bsp to .mdl) 
Add if at the bottom
if (self.items & IT_JAZZAXE) return IT_JAZZAXE; else return IT_AXE;

And just below that in W_CheckNoAmmo:
inside the if (self.weapon == IT_AXE add "|| self.weapon == IT_JAZZAXE") 
Something is not right.

CheckNoAmmo does not have if (self.weapon == IT_AXE) part! 
i'm out of axe ammo! 
? From The Weapons.qc In The Zip You Sent Me... 
float() W_CheckNoAmmo =
if (self.currentammo > 0)
return TRUE;

if (self.weapon == IT_AXE)
return TRUE;

self.weapon = W_BestWeapon ();

W_SetCurrentAmmo ();

// drop the weapon down
return FALSE;
Never mind,found it.FTEQCCGUI has no Atrl+F combo!!! why!!!!! 
QMaster,the problem is still there.
I did some checking but I can't find anything wrong. 
in checknoammo shouldint you also add if(self.weapon == IT_JAZZAXE) return; ? 
otherwise it says you have no ammo jump to SG 
otherwise it says you have no ammo jump to SG 
if ((self.weapon == IT_AXE) || (self.weapon == IT_JAZZAXE))
return TRUE; 
Yes,I added that.It sill switches to SG after showing JAZZAXE for a split second. 
hmm what about ‘rankforweapon’ function?
im just thinking off the top of my head been awhile since i did the ol double tap
impuls to switch weapons; i had once made the lg
double as a flame thrower
you might need to add your axe there too 
Have you looked at client.qc?

There's a line

if(time > self.attack_finished && self.currentammo == 0 &&
       self.weapon != IT_AXE)
   self.weapon = W_BestWeapon ();
   W_SetCurrentAmmo ();

I suspect you need to change that last test to also consider IT_JAZZAXE
I am sorry.It does not work.Still switching after a second.

I am going to try and hunt down the warpspasm decompiled code I gave someone when I played Quake 2 years ago before going to Half-(my)-Life.

But please,try helping me.I might feature you in my mod. 
Just Checking 
What did you change it to? Was it this:

if(time > self.attack_finished && self.currentammo == 0 &&
self.weapon != IT_AXE && self.weapon != IT_JAZZAXE )
Thank You Sir 
You have saved me a complete rewrite.
Now,the world shall remember you as the savior of QuakeC.

Go Preach! 
Lol, Preach Is Always The Qc Master 
You Guys Might See 4 Teens Around 14-15 Age. 
They also will ask questions like these.Why?

Those idiots are my classmates! 
PDF For Beginners 
I created this PDF from a forum post on QuakeOne. This may be useful information for users new to QuakeC. 
Seconded That 
The way I found the problem line for the jazz axe was searching the entire sourcecode for every example of the keyword IT_AXE, which lead me to the one you hadn't changed yet. 
(from discord chat, I've chopped it down to just give the salient points)

Kinn - Today at 10:19 AM
I've had the "grenades occasionally clip straight through shamblers" bug plenty of times in vanilla quake. I'd totally forgotten it was a thing. Is it still a thing in QS etc?


c0burn - Today at 8:18 PM
entities are re-used
when an entity is removed, not all fields are cleared
the shambler code sets self.owner = lightningbolt


[editors note: player then fires a rocket/grenade, spawning a new entity just after the lightning ent has been removed]

c0burn - Today at 8:21 PM
the shamblers .owner field is set to your rocket
so it passes straight through


c0burn - Today at 8:21 PM
you can just set self.owner = world to fix it
when the bolt is removed
or not set self.owner
really it should be bolt.owner = shambler


Kinn - Today at 8:27 PM
holky fuck 
c0burn gets the Preach award for April. 
The Shambler needs to store a "link" to the lighting flash, just so that it can refer to it over the next few frames in order to animate it. There is no special reason why the Shambler has to use the ".owner" field to create this link. It could have used another entity field. Using .owner for this is a pretty dumb hack and as we can see, just invites bugs.

IMO however, the cleanest fix would be to not actually require the Shambler and flash to be linked like this - I would personally simply spawn the flash, and make it animate by thinking for itself (like the rocket explosion does.)

BONUS POINTS: notice also that whilst this is all kicking off, the Shambler sets self.effects = self.effects | EF_MUZZLEFLASH;

This has the (probably unwanted) side effect of disabling animation interpolation on the Shambler during its lighting attack.

If you made the lightning flash animate itself, as suggested earlier, you could also throw the muzzleflash effect on the flash ent instead of the shambler, controlling it through the flash anim functions. This will re-enable anim interpolation on the Shambler, and disable it on the flash - which is kind of what you want. 
Some Extra Detail 
when an entity is removed, not all fields are cleared

To expand on this part a bit: behind the scenes entity variables store a number. That number represents how far down that entity is in the list of entities - it's also the number you'd use with the edict command to print it, so the number isn't entirely hidden.

Suppose the lightning entity is number 666 on the list*. When the shambler spawns the lightning, it stores the number 666 in its owner variable. When the lightning gets removed, all of the data in slot 666 is cleared**, but the shambler entity isn't modified in any way. So the number 666 stays in place.

The only thing that will ever clear the value 666 is if the shambler spawns another lightning bolt, which will replace 666 with a new entity number. Until that happens, any entity which spawns in position 666 will be the shambler's owner (and so noclip through it). An entity slot won't be reused until 0.5 seconds has passed since the previous occupant was removed, so firing a rocket half a second after the lightning disappears is the easiest way to reproduce the bug.

The only reason this is really a problem is because the engine does special things with the owner field. In a normal entity field, the value 666 hanging around would be completely benign, as the shambler never does anything with the field except during the window where the lightning is spawned. So just changing the entity field the value is stored in will be enough to handle the bug.

*pedants corner: assume we're using an engine with raised limits so that entity 666 is valid.

**in fact in the original implementation, only a small amount of the data is cleared at the point when the entity is deleted - just enough to prevent it affecting the game further. The real deep clean of the data only takes place when the slot is reused. Until then you can access most data from the "ghost" of the previous entity - but don't ever depend on that behaviour as engines are liable to change it. Just something to be aware of when trying to debug issues. 
Quick and dirty memory management? in MY C code? It's more likely than you think! 
Concatenate Strings? 
I'd like to make an entity's targetname consist of two strings that both contain targeting information, but there doesn't seem to be an obvious way to concatenate strings. strcpy() and strcat() are unavailabe, and I haven't found a single example in the id code where concatenation is used.

Is there any other way to create a targetname from two strings I'm unaware of, or do I have to use a seperate field for the second string? 
Separate Fields 
Standard QC doesn't contain a way to concatenate strings, all strings are immutable things that you have to just take as they come. There are some complicated ways to output combinations of strings or characters to the console or the screen, but they can't be employed for logical string comparison in a sensible way. 
Abandon All Hope Ye Who Concatenates Strings 
the vanilla engine has only two ways to concatenate strings.
The first is that some of the builtins that accept a 'single' string argument will perform an implicit strcat. this is useful primarily for centerprint, but also works with bprint+sprint+error+objerror too.
The second is that console prints don't have any implicit new-lines, so you can just call sprint 50 different times to construct a single line. There are numerous mods out there that do things like this in order to try to print various numbers etc.

Other than that, you're screwed. Have a nice day.

If you're okay with requiring engine extensions, fte+qss+dp all have strcat builtins, and are all mostly compatible.
However, note that each of these engines have different temp-string behaviour. Strings in QC are essentially just pointers, so the memory that the pointer/string refers to can actually change and contain some other string entirely (usually as a result of calling other builtins that return temp-strings).

vanilla: ftos and vtos both return the exact same bit of memory, with every single call.
qs/qss: multiple temp strings - after 16 different temp-string-returning builtins have been called (from anywhere) it'll start reusing
the oldest temp-string. Use strzone if you want it to last longer.
dp: unlimited temp strings - call strcat or whatever as much as you want, but they'll ALL be forgotten once the QC returns to the engine, so ANY field or global that contains a tempstring will cause warnings when saving the game, etc. Use strzone still to avoid that.
fteqw: persistent temp strings - call strcat or whatever as much as you want. Store them in fields too, if you want.

Actually, there is a way to do strcat even in vanilla, but its so evil, obtuse, and just generally annoying that I'm not going to describe it. It also breaks compatibility with almost every other engine too, and can even be broken by just the C compiler that the engine was compiled with!

So if you're explicitly targetting vanilla and your targetname thing, just use two fields.
Whereas if you're doing more complex stuff, then you'll need to get people to stop using vanilla or quakespasm, and start using a decent engine instead that actually supports strcat (probably qss, because its basically just a super-set of quakespasm making it an easier engine to 'sell'). 
get people to stop using vanilla or quakespasm, and start using a decent engine instead

Eat shit, you gigantic self-fellating cuntflap of a non-person. 
OTP, if your definition of 'decent' is one that leaves things crippled and requires obtuse workarounds, then that's your problem, not mine. 
Your engine can have every thing ever requested by mappers and players alike and itd be nullified by the lack of documentation.

Want us to make the switch? Create some documentation. Make the source easier to access. I have reasons to use your engines but the lack of documentation is a huge turn off 
Use the pr_dumpplatform command and then just read through the resulting qsextensions.qc file if you want a list of the added qc extensions. Read the included comments if you want to figure out how to actually use it.

For particle effects, you can find some specs on fte's svn, or if you're sticking to dp-compatible stuff then you should be able to find info on that stuff on dp's site somewhere. 
Use the pr_dumpplatform command and then just read through the resulting qsextensions.qc file if you want a list of the added qc extensions.

Does this actually work in QSS? I can't find the resulting qc file 
you mentioned once that CSQC for custom HUDs could be coming for QSS - is this still planned? 
Another Question 
Now here is another thing:
Today I was testing and I noticed that no matter what ever T_Damage value I set for W_FireJazzAxeJazzaxe deals the same damage as in FireAxe.

I had set damage 40 for jazzaxe earlier and today I noticed it took me the same amount of hits to kill a shambler with the regular axe and jazzaxe.

Then I changed the regular axe damage to 600 and both axes kill the shambler instantly.

How do I fix this?
I want the jazzaxe to replace the normal axe like with the hammer in quoth and the jazzaxe should deal its own damage.
How do I do that?

(also I seem to have figured out how to add sounds like when you hit an enemy in AD and Drake.) 
I can't be sure without seeing the code but it sounds like W_FireJazzAxe isn't being called.

First step would be checking W_Attack further down in weapons.qc and checking that your (presumed) if (self.weapon == IT_JAZZAXE) clause is pointing to a different player animation function than the normal axe.

If it is, then check that the relevant function in player.qc contains W_FireJazzAxe() instead of W_FireAxe() 
add a call to error("function name here"); into both functions.
then you'll see which one is actually getting called.
it should also give you a stack trace, so you can figure out where its getting called from too.

(or if you're using fteqccgui+fteqw, you can just set a breakpoint and then step through the code.) 
I Got It! 
The problem was this

void() player_jazzaxe1 = player_axe,not jazzaxe! 
I Would Like A Little Bit Of Help 
So now I migrated to Rubicon Rumble Pack's code.With some of my changes.

I have some questions.Again.

1.How do I add a weapon? All the bit values upto 8388608 are used.And I tried 16777216 but it doesn't seem to work.

2.How do I do that subtraction thingy with self.items?
How does it work,anyway?

3.I checked out the Keep mod by QMaster,and it has a self.items2.What is the self.items2?
How do I add it in my mod?

I know I can just do a .float self.items2,but how can I manipulate it?

I Would Like A Little Bit Of Help 
So now I migrated to Rubicon Rumble Pack's code.With some of my changes.

I have some questions.Again.

1.How do I add a weapon? All the bit values upto 8388608 are used.And I tried 16777216 but it doesn't seem to work.

2.How do I do that subtraction thingy with self.items?
How does it work,anyway?

3.I checked out the Keep mod by QMaster,and it has a self.items2.What is the self.items2?
How do I add it in my mod?

I know I can just do a .float self.items2,but how can I manipulate it?

I don't want to clog this thread with my questions so I gave my email. 
Use Notepad++ 
It has a search in folders option to let you find every instance of .items2

.items2 was derived from the rogue mission pack since .items ran out of bits. 
So in which file can I find a way to derive?

Do I just add

.float items2 in defs.qc?

Then how do I add stuff to it? 
Treat It The Same As Self.items 
Ya just add it to defs.qc or anywhere in the compile order before you use it.

Add in any IT2_JAZZYSTUFFBITS = 1, 2, 4, 8, 16, etc flags. The only really tricky bit is in situations like weapons where you need to know when to check .items and when to check .items2 or you'll be able to switch to weapons you don't have, or accidentally give yourself quad or something. 
Can Teleportation To A Random Destination Be Done In Qc? 
if a trigger_teleport has multiple destinations with the matching targetname, it will always pick what I assume is the the one that is loaded first in the map and therefore has the lowest index of some sort that the find function looks for. I'm not really sure how it works since find is only defined as #18 in the code. I'm not very well versed in qc or regular c for that matter. I implement stuff by deriving heavily from existing code, so I'm at a loss here.

I need a more thorough find function that takes an additional index parameter that returns the first entity whose targetname and index match the given arguments. Then I would only need access to the amount of entities with that targetname and could generate a random number between 0 and that amount to use as the index argument.

I assume the reason find isn't defined in qc is that the the finding process can only be done by the engine, which would be a death sentence for my mod. I stand even less of a chance of understanding complex engine code than qc, and even if I did manage it the mod would be dependent on my custom engine branch which would make it an even harder sell to potential players.

I'm pretty much ready to throw in the towel, but I figured I'd try consulting the mighty code wizards first. Is there a way you could see making random teleportation work without engine modifications? 
just call find in a loop with the first arg set to the previous call's return value, until it returns world.
you then know how many matches there are, and you can pick a random index and select that destination with a second find loop.
no engine changes necessary. 
Thanks Spike 
works like a charm 
Here's a sneaky way to randomly select while only looping through the list once 
Post 2513 
If my memory serves me well,
Custents has a random teleport code.
Or was it nsoe_devkit? 
It's Getting Annoying 
I keep getting this error
Warning Q208:progs CRC not recognised from quake or clones.
This always happens.
If I make a new weapon to add to RRP?
Copy the fx_beam and telefrag?
Part of my code is copied and modified from RRP,Custents and some other sources.

Today I had to reset all my code because of their error.I call it an error because it compiles,but you can't run the game.

How does this warning happen and why?
How should I fix it? 
Warning Q208:progs CRC not recognised from quake or clones.
This can be translated to:
Don't fuck with the initial part of defs.qc

NEVER change 'ANYTHING' before the 'end_sys_fields' line of defs.qc or you get that warning.

(actually, you can change comments, add some preprocessor (like #pragma warning error Q208 etc), etc, but if any of the basic types or names changes, or any symbols are added or removed, then you will have problems as the interface between the engine and progs will end up incompatible.)

(one option is to just include [fte|qs]extensions.qc (not dp's though) before your defs.qc, as it includes systemdefs appropriate to its configured target. you'll also get extension builtins defined for you.) 
Or Use A Separate Defscustom.qc For Your Mod Variables. 
Thanks Qmaster and Spike.
I'm using a custom Def's.qc called astaf.qc,which was the name of my cancelled Half Life mod. 
Sorry For Double Post 
How do I use the Gyro library?
I've added it to my mod,but it's a little confusing.
I think I'm going too fast,this is my first mod after all. 
Sorry For Double Post 
How do I use the Gyro library?
I've added it to my mod,but it's a little confusing.
I think I'm going too fast,this is my first mod after all. 
Sorry For Double Post 
How do I use the Gyro library?
I've added it to my mod,but it's a little confusing.
I think I'm going too fast,this is my first mod after all. 
It's Been A While 
I haven't messed with Gyro in ages, but you might be able to take a look at how things were done using it in the SMC (Small Mod Compilation) created by sevin:

I'm stuck in an airport for a few hours so maybe I can poke around and let you know what I find. 
bumpity bump bump 
I Haven't Found A Working Link For Gyro Yet So... 
..a Mammuth Sized Shambler ! Headed To Preach..but Not Only 
Hi.. is it possible to create a huge Shambler (10 times the player size) ? What about bouncing-box issues ?
What qc changes needed ?
My map is called "Hunt 4 The Great White" 
Komagama Muth 
Here's one. I made it eight times as big as the original.
Bouncing box extends automaticly.
If you use it without changes it flashes from its heels, and can only be hit when you hit it in its foot.

Just for try out, replace it in your progs with the original one and give it enough space.
The best way to make it addepted is by mulyiplying all counts of walk and run with 8. Also the magic lightning will need that number.

I included a mdl and a probable qc, no idea what will happen.
Didn't test the beast. 
Some Adds 
I made a quick try and it seems to work, unless...,
you delete the original shambler out of your qc as all names are the same.
If you need small shamblers too, then give all related names for shambler in the new qc file another name, ie mamuth.

The bouncing box doesn't fit, it's way too small. Although I altered them too. Also the lightning emerges so high its inside its corps. So some alterations are needed here.

I was afraid the skin would look horrible, but that isn't the case.
I just can't escape from it as it moves that incredible fast. 
Bouncing Box? 
Is that what we are calling the bullet interactable box now to distinguish from the physical box?

BounDing box max is hull 2 size of 64x64x80. However, setting the size of a monster to something larger in qc allows bullets to hit it at the larger size even though its physical size is the same. E.g. It could still fit in 81 unit high spaces however, and have its model sticking through the ceiling. 
Oh Thanks To All.. Another (fancy) Question 
supposing I make a total conversion eligible for sale commercially.. what exactly is gpl ?

-I've read that qc code(progs.dat)also is an "asset" because is read by engine as data ?!
Then should I rewrite it all from scratch ?

-And what about the .exe's(glquake.exe,winquake.exe,darkplaces.exe,fitzquake.exe) since are not included in id released source code ! 
My Name Is Madfox And I Want My Money Back! 
GPL is a copyleft license for software, devised by Richard M. Stallman of GNU, who (in short) states that you can use the software to do what you want, including customizing and selling, provided you pass that right on to others and the author. (s) of the software. In concrete terms, the foregoing means that if you want to distribute software that has been published under the GPL, the source code will have to be added. This source code may then be further distributed under the GPL. Anyone can choose to publish his or her program under the terms of this license.

You don't need to rewrite it, as long as you include the code you might have read the scripts that are in the qc that state:
Copyright (C) 1996-1997 Id Software, Inc.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

See file, 'COPYING', for details.

But seriously komagama, I thought you were mapping for fun. I understand your considderation of making a commercial project but then why not start with something like gamemaker?

I'm mapping for several years now, I have only the love for the game, and when I ever had the intention to sit on iD's hat for making a commercial addon I probably had stopped many years ago.

Don't get me wrong, I don't want to disappoint you, but I've seen it before. People with the best intentions to make a coin out of hard earned worked getting screwed off by others who just wanted a piece of the (qc)ake.

Anyway, it is your decision. But watch out, I would love to play your map for free, but if you would ask money for it I would become so critical you wouldn't like your own map anymore.

So I'll start with ten bitcoins for the advice I gave.
Just Kidding Komagama 
You can find the correkted file here.
It's the mamuth.mdl of the super shambler, the h_mamuth.mdl of its head and the mamuth.qc.

If you compile this file you can use it with the normal shamblers in your map, with this result. The bouncing box is right his size.

Only thing left is tweaking the size of its lightning, but I supose it will always be beyond the player view, due to its size.

Succes with it, curious to your map. 
Thank Madfox.. But 
i'm not a noob in game-designing, sorry if I gave that impression.. Fact is there's something in gpl quake code that I cannot understand:
help me if you can:
-may I use big portions of Id qc unmodified (ai.qc, buttons.qc, monsters.qc) ? Carmack stated that you can create your standalone game based upon that code.. 
Would you look at that mammuth shambler! :3c It's so big and clumsy. He'll never be able to reach the "mouseholes" the player escapes into.

Which reminds me, compared to the regular shambler, has the movement speed been increased for this adorable little monstrosity?

Nice work, btw! ;) 
@komagama- well, I'm a noob in gpl code, so I can't help you out.
Maybe someone else.

@Esrael- Mouseholes? That's where the little Shambs come in.
I'm more concerned when it dies the player walks 96 units in shamb space nothingness.
And as I wrote: I just can't escape from it as it moves that incredible fast. 
The QC code is not under the GPL. However, when I talked to someone at id before they were sold to Bethesda, they expected people to handle the original QC code in the same way as the engine code, which means keeping the source open. 
You Heard The Man 
QC please! Chop chop. That means you. Haha. 
Broken English 
mamuth groans I'm too Q to see. 
Oh.. My Headache.. 
now I know why nobody made commercial tc based upon this engine.. aha
Anyway the official released from github includes qc files so they must be gpl as well :) 
The ogre has a pull pose of 11 frames which won't be used in the qc. What should have been its purpose?

I'm retrieving the Qtest1 qc, without any luck.
I'm using the one from Megalol, which luckely has a progs.src
Only problem is that it is casting more than eighty nine warnings.
It seems to me that a lot of it is just a replacement of the original qc.

I spent a whole evening just to get rid of the first moveangles to moveangles2. Is it realy that bunch of spagetthi? 
Projecting Text To A Quad 
are there any examples out there of projecting text to a mesh using an engine like DP or FTE? Or even just dynamically creating a texture and assigning it to a mesh? 
With an animationmaster it is simple, but I know you won't have obviously. You might try max3d or gmax. Here's an example I made.

Or hand me the file and I can see what I can do for you, beer me up, scotty
That's Pretty Cool 
but not what I meant :P sorry, I didn't explain clearly.

I meant taking plain text from a text file and projecting it onto a quad or converting it to a texture dynamically to be assigned to a mesh. If that makes sense. 
Blender can make polygonal text...not quads though.

Best bet might be to make an alphamasked sheet texture with all letters and numbers on it...then assign UV to uach letter for quads.

For quake mdl format you might be able to have 1 quad for each letter/number/rune and have only one quad visible per frame....then in-game you could set the frame number for the letter, but that's a boatload of work. 
If you know the direction your quad faces and the tangent+other one then you can generate the text from csqc with beginpolygon in 3d space.
If its co-planar, you'll need to use stuff like polygonoffset and/or pay attention to shader sort ordering.
This will work in both FTE and DP. The shader tricks may not, however.

Alternatively, a shader with 'deformvertexes textN' will replace a quad surface with the text in the r_shadertext_N cvar(s) (the shader's texture should be a 16*16 grid of chars).
This will only work in FTE.

The third option is to use render-to-texture, and to draw your text that way (which means it can also support unicode etc easily, or even other scenes). You can then use .forceshader or whatever to wrap it over even non-planar surfaces on some target entity.
'map $rt:foo' in your shader, possibly via shaderforname.
setviewprop(VF_RT_DESTCOLOUR, "foo", 1, [width,height]);drawstuff(); setviewprop(VF_RT_DESTCOLOUR, __NULL__);
This will only work in FTE.

Or you can use r_uploadimage and scribble over a texture from QC (which basically requires pointers+ints and masking), FTE-only.

You can also use rtlight cubemaps to dynamically project a texture, but this assumes you've a number of prior cubemaps to select between. You really don't want to use one per letter.
You could also use one sprite per letter (or more realistically one sprite-frame per). Will at least scale better than rtlights... 
@qmaster - that sounds... crazy :P

@spike - exactly the info I was looking for, thanks! 
I'm adding old sprites to Quake1Test maps.
I added some lines on misc.qc for a new light_large_flame,
and to world.qc and it comes up in game.
Only eddict is : R_drawsprite: there is no such frame 1
Does the QTest torches use framegroups in their sprites? All frames will cycle through frame 0 then. No need to animate manually.

Most Quake sprite editors can't generate framegroups. 
What Does Edit Framegroups? 
Also the first frame is frame 0. 
Never Got Out That $pr1te Thing. 
Here's my statement I'll think.

Sprites: Torch (s_torch4.spr) comes through right.
Flame_ball sprite (s_torch6.spr) comes through with error:
R_DRAWVIEW : No Such A Frame1

and it keeps rolling on screen..,

Or better, download following.
Here are my poor reasults for making a SinglePlayer QTest1.mod. 
s_puff.spr and s_statue1.spr and s_telep.spr have (nogroups) frames.
s_torch4.spr and have (Group 0) frames.

How do I change them from Group0 to nogroups?
I use FimG and the window indicates Group Properties but leaves blanc. 
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.

First | Previous | Next | Last
Post A Reply:
Website copyright © 2002-2018 John Fitzgibbons. All posts are copyright their respective authors.