File diff r23952:2d92a4a7c152 → r23953:ba75d2f3b530
src/engine.cpp
Show inline comments
 
@@ -682,50 +682,49 @@ void StartupOneEngine(Engine *e, Date ag
 
	CalcEngineReliability(e);
 

	
 
	/* 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()
 
{
 
	Engine *e;
 
	/* Aging of vehicles stops, so account for that when starting late */
 
	const Date aging_date = min(_date, ConvertYMDToDate(_year_engine_aging_stops, 0, 1));
 

	
 
	FOR_ALL_ENGINES(e) {
 
		StartupOneEngine(e, aging_date);
 
	}
 

	
 
	/* Update the bitmasks for the vehicle lists */
 
	Company *c;
 
	FOR_ALL_COMPANIES(c) {
 
	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);
 
}
 

	
 
/**
 
 * Company \a company accepts engine \a eid for preview.
 
 * @param eid Engine being accepted (is under preview).
 
 * @param company Current company previewing the engine.
 
 */
 
static void AcceptEnginePreview(EngineID eid, CompanyID company)
 
{
 
	Engine *e = Engine::Get(eid);
 
	Company *c = Company::Get(company);
 

	
 
	SetBit(e->company_avail, company);
 
	if (e->type == VEH_TRAIN) {
 
		assert(e->u.rail.railtype < RAILTYPE_END);
 
		c->avail_railtypes = AddDateIntroducedRailTypes(c->avail_railtypes | GetRailTypeInfo(e->u.rail.railtype)->introduces_railtypes, _date);
 
	} else if (e->type == VEH_ROAD) {
 
		assert(e->u.road.roadtype < ROADTYPE_END);
 
@@ -742,93 +741,91 @@ static void AcceptEnginePreview(EngineID
 
	if (e->type == VEH_ROAD) InvalidateWindowData(WC_BUILD_TOOLBAR, TRANSPORT_ROAD);
 
	if (e->type == VEH_SHIP) InvalidateWindowData(WC_BUILD_TOOLBAR, TRANSPORT_WATER);
 

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

	
 
/**
 
 * 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 */
 
	CargoTypes cargomask = e->type != VEH_TRAIN ? GetUnionOfArticulatedRefitMasks(e->index, true) : ALL_CARGOTYPES;
 

	
 
	int32 best_hist = -1;
 
	const Company *c;
 
	FOR_ALL_COMPANIES(c) {
 
	for (const Company *c : Company::Iterate()) {
 
		if (c->block_preview == 0 && !HasBit(e->preview_asked, c->index) &&
 
				c->old_economy[0].performance_history > best_hist) {
 

	
 
			/* Check whether the company uses similar vehicles */
 
			Vehicle *v;
 
			FOR_ALL_VEHICLES(v) {
 
				if (v->owner != c->index || v->type != e->type) continue;
 
				if (!v->GetEngine()->CanCarryCargo() || !HasBit(cargomask, v->cargo_type)) continue;
 

	
 
				best_hist = c->old_economy[0].performance_history;
 
				best_company = c->index;
 
				break;
 
			}
 
		}
 
	}
 

	
 
	return best_company;
 
}
 

	
 
/**
 
 * Checks if a vehicle type is disabled for all/ai companies.
 
 * @param type The vehicle type which shall be checked.
 
 * @param ai If true, check if the type is disabled for AI companies, otherwise check if
 
 *           the vehicle type is disabled for human companies.
 
 * @return Whether or not a vehicle type is disabled.
 
 */
 
static bool IsVehicleTypeDisabled(VehicleType type, bool ai)
 
{
 
	switch (type) {
 
		case VEH_TRAIN:    return _settings_game.vehicle.max_trains == 0   || (ai && _settings_game.ai.ai_disable_veh_train);
 
		case VEH_ROAD:     return _settings_game.vehicle.max_roadveh == 0  || (ai && _settings_game.ai.ai_disable_veh_roadveh);
 
		case VEH_SHIP:     return _settings_game.vehicle.max_ships == 0    || (ai && _settings_game.ai.ai_disable_veh_ship);
 
		case VEH_AIRCRAFT: return _settings_game.vehicle.max_aircraft == 0 || (ai && _settings_game.ai.ai_disable_veh_aircraft);
 

	
 
		default: NOT_REACHED();
 
	}
 
}
 

	
 
/** Daily check to offer an exclusive engine preview to the companies. */
 
void EnginesDailyLoop()
 
{
 
	Company *c;
 
	FOR_ALL_COMPANIES(c) {
 
	for (Company *c : Company::Iterate()) {
 
		c->avail_railtypes = AddDateIntroducedRailTypes(c->avail_railtypes, _date);
 
		c->avail_roadtypes = AddDateIntroducedRoadTypes(c->avail_roadtypes, _date);
 
	}
 

	
 
	if (_cur_year >= _year_engine_aging_stops) return;
 

	
 
	Engine *e;
 
	FOR_ALL_ENGINES(e) {
 
		EngineID i = e->index;
 
		if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) {
 
			if (e->preview_company != INVALID_COMPANY) {
 
				if (!--e->preview_wait) {
 
					DeleteWindowById(WC_ENGINE_PREVIEW, i);
 
					e->preview_company = INVALID_COMPANY;
 
				}
 
			} else if (CountBits(e->preview_asked) < MAX_COMPANIES) {
 
				e->preview_company = GetPreviewCompany(e);
 

	
 
				if (e->preview_company == INVALID_COMPANY) {
 
					e->preview_asked = (CompanyMask)-1;
 
					continue;
 
				}
 

	
 
				SetBit(e->preview_asked, e->preview_company);
 
@@ -887,93 +884,92 @@ CommandCost CmdSetVehicleVisibility(Tile
 
 * @param flags operation to perform
 
 * @param p1 engine-prototype offered
 
 * @param p2 unused
 
 * @param text unused
 
 * @return the cost of this operation or an error
 
 */
 
CommandCost CmdWantEnginePreview(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 
{
 
	Engine *e = Engine::GetIfValid(p1);
 
	if (e == nullptr || !(e->flags & ENGINE_EXCLUSIVE_PREVIEW) || e->preview_company != _current_company) return CMD_ERROR;
 

	
 
	if (flags & DC_EXEC) AcceptEnginePreview(p1, _current_company);
 

	
 
	return CommandCost();
 
}
 

	
 
/**
 
 * An engine has become available for general use.
 
 * Also handle the exclusive engine preview contract.
 
 * @param e Engine generally available as of now.
 
 */
 
static void NewVehicleAvailable(Engine *e)
 
{
 
	Vehicle *v;
 
	Company *c;
 
	EngineID index = e->index;
 

	
 
	/* In case the company didn't build the vehicle during the intro period,
 
	 * prevent that company from getting future intro periods for a while. */
 
	if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) {
 
		FOR_ALL_COMPANIES(c) {
 
		for (Company *c : Company::Iterate()) {
 
			uint block_preview = c->block_preview;
 

	
 
			if (!HasBit(e->company_avail, c->index)) continue;
 

	
 
			/* We assume the user did NOT build it.. prove me wrong ;) */
 
			c->block_preview = 20;
 

	
 
			FOR_ALL_VEHICLES(v) {
 
				if (v->type == VEH_TRAIN || v->type == VEH_ROAD || v->type == VEH_SHIP ||
 
						(v->type == VEH_AIRCRAFT && Aircraft::From(v)->IsNormalAircraft())) {
 
					if (v->owner == c->index && v->engine_type == index) {
 
						/* The user did prove me wrong, so restore old value */
 
						c->block_preview = block_preview;
 
						break;
 
					}
 
				}
 
			}
 
		}
 
	}
 

	
 
	e->flags = (e->flags & ~ENGINE_EXCLUSIVE_PREVIEW) | ENGINE_AVAILABLE;
 
	AddRemoveEngineFromAutoreplaceAndBuildWindows(e->type);
 

	
 
	/* Now available for all companies */
 
	e->company_avail = (CompanyMask)-1;
 

	
 
	/* Do not introduce new rail wagons */
 
	if (IsWagon(index)) return;
 

	
 
	if (e->type == VEH_TRAIN) {
 
		/* maybe make another rail type available */
 
		RailType railtype = e->u.rail.railtype;
 
		assert(railtype < RAILTYPE_END);
 
		FOR_ALL_COMPANIES(c) c->avail_railtypes = AddDateIntroducedRailTypes(c->avail_railtypes | GetRailTypeInfo(e->u.rail.railtype)->introduces_railtypes, _date);
 
		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_ALL_COMPANIES(c) c->avail_roadtypes = AddDateIntroducedRoadTypes(c->avail_roadtypes | GetRoadTypeInfo(e->u.road.roadtype)->introduces_roadtypes, _date);
 
		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)) {
 
		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);
 

	
 
	/* Close pending preview windows */
 
	DeleteWindowById(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) {