Changeset - r26684:bd3e30073232
[Not reviewed]
master
0 6 0
Peter Nelson - 18 months ago 2022-12-09 01:40:55
peter1138@openttd.org
Add: Additional vehicle flags to control variants.
6 files changed with 75 insertions and 14 deletions:
0 comments (0 inline, 0 general)
src/engine.cpp
Show inline comments
 
@@ -569,27 +569,34 @@ static bool IsWagon(EngineID index)
 
 */
 
static void ClearLastVariant(EngineID engine_id, VehicleType type)
 
{
 
	for (Engine *e : Engine::IterateType(type)) {
 
		if (e->display_last_variant == engine_id) e->display_last_variant = INVALID_ENGINE;
 
	}
 
}
 

	
 
/**
 
 * Update #Engine::reliability and (if needed) update the engine GUIs.
 
 * @param e %Engine to update.
 
 */
 
static void CalcEngineReliability(Engine *e)
 
void CalcEngineReliability(Engine *e, bool new_month)
 
{
 
	uint age = e->age;
 
	/* Get source engine for reliability age. This is normally our engine unless variant reliability syncing is requested. */
 
	Engine *re = e;
 
	while (re->info.variant_id != INVALID_ENGINE && re->info.variant_id != re->index && (re->info.extra_flags & ExtraEngineFlags::SyncReliability) != ExtraEngineFlags::None) {
 
		re = Engine::Get(re->info.variant_id);
 
	}
 

	
 
	uint age = re->age;
 
	if (new_month && re->index > e->index && age != MAX_DAY) age++; /* parent variant's age has not yet updated. */
 

	
 
	/* Check for early retirement */
 
	if (e->company_avail != 0 && !_settings_game.vehicle.never_expire_vehicles && e->info.base_life != 0xFF) {
 
		int retire_early = e->info.retire_early;
 
		uint retire_early_max_age = std::max(0, e->duration_phase_1 + e->duration_phase_2 - retire_early * 12);
 
		if (retire_early != 0 && age >= retire_early_max_age) {
 
			/* Early retirement is enabled and we're past the date... */
 
			e->company_avail = 0;
 
			ClearLastVariant(e->index, e->type);
 
			AddRemoveEngineFromAutoreplaceAndBuildWindows(e->type);
 
		}
 
	}
 
@@ -662,59 +669,71 @@ void StartupOneEngine(Engine *e, Date ag
 
	uint32 r = Random();
 

	
 
	/* Don't randomise the start-date in the first two years after gamestart to ensure availability
 
	 * of engines in early starting games.
 
	 * Note: TTDP uses fixed 1922 */
 
	e->intro_date = ei->base_intro <= ConvertYMDToDate(_settings_game.game_creation.starting_year + 2, 0, 1) ? ei->base_intro : (Date)GB(r, 0, 9) + ei->base_intro;
 
	if (e->intro_date <= _date) {
 
		e->age = (aging_date - e->intro_date) >> 5;
 
		e->company_avail = (CompanyMask)-1;
 
		e->flags |= ENGINE_AVAILABLE;
 
	}
 

	
 
	RestoreRandomSeeds(saved_seeds);
 
	/* Get parent variant index for syncing reliability via random seed. */
 
	const Engine *re = e;
 
	while (re->info.variant_id != INVALID_ENGINE && re->info.variant_id != re->index && (re->info.extra_flags & ExtraEngineFlags::SyncReliability) != ExtraEngineFlags::None) {
 
		re = Engine::Get(re->info.variant_id);
 
	}
 

	
 
	SetRandomSeed(_settings_game.game_creation.generation_seed ^
 
	              re->index ^
 
	              e->type ^
 
	              e->GetGRFID());
 

	
 
	r = Random();
 
	e->reliability_start = GB(r, 16, 14) + 0x7AE0;
 
	e->reliability_max   = GB(r,  0, 14) + 0xBFFF;
 

	
 
	r = Random();
 
	e->reliability_final = GB(r, 16, 14) + 0x3FFF;
 
	e->duration_phase_1 = GB(r, 0, 5) + 7;
 
	e->duration_phase_2 = GB(r, 5, 4) + ei->base_life * 12 - 96;
 
	e->duration_phase_3 = GB(r, 9, 7) + 120;
 

	
 
	e->reliability_spd_dec = ei->decay_speed << 2;
 
	RestoreRandomSeeds(saved_seeds);
 

	
 
	CalcEngineReliability(e);
 
	e->reliability_spd_dec = ei->decay_speed << 2;
 

	
 
	/* prevent certain engines from ever appearing. */
 
	if (!HasBit(ei->climates, _settings_game.game_creation.landscape)) {
 
		e->flags |= ENGINE_AVAILABLE;
 
		e->company_avail = 0;
 
	}
 
}
 

	
 
/**
 
 * Start/initialise all our engines. Must be called whenever there are changes
 
 * to the NewGRF config.
 
 */
 
void StartupEngines()
 
{
 
	/* Aging of vehicles stops, so account for that when starting late */
 
	const Date aging_date = std::min(_date, ConvertYMDToDate(_year_engine_aging_stops, 0, 1));
 

	
 
	for (Engine *e : Engine::Iterate()) {
 
		StartupOneEngine(e, aging_date);
 
	}
 
	for (Engine *e : Engine::Iterate()) {
 
		CalcEngineReliability(e, false);
 
	}
 

	
 
	/* Update the bitmasks for the vehicle lists */
 
	for (Company *c : Company::Iterate()) {
 
		c->avail_railtypes = GetCompanyRailtypes(c->index);
 
		c->avail_roadtypes = GetCompanyRoadTypes(c->index);
 
	}
 

	
 
	/* Invalidate any open purchase lists */
 
	InvalidateWindowClassesData(WC_BUILD_VEHICLE);
 

	
 
	SetWindowClassesDirty(WC_BUILD_VEHICLE);
 
	SetWindowClassesDirty(WC_REPLACE_VEHICLE);
 
@@ -766,40 +785,51 @@ static void DisableEngineForCompany(Engi
 
	}
 

	
 
	if (company == _local_company) {
 
		ClearLastVariant(e->index, e->type);
 
		AddRemoveEngineFromAutoreplaceAndBuildWindows(e->type);
 
	}
 
}
 

	
 
/**
 
 * Company \a company accepts engine \a eid for preview.
 
 * @param eid Engine being accepted (is under preview).
 
 * @param company Current company previewing the engine.
 
 * @param recursion_depth Recursion depth to avoid infinite loop.
 
 */
 
static void AcceptEnginePreview(EngineID eid, CompanyID company)
 
static void AcceptEnginePreview(EngineID eid, CompanyID company, int recursion_depth = 0)
 
{
 
	Engine *e = Engine::Get(eid);
 

	
 
	e->preview_company = INVALID_COMPANY;
 
	e->preview_asked = (CompanyMask)-1;
 

	
 
	EnableEngineForCompany(eid, company);
 

	
 
	/* Notify preview window, that it might want to close.
 
	 * Note: We cannot directly close the window.
 
	 *       In singleplayer this function is called from the preview window, so
 
	 *       we have to use the GUI-scope scheduling of InvalidateWindowData.
 
	 */
 
	InvalidateWindowData(WC_ENGINE_PREVIEW, eid);
 

	
 
	/* Don't search for variants to include if we are 10 levels deep already. */
 
	if (recursion_depth >= 10) return;
 

	
 
	/* Find variants to be included in preview. */
 
	for (Engine *ve : Engine::IterateType(e->type)) {
 
		if (ve->index != eid && ve->info.variant_id == eid && (ve->info.extra_flags & ExtraEngineFlags::JoinPreview) != ExtraEngineFlags::None) {
 
			AcceptEnginePreview(ve->index, company, recursion_depth + 1);
 
		}
 
	}
 
}
 

	
 
/**
 
 * Get the best company for an engine preview.
 
 * @param e Engine to preview.
 
 * @return Best company if it exists, #INVALID_COMPANY otherwise.
 
 */
 
static CompanyID GetPreviewCompany(Engine *e)
 
{
 
	CompanyID best_company = INVALID_COMPANY;
 

	
 
	/* For trains the cargomask has no useful meaning, since you can attach other wagons */
 
@@ -1005,68 +1035,71 @@ static void NewVehicleAvailable(Engine *
 
		assert(e->u.rail.railtype < RAILTYPE_END);
 
		for (Company *c : Company::Iterate()) 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 */
 
		assert(e->u.road.roadtype < ROADTYPE_END);
 
		for (Company* c : Company::Iterate()) c->avail_roadtypes = AddDateIntroducedRoadTypes(c->avail_roadtypes | GetRoadTypeInfo(e->u.road.roadtype)->introduces_roadtypes, _date);
 
	}
 

	
 
	/* Only broadcast event if AIs are able to build this vehicle type. */
 
	if (!IsVehicleTypeDisabled(e->type, true)) AI::BroadcastNewEvent(new ScriptEventEngineAvailable(index));
 

	
 
	/* Only provide the "New Vehicle available" news paper entry, if engine can be built. */
 
	if (!IsVehicleTypeDisabled(e->type, false)) {
 
	if (!IsVehicleTypeDisabled(e->type, false) && (e->info.extra_flags & ExtraEngineFlags::NoNews) == ExtraEngineFlags::None) {
 
		SetDParam(0, GetEngineCategoryName(index));
 
		SetDParam(1, index);
 
		AddNewsItem(STR_NEWS_NEW_VEHICLE_NOW_AVAILABLE_WITH_TYPE, NT_NEW_VEHICLES, NF_VEHICLE, NR_ENGINE, index);
 
	}
 

	
 
	/* Update the toolbar. */
 
	if (e->type == VEH_ROAD) InvalidateWindowData(WC_BUILD_TOOLBAR, TRANSPORT_ROAD);
 
	if (e->type == VEH_SHIP) InvalidateWindowData(WC_BUILD_TOOLBAR, TRANSPORT_WATER);
 
	if (e->type == VEH_AIRCRAFT) InvalidateWindowData(WC_BUILD_TOOLBAR, TRANSPORT_AIR);
 

	
 
	/* Close pending preview windows */
 
	CloseWindowById(WC_ENGINE_PREVIEW, index);
 
}
 

	
 
/** Monthly update of the availability, reliability, and preview offers of the engines. */
 
void EnginesMonthlyLoop()
 
{
 
	if (_cur_year < _year_engine_aging_stops) {
 
		bool refresh = false;
 
		for (Engine *e : Engine::Iterate()) {
 
			/* Age the vehicle */
 
			if ((e->flags & ENGINE_AVAILABLE) && e->age != MAX_DAY) {
 
				e->age++;
 
				CalcEngineReliability(e);
 
				CalcEngineReliability(e, true);
 
				refresh = true;
 
			}
 

	
 
			/* Do not introduce invalid engines */
 
			if (!e->IsEnabled()) continue;
 

	
 
			if (!(e->flags & ENGINE_AVAILABLE) && _date >= (e->intro_date + DAYS_IN_YEAR)) {
 
				/* Introduce it to all companies */
 
				NewVehicleAvailable(e);
 
			} else if (!(e->flags & (ENGINE_AVAILABLE | ENGINE_EXCLUSIVE_PREVIEW)) && _date >= e->intro_date) {
 
				/* Introduction date has passed...
 
				 * Check if it is allowed to build this vehicle type at all
 
				 * based on the current game settings. If not, it does not
 
				 * make sense to show the preview dialog to any company. */
 
				if (IsVehicleTypeDisabled(e->type, false)) continue;
 

	
 
				/* Do not introduce new rail wagons */
 
				if (IsWagon(e->index)) continue;
 

	
 
				/* Engine has no preview */
 
				if ((e->info.extra_flags & ExtraEngineFlags::NoPreview) != ExtraEngineFlags::None) continue;
 

	
 
				/* Show preview dialog to one of the companies. */
 
				e->flags |= ENGINE_EXCLUSIVE_PREVIEW;
 
				e->preview_company = INVALID_COMPANY;
 
				e->preview_asked = 0;
 
			}
 
		}
 

	
 
		InvalidateWindowClassesData(WC_BUILD_VEHICLE); // rebuild the purchase list (esp. when sorted by reliability)
 

	
 
		if (refresh) {
 
			SetWindowClassesDirty(WC_BUILD_VEHICLE);
 
			SetWindowClassesDirty(WC_REPLACE_VEHICLE);
src/engine_func.h
Show inline comments
 
@@ -17,17 +17,18 @@
 
void SetupEngines();
 
void StartupEngines();
 
void CheckEngines();
 

	
 
/* Original engine data counts and offsets */
 
extern const uint8 _engine_counts[4];
 
extern const uint8 _engine_offsets[4];
 

	
 
bool IsEngineBuildable(EngineID engine, VehicleType type, CompanyID company);
 
bool IsEngineRefittable(EngineID engine);
 
void GetArticulatedVehicleCargoesAndRefits(EngineID engine, CargoArray *cargoes, CargoTypes *refits, CargoID cargo_type, uint cargo_capacity);
 
void SetYearEngineAgingStops();
 
void CalcEngineReliability(Engine *e, bool new_month);
 
void StartupOneEngine(Engine *e, Date aging_date);
 

	
 
uint GetTotalCapacityOfArticulatedParts(EngineID engine);
 

	
 
#endif /* ENGINE_FUNC_H */
src/engine_type.h
Show inline comments
 
@@ -117,44 +117,54 @@ struct RoadVehicleInfo {
 
	SoundID sfx;
 
	uint16 max_speed;        ///< Maximum speed (1 unit = 1/3.2 mph = 0.5 km-ish/h)
 
	byte capacity;
 
	uint8 weight;            ///< Weight in 1/4t units
 
	uint8 power;             ///< Power in 10hp units
 
	uint8 tractive_effort;   ///< Coefficient of tractive effort
 
	uint8 air_drag;          ///< Coefficient of air drag
 
	byte visual_effect;      ///< Bitstuffed NewGRF visual effect data
 
	byte shorten_factor;     ///< length on main map for this type is 8 - shorten_factor
 
	RoadType roadtype;       ///< Road type
 
};
 

	
 
enum class ExtraEngineFlags : uint32 {
 
	None = 0,
 
	NoNews          = (1U << 0), ///< No 'new vehicle' news will be generated.
 
	NoPreview       = (1U << 1), ///< No exclusive preview will be offered.
 
	JoinPreview     = (1U << 2), ///< Engine will join exclusive preview with variant parent.
 
	SyncReliability = (1U << 3), ///< Engine reliability will be synced with variant parent.
 
};
 
DECLARE_ENUM_AS_BIT_SET(ExtraEngineFlags);
 

	
 
/**
 
 * Information about a vehicle
 
 *  @see table/engines.h
 
 */
 
struct EngineInfo {
 
	Date base_intro;    ///< Basic date of engine introduction (without random parts).
 
	Year lifelength;    ///< Lifetime of a single vehicle
 
	Year base_life;     ///< Basic duration of engine availability (without random parts). \c 0xFF means infinite life.
 
	byte decay_speed;
 
	byte load_amount;
 
	byte climates;      ///< Climates supported by the engine.
 
	CargoID cargo_type;
 
	CargoTypes refit_mask;
 
	byte refit_cost;
 
	byte misc_flags;    ///< Miscellaneous flags. @see EngineMiscFlags
 
	byte callback_mask; ///< Bitmask of vehicle callbacks that have to be called
 
	int8 retire_early;  ///< Number of years early to retire vehicle
 
	StringID string_id; ///< Default name of engine
 
	uint16 cargo_age_period; ///< Number of ticks before carried cargo is aged.
 
	EngineID variant_id;     ///< Engine variant ID. If set, will be treated specially in purchase lists.
 
	ExtraEngineFlags extra_flags;
 
};
 

	
 
/**
 
 * EngineInfo.misc_flags is a bitmask, with the following values
 
 */
 
enum EngineMiscFlags {
 
	EF_RAIL_TILTS = 0, ///< Rail vehicle tilts in curves
 
	EF_ROAD_TRAM  = 0, ///< Road vehicle is a tram/light rail vehicle
 
	EF_USES_2CC   = 1, ///< Vehicle uses two company colours
 
	EF_RAIL_IS_MU = 2, ///< Rail vehicle is a multiple-unit (DMU/EMU)
 
	EF_RAIL_FLIPS = 3, ///< Rail vehicle has old depot-flip handling
 
	EF_AUTO_REFIT = 4, ///< Automatic refitting is allowed
src/newgrf.cpp
Show inline comments
 
@@ -1329,24 +1329,28 @@ static ChangeInfoResult RailVehicleChang
 
				}
 
				break;
 
			}
 

	
 
			case PROP_TRAIN_CURVE_SPEED_MOD: // 0x2E Curve speed modifier
 
				rvi->curve_speed_mod = buf->ReadWord();
 
				break;
 

	
 
			case 0x2F: // Engine variant
 
				ei->variant_id = GetNewEngineID(_cur.grffile, VEH_TRAIN, buf->ReadWord());
 
				break;
 

	
 
			case 0x30: // Extra miscellaneous flags
 
				ei->extra_flags = static_cast<ExtraEngineFlags>(buf->ReadDWord());
 
				break;
 

	
 
			default:
 
				ret = CommonVehicleChangeInfo(ei, prop, buf);
 
				break;
 
		}
 
	}
 

	
 
	return ret;
 
}
 

	
 
/**
 
 * Define properties for road vehicles
 
 * @param engine Local ID of the first vehicle.
 
@@ -1527,24 +1531,28 @@ static ChangeInfoResult RoadVehicleChang
 
				while (count--) {
 
					CargoID ctype = GetCargoTranslation(buf->ReadByte(), _cur.grffile);
 
					if (ctype == CT_INVALID) continue;
 
					SetBit(ctt, ctype);
 
				}
 
				break;
 
			}
 

	
 
			case 0x26: // Engine variant
 
				ei->variant_id = GetNewEngineID(_cur.grffile, VEH_ROAD, buf->ReadWord());
 
				break;
 

	
 
			case 0x27: // Extra miscellaneous flags
 
				ei->extra_flags = static_cast<ExtraEngineFlags>(buf->ReadDWord());
 
				break;
 

	
 
			default:
 
				ret = CommonVehicleChangeInfo(ei, prop, buf);
 
				break;
 
		}
 
	}
 

	
 
	return ret;
 
}
 

	
 
/**
 
 * Define properties for ships
 
 * @param engine Local ID of the first vehicle.
 
@@ -1703,24 +1711,28 @@ static ChangeInfoResult ShipVehicleChang
 
				while (count--) {
 
					CargoID ctype = GetCargoTranslation(buf->ReadByte(), _cur.grffile);
 
					if (ctype == CT_INVALID) continue;
 
					SetBit(ctt, ctype);
 
				}
 
				break;
 
			}
 

	
 
			case 0x20: // Engine variant
 
				ei->variant_id = GetNewEngineID(_cur.grffile, VEH_SHIP, buf->ReadWord());
 
				break;
 

	
 
			case 0x21: // Extra miscellaneous flags
 
				ei->extra_flags = static_cast<ExtraEngineFlags>(buf->ReadDWord());
 
				break;
 

	
 
			default:
 
				ret = CommonVehicleChangeInfo(ei, prop, buf);
 
				break;
 
		}
 
	}
 

	
 
	return ret;
 
}
 

	
 
/**
 
 * Define properties for aircraft
 
 * @param engine Local ID of the aircraft.
 
@@ -1861,24 +1873,28 @@ static ChangeInfoResult AircraftVehicleC
 
				}
 
				break;
 
			}
 

	
 
			case PROP_AIRCRAFT_RANGE: // 0x1F Max aircraft range
 
				avi->max_range = buf->ReadWord();
 
				break;
 

	
 
			case 0x20: // Engine variant
 
				ei->variant_id = GetNewEngineID(_cur.grffile, VEH_AIRCRAFT, buf->ReadWord());
 
				break;
 

	
 
			case 0x21: // Extra miscellaneous flags
 
				ei->extra_flags = static_cast<ExtraEngineFlags>(buf->ReadDWord());
 
				break;
 

	
 
			default:
 
				ret = CommonVehicleChangeInfo(ei, prop, buf);
 
				break;
 
		}
 
	}
 

	
 
	return ret;
 
}
 

	
 
/**
 
 * Define properties for stations
 
 * @param stid StationID of the first station tile.
src/saveload/oldloader_sl.cpp
Show inline comments
 
@@ -393,24 +393,25 @@ static bool FixTTOEngines()
 
	for (uint i = 0; i < lengthof(_orig_aircraft_vehicle_info); i++, j++) new (GetTempDataEngine(j)) Engine(VEH_AIRCRAFT, i);
 

	
 
	Date aging_date = std::min(_date + DAYS_TILL_ORIGINAL_BASE_YEAR, ConvertYMDToDate(2050, 0, 1));
 

	
 
	for (EngineID i = 0; i < 256; i++) {
 
		int oi = ttd_to_tto[i];
 
		Engine *e = GetTempDataEngine(i);
 

	
 
		if (oi == 255) {
 
			/* Default engine is used */
 
			_date += DAYS_TILL_ORIGINAL_BASE_YEAR;
 
			StartupOneEngine(e, aging_date);
 
			CalcEngineReliability(e, false);
 
			e->intro_date -= DAYS_TILL_ORIGINAL_BASE_YEAR;
 
			_date -= DAYS_TILL_ORIGINAL_BASE_YEAR;
 

	
 
			/* Make sure for example monorail and maglev are available when they should be */
 
			if (_date >= e->intro_date && HasBit(e->info.climates, 0)) {
 
				e->flags |= ENGINE_AVAILABLE;
 
				e->company_avail = (CompanyMask)0xFF;
 
				e->age = _date > e->intro_date ? (_date - e->intro_date) / 30 : 0;
 
			}
 
		} else {
 
			/* Using data from TTO savegame */
 
			Engine *oe = &_old_engines[oi];
src/table/engines.h
Show inline comments
 
@@ -15,87 +15,87 @@
 

	
 
/**
 
 * Writes the properties of a train into the EngineInfo struct.
 
 * @see EngineInfo
 
 * @param a base introduction date (days since 1920-01-01)
 
 * @param b decay speed
 
 * @param c life length (years)
 
 * @param d base life (years)
 
 * @param e cargo type
 
 * @param f Bitmask of the climates
 
 * @note the 5 between b and f is the load amount
 
 */
 
#define MT(a, b, c, d, e, f) { DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, f, e, 0, 8, 0, 0, 0, STR_EMPTY, CARGO_AGING_TICKS, INVALID_ENGINE }
 
#define MT(a, b, c, d, e, f) { DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, f, e, 0, 8, 0, 0, 0, STR_EMPTY, CARGO_AGING_TICKS, INVALID_ENGINE, ExtraEngineFlags::None }
 

	
 
/**
 
 * Writes the properties of a multiple-unit train into the EngineInfo struct.
 
 * @see EngineInfo
 
 * @param a base introduction date (days since 1920-01-01)
 
 * @param b decay speed
 
 * @param c life length (years)
 
 * @param d base life (years)
 
 * @param e cargo type
 
 * @param f Bitmask of the climates
 
 * @note the 5 between b and f is the load amount
 
 */
 
#define MM(a, b, c, d, e, f) { DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, f, e, 0, 8, 1 << EF_RAIL_IS_MU, 0, 0, STR_EMPTY, CARGO_AGING_TICKS, INVALID_ENGINE }
 
#define MM(a, b, c, d, e, f) { DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, f, e, 0, 8, 1 << EF_RAIL_IS_MU, 0, 0, STR_EMPTY, CARGO_AGING_TICKS, INVALID_ENGINE, ExtraEngineFlags::None }
 

	
 
/**
 
 * Writes the properties of a train carriage into the EngineInfo struct.
 
 * @param a base introduction date (days since 1920-01-01)
 
 * @param b decay speed
 
 * @param c life length (years)
 
 * @param d base life (years)
 
 * @param e cargo type
 
 * @param f Bitmask of the climates
 
 * @see MT
 
 * @note the 5 between b and f is the load amount
 
 */
 
#define MW(a, b, c, d, e, f) { DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, f, e, 0, 8, 0, 0, 0, STR_EMPTY, CARGO_AGING_TICKS, INVALID_ENGINE }
 
#define MW(a, b, c, d, e, f) { DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, f, e, 0, 8, 0, 0, 0, STR_EMPTY, CARGO_AGING_TICKS, INVALID_ENGINE, ExtraEngineFlags::None }
 

	
 
/**
 
 * Writes the properties of a road vehicle into the EngineInfo struct.
 
 * @see EngineInfo
 
 * @param a base introduction date (days since 1920-01-01)
 
 * @param b decay speed
 
 * @param c life length (years)
 
 * @param d base life (years)
 
 * @param e cargo type
 
 * @param f Bitmask of the climates
 
 * @note the 5 between b and f is the load amount
 
 */
 
#define MR(a, b, c, d, e, f) { DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, f, e, 0, 8, 0, 0, 0, STR_EMPTY, CARGO_AGING_TICKS, INVALID_ENGINE }
 
#define MR(a, b, c, d, e, f) { DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, f, e, 0, 8, 0, 0, 0, STR_EMPTY, CARGO_AGING_TICKS, INVALID_ENGINE, ExtraEngineFlags::None }
 

	
 
/**
 
 * Writes the properties of a ship into the EngineInfo struct.
 
 * @param a base introduction date (days since 1920-01-01)
 
 * @param b decay speed
 
 * @param c life length (years)
 
 * @param d base life (years)
 
 * @param e cargo type
 
 * @param f Bitmask of the climates
 
 * @note the 10 between b and f is the load amount
 
 */
 
#define MS(a, b, c, d, e, f) { DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 10, f, e, 0, 8, 0, 0, 0, STR_EMPTY, CARGO_AGING_TICKS, INVALID_ENGINE }
 
#define MS(a, b, c, d, e, f) { DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 10, f, e, 0, 8, 0, 0, 0, STR_EMPTY, CARGO_AGING_TICKS, INVALID_ENGINE, ExtraEngineFlags::None }
 

	
 
/**
 
 * Writes the properties of an aeroplane into the EngineInfo struct.
 
 * @param a base introduction date (days since 1920-01-01)
 
 * @param b decay speed
 
 * @param c life length (years)
 
 * @param d base life (years)
 
 * @param e Bitmask of the climates
 
 * @note the 20 between b and e is the load amount
 
 */
 
#define MA(a, b, c, d, e) { DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 20, e, CT_INVALID, 0, 8, 0, 0, 0, STR_EMPTY, CARGO_AGING_TICKS, INVALID_ENGINE }
 
#define MA(a, b, c, d, e) { DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 20, e, CT_INVALID, 0, 8, 0, 0, 0, STR_EMPTY, CARGO_AGING_TICKS, INVALID_ENGINE, ExtraEngineFlags::None }
 

	
 
/* Climates
 
 * T = Temperate
 
 * A = Sub-Arctic
 
 * S = Sub-Tropic
 
 * Y = Toyland */
 
#define T 1
 
#define A 2
 
#define S 4
 
#define Y 8
 
static const EngineInfo _orig_engine_info[] = {
 
	/*      base_intro     base_life
0 comments (0 inline, 0 general)