1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-06 06:32:56 +01:00

Merge branch 'implement-editor-callprocs' into develop

This commit is contained in:
IntelOrca
2015-07-06 14:41:08 +01:00
6 changed files with 291 additions and 12 deletions

View File

@@ -39,6 +39,7 @@
#include "util/util.h"
#include "world/banner.h"
#include "world/climate.h"
#include "world/footpath.h"
#include "world/map.h"
#include "world/park.h"
#include "world/scenery.h"
@@ -599,4 +600,67 @@ static void editor_finalise_main_view()
RCT2_GLOBAL(0x009DEB7C, uint16) = 0;
load_palette();
gfx_invalidate_screen();
}
}
/**
*
* rct2: 0x006AB9B8
*/
bool editor_check_object_selection()
{
return !(RCT2_CALLPROC_EBPSAFE(0x006AB9B8) & 0x100);
}
/**
*
* rct2: 0x0066FEAC
*/
bool editor_check_park()
{
int parkSize = park_calculate_size();
if (parkSize == 0) {
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_PARK_MUST_OWN_SOME_LAND;
return false;
}
for (int i = 0; i < 4; i++) {
if (RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_X, uint16)[i] != 0x8000)
break;
if (i == 3) {
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_NO_PARK_ENTRANCES;
return false;
}
}
for (int i = 0; i < 4; i++) {
if (RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_X, uint16)[i] == 0x8000)
continue;
int x = RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_X, uint16)[i];
int y = RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_Y, uint16)[i];
int z = RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_Z, uint16)[i] / 8;
int direction = RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_DIRECTION, uint8)[i] ^ 2;
switch (footpath_is_connected_to_map_edge(x, y, z, direction, 0)) {
case FOOTPATH_SEARCH_NOT_FOUND:
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_PARK_ENTRANCE_WRONG_DIRECTION_OR_NO_PATH;
return false;
case FOOTPATH_SEARCH_INCOMPLETE:
case FOOTPATH_SEARCH_TOO_COMPLEX:
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_PARK_ENTRANCE_PATH_INCOMPLETE_OR_COMPLEX;
return false;
case FOOTPATH_SEARCH_SUCCESS:
// Run the search again and unown the path
footpath_is_connected_to_map_edge(x, y, z, direction, 0x20);
break;
}
}
if (gPeepSpawns[0].x == 0xFFFF && gPeepSpawns[1].x == 0xFFFF) {
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_PEEP_SPAWNS_NOT_SET;
return false;
}
return true;
}

View File

@@ -47,4 +47,7 @@ void sub_6BD3A4();
void editor_open_windows_for_current_step();
bool editor_check_park();
bool editor_check_object_selection();
#endif

View File

@@ -1625,6 +1625,7 @@ enum {
STR_OBJECTIVE = 3322,
STR_PEEP_SPAWNS_NOT_SET = 3327,
STR_CANT_ADVANCE_TO_NEXT_EDITOR_STAGE = 3328,
STR_NO_PARK_ENTRANCES = 3329,
STR_PARK_MUST_OWN_SOME_LAND = 3330,

View File

@@ -25,15 +25,16 @@
#include "../scenario.h"
#include "../sprites.h"
#include "../localisation/localisation.h"
#include "../interface/themes.h"
#include "../interface/viewport.h"
#include "../interface/widget.h"
#include "../interface/window.h"
#include "../platform/platform.h"
#include "../title.h"
#include "../util/util.h"
#include "../world/footpath.h"
#include "../world/scenery.h"
#include "error.h"
#include "../interface/themes.h"
enum {
WIDX_PREVIOUS_IMAGE, // 1
@@ -153,13 +154,23 @@ void window_editor_bottom_toolbar_jump_back_to_object_selection() {
gfx_invalidate_screen();
}
/**
*
* rct2: 0x006DFED0
*/
static void sub_6DFED0()
{
for (int i = 0; i < 56; i++)
RCT2_ADDRESS(0x01357BD0, sint32)[i] = -1;
}
/**
*
* rct2: 0x0066F62C
*/
void window_editor_bottom_toolbar_jump_back_to_landscape_editor() {
window_close_all();
RCT2_CALLPROC_EBPSAFE(0x006DFED0);
sub_6DFED0();
scenery_set_default_placement_configuration();
g_editor_step = EDITOR_STEP_LANDSCAPE_EDITOR;
window_map_open();
@@ -203,9 +214,47 @@ void window_editor_bottom_toolbar_jump_back_to_options_selection() {
*
* rct2: 0x006AB1CE
*/
int window_editor_bottom_toolbar_check_object_selection()
bool window_editor_bottom_toolbar_check_object_selection()
{
return RCT2_CALLPROC_EBPSAFE(0x006AB1CE) & 0x100;
rct_window *w;
if (editor_check_object_selection()) {
window_close_by_class(WC_EDITOR_OBJECT_SELECTION);
return true;
}
window_error_open(STR_INVALID_SELECTION_OF_OBJECTS, RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id));
w = window_find_by_class(WC_EDITOR_OBJECT_SELECTION);
if (w != NULL) {
// Click first tab (rides)
window_event_mouse_up_call(w, 4);
}
return false;
}
/**
*
* rct2: 0x0066F6E3
*/
static void sub_66F6E3()
{
RCT2_GLOBAL(0x01357404, uint32) = 0xFFFFFFFF;
RCT2_GLOBAL(0x01357408, uint32) = 0xFFFFFFFF;
RCT2_GLOBAL(0x0135740C, uint32) = 0xFFFFFFFF;
RCT2_GLOBAL(0x01357410, uint32) = 0xFFFFFFFF;
for (int i = 0; i < 128; i++) {
RCT2_ADDRESS(0x01357444, uint32)[i] = RCT2_ADDRESS(0x0097C468, uint32)[i];
RCT2_ADDRESS(0x01357644, uint32)[i] = RCT2_ADDRESS(0x0097C5D4, uint32)[i];
}
for (int i = 0; i < 8; i++) {
RCT2_ADDRESS(0x01357424, uint32)[i] = 0xFFFFFFFF;
}
window_new_ride_open();
RCT2_GLOBAL(0x0141F570, uint8) = 6;
gfx_invalidate_screen();
}
/**
@@ -214,13 +263,13 @@ int window_editor_bottom_toolbar_check_object_selection()
*/
void window_editor_bottom_toolbar_jump_forward_from_object_selection()
{
if (window_editor_bottom_toolbar_check_object_selection())
if (!window_editor_bottom_toolbar_check_object_selection())
return;
if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_DESIGNER) {
RCT2_CALLPROC_EBPSAFE(0x0066F6E3);
sub_66F6E3();
} else {
RCT2_CALLPROC_EBPSAFE(0x006DFED0);
sub_6DFED0();
scenery_set_default_placement_configuration();
RCT2_GLOBAL(0x00141F570, uint8) = 1;
window_map_open();
@@ -230,12 +279,10 @@ void window_editor_bottom_toolbar_jump_forward_from_object_selection()
/**
*
* rct2: 0x0066f758
* rct2: 0x0066F758
*/
void window_editor_bottom_toolbar_jump_forward_to_invention_list_set_up() {
uint32 flags = RCT2_CALLPROC_X(0x0066FEAC, 0, 0, 0, 0, 0, 0, 0);
if (!(flags & 0x100)) {
if (editor_check_park()) {
window_close_all();
window_editor_inventions_list_open();
g_editor_step = EDITOR_STEP_INVENTIONS_LIST_SET_UP;

View File

@@ -731,3 +731,156 @@ void sub_6A759F()
}
}
}
/**
*
* rct2: 0x0069ADBD
*/
static void footpath_unown(int x, int y, rct_map_element *pathElement)
{
int ownershipUnk = 0;
int z = pathElement->base_height;
rct_map_element *surfaceElement = map_get_surface_element_at(x >> 5, y >> 5);
if (surfaceElement->base_height |= z) {
z -= 2;
if (surfaceElement->base_height |= z) {
ownershipUnk = (surfaceElement->properties.surface.ownership & 0xCF) >> 4;
}
}
map_buy_land_rights(x, y, x, y, 6, 1);
}
bool get_next_direction(int edges, int *direction)
{
int index = bitscanforward(edges);
if (index == -1)
return false;
*direction = index;
return true;
}
/**
*
* rct2: 0x0069AC1A
*/
int footpath_is_connected_to_map_edge_recurse(
int x, int y, int z, int direction, int flags,
int level, int distanceFromJunction, int junctionTolerance
) {
rct_map_element *mapElement;
int edges, slopeDirection;
x += TileDirectionDelta[direction].x;
y += TileDirectionDelta[direction].y;
if (++level > 250)
return FOOTPATH_SEARCH_TOO_COMPLEX;
// Check if we are at edge of map
if (x < 32 || y < 32)
return FOOTPATH_SEARCH_SUCCESS;
if (x >= RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, uint16) || y >= RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, uint16))
return FOOTPATH_SEARCH_SUCCESS;
mapElement = map_get_first_element_at(x >> 5, y >> 5);
do {
if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_PATH)
continue;
if (
footpath_element_is_sloped(mapElement) &&
(slopeDirection = footpath_element_get_slope_direction(mapElement)) != direction
) {
if ((slopeDirection ^ 2) != direction) continue;
if (mapElement->base_height + 2 != z) continue;
} else if (mapElement->base_height != z) {
continue;
}
if (mapElement->type & RCT2_GLOBAL(0x00F1AEE0, uint8)) continue;
if (flags & 0x20) {
footpath_unown(x, y, mapElement);
}
edges = mapElement->properties.path.edges & 0x0F;
direction ^= 2;
if (!(flags & 0x80)) {
if (mapElement[1].type == MAP_ELEMENT_TYPE_BANNER) {
for (int i = 1; i < 4; i++) {
if (map_element_is_last_for_tile(&mapElement[i - 1])) break;
if (mapElement[i].type != MAP_ELEMENT_TYPE_BANNER) break;
edges &= mapElement[i].properties.banner.flags;
}
}
if (mapElement[2].type == MAP_ELEMENT_TYPE_BANNER && mapElement[1].type != MAP_ELEMENT_TYPE_PATH) {
for (int i = 1; i < 6; i++) {
if (map_element_is_last_for_tile(&mapElement[i - 1])) break;
if (mapElement[i].type != MAP_ELEMENT_TYPE_BANNER) break;
edges &= mapElement[i].properties.banner.flags;
}
}
}
goto searchFromFootpath;
} while (!map_element_is_last_for_tile(mapElement++));
return level == 1 ? FOOTPATH_SEARCH_NOT_FOUND : FOOTPATH_SEARCH_INCOMPLETE;
searchFromFootpath:
// Exclude direction we came from
z = mapElement->base_height;
edges &= ~(1 << direction);
// Find next direction to go
if (!get_next_direction(edges, &direction)) {
return FOOTPATH_SEARCH_INCOMPLETE;
}
edges &= ~(1 << direction);
if (edges == 0) {
// Only possible direction to go
if (footpath_element_is_sloped(mapElement) && footpath_element_get_slope_direction(mapElement) == direction) {
z += 2;
}
return footpath_is_connected_to_map_edge_recurse(
x, y, z, direction, flags,
level, distanceFromJunction + 1, junctionTolerance
);
} else {
// We have reached a junction
if (distanceFromJunction != 0) {
junctionTolerance--;
}
junctionTolerance--;
if (junctionTolerance < 0) {
return FOOTPATH_SEARCH_TOO_COMPLEX;
}
do {
edges &= ~(1 << direction);
if (footpath_element_is_sloped(mapElement) && footpath_element_get_slope_direction(mapElement) == direction) {
z += 2;
}
int result = footpath_is_connected_to_map_edge_recurse(x, y, z, direction, flags, level, 0, junctionTolerance);
if (result == FOOTPATH_SEARCH_SUCCESS) {
return result;
}
} while (get_next_direction(edges, &direction));
return FOOTPATH_SEARCH_INCOMPLETE;
}
}
int footpath_is_connected_to_map_edge(int x, int y, int z, int direction, int flags)
{
RCT2_GLOBAL(0x00F1AEE0, uint8) = 1;
return footpath_is_connected_to_map_edge_recurse(x, y, z, direction, flags, 0, 0, 16);
}
bool footpath_element_is_sloped(rct_map_element *mapElement)
{
return mapElement->properties.path.type & 4;
}
int footpath_element_get_slope_direction(rct_map_element *mapElement)
{
return mapElement->properties.path.type & 3;
}

View File

@@ -37,6 +37,13 @@ typedef struct {
uint8 flags; // 0x0B
} rct_path_type;
enum {
FOOTPATH_SEARCH_SUCCESS,
FOOTPATH_SEARCH_NOT_FOUND,
FOOTPATH_SEARCH_INCOMPLETE,
FOOTPATH_SEARCH_TOO_COMPLEX
};
#define g_pathTypeEntries ((rct_path_type**)object_entry_groups[OBJECT_TYPE_PATHS].chunks)
extern const rct_xy16 word_981D6C[4];
@@ -57,4 +64,8 @@ void sub_6A742F(int rideIndex, int entranceIndex, int x, int y, rct_map_element
void footpath_bridge_get_info_from_pos(int screenX, int screenY, int *x, int *y, int *direction, rct_map_element **mapElement);
int footpath_is_connected_to_map_edge(int x, int y, int z, int direction, int flags);
bool footpath_element_is_sloped(rct_map_element *mapElement);
int footpath_element_get_slope_direction(rct_map_element *mapElement);
#endif