(svn r24810) -Fix: Make engine preview offers more robust wrt. changes in the company ranking.
This commit is contained in:
		@@ -740,7 +740,8 @@ static void AcceptEnginePreview(EngineID eid, CompanyID company)
 | 
			
		||||
		SetBit(c->avail_roadtypes, HasBit(e->info.misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	e->preview_company_rank = 0xFF;
 | 
			
		||||
	e->preview_company = INVALID_COMPANY;
 | 
			
		||||
	e->preview_asked = (CompanyMask)-1;
 | 
			
		||||
	if (company == _local_company) {
 | 
			
		||||
		AddRemoveEngineFromAutoreplaceAndBuildWindows(e->type);
 | 
			
		||||
	}
 | 
			
		||||
@@ -751,32 +752,23 @@ static void AcceptEnginePreview(EngineID eid, CompanyID company)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Get the N-th best company.
 | 
			
		||||
 * @param pp Value N, 1 means best, 2 means second best, etc.
 | 
			
		||||
 * @return N-th best company if it exists, #INVALID_COMPANY otherwise.
 | 
			
		||||
 * Get the best company for an engine preview.
 | 
			
		||||
 * @param e Engine to preview.
 | 
			
		||||
 * @return Best company if it exists, #INVALID_COMPANY otherwise.
 | 
			
		||||
 */
 | 
			
		||||
static CompanyID GetBestCompany(uint8 pp)
 | 
			
		||||
static CompanyID GetPreviewCompany(Engine *e)
 | 
			
		||||
{
 | 
			
		||||
	CompanyID best_company;
 | 
			
		||||
	CompanyMask mask = 0;
 | 
			
		||||
	CompanyID best_company = INVALID_COMPANY;
 | 
			
		||||
 | 
			
		||||
	do {
 | 
			
		||||
		int32 best_hist = -1;
 | 
			
		||||
		best_company = INVALID_COMPANY;
 | 
			
		||||
 | 
			
		||||
		const Company *c;
 | 
			
		||||
		FOR_ALL_COMPANIES(c) {
 | 
			
		||||
			if (c->block_preview == 0 && !HasBit(mask, c->index) &&
 | 
			
		||||
					c->old_economy[0].performance_history > best_hist) {
 | 
			
		||||
				best_hist = c->old_economy[0].performance_history;
 | 
			
		||||
				best_company = c->index;
 | 
			
		||||
			}
 | 
			
		||||
	int32 best_hist = -1;
 | 
			
		||||
	const Company *c;
 | 
			
		||||
	FOR_ALL_COMPANIES(c) {
 | 
			
		||||
		if (c->block_preview == 0 && !HasBit(e->preview_asked, c->index) &&
 | 
			
		||||
				c->old_economy[0].performance_history > best_hist) {
 | 
			
		||||
			best_hist = c->old_economy[0].performance_history;
 | 
			
		||||
			best_company = c->index;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (best_company == INVALID_COMPANY) return INVALID_COMPANY;
 | 
			
		||||
 | 
			
		||||
		SetBit(mask, best_company);
 | 
			
		||||
	} while (--pp != 0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return best_company;
 | 
			
		||||
}
 | 
			
		||||
@@ -811,29 +803,28 @@ void EnginesDailyLoop()
 | 
			
		||||
	FOR_ALL_ENGINES(e) {
 | 
			
		||||
		EngineID i = e->index;
 | 
			
		||||
		if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) {
 | 
			
		||||
			if (e->flags & ENGINE_OFFER_WINDOW_OPEN) {
 | 
			
		||||
				if (e->preview_company_rank != 0xFF && !--e->preview_wait) {
 | 
			
		||||
					e->flags &= ~ENGINE_OFFER_WINDOW_OPEN;
 | 
			
		||||
			if (e->preview_company != INVALID_COMPANY) {
 | 
			
		||||
				if (!--e->preview_wait) {
 | 
			
		||||
					DeleteWindowById(WC_ENGINE_PREVIEW, i);
 | 
			
		||||
					e->preview_company_rank++;
 | 
			
		||||
					e->preview_company = INVALID_COMPANY;
 | 
			
		||||
				}
 | 
			
		||||
			} else if (e->preview_company_rank != 0xFF) {
 | 
			
		||||
				CompanyID best_company = GetBestCompany(e->preview_company_rank);
 | 
			
		||||
			} else if (CountBits(e->preview_asked) < MAX_COMPANIES) {
 | 
			
		||||
				e->preview_company = GetPreviewCompany(e);
 | 
			
		||||
 | 
			
		||||
				if (best_company == INVALID_COMPANY) {
 | 
			
		||||
					e->preview_company_rank = 0xFF;
 | 
			
		||||
				if (e->preview_company == INVALID_COMPANY) {
 | 
			
		||||
					e->preview_asked = (CompanyMask)-1;
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				e->flags |= ENGINE_OFFER_WINDOW_OPEN;
 | 
			
		||||
				SetBit(e->preview_asked, e->preview_company);
 | 
			
		||||
				e->preview_wait = 20;
 | 
			
		||||
				/* AIs are intentionally not skipped for preview even if they cannot build a certain
 | 
			
		||||
				 * vehicle type. This is done to not give poor performing human companies an "unfair"
 | 
			
		||||
				 * boost that they wouldn't have gotten against other human companies. The check on
 | 
			
		||||
				 * the line below is just to make AIs not notice that they have a preview if they
 | 
			
		||||
				 * cannot build the vehicle. */
 | 
			
		||||
				if (!IsVehicleTypeDisabled(e->type, true)) AI::NewEvent(best_company, new ScriptEventEnginePreview(i));
 | 
			
		||||
				if (IsInteractiveCompany(best_company)) ShowEnginePreviewWindow(i);
 | 
			
		||||
				if (!IsVehicleTypeDisabled(e->type, true)) AI::NewEvent(e->preview_company, new ScriptEventEnginePreview(i));
 | 
			
		||||
				if (IsInteractiveCompany(e->preview_company)) ShowEnginePreviewWindow(i);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -852,7 +843,7 @@ void EnginesDailyLoop()
 | 
			
		||||
CommandCost CmdWantEnginePreview(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 | 
			
		||||
{
 | 
			
		||||
	Engine *e = Engine::GetIfValid(p1);
 | 
			
		||||
	if (e == NULL || GetBestCompany(e->preview_company_rank) != _current_company) return CMD_ERROR;
 | 
			
		||||
	if (e == NULL || e->preview_company != _current_company) return CMD_ERROR;
 | 
			
		||||
 | 
			
		||||
	if (flags & DC_EXEC) AcceptEnginePreview(p1, _current_company);
 | 
			
		||||
 | 
			
		||||
@@ -953,13 +944,13 @@ 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;
 | 
			
		||||
 | 
			
		||||
				/* Show preview dialog to one of the companies. */
 | 
			
		||||
				e->flags |= ENGINE_EXCLUSIVE_PREVIEW;
 | 
			
		||||
 | 
			
		||||
				/* Do not introduce new rail wagons */
 | 
			
		||||
				if (!IsWagon(e->index)) {
 | 
			
		||||
					e->preview_company_rank = 1; // Give to the company with the highest rating.
 | 
			
		||||
				}
 | 
			
		||||
				e->preview_company = INVALID_COMPANY;
 | 
			
		||||
				e->preview_asked = 0;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -33,8 +33,9 @@ struct Engine : EnginePool::PoolItem<&_engine_pool> {
 | 
			
		||||
	uint16 duration_phase_2;    ///< Second reliability phase in months, keeping #reliability_max.
 | 
			
		||||
	uint16 duration_phase_3;    ///< Third reliability phase on months, decaying to #reliability_final.
 | 
			
		||||
	byte flags;                 ///< Flags of the engine. @see EngineFlags
 | 
			
		||||
	uint8 preview_company_rank; ///< Rank of the company that is offered a preview. \c 0xFF means no company.
 | 
			
		||||
	byte preview_wait;          ///< Daily countdown timer for timeout of offering the engine to the #preview_company_rank company.
 | 
			
		||||
	CompanyMask preview_asked;  ///< Bit for each company which has already been offered a preview.
 | 
			
		||||
	CompanyByte preview_company;///< Company which is currently being offered a preview \c INVALID_COMPANY means no company.
 | 
			
		||||
	byte preview_wait;          ///< Daily countdown timer for timeout of offering the engine to the #preview_company company.
 | 
			
		||||
	CompanyMask company_avail;  ///< Bit for each company whether the engine is available for that company.
 | 
			
		||||
	uint8 original_image_index; ///< Original vehicle image index, thus the image index of the overridden vehicle
 | 
			
		||||
	VehicleType type;           ///< %Vehicle type, ie #VEH_ROAD, #VEH_TRAIN, etc.
 | 
			
		||||
 
 | 
			
		||||
@@ -166,7 +166,6 @@ enum EngineMiscFlags {
 | 
			
		||||
enum EngineFlags {
 | 
			
		||||
	ENGINE_AVAILABLE         = 1, ///< This vehicle is available to everyone.
 | 
			
		||||
	ENGINE_EXCLUSIVE_PREVIEW = 2, ///< This vehicle is in the exclusive preview stage, either being used or being offered to a company.
 | 
			
		||||
	ENGINE_OFFER_WINDOW_OPEN = 4, ///< The exclusive offer window is currently open for a company.
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const uint MAX_LENGTH_ENGINE_NAME_CHARS = 32; ///< The maximum length of an engine name in characters including '\0'
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,9 @@ static const SaveLoad _engine_desc[] = {
 | 
			
		||||
 | 
			
		||||
	SLE_CONDNULL(1,                                                        0, 120),
 | 
			
		||||
	     SLE_VAR(Engine, flags,               SLE_UINT8),
 | 
			
		||||
	     SLE_VAR(Engine, preview_company_rank,SLE_UINT8),
 | 
			
		||||
	SLE_CONDNULL(1,                                                        0, 178), // old preview_company_rank
 | 
			
		||||
	 SLE_CONDVAR(Engine, preview_asked,       SLE_UINT16,                179, SL_MAX_VERSION),
 | 
			
		||||
	 SLE_CONDVAR(Engine, preview_company,     SLE_UINT8,                 179, SL_MAX_VERSION),
 | 
			
		||||
	     SLE_VAR(Engine, preview_wait,        SLE_UINT8),
 | 
			
		||||
	SLE_CONDNULL(1,                                                        0,  44),
 | 
			
		||||
	 SLE_CONDVAR(Engine, company_avail,       SLE_FILE_U8  | SLE_VAR_U16,  0, 103),
 | 
			
		||||
@@ -67,6 +69,14 @@ static void Load_ENGN()
 | 
			
		||||
	while ((index = SlIterateArray()) != -1) {
 | 
			
		||||
		Engine *e = GetTempDataEngine(index);
 | 
			
		||||
		SlObject(e, _engine_desc);
 | 
			
		||||
 | 
			
		||||
		if (IsSavegameVersionBefore(179)) {
 | 
			
		||||
			/* preview_company_rank was replaced with preview_company and preview_asked.
 | 
			
		||||
			 * Just cancel any previews. */
 | 
			
		||||
			e->flags &= ~4; // ENGINE_OFFER_WINDOW_OPEN
 | 
			
		||||
			e->preview_company = INVALID_COMPANY;
 | 
			
		||||
			e->preview_asked = (CompanyMask)-1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -91,7 +101,8 @@ void CopyTempEngineData()
 | 
			
		||||
		e->duration_phase_2    = se->duration_phase_2;
 | 
			
		||||
		e->duration_phase_3    = se->duration_phase_3;
 | 
			
		||||
		e->flags               = se->flags;
 | 
			
		||||
		e->preview_company_rank= se->preview_company_rank;
 | 
			
		||||
		e->preview_asked       = se->preview_asked;
 | 
			
		||||
		e->preview_company     = se->preview_company;
 | 
			
		||||
		e->preview_wait        = se->preview_wait;
 | 
			
		||||
		e->company_avail       = se->company_avail;
 | 
			
		||||
		if (se->name != NULL) e->name = strdup(se->name);
 | 
			
		||||
 
 | 
			
		||||
@@ -445,7 +445,8 @@ static bool FixTTOEngines()
 | 
			
		||||
			e->info.climates = 1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		e->preview_company_rank = 0;
 | 
			
		||||
		e->preview_company = INVALID_COMPANY;
 | 
			
		||||
		e->preview_asked = (CompanyMask)-1;
 | 
			
		||||
		e->preview_wait = 0;
 | 
			
		||||
		e->name = NULL;
 | 
			
		||||
	}
 | 
			
		||||
@@ -1401,7 +1402,7 @@ static const OldChunks engine_chunk[] = {
 | 
			
		||||
 | 
			
		||||
	OCL_NULL( 1 ), // lifelength
 | 
			
		||||
	OCL_SVAR(  OC_UINT8, Engine, flags ),
 | 
			
		||||
	OCL_SVAR(  OC_UINT8, Engine, preview_company_rank ),
 | 
			
		||||
	OCL_NULL( 1 ), // preview_company_rank
 | 
			
		||||
	OCL_SVAR(  OC_UINT8, Engine, preview_wait ),
 | 
			
		||||
 | 
			
		||||
	OCL_CNULL( OC_TTD, 2 ), ///< railtype + junk
 | 
			
		||||
 
 | 
			
		||||
@@ -242,8 +242,9 @@
 | 
			
		||||
 *  176   24446
 | 
			
		||||
 *  177   24619
 | 
			
		||||
 *  178   24789
 | 
			
		||||
 *  179   24810
 | 
			
		||||
 */
 | 
			
		||||
extern const uint16 SAVEGAME_VERSION = 178; ///< Current savegame version of OpenTTD.
 | 
			
		||||
extern const uint16 SAVEGAME_VERSION = 179; ///< Current savegame version of OpenTTD.
 | 
			
		||||
 | 
			
		||||
SavegameType _savegame_type; ///< type of savegame we are loading
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user