File diff r2847:8df2aeef9e0e → r2848:ae67043fa1f1
engine.c
Show inline comments
 
@@ -1051,6 +1051,195 @@ int32 CmdRenameEngine(int x, int y, uint
 
}
 

	
 

	
 
/*
 
 * returns true if an engine is valid, of the specified type, and buildable by
 
 * the current player, false otherwise
 
 *
 
 * engine = index of the engine to check
 
 * type   = the type the engine should be of (VEH_xxx)
 
 */
 
bool IsEngineBuildable(uint engine, byte type)
 
{
 
	const Engine *e;
 

	
 
	// check if it's an engine that is in the engine array
 
	if (!IsEngineIndex(engine)) return false;
 

	
 
	e = GetEngine(engine);
 

	
 
	// check if it's an engine of specified type
 
	if (e->type != type) return false;
 

	
 
	// check if it's available
 
	if (!HASBIT(e->player_avail, _current_player)) return false;
 

	
 
	return true;
 
}
 

	
 
/************************************************************************
 
 * Engine Replacement stuff
 
 ************************************************************************/
 

	
 
static void EngineRenewPoolNewBlock(uint start_item); /* Forward declare for initializer of _engine_renew_pool */
 
enum {
 
	ENGINE_RENEW_POOL_BLOCK_SIZE_BITS = 3,
 
	ENGINE_RENEW_POOL_MAX_BLOCKS      = 8000,
 
};
 

	
 
MemoryPool _engine_renew_pool = { "EngineRe", ENGINE_RENEW_POOL_MAX_BLOCKS, ENGINE_RENEW_POOL_BLOCK_SIZE_BITS, sizeof(EngineRenew), &EngineRenewPoolNewBlock, 0, 0, NULL };
 

	
 
static inline uint16 GetEngineRenewPoolSize(void)
 
{
 
	return _engine_renew_pool.total_items;
 
}
 

	
 
#define FOR_ALL_ENGINE_RENEWS_FROM(er, start) for (er = GetEngineRenew(start); er != NULL; er = (er->index + 1 < GetEngineRenewPoolSize()) ? GetEngineRenew(er->index + 1) : NULL)
 
#define FOR_ALL_ENGINE_RENEWS(er) FOR_ALL_ENGINE_RENEWS_FROM(er, 0)
 

	
 
static void EngineRenewPoolNewBlock(uint start_item)
 
{
 
	EngineRenew *er;
 

	
 
	FOR_ALL_ENGINE_RENEWS_FROM(er, start_item) {
 
		er->index = start_item++;
 
		er->from = INVALID_ENGINE;
 
	}
 
}
 

	
 

	
 
static EngineRenew *AllocateEngineRenew(void)
 
{
 
	EngineRenew *er;
 

	
 
	FOR_ALL_ENGINE_RENEWS(er) {
 
		if (er->from == INVALID_ENGINE) {
 
			er->to = INVALID_ENGINE;
 
			er->next = NULL;
 
			return er;
 
		}
 
	}
 

	
 
	/* Check if we can add a block to the pool */
 
	if (AddBlockToPool(&_engine_renew_pool)) return AllocateEngineRenew();
 

	
 
	return NULL;
 
}
 

	
 
/**
 
 * Retrieves the EngineRenew that specifies the replacement of the given
 
 * engine type from the given renewlist */
 
static EngineRenew *GetEngineReplacement(EngineRenewList erl, EngineID engine)
 
{
 
	EngineRenew* er = (EngineRenew*)erl; /* Fetch first element */
 
	while (er) {
 
		if (er->from == engine) return er;
 
		er = er->next;
 
	}
 
	return NULL;
 
}
 

	
 
void RemoveAllEngineReplacement(EngineRenewList* erl)
 
{
 
	EngineRenew* er = (EngineRenew*)(*erl); /* Fetch first element */
 
	while (er) {
 
		er->from = INVALID_ENGINE; /* "Deallocate" all elements */
 
		er = er->next;
 
	}
 
	*erl = NULL; /* Empty list */
 
}
 

	
 
EngineID EngineReplacement(EngineRenewList erl, EngineID engine)
 
{
 
	const EngineRenew *er = GetEngineReplacement(erl, engine);
 
	return er == NULL ? INVALID_ENGINE : er->to;
 
}
 

	
 
int32 AddEngineReplacement(EngineRenewList* erl, EngineID old_engine, EngineID new_engine, uint32 flags)
 
{
 
	EngineRenew *er;
 

	
 
	// Check if the old vehicle is already in the list
 
	er = GetEngineReplacement(*erl, old_engine);
 
	if (er != NULL) {
 
		if (flags & DC_EXEC) er->to = new_engine;
 
		return 0;
 
	}
 

	
 
	er = AllocateEngineRenew();
 
	if (er == NULL) return CMD_ERROR;
 

	
 
	if (flags & DC_EXEC) {
 
		er->from = old_engine;
 
		er->to = new_engine;
 
		er->next = (EngineRenew*)(*erl); /* Resolve the first element in the list */
 

	
 
		*erl = (EngineRenewList)er; /* Insert before the first element */
 
	}
 

	
 
	return 0;
 
}
 

	
 
int32 RemoveEngineReplacement(EngineRenewList* erl, EngineID engine, uint32 flags)
 
{
 
	EngineRenew* er = (EngineRenew*)(*erl); /* Start at the first element */
 
	EngineRenew* prev = NULL;
 

	
 
	while (er)
 
	{
 
		if (er->from == engine) {
 
			if (flags & DC_EXEC) {
 
				if (prev == NULL) { /* First element */
 
					(*erl) = (EngineRenewList)er->next; /* The second becomes the new first element */
 
				} else {
 
					prev->next = er->next; /* Cut this element out */
 
				}
 
				er->from = INVALID_ENGINE; /* Deallocate */
 
			}
 
			return 0;
 
		}
 
		prev = er;
 
		er = er->next; /* Look at next element */
 
	}
 

	
 
	return CMD_ERROR; /* Not found? */
 
}
 

	
 
static const SaveLoad _engine_renew_desc[] = {
 
	SLE_VAR(EngineRenew, from, SLE_UINT16),
 
	SLE_VAR(EngineRenew, to,   SLE_UINT16),
 

	
 
	SLE_REF(EngineRenew, next, REF_ENGINE_RENEWS),
 

	
 
	SLE_END()
 
};
 

	
 
static void Save_ERNW(void)
 
{
 
	EngineRenew *er;
 

	
 
	FOR_ALL_ENGINE_RENEWS(er) {
 
		if (er->from != INVALID_ENGINE) {
 
			SlSetArrayIndex(er->index);
 
			SlObject(er, _engine_renew_desc);
 
		}
 
	}
 
}
 

	
 
static void Load_ERNW(void)
 
{
 
	int index;
 

	
 
	while ((index = SlIterateArray()) != -1) {
 
		EngineRenew *er;
 

	
 
		if (!AddBlockIfNeeded(&_engine_renew_pool, index))
 
			error("EngineRenews: failed loading savegame: too many EngineRenews");
 

	
 
		er = GetEngineRenew(index);
 
		SlObject(er, _engine_renew_desc);
 
	}
 
}
 

	
 
static const SaveLoad _engine_desc[] = {
 
	SLE_VAR(Engine,intro_date,						SLE_UINT16),
 
	SLE_VAR(Engine,age,										SLE_UINT16),
 
@@ -1100,32 +1289,14 @@ static void LoadSave_ENGS(void)
 
}
 

	
 
const ChunkHandler _engine_chunk_handlers[] = {
 
	{ 'ENGN', Save_ENGN, Load_ENGN, CH_ARRAY},
 
	{ 'ENGS', LoadSave_ENGS, LoadSave_ENGS, CH_RIFF | CH_LAST},
 
	{ 'ENGN', Save_ENGN,     Load_ENGN,     CH_ARRAY          },
 
	{ 'ENGS', LoadSave_ENGS, LoadSave_ENGS, CH_RIFF           },
 
	{ 'ERNW', Save_ERNW,     Load_ERNW,     CH_ARRAY | CH_LAST},
 
};
 

	
 

	
 
/*
 
 * returns true if an engine is valid, of the specified type, and buildable by
 
 * the current player, false otherwise
 
 *
 
 * engine = index of the engine to check
 
 * type   = the type the engine should be of (VEH_xxx)
 
 */
 
bool IsEngineBuildable(uint engine, byte type)
 
void InitializeEngines(void)
 
{
 
	const Engine *e;
 

	
 
	// check if it's an engine that is in the engine array
 
	if (!IsEngineIndex(engine)) return false;
 

	
 
	e = GetEngine(engine);
 

	
 
	// check if it's an engine of specified type
 
	if (e->type != type) return false;
 

	
 
	// check if it's available
 
	if (!HASBIT(e->player_avail, _current_player)) return false;
 

	
 
	return true;
 
	/* Clean the engine renew pool and create 1 block in it */
 
	CleanPool(&_engine_renew_pool);
 
	AddBlockToPool(&_engine_renew_pool);
 
}