diff --git a/src/coaster.cpp b/src/coaster.cpp
--- a/src/coaster.cpp
+++ b/src/coaster.cpp
@@ -602,6 +602,16 @@ uint8 CoasterInstance::GetEntranceDirect
return 0; /// \todo add entrance bits for the coaster.
}
+bool CoasterInstance::EnterRide(int guest)
+{
+ return true; /// \todo Store the guest number.
+}
+
+void CoasterInstance::GetExit(int guest, uint32 *xpos, uint32 *ypos, uint32 *zpos)
+{
+ assert(false); // Not yet implemented.
+}
+
/**
* Check the state of the coaster ride, and set the #state flag.
* @return The new coaster instance state.
diff --git a/src/coaster.h b/src/coaster.h
--- a/src/coaster.h
+++ b/src/coaster.h
@@ -193,6 +193,8 @@ public:
void GetSprites(uint16 voxel_number, uint8 orient, const ImageData *sprites[4]) const override;
uint8 GetEntranceDirections(uint16 xvox, uint16 yvox, uint8 zvox) const override;
+ bool EnterRide(int guest) override;
+ void GetExit(int guest, uint32 *xpos, uint32 *ypos, uint32 *zpos) override;
RideInstanceState DecideRideState();
diff --git a/src/person.cpp b/src/person.cpp
--- a/src/person.cpp
+++ b/src/person.cpp
@@ -855,8 +855,19 @@ AnimateResult Guest::OnAnimate(int delay
if (instance >= SRI_FULL_RIDES) {
assert(exit_edge != INVALID_EDGE);
RideInstance *ri = _rides_manager.GetRideInstance(instance);
- if (ri->CanBeVisited(this->x_vox, this->y_vox, this->z_vox, exit_edge)) {
- this->VisitShop(ri);
+ if (ri->CanBeVisited(this->x_vox, this->y_vox, this->z_vox, exit_edge) && this->VisitRide(ri)) {
+ /* Visited ride, ask ride where to go. */
+ if (ri->EnterRide(this->id)) {
+ assert(false); // Rides should no request a guest to stay.
+ }
+ uint32 xpos, ypos, zpos;
+ ri->GetExit(this->id, &xpos, &ypos, &zpos);
+ this->x_vox = xpos >> 8; this->x_pos = xpos & 0xff;
+ this->y_vox = ypos >> 8; this->y_pos = ypos & 0xff;
+ this->z_vox = zpos >> 8; this->z_pos = zpos & 0xff;
+ this->AddSelf(_world.GetCreateVoxel(this->x_vox, this->y_vox, this->z_vox, false));
+ this->DecideMoveDirection();
+ return OAR_OK;
}
/* Ride is closed, fall-through to reversing movement. */
@@ -1175,9 +1186,9 @@ void Guest::AddItem(ItemType it)
/**
* Visit the shop.
* @param ri Ride being visited.
- * @note It is called 'shop', but it is quite generic, so it may be usable for more rides (without queue in front of it).
+ * @return Guest actually visited the ride, perform the RideInstance::EnterRide protocol, to make the guest stay inside, if needed.
*/
-void Guest::VisitShop(RideInstance *ri)
+bool Guest::VisitRide(RideInstance *ri)
{
bool can_buy[NUMBER_ITEM_TYPES_SOLD];
int count = 0;
@@ -1206,9 +1217,10 @@ void Guest::VisitShop(RideInstance *ri)
this->cash -= ri->GetSaleItemPrice(i);
this->AddItem(ri->GetSaleItemType(i));
this->ChangeHappiness(10);
- return;
+ return true;
}
}
this->ChangeHappiness(-10);
+ return false;
}
diff --git a/src/person.h b/src/person.h
--- a/src/person.h
+++ b/src/person.h
@@ -160,7 +160,7 @@ public:
bool DailyUpdate() override;
void ChangeHappiness(int16 amount);
- void VisitShop(RideInstance *ri);
+ bool VisitRide(RideInstance *ri);
void NotifyRideDeletion(const RideInstance *ri);
GuestActivity activity; ///< Activity being done by the guest currently.
diff --git a/src/ride_type.cpp b/src/ride_type.cpp
--- a/src/ride_type.cpp
+++ b/src/ride_type.cpp
@@ -200,7 +200,25 @@ const RideType *RideInstance::GetRideTyp
*/
/**
- * Can the ride be visited, assuming the shop is approached from direction \a edge?
+ * \fn bool RideInstance::EnterRide(int guest)
+ * The given guest enters the ride. If the call returns \c false, the guest should immediately call RideInstance::GetExit
+ * to get the exit coordinates. If the call returns \c true, the guest should wait until the ride sends a Guest::ExitRide
+ * request (and then call RideInstance::GetExit for the coordinates).
+ * @param guest Number of the guest entering the ride.
+ * @return Whether the guest should stay in the ride.
+ */
+
+/**
+ * \fn void RideInstance::GetExit(int guest, uint32 *xpos, uint32 *ypos, uint32 *zpos)
+ * Get the exit coordinates of the ride, is near the middle of a tile edge.
+ * @param guest Number of the guest querying the exit coordinates.
+ * @param xpos X world position of the exit.
+ * @param ypos Y world position of the exit.
+ * @param zpos Z world position of the exit
+ */
+
+/**
+ * Can the ride be visited, assuming it is approached from direction \a edge?
* @param xvox X position of the voxel with the ride.
* @param yvox Y position of the voxel with the ride.
* @param zvox Z position of the voxel with the ride.
diff --git a/src/ride_type.h b/src/ride_type.h
--- a/src/ride_type.h
+++ b/src/ride_type.h
@@ -131,6 +131,8 @@ public:
virtual void GetSprites(uint16 voxel_number, uint8 orient, const ImageData *sprites[4]) const = 0;
virtual uint8 GetEntranceDirections(uint16 xvox, uint16 yvox, uint8 zvox) const = 0;
+ virtual bool EnterRide(int guest) = 0;
+ virtual void GetExit(int guest, uint32 *xpos, uint32 *ypos, uint32 *zpos) = 0;
bool CanBeVisited(uint16 xvox, uint16 yvox, uint8 zvox, TileEdge edge) const;
void SellItem(int item_index);
diff --git a/src/shop_type.cpp b/src/shop_type.cpp
--- a/src/shop_type.cpp
+++ b/src/shop_type.cpp
@@ -176,3 +176,25 @@ uint8 ShopInstance::GetEntranceDirection
uint8 entrances = this->GetShopType()->flags & SHF_ENTRANCE_BITS;
return ROL(entrances, 4, this->orientation);
}
+
+bool ShopInstance::EnterRide(int guest)
+{
+ return false; // Don't stay inside a shop.
+}
+
+void ShopInstance::GetExit(int guest, uint32 *xpos, uint32 *ypos, uint32 *zpos)
+{
+ /* Put the guest just outside the door. */
+ uint8 entrances = this->GetShopType()->flags & SHF_ENTRANCE_BITS;
+ entrances = ROL(entrances, 4, this->orientation);
+ for (TileEdge edge = EDGE_BEGIN; edge < EDGE_COUNT; edge++) {
+ if ((entrances & (1 << edge)) != 0) {
+ Point16 dxy = _exit_dxy[edge];
+ *xpos = this->xpos * 256 + dxy.x;
+ *ypos = this->ypos * 256 + dxy.y;
+ *zpos = this->zpos * 256;
+ return;
+ }
+ }
+ NOT_REACHED();
+}
diff --git a/src/shop_type.h b/src/shop_type.h
--- a/src/shop_type.h
+++ b/src/shop_type.h
@@ -47,6 +47,8 @@ public:
void SetRide(uint8 orientation, uint16 xpos, uint16 ypos, uint8 zpos);
uint8 GetEntranceDirections(uint16 xvox, uint16 yvox, uint8 zvox) const override;
+ bool EnterRide(int guest) override;
+ void GetExit(int guest, uint32 *xpos, uint32 *ypos, uint32 *zpos) override;
uint8 orientation; ///< Orientation of the shop.
uint16 xpos; ///< X position of the shop base voxel.
diff --git a/src/tile.h b/src/tile.h
--- a/src/tile.h
+++ b/src/tile.h
@@ -237,6 +237,7 @@ DECLARE_POSTFIX_INCREMENT(TrackSlope)
extern const uint8 _corners_at_edge[EDGE_COUNT];
extern const Point16 _corner_dxy[4];
extern const Point16 _tile_dxy[EDGE_COUNT];
+extern const Point16 _exit_dxy[EDGE_COUNT];
void ComputeCornerHeight(TileSlope slope, uint8 base_height, uint8 *output);
void ComputeSlopeAndHeight(uint8 *corners, TileSlope *slope, uint8 *base);
diff --git a/src/tile_func.cpp b/src/tile_func.cpp
--- a/src/tile_func.cpp
+++ b/src/tile_func.cpp
@@ -36,6 +36,14 @@ const Point16 _tile_dxy[EDGE_COUNT] = {
{ 0, -1}, ///< EDGE_NW
};
+/** Pixel position for a guest exiting a ride exit, relative to the base position of the exit voxel of the ride. */
+const Point16 _exit_dxy[EDGE_COUNT] = {
+ { -1, 128}, ///< EDGE_NE
+ {128, 256}, ///< EDGE_SE
+ {256, 128}, ///< EDGE_SW
+ {128, -1}, ///< EDGE_NW
+};
+
/**
* Compute the height of the corners of an expanded ground tile.
* @param slope Expanded slope.