diff --git a/qbsp/brush.cc b/qbsp/brush.cc index 1575542c..b88cdafd 100644 --- a/qbsp/brush.cc +++ b/qbsp/brush.cc @@ -687,30 +687,14 @@ static void Brush_LoadEntity(mapentity_t &dst, mapentity_t &src, hull_index_t hu } } - /* _mirrorinside key (for func_water etc.) */ - std::optional mirrorinside; - - if (src.epairs.has("_mirrorinside")) { - mirrorinside = src.epairs.get_int("_mirrorinside") ? true : false; - } - - /* _noclipfaces */ - std::optional clipsametype; - - if (src.epairs.has("_noclipfaces")) { - clipsametype = src.epairs.get_int("_noclipfaces") ? false : true; - } - - const bool func_illusionary_visblocker = (0 == Q_strcasecmp(classname, "func_illusionary_visblocker")); - - auto it = src.mapbrushes.begin(); - - for (size_t i = 0; i < src.mapbrushes.size(); i++, it++) { + for (auto &mapbrush : src.mapbrushes) { clock(); - auto &mapbrush = *it; contentflags_t contents = mapbrush.contents; + /* "origin" brushes always discarded beforehand */ + Q_assert(!contents.is_origin(qbsp_options.target_game)); + // per-brush settings bool detail = false; bool detail_illusionary = false; @@ -721,10 +705,6 @@ static void Brush_LoadEntity(mapentity_t &dst, mapentity_t &src, hull_index_t hu detail_illusionary |= all_detail_illusionary; detail_fence |= all_detail_fence; - /* "origin" brushes always discarded */ - if (contents.is_origin(qbsp_options.target_game)) - continue; - /* -omitdetail option omits all types of detail */ if (qbsp_options.omitdetail.value() && detail) continue; @@ -787,25 +767,27 @@ static void Brush_LoadEntity(mapentity_t &dst, mapentity_t &src, hull_index_t hu before writing the bsp, and bmodels normally have CONTENTS_SOLID as their contents type. */ - if (!hullnum.value_or(0) && mirrorinside.value_or(false)) { + if (!hullnum.value_or(0) && contents.is_mirrored(qbsp_options.target_game)) { contents = qbsp_options.target_game->create_detail_fence_contents(contents); } } if (hullnum.value_or(0)) { /* nonsolid brushes don't show up in clipping hulls */ - if (!contents.is_any_solid(qbsp_options.target_game) && !contents.is_sky(qbsp_options.target_game)) + if (!contents.is_any_solid(qbsp_options.target_game) && !contents.is_sky(qbsp_options.target_game)) { continue; + } /* sky brushes are solid in the collision hulls */ - if (contents.is_sky(qbsp_options.target_game)) + if (contents.is_sky(qbsp_options.target_game)) { contents = qbsp_options.target_game->create_solid_contents(); + } } - // apply extended flags - contents.set_mirrored(mirrorinside); - contents.set_clips_same_type(clipsametype); - contents.illusionary_visblocker = func_illusionary_visblocker; + // fixme-brushbsp: function calls above can override the values below + // so we have to re-set them to be sure they stay what the mapper intended.. + contents.set_mirrored(mapbrush.contents.mirror_inside); + contents.set_clips_same_type(mapbrush.contents.clips_same_type); auto brush = LoadBrush(src, mapbrush, contents, hullnum, num_clipped); diff --git a/qbsp/map.cc b/qbsp/map.cc index 97d59363..44ce10f8 100644 --- a/qbsp/map.cc +++ b/qbsp/map.cc @@ -2064,7 +2064,7 @@ Brush_GetContents Fetch the final contents flag of the given mapbrush. ================= */ -static contentflags_t Brush_GetContents(const mapbrush_t &mapbrush) +static contentflags_t Brush_GetContents(const mapentity_t &entity, const mapbrush_t &mapbrush) { bool base_contents_set = false; contentflags_t base_contents = qbsp_options.target_game->create_empty_contents(); @@ -2096,6 +2096,25 @@ static contentflags_t Brush_GetContents(const mapbrush_t &mapbrush) // make sure we found a valid type Q_assert(base_contents.is_valid(qbsp_options.target_game, false)); + // extended flags + if (entity.epairs.has("_mirrorinside")) { + base_contents.set_mirrored(entity.epairs.get_int("_mirrorinside") ? true : false); + } else { + // fixme-brushbsp: this shouldn't be necessary, but Q1's game contents + // store these as booleans and not trinaries + base_contents.set_mirrored(std::nullopt); + } + + if (entity.epairs.has("_noclipfaces")) { + base_contents.set_clips_same_type(entity.epairs.get_int("_noclipfaces") ? false : true); + } else { + // fixme-brushbsp: this shouldn't be necessary, but Q1's game contents + // store these as booleans and not trinaries + base_contents.set_clips_same_type(std::nullopt); + } + + base_contents.illusionary_visblocker = string_iequals(entity.epairs.get("classname"), "func_illusionary_visblocker"); + return base_contents; } @@ -2173,7 +2192,7 @@ static mapbrush_t ParseBrush(parser_t &parser, mapentity_t &entity) } // ericw -- end brush primitives - brush.contents = Brush_GetContents(brush); + brush.contents = Brush_GetContents(entity, brush); return brush; }