1
0
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:
Broxzier
2017-01-15 13:53:19 +01:00
committed by Michał Janiszewski
parent 6efb94bbe4
commit 88a0bb4270
10 changed files with 250 additions and 39 deletions

View File

@@ -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,
};

View File

@@ -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
};

View File

@@ -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>

View File

@@ -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)));

View 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);

View File

@@ -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;
}
}

View File

@@ -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.

View File

@@ -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;

View 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;
}

View 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);