|
Posted by metlslime on 2007/08/08 04:57:56 |
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. |
|
|
Incidentally
#420 posted by necros on 2010/09/25 06:00:52
i only noticed this happening because i have some debug code that outputs a ton of text repeatedly to the screen. with that many outputs, the screen practically shakes when riding a lift up.
it's not like it's really a big deal since when you play normally outside of developer 1 mode, you don't get the outputs and so don't get the shaking.
on a possibly(?) related note, monsters riding a lift up appear to not interpolate their positions if they are walking on the platform?
#421 posted by metlslime on 2010/09/25 19:19:38
on a possibly(?) related note, monsters riding a lift up appear to not interpolate their positions if they are walking on the platform?
yeah, I noticed this recently. Must fix!
As for the view jerkiness on lifts... I've seen this but it didn't notice a connection to console prints. Will investigate.
#422 posted by necros on 2010/09/25 21:41:16
possibly helpful:
it is not strictly bprints that cause this. when i turn the console spam off, every so often the view will jerk rarely.
Engine/editor/compiler Coders Please Help!
#423 posted by than on 2010/10/03 19:17:48
I got this urge to try and write my own Quake map editor for fun (don't hold your breath) and I am already stuck at the first hurdle (for this reason).
I don't know why, but I thought I would try and load a wad file first. Just so I understand the format I thought I'd read about it and implement it myself. I've also got the code from the engine to look at, so it's not super difficult, but I am having a weird problem.
When trying to read the individual lumps that contain the image data for textures, if I try and read the width or height value I just get nonsense UNLESS I add a weird 16 byte offset to the pointer I am using.
example:
LUMP_t* lump = (LUMP_t*)(waddata + lumpinfos[lumpno].filepos + 16);
cout << "width: " << lump->width << ", height: " << lump->height << "\n";
will output the correct width and height, but if I remove the 16 byte offset, it doesn't work and I get gibberish.
My problem is that I have no idea why I need to add the 16 byte offset, and am worried that it might cause problems down the road if I don't understand why it's there.
Aside from that offset, everything seems to be as I expected.
Than
My tip: try and implement some simple editing functionality as quickly as possible because that will keep you motivated. Don't write struts code like reading wad files. Write your internal model for brushes and write a simple renderer for that. Then, improve on that code. If you have to write code that doesn't draw anything on screen for weeks, you will very likely lose your motivation quickly.
Sleep
#425 posted by than on 2010/10/04 13:00:37
thanks for the tip. I know it can be really boring to write code that doesn't draw stuff, but for some reason I like writing file loaders and figuring out how stuff works. My plan for tonight is to get wad textures displaying on screen and then I want to go onto the exciting brush stuff and improve my 3d math knowledge (I forgot most of it... oops).
I don't think I will be able to write an editor as awesome as Willem's Toetag, but if I get even 1/4 of the way there, I will have learnt a lot :)
One Tip
Brushes are represented in map files as the intersection of a number of half space equations (each face is such an equation). You must convert this representation into a representation that you can use to draw stuff, i.e. polygons which you send more or less directly to OpenGL. There are several techniques to do this by calculating the extreme points of the solution of the original system of (inequality) equations. These techniques are computationally optimal, but very hard to implement correctly. I suggest you don't touch that stuff for your first version.
Another very simple way of converting a brush to polygons that you can draw is to start with a cuboid polyhedron (represented by its vertices and edges) with maximum dimensions and then simply split the brush along the planes which are defined by the faces. This is easy to do because you just have to intersect all edges of the polyhedron with the splitting plane. You'll end up with a polyhedron that has the same shape as the brush, but you can easily determine the face polygons from that data structure. This is computationally inefficient, but since you are not dealing with a lot of data, it's fast enough.
Another tip is to use the vertex / edge representation only for rendering, not for manipulation of the underlying brushes. The brushes should remain in their original representation and should be manipulated in that representation as well, This way you can use the very high precision that the half equation intersection representation offers (and don't have to convert float vertices back to int).
Sleep: No No
#427 posted by bear on 2010/10/04 17:50:49
implement rounding errors or some other form of sloppy calculations so it will feel just like using qoole!
Thanks For The Tips
#428 posted by than on 2010/10/04 18:33:43
I got my wad loader working ok and it renders textures from a 570 texture wad just fine. The code is a total mess and I still don't know what that weird 16 byte offset is, but I got Quake textures displaying on screen in sexy Quake colours, so I'm happy for today. Next step will be a map loader :)
I made a map compiler (not to bsp, but to a much simpler format that just uses polygons) before, so I still have some code that can create polys from brushes somewhere. I was going to use that. Pretty sure it uses the clipping method. The first solution sounds difficult :)
this?: http://en.wikipedia.org/wiki/Convex_polytope#Vertex_representation_.28Convex_hull.29
Math on wikipedia is always extremely hardcore sounding.
Just Had A Look
#429 posted by than on 2010/10/04 18:48:45
at my old brush compiler code and it appears to take a series of 3 planes to generate a vertex and then adds the generated vertex to a vertex list for the each face involved in its calculation. It iterates through this until it's done and looks very inefficient.
But if it works, I don't care :)
When editing a map, most of the brushes just sit there unselected. I would imagine the average user doesn't touch more than a handful at once, and even then most of the operations are probably moves.
Probability Of Attack
#430 posted by necros on 2010/10/05 20:07:17
anyone who's studied this could answer a question?
if i've got a monster who has an 80% chance to attack when his checkAttack function is called:
if (random() < 0.8)
attack!
does that really mean he has an 80% chance to attack at all times? or is it more like 10.7% chance to attack every second? (0.8 ^ 10 since animation rate is 10fps)
probability has always been pretty impenetrable for me. :S
as a result, i tend to rely much more on 'cooldown' (attack_finished) timers to regulate monster attack rates.
Geometric Distribution
#431 posted by Preach on 2010/10/05 21:53:02
The code you posted means he has an 80% chance to attack each frame. One of the best ways to understand what this means is to look at the probability that the monster will start attacking before the 2nd, 3rd, 4th frames etc.
The easiest way to do the calculation is to flip the question on it's head. What is the probability that we are still not attacking on the 2nd, 3rd, 4th frame? For that to be the case, we must have failed to attack in all the previous frames, and the chance of that is 0.2 each time. Since each trial is independent, we can multiply them together, as follows:
Frame 2: 0.2 * 0.2 = 0.04. 4% chance of not attacking after the second frame
Frame 3: 0.2 * 0.04 = 0.008. A 0.8% chance of not attacking on the third frame or earlier.
Frame 4: 0.2 * 0.008 = 0.0016. Scarcely a 0.1% chance that we are not attacking 4 frames of considering it.
So it's pretty certain we'll attack within the first 3 frames, our code is largely creating variety in behaviour over a range of just 0.3 seconds. Even if we changed the probability to 0.5 we'd still expect the monster to attack quite quickly: 1 / (2^10) is the probability that we wouldn't have attacked after 1 second - which works out at > 0.1%.
Using attack_finished as a cooldown is probably the best way to to long pauses out of your monsters, if you want them to choose between attacking with a missile or closing the distance with the player.
Yeah
#432 posted by necros on 2010/10/05 23:25:20
that makes a whole lot more sense. i confused myself over why the chance to attack would go down over time, which is just stupid because every time we check, we are giving a new chance to attack.
Quick Question
#433 posted by than on 2010/10/07 16:21:16
I have a feeling I could find this if I dug through the Quake source, but are the lengths of key/value pairs for map entities limited to 16 and 32 chars respectively? If not is there some other limit? Does anyone know.
On top of that, if anyone happens to know the max number of:
entities in a map
faces per brush (guess this is compiler limited)
key/value pairs per entity
I'd love to know them :)
^^
#434 posted by necros on 2010/10/07 19:04:03
Thanks
#435 posted by than on 2010/10/08 00:20:21
1024 seems quite a lot. I'll just get rid of the limits I put on my map loader.
Texture names do appear to be limited to 16 chars though.
#436 posted by metlslime on 2010/10/08 00:39:27
Texture names do appear to be limited to 16 chars though.
15 chars unfortunately, since you need a null terminator.
#437 posted by Spirit on 2010/10/08 16:25:55
This is not QuakeC related. The answer is hopefully simple algebra but I am too stupid to figure it out for myself and Google is not helping.
Let's say I have these 2D coordinates:
1) 10;10
2) 54321;12345
and want to fit them into a smaller (let's say 800x800) window. How would I code that? Do I really need to make an affine transformation? If yes, no need to explain the how, I should know that.
";" Is Not A Name
#438 posted by jt_ on 2010/10/08 22:57:46
frikqcc keeps complaining about ";" not being a name in the following function, but I can't any ;'s being used as names, or any stray ones that might being messing with things. This is just the BackpackTouch func from progs106
<code>
/* PLAYER BACKPACKS */
void() BackpackTouch =
{
local string s;
local float best, old, new;
local entity stemp;
local float acount;
if(other.classname != "player")
return;
if(other.health <= 0)
return;
acount = 0;
sprint(other, "You get ");
if(self.items)
if((other.items & self.items) == 0) {
acount = 1;
sprint(other, "the ");
sprint(other, self.netname);
}
// if the player was using his best weapon, change up to the new one if better
stemp = self;
self = other;
best = W_BestWeapon();
self = stemp;
// change weapons
other.ammo_shells = other.ammo_shells + self.ammo_shells;
other.ammo_nails = other.ammo_nails + self.ammo_nails;
other.ammo_rockets = other.ammo_rockets + self.ammo_rockets;
other.ammo_cells = other.ammo_cells + self.ammo_cells;
new = self.items;
if(!new)
new = other.weapon;
old = other.items;
other.items = other.items | new;
bound_other_ammo();
if(self.ammo_shells) {
if(acount)
sprint(other, ", ");
acount = 1;
s = ftos(self.ammo_shells);
sprint(other, s);
sprint(other, " shells");
}
if(self.ammo_nails) {
if(acount)
sprint(other, ", ");
acount = 1;
s = ftos(self.ammo_nails);
sprint(other, s);
sprint(other, " nails");
}
if(self.ammo_rockets) {
if(acount)
sprint(other, ", ");
acount = 1;
s = ftos(self.ammo_rockets);
sprint(other, s);
sprint(other, " rockets");
}
if(self.ammo_cells) {
if(acount)
sprint(other, ", ");
acount = 1;
s = ftos(self.ammo_cells);
sprint(other, s);
sprint(other, " cells");
sprint(other, "\n");
// backpack touch sound
sound(other, CHAN_ITEM, "weapons/lock4.wav", 1, ATTN_NORM);
stuffcmd(other, "bf\n");
// remove the backpack, change self to the player
remove(self);
self = other;
// change to the weapon
if(!deathmatch)
self.weapon = new;
else
Deathmatch_Weapon(old, new);
W_SetCurrentAmmo();
};</code>
Deception
#439 posted by Preach on 2010/10/09 00:14:24
The error message is true but unhelpful. It's trying to use a ; as a name, but what that means is that it's reading a line in a way you didn't intend. Often you get unexpected parsing errors when you leave a function earlier or later than expected. In this case you're missing the closing braces for the self.ammo_cells block, and so it's reading some further code incorrectly.
I know that func_ eats indentation(unless you're really patient with inserting nbsp character entities) so I can't say if missing indentation might have made this harder to spot. But I can recommend editing code in something that can highlight matching braces in some way - I pasted the code into notepad++ to check the matching. I will concede that knowing it could be a mismatched brace based on the error was really key, so it's not all software solutions.
Hat Tip
#440 posted by jt_ on 2010/10/09 00:32:49
That was it, thanks Preach. In my editor (acme) everything is indented fine, but as you said func_ at them. Wish func_ has support for <code></code> tags.
Don't Forget To Spellcheck...
#441 posted by jt_ on 2010/10/09 00:33:58
s/at/&e
#442 posted by necros on 2010/10/09 02:23:15
a preformatted tag would be nice, but that would likely break the forum width?
mind you, the forum could probably get twice as wide without bothering anyone.
#443 posted by Spirit on 2010/10/09 08:23:06
No, absolutely not. Apart from the colours and no-clutter, the 72-80 character line length ensures the great readability of func. Forums that spread to full-width (or anything remotely like that) are an abomination.
Use http://www.inside3d.com/pastebin.php , that even gives you syntax highlighting. Also be aware that func has a preview button. ;)
Yeah
#444 posted by RickyT33 on 2010/10/09 14:59:28
No offence to Quakeone.com for example, but having like more than 12 words on a line is a bit of a no-no. Just hurts my eyes :)
|
|
You must be logged in to post in this thread.
|
Website copyright © 2002-2024 John Fitzgibbons. All posts are copyright their respective authors.
|
|