|
QuakeC Question
#6969 posted by JneeraZ on 2008/02/14 15:48:16
So I'm hacking around with some stuff and have a question. I know QuakeC isn't object oriented so you can't call methods within entities but at the same ... man, that would be handy.
I find myself setting up stuff like changing an entities think function to point to a function where I can do something to the entity and then it changes it back to it's regular think. This works but it feels ... hacky and smells bad.
Is there a more elegant way to call functions on an entity that you've just spawned (for example) than this, or is this the only way and I'm wasting time benig annoying about it?
For example, say I have an entity that spawns a monster_army. I then want to call a function on that entity. This is how I currently do it:
myentity = spawn();
myentity.think = monster_army_myinitfunction;
myentity.nextthink = time + 0.01;
And then monster_army_myinitfunction will get called next frame. Which works. But it smells bad. Is there a better way?
Yeah
#6970 posted by Preach on 2008/02/14 16:57:47
Would something along the lines of this do the job?
local entity temp_self
myentity = spawn();
temp_self = self;
monster_army_myinitfunction();
self = temp_self;
#6971 posted by JneeraZ on 2008/02/14 17:03:53
Interesting. I assume you left out a "self = myentity;" line though, right?
Thanks Everyone!
#6972 posted by FaTbOy! on 2008/02/14 18:06:27
I looked around Shub-hub yesterday but I missed those files. Lunch hour rush I 'spose...
Anyone have a clue why the doors in my map arent playing their sounds at full volume? Im using BSP v 96d, and Im running Fitzquake080. No matter what sounds I assign it it is barely audible. Other sounds like jumping & weapons fire are fine.
Arrgh, Yeah
#6973 posted by Preach on 2008/02/14 18:06:30
Yeah, I did.
If this initialisation function never needs to be run as a think function, then the alternative is to pass the spawned entity as a parameter to the monster_army_myinitfunction().
How that would go is you'd change the definition of that function to
void(entity grunt) monster_army_myinitfunction =
{
...
};
Then replace all instances of self in that function with grunt.
You'd then make your calling code look like:
myentity = spawn();
monster_army_myinitfunction (myentity);
As I mentioned above, the problem with this is that you can't then have monster_army_myinitfunction as a .think or .use function. If you like the suggestion in this post, it's cleaner code to my eyes, but you do need it as a .think at some point, then there is a way round that. Simply define another function like so:
void() monster_army_myinitfunction_self =
{
monster_army_myinitfunction(self);
}
and use that function as the think. The most frequently used example of this idea in the quakec code is SUB_Remove, which simply calls the function "remove" on the entity "self", making it possible for entities to remove themselves with use and think functions.
#6974 posted by JneeraZ on 2008/02/14 18:20:54
Thanks Preach! It never even occured to me that "self" would be writable. Learn something new every day!
I'll give this all a shot tonight...
#6975 posted by JneeraZ on 2008/02/14 22:34:05
As a follow up, what options do I have for doing HUD stuff in QuakeC on vanilla Quake 1?
Can I do anything at all? Even some text strings would be helpful.
Not Really
#6976 posted by Preach on 2008/02/14 22:42:39
You're pretty limited. Your options for writing text strings are to centerprint them or bprint them. There are complicated ways of hijacking centerprint so that you can use some space for your own message, and still use the rest of the space for normal centerprints, but it's a pain to do in technical terms.
If you just need a few more weapon/powerup icons, you might consider using the -hipnotic or -rogue options, which are supported in all engines. The best way to see what extra icons they allow you is to just play about in either mission pack and see what new icons are added. Rogue adds more, but they're more complicated to actually use well. Also, both options will probably require you to rewrite some qc code just to make things look normal again. But since you're gonna mess with it to add your icons anyway, it's not that bad.
Oh
#6977 posted by Preach on 2008/02/14 22:43:22
...and if the inside3d folks start going on about csqc stay well away.
#6978 posted by JneeraZ on 2008/02/14 22:57:12
Heh, OK, noted.
That's why I was careful to specify vanilla Quake 1 so they wouldn't do that. We'll see.
Bummer about the HUD though. Oh well.
Skeletal Animation In Quake.
#6979 posted by Voultar on 2008/02/15 02:05:33
It can be done, with relative ease. Why haven't we seen it yet? The world may never know..
Well...
#6980 posted by metlslime on 2008/02/15 08:41:48
All we need is an engine that supports it, a file format that implements it, and a modelling program that exports it.
Actually, this sounds like the sort of thing Darkplaces would support (it loads a lot of half-life, quake3, etc. formats.)
Random Squishing
#6981 posted by negke on 2008/02/15 10:22:24
What is it that the player sometimes seems to block a lift/door/train for no apparent reason (no obstacle in the way)? In most cases the engine only reports an 'unstuck' message, but sometimes it's more severe and the player's health is drained rapidly or he dies if the func's dmg value is high enough. This keeps happening even if all surrounding geometry is clipped off.
Wouldnt It Make Animation A Lot Easier?
#6982 posted by RickyT33 on 2008/02/15 10:25:13
I mean I never tried modeling (knew from the start I was too ugly man), but you have to sculpt each frame individually dont you? Whereas skeletal animation - your just saying where each 'bone' is going. Wouldnt that make creature creation easier and faster? (Not really for Quake purists though)
Neg
#6983 posted by RickyT33 on 2008/02/15 10:29:12
Erm, I played a level called The Harb!ngeR of Fish's 'Assault' level collection. Or assault.zip to every other Quaker. It is quite creative with func_trains, and there's a shuttle which you have to climb in. You always get gibbed in that! I died about 10 times, without doing anything! Eventually it crash landed as planned and I survived though....
Skeletal Animation
#6984 posted by Preach on 2008/02/15 11:07:24
Darkplaces supports it's own file format called dpm, which uses skeletal animation. Models for this format are compiled from smd files, the same ones that are used to create HL1 models. There are ways to create these files from max, gmax, milkshape and probably many other programs.
The reason why it's not widely used is that at the moment there's no way to control individual bones, all you can do with the bone information is read the orientations of the bones. That's useful for, say, attaching weapon models to the players hand, but little else. The plan as I understand it is to get csqc working first, then you will be able to blend animations/rotate bones manually. Of course, that means we could still be years away from it becoming useful.
Even if you aren't using a skeletal format, it's still possible to use bones in the creation process, it's the easiest way to make animations. You just calculate the position of each vertex per frame when it's time to export the model and ignore the bones themselves. Hopefully nobody sculpts each frame by hand in anything complicated.
?
#6985 posted by ijed on 2008/02/15 13:22:16
When you're talking about a game as old as this it doesn't really matter if it supports bones or not, most modern games only have limited bone support, because as an animation system its excellent but for a programming system to understand it is a ballache.
The only game I remember as using bones well was Undying.
Don't ask me about 'joints' fucking stupid crap.
Any animator with the right mix of sense / laziness / psychosis making a creature for Quake is going to do it in their favourite 3d package then export it frame by frame.
My animation is bad, but I remember suffering over cell animation for weeks in uni; anyone who enjoys putting themselves through that kind of thing isn't going to be bothered by doing a few extra exports, at least one of which needs to be done anyway.
Whats That Thing "motion Capture"?
#6986 posted by RickyT33 on 2008/02/15 14:47:25
Where you stick rubber balls with sensors in on specific places on your body, and then carry out movements with a sensor picking up where the balls are moving, and then use that data to create the animation?
Hehe, thats got to be quicker than frame-by-frame animation!!
I wander how many thousands of pounds it costs for that sort of rig? :P
Kinda loose that whole hobbyists charm aspect aswell.... dontyouthink?
#6987 posted by JneeraZ on 2008/02/15 15:37:44
OK, I'm trying to spawn monsters by hand and having a hard time. I can get them into the world at the location/rotation that I want but I can't seem to activate them (aka make them hostile towards the player) without them doing bizarro stuff.
I do something like this:
local entity SS;
SS = self;
self = spawn();
monster_army();
self.origin = origin_i_want;
self.angles = angles_i_want;
self.fixangle = TRUE;
monster_use();
self = SS;
This is not my exact code, but close enough. The problem that I'm having is the "monster_use" function. This makes them hostile towards me, but they don't turn to look at me and I can't hurt them (bullets hit them but don't hurt them). If I don't call "monster_use", everything is fine except that I have to shoot them to get them angry.
Does this ring a bell for anyone or do I need to slog through this over the weekend?
Intiialisation
#6988 posted by Preach on 2008/02/15 16:08:56
You've fallen afoul of one of the most common problems with spawning monsters, although in one of the most damaging ways I've ever seen :-).
The key to this problem lies at the bottom of the function monster_army, where it calls
walkmonster_start ();
There is a second function called walkmonster_start_go() in monsters.qc, which fixes all of the problems you are having with your monster, giving them a turning speed and making them damagable for instance. What walkmonster_start () does is sets walkmonster_start_go() as the think function for the monster in question, to be carried out some short time in the future. This delay is put in so that not all the monsters start at the same time, which makes the first frame much less demanding.
Normally when you spawn monsters like this, you end up with monsters that are undamageable for a fraction of a second, before walkmonster_start_go() kicks in and they start up. However, this minor glitch that only really affects nitpickers and telefrags is then compounded by the second thing you do.
monster_use() wakes the monster up, but in doing so it also changes its think function to the first frame of its running behaviour. This of course overwrites the previous think function of walkmonster_start_go(), and so the monster is never properly initialised.
So how do you fix it? It's luckily nice and simple. Add a call to walkmonster_start_go() right after your call to monster_army().
This skips the delay, but that's fine because the world is already spawned so there should be no problems with running both functions back to back. Then the monster_use() (probably) overwrites the call to walkmonster_start_go(). I say probably, because it's possible that the monster won't be woken up, if they have a ring of shadows or notarget on. You might want to call self.th_stand() before the call to monster_use, so that they behave straight away if the player is hidden. They will behave after the walkmonster_start_go() call anyway, but this is a little quicker and avoids going through that twice.
#6989 posted by JneeraZ on 2008/02/15 16:19:54
THANK YOU! :) You've been invaluable, Preach. I'll give this a try tonight.
"You've fallen afoul of one of the most common problems with spawning monsters, although in one of the most damaging ways I've ever seen :-)."
When I go down, I go down hard. Heh.
Skeletal Animation....
#6990 posted by metlslime on 2008/02/15 22:13:03
Of course, professional game animators use skeletal animation to create their work regardless of whether the game itself supports it. And even qME has some half-assed bone system which you can use to animate before exporting to the skeleton-free mdl format.
But a lot of modern games DO support it, and there are two main benefits --
1. reduced disk space usage. Skeletal animation can be seen as a type of compression since there are many more verts than bones on most models.
2. adding/combining animations. Games with skeletal animation can add multiple animations together, such as a walking animation that only affects the legs, and a shooting/gesturing animation that only affects the upper body.
Fun fact: the Medal of Honor:Allied Assault human skeleton only had individual bones for thumb and index finger, and the last three fingers had to share bones. So the characters could point, make a fist, and hold a gun, but could not spread their fingers apart, count from 1 to 5, or do other useful gestures.
Fused Hands
#6991 posted by Preach on 2008/02/16 03:43:03
The wonderful low poly TF2 models found at
http://boards.polycount.net/showflat.php?Cat=0&Number=261922&page=0&fpart=1&vc=1
use a similar idea, this time only modelling the thumb and forefinger separately, while combining the three lower fingers into a single polygon to keep the counts low. This is mainly an excuse to share the joy of these models with the rest of the folks here, they are pretty cool though.
More QuakeC
#6992 posted by JneeraZ on 2008/02/16 12:16:31
OK, so let's say I put this into defs.qc:
.float blargh;
Then, in ToeTag, I add a key "blargh=666" to an entity. Then I add a "dprint( ftos(blargh) );" to the spawn function of that entity.
I would think that 666 would find it's way into the blargh variable - right? Instead, Quake prints "0" in the console. What's up with that?
Almost
#6993 posted by Preach on 2008/02/16 12:30:51
Change it to
dprint( ftos(self.blargh) );
The key values are added as fields of that entity, which self points to during spawn functions.
You might also fall victim to some of the limitations of early qc compilers here. It used to be the case that you needed to do
local string debug;
debug = ftos(self.blargh);
dprint(debug);
dprint("\n"); //add a newline too
fteqcc and probably frikqcc add these temporary variables in for you, so there's no need to worry about it.
|
|
You must be logged in to post in this thread.
|
Website copyright © 2002-2024 John Fitzgibbons. All posts are copyright their respective authors.
|
|