mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-24 07:14:31 +01:00
Add patrol area tool window
This commit is contained in:
@@ -3657,6 +3657,8 @@ STR_6465 :Intensity: {COMMA2DP32}
|
||||
STR_6466 :Nausea
|
||||
STR_6467 :Nausea: {COMMA2DP32}
|
||||
STR_6468 :Not Yet Known
|
||||
STR_6469 :Adjust smaller area of patrol area
|
||||
STR_6470 :Adjust larger area of patrol area
|
||||
|
||||
#############
|
||||
# Scenarios #
|
||||
|
||||
@@ -174,6 +174,7 @@ static constexpr const WindowThemeDesc WindowThemeDescriptors[] =
|
||||
{ THEME_WC(WC_TITLE_EDITOR), STR_TITLE_EDITOR_TITLE, COLOURS_3(COLOUR_GREY, COLOUR_OLIVE_GREEN, COLOUR_OLIVE_GREEN ) },
|
||||
{ THEME_WC(WC_TILE_INSPECTOR), STR_TILE_INSPECTOR_TITLE, COLOURS_2(COLOUR_LIGHT_BLUE, COLOUR_LIGHT_BLUE ) },
|
||||
{ THEME_WC(WC_VIEW_CLIPPING), STR_VIEW_CLIPPING_TITLE, COLOURS_1(COLOUR_DARK_GREEN ) },
|
||||
{ THEME_WC(WC_PATROL_AREA), STR_SET_PATROL_AREA, COLOURS_3(COLOUR_LIGHT_PURPLE, COLOUR_LIGHT_PURPLE, COLOUR_LIGHT_PURPLE ) },
|
||||
{ THEME_WC(WC_ABOUT), STR_ABOUT, COLOURS_2(COLOUR_GREY, COLOUR_LIGHT_BLUE ) },
|
||||
{ THEME_WC(WC_CHANGELOG), STR_CHANGELOG_TITLE, COLOURS_2(COLOUR_LIGHT_BLUE, COLOUR_LIGHT_BLUE ) },
|
||||
{ THEME_WC(WC_MULTIPLAYER), STR_MULTIPLAYER, COLOURS_3(COLOUR_LIGHT_BLUE, COLOUR_LIGHT_BLUE, COLOUR_LIGHT_BLUE ) },
|
||||
|
||||
@@ -156,6 +156,7 @@
|
||||
<ClCompile Include="windows\ObjectLoadError.cpp" />
|
||||
<ClCompile Include="windows\Options.cpp" />
|
||||
<ClCompile Include="windows\Park.cpp" />
|
||||
<ClCompile Include="windows\PatrolArea.cpp" />
|
||||
<ClCompile Include="windows\Player.cpp" />
|
||||
<ClCompile Include="windows\RefurbishRidePrompt.cpp" />
|
||||
<ClCompile Include="windows\Research.cpp" />
|
||||
|
||||
305
src/openrct2-ui/windows/PatrolArea.cpp
Normal file
305
src/openrct2-ui/windows/PatrolArea.cpp
Normal file
@@ -0,0 +1,305 @@
|
||||
/*****************************************************************************
|
||||
* Copyright (c) 2014-2020 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 <algorithm>
|
||||
#include <openrct2-ui/interface/LandTool.h>
|
||||
#include <openrct2-ui/interface/Viewport.h>
|
||||
#include <openrct2-ui/interface/Widget.h>
|
||||
#include <openrct2-ui/windows/Window.h>
|
||||
#include <openrct2/Context.h>
|
||||
#include <openrct2/Game.h>
|
||||
#include <openrct2/Input.h>
|
||||
#include <openrct2/actions/StaffSetPatrolAreaAction.h>
|
||||
#include <openrct2/core/String.hpp>
|
||||
#include <openrct2/drawing/Drawing.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>
|
||||
#include <openrct2/world/Park.h>
|
||||
|
||||
static constexpr const rct_string_id WINDOW_TITLE = STR_SET_PATROL_AREA;
|
||||
static constexpr const int32_t WH = 54;
|
||||
static constexpr const int32_t WW = 104;
|
||||
|
||||
enum WindowPatrolAreaWidgetIdx
|
||||
{
|
||||
WIDX_BACKGROUND,
|
||||
WIDX_TITLE,
|
||||
WIDX_CLOSE,
|
||||
WIDX_PREVIEW,
|
||||
WIDX_DECREMENT,
|
||||
WIDX_INCREMENT,
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
static rct_widget PatrolAreaWidgets[] = {
|
||||
WINDOW_SHIM(WINDOW_TITLE, WW, WH),
|
||||
MakeWidget ({27, 17}, {44, 32}, WindowWidgetType::ImgBtn, WindowColour::Primary , SPR_LAND_TOOL_SIZE_0 ), // preview box
|
||||
MakeRemapWidget({28, 18}, {16, 16}, WindowWidgetType::TrnBtn, WindowColour::Tertiary, SPR_LAND_TOOL_DECREASE, STR_ADJUST_SMALLER_PATROL_AREA_TIP), // decrement size
|
||||
MakeRemapWidget({54, 32}, {16, 16}, WindowWidgetType::TrnBtn, WindowColour::Tertiary, SPR_LAND_TOOL_INCREASE, STR_ADJUST_LARGER_PATROL_AREA_TIP ), // increment size
|
||||
WIDGETS_END,
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
class PatrolAreaWindow final : public Window
|
||||
{
|
||||
public:
|
||||
void OnOpen() override
|
||||
{
|
||||
widgets = PatrolAreaWidgets;
|
||||
hold_down_widgets = (1ULL << WIDX_INCREMENT) | (1ULL << WIDX_DECREMENT);
|
||||
WindowInitScrollWidgets(this);
|
||||
window_push_others_below(this);
|
||||
gLandToolSize = 4;
|
||||
}
|
||||
|
||||
void OnClose() override
|
||||
{
|
||||
// If the tool wasn't changed, turn tool off
|
||||
if (PatrolAreaToolIsActive())
|
||||
tool_cancel();
|
||||
}
|
||||
|
||||
void OnMouseUp(rct_widgetindex widgetIndex) override
|
||||
{
|
||||
switch (widgetIndex)
|
||||
{
|
||||
case WIDX_CLOSE:
|
||||
Close();
|
||||
break;
|
||||
case WIDX_PREVIEW:
|
||||
InputSize();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OnMouseDown(rct_widgetindex widgetIndex) override
|
||||
{
|
||||
switch (widgetIndex)
|
||||
{
|
||||
case WIDX_DECREMENT:
|
||||
gLandToolSize = std::max(MINIMUM_TOOL_SIZE, gLandToolSize - 1);
|
||||
Invalidate();
|
||||
break;
|
||||
case WIDX_INCREMENT:
|
||||
gLandToolSize = std::min(MAXIMUM_TOOL_SIZE, gLandToolSize + 1);
|
||||
Invalidate();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OnTextInput(rct_widgetindex widgetIndex, std::string_view text) override
|
||||
{
|
||||
if (text.empty())
|
||||
return;
|
||||
|
||||
if (widgetIndex != WIDX_PREVIEW)
|
||||
return;
|
||||
|
||||
const auto res = String::Parse<int32_t>(text);
|
||||
if (res.has_value())
|
||||
{
|
||||
int32_t size;
|
||||
size = res.value();
|
||||
size = std::max(MINIMUM_TOOL_SIZE, size);
|
||||
size = std::min(MAXIMUM_TOOL_SIZE, size);
|
||||
gLandToolSize = size;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
void OnUpdate() override
|
||||
{
|
||||
// Close window if another tool is open or staff window gets closed
|
||||
if (!PatrolAreaToolIsActive() || !IsStaffWindowOpen())
|
||||
{
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
||||
void OnPrepareDraw() override
|
||||
{
|
||||
SetWidgetPressed(WIDX_PREVIEW, true);
|
||||
PatrolAreaWidgets[WIDX_PREVIEW].image = LandTool::SizeToSpriteIndex(gLandToolSize);
|
||||
}
|
||||
|
||||
void OnDraw(rct_drawpixelinfo& dpi) override
|
||||
{
|
||||
DrawWidgets(dpi);
|
||||
|
||||
// Draw number for tool sizes bigger than 7
|
||||
if (gLandToolSize > MAX_TOOL_SIZE_WITH_SPRITE)
|
||||
{
|
||||
auto screenCoords = ScreenCoordsXY{ windowPos.x + PatrolAreaWidgets[WIDX_PREVIEW].midX(),
|
||||
windowPos.y + PatrolAreaWidgets[WIDX_PREVIEW].midY() };
|
||||
auto ft = Formatter();
|
||||
ft.Add<uint16_t>(gLandToolSize);
|
||||
DrawTextBasic(&dpi, screenCoords - ScreenCoordsXY{ 0, 2 }, STR_LAND_TOOL_SIZE_VALUE, ft, { TextAlignment::CENTRE });
|
||||
}
|
||||
}
|
||||
|
||||
void OnToolUpdate(rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords) override
|
||||
{
|
||||
auto mapTile = GetBestCoordsFromPos(screenCoords);
|
||||
if (!mapTile)
|
||||
return;
|
||||
|
||||
auto stateChanged = false;
|
||||
if (!(gMapSelectFlags & MAP_SELECT_FLAG_ENABLE))
|
||||
stateChanged = true;
|
||||
|
||||
if (gMapSelectType != MAP_SELECT_TYPE_FULL)
|
||||
stateChanged = true;
|
||||
|
||||
auto toolSize = std::max<uint16_t>(1, gLandToolSize);
|
||||
auto toolLength = (toolSize - 1) * 32;
|
||||
|
||||
// Move to tool bottom left
|
||||
mapTile->x -= (toolSize - 1) * 16;
|
||||
mapTile->y -= (toolSize - 1) * 16;
|
||||
mapTile = mapTile->ToTileStart();
|
||||
auto posA = *mapTile;
|
||||
mapTile->x += toolLength;
|
||||
mapTile->y += toolLength;
|
||||
auto posB = *mapTile;
|
||||
if (gMapSelectPositionA != posA || gMapSelectPositionB != posB)
|
||||
stateChanged = true;
|
||||
|
||||
if (stateChanged)
|
||||
{
|
||||
// Invalidate previous area
|
||||
map_invalidate_selection_rect();
|
||||
|
||||
// Update and invalidate new area
|
||||
gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE;
|
||||
gMapSelectType = MAP_SELECT_TYPE_FULL;
|
||||
gMapSelectPositionA = posA;
|
||||
gMapSelectPositionB = posB;
|
||||
map_invalidate_selection_rect();
|
||||
}
|
||||
}
|
||||
|
||||
void OnToolAbort(rct_widgetindex widgetIndex) override
|
||||
{
|
||||
hide_gridlines();
|
||||
ClearPatrolAreaToRender();
|
||||
gfx_invalidate_screen();
|
||||
}
|
||||
|
||||
void OnToolDown(rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords) override
|
||||
{
|
||||
auto mapTile = GetBestCoordsFromPos(screenCoords);
|
||||
if (mapTile)
|
||||
{
|
||||
auto staff = GetEntity<Staff>(_staffId);
|
||||
if (staff != nullptr)
|
||||
{
|
||||
_mode = staff->IsPatrolAreaSet(*mapTile) ? StaffSetPatrolAreaMode::Unset : StaffSetPatrolAreaMode::Set;
|
||||
}
|
||||
}
|
||||
|
||||
OnToolDrag(widgetIndex, screenCoords);
|
||||
}
|
||||
|
||||
void OnToolDrag(rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords) override
|
||||
{
|
||||
auto staff = GetEntity<Staff>(_staffId);
|
||||
if (staff != nullptr)
|
||||
{
|
||||
MapRange range(gMapSelectPositionA, gMapSelectPositionB);
|
||||
auto staffSetPatrolAreaAction = StaffSetPatrolAreaAction(_staffId, range, _mode);
|
||||
GameActions::Execute(&staffSetPatrolAreaAction);
|
||||
}
|
||||
}
|
||||
|
||||
EntityId GetStaffId() const
|
||||
{
|
||||
return _staffId;
|
||||
}
|
||||
|
||||
void SetStaffId(EntityId staffId)
|
||||
{
|
||||
_staffId = staffId;
|
||||
EnableTool();
|
||||
}
|
||||
|
||||
private:
|
||||
EntityId _staffId;
|
||||
StaffSetPatrolAreaMode _mode;
|
||||
|
||||
void EnableTool()
|
||||
{
|
||||
show_gridlines();
|
||||
if (!tool_set(this, 0, Tool::WalkDown))
|
||||
{
|
||||
input_set_flag(INPUT_FLAG_6, true);
|
||||
show_gridlines();
|
||||
SetPatrolAreaToRender(_staffId);
|
||||
gfx_invalidate_screen();
|
||||
}
|
||||
}
|
||||
|
||||
void InputSize()
|
||||
{
|
||||
Formatter ft;
|
||||
ft.Add<int16_t>(MINIMUM_TOOL_SIZE);
|
||||
ft.Add<int16_t>(MAXIMUM_TOOL_SIZE);
|
||||
WindowTextInputOpen(this, WIDX_PREVIEW, STR_SELECTION_SIZE, STR_ENTER_SELECTION_SIZE, ft, STR_NONE, STR_NONE, 3);
|
||||
}
|
||||
|
||||
bool PatrolAreaToolIsActive()
|
||||
{
|
||||
if (!(input_test_flag(INPUT_FLAG_TOOL_ACTIVE)))
|
||||
return false;
|
||||
if (gCurrentToolWidget.window_classification != WC_PATROL_AREA)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsStaffWindowOpen()
|
||||
{
|
||||
// If staff window for this patrol area was closed, tool is no longer active
|
||||
auto staffWindow = window_find_by_number(WC_PEEP, _staffId);
|
||||
return staffWindow != nullptr;
|
||||
}
|
||||
|
||||
std::optional<CoordsXY> GetBestCoordsFromPos(const ScreenCoordsXY& pos)
|
||||
{
|
||||
auto coords = footpath_get_coordinates_from_pos(pos, nullptr, nullptr);
|
||||
return coords.IsNull() ? std::nullopt : std::make_optional(coords);
|
||||
}
|
||||
};
|
||||
|
||||
rct_window* WindowPatrolAreaOpen(EntityId staffId)
|
||||
{
|
||||
auto current = reinterpret_cast<PatrolAreaWindow*>(window_find_by_class(WC_PATROL_AREA));
|
||||
if (current != nullptr)
|
||||
{
|
||||
if (current->GetStaffId() == staffId)
|
||||
{
|
||||
return window_bring_to_front(current);
|
||||
}
|
||||
current->Close();
|
||||
}
|
||||
|
||||
auto w = WindowFocusOrCreate<PatrolAreaWindow>(WC_PATROL_AREA, ScreenCoordsXY(context_get_width() - WW, 29), WW, WH, 0);
|
||||
if (w != nullptr)
|
||||
{
|
||||
w->SetStaffId(staffId);
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
||||
EntityId WindowPatrolAreaGetCurrentStaffId()
|
||||
{
|
||||
auto current = reinterpret_cast<PatrolAreaWindow*>(window_find_by_class(WC_PATROL_AREA));
|
||||
return current != nullptr ? current->GetStaffId() : EntityId();
|
||||
}
|
||||
@@ -135,8 +135,6 @@ static void WindowStaffOverviewPaint(rct_window* w, rct_drawpixelinfo* dpi);
|
||||
static void WindowStaffOverviewTabPaint(rct_window* w, rct_drawpixelinfo* dpi);
|
||||
static void WindowStaffOverviewToolUpdate(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords);
|
||||
static void WindowStaffOverviewToolDown(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords);
|
||||
static void WindowStaffOverviewToolDrag(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords);
|
||||
static void WindowStaffOverviewToolUp(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords);
|
||||
static void WindowStaffOverviewToolAbort(rct_window* w, rct_widgetindex widgetIndex);
|
||||
static void WindowStaffOverviewTextInput(rct_window* w, rct_widgetindex widgetIndex, char* text);
|
||||
static void WindowStaffOverviewViewportRotate(rct_window* w);
|
||||
@@ -170,8 +168,6 @@ static rct_window_event_list window_staff_overview_events([](auto& events) {
|
||||
events.update = &WindowStaffOverviewUpdate;
|
||||
events.tool_update = &WindowStaffOverviewToolUpdate;
|
||||
events.tool_down = &WindowStaffOverviewToolDown;
|
||||
events.tool_drag = &WindowStaffOverviewToolDrag;
|
||||
events.tool_up = &WindowStaffOverviewToolUp;
|
||||
events.tool_abort = &WindowStaffOverviewToolAbort;
|
||||
events.text_input = &WindowStaffOverviewTextInput;
|
||||
events.viewport_rotate = &WindowStaffOverviewViewportRotate;
|
||||
@@ -209,15 +205,6 @@ static rct_window_event_list* window_staff_page_events[] = {
|
||||
|
||||
static EntertainerCostume _availableCostumes[static_cast<uint8_t>(EntertainerCostume::Count)];
|
||||
|
||||
enum class PatrolAreaValue
|
||||
{
|
||||
UNSET = 0,
|
||||
SET = 1,
|
||||
NONE = -1,
|
||||
};
|
||||
|
||||
static PatrolAreaValue _staffPatrolAreaPaintValue = PatrolAreaValue::NONE;
|
||||
|
||||
static Staff* GetStaff(rct_window* w)
|
||||
{
|
||||
auto staff = GetEntity<Staff>(EntityId::FromUnderlying(w->number));
|
||||
@@ -542,17 +529,22 @@ void WindowStaffOverviewDropdown(rct_window* w, rct_widgetindex widgetIndex, int
|
||||
return;
|
||||
}
|
||||
|
||||
window_close_by_class(WC_PATROL_AREA);
|
||||
|
||||
auto staffSetPatrolAreaAction = StaffSetPatrolAreaAction(
|
||||
peep->sprite_index, {}, StaffSetPatrolAreaMode::ClearAll);
|
||||
GameActions::Execute(&staffSetPatrolAreaAction);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!tool_set(w, widgetIndex, Tool::WalkDown))
|
||||
auto staffId = EntityId::FromUnderlying(w->number);
|
||||
if (WindowPatrolAreaGetCurrentStaffId() == staffId)
|
||||
{
|
||||
show_gridlines();
|
||||
SetPatrolAreaToRender(EntityId::FromUnderlying(w->number));
|
||||
gfx_invalidate_screen();
|
||||
window_close_by_class(WC_PATROL_AREA);
|
||||
}
|
||||
else
|
||||
{
|
||||
WindowPatrolAreaOpen(staffId);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -895,6 +887,7 @@ void WindowStaffOverviewInvalidate(rct_window* w)
|
||||
window_staff_overview_widgets[WIDX_PICKUP].left = w->width - 25;
|
||||
window_staff_overview_widgets[WIDX_PICKUP].right = w->width - 2;
|
||||
|
||||
WidgetSetPressed(w, WIDX_PATROL, WindowPatrolAreaGetCurrentStaffId() == peep->sprite_index);
|
||||
window_staff_overview_widgets[WIDX_PATROL].left = w->width - 25;
|
||||
window_staff_overview_widgets[WIDX_PATROL].right = w->width - 2;
|
||||
|
||||
@@ -1174,96 +1167,26 @@ void WindowStaffOverviewToolUpdate(rct_window* w, rct_widgetindex widgetIndex, c
|
||||
*/
|
||||
void WindowStaffOverviewToolDown(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords)
|
||||
{
|
||||
if (widgetIndex != WIDX_PICKUP)
|
||||
return;
|
||||
|
||||
const auto staffEntityId = EntityId::FromUnderlying(w->number);
|
||||
|
||||
if (widgetIndex == WIDX_PICKUP)
|
||||
{
|
||||
TileElement* tileElement;
|
||||
auto destCoords = footpath_get_coordinates_from_pos({ screenCoords.x, screenCoords.y + 16 }, nullptr, &tileElement);
|
||||
|
||||
if (destCoords.IsNull())
|
||||
return;
|
||||
|
||||
PeepPickupAction pickupAction{
|
||||
PeepPickupType::Place, staffEntityId, { destCoords, tileElement->GetBaseZ() }, network_get_current_player_id()
|
||||
};
|
||||
pickupAction.SetCallback([](const GameAction* ga, const GameActions::Result* result) {
|
||||
if (result->Error != GameActions::Status::Ok)
|
||||
return;
|
||||
tool_cancel();
|
||||
gPickupPeepImage = ImageId();
|
||||
});
|
||||
GameActions::Execute(&pickupAction);
|
||||
}
|
||||
else if (widgetIndex == WIDX_PATROL)
|
||||
{
|
||||
auto destCoords = footpath_get_coordinates_from_pos(screenCoords, nullptr, nullptr);
|
||||
|
||||
if (destCoords.IsNull())
|
||||
return;
|
||||
|
||||
auto staff = TryGetEntity<Staff>(staffEntityId);
|
||||
if (staff == nullptr)
|
||||
return;
|
||||
|
||||
if (staff->IsPatrolAreaSet(destCoords))
|
||||
{
|
||||
_staffPatrolAreaPaintValue = PatrolAreaValue::UNSET;
|
||||
}
|
||||
else
|
||||
{
|
||||
_staffPatrolAreaPaintValue = PatrolAreaValue::SET;
|
||||
}
|
||||
auto staffSetPatrolAreaAction = StaffSetPatrolAreaAction(
|
||||
staffEntityId, destCoords,
|
||||
_staffPatrolAreaPaintValue == PatrolAreaValue::SET ? StaffSetPatrolAreaMode::Set : StaffSetPatrolAreaMode::Unset);
|
||||
GameActions::Execute(&staffSetPatrolAreaAction);
|
||||
}
|
||||
}
|
||||
|
||||
void WindowStaffOverviewToolDrag(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords)
|
||||
{
|
||||
if (widgetIndex != WIDX_PATROL)
|
||||
return;
|
||||
|
||||
if (network_get_mode() != NETWORK_MODE_NONE)
|
||||
return;
|
||||
|
||||
// This works only for singleplayer if the game_do_command can not be prevented
|
||||
// to send packets more often than patrol area is updated.
|
||||
|
||||
if (_staffPatrolAreaPaintValue == PatrolAreaValue::NONE)
|
||||
return; // Do nothing if we do not have a paintvalue(this should never happen)
|
||||
|
||||
auto destCoords = footpath_get_coordinates_from_pos(screenCoords, nullptr, nullptr);
|
||||
TileElement* tileElement;
|
||||
auto destCoords = footpath_get_coordinates_from_pos({ screenCoords.x, screenCoords.y + 16 }, nullptr, &tileElement);
|
||||
|
||||
if (destCoords.IsNull())
|
||||
return;
|
||||
|
||||
const auto staffEntityId = EntityId::FromUnderlying(w->number);
|
||||
|
||||
auto* staff = TryGetEntity<Staff>(staffEntityId);
|
||||
if (staff == nullptr)
|
||||
return;
|
||||
|
||||
bool patrolAreaValue = staff->IsPatrolAreaSet(destCoords);
|
||||
if (_staffPatrolAreaPaintValue == PatrolAreaValue::SET && patrolAreaValue)
|
||||
return; // Since area is already the value we want, skip...
|
||||
if (_staffPatrolAreaPaintValue == PatrolAreaValue::UNSET && !patrolAreaValue)
|
||||
return; // Since area is already the value we want, skip...
|
||||
|
||||
auto staffSetPatrolAreaAction = StaffSetPatrolAreaAction(
|
||||
staffEntityId, destCoords,
|
||||
_staffPatrolAreaPaintValue == PatrolAreaValue::SET ? StaffSetPatrolAreaMode::Set : StaffSetPatrolAreaMode::Unset);
|
||||
GameActions::Execute(&staffSetPatrolAreaAction);
|
||||
}
|
||||
|
||||
void WindowStaffOverviewToolUp(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords)
|
||||
{
|
||||
if (widgetIndex != WIDX_PATROL)
|
||||
return;
|
||||
|
||||
_staffPatrolAreaPaintValue = PatrolAreaValue::NONE;
|
||||
PeepPickupAction pickupAction{
|
||||
PeepPickupType::Place, staffEntityId, { destCoords, tileElement->GetBaseZ() }, network_get_current_player_id()
|
||||
};
|
||||
pickupAction.SetCallback([](const GameAction* ga, const GameActions::Result* result) {
|
||||
if (result->Error != GameActions::Status::Ok)
|
||||
return;
|
||||
tool_cancel();
|
||||
gPickupPeepImage = ImageId();
|
||||
});
|
||||
GameActions::Execute(&pickupAction);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1272,20 +1195,14 @@ void WindowStaffOverviewToolUp(rct_window* w, rct_widgetindex widgetIndex, const
|
||||
*/
|
||||
void WindowStaffOverviewToolAbort(rct_window* w, rct_widgetindex widgetIndex)
|
||||
{
|
||||
if (widgetIndex == WIDX_PICKUP)
|
||||
{
|
||||
PeepPickupAction pickupAction{ PeepPickupType::Cancel,
|
||||
EntityId::FromUnderlying(w->number),
|
||||
{ w->picked_peep_old_x, 0, 0 },
|
||||
network_get_current_player_id() };
|
||||
GameActions::Execute(&pickupAction);
|
||||
}
|
||||
else if (widgetIndex == WIDX_PATROL)
|
||||
{
|
||||
hide_gridlines();
|
||||
ClearPatrolAreaToRender();
|
||||
gfx_invalidate_screen();
|
||||
}
|
||||
if (widgetIndex != WIDX_PICKUP)
|
||||
return;
|
||||
|
||||
PeepPickupAction pickupAction{ PeepPickupType::Cancel,
|
||||
EntityId::FromUnderlying(w->number),
|
||||
{ w->picked_peep_old_x, 0, 0 },
|
||||
network_get_current_player_id() };
|
||||
GameActions::Execute(&pickupAction);
|
||||
}
|
||||
|
||||
/* rct2: 0x6BDFED */
|
||||
|
||||
@@ -195,6 +195,7 @@ static rct_windowclass window_themes_tab_3_classes[] = {
|
||||
WC_TRACK_DESIGN_PLACE,
|
||||
WC_CONSTRUCT_RIDE,
|
||||
WC_TRACK_DESIGN_LIST,
|
||||
WC_PATROL_AREA,
|
||||
};
|
||||
|
||||
static rct_windowclass window_themes_tab_4_classes[] = {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <openrct2-ui/interface/Window.h>
|
||||
#include <openrct2/Identifiers.h>
|
||||
#include <openrct2/common.h>
|
||||
#include <openrct2/ride/Ride.h>
|
||||
#include <openrct2/windows/tile_inspector.h>
|
||||
@@ -200,6 +201,8 @@ void WindowTooltipOpen(rct_window* widgetWindow, rct_widgetindex widgetIndex, co
|
||||
void WindowTooltipClose();
|
||||
|
||||
rct_window* WindowSceneryScatterOpen();
|
||||
rct_window* WindowPatrolAreaOpen(EntityId staffId);
|
||||
EntityId WindowPatrolAreaGetCurrentStaffId();
|
||||
|
||||
// clang-format off
|
||||
#define WINDOW_SHIM_RAW(TITLE, WIDTH, HEIGHT, CLOSE_STR) \
|
||||
|
||||
@@ -79,6 +79,14 @@ public:
|
||||
Visit("direction", param.direction);
|
||||
}
|
||||
|
||||
void Visit(MapRange& param)
|
||||
{
|
||||
Visit("x1", param.Point1.x);
|
||||
Visit("y1", param.Point1.y);
|
||||
Visit("x2", param.Point2.x);
|
||||
Visit("y2", param.Point2.y);
|
||||
}
|
||||
|
||||
template<typename T> void Visit(std::string_view name, T& param)
|
||||
{
|
||||
static_assert(std::is_arithmetic_v<T> || std::is_enum_v<T>, "Not an arithmetic type");
|
||||
|
||||
@@ -15,13 +15,20 @@
|
||||
#include "../entity/Staff.h"
|
||||
#include "../interface/Window.h"
|
||||
|
||||
StaffSetPatrolAreaAction::StaffSetPatrolAreaAction(EntityId spriteId, const CoordsXY& loc, const StaffSetPatrolAreaMode mode)
|
||||
StaffSetPatrolAreaAction::StaffSetPatrolAreaAction(EntityId spriteId, const MapRange& range, const StaffSetPatrolAreaMode mode)
|
||||
: _spriteId(spriteId)
|
||||
, _loc(loc)
|
||||
, _range(range)
|
||||
, _mode(mode)
|
||||
{
|
||||
}
|
||||
|
||||
void StaffSetPatrolAreaAction::AcceptParameters(GameActionParameterVisitor& visitor)
|
||||
{
|
||||
visitor.Visit("id", _spriteId);
|
||||
visitor.Visit(_range);
|
||||
visitor.Visit("mode", _mode);
|
||||
}
|
||||
|
||||
uint16_t StaffSetPatrolAreaAction::GetActionFlags() const
|
||||
{
|
||||
return GameAction::GetActionFlags() | GameActions::Flags::AllowWhilePaused;
|
||||
@@ -30,7 +37,7 @@ uint16_t StaffSetPatrolAreaAction::GetActionFlags() const
|
||||
void StaffSetPatrolAreaAction::Serialise(DataSerialiser& stream)
|
||||
{
|
||||
GameAction::Serialise(stream);
|
||||
stream << DS_TAG(_spriteId) << DS_TAG(_loc) << DS_TAG(_mode);
|
||||
stream << DS_TAG(_spriteId) << DS_TAG(_range) << DS_TAG(_mode);
|
||||
}
|
||||
|
||||
GameActions::Result StaffSetPatrolAreaAction::Query() const
|
||||
@@ -41,11 +48,6 @@ GameActions::Result StaffSetPatrolAreaAction::Query() const
|
||||
return GameActions::Result(GameActions::Status::InvalidParameters, STR_NONE, STR_NONE);
|
||||
}
|
||||
|
||||
if (!LocationValid(_loc))
|
||||
{
|
||||
return GameActions::Result(GameActions::Status::InvalidParameters, STR_NONE, STR_NONE);
|
||||
}
|
||||
|
||||
auto staff = TryGetEntity<Staff>(_spriteId);
|
||||
if (staff == nullptr)
|
||||
{
|
||||
@@ -56,17 +58,9 @@ GameActions::Result StaffSetPatrolAreaAction::Query() const
|
||||
return GameActions::Result();
|
||||
}
|
||||
|
||||
static void InvalidatePatrolTile(const CoordsXY& loc)
|
||||
static void InvalidatePatrolTiles(const MapRange& range)
|
||||
{
|
||||
// Align the location to the top left of the patrol square
|
||||
const auto alignedLoc = CoordsXY{ loc.x & 0x1F80, loc.y & 0x1F80 };
|
||||
for (int32_t y = 0; y < 4 * COORDS_XY_STEP; y += COORDS_XY_STEP)
|
||||
{
|
||||
for (int32_t x = 0; x < 4 * COORDS_XY_STEP; x += COORDS_XY_STEP)
|
||||
{
|
||||
map_invalidate_tile_full(alignedLoc + CoordsXY{ x, y });
|
||||
}
|
||||
}
|
||||
map_invalidate_region(range.Point1, range.Point2);
|
||||
}
|
||||
|
||||
GameActions::Result StaffSetPatrolAreaAction::Execute() const
|
||||
@@ -81,16 +75,16 @@ GameActions::Result StaffSetPatrolAreaAction::Execute() const
|
||||
switch (_mode)
|
||||
{
|
||||
case StaffSetPatrolAreaMode::Set:
|
||||
staff->SetPatrolArea(_loc, true);
|
||||
InvalidatePatrolTile(_loc);
|
||||
staff->SetPatrolArea(_range, true);
|
||||
InvalidatePatrolTiles(_range);
|
||||
break;
|
||||
case StaffSetPatrolAreaMode::Unset:
|
||||
staff->SetPatrolArea(_loc, false);
|
||||
staff->SetPatrolArea(_range, false);
|
||||
if (!staff->HasPatrolArea())
|
||||
{
|
||||
staff->ClearPatrolArea();
|
||||
}
|
||||
InvalidatePatrolTile(_loc);
|
||||
InvalidatePatrolTiles(_range);
|
||||
break;
|
||||
case StaffSetPatrolAreaMode::ClearAll:
|
||||
staff->ClearPatrolArea();
|
||||
|
||||
@@ -22,15 +22,16 @@ class StaffSetPatrolAreaAction final : public GameActionBase<GameCommand::SetSta
|
||||
{
|
||||
private:
|
||||
EntityId _spriteId{ EntityId::GetNull() };
|
||||
CoordsXY _loc;
|
||||
MapRange _range;
|
||||
StaffSetPatrolAreaMode _mode;
|
||||
|
||||
public:
|
||||
StaffSetPatrolAreaAction() = default;
|
||||
StaffSetPatrolAreaAction(EntityId spriteId, const CoordsXY& loc, const StaffSetPatrolAreaMode mode);
|
||||
StaffSetPatrolAreaAction(EntityId spriteId, const MapRange& range, const StaffSetPatrolAreaMode mode);
|
||||
|
||||
uint16_t GetActionFlags() const override;
|
||||
|
||||
void AcceptParameters(GameActionParameterVisitor& visitor) override;
|
||||
void Serialise(DataSerialiser& stream) override;
|
||||
GameActions::Result Query() const override;
|
||||
GameActions::Result Execute() const override;
|
||||
|
||||
@@ -462,6 +462,7 @@ enum
|
||||
WC_DEBUG_PAINT = 130,
|
||||
WC_VIEW_CLIPPING = 131,
|
||||
WC_OBJECT_LOAD_ERROR = 132,
|
||||
WC_PATROL_AREA = 133,
|
||||
|
||||
// Only used for colour schemes
|
||||
WC_STAFF = 220,
|
||||
|
||||
@@ -3925,6 +3925,9 @@ enum : uint16_t
|
||||
STR_NAUSEA_LABEL = 6467,
|
||||
STR_RATING_UKNOWN_LABEL = 6468,
|
||||
|
||||
STR_ADJUST_SMALLER_PATROL_AREA_TIP = 6469,
|
||||
STR_ADJUST_LARGER_PATROL_AREA_TIP = 6470,
|
||||
|
||||
// Have to include resource strings (from scenarios and objects) for the time being now that language is partially working
|
||||
/* MAX_STR_COUNT = 32768 */ // MAX_STR_COUNT - upper limit for number of strings, not the current count strings
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user