|
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. |
|
|
I'm
#122 posted by ijed on 2008/10/11 20:37:40
Used to engine side vertex interpolation so don't usually notice it so much, except when looking at the models in raw state, as it were.
Swung
#123 posted by madfox on 2008/10/11 21:27:50
custents support the func_rotation and the func_rotate_train.
I'm trying to understand these options to get a better flyer.
that strange swing don't seem related to the func triggers.
Haven't found out where it comes from.
Reason that in custents a part of the func_rotate is hided.
Armor
#124 posted by madfox on 2008/10/14 10:35:53
I succeeded to create a health bowl and give it a health strength , by adding a health function in the qc.
I thought giving it armor points would be that easy. But it isn't.
There are only three IT_ARMOR types.
By substituring one I get my extra powerup object of ten armor points.
But not as alike the health paks I can only take one at the time,
the rest stays non solid as if I have taken a full armor .
To Clarify
#125 posted by Preach on 2008/10/14 12:49:50
I want to check what you're trying to do here. You would like an item which gives a boost of, 10 points of armour to a player who picks it up. So far, you've managed to make an item which gives the player 10 points of armour if they pick one up, but then subsequent ones will only top the player back up to 10, and if they are already at 10, then it doesn't increase.
To me, that sounds exactly like what would happen if you rewrote the green armour to have 10 armour points rather that 100. Have I read your aim and current result right?
Yes
#126 posted by madfox on 2008/10/14 12:59:29
I trie to reproduce the armor powerup with skulls, like in Doom
Items
#127 posted by madfox on 2008/10/14 13:05:41
I was rewriting in the items.qc
+---------------------------------------------+
void() armor_touch =
{
local float type, value, bit;
if (other.health <= 0)
return;
if (other.classname != "player")
return;
if (self.classname == "item_armor1")
{
type = 0.3;
value = 100;
bit = IT_ARMOR1;
}
if (self.classname == "item_armor2")
{
type = 0.6;
value = 150;
bit = IT_ARMOR2;
}
if (self.classname == "item_armorInv")
{
type = 0.8;
value = 200;
bit = IT_ARMOR3;
}
if (self.classname == "item_skull")
{
type = 0.1;
value = 10;
bit = IT_ARMOR1;
}
if (other.armortype*other.armorvalue >= type*value)
return;
+-------------------------------------------+
};
void() item_skull =
{
self.touch = armor_touch;
precache_model ("maps/skull.bsp");
setmodel (self, "maps/skull.bsp");
self.skin = 0;
setsize (self, '-16 -16 0', '16 16 56');
StartItem ();
};
+---------------------------------------------+
It's The Last 2 Lines
#128 posted by Lunaran on 2008/10/14 15:35:18
they skip the pickup entirely if the armor you're touching is weaker than what you have. you need to add a special exception there for skulls that add 10 armor and keep the preexisting armortype.
Additionally
#129 posted by Lardarse on 2008/10/14 15:52:25
You should check for the player having no armor, and if this is the case, set their armortype to green (0.3 and IT_ARMOR1)
You may also want to set a limit for both health and armor shards. Probably at 250 or soemthing like that. I don;t know if the 3 numbers at the bottom are limited to 8 bits, but even if they're not, you might want to not let them get out of hand...
Addition
#130 posted by Preach on 2008/10/14 17:54:08
There's another problem with this code, which is the way armour and health packs differ in increasing stats. A health pack adds on a certain amount of health to the amount you started with. Armour always sets the value to the same amount, regardless of how much you had, it's not adding anything on. Code like "add on 150 points to his armour, but then if the total is more than 150, cap it there" would be redundant.
So you're going to have to write something more complicated.
This
#131 posted by ijed on 2008/10/14 19:41:56
http://qexpo.tastyspleen.net/booth.php?id=131&page=273
Might help some, it's Dr Shadowborg's revised health system tutorial.
Thanks For Your Explain
#132 posted by madfox on 2008/10/14 23:46:40
I'm no coder, so the fact I get any outcome is a wonder to me.
With health it was easy, adding a new b_model with args and the code run.
With this armor code I can let the strength deplenish untill it reaches under 10 before it powers up.
But I can change to any value, only 10 counts.
Eventually I can understand the options you mention,
but I miss the ability to write them down.
Adding New Weapons
#133 posted by Killa on 2008/10/15 10:54:58
hey, was wanting to know if you guys knew of a good and easily understood tutorial for adding a new weapon, that also shows me how to add it to where its usable when added to a FGD "not just when you have a shot gun and enough ammo -.-)
Ok, More Detailed Explanation
#134 posted by Preach on 2008/10/15 11:07:41
I think the best way to do it would be to write an entirely separate touch function for your new item. It needs to:
* Do the usual checks that the other entity is a player who is not dead.
* Deal with the 4 cases: player has red/yellow/green/no armour.
* Add the correct amount to the armour total.
I'd do something like this:
void() armorboost_touch =
{
local float maxarmor;
if (other.health <= 0)
return;
if (other.classname != "player")
return; //usual checks
if(other.items & IT_ARMOR3) //Player has red armor
maxarmor = 200;
else if (other.items & IT_ARMOR2) //Yellow
maxarmor = 150;
else //deal with green and none at same time
{
other.armortype = 0.3;
other.items = other.items | IT_ARMOR1;
maxarmor = 100;
}
other.armorvalue = other.armorvalue + 10; //add it on
if(other.armorvalue > maxarmor)//if we're over max
other.armorvalue = maxarmor;//set to max
self.solid = SOLID_NOT;
self.model = string_null;
if (deathmatch == 1)
self.nextthink = time + 20;
self.think = SUB_regen;
sprint(other, "You got armor\n");
sound(other, CHAN_ITEM, "items/armor1.wav", 1, ATTN_NORM);
stuffcmd (other, "bf\n");
activator = other;
SUB_UseTargets();//fire all targets/killtargets
};
I've not tested it in game, but it should work well enough. Remember to change the line in item_skull to
self.touch = armorboost_touch;
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.
|
|
You must be logged in to post in this thread.
|
Website copyright © 2002-2024 John Fitzgibbons. All posts are copyright their respective authors.
|
|