integrate ground flag variables

This commit is contained in:
Ted John 2016-05-17 20:51:11 +01:00
parent 52a92fa6f1
commit c879638f22
14 changed files with 59 additions and 40 deletions

View File

@ -181,8 +181,6 @@
#define RCT2_ADDRESS_UNCOMPLETED_RESEARCH_TYPES 0x00EE787C
#define RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER 0x00F1AD60
#define RCT2_ADDRESS_MAP_IMAGE_DATA 0x00F1AD68
// No longer used
@ -553,6 +551,8 @@
#define RCT2_ADDRESS_PARK_ENTRANCE_GHOST_EXISTS 0x009E32D2
#define RCT2_ADDRESS_PARK_ENTRANCE_GHOST_PRICE 0x009E32D3
#define RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER 0x00F1AD60
#define RCT2_ADDRESS_PROVISIONAL_PATH_FLAGS 0x00F3EF92
#define RCT2_ADDRESS_PROVISIONAL_PATH_X 0x00F3EF94
#define RCT2_ADDRESS_PROVISIONAL_PATH_Y 0x00F3EF96

View File

@ -8096,7 +8096,7 @@ money32 place_ride_entrance_or_exit(sint16 x, sint16 y, sint16 z, uint8 directio
return MONEY32_UNDEFINED;
}
if (RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8) & ELEMENT_IS_UNDERWATER) {
if (gMapGroundFlags & ELEMENT_IS_UNDERWATER) {
gGameCommandErrorText = STR_RIDE_CANT_BUILD_THIS_UNDERWATER;
return MONEY32_UNDEFINED;
}
@ -8194,7 +8194,7 @@ money32 place_ride_entrance_or_exit(sint16 x, sint16 y, sint16 z, uint8 directio
return MONEY32_UNDEFINED;
}
if (RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8) & ELEMENT_IS_UNDERWATER) {
if (gMapGroundFlags & ELEMENT_IS_UNDERWATER) {
gGameCommandErrorText = STR_RIDE_CANT_BUILD_THIS_UNDERWATER;
return MONEY32_UNDEFINED;
}

View File

@ -38,6 +38,8 @@
#include "track.h"
#include "track_data.h"
uint8 gTrackGroundFlags;
/**
*
* rct2: 0x00997C9D
@ -614,7 +616,7 @@ static money32 track_place(int rideIndex, int type, int originX, int originY, in
RCT2_GLOBAL(0x00F441D5, uint32) = properties_1;
RCT2_GLOBAL(0x00F441D9, uint32) = properties_2;
RCT2_GLOBAL(0x00F441DD, uint32) = properties_3;
RCT2_GLOBAL(RCT2_ADDRESS_ABOVE_GROUND_FLAGS, uint8) = 0;
gTrackGroundFlags = 0;
uint64 enabledTrackPieces = 0;
enabledTrackPieces |= rideEntry->enabledTrackPiecesB & gResearchedTrackTypesB[ride->type];
@ -808,16 +810,16 @@ static money32 track_place(int rideIndex, int type, int originX, int originY, in
}
}
bh = RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8) & 3;
if (RCT2_GLOBAL(RCT2_ADDRESS_ABOVE_GROUND_FLAGS, uint8) != 0 && (RCT2_GLOBAL(RCT2_ADDRESS_ABOVE_GROUND_FLAGS, uint8) & bh) == 0) {
bh = gMapGroundFlags & (ELEMENT_IS_1 | ELEMENT_IS_UNDERGROUND);
if (gTrackGroundFlags != 0 && (gTrackGroundFlags & bh) == 0) {
gGameCommandErrorText = STR_CANT_BUILD_PARTLY_ABOVE_AND_PARTLY_BELOW_GROUND;
return MONEY32_UNDEFINED;
}
RCT2_GLOBAL(RCT2_ADDRESS_ABOVE_GROUND_FLAGS, uint8) = bh;
gTrackGroundFlags = bh;
if (rideTypeFlags & RIDE_TYPE_FLAG_FLAT_RIDE) {
if (RCT2_ADDRESS(0x0099443C, uint16)[type] & 0x200) {
if (RCT2_GLOBAL(RCT2_ADDRESS_ABOVE_GROUND_FLAGS, uint8) & TRACK_ELEMENT_LOCATION_IS_UNDERGROUND) {
if (gTrackGroundFlags & TRACK_ELEMENT_LOCATION_IS_UNDERGROUND) {
gGameCommandErrorText = STR_CAN_ONLY_BUILD_THIS_ABOVE_GROUND;
return MONEY32_UNDEFINED;
}
@ -825,7 +827,7 @@ static money32 track_place(int rideIndex, int type, int originX, int originY, in
}
else {
if (RCT2_ADDRESS(0x0099423C, uint16)[type] & 0x200) {
if (RCT2_GLOBAL(RCT2_ADDRESS_ABOVE_GROUND_FLAGS, uint8) & TRACK_ELEMENT_LOCATION_IS_UNDERGROUND) {
if (gTrackGroundFlags & TRACK_ELEMENT_LOCATION_IS_UNDERGROUND) {
gGameCommandErrorText = STR_CAN_ONLY_BUILD_THIS_ABOVE_GROUND;
return MONEY32_UNDEFINED;
}
@ -834,7 +836,7 @@ static money32 track_place(int rideIndex, int type, int originX, int originY, in
if (rideTypeFlags & RIDE_TYPE_FLAG_FLAT_RIDE) {
if (RCT2_ADDRESS(0x0099443C, uint16)[type] & 1) {
if (!(RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8) & ELEMENT_IS_UNDERWATER)) {
if (!(gMapGroundFlags & ELEMENT_IS_UNDERWATER)) {
gGameCommandErrorText = STR_CAN_ONLY_BUILD_THIS_UNDERWATER;
return MONEY32_UNDEFINED;
}
@ -842,14 +844,14 @@ static money32 track_place(int rideIndex, int type, int originX, int originY, in
}
else {
if (RCT2_ADDRESS(0x0099423C, uint16)[type] & 1) {
if (RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8) & ELEMENT_IS_UNDERWATER) {
if (gMapGroundFlags & ELEMENT_IS_UNDERWATER) {
gGameCommandErrorText = STR_CAN_ONLY_BUILD_THIS_UNDERWATER;
return MONEY32_UNDEFINED;
}
}
}
if (RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8) & ELEMENT_IS_UNDERWATER) {
if (gMapGroundFlags & ELEMENT_IS_UNDERWATER) {
gGameCommandErrorText = STR_RIDE_CANT_BUILD_THIS_UNDERWATER;
return MONEY32_UNDEFINED;
}
@ -1477,12 +1479,12 @@ money32 set_maze_track(uint16 x, uint8 flags, uint8 direction, uint16 y, uint8 r
return MONEY32_UNDEFINED;
}
if (RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8) & ELEMENT_IS_UNDERWATER) {
if (gMapGroundFlags & ELEMENT_IS_UNDERWATER) {
gGameCommandErrorText = STR_RIDE_CANT_BUILD_THIS_UNDERWATER;
return MONEY32_UNDEFINED;
}
if (RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8) & 0x02) {
if (gMapGroundFlags & ELEMENT_IS_UNDERGROUND) {
gGameCommandErrorText = STR_CAN_ONLY_BUILD_THIS_ABOVE_GROUND;
return MONEY32_UNDEFINED;
}

View File

@ -461,6 +461,8 @@ typedef struct track_circuit_iterator {
extern const rct_trackdefinition *gFlatRideTrackDefinitions;
extern const rct_trackdefinition *gTrackDefinitions;
extern uint8 gTrackGroundFlags;
int track_is_connected_by_shape(rct_map_element *a, rct_map_element *b);
const rct_preview_track *get_track_def_from_ride(rct_ride *ride, int trackType);

View File

@ -1575,7 +1575,7 @@ money32 place_maze_design(uint8 flags, uint8 rideIndex, uint16 mazeEntry, sint16
return MONEY32_UNDEFINED;
}
uint8 elctgaw = RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8);
uint8 elctgaw = gMapGroundFlags;
if (elctgaw & ELEMENT_IS_UNDERWATER) {
gGameCommandErrorText = STR_RIDE_CANT_BUILD_THIS_UNDERWATER;
return MONEY32_UNDEFINED;

View File

@ -878,7 +878,7 @@ static void window_footpath_construct()
gFootpathConstructValidDirections = gFootpathConstructDirection;
}
if (RCT2_GLOBAL(0x00F3EFA4, uint8) & 2)
if (gFootpathGroundFlags & ELEMENT_IS_UNDERGROUND)
viewport_set_visibility(1);
// If we have just built an upwards slope, the next path to construct is

View File

@ -1632,7 +1632,7 @@ static void window_ride_construction_construct(rct_window *w)
audio_play_sound_at_location(SOUND_PLACE_ITEM, x, y, z);
if (RCT2_GLOBAL(RCT2_ADDRESS_ABOVE_GROUND_FLAGS, uint8) & TRACK_ELEMENT_LOCATION_IS_UNDERGROUND) {
if (gTrackGroundFlags & TRACK_ELEMENT_LOCATION_IS_UNDERGROUND) {
viewport_set_visibility(1);
}
@ -2687,7 +2687,7 @@ money32 sub_6CA162(int rideIndex, int trackType, int trackDirection, int edxRS16
RCT2_GLOBAL(0x00F440C9, uint16) = z;
RCT2_GLOBAL(0x00F440CB, uint8) = trackDirection;
_currentTrackSelectionFlags |= 2;
viewport_set_visibility(RCT2_GLOBAL(RCT2_ADDRESS_ABOVE_GROUND_FLAGS, uint8) & TRACK_ELEMENT_LOCATION_IS_UNDERGROUND ? 1 : 3);
viewport_set_visibility(gTrackGroundFlags & TRACK_ELEMENT_LOCATION_IS_UNDERGROUND ? 1 : 3);
if (_currentTrackSlopeEnd != 0)
viewport_set_visibility(2);
@ -2706,7 +2706,7 @@ money32 sub_6CA162(int rideIndex, int trackType, int trackDirection, int edxRS16
RCT2_GLOBAL(0x00F440C9, uint16) = z;
RCT2_GLOBAL(0x00F440CB, uint8) = trackDirection;
_currentTrackSelectionFlags |= 2;
viewport_set_visibility(RCT2_GLOBAL(RCT2_ADDRESS_ABOVE_GROUND_FLAGS, uint8) & TRACK_ELEMENT_LOCATION_IS_UNDERGROUND ? 1 : 3);
viewport_set_visibility(gTrackGroundFlags & TRACK_ELEMENT_LOCATION_IS_UNDERGROUND ? 1 : 3);
if (_currentTrackSlopeEnd != 0)
viewport_set_visibility(2);

View File

@ -2133,7 +2133,7 @@ money32 try_place_ghost_scenery(rct_xy16 map_tile, uint32 parameter_1, uint32 pa
mapElement = gSceneryMapElement;
gSceneryGhostPosition.z = mapElement->base_height;
gSceneryMapElementType = mapElement->type;
if (RCT2_GLOBAL(0x00F64F14, uint8) & (1 << 1)){
if (gSceneryGroundFlags & ELEMENT_IS_UNDERGROUND){
//Set underground on
viewport_set_visibility(4);
}
@ -2220,7 +2220,7 @@ money32 try_place_ghost_scenery(rct_xy16 map_tile, uint32 parameter_1, uint32 pa
mapElement = gSceneryMapElement;
gSceneryGhostPosition.z = mapElement->base_height;
if (RCT2_GLOBAL(0x00F64F14, uint8) & (1 << 1)){
if (gSceneryGroundFlags & ELEMENT_IS_UNDERGROUND){
//Set underground on
viewport_set_visibility(4);
}

View File

@ -41,6 +41,7 @@ uint8 gFootpathConstructDirection;
uint8 gFootpathConstructSlope;
uint8 gFootpathConstructValidDirections;
money32 gFootpathPrice;
uint8 gFootpathGroundFlags;
const rct_xy16 word_981D6C[4] = {
{ -1, 0 },
@ -168,8 +169,8 @@ static money32 footpath_element_insert(int type, int x, int y, int z, int slope,
if (!gCheatsDisableClearanceChecks && !map_can_construct_with_clear_at(x, y, z, zHigh, &map_place_non_scenery_clear_func, bl, flags, &gFootpathPrice))
return MONEY32_UNDEFINED;
RCT2_GLOBAL(0x00F3EFA4, uint8) = RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8);
if (!gCheatsDisableClearanceChecks && (RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8) & ELEMENT_IS_UNDERWATER)) {
gFootpathGroundFlags = gMapGroundFlags;
if (!gCheatsDisableClearanceChecks && (gMapGroundFlags & ELEMENT_IS_UNDERWATER)) {
gGameCommandErrorText = STR_CANT_BUILD_THIS_UNDERWATER;
return MONEY32_UNDEFINED;
}
@ -324,7 +325,7 @@ static money32 footpath_place_real(int type, int x, int y, int z, int slope, int
footpath_interrupt_peeps(x, y, z * 8);
gFootpathPrice = 0;
RCT2_GLOBAL(0x00F3EFA4, uint8) = 0;
gFootpathGroundFlags = 0;
if (x >= gMapSizeUnits || y >= gMapSizeUnits) {
gGameCommandErrorText = STR_OFF_EDGE_OF_MAP;
@ -461,7 +462,7 @@ static money32 footpath_place_from_track(int type, int x, int y, int z, int slop
footpath_interrupt_peeps(x, y, z * 8);
gFootpathPrice = 0;
RCT2_GLOBAL(0x00F3EFA4, uint8) = 0;
gFootpathGroundFlags = 0;
if (!map_is_location_owned(x, y, z * 8) && !gCheatsSandboxMode) {
return MONEY32_UNDEFINED;
@ -497,8 +498,8 @@ static money32 footpath_place_from_track(int type, int x, int y, int z, int slop
if (!gCheatsDisableClearanceChecks && !map_can_construct_with_clear_at(x, y, z, zHigh, &map_place_non_scenery_clear_func, bl, flags, &gFootpathPrice))
return MONEY32_UNDEFINED;
RCT2_GLOBAL(0x00F3EFA4, uint8) = RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8);
if (!gCheatsDisableClearanceChecks && (RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8) & ELEMENT_IS_UNDERWATER)) {
gFootpathGroundFlags = gMapGroundFlags;
if (!gCheatsDisableClearanceChecks && (gMapGroundFlags & ELEMENT_IS_UNDERWATER)) {
gGameCommandErrorText = STR_CANT_BUILD_THIS_UNDERWATER;
return MONEY32_UNDEFINED;
}
@ -588,7 +589,11 @@ money32 footpath_provisional_set(int type, int x, int y, int z, int slope)
gFootpathProvisionalPosition.z = z & 0xFF;
gFootpathProvisionalFlags |= PROVISIONAL_PATH_FLAG_1;
viewport_set_visibility(RCT2_GLOBAL(0x00F3EFA4, uint8) & 2 ? 1 : 3);
if (gFootpathGroundFlags & ELEMENT_IS_UNDERGROUND) {
viewport_set_visibility(1);
} else {
viewport_set_visibility(3);
}
}
return cost;

View File

@ -54,6 +54,7 @@ extern uint8 gFootpathConstructDirection;
extern uint8 gFootpathConstructSlope;
extern uint8 gFootpathConstructValidDirections;
extern money32 gFootpathPrice;
extern uint8 gFootpathGroundFlags;
extern const rct_xy16 word_981D6C[4];

View File

@ -59,6 +59,8 @@ rct_xy16 gMapSelectPositionB;
rct_xyz16 gMapSelectArrowPosition;
uint8 gMapSelectArrowDirection;
uint8 gMapGroundFlags;
rct_map_element *gMapElements = (rct_map_element*)RCT2_ADDRESS_MAP_ELEMENTS;
rct_map_element **gMapElementTilePointers = (rct_map_element**)RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS;
rct_xy16 *gMapSelectionTiles = (rct_xy16*)0x009DE596;
@ -3033,7 +3035,7 @@ void game_command_place_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi
}
if(gCheatsDisableClearanceChecks || map_can_construct_with_clear_at(x, y, zLow, zHigh, &map_place_scenery_clear_func, bl, flags, RCT2_ADDRESS(0x00F64F26, money32))){
RCT2_GLOBAL(0x00F64F14, uint8) = RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8) & 0x3;
gSceneryGroundFlags = gMapGroundFlags & (ELEMENT_IS_1 | ELEMENT_IS_UNDERGROUND);
if(flags & GAME_COMMAND_FLAG_APPLY){
if (RCT2_GLOBAL(0x009A8C28, uint8) == 1 && !(flags & GAME_COMMAND_FLAG_GHOST)) {
rct_xyz16 coord;
@ -3206,7 +3208,7 @@ static bool map_place_fence_check_obstruction(rct_scenery_entry *wall, int x, in
rct_large_scenery_tile *tile;
RCT2_GLOBAL(0x0141F725, uint8) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8) = 1;
gMapGroundFlags = ELEMENT_IS_1;
if (map_is_location_at_edge(x, y)) {
gGameCommandErrorText = STR_OFF_EDGE_OF_MAP;
return false;
@ -3556,7 +3558,7 @@ void game_command_place_large_scenery(int* eax, int* ebx, int* ecx, int* edx, in
gCommandPosition.x = x + 16;
gCommandPosition.y = y + 16;
gCommandPosition.z = base_height;
RCT2_GLOBAL(0x00F64F14, uint8) = 0;
gSceneryGroundFlags = 0;
uint8 banner_id = 0xFF;
// Supports cost
@ -3686,20 +3688,20 @@ void game_command_place_large_scenery(int* eax, int* ebx, int* ecx, int* edx, in
return;
}
if ((RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8) & ELEMENT_IS_UNDERWATER) || (RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8) & ELEMENT_IS_UNDERGROUND)) {
if ((gMapGroundFlags & ELEMENT_IS_UNDERWATER) || (gMapGroundFlags & ELEMENT_IS_UNDERGROUND)) {
*ebx = MONEY32_UNDEFINED;
return;
}
int b = RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8) & 0x3;
int b = gMapGroundFlags & (ELEMENT_IS_1 | ELEMENT_IS_UNDERGROUND);
if (!gCheatsDisableClearanceChecks) {
if (RCT2_GLOBAL(0x00F64F14, uint8) && !(RCT2_GLOBAL(0x00F64F14, uint8) & b)) {
if (gSceneryGroundFlags && !(gSceneryGroundFlags & b)) {
gGameCommandErrorText = STR_CANT_BUILD_PARTLY_ABOVE_AND_PARTLY_BELOW_GROUND;
*ebx = MONEY32_UNDEFINED;
return;
}
}
RCT2_GLOBAL(0x00F64F14, uint8) = b;
gSceneryGroundFlags = b;
if (curTile.x >= gMapSizeUnits || curTile.y >= gMapSizeUnits) {
gGameCommandErrorText = STR_OFF_EDGE_OF_MAP;
@ -4094,7 +4096,7 @@ static void map_obstruction_set_error_text(rct_map_element *mapElement)
*/
int map_can_construct_with_clear_at(int x, int y, int zLow, int zHigh, CLEAR_FUNC *clearFunc, uint8 bl, uint8 flags, money32 *price)
{
RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8) = 1;
gMapGroundFlags = ELEMENT_IS_1;
if (x >= gMapSizeUnits || y >= gMapSizeUnits || x < 32 || y < 32) {
gGameCommandErrorText = STR_OFF_EDGE_OF_MAP;
return false;
@ -4111,7 +4113,7 @@ int map_can_construct_with_clear_at(int x, int y, int zLow, int zHigh, CLEAR_FUN
}
int water_height = ((map_element->properties.surface.terrain & MAP_ELEMENT_WATER_HEIGHT_MASK) * 2);
if (water_height && water_height > zLow && map_element->base_height < zHigh) {
RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8) |= ELEMENT_IS_UNDERWATER;
gMapGroundFlags |= ELEMENT_IS_UNDERWATER;
if (water_height < zHigh) {
goto loc_68BAE6;
}
@ -4129,8 +4131,8 @@ int map_can_construct_with_clear_at(int x, int y, int zLow, int zHigh, CLEAR_FUN
if ((bl & 0xF0) != 0xF0) {
if (map_element->base_height >= zHigh) {
// loc_68BA81
RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8) |= ELEMENT_IS_UNDERGROUND;
RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8) &= 0xFE;
gMapGroundFlags |= ELEMENT_IS_UNDERGROUND;
gMapGroundFlags &= ~ELEMENT_IS_1;
} else {
int al = map_element->base_height;
int ah = al;

View File

@ -204,6 +204,7 @@ enum {
};
enum {
ELEMENT_IS_1 = 1 << 0,
ELEMENT_IS_UNDERGROUND = 1 << 1,
ELEMENT_IS_UNDERWATER = 1 << 2,
};
@ -307,6 +308,8 @@ extern rct_xy16 gMapSelectPositionB;
extern rct_xyz16 gMapSelectArrowPosition;
extern uint8 gMapSelectArrowDirection;
extern uint8 gMapGroundFlags;
extern rct_map_element *gMapElements;
extern rct_map_element **gMapElementTilePointers;

View File

@ -58,6 +58,8 @@ sint16 gSceneryShiftPressZOffset;
sint16 gSceneryCtrlPressed;
sint16 gSceneryCtrlPressZ;
uint8 gSceneryGroundFlags;
void scenery_increase_age(int x, int y, rct_map_element *mapElement);
void scenery_update_tile(int x, int y)

View File

@ -198,6 +198,8 @@ extern sint16 gSceneryShiftPressZOffset;
extern sint16 gSceneryCtrlPressed;
extern sint16 gSceneryCtrlPressZ;
extern uint8 gSceneryGroundFlags;
extern sint16 window_scenery_tab_entries[20][SCENERY_ENTRIES_BY_TAB + 1];
void init_scenery();