mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-15 11:03:00 +01:00
Merge pull request #5291 from duncanspumpkin/refactor_banner
Refactor Banner Map Element Functions
This commit is contained in:
@@ -20,12 +20,14 @@
|
||||
656F6C8E1E45BFC200E0F770 /* Version.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 656F6C8C1E45BFC200E0F770 /* Version.cpp */; };
|
||||
658F3D911E44A6C200388550 /* ParkImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 658F3D8F1E44A6C200388550 /* ParkImporter.cpp */; };
|
||||
6876808CD662C4B16392A9B4 /* Balloon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 437490DBD74ECF60C3363559 /* Balloon.cpp */; };
|
||||
689149B0417A68D6765F09CD /* banner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEEAE6E8AC49B6F288E69B40 /* banner.cpp */; };
|
||||
791166FB1D7486EF005912EA /* NetworkServerAdvertiser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 791166F91D7486EF005912EA /* NetworkServerAdvertiser.cpp */; };
|
||||
7D02D519C9A56A1FB9854FE7 /* Climate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 242F470FE91956ACA4078F6A /* Climate.cpp */; };
|
||||
85060FD31D8C17CC00DFA2B3 /* track_data_old.c in Sources */ = {isa = PBXBuildFile; fileRef = 8594C05F1D885CF600235E93 /* track_data_old.c */; };
|
||||
8594C0601D885CF600235E93 /* track_data_old.c in Sources */ = {isa = PBXBuildFile; fileRef = 8594C05F1D885CF600235E93 /* track_data_old.c */; };
|
||||
85B468FC1D96822F000F1DB5 /* paint_helpers.c in Sources */ = {isa = PBXBuildFile; fileRef = 85B468FB1D96822F000F1DB5 /* paint_helpers.c */; };
|
||||
85B468FD1D96822F000F1DB5 /* paint_helpers.c in Sources */ = {isa = PBXBuildFile; fileRef = 85B468FB1D96822F000F1DB5 /* paint_helpers.c */; };
|
||||
8DED2F20E0D63A1DCFCE0197 /* banner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEEAE6E8AC49B6F288E69B40 /* banner.cpp */; };
|
||||
C606CCBE1DB4054000FE4015 /* compat.c in Sources */ = {isa = PBXBuildFile; fileRef = C606CCAB1DB4054000FE4015 /* compat.c */; };
|
||||
C606CCBF1DB4054000FE4015 /* data.c in Sources */ = {isa = PBXBuildFile; fileRef = C606CCAC1DB4054000FE4015 /* data.c */; };
|
||||
C606CCC01DB4054000FE4015 /* FunctionCall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCAE1DB4054000FE4015 /* FunctionCall.cpp */; };
|
||||
@@ -415,6 +417,8 @@
|
||||
D44272971CC81B3200D84D28 /* viewport.c in Sources */ = {isa = PBXBuildFile; fileRef = D44271D61CC81B3200D84D28 /* viewport.c */; };
|
||||
D44272981CC81B3200D84D28 /* water.c in Sources */ = {isa = PBXBuildFile; fileRef = D44271D71CC81B3200D84D28 /* water.c */; };
|
||||
D442729A1CC81B3200D84D28 /* banner.c in Sources */ = {isa = PBXBuildFile; fileRef = D44271DA1CC81B3200D84D28 /* banner.c */; };
|
||||
D44272991CC81B3200D84D28 /* balloon.c in Sources */ = {isa = PBXBuildFile; fileRef = D44271D91CC81B3200D84D28 /* balloon.c */; };
|
||||
D442729B1CC81B3200D84D28 /* climate.c in Sources */ = {isa = PBXBuildFile; fileRef = D44271DC1CC81B3200D84D28 /* climate.c */; };
|
||||
D442729C1CC81B3200D84D28 /* duck.c in Sources */ = {isa = PBXBuildFile; fileRef = D44271DE1CC81B3200D84D28 /* duck.c */; };
|
||||
D442729D1CC81B3200D84D28 /* footpath.c in Sources */ = {isa = PBXBuildFile; fileRef = D44271E01CC81B3200D84D28 /* footpath.c */; };
|
||||
D442729E1CC81B3200D84D28 /* fountain.c in Sources */ = {isa = PBXBuildFile; fileRef = D44271E21CC81B3200D84D28 /* fountain.c */; };
|
||||
@@ -994,6 +998,7 @@
|
||||
D44271D61CC81B3200D84D28 /* viewport.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = viewport.c; sourceTree = "<group>"; };
|
||||
D44271D71CC81B3200D84D28 /* water.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = water.c; sourceTree = "<group>"; };
|
||||
D44271DA1CC81B3200D84D28 /* banner.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = banner.c; sourceTree = "<group>"; };
|
||||
D44271D91CC81B3200D84D28 /* balloon.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = balloon.c; sourceTree = "<group>"; };
|
||||
D44271DB1CC81B3200D84D28 /* banner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = banner.h; sourceTree = "<group>"; };
|
||||
D44271DE1CC81B3200D84D28 /* duck.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = duck.c; sourceTree = "<group>"; };
|
||||
D44271DF1CC81B3200D84D28 /* entrance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = entrance.h; sourceTree = "<group>"; };
|
||||
@@ -1243,6 +1248,7 @@
|
||||
D4F5B5ED1DAD8A4300AB6075 /* Cursors.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Cursors.cpp; sourceTree = "<group>"; };
|
||||
D4F5B5EE1DAD8A4300AB6075 /* Cursors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Cursors.h; sourceTree = "<group>"; };
|
||||
EC3C3FED9FA55B65F65D706F /* Climate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Climate.h; sourceTree = "<group>"; };
|
||||
DEEAE6E8AC49B6F288E69B40 /* banner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = banner.cpp; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@@ -2044,6 +2050,8 @@
|
||||
242F470FE91956ACA4078F6A /* Climate.cpp */,
|
||||
437490DBD74ECF60C3363559 /* Balloon.cpp */,
|
||||
D44271DA1CC81B3200D84D28 /* banner.c */,
|
||||
DEEAE6E8AC49B6F288E69B40 /* banner.cpp */,
|
||||
D44271D91CC81B3200D84D28 /* balloon.c */,
|
||||
D44271DB1CC81B3200D84D28 /* banner.h */,
|
||||
D44271DE1CC81B3200D84D28 /* duck.c */,
|
||||
D48ABAB91E71EBD500A3E39C /* entrance.cpp */,
|
||||
@@ -2693,6 +2701,7 @@
|
||||
C64FDAAE1D6D9A2100F259B9 /* water_coaster.c in Sources */,
|
||||
6876808CD662C4B16392A9B4 /* Balloon.cpp in Sources */,
|
||||
7D02D519C9A56A1FB9854FE7 /* Climate.cpp in Sources */,
|
||||
689149B0417A68D6765F09CD /* banner.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -2722,7 +2731,6 @@
|
||||
C65A88921E1B1148000368D7 /* AudioChannel.cpp in Sources */,
|
||||
C686F91D1CDBC3B7009F9BFC /* multi_dimension_roller_coaster.c in Sources */,
|
||||
C686F8B31CDBC37E009F9BFC /* surface.c in Sources */,
|
||||
D442729A1CC81B3200D84D28 /* banner.c in Sources */,
|
||||
C650B21C1CCABC4400B4D91C /* ConvertCommand.cpp in Sources */,
|
||||
D44272211CC81B3200D84D28 /* viewport_interaction.c in Sources */,
|
||||
D442721B1CC81B3200D84D28 /* graph.c in Sources */,
|
||||
@@ -3052,6 +3060,7 @@
|
||||
D44272871CC81B3200D84D28 /* staff_list.c in Sources */,
|
||||
F61331C839858250899F1E9B /* Balloon.cpp in Sources */,
|
||||
F2CC500E17C9411FBA859888 /* Climate.cpp in Sources */,
|
||||
8DED2F20E0D63A1DCFCE0197 /* banner.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
||||
@@ -1139,7 +1139,7 @@ static sint32 cc_reset_user_strings(const utf8 **argv, sint32 argc)
|
||||
|
||||
static sint32 cc_fix_banner_count(const utf8 **argv, sint32 argc)
|
||||
{
|
||||
fix_banner_count();
|
||||
banner_reset_broken_index();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -336,6 +336,7 @@
|
||||
<ClCompile Include="windows\title_editor.c" />
|
||||
<ClCompile Include="windows\maze_construction.c" />
|
||||
<ClCompile Include="world\Balloon.cpp" />
|
||||
<ClCompile Include="world\banner.cpp" />
|
||||
<ClCompile Include="world\duck.c" />
|
||||
<ClCompile Include="world\entrance.cpp" />
|
||||
<ClCompile Include="world\money_effect.c" />
|
||||
@@ -405,7 +406,6 @@
|
||||
<ClCompile Include="windows\view_clipping.c" />
|
||||
<ClCompile Include="windows\viewport.c" />
|
||||
<ClCompile Include="windows\water.c" />
|
||||
<ClCompile Include="world\banner.c" />
|
||||
<ClCompile Include="world\Climate.cpp" />
|
||||
<ClCompile Include="world\footpath.c" />
|
||||
<ClCompile Include="world\fountain.c" />
|
||||
@@ -618,4 +618,4 @@
|
||||
<Image Include="..\..\resources\logo\icon.ico" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -1,169 +0,0 @@
|
||||
#pragma region Copyright (c) 2014-2016 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 "../game.h"
|
||||
#include "../localisation/localisation.h"
|
||||
#include "../ride/ride.h"
|
||||
#include "banner.h"
|
||||
#include "map.h"
|
||||
|
||||
rct_banner gBanners[MAX_BANNERS];
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006B9CB0
|
||||
*/
|
||||
void banner_init()
|
||||
{
|
||||
for (sint32 i = 0; i < MAX_BANNERS; i++) {
|
||||
gBanners[i].type = BANNER_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new banner and returns the index of the banner
|
||||
* If the flag GAME_COMMAND_FLAG_APPLY is NOT set then returns
|
||||
* the first unused index but does NOT mark the banner as created.
|
||||
* returns 0xFF on failure.
|
||||
*
|
||||
* rct2: 0x006BA278
|
||||
*/
|
||||
sint32 create_new_banner(uint8 flags)
|
||||
{
|
||||
sint32 banner_index = 0;
|
||||
for (; banner_index < MAX_BANNERS; banner_index++){
|
||||
if (gBanners[banner_index].type == BANNER_NULL){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (banner_index == MAX_BANNERS){
|
||||
gGameCommandErrorText = STR_TOO_MANY_BANNERS_IN_GAME;
|
||||
return BANNER_NULL;
|
||||
}
|
||||
|
||||
if (flags & GAME_COMMAND_FLAG_APPLY){
|
||||
rct_banner* banner = &gBanners[banner_index];
|
||||
|
||||
banner->flags = 0;
|
||||
banner->type = 0;
|
||||
banner->string_idx = STR_DEFAULT_SIGN;
|
||||
banner->colour = 2;
|
||||
banner->text_colour = 2;
|
||||
}
|
||||
return banner_index;
|
||||
}
|
||||
|
||||
rct_map_element *banner_get_map_element(sint32 bannerIndex)
|
||||
{
|
||||
rct_banner *banner = &gBanners[bannerIndex];
|
||||
rct_map_element *mapElement = map_get_first_element_at(banner->x, banner->y);
|
||||
do {
|
||||
if (map_element_get_banner_index(mapElement) == bannerIndex) {
|
||||
return mapElement;
|
||||
}
|
||||
} while (!map_element_is_last_for_tile(mapElement++));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006B7EAB
|
||||
*/
|
||||
static sint32 banner_get_ride_index_at(sint32 x, sint32 y, sint32 z)
|
||||
{
|
||||
rct_map_element *mapElement;
|
||||
rct_ride *ride;
|
||||
sint32 rideIndex, resultRideIndex;
|
||||
|
||||
resultRideIndex = -1;
|
||||
mapElement = map_get_first_element_at(x >> 5, y >> 5);
|
||||
do {
|
||||
if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_TRACK)
|
||||
continue;
|
||||
|
||||
rideIndex = mapElement->properties.track.ride_index;
|
||||
ride = get_ride(rideIndex);
|
||||
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IS_SHOP))
|
||||
continue;
|
||||
|
||||
if ((mapElement->clearance_height * 8) + 32 <= z)
|
||||
continue;
|
||||
|
||||
resultRideIndex = rideIndex;
|
||||
} while (!map_element_is_last_for_tile(mapElement++));
|
||||
|
||||
return resultRideIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006B7D86
|
||||
*/
|
||||
sint32 banner_get_closest_ride_index(sint32 x, sint32 y, sint32 z)
|
||||
{
|
||||
sint32 i, rideIndex;
|
||||
rct_ride *ride;
|
||||
|
||||
static const rct_xy16 NeighbourCheckOrder[] = {
|
||||
{ 32, 0 },
|
||||
{ -32, 0 },
|
||||
{ 0, 32 },
|
||||
{ 0, -32 },
|
||||
{ -32, +32 },
|
||||
{ +32, -32 },
|
||||
{ +32, +32 },
|
||||
{ -32, +32 },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
for (i = 0; i < countof(NeighbourCheckOrder); i++) {
|
||||
rideIndex = banner_get_ride_index_at(x + NeighbourCheckOrder[i].x, y + NeighbourCheckOrder[i].y, z);
|
||||
if (rideIndex != -1) {
|
||||
return rideIndex;
|
||||
}
|
||||
}
|
||||
|
||||
rideIndex = -1;
|
||||
sint32 resultDistance = INT_MAX;
|
||||
FOR_ALL_RIDES(i, ride) {
|
||||
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IS_SHOP))
|
||||
continue;
|
||||
|
||||
uint16 xy = ride->overall_view;
|
||||
if (xy == 0xFFFF)
|
||||
continue;
|
||||
|
||||
sint32 rideX = (xy & 0xFF) * 32;
|
||||
sint32 rideY = (xy >> 8) * 32;
|
||||
sint32 distance = abs(x - rideX) + abs(y - rideY);
|
||||
if (distance < resultDistance) {
|
||||
resultDistance = distance;
|
||||
rideIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
return rideIndex;
|
||||
}
|
||||
|
||||
void fix_banner_count()
|
||||
{
|
||||
for (sint32 banner_index = 0; banner_index < MAX_BANNERS; banner_index++){
|
||||
rct_map_element *map_element = banner_get_map_element(banner_index);
|
||||
if(map_element==NULL)
|
||||
gBanners[banner_index].type = BANNER_NULL;
|
||||
}
|
||||
}
|
||||
623
src/openrct2/world/banner.cpp
Normal file
623
src/openrct2/world/banner.cpp
Normal file
@@ -0,0 +1,623 @@
|
||||
#pragma region Copyright (c) 2014-2016 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/Math.hpp"
|
||||
#include "../core/Memory.hpp"
|
||||
#include "../core/Util.hpp"
|
||||
#include "../core/String.hpp"
|
||||
#include "../network/network.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "banner.h"
|
||||
#include "map.h"
|
||||
#include "park.h"
|
||||
#include "scenery.h"
|
||||
#include "../game.h"
|
||||
#include "../interface/window.h"
|
||||
#include "../localisation/localisation.h"
|
||||
#include "../ride/ride.h"
|
||||
}
|
||||
|
||||
rct_banner gBanners[MAX_BANNERS];
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006B7EAB
|
||||
*/
|
||||
static sint32 banner_get_ride_index_at(sint32 x, sint32 y, sint32 z)
|
||||
{
|
||||
rct_map_element *mapElement;
|
||||
rct_ride *ride;
|
||||
sint32 rideIndex, resultRideIndex;
|
||||
|
||||
resultRideIndex = -1;
|
||||
mapElement = map_get_first_element_at(x >> 5, y >> 5);
|
||||
do
|
||||
{
|
||||
if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_TRACK)
|
||||
continue;
|
||||
|
||||
rideIndex = mapElement->properties.track.ride_index;
|
||||
ride = get_ride(rideIndex);
|
||||
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IS_SHOP))
|
||||
continue;
|
||||
|
||||
if ((mapElement->clearance_height * 8) + 32 <= z)
|
||||
continue;
|
||||
|
||||
resultRideIndex = rideIndex;
|
||||
} while (!map_element_is_last_for_tile(mapElement++));
|
||||
|
||||
return resultRideIndex;
|
||||
}
|
||||
|
||||
static money32 BannerRemove(sint16 x, sint16 y, uint8 baseHeight, uint8 direction, uint8 flags)
|
||||
{
|
||||
sint32 z = baseHeight * 8;
|
||||
gCommandExpenditureType = RCT_EXPENDITURE_TYPE_LANDSCAPING;
|
||||
gCommandPosition.x = x + 16;
|
||||
gCommandPosition.y = y + 16;
|
||||
gCommandPosition.z = z;
|
||||
|
||||
if (!(flags & GAME_COMMAND_FLAG_GHOST) && game_is_paused() && !gCheatsBuildInPauseMode)
|
||||
{
|
||||
gGameCommandErrorText = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED;
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
if (!map_can_build_at(x, y, z - 16))
|
||||
{
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
// Slight modification to the code so that it now checks height as well
|
||||
// This was causing a bug with banners on two paths stacked.
|
||||
rct_map_element* mapElement = map_get_banner_element_at(x / 32, y / 32, baseHeight, direction);
|
||||
if (mapElement == nullptr)
|
||||
{
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
rct_banner *banner = &gBanners[mapElement->properties.banner.index];
|
||||
rct_scenery_entry *bannerEntry = get_banner_entry(banner->type);
|
||||
money32 refund = 0;
|
||||
if (bannerEntry != nullptr && bannerEntry != (rct_scenery_entry *)-1)
|
||||
{
|
||||
refund = -((bannerEntry->banner.price * 3) / 4);
|
||||
}
|
||||
|
||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
||||
{
|
||||
if (gGameCommandNestLevel == 1 && !(flags & GAME_COMMAND_FLAG_GHOST))
|
||||
{
|
||||
rct_xyz16 coord;
|
||||
coord.x = x + 16;
|
||||
coord.y = y + 16;
|
||||
coord.z = map_element_height(coord.x, coord.y);
|
||||
network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord);
|
||||
}
|
||||
|
||||
map_element_remove_banner_entry(mapElement);
|
||||
map_invalidate_tile_zoom1(x, y, z, z + 32);
|
||||
map_element_remove(mapElement);
|
||||
}
|
||||
|
||||
if (gParkFlags & PARK_FLAGS_NO_MONEY)
|
||||
{
|
||||
refund = 0;
|
||||
}
|
||||
return refund;
|
||||
}
|
||||
|
||||
static money32 BannerSetColour(sint16 x, sint16 y, uint8 baseHeight, uint8 direction, uint8 colour, uint8 flags)
|
||||
{
|
||||
gCommandExpenditureType = RCT_EXPENDITURE_TYPE_LANDSCAPING;
|
||||
sint32 z = (baseHeight * 8);
|
||||
gCommandPosition.x = x + 16;
|
||||
gCommandPosition.y = y + 16;
|
||||
gCommandPosition.z = z;
|
||||
|
||||
if (!map_can_build_at(x, y, z - 16))
|
||||
{
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
|
||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
||||
{
|
||||
rct_map_element* mapElement = map_get_first_element_at(x / 32, y / 32);
|
||||
|
||||
bool found = false;
|
||||
do
|
||||
{
|
||||
if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_BANNER)
|
||||
continue;
|
||||
|
||||
if (mapElement->properties.banner.position != direction)
|
||||
continue;
|
||||
|
||||
found = true;
|
||||
break;
|
||||
} while (!map_element_is_last_for_tile(mapElement++));
|
||||
|
||||
if (found == false)
|
||||
{
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
rct_window* window = window_find_by_number(WC_BANNER, mapElement->properties.banner.index);
|
||||
if (window != nullptr)
|
||||
{
|
||||
window_invalidate(window);
|
||||
}
|
||||
gBanners[mapElement->properties.banner.index].colour = colour;
|
||||
map_invalidate_tile_zoom1(x, y, z, z + 32);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static money32 BannerPlace(sint16 x, sint16 y, uint8 pathBaseHeight, uint8 direction, uint8 colour, uint8 type, uint8 *bannerIndex, uint8 flags)
|
||||
{
|
||||
gCommandPosition.x = x + 16;
|
||||
gCommandPosition.y = y + 16;
|
||||
gCommandPosition.z = pathBaseHeight * 16;
|
||||
gCommandExpenditureType = RCT_EXPENDITURE_TYPE_LANDSCAPING;
|
||||
if (game_is_paused() && !gCheatsBuildInPauseMode)
|
||||
{
|
||||
gGameCommandErrorText = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED;
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
if (!map_check_free_elements_and_reorganise(1))
|
||||
{
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
if (!map_is_location_valid(x, y))
|
||||
{
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
rct_map_element* mapElement = map_get_first_element_at(x / 32, y / 32);
|
||||
|
||||
bool pathFound = false;
|
||||
do
|
||||
{
|
||||
if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_PATH)
|
||||
continue;
|
||||
|
||||
if (mapElement->base_height != pathBaseHeight * 2 && mapElement->base_height != (pathBaseHeight - 1) * 2)
|
||||
continue;
|
||||
|
||||
if (!(mapElement->properties.path.edges & (1 << direction)))
|
||||
continue;
|
||||
|
||||
pathFound = true;
|
||||
break;
|
||||
} while (!map_element_is_last_for_tile(mapElement++));
|
||||
|
||||
if (pathFound == false)
|
||||
{
|
||||
gGameCommandErrorText = STR_CAN_ONLY_BE_BUILT_ACROSS_PATHS;
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
if (!map_can_build_at(x, y, pathBaseHeight * 16))
|
||||
{
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
uint8 baseHeight = (pathBaseHeight + 1) * 2;
|
||||
mapElement = map_get_banner_element_at(x / 32, y / 32, baseHeight, direction);
|
||||
if (mapElement != nullptr)
|
||||
{
|
||||
gGameCommandErrorText = STR_BANNER_SIGN_IN_THE_WAY;
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
*bannerIndex = create_new_banner(flags);
|
||||
if (*bannerIndex == BANNER_NULL)
|
||||
{
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
||||
{
|
||||
if (gGameCommandNestLevel == 1 && !(flags & GAME_COMMAND_FLAG_GHOST))
|
||||
{
|
||||
rct_xyz16 coord;
|
||||
coord.x = x + 16;
|
||||
coord.y = y + 16;
|
||||
coord.z = map_element_height(coord.x, coord.y);
|
||||
network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord);
|
||||
}
|
||||
|
||||
rct_map_element* newMapElement = map_element_insert(x / 32, y / 32, baseHeight, 0);
|
||||
assert(newMapElement != nullptr);
|
||||
gBanners[*bannerIndex].type = type;
|
||||
gBanners[*bannerIndex].colour = colour;
|
||||
gBanners[*bannerIndex].x = x / 32;
|
||||
gBanners[*bannerIndex].y = y / 32;
|
||||
newMapElement->type = MAP_ELEMENT_TYPE_BANNER;
|
||||
newMapElement->clearance_height = newMapElement->base_height + 2;
|
||||
newMapElement->properties.banner.position = direction;
|
||||
newMapElement->properties.banner.flags = 0xFF;
|
||||
newMapElement->properties.banner.unused = 0;
|
||||
newMapElement->properties.banner.index = *bannerIndex;
|
||||
if (flags & GAME_COMMAND_FLAG_GHOST)
|
||||
{
|
||||
newMapElement->flags |= MAP_ELEMENT_FLAG_GHOST;
|
||||
}
|
||||
map_invalidate_tile_full(x, y);
|
||||
map_animation_create(MAP_ANIMATION_TYPE_BANNER, x, y, newMapElement->base_height);
|
||||
}
|
||||
|
||||
rct_scenery_entry *bannerEntry = get_banner_entry(type);
|
||||
if ((bannerEntry == nullptr) || (bannerEntry == (rct_scenery_entry *)-1))
|
||||
{
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
if (gParkFlags & PARK_FLAGS_NO_MONEY)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return bannerEntry->banner.price;
|
||||
}
|
||||
|
||||
static money32 BannerSetName(uint8 bannerIndex,
|
||||
uint16 nameChunkIndex,
|
||||
uint32 nameChunk1,
|
||||
uint32 nameChunk2,
|
||||
uint32 nameChunk3,
|
||||
uint8 flags)
|
||||
{
|
||||
static char newName[128];
|
||||
|
||||
if (bannerIndex >= MAX_BANNERS)
|
||||
{
|
||||
log_warning("Invalid game command for setting banner name, banner id = %d", bannerIndex);
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
rct_banner* banner = &gBanners[bannerIndex];
|
||||
|
||||
gCommandExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_RUNNING_COSTS;
|
||||
size_t indexToOffset[3] = { 24, 12, 0 };
|
||||
|
||||
if (nameChunkIndex > Util::CountOf(indexToOffset))
|
||||
{
|
||||
log_warning("Invalid chunk index for setting banner name, banner id = %d, index = %d", bannerIndex, nameChunkIndex);
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
size_t nameChunkOffset = Math::Min<size_t>(indexToOffset[nameChunkIndex], Util::CountOf(newName) - 12);
|
||||
Memory::Copy<uint32>((uint32*)(&newName[0 + nameChunkOffset]), &nameChunk1, sizeof(uint32));
|
||||
Memory::Copy<uint32>((uint32*)(&newName[4 + nameChunkOffset]), &nameChunk2, sizeof(uint32));
|
||||
Memory::Copy<uint32>((uint32*)(&newName[8 + nameChunkOffset]), &nameChunk3, sizeof(uint32));
|
||||
|
||||
if (nameChunkIndex != 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(flags & GAME_COMMAND_FLAG_APPLY))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
utf8 *buffer = gCommonStringFormatBuffer;
|
||||
utf8 *dst = buffer;
|
||||
dst = utf8_write_codepoint(dst, FORMAT_COLOUR_CODE_START + banner->text_colour);
|
||||
String::Set(dst, 256, newName, 32);
|
||||
|
||||
rct_string_id stringId = user_string_allocate(128, buffer);
|
||||
if (stringId != 0)
|
||||
{
|
||||
rct_string_id prevStringId = banner->string_idx;
|
||||
banner->string_idx = stringId;
|
||||
user_string_free(prevStringId);
|
||||
rct_window* w = window_bring_to_front_by_number(WC_BANNER, bannerIndex);
|
||||
if (w != nullptr)
|
||||
{
|
||||
window_invalidate(w);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gGameCommandErrorText = STR_ERR_CANT_SET_BANNER_TEXT;
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static money32 BannerSetStyle(uint8 bannerIndex, uint8 colour, uint8 textColour, uint8 bannerFlags, uint8 flags)
|
||||
{
|
||||
if (bannerIndex >= MAX_BANNERS)
|
||||
{
|
||||
gGameCommandErrorText = STR_INVALID_SELECTION_OF_OBJECTS;
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
rct_banner* banner = &gBanners[bannerIndex];
|
||||
|
||||
rct_map_element* mapElement = banner_get_map_element(bannerIndex);
|
||||
|
||||
if (mapElement == nullptr)
|
||||
{
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
if (!(flags & GAME_COMMAND_FLAG_APPLY))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
banner->colour = colour;
|
||||
banner->text_colour = textColour;
|
||||
banner->flags = bannerFlags;
|
||||
|
||||
mapElement->properties.banner.flags = 0xFF;
|
||||
if (banner->flags & BANNER_FLAG_NO_ENTRY)
|
||||
{
|
||||
mapElement->properties.banner.flags &= ~(1 << mapElement->properties.banner.position);
|
||||
}
|
||||
|
||||
sint32 colourCodepoint = FORMAT_COLOUR_CODE_START + banner->text_colour;
|
||||
|
||||
utf8 buffer[256];
|
||||
format_string(buffer, 256, banner->string_idx, 0);
|
||||
sint32 firstCodepoint = utf8_get_next(buffer, nullptr);
|
||||
if (firstCodepoint >= FORMAT_COLOUR_CODE_START && firstCodepoint <= FORMAT_COLOUR_CODE_END)
|
||||
{
|
||||
utf8_write_codepoint(buffer, colourCodepoint);
|
||||
}
|
||||
else
|
||||
{
|
||||
utf8_insert_codepoint(buffer, colourCodepoint);
|
||||
}
|
||||
|
||||
rct_string_id stringId = user_string_allocate(128, buffer);
|
||||
if (stringId != 0)
|
||||
{
|
||||
rct_string_id prevStringId = banner->string_idx;
|
||||
banner->string_idx = stringId;
|
||||
user_string_free(prevStringId);
|
||||
rct_window* w = window_bring_to_front_by_number(WC_BANNER, bannerIndex);
|
||||
if (w != nullptr)
|
||||
{
|
||||
window_invalidate(w);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gGameCommandErrorText = STR_ERR_CANT_SET_BANNER_TEXT;
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8 BannerGetNewIndex() {
|
||||
uint8 bannerIndex = 0;
|
||||
for (; bannerIndex < MAX_BANNERS; bannerIndex++)
|
||||
{
|
||||
if (gBanners[bannerIndex].type == BANNER_NULL)
|
||||
{
|
||||
return bannerIndex;
|
||||
}
|
||||
}
|
||||
return BANNER_NULL;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006B9CB0
|
||||
*/
|
||||
void banner_init()
|
||||
{
|
||||
for (sint32 i = 0; i < MAX_BANNERS; i++)
|
||||
{
|
||||
gBanners[i].type = BANNER_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new banner and returns the index of the banner
|
||||
* If the flag GAME_COMMAND_FLAG_APPLY is NOT set then returns
|
||||
* the first unused index but does NOT mark the banner as created.
|
||||
* returns 0xFF on failure.
|
||||
*
|
||||
* rct2: 0x006BA278
|
||||
*/
|
||||
sint32 create_new_banner(uint8 flags)
|
||||
{
|
||||
uint8 bannerIndex = BannerGetNewIndex();
|
||||
|
||||
if (bannerIndex == BANNER_NULL)
|
||||
{
|
||||
gGameCommandErrorText = STR_TOO_MANY_BANNERS_IN_GAME;
|
||||
return BANNER_NULL;
|
||||
}
|
||||
|
||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
||||
{
|
||||
rct_banner* banner = &gBanners[bannerIndex];
|
||||
|
||||
banner->flags = 0;
|
||||
banner->type = 0;
|
||||
banner->string_idx = STR_DEFAULT_SIGN;
|
||||
banner->colour = 2;
|
||||
banner->text_colour = 2;
|
||||
}
|
||||
return bannerIndex;
|
||||
}
|
||||
|
||||
rct_map_element *banner_get_map_element(sint32 bannerIndex)
|
||||
{
|
||||
rct_banner *banner = &gBanners[bannerIndex];
|
||||
rct_map_element *mapElement = map_get_first_element_at(banner->x, banner->y);
|
||||
do
|
||||
{
|
||||
if (map_element_get_banner_index(mapElement) == bannerIndex)
|
||||
{
|
||||
return mapElement;
|
||||
}
|
||||
} while (!map_element_is_last_for_tile(mapElement++));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006B7D86
|
||||
*/
|
||||
sint32 banner_get_closest_ride_index(sint32 x, sint32 y, sint32 z)
|
||||
{
|
||||
sint32 i, rideIndex;
|
||||
rct_ride *ride;
|
||||
|
||||
static const rct_xy16 NeighbourCheckOrder[] =
|
||||
{
|
||||
{ 32, 0 },
|
||||
{ -32, 0 },
|
||||
{ 0, 32 },
|
||||
{ 0, -32 },
|
||||
{ -32, +32 },
|
||||
{ +32, -32 },
|
||||
{ +32, +32 },
|
||||
{ -32, +32 },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
for (i = 0; i < (sint32)Util::CountOf(NeighbourCheckOrder); i++)
|
||||
{
|
||||
rideIndex = banner_get_ride_index_at(x + NeighbourCheckOrder[i].x, y + NeighbourCheckOrder[i].y, z);
|
||||
if (rideIndex != -1)
|
||||
{
|
||||
return rideIndex;
|
||||
}
|
||||
}
|
||||
|
||||
rideIndex = -1;
|
||||
sint32 resultDistance = INT_MAX;
|
||||
FOR_ALL_RIDES(i, ride)
|
||||
{
|
||||
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IS_SHOP))
|
||||
continue;
|
||||
|
||||
uint16 xy = ride->overall_view;
|
||||
if (xy == 0xFFFF)
|
||||
continue;
|
||||
|
||||
sint32 rideX = (xy & 0xFF) * 32;
|
||||
sint32 rideY = (xy >> 8) * 32;
|
||||
sint32 distance = abs(x - rideX) + abs(y - rideY);
|
||||
if (distance < resultDistance)
|
||||
{
|
||||
resultDistance = distance;
|
||||
rideIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
return rideIndex;
|
||||
}
|
||||
|
||||
void banner_reset_broken_index()
|
||||
{
|
||||
for (sint32 bannerIndex = 0; bannerIndex < MAX_BANNERS; bannerIndex++)
|
||||
{
|
||||
rct_map_element *mapElement = banner_get_map_element(bannerIndex);
|
||||
if (mapElement == nullptr)
|
||||
gBanners[bannerIndex].type = BANNER_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006BA058
|
||||
*/
|
||||
void game_command_remove_banner(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp)
|
||||
{
|
||||
*ebx = BannerRemove(
|
||||
*eax & 0xFFFF,
|
||||
*ecx & 0xFFFF,
|
||||
*edx & 0xFF,
|
||||
(*edx >> 8) & 0xFF,
|
||||
*ebx & 0xFF
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006BA16A
|
||||
*/
|
||||
void game_command_set_banner_colour(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp)
|
||||
{
|
||||
*ebx = BannerSetColour(
|
||||
*eax & 0xFFFF,
|
||||
*ecx & 0xFFFF,
|
||||
*edx & 0xFF,
|
||||
(*edx >> 8) & 0xFF,
|
||||
*ebp & 0xFF,
|
||||
*ebx & 0xFF
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006B9E6D
|
||||
*/
|
||||
void game_command_place_banner(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp)
|
||||
{
|
||||
*ebx = BannerPlace(
|
||||
*eax & 0xFFFF,
|
||||
*ecx & 0xFFFF,
|
||||
*edx & 0xFF,
|
||||
(*edx >> 8) & 0xFF,
|
||||
*ebp & 0xFF,
|
||||
(*ebx >> 8) & 0xFF,
|
||||
(uint8 *)edi,
|
||||
*ebx & 0xFF
|
||||
);
|
||||
}
|
||||
|
||||
void game_command_set_banner_name(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp)
|
||||
{
|
||||
*ebx = BannerSetName(
|
||||
*ecx & 0xFF,
|
||||
*eax & 0xFFFF,
|
||||
*edx,
|
||||
*ebp,
|
||||
*edi,
|
||||
*ebx & 0xFF
|
||||
);
|
||||
}
|
||||
|
||||
void game_command_set_banner_style(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp)
|
||||
{
|
||||
*ebx = BannerSetStyle(
|
||||
*ecx & 0xFF,
|
||||
*edx & 0xFF,
|
||||
*edi & 0xFF,
|
||||
*ebp & 0xFF,
|
||||
*ebx & 0xFF
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,7 @@ enum{
|
||||
BANNER_FLAG_NO_ENTRY = (1 << 0),
|
||||
BANNER_FLAG_IS_LARGE_SCENERY = (1 << 1),
|
||||
BANNER_FLAG_LINKED_TO_RIDE = (1 << 2),
|
||||
BANNER_FLAG_4 = (1 << 3)
|
||||
BANNER_FLAG_IS_WALL = (1 << 3)
|
||||
};
|
||||
|
||||
extern rct_banner gBanners[MAX_BANNERS];
|
||||
@@ -49,7 +49,7 @@ void banner_init();
|
||||
sint32 create_new_banner(uint8 flags);
|
||||
rct_map_element *banner_get_map_element(sint32 bannerIndex);
|
||||
sint32 banner_get_closest_ride_index(sint32 x, sint32 y, sint32 z);
|
||||
void fix_banner_count();
|
||||
void banner_reset_broken_index();
|
||||
void game_command_callback_place_banner(sint32 eax, sint32 ebx, sint32 ecx, sint32 edx, sint32 esi, sint32 edi, sint32 ebp);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -788,6 +788,17 @@ bool map_is_location_valid(sint32 x, sint32 y)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool map_can_build_at(sint32 x, sint32 y, sint32 z)
|
||||
{
|
||||
if (gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR)
|
||||
return true;
|
||||
if (gCheatsSandboxMode)
|
||||
return true;
|
||||
if (map_is_location_owned(x, y, z))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x00664F72
|
||||
@@ -1089,69 +1100,6 @@ void game_command_remove_large_scenery(sint32* eax, sint32* ebx, sint32* ecx, si
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006BA058
|
||||
*/
|
||||
void game_command_remove_banner(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp)
|
||||
{
|
||||
sint32 x = *eax;
|
||||
sint32 y = *ecx;
|
||||
uint8 base_height = *edx;
|
||||
uint8 banner_position = *edx >> 8;
|
||||
uint8 flags = *ebx & 0xFF;
|
||||
sint32 z = base_height * 8;
|
||||
gCommandExpenditureType = RCT_EXPENDITURE_TYPE_LANDSCAPING;
|
||||
gCommandPosition.x = x + 16;
|
||||
gCommandPosition.y = y + 16;
|
||||
gCommandPosition.z = z;
|
||||
|
||||
if(!(flags & GAME_COMMAND_FLAG_GHOST) && game_is_paused() && !gCheatsBuildInPauseMode){
|
||||
gGameCommandErrorText = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED;
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
|
||||
if(!(gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) && !gCheatsSandboxMode && !map_is_location_owned(x, y, z - 16)){
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
|
||||
// Slight modification to the code so that it now checks height as well
|
||||
// This was causing a bug with banners on two paths stacked.
|
||||
rct_map_element* map_element = map_get_banner_element_at(x / 32, y / 32, base_height, banner_position);
|
||||
if (map_element == NULL){
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
|
||||
rct_banner *banner = &gBanners[map_element->properties.banner.index];
|
||||
rct_scenery_entry *scenery_entry = get_banner_entry(banner->type);
|
||||
money32 refund = 0;
|
||||
if (scenery_entry != NULL && scenery_entry != (rct_scenery_entry *)-1) {
|
||||
refund = -((scenery_entry->banner.price * 3) / 4);
|
||||
}
|
||||
|
||||
if (flags & GAME_COMMAND_FLAG_APPLY) {
|
||||
if (gGameCommandNestLevel == 1 && !(*ebx & GAME_COMMAND_FLAG_GHOST)) {
|
||||
rct_xyz16 coord;
|
||||
coord.x = x + 16;
|
||||
coord.y = y + 16;
|
||||
coord.z = map_element_height(coord.x, coord.y);
|
||||
network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord);
|
||||
}
|
||||
|
||||
map_element_remove_banner_entry(map_element);
|
||||
map_invalidate_tile_zoom1(x, y, z, z + 32);
|
||||
map_element_remove(map_element);
|
||||
}
|
||||
|
||||
*ebx = refund;
|
||||
if (gParkFlags & PARK_FLAGS_NO_MONEY) {
|
||||
*ebx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006E0F26
|
||||
@@ -1287,61 +1235,6 @@ void game_command_set_large_scenery_colour(sint32* eax, sint32* ebx, sint32* ecx
|
||||
*ebx = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006BA16A
|
||||
*/
|
||||
void game_command_set_banner_colour(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp)
|
||||
{
|
||||
gCommandExpenditureType = RCT_EXPENDITURE_TYPE_LANDSCAPING;
|
||||
sint32 x = *eax;
|
||||
sint32 y = *ecx;
|
||||
uint8 base_height = *edx;
|
||||
uint8 banner_position = *edx >> 8;
|
||||
uint8 colour = *ebp;
|
||||
sint32 z = (base_height * 8);
|
||||
gCommandPosition.x = x + 16;
|
||||
gCommandPosition.y = y + 16;
|
||||
gCommandPosition.z = z;
|
||||
|
||||
if (!(gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) && !gCheatsSandboxMode){
|
||||
if (!map_is_location_owned(x, y, z - 16)){
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(*ebx & GAME_COMMAND_FLAG_APPLY){
|
||||
rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32);
|
||||
|
||||
bool found = false;
|
||||
do {
|
||||
if (map_element_get_type(map_element) != MAP_ELEMENT_TYPE_BANNER)
|
||||
continue;
|
||||
|
||||
if (map_element->properties.banner.position != banner_position)
|
||||
continue;
|
||||
|
||||
found = true;
|
||||
break;
|
||||
} while (!map_element_is_last_for_tile(map_element++));
|
||||
|
||||
if (found == false){
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
|
||||
rct_window* window = window_find_by_number(WC_BANNER, map_element->properties.banner.index);
|
||||
if(window){
|
||||
window_invalidate(window);
|
||||
}
|
||||
gBanners[map_element->properties.banner.index].colour = colour;
|
||||
map_invalidate_tile_zoom1(x, y, z, z + 32);
|
||||
}
|
||||
|
||||
*ebx = 0;
|
||||
}
|
||||
|
||||
// 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
|
||||
@@ -2746,126 +2639,6 @@ void game_command_set_water_height(sint32* eax, sint32* ebx, sint32* ecx, sint32
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006B9E6D
|
||||
*/
|
||||
void game_command_place_banner(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp)
|
||||
{
|
||||
sint32 x = (uint16)*eax;
|
||||
sint32 y = (uint16)*ecx;
|
||||
uint8 base_height = *edx;
|
||||
uint8 edge = *edx >> 8;
|
||||
uint8 colour = *edi;
|
||||
uint8 type = *ebx >> 8;
|
||||
gCommandPosition.x = x + 16;
|
||||
gCommandPosition.y = y + 16;
|
||||
gCommandPosition.z = base_height * 16;
|
||||
gCommandExpenditureType = RCT_EXPENDITURE_TYPE_LANDSCAPING;
|
||||
if (game_is_paused() && !gCheatsBuildInPauseMode) {
|
||||
gGameCommandErrorText = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED;
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!map_check_free_elements_and_reorganise(1)) {
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
|
||||
if (x >= 8192 || y >= 8192) {
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
|
||||
rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32);
|
||||
sint32 dl = base_height * 2;
|
||||
sint32 ch = (base_height - 1) * 2;
|
||||
|
||||
bool pathFound = false;
|
||||
do {
|
||||
if (map_element_get_type(map_element) != MAP_ELEMENT_TYPE_PATH)
|
||||
continue;
|
||||
|
||||
if (map_element->base_height != dl && map_element->base_height != ch)
|
||||
continue;
|
||||
|
||||
if (!(map_element->properties.path.edges & (1 << edge)))
|
||||
continue;
|
||||
|
||||
pathFound = true;
|
||||
break;
|
||||
} while (!map_element_is_last_for_tile(map_element++));
|
||||
|
||||
if (pathFound == false) {
|
||||
gGameCommandErrorText = STR_CAN_ONLY_BE_BUILT_ACROSS_PATHS;
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
|
||||
if(!(gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) && !gCheatsSandboxMode && !map_is_location_owned(x, y, base_height * 16)){
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
map_element = map_get_first_element_at(x / 32, y / 32);
|
||||
dl = (base_height + 1) * 2;
|
||||
|
||||
// Check to see if there is a banner in the way
|
||||
do {
|
||||
if (map_element_get_type(map_element) != MAP_ELEMENT_TYPE_BANNER)
|
||||
continue;
|
||||
|
||||
if (map_element->base_height != dl)
|
||||
continue;
|
||||
|
||||
if ((map_element->properties.banner.position & 0x3) != edge)
|
||||
continue;
|
||||
|
||||
gGameCommandErrorText = STR_BANNER_SIGN_IN_THE_WAY;
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
return;
|
||||
} while (!map_element_is_last_for_tile(map_element++));
|
||||
|
||||
sint32 banner_index = create_new_banner(*ebx);
|
||||
if(banner_index == BANNER_NULL){
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
*edi = banner_index;
|
||||
if(*ebx & GAME_COMMAND_FLAG_APPLY){
|
||||
if (gGameCommandNestLevel == 1 && !(*ebx & GAME_COMMAND_FLAG_GHOST)) {
|
||||
rct_xyz16 coord;
|
||||
coord.x = x + 16;
|
||||
coord.y = y + 16;
|
||||
coord.z = map_element_height(coord.x, coord.y);
|
||||
network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord);
|
||||
}
|
||||
|
||||
rct_map_element* new_map_element = map_element_insert(x / 32, y / 32, (base_height + 1) * 2, 0);
|
||||
assert(new_map_element != NULL);
|
||||
gBanners[banner_index].type = type;
|
||||
gBanners[banner_index].colour = colour;
|
||||
gBanners[banner_index].x = x / 32;
|
||||
gBanners[banner_index].y = y / 32;
|
||||
new_map_element->type = MAP_ELEMENT_TYPE_BANNER;
|
||||
new_map_element->clearance_height = new_map_element->base_height + 2;
|
||||
new_map_element->properties.banner.position = edge;
|
||||
new_map_element->properties.banner.flags = 0xFF;
|
||||
new_map_element->properties.banner.unused = 0;
|
||||
new_map_element->properties.banner.index = banner_index;
|
||||
if(*ebx & GAME_COMMAND_FLAG_GHOST){
|
||||
new_map_element->flags |= MAP_ELEMENT_FLAG_GHOST;
|
||||
}
|
||||
map_invalidate_tile_full(x, y);
|
||||
map_animation_create(0x0A, x, y, new_map_element->base_height);
|
||||
}
|
||||
rct_scenery_entry *scenery_entry = (rct_scenery_entry*)object_entry_groups[OBJECT_TYPE_BANNERS].chunks[type];
|
||||
*ebx = scenery_entry->banner.price;
|
||||
if(gParkFlags & PARK_FLAGS_NO_MONEY){
|
||||
*ebx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006E0D6E, 0x006B8D88
|
||||
@@ -4580,62 +4353,6 @@ void map_clear_all_elements()
|
||||
}
|
||||
}
|
||||
|
||||
void game_command_set_banner_name(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp) {
|
||||
static char newName[128];
|
||||
|
||||
if ((*ecx >= MAX_BANNERS) || (*ecx < 0))
|
||||
{
|
||||
log_warning("Invalid game command for setting banner name, banner id = %d", *ecx);
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
rct_banner* banner = &gBanners[*ecx];
|
||||
|
||||
sint32 nameChunkIndex = *eax & 0xFFFF;
|
||||
|
||||
gCommandExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_RUNNING_COSTS;
|
||||
sint32 nameChunkOffset = nameChunkIndex - 1;
|
||||
if (nameChunkOffset < 0)
|
||||
nameChunkOffset = 2;
|
||||
nameChunkOffset *= 12;
|
||||
nameChunkOffset = min(nameChunkOffset, countof(newName) - 12);
|
||||
memcpy((void*)((uintptr_t)newName + (uintptr_t)nameChunkOffset + 0), edx, sizeof(uint32));
|
||||
memcpy((void*)((uintptr_t)newName + (uintptr_t)nameChunkOffset + 4), ebp, sizeof(uint32));
|
||||
memcpy((void*)((uintptr_t)newName + (uintptr_t)nameChunkOffset + 8), edi, sizeof(uint32));
|
||||
|
||||
if (nameChunkIndex != 0) {
|
||||
*ebx = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(*ebx & GAME_COMMAND_FLAG_APPLY)) {
|
||||
*ebx = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
utf8 *buffer = gCommonStringFormatBuffer;
|
||||
utf8 *dst = buffer;
|
||||
dst = utf8_write_codepoint(dst, FORMAT_COLOUR_CODE_START + banner->text_colour);
|
||||
safe_strcpy(dst, newName, 32);
|
||||
|
||||
rct_string_id stringId = user_string_allocate(128, buffer);
|
||||
if (stringId) {
|
||||
rct_string_id prev_string_id = banner->string_idx;
|
||||
banner->string_idx = stringId;
|
||||
user_string_free(prev_string_id);
|
||||
rct_window* w = window_bring_to_front_by_number(WC_BANNER, *ecx);
|
||||
if (w) {
|
||||
window_invalidate(w);
|
||||
}
|
||||
} else {
|
||||
gGameCommandErrorText = STR_ERR_CANT_SET_BANNER_TEXT;
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
|
||||
*ebx = 0;
|
||||
}
|
||||
|
||||
void game_command_set_sign_name(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp) {
|
||||
static char newName[128];
|
||||
|
||||
@@ -4705,82 +4422,6 @@ void game_command_set_sign_name(sint32* eax, sint32* ebx, sint32* ecx, sint32* e
|
||||
*ebx = 0;
|
||||
}
|
||||
|
||||
void game_command_set_banner_style(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp) {
|
||||
if ((*ecx >= MAX_BANNERS) || (*ecx < 0))
|
||||
{
|
||||
gGameCommandErrorText = STR_INVALID_SELECTION_OF_OBJECTS;
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(*ebx & GAME_COMMAND_FLAG_APPLY)) {
|
||||
*ebx = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
rct_banner* banner = &gBanners[*ecx];
|
||||
|
||||
banner->colour = (uint8)*edx;
|
||||
banner->text_colour = (uint8)*edi;
|
||||
banner->flags = (uint8)*ebp;
|
||||
|
||||
uint8 bannerIndex = *ecx & 0xFF;
|
||||
|
||||
sint32 x = banner->x << 5;
|
||||
sint32 y = banner->y << 5;
|
||||
|
||||
rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32);
|
||||
bool bannerFound = false;
|
||||
do {
|
||||
if (map_element_get_type(map_element) != MAP_ELEMENT_TYPE_BANNER)
|
||||
continue;
|
||||
|
||||
if (map_element->properties.banner.index != bannerIndex)
|
||||
continue;
|
||||
|
||||
bannerFound = true;
|
||||
break;
|
||||
} while (!map_element_is_last_for_tile(map_element++));
|
||||
|
||||
if (bannerFound == false) {
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
|
||||
map_element->properties.banner.flags = 0xFF;
|
||||
if (banner->flags & BANNER_FLAG_NO_ENTRY){
|
||||
map_element->properties.banner.flags &= ~(1 << map_element->properties.banner.position);
|
||||
}
|
||||
|
||||
sint32 colourCodepoint = FORMAT_COLOUR_CODE_START + banner->text_colour;
|
||||
|
||||
utf8 buffer[256];
|
||||
format_string(buffer, 256, banner->string_idx, 0);
|
||||
sint32 firstCodepoint = utf8_get_next(buffer, NULL);
|
||||
if (firstCodepoint >= FORMAT_COLOUR_CODE_START && firstCodepoint <= FORMAT_COLOUR_CODE_END) {
|
||||
utf8_write_codepoint(buffer, colourCodepoint);
|
||||
} else {
|
||||
utf8_insert_codepoint(buffer, colourCodepoint);
|
||||
}
|
||||
|
||||
rct_string_id stringId = user_string_allocate(128, buffer);
|
||||
if (stringId != 0) {
|
||||
rct_string_id prev_string_id = banner->string_idx;
|
||||
banner->string_idx = stringId;
|
||||
user_string_free(prev_string_id);
|
||||
rct_window* w = window_bring_to_front_by_number(WC_BANNER, *ecx);
|
||||
if (w) {
|
||||
window_invalidate(w);
|
||||
}
|
||||
} else {
|
||||
gGameCommandErrorText = STR_ERR_CANT_SET_BANNER_TEXT;
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
|
||||
*ebx = 0;
|
||||
}
|
||||
|
||||
void game_command_set_sign_style(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp) {
|
||||
uint8 bannerId = *ecx & 0xFF;
|
||||
rct_banner *banner = &gBanners[bannerId];
|
||||
|
||||
@@ -436,6 +436,7 @@ void map_remove_provisional_elements();
|
||||
void map_restore_provisional_elements();
|
||||
void map_update_path_wide_flags();
|
||||
bool map_is_location_valid(sint32 x, sint32 y);
|
||||
bool map_can_build_at(sint32 x, sint32 y, sint32 z);
|
||||
bool map_is_location_owned(sint32 x, sint32 y, sint32 z);
|
||||
bool map_is_location_in_park(sint32 x, sint32 y);
|
||||
bool map_is_location_owned_or_has_rights(sint32 x, sint32 y);
|
||||
|
||||
@@ -476,7 +476,7 @@ static money32 WallPlace(uint8 wallType,
|
||||
rct_banner * banner = &gBanners[bannerIndex];
|
||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
||||
{
|
||||
banner->flags |= BANNER_FLAG_4;
|
||||
banner->flags |= BANNER_FLAG_IS_WALL;
|
||||
banner->type = 0;
|
||||
banner->x = position.x / 32;
|
||||
banner->y = position.y / 32;
|
||||
|
||||
Reference in New Issue
Block a user