(svn r21842) -Feature [FS#4393]: [NewGRF] Introduction dates/required types for rail types; e.g. introduce a particular rail type in 1960 (or when a vehicle using it is introduced), but also allow limiting its introduction to only happen when the required railtypes are available

This commit is contained in:
rubidium 2011-01-18 21:30:59 +00:00
parent 6371b75bcc
commit b8c9988d9f
6 changed files with 135 additions and 3 deletions

View File

@ -44,6 +44,11 @@ EngineOverrideManager _engine_mngr;
*/ */
static Year _year_engine_aging_stops; 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 */ /** Number of engines of each vehicle type in original engine data */
const uint8 _engine_counts[4] = { const uint8 _engine_counts[4] = {
lengthof(_orig_rail_vehicle_info), lengthof(_orig_rail_vehicle_info),
@ -474,8 +479,30 @@ void SetupEngines()
const Engine *e = new Engine(eid->type, eid->internal_id); const Engine *e = new Engine(eid->type, eid->internal_id);
assert(e->index == index); 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); void ShowEnginePreviewWindow(EngineID engine);
@ -602,6 +629,19 @@ void StartupEngines()
c->avail_roadtypes = GetCompanyRoadtypes(c->index); 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 */ /* Invalidate any open purchase lists */
InvalidateWindowClassesData(WC_BUILD_VEHICLE); InvalidateWindowClassesData(WC_BUILD_VEHICLE);
} }
@ -614,7 +654,7 @@ static void AcceptEnginePreview(EngineID eid, CompanyID company)
SetBit(e->company_avail, company); SetBit(e->company_avail, company);
if (e->type == VEH_TRAIN) { if (e->type == VEH_TRAIN) {
assert(e->u.rail.railtype < RAILTYPE_END); 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) { } else if (e->type == VEH_ROAD) {
SetBit(c->avail_roadtypes, HasBit(e->info.misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_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. */ /** Daily check to offer an exclusive engine preview to the companies. */
void EnginesDailyLoop() void EnginesDailyLoop()
{ {
CheckRailIntroduction();
if (_cur_year >= _year_engine_aging_stops) return; if (_cur_year >= _year_engine_aging_stops) return;
Engine *e; Engine *e;
@ -760,7 +802,7 @@ static void NewVehicleAvailable(Engine *e)
/* maybe make another rail type available */ /* maybe make another rail type available */
RailType railtype = e->u.rail.railtype; RailType railtype = e->u.rail.railtype;
assert(railtype < RAILTYPE_END); 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) { } else if (e->type == VEH_ROAD) {
/* maybe make another road type available */ /* 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); FOR_ALL_COMPANIES(c) SetBit(c->avail_roadtypes, HasBit(e->info.misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD);

View File

@ -3209,6 +3209,7 @@ static ChangeInfoResult RailTypeChangeInfo(uint id, int numinfo, int prop, ByteR
case 0x0E: // Compatible railtype list case 0x0E: // Compatible railtype list
case 0x0F: // Powered railtype list case 0x0F: // Powered railtype list
case 0x18: // Railtype list required for date introduction
case 0x19: // Introduced railtype list case 0x19: // Introduced railtype list
{ {
/* Rail type compatibility bits are added to the existing bits /* 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) { switch (prop) {
case 0x0E: SetBit(rti->compatible_railtypes, rt); break; case 0x0E: SetBit(rti->compatible_railtypes, rt); break;
case 0x0F: SetBit(rti->powered_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; 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()); rti->map_colour = MapDOSColour(buf->ReadByte());
break; break;
case 0x17: // Introduction date
rti->introduction_date = buf->ReadDWord();
break;
default: default:
ret = CIR_UNKNOWN; ret = CIR_UNKNOWN;
break; break;
@ -3304,6 +3310,7 @@ static ChangeInfoResult RailTypeReserveInfo(uint id, int numinfo, int prop, Byte
case 0x0E: // Compatible railtype list case 0x0E: // Compatible railtype list
case 0x0F: // Powered railtype list case 0x0F: // Powered railtype list
case 0x18: // Railtype list required for date introduction
case 0x19: // Introduced railtype list case 0x19: // Introduced railtype list
for (int j = buf->ReadByte(); j != 0; j--) buf->ReadDWord(); for (int j = buf->ReadByte(); j != 0; j--) buf->ReadDWord();
break; break;
@ -3316,6 +3323,10 @@ static ChangeInfoResult RailTypeReserveInfo(uint id, int numinfo, int prop, Byte
buf->ReadByte(); buf->ReadByte();
break; break;
case 0x17: // Introduction date
buf->ReadDWord();
break;
default: default:
ret = CIR_UNKNOWN; ret = CIR_UNKNOWN;
break; break;

View File

@ -192,6 +192,40 @@ RailType GetBestRailtype(const CompanyID company)
return RAILTYPE_RAIL; 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 GetCompanyRailtypes(CompanyID company)
{ {
RailTypes rts = RAILTYPES_NONE; RailTypes rts = RAILTYPES_NONE;
@ -211,7 +245,7 @@ RailTypes GetCompanyRailtypes(CompanyID company)
} }
} }
return rts; return AddDateIntroducedRailTypes(rts, _date);
} }
RailType GetRailTypeByLabel(RailTypeLabel label) RailType GetRailTypeByLabel(RailTypeLabel label)

View File

@ -19,6 +19,7 @@
#include "economy_func.h" #include "economy_func.h"
#include "slope_type.h" #include "slope_type.h"
#include "strings_type.h" #include "strings_type.h"
#include "date_type.h"
/** Railtype flags. */ /** Railtype flags. */
enum RailTypeFlags { enum RailTypeFlags {
@ -216,6 +217,21 @@ struct RailtypeInfo {
*/ */
byte map_colour; 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. * Bitmask of which other railtypes are introduced when this railtype is introduced.
*/ */
@ -368,6 +384,8 @@ bool ValParamRailtype(const RailType rail);
*/ */
RailType GetBestRailtype(const CompanyID company); RailType GetBestRailtype(const CompanyID company);
RailTypes AddDateIntroducedRailTypes(RailTypes current, Date date);
/** /**
* Get the rail types the given company can build. * Get the rail types the given company can build.
* @param c the company to get the rail types for. * @param c the company to get the rail types for.

View File

@ -95,6 +95,12 @@ static const RailtypeInfo _original_railtypes[] = {
/* map colour */ /* map colour */
0x0A, 0x0A,
/* introduction date */
INVALID_DATE,
/* railtypes required for this to be introduced */
RAILTYPES_NONE,
/* introduction rail types */ /* introduction rail types */
RAILTYPES_RAIL, RAILTYPES_RAIL,
@ -181,6 +187,12 @@ static const RailtypeInfo _original_railtypes[] = {
/* map colour */ /* map colour */
0x0A, 0x0A,
/* introduction date */
INVALID_DATE,
/* railtypes required for this to be introduced */
RAILTYPES_NONE,
/* introduction rail types */ /* introduction rail types */
RAILTYPES_ELECTRIC, RAILTYPES_ELECTRIC,
@ -263,6 +275,12 @@ static const RailtypeInfo _original_railtypes[] = {
/* map colour */ /* map colour */
0x0A, 0x0A,
/* introduction date */
INVALID_DATE,
/* railtypes required for this to be introduced */
RAILTYPES_NONE,
/* introduction rail types */ /* introduction rail types */
RAILTYPES_MONO, RAILTYPES_MONO,
@ -345,6 +363,12 @@ static const RailtypeInfo _original_railtypes[] = {
/* map colour */ /* map colour */
0x0A, 0x0A,
/* introduction date */
INVALID_DATE,
/* railtypes required for this to be introduced */
RAILTYPES_NONE,
/* introduction rail types */ /* introduction rail types */
RAILTYPES_MAGLEV, RAILTYPES_MAGLEV,

View File

@ -703,6 +703,9 @@ static CallBackFunction ToolbarBuildRailClick(Window *w)
used_railtypes |= GetRailTypeInfo(e->u.rail.railtype)->introduces_railtypes; 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); const Company *c = Company::Get(_local_company);
DropDownList *list = new DropDownList(); DropDownList *list = new DropDownList();
for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) { for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) {