Page 1 of 1
Better detection of Water Depth
Posted: 03 Aug 2006, 11:35
by Argh
Very simply... I'd like us to be able to return a non-binary value for "is over water". Spring has inherited the TA engine's very crude recognition of water depth. This leaves us with the same limitations as OTA, where a lot've units, like "swimming tanks" aren't really practical. I've built a unit for NanoBlobs 0.51b that can "swim", but the crudity of the water/land boundary is obvious, and annoying.
What we need, in my opinion, is to use the standard BOS, but have the results coming back from the engine be a little different. Currently, we use scripts to detect water like this one:
Code: Select all
setSFXoccupy(level)
{
WaterDepth = level;
If( Waterdepth == 1 )
{
Overwater = 0;
}
If( Waterdepth == 2 )
{
Overwater = 1;
}
If( Waterdepth == 3 )
{
Overwater = 1;
}
If( Waterdepth == 4 )
{
Overwater = 0;
}
return (0);
}
Surely we can have something better than this. We already know the waterheight, so we know when the water "begins". So why not just have something like this:
Code: Select all
setSFXoccupy(level)
{
WaterDepth = level;
If( Waterdepth >= 1 )
{
Overwater = 0;
}
return (0);
}
... where
level, the value we're seeking from the Spring game engine, is the difference between the Y height of the unit and the water level set in the map, expressed as a float for smooth translations between states?
When you see my new unit I made for NanoBlobs, I think you'll understand why I'm a little disappointed that this part of Spring is very crude- it's an awesome unit that has some serious problems in terms of look-and-feel simply because I cannot make it accurately anticipate that it's about to leave the water

Posted: 03 Aug 2006, 11:54
by Gnomre
What does "get GROUND_HEIGHT" report when on the water?
Posted: 03 Aug 2006, 12:37
by AF
I thought thats how it worked currently??
Currently the water plane is always at 0 in spring. Anything below 0 gets rendered below the water plane and anything above 0 is rendered above the water plane.
Thus
if(height >0){
overwater=0;
}
If this is different for BOS then I'm sure it can be changed easily...
Posted: 03 Aug 2006, 13:57
by Argh
<Shrugs>
Wrote this code, and it consistently returns 0. GROUND_HEIGHT is returning a non-zero number... now for some experiments to find out if it's returning anything that's actually useful...
Code: Select all
CheckWaterDepth()
{
WaterDepth = get GROUND_HEIGHT;
If (WaterDepth < 0)
{
OverWater = 1;
}
If (WaterDepth > 0)
{
OverWater = 0;
}
sleep 100;
}
Posted: 03 Aug 2006, 14:12
by Argh
Aha. Getting somewhere. This returns a value of 1. Betcha it's using a value of 256, with 127 or 128 as the value for the water level.
Code: Select all
CheckWaterDepth()
{
WaterDepth = get GROUND_HEIGHT;
If (WaterDepth <= 10000)
{
OverWater = 1;
}
If (WaterDepth > 10000)
{
OverWater = 0;
}
sleep 100;
}
... nope, that doesn't work. Thinks I'm over water!
Code: Select all
CheckWaterDepth()
{
WaterDepth = get GROUND_HEIGHT;
If (WaterDepth <= 0.5)
{
OverWater = 1;
}
If (WaterDepth > 0.5)
{
OverWater = 0;
}
sleep 100;
}
STILL thinks I'm over water! Something's very, very odd here.
Posted: 03 Aug 2006, 14:22
by Argh
Soooo... the number is over 0, but below 0.5. Erm, ok... let's try something absurdely low:
Code: Select all
CheckWaterDepth()
{
WaterDepth = get GROUND_HEIGHT;
If (WaterDepth <= 0.000001)
{
OverWater = 1;
}
If (WaterDepth > 0.000001)
{
OverWater = 0;
}
sleep 100;
}
.... no dice!
Oops, my first check didn't look for == 0. Let's try that...
Code: Select all
CheckWaterDepth()
{
WaterDepth = get GROUND_HEIGHT;
If (WaterDepth < 0)
{
OverWater = 1;
}
If (WaterDepth >= 0)
{
OverWater = 0;
}
sleep 100;
}
Hmm... zero.
Code: Select all
CheckWaterDepth()
{
WaterDepth = get GROUND_HEIGHT;
If (WaterDepth <= 0)
{
OverWater = 1;
}
If (WaterDepth > 0)
{
OverWater = 0;
}
sleep 100;
}
Zero! It always returns zero, period. Any other ideas, folks? It appears that this value is returned as zero by Spring... probably to prevent crashes with units that made use of this feature in OTA. Methinks it should just return the real Y value of the heightmap pixel the unit's over when queried, with any values under the water level returning negative numbers, for simplicity's sake. That'd solve it, and be easy to wrap our heads around.
Posted: 03 Aug 2006, 15:16
by Yeha
It returns the height at specific coordinates. If you want the height under the unit try "get GROUND_HEIGHT(get UNIT_XZ)".
Posted: 03 Aug 2006, 15:22
by ILMTitan
If GROUND_HEIGHT is being converted to an unsigned int from an int, then 128 and above would be below water and below would be ground. 255 -> -1, 128->-128.
Posted: 03 Aug 2006, 16:34
by Argh
Interesting. I've gotten it to work, kind've, but... it's not returning anything like the values you guys are talking about.
I got it to work with a combo that evaluated it for 0 or not 0, but when I try to convert it to a number that I can look at as a range (which is what I need here- something less crude than just a binary state change)... it's not returning a number... hmm
Posted: 03 Aug 2006, 16:41
by Argh
Getting closer to the truth, here. This script finally returns a valid TRUE/FALSE every time. It looks dumb, but the little math bits there at the start seem to be forcing Spring to finally evaluate it as a number properly.
Code: Select all
CheckWaterDepth()
{
while(TRUE)
{
WaterDepth = get GROUND_HEIGHT(get UNIT_XZ);
WaterDepth = WaterDepth + 1.00;
WaterDepth = WaterDepth * 1.00;
If (WaterDepth > 1)
{
OverWater = 0;
}
If (WaterDepth <= 1)
{
OverWater = 1;
}
sleep 100;
}
}
Posted: 03 Aug 2006, 16:48
by Argh
More trouble. Whatever this is returning, it's greater than -5, no matter how deep the water is. Methinks it's zero. Sigh. That's
not what I was hoping for!
Code: Select all
CheckWaterDepth()
{
while(TRUE)
{
WaterDepth = get GROUND_HEIGHT(get UNIT_XZ);
WaterDepth = WaterDepth + 1.00;
WaterDepth = WaterDepth * 1.00;
WaterDepth = WaterDepth - 1.00;
If (WaterDepth > -5.0)
{
OverWater = 0;
}
If (WaterDepth <= -5.0)
{
OverWater = 1;
}
sleep 100;
}
}
Posted: 03 Aug 2006, 16:57
by Argh
Definately... zero! Ok, so water is zero. Everything else is positive- there are no negative numbers. I cannot measure the distance from the ocean surface to the ocean floor- insofar as Spring is concerned, it doesn't really exist, since my unit isn't a sub/ship (which is a whole nother set of issues- I have got to convince you guys to do away with all of the special classes someday). Kind've sucks to be me. Now, let's see... maybe I can get this another way...
Posted: 03 Aug 2006, 17:04
by SinbadEV
so how do tanks that run across the bottom of the water report their deapth?
reason I ask is that units that "float" never go under water... so maybe from THEIR perpective the water is always 0 pixles deep, while to a submersible unit (not a sub, subs are just boats whoes models are drawn underwater) who acctually goes underwater might recornoze the acctual deapth... still useless to you I would think... but good to know...
Posted: 03 Aug 2006, 18:31
by Argh
Ok, I'm reeeeeally close now. I just have one final problem, and this is probably a no-brainer for you scripting experts out there...
It almost works perfectly now. It can tell when it's over water, and when it's over land. I've set the detection points far enough apart that it needs to go a ways "out to sea" before submerging (the whole point of this, really). The only problem left is that it keeps "tipping" on land- it's very clearly getting a value that tells it it's on the ocean, and then is very quickly getting corrected... over and over and over again

Any idea why it's failing to continuously update properly? It's gotta be something dumb, but I'm too tired to find it.
Code: Select all
CheckWaterDepth()
{
WaterDepth = (((get GROUND_HEIGHT(get PIECE_XZ(front_point))) + 1) * ((get GROUND_HEIGHT(get PIECE_XZ(rear_point))) + 1) * ((get GROUND_HEIGHT(get PIECE_XZ(right_point))) + 1) * ((get GROUND_HEIGHT(get PIECE_XZ(front_point))) + 1));
If (WaterDepth > 1)
{
OverWater = 1;
}
If (WaterDepth <= 1)
{
OverWater = 0;
}
sleep 1;
return(0);
}
SlopeAdjust()
{
var x-slope, z-slope;
while(TRUE)
{
call-script CheckWaterDepth();
sleep 50;
if (OverWater == 1)
{
x-slope=get ATAN (((get GROUND_HEIGHT(get PIECE_XZ(front_point))) - (get GROUND_HEIGHT(get PIECE_XZ(front_point)))),((get XZ_HYPOT( ((get PIECE_XZ(rear_point)) - (get PIECE_XZ(front_point)))))));
z-slope=get ATAN (((get GROUND_HEIGHT(get PIECE_XZ(right_point))) - (get GROUND_HEIGHT(get PIECE_XZ(left_point)))),((get XZ_HYPOT( ((get PIECE_XZ(right_point)) - (get PIECE_XZ(left_point)))))));
turn body to x-axis x-slope speed <400>;
turn body to z-axis z-slope speed <400>;
move body to y-axis [0] speed [30];
}
if (OverWater == 0)
{
turn body to x-axis <-20> speed <200>;
move body to y-axis [-6] speed [1];
}
}
return(0);
}
Posted: 04 Aug 2006, 13:13
by KDR_11k
In case you want to get a value out of a BOS script,
here is a model and script for an eleven digit decimal counter that can display any number from the script. If I knew how to do modulo it'd work better, though.
Just in case you need to do that later on.
Posted: 04 Aug 2006, 22:26
by Argh
Cool, well I can use that to find out what feedback I'm getting from this... didn't have any time/mental energy to mess with this last night (been very rough at work this week, had Weds off).
Posted: 05 Aug 2006, 08:46
by Argh
WOOT!!! GOT IT!
The best part is, it's not even terribly hard... now I just need to get the timing right, for perfect animation...