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, TileEdge entry_edge, 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, TileEdge entry_edge, 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 not request a guest to stay. + } + uint32 xpos, ypos, zpos; + ri->GetExit(this->id, exit_edge, &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,26 @@ 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, TileEdge entry_edge, 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 entry_edge %Edge used for entering the ride. + * @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, TileEdge entry_edge, 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,18 @@ 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, TileEdge entry_edge, uint32 *xpos, uint32 *ypos, uint32 *zpos) +{ + /* Put the guest just outside the ride. */ + Point16 dxy = _exit_dxy[(entry_edge + 2) % 4]; + *xpos = this->xpos * 256 + dxy.x; + *ypos = this->ypos * 256 + dxy.y; + *zpos = this->zpos * 256; + return; +} 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, TileEdge entry_edge, 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.