mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-17 12:03:07 +01:00
implement clear scenery game command, try out removing paths feature
This commit is contained in:
@@ -878,7 +878,7 @@ static uint32 game_do_command_table[58] = {
|
||||
0x006B909A,
|
||||
0x006BA16A,
|
||||
0x006648E3,
|
||||
0x0068DF91
|
||||
0
|
||||
};
|
||||
|
||||
void game_command_emptysub(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) {}
|
||||
@@ -941,7 +941,7 @@ static GAME_COMMAND_POINTER* new_game_command_table[58] = {
|
||||
game_command_emptysub,
|
||||
game_command_emptysub,
|
||||
game_command_emptysub,
|
||||
game_command_emptysub
|
||||
game_command_clear_scenery
|
||||
};
|
||||
|
||||
#pragma endregion
|
||||
|
||||
@@ -36,7 +36,7 @@ enum GAME_COMMAND {
|
||||
GAME_COMMAND_11,
|
||||
GAME_COMMAND_12,
|
||||
GAME_COMMAND_13,
|
||||
GAME_COMMAND_14,
|
||||
GAME_COMMAND_REMOVE_SCENERY,
|
||||
GAME_COMMAND_15,
|
||||
GAME_COMMAND_16,
|
||||
GAME_COMMAND_PLACE_PATH, // 17
|
||||
@@ -64,7 +64,7 @@ enum GAME_COMMAND {
|
||||
GAME_COMMAND_SET_PARK_ENTRANCE_FEE, // 39
|
||||
GAME_COMMAND_SET_STAFF_COLOUR, // 40
|
||||
GAME_COMMAND_41,
|
||||
GAME_COMMAND_42,
|
||||
GAME_COMMAND_REMOVE_FENCE,
|
||||
GAME_COMMAND_43,
|
||||
GAME_COMMAND_44,
|
||||
GAME_COMMAND_SET_CURRENT_LOAN, // 45
|
||||
@@ -79,7 +79,7 @@ enum GAME_COMMAND {
|
||||
GAME_COMMAND_54,
|
||||
GAME_COMMAND_55,
|
||||
GAME_COMMAND_56, // Set land owned (possibly does other things)
|
||||
GAME_COMMAND_57
|
||||
GAME_COMMAND_CLEAR_SCENERY
|
||||
};
|
||||
|
||||
typedef void (GAME_COMMAND_POINTER)(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
|
||||
|
||||
@@ -854,7 +854,7 @@ static void game_handle_input_mouse(int x, int y, int state)
|
||||
1,
|
||||
ecx,
|
||||
(map_element->type & 0x3) | (map_element->base_height << 8),
|
||||
GAME_COMMAND_42,
|
||||
GAME_COMMAND_REMOVE_FENCE,
|
||||
0,
|
||||
0);
|
||||
}
|
||||
|
||||
@@ -652,6 +652,8 @@ enum {
|
||||
STR_STAFF_MECHANICS_TAB_TIP = 2211,
|
||||
STR_STAFF_SECURITY_TAB_TIP = 2212,
|
||||
STR_STAFF_ENTERTAINERS_TAB_TIP = 2213,
|
||||
|
||||
STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED = 2214,
|
||||
|
||||
STR_CELSIUS_VALUE = 2216,
|
||||
STR_FAHRENHEIT_VALUE = 2217,
|
||||
@@ -981,6 +983,7 @@ enum {
|
||||
|
||||
STR_NO_RECENT_AWARDS = 2848,
|
||||
|
||||
STR_FORBIDDEN_BY_THE_LOCAL_AUTHORITY = 2853,
|
||||
STR_ENTRANCE_NOT_CONNECTED = 2854,
|
||||
STR_EXIT_NOT_CONNECTED = 2855,
|
||||
|
||||
|
||||
@@ -106,9 +106,11 @@ static void window_game_top_toolbar_emptysub() { }
|
||||
static void window_game_top_toolbar_mouseup();
|
||||
static void window_game_top_toolbar_mousedown(int widgetIndex, rct_window*w, rct_widget* widget);
|
||||
static void window_game_top_toolbar_dropdown();
|
||||
static void window_game_top_toolbar_tool_update();
|
||||
static void window_game_top_toolbar_tool_down();
|
||||
static void window_game_top_toolbar_tool_drag();
|
||||
static void window_game_top_toolbar_invalidate();
|
||||
static void window_game_top_toolbar_paint();
|
||||
static void window_game_top_toolbar_tool_down();
|
||||
|
||||
static void* window_game_top_toolbar_events[] = {
|
||||
window_game_top_toolbar_emptysub,
|
||||
@@ -120,9 +122,9 @@ static void* window_game_top_toolbar_events[] = {
|
||||
window_game_top_toolbar_emptysub,
|
||||
window_game_top_toolbar_emptysub,
|
||||
window_game_top_toolbar_emptysub,
|
||||
(void*)0x0066CB25, //Update
|
||||
window_game_top_toolbar_tool_update,
|
||||
window_game_top_toolbar_tool_down,
|
||||
(void*)0x0066CB4E,
|
||||
window_game_top_toolbar_tool_drag,
|
||||
(void*)0x0066CC5B,
|
||||
(void*)0x0066CA58,
|
||||
window_game_top_toolbar_emptysub,
|
||||
@@ -665,6 +667,34 @@ static void window_game_top_toolbar_scenery_tool_down(short x, short y, rct_wind
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x0066CB25
|
||||
*/
|
||||
static void window_game_top_toolbar_tool_update()
|
||||
{
|
||||
short widgetIndex;
|
||||
rct_window *w;
|
||||
short x, y;
|
||||
|
||||
window_tool_get_registers(w, widgetIndex, x, y);
|
||||
|
||||
switch (widgetIndex){
|
||||
case WIDX_CLEAR_SCENERY:
|
||||
RCT2_CALLPROC_X(0x0068E213, x, y, 0, widgetIndex, (int)w, 0, 0);
|
||||
break;
|
||||
case WIDX_LAND:
|
||||
RCT2_CALLPROC_X(0x00664280, x, y, 0, widgetIndex, (int)w, 0, 0);
|
||||
break;
|
||||
case WIDX_WATER:
|
||||
RCT2_CALLPROC_X(0x006E6BDC, x, y, 0, widgetIndex, (int)w, 0, 0);
|
||||
break;
|
||||
case WIDX_SCENERY:
|
||||
RCT2_CALLPROC_X(0x006E287B, x, y, 0, widgetIndex, (int)w, 0, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* rct2: 0x0066CB73
|
||||
*/
|
||||
@@ -677,9 +707,8 @@ static void window_game_top_toolbar_tool_down(){
|
||||
|
||||
switch (widgetIndex){
|
||||
case WIDX_CLEAR_SCENERY:
|
||||
if (!RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16)&(1 << 0)){
|
||||
return;
|
||||
}
|
||||
if (!RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) & (1 << 0))
|
||||
break;
|
||||
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_STRING_ID, rct_string_id) = 3438;
|
||||
|
||||
@@ -688,10 +717,11 @@ static void window_game_top_toolbar_tool_down(){
|
||||
1,
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, uint16),
|
||||
0,
|
||||
GAME_COMMAND_57,
|
||||
GAME_COMMAND_CLEAR_SCENERY,
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, uint16),
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, uint16)
|
||||
);
|
||||
);
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TOOL, uint8) = 12;
|
||||
break;
|
||||
case WIDX_LAND:
|
||||
RCT2_CALLPROC_X(0x66CBF3, x, y, 0, widgetIndex, (int)w, 0, 0);
|
||||
@@ -703,4 +733,49 @@ static void window_game_top_toolbar_tool_down(){
|
||||
window_game_top_toolbar_scenery_tool_down(x, y, w, widgetIndex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x0066CB4E
|
||||
*/
|
||||
static void window_game_top_toolbar_tool_drag()
|
||||
{
|
||||
short widgetIndex;
|
||||
rct_window *w;
|
||||
short x, y;
|
||||
|
||||
window_tool_get_registers(w, widgetIndex, x, y);
|
||||
|
||||
switch (widgetIndex){
|
||||
case WIDX_CLEAR_SCENERY:
|
||||
if (window_find_by_class(WC_ERROR) != NULL)
|
||||
break;
|
||||
|
||||
if (!RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) & (1 << 0))
|
||||
break;
|
||||
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_STRING_ID, rct_string_id) = 3438;
|
||||
|
||||
game_do_command(
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, uint16),
|
||||
1,
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, uint16),
|
||||
0,
|
||||
GAME_COMMAND_CLEAR_SCENERY,
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, uint16),
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, uint16)
|
||||
);
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TOOL, uint8) = 12;
|
||||
break;
|
||||
case WIDX_LAND:
|
||||
RCT2_CALLPROC_X(0x00664454, x, y, 0, widgetIndex, (int)w, 0, 0);
|
||||
break;
|
||||
case WIDX_WATER:
|
||||
RCT2_CALLPROC_X(0x006E6D4B, x, y, 0, widgetIndex, (int)w, 0, 0);
|
||||
break;
|
||||
case WIDX_SCENERY:
|
||||
RCT2_CALLPROC_X(0x006E2CBC, x, y, 0, widgetIndex, (int)w, 0, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -584,7 +584,7 @@ static void window_sign_small_mouseup()
|
||||
1 | ((map_element->type & 0x3) << 8),
|
||||
y,
|
||||
(map_element->base_height << 8) | (map_element->type & 0x3),
|
||||
GAME_COMMAND_42,
|
||||
GAME_COMMAND_REMOVE_FENCE,
|
||||
0,
|
||||
0);
|
||||
break;
|
||||
|
||||
186
src/world/map.c
186
src/world/map.c
@@ -20,8 +20,11 @@
|
||||
|
||||
#include "../addresses.h"
|
||||
#include "../localisation/date.h"
|
||||
#include "../localisation/localisation.h"
|
||||
#include "climate.h"
|
||||
#include "map.h"
|
||||
#include "park.h"
|
||||
#include "scenery.h"
|
||||
|
||||
int _sub_6A876D_save_x;
|
||||
int _sub_6A876D_save_y;
|
||||
@@ -455,4 +458,187 @@ int sub_664F72(int x, int y, int z){
|
||||
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = 0x6C1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006E0E01
|
||||
*/
|
||||
money32 map_try_clear_scenery(int x, int y, rct_map_element *mapElement, int flags)
|
||||
{
|
||||
money32 cost;
|
||||
rct_scenery_entry *entry;
|
||||
|
||||
entry = g_smallSceneryEntries[mapElement->properties.scenery.type];
|
||||
cost = entry->small_scenery.removal_price * 10;
|
||||
|
||||
RCT2_GLOBAL(0x0141F56C, uint8) = 12;
|
||||
RCT2_GLOBAL(0x009DEA5E, uint32) = x * 32 + 16;
|
||||
RCT2_GLOBAL(0x009DEA60, uint32) = y * 32 + 16;
|
||||
RCT2_GLOBAL(0x009DEA62, uint32) = mapElement->base_height * 8;
|
||||
|
||||
x *= 32;
|
||||
y *= 32;
|
||||
|
||||
if (!(flags & 0x40) && RCT2_GLOBAL(0x009DEA6E, uint8) != 0) {
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED;
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR) && !(flags & 0x40)) {
|
||||
// Check if allowed to remove item
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_FORBID_TREE_REMOVAL) {
|
||||
if (entry->small_scenery.height > 64) {
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_FORBIDDEN_BY_THE_LOCAL_AUTHORITY;
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the land is owned
|
||||
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR))
|
||||
if (sub_664F72(x, y, RCT2_GLOBAL(0x009DEA62, uint32)))
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
if ((flags & 0x40) && !(mapElement->flags & 0x10))
|
||||
return 0;
|
||||
|
||||
// Remove element
|
||||
if (flags & 1) {
|
||||
RCT2_CALLPROC_X(0x006EC6D7, x, 0, y, 0, 0, 0, 0);
|
||||
RCT2_CALLPROC_X(0x0068B280, 0, 0, 0, 0, (int)mapElement, 0, 0);
|
||||
}
|
||||
return RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY ? 0 : cost;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006E5597
|
||||
*/
|
||||
money32 sub_6E5597(int x, int y, int dl, int dh, int bl)
|
||||
{
|
||||
int eax, ebx, ecx, edx, esi, edi, ebp;
|
||||
eax = x * 32;
|
||||
ecx = y * 32;
|
||||
ebx = bl & 0xFF;
|
||||
edx = ((dh & 0xFF) << 8) | (dl & 0xFF);
|
||||
RCT2_CALLFUNC_X(0x006E5597, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
|
||||
return ebx;
|
||||
}
|
||||
|
||||
money32 sub_6A67C0(int x, int y, int z, int flags)
|
||||
{
|
||||
int eax, ebx, ecx, edx, esi, edi, ebp;
|
||||
eax = x * 32;
|
||||
ecx = y * 32;
|
||||
ebx = flags & 0xFF;
|
||||
edx = z & 0xFF;
|
||||
RCT2_CALLFUNC_X(0x006A67C0, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
|
||||
return ebx;
|
||||
}
|
||||
|
||||
// This will cause clear scenery to remove paths
|
||||
// This should be a flag for the game command which can be set via a checkbox on the clear scenery window.
|
||||
// #define CLEAR_SCENERY_REMOVES_PATHS
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x0068DFE4
|
||||
*/
|
||||
money32 map_clear_scenery_from_tile(int x, int y, int flags)
|
||||
{
|
||||
int type;
|
||||
money32 cost, totalCost;
|
||||
rct_map_element *mapElement;
|
||||
|
||||
totalCost = 0;
|
||||
|
||||
restart_from_beginning:
|
||||
mapElement = TILE_MAP_ELEMENT_POINTER(y * 256 + x);
|
||||
do {
|
||||
type = mapElement->type & MAP_ELEMENT_TYPE_MASK;
|
||||
switch (type) {
|
||||
case MAP_ELEMENT_TYPE_PATH:
|
||||
#ifdef CLEAR_SCENERY_REMOVES_PATHS
|
||||
cost = sub_6A67C0(x, y, mapElement->base_height, flags);
|
||||
if (cost == MONEY32_UNDEFINED)
|
||||
return MONEY32_UNDEFINED;
|
||||
|
||||
totalCost += cost;
|
||||
if (flags & 1)
|
||||
goto restart_from_beginning;
|
||||
#endif
|
||||
break;
|
||||
case MAP_ELEMENT_TYPE_SCENERY:
|
||||
cost = map_try_clear_scenery(x, y, mapElement, flags);
|
||||
if (cost == MONEY32_UNDEFINED)
|
||||
return MONEY32_UNDEFINED;
|
||||
|
||||
totalCost += cost;
|
||||
if (flags & 1)
|
||||
goto restart_from_beginning;
|
||||
|
||||
break;
|
||||
case MAP_ELEMENT_TYPE_FENCE:
|
||||
cost = sub_6E5597(x, y, mapElement->type & 3, mapElement->base_height, flags);
|
||||
if (cost == MONEY32_UNDEFINED)
|
||||
return MONEY32_UNDEFINED;
|
||||
|
||||
totalCost += cost;
|
||||
if (flags & 1)
|
||||
goto restart_from_beginning;
|
||||
|
||||
break;
|
||||
}
|
||||
} while (!((mapElement++)->flags & MAP_ELEMENT_FLAG_LAST_TILE));
|
||||
|
||||
return totalCost;
|
||||
}
|
||||
|
||||
money32 map_clear_scenery(int x0, int y0, int x1, int y1, int flags)
|
||||
{
|
||||
int x, y, z;
|
||||
money32 totalCost, cost;
|
||||
|
||||
RCT2_GLOBAL(0x0141F56C, uint8) = 12;
|
||||
|
||||
x = (x0 + x1) / 2 + 16;
|
||||
y = (y0 + y1) / 2 + 16;
|
||||
z = map_element_height(x, y);
|
||||
RCT2_GLOBAL(0x009DEA5E, uint16) = x;
|
||||
RCT2_GLOBAL(0x009DEA60, uint16) = y;
|
||||
RCT2_GLOBAL(0x009DEA62, uint16) = z;
|
||||
|
||||
x0 = clamp(0, x0, 255);
|
||||
y0 = clamp(0, y0, 255);
|
||||
x1 = clamp(0, x1, 255);
|
||||
y1 = clamp(0, y1, 255);
|
||||
|
||||
totalCost = 0;
|
||||
for (y = y0; y <= y1; y++) {
|
||||
for (x = x0; x <= x1; x++) {
|
||||
cost = map_clear_scenery_from_tile(x, y, flags);
|
||||
if (cost == MONEY32_UNDEFINED)
|
||||
return MONEY32_UNDEFINED;
|
||||
|
||||
totalCost += cost;
|
||||
}
|
||||
}
|
||||
|
||||
return totalCost;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x0068DF91
|
||||
*/
|
||||
void game_command_clear_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp)
|
||||
{
|
||||
*ebx = map_clear_scenery(
|
||||
(*eax & 0xFFFF) / 32,
|
||||
(*ecx & 0xFFFF) / 32,
|
||||
(*edi & 0xFFFF) / 32,
|
||||
(*ebp & 0xFFFF) / 32,
|
||||
*ebx & 0xFF
|
||||
);
|
||||
}
|
||||
@@ -209,6 +209,8 @@ int sub_664F72(int x, int y, int z);
|
||||
|
||||
void fountain_update_all();
|
||||
|
||||
void game_command_clear_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
|
||||
|
||||
#define GET_MAP_ELEMENT(x) (&(RCT2_ADDRESS(RCT2_ADDRESS_MAP_ELEMENTS, rct_map_element)[x]))
|
||||
#define TILE_MAP_ELEMENT_POINTER(x) (RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[x])
|
||||
|
||||
|
||||
@@ -28,7 +28,8 @@ typedef struct {
|
||||
uint8 height; // 0x0A
|
||||
uint8 tool_id; // 0x0B
|
||||
uint16 price; // 0x0C
|
||||
uint8 pad_0E[12];
|
||||
uint16 removal_price; // 0x0E
|
||||
uint8 pad_10[0x0A];
|
||||
uint8 scenery_tab_id; // 0x1A
|
||||
} rct_small_scenery_entry;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user