diff --git a/common/bspfile.cc b/common/bspfile.cc index f155b9e0..fa0eac55 100644 --- a/common/bspfile.cc +++ b/common/bspfile.cc @@ -109,7 +109,7 @@ private: // todo: this should be the only state inside a contentflags_t in q1 mode. struct q1_contentflags_bits { - using bitset_t = std::bitset<14>; + using bitset_t = std::bitset<15>; // visible contents bool solid = false; @@ -129,6 +129,7 @@ private: // content flags bool detail = false; bool mirror_inside = false; + bool mirror_inside_set = false; // whether to use mirror_inside (if false, use content default) bool suppress_clipping_same_type = false; constexpr size_t last_visible_contents() const { return 7; } @@ -148,7 +149,8 @@ private: result[10] = illusionary_visblocker; result[11] = detail; result[12] = mirror_inside; - result[13] = suppress_clipping_same_type; + result[13] = mirror_inside_set; + result[14] = suppress_clipping_same_type; return result; } @@ -167,12 +169,13 @@ private: illusionary_visblocker(bitset[10]), detail(bitset[11]), mirror_inside(bitset[12]), - suppress_clipping_same_type(bitset[13]) + mirror_inside_set(bitset[13]), + suppress_clipping_same_type(bitset[14]) { } static constexpr const char *bitflag_names[] = {"SOLID", "SKY", "WALL", "FENCE", "LAVA", "SLIME", "WATER", - "MIST", "ORIGIN", "CLIP", "ILLUSIONARY_VISBLOCKER", "DETAIL", "MIRROR_INSIDE", + "MIST", "ORIGIN", "CLIP", "ILLUSIONARY_VISBLOCKER", "DETAIL", "MIRROR_INSIDE", "MIRROR_INSIDE_SET", "SUPPRESS_CLIPPING_SAME_TYPE"}; constexpr bool operator[](size_t index) const @@ -191,7 +194,8 @@ private: case 10: return illusionary_visblocker; case 11: return detail; case 12: return mirror_inside; - case 13: return suppress_clipping_same_type; + case 13: return mirror_inside_set; + case 14: return suppress_clipping_same_type; default: throw std::out_of_range("index"); } } @@ -212,7 +216,8 @@ private: case 10: return illusionary_visblocker; case 11: return detail; case 12: return mirror_inside; - case 13: return suppress_clipping_same_type; + case 13: return mirror_inside_set; + case 14: return suppress_clipping_same_type; default: throw std::out_of_range("index"); } } @@ -270,6 +275,7 @@ private: // clear flags this_test.detail = false; this_test.mirror_inside = false; + this_test.mirror_inside_set = false; this_test.suppress_clipping_same_type = false; q1_contentflags_bits empty_test; @@ -300,6 +306,7 @@ private: result.detail = data.is_detail; result.illusionary_visblocker = contents.illusionary_visblocker; + result.mirror_inside_set = contents.mirror_inside.has_value(); result.mirror_inside = contents.mirror_inside.value_or(false); result.suppress_clipping_same_type = !contents.clips_same_type.value_or(true); @@ -339,7 +346,11 @@ private: } result.illusionary_visblocker = bits.illusionary_visblocker; - result.mirror_inside = bits.mirror_inside; + if (bits.mirror_inside_set) { + result.mirror_inside = bits.mirror_inside; + } else { + result.mirror_inside = std::nullopt; + } result.clips_same_type = !bits.suppress_clipping_same_type; return result; @@ -471,6 +482,13 @@ public: return contentflags_from_bits(bits); } + contentflags_t set_detail(const contentflags_t &original) const override + { + auto bits = contentflags_to_bits(original); + bits.detail = true; + return contentflags_from_bits(bits); + } + bool contents_are_type_equal(const contentflags_t &self, const contentflags_t &other) const override { // fixme-brushbsp: document what this is supposed to do, remove if unneeded? @@ -1126,6 +1144,13 @@ struct gamedef_q2_t : public gamedef_t return result; } + contentflags_t set_detail(const contentflags_t &original) const override + { + contentflags_t result = original; + result.native |= Q2_CONTENTS_DETAIL; + return result; + } + bool contents_are_type_equal(const contentflags_t &self, const contentflags_t &other) const override { return self.illusionary_visblocker == other.illusionary_visblocker && diff --git a/include/common/bspfile.hh b/include/common/bspfile.hh index bf008470..a0a96e24 100644 --- a/include/common/bspfile.hh +++ b/include/common/bspfile.hh @@ -278,6 +278,7 @@ struct gamedef_t virtual contentflags_t create_detail_wall_contents(const contentflags_t &original) const = 0; virtual contentflags_t create_detail_solid_contents(const contentflags_t &original) const = 0; virtual contentflags_t clear_detail(const contentflags_t &original) const = 0; + virtual contentflags_t set_detail(const contentflags_t &original) const = 0; virtual bool contents_are_type_equal(const contentflags_t &self, const contentflags_t &other) const = 0; virtual bool contents_are_equal(const contentflags_t &self, const contentflags_t &other) const = 0; virtual bool contents_are_any_detail(const contentflags_t &contents) const = 0; diff --git a/qbsp/map.cc b/qbsp/map.cc index 3d3a866d..bfba543e 100644 --- a/qbsp/map.cc +++ b/qbsp/map.cc @@ -2473,6 +2473,13 @@ static contentflags_t Brush_GetContents(const mapentity_t &entity, const mapbrus base_contents.illusionary_visblocker = string_iequals(entity.epairs.get("classname"), "func_illusionary_visblocker"); + // non-Q2: -transwater implies liquids are detail + if (qbsp_options.target_game->id != GAME_QUAKE_II && qbsp_options.transwater.value()) { + if (base_contents.is_liquid(qbsp_options.target_game)) { + base_contents = qbsp_options.target_game->set_detail(base_contents); + } + } + return base_contents; } diff --git a/testmaps/q1_liquid_is_detail.map b/testmaps/q1_liquid_is_detail.map new file mode 100644 index 00000000..1927215b --- /dev/null +++ b/testmaps/q1_liquid_is_detail.map @@ -0,0 +1,275 @@ +// Game: Quake +// Format: Valve +// entity 0 +{ +"mapversion" "220" +"classname" "worldspawn" +"wad" "deprecated/free_wad.wad;deprecated/hintskip.wad" +// brush 0 +{ +( 184 112 168 ) ( 184 -432 168 ) ( 184 112 -64 ) bolt17 [ 0 1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( 192 -432 -64 ) ( 184 -432 -64 ) ( 192 -432 168 ) bolt17 [ 1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( 192 112 -64 ) ( 184 112 -64 ) ( 192 -432 -64 ) bolt17 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( 192 -432 168 ) ( 184 -432 168 ) ( 192 112 168 ) bolt17 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( 192 112 168 ) ( 184 112 168 ) ( 192 112 -64 ) bolt17 [ -1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( 192 -432 168 ) ( 192 112 168 ) ( 192 -432 -64 ) bolt17 [ 0 1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +} +// brush 1 +{ +( -168 112 168 ) ( -168 104 168 ) ( -168 112 -64 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( 184 104 168 ) ( 184 104 -64 ) ( -168 104 168 ) bolt17 [ -1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -168 112 -64 ) ( -168 104 -64 ) ( 184 112 -64 ) bolt17 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( 184 112 168 ) ( 184 104 168 ) ( -168 112 168 ) bolt17 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( 184 112 168 ) ( -168 112 168 ) ( 184 112 -64 ) bolt17 [ -1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( 184 112 -64 ) ( 184 104 -64 ) ( 184 112 168 ) bolt17 [ 0 1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +} +// brush 2 +{ +( -168 -432 -64 ) ( -168 -424 -64 ) ( -168 -432 168 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( 184 -432 -64 ) ( -168 -432 -64 ) ( 184 -432 168 ) bolt17 [ 1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( 184 -432 -64 ) ( 184 -424 -64 ) ( -168 -432 -64 ) bolt17 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -168 -432 168 ) ( -168 -424 168 ) ( 184 -432 168 ) bolt17 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -168 -424 -64 ) ( 184 -424 -64 ) ( -168 -424 168 ) bolt17 [ 1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( 184 -432 168 ) ( 184 -424 168 ) ( 184 -432 -64 ) bolt17 [ 0 1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +} +// brush 3 +{ +( -168 -424 168 ) ( -168 -424 160 ) ( -168 104 168 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( 184 -424 168 ) ( 184 -424 160 ) ( -168 -424 168 ) bolt17 [ 1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( 184 104 160 ) ( -168 104 160 ) ( 184 -424 160 ) bolt17 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( 184 104 168 ) ( 184 -424 168 ) ( -168 104 168 ) bolt17 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -168 104 168 ) ( -168 104 160 ) ( 184 104 168 ) bolt17 [ -1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( 184 104 168 ) ( 184 104 160 ) ( 184 -424 168 ) bolt17 [ 0 1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +} +// brush 4 +{ +( -168 104 -64 ) ( -168 104 -56 ) ( -168 -424 -64 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -168 -424 -64 ) ( -168 -424 -56 ) ( 184 -424 -64 ) bolt17 [ 1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -168 104 -64 ) ( -168 -424 -64 ) ( 184 104 -64 ) bolt17 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -168 -424 -56 ) ( -168 104 -56 ) ( 184 -424 -56 ) bolt17 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( 184 104 -64 ) ( 184 104 -56 ) ( -168 104 -64 ) bolt17 [ -1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( 184 -424 -64 ) ( 184 -424 -56 ) ( 184 104 -64 ) bolt17 [ 0 1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +} +// brush 5 +{ +( -304 104 -48 ) ( -304 104 -40 ) ( -304 -424 -48 ) *swater4 [ 0 -1 0 0 ] [ 0 0 -1 48 ] 0 1 1 +( -168 -424 -48 ) ( -168 -424 -40 ) ( 184 -424 -48 ) *swater4 [ 1 0 0 0 ] [ 0 0 -1 48 ] 0 1 1 +( -168 104 -56 ) ( -168 -424 -56 ) ( 184 104 -56 ) *swater4 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -168 -424 48 ) ( -168 104 48 ) ( 184 -424 48 ) *swater4 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( 184 104 -48 ) ( 184 104 -40 ) ( -168 104 -48 ) *swater4 [ -1 0 0 0 ] [ 0 0 -1 48 ] 0 1 1 +( 184 -424 -48 ) ( 184 -424 -40 ) ( 184 104 -48 ) *swater4 [ 0 1 0 0 ] [ 0 0 -1 48 ] 0 1 1 +} +// brush 6 +{ +( -176 -432 -64 ) ( -176 112 -64 ) ( -176 -432 168 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -168 -320 0 ) ( -168 -320 16 ) ( -40 -320 16 ) bolt17 [ 1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -176 -432 -64 ) ( -168 -432 -64 ) ( -176 112 -64 ) bolt17 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -168 -384 -32 ) ( -168 -368 -32 ) ( -40 -368 -32 ) bolt17 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -176 112 -64 ) ( -168 112 -64 ) ( -176 112 168 ) bolt17 [ -1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -168 -432 -64 ) ( -168 -432 168 ) ( -168 112 -64 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +} +// brush 7 +{ +( -176 -432 -64 ) ( -176 112 -64 ) ( -176 -432 168 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -168 -320 0 ) ( -168 -320 16 ) ( -40 -320 16 ) bolt17 [ 1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -168 -384 -32 ) ( -40 -368 -32 ) ( -168 -368 -32 ) bolt17 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -168 -384 32 ) ( -168 -368 32 ) ( -40 -368 32 ) bolt17 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -176 112 -64 ) ( -168 112 -64 ) ( -176 112 168 ) bolt17 [ -1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -168 -432 -64 ) ( -168 -432 168 ) ( -168 112 -64 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +} +// brush 8 +{ +( -176 -432 -64 ) ( -176 112 -64 ) ( -176 -432 168 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -168 -384 -16 ) ( -168 -384 0 ) ( -40 -384 0 ) bolt17 [ 1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -176 -432 -64 ) ( -168 -432 -64 ) ( -176 112 -64 ) bolt17 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -168 -384 -32 ) ( -168 -368 -32 ) ( -40 -368 -32 ) bolt17 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -168 -320 0 ) ( -40 -320 16 ) ( -168 -320 16 ) bolt17 [ -1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -168 -432 -64 ) ( -168 -432 168 ) ( -168 112 -64 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +} +// brush 9 +{ +( -304 -432 -64 ) ( -304 112 -64 ) ( -304 -432 168 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -296 -384 -16 ) ( -296 -384 0 ) ( -168 -384 0 ) bolt17 [ 1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -296 -384 -32 ) ( -168 -368 -32 ) ( -296 -368 -32 ) bolt17 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -296 -384 32 ) ( -296 -368 32 ) ( -168 -368 32 ) bolt17 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -296 -320 0 ) ( -168 -320 16 ) ( -296 -320 16 ) bolt17 [ -1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -296 -432 -64 ) ( -296 -432 168 ) ( -296 112 -64 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +} +// brush 10 +{ +( -176 -432 -64 ) ( -176 112 -64 ) ( -176 -432 168 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -168 -384 -16 ) ( -168 -384 0 ) ( -40 -384 0 ) bolt17 [ 1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -168 -384 32 ) ( -40 -368 32 ) ( -168 -368 32 ) bolt17 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -176 112 168 ) ( -168 112 168 ) ( -176 -432 168 ) bolt17 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -168 -320 0 ) ( -40 -320 16 ) ( -168 -320 16 ) bolt17 [ -1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -168 -432 -64 ) ( -168 -432 168 ) ( -168 112 -64 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +} +// brush 11 +{ +( -176 -432 -64 ) ( -176 112 -64 ) ( -176 -432 168 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -176 -432 168 ) ( -168 -432 168 ) ( -176 -432 -64 ) bolt17 [ 1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -176 -432 -64 ) ( -168 -432 -64 ) ( -176 112 -64 ) bolt17 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -168 -384 -32 ) ( -168 -368 -32 ) ( -40 -368 -32 ) bolt17 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -168 -384 -16 ) ( -40 -384 0 ) ( -168 -384 0 ) bolt17 [ -1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -168 -432 -64 ) ( -168 -432 168 ) ( -168 112 -64 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +} +// brush 12 +{ +( -176 -432 -64 ) ( -176 112 -64 ) ( -176 -432 168 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -176 -432 168 ) ( -168 -432 168 ) ( -176 -432 -64 ) bolt17 [ 1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -168 -384 -32 ) ( -40 -368 -32 ) ( -168 -368 -32 ) bolt17 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -168 -384 32 ) ( -168 -368 32 ) ( -40 -368 32 ) bolt17 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -168 -384 -16 ) ( -40 -384 0 ) ( -168 -384 0 ) bolt17 [ -1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -168 -432 -64 ) ( -168 -432 168 ) ( -168 112 -64 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +} +// brush 13 +{ +( -176 -432 -64 ) ( -176 112 -64 ) ( -176 -432 168 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -176 -432 168 ) ( -168 -432 168 ) ( -176 -432 -64 ) bolt17 [ 1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -168 -384 32 ) ( -40 -368 32 ) ( -168 -368 32 ) bolt17 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -176 112 168 ) ( -168 112 168 ) ( -176 -432 168 ) bolt17 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -168 -384 -16 ) ( -40 -384 0 ) ( -168 -384 0 ) bolt17 [ -1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -168 -432 -64 ) ( -168 -432 168 ) ( -168 112 -64 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +} +// brush 14 +{ +( -304 -432 -64 ) ( -304 112 -64 ) ( -304 -432 168 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -296 -320 0 ) ( -296 -320 16 ) ( -168 -320 16 ) bolt17 [ -1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -296 -384 -32 ) ( -168 -368 -32 ) ( -296 -368 -32 ) bolt17 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -296 -384 32 ) ( -296 -368 32 ) ( -168 -368 32 ) bolt17 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -296 -312 0 ) ( -168 -312 16 ) ( -296 -312 16 ) bolt17 [ -1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -176 -432 -64 ) ( -176 -432 168 ) ( -176 112 -64 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +} +// brush 15 +{ +( -304 -432 -64 ) ( -304 112 -64 ) ( -304 -432 168 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -296 -392 -16 ) ( -296 -392 0 ) ( -168 -392 0 ) bolt17 [ 1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -296 -384 -32 ) ( -168 -368 -32 ) ( -296 -368 -32 ) bolt17 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -296 -384 32 ) ( -296 -368 32 ) ( -168 -368 32 ) bolt17 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -296 -384 -16 ) ( -168 -384 0 ) ( -296 -384 0 ) bolt17 [ 1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -176 -432 -64 ) ( -176 -432 168 ) ( -176 112 -64 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +} +// brush 16 +{ +( -304 -432 -64 ) ( -304 112 -64 ) ( -304 -432 168 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -296 -384 -16 ) ( -296 -384 0 ) ( -168 -384 0 ) bolt17 [ 1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -296 -384 32 ) ( -168 -368 32 ) ( -296 -368 32 ) bolt17 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -296 -384 40 ) ( -296 -368 40 ) ( -168 -368 40 ) bolt17 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -296 -320 0 ) ( -168 -320 16 ) ( -296 -320 16 ) bolt17 [ -1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -176 -432 -64 ) ( -176 -432 168 ) ( -176 112 -64 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +} +// brush 17 +{ +( -304 -432 -64 ) ( -304 112 -64 ) ( -304 -432 168 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -296 -384 -16 ) ( -296 -384 0 ) ( -168 -384 0 ) bolt17 [ 1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -296 -384 -40 ) ( -168 -368 -40 ) ( -296 -368 -40 ) bolt17 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -296 -384 -32 ) ( -296 -368 -32 ) ( -168 -368 -32 ) bolt17 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -296 -320 0 ) ( -168 -320 16 ) ( -296 -320 16 ) bolt17 [ -1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -176 -432 -64 ) ( -176 -432 168 ) ( -176 112 -64 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +} +// brush 18 +{ +( -304 -112 64 ) ( -304 432 64 ) ( -304 -112 296 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -296 -64 112 ) ( -296 -64 128 ) ( -168 -64 128 ) bolt17 [ 1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -296 -64 160 ) ( -168 -48 160 ) ( -296 -48 160 ) bolt17 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -296 -64 168 ) ( -296 -48 168 ) ( -168 -48 168 ) bolt17 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -296 0 128 ) ( -168 0 144 ) ( -296 0 144 ) bolt17 [ -1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -176 -112 64 ) ( -176 -112 296 ) ( -176 432 64 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +} +// brush 19 +{ +( -304 -112 64 ) ( -304 432 64 ) ( -304 -112 296 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -296 -72 112 ) ( -296 -72 128 ) ( -168 -72 128 ) bolt17 [ 1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -296 -64 96 ) ( -168 -48 96 ) ( -296 -48 96 ) bolt17 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -296 -64 160 ) ( -296 -48 160 ) ( -168 -48 160 ) bolt17 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -296 -64 112 ) ( -168 -64 128 ) ( -296 -64 128 ) bolt17 [ 1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -176 -112 64 ) ( -176 -112 296 ) ( -176 432 64 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +} +// brush 20 +{ +( -304 -112 64 ) ( -304 432 64 ) ( -304 -112 296 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -296 -64 112 ) ( -296 -64 128 ) ( -168 -64 128 ) bolt17 [ 1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -296 -64 96 ) ( -168 -48 96 ) ( -296 -48 96 ) bolt17 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -296 -64 160 ) ( -296 -48 160 ) ( -168 -48 160 ) bolt17 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -296 0 128 ) ( -168 0 144 ) ( -296 0 144 ) bolt17 [ -1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -296 -112 64 ) ( -296 -112 296 ) ( -296 432 64 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +} +// brush 21 +{ +( -304 -112 64 ) ( -304 432 64 ) ( -304 -112 296 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -296 0 128 ) ( -296 0 144 ) ( -168 0 144 ) bolt17 [ -1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -296 -64 96 ) ( -168 -48 96 ) ( -296 -48 96 ) bolt17 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -296 -64 160 ) ( -296 -48 160 ) ( -168 -48 160 ) bolt17 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -296 8 128 ) ( -168 8 144 ) ( -296 8 144 ) bolt17 [ -1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -176 -112 64 ) ( -176 -112 296 ) ( -176 432 64 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +} +// brush 22 +{ +( -304 -112 64 ) ( -304 432 64 ) ( -304 -112 296 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -296 -64 112 ) ( -296 -64 128 ) ( -168 -64 128 ) bolt17 [ 1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -296 -64 88 ) ( -168 -48 88 ) ( -296 -48 88 ) bolt17 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -296 -64 96 ) ( -296 -48 96 ) ( -168 -48 96 ) bolt17 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -296 0 128 ) ( -168 0 144 ) ( -296 0 144 ) bolt17 [ -1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -176 -112 64 ) ( -176 -112 296 ) ( -176 432 64 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +} +// brush 23 +{ +( -176 -432 -64 ) ( -176 112 -64 ) ( -176 -432 168 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -168 0 72 ) ( -168 0 96 ) ( -40 0 96 ) bolt17 [ 1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -168 -384 32 ) ( -40 -368 32 ) ( -168 -368 32 ) bolt17 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -168 -64 96 ) ( -168 -40 96 ) ( -40 -40 96 ) bolt17 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -176 112 -64 ) ( -168 112 -64 ) ( -176 112 168 ) bolt17 [ -1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -168 -432 -64 ) ( -168 -432 168 ) ( -168 112 -64 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +} +// brush 24 +{ +( -176 -432 -64 ) ( -176 112 -64 ) ( -176 -432 168 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -168 0 72 ) ( -168 0 96 ) ( -40 0 96 ) bolt17 [ 1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -168 -64 96 ) ( -40 -40 96 ) ( -168 -40 96 ) bolt17 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -176 112 168 ) ( -168 112 168 ) ( -176 -432 168 ) bolt17 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -176 112 -64 ) ( -168 112 -64 ) ( -176 112 168 ) bolt17 [ -1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -168 -432 -64 ) ( -168 -432 168 ) ( -168 112 -64 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +} +// brush 25 +{ +( -176 -432 -64 ) ( -176 112 -64 ) ( -176 -432 168 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -168 -64 120 ) ( -168 -64 136 ) ( -40 -64 136 ) bolt17 [ 1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -168 -384 32 ) ( -40 -368 32 ) ( -168 -368 32 ) bolt17 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -168 -64 96 ) ( -168 -40 96 ) ( -40 -40 96 ) bolt17 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -168 0 72 ) ( -40 0 96 ) ( -168 0 96 ) bolt17 [ -1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -168 -432 -64 ) ( -168 -432 168 ) ( -168 112 -64 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +} +// brush 26 +{ +( -176 -432 -64 ) ( -176 112 -64 ) ( -176 -432 168 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -168 -320 0 ) ( -168 -320 16 ) ( -40 -320 16 ) bolt17 [ 1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -168 -384 32 ) ( -40 -368 32 ) ( -168 -368 32 ) bolt17 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -168 -64 96 ) ( -168 -40 96 ) ( -40 -40 96 ) bolt17 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -168 -64 120 ) ( -40 -64 136 ) ( -168 -64 136 ) bolt17 [ -1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -168 -432 -64 ) ( -168 -432 168 ) ( -168 112 -64 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +} +// brush 27 +{ +( -176 -432 -64 ) ( -176 112 -64 ) ( -176 -432 168 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -168 -320 0 ) ( -168 -320 16 ) ( -40 -320 16 ) bolt17 [ 1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -168 -64 96 ) ( -40 -40 96 ) ( -168 -40 96 ) bolt17 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -176 112 168 ) ( -168 112 168 ) ( -176 -432 168 ) bolt17 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -168 -64 120 ) ( -40 -64 136 ) ( -168 -64 136 ) bolt17 [ -1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -168 -432 -64 ) ( -168 -432 168 ) ( -168 112 -64 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +} +// brush 28 +{ +( -176 -432 -64 ) ( -176 112 -64 ) ( -176 -432 168 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -168 -64 120 ) ( -168 -64 136 ) ( -40 -64 136 ) bolt17 [ -1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -168 -64 160 ) ( -40 -40 160 ) ( -168 -40 160 ) bolt17 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -176 112 168 ) ( -168 112 168 ) ( -176 -432 168 ) bolt17 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -168 0 120 ) ( -40 0 136 ) ( -168 0 136 ) bolt17 [ -1 0 0 0 ] [ 0 0 -1 32 ] 0 1 1 +( -168 -432 -64 ) ( -168 -432 168 ) ( -168 112 -64 ) bolt17 [ 0 -1 0 0 ] [ 0 0 -1 32 ] 0 1 1 +} +} +// entity 1 +{ +"classname" "info_player_start" +"origin" "-96 -304 -24" +"angle" "90" +} diff --git a/tests/test_qbsp.cc b/tests/test_qbsp.cc index 6e672055..979d85fe 100644 --- a/tests/test_qbsp.cc +++ b/tests/test_qbsp.cc @@ -2324,3 +2324,46 @@ TEST_CASE("q1_tjunc_matrix") CHECK( has_tjunc(INDEX_SKY, INDEX_SKY)); } } + +TEST_CASE("q1_liquid_is_detail" * doctest::test_suite("testmaps_q1")) +{ + const auto portal_underwater = prtfile_winding_t{{-168, -384, 32}, {-168, -320, 32}, {-168, -320, -32}, {-168, -384, -32}}; + const auto portal_above = portal_underwater.translate({0, 320, 128}); + + SUBCASE("transparent water") { + // by default, we're compiling with transparent water + // this implies water is detail + + const auto [bsp, bspx, prt] = LoadTestmapQ1("q1_liquid_is_detail.map"); + + REQUIRE(prt.has_value()); + REQUIRE(2 == prt->portals.size()); + + CHECK(((PortalMatcher(prt->portals[0].winding, portal_underwater) && PortalMatcher(prt->portals[1].winding, portal_above)) || + (PortalMatcher(prt->portals[0].winding, portal_above) && PortalMatcher(prt->portals[1].winding, portal_underwater)))); + + // only 3 clusters: room with water, side corridors + CHECK(prt->portalleafs == 3); + + // above water, in water, plus 2 side rooms. + // note + CHECK(prt->portalleafs_real == 4); + } + + SUBCASE("opaque water") { + const auto [bsp, bspx, prt] = LoadTestmapQ1("q1_liquid_is_detail.map", {"-notranswater"}); + + REQUIRE(prt.has_value()); + REQUIRE(2 == prt->portals.size()); + + // same portals as transparent water case + // (since the water is opqaue, it doesn't get a portal) + CHECK(((PortalMatcher(prt->portals[0].winding, portal_underwater) && PortalMatcher(prt->portals[1].winding, portal_above)) || + (PortalMatcher(prt->portals[0].winding, portal_above) && PortalMatcher(prt->portals[1].winding, portal_underwater)))); + + // 4 clusters this time: + // above water, in water, plus 2 side rooms. + CHECK(prt->portalleafs == 4); + CHECK(prt->portalleafs_real == 4); + } +}