@@ -160,42 +160,30 @@ static void CalcEngineReliability(Engine
e->reliability = e->reliability_final;
}
void AddTypeToEngines(void)
{
Engine *e;
uint32 counter = 0;
for(e=_engines; e != endof(_engines); e++, counter++) {
Engine* e = _engines;
e->type = VEH_Train;
if (counter >= ROAD_ENGINES_INDEX) {
e->type = VEH_Road;
if (counter >= SHIP_ENGINES_INDEX) {
e->type = VEH_Ship;
if (counter >= AIRCRAFT_ENGINES_INDEX) {
e->type = VEH_Aircraft;
if (counter >= TOTAL_NUM_ENGINES) {
e->type = VEH_Special;
do e->type = VEH_Train; while (++e < &_engines[ROAD_ENGINES_INDEX]);
do e->type = VEH_Road; while (++e < &_engines[SHIP_ENGINES_INDEX]);
do e->type = VEH_Ship; while (++e < &_engines[AIRCRAFT_ENGINES_INDEX]);
do e->type = VEH_Aircraft; while (++e < &_engines[TOTAL_NUM_ENGINES]);
do e->type = VEH_Special; while (++e < endof(_engines));
void StartupEngines(void)
const EngineInfo *ei;
uint32 r, counter = 0;
SetupEngineNames();
for(e=_engines, ei=_engine_info; e != endof(_engines); e++, ei++, counter++) {
for (e = _engines, ei = _engine_info; e != endof(_engines); e++, ei++) {
uint32 r;
e->age = 0;
e->railtype = ei->railtype_climates >> 4;
e->flags = 0;
e->player_avail = 0;
@@ -280,36 +268,35 @@ void SetWagonOverrideSprites(byte engine
wo->group = *group;
wo->trains = trains;
wo->train_id = malloc(trains);
memcpy(wo->train_id, train_id, trains);
static SpriteGroup *GetWagonOverrideSpriteSet(byte engine, byte overriding_engine)
static const SpriteGroup *GetWagonOverrideSpriteSet(byte engine, byte overriding_engine)
WagonOverrides *wos = &_engine_wagon_overrides[engine];
const WagonOverrides *wos = &_engine_wagon_overrides[engine];
int i;
// XXX: This could turn out to be a timesink on profiles. We could
// always just dedicate 65535 bytes for an [engine][train] trampoline
// for O(1). Or O(logMlogN) and searching binary tree or smt. like
// that. --pasky
for (i = 0; i < wos->overrides_count; i++) {
WagonOverride *wo = &wos->overrides[i];
const WagonOverride *wo = &wos->overrides[i];
int j;
for (j = 0; j < wo->trains; j++) {
if (wo->train_id[j] == overriding_engine)
return &wo->group;
return NULL;
byte _engine_original_sprites[TOTAL_NUM_ENGINES];
// 0 - 28 are cargos, 29 is default, 30 is the advert (purchase list)
// (It isn't and shouldn't be like this in the GRF files since new cargo types
// may appear in future - however it's more convenient to store it like this in
// memory. --pasky)
static SpriteGroup _engine_custom_sprites[TOTAL_NUM_ENGINES][NUM_GLOBAL_CID];
@@ -318,27 +305,27 @@ void SetCustomEngineSprites(byte engine,
/* FIXME: If we are replacing an override, release original SpriteGroup
* to prevent leaks. But first we need to refcount the SpriteGroup.
* --pasky */
_engine_custom_sprites[engine][cargo] = *group;
typedef SpriteGroup *(*resolve_callback)(SpriteGroup *spritegroup,
typedef SpriteGroup *(*resolve_callback)(const SpriteGroup *spritegroup,
const Vehicle *veh, uint16 callback_info, void *resolve_func); /* XXX data pointer used as function pointer */
static SpriteGroup* ResolveVehicleSpriteGroup(SpriteGroup *spritegroup,
static const SpriteGroup* ResolveVehicleSpriteGroup(const SpriteGroup *spritegroup,
const Vehicle *veh, uint16 callback_info, resolve_callback resolve_func)
//debug("spgt %d", spritegroup->type);
switch (spritegroup->type) {
case SGT_REAL:
case SGT_CALLBACK:
return spritegroup;
case SGT_DETERMINISTIC: {
DeterministicSpriteGroup *dsg = &spritegroup->g.determ;
SpriteGroup *target;
const DeterministicSpriteGroup *dsg = &spritegroup->g.determ;
const SpriteGroup *target;
int value = -1;
//debug("[%p] Having fun resolving variable %x", veh, dsg->variable);
if (dsg->variable == 0x0C) {
/* Callback ID */
value = callback_info & 0xFF;
@@ -366,13 +353,13 @@ static SpriteGroup* ResolveVehicleSprite
if (veh->type == VEH_Train)
veh = GetFirstVehicleInChain(veh);
if (dsg->variable == 0x40 || dsg->variable == 0x41) {
if (veh->type == VEH_Train) {
Vehicle *u = GetFirstVehicleInChain(veh);
const Vehicle *u = GetFirstVehicleInChain(veh);
byte chain_before = 0, chain_after = 0;
while (u != veh) {
chain_before++;
if (dsg->variable == 0x41 && u->engine_type != veh->engine_type)
chain_before = 0;
@@ -480,13 +467,13 @@ static SpriteGroup* ResolveVehicleSprite
target = value != -1 ? EvalDeterministicSpriteGroup(dsg, value) : dsg->default_group;
//debug("Resolved variable %x: %d, %p", dsg->variable, value, callback);
return resolve_func(target, veh, callback_info, resolve_func);
case SGT_RANDOMIZED: {
RandomizedSpriteGroup *rsg = &spritegroup->g.random;
const RandomizedSpriteGroup *rsg = &spritegroup->g.random;
if (veh == NULL) {
/* Purchase list of something. Show the first one. */
assert(rsg->num_groups > 0);
//debug("going for %p: %d", rsg->groups[0], rsg->groups[0].type);
return resolve_func(&rsg->groups[0], NULL, callback_info, resolve_func);
@@ -504,37 +491,37 @@ static SpriteGroup* ResolveVehicleSprite
default:
error("I don't know how to handle such a spritegroup %d!", spritegroup->type);
static SpriteGroup *GetVehicleSpriteGroup(byte engine, const Vehicle *v)
static const SpriteGroup *GetVehicleSpriteGroup(byte engine, const Vehicle *v)
SpriteGroup *group;
const SpriteGroup *group;
byte cargo = GC_PURCHASE;
if (v != NULL) {
cargo = _global_cargo_id[_opt.landscape][v->cargo_type];
assert(cargo != GC_INVALID);
group = &_engine_custom_sprites[engine][cargo];
if (v != NULL && v->type == VEH_Train) {
SpriteGroup *overset = GetWagonOverrideSpriteSet(engine, v->u.rail.first_engine);
const SpriteGroup *overset = GetWagonOverrideSpriteSet(engine, v->u.rail.first_engine);
if (overset != NULL) group = overset;
return group;
int GetCustomEngineSprite(byte engine, const Vehicle *v, byte direction)
RealSpriteGroup *rsg;
const RealSpriteGroup *rsg;
byte loaded = 0;
bool in_motion = 0;
int totalsets, spriteset;
int r;
@@ -595,13 +582,13 @@ int GetCustomEngineSprite(byte engine, c
* Check if a wagon is currently using a wagon override
* @param v The wagon to check
* @return true if it is using an override, false otherwise
*/
bool UsesWagonOverride(const Vehicle *v) {
assert(v->type == VEH_Train);
return (GetWagonOverrideSpriteSet(v->engine_type, v->u.rail.first_engine) != NULL);
return GetWagonOverrideSpriteSet(v->engine_type, v->u.rail.first_engine) != NULL;
/**
* Evaluates a newgrf callback
* @param callback_info info about which callback to evaluate
* (bit 0-7) = CallBack id of the callback to use, see CallBackId enum
@@ -609,22 +596,22 @@ bool UsesWagonOverride(const Vehicle *v)
* @param engine Engine type of the vehicle to evaluate the callback for
* @param vehicle The vehicle to evaluate the callback for, NULL if it doesnt exist (yet)
* @return The value the callback returned, or CALLBACK_FAILED if it failed
uint16 GetCallBackResult(uint16 callback_info, byte engine, const Vehicle *v)
byte cargo = GC_DEFAULT;
if (v != NULL)
group = ResolveVehicleSpriteGroup(group, v, callback_info, (resolve_callback) ResolveVehicleSpriteGroup);
@@ -644,13 +631,13 @@ uint16 GetCallBackResult(uint16 callback
// Global variables are evil, yes, but we would end up with horribly overblown
// calling convention otherwise and this should be 100% reentrant.
static byte _vsg_random_triggers;
static byte _vsg_bits_to_reseed;
static SpriteGroup *TriggerVehicleSpriteGroup(SpriteGroup *spritegroup,
static const SpriteGroup *TriggerVehicleSpriteGroup(const SpriteGroup *spritegroup,
Vehicle *veh, uint16 callback_info, resolve_callback resolve_func)
if (spritegroup->type == SGT_RANDOMIZED) {
_vsg_bits_to_reseed |= RandomizedSpriteGroupTriggeredBits(
&spritegroup->g.random,
_vsg_random_triggers,
@@ -660,14 +647,14 @@ static SpriteGroup *TriggerVehicleSprite
return ResolveVehicleSpriteGroup(spritegroup, veh, callback_info, resolve_func);
static void DoTriggerVehicle(Vehicle *veh, VehicleTrigger trigger, byte base_random_bits, bool first)
byte new_random_bits;
_vsg_random_triggers = trigger;
_vsg_bits_to_reseed = 0;
group = TriggerVehicleSpriteGroup(GetVehicleSpriteGroup(veh->engine_type, veh), veh, 0,
(resolve_callback) TriggerVehicleSpriteGroup);
@@ -790,18 +777,19 @@ static PlayerID GetBestPlayer(PlayerID p
return best_player;
void EnginesDailyLoop(void)
uint i;
if (_cur_year >= 130) return;
for (e = _engines, i = 0; i != TOTAL_NUM_ENGINES; e++, i++) {
for (i = 0; i != lengthof(_engines); i++) {
Engine* e = &_engines[i];
if (e->flags & ENGINE_INTRODUCING) {
if (e->flags & ENGINE_PREVIEWING) {
if (e->preview_player != 0xFF && !--e->preview_wait) {
e->flags &= ~ENGINE_PREVIEWING;
DeleteWindowById(WC_ENGINE_PREVIEW, i);
e->preview_player++;
@@ -917,15 +905,15 @@ static void NewVehicleAvailable(Engine *
void EnginesMonthlyLoop(void)
if (_cur_year < 130) {
for(e=_engines; e != endof(_engines); e++) {
for (e = _engines; e != endof(_engines); e++) {
// Age the vehicle
if (e->flags&ENGINE_AVAILABLE && e->age != 0xFFFF) {
if (e->flags & ENGINE_AVAILABLE && e->age != 0xFFFF) {
e->age++;
CalcEngineReliability(e);
if (!(e->flags & ENGINE_AVAILABLE) && (uint16)(_date - min(_date, 365)) >= e->intro_date) {
// Introduce it to all players
@@ -995,17 +983,17 @@ static const SaveLoad _engine_desc[] = {
SLE_END()
};
static void Save_ENGN(void)
for(i=0,e=_engines; i != lengthof(_engines); i++,e++) {
SlSetArrayIndex(i);
SlObject(e, _engine_desc);
SlObject(&_engines[i], _engine_desc);
static void Load_ENGN(void)
int index;
@@ -6,13 +6,13 @@
#include "openttd.h"
#include "sprite.h"
#include "variables.h"
SpriteGroup *EvalDeterministicSpriteGroup(DeterministicSpriteGroup *dsg, int value)
SpriteGroup *EvalDeterministicSpriteGroup(const DeterministicSpriteGroup *dsg, int value)
value >>= dsg->shift_num; // This should bring us to the byte range.
value &= dsg->and_mask;
@@ -61,13 +61,13 @@ int GetDeterministicSpriteValue(byte var
return 0;
return -1;
SpriteGroup *EvalRandomizedSpriteGroup(RandomizedSpriteGroup *rsg, byte random_bits)
SpriteGroup *EvalRandomizedSpriteGroup(const RandomizedSpriteGroup *rsg, byte random_bits)
byte mask;
byte index;
/* Noone likes mangling with bits, but you don't get around it here.
* Sorry. --pasky */
@@ -75,13 +75,13 @@ SpriteGroup *EvalRandomizedSpriteGroup(R
mask = (rsg->num_groups - 1) << rsg->lowest_randbit;
index = (random_bits & mask) >> rsg->lowest_randbit;
assert(index < rsg->num_groups);
return &rsg->groups[index];
byte RandomizedSpriteGroupTriggeredBits(RandomizedSpriteGroup *rsg,
byte RandomizedSpriteGroupTriggeredBits(const RandomizedSpriteGroup *rsg,
byte triggers, byte *waiting_triggers)
byte match = rsg->triggers & (*waiting_triggers | triggers);
bool res;
if (rsg->cmp_mode == RSG_CMP_ANY) {
@@ -137,20 +137,20 @@ struct DeterministicSpriteGroupRange {
byte high;
/* This takes value (probably of the variable specified in the group) and
* chooses corresponding SpriteGroup accordingly to the given
* DeterministicSpriteGroup. */
struct SpriteGroup *EvalDeterministicSpriteGroup(struct DeterministicSpriteGroup *dsg, int value);
SpriteGroup *EvalDeterministicSpriteGroup(const DeterministicSpriteGroup *dsg, int value);
/* Get value of a common deterministic SpriteGroup variable. */
int GetDeterministicSpriteValue(byte var);
/* This takes randomized bitmask (probably associated with
* vehicle/station/whatever) and chooses corresponding SpriteGroup
* accordingly to the given RandomizedSpriteGroup. */
SpriteGroup *EvalRandomizedSpriteGroup(RandomizedSpriteGroup *rsg, byte random_bits);
SpriteGroup *EvalRandomizedSpriteGroup(const RandomizedSpriteGroup *rsg, byte random_bits);
/* Triggers given RandomizedSpriteGroup with given bitmask and returns and-mask
* of random bits to be reseeded, or zero if there were no triggers matched
* (then they are |ed to @waiting_triggers instead). */
byte RandomizedSpriteGroupTriggeredBits(RandomizedSpriteGroup *rsg, byte triggers, byte *waiting_triggers);
byte RandomizedSpriteGroupTriggeredBits(const RandomizedSpriteGroup *rsg, byte triggers, byte *waiting_triggers);
#endif
Status change: