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
 
bad implicit conversions are 'allowed' mostly due to decompilers not being able to determine types properly, and just writing out vec_x as vec instead. such ocde is of course buggy, but should run fine once its recompiled.

c-style casts exist in fteqcc, but are dependant upon opcode extensions or builtins to do the work where the fundamental types are made of different fundamental primitives (ie: floats+vectors are floats, everything else is an int).

qccx-style casts can be achieved with: asm mul_f yoursourcefloat, 1i, yourdestint;
which will rescale your source float and write it as some denormalised float which just happens to match the float's value as an int - so long as its smaller than 1<<23 or whatever it was.
fteqcc does not directly accept (float*1i) because it will convert the int to a float first resulting in no operation, instead of pretending that the int is a float.

note that asm add_f someconststring, 1i, someresult; will return a string omitting the first byte, etc.
hurrah for evil hacks.

ijed, when dealing with angles, I'd be surprised if you could actually get away with comparing exact numbers like that. such things typically need a range tolerance. 
Thanks For The Detail 
It clarifies things for my non-coder mind.

Apples and oranges - got it :)

I'm compiling with fteqcc.

I've got it working now doing the direct comparisons - they've done the trick since I'm looking at a static object placed by the mapper.

A range would be more elegant, but the primitive nature of the mapobjects involved means they should only be rotated 90 degrees anyway - they usually have one or more surfaces that can should be flush to a wall.

And a 45 degree rotation would make baby jesus be shot full of nails ie. cry. 
Jump Tables 
Spike: while you're hear sharing all kinds of wisdom about hacky things involving ints, I've got a question about them.

Is it possible to have a non-constant jump instruction in QC? If that were possible you could create a proper c++ style vtable - have a function which takes a parameter, pass specially designed integer constants for that parameter, and use them to jump to a function call for the "virtual" function the parameter designates. I tried messing around with the asm stuff but the compiler interpreted the variable as a goto label instead. Is this a compiler limitation or something completely impossible in QC? 
 
there's no such thing as jumptables in QC.
op_if_i, op_ifnot_i, op_goto all take constants only, the offset is directly encoded into the instruction.
on the other hand, op_call* takes a function variable (an index/int).

if you pass a function as an argument, you can theoretically add_f to it to move it on to the next function body defined in the source code, but that's evil.
yeah, a proper c++ style vtable could theoretically be achieved by storing the first function and add_fing an offset to get an indexed function by name... but frankly, I'd just go with fields for them, less hacky then. fteqcc's class stuff already does that, of course. 
Switching Plans 
op_if_i, op_ifnot_i, op_goto all take constants only, the offset is directly encoded into the instruction.

Yeah, this is what scuppers my plan. I basically just wanted a "switch" statement where each "case" calls a virtual function then returns. I think the easiest way to do it now is just use fteqcc arrays, have an array of function pointers, and select/execute the function using an index - which is a bit slower but doesn't need any integer tricks. By having multiple arrays with the same layout for corresponding functions it should be possible to switch between sets. 
 
struct
{
float(float a) func1;
vector() func2;
float() func3;
} vtable[] =
{
{
class1_func1,
class1_func2,
class1_func3
},
{etc2}, {etc3}, {etc4},
{
class5_func1,
class5_func2,
class5_func3
}
};

idx = bound(0, idx, sizeof(vtable)/sizeof(vtable[0]));
vtable[idx].func1(3);

can do different args that way. all functions from a single class form part of a single struct. 
Quakespy 5.3 (1997) 
Hi - Didnt know where else to post this here on the site, but was wondering does any one have an old key or registration for the original Quakespy? Not Gamespy, but just Quakespy. I have asked Gamespy if they would release the old src to the public but never got an answer.... 
A Random Article 
It was nice to get so much positive feedback for the ogre article, I'll try and do more like it in the future. I think it was helped by being reasonably timely about an interesting open problem - so keep generating those kinds of ideas for me to tackle :-p

Today I'm polishing up an article I started in October, and it's on the maths-heavy side. In UK secondary schools you typically take one of two routes when studying Maths to age 18. Some students take on modules in Mechanics, and they would be well placed to tackle the grenade article from last time. The other route is Statistics, and so here's an article for them instead!

http://tomeofpreach.wordpress.com/2014/01/23/removing-busy-random-polling/

I've tried to push the heavy maths parts onto links again, but I do spend some time in the middle justifying the core idea. It's an older article and I spent too long on the graphs to delete them, so just feel free to skip that chunk. Also if you get the feeling at the start that this is unnecessary optimisation, make sure you catch the better reasons to do it near the end! 
High Plane Maths 
I am not really sure how I can use this for anything, I don't have any functions that do what you are optimizing. Sorry, this article feels too abstract and more for you than anyone else.

If you want ideas for future code articles what about, creating ladders, tracking missiles (quoth rocket guy), vertical movement code (quoth bob), or improving the fiend jumping mechanic. 
How About Enemies 
That are set up with proper pathing? Like in unreal? 
Pathfinding 
you'd need to write an a-star algorithm in QC and lay down a veritable shitbiscuit of triggers to acts as nodes.

It's not a great language to do that in tbh but i think it's been done in the past. 
Why Not Use Path Corner? 
Wouldn't that work? 
FBX Waypoints 
 
The Point Is 
you need to write the underlying system that dynamically creates the sequence of path-corners the monster needs to follow to get from where he is to his goal. 
Lost In Translation 
when i said "trigger" i meant whatever entity you create to represent your a-star node. 
AI Pathing 
It's not a great language to do that in tbh but i think it's been done in the past.
Did you play my ITS mod? I wrote an Article on what AI system I wrote in QC and how it works, ingame/editor shots as well! 
That's Pretty Cool, Yeah 
I was talking more about this stuff: http://en.wikipedia.org/wiki/A*_search_algorithm

Your system looks pretty hand-placed but if it works for basic quakery, then it's all good :} 
Different Strokes 
Necros did a similar system with nodes, generating best paths from node networks and then setting the AI on that path. The problem with that system is, it can be CPU intense to generate the path every time (especially vertical complex levels) and if anything changes (player / environment) it becomes out of date quickly.

I personally elected for a dynamic system, the AI knows where it wants to go (final objective) but trusts the node network to reach there. The AI find the nearest node, finds the best direction and then starts following the network.

As the final destination (player) keeps moving the AI keeps adapting using the node network. The minor navigation (around rooms) is left to the node network while the high level signposts stuff is done via volume brushes.

Its not perfect but it does cope with fairly well with moving objectives (player) and even gets the AI back to what they were doing before.

The downside is the node network has to be hand placed and the network has to be validated / connected together when the map loads. 
Repost 
This is an interesting read on making a dynamic system that follows simple empirical rules.

https://www.quaddicted.com/webarchive/minion.planetquake.gamespy.com/tutorial/main.htm 
Btw 
A word about A* pathfinding being cpu-intensive... I've coded a couple of A* systems for games in the past, and if you can create a sort of heirarchical A*, it's incredibly fast (basically you do pathfinding on a heirarchy of graphs, starting from the coarsest and working down - e.g. "region nodes", then "room nodes", then "nav-tri nodes")

e.g. once you get down to the point where you need a path between individual navtris, you only have to find a navtri path between nodes on the next graph up (e.g. just between adjacent room nodes)

This already makes it blazingly fast, but you can still get spikes if you need lots of paths all at once (e.g. lots of monsters all going at it) - I handle this by amortising the algorithm over several frames and also queueing up requests, so they are processed for each monster in a linear fashion. The upshot of it all is basically no performance impact whatsoever.

The creatures have simple fallback behaviours that they can do whilst waiting for their paths to be processed, but I find the delay is so small it's never noticeable.

But, yeah I wouldn't wanna do it in QC... 
Sounds Like 
Navmesh. I haven't personally implemented this before, but have worked with it quite a bit.

As I've seen it throws voxels at a map and creates polys where possible. The quake equivalent tech is probably the vis process, with leafs instead of polys.

Ai navigates between the polys, path finding to their ideal destination.

Incredibly slick system, works amazingly well. They used a terribly shitty version of this in L4D... We analyzed it and it was puzzling why it was so bad, when we stole ours from an online tutorial and it worked like a charm.

I suppose they were worried about more important things though, like not making a game that sucked. Our game sucked, but I'm not going to say which it was since it got universally panned.

All this makes me wonder if a similar approach could be applied to the vis data though, using ray casts or something to construct chains. Wouldn't work for areas that monsters can't navigate though, like vertical drops and the like.

Detail brushes would also cause problems. 
It's A Navmesh System Yes 
Also you make an interesting point with vis connectivity.

One thing I've been meaning to do is dig around to see how the doom3 AAS is generated - that's another system where the graph is created procedurally with almost no work from the designer required... 
 
I handle this by amortising the algorithm over several frames and also queueing up requests, so they are processed for each monster in a linear fashion. The upshot of it all is basically no performance impact whatsoever.

I've had to do this as well; ne_ruins didn't have it though.

Deferring the path solution over multiple frames works very well and I remember testing giant horde maps with a hundred monsters all able to path without any slowdown at all. The only downside is that the more monsters there are, the longer it can take for each AI to have it's turn at getting a path generated for it.

The last optimization that I have yet to implement is having a monster save a generated path.
As it is now, I regen a path every time an AI hits the node it was heading towards. This is pretty expensive, especially in node-dense areas. If an AI could get a path generated and remember not just the next node, but all the nodes that make up that path, it could treat it's A* path like a series of path_corners and be very cheap to run. 
 
But, yeah I wouldn't wanna do it in QC...

In hindsight it was a crazy idea, but I did learn a load of things about AI. When I finally got the Quake monsters to path around a map avoiding obstacles and hunting the player it was an awesome feeling of accomplishment.

I did look at necros QC but soon realized I was going to struggle with the idea, I am designer not a coder. In the end I decided to go with a simple path node system (like in heretic2) with some extra helper options (jump, shoot, path choice) so that the AI can look intelligent when the player is around. I even wrote a ton of debug modes for tracking down errors in the pathing routines so it was easy to find out where things were going wrong. 
When I Saw ITS 
I assumed you'd used the frikbot code, since the behavior was so similar in many respects.

One rainy day I'll dive into that and see how to link it into the monster ai.

It almost never rains in Chile. There are more earthquakes than storms. 
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.