# Forum

## Calculating WaterDepth

Discuss programming in the QuakeC language.

### Calculating WaterDepth

Trying to create some code to supply the actual number of Quake units reflecting actual Waterdepth an ent is in. This almost is working, except if we are under a bridge and our waterlevel is 3, its lowering the value. Anyone have an idea whats wrong?

// Called when waterlevel = 3 for a player
Code: Select all
`float (vector xyz) WaterDepth ={local vector zyx;local float zz;zyx = xyz;if (self.ishuman) // offset to add player models height to the final result , zero for non client entszz = 56;zyx_z = self.absmax_z;makevectors (self.v_angle);normalize (v_forward);traceline (zyx, (zyx + '0 0 +1000' + v_forward), TRUE, self);if (!trace_inwater){bprint ("waterdepth : ");bprint (ftos (floor(zz + (trace_fraction) * 112)));PrintNL();   return (floor(zz + trace_fraction * 112));      }`

Cobalt

Posts: 445
Joined: Wed Jun 10, 2009 2:58 am
Location: New England, USA

### Re: Calculating WaterDepth

what are you actually trying to do? work out how much water there is above the player?
that's not going to work with traceline. traceline can only detect solids, it can't find water.
trace_inwater / trace_inopen merely state that *part* of the trace was inside water/empty. if they're both set then you know that it crosses a water surface, but you don't know where. probably you'll have to bisect it until you find where the surface is.

basically trace up from 0 to 1000 units. if it crosses into air, try 0 to 500, if it doesn't, try 500 to 750, etc, until the range is small enough that you don't care too much.
or you can spam some pointcontents calls.
Spike

Posts: 2890
Joined: Fri Nov 05, 2004 3:12 am
Location: UK

### Re: Calculating WaterDepth

Hrm, I thought the trace_fraction would reflect how much of the trace took place before it encountered the non water content.

There is also : trace_plane_dist , but it does not seem to be well documented in any QC stuff I can find.

Cobalt

Posts: 445
Joined: Wed Jun 10, 2009 2:58 am
Location: New England, USA

### Re: Calculating WaterDepth

like I said. traceline is never blocked by 'nothing', thus the trace will happily leave the water and give you nice fractions and stuff. it can never impact on the inside of the water surface.

trace_plane_dist describes the wall that got hit. its not really very useful, so noone uses it. go research standard plane equations, and then negate the distance, and you'll have a better understanding of this result value.
Spike

Posts: 2890
Joined: Fri Nov 05, 2004 3:12 am
Location: UK

### Re: Calculating WaterDepth

Thanks Spike.

For the time being, I figured another way. Using DP_SV_ENTITYCONTENTSTRANSITION, I will mark that origin_z where the transition takes place as the surface of the water and merely subtract from it to get the waterfdepth.

For the most part it ought to work, save for a map like E1M4, where you can re-surface at lower depths than previously marked....but thats a problem for another day.

Spike wrote:like I said. traceline is never blocked by 'nothing', thus the trace will happily leave the water and give you nice fractions and stuff. it can never impact on the inside of the water surface.

trace_plane_dist describes the wall that got hit. its not really very useful, so noone uses it. go research standard plane equations, and then negate the distance, and you'll have a better understanding of this result value.

Cobalt

Posts: 445
Joined: Wed Jun 10, 2009 2:58 am
Location: New England, USA

### Re: Calculating WaterDepth

Hello Cobalt,

If I understood you correctly, you want to write qc for detecting a water surface, and then start a calculation to compare the players origin with it ?
Qrv did the 1st part here for you:
viewtopic.php?f=2&t=4397

I also use this and it works great.
The only thing is, that you should not do it every frame as it will become a bit performance hungry then.
You can adjust its accuracy and thereby influence directly the performance impact.

For Darkplaces (or other supporting engines), DP_SV_ENTITYCONTENTSTRANSITION might be better though.

Best regards.
Seven

Posts: 301
Joined: Sat Oct 06, 2007 8:49 pm
Location: Germany

### Re: Calculating WaterDepth

Hi Seven

Yes, I believe I found that same code in your mod as its used to traceline with the shotguns to spawn a bullet splash. Its similar to what I was looking to do, but for the ost part I was looking to get a starting value for the surface z_ origin on maps that have liquid so in case an entity winds up in the liquid, we can apply that into how the entity will behave in regard to movement physics, such as avelocity and such. Its really experimental tests, but today I was also thinking that could be used as a way to maybe reduce the sound volume on the client / players side sound levels as a cheap hack for an underwater sound only mod, but there is probably more to it, and best done engine side anyway.

On maps like e1m4, where you have pockets and more than one surface level, it also creates some more complex problems that most likely require seperate QC for the specific map....

Seven wrote:Hello Cobalt,

If I understood you correctly, you want to write qc for detecting a water surface, and then start a calculation to compare the players origin with it ?
Qrv did the 1st part here for you:
viewtopic.php?f=2&t=4397

I also use this and it works great.
The only thing is, that you should not do it every frame as it will become a bit performance hungry then.
You can adjust its accuracy and thereby influence directly the performance impact.

For Darkplaces (or other supporting engines), DP_SV_ENTITYCONTENTSTRANSITION might be better though.

Best regards.

Cobalt

Posts: 445
Joined: Wed Jun 10, 2009 2:58 am
Location: New England, USA

### Re: Calculating WaterDepth

Code: Select all
`.float water_depth;.float water_check_time;.float water_in;// Keeps Entity Just Below Water Surface void() water_depth_think ={      local vector spot1, spot2;   local string depth;   spot1 = self.origin;   spot2 = self.owner.origin + self.owner.view_ofs;      if (self.owner.waterlevel <= 2)        {        self.owner.water_in = 0;   remove(self);        }           // Just here for testing. Prints the current vector length in a rounded integer   if (self.water_check_time < time)   {   self.water_check_time = time + 1.5;   self.owner.water_depth = vlen (spot1 - spot2);   depth = ftos(rint(self.owner.water_depth));   bprint (depth);   bprint ("\n");   }   self.velocity = self.owner.velocity;   self.avelocity = self.owner.avelocity;       // Kind of a hack   :roll:     if (pointcontents(self.origin) != CONTENT_WATER)   self.velocity_z = -50;   else if (self.waterlevel > 1)   self.velocity_z = 50;   else   {   self.velocity_z = 0;   self.avelocity_z = 0;   }   self.nextthink = time + .01;};   // Made visible here for testing   void() water_depth_entity ={   local entity wmeter;   wmeter = spawn();   setmodel(wmeter, "progs/s_bubble.spr");   wmeter.origin = self.origin + self.view_ofs;   wmeter.colormod = '0 0 10';   wmeter.classname = "wmeter";   wmeter.solid = SOLID_NOT;   wmeter.movetype = MOVETYPE_NOCLIP;   wmeter.owner = self;   wmeter.think = water_depth_think;   wmeter.nextthink = time;   self.water_in = 1;};   // Place in PlayerPreThink Or Similar   if (self.waterlevel == 2)      CheckWaterJump ();         [b]if (self.waterlevel == 3 && !(self.water_in))      water_depth_entity();[/b]`

This entity would keep readjusting itself to different waterlevels or if it somehow moved into a location that wasn't content_water. However, this wouldn't be a very good solution but a workable one even on levels that have different waterlevel sections.
PrimalLove

Posts: 14
Joined: Sun Oct 19, 2014 2:37 am