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
Ffs Don't Crosspost 
 
 
there's 2 ways to create reskin monsters.

1. Create all new .qc files for each reskin, using the same frame macros but renaming the function names (so they don't conflict at compile time).

2. Integrate all the types of monsters into the same original monster code so that at key points in the code, it checks to see what type of reskin it is and then behave different accordingly.

method 1 is the easiest to understand and and read because everything is seperated into individual files. the monsters will adhere to the standard monster coding setups.
method 2 is the easiest to code because you don't have to rewrite anything and just add in little snippets for things like different attacks or a different ai_run routine.

also of note, a lot of the behaviour is controlled by the checkattack function, so simply having a seperate one of those can help distinguish between reskins.

if you're planning on doing this much coding, you should probably check out inside3d. they are more focused on coding while this board is more focused on mapping. 
 
re 460: clairvoyant? o.0 
Oh Nm 
i see what you meant now.

also: http://www.youtube.com/watch?v=21D-21MLrAE

not sure what those 'shivers' are... i can't only guess it is a symptom of irregular framerate. a momentary dip would cause it, i suppose, although i thought i fixed that. :P

also, i obviously need to find some way of adding in damping of some sort because those things will bounce around for ever. 
Lost Chapters Src 
Does anyone have/have a link to the lost chapters src from qexpo? http://qexpo.quakedev.com/booths.php?tag=necros doesn't go to the page. I've seen it linked somewhere here, just can't find it.. 
 
Ty 
 
 
http://necros.quaddicted.com/temp/qcgui1.jpg

another program with debatable usefulness. :P 
 
is it possible to determine if the player is inside a triangular space with just the info of the 3 vertices and discounting vertical axis with QC?

making a monster that traps the player inside a triangular area but it would be awesome if the monster could tell if you were actually trapped (inside) or not. 
 
god damn it...
as usual, after thinking about it for a few minutes, i figure it out a few seconds after posting.

i can just use the dot product of normalized vectors from the origin vertex.

we need a delete button. :P 
Rapid Fire Round 
Ok, I've got an idea to share with y'all about making QC events that happen at high frequencies cope with the framerate dropping below that frequency. But in order to make it a bit different, I'm going to set a bit of a puzzle about it first, which comes as a piece of code and three questions:

void() generic_think =
{
���// do some kind of thing which needs to
���// occur rapidly

���self.nextthink = self.nextthink + 0.05;
���self.think = generic_think;
���if(self.nextthink <= time)
������self.think();
}


� For partial credit, what is this code trying to do?
� For full credit, why will it fail?
� For extra credit, what can we do to fix it? 
 
it looks like you're trying to get the think function to recursively take care of missed thinks.

i've never thought of doing it this way. usually, if i have a think function that needs to be accurate across inaccurate think times, i just use something like this:

void() thinkfunction =
{
����fraction = (time - self.ltime) / 0.05;
����self.ltime = time;

����self.nextthink = time + 0.05;
����self.think = thinkfunction;

}

and just scale whatever it is i'm doing with fraction.

doing it recursively would be easier to code, i guess, but i would think much more expensive on operations. 
Tail Recursion After This Message... 
That's exactly the point of the code, so here's what goes wrong with it:

The assumptions behind this bit of the code are that the QC global time stores the current server time, and self.nextthink stores the time we wanted the think to occur. One of these things is often not the case, and the other is always incorrect.

If you run a dprint on self.nextthink during a think function (but not an animated think function) you will find that nextthink is equal to 0! It's always reset by the engine, so that unless you explicitly call for a new nextthink, the engine can skip over thinking. Conversely, nothing happens to the think field when you run a think function, so if you're optimising QC code for a looping think function, you can remove the bit where you reset self.think in each call safely.

So that's the assumption that's always wrong, that the nextthink time you originally set is preserved in that variable when the think function eventually runs. But is the information lost forever? Not always! The QC variable time is set to either the current server time, or the actual nextthink time which WAS set - whichever is the largest. So as long as you don't ever set nextthink to be smaller than the server time + frametime (which calculates the server time for the NEXT frame), you get the information back.

Luckily never doing that is the point of this whole missed-think-avoidance code. All we need now is to find out the true server time during our think. This is easy though, as we just create a new global called servertime. We then use StartFrame to set servertime = time, and then refer to that in our calculation.

Our code then looks like:

void() generic_think =
{
���//do stuff
���self.nextthink = time + 0.05;
���if (self.nextthink < servertime + frametime)
������self.think();
}

As a closing remark, this function has tail recursion, so you don't actually have to fill up the callstack repeating it over and again. Just wrap it in a do...while loop for performance.

And there we go, a way to ensure that a given function executes 100 times in a second, regardless of the framerate of the server. 
 
clever! :) i had no idea about time being set to nextthink.

also, you could just make a new .nextthink2 var:
self.nextthink = self.nextthink2 + 0.05;
this neatly avoids the engine resetting nextthink. 
Help With Those Damn .lmp Files ! 
Hi,

how can I modify those .lmp files included in id/paks ?
my goal is to have a new hud for my mod (at least change color and quake guy face !) 
 
adquedit can import bmp and pcx (i think?) and convert them to lmp. 
Lmp2pcx 
Or is it pcx2lump..i have one of them on my laptop, i can see if i can dig it up. 
QuakeC Source Code Licensing Status 
So what's the licensing status of the quakec source code? I was planning on releasing the rubicon 2 source, but not sure what license i can put on it (e.g. GPL)

I know that the original source release was sort of an informal "you can make quake mods with it" type license, but not sure if there was a more recent GPL release of the same code. And whether it applies to hipnotic code as well (since i'm using the hipnotic rotating code.) 
Useless Qc Observation Of The Day 
It turns out that the builtins floor, ceil and rint are not as efficient as abusing the bitwise functions.

So if you're optimising a tight loop with a call to floor(x) you can instead substitute:(x | x) which does the same thing. Similarly ceil(x) can be replaced by ((x | x) + 1). rint(x) is a little more complicated to replace, it takes two statements:

x = x + 0.5;
(x | x);//is now the same as rint(x) before the first line

Note that you can't make a helper function like

float(float x) rint2 =
{
�x = x + 0.5;
�return x | x;
}

- because the efficiency saving arises from avoiding the function call overhead, and you waste that by making it a function instead. Also, reducing the number of instructions is only really worthwhile in a tight loop that might trip the runaway-loop counter. Hence this being the useless qc observation of the day... 
Except That 
((x | x) + 1) is incorrect for ceil() as if x==floor(x) then you get a number that's 1 higher. 
True Dat. 
 
Man 
i didn't understand any of that. :(

what is |? i only know it's the bitwise add operator. never heard of using it with normal numbers. 
| Is Bitwise OR 
However, since it can only work with integers, it floors each number before doing the OR. 
Doh 
Yeah, I completely fluffed that one. I guess you'd need to do something along the lines of

temp = (x|x)
(temp != x) + temp;//this ACTUALLY evaluates to ceil x

Some lovely abuse of the boolean to float conversion there. I'm not sure if that's still fewer instructions than the call to ceil though... 
More Negatives 
The "better" version of ceil still doesn't work for negative numbers, and you might not get the same results as you expect for negative numbers using the rint substitute either. So they're both limited in scope. The floor one works well though, since it does the least work... 
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.