Well
#404 posted by Preach on 2010/08/21 02:49:06
I do have a fun fact about that fun fact: it implies that in a multiple collision, the order that the collisions are resolved is essentially unpredictable - they depend on the location of the entities within the bsp tree that comprises the level.
Speculation: it might be possible to exploit this to glean some information about the bsp tree from QC - using force_retouch with a trigger and some point entities spawned in a region. Knowing that one point is in a leaf higher up the tree(or further left) than another may not be incredibly useful though...
Path_corner Weirdness...
#405 posted by necros on 2010/09/04 22:25:12
void() movetarget_f =
{
if (!self.targetname)
objerror ("monster_movetarget: no targetname");
self.solid = SOLID_TRIGGER;
self.touch = t_movetarget;
setsize (self, '-8 -8 -8', '8 8 8');
};
void() path_corner =
{
movetarget_f();
};
quoted is the path_corner entity. unlike every other entity, path_corner defer's it's setup code in another function.
as i'm passing by, i frown at it, comment out movetarget_f and just paste the code into the path_corner function and grin at my cleverness.
suddenly, none of the path_corners work anymore. so i o_O and put it back the way it was. of course, i'm left with the question of why? it's just an entity with a touch function.
Path_corner
#406 posted by Preach on 2010/09/05 20:11:28
I couldn't reproduce this - the monsters seemed to follow their usual paths when this was the only change made to the vanilla source code. Any chance that something else changed at the same time?
#407 posted by necros on 2010/09/05 20:26:56
well... i dunno but it works now...
new comment:
//deprecated. why was it even like this to begin with? (not deprecated, it stopped working when i moved this down into the path_corner function o_O) un-not-deprecated: it ended up working now. o.o
Hmm
#408 posted by nonentity on 2010/09/19 14:42:31
Just bumping for easier location by new users (coding scares me way to much to be in here for any other reason ;)
Self
#409 posted by necros on 2010/09/22 22:25:51
if you change 'self' in a think function and forget to change it back, what happens? (beyond just the operations in the same think function)
does it mess up the engine's think iteration as it goes through the list of stuff?
what about entity links? can something cause a .entity link to get broken?
i'm having some weird problem with entities randomly getting messed up but it's so random that tracking it down is proving quite annoying.
Selfless
#410 posted by Preach on 2010/09/22 22:42:42
The 'self' that you can access from the qc side is not used (at least in the standard source) in any of the engine code, it always begins with it's own reference to an entity passed as a parameter, and then set in the global_qc_self variable (not it's actual name in the source). So I don't think that could be your problem.
Is it possible that some of the entity links you have run through entities which are removed? The quake engine has a 'lazy remove' paired with a 'thorough spawn' function. Only 5 or 6 entity fields are cleared on removed entities, just enough that they are no longer transmitted to clients. When the entity slot is reused, the spawn builtin goes through and zeroes all of the fields.
Although it makes sense to not go to the trouble of zeroing all of that memory until necessary from a performance point of view, it can make bugs intermittent. If your code relies on a reference to an entity which has been removed, then it will more than likely perform correctly until something uses that entity slot. The trouble is now that the cause of the bug is separated from it's first effect by an unpredictable length of time, making it very hard to diagnose.
#411 posted by necros on 2010/09/23 00:37:22
i use
if (self.someEntityLink)
{
self.someEntityLink.think = SUB_Remove;
self.someEntityLink.nextthink = 0.1;
}
which i felt was pretty safe.
the problem seems to be centered around accelerating movers.
i'm still using helper entities to control velocity but it seems as if after a few minutes a helper will just become removed (when i check the helper's edict it is either free or a new entity).
however, this also happens with a custom lightning entity. the custom lightning entity spawns a chain of models to simulate the lightning effect and cleans them up when the effect is over. somehow that master entity just dies sometimes leaving the models in the game.
both of those entity's think loops seem to be solid so i can only guess something outside of their thinks are killing them.
The Debugging Wrap
#412 posted by Preach on 2010/09/23 11:12:04
You could put a wrapper around the remove function to try and work out exactly what is removing them. In defs.qc rename the builtin definition #15 to
void(entity e) remove_builtin = #15;
You can then define a function called remove which has extra behaviour before calling remove_builtin. I'd probably add a boolean field to the entities you want to monitor.
.float donotremove;
void(entity e) remove =
{
�if(e.donotremove)
�{
��dprint("Entity of class '");
��dprint(e.classname);
��dprint(' was removed!);
�}
�remove_builtin(e);
}
This doesn't give you much debugging information though, it still requires you to guess what just happened. It would be better to get a stack trace, but the only way to get one of those is to crash the map. I'm not sure how much of a stacktrace you get by calling error() or objerror(e). I do know that you'll get one by creating a runaway loop though, so something like:
void(entity e) remove =
{
�if(e.donotremove)
�{
��eprint(e);
��while(0){};
�}
�remove_builtin(e);
}
That ought to give you plenty of information as soon as one of these entities gets removed. Just remember to clear the donotremove flag before actually removing them! Also, it should be obvious that this kind of code shouldn't go in a release build...
Oops
#413 posted by Preach on 2010/09/23 11:13:30
That of course should be while(1) in the code above, so that it loops forwever rather than not at all.
#414 posted by necros on 2010/09/23 23:11:16
that's a great idea, thanks! maybe i should create a wrapper for spawn() so that donotremove is set to true by default, or do the inverse have it as 'safetoremove' defaulting to 0.
anyway, nice idea to abuse the stack trace engine feature. ^_^
it's like teaching progs new tricks but for engines. :P
Donotremoveanything
#415 posted by Preach on 2010/09/23 23:30:58
I was figuring you'd only apply donotremove in the spawn functions of the two entities you were trying to debug, otherwise you've got to worry about your game crashing every time a missile hits a wall and stuff! Wrapping spawn and remove is a really great trick with lots of uses, I'm really grateful to frikbot for showing me the trick of redirecting builtins.
More Weirdness
#416 posted by necros on 2010/09/25 00:42:31
you know how, when you're riding a platform that's moving upward, your viewpoint sort of sinks down a bit?
currently, console prints (like bprints or stuffcmd bf) are causing the view sink effect to reset each time. every time there's a bprint, the view height resets to the standard height and starts to sink again.
i have the feeling i've fucked something up pretty badly. :P
Oh O.o
#417 posted by necros on 2010/09/25 01:21:56
apparently, the bprint thing is happening in stock quake too. this must be some setting in fitzquake because it doesn't happen in aguirre's quake.
will investigate... o.0
Uh Oh...
#418 posted by metlslime on 2010/09/25 02:10:26
#419 posted by necros on 2010/09/25 05:57:50
i'm still unsure exactly what's causing it... if someone wouldn't mind checking this out, an easy way to test this is to bind a key to 'god' and then load up e1m1. hit the button for the first lift and let it lower.
when it starts to raise back up, repeatedly hit the key you bound to god mode. each time the screen should reset to the normal view height before sinking back down.
this happens in fitzquake and quakespasm.
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.
|