diff --git a/src/fontcache.cpp b/src/fontcache.cpp index d5f2b3f7c4..1d7f528d63 100644 --- a/src/fontcache.cpp +++ b/src/fontcache.cpp @@ -173,7 +173,7 @@ static FT_Error GetFontByFaceName(const char *font_name, FT_Face *face) } } - if (!SUCCEEDED(SHGetFolderPath(NULL, CSIDL_FONTS, NULL, SHGFP_TYPE_CURRENT, vbuffer))) { + if (!SUCCEEDED(OTTDSHGetFolderPath(NULL, CSIDL_FONTS, NULL, SHGFP_TYPE_CURRENT, vbuffer))) { DEBUG(freetype, 0, "SHGetFolderPath cannot return fonts directory"); goto folder_error; } diff --git a/src/os/windows/win32.cpp b/src/os/windows/win32.cpp index 992ae16c71..3bb22288f5 100644 --- a/src/os/windows/win32.cpp +++ b/src/os/windows/win32.cpp @@ -17,6 +17,7 @@ #include "../../fios.h" #include #include +#include #include /* SHGetFolderPath */ #include #include "win32.h" @@ -505,19 +506,25 @@ void DetermineBasePaths(const char *exe) char tmp[MAX_PATH]; TCHAR path[MAX_PATH]; #ifdef WITH_PERSONAL_DIR - SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, path); - strecpy(tmp, WIDE_TO_MB_BUFFER(path, tmp, lengthof(tmp)), lastof(tmp)); - AppendPathSeparator(tmp, MAX_PATH); - ttd_strlcat(tmp, PERSONAL_DIR, MAX_PATH); - AppendPathSeparator(tmp, MAX_PATH); - _searchpaths[SP_PERSONAL_DIR] = strdup(tmp); + if (SUCCEEDED(OTTDSHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, path))) { + strecpy(tmp, WIDE_TO_MB_BUFFER(path, tmp, lengthof(tmp)), lastof(tmp)); + AppendPathSeparator(tmp, MAX_PATH); + ttd_strlcat(tmp, PERSONAL_DIR, MAX_PATH); + AppendPathSeparator(tmp, MAX_PATH); + _searchpaths[SP_PERSONAL_DIR] = strdup(tmp); + } else { + _searchpaths[SP_PERSONAL_DIR] = NULL; + } - SHGetFolderPath(NULL, CSIDL_COMMON_DOCUMENTS, NULL, SHGFP_TYPE_CURRENT, path); - strecpy(tmp, WIDE_TO_MB_BUFFER(path, tmp, lengthof(tmp)), lastof(tmp)); - AppendPathSeparator(tmp, MAX_PATH); - ttd_strlcat(tmp, PERSONAL_DIR, MAX_PATH); - AppendPathSeparator(tmp, MAX_PATH); - _searchpaths[SP_SHARED_DIR] = strdup(tmp); + if (SUCCEEDED(OTTDSHGetFolderPath(NULL, CSIDL_COMMON_DOCUMENTS, NULL, SHGFP_TYPE_CURRENT, path))) { + strecpy(tmp, WIDE_TO_MB_BUFFER(path, tmp, lengthof(tmp)), lastof(tmp)); + AppendPathSeparator(tmp, MAX_PATH); + ttd_strlcat(tmp, PERSONAL_DIR, MAX_PATH); + AppendPathSeparator(tmp, MAX_PATH); + _searchpaths[SP_SHARED_DIR] = strdup(tmp); + } else { + _searchpaths[SP_SHARED_DIR] = NULL; + } #else _searchpaths[SP_PERSONAL_DIR] = NULL; _searchpaths[SP_SHARED_DIR] = NULL; @@ -726,8 +733,11 @@ HRESULT OTTDSHGetFolderPath(HWND hwnd, int csidl, HANDLE hToken, DWORD dwFlags, #else # define W(x) x "A" #endif - if (!LoadLibraryList((Function*)&SHGetFolderPath, "SHFolder.dll\0" W("SHGetFolderPath") "\0\0")) { - DEBUG(misc, 0, "Unable to load " W("SHGetFolderPath") "from SHFolder.dll"); + /* The function lives in shell32.dll for all current Windows versions, but it first started to appear in SHFolder.dll. */ + if (!LoadLibraryList((Function*)&SHGetFolderPath, "shell32.dll\0" W("SHGetFolderPath") "\0\0")) { + if (!LoadLibraryList((Function*)&SHGetFolderPath, "SHFolder.dll\0" W("SHGetFolderPath") "\0\0")) { + DEBUG(misc, 0, "Unable to load " W("SHGetFolderPath") "from either shell32.dll or SHFolder.dll"); + } } #undef W first_time = false; @@ -752,6 +762,17 @@ HRESULT OTTDSHGetFolderPath(HWND hwnd, int csidl, HANDLE hToken, DWORD dwFlags, return (HRESULT)0; + case CSIDL_PERSONAL: + case CSIDL_COMMON_DOCUMENTS: { + HKEY key; + if (RegOpenKeyEx(csidl == CSIDL_PERSONAL ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, REGSTR_PATH_SPECIAL_FOLDERS, 0, KEY_READ, &key) != ERROR_SUCCESS) break; + DWORD len = MAX_PATH; + ret = RegQueryValueEx(key, csidl == CSIDL_PERSONAL ? _T("Personal") : _T("Common Documents"), NULL, NULL, (LPBYTE)pszPath, &len); + RegCloseKey(key); + if (ret == ERROR_SUCCESS) return (HRESULT)0; + break; + } + /* XXX - other types to go here when needed... */ } } diff --git a/src/os/windows/win32.h b/src/os/windows/win32.h index 66c519973f..941d3ea840 100644 --- a/src/os/windows/win32.h +++ b/src/os/windows/win32.h @@ -40,12 +40,6 @@ extern uint _codepage; // local code-page in the system @see win32_v.cpp:WM_INPU # define WIDE_TO_MB_BUFFER(str, buffer, buflen) (str) #endif -/* Override SHGetFolderPath with our custom implementation */ -#if defined(SHGetFolderPath) -#undef SHGetFolderPath -#endif -#define SHGetFolderPath OTTDSHGetFolderPath - HRESULT OTTDSHGetFolderPath(HWND, int, HANDLE, DWORD, LPTSTR); #if defined(__MINGW32__) diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp index e740e26f9e..bba108d4c6 100644 --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -429,17 +429,17 @@ void RoadVehicle::UpdateDeltaXY(Direction direction) */ inline int RoadVehicle::GetCurrentMaxSpeed() const { - if (_settings_game.vehicle.roadveh_acceleration_model == AM_ORIGINAL) return min(this->vcache.cached_max_speed, this->current_order.max_speed * 2); - int max_speed = this->vcache.cached_max_speed; /* Limit speed to 50% while reversing, 75% in curves. */ for (const RoadVehicle *u = this; u != NULL; u = u->Next()) { - if (this->state <= RVSB_TRACKDIR_MASK && IsReversingRoadTrackdir((Trackdir)this->state)) { - max_speed = this->vcache.cached_max_speed / 2; - break; - } else if ((u->direction & 1) == 0) { - max_speed = this->vcache.cached_max_speed * 3 / 4; + if (_settings_game.vehicle.roadveh_acceleration_model == AM_REALISTIC) { + if (this->state <= RVSB_TRACKDIR_MASK && IsReversingRoadTrackdir((Trackdir)this->state)) { + max_speed = this->vcache.cached_max_speed / 2; + break; + } else if ((u->direction & 1) == 0) { + max_speed = this->vcache.cached_max_speed * 3 / 4; + } } /* Vehicle is on the middle part of a bridge. */ diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index a3837942c8..91ba3a5e89 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -2770,6 +2770,14 @@ bool AfterLoadGame() v->acceleration = avi->acceleration; } } + + /* Blocked tiles could be reserved due to a bug, which causes + * other places to assert upon e.g. station reconstruction. */ + for (TileIndex t = 0; t < map_size; t++) { + if (HasStationTileRail(t) && IsStationTileBlocked(t)) { + SetRailStationReservation(t, false); + } + } } /* Road stops is 'only' updating some caches */ diff --git a/src/script/api/script_base.cpp b/src/script/api/script_base.cpp index 2472fe1c77..7fd5b2df90 100644 --- a/src/script/api/script_base.cpp +++ b/src/script/api/script_base.cpp @@ -44,7 +44,7 @@ /* static */ bool ScriptBase::Chance(uint out, uint max) { EnforcePrecondition(false, out <= max); - return (uint16)Rand() <= (uint16)((65535 * out) / max); + return ScriptBase::RandRange(max) < out; } /* static */ bool ScriptBase::ChanceItem(int unused_param, uint out, uint max) diff --git a/src/script/api/script_base.hpp b/src/script/api/script_base.hpp index a01325820f..936dee77d9 100644 --- a/src/script/api/script_base.hpp +++ b/src/script/api/script_base.hpp @@ -70,6 +70,7 @@ public: * @param unused_param This parameter is not used, but is needed to work with lists. * @param out How many times it should return true. * @param max Out of this many times. + * @pre \a out is at most equal to \a max. * @return True if the chance worked out. */ static bool ChanceItem(int unused_param, uint out, uint max); diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index a01612511d..f1fb503930 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -371,10 +371,11 @@ int Train::GetCurveSpeedLimit() const */ int Train::GetCurrentMaxSpeed() const { - if (_settings_game.vehicle.train_acceleration_model == AM_ORIGINAL) return min(this->gcache.cached_max_track_speed, this->current_order.max_speed); + int max_speed = _settings_game.vehicle.train_acceleration_model == AM_ORIGINAL ? + this->gcache.cached_max_track_speed : + this->tcache.cached_max_curve_speed; - int max_speed = this->tcache.cached_max_curve_speed; - if (IsRailStationTile(this->tile)) { + if (_settings_game.vehicle.train_acceleration_model == AM_REALISTIC && IsRailStationTile(this->tile)) { StationID sid = GetStationIndex(this->tile); if (this->current_order.ShouldStopAtStation(this, sid)) { int station_ahead; @@ -400,7 +401,7 @@ int Train::GetCurrentMaxSpeed() const } for (const Train *u = this; u != NULL; u = u->Next()) { - if (u->track == TRACK_BIT_DEPOT) { + if (_settings_game.vehicle.train_acceleration_model == AM_REALISTIC && u->track == TRACK_BIT_DEPOT) { max_speed = min(max_speed, 61); break; } @@ -2775,7 +2776,7 @@ int Train::UpdateSpeed() switch (_settings_game.vehicle.train_acceleration_model) { default: NOT_REACHED(); case AM_ORIGINAL: - return this->DoUpdateSpeed(this->acceleration * (this->GetAccelerationStatus() == AS_BRAKE ? -4 : 2), 0, min(this->gcache.cached_max_track_speed, this->current_order.max_speed)); + return this->DoUpdateSpeed(this->acceleration * (this->GetAccelerationStatus() == AS_BRAKE ? -4 : 2), 0, this->GetCurrentMaxSpeed()); case AM_REALISTIC: return this->DoUpdateSpeed(this->GetAcceleration(), this->GetAccelerationStatus() == AS_BRAKE ? 0 : 2, this->GetCurrentMaxSpeed());