ValveSoftware / halflife

Half-Life 1 engine based games
Other
3.61k stars 599 forks source link

[GoldSRC] Water Bug #2062

Open DarthMan opened 5 years ago

DarthMan commented 5 years ago

Hello. So recently, I opened an EntMod-only server with entmaps. One of the maps is entmap_2houseshop and that 1 contains a func_water. I use the weapon phaser to grab it and move up, but there's probably a bug in the engine because everytime (only when grabbing water) the z origin is higher by some unknown value, the entity starts to become invisibible. Then, if I start moving again while it is invisible and move it down, so, lowering the z origin, it starts to appear again. Any possibility of this being fixed? This is really important for me because water is part of the map and it was put for a reason (to be able to clone it and put on the map). Un-solid entities can't be normally grabbed, but my EntMod uses a special trick to grab any kind of entity, even func_ilusionary or weapons etc.

SamVanheer commented 3 years ago

This kind of bug needs a test map to reproduce it with before it can be investigated.

SamVanheer commented 3 years ago

You can't expect a bug in a 22 year old game to be fixed based solely on vague bug reports. This still needs a test map. Make a small, self-contained map that reproduces the issue, if you know how to reproduce it it should be easy enough.

Edit: i was able to reproduce it in a map with water moving up. I'll see if i can isolate the cause, but if it's in the engine i can't track it much further.

SamVanheer commented 3 years ago

Looks like this is actually intentional, i don't know why though.

When a brush surface that has water textured on it is drawn an extra check is performed:

if (mins[2] + 1.0 < surface->plane->dist)

Where mins[2] is:

mins[2] = entity->origin[2] + entity->mins[2];

This is the entity's bounding box minimum Z value. Meaning basically the lowest vertex in the entity is at that height in the map, in absolute coordinates.

The surface plane distance value is the shortest signed distance to the plane from the origin.

If this is false then it won't draw the surface.

Only surfaces that are facing directly up are drawn if they have a water texture on them, so this calculation results in water not being drawn if the brush has moved up at least the total height of the brush.

So the higher the brush is, the further up it can move before it becomes invisible. The position of the entity itself doesn't seem to matter here. The entity can be moved up and it will still stop rendering once it has moved up at least by the height of the entity or more.

Adding an origin brush causes it to stop rendering altogether, at least when the entity is above the world origin. The plane distance value becomes a relative value (-32 in my case, where the water surface is 32 units above the origin brush's center) while the minimum Z value is a positive value even before moving.

I don't know why this check exists. It doesn't exist in Quake. Maybe it was added to fix some issue where water rendered when it shouldn't. Without being able to see the actual code there's no way to know.

I can verify that this code has been in the game since launch. Half-Life Uplink also has it, so it must have been added during the game's development.

Assuming this is unwanted behavior the fix is simple: remove the if check and water will render as expected.

As a workaround you could try putting the water brush at its intended end position and having it move down, combined with having it start open. This should be equivalent to a water brush moving up without triggering the check that breaks rendering.

I tested this and it works, however other rendering issues occur:

Also, for the sake of completeness, i tested the map in Sven Co-op 3.0 to which the above change you listed was added. The bug also occurs there. It might be fixed in 5.0 onwards but it's not the change you listed.

SamVanheer commented 3 years ago

I've been thinking about this and i think i know why this is done. Back when Half-Life was made there were no null textures to strip surfaces (ZHLT added those), so water brushes needed to be textured on all sides.

The check performed to see if a water surface is a side surface doesn't work on bottom surfaces since they're treated as Z planes: https://github.com/ValveSoftware/halflife/blob/c7240b965743a53a29491dd49320c88eecf6257b/utils/common/bspfile.h#L112

So this check hides those bottom surfaces, but only if the entity hasn't moved lower than it starts off at.

My guess is this was a workaround for that issue. If that's the case then the proper solution is to remove the check and making a tool to find these surfaces and to make them invisible.

Such a tool would need to check if a surface has a texture that the engine treats as water (name starts with !, laser or water) and has a plane that is coplanar with the Z plane, and has a normal pointing down. The latter checks are essentially the same since a plane with the normal pointing down is always a Z plane (unless there's some compiler trickery involved).

There's no out-of-the-box invisible texture to use so removing the surface from the bsp might be necessary, unless the engine can be updated to add a new kind of special texture name that isn't drawn.

Alternatively checking the plane normal to see if it points down could work too.

The first solution is the cleanest, but requires really old maps (mostly official maps) to be patched to fix it.

One example of bottom surfaces being rendered is in c2a1a. After you activate the pumps, if you noclip into the floor so your view is intersecting a wall you can see both the top and bottom surfaces: xVRZ2U9

SamVanheer commented 3 years ago

A lot of what you posted seems unrelated to the actual issue so'd recommend trimming it down a bit.

If what you're saying is that any entity textured with water textures that moves up becomes invisible then that's because this is a bug in the rendering code, it's not tied to any particular entity type. The type of the texture is what matters, not the type of the entity.

SamVanheer commented 3 years ago

Only 256 visible entities can be sent from the server to the client in any given frame. That's just the way the engine was built. It's not related to this issue.

djearthquake commented 3 years ago

It was working 1 day and then the next it is not on Half-Life Opposing Force. I removed the apache. The problem did not go away. It spread to 3/4 of the map. How does that happen?

SamVanheer commented 3 years ago

That screenshot shows you're making a map for Sven Co-op which uses a modified engine. I suggest you ask for help in their forums or Discord.

djearthquake commented 3 years ago

Sven I have no issues with. It's Half-life. Pointing towards faulty compiling software more and more. Thanks for the heads up on the 256 limit. That has helped. The map is for Opposing Force. I am well under the limit and water comes and goes in some spots when walking. So does any large ent like func_illusionary and func_wall but is not limited to certain functions. New thread or same thing Darthman is talking about? He is modifying ents I am making new maps and seeing this too. You see and have a solution. My perspective was to do what Sven is doing as much as possible. That also sounded like a good idea to you initially. Now we are on modified engine can't do anything about it mindset. Good luck. I've multiple workarounds to this bug/feat. The only true water bug was Linux 1999-2002. Stand in the water had god mode. That is only true water bug there ever was. This is just a patch few need. Somebody was thinking everything turning blue when underwater was a bug. Hardly. It can be controlled in Hammer and elsewhere.

SamVanheer commented 3 years ago

If you're referring to VHLT then you need to talk to whoever's maintaining that. VHLT is not made by Valve, it's a community modified version of the original compile tools. If a mistake was made that causes graphical issues then it needs to be investigated by the maintainers.

As far as engine limits go there are already issues covering the increasing of those.

You should ask for help on mapping forums, Discords, etc to figure out what the problem is. This is just a bug tracker, for reporting known issues. It's not a help desk to help find what the problems are.

Also keep in mind that this is a very old engine. It's limited in many ways and things that are trivial to do in modern engines are difficult or outright impossible to do in this engine. Sometimes it just isn't possible to make something work properly.

djearthquake commented 3 years ago

We are talking about the same bug . Water will disappear just for a moment then come back in a flash when walking or stay disappeared when standing in one of the hotspots so to speak on maps made decades before mine. Func_illusonary is func_water so it is not like I am taking about 2 different things with that regard. Acknowledge to me you understand func_illusionary is func_water please. Func_water is a skin setting within func_illusionary. It is related and is the same bug.

SamVanheer commented 3 years ago

No, func_water is the same entity as func_door: https://github.com/ValveSoftware/halflife/blob/c7240b965743a53a29491dd49320c88eecf6257b/dlls/doors.cpp#L272-L276

func_illusionary is a separate entity with solid set to SOLID_NOT: https://github.com/ValveSoftware/halflife/blob/c7240b965743a53a29491dd49320c88eecf6257b/dlls/bmodels.cpp#L234

Both overload skin to tell the engine and movement code that it uses custom contents (ladders do that as well), but they don't use the same code in the entity aspect of things: https://github.com/ValveSoftware/halflife/blob/c7240b965743a53a29491dd49320c88eecf6257b/dlls/doors.cpp#L198-L202 https://github.com/ValveSoftware/halflife/blob/c7240b965743a53a29491dd49320c88eecf6257b/dlls/bmodels.cpp#L221-L225

The movement code checks if you're in water here: https://github.com/ValveSoftware/halflife/blob/c7240b965743a53a29491dd49320c88eecf6257b/pm_shared/pm_shared.c#L1489

Which eventually returns skin if the player is standing in an entity.

It's possible for other entities to use custom contents types. I haven't tested it, but you could perhaps even use it on entities that use studio models.

Any entity that uses water textures will experience the bug reported in this issue. If it's not using water textures then it's a different bug. It's possible for a func_water entity to be textured with regular textures which renders just fine when the same entity with water textures would not.

The bug you're describing sounds like the entity's bounds aren't intersecting with the view frustum which causes it to disappear, but that is still a separate issue.

djearthquake commented 3 years ago

Func_illusionary contents can be water, slime, lava, ladder, even the default volumetric light. Thank you for reminding me about the 256 limit. That has helped tremendously.