OpenRCT2/src/openrct2/world/Entrance.cpp

269 lines
8.4 KiB
C++
Raw Normal View History

2017-02-25 14:51:30 +01:00
/*****************************************************************************
* Copyright (c) 2014-2019 OpenRCT2 developers
2017-02-25 14:51:30 +01:00
*
* For a complete list of all authors, please refer to contributors.md
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
2017-02-25 14:51:30 +01:00
*
* OpenRCT2 is licensed under the GNU General Public License version 3.
2017-02-25 14:51:30 +01:00
*****************************************************************************/
2017-12-14 10:34:12 +01:00
#include "Entrance.h"
2018-06-22 23:17:03 +02:00
2017-12-13 13:02:24 +01:00
#include "../Cheats.h"
2017-11-30 18:17:06 +01:00
#include "../Game.h"
2018-06-22 23:17:03 +02:00
#include "../OpenRCT2.h"
2019-03-24 21:41:14 +01:00
#include "../actions/ParkEntranceRemoveAction.hpp"
#include "../actions/RideEntranceExitPlaceAction.hpp"
#include "../actions/RideEntranceExitRemoveAction.hpp"
2018-01-06 18:32:25 +01:00
#include "../localisation/StringIds.h"
2017-10-06 22:37:06 +02:00
#include "../management/Finance.h"
2018-06-22 23:17:03 +02:00
#include "../network/network.h"
#include "../ride/Station.h"
2018-06-22 23:17:03 +02:00
#include "../ride/Track.h"
#include "Footpath.h"
#include "Map.h"
#include "MapAnimation.h"
#include "Park.h"
#include "Sprite.h"
2017-02-25 14:51:30 +01:00
2018-12-15 20:20:04 +01:00
#include <algorithm>
bool gParkEntranceGhostExists = false;
2019-12-12 10:58:27 +01:00
CoordsXYZD gParkEntranceGhostPosition = { 0, 0, 0, 0 };
std::vector<CoordsXYZD> gParkEntrances;
2017-02-25 14:51:30 +01:00
2018-02-16 09:50:40 +01:00
CoordsXYZD gRideEntranceExitGhostPosition;
uint8_t gRideEntranceExitGhostStationIndex;
2018-06-22 23:17:03 +02:00
static money32 RideEntranceExitPlaceGhost(
ride_id_t rideIndex, const CoordsXY& entranceExitCoords, uint8_t direction, uint8_t placeType, uint8_t stationNum)
{
auto rideEntranceExitPlaceAction = RideEntranceExitPlaceAction(
entranceExitCoords, direction, rideIndex, stationNum, placeType == ENTRANCE_TYPE_RIDE_EXIT);
rideEntranceExitPlaceAction.SetFlags(GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_GHOST);
auto res = GameActions::Execute(&rideEntranceExitPlaceAction);
return res->Error == GA_ERROR::OK ? res->Cost : MONEY32_UNDEFINED;
}
2017-02-25 14:51:30 +01:00
2018-02-01 18:49:14 +01:00
/**
*
* rct2: 0x00666F9E
*/
void park_entrance_remove_ghost()
{
if (gParkEntranceGhostExists)
2017-02-25 14:51:30 +01:00
{
2018-02-01 18:49:14 +01:00
gParkEntranceGhostExists = false;
2019-12-12 10:58:27 +01:00
auto parkEntranceRemoveAction = ParkEntranceRemoveAction(gParkEntranceGhostPosition);
2019-03-24 21:41:14 +01:00
parkEntranceRemoveAction.SetFlags(GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED);
GameActions::Execute(&parkEntranceRemoveAction);
2017-02-25 14:51:30 +01:00
}
2018-02-01 18:49:14 +01:00
}
2017-02-25 14:51:30 +01:00
int32_t park_entrance_get_index(const CoordsXYZ& entrancePos)
2018-02-01 18:49:14 +01:00
{
int32_t i = 0;
for (const auto& entrance : gParkEntrances)
2017-02-25 14:51:30 +01:00
{
if (entrancePos == entrance)
2017-03-01 22:19:15 +01:00
{
2018-02-01 18:49:14 +01:00
return i;
2017-03-01 22:19:15 +01:00
}
i++;
2017-02-25 14:51:30 +01:00
}
2018-02-01 18:49:14 +01:00
return -1;
}
void reset_park_entrance()
{
gParkEntrances.clear();
2018-02-01 18:49:14 +01:00
}
2018-02-01 18:49:14 +01:00
void ride_entrance_exit_place_provisional_ghost()
{
2018-06-22 23:17:03 +02:00
if (_currentTrackSelectionFlags & TRACK_SELECTION_FLAG_ENTRANCE_OR_EXIT)
{
RideEntranceExitPlaceGhost(
_currentRideIndex, gRideEntranceExitGhostPosition, gRideEntranceExitGhostPosition.direction,
gRideEntranceExitPlaceType, gRideEntranceExitGhostStationIndex);
}
2018-02-01 18:49:14 +01:00
}
2018-02-01 18:49:14 +01:00
void ride_entrance_exit_remove_ghost()
{
2018-06-22 23:17:03 +02:00
if (_currentTrackSelectionFlags & TRACK_SELECTION_FLAG_ENTRANCE_OR_EXIT)
{
auto rideEntranceExitRemove = RideEntranceExitRemoveAction(
gRideEntranceExitGhostPosition, _currentRideIndex, gRideEntranceExitGhostStationIndex,
gRideEntranceExitPlaceType == ENTRANCE_TYPE_RIDE_EXIT);
2019-02-27 19:35:55 +01:00
rideEntranceExitRemove.SetFlags(GAME_COMMAND_FLAG_GHOST | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED);
GameActions::Execute(&rideEntranceExitRemove);
}
2018-02-01 18:49:14 +01:00
}
2018-02-01 18:49:14 +01:00
/**
*
* rct2: 0x006CA28C
*/
2018-06-22 23:17:03 +02:00
money32 ride_entrance_exit_place_ghost(
Ride* ride, const CoordsXY& entranceExitCoords, int32_t direction, int32_t placeType, int32_t stationNum)
2018-02-01 18:49:14 +01:00
{
ride_construction_remove_ghosts();
money32 result = RideEntranceExitPlaceGhost(ride->id, entranceExitCoords, direction, placeType, stationNum);
2018-02-01 18:49:14 +01:00
if (result != MONEY32_UNDEFINED)
2017-03-09 19:48:09 +01:00
{
2018-02-01 18:49:14 +01:00
_currentTrackSelectionFlags |= TRACK_SELECTION_FLAG_ENTRANCE_OR_EXIT;
gRideEntranceExitGhostPosition.x = entranceExitCoords.x;
gRideEntranceExitGhostPosition.y = entranceExitCoords.y;
2018-02-01 18:49:14 +01:00
gRideEntranceExitGhostPosition.direction = direction;
gRideEntranceExitGhostStationIndex = stationNum & 0xFF;
}
2018-02-01 18:49:14 +01:00
return result;
}
2018-02-01 18:49:14 +01:00
/**
* Replaces the outer hedge walls for an entrance placement removal.
* rct2: 0x00666D6F
*/
void maze_entrance_hedge_replacement(const CoordsXYE& entrance)
2018-02-01 18:49:14 +01:00
{
int32_t direction = entrance.element->GetDirection();
auto hedgePos = entrance + CoordsDirectionDelta[direction];
int32_t z = entrance.element->GetBaseZ();
ride_id_t rideIndex = entrance.element->AsEntrance()->GetRideIndex();
2018-02-01 18:49:14 +01:00
auto tileElement = map_get_first_element_at(hedgePos);
Avoid dereferencing map_get_first_element_at nullptr on libopenrct2 (#10013) * Avoid dereferencing map_get_first_element_at nullptr on Map.cpp * Avoid dereferencing map_get_first_element_at nullptr on MapAnimation.cpp Returning true or internal control variable, based on what was seen on `map_animation_invalidate_track_onridephoto` * Avoid dereferencing map_get_first_element_at nullptr on Park.cpp * Avoid dereferencing map_get_first_element_at nullptr on Scenery.cpp * Avoid dereferencing map_get_first_element_at nullptr on Sprite.cpp * Avoid dereferencing map_get_first_element_at nullptr on TileInspector.cpp * Avoid dereferencing map_get_first_element_at nullptr on Wall.cpp * Avoid dereferencing map_get_first_element_at nullptr on Fountain.cpp * Avoid dereferencing map_get_first_element_at nullptr on Footpath.cpp * Avoid dereferencing map_get_first_element_at nullptr on Entrance.cpp * Avoid dereferencing map_get_first_element_at nullptr on Banner.cpp * Avoid dereferencing map_get_first_element_at nullptr on Vehicle.cpp * Avoid dereferencing map_get_first_element_at nullptr on TrackDesignSave.cpp * Avoid dereferencing map_get_first_element_at nullptr on TrackDesign.cpp * Avoid dereferencing map_get_first_element_at nullptr on Track.cpp * Avoid dereferencing map_get_first_element_at nullptr on Station.cpp * Avoid dereferencing map_get_first_element_at nullptr on RideRatings.cpp * Avoid dereferencing map_get_first_element_at nullptr on Ride.cpp * Avoid dereferencing map_get_first_element_at nullptr on S4Importer.cpp * Avoid dereferencing map_get_first_element_at nullptr on Staff.cpp * Avoid dereferencing map_get_first_element_at nullptr on Peep.cpp * Avoid dereferencing map_get_first_element_at nullptr on GuestPathfinding.cpp * Avoid dereferencing map_get_first_element_at nullptr on Guest.cpp * Avoid dereferencing map_get_first_element_at nullptr on VirtualFloor.cpp * Avoid dereferencing map_get_first_element_at nullptr on Paint.TileElement.cpp * Fix issues raised on review * Fix remaining review issues. * Early exit on loops if tileElement is nullptr * Fix clang-format issues
2019-10-09 16:02:21 +02:00
if (tileElement == nullptr)
return;
2018-06-22 23:17:03 +02:00
do
{
if (tileElement->GetType() != TILE_ELEMENT_TYPE_TRACK)
continue;
2018-09-18 13:10:29 +02:00
if (tileElement->AsTrack()->GetRideIndex() != rideIndex)
2018-06-22 23:17:03 +02:00
continue;
if (tileElement->GetBaseZ() != z)
2018-06-22 23:17:03 +02:00
continue;
if (tileElement->AsTrack()->GetTrackType() != TRACK_ELEM_MAZE)
2018-06-22 23:17:03 +02:00
continue;
2018-02-01 18:49:14 +01:00
// Each maze element is split into 4 sections with 4 different walls
uint8_t mazeSection = direction * 4;
2018-02-01 18:49:14 +01:00
// Add the top outer wall
tileElement->AsTrack()->MazeEntryAdd(1 << ((mazeSection + 9) & 0x0F));
2018-02-01 18:49:14 +01:00
// Add the bottom outer wall
tileElement->AsTrack()->MazeEntryAdd(1 << ((mazeSection + 12) & 0x0F));
2018-02-01 18:49:14 +01:00
map_invalidate_tile({ hedgePos, tileElement->GetBaseZ(), tileElement->GetClearanceZ() });
2018-02-01 18:49:14 +01:00
return;
} while (!(tileElement++)->IsLastForTile());
2018-02-01 18:49:14 +01:00
}
2018-02-01 18:49:14 +01:00
/**
* Removes the hedge walls for an entrance placement.
* rct2: 0x00666CBE
*/
2018-11-01 13:53:50 +01:00
void maze_entrance_hedge_removal(int32_t x, int32_t y, TileElement* tileElement)
2018-02-01 18:49:14 +01:00
{
int32_t direction = tileElement->GetDirection();
x += CoordsDirectionDelta[direction].x;
y += CoordsDirectionDelta[direction].y;
int32_t z = tileElement->GetBaseZ();
2019-01-12 11:11:55 +01:00
ride_id_t rideIndex = tileElement->AsEntrance()->GetRideIndex();
2018-02-01 18:49:14 +01:00
tileElement = map_get_first_element_at({ x, y });
Avoid dereferencing map_get_first_element_at nullptr on libopenrct2 (#10013) * Avoid dereferencing map_get_first_element_at nullptr on Map.cpp * Avoid dereferencing map_get_first_element_at nullptr on MapAnimation.cpp Returning true or internal control variable, based on what was seen on `map_animation_invalidate_track_onridephoto` * Avoid dereferencing map_get_first_element_at nullptr on Park.cpp * Avoid dereferencing map_get_first_element_at nullptr on Scenery.cpp * Avoid dereferencing map_get_first_element_at nullptr on Sprite.cpp * Avoid dereferencing map_get_first_element_at nullptr on TileInspector.cpp * Avoid dereferencing map_get_first_element_at nullptr on Wall.cpp * Avoid dereferencing map_get_first_element_at nullptr on Fountain.cpp * Avoid dereferencing map_get_first_element_at nullptr on Footpath.cpp * Avoid dereferencing map_get_first_element_at nullptr on Entrance.cpp * Avoid dereferencing map_get_first_element_at nullptr on Banner.cpp * Avoid dereferencing map_get_first_element_at nullptr on Vehicle.cpp * Avoid dereferencing map_get_first_element_at nullptr on TrackDesignSave.cpp * Avoid dereferencing map_get_first_element_at nullptr on TrackDesign.cpp * Avoid dereferencing map_get_first_element_at nullptr on Track.cpp * Avoid dereferencing map_get_first_element_at nullptr on Station.cpp * Avoid dereferencing map_get_first_element_at nullptr on RideRatings.cpp * Avoid dereferencing map_get_first_element_at nullptr on Ride.cpp * Avoid dereferencing map_get_first_element_at nullptr on S4Importer.cpp * Avoid dereferencing map_get_first_element_at nullptr on Staff.cpp * Avoid dereferencing map_get_first_element_at nullptr on Peep.cpp * Avoid dereferencing map_get_first_element_at nullptr on GuestPathfinding.cpp * Avoid dereferencing map_get_first_element_at nullptr on Guest.cpp * Avoid dereferencing map_get_first_element_at nullptr on VirtualFloor.cpp * Avoid dereferencing map_get_first_element_at nullptr on Paint.TileElement.cpp * Fix issues raised on review * Fix remaining review issues. * Early exit on loops if tileElement is nullptr * Fix clang-format issues
2019-10-09 16:02:21 +02:00
if (tileElement == nullptr)
return;
2018-06-22 23:17:03 +02:00
do
{
if (tileElement->GetType() != TILE_ELEMENT_TYPE_TRACK)
continue;
2018-09-18 13:10:29 +02:00
if (tileElement->AsTrack()->GetRideIndex() != rideIndex)
2018-06-22 23:17:03 +02:00
continue;
if (tileElement->GetBaseZ() != z)
2018-06-22 23:17:03 +02:00
continue;
if (tileElement->AsTrack()->GetTrackType() != TRACK_ELEM_MAZE)
2018-06-22 23:17:03 +02:00
continue;
2018-02-01 18:49:14 +01:00
// Each maze element is split into 4 sections with 4 different walls
uint8_t mazeSection = direction * 4;
2018-02-01 18:49:14 +01:00
// Remove the top outer wall
tileElement->AsTrack()->MazeEntrySubtract(1 << ((mazeSection + 9) & 0x0F));
2018-02-01 18:49:14 +01:00
// Remove the bottom outer wall
tileElement->AsTrack()->MazeEntrySubtract(1 << ((mazeSection + 12) & 0x0F));
2018-02-01 18:49:14 +01:00
// Remove the intersecting wall
tileElement->AsTrack()->MazeEntrySubtract(1 << ((mazeSection + 10) & 0x0F));
2018-02-01 18:49:14 +01:00
// Remove the top hedge section
tileElement->AsTrack()->MazeEntrySubtract(1 << ((mazeSection + 11) & 0x0F));
2018-02-01 18:49:14 +01:00
// Remove the bottom hedge section
tileElement->AsTrack()->MazeEntrySubtract(1 << ((mazeSection + 15) & 0x0F));
2018-02-01 18:49:14 +01:00
map_invalidate_tile({ x, y, tileElement->GetBaseZ(), tileElement->GetClearanceZ() });
2018-02-01 18:49:14 +01:00
return;
} while (!(tileElement++)->IsLastForTile());
2018-02-01 18:49:14 +01:00
}
void fix_park_entrance_locations(void)
{
// Fix gParkEntrance locations for which the tile_element no longer exists
gParkEntrances.erase(
std::remove_if(
gParkEntrances.begin(), gParkEntrances.end(),
2019-12-15 03:07:45 +01:00
[](const auto& entrance) { return map_get_park_entrance_element_at(entrance, false) == nullptr; }),
gParkEntrances.end());
}
uint8_t EntranceElement::GetStationIndex() const
{
2018-09-26 12:02:41 +02:00
return (index & MAP_ELEM_TRACK_SEQUENCE_STATION_INDEX_MASK) >> 4;
}
void EntranceElement::SetStationIndex(uint8_t stationIndex)
{
2018-09-26 12:02:41 +02:00
index &= ~MAP_ELEM_TRACK_SEQUENCE_STATION_INDEX_MASK;
index |= (stationIndex << 4);
}
2018-09-26 12:13:44 +02:00
uint8_t EntranceElement::GetEntranceType() const
{
return entranceType;
}
void EntranceElement::SetEntranceType(uint8_t newType)
{
entranceType = newType;
}
2018-09-26 12:30:27 +02:00
2019-01-12 11:11:55 +01:00
ride_id_t EntranceElement::GetRideIndex() const
2018-09-26 12:30:27 +02:00
{
return rideIndex;
}
2019-01-12 11:11:55 +01:00
void EntranceElement::SetRideIndex(ride_id_t newRideIndex)
2018-09-26 12:30:27 +02:00
{
rideIndex = newRideIndex;
}
uint8_t EntranceElement::GetSequenceIndex() const
{
return index & 0xF;
}
void EntranceElement::SetSequenceIndex(uint8_t newSequenceIndex)
{
index &= ~0xF;
index |= (newSequenceIndex & 0xF);
2018-09-26 13:02:51 +02:00
}
uint8_t EntranceElement::GetPathType() const
{
return pathType;
}
void EntranceElement::SetPathType(uint8_t newPathType)
{
pathType = newPathType;
2018-09-26 14:52:16 +02:00
}