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
 
depends how large your projectiles are.
with the vanilla network protocol, origins have 1/8th qu precision.
angles have 1/256th revolution precision

on a large object with offset origins (read: rotating bsp doors), the angular precision can result in significant jerks. this is generally not much of an issue with models though.

if you want to test if its an engine precision thing, try the following engine+cvar settings.
fte: compare sv_bigcoords 0(low/vanilla precision) to 1(16bit angles, 32bit float coords). restart the map for it to take effect.
dp: compare sv_protocol 'quake' (vanilla) to 'dpp7' (16bit angles, 32bit float coords), or whatever it was. not sure what you need to do to actually apply the new setting. 
They're Points 
So that pretty much rules that out. I need to debug again.

Thanks for the answer. 
 
you're using makevectors and v_* to do the offsets? 
 
yeah, makevectors(self.angles) is bad if self.angles_x will ever be anything but 0.
makevectors pitch angle is inverted relative to non-brush models (old id bug).
yes, its inverted relative to vectoangles too. 
No Makevectors... 
I got it working eventually in a testmap like I say, without any weirdness. Just in my large BSP2 it seems like the org (point of origin) is behaving like the vec (point of aim).


org1 = self.origin + v_forward * 20 + v_right * 36 + '0 0 24'; //right hand
org2 = self.origin + v_forward * 20 + v_right * -36 + '0 0 24'; //left hand

vec1 = self.enemy.origin + RandomOffset(22) - org1;
vec2 = self.enemy.origin + RandomOffset(22) - org2;


The RandomOffset function just does this:

local vector offset;

offset_x = crandom() * offset_amt;
offset_y = crandom() * offset_amt;
offset_z = crandom() * offset_amt;

return offset;


Am I missing something obvious there or taking something for granted? My coding is built on trial and lots of error, meaning I kn ow nothing of good practices etc. I don't have makevectors anywhere in the qc file actually... 
Well There's Yer Problem 
makevectors is where v_forward and v_right get populated. if you don't call it on self before doing all that, they'll be left over v_forward and v_right vectors from whatever thing last used them. 
Hah, So... 
It was all in my head about it only happening in the larger map.

Will test it out tonight, thanks. 
So It Works 
After all that pissing about it turns out I just forgot to reset the vectors.

But it works now!

Screaming plasma death coming to a mod near you 'soon'. 
Writing Some Tools... 
I'm currently trying to make some simple tools for working with wads and paks that work via web browsers. I know this sounds pointless, but given that texmex, qped and pakexplorer are windows only, I thought it might be worthwhile so that people on any platform can fiddle with these formats.

Although both formats are trivial, I've noticed a few weird things with the contained images. I've been looking at the (old and eronious in a few spots) quake specs, and there seem to be three different types of image format used in Quake:
1. pixels
palette files, conchars in gfx.wad, colormap.lmp and maybe others
2. width, height, pixels
most, if not all lmps and status images in gfx.wad
3. name, width, height, pixels1, pixels2, pixels3, pixels4
all standard textures contained in most wads and bsp files

WAD file entries contain a type parameter that specify which format is used, but I've noticed that this isn't always correct. In gfx.wad, for example, the file conchars is listed as the same type as a regular wall texture (type 3), yet has no header and is exactly 128x128 bytes. The lmp files in pak0.pak also contain a couple of textures that have no header, whereas the others do, and a handful of them are strange sizes.

The mystery lmp files are 3352 bytes each. Since all images are meant to have width and height that are multiples of 8 the size doesn't work out, even accounting for an 8 byte width x height header. Just wondering what kind of files these are. The names are " gfx/dim_???.lmp" and "gfx/netmen?.lmp".

Should I just ignore the size and assume that aside from the special cases I mentioned above, that all UI textures and lmps are class 2 and all wall textures are class 3? 
That Sounds Awesome 
but to answer your question, I don't know. probably! 
 
tbh I'd just special-case it.

netmen* are image lumps. serial, modem, ipx, tcp, etc options.
dim_* are greyed out versions of those.

the *8 size applies _only_ to transparent lumps, and only to their width. the height can always be any value it wants.
for non-transparent lumps, the width can be anything, even 1... at least in the software renderer. I imagine the gl renderer mandates a multiple-of-4 width, but not height.
I should probaly mention at this point that hexen2 has some &3 widths in its gfx.wad.
the two lmp groups that you name are not transparent, and thus can be any size they want, ish.

palette, colormap, conchars. these have special handling in the engine. the engine doesn't care about types.
other images in gfx.wad should never be mip textures, as that would be pointless.
any other wad with any other name should contain mip textures. any time that that's broken you can expect issues all round.

what I'm trying to say is that there isn't really any reason that the data must be of a specific format, unless the thing trying to read it requires it to be.
.wad dates back to doom, it really is just a collection of file lumps rather than some clever format with well-defined file types. 
Spike 
Thanks. I put a special case for conchars already, so I guess I'll do the same for lmp. Maybe there is some formula that would allow me to figure out the header type, but I'm not sure. I guess special case by name and size is probably safest :/ 
Wad Lump Types 
Than: it sounds like you already identified the special files for the most part, but I will clarify:
gfx.wad conchars.lmp - 128x128 raw image, color 0 is transparent (unlike other pics)

gfx.wad colormap.lmp - 256x64 image of nearest-match colors for light level shading (0-63, with 32 as neutral, 63 as 2x brightness), followed by a 32bit integer (which sometimes stored as a single byte instead), which is 32 in id1 and typically 32 in all mods (there might be some with 0), this number is how many palette entries are fullbright (256-n is the start of the n fullbright colors in other words).

gfx.wad palette.lmp - 256x3 array of RGB colors, not copyrighted (John Carmack explicitly stated that id do not care if you copy the palette, or even embed it in code).

Miptex wads also contain palette.lmp, but all other files in them are .mip.

All other files are consistently formatted, the transparent color in .lmp (and .spr for what it's worth) is 255, no other format supports transparent pixels.

Size restrictions:
.lmp - no real restrictions, but glquake has errors if the width is not a multiple of 4 (software quake has no such restriction), and software quake corrupts memory if an image exceeds the screen boundaries, so even centered 320x200 image is the practical limit.

.mip - glquake has errors if the width is not a multiple of 4, software quake requires the width and height to be a multiple of 16 (due to surfacecache having a hard-wired function for applying lightmaps to a 2x2, 4x4, 8x8, or 16x16 grouping of pixels).

If you wanted to solve a problem that has probably been vexing people for some years now, why not make a converter for combining two .tga 32bit color images (one .tga for albedo/diffuse, and one _glow.tga) into one .mip file (or .pcx for loading into .mdl and .spr editors) where the glow colors are mapped to fullbright range (according to colormap.lmp's value for how many fullbrights exist) and the regular .tga's colors map only into non-fullbright colors, it's always been a pet peeve of mine with the tools at hand, but as I was kind of rendering the quake formats obsolete over the years I never bothered.

Note that there are some special files outside the .wad as well that may not be obvious:

gfx/qpop.lmp - this is a 16x16 image (I think in Quake palette?) that is the quake logo, the general going theory on this is that the quake logo is trademarked and thus it would give them a way to sue people for distributing quake mods designed to be used with shareware quake (which lacks this file, and thus refuses to run mods).

end1.bin - shareware quake dos text to show on exit

end2.bin - registered quake dos text to show on exit 
/me Weeps 
I Have Two Stupid Questions 
1. I want to pass an entity field to a function. What's more efficient: to pass one field (say, a string) or an entity pointer? Assuming that other fields won't be needed in said function.

2. There are various styles of naming the functions in id1 QC: DerpDerp(), derp_derp(), even Derp_Derp(). Is that because various programmers didn't care about naming conventions, or is that meaningful in some way? 
Answers 
1. Pass the string, not the entity. All strings in QC are immutable and all you're doing is copying around the pointer, which is cheap. On the other hand if you send the entity, then you have to go through an extra two intructions each time you need to access the string, which is marginally more expensive.

2. There's no meaning, it's just that lots of id staff worked on the code and had different coding styles. There isn't even a good way to tidy the codebase back up into one convention: the fixed QC functions that the engine calls are all InitialCapital style like StartFrame and PutClientInServer, but unless you're going for a total conversion all the classnames are in lower_case_underscore format and you're stuck with those function name too!

So do whatever you're comfortable with in your own code, but I would recommend obeying the conventions on classnames - stick with lower_case_underscore for the names, starting with func_ for visible brush entities, trigger_ for invisible brush entities, and monster_, item_ OR info_ for point entities. 
 
1. If you pass the value, you can't write to it. The caller will need an extra intruction to pass the value, which is the same as if you read it once inside the function anyway.
If you pass the entity, you can change it to some other string, but reading will cost 1 more instruction (1 to read, 2 to write).

2. For engine->qc calls, I generally expect camelback function names combined with at least one underscore! which helps when the majority of functions are all lowercase. less possible conflicts.
spawn functions should probably be lower case, just because. however, there's at least one that isn't. oh well. 
 
Is QC performance ever a real concern these days to where an extra instruction here or there makes the difference between smooth and choppy gameplay? I don't know, I'm seriously asking. 
 
Thanks for the answers.

Willem, I doubt it. I just don't want to pick any bad habits if I can avoid it. Besides, I was curious. 
 
No. But very rarely yes.

A lot of code gets run once per frame or once every animation frame (typically 10 times a second). This kind of code can be messy without impacting performance on even a semi-modern machine.

The times where it can matter are when you are doing things in a loop during the same frame. For example, pathfinding, or searching for new enemy targets. 
 
dwere

Sure, I understand that. Tinkering with something like Quake is fun because you get to understand every nook and cranny after awhile. It's stable and unchanging and there's something comfortable about that. 
 
And something a little disheartening as a programmer. As you're figuring out more and more about how things work and what does what, you realize that Carmack came up with and wrote most of this from scratch 18+ years ago. Damn him... 
 
self.function = (void(float))funcWithFloatArg;

results in:
type mismatch for = (pointer and __variant)

What version of FTEQCC do I need to make that work? 
A New Version 
http://triptohell.info/moodles/fteqcc/ does all of that, as well as adding a bunch of warning for NOT doing it. 
 
Thanks! Shame that's buried on some hidden server. :( 
First | Previous | Next | Last
You must be logged in to post in this thread.
Website copyright © 2002-2024 John Fitzgibbons. All posts are copyright their respective authors.