Merge pull request #10922 from Gymnasiast/cleanup-scenery

Cleanup scenery
This commit is contained in:
Michael Steenbeek 2020-03-18 18:44:27 +01:00 committed by GitHub
commit ae6e53153b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 441 additions and 368 deletions

View File

@ -31,6 +31,7 @@ constexpr int32_t WINDOW_SCENERY_HEIGHT = 180;
constexpr int32_t SCENERY_BUTTON_WIDTH = 66;
constexpr int32_t SCENERY_BUTTON_HEIGHT = 80;
constexpr int32_t SCENERY_WINDOW_TABS = MAX_SCENERY_GROUP_OBJECTS + 1; // The + 1 is for the 'Miscellaneous' tab
constexpr uint16_t SCENERY_ENTRIES_PER_TAB = 1024;
// clang-format off
enum {
@ -56,7 +57,7 @@ enum {
WINDOW_SCENERY_TAB_20
};
uint16_t gWindowSceneryTabSelections[SCENERY_WINDOW_TABS];
ScenerySelection gWindowSceneryTabSelections[SCENERY_WINDOW_TABS];
uint8_t gWindowSceneryActiveTabIndex;
uint8_t gWindowSceneryPaintEnabled;
uint8_t gWindowSceneryRotation;
@ -191,25 +192,25 @@ static rct_widget window_scenery_widgets[] = {
void window_scenery_update_scroll(rct_window* w);
// rct2: 0x00F64F2C
static uint16_t window_scenery_tab_entries[SCENERY_WINDOW_TABS][SCENERY_ENTRIES_BY_TAB + 1];
static ScenerySelection window_scenery_tab_entries[SCENERY_WINDOW_TABS][SCENERY_ENTRIES_PER_TAB + 1];
/**
* Was part of 0x006DFA00
* The same code repeated five times for every scenery entry type
*/
static void init_scenery_entry(rct_scenery_entry* sceneryEntry, int32_t index, uint8_t sceneryTabId)
static void init_scenery_entry(rct_scenery_entry* sceneryEntry, const ScenerySelection& selection, uint8_t sceneryTabId)
{
Guard::ArgumentInRange<int32_t>(index, 0, WINDOW_SCENERY_TAB_SELECTION_UNDEFINED);
if (scenery_is_invented(index) || gCheatsIgnoreResearchStatus)
Guard::ArgumentInRange<int32_t>(selection.EntryIndex, 0, WINDOW_SCENERY_TAB_SELECTION_UNDEFINED);
if (scenery_is_invented(selection) || gCheatsIgnoreResearchStatus)
{
if (sceneryTabId != 0xFF)
{
for (int32_t i = 0; i < SCENERY_ENTRIES_BY_TAB; i++)
for (int32_t i = 0; i < SCENERY_ENTRIES_PER_TAB; i++)
{
if (window_scenery_tab_entries[sceneryTabId][i] == WINDOW_SCENERY_TAB_SELECTION_UNDEFINED)
if (window_scenery_tab_entries[sceneryTabId][i].IsUndefined())
{
window_scenery_tab_entries[sceneryTabId][i] = index;
window_scenery_tab_entries[sceneryTabId][i + 1] = WINDOW_SCENERY_TAB_SELECTION_UNDEFINED;
window_scenery_tab_entries[sceneryTabId][i] = selection;
window_scenery_tab_entries[sceneryTabId][i + 1].SetUndefined();
return;
}
}
@ -219,9 +220,9 @@ static void init_scenery_entry(rct_scenery_entry* sceneryEntry, int32_t index, u
{
int32_t counter = 0;
while (window_scenery_tab_entries[i][counter] != WINDOW_SCENERY_TAB_SELECTION_UNDEFINED)
while (!window_scenery_tab_entries[i][counter].IsUndefined())
{
if (window_scenery_tab_entries[i][counter] == index)
if (window_scenery_tab_entries[i][counter] == selection)
{
return;
}
@ -230,12 +231,12 @@ static void init_scenery_entry(rct_scenery_entry* sceneryEntry, int32_t index, u
}
}
for (int32_t i = 0; i < SCENERY_ENTRIES_BY_TAB; i++)
for (int32_t i = 0; i < SCENERY_ENTRIES_PER_TAB; i++)
{
if (window_scenery_tab_entries[SCENERY_WINDOW_TABS - 1][i] == WINDOW_SCENERY_TAB_SELECTION_UNDEFINED)
if (window_scenery_tab_entries[SCENERY_WINDOW_TABS - 1][i].IsUndefined())
{
window_scenery_tab_entries[SCENERY_WINDOW_TABS - 1][i] = index;
window_scenery_tab_entries[SCENERY_WINDOW_TABS - 1][i + 1] = WINDOW_SCENERY_TAB_SELECTION_UNDEFINED;
window_scenery_tab_entries[SCENERY_WINDOW_TABS - 1][i] = selection;
window_scenery_tab_entries[SCENERY_WINDOW_TABS - 1][i + 1].SetUndefined();
break;
}
}
@ -252,7 +253,7 @@ void window_scenery_init()
for (int32_t scenerySetIndex = 0; scenerySetIndex < SCENERY_WINDOW_TABS; scenerySetIndex++)
{
window_scenery_tab_entries[scenerySetIndex][0] = WINDOW_SCENERY_TAB_SELECTION_UNDEFINED;
window_scenery_tab_entries[scenerySetIndex][0].SetUndefined();
if (scenerySetIndex == MAX_SCENERY_GROUP_OBJECTS)
continue;
@ -263,11 +264,11 @@ void window_scenery_init()
int32_t sceneryTabEntryCount = 0;
for (int32_t i = 0; i < sceneryGroupEntry->entry_count; i++)
{
uint16_t sceneryEntryId = sceneryGroupEntry->scenery_entries[i];
if (scenery_is_invented(sceneryEntryId) || gCheatsIgnoreResearchStatus)
auto sceneryEntry = sceneryGroupEntry->scenery_entries[i];
if (scenery_is_invented(sceneryEntry) || gCheatsIgnoreResearchStatus)
{
window_scenery_tab_entries[scenerySetIndex][sceneryTabEntryCount] = sceneryEntryId;
window_scenery_tab_entries[scenerySetIndex][++sceneryTabEntryCount] = WINDOW_SCENERY_TAB_SELECTION_UNDEFINED;
window_scenery_tab_entries[scenerySetIndex][sceneryTabEntryCount] = sceneryEntry;
window_scenery_tab_entries[scenerySetIndex][++sceneryTabEntryCount].SetUndefined();
}
else
{
@ -277,61 +278,53 @@ void window_scenery_init()
}
// small scenery
for (uint16_t sceneryId = SCENERY_SMALL_SCENERY_ID_MIN; sceneryId <= SCENERY_SMALL_SCENERY_ID_MAX; sceneryId++)
for (uint16_t sceneryId = 0; sceneryId < MAX_SMALL_SCENERY_OBJECTS; sceneryId++)
{
rct_scenery_entry* sceneryEntry = get_small_scenery_entry(sceneryId);
if (sceneryEntry == nullptr)
continue;
init_scenery_entry(sceneryEntry, sceneryId, sceneryEntry->small_scenery.scenery_tab_id);
init_scenery_entry(sceneryEntry, { SCENERY_TYPE_SMALL, sceneryId }, sceneryEntry->small_scenery.scenery_tab_id);
}
// large scenery
for (int32_t sceneryId = SCENERY_LARGE_SCENERY_ID_MIN; sceneryId <= SCENERY_LARGE_SCENERY_ID_MAX; sceneryId++)
for (uint16_t sceneryId = 0; sceneryId < MAX_LARGE_SCENERY_OBJECTS; sceneryId++)
{
int32_t largeSceneryIndex = sceneryId - SCENERY_LARGE_SCENERY_ID_MIN;
rct_scenery_entry* sceneryEntry = get_large_scenery_entry(largeSceneryIndex);
rct_scenery_entry* sceneryEntry = get_large_scenery_entry(sceneryId);
if (sceneryEntry == nullptr)
continue;
init_scenery_entry(sceneryEntry, sceneryId, sceneryEntry->large_scenery.scenery_tab_id);
init_scenery_entry(sceneryEntry, { SCENERY_TYPE_LARGE, sceneryId }, sceneryEntry->large_scenery.scenery_tab_id);
}
// walls
for (int32_t sceneryId = SCENERY_WALLS_ID_MIN; sceneryId <= SCENERY_WALLS_ID_MAX; sceneryId++)
for (uint16_t sceneryId = 0; sceneryId < MAX_WALL_SCENERY_OBJECTS; sceneryId++)
{
int32_t wallSceneryIndex = sceneryId - SCENERY_WALLS_ID_MIN;
rct_scenery_entry* sceneryEntry = get_wall_entry(wallSceneryIndex);
rct_scenery_entry* sceneryEntry = get_wall_entry(sceneryId);
if (sceneryEntry == nullptr)
continue;
init_scenery_entry(sceneryEntry, sceneryId, sceneryEntry->wall.scenery_tab_id);
init_scenery_entry(sceneryEntry, { SCENERY_TYPE_WALL, sceneryId }, sceneryEntry->wall.scenery_tab_id);
}
// banners
for (int32_t sceneryId = SCENERY_BANNERS_ID_MIN; sceneryId <= SCENERY_BANNERS_ID_MAX; sceneryId++)
for (uint16_t sceneryId = 0; sceneryId < MAX_BANNER_OBJECTS; sceneryId++)
{
int32_t bannerIndex = sceneryId - SCENERY_BANNERS_ID_MIN;
rct_scenery_entry* sceneryEntry = get_banner_entry(bannerIndex);
rct_scenery_entry* sceneryEntry = get_banner_entry(sceneryId);
if (sceneryEntry == nullptr)
continue;
init_scenery_entry(sceneryEntry, sceneryId, sceneryEntry->banner.scenery_tab_id);
init_scenery_entry(sceneryEntry, { SCENERY_TYPE_BANNER, sceneryId }, sceneryEntry->banner.scenery_tab_id);
}
// path bits
for (int32_t sceneryId = SCENERY_PATH_SCENERY_ID_MIN; sceneryId <= SCENERY_PATH_SCENERY_ID_MAX; sceneryId++)
for (uint16_t sceneryId = 0; sceneryId < MAX_PATH_ADDITION_OBJECTS; sceneryId++)
{
int32_t pathBitIndex = sceneryId - SCENERY_PATH_SCENERY_ID_MIN;
rct_scenery_entry* sceneryEntry = get_footpath_item_entry(pathBitIndex);
rct_scenery_entry* sceneryEntry = get_footpath_item_entry(sceneryId);
if (sceneryEntry == nullptr)
continue;
init_scenery_entry(sceneryEntry, sceneryId, sceneryEntry->path_bit.scenery_tab_id);
init_scenery_entry(sceneryEntry, { SCENERY_TYPE_PATH_ITEM, sceneryId }, sceneryEntry->path_bit.scenery_tab_id);
}
for (rct_widgetindex widgetIndex = WIDX_SCENERY_TAB_1; widgetIndex < WIDX_SCENERY_LIST; widgetIndex++)
@ -385,7 +378,7 @@ void window_scenery_init()
if (left != 3 || tabIndex != SCENERY_WINDOW_TABS - 1)
{
if (window_scenery_tab_entries[tabIndex][0] == WINDOW_SCENERY_TAB_SELECTION_UNDEFINED)
if (window_scenery_tab_entries[tabIndex][0].IsUndefined())
continue;
if (enabledScenerySets[tabIndex])
@ -419,11 +412,11 @@ void window_scenery_set_default_placement_configuration()
window_scenery_init();
for (int32_t i = 0; i < SCENERY_WINDOW_TABS; i++)
gWindowSceneryTabSelections[i] = WINDOW_SCENERY_TAB_SELECTION_UNDEFINED;
gWindowSceneryTabSelections[i] = ScenerySelection::CreateUndefined();
for (int32_t i = 0; i < SCENERY_WINDOW_TABS; i++)
{
if (window_scenery_tab_entries[i][0] != WINDOW_SCENERY_TAB_SELECTION_UNDEFINED)
if (!window_scenery_tab_entries[i][0].IsUndefined())
{
gWindowSceneryActiveTabIndex = i;
return;
@ -477,7 +470,7 @@ rct_window* window_scenery_open()
gWindowSceneryRotation = 3;
gSceneryCtrlPressed = false;
gSceneryShiftPressed = false;
window->scenery.selected_scenery_id = WINDOW_SCENERY_TAB_SELECTION_UNDEFINED;
window->scenery.SelectedScenery = ScenerySelection::CreateUndefined();
window->scenery.hover_counter = 0;
window_push_others_below(window);
gSceneryGhostType = 0;
@ -522,22 +515,22 @@ struct scenery_item
{
int32_t allRows;
int32_t selected_item;
uint16_t sceneryId;
ScenerySelection scenerySelection;
};
static scenery_item window_scenery_count_rows_with_selected_item(int32_t tabIndex)
{
scenery_item sceneryItem = { 0, 0, WINDOW_SCENERY_TAB_SELECTION_UNDEFINED };
scenery_item sceneryItem = { 0, 0, ScenerySelection::CreateUndefined() };
int32_t totalItems = 0;
uint16_t id = 0;
uint16_t sceneryId = gWindowSceneryTabSelections[tabIndex];
ScenerySelection currentEntry = { 0, 0 };
ScenerySelection scenerySelection = gWindowSceneryTabSelections[tabIndex];
while ((id = window_scenery_tab_entries[tabIndex][totalItems]) != WINDOW_SCENERY_TAB_SELECTION_UNDEFINED)
while ((currentEntry = window_scenery_tab_entries[tabIndex][totalItems]), !currentEntry.IsUndefined())
{
if (id == sceneryId)
if (currentEntry == scenerySelection)
{
sceneryItem.selected_item = totalItems;
sceneryItem.sceneryId = sceneryId;
sceneryItem.scenerySelection = scenerySelection;
}
totalItems++;
}
@ -550,7 +543,7 @@ static int32_t window_scenery_count_rows()
int32_t tabIndex = gWindowSceneryActiveTabIndex;
int32_t totalItems = 0;
while (window_scenery_tab_entries[tabIndex][totalItems] != WINDOW_SCENERY_TAB_SELECTION_UNDEFINED)
while (!window_scenery_tab_entries[tabIndex][totalItems].IsUndefined())
{
totalItems++;
}
@ -632,12 +625,12 @@ void window_scenery_update_scroll(rct_window* w)
int32_t maxTop = std::max(0, w->scrolls[0].v_bottom - listHeight);
int32_t rowSelected = count_rows(sceneryItem.selected_item);
if (sceneryItem.sceneryId == WINDOW_SCENERY_TAB_SELECTION_UNDEFINED)
if (sceneryItem.scenerySelection.IsUndefined())
{
rowSelected = 0;
uint16_t sceneryId = window_scenery_tab_entries[tabIndex][0];
if (sceneryId != WINDOW_SCENERY_TAB_SELECTION_UNDEFINED)
gWindowSceneryTabSelections[tabIndex] = sceneryId;
ScenerySelection scenery = window_scenery_tab_entries[tabIndex][0];
if (!scenery.IsUndefined())
gWindowSceneryTabSelections[tabIndex] = scenery;
}
w->scrolls[0].v_top = window_scenery_rows_height(rowSelected);
@ -748,9 +741,9 @@ static void window_scenery_dropdown(rct_window* w, rct_widgetindex widgetIndex,
*/
static void window_scenery_periodic_update(rct_window* w)
{
if (w->scenery.selected_scenery_id != WINDOW_SCENERY_TAB_SELECTION_UNDEFINED)
if (!w->scenery.SelectedScenery.IsUndefined())
{
w->scenery.selected_scenery_id = WINDOW_SCENERY_TAB_SELECTION_UNDEFINED;
w->scenery.SelectedScenery = ScenerySelection::CreateUndefined();
}
}
@ -822,38 +815,38 @@ static void window_scenery_update(rct_window* w)
gCurrentToolId = TOOL_CROSSHAIR;
}
else if (gWindowSceneryPaintEnabled == 1)
{ // the repaint scenery tool is active
{
gCurrentToolId = TOOL_PAINT_DOWN;
}
else
{
uint16_t tabIndex = gWindowSceneryActiveTabIndex;
int16_t tabSelectedSceneryId = gWindowSceneryTabSelections[tabIndex];
ScenerySelection tabSelectedScenery = gWindowSceneryTabSelections[tabIndex];
if (tabSelectedSceneryId != -1)
if (!tabSelectedScenery.IsUndefined())
{
if (tabSelectedSceneryId >= SCENERY_BANNERS_ID_MIN)
{ // banner
if (tabSelectedScenery.SceneryType == SCENERY_TYPE_BANNER)
{
gCurrentToolId = TOOL_ENTRANCE_DOWN;
}
else if (tabSelectedSceneryId >= SCENERY_LARGE_SCENERY_ID_MIN)
{ // large scenery
else if (tabSelectedScenery.SceneryType == SCENERY_TYPE_LARGE)
{
gCurrentToolId = static_cast<TOOL_IDX>(
get_large_scenery_entry(tabSelectedSceneryId - SCENERY_LARGE_SCENERY_ID_MIN)->large_scenery.tool_id);
get_large_scenery_entry(tabSelectedScenery.EntryIndex)->large_scenery.tool_id);
}
else if (tabSelectedSceneryId >= SCENERY_WALLS_ID_MIN)
{ // wall
gCurrentToolId = static_cast<TOOL_IDX>(
get_wall_entry(tabSelectedSceneryId - SCENERY_WALLS_ID_MIN)->wall.tool_id);
else if (tabSelectedScenery.SceneryType == SCENERY_TYPE_WALL)
{
gCurrentToolId = static_cast<TOOL_IDX>(get_wall_entry(tabSelectedScenery.EntryIndex)->wall.tool_id);
}
else if (tabSelectedSceneryId >= SCENERY_PATH_SCENERY_ID_MIN)
else if (tabSelectedScenery.SceneryType == SCENERY_TYPE_PATH_ITEM)
{ // path bit
gCurrentToolId = static_cast<TOOL_IDX>(
get_footpath_item_entry(tabSelectedSceneryId - SCENERY_PATH_SCENERY_ID_MIN)->path_bit.tool_id);
get_footpath_item_entry(tabSelectedScenery.EntryIndex)->path_bit.tool_id);
}
else
{ // small scenery
gCurrentToolId = static_cast<TOOL_IDX>(get_small_scenery_entry(tabSelectedSceneryId)->small_scenery.tool_id);
gCurrentToolId = static_cast<TOOL_IDX>(
get_small_scenery_entry(tabSelectedScenery.EntryIndex)->small_scenery.tool_id);
}
}
}
@ -869,23 +862,23 @@ void window_scenery_scrollgetsize(rct_window* w, int32_t scrollIndex, int32_t* w
*height = window_scenery_rows_height(rows);
}
static uint16_t get_scenery_id_by_cursor_pos(const ScreenCoordsXY& screenCoords)
static ScenerySelection get_scenery_id_by_cursor_pos(const ScreenCoordsXY& screenCoords)
{
int32_t tabSceneryIndex = screenCoords.x / SCENERY_BUTTON_WIDTH + (screenCoords.y / SCENERY_BUTTON_HEIGHT) * 9;
uint8_t tabIndex = gWindowSceneryActiveTabIndex;
int32_t itemCounter = 0;
uint16_t sceneryId = 0;
ScenerySelection scenery = ScenerySelection::CreateUndefined();
while (itemCounter <= tabSceneryIndex)
{
sceneryId = window_scenery_tab_entries[tabIndex][itemCounter];
if (sceneryId == WINDOW_SCENERY_TAB_SELECTION_UNDEFINED)
return WINDOW_SCENERY_TAB_SELECTION_UNDEFINED;
scenery = window_scenery_tab_entries[tabIndex][itemCounter];
if (scenery.IsUndefined())
return ScenerySelection::CreateUndefined();
itemCounter++;
}
return sceneryId;
return scenery;
}
/**
@ -894,12 +887,12 @@ static uint16_t get_scenery_id_by_cursor_pos(const ScreenCoordsXY& screenCoords)
*/
void window_scenery_scrollmousedown(rct_window* w, int32_t scrollIndex, const ScreenCoordsXY& screenCoords)
{
uint16_t sceneryId = get_scenery_id_by_cursor_pos(screenCoords);
if (sceneryId == WINDOW_SCENERY_TAB_SELECTION_UNDEFINED)
ScenerySelection scenery = get_scenery_id_by_cursor_pos(screenCoords);
if (scenery.IsUndefined())
return;
uint8_t tabIndex = gWindowSceneryActiveTabIndex;
gWindowSceneryTabSelections[tabIndex] = sceneryId;
gWindowSceneryTabSelections[tabIndex] = scenery;
gWindowSceneryPaintEnabled &= 0xFE;
gWindowSceneryEyedropperEnabled = false;
@ -915,10 +908,10 @@ void window_scenery_scrollmousedown(rct_window* w, int32_t scrollIndex, const Sc
*/
void window_scenery_scrollmouseover(rct_window* w, int32_t scrollIndex, const ScreenCoordsXY& screenCoords)
{
uint16_t sceneryId = get_scenery_id_by_cursor_pos(screenCoords);
if (sceneryId != WINDOW_SCENERY_TAB_SELECTION_UNDEFINED)
ScenerySelection scenery = get_scenery_id_by_cursor_pos(screenCoords);
if (!scenery.IsUndefined())
{
w->scenery.selected_scenery_id = sceneryId;
w->scenery.SelectedScenery = scenery;
w->Invalidate();
}
}
@ -995,23 +988,23 @@ void window_scenery_invalidate(rct_window* w)
window_scenery_widgets[WIDX_SCENERY_EYEDROPPER_BUTTON].type = WWT_FLATBTN;
}
int16_t tabSelectedSceneryId = gWindowSceneryTabSelections[tabIndex];
if (tabSelectedSceneryId != -1)
ScenerySelection tabSelectedScenery = gWindowSceneryTabSelections[tabIndex];
if (!tabSelectedScenery.IsUndefined())
{
if (tabSelectedSceneryId <= SCENERY_SMALL_SCENERY_ID_MAX)
if (tabSelectedScenery.SceneryType == SCENERY_TYPE_SMALL)
{
if (!(gWindowSceneryPaintEnabled & 1))
{
window_scenery_widgets[WIDX_SCENERY_BUILD_CLUSTER_BUTTON].type = WWT_FLATBTN;
}
rct_scenery_entry* sceneryEntry = get_small_scenery_entry(tabSelectedSceneryId);
rct_scenery_entry* sceneryEntry = get_small_scenery_entry(tabSelectedScenery.EntryIndex);
if (scenery_small_entry_has_flag(sceneryEntry, SMALL_SCENERY_FLAG_ROTATABLE))
{
window_scenery_widgets[WIDX_SCENERY_ROTATE_OBJECTS_BUTTON].type = WWT_FLATBTN;
}
}
else if (tabSelectedSceneryId >= SCENERY_LARGE_SCENERY_ID_MIN)
else if (tabSelectedScenery.SceneryType >= SCENERY_TYPE_LARGE)
{
window_scenery_widgets[WIDX_SCENERY_ROTATE_OBJECTS_BUTTON].type = WWT_FLATBTN;
}
@ -1036,30 +1029,30 @@ void window_scenery_invalidate(rct_window* w)
window_scenery_widgets[WIDX_SCENERY_TERTIARY_COLOUR_BUTTON].type = WWT_COLOURBTN;
window_scenery_widgets[WIDX_SCENERY_ROTATE_OBJECTS_BUTTON].type = WWT_EMPTY;
}
else if (tabSelectedSceneryId != -1)
else if (!tabSelectedScenery.IsUndefined())
{
rct_scenery_entry* sceneryEntry = nullptr;
if (tabSelectedSceneryId >= SCENERY_BANNERS_ID_MIN)
if (tabSelectedScenery.SceneryType == SCENERY_TYPE_BANNER)
{
sceneryEntry = get_banner_entry(tabSelectedSceneryId - SCENERY_BANNERS_ID_MIN);
sceneryEntry = get_banner_entry(tabSelectedScenery.EntryIndex);
if (sceneryEntry->banner.flags & BANNER_ENTRY_FLAG_HAS_PRIMARY_COLOUR)
{
window_scenery_widgets[WIDX_SCENERY_PRIMARY_COLOUR_BUTTON].type = WWT_COLOURBTN;
}
}
else if (tabSelectedSceneryId >= SCENERY_LARGE_SCENERY_ID_MIN)
else if (tabSelectedScenery.SceneryType == SCENERY_TYPE_LARGE)
{
sceneryEntry = get_large_scenery_entry(tabSelectedSceneryId - SCENERY_LARGE_SCENERY_ID_MIN);
sceneryEntry = get_large_scenery_entry(tabSelectedScenery.EntryIndex);
if (sceneryEntry->large_scenery.flags & LARGE_SCENERY_FLAG_HAS_PRIMARY_COLOUR)
window_scenery_widgets[WIDX_SCENERY_PRIMARY_COLOUR_BUTTON].type = WWT_COLOURBTN;
if (sceneryEntry->large_scenery.flags & LARGE_SCENERY_FLAG_HAS_SECONDARY_COLOUR)
window_scenery_widgets[WIDX_SCENERY_SECONDARY_COLOUR_BUTTON].type = WWT_COLOURBTN;
}
else if (tabSelectedSceneryId >= SCENERY_WALLS_ID_MIN)
else if (tabSelectedScenery.SceneryType == SCENERY_TYPE_WALL)
{
sceneryEntry = get_wall_entry(tabSelectedSceneryId - SCENERY_WALLS_ID_MIN);
sceneryEntry = get_wall_entry(tabSelectedScenery.EntryIndex);
if (sceneryEntry->wall.flags & (WALL_SCENERY_HAS_PRIMARY_COLOUR | WALL_SCENERY_HAS_GLASS))
{
window_scenery_widgets[WIDX_SCENERY_PRIMARY_COLOUR_BUTTON].type = WWT_COLOURBTN;
@ -1075,9 +1068,9 @@ void window_scenery_invalidate(rct_window* w)
}
}
}
else if (tabSelectedSceneryId <= SCENERY_SMALL_SCENERY_ID_MAX)
else if (tabSelectedScenery.SceneryType == SCENERY_TYPE_SMALL)
{
sceneryEntry = get_small_scenery_entry(tabSelectedSceneryId);
sceneryEntry = get_small_scenery_entry(tabSelectedScenery.EntryIndex);
if (scenery_small_entry_has_flag(
sceneryEntry, SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR | SMALL_SCENERY_FLAG_HAS_GLASS))
@ -1133,50 +1126,48 @@ void window_scenery_paint(rct_window* w, rct_drawpixelinfo* dpi)
dpi, imageId, w->windowPos.x + window_scenery_widgets[selectedWidgetId].left,
w->windowPos.y + window_scenery_widgets[selectedWidgetId].top, selectedWidgetId);
uint16_t selectedSceneryEntryId = w->scenery.selected_scenery_id;
if (selectedSceneryEntryId == WINDOW_SCENERY_TAB_SELECTION_UNDEFINED)
ScenerySelection selectedSceneryEntry = w->scenery.SelectedScenery;
if (selectedSceneryEntry.IsUndefined())
{
if (gWindowSceneryPaintEnabled & 1) // repaint coloured scenery tool is on
return;
if (gWindowSceneryEyedropperEnabled)
return;
selectedSceneryEntryId = gWindowSceneryTabSelections[tabIndex];
selectedSceneryEntry = gWindowSceneryTabSelections[tabIndex];
if (selectedSceneryEntryId == WINDOW_SCENERY_TAB_SELECTION_UNDEFINED)
if (selectedSceneryEntry.IsUndefined())
return;
}
uint32_t price = 0;
rct_scenery_entry* sceneryEntry = nullptr;
if (selectedSceneryEntryId >= SCENERY_BANNERS_ID_MIN)
switch (selectedSceneryEntry.SceneryType)
{
sceneryEntry = get_banner_entry(selectedSceneryEntryId - SCENERY_BANNERS_ID_MIN);
price = sceneryEntry->banner.price;
}
else if (selectedSceneryEntryId >= SCENERY_LARGE_SCENERY_ID_MIN)
{
sceneryEntry = get_large_scenery_entry(selectedSceneryEntryId - SCENERY_LARGE_SCENERY_ID_MIN);
price = sceneryEntry->large_scenery.price * 10;
}
else if (selectedSceneryEntryId >= SCENERY_WALLS_ID_MIN)
{
sceneryEntry = get_wall_entry(selectedSceneryEntryId - SCENERY_WALLS_ID_MIN);
price = sceneryEntry->wall.price;
}
else if (selectedSceneryEntryId >= SCENERY_PATH_SCENERY_ID_MIN)
{
sceneryEntry = get_footpath_item_entry(selectedSceneryEntryId - SCENERY_PATH_SCENERY_ID_MIN);
price = sceneryEntry->path_bit.price;
}
else
{
sceneryEntry = get_small_scenery_entry(selectedSceneryEntryId);
price = sceneryEntry->small_scenery.price * 10;
case SCENERY_TYPE_SMALL:
sceneryEntry = get_small_scenery_entry(selectedSceneryEntry.EntryIndex);
price = sceneryEntry->small_scenery.price * 10;
break;
case SCENERY_TYPE_PATH_ITEM:
sceneryEntry = get_footpath_item_entry(selectedSceneryEntry.EntryIndex);
price = sceneryEntry->path_bit.price;
break;
case SCENERY_TYPE_WALL:
sceneryEntry = get_wall_entry(selectedSceneryEntry.EntryIndex);
price = sceneryEntry->wall.price;
break;
case SCENERY_TYPE_LARGE:
sceneryEntry = get_large_scenery_entry(selectedSceneryEntry.EntryIndex);
price = sceneryEntry->large_scenery.price * 10;
break;
case SCENERY_TYPE_BANNER:
sceneryEntry = get_banner_entry(selectedSceneryEntry.EntryIndex);
price = sceneryEntry->banner.price;
break;
}
if (w->scenery.selected_scenery_id == WINDOW_SCENERY_TAB_SELECTION_UNDEFINED && gSceneryPlaceCost != MONEY32_UNDEFINED)
if (w->scenery.SelectedScenery.IsUndefined() && gSceneryPlaceCost != MONEY32_UNDEFINED)
{
price = gSceneryPlaceCost;
}
@ -1208,17 +1199,17 @@ void window_scenery_scrollpaint(rct_window* w, rct_drawpixelinfo* dpi, int32_t s
uint8_t tabIndex = gWindowSceneryActiveTabIndex;
int32_t sceneryTabItemIndex = 0;
uint16_t currentSceneryGlobalId = WINDOW_SCENERY_TAB_SELECTION_UNDEFINED;
ScenerySelection currentSceneryGlobal = ScenerySelection::CreateUndefined();
int16_t left = 0, top = 0;
while ((currentSceneryGlobalId = window_scenery_tab_entries[tabIndex][sceneryTabItemIndex])
!= WINDOW_SCENERY_TAB_SELECTION_UNDEFINED)
while ((currentSceneryGlobal = window_scenery_tab_entries[tabIndex][sceneryTabItemIndex]),
!currentSceneryGlobal.IsUndefined())
{
uint16_t tabSelectedSceneryId = gWindowSceneryTabSelections[tabIndex];
ScenerySelection tabSelectedScenery = gWindowSceneryTabSelections[tabIndex];
if (gWindowSceneryPaintEnabled == 1 || gWindowSceneryEyedropperEnabled)
{
if (w->scenery.selected_scenery_id == currentSceneryGlobalId)
if (w->scenery.SelectedScenery == currentSceneryGlobal)
{
gfx_fill_rect_inset(
dpi, left, top, left + SCENERY_BUTTON_WIDTH - 1, top + SCENERY_BUTTON_HEIGHT - 1, w->colours[1],
@ -1227,13 +1218,13 @@ void window_scenery_scrollpaint(rct_window* w, rct_drawpixelinfo* dpi, int32_t s
}
else
{
if (tabSelectedSceneryId == currentSceneryGlobalId)
if (tabSelectedScenery == currentSceneryGlobal)
{
gfx_fill_rect_inset(
dpi, left, top, left + SCENERY_BUTTON_WIDTH - 1, top + SCENERY_BUTTON_HEIGHT - 1, w->colours[1],
(INSET_RECT_FLAG_BORDER_INSET | INSET_RECT_FLAG_FILL_MID_LIGHT));
}
else if (w->scenery.selected_scenery_id == currentSceneryGlobalId)
else if (w->scenery.SelectedScenery == currentSceneryGlobal)
{
gfx_fill_rect_inset(
dpi, left, top, left + SCENERY_BUTTON_WIDTH - 1, top + SCENERY_BUTTON_HEIGHT - 1, w->colours[1],
@ -1245,27 +1236,27 @@ void window_scenery_scrollpaint(rct_window* w, rct_drawpixelinfo* dpi, int32_t s
rct_drawpixelinfo clipdpi;
if (clip_drawpixelinfo(&clipdpi, dpi, left + 1, top + 1, SCENERY_BUTTON_WIDTH - 2, SCENERY_BUTTON_HEIGHT - 2))
{
if (currentSceneryGlobalId >= SCENERY_BANNERS_ID_MIN)
if (currentSceneryGlobal.SceneryType == SCENERY_TYPE_BANNER)
{
sceneryEntry = get_banner_entry(currentSceneryGlobalId - SCENERY_BANNERS_ID_MIN);
sceneryEntry = get_banner_entry(currentSceneryGlobal.EntryIndex);
uint32_t imageId = sceneryEntry->image + gWindowSceneryRotation * 2;
imageId |= (gWindowSceneryPrimaryColour << 19) | IMAGE_TYPE_REMAP;
gfx_draw_sprite(&clipdpi, imageId, 0x21, 0x28, w->colours[1]);
gfx_draw_sprite(&clipdpi, imageId + 1, 0x21, 0x28, w->colours[1]);
}
else if (currentSceneryGlobalId >= SCENERY_LARGE_SCENERY_ID_MIN)
else if (currentSceneryGlobal.SceneryType == SCENERY_TYPE_LARGE)
{
sceneryEntry = get_large_scenery_entry(currentSceneryGlobalId - SCENERY_LARGE_SCENERY_ID_MIN);
sceneryEntry = get_large_scenery_entry(currentSceneryGlobal.EntryIndex);
uint32_t imageId = sceneryEntry->image + gWindowSceneryRotation;
imageId |= (gWindowSceneryPrimaryColour << 19) | IMAGE_TYPE_REMAP;
imageId |= (gWindowScenerySecondaryColour << 24) | IMAGE_TYPE_REMAP_2_PLUS;
gfx_draw_sprite(&clipdpi, imageId, 0x21, 0, w->colours[1]);
}
else if (currentSceneryGlobalId >= SCENERY_WALLS_ID_MIN)
else if (currentSceneryGlobal.SceneryType == SCENERY_TYPE_WALL)
{
sceneryEntry = get_wall_entry(currentSceneryGlobalId - SCENERY_WALLS_ID_MIN);
sceneryEntry = get_wall_entry(currentSceneryGlobal.EntryIndex);
uint32_t imageId = sceneryEntry->image;
uint8_t tertiaryColour = w->colours[1];
uint16_t spriteTop = (sceneryEntry->wall.height * 2) + 0x32;
@ -1305,16 +1296,16 @@ void window_scenery_scrollpaint(rct_window* w, rct_drawpixelinfo* dpi, int32_t s
}
}
}
else if (currentSceneryGlobalId >= SCENERY_PATH_SCENERY_ID_MIN)
else if (currentSceneryGlobal.SceneryType == SCENERY_TYPE_PATH_ITEM)
{
sceneryEntry = get_footpath_item_entry(currentSceneryGlobalId - SCENERY_PATH_SCENERY_ID_MIN);
sceneryEntry = get_footpath_item_entry(currentSceneryGlobal.EntryIndex);
uint32_t imageId = sceneryEntry->image;
gfx_draw_sprite(&clipdpi, imageId, 0x0B, 0x10, w->colours[1]);
}
else
{
sceneryEntry = get_small_scenery_entry(currentSceneryGlobalId);
sceneryEntry = get_small_scenery_entry(currentSceneryGlobal.EntryIndex);
uint32_t imageId = sceneryEntry->image + gWindowSceneryRotation;
if (scenery_small_entry_has_flag(sceneryEntry, SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR))
@ -1363,33 +1354,33 @@ void window_scenery_scrollpaint(rct_window* w, rct_drawpixelinfo* dpi, int32_t s
}
}
static int32_t window_scenery_find_tab_with_scenery_id(int32_t sceneryId)
static int32_t window_scenery_find_tab_with_scenery(const ScenerySelection& scenery)
{
for (int32_t i = 0; i < SCENERY_WINDOW_TABS; i++)
{
for (int32_t j = 0; j < SCENERY_ENTRIES_BY_TAB; j++)
for (int32_t j = 0; j < SCENERY_ENTRIES_PER_TAB; j++)
{
uint16_t entry = window_scenery_tab_entries[i][j];
if (entry == WINDOW_SCENERY_TAB_SELECTION_UNDEFINED)
ScenerySelection entry = window_scenery_tab_entries[i][j];
if (entry.IsUndefined())
break;
if (entry == sceneryId)
if (entry == scenery)
return i;
}
}
return -1;
}
bool window_scenery_set_selected_item(int32_t sceneryId)
bool window_scenery_set_selected_item(const ScenerySelection& scenery)
{
bool result = false;
rct_window* w = window_bring_to_front_by_class(WC_SCENERY);
if (w != nullptr)
{
int32_t tabIndex = window_scenery_find_tab_with_scenery_id(sceneryId);
int32_t tabIndex = window_scenery_find_tab_with_scenery(scenery);
if (tabIndex != -1)
{
gWindowSceneryActiveTabIndex = tabIndex;
gWindowSceneryTabSelections[tabIndex] = sceneryId;
gWindowSceneryTabSelections[tabIndex] = scenery;
audio_play_sound(SoundId::Click1, 0, context_get_width() / 2);
w->scenery.hover_counter = -16;
@ -1406,6 +1397,6 @@ void window_scenery_reset_selected_scenery_items()
{
for (size_t i = 0; i < SCENERY_WINDOW_TABS; i++)
{
gWindowSceneryTabSelections[i] = WINDOW_SCENERY_TAB_SELECTION_UNDEFINED;
gWindowSceneryTabSelections[i].SetUndefined();
}
}

View File

@ -1117,12 +1117,11 @@ static void scenery_eyedropper_tool_down(int16_t x, int16_t y, rct_widgetindex w
case VIEWPORT_INTERACTION_ITEM_SCENERY:
{
SmallSceneryElement* sceneryElement = tileElement->AsSmallScenery();
int32_t entryIndex = sceneryElement->GetEntryIndex();
auto entryIndex = sceneryElement->GetEntryIndex();
rct_scenery_entry* sceneryEntry = get_small_scenery_entry(entryIndex);
if (sceneryEntry != nullptr)
{
int32_t sceneryId = get_scenery_id_from_entry_index(OBJECT_TYPE_SMALL_SCENERY, entryIndex);
if (sceneryId != -1 && window_scenery_set_selected_item(sceneryId))
if (window_scenery_set_selected_item({ SCENERY_TYPE_SMALL, entryIndex }))
{
gWindowSceneryRotation = sceneryElement->GetDirectionWithOffset(get_current_rotation());
gWindowSceneryPrimaryColour = sceneryElement->GetPrimaryColour();
@ -1134,12 +1133,11 @@ static void scenery_eyedropper_tool_down(int16_t x, int16_t y, rct_widgetindex w
}
case VIEWPORT_INTERACTION_ITEM_WALL:
{
int32_t entryIndex = tileElement->AsWall()->GetEntryIndex();
auto entryIndex = tileElement->AsWall()->GetEntryIndex();
rct_scenery_entry* sceneryEntry = get_wall_entry(entryIndex);
if (sceneryEntry != nullptr)
{
int32_t sceneryId = get_scenery_id_from_entry_index(OBJECT_TYPE_WALLS, entryIndex);
if (sceneryId != -1 && window_scenery_set_selected_item(sceneryId))
if (window_scenery_set_selected_item({ SCENERY_TYPE_WALL, entryIndex }))
{
gWindowSceneryPrimaryColour = tileElement->AsWall()->GetPrimaryColour();
gWindowScenerySecondaryColour = tileElement->AsWall()->GetSecondaryColour();
@ -1151,12 +1149,11 @@ static void scenery_eyedropper_tool_down(int16_t x, int16_t y, rct_widgetindex w
}
case VIEWPORT_INTERACTION_ITEM_LARGE_SCENERY:
{
int32_t entryIndex = tileElement->AsLargeScenery()->GetEntryIndex();
auto entryIndex = tileElement->AsLargeScenery()->GetEntryIndex();
rct_scenery_entry* sceneryEntry = get_large_scenery_entry(entryIndex);
if (sceneryEntry != nullptr)
{
int32_t sceneryId = get_scenery_id_from_entry_index(OBJECT_TYPE_LARGE_SCENERY, entryIndex);
if (sceneryId != -1 && window_scenery_set_selected_item(sceneryId))
if (window_scenery_set_selected_item({ SCENERY_TYPE_LARGE, entryIndex }))
{
gWindowSceneryRotation = (get_current_rotation() + tileElement->GetDirection()) & 3;
gWindowSceneryPrimaryColour = tileElement->AsLargeScenery()->GetPrimaryColour();
@ -1174,8 +1171,7 @@ static void scenery_eyedropper_tool_down(int16_t x, int16_t y, rct_widgetindex w
auto sceneryEntry = get_banner_entry(banner->type);
if (sceneryEntry != nullptr)
{
int32_t sceneryId = get_scenery_id_from_entry_index(OBJECT_TYPE_BANNERS, banner->type);
if (sceneryId != -1 && window_scenery_set_selected_item(sceneryId))
if (window_scenery_set_selected_item({ SCENERY_TYPE_BANNER, banner->type }))
{
gWindowSceneryEyedropperEnabled = false;
}
@ -1185,12 +1181,11 @@ static void scenery_eyedropper_tool_down(int16_t x, int16_t y, rct_widgetindex w
}
case VIEWPORT_INTERACTION_ITEM_FOOTPATH_ITEM:
{
int32_t entryIndex = tileElement->AsPath()->GetAdditionEntryIndex();
auto entryIndex = tileElement->AsPath()->GetAdditionEntryIndex();
rct_scenery_entry* sceneryEntry = get_footpath_item_entry(entryIndex);
if (sceneryEntry != nullptr)
{
int32_t sceneryId = get_scenery_id_from_entry_index(OBJECT_TYPE_PATH_BITS, entryIndex);
if (sceneryId != -1 && window_scenery_set_selected_item(sceneryId))
if (window_scenery_set_selected_item({ SCENERY_TYPE_PATH_ITEM, entryIndex }))
{
gWindowSceneryEyedropperEnabled = false;
}
@ -1211,7 +1206,7 @@ static void scenery_eyedropper_tool_down(int16_t x, int16_t y, rct_widgetindex w
* edi : parameter_3
*/
static void sub_6E1F34(
int16_t x, int16_t y, uint16_t selected_scenery, CoordsXY& gridPos, uint32_t* parameter_1, uint32_t* parameter_2,
int16_t x, int16_t y, ScenerySelection selection, CoordsXY& gridPos, uint32_t* parameter_1, uint32_t* parameter_2,
uint32_t* parameter_3)
{
rct_window* w = window_find_by_class(WC_SCENERY);
@ -1222,33 +1217,30 @@ static void sub_6E1F34(
return;
}
// The upper byte of selected_scenery contains the type, the lower byte the index.
uint8_t scenery_type = selected_scenery >> 8;
selected_scenery &= 0xFF;
uint16_t maxPossibleHeight = (std::numeric_limits<decltype(TileElement::base_height)>::max() - 32) << MAX_ZOOM_LEVEL;
bool can_raise_item = false;
if (scenery_type == SCENERY_TYPE_SMALL)
if (selection.SceneryType == SCENERY_TYPE_SMALL)
{
rct_scenery_entry* scenery_entry = get_small_scenery_entry(selected_scenery);
rct_scenery_entry* scenery_entry = get_small_scenery_entry(selection.EntryIndex);
maxPossibleHeight -= scenery_entry->small_scenery.height;
if (scenery_small_entry_has_flag(scenery_entry, SMALL_SCENERY_FLAG_STACKABLE))
{
can_raise_item = true;
}
}
else if (scenery_type == SCENERY_TYPE_WALL)
else if (selection.SceneryType == SCENERY_TYPE_WALL)
{
rct_scenery_entry* scenery_entry = get_wall_entry(selected_scenery);
rct_scenery_entry* scenery_entry = get_wall_entry(selection.EntryIndex);
if (scenery_entry)
{
maxPossibleHeight -= scenery_entry->wall.height;
}
can_raise_item = true;
}
else if (scenery_type == SCENERY_TYPE_LARGE)
else if (selection.SceneryType == SCENERY_TYPE_LARGE)
{
rct_scenery_entry* scenery_entry = get_large_scenery_entry(selected_scenery);
rct_scenery_entry* scenery_entry = get_large_scenery_entry(selection.EntryIndex);
if (scenery_entry)
{
int16_t maxClearZ = 0;
@ -1333,20 +1325,20 @@ static void sub_6E1F34(
}
}
switch (scenery_type)
switch (selection.SceneryType)
{
case SCENERY_TYPE_SMALL:
{
// Small scenery
rct_scenery_entry* scenery = get_small_scenery_entry(selected_scenery);
rct_scenery_entry* scenery = get_small_scenery_entry(selection.EntryIndex);
if (!scenery_small_entry_has_flag(scenery, SMALL_SCENERY_FLAG_FULL_TILE))
{
uint8_t cl = 0;
uint8_t quadrant = 0;
// If CTRL not pressed
if (!gSceneryCtrlPressed)
{
auto gridCoords = screen_get_map_xy_quadrant({ x, y }, &cl);
auto gridCoords = screen_get_map_xy_quadrant({ x, y }, &quadrant);
if (!gridCoords)
{
gridPos.setNull();
@ -1379,7 +1371,7 @@ static void sub_6E1F34(
{
int16_t z = gSceneryCtrlPressZ;
auto mapCoords = screen_get_map_xy_quadrant_with_z({ x, y }, z, &cl);
auto mapCoords = screen_get_map_xy_quadrant_with_z({ x, y }, z, &quadrant);
if (!mapCoords)
{
gridPos.setNull();
@ -1412,8 +1404,8 @@ static void sub_6E1F34(
rotation &= 0x3;
// Also places it in lower but think thats for clobbering
*parameter_1 = selected_scenery << 8;
*parameter_2 = (cl ^ (1 << 1)) | (gWindowSceneryPrimaryColour << 8);
*parameter_1 = selection.EntryIndex << 8;
*parameter_2 = (quadrant ^ (1 << 1)) | (gWindowSceneryPrimaryColour << 8);
*parameter_3 = rotation | (gWindowScenerySecondaryColour << 16);
if (gConfigGeneral.virtual_floor_style != VIRTUAL_FLOOR_STYLE_OFF)
@ -1501,7 +1493,7 @@ static void sub_6E1F34(
rotation &= 0x3;
// Also places it in lower but think thats for clobbering
*parameter_1 = selected_scenery << 8;
*parameter_1 = selection.EntryIndex << 8;
*parameter_2 = 0 | (gWindowSceneryPrimaryColour << 8);
*parameter_3 = rotation | (gWindowScenerySecondaryColour << 16);
break;
@ -1532,7 +1524,7 @@ static void sub_6E1F34(
{
*parameter_2 |= LOCATION_NULL;
}
*parameter_3 = selected_scenery + 1;
*parameter_3 = selection.EntryIndex + 1;
break;
}
case SCENERY_TYPE_WALL:
@ -1599,7 +1591,7 @@ static void sub_6E1F34(
_secondaryColour = gWindowScenerySecondaryColour;
_tertiaryColour = gWindowSceneryTertiaryColour;
// Also places it in lower but think thats for clobbering
*parameter_1 = selected_scenery << 8;
*parameter_1 = selection.EntryIndex << 8;
*parameter_2 = cl | (gWindowSceneryPrimaryColour << 8);
*parameter_3 = 0;
break;
@ -1672,7 +1664,7 @@ static void sub_6E1F34(
*parameter_1 = (rotation << 8);
*parameter_2 = gWindowSceneryPrimaryColour | (gWindowScenerySecondaryColour << 8);
*parameter_3 = selected_scenery;
*parameter_3 = selection.EntryIndex;
break;
}
case SCENERY_TYPE_BANNER:
@ -1709,7 +1701,7 @@ static void sub_6E1F34(
z /= 2;
// Also places it in lower but think thats for clobbering
*parameter_1 = selected_scenery << 8;
*parameter_1 = selection.EntryIndex << 8;
*parameter_2 = z | (rotation << 8);
*parameter_3 = gWindowSceneryPrimaryColour;
break;
@ -1722,6 +1714,64 @@ static void sub_6E1F34(
}
}
static void sub_6E1F34_small_scenery(
const ScreenCoordsXY& screenCoords, uint16_t sceneryIndex, CoordsXY& gridPos, uint8_t* outQuadrant,
colour_t* outPrimaryColour, colour_t* outSecondaryColour)
{
uint32_t parameter1 = 0, parameter2 = 0, parameter3 = 0;
sub_6E1F34(
screenCoords.x, screenCoords.y, { SCENERY_TYPE_SMALL, sceneryIndex }, gridPos, &parameter1, &parameter2, &parameter3);
*outQuadrant = parameter2 & 0xFF;
*outPrimaryColour = (parameter2 >> 8) & 0xFF;
*outSecondaryColour = (parameter3 >> 16) & 0xFF;
}
static void sub_6E1F34_path_item(const ScreenCoordsXY& screenCoords, uint16_t sceneryIndex, CoordsXY& gridPos, int32_t* outZ)
{
uint32_t parameter1 = 0, parameter2 = 0, parameter3 = 0;
sub_6E1F34(
screenCoords.x, screenCoords.y, { SCENERY_TYPE_PATH_ITEM, sceneryIndex }, gridPos, &parameter1, &parameter2,
&parameter3);
*outZ = (parameter2 & 0xFF) * COORDS_Z_STEP;
}
static void sub_6E1F34_wall(
const ScreenCoordsXY& screenCoords, uint16_t sceneryIndex, CoordsXY& gridPos, colour_t* outPrimaryColour, uint8_t* outEdges)
{
uint32_t parameter1 = 0, parameter2 = 0, parameter3 = 0;
sub_6E1F34(
screenCoords.x, screenCoords.y, { SCENERY_TYPE_WALL, sceneryIndex }, gridPos, &parameter1, &parameter2, &parameter3);
*outPrimaryColour = (parameter2 >> 8) & 0xFF;
*outEdges = parameter2 & 0xFF;
}
static void sub_6E1F34_large_scenery(
const ScreenCoordsXY& screenCoords, uint16_t sceneryIndex, CoordsXY& gridPos, colour_t* outPrimaryColour,
colour_t* outSecondaryColour, Direction* outDirection)
{
uint32_t parameter1 = 0, parameter2 = 0, parameter3 = 0;
sub_6E1F34(
screenCoords.x, screenCoords.y, { SCENERY_TYPE_LARGE, sceneryIndex }, gridPos, &parameter1, &parameter2, &parameter3);
*outPrimaryColour = parameter2 & 0xFF;
*outSecondaryColour = (parameter2 >> 8) & 0xFF;
*outDirection = (parameter1 & 0xFF00) >> 8;
}
static void sub_6E1F34_banner(
const ScreenCoordsXY& screenCoords, uint16_t sceneryIndex, CoordsXY& gridPos, int32_t* outZ, Direction* outDirection)
{
uint32_t parameter1 = 0, parameter2 = 0, parameter3 = 0;
sub_6E1F34(
screenCoords.x, screenCoords.y, { SCENERY_TYPE_BANNER, sceneryIndex }, gridPos, &parameter1, &parameter2, &parameter3);
*outDirection = (parameter2 >> 8) & 0xFF;
*outZ = (parameter2 & 0xFF) * COORDS_Z_PER_TINY_Z;
}
/**
*
* rct2: 0x006E2CC6
@ -1740,24 +1790,26 @@ static void window_top_toolbar_scenery_tool_down(int16_t x, int16_t y, rct_windo
return;
}
uint16_t selectedTab = gWindowSceneryTabSelections[gWindowSceneryActiveTabIndex];
uint8_t sceneryType = (selectedTab & 0xFF00) >> 8;
ScenerySelection selectedTab = gWindowSceneryTabSelections[gWindowSceneryActiveTabIndex];
uint8_t sceneryType = selectedTab.SceneryType;
uint16_t selectedScenery = selectedTab.EntryIndex;
if (selectedTab == WINDOW_SCENERY_TAB_SELECTION_UNDEFINED)
if (selectedTab.IsUndefined())
return;
CoordsXY gridPos;
uint32_t parameter_1, parameter_2, parameter_3;
sub_6E1F34(x, y, selectedTab, gridPos, &parameter_1, &parameter_2, &parameter_3);
if (gridPos.isNull())
return;
switch (sceneryType)
{
case SCENERY_TYPE_SMALL:
{
uint8_t quadrant;
colour_t primaryColour;
colour_t secondaryColour;
sub_6E1F34_small_scenery({ x, y }, selectedScenery, gridPos, &quadrant, &primaryColour, &secondaryColour);
if (gridPos.isNull())
return;
int32_t quantity = 1;
bool isCluster = gWindowSceneryScatterEnabled
&& (network_get_mode() != NETWORK_MODE_CLIENT
@ -1785,7 +1837,7 @@ static void window_top_toolbar_scenery_tool_down(int16_t x, int16_t y, rct_windo
for (int32_t q = 0; q < quantity; q++)
{
int32_t zCoordinate = gSceneryPlaceZ;
rct_scenery_entry* scenery = get_small_scenery_entry((parameter_1 >> 8) & 0xFF);
rct_scenery_entry* scenery = get_small_scenery_entry(selectedScenery);
int16_t cur_grid_x = gridPos.x;
int16_t cur_grid_y = gridPos.y;
@ -1794,8 +1846,7 @@ static void window_top_toolbar_scenery_tool_down(int16_t x, int16_t y, rct_windo
{
if (!scenery_small_entry_has_flag(scenery, SMALL_SCENERY_FLAG_FULL_TILE))
{
parameter_2 &= 0xFF00;
parameter_2 |= util_rand() & 3;
quadrant = util_rand() & 3;
}
int16_t grid_x_offset = (util_rand() % gWindowSceneryScatterSize) - (gWindowSceneryScatterSize / 2);
@ -1820,17 +1871,13 @@ static void window_top_toolbar_scenery_tool_down(int16_t x, int16_t y, rct_windo
zAttemptRange = 20;
}
uint8_t quadrant = parameter_2 & 0xFF;
uint8_t primaryColour = (parameter_2 >> 8) & 0xFF;
uint8_t secondaryColour = (parameter_3 >> 16) & 0xFF;
uint8_t type = (parameter_1 >> 8) & 0xFF;
auto success = GA_ERROR::UNKNOWN;
// Try find a valid z coordinate
for (; zAttemptRange != 0; zAttemptRange--)
{
auto smallSceneryPlaceAction = SmallSceneryPlaceAction(
{ cur_grid_x, cur_grid_y, gSceneryPlaceZ, gSceneryPlaceRotation }, quadrant, type, primaryColour,
secondaryColour);
{ cur_grid_x, cur_grid_y, gSceneryPlaceZ, gSceneryPlaceRotation }, quadrant, selectedScenery,
primaryColour, secondaryColour);
auto res = GameActions::Query(&smallSceneryPlaceAction);
success = res->Error;
if (res->Error == GA_ERROR::OK)
@ -1852,8 +1899,8 @@ static void window_top_toolbar_scenery_tool_down(int16_t x, int16_t y, rct_windo
if (success == GA_ERROR::OK || ((q + 1 == quantity) && forceError))
{
auto smallSceneryPlaceAction = SmallSceneryPlaceAction(
{ cur_grid_x, cur_grid_y, gSceneryPlaceZ, gSceneryPlaceRotation }, quadrant, type, primaryColour,
secondaryColour);
{ cur_grid_x, cur_grid_y, gSceneryPlaceZ, gSceneryPlaceRotation }, quadrant, selectedScenery,
primaryColour, secondaryColour);
smallSceneryPlaceAction.SetCallback([=](const GameAction* ga, const GameActionResult* result) {
if (result->Error == GA_ERROR::OK)
@ -1878,9 +1925,12 @@ static void window_top_toolbar_scenery_tool_down(int16_t x, int16_t y, rct_windo
}
case SCENERY_TYPE_PATH_ITEM:
{
auto pathItemType = parameter_3 & 0xFF;
int32_t z = (parameter_2 & 0xFF) * COORDS_Z_STEP;
auto footpathSceneryPlaceAction = FootpathSceneryPlaceAction({ gridPos, z }, pathItemType);
int32_t z;
sub_6E1F34_path_item({ x, y }, selectedScenery, gridPos, &z);
if (gridPos.isNull())
return;
auto footpathSceneryPlaceAction = FootpathSceneryPlaceAction({ gridPos, z }, selectedScenery + 1);
footpathSceneryPlaceAction.SetCallback([](const GameAction* ga, const GameActionResult* result) {
if (result->Error != GA_ERROR::OK)
@ -1894,6 +1944,12 @@ static void window_top_toolbar_scenery_tool_down(int16_t x, int16_t y, rct_windo
}
case SCENERY_TYPE_WALL:
{
colour_t primaryColour;
uint8_t edges;
sub_6E1F34_wall({ x, y }, selectedScenery, gridPos, &primaryColour, &edges);
if (gridPos.isNull())
return;
uint8_t zAttemptRange = 1;
if (gSceneryPlaceZ != 0 && gSceneryShiftPressed)
{
@ -1902,11 +1958,8 @@ static void window_top_toolbar_scenery_tool_down(int16_t x, int16_t y, rct_windo
for (; zAttemptRange != 0; zAttemptRange--)
{
auto primaryColour = (parameter_2 >> 8) & 0xFF;
auto edges = parameter_2 & 0xFF;
auto type = (parameter_1 >> 8) & 0xFF;
auto wallPlaceAction = WallPlaceAction(
type, { gridPos, gSceneryPlaceZ }, edges, primaryColour, _secondaryColour, _tertiaryColour);
selectedScenery, { gridPos, gSceneryPlaceZ }, edges, primaryColour, _secondaryColour, _tertiaryColour);
auto res = GameActions::Query(&wallPlaceAction);
if (res->Error == GA_ERROR::OK)
@ -1925,11 +1978,8 @@ static void window_top_toolbar_scenery_tool_down(int16_t x, int16_t y, rct_windo
}
}
auto primaryColour = (parameter_2 >> 8) & 0xFF;
auto edges = parameter_2 & 0xFF;
auto type = (parameter_1 >> 8) & 0xFF;
auto wallPlaceAction = WallPlaceAction(
type, { gridPos, gSceneryPlaceZ }, edges, primaryColour, _secondaryColour, _tertiaryColour);
selectedScenery, { gridPos, gSceneryPlaceZ }, edges, primaryColour, _secondaryColour, _tertiaryColour);
wallPlaceAction.SetCallback([](const GameAction* ga, const GameActionResult* result) {
if (result->Error == GA_ERROR::OK)
@ -1942,6 +1992,13 @@ static void window_top_toolbar_scenery_tool_down(int16_t x, int16_t y, rct_windo
}
case SCENERY_TYPE_LARGE:
{
colour_t primaryColour;
colour_t secondaryColour;
Direction direction;
sub_6E1F34_large_scenery({ x, y }, selectedScenery, gridPos, &primaryColour, &secondaryColour, &direction);
if (gridPos.isNull())
return;
uint8_t zAttemptRange = 1;
if (gSceneryPlaceZ != 0 && gSceneryShiftPressed)
{
@ -1950,13 +2007,9 @@ static void window_top_toolbar_scenery_tool_down(int16_t x, int16_t y, rct_windo
for (; zAttemptRange != 0; zAttemptRange--)
{
auto primaryColour = parameter_2 & 0xFF;
auto secondaryColour = (parameter_2 >> 8) & 0xFF;
auto largeSceneryType = parameter_3 & 0xFF;
uint8_t direction = (parameter_1 & 0xFF00) >> 8;
CoordsXYZD loc = { gridPos, gSceneryPlaceZ, direction };
auto sceneryPlaceAction = LargeSceneryPlaceAction(loc, largeSceneryType, primaryColour, secondaryColour);
auto sceneryPlaceAction = LargeSceneryPlaceAction(loc, selectedScenery, primaryColour, secondaryColour);
auto res = GameActions::Query(&sceneryPlaceAction);
if (res->Error == GA_ERROR::OK)
@ -1974,13 +2027,10 @@ static void window_top_toolbar_scenery_tool_down(int16_t x, int16_t y, rct_windo
gSceneryPlaceZ += 8;
}
}
auto primaryColour = parameter_2 & 0xFF;
auto secondaryColour = (parameter_2 >> 8) & 0xFF;
auto largeSceneryType = parameter_3 & 0xFF;
uint8_t direction = (parameter_1 & 0xFF00) >> 8;
CoordsXYZD loc = { gridPos, gSceneryPlaceZ, direction };
auto sceneryPlaceAction = LargeSceneryPlaceAction(loc, largeSceneryType, primaryColour, secondaryColour);
auto sceneryPlaceAction = LargeSceneryPlaceAction(loc, selectedScenery, primaryColour, secondaryColour);
sceneryPlaceAction.SetCallback([=](const GameAction* ga, const GameActionResult* result) {
if (result->Error == GA_ERROR::OK)
{
@ -1996,18 +2046,21 @@ static void window_top_toolbar_scenery_tool_down(int16_t x, int16_t y, rct_windo
}
case SCENERY_TYPE_BANNER:
{
uint8_t direction = (parameter_2 >> 8) & 0xFF;
int32_t z = (parameter_2 & 0xFF) * 16;
int32_t z;
Direction direction;
sub_6E1F34_banner({ x, y }, selectedScenery, gridPos, &z, &direction);
if (gridPos.isNull())
return;
CoordsXYZD loc{ gridPos, z, direction };
auto primaryColour = gWindowSceneryPrimaryColour;
auto bannerType = (parameter_1 & 0xFF00) >> 8;
auto bannerIndex = create_new_banner(0);
if (bannerIndex == BANNER_INDEX_NULL)
{
context_show_error(STR_CANT_POSITION_THIS_HERE, STR_TOO_MANY_BANNERS_IN_GAME);
break;
}
auto bannerPlaceAction = BannerPlaceAction(loc, bannerType, bannerIndex, primaryColour);
auto bannerPlaceAction = BannerPlaceAction(loc, selectedScenery, bannerIndex, primaryColour);
bannerPlaceAction.SetCallback([=](const GameAction* ga, const GameActionResult* result) {
if (result->Error == GA_ERROR::OK)
{
@ -2483,34 +2536,34 @@ static void top_toolbar_tool_update_water(int16_t x, int16_t y)
* On success places ghost scenery and returns cost to place proper
*/
static money32 try_place_ghost_scenery(
CoordsXY map_tile, uint32_t parameter_1, uint32_t parameter_2, uint32_t parameter_3, uint16_t selected_tab)
CoordsXY map_tile, uint32_t parameter_1, uint32_t parameter_2, uint32_t parameter_3, uint8_t scenery_type,
uint16_t entryIndex)
{
scenery_remove_ghost_tool_placement();
uint8_t scenery_type = (selected_tab & 0xFF00) >> 8;
money32 cost = 0;
TileElement* tileElement;
switch (scenery_type)
{
case 0:
case SCENERY_TYPE_SMALL:
{
// Small Scenery
// 6e252b
uint8_t quadrant = parameter_2 & 0xFF;
uint8_t primaryColour = (parameter_2 >> 8) & 0xFF;
uint8_t secondaryColour = (parameter_3 >> 16) & 0xFF;
uint8_t type = (parameter_1 >> 8) & 0xFF;
uint8_t rotation = parameter_3 & 0xFF;
auto smallSceneryPlaceAction = SmallSceneryPlaceAction(
{ map_tile.x, map_tile.y, gSceneryPlaceZ, rotation }, quadrant, type, primaryColour, secondaryColour);
{ map_tile.x, map_tile.y, gSceneryPlaceZ, rotation }, quadrant, entryIndex, primaryColour, secondaryColour);
smallSceneryPlaceAction.SetFlags(GAME_COMMAND_FLAG_GHOST | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED);
auto res = GameActions::Execute(&smallSceneryPlaceAction);
if (res->Error != GA_ERROR::OK)
return MONEY32_UNDEFINED;
gSceneryPlaceRotation = (uint16_t)(parameter_3 & 0xFF);
gSceneryPlaceObject = selected_tab;
gSceneryPlaceObject.SceneryType = SCENERY_TYPE_SMALL;
gSceneryPlaceObject.EntryIndex = entryIndex;
tileElement = dynamic_cast<SmallSceneryPlaceActionResult*>(res.get())->tileElement;
gSceneryGhostPosition = { map_tile, tileElement->GetBaseZ() };
@ -2530,13 +2583,12 @@ static money32 try_place_ghost_scenery(
cost = res->Cost;
break;
}
case 1:
case SCENERY_TYPE_PATH_ITEM:
{
// Path Bits
// 6e265b
auto pathItemType = parameter_3 & 0xFF;
int32_t z = (parameter_2 & 0xFF) * COORDS_Z_STEP;
auto footpathSceneryPlaceAction = FootpathSceneryPlaceAction({ map_tile.x, map_tile.y, z }, pathItemType);
auto footpathSceneryPlaceAction = FootpathSceneryPlaceAction({ map_tile.x, map_tile.y, z }, entryIndex + 1);
footpathSceneryPlaceAction.SetFlags(GAME_COMMAND_FLAG_GHOST | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED);
footpathSceneryPlaceAction.SetCallback([=](const GameAction* ga, const GameActionResult* result) {
if (result->Error != GA_ERROR::OK)
@ -2553,15 +2605,15 @@ static money32 try_place_ghost_scenery(
cost = res->Cost;
break;
}
case 2:
case SCENERY_TYPE_WALL:
{
// Walls
// 6e26b0
auto primaryColour = (parameter_2 >> 8) & 0xFF;
auto edges = parameter_2 & 0xFF;
auto type = (parameter_1 >> 8) & 0xFF;
auto wallPlaceAction = WallPlaceAction(
type, { map_tile.x, map_tile.y, gSceneryPlaceZ }, edges, primaryColour, _secondaryColour, _tertiaryColour);
entryIndex, { map_tile.x, map_tile.y, gSceneryPlaceZ }, edges, primaryColour, _secondaryColour,
_tertiaryColour);
wallPlaceAction.SetFlags(
GAME_COMMAND_FLAG_GHOST | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_NO_SPEND);
wallPlaceAction.SetCallback([=](const GameAction* ga, const WallPlaceActionResult* result) {
@ -2580,17 +2632,16 @@ static money32 try_place_ghost_scenery(
cost = res->Cost;
break;
}
case 3:
case SCENERY_TYPE_LARGE:
{
// Large Scenery
// 6e25a7
auto primaryColour = parameter_2 & 0xFF;
auto secondaryColour = (parameter_2 >> 8) & 0xFF;
auto sceneryType = parameter_3 & 0xFF;
uint8_t direction = (parameter_1 & 0xFF00) >> 8;
CoordsXYZD loc = { map_tile.x, map_tile.y, gSceneryPlaceZ, direction };
auto sceneryPlaceAction = LargeSceneryPlaceAction(loc, sceneryType, primaryColour, secondaryColour);
auto sceneryPlaceAction = LargeSceneryPlaceAction(loc, entryIndex, primaryColour, secondaryColour);
sceneryPlaceAction.SetFlags(
GAME_COMMAND_FLAG_GHOST | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_NO_SPEND);
auto res = GameActions::Execute(&sceneryPlaceAction);
@ -2617,22 +2668,21 @@ static money32 try_place_ghost_scenery(
cost = res->Cost;
break;
}
case 4:
case SCENERY_TYPE_BANNER:
{
// Banners
// 6e2612
uint8_t direction = (parameter_2 >> 8) & 0xFF;
int32_t z = (parameter_2 & 0xFF) * 16;
int32_t z = (parameter_2 & 0xFF) * COORDS_Z_PER_TINY_Z;
CoordsXYZD loc{ map_tile.x, map_tile.y, z, direction };
auto primaryColour = gWindowSceneryPrimaryColour;
auto bannerType = (parameter_1 & 0xFF00) >> 8;
auto bannerIndex = create_new_banner(0);
if (bannerIndex == BANNER_INDEX_NULL)
{
// Silently fail as this is just for the ghost
break;
}
auto bannerPlaceAction = BannerPlaceAction(loc, bannerType, bannerIndex, primaryColour);
auto bannerPlaceAction = BannerPlaceAction(loc, entryIndex, bannerIndex, primaryColour);
bannerPlaceAction.SetFlags(
GAME_COMMAND_FLAG_GHOST | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_NO_SPEND);
auto res = GameActions::Execute(&bannerPlaceAction);
@ -2673,20 +2723,20 @@ static void top_toolbar_tool_update_scenery(int16_t x, int16_t y)
if (gWindowSceneryEyedropperEnabled)
return;
int16_t selected_tab = gWindowSceneryTabSelections[gWindowSceneryActiveTabIndex];
ScenerySelection selection = gWindowSceneryTabSelections[gWindowSceneryActiveTabIndex];
if (selected_tab == -1)
if (selection.IsUndefined())
{
scenery_remove_ghost_tool_placement();
return;
}
uint8_t scenery_type = (selected_tab & 0xFF00) >> 8;
uint8_t selected_scenery = selected_tab & 0xFF;
uint8_t sceneryType = selection.SceneryType;
uint16_t selectedScenery = selection.EntryIndex;
CoordsXY mapTile = {};
uint32_t parameter1, parameter2, parameter3;
sub_6E1F34(x, y, selected_tab, mapTile, &parameter1, &parameter2, &parameter3);
sub_6E1F34(x, y, selection, mapTile, &parameter1, &parameter2, &parameter3);
if (mapTile.isNull())
{
@ -2698,7 +2748,7 @@ static void top_toolbar_tool_update_scenery(int16_t x, int16_t y)
uint8_t bl;
money32 cost = 0;
switch (scenery_type)
switch (sceneryType)
{
case SCENERY_TYPE_SMALL:
gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE;
@ -2723,7 +2773,7 @@ static void top_toolbar_tool_update_scenery(int16_t x, int16_t y)
gMapSelectPositionB.y = mapTile.y;
}
scenery = get_small_scenery_entry(selected_scenery);
scenery = get_small_scenery_entry(selectedScenery);
gMapSelectType = MAP_SELECT_TYPE_FULL;
if (!scenery_small_entry_has_flag(scenery, SMALL_SCENERY_FLAG_FULL_TILE) && !gWindowSceneryScatterEnabled)
@ -2735,7 +2785,8 @@ static void top_toolbar_tool_update_scenery(int16_t x, int16_t y)
// If no change in ghost placement
if ((gSceneryGhostType & SCENERY_GHOST_FLAG_0) && mapTile == gSceneryGhostPosition
&& (parameter2 & 0xFF) == _unkF64F0E && gSceneryPlaceZ == _unkF64F0A && gSceneryPlaceObject == selected_tab)
&& (parameter2 & 0xFF) == _unkF64F0E && gSceneryPlaceZ == _unkF64F0A
&& gSceneryPlaceObject.SceneryType == SCENERY_TYPE_SMALL && gSceneryPlaceObject.EntryIndex == selectedScenery)
{
return;
}
@ -2753,7 +2804,7 @@ static void top_toolbar_tool_update_scenery(int16_t x, int16_t y)
for (; bl != 0; bl--)
{
cost = try_place_ghost_scenery(mapTile, parameter1, parameter2, parameter3, selected_tab);
cost = try_place_ghost_scenery(mapTile, parameter1, parameter2, parameter3, sceneryType, selectedScenery);
if (cost != MONEY32_UNDEFINED)
break;
@ -2781,7 +2832,7 @@ static void top_toolbar_tool_update_scenery(int16_t x, int16_t y)
scenery_remove_ghost_tool_placement();
cost = try_place_ghost_scenery(mapTile, parameter1, parameter2, parameter3, selected_tab);
cost = try_place_ghost_scenery(mapTile, parameter1, parameter2, parameter3, sceneryType, selectedScenery);
gSceneryPlaceCost = cost;
break;
@ -2816,7 +2867,7 @@ static void top_toolbar_tool_update_scenery(int16_t x, int16_t y)
cost = 0;
for (; bl != 0; bl--)
{
cost = try_place_ghost_scenery(mapTile, parameter1, parameter2, parameter3, selected_tab);
cost = try_place_ghost_scenery(mapTile, parameter1, parameter2, parameter3, sceneryType, selectedScenery);
if (cost != MONEY32_UNDEFINED)
break;
@ -2827,7 +2878,7 @@ static void top_toolbar_tool_update_scenery(int16_t x, int16_t y)
break;
case SCENERY_TYPE_LARGE:
{
scenery = get_large_scenery_entry(selected_scenery);
scenery = get_large_scenery_entry(selectedScenery);
gMapSelectionTiles.clear();
for (rct_large_scenery_tile* tile = scenery->large_scenery.tiles; tile->x_offset != (int16_t)(uint16_t)0xFFFF;
@ -2847,14 +2898,15 @@ static void top_toolbar_tool_update_scenery(int16_t x, int16_t y)
// If no change in ghost placement
if ((gSceneryGhostType & SCENERY_GHOST_FLAG_3) && mapTile == gSceneryGhostPosition && gSceneryPlaceZ == _unkF64F0A
&& (int16_t)(parameter3 & 0xFFFF) == gSceneryPlaceObject)
&& gSceneryPlaceObject.SceneryType == SCENERY_TYPE_LARGE && gSceneryPlaceObject.EntryIndex == selectedScenery)
{
return;
}
scenery_remove_ghost_tool_placement();
gSceneryPlaceObject = (parameter3 & 0xFFFF);
gSceneryPlaceObject.SceneryType = SCENERY_TYPE_LARGE;
gSceneryPlaceObject.EntryIndex = selectedScenery;
_unkF64F0A = gSceneryPlaceZ;
bl = 1;
@ -2866,7 +2918,7 @@ static void top_toolbar_tool_update_scenery(int16_t x, int16_t y)
cost = 0;
for (; bl != 0; bl--)
{
cost = try_place_ghost_scenery(mapTile, parameter1, parameter2, parameter3, selected_tab);
cost = try_place_ghost_scenery(mapTile, parameter1, parameter2, parameter3, sceneryType, selectedScenery);
if (cost != MONEY32_UNDEFINED)
break;
@ -2896,7 +2948,7 @@ static void top_toolbar_tool_update_scenery(int16_t x, int16_t y)
scenery_remove_ghost_tool_placement();
cost = try_place_ghost_scenery(mapTile, parameter1, parameter2, parameter3, selected_tab);
cost = try_place_ghost_scenery(mapTile, parameter1, parameter2, parameter3, sceneryType, selectedScenery);
gSceneryPlaceCost = cost;
break;

View File

@ -21,7 +21,7 @@ struct TileElement;
struct Vehicle;
enum class ScatterToolDensity : uint8_t;
extern uint16_t gWindowSceneryTabSelections[];
extern ScenerySelection gWindowSceneryTabSelections[];
extern uint8_t gWindowSceneryActiveTabIndex;
extern bool gWindowSceneryScatterEnabled;
extern uint16_t gWindowSceneryScatterSize;
@ -164,7 +164,7 @@ bool clear_scenery_tool_is_active();
bool water_tool_is_active();
rct_window* window_scenery_open();
bool window_scenery_set_selected_item(int32_t sceneryId);
bool window_scenery_set_selected_item(const ScenerySelection& scenery);
void window_scenery_set_default_placement_configuration();
void window_scenery_init();
void window_scenery_reset_selected_scenery_items();

View File

@ -13,6 +13,7 @@
#include "../common.h"
#include "../ride/RideTypes.h"
#include "../world/Location.hpp"
#include "../world/ScenerySelection.h"
#include <functional>
#include <limits>
@ -243,7 +244,7 @@ struct ride_variables
struct scenery_variables
{
uint16_t selected_scenery_id;
ScenerySelection SelectedScenery;
int16_t hover_counter;
};

View File

@ -61,7 +61,7 @@ uint8_t gResearchUncompletedCategories;
static bool _researchedRideTypes[RIDE_TYPE_COUNT];
static bool _researchedRideEntries[MAX_RIDE_OBJECTS];
static bool _researchedSceneryItems[MAX_RESEARCHED_SCENERY_ITEMS];
static bool _researchedSceneryItems[SCENERY_TYPE_COUNT][UINT16_MAX];
bool gSilentResearch = false;
@ -599,19 +599,21 @@ void ride_entry_set_invented(int32_t rideEntryIndex)
_researchedRideEntries[rideEntryIndex] = true;
}
bool scenery_is_invented(uint16_t sceneryItem)
bool scenery_is_invented(const ScenerySelection& sceneryItem)
{
return _researchedSceneryItems[sceneryItem];
return _researchedSceneryItems[sceneryItem.SceneryType][sceneryItem.EntryIndex];
}
void scenery_set_invented(uint16_t sceneryItem)
void scenery_set_invented(const ScenerySelection& sceneryItem)
{
_researchedSceneryItems[sceneryItem] = true;
assert(sceneryItem.SceneryType < SCENERY_TYPE_COUNT);
_researchedSceneryItems[sceneryItem.SceneryType][sceneryItem.EntryIndex] = true;
}
void scenery_set_not_invented(uint16_t sceneryItem)
void scenery_set_not_invented(const ScenerySelection& sceneryItem)
{
_researchedSceneryItems[sceneryItem] = false;
assert(sceneryItem.SceneryType < SCENERY_TYPE_COUNT);
_researchedSceneryItems[sceneryItem.SceneryType][sceneryItem.EntryIndex] = false;
}
bool scenery_group_is_invented(int32_t sgIndex)
@ -628,8 +630,8 @@ bool scenery_group_is_invented(int32_t sgIndex)
{
for (auto i = 0; i < sgEntry->entry_count; i++)
{
auto sceneryEntryIndex = sgEntry->scenery_entries[i];
if (scenery_is_invented(sceneryEntryIndex))
auto sceneryEntry = sgEntry->scenery_entries[i];
if (scenery_is_invented(sceneryEntry))
{
invented = true;
break;
@ -672,12 +674,18 @@ void set_all_scenery_groups_not_invented()
void set_all_scenery_items_invented()
{
std::fill(std::begin(_researchedSceneryItems), std::end(_researchedSceneryItems), true);
for (auto sceneryType = 0; sceneryType < SCENERY_TYPE_COUNT; sceneryType++)
{
std::fill(std::begin(_researchedSceneryItems[sceneryType]), std::end(_researchedSceneryItems[sceneryType]), true);
}
}
void set_all_scenery_items_not_invented()
{
std::fill(std::begin(_researchedSceneryItems), std::end(_researchedSceneryItems), false);
for (auto sceneryType = 0; sceneryType < SCENERY_TYPE_COUNT; sceneryType++)
{
std::fill(std::begin(_researchedSceneryItems[sceneryType]), std::end(_researchedSceneryItems[sceneryType]), true);
}
}
void set_every_ride_type_invented()

View File

@ -63,8 +63,6 @@ enum
#define RESEARCH_ITEM_NULL 0xFFFFFFFF
#define MAX_RESEARCH_ITEMS 500
#define MAX_RESEARCHED_TRACK_TYPES 128
#define MAX_RESEARCHED_SCENERY_ITEMS 1792
#define RESEARCH_ENTRY_RIDE_MASK 0x10000
@ -129,15 +127,15 @@ void research_insert_scenery_group_entry(uint8_t entryIndex, bool researched);
void ride_type_set_invented(uint32_t rideType);
void ride_entry_set_invented(int32_t rideEntryIndex);
void scenery_set_invented(uint16_t sceneryItem);
void scenery_set_not_invented(uint16_t sceneryItem);
void scenery_set_invented(const ScenerySelection& sceneryItem);
void scenery_set_not_invented(const ScenerySelection& sceneryItem);
bool ride_type_is_invented(uint32_t rideType);
bool ride_entry_is_invented(int32_t rideEntryIndex);
uint64_t get_available_track_pieces_for_ride_type(uint8_t rideType);
bool track_piece_is_available_for_ride_type(uint8_t rideType, int32_t trackType);
bool scenery_group_is_invented(int32_t sgIndex);
void scenery_group_set_invented(int32_t sgIndex);
bool scenery_is_invented(uint16_t sceneryItem);
bool scenery_is_invented(const ScenerySelection& sceneryItem);
void set_all_scenery_items_invented();
void set_all_scenery_items_not_invented();
void set_all_scenery_groups_not_invented();

View File

@ -13,6 +13,7 @@
#include "../core/String.hpp"
#include "../localisation/Language.h"
#include "../localisation/StringIds.h"
#include "../world/Scenery.h"
#include "ObjectLimits.h"
#include <algorithm>
@ -168,6 +169,25 @@ std::string Object::GetName(int32_t language) const
return GetString(language, OBJ_STRING_ID_NAME);
}
std::optional<uint8_t> rct_object_entry::GetSceneryType() const
{
switch (GetType())
{
case OBJECT_TYPE_SMALL_SCENERY:
return SCENERY_TYPE_SMALL;
case OBJECT_TYPE_LARGE_SCENERY:
return SCENERY_TYPE_LARGE;
case OBJECT_TYPE_WALLS:
return SCENERY_TYPE_WALL;
case OBJECT_TYPE_BANNERS:
return SCENERY_TYPE_BANNER;
case OBJECT_TYPE_PATH_BITS:
return SCENERY_TYPE_PATH_ITEM;
default:
return std::nullopt;
}
}
#ifdef __WARN_SUGGEST_FINAL_METHODS__
# pragma GCC diagnostic pop
#endif

View File

@ -13,6 +13,7 @@
#include "ImageTable.h"
#include "StringTable.h"
#include <optional>
#include <string_view>
#include <vector>
@ -110,6 +111,8 @@ struct rct_object_entry
{
return flags & 0x0F;
}
std::optional<uint8_t> GetSceneryType() const;
};
assert_struct_size(rct_object_entry, 0x10);

View File

@ -31,9 +31,9 @@ void SceneryGroupObject::ReadLegacy(IReadObjectContext* context, IStream* stream
stream->Seek(6, STREAM_SEEK_CURRENT);
stream->Seek(0x80 * 2, STREAM_SEEK_CURRENT);
_legacyType.entry_count = stream->ReadValue<uint8_t>();
_legacyType.pad_107 = stream->ReadValue<uint8_t>();
stream->Seek(1, STREAM_SEEK_CURRENT); // pad_107;
_legacyType.priority = stream->ReadValue<uint8_t>();
_legacyType.pad_109 = stream->ReadValue<uint8_t>();
stream->Seek(1, STREAM_SEEK_CURRENT); // pad_109;
_legacyType.entertainer_costumes = stream->ReadValue<uint32_t>();
GetStringTable().Read(context, stream, OBJ_STRING_ID_NAME);
@ -82,33 +82,13 @@ void SceneryGroupObject::UpdateEntryIndexes()
if (ori->LoadedObject == nullptr)
continue;
uint16_t sceneryEntry = objectManager.GetLoadedObjectEntryIndex(ori->LoadedObject);
Guard::Assert(sceneryEntry != UINT8_MAX, GUARD_LINE);
uint16_t entryIndex = objectManager.GetLoadedObjectEntryIndex(ori->LoadedObject);
Guard::Assert(entryIndex != UINT8_MAX, GUARD_LINE);
auto objectType = ori->ObjectEntry.GetType();
switch (objectType)
auto sceneryType = ori->ObjectEntry.GetSceneryType();
if (sceneryType != std::nullopt)
{
case OBJECT_TYPE_SMALL_SCENERY:
break;
case OBJECT_TYPE_PATH_BITS:
sceneryEntry += SCENERY_PATH_SCENERY_ID_MIN;
break;
case OBJECT_TYPE_WALLS:
sceneryEntry += SCENERY_WALLS_ID_MIN;
break;
case OBJECT_TYPE_LARGE_SCENERY:
sceneryEntry += SCENERY_LARGE_SCENERY_ID_MIN;
break;
case OBJECT_TYPE_BANNERS:
sceneryEntry += SCENERY_BANNERS_ID_MIN;
break;
default:
sceneryEntry = UINT16_MAX;
break;
}
if (sceneryEntry != UINT16_MAX)
{
_legacyType.scenery_entries[_legacyType.entry_count] = sceneryEntry;
_legacyType.scenery_entries[_legacyType.entry_count] = { *sceneryType, entryIndex };
_legacyType.entry_count++;
}
}

View File

@ -880,7 +880,9 @@ void S6Exporter::ExportResearchedSceneryItems()
for (uint16_t sceneryEntryIndex = 0; sceneryEntryIndex < RCT2_MAX_RESEARCHED_SCENERY_ITEMS; sceneryEntryIndex++)
{
if (scenery_is_invented(sceneryEntryIndex))
ScenerySelection scenerySelection = { static_cast<uint8_t>((sceneryEntryIndex >> 8) & 0xFF),
static_cast<uint16_t>(sceneryEntryIndex & 0xFF) };
if (scenery_is_invented(scenerySelection))
{
int32_t quadIndex = sceneryEntryIndex >> 5;
int32_t bitIndex = sceneryEntryIndex & 0x1F;

View File

@ -874,7 +874,17 @@ public:
bool invented = (_s6.researched_scenery_items[quadIndex] & ((uint32_t)1 << bitIndex));
if (invented)
scenery_set_invented(sceneryEntryIndex);
{
ScenerySelection scenerySelection = { static_cast<uint8_t>((sceneryEntryIndex >> 8) & 0xFF),
static_cast<uint16_t>(sceneryEntryIndex & 0xFF) };
// SV6 has room for 8 types of scenery, and sometimes scenery of non-existing types 5 and 6 is marked as
// "invented".
if (scenerySelection.SceneryType < SCENERY_TYPE_COUNT)
{
scenery_set_invented(scenerySelection);
}
}
}
}

View File

@ -34,7 +34,7 @@
uint8_t gSceneryQuadrant;
money32 gSceneryPlaceCost;
int16_t gSceneryPlaceObject;
ScenerySelection gSceneryPlaceObject;
int16_t gSceneryPlaceZ;
uint8_t gSceneryPlaceRotation;
@ -167,7 +167,8 @@ void scenery_remove_ghost_tool_placement()
{
gSceneryGhostType &= ~SCENERY_GHOST_FLAG_0;
auto removeSceneryAction = SmallSceneryRemoveAction(gSceneryGhostPosition, gSceneryQuadrant, gSceneryPlaceObject);
auto removeSceneryAction = SmallSceneryRemoveAction(
gSceneryGhostPosition, gSceneryQuadrant, gSceneryPlaceObject.EntryIndex);
removeSceneryAction.SetFlags(
GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_NO_SPEND | GAME_COMMAND_FLAG_GHOST);
removeSceneryAction.Execute();
@ -276,25 +277,6 @@ rct_scenery_group_entry* get_scenery_group_entry(int32_t entryIndex)
return result;
}
int32_t get_scenery_id_from_entry_index(uint8_t objectType, int32_t entryIndex)
{
switch (objectType)
{
case OBJECT_TYPE_SMALL_SCENERY:
return entryIndex + SCENERY_SMALL_SCENERY_ID_MIN;
case OBJECT_TYPE_PATH_BITS:
return entryIndex + SCENERY_PATH_SCENERY_ID_MIN;
case OBJECT_TYPE_WALLS:
return entryIndex + SCENERY_WALLS_ID_MIN;
case OBJECT_TYPE_LARGE_SCENERY:
return entryIndex + SCENERY_LARGE_SCENERY_ID_MIN;
case OBJECT_TYPE_BANNERS:
return entryIndex + SCENERY_BANNERS_ID_MIN;
default:
return -1;
}
}
int32_t wall_entry_get_door_sound(const rct_scenery_entry* wallEntry)
{
return (wallEntry->wall.flags2 & WALL_SCENERY_2_DOOR_SOUND_MASK) >> WALL_SCENERY_2_DOOR_SOUND_SHIFT;

View File

@ -11,24 +11,12 @@
#define _SCENERY_H_
#include "../common.h"
#include "../object/Object.h"
#include "../object/ObjectLimits.h"
#include "../world/Location.hpp"
#include "../world/ScenerySelection.h"
#include "TileElement.h"
#include <limits>
constexpr const uint16_t SCENERY_SMALL_SCENERY_ID_MIN = 0;
constexpr const uint16_t SCENERY_SMALL_SCENERY_ID_MAX = MAX_SMALL_SCENERY_OBJECTS - 1;
constexpr const uint16_t SCENERY_PATH_SCENERY_ID_MIN = 0x100;
constexpr const uint16_t SCENERY_PATH_SCENERY_ID_MAX = SCENERY_PATH_SCENERY_ID_MIN + MAX_PATH_ADDITION_OBJECTS - 1;
constexpr const uint16_t SCENERY_WALLS_ID_MIN = 0x200;
constexpr const uint16_t SCENERY_WALLS_ID_MAX = SCENERY_WALLS_ID_MIN + MAX_WALL_SCENERY_OBJECTS - 1;
constexpr const uint16_t SCENERY_LARGE_SCENERY_ID_MIN = 0x300;
constexpr const uint16_t SCENERY_LARGE_SCENERY_ID_MAX = SCENERY_LARGE_SCENERY_ID_MIN + MAX_LARGE_SCENERY_OBJECTS - 1;
constexpr const uint16_t SCENERY_BANNERS_ID_MIN = 0x400;
constexpr const uint16_t SCENERY_BANNERS_ID_MAX = SCENERY_BANNERS_ID_MIN + MAX_BANNER_OBJECTS - 1;
#define SCENERY_WITHER_AGE_THRESHOLD_1 0x28
#define SCENERY_WITHER_AGE_THRESHOLD_2 0x37
@ -187,19 +175,17 @@ struct rct_scenery_entry
assert_struct_size(rct_scenery_entry, 6 + 21);
#endif
#pragma pack(pop)
struct rct_scenery_group_entry
{
rct_string_id name; // 0x00
uint32_t image; // 0x02
uint16_t scenery_entries[0x80]; // 0x06
uint8_t entry_count; // 0x106
uint8_t pad_107;
uint8_t priority; // 0x108
uint8_t pad_109;
uint32_t entertainer_costumes; // 0x10A
rct_string_id name;
uint32_t image;
ScenerySelection scenery_entries[0x80];
uint8_t entry_count;
uint8_t priority;
uint32_t entertainer_costumes;
};
assert_struct_size(rct_scenery_group_entry, 14 + 2 * 0x80);
#pragma pack(pop)
enum
{
@ -228,7 +214,9 @@ enum
SCENERY_TYPE_PATH_ITEM,
SCENERY_TYPE_WALL,
SCENERY_TYPE_LARGE,
SCENERY_TYPE_BANNER
SCENERY_TYPE_BANNER,
SCENERY_TYPE_COUNT,
};
enum
@ -252,13 +240,11 @@ enum class ScatterToolDensity : uint8_t
HighDensity
};
#define SCENERY_ENTRIES_BY_TAB 1024
constexpr auto WINDOW_SCENERY_TAB_SELECTION_UNDEFINED = std::numeric_limits<uint16_t>::max();
extern uint8_t gSceneryQuadrant;
extern money32 gSceneryPlaceCost;
extern int16_t gSceneryPlaceObject;
extern ScenerySelection gSceneryPlaceObject;
extern uint16_t gSceneryPlaceObjectEntryIndex;
extern int16_t gSceneryPlaceZ;
extern uint8_t gSceneryPlaceRotation;
@ -288,7 +274,6 @@ rct_scenery_entry* get_banner_entry(int32_t entryIndex);
rct_scenery_entry* get_footpath_item_entry(int32_t entryIndex);
rct_scenery_group_entry* get_scenery_group_entry(int32_t entryIndex);
int32_t get_scenery_id_from_entry_index(uint8_t objectType, int32_t entryIndex);
int32_t wall_entry_get_door_sound(const rct_scenery_entry* wallEntry);
#endif

View File

@ -0,0 +1,41 @@
/*****************************************************************************
* Copyright (c) 2014-2020 OpenRCT2 developers
*
* For a complete list of all authors, please refer to contributors.md
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#pragma once
#include <cstdint>
#include <limits>
constexpr auto WINDOW_SCENERY_TAB_SELECTION_UNDEFINED = std::numeric_limits<uint16_t>::max();
struct ScenerySelection
{
uint8_t SceneryType;
uint16_t EntryIndex;
inline bool operator==(const ScenerySelection& rhs)
{
return SceneryType == rhs.SceneryType && EntryIndex == rhs.EntryIndex;
}
bool IsUndefined() const
{
return EntryIndex == WINDOW_SCENERY_TAB_SELECTION_UNDEFINED;
}
void SetUndefined()
{
EntryIndex = WINDOW_SCENERY_TAB_SELECTION_UNDEFINED;
}
static ScenerySelection CreateUndefined()
{
return ScenerySelection{ 0, WINDOW_SCENERY_TAB_SELECTION_UNDEFINED };
}
};