Allow overriding town settings on a per-town basis
Add a setting for whether this is allowed for non-privileged multiplayer clients
This commit is contained in:
@@ -155,6 +155,7 @@ CommandProc CmdFoundTown;
|
|||||||
CommandProc CmdRenameTown;
|
CommandProc CmdRenameTown;
|
||||||
CommandProc CmdRenameTownNonAdmin;
|
CommandProc CmdRenameTownNonAdmin;
|
||||||
CommandProc CmdDoTownAction;
|
CommandProc CmdDoTownAction;
|
||||||
|
CommandProc CmdOverrideTownSetting;
|
||||||
CommandProc CmdTownGrowthRate;
|
CommandProc CmdTownGrowthRate;
|
||||||
CommandProc CmdTownRating;
|
CommandProc CmdTownRating;
|
||||||
CommandProc CmdTownCargoGoal;
|
CommandProc CmdTownCargoGoal;
|
||||||
@@ -401,6 +402,7 @@ static const Command _command_proc_table[] = {
|
|||||||
DEF_CMD(CmdRenameTown, CMD_DEITY | CMD_SERVER, CMDT_OTHER_MANAGEMENT ), // CMD_RENAME_TOWN
|
DEF_CMD(CmdRenameTown, CMD_DEITY | CMD_SERVER, CMDT_OTHER_MANAGEMENT ), // CMD_RENAME_TOWN
|
||||||
DEF_CMD(CmdRenameTownNonAdmin, 0, CMDT_OTHER_MANAGEMENT ), // CMD_RENAME_TOWN_NON_ADMIN
|
DEF_CMD(CmdRenameTownNonAdmin, 0, CMDT_OTHER_MANAGEMENT ), // CMD_RENAME_TOWN_NON_ADMIN
|
||||||
DEF_CMD(CmdDoTownAction, 0, CMDT_LANDSCAPE_CONSTRUCTION), // CMD_DO_TOWN_ACTION
|
DEF_CMD(CmdDoTownAction, 0, CMDT_LANDSCAPE_CONSTRUCTION), // CMD_DO_TOWN_ACTION
|
||||||
|
DEF_CMD(CmdOverrideTownSetting, 0, CMDT_OTHER_MANAGEMENT ), // CMD_TOWN_SETTING_OVERRIDE
|
||||||
DEF_CMD(CmdTownCargoGoal, CMD_LOG_AUX | CMD_DEITY, CMDT_OTHER_MANAGEMENT ), // CMD_TOWN_CARGO_GOAL
|
DEF_CMD(CmdTownCargoGoal, CMD_LOG_AUX | CMD_DEITY, CMDT_OTHER_MANAGEMENT ), // CMD_TOWN_CARGO_GOAL
|
||||||
DEF_CMD(CmdTownGrowthRate, CMD_LOG_AUX | CMD_DEITY, CMDT_OTHER_MANAGEMENT ), // CMD_TOWN_GROWTH_RATE
|
DEF_CMD(CmdTownGrowthRate, CMD_LOG_AUX | CMD_DEITY, CMDT_OTHER_MANAGEMENT ), // CMD_TOWN_GROWTH_RATE
|
||||||
DEF_CMD(CmdTownRating, CMD_LOG_AUX | CMD_DEITY, CMDT_OTHER_MANAGEMENT ), // CMD_TOWN_RATING
|
DEF_CMD(CmdTownRating, CMD_LOG_AUX | CMD_DEITY, CMDT_OTHER_MANAGEMENT ), // CMD_TOWN_RATING
|
||||||
|
@@ -347,6 +347,7 @@ enum Commands {
|
|||||||
CMD_RENAME_TOWN, ///< rename a town
|
CMD_RENAME_TOWN, ///< rename a town
|
||||||
CMD_RENAME_TOWN_NON_ADMIN, ///< rename a town, non-admin command
|
CMD_RENAME_TOWN_NON_ADMIN, ///< rename a town, non-admin command
|
||||||
CMD_DO_TOWN_ACTION, ///< do a action from the town detail window (like advertises or bribe)
|
CMD_DO_TOWN_ACTION, ///< do a action from the town detail window (like advertises or bribe)
|
||||||
|
CMD_TOWN_SETTING_OVERRIDE, ///< override a town setting
|
||||||
CMD_TOWN_CARGO_GOAL, ///< set the goal of a cargo for a town
|
CMD_TOWN_CARGO_GOAL, ///< set the goal of a cargo for a town
|
||||||
CMD_TOWN_GROWTH_RATE, ///< set the town growth rate
|
CMD_TOWN_GROWTH_RATE, ///< set the town growth rate
|
||||||
CMD_TOWN_RATING, ///< set rating of a company in a town
|
CMD_TOWN_RATING, ///< set rating of a company in a town
|
||||||
|
@@ -1332,6 +1332,8 @@ STR_CONFIG_SETTING_MONEY_CHEAT_MULTIPLAYER :Allow multiplay
|
|||||||
STR_CONFIG_SETTING_MONEY_CHEAT_MULTIPLAYER_HELPTEXT :If enabled, non-admin multiplayer clients can use the money cheat. The money cheat is always available in single-player mode, and to the multiplayer server admin.
|
STR_CONFIG_SETTING_MONEY_CHEAT_MULTIPLAYER_HELPTEXT :If enabled, non-admin multiplayer clients can use the money cheat. The money cheat is always available in single-player mode, and to the multiplayer server admin.
|
||||||
STR_CONFIG_SETTING_RENAME_TOWNS_MULTIPLAYER :Allow multiplayer clients to rename towns: {STRING2}
|
STR_CONFIG_SETTING_RENAME_TOWNS_MULTIPLAYER :Allow multiplayer clients to rename towns: {STRING2}
|
||||||
STR_CONFIG_SETTING_RENAME_TOWNS_MULTIPLAYER_HELPTEXT :If enabled, non-admin multiplayer clients which are not spectating can rename towns. Renaming towns is always available in single-player mode, and to the multiplayer server admin.
|
STR_CONFIG_SETTING_RENAME_TOWNS_MULTIPLAYER_HELPTEXT :If enabled, non-admin multiplayer clients which are not spectating can rename towns. Renaming towns is always available in single-player mode, and to the multiplayer server admin.
|
||||||
|
STR_CONFIG_SETTING_OVERRIDE_TOWN_SETTINGS_MULTIPLAYER :Allow multiplayer clients to override town settings: {STRING2}
|
||||||
|
STR_CONFIG_SETTING_OVERRIDE_TOWN_SETTINGS_MULTIPLAYER_HELPTEXT :If enabled, non-admin multiplayer clients which are not spectating can override town settings, on a per-town basis. Overriding individual town settings is always available in single-player mode, and to the multiplayer server admin.
|
||||||
|
|
||||||
STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT :Map height limit: {STRING2}
|
STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT :Map height limit: {STRING2}
|
||||||
STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT_HELPTEXT :Set the maximum height of the map terrain. With "(auto)" a good value will be picked after terrain generation
|
STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT_HELPTEXT :Set the maximum height of the map terrain. With "(auto)" a good value will be picked after terrain generation
|
||||||
@@ -4478,6 +4480,17 @@ STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_NEW_BUILDINGS :{YELLOW}Fund th
|
|||||||
STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_EXCLUSIVE_TRANSPORT :{YELLOW}Buy 1 year's exclusive transport rights in town.{}Town authority will not allow passengers and cargo to use your competitors' stations.{}Cost: {CURRENCY_LONG}
|
STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_EXCLUSIVE_TRANSPORT :{YELLOW}Buy 1 year's exclusive transport rights in town.{}Town authority will not allow passengers and cargo to use your competitors' stations.{}Cost: {CURRENCY_LONG}
|
||||||
STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_BRIBE :{YELLOW}Bribe the local authority to increase your rating, at the risk of a severe penalty if caught.{}Cost: {CURRENCY_LONG}
|
STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_BRIBE :{YELLOW}Bribe the local authority to increase your rating, at the risk of a severe penalty if caught.{}Cost: {CURRENCY_LONG}
|
||||||
|
|
||||||
|
###length 4
|
||||||
|
STR_LOCAL_AUTHORITY_SETTING_OVERRIDE_ALLOW_ROADS :Allowed to build roads
|
||||||
|
STR_LOCAL_AUTHORITY_SETTING_OVERRIDE_ALLOW_LEVEL_CROSSINGS :Allowed to level crossings
|
||||||
|
STR_LOCAL_AUTHORITY_SETTING_OVERRIDE_TUNNELS :Allowed to build tunnels
|
||||||
|
STR_LOCAL_AUTHORITY_SETTING_OVERRIDE_MAX_ROAD_SLOPE :Limit building continuous inclined roads
|
||||||
|
|
||||||
|
STR_LOCAL_AUTHORITY_SETTING_OVERRIDE_DEFAULT :Default ({STRING1})
|
||||||
|
STR_LOCAL_AUTHORITY_SETTING_OVERRIDE_STR :{STRING}: {PUSH_COLOUR}{YELLOW}{STRING2}{POP_COLOUR}
|
||||||
|
STR_LOCAL_AUTHORITY_SETTING_OVERRIDE_TEXT :{YELLOW}Override the following setting for this individual town:{}{STRING}{}{STRING}
|
||||||
|
STR_LOCAL_AUTHORITY_SETTING_OVERRIDE_TOOLTIP :{BLACK}Change setting override
|
||||||
|
|
||||||
# Goal window
|
# Goal window
|
||||||
STR_GOALS_CAPTION :{WHITE}{COMPANY} Goals
|
STR_GOALS_CAPTION :{WHITE}{COMPANY} Goals
|
||||||
STR_GOALS_SPECTATOR_CAPTION :{WHITE}Global Goals
|
STR_GOALS_SPECTATOR_CAPTION :{WHITE}Global Goals
|
||||||
|
@@ -175,6 +175,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
|
|||||||
{ XSLFI_INDUSTRY_ANIM_MASK, XSCF_IGNORABLE_ALL, 1, 1, "industry_anim_mask", nullptr, nullptr, nullptr },
|
{ XSLFI_INDUSTRY_ANIM_MASK, XSCF_IGNORABLE_ALL, 1, 1, "industry_anim_mask", nullptr, nullptr, nullptr },
|
||||||
{ XSLFI_NEW_SIGNAL_STYLES, XSCF_NULL, 2, 2, "new_signal_styles", nullptr, nullptr, "XBST,NSID" },
|
{ XSLFI_NEW_SIGNAL_STYLES, XSCF_NULL, 2, 2, "new_signal_styles", nullptr, nullptr, "XBST,NSID" },
|
||||||
{ XSLFI_NO_TREE_COUNTER, XSCF_IGNORABLE_ALL, 1, 1, "no_tree_counter", nullptr, nullptr, nullptr },
|
{ XSLFI_NO_TREE_COUNTER, XSCF_IGNORABLE_ALL, 1, 1, "no_tree_counter", nullptr, nullptr, nullptr },
|
||||||
|
{ XSLFI_TOWN_SETTING_OVERRIDE, XSCF_NULL, 1, 1, "town_setting_override", nullptr, nullptr, nullptr },
|
||||||
{ XSLFI_SCRIPT_INT64, XSCF_NULL, 1, 1, "script_int64", nullptr, nullptr, nullptr },
|
{ XSLFI_SCRIPT_INT64, XSCF_NULL, 1, 1, "script_int64", nullptr, nullptr, nullptr },
|
||||||
{ XSLFI_U64_TICK_COUNTER, XSCF_NULL, 1, 1, "u64_tick_counter", nullptr, nullptr, nullptr },
|
{ XSLFI_U64_TICK_COUNTER, XSCF_NULL, 1, 1, "u64_tick_counter", nullptr, nullptr, nullptr },
|
||||||
{ XSLFI_NULL, XSCF_NULL, 0, 0, nullptr, nullptr, nullptr, nullptr },// This is the end marker
|
{ XSLFI_NULL, XSCF_NULL, 0, 0, nullptr, nullptr, nullptr, nullptr },// This is the end marker
|
||||||
|
@@ -128,6 +128,7 @@ enum SlXvFeatureIndex {
|
|||||||
XSLFI_INDUSTRY_ANIM_MASK, ///< Industry tile animation masking
|
XSLFI_INDUSTRY_ANIM_MASK, ///< Industry tile animation masking
|
||||||
XSLFI_NEW_SIGNAL_STYLES, ///< New signal styles
|
XSLFI_NEW_SIGNAL_STYLES, ///< New signal styles
|
||||||
XSLFI_NO_TREE_COUNTER, ///< No tree counter
|
XSLFI_NO_TREE_COUNTER, ///< No tree counter
|
||||||
|
XSLFI_TOWN_SETTING_OVERRIDE, ///< Town setting overrides
|
||||||
|
|
||||||
XSLFI_SCRIPT_INT64, ///< See: SLV_SCRIPT_INT64
|
XSLFI_SCRIPT_INT64, ///< See: SLV_SCRIPT_INT64
|
||||||
XSLFI_U64_TICK_COUNTER, ///< See: SLV_U64_TICK_COUNTER
|
XSLFI_U64_TICK_COUNTER, ///< See: SLV_U64_TICK_COUNTER
|
||||||
|
@@ -243,6 +243,11 @@ static const SaveLoad _town_desc[] = {
|
|||||||
SLE_CONDNULL(4, SLV_166, SLV_EXTEND_CARGOTYPES), ///< cargo_produced, no longer in use
|
SLE_CONDNULL(4, SLV_166, SLV_EXTEND_CARGOTYPES), ///< cargo_produced, no longer in use
|
||||||
SLE_CONDNULL(8, SLV_EXTEND_CARGOTYPES, SLV_REMOVE_TOWN_CARGO_CACHE), ///< cargo_produced, no longer in use
|
SLE_CONDNULL(8, SLV_EXTEND_CARGOTYPES, SLV_REMOVE_TOWN_CARGO_CACHE), ///< cargo_produced, no longer in use
|
||||||
SLE_CONDNULL(30, SLV_2, SLV_REMOVE_TOWN_CARGO_CACHE), ///< old reserved space
|
SLE_CONDNULL(30, SLV_2, SLV_REMOVE_TOWN_CARGO_CACHE), ///< old reserved space
|
||||||
|
|
||||||
|
SLE_CONDVAR_X(Town, override_flags, SLE_UINT8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_TOWN_SETTING_OVERRIDE)),
|
||||||
|
SLE_CONDVAR_X(Town, override_values, SLE_UINT8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_TOWN_SETTING_OVERRIDE)),
|
||||||
|
SLE_CONDVAR_X(Town, build_tunnels, SLE_UINT8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_TOWN_SETTING_OVERRIDE)),
|
||||||
|
SLE_CONDVAR_X(Town, max_road_slope, SLE_UINT8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_TOWN_SETTING_OVERRIDE)),
|
||||||
};
|
};
|
||||||
|
|
||||||
static const SaveLoad _town_supplied_desc[] = {
|
static const SaveLoad _town_supplied_desc[] = {
|
||||||
|
@@ -1465,6 +1465,11 @@ static void DifficultyRenameTownsMultiplayerChange(int32 new_value)
|
|||||||
SetWindowClassesDirty(WC_TOWN_VIEW);
|
SetWindowClassesDirty(WC_TOWN_VIEW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void DifficultyOverrideTownSettingsMultiplayerChange(int32 new_value)
|
||||||
|
{
|
||||||
|
SetWindowClassesDirty(WC_TOWN_AUTHORITY);
|
||||||
|
}
|
||||||
|
|
||||||
static void MaxNoAIsChange(int32 new_value)
|
static void MaxNoAIsChange(int32 new_value)
|
||||||
{
|
{
|
||||||
if (GetGameSettings().difficulty.max_no_competitors != 0 &&
|
if (GetGameSettings().difficulty.max_no_competitors != 0 &&
|
||||||
|
@@ -2283,6 +2283,7 @@ static SettingsContainer &GetSettingsTree()
|
|||||||
ai->Add(new SettingEntry("economy.min_years_for_shares"));
|
ai->Add(new SettingEntry("economy.min_years_for_shares"));
|
||||||
ai->Add(new SettingEntry("difficulty.money_cheat_in_multiplayer"));
|
ai->Add(new SettingEntry("difficulty.money_cheat_in_multiplayer"));
|
||||||
ai->Add(new SettingEntry("difficulty.rename_towns_in_multiplayer"));
|
ai->Add(new SettingEntry("difficulty.rename_towns_in_multiplayer"));
|
||||||
|
ai->Add(new SettingEntry("difficulty.override_town_settings_in_multiplayer"));
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsPage *scenario = main->Add(new SettingsPage(STR_CONFIG_SETTING_SCENARIO_EDITOR));
|
SettingsPage *scenario = main->Add(new SettingsPage(STR_CONFIG_SETTING_SCENARIO_EDITOR));
|
||||||
|
@@ -97,6 +97,7 @@ struct DifficultySettings {
|
|||||||
byte town_council_tolerance; ///< minimum required town ratings to be allowed to demolish stuff
|
byte town_council_tolerance; ///< minimum required town ratings to be allowed to demolish stuff
|
||||||
bool money_cheat_in_multiplayer; ///< is the money cheat permitted for non-admin multiplayer clients
|
bool money_cheat_in_multiplayer; ///< is the money cheat permitted for non-admin multiplayer clients
|
||||||
bool rename_towns_in_multiplayer; ///< is renaming towns permitted for non-admin multiplayer clients
|
bool rename_towns_in_multiplayer; ///< is renaming towns permitted for non-admin multiplayer clients
|
||||||
|
bool override_town_settings_in_multiplayer; ///< is overriding town settings permitted for non-admin multiplayer clients
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Settings relating to viewport/smallmap scrolling. */
|
/** Settings relating to viewport/smallmap scrolling. */
|
||||||
|
@@ -27,6 +27,7 @@ static bool TownCouncilToleranceAdjust(int32 &new_value);
|
|||||||
static void DifficultyNoiseChange(int32 new_value);
|
static void DifficultyNoiseChange(int32 new_value);
|
||||||
static void DifficultyMoneyCheatMultiplayerChange(int32 new_value);
|
static void DifficultyMoneyCheatMultiplayerChange(int32 new_value);
|
||||||
static void DifficultyRenameTownsMultiplayerChange(int32 new_value);
|
static void DifficultyRenameTownsMultiplayerChange(int32 new_value);
|
||||||
|
static void DifficultyOverrideTownSettingsMultiplayerChange(int32 new_value);
|
||||||
static void MaxNoAIsChange(int32 new_value);
|
static void MaxNoAIsChange(int32 new_value);
|
||||||
static bool CheckRoadSide(int32 &new_value);
|
static bool CheckRoadSide(int32 &new_value);
|
||||||
static void RoadSideChanged(int32 new_value);
|
static void RoadSideChanged(int32 new_value);
|
||||||
@@ -476,6 +477,15 @@ post_cb = DifficultyRenameTownsMultiplayerChange
|
|||||||
cat = SC_EXPERT
|
cat = SC_EXPERT
|
||||||
patxname = ""cheat.difficulty.rename_towns_in_multiplayer""
|
patxname = ""cheat.difficulty.rename_towns_in_multiplayer""
|
||||||
|
|
||||||
|
[SDT_BOOL]
|
||||||
|
var = difficulty.override_town_settings_in_multiplayer
|
||||||
|
def = false
|
||||||
|
str = STR_CONFIG_SETTING_OVERRIDE_TOWN_SETTINGS_MULTIPLAYER
|
||||||
|
strhelp = STR_CONFIG_SETTING_OVERRIDE_TOWN_SETTINGS_MULTIPLAYER_HELPTEXT
|
||||||
|
post_cb = DifficultyOverrideTownSettingsMultiplayerChange
|
||||||
|
cat = SC_EXPERT
|
||||||
|
patxname = ""cheat.difficulty.override_town_settings_in_multiplayer""
|
||||||
|
|
||||||
[SDTG_VAR]
|
[SDTG_VAR]
|
||||||
name = ""diff_level""
|
name = ""diff_level""
|
||||||
var = _old_diff_level
|
var = _old_diff_level
|
||||||
|
34
src/town.h
34
src/town.h
@@ -59,6 +59,14 @@ struct TownCache {
|
|||||||
BuildingCounts<uint16> building_counts; ///< The number of each type of building in the town
|
BuildingCounts<uint16> building_counts; ///< The number of each type of building in the town
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Town setting override flags */
|
||||||
|
enum TownSettingOverrideFlags {
|
||||||
|
TSOF_OVERRIDE_BUILD_ROADS = 0,
|
||||||
|
TSOF_OVERRIDE_BUILD_LEVEL_CROSSINGS = 1,
|
||||||
|
TSOF_OVERRIDE_BUILD_TUNNELS = 2,
|
||||||
|
TSOF_OVERRIDE_BUILD_INCLINED_ROADS = 3,
|
||||||
|
};
|
||||||
|
|
||||||
/** Town data structure. */
|
/** Town data structure. */
|
||||||
struct Town : TownPool::PoolItem<&_town_pool> {
|
struct Town : TownPool::PoolItem<&_town_pool> {
|
||||||
TileIndex xy; ///< town center tile
|
TileIndex xy; ///< town center tile
|
||||||
@@ -73,6 +81,12 @@ struct Town : TownPool::PoolItem<&_town_pool> {
|
|||||||
mutable std::string cached_name; ///< NOSAVE: Cache of the resolved name of the town, if not using a custom town name
|
mutable std::string cached_name; ///< NOSAVE: Cache of the resolved name of the town, if not using a custom town name
|
||||||
|
|
||||||
byte flags; ///< See #TownFlags.
|
byte flags; ///< See #TownFlags.
|
||||||
|
|
||||||
|
byte override_flags; ///< Bitmask of enabled flag overrides. See #TownSettingOverrideFlags.
|
||||||
|
byte override_values; ///< Bitmask of flag override values. See #TownSettingOverrideFlags.
|
||||||
|
TownTunnelMode build_tunnels; ///< If/when towns are allowed to build road tunnels (if TSOF_OVERRIDE_BUILD_TUNNELS set in override_flags)
|
||||||
|
uint8 max_road_slope; ///< Maximum number of consecutive sloped road tiles which towns are allowed to build (if TSOF_OVERRIDE_BUILD_INCLINED_ROADS set in override_flags)
|
||||||
|
|
||||||
uint16 church_count; ///< Number of church buildings in the town.
|
uint16 church_count; ///< Number of church buildings in the town.
|
||||||
uint16 stadium_count; ///< Number of stadium buildings in the town.
|
uint16 stadium_count; ///< Number of stadium buildings in the town.
|
||||||
|
|
||||||
@@ -173,6 +187,26 @@ struct Town : TownPool::PoolItem<&_town_pool> {
|
|||||||
return this->cached_name.c_str();
|
return this->cached_name.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool GetAllowBuildRoads() const
|
||||||
|
{
|
||||||
|
return HasBit(this->override_flags, TSOF_OVERRIDE_BUILD_ROADS) ? HasBit(this->override_values, TSOF_OVERRIDE_BUILD_ROADS) : _settings_game.economy.allow_town_roads;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool GetAllowBuildLevelCrossings() const
|
||||||
|
{
|
||||||
|
return HasBit(this->override_flags, TSOF_OVERRIDE_BUILD_LEVEL_CROSSINGS) ? HasBit(this->override_values, TSOF_OVERRIDE_BUILD_LEVEL_CROSSINGS) : _settings_game.economy.allow_town_level_crossings;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline TownTunnelMode GetBuildTunnelMode() const
|
||||||
|
{
|
||||||
|
return HasBit(this->override_flags, TSOF_OVERRIDE_BUILD_TUNNELS) ? this->build_tunnels : _settings_game.economy.town_build_tunnels;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint8 GetBuildMaxRoadSlope() const
|
||||||
|
{
|
||||||
|
return HasBit(this->override_flags, TSOF_OVERRIDE_BUILD_INCLINED_ROADS) ? this->max_road_slope : _settings_game.economy.town_max_road_slope;
|
||||||
|
}
|
||||||
|
|
||||||
static inline Town *GetByTile(TileIndex tile)
|
static inline Town *GetByTile(TileIndex tile)
|
||||||
{
|
{
|
||||||
return Town::Get(GetTownIndex(tile));
|
return Town::Get(GetTownIndex(tile));
|
||||||
|
@@ -67,7 +67,7 @@ static Rect _record_house_rect;
|
|||||||
TownPool _town_pool("Town");
|
TownPool _town_pool("Town");
|
||||||
INSTANTIATE_POOL_METHODS(Town)
|
INSTANTIATE_POOL_METHODS(Town)
|
||||||
|
|
||||||
static bool CanFollowRoad(TileIndex tile, DiagDirection dir);
|
static bool CanFollowRoad(const Town *t, TileIndex tile, DiagDirection dir);
|
||||||
|
|
||||||
TownKdtree _town_kdtree(&Kdtree_TownXYFunc);
|
TownKdtree _town_kdtree(&Kdtree_TownXYFunc);
|
||||||
|
|
||||||
@@ -1311,7 +1311,7 @@ static bool CanRoadContinueIntoNextTile(const Town *t, const TileIndex tile, con
|
|||||||
|
|
||||||
/* If the next tile is a railroad track, check if towns are allowed to build level crossings.
|
/* If the next tile is a railroad track, check if towns are allowed to build level crossings.
|
||||||
* If level crossing are not allowed, reject the construction. Else allow DoCommand to determine if the rail track is buildable. */
|
* If level crossing are not allowed, reject the construction. Else allow DoCommand to determine if the rail track is buildable. */
|
||||||
if (IsTileType(next_tile, MP_RAILWAY) && !_settings_game.economy.allow_town_level_crossings) return false;
|
if (IsTileType(next_tile, MP_RAILWAY) && !t->GetAllowBuildLevelCrossings()) return false;
|
||||||
|
|
||||||
/* If a road tile can be built, the construction is allowed. */
|
/* If a road tile can be built, the construction is allowed. */
|
||||||
return DoCommand(next_tile, rcmd | (rt << 4), t->index, DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD).Succeeded();
|
return DoCommand(next_tile, rcmd | (rt << 4), t->index, DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD).Succeeded();
|
||||||
@@ -1452,7 +1452,8 @@ static bool GrowTownWithTunnel(const Town *t, const TileIndex tile, const DiagDi
|
|||||||
{
|
{
|
||||||
assert(tunnel_dir < DIAGDIR_END);
|
assert(tunnel_dir < DIAGDIR_END);
|
||||||
|
|
||||||
if (_settings_game.economy.town_build_tunnels == TTM_FORBIDDEN) return false;
|
const TownTunnelMode tunnel_mode = t->GetBuildTunnelMode();
|
||||||
|
if (tunnel_mode == TTM_FORBIDDEN) return false;
|
||||||
|
|
||||||
Slope slope = GetTileSlope(tile);
|
Slope slope = GetTileSlope(tile);
|
||||||
|
|
||||||
@@ -1467,7 +1468,7 @@ static bool GrowTownWithTunnel(const Town *t, const TileIndex tile, const DiagDi
|
|||||||
|
|
||||||
/* There are two conditions for building tunnels: Under a mountain and under an obstruction. */
|
/* There are two conditions for building tunnels: Under a mountain and under an obstruction. */
|
||||||
if (CanRoadContinueIntoNextTile(t, tile, tunnel_dir)) {
|
if (CanRoadContinueIntoNextTile(t, tile, tunnel_dir)) {
|
||||||
if (_settings_game.economy.town_build_tunnels != TTM_ALLOWED) return false;
|
if (tunnel_mode != TTM_ALLOWED) return false;
|
||||||
|
|
||||||
/* Only tunnel under a mountain if the slope is continuous for at least 4 tiles. We want tunneling to be a last resort for large hills. */
|
/* Only tunnel under a mountain if the slope is continuous for at least 4 tiles. We want tunneling to be a last resort for large hills. */
|
||||||
TileIndex slope_tile = tile;
|
TileIndex slope_tile = tile;
|
||||||
@@ -1571,8 +1572,8 @@ static void GrowTownInTile(TileIndex *tile_ptr, RoadBits cur_rb, DiagDirection t
|
|||||||
* to say that this is the last iteration. */
|
* to say that this is the last iteration. */
|
||||||
_grow_town_result = GROWTH_SEARCH_STOPPED;
|
_grow_town_result = GROWTH_SEARCH_STOPPED;
|
||||||
|
|
||||||
if (!_settings_game.economy.allow_town_roads && !_generating_world) return;
|
if (!t1->GetAllowBuildRoads() && !_generating_world) return;
|
||||||
if (!_settings_game.economy.allow_town_level_crossings && IsTileType(tile, MP_RAILWAY)) return;
|
if (!t1->GetAllowBuildLevelCrossings() && IsTileType(tile, MP_RAILWAY)) return;
|
||||||
if (!MayTownModifyRoad(tile)) return;
|
if (!MayTownModifyRoad(tile)) return;
|
||||||
|
|
||||||
/* Remove hills etc */
|
/* Remove hills etc */
|
||||||
@@ -1618,7 +1619,8 @@ static void GrowTownInTile(TileIndex *tile_ptr, RoadBits cur_rb, DiagDirection t
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_settings_game.economy.town_max_road_slope > 0 && ((rcmd == ROAD_X) || (rcmd == ROAD_Y))) {
|
const uint8 max_road_slope = t1->GetBuildMaxRoadSlope();
|
||||||
|
if (max_road_slope > 0 && ((rcmd == ROAD_X) || (rcmd == ROAD_Y))) {
|
||||||
/* Limit consecutive sloped road tiles */
|
/* Limit consecutive sloped road tiles */
|
||||||
|
|
||||||
auto get_road_slope = [rcmd](TileIndex t) -> Slope {
|
auto get_road_slope = [rcmd](TileIndex t) -> Slope {
|
||||||
@@ -1633,7 +1635,7 @@ static void GrowTownInTile(TileIndex *tile_ptr, RoadBits cur_rb, DiagDirection t
|
|||||||
const int delta = TileOffsByDiagDir(ReverseDiagDir(target_dir));
|
const int delta = TileOffsByDiagDir(ReverseDiagDir(target_dir));
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
TileIndex t = tile;
|
TileIndex t = tile;
|
||||||
for (uint i = 0; i < _settings_game.economy.town_max_road_slope; i++) {
|
for (uint i = 0; i < max_road_slope; i++) {
|
||||||
t += delta;
|
t += delta;
|
||||||
if (!IsValidTile(t) || !IsNormalRoadTile(t) || GetRoadBits(t, RTT_ROAD) != rcmd || get_road_slope(t) != slope) {
|
if (!IsValidTile(t) || !IsNormalRoadTile(t) || GetRoadBits(t, RTT_ROAD) != rcmd || get_road_slope(t) != slope) {
|
||||||
ok = true;
|
ok = true;
|
||||||
@@ -1653,7 +1655,7 @@ static void GrowTownInTile(TileIndex *tile_ptr, RoadBits cur_rb, DiagDirection t
|
|||||||
* the fitting RoadBits */
|
* the fitting RoadBits */
|
||||||
_grow_town_result = GROWTH_SEARCH_STOPPED;
|
_grow_town_result = GROWTH_SEARCH_STOPPED;
|
||||||
|
|
||||||
if (!_settings_game.economy.allow_town_roads && !_generating_world) return;
|
if (!t1->GetAllowBuildRoads() && !_generating_world) return;
|
||||||
|
|
||||||
switch (t1->layout) {
|
switch (t1->layout) {
|
||||||
default: NOT_REACHED();
|
default: NOT_REACHED();
|
||||||
@@ -1691,7 +1693,7 @@ static void GrowTownInTile(TileIndex *tile_ptr, RoadBits cur_rb, DiagDirection t
|
|||||||
target_bits = DiagDirToRoadBits(target_dir);
|
target_bits = DiagDirToRoadBits(target_dir);
|
||||||
} while (!(cur_rb & target_bits));
|
} while (!(cur_rb & target_bits));
|
||||||
cur_rb &= ~target_bits;
|
cur_rb &= ~target_bits;
|
||||||
} while (!(target_dir == GetTunnelBridgeDirection(tile) || CanFollowRoad(tile, target_dir)));
|
} while (!(target_dir == GetTunnelBridgeDirection(tile) || CanFollowRoad(t1, tile, target_dir)));
|
||||||
if (target_dir == GetTunnelBridgeDirection(tile)) {
|
if (target_dir == GetTunnelBridgeDirection(tile)) {
|
||||||
/* cross the bridge */
|
/* cross the bridge */
|
||||||
*tile_ptr = GetOtherTunnelBridgeEnd(tile);
|
*tile_ptr = GetOtherTunnelBridgeEnd(tile);
|
||||||
@@ -1746,7 +1748,7 @@ static void GrowTownInTile(TileIndex *tile_ptr, RoadBits cur_rb, DiagDirection t
|
|||||||
|
|
||||||
if (!IsValidTile(house_tile)) return;
|
if (!IsValidTile(house_tile)) return;
|
||||||
|
|
||||||
if (target_dir != DIAGDIR_END && (_settings_game.economy.allow_town_roads || _generating_world)) {
|
if (target_dir != DIAGDIR_END && (t1->GetAllowBuildRoads() || _generating_world)) {
|
||||||
switch (t1->layout) {
|
switch (t1->layout) {
|
||||||
default: NOT_REACHED();
|
default: NOT_REACHED();
|
||||||
|
|
||||||
@@ -1811,18 +1813,19 @@ static void GrowTownInTile(TileIndex *tile_ptr, RoadBits cur_rb, DiagDirection t
|
|||||||
/**
|
/**
|
||||||
* Checks whether a road can be followed or is a dead end, that can not be extended to the next tile.
|
* Checks whether a road can be followed or is a dead end, that can not be extended to the next tile.
|
||||||
* This only checks trivial but often cases.
|
* This only checks trivial but often cases.
|
||||||
|
* @param t Town doing the following
|
||||||
* @param tile Start tile for road.
|
* @param tile Start tile for road.
|
||||||
* @param dir Direction for road to follow or build.
|
* @param dir Direction for road to follow or build.
|
||||||
* @return true If road is or can be connected in the specified direction.
|
* @return true If road is or can be connected in the specified direction.
|
||||||
*/
|
*/
|
||||||
static bool CanFollowRoad(TileIndex tile, DiagDirection dir)
|
static bool CanFollowRoad(const Town *t, TileIndex tile, DiagDirection dir)
|
||||||
{
|
{
|
||||||
TileIndex target_tile = tile + TileOffsByDiagDir(dir);
|
TileIndex target_tile = tile + TileOffsByDiagDir(dir);
|
||||||
if (!IsValidTile(target_tile)) return false;
|
if (!IsValidTile(target_tile)) return false;
|
||||||
if (HasTileWaterGround(target_tile)) return false;
|
if (HasTileWaterGround(target_tile)) return false;
|
||||||
|
|
||||||
RoadBits target_rb = GetTownRoadBits(target_tile);
|
RoadBits target_rb = GetTownRoadBits(target_tile);
|
||||||
if (_settings_game.economy.allow_town_roads || _generating_world) {
|
if (t->GetAllowBuildRoads() || _generating_world) {
|
||||||
/* Check whether a road connection exists or can be build. */
|
/* Check whether a road connection exists or can be build. */
|
||||||
switch (GetTileType(target_tile)) {
|
switch (GetTileType(target_tile)) {
|
||||||
case MP_ROAD:
|
case MP_ROAD:
|
||||||
@@ -1922,7 +1925,7 @@ static bool GrowTownAtRoad(Town *t, TileIndex tile)
|
|||||||
target_bits = DiagDirToRoadBits(target_dir);
|
target_bits = DiagDirToRoadBits(target_dir);
|
||||||
} while (!(cur_rb & target_bits));
|
} while (!(cur_rb & target_bits));
|
||||||
cur_rb &= ~target_bits;
|
cur_rb &= ~target_bits;
|
||||||
} while (!CanFollowRoad(tile, target_dir));
|
} while (!CanFollowRoad(t, tile, target_dir));
|
||||||
}
|
}
|
||||||
tile = TileAddByDiagDir(tile, target_dir);
|
tile = TileAddByDiagDir(tile, target_dir);
|
||||||
|
|
||||||
@@ -2001,7 +2004,7 @@ static bool GrowTown(Town *t)
|
|||||||
|
|
||||||
/* No road available, try to build a random road block by
|
/* No road available, try to build a random road block by
|
||||||
* clearing some land and then building a road there. */
|
* clearing some land and then building a road there. */
|
||||||
if (_settings_game.economy.allow_town_roads || _generating_world) {
|
if (t->GetAllowBuildRoads() || _generating_world) {
|
||||||
tile = t->xy;
|
tile = t->xy;
|
||||||
for (ptr = _town_coord_mod; ptr != endof(_town_coord_mod); ++ptr) {
|
for (ptr = _town_coord_mod; ptr != endof(_town_coord_mod); ++ptr) {
|
||||||
/* Only work with plain land that not already has a house */
|
/* Only work with plain land that not already has a house */
|
||||||
@@ -2789,7 +2792,7 @@ static inline CommandCost IsAnotherHouseTypeAllowedInTown(Town *t, HouseID house
|
|||||||
static inline bool TownLayoutAllowsHouseHere(Town *t, const TileArea &ta)
|
static inline bool TownLayoutAllowsHouseHere(Town *t, const TileArea &ta)
|
||||||
{
|
{
|
||||||
/* Allow towns everywhere when we don't build roads */
|
/* Allow towns everywhere when we don't build roads */
|
||||||
if (!_settings_game.economy.allow_town_roads && !_generating_world) return true;
|
if (!t->GetAllowBuildRoads() && !_generating_world) return true;
|
||||||
|
|
||||||
TileIndexDiffC grid_pos = TileIndexToTileIndexDiffC(t->xy, ta.tile);
|
TileIndexDiffC grid_pos = TileIndexToTileIndexDiffC(t->xy, ta.tile);
|
||||||
|
|
||||||
@@ -3792,6 +3795,67 @@ CommandCost CmdDoTownAction(TileIndex tile, DoCommandFlag flags, uint32 p1, uint
|
|||||||
return cost;
|
return cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override a town setting
|
||||||
|
* @param tile unused
|
||||||
|
* @param flags type of operation
|
||||||
|
* @param p1 town to do the action at
|
||||||
|
* @param p2 various bitstuffed elements
|
||||||
|
* - p2 = (bit 0 - 7) - what setting to change
|
||||||
|
* - p2 = (bit 8 - 15) - the data to modify
|
||||||
|
* - p2 = (bit 16) - whether to override the value, or use the default
|
||||||
|
* @param text unused
|
||||||
|
* @return the cost of this operation or an error
|
||||||
|
*/
|
||||||
|
CommandCost CmdOverrideTownSetting(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
|
||||||
|
{
|
||||||
|
if (_networking && !_settings_game.difficulty.override_town_settings_in_multiplayer) return CMD_ERROR;
|
||||||
|
|
||||||
|
Town *t = Town::GetIfValid(p1);
|
||||||
|
if (t == nullptr) return CMD_ERROR;
|
||||||
|
|
||||||
|
const uint8 setting = GB(p2, 0, 8);
|
||||||
|
const bool is_override = HasBit(p2, 16);
|
||||||
|
const uint8 value = GB(p2, 8, 8);
|
||||||
|
switch (setting) {
|
||||||
|
case TSOF_OVERRIDE_BUILD_ROADS:
|
||||||
|
case TSOF_OVERRIDE_BUILD_LEVEL_CROSSINGS:
|
||||||
|
if (is_override && value != 0 && value != 1) return CMD_ERROR;
|
||||||
|
break;
|
||||||
|
case TSOF_OVERRIDE_BUILD_TUNNELS:
|
||||||
|
if (is_override && value >= TTM_END) return CMD_ERROR;
|
||||||
|
break;
|
||||||
|
case TSOF_OVERRIDE_BUILD_INCLINED_ROADS:
|
||||||
|
if (is_override && value > 8) return CMD_ERROR;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return CMD_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & DC_EXEC) {
|
||||||
|
SB(t->override_flags, setting, 1, is_override ? 1 : 0);
|
||||||
|
if (is_override) {
|
||||||
|
switch (setting) {
|
||||||
|
case TSOF_OVERRIDE_BUILD_ROADS:
|
||||||
|
case TSOF_OVERRIDE_BUILD_LEVEL_CROSSINGS:
|
||||||
|
SB(t->override_values, setting, 1, value & 1);
|
||||||
|
break;
|
||||||
|
case TSOF_OVERRIDE_BUILD_TUNNELS:
|
||||||
|
t->build_tunnels = (TownTunnelMode)value;
|
||||||
|
break;
|
||||||
|
case TSOF_OVERRIDE_BUILD_INCLINED_ROADS:
|
||||||
|
t->max_road_slope = value;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
NOT_REACHED();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SetWindowDirty(WC_TOWN_AUTHORITY, p1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CommandCost();
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Func>
|
template <typename Func>
|
||||||
static void ForAllStationsNearTown(Town *t, Func func)
|
static void ForAllStationsNearTown(Town *t, Func func)
|
||||||
{
|
{
|
||||||
|
189
src/town_gui.cpp
189
src/town_gui.cpp
@@ -68,7 +68,10 @@ static const NWidgetPart _nested_town_authority_widgets[] = {
|
|||||||
EndContainer(),
|
EndContainer(),
|
||||||
NWidget(WWT_PANEL, COLOUR_BROWN, WID_TA_ACTION_INFO), SetMinimalSize(317, 52), SetResize(1, 0), EndContainer(),
|
NWidget(WWT_PANEL, COLOUR_BROWN, WID_TA_ACTION_INFO), SetMinimalSize(317, 52), SetResize(1, 0), EndContainer(),
|
||||||
NWidget(NWID_HORIZONTAL),
|
NWidget(NWID_HORIZONTAL),
|
||||||
NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_TA_EXECUTE), SetMinimalSize(317, 12), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_LOCAL_AUTHORITY_DO_IT_BUTTON, STR_LOCAL_AUTHORITY_DO_IT_TOOLTIP),
|
NWidget(NWID_SELECTION, INVALID_COLOUR, WID_TA_BTN_SEL),
|
||||||
|
NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_TA_EXECUTE), SetMinimalSize(317, 12), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_LOCAL_AUTHORITY_DO_IT_BUTTON, STR_LOCAL_AUTHORITY_DO_IT_TOOLTIP),
|
||||||
|
NWidget(WWT_DROPDOWN, COLOUR_BROWN, WID_TA_SETTING), SetMinimalSize(317, 12), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_BLACK_STRING1, STR_LOCAL_AUTHORITY_SETTING_OVERRIDE_TOOLTIP),
|
||||||
|
EndContainer(),
|
||||||
NWidget(WWT_RESIZEBOX, COLOUR_BROWN),
|
NWidget(WWT_RESIZEBOX, COLOUR_BROWN),
|
||||||
EndContainer()
|
EndContainer()
|
||||||
};
|
};
|
||||||
@@ -101,6 +104,14 @@ private:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool ChangeSettingsDisabled()
|
||||||
|
{
|
||||||
|
return _networking && !(_network_server || _network_settings_access) &&
|
||||||
|
!(_local_company != COMPANY_SPECTATOR && _settings_game.difficulty.override_town_settings_in_multiplayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const uint SETTING_OVERRIDE_COUNT = 4;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TownAuthorityWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc), sel_index(-1), displayed_actions_on_previous_painting(0)
|
TownAuthorityWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc), sel_index(-1), displayed_actions_on_previous_painting(0)
|
||||||
{
|
{
|
||||||
@@ -114,17 +125,20 @@ public:
|
|||||||
{
|
{
|
||||||
int numact;
|
int numact;
|
||||||
uint buttons = GetMaskOfTownActions(&numact, _local_company, this->town);
|
uint buttons = GetMaskOfTownActions(&numact, _local_company, this->town);
|
||||||
|
numact += SETTING_OVERRIDE_COUNT;
|
||||||
if (buttons != displayed_actions_on_previous_painting) this->SetDirty();
|
if (buttons != displayed_actions_on_previous_painting) this->SetDirty();
|
||||||
displayed_actions_on_previous_painting = buttons;
|
displayed_actions_on_previous_painting = buttons;
|
||||||
|
|
||||||
this->vscroll->SetCount(numact + 1);
|
this->vscroll->SetCount(numact + 1);
|
||||||
|
|
||||||
if (this->sel_index != -1 && !HasBit(buttons, this->sel_index)) {
|
if (this->sel_index != -1 && this->sel_index < 0x100 && !HasBit(buttons, this->sel_index)) {
|
||||||
this->sel_index = -1;
|
this->sel_index = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->SetWidgetLoweredState(WID_TA_ZONE_BUTTON, this->town->show_zone);
|
this->SetWidgetLoweredState(WID_TA_ZONE_BUTTON, this->town->show_zone);
|
||||||
this->SetWidgetDisabledState(WID_TA_EXECUTE, this->sel_index == -1);
|
this->SetWidgetDisabledState(WID_TA_EXECUTE, this->sel_index == -1 || this->sel_index >= 0x100);
|
||||||
|
this->SetWidgetDisabledState(WID_TA_SETTING, ChangeSettingsDisabled());
|
||||||
|
this->GetWidget<NWidgetStacked>(WID_TA_BTN_SEL)->SetDisplayedPlane(this->sel_index >= 0x100 ? 1 : 0);
|
||||||
|
|
||||||
this->DrawWidgets();
|
this->DrawWidgets();
|
||||||
if (!this->IsShaded()) this->DrawRatings();
|
if (!this->IsShaded()) this->DrawRatings();
|
||||||
@@ -193,7 +207,31 @@ public:
|
|||||||
|
|
||||||
void SetStringParameters(int widget) const override
|
void SetStringParameters(int widget) const override
|
||||||
{
|
{
|
||||||
if (widget == WID_TA_CAPTION) SetDParam(0, this->window_number);
|
if (widget == WID_TA_CAPTION) {
|
||||||
|
SetDParam(0, this->window_number);
|
||||||
|
} else if (widget == WID_TA_SETTING) {
|
||||||
|
SetDParam(0, STR_EMPTY);
|
||||||
|
if (this->sel_index >= 0x100 && this->sel_index < (int)(0x100 + SETTING_OVERRIDE_COUNT)) {
|
||||||
|
if (!HasBit(this->town->override_flags, this->sel_index - 0x100)) {
|
||||||
|
SetDParam(0, STR_COLOUR_DEFAULT);
|
||||||
|
} else {
|
||||||
|
int idx = this->sel_index - 0x100;
|
||||||
|
switch (idx) {
|
||||||
|
case TSOF_OVERRIDE_BUILD_ROADS:
|
||||||
|
case TSOF_OVERRIDE_BUILD_LEVEL_CROSSINGS:
|
||||||
|
SetDParam(0, HasBit(this->town->override_values, idx) ? STR_CONFIG_SETTING_ON : STR_CONFIG_SETTING_OFF);
|
||||||
|
break;
|
||||||
|
case TSOF_OVERRIDE_BUILD_TUNNELS:
|
||||||
|
SetDParam(0, STR_CONFIG_SETTING_TOWN_TUNNELS_FORBIDDEN + this->town->build_tunnels);
|
||||||
|
break;
|
||||||
|
case TSOF_OVERRIDE_BUILD_INCLINED_ROADS:
|
||||||
|
SetDParam(0, STR_CONFIG_SETTING_TOWN_MAX_ROAD_SLOPE_VALUE + ((this->town->max_road_slope == 0) ? 1 : 0));
|
||||||
|
SetDParam(1, this->town->max_road_slope);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawWidget(const Rect &r, int widget) const override
|
void DrawWidget(const Rect &r, int widget) const override
|
||||||
@@ -201,14 +239,36 @@ public:
|
|||||||
switch (widget) {
|
switch (widget) {
|
||||||
case WID_TA_ACTION_INFO:
|
case WID_TA_ACTION_INFO:
|
||||||
if (this->sel_index != -1) {
|
if (this->sel_index != -1) {
|
||||||
SetDParam(0, _price[PR_TOWN_ACTION] * _town_action_costs[this->sel_index] >> 8);
|
StringID text = STR_NULL;
|
||||||
DrawStringMultiLine(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, r.bottom - WD_FRAMERECT_BOTTOM,
|
if (this->sel_index >= 0x100) {
|
||||||
STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_SMALL_ADVERTISING + this->sel_index);
|
SetDParam(1, STR_EMPTY);
|
||||||
|
switch (this->sel_index - 0x100) {
|
||||||
|
case TSOF_OVERRIDE_BUILD_ROADS:
|
||||||
|
SetDParam(1, STR_CONFIG_SETTING_ALLOW_TOWN_ROADS_HELPTEXT);
|
||||||
|
break;
|
||||||
|
case TSOF_OVERRIDE_BUILD_LEVEL_CROSSINGS:
|
||||||
|
SetDParam(1, STR_CONFIG_SETTING_ALLOW_TOWN_LEVEL_CROSSINGS_HELPTEXT);
|
||||||
|
break;
|
||||||
|
case TSOF_OVERRIDE_BUILD_TUNNELS:
|
||||||
|
SetDParam(1, STR_CONFIG_SETTING_TOWN_TUNNELS_HELPTEXT);
|
||||||
|
break;
|
||||||
|
case TSOF_OVERRIDE_BUILD_INCLINED_ROADS:
|
||||||
|
SetDParam(1, STR_CONFIG_SETTING_TOWN_MAX_ROAD_SLOPE_HELPTEXT);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
text = STR_LOCAL_AUTHORITY_SETTING_OVERRIDE_TEXT;
|
||||||
|
SetDParam(0, STR_LOCAL_AUTHORITY_SETTING_OVERRIDE_ALLOW_ROADS + this->sel_index - 0x100);
|
||||||
|
} else {
|
||||||
|
text = STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_SMALL_ADVERTISING + this->sel_index;
|
||||||
|
SetDParam(0, _price[PR_TOWN_ACTION] * _town_action_costs[this->sel_index] >> 8);
|
||||||
|
}
|
||||||
|
DrawStringMultiLine(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, r.bottom - WD_FRAMERECT_BOTTOM, text);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case WID_TA_COMMAND_LIST: {
|
case WID_TA_COMMAND_LIST: {
|
||||||
int numact;
|
int numact;
|
||||||
uint buttons = GetMaskOfTownActions(&numact, _local_company, this->town);
|
uint buttons = GetMaskOfTownActions(&numact, _local_company, this->town);
|
||||||
|
numact += SETTING_OVERRIDE_COUNT;
|
||||||
int y = r.top + WD_FRAMERECT_TOP;
|
int y = r.top + WD_FRAMERECT_TOP;
|
||||||
int pos = this->vscroll->GetPosition();
|
int pos = this->vscroll->GetPosition();
|
||||||
|
|
||||||
@@ -218,14 +278,47 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; buttons; i++, buttons >>= 1) {
|
for (int i = 0; buttons; i++, buttons >>= 1) {
|
||||||
if (pos <= -5) break; ///< Draw only the 5 fitting lines
|
|
||||||
|
|
||||||
if ((buttons & 1) && --pos < 0) {
|
if ((buttons & 1) && --pos < 0) {
|
||||||
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y,
|
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y,
|
||||||
STR_LOCAL_AUTHORITY_ACTION_SMALL_ADVERTISING_CAMPAIGN + i, this->sel_index == i ? TC_WHITE : TC_ORANGE);
|
STR_LOCAL_AUTHORITY_ACTION_SMALL_ADVERTISING_CAMPAIGN + i, this->sel_index == i ? TC_WHITE : TC_ORANGE);
|
||||||
y += FONT_HEIGHT_NORMAL;
|
y += FONT_HEIGHT_NORMAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (int i = 0; i < (int)SETTING_OVERRIDE_COUNT; i++) {
|
||||||
|
if (--pos < 0) {
|
||||||
|
const bool disabled = ChangeSettingsDisabled();
|
||||||
|
const bool selected = (this->sel_index == (0x100 + i));
|
||||||
|
const TextColour tc = disabled ? (TC_NO_SHADE | (selected ? TC_SILVER : TC_GREY)) : (selected ? TC_WHITE : TC_ORANGE);
|
||||||
|
const bool overriden = HasBit(this->town->override_flags, i);
|
||||||
|
SetDParam(0, STR_LOCAL_AUTHORITY_SETTING_OVERRIDE_ALLOW_ROADS + i);
|
||||||
|
SetDParam(1, overriden ? STR_JUST_STRING1 : STR_LOCAL_AUTHORITY_SETTING_OVERRIDE_DEFAULT);
|
||||||
|
switch (i) {
|
||||||
|
case TSOF_OVERRIDE_BUILD_ROADS:
|
||||||
|
SetDParam(2, this->town->GetAllowBuildRoads() ? STR_CONFIG_SETTING_ON : STR_CONFIG_SETTING_OFF);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TSOF_OVERRIDE_BUILD_LEVEL_CROSSINGS:
|
||||||
|
SetDParam(2, this->town->GetAllowBuildLevelCrossings() ? STR_CONFIG_SETTING_ON : STR_CONFIG_SETTING_OFF);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TSOF_OVERRIDE_BUILD_TUNNELS: {
|
||||||
|
TownTunnelMode tunnel_mode = this->town->GetBuildTunnelMode();
|
||||||
|
SetDParam(2, STR_CONFIG_SETTING_TOWN_TUNNELS_FORBIDDEN + tunnel_mode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TSOF_OVERRIDE_BUILD_INCLINED_ROADS: {
|
||||||
|
uint8 max_slope = this->town->GetBuildMaxRoadSlope();
|
||||||
|
SetDParam(2, STR_CONFIG_SETTING_TOWN_MAX_ROAD_SLOPE_VALUE + ((max_slope == 0) ? 1 : 0));
|
||||||
|
SetDParam(3, max_slope);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y,
|
||||||
|
STR_LOCAL_AUTHORITY_SETTING_OVERRIDE_STR, tc);
|
||||||
|
y += FONT_HEIGHT_NORMAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -250,7 +343,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
case WID_TA_COMMAND_LIST:
|
case WID_TA_COMMAND_LIST:
|
||||||
size->height = WD_FRAMERECT_TOP + 5 * FONT_HEIGHT_NORMAL + WD_FRAMERECT_BOTTOM;
|
size->height = WD_FRAMERECT_TOP + (5 + SETTING_OVERRIDE_COUNT) * FONT_HEIGHT_NORMAL + WD_FRAMERECT_BOTTOM;
|
||||||
size->width = GetStringBoundingBox(STR_LOCAL_AUTHORITY_ACTIONS_TITLE).width;
|
size->width = GetStringBoundingBox(STR_LOCAL_AUTHORITY_ACTIONS_TITLE).width;
|
||||||
for (uint i = 0; i < TACT_COUNT; i++ ) {
|
for (uint i = 0; i < TACT_COUNT; i++ ) {
|
||||||
size->width = std::max(size->width, GetStringBoundingBox(STR_LOCAL_AUTHORITY_ACTION_SMALL_ADVERTISING_CAMPAIGN + i).width);
|
size->width = std::max(size->width, GetStringBoundingBox(STR_LOCAL_AUTHORITY_ACTION_SMALL_ADVERTISING_CAMPAIGN + i).width);
|
||||||
@@ -283,10 +376,16 @@ public:
|
|||||||
|
|
||||||
case WID_TA_COMMAND_LIST: {
|
case WID_TA_COMMAND_LIST: {
|
||||||
int y = this->GetRowFromWidget(pt.y, WID_TA_COMMAND_LIST, 1, FONT_HEIGHT_NORMAL);
|
int y = this->GetRowFromWidget(pt.y, WID_TA_COMMAND_LIST, 1, FONT_HEIGHT_NORMAL);
|
||||||
if (!IsInsideMM(y, 0, 5)) return;
|
if (!IsInsideMM(y, 0, 5 + SETTING_OVERRIDE_COUNT)) return;
|
||||||
|
|
||||||
y = GetNthSetBit(GetMaskOfTownActions(nullptr, _local_company, this->town), y + this->vscroll->GetPosition() - 1);
|
const uint setting_override_offset = 32 - SETTING_OVERRIDE_COUNT;
|
||||||
if (y >= 0) {
|
|
||||||
|
y = GetNthSetBit(GetMaskOfTownActions(nullptr, _local_company, this->town) | (UINT32_MAX << setting_override_offset), y + this->vscroll->GetPosition() - 1);
|
||||||
|
if (y >= (int)setting_override_offset) {
|
||||||
|
this->sel_index = y + 0x100 - setting_override_offset;
|
||||||
|
this->SetDirty();
|
||||||
|
break;
|
||||||
|
} else if (y >= 0) {
|
||||||
this->sel_index = y;
|
this->sel_index = y;
|
||||||
this->SetDirty();
|
this->SetDirty();
|
||||||
}
|
}
|
||||||
@@ -298,9 +397,71 @@ public:
|
|||||||
case WID_TA_EXECUTE:
|
case WID_TA_EXECUTE:
|
||||||
DoCommandP(this->town->xy, this->window_number, this->sel_index, CMD_DO_TOWN_ACTION | CMD_MSG(STR_ERROR_CAN_T_DO_THIS));
|
DoCommandP(this->town->xy, this->window_number, this->sel_index, CMD_DO_TOWN_ACTION | CMD_MSG(STR_ERROR_CAN_T_DO_THIS));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case WID_TA_SETTING: {
|
||||||
|
uint8 idx = this->sel_index - 0x100;
|
||||||
|
switch (idx) {
|
||||||
|
case TSOF_OVERRIDE_BUILD_ROADS:
|
||||||
|
case TSOF_OVERRIDE_BUILD_LEVEL_CROSSINGS: {
|
||||||
|
int value = HasBit(this->town->override_flags, idx) ? (HasBit(this->town->override_values, idx) ? 2 : 1) : 0;
|
||||||
|
const StringID names[] = {
|
||||||
|
STR_COLOUR_DEFAULT,
|
||||||
|
STR_CONFIG_SETTING_OFF,
|
||||||
|
STR_CONFIG_SETTING_ON,
|
||||||
|
INVALID_STRING_ID
|
||||||
|
};
|
||||||
|
ShowDropDownMenu(this, names, value, WID_TA_SETTING, 0, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TSOF_OVERRIDE_BUILD_TUNNELS: {
|
||||||
|
const StringID names[] = {
|
||||||
|
STR_COLOUR_DEFAULT,
|
||||||
|
STR_CONFIG_SETTING_TOWN_TUNNELS_FORBIDDEN,
|
||||||
|
STR_CONFIG_SETTING_TOWN_TUNNELS_ALLOWED_OBSTRUCTION,
|
||||||
|
STR_CONFIG_SETTING_TOWN_TUNNELS_ALLOWED,
|
||||||
|
INVALID_STRING_ID
|
||||||
|
};
|
||||||
|
ShowDropDownMenu(this, names, HasBit(this->town->override_flags, idx) ? this->town->build_tunnels + 1 : 0, WID_TA_SETTING, 0, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TSOF_OVERRIDE_BUILD_INCLINED_ROADS:
|
||||||
|
DropDownList dlist;
|
||||||
|
dlist.emplace_back(new DropDownListStringItem(STR_COLOUR_DEFAULT, 0, false));
|
||||||
|
dlist.emplace_back(new DropDownListStringItem(STR_CONFIG_SETTING_TOWN_MAX_ROAD_SLOPE_ZERO, 1, false));
|
||||||
|
for (int i = 1; i <= 8; i++) {
|
||||||
|
DropDownListParamStringItem *item = new DropDownListParamStringItem(STR_CONFIG_SETTING_TOWN_MAX_ROAD_SLOPE_VALUE, i + 1, false);
|
||||||
|
item->SetParam(0, i);
|
||||||
|
dlist.emplace_back(item);
|
||||||
|
}
|
||||||
|
ShowDropDownList(this, std::move(dlist), HasBit(this->town->override_flags, idx) ? this->town->max_road_slope + 1 : 0, WID_TA_SETTING);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void OnDropdownSelect(int widget, int index) override
|
||||||
|
{
|
||||||
|
switch (widget) {
|
||||||
|
case WID_TA_SETTING: {
|
||||||
|
if (index < 0) break;
|
||||||
|
uint32 p2 = this->sel_index - 0x100;
|
||||||
|
if (index > 0) {
|
||||||
|
SetBit(p2, 16);
|
||||||
|
p2 |= (index - 1) << 8;
|
||||||
|
}
|
||||||
|
DoCommandP(this->town->xy, this->window_number, p2, CMD_TOWN_SETTING_OVERRIDE | CMD_MSG(STR_ERROR_CAN_T_DO_THIS));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
this->SetDirty();
|
||||||
|
}
|
||||||
|
|
||||||
void OnHundredthTick() override
|
void OnHundredthTick() override
|
||||||
{
|
{
|
||||||
this->SetDirty();
|
this->SetDirty();
|
||||||
@@ -477,7 +638,7 @@ public:
|
|||||||
/* Warn the user if towns are not allowed to build roads, but do this only once per OpenTTD run. */
|
/* Warn the user if towns are not allowed to build roads, but do this only once per OpenTTD run. */
|
||||||
static bool _warn_town_no_roads = false;
|
static bool _warn_town_no_roads = false;
|
||||||
|
|
||||||
if (!_settings_game.economy.allow_town_roads && !_warn_town_no_roads) {
|
if (!Town::Get(this->window_number)->GetAllowBuildRoads() && !_warn_town_no_roads) {
|
||||||
ShowErrorMessage(STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS, INVALID_STRING_ID, WL_WARNING);
|
ShowErrorMessage(STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS, INVALID_STRING_ID, WL_WARNING);
|
||||||
_warn_town_no_roads = true;
|
_warn_town_no_roads = true;
|
||||||
}
|
}
|
||||||
|
@@ -29,6 +29,8 @@ enum TownAuthorityWidgets {
|
|||||||
WID_TA_SCROLLBAR, ///< Scrollbar of the list of commands.
|
WID_TA_SCROLLBAR, ///< Scrollbar of the list of commands.
|
||||||
WID_TA_ACTION_INFO, ///< Additional information about the action.
|
WID_TA_ACTION_INFO, ///< Additional information about the action.
|
||||||
WID_TA_EXECUTE, ///< Do-it button.
|
WID_TA_EXECUTE, ///< Do-it button.
|
||||||
|
WID_TA_SETTING, ///< Setting drop-down.
|
||||||
|
WID_TA_BTN_SEL, ///< Button selector.
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Widgets of the #TownViewWindow class. */
|
/** Widgets of the #TownViewWindow class. */
|
||||||
|
Reference in New Issue
Block a user