summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ground_vehicle.hpp37
-rw-r--r--src/train.h10
-rw-r--r--src/train_cmd.cpp38
3 files changed, 51 insertions, 34 deletions
diff --git a/src/ground_vehicle.hpp b/src/ground_vehicle.hpp
index 2682fb04d..7a47e20ba 100644
--- a/src/ground_vehicle.hpp
+++ b/src/ground_vehicle.hpp
@@ -13,6 +13,7 @@
#define GROUND_VEHICLE_HPP
#include "vehicle_base.h"
+#include "landscape.h"
/** What is the status of our acceleration? */
enum AccelStatus {
@@ -60,6 +61,7 @@ enum GroundVehicleFlags {
* virtual int32 GetSlopeSteepness() const = 0;
* virtual uint16 GetInitialMaxSpeed() const = 0;
* virtual uint16 GetMaxTrackSpeed() const = 0;
+ * virtual bool TileMayHaveSlopedTrack() const = 0;
*/
template <class T, VehicleType Type>
struct GroundVehicle : public SpecializedVehicle<T, Type> {
@@ -93,6 +95,41 @@ struct GroundVehicle : public SpecializedVehicle<T, Type> {
return incl;
}
+
+ /**
+ * Checks if the vehicle is in a slope and sets the required flags in that case.
+ * @param new_tile True if the vehicle reached a new tile.
+ * @param turned Indicates if the vehicle has turned.
+ * @return Old height of the vehicle.
+ */
+ FORCEINLINE byte UpdateInclination(bool new_tile, bool turned)
+ {
+ byte old_z = this->z_pos;
+ this->z_pos = GetSlopeZ(this->x_pos, this->y_pos);
+
+ if (new_tile) {
+ ClrBit(this->gv_flags, GVF_GOINGUP_BIT);
+ ClrBit(this->gv_flags, GVF_GOINGDOWN_BIT);
+
+ if (T::From(this)->TileMayHaveSlopedTrack()) {
+ /* To check whether the current tile is sloped, and in which
+ * direction it is sloped, we get the 'z' at the center of
+ * the tile (middle_z) and the edge of the tile (old_z),
+ * which we then can compare. */
+ static const int HALF_TILE_SIZE = TILE_SIZE / 2;
+ static const int INV_TILE_SIZE_MASK = ~(TILE_SIZE - 1);
+
+ byte middle_z = GetSlopeZ((this->x_pos & INV_TILE_SIZE_MASK) | HALF_TILE_SIZE, (this->y_pos & INV_TILE_SIZE_MASK) | HALF_TILE_SIZE);
+
+ if (middle_z != this->z_pos) {
+ SetBit(this->gv_flags, (middle_z > old_z) ? GVF_GOINGUP_BIT : GVF_GOINGDOWN_BIT);
+ }
+ }
+ }
+
+ this->UpdateViewport(true, turned);
+ return old_z;
+ }
};
#endif /* GROUND_VEHICLE_HPP */
diff --git a/src/train.h b/src/train.h
index 71724c2c3..b21900ece 100644
--- a/src/train.h
+++ b/src/train.h
@@ -483,6 +483,16 @@ protected: // These functions should not be called outside acceleration code.
{
return GetRailTypeInfo(GetRailType(this->tile))->max_speed;
}
+
+ /**
+ * Checks if the vehicle is at a tile that can be sloped.
+ * @return True if the tile can be sloped.
+ */
+ FORCEINLINE bool TileMayHaveSlopedTrack() const
+ {
+ /* Any track that isn't TRACK_BIT_X or TRACK_BIT_Y cannot be sloped. */
+ return this->track == TRACK_BIT_X || this->track == TRACK_BIT_Y;
+ }
};
#define FOR_ALL_TRAINS(var) FOR_ALL_VEHICLES_OF_TYPE(Train, var)
diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp
index 83fa327b1..050727a3d 100644
--- a/src/train_cmd.cpp
+++ b/src/train_cmd.cpp
@@ -2869,36 +2869,6 @@ static void TrainEnterStation(Train *v, StationID station)
StationAnimationTrigger(st, v->tile, STAT_ANIM_TRAIN_ARRIVES);
}
-static byte AfterSetTrainPos(Train *v, bool new_tile)
-{
- byte old_z = v->z_pos;
- v->z_pos = GetSlopeZ(v->x_pos, v->y_pos);
-
- if (new_tile) {
- ClrBit(v->gv_flags, GVF_GOINGUP_BIT);
- ClrBit(v->gv_flags, GVF_GOINGDOWN_BIT);
-
- if (v->track == TRACK_BIT_X || v->track == TRACK_BIT_Y) {
- /* Any track that isn't TRACK_BIT_X or TRACK_BIT_Y cannot be sloped.
- * To check whether the current tile is sloped, and in which
- * direction it is sloped, we get the 'z' at the center of
- * the tile (middle_z) and the edge of the tile (old_z),
- * which we then can compare. */
- static const int HALF_TILE_SIZE = TILE_SIZE / 2;
- static const int INV_TILE_SIZE_MASK = ~(TILE_SIZE - 1);
-
- byte middle_z = GetSlopeZ((v->x_pos & INV_TILE_SIZE_MASK) | HALF_TILE_SIZE, (v->y_pos & INV_TILE_SIZE_MASK) | HALF_TILE_SIZE);
-
- if (middle_z != v->z_pos) {
- SetBit(v->gv_flags, (middle_z > old_z) ? GVF_GOINGUP_BIT : GVF_GOINGDOWN_BIT);
- }
- }
- }
-
- VehicleMove(v, true);
- return old_z;
-}
-
/* Check if the vehicle is compatible with the specified tile */
static inline bool CheckCompatibleRail(const Train *v, TileIndex tile)
{
@@ -3322,7 +3292,7 @@ static void TrainController(Train *v, Vehicle *nomove)
}
/* We need to update signal status, but after the vehicle position hash
- * has been updated by AfterSetTrainPos() */
+ * has been updated by UpdateInclination() */
update_signals_crossing = true;
if (chosen_dir != v->direction) {
@@ -3381,7 +3351,7 @@ static void TrainController(Train *v, Vehicle *nomove)
v->y_pos = gp.y;
/* update the Z position of the vehicle */
- byte old_z = AfterSetTrainPos(v, (gp.new_tile != gp.old_tile));
+ byte old_z = v->UpdateInclination(gp.new_tile != gp.old_tile, false);
if (prev == NULL) {
/* This is the first vehicle in the train */
@@ -3537,9 +3507,9 @@ static void ChangeTrainDirRandomly(Train *v)
v->UpdateDeltaXY(v->direction);
v->cur_image = v->GetImage(v->direction);
/* Refrain from updating the z position of the vehicle when on
- * a bridge, because AfterSetTrainPos will put the vehicle under
+ * a bridge, because UpdateInclination() will put the vehicle under
* the bridge in that case */
- if (v->track != TRACK_BIT_WORMHOLE) AfterSetTrainPos(v, false);
+ if (v->track != TRACK_BIT_WORMHOLE) v->UpdateInclination(false, false);
}
} while ((v = v->Next()) != NULL);
}