Onground Calculation

Discuss programming in the QuakeC language.
Post Reply
Cobalt
Posts: 445
Joined: Wed Jun 10, 2009 2:58 am
Location: New England, USA
Contact:

Onground Calculation

Post by Cobalt »

Not sure if this is any good, but I thought maybe this could be a possible way to determine weather a dead body or other ent is laying on a wall and thinks its on ground?

Code: Select all

float (entity targ) Ongroundscore =
{
	local vector spot1;
	local vector spot2;
            local entity calc;
            local float score;

calc = spawn ();
 setorigin (calc, targ.origin);
 setsize (calc, '0 0 0', '0 0 0');
calc.solid = SOLID_TRIGGER;

if (calc.flags & FL_ONGROUND)
score = score + .25;
if (checkbottom(calc)
score = score + .25
if (droptofloor (calc))
score = score + .25;

tracebox(calc.origin, '-32 -32 0', '32 32 56', calc.origin, FALSE, calc);
       if (trace_startsolid)
 score = score + .25;
	
	if ((score == 1))
	{
		return (TRUE);
	}
	return (FALSE);
};

Its just a rough draft, surely needs work, feel free to re-edit with ideas. I know that FL_ONGROUND is true when we are touching a wall for example, so that is one condition that needs to be isolated as a smaller factor in the equasion. Perhaps some tracelines would also help?
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: Onground Calculation

Post by Spike »

You don't free calc. And certainly spawning an ent for use within a single function is not good karma.
Tracebox is a 'pure' function and won't harm anything but the trace globals, so spawning an extra ent is pointless.
droptofloor uses tracebox internally, so that is redundant.
checkbottom uses pointcontents and is thus buggy with clip brushes.
your tracebox will start -targ.mins_z units above the bottom of targ.

If you just want to check if an ent is stuck in something, you can just call tracebox(self.origin, self.mins, self.maxs, self.origin, FALSE, self); and then test trace_startsolid as you already do. False means that its free to move around, true means its stuck within something.
frag.machine
Posts: 2126
Joined: Sat Nov 25, 2006 1:49 pm

Re: Onground Calculation

Post by frag.machine »

Spike wrote:You don't free calc. And certainly spawning an ent for use within a single function is not good karma.
What ? Even vanilla QuakeC code does this. A lot.
I always presumed the entity discard was handled under the hood by the compiler (or the engine) ? Isn't that the case ? :?:
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:

Re: Onground Calculation

Post by Spike »

no
the engine/qcc never remove()s any entities ever, except when the qc explicitly calls remove().

and even if it did, there's a 2 second grace period before the entity can be reused. call it once per frame, run it on a machine with a good cpu + small res (2000fps), and you'll crash the (vanilla) server in a quater of a second. if you're calling it once per frame per monster then oh boy!
if you really need such a temporary entity, you can always spawn one in worldspawn and just reuse it each time. I just don't think you really need an entity.
Cobalt
Posts: 445
Joined: Wed Jun 10, 2009 2:58 am
Location: New England, USA
Contact:

Re: Onground Calculation

Post by Cobalt »

yea, forgot to remove the ent, but this was just an idea / concept.

I thought I recalled testing droptofloor with vanilla quake years ago , whenever called, will actually drop the (self) entity its called down in to the floor no matter what. So that was why I decided to spawn an ent at the object we are testing's origin, and drop a test marker. No sense dropping the object itself to the floor.

For the most part I am trying to detect a condition where for example a player is moved off a ledge via a rocket blast, and hits a wall and is still
technicly not standing or laying on the ground below. I figure the collision to the wall will definatley set FL_ONGROUND to TRUE, and I guess the tracebox code would also start in a solid at some point, but I figure if we did that droptofloor with the entity it had some way to detect if really we are on the ground of the map, but I guess it would not matter if droptofloor moved side to side when ' dropping'? It would still be TRUE as long at it hit a solid, so the only thing that would work with is if the playwr was over a liquid I guess.

Another idea is the .jumpflag float.....however I believe that is utilized with the negative value of self.velocity_z ?
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: Onground Calculation

Post by Spike »

droptofloor will not move sideways, like I said its just a tracebox, one vertically down. But you are right in that its also a setorigin, but that is bypassed by using tracebox only, thus removing the need for a temp ent.

The general rule is that if the player is within 1 quake unit of the ground, then they're sufficiently onground to be, urm, onground. So tracebox from self.origin to self.origin-'0 0 1', and if trace_fraction is < 1, they're standing on something. If you use traceline at the same time, you can check if at least half the bbox is over a ledge and thus give different amounts of friction or something.

When tracebox-testing a player's origin, startsolid==true indicates a bug. It should not happen during normal play (if an NQ engine sees it, it'll move the player back to self.oldorigin) - it can happen due to precision issues, but is pretty rare and won't last more than a frame.

Quake considers ground planes with a trace_plane_normal_z < 0.7 to be walls. It must be >0.7 for it to be considered ground, by the engine.
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Re: Onground Calculation

Post by Baker »

Spike wrote:no
the engine/qcc never remove()s any entities ever, except when the qc explicitly calls remove().
Filed info away. One less surprise to deal with in future.
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: Onground Calculation

Post by Spike »

actually, one exception to that - makestatic contains an implicit remove. A copy of the ent lives on as a static entity, but the original qc entity is indeed removed in that case.
Even with csqc, the engine expects the csqc to call the final remove() on entities that left pvs (this allows entities to live on as explosions or corpses or whatever, which is handy with the pvsf_noremove flag, which is really handy with allowing longer-lived event entities).
Cobalt
Posts: 445
Joined: Wed Jun 10, 2009 2:58 am
Location: New England, USA
Contact:

Re: Onground Calculation

Post by Cobalt »

Great info Spike.

Can you elaborate more on the ground planes? Is that a map only specific or can QCC connect to it in some way?

I am also wondering if its just as simple as merely doing an old fashioned traceline from the player origin perhaps 2-4 units below its absolute min_z to check for either .solid or if the trace is touching world. Maybe assign the player a .touch field, call the traceline upon it touching something. Or perhaps .blocked would be better suited? I am guessing the difference between the 2 are .blocked checks for a velocity of 0 0 0 or whatever to call that field? Where .touch dont rely on anytning else at all except collision.

Interesting you mentioned makestatic. Lord Havoc has described that to me as if you were merely 'freezing' all the specifics that entity holds so its no longer a dynamic entity, which means in MP netplay, its no longer considered part of the sign-on packet. I am messing with this for my ng nails and I have it coded so that a nail will sometimes stick in the wall, and become static. If you remain in the game you can see the nails stuck in the walls , but if another player joins, they do not see the nails. I had hoped this would cut down on framerates on the client end, and also the number of entities in the netplay packets. On one map however there is a problem where you sign on and get message: "too many static entities" which I found very strange and yet have to look into.

So if indeed the engine removed static entities, I am not sure why it would be transmitting them in the sign on packets anymore unless this is just a DP only type bug.
Spike wrote: Quake considers ground planes with a trace_plane_normal_z < 0.7 to be walls. It must be >0.7 for it to be considered ground, by the engine.

actually, one exception to that - makestatic contains an implicit remove. A copy of the ent lives on as a static entity, but the original qc entity is indeed removed in that case.
Even with csqc, the engine expects the csqc to call the final remove() on entities that left pvs (this allows entities to live on as explosions or corpses or whatever, which is handy with the pvsf_noremove flag, which is really handy with allowing longer-lived event entities).

r00k
Posts: 1111
Joined: Sat Nov 13, 2004 10:39 pm

Re: Onground Calculation

Post by r00k »

A dirty solution for ents getting stuck over an edge would be to randomly rotate the object ever so minutely until it is removed or drops. ;)
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: Onground Calculation

Post by Spike »

.blocked is exclusively for movetype_push entities, and is called by the engine to say 'pusher can't keep moving, something is blocking it'. Its not useful for players at all.

Go google for planes or plane equations, etc. An infinitely large surfaces with no edges ever can have its position and orientation expressed with just 4 values - a normal and a distance (ie: how many units along that normal you'll find the surface). Being a normal and all, its normalized, thus a value of at least 0.7 ensures that its pointing more upwards than any other axial direction. You can access the properties of the plane the traceline hit via trace_plane_normal and trace_plane_dist. The dist generally isn't useful (the engine calculates trace_endpos for you with it so qc and most of the engine code doesn't need it).


Logically, makestatic does freeze the entity...
But back in reality, the engine copies the visible attributes of the entity out into an svc_spawnstatic message which it puts into the MSG_INIT buffer. Then remove()s the original entity. From then on, the entity has been destroyed as far as QC is concerned. The client will receive the contents of the MSG_INIT buffer when it connects (after the map is spawned), and will read that copy of the entity's visible attributes. The client doesn't know anything about the entity other than what it looks like and where it is.
Send too many static entities to a client and you'll fill some client-side list, resulting in the client ignoring any more.
If makestatic didn't remove() the original QC entity, you would have two separate entities visible on the same spot.
Calling makestatic will not affect the size of the MSG_INIT (aka: sign-on) message - you are basically trading an svc_spawnbaseline for an svc_spawnstatic. The real gain is that the server is no longer doing pvs/physics/etc for the now-static entity (because it got remove()d and doesn't technically exist any more), and is no longer sending the entity over the network (beyond the MSG_INIT) message.
Cobalt
Posts: 445
Joined: Wed Jun 10, 2009 2:58 am
Location: New England, USA
Contact:

Re: Onground Calculation

Post by Cobalt »

Thats interesting, do you have any prototype code to share? In my example I am going by the player model which is in mid air and touching a wall.
Your example maybe is like a dead body with a good percentage of its bottom not really touching the bsp? I thought of that too, and you could probably use some tracelines to determine which part of that ent is mostly off-ground, and apply force to that percentage of the model via a rotation to nudge it off the ledge for example. Might another idea be sort of like the wind tunnels map where those vents push you up off the ground a bit when you walk over them?
r00k wrote:A dirty solution for ents getting stuck over an edge would be to randomly rotate the object ever so minutely until it is removed or drops. ;)
frag.machine
Posts: 2126
Joined: Sat Nov 25, 2006 1:49 pm

Re: Onground Calculation

Post by frag.machine »

Spike wrote:no
the engine/qcc never remove()s any entities ever, except when the qc explicitly calls remove().

and even if it did, there's a 2 second grace period before the entity can be reused. call it once per frame, run it on a machine with a good cpu + small res (2000fps), and you'll crash the (vanilla) server in a quater of a second. if you're calling it once per frame per monster then oh boy!
if you really need such a temporary entity, you can always spawn one in worldspawn and just reuse it each time. I just don't think you really need an entity.
Yeah, of course you're right. Silly me, I must be spoiled by programming with managed memory languages too much. :P
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC :) (LordHavoc)
Post Reply