1
0
mirror of https://github.com/OpenTTD/OpenTTD.git synced 2025-08-21 13:39:09 +00:00

Compare commits

..

7 Commits

10 changed files with 64 additions and 25 deletions

View File

@@ -700,7 +700,10 @@ bool ExtractTar(const std::string &tar_filename, Subdirectory subdir)
for (auto &it2 : _tar_filelist[subdir]) { for (auto &it2 : _tar_filelist[subdir]) {
if (tar_filename != it2.second.tar_filename) continue; if (tar_filename != it2.second.tar_filename) continue;
filename.replace(p + 1, std::string::npos, it2.first); /* it2.first is tarball + PATHSEPCHAR + name. */
std::string_view name = it2.first;
name.remove_prefix(name.find_first_of(PATHSEPCHAR) + 1);
filename.replace(p + 1, std::string::npos, name);
Debug(misc, 9, " extracting {}", filename); Debug(misc, 9, " extracting {}", filename);

View File

@@ -712,6 +712,8 @@ std::tuple<CommandCost, Money> CmdClearArea(DoCommandFlag flags, TileIndex tile,
const Company *c = (flags & (DC_AUTO | DC_BANKRUPT)) ? nullptr : Company::GetIfValid(_current_company); const Company *c = (flags & (DC_AUTO | DC_BANKRUPT)) ? nullptr : Company::GetIfValid(_current_company);
int limit = (c == nullptr ? INT32_MAX : GB(c->clear_limit, 16, 16)); int limit = (c == nullptr ? INT32_MAX : GB(c->clear_limit, 16, 16));
if (tile != start_tile) flags |= DC_FORCE_CLEAR_TILE;
std::unique_ptr<TileIterator> iter = TileIterator::Create(tile, start_tile, diagonal); std::unique_ptr<TileIterator> iter = TileIterator::Create(tile, start_tile, diagonal);
for (; *iter != INVALID_TILE; ++(*iter)) { for (; *iter != INVALID_TILE; ++(*iter)) {
TileIndex t = *iter; TileIndex t = *iter;

View File

@@ -1923,7 +1923,7 @@ STR_CONFIG_SETTING_DRAG_SIGNALS_DENSITY :When dragging,
STR_CONFIG_SETTING_DRAG_SIGNALS_DENSITY_HELPTEXT :Set the distance at which signals will be built on a track up to the next obstacle (signal, junction), if signals are dragged STR_CONFIG_SETTING_DRAG_SIGNALS_DENSITY_HELPTEXT :Set the distance at which signals will be built on a track up to the next obstacle (signal, junction), if signals are dragged
STR_CONFIG_SETTING_DRAG_SIGNALS_DENSITY_VALUE :{COMMA} tile{P 0 "" s} STR_CONFIG_SETTING_DRAG_SIGNALS_DENSITY_VALUE :{COMMA} tile{P 0 "" s}
STR_CONFIG_SETTING_DRAG_SIGNALS_FIXED_DISTANCE :When dragging, keep fixed distance between signals: {STRING2} STR_CONFIG_SETTING_DRAG_SIGNALS_FIXED_DISTANCE :When dragging, keep fixed distance between signals: {STRING2}
STR_CONFIG_SETTING_DRAG_SIGNALS_FIXED_DISTANCE_HELPTEXT :Select the behaviour of signal placement when dragging signals. If disabled, signals are placed around tunnels or bridges to avoid long stretches without signals. If enabled, signals are placed every n tiles, making alignment of signals at parallel tracks easier STR_CONFIG_SETTING_DRAG_SIGNALS_FIXED_DISTANCE_HELPTEXT :Select the behaviour of signal placement when Ctrl+dragging signals. If disabled, signals are placed around tunnels or bridges to avoid long stretches without signals. If enabled, signals are placed every n tiles, making alignment of signals at parallel tracks easier
STR_CONFIG_SETTING_SEMAPHORE_BUILD_BEFORE_DATE :Automatically build semaphores before: {STRING2} STR_CONFIG_SETTING_SEMAPHORE_BUILD_BEFORE_DATE :Automatically build semaphores before: {STRING2}
STR_CONFIG_SETTING_SEMAPHORE_BUILD_BEFORE_DATE_HELPTEXT :Set the year when electric signals will be used for tracks. Before this year, non-electric signals will be used (which have the exact same function, but different looks) STR_CONFIG_SETTING_SEMAPHORE_BUILD_BEFORE_DATE_HELPTEXT :Set the year when electric signals will be used for tracks. Before this year, non-electric signals will be used (which have the exact same function, but different looks)
@@ -2788,7 +2788,7 @@ STR_RAIL_TOOLBAR_TOOLTIP_BUILD_AUTORAIL :{BLACK}Build ra
STR_RAIL_TOOLBAR_TOOLTIP_BUILD_TRAIN_DEPOT_FOR_BUILDING :{BLACK}Build train depot (for buying and servicing trains). Also press Shift to show cost estimate only STR_RAIL_TOOLBAR_TOOLTIP_BUILD_TRAIN_DEPOT_FOR_BUILDING :{BLACK}Build train depot (for buying and servicing trains). Also press Shift to show cost estimate only
STR_RAIL_TOOLBAR_TOOLTIP_CONVERT_RAIL_TO_WAYPOINT :{BLACK}Build waypoint on railway. Ctrl+Click to select another waypoint to join. Also press Shift to show cost estimate only STR_RAIL_TOOLBAR_TOOLTIP_CONVERT_RAIL_TO_WAYPOINT :{BLACK}Build waypoint on railway. Ctrl+Click to select another waypoint to join. Also press Shift to show cost estimate only
STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_STATION :{BLACK}Build railway station. Ctrl+Click to select another station to join. Also press Shift to show cost estimate only STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_STATION :{BLACK}Build railway station. Ctrl+Click to select another station to join. Also press Shift to show cost estimate only
STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_SIGNALS :{BLACK}Build signal on railway. Ctrl+Click to build the alternate signal style{}Click+Drag to fill signals up to the next junction, station, or signal. Also press Shift to show cost estimate only STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_SIGNALS :{BLACK}Build signal on railway. Ctrl+Click to build the alternate signal style{}Click+Drag to fill the selected section of rail with signals at the chosen spacing. Ctrl+Click+Drag to fill signals up to the next junction, station, or signal. Also press Shift to show cost estimate only
STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_BRIDGE :{BLACK}Build railway bridge. Also press Shift to show cost estimate only STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_BRIDGE :{BLACK}Build railway bridge. Also press Shift to show cost estimate only
STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_TUNNEL :{BLACK}Build railway tunnel. Also press Shift to show cost estimate only STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_TUNNEL :{BLACK}Build railway tunnel. Also press Shift to show cost estimate only
STR_RAIL_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR :{BLACK}Toggle build/remove for railway track, signals, waypoints and stations. Ctrl+Click to also remove the rail of waypoints and stations STR_RAIL_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR :{BLACK}Toggle build/remove for railway track, signals, waypoints and stations. Ctrl+Click to also remove the rail of waypoints and stations

View File

@@ -263,8 +263,7 @@ const Sprite *CoreTextFontCache::InternalGetGlyph(GlyphID key, bool use_aa)
CGContextSetAllowsFontSubpixelQuantization(context.get(), !use_aa); CGContextSetAllowsFontSubpixelQuantization(context.get(), !use_aa);
CGContextSetShouldSmoothFonts(context.get(), false); CGContextSetShouldSmoothFonts(context.get(), false);
float offset = 0.5f; // CoreText uses 0.5 as pixel centers. We want pixel alignment. CGPoint pos{-bounds.origin.x, -bounds.origin.y};
CGPoint pos{offset - bounds.origin.x, offset - bounds.origin.y};
CTFontDrawGlyphs(this->font.get(), &glyph, &pos, 1, context.get()); CTFontDrawGlyphs(this->font.get(), &glyph, &pos, 1, context.get());
/* Draw shadow for medium size. */ /* Draw shadow for medium size. */

View File

@@ -172,20 +172,28 @@ public:
return 'w'; return 'w';
} }
/** Returns a random trackdir that can be reached from the current tile/trackdir, or INVALID_TRACK if none is available. */
static Trackdir GetRandomFollowUpTrackdir(const Ship *v, TileIndex tile, Trackdir dir, bool include_90_degree_turns)
{
TrackFollower follower(v);
if (follower.Follow(tile, dir)) {
tile = follower.m_new_tile;
TrackdirBits dirs = follower.m_new_td_bits;
if (!include_90_degree_turns) dirs &= ~TrackdirCrossesTrackdirs(dir);
const int strip_amount = _random.Next(CountBits(dirs));
for (int s = 0; s < strip_amount; ++s) RemoveFirstTrackdir(&dirs);
return FindFirstTrackdir(dirs);
}
return INVALID_TRACKDIR;
}
/** Creates a random path, avoids 90 degree turns. */ /** Creates a random path, avoids 90 degree turns. */
static Trackdir CreateRandomPath(const Ship *v, TileIndex tile, Trackdir dir, ShipPathCache &path_cache, int path_length) static Trackdir CreateRandomPath(const Ship *v, TileIndex tile, Trackdir dir, ShipPathCache &path_cache, int path_length)
{ {
for (int i = 0; i < path_length; ++i) { for (int i = 0; i < path_length; ++i) {
TrackFollower F(v); const Trackdir random_dir = GetRandomFollowUpTrackdir(v, tile, dir, false);
if (F.Follow(tile, dir)) { if (random_dir == INVALID_TRACKDIR) break;
tile = F.m_new_tile; path_cache.push_back(random_dir);
TrackdirBits dirs = F.m_new_td_bits & ~TrackdirCrossesTrackdirs(dir);
const int strip_amount = _random.Next(CountBits(dirs));
for (int s = 0; s < strip_amount; ++s) RemoveFirstTrackdir(&dirs);
dir = FindFirstTrackdir(dirs);
if (dir == INVALID_TRACKDIR) break;
path_cache.push_back(dir);
}
} }
if (path_cache.empty()) return INVALID_TRACKDIR; if (path_cache.empty()) return INVALID_TRACKDIR;
@@ -210,12 +218,12 @@ public:
} }
/* Move back to the old tile/trackdir (where ship is coming from). */ /* Move back to the old tile/trackdir (where ship is coming from). */
TileIndex src_tile = TileAddByDiagDir(tile, ReverseDiagDir(enterdir)); const TileIndex src_tile = TileAddByDiagDir(tile, ReverseDiagDir(enterdir));
Trackdir trackdir = v->GetVehicleTrackdir(); const Trackdir trackdir = v->GetVehicleTrackdir();
assert(IsValidTrackdir(trackdir)); assert(IsValidTrackdir(trackdir));
/* Convert origin trackdir to TrackdirBits. */ /* Convert origin trackdir to TrackdirBits. */
TrackdirBits trackdirs = TrackdirToTrackdirBits(trackdir); const TrackdirBits trackdirs = TrackdirToTrackdirBits(trackdir);
const std::vector<WaterRegionPatchDesc> high_level_path = YapfShipFindWaterRegionPath(v, tile, NUMBER_OR_WATER_REGIONS_LOOKAHEAD + 1); const std::vector<WaterRegionPatchDesc> high_level_path = YapfShipFindWaterRegionPath(v, tile, NUMBER_OR_WATER_REGIONS_LOOKAHEAD + 1);
if (high_level_path.empty()) { if (high_level_path.empty()) {
@@ -244,7 +252,7 @@ public:
path_found = pf.FindPath(v); path_found = pf.FindPath(v);
Node *node = pf.GetBestNode(); Node *node = pf.GetBestNode();
if (attempt == 0 && !path_found) continue; // Try again with restricted search area. if (attempt == 0 && !path_found) continue; // Try again with restricted search area.
if (!path_found || !node) return INVALID_TRACKDIR; if (!path_found || node == nullptr) GetRandomFollowUpTrackdir(v, src_tile, trackdir, true);
/* Return only the path within the current water region if an intermediate destination was returned. If not, cache the entire path /* Return only the path within the current water region if an intermediate destination was returned. If not, cache the entire path
* to the final destination tile. The low-level pathfinder might actually prefer a different docking tile in a nearby region. Without * to the final destination tile. The low-level pathfinder might actually prefer a different docking tile in a nearby region. Without

View File

@@ -1450,7 +1450,7 @@ static CommandCost CmdSignalTrackHelper(DoCommandFlag flags, TileIndex tile, Til
* @param sigtype default signal type * @param sigtype default signal type
* @param sigvar signal variant to build * @param sigvar signal variant to build
* @param mode true = override signal/semaphore, or pre/exit/combo signal (CTRL-toggle) * @param mode true = override signal/semaphore, or pre/exit/combo signal (CTRL-toggle)
* @param autofill fill beyond selected stretch? (currently always true but keep the command parameter so network-compatible patch packs can restore this functionality). * @param autofill fill beyond selected stretch?
* @param minimise_gaps false = keep fixed distance, true = minimise gaps between signals * @param minimise_gaps false = keep fixed distance, true = minimise gaps between signals
* @param signal_density user defined signals_density * @param signal_density user defined signals_density
* @return the cost of this operation or an error * @return the cost of this operation or an error
@@ -1530,7 +1530,7 @@ CommandCost CmdRemoveSingleSignal(DoCommandFlag flags, TileIndex tile, Track tra
* @param tile start tile of drag * @param tile start tile of drag
* @param end_tile end tile of drag * @param end_tile end tile of drag
* @param track track-orientation * @param track track-orientation
* @param autofill fill beyond selected stretch? (currently always true but keep the command parameter so network-compatible patch packs can restore this functionality). * @param autofill fill beyond selected stretch?
* @return the cost of this operation or an error * @return the cost of this operation or an error
* @see CmdSignalTrackHelper * @see CmdSignalTrackHelper
*/ */

View File

@@ -413,13 +413,13 @@ static void HandleAutoSignalPlacement()
* in a network game can specify their own signal density */ * in a network game can specify their own signal density */
if (_remove_button_clicked) { if (_remove_button_clicked) {
Command<CMD_REMOVE_SIGNAL_TRACK>::Post(STR_ERROR_CAN_T_REMOVE_SIGNALS_FROM, CcPlaySound_CONSTRUCTION_RAIL, Command<CMD_REMOVE_SIGNAL_TRACK>::Post(STR_ERROR_CAN_T_REMOVE_SIGNALS_FROM, CcPlaySound_CONSTRUCTION_RAIL,
TileVirtXY(_thd.selstart.x, _thd.selstart.y), TileVirtXY(_thd.selend.x, _thd.selend.y), track, true); TileVirtXY(_thd.selstart.x, _thd.selstart.y), TileVirtXY(_thd.selend.x, _thd.selend.y), track, _ctrl_pressed);
} else { } else {
bool sig_gui = FindWindowById(WC_BUILD_SIGNAL, 0) != nullptr; bool sig_gui = FindWindowById(WC_BUILD_SIGNAL, 0) != nullptr;
SignalType sigtype = sig_gui ? _cur_signal_type : _settings_client.gui.default_signal_type; SignalType sigtype = sig_gui ? _cur_signal_type : _settings_client.gui.default_signal_type;
SignalVariant sigvar = sig_gui ? _cur_signal_variant : (TimerGameCalendar::year < _settings_client.gui.semaphore_build_before ? SIG_SEMAPHORE : SIG_ELECTRIC); SignalVariant sigvar = sig_gui ? _cur_signal_variant : (TimerGameCalendar::year < _settings_client.gui.semaphore_build_before ? SIG_SEMAPHORE : SIG_ELECTRIC);
Command<CMD_BUILD_SIGNAL_TRACK>::Post(STR_ERROR_CAN_T_BUILD_SIGNALS_HERE, CcPlaySound_CONSTRUCTION_RAIL, Command<CMD_BUILD_SIGNAL_TRACK>::Post(STR_ERROR_CAN_T_BUILD_SIGNALS_HERE, CcPlaySound_CONSTRUCTION_RAIL,
TileVirtXY(_thd.selstart.x, _thd.selstart.y), TileVirtXY(_thd.selend.x, _thd.selend.y), track, sigtype, sigvar, false, true, !_settings_client.gui.drag_signals_fixed_distance, _settings_client.gui.drag_signals_density); TileVirtXY(_thd.selstart.x, _thd.selstart.y), TileVirtXY(_thd.selend.x, _thd.selend.y), track, sigtype, sigvar, false, _ctrl_pressed, !_settings_client.gui.drag_signals_fixed_distance, _settings_client.gui.drag_signals_density);
} }
} }

View File

@@ -374,7 +374,7 @@ enum SaveLoadVersion : uint16_t {
SLV_SHIP_ACCELERATION, ///< 329 PR#10734 Start using Vehicle's acceleration field for ships too. SLV_SHIP_ACCELERATION, ///< 329 PR#10734 Start using Vehicle's acceleration field for ships too.
SLV_MAX_LOAN_FOR_COMPANY, ///< 330 PR#11224 Separate max loan for each company. SLV_MAX_LOAN_FOR_COMPANY, ///< 330 PR#11224 Separate max loan for each company.
SLV_DEPOT_UNBUNCHING, ///< 330 PR#11945 Allow unbunching shared order vehicles at a depot. SLV_DEPOT_UNBUNCHING, ///< 331 PR#11945 Allow unbunching shared order vehicles at a depot.
SL_MAX_VERSION, ///< Highest possible saveload version SL_MAX_VERSION, ///< Highest possible saveload version
}; };

View File

@@ -17,6 +17,7 @@
#include "network/network_func.h" #include "network/network_func.h"
#include "network/core/config.h" #include "network/core/config.h"
#include "pathfinder/pathfinder_type.h" #include "pathfinder/pathfinder_type.h"
#include "linkgraph/linkgraphschedule.h"
#include "genworld.h" #include "genworld.h"
#include "train.h" #include "train.h"
#include "news_func.h" #include "news_func.h"
@@ -541,6 +542,29 @@ static void ChangeTimekeepingUnits(int32_t)
} }
InvalidateWindowClassesData(WC_GAME_OPTIONS, 0); InvalidateWindowClassesData(WC_GAME_OPTIONS, 0);
/* It is possible to change these units in Scenario Editor. We must set the economy date appropriately. */
if (_game_mode == GM_EDITOR) {
TimerGameEconomy::Date new_economy_date;
TimerGameEconomy::DateFract new_economy_date_fract;
if (TimerGameEconomy::UsingWallclockUnits()) {
/* If the new mode is wallclock units, set the economy year back to 1. */
new_economy_date = TimerGameEconomy::ConvertYMDToDate(1, 0, 1);
new_economy_date_fract = 0;
} else {
/* If the new mode is calendar units, sync the economy year with the calendar year. */
new_economy_date = TimerGameCalendar::date.base();
new_economy_date_fract = TimerGameCalendar::date_fract;
}
/* If you open a savegame as a scenario, there may already be link graphs and/or vehicles. These use economy date. */
LinkGraphSchedule::instance.ShiftDates(new_economy_date - TimerGameEconomy::date);
for (auto v : Vehicle::Iterate()) v->ShiftDates(new_economy_date - TimerGameEconomy::date);
/* Only change the date after changing cached values above. */
TimerGameEconomy::SetDate(new_economy_date, new_economy_date_fract);
}
} }
/** /**

View File

@@ -273,16 +273,19 @@ static CommandCost RemoveShipDepot(TileIndex tile, DoCommandFlag flags)
if (ret.Failed()) return ret; if (ret.Failed()) return ret;
} }
bool do_clear = (flags & DC_FORCE_CLEAR_TILE) != 0;
if (flags & DC_EXEC) { if (flags & DC_EXEC) {
delete Depot::GetByTile(tile); delete Depot::GetByTile(tile);
Company *c = Company::GetIfValid(GetTileOwner(tile)); Company *c = Company::GetIfValid(GetTileOwner(tile));
if (c != nullptr) { if (c != nullptr) {
c->infrastructure.water -= 2 * LOCK_DEPOT_TILE_FACTOR; c->infrastructure.water -= 2 * LOCK_DEPOT_TILE_FACTOR;
if (do_clear && GetWaterClass(tile) == WATER_CLASS_CANAL) c->infrastructure.water--;
DirtyCompanyInfrastructureWindows(c->index); DirtyCompanyInfrastructureWindows(c->index);
} }
MakeWaterKeepingClass(tile, GetTileOwner(tile)); if (!do_clear) MakeWaterKeepingClass(tile, GetTileOwner(tile));
MakeWaterKeepingClass(tile2, GetTileOwner(tile2)); MakeWaterKeepingClass(tile2, GetTileOwner(tile2));
} }