|
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. |
|
|
Hey
#135 posted by madfox on 2008/10/15 12:07:39
that's another qup of tea Preach.
I already reminded myself to be glad with a strike of luck and leave it that way.
And yes indeed, the powerups go clearly from 0 to 100. Never thought it was possible.
Thanks!
LIT File Format?
#136 posted by JneeraZ on 2008/10/23 13:44:21
Can someone point me towards what the LIT file format looks like? I've spent 20 minutes Googling with nothing to show for it. Is it documented somewhere?
#137 posted by Spirit on 2008/10/23 16:21:47
According to QIP LordHavoc created the format so just try getting hold of him in #darkplaces on Anynet (IRC). Otherwise you could read through the TomLite or Tyrlite sources (Hmap probably too), you seem to be able to grasp code (unlike me).
I Emailed Him A Couple Of Weeks Ago...
#138 posted by RickyT33 on 2008/10/23 16:57:59
He helped me out! :-)
Willem
#139 posted by Lardarse on 2008/10/23 17:05:45
From dpextensions.qc:
//DP_LITSUPPORT
//idea: LordHavoc
//darkplaces implementation: LordHavoc
//description:
//indicates this engine loads .lit files for any quake1 format .bsp files it loads to enhance maps with colored lighting.
//implementation description: these files begin with the header QLIT followed by version number 1 (as little endian 32bit), the rest of the file is a replacement lightmaps lump, except being 3x as large as the lightmaps lump of the map it matches up with (and yes the between-lightmap padding is expanded 3x to keep this consistent), so the lightmap offset in each surface is simply multiplied by 3 during loading to properly index the lit data, and the lit file is loaded instead of the lightmap lump, other renderer changes are needed to display these of course... see the litsupport.zip sample code (almost a tutorial) at http://icculus.org/twilight/darkplaces for more information.
#140 posted by JneeraZ on 2008/10/23 17:21:47
Excellent! Thanks, that should give me what I need...
Coding Tip Of The Day
#141 posted by Preach on 2008/12/03 01:15:00
Don't expect them daily though, this is just my aggravation of the moment:
if(1)
dprint("1: went down the TRUE branch\n");
else
dprint("1: went down the FALSE branch\n");
This will, as you would expect, go down the TRUE branch. The value in the if() is non-zero, which is true in boolean logic.
if('1 0 0')
dprint("2: went down the TRUE branch\n");
else
dprint("2: went down the FALSE branch\n");
This will also go down the TRUE branch, it looks like any non zero vector counts as true.
if('0 1 0')
dprint("3: went down the TRUE branch\n");
else
dprint("3: went down the FALSE branch\n");
This will go down the FALSE branch! QC only checks the first component of a vector when evaluating boolean logic on them. This is a bit of an oversight, and you should be careful. If you want to properly check if a vector is non-zero, you must do it explicitly as
if(self.angles != '0 0 0')
OK, that's the one that bugged me for tonight, venting over. But while I'm posting about QC and if() logic, here's another related bug that can catch people out:
self.noise = "";
if(self.noise)
dprint("4: went down the TRUE branch\n");
else
dprint("4: went down the FALSE branch\n");
This one goes down the TRUE branch. Why it does is a bit technical, it's because if(self.noise) is checking whether the pointer which self.noise stores is non-zero. The string constant "" is not the same thing as a null pointer, it is a string comprised solely of a null terminator, which actually gets allocated somewhere and so the pointer has a non-zero value.
There are two ways around this. One is to properly null the string pointer, like this:
self.noise = string_null;
if(self.noise)
dprint("5: went down the TRUE branch\n");
else
dprint("5: went down the FALSE branch\n");
This one evaluates to false.
Alternatively you can put
if(self.noise != "")
This will go down the false branch in either of the cases self.noise = ""; or self.noise = string_null.
#142 posted by JneeraZ on 2008/12/03 01:45:54
"This will go down the FALSE branch! QC only checks the first component of a vector when evaluating boolean logic on them."
I'd venture a guess that when it sees a string maybe it's just doing an atoi call on it, which would stop at the first space? I dunno.
Assembling A Vector
#143 posted by Preach on 2008/12/03 11:00:49
Looking at the assembler output, it looks like every time a vector is passed as a parameter to something, the instruction looks like:
STOREP_V VEC_ORIGIN_x, temp_0;
So it seems to be passing just the first component of the vector. What happens then is that the engine knows that this is a vector, and that the other two components will be in the next two entries in memory. Any operation with _V on the end does this.
The problem arises when you get to the IF operations. There isn't a separate case for vector, or indeed for any types. Every memory location which gets passed by the assembler to IF is cast to int, and then checked to see if it's non-zero.
It wouldn't be easy to fix this on the engine side, because you'd need to read what type of temporary was being stored, so that you could distinguish between
if(self.angles)
and
if(self.angles_x)
because the IF operation would look the same. You'd need to look back a few operations at least, which is basically a no-go.
On the other hand, it wouldn't be hard to write a compiler which always substitutes
if(vector != '0 0 0') for if(vector).
FTEQCC already offers a similar fix for
if(string)
It isn't on by default, because some of the engine extensions which add string concatenation etc. require actual tests for null strings instead of empty ones.
Mdl Versus Sprite
#144 posted by madfox on 2008/12/14 12:38:08
Well, I managed to get a sprite in Quake, but I was wondering how to add it to a monster's subroutine.
Simple fact, quake sprites are mostly just one model frame. Except for the orgue which is the only one with his grenade. If I'm looking to the qc I can't find nothing about sprites, so I consume it is engine wise.
When I change the model laser.mdl of the enforcer with a sprite I see only the first frame.
How do I add a sprite to a monster's subroutine?
Is it something you add to the statement of the laser.mdl of the enforcer?
In Hope To Help
#145 posted by meTch on 2008/12/14 17:15:32
void() s_explode1 = [0, s_explode2] {};
void() s_explode2 = [1, s_explode3] {};
void() s_explode3 = [2, s_explode4] {};
void() s_explode4 = [3, s_explode5] {};
void() s_explode5 = [4, s_explode6] {};
void() s_explode6 = [5, SUB_Remove] {};
void() BecomeExplosion =
i think you have to make a multi-image sprite, like the explosion?
and deal it out above like so, and give it setmodel "ursprite.spr"
or umm, heh <8*
Well
#146 posted by madfox on 2008/12/17 01:16:23
For creating a sprite it could work, but not when I try to make it happen in a monster's subroutine like the enforcer.
If I add something at the qc point launchlaser, I first need to declare the sprite frames. And as the enforcer already has it frames declared qc matches out.
Madfox
#147 posted by necros on 2008/12/17 01:54:27
If I add something at the qc point launchlaser, I first need to declare the sprite frames.
no, you do not. like i said before, just put a number where the $frame macro would be.
Is It Still Necessary To Use Quakeworld Progs?
#148 posted by necros on 2008/12/22 20:49:09
are there qw clients that can just read the normal netquake progs?
#149 posted by Spirit on 2008/12/23 10:22:11
zQuake can do, both as client and server (so you can serve a "netquake" progs with zquake and have other qw clients connect to it).
FTE can do too.
ezQuake I am not sure, from what I know the singleplayer is broken.
Zquake Sounds Promising
#150 posted by necros on 2008/12/23 20:07:13
except i have the same problem i have with a lot of other clients with zquake...
the screen is half-filled with giant red pixels (using +gl_clear 1) like someone got decapitated right next to my screen. in other gl engines, like aguire's, the pixels are grey because i set the gl_clear colour to grey.
fuhquake has this problem, but ezquake does not though. (fitzquake doesn't have the problem either).
does anyone know what that's about?
#151 posted by madfox on 2009/01/07 19:44:06
I made a sprite of the Shambler's bold, this in order to use it in a mod for temperary bold flashes.
Now I'm sofar I can import the sprite in Quake.
I need the sprite to turn on and off.
I don't know if it's possible or I'm missing the logic to understand.
I used this code as bold.qc
$frame 0 1 2 3
void() bold_stand1 =[ $0, bold_stand2 ] {};
void() bold_stand2 =[ $1, bold_stand3 ] {};
void() bold_stand3 =[ $2, bold_stand4 ] {};
void() bold_stand4 =[ $3, bold_stand1 ] {};
void() model_bold =
{
if (self.style >= 32)
{
self.use = light_use;
if (self.spawnflags & START_OFF)
lightstyle(self.style, "a");
else
lightstyle(self.style, "m");
}
precache_model ("progs/bo1.spr");
precache_sound ("ambience/buzz1.wav");
self.solid = SOLID_BBOX;
self.movetype = MOVETYPE_NONE;
setmodel (self, "progs/bo1.spr");
setsize (self, '16 16 16', '24 24 24');
self.think = bold_stand1;
self.nextthink = time + 0.1;
ambientsound (self.origin, "ambience/buzz1.wav", 0.5, ATTN_STATIC);
};
Now I have bold sprite that constantly flashes.
I used the selfuse = light_use; to turn it on or off but it don't seem to work.
Is there a way to turn it on or of with a trigger?
Well
#152 posted by madfox on 2009/01/13 23:43:52
the logic is probably it is a static entity that can't be moved because it is a MOVETYPE_NONE
Ohter question: I'm coding LostSoul from Doom to Quake. If I give it the normal routines like stand,walk,pain,die and give it a bite like the dog for attack with self.th.melee
all goes right so, I should be glad I can archve it.
The distance the monster reaches while biting to the player is too wide. I don't know how to make it closer.
Then I decided to try the jump scene of the dog. Adding it to the qc worked, but there are some strange sidekicks.
Because LostSoul is a flying monster this doesn't compare with a walkmonster. The lostsoul make a giant jump, but it wants to land onground. And because it is a flying monster this is strange sight.
The monster bumps undergound, than jumps up 64 units, aims to the player, moves 64 units again and then returns to its jump session.
Also the chance of hitting the player is almost harmfull.
I know this is becuase I switch a flymonster with walkmonster code, but would it be possible?
A lostSoul that excellerates its move in air, without the bounce of a walkmonster.
#153 posted by necros on 2009/01/14 00:11:59
to get a flyer to fly toward the player:
take the origin of the enemy (player)
subtract from monster's origin
normalize vector
set monster's velocity with vector * speed you want it to move at.
local vector vec
vec = normalize(self.enemy.origin - self.origin);
self.velocity = vec * 1000;
you'll need to make a touch function to set self.velocity to 0 otherwise, things will get messed up when the monster tries to move from AI.
Great!
#154 posted by madfox on 2009/01/15 06:47:31
I had to make some prototyping to get my SolJumpTouch run, but now it is a fast Soul!
Thanks!
MDL Question (cross Posted From Inside3D...)
#155 posted by JneeraZ on 2009/01/16 15:25:57
OK, so inside the MDL file format there is support for simple frames and group frames. I'm trying to get it straight in my head which is good for what.
It looks like things like the walltorch use group frames. Is this so the engine can start animating them on a random frame? I don't see anything in the QuakeC that uses this information so it must be engine side.
Am I thinking about this the right way? Do group frames have other uses?
Groupies
#156 posted by Preach on 2009/01/16 19:57:21
Basically a grouped frame is a way to make a looped animation on the client side, so the animation changes frame without any input from the server/qc. The advantages are that it uses no network traffic once it starts, and can be applied to a static entity.
From a QC point of view, the entire framegroup just looks like a single frame. Suppose you had a monster with:
regular frames run1 .... run6
a framegroup [idle1 ... idle40]
more regular frames attack1 .... attack8 etc
Then to get at the run frames you'd set
self.frame = 0...self.frame = 5
To play the idle animation you'd set
self.frame = 6
And to get the attack frames
self.frame = 7...self.frame = 14
One of the disadvantages of this arrangement is that the QC has no way of reading where the animation has reached at a given time. This would make it hard to sync a sound with the animation for example.
Open question here...when you have a QC command like self.frame = 6 on a model with a framegroup at frame 6 and NO random flag set, does that command start the animation from the beginning? I suspect that if the frame was already 6 it wouldn't work, as no network update is sent out for a frame remaining the same. If you could get that to work you could do some nice long idle sequences on a monster using them, without running out of frames for important things
So basically the use of them is to cut down on the amount of QC you need to make a simple looping animation. This is vital for static entities which don't have any qc interaction once created(hence static), and can make other things easier.
Another open question paired with a technical fact...If you poke around in the mdl specs like Willem has been doing, you'll notice framegroups come with a value to control the duration of each frame in the group. From my memory of messing with these thing, I could only ever get it to obey the duration of the first frame in the group, the rest of them just automatically followed that. Is that a long standing bug/just Carmack forgetting to add (frameindex*framesize) to the pointer to retrieve it?
#157 posted by JneeraZ on 2009/01/16 20:54:27
I thought that the animations ran at 10Hz or something and that was that. I know the spec has that array of floats that are claimed to be timings, but nobody ever talks about them so I sort of assumed that they were always set to even intervals or just plain didn't work.
All the fire and stuff in Quake seems to animate at the same speed, at least to the naked eye.
#158 posted by necros on 2009/01/16 21:12:21
i could never get the framegroup animation speed thing to work from within qme3.1 :S
#159 posted by JneeraZ on 2009/01/16 21:17:27
Could someone with engine familiarity confirm or deny if that code works or not? I'll bet Preach is correct that either it's being ignored intentionally or Carmack has a bug in the engine where he doesn't read the values in correctly and never noticed.
|
|
You must be logged in to post in this thread.
|
Website copyright © 2002-2024 John Fitzgibbons. All posts are copyright their respective authors.
|
|