Changeset - r21008:be2e3d3c935b
[Not reviewed]
src/base_station_base.h
Show inline comments
 
@@ -94,25 +94,25 @@ struct BaseStation : StationPool::PoolIt
 
	 * @return true if the tile belongs to this station
 
	 */
 
	virtual bool TileBelongsToRailStation(TileIndex tile) const = 0;
 

	
 
	/**
 
	 * Helper function to get a NewGRF variable that isn't implemented by the base class.
 
	 * @param object the resolver object related to this query
 
	 * @param variable that is queried
 
	 * @param parameter parameter for that variable
 
	 * @param available will return false if ever the variable asked for does not exist
 
	 * @return the value stored in the corresponding variable
 
	 */
 
	virtual uint32 GetNewGRFVariable(const struct ResolverObject *object, byte variable, byte parameter, bool *available) const = 0;
 
	virtual uint32 GetNewGRFVariable(const struct ResolverObject &object, byte variable, byte parameter, bool *available) const = 0;
 

	
 
	/**
 
	 * Update the coordinated of the sign (as shown in the viewport).
 
	 */
 
	virtual void UpdateVirtCoord() = 0;
 

	
 
	/**
 
	 * Get the tile area for a given station type.
 
	 * @param ta tile area to fill.
 
	 * @param type the type of the area
 
	 */
 
	virtual void GetTileArea(TileArea *ta, StationType type) const = 0;
src/newgrf_airport.cpp
Show inline comments
 
@@ -15,25 +15,25 @@
 
#include "newgrf_spritegroup.h"
 
#include "newgrf_text.h"
 
#include "station_base.h"
 
#include "newgrf_class_func.h"
 

	
 
/** Resolver for the airport scope. */
 
struct AirportScopeResolver : public ScopeResolver {
 
	struct Station *st; ///< Station of the airport for which the callback is run, or \c NULL for build gui.
 
	byte airport_id;    ///< Type of airport for which the callback is run.
 
	byte layout;        ///< Layout of the airport to build.
 
	TileIndex tile;     ///< Tile for the callback, only valid for airporttile callbacks.
 

	
 
	AirportScopeResolver(ResolverObject *ro, TileIndex tile, Station *st, byte airport_id, byte layout);
 
	AirportScopeResolver(ResolverObject &ro, TileIndex tile, Station *st, byte airport_id, byte layout);
 

	
 
	/* virtual */ uint32 GetRandomBits() const;
 
	/* virtual */ uint32 GetVariable(byte variable, uint32 parameter, bool *available) const;
 
	/* virtual */ void StorePSA(uint pos, int32 value);
 
};
 

	
 
/** Resolver object for airports. */
 
struct AirportResolverObject : public ResolverObject {
 
	AirportScopeResolver airport_scope;
 

	
 
	AirportResolverObject(TileIndex tile, Station *st, byte airport_id, byte layout,
 
			CallbackID callback = CBID_NO_CALLBACK, uint32 callback_param1 = 0, uint32 callback_param2 = 0);
 
@@ -207,89 +207,89 @@ void AirportOverrideManager::SetEntitySp
 
 * @param pos Position in the persistent storage to use.
 
 * @param value Value to store.
 
 */
 
/* virtual */ void AirportScopeResolver::StorePSA(uint pos, int32 value)
 
{
 
	if (this->st == NULL) return;
 

	
 
	if (this->st->airport.psa == NULL) {
 
		/* There is no need to create a storage if the value is zero. */
 
		if (value == 0) return;
 

	
 
		/* Create storage on first modification. */
 
		uint32 grfid = (this->ro->grffile != NULL) ? this->ro->grffile->grfid : 0;
 
		uint32 grfid = (this->ro.grffile != NULL) ? this->ro.grffile->grfid : 0;
 
		assert(PersistentStorage::CanAllocateItem());
 
		this->st->airport.psa = new PersistentStorage(grfid);
 
	}
 
	this->st->airport.psa->StoreValue(pos, value);
 
}
 

	
 
/**
 
 * Constructor of the airport resolver.
 
 * @param tile %Tile for the callback, only valid for airporttile callbacks.
 
 * @param st %Station of the airport for which the callback is run, or \c NULL for build gui.
 
 * @param airport_id Type of airport for which the callback is run.
 
 * @param layout Layout of the airport to build.
 
 * @param callback Callback ID.
 
 * @param param1 First parameter (var 10) of the callback.
 
 * @param param2 Second parameter (var 18) of the callback.
 
 */
 
AirportResolverObject::AirportResolverObject(TileIndex tile, Station *st, byte airport_id, byte layout,
 
		CallbackID callback, uint32 param1, uint32 param2)
 
	: ResolverObject(AirportSpec::Get(airport_id)->grf_prop.grffile, callback, param1, param2), airport_scope(this, tile, st, airport_id, layout)
 
	: ResolverObject(AirportSpec::Get(airport_id)->grf_prop.grffile, callback, param1, param2), airport_scope(*this, tile, st, airport_id, layout)
 
{
 
}
 

	
 
/**
 
 * Constructor of the scope resolver for an airport.
 
 * @param ro Surrounding resolver.
 
 * @param tile %Tile for the callback, only valid for airporttile callbacks.
 
 * @param st %Station of the airport for which the callback is run, or \c NULL for build gui.
 
 * @param airport_id Type of airport for which the callback is run.
 
 * @param layout Layout of the airport to build.
 
 */
 
AirportScopeResolver::AirportScopeResolver(ResolverObject *ro, TileIndex tile, Station *st, byte airport_id, byte layout) : ScopeResolver(ro)
 
AirportScopeResolver::AirportScopeResolver(ResolverObject &ro, TileIndex tile, Station *st, byte airport_id, byte layout) : ScopeResolver(ro)
 
{
 
	this->st = st;
 
	this->airport_id = airport_id;
 
	this->layout = layout;
 
	this->tile = tile;
 
}
 

	
 
SpriteID GetCustomAirportSprite(const AirportSpec *as, byte layout)
 
{
 
	AirportResolverObject object(INVALID_TILE, NULL, as->GetIndex(), layout);
 
	const SpriteGroup *group = SpriteGroup::Resolve(as->grf_prop.spritegroup[0], &object);
 
	const SpriteGroup *group = SpriteGroup::Resolve(as->grf_prop.spritegroup[0], object);
 
	if (group == NULL) return as->preview_sprite;
 

	
 
	return group->GetResult();
 
}
 

	
 
uint16 GetAirportCallback(CallbackID callback, uint32 param1, uint32 param2, Station *st, TileIndex tile)
 
{
 
	AirportResolverObject object(tile, st, st->airport.type, st->airport.layout, callback, param1, param2);
 
	const SpriteGroup *group = SpriteGroup::Resolve(st->airport.GetSpec()->grf_prop.spritegroup[0], &object);
 
	const SpriteGroup *group = SpriteGroup::Resolve(st->airport.GetSpec()->grf_prop.spritegroup[0], object);
 
	if (group == NULL) return CALLBACK_FAILED;
 

	
 
	return group->GetCallbackResult();
 
}
 

	
 
/**
 
 * Get a custom text for the airport.
 
 * @param as The airport type's specification.
 
 * @param layout The layout index.
 
 * @param callback The callback to call.
 
 * @return The custom text.
 
 */
 
StringID GetAirportTextCallback(const AirportSpec *as, byte layout, uint16 callback)
 
{
 
	AirportResolverObject object(INVALID_TILE, NULL, as->GetIndex(), layout, (CallbackID)callback);
 
	const SpriteGroup *group = SpriteGroup::Resolve(as->grf_prop.spritegroup[0], &object);
 
	const SpriteGroup *group = SpriteGroup::Resolve(as->grf_prop.spritegroup[0], object);
 
	uint16 cb_res = (group != NULL) ? group->GetCallbackResult() : CALLBACK_FAILED;
 
	if (cb_res == CALLBACK_FAILED || cb_res == 0x400) return STR_UNDEFINED;
 
	if (cb_res > 0x400) {
 
		ErrorUnknownCallbackResult(as->grf_prop.grffile->grfid, callback, cb_res);
 
		return STR_UNDEFINED;
 
	}
 

	
 
	return GetGRFStringID(as->grf_prop.grffile->grfid, 0xD000 + cb_res);
 
}
src/newgrf_airporttiles.cpp
Show inline comments
 
@@ -169,84 +169,84 @@ static uint32 GetAirportTileIDAtOffset(T
 
		case 0x41: return GetTerrainType(this->tile);
 

	
 
		/* Current town zone of the tile in the nearest town */
 
		case 0x42: return GetTownRadiusGroup(ClosestTownFromTile(this->tile, UINT_MAX), this->tile);
 

	
 
		/* Position relative to most northern airport tile. */
 
		case 0x43: return GetRelativePosition(this->tile, this->st->airport.tile);
 

	
 
		/* Animation frame of tile */
 
		case 0x44: return GetAnimationFrame(this->tile);
 

	
 
		/* Land info of nearby tiles */
 
		case 0x60: return GetNearbyAirportTileInformation(parameter, this->tile, this->st->index, this->ro->grffile->grf_version >= 8);
 
		case 0x60: return GetNearbyAirportTileInformation(parameter, this->tile, this->st->index, this->ro.grffile->grf_version >= 8);
 

	
 
		/* Animation stage of nearby tiles */
 
		case 0x61: {
 
			TileIndex tile = GetNearbyTile(parameter, this->tile);
 
			if (this->st->TileBelongsToAirport(tile)) {
 
				return GetAnimationFrame(tile);
 
			}
 
			return UINT_MAX;
 
		}
 

	
 
		/* Get airport tile ID at offset */
 
		case 0x62: return GetAirportTileIDAtOffset(GetNearbyTile(parameter, this->tile), this->st, this->ro->grffile->grfid);
 
		case 0x62: return GetAirportTileIDAtOffset(GetNearbyTile(parameter, this->tile), this->st, this->ro.grffile->grfid);
 
	}
 

	
 
	DEBUG(grf, 1, "Unhandled airport tile variable 0x%X", variable);
 

	
 
	*available = false;
 
	return UINT_MAX;
 
}
 

	
 
/* virtual */ uint32 AirportTileScopeResolver::GetRandomBits() const
 
{
 
	return (this->st == NULL ? 0 : this->st->random_bits) | (this->tile == INVALID_TILE ? 0 : GetStationTileRandomBits(this->tile) << 16);
 
}
 

	
 
/**
 
 * Constructor of the resolver for airport tiles.
 
 * @param ats Specification of the airport tiles.
 
 * @param tile %Tile for the callback, only valid for airporttile callbacks.
 
 * @param st Station of the airport for which the callback is run, or \c NULL for build gui.
 
 * @param callback Callback ID.
 
 * @param callback_param1 First parameter (var 10) of the callback.
 
 * @param callback_param2 Second parameter (var 18) of the callback.
 
 */
 
AirportTileResolverObject::AirportTileResolverObject(const AirportTileSpec *ats, TileIndex tile, Station *st,
 
		CallbackID callback, uint32 callback_param1, uint32 callback_param2)
 
	: ResolverObject(ats->grf_prop.grffile, callback, callback_param1, callback_param2), tiles_scope(this, ats, tile, st)
 
	: ResolverObject(ats->grf_prop.grffile, callback, callback_param1, callback_param2), tiles_scope(*this, ats, tile, st)
 
{
 
}
 

	
 
/**
 
 * Constructor of the scope resolver specific for airport tiles.
 
 * @param ats Specification of the airport tiles.
 
 * @param tile %Tile for the callback, only valid for airporttile callbacks.
 
 * @param st Station of the airport for which the callback is run, or \c NULL for build gui.
 
 */
 
AirportTileScopeResolver::AirportTileScopeResolver(ResolverObject *ro, const AirportTileSpec *ats, TileIndex tile, Station *st) : ScopeResolver(ro)
 
AirportTileScopeResolver::AirportTileScopeResolver(ResolverObject &ro, const AirportTileSpec *ats, TileIndex tile, Station *st) : ScopeResolver(ro)
 
{
 
	assert(st != NULL);
 

	
 
	this->st = st;
 
	this->airport_id = st->airport.type;
 
	this->tile = tile;
 
}
 

	
 
uint16 GetAirportTileCallback(CallbackID callback, uint32 param1, uint32 param2, const AirportTileSpec *ats, Station *st, TileIndex tile, int extra_data = 0)
 
{
 
	AirportTileResolverObject object(ats, tile, st, callback, param1, param2);
 
	const SpriteGroup *group = SpriteGroup::Resolve(ats->grf_prop.spritegroup[0], &object);
 
	const SpriteGroup *group = SpriteGroup::Resolve(ats->grf_prop.spritegroup[0], object);
 
	if (group == NULL) return CALLBACK_FAILED;
 

	
 
	return group->GetCallbackResult();
 
}
 

	
 
static void AirportDrawTileLayout(const TileInfo *ti, const TileLayoutSpriteGroup *group, byte colour, StationGfx gfx)
 
{
 
	const DrawTileSprites *dts = group->ProcessRegisters(NULL);
 

	
 
	SpriteID image = dts->ground.sprite;
 
	SpriteID pal   = dts->ground.pal;
 

	
 
@@ -266,25 +266,25 @@ bool DrawNewAirportTile(TileInfo *ti, St
 
	if (ti->tileh != SLOPE_FLAT) {
 
		bool draw_old_one = true;
 
		if (HasBit(airts->callback_mask, CBM_AIRT_DRAW_FOUNDATIONS)) {
 
			/* Called to determine the type (if any) of foundation to draw */
 
			uint32 callback_res = GetAirportTileCallback(CBID_AIRPTILE_DRAW_FOUNDATIONS, 0, 0, airts, st, ti->tile);
 
			if (callback_res != CALLBACK_FAILED) draw_old_one = ConvertBooleanCallback(airts->grf_prop.grffile, CBID_AIRPTILE_DRAW_FOUNDATIONS, callback_res);
 
		}
 

	
 
		if (draw_old_one) DrawFoundation(ti, FOUNDATION_LEVELED);
 
	}
 

	
 
	AirportTileResolverObject object(airts, ti->tile, st);
 
	const SpriteGroup *group = SpriteGroup::Resolve(airts->grf_prop.spritegroup[0], &object);
 
	const SpriteGroup *group = SpriteGroup::Resolve(airts->grf_prop.spritegroup[0], object);
 
	if (group == NULL || group->type != SGT_TILELAYOUT) {
 
		return false;
 
	}
 

	
 
	const TileLayoutSpriteGroup *tlgroup = (const TileLayoutSpriteGroup *)group;
 
	AirportDrawTileLayout(ti, tlgroup, Company::Get(st->owner)->colour, gfx);
 
	return true;
 
}
 

	
 
/** Helper class for animation control. */
 
struct AirportTileAnimationBase : public AnimationBase<AirportTileAnimationBase, AirportTileSpec, Station, int, GetAirportTileCallback> {
 
	static const CallbackID cb_animation_speed      = CBID_AIRPTILE_ANIMATION_SPEED;
src/newgrf_airporttiles.h
Show inline comments
 
@@ -15,25 +15,25 @@
 
#include "airport.h"
 
#include "station_map.h"
 
#include "newgrf_animation_type.h"
 
#include "newgrf_commons.h"
 
#include "newgrf_spritegroup.h"
 

	
 
/** Scope resolver for handling the tiles of an airport. */
 
struct AirportTileScopeResolver : public ScopeResolver {
 
	struct Station *st;  ///< %Station of the airport for which the callback is run, or \c NULL for build gui.
 
	byte airport_id;     ///< Type of airport for which the callback is run.
 
	TileIndex tile;      ///< Tile for the callback, only valid for airporttile callbacks.
 

	
 
	AirportTileScopeResolver(ResolverObject *ro, const AirportTileSpec *ats, TileIndex tile, Station *st);
 
	AirportTileScopeResolver(ResolverObject &ro, const AirportTileSpec *ats, TileIndex tile, Station *st);
 

	
 
	/* virtual */ uint32 GetRandomBits() const;
 
	/* virtual */ uint32 GetVariable(byte variable, uint32 parameter, bool *available) const;
 
};
 

	
 
/** Resolver for tiles of an airport. */
 
struct AirportTileResolverObject : public ResolverObject {
 
	AirportTileScopeResolver tiles_scope; ///< Scope resolver for the tiles.
 

	
 
	AirportTileResolverObject(const AirportTileSpec *ats, TileIndex tile, Station *st,
 
			CallbackID callback = CBID_NO_CALLBACK, uint32 callback_param1 = 0, uint32 callback_param2 = 0);
 

	
src/newgrf_canal.cpp
Show inline comments
 
@@ -14,25 +14,25 @@
 
#include "newgrf_spritegroup.h"
 
#include "newgrf_canal.h"
 
#include "water.h"
 
#include "water_map.h"
 

	
 
/** Table of canal 'feature' sprite groups */
 
WaterFeature _water_feature[CF_END];
 

	
 
/** Scope resolver of a canal tile. */
 
struct CanalScopeResolver : public ScopeResolver {
 
	TileIndex tile; ///< Tile containing the canal.
 

	
 
	CanalScopeResolver(ResolverObject *ro, TileIndex tile);
 
	CanalScopeResolver(ResolverObject &ro, TileIndex tile);
 

	
 
	/* virtual */ uint32 GetRandomBits() const;
 
	/* virtual */ uint32 GetVariable(byte variable, uint32 parameter, bool *available) const;
 
};
 

	
 
/** Resolver object for canals. */
 
struct CanalResolverObject : public ResolverObject {
 
	CanalScopeResolver canal_scope;
 

	
 
	CanalResolverObject(const GRFFile *grffile, TileIndex tile,
 
			CallbackID callback = CBID_NO_CALLBACK, uint32 callback_param1 = 0, uint32 callback_param2 = 0);
 

	
 
@@ -99,71 +99,71 @@ struct CanalResolverObject : public Reso
 
	*available = false;
 
	return UINT_MAX;
 
}
 

	
 

	
 
/* virtual */ const SpriteGroup *CanalResolverObject::ResolveReal(const RealSpriteGroup *group) const
 
{
 
	if (group->num_loaded == 0) return NULL;
 

	
 
	return group->loaded[0];
 
}
 

	
 
CanalScopeResolver::CanalScopeResolver(ResolverObject *ro, TileIndex tile) : ScopeResolver(ro)
 
CanalScopeResolver::CanalScopeResolver(ResolverObject &ro, TileIndex tile) : ScopeResolver(ro)
 
{
 
	this->tile = tile;
 
}
 

	
 
/**
 
 * Canal resolver constructor.
 
 * @param grffile Grf file.
 
 * @param tile Tile index of canal.
 
 * @param callback Callback ID.
 
 * @param callback_param1 First parameter (var 10) of the callback.
 
 * @param callback_param2 Second parameter (var 18) of the callback.
 
 */
 
CanalResolverObject::CanalResolverObject(const GRFFile *grffile, TileIndex tile,
 
		CallbackID callback, uint32 callback_param1, uint32 callback_param2)
 
		: ResolverObject(grffile, callback, callback_param1, callback_param2), canal_scope(this, tile)
 
		: ResolverObject(grffile, callback, callback_param1, callback_param2), canal_scope(*this, tile)
 
{
 
}
 

	
 
/**
 
 * Lookup the base sprite to use for a canal.
 
 * @param feature Which canal feature we want.
 
 * @param tile Tile index of canal, if appropriate.
 
 * @return Base sprite returned by GRF, or \c 0 if none.
 
 */
 
SpriteID GetCanalSprite(CanalFeature feature, TileIndex tile)
 
{
 
	CanalResolverObject object(_water_feature[feature].grffile, tile);
 
	const SpriteGroup *group = SpriteGroup::Resolve(_water_feature[feature].group, &object);
 
	const SpriteGroup *group = SpriteGroup::Resolve(_water_feature[feature].group, object);
 
	if (group == NULL) return 0;
 

	
 
	return group->GetResult();
 
}
 

	
 
/**
 
 * Run a specific callback for canals.
 
 * @param callback Callback ID.
 
 * @param param1   Callback parameter 1.
 
 * @param param2   Callback parameter 2.
 
 * @param feature  For which feature to run the callback.
 
 * @param tile     Tile index of canal.
 
 * @return Callback result or #CALLBACK_FAILED if the callback failed.
 
 */
 
static uint16 GetCanalCallback(CallbackID callback, uint32 param1, uint32 param2, CanalFeature feature, TileIndex tile)
 
{
 
	CanalResolverObject object(_water_feature[feature].grffile, tile, callback, param1, param2);
 
	const SpriteGroup *group = SpriteGroup::Resolve(_water_feature[feature].group, &object);
 
	const SpriteGroup *group = SpriteGroup::Resolve(_water_feature[feature].group, object);
 
	if (group == NULL) return CALLBACK_FAILED;
 

	
 
	return group->GetCallbackResult();
 
}
 

	
 
/**
 
 * Get the new sprite offset for a water tile.
 
 * @param tile       Tile index of the canal/water tile.
 
 * @param feature    For which feature to get the new sprite offset.
 
 * @param cur_offset Current sprite offset.
 
 * @return New sprite offset.
 
 */
src/newgrf_cargo.cpp
Show inline comments
 
@@ -41,35 +41,35 @@ CargoResolverObject::CargoResolverObject
 
		: ResolverObject(cs->grffile, callback, callback_param1, callback_param2)
 
{
 
}
 

	
 
/**
 
 * Get the custom sprite for the given cargo type.
 
 * @param cs Cargo being queried.
 
 * @return Custom sprite to draw, or \c 0 if not available.
 
 */
 
SpriteID GetCustomCargoSprite(const CargoSpec *cs)
 
{
 
	CargoResolverObject object(cs);
 
	const SpriteGroup *group = SpriteGroup::Resolve(cs->group, &object);
 
	const SpriteGroup *group = SpriteGroup::Resolve(cs->group, object);
 
	if (group == NULL) return 0;
 

	
 
	return group->GetResult();
 
}
 

	
 

	
 
uint16 GetCargoCallback(CallbackID callback, uint32 param1, uint32 param2, const CargoSpec *cs)
 
{
 
	CargoResolverObject object(cs, callback, param1, param2);
 
	const SpriteGroup *group = SpriteGroup::Resolve(cs->group, &object);
 
	const SpriteGroup *group = SpriteGroup::Resolve(cs->group, object);
 
	if (group == NULL) return CALLBACK_FAILED;
 

	
 
	return group->GetCallbackResult();
 
}
 

	
 
/**
 
 * Translate a GRF-local cargo slot/bitnum into a CargoID.
 
 * @param cargo   GRF-local cargo slot/bitnum.
 
 * @param grffile Originating GRF file.
 
 * @param usebit  Defines the meaning of \a cargo for GRF version < 7.
 
 *                If true, then \a cargo is a bitnum. If false, then \a cargo is a cargoslot.
 
 *                For GRF version >= 7 \a cargo is always a translated cargo bit.
src/newgrf_engine.cpp
Show inline comments
 
@@ -351,25 +351,25 @@ static byte MapAircraftMovementAction(co
 
}
 

	
 
/* virtual */ void VehicleScopeResolver::SetTriggers(int triggers) const
 
{
 
	/* Evil cast to get around const-ness. This used to be achieved by an
 
	 * innocent looking function pointer cast... Currently I cannot see a
 
	 * way of avoiding this without removing consts deep within gui code.
 
	 */
 
	Vehicle *v = const_cast<Vehicle *>(this->v);
 

	
 
	/* This function must only be called when processing triggers -- any
 
	 * other time is an error. */
 
	assert(this->ro->trigger != 0);
 
	assert(this->ro.trigger != 0);
 

	
 
	if (v != NULL) v->waiting_triggers = triggers;
 
}
 

	
 

	
 
/* virtual */ ScopeResolver *VehicleResolverObject::GetScope(VarSpriteGroupScope scope, byte relative)
 
{
 
	switch (scope) {
 
		case VSG_SCOPE_SELF:   return &this->self_scope;
 
		case VSG_SCOPE_PARENT: return &this->parent_scope;
 
		case VSG_SCOPE_RELATIVE: {
 
			int32 count = GB(relative, 0, 4);
 
@@ -537,25 +537,25 @@ static uint32 VehicleGetVariable(Vehicle
 
				/* Note: We have to store the untranslated cargotype in the cache as the cache can be read by different NewGRFs,
 
				 *       which will need different translations */
 
				v->grf_cache.consist_cargo_information = cargo_classes | (common_cargo_type << 8) | (common_subtype << 16) | (user_def_data << 24);
 
				SetBit(v->grf_cache.cache_valid, NCVV_CONSIST_CARGO_INFORMATION);
 
			}
 

	
 
			/* The cargo translation is specific to the accessing GRF, and thus cannot be cached. */
 
			CargoID common_cargo_type = (v->grf_cache.consist_cargo_information >> 8) & 0xFF;
 

	
 
			/* Unlike everywhere else the cargo translation table is only used since grf version 8, not 7.
 
			 * Note: The grffile == NULL case only happens if this function is called for default vehicles.
 
			 *       And this is only done by CheckCaches(). */
 
			const GRFFile *grffile = object->ro->grffile;
 
			const GRFFile *grffile = object->ro.grffile;
 
			uint8 common_bitnum = (common_cargo_type == CT_INVALID) ? 0xFF :
 
				(grffile == NULL || grffile->grf_version < 8) ? CargoSpec::Get(common_cargo_type)->bitnum : grffile->cargo_map[common_cargo_type];
 

	
 
			return (v->grf_cache.consist_cargo_information & 0xFFFF00FF) | common_bitnum << 8;
 
		}
 

	
 
		case 0x43: // Company information
 
			if (!HasBit(v->grf_cache.cache_valid, NCVV_COMPANY_INFORMATION)) {
 
				v->grf_cache.company_information = GetCompanyInfo(v->owner, LiveryHelper(v->engine_type, v));
 
				SetBit(v->grf_cache.cache_valid, NCVV_COMPANY_INFORMATION);
 
			}
 
			return v->grf_cache.company_information;
 
@@ -608,25 +608,25 @@ static uint32 VehicleGetVariable(Vehicle
 
			 */
 
			const CargoSpec *cs = CargoSpec::Get(v->cargo_type);
 

	
 
			return (cs->classes << 16) | (cs->weight << 8) | v->GetGRF()->cargo_map[v->cargo_type];
 
		}
 

	
 
		case 0x48: return v->GetEngine()->flags; // Vehicle Type Info
 
		case 0x49: return v->build_year;
 

	
 
		case 0x4A: {
 
			if (v->type != VEH_TRAIN) return 0;
 
			RailType rt = GetTileRailType(v->tile);
 
			return (HasPowerOnRail(Train::From(v)->railtype, rt) ? 0x100 : 0) | GetReverseRailTypeTranslation(rt, object->ro->grffile);
 
			return (HasPowerOnRail(Train::From(v)->railtype, rt) ? 0x100 : 0) | GetReverseRailTypeTranslation(rt, object->ro.grffile);
 
		}
 

	
 
		case 0x4B: // Long date of last service
 
			return v->date_of_last_service;
 

	
 
		case 0x4C: // Current maximum speed in NewGRF units
 
			if (!v->IsPrimaryVehicle()) return 0;
 
			return v->GetCurrentMaxSpeed();
 

	
 
		/* Variables which use the parameter */
 
		case 0x60: // Count consist's engine ID occurrence
 
			if (v->type != VEH_TRAIN) return v->GetEngine()->grf_prop.local_id == parameter ? 1 : 0;
 
@@ -634,26 +634,26 @@ static uint32 VehicleGetVariable(Vehicle
 
			{
 
				uint count = 0;
 
				for (; v != NULL; v = v->Next()) {
 
					if (v->GetEngine()->grf_prop.local_id == parameter) count++;
 
				}
 
				return count;
 
			}
 

	
 
		case 0x61: // Get variable of n-th vehicle in chain [signed number relative to vehicle]
 
			if (!v->IsGroundVehicle() || parameter == 0x61) return 0;
 

	
 
			/* Only allow callbacks that don't change properties to avoid circular dependencies. */
 
			if (object->ro->callback == CBID_NO_CALLBACK || object->ro->callback == CBID_RANDOM_TRIGGER || object->ro->callback == CBID_TRAIN_ALLOW_WAGON_ATTACH ||
 
					object->ro->callback == CBID_VEHICLE_START_STOP_CHECK || object->ro->callback == CBID_VEHICLE_32DAY_CALLBACK || object->ro->callback == CBID_VEHICLE_COLOUR_MAPPING) {
 
			if (object->ro.callback == CBID_NO_CALLBACK || object->ro.callback == CBID_RANDOM_TRIGGER || object->ro.callback == CBID_TRAIN_ALLOW_WAGON_ATTACH ||
 
					object->ro.callback == CBID_VEHICLE_START_STOP_CHECK || object->ro.callback == CBID_VEHICLE_32DAY_CALLBACK || object->ro.callback == CBID_VEHICLE_COLOUR_MAPPING) {
 
				Vehicle *u = v->Move((int32)GetRegister(0x10F));
 
				if (u == NULL) return 0;
 

	
 
				if (parameter == 0x5F) {
 
					/* This seems to be the only variable that makes sense to access via var 61, but is not handled by VehicleGetVariable */
 
					return (u->random_bits << 8) | u->waiting_triggers;
 
				} else {
 
					return VehicleGetVariable(u, object, parameter, GetRegister(0x10E), available);
 
				}
 
			}
 
			return 0;
 

	
 
@@ -926,25 +926,25 @@ static uint32 VehicleGetVariable(Vehicle
 
	set = min(set, totalsets - 1);
 

	
 
	return in_motion ? group->loaded[set] : group->loading[set];
 
}
 

	
 
/**
 
 * Scope resolver of a single vehicle.
 
 * @param ro Surrounding resolver.
 
 * @param engine_type Engine type
 
 * @param v %Vehicle being resolved.
 
 * @param info_view Indicates if the item is being drawn in an info window.
 
 */
 
VehicleScopeResolver::VehicleScopeResolver(ResolverObject *ro, EngineID engine_type, const Vehicle *v, bool info_view)
 
VehicleScopeResolver::VehicleScopeResolver(ResolverObject &ro, EngineID engine_type, const Vehicle *v, bool info_view)
 
		: ScopeResolver(ro)
 
{
 
	this->v = v;
 
	this->self_type = engine_type;
 
	this->info_view = info_view;
 
}
 

	
 
/**
 
 * Get the grf file associated with an engine type.
 
 * @param engine_type Engine to query.
 
 * @return grf file associated with the engine.
 
 */
 
@@ -957,27 +957,27 @@ static const GRFFile *GetEngineGrfFile(E
 
/**
 
 * Resolver of a vehicle (chain).
 
 * @param engine_type Engine type
 
 * @param v %Vehicle being resolved.
 
 * @param info_view Indicates if the item is being drawn in an info window.
 
 * @param callback Callback ID.
 
 * @param callback_param1 First parameter (var 10) of the callback.
 
 * @param callback_param2 Second parameter (var 18) of the callback.
 
 */
 
VehicleResolverObject::VehicleResolverObject(EngineID engine_type, const Vehicle *v, bool info_view,
 
		CallbackID callback, uint32 callback_param1, uint32 callback_param2)
 
	: ResolverObject(GetEngineGrfFile(engine_type), callback, callback_param1, callback_param2),
 
	self_scope(this, engine_type, v, info_view),
 
	parent_scope(this, engine_type, ((v != NULL) ? v->First() : v), info_view),
 
	relative_scope(this, engine_type, v, info_view),
 
	self_scope(*this, engine_type, v, info_view),
 
	parent_scope(*this, engine_type, ((v != NULL) ? v->First() : v), info_view),
 
	relative_scope(*this, engine_type, v, info_view),
 
	cached_relative_count(0)
 
{
 
}
 

	
 
/**
 
 * Retrieve the SpriteGroup for the specified vehicle.
 
 * If the vehicle is not specified, the purchase list group for the engine is
 
 * chosen. For trains, an additional engine override lookup is performed.
 
 * @param engine    Engine type of the vehicle.
 
 * @param v         The vehicle itself.
 
 * @param use_cache Use cached override
 
 * @returns         The selected SpriteGroup for the vehicle.
 
@@ -1010,42 +1010,42 @@ static const SpriteGroup *GetVehicleSpri
 
	assert(cargo < lengthof(e->grf_prop.spritegroup));
 
	group = e->grf_prop.spritegroup[cargo];
 
	if (group != NULL) return group;
 

	
 
	/* Fall back to the default set if the selected cargo type is not defined */
 
	return e->grf_prop.spritegroup[CT_DEFAULT];
 
}
 

	
 

	
 
SpriteID GetCustomEngineSprite(EngineID engine, const Vehicle *v, Direction direction, EngineImageType image_type)
 
{
 
	VehicleResolverObject object(engine, v, false, CBID_NO_CALLBACK, image_type);
 
	const SpriteGroup *group = SpriteGroup::Resolve(GetVehicleSpriteGroup(engine, v), &object);
 
	const SpriteGroup *group = SpriteGroup::Resolve(GetVehicleSpriteGroup(engine, v), object);
 
	if (group == NULL || group->GetNumResults() == 0) return 0;
 

	
 
	return group->GetResult() + (direction % group->GetNumResults());
 
}
 

	
 

	
 
SpriteID GetRotorOverrideSprite(EngineID engine, const Aircraft *v, bool info_view, EngineImageType image_type)
 
{
 
	const Engine *e = Engine::Get(engine);
 

	
 
	/* Only valid for helicopters */
 
	assert(e->type == VEH_AIRCRAFT);
 
	assert(!(e->u.air.subtype & AIR_CTOL));
 

	
 
	VehicleResolverObject object(engine, v, info_view, CBID_NO_CALLBACK, image_type);
 
	const SpriteGroup *group = GetWagonOverrideSpriteSet(engine, CT_DEFAULT, engine);
 
	group = SpriteGroup::Resolve(group, &object);
 
	group = SpriteGroup::Resolve(group, object);
 

	
 
	if (group == NULL || group->GetNumResults() == 0) return 0;
 

	
 
	if (v == NULL) return group->GetResult();
 

	
 
	return group->GetResult() + (info_view ? 0 : (v->Next()->Next()->state % group->GetNumResults()));
 
}
 

	
 

	
 
/**
 
 * Check if a wagon is currently using a wagon override
 
 * @param v The wagon to check
 
@@ -1060,46 +1060,46 @@ bool UsesWagonOverride(const Vehicle *v)
 
/**
 
 * Evaluate a newgrf callback for vehicles
 
 * @param callback The callback to evaluate
 
 * @param param1   First parameter of the callback
 
 * @param param2   Second parameter of the callback
 
 * @param engine   Engine type of the vehicle to evaluate the callback for
 
 * @param v        The vehicle to evaluate the callback for, or NULL if it doesnt exist yet
 
 * @return The value the callback returned, or CALLBACK_FAILED if it failed
 
 */
 
uint16 GetVehicleCallback(CallbackID callback, uint32 param1, uint32 param2, EngineID engine, const Vehicle *v)
 
{
 
	VehicleResolverObject object(engine, v, false, callback, param1, param2);
 
	const SpriteGroup *group = SpriteGroup::Resolve(GetVehicleSpriteGroup(engine, v, false), &object);
 
	const SpriteGroup *group = SpriteGroup::Resolve(GetVehicleSpriteGroup(engine, v, false), object);
 
	if (group == NULL) return CALLBACK_FAILED;
 

	
 
	return group->GetCallbackResult();
 
}
 

	
 
/**
 
 * Evaluate a newgrf callback for vehicles with a different vehicle for parent scope.
 
 * @param callback The callback to evaluate
 
 * @param param1   First parameter of the callback
 
 * @param param2   Second parameter of the callback
 
 * @param engine   Engine type of the vehicle to evaluate the callback for
 
 * @param v        The vehicle to evaluate the callback for, or NULL if it doesn't exist yet
 
 * @param parent   The vehicle to use for parent scope
 
 * @return The value the callback returned, or CALLBACK_FAILED if it failed
 
 */
 
uint16 GetVehicleCallbackParent(CallbackID callback, uint32 param1, uint32 param2, EngineID engine, const Vehicle *v, const Vehicle *parent)
 
{
 
	VehicleResolverObject object(engine, v, false, callback, param1, param2);
 
	object.parent_scope.SetVehicle(parent);
 

	
 
	const SpriteGroup *group = SpriteGroup::Resolve(GetVehicleSpriteGroup(engine, v, false), &object);
 
	const SpriteGroup *group = SpriteGroup::Resolve(GetVehicleSpriteGroup(engine, v, false), object);
 
	if (group == NULL) return CALLBACK_FAILED;
 

	
 
	return group->GetCallbackResult();
 
}
 

	
 

	
 
/* Callback 36 handlers */
 
uint GetVehicleProperty(const Vehicle *v, PropertyID property, uint orig_value)
 
{
 
	return GetEngineProperty(v->engine_type, property, orig_value, v);
 
}
 

	
 
@@ -1112,25 +1112,25 @@ uint GetEngineProperty(EngineID engine, 
 
	return orig_value;
 
}
 

	
 

	
 
static void DoTriggerVehicle(Vehicle *v, VehicleTrigger trigger, byte base_random_bits, bool first)
 
{
 
	/* We can't trigger a non-existent vehicle... */
 
	assert(v != NULL);
 

	
 
	VehicleResolverObject object(v->engine_type, v, false, CBID_RANDOM_TRIGGER);
 
	object.trigger = trigger;
 

	
 
	const SpriteGroup *group = SpriteGroup::Resolve(GetVehicleSpriteGroup(v->engine_type, v), &object);
 
	const SpriteGroup *group = SpriteGroup::Resolve(GetVehicleSpriteGroup(v->engine_type, v), object);
 
	if (group == NULL) return;
 

	
 
	byte new_random_bits = Random();
 
	uint32 reseed = object.GetReseedSum(); // The scope only affects triggers, not the reseeding
 
	v->random_bits &= ~reseed;
 
	v->random_bits |= (first ? new_random_bits : base_random_bits) & reseed;
 

	
 
	switch (trigger) {
 
		case VEHICLE_TRIGGER_NEW_CARGO:
 
			/* All vehicles in chain get ANY_NEW_CARGO trigger now.
 
			 * So we call it for the first one and they will recurse.
 
			 * Indexing part of vehicle random bits needs to be
src/newgrf_engine.h
Show inline comments
 
@@ -17,25 +17,25 @@
 
#include "newgrf_properties.h"
 
#include "vehicle_type.h"
 
#include "engine_type.h"
 
#include "gfx_type.h"
 
#include "newgrf_spritegroup.h"
 

	
 
/** Resolver for a vehicle scope. */
 
struct VehicleScopeResolver : public ScopeResolver {
 
	const struct Vehicle *v; ///< The vehicle being resolved.
 
	EngineID self_type;      ///< Type of the vehicle.
 
	bool info_view;          ///< Indicates if the item is being drawn in an info window.
 

	
 
	VehicleScopeResolver(ResolverObject *ro, EngineID engine_type, const Vehicle *v, bool info_view);
 
	VehicleScopeResolver(ResolverObject &ro, EngineID engine_type, const Vehicle *v, bool info_view);
 

	
 
	void SetVehicle(const Vehicle *v) { this->v = v; }
 

	
 
	/* virtual */ uint32 GetRandomBits() const;
 
	/* virtual */ uint32 GetVariable(byte variable, uint32 parameter, bool *available) const;
 
	/* virtual */ uint32 GetTriggers() const;
 
	/* virtual */ void SetTriggers(int triggers) const;
 
};
 

	
 
/** Resolver for a vehicle (chain) */
 
struct VehicleResolverObject : public ResolverObject {
 
	VehicleScopeResolver self_scope;     ///< Scope resolver for the indicated vehicle.
src/newgrf_generic.cpp
Show inline comments
 
@@ -20,25 +20,25 @@
 

	
 
/** Scope resolver for generic objects and properties. */
 
struct GenericScopeResolver : public ScopeResolver {
 
	CargoID cargo_type;
 
	uint8 default_selection;
 
	uint8 src_industry;        ///< Source industry substitute type. 0xFF for "town", 0xFE for "unknown".
 
	uint8 dst_industry;        ///< Destination industry substitute type. 0xFF for "town", 0xFE for "unknown".
 
	uint8 distance;
 
	AIConstructionEvent event;
 
	uint8 count;
 
	uint8 station_size;
 

	
 
	GenericScopeResolver(ResolverObject *ro, bool ai_callback);
 
	GenericScopeResolver(ResolverObject &ro, bool ai_callback);
 

	
 
	/* virtual */ uint32 GetVariable(byte variable, uint32 parameter, bool *available) const;
 

	
 
private:
 
	bool ai_callback; ///< Callback comes from the AI.
 
};
 

	
 

	
 
/** Resolver object for generic objects/properties. */
 
struct GenericResolverObject : public ResolverObject {
 
	GenericScopeResolver generic_scope;
 

	
 
@@ -95,25 +95,25 @@ void AddGenericCallback(uint8 feature, c
 
	}
 

	
 
	/* Generic feature callbacks are evaluated in reverse (i.e. the last group
 
	 * to be added is evaluated first, etc) thus we push the group to the
 
	 * beginning of the list so a standard iterator will do the right thing. */
 
	_gcl[feature].push_front(GenericCallback(file, group));
 
}
 

	
 
/* virtual */ uint32 GenericScopeResolver::GetVariable(byte variable, uint32 parameter, bool *available) const
 
{
 
	if (this->ai_callback) {
 
		switch (variable) {
 
			case 0x40: return this->ro->grffile->cargo_map[this->cargo_type];
 
			case 0x40: return this->ro.grffile->cargo_map[this->cargo_type];
 

	
 
			case 0x80: return this->cargo_type;
 
			case 0x81: return CargoSpec::Get(this->cargo_type)->bitnum;
 
			case 0x82: return this->default_selection;
 
			case 0x83: return this->src_industry;
 
			case 0x84: return this->dst_industry;
 
			case 0x85: return this->distance;
 
			case 0x86: return this->event;
 
			case 0x87: return this->count;
 
			case 0x88: return this->station_size;
 

	
 
			default: break;
 
@@ -130,68 +130,68 @@ void AddGenericCallback(uint8 feature, c
 
/* virtual */ const SpriteGroup *GenericResolverObject::ResolveReal(const RealSpriteGroup *group) const
 
{
 
	if (group->num_loaded == 0) return NULL;
 

	
 
	return group->loaded[0];
 
}
 

	
 
/**
 
 * Generic resolver.
 
 * @param ai_callback Callback comes from the AI.
 
 * @param callback Callback ID.
 
 */
 
GenericResolverObject::GenericResolverObject(bool ai_callback, CallbackID callback) : ResolverObject(NULL, callback), generic_scope(this, ai_callback)
 
GenericResolverObject::GenericResolverObject(bool ai_callback, CallbackID callback) : ResolverObject(NULL, callback), generic_scope(*this, ai_callback)
 
{
 
}
 

	
 
/**
 
 * Generic scope resolver.
 
 * @param ro Surrounding resolver.
 
 * @param ai_callback Callback comes from the AI.
 
 */
 
GenericScopeResolver::GenericScopeResolver(ResolverObject *ro, bool ai_callback) : ScopeResolver(ro)
 
GenericScopeResolver::GenericScopeResolver(ResolverObject &ro, bool ai_callback) : ScopeResolver(ro)
 
{
 
	this->cargo_type = 0;
 
	this->default_selection = 0;
 
	this->src_industry = 0;
 
	this->dst_industry = 0;
 
	this->distance = 0;
 
	this->event = (AIConstructionEvent)0;
 
	this->count = 0;
 
	this->station_size = 0;
 
	this->ai_callback = ai_callback;
 
}
 

	
 

	
 
/**
 
 * Follow a generic feature callback list and return the first successful
 
 * answer
 
 * @param feature GRF Feature of callback
 
 * @param object  pre-populated resolver object
 
 * @param param1_grfv7 callback_param1 for GRFs up to version 7.
 
 * @param param1_grfv8 callback_param1 for GRFs from version 8 on.
 
 * @param [out] file Optionally returns the GRFFile which made the final decision for the callback result.
 
 *                   May be NULL if not required.
 
 * @return callback value if successful or CALLBACK_FAILED
 
 */
 
static uint16 GetGenericCallbackResult(uint8 feature, ResolverObject *object, uint32 param1_grfv7, uint32 param1_grfv8, const GRFFile **file)
 
static uint16 GetGenericCallbackResult(uint8 feature, ResolverObject &object, uint32 param1_grfv7, uint32 param1_grfv8, const GRFFile **file)
 
{
 
	assert(feature < lengthof(_gcl));
 

	
 
	/* Test each feature callback sprite group. */
 
	for (GenericCallbackList::const_iterator it = _gcl[feature].begin(); it != _gcl[feature].end(); ++it) {
 
		const SpriteGroup *group = it->group;
 
		object->grffile = it->file;
 
		object.grffile = it->file;
 
		/* Set callback param based on GRF version. */
 
		object->callback_param1 = it->file->grf_version >= 8 ? param1_grfv8 : param1_grfv7;
 
		object.callback_param1 = it->file->grf_version >= 8 ? param1_grfv8 : param1_grfv7;
 
		group = SpriteGroup::Resolve(group, object);
 
		if (group == NULL || group->GetCallbackResult() == CALLBACK_FAILED) continue;
 

	
 
		/* Return NewGRF file if necessary */
 
		if (file != NULL) *file = it->file;
 

	
 
		return group->GetCallbackResult();
 
	}
 

	
 
	/* No callback returned a valid result, so we've failed. */
 
	return CALLBACK_FAILED;
 
}
 
@@ -229,25 +229,25 @@ uint16 GetAiPurchaseCallbackResult(uint8
 
		if (is->grf_prop.subst_id != INVALID_INDUSTRYTYPE) dst_industry = is->grf_prop.subst_id;
 
	}
 

	
 
	object.generic_scope.cargo_type        = cargo_type;
 
	object.generic_scope.default_selection = default_selection;
 
	object.generic_scope.src_industry      = src_industry;
 
	object.generic_scope.dst_industry      = dst_industry;
 
	object.generic_scope.distance          = distance;
 
	object.generic_scope.event             = event;
 
	object.generic_scope.count             = count;
 
	object.generic_scope.station_size      = station_size;
 

	
 
	uint16 callback = GetGenericCallbackResult(feature, &object, 0, 0, file);
 
	uint16 callback = GetGenericCallbackResult(feature, object, 0, 0, file);
 
	if (callback != CALLBACK_FAILED) callback = GB(callback, 0, 8);
 
	return callback;
 
}
 

	
 

	
 
/**
 
 * 'Execute' the ambient sound effect callback.
 
 * @param tile Tile the sound effect should be generated for.
 
 */
 
void AmbientSoundEffectCallback(TileIndex tile)
 
{
 
	assert(IsTileType(tile, MP_CLEAR) || IsTileType(tile, MP_TREES) || IsTileType(tile, MP_WATER));
 
@@ -255,16 +255,16 @@ void AmbientSoundEffectCallback(TileInde
 
	/* Only run every 1/200-th time. */
 
	uint32 r; // Save for later
 
	if (!Chance16R(1, 200, r) || !_settings_client.sound.ambient) return;
 

	
 
	/* Prepare resolver object. */
 
	GenericResolverObject object(false, CBID_SOUNDS_AMBIENT_EFFECT);
 

	
 
	uint32 param1_v7 = GetTileType(tile) << 28 | Clamp(TileHeight(tile), 0, 15) << 24 | GB(r, 16, 8) << 16 | GetTerrainType(tile);
 
	uint32 param1_v8 = GetTileType(tile) << 24 | GetTileZ(tile) << 16 | GB(r, 16, 8) << 8 | (HasTileWaterClass(tile) ? GetWaterClass(tile) : 0) << 3 | GetTerrainType(tile);
 

	
 
	/* Run callback. */
 
	const GRFFile *grf_file;
 
	uint16 callback = GetGenericCallbackResult(GSF_SOUNDFX, &object, param1_v7, param1_v8, &grf_file);
 
	uint16 callback = GetGenericCallbackResult(GSF_SOUNDFX, object, param1_v7, param1_v8, &grf_file);
 

	
 
	if (callback != CALLBACK_FAILED) PlayTileSound(grf_file, callback, tile);
 
}
src/newgrf_house.cpp
Show inline comments
 
@@ -30,25 +30,25 @@ static HouseClassMapping _class_mapping[
 
HouseOverrideManager _house_mngr(NEW_HOUSE_OFFSET, NUM_HOUSES, INVALID_HOUSE_ID);
 

	
 
/**
 
 * Constructor of a house scope resolver.
 
 * @param ro Surrounding resolver.
 
 * @param house_id House type being queried.
 
 * @param tile %Tile containing the house.
 
 * @param town %Town containing the house.
 
 * @param not_yet_constructed House is still under construction.
 
 * @param initial_random_bits Random bits during construction checks.
 
 * @param watched_cargo_triggers Cargo types that triggered the watched cargo callback.
 
 */
 
HouseScopeResolver::HouseScopeResolver(ResolverObject *ro, HouseID house_id, TileIndex tile, Town *town,
 
HouseScopeResolver::HouseScopeResolver(ResolverObject &ro, HouseID house_id, TileIndex tile, Town *town,
 
			bool not_yet_constructed, uint8 initial_random_bits, uint32 watched_cargo_triggers)
 
		: ScopeResolver(ro)
 
{
 
	this->house_id = house_id;
 
	this->tile = tile;
 
	this->town = town;
 
	this->not_yet_constructed = not_yet_constructed;
 
	this->initial_random_bits = initial_random_bits;
 
	this->watched_cargo_triggers = watched_cargo_triggers;
 
}
 

	
 
/**
 
@@ -69,26 +69,26 @@ static const GRFFile *GetHouseSpecGrf(Ho
 
 * @param town %Town containing the house.
 
 * @param callback Callback ID.
 
 * @param param1 First parameter (var 10) of the callback.
 
 * @param param2 Second parameter (var 18) of the callback.
 
 * @param not_yet_constructed House is still under construction.
 
 * @param initial_random_bits Random bits during construction checks.
 
 * @param watched_cargo_triggers Cargo types that triggered the watched cargo callback.
 
 */
 
HouseResolverObject::HouseResolverObject(HouseID house_id, TileIndex tile, Town *town,
 
		CallbackID callback, uint32 param1, uint32 param2,
 
		bool not_yet_constructed, uint8 initial_random_bits, uint32 watched_cargo_triggers)
 
	: ResolverObject(GetHouseSpecGrf(house_id), callback, param1, param2),
 
	house_scope(this, house_id, tile, town, not_yet_constructed, initial_random_bits, watched_cargo_triggers),
 
	town_scope(this, town, not_yet_constructed) // Don't access StorePSA if house is not yet constructed.
 
	house_scope(*this, house_id, tile, town, not_yet_constructed, initial_random_bits, watched_cargo_triggers),
 
	town_scope(*this, town, not_yet_constructed) // Don't access StorePSA if house is not yet constructed.
 
{
 
}
 

	
 
HouseClassID AllocateHouseClassID(byte grf_class_id, uint32 grfid)
 
{
 
	/* Start from 1 because 0 means that no class has been assigned. */
 
	for (int i = 1; i != lengthof(_class_mapping); i++) {
 
		HouseClassMapping *map = &_class_mapping[i];
 

	
 
		if (map->class_id == grf_class_id && map->grfid == grfid) return (HouseClassID)i;
 

	
 
		if (map->class_id == 0 && map->grfid == 0) {
 
@@ -343,35 +343,35 @@ static uint32 GetDistanceFromNearbyHouse
 
		case 0x60: return parameter < NEW_HOUSE_OFFSET ? GetNumHouses(parameter, this->town) : 0;
 

	
 
		/* Building counts for new houses with id = parameter. */
 
		case 0x61: {
 
			const HouseSpec *hs = HouseSpec::Get(this->house_id);
 
			if (hs->grf_prop.grffile == NULL) return 0;
 

	
 
			HouseID new_house = _house_mngr.GetID(parameter, hs->grf_prop.grffile->grfid);
 
			return new_house == INVALID_HOUSE_ID ? 0 : GetNumHouses(new_house, this->town);
 
		}
 

	
 
		/* Land info for nearby tiles. */
 
		case 0x62: return GetNearbyTileInformation(parameter, this->tile, this->ro->grffile->grf_version >= 8);
 
		case 0x62: return GetNearbyTileInformation(parameter, this->tile, this->ro.grffile->grf_version >= 8);
 

	
 
		/* Current animation frame of nearby house tiles */
 
		case 0x63: {
 
			TileIndex testtile = GetNearbyTile(parameter, this->tile);
 
			return IsTileType(testtile, MP_HOUSE) ? GetAnimationFrame(testtile) : 0;
 
		}
 

	
 
		/* Cargo acceptance history of nearby stations */
 
		case 0x64: {
 
			CargoID cid = GetCargoTranslation(parameter, this->ro->grffile);
 
			CargoID cid = GetCargoTranslation(parameter, this->ro.grffile);
 
			if (cid == CT_INVALID) return 0;
 

	
 
			/* Extract tile offset. */
 
			int8 x_offs = GB(GetRegister(0x100), 0, 8);
 
			int8 y_offs = GB(GetRegister(0x100), 8, 8);
 
			TileIndex testtile = TILE_MASK(this->tile + TileDiffXY(x_offs, y_offs));
 

	
 
			StationFinder stations(TileArea(testtile, 1, 1));
 
			const StationList *sl = stations.GetStations();
 

	
 
			/* Collect acceptance stats. */
 
			uint32 res = 0;
 
@@ -391,33 +391,33 @@ static uint32 GetDistanceFromNearbyHouse
 

	
 
		/* Distance test for some house types */
 
		case 0x65: return GetDistanceFromNearbyHouse(parameter, this->tile, this->house_id);
 

	
 
		/* Class and ID of nearby house tile */
 
		case 0x66: {
 
			TileIndex testtile = GetNearbyTile(parameter, this->tile);
 
			if (!IsTileType(testtile, MP_HOUSE)) return 0xFFFFFFFF;
 
			HouseSpec *hs = HouseSpec::Get(GetHouseType(testtile));
 
			/* Information about the grf local classid if the house has a class */
 
			uint houseclass = 0;
 
			if (hs->class_id != HOUSE_NO_CLASS) {
 
				houseclass = (hs->grf_prop.grffile == this->ro->grffile ? 1 : 2) << 8;
 
				houseclass = (hs->grf_prop.grffile == this->ro.grffile ? 1 : 2) << 8;
 
				houseclass |= _class_mapping[hs->class_id].class_id;
 
			}
 
			/* old house type or grf-local houseid */
 
			uint local_houseid = 0;
 
			if (this->house_id < NEW_HOUSE_OFFSET) {
 
				local_houseid = this->house_id;
 
			} else {
 
				local_houseid = (hs->grf_prop.grffile == this->ro->grffile ? 1 : 2) << 8;
 
				local_houseid = (hs->grf_prop.grffile == this->ro.grffile ? 1 : 2) << 8;
 
				local_houseid |= hs->grf_prop.local_id;
 
			}
 
			return houseclass << 16 | local_houseid;
 
		}
 

	
 
		/* GRFID of nearby house tile */
 
		case 0x67: {
 
			TileIndex testtile = GetNearbyTile(parameter, this->tile);
 
			if (!IsTileType(testtile, MP_HOUSE)) return 0xFFFFFFFF;
 
			HouseID house_id = GetHouseType(testtile);
 
			if (house_id < NEW_HOUSE_OFFSET) return 0;
 
			/* Checking the grffile information via HouseSpec doesn't work
 
@@ -431,25 +431,25 @@ static uint32 GetDistanceFromNearbyHouse
 
	*available = false;
 
	return UINT_MAX;
 
}
 

	
 
uint16 GetHouseCallback(CallbackID callback, uint32 param1, uint32 param2, HouseID house_id, Town *town, TileIndex tile,
 
		bool not_yet_constructed, uint8 initial_random_bits, uint32 watched_cargo_triggers)
 
{
 
	assert(IsValidTile(tile) && (not_yet_constructed || IsTileType(tile, MP_HOUSE)));
 

	
 
	HouseResolverObject object(house_id, tile, town, callback, param1, param2,
 
			not_yet_constructed, initial_random_bits, watched_cargo_triggers);
 

	
 
	const SpriteGroup *group = SpriteGroup::Resolve(HouseSpec::Get(house_id)->grf_prop.spritegroup[0], &object);
 
	const SpriteGroup *group = SpriteGroup::Resolve(HouseSpec::Get(house_id)->grf_prop.spritegroup[0], object);
 
	if (group == NULL) return CALLBACK_FAILED;
 

	
 
	return group->GetCallbackResult();
 
}
 

	
 
static void DrawTileLayout(const TileInfo *ti, const TileLayoutSpriteGroup *group, byte stage, HouseID house_id)
 
{
 
	const DrawTileSprites *dts = group->ProcessRegisters(&stage);
 

	
 
	const HouseSpec *hs = HouseSpec::Get(house_id);
 
	PaletteID palette = hs->random_colour[TileHash2Bit(ti->x, ti->y)] + PALETTE_RECOLOUR_START;
 
	if (HasBit(hs->callback_mask, CBM_HOUSE_COLOUR)) {
 
@@ -481,25 +481,25 @@ void DrawNewHouseTile(TileInfo *ti, Hous
 
		bool draw_old_one = true;
 
		if (HasBit(hs->callback_mask, CBM_HOUSE_DRAW_FOUNDATIONS)) {
 
			/* Called to determine the type (if any) of foundation to draw for the house tile */
 
			uint32 callback_res = GetHouseCallback(CBID_HOUSE_DRAW_FOUNDATIONS, 0, 0, house_id, Town::GetByTile(ti->tile), ti->tile);
 
			if (callback_res != CALLBACK_FAILED) draw_old_one = ConvertBooleanCallback(hs->grf_prop.grffile, CBID_HOUSE_DRAW_FOUNDATIONS, callback_res);
 
		}
 

	
 
		if (draw_old_one) DrawFoundation(ti, FOUNDATION_LEVELED);
 
	}
 

	
 
	HouseResolverObject object(house_id, ti->tile, Town::GetByTile(ti->tile));
 

	
 
	const SpriteGroup *group = SpriteGroup::Resolve(hs->grf_prop.spritegroup[0], &object);
 
	const SpriteGroup *group = SpriteGroup::Resolve(hs->grf_prop.spritegroup[0], object);
 
	if (group != NULL && group->type == SGT_TILELAYOUT) {
 
		/* Limit the building stage to the number of stages supplied. */
 
		const TileLayoutSpriteGroup *tlgroup = (const TileLayoutSpriteGroup *)group;
 
		byte stage = GetHouseBuildingStage(ti->tile);
 
		DrawTileLayout(ti, tlgroup, stage, house_id);
 
	}
 
}
 

	
 
/* Simple wrapper for GetHouseCallback to keep the animation unified. */
 
uint16 GetSimpleHouseCallback(CallbackID callback, uint32 param1, uint32 param2, const HouseSpec *spec, Town *town, TileIndex tile, uint32 extra_data)
 
{
 
	return GetHouseCallback(callback, param1, param2, spec - HouseSpec::Get(0), town, tile, false, 0, extra_data);
 
@@ -606,25 +606,25 @@ static void DoTriggerHouse(TileIndex til
 
{
 
	/* We can't trigger a non-existent building... */
 
	assert(IsTileType(tile, MP_HOUSE));
 

	
 
	HouseID hid = GetHouseType(tile);
 
	HouseSpec *hs = HouseSpec::Get(hid);
 

	
 
	if (hs->grf_prop.spritegroup[0] == NULL) return;
 

	
 
	HouseResolverObject object(hid, tile, Town::GetByTile(tile), CBID_RANDOM_TRIGGER);
 
	object.trigger = trigger;
 

	
 
	const SpriteGroup *group = SpriteGroup::Resolve(hs->grf_prop.spritegroup[0], &object);
 
	const SpriteGroup *group = SpriteGroup::Resolve(hs->grf_prop.spritegroup[0], object);
 
	if (group == NULL) return;
 

	
 
	byte new_random_bits = Random();
 
	byte random_bits = GetHouseRandomBits(tile);
 
	uint32 reseed = object.GetReseedSum(); // The scope only affects triggers, not the reseeding
 
	random_bits &= ~reseed;
 
	random_bits |= (first ? new_random_bits : base_random) & reseed;
 
	SetHouseRandomBits(tile, random_bits);
 

	
 
	switch (trigger) {
 
		case HOUSE_TRIGGER_TILE_LOOP:
 
			/* Random value already set. */
src/newgrf_house.h
Show inline comments
 
@@ -18,25 +18,25 @@
 
#include "newgrf_spritegroup.h"
 
#include "newgrf_town.h"
 

	
 
/** Scope resolver for houses. */
 
struct HouseScopeResolver : public ScopeResolver {
 
	HouseID house_id;              ///< Type of house being queried.
 
	TileIndex tile;                ///< Tile of this house.
 
	Town *town;                    ///< Town of this house.
 
	bool not_yet_constructed;      ///< True for construction check.
 
	uint16 initial_random_bits;    ///< Random bits during construction checks.
 
	uint32 watched_cargo_triggers; ///< Cargo types that triggered the watched cargo callback.
 

	
 
	HouseScopeResolver(ResolverObject *ro, HouseID house_id, TileIndex tile, Town *town,
 
	HouseScopeResolver(ResolverObject &ro, HouseID house_id, TileIndex tile, Town *town,
 
			bool not_yet_constructed, uint8 initial_random_bits, uint32 watched_cargo_triggers);
 

	
 
	/* virtual */ uint32 GetRandomBits() const;
 
	/* virtual */ uint32 GetVariable(byte variable, uint32 parameter, bool *available) const;
 
	/* virtual */ uint32 GetTriggers() const;
 
	/* virtual */ void SetTriggers(int triggers) const;
 
};
 

	
 
/** Resolver object to be used for houses (feature 07 spritegroups). */
 
struct HouseResolverObject : public ResolverObject {
 
	HouseScopeResolver house_scope;
 
	TownScopeResolver  town_scope;
src/newgrf_industries.cpp
Show inline comments
 
@@ -150,25 +150,25 @@ static uint32 GetCountAndDistanceOfClose
 
			if (i->type == ind_index && i != current && (i->selected_layout == layout_filter || layout_filter == 0) && (!town_filter || i->town == current->town)) {
 
				closest_dist = min(closest_dist, DistanceManhattan(current->location.tile, i->location.tile));
 
				count++;
 
			}
 
		}
 
	}
 

	
 
	return count << 16 | GB(closest_dist, 0, 16);
 
}
 

	
 
/* virtual */ uint32 IndustriesScopeResolver::GetVariable(byte variable, uint32 parameter, bool *available) const
 
{
 
	if (this->ro->callback == CBID_INDUSTRY_LOCATION) {
 
	if (this->ro.callback == CBID_INDUSTRY_LOCATION) {
 
		/* Variables available during construction check. */
 

	
 
		switch (variable) {
 
			case 0x80: return this->tile;
 
			case 0x81: return GB(this->tile, 8, 8);
 

	
 
			/* Pointer to the town the industry is associated with */
 
			case 0x82: return this->industry->town->index;
 
			case 0x83:
 
			case 0x84:
 
			case 0x85: DEBUG(grf, 0, "NewGRFs shouldn't be doing pointer magic"); break; // not supported
 

	
 
@@ -176,41 +176,41 @@ static uint32 GetCountAndDistanceOfClose
 
			case 0x86: return this->industry->selected_layout;
 

	
 
			/* Ground type */
 
			case 0x87: return GetTerrainType(this->tile);
 

	
 
			/* Town zone */
 
			case 0x88: return GetTownRadiusGroup(this->industry->town, this->tile);
 

	
 
			/* Manhattan distance of the closest town */
 
			case 0x89: return min(DistanceManhattan(this->industry->town->xy, this->tile), 255);
 

	
 
			/* Lowest height of the tile */
 
			case 0x8A: return Clamp(GetTileZ(this->tile) * (this->ro->grffile->grf_version >= 8 ? 1 : TILE_HEIGHT), 0, 0xFF);
 
			case 0x8A: return Clamp(GetTileZ(this->tile) * (this->ro.grffile->grf_version >= 8 ? 1 : TILE_HEIGHT), 0, 0xFF);
 

	
 
			/* Distance to the nearest water/land tile */
 
			case 0x8B: return GetClosestWaterDistance(this->tile, (GetIndustrySpec(this->industry->type)->behaviour & INDUSTRYBEH_BUILT_ONWATER) == 0);
 

	
 
			/* Square of Euclidian distance from town */
 
			case 0x8D: return min(DistanceSquare(this->industry->town->xy, this->tile), 65535);
 

	
 
			/* 32 random bits */
 
			case 0x8F: return this->random_bits;
 
		}
 
	}
 

	
 
	const IndustrySpec *indspec = GetIndustrySpec(this->type);
 

	
 
	if (this->industry == NULL) {
 
		DEBUG(grf, 1, "Unhandled variable 0x%X (no available industry) in callback 0x%x", variable, this->ro->callback);
 
		DEBUG(grf, 1, "Unhandled variable 0x%X (no available industry) in callback 0x%x", variable, this->ro.callback);
 

	
 
		*available = false;
 
		return UINT_MAX;
 
	}
 

	
 
	switch (variable) {
 
		case 0x40:
 
		case 0x41:
 
		case 0x42: { // waiting cargo, but only if those two callback flags are set
 
			uint16 callback = indspec->callback_mask;
 
			if (HasBit(callback, CBM_IND_PRODUCTION_CARGO_ARRIVAL) || HasBit(callback, CBM_IND_PRODUCTION_256_TICKS)) {
 
				if ((indspec->behaviour & INDUSTRYBEH_PROD_MULTI_HNDLING) != 0) {
 
@@ -242,37 +242,37 @@ static uint32 GetCountAndDistanceOfClose
 
				const Livery *l = &c->livery[LS_DEFAULT];
 

	
 
				is_ai = c->is_ai;
 
				colours = l->colour1 + l->colour2 * 16;
 
			}
 

	
 
			return this->industry->founder | (is_ai ? 0x10000 : 0) | (colours << 24);
 
		}
 

	
 
		case 0x46: return this->industry->construction_date; // Date when built - long format - (in days)
 

	
 
		/* Get industry ID at offset param */
 
		case 0x60: return GetIndustryIDAtOffset(GetNearbyTile(parameter, this->industry->location.tile, false), this->industry, this->ro->grffile->grfid);
 
		case 0x60: return GetIndustryIDAtOffset(GetNearbyTile(parameter, this->industry->location.tile, false), this->industry, this->ro.grffile->grfid);
 

	
 
		/* Get random tile bits at offset param */
 
		case 0x61: {
 
			if (this->tile == INVALID_TILE) break;
 
			TileIndex tile = GetNearbyTile(parameter, this->tile, false);
 
			return this->industry->TileBelongsToIndustry(tile) ? GetIndustryRandomBits(tile) : 0;
 
		}
 

	
 
		/* Land info of nearby tiles */
 
		case 0x62:
 
			if (this->tile == INVALID_TILE) break;
 
			return GetNearbyIndustryTileInformation(parameter, this->tile, INVALID_INDUSTRY, false, this->ro->grffile->grf_version >= 8);
 
			return GetNearbyIndustryTileInformation(parameter, this->tile, INVALID_INDUSTRY, false, this->ro.grffile->grf_version >= 8);
 

	
 
		/* Animation stage of nearby tiles */
 
		case 0x63: {
 
			if (this->tile == INVALID_TILE) break;
 
			TileIndex tile = GetNearbyTile(parameter, this->tile, false);
 
			if (this->industry->TileBelongsToIndustry(tile)) {
 
				return GetAnimationFrame(tile);
 
			}
 
			return 0xFFFFFFFF;
 
		}
 

	
 
		/* Distance of nearest industry of given type */
 
@@ -420,25 +420,25 @@ static const GRFFile *GetGrffile(Industr
 
 * Constructor of the industries resolver.
 
 * @param tile %Tile owned by the industry.
 
 * @param industry %Industry being resolved.
 
 * @param type Type of the industry.
 
 * @param random_bits Random bits of the new industry.
 
 * @param callback Callback ID.
 
 * @param callback_param1 First parameter (var 10) of the callback.
 
 * @param callback_param2 Second parameter (var 18) of the callback.
 
 */
 
IndustriesResolverObject::IndustriesResolverObject(TileIndex tile, Industry *indus, IndustryType type, uint32 random_bits,
 
		CallbackID callback, uint32 callback_param1, uint32 callback_param2)
 
	: ResolverObject(GetGrffile(type), callback, callback_param1, callback_param2),
 
	industries_scope(this, tile, indus, type, random_bits),
 
	industries_scope(*this, tile, indus, type, random_bits),
 
	town_scope(NULL)
 
{
 
}
 

	
 
IndustriesResolverObject::~IndustriesResolverObject()
 
{
 
	delete this->town_scope;
 
}
 

	
 
/**
 
 * Get or create the town scope object associated with the industry.
 
 * @return The associated town scope, if it exists.
 
@@ -446,60 +446,60 @@ IndustriesResolverObject::~IndustriesRes
 
TownScopeResolver *IndustriesResolverObject::GetTown()
 
{
 
	if (this->town_scope == NULL) {
 
		Town *t = NULL;
 
		bool readonly = true;
 
		if (this->industries_scope.industry != NULL) {
 
			t = this->industries_scope.industry->town;
 
			readonly = this->industries_scope.industry->index == INVALID_INDUSTRY;
 
		} else if (this->industries_scope.tile != INVALID_TILE) {
 
			t = ClosestTownFromTile(this->industries_scope.tile, UINT_MAX);
 
		}
 
		if (t == NULL) return NULL;
 
		this->town_scope = new TownScopeResolver(this, t, readonly);
 
		this->town_scope = new TownScopeResolver(*this, t, readonly);
 
	}
 
	return this->town_scope;
 
}
 

	
 
/**
 
 * Scope resolver for industries.
 
 * @param ro Surrounding resolver.
 
 * @param tile %Tile owned by the industry.
 
 * @param industry %Industry being resolved.
 
 * @param type Type of the industry.
 
 * @param random_bits Random bits of the new industry.
 
 */
 
IndustriesScopeResolver::IndustriesScopeResolver(ResolverObject *ro, TileIndex tile, Industry *industry, IndustryType type, uint32 random_bits)
 
IndustriesScopeResolver::IndustriesScopeResolver(ResolverObject &ro, TileIndex tile, Industry *industry, IndustryType type, uint32 random_bits)
 
	: ScopeResolver(ro)
 
{
 
	this->tile = tile;
 
	this->industry = industry;
 
	this->type = type;
 
	this->random_bits = random_bits;
 
}
 

	
 
/**
 
 * Perform an industry callback.
 
 * @param callback The callback to perform.
 
 * @param param1 The first parameter.
 
 * @param param2 The second parameter.
 
 * @param industry The industry to do the callback for.
 
 * @param type The type of industry to do the callback for.
 
 * @param tile The tile associated with the callback.
 
 * @return The callback result.
 
 */
 
uint16 GetIndustryCallback(CallbackID callback, uint32 param1, uint32 param2, Industry *industry, IndustryType type, TileIndex tile)
 
{
 
	IndustriesResolverObject object(tile, industry, type, 0, callback, param1, param2);
 
	const SpriteGroup *group = SpriteGroup::Resolve(GetIndustrySpec(type)->grf_prop.spritegroup[0], &object);
 
	const SpriteGroup *group = SpriteGroup::Resolve(GetIndustrySpec(type)->grf_prop.spritegroup[0], object);
 
	if (group == NULL) return CALLBACK_FAILED;
 

	
 
	return group->GetCallbackResult();
 
}
 

	
 
/**
 
 * Check that the industry callback allows creation of the industry.
 
 * @param tile %Tile to build the industry.
 
 * @param type Type of industry to build.
 
 * @param layout Layout number.
 
 * @param seed Seed for the random generator.
 
 * @param initial_random_bits The random bits the industry is going to have after construction.
 
@@ -514,25 +514,25 @@ CommandCost CheckIfCallBackAllowsCreatio
 
	Industry ind;
 
	ind.index = INVALID_INDUSTRY;
 
	ind.location.tile = tile;
 
	ind.location.w = 0; // important to mark the industry invalid
 
	ind.type = type;
 
	ind.selected_layout = layout;
 
	ind.town = ClosestTownFromTile(tile, UINT_MAX);
 
	ind.random = initial_random_bits;
 
	ind.founder = founder;
 
	ind.psa = NULL;
 

	
 
	IndustriesResolverObject object(tile, &ind, type, seed, CBID_INDUSTRY_LOCATION, 0, creation_type);
 
	const SpriteGroup *group = SpriteGroup::Resolve(GetIndustrySpec(type)->grf_prop.spritegroup[0], &object);
 
	const SpriteGroup *group = SpriteGroup::Resolve(GetIndustrySpec(type)->grf_prop.spritegroup[0], object);
 

	
 
	/* Unlike the "normal" cases, not having a valid result means we allow
 
	 * the building of the industry, as that's how it's done in TTDP. */
 
	if (group == NULL) return CommandCost();
 
	uint16 result = group->GetCallbackResult();
 
	if (result == CALLBACK_FAILED) return CommandCost();
 

	
 
	return GetErrorMessageFromLocationCallbackResult(result, indspec->grf_prop.grffile->grfid, STR_ERROR_SITE_UNSUITABLE);
 
}
 

	
 
/**
 
 * Check with callback #CBID_INDUSTRY_PROBABILITY whether the industry can be built.
 
@@ -587,25 +587,25 @@ void IndustryProductionCallback(Industry
 
		 * 'loop' is provided as 16 bits to the newgrf, so abort when those are exceeded. */
 
		if (loop >= 0x10000) {
 
			/* display error message */
 
			SetDParamStr(0, spec->grf_prop.grffile->filename);
 
			SetDParam(1, spec->name);
 
			ShowErrorMessage(STR_NEWGRF_BUGGY, STR_NEWGRF_BUGGY_ENDLESS_PRODUCTION_CALLBACK, WL_WARNING);
 

	
 
			/* abort the function early, this error isn't critical and will allow the game to continue to run */
 
			break;
 
		}
 

	
 
		SB(object.callback_param2, 8, 16, loop);
 
		const SpriteGroup *tgroup = SpriteGroup::Resolve(spec->grf_prop.spritegroup[0], &object);
 
		const SpriteGroup *tgroup = SpriteGroup::Resolve(spec->grf_prop.spritegroup[0], object);
 
		if (tgroup == NULL || tgroup->type != SGT_INDUSTRY_PRODUCTION) break;
 
		const IndustryProductionSpriteGroup *group = (const IndustryProductionSpriteGroup *)tgroup;
 

	
 
		bool deref = (group->version == 1);
 

	
 
		for (uint i = 0; i < 3; i++) {
 
			ind->incoming_cargo_waiting[i] = Clamp(ind->incoming_cargo_waiting[i] - DerefIndProd(group->subtract_input[i], deref) * multiplier, 0, 0xFFFF);
 
		}
 
		for (uint i = 0; i < 2; i++) {
 
			ind->produced_cargo_waiting[i] = Clamp(ind->produced_cargo_waiting[i] + max(DerefIndProd(group->add_output[i], deref), 0) * multiplier, 0, 0xFFFF);
 
		}
 

	
src/newgrf_industries.h
Show inline comments
 
@@ -12,25 +12,25 @@
 
#ifndef NEWGRF_INDUSTRIES_H
 
#define NEWGRF_INDUSTRIES_H
 

	
 
#include "newgrf_town.h"
 

	
 
/** Resolver for industry scopes. */
 
struct IndustriesScopeResolver : public ScopeResolver {
 
	TileIndex tile;     ///< Tile owned by the industry.
 
	Industry *industry; ///< %Industry being resolved.
 
	IndustryType type;  ///< Type of the industry.
 
	uint32 random_bits; ///< Random bits of the new industry.
 

	
 
	IndustriesScopeResolver(ResolverObject *ro, TileIndex tile, Industry *industry, IndustryType type, uint32 random_bits = 0);
 
	IndustriesScopeResolver(ResolverObject &ro, TileIndex tile, Industry *industry, IndustryType type, uint32 random_bits = 0);
 

	
 
	/* virtual */ uint32 GetRandomBits() const;
 
	/* virtual */ uint32 GetVariable(byte variable, uint32 parameter, bool *available) const;
 
	/* virtual */ uint32 GetTriggers() const;
 
	/* virtual */ void SetTriggers(int triggers) const;
 
	/* virtual */ void StorePSA(uint pos, int32 value);
 
};
 

	
 
/** Resolver for industries. */
 
struct IndustriesResolverObject : public ResolverObject {
 
	IndustriesScopeResolver industries_scope; ///< Scope resolver for the industry.
 
	TownScopeResolver *town_scope;            ///< Scope resolver for the associated town (if needed and available, else \c NULL).
src/newgrf_industrytiles.cpp
Show inline comments
 
@@ -69,37 +69,37 @@ uint32 GetRelativePosition(TileIndex til
 

	
 
		/* Current town zone of the tile in the nearest town */
 
		case 0x42: return GetTownRadiusGroup(ClosestTownFromTile(this->tile, UINT_MAX), this->tile);
 

	
 
		/* Relative position */
 
		case 0x43: return GetRelativePosition(this->tile, this->industry->location.tile);
 

	
 
		/* Animation frame. Like house variable 46 but can contain anything 0..FF. */
 
		case 0x44: return IsTileType(this->tile, MP_INDUSTRY) ? GetAnimationFrame(this->tile) : 0;
 

	
 
		/* Land info of nearby tiles */
 
		case 0x60: return GetNearbyIndustryTileInformation(parameter, this->tile,
 
				this->industry == NULL ? (IndustryID)INVALID_INDUSTRY : this->industry->index, true, this->ro->grffile->grf_version >= 8);
 
				this->industry == NULL ? (IndustryID)INVALID_INDUSTRY : this->industry->index, true, this->ro.grffile->grf_version >= 8);
 

	
 
		/* Animation stage of nearby tiles */
 
		case 0x61: {
 
			TileIndex tile = GetNearbyTile(parameter, this->tile);
 
			if (IsTileType(tile, MP_INDUSTRY) && Industry::GetByTile(tile) == this->industry) {
 
				return GetAnimationFrame(tile);
 
			}
 
			return UINT_MAX;
 
		}
 

	
 
		/* Get industry tile ID at offset */
 
		case 0x62: return GetIndustryIDAtOffset(GetNearbyTile(parameter, this->tile), this->industry, this->ro->grffile->grfid);
 
		case 0x62: return GetIndustryIDAtOffset(GetNearbyTile(parameter, this->tile), this->industry, this->ro.grffile->grfid);
 
	}
 

	
 
	DEBUG(grf, 1, "Unhandled industry tile variable 0x%X", variable);
 

	
 
	*available = false;
 
	return UINT_MAX;
 
}
 

	
 
/* virtual */ uint32 IndustryTileScopeResolver::GetRandomBits() const
 
{
 
	assert(this->industry != NULL && IsValidTile(this->tile));
 
	assert(this->industry->index == INVALID_INDUSTRY || IsTileType(this->tile, MP_INDUSTRY));
 
@@ -135,36 +135,36 @@ static const GRFFile *GetIndTileGrffile(
 
/**
 
 * Constructor of the industry tiles scope resolver.
 
 * @param gfx Graphics of the industry.
 
 * @param tile %Tile of the industry.
 
 * @param indus %Industry owning the tile.
 
 * @param callback Callback ID.
 
 * @param callback_param1 First parameter (var 10) of the callback.
 
 * @param callback_param2 Second parameter (var 18) of the callback.
 
 */
 
IndustryTileResolverObject::IndustryTileResolverObject(IndustryGfx gfx, TileIndex tile, Industry *indus,
 
			CallbackID callback, uint32 callback_param1, uint32 callback_param2)
 
	: ResolverObject(GetIndTileGrffile(gfx), callback, callback_param1, callback_param2),
 
	indtile_scope(this, indus, tile),
 
	ind_scope(this, tile, indus, indus->type)
 
	indtile_scope(*this, indus, tile),
 
	ind_scope(*this, tile, indus, indus->type)
 
{
 
}
 

	
 
/**
 
 * Constructor of the scope resolver for the industry tile.
 
 * @param ro Surrounding resolver.
 
 * @param industry %Industry owning the tile.
 
 * @param tile %Tile of the industry.
 
 */
 
IndustryTileScopeResolver::IndustryTileScopeResolver(ResolverObject *ro, Industry *industry, TileIndex tile) : ScopeResolver(ro)
 
IndustryTileScopeResolver::IndustryTileScopeResolver(ResolverObject &ro, Industry *industry, TileIndex tile) : ScopeResolver(ro)
 
{
 
	this->industry = industry;
 
	this->tile = tile;
 
}
 

	
 
static void IndustryDrawTileLayout(const TileInfo *ti, const TileLayoutSpriteGroup *group, byte rnd_colour, byte stage, IndustryGfx gfx)
 
{
 
	const DrawTileSprites *dts = group->ProcessRegisters(&stage);
 

	
 
	SpriteID image = dts->ground.sprite;
 
	PaletteID pal  = dts->ground.pal;
 

	
 
@@ -181,46 +181,46 @@ static void IndustryDrawTileLayout(const
 
		}
 
	}
 

	
 
	DrawNewGRFTileSeq(ti, dts, TO_INDUSTRIES, stage, GENERAL_SPRITE_COLOUR(rnd_colour));
 
}
 

	
 
uint16 GetIndustryTileCallback(CallbackID callback, uint32 param1, uint32 param2, IndustryGfx gfx_id, Industry *industry, TileIndex tile)
 
{
 
	assert(industry != NULL && IsValidTile(tile));
 
	assert(industry->index == INVALID_INDUSTRY || IsTileType(tile, MP_INDUSTRY));
 

	
 
	IndustryTileResolverObject object(gfx_id, tile, industry, callback, param1, param2);
 
	const SpriteGroup *group = SpriteGroup::Resolve(GetIndustryTileSpec(gfx_id)->grf_prop.spritegroup[0], &object);
 
	const SpriteGroup *group = SpriteGroup::Resolve(GetIndustryTileSpec(gfx_id)->grf_prop.spritegroup[0], object);
 
	if (group == NULL || group->type != SGT_CALLBACK) return CALLBACK_FAILED;
 

	
 
	return group->GetCallbackResult();
 
}
 

	
 
bool DrawNewIndustryTile(TileInfo *ti, Industry *i, IndustryGfx gfx, const IndustryTileSpec *inds)
 
{
 
	if (ti->tileh != SLOPE_FLAT) {
 
		bool draw_old_one = true;
 
		if (HasBit(inds->callback_mask, CBM_INDT_DRAW_FOUNDATIONS)) {
 
			/* Called to determine the type (if any) of foundation to draw for industry tile */
 
			uint32 callback_res = GetIndustryTileCallback(CBID_INDTILE_DRAW_FOUNDATIONS, 0, 0, gfx, i, ti->tile);
 
			if (callback_res != CALLBACK_FAILED) draw_old_one = ConvertBooleanCallback(inds->grf_prop.grffile, CBID_INDTILE_DRAW_FOUNDATIONS, callback_res);
 
		}
 

	
 
		if (draw_old_one) DrawFoundation(ti, FOUNDATION_LEVELED);
 
	}
 

	
 
	IndustryTileResolverObject object(gfx, ti->tile, i);
 

	
 
	const SpriteGroup *group = SpriteGroup::Resolve(inds->grf_prop.spritegroup[0], &object);
 
	const SpriteGroup *group = SpriteGroup::Resolve(inds->grf_prop.spritegroup[0], object);
 
	if (group == NULL || group->type != SGT_TILELAYOUT) return false;
 

	
 
	/* Limit the building stage to the number of stages supplied. */
 
	const TileLayoutSpriteGroup *tlgroup = (const TileLayoutSpriteGroup *)group;
 
	byte stage = GetIndustryConstructionStage(ti->tile);
 
	IndustryDrawTileLayout(ti, tlgroup, i->random_colour, stage, gfx);
 
	return true;
 
}
 

	
 
extern bool IsSlopeRefused(Slope current, Slope refused);
 

	
 
/**
 
@@ -319,25 +319,25 @@ bool StartStopIndustryTileAnimation(cons
 
static void DoTriggerIndustryTile(TileIndex tile, IndustryTileTrigger trigger, Industry *ind, uint32 &reseed_industry)
 
{
 
	assert(IsValidTile(tile) && IsTileType(tile, MP_INDUSTRY));
 

	
 
	IndustryGfx gfx = GetIndustryGfx(tile);
 
	const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx);
 

	
 
	if (itspec->grf_prop.spritegroup[0] == NULL) return;
 

	
 
	IndustryTileResolverObject object(gfx, tile, ind, CBID_RANDOM_TRIGGER);
 
	object.trigger = trigger;
 

	
 
	const SpriteGroup *group = SpriteGroup::Resolve(itspec->grf_prop.spritegroup[0], &object);
 
	const SpriteGroup *group = SpriteGroup::Resolve(itspec->grf_prop.spritegroup[0], object);
 
	if (group == NULL) return;
 

	
 
	byte new_random_bits = Random();
 
	byte random_bits = GetIndustryRandomBits(tile);
 
	random_bits &= ~object.reseed[VSG_SCOPE_SELF];
 
	random_bits |= new_random_bits & object.reseed[VSG_SCOPE_SELF];
 
	SetIndustryRandomBits(tile, random_bits);
 
	MarkTileDirtyByTile(tile);
 

	
 
	reseed_industry |= object.reseed[VSG_SCOPE_PARENT];
 
}
 

	
src/newgrf_industrytiles.h
Show inline comments
 
@@ -12,25 +12,25 @@
 
#ifndef NEWGRF_INDUSTRYTILES_H
 
#define NEWGRF_INDUSTRYTILES_H
 

	
 
#include "newgrf_animation_type.h"
 
#include "newgrf_industries.h"
 
#include "core/random_func.hpp"
 

	
 
/** Resolver for the industry tiles scope. */
 
struct IndustryTileScopeResolver : public ScopeResolver {
 
	Industry *industry; ///< Industry owning the tiles.
 
	TileIndex tile;     ///< %Tile being resolved.
 

	
 
	IndustryTileScopeResolver(ResolverObject *ro, Industry *industry, TileIndex tile);
 
	IndustryTileScopeResolver(ResolverObject &ro, Industry *industry, TileIndex tile);
 

	
 
	/* virtual */ uint32 GetRandomBits() const;
 
	/* virtual */ uint32 GetVariable(byte variable, uint32 parameter, bool *available) const;
 
	/* virtual */ uint32 GetTriggers() const;
 
	/* virtual */ void SetTriggers(int triggers) const;
 
};
 

	
 
/** Resolver for industry tiles. */
 
struct IndustryTileResolverObject : public ResolverObject {
 
	IndustryTileScopeResolver indtile_scope; ///< Scope resolver for the industry tile.
 
	IndustriesScopeResolver ind_scope;       ///< Scope resolver for the industry owning the tile.
 

	
src/newgrf_object.cpp
Show inline comments
 
@@ -124,25 +124,25 @@ bool NewGRFClass<Tspec, Tid, Tmax>::IsUI
 
	return this->GetSpec(index)->IsEverAvailable();
 
}
 

	
 
INSTANTIATE_NEWGRF_CLASS_METHODS(ObjectClass, ObjectSpec, ObjectClassID, OBJECT_CLASS_MAX)
 

	
 
/**
 
 * Constructor of an object scope resolver.
 
 * @param ro Surrounding resolver.
 
 * @param obj Object being resolved.
 
 * @param tile %Tile of the object.
 
 * @param view View of the object.
 
 */
 
ObjectScopeResolver::ObjectScopeResolver(ResolverObject *ro, Object *obj, TileIndex tile, uint8 view)
 
ObjectScopeResolver::ObjectScopeResolver(ResolverObject &ro, Object *obj, TileIndex tile, uint8 view)
 
		: ScopeResolver(ro)
 
{
 
	this->obj = obj;
 
	this->tile = tile;
 
	this->view = view;
 
}
 

	
 
/* virtual */ uint32 ObjectScopeResolver::GetRandomBits() const
 
{
 
	return IsValidTile(this->tile) && IsTileType(this->tile, MP_OBJECT) ? GetObjectRandomBits(this->tile) : 0;
 
}
 

	
 
@@ -317,43 +317,43 @@ static uint32 GetCountAndDistanceOfClose
 
		case 0x45: return GetTownRadiusGroup(t, this->tile) << 16 | min(DistanceManhattan(this->tile, t->xy), 0xFFFF);
 

	
 
		/* Get square of Euclidian distance of closes town */
 
		case 0x46: return GetTownRadiusGroup(t, this->tile) << 16 | min(DistanceSquare(this->tile, t->xy), 0xFFFF);
 

	
 
		/* Object colour */
 
		case 0x47: return this->obj->colour;
 

	
 
		/* Object view */
 
		case 0x48: return this->obj->view;
 

	
 
		/* Get object ID at offset param */
 
		case 0x60: return GetObjectIDAtOffset(GetNearbyTile(parameter, this->tile), this->ro->grffile->grfid);
 
		case 0x60: return GetObjectIDAtOffset(GetNearbyTile(parameter, this->tile), this->ro.grffile->grfid);
 

	
 
		/* Get random tile bits at offset param */
 
		case 0x61: {
 
			TileIndex tile = GetNearbyTile(parameter, this->tile);
 
			return (IsTileType(tile, MP_OBJECT) && Object::GetByTile(tile) == this->obj) ? GetObjectRandomBits(tile) : 0;
 
		}
 

	
 
		/* Land info of nearby tiles */
 
		case 0x62: return GetNearbyObjectTileInformation(parameter, this->tile, this->obj == NULL ? INVALID_OBJECT : this->obj->index, this->ro->grffile->grf_version >= 8);
 
		case 0x62: return GetNearbyObjectTileInformation(parameter, this->tile, this->obj == NULL ? INVALID_OBJECT : this->obj->index, this->ro.grffile->grf_version >= 8);
 

	
 
		/* Animation counter of nearby tile */
 
		case 0x63: {
 
			TileIndex tile = GetNearbyTile(parameter, this->tile);
 
			return (IsTileType(tile, MP_OBJECT) && Object::GetByTile(tile) == this->obj) ? GetAnimationFrame(tile) : 0;
 
		}
 

	
 
		/* Count of object, distance of closest instance */
 
		case 0x64: return GetCountAndDistanceOfClosestInstance(parameter, this->ro->grffile->grfid, this->tile, this->obj);
 
		case 0x64: return GetCountAndDistanceOfClosestInstance(parameter, this->ro.grffile->grfid, this->tile, this->obj);
 
	}
 

	
 
unhandled:
 
	DEBUG(grf, 1, "Unhandled object variable 0x%X", variable);
 

	
 
	*available = false;
 
	return UINT_MAX;
 
}
 

	
 
/**
 
 * Get the object's sprite group.
 
 * @param spec The specification to get the sprite group from.
 
@@ -374,69 +374,69 @@ static const SpriteGroup *GetObjectSprit
 

	
 
/**
 
 * Constructor of the object resolver.
 
 * @param obj Object being resolved.
 
 * @param tile %Tile of the object.
 
 * @param view View of the object.
 
 * @param callback Callback ID.
 
 * @param callback_param1 First parameter (var 10) of the callback.
 
 * @param callback_param2 Second parameter (var 18) of the callback.
 
 */
 
ObjectResolverObject::ObjectResolverObject(const ObjectSpec *spec, Object *obj, TileIndex tile, uint8 view,
 
		CallbackID callback, uint32 param1, uint32 param2)
 
	: ResolverObject(spec->grf_prop.grffile, callback, param1, param2), object_scope(this, obj, tile, view)
 
	: ResolverObject(spec->grf_prop.grffile, callback, param1, param2), object_scope(*this, obj, tile, view)
 
{
 
	this->town_scope = NULL;
 
}
 

	
 
ObjectResolverObject::~ObjectResolverObject()
 
{
 
	delete this->town_scope;
 
}
 

	
 
/**
 
 * Get the town resolver scope that belongs to this object resolver.
 
 * On the first call, the town scope is created (if possible).
 
 * @return Town scope, if available.
 
 */
 
TownScopeResolver *ObjectResolverObject::GetTown()
 
{
 
	if (this->town_scope == NULL) {
 
		Town *t;
 
		if (this->object_scope.obj != NULL) {
 
			t = this->object_scope.obj->town;
 
		} else {
 
			t = ClosestTownFromTile(this->object_scope.tile, UINT_MAX);
 
		}
 
		if (t == NULL) return NULL;
 
		this->town_scope = new TownScopeResolver(this, t, this->object_scope.obj == NULL);
 
		this->town_scope = new TownScopeResolver(*this, t, this->object_scope.obj == NULL);
 
	}
 
	return this->town_scope;
 
}
 

	
 
/**
 
 * Perform a callback for an object.
 
 * @param callback The callback to perform.
 
 * @param param1   The first parameter to pass to the NewGRF.
 
 * @param param2   The second parameter to pass to the NewGRF.
 
 * @param spec     The specification of the object / the entry point.
 
 * @param o        The object to call the callback for.
 
 * @param tile     The tile the callback is called for.
 
 * @param view     The view of the object (only used when o == NULL).
 
 * @return The result of the callback.
 
 */
 
uint16 GetObjectCallback(CallbackID callback, uint32 param1, uint32 param2, const ObjectSpec *spec, Object *o, TileIndex tile, uint8 view)
 
{
 
	ObjectResolverObject object(spec, o, tile, view, callback, param1, param2);
 
	const SpriteGroup *group = SpriteGroup::Resolve(GetObjectSpriteGroup(spec, o), &object);
 
	const SpriteGroup *group = SpriteGroup::Resolve(GetObjectSpriteGroup(spec, o), object);
 
	if (group == NULL) return CALLBACK_FAILED;
 

	
 
	return group->GetCallbackResult();
 
}
 

	
 
/**
 
 * Draw an group of sprites on the map.
 
 * @param ti    Information about the tile to draw on.
 
 * @param group The group of sprites to draw.
 
 * @param spec  Object spec to draw.
 
 */
 
static void DrawTileLayout(const TileInfo *ti, const TileLayoutSpriteGroup *group, const ObjectSpec *spec)
 
@@ -461,41 +461,41 @@ static void DrawTileLayout(const TileInf
 
}
 

	
 
/**
 
 * Draw an object on the map.
 
 * @param ti   Information about the tile to draw on.
 
 * @param spec Object spec to draw.
 
 */
 
void DrawNewObjectTile(TileInfo *ti, const ObjectSpec *spec)
 
{
 
	Object *o = Object::GetByTile(ti->tile);
 
	ObjectResolverObject object(spec, o, ti->tile);
 

	
 
	const SpriteGroup *group = SpriteGroup::Resolve(GetObjectSpriteGroup(spec, o), &object);
 
	const SpriteGroup *group = SpriteGroup::Resolve(GetObjectSpriteGroup(spec, o), object);
 
	if (group == NULL || group->type != SGT_TILELAYOUT) return;
 

	
 
	DrawTileLayout(ti, (const TileLayoutSpriteGroup *)group, spec);
 
}
 

	
 
/**
 
 * Draw representation of an object (tile) for GUI purposes.
 
 * @param x    Position x of image.
 
 * @param y    Position y of image.
 
 * @param spec Object spec to draw.
 
 * @param view The object's view.
 
 */
 
void DrawNewObjectTileInGUI(int x, int y, const ObjectSpec *spec, uint8 view)
 
{
 
	ObjectResolverObject object(spec, NULL, INVALID_TILE, view);
 
	const SpriteGroup *group = SpriteGroup::Resolve(GetObjectSpriteGroup(spec, NULL), &object);
 
	const SpriteGroup *group = SpriteGroup::Resolve(GetObjectSpriteGroup(spec, NULL), object);
 
	if (group == NULL || group->type != SGT_TILELAYOUT) return;
 

	
 
	const DrawTileSprites *dts = ((const TileLayoutSpriteGroup *)group)->ProcessRegisters(NULL);
 

	
 
	PaletteID palette;
 
	if (Company::IsValidID(_local_company)) {
 
		/* Get the colours of our company! */
 
		if (spec->flags & OBJECT_FLAG_2CC_COLOUR) {
 
			const Livery *l = Company::Get(_local_company)->livery;
 
			palette = SPR_2CCMAP_BASE + l->colour1 + l->colour2 * 16;
 
		} else {
 
			palette = COMPANY_SPRITE_COLOUR(_local_company);
src/newgrf_object.h
Show inline comments
 
@@ -95,25 +95,25 @@ struct ObjectSpec {
 
	uint Index() const;
 

	
 
	static const ObjectSpec *Get(ObjectType index);
 
	static const ObjectSpec *GetByTile(TileIndex tile);
 
};
 

	
 
/** Object scope resolver. */
 
struct ObjectScopeResolver : public ScopeResolver {
 
	struct Object *obj; ///< The object the callback is ran for.
 
	TileIndex tile;     ///< The tile related to the object.
 
	uint8 view;         ///< The view of the object.
 

	
 
	ObjectScopeResolver(ResolverObject *ro, Object *obj, TileIndex tile, uint8 view = 0);
 
	ObjectScopeResolver(ResolverObject &ro, Object *obj, TileIndex tile, uint8 view = 0);
 

	
 
	/* virtual */ uint32 GetRandomBits() const;
 
	/* virtual */ uint32 GetVariable(byte variable, uint32 parameter, bool *available) const;
 
};
 

	
 
/** A resolver object to be used with feature 0F spritegroups. */
 
struct ObjectResolverObject : public ResolverObject {
 
	ObjectScopeResolver object_scope; ///< The object scope resolver.
 
	TownScopeResolver *town_scope;    ///< The town scope resolver (created on the first call).
 

	
 
	ObjectResolverObject(const ObjectSpec *spec, Object *o, TileIndex tile, uint8 view = 0,
 
			CallbackID callback = CBID_NO_CALLBACK, uint32 param1 = 0, uint32 param2 = 0);
src/newgrf_railtype.cpp
Show inline comments
 
@@ -62,83 +62,83 @@
 
{
 
	if (group->num_loading > 0) return group->loading[0];
 
	if (group->num_loaded  > 0) return group->loaded[0];
 
	return NULL;
 
}
 

	
 
/**
 
 * Constructor of the railtype scope resolvers.
 
 * @param ro Surrounding resolver.
 
 * @param tile %Tile containing the track. For track on a bridge this is the southern bridgehead.
 
 * @param context Are we resolving sprites for the upper halftile, or on a bridge?
 
 */
 
RailTypeScopeResolver::RailTypeScopeResolver(ResolverObject *ro, TileIndex tile, TileContext context) : ScopeResolver(ro)
 
RailTypeScopeResolver::RailTypeScopeResolver(ResolverObject &ro, TileIndex tile, TileContext context) : ScopeResolver(ro)
 
{
 
	this->tile = tile;
 
	this->context = context;
 
}
 

	
 
/**
 
 * Resolver object for rail types.
 
 * @param tile %Tile containing the track. For track on a bridge this is the southern bridgehead.
 
 * @param context Are we resolving sprites for the upper halftile, or on a bridge?
 
 * @param grffile The GRF to do the lookup for.
 
 * @param param1 Extra parameter (first parameter of the callback, except railtypes do not have callbacks).
 
 * @param param2 Extra parameter (second parameter of the callback, except railtypes do not have callbacks).
 
 */
 
RailTypeResolverObject::RailTypeResolverObject(TileIndex tile, TileContext context, const GRFFile *grffile, uint32 param1, uint32 param2)
 
	: ResolverObject(grffile, CBID_NO_CALLBACK, param1, param2), railtype_scope(this, tile, context)
 
	: ResolverObject(grffile, CBID_NO_CALLBACK, param1, param2), railtype_scope(*this, tile, context)
 
{
 
}
 

	
 
/**
 
 * Get the sprite to draw for the given tile.
 
 * @param rti The rail type data (spec).
 
 * @param tile The tile to get the sprite for.
 
 * @param rtsg The type of sprite to draw.
 
 * @param content Where are we drawing the tile?
 
 * @return The sprite to draw.
 
 */
 
SpriteID GetCustomRailSprite(const RailtypeInfo *rti, TileIndex tile, RailTypeSpriteGroup rtsg, TileContext context)
 
{
 
	assert(rtsg < RTSG_END);
 

	
 
	if (rti->group[rtsg] == NULL) return 0;
 

	
 
	RailTypeResolverObject object(tile, context, rti->grffile[rtsg]);
 
	const SpriteGroup *group = SpriteGroup::Resolve(rti->group[rtsg], &object);
 
	const SpriteGroup *group = SpriteGroup::Resolve(rti->group[rtsg], object);
 
	if (group == NULL || group->GetNumResults() == 0) return 0;
 

	
 
	return group->GetResult();
 
}
 

	
 
/**
 
 * Get the sprite to draw for a given signal.
 
 * @param rti The rail type data (spec).
 
 * @param tile The tile to get the sprite for.
 
 * @param type Signal type.
 
 * @param var Signal variant.
 
 * @param state Signal state.
 
 * @param gui Is the sprite being used on the map or in the GUI?
 
 * @return The sprite to draw.
 
 */
 
SpriteID GetCustomSignalSprite(const RailtypeInfo *rti, TileIndex tile, SignalType type, SignalVariant var, SignalState state, bool gui)
 
{
 
	if (rti->group[RTSG_SIGNALS] == NULL) return 0;
 

	
 
	uint32 param1 = gui ? 0x10 : 0x00;
 
	uint32 param2 = (type << 16) | (var << 8) | state;
 
	RailTypeResolverObject object(tile, TCX_NORMAL, rti->grffile[RTSG_SIGNALS], param1, param2);
 

	
 
	const SpriteGroup *group = SpriteGroup::Resolve(rti->group[RTSG_SIGNALS], &object);
 
	const SpriteGroup *group = SpriteGroup::Resolve(rti->group[RTSG_SIGNALS], object);
 
	if (group == NULL || group->GetNumResults() == 0) return 0;
 

	
 
	return group->GetResult();
 
}
 

	
 
/**
 
 * Perform a reverse railtype lookup to get the GRF internal ID.
 
 * @param railtype The global (OpenTTD) railtype.
 
 * @param grffile The GRF to do the lookup for.
 
 * @return the GRF internal ID.
 
 */
 
uint8 GetReverseRailTypeTranslation(RailType railtype, const GRFFile *grffile)
src/newgrf_railtype.h
Show inline comments
 
@@ -12,25 +12,25 @@
 
#ifndef NEWGRF_RAILTYPE_H
 
#define NEWGRF_RAILTYPE_H
 

	
 
#include "rail.h"
 
#include "newgrf_commons.h"
 
#include "newgrf_spritegroup.h"
 

	
 
/** Resolver for the railtype scope. */
 
struct RailTypeScopeResolver : public ScopeResolver {
 
	TileIndex tile;      ///< Tracktile. For track on a bridge this is the southern bridgehead.
 
	TileContext context; ///< Are we resolving sprites for the upper halftile, or on a bridge?
 

	
 
	RailTypeScopeResolver(ResolverObject *ro, TileIndex tile, TileContext context);
 
	RailTypeScopeResolver(ResolverObject &ro, TileIndex tile, TileContext context);
 

	
 
	/* virtual */ uint32 GetRandomBits() const;
 
	/* virtual */ uint32 GetVariable(byte variable, uint32 parameter, bool *available) const;
 
};
 

	
 
/** Resolver object for rail types. */
 
struct RailTypeResolverObject : public ResolverObject {
 
	RailTypeScopeResolver railtype_scope; ///< Resolver for the railtype scope.
 

	
 
	RailTypeResolverObject(TileIndex tile, TileContext context, const GRFFile *grffile, uint32 param1 = 0, uint32 param2 = 0);
 

	
 
	/* virtual */ ScopeResolver *GetScope(VarSpriteGroupScope scope = VSG_SCOPE_SELF, byte relative = 0)
src/newgrf_spritegroup.cpp
Show inline comments
 
@@ -28,53 +28,53 @@ DeterministicSpriteGroup::~Deterministic
 
	free(this->adjusts);
 
	free(this->ranges);
 
}
 

	
 
RandomizedSpriteGroup::~RandomizedSpriteGroup()
 
{
 
	free(this->groups);
 
}
 

	
 
TemporaryStorageArray<int32, 0x110> _temp_store;
 

	
 

	
 
static inline uint32 GetVariable(const ResolverObject *object, ScopeResolver *scope, byte variable, uint32 parameter, bool *available)
 
static inline uint32 GetVariable(const ResolverObject &object, ScopeResolver *scope, byte variable, uint32 parameter, bool *available)
 
{
 
	/* First handle variables common with Action7/9/D */
 
	uint32 value;
 
	if (GetGlobalVariable(variable, &value, object->grffile)) return value;
 
	if (GetGlobalVariable(variable, &value, object.grffile)) return value;
 

	
 
	/* Non-common variable */
 
	switch (variable) {
 
		case 0x0C: return object->callback;
 
		case 0x10: return object->callback_param1;
 
		case 0x18: return object->callback_param2;
 
		case 0x1C: return object->last_value;
 
		case 0x0C: return object.callback;
 
		case 0x10: return object.callback_param1;
 
		case 0x18: return object.callback_param2;
 
		case 0x1C: return object.last_value;
 

	
 
		case 0x5F: return (scope->GetRandomBits() << 8) | scope->GetTriggers();
 

	
 
		case 0x7D: return _temp_store.GetValue(parameter);
 

	
 
		case 0x7F:
 
			if (object == NULL || object->grffile == NULL) return 0;
 
			return object->grffile->GetParam(parameter);
 
			if (object.grffile == NULL) return 0;
 
			return object.grffile->GetParam(parameter);
 

	
 
		/* Not a common variable, so evaluate the feature specific variables */
 
		default: return scope->GetVariable(variable, parameter, available);
 
	}
 
}
 

	
 
ScopeResolver::ScopeResolver(ResolverObject *ro)
 
ScopeResolver::ScopeResolver(ResolverObject &ro)
 
		: ro(ro)
 
{
 
	this->ro = ro;
 
}
 

	
 
ScopeResolver::~ScopeResolver() {}
 

	
 
/**
 
 * Get a few random bits. Default implementation has no random bits.
 
 * @return Random bits.
 
 */
 
/* virtual */ uint32 ScopeResolver::GetRandomBits() const
 
{
 
	return 0;
 
}
 
@@ -114,25 +114,25 @@ ScopeResolver::~ScopeResolver() {}
 
 * @param value Value to store.
 
 */
 
/* virtual */ void ScopeResolver::StorePSA(uint reg, int32 value) {}
 

	
 
/**
 
 * Resolver constructor.
 
 * @param grffile NewGRF file associated with the object (or \c NULL if none).
 
 * @param callback Callback code being resolved (default value is #CBID_NO_CALLBACK).
 
 * @param callback_param1 First parameter (var 10) of the callback (only used when \a callback is also set).
 
 * @param callback_param2 Second parameter (var 18) of the callback (only used when \a callback is also set).
 
 */
 
ResolverObject::ResolverObject(const GRFFile *grffile, CallbackID callback, uint32 callback_param1, uint32 callback_param2)
 
		: default_scope(this)
 
		: default_scope(*this)
 
{
 
	this->callback = callback;
 
	this->callback_param1 = callback_param1;
 
	this->callback_param2 = callback_param2;
 
	this->ResetState();
 

	
 
	this->grffile = grffile;
 
}
 

	
 
ResolverObject::~ResolverObject() {}
 

	
 
/**
 
@@ -207,31 +207,31 @@ static U EvalAdjustT(const Deterministic
 
		case DSGA_OP_STOP: scope->StorePSA((U)value, (S)last_value); return last_value;
 
		case DSGA_OP_ROR:  return RotateRight(last_value, value);
 
		case DSGA_OP_SCMP: return ((S)last_value == (S)value) ? 1 : ((S)last_value < (S)value ? 0 : 2);
 
		case DSGA_OP_UCMP: return ((U)last_value == (U)value) ? 1 : ((U)last_value < (U)value ? 0 : 2);
 
		case DSGA_OP_SHL:  return (U)last_value << ((U)value & 0x1F); // mask 'value' to 5 bits, which should behave the same on all architectures.
 
		case DSGA_OP_SHR:  return (U)last_value >> ((U)value & 0x1F);
 
		case DSGA_OP_SAR:  return (S)last_value >> ((U)value & 0x1F);
 
		default:           return value;
 
	}
 
}
 

	
 

	
 
const SpriteGroup *DeterministicSpriteGroup::Resolve(ResolverObject *object) const
 
const SpriteGroup *DeterministicSpriteGroup::Resolve(ResolverObject &object) const
 
{
 
	uint32 last_value = 0;
 
	uint32 value = 0;
 
	uint i;
 

	
 
	ScopeResolver *scope = object->GetScope(this->var_scope);
 
	ScopeResolver *scope = object.GetScope(this->var_scope);
 

	
 
	for (i = 0; i < this->num_adjusts; i++) {
 
		DeterministicSpriteGroupAdjust *adjust = &this->adjusts[i];
 

	
 
		/* Try to get the variable. We shall assume it is available, unless told otherwise. */
 
		bool available = true;
 
		if (adjust->variable == 0x7E) {
 
			const SpriteGroup *subgroup = SpriteGroup::Resolve(adjust->subroutine, object);
 
			if (subgroup == NULL) {
 
				value = CALLBACK_FAILED;
 
			} else {
 
				value = subgroup->GetCallbackResult();
 
@@ -250,74 +250,74 @@ const SpriteGroup *DeterministicSpriteGr
 
			return SpriteGroup::Resolve(this->num_ranges > 0 ? this->ranges[0].group : this->default_group, object);
 
		}
 

	
 
		switch (this->size) {
 
			case DSG_SIZE_BYTE:  value = EvalAdjustT<uint8,  int8> (adjust, scope, last_value, value); break;
 
			case DSG_SIZE_WORD:  value = EvalAdjustT<uint16, int16>(adjust, scope, last_value, value); break;
 
			case DSG_SIZE_DWORD: value = EvalAdjustT<uint32, int32>(adjust, scope, last_value, value); break;
 
			default: NOT_REACHED();
 
		}
 
		last_value = value;
 
	}
 

	
 
	object->last_value = last_value;
 
	object.last_value = last_value;
 

	
 
	if (this->num_ranges == 0) {
 
		/* nvar == 0 is a special case -- we turn our value into a callback result */
 
		if (value != CALLBACK_FAILED) value = GB(value, 0, 15);
 
		static CallbackResultSpriteGroup nvarzero(0, true);
 
		nvarzero.result = value;
 
		return &nvarzero;
 
	}
 

	
 
	for (i = 0; i < this->num_ranges; i++) {
 
		if (this->ranges[i].low <= value && value <= this->ranges[i].high) {
 
			return SpriteGroup::Resolve(this->ranges[i].group, object);
 
		}
 
	}
 

	
 
	return SpriteGroup::Resolve(this->default_group, object);
 
}
 

	
 

	
 
const SpriteGroup *RandomizedSpriteGroup::Resolve(ResolverObject *object) const
 
const SpriteGroup *RandomizedSpriteGroup::Resolve(ResolverObject &object) const
 
{
 
	ScopeResolver *scope = object->GetScope(this->var_scope, this->count);
 
	if (object->trigger != 0) {
 
	ScopeResolver *scope = object.GetScope(this->var_scope, this->count);
 
	if (object.trigger != 0) {
 
		/* Handle triggers */
 
		/* Magic code that may or may not do the right things... */
 
		byte waiting_triggers = scope->GetTriggers();
 
		byte match = this->triggers & (waiting_triggers | object->trigger);
 
		byte match = this->triggers & (waiting_triggers | object.trigger);
 
		bool res = (this->cmp_mode == RSG_CMP_ANY) ? (match != 0) : (match == this->triggers);
 

	
 
		if (res) {
 
			waiting_triggers &= ~match;
 
			object->reseed[this->var_scope] |= (this->num_groups - 1) << this->lowest_randbit;
 
			object.reseed[this->var_scope] |= (this->num_groups - 1) << this->lowest_randbit;
 
		} else {
 
			waiting_triggers |= object->trigger;
 
			waiting_triggers |= object.trigger;
 
		}
 

	
 
		scope->SetTriggers(waiting_triggers);
 
	}
 

	
 
	uint32 mask  = (this->num_groups - 1) << this->lowest_randbit;
 
	byte index = (scope->GetRandomBits() & mask) >> this->lowest_randbit;
 

	
 
	return SpriteGroup::Resolve(this->groups[index], object);
 
}
 

	
 

	
 
const SpriteGroup *RealSpriteGroup::Resolve(ResolverObject *object) const
 
const SpriteGroup *RealSpriteGroup::Resolve(ResolverObject &object) const
 
{
 
	return object->ResolveReal(this);
 
	return object.ResolveReal(this);
 
}
 

	
 
/**
 
 * Process registers and the construction stage into the sprite layout.
 
 * The passed construction stage might get reset to zero, if it gets incorporated into the layout
 
 * during the preprocessing.
 
 * @param [in, out] stage Construction stage (0-3), or NULL if not applicable.
 
 * @return sprite layout to draw.
 
 */
 
const DrawTileSprites *TileLayoutSpriteGroup::ProcessRegisters(uint8 *stage) const
 
{
 
	if (!this->dts.NeedsPreprocessing()) {
src/newgrf_spritegroup.h
Show inline comments
 
@@ -48,57 +48,58 @@ static inline void ClearRegister(uint i)
 
enum SpriteGroupType {
 
	SGT_REAL,
 
	SGT_DETERMINISTIC,
 
	SGT_RANDOMIZED,
 
	SGT_CALLBACK,
 
	SGT_RESULT,
 
	SGT_TILELAYOUT,
 
	SGT_INDUSTRY_PRODUCTION,
 
};
 

	
 
struct SpriteGroup;
 
typedef uint32 SpriteGroupID;
 
struct ResolverObject;
 

	
 
/* SPRITE_WIDTH is 24. ECS has roughly 30 sprite groups per real sprite.
 
 * Adding an 'extra' margin would be assuming 64 sprite groups per real
 
 * sprite. 64 = 2^6, so 2^30 should be enough (for now) */
 
typedef Pool<SpriteGroup, SpriteGroupID, 1024, 1 << 30, PT_DATA> SpriteGroupPool;
 
extern SpriteGroupPool _spritegroup_pool;
 

	
 
/* Common wrapper for all the different sprite group types */
 
struct SpriteGroup : SpriteGroupPool::PoolItem<&_spritegroup_pool> {
 
protected:
 
	SpriteGroup(SpriteGroupType type) : type(type) {}
 
	/** Base sprite group resolver */
 
	virtual const SpriteGroup *Resolve(struct ResolverObject *object) const { return this; };
 
	virtual const SpriteGroup *Resolve(ResolverObject &object) const { return this; };
 

	
 
public:
 
	virtual ~SpriteGroup() {}
 

	
 
	SpriteGroupType type;
 

	
 
	virtual SpriteID GetResult() const { return 0; }
 
	virtual byte GetNumResults() const { return 0; }
 
	virtual uint16 GetCallbackResult() const { return CALLBACK_FAILED; }
 

	
 
	/**
 
	 * ResolverObject (re)entry point.
 
	 * This cannot be made a call to a virtual function because virtual functions
 
	 * do not like NULL and checking for NULL *everywhere* is more cumbersome than
 
	 * this little helper function.
 
	 * @param group the group to resolve for
 
	 * @param object information needed to resolve the group
 
	 * @return the resolved group
 
	 */
 
	static const SpriteGroup *Resolve(const SpriteGroup *group, ResolverObject *object)
 
	static const SpriteGroup *Resolve(const SpriteGroup *group, ResolverObject &object)
 
	{
 
		return group == NULL ? NULL : group->Resolve(object);
 
	}
 
};
 

	
 

	
 
/* 'Real' sprite groups contain a list of other result or callback sprite
 
 * groups. */
 
struct RealSpriteGroup : SpriteGroup {
 
	RealSpriteGroup() : SpriteGroup(SGT_REAL) {}
 
	~RealSpriteGroup();
 

	
 
@@ -106,25 +107,25 @@ struct RealSpriteGroup : SpriteGroup {
 
	 * Each group contains several spritesets, for various loading stages */
 

	
 
	/* XXX: For stations the meaning is different - loaded is for stations
 
	 * with small amount of cargo whilst loading is for stations with a lot
 
	 * of da stuff. */
 

	
 
	byte num_loaded;       ///< Number of loaded groups
 
	byte num_loading;      ///< Number of loading groups
 
	const SpriteGroup **loaded;  ///< List of loaded groups (can be SpriteIDs or Callback results)
 
	const SpriteGroup **loading; ///< List of loading groups (can be SpriteIDs or Callback results)
 

	
 
protected:
 
	const SpriteGroup *Resolve(ResolverObject *object) const;
 
	const SpriteGroup *Resolve(ResolverObject &object) const;
 
};
 

	
 
/* Shared by deterministic and random groups. */
 
enum VarSpriteGroupScope {
 
	VSG_BEGIN,
 

	
 
	VSG_SCOPE_SELF = VSG_BEGIN, ///< Resolved object itself
 
	VSG_SCOPE_PARENT,           ///< Related object of the resolved one
 
	VSG_SCOPE_RELATIVE,         ///< Relative position (vehicles only)
 

	
 
	VSG_END
 
};
 
@@ -195,49 +196,49 @@ struct DeterministicSpriteGroup : Sprite
 

	
 
	VarSpriteGroupScope var_scope;
 
	DeterministicSpriteGroupSize size;
 
	uint num_adjusts;
 
	byte num_ranges;
 
	DeterministicSpriteGroupAdjust *adjusts;
 
	DeterministicSpriteGroupRange *ranges; // Dynamically allocated
 

	
 
	/* Dynamically allocated, this is the sole owner */
 
	const SpriteGroup *default_group;
 

	
 
protected:
 
	const SpriteGroup *Resolve(ResolverObject *object) const;
 
	const SpriteGroup *Resolve(ResolverObject &object) const;
 
};
 

	
 
enum RandomizedSpriteGroupCompareMode {
 
	RSG_CMP_ANY,
 
	RSG_CMP_ALL,
 
};
 

	
 
struct RandomizedSpriteGroup : SpriteGroup {
 
	RandomizedSpriteGroup() : SpriteGroup(SGT_RANDOMIZED) {}
 
	~RandomizedSpriteGroup();
 

	
 
	VarSpriteGroupScope var_scope;  ///< Take this object:
 

	
 
	RandomizedSpriteGroupCompareMode cmp_mode; ///< Check for these triggers:
 
	byte triggers;
 
	byte count;
 

	
 
	byte lowest_randbit; ///< Look for this in the per-object randomized bitmask:
 
	byte num_groups; ///< must be power of 2
 

	
 
	const SpriteGroup **groups; ///< Take the group with appropriate index:
 

	
 
protected:
 
	const SpriteGroup *Resolve(ResolverObject *object) const;
 
	const SpriteGroup *Resolve(ResolverObject &object) const;
 
};
 

	
 

	
 
/* This contains a callback result. A failed callback has a value of
 
 * CALLBACK_FAILED */
 
struct CallbackResultSpriteGroup : SpriteGroup {
 
	/**
 
	 * Creates a spritegroup representing a callback result
 
	 * @param value The value that was used to represent this callback result
 
	 * @param grf_version8 True, if we are dealing with a new NewGRF which uses GRF version >= 8.
 
	 */
 
	CallbackResultSpriteGroup(uint16 value, bool grf_version8) :
 
@@ -292,36 +293,34 @@ struct TileLayoutSpriteGroup : SpriteGro
 
	const DrawTileSprites *ProcessRegisters(uint8 *stage) const;
 
};
 

	
 
struct IndustryProductionSpriteGroup : SpriteGroup {
 
	IndustryProductionSpriteGroup() : SpriteGroup(SGT_INDUSTRY_PRODUCTION) {}
 

	
 
	uint8 version;
 
	int16 subtract_input[3];  // signed
 
	uint16 add_output[2];     // unsigned
 
	uint8 again;
 
};
 

	
 
struct ResolverObject;
 

	
 
/**
 
 * Interface to query and set values specific to a single #VarSpriteGroupScope (action 2 scope).
 
 *
 
 * Multiple of these interfaces are combined into a #ResolverObject to allow access
 
 * to different game entities from a #SpriteGroup-chain (action 1-2-3 chain).
 
 */
 
struct ScopeResolver {
 
	ResolverObject *ro; ///< Surrounding resolver object.
 
	ResolverObject &ro; ///< Surrounding resolver object.
 

	
 
	ScopeResolver(ResolverObject *ro);
 
	ScopeResolver(ResolverObject &ro);
 
	virtual ~ScopeResolver();
 

	
 
	virtual uint32 GetRandomBits() const;
 
	virtual uint32 GetTriggers() const;
 
	virtual void SetTriggers(int triggers) const;
 

	
 
	virtual uint32 GetVariable(byte variable, uint32 parameter, bool *available) const;
 
	virtual void StorePSA(uint reg, int32 value);
 
};
 

	
 
/**
 
 * Interface for #SpriteGroup-s to access the gamestate.
src/newgrf_station.cpp
Show inline comments
 
@@ -261,25 +261,25 @@ static struct {
 
 * @return Town scope, if available.
 
 */
 
TownScopeResolver *StationResolverObject::GetTown()
 
{
 
	if (this->town_scope == NULL) {
 
		Town *t = NULL;
 
		if (this->station_scope.st != NULL) {
 
			t = this->station_scope.st->town;
 
		} else if (this->station_scope.tile != INVALID_TILE) {
 
			t = ClosestTownFromTile(this->station_scope.tile, UINT_MAX);
 
		}
 
		if (t == NULL) return NULL;
 
		this->town_scope = new TownScopeResolver(this, t, this->station_scope.st == NULL);
 
		this->town_scope = new TownScopeResolver(*this, t, this->station_scope.st == NULL);
 
	}
 
	return this->town_scope;
 
}
 

	
 
/* virtual */ uint32 StationScopeResolver::GetVariable(byte variable, uint32 parameter, bool *available) const
 
{
 
	if (this->st == NULL) {
 
		/* Station does not exist, so we're in a purchase list or the land slope check callback. */
 
		switch (variable) {
 
			case 0x40:
 
			case 0x41:
 
			case 0x46:
 
@@ -287,25 +287,25 @@ TownScopeResolver *StationResolverObject
 
			case 0x49: return 0x2110000;        // Platforms, tracks & position
 
			case 0x42: return 0;                // Rail type (XXX Get current type from GUI?)
 
			case 0x43: return GetCompanyInfo(_current_company); // Station owner
 
			case 0x44: return 2;                // PBS status
 
			case 0x67: // Land info of nearby tile
 
				if (this->axis != INVALID_AXIS && this->tile != INVALID_TILE) {
 
					TileIndex tile = this->tile;
 
					if (parameter != 0) tile = GetNearbyTile(parameter, tile, true, this->axis); // only perform if it is required
 

	
 
					Slope tileh = GetTileSlope(tile);
 
					bool swap = (this->axis == AXIS_Y && HasBit(tileh, CORNER_W) != HasBit(tileh, CORNER_E));
 

	
 
					return GetNearbyTileInformation(tile, this->ro->grffile->grf_version >= 8) ^ (swap ? SLOPE_EW : 0);
 
					return GetNearbyTileInformation(tile, this->ro.grffile->grf_version >= 8) ^ (swap ? SLOPE_EW : 0);
 
				}
 
				break;
 

	
 
			case 0xFA: return Clamp(_date - DAYS_TILL_ORIGINAL_BASE_YEAR, 0, 65535); // Build date, clamped to a 16 bit value
 
		}
 

	
 
		*available = false;
 
		return UINT_MAX;
 
	}
 

	
 
	switch (variable) {
 
		/* Calculated station variables */
 
@@ -346,25 +346,25 @@ TownScopeResolver *StationResolverObject
 
			if (parameter != 0) tile = GetNearbyTile(parameter, tile);
 
			return this->st->TileBelongsToRailStation(tile) ? GetAnimationFrame(tile) : UINT_MAX;
 
		}
 

	
 
		case 0x67: { // Land info of nearby tile
 
			Axis axis = GetRailStationAxis(this->tile);
 
			TileIndex tile = this->tile;
 
			if (parameter != 0) tile = GetNearbyTile(parameter, tile); // only perform if it is required
 

	
 
			Slope tileh = GetTileSlope(tile);
 
			bool swap = (axis == AXIS_Y && HasBit(tileh, CORNER_W) != HasBit(tileh, CORNER_E));
 

	
 
			return GetNearbyTileInformation(tile, this->ro->grffile->grf_version >= 8) ^ (swap ? SLOPE_EW : 0);
 
			return GetNearbyTileInformation(tile, this->ro.grffile->grf_version >= 8) ^ (swap ? SLOPE_EW : 0);
 
		}
 

	
 
		case 0x68: { // Station info of nearby tiles
 
			TileIndex nearby_tile = GetNearbyTile(parameter, this->tile);
 

	
 
			if (!HasStationTileRail(nearby_tile)) return 0xFFFFFFFF;
 

	
 
			uint32 grfid = this->st->speclist[GetCustomStationSpecIndex(this->tile)].grfid;
 
			bool perpendicular = GetRailStationAxis(this->tile) != GetRailStationAxis(nearby_tile);
 
			bool same_station = this->st->TileBelongsToRailStation(nearby_tile);
 
			uint32 res = GB(GetStationGfx(nearby_tile), 1, 2) << 12 | !!perpendicular << 11 | !!same_station << 10;
 

	
 
@@ -377,48 +377,48 @@ TownScopeResolver *StationResolverObject
 

	
 
		/* General station variables */
 
		case 0x82: return 50;
 
		case 0x84: return this->st->string_id;
 
		case 0x86: return 0;
 
		case 0xF0: return this->st->facilities;
 
		case 0xFA: return Clamp(this->st->build_date - DAYS_TILL_ORIGINAL_BASE_YEAR, 0, 65535);
 
	}
 

	
 
	return this->st->GetNewGRFVariable(this->ro, variable, parameter, available);
 
}
 

	
 
uint32 Station::GetNewGRFVariable(const ResolverObject *object, byte variable, byte parameter, bool *available) const
 
uint32 Station::GetNewGRFVariable(const ResolverObject &object, byte variable, byte parameter, bool *available) const
 
{
 
	switch (variable) {
 
		case 0x48: { // Accepted cargo types
 
			CargoID cargo_type;
 
			uint32 value = 0;
 

	
 
			for (cargo_type = 0; cargo_type < NUM_CARGO; cargo_type++) {
 
				if (HasBit(this->goods[cargo_type].acceptance_pickup, GoodsEntry::GES_ACCEPTANCE)) SetBit(value, cargo_type);
 
			}
 
			return value;
 
		}
 

	
 
		case 0x8A: return this->had_vehicle_of_type;
 
		case 0xF1: return (this->airport.tile != INVALID_TILE) ? this->airport.GetSpec()->ttd_airport_type : ATP_TTDP_LARGE;
 
		case 0xF2: return (this->truck_stops != NULL) ? this->truck_stops->status : 0;
 
		case 0xF3: return (this->bus_stops != NULL)   ? this->bus_stops->status   : 0;
 
		case 0xF6: return this->airport.flags;
 
		case 0xF7: return GB(this->airport.flags, 8, 8);
 
	}
 

	
 
	/* Handle cargo variables with parameter, 0x60 to 0x65 and 0x69 */
 
	if ((variable >= 0x60 && variable <= 0x65) || variable == 0x69) {
 
		CargoID c = GetCargoTranslation(parameter, object->grffile);
 
		CargoID c = GetCargoTranslation(parameter, object.grffile);
 

	
 
		if (c == CT_INVALID) {
 
			switch (variable) {
 
				case 0x62: return 0xFFFFFFFF;
 
				case 0x64: return 0xFF00;
 
				default:   return 0;
 
			}
 
		}
 
		const GoodsEntry *ge = &this->goods[c];
 

	
 
		switch (variable) {
 
			case 0x60: return min(ge->cargo.TotalCount(), 4095);
 
@@ -448,25 +448,25 @@ uint32 Station::GetNewGRFVariable(const 
 
			case 5: return g->cargo.DaysInTransit();
 
			case 6: return g->last_speed;
 
			case 7: return g->last_age;
 
		}
 
	}
 

	
 
	DEBUG(grf, 1, "Unhandled station variable 0x%X", variable);
 

	
 
	*available = false;
 
	return UINT_MAX;
 
}
 

	
 
uint32 Waypoint::GetNewGRFVariable(const ResolverObject *object, byte variable, byte parameter, bool *available) const
 
uint32 Waypoint::GetNewGRFVariable(const ResolverObject &object, byte variable, byte parameter, bool *available) const
 
{
 
	switch (variable) {
 
		case 0x48: return 0; // Accepted cargo types
 
		case 0x8A: return HVOT_WAYPOINT;
 
		case 0xF1: return 0; // airport type
 
		case 0xF2: return 0; // truck stop status
 
		case 0xF3: return 0; // bus stop status
 
		case 0xF6: return 0; // airport flags
 
		case 0xF7: return 0; // airport flags cont.
 
	}
 

	
 
	/* Handle cargo variables with parameter, 0x60 to 0x65 */
 
@@ -537,151 +537,151 @@ uint32 Waypoint::GetNewGRFVariable(const
 
/**
 
 * Resolver for stations.
 
 * @param statspec Station (type) specification.
 
 * @param st Instance of the station.
 
 * @param tile %Tile of the station.
 
 * @param callback Callback ID.
 
 * @param callback_param1 First parameter (var 10) of the callback.
 
 * @param callback_param2 Second parameter (var 18) of the callback.
 
 */
 
StationResolverObject::StationResolverObject(const StationSpec *statspec, BaseStation *st, TileIndex tile,
 
		CallbackID callback, uint32 callback_param1, uint32 callback_param2)
 
	: ResolverObject((statspec != NULL ? statspec->grf_prop.grffile : NULL), callback, callback_param1, callback_param2),
 
	station_scope(this, statspec, st, tile), town_scope(NULL)
 
	station_scope(*this, statspec, st, tile), town_scope(NULL)
 
{
 
	/* Invalidate all cached vars */
 
	_svc.valid = 0;
 
}
 

	
 
StationResolverObject::~StationResolverObject()
 
{
 
	delete this->town_scope;
 
}
 

	
 
/**
 
 * Constructor for station scopes.
 
 * @param ro Surrounding resolver.
 
 * @param statspec Station (type) specification.
 
 * @param st Instance of the station.
 
 * @param tile %Tile of the station.
 
 */
 
StationScopeResolver::StationScopeResolver(ResolverObject *ro, const StationSpec *statspec, BaseStation *st, TileIndex tile)
 
StationScopeResolver::StationScopeResolver(ResolverObject &ro, const StationSpec *statspec, BaseStation *st, TileIndex tile)
 
	: ScopeResolver(ro)
 
{
 
	this->tile = tile;
 
	this->st = st;
 
	this->statspec = statspec;
 
	this->cargo_type = CT_INVALID;
 
	this->axis = INVALID_AXIS;
 
}
 

	
 
static const SpriteGroup *ResolveStation(StationResolverObject *object)
 
static const SpriteGroup *ResolveStation(StationResolverObject &object)
 
{
 
	CargoID ctype = CT_DEFAULT_NA;
 

	
 
	if (object->station_scope.st == NULL) {
 
	if (object.station_scope.st == NULL) {
 
		/* No station, so we are in a purchase list */
 
		ctype = CT_PURCHASE;
 
	} else if (Station::IsExpected(object->station_scope.st)) {
 
		const Station *st = Station::From(object->station_scope.st);
 
	} else if (Station::IsExpected(object.station_scope.st)) {
 
		const Station *st = Station::From(object.station_scope.st);
 
		/* Pick the first cargo that we have waiting */
 
		const CargoSpec *cs;
 
		FOR_ALL_CARGOSPECS(cs) {
 
			if (object->station_scope.statspec->grf_prop.spritegroup[cs->Index()] != NULL &&
 
			if (object.station_scope.statspec->grf_prop.spritegroup[cs->Index()] != NULL &&
 
					st->goods[cs->Index()].cargo.TotalCount() > 0) {
 
				ctype = cs->Index();
 
				break;
 
			}
 
		}
 
	}
 

	
 
	const SpriteGroup *group = object->station_scope.statspec->grf_prop.spritegroup[ctype];
 
	const SpriteGroup *group = object.station_scope.statspec->grf_prop.spritegroup[ctype];
 
	if (group == NULL) {
 
		ctype = CT_DEFAULT;
 
		group = object->station_scope.statspec->grf_prop.spritegroup[ctype];
 
		group = object.station_scope.statspec->grf_prop.spritegroup[ctype];
 
		if (group == NULL) return NULL;
 
	}
 

	
 
	/* Remember the cargo type we've picked */
 
	object->station_scope.cargo_type = ctype;
 
	object.station_scope.cargo_type = ctype;
 

	
 
	return SpriteGroup::Resolve(group, object);
 
}
 

	
 
/**
 
 * Resolve sprites for drawing a station tile.
 
 * @param statspec Station spec
 
 * @param st Station (NULL in GUI)
 
 * @param tile Station tile being drawn (INVALID_TILE in GUI)
 
 * @param var10 Value to put in variable 10; normally 0; 1 when resolving the groundsprite and SSF_SEPARATE_GROUND is set.
 
 * @return First sprite of the Action 1 spriteset to use, minus an offset of 0x42D to accommodate for weird NewGRF specs.
 
 */
 
SpriteID GetCustomStationRelocation(const StationSpec *statspec, BaseStation *st, TileIndex tile, uint32 var10)
 
{
 
	StationResolverObject object(statspec, st, tile, CBID_NO_CALLBACK, var10);
 
	const SpriteGroup *group = ResolveStation(&object);
 
	const SpriteGroup *group = ResolveStation(object);
 
	if (group == NULL || group->type != SGT_RESULT) return 0;
 
	return group->GetResult() - 0x42D;
 
}
 

	
 
/**
 
 * Resolve the sprites for custom station foundations.
 
 * @param statspec Station spec
 
 * @param st Station
 
 * @param tile Station tile being drawn
 
 * @param layout Spritelayout as returned by previous callback
 
 * @param edge_info Information about northern tile edges; whether they need foundations or merge into adjacent tile's foundations.
 
 * @return First sprite of a set of foundation sprites for various slopes, or 0 if default foundations shall be drawn.
 
 */
 
SpriteID GetCustomStationFoundationRelocation(const StationSpec *statspec, BaseStation *st, TileIndex tile, uint layout, uint edge_info)
 
{
 
	/* callback_param1 == 2 means  we are resolving the foundation sprites. */
 
	StationResolverObject object(statspec, st, tile, CBID_NO_CALLBACK, 2, layout | (edge_info << 16));
 

	
 
	ClearRegister(0x100);
 
	const SpriteGroup *group = ResolveStation(&object);
 
	const SpriteGroup *group = ResolveStation(object);
 
	if (group == NULL || group->type != SGT_RESULT) return 0;
 
	return group->GetResult() + GetRegister(0x100);
 
}
 

	
 

	
 
uint16 GetStationCallback(CallbackID callback, uint32 param1, uint32 param2, const StationSpec *statspec, BaseStation *st, TileIndex tile)
 
{
 
	StationResolverObject object(statspec, st, tile, callback, param1, param2);
 
	const SpriteGroup *group = ResolveStation(&object);
 
	const SpriteGroup *group = ResolveStation(object);
 
	if (group == NULL) return CALLBACK_FAILED;
 
	return group->GetCallbackResult();
 
}
 

	
 
/**
 
 * Check the slope of a tile of a new station.
 
 * @param north_tile Norther tile of the station rect.
 
 * @param cur_tile Tile to check.
 
 * @param statspec Station spec.
 
 * @param axis Axis of the new station.
 
 * @param plat_len Platform length.
 
 * @param numtracks Number of platforms.
 
 * @return Succeeded or failed command.
 
 */
 
CommandCost PerformStationTileSlopeCheck(TileIndex north_tile, TileIndex cur_tile, const StationSpec *statspec, Axis axis, byte plat_len, byte numtracks)
 
{
 
	TileIndexDiff diff = cur_tile - north_tile;
 
	Slope slope = GetTileSlope(cur_tile);
 

	
 
	StationResolverObject object(statspec, NULL, cur_tile, CBID_STATION_LAND_SLOPE_CHECK,
 
			(slope << 4) | (slope ^ (axis == AXIS_Y && HasBit(slope, CORNER_W) != HasBit(slope, CORNER_E) ? SLOPE_EW : 0)),
 
			(numtracks << 24) | (plat_len << 16) | (axis == AXIS_Y ? TileX(diff) << 8 | TileY(diff) : TileY(diff) << 8 | TileX(diff)));
 
	object.station_scope.axis = axis;
 

	
 
	const SpriteGroup *group = ResolveStation(&object);
 
	const SpriteGroup *group = ResolveStation(object);
 
	uint16 cb_res = group != NULL ? group->GetCallbackResult() : CALLBACK_FAILED;
 

	
 
	/* Failed callback means success. */
 
	if (cb_res == CALLBACK_FAILED) return CommandCost();
 

	
 
	/* The meaning of bit 10 is inverted for a grf version < 8. */
 
	if (statspec->grf_prop.grffile->grf_version < 8) ToggleBit(cb_res, 10);
 
	return GetErrorMessageFromLocationCallbackResult(cb_res, statspec->grf_prop.grffile->grfid, STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
 
}
 

	
 

	
 
/**
 
@@ -1014,25 +1014,25 @@ void TriggerStationRandomisation(Station
 
			if (ss == NULL) continue;
 

	
 
			/* Cargo taken "will only be triggered if all of those
 
			 * cargo types have no more cargo waiting." */
 
			if (trigger == SRT_CARGO_TAKEN) {
 
				if ((ss->cargo_triggers & ~empty_mask) != 0) continue;
 
			}
 

	
 
			if (cargo_type == CT_INVALID || HasBit(ss->cargo_triggers, cargo_type)) {
 
				StationResolverObject object(ss, st, tile, CBID_RANDOM_TRIGGER, 0);
 
				object.trigger = trigger_bit;
 

	
 
				const SpriteGroup *group = ResolveStation(&object);
 
				const SpriteGroup *group = ResolveStation(object);
 
				if (group == NULL) continue;
 

	
 
				uint32 reseed = object.GetReseedSum();
 
				if (reseed != 0) {
 
					whole_reseed |= reseed;
 
					reseed >>= 16;
 

	
 
					/* Set individual tile random bits */
 
					uint8 random_bits = GetStationTileRandomBits(tile);
 
					random_bits &= ~reseed;
 
					random_bits |= Random() & reseed;
 
					SetStationTileRandomBits(tile, random_bits);
src/newgrf_station.h
Show inline comments
 
@@ -21,25 +21,25 @@
 
#include "rail_type.h"
 
#include "newgrf_spritegroup.h"
 
#include "newgrf_town.h"
 

	
 
/** Scope resolver for stations. */
 
struct StationScopeResolver : public ScopeResolver {
 
	TileIndex tile;                     ///< %Tile of the station.
 
	struct BaseStation *st;             ///< Instance of the station.
 
	const struct StationSpec *statspec; ///< Station (type) specification.
 
	CargoID cargo_type;                 ///< Type of cargo of the station.
 
	Axis axis;                          ///< Station axis, used only for the slope check callback.
 

	
 
	StationScopeResolver(ResolverObject *ro, const StationSpec *statspec, BaseStation *st, TileIndex tile);
 
	StationScopeResolver(ResolverObject &ro, const StationSpec *statspec, BaseStation *st, TileIndex tile);
 

	
 
	/* virtual */ uint32 GetRandomBits() const;
 
	/* virtual */ uint32 GetTriggers() const;
 
	/* virtual */ void SetTriggers(int triggers) const;
 

	
 
	/* virtual */ uint32 GetVariable(byte variable, uint32 parameter, bool *available) const;
 
};
 

	
 
/** Station resolver. */
 
struct StationResolverObject : public ResolverObject {
 
	StationScopeResolver station_scope; ///< The station scope resolver.
 
	TownScopeResolver *town_scope;      ///< The town scope resolver (created on the first call).
src/newgrf_town.cpp
Show inline comments
 
@@ -11,49 +11,49 @@
 

	
 
#include "stdafx.h"
 
#include "debug.h"
 
#include "town.h"
 
#include "newgrf_town.h"
 

	
 
/**
 
 * Resolver of a town scope.
 
 * @param ro Surrounding resolver.
 
 * @param t %Town of the scope.
 
 * @param readonly Scope may change persistent storage of the town.
 
 */
 
TownScopeResolver::TownScopeResolver(ResolverObject *ro, Town *t, bool readonly) : ScopeResolver(ro)
 
TownScopeResolver::TownScopeResolver(ResolverObject &ro, Town *t, bool readonly) : ScopeResolver(ro)
 
{
 
	this->t = t;
 
	this->readonly = readonly;
 
}
 

	
 
/* virtual */ uint32 TownScopeResolver::GetVariable(byte variable, uint32 parameter, bool *available) const
 
{
 
	switch (variable) {
 
		/* Larger towns */
 
		case 0x40:
 
			if (_settings_game.economy.larger_towns == 0) return 2;
 
			if (this->t->larger_town) return 1;
 
			return 0;
 

	
 
		/* Town index */
 
		case 0x41: return this->t->index;
 

	
 
		/* Get a variable from the persistent storage */
 
		case 0x7C: {
 
			/* Check the persistent storage for the GrfID stored in register 100h. */
 
			uint32 grfid = GetRegister(0x100);
 
			if (grfid == 0xFFFFFFFF) {
 
				if (this->ro->grffile == NULL) return 0;
 
				grfid = this->ro->grffile->grfid;
 
				if (this->ro.grffile == NULL) return 0;
 
				grfid = this->ro.grffile->grfid;
 
			}
 

	
 
			std::list<PersistentStorage *>::iterator iter;
 
			for (iter = this->t->psa_list.begin(); iter != this->t->psa_list.end(); iter++) {
 
				if ((*iter)->grfid == grfid) return (*iter)->GetValue(parameter);
 
			}
 

	
 
			return 0;
 
		}
 

	
 
		/* Town properties */
 
		case 0x80: return this->t->xy;
 
@@ -126,48 +126,48 @@ TownScopeResolver::TownScopeResolver(Res
 
	DEBUG(grf, 1, "Unhandled town variable 0x%X", variable);
 

	
 
	*available = false;
 
	return UINT_MAX;
 
}
 

	
 
/* virtual */ void TownScopeResolver::StorePSA(uint pos, int32 value)
 
{
 
	if (this->readonly) return;
 

	
 
	assert(this->t != NULL);
 
	/* We can't store anything if the caller has no #GRFFile. */
 
	if (this->ro->grffile == NULL) return;
 
	if (this->ro.grffile == NULL) return;
 

	
 
	/* Check the persistent storage for the GrfID stored in register 100h. */
 
	uint32 grfid = GetRegister(0x100);
 

	
 
	/* A NewGRF can only write in the persistent storage associated to its own GRFID. */
 
	if (grfid == 0xFFFFFFFF) grfid = this->ro->grffile->grfid;
 
	if (grfid != this->ro->grffile->grfid) return;
 
	if (grfid == 0xFFFFFFFF) grfid = this->ro.grffile->grfid;
 
	if (grfid != this->ro.grffile->grfid) return;
 

	
 
	/* Check if the storage exists. */
 
	std::list<PersistentStorage *>::iterator iter;
 
	for (iter = t->psa_list.begin(); iter != t->psa_list.end(); iter++) {
 
		if ((*iter)->grfid == grfid) {
 
			(*iter)->StoreValue(pos, value);
 
			return;
 
		}
 
	}
 

	
 
	/* Create a new storage. */
 
	assert(PersistentStorage::CanAllocateItem());
 
	PersistentStorage *psa = new PersistentStorage(grfid);
 
	psa->StoreValue(pos, value);
 
	t->psa_list.push_back(psa);
 
}
 

	
 
/**
 
 * Resolver for a town.
 
 * @param grffile NewGRF file associated with the town.
 
 * @param t %Town of the scope.
 
 * @param readonly Scope may change persistent storage of the town.
 
 */
 
TownResolverObject::TownResolverObject(const struct GRFFile *grffile, Town *t, bool readonly)
 
		: ResolverObject(grffile), town_scope(this, t, readonly)
 
		: ResolverObject(grffile), town_scope(*this, t, readonly)
 
{
 
}
 

	
src/newgrf_town.h
Show inline comments
 
@@ -16,25 +16,25 @@
 
#include "newgrf_spritegroup.h"
 

	
 
/**
 
 * Scope resolver for a town.
 
 * @note Currently there is no direct town resolver; we only need to get town
 
 *       variable results from inside stations, house tiles and industries,
 
 *       and to check the town's persistent storage.
 
 */
 
struct TownScopeResolver : public ScopeResolver {
 
	Town *t;       ///< %Town of the scope.
 
	bool readonly; ///< When set, persistent storage of the town is read-only,
 

	
 
	TownScopeResolver(ResolverObject *ro, Town *t, bool readonly);
 
	TownScopeResolver(ResolverObject &ro, Town *t, bool readonly);
 

	
 
	virtual uint32 GetVariable(byte variable, uint32 parameter, bool *available) const;
 
	virtual void StorePSA(uint reg, int32 value);
 
};
 

	
 
/** Resolver of town properties. */
 
struct TownResolverObject : public ResolverObject {
 
	TownScopeResolver town_scope; ///< Scope resolver specific for towns.
 

	
 
	TownResolverObject(const struct GRFFile *grffile, Town *t, bool readonly);
 

	
 
	/* virtual */ ScopeResolver *GetScope(VarSpriteGroupScope scope = VSG_SCOPE_SELF, byte relative = 0)
src/station_base.h
Show inline comments
 
@@ -483,25 +483,25 @@ public:
 
	Rect GetCatchmentRect() const;
 

	
 
	/* virtual */ inline bool TileBelongsToRailStation(TileIndex tile) const
 
	{
 
		return IsRailStationTile(tile) && GetStationIndex(tile) == this->index;
 
	}
 

	
 
	inline bool TileBelongsToAirport(TileIndex tile) const
 
	{
 
		return IsAirportTile(tile) && GetStationIndex(tile) == this->index;
 
	}
 

	
 
	/* virtual */ uint32 GetNewGRFVariable(const ResolverObject *object, byte variable, byte parameter, bool *available) const;
 
	/* virtual */ uint32 GetNewGRFVariable(const ResolverObject &object, byte variable, byte parameter, bool *available) const;
 

	
 
	/* virtual */ void GetTileArea(TileArea *ta, StationType type) const;
 
};
 

	
 
#define FOR_ALL_STATIONS(var) FOR_ALL_BASE_STATIONS_OF_TYPE(Station, var)
 

	
 
/** Iterator to iterate over all tiles belonging to an airport. */
 
class AirportTileIterator : public OrthogonalTileIterator {
 
private:
 
	const Station *st; ///< The station the airport is a part of.
 

	
 
public:
src/waypoint_base.h
Show inline comments
 
@@ -23,25 +23,25 @@ struct Waypoint FINAL : SpecializedStati
 
	 * @param tile The location of the waypoint.
 
	 */
 
	Waypoint(TileIndex tile = INVALID_TILE) : SpecializedStation<Waypoint, true>(tile) { }
 
	~Waypoint();
 

	
 
	void UpdateVirtCoord();
 

	
 
	/* virtual */ inline bool TileBelongsToRailStation(TileIndex tile) const
 
	{
 
		return IsRailWaypointTile(tile) && GetStationIndex(tile) == this->index;
 
	}
 

	
 
	/* virtual */ uint32 GetNewGRFVariable(const struct ResolverObject *object, byte variable, byte parameter, bool *available) const;
 
	/* virtual */ uint32 GetNewGRFVariable(const struct ResolverObject &object, byte variable, byte parameter, bool *available) const;
 

	
 
	/* virtual */ void GetTileArea(TileArea *ta, StationType type) const;
 

	
 
	/* virtual */ uint GetPlatformLength(TileIndex tile, DiagDirection dir) const
 
	{
 
		return 1;
 
	}
 

	
 
	/* virtual */ uint GetPlatformLength(TileIndex tile) const
 
	{
 
		return 1;
 
	}
0 comments (0 inline, 0 general)