1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-26 16:24:35 +01:00

Initial attempt at getting place entrance into game action

This commit is contained in:
duncanspumpkin
2017-04-15 11:07:26 +01:00
committed by Michał Janiszewski
parent 8adcbd6e35
commit 1d3076a2af
5 changed files with 292 additions and 60 deletions

View File

@@ -36,10 +36,15 @@ enum class GA_ERROR : uint16
DISALLOWED,
GAME_PAUSED,
INSUFFICIENT_FUNDS,
NOT_IN_EDITOR_MODE,
NOT_OWNED,
TOO_LOW,
TOO_HIGH,
NO_CLEARANCE,
ITEM_ALREADY_PLACED,
NO_FREE_ELEMENTS,
UNKNOWN = UINT16_MAX,
};
@@ -48,6 +53,7 @@ namespace GA_FLAGS
{
constexpr uint16 ALLOW_WHILE_PAUSED = 1 << 0;
constexpr uint16 CLIENT_ONLY = 1 << 1;
constexpr uint16 EDITOR_ONLY = 1 << 2;
}
/**

View File

@@ -0,0 +1,284 @@
#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 "../core/MemoryStream.h"
#include "../localisation/string_ids.h"
#include "GameAction.h"
extern "C"
{
#include "../cheats.h"
#include "../world/entrance.h"
#include "../world/park.h"
#include "../world/footpath.h"
}
class PlaceParkEntranceAction : public IGameAction
{
public:
sint16 x;
sint16 y;
sint16 z;
uint8 direction;
uint16 GetFlags() const override
{
return GA_FLAGS::EDITOR_ONLY;
}
uint32 GetType() const override
{
return GAME_COMMAND_PLACE_PARK_ENTRANCE;
}
void Deserialise(IStream * stream) override
{
x = stream->ReadValue<sint16>();
y = stream->ReadValue<sint16>();
z = stream->ReadValue<sint16>();
direction = stream->ReadValue<uint8>();
}
void Serialise(IStream * stream) const override
{
stream->WriteValue(x);
stream->WriteValue(y);
stream->WriteValue(z);
stream->WriteValue(direction);
}
GameActionResult Query(uint32 flags = 0) const override
{
if (!(gScreenFlags & SCREEN_FLAGS_EDITOR) && !gCheatsSandboxMode)
{
return GameActionResult(GA_ERROR::NOT_IN_EDITOR_MODE, STR_NONE);
}
gCommandExpenditureType = RCT_EXPENDITURE_TYPE_LAND_PURCHASE;
gCommandPosition.x = x;
gCommandPosition.y = y;
gCommandPosition.z = z * 16;
if (!map_check_free_elements_and_reorganise(3))
{
return GameActionResult(GA_ERROR::NO_FREE_ELEMENTS, STR_NONE);
}
if (x <= 32 || y <= 32 || x >= (gMapSizeUnits - 32) || y >= (gMapSizeUnits - 32))
{
return GameActionResult(GA_ERROR::INVALID_PARAMETERS, STR_TOO_CLOSE_TO_EDGE_OF_MAP);
}
sint8 entranceNum = -1;
for (uint8 i = 0; i < MAX_PARK_ENTRANCES; ++i)
{
if (gParkEntrances[i].x == MAP_LOCATION_NULL)
{
entranceNum = i;
break;
}
}
if (entranceNum == -1)
{
return GameActionResult(GA_ERROR::INVALID_PARAMETERS, STR_ERR_TOO_MANY_PARK_ENTRANCES);
}
sint8 zLow = z * 2;
sint8 zHigh = zLow + 12;
rct_xy16 entranceLoc = { x, y };
for (uint8 index = 0; index < 3; index++)
{
if (index == 1)
{
entranceLoc.x += TileDirectionDelta[(direction - 1) & 0x3].x;
entranceLoc.y += TileDirectionDelta[(direction - 1) & 0x3].y;
}
else if (index == 2)
{
entranceLoc.x += TileDirectionDelta[(direction + 1) & 0x3].x * 2;
entranceLoc.y += TileDirectionDelta[(direction + 1) & 0x3].y * 2;
}
if (!gCheatsDisableClearanceChecks)
{
if (!map_can_construct_at(entranceLoc.x, entranceLoc.y, zLow, zHigh, 0xF))
{
return GameActionResult(GA_ERROR::NO_CLEARANCE, STR_NONE);
}
}
// Check that entrance element does not already exist at this location
rct_map_element* entranceElement = map_get_park_entrance_element_at(entranceLoc.x, entranceLoc.y, zLow, false);
if (entranceElement != NULL)
{
return GameActionResult(GA_ERROR::ITEM_ALREADY_PLACED, STR_NONE);
}
}
return GameActionResult();
}
GameActionResult Execute(uint32 flags = 0) const override
{
gCommandExpenditureType = RCT_EXPENDITURE_TYPE_LAND_PURCHASE;
gCommandPosition.x = x;
gCommandPosition.y = y;
gCommandPosition.z = z * 16;
sint8 entranceNum = -1;
for (uint8 i = 0; i < MAX_PARK_ENTRANCES; ++i)
{
if (gParkEntrances[i].x == MAP_LOCATION_NULL)
{
entranceNum = i;
break;
}
}
Guard::Assert(entranceNum != -1);
gParkEntrances[entranceNum].x = x;
gParkEntrances[entranceNum].y = y;
gParkEntrances[entranceNum].z = z * 16;
gParkEntrances[entranceNum].direction = direction;
sint8 zLow = z * 2;
sint8 zHigh = zLow + 12;
rct_xy16 entranceLoc = { x, y };
for (uint8 index = 0; index < 3; index++)
{
if (index == 1)
{
entranceLoc.x += TileDirectionDelta[(direction - 1) & 0x3].x;
entranceLoc.y += TileDirectionDelta[(direction - 1) & 0x3].y;
}
else if (index == 2)
{
entranceLoc.x += TileDirectionDelta[(direction + 1) & 0x3].x * 2;
entranceLoc.y += TileDirectionDelta[(direction + 1) & 0x3].y * 2;
}
if (!(flags & GAME_COMMAND_FLAG_GHOST))
{
rct_map_element* surfaceElement = map_get_surface_element_at(entranceLoc.x / 32, entranceLoc.y / 32);
surfaceElement->properties.surface.ownership = 0;
}
rct_map_element* newElement = map_element_insert(entranceLoc.x / 32, entranceLoc.y / 32, zLow, 0xF);
assert(newElement != NULL);
newElement->clearance_height = zHigh;
if (flags & GAME_COMMAND_FLAG_GHOST)
{
newElement->flags |= MAP_ELEMENT_FLAG_GHOST;
}
newElement->type = MAP_ELEMENT_TYPE_ENTRANCE;
newElement->type |= direction;
newElement->properties.entrance.index = index;
newElement->properties.entrance.type = ENTRANCE_TYPE_PARK_ENTRANCE;
newElement->properties.entrance.path_type = gFootpathSelectedId;
if (!(flags & GAME_COMMAND_FLAG_GHOST))
{
footpath_connect_edges(entranceLoc.x, entranceLoc.y, newElement, 1);
}
update_park_fences(entranceLoc.x, entranceLoc.y);
update_park_fences(entranceLoc.x - 32, entranceLoc.y);
update_park_fences(entranceLoc.x + 32, entranceLoc.y);
update_park_fences(entranceLoc.x, entranceLoc.y - 32);
update_park_fences(entranceLoc.x, entranceLoc.y + 32);
map_invalidate_tile(entranceLoc.x, entranceLoc.y, newElement->base_height * 8, newElement->clearance_height * 8);
if (index == 0)
{
map_animation_create(MAP_ANIMATION_TYPE_PARK_ENTRANCE, entranceLoc.x, entranceLoc.y, zLow);
}
}
return GameActionResult();
}
};
static auto Factory = GameActions::Register<PlaceParkEntranceAction>(GAME_COMMAND_PLACE_PARK_ENTRANCE);
extern "C"
{
/**
*
* rct2: 0x006666E7
*/
void game_command_place_park_entrance(sint32* eax,
sint32* ebx,
sint32* ecx,
sint32* edx,
sint32* esi,
sint32* edi,
sint32* ebp)
{
auto gameAction = PlaceParkEntranceAction();
gameAction.x = (*eax & 0xFFFF);
gameAction.y = (*ecx & 0xFFFF);
gameAction.z = (*edx & 0xFF);
gameAction.direction = ((*ebx >> 8) & 0xFF);
uint8 flags = (*ebx & 0xFF);
GameActionResult result;
if (flags & GAME_COMMAND_FLAG_APPLY) {
result = GameActions::Execute(&gameAction, flags);
}
else
{
result = GameActions::Query(&gameAction, flags);
}
if (result.Error != GA_ERROR::OK)
{
*ebx = MONEY32_UNDEFINED;
}
else
{
*ebx = result.Cost;
}
}
/**
*
* rct2: 0x00666F4E
*/
money32 park_entrance_place_ghost(sint32 x, sint32 y, sint32 z, sint32 direction)
{
park_entrance_remove_ghost();
auto gameAction = PlaceParkEntranceAction();
gameAction.x = x;
gameAction.y = y;
gameAction.z = z;
gameAction.direction = direction;
auto result = GameActions::Execute(&gameAction, GAME_COMMAND_FLAG_GHOST);
if (result.Error == GA_ERROR::OK)
{
gParkEntranceGhostPosition.x = x;
gParkEntranceGhostPosition.y = y;
gParkEntranceGhostPosition.z = z;
gParkEntranceGhostDirection = direction;
gParkEntranceGhostExists = true;
}
return result.Cost;
}
}

View File

@@ -1363,6 +1363,7 @@ void Network::ProcessGameCommandQueue()
IGameAction * action = GameActions::Create(gc.actionType);
uint32 flags = gc.parameters->ReadValue<uint32>();
action->Deserialise(gc.parameters);
delete gc.parameters;
GameActionResult result = GameActions::Execute(action, flags | GAME_COMMAND_FLAG_NETWORKED);
if (result.Error != GA_ERROR::OK)
{

View File

@@ -175,6 +175,7 @@ public:
std::string ServerProviderWebsite;
private:
<<<<<<< 8f169e5ce2dfbca82427a8ee4023704f0ea31e2c
bool ProcessConnection(NetworkConnection& connection);
void ProcessPacket(NetworkConnection& connection, NetworkPacket& packet);
void AddClient(ITcpSocket * socket);
@@ -204,12 +205,6 @@ private:
parameters = new MemoryStream(stream);
}
~GameCommand()
{
if (parameters != nullptr)
delete parameters;
}
uint32 tick;
uint32 eax, ebx, ecx, edx, esi, edi, ebp;
uint32 actionType = 0xFFFFFFFF;

View File

@@ -573,25 +573,6 @@ static money32 RideEntranceExitPlaceGhost(uint8 rideIndex, sint16 x, sint16 y, u
extern "C"
{
/**
*
* rct2: 0x006666E7
*/
void game_command_place_park_entrance(sint32* eax,
sint32* ebx,
sint32* ecx,
sint32* edx,
sint32* esi,
sint32* edi,
sint32* ebp)
{
*ebx = ParkEntrancePlace(
*ebx & 0xFF,
*eax & 0xFFFF,
*ecx & 0xFFFF,
*edx & 0xFF,
(*ebx >> 8) & 0xFF);
}
/**
*
@@ -633,41 +614,6 @@ extern "C"
}
}
/**
*
* rct2: 0x00666F4E
*/
money32 park_entrance_place_ghost(sint32 x, sint32 y, sint32 z, sint32 direction)
{
money32 result;
park_entrance_remove_ghost();
result = game_do_command(
x,
GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED |
GAME_COMMAND_FLAG_5 |
GAME_COMMAND_FLAG_GHOST |
GAME_COMMAND_FLAG_APPLY |
(direction << 8),
y,
z,
GAME_COMMAND_PLACE_PARK_ENTRANCE,
0,
0
);
if (result != MONEY32_UNDEFINED)
{
gParkEntranceGhostPosition.x = x;
gParkEntranceGhostPosition.y = y;
gParkEntranceGhostPosition.z = z;
gParkEntranceGhostDirection = direction;
gParkEntranceGhostExists = true;
}
return result;
}
sint32 park_entrance_get_index(sint32 x, sint32 y, sint32 z)
{
sint32 i;