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:
66
src/editor.c
66
src/editor.c
@@ -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;
|
||||
}
|
||||
|
||||
@@ -47,4 +47,7 @@ void sub_6BD3A4();
|
||||
|
||||
void editor_open_windows_for_current_step();
|
||||
|
||||
bool editor_check_park();
|
||||
bool editor_check_object_selection();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user