diff --git a/src/openttd.cpp b/src/openttd.cpp index be588e5d99..c79b68014e 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -2570,6 +2570,13 @@ bool AfterLoadGame() FOR_ALL_SIGNS(si) { if (si->owner != OWNER_NONE && !IsValidCompanyID(si->owner)) si->owner = OWNER_NONE; } + + /* Station can get named based on an industry type, but the current ones + * are not, so mark them as if they are not named by an industry. */ + Station *st; + FOR_ALL_STATIONS(st) { + st->indtype = IT_INVALID; + } } GamelogPrintDebug(1); diff --git a/src/saveload.cpp b/src/saveload.cpp index ce48465caf..ac441ffba1 100644 --- a/src/saveload.cpp +++ b/src/saveload.cpp @@ -37,7 +37,7 @@ #include "table/strings.h" -extern const uint16 SAVEGAME_VERSION = 102; +extern const uint16 SAVEGAME_VERSION = 103; SavegameType _savegame_type; ///< type of savegame we are loading diff --git a/src/station.cpp b/src/station.cpp index 1c3570d521..371a8fc43b 100644 --- a/src/station.cpp +++ b/src/station.cpp @@ -51,6 +51,7 @@ Station::Station(TileIndex tile) facilities = 0; last_vehicle_type = VEH_INVALID; + indtype = IT_INVALID; random_bits = 0; // Random() must be called when station is really built (DC_EXEC) waiting_triggers = 0; diff --git a/src/station_base.h b/src/station_base.h index 9e22f231ea..2943c10f8d 100644 --- a/src/station_base.h +++ b/src/station_base.h @@ -15,6 +15,7 @@ #include "date_type.h" #include "vehicle_type.h" #include "company_type.h" +#include "industry_type.h" #include "core/geometry_type.hpp" #include "viewport_type.h" #include @@ -130,8 +131,11 @@ public: TileIndex airport_tile; TileIndex dock_tile; Town *town; - StringID string_id; ///< Default name (town area) of station + + /* Place to get a name from, in order of importance: */ char *name; ///< Custom name + IndustryType indtype; ///< Industry type to get the name from + StringID string_id; ///< Default name (town area) of station ViewportSign sign; diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 9adb5aff96..95ea6e7503 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -223,6 +223,36 @@ enum StationNaming { STATIONNAMING_HELIPORT, }; +/** Information to handle station action 0 property 24 correctly */ +struct StationNameInformation { + uint32 free_names; ///< Current bitset of free names (we can remove names). + bool *indtypes; ///< Array of bools telling whether an industry type has been found. +}; + +/** + * Find a station action 0 property 24 station name, or reduce the + * free_names if needed. + * @param tile the tile to search + * @param user_data the StationNameInformation to base the search on + * @return true if the tile contains an industry that has not given + * it's name to one of the other stations in town. + */ +static bool FindNearIndustryName(TileIndex tile, void *user_data) +{ + /* All already found industry types */ + StationNameInformation *sni = (StationNameInformation*)user_data; + if (!IsTileType(tile, MP_INDUSTRY)) return false; + + /* If the station name is undefined it means that it doesn't name a station */ + IndustryType indtype = GetIndustryType(tile); + if (GetIndustrySpec(indtype)->station_name == STR_UNDEFINED) return false; + + /* In all cases if an industry that provides a name is found two of + * the standard names will be disabled. */ + sni->free_names &= ~(1 << M(STR_SV_STNAME_OILFIELD) | 1 << M(STR_SV_STNAME_MINES)); + return !sni->indtypes[indtype]; +} + static StringID GenerateStationName(Station *st, TileIndex tile, int flag) { static const uint32 _gen_station_name_bits[] = { @@ -237,9 +267,16 @@ static StringID GenerateStationName(Station *st, TileIndex tile, int flag) const Town *t = st->town; uint32 free_names = UINT32_MAX; + bool indtypes[NUM_INDUSTRYTYPES]; + memset(indtypes, 0, sizeof(indtypes)); + const Station *s; FOR_ALL_STATIONS(s) { if (s != st && s->town == t) { + if (s->indtype != IT_INVALID) { + indtypes[s->indtype] = true; + continue; + } uint str = M(s->string_id); if (str <= 0x20) { if (str == M(STR_SV_STNAME_FOREST)) { @@ -250,6 +287,24 @@ static StringID GenerateStationName(Station *st, TileIndex tile, int flag) } } + if (flag != STATIONNAMING_BUOY) { + TileIndex indtile = tile; + StationNameInformation sni = { free_names, indtypes }; + if (CircularTileSearch(&indtile, 7, FindNearIndustryName, &sni)) { + /* An industry has been found nearby */ + IndustryType indtype = GetIndustryType(indtile); + const IndustrySpec *indsp = GetIndustrySpec(indtype); + /* STR_NULL means it only disables oil rig/mines */ + if (indsp->station_name != STR_NULL) { + st->indtype = indtype; + return STR_SV_STNAME_FALLBACK; + } + } + + /* Oil rigs/mines name could be marked not free by looking for a near by industry. */ + free_names = sni.free_names; + } + /* check default names */ uint32 tmp = free_names & _gen_station_name_bits[flag]; if (tmp != 0) return STR_SV_STNAME + FindFirstBit(tmp); @@ -3255,6 +3310,7 @@ static const SaveLoad _station_desc[] = { SLE_VAR(Station, string_id, SLE_STRINGID), SLE_CONDSTR(Station, name, SLE_STR, 0, 84, SL_MAX_VERSION), + SLE_CONDVAR(Station, indtype, SLE_UINT8, 103, SL_MAX_VERSION), SLE_VAR(Station, had_vehicle_of_type, SLE_UINT16), SLE_VAR(Station, time_since_load, SLE_UINT8), diff --git a/src/strings.cpp b/src/strings.cpp index 010298062f..8512a99c41 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -862,11 +862,24 @@ static char* FormatString(char* buff, const char* str, const int64* argv, uint c if (st->name != NULL) { buff = strecpy(buff, st->name, last); } else { + StringID str = st->string_id; + if (st->indtype != IT_INVALID) { + /* Special case where the industry provides the name for the station */ + const IndustrySpec *indsp = GetIndustrySpec(st->indtype); + + /* Industry GRFs can change which might remove the station name and + * thus cause very strange things. Here we check for that before we + * actually set the station name. */ + if (indsp->station_name != STR_NULL && indsp->station_name != STR_UNDEFINED) { + str = indsp->station_name; + } + } + int64 temp[3]; temp[0] = STR_TOWN; temp[1] = st->town->index; temp[2] = st->index; - buff = GetStringWithArgs(buff, st->string_id, temp, last); + buff = GetStringWithArgs(buff, str, temp, last); } break; }