CSQC Tracelines

Discuss CSQC related programming.
Post Reply
c0burn
Posts: 208
Joined: Fri Nov 05, 2004 12:48 pm
Location: Liverpool, England
Contact:

CSQC Tracelines

Post by c0burn »

I'm trying to get ents sent to CSQC via sendentity to be hit by tracelines, but my trace never detects anything. Has anyone got an idea what the problem is? This is in FTE.

SSQC:

Code: Select all

float(entity to, float sendflags) explobox_send =
{
	WriteByte(MSG_ENTITY, 1);
	WriteByte(MSG_ENTITY, sendflags);
	WriteCoord(MSG_ENTITY, self.origin_x);
	WriteCoord(MSG_ENTITY, self.origin_y);
	WriteCoord(MSG_ENTITY, self.origin_z);
	WriteByte(MSG_ENTITY, self.modelindex);
	return 1;
};

void() spawn_explobox =
{
	self.classname = "misc_explobox";

	self.solid = SOLID_BBOX;
	self.movetype = MOVETYPE_NONE;

	precache_model ("progs/exbox.mdl");
  	setmodel (self, "progs/exbox.mdl");
  	setsize (self, '-16 -16 -16', '16 16 16');

	precache_sound ("weapons/r_exp3.wav");
	
	self.health = 20;
	self.th_die = explobox_boom;
	self.takedamage = DAMAGE_AIM;

	self.touch = explobox_touch;

	self.origin_z = self.origin_z + 32;
	// the original quake exploboxes were oriented on a corner, but our new .mdl is centered
	// around its origin, therefore we need to nudge it a bit
	self.origin_x += 16;
	self.origin_y += 16;
	
	self.SendEntity = explobox_send;
	
	if (!droptofloor())
	{
		dprint ("misc_explobox fell out of level at ");
		dprint (vtos(self.origin));
		dprint ("\n");
		remove(self);
	}
};

void() misc_explobox =
{
	self.nextthink = time + 0.2;
	self.think = spawn_explobox;
};
CSQC:

Code: Select all

void() checkshit =
{
	local vector o, v;
	o = getviewprop(VF_ORIGIN);
	v = getviewprop(VF_ANGLES);
	makevectors(v);
	
	traceline(o, o + v_forward * 4096, FALSE, world);
	
	// traceline never detects anything
if (trace_ent != world)
 eprint(trace_ent);
};

float(float evtype, float scanx, float chary, float devid) CSQC_InputEvent =
{
	if (evtype == IE_KEYDOWN)
	{
		if (chary == 101)
		{
			checkshit();
			return TRUE;
		}
	}
	return FALSE;
};

void CSQC_Ent_Update (float isnew)
{
	local float enttype = readbyte();
	local float flags;
	
	switch (enttype)
	{
		case 1:
			flags = readbyte();		
			self.origin_x = readcoord();
			self.origin_y = readcoord();
			self.origin_z = readcoord();
			setorigin(self, self.origin);
			setmodelindex(self, readbyte());
			self.drawmask = MASK_ENGINE;
			if (isnew)
			{
				self.solid = SOLID_BBOX;
				self.movetype = MOVETYPE_TOSS;
				setorigin(self, self.origin);
				self.classname = "misc_explobox";
			}
			break;
		default:
			break;
	}
};
Last edited by c0burn on Thu May 26, 2016 7:25 am, edited 1 time in total.
frag.machine
Posts: 2126
Joined: Sat Nov 25, 2006 1:49 pm

Re: CSQC Tracelines

Post by frag.machine »

Not saying I have any idea why your code isn't working as expected but... usually I prefer

Code: Select all

 if (trace_fraction < 1.0)
because traceline can actually hit the world, and your test would not detect it.
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC :) (LordHavoc)
toneddu2000
Posts: 1395
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

Re: CSQC Tracelines

Post by toneddu2000 »

Saw this post just now. Please frag.machine, can you please explain how to use trace_fraction? I never understood how to use it.
Is it the percentage of world hit by line(0.1 = 10%, 0.5 = 50%, etc.)?

Thanks in advance for your clarification
Meadow Fun!! - my first commercial game, made with FTEQW game engine
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: CSQC Tracelines

Post by Spike »

trace_fraction:
if you cast a ray from A to B, that ray you can hit planes C,D,E,F, etc. each plane has its own plane and normal.

distfromA = dotproduct(A, planenormal) - planedist;
distfromB = dotproduct(B, planenormal) - planedist;
fraction = distfromA / (distfromB-distfromA);
endpos = A + (B-A)*fraction;

if you're doing triangle-based collision, then there are 3 more dotproducts against endpos and the 3 planes that define the edges of the triangle.
brush collision does some traces against every single plane of the brush to figure out which plane it actually hit (furthest, so long as it wasn't clipped by another plane).
bsp collision provides an ordered tree of planes, with the results of plane checks determining which other leafs/planes need to be checked.

the actual trace that is returned by traceline is then the trace against the plane which resulted in the lowest fraction (where it actually hit the geometry that included that plane, and where the far side is considered solid with the near side not).
things get more messy when using traceboxes - the plane distances are expanded according to the size of the box. in the case of q1bsp these distances are precomputed, hence why only certain 'hull' sizes work correctly.

so yes, fraction is the (decimal)percentage of the distance travelled. 0 if it hit immediately, 50% if the wall was half of the distance away, and 1 if it travelled the full distance without hitting anything.

the startsolid flag is poorly defined. logic dictates that it can only be set when fraction is 1, which makes testing for it unreliable. often you'll want to ignore startsolid, because it can be better to allow traces through solids if you're already inside them as a way to attempt to counter any precision issues. alternatively you can do what nq player physics does, and just teleport the player back to their oldorigin if the player gets stuck.
the other contents flags are similarly unreliable, and reflect only the nearest impact. if you're pushing against a submodel while in water, if it detects and impact against that submodel then you won't be in water, but if you move away slightly then suddenly you will be. pointcontents is more reliable for this sort of thing.
toneddu2000
Posts: 1395
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

Re: CSQC Tracelines

Post by toneddu2000 »

Thanks a lot Spike, as always very detailed answer! :)

The description you posted of trace_fraction is of course, about how it works in C engine, right?
Spike wrote:each plane has its own plane and normal.
?? Every plane has its own plane? And when do you talk about planes, do you mean bsp faces splitted in quad faces(2 triangles joined by 1 edge)?
so yes, fraction is the (decimal)percentage of the distance travelled. 0 if it hit immediately, 50% if the wall was half of the distance away, and 1 if it travelled the full distance without hitting anything. wrote:
Ok, so, writing

Code: Select all

if (trace_fraction == 1){
//do something
}
It means "do something only if the ray didn't intercept anything solid", right? But, the thing I cannot understand is: why should I need that information?
Usually I use tracelines (I use it for 100 other thing but most of it for) either for physics or for weapon code.

Usually I do something like that:

Code: Select all

//mouse fire check
//refire check
traceline(weapon fire source,weapon fire source+ v_forward * how far weapon can shoot,0,self);
if (trace_ent.takedamage){
trace.ent.health-=whatever;
}


If I add

Code: Select all

if(trace_fraction != 0){
  if (trace_ent.takedamage){
    trace.ent.health-=whatever;
  }
}
How can change the weapon damage code?

Thanks again for your great explanation! :)
Meadow Fun!! - my first commercial game, made with FTEQW game engine
frag.machine
Posts: 2126
Joined: Sat Nov 25, 2006 1:49 pm

Re: CSQC Tracelines

Post by frag.machine »

There is a lot of applications to trace_fraction, but I mostly use it for either proportional damage or because as I said is a more reliable collision test than checking trace_ent directly.
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC :) (LordHavoc)
toneddu2000
Posts: 1395
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

Re: CSQC Tracelines

Post by toneddu2000 »

Thanks frag.machine, so, why
if (trace_fraction < 1.0)
it's
a more reliable collision test than checking trace_ent directly
?

could it be considered as "if the tracing ray hasn't hit anything yet, let's see if the trace_ent has requirements I'm looking for"?

Thanks again
Meadow Fun!! - my first commercial game, made with FTEQW game engine
frag.machine
Posts: 2126
Joined: Sat Nov 25, 2006 1:49 pm

Re: CSQC Tracelines

Post by frag.machine »

If trace_fraction is less than 1.0 means it hit something (including the world).

if trace_ent == world either can be "I hit nothing, then I will return a null reference entity (trace_ent == world and trace_fraction == 1.0)
OR
"I hit the world, thus I'll return it, even though I normally return it when I hit nothing too (trace_ent == world but trace_fraction < 1.0).

traceline has a very particular behaviour regarding entities it may ignore. In DP and FTE its behaviour was extended (and additional buitins like tracebox are supported), making it even more complicated to understand.

I remember reading some stuff from FrikaC that helped me a lot. Check the Wiki.

EDIT: added wiki link.
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC :) (LordHavoc)
toneddu2000
Posts: 1395
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

Re: CSQC Tracelines

Post by toneddu2000 »

As far as I know ssqc and csqc don't know anything about each others (but they can share data, though). So, basically is as they would live in different dimensions. I usually do all the traceline computation in ssqc and then sendentity a vector and then I read that vector in csqc and make all the magic directly in csqc. Sorry cannot to help you more now but I'm replying from mobile and it's impossible for me to write code with phone.. :confused:
Meadow Fun!! - my first commercial game, made with FTEQW game engine
toneddu2000
Posts: 1395
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

Re: CSQC Tracelines

Post by toneddu2000 »

This is why I hate smartphones. I saw first post on my mobile and I thought c0burn's post it was the last one and I replied to it. Back to pc I found out it was the first one...grrrr :confused:
Meadow Fun!! - my first commercial game, made with FTEQW game engine
Post Reply