mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-19 21:13:05 +01:00
Add support for inserting corrupt elements in MP
This PR adds three new files, one to expose some of the funcitons for the tile inspector window, and two completely new ones for the tile inspector logic, which handles what happens. This commit adds the logic for inserting corrupt elements, while keeping the list on both server and client correct (e.g. client has the same tile selected, and keeps the same element in focus when the tiles gets changed)
This commit is contained in:
committed by
Michał Janiszewski
parent
6efb94bbe4
commit
88a0bb4270
@@ -1245,4 +1245,6 @@ GAME_COMMAND_POINTER* new_game_command_table[GAME_COMMAND_COUNT] = {
|
||||
game_command_pickup_guest,
|
||||
game_command_pickup_staff,
|
||||
game_command_balloon_press,
|
||||
game_command_modify_tile,
|
||||
game_command_modify_element,
|
||||
};
|
||||
|
||||
@@ -93,6 +93,8 @@ enum GAME_COMMAND {
|
||||
GAME_COMMAND_PICKUP_GUEST,
|
||||
GAME_COMMAND_PICKUP_STAFF,
|
||||
GAME_COMMAND_BALLOON_PRESS,
|
||||
GAME_COMMAND_MODIFY_TILE,
|
||||
GAME_COMMAND_MODIFY_ELEMENT,
|
||||
GAME_COMMAND_COUNT
|
||||
};
|
||||
|
||||
|
||||
@@ -411,6 +411,7 @@
|
||||
<ClCompile Include="world\park.c" />
|
||||
<ClCompile Include="world\scenery.c" />
|
||||
<ClCompile Include="world\sprite.c" />
|
||||
<ClCompile Include="world\tile_inspector.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\resources\resource.h" />
|
||||
@@ -584,6 +585,7 @@
|
||||
<ClInclude Include="util\util.h" />
|
||||
<ClInclude Include="windows\dropdown.h" />
|
||||
<ClInclude Include="windows\error.h" />
|
||||
<ClInclude Include="windows\tile_inspector.h" />
|
||||
<ClInclude Include="windows\tooltip.h" />
|
||||
<ClInclude Include="world\banner.h" />
|
||||
<ClInclude Include="world\climate.h" />
|
||||
@@ -597,6 +599,7 @@
|
||||
<ClInclude Include="world\park.h" />
|
||||
<ClInclude Include="world\scenery.h" />
|
||||
<ClInclude Include="world\sprite.h" />
|
||||
<ClInclude Include="world\tile_inspector.h" />
|
||||
<ClInclude Include="world\water.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
#include "dropdown.h"
|
||||
#include "error.h"
|
||||
#include "tile_inspector.h"
|
||||
#include "../game.h"
|
||||
#include "../input.h"
|
||||
#include "../interface/themes.h"
|
||||
#include "../interface/viewport.h"
|
||||
@@ -28,6 +30,7 @@
|
||||
#include "../world/footpath.h"
|
||||
#include "../world/map.h"
|
||||
#include "../world/scenery.h"
|
||||
#include "../world/tile_inspector.h"
|
||||
|
||||
static const rct_string_id terrainTypeStringIds[] = {
|
||||
STR_TILE_INSPECTOR_TERRAIN_GRASS,
|
||||
@@ -74,19 +77,6 @@ static const rct_string_id fenceSlopeStringIds[] = {
|
||||
STR_TILE_INSPECTOR_FENCE_SLOPED_RIGHT
|
||||
};
|
||||
|
||||
enum WINDOW_TILE_INSPECTOR_PAGES {
|
||||
PAGE_DEFAULT,
|
||||
PAGE_SURFACE,
|
||||
PAGE_PATH,
|
||||
PAGE_TRACK,
|
||||
PAGE_SCENERY,
|
||||
PAGE_ENTRANCE,
|
||||
PAGE_FENCE,
|
||||
PAGE_LARGE_SCENERY,
|
||||
PAGE_BANNER,
|
||||
PAGE_CORRUPT
|
||||
};
|
||||
|
||||
enum WINDOW_TILE_INSPECTOR_WIDGET_IDX {
|
||||
WIDX_BACKGROUND,
|
||||
WIDX_TITLE,
|
||||
@@ -460,7 +450,7 @@ static sint32 windowTileInspectorToolMouseX = 0;
|
||||
static sint32 windowTileInspectorToolMouseY = 0;
|
||||
static sint32 windowTileInspectorToolMapX = 0;
|
||||
static sint32 windowTileInspectorToolMapY = 0;
|
||||
static sint32 windowTileInspectorElementCount = 0;
|
||||
sint32 windowTileInspectorElementCount = 0;
|
||||
static bool windowTileInspectorApplyToAll = false;
|
||||
static bool windowTileInspectorElementCopied = false;
|
||||
static rct_map_element tileInspectorCopiedElement;
|
||||
@@ -494,8 +484,6 @@ static void window_tile_inspector_scrollmouseover(rct_window *w, sint32 scrollIn
|
||||
static void window_tile_inspector_invalidate(rct_window *w);
|
||||
static void window_tile_inspector_paint(rct_window *w, rct_drawpixelinfo *dpi);
|
||||
static void window_tile_inspector_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, sint32 scrollIndex);
|
||||
static void window_tile_inspector_set_page(rct_window *w, const sint32 page);
|
||||
static void window_tile_inspector_auto_set_buttons(rct_window *w);
|
||||
|
||||
static rct_window_event_list windowTileInspectorEvents = {
|
||||
NULL,
|
||||
@@ -621,23 +609,15 @@ static void window_tile_inspector_load_tile(rct_window* w)
|
||||
|
||||
static void window_tile_inspector_insert_corrupt_element(rct_window *w)
|
||||
{
|
||||
// Create new corrupt element
|
||||
rct_map_element *curruptElement = map_element_insert(windowTileInspectorTileX, windowTileInspectorTileY, -1, 0); // Ugly hack: -1 guarantees this to be placed first
|
||||
windowTileInspectorElementCount++;
|
||||
assert(curruptElement != NULL);
|
||||
curruptElement->type = MAP_ELEMENT_TYPE_CORRUPT;
|
||||
|
||||
// Set the base height to be the same as the selected element
|
||||
rct_map_element *const selectedElement = window_tile_inspector_get_selected_element(w);
|
||||
curruptElement->base_height = curruptElement->clearance_height = selectedElement->base_height;
|
||||
|
||||
// Move the corrupt element up until the selected list item is reached
|
||||
// this way it's placed under the selected element, even when there are multiple elements with the same base height
|
||||
for (sint32 i = 0; i < w->selected_list_item; i++) {
|
||||
window_tile_inspector_swap_elements(i, i + 1);
|
||||
}
|
||||
|
||||
map_invalidate_tile_full(windowTileInspectorTileX << 5, windowTileInspectorTileY << 5);
|
||||
game_do_command(
|
||||
TILE_INSPECTOR_ELEMENT_CORRUPT,
|
||||
GAME_COMMAND_FLAG_APPLY,
|
||||
windowTileInspectorTileX | (windowTileInspectorTileY << 8),
|
||||
w->selected_list_item,
|
||||
GAME_COMMAND_MODIFY_TILE,
|
||||
0,
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
static void window_tile_inspector_remove_element(sint32 index)
|
||||
@@ -1049,9 +1029,6 @@ static void window_tile_inspector_mouseup(rct_window *w, sint32 widgetIndex)
|
||||
break;
|
||||
case WIDX_BUTTON_CORRUPT:
|
||||
window_tile_inspector_insert_corrupt_element(w);
|
||||
window_tile_inspector_set_page(w, PAGE_CORRUPT);
|
||||
window_tile_inspector_auto_set_buttons(w);
|
||||
window_invalidate(w);
|
||||
break;
|
||||
case WIDX_BUTTON_REMOVE:
|
||||
window_tile_inspector_remove_element(w->selected_list_item);
|
||||
@@ -1518,7 +1495,7 @@ static void window_tile_inspector_scrollgetsize(rct_window *w, sint32 scrollInde
|
||||
*height = windowTileInspectorElementCount * LIST_ITEM_HEIGHT;
|
||||
}
|
||||
|
||||
static void window_tile_inspector_set_page(rct_window *w, const sint32 page)
|
||||
void window_tile_inspector_set_page(rct_window *w, const tile_inspector_page page)
|
||||
{
|
||||
w->page = page;
|
||||
w->widgets = tileInspectorWidgets[page];
|
||||
@@ -1526,7 +1503,7 @@ static void window_tile_inspector_set_page(rct_window *w, const sint32 page)
|
||||
w->disabled_widgets = windowTileInspectorDisabledWidgets[page];
|
||||
}
|
||||
|
||||
static void window_tile_inspector_auto_set_buttons(rct_window *w)
|
||||
void window_tile_inspector_auto_set_buttons(rct_window *w)
|
||||
{
|
||||
// X and Y spinners
|
||||
widget_set_enabled(w, WIDX_SPINNER_X_INCREASE, (windowTileInspectorTileSelected && (windowTileInspectorTileX < 255)));
|
||||
|
||||
39
src/openrct2/windows/tile_inspector.h
Normal file
39
src/openrct2/windows/tile_inspector.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers
|
||||
/*****************************************************************************
|
||||
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
||||
*
|
||||
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
|
||||
* For more information, visit https://github.com/OpenRCT2/OpenRCT2
|
||||
*
|
||||
* OpenRCT2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* A full copy of the GNU General Public License can be found in licence.txt
|
||||
*****************************************************************************/
|
||||
#pragma endregion
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../common.h"
|
||||
#include "../interface/window.h"
|
||||
|
||||
typedef enum tile_inspector_page
|
||||
{
|
||||
PAGE_DEFAULT,
|
||||
PAGE_SURFACE,
|
||||
PAGE_PATH,
|
||||
PAGE_TRACK,
|
||||
PAGE_SCENERY,
|
||||
PAGE_ENTRANCE,
|
||||
PAGE_FENCE,
|
||||
PAGE_LARGE_SCENERY,
|
||||
PAGE_BANNER,
|
||||
PAGE_CORRUPT
|
||||
} tile_inspector_page;
|
||||
|
||||
extern sint32 windowTileInspectorElementCount;
|
||||
|
||||
void window_tile_inspector_set_page(rct_window *w, const tile_inspector_page page);
|
||||
void window_tile_inspector_auto_set_buttons(rct_window *w);
|
||||
@@ -719,7 +719,6 @@ static void window_top_toolbar_invalidate(rct_window *w)
|
||||
// Fall-through
|
||||
case NETWORK_MODE_SERVER:
|
||||
window_top_toolbar_widgets[WIDX_FASTFORWARD].type = WWT_EMPTY;
|
||||
window_top_toolbar_widgets[WIDX_DEBUG].type = WWT_EMPTY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "map_animation.h"
|
||||
#include "park.h"
|
||||
#include "scenery.h"
|
||||
#include "tile_inspector.h"
|
||||
|
||||
/**
|
||||
* Replaces 0x00993CCC, 0x00993CCE
|
||||
@@ -5604,6 +5605,43 @@ void game_command_set_sign_style(sint32* eax, sint32* ebx, sint32* ecx, sint32*
|
||||
*ebx = 0;
|
||||
}
|
||||
|
||||
void game_command_modify_tile(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp)
|
||||
{
|
||||
sint32 flags = *ebx;
|
||||
const tile_inspector_element_type action_type = *eax;
|
||||
switch (action_type)
|
||||
{
|
||||
case TILE_INSPECTOR_ELEMENT_ANY:
|
||||
case TILE_INSPECTOR_ELEMENT_SURFACE:
|
||||
case TILE_INSPECTOR_ELEMENT_PATH:
|
||||
case TILE_INSPECTOR_ELEMENT_TRACK:
|
||||
case TILE_INSPECTOR_ELEMENT_SCENERY:
|
||||
case TILE_INSPECTOR_ELEMENT_ENTRANCE:
|
||||
case TILE_INSPECTOR_ELEMENT_FENCE:
|
||||
case TILE_INSPECTOR_ELEMENT_SCENERYMULTIPLE:
|
||||
case TILE_INSPECTOR_ELEMENT_BANNER:
|
||||
return;
|
||||
case TILE_INSPECTOR_ELEMENT_CORRUPT:
|
||||
{
|
||||
const sint32 x = *ecx & 0xFF;
|
||||
const sint32 y = (*ecx >> 8) & 0xFF;
|
||||
const sint16 index = *edx;
|
||||
*ebx = tile_inspector_insert_corrupt_at(x, y, index, flags);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void game_command_modify_element(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp)
|
||||
{
|
||||
log_info("Modifying element");
|
||||
if (*ebx & GAME_COMMAND_FLAG_APPLY) {
|
||||
puts("Yeah baby");
|
||||
}
|
||||
|
||||
*ebx = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the track element at x, y, z.
|
||||
* @param x x units, not tiles.
|
||||
|
||||
@@ -473,6 +473,8 @@ void game_command_set_banner_name(sint32* eax, sint32* ebx, sint32* ecx, sint32*
|
||||
void game_command_set_sign_name(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp);
|
||||
void game_command_set_banner_style(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp);
|
||||
void game_command_set_sign_style(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp);
|
||||
void game_command_modify_tile(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp);
|
||||
void game_command_modify_element(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp);
|
||||
|
||||
typedef struct map_element_iterator {
|
||||
sint32 x;
|
||||
|
||||
115
src/openrct2/world/tile_inspector.c
Normal file
115
src/openrct2/world/tile_inspector.c
Normal file
@@ -0,0 +1,115 @@
|
||||
#pragma region Copyright (c) 2014-2017 OpenRCT2 Developers
|
||||
/*****************************************************************************
|
||||
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
||||
*
|
||||
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
|
||||
* For more information, visit https://github.com/OpenRCT2/OpenRCT2
|
||||
*
|
||||
* OpenRCT2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* A full copy of the GNU General Public License can be found in licence.txt
|
||||
*****************************************************************************/
|
||||
#pragma endregion
|
||||
|
||||
#include "../game.h"
|
||||
#include "../interface/window.h"
|
||||
#include "../windows/tile_inspector.h"
|
||||
#include "map.h"
|
||||
#include "tile_inspector.h"
|
||||
|
||||
static void map_swap_elements_at(sint32 x, sint32 y, sint16 first, sint16 second)
|
||||
{
|
||||
rct_map_element *mapElement = map_get_first_element_at(x, y);
|
||||
rct_map_element *const firstElement = mapElement + first;
|
||||
rct_map_element *const secondElement = mapElement + second;
|
||||
|
||||
// swap_elements shouldn't be called when there is only one element on the tile
|
||||
assert(!map_element_is_last_for_tile(mapElement));
|
||||
|
||||
// Make sure both elements are actually on the current tile
|
||||
sint16 elementCount = 0;
|
||||
do
|
||||
{
|
||||
elementCount++;
|
||||
} while (!map_element_is_last_for_tile(mapElement++));
|
||||
assert(elementCount > max(first, second));
|
||||
|
||||
// Swap their memory
|
||||
rct_map_element temp = *firstElement;
|
||||
*firstElement = *secondElement;
|
||||
*secondElement = temp;
|
||||
|
||||
// Swap the 'last map element for tile' flag if either one of them was last
|
||||
if (map_element_is_last_for_tile(firstElement) || map_element_is_last_for_tile(secondElement))
|
||||
{
|
||||
firstElement->flags ^= MAP_ELEMENT_FLAG_LAST_TILE;
|
||||
secondElement->flags ^= MAP_ELEMENT_FLAG_LAST_TILE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a corrupt element under a given element on a given tile
|
||||
* @param x, y: The coordinates of the tile
|
||||
* @param element_index: The nth element on this tile
|
||||
* Returns 0 on success, MONEY_UNDEFINED otherwise.
|
||||
*/
|
||||
sint32 tile_inspector_insert_corrupt_at(sint32 x, sint32 y, sint16 element_index, sint32 flags)
|
||||
{
|
||||
// Make sure there is enough space for the new element
|
||||
if (!map_check_free_elements_and_reorganise(1))
|
||||
{
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
||||
{
|
||||
// Create new corrupt element
|
||||
rct_map_element *curruptElement = map_element_insert(x, y, -1, 0); // Ugly hack: -1 guarantees this to be placed first
|
||||
if (curruptElement == NULL)
|
||||
{
|
||||
log_warning("Failed to insert corrupt element.");
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
curruptElement->type = MAP_ELEMENT_TYPE_CORRUPT;
|
||||
|
||||
// Set the base height to be the same as the selected element
|
||||
rct_map_element *const selectedElement = map_get_first_element_at(x, y) + element_index;
|
||||
curruptElement->base_height = curruptElement->clearance_height = selectedElement->base_height;
|
||||
|
||||
// Move the corrupt element up until the selected list item is reached
|
||||
// this way it's placed under the selected element, even when there are multiple elements with the same base height
|
||||
for (sint16 i = 0; i < element_index; i++)
|
||||
{
|
||||
map_swap_elements_at(x, y, i, i + 1);
|
||||
}
|
||||
|
||||
map_invalidate_tile_full(x << 5, y << 5);
|
||||
|
||||
// Update the tile inspector's list for everyone who has the tile selected
|
||||
rct_window *tile_inspector_window = window_find_by_class(WC_TILE_INSPECTOR);
|
||||
if (tile_inspector_window != NULL)
|
||||
{
|
||||
windowTileInspectorElementCount++;
|
||||
|
||||
// Keep other elements (that are not being hidden) selected
|
||||
if (tile_inspector_window->selected_list_item > element_index)
|
||||
{
|
||||
tile_inspector_window->selected_list_item++;
|
||||
}
|
||||
|
||||
if (tile_inspector_window->selected_list_item == element_index)
|
||||
{
|
||||
window_tile_inspector_set_page(tile_inspector_window, PAGE_CORRUPT);
|
||||
}
|
||||
|
||||
window_tile_inspector_auto_set_buttons(tile_inspector_window);
|
||||
window_invalidate(tile_inspector_window);
|
||||
}
|
||||
}
|
||||
|
||||
// Nothing went wrong
|
||||
return 0;
|
||||
}
|
||||
34
src/openrct2/world/tile_inspector.h
Normal file
34
src/openrct2/world/tile_inspector.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers
|
||||
/*****************************************************************************
|
||||
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
||||
*
|
||||
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
|
||||
* For more information, visit https://github.com/OpenRCT2/OpenRCT2
|
||||
*
|
||||
* OpenRCT2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* A full copy of the GNU General Public License can be found in licence.txt
|
||||
*****************************************************************************/
|
||||
#pragma endregion
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../common.h"
|
||||
|
||||
typedef enum {
|
||||
TILE_INSPECTOR_ELEMENT_ANY = 0,
|
||||
TILE_INSPECTOR_ELEMENT_SURFACE,
|
||||
TILE_INSPECTOR_ELEMENT_PATH,
|
||||
TILE_INSPECTOR_ELEMENT_TRACK,
|
||||
TILE_INSPECTOR_ELEMENT_SCENERY,
|
||||
TILE_INSPECTOR_ELEMENT_ENTRANCE,
|
||||
TILE_INSPECTOR_ELEMENT_FENCE,
|
||||
TILE_INSPECTOR_ELEMENT_SCENERYMULTIPLE,
|
||||
TILE_INSPECTOR_ELEMENT_BANNER,
|
||||
TILE_INSPECTOR_ELEMENT_CORRUPT,
|
||||
} tile_inspector_element_type;
|
||||
|
||||
sint32 tile_inspector_insert_corrupt_at(sint32 x, sint32 y, sint16 element_index, sint32 flags);
|
||||
Reference in New Issue
Block a user