mirror of
https://github.com/JGRennison/OpenTTD-patches.git
synced 2024-11-11 13:10:45 +00:00
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.
This commit is contained in:
parent
a971eee2e0
commit
7b5edba76c
@ -155,7 +155,7 @@ enum EngineMiscFlags {
|
|||||||
EF_ROAD_TRAM = 0, ///< Road vehicle is a tram/light rail vehicle
|
EF_ROAD_TRAM = 0, ///< Road vehicle is a tram/light rail vehicle
|
||||||
EF_USES_2CC = 1, ///< Vehicle uses two company colours
|
EF_USES_2CC = 1, ///< Vehicle uses two company colours
|
||||||
EF_RAIL_IS_MU = 2, ///< Rail vehicle is a multiple-unit (DMU/EMU)
|
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_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_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.
|
EF_NO_BREAKDOWN_SMOKE = 6, ///< Do not show black smoke during a breakdown.
|
||||||
|
@ -328,7 +328,6 @@ struct GRFTempEngineData {
|
|||||||
uint8 roadtramtype;
|
uint8 roadtramtype;
|
||||||
const GRFFile *defaultcargo_grf; ///< GRF defining the cargo translation table to use if the default cargo is the 'first refittable'.
|
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.
|
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
|
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_include_mask; ///< Cargo types always included in the refit mask.
|
||||||
CargoTypes ctt_exclude_mask; ///< Cargo types always excluded from the refit mask.
|
CargoTypes ctt_exclude_mask; ///< Cargo types always excluded from the refit mask.
|
||||||
@ -1295,7 +1294,6 @@ static ChangeInfoResult RailVehicleChangeInfo(uint engine, int numinfo, int prop
|
|||||||
case 0x27: // Miscellaneous flags
|
case 0x27: // Miscellaneous flags
|
||||||
ei->misc_flags = buf->ReadByte();
|
ei->misc_flags = buf->ReadByte();
|
||||||
_loaded_newgrf_features.has_2CC |= HasBit(ei->misc_flags, EF_USES_2CC);
|
_loaded_newgrf_features.has_2CC |= HasBit(ei->misc_flags, EF_USES_2CC);
|
||||||
_gted[e->index].prop27_set = true;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x28: // Cargo classes allowed
|
case 0x28: // Cargo classes allowed
|
||||||
@ -8985,13 +8983,6 @@ static void FinaliseEngineArray()
|
|||||||
|
|
||||||
if (!HasBit(e->info.climates, _settings_game.game_creation.landscape)) continue;
|
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 */
|
/* Skip wagons, there livery is defined via the engine */
|
||||||
if (e->type != VEH_TRAIN || e->u.rail.railveh_type != RAILVEH_WAGON) {
|
if (e->type != VEH_TRAIN || e->u.rail.railveh_type != RAILVEH_WAGON) {
|
||||||
LiveryScheme ls = GetEngineLiveryScheme(e->index, INVALID_ENGINE, nullptr);
|
LiveryScheme ls = GetEngineLiveryScheme(e->index, INVALID_ENGINE, nullptr);
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
* @param f Bitmask of the climates
|
* @param f Bitmask of the climates
|
||||||
* @note the 5 between b and f is the load amount
|
* @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.
|
* Writes the properties of a multiple-unit train into the EngineInfo struct.
|
||||||
@ -37,7 +37,7 @@
|
|||||||
* @param f Bitmask of the climates
|
* @param f Bitmask of the climates
|
||||||
* @note the 5 between b and f is the load amount
|
* @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.
|
* Writes the properties of a train carriage into the EngineInfo struct.
|
||||||
@ -50,7 +50,7 @@
|
|||||||
* @see MT
|
* @see MT
|
||||||
* @note the 5 between b and f is the load amount
|
* @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.
|
* Writes the properties of a road vehicle into the EngineInfo struct.
|
||||||
|
@ -116,6 +116,7 @@ struct Train FINAL : public GroundVehicle<Train, VEH_TRAIN> {
|
|||||||
int GetDisplaySpeed() const override { return this->gcache.last_speed; }
|
int GetDisplaySpeed() const override { return this->gcache.last_speed; }
|
||||||
int GetDisplayMaxSpeed() const override { return this->vcache.cached_max_speed; }
|
int GetDisplayMaxSpeed() const override { return this->vcache.cached_max_speed; }
|
||||||
Money GetRunningCost() const override;
|
Money GetRunningCost() const override;
|
||||||
|
int GetCursorImageOffset() const;
|
||||||
int GetDisplayImageWidth(Point *offset = nullptr) const;
|
int GetDisplayImageWidth(Point *offset = nullptr) const;
|
||||||
bool IsInDepot() const override { return this->track == TRACK_BIT_DEPOT; }
|
bool IsInDepot() const override { return this->track == TRACK_BIT_DEPOT; }
|
||||||
bool Tick() override;
|
bool Tick() override;
|
||||||
|
@ -434,6 +434,21 @@ void Train::UpdateAcceleration()
|
|||||||
this->acceleration = Clamp(power / weight * 4, 1, 255);
|
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.
|
* 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
|
* @param offset Additional offset for positioning the sprite; set to nullptr if not needed
|
||||||
@ -451,7 +466,11 @@ int Train::GetDisplayImageWidth(Point *offset) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (offset != nullptr) {
|
if (offset != nullptr) {
|
||||||
|
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->x = ScaleSpriteTrad(reference_width) / 2;
|
||||||
|
}
|
||||||
offset->y = ScaleSpriteTrad(vehicle_pitch);
|
offset->y = ScaleSpriteTrad(vehicle_pitch);
|
||||||
}
|
}
|
||||||
return ScaleSpriteTrad(this->gcache.cached_veh_length * reference_width / VEHICLE_LENGTH);
|
return ScaleSpriteTrad(this->gcache.cached_veh_length * reference_width / VEHICLE_LENGTH);
|
||||||
@ -1438,7 +1457,15 @@ void Train::UpdateDeltaXY()
|
|||||||
this->x_bb_offs = 0;
|
this->x_bb_offs = 0;
|
||||||
this->y_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[] =
|
static const int _sign_table[] =
|
||||||
{
|
{
|
||||||
/* x, y */
|
/* x, y */
|
||||||
@ -1448,25 +1475,25 @@ void Train::UpdateDeltaXY()
|
|||||||
1, -1, // DIR_W
|
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. */
|
/* 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->x_offs -= half_shorten * _sign_table[dir];
|
||||||
this->y_offs -= half_shorten * _sign_table[this->direction + 1];
|
this->y_offs -= half_shorten * _sign_table[dir + 1];
|
||||||
this->x_extent += this->x_bb_offs = half_shorten * _sign_table[direction];
|
this->x_extent += this->x_bb_offs = half_shorten * _sign_table[dir];
|
||||||
this->y_extent += this->y_bb_offs = half_shorten * _sign_table[direction + 1];
|
this->y_extent += this->y_bb_offs = half_shorten * _sign_table[dir + 1];
|
||||||
} else {
|
} else {
|
||||||
switch (this->direction) {
|
switch (dir) {
|
||||||
/* Shorten southern corner of the bounding box according the vehicle length
|
/* Shorten southern corner of the bounding box according the vehicle length
|
||||||
* and center the bounding box on the vehicle. */
|
* and center the bounding box on the vehicle. */
|
||||||
case DIR_NE:
|
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_extent = this->gcache.cached_veh_length - 1;
|
||||||
this->x_bb_offs = -1;
|
this->x_bb_offs = -1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DIR_NW:
|
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_extent = this->gcache.cached_veh_length - 1;
|
||||||
this->y_bb_offs = -1;
|
this->y_bb_offs = -1;
|
||||||
break;
|
break;
|
||||||
@ -1474,13 +1501,13 @@ void Train::UpdateDeltaXY()
|
|||||||
/* Move northern corner of the bounding box down according to vehicle length
|
/* Move northern corner of the bounding box down according to vehicle length
|
||||||
* and center the bounding box on the vehicle. */
|
* and center the bounding box on the vehicle. */
|
||||||
case DIR_SW:
|
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_extent = VEHICLE_LENGTH - 1;
|
||||||
this->x_bb_offs = VEHICLE_LENGTH - this->gcache.cached_veh_length - 1;
|
this->x_bb_offs = VEHICLE_LENGTH - this->gcache.cached_veh_length - 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DIR_SE:
|
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_extent = VEHICLE_LENGTH - 1;
|
||||||
this->y_bb_offs = VEHICLE_LENGTH - this->gcache.cached_veh_length - 1;
|
this->y_bb_offs = VEHICLE_LENGTH - this->gcache.cached_veh_length - 1;
|
||||||
break;
|
break;
|
||||||
@ -1975,7 +2002,6 @@ CommandCost CmdReverseTrainDirection(DoCommandFlag flags, VehicleID veh_id, bool
|
|||||||
if (v->IsMultiheaded() || HasBit(EngInfo(v->engine_type)->callback_mask, CBM_VEHICLE_ARTIC_ENGINE)) {
|
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);
|
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();
|
Train *front = v->First();
|
||||||
/* make sure the vehicle is stopped in the depot */
|
/* make sure the vehicle is stopped in the depot */
|
||||||
|
@ -3418,11 +3418,14 @@ void SetMouseCursorVehicle(const Vehicle *v, EngineImageType image_type)
|
|||||||
|
|
||||||
if (_cursor.sprite_count + seq.count > lengthof(_cursor.sprite_seq)) break;
|
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) {
|
for (uint i = 0; i < seq.count; ++i) {
|
||||||
PaletteID pal2 = (v->vehstatus & VS_CRASHED) || !seq.seq[i].pal ? pal : seq.seq[i].pal;
|
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].sprite = seq.seq[i].sprite;
|
||||||
_cursor.sprite_seq[_cursor.sprite_count].pal = pal2;
|
_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_pos[_cursor.sprite_count].y = y_offset;
|
||||||
_cursor.sprite_count++;
|
_cursor.sprite_count++;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user