Query before destroying important structures (rail stations and industries)
Prior to this change, the use of NewObjects often lead to the problem of players trying to clear those and accidentally destroying a rail station or (when using magic bulldozer) an industry. This action cannot be undone. This change shows a query making sure the player actually wants to destroy the station or industry. NOTE: The switch to a std::function no longer allows for the inequality check in ShowQuery in misc_gui. If this was required a different solution has to be found.
This commit is contained in:
@@ -5550,6 +5550,10 @@ STR_ERROR_NAME_MUST_BE_UNIQUE :{WHITE}Name mus
|
|||||||
STR_ERROR_GENERIC_OBJECT_IN_THE_WAY :{WHITE}{1:STRING} in the way
|
STR_ERROR_GENERIC_OBJECT_IN_THE_WAY :{WHITE}{1:STRING} in the way
|
||||||
STR_ERROR_NOT_ALLOWED_WHILE_PAUSED :{WHITE}Not allowed while paused
|
STR_ERROR_NOT_ALLOWED_WHILE_PAUSED :{WHITE}Not allowed while paused
|
||||||
|
|
||||||
|
# Clear area query
|
||||||
|
STR_QUERY_CLEAR_AREA_CAPTION :{WHITE}Clear area
|
||||||
|
STR_CLEAR_AREA_CONFIRMATION_TEXT :{YELLOW}You are about to destroy an important structure. Are you sure?
|
||||||
|
|
||||||
# Local authority errors
|
# Local authority errors
|
||||||
STR_ERROR_LOCAL_AUTHORITY_REFUSES_TO_ALLOW_THIS :{WHITE}{TOWN} local authority refuses to allow this
|
STR_ERROR_LOCAL_AUTHORITY_REFUSES_TO_ALLOW_THIS :{WHITE}{TOWN} local authority refuses to allow this
|
||||||
STR_ERROR_LOCAL_AUTHORITY_REFUSES_AIRPORT :{WHITE}{TOWN} local authority refuses to allow another airport to be built in this town
|
STR_ERROR_LOCAL_AUTHORITY_REFUSES_AIRPORT :{WHITE}{TOWN} local authority refuses to allow another airport to be built in this town
|
||||||
|
@@ -12,6 +12,8 @@
|
|||||||
#include "landscape.h"
|
#include "landscape.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
#include "command_func.h"
|
#include "command_func.h"
|
||||||
#include "company_func.h"
|
#include "company_func.h"
|
||||||
#include "town.h"
|
#include "town.h"
|
||||||
@@ -1230,19 +1232,19 @@ void ShowQueryString(StringID str, StringID caption, uint maxsize, Window *paren
|
|||||||
* Window used for asking the user a YES/NO question.
|
* Window used for asking the user a YES/NO question.
|
||||||
*/
|
*/
|
||||||
struct QueryWindow : public Window {
|
struct QueryWindow : public Window {
|
||||||
QueryCallbackProc *proc; ///< callback function executed on closing of popup. Window* points to parent, bool is true if 'yes' clicked, false otherwise
|
QueryCallbackProc proc; ///< callback function executed on closing of popup. Window* points to parent, bool is true if 'yes' clicked, false otherwise
|
||||||
uint64 params[10]; ///< local copy of #_global_string_params
|
uint64 params[10]; ///< local copy of #_global_string_params
|
||||||
StringID message; ///< message shown for query window
|
StringID message; ///< message shown for query window
|
||||||
StringID caption; ///< title of window
|
StringID caption; ///< title of window
|
||||||
|
|
||||||
QueryWindow(WindowDesc *desc, StringID caption, StringID message, Window *parent, QueryCallbackProc *callback) : Window(desc)
|
QueryWindow(WindowDesc *desc, StringID caption, StringID message, Window *parent, QueryCallbackProc callback) : Window(desc)
|
||||||
{
|
{
|
||||||
/* Create a backup of the variadic arguments to strings because it will be
|
/* Create a backup of the variadic arguments to strings because it will be
|
||||||
* overridden pretty often. We will copy these back for drawing */
|
* overridden pretty often. We will copy these back for drawing */
|
||||||
CopyOutDParam(this->params, 0, lengthof(this->params));
|
CopyOutDParam(this->params, 0, lengthof(this->params));
|
||||||
this->caption = caption;
|
this->caption = caption;
|
||||||
this->message = message;
|
this->message = message;
|
||||||
this->proc = callback;
|
this->proc = std::move(callback);
|
||||||
this->parent = parent;
|
this->parent = parent;
|
||||||
|
|
||||||
this->InitNested(WN_CONFIRM_POPUP_QUERY);
|
this->InitNested(WN_CONFIRM_POPUP_QUERY);
|
||||||
@@ -1299,7 +1301,7 @@ struct QueryWindow : public Window {
|
|||||||
case WID_Q_YES: {
|
case WID_Q_YES: {
|
||||||
/* in the Generate New World window, clicking 'Yes' causes
|
/* in the Generate New World window, clicking 'Yes' causes
|
||||||
* DeleteNonVitalWindows() to be called - we shouldn't be in a window then */
|
* DeleteNonVitalWindows() to be called - we shouldn't be in a window then */
|
||||||
QueryCallbackProc *proc = this->proc;
|
QueryCallbackProc proc = this->proc;
|
||||||
Window *parent = this->parent;
|
Window *parent = this->parent;
|
||||||
/* Prevent the destructor calling the callback function */
|
/* Prevent the destructor calling the callback function */
|
||||||
this->proc = nullptr;
|
this->proc = nullptr;
|
||||||
@@ -1364,9 +1366,9 @@ static WindowDesc _query_desc(
|
|||||||
* @param message string that will be shown for the window
|
* @param message string that will be shown for the window
|
||||||
* @param parent pointer to parent window, if this pointer is nullptr the parent becomes
|
* @param parent pointer to parent window, if this pointer is nullptr the parent becomes
|
||||||
* the main window WC_MAIN_WINDOW
|
* the main window WC_MAIN_WINDOW
|
||||||
* @param callback callback function pointer to set in the window descriptor
|
* @param callback callback function to set in the window descriptor
|
||||||
*/
|
*/
|
||||||
void ShowQuery(StringID caption, StringID message, Window *parent, QueryCallbackProc *callback)
|
void ShowQuery(StringID caption, StringID message, Window *parent, QueryCallbackProc callback)
|
||||||
{
|
{
|
||||||
if (parent == nullptr) parent = FindWindowById(WC_MAIN_WINDOW, 0);
|
if (parent == nullptr) parent = FindWindowById(WC_MAIN_WINDOW, 0);
|
||||||
|
|
||||||
@@ -1374,7 +1376,7 @@ void ShowQuery(StringID caption, StringID message, Window *parent, QueryCallback
|
|||||||
if (w->window_class != WC_CONFIRM_POPUP_QUERY) continue;
|
if (w->window_class != WC_CONFIRM_POPUP_QUERY) continue;
|
||||||
|
|
||||||
const QueryWindow *qw = (const QueryWindow *)w;
|
const QueryWindow *qw = (const QueryWindow *)w;
|
||||||
if (qw->parent != parent || qw->proc != callback) continue;
|
if (qw->parent != parent) continue;
|
||||||
|
|
||||||
delete qw;
|
delete qw;
|
||||||
break;
|
break;
|
||||||
|
@@ -2141,7 +2141,7 @@ public:
|
|||||||
|
|
||||||
case WID_CL_MATRIX: {
|
case WID_CL_MATRIX: {
|
||||||
StringID text = STR_NULL;
|
StringID text = STR_NULL;
|
||||||
QueryCallbackProc *callback = nullptr;
|
QueryCallbackProc callback = nullptr;
|
||||||
|
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case DD_CLIENT_ADMIN_KICK:
|
case DD_CLIENT_ADMIN_KICK:
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
#include "hotkeys.h"
|
#include "hotkeys.h"
|
||||||
#include "engine_base.h"
|
#include "engine_base.h"
|
||||||
#include "terraform_gui.h"
|
#include "terraform_gui.h"
|
||||||
|
#include "cheat_func.h"
|
||||||
#include "town_gui.h"
|
#include "town_gui.h"
|
||||||
#include "zoom_func.h"
|
#include "zoom_func.h"
|
||||||
|
|
||||||
@@ -95,6 +96,30 @@ static void GenerateRockyArea(TileIndex end, TileIndex start)
|
|||||||
if (success && _settings_client.sound.confirm) SndPlayTileFx(SND_1F_CONSTRUCTION_OTHER, end);
|
if (success && _settings_client.sound.confirm) SndPlayTileFx(SND_1F_CONSTRUCTION_OTHER, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Checks if the area contains any structures that are important enough to query about first */
|
||||||
|
static bool IsIndustryOrRailStationInArea(TileIndex start_tile, TileIndex end_tile, bool diagonal)
|
||||||
|
{
|
||||||
|
std::unique_ptr<TileIterator> tile_iterator;
|
||||||
|
|
||||||
|
if (diagonal) {
|
||||||
|
tile_iterator = std::make_unique<DiagonalTileIterator>(end_tile, start_tile);
|
||||||
|
} else {
|
||||||
|
tile_iterator = std::make_unique<OrthogonalTileIterator>(end_tile, start_tile);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool destroying_industry_or_station = false;
|
||||||
|
|
||||||
|
for (; *tile_iterator != INVALID_TILE; ++(*tile_iterator)) {
|
||||||
|
if ((_cheats.magic_bulldozer.value && IsTileType(*tile_iterator, MP_INDUSTRY)) ||
|
||||||
|
IsRailStationTile(*tile_iterator)) {
|
||||||
|
destroying_industry_or_station = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return destroying_industry_or_station;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A central place to handle all X_AND_Y dragged GUI functions.
|
* A central place to handle all X_AND_Y dragged GUI functions.
|
||||||
* @param proc Procedure related to the dragging
|
* @param proc Procedure related to the dragging
|
||||||
@@ -114,9 +139,23 @@ bool GUIPlaceProcDragXY(ViewportDragDropSelectionProcess proc, TileIndex start_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (proc) {
|
switch (proc) {
|
||||||
case DDSP_DEMOLISH_AREA:
|
case DDSP_DEMOLISH_AREA: {
|
||||||
|
const bool should_query_first = IsIndustryOrRailStationInArea(start_tile, end_tile, _ctrl_pressed);
|
||||||
|
|
||||||
|
const auto cmd_clear_area = [=](Window*, bool confirmed) {
|
||||||
|
if (confirmed) {
|
||||||
DoCommandP(end_tile, start_tile, _ctrl_pressed ? 1 : 0, CMD_CLEAR_AREA | CMD_MSG(STR_ERROR_CAN_T_CLEAR_THIS_AREA), CcPlaySound_EXPLOSION);
|
DoCommandP(end_tile, start_tile, _ctrl_pressed ? 1 : 0, CMD_CLEAR_AREA | CMD_MSG(STR_ERROR_CAN_T_CLEAR_THIS_AREA), CcPlaySound_EXPLOSION);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (should_query_first) {
|
||||||
|
ShowQuery(STR_QUERY_CLEAR_AREA_CAPTION, STR_CLEAR_AREA_CONFIRMATION_TEXT, nullptr, cmd_clear_area);
|
||||||
|
} else {
|
||||||
|
cmd_clear_area(nullptr, true);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case DDSP_RAISE_AND_LEVEL_AREA:
|
case DDSP_RAISE_AND_LEVEL_AREA:
|
||||||
DoCommandP(end_tile, start_tile, LM_RAISE << 1 | (_ctrl_pressed ? 1 : 0), CMD_LEVEL_LAND | CMD_MSG(STR_ERROR_CAN_T_RAISE_LAND_HERE), CcTerraform);
|
DoCommandP(end_tile, start_tile, LM_RAISE << 1 | (_ctrl_pressed ? 1 : 0), CMD_LEVEL_LAND | CMD_MSG(STR_ERROR_CAN_T_RAISE_LAND_HERE), CcTerraform);
|
||||||
break;
|
break;
|
||||||
|
@@ -10,10 +10,13 @@
|
|||||||
#ifndef TEXTBUF_GUI_H
|
#ifndef TEXTBUF_GUI_H
|
||||||
#define TEXTBUF_GUI_H
|
#define TEXTBUF_GUI_H
|
||||||
|
|
||||||
#include "window_type.h"
|
|
||||||
#include "string_type.h"
|
#include "string_type.h"
|
||||||
#include "strings_type.h"
|
#include "strings_type.h"
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
struct Window;
|
||||||
|
|
||||||
/** Flags used in ShowQueryString() call */
|
/** Flags used in ShowQueryString() call */
|
||||||
enum QueryStringFlags {
|
enum QueryStringFlags {
|
||||||
QSF_NONE = 0,
|
QSF_NONE = 0,
|
||||||
@@ -26,10 +29,10 @@ enum QueryStringFlags {
|
|||||||
DECLARE_ENUM_AS_BIT_SET(QueryStringFlags)
|
DECLARE_ENUM_AS_BIT_SET(QueryStringFlags)
|
||||||
|
|
||||||
/** Callback procedure for the ShowQuery method. */
|
/** Callback procedure for the ShowQuery method. */
|
||||||
typedef void QueryCallbackProc(Window*, bool);
|
typedef std::function<void(Window*, bool)> QueryCallbackProc;
|
||||||
|
|
||||||
void ShowQueryString(StringID str, StringID caption, uint max_len, Window *parent, CharSetFilter afilter, QueryStringFlags flags);
|
void ShowQueryString(StringID str, StringID caption, uint max_len, Window *parent, CharSetFilter afilter, QueryStringFlags flags);
|
||||||
void ShowQuery(StringID caption, StringID message, Window *w, QueryCallbackProc *callback);
|
void ShowQuery(StringID caption, StringID message, Window *w, QueryCallbackProc callback);
|
||||||
|
|
||||||
/** The number of 'characters' on the on-screen keyboard. */
|
/** The number of 'characters' on the on-screen keyboard. */
|
||||||
static const uint OSK_KEYBOARD_ENTRIES = 50;
|
static const uint OSK_KEYBOARD_ENTRIES = 50;
|
||||||
|
Reference in New Issue
Block a user