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
 
@@ -575,15 +575,22 @@ static void ClearLastVariant(EngineID en
 
}
 

	
 
/**
 
 * 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) {
 
@@ -668,27 +675,36 @@ void StartupOneEngine(Engine *e, Date ag
 
	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;
 
	}
 
@@ -703,12 +719,15 @@ 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);
 
	}
 
@@ -772,14 +791,15 @@ static void DisableEngineForCompany(Engi
 
}
 

	
 
/**
 
 * 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;
 

	
 
@@ -788,12 +808,22 @@ static void AcceptEnginePreview(EngineID
 
	/* 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.
 
@@ -1011,13 +1041,13 @@ static void NewVehicleAvailable(Engine *
 
	}
 

	
 
	/* 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. */
 
@@ -1035,13 +1065,13 @@ 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;
 

	
 
@@ -1055,12 +1085,15 @@ void EnginesMonthlyLoop()
 
				 * 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;
 
			}
 
		}
src/engine_func.h
Show inline comments
 
@@ -23,11 +23,12 @@ 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
 
@@ -123,12 +123,21 @@ struct RoadVehicleInfo {
 
	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).
 
@@ -143,12 +152,13 @@ struct EngineInfo {
 
	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 {
src/newgrf.cpp
Show inline comments
 
@@ -1335,12 +1335,16 @@ static ChangeInfoResult RailVehicleChang
 
				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;
 
		}
 
	}
 

	
 
@@ -1533,12 +1537,16 @@ static ChangeInfoResult RoadVehicleChang
 
			}
 

	
 
			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;
 
		}
 
	}
 

	
 
@@ -1709,12 +1717,16 @@ static ChangeInfoResult ShipVehicleChang
 
			}
 

	
 
			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;
 
		}
 
	}
 

	
 
@@ -1867,12 +1879,16 @@ static ChangeInfoResult AircraftVehicleC
 
				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;
 
		}
 
	}
 

	
src/saveload/oldloader_sl.cpp
Show inline comments
 
@@ -399,12 +399,13 @@ static bool FixTTOEngines()
 
		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;
src/table/engines.h
Show inline comments
 
@@ -21,75 +21,75 @@
 
 * @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 */
0 comments (0 inline, 0 general)