Changeset - r26672:e217fb99c0ac
[Not reviewed]
master
0 6 0
PeterN - 23 months ago 2022-12-23 21:02:14
peter1138@openttd.org
Change: Support flipping shorter engines without NewGRF support. (#10262)

* Change: Support flipping shorter engines without NewGRF support.
* Cleanup: Remove write-only prop27_set temporary flag.
6 files changed with 48 insertions and 27 deletions:
0 comments (0 inline, 0 general)
src/engine_type.h
Show inline comments
 
@@ -155,7 +155,7 @@ enum EngineMiscFlags {
 
	EF_ROAD_TRAM  = 0, ///< Road vehicle is a tram/light rail vehicle
 
	EF_USES_2CC   = 1, ///< Vehicle uses two company colours
 
	EF_RAIL_IS_MU = 2, ///< Rail vehicle is a multiple-unit (DMU/EMU)
 
	EF_RAIL_FLIPS = 3, ///< Rail vehicle can be flipped in the depot
 
	EF_RAIL_FLIPS = 3, ///< Rail vehicle has old depot-flip handling
 
	EF_AUTO_REFIT = 4, ///< Automatic refitting is allowed
 
	EF_NO_DEFAULT_CARGO_MULTIPLIER = 5, ///< Use the new capacity algorithm. The default cargotype of the vehicle does not affect capacity multipliers. CB 15 is also called in purchase list.
 
	EF_NO_BREAKDOWN_SMOKE          = 6, ///< Do not show black smoke during a breakdown.
src/newgrf.cpp
Show inline comments
 
@@ -328,7 +328,6 @@ struct GRFTempEngineData {
 
	uint8 roadtramtype;
 
	const GRFFile *defaultcargo_grf; ///< GRF defining the cargo translation table to use if the default cargo is the 'first refittable'.
 
	Refittability refittability;     ///< Did the newgrf set any refittability property? If not, default refittability will be applied.
 
	bool prop27_set;         ///< Did the NewGRF set property 27 (misc flags)?
 
	uint8 rv_max_speed;      ///< Temporary storage of RV prop 15, maximum speed in mph/0.8
 
	CargoTypes ctt_include_mask; ///< Cargo types always included in the refit mask.
 
	CargoTypes ctt_exclude_mask; ///< Cargo types always excluded from the refit mask.
 
@@ -1295,7 +1294,6 @@ static ChangeInfoResult RailVehicleChang
 
			case 0x27: // Miscellaneous flags
 
				ei->misc_flags = buf->ReadByte();
 
				_loaded_newgrf_features.has_2CC |= HasBit(ei->misc_flags, EF_USES_2CC);
 
				_gted[e->index].prop27_set = true;
 
				break;
 

	
 
			case 0x28: // Cargo classes allowed
 
@@ -8985,13 +8983,6 @@ static void FinaliseEngineArray()
 

	
 
		if (!HasBit(e->info.climates, _settings_game.game_creation.landscape)) continue;
 

	
 
		/* When the train does not set property 27 (misc flags), but it
 
		 * is overridden by a NewGRF graphically we want to disable the
 
		 * flipping possibility. */
 
		if (e->type == VEH_TRAIN && !_gted[e->index].prop27_set && e->GetGRF() != nullptr && is_custom_sprite(e->u.rail.image_index)) {
 
			ClrBit(e->info.misc_flags, EF_RAIL_FLIPS);
 
		}
 

	
 
		/* Skip wagons, there livery is defined via the engine */
 
		if (e->type != VEH_TRAIN || e->u.rail.railveh_type != RAILVEH_WAGON) {
 
			LiveryScheme ls = GetEngineLiveryScheme(e->index, INVALID_ENGINE, nullptr);
src/table/engines.h
Show inline comments
 
@@ -24,7 +24,7 @@
 
 * @param f Bitmask of the climates
 
 * @note the 5 between b and f is the load amount
 
 */
 
#define MT(a, b, c, d, e, f) { DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, f, e, 0, 8, 1 << EF_RAIL_FLIPS, 0, 0, STR_EMPTY, CARGO_AGING_TICKS }
 
#define MT(a, b, c, d, e, f) { DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, f, e, 0, 8, 0, 0, 0, STR_EMPTY, CARGO_AGING_TICKS }
 

	
 
/**
 
 * Writes the properties of a multiple-unit train into the EngineInfo struct.
 
@@ -37,7 +37,7 @@
 
 * @param f Bitmask of the climates
 
 * @note the 5 between b and f is the load amount
 
 */
 
#define MM(a, b, c, d, e, f) { DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, f, e, 0, 8, 1 << EF_RAIL_FLIPS | 1 << EF_RAIL_IS_MU, 0, 0, STR_EMPTY, CARGO_AGING_TICKS }
 
#define MM(a, b, c, d, e, f) { DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, f, e, 0, 8, 1 << EF_RAIL_IS_MU, 0, 0, STR_EMPTY, CARGO_AGING_TICKS }
 

	
 
/**
 
 * Writes the properties of a train carriage into the EngineInfo struct.
 
@@ -50,7 +50,7 @@
 
 * @see MT
 
 * @note the 5 between b and f is the load amount
 
 */
 
#define MW(a, b, c, d, e, f) { DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, f, e, 0, 8, 1 << EF_RAIL_FLIPS, 0, 0, STR_EMPTY, CARGO_AGING_TICKS }
 
#define MW(a, b, c, d, e, f) { DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, f, e, 0, 8, 0, 0, 0, STR_EMPTY, CARGO_AGING_TICKS }
 

	
 
/**
 
 * Writes the properties of a road vehicle into the EngineInfo struct.
src/train.h
Show inline comments
 
@@ -116,6 +116,7 @@ struct Train FINAL : public GroundVehicl
 
	int GetDisplaySpeed() const override { return this->gcache.last_speed; }
 
	int GetDisplayMaxSpeed() const override { return this->vcache.cached_max_speed; }
 
	Money GetRunningCost() const override;
 
	int GetCursorImageOffset() const;
 
	int GetDisplayImageWidth(Point *offset = nullptr) const;
 
	bool IsInDepot() const override { return this->track == TRACK_BIT_DEPOT; }
 
	bool Tick() override;
src/train_cmd.cpp
Show inline comments
 
@@ -434,6 +434,21 @@ void Train::UpdateAcceleration()
 
	this->acceleration = Clamp(power / weight * 4, 1, 255);
 
}
 

	
 
int Train::GetCursorImageOffset() const
 
{
 
	if (this->gcache.cached_veh_length != 8 && HasBit(this->flags, VRF_REVERSE_DIRECTION) && !HasBit(EngInfo(this->engine_type)->misc_flags, EF_RAIL_FLIPS)) {
 
		int reference_width = TRAININFO_DEFAULT_VEHICLE_WIDTH;
 

	
 
		const Engine *e = this->GetEngine();
 
		if (e->GetGRF() != nullptr && is_custom_sprite(e->u.rail.image_index)) {
 
			reference_width = e->GetGRF()->traininfo_vehicle_width;
 
		}
 

	
 
		return ScaleSpriteTrad((this->gcache.cached_veh_length - (int)VEHICLE_LENGTH) * reference_width / (int)VEHICLE_LENGTH);
 
	}
 
	return 0;
 
}
 

	
 
/**
 
 * Get the width of a train vehicle image in the GUI.
 
 * @param offset Additional offset for positioning the sprite; set to nullptr if not needed
 
@@ -451,7 +466,11 @@ int Train::GetDisplayImageWidth(Point *o
 
	}
 

	
 
	if (offset != nullptr) {
 
		offset->x = ScaleSpriteTrad(reference_width) / 2;
 
		if (HasBit(this->flags, VRF_REVERSE_DIRECTION) && !HasBit(EngInfo(this->engine_type)->misc_flags, EF_RAIL_FLIPS)) {
 
			offset->x = ScaleSpriteTrad((this->gcache.cached_veh_length - VEHICLE_LENGTH / 2) * reference_width / VEHICLE_LENGTH);
 
		} else {
 
			offset->x = ScaleSpriteTrad(reference_width) / 2;
 
		}
 
		offset->y = ScaleSpriteTrad(vehicle_pitch);
 
	}
 
	return ScaleSpriteTrad(this->gcache.cached_veh_length * reference_width / VEHICLE_LENGTH);
 
@@ -1438,7 +1457,15 @@ void Train::UpdateDeltaXY()
 
	this->x_bb_offs =  0;
 
	this->y_bb_offs =  0;
 

	
 
	if (!IsDiagonalDirection(this->direction)) {
 
	/* Set if flipped and engine is NOT flagged with custom flip handling. */
 
	int flipped = HasBit(this->flags, VRF_REVERSE_DIRECTION) && !HasBit(EngInfo(this->engine_type)->misc_flags, EF_RAIL_FLIPS);
 
	/* If flipped and vehicle length is odd, we need to adjust the bounding box offset slightly. */
 
	int flip_offs = flipped && (this->gcache.cached_veh_length & 1);
 

	
 
	Direction dir = this->direction;
 
	if (flipped) dir = ReverseDir(dir);
 

	
 
	if (!IsDiagonalDirection(dir)) {
 
		static const int _sign_table[] =
 
		{
 
			/* x, y */
 
@@ -1448,25 +1475,25 @@ void Train::UpdateDeltaXY()
 
			 1, -1, // DIR_W
 
		};
 

	
 
		int half_shorten = (VEHICLE_LENGTH - this->gcache.cached_veh_length) / 2;
 
		int half_shorten = (VEHICLE_LENGTH - this->gcache.cached_veh_length + flipped) / 2;
 

	
 
		/* For all straight directions, move the bound box to the centre of the vehicle, but keep the size. */
 
		this->x_offs -= half_shorten * _sign_table[this->direction];
 
		this->y_offs -= half_shorten * _sign_table[this->direction + 1];
 
		this->x_extent += this->x_bb_offs = half_shorten * _sign_table[direction];
 
		this->y_extent += this->y_bb_offs = half_shorten * _sign_table[direction + 1];
 
		this->x_offs -= half_shorten * _sign_table[dir];
 
		this->y_offs -= half_shorten * _sign_table[dir + 1];
 
		this->x_extent += this->x_bb_offs = half_shorten * _sign_table[dir];
 
		this->y_extent += this->y_bb_offs = half_shorten * _sign_table[dir + 1];
 
	} else {
 
		switch (this->direction) {
 
		switch (dir) {
 
				/* Shorten southern corner of the bounding box according the vehicle length
 
				 * and center the bounding box on the vehicle. */
 
			case DIR_NE:
 
				this->x_offs    = 1 - (this->gcache.cached_veh_length + 1) / 2;
 
				this->x_offs    = 1 - (this->gcache.cached_veh_length + 1) / 2 + flip_offs;
 
				this->x_extent  = this->gcache.cached_veh_length - 1;
 
				this->x_bb_offs = -1;
 
				break;
 

	
 
			case DIR_NW:
 
				this->y_offs    = 1 - (this->gcache.cached_veh_length + 1) / 2;
 
				this->y_offs    = 1 - (this->gcache.cached_veh_length + 1) / 2 + flip_offs;
 
				this->y_extent  = this->gcache.cached_veh_length - 1;
 
				this->y_bb_offs = -1;
 
				break;
 
@@ -1474,13 +1501,13 @@ void Train::UpdateDeltaXY()
 
				/* Move northern corner of the bounding box down according to vehicle length
 
				 * and center the bounding box on the vehicle. */
 
			case DIR_SW:
 
				this->x_offs    = 1 + (this->gcache.cached_veh_length + 1) / 2 - VEHICLE_LENGTH;
 
				this->x_offs    = 1 + (this->gcache.cached_veh_length + 1) / 2 - VEHICLE_LENGTH - flip_offs;
 
				this->x_extent  = VEHICLE_LENGTH - 1;
 
				this->x_bb_offs = VEHICLE_LENGTH - this->gcache.cached_veh_length - 1;
 
				break;
 

	
 
			case DIR_SE:
 
				this->y_offs    = 1 + (this->gcache.cached_veh_length + 1) / 2 - VEHICLE_LENGTH;
 
				this->y_offs    = 1 + (this->gcache.cached_veh_length + 1) / 2 - VEHICLE_LENGTH - flip_offs;
 
				this->y_extent  = VEHICLE_LENGTH - 1;
 
				this->y_bb_offs = VEHICLE_LENGTH - this->gcache.cached_veh_length - 1;
 
				break;
 
@@ -1975,7 +2002,6 @@ CommandCost CmdReverseTrainDirection(DoC
 
		if (v->IsMultiheaded() || HasBit(EngInfo(v->engine_type)->callback_mask, CBM_VEHICLE_ARTIC_ENGINE)) {
 
			return_cmd_error(STR_ERROR_CAN_T_REVERSE_DIRECTION_RAIL_VEHICLE_MULTIPLE_UNITS);
 
		}
 
		if (!HasBit(EngInfo(v->engine_type)->misc_flags, EF_RAIL_FLIPS)) return CMD_ERROR;
 

	
 
		Train *front = v->First();
 
		/* make sure the vehicle is stopped in the depot */
src/vehicle_gui.cpp
Show inline comments
 
@@ -3418,11 +3418,14 @@ void SetMouseCursorVehicle(const Vehicle
 

	
 
		if (_cursor.sprite_count + seq.count > lengthof(_cursor.sprite_seq)) break;
 

	
 
		int x_offs = 0;
 
		if (v->type == VEH_TRAIN) x_offs = Train::From(v)->GetCursorImageOffset();
 

	
 
		for (uint i = 0; i < seq.count; ++i) {
 
			PaletteID pal2 = (v->vehstatus & VS_CRASHED) || !seq.seq[i].pal ? pal : seq.seq[i].pal;
 
			_cursor.sprite_seq[_cursor.sprite_count].sprite = seq.seq[i].sprite;
 
			_cursor.sprite_seq[_cursor.sprite_count].pal = pal2;
 
			_cursor.sprite_pos[_cursor.sprite_count].x = rtl ? -total_width : total_width;
 
			_cursor.sprite_pos[_cursor.sprite_count].x = rtl ? (-total_width + x_offs) : (total_width + x_offs);
 
			_cursor.sprite_pos[_cursor.sprite_count].y = y_offset;
 
			_cursor.sprite_count++;
 
		}
0 comments (0 inline, 0 general)