summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/engine.cpp46
-rw-r--r--src/newgrf.cpp11
-rw-r--r--src/rail.cpp36
-rw-r--r--src/rail.h18
-rw-r--r--src/table/railtypes.h24
-rw-r--r--src/toolbar_gui.cpp3
6 files changed, 135 insertions, 3 deletions
diff --git a/src/engine.cpp b/src/engine.cpp
index 198434a88..048fcc82f 100644
--- a/src/engine.cpp
+++ b/src/engine.cpp
@@ -44,6 +44,11 @@ EngineOverrideManager _engine_mngr;
*/
static Year _year_engine_aging_stops;
+/**
+ * The railtypes that have been or never will be introduced, or
+ * an inverse bitmap of rail types that have to be introduced. */
+static uint16 _introduced_railtypes;
+
/** Number of engines of each vehicle type in original engine data */
const uint8 _engine_counts[4] = {
lengthof(_orig_rail_vehicle_info),
@@ -474,8 +479,30 @@ void SetupEngines()
const Engine *e = new Engine(eid->type, eid->internal_id);
assert(e->index == index);
}
+
+ _introduced_railtypes = 0;
}
+/**
+ * Check whether the railtypes should be introduced.
+ */
+static void CheckRailIntroduction()
+{
+ /* All railtypes have been introduced. */
+ if (_introduced_railtypes == UINT16_MAX || Company::GetPoolSize() == 0) return;
+
+ /* We need to find the railtypes that are known to all companies. */
+ RailTypes rts = (RailTypes)UINT16_MAX;
+
+ /* We are at, or past the introduction date of the rail. */
+ Company *c;
+ FOR_ALL_COMPANIES(c) {
+ c->avail_railtypes = AddDateIntroducedRailTypes(c->avail_railtypes, _date);
+ rts &= c->avail_railtypes;
+ }
+
+ _introduced_railtypes |= rts;
+}
void ShowEnginePreviewWindow(EngineID engine);
@@ -602,6 +629,19 @@ void StartupEngines()
c->avail_roadtypes = GetCompanyRoadtypes(c->index);
}
+ /* Rail types that are invalid or never introduced are marked as
+ * being introduced upon start. That way we can easily check whether
+ * there is any date related introduction that is still going to
+ * happen somewhere in the future. */
+ for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) {
+ const RailtypeInfo *rti = GetRailTypeInfo(rt);
+ if (rti->label != 0 && IsInsideMM(rti->introduction_date, 0, MAX_DAY)) continue;
+
+ SetBit(_introduced_railtypes, rt);
+ }
+
+ CheckRailIntroduction();
+
/* Invalidate any open purchase lists */
InvalidateWindowClassesData(WC_BUILD_VEHICLE);
}
@@ -614,7 +654,7 @@ static void AcceptEnginePreview(EngineID eid, CompanyID company)
SetBit(e->company_avail, company);
if (e->type == VEH_TRAIN) {
assert(e->u.rail.railtype < RAILTYPE_END);
- c->avail_railtypes |= GetRailTypeInfo(e->u.rail.railtype)->introduces_railtypes;
+ c->avail_railtypes = AddDateIntroducedRailTypes(c->avail_railtypes | GetRailTypeInfo(e->u.rail.railtype)->introduces_railtypes, _date);
} else if (e->type == VEH_ROAD) {
SetBit(c->avail_roadtypes, HasBit(e->info.misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD);
}
@@ -663,6 +703,8 @@ static CompanyID GetBestCompany(uint8 pp)
/** Daily check to offer an exclusive engine preview to the companies. */
void EnginesDailyLoop()
{
+ CheckRailIntroduction();
+
if (_cur_year >= _year_engine_aging_stops) return;
Engine *e;
@@ -760,7 +802,7 @@ static void NewVehicleAvailable(Engine *e)
/* maybe make another rail type available */
RailType railtype = e->u.rail.railtype;
assert(railtype < RAILTYPE_END);
- FOR_ALL_COMPANIES(c) c->avail_railtypes |= GetRailTypeInfo(e->u.rail.railtype)->introduces_railtypes;
+ FOR_ALL_COMPANIES(c) c->avail_railtypes = AddDateIntroducedRailTypes(c->avail_railtypes | GetRailTypeInfo(e->u.rail.railtype)->introduces_railtypes, _date);
} else if (e->type == VEH_ROAD) {
/* maybe make another road type available */
FOR_ALL_COMPANIES(c) SetBit(c->avail_roadtypes, HasBit(e->info.misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD);
diff --git a/src/newgrf.cpp b/src/newgrf.cpp
index 4f3c23f2f..622297fb5 100644
--- a/src/newgrf.cpp
+++ b/src/newgrf.cpp
@@ -3209,6 +3209,7 @@ static ChangeInfoResult RailTypeChangeInfo(uint id, int numinfo, int prop, ByteR
case 0x0E: // Compatible railtype list
case 0x0F: // Powered railtype list
+ case 0x18: // Railtype list required for date introduction
case 0x19: // Introduced railtype list
{
/* Rail type compatibility bits are added to the existing bits
@@ -3222,6 +3223,7 @@ static ChangeInfoResult RailTypeChangeInfo(uint id, int numinfo, int prop, ByteR
switch (prop) {
case 0x0E: SetBit(rti->compatible_railtypes, rt); break;
case 0x0F: SetBit(rti->powered_railtypes, rt); break;
+ case 0x18: SetBit(rti->introduction_required_railtypes, rt); break;
case 0x19: SetBit(rti->introduces_railtypes, rt); break;
}
}
@@ -3257,6 +3259,10 @@ static ChangeInfoResult RailTypeChangeInfo(uint id, int numinfo, int prop, ByteR
rti->map_colour = MapDOSColour(buf->ReadByte());
break;
+ case 0x17: // Introduction date
+ rti->introduction_date = buf->ReadDWord();
+ break;
+
default:
ret = CIR_UNKNOWN;
break;
@@ -3304,6 +3310,7 @@ static ChangeInfoResult RailTypeReserveInfo(uint id, int numinfo, int prop, Byte
case 0x0E: // Compatible railtype list
case 0x0F: // Powered railtype list
+ case 0x18: // Railtype list required for date introduction
case 0x19: // Introduced railtype list
for (int j = buf->ReadByte(); j != 0; j--) buf->ReadDWord();
break;
@@ -3316,6 +3323,10 @@ static ChangeInfoResult RailTypeReserveInfo(uint id, int numinfo, int prop, Byte
buf->ReadByte();
break;
+ case 0x17: // Introduction date
+ buf->ReadDWord();
+ break;
+
default:
ret = CIR_UNKNOWN;
break;
diff --git a/src/rail.cpp b/src/rail.cpp
index a2285ef16..2a308c547 100644
--- a/src/rail.cpp
+++ b/src/rail.cpp
@@ -192,6 +192,40 @@ RailType GetBestRailtype(const CompanyID company)
return RAILTYPE_RAIL;
}
+/**
+ * Add the rail types that are to be introduced at the given date.
+ * @param current The currently available railtypes.
+ * @param date The date for the introduction comparisions.
+ * @return The rail types that should be available when date
+ * introduced rail types are taken into account as well.
+ */
+RailTypes AddDateIntroducedRailTypes(RailTypes current, Date date)
+{
+ RailTypes rts = current;
+
+ for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) {
+ const RailtypeInfo *rti = GetRailTypeInfo(rt);
+ /* Unused rail type. */
+ if (rti->label == 0) continue;
+
+ /* Not date introduced. */
+ if (!IsInsideMM(rti->introduction_date, 0, MAX_DAY)) continue;
+
+ /* Not yet introduced at this date. */
+ if (rti->introduction_date > date) continue;
+
+ /* Have we introduced all required railtypes? */
+ RailTypes required = rti->introduction_required_railtypes;
+ if ((rts & required) != required) continue;
+
+ rts |= rti->introduces_railtypes;
+ }
+
+ /* When we added railtypes we need to run this method again; the added
+ * railtypes might enable more rail types to become introduced. */
+ return rts == current ? rts : AddDateIntroducedRailTypes(rts, date);
+}
+
RailTypes GetCompanyRailtypes(CompanyID company)
{
RailTypes rts = RAILTYPES_NONE;
@@ -211,7 +245,7 @@ RailTypes GetCompanyRailtypes(CompanyID company)
}
}
- return rts;
+ return AddDateIntroducedRailTypes(rts, _date);
}
RailType GetRailTypeByLabel(RailTypeLabel label)
diff --git a/src/rail.h b/src/rail.h
index 81bac120c..46df36803 100644
--- a/src/rail.h
+++ b/src/rail.h
@@ -19,6 +19,7 @@
#include "economy_func.h"
#include "slope_type.h"
#include "strings_type.h"
+#include "date_type.h"
/** Railtype flags. */
enum RailTypeFlags {
@@ -217,6 +218,21 @@ struct RailtypeInfo {
byte map_colour;
/**
+ * Introduction date.
+ * When #INVALID_DATE or a vehicle using this railtype gets introduced earlier,
+ * the vehicle's introduction date will be used instead for this railtype.
+ * The introduction at this date is furthermore limited by the
+ * #introduction_required_types.
+ */
+ Date introduction_date;
+
+ /**
+ * Bitmask of railtypes that are required for this railtype to be introduced
+ * at a given #introduction_date.
+ */
+ RailTypes introduction_required_railtypes;
+
+ /**
* Bitmask of which other railtypes are introduced when this railtype is introduced.
*/
RailTypes introduces_railtypes;
@@ -368,6 +384,8 @@ bool ValParamRailtype(const RailType rail);
*/
RailType GetBestRailtype(const CompanyID company);
+RailTypes AddDateIntroducedRailTypes(RailTypes current, Date date);
+
/**
* Get the rail types the given company can build.
* @param c the company to get the rail types for.
diff --git a/src/table/railtypes.h b/src/table/railtypes.h
index 7e59ab70b..c4decab18 100644
--- a/src/table/railtypes.h
+++ b/src/table/railtypes.h
@@ -95,6 +95,12 @@ static const RailtypeInfo _original_railtypes[] = {
/* map colour */
0x0A,
+ /* introduction date */
+ INVALID_DATE,
+
+ /* railtypes required for this to be introduced */
+ RAILTYPES_NONE,
+
/* introduction rail types */
RAILTYPES_RAIL,
@@ -181,6 +187,12 @@ static const RailtypeInfo _original_railtypes[] = {
/* map colour */
0x0A,
+ /* introduction date */
+ INVALID_DATE,
+
+ /* railtypes required for this to be introduced */
+ RAILTYPES_NONE,
+
/* introduction rail types */
RAILTYPES_ELECTRIC,
@@ -263,6 +275,12 @@ static const RailtypeInfo _original_railtypes[] = {
/* map colour */
0x0A,
+ /* introduction date */
+ INVALID_DATE,
+
+ /* railtypes required for this to be introduced */
+ RAILTYPES_NONE,
+
/* introduction rail types */
RAILTYPES_MONO,
@@ -345,6 +363,12 @@ static const RailtypeInfo _original_railtypes[] = {
/* map colour */
0x0A,
+ /* introduction date */
+ INVALID_DATE,
+
+ /* railtypes required for this to be introduced */
+ RAILTYPES_NONE,
+
/* introduction rail types */
RAILTYPES_MAGLEV,
diff --git a/src/toolbar_gui.cpp b/src/toolbar_gui.cpp
index a93568969..90e107550 100644
--- a/src/toolbar_gui.cpp
+++ b/src/toolbar_gui.cpp
@@ -703,6 +703,9 @@ static CallBackFunction ToolbarBuildRailClick(Window *w)
used_railtypes |= GetRailTypeInfo(e->u.rail.railtype)->introduces_railtypes;
}
+ /* Get the date introduced railtypes as well. */
+ used_railtypes = AddDateIntroducedRailTypes(used_railtypes, MAX_DAY);
+
const Company *c = Company::Get(_local_company);
DropDownList *list = new DropDownList();
for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) {