Skip to content

Commit 06c1680

Browse files
authored
[Terrain] Suppress ADT liquid inside WMO interior groups (#313)
FusedTerrain::ColumnAt added tile (ADT) liquid unconditionally, and getLiquidStatus always took the column's highest liquid surface. In Vashj'ir, L'ghorek's air-pocket interior sits ~700yd under the ocean surface, so that outside water always won and bots inside the dome were reported UNDER_WATER despite standing in a dry interior. No code in the liquid path consulted MOGP interior flags. Tag ADT liquid surfaces (Column::Surface::fromAdt, set via FusedTerrain.cpp's AddLiquid(*adt, true) call), add Column::HighestLiquid(bool includeAdt) and Column::HasStatic(), and in getLiquidStatus: when the winning surface is ADT-sourced and the column also has a baked model, raycast for the group's mogpFlags via GetAreaInfo and drop the ADT surface if the interior bit (0x2000) is set, falling back to whatever liquid the WMO itself carries. Zero extra cost outside a WMO footprint (HasStatic() false). Server side only, no re-bake needed -- interior flags are already baked.
1 parent 171c9f0 commit 06c1680

3 files changed

Lines changed: 44 additions & 5 deletions

File tree

src/game/WorldHandlers/GridMap.cpp

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,11 @@ namespace
8282
const uint32 LIQUID_OUTLAND_OCEAN_ROW = 15;
8383
const uint32 LIQUID_FIRST_OVERRIDABLE_ROW = 21;
8484

85+
// MOGP group flag: the group is an interior. Outside (ADT) liquid must not
86+
// reach a point inside one -- Vashj'ir's L'ghorek air pocket, a dry hold
87+
// under the sea -- only liquid the WMO itself carries counts there.
88+
const uint32 MOGP_FLAG_INTERIOR = 0x2000;
89+
8590
// LiquidType.dbc SoundBank is the family the client uses (0 water .. 3 slime), and
8691
// MAP_LIQUID_TYPE_* is one bit per family in that order. The DBC is the authority:
8792
// the tile carries the row id, never a pre-chewed category.
@@ -352,11 +357,28 @@ GridMapLiquidStatus TerrainInfo::getLiquidStatus(float x, float y, float z,
352357
const world::terrain::Column column =
353358
ColumnAt(x, y, z + FLOOR_BURIED_LIFT, z - FLOOR_SEARCH_DOWN);
354359

355-
const auto liquid = column.HighestLiquid();
360+
auto liquid = column.HighestLiquid();
356361
if (!liquid || !liquid->liquidEntry)
357362
{
358363
return LIQUID_MAP_NO_WATER;
359364
}
365+
366+
// Tile liquid is the OUTSIDE water. When the point sits inside a WMO
367+
// interior group, drop it and keep only what the model itself carries.
368+
if (liquid->fromAdt && column.HasStatic())
369+
{
370+
uint32 mogpFlags = 0;
371+
int32 adtId = 0, rootId = 0, groupId = 0;
372+
if (GetAreaInfo(x, y, z, mogpFlags, adtId, rootId, groupId) &&
373+
(mogpFlags & MOGP_FLAG_INTERIOR))
374+
{
375+
liquid = column.HighestLiquid(false);
376+
if (!liquid || !liquid->liquidEntry)
377+
{
378+
return LIQUID_MAP_NO_WATER;
379+
}
380+
}
381+
}
360382
const LiquidInfo info = liquid->AsLiquid();
361383

362384
uint32 entry = info.entry;

src/shared/terrain/Column.hpp

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ namespace world::terrain
2929
LiquidKind liquid = LiquidKind::None;
3030
uint16_t liquidEntry = 0;
3131
bool deep = false;
32+
bool fromAdt = false; ///< tile (ADT) liquid, not carried by a model
3233

3334
bool Solid() const { return kind != SurfaceKind::Liquid; }
3435

@@ -54,14 +55,15 @@ namespace world::terrain
5455
m_surfaces.push_back(s);
5556
}
5657

57-
void AddLiquid(const LiquidInfo& info)
58+
void AddLiquid(const LiquidInfo& info, bool fromAdt = false)
5859
{
5960
Surface s;
6061
s.z = info.level;
6162
s.kind = SurfaceKind::Liquid;
6263
s.liquid = info.kind;
6364
s.liquidEntry = info.entry;
6465
s.deep = info.deep;
66+
s.fromAdt = fromAdt;
6567
m_surfaces.push_back(s);
6668
}
6769

@@ -118,19 +120,34 @@ namespace world::terrain
118120
return LowestSolidAbove(z + tolerance);
119121
}
120122

121-
std::optional<Surface> HighestLiquid() const
123+
std::optional<Surface> HighestLiquid(bool includeAdt = true) const
122124
{
123125
std::optional<Surface> best;
124126
for (const Surface& s : m_surfaces)
125127
{
126-
if (s.kind == SurfaceKind::Liquid && (!best || s.z > best->z))
128+
if (s.kind == SurfaceKind::Liquid &&
129+
(includeAdt || !s.fromAdt) && (!best || s.z > best->z))
127130
{
128131
best = s;
129132
}
130133
}
131134
return best;
132135
}
133136

137+
/// Whether any baked model surface lies in the sweep -- the cheap
138+
/// pre-test for "could this point be inside a WMO at all".
139+
bool HasStatic() const
140+
{
141+
for (const Surface& s : m_surfaces)
142+
{
143+
if (s.kind == SurfaceKind::Static)
144+
{
145+
return true;
146+
}
147+
}
148+
return false;
149+
}
150+
134151
private:
135152
std::vector<Surface> m_surfaces;
136153
};

src/shared/terrain/FusedTerrain.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ namespace world::terrain
345345
{
346346
if (auto adt = tile->LiquidAt(x, y))
347347
{
348-
column.AddLiquid(*adt);
348+
column.AddLiquid(*adt, true);
349349
}
350350
}
351351

0 commit comments

Comments
 (0)