summaryrefslogtreecommitdiff
path: root/src/ground_vehicle.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ground_vehicle.cpp')
-rw-r--r--src/ground_vehicle.cpp65
1 files changed, 65 insertions, 0 deletions
diff --git a/src/ground_vehicle.cpp b/src/ground_vehicle.cpp
index f6e44c2e2..08879b084 100644
--- a/src/ground_vehicle.cpp
+++ b/src/ground_vehicle.cpp
@@ -11,6 +11,8 @@
#include "train.h"
#include "roadveh.h"
#include "depot_map.h"
+#include "tunnel_base.h"
+#include "slope_type.h"
#include "safeguards.h"
@@ -203,6 +205,69 @@ bool GroundVehicle<T, Type>::IsChainInDepot() const
return true;
}
+/**
+ * Updates vehicle's Z inclination inside a wormhole, where applicable.
+ */
+template <class T, VehicleType Type>
+void GroundVehicle<T, Type>::UpdateZPositionInWormhole()
+{
+ if (!IsTunnel(this->tile)) return;
+
+ const Tunnel *t = Tunnel::GetByTile(this->tile);
+ if (!t->is_chunnel) return;
+
+ TileIndex pos_tile = TileVirtXY(this->x_pos, this->y_pos);
+
+ ClrBit(this->gv_flags, GVF_GOINGUP_BIT);
+ ClrBit(this->gv_flags, GVF_GOINGDOWN_BIT);
+
+ if (pos_tile == t->tile_n || pos_tile == t->tile_s) {
+ this->z_pos = 0;
+ return;
+ }
+
+ int north_coord, south_coord, pos_coord;
+ Slope slope = SLOPE_FLAT;
+ int delta;
+ if (t->tile_s - t->tile_n > MapMaxX()) {
+ // tunnel extends along Y axis (DIAGDIR_SE from north end), has same X values
+ north_coord = TileY(t->tile_n);
+ south_coord = TileY(t->tile_s);
+ pos_coord = TileY(pos_tile);
+
+ if ((delta = pos_coord - north_coord) <= 3) {
+ this->z_pos = TILE_HEIGHT * (delta == 3 ? -2 : -1);
+ if (delta != 2) {
+ slope = SLOPE_NW;
+ SetBit(this->gv_flags, this->direction == DIR_NW ? GVF_GOINGUP_BIT : GVF_GOINGDOWN_BIT);
+ }
+ } else if ((delta = south_coord - pos_coord) <= 3) {
+ this->z_pos = TILE_HEIGHT * (delta == 3 ? -2 : -1);
+ if (delta != 2) {
+ slope = SLOPE_ELEVATED ^ SLOPE_NW;
+ SetBit(this->gv_flags, this->direction == DIR_NW ? GVF_GOINGDOWN_BIT : GVF_GOINGUP_BIT);
+ }
+ }
+ } else {
+ // tunnel extends along X axis (DIAGDIR_SW from north end), has same Y values
+ north_coord = TileX(t->tile_n);
+ south_coord = TileX(t->tile_s);
+ pos_coord = TileX(pos_tile);
+
+ if ((delta = pos_coord - north_coord) <= 3) {
+ this->z_pos = TILE_HEIGHT * (delta == 3 ? -3 : (delta == 2 ? -2 : -1));
+ slope = SLOPE_NE;
+ SetBit(this->gv_flags, this->direction == DIR_NE ? GVF_GOINGUP_BIT : GVF_GOINGDOWN_BIT);
+ } else if ((delta = south_coord - pos_coord) <= 3) {
+ this->z_pos = TILE_HEIGHT * (delta == 3 ? -3 : (delta == 2 ? -2 : -1));
+ slope = SLOPE_ELEVATED ^ SLOPE_NE;
+ SetBit(this->gv_flags, this->direction == DIR_NE ? GVF_GOINGDOWN_BIT : GVF_GOINGUP_BIT);
+ }
+ }
+
+ if (slope != SLOPE_FLAT) this->z_pos += GetPartialPixelZ(this->x_pos & 0xF, this->y_pos & 0xF, slope);
+}
+
/* Instantiation for Train */
template struct GroundVehicle<Train, VEH_TRAIN>;
/* Instantiation for RoadVehicle */