Merge branch 'openttd'
This commit is contained in:
@@ -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,10 +466,14 @@ int Train::GetDisplayImageWidth(Point *offset) const
|
||||
}
|
||||
|
||||
if (offset != nullptr) {
|
||||
offset->x = ScaleGUITrad(reference_width) / 2;
|
||||
offset->y = ScaleGUITrad(vehicle_pitch);
|
||||
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 ScaleGUITrad(this->gcache.cached_veh_length * reference_width / VEHICLE_LENGTH);
|
||||
return ScaleSpriteTrad(this->gcache.cached_veh_length * reference_width / VEHICLE_LENGTH);
|
||||
}
|
||||
|
||||
static SpriteID GetDefaultTrainSprite(uint8 spritenum, Direction direction)
|
||||
@@ -500,7 +519,7 @@ static void GetRailIcon(EngineID engine, bool rear_head, int &y, EngineImageType
|
||||
GetCustomVehicleIcon(engine, dir, image_type, result);
|
||||
if (result->IsValid()) {
|
||||
if (e->GetGRF() != nullptr) {
|
||||
y += ScaleGUITrad(e->GetGRF()->traininfo_vehicle_pitch);
|
||||
y += ScaleSpriteTrad(e->GetGRF()->traininfo_vehicle_pitch);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -528,11 +547,11 @@ void DrawTrainEngine(int left, int right, int preferred_x, int y, EngineID engin
|
||||
seqr.GetBounds(&rectr);
|
||||
|
||||
preferred_x = Clamp(preferred_x,
|
||||
left - UnScaleGUI(rectf.left) + ScaleGUITrad(14),
|
||||
right - UnScaleGUI(rectr.right) - ScaleGUITrad(15));
|
||||
left - UnScaleGUI(rectf.left) + ScaleSpriteTrad(14),
|
||||
right - UnScaleGUI(rectr.right) - ScaleSpriteTrad(15));
|
||||
|
||||
seqf.Draw(preferred_x - ScaleGUITrad(14), yf, pal, pal == PALETTE_CRASH);
|
||||
seqr.Draw(preferred_x + ScaleGUITrad(15), yr, pal, pal == PALETTE_CRASH);
|
||||
seqf.Draw(preferred_x - ScaleSpriteTrad(14), yf, pal, pal == PALETTE_CRASH);
|
||||
seqr.Draw(preferred_x + ScaleSpriteTrad(15), yr, pal, pal == PALETTE_CRASH);
|
||||
} else {
|
||||
VehicleSpriteSeq seq;
|
||||
GetRailIcon(engine, false, y, image_type, &seq);
|
||||
@@ -566,8 +585,8 @@ void GetTrainSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs,
|
||||
Rect rect;
|
||||
seq.GetBounds(&rect);
|
||||
|
||||
width = UnScaleGUI(rect.right - rect.left + 1);
|
||||
height = UnScaleGUI(rect.bottom - rect.top + 1);
|
||||
width = UnScaleGUI(rect.Width());
|
||||
height = UnScaleGUI(rect.Height());
|
||||
xoffs = UnScaleGUI(rect.left);
|
||||
yoffs = UnScaleGUI(rect.top);
|
||||
|
||||
@@ -576,9 +595,9 @@ void GetTrainSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs,
|
||||
seq.GetBounds(&rect);
|
||||
|
||||
/* Calculate values relative to an imaginary center between the two sprites. */
|
||||
width = ScaleGUITrad(TRAININFO_DEFAULT_VEHICLE_WIDTH) + UnScaleGUI(rect.right) - xoffs;
|
||||
height = std::max<uint>(height, UnScaleGUI(rect.bottom - rect.top + 1));
|
||||
xoffs = xoffs - ScaleGUITrad(TRAININFO_DEFAULT_VEHICLE_WIDTH) / 2;
|
||||
width = ScaleSpriteTrad(TRAININFO_DEFAULT_VEHICLE_WIDTH) + UnScaleGUI(rect.right) - xoffs;
|
||||
height = std::max<uint>(height, UnScaleGUI(rect.Height()));
|
||||
xoffs = xoffs - ScaleSpriteTrad(TRAININFO_DEFAULT_VEHICLE_WIDTH) / 2;
|
||||
yoffs = std::min(yoffs, UnScaleGUI(rect.top));
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
@@ -1674,29 +1701,88 @@ static bool TrainApproachingCrossing(TileIndex tile)
|
||||
return HasVehicleOnPos(tile_from, &tile, &TrainApproachingCrossingEnum);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a level crossing should be barred.
|
||||
* @param tile The tile to check.
|
||||
* @return True if the crossing should be barred, else false.
|
||||
*/
|
||||
static inline bool CheckLevelCrossing(TileIndex tile)
|
||||
{
|
||||
/* reserved || train on crossing || train approaching crossing */
|
||||
return HasCrossingReservation(tile) || HasVehicleOnPos(tile, NULL, &TrainOnTileEnum) || TrainApproachingCrossing(tile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets correct crossing state
|
||||
* @param tile tile to update
|
||||
* @param sound should we play sound?
|
||||
* @pre tile is a rail-road crossing
|
||||
* Sets a level crossing tile to the correct state.
|
||||
* @param tile Tile to update.
|
||||
* @param sound Should we play sound?
|
||||
* @param force_barred Should we set the crossing to barred?
|
||||
* @pre tile is a rail-road crossing.
|
||||
*/
|
||||
void UpdateLevelCrossing(TileIndex tile, bool sound)
|
||||
static void UpdateLevelCrossingTile(TileIndex tile, bool sound, bool force_barred)
|
||||
{
|
||||
assert(IsLevelCrossingTile(tile));
|
||||
bool set_barred;
|
||||
|
||||
/* reserved || train on crossing || train approaching crossing */
|
||||
bool new_state = HasCrossingReservation(tile) || HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum) || TrainApproachingCrossing(tile);
|
||||
/* We force the crossing to be barred when an adjacent crossing is barred, otherwise let it decide for itself. */
|
||||
set_barred = force_barred || CheckLevelCrossing(tile);
|
||||
|
||||
if (new_state != IsCrossingBarred(tile)) {
|
||||
if (new_state && sound) {
|
||||
if (_settings_client.sound.ambient) SndPlayTileFx(SND_0E_LEVEL_CROSSING, tile);
|
||||
}
|
||||
SetCrossingBarred(tile, new_state);
|
||||
/* The state has changed */
|
||||
if (set_barred != IsCrossingBarred(tile)) {
|
||||
if (set_barred && sound && _settings_client.sound.ambient) SndPlayTileFx(SND_0E_LEVEL_CROSSING, tile);
|
||||
SetCrossingBarred(tile, set_barred);
|
||||
MarkTileDirtyByTile(tile);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a level crossing to barred or open (crossing may include multiple adjacent tiles).
|
||||
* @param tile Tile which causes the update.
|
||||
* @param sound Should we play sound?
|
||||
* @param force_bar Should we force the crossing to be barred?
|
||||
*/
|
||||
void UpdateLevelCrossing(TileIndex tile, bool sound, bool force_bar)
|
||||
{
|
||||
if (!IsLevelCrossingTile(tile)) return;
|
||||
|
||||
bool forced_state = force_bar;
|
||||
|
||||
const Axis axis = GetCrossingRoadAxis(tile);
|
||||
const DiagDirection dir1 = AxisToDiagDir(axis);
|
||||
const DiagDirection dir2 = ReverseDiagDir(dir1);
|
||||
|
||||
/* Check if an adjacent crossing is barred. */
|
||||
for (DiagDirection dir : { dir1, dir2 }) {
|
||||
for (TileIndex t = tile; !forced_state && t < MapSize() && IsLevelCrossingTile(t) && GetCrossingRoadAxis(t) == axis; t = TileAddByDiagDir(t, dir)) {
|
||||
forced_state |= CheckLevelCrossing(t);
|
||||
}
|
||||
}
|
||||
|
||||
/* Now that we know whether all tiles in this crossing should be barred or open,
|
||||
* we need to update those tiles. We start with the tile itself, then look along the road axis. */
|
||||
UpdateLevelCrossingTile(tile, sound, forced_state);
|
||||
for (DiagDirection dir : { dir1, dir2 }) {
|
||||
for (TileIndex t = TileAddByDiagDir(tile, dir); t < MapSize() && IsLevelCrossingTile(t) && GetCrossingRoadAxis(t) == axis; t = TileAddByDiagDir(t, dir)) {
|
||||
UpdateLevelCrossingTile(t, sound, forced_state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find adjacent level crossing tiles in this multi-track crossing and mark them dirty.
|
||||
* @param The tile which causes the update.
|
||||
*/
|
||||
void MarkDirtyAdjacentLevelCrossingTiles(TileIndex tile, Axis road_axis)
|
||||
{
|
||||
const DiagDirection dir1 = AxisToDiagDir(road_axis);
|
||||
const DiagDirection dir2 = ReverseDiagDir(dir1);
|
||||
for (DiagDirection dir : { dir1, dir2 }) {
|
||||
const TileIndex t = TileAddByDiagDir(tile, dir);
|
||||
if (t < MapSize() && IsLevelCrossingTile(t) && GetCrossingRoadAxis(t) == road_axis) {
|
||||
MarkTileDirtyByTile(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Bars crossing and plays ding-ding sound if not barred already
|
||||
@@ -1706,9 +1792,8 @@ void UpdateLevelCrossing(TileIndex tile, bool sound)
|
||||
static inline void MaybeBarCrossingWithSound(TileIndex tile)
|
||||
{
|
||||
if (!IsCrossingBarred(tile)) {
|
||||
BarCrossing(tile);
|
||||
if (_settings_client.sound.ambient) SndPlayTileFx(SND_0E_LEVEL_CROSSING, tile);
|
||||
MarkTileDirtyByTile(tile);
|
||||
SetCrossingReservation(tile, true);
|
||||
UpdateLevelCrossing(tile, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1917,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)) {
|
||||
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 */
|
||||
@@ -2042,7 +2126,7 @@ bool Train::FindClosestDepot(TileIndex *location, DestinationID *destination, bo
|
||||
}
|
||||
|
||||
/** Play a sound for a train leaving the station. */
|
||||
void Train::PlayLeaveStationSound() const
|
||||
void Train::PlayLeaveStationSound(bool force) const
|
||||
{
|
||||
static const SoundFx sfx[] = {
|
||||
SND_04_DEPARTURE_STEAM,
|
||||
@@ -2052,10 +2136,9 @@ void Train::PlayLeaveStationSound() const
|
||||
SND_41_DEPARTURE_MAGLEV
|
||||
};
|
||||
|
||||
if (PlayVehicleSound(this, VSE_START)) return;
|
||||
if (PlayVehicleSound(this, VSE_START, force)) return;
|
||||
|
||||
EngineID engtype = this->engine_type;
|
||||
SndPlayVehicleFx(sfx[RailVehInfo(engtype)->engclass], this);
|
||||
SndPlayVehicleFx(sfx[RailVehInfo(this->engine_type)->engclass], this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4062,6 +4145,23 @@ Trackdir Train::GetVehicleTrackdir() const
|
||||
return TrackDirectionToTrackdir(FindFirstTrack(this->track), this->direction);
|
||||
}
|
||||
|
||||
uint16 Train::GetMaxWeight() const
|
||||
{
|
||||
uint16 weight = CargoSpec::Get(this->cargo_type)->WeightOfNUnitsInTrain(this->GetEngine()->DetermineCapacity(this));
|
||||
|
||||
/* Vehicle weight is not added for articulated parts. */
|
||||
if (!this->IsArticulatedPart()) {
|
||||
weight += GetVehicleProperty(this, PROP_TRAIN_WEIGHT, RailVehInfo(this->engine_type)->weight);
|
||||
}
|
||||
|
||||
/* Powered wagons have extra weight added. */
|
||||
if (HasBit(this->flags, VRF_POWEREDWAGON)) {
|
||||
weight += RailVehInfo(this->gcache.first_engine)->pow_wag_weight;
|
||||
}
|
||||
|
||||
return weight;
|
||||
}
|
||||
|
||||
namespace citymania {
|
||||
auto GetDefaultTrainSprite = &::GetDefaultTrainSprite;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user