Refactor patrol area class to new file

This commit is contained in:
Ted John 2022-03-08 00:14:52 +00:00
parent 566bc4d311
commit 90718ca81c
19 changed files with 340 additions and 296 deletions

View File

@ -23,6 +23,7 @@
#include <openrct2/actions/StaffSetPatrolAreaAction.h>
#include <openrct2/config/Config.h>
#include <openrct2/entity/EntityRegistry.h>
#include <openrct2/entity/PatrolArea.h>
#include <openrct2/entity/Staff.h>
#include <openrct2/localisation/Formatter.h>
#include <openrct2/localisation/Localisation.h>
@ -550,7 +551,7 @@ void WindowStaffOverviewDropdown(rct_window* w, rct_widgetindex widgetIndex, int
if (!tool_set(w, widgetIndex, Tool::WalkDown))
{
show_gridlines();
gStaffDrawPatrolAreas = w->number;
SetPatrolAreaToRender(EntityId::FromUnderlying(w->number));
gfx_invalidate_screen();
}
}
@ -1282,7 +1283,7 @@ void WindowStaffOverviewToolAbort(rct_window* w, rct_widgetindex widgetIndex)
else if (widgetIndex == WIDX_PATROL)
{
hide_gridlines();
gStaffDrawPatrolAreas = 0xFFFF;
ClearPatrolAreaToRender();
gfx_invalidate_screen();
}
}

View File

@ -22,6 +22,7 @@
#include <openrct2/drawing/Drawing.h>
#include <openrct2/entity/EntityList.h>
#include <openrct2/entity/EntityRegistry.h>
#include <openrct2/entity/PatrolArea.h>
#include <openrct2/entity/Staff.h>
#include <openrct2/localisation/Formatter.h>
#include <openrct2/localisation/Localisation.h>
@ -141,7 +142,7 @@ public:
if (!tool_set(this, WIDX_STAFF_LIST_SHOW_PATROL_AREA_BUTTON, Tool::Crosshair))
{
show_gridlines();
gStaffDrawPatrolAreas = _selectedTab | 0x8000;
SetPatrolAreaToRender(GetSelectedStaffType());
gfx_invalidate_screen();
}
break;
@ -471,7 +472,7 @@ public:
{
hide_gridlines();
tool_cancel();
gStaffDrawPatrolAreas = 0xFFFF;
ClearPatrolAreaToRender();
gfx_invalidate_screen();
}
}
@ -593,7 +594,7 @@ private:
if (footpathCoords.IsNull())
return nullptr;
auto isPatrolAreaSet = staff_is_patrol_area_set_for_type(GetSelectedStaffType(), footpathCoords);
auto isPatrolAreaSet = IsPatrolAreaSetForStaffType(GetSelectedStaffType(), footpathCoords);
Peep* closestPeep = nullptr;
auto closestPeepDistance = std::numeric_limits<int32_t>::max();

View File

@ -23,6 +23,7 @@
#include "entity/EntityList.h"
#include "entity/EntityRegistry.h"
#include "entity/Guest.h"
#include "entity/PatrolArea.h"
#include "entity/Staff.h"
#include "interface/Viewport.h"
#include "interface/Window_internal.h"
@ -350,7 +351,7 @@ namespace Editor
}
ResetAllEntities();
staff_reset_modes();
UpdateConsolidatedPatrolAreas();
gNumGuestsInPark = 0;
gNumGuestsHeadingForPark = 0;
gNumGuestsInParkLastWeek = 0;

View File

@ -27,6 +27,7 @@
#include "core/FileScanner.h"
#include "core/Path.hpp"
#include "entity/EntityRegistry.h"
#include "entity/PatrolArea.h"
#include "entity/Peep.h"
#include "entity/Staff.h"
#include "interface/Colour.h"
@ -448,7 +449,7 @@ void game_fix_save_vars()
// Fix gParkEntrance locations for which the tile_element no longer exists
fix_park_entrance_locations();
staff_update_greyed_patrol_areas();
UpdateConsolidatedPatrolAreas();
}
void game_load_init()

View File

@ -20,6 +20,7 @@
#include "actions/GameAction.h"
#include "config/Config.h"
#include "entity/EntityRegistry.h"
#include "entity/PatrolArea.h"
#include "entity/Staff.h"
#include "interface/Screenshot.h"
#include "localisation/Date.h"
@ -67,7 +68,7 @@ void GameState::InitAll(const TileCoordsXY& mapSize)
banner_init();
ride_init_all();
ResetAllEntities();
staff_reset_modes();
UpdateConsolidatedPatrolAreas();
date_reset();
climate_reset(ClimateType::CoolAndWet);
News::InitQueue();

View File

@ -10,6 +10,7 @@
#include "StaffSetPatrolAreaAction.h"
#include "../entity/EntityRegistry.h"
#include "../entity/PatrolArea.h"
#include "../entity/Peep.h"
#include "../entity/Staff.h"
#include "../interface/Window.h"
@ -97,7 +98,7 @@ GameActions::Result StaffSetPatrolAreaAction::Execute() const
break;
}
staff_update_greyed_patrol_areas();
UpdateConsolidatedPatrolAreas();
return GameActions::Result();
}

View File

@ -0,0 +1,177 @@
/*****************************************************************************
* Copyright (c) 2014-2022 OpenRCT2 developers
*
* For a complete list of all authors, please refer to contributors.md
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include "PatrolArea.h"
#include "EntityList.h"
#include "Staff.h"
static PatrolArea _consolidatedPatrolArea[EnumValue(StaffType::Count)];
static std::variant<StaffType, EntityId> _patrolAreaToRender;
static bool CompareTileCoordsXY(const TileCoordsXY& lhs, const TileCoordsXY& rhs)
{
if (lhs.y == rhs.y)
return lhs.x < rhs.x;
return lhs.y < rhs.y;
}
const PatrolArea::Cell* PatrolArea::GetCell(const TileCoordsXY& pos) const
{
return const_cast<PatrolArea*>(this)->GetCell(pos);
}
PatrolArea::Cell* PatrolArea::GetCell(const TileCoordsXY& pos)
{
auto areaPos = TileCoordsXY(pos.x / Cell::Width, pos.y / Cell::Height);
if (areaPos.x < 0 || areaPos.x >= CellColumns || areaPos.y < 0 || areaPos.y >= CellRows)
return nullptr;
auto& area = Areas[(areaPos.y * CellColumns) + areaPos.x];
return &area;
}
bool PatrolArea::IsEmpty() const
{
return TileCount == 0;
}
void PatrolArea::Clear()
{
for (auto& area : Areas)
{
area.SortedTiles.clear();
}
}
bool PatrolArea::Get(const TileCoordsXY& pos) const
{
auto* area = GetCell(pos);
if (area == nullptr)
return false;
auto it = std::lower_bound(area->SortedTiles.begin(), area->SortedTiles.end(), pos, CompareTileCoordsXY);
auto found = it != area->SortedTiles.end() && *it == pos;
return found;
}
bool PatrolArea::Get(const CoordsXY& pos) const
{
return Get(TileCoordsXY(pos));
}
void PatrolArea::Set(const TileCoordsXY& pos, bool value)
{
auto* area = GetCell(pos);
if (area == nullptr)
return;
auto it = std::lower_bound(area->SortedTiles.begin(), area->SortedTiles.end(), pos, CompareTileCoordsXY);
auto found = it != area->SortedTiles.end() && *it == pos;
if (!found && value)
{
area->SortedTiles.insert(it, pos);
TileCount++;
}
else if (found && !value)
{
area->SortedTiles.erase(it);
assert(TileCount != 0);
TileCount--;
}
}
void PatrolArea::Set(const CoordsXY& pos, bool value)
{
Set(TileCoordsXY(pos), value);
}
void PatrolArea::Union(const PatrolArea& other)
{
for (size_t i = 0; i < Areas.size(); i++)
{
for (const auto& pos : other.Areas[i].SortedTiles)
{
Set(pos, true);
}
}
}
void PatrolArea::Union(const std::vector<TileCoordsXY>& other)
{
for (const auto& pos : other)
{
Set(pos, true);
}
}
std::vector<TileCoordsXY> PatrolArea::ToVector() const
{
std::vector<TileCoordsXY> result;
for (const auto& area : Areas)
{
for (const auto& pos : area.SortedTiles)
{
result.push_back(pos);
}
}
return result;
}
const PatrolArea& GetMergedPatrolArea(const StaffType type)
{
return _consolidatedPatrolArea[EnumValue(type)];
}
void UpdateConsolidatedPatrolAreas()
{
for (int32_t staffType = 0; staffType < EnumValue(StaffType::Count); ++staffType)
{
// Reset all of the merged data for the type.
auto& mergedArea = _consolidatedPatrolArea[staffType];
mergedArea.Clear();
for (auto staff : EntityList<Staff>())
{
if (EnumValue(staff->AssignedStaffType) != staffType)
continue;
if (staff->PatrolInfo == nullptr)
continue;
mergedArea.Union(*staff->PatrolInfo);
}
}
}
bool IsPatrolAreaSetForStaffType(StaffType type, const CoordsXY& coords)
{
return _consolidatedPatrolArea[EnumValue(type)].Get(coords);
}
std::variant<StaffType, EntityId> GetPatrolAreaToRender()
{
return _patrolAreaToRender;
}
void ClearPatrolAreaToRender()
{
SetPatrolAreaToRender(EntityId::GetNull());
}
void SetPatrolAreaToRender(EntityId staffId)
{
_patrolAreaToRender = staffId;
}
void SetPatrolAreaToRender(StaffType staffType)
{
_patrolAreaToRender = staffType;
}

View File

@ -0,0 +1,61 @@
/*****************************************************************************
* Copyright (c) 2014-2022 OpenRCT2 developers
*
* For a complete list of all authors, please refer to contributors.md
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#pragma once
#include "../world/Map.h"
#include "Peep.h"
#include <variant>
// The number of elements in the gStaffPatrolAreas array per staff member. Every bit in the array represents a 4x4 square.
// Right now, it's a 32-bit array like in RCT2. 32 * 128 = 4096 bits, which is also the number of 4x4 squares on a 256x256 map.
constexpr size_t STAFF_PATROL_AREA_BLOCKS_PER_LINE = MAXIMUM_MAP_SIZE_TECHNICAL / 4;
constexpr size_t STAFF_PATROL_AREA_SIZE = (STAFF_PATROL_AREA_BLOCKS_PER_LINE * STAFF_PATROL_AREA_BLOCKS_PER_LINE) / 32;
class PatrolArea
{
private:
struct Cell
{
static constexpr auto Width = 64;
static constexpr auto Height = 64;
static constexpr auto NumTiles = Width * Height;
std::vector<TileCoordsXY> SortedTiles;
};
static constexpr auto CellColumns = (MAXIMUM_MAP_SIZE_TECHNICAL + (Cell::Width - 1)) / Cell::Width;
static constexpr auto CellRows = (MAXIMUM_MAP_SIZE_TECHNICAL + (Cell::Height - 1)) / Cell::Height;
static constexpr auto NumCells = CellColumns * CellRows;
std::array<Cell, NumCells> Areas;
size_t TileCount{};
const Cell* GetCell(const TileCoordsXY& pos) const;
Cell* GetCell(const TileCoordsXY& pos);
public:
bool IsEmpty() const;
void Clear();
bool Get(const TileCoordsXY& pos) const;
bool Get(const CoordsXY& pos) const;
void Set(const TileCoordsXY& pos, bool value);
void Set(const CoordsXY& pos, bool value);
void Union(const PatrolArea& other);
void Union(const std::vector<TileCoordsXY>& other);
std::vector<TileCoordsXY> ToVector() const;
};
void UpdateConsolidatedPatrolAreas();
bool IsPatrolAreaSetForStaffType(StaffType type, const CoordsXY& coords);
std::variant<StaffType, EntityId> GetPatrolAreaToRender();
void ClearPatrolAreaToRender();
void SetPatrolAreaToRender(EntityId staffId);
void SetPatrolAreaToRender(StaffType staffType);

View File

@ -52,6 +52,7 @@
#include "../world/Scenery.h"
#include "../world/SmallScenery.h"
#include "../world/Surface.h"
#include "PatrolArea.h"
#include "Staff.h"
#include <algorithm>
@ -667,7 +668,7 @@ void peep_sprite_remove(Peep* peep)
else
{
staff->ClearPatrolArea();
staff_update_greyed_patrol_areas();
UpdateConsolidatedPatrolAreas();
News::DisableNewsItems(News::ItemType::Peep, staff->sprite_index.ToUnderlying());
}

View File

@ -40,6 +40,7 @@
#include "../world/Scenery.h"
#include "../world/SmallScenery.h"
#include "../world/Surface.h"
#include "PatrolArea.h"
#include "Peep.h"
#include <algorithm>
@ -61,128 +62,10 @@ const rct_string_id StaffCostumeNames[] = {
};
// clang-format on
uint16_t gStaffDrawPatrolAreas;
colour_t gStaffHandymanColour;
colour_t gStaffMechanicColour;
colour_t gStaffSecurityColour;
static PatrolArea _mergedPatrolAreas[EnumValue(StaffType::Count)];
static bool CompareTileCoordsXY(const TileCoordsXY& lhs, const TileCoordsXY& rhs)
{
if (lhs.y == rhs.y)
return lhs.x < rhs.x;
return lhs.y < rhs.y;
}
const PatrolArea::Cell* PatrolArea::GetCell(TileCoordsXY pos) const
{
return const_cast<PatrolArea*>(this)->GetCell(pos);
}
PatrolArea::Cell* PatrolArea::GetCell(TileCoordsXY pos)
{
auto areaPos = TileCoordsXY(pos.x / Cell::Width, pos.y / Cell::Height);
if (areaPos.x < 0 || areaPos.x >= CellColumns || areaPos.y < 0 || areaPos.y >= CellRows)
return nullptr;
auto& area = Areas[(areaPos.y * CellColumns) + areaPos.x];
return &area;
}
bool PatrolArea::IsEmpty() const
{
return TileCount == 0;
}
void PatrolArea::Clear()
{
for (auto& area : Areas)
{
area.SortedTiles.clear();
}
}
bool PatrolArea::Get(TileCoordsXY pos) const
{
auto* area = GetCell(pos);
if (area == nullptr)
return false;
auto it = std::lower_bound(area->SortedTiles.begin(), area->SortedTiles.end(), pos, CompareTileCoordsXY);
auto found = it != area->SortedTiles.end() && *it == pos;
return found;
}
bool PatrolArea::Get(CoordsXY pos) const
{
return Get(TileCoordsXY(pos));
}
void PatrolArea::Set(TileCoordsXY pos, bool value)
{
auto* area = GetCell(pos);
if (area == nullptr)
return;
auto it = std::lower_bound(area->SortedTiles.begin(), area->SortedTiles.end(), pos, CompareTileCoordsXY);
auto found = it != area->SortedTiles.end() && *it == pos;
if (!found && value)
{
area->SortedTiles.insert(it, pos);
TileCount++;
}
else if (found && !value)
{
area->SortedTiles.erase(it);
assert(TileCount != 0);
TileCount--;
}
}
void PatrolArea::Set(CoordsXY pos, bool value)
{
Set(TileCoordsXY(pos), value);
}
void PatrolArea::Union(const PatrolArea& other)
{
for (size_t i = 0; i < Areas.size(); i++)
{
for (const auto& pos : other.Areas[i].SortedTiles)
{
Set(pos, true);
}
}
}
void PatrolArea::Union(const std::vector<TileCoordsXY>& other)
{
for (const auto& pos : other)
{
Set(pos, true);
}
}
std::vector<TileCoordsXY> PatrolArea::ToVector() const
{
std::vector<TileCoordsXY> result;
for (const auto& area : Areas)
{
for (const auto& pos : area.SortedTiles)
{
result.push_back(pos);
}
}
return result;
}
const PatrolArea& GetMergedPatrolArea(const StaffType type)
{
return _mergedPatrolAreas[EnumValue(type)];
}
// Maximum manhattan distance that litter can be for a handyman to seek to it
const uint16_t MAX_LITTER_DISTANCE = 3 * COORDS_XY_STEP;
@ -191,40 +74,6 @@ template<> bool EntityBase::Is<Staff>() const
return Type == EntityType::Staff;
}
/**
*
* rct2: 0x006BD3A4
*/
void staff_reset_modes()
{
staff_update_greyed_patrol_areas();
}
/**
*
* rct2: 0x006C0C3F
*/
void staff_update_greyed_patrol_areas()
{
for (int32_t staffType = 0; staffType < EnumValue(StaffType::Count); ++staffType)
{
// Reset all of the merged data for the type.
auto& mergedArea = _mergedPatrolAreas[staffType];
mergedArea.Clear();
for (auto staff : EntityList<Staff>())
{
if (EnumValue(staff->AssignedStaffType) != staffType)
continue;
if (staff->PatrolInfo == nullptr)
return;
mergedArea.Union(*staff->PatrolInfo);
}
}
}
/**
*
* rct2: 0x006C0905
@ -433,11 +282,6 @@ bool Staff::IsPatrolAreaSet(const CoordsXY& coords) const
return false;
}
bool staff_is_patrol_area_set_for_type(StaffType type, const CoordsXY& coords)
{
return _mergedPatrolAreas[EnumValue(type)].Get(coords);
}
void Staff::SetPatrolArea(const CoordsXY& coords, bool value)
{
if (PatrolInfo == nullptr)

View File

@ -14,45 +14,7 @@
#include "Peep.h"
class DataSerialiser;
// The number of elements in the gStaffPatrolAreas array per staff member. Every bit in the array represents a 4x4 square.
// Right now, it's a 32-bit array like in RCT2. 32 * 128 = 4096 bits, which is also the number of 4x4 squares on a 256x256 map.
constexpr size_t STAFF_PATROL_AREA_BLOCKS_PER_LINE = MAXIMUM_MAP_SIZE_TECHNICAL / 4;
constexpr size_t STAFF_PATROL_AREA_SIZE = (STAFF_PATROL_AREA_BLOCKS_PER_LINE * STAFF_PATROL_AREA_BLOCKS_PER_LINE) / 32;
struct PatrolArea
{
private:
struct Cell
{
static constexpr auto Width = 64;
static constexpr auto Height = 64;
static constexpr auto NumTiles = Width * Height;
std::vector<TileCoordsXY> SortedTiles;
};
static constexpr auto CellColumns = (MAXIMUM_MAP_SIZE_TECHNICAL + (Cell::Width - 1)) / Cell::Width;
static constexpr auto CellRows = (MAXIMUM_MAP_SIZE_TECHNICAL + (Cell::Height - 1)) / Cell::Height;
static constexpr auto NumCells = CellColumns * CellRows;
std::array<Cell, NumCells> Areas;
size_t TileCount{};
const Cell* GetCell(TileCoordsXY pos) const;
Cell* GetCell(TileCoordsXY pos);
public:
bool IsEmpty() const;
void Clear();
bool Get(TileCoordsXY pos) const;
bool Get(CoordsXY pos) const;
void Set(TileCoordsXY pos, bool value);
void Set(CoordsXY pos, bool value);
void Union(const PatrolArea& other);
void Union(const std::vector<TileCoordsXY>& other);
std::vector<TileCoordsXY> ToVector() const;
};
class PatrolArea;
struct Staff : Peep
{
@ -181,14 +143,10 @@ enum class EntertainerCostume : uint8_t
extern const rct_string_id StaffCostumeNames[static_cast<uint8_t>(EntertainerCostume::Count)];
extern uint16_t gStaffDrawPatrolAreas;
extern colour_t gStaffHandymanColour;
extern colour_t gStaffMechanicColour;
extern colour_t gStaffSecurityColour;
void staff_reset_modes();
void staff_update_greyed_patrol_areas();
bool staff_is_patrol_area_set_for_type(StaffType type, const CoordsXY& coords);
colour_t staff_get_colour(StaffType staffType);
bool staff_set_colour(StaffType staffType, colour_t value);
uint32_t staff_get_available_entertainer_costumes();

View File

@ -20,6 +20,7 @@
#include "../drawing/IDrawingEngine.h"
#include "../entity/EntityList.h"
#include "../entity/Guest.h"
#include "../entity/PatrolArea.h"
#include "../entity/Staff.h"
#include "../paint/Paint.h"
#include "../profiling/Profiling.h"
@ -90,7 +91,7 @@ void viewport_init_all()
gPickupPeepImage = ImageId();
reset_tooltip_not_shown();
gMapSelectFlags = 0;
gStaffDrawPatrolAreas = 0xFFFF;
ClearPatrolAreaToRender();
textinput_cancel();
}

View File

@ -218,6 +218,7 @@
<ClInclude Include="entity\Litter.h" />
<ClInclude Include="entity\MoneyEffect.h" />
<ClInclude Include="entity\Particle.h" />
<ClInclude Include="entity\PatrolArea.h" />
<ClInclude Include="entity\Peep.h" />
<ClInclude Include="entity\Staff.h" />
<ClInclude Include="FileClassifier.h" />
@ -687,6 +688,7 @@
<ClCompile Include="entity\Litter.cpp" />
<ClCompile Include="entity\MoneyEffect.cpp" />
<ClCompile Include="entity\Particle.cpp" />
<ClCompile Include="entity\PatrolArea.cpp" />
<ClCompile Include="entity\Peep.cpp" />
<ClCompile Include="entity\Staff.cpp" />
<ClCompile Include="FileClassifier.cpp" />
@ -952,4 +954,4 @@
</ClCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>
</Project>

View File

@ -15,6 +15,7 @@
#include "../../core/Numerics.hpp"
#include "../../drawing/LightFX.h"
#include "../../entity/EntityRegistry.h"
#include "../../entity/PatrolArea.h"
#include "../../entity/Peep.h"
#include "../../entity/Staff.h"
#include "../../interface/Viewport.h"
@ -898,45 +899,19 @@ static bool ShouldDrawSupports(paint_session& session, const PathElement& pathEl
static void PaintPatrolAreas(paint_session& session, const PathElement& pathEl)
{
if (gStaffDrawPatrolAreas != 0xFFFF)
auto colour = GetPatrolAreaTileColour(session.MapPosition);
if (colour)
{
// TODO: Split this into two.
auto staffIndex = gStaffDrawPatrolAreas;
auto staffType = static_cast<StaffType>(staffIndex & 0x7FFF);
auto is_staff_list = staffIndex & 0x8000;
auto patrolColour = COLOUR_LIGHT_BLUE;
if (!is_staff_list)
uint32_t baseImageIndex = SPR_TERRAIN_STAFF;
auto patrolAreaBaseZ = pathEl.GetBaseZ();
if (pathEl.IsSloped())
{
Staff* staff = GetEntity<Staff>(EntityId::FromUnderlying(staffIndex));
if (staff == nullptr)
{
log_error("Invalid staff index for draw patrol areas!");
}
else
{
if (!staff->IsPatrolAreaSet(session.MapPosition))
{
patrolColour = COLOUR_GREY;
}
staffType = staff->AssignedStaffType;
}
baseImageIndex = SPR_TERRAIN_STAFF_SLOPED + ((pathEl.GetSlopeDirection() + session.CurrentRotation) & 3);
patrolAreaBaseZ += 16;
}
if (staff_is_patrol_area_set_for_type(staffType, session.MapPosition))
{
uint32_t baseImageIndex = SPR_TERRAIN_STAFF;
auto patrolAreaBaseZ = pathEl.GetBaseZ();
if (pathEl.IsSloped())
{
baseImageIndex = SPR_TERRAIN_STAFF_SLOPED + ((pathEl.GetSlopeDirection() + session.CurrentRotation) & 3);
patrolAreaBaseZ += 16;
}
auto imageId = ImageId(baseImageIndex, patrolColour);
PaintAddImageAsParent(session, imageId, { 16, 16, patrolAreaBaseZ + 2 }, { 1, 1, 0 });
}
auto imageId = ImageId(baseImageIndex, *colour);
PaintAddImageAsParent(session, imageId, { 16, 16, patrolAreaBaseZ + 2 }, { 1, 1, 0 });
}
}

View File

@ -17,6 +17,7 @@
#include "../../core/Numerics.hpp"
#include "../../drawing/Drawing.h"
#include "../../entity/EntityRegistry.h"
#include "../../entity/PatrolArea.h"
#include "../../entity/Peep.h"
#include "../../entity/Staff.h"
#include "../../interface/Colour.h"
@ -969,6 +970,51 @@ static std::pair<int32_t, int32_t> surface_get_height_above_water(
return { localHeight, localSurfaceShape };
}
std::optional<colour_t> GetPatrolAreaTileColour(const CoordsXY& pos)
{
auto patrolAreaToRender = GetPatrolAreaToRender();
if (const auto* staffType = std::get_if<StaffType>(&patrolAreaToRender))
{
if (IsPatrolAreaSetForStaffType(*staffType, pos))
{
return COLOUR_GREY;
}
}
else
{
auto& staffId = std::get<EntityId>(patrolAreaToRender);
auto* staff = GetEntity<Staff>(staffId);
if (staff != nullptr)
{
if (staff->IsPatrolAreaSet(pos))
{
return COLOUR_LIGHT_BLUE;
}
else if (IsPatrolAreaSetForStaffType(staff->AssignedStaffType, pos))
{
return COLOUR_GREY;
}
}
}
return {};
}
static void PaintPatrolArea(paint_session& session, const SurfaceElement& element, int32_t height, uint8_t surfaceShape)
{
auto colour = GetPatrolAreaTileColour(session.MapPosition);
if (colour)
{
assert(surfaceShape < std::size(byte_97B444));
auto [localZ, localSurfaceShape] = surface_get_height_above_water(element, height, surfaceShape);
auto imageId = ImageId(SPR_TERRAIN_SELECTION_PATROL_AREA + byte_97B444[localSurfaceShape], *colour);
auto* backup = session.LastPS;
PaintAddImageAsParent(session, imageId, { 0, 0, localZ }, { 32, 32, 1 });
session.LastPS = backup;
}
}
/**
* rct2: 0x0066062C
*/
@ -1101,49 +1147,7 @@ void PaintSurface(paint_session& session, uint8_t direction, uint16_t height, co
has_surface = true;
}
// Draw Staff Patrol Areas
// loc_660D02
if (gStaffDrawPatrolAreas != EntityId::GetNull().ToUnderlying())
{
// TODO: Split is_staff_list into a new variable.
const int32_t staffIndex = gStaffDrawPatrolAreas;
const bool is_staff_list = staffIndex & 0x8000;
const int16_t x = session.MapPosition.x, y = session.MapPosition.y;
uint8_t staffType = staffIndex & 0x7FFF;
uint32_t image_id = IMAGE_TYPE_REMAP;
uint8_t patrolColour = COLOUR_LIGHT_BLUE;
if (!is_staff_list)
{
Staff* staff = GetEntity<Staff>(EntityId::FromUnderlying(staffIndex));
if (staff == nullptr)
{
log_error("Invalid staff index for draw patrol areas!");
}
else
{
if (!staff->IsPatrolAreaSet({ x, y }))
{
patrolColour = COLOUR_GREY;
}
staffType = static_cast<uint8_t>(staff->AssignedStaffType);
}
}
if (staff_is_patrol_area_set_for_type(static_cast<StaffType>(staffType), session.MapPosition))
{
assert(surfaceShape < std::size(byte_97B444));
auto [local_height, local_surfaceShape] = surface_get_height_above_water(tileElement, height, surfaceShape);
image_id |= SPR_TERRAIN_SELECTION_PATROL_AREA + byte_97B444[local_surfaceShape];
image_id |= patrolColour << 19;
paint_struct* backup = session.LastPS;
PaintAddImageAsParent(session, image_id, { 0, 0, local_height }, { 32, 32, 1 });
session.LastPS = backup;
}
}
PaintPatrolArea(session, tileElement, height, surfaceShape);
// Draw Peep Spawns
if (((gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) || gCheatsSandboxMode)

View File

@ -11,6 +11,9 @@
#include "../../common.h"
#include "../../sprites.h"
#include "../../world/Location.hpp"
#include <optional>
enum
{
@ -102,3 +105,5 @@ enum
SPR_RCT1_WATER_MASK = SPR_CSG_BEGIN + 46787,
SPR_RCT1_WATER_OVERLAY = SPR_CSG_BEGIN + 46792,
};
std::optional<colour_t> GetPatrolAreaTileColour(const CoordsXY& pos);

View File

@ -31,6 +31,7 @@
#include "../entity/Litter.h"
#include "../entity/MoneyEffect.h"
#include "../entity/Particle.h"
#include "../entity/PatrolArea.h"
#include "../entity/Staff.h"
#include "../interface/Viewport.h"
#include "../interface/Window.h"
@ -2027,11 +2028,18 @@ namespace OpenRCT2
cs.ReadWriteVector(patrolArea, [&cs](TileCoordsXY& value) { cs.ReadWrite(value); });
if (cs.GetMode() == OrcaStream::Mode::READING)
{
if (entity.PatrolInfo == nullptr)
entity.PatrolInfo = new PatrolArea();
if (patrolArea.empty())
{
entity.ClearPatrolArea();
}
else
entity.PatrolInfo->Clear();
entity.PatrolInfo->Union(patrolArea);
{
if (entity.PatrolInfo == nullptr)
entity.PatrolInfo = new PatrolArea();
else
entity.PatrolInfo->Clear();
entity.PatrolInfo->Union(patrolArea);
}
}
if (os.GetHeader().TargetVersion <= 1)

View File

@ -32,6 +32,7 @@
#include "../entity/Litter.h"
#include "../entity/MoneyEffect.h"
#include "../entity/Particle.h"
#include "../entity/PatrolArea.h"
#include "../entity/Peep.h"
#include "../entity/Staff.h"
#include "../interface/Window.h"
@ -1260,7 +1261,7 @@ namespace RCT1
void FixImportStaff()
{
// Only the individual patrol areas have been converted, so generate the combined patrol areas of each staff type
staff_update_greyed_patrol_areas();
UpdateConsolidatedPatrolAreas();
}
void ImportPeep(::Peep* dst, const RCT1::Peep* src)

View File

@ -32,6 +32,7 @@
#include "../entity/Litter.h"
#include "../entity/MoneyEffect.h"
#include "../entity/Particle.h"
#include "../entity/PatrolArea.h"
#include "../entity/Staff.h"
#include "../interface/Viewport.h"
#include "../localisation/Date.h"
@ -490,7 +491,7 @@ namespace RCT2
FixLandOwnership();
research_determine_first_of_type();
staff_update_greyed_patrol_areas();
UpdateConsolidatedPatrolAreas();
CheatsReset();
ClearRestrictedScenery();