mirror of https://github.com/OpenRCT2/OpenRCT2.git
Continue refactor. Fix bug with provisional tracks.
Note this might bring back #4728.
This commit is contained in:
parent
9725e6b647
commit
652cf510e5
|
@ -185,8 +185,8 @@ uint8 _currentBrakeSpeed2;
|
||||||
uint8 _currentSeatRotationAngle;
|
uint8 _currentSeatRotationAngle;
|
||||||
|
|
||||||
rct_xyz16 _unkF44188;
|
rct_xyz16 _unkF44188;
|
||||||
rct_xyzd16 _unkF440BF;
|
|
||||||
uint8 _unkF440C4;
|
|
||||||
rct_xyzd16 _unkF440C5;
|
rct_xyzd16 _unkF440C5;
|
||||||
|
|
||||||
uint8 gRideEntranceExitPlaceType;
|
uint8 gRideEntranceExitPlaceType;
|
||||||
|
@ -214,9 +214,7 @@ static void ride_spiral_slide_update(rct_ride *ride);
|
||||||
static void ride_update(sint32 rideIndex);
|
static void ride_update(sint32 rideIndex);
|
||||||
static void ride_update_vehicle_colours(sint32 rideIndex);
|
static void ride_update_vehicle_colours(sint32 rideIndex);
|
||||||
static void ride_set_vehicle_colours_to_random_preset(rct_ride *ride, uint8 preset_index);
|
static void ride_set_vehicle_colours_to_random_preset(rct_ride *ride, uint8 preset_index);
|
||||||
static void maze_entrance_hedge_removal(sint32 x, sint32 y, rct_map_element *mapElement);
|
|
||||||
void loc_6DDF9C(rct_ride *ride, rct_map_element *mapElement);
|
void loc_6DDF9C(rct_ride *ride, rct_map_element *mapElement);
|
||||||
static void maze_entrance_hedge_replacement(sint32 x, sint32 y, rct_map_element *mapElement);
|
|
||||||
bool sub_6CA2DF(sint32 *trackType, sint32 *trackDirection, sint32 *rideIndex, sint32 *edxRS16, sint32 *x, sint32 *y, sint32 *z, sint32 *properties);
|
bool sub_6CA2DF(sint32 *trackType, sint32 *trackDirection, sint32 *rideIndex, sint32 *edxRS16, sint32 *x, sint32 *y, sint32 *z, sint32 *properties);
|
||||||
money32 sub_6CA162(sint32 rideIndex, sint32 trackType, sint32 trackDirection, sint32 edxRS16, sint32 x, sint32 y, sint32 z);
|
money32 sub_6CA162(sint32 rideIndex, sint32 trackType, sint32 trackDirection, sint32 edxRS16, sint32 x, sint32 y, sint32 z);
|
||||||
|
|
||||||
|
@ -1099,7 +1097,7 @@ void ride_clear_for_construction(sint32 rideIndex)
|
||||||
*
|
*
|
||||||
* rct2: 0x006664DF
|
* rct2: 0x006664DF
|
||||||
*/
|
*/
|
||||||
static void ride_remove_peeps(sint32 rideIndex)
|
void ride_remove_peeps(sint32 rideIndex)
|
||||||
{
|
{
|
||||||
rct_ride *ride = get_ride(rideIndex);
|
rct_ride *ride = get_ride(rideIndex);
|
||||||
|
|
||||||
|
@ -1330,36 +1328,6 @@ sint32 sub_6C683D(sint32* x, sint32* y, sint32* z, sint32 direction, sint32 type
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ride_restore_provisional_entrance_or_exit()
|
|
||||||
{
|
|
||||||
if (_currentTrackSelectionFlags & TRACK_SELECTION_FLAG_ENTRANCE_OR_EXIT) {
|
|
||||||
game_do_command(
|
|
||||||
_unkF440BF.x,
|
|
||||||
(GAME_COMMAND_FLAG_APPLY | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_5 | GAME_COMMAND_FLAG_GHOST) | (_unkF440BF.direction << 8),
|
|
||||||
_unkF440BF.y,
|
|
||||||
_currentRideIndex | (gRideEntranceExitPlaceType << 8),
|
|
||||||
GAME_COMMAND_PLACE_RIDE_ENTRANCE_OR_EXIT,
|
|
||||||
_unkF440C4,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ride_remove_provisional_entrance_or_exit()
|
|
||||||
{
|
|
||||||
if (_currentTrackSelectionFlags & TRACK_SELECTION_FLAG_ENTRANCE_OR_EXIT) {
|
|
||||||
game_do_command(
|
|
||||||
_unkF440BF.x,
|
|
||||||
(GAME_COMMAND_FLAG_5 | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_APPLY),
|
|
||||||
_unkF440BF.y,
|
|
||||||
_currentRideIndex,
|
|
||||||
GAME_COMMAND_REMOVE_RIDE_ENTRANCE_OR_EXIT,
|
|
||||||
_unkF440C4,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ride_restore_provisional_track_piece()
|
void ride_restore_provisional_track_piece()
|
||||||
{
|
{
|
||||||
if (_currentTrackSelectionFlags & TRACK_SELECTION_FLAG_TRACK) {
|
if (_currentTrackSelectionFlags & TRACK_SELECTION_FLAG_TRACK) {
|
||||||
|
@ -1423,7 +1391,7 @@ void sub_6C96C0()
|
||||||
{
|
{
|
||||||
|
|
||||||
if (_currentTrackSelectionFlags & TRACK_SELECTION_FLAG_ENTRANCE_OR_EXIT) {
|
if (_currentTrackSelectionFlags & TRACK_SELECTION_FLAG_ENTRANCE_OR_EXIT) {
|
||||||
ride_remove_provisional_entrance_or_exit();
|
ride_entrance_exit_remove_ghost();
|
||||||
_currentTrackSelectionFlags &= ~TRACK_SELECTION_FLAG_ENTRANCE_OR_EXIT;
|
_currentTrackSelectionFlags &= ~TRACK_SELECTION_FLAG_ENTRANCE_OR_EXIT;
|
||||||
}
|
}
|
||||||
if (_currentTrackSelectionFlags & TRACK_SELECTION_FLAG_TRACK) {
|
if (_currentTrackSelectionFlags & TRACK_SELECTION_FLAG_TRACK) {
|
||||||
|
@ -7044,32 +7012,6 @@ void set_vehicle_type_image_max_sizes(rct_ride_entry_vehicle* vehicle_type, sint
|
||||||
vehicle_type->sprite_height_positive = bh;
|
vehicle_type->sprite_height_positive = bh;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* rct2: 0x006CA28C
|
|
||||||
*/
|
|
||||||
money32 ride_get_entrance_or_exit_price(sint32 rideIndex, sint32 x, sint32 y, sint32 direction, sint32 dh, sint32 di)
|
|
||||||
{
|
|
||||||
sub_6C96C0();
|
|
||||||
money32 result = game_do_command(
|
|
||||||
x,
|
|
||||||
(GAME_COMMAND_FLAG_APPLY | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_5 | GAME_COMMAND_FLAG_GHOST) | (direction << 8),
|
|
||||||
y,
|
|
||||||
rideIndex | (dh << 8),
|
|
||||||
GAME_COMMAND_PLACE_RIDE_ENTRANCE_OR_EXIT,
|
|
||||||
di,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
if (result != MONEY32_UNDEFINED) {
|
|
||||||
_currentTrackSelectionFlags |= TRACK_SELECTION_FLAG_ENTRANCE_OR_EXIT;
|
|
||||||
_unkF440BF.x = x;
|
|
||||||
_unkF440BF.y = y;
|
|
||||||
_unkF440BF.direction = direction;
|
|
||||||
_unkF440C4 = di & 0xFF;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static sint32 loc_6CD18E(sint16 mapX, sint16 mapY, sint16 entranceMinX, sint16 entranceMinY, sint16 entranceMaxX, sint16 entranceMaxY)
|
static sint32 loc_6CD18E(sint16 mapX, sint16 mapY, sint16 entranceMinX, sint16 entranceMinY, sint16 entranceMaxX, sint16 entranceMaxY)
|
||||||
{
|
{
|
||||||
sint32 direction = 0;
|
sint32 direction = 0;
|
||||||
|
@ -8082,379 +8024,6 @@ void sub_6CB945(sint32 rideIndex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the hedge walls for an entrance placement.
|
|
||||||
* rct2: 0x00666CBE
|
|
||||||
*/
|
|
||||||
static void maze_entrance_hedge_removal(sint32 x, sint32 y, rct_map_element *mapElement)
|
|
||||||
{
|
|
||||||
sint32 direction = mapElement->type & MAP_ELEMENT_DIRECTION_MASK;
|
|
||||||
x += TileDirectionDelta[direction].x;
|
|
||||||
y += TileDirectionDelta[direction].y;
|
|
||||||
sint32 z = mapElement->base_height;
|
|
||||||
sint32 rideIndex = mapElement->properties.track.ride_index;
|
|
||||||
|
|
||||||
mapElement = map_get_first_element_at(x >> 5, y >> 5);
|
|
||||||
do {
|
|
||||||
if (mapElement->type != MAP_ELEMENT_TYPE_TRACK) continue;
|
|
||||||
if (mapElement->properties.track.ride_index != rideIndex) continue;
|
|
||||||
if (mapElement->base_height != z) continue;
|
|
||||||
if (mapElement->properties.track.type != TRACK_ELEM_INVERTED_90_DEG_UP_TO_FLAT_QUARTER_LOOP) continue;
|
|
||||||
|
|
||||||
// Each maze element is split into 4 sections with 4 different walls
|
|
||||||
uint8 mazeSection = direction * 4;
|
|
||||||
// Remove the top outer wall
|
|
||||||
mapElement->properties.track.maze_entry &= ~(1 << ((mazeSection + 9) & 0x0F));
|
|
||||||
// Remove the bottom outer wall
|
|
||||||
mapElement->properties.track.maze_entry &= ~(1 << ((mazeSection + 12) & 0x0F));
|
|
||||||
// Remove the intersecting wall
|
|
||||||
mapElement->properties.track.maze_entry &= ~(1 << ((mazeSection + 10) & 0x0F));
|
|
||||||
// Remove the top hedge section
|
|
||||||
mapElement->properties.track.maze_entry &= ~(1 << ((mazeSection + 11) & 0x0F));
|
|
||||||
// Remove the bottom hedge section
|
|
||||||
mapElement->properties.track.maze_entry &= ~(1 << ((mazeSection + 15) & 0x0F));
|
|
||||||
|
|
||||||
map_invalidate_tile(x, y, mapElement->base_height * 8, mapElement->clearance_height * 8);
|
|
||||||
return;
|
|
||||||
} while (!map_element_is_last_for_tile(mapElement++));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Replaces the outer hedge walls for an entrance placement removal.
|
|
||||||
* rct2: 0x00666D6F
|
|
||||||
*/
|
|
||||||
static void maze_entrance_hedge_replacement(sint32 x, sint32 y, rct_map_element *mapElement)
|
|
||||||
{
|
|
||||||
sint32 direction = mapElement->type & MAP_ELEMENT_DIRECTION_MASK;
|
|
||||||
x += TileDirectionDelta[direction].x;
|
|
||||||
y += TileDirectionDelta[direction].y;
|
|
||||||
sint32 z = mapElement->base_height;
|
|
||||||
sint32 rideIndex = mapElement->properties.track.ride_index;
|
|
||||||
|
|
||||||
mapElement = map_get_first_element_at(x >> 5, y >> 5);
|
|
||||||
do {
|
|
||||||
if (mapElement->type != MAP_ELEMENT_TYPE_TRACK) continue;
|
|
||||||
if (mapElement->properties.track.ride_index != rideIndex) continue;
|
|
||||||
if (mapElement->base_height != z) continue;
|
|
||||||
if (mapElement->properties.track.type != TRACK_ELEM_INVERTED_90_DEG_UP_TO_FLAT_QUARTER_LOOP) continue;
|
|
||||||
|
|
||||||
// Each maze element is split into 4 sections with 4 different walls
|
|
||||||
uint8 mazeSection = direction * 4;
|
|
||||||
// Add the top outer wall
|
|
||||||
mapElement->properties.track.maze_entry |= (1 << ((mazeSection + 9) & 0x0F));
|
|
||||||
// Add the bottom outer wall
|
|
||||||
mapElement->properties.track.maze_entry |= (1 << ((mazeSection + 12) & 0x0F));
|
|
||||||
|
|
||||||
map_invalidate_tile(x, y, mapElement->base_height * 8, mapElement->clearance_height * 8);
|
|
||||||
return;
|
|
||||||
} while (!map_element_is_last_for_tile(mapElement++));
|
|
||||||
}
|
|
||||||
|
|
||||||
static money32 place_ride_entrance_or_exit(sint16 x, sint16 y, sint16 z, uint8 direction, uint8 flags, uint8 rideIndex, uint8 station_num, uint8 is_exit)
|
|
||||||
{
|
|
||||||
// Remember when in Unknown station num mode rideIndex is unknown and z is set
|
|
||||||
// When in known station num mode rideIndex is known and z is unknown
|
|
||||||
|
|
||||||
money32 cost = 0;
|
|
||||||
gCommandPosition.x = x;
|
|
||||||
gCommandPosition.y = y;
|
|
||||||
|
|
||||||
if (!map_check_free_elements_and_reorganise(1)) {
|
|
||||||
return MONEY32_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(flags & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED) && game_is_paused() && !gCheatsBuildInPauseMode){
|
|
||||||
gGameCommandErrorText = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED;
|
|
||||||
return MONEY32_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (station_num == 0xFF) {
|
|
||||||
z *= 16;
|
|
||||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
|
||||||
return MONEY32_UNDEFINED;
|
|
||||||
|
|
||||||
if (!gCheatsSandboxMode && !map_is_location_owned(x, y, z)) {
|
|
||||||
return MONEY32_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
sint16 clear_z = z / 8 + (is_exit ? 5 : 7);
|
|
||||||
|
|
||||||
if (!gCheatsDisableClearanceChecks && !map_can_construct_with_clear_at(x, y, z / 8, clear_z, &map_place_non_scenery_clear_func, 0xF, flags, &cost)) {
|
|
||||||
return MONEY32_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gMapGroundFlags & ELEMENT_IS_UNDERWATER) {
|
|
||||||
gGameCommandErrorText = STR_RIDE_CANT_BUILD_THIS_UNDERWATER;
|
|
||||||
return MONEY32_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (z > 1952) {
|
|
||||||
gGameCommandErrorText = STR_TOO_HIGH;
|
|
||||||
return MONEY32_UNDEFINED;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (rideIndex >= MAX_RIDES)
|
|
||||||
{
|
|
||||||
log_warning("Invalid game command for ride %u", rideIndex);
|
|
||||||
return MONEY32_UNDEFINED;
|
|
||||||
}
|
|
||||||
rct_ride* ride = get_ride(rideIndex);
|
|
||||||
if (ride->type == RIDE_TYPE_NULL)
|
|
||||||
{
|
|
||||||
log_warning("Invalid game command for ride %u", rideIndex);
|
|
||||||
return MONEY32_UNDEFINED;
|
|
||||||
}
|
|
||||||
if (ride->status != RIDE_STATUS_CLOSED) {
|
|
||||||
gGameCommandErrorText = STR_MUST_BE_CLOSED_FIRST;
|
|
||||||
return MONEY32_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ride->lifecycle_flags & RIDE_LIFECYCLE_INDESTRUCTIBLE_TRACK) {
|
|
||||||
gGameCommandErrorText = STR_NOT_ALLOWED_TO_MODIFY_STATION;
|
|
||||||
return MONEY32_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
ride_clear_for_construction(rideIndex);
|
|
||||||
ride_remove_peeps(rideIndex);
|
|
||||||
|
|
||||||
uint8 requires_remove = 0;
|
|
||||||
sint16 remove_x = 0;
|
|
||||||
sint16 remove_y = 0;
|
|
||||||
|
|
||||||
if (is_exit) {
|
|
||||||
if (ride->exits[station_num] != 0xFFFF) {
|
|
||||||
if (flags & GAME_COMMAND_FLAG_GHOST) {
|
|
||||||
gGameCommandErrorText = 0;
|
|
||||||
return MONEY32_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
remove_x = (ride->exits[station_num] & 0xFF) * 32;
|
|
||||||
remove_y = ((ride->exits[station_num] >> 8) & 0xFF) * 32;
|
|
||||||
requires_remove = 1;
|
|
||||||
}
|
|
||||||
} else if (ride->entrances[station_num] != 0xFFFF) {
|
|
||||||
if (flags & GAME_COMMAND_FLAG_GHOST) {
|
|
||||||
gGameCommandErrorText = 0;
|
|
||||||
return MONEY32_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
remove_x = (ride->entrances[station_num] & 0xFF) * 32;
|
|
||||||
remove_y = ((ride->entrances[station_num] >> 8) & 0xFF) * 32;
|
|
||||||
requires_remove = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (requires_remove) {
|
|
||||||
money32 success = game_do_command(
|
|
||||||
remove_x,
|
|
||||||
flags,
|
|
||||||
remove_y,
|
|
||||||
rideIndex,
|
|
||||||
GAME_COMMAND_REMOVE_RIDE_ENTRANCE_OR_EXIT,
|
|
||||||
station_num,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
|
|
||||||
if (success == MONEY32_UNDEFINED) {
|
|
||||||
return MONEY32_UNDEFINED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
z = ride->station_heights[station_num] * 8;
|
|
||||||
gCommandPosition.z = z;
|
|
||||||
|
|
||||||
if (
|
|
||||||
(flags & GAME_COMMAND_FLAG_APPLY) &&
|
|
||||||
!(flags & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED) &&
|
|
||||||
!(flags & GAME_COMMAND_FLAG_GHOST)
|
|
||||||
) {
|
|
||||||
footpath_remove_litter(x, y, z);
|
|
||||||
wall_remove_at_z(x, y, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!gCheatsSandboxMode && !map_is_location_owned(x, y, z)) {
|
|
||||||
return MONEY32_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
sint8 clear_z = (z / 8) + (is_exit ? 5 : 7);
|
|
||||||
|
|
||||||
if (!gCheatsDisableClearanceChecks && !map_can_construct_with_clear_at(x, y, z / 8, clear_z, &map_place_non_scenery_clear_func, 0xF, flags, &cost)) {
|
|
||||||
return MONEY32_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gMapGroundFlags & ELEMENT_IS_UNDERWATER) {
|
|
||||||
gGameCommandErrorText = STR_RIDE_CANT_BUILD_THIS_UNDERWATER;
|
|
||||||
return MONEY32_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (z / 8 > 244){
|
|
||||||
gGameCommandErrorText = STR_TOO_HIGH;
|
|
||||||
return MONEY32_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & GAME_COMMAND_FLAG_APPLY) {
|
|
||||||
rct_xyz16 coord;
|
|
||||||
coord.x = x + 16;
|
|
||||||
coord.y = y + 16;
|
|
||||||
coord.z = map_element_height(coord.x, coord.y);
|
|
||||||
network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord);
|
|
||||||
|
|
||||||
rct_map_element* mapElement = map_element_insert(x / 32, y / 32, z / 8, 0xF);
|
|
||||||
assert(mapElement != NULL);
|
|
||||||
mapElement->clearance_height = clear_z;
|
|
||||||
mapElement->properties.entrance.type = is_exit;
|
|
||||||
mapElement->properties.entrance.index = station_num << 4;
|
|
||||||
mapElement->properties.entrance.ride_index = rideIndex;
|
|
||||||
mapElement->type = MAP_ELEMENT_TYPE_ENTRANCE | direction;
|
|
||||||
|
|
||||||
if (flags & GAME_COMMAND_FLAG_GHOST) {
|
|
||||||
mapElement->flags |= MAP_ELEMENT_FLAG_GHOST;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_exit) {
|
|
||||||
ride->exits[station_num] = (x / 32) | (y / 32 << 8);
|
|
||||||
} else {
|
|
||||||
ride->entrances[station_num] = (x / 32) | (y / 32 << 8);
|
|
||||||
ride->last_peep_in_queue[station_num] = SPRITE_INDEX_NULL;
|
|
||||||
ride->queue_length[station_num] = 0;
|
|
||||||
|
|
||||||
map_animation_create(MAP_ANIMATION_TYPE_RIDE_ENTRANCE, x, y, z / 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
footpath_queue_chain_reset();
|
|
||||||
if (!(flags & GAME_COMMAND_FLAG_GHOST)) {
|
|
||||||
maze_entrance_hedge_removal(x, y, mapElement);
|
|
||||||
}
|
|
||||||
footpath_connect_edges(x, y, mapElement, flags);
|
|
||||||
sub_6A759F();
|
|
||||||
|
|
||||||
map_invalidate_tile_full(x, y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gCommandExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION;
|
|
||||||
return cost;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* rct2: 0x006660A8
|
|
||||||
*/
|
|
||||||
void game_command_place_ride_entrance_or_exit(sint32 *eax, sint32 *ebx, sint32 *ecx, sint32 *edx, sint32 *esi, sint32 *edi, sint32 *ebp){
|
|
||||||
*ebx = place_ride_entrance_or_exit(
|
|
||||||
*eax & 0xFFFF,
|
|
||||||
*ecx & 0xFFFF,
|
|
||||||
*edx & 0xFF,
|
|
||||||
(*ebx >> 8) & 0xFF,
|
|
||||||
*ebx & 0xFF,
|
|
||||||
*edx & 0xFF,
|
|
||||||
*edi & 0xFF,
|
|
||||||
(*edx >> 8) & 0xFF
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static money32 remove_ride_entrance_or_exit(sint16 x, sint16 y, uint8 rideIndex, uint8 station_num, uint8 flags){
|
|
||||||
if (rideIndex >= MAX_RIDES)
|
|
||||||
{
|
|
||||||
log_warning("Invalid game command for ride %u", rideIndex);
|
|
||||||
return MONEY32_UNDEFINED;
|
|
||||||
}
|
|
||||||
rct_ride* ride = get_ride(rideIndex);
|
|
||||||
if (ride->type == RIDE_TYPE_NULL)
|
|
||||||
{
|
|
||||||
log_warning("Invalide ride id %u for entrance/exit removal", rideIndex);
|
|
||||||
return MONEY32_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(flags & GAME_COMMAND_FLAG_GHOST)){
|
|
||||||
if (!(flags & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED) && game_is_paused() && !gCheatsBuildInPauseMode){
|
|
||||||
gGameCommandErrorText = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED;
|
|
||||||
return MONEY32_UNDEFINED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ride->status != RIDE_STATUS_CLOSED){
|
|
||||||
gGameCommandErrorText = STR_MUST_BE_CLOSED_FIRST;
|
|
||||||
return MONEY32_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ride->lifecycle_flags & RIDE_LIFECYCLE_INDESTRUCTIBLE_TRACK) {
|
|
||||||
gGameCommandErrorText = STR_NOT_ALLOWED_TO_MODIFY_STATION;
|
|
||||||
return MONEY32_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & GAME_COMMAND_FLAG_APPLY){
|
|
||||||
ride_clear_for_construction(rideIndex);
|
|
||||||
ride_remove_peeps(rideIndex);
|
|
||||||
invalidate_test_results(rideIndex);
|
|
||||||
|
|
||||||
uint8 found = 0;
|
|
||||||
rct_map_element* mapElement = map_get_first_element_at(x / 32, y / 32);
|
|
||||||
if (mapElement == NULL)
|
|
||||||
{
|
|
||||||
log_warning("Invalid coordinates for entrance/exit removal x = %d, y = %d", x, y);
|
|
||||||
return MONEY32_UNDEFINED;
|
|
||||||
}
|
|
||||||
do{
|
|
||||||
if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_ENTRANCE)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (mapElement->base_height != ride->station_heights[station_num])
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (flags & (1 << 5) && !(mapElement->flags & MAP_ELEMENT_FLAG_GHOST))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
found = 1;
|
|
||||||
break;
|
|
||||||
} while (!map_element_is_last_for_tile(mapElement++));
|
|
||||||
|
|
||||||
if (!found){
|
|
||||||
return MONEY32_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
rct_xyz16 coord;
|
|
||||||
coord.x = x + 16;
|
|
||||||
coord.y = y + 16;
|
|
||||||
coord.z = map_element_height(coord.x, coord.y);
|
|
||||||
network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord);
|
|
||||||
|
|
||||||
footpath_queue_chain_reset();
|
|
||||||
maze_entrance_hedge_replacement(x, y, mapElement);
|
|
||||||
footpath_remove_edges_at(x, y, mapElement);
|
|
||||||
|
|
||||||
uint8 is_exit = mapElement->properties.entrance.type;
|
|
||||||
|
|
||||||
map_element_remove(mapElement);
|
|
||||||
|
|
||||||
if (is_exit){
|
|
||||||
ride->exits[station_num] = 0xFFFF;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
ride->entrances[station_num] = 0xFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub_6A759F();
|
|
||||||
|
|
||||||
map_invalidate_tile_full(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
gCommandExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* rct2: 0x0066640B
|
|
||||||
*/
|
|
||||||
void game_command_remove_ride_entrance_or_exit(sint32 *eax, sint32 *ebx, sint32 *ecx, sint32 *edx, sint32 *esi, sint32 *edi, sint32 *ebp){
|
|
||||||
*ebx = remove_ride_entrance_or_exit(
|
|
||||||
*eax & 0xFFFF,
|
|
||||||
*ecx & 0xFFFF,
|
|
||||||
*edx & 0xFF,
|
|
||||||
*edi & 0xFF,
|
|
||||||
*ebx & 0xFF
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ride_set_to_default_inspection_interval(sint32 rideIndex)
|
void ride_set_to_default_inspection_interval(sint32 rideIndex)
|
||||||
{
|
{
|
||||||
|
|
|
@ -978,8 +978,7 @@ extern uint8 _currentBrakeSpeed2;
|
||||||
extern uint8 _currentSeatRotationAngle;
|
extern uint8 _currentSeatRotationAngle;
|
||||||
|
|
||||||
extern rct_xyz16 _unkF44188;
|
extern rct_xyz16 _unkF44188;
|
||||||
extern rct_xyzd16 _unkF440BF;
|
|
||||||
extern uint8 _unkF440C4;
|
|
||||||
extern rct_xyzd16 _unkF440C5;
|
extern rct_xyzd16 _unkF440C5;
|
||||||
|
|
||||||
extern uint8 gRideEntranceExitPlaceType;
|
extern uint8 gRideEntranceExitPlaceType;
|
||||||
|
@ -1016,6 +1015,7 @@ sint32 ride_find_track_gap(rct_xy_element *input, rct_xy_element *output);
|
||||||
void ride_construct_new(ride_list_item listItem);
|
void ride_construct_new(ride_list_item listItem);
|
||||||
void ride_construct(sint32 rideIndex);
|
void ride_construct(sint32 rideIndex);
|
||||||
sint32 ride_modify(rct_xy_element *input);
|
sint32 ride_modify(rct_xy_element *input);
|
||||||
|
void ride_remove_peeps(sint32 rideIndex);
|
||||||
void ride_get_status(sint32 rideIndex, rct_string_id *formatSecondary, sint32 *argument);
|
void ride_get_status(sint32 rideIndex, rct_string_id *formatSecondary, sint32 *argument);
|
||||||
rct_peep *ride_get_assigned_mechanic(rct_ride *ride);
|
rct_peep *ride_get_assigned_mechanic(rct_ride *ride);
|
||||||
sint32 ride_get_total_length(rct_ride *ride);
|
sint32 ride_get_total_length(rct_ride *ride);
|
||||||
|
@ -1059,8 +1059,8 @@ void game_command_set_ride_price(sint32 *eax, sint32 *ebx, sint32 *ecx, sint32 *
|
||||||
money32 ride_create_command(sint32 type, sint32 subType, sint32 flags, uint8 *outRideIndex, uint8 *outRideColour);
|
money32 ride_create_command(sint32 type, sint32 subType, sint32 flags, uint8 *outRideIndex, uint8 *outRideColour);
|
||||||
|
|
||||||
void ride_clear_for_construction(sint32 rideIndex);
|
void ride_clear_for_construction(sint32 rideIndex);
|
||||||
void ride_restore_provisional_entrance_or_exit();
|
void ride_entrance_exit_place_provisional_ghost();
|
||||||
void ride_remove_provisional_entrance_or_exit();
|
void ride_entrance_exit_remove_ghost();
|
||||||
void ride_restore_provisional_track_piece();
|
void ride_restore_provisional_track_piece();
|
||||||
void ride_remove_provisional_track_piece();
|
void ride_remove_provisional_track_piece();
|
||||||
void set_vehicle_type_image_max_sizes(rct_ride_entry_vehicle* vehicle_type, sint32 num_images);
|
void set_vehicle_type_image_max_sizes(rct_ride_entry_vehicle* vehicle_type, sint32 num_images);
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include "dropdown.h"
|
#include "dropdown.h"
|
||||||
#include "../sprites.h"
|
#include "../sprites.h"
|
||||||
#include "../world/map.h"
|
#include "../world/map.h"
|
||||||
|
#include "../world/entrance.h"
|
||||||
|
|
||||||
/* move to ride.c */
|
/* move to ride.c */
|
||||||
static void sub_6B2FA9(rct_windownumber number)
|
static void sub_6B2FA9(rct_windownumber number)
|
||||||
|
@ -3737,7 +3738,7 @@ void ride_construction_toolupdate_construct(sint32 screenX, sint32 screenY)
|
||||||
void ride_construction_toolupdate_entrance_exit(sint32 screenX, sint32 screenY)
|
void ride_construction_toolupdate_entrance_exit(sint32 screenX, sint32 screenY)
|
||||||
{
|
{
|
||||||
sint32 x, y, direction;
|
sint32 x, y, direction;
|
||||||
uint8 unk;
|
uint8 stationNum;
|
||||||
|
|
||||||
map_invalidate_selection_rect();
|
map_invalidate_selection_rect();
|
||||||
map_invalidate_map_selection_tiles();
|
map_invalidate_map_selection_tiles();
|
||||||
|
@ -3763,16 +3764,16 @@ void ride_construction_toolupdate_entrance_exit(sint32 screenX, sint32 screenY)
|
||||||
map_invalidate_selection_rect();
|
map_invalidate_selection_rect();
|
||||||
|
|
||||||
direction = gRideEntranceExitPlaceDirection ^ 2;
|
direction = gRideEntranceExitPlaceDirection ^ 2;
|
||||||
unk = gRideEntranceExitPlaceStationIndex;
|
stationNum = gRideEntranceExitPlaceStationIndex;
|
||||||
if (
|
if (
|
||||||
!(_currentTrackSelectionFlags & TRACK_SELECTION_FLAG_ENTRANCE_OR_EXIT) ||
|
!(_currentTrackSelectionFlags & TRACK_SELECTION_FLAG_ENTRANCE_OR_EXIT) ||
|
||||||
x != _unkF440BF.x ||
|
x != gRideEntranceExitGhostPosition.x ||
|
||||||
y != _unkF440BF.y ||
|
y != gRideEntranceExitGhostPosition.y ||
|
||||||
direction != _unkF440BF.direction ||
|
direction != gRideEntranceExitGhostPosition.direction ||
|
||||||
unk != _unkF440C4
|
stationNum != gRideEntranceExitGhostStationIndex
|
||||||
) {
|
) {
|
||||||
_currentTrackPrice = ride_get_entrance_or_exit_price(
|
_currentTrackPrice = ride_get_entrance_or_exit_price(
|
||||||
_currentRideIndex, x, y, direction, gRideEntranceExitPlaceType, unk
|
_currentRideIndex, x, y, direction, gRideEntranceExitPlaceType, stationNum
|
||||||
);
|
);
|
||||||
sub_6C84CE();
|
sub_6C84CE();
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
#include "../rct2.h"
|
#include "../rct2.h"
|
||||||
|
#include "../network/network.h"
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
|
@ -24,17 +25,20 @@ extern "C"
|
||||||
#include "park.h"
|
#include "park.h"
|
||||||
#include "../cheats.h"
|
#include "../cheats.h"
|
||||||
#include "../game.h"
|
#include "../game.h"
|
||||||
#include "../management/finance.h"
|
|
||||||
#include "../localisation/string_ids.h"
|
#include "../localisation/string_ids.h"
|
||||||
|
#include "../management/finance.h"
|
||||||
|
#include "../ride/track.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
bool gParkEntranceGhostExists;
|
bool gParkEntranceGhostExists;
|
||||||
rct_xyz16 gParkEntranceGhostPosition;
|
rct_xyz16 gParkEntranceGhostPosition;
|
||||||
uint8 gParkEntranceGhostDirection;
|
uint8 gParkEntranceGhostDirection;
|
||||||
money32 gParkEntranceGhostPrice;
|
money32 gParkEntranceGhostPrice;
|
||||||
|
|
||||||
rct_xyzd16 gParkEntrances[MAX_PARK_ENTRANCES];
|
rct_xyzd16 gParkEntrances[MAX_PARK_ENTRANCES];
|
||||||
|
|
||||||
|
rct_xyzd16 gRideEntranceExitGhostPosition;
|
||||||
|
uint8 gRideEntranceExitGhostStationIndex;
|
||||||
|
|
||||||
static money32 ParkEntrancePlace(sint32 flags, sint16 x, sint16 y, uint8 z, uint8 direction)
|
static money32 ParkEntrancePlace(sint32 flags, sint16 x, sint16 y, uint8 z, uint8 direction)
|
||||||
{
|
{
|
||||||
if (!(gScreenFlags & SCREEN_FLAGS_EDITOR) && !gCheatsSandboxMode)
|
if (!(gScreenFlags & SCREEN_FLAGS_EDITOR) && !gCheatsSandboxMode)
|
||||||
|
@ -224,6 +228,293 @@ static money32 ParkEntranceRemove(sint16 x, sint16 y, uint8 z, uint8 flags)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static money32 place_ride_entrance_or_exit(sint16 x, sint16 y, sint16 z, uint8 direction, uint8 flags, uint8 rideIndex, uint8 station_num, uint8 is_exit)
|
||||||
|
{
|
||||||
|
// Remember when in Unknown station num mode rideIndex is unknown and z is set
|
||||||
|
// When in known station num mode rideIndex is known and z is unknown
|
||||||
|
|
||||||
|
money32 cost = 0;
|
||||||
|
gCommandPosition.x = x;
|
||||||
|
gCommandPosition.y = y;
|
||||||
|
|
||||||
|
if (!map_check_free_elements_and_reorganise(1)) {
|
||||||
|
return MONEY32_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(flags & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED) && game_is_paused() && !gCheatsBuildInPauseMode){
|
||||||
|
gGameCommandErrorText = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED;
|
||||||
|
return MONEY32_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (station_num == 0xFF) {
|
||||||
|
z *= 16;
|
||||||
|
if (flags & GAME_COMMAND_FLAG_APPLY)
|
||||||
|
return MONEY32_UNDEFINED;
|
||||||
|
|
||||||
|
if (!gCheatsSandboxMode && !map_is_location_owned(x, y, z)) {
|
||||||
|
return MONEY32_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
sint16 clear_z = z / 8 + (is_exit ? 5 : 7);
|
||||||
|
|
||||||
|
if (!gCheatsDisableClearanceChecks && !map_can_construct_with_clear_at(x, y, z / 8, clear_z, &map_place_non_scenery_clear_func, 0xF, flags, &cost)) {
|
||||||
|
return MONEY32_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gMapGroundFlags & ELEMENT_IS_UNDERWATER) {
|
||||||
|
gGameCommandErrorText = STR_RIDE_CANT_BUILD_THIS_UNDERWATER;
|
||||||
|
return MONEY32_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (z > 1952) {
|
||||||
|
gGameCommandErrorText = STR_TOO_HIGH;
|
||||||
|
return MONEY32_UNDEFINED;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (rideIndex >= MAX_RIDES)
|
||||||
|
{
|
||||||
|
log_warning("Invalid game command for ride %u", rideIndex);
|
||||||
|
return MONEY32_UNDEFINED;
|
||||||
|
}
|
||||||
|
rct_ride* ride = get_ride(rideIndex);
|
||||||
|
if (ride->type == RIDE_TYPE_NULL)
|
||||||
|
{
|
||||||
|
log_warning("Invalid game command for ride %u", rideIndex);
|
||||||
|
return MONEY32_UNDEFINED;
|
||||||
|
}
|
||||||
|
if (ride->status != RIDE_STATUS_CLOSED) {
|
||||||
|
gGameCommandErrorText = STR_MUST_BE_CLOSED_FIRST;
|
||||||
|
return MONEY32_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ride->lifecycle_flags & RIDE_LIFECYCLE_INDESTRUCTIBLE_TRACK) {
|
||||||
|
gGameCommandErrorText = STR_NOT_ALLOWED_TO_MODIFY_STATION;
|
||||||
|
return MONEY32_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
ride_clear_for_construction(rideIndex);
|
||||||
|
ride_remove_peeps(rideIndex);
|
||||||
|
|
||||||
|
uint8 requires_remove = 0;
|
||||||
|
sint16 remove_x = 0;
|
||||||
|
sint16 remove_y = 0;
|
||||||
|
|
||||||
|
if (is_exit) {
|
||||||
|
if (ride->exits[station_num] != 0xFFFF) {
|
||||||
|
if (flags & GAME_COMMAND_FLAG_GHOST) {
|
||||||
|
gGameCommandErrorText = 0;
|
||||||
|
return MONEY32_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_x = (ride->exits[station_num] & 0xFF) * 32;
|
||||||
|
remove_y = ((ride->exits[station_num] >> 8) & 0xFF) * 32;
|
||||||
|
requires_remove = 1;
|
||||||
|
}
|
||||||
|
} else if (ride->entrances[station_num] != 0xFFFF) {
|
||||||
|
if (flags & GAME_COMMAND_FLAG_GHOST) {
|
||||||
|
gGameCommandErrorText = 0;
|
||||||
|
return MONEY32_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_x = (ride->entrances[station_num] & 0xFF) * 32;
|
||||||
|
remove_y = ((ride->entrances[station_num] >> 8) & 0xFF) * 32;
|
||||||
|
requires_remove = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (requires_remove) {
|
||||||
|
money32 success = game_do_command(
|
||||||
|
remove_x,
|
||||||
|
flags,
|
||||||
|
remove_y,
|
||||||
|
rideIndex,
|
||||||
|
GAME_COMMAND_REMOVE_RIDE_ENTRANCE_OR_EXIT,
|
||||||
|
station_num,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
if (success == MONEY32_UNDEFINED) {
|
||||||
|
return MONEY32_UNDEFINED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
z = ride->station_heights[station_num] * 8;
|
||||||
|
gCommandPosition.z = z;
|
||||||
|
|
||||||
|
if (
|
||||||
|
(flags & GAME_COMMAND_FLAG_APPLY) &&
|
||||||
|
!(flags & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED) &&
|
||||||
|
!(flags & GAME_COMMAND_FLAG_GHOST)
|
||||||
|
) {
|
||||||
|
footpath_remove_litter(x, y, z);
|
||||||
|
wall_remove_at_z(x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gCheatsSandboxMode && !map_is_location_owned(x, y, z)) {
|
||||||
|
return MONEY32_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
sint8 clear_z = (z / 8) + (is_exit ? 5 : 7);
|
||||||
|
|
||||||
|
if (!gCheatsDisableClearanceChecks && !map_can_construct_with_clear_at(x, y, z / 8, clear_z, &map_place_non_scenery_clear_func, 0xF, flags, &cost)) {
|
||||||
|
return MONEY32_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gMapGroundFlags & ELEMENT_IS_UNDERWATER) {
|
||||||
|
gGameCommandErrorText = STR_RIDE_CANT_BUILD_THIS_UNDERWATER;
|
||||||
|
return MONEY32_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (z / 8 > 244){
|
||||||
|
gGameCommandErrorText = STR_TOO_HIGH;
|
||||||
|
return MONEY32_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & GAME_COMMAND_FLAG_APPLY) {
|
||||||
|
rct_xyz16 coord;
|
||||||
|
coord.x = x + 16;
|
||||||
|
coord.y = y + 16;
|
||||||
|
coord.z = map_element_height(coord.x, coord.y);
|
||||||
|
network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord);
|
||||||
|
|
||||||
|
rct_map_element* mapElement = map_element_insert(x / 32, y / 32, z / 8, 0xF);
|
||||||
|
assert(mapElement != NULL);
|
||||||
|
mapElement->clearance_height = clear_z;
|
||||||
|
mapElement->properties.entrance.type = is_exit;
|
||||||
|
mapElement->properties.entrance.index = station_num << 4;
|
||||||
|
mapElement->properties.entrance.ride_index = rideIndex;
|
||||||
|
mapElement->type = MAP_ELEMENT_TYPE_ENTRANCE | direction;
|
||||||
|
|
||||||
|
if (flags & GAME_COMMAND_FLAG_GHOST) {
|
||||||
|
mapElement->flags |= MAP_ELEMENT_FLAG_GHOST;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_exit) {
|
||||||
|
ride->exits[station_num] = (x / 32) | (y / 32 << 8);
|
||||||
|
} else {
|
||||||
|
ride->entrances[station_num] = (x / 32) | (y / 32 << 8);
|
||||||
|
ride->last_peep_in_queue[station_num] = SPRITE_INDEX_NULL;
|
||||||
|
ride->queue_length[station_num] = 0;
|
||||||
|
|
||||||
|
map_animation_create(MAP_ANIMATION_TYPE_RIDE_ENTRANCE, x, y, z / 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
footpath_queue_chain_reset();
|
||||||
|
if (!(flags & GAME_COMMAND_FLAG_GHOST)) {
|
||||||
|
maze_entrance_hedge_removal(x, y, mapElement);
|
||||||
|
}
|
||||||
|
footpath_connect_edges(x, y, mapElement, flags);
|
||||||
|
sub_6A759F();
|
||||||
|
|
||||||
|
map_invalidate_tile_full(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gCommandExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION;
|
||||||
|
return cost;
|
||||||
|
}
|
||||||
|
|
||||||
|
static money32 remove_ride_entrance_or_exit(sint16 x, sint16 y, uint8 rideIndex, uint8 station_num, uint8 flags){
|
||||||
|
if (rideIndex >= MAX_RIDES)
|
||||||
|
{
|
||||||
|
log_warning("Invalid game command for ride %u", rideIndex);
|
||||||
|
return MONEY32_UNDEFINED;
|
||||||
|
}
|
||||||
|
rct_ride* ride = get_ride(rideIndex);
|
||||||
|
if (ride->type == RIDE_TYPE_NULL)
|
||||||
|
{
|
||||||
|
log_warning("Invalide ride id %u for entrance/exit removal", rideIndex);
|
||||||
|
return MONEY32_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(flags & GAME_COMMAND_FLAG_GHOST)){
|
||||||
|
if (!(flags & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED) && game_is_paused() && !gCheatsBuildInPauseMode){
|
||||||
|
gGameCommandErrorText = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED;
|
||||||
|
return MONEY32_UNDEFINED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ride->status != RIDE_STATUS_CLOSED){
|
||||||
|
gGameCommandErrorText = STR_MUST_BE_CLOSED_FIRST;
|
||||||
|
return MONEY32_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ride->lifecycle_flags & RIDE_LIFECYCLE_INDESTRUCTIBLE_TRACK) {
|
||||||
|
gGameCommandErrorText = STR_NOT_ALLOWED_TO_MODIFY_STATION;
|
||||||
|
return MONEY32_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & GAME_COMMAND_FLAG_APPLY){
|
||||||
|
ride_clear_for_construction(rideIndex);
|
||||||
|
ride_remove_peeps(rideIndex);
|
||||||
|
invalidate_test_results(rideIndex);
|
||||||
|
|
||||||
|
uint8 found = 0;
|
||||||
|
rct_map_element* mapElement = map_get_first_element_at(x / 32, y / 32);
|
||||||
|
if (mapElement == NULL)
|
||||||
|
{
|
||||||
|
log_warning("Invalid coordinates for entrance/exit removal x = %d, y = %d", x, y);
|
||||||
|
return MONEY32_UNDEFINED;
|
||||||
|
}
|
||||||
|
do{
|
||||||
|
if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_ENTRANCE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (mapElement->base_height != ride->station_heights[station_num])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (flags & (1 << 5) && !(mapElement->flags & MAP_ELEMENT_FLAG_GHOST))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
found = 1;
|
||||||
|
break;
|
||||||
|
} while (!map_element_is_last_for_tile(mapElement++));
|
||||||
|
|
||||||
|
if (!found){
|
||||||
|
return MONEY32_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
rct_xyz16 coord;
|
||||||
|
coord.x = x + 16;
|
||||||
|
coord.y = y + 16;
|
||||||
|
coord.z = map_element_height(coord.x, coord.y);
|
||||||
|
network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord);
|
||||||
|
|
||||||
|
footpath_queue_chain_reset();
|
||||||
|
maze_entrance_hedge_replacement(x, y, mapElement);
|
||||||
|
footpath_remove_edges_at(x, y, mapElement);
|
||||||
|
|
||||||
|
uint8 is_exit = mapElement->properties.entrance.type;
|
||||||
|
|
||||||
|
map_element_remove(mapElement);
|
||||||
|
|
||||||
|
if (is_exit){
|
||||||
|
ride->exits[station_num] = 0xFFFF;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
ride->entrances[station_num] = 0xFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub_6A759F();
|
||||||
|
|
||||||
|
map_invalidate_tile_full(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
gCommandExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
money32 ride_entrance_exit_place_ghost(uint8 rideIndex, sint16 x, sint16 y, uint8 direction, uint8 placeType, uint8 stationNum)
|
||||||
|
{
|
||||||
|
return game_do_command(
|
||||||
|
x,
|
||||||
|
(GAME_COMMAND_FLAG_APPLY | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_5 | GAME_COMMAND_FLAG_GHOST) | (direction << 8),
|
||||||
|
y,
|
||||||
|
rideIndex | (placeType << 8),
|
||||||
|
GAME_COMMAND_PLACE_RIDE_ENTRANCE_OR_EXIT,
|
||||||
|
stationNum,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
|
@ -346,4 +637,150 @@ extern "C"
|
||||||
gParkEntrances[i].x = MAP_LOCATION_NULL;
|
gParkEntrances[i].x = MAP_LOCATION_NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ride_entrance_exit_place_provisional_ghost()
|
||||||
|
{
|
||||||
|
if (_currentTrackSelectionFlags & TRACK_SELECTION_FLAG_ENTRANCE_OR_EXIT) {
|
||||||
|
ride_entrance_exit_place_ghost(_currentRideIndex,
|
||||||
|
gRideEntranceExitGhostPosition.x,
|
||||||
|
gRideEntranceExitGhostPosition.y,
|
||||||
|
gRideEntranceExitGhostPosition.direction,
|
||||||
|
gRideEntranceExitPlaceType,
|
||||||
|
gRideEntranceExitGhostStationIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ride_entrance_exit_remove_ghost()
|
||||||
|
{
|
||||||
|
if (_currentTrackSelectionFlags & TRACK_SELECTION_FLAG_ENTRANCE_OR_EXIT) {
|
||||||
|
game_do_command(
|
||||||
|
gRideEntranceExitGhostPosition.x,
|
||||||
|
(GAME_COMMAND_FLAG_5 | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_APPLY),
|
||||||
|
gRideEntranceExitGhostPosition.y,
|
||||||
|
_currentRideIndex,
|
||||||
|
GAME_COMMAND_REMOVE_RIDE_ENTRANCE_OR_EXIT,
|
||||||
|
gRideEntranceExitGhostStationIndex,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* rct2: 0x006CA28C
|
||||||
|
*/
|
||||||
|
money32 ride_get_entrance_or_exit_price(sint32 rideIndex, sint32 x, sint32 y, sint32 direction, sint32 dh, sint32 di)
|
||||||
|
{
|
||||||
|
sub_6C96C0();
|
||||||
|
money32 result = ride_entrance_exit_place_ghost(rideIndex, x, y, direction, dh, di);
|
||||||
|
if (result != MONEY32_UNDEFINED) {
|
||||||
|
_currentTrackSelectionFlags |= TRACK_SELECTION_FLAG_ENTRANCE_OR_EXIT;
|
||||||
|
gRideEntranceExitGhostPosition.x = x;
|
||||||
|
gRideEntranceExitGhostPosition.y = y;
|
||||||
|
gRideEntranceExitGhostPosition.direction = direction;
|
||||||
|
gRideEntranceExitGhostStationIndex = di & 0xFF;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* rct2: 0x006660A8
|
||||||
|
*/
|
||||||
|
void game_command_place_ride_entrance_or_exit(sint32 *eax, sint32 *ebx, sint32 *ecx, sint32 *edx, sint32 *esi, sint32 *edi, sint32 *ebp){
|
||||||
|
*ebx = place_ride_entrance_or_exit(
|
||||||
|
*eax & 0xFFFF,
|
||||||
|
*ecx & 0xFFFF,
|
||||||
|
*edx & 0xFF,
|
||||||
|
(*ebx >> 8) & 0xFF,
|
||||||
|
*ebx & 0xFF,
|
||||||
|
*edx & 0xFF,
|
||||||
|
*edi & 0xFF,
|
||||||
|
(*edx >> 8) & 0xFF
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* rct2: 0x0066640B
|
||||||
|
*/
|
||||||
|
void game_command_remove_ride_entrance_or_exit(sint32 *eax, sint32 *ebx, sint32 *ecx, sint32 *edx, sint32 *esi, sint32 *edi, sint32 *ebp){
|
||||||
|
*ebx = remove_ride_entrance_or_exit(
|
||||||
|
*eax & 0xFFFF,
|
||||||
|
*ecx & 0xFFFF,
|
||||||
|
*edx & 0xFF,
|
||||||
|
*edi & 0xFF,
|
||||||
|
*ebx & 0xFF
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces the outer hedge walls for an entrance placement removal.
|
||||||
|
* rct2: 0x00666D6F
|
||||||
|
*/
|
||||||
|
void maze_entrance_hedge_replacement(sint32 x, sint32 y, rct_map_element *mapElement)
|
||||||
|
{
|
||||||
|
sint32 direction = mapElement->type & MAP_ELEMENT_DIRECTION_MASK;
|
||||||
|
x += TileDirectionDelta[direction].x;
|
||||||
|
y += TileDirectionDelta[direction].y;
|
||||||
|
sint32 z = mapElement->base_height;
|
||||||
|
sint32 rideIndex = mapElement->properties.track.ride_index;
|
||||||
|
|
||||||
|
mapElement = map_get_first_element_at(x >> 5, y >> 5);
|
||||||
|
do {
|
||||||
|
if (mapElement->type != MAP_ELEMENT_TYPE_TRACK) continue;
|
||||||
|
if (mapElement->properties.track.ride_index != rideIndex) continue;
|
||||||
|
if (mapElement->base_height != z) continue;
|
||||||
|
if (mapElement->properties.track.type != TRACK_ELEM_MAZE) continue;
|
||||||
|
|
||||||
|
// Each maze element is split into 4 sections with 4 different walls
|
||||||
|
uint8 mazeSection = direction * 4;
|
||||||
|
// Add the top outer wall
|
||||||
|
mapElement->properties.track.maze_entry |= (1 << ((mazeSection + 9) & 0x0F));
|
||||||
|
// Add the bottom outer wall
|
||||||
|
mapElement->properties.track.maze_entry |= (1 << ((mazeSection + 12) & 0x0F));
|
||||||
|
|
||||||
|
map_invalidate_tile(x, y, mapElement->base_height * 8, mapElement->clearance_height * 8);
|
||||||
|
return;
|
||||||
|
} while (!map_element_is_last_for_tile(mapElement++));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the hedge walls for an entrance placement.
|
||||||
|
* rct2: 0x00666CBE
|
||||||
|
*/
|
||||||
|
void maze_entrance_hedge_removal(sint32 x, sint32 y, rct_map_element *mapElement)
|
||||||
|
{
|
||||||
|
sint32 direction = mapElement->type & MAP_ELEMENT_DIRECTION_MASK;
|
||||||
|
x += TileDirectionDelta[direction].x;
|
||||||
|
y += TileDirectionDelta[direction].y;
|
||||||
|
sint32 z = mapElement->base_height;
|
||||||
|
sint32 rideIndex = mapElement->properties.track.ride_index;
|
||||||
|
|
||||||
|
mapElement = map_get_first_element_at(x >> 5, y >> 5);
|
||||||
|
do {
|
||||||
|
if (mapElement->type != MAP_ELEMENT_TYPE_TRACK) continue;
|
||||||
|
if (mapElement->properties.track.ride_index != rideIndex) continue;
|
||||||
|
if (mapElement->base_height != z) continue;
|
||||||
|
if (mapElement->properties.track.type != TRACK_ELEM_MAZE) continue;
|
||||||
|
|
||||||
|
// Each maze element is split into 4 sections with 4 different walls
|
||||||
|
uint8 mazeSection = direction * 4;
|
||||||
|
// Remove the top outer wall
|
||||||
|
mapElement->properties.track.maze_entry &= ~(1 << ((mazeSection + 9) & 0x0F));
|
||||||
|
// Remove the bottom outer wall
|
||||||
|
mapElement->properties.track.maze_entry &= ~(1 << ((mazeSection + 12) & 0x0F));
|
||||||
|
// Remove the intersecting wall
|
||||||
|
mapElement->properties.track.maze_entry &= ~(1 << ((mazeSection + 10) & 0x0F));
|
||||||
|
// Remove the top hedge section
|
||||||
|
mapElement->properties.track.maze_entry &= ~(1 << ((mazeSection + 11) & 0x0F));
|
||||||
|
// Remove the bottom hedge section
|
||||||
|
mapElement->properties.track.maze_entry &= ~(1 << ((mazeSection + 15) & 0x0F));
|
||||||
|
|
||||||
|
map_invalidate_tile(x, y, mapElement->base_height * 8, mapElement->clearance_height * 8);
|
||||||
|
return;
|
||||||
|
} while (!map_element_is_last_for_tile(mapElement++));
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -33,6 +33,7 @@ void game_command_remove_park_entrance(sint32 *eax, sint32 *ebx, sint32 *ecx, si
|
||||||
|
|
||||||
typedef struct rct_xyz16;
|
typedef struct rct_xyz16;
|
||||||
typedef struct rct_xyzd16;
|
typedef struct rct_xyzd16;
|
||||||
|
typedef struct rct_map_element;
|
||||||
|
|
||||||
extern bool gParkEntranceGhostExists;
|
extern bool gParkEntranceGhostExists;
|
||||||
extern rct_xyz16 gParkEntranceGhostPosition;
|
extern rct_xyz16 gParkEntranceGhostPosition;
|
||||||
|
@ -43,8 +44,13 @@ extern money32 gParkEntranceGhostPrice;
|
||||||
|
|
||||||
extern rct_xyzd16 gParkEntrances[MAX_PARK_ENTRANCES];
|
extern rct_xyzd16 gParkEntrances[MAX_PARK_ENTRANCES];
|
||||||
|
|
||||||
|
extern rct_xyzd16 gRideEntranceExitGhostPosition;
|
||||||
|
extern uint8 gRideEntranceExitGhostStationIndex;
|
||||||
|
|
||||||
void park_entrance_remove_ghost();
|
void park_entrance_remove_ghost();
|
||||||
money32 park_entrance_place_ghost(sint32 x, sint32 y, sint32 z, sint32 direction);
|
money32 park_entrance_place_ghost(sint32 x, sint32 y, sint32 z, sint32 direction);
|
||||||
void reset_park_entrance();
|
void reset_park_entrance();
|
||||||
|
void maze_entrance_hedge_replacement(sint32 x, sint32 y, rct_map_element *mapElement);
|
||||||
|
void maze_entrance_hedge_removal(sint32 x, sint32 y, rct_map_element *mapElement);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -3971,10 +3971,10 @@ void map_remove_provisional_elements()
|
||||||
footpath_provisional_remove();
|
footpath_provisional_remove();
|
||||||
gFootpathProvisionalFlags |= PROVISIONAL_PATH_FLAG_1;
|
gFootpathProvisionalFlags |= PROVISIONAL_PATH_FLAG_1;
|
||||||
}
|
}
|
||||||
if (window_find_by_class(WC_CONSTRUCT_RIDE) != NULL)
|
if (window_find_by_class(WC_RIDE_CONSTRUCTION ) != NULL)
|
||||||
{
|
{
|
||||||
ride_remove_provisional_track_piece();
|
ride_remove_provisional_track_piece();
|
||||||
ride_remove_provisional_entrance_or_exit();
|
ride_entrance_exit_remove_ghost();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3989,10 +3989,10 @@ void map_restore_provisional_elements()
|
||||||
gFootpathProvisionalPosition.z,
|
gFootpathProvisionalPosition.z,
|
||||||
gFootpathProvisionalSlope);
|
gFootpathProvisionalSlope);
|
||||||
}
|
}
|
||||||
if (window_find_by_class(WC_CONSTRUCT_RIDE) != NULL)
|
if (window_find_by_class(WC_RIDE_CONSTRUCTION) != NULL)
|
||||||
{
|
{
|
||||||
ride_restore_provisional_track_piece();
|
ride_restore_provisional_track_piece();
|
||||||
ride_restore_provisional_entrance_or_exit();
|
ride_entrance_exit_place_provisional_ghost();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue