1
0
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:
IntelOrca
2014-11-04 03:34:12 +00:00
parent c75ae048a4
commit d92a4d9418
9 changed files with 283 additions and 16 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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