is there a way to do location specific damage in QC?

Discuss programming in the QuakeC language.
Error
InsideQC Staff
Posts: 865
Joined: Fri Nov 05, 2004 5:15 am
Location: VA, USA
Contact:

Post by Error »

Darkplaces can do per-poly collision... at least using SOLID_CORPSE.
Urre
Posts: 1109
Joined: Fri Nov 05, 2004 2:36 am
Location: Moon
Contact:

Post by Urre »

It can do per-poly collisions on all solids which tracelines can hit, IE not SOLID_NOT and SOLID_TRIGGER. If you're using this, I'd recommend having a separate entity representing the agent model, with a larger bounding-box than the physical agent and something like SOLID_CORPSE on so you can't run into it, which follows the agent around using MOVETYPE_FOLLOW or whatever you feel like using. This is because limbs and such often poke outside the regular bounding-box which is used for world-collisions and such, meaning those limbs won't be hit with your per-poly tracelines. DP uses the entitys bounding-box as a way to cull the collisions. Might not be noticeable in most cases, but is important if you're doing something like Dead Space where you shoot off limbs and such.
I was once a Quake modder
GiffE
Posts: 170
Joined: Sun Oct 08, 2006 3:39 pm
Location: USA, CT
Contact:

Post by GiffE »

Urre, so if I got this clear, when using SOLID_CORPSE (as I use this for my players) tracelines will collide per-poly? And the bbox is only used for world collisions?
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Post by Spike »

There's a MOVE_HITMODEL flag on traceline/tracebox. Its that that will make it per-poly.

However it'll only collide against polys within the normal bounding box (so MOVE_HITMODEL will _always_ hit less often).
If you have a limb sticking out of the regular bounding box, and you 'hit' that limb, if you didn't also hit the bounding box it won't even check the limb, it'll just assume a miss. _that_ is what the solid_corpse is for - to allow a bigger bounding box on ents without breaking regular movement physics.
Urre
Posts: 1109
Joined: Fri Nov 05, 2004 2:36 am
Location: Moon
Contact:

Post by Urre »

Yes, I sometimes suck at explaining, atleast in hastily written forum posts... Note that you'll still need a separate entity in order to have this bigger SOLID_CORPSE action going on, unless someone knows another clever trick. You'd also require separate entities per limb if you want to do different amounts of damage based on which limb was hit, as far as I know there's no mesh name checking or anything like that. That'd be great though...
I was once a Quake modder
frag.machine
Posts: 2126
Joined: Sat Nov 25, 2006 1:49 pm

Post by frag.machine »

One could add engine side support to update a vector field holding the last collision coordinates relative to entity origin, allowing the proper treatment from QuakeC side. But of course that would be useful only for single point-sized or hitscan projectiles.
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC :) (LordHavoc)
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Post by Spike »

frag.machine wrote:One could add engine side support to update a vector field holding the last collision coordinates relative to entity origin, allowing the proper treatment from QuakeC side. But of course that would be useful only for single point-sized or hitscan projectiles.
you mean: impact = (trace_endpos - trace_entity.origin)
you can then use impact_z, and you have what orion described (hint: don't forget mins/max sizes...).
frag.machine
Posts: 2126
Joined: Sat Nov 25, 2006 1:49 pm

Post by frag.machine »

Spike wrote:
frag.machine wrote:One could add engine side support to update a vector field holding the last collision coordinates relative to entity origin, allowing the proper treatment from QuakeC side. But of course that would be useful only for single point-sized or hitscan projectiles.
you mean: impact = (trace_endpos - trace_entity.origin)
you can then use impact_z, and you have what orion described (hint: don't forget mins/max sizes...).
Calculating on the engine side could be precise at polygon level, avoiding the false positives the formula above can lead.
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC :) (LordHavoc)
GiffE
Posts: 170
Joined: Sun Oct 08, 2006 3:39 pm
Location: USA, CT
Contact:

Post by GiffE »

Would it also be possible to just check which tag the trace_endpos is closest too?
Urre
Posts: 1109
Joined: Fri Nov 05, 2004 2:36 am
Location: Moon
Contact:

Post by Urre »

GiffE wrote:Would it also be possible to just check which tag the trace_endpos is closest too?
That's a clever trick which should work in most cases yeah. Neat! You might run into problems such as a fat part close to a thin part, where you actually hit the fat part, but the thin parts tag is still closer.
I was once a Quake modder
Karatorian
Posts: 31
Joined: Tue Aug 17, 2010 4:26 am
Location: Rindge, NH, USA
Contact:

Post by Karatorian »

While I'm sure that engine support would make this all easier, I bet it could all be done with fairly generic QuakeC as well.

The basic idea goes like this. Create invisible target location entities for each player and update their positions in PlayerPostThink. (Which could get kinda complicated, depending on how accurate you wish to be. But possible.)

Then change the attack code to use these entities. By referencing a field to specify the target player and another to specify which part was hit, it should be fairly basic.

However, without using much in the way of extensions, I'm not sure how easy it'd be to make the targeting part work. I don't know exactly what traceline will and won't hit. So it might be difficult to make the entities that represent the target areas be nicely invisible and not interfere with the rest of the physics while still being targetable.

Any thoughts on this?
Cobalt
Posts: 445
Joined: Wed Jun 10, 2009 2:58 am
Location: New England, USA
Contact:

Re:

Post by Cobalt »

I know this is a played out topic already, but I thought I would follow this thread from the one over on Quakeone [ http://quakeone.com/forums/quake-help/s ... ctile.html ]

Spike made some new code that seems to work pretty well on the client hitboxes to determine the side. I played with it a little bit so the OTHER is an ent fed into the function, so that it dont depend on the touch
and its returning a string.

Code: Select all

string (entity box) Side_touch =
{
vector dir;
vector rel;
string side; //string for demonstration purposes, you probably want to fix that.

if (!box.ishuman)
makevectors(box.angles);
else
makevectors([box.angles_x*-1, box.angles_y, box.angles_z]); //stupid vanilla bug, but needed if you want to cope with eg players and their pitch angle that isn't 0.

dir = self.origin - box.origin;

//vector*vector is a dotproduct
rel_x = v_forward * dir;
rel_y = v_right * dir;
rel_z = v_up * dir;
//dotproduct: result=a_x*b_x+a_y*b_y+a_z+b_z
//consider that for instance, v_up is '0 0 1'. this means rel_z is equal to dir_z only.
//because forward,right,up are all normalised unit vectors, the result will be scaled according to that, giving the distance that dir points along the direction vector.
//thus this works regardless of the orientation of the other entity.

//float*float is a regular multiplication, dumbass. I'm using it to 'strip' the sign.
if (rel_x*rel_x > rel_y*rel_y && rel_x*rel_x > rel_z*rel_z)
{ //x is most significant
if (rel_x >= 0)
side = "FRONT";//and positive, so its in the forward direction
else
side = "BACK";//negative, so backward
}
else if (rel_y*rel_y > rel_z*rel_z)
{//its not going to be x. but it might be y / sideways
if (rel_y >= 0)
side = "RIGHT"; //rel_y was aligned to the RIGHT vector
else
side = "LEFT";
}
else
{
if (rel_z >= 0)
side = "TOP";
else
side = "BOTTOM";
}
if ((cvar ("local"))) // if we are a loval dev, for debug
{
local string readout;
readout = strcat ("hit the ", side);
readout = strcat (readout, " of ");
readout = strcat (readout, trace_ent.netname);
readout = strcat (readout, "\n");
centerprint(self,readout);
}

if (box.flags & FL_CLIENT)
return side;
[\code]

If I read this right, it ought to resolve or help filter out false positives if the Z_origin method for a headshot is used, but coding a special case for "TOP" impacts using this code. So far in my tests, for some reason if I am located above the box , no matter where I hit with the sg, always returns a "SIDE" value, which might be a coding mistake on my part, or maybe this code needs more tweaking. My idea is to create a "zone" that represents the top of the head using the self.origin_z and _y and bounding them about 8 units or so each direction from center with respect to whatever we calculate the top of the head zone (z) value to be. Most peoples heads seem to be about the same direction each way, except maybe Bill Gates.... :) 

Taking this concept to other body parts likely wont work, because the head has the same Z_axis all the time, I guess except for pain frames, but we could also work in frame numbers if we wanted to be really precise I guess.

Also I thought about marking the trace_endpos where it hit the box, then continuing smaller tracelines at maybe 2-4 step increments , then in reverse direction along the same travel vector, and if we encounter the hitbox again on the backwards traceline, that could be another reinforcement  for detection of the issue mentioned where certain angles are always headshots.

I also like the idea of being able to shoot thru the players legs, however that is gonna be angle dependent and also frame dependent. When it boils down to it, its all possible if you hard code exact quake unit values with respect to the hitbox vectors with respect to angles and frames, but its alot of work, and I suppose a modeling tool like maybe blender thats open source could be coded to manage all this.

Seperate entities for body parts probably solves this all, I know....but its definately an interesting Quake C learning experience.







[quote="Spike"]because shooting from up high is always a headshot.[/quote]
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: is there a way to do location specific damage in QC?

Post by Spike »

why did you change the makevectors logic? with that you broke pitch angles. only solid_bsp entities have correct the correct angles_x sign for makevectors. assuming you're going for visuals, you want .angles and not v_angle.
My code was written in the context of the projectile, thus 'other' was the victim, and 'self' was an impactor (read: a nail), which is why it used other.angles instead of self.angles. If you're tweaking the shotgun for a sniper rifle or whatever, then you'll need to ensure that the impact point (self.origin in my code) is actually still correct (eg: becomes trace_endpos). If you don't fix that then you're just testing which side of the enemy the player is on rather than where they actually hit.
Cobalt
Posts: 445
Joined: Wed Jun 10, 2009 2:58 am
Location: New England, USA
Contact:

Re: is there a way to do location specific damage in QC?

Post by Cobalt »

oops, sorry the !ishuman means the "box" ent is a bot, so we use its angles as oposed to the other condition. Im calling this only on FL_CLIENT ents for now from the traceattack () function, so Im not considering the SOLID_BSP's just yet, but I will be asking you about that because Id like this code to maybe be modified in the future so if we hit an explobox that say is "disarmed" the force of the bullet might tip it over. I had posted on the other forum the question, but was gonna ask that here, because it probably would need a changeroll () function to tip it over and I dont see any at least over here in DP.

Also took a peek as Seven sugguested at Muavebibs code [ http://www.quakewiki.net/articles/hit-location-system/ ] and saw its somewhat using what you did but seems to be able to get a good grip on the angle the model is facing, and determine chest, legs and head based on Z values, however as we already know, they become borked as you shoot from lower or upper self.origins. Seems perhaps some more trig could resolve that tho?

Headshot detected from the top using your code I almost have working, except it still would think you hit the head even if your trace_endpos on the box is outside the _x and _y bounds that you pick to mark it. Can be resolved by setting the damage float so no damage is actually done I suppose.

Definately a mess of hackery so far.... :)
Spike wrote:why did you change the makevectors logic? with that you broke pitch angles. only solid_bsp entities have correct the correct angles_x sign for makevectors. assuming you're going for visuals, you want .angles and not v_angle.
My code was written in the context of the projectile, thus 'other' was the victim, and 'self' was an impactor (read: a nail), which is why it used other.angles instead of self.angles. If you're tweaking the shotgun for a sniper rifle or whatever, then you'll need to ensure that the impact point (self.origin in my code) is actually still correct (eg: becomes trace_endpos). If you don't fix that then you're just testing which side of the enemy the player is on rather than where they actually hit.
Cobalt
Posts: 445
Joined: Wed Jun 10, 2009 2:58 am
Location: New England, USA
Contact:

Re: is there a way to do location specific damage in QC?

Post by Cobalt »

So lets say we are touching a player, this code seems to return perfectly the side touched , but if the player changes angles_y for example, since the hit box does not rotate with it, how could we recalculate the new side?

I had asked LH a similar question years ago and he said we need to use dotproduct, but it was to really see what side if the face we are closest to. I had the code working but forgot where I put it. We could use similar here to get started on this job, but of course there is the issue when the angle is a% toward one side and b% on the other.

Not sure if it makes things easier but in the mod I am putting this in, its using Frikbots and I believe Frik has a Phys_obj ent spawned around the outside of the hitbox with a movetype_fly to avoid the old "demonland" wav thud noise and maybe some other stuff Im not sure. Id have to look further, but it might match the players angles_y or it could be modded to match them. Looking at this concept, could this code merely spawn something similar as perhaps a trigger field which rotates with the players angles_y then we check for that ent specificly? Or do we get more mileage doing more involved calcs the other way?


Also wanted to bring up the previously mentioned issue about the Z calc for a headshot not working when the target is a percentage lower or higher then the attacker. I thought that could merely be cured with some basic trig, but it seems there is something missing. Also I noticed if you change the start of the Z for the traceline higher to a point representing the players actual eye level, you fix this, at least for the cases where the target is super close with the same Z origin.
As the target gets higher, you have to aim higher within what looks like a proportional area relative to the new z, but I am at a loss to get there completely - same goes for when the Z is lower for the targ vs the attacker.....
Post Reply