mirror of https://github.com/OpenRCT2/OpenRCT2.git
clang-format world
This commit is contained in:
parent
adb69a2fe8
commit
5c55fd6132
|
@ -7,38 +7,36 @@
|
|||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "../network/network.h"
|
||||
|
||||
#include "../audio/audio.h"
|
||||
#include "../network/network.h"
|
||||
#include "../scenario/Scenario.h"
|
||||
#include "../util/Util.h"
|
||||
#include "Sprite.h"
|
||||
|
||||
bool rct_sprite::IsBalloon()
|
||||
{
|
||||
return this->balloon.sprite_identifier == SPRITE_IDENTIFIER_MISC &&
|
||||
this->balloon.misc_identifier == SPRITE_MISC_BALLOON;
|
||||
return this->balloon.sprite_identifier == SPRITE_IDENTIFIER_MISC && this->balloon.misc_identifier == SPRITE_MISC_BALLOON;
|
||||
}
|
||||
|
||||
rct_balloon * rct_sprite::AsBalloon()
|
||||
rct_balloon* rct_sprite::AsBalloon()
|
||||
{
|
||||
rct_balloon * result = nullptr;
|
||||
rct_balloon* result = nullptr;
|
||||
if (IsBalloon())
|
||||
{
|
||||
result = (rct_balloon *)this;
|
||||
result = (rct_balloon*)this;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void rct_balloon::Update()
|
||||
{
|
||||
invalidate_sprite_2((rct_sprite *)this);
|
||||
invalidate_sprite_2((rct_sprite*)this);
|
||||
if (popped == 1)
|
||||
{
|
||||
frame++;
|
||||
if (frame >= 5)
|
||||
{
|
||||
sprite_remove((rct_sprite *)this);
|
||||
sprite_remove((rct_sprite*)this);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -73,7 +71,7 @@ void rct_balloon::Press()
|
|||
else
|
||||
{
|
||||
int16_t shift = ((random & 0x80000000) ? -6 : 6);
|
||||
sprite_move(x + shift, y, z, (rct_sprite *)this);
|
||||
sprite_move(x + shift, y, z, (rct_sprite*)this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -87,7 +85,7 @@ void rct_balloon::Pop()
|
|||
|
||||
static money32 game_command_balloon_press(uint16_t spriteIndex, uint8_t flags)
|
||||
{
|
||||
rct_sprite * sprite = try_get_sprite(spriteIndex);
|
||||
rct_sprite* sprite = try_get_sprite(spriteIndex);
|
||||
if (sprite == nullptr || !sprite->IsBalloon())
|
||||
{
|
||||
log_error("Tried getting invalid sprite for balloon: %u", spriteIndex);
|
||||
|
@ -97,8 +95,7 @@ static money32 game_command_balloon_press(uint16_t spriteIndex, uint8_t flags)
|
|||
{
|
||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
||||
{
|
||||
sprite->AsBalloon()
|
||||
->Press();
|
||||
sprite->AsBalloon()->Press();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -122,19 +119,19 @@ void create_balloon(int32_t x, int32_t y, int32_t z, int32_t colour, bool isPopp
|
|||
}
|
||||
}
|
||||
|
||||
void balloon_update(rct_balloon * balloon)
|
||||
void balloon_update(rct_balloon* balloon)
|
||||
{
|
||||
balloon->Update();
|
||||
}
|
||||
|
||||
void game_command_balloon_press(
|
||||
int32_t * eax,
|
||||
int32_t * ebx,
|
||||
[[maybe_unused]] int32_t * ecx,
|
||||
[[maybe_unused]] int32_t * edx,
|
||||
[[maybe_unused]] int32_t * esi,
|
||||
[[maybe_unused]] int32_t * edi,
|
||||
[[maybe_unused]] int32_t * ebp)
|
||||
int32_t* eax,
|
||||
int32_t* ebx,
|
||||
[[maybe_unused]] int32_t* ecx,
|
||||
[[maybe_unused]] int32_t* edx,
|
||||
[[maybe_unused]] int32_t* esi,
|
||||
[[maybe_unused]] int32_t* edi,
|
||||
[[maybe_unused]] int32_t* ebp)
|
||||
{
|
||||
*ebx = game_command_balloon_press(*eax & 0xFFFF, *ebx & 0xFF);
|
||||
}
|
||||
|
|
|
@ -7,29 +7,29 @@
|
|||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||
*****************************************************************************/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
#include "Banner.h"
|
||||
|
||||
#include "../Context.h"
|
||||
#include "../Game.h"
|
||||
#include "../core/Math.hpp"
|
||||
#include "../core/Memory.hpp"
|
||||
#include "../core/Util.hpp"
|
||||
#include "../core/String.hpp"
|
||||
#include "../core/Util.hpp"
|
||||
#include "../interface/Window.h"
|
||||
#include "../localisation/Localisation.h"
|
||||
#include "../management/Finance.h"
|
||||
#include "../network/network.h"
|
||||
|
||||
#include "Banner.h"
|
||||
#include "../ride/Ride.h"
|
||||
#include "../ride/Track.h"
|
||||
#include "../windows/Intent.h"
|
||||
#include "Map.h"
|
||||
#include "MapAnimation.h"
|
||||
#include "Park.h"
|
||||
#include "Scenery.h"
|
||||
#include "../Game.h"
|
||||
#include "../interface/Window.h"
|
||||
#include "../localisation/Localisation.h"
|
||||
#include "../management/Finance.h"
|
||||
#include "../ride/Ride.h"
|
||||
#include "../ride/Track.h"
|
||||
#include "../windows/Intent.h"
|
||||
#include "../Context.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
|
||||
rct_banner gBanners[MAX_BANNERS];
|
||||
|
||||
|
@ -87,8 +87,8 @@ static money32 BannerRemove(int16_t x, int16_t y, uint8_t baseHeight, uint8_t di
|
|||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
rct_banner *banner = &gBanners[tileElement->properties.banner.index];
|
||||
rct_scenery_entry *bannerEntry = get_banner_entry(banner->type);
|
||||
rct_banner* banner = &gBanners[tileElement->properties.banner.index];
|
||||
rct_scenery_entry* bannerEntry = get_banner_entry(banner->type);
|
||||
money32 refund = 0;
|
||||
if (bannerEntry != nullptr)
|
||||
{
|
||||
|
@ -165,7 +165,14 @@ static money32 BannerSetColour(int16_t x, int16_t y, uint8_t baseHeight, uint8_t
|
|||
}
|
||||
|
||||
static money32 BannerPlace(
|
||||
int16_t x, int16_t y, uint8_t pathBaseHeight, uint8_t direction, uint8_t colour, uint8_t type, BannerIndex* bannerIndex, uint8_t flags)
|
||||
int16_t x,
|
||||
int16_t y,
|
||||
uint8_t pathBaseHeight,
|
||||
uint8_t direction,
|
||||
uint8_t colour,
|
||||
uint8_t type,
|
||||
BannerIndex* bannerIndex,
|
||||
uint8_t flags)
|
||||
{
|
||||
gCommandPosition.x = x + 16;
|
||||
gCommandPosition.y = y + 16;
|
||||
|
@ -182,7 +189,7 @@ static money32 BannerPlace(
|
|||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
if (!map_is_location_valid({x, y}))
|
||||
if (!map_is_location_valid({ x, y }))
|
||||
{
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
@ -261,7 +268,7 @@ static money32 BannerPlace(
|
|||
map_animation_create(MAP_ANIMATION_TYPE_BANNER, x, y, newTileElement->base_height);
|
||||
}
|
||||
|
||||
rct_scenery_entry *bannerEntry = get_banner_entry(type);
|
||||
rct_scenery_entry* bannerEntry = get_banner_entry(type);
|
||||
if (bannerEntry == nullptr)
|
||||
{
|
||||
return MONEY32_UNDEFINED;
|
||||
|
@ -358,7 +365,8 @@ static BannerIndex BannerGetNewIndex()
|
|||
*/
|
||||
void banner_init()
|
||||
{
|
||||
for (auto &banner : gBanners) {
|
||||
for (auto& banner : gBanners)
|
||||
{
|
||||
banner.type = BANNER_NULL;
|
||||
}
|
||||
}
|
||||
|
@ -396,8 +404,8 @@ BannerIndex create_new_banner(uint8_t flags)
|
|||
|
||||
rct_tile_element* banner_get_tile_element(BannerIndex bannerIndex)
|
||||
{
|
||||
rct_banner *banner = &gBanners[bannerIndex];
|
||||
rct_tile_element *tileElement = map_get_first_element_at(banner->x, banner->y);
|
||||
rct_banner* banner = &gBanners[bannerIndex];
|
||||
rct_tile_element* tileElement = map_get_first_element_at(banner->x, banner->y);
|
||||
do
|
||||
{
|
||||
if (tile_element_get_banner_index(tileElement) == bannerIndex)
|
||||
|
@ -414,20 +422,10 @@ rct_tile_element* banner_get_tile_element(BannerIndex bannerIndex)
|
|||
*/
|
||||
uint8_t banner_get_closest_ride_index(int32_t x, int32_t y, int32_t z)
|
||||
{
|
||||
Ride *ride;
|
||||
Ride* ride;
|
||||
|
||||
static constexpr const LocationXY16 NeighbourCheckOrder[] =
|
||||
{
|
||||
{ 32, 0 },
|
||||
{ -32, 0 },
|
||||
{ 0, 32 },
|
||||
{ 0, -32 },
|
||||
{ -32, +32 },
|
||||
{ +32, -32 },
|
||||
{ +32, +32 },
|
||||
{ -32, +32 },
|
||||
{ 0, 0 }
|
||||
};
|
||||
static constexpr const LocationXY16 NeighbourCheckOrder[]
|
||||
= { { 32, 0 }, { -32, 0 }, { 0, 32 }, { 0, -32 }, { -32, +32 }, { +32, -32 }, { +32, +32 }, { -32, +32 }, { 0, 0 } };
|
||||
|
||||
for (size_t i = 0; i < (int32_t)Util::CountOf(NeighbourCheckOrder); i++)
|
||||
{
|
||||
|
@ -441,7 +439,7 @@ uint8_t banner_get_closest_ride_index(int32_t x, int32_t y, int32_t z)
|
|||
uint8_t index;
|
||||
uint8_t rideIndex = RIDE_ID_NULL;
|
||||
int32_t resultDistance = std::numeric_limits<int32_t>::max();
|
||||
FOR_ALL_RIDES(index, ride)
|
||||
FOR_ALL_RIDES (index, ride)
|
||||
{
|
||||
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IS_SHOP))
|
||||
continue;
|
||||
|
@ -467,7 +465,7 @@ void banner_reset_broken_index()
|
|||
{
|
||||
for (BannerIndex bannerIndex = 0; bannerIndex < MAX_BANNERS; bannerIndex++)
|
||||
{
|
||||
rct_tile_element *tileElement = banner_get_tile_element(bannerIndex);
|
||||
rct_tile_element* tileElement = banner_get_tile_element(bannerIndex);
|
||||
if (tileElement == nullptr)
|
||||
gBanners[bannerIndex].type = BANNER_NULL;
|
||||
}
|
||||
|
@ -476,8 +474,8 @@ void banner_reset_broken_index()
|
|||
void fix_duplicated_banners()
|
||||
{
|
||||
// For each banner in the map, check if the banner index is in use already, and if so, create a new entry for it
|
||||
bool activeBanners[Util::CountOf(gBanners)]{};
|
||||
rct_tile_element * tileElement;
|
||||
bool activeBanners[Util::CountOf(gBanners)]{};
|
||||
rct_tile_element* tileElement;
|
||||
for (int y = 0; y < MAXIMUM_MAP_SIZE_TECHNICAL; y++)
|
||||
{
|
||||
for (int x = 0; x < MAXIMUM_MAP_SIZE_TECHNICAL; x++)
|
||||
|
@ -493,7 +491,10 @@ void fix_duplicated_banners()
|
|||
if (activeBanners[bannerIndex])
|
||||
{
|
||||
log_info(
|
||||
"Duplicated banner with index %d found at x = %d, y = %d and z = %d.", bannerIndex, x, y,
|
||||
"Duplicated banner with index %d found at x = %d, y = %d and z = %d.",
|
||||
bannerIndex,
|
||||
x,
|
||||
y,
|
||||
tileElement->base_height);
|
||||
|
||||
// Banner index is already in use by another banner, so duplicate it
|
||||
|
@ -506,10 +507,10 @@ void fix_duplicated_banners()
|
|||
Guard::Assert(activeBanners[newBannerIndex] == false);
|
||||
|
||||
// Copy over the original banner, but update the location
|
||||
rct_banner & newBanner = gBanners[newBannerIndex];
|
||||
newBanner = gBanners[bannerIndex];
|
||||
newBanner.x = x;
|
||||
newBanner.y = y;
|
||||
rct_banner& newBanner = gBanners[newBannerIndex];
|
||||
newBanner = gBanners[bannerIndex];
|
||||
newBanner.x = x;
|
||||
newBanner.y = y;
|
||||
|
||||
// Duplicate user string too
|
||||
rct_string_id stringIdx = newBanner.string_idx;
|
||||
|
@ -542,21 +543,15 @@ void fix_duplicated_banners()
|
|||
* rct2: 0x006BA058
|
||||
*/
|
||||
void game_command_remove_banner(
|
||||
int32_t * eax,
|
||||
int32_t * ebx,
|
||||
int32_t * ecx,
|
||||
int32_t * edx,
|
||||
[[maybe_unused]] int32_t * esi,
|
||||
[[maybe_unused]] int32_t * edi,
|
||||
[[maybe_unused]] int32_t * ebp)
|
||||
int32_t* eax,
|
||||
int32_t* ebx,
|
||||
int32_t* ecx,
|
||||
int32_t* edx,
|
||||
[[maybe_unused]] int32_t* esi,
|
||||
[[maybe_unused]] int32_t* edi,
|
||||
[[maybe_unused]] int32_t* ebp)
|
||||
{
|
||||
*ebx = BannerRemove(
|
||||
*eax & 0xFFFF,
|
||||
*ecx & 0xFFFF,
|
||||
*edx & 0xFF,
|
||||
(*edx >> 8) & 0xFF,
|
||||
*ebx & 0xFF
|
||||
);
|
||||
*ebx = BannerRemove(*eax & 0xFFFF, *ecx & 0xFFFF, *edx & 0xFF, (*edx >> 8) & 0xFF, *ebx & 0xFF);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -564,22 +559,15 @@ void game_command_remove_banner(
|
|||
* rct2: 0x006BA16A
|
||||
*/
|
||||
void game_command_set_banner_colour(
|
||||
int32_t * eax,
|
||||
int32_t * ebx,
|
||||
int32_t * ecx,
|
||||
int32_t * edx,
|
||||
[[maybe_unused]] int32_t * esi,
|
||||
[[maybe_unused]] int32_t * edi,
|
||||
int32_t * ebp)
|
||||
int32_t* eax,
|
||||
int32_t* ebx,
|
||||
int32_t* ecx,
|
||||
int32_t* edx,
|
||||
[[maybe_unused]] int32_t* esi,
|
||||
[[maybe_unused]] int32_t* edi,
|
||||
int32_t* ebp)
|
||||
{
|
||||
*ebx = BannerSetColour(
|
||||
*eax & 0xFFFF,
|
||||
*ecx & 0xFFFF,
|
||||
*edx & 0xFF,
|
||||
(*edx >> 8) & 0xFF,
|
||||
*ebp & 0xFF,
|
||||
*ebx & 0xFF
|
||||
);
|
||||
*ebx = BannerSetColour(*eax & 0xFFFF, *ecx & 0xFFFF, *edx & 0xFF, (*edx >> 8) & 0xFF, *ebp & 0xFF, *ebx & 0xFF);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -587,7 +575,7 @@ void game_command_set_banner_colour(
|
|||
* rct2: 0x006B9E6D
|
||||
*/
|
||||
void game_command_place_banner(
|
||||
int32_t * eax, int32_t * ebx, int32_t * ecx, int32_t * edx, [[maybe_unused]] int32_t * esi, int32_t * edi, int32_t * ebp)
|
||||
int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, [[maybe_unused]] int32_t* esi, int32_t* edi, int32_t* ebp)
|
||||
{
|
||||
*ebx = BannerPlace(
|
||||
*eax & 0xFFFF,
|
||||
|
@ -597,24 +585,17 @@ void game_command_place_banner(
|
|||
*ebp & 0xFF,
|
||||
(*ebx >> 8) & 0xFF,
|
||||
(BannerIndex*)edi,
|
||||
*ebx & 0xFF
|
||||
);
|
||||
*ebx & 0xFF);
|
||||
}
|
||||
|
||||
void game_command_set_banner_style(
|
||||
[[maybe_unused]] int32_t * eax,
|
||||
int32_t * ebx,
|
||||
int32_t * ecx,
|
||||
int32_t * edx,
|
||||
[[maybe_unused]] int32_t * esi,
|
||||
int32_t * edi,
|
||||
int32_t * ebp)
|
||||
[[maybe_unused]] int32_t* eax,
|
||||
int32_t* ebx,
|
||||
int32_t* ecx,
|
||||
int32_t* edx,
|
||||
[[maybe_unused]] int32_t* esi,
|
||||
int32_t* edi,
|
||||
int32_t* ebp)
|
||||
{
|
||||
*ebx = BannerSetStyle(
|
||||
*ecx & 0xFF,
|
||||
*edx & 0xFF,
|
||||
*edi & 0xFF,
|
||||
*ebp & 0xFF,
|
||||
*ebx & 0xFF
|
||||
);
|
||||
*ebx = BannerSetStyle(*ecx & 0xFF, *edx & 0xFF, *edi & 0xFF, *ebp & 0xFF, *ebx & 0xFF);
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ constexpr BannerIndex BANNER_INDEX_NULL = (BannerIndex)-1;
|
|||
struct rct_banner
|
||||
{
|
||||
uint8_t type;
|
||||
uint8_t flags; // 0x01
|
||||
uint8_t flags; // 0x01
|
||||
rct_string_id string_idx; // 0x02
|
||||
union
|
||||
{
|
||||
|
@ -50,4 +50,5 @@ rct_tile_element* banner_get_tile_element(BannerIndex bannerIndex);
|
|||
uint8_t banner_get_closest_ride_index(int32_t x, int32_t y, int32_t z);
|
||||
void banner_reset_broken_index();
|
||||
void fix_duplicated_banners();
|
||||
void game_command_callback_place_banner(int32_t eax, int32_t ebx, int32_t ecx, int32_t edx, int32_t esi, int32_t edi, int32_t ebp);
|
||||
void game_command_callback_place_banner(
|
||||
int32_t eax, int32_t ebx, int32_t ecx, int32_t edx, int32_t esi, int32_t edi, int32_t ebp);
|
||||
|
|
|
@ -7,23 +7,24 @@
|
|||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "../audio/audio.h"
|
||||
#include "../audio/AudioMixer.h"
|
||||
#include "Climate.h"
|
||||
|
||||
#include "../Cheats.h"
|
||||
#include "../Context.h"
|
||||
#include "../Game.h"
|
||||
#include "../OpenRCT2.h"
|
||||
#include "../audio/AudioMixer.h"
|
||||
#include "../audio/audio.h"
|
||||
#include "../config/Config.h"
|
||||
#include "../core/Math.hpp"
|
||||
#include "../core/Util.hpp"
|
||||
#include "../drawing/Drawing.h"
|
||||
#include "../Game.h"
|
||||
#include "../interface/Window.h"
|
||||
#include "../localisation/Date.h"
|
||||
#include "../OpenRCT2.h"
|
||||
#include "../scenario/Scenario.h"
|
||||
#include "../sprites.h"
|
||||
#include "../util/Util.h"
|
||||
#include "Climate.h"
|
||||
#include "../windows/Intent.h"
|
||||
#include "../Context.h"
|
||||
|
||||
constexpr int32_t MAX_THUNDER_INSTANCES = 2;
|
||||
|
||||
|
@ -40,26 +41,26 @@ struct WeatherTransition
|
|||
int8_t Distribution[24];
|
||||
};
|
||||
|
||||
extern const WeatherTransition * ClimateTransitions[4];
|
||||
extern const WeatherState ClimateWeatherData[6];
|
||||
extern const FILTER_PALETTE_ID ClimateWeatherGloomColours[4];
|
||||
extern const WeatherTransition* ClimateTransitions[4];
|
||||
extern const WeatherState ClimateWeatherData[6];
|
||||
extern const FILTER_PALETTE_ID ClimateWeatherGloomColours[4];
|
||||
|
||||
// Climate data
|
||||
uint8_t gClimate;
|
||||
ClimateState gClimateCurrent;
|
||||
ClimateState gClimateNext;
|
||||
uint16_t gClimateUpdateTimer;
|
||||
uint16_t gClimateLightningFlash;
|
||||
uint8_t gClimate;
|
||||
ClimateState gClimateCurrent;
|
||||
ClimateState gClimateNext;
|
||||
uint16_t gClimateUpdateTimer;
|
||||
uint16_t gClimateLightningFlash;
|
||||
|
||||
// Sound data
|
||||
static int32_t _rainVolume = 1;
|
||||
static uint32_t _lightningTimer;
|
||||
static uint32_t _thunderTimer;
|
||||
static void * _thunderSoundChannels[MAX_THUNDER_INSTANCES];
|
||||
static THUNDER_STATUS _thunderStatus[MAX_THUNDER_INSTANCES] = { THUNDER_STATUS::NONE, THUNDER_STATUS::NONE };
|
||||
static uint32_t _thunderSoundId;
|
||||
static int32_t _thunderVolume;
|
||||
static int32_t _thunderStereoEcho = 0;
|
||||
static int32_t _rainVolume = 1;
|
||||
static uint32_t _lightningTimer;
|
||||
static uint32_t _thunderTimer;
|
||||
static void* _thunderSoundChannels[MAX_THUNDER_INSTANCES];
|
||||
static THUNDER_STATUS _thunderStatus[MAX_THUNDER_INSTANCES] = { THUNDER_STATUS::NONE, THUNDER_STATUS::NONE };
|
||||
static uint32_t _thunderSoundId;
|
||||
static int32_t _thunderVolume;
|
||||
static int32_t _thunderStereoEcho = 0;
|
||||
|
||||
static int8_t climate_step_weather_level(int8_t currentWeatherLevel, int8_t nextWeatherLevel);
|
||||
static void climate_determine_future_weather(int32_t randomDistribution);
|
||||
|
@ -81,8 +82,8 @@ void climate_reset(int32_t climate)
|
|||
{
|
||||
uint8_t weather = WEATHER_PARTIALLY_CLOUDY;
|
||||
int32_t month = date_get_month(gDateMonthsElapsed);
|
||||
const WeatherTransition * transition = &ClimateTransitions[climate][month];
|
||||
const WeatherState * weatherState = &ClimateWeatherData[weather];
|
||||
const WeatherTransition* transition = &ClimateTransitions[climate][month];
|
||||
const WeatherState* weatherState = &ClimateWeatherData[weather];
|
||||
|
||||
gClimate = climate;
|
||||
gClimateCurrent.Weather = weather;
|
||||
|
@ -109,7 +110,8 @@ void climate_reset(int32_t climate)
|
|||
void climate_update()
|
||||
{
|
||||
// Only do climate logic if playing (not in scenario editor or title screen)
|
||||
if (gScreenFlags & (~SCREEN_FLAGS_PLAYING)) return;
|
||||
if (gScreenFlags & (~SCREEN_FLAGS_PLAYING))
|
||||
return;
|
||||
|
||||
if (!gCheatsFreezeClimate)
|
||||
{
|
||||
|
@ -141,12 +143,14 @@ void climate_update()
|
|||
}
|
||||
else if (gClimateNext.RainLevel <= RAIN_LEVEL_HEAVY)
|
||||
{
|
||||
gClimateCurrent.RainLevel = climate_step_weather_level(gClimateCurrent.RainLevel, gClimateNext.RainLevel);
|
||||
gClimateCurrent.RainLevel
|
||||
= climate_step_weather_level(gClimateCurrent.RainLevel, gClimateNext.RainLevel);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gClimateCurrent.WeatherGloom = climate_step_weather_level(gClimateCurrent.WeatherGloom, gClimateNext.WeatherGloom);
|
||||
gClimateCurrent.WeatherGloom
|
||||
= climate_step_weather_level(gClimateCurrent.WeatherGloom, gClimateNext.WeatherGloom);
|
||||
gfx_invalidate_screen();
|
||||
}
|
||||
}
|
||||
|
@ -157,7 +161,6 @@ void climate_update()
|
|||
context_broadcast_intent(&intent);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (_thunderTimer != 0)
|
||||
|
@ -193,13 +196,16 @@ void climate_force_weather(uint8_t weather)
|
|||
gfx_invalidate_screen();
|
||||
}
|
||||
|
||||
|
||||
void climate_update_sound()
|
||||
{
|
||||
if (gAudioCurrentDevice == -1) return;
|
||||
if (gGameSoundsOff) return;
|
||||
if (!gConfigSound.sound_enabled) return;
|
||||
if (gScreenFlags & SCREEN_FLAGS_TITLE_DEMO) return;
|
||||
if (gAudioCurrentDevice == -1)
|
||||
return;
|
||||
if (gGameSoundsOff)
|
||||
return;
|
||||
if (!gConfigSound.sound_enabled)
|
||||
return;
|
||||
if (gScreenFlags & SCREEN_FLAGS_TITLE_DEMO)
|
||||
return;
|
||||
|
||||
climate_update_rain_sound();
|
||||
climate_update_thunder_sound();
|
||||
|
@ -210,7 +216,7 @@ bool climate_is_raining()
|
|||
return gClimateCurrent.RainLevel != RAIN_LEVEL_NONE;
|
||||
}
|
||||
|
||||
FILTER_PALETTE_ID climate_get_weather_gloom_palette_id(const ClimateState &state)
|
||||
FILTER_PALETTE_ID climate_get_weather_gloom_palette_id(const ClimateState& state)
|
||||
{
|
||||
auto paletteId = PALETTE_NULL;
|
||||
auto gloom = state.WeatherGloom;
|
||||
|
@ -221,7 +227,7 @@ FILTER_PALETTE_ID climate_get_weather_gloom_palette_id(const ClimateState &state
|
|||
return paletteId;
|
||||
}
|
||||
|
||||
uint32_t climate_get_weather_sprite_id(const ClimateState &state)
|
||||
uint32_t climate_get_weather_sprite_id(const ClimateState& state)
|
||||
{
|
||||
uint32_t spriteId = SPR_WEATHER_SUN;
|
||||
if (state.Weather < Util::CountOf(ClimateWeatherData))
|
||||
|
@ -244,17 +250,18 @@ static int8_t climate_step_weather_level(int8_t currentWeatherLevel, int8_t next
|
|||
}
|
||||
|
||||
/**
|
||||
* Calculates future weather development.
|
||||
* RCT2 implements this as discrete probability distributions dependant on month and climate
|
||||
* for nextWeather. The other weather parameters are then looked up depending only on the
|
||||
* next weather.
|
||||
*/
|
||||
* Calculates future weather development.
|
||||
* RCT2 implements this as discrete probability distributions dependant on month and climate
|
||||
* for nextWeather. The other weather parameters are then looked up depending only on the
|
||||
* next weather.
|
||||
*/
|
||||
static void climate_determine_future_weather(int32_t randomDistribution)
|
||||
{
|
||||
int8_t month = date_get_month(gDateMonthsElapsed);
|
||||
|
||||
// Generate a random variable with values 0 up to DistributionSize-1 and chose weather from the distribution table accordingly
|
||||
const WeatherTransition * transition = &ClimateTransitions[gClimate][month];
|
||||
// Generate a random variable with values 0 up to DistributionSize-1 and chose weather from the distribution table
|
||||
// accordingly
|
||||
const WeatherTransition* transition = &ClimateTransitions[gClimate][month];
|
||||
int8_t nextWeather = transition->Distribution[((randomDistribution & 0xFF) * transition->DistributionSize) >> 8];
|
||||
gClimateNext.Weather = nextWeather;
|
||||
|
||||
|
@ -269,8 +276,7 @@ static void climate_determine_future_weather(int32_t randomDistribution)
|
|||
|
||||
static void climate_update_rain_sound()
|
||||
{
|
||||
if (gClimateCurrent.WeatherEffect == WEATHER_EFFECT_RAIN ||
|
||||
gClimateCurrent.WeatherEffect == WEATHER_EFFECT_STORM)
|
||||
if (gClimateCurrent.WeatherEffect == WEATHER_EFFECT_RAIN || gClimateCurrent.WeatherEffect == WEATHER_EFFECT_STORM)
|
||||
{
|
||||
// Start playing the rain sound
|
||||
if (gRainSoundChannel == nullptr)
|
||||
|
@ -324,7 +330,7 @@ static void climate_update_thunder_sound()
|
|||
{
|
||||
if (_thunderStatus[i] != THUNDER_STATUS::NONE)
|
||||
{
|
||||
void * channel = _thunderSoundChannels[i];
|
||||
void* channel = _thunderSoundChannels[i];
|
||||
if (!Mixer_Channel_IsPlaying(channel))
|
||||
{
|
||||
Mixer_Stop_Channel(channel);
|
||||
|
@ -336,9 +342,12 @@ static void climate_update_thunder_sound()
|
|||
|
||||
static void climate_update_lightning()
|
||||
{
|
||||
if (_lightningTimer == 0) return;
|
||||
if (gConfigGeneral.disable_lightning_effect) return;
|
||||
if (!gConfigGeneral.render_weather_effects && !gConfigGeneral.render_weather_gloom) return;
|
||||
if (_lightningTimer == 0)
|
||||
return;
|
||||
if (gConfigGeneral.disable_lightning_effect)
|
||||
return;
|
||||
if (!gConfigGeneral.render_weather_effects && !gConfigGeneral.render_weather_gloom)
|
||||
return;
|
||||
|
||||
_lightningTimer--;
|
||||
if (gClimateLightningFlash == 0)
|
||||
|
@ -358,8 +367,7 @@ static void climate_update_thunder()
|
|||
uint32_t randomNumber = util_rand();
|
||||
if (randomNumber & 0x10000)
|
||||
{
|
||||
if (_thunderStatus[0] == THUNDER_STATUS::NONE &&
|
||||
_thunderStatus[1] == THUNDER_STATUS::NONE)
|
||||
if (_thunderStatus[0] == THUNDER_STATUS::NONE && _thunderStatus[1] == THUNDER_STATUS::NONE)
|
||||
{
|
||||
// Play thunder on left side
|
||||
_thunderSoundId = (randomNumber & 0x20000) ? SOUND_THUNDER_1 : SOUND_THUNDER_2;
|
||||
|
@ -384,7 +392,8 @@ static void climate_update_thunder()
|
|||
|
||||
static void climate_play_thunder(int32_t instanceIndex, int32_t soundId, int32_t volume, int32_t pan)
|
||||
{
|
||||
_thunderSoundChannels[instanceIndex] = Mixer_Play_Effect(soundId, MIXER_LOOP_NONE, DStoMixerVolume(volume), DStoMixerPan(pan), 1, 0);
|
||||
_thunderSoundChannels[instanceIndex]
|
||||
= Mixer_Play_Effect(soundId, MIXER_LOOP_NONE, DStoMixerVolume(volume), DStoMixerPan(pan), 1, 0);
|
||||
if (_thunderSoundChannels[instanceIndex] != nullptr)
|
||||
{
|
||||
_thunderStatus[instanceIndex] = THUNDER_STATUS::PLAYING;
|
||||
|
@ -393,8 +402,7 @@ static void climate_play_thunder(int32_t instanceIndex, int32_t soundId, int32_t
|
|||
|
||||
#pragma region Climate / Weather data tables
|
||||
|
||||
const FILTER_PALETTE_ID ClimateWeatherGloomColours[4] =
|
||||
{
|
||||
const FILTER_PALETTE_ID ClimateWeatherGloomColours[4] = {
|
||||
PALETTE_NULL,
|
||||
PALETTE_DARKEN_1,
|
||||
PALETTE_DARKEN_2,
|
||||
|
@ -402,19 +410,17 @@ const FILTER_PALETTE_ID ClimateWeatherGloomColours[4] =
|
|||
};
|
||||
|
||||
// There is actually a sprite at 0x5A9C for snow but only these weather types seem to be fully implemented
|
||||
const WeatherState ClimateWeatherData[6] =
|
||||
{
|
||||
{ 10, WEATHER_EFFECT_NONE, 0, RAIN_LEVEL_NONE, SPR_WEATHER_SUN }, // Sunny
|
||||
{ 5, WEATHER_EFFECT_NONE, 0, RAIN_LEVEL_NONE, SPR_WEATHER_SUN_CLOUD }, // Partially Cloudy
|
||||
{ 0, WEATHER_EFFECT_NONE, 0, RAIN_LEVEL_NONE, SPR_WEATHER_CLOUD }, // Cloudy
|
||||
{ -2, WEATHER_EFFECT_RAIN, 1, RAIN_LEVEL_LIGHT, SPR_WEATHER_LIGHT_RAIN }, // Rain
|
||||
{ -4, WEATHER_EFFECT_RAIN, 2, RAIN_LEVEL_HEAVY, SPR_WEATHER_HEAVY_RAIN }, // Heavy Rain
|
||||
{ 2, WEATHER_EFFECT_STORM, 2, RAIN_LEVEL_HEAVY, SPR_WEATHER_STORM }, // Thunderstorm
|
||||
const WeatherState ClimateWeatherData[6] = {
|
||||
{ 10, WEATHER_EFFECT_NONE, 0, RAIN_LEVEL_NONE, SPR_WEATHER_SUN }, // Sunny
|
||||
{ 5, WEATHER_EFFECT_NONE, 0, RAIN_LEVEL_NONE, SPR_WEATHER_SUN_CLOUD }, // Partially Cloudy
|
||||
{ 0, WEATHER_EFFECT_NONE, 0, RAIN_LEVEL_NONE, SPR_WEATHER_CLOUD }, // Cloudy
|
||||
{ -2, WEATHER_EFFECT_RAIN, 1, RAIN_LEVEL_LIGHT, SPR_WEATHER_LIGHT_RAIN }, // Rain
|
||||
{ -4, WEATHER_EFFECT_RAIN, 2, RAIN_LEVEL_HEAVY, SPR_WEATHER_HEAVY_RAIN }, // Heavy Rain
|
||||
{ 2, WEATHER_EFFECT_STORM, 2, RAIN_LEVEL_HEAVY, SPR_WEATHER_STORM }, // Thunderstorm
|
||||
};
|
||||
|
||||
static constexpr const WeatherTransition ClimateTransitionsCoolAndWet[] =
|
||||
{
|
||||
{ 8, 18, { 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 0, 0, 0, 0, 0 } },
|
||||
static constexpr const WeatherTransition ClimateTransitionsCoolAndWet[] = {
|
||||
{ 8, 18, { 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 0, 0, 0, 0, 0 } },
|
||||
{ 10, 21, { 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 0, 0 } },
|
||||
{ 14, 17, { 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 0, 0, 0, 0, 0, 0 } },
|
||||
{ 17, 17, { 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 0, 0, 0, 0, 0, 0 } },
|
||||
|
@ -437,25 +443,24 @@ static constexpr const WeatherTransition ClimateTransitionsHotAndDry[] = {
|
|||
{ 12, 15, { 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0 } },
|
||||
{ 14, 12, { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
|
||||
{ 16, 11, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
|
||||
{ 19, 9, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
|
||||
{ 19, 9, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
|
||||
{ 21, 13, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
|
||||
{ 22, 11, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
|
||||
{ 21, 12, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
|
||||
{ 16, 13, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
|
||||
};
|
||||
static constexpr const WeatherTransition ClimateTransitionsCold[] = {
|
||||
{ 4, 18, { 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 4, 0, 0, 0, 0, 0 } },
|
||||
{ 5, 21, { 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5, 0, 0 } },
|
||||
{ 7, 17, { 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 4, 0, 0, 0, 0, 0, 0 } },
|
||||
{ 9, 17, { 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 0, 0, 0, 0, 0, 0 } },
|
||||
{ 4, 18, { 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 4, 0, 0, 0, 0, 0 } },
|
||||
{ 5, 21, { 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5, 0, 0 } },
|
||||
{ 7, 17, { 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 4, 0, 0, 0, 0, 0, 0 } },
|
||||
{ 9, 17, { 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 0, 0, 0, 0, 0, 0 } },
|
||||
{ 10, 23, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 4 } },
|
||||
{ 11, 23, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 4, 5 } },
|
||||
{ 9, 19, { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 4, 5, 0, 0, 0, 0 } },
|
||||
{ 6, 16, { 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0 } },
|
||||
{ 9, 19, { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 4, 5, 0, 0, 0, 0 } },
|
||||
{ 6, 16, { 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0 } },
|
||||
};
|
||||
|
||||
const WeatherTransition * ClimateTransitions[] =
|
||||
{
|
||||
const WeatherTransition* ClimateTransitions[] = {
|
||||
ClimateTransitionsCoolAndWet,
|
||||
ClimateTransitionsWarm,
|
||||
ClimateTransitionsHotAndDry,
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "../common.h"
|
||||
|
||||
#include "../drawing/Drawing.h"
|
||||
|
||||
enum CLIMATE
|
||||
|
@ -47,11 +46,11 @@ enum RAIN_LEVEL
|
|||
|
||||
struct WeatherState
|
||||
{
|
||||
int8_t TemperatureDelta;
|
||||
int8_t EffectLevel;
|
||||
int8_t GloomLevel;
|
||||
int8_t RainLevel;
|
||||
uint32_t SpriteId;
|
||||
int8_t TemperatureDelta;
|
||||
int8_t EffectLevel;
|
||||
int8_t GloomLevel;
|
||||
int8_t RainLevel;
|
||||
uint32_t SpriteId;
|
||||
};
|
||||
|
||||
struct ClimateState
|
||||
|
@ -63,11 +62,11 @@ struct ClimateState
|
|||
uint8_t RainLevel;
|
||||
};
|
||||
|
||||
extern uint8_t gClimate;
|
||||
extern uint8_t gClimate;
|
||||
extern ClimateState gClimateCurrent;
|
||||
extern ClimateState gClimateNext;
|
||||
extern uint16_t gClimateUpdateTimer;
|
||||
extern uint16_t gClimateLightningFlash;
|
||||
extern uint16_t gClimateUpdateTimer;
|
||||
extern uint16_t gClimateLightningFlash;
|
||||
|
||||
int32_t climate_celsius_to_fahrenheit(int32_t celsius);
|
||||
void climate_reset(int32_t climate);
|
||||
|
@ -76,5 +75,5 @@ void climate_update_sound();
|
|||
void climate_force_weather(uint8_t weather);
|
||||
|
||||
bool climate_is_raining();
|
||||
FILTER_PALETTE_ID climate_get_weather_gloom_palette_id(const ClimateState &state);
|
||||
uint32_t climate_get_weather_sprite_id(const ClimateState &state);
|
||||
FILTER_PALETTE_ID climate_get_weather_gloom_palette_id(const ClimateState& state);
|
||||
uint32_t climate_get_weather_sprite_id(const ClimateState& state);
|
||||
|
|
|
@ -7,18 +7,18 @@
|
|||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||
*****************************************************************************/
|
||||
|
||||
#include <limits>
|
||||
#include "../Game.h"
|
||||
#include "../audio/audio.h"
|
||||
#include "../core/Math.hpp"
|
||||
#include "../core/Util.hpp"
|
||||
#include "../sprites.h"
|
||||
|
||||
#include "../audio/audio.h"
|
||||
#include "../Game.h"
|
||||
#include "../localisation/Date.h"
|
||||
#include "../scenario/Scenario.h"
|
||||
#include "../sprites.h"
|
||||
#include "../world/Surface.h"
|
||||
#include "Sprite.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
// clang-format off
|
||||
enum DUCK_STATE
|
||||
{
|
||||
|
@ -76,38 +76,38 @@ static constexpr const uint8_t * DuckAnimations[] =
|
|||
|
||||
bool rct_sprite::IsDuck()
|
||||
{
|
||||
return this->duck.sprite_identifier == SPRITE_IDENTIFIER_MISC &&
|
||||
this->duck.misc_identifier == SPRITE_MISC_DUCK;
|
||||
return this->duck.sprite_identifier == SPRITE_IDENTIFIER_MISC && this->duck.misc_identifier == SPRITE_MISC_DUCK;
|
||||
}
|
||||
|
||||
rct_duck * rct_sprite::AsDuck()
|
||||
rct_duck* rct_sprite::AsDuck()
|
||||
{
|
||||
rct_duck * result = nullptr;
|
||||
rct_duck* result = nullptr;
|
||||
if (IsDuck())
|
||||
{
|
||||
return (rct_duck *)this;
|
||||
return (rct_duck*)this;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void rct_duck::Invalidate()
|
||||
{
|
||||
invalidate_sprite_0((rct_sprite *)this);
|
||||
invalidate_sprite_0((rct_sprite*)this);
|
||||
}
|
||||
|
||||
void rct_duck::Remove()
|
||||
{
|
||||
sprite_remove((rct_sprite *)this);
|
||||
sprite_remove((rct_sprite*)this);
|
||||
}
|
||||
|
||||
void rct_duck::MoveTo(int16_t destX, int16_t destY, int16_t destZ)
|
||||
{
|
||||
sprite_move(destX, destY, destZ, (rct_sprite *)this);
|
||||
sprite_move(destX, destY, destZ, (rct_sprite*)this);
|
||||
}
|
||||
|
||||
void rct_duck::UpdateFlyToWater()
|
||||
{
|
||||
if ((gCurrentTicks & 3) != 0) return;
|
||||
if ((gCurrentTicks & 3) != 0)
|
||||
return;
|
||||
|
||||
frame++;
|
||||
if (frame >= Util::CountOf(DuckAnimationFlyToWater))
|
||||
|
@ -122,7 +122,7 @@ void rct_duck::UpdateFlyToWater()
|
|||
int32_t newY = y + DuckMoveOffset[direction].y;
|
||||
int32_t manhattanDistanceN = abs(target_x - newX) + abs(target_y - newY);
|
||||
|
||||
rct_tile_element * tileElement = map_get_surface_element_at({target_x, target_y});
|
||||
rct_tile_element* tileElement = map_get_surface_element_at({ target_x, target_y });
|
||||
int32_t waterHeight = surface_get_water_height(tileElement);
|
||||
if (waterHeight == 0)
|
||||
{
|
||||
|
@ -171,7 +171,8 @@ void rct_duck::UpdateFlyToWater()
|
|||
|
||||
void rct_duck::UpdateSwim()
|
||||
{
|
||||
if (((gCurrentTicks + sprite_index) & 3) != 0) return;
|
||||
if (((gCurrentTicks + sprite_index) & 3) != 0)
|
||||
return;
|
||||
|
||||
uint32_t randomNumber = scenario_rand();
|
||||
if ((randomNumber & 0xFFFF) < 0x666)
|
||||
|
@ -282,7 +283,7 @@ void rct_duck::UpdateFlyAway()
|
|||
int32_t newX = x + (DuckMoveOffset[direction].x * 2);
|
||||
int32_t newY = y + (DuckMoveOffset[direction].y * 2);
|
||||
int32_t newZ = std::min(z + 2, 496);
|
||||
if (map_is_location_valid({newX, newY}))
|
||||
if (map_is_location_valid({ newX, newY }))
|
||||
{
|
||||
MoveTo(newX, newY, newZ);
|
||||
Invalidate();
|
||||
|
@ -308,7 +309,7 @@ uint32_t rct_duck::GetFrameImage(int32_t direction) const
|
|||
|
||||
void create_duck(int32_t targetX, int32_t targetY)
|
||||
{
|
||||
rct_sprite * sprite = create_sprite(2);
|
||||
rct_sprite* sprite = create_sprite(2);
|
||||
if (sprite != nullptr)
|
||||
{
|
||||
sprite->duck.sprite_identifier = SPRITE_IDENTIFIER_MISC;
|
||||
|
@ -322,19 +323,20 @@ void create_duck(int32_t targetX, int32_t targetY)
|
|||
sprite->duck.target_x = targetX;
|
||||
sprite->duck.target_y = targetY;
|
||||
uint8_t direction = scenario_rand() & 3;
|
||||
switch (direction) {
|
||||
case 0:
|
||||
targetX = 8191 - (scenario_rand() & 0x3F);
|
||||
break;
|
||||
case 1:
|
||||
targetY = scenario_rand() & 0x3F;
|
||||
break;
|
||||
case 2:
|
||||
targetX = scenario_rand() & 0x3F;
|
||||
break;
|
||||
case 3:
|
||||
targetY = 8191 - (scenario_rand() & 0x3F);
|
||||
break;
|
||||
switch (direction)
|
||||
{
|
||||
case 0:
|
||||
targetX = 8191 - (scenario_rand() & 0x3F);
|
||||
break;
|
||||
case 1:
|
||||
targetY = scenario_rand() & 0x3F;
|
||||
break;
|
||||
case 2:
|
||||
targetX = scenario_rand() & 0x3F;
|
||||
break;
|
||||
case 3:
|
||||
targetY = 8191 - (scenario_rand() & 0x3F);
|
||||
break;
|
||||
}
|
||||
sprite->duck.sprite_direction = direction << 3;
|
||||
sprite_move(targetX, targetY, 496, sprite);
|
||||
|
@ -343,28 +345,29 @@ void create_duck(int32_t targetX, int32_t targetY)
|
|||
}
|
||||
}
|
||||
|
||||
void duck_update(rct_duck * duck)
|
||||
void duck_update(rct_duck* duck)
|
||||
{
|
||||
switch ((DUCK_STATE)duck->state) {
|
||||
case DUCK_STATE::FLY_TO_WATER:
|
||||
duck->UpdateFlyToWater();
|
||||
break;
|
||||
case DUCK_STATE::SWIM:
|
||||
duck->UpdateSwim();
|
||||
break;
|
||||
case DUCK_STATE::DRINK:
|
||||
duck->UpdateDrink();
|
||||
break;
|
||||
case DUCK_STATE::DOUBLE_DRINK:
|
||||
duck->UpdateDoubleDrink();
|
||||
break;
|
||||
case DUCK_STATE::FLY_AWAY:
|
||||
duck->UpdateFlyAway();
|
||||
break;
|
||||
switch ((DUCK_STATE)duck->state)
|
||||
{
|
||||
case DUCK_STATE::FLY_TO_WATER:
|
||||
duck->UpdateFlyToWater();
|
||||
break;
|
||||
case DUCK_STATE::SWIM:
|
||||
duck->UpdateSwim();
|
||||
break;
|
||||
case DUCK_STATE::DRINK:
|
||||
duck->UpdateDrink();
|
||||
break;
|
||||
case DUCK_STATE::DOUBLE_DRINK:
|
||||
duck->UpdateDoubleDrink();
|
||||
break;
|
||||
case DUCK_STATE::FLY_AWAY:
|
||||
duck->UpdateFlyAway();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void duck_press(rct_duck * duck)
|
||||
void duck_press(rct_duck* duck)
|
||||
{
|
||||
audio_play_sound_at_location(SOUND_QUACK, duck->x, duck->y, duck->z);
|
||||
}
|
||||
|
@ -372,19 +375,19 @@ void duck_press(rct_duck * duck)
|
|||
void duck_remove_all()
|
||||
{
|
||||
uint16_t nextSpriteIndex;
|
||||
for (uint16_t spriteIndex = gSpriteListHead[SPRITE_LIST_MISC]; spriteIndex != SPRITE_INDEX_NULL; spriteIndex = nextSpriteIndex)
|
||||
for (uint16_t spriteIndex = gSpriteListHead[SPRITE_LIST_MISC]; spriteIndex != SPRITE_INDEX_NULL;
|
||||
spriteIndex = nextSpriteIndex)
|
||||
{
|
||||
rct_unk_sprite * sprite = &(get_sprite(spriteIndex)->unknown);
|
||||
rct_unk_sprite* sprite = &(get_sprite(spriteIndex)->unknown);
|
||||
nextSpriteIndex = sprite->next;
|
||||
if (sprite->misc_identifier == SPRITE_MISC_DUCK)
|
||||
{
|
||||
sprite_remove((rct_sprite *)sprite);
|
||||
sprite_remove((rct_sprite*)sprite);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t duck_get_frame_image(const rct_duck * duck, int32_t direction)
|
||||
uint32_t duck_get_frame_image(const rct_duck* duck, int32_t direction)
|
||||
{
|
||||
return duck->GetFrameImage(direction);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,21 +7,21 @@
|
|||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "../network/network.h"
|
||||
#include "../OpenRCT2.h"
|
||||
|
||||
#include "Entrance.h"
|
||||
|
||||
#include "../Cheats.h"
|
||||
#include "../Game.h"
|
||||
#include "../OpenRCT2.h"
|
||||
#include "../localisation/StringIds.h"
|
||||
#include "../management/Finance.h"
|
||||
#include "../network/network.h"
|
||||
#include "../ride/Station.h"
|
||||
#include "../ride/Track.h"
|
||||
#include "Footpath.h"
|
||||
#include "Map.h"
|
||||
#include "MapAnimation.h"
|
||||
#include "Park.h"
|
||||
#include "Sprite.h"
|
||||
#include "../Cheats.h"
|
||||
#include "../Game.h"
|
||||
#include "../localisation/StringIds.h"
|
||||
#include "../management/Finance.h"
|
||||
#include "../ride/Track.h"
|
||||
#include "../ride/Station.h"
|
||||
|
||||
bool gParkEntranceGhostExists = false;
|
||||
LocationXYZ16 gParkEntranceGhostPosition = { 0, 0, 0 };
|
||||
|
@ -33,7 +33,7 @@ uint8_t gRideEntranceExitGhostStationIndex;
|
|||
|
||||
static void ParkEntranceRemoveSegment(int32_t x, int32_t y, int32_t z)
|
||||
{
|
||||
rct_tile_element *tileElement;
|
||||
rct_tile_element* tileElement;
|
||||
|
||||
tileElement = map_get_park_entrance_element_at(x, y, z, true);
|
||||
if (tileElement == nullptr)
|
||||
|
@ -43,7 +43,7 @@ static void ParkEntranceRemoveSegment(int32_t x, int32_t y, int32_t z)
|
|||
|
||||
map_invalidate_tile(x, y, tileElement->base_height * 8, tileElement->clearance_height * 8);
|
||||
tile_element_remove(tileElement);
|
||||
update_park_fences({x, y});
|
||||
update_park_fences({ x, y });
|
||||
}
|
||||
|
||||
static money32 ParkEntranceRemove(int16_t x, int16_t y, uint8_t z, uint8_t flags)
|
||||
|
@ -78,30 +78,16 @@ static money32 ParkEntranceRemove(int16_t x, int16_t y, uint8_t z, uint8_t flags
|
|||
ParkEntranceRemoveSegment(x, y, z * 2);
|
||||
|
||||
// Left post
|
||||
ParkEntranceRemoveSegment(
|
||||
x + CoordsDirectionDelta[direction].x,
|
||||
y + CoordsDirectionDelta[direction].y,
|
||||
z * 2
|
||||
);
|
||||
ParkEntranceRemoveSegment(x + CoordsDirectionDelta[direction].x, y + CoordsDirectionDelta[direction].y, z * 2);
|
||||
|
||||
// Right post
|
||||
ParkEntranceRemoveSegment(
|
||||
x - CoordsDirectionDelta[direction].x,
|
||||
y - CoordsDirectionDelta[direction].y,
|
||||
z * 2
|
||||
);
|
||||
ParkEntranceRemoveSegment(x - CoordsDirectionDelta[direction].x, y - CoordsDirectionDelta[direction].y, z * 2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static money32 RideEntranceExitPlace(int16_t x,
|
||||
int16_t y,
|
||||
int16_t z,
|
||||
uint8_t direction,
|
||||
uint8_t flags,
|
||||
uint8_t rideIndex,
|
||||
uint8_t stationNum,
|
||||
bool isExit)
|
||||
static money32 RideEntranceExitPlace(
|
||||
int16_t x, int16_t y, int16_t z, uint8_t direction, uint8_t flags, uint8_t rideIndex, uint8_t stationNum, bool isExit)
|
||||
{
|
||||
// Remember when in unknown station num mode rideIndex is unknown and z is set
|
||||
// When in known station num mode rideIndex is known and z is unknown
|
||||
|
@ -136,8 +122,9 @@ static money32 RideEntranceExitPlace(int16_t x,
|
|||
|
||||
int16_t clear_z = z / 8 + (isExit ? 5 : 7);
|
||||
|
||||
if (!gCheatsDisableClearanceChecks &&
|
||||
!map_can_construct_with_clear_at(x, y, z / 8, clear_z, &map_place_non_scenery_clear_func, 0xF, flags, &cost, CREATE_CROSSING_MODE_NONE))
|
||||
if (!gCheatsDisableClearanceChecks
|
||||
&& !map_can_construct_with_clear_at(
|
||||
x, y, z / 8, clear_z, &map_place_non_scenery_clear_func, 0xF, flags, &cost, CREATE_CROSSING_MODE_NONE))
|
||||
{
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
@ -223,14 +210,7 @@ static money32 RideEntranceExitPlace(int16_t x,
|
|||
if (requiresRemove)
|
||||
{
|
||||
money32 success = game_do_command(
|
||||
removeCoord.x,
|
||||
flags,
|
||||
removeCoord.y,
|
||||
rideIndex,
|
||||
GAME_COMMAND_REMOVE_RIDE_ENTRANCE_OR_EXIT,
|
||||
stationNum,
|
||||
0
|
||||
);
|
||||
removeCoord.x, flags, removeCoord.y, rideIndex, GAME_COMMAND_REMOVE_RIDE_ENTRANCE_OR_EXIT, stationNum, 0);
|
||||
|
||||
if (success == MONEY32_UNDEFINED)
|
||||
{
|
||||
|
@ -241,9 +221,8 @@ static money32 RideEntranceExitPlace(int16_t x,
|
|||
z = ride->station_heights[stationNum] * 8;
|
||||
gCommandPosition.z = z;
|
||||
|
||||
if ((flags & GAME_COMMAND_FLAG_APPLY) &&
|
||||
!(flags & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED) &&
|
||||
!(flags & GAME_COMMAND_FLAG_GHOST))
|
||||
if ((flags & GAME_COMMAND_FLAG_APPLY) && !(flags & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED)
|
||||
&& !(flags & GAME_COMMAND_FLAG_GHOST))
|
||||
{
|
||||
footpath_remove_litter(x, y, z);
|
||||
wall_remove_at_z(x, y, z);
|
||||
|
@ -256,8 +235,9 @@ static money32 RideEntranceExitPlace(int16_t x,
|
|||
|
||||
int8_t clear_z = (z / 8) + (isExit ? 5 : 7);
|
||||
|
||||
if (!gCheatsDisableClearanceChecks &&
|
||||
!map_can_construct_with_clear_at(x, y, z / 8, clear_z, &map_place_non_scenery_clear_func, 0xF, flags, &cost, CREATE_CROSSING_MODE_NONE))
|
||||
if (!gCheatsDisableClearanceChecks
|
||||
&& !map_can_construct_with_clear_at(
|
||||
x, y, z / 8, clear_z, &map_place_non_scenery_clear_func, 0xF, flags, &cost, CREATE_CROSSING_MODE_NONE))
|
||||
{
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
@ -298,11 +278,13 @@ static money32 RideEntranceExitPlace(int16_t x,
|
|||
|
||||
if (isExit)
|
||||
{
|
||||
ride_set_exit_location(ride, stationNum, { x / 32, y / 32, z / 8, (uint8_t)tile_element_get_direction(tileElement)});
|
||||
ride_set_exit_location(
|
||||
ride, stationNum, { x / 32, y / 32, z / 8, (uint8_t)tile_element_get_direction(tileElement) });
|
||||
}
|
||||
else
|
||||
{
|
||||
ride_set_entrance_location(ride, stationNum, { x / 32, y / 32, z / 8, (uint8_t)tile_element_get_direction(tileElement)});
|
||||
ride_set_entrance_location(
|
||||
ride, stationNum, { x / 32, y / 32, z / 8, (uint8_t)tile_element_get_direction(tileElement) });
|
||||
ride->last_peep_in_queue[stationNum] = SPRITE_INDEX_NULL;
|
||||
ride->queue_length[stationNum] = 0;
|
||||
|
||||
|
@ -344,9 +326,7 @@ static money32 RideEntranceExitRemove(int16_t x, int16_t y, uint8_t rideIndex, u
|
|||
|
||||
if (!(flags & GAME_COMMAND_FLAG_GHOST))
|
||||
{
|
||||
if (!(flags & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED) &&
|
||||
game_is_paused() &&
|
||||
!gCheatsBuildInPauseMode)
|
||||
if (!(flags & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED) && game_is_paused() && !gCheatsBuildInPauseMode)
|
||||
{
|
||||
gGameCommandErrorText = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED;
|
||||
return MONEY32_UNDEFINED;
|
||||
|
@ -395,8 +375,7 @@ static money32 RideEntranceExitRemove(int16_t x, int16_t y, uint8_t rideIndex, u
|
|||
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
while (!(tileElement++)->IsLastForTile());
|
||||
} while (!(tileElement++)->IsLastForTile());
|
||||
|
||||
if (!found)
|
||||
{
|
||||
|
@ -435,21 +414,18 @@ static money32 RideEntranceExitRemove(int16_t x, int16_t y, uint8_t rideIndex, u
|
|||
return 0;
|
||||
}
|
||||
|
||||
static money32 RideEntranceExitPlaceGhost(uint8_t rideIndex, int16_t x, int16_t y, uint8_t direction, uint8_t placeType, uint8_t stationNum)
|
||||
static money32 RideEntranceExitPlaceGhost(
|
||||
uint8_t rideIndex, int16_t x, int16_t y, uint8_t direction, uint8_t placeType, uint8_t stationNum)
|
||||
{
|
||||
return game_do_command(
|
||||
x,
|
||||
(GAME_COMMAND_FLAG_APPLY |
|
||||
GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED |
|
||||
GAME_COMMAND_FLAG_5 |
|
||||
GAME_COMMAND_FLAG_GHOST) |
|
||||
(direction << 8),
|
||||
(GAME_COMMAND_FLAG_APPLY | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_5 | GAME_COMMAND_FLAG_GHOST)
|
||||
| (direction << 8),
|
||||
y,
|
||||
rideIndex | (placeType << 8),
|
||||
GAME_COMMAND_PLACE_RIDE_ENTRANCE_OR_EXIT,
|
||||
stationNum,
|
||||
0
|
||||
);
|
||||
0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -457,19 +433,15 @@ static money32 RideEntranceExitPlaceGhost(uint8_t rideIndex, int16_t x, int16_t
|
|||
* rct2: 0x00666A63
|
||||
*/
|
||||
void game_command_remove_park_entrance(
|
||||
int32_t * eax,
|
||||
int32_t * ebx,
|
||||
int32_t * ecx,
|
||||
int32_t * edx,
|
||||
[[maybe_unused]] int32_t * esi,
|
||||
[[maybe_unused]] int32_t * edi,
|
||||
[[maybe_unused]] int32_t * ebp)
|
||||
int32_t* eax,
|
||||
int32_t* ebx,
|
||||
int32_t* ecx,
|
||||
int32_t* edx,
|
||||
[[maybe_unused]] int32_t* esi,
|
||||
[[maybe_unused]] int32_t* edi,
|
||||
[[maybe_unused]] int32_t* ebp)
|
||||
{
|
||||
*ebx = ParkEntranceRemove(
|
||||
*eax & 0xFFFF,
|
||||
*ecx & 0xFFFF,
|
||||
*edx & 0xFF,
|
||||
*ebx & 0xFF);
|
||||
*ebx = ParkEntranceRemove(*eax & 0xFFFF, *ecx & 0xFFFF, *edx & 0xFF, *ebx & 0xFF);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -488,8 +460,7 @@ void park_entrance_remove_ghost()
|
|||
gParkEntranceGhostPosition.z,
|
||||
GAME_COMMAND_REMOVE_PARK_ENTRANCE,
|
||||
0,
|
||||
0
|
||||
);
|
||||
0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -499,9 +470,7 @@ int32_t park_entrance_get_index(int32_t x, int32_t y, int32_t z)
|
|||
|
||||
for (i = 0; i < MAX_PARK_ENTRANCES; i++)
|
||||
{
|
||||
if (x == gParkEntrances[i].x &&
|
||||
y == gParkEntrances[i].y &&
|
||||
z == gParkEntrances[i].z)
|
||||
if (x == gParkEntrances[i].x && y == gParkEntrances[i].y && z == gParkEntrances[i].z)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
|
@ -512,28 +481,30 @@ int32_t park_entrance_get_index(int32_t x, int32_t y, int32_t z)
|
|||
|
||||
void reset_park_entrance()
|
||||
{
|
||||
for (auto &parkEntrance : gParkEntrances)
|
||||
for (auto& parkEntrance : gParkEntrances)
|
||||
{
|
||||
parkEntrance.x = LOCATION_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ride_entrance_exit_place_provisional_ghost()
|
||||
{
|
||||
if (_currentTrackSelectionFlags & TRACK_SELECTION_FLAG_ENTRANCE_OR_EXIT) {
|
||||
RideEntranceExitPlaceGhost(_currentRideIndex,
|
||||
gRideEntranceExitGhostPosition.x,
|
||||
gRideEntranceExitGhostPosition.y,
|
||||
gRideEntranceExitGhostPosition.direction,
|
||||
gRideEntranceExitPlaceType,
|
||||
gRideEntranceExitGhostStationIndex);
|
||||
if (_currentTrackSelectionFlags & TRACK_SELECTION_FLAG_ENTRANCE_OR_EXIT)
|
||||
{
|
||||
RideEntranceExitPlaceGhost(
|
||||
_currentRideIndex,
|
||||
gRideEntranceExitGhostPosition.x,
|
||||
gRideEntranceExitGhostPosition.y,
|
||||
gRideEntranceExitGhostPosition.direction,
|
||||
gRideEntranceExitPlaceType,
|
||||
gRideEntranceExitGhostStationIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void ride_entrance_exit_remove_ghost()
|
||||
{
|
||||
if (_currentTrackSelectionFlags & TRACK_SELECTION_FLAG_ENTRANCE_OR_EXIT) {
|
||||
if (_currentTrackSelectionFlags & TRACK_SELECTION_FLAG_ENTRANCE_OR_EXIT)
|
||||
{
|
||||
game_do_command(
|
||||
gRideEntranceExitGhostPosition.x,
|
||||
(GAME_COMMAND_FLAG_5 | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_APPLY),
|
||||
|
@ -541,22 +512,16 @@ void ride_entrance_exit_remove_ghost()
|
|||
_currentRideIndex,
|
||||
GAME_COMMAND_REMOVE_RIDE_ENTRANCE_OR_EXIT,
|
||||
gRideEntranceExitGhostStationIndex,
|
||||
0
|
||||
);
|
||||
0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006CA28C
|
||||
*/
|
||||
money32 ride_entrance_exit_place_ghost(int32_t rideIndex,
|
||||
int32_t x,
|
||||
int32_t y,
|
||||
int32_t direction,
|
||||
int32_t placeType,
|
||||
int32_t stationNum)
|
||||
money32 ride_entrance_exit_place_ghost(
|
||||
int32_t rideIndex, int32_t x, int32_t y, int32_t direction, int32_t placeType, int32_t stationNum)
|
||||
{
|
||||
ride_construction_remove_ghosts();
|
||||
money32 result = RideEntranceExitPlaceGhost(rideIndex, x, y, direction, placeType, stationNum);
|
||||
|
@ -577,13 +542,13 @@ money32 ride_entrance_exit_place_ghost(int32_t rideIndex,
|
|||
* rct2: 0x006660A8
|
||||
*/
|
||||
void game_command_place_ride_entrance_or_exit(
|
||||
int32_t * eax,
|
||||
int32_t * ebx,
|
||||
int32_t * ecx,
|
||||
int32_t * edx,
|
||||
[[maybe_unused]] int32_t * esi,
|
||||
int32_t * edi,
|
||||
[[maybe_unused]] int32_t * ebp)
|
||||
int32_t* eax,
|
||||
int32_t* ebx,
|
||||
int32_t* ecx,
|
||||
int32_t* edx,
|
||||
[[maybe_unused]] int32_t* esi,
|
||||
int32_t* edi,
|
||||
[[maybe_unused]] int32_t* ebp)
|
||||
{
|
||||
*ebx = RideEntranceExitPlace(
|
||||
*eax & 0xFFFF,
|
||||
|
@ -593,8 +558,7 @@ void game_command_place_ride_entrance_or_exit(
|
|||
*ebx & 0xFF,
|
||||
*edx & 0xFF,
|
||||
*edi & 0xFF,
|
||||
((*edx >> 8) & 0xFF) != 0
|
||||
);
|
||||
((*edx >> 8) & 0xFF) != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -602,28 +566,22 @@ void game_command_place_ride_entrance_or_exit(
|
|||
* rct2: 0x0066640B
|
||||
*/
|
||||
void game_command_remove_ride_entrance_or_exit(
|
||||
int32_t * eax,
|
||||
int32_t * ebx,
|
||||
int32_t * ecx,
|
||||
int32_t * edx,
|
||||
[[maybe_unused]] int32_t * esi,
|
||||
int32_t * edi,
|
||||
[[maybe_unused]] int32_t * ebp)
|
||||
int32_t* eax,
|
||||
int32_t* ebx,
|
||||
int32_t* ecx,
|
||||
int32_t* edx,
|
||||
[[maybe_unused]] int32_t* esi,
|
||||
int32_t* edi,
|
||||
[[maybe_unused]] int32_t* ebp)
|
||||
{
|
||||
*ebx = RideEntranceExitRemove(
|
||||
*eax & 0xFFFF,
|
||||
*ecx & 0xFFFF,
|
||||
*edx & 0xFF,
|
||||
*edi & 0xFF,
|
||||
*ebx & 0xFF
|
||||
);
|
||||
*ebx = RideEntranceExitRemove(*eax & 0xFFFF, *ecx & 0xFFFF, *edx & 0xFF, *edi & 0xFF, *ebx & 0xFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the outer hedge walls for an entrance placement removal.
|
||||
* rct2: 0x00666D6F
|
||||
*/
|
||||
void maze_entrance_hedge_replacement(int32_t x, int32_t y, rct_tile_element *tileElement)
|
||||
void maze_entrance_hedge_replacement(int32_t x, int32_t y, rct_tile_element* tileElement)
|
||||
{
|
||||
int32_t direction = tile_element_get_direction(tileElement);
|
||||
x += CoordsDirectionDelta[direction].x;
|
||||
|
@ -632,11 +590,16 @@ void maze_entrance_hedge_replacement(int32_t x, int32_t y, rct_tile_element *til
|
|||
int32_t rideIndex = track_element_get_ride_index(tileElement);
|
||||
|
||||
tileElement = map_get_first_element_at(x >> 5, y >> 5);
|
||||
do {
|
||||
if (tileElement->GetType() != TILE_ELEMENT_TYPE_TRACK) continue;
|
||||
if (track_element_get_ride_index(tileElement) != rideIndex) continue;
|
||||
if (tileElement->base_height != z) continue;
|
||||
if (track_element_get_type(tileElement) != TRACK_ELEM_MAZE) continue;
|
||||
do
|
||||
{
|
||||
if (tileElement->GetType() != TILE_ELEMENT_TYPE_TRACK)
|
||||
continue;
|
||||
if (track_element_get_ride_index(tileElement) != rideIndex)
|
||||
continue;
|
||||
if (tileElement->base_height != z)
|
||||
continue;
|
||||
if (track_element_get_type(tileElement) != TRACK_ELEM_MAZE)
|
||||
continue;
|
||||
|
||||
// Each maze element is split into 4 sections with 4 different walls
|
||||
uint8_t mazeSection = direction * 4;
|
||||
|
@ -654,7 +617,7 @@ void maze_entrance_hedge_replacement(int32_t x, int32_t y, rct_tile_element *til
|
|||
* Removes the hedge walls for an entrance placement.
|
||||
* rct2: 0x00666CBE
|
||||
*/
|
||||
void maze_entrance_hedge_removal(int32_t x, int32_t y, rct_tile_element *tileElement)
|
||||
void maze_entrance_hedge_removal(int32_t x, int32_t y, rct_tile_element* tileElement)
|
||||
{
|
||||
int32_t direction = tile_element_get_direction(tileElement);
|
||||
x += CoordsDirectionDelta[direction].x;
|
||||
|
@ -663,11 +626,16 @@ void maze_entrance_hedge_removal(int32_t x, int32_t y, rct_tile_element *tileEle
|
|||
int32_t rideIndex = track_element_get_ride_index(tileElement);
|
||||
|
||||
tileElement = map_get_first_element_at(x >> 5, y >> 5);
|
||||
do {
|
||||
if (tileElement->GetType() != TILE_ELEMENT_TYPE_TRACK) continue;
|
||||
if (track_element_get_ride_index(tileElement) != rideIndex) continue;
|
||||
if (tileElement->base_height != z) continue;
|
||||
if (track_element_get_type(tileElement) != TRACK_ELEM_MAZE) continue;
|
||||
do
|
||||
{
|
||||
if (tileElement->GetType() != TILE_ELEMENT_TYPE_TRACK)
|
||||
continue;
|
||||
if (track_element_get_ride_index(tileElement) != rideIndex)
|
||||
continue;
|
||||
if (tileElement->base_height != z)
|
||||
continue;
|
||||
if (track_element_get_type(tileElement) != TRACK_ELEM_MAZE)
|
||||
continue;
|
||||
|
||||
// Each maze element is split into 4 sections with 4 different walls
|
||||
uint8_t mazeSection = direction * 4;
|
||||
|
@ -690,18 +658,14 @@ void maze_entrance_hedge_removal(int32_t x, int32_t y, rct_tile_element *tileEle
|
|||
void fix_park_entrance_locations(void)
|
||||
{
|
||||
// Fix gParkEntrance locations for which the tile_element no longer exists
|
||||
for (auto &entrance : gParkEntrances)
|
||||
for (auto& entrance : gParkEntrances)
|
||||
{
|
||||
if (entrance.x == LOCATION_NULL)
|
||||
continue;
|
||||
|
||||
if (map_get_park_entrance_element_at(
|
||||
entrance.x,
|
||||
entrance.y,
|
||||
entrance.z >> 3, false) == nullptr)
|
||||
if (map_get_park_entrance_element_at(entrance.x, entrance.y, entrance.z >> 3, false) == nullptr)
|
||||
{
|
||||
entrance.x = LOCATION_NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,16 +14,18 @@
|
|||
#include "Location.hpp"
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct rct_entrance_type {
|
||||
rct_string_id string_idx; // 0x00
|
||||
uint32_t image_id; // 0x02
|
||||
uint8_t scrolling_mode; // 0x06
|
||||
uint8_t text_height; // 0x07
|
||||
struct rct_entrance_type
|
||||
{
|
||||
rct_string_id string_idx; // 0x00
|
||||
uint32_t image_id; // 0x02
|
||||
uint8_t scrolling_mode; // 0x06
|
||||
uint8_t text_height; // 0x07
|
||||
};
|
||||
assert_struct_size(rct_entrance_type, 8);
|
||||
#pragma pack(pop)
|
||||
|
||||
void game_command_remove_park_entrance(int32_t *eax, int32_t *ebx, int32_t *ecx, int32_t *edx, int32_t *esi, int32_t *edi, int32_t *ebp);
|
||||
void game_command_remove_park_entrance(
|
||||
int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
|
||||
struct rct_tile_element;
|
||||
|
||||
|
@ -43,8 +45,8 @@ money32 park_entrance_place_ghost(int32_t x, int32_t y, int32_t z, int32_t direc
|
|||
money32 place_park_entrance(int16_t x, int16_t y, int16_t z, uint8_t direction);
|
||||
|
||||
void reset_park_entrance();
|
||||
void maze_entrance_hedge_replacement(int32_t x, int32_t y, rct_tile_element *tileElement);
|
||||
void maze_entrance_hedge_removal(int32_t x, int32_t y, rct_tile_element *tileElement);
|
||||
void maze_entrance_hedge_replacement(int32_t x, int32_t y, rct_tile_element* tileElement);
|
||||
void maze_entrance_hedge_removal(int32_t x, int32_t y, rct_tile_element* tileElement);
|
||||
|
||||
void fix_park_entrance_locations();
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -17,20 +17,21 @@
|
|||
enum
|
||||
{
|
||||
PROVISIONAL_PATH_FLAG_SHOW_ARROW = (1 << 0),
|
||||
PROVISIONAL_PATH_FLAG_1 = (1 << 1),
|
||||
PROVISIONAL_PATH_FLAG_2 = (1 << 2),
|
||||
PROVISIONAL_PATH_FLAG_1 = (1 << 1),
|
||||
PROVISIONAL_PATH_FLAG_2 = (1 << 2),
|
||||
};
|
||||
|
||||
#define FOOTPATH_ELEMENT_INSERT_QUEUE 0x80
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct rct_footpath_entry {
|
||||
rct_string_id string_idx; // 0x00
|
||||
uint32_t image; // 0x02
|
||||
uint32_t bridge_image; // 0x06
|
||||
uint8_t support_type; // 0x0A
|
||||
uint8_t flags; // 0x0B
|
||||
uint8_t scrolling_mode; // 0x0C
|
||||
struct rct_footpath_entry
|
||||
{
|
||||
rct_string_id string_idx; // 0x00
|
||||
uint32_t image; // 0x02
|
||||
uint32_t bridge_image; // 0x06
|
||||
uint8_t support_type; // 0x0A
|
||||
uint8_t flags; // 0x0B
|
||||
uint8_t scrolling_mode; // 0x0C
|
||||
};
|
||||
assert_struct_size(rct_footpath_entry, 13);
|
||||
#pragma pack(pop)
|
||||
|
@ -38,34 +39,34 @@ assert_struct_size(rct_footpath_entry, 13);
|
|||
// Masks for values stored in rct_tile_element.type
|
||||
enum
|
||||
{
|
||||
FOOTPATH_ELEMENT_TYPE_FLAG_IS_QUEUE = (1 << 0),
|
||||
FOOTPATH_ELEMENT_TYPE_FLAG_IS_WIDE = (1 << 1),
|
||||
FOOTPATH_ELEMENT_TYPE_FLAG_IS_QUEUE = (1 << 0),
|
||||
FOOTPATH_ELEMENT_TYPE_FLAG_IS_WIDE = (1 << 1),
|
||||
FOOTPATH_ELEMENT_TYPE_DIRECTION_MASK = (1 << 6) | (1 << 7),
|
||||
};
|
||||
|
||||
// Masks and flags for values stored in rct_tile_element.properties.path.type
|
||||
enum
|
||||
{
|
||||
FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK = (1 << 0) | (1 << 1),
|
||||
FOOTPATH_PROPERTIES_FLAG_IS_SLOPED = (1 << 2),
|
||||
FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK = (1 << 0) | (1 << 1),
|
||||
FOOTPATH_PROPERTIES_FLAG_IS_SLOPED = (1 << 2),
|
||||
FOOTPATH_PROPERTIES_FLAG_HAS_QUEUE_BANNER = (1 << 3),
|
||||
FOOTPATH_PROPERTIES_TYPE_MASK = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7),
|
||||
FOOTPATH_PROPERTIES_TYPE_MASK = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7),
|
||||
};
|
||||
|
||||
// Masks and flags for values stored in in rct_tile_element.properties.path.edges
|
||||
enum
|
||||
{
|
||||
FOOTPATH_PROPERTIES_EDGES_EDGES_MASK = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3),
|
||||
FOOTPATH_PROPERTIES_EDGES_EDGES_MASK = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3),
|
||||
FOOTPATH_PROPERTIES_EDGES_CORNERS_MASK = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7),
|
||||
};
|
||||
|
||||
// Masks and flags for values stored in in rct_tile_element.properties.path.additions
|
||||
enum
|
||||
{
|
||||
FOOTPATH_PROPERTIES_ADDITIONS_TYPE_MASK = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3),
|
||||
FOOTPATH_PROPERTIES_ADDITIONS_TYPE_MASK = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3),
|
||||
// The most significant bit in this mask will always be zero, since rides can only have 4 stations
|
||||
FOOTPATH_PROPERTIES_ADDITIONS_STATION_INDEX_MASK = (1 << 4) | (1 << 5) | (1 << 6),
|
||||
FOOTPATH_PROPERTIES_ADDITIONS_FLAG_GHOST = (1 << 7),
|
||||
FOOTPATH_PROPERTIES_ADDITIONS_FLAG_GHOST = (1 << 7),
|
||||
};
|
||||
|
||||
enum
|
||||
|
@ -77,8 +78,8 @@ enum
|
|||
|
||||
enum
|
||||
{
|
||||
FOOTPATH_ENTRY_FLAG_HAS_SUPPORT_BASE_SPRITE = (1 << 0),
|
||||
FOOTPATH_ENTRY_FLAG_HAS_PATH_BASE_SPRITE = (1 << 1), // When elevated
|
||||
FOOTPATH_ENTRY_FLAG_HAS_SUPPORT_BASE_SPRITE = (1 << 0),
|
||||
FOOTPATH_ENTRY_FLAG_HAS_PATH_BASE_SPRITE = (1 << 1), // When elevated
|
||||
FOOTPATH_ENTRY_FLAG_SHOW_ONLY_IN_SCENARIO_EDITOR = (1 << 2),
|
||||
};
|
||||
|
||||
|
@ -97,7 +98,7 @@ enum
|
|||
|
||||
enum
|
||||
{
|
||||
FOOTPATH_CLEAR_DIRECTIONAL = (1 << 8), // Flag set when direction is used.
|
||||
FOOTPATH_CLEAR_DIRECTIONAL = (1 << 8), // Flag set when direction is used.
|
||||
};
|
||||
|
||||
enum
|
||||
|
@ -123,55 +124,62 @@ extern const LocationXY16 word_981D6C[4];
|
|||
extern const LocationXY16 BinUseOffsets[4];
|
||||
extern const LocationXY16 BenchUseOffsets[8];
|
||||
|
||||
rct_tile_element *map_get_footpath_element(int32_t x, int32_t y, int32_t z);
|
||||
rct_tile_element* map_get_footpath_element(int32_t x, int32_t y, int32_t z);
|
||||
money32 footpath_remove_real(int32_t x, int32_t y, int32_t z, int32_t flags);
|
||||
void game_command_place_footpath(int32_t * eax, int32_t * ebx, int32_t * ecx, int32_t * edx, int32_t * esi, int32_t * edi, int32_t * ebp);
|
||||
void game_command_place_footpath_from_track(int32_t * eax, int32_t * ebx, int32_t * ecx, int32_t * edx, int32_t * esi, int32_t * edi, int32_t * ebp);
|
||||
void game_command_remove_footpath(int32_t * eax, int32_t * ebx, int32_t * ecx, int32_t * edx, int32_t * esi, int32_t * edi, int32_t * ebp);
|
||||
void game_command_place_footpath(
|
||||
int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_place_footpath_from_track(
|
||||
int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_remove_footpath(
|
||||
int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
money32 footpath_place(int32_t type, int32_t x, int32_t y, int32_t z, int32_t slope, int32_t flags);
|
||||
money32 footpath_place_remove_intersecting(int32_t type, int32_t x, int32_t y, int32_t z, int32_t slope, int32_t flags, int32_t direction);
|
||||
money32 footpath_place_remove_intersecting(
|
||||
int32_t type, int32_t x, int32_t y, int32_t z, int32_t slope, int32_t flags, int32_t direction);
|
||||
void footpath_remove(int32_t x, int32_t y, int32_t z, int32_t flags);
|
||||
money32 footpath_provisional_set(int32_t type, int32_t x, int32_t y, int32_t z, int32_t slope);
|
||||
void footpath_provisional_remove();
|
||||
void footpath_provisional_update();
|
||||
void footpath_get_coordinates_from_pos(int32_t screenX, int32_t screenY, int32_t * x, int32_t * y, int32_t * direction, rct_tile_element ** tileElement);
|
||||
void footpath_bridge_get_info_from_pos(int32_t screenX, int32_t screenY, int32_t * x, int32_t * y, int32_t * direction, rct_tile_element ** tileElement);
|
||||
void footpath_get_coordinates_from_pos(
|
||||
int32_t screenX, int32_t screenY, int32_t* x, int32_t* y, int32_t* direction, rct_tile_element** tileElement);
|
||||
void footpath_bridge_get_info_from_pos(
|
||||
int32_t screenX, int32_t screenY, int32_t* x, int32_t* y, int32_t* direction, rct_tile_element** tileElement);
|
||||
void footpath_remove_litter(int32_t x, int32_t y, int32_t z);
|
||||
void footpath_connect_edges(int32_t x, int32_t y, rct_tile_element * tileElement, int32_t flags);
|
||||
void footpath_connect_edges(int32_t x, int32_t y, rct_tile_element* tileElement, int32_t flags);
|
||||
void footpath_update_queue_chains();
|
||||
bool fence_in_the_way(int32_t x, int32_t y, int32_t z0, int32_t z1, int32_t direction);
|
||||
void footpath_chain_ride_queue(int32_t rideIndex, int32_t entranceIndex, int32_t x, int32_t y, rct_tile_element * tileElement, int32_t direction);
|
||||
void footpath_chain_ride_queue(
|
||||
int32_t rideIndex, int32_t entranceIndex, int32_t x, int32_t y, rct_tile_element* tileElement, int32_t direction);
|
||||
void footpath_update_path_wide_flags(int32_t x, int32_t y);
|
||||
bool footpath_is_blocked_by_vehicle(const TileCoordsXYZ& position);
|
||||
|
||||
int32_t footpath_is_connected_to_map_edge(int32_t x, int32_t y, int32_t z, int32_t direction, int32_t flags);
|
||||
bool footpath_element_is_sloped(const rct_tile_element * tileElement);
|
||||
void footpath_element_set_sloped(rct_tile_element * tileElement, bool isSloped);
|
||||
uint8_t footpath_element_get_slope_direction(const rct_tile_element * tileElement);
|
||||
bool footpath_element_is_queue(const rct_tile_element * tileElement);
|
||||
void footpath_element_set_queue(rct_tile_element * tileElement);
|
||||
void footpath_element_clear_queue(rct_tile_element * tileElement);
|
||||
bool footpath_element_has_queue_banner(const rct_tile_element * tileElement);
|
||||
bool footpath_element_is_wide(const rct_tile_element * tileElement);
|
||||
uint8_t footpath_element_get_type(const rct_tile_element * tileElement);
|
||||
void footpath_element_set_type(rct_tile_element * tileElement, uint8_t type);
|
||||
uint8_t footpath_element_get_direction(const rct_tile_element * tileElement);
|
||||
void footpath_element_set_direction(rct_tile_element * tileElement, uint8_t direction);
|
||||
void footpath_element_set_wide(rct_tile_element * tileElement, bool isWide);
|
||||
bool footpath_element_has_path_scenery(const rct_tile_element * tileElement);
|
||||
uint8_t footpath_element_get_path_scenery(const rct_tile_element * tileElement);
|
||||
void footpath_element_set_path_scenery(rct_tile_element * tileElement, uint8_t pathSceneryType);
|
||||
uint8_t footpath_element_get_path_scenery_index(const rct_tile_element * tileElement);
|
||||
bool footpath_element_path_scenery_is_ghost(const rct_tile_element * tileElement);
|
||||
void footpath_scenery_set_is_ghost(rct_tile_element * tileElement, bool isGhost);
|
||||
void footpath_remove_edges_at(int32_t x, int32_t y, rct_tile_element * tileElement);
|
||||
int32_t entrance_get_directions(const rct_tile_element * tileElement);
|
||||
bool footpath_element_is_sloped(const rct_tile_element* tileElement);
|
||||
void footpath_element_set_sloped(rct_tile_element* tileElement, bool isSloped);
|
||||
uint8_t footpath_element_get_slope_direction(const rct_tile_element* tileElement);
|
||||
bool footpath_element_is_queue(const rct_tile_element* tileElement);
|
||||
void footpath_element_set_queue(rct_tile_element* tileElement);
|
||||
void footpath_element_clear_queue(rct_tile_element* tileElement);
|
||||
bool footpath_element_has_queue_banner(const rct_tile_element* tileElement);
|
||||
bool footpath_element_is_wide(const rct_tile_element* tileElement);
|
||||
uint8_t footpath_element_get_type(const rct_tile_element* tileElement);
|
||||
void footpath_element_set_type(rct_tile_element* tileElement, uint8_t type);
|
||||
uint8_t footpath_element_get_direction(const rct_tile_element* tileElement);
|
||||
void footpath_element_set_direction(rct_tile_element* tileElement, uint8_t direction);
|
||||
void footpath_element_set_wide(rct_tile_element* tileElement, bool isWide);
|
||||
bool footpath_element_has_path_scenery(const rct_tile_element* tileElement);
|
||||
uint8_t footpath_element_get_path_scenery(const rct_tile_element* tileElement);
|
||||
void footpath_element_set_path_scenery(rct_tile_element* tileElement, uint8_t pathSceneryType);
|
||||
uint8_t footpath_element_get_path_scenery_index(const rct_tile_element* tileElement);
|
||||
bool footpath_element_path_scenery_is_ghost(const rct_tile_element* tileElement);
|
||||
void footpath_scenery_set_is_ghost(rct_tile_element* tileElement, bool isGhost);
|
||||
void footpath_remove_edges_at(int32_t x, int32_t y, rct_tile_element* tileElement);
|
||||
int32_t entrance_get_directions(const rct_tile_element* tileElement);
|
||||
|
||||
rct_footpath_entry * get_footpath_entry(int32_t entryIndex);
|
||||
rct_footpath_entry* get_footpath_entry(int32_t entryIndex);
|
||||
|
||||
void footpath_queue_chain_reset();
|
||||
void footpath_queue_chain_push(uint8_t rideIndex);
|
||||
|
||||
uint8_t footpath_get_edges(const rct_tile_element * element);
|
||||
uint8_t footpath_get_edges(const rct_tile_element* element);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -30,147 +30,132 @@ enum class PATTERN
|
|||
|
||||
namespace FOUNTAIN_FLAG
|
||||
{
|
||||
const uint32_t FAST = 1 << 0;
|
||||
const uint32_t GOTO_EDGE = 1 << 1;
|
||||
const uint32_t SPLIT = 1 << 2;
|
||||
const uint32_t TERMINATE = 1 << 3;
|
||||
const uint32_t BOUNCE = 1 << 4;
|
||||
const uint32_t DIRECTION = 1 << 7;
|
||||
const uint32_t FAST = 1 << 0;
|
||||
const uint32_t GOTO_EDGE = 1 << 1;
|
||||
const uint32_t SPLIT = 1 << 2;
|
||||
const uint32_t TERMINATE = 1 << 3;
|
||||
const uint32_t BOUNCE = 1 << 4;
|
||||
const uint32_t DIRECTION = 1 << 7;
|
||||
}; // namespace FOUNTAIN_FLAG
|
||||
|
||||
static constexpr const LocationXY16 _fountainDirectionsNegative[] = {
|
||||
{ -32, 0 }, { -32, -32 }, { 0, 0 }, { -32, 0 }, { 0, 0 }, { 0, -32 }, { 0, -32 }, { -32, -32 },
|
||||
};
|
||||
|
||||
static constexpr const LocationXY16 _fountainDirectionsNegative[] =
|
||||
{
|
||||
{ -32, 0 },
|
||||
{ -32, -32 },
|
||||
{ 0, 0 },
|
||||
{ -32, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, -32 },
|
||||
{ 0, -32 },
|
||||
{ -32, -32 },
|
||||
};
|
||||
|
||||
static constexpr const LocationXY16 _fountainDirectionsPositive[] =
|
||||
{
|
||||
{ 32, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 32 },
|
||||
{ 32, 32 },
|
||||
{ 32, 32 },
|
||||
{ 32, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 32 }
|
||||
};
|
||||
static constexpr const LocationXY16 _fountainDirectionsPositive[]
|
||||
= { { 32, 0 }, { 0, 0 }, { 0, 32 }, { 32, 32 }, { 32, 32 }, { 32, 0 }, { 0, 0 }, { 0, 32 } };
|
||||
|
||||
// rct2: 0x0097F040
|
||||
const uint8_t _fountainDirections[] = { 0, 1, 2, 3, 0, 1, 2, 3 };
|
||||
|
||||
// rct2: 0x0097F048
|
||||
const uint8_t _fountainDirectionFlags[] = { 0, 0, FOUNTAIN_FLAG::DIRECTION, FOUNTAIN_FLAG::DIRECTION, FOUNTAIN_FLAG::DIRECTION, FOUNTAIN_FLAG::DIRECTION, 0, 0 };
|
||||
const uint8_t _fountainDirectionFlags[]
|
||||
= { 0, 0, FOUNTAIN_FLAG::DIRECTION, FOUNTAIN_FLAG::DIRECTION, FOUNTAIN_FLAG::DIRECTION, FOUNTAIN_FLAG::DIRECTION, 0, 0 };
|
||||
|
||||
// rct2: 0x0097F050
|
||||
const uint8_t _fountainPatternFlags[] = {
|
||||
FOUNTAIN_FLAG::TERMINATE, // CYCLIC_SQUARES
|
||||
FOUNTAIN_FLAG::FAST | FOUNTAIN_FLAG::GOTO_EDGE, // CONTINUOUS_CHASERS
|
||||
FOUNTAIN_FLAG::BOUNCE, // BOUNCING_PAIRS
|
||||
FOUNTAIN_FLAG::FAST | FOUNTAIN_FLAG::SPLIT, // SPROUTING_BLOOMS
|
||||
FOUNTAIN_FLAG::GOTO_EDGE, // RACING_PAIRS
|
||||
FOUNTAIN_FLAG::FAST | FOUNTAIN_FLAG::GOTO_EDGE | FOUNTAIN_FLAG::SPLIT, // SPLITTING_CHASERS
|
||||
0, // DOPEY_JUMPERS
|
||||
FOUNTAIN_FLAG::FAST // FAST_RANDOM_CHASERS
|
||||
FOUNTAIN_FLAG::TERMINATE, // CYCLIC_SQUARES
|
||||
FOUNTAIN_FLAG::FAST | FOUNTAIN_FLAG::GOTO_EDGE, // CONTINUOUS_CHASERS
|
||||
FOUNTAIN_FLAG::BOUNCE, // BOUNCING_PAIRS
|
||||
FOUNTAIN_FLAG::FAST | FOUNTAIN_FLAG::SPLIT, // SPROUTING_BLOOMS
|
||||
FOUNTAIN_FLAG::GOTO_EDGE, // RACING_PAIRS
|
||||
FOUNTAIN_FLAG::FAST | FOUNTAIN_FLAG::GOTO_EDGE | FOUNTAIN_FLAG::SPLIT, // SPLITTING_CHASERS
|
||||
0, // DOPEY_JUMPERS
|
||||
FOUNTAIN_FLAG::FAST // FAST_RANDOM_CHASERS
|
||||
};
|
||||
|
||||
static int32_t jumping_fountain_get_type(const rct_jumping_fountain * jumpingFountain);
|
||||
static void jumping_fountain_continue(rct_jumping_fountain * jumpingFountain);
|
||||
static int32_t jumping_fountain_get_type(const rct_jumping_fountain* jumpingFountain);
|
||||
static void jumping_fountain_continue(rct_jumping_fountain* jumpingFountain);
|
||||
static bool is_jumping_fountain(int32_t type, int32_t x, int32_t y, int32_t z);
|
||||
|
||||
static void jumping_fountain_goto_edge(const rct_jumping_fountain * jumpingFountain, int32_t x, int32_t y, int32_t z, int32_t availableDirections);
|
||||
static void jumping_fountain_bounce(rct_jumping_fountain * jumpingFountain, int32_t x, int32_t y, int32_t z, int32_t availableDirections);
|
||||
static void jumping_fountain_split(const rct_jumping_fountain * jumpingFountain, int32_t x, int32_t y, int32_t z, int32_t availableDirections);
|
||||
static void jumping_fountain_random(const rct_jumping_fountain * jumpingFountain, int32_t x, int32_t y, int32_t z, int32_t availableDirections);
|
||||
static void jumping_fountain_create_next(const rct_jumping_fountain * jumpingFountain, int32_t x, int32_t y, int32_t z, int32_t direction);
|
||||
static void jumping_fountain_goto_edge(
|
||||
const rct_jumping_fountain* jumpingFountain, int32_t x, int32_t y, int32_t z, int32_t availableDirections);
|
||||
static void jumping_fountain_bounce(
|
||||
rct_jumping_fountain* jumpingFountain, int32_t x, int32_t y, int32_t z, int32_t availableDirections);
|
||||
static void jumping_fountain_split(
|
||||
const rct_jumping_fountain* jumpingFountain, int32_t x, int32_t y, int32_t z, int32_t availableDirections);
|
||||
static void jumping_fountain_random(
|
||||
const rct_jumping_fountain* jumpingFountain, int32_t x, int32_t y, int32_t z, int32_t availableDirections);
|
||||
static void jumping_fountain_create_next(
|
||||
const rct_jumping_fountain* jumpingFountain, int32_t x, int32_t y, int32_t z, int32_t direction);
|
||||
|
||||
void jumping_fountain_begin(int32_t type, int32_t x, int32_t y, const rct_tile_element * tileElement)
|
||||
void jumping_fountain_begin(int32_t type, int32_t x, int32_t y, const rct_tile_element* tileElement)
|
||||
{
|
||||
int32_t randomIndex;
|
||||
int32_t z = tileElement->base_height * 8;
|
||||
|
||||
// Change pattern approximately every 51 seconds
|
||||
uint32_t pattern = (gCurrentTicks >> 11) & 7;
|
||||
switch ((PATTERN)pattern) {
|
||||
case PATTERN::CYCLIC_SQUARES:
|
||||
// 0, 1, 2, 3
|
||||
for (int32_t i = 0; i < 4; i++)
|
||||
{
|
||||
switch ((PATTERN)pattern)
|
||||
{
|
||||
case PATTERN::CYCLIC_SQUARES:
|
||||
// 0, 1, 2, 3
|
||||
for (int32_t i = 0; i < 4; i++)
|
||||
{
|
||||
jumping_fountain_create(
|
||||
type,
|
||||
x + _fountainDirectionsPositive[i].x,
|
||||
y + _fountainDirectionsPositive[i].y,
|
||||
z,
|
||||
_fountainDirections[i],
|
||||
_fountainDirectionFlags[i] | _fountainPatternFlags[pattern],
|
||||
0);
|
||||
}
|
||||
break;
|
||||
case PATTERN::BOUNCING_PAIRS:
|
||||
// random [0, 2 or 1, 3]
|
||||
randomIndex = scenario_rand() & 1;
|
||||
for (int32_t i = randomIndex; i < 4; i += 2)
|
||||
{
|
||||
jumping_fountain_create(
|
||||
type,
|
||||
x + _fountainDirectionsPositive[i].x,
|
||||
y + _fountainDirectionsPositive[i].y,
|
||||
z,
|
||||
_fountainDirections[i],
|
||||
_fountainDirectionFlags[i] | _fountainPatternFlags[pattern],
|
||||
0);
|
||||
}
|
||||
break;
|
||||
case PATTERN::RACING_PAIRS:
|
||||
// random [0 - 3 and 4 - 7]
|
||||
randomIndex = scenario_rand() & 3;
|
||||
jumping_fountain_create(
|
||||
type,
|
||||
x + _fountainDirectionsPositive[i].x,
|
||||
y + _fountainDirectionsPositive[i].y,
|
||||
x + _fountainDirectionsPositive[randomIndex].x,
|
||||
y + _fountainDirectionsPositive[randomIndex].y,
|
||||
z,
|
||||
_fountainDirections[i],
|
||||
_fountainDirectionFlags[i] | _fountainPatternFlags[pattern],
|
||||
0
|
||||
);
|
||||
}
|
||||
break;
|
||||
case PATTERN::BOUNCING_PAIRS:
|
||||
// random [0, 2 or 1, 3]
|
||||
randomIndex = scenario_rand() & 1;
|
||||
for (int32_t i = randomIndex; i < 4; i += 2)
|
||||
{
|
||||
_fountainDirections[randomIndex],
|
||||
_fountainDirectionFlags[randomIndex] | _fountainPatternFlags[pattern],
|
||||
0);
|
||||
randomIndex += 4;
|
||||
jumping_fountain_create(
|
||||
type,
|
||||
x + _fountainDirectionsPositive[i].x,
|
||||
y + _fountainDirectionsPositive[i].y,
|
||||
x + _fountainDirectionsPositive[randomIndex].x,
|
||||
y + _fountainDirectionsPositive[randomIndex].y,
|
||||
z,
|
||||
_fountainDirections[i],
|
||||
_fountainDirectionFlags[i] | _fountainPatternFlags[pattern],
|
||||
0
|
||||
);
|
||||
}
|
||||
break;
|
||||
case PATTERN::RACING_PAIRS:
|
||||
// random [0 - 3 and 4 - 7]
|
||||
randomIndex = scenario_rand() & 3;
|
||||
jumping_fountain_create(
|
||||
type,
|
||||
x + _fountainDirectionsPositive[randomIndex].x,
|
||||
y + _fountainDirectionsPositive[randomIndex].y,
|
||||
z,
|
||||
_fountainDirections[randomIndex],
|
||||
_fountainDirectionFlags[randomIndex] | _fountainPatternFlags[pattern],
|
||||
0
|
||||
);
|
||||
randomIndex += 4;
|
||||
jumping_fountain_create(
|
||||
type,
|
||||
x + _fountainDirectionsPositive[randomIndex].x,
|
||||
y + _fountainDirectionsPositive[randomIndex].y,
|
||||
z,
|
||||
_fountainDirections[randomIndex],
|
||||
_fountainDirectionFlags[randomIndex] | _fountainPatternFlags[pattern],
|
||||
0
|
||||
);
|
||||
break;
|
||||
default:
|
||||
// random [0 - 7]
|
||||
randomIndex = scenario_rand() & 7;
|
||||
jumping_fountain_create(
|
||||
type,
|
||||
x + _fountainDirectionsPositive[randomIndex].x,
|
||||
y + _fountainDirectionsPositive[randomIndex].y,
|
||||
z,
|
||||
_fountainDirections[randomIndex],
|
||||
_fountainDirectionFlags[randomIndex] | _fountainPatternFlags[pattern],
|
||||
0
|
||||
);
|
||||
break;
|
||||
_fountainDirections[randomIndex],
|
||||
_fountainDirectionFlags[randomIndex] | _fountainPatternFlags[pattern],
|
||||
0);
|
||||
break;
|
||||
default:
|
||||
// random [0 - 7]
|
||||
randomIndex = scenario_rand() & 7;
|
||||
jumping_fountain_create(
|
||||
type,
|
||||
x + _fountainDirectionsPositive[randomIndex].x,
|
||||
y + _fountainDirectionsPositive[randomIndex].y,
|
||||
z,
|
||||
_fountainDirections[randomIndex],
|
||||
_fountainDirectionFlags[randomIndex] | _fountainPatternFlags[pattern],
|
||||
0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void jumping_fountain_create(int32_t type, int32_t x, int32_t y, int32_t z, int32_t direction, int32_t flags, int32_t iteration)
|
||||
{
|
||||
rct_jumping_fountain * jumpingFountain = (rct_jumping_fountain *)create_sprite(SPRITE_IDENTIFIER_MISC);
|
||||
rct_jumping_fountain* jumpingFountain = (rct_jumping_fountain*)create_sprite(SPRITE_IDENTIFIER_MISC);
|
||||
if (jumpingFountain != nullptr)
|
||||
{
|
||||
jumpingFountain->iteration = iteration;
|
||||
|
@ -180,16 +165,15 @@ void jumping_fountain_create(int32_t type, int32_t x, int32_t y, int32_t z, int3
|
|||
jumpingFountain->sprite_height_negative = 36;
|
||||
jumpingFountain->sprite_height_positive = 12;
|
||||
jumpingFountain->sprite_identifier = SPRITE_IDENTIFIER_MISC;
|
||||
sprite_move(x, y, z, (rct_sprite *)jumpingFountain);
|
||||
jumpingFountain->misc_identifier = type == JUMPING_FOUNTAIN_TYPE_SNOW ?
|
||||
SPRITE_MISC_JUMPING_FOUNTAIN_SNOW :
|
||||
SPRITE_MISC_JUMPING_FOUNTAIN_WATER;
|
||||
sprite_move(x, y, z, (rct_sprite*)jumpingFountain);
|
||||
jumpingFountain->misc_identifier
|
||||
= type == JUMPING_FOUNTAIN_TYPE_SNOW ? SPRITE_MISC_JUMPING_FOUNTAIN_SNOW : SPRITE_MISC_JUMPING_FOUNTAIN_WATER;
|
||||
jumpingFountain->num_ticks_alive = 0;
|
||||
jumpingFountain->frame = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void jumping_fountain_update(rct_jumping_fountain * jumpingFountain)
|
||||
void jumping_fountain_update(rct_jumping_fountain* jumpingFountain)
|
||||
{
|
||||
jumpingFountain->num_ticks_alive++;
|
||||
// Originaly this would not update the frame on the following
|
||||
|
@ -201,26 +185,27 @@ void jumping_fountain_update(rct_jumping_fountain * jumpingFountain)
|
|||
return;
|
||||
}
|
||||
|
||||
invalidate_sprite_0((rct_sprite *)jumpingFountain);
|
||||
invalidate_sprite_0((rct_sprite*)jumpingFountain);
|
||||
jumpingFountain->frame++;
|
||||
|
||||
switch (jumpingFountain->misc_identifier) {
|
||||
case SPRITE_MISC_JUMPING_FOUNTAIN_WATER:
|
||||
if (jumpingFountain->frame == 11 && (jumpingFountain->fountain_flags & FOUNTAIN_FLAG::FAST))
|
||||
{
|
||||
jumping_fountain_continue(jumpingFountain);
|
||||
}
|
||||
if (jumpingFountain->frame == 16 && !(jumpingFountain->fountain_flags & FOUNTAIN_FLAG::FAST))
|
||||
{
|
||||
jumping_fountain_continue(jumpingFountain);
|
||||
}
|
||||
break;
|
||||
case SPRITE_MISC_JUMPING_FOUNTAIN_SNOW:
|
||||
if (jumpingFountain->frame == 16)
|
||||
{
|
||||
jumping_fountain_continue(jumpingFountain);
|
||||
}
|
||||
break;
|
||||
switch (jumpingFountain->misc_identifier)
|
||||
{
|
||||
case SPRITE_MISC_JUMPING_FOUNTAIN_WATER:
|
||||
if (jumpingFountain->frame == 11 && (jumpingFountain->fountain_flags & FOUNTAIN_FLAG::FAST))
|
||||
{
|
||||
jumping_fountain_continue(jumpingFountain);
|
||||
}
|
||||
if (jumpingFountain->frame == 16 && !(jumpingFountain->fountain_flags & FOUNTAIN_FLAG::FAST))
|
||||
{
|
||||
jumping_fountain_continue(jumpingFountain);
|
||||
}
|
||||
break;
|
||||
case SPRITE_MISC_JUMPING_FOUNTAIN_SNOW:
|
||||
if (jumpingFountain->frame == 16)
|
||||
{
|
||||
jumping_fountain_continue(jumpingFountain);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (jumpingFountain->frame == 16)
|
||||
|
@ -229,16 +214,14 @@ void jumping_fountain_update(rct_jumping_fountain * jumpingFountain)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static int32_t jumping_fountain_get_type(const rct_jumping_fountain * jumpingFountain)
|
||||
static int32_t jumping_fountain_get_type(const rct_jumping_fountain* jumpingFountain)
|
||||
{
|
||||
int32_t type = jumpingFountain->misc_identifier == SPRITE_MISC_JUMPING_FOUNTAIN_SNOW ?
|
||||
JUMPING_FOUNTAIN_TYPE_SNOW :
|
||||
JUMPING_FOUNTAIN_TYPE_WATER;
|
||||
int32_t type = jumpingFountain->misc_identifier == SPRITE_MISC_JUMPING_FOUNTAIN_SNOW ? JUMPING_FOUNTAIN_TYPE_SNOW
|
||||
: JUMPING_FOUNTAIN_TYPE_WATER;
|
||||
return type;
|
||||
}
|
||||
|
||||
static void jumping_fountain_continue(rct_jumping_fountain * jumpingFountain)
|
||||
static void jumping_fountain_continue(rct_jumping_fountain* jumpingFountain)
|
||||
{
|
||||
int32_t type = jumping_fountain_get_type(jumpingFountain);
|
||||
int32_t direction = (jumpingFountain->sprite_direction >> 3) & 7;
|
||||
|
@ -290,31 +273,34 @@ static bool is_jumping_fountain(int32_t type, int32_t x, int32_t y, int32_t z)
|
|||
{
|
||||
z = z >> 3;
|
||||
|
||||
int32_t pathBitFlagMask = type == JUMPING_FOUNTAIN_TYPE_SNOW ?
|
||||
PATH_BIT_FLAG_JUMPING_FOUNTAIN_SNOW :
|
||||
PATH_BIT_FLAG_JUMPING_FOUNTAIN_WATER;
|
||||
int32_t pathBitFlagMask
|
||||
= type == JUMPING_FOUNTAIN_TYPE_SNOW ? PATH_BIT_FLAG_JUMPING_FOUNTAIN_SNOW : PATH_BIT_FLAG_JUMPING_FOUNTAIN_WATER;
|
||||
|
||||
rct_tile_element * tileElement = map_get_first_element_at(x >> 5, y >> 5);
|
||||
rct_tile_element* tileElement = map_get_first_element_at(x >> 5, y >> 5);
|
||||
do
|
||||
{
|
||||
if (tileElement->GetType() != TILE_ELEMENT_TYPE_PATH) continue;
|
||||
if (tileElement->base_height != z) continue;
|
||||
if (footpath_element_path_scenery_is_ghost(tileElement)) continue;
|
||||
if (!footpath_element_has_path_scenery(tileElement)) continue;
|
||||
if (tileElement->GetType() != TILE_ELEMENT_TYPE_PATH)
|
||||
continue;
|
||||
if (tileElement->base_height != z)
|
||||
continue;
|
||||
if (footpath_element_path_scenery_is_ghost(tileElement))
|
||||
continue;
|
||||
if (!footpath_element_has_path_scenery(tileElement))
|
||||
continue;
|
||||
|
||||
uint8_t additionIndex = footpath_element_get_path_scenery_index(tileElement);
|
||||
rct_scenery_entry * sceneryEntry = get_footpath_item_entry(additionIndex);
|
||||
rct_scenery_entry* sceneryEntry = get_footpath_item_entry(additionIndex);
|
||||
if (sceneryEntry != reinterpret_cast<void*>(-1) && sceneryEntry->path_bit.flags & pathBitFlagMask)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
while (!(tileElement++)->IsLastForTile());
|
||||
} while (!(tileElement++)->IsLastForTile());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void jumping_fountain_goto_edge(const rct_jumping_fountain * jumpingFountain, int32_t x, int32_t y, int32_t z, int32_t availableDirections)
|
||||
static void jumping_fountain_goto_edge(
|
||||
const rct_jumping_fountain* jumpingFountain, int32_t x, int32_t y, int32_t z, int32_t availableDirections)
|
||||
{
|
||||
int32_t direction = (jumpingFountain->sprite_direction >> 3) << 1;
|
||||
if (availableDirections & (1 << direction))
|
||||
|
@ -351,7 +337,8 @@ static void jumping_fountain_goto_edge(const rct_jumping_fountain * jumpingFount
|
|||
jumping_fountain_create_next(jumpingFountain, x, y, z, direction);
|
||||
}
|
||||
|
||||
static void jumping_fountain_bounce(rct_jumping_fountain * jumpingFountain, int32_t x, int32_t y, int32_t z, int32_t availableDirections)
|
||||
static void
|
||||
jumping_fountain_bounce(rct_jumping_fountain* jumpingFountain, int32_t x, int32_t y, int32_t z, int32_t availableDirections)
|
||||
{
|
||||
jumpingFountain->iteration++;
|
||||
if (jumpingFountain->iteration < 8)
|
||||
|
@ -372,7 +359,8 @@ static void jumping_fountain_bounce(rct_jumping_fountain * jumpingFountain, int3
|
|||
}
|
||||
}
|
||||
|
||||
static void jumping_fountain_split(const rct_jumping_fountain * jumpingFountain, int32_t x, int32_t y, int32_t z, int32_t availableDirections)
|
||||
static void jumping_fountain_split(
|
||||
const rct_jumping_fountain* jumpingFountain, int32_t x, int32_t y, int32_t z, int32_t availableDirections)
|
||||
{
|
||||
if (jumpingFountain->iteration < 3)
|
||||
{
|
||||
|
@ -387,28 +375,31 @@ static void jumping_fountain_split(const rct_jumping_fountain * jumpingFountain,
|
|||
{
|
||||
jumping_fountain_create(
|
||||
type,
|
||||
x, y, z,
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
direction >> 1,
|
||||
jumpingFountain->fountain_flags & ~FOUNTAIN_FLAG::DIRECTION,
|
||||
jumpingFountain->iteration + 1
|
||||
);
|
||||
jumpingFountain->iteration + 1);
|
||||
}
|
||||
direction++;
|
||||
if (availableDirections & (1 << direction))
|
||||
{
|
||||
jumping_fountain_create(
|
||||
type,
|
||||
x, y, z,
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
direction >> 1,
|
||||
jumpingFountain->fountain_flags | FOUNTAIN_FLAG::DIRECTION,
|
||||
jumpingFountain->iteration + 1
|
||||
);
|
||||
jumpingFountain->iteration + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void jumping_fountain_random(const rct_jumping_fountain * jumpingFountain, int32_t x, int32_t y, int32_t z, int32_t availableDirections)
|
||||
static void jumping_fountain_random(
|
||||
const rct_jumping_fountain* jumpingFountain, int32_t x, int32_t y, int32_t z, int32_t availableDirections)
|
||||
{
|
||||
uint32_t randomIndex = scenario_rand();
|
||||
if ((randomIndex & 0xFFFF) >= 0x2000)
|
||||
|
@ -422,7 +413,8 @@ static void jumping_fountain_random(const rct_jumping_fountain * jumpingFountain
|
|||
}
|
||||
}
|
||||
|
||||
static void jumping_fountain_create_next(const rct_jumping_fountain * jumpingFountain, int32_t x, int32_t y, int32_t z, int32_t direction)
|
||||
static void jumping_fountain_create_next(
|
||||
const rct_jumping_fountain* jumpingFountain, int32_t x, int32_t y, int32_t z, int32_t direction)
|
||||
{
|
||||
int32_t type = jumping_fountain_get_type(jumpingFountain);
|
||||
int32_t flags = jumpingFountain->fountain_flags & ~FOUNTAIN_FLAG::DIRECTION;
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "../common.h"
|
||||
|
||||
#include "Map.h"
|
||||
#include "Sprite.h"
|
||||
|
||||
|
@ -20,7 +19,7 @@ enum
|
|||
JUMPING_FOUNTAIN_TYPE_SNOW
|
||||
};
|
||||
|
||||
void jumping_fountain_begin(int32_t type, int32_t x, int32_t y, const rct_tile_element * tileElement);
|
||||
void jumping_fountain_create(int32_t type, int32_t x, int32_t y, int32_t z, int32_t direction, int32_t flags, int32_t iteration);
|
||||
void jumping_fountain_update(rct_jumping_fountain * jumpingFountain);
|
||||
|
||||
void jumping_fountain_begin(int32_t type, int32_t x, int32_t y, const rct_tile_element* tileElement);
|
||||
void jumping_fountain_create(
|
||||
int32_t type, int32_t x, int32_t y, int32_t z, int32_t direction, int32_t flags, int32_t iteration);
|
||||
void jumping_fountain_update(rct_jumping_fountain* jumpingFountain);
|
||||
|
|
|
@ -7,28 +7,29 @@
|
|||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "../common.h"
|
||||
#include "LargeScenery.h"
|
||||
|
||||
#include "../common.h"
|
||||
#include "TileElement.h"
|
||||
|
||||
colour_t scenery_large_get_primary_colour(const rct_tile_element * tileElement)
|
||||
colour_t scenery_large_get_primary_colour(const rct_tile_element* tileElement)
|
||||
{
|
||||
return tileElement->properties.scenerymultiple.colour[0] & TILE_ELEMENT_COLOUR_MASK;
|
||||
}
|
||||
|
||||
colour_t scenery_large_get_secondary_colour(const rct_tile_element * tileElement)
|
||||
colour_t scenery_large_get_secondary_colour(const rct_tile_element* tileElement)
|
||||
{
|
||||
return tileElement->properties.scenerymultiple.colour[1] & TILE_ELEMENT_COLOUR_MASK;
|
||||
}
|
||||
|
||||
void scenery_large_set_primary_colour(rct_tile_element * tileElement, colour_t colour)
|
||||
void scenery_large_set_primary_colour(rct_tile_element* tileElement, colour_t colour)
|
||||
{
|
||||
assert(colour <= 31);
|
||||
tileElement->properties.scenerymultiple.colour[0] &= ~TILE_ELEMENT_COLOUR_MASK;
|
||||
tileElement->properties.scenerymultiple.colour[0] |= colour;
|
||||
}
|
||||
|
||||
void scenery_large_set_secondary_colour(rct_tile_element * tileElement, colour_t colour)
|
||||
void scenery_large_set_secondary_colour(rct_tile_element* tileElement, colour_t colour)
|
||||
{
|
||||
assert(colour <= 31);
|
||||
tileElement->properties.scenerymultiple.colour[1] &= ~TILE_ELEMENT_COLOUR_MASK;
|
||||
|
@ -37,35 +38,34 @@ void scenery_large_set_secondary_colour(rct_tile_element * tileElement, colour_t
|
|||
|
||||
BannerIndex scenery_large_get_banner_id(const rct_tile_element* tileElement)
|
||||
{
|
||||
return (tileElement->type & 0xC0) |
|
||||
(((tileElement->properties.scenerymultiple.colour[0]) &~ TILE_ELEMENT_COLOUR_MASK) >> 2) |
|
||||
(((tileElement->properties.scenerymultiple.colour[1]) &~ TILE_ELEMENT_COLOUR_MASK) >> 5);
|
||||
return (tileElement->type & 0xC0) | (((tileElement->properties.scenerymultiple.colour[0]) & ~TILE_ELEMENT_COLOUR_MASK) >> 2)
|
||||
| (((tileElement->properties.scenerymultiple.colour[1]) & ~TILE_ELEMENT_COLOUR_MASK) >> 5);
|
||||
}
|
||||
|
||||
void scenery_large_set_banner_id(rct_tile_element * tileElement, BannerIndex bannerIndex)
|
||||
void scenery_large_set_banner_id(rct_tile_element* tileElement, BannerIndex bannerIndex)
|
||||
{
|
||||
tileElement->type |= bannerIndex & 0xC0;
|
||||
tileElement->properties.scenerymultiple.colour[0] |= (bannerIndex & 0x38) << 2;
|
||||
tileElement->properties.scenerymultiple.colour[1] |= (bannerIndex & 7) << 5;
|
||||
}
|
||||
|
||||
int32_t scenery_large_get_type(const rct_tile_element * tileElement)
|
||||
int32_t scenery_large_get_type(const rct_tile_element* tileElement)
|
||||
{
|
||||
return (tileElement->properties.scenerymultiple.type & TILE_ELEMENT_LARGE_TYPE_MASK);
|
||||
}
|
||||
|
||||
int32_t scenery_large_get_sequence(const rct_tile_element * tileElement)
|
||||
int32_t scenery_large_get_sequence(const rct_tile_element* tileElement)
|
||||
{
|
||||
return (tileElement->properties.scenerymultiple.type >> 10);
|
||||
}
|
||||
|
||||
void scenery_large_set_type(rct_tile_element * tileElement, uint16_t type)
|
||||
void scenery_large_set_type(rct_tile_element* tileElement, uint16_t type)
|
||||
{
|
||||
tileElement->properties.scenerymultiple.type &= ~TILE_ELEMENT_LARGE_TYPE_MASK;
|
||||
tileElement->properties.scenerymultiple.type |= (type & TILE_ELEMENT_LARGE_TYPE_MASK);
|
||||
}
|
||||
|
||||
void scenery_large_set_sequence(rct_tile_element * tileElement, uint16_t sequence)
|
||||
void scenery_large_set_sequence(rct_tile_element* tileElement, uint16_t sequence)
|
||||
{
|
||||
tileElement->properties.scenerymultiple.type &= TILE_ELEMENT_LARGE_TYPE_MASK;
|
||||
tileElement->properties.scenerymultiple.type |= (sequence << 10);
|
||||
|
|
|
@ -13,13 +13,13 @@
|
|||
#include "Map.h"
|
||||
#include "TileElement.h"
|
||||
|
||||
colour_t scenery_large_get_primary_colour(const rct_tile_element * tileElement);
|
||||
colour_t scenery_large_get_secondary_colour(const rct_tile_element * tileElement);
|
||||
void scenery_large_set_primary_colour(rct_tile_element * tileElement, colour_t colour);
|
||||
void scenery_large_set_secondary_colour(rct_tile_element * tileElement, colour_t colour);
|
||||
colour_t scenery_large_get_primary_colour(const rct_tile_element* tileElement);
|
||||
colour_t scenery_large_get_secondary_colour(const rct_tile_element* tileElement);
|
||||
void scenery_large_set_primary_colour(rct_tile_element* tileElement, colour_t colour);
|
||||
void scenery_large_set_secondary_colour(rct_tile_element* tileElement, colour_t colour);
|
||||
BannerIndex scenery_large_get_banner_id(const rct_tile_element* tileElement);
|
||||
void scenery_large_set_banner_id(rct_tile_element * tileElement, BannerIndex bannerIndex);
|
||||
int32_t scenery_large_get_type(const rct_tile_element * tileElement);
|
||||
int32_t scenery_large_get_sequence(const rct_tile_element * tileElement);
|
||||
void scenery_large_set_type(rct_tile_element * tileElement, uint16_t type);
|
||||
void scenery_large_set_sequence(rct_tile_element * tileElement, uint16_t sequence);
|
||||
void scenery_large_set_banner_id(rct_tile_element* tileElement, BannerIndex bannerIndex);
|
||||
int32_t scenery_large_get_type(const rct_tile_element* tileElement);
|
||||
int32_t scenery_large_get_sequence(const rct_tile_element* tileElement);
|
||||
void scenery_large_set_type(rct_tile_element* tileElement, uint16_t type);
|
||||
void scenery_large_set_sequence(rct_tile_element* tileElement, uint16_t sequence);
|
||||
|
|
|
@ -11,14 +11,20 @@
|
|||
|
||||
#include "../common.h"
|
||||
|
||||
#define LOCATION_NULL ((int16_t)(uint16_t)0x8000)
|
||||
#define LOCATION_NULL ((int16_t)(uint16_t)0x8000)
|
||||
#define RCT_XY8_UNDEFINED 0xFFFF
|
||||
#define MakeXY16(x, y) {(int16_t)(x), (int16_t)(y)}
|
||||
#define MakeXY16(x, y) \
|
||||
{ \
|
||||
(int16_t)(x), (int16_t)(y) \
|
||||
}
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct LocationXY8 {
|
||||
union {
|
||||
struct {
|
||||
struct LocationXY8
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8_t x, y;
|
||||
};
|
||||
uint16_t xy;
|
||||
|
@ -26,18 +32,20 @@ struct LocationXY8 {
|
|||
};
|
||||
assert_struct_size(LocationXY8, 2);
|
||||
|
||||
struct sLocationXY8 {
|
||||
struct sLocationXY8
|
||||
{
|
||||
int8_t x, y;
|
||||
};
|
||||
assert_struct_size(sLocationXY8, 2);
|
||||
|
||||
struct LocationXY16 {
|
||||
struct LocationXY16
|
||||
{
|
||||
int16_t x, y;
|
||||
};
|
||||
assert_struct_size(LocationXY16, 4);
|
||||
|
||||
|
||||
struct LocationXYZ16 {
|
||||
struct LocationXYZ16
|
||||
{
|
||||
int16_t x, y, z;
|
||||
};
|
||||
assert_struct_size(LocationXYZ16, 6);
|
||||
|
@ -57,8 +65,16 @@ struct CoordsXY
|
|||
struct TileCoordsXY
|
||||
{
|
||||
TileCoordsXY() = default;
|
||||
TileCoordsXY(int32_t x_, int32_t y_) : x(x_), y(y_) {}
|
||||
explicit TileCoordsXY(CoordsXY c) : x(c.x / 32), y(c.y / 32) {}
|
||||
TileCoordsXY(int32_t x_, int32_t y_)
|
||||
: x(x_)
|
||||
, y(y_)
|
||||
{
|
||||
}
|
||||
explicit TileCoordsXY(CoordsXY c)
|
||||
: x(c.x / 32)
|
||||
, y(c.y / 32)
|
||||
{
|
||||
}
|
||||
TileCoordsXY& operator+=(const TileCoordsXY rhs)
|
||||
{
|
||||
x += rhs.x;
|
||||
|
@ -76,9 +92,24 @@ struct CoordsXYZ
|
|||
struct TileCoordsXYZ
|
||||
{
|
||||
TileCoordsXYZ() = default;
|
||||
TileCoordsXYZ(int32_t x_, int32_t y_, int32_t z_) : x(x_), y(y_), z(z_) {}
|
||||
explicit TileCoordsXYZ(CoordsXY c, int32_t z_) : x(c.x / 32), y(c.y / 32), z(z_) {}
|
||||
explicit TileCoordsXYZ(CoordsXYZ c) : x(c.x / 32), y(c.y / 32), z(c.z / 8) {}
|
||||
TileCoordsXYZ(int32_t x_, int32_t y_, int32_t z_)
|
||||
: x(x_)
|
||||
, y(y_)
|
||||
, z(z_)
|
||||
{
|
||||
}
|
||||
explicit TileCoordsXYZ(CoordsXY c, int32_t z_)
|
||||
: x(c.x / 32)
|
||||
, y(c.y / 32)
|
||||
, z(z_)
|
||||
{
|
||||
}
|
||||
explicit TileCoordsXYZ(CoordsXYZ c)
|
||||
: x(c.x / 32)
|
||||
, y(c.y / 32)
|
||||
, z(c.z / 8)
|
||||
{
|
||||
}
|
||||
TileCoordsXYZ& operator+=(const TileCoordsXY rhs)
|
||||
{
|
||||
x += rhs.x;
|
||||
|
@ -93,7 +124,10 @@ struct CoordsXYZD
|
|||
int32_t x, y, z;
|
||||
uint8_t direction;
|
||||
|
||||
bool isNull() const { return x == COORDS_NULL; };
|
||||
bool isNull() const
|
||||
{
|
||||
return x == COORDS_NULL;
|
||||
};
|
||||
};
|
||||
|
||||
struct TileCoordsXYZD
|
||||
|
@ -101,5 +135,8 @@ struct TileCoordsXYZD
|
|||
int32_t x, y, z;
|
||||
uint8_t direction;
|
||||
|
||||
bool isNull() const { return x == COORDS_NULL; };
|
||||
bool isNull() const
|
||||
{
|
||||
return x == COORDS_NULL;
|
||||
};
|
||||
};
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -10,18 +10,19 @@
|
|||
#ifndef _MAP_H_
|
||||
#define _MAP_H_
|
||||
|
||||
#include <initializer_list>
|
||||
#include "../common.h"
|
||||
#include "Location.hpp"
|
||||
#include "TileElement.h"
|
||||
|
||||
#include <initializer_list>
|
||||
|
||||
#define MINIMUM_LAND_HEIGHT 2
|
||||
#define MAXIMUM_LAND_HEIGHT 142
|
||||
|
||||
#define MINIMUM_MAP_SIZE_TECHNICAL 15
|
||||
#define MAXIMUM_MAP_SIZE_TECHNICAL 256
|
||||
#define MINIMUM_MAP_SIZE_PRACTICAL (MINIMUM_MAP_SIZE_TECHNICAL-2)
|
||||
#define MAXIMUM_MAP_SIZE_PRACTICAL (MAXIMUM_MAP_SIZE_TECHNICAL-2)
|
||||
#define MINIMUM_MAP_SIZE_PRACTICAL (MINIMUM_MAP_SIZE_TECHNICAL - 2)
|
||||
#define MAXIMUM_MAP_SIZE_PRACTICAL (MAXIMUM_MAP_SIZE_TECHNICAL - 2)
|
||||
|
||||
#define MAP_MINIMUM_X_Y (-MAXIMUM_MAP_SIZE_TECHNICAL)
|
||||
|
||||
|
@ -39,17 +40,19 @@ typedef CoordsXYZD PeepSpawn;
|
|||
struct CoordsXYE
|
||||
{
|
||||
int32_t x, y;
|
||||
rct_tile_element * element;
|
||||
rct_tile_element* element;
|
||||
};
|
||||
|
||||
enum {
|
||||
MAP_SELECT_FLAG_ENABLE = 1 << 0,
|
||||
MAP_SELECT_FLAG_ENABLE_CONSTRUCT = 1 << 1,
|
||||
MAP_SELECT_FLAG_ENABLE_ARROW = 1 << 2,
|
||||
MAP_SELECT_FLAG_GREEN = 1 << 3,
|
||||
enum
|
||||
{
|
||||
MAP_SELECT_FLAG_ENABLE = 1 << 0,
|
||||
MAP_SELECT_FLAG_ENABLE_CONSTRUCT = 1 << 1,
|
||||
MAP_SELECT_FLAG_ENABLE_ARROW = 1 << 2,
|
||||
MAP_SELECT_FLAG_GREEN = 1 << 3,
|
||||
};
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
MAP_SELECT_TYPE_CORNER_0,
|
||||
MAP_SELECT_TYPE_CORNER_1,
|
||||
MAP_SELECT_TYPE_CORNER_2,
|
||||
|
@ -90,22 +93,22 @@ extern int16_t gMapSize;
|
|||
extern int16_t gMapSizeMaxXY;
|
||||
extern int16_t gMapBaseZ;
|
||||
|
||||
extern uint16_t gMapSelectFlags;
|
||||
extern uint16_t gMapSelectType;
|
||||
extern LocationXY16 gMapSelectPositionA;
|
||||
extern LocationXY16 gMapSelectPositionB;
|
||||
extern LocationXYZ16 gMapSelectArrowPosition;
|
||||
extern uint8_t gMapSelectArrowDirection;
|
||||
extern uint16_t gMapSelectFlags;
|
||||
extern uint16_t gMapSelectType;
|
||||
extern LocationXY16 gMapSelectPositionA;
|
||||
extern LocationXY16 gMapSelectPositionB;
|
||||
extern LocationXYZ16 gMapSelectArrowPosition;
|
||||
extern uint8_t gMapSelectArrowDirection;
|
||||
|
||||
extern uint8_t gMapGroundFlags;
|
||||
|
||||
extern rct_tile_element gTileElements[MAX_TILE_TILE_ELEMENT_POINTERS * 3];
|
||||
extern rct_tile_element *gTileElementTilePointers[MAX_TILE_TILE_ELEMENT_POINTERS];
|
||||
extern rct_tile_element* gTileElementTilePointers[MAX_TILE_TILE_ELEMENT_POINTERS];
|
||||
|
||||
extern LocationXY16 gMapSelectionTiles[300];
|
||||
extern PeepSpawn gPeepSpawns[MAX_PEEP_SPAWNS];
|
||||
|
||||
extern rct_tile_element *gNextFreeTileElement;
|
||||
extern rct_tile_element* gNextFreeTileElement;
|
||||
extern uint32_t gNextFreeTileElementPointerIndex;
|
||||
|
||||
// Used in the land tool window to enable mountain tool / land smoothing
|
||||
|
@ -128,19 +131,19 @@ void map_init(int32_t size);
|
|||
void map_count_remaining_land_rights();
|
||||
void map_strip_ghost_flag_from_elements();
|
||||
void map_update_tile_pointers();
|
||||
rct_tile_element *map_get_first_element_at(int32_t x, int32_t y);
|
||||
rct_tile_element *map_get_nth_element_at(int32_t x, int32_t y, int32_t n);
|
||||
void map_set_tile_elements(int32_t x, int32_t y, rct_tile_element *elements);
|
||||
rct_tile_element* map_get_first_element_at(int32_t x, int32_t y);
|
||||
rct_tile_element* map_get_nth_element_at(int32_t x, int32_t y, int32_t n);
|
||||
void map_set_tile_elements(int32_t x, int32_t y, rct_tile_element* elements);
|
||||
int32_t map_height_from_slope(int32_t x, int32_t y, int32_t slope);
|
||||
rct_tile_element* map_get_banner_element_at(int32_t x, int32_t y, int32_t z, uint8_t direction);
|
||||
rct_tile_element *map_get_surface_element_at(int32_t x, int32_t y);
|
||||
rct_tile_element * map_get_surface_element_at(CoordsXY coords);
|
||||
rct_tile_element* map_get_surface_element_at(int32_t x, int32_t y);
|
||||
rct_tile_element* map_get_surface_element_at(CoordsXY coords);
|
||||
rct_tile_element* map_get_path_element_at(int32_t x, int32_t y, int32_t z);
|
||||
rct_tile_element *map_get_wall_element_at(int32_t x, int32_t y, int32_t z, int32_t direction);
|
||||
rct_tile_element *map_get_small_scenery_element_at(int32_t x, int32_t y, int32_t z, int32_t type, uint8_t quadrant);
|
||||
rct_tile_element *map_get_park_entrance_element_at(int32_t x, int32_t y, int32_t z, bool ghost);
|
||||
rct_tile_element * map_get_ride_entrance_element_at(int32_t x, int32_t y, int32_t z, bool ghost);
|
||||
rct_tile_element * map_get_ride_exit_element_at(int32_t x, int32_t y, int32_t z, bool ghost);
|
||||
rct_tile_element* map_get_wall_element_at(int32_t x, int32_t y, int32_t z, int32_t direction);
|
||||
rct_tile_element* map_get_small_scenery_element_at(int32_t x, int32_t y, int32_t z, int32_t type, uint8_t quadrant);
|
||||
rct_tile_element* map_get_park_entrance_element_at(int32_t x, int32_t y, int32_t z, bool ghost);
|
||||
rct_tile_element* map_get_ride_entrance_element_at(int32_t x, int32_t y, int32_t z, bool ghost);
|
||||
rct_tile_element* map_get_ride_exit_element_at(int32_t x, int32_t y, int32_t z, bool ghost);
|
||||
int32_t tile_element_height(int32_t x, int32_t y);
|
||||
bool map_coord_is_connected(int32_t x, int32_t y, int32_t z, uint8_t faceDirection);
|
||||
void map_remove_provisional_elements();
|
||||
|
@ -153,78 +156,118 @@ bool map_is_location_owned(int32_t x, int32_t y, int32_t z);
|
|||
bool map_is_location_in_park(CoordsXY coords);
|
||||
bool map_is_location_owned_or_has_rights(int32_t x, int32_t y);
|
||||
bool map_surface_is_blocked(int16_t x, int16_t y);
|
||||
void tile_element_remove(rct_tile_element *tileElement);
|
||||
void tile_element_remove(rct_tile_element* tileElement);
|
||||
void map_remove_all_rides();
|
||||
void map_invalidate_map_selection_tiles();
|
||||
void map_get_bounding_box(int32_t ax, int32_t ay, int32_t bx, int32_t by, int32_t *left, int32_t *top, int32_t *right, int32_t *bottom);
|
||||
void map_get_bounding_box(
|
||||
int32_t ax, int32_t ay, int32_t bx, int32_t by, int32_t* left, int32_t* top, int32_t* right, int32_t* bottom);
|
||||
void map_invalidate_selection_rect();
|
||||
void map_reorganise_elements();
|
||||
bool map_check_free_elements_and_reorganise(int32_t num_elements);
|
||||
rct_tile_element *tile_element_insert(int32_t x, int32_t y, int32_t z, int32_t flags);
|
||||
rct_tile_element* tile_element_insert(int32_t x, int32_t y, int32_t z, int32_t flags);
|
||||
|
||||
using CLEAR_FUNC = int32_t(*)(rct_tile_element** tile_element, int32_t x, int32_t y, uint8_t flags, money32* price);
|
||||
using CLEAR_FUNC = int32_t (*)(rct_tile_element** tile_element, int32_t x, int32_t y, uint8_t flags, money32* price);
|
||||
|
||||
int32_t map_place_non_scenery_clear_func(rct_tile_element** tile_element, int32_t x, int32_t y, uint8_t flags, money32* price);
|
||||
int32_t map_place_scenery_clear_func(rct_tile_element** tile_element, int32_t x, int32_t y, uint8_t flags, money32* price);
|
||||
bool map_can_construct_with_clear_at(int32_t x, int32_t y, int32_t zLow, int32_t zHigh, CLEAR_FUNC clearFunc, uint8_t bl, uint8_t flags, money32 *price, uint8_t crossingMode);
|
||||
bool map_can_construct_with_clear_at(
|
||||
int32_t x,
|
||||
int32_t y,
|
||||
int32_t zLow,
|
||||
int32_t zHigh,
|
||||
CLEAR_FUNC clearFunc,
|
||||
uint8_t bl,
|
||||
uint8_t flags,
|
||||
money32* price,
|
||||
uint8_t crossingMode);
|
||||
int32_t map_can_construct_at(int32_t x, int32_t y, int32_t zLow, int32_t zHigh, uint8_t bl);
|
||||
void rotate_map_coordinates(int16_t *x, int16_t *y, int32_t rotation);
|
||||
void rotate_map_coordinates(int16_t* x, int16_t* y, int32_t rotation);
|
||||
LocationXY16 coordinate_3d_to_2d(const LocationXYZ16* coordinate_3d, int32_t rotation);
|
||||
money32 map_clear_scenery(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t clear, int32_t flags);
|
||||
money32 lower_water(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint8_t flags);
|
||||
money32 raise_water(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint8_t flags);
|
||||
money32 wall_place(int32_t type, int32_t x, int32_t y, int32_t z, int32_t edge, int32_t primaryColour, int32_t secondaryColour, int32_t tertiaryColour, int32_t flags);
|
||||
money32 wall_place(
|
||||
int32_t type,
|
||||
int32_t x,
|
||||
int32_t y,
|
||||
int32_t z,
|
||||
int32_t edge,
|
||||
int32_t primaryColour,
|
||||
int32_t secondaryColour,
|
||||
int32_t tertiaryColour,
|
||||
int32_t flags);
|
||||
|
||||
void game_command_set_land_height(int32_t *eax, int32_t *ebx, int32_t *ecx, int32_t *edx, int32_t *esi, int32_t *edi, int32_t *ebp);
|
||||
void game_command_set_land_ownership(int32_t *eax, int32_t *ebx, int32_t *ecx, int32_t *edx, int32_t *esi, int32_t *edi, int32_t *ebp);
|
||||
void game_command_remove_scenery(int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_remove_large_scenery(int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_remove_banner(int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_set_scenery_colour(int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_set_wall_colour(int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_set_large_scenery_colour(int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_set_banner_colour(int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_clear_scenery(int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_change_surface_style(int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_set_land_height(
|
||||
int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_set_land_ownership(
|
||||
int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_remove_scenery(
|
||||
int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_remove_large_scenery(
|
||||
int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_remove_banner(
|
||||
int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_set_scenery_colour(
|
||||
int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_set_wall_colour(
|
||||
int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_set_large_scenery_colour(
|
||||
int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_set_banner_colour(
|
||||
int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_clear_scenery(
|
||||
int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_change_surface_style(
|
||||
int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_raise_land(int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_lower_land(int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_smooth_land(int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_raise_water(int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_lower_water(int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_set_water_height(int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_place_banner(int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_place_scenery(int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_set_water_height(
|
||||
int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_place_banner(
|
||||
int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_place_scenery(
|
||||
int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_place_wall(int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_place_large_scenery(int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_place_park_entrance(int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_set_banner_name(int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_set_banner_style(int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_set_sign_style(int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_place_large_scenery(
|
||||
int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_place_park_entrance(
|
||||
int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_set_banner_name(
|
||||
int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_set_banner_style(
|
||||
int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_set_sign_style(
|
||||
int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_modify_tile(int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
|
||||
struct tile_element_iterator{
|
||||
struct tile_element_iterator
|
||||
{
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
rct_tile_element *element;
|
||||
rct_tile_element* element;
|
||||
};
|
||||
#ifdef PLATFORM_32BIT
|
||||
assert_struct_size(tile_element_iterator, 12);
|
||||
#endif
|
||||
|
||||
void tile_element_iterator_begin(tile_element_iterator *it);
|
||||
int32_t tile_element_iterator_next(tile_element_iterator *it);
|
||||
void tile_element_iterator_restart_for_tile(tile_element_iterator *it);
|
||||
void tile_element_iterator_begin(tile_element_iterator* it);
|
||||
int32_t tile_element_iterator_next(tile_element_iterator* it);
|
||||
void tile_element_iterator_restart_for_tile(tile_element_iterator* it);
|
||||
|
||||
void wall_remove_intersecting_walls(int32_t x, int32_t y, int32_t z0, int32_t z1, int32_t direction);
|
||||
void map_update_tiles();
|
||||
int32_t map_get_highest_z(int32_t tileX, int32_t tileY);
|
||||
|
||||
bool tile_element_wants_path_connection_towards(TileCoordsXYZD coords, const rct_tile_element * const elementToBeRemoved);
|
||||
bool tile_element_wants_path_connection_towards(TileCoordsXYZD coords, const rct_tile_element* const elementToBeRemoved);
|
||||
|
||||
void map_remove_out_of_range_elements();
|
||||
void map_extend_boundary_surface();
|
||||
|
||||
bool sign_set_colour(int32_t x, int32_t y, int32_t z, int32_t direction, int32_t sequence, uint8_t mainColour, uint8_t textColour);
|
||||
bool sign_set_colour(
|
||||
int32_t x, int32_t y, int32_t z, int32_t direction, int32_t sequence, uint8_t mainColour, uint8_t textColour);
|
||||
void wall_remove_at(int32_t x, int32_t y, int32_t z0, int32_t z1);
|
||||
void wall_remove_at_z(int32_t x, int32_t y, int32_t z);
|
||||
|
||||
|
@ -232,7 +275,7 @@ void map_invalidate_tile(int32_t x, int32_t y, int32_t z0, int32_t z1);
|
|||
void map_invalidate_tile_zoom1(int32_t x, int32_t y, int32_t z0, int32_t z1);
|
||||
void map_invalidate_tile_zoom0(int32_t x, int32_t y, int32_t z0, int32_t z1);
|
||||
void map_invalidate_tile_full(int32_t x, int32_t y);
|
||||
void map_invalidate_element(int32_t x, int32_t y, rct_tile_element *tileElement);
|
||||
void map_invalidate_element(int32_t x, int32_t y, rct_tile_element* tileElement);
|
||||
void map_invalidate_region(const LocationXY16& mins, const LocationXY16& maxs);
|
||||
|
||||
int32_t map_get_tile_side(int32_t mapX, int32_t mapY);
|
||||
|
@ -240,24 +283,32 @@ int32_t map_get_tile_quadrant(int32_t mapX, int32_t mapY);
|
|||
|
||||
void map_clear_all_elements();
|
||||
|
||||
rct_tile_element *map_get_large_scenery_segment(int32_t x, int32_t y, int32_t z, int32_t direction, int32_t sequence);
|
||||
rct_tile_element* map_get_large_scenery_segment(int32_t x, int32_t y, int32_t z, int32_t direction, int32_t sequence);
|
||||
bool map_large_scenery_get_origin(
|
||||
int32_t x, int32_t y, int32_t z, int32_t direction, int32_t sequence,
|
||||
int32_t *outX, int32_t *outY, int32_t *outZ, rct_tile_element** outElement
|
||||
);
|
||||
int32_t x,
|
||||
int32_t y,
|
||||
int32_t z,
|
||||
int32_t direction,
|
||||
int32_t sequence,
|
||||
int32_t* outX,
|
||||
int32_t* outY,
|
||||
int32_t* outZ,
|
||||
rct_tile_element** outElement);
|
||||
|
||||
void map_offset_with_rotation(int16_t *x, int16_t *y, int16_t offsetX, int16_t offsetY, uint8_t rotation);
|
||||
void map_offset_with_rotation(int16_t* x, int16_t* y, int16_t offsetX, int16_t offsetY, uint8_t rotation);
|
||||
CoordsXY translate_3d_to_2d_with_z(int32_t rotation, CoordsXYZ pos);
|
||||
|
||||
rct_tile_element *map_get_track_element_at(int32_t x, int32_t y, int32_t z);
|
||||
rct_tile_element *map_get_track_element_at_of_type(int32_t x, int32_t y, int32_t z, int32_t trackType);
|
||||
rct_tile_element *map_get_track_element_at_of_type_seq(int32_t x, int32_t y, int32_t z, int32_t trackType, int32_t sequence);
|
||||
rct_tile_element *map_get_track_element_at_of_type_from_ride(int32_t x, int32_t y, int32_t z, int32_t trackType, int32_t rideIndex);
|
||||
rct_tile_element *map_get_track_element_at_from_ride(int32_t x, int32_t y, int32_t z, int32_t rideIndex);
|
||||
rct_tile_element *map_get_track_element_at_with_direction_from_ride(int32_t x, int32_t y, int32_t z, int32_t direction, int32_t rideIndex);
|
||||
rct_tile_element* map_get_track_element_at(int32_t x, int32_t y, int32_t z);
|
||||
rct_tile_element* map_get_track_element_at_of_type(int32_t x, int32_t y, int32_t z, int32_t trackType);
|
||||
rct_tile_element* map_get_track_element_at_of_type_seq(int32_t x, int32_t y, int32_t z, int32_t trackType, int32_t sequence);
|
||||
rct_tile_element*
|
||||
map_get_track_element_at_of_type_from_ride(int32_t x, int32_t y, int32_t z, int32_t trackType, int32_t rideIndex);
|
||||
rct_tile_element* map_get_track_element_at_from_ride(int32_t x, int32_t y, int32_t z, int32_t rideIndex);
|
||||
rct_tile_element*
|
||||
map_get_track_element_at_with_direction_from_ride(int32_t x, int32_t y, int32_t z, int32_t direction, int32_t rideIndex);
|
||||
|
||||
bool map_is_location_at_edge(int32_t x, int32_t y);
|
||||
void map_obstruction_set_error_text(rct_tile_element *tileElement);
|
||||
void map_obstruction_set_error_text(rct_tile_element* tileElement);
|
||||
|
||||
uint32_t map_get_available_peep_spawn_index_list(uint32_t* peepSpawnIndexList);
|
||||
uint16_t check_max_allowable_land_rights_for_tile(uint8_t x, uint8_t y, uint8_t base_z);
|
||||
|
@ -267,6 +318,6 @@ void FixLandOwnershipTilesWithOwnership(std::initializer_list<TileCoordsXY> tile
|
|||
|
||||
bool place_peep_spawn(CoordsXYZD location);
|
||||
|
||||
uint8_t entrance_element_get_type(const rct_tile_element * tileElement);
|
||||
uint8_t entrance_element_get_type(const rct_tile_element* tileElement);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -7,24 +7,25 @@
|
|||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||
*****************************************************************************/
|
||||
|
||||
#include <cstring>
|
||||
#include "MapAnimation.h"
|
||||
|
||||
#include "../Game.h"
|
||||
#include "../interface/Viewport.h"
|
||||
#include "../ride/Ride.h"
|
||||
#include "../ride/RideData.h"
|
||||
#include "../ride/Track.h"
|
||||
#include "../interface/Viewport.h"
|
||||
#include "../world/Wall.h"
|
||||
#include "MapAnimation.h"
|
||||
#include "Footpath.h"
|
||||
#include "Map.h"
|
||||
#include "Scenery.h"
|
||||
#include "SmallScenery.h"
|
||||
#include "Sprite.h"
|
||||
#include "Footpath.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
using map_animation_invalidate_event_handler = bool (*)(int32_t x, int32_t y, int32_t baseZ);
|
||||
|
||||
static bool map_animation_invalidate(rct_map_animation *obj);
|
||||
static bool map_animation_invalidate(rct_map_animation* obj);
|
||||
|
||||
uint16_t gNumMapAnimations;
|
||||
rct_map_animation gAnimatedObjects[MAX_ANIMATED_OBJECTS];
|
||||
|
@ -40,13 +41,15 @@ rct_map_animation gAnimatedObjects[MAX_ANIMATED_OBJECTS];
|
|||
*/
|
||||
void map_animation_create(int32_t type, int32_t x, int32_t y, int32_t z)
|
||||
{
|
||||
rct_map_animation *aobj = &gAnimatedObjects[0];
|
||||
rct_map_animation* aobj = &gAnimatedObjects[0];
|
||||
int32_t numAnimatedObjects = gNumMapAnimations;
|
||||
if (numAnimatedObjects >= MAX_ANIMATED_OBJECTS) {
|
||||
if (numAnimatedObjects >= MAX_ANIMATED_OBJECTS)
|
||||
{
|
||||
log_error("Exceeded the maximum number of animations");
|
||||
return;
|
||||
}
|
||||
for (int32_t i = 0; i < numAnimatedObjects; i++, aobj++) {
|
||||
for (int32_t i = 0; i < numAnimatedObjects; i++, aobj++)
|
||||
{
|
||||
if (aobj->x != x)
|
||||
continue;
|
||||
if (aobj->y != y)
|
||||
|
@ -73,16 +76,20 @@ void map_animation_create(int32_t type, int32_t x, int32_t y, int32_t z)
|
|||
*/
|
||||
void map_animation_invalidate_all()
|
||||
{
|
||||
rct_map_animation *aobj = &gAnimatedObjects[0];
|
||||
rct_map_animation* aobj = &gAnimatedObjects[0];
|
||||
int32_t numAnimatedObjects = gNumMapAnimations;
|
||||
while (numAnimatedObjects > 0) {
|
||||
if (map_animation_invalidate(aobj)) {
|
||||
while (numAnimatedObjects > 0)
|
||||
{
|
||||
if (map_animation_invalidate(aobj))
|
||||
{
|
||||
// Remove animated object
|
||||
gNumMapAnimations--;
|
||||
numAnimatedObjects--;
|
||||
if (numAnimatedObjects > 0)
|
||||
memmove(aobj, aobj + 1, numAnimatedObjects * sizeof(rct_map_animation));
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
numAnimatedObjects--;
|
||||
aobj++;
|
||||
}
|
||||
|
@ -95,12 +102,13 @@ void map_animation_invalidate_all()
|
|||
*/
|
||||
static bool map_animation_invalidate_ride_entrance(int32_t x, int32_t y, int32_t baseZ)
|
||||
{
|
||||
rct_tile_element *tileElement;
|
||||
Ride *ride;
|
||||
const rct_ride_entrance_definition *entranceDefinition;
|
||||
rct_tile_element* tileElement;
|
||||
Ride* ride;
|
||||
const rct_ride_entrance_definition* entranceDefinition;
|
||||
|
||||
tileElement = map_get_first_element_at(x >> 5, y >> 5);
|
||||
do {
|
||||
do
|
||||
{
|
||||
if (tileElement->base_height != baseZ)
|
||||
continue;
|
||||
if (tileElement->GetType() != TILE_ELEMENT_TYPE_ENTRANCE)
|
||||
|
@ -125,10 +133,11 @@ static bool map_animation_invalidate_ride_entrance(int32_t x, int32_t y, int32_t
|
|||
*/
|
||||
static bool map_animation_invalidate_queue_banner(int32_t x, int32_t y, int32_t baseZ)
|
||||
{
|
||||
rct_tile_element *tileElement;
|
||||
rct_tile_element* tileElement;
|
||||
|
||||
tileElement = map_get_first_element_at(x >> 5, y >> 5);
|
||||
do {
|
||||
do
|
||||
{
|
||||
if (tileElement->base_height != baseZ)
|
||||
continue;
|
||||
if (tileElement->GetType() != TILE_ELEMENT_TYPE_PATH)
|
||||
|
@ -139,7 +148,8 @@ static bool map_animation_invalidate_queue_banner(int32_t x, int32_t y, int32_t
|
|||
continue;
|
||||
|
||||
int32_t direction = (footpath_element_get_direction(tileElement) + get_current_rotation()) & 3;
|
||||
if (direction == TILE_ELEMENT_DIRECTION_NORTH || direction == TILE_ELEMENT_DIRECTION_EAST) {
|
||||
if (direction == TILE_ELEMENT_DIRECTION_NORTH || direction == TILE_ELEMENT_DIRECTION_EAST)
|
||||
{
|
||||
baseZ = tileElement->base_height * 8;
|
||||
map_invalidate_tile_zoom1(x, y, baseZ + 16, baseZ + 30);
|
||||
}
|
||||
|
@ -155,13 +165,14 @@ static bool map_animation_invalidate_queue_banner(int32_t x, int32_t y, int32_t
|
|||
*/
|
||||
static bool map_animation_invalidate_small_scenery(int32_t x, int32_t y, int32_t baseZ)
|
||||
{
|
||||
rct_tile_element *tileElement;
|
||||
rct_scenery_entry *sceneryEntry;
|
||||
rct_sprite *sprite;
|
||||
rct_peep *peep;
|
||||
rct_tile_element* tileElement;
|
||||
rct_scenery_entry* sceneryEntry;
|
||||
rct_sprite* sprite;
|
||||
rct_peep* peep;
|
||||
|
||||
tileElement = map_get_first_element_at(x >> 5, y >> 5);
|
||||
do {
|
||||
do
|
||||
{
|
||||
if (tileElement->base_height != baseZ)
|
||||
continue;
|
||||
if (tileElement->GetType() != TILE_ELEMENT_TYPE_SMALL_SCENERY)
|
||||
|
@ -170,7 +181,10 @@ static bool map_animation_invalidate_small_scenery(int32_t x, int32_t y, int32_t
|
|||
continue;
|
||||
|
||||
sceneryEntry = get_small_scenery_entry(tileElement->properties.scenery.type);
|
||||
if (scenery_small_entry_has_flag(sceneryEntry, SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_1 | SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_4 | SMALL_SCENERY_FLAG_SWAMP_GOO | SMALL_SCENERY_FLAG_HAS_FRAME_OFFSETS))
|
||||
if (scenery_small_entry_has_flag(
|
||||
sceneryEntry,
|
||||
SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_1 | SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_4 | SMALL_SCENERY_FLAG_SWAMP_GOO
|
||||
| SMALL_SCENERY_FLAG_HAS_FRAME_OFFSETS))
|
||||
{
|
||||
map_invalidate_tile_zoom1(x, y, tileElement->base_height * 8, tileElement->clearance_height * 8);
|
||||
return false;
|
||||
|
@ -179,13 +193,15 @@ static bool map_animation_invalidate_small_scenery(int32_t x, int32_t y, int32_t
|
|||
if (scenery_small_entry_has_flag(sceneryEntry, SMALL_SCENERY_FLAG_IS_CLOCK))
|
||||
{
|
||||
// Peep, looking at scenery
|
||||
if (!(gCurrentTicks & 0x3FF) && game_is_not_paused()) {
|
||||
if (!(gCurrentTicks & 0x3FF) && game_is_not_paused())
|
||||
{
|
||||
int32_t direction = tile_element_get_direction(tileElement);
|
||||
int32_t x2 = x - CoordsDirectionDelta[direction].x;
|
||||
int32_t y2 = y - CoordsDirectionDelta[direction].y;
|
||||
|
||||
uint16_t spriteIdx = sprite_get_first_in_quadrant(x2, y2);
|
||||
for (; spriteIdx != SPRITE_INDEX_NULL; spriteIdx = sprite->unknown.next_in_quadrant) {
|
||||
for (; spriteIdx != SPRITE_INDEX_NULL; spriteIdx = sprite->unknown.next_in_quadrant)
|
||||
{
|
||||
sprite = get_sprite(spriteIdx);
|
||||
if (sprite->unknown.linked_list_type_offset != SPRITE_LIST_PEEP * 2)
|
||||
continue;
|
||||
|
@ -220,10 +236,11 @@ static bool map_animation_invalidate_small_scenery(int32_t x, int32_t y, int32_t
|
|||
*/
|
||||
static bool map_animation_invalidate_park_entrance(int32_t x, int32_t y, int32_t baseZ)
|
||||
{
|
||||
rct_tile_element *tileElement;
|
||||
rct_tile_element* tileElement;
|
||||
|
||||
tileElement = map_get_first_element_at(x >> 5, y >> 5);
|
||||
do {
|
||||
do
|
||||
{
|
||||
if (tileElement->base_height != baseZ)
|
||||
continue;
|
||||
if (tileElement->GetType() != TILE_ELEMENT_TYPE_ENTRANCE)
|
||||
|
@ -247,16 +264,18 @@ static bool map_animation_invalidate_park_entrance(int32_t x, int32_t y, int32_t
|
|||
*/
|
||||
static bool map_animation_invalidate_track_waterfall(int32_t x, int32_t y, int32_t baseZ)
|
||||
{
|
||||
rct_tile_element *tileElement;
|
||||
rct_tile_element* tileElement;
|
||||
|
||||
tileElement = map_get_first_element_at(x >> 5, y >> 5);
|
||||
do {
|
||||
do
|
||||
{
|
||||
if (tileElement->base_height != baseZ)
|
||||
continue;
|
||||
if (tileElement->GetType() != TILE_ELEMENT_TYPE_TRACK)
|
||||
continue;
|
||||
|
||||
if (track_element_get_type(tileElement) == TRACK_ELEM_WATERFALL) {
|
||||
if (track_element_get_type(tileElement) == TRACK_ELEM_WATERFALL)
|
||||
{
|
||||
int32_t z = tileElement->base_height * 8;
|
||||
map_invalidate_tile_zoom1(x, y, z + 14, z + 46);
|
||||
return false;
|
||||
|
@ -272,16 +291,18 @@ static bool map_animation_invalidate_track_waterfall(int32_t x, int32_t y, int32
|
|||
*/
|
||||
static bool map_animation_invalidate_track_rapids(int32_t x, int32_t y, int32_t baseZ)
|
||||
{
|
||||
rct_tile_element *tileElement;
|
||||
rct_tile_element* tileElement;
|
||||
|
||||
tileElement = map_get_first_element_at(x >> 5, y >> 5);
|
||||
do {
|
||||
do
|
||||
{
|
||||
if (tileElement->base_height != baseZ)
|
||||
continue;
|
||||
if (tileElement->GetType() != TILE_ELEMENT_TYPE_TRACK)
|
||||
continue;
|
||||
|
||||
if (track_element_get_type(tileElement) == TRACK_ELEM_RAPIDS) {
|
||||
if (track_element_get_type(tileElement) == TRACK_ELEM_RAPIDS)
|
||||
{
|
||||
int32_t z = tileElement->base_height * 8;
|
||||
map_invalidate_tile_zoom1(x, y, z + 14, z + 18);
|
||||
return false;
|
||||
|
@ -297,10 +318,11 @@ static bool map_animation_invalidate_track_rapids(int32_t x, int32_t y, int32_t
|
|||
*/
|
||||
static bool map_animation_invalidate_track_onridephoto(int32_t x, int32_t y, int32_t baseZ)
|
||||
{
|
||||
rct_tile_element *tileElement;
|
||||
rct_tile_element* tileElement;
|
||||
|
||||
tileElement = map_get_first_element_at(x >> 5, y >> 5);
|
||||
do {
|
||||
do
|
||||
{
|
||||
if (tileElement == nullptr)
|
||||
break;
|
||||
if (tileElement->base_height != baseZ)
|
||||
|
@ -308,15 +330,20 @@ static bool map_animation_invalidate_track_onridephoto(int32_t x, int32_t y, int
|
|||
if (tileElement->GetType() != TILE_ELEMENT_TYPE_TRACK)
|
||||
continue;
|
||||
|
||||
if (track_element_get_type(tileElement) == TRACK_ELEM_ON_RIDE_PHOTO) {
|
||||
if (track_element_get_type(tileElement) == TRACK_ELEM_ON_RIDE_PHOTO)
|
||||
{
|
||||
map_invalidate_tile_zoom1(x, y, tileElement->base_height * 8, tileElement->clearance_height * 8);
|
||||
if (game_is_paused()) {
|
||||
if (game_is_paused())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (tile_element_is_taking_photo(tileElement)) {
|
||||
if (tile_element_is_taking_photo(tileElement))
|
||||
{
|
||||
tile_element_decrement_onride_photo_timout(tileElement);
|
||||
return false;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -331,16 +358,18 @@ static bool map_animation_invalidate_track_onridephoto(int32_t x, int32_t y, int
|
|||
*/
|
||||
static bool map_animation_invalidate_track_whirlpool(int32_t x, int32_t y, int32_t baseZ)
|
||||
{
|
||||
rct_tile_element *tileElement;
|
||||
rct_tile_element* tileElement;
|
||||
|
||||
tileElement = map_get_first_element_at(x >> 5, y >> 5);
|
||||
do {
|
||||
do
|
||||
{
|
||||
if (tileElement->base_height != baseZ)
|
||||
continue;
|
||||
if (tileElement->GetType() != TILE_ELEMENT_TYPE_TRACK)
|
||||
continue;
|
||||
|
||||
if (track_element_get_type(tileElement) == TRACK_ELEM_WHIRLPOOL) {
|
||||
if (track_element_get_type(tileElement) == TRACK_ELEM_WHIRLPOOL)
|
||||
{
|
||||
int32_t z = tileElement->base_height * 8;
|
||||
map_invalidate_tile_zoom1(x, y, z + 14, z + 18);
|
||||
return false;
|
||||
|
@ -356,16 +385,18 @@ static bool map_animation_invalidate_track_whirlpool(int32_t x, int32_t y, int32
|
|||
*/
|
||||
static bool map_animation_invalidate_track_spinningtunnel(int32_t x, int32_t y, int32_t baseZ)
|
||||
{
|
||||
rct_tile_element *tileElement;
|
||||
rct_tile_element* tileElement;
|
||||
|
||||
tileElement = map_get_first_element_at(x >> 5, y >> 5);
|
||||
do {
|
||||
do
|
||||
{
|
||||
if (tileElement->base_height != baseZ)
|
||||
continue;
|
||||
if (tileElement->GetType() != TILE_ELEMENT_TYPE_TRACK)
|
||||
continue;
|
||||
|
||||
if (track_element_get_type(tileElement) == TRACK_ELEM_SPINNING_TUNNEL) {
|
||||
if (track_element_get_type(tileElement) == TRACK_ELEM_SPINNING_TUNNEL)
|
||||
{
|
||||
int32_t z = tileElement->base_height * 8;
|
||||
map_invalidate_tile_zoom1(x, y, z + 14, z + 32);
|
||||
return false;
|
||||
|
@ -379,7 +410,8 @@ static bool map_animation_invalidate_track_spinningtunnel(int32_t x, int32_t y,
|
|||
*
|
||||
* rct2: 0x0068DF8F
|
||||
*/
|
||||
static bool map_animation_invalidate_remove([[maybe_unused]] int32_t x, [[maybe_unused]] int32_t y, [[maybe_unused]] int32_t baseZ)
|
||||
static bool
|
||||
map_animation_invalidate_remove([[maybe_unused]] int32_t x, [[maybe_unused]] int32_t y, [[maybe_unused]] int32_t baseZ)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -390,10 +422,11 @@ static bool map_animation_invalidate_remove([[maybe_unused]] int32_t x, [[maybe_
|
|||
*/
|
||||
static bool map_animation_invalidate_banner(int32_t x, int32_t y, int32_t baseZ)
|
||||
{
|
||||
rct_tile_element *tileElement;
|
||||
rct_tile_element* tileElement;
|
||||
|
||||
tileElement = map_get_first_element_at(x >> 5, y >> 5);
|
||||
do {
|
||||
do
|
||||
{
|
||||
if (tileElement->base_height != baseZ)
|
||||
continue;
|
||||
if (tileElement->GetType() != TILE_ELEMENT_TYPE_BANNER)
|
||||
|
@ -413,19 +446,21 @@ static bool map_animation_invalidate_banner(int32_t x, int32_t y, int32_t baseZ)
|
|||
*/
|
||||
static bool map_animation_invalidate_large_scenery(int32_t x, int32_t y, int32_t baseZ)
|
||||
{
|
||||
rct_tile_element *tileElement;
|
||||
rct_scenery_entry *sceneryEntry;
|
||||
rct_tile_element* tileElement;
|
||||
rct_scenery_entry* sceneryEntry;
|
||||
|
||||
bool wasInvalidated = false;
|
||||
tileElement = map_get_first_element_at(x >> 5, y >> 5);
|
||||
do {
|
||||
do
|
||||
{
|
||||
if (tileElement->base_height != baseZ)
|
||||
continue;
|
||||
if (tileElement->GetType() != TILE_ELEMENT_TYPE_LARGE_SCENERY)
|
||||
continue;
|
||||
|
||||
sceneryEntry = get_large_scenery_entry(tileElement->properties.scenery.type & 0x3FF);
|
||||
if (sceneryEntry->large_scenery.flags & LARGE_SCENERY_FLAG_ANIMATED) {
|
||||
if (sceneryEntry->large_scenery.flags & LARGE_SCENERY_FLAG_ANIMATED)
|
||||
{
|
||||
int32_t z = tileElement->base_height * 8;
|
||||
map_invalidate_tile_zoom1(x, y, z, z + 16);
|
||||
wasInvalidated = true;
|
||||
|
@ -441,15 +476,16 @@ static bool map_animation_invalidate_large_scenery(int32_t x, int32_t y, int32_t
|
|||
*/
|
||||
static bool map_animation_invalidate_wall_door(int32_t x, int32_t y, int32_t baseZ)
|
||||
{
|
||||
rct_tile_element *tileElement;
|
||||
rct_scenery_entry *sceneryEntry;
|
||||
rct_tile_element* tileElement;
|
||||
rct_scenery_entry* sceneryEntry;
|
||||
|
||||
if (gCurrentTicks & 1)
|
||||
return false;
|
||||
|
||||
bool removeAnimation = true;
|
||||
tileElement = map_get_first_element_at(x >> 5, y >> 5);
|
||||
do {
|
||||
do
|
||||
{
|
||||
if (tileElement->base_height != baseZ)
|
||||
continue;
|
||||
if (tileElement->GetType() != TILE_ELEMENT_TYPE_WALL)
|
||||
|
@ -459,19 +495,25 @@ static bool map_animation_invalidate_wall_door(int32_t x, int32_t y, int32_t bas
|
|||
if (!(sceneryEntry->wall.flags & WALL_SCENERY_IS_DOOR))
|
||||
continue;
|
||||
|
||||
if (game_is_paused()) {
|
||||
if (game_is_paused())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool invalidate = false;
|
||||
|
||||
uint8_t currentFrame = wall_get_animation_frame(tileElement);
|
||||
if (currentFrame != 0) {
|
||||
if (currentFrame == 15) {
|
||||
if (currentFrame != 0)
|
||||
{
|
||||
if (currentFrame == 15)
|
||||
{
|
||||
currentFrame = 0;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
removeAnimation = false;
|
||||
if (currentFrame != 5) {
|
||||
if (currentFrame != 5)
|
||||
{
|
||||
currentFrame++;
|
||||
if (currentFrame == 13 && !(sceneryEntry->wall.flags & WALL_SCENERY_LONG_DOOR_ANIMATION))
|
||||
currentFrame = 15;
|
||||
|
@ -481,7 +523,8 @@ static bool map_animation_invalidate_wall_door(int32_t x, int32_t y, int32_t bas
|
|||
}
|
||||
}
|
||||
wall_set_animation_frame(tileElement, currentFrame);
|
||||
if (invalidate) {
|
||||
if (invalidate)
|
||||
{
|
||||
int32_t z = tileElement->base_height * 8;
|
||||
map_invalidate_tile_zoom1(x, y, z, z + 32);
|
||||
}
|
||||
|
@ -496,12 +539,13 @@ static bool map_animation_invalidate_wall_door(int32_t x, int32_t y, int32_t bas
|
|||
*/
|
||||
static bool map_animation_invalidate_wall(int32_t x, int32_t y, int32_t baseZ)
|
||||
{
|
||||
rct_tile_element *tileElement;
|
||||
rct_scenery_entry *sceneryEntry;
|
||||
rct_tile_element* tileElement;
|
||||
rct_scenery_entry* sceneryEntry;
|
||||
|
||||
bool wasInvalidated = false;
|
||||
tileElement = map_get_first_element_at(x >> 5, y >> 5);
|
||||
do {
|
||||
do
|
||||
{
|
||||
if (tileElement->base_height != baseZ)
|
||||
continue;
|
||||
if (tileElement->GetType() != TILE_ELEMENT_TYPE_WALL)
|
||||
|
@ -524,29 +568,28 @@ static bool map_animation_invalidate_wall(int32_t x, int32_t y, int32_t baseZ)
|
|||
*
|
||||
* rct2: 0x009819DC
|
||||
*/
|
||||
static constexpr const map_animation_invalidate_event_handler _animatedObjectEventHandlers[MAP_ANIMATION_TYPE_COUNT] = {
|
||||
map_animation_invalidate_ride_entrance,
|
||||
map_animation_invalidate_queue_banner,
|
||||
map_animation_invalidate_small_scenery,
|
||||
map_animation_invalidate_park_entrance,
|
||||
map_animation_invalidate_track_waterfall,
|
||||
map_animation_invalidate_track_rapids,
|
||||
map_animation_invalidate_track_onridephoto,
|
||||
map_animation_invalidate_track_whirlpool,
|
||||
map_animation_invalidate_track_spinningtunnel,
|
||||
map_animation_invalidate_remove,
|
||||
map_animation_invalidate_banner,
|
||||
map_animation_invalidate_large_scenery,
|
||||
map_animation_invalidate_wall_door,
|
||||
map_animation_invalidate_wall
|
||||
};
|
||||
static constexpr const map_animation_invalidate_event_handler _animatedObjectEventHandlers[MAP_ANIMATION_TYPE_COUNT]
|
||||
= { map_animation_invalidate_ride_entrance,
|
||||
map_animation_invalidate_queue_banner,
|
||||
map_animation_invalidate_small_scenery,
|
||||
map_animation_invalidate_park_entrance,
|
||||
map_animation_invalidate_track_waterfall,
|
||||
map_animation_invalidate_track_rapids,
|
||||
map_animation_invalidate_track_onridephoto,
|
||||
map_animation_invalidate_track_whirlpool,
|
||||
map_animation_invalidate_track_spinningtunnel,
|
||||
map_animation_invalidate_remove,
|
||||
map_animation_invalidate_banner,
|
||||
map_animation_invalidate_large_scenery,
|
||||
map_animation_invalidate_wall_door,
|
||||
map_animation_invalidate_wall };
|
||||
|
||||
/**
|
||||
* @returns true if the animation should be removed.
|
||||
*/
|
||||
static bool map_animation_invalidate(rct_map_animation *obj)
|
||||
static bool map_animation_invalidate(rct_map_animation* obj)
|
||||
{
|
||||
assert(obj->type < MAP_ANIMATION_TYPE_COUNT);
|
||||
|
||||
|
||||
return _animatedObjectEventHandlers[obj->type](obj->x, obj->y, obj->baseZ);
|
||||
}
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
* Animated object
|
||||
* size: 0x06
|
||||
*/
|
||||
struct rct_map_animation {
|
||||
struct rct_map_animation
|
||||
{
|
||||
uint8_t baseZ;
|
||||
uint8_t type;
|
||||
uint16_t x;
|
||||
|
@ -26,7 +27,8 @@ struct rct_map_animation {
|
|||
assert_struct_size(rct_map_animation, 6);
|
||||
#pragma pack(pop)
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
MAP_ANIMATION_TYPE_RIDE_ENTRANCE,
|
||||
MAP_ANIMATION_TYPE_QUEUE_BANNER,
|
||||
MAP_ANIMATION_TYPE_SMALL_SCENERY,
|
||||
|
|
|
@ -7,83 +7,80 @@
|
|||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "../common.h"
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
#include "MapGen.h"
|
||||
|
||||
#include "../Context.h"
|
||||
#include "../Game.h"
|
||||
#include "../common.h"
|
||||
#include "../core/Guard.hpp"
|
||||
#include "../core/Imaging.h"
|
||||
#include "../core/Math.hpp"
|
||||
#include "../core/String.hpp"
|
||||
#include "../core/Util.hpp"
|
||||
#include "../Game.h"
|
||||
#include "../core/Imaging.h"
|
||||
#include "../localisation/StringIds.h"
|
||||
#include "../object/Object.h"
|
||||
#include "../platform/platform.h"
|
||||
#include "../util/Util.h"
|
||||
#include "Map.h"
|
||||
#include "MapHelpers.h"
|
||||
#include "MapGen.h"
|
||||
#include "Scenery.h"
|
||||
#include "SmallScenery.h"
|
||||
#include "Surface.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
#pragma region Height map struct
|
||||
|
||||
static struct
|
||||
{
|
||||
uint32_t width, height;
|
||||
uint8_t * mono_bitmap;
|
||||
} _heightMapData = {
|
||||
0,
|
||||
0,
|
||||
nullptr
|
||||
};
|
||||
uint8_t* mono_bitmap;
|
||||
} _heightMapData = { 0, 0, nullptr };
|
||||
|
||||
#pragma endregion Height map struct
|
||||
|
||||
#pragma region Random objects
|
||||
|
||||
static constexpr const char * GrassTrees[] = {
|
||||
static constexpr const char* GrassTrees[] = {
|
||||
// Dark
|
||||
"TCF ", // Caucasian Fir Tree
|
||||
"TRF ", // Red Fir Tree
|
||||
"TRF2 ", // Red Fir Tree
|
||||
"TSP ", // Scots Pine Tree
|
||||
"TMZP ", // Montezuma Pine Tree
|
||||
"TAP ", // Aleppo Pine Tree
|
||||
"TCRP ", // Corsican Pine Tree
|
||||
"TBP ", // Black Poplar Tree
|
||||
"TCF ", // Caucasian Fir Tree
|
||||
"TRF ", // Red Fir Tree
|
||||
"TRF2 ", // Red Fir Tree
|
||||
"TSP ", // Scots Pine Tree
|
||||
"TMZP ", // Montezuma Pine Tree
|
||||
"TAP ", // Aleppo Pine Tree
|
||||
"TCRP ", // Corsican Pine Tree
|
||||
"TBP ", // Black Poplar Tree
|
||||
|
||||
// Light
|
||||
"TCL ", // Cedar of Lebanon Tree
|
||||
"TEL ", // European Larch Tree
|
||||
"TCL ", // Cedar of Lebanon Tree
|
||||
"TEL ", // European Larch Tree
|
||||
};
|
||||
|
||||
static constexpr const char * DesertTrees[] = {
|
||||
"TMP ", // Monkey-Puzzle Tree
|
||||
"THL ", // Honey Locust Tree
|
||||
"TH1 ", // Canary Palm Tree
|
||||
"TH2 ", // Palm Tree
|
||||
"TPM ", // Palm Tree
|
||||
"TROPT1 ", // Tree
|
||||
"TBC ", // Cactus
|
||||
"TSC ", // Cactus
|
||||
static constexpr const char* DesertTrees[] = {
|
||||
"TMP ", // Monkey-Puzzle Tree
|
||||
"THL ", // Honey Locust Tree
|
||||
"TH1 ", // Canary Palm Tree
|
||||
"TH2 ", // Palm Tree
|
||||
"TPM ", // Palm Tree
|
||||
"TROPT1 ", // Tree
|
||||
"TBC ", // Cactus
|
||||
"TSC ", // Cactus
|
||||
};
|
||||
|
||||
static constexpr const char * SnowTrees[] = {
|
||||
"TCFS ", // Snow-covered Caucasian Fir Tree
|
||||
"TNSS ", // Snow-covered Norway Spruce Tree
|
||||
"TRF3 ", // Snow-covered Red Fir Tree
|
||||
"TRFS ", // Snow-covered Red Fir Tree
|
||||
static constexpr const char* SnowTrees[] = {
|
||||
"TCFS ", // Snow-covered Caucasian Fir Tree
|
||||
"TNSS ", // Snow-covered Norway Spruce Tree
|
||||
"TRF3 ", // Snow-covered Red Fir Tree
|
||||
"TRFS ", // Snow-covered Red Fir Tree
|
||||
};
|
||||
|
||||
#pragma endregion
|
||||
|
||||
// Randomly chosen base terrains. We rarely want a whole map made out of chequerboard or rock.
|
||||
static constexpr const uint8_t BaseTerrain[] = {TERRAIN_GRASS, TERRAIN_SAND, TERRAIN_SAND_LIGHT, TERRAIN_DIRT, TERRAIN_ICE};
|
||||
static constexpr const uint8_t BaseTerrain[] = { TERRAIN_GRASS, TERRAIN_SAND, TERRAIN_SAND_LIGHT, TERRAIN_DIRT, TERRAIN_ICE };
|
||||
|
||||
#define BLOB_HEIGHT 255
|
||||
|
||||
|
@ -92,10 +89,10 @@ static void mapgen_set_water_level(int32_t waterLevel);
|
|||
static void mapgen_smooth_height(int32_t iterations);
|
||||
static void mapgen_set_height();
|
||||
|
||||
static void mapgen_simplex(mapgen_settings * settings);
|
||||
static void mapgen_simplex(mapgen_settings* settings);
|
||||
|
||||
static int32_t _heightSize;
|
||||
static uint8_t * _height;
|
||||
static int32_t _heightSize;
|
||||
static uint8_t* _height;
|
||||
|
||||
static int32_t get_height(int32_t x, int32_t y)
|
||||
{
|
||||
|
@ -111,10 +108,10 @@ static void set_height(int32_t x, int32_t y, int32_t height)
|
|||
_height[x + y * _heightSize] = height;
|
||||
}
|
||||
|
||||
void mapgen_generate_blank(mapgen_settings * settings)
|
||||
void mapgen_generate_blank(mapgen_settings* settings)
|
||||
{
|
||||
int32_t x, y;
|
||||
rct_tile_element * tileElement;
|
||||
rct_tile_element* tileElement;
|
||||
|
||||
map_clear_all_elements();
|
||||
|
||||
|
@ -126,7 +123,7 @@ void mapgen_generate_blank(mapgen_settings * settings)
|
|||
tileElement = map_get_surface_element_at(x, y);
|
||||
surface_set_terrain(tileElement, settings->floor);
|
||||
surface_set_terrain_edge(tileElement, settings->wall);
|
||||
tileElement->base_height = settings->height;
|
||||
tileElement->base_height = settings->height;
|
||||
tileElement->clearance_height = settings->height;
|
||||
}
|
||||
}
|
||||
|
@ -134,17 +131,17 @@ void mapgen_generate_blank(mapgen_settings * settings)
|
|||
mapgen_set_water_level(settings->water_level);
|
||||
}
|
||||
|
||||
void mapgen_generate(mapgen_settings * settings)
|
||||
void mapgen_generate(mapgen_settings* settings)
|
||||
{
|
||||
int32_t x, y, mapSize, floorTexture, wallTexture, waterLevel;
|
||||
rct_tile_element * tileElement;
|
||||
rct_tile_element* tileElement;
|
||||
|
||||
util_srand((int32_t) platform_get_ticks());
|
||||
util_srand((int32_t)platform_get_ticks());
|
||||
|
||||
mapSize = settings->mapSize;
|
||||
mapSize = settings->mapSize;
|
||||
floorTexture = settings->floor;
|
||||
wallTexture = settings->wall;
|
||||
waterLevel = settings->water_level;
|
||||
wallTexture = settings->wall;
|
||||
waterLevel = settings->water_level;
|
||||
|
||||
if (floorTexture == -1)
|
||||
floorTexture = BaseTerrain[util_rand() % Util::CountOf(BaseTerrain)];
|
||||
|
@ -154,15 +151,15 @@ void mapgen_generate(mapgen_settings * settings)
|
|||
// Base edge type on surface type
|
||||
switch (floorTexture)
|
||||
{
|
||||
case TERRAIN_DIRT:
|
||||
wallTexture = TERRAIN_EDGE_WOOD_RED;
|
||||
break;
|
||||
case TERRAIN_ICE:
|
||||
wallTexture = TERRAIN_EDGE_ICE;
|
||||
break;
|
||||
default:
|
||||
wallTexture = TERRAIN_EDGE_ROCK;
|
||||
break;
|
||||
case TERRAIN_DIRT:
|
||||
wallTexture = TERRAIN_EDGE_WOOD_RED;
|
||||
break;
|
||||
case TERRAIN_ICE:
|
||||
wallTexture = TERRAIN_EDGE_ICE;
|
||||
break;
|
||||
default:
|
||||
wallTexture = TERRAIN_EDGE_ROCK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -177,14 +174,14 @@ void mapgen_generate(mapgen_settings * settings)
|
|||
tileElement = map_get_surface_element_at(x, y);
|
||||
surface_set_terrain(tileElement, floorTexture);
|
||||
surface_set_terrain_edge(tileElement, wallTexture);
|
||||
tileElement->base_height = settings->height;
|
||||
tileElement->base_height = settings->height;
|
||||
tileElement->clearance_height = settings->height;
|
||||
}
|
||||
}
|
||||
|
||||
// Create the temporary height map and initialise
|
||||
_heightSize = mapSize * 2;
|
||||
_height = new uint8_t[_heightSize * _heightSize];
|
||||
_height = new uint8_t[_heightSize * _heightSize];
|
||||
memset(_height, 0, _heightSize * _heightSize * sizeof(uint8_t));
|
||||
|
||||
mapgen_simplex(settings);
|
||||
|
@ -195,7 +192,9 @@ void mapgen_generate(mapgen_settings * settings)
|
|||
delete[] _height;
|
||||
|
||||
// Set the tile slopes so that there are no cliffs
|
||||
while (map_smooth(1, 1, mapSize - 1, mapSize - 1)) {}
|
||||
while (map_smooth(1, 1, mapSize - 1, mapSize - 1))
|
||||
{
|
||||
}
|
||||
|
||||
// Add the water
|
||||
mapgen_set_water_level(waterLevel);
|
||||
|
@ -206,12 +205,12 @@ void mapgen_generate(mapgen_settings * settings)
|
|||
{
|
||||
switch (util_rand() % 4)
|
||||
{
|
||||
case 0:
|
||||
beachTexture = TERRAIN_SAND;
|
||||
break;
|
||||
case 1:
|
||||
beachTexture = TERRAIN_SAND_LIGHT;
|
||||
break;
|
||||
case 0:
|
||||
beachTexture = TERRAIN_SAND;
|
||||
break;
|
||||
case 1:
|
||||
beachTexture = TERRAIN_SAND_LIGHT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (y = 1; y < mapSize - 1; y++)
|
||||
|
@ -235,21 +234,21 @@ void mapgen_generate(mapgen_settings * settings)
|
|||
static void mapgen_place_tree(int32_t type, int32_t x, int32_t y)
|
||||
{
|
||||
int32_t surfaceZ;
|
||||
rct_tile_element * tileElement;
|
||||
rct_scenery_entry * sceneryEntry = get_small_scenery_entry(type);
|
||||
rct_tile_element* tileElement;
|
||||
rct_scenery_entry* sceneryEntry = get_small_scenery_entry(type);
|
||||
if (sceneryEntry == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
surfaceZ = tile_element_height(x * 32 + 16, y * 32 + 16) / 8;
|
||||
surfaceZ = tile_element_height(x * 32 + 16, y * 32 + 16) / 8;
|
||||
tileElement = tile_element_insert(x, y, surfaceZ, (1 | 2 | 4 | 8));
|
||||
assert(tileElement != nullptr);
|
||||
tileElement->clearance_height = surfaceZ + (sceneryEntry->small_scenery.height >> 3);
|
||||
|
||||
tileElement->type = TILE_ELEMENT_TYPE_SMALL_SCENERY | (util_rand() & 3);
|
||||
tileElement->type = TILE_ELEMENT_TYPE_SMALL_SCENERY | (util_rand() & 3);
|
||||
tileElement->properties.scenery.type = type;
|
||||
tileElement->properties.scenery.age = 0;
|
||||
tileElement->properties.scenery.age = 0;
|
||||
scenery_small_set_primary_colour(tileElement, COLOUR_YELLOW);
|
||||
}
|
||||
|
||||
|
@ -314,7 +313,7 @@ static void mapgen_place_trees()
|
|||
{
|
||||
for (int32_t x = 1; x < gMapSize - 1; x++)
|
||||
{
|
||||
rct_tile_element * tileElement = map_get_surface_element_at(x, y);
|
||||
rct_tile_element* tileElement = map_get_surface_element_at(x, y);
|
||||
|
||||
// Exclude water tiles
|
||||
if (surface_get_water_height(tileElement) > 0)
|
||||
|
@ -323,7 +322,6 @@ static void mapgen_place_trees()
|
|||
pos.x = x;
|
||||
pos.y = y;
|
||||
availablePositions.push_back(pos);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -335,47 +333,48 @@ static void mapgen_place_trees()
|
|||
continue;
|
||||
|
||||
tmp = availablePositions[i];
|
||||
availablePositions[i] = availablePositions[rindex];
|
||||
availablePositions[i] = availablePositions[rindex];
|
||||
availablePositions[rindex] = tmp;
|
||||
}
|
||||
|
||||
// Place trees
|
||||
float treeToLandRatio = (10 + (util_rand() % 30)) / 100.0f;
|
||||
int32_t numTrees = std::min(std::max(4, (int32_t) (availablePositions.size() * treeToLandRatio)), (int32_t)availablePositions.size());
|
||||
float treeToLandRatio = (10 + (util_rand() % 30)) / 100.0f;
|
||||
int32_t numTrees
|
||||
= std::min(std::max(4, (int32_t)(availablePositions.size() * treeToLandRatio)), (int32_t)availablePositions.size());
|
||||
|
||||
for (int32_t i = 0; i < numTrees; i++)
|
||||
{
|
||||
pos = availablePositions[i];
|
||||
|
||||
int32_t type = -1;
|
||||
rct_tile_element * tileElement = map_get_surface_element_at(pos.x, pos.y);
|
||||
rct_tile_element* tileElement = map_get_surface_element_at(pos.x, pos.y);
|
||||
switch (surface_get_terrain(tileElement))
|
||||
{
|
||||
case TERRAIN_GRASS:
|
||||
case TERRAIN_DIRT:
|
||||
case TERRAIN_GRASS_CLUMPS:
|
||||
if (grassTreeIds.size() == 0)
|
||||
case TERRAIN_GRASS:
|
||||
case TERRAIN_DIRT:
|
||||
case TERRAIN_GRASS_CLUMPS:
|
||||
if (grassTreeIds.size() == 0)
|
||||
break;
|
||||
|
||||
type = grassTreeIds[util_rand() % grassTreeIds.size()];
|
||||
break;
|
||||
|
||||
type = grassTreeIds[util_rand() % grassTreeIds.size()];
|
||||
break;
|
||||
case TERRAIN_SAND:
|
||||
case TERRAIN_SAND_DARK:
|
||||
case TERRAIN_SAND_LIGHT:
|
||||
if (desertTreeIds.size() == 0)
|
||||
break;
|
||||
|
||||
case TERRAIN_SAND:
|
||||
case TERRAIN_SAND_DARK:
|
||||
case TERRAIN_SAND_LIGHT:
|
||||
if (desertTreeIds.size() == 0)
|
||||
if (util_rand() % 4 == 0)
|
||||
type = desertTreeIds[util_rand() % desertTreeIds.size()];
|
||||
break;
|
||||
|
||||
if (util_rand() % 4 == 0)
|
||||
type = desertTreeIds[util_rand() % desertTreeIds.size()];
|
||||
break;
|
||||
case TERRAIN_ICE:
|
||||
if (snowTreeIds.size() == 0)
|
||||
break;
|
||||
|
||||
case TERRAIN_ICE:
|
||||
if (snowTreeIds.size() == 0)
|
||||
type = snowTreeIds[util_rand() % snowTreeIds.size()];
|
||||
break;
|
||||
|
||||
type = snowTreeIds[util_rand() % snowTreeIds.size()];
|
||||
break;
|
||||
}
|
||||
|
||||
if (type != -1)
|
||||
|
@ -389,7 +388,7 @@ static void mapgen_place_trees()
|
|||
static void mapgen_set_water_level(int32_t waterLevel)
|
||||
{
|
||||
int32_t x, y, mapSize;
|
||||
rct_tile_element * tileElement;
|
||||
rct_tile_element* tileElement;
|
||||
|
||||
mapSize = gMapSize;
|
||||
|
||||
|
@ -411,7 +410,7 @@ static void mapgen_smooth_height(int32_t iterations)
|
|||
{
|
||||
int32_t i, x, y, xx, yy, avg;
|
||||
int32_t arraySize = _heightSize * _heightSize * sizeof(uint8_t);
|
||||
uint8_t * copyHeight = new uint8_t[arraySize];
|
||||
uint8_t* copyHeight = new uint8_t[arraySize];
|
||||
|
||||
for (i = 0; i < iterations; i++)
|
||||
{
|
||||
|
@ -420,7 +419,7 @@ static void mapgen_smooth_height(int32_t iterations)
|
|||
{
|
||||
for (x = 1; x < _heightSize - 1; x++)
|
||||
{
|
||||
avg = 0;
|
||||
avg = 0;
|
||||
for (yy = -1; yy <= 1; yy++)
|
||||
{
|
||||
for (xx = -1; xx <= 1; xx++)
|
||||
|
@ -443,10 +442,10 @@ static void mapgen_smooth_height(int32_t iterations)
|
|||
static void mapgen_set_height()
|
||||
{
|
||||
int32_t x, y, heightX, heightY, mapSize;
|
||||
rct_tile_element * tileElement;
|
||||
rct_tile_element* tileElement;
|
||||
|
||||
mapSize = _heightSize / 2;
|
||||
for (y = 1; y < mapSize - 1; y++)
|
||||
for (y = 1; y < mapSize - 1; y++)
|
||||
{
|
||||
for (x = 1; x < mapSize - 1; x++)
|
||||
{
|
||||
|
@ -461,7 +460,7 @@ static void mapgen_set_height()
|
|||
uint8_t baseHeight = (q00 + q01 + q10 + q11) / 4;
|
||||
|
||||
tileElement = map_get_surface_element_at(x, y);
|
||||
tileElement->base_height = std::max(2, baseHeight * 2);
|
||||
tileElement->base_height = std::max(2, baseHeight * 2);
|
||||
tileElement->clearance_height = tileElement->base_height;
|
||||
|
||||
if (q00 > baseHeight)
|
||||
|
@ -493,7 +492,7 @@ static uint8_t perm[512];
|
|||
|
||||
static void noise_rand()
|
||||
{
|
||||
for (auto &i : perm)
|
||||
for (auto& i : perm)
|
||||
{
|
||||
i = util_rand() & 0xFF;
|
||||
}
|
||||
|
@ -501,9 +500,9 @@ static void noise_rand()
|
|||
|
||||
static float fractal_noise(int32_t x, int32_t y, float frequency, int32_t octaves, float lacunarity, float persistence)
|
||||
{
|
||||
float total = 0.0f;
|
||||
float amplitude = persistence;
|
||||
for (int32_t i = 0; i < octaves; i++)
|
||||
float total = 0.0f;
|
||||
float amplitude = persistence;
|
||||
for (int32_t i = 0; i < octaves; i++)
|
||||
{
|
||||
total += generate(x * frequency, y * frequency) * amplitude;
|
||||
frequency *= lacunarity;
|
||||
|
@ -520,13 +519,13 @@ static float generate(float x, float y)
|
|||
float n0, n1, n2; // Noise contributions from the three corners
|
||||
|
||||
// Skew the input space to determine which simplex cell we're in
|
||||
float s = (x + y) * F2; // Hairy factor for 2D
|
||||
float xs = x + s;
|
||||
float ys = y + s;
|
||||
int32_t i = fast_floor(xs);
|
||||
int32_t j = fast_floor(ys);
|
||||
float s = (x + y) * F2; // Hairy factor for 2D
|
||||
float xs = x + s;
|
||||
float ys = y + s;
|
||||
int32_t i = fast_floor(xs);
|
||||
int32_t j = fast_floor(ys);
|
||||
|
||||
float t = (float) (i + j) * G2;
|
||||
float t = (float)(i + j) * G2;
|
||||
float X0 = i - t; // Unskew the cell origin back to (x,y) space
|
||||
float Y0 = j - t;
|
||||
float x0 = x - X0; // The x,y distances from the cell origin
|
||||
|
@ -544,7 +543,7 @@ static float generate(float x, float y)
|
|||
{
|
||||
i1 = 0;
|
||||
j1 = 1;
|
||||
} // upper triangle, YX order: (0,0)->(0,1)->(1,1)
|
||||
} // upper triangle, YX order: (0,0)->(0,1)->(1,1)
|
||||
|
||||
// A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and
|
||||
// a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where
|
||||
|
@ -600,25 +599,25 @@ static float generate(float x, float y)
|
|||
|
||||
static int32_t fast_floor(float x)
|
||||
{
|
||||
return (x > 0) ? ((int32_t) x) : (((int32_t) x) - 1);
|
||||
return (x > 0) ? ((int32_t)x) : (((int32_t)x) - 1);
|
||||
}
|
||||
|
||||
static float grad(int32_t hash, float x, float y)
|
||||
{
|
||||
int32_t h = hash & 7; // Convert low 3 bits of hash code
|
||||
float u = h < 4 ? x : y; // into 8 simple gradient directions,
|
||||
float v = h < 4 ? y : x; // and compute the dot product with (x,y).
|
||||
int32_t h = hash & 7; // Convert low 3 bits of hash code
|
||||
float u = h < 4 ? x : y; // into 8 simple gradient directions,
|
||||
float v = h < 4 ? y : x; // and compute the dot product with (x,y).
|
||||
return ((h & 1) != 0 ? -u : u) + ((h & 2) != 0 ? -2.0f * v : 2.0f * v);
|
||||
}
|
||||
|
||||
static void mapgen_simplex(mapgen_settings * settings)
|
||||
static void mapgen_simplex(mapgen_settings* settings)
|
||||
{
|
||||
int32_t x, y;
|
||||
|
||||
float freq = settings->simplex_base_freq * (1.0f / _heightSize);
|
||||
float freq = settings->simplex_base_freq * (1.0f / _heightSize);
|
||||
int32_t octaves = settings->simplex_octaves;
|
||||
|
||||
int32_t low = settings->simplex_low;
|
||||
int32_t low = settings->simplex_low;
|
||||
int32_t high = settings->simplex_high;
|
||||
|
||||
noise_rand();
|
||||
|
@ -626,10 +625,10 @@ static void mapgen_simplex(mapgen_settings * settings)
|
|||
{
|
||||
for (x = 0; x < _heightSize; x++)
|
||||
{
|
||||
float noiseValue = Math::Clamp(-1.0f, fractal_noise(x, y, freq, octaves, 2.0f, 0.65f), 1.0f);
|
||||
float noiseValue = Math::Clamp(-1.0f, fractal_noise(x, y, freq, octaves, 2.0f, 0.65f), 1.0f);
|
||||
float normalisedNoiseValue = (noiseValue + 1.0f) / 2.0f;
|
||||
|
||||
set_height(x, y, low + (int32_t) (normalisedNoiseValue * high));
|
||||
set_height(x, y, low + (int32_t)(normalisedNoiseValue * high));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -638,7 +637,7 @@ static void mapgen_simplex(mapgen_settings * settings)
|
|||
|
||||
#pragma region Heightmap
|
||||
|
||||
bool mapgen_load_heightmap(const utf8 * path)
|
||||
bool mapgen_load_heightmap(const utf8* path)
|
||||
{
|
||||
auto format = Imaging::GetImageFormatFromPath(path);
|
||||
if (format == IMAGE_FORMAT::PNG)
|
||||
|
@ -709,17 +708,17 @@ bool mapgen_load_heightmap(const utf8 * path)
|
|||
void mapgen_unload_heightmap()
|
||||
{
|
||||
SafeDeleteArray(_heightMapData.mono_bitmap);
|
||||
_heightMapData.width = 0;
|
||||
_heightMapData.height = 0;
|
||||
_heightMapData.width = 0;
|
||||
_heightMapData.height = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies box blur to the surface N times
|
||||
*/
|
||||
static void mapgen_smooth_heightmap(uint8_t * src, int32_t strength)
|
||||
static void mapgen_smooth_heightmap(uint8_t* src, int32_t strength)
|
||||
{
|
||||
// Create buffer to store one channel
|
||||
uint8_t * dest = new uint8_t[_heightMapData.width * _heightMapData.height];
|
||||
uint8_t* dest = new uint8_t[_heightMapData.width * _heightMapData.height];
|
||||
|
||||
for (int32_t i = 0; i < strength; i++)
|
||||
{
|
||||
|
@ -737,8 +736,8 @@ static void mapgen_smooth_heightmap(uint8_t * src, int32_t strength)
|
|||
{
|
||||
// Clamp x and y so they stay within the image
|
||||
// This assumes the height map is not tiled, and increases the weight of the edges
|
||||
const int32_t readX = Math::Clamp((int32_t) x + offsetX, 0, (int32_t) _heightMapData.width - 1);
|
||||
const int32_t readY = Math::Clamp((int32_t) y + offsetY, 0, (int32_t) _heightMapData.height - 1);
|
||||
const int32_t readX = Math::Clamp((int32_t)x + offsetX, 0, (int32_t)_heightMapData.width - 1);
|
||||
const int32_t readY = Math::Clamp((int32_t)y + offsetY, 0, (int32_t)_heightMapData.height - 1);
|
||||
heightSum += src[readX + readY * _heightMapData.width];
|
||||
}
|
||||
}
|
||||
|
@ -761,14 +760,14 @@ static void mapgen_smooth_heightmap(uint8_t * src, int32_t strength)
|
|||
delete[] dest;
|
||||
}
|
||||
|
||||
void mapgen_generate_from_heightmap(mapgen_settings * settings)
|
||||
void mapgen_generate_from_heightmap(mapgen_settings* settings)
|
||||
{
|
||||
openrct2_assert(_heightMapData.width == _heightMapData.height, "Invalid height map size");
|
||||
openrct2_assert(_heightMapData.mono_bitmap != nullptr, "No height map loaded");
|
||||
openrct2_assert(settings->simplex_high != settings->simplex_low, "Low and high setting cannot be the same");
|
||||
|
||||
// Make a copy of the original height map that we can edit
|
||||
uint8_t * dest = new uint8_t[_heightMapData.width * _heightMapData.height];
|
||||
uint8_t* dest = new uint8_t[_heightMapData.width * _heightMapData.height];
|
||||
memcpy(dest, _heightMapData.mono_bitmap, _heightMapData.width * _heightMapData.width);
|
||||
|
||||
map_init(_heightMapData.width + 2); // + 2 for the black tiles around the map
|
||||
|
@ -791,8 +790,8 @@ void mapgen_generate_from_heightmap(mapgen_settings * settings)
|
|||
for (uint32_t x = 0; x < _heightMapData.width; x++)
|
||||
{
|
||||
uint8_t value = dest[x + y * _heightMapData.width];
|
||||
maxValue = std::max(maxValue, value);
|
||||
minValue = std::min(minValue, value);
|
||||
maxValue = std::max(maxValue, value);
|
||||
minValue = std::min(minValue, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -807,7 +806,7 @@ void mapgen_generate_from_heightmap(mapgen_settings * settings)
|
|||
openrct2_assert(maxValue > minValue, "Input range is invalid");
|
||||
openrct2_assert(settings->simplex_high > settings->simplex_low, "Output range is invalid");
|
||||
|
||||
const uint8_t rangeIn = maxValue - minValue;
|
||||
const uint8_t rangeIn = maxValue - minValue;
|
||||
const uint8_t rangeOut = settings->simplex_high - settings->simplex_low;
|
||||
|
||||
for (uint32_t y = 0; y < _heightMapData.height; y++)
|
||||
|
@ -815,12 +814,12 @@ void mapgen_generate_from_heightmap(mapgen_settings * settings)
|
|||
for (uint32_t x = 0; x < _heightMapData.width; x++)
|
||||
{
|
||||
// The x and y axis are flipped in the world, so this uses y for x and x for y.
|
||||
rct_tile_element * const surfaceElement = map_get_surface_element_at(y + 1, x + 1);
|
||||
rct_tile_element* const surfaceElement = map_get_surface_element_at(y + 1, x + 1);
|
||||
|
||||
// Read value from bitmap, and convert its range
|
||||
uint8_t value = dest[x + y * _heightMapData.width];
|
||||
value = (uint8_t) ((float) (value - minValue) / rangeIn * rangeOut) + settings->simplex_low;
|
||||
surfaceElement->base_height = value;
|
||||
value = (uint8_t)((float)(value - minValue) / rangeIn * rangeOut) + settings->simplex_low;
|
||||
surfaceElement->base_height = value;
|
||||
|
||||
// Floor to even number
|
||||
surfaceElement->base_height /= 2;
|
||||
|
|
|
@ -26,19 +26,19 @@ struct mapgen_settings
|
|||
// Simplex Noise Parameters
|
||||
int32_t simplex_low;
|
||||
int32_t simplex_high;
|
||||
float simplex_base_freq;
|
||||
float simplex_base_freq;
|
||||
int32_t simplex_octaves;
|
||||
|
||||
// Height map settings
|
||||
bool smooth;
|
||||
bool smooth_height_map;
|
||||
bool smooth;
|
||||
bool smooth_height_map;
|
||||
uint32_t smooth_strength;
|
||||
bool normalize_height;
|
||||
bool normalize_height;
|
||||
};
|
||||
|
||||
void mapgen_generate_blank(mapgen_settings * settings);
|
||||
void mapgen_generate(mapgen_settings * settings);
|
||||
void mapgen_generate_custom_simplex(mapgen_settings * settings);
|
||||
bool mapgen_load_heightmap(const utf8 * path);
|
||||
void mapgen_generate_blank(mapgen_settings* settings);
|
||||
void mapgen_generate(mapgen_settings* settings);
|
||||
void mapgen_generate_custom_simplex(mapgen_settings* settings);
|
||||
bool mapgen_load_heightmap(const utf8* path);
|
||||
void mapgen_unload_heightmap();
|
||||
void mapgen_generate_from_heightmap(mapgen_settings * settings);
|
||||
void mapgen_generate_from_heightmap(mapgen_settings* settings);
|
||||
|
|
|
@ -7,12 +7,14 @@
|
|||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||
*****************************************************************************/
|
||||
|
||||
#include <algorithm>
|
||||
#include "MapHelpers.h"
|
||||
|
||||
#include "../core/Math.hpp"
|
||||
#include "Map.h"
|
||||
#include "MapHelpers.h"
|
||||
#include "Surface.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
/**
|
||||
* Not perfect, this still leaves some particular tiles unsmoothed.
|
||||
*/
|
||||
|
@ -21,8 +23,10 @@ int32_t map_smooth(int32_t l, int32_t t, int32_t r, int32_t b)
|
|||
int32_t i, x, y, count, doubleCorner, raisedLand = 0;
|
||||
uint8_t highest, cornerHeights[4];
|
||||
rct_tile_element *tileElement, *tileElement2;
|
||||
for (y = t; y < b; y++) {
|
||||
for (x = l; x < r; x++) {
|
||||
for (y = t; y < b; y++)
|
||||
{
|
||||
for (x = l; x < r; x++)
|
||||
{
|
||||
tileElement = map_get_surface_element_at(x, y);
|
||||
tileElement->properties.surface.slope &= ~TILE_ELEMENT_SURFACE_SLOPE_MASK;
|
||||
|
||||
|
@ -32,7 +36,8 @@ int32_t map_smooth(int32_t l, int32_t t, int32_t r, int32_t b)
|
|||
highest = std::max(highest, map_get_surface_element_at(x + 1, y + 0)->base_height);
|
||||
highest = std::max(highest, map_get_surface_element_at(x + 0, y - 1)->base_height);
|
||||
highest = std::max(highest, map_get_surface_element_at(x + 0, y + 1)->base_height);
|
||||
if (tileElement->base_height < highest - 2) {
|
||||
if (tileElement->base_height < highest - 2)
|
||||
{
|
||||
raisedLand = 1;
|
||||
tileElement->base_height = tileElement->clearance_height = highest - 2;
|
||||
}
|
||||
|
@ -47,50 +52,56 @@ int32_t map_smooth(int32_t l, int32_t t, int32_t r, int32_t b)
|
|||
for (i = 0; i < 4; i++)
|
||||
highest = std::max(highest, cornerHeights[i]);
|
||||
|
||||
if (highest >= tileElement->base_height + 4) {
|
||||
if (highest >= tileElement->base_height + 4)
|
||||
{
|
||||
count = 0;
|
||||
int32_t canCompensate = 1;
|
||||
for (i = 0; i < 4; i++)
|
||||
if (cornerHeights[i] == highest){
|
||||
if (cornerHeights[i] == highest)
|
||||
{
|
||||
count++;
|
||||
|
||||
// Check if surrounding corners aren't too high. The current tile
|
||||
// can't compensate for all the height differences anymore if it has
|
||||
// the extra height slope.
|
||||
int32_t highestOnLowestSide;
|
||||
switch (i){
|
||||
default:
|
||||
case 0:
|
||||
highestOnLowestSide = std::max(
|
||||
map_get_surface_element_at(x + 1, y)->base_height,
|
||||
map_get_surface_element_at(x, y + 1)->base_height);
|
||||
break;
|
||||
case 1:
|
||||
highestOnLowestSide = std::max(
|
||||
map_get_surface_element_at(x - 1, y)->base_height,
|
||||
map_get_surface_element_at(x, y + 1)->base_height);
|
||||
break;
|
||||
case 2:
|
||||
highestOnLowestSide = std::max(
|
||||
map_get_surface_element_at(x - 1, y)->base_height,
|
||||
map_get_surface_element_at(x, y - 1)->base_height);
|
||||
break;
|
||||
case 3:
|
||||
highestOnLowestSide = std::max(
|
||||
map_get_surface_element_at(x + 1, y)->base_height,
|
||||
map_get_surface_element_at(x, y - 1)->base_height);
|
||||
break;
|
||||
switch (i)
|
||||
{
|
||||
default:
|
||||
case 0:
|
||||
highestOnLowestSide = std::max(
|
||||
map_get_surface_element_at(x + 1, y)->base_height,
|
||||
map_get_surface_element_at(x, y + 1)->base_height);
|
||||
break;
|
||||
case 1:
|
||||
highestOnLowestSide = std::max(
|
||||
map_get_surface_element_at(x - 1, y)->base_height,
|
||||
map_get_surface_element_at(x, y + 1)->base_height);
|
||||
break;
|
||||
case 2:
|
||||
highestOnLowestSide = std::max(
|
||||
map_get_surface_element_at(x - 1, y)->base_height,
|
||||
map_get_surface_element_at(x, y - 1)->base_height);
|
||||
break;
|
||||
case 3:
|
||||
highestOnLowestSide = std::max(
|
||||
map_get_surface_element_at(x + 1, y)->base_height,
|
||||
map_get_surface_element_at(x, y - 1)->base_height);
|
||||
break;
|
||||
}
|
||||
|
||||
if (highestOnLowestSide > tileElement->base_height){
|
||||
if (highestOnLowestSide > tileElement->base_height)
|
||||
{
|
||||
tileElement->base_height = tileElement->clearance_height = highestOnLowestSide;
|
||||
raisedLand = 1;
|
||||
canCompensate = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 1 && canCompensate) {
|
||||
if (tileElement->base_height < highest - 4) {
|
||||
if (count == 1 && canCompensate)
|
||||
{
|
||||
if (tileElement->base_height < highest - 4)
|
||||
{
|
||||
tileElement->base_height = tileElement->clearance_height = highest - 4;
|
||||
raisedLand = 1;
|
||||
}
|
||||
|
@ -102,31 +113,38 @@ int32_t map_smooth(int32_t l, int32_t t, int32_t r, int32_t b)
|
|||
doubleCorner = 2;
|
||||
else if (cornerHeights[3] == highest && cornerHeights[1] <= cornerHeights[3] - 4)
|
||||
doubleCorner = 3;
|
||||
} else {
|
||||
if (tileElement->base_height < highest - 2) {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tileElement->base_height < highest - 2)
|
||||
{
|
||||
tileElement->base_height = tileElement->clearance_height = highest - 2;
|
||||
raisedLand = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (doubleCorner != -1) {
|
||||
if (doubleCorner != -1)
|
||||
{
|
||||
tileElement->properties.surface.slope |= TILE_ELEMENT_SLOPE_DOUBLE_HEIGHT;
|
||||
switch (doubleCorner) {
|
||||
case 0:
|
||||
tileElement->properties.surface.slope |= TILE_ELEMENT_SLOPE_N_CORNER_DN;
|
||||
break;
|
||||
case 1:
|
||||
tileElement->properties.surface.slope |= TILE_ELEMENT_SLOPE_W_CORNER_DN;
|
||||
break;
|
||||
case 2:
|
||||
tileElement->properties.surface.slope |= TILE_ELEMENT_SLOPE_S_CORNER_DN;
|
||||
break;
|
||||
case 3:
|
||||
tileElement->properties.surface.slope |= TILE_ELEMENT_SLOPE_E_CORNER_DN;
|
||||
break;
|
||||
switch (doubleCorner)
|
||||
{
|
||||
case 0:
|
||||
tileElement->properties.surface.slope |= TILE_ELEMENT_SLOPE_N_CORNER_DN;
|
||||
break;
|
||||
case 1:
|
||||
tileElement->properties.surface.slope |= TILE_ELEMENT_SLOPE_W_CORNER_DN;
|
||||
break;
|
||||
case 2:
|
||||
tileElement->properties.surface.slope |= TILE_ELEMENT_SLOPE_S_CORNER_DN;
|
||||
break;
|
||||
case 3:
|
||||
tileElement->properties.surface.slope |= TILE_ELEMENT_SLOPE_E_CORNER_DN;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// Corners
|
||||
tileElement2 = map_get_surface_element_at(x + 1, y + 1);
|
||||
if (tileElement2->base_height > tileElement->base_height)
|
||||
|
@ -181,7 +199,7 @@ int32_t map_smooth(int32_t l, int32_t t, int32_t r, int32_t b)
|
|||
*/
|
||||
int32_t tile_smooth(int32_t x, int32_t y)
|
||||
{
|
||||
rct_tile_element *const surfaceElement = map_get_surface_element_at(x, y);
|
||||
rct_tile_element* const surfaceElement = map_get_surface_element_at(x, y);
|
||||
|
||||
// +-----+-----+-----+
|
||||
// | W | NW | N |
|
||||
|
@ -193,11 +211,12 @@ int32_t tile_smooth(int32_t x, int32_t y)
|
|||
// | S | SE | E |
|
||||
// | 7 | 6 | 5 |
|
||||
// +-----+-----+-----+
|
||||
|
||||
|
||||
union
|
||||
{
|
||||
int32_t baseheight[8];
|
||||
struct {
|
||||
struct
|
||||
{
|
||||
int32_t N;
|
||||
int32_t NW;
|
||||
int32_t W;
|
||||
|
@ -219,8 +238,9 @@ int32_t tile_smooth(int32_t x, int32_t y)
|
|||
continue;
|
||||
|
||||
// Get neighbour height. If the element is not valid (outside of map) assume the same height
|
||||
rct_tile_element *neighbour_element = map_get_surface_element_at(x + x_offset, y + y_offset);
|
||||
neighbourHeightOffset.baseheight[index] = neighbour_element ? neighbour_element->base_height : surfaceElement->base_height;
|
||||
rct_tile_element* neighbour_element = map_get_surface_element_at(x + x_offset, y + y_offset);
|
||||
neighbourHeightOffset.baseheight[index]
|
||||
= neighbour_element ? neighbour_element->base_height : surfaceElement->base_height;
|
||||
|
||||
// Make the height relative to the current surface element
|
||||
neighbourHeightOffset.baseheight[index] -= surfaceElement->base_height;
|
||||
|
@ -230,10 +250,14 @@ int32_t tile_smooth(int32_t x, int32_t y)
|
|||
}
|
||||
|
||||
// Count number from the three tiles that is currently higher
|
||||
int8_t thresholdW = Math::Clamp(0, neighbourHeightOffset.SW, 1) + Math::Clamp(0, neighbourHeightOffset.W, 1) + Math::Clamp(0, neighbourHeightOffset.NW, 1);
|
||||
int8_t thresholdN = Math::Clamp(0, neighbourHeightOffset.NW, 1) + Math::Clamp(0, neighbourHeightOffset.N, 1) + Math::Clamp(0, neighbourHeightOffset.NE, 1);
|
||||
int8_t thresholdE = Math::Clamp(0, neighbourHeightOffset.NE, 1) + Math::Clamp(0, neighbourHeightOffset.E, 1) + Math::Clamp(0, neighbourHeightOffset.SE, 1);
|
||||
int8_t thresholdS = Math::Clamp(0, neighbourHeightOffset.SE, 1) + Math::Clamp(0, neighbourHeightOffset.S, 1) + Math::Clamp(0, neighbourHeightOffset.SW, 1);
|
||||
int8_t thresholdW = Math::Clamp(0, neighbourHeightOffset.SW, 1) + Math::Clamp(0, neighbourHeightOffset.W, 1)
|
||||
+ Math::Clamp(0, neighbourHeightOffset.NW, 1);
|
||||
int8_t thresholdN = Math::Clamp(0, neighbourHeightOffset.NW, 1) + Math::Clamp(0, neighbourHeightOffset.N, 1)
|
||||
+ Math::Clamp(0, neighbourHeightOffset.NE, 1);
|
||||
int8_t thresholdE = Math::Clamp(0, neighbourHeightOffset.NE, 1) + Math::Clamp(0, neighbourHeightOffset.E, 1)
|
||||
+ Math::Clamp(0, neighbourHeightOffset.SE, 1);
|
||||
int8_t thresholdS = Math::Clamp(0, neighbourHeightOffset.SE, 1) + Math::Clamp(0, neighbourHeightOffset.S, 1)
|
||||
+ Math::Clamp(0, neighbourHeightOffset.SW, 1);
|
||||
|
||||
uint8_t slope = TILE_ELEMENT_SLOPE_FLAT;
|
||||
slope |= (thresholdW >= 1) ? SLOPE_W_THRESHOLD_FLAGS : 0;
|
||||
|
@ -242,10 +266,10 @@ int32_t tile_smooth(int32_t x, int32_t y)
|
|||
slope |= (thresholdS >= 1) ? SLOPE_S_THRESHOLD_FLAGS : 0;
|
||||
|
||||
// Set diagonal when three corners (one corner down) have been raised, and the middle one can be raised one more
|
||||
if ((slope == TILE_ELEMENT_SLOPE_W_CORNER_DN && neighbourHeightOffset.W >= 4) ||
|
||||
(slope == TILE_ELEMENT_SLOPE_S_CORNER_DN && neighbourHeightOffset.S >= 4) ||
|
||||
(slope == TILE_ELEMENT_SLOPE_E_CORNER_DN && neighbourHeightOffset.E >= 4) ||
|
||||
(slope == TILE_ELEMENT_SLOPE_N_CORNER_DN && neighbourHeightOffset.N >= 4))
|
||||
if ((slope == TILE_ELEMENT_SLOPE_W_CORNER_DN && neighbourHeightOffset.W >= 4)
|
||||
|| (slope == TILE_ELEMENT_SLOPE_S_CORNER_DN && neighbourHeightOffset.S >= 4)
|
||||
|| (slope == TILE_ELEMENT_SLOPE_E_CORNER_DN && neighbourHeightOffset.E >= 4)
|
||||
|| (slope == TILE_ELEMENT_SLOPE_N_CORNER_DN && neighbourHeightOffset.N >= 4))
|
||||
{
|
||||
slope |= TILE_ELEMENT_SLOPE_DOUBLE_HEIGHT;
|
||||
}
|
||||
|
|
|
@ -12,7 +12,8 @@
|
|||
|
||||
#include "../common.h"
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
SLOPE_S_THRESHOLD_FLAGS = (1 << 0),
|
||||
SLOPE_W_THRESHOLD_FLAGS = (1 << 1),
|
||||
SLOPE_N_THRESHOLD_FLAGS = (1 << 2),
|
||||
|
|
|
@ -7,20 +7,15 @@
|
|||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "../OpenRCT2.h"
|
||||
#include "../drawing/Drawing.h"
|
||||
#include "../localisation/Localisation.h"
|
||||
#include "../interface/Viewport.h"
|
||||
#include "../interface/Window.h"
|
||||
#include "../localisation/Localisation.h"
|
||||
#include "Map.h"
|
||||
#include "../OpenRCT2.h"
|
||||
#include "Sprite.h"
|
||||
|
||||
static constexpr const LocationXY16 _moneyEffectMoveOffset[] = {
|
||||
{1, -1},
|
||||
{1, 1},
|
||||
{-1, 1},
|
||||
{-1, -1}
|
||||
};
|
||||
static constexpr const LocationXY16 _moneyEffectMoveOffset[] = { { 1, -1 }, { 1, 1 }, { -1, 1 }, { -1, -1 } };
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -31,20 +26,20 @@ void money_effect_create_at(money32 value, int32_t x, int32_t y, int32_t z, bool
|
|||
if (value == MONEY(0, 00))
|
||||
return;
|
||||
|
||||
rct_money_effect * moneyEffect = (rct_money_effect *) create_sprite(2);
|
||||
rct_money_effect* moneyEffect = (rct_money_effect*)create_sprite(2);
|
||||
if (moneyEffect == nullptr)
|
||||
return;
|
||||
|
||||
moneyEffect->value = value;
|
||||
moneyEffect->vertical = (vertical ? 1 : 0);
|
||||
moneyEffect->sprite_width = 64;
|
||||
moneyEffect->value = value;
|
||||
moneyEffect->vertical = (vertical ? 1 : 0);
|
||||
moneyEffect->sprite_width = 64;
|
||||
moneyEffect->sprite_height_negative = 20;
|
||||
moneyEffect->sprite_height_positive = 30;
|
||||
moneyEffect->sprite_identifier = SPRITE_IDENTIFIER_MISC;
|
||||
sprite_move(x, y, z, (rct_sprite *) moneyEffect);
|
||||
moneyEffect->misc_identifier = SPRITE_MISC_MONEY_EFFECT;
|
||||
moneyEffect->num_movements = 0;
|
||||
moneyEffect->move_delay = 0;
|
||||
sprite_move(x, y, z, (rct_sprite*)moneyEffect);
|
||||
moneyEffect->misc_identifier = SPRITE_MISC_MONEY_EFFECT;
|
||||
moneyEffect->num_movements = 0;
|
||||
moneyEffect->move_delay = 0;
|
||||
|
||||
int16_t offsetX = 0;
|
||||
if (!gOpenRCT2NoGraphics)
|
||||
|
@ -54,7 +49,7 @@ void money_effect_create_at(money32 value, int32_t x, int32_t y, int32_t z, bool
|
|||
char buffer[128];
|
||||
format_string(buffer, 128, stringId, &value);
|
||||
gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM;
|
||||
offsetX = -(gfx_get_string_width(buffer) / 2);
|
||||
offsetX = -(gfx_get_string_width(buffer) / 2);
|
||||
}
|
||||
moneyEffect->offset_x = offsetX;
|
||||
moneyEffect->wiggle = 0;
|
||||
|
@ -66,27 +61,21 @@ void money_effect_create_at(money32 value, int32_t x, int32_t y, int32_t z, bool
|
|||
*/
|
||||
void money_effect_create(money32 value)
|
||||
{
|
||||
LocationXYZ16 mapPosition =
|
||||
{
|
||||
gCommandPosition.x,
|
||||
gCommandPosition.y,
|
||||
gCommandPosition.z
|
||||
};
|
||||
LocationXYZ16 mapPosition = { gCommandPosition.x, gCommandPosition.y, gCommandPosition.z };
|
||||
|
||||
if (mapPosition.x == LOCATION_NULL)
|
||||
{
|
||||
rct_window * mainWindow = window_get_main();
|
||||
rct_window* mainWindow = window_get_main();
|
||||
if (mainWindow == nullptr)
|
||||
return;
|
||||
|
||||
rct_viewport * mainViewport = window_get_viewport(mainWindow);
|
||||
rct_viewport* mainViewport = window_get_viewport(mainWindow);
|
||||
screen_get_map_xy(
|
||||
mainViewport->x + (mainViewport->width / 2),
|
||||
mainViewport->y + (mainViewport->height / 2),
|
||||
&mapPosition.x,
|
||||
&mapPosition.y,
|
||||
nullptr
|
||||
);
|
||||
nullptr);
|
||||
if (mapPosition.x == LOCATION_NULL)
|
||||
return;
|
||||
|
||||
|
@ -100,9 +89,9 @@ void money_effect_create(money32 value)
|
|||
*
|
||||
* rct2: 0x00673232
|
||||
*/
|
||||
void money_effect_update(rct_money_effect * moneyEffect)
|
||||
void money_effect_update(rct_money_effect* moneyEffect)
|
||||
{
|
||||
invalidate_sprite_2((rct_sprite *) moneyEffect);
|
||||
invalidate_sprite_2((rct_sprite*)moneyEffect);
|
||||
moneyEffect->wiggle++;
|
||||
if (moneyEffect->wiggle >= 22)
|
||||
{
|
||||
|
@ -127,7 +116,7 @@ void money_effect_update(rct_money_effect * moneyEffect)
|
|||
y += _moneyEffectMoveOffset[get_current_rotation()].y;
|
||||
x += _moneyEffectMoveOffset[get_current_rotation()].x;
|
||||
|
||||
sprite_move(x, y, z, (rct_sprite *) moneyEffect);
|
||||
sprite_move(x, y, z, (rct_sprite*)moneyEffect);
|
||||
|
||||
moneyEffect->num_movements++;
|
||||
if (moneyEffect->num_movements < 55)
|
||||
|
@ -135,16 +124,16 @@ void money_effect_update(rct_money_effect * moneyEffect)
|
|||
return;
|
||||
}
|
||||
|
||||
sprite_remove((rct_sprite *) moneyEffect);
|
||||
sprite_remove((rct_sprite*)moneyEffect);
|
||||
}
|
||||
|
||||
rct_string_id money_effect_get_string_id(const rct_money_effect * sprite, money32 * outValue)
|
||||
rct_string_id money_effect_get_string_id(const rct_money_effect* sprite, money32* outValue)
|
||||
{
|
||||
bool vertical = (sprite->vertical != 0);
|
||||
rct_string_id spentStringId = vertical ? STR_MONEY_EFFECT_SPEND_HIGHP : STR_MONEY_EFFECT_SPEND;
|
||||
bool vertical = (sprite->vertical != 0);
|
||||
rct_string_id spentStringId = vertical ? STR_MONEY_EFFECT_SPEND_HIGHP : STR_MONEY_EFFECT_SPEND;
|
||||
rct_string_id receiveStringId = vertical ? STR_MONEY_EFFECT_RECEIVE_HIGHP : STR_MONEY_EFFECT_RECEIVE;
|
||||
rct_string_id stringId = receiveStringId;
|
||||
money32 value = sprite->value;
|
||||
rct_string_id stringId = receiveStringId;
|
||||
money32 value = sprite->value;
|
||||
if (value < 0)
|
||||
{
|
||||
value *= -1;
|
||||
|
|
|
@ -7,15 +7,18 @@
|
|||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "Park.h"
|
||||
|
||||
#include "../Cheats.h"
|
||||
#include "../Context.h"
|
||||
#include "../Date.h"
|
||||
#include "../Game.h"
|
||||
#include "../GameState.h"
|
||||
#include "../OpenRCT2.h"
|
||||
#include "../config/Config.h"
|
||||
#include "../core/Math.hpp"
|
||||
#include "../core/Memory.hpp"
|
||||
#include "../core/Util.hpp"
|
||||
#include "../Date.h"
|
||||
#include "../Game.h"
|
||||
#include "../GameState.h"
|
||||
#include "../interface/Colour.h"
|
||||
#include "../interface/Window.h"
|
||||
#include "../localisation/Localisation.h"
|
||||
|
@ -25,7 +28,6 @@
|
|||
#include "../management/NewsItem.h"
|
||||
#include "../management/Research.h"
|
||||
#include "../network/network.h"
|
||||
#include "../OpenRCT2.h"
|
||||
#include "../peep/Peep.h"
|
||||
#include "../peep/Staff.h"
|
||||
#include "../ride/Ride.h"
|
||||
|
@ -35,7 +37,6 @@
|
|||
#include "../windows/Intent.h"
|
||||
#include "Entrance.h"
|
||||
#include "Map.h"
|
||||
#include "Park.h"
|
||||
#include "Sprite.h"
|
||||
#include "Surface.h"
|
||||
|
||||
|
@ -84,7 +85,8 @@ void reset_park_entry()
|
|||
{
|
||||
gParkName = 0;
|
||||
reset_park_entrance();
|
||||
for (int32_t i = 0; i < MAX_PEEP_SPAWNS; i++) {
|
||||
for (int32_t i = 0; i < MAX_PEEP_SPAWNS; i++)
|
||||
{
|
||||
gPeepSpawns[i].x = PEEP_SPAWN_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
@ -96,10 +98,12 @@ static uint32_t get_random_peep_spawn_index()
|
|||
{
|
||||
uint32_t spawnIndexList[MAX_PEEP_SPAWNS];
|
||||
uint32_t numSpawns = map_get_available_peep_spawn_index_list(spawnIndexList);
|
||||
if (numSpawns > 0) {
|
||||
if (numSpawns > 0)
|
||||
{
|
||||
return spawnIndexList[scenario_rand() % numSpawns];
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -114,15 +118,16 @@ void park_set_open(int32_t open)
|
|||
* rct2: 0x00669D4A
|
||||
*/
|
||||
void game_command_set_park_open(
|
||||
[[maybe_unused]] int32_t * eax,
|
||||
int32_t * ebx,
|
||||
[[maybe_unused]] int32_t * ecx,
|
||||
int32_t * edx,
|
||||
[[maybe_unused]] int32_t * esi,
|
||||
int32_t * edi,
|
||||
[[maybe_unused]] int32_t * ebp)
|
||||
[[maybe_unused]] int32_t* eax,
|
||||
int32_t* ebx,
|
||||
[[maybe_unused]] int32_t* ecx,
|
||||
int32_t* edx,
|
||||
[[maybe_unused]] int32_t* esi,
|
||||
int32_t* edi,
|
||||
[[maybe_unused]] int32_t* ebp)
|
||||
{
|
||||
if (!(*ebx & GAME_COMMAND_FLAG_APPLY)) {
|
||||
if (!(*ebx & GAME_COMMAND_FLAG_APPLY))
|
||||
{
|
||||
*ebx = 0;
|
||||
return;
|
||||
}
|
||||
|
@ -130,36 +135,39 @@ void game_command_set_park_open(
|
|||
int32_t dh = (*edx >> 8) & 0xFF;
|
||||
|
||||
gCommandExpenditureType = RCT_EXPENDITURE_TYPE_PARK_ENTRANCE_TICKETS;
|
||||
switch (dh) {
|
||||
case 0:
|
||||
if (gParkFlags & PARK_FLAGS_PARK_OPEN) {
|
||||
gParkFlags &= ~PARK_FLAGS_PARK_OPEN;
|
||||
window_invalidate_by_class(WC_PARK_INFORMATION);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (!(gParkFlags & PARK_FLAGS_PARK_OPEN)) {
|
||||
gParkFlags |= PARK_FLAGS_PARK_OPEN;
|
||||
window_invalidate_by_class(WC_PARK_INFORMATION);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
gSamePriceThroughoutParkA = *edi;
|
||||
window_invalidate_by_class(WC_RIDE);
|
||||
break;
|
||||
case 3:
|
||||
gSamePriceThroughoutParkB = *edi;
|
||||
window_invalidate_by_class(WC_RIDE);
|
||||
break;
|
||||
switch (dh)
|
||||
{
|
||||
case 0:
|
||||
if (gParkFlags & PARK_FLAGS_PARK_OPEN)
|
||||
{
|
||||
gParkFlags &= ~PARK_FLAGS_PARK_OPEN;
|
||||
window_invalidate_by_class(WC_PARK_INFORMATION);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (!(gParkFlags & PARK_FLAGS_PARK_OPEN))
|
||||
{
|
||||
gParkFlags |= PARK_FLAGS_PARK_OPEN;
|
||||
window_invalidate_by_class(WC_PARK_INFORMATION);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
gSamePriceThroughoutParkA = *edi;
|
||||
window_invalidate_by_class(WC_RIDE);
|
||||
break;
|
||||
case 3:
|
||||
gSamePriceThroughoutParkB = *edi;
|
||||
window_invalidate_by_class(WC_RIDE);
|
||||
break;
|
||||
}
|
||||
|
||||
*ebx = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x00664D05
|
||||
*/
|
||||
*
|
||||
* rct2: 0x00664D05
|
||||
*/
|
||||
void update_park_fences(const CoordsXY coords)
|
||||
{
|
||||
if (map_is_edge(coords))
|
||||
|
@ -170,41 +178,49 @@ void update_park_fences(const CoordsXY coords)
|
|||
return;
|
||||
|
||||
uint8_t newOwnership = surfaceElement->properties.surface.ownership & 0xF0;
|
||||
if ((surfaceElement->properties.surface.ownership & OWNERSHIP_OWNED) == 0) {
|
||||
if ((surfaceElement->properties.surface.ownership & OWNERSHIP_OWNED) == 0)
|
||||
{
|
||||
bool fenceRequired = true;
|
||||
|
||||
rct_tile_element* tileElement = map_get_first_element_at(coords.x / 32, coords.y / 32);
|
||||
// If an entrance element do not place flags around surface
|
||||
do {
|
||||
do
|
||||
{
|
||||
if (tileElement->GetType() != TILE_ELEMENT_TYPE_ENTRANCE)
|
||||
continue;
|
||||
|
||||
if (tileElement->properties.entrance.type != ENTRANCE_TYPE_PARK_ENTRANCE)
|
||||
continue;
|
||||
|
||||
if (!(tileElement->flags & TILE_ELEMENT_FLAG_GHOST)) {
|
||||
if (!(tileElement->flags & TILE_ELEMENT_FLAG_GHOST))
|
||||
{
|
||||
fenceRequired = false;
|
||||
break;
|
||||
}
|
||||
} while (!(tileElement++)->IsLastForTile());
|
||||
|
||||
if (fenceRequired) {
|
||||
if (fenceRequired)
|
||||
{
|
||||
// As map_is_location_in_park sets the error text
|
||||
// will require to back it up.
|
||||
rct_string_id previous_error = gGameCommandErrorText;
|
||||
if (map_is_location_in_park({coords.x - 32, coords.y})){
|
||||
if (map_is_location_in_park({ coords.x - 32, coords.y }))
|
||||
{
|
||||
newOwnership |= 0x8;
|
||||
}
|
||||
|
||||
if (map_is_location_in_park({coords.x, coords.y - 32})){
|
||||
if (map_is_location_in_park({ coords.x, coords.y - 32 }))
|
||||
{
|
||||
newOwnership |= 0x4;
|
||||
}
|
||||
|
||||
if (map_is_location_in_park({coords.x + 32, coords.y})){
|
||||
if (map_is_location_in_park({ coords.x + 32, coords.y }))
|
||||
{
|
||||
newOwnership |= 0x2;
|
||||
}
|
||||
|
||||
if (map_is_location_in_park({coords.x, coords.y + 32})){
|
||||
if (map_is_location_in_park({ coords.x, coords.y + 32 }))
|
||||
{
|
||||
newOwnership |= 0x1;
|
||||
}
|
||||
|
||||
|
@ -212,7 +228,8 @@ void update_park_fences(const CoordsXY coords)
|
|||
}
|
||||
}
|
||||
|
||||
if (surfaceElement->properties.surface.ownership != newOwnership) {
|
||||
if (surfaceElement->properties.surface.ownership != newOwnership)
|
||||
{
|
||||
int32_t z0 = surfaceElement->base_height * 8;
|
||||
int32_t z1 = z0 + 16;
|
||||
map_invalidate_tile(coords.x, coords.y, z0, z1);
|
||||
|
@ -223,13 +240,13 @@ void update_park_fences(const CoordsXY coords)
|
|||
void update_park_fences_around_tile(const CoordsXY coords)
|
||||
{
|
||||
update_park_fences(coords);
|
||||
update_park_fences({coords.x + 32, coords.y});
|
||||
update_park_fences({coords.x - 32, coords.y});
|
||||
update_park_fences({coords.x, coords.y + 32});
|
||||
update_park_fences({coords.x, coords.y - 32});
|
||||
update_park_fences({ coords.x + 32, coords.y });
|
||||
update_park_fences({ coords.x - 32, coords.y });
|
||||
update_park_fences({ coords.x, coords.y + 32 });
|
||||
update_park_fences({ coords.x, coords.y - 32 });
|
||||
}
|
||||
|
||||
void park_set_name(const char *name)
|
||||
void park_set_name(const char* name)
|
||||
{
|
||||
auto nameId = user_string_allocate(USER_STRING_HIGH_ID_NUMBER, name);
|
||||
if (nameId != 0)
|
||||
|
@ -239,116 +256,141 @@ void park_set_name(const char *name)
|
|||
}
|
||||
}
|
||||
|
||||
static money32 map_buy_land_rights_for_tile(int32_t x, int32_t y, int32_t setting, int32_t flags) {
|
||||
rct_tile_element* surfaceElement = map_get_surface_element_at({x, y});
|
||||
static money32 map_buy_land_rights_for_tile(int32_t x, int32_t y, int32_t setting, int32_t flags)
|
||||
{
|
||||
rct_tile_element* surfaceElement = map_get_surface_element_at({ x, y });
|
||||
if (surfaceElement == nullptr)
|
||||
return MONEY32_UNDEFINED;
|
||||
|
||||
switch (setting) {
|
||||
case BUY_LAND_RIGHTS_FLAG_BUY_LAND: // 0
|
||||
if ((surfaceElement->properties.surface.ownership & OWNERSHIP_OWNED) != 0) { // If the land is already owned
|
||||
switch (setting)
|
||||
{
|
||||
case BUY_LAND_RIGHTS_FLAG_BUY_LAND: // 0
|
||||
if ((surfaceElement->properties.surface.ownership & OWNERSHIP_OWNED) != 0)
|
||||
{ // If the land is already owned
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) != 0
|
||||
|| (surfaceElement->properties.surface.ownership & OWNERSHIP_AVAILABLE) == 0)
|
||||
{
|
||||
gGameCommandErrorText = STR_LAND_NOT_FOR_SALE;
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
||||
{
|
||||
surfaceElement->properties.surface.ownership |= OWNERSHIP_OWNED;
|
||||
update_park_fences_around_tile({ x, y });
|
||||
}
|
||||
return gLandPrice;
|
||||
case BUY_LAND_RIGHTS_FLAG_UNOWN_TILE: // 1
|
||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
||||
{
|
||||
surfaceElement->properties.surface.ownership &= ~(OWNERSHIP_OWNED | OWNERSHIP_CONSTRUCTION_RIGHTS_OWNED);
|
||||
update_park_fences_around_tile({ x, y });
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
case BUY_LAND_RIGHTS_FLAG_BUY_CONSTRUCTION_RIGHTS: // 2
|
||||
if ((surfaceElement->properties.surface.ownership & (OWNERSHIP_OWNED | OWNERSHIP_CONSTRUCTION_RIGHTS_OWNED)) != 0)
|
||||
{ // If the land or construction rights are already owned
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) != 0 || (surfaceElement->properties.surface.ownership & OWNERSHIP_AVAILABLE) == 0) {
|
||||
gGameCommandErrorText = STR_LAND_NOT_FOR_SALE;
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
if (flags & GAME_COMMAND_FLAG_APPLY) {
|
||||
surfaceElement->properties.surface.ownership |= OWNERSHIP_OWNED;
|
||||
update_park_fences_around_tile({x, y});
|
||||
}
|
||||
return gLandPrice;
|
||||
case BUY_LAND_RIGHTS_FLAG_UNOWN_TILE: // 1
|
||||
if (flags & GAME_COMMAND_FLAG_APPLY) {
|
||||
surfaceElement->properties.surface.ownership &= ~(OWNERSHIP_OWNED | OWNERSHIP_CONSTRUCTION_RIGHTS_OWNED);
|
||||
update_park_fences_around_tile({x, y});
|
||||
}
|
||||
return 0;
|
||||
case BUY_LAND_RIGHTS_FLAG_BUY_CONSTRUCTION_RIGHTS: // 2
|
||||
if ((surfaceElement->properties.surface.ownership & (OWNERSHIP_OWNED | OWNERSHIP_CONSTRUCTION_RIGHTS_OWNED)) != 0) { // If the land or construction rights are already owned
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) != 0 || (surfaceElement->properties.surface.ownership & OWNERSHIP_CONSTRUCTION_RIGHTS_AVAILABLE) == 0) {
|
||||
gGameCommandErrorText = STR_CONSTRUCTION_RIGHTS_NOT_FOR_SALE;
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
if (flags & GAME_COMMAND_FLAG_APPLY) {
|
||||
surfaceElement->properties.surface.ownership |= OWNERSHIP_CONSTRUCTION_RIGHTS_OWNED;
|
||||
uint16_t baseHeight = surfaceElement->base_height * 8;
|
||||
map_invalidate_tile(x, y, baseHeight, baseHeight + 16);
|
||||
}
|
||||
return gConstructionRightsPrice;
|
||||
case BUY_LAND_RIGHTS_FLAG_UNOWN_CONSTRUCTION_RIGHTS: // 3
|
||||
if (flags & GAME_COMMAND_FLAG_APPLY) {
|
||||
surfaceElement->properties.surface.ownership &= ~OWNERSHIP_CONSTRUCTION_RIGHTS_OWNED;
|
||||
uint16_t baseHeight = surfaceElement->base_height * 8;
|
||||
map_invalidate_tile(x, y, baseHeight, baseHeight + 16);
|
||||
}
|
||||
return 0;
|
||||
case BUY_LAND_RIGHTS_FLAG_SET_FOR_SALE: // 4
|
||||
if (flags & GAME_COMMAND_FLAG_APPLY) {
|
||||
surfaceElement->properties.surface.ownership |= OWNERSHIP_AVAILABLE;
|
||||
uint16_t baseHeight = surfaceElement->base_height * 8;
|
||||
map_invalidate_tile(x, y, baseHeight, baseHeight + 16);
|
||||
}
|
||||
return 0;
|
||||
case BUY_LAND_RIGHTS_FLAG_SET_CONSTRUCTION_RIGHTS_FOR_SALE: // 5
|
||||
if (flags & GAME_COMMAND_FLAG_APPLY) {
|
||||
surfaceElement->properties.surface.ownership |= OWNERSHIP_CONSTRUCTION_RIGHTS_AVAILABLE;
|
||||
uint16_t baseHeight = surfaceElement->base_height * 8;
|
||||
map_invalidate_tile(x, y, baseHeight, baseHeight + 16);
|
||||
}
|
||||
return 0;
|
||||
case BUY_LAND_RIGHTS_FLAG_SET_OWNERSHIP_WITH_CHECKS:
|
||||
{
|
||||
if (!(gScreenFlags & SCREEN_FLAGS_EDITOR) && !gCheatsSandboxMode) {
|
||||
if ((gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) != 0
|
||||
|| (surfaceElement->properties.surface.ownership & OWNERSHIP_CONSTRUCTION_RIGHTS_AVAILABLE) == 0)
|
||||
{
|
||||
gGameCommandErrorText = STR_CONSTRUCTION_RIGHTS_NOT_FOR_SALE;
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
if (x <= 0 || y <= 0) {
|
||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
||||
{
|
||||
surfaceElement->properties.surface.ownership |= OWNERSHIP_CONSTRUCTION_RIGHTS_OWNED;
|
||||
uint16_t baseHeight = surfaceElement->base_height * 8;
|
||||
map_invalidate_tile(x, y, baseHeight, baseHeight + 16);
|
||||
}
|
||||
return gConstructionRightsPrice;
|
||||
case BUY_LAND_RIGHTS_FLAG_UNOWN_CONSTRUCTION_RIGHTS: // 3
|
||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
||||
{
|
||||
surfaceElement->properties.surface.ownership &= ~OWNERSHIP_CONSTRUCTION_RIGHTS_OWNED;
|
||||
uint16_t baseHeight = surfaceElement->base_height * 8;
|
||||
map_invalidate_tile(x, y, baseHeight, baseHeight + 16);
|
||||
}
|
||||
return 0;
|
||||
case BUY_LAND_RIGHTS_FLAG_SET_FOR_SALE: // 4
|
||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
||||
{
|
||||
surfaceElement->properties.surface.ownership |= OWNERSHIP_AVAILABLE;
|
||||
uint16_t baseHeight = surfaceElement->base_height * 8;
|
||||
map_invalidate_tile(x, y, baseHeight, baseHeight + 16);
|
||||
}
|
||||
return 0;
|
||||
case BUY_LAND_RIGHTS_FLAG_SET_CONSTRUCTION_RIGHTS_FOR_SALE: // 5
|
||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
||||
{
|
||||
surfaceElement->properties.surface.ownership |= OWNERSHIP_CONSTRUCTION_RIGHTS_AVAILABLE;
|
||||
uint16_t baseHeight = surfaceElement->base_height * 8;
|
||||
map_invalidate_tile(x, y, baseHeight, baseHeight + 16);
|
||||
}
|
||||
return 0;
|
||||
case BUY_LAND_RIGHTS_FLAG_SET_OWNERSHIP_WITH_CHECKS:
|
||||
{
|
||||
if (!(gScreenFlags & SCREEN_FLAGS_EDITOR) && !gCheatsSandboxMode)
|
||||
{
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
if (x <= 0 || y <= 0)
|
||||
{
|
||||
gGameCommandErrorText = STR_TOO_CLOSE_TO_EDGE_OF_MAP;
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
if (x >= gMapSizeUnits || y >= gMapSizeUnits) {
|
||||
if (x >= gMapSizeUnits || y >= gMapSizeUnits)
|
||||
{
|
||||
gGameCommandErrorText = STR_TOO_CLOSE_TO_EDGE_OF_MAP;
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
uint8_t newOwnership = (flags & 0xFF00) >> 4;
|
||||
if (newOwnership == (surfaceElement->properties.surface.ownership & 0xF0)) {
|
||||
if (newOwnership == (surfaceElement->properties.surface.ownership & 0xF0))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
rct_tile_element* tileElement = map_get_first_element_at(x / 32, y / 32);
|
||||
do {
|
||||
if (tileElement->GetType() == TILE_ELEMENT_TYPE_ENTRANCE) {
|
||||
do
|
||||
{
|
||||
if (tileElement->GetType() == TILE_ELEMENT_TYPE_ENTRANCE)
|
||||
{
|
||||
// Do not allow ownership of park entrance.
|
||||
if (newOwnership == OWNERSHIP_OWNED || newOwnership == OWNERSHIP_AVAILABLE)
|
||||
return 0;
|
||||
// Allow construction rights available / for sale on park entrances on surface.
|
||||
// There is no need to check the height if newOwnership is 0 (unowned and no rights available).
|
||||
if ((newOwnership == OWNERSHIP_CONSTRUCTION_RIGHTS_OWNED ||
|
||||
newOwnership == OWNERSHIP_CONSTRUCTION_RIGHTS_AVAILABLE) &&
|
||||
(tileElement->base_height - 3 > surfaceElement->base_height ||
|
||||
tileElement->base_height < surfaceElement->base_height))
|
||||
if ((newOwnership == OWNERSHIP_CONSTRUCTION_RIGHTS_OWNED
|
||||
|| newOwnership == OWNERSHIP_CONSTRUCTION_RIGHTS_AVAILABLE)
|
||||
&& (tileElement->base_height - 3 > surfaceElement->base_height
|
||||
|| tileElement->base_height < surfaceElement->base_height))
|
||||
return 0;
|
||||
}
|
||||
} while (!(tileElement++)->IsLastForTile());
|
||||
|
||||
if (!(flags & GAME_COMMAND_FLAG_APPLY)) {
|
||||
if (!(flags & GAME_COMMAND_FLAG_APPLY))
|
||||
{
|
||||
return gLandPrice;
|
||||
}
|
||||
|
||||
if ((newOwnership & 0xF0) != 0) {
|
||||
PeepSpawn *peepSpawns = gPeepSpawns;
|
||||
if ((newOwnership & 0xF0) != 0)
|
||||
{
|
||||
PeepSpawn* peepSpawns = gPeepSpawns;
|
||||
|
||||
for (uint8_t i = 0; i < MAX_PEEP_SPAWNS; ++i) {
|
||||
if (x == (peepSpawns[i].x & 0xFFE0)) {
|
||||
if (y == (peepSpawns[i].y & 0xFFE0)) {
|
||||
for (uint8_t i = 0; i < MAX_PEEP_SPAWNS; ++i)
|
||||
{
|
||||
if (x == (peepSpawns[i].x & 0xFFE0))
|
||||
{
|
||||
if (y == (peepSpawns[i].y & 0xFFE0))
|
||||
{
|
||||
peepSpawns[i].x = PEEP_SPAWN_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
@ -356,14 +398,14 @@ static money32 map_buy_land_rights_for_tile(int32_t x, int32_t y, int32_t settin
|
|||
}
|
||||
surfaceElement->properties.surface.ownership &= 0x0F;
|
||||
surfaceElement->properties.surface.ownership |= newOwnership;
|
||||
update_park_fences_around_tile({x, y});
|
||||
update_park_fences_around_tile({ x, y });
|
||||
gMapLandRightsUpdateSuccess = true;
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
log_warning("Tried calling map_buy_land_rights_for_tile() with an incorrect setting!");
|
||||
assert(false);
|
||||
return MONEY32_UNDEFINED;
|
||||
default:
|
||||
log_warning("Tried calling map_buy_land_rights_for_tile() with an incorrect setting!");
|
||||
assert(false);
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -373,7 +415,8 @@ int32_t map_buy_land_rights(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int3
|
|||
money32 totalCost, cost;
|
||||
gCommandExpenditureType = RCT_EXPENDITURE_TYPE_LAND_PURCHASE;
|
||||
|
||||
if (x1 == 0 && y1 == 0) {
|
||||
if (x1 == 0 && y1 == 0)
|
||||
{
|
||||
x1 = x0;
|
||||
y1 = y0;
|
||||
}
|
||||
|
@ -388,9 +431,12 @@ int32_t map_buy_land_rights(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int3
|
|||
// Game command modified to accept selection size
|
||||
totalCost = 0;
|
||||
gGameCommandErrorText = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED;
|
||||
if ((gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) != 0 || game_is_not_paused() || gCheatsBuildInPauseMode) {
|
||||
for (y = y0; y <= y1; y += 32) {
|
||||
for (x = x0; x <= x1; x += 32) {
|
||||
if ((gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) != 0 || game_is_not_paused() || gCheatsBuildInPauseMode)
|
||||
{
|
||||
for (y = y0; y <= y1; y += 32)
|
||||
{
|
||||
for (x = x0; x <= x1; x += 32)
|
||||
{
|
||||
cost = map_buy_land_rights_for_tile(x, y, setting, flags);
|
||||
if (cost != MONEY32_UNDEFINED)
|
||||
{
|
||||
|
@ -404,27 +450,21 @@ int32_t map_buy_land_rights(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int3
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006649BD
|
||||
*/
|
||||
*
|
||||
* rct2: 0x006649BD
|
||||
*/
|
||||
void game_command_buy_land_rights(
|
||||
int32_t * eax, int32_t * ebx, int32_t * ecx, int32_t * edx, [[maybe_unused]] int32_t * esi, int32_t * edi, int32_t * ebp)
|
||||
int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, [[maybe_unused]] int32_t* esi, int32_t* edi, int32_t* ebp)
|
||||
{
|
||||
int32_t flags = *ebx & 0xFFFF;
|
||||
|
||||
*ebx = map_buy_land_rights(
|
||||
(*eax & 0xFFFF),
|
||||
(*ecx & 0xFFFF),
|
||||
(*edi & 0xFFFF),
|
||||
(*ebp & 0xFFFF),
|
||||
(*edx & 0x00FF),
|
||||
flags
|
||||
);
|
||||
*ebx = map_buy_land_rights((*eax & 0xFFFF), (*ecx & 0xFFFF), (*edi & 0xFFFF), (*ebp & 0xFFFF), (*edx & 0x00FF), flags);
|
||||
|
||||
// Too expensive to always call in map_buy_land_rights.
|
||||
// It's already counted when the park is loaded, after
|
||||
// that it should only be called for user actions.
|
||||
if (flags & GAME_COMMAND_FLAG_APPLY) {
|
||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
||||
{
|
||||
map_count_remaining_land_rights();
|
||||
}
|
||||
}
|
||||
|
@ -532,30 +572,25 @@ void Park::Initialise()
|
|||
|
||||
gParkEntranceFee = MONEY(10, 00);
|
||||
|
||||
for (auto &peepSpawn : gPeepSpawns)
|
||||
for (auto& peepSpawn : gPeepSpawns)
|
||||
{
|
||||
peepSpawn.x = PEEP_SPAWN_UNDEFINED;
|
||||
}
|
||||
|
||||
gResearchPriorities =
|
||||
(1 << RESEARCH_CATEGORY_TRANSPORT) |
|
||||
(1 << RESEARCH_CATEGORY_GENTLE) |
|
||||
(1 << RESEARCH_CATEGORY_ROLLERCOASTER) |
|
||||
(1 << RESEARCH_CATEGORY_THRILL) |
|
||||
(1 << RESEARCH_CATEGORY_WATER) |
|
||||
(1 << RESEARCH_CATEGORY_SHOP) |
|
||||
(1 << RESEARCH_CATEGORY_SCENERY_GROUP);
|
||||
gResearchPriorities = (1 << RESEARCH_CATEGORY_TRANSPORT) | (1 << RESEARCH_CATEGORY_GENTLE)
|
||||
| (1 << RESEARCH_CATEGORY_ROLLERCOASTER) | (1 << RESEARCH_CATEGORY_THRILL) | (1 << RESEARCH_CATEGORY_WATER)
|
||||
| (1 << RESEARCH_CATEGORY_SHOP) | (1 << RESEARCH_CATEGORY_SCENERY_GROUP);
|
||||
gResearchFundingLevel = RESEARCH_FUNDING_NORMAL;
|
||||
|
||||
gGuestInitialCash = MONEY(50,00);
|
||||
gGuestInitialCash = MONEY(50, 00);
|
||||
gGuestInitialHappiness = CalculateGuestInitialHappiness(50);
|
||||
gGuestInitialHunger = 200;
|
||||
gGuestInitialThirst = 200;
|
||||
gScenarioObjectiveType = OBJECTIVE_GUESTS_BY;
|
||||
gScenarioObjectiveYear = 4;
|
||||
gScenarioObjectiveNumGuests = 1000;
|
||||
gLandPrice = MONEY(90,00);
|
||||
gConstructionRightsPrice = MONEY(40,00);
|
||||
gLandPrice = MONEY(90, 00);
|
||||
gConstructionRightsPrice = MONEY(40, 00);
|
||||
gParkFlags = PARK_FLAGS_NO_MONEY | PARK_FLAGS_SHOW_REAL_GUEST_NAMES;
|
||||
ResetHistories();
|
||||
finance_reset_history();
|
||||
|
@ -565,7 +600,7 @@ void Park::Initialise()
|
|||
format_string(gS6Info.details, 256, STR_NO_DETAILS_YET, nullptr);
|
||||
}
|
||||
|
||||
void Park::Update(const Date &date)
|
||||
void Park::Update(const Date& date)
|
||||
{
|
||||
// Every ~13 seconds
|
||||
if (gCurrentTicks % 512 == 0)
|
||||
|
@ -602,7 +637,8 @@ int32_t Park::CalculateParkSize() const
|
|||
|
||||
tiles = 0;
|
||||
tile_element_iterator_begin(&it);
|
||||
do {
|
||||
do
|
||||
{
|
||||
if (it.element->GetType() == TILE_ELEMENT_TYPE_SURFACE)
|
||||
{
|
||||
if (it.element->properties.surface.ownership & (OWNERSHIP_CONSTRUCTION_RIGHTS_OWNED | OWNERSHIP_OWNED))
|
||||
|
@ -612,7 +648,8 @@ int32_t Park::CalculateParkSize() const
|
|||
}
|
||||
} while (tile_element_iterator_next(&it));
|
||||
|
||||
if (tiles != gParkSize) {
|
||||
if (tiles != gParkSize)
|
||||
{
|
||||
gParkSize = tiles;
|
||||
window_invalidate_by_class(WC_PARK_INFORMATION);
|
||||
}
|
||||
|
@ -642,8 +679,8 @@ int32_t Park::CalculateParkRating() const
|
|||
int32_t happyGuestCount = 0;
|
||||
int32_t lostGuestCount = 0;
|
||||
uint16_t spriteIndex;
|
||||
rct_peep * peep;
|
||||
FOR_ALL_GUESTS(spriteIndex, peep)
|
||||
rct_peep* peep;
|
||||
FOR_ALL_GUESTS (spriteIndex, peep)
|
||||
{
|
||||
if (peep->outside_of_park == 0)
|
||||
{
|
||||
|
@ -651,8 +688,7 @@ int32_t Park::CalculateParkRating() const
|
|||
{
|
||||
happyGuestCount++;
|
||||
}
|
||||
if ((peep->peep_flags & PEEP_FLAGS_LEAVING_PARK) &&
|
||||
(peep->peep_is_lost_countdown < 90))
|
||||
if ((peep->peep_flags & PEEP_FLAGS_LEAVING_PARK) && (peep->peep_is_lost_countdown < 90))
|
||||
{
|
||||
lostGuestCount++;
|
||||
}
|
||||
|
@ -682,8 +718,8 @@ int32_t Park::CalculateParkRating() const
|
|||
int32_t totalRideExcitement = 0;
|
||||
|
||||
int32_t i;
|
||||
Ride * ride;
|
||||
FOR_ALL_RIDES(i, ride)
|
||||
Ride* ride;
|
||||
FOR_ALL_RIDES (i, ride)
|
||||
{
|
||||
totalRideUptime += 100 - ride->downtime;
|
||||
if (ride->excitement != RIDE_RATING_UNDEFINED)
|
||||
|
@ -729,9 +765,10 @@ int32_t Park::CalculateParkRating() const
|
|||
|
||||
// Litter
|
||||
{
|
||||
rct_litter * litter;
|
||||
rct_litter* litter;
|
||||
int32_t litterCount = 0;
|
||||
for (uint16_t spriteIndex = gSpriteListHead[SPRITE_LIST_LITTER]; spriteIndex != SPRITE_INDEX_NULL; spriteIndex = litter->next)
|
||||
for (uint16_t spriteIndex = gSpriteListHead[SPRITE_LIST_LITTER]; spriteIndex != SPRITE_INDEX_NULL;
|
||||
spriteIndex = litter->next)
|
||||
{
|
||||
litter = &(get_sprite(spriteIndex)->litter);
|
||||
|
||||
|
@ -766,11 +803,10 @@ money32 Park::CalculateParkValue() const
|
|||
return result;
|
||||
}
|
||||
|
||||
money32 Park::CalculateRideValue(const Ride * ride) const
|
||||
money32 Park::CalculateRideValue(const Ride* ride) const
|
||||
{
|
||||
money32 result = 0;
|
||||
if (ride->type != RIDE_TYPE_NULL &&
|
||||
ride->value != RIDE_VALUE_UNDEFINED)
|
||||
if (ride->type != RIDE_TYPE_NULL && ride->value != RIDE_VALUE_UNDEFINED)
|
||||
{
|
||||
result = (ride->value * 10) * (ride_customers_in_last_5_minutes(ride) + rideBonusValue[ride->type] * 4);
|
||||
}
|
||||
|
@ -786,12 +822,15 @@ money16 Park::CalculateTotalRideValueForMoney() const
|
|||
{
|
||||
money16 totalRideValue = 0;
|
||||
int32_t i;
|
||||
Ride * ride;
|
||||
FOR_ALL_RIDES(i, ride)
|
||||
Ride* ride;
|
||||
FOR_ALL_RIDES (i, ride)
|
||||
{
|
||||
if (ride->status != RIDE_STATUS_OPEN) continue;
|
||||
if (ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN) continue;
|
||||
if (ride->lifecycle_flags & RIDE_LIFECYCLE_CRASHED) continue;
|
||||
if (ride->status != RIDE_STATUS_OPEN)
|
||||
continue;
|
||||
if (ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN)
|
||||
continue;
|
||||
if (ride->lifecycle_flags & RIDE_LIFECYCLE_CRASHED)
|
||||
continue;
|
||||
|
||||
// Add ride value
|
||||
if (ride->value != RIDE_VALUE_UNDEFINED)
|
||||
|
@ -812,12 +851,15 @@ uint32_t Park::CalculateSuggestedMaxGuests() const
|
|||
|
||||
// TODO combine the two ride loops
|
||||
int32_t i;
|
||||
Ride * ride;
|
||||
FOR_ALL_RIDES(i, ride)
|
||||
Ride* ride;
|
||||
FOR_ALL_RIDES (i, ride)
|
||||
{
|
||||
if (ride->status != RIDE_STATUS_OPEN) continue;
|
||||
if (ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN) continue;
|
||||
if (ride->lifecycle_flags & RIDE_LIFECYCLE_CRASHED) continue;
|
||||
if (ride->status != RIDE_STATUS_OPEN)
|
||||
continue;
|
||||
if (ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN)
|
||||
continue;
|
||||
if (ride->lifecycle_flags & RIDE_LIFECYCLE_CRASHED)
|
||||
continue;
|
||||
|
||||
// Add guest score for ride type
|
||||
suggestedMaxGuests += rideBonusValue[ride->type];
|
||||
|
@ -827,15 +869,22 @@ uint32_t Park::CalculateSuggestedMaxGuests() const
|
|||
if (gParkFlags & PARK_FLAGS_DIFFICULT_GUEST_GENERATION)
|
||||
{
|
||||
suggestedMaxGuests = std::min<uint32_t>(suggestedMaxGuests, 1000);
|
||||
FOR_ALL_RIDES(i, ride)
|
||||
FOR_ALL_RIDES (i, ride)
|
||||
{
|
||||
if (ride->lifecycle_flags & RIDE_LIFECYCLE_CRASHED) continue;
|
||||
if (ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN) continue;
|
||||
if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED)) continue;
|
||||
if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_TRACK)) continue;
|
||||
if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_DATA_LOGGING)) continue;
|
||||
if (ride->length[0] < (600 << 16)) continue;
|
||||
if (ride->excitement < RIDE_RATING(6, 00)) continue;
|
||||
if (ride->lifecycle_flags & RIDE_LIFECYCLE_CRASHED)
|
||||
continue;
|
||||
if (ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN)
|
||||
continue;
|
||||
if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED))
|
||||
continue;
|
||||
if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_TRACK))
|
||||
continue;
|
||||
if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_DATA_LOGGING))
|
||||
continue;
|
||||
if (ride->length[0] < (600 << 16))
|
||||
continue;
|
||||
if (ride->excitement < RIDE_RATING(6, 00))
|
||||
continue;
|
||||
|
||||
// Bonus guests for good ride
|
||||
suggestedMaxGuests += rideBonusValue[ride->type] * 2;
|
||||
|
@ -947,7 +996,7 @@ void Park::GenerateGuests()
|
|||
}
|
||||
}
|
||||
|
||||
rct_peep * Park::GenerateGuestFromCampaign(int32_t campaign)
|
||||
rct_peep* Park::GenerateGuestFromCampaign(int32_t campaign)
|
||||
{
|
||||
auto peep = GenerateGuest();
|
||||
if (peep != nullptr)
|
||||
|
@ -957,9 +1006,9 @@ rct_peep * Park::GenerateGuestFromCampaign(int32_t campaign)
|
|||
return peep;
|
||||
}
|
||||
|
||||
rct_peep * Park::GenerateGuest()
|
||||
rct_peep* Park::GenerateGuest()
|
||||
{
|
||||
rct_peep * peep = nullptr;
|
||||
rct_peep* peep = nullptr;
|
||||
PeepSpawn spawn = gPeepSpawns[get_random_peep_spawn_index()];
|
||||
|
||||
if (spawn.x != PEEP_SPAWN_UNDEFINED)
|
||||
|
@ -983,8 +1032,7 @@ rct_peep * Park::GenerateGuest()
|
|||
return peep;
|
||||
}
|
||||
|
||||
template<typename T, size_t TSize>
|
||||
static void HistoryPushRecord(T history[TSize], T newItem)
|
||||
template<typename T, size_t TSize> static void HistoryPushRecord(T history[TSize], T newItem)
|
||||
{
|
||||
for (size_t i = TSize - 1; i > 0; i--)
|
||||
{
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#define DECRYPT_MONEY(money) ((money32)rol32((money) ^ 0xF4EC9621, 13))
|
||||
#define ENCRYPT_MONEY(money) ((money32)(ror32((money), 13) ^ 0xF4EC9621))
|
||||
|
||||
#define MAX_ENTRANCE_FEE MONEY(200,00)
|
||||
#define MAX_ENTRANCE_FEE MONEY(200, 00)
|
||||
|
||||
struct rct_peep;
|
||||
|
||||
|
@ -37,10 +37,10 @@ enum : uint32_t
|
|||
PARK_FLAGS_PARK_FREE_ENTRY = (1 << 13),
|
||||
PARK_FLAGS_DIFFICULT_PARK_RATING = (1 << 14),
|
||||
PARK_FLAGS_LOCK_REAL_NAMES_OPTION_DEPRECATED = (1 << 15), // Deprecated now we use a persistent 'real names' setting
|
||||
PARK_FLAGS_NO_MONEY_SCENARIO = (1 << 17), // equivalent to PARK_FLAGS_NO_MONEY, but used in scenario editor
|
||||
PARK_FLAGS_SPRITES_INITIALISED = (1 << 18), // After a scenario is loaded this prevents edits in the scenario editor
|
||||
PARK_FLAGS_NO_MONEY_SCENARIO = (1 << 17), // equivalent to PARK_FLAGS_NO_MONEY, but used in scenario editor
|
||||
PARK_FLAGS_SPRITES_INITIALISED = (1 << 18), // After a scenario is loaded this prevents edits in the scenario editor
|
||||
PARK_FLAGS_SIX_FLAGS_DEPRECATED = (1 << 19), // Not used anymore
|
||||
PARK_FLAGS_UNLOCK_ALL_PRICES = (1u << 31), // OpenRCT2 only!
|
||||
PARK_FLAGS_UNLOCK_ALL_PRICES = (1u << 31), // OpenRCT2 only!
|
||||
};
|
||||
|
||||
struct rct_peep;
|
||||
|
@ -58,35 +58,34 @@ namespace OpenRCT2
|
|||
|
||||
bool IsOpen() const;
|
||||
|
||||
uint16_t GetParkRating() const;
|
||||
uint16_t GetParkRating() const;
|
||||
money32 GetParkValue() const;
|
||||
money32 GetCompanyValue() const;
|
||||
|
||||
void Initialise();
|
||||
void Update(const Date &date);
|
||||
void Update(const Date& date);
|
||||
|
||||
int32_t CalculateParkSize() const;
|
||||
int32_t CalculateParkRating() const;
|
||||
money32 CalculateParkValue() const;
|
||||
money32 CalculateCompanyValue() const;
|
||||
static uint8_t CalculateGuestInitialHappiness(uint8_t percentage);
|
||||
int32_t CalculateParkSize() const;
|
||||
int32_t CalculateParkRating() const;
|
||||
money32 CalculateParkValue() const;
|
||||
money32 CalculateCompanyValue() const;
|
||||
static uint8_t CalculateGuestInitialHappiness(uint8_t percentage);
|
||||
|
||||
rct_peep * GenerateGuest();
|
||||
rct_peep* GenerateGuest();
|
||||
|
||||
void ResetHistories();
|
||||
void UpdateHistories();
|
||||
|
||||
private:
|
||||
money32 CalculateRideValue(const Ride * ride) const;
|
||||
money16 CalculateTotalRideValueForMoney() const;
|
||||
uint32_t CalculateSuggestedMaxGuests() const;
|
||||
uint32_t CalculateGuestGenerationProbability() const;
|
||||
|
||||
void GenerateGuests();
|
||||
rct_peep * GenerateGuestFromCampaign(int32_t campaign);
|
||||
money32 CalculateRideValue(const Ride* ride) const;
|
||||
money16 CalculateTotalRideValueForMoney() const;
|
||||
uint32_t CalculateSuggestedMaxGuests() const;
|
||||
uint32_t CalculateGuestGenerationProbability() const;
|
||||
|
||||
void GenerateGuests();
|
||||
rct_peep* GenerateGuestFromCampaign(int32_t campaign);
|
||||
};
|
||||
}
|
||||
} // namespace OpenRCT2
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -135,14 +134,17 @@ uint8_t calculate_guest_initial_happiness(uint8_t percentage);
|
|||
|
||||
void park_set_open(int32_t open);
|
||||
int32_t park_entrance_get_index(int32_t x, int32_t y, int32_t z);
|
||||
void park_set_name(const char *name);
|
||||
void park_set_name(const char* name);
|
||||
void park_set_entrance_fee(money32 value);
|
||||
|
||||
int32_t map_buy_land_rights(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t setting, int32_t flags);
|
||||
|
||||
void game_command_set_park_entrance_fee(int32_t *eax, int32_t *ebx, int32_t *ecx, int32_t *edx, int32_t *esi, int32_t *edi, int32_t *ebp);
|
||||
void game_command_set_park_open(int32_t *eax, int32_t *ebx, int32_t *ecx, int32_t *edx, int32_t *esi, int32_t *edi, int32_t *ebp);
|
||||
void game_command_buy_land_rights(int32_t *eax, int32_t *ebx, int32_t *ecx, int32_t *edx, int32_t *esi, int32_t *edi, int32_t *ebp);
|
||||
void game_command_set_park_entrance_fee(
|
||||
int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_set_park_open(
|
||||
int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void game_command_buy_land_rights(
|
||||
int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
|
||||
money16 park_get_entrance_fee();
|
||||
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
|
||||
#include "../audio/audio.h"
|
||||
#include "../core/Util.hpp"
|
||||
#include "../scenario/Scenario.h"
|
||||
#include "../paint/sprite/Paint.Sprite.h"
|
||||
#include "../scenario/Scenario.h"
|
||||
#include "Sprite.h"
|
||||
|
||||
/**
|
||||
|
@ -19,27 +19,27 @@
|
|||
*/
|
||||
void crashed_vehicle_particle_create(rct_vehicle_colour colours, int32_t x, int32_t y, int32_t z)
|
||||
{
|
||||
rct_crashed_vehicle_particle * sprite = (rct_crashed_vehicle_particle *) create_sprite(2);
|
||||
rct_crashed_vehicle_particle* sprite = (rct_crashed_vehicle_particle*)create_sprite(2);
|
||||
if (sprite != nullptr)
|
||||
{
|
||||
sprite->colour[0] = colours.body_colour;
|
||||
sprite->colour[1] = colours.trim_colour;
|
||||
sprite->sprite_width = 8;
|
||||
sprite->sprite_width = 8;
|
||||
sprite->sprite_height_negative = 8;
|
||||
sprite->sprite_height_positive = 8;
|
||||
sprite->sprite_identifier = SPRITE_IDENTIFIER_MISC;
|
||||
sprite_move(x, y, z, (rct_sprite *) sprite);
|
||||
sprite->sprite_identifier = SPRITE_IDENTIFIER_MISC;
|
||||
sprite_move(x, y, z, (rct_sprite*)sprite);
|
||||
sprite->misc_identifier = SPRITE_MISC_CRASHED_VEHICLE_PARTICLE;
|
||||
|
||||
sprite->frame = (scenario_rand() & 0xFF) * 12;
|
||||
sprite->time_to_live = (scenario_rand() & 0x7F) + 140;
|
||||
sprite->frame = (scenario_rand() & 0xFF) * 12;
|
||||
sprite->time_to_live = (scenario_rand() & 0x7F) + 140;
|
||||
sprite->crashed_sprite_base = scenario_rand_max((uint32_t)Util::CountOf(vehicle_particle_base_sprites));
|
||||
sprite->acceleration_x = ((int16_t) (scenario_rand() & 0xFFFF)) * 4;
|
||||
sprite->acceleration_y = ((int16_t) (scenario_rand() & 0xFFFF)) * 4;
|
||||
sprite->acceleration_x = ((int16_t)(scenario_rand() & 0xFFFF)) * 4;
|
||||
sprite->acceleration_y = ((int16_t)(scenario_rand() & 0xFFFF)) * 4;
|
||||
sprite->acceleration_z = (scenario_rand() & 0xFFFF) * 4 + 0x10000;
|
||||
sprite->velocity_x = 0;
|
||||
sprite->velocity_y = 0;
|
||||
sprite->velocity_z = 0;
|
||||
sprite->velocity_x = 0;
|
||||
sprite->velocity_y = 0;
|
||||
sprite->velocity_z = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -47,13 +47,13 @@ void crashed_vehicle_particle_create(rct_vehicle_colour colours, int32_t x, int3
|
|||
*
|
||||
* rct2: 0x00673298
|
||||
*/
|
||||
void crashed_vehicle_particle_update(rct_crashed_vehicle_particle * particle)
|
||||
void crashed_vehicle_particle_update(rct_crashed_vehicle_particle* particle)
|
||||
{
|
||||
invalidate_sprite_0((rct_sprite *) particle);
|
||||
invalidate_sprite_0((rct_sprite*)particle);
|
||||
particle->time_to_live--;
|
||||
if (particle->time_to_live == 0)
|
||||
{
|
||||
sprite_remove((rct_sprite *) particle);
|
||||
sprite_remove((rct_sprite*)particle);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -80,15 +80,15 @@ void crashed_vehicle_particle_update(rct_crashed_vehicle_particle * particle)
|
|||
|
||||
// Check collision with land / water
|
||||
uint32_t waterLand = tile_element_height(x, y);
|
||||
int16_t landZ = (waterLand & 0xFFFF);
|
||||
int16_t waterZ = (waterLand >> 16);
|
||||
int16_t landZ = (waterLand & 0xFFFF);
|
||||
int16_t waterZ = (waterLand >> 16);
|
||||
|
||||
if (waterZ != 0 && particle->z >= waterZ && z <= waterZ)
|
||||
{
|
||||
// Splash
|
||||
audio_play_sound_at_location(SOUND_WATER_2, particle->x, particle->y, waterZ);
|
||||
crash_splash_create(particle->x, particle->y, waterZ);
|
||||
sprite_remove((rct_sprite *) particle);
|
||||
sprite_remove((rct_sprite*)particle);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -98,8 +98,8 @@ void crashed_vehicle_particle_update(rct_crashed_vehicle_particle * particle)
|
|||
particle->acceleration_z *= -1;
|
||||
z = landZ;
|
||||
}
|
||||
sprite_move(x, y, z, (rct_sprite *) particle);
|
||||
invalidate_sprite_0((rct_sprite *) particle);
|
||||
sprite_move(x, y, z, (rct_sprite*)particle);
|
||||
invalidate_sprite_0((rct_sprite*)particle);
|
||||
|
||||
particle->frame += 85;
|
||||
if (particle->frame >= 3072)
|
||||
|
@ -114,16 +114,16 @@ void crashed_vehicle_particle_update(rct_crashed_vehicle_particle * particle)
|
|||
*/
|
||||
void crash_splash_create(int32_t x, int32_t y, int32_t z)
|
||||
{
|
||||
rct_unk_sprite * sprite = (rct_unk_sprite *) create_sprite(2);
|
||||
rct_unk_sprite* sprite = (rct_unk_sprite*)create_sprite(2);
|
||||
if (sprite != nullptr)
|
||||
{
|
||||
sprite->sprite_width = 33;
|
||||
sprite->sprite_width = 33;
|
||||
sprite->sprite_height_negative = 51;
|
||||
sprite->sprite_height_positive = 16;
|
||||
sprite->sprite_identifier = SPRITE_IDENTIFIER_MISC;
|
||||
sprite_move(x, y, z + 3, (rct_sprite *) sprite);
|
||||
sprite->sprite_identifier = SPRITE_IDENTIFIER_MISC;
|
||||
sprite_move(x, y, z + 3, (rct_sprite*)sprite);
|
||||
sprite->misc_identifier = SPRITE_MISC_CRASH_SPLASH;
|
||||
sprite->frame = 0;
|
||||
sprite->frame = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,12 +131,12 @@ void crash_splash_create(int32_t x, int32_t y, int32_t z)
|
|||
*
|
||||
* rct2: 0x0067339D
|
||||
*/
|
||||
void crash_splash_update(rct_crash_splash * splash)
|
||||
void crash_splash_update(rct_crash_splash* splash)
|
||||
{
|
||||
invalidate_sprite_2((rct_sprite *) splash);
|
||||
invalidate_sprite_2((rct_sprite*)splash);
|
||||
splash->frame += 85;
|
||||
if (splash->frame >= 7168)
|
||||
{
|
||||
sprite_remove((rct_sprite *) splash);
|
||||
sprite_remove((rct_sprite*)splash);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,22 +7,23 @@
|
|||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "../common.h"
|
||||
#include "../Context.h"
|
||||
#include "Scenery.h"
|
||||
|
||||
#include "../Cheats.h"
|
||||
#include "../Context.h"
|
||||
#include "../Game.h"
|
||||
#include "../actions/WallRemoveAction.hpp"
|
||||
#include "../common.h"
|
||||
#include "../localisation/Localisation.h"
|
||||
#include "../network/network.h"
|
||||
#include "../object/ObjectList.h"
|
||||
#include "../object/ObjectManager.h"
|
||||
#include "../scenario/Scenario.h"
|
||||
#include "../actions/WallRemoveAction.hpp"
|
||||
#include "Climate.h"
|
||||
#include "Footpath.h"
|
||||
#include "Fountain.h"
|
||||
#include "Map.h"
|
||||
#include "Park.h"
|
||||
#include "Scenery.h"
|
||||
#include "SmallScenery.h"
|
||||
#include "Wall.h"
|
||||
|
||||
|
@ -36,7 +37,7 @@ colour_t gWindowScenerySecondaryColour;
|
|||
colour_t gWindowSceneryTertiaryColour;
|
||||
bool gWindowSceneryEyedropperEnabled;
|
||||
|
||||
rct_tile_element *gSceneryTileElement;
|
||||
rct_tile_element* gSceneryTileElement;
|
||||
uint8_t gSceneryTileElementType;
|
||||
|
||||
money32 gSceneryPlaceCost;
|
||||
|
@ -64,21 +65,17 @@ uint8_t gSceneryGroundFlags;
|
|||
money32 gClearSceneryCost;
|
||||
|
||||
// rct2: 0x009A3E74
|
||||
const LocationXY8 ScenerySubTileOffsets[] = {
|
||||
{ 7, 7 },
|
||||
{ 7, 23 },
|
||||
{ 23, 23 },
|
||||
{ 23, 7 }
|
||||
};
|
||||
const LocationXY8 ScenerySubTileOffsets[] = { { 7, 7 }, { 7, 23 }, { 23, 23 }, { 23, 7 } };
|
||||
|
||||
void scenery_increase_age(int32_t x, int32_t y, rct_tile_element *tileElement);
|
||||
void scenery_increase_age(int32_t x, int32_t y, rct_tile_element* tileElement);
|
||||
|
||||
void scenery_update_tile(int32_t x, int32_t y)
|
||||
{
|
||||
rct_tile_element *tileElement;
|
||||
rct_tile_element* tileElement;
|
||||
|
||||
tileElement = map_get_first_element_at(x >> 5, y >> 5);
|
||||
do {
|
||||
do
|
||||
{
|
||||
// Ghosts are purely this-client-side and should not cause any interaction,
|
||||
// as that may lead to a desync.
|
||||
if (network_get_mode() != NETWORK_MODE_NONE)
|
||||
|
@ -87,16 +84,23 @@ void scenery_update_tile(int32_t x, int32_t y)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (tileElement->GetType() == TILE_ELEMENT_TYPE_SMALL_SCENERY) {
|
||||
if (tileElement->GetType() == TILE_ELEMENT_TYPE_SMALL_SCENERY)
|
||||
{
|
||||
scenery_update_age(x, y, tileElement);
|
||||
} else if (tileElement->GetType() == TILE_ELEMENT_TYPE_PATH) {
|
||||
if (footpath_element_has_path_scenery(tileElement) && !footpath_element_path_scenery_is_ghost(tileElement)) {
|
||||
rct_scenery_entry *sceneryEntry = get_footpath_item_entry(footpath_element_get_path_scenery_index(tileElement));
|
||||
if (sceneryEntry != nullptr) {
|
||||
if (sceneryEntry->path_bit.flags & PATH_BIT_FLAG_JUMPING_FOUNTAIN_WATER) {
|
||||
}
|
||||
else if (tileElement->GetType() == TILE_ELEMENT_TYPE_PATH)
|
||||
{
|
||||
if (footpath_element_has_path_scenery(tileElement) && !footpath_element_path_scenery_is_ghost(tileElement))
|
||||
{
|
||||
rct_scenery_entry* sceneryEntry = get_footpath_item_entry(footpath_element_get_path_scenery_index(tileElement));
|
||||
if (sceneryEntry != nullptr)
|
||||
{
|
||||
if (sceneryEntry->path_bit.flags & PATH_BIT_FLAG_JUMPING_FOUNTAIN_WATER)
|
||||
{
|
||||
jumping_fountain_begin(JUMPING_FOUNTAIN_TYPE_WATER, x, y, tileElement);
|
||||
}
|
||||
else if (sceneryEntry->path_bit.flags & PATH_BIT_FLAG_JUMPING_FOUNTAIN_SNOW) {
|
||||
else if (sceneryEntry->path_bit.flags & PATH_BIT_FLAG_JUMPING_FOUNTAIN_SNOW)
|
||||
{
|
||||
jumping_fountain_begin(JUMPING_FOUNTAIN_TYPE_SNOW, x, y, tileElement);
|
||||
}
|
||||
}
|
||||
|
@ -109,10 +113,10 @@ void scenery_update_tile(int32_t x, int32_t y)
|
|||
*
|
||||
* rct2: 0x006E33D9
|
||||
*/
|
||||
void scenery_update_age(int32_t x, int32_t y, rct_tile_element *tileElement)
|
||||
void scenery_update_age(int32_t x, int32_t y, rct_tile_element* tileElement)
|
||||
{
|
||||
rct_tile_element *tileElementAbove;
|
||||
rct_scenery_entry *sceneryEntry;
|
||||
rct_tile_element* tileElementAbove;
|
||||
rct_scenery_entry* sceneryEntry;
|
||||
|
||||
sceneryEntry = get_small_scenery_entry(tileElement->properties.scenery.type);
|
||||
if (sceneryEntry == nullptr)
|
||||
|
@ -125,19 +129,17 @@ void scenery_update_age(int32_t x, int32_t y, rct_tile_element *tileElement)
|
|||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
!scenery_small_entry_has_flag(sceneryEntry, SMALL_SCENERY_FLAG_CAN_BE_WATERED) ||
|
||||
(gClimateCurrent.Weather < WEATHER_RAIN) ||
|
||||
(tileElement->properties.scenery.age < 5)
|
||||
) {
|
||||
if (!scenery_small_entry_has_flag(sceneryEntry, SMALL_SCENERY_FLAG_CAN_BE_WATERED)
|
||||
|| (gClimateCurrent.Weather < WEATHER_RAIN) || (tileElement->properties.scenery.age < 5))
|
||||
{
|
||||
scenery_increase_age(x, y, tileElement);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check map elements above, presumably to see if map element is blocked from rain
|
||||
tileElementAbove = tileElement;
|
||||
while (!(tileElementAbove->flags & 7)) {
|
||||
|
||||
while (!(tileElementAbove->flags & 7))
|
||||
{
|
||||
tileElementAbove++;
|
||||
|
||||
// Ghosts are purely this-client-side and should not cause any interaction,
|
||||
|
@ -145,21 +147,22 @@ void scenery_update_age(int32_t x, int32_t y, rct_tile_element *tileElement)
|
|||
if (tile_element_is_ghost(tileElementAbove))
|
||||
continue;
|
||||
|
||||
switch (tileElementAbove->GetType()) {
|
||||
case TILE_ELEMENT_TYPE_LARGE_SCENERY:
|
||||
case TILE_ELEMENT_TYPE_ENTRANCE:
|
||||
case TILE_ELEMENT_TYPE_PATH:
|
||||
map_invalidate_tile_zoom1(x, y, tileElementAbove->base_height * 8, tileElementAbove->clearance_height * 8);
|
||||
scenery_increase_age(x, y, tileElement);
|
||||
return;
|
||||
case TILE_ELEMENT_TYPE_SMALL_SCENERY:
|
||||
sceneryEntry = get_small_scenery_entry(tileElementAbove->properties.scenery.type);
|
||||
if (scenery_small_entry_has_flag(sceneryEntry, SMALL_SCENERY_FLAG_VOFFSET_CENTRE))
|
||||
{
|
||||
switch (tileElementAbove->GetType())
|
||||
{
|
||||
case TILE_ELEMENT_TYPE_LARGE_SCENERY:
|
||||
case TILE_ELEMENT_TYPE_ENTRANCE:
|
||||
case TILE_ELEMENT_TYPE_PATH:
|
||||
map_invalidate_tile_zoom1(x, y, tileElementAbove->base_height * 8, tileElementAbove->clearance_height * 8);
|
||||
scenery_increase_age(x, y, tileElement);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case TILE_ELEMENT_TYPE_SMALL_SCENERY:
|
||||
sceneryEntry = get_small_scenery_entry(tileElementAbove->properties.scenery.type);
|
||||
if (scenery_small_entry_has_flag(sceneryEntry, SMALL_SCENERY_FLAG_VOFFSET_CENTRE))
|
||||
{
|
||||
scenery_increase_age(x, y, tileElement);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -168,18 +171,19 @@ void scenery_update_age(int32_t x, int32_t y, rct_tile_element *tileElement)
|
|||
map_invalidate_tile_zoom1(x, y, tileElement->base_height * 8, tileElement->clearance_height * 8);
|
||||
}
|
||||
|
||||
void scenery_increase_age(int32_t x, int32_t y, rct_tile_element *tileElement)
|
||||
void scenery_increase_age(int32_t x, int32_t y, rct_tile_element* tileElement)
|
||||
{
|
||||
if (tileElement->flags & SMALL_SCENERY_FLAG_ANIMATED)
|
||||
return;
|
||||
|
||||
if (tileElement->properties.scenery.age < 255) {
|
||||
if (tileElement->properties.scenery.age < 255)
|
||||
{
|
||||
uint8_t newAge = tileElement->properties.scenery.age++;
|
||||
|
||||
// Only invalidate tiles when scenery crosses the withering threshholds, and can be withered.
|
||||
if (newAge == SCENERY_WITHER_AGE_THRESHOLD_1 || newAge == SCENERY_WITHER_AGE_THRESHOLD_2)
|
||||
{
|
||||
rct_scenery_entry *entry = get_small_scenery_entry(tileElement->properties.scenery.type);
|
||||
rct_scenery_entry* entry = get_small_scenery_entry(tileElement->properties.scenery.type);
|
||||
|
||||
if (scenery_small_entry_has_flag(entry, SMALL_SCENERY_FLAG_CAN_WITHER))
|
||||
{
|
||||
|
@ -193,29 +197,25 @@ void scenery_increase_age(int32_t x, int32_t y, rct_tile_element *tileElement)
|
|||
*
|
||||
* rct2: 0x006E2712
|
||||
*/
|
||||
void scenery_remove_ghost_tool_placement(){
|
||||
void scenery_remove_ghost_tool_placement()
|
||||
{
|
||||
int16_t x, y, z;
|
||||
|
||||
x = gSceneryGhostPosition.x;
|
||||
y = gSceneryGhostPosition.y;
|
||||
z = gSceneryGhostPosition.z;
|
||||
|
||||
if (gSceneryGhostType & SCENERY_ENTRY_FLAG_0){
|
||||
if (gSceneryGhostType & SCENERY_ENTRY_FLAG_0)
|
||||
{
|
||||
gSceneryGhostType &= ~SCENERY_ENTRY_FLAG_0;
|
||||
game_do_command(
|
||||
x,
|
||||
105 | (gSceneryTileElementType << 8),
|
||||
y,
|
||||
z | (gSceneryPlaceObject << 8),
|
||||
GAME_COMMAND_REMOVE_SCENERY,
|
||||
0,
|
||||
0);
|
||||
x, 105 | (gSceneryTileElementType << 8), y, z | (gSceneryPlaceObject << 8), GAME_COMMAND_REMOVE_SCENERY, 0, 0);
|
||||
}
|
||||
|
||||
if (gSceneryGhostType & SCENERY_ENTRY_FLAG_1)
|
||||
{
|
||||
gSceneryGhostType &= ~SCENERY_ENTRY_FLAG_1;
|
||||
rct_tile_element * tileElement = map_get_first_element_at(x / 32, y / 32);
|
||||
rct_tile_element* tileElement = map_get_first_element_at(x / 32, y / 32);
|
||||
|
||||
do
|
||||
{
|
||||
|
@ -247,116 +247,104 @@ void scenery_remove_ghost_tool_placement(){
|
|||
wallRemoveAction.Execute();
|
||||
}
|
||||
|
||||
if (gSceneryGhostType & SCENERY_ENTRY_FLAG_3){
|
||||
if (gSceneryGhostType & SCENERY_ENTRY_FLAG_3)
|
||||
{
|
||||
gSceneryGhostType &= ~SCENERY_ENTRY_FLAG_3;
|
||||
game_do_command(
|
||||
x,
|
||||
105 | (gSceneryPlaceRotation << 8),
|
||||
y,
|
||||
z,
|
||||
GAME_COMMAND_REMOVE_LARGE_SCENERY,
|
||||
0,
|
||||
0);
|
||||
game_do_command(x, 105 | (gSceneryPlaceRotation << 8), y, z, GAME_COMMAND_REMOVE_LARGE_SCENERY, 0, 0);
|
||||
}
|
||||
|
||||
if (gSceneryGhostType & SCENERY_ENTRY_FLAG_4){
|
||||
if (gSceneryGhostType & SCENERY_ENTRY_FLAG_4)
|
||||
{
|
||||
gSceneryGhostType &= ~SCENERY_ENTRY_FLAG_4;
|
||||
game_do_command(
|
||||
x,
|
||||
105,
|
||||
y,
|
||||
z | (gSceneryPlaceRotation << 8),
|
||||
GAME_COMMAND_REMOVE_BANNER,
|
||||
0,
|
||||
0);
|
||||
game_do_command(x, 105, y, z | (gSceneryPlaceRotation << 8), GAME_COMMAND_REMOVE_BANNER, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
rct_scenery_entry *get_small_scenery_entry(int32_t entryIndex)
|
||||
rct_scenery_entry* get_small_scenery_entry(int32_t entryIndex)
|
||||
{
|
||||
rct_scenery_entry * result = nullptr;
|
||||
rct_scenery_entry* result = nullptr;
|
||||
auto objMgr = OpenRCT2::GetContext()->GetObjectManager();
|
||||
if (objMgr != nullptr)
|
||||
{
|
||||
auto obj = objMgr->GetLoadedObject(OBJECT_TYPE_SMALL_SCENERY, entryIndex);
|
||||
if (obj != nullptr)
|
||||
{
|
||||
result = (rct_scenery_entry *)obj->GetLegacyData();
|
||||
result = (rct_scenery_entry*)obj->GetLegacyData();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
rct_scenery_entry *get_large_scenery_entry(int32_t entryIndex)
|
||||
rct_scenery_entry* get_large_scenery_entry(int32_t entryIndex)
|
||||
{
|
||||
rct_scenery_entry * result = nullptr;
|
||||
rct_scenery_entry* result = nullptr;
|
||||
auto objMgr = OpenRCT2::GetContext()->GetObjectManager();
|
||||
if (objMgr != nullptr)
|
||||
{
|
||||
auto obj = objMgr->GetLoadedObject(OBJECT_TYPE_LARGE_SCENERY, entryIndex);
|
||||
if (obj != nullptr)
|
||||
{
|
||||
result = (rct_scenery_entry *)obj->GetLegacyData();
|
||||
result = (rct_scenery_entry*)obj->GetLegacyData();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
rct_scenery_entry *get_wall_entry(int32_t entryIndex)
|
||||
rct_scenery_entry* get_wall_entry(int32_t entryIndex)
|
||||
{
|
||||
rct_scenery_entry * result = nullptr;
|
||||
rct_scenery_entry* result = nullptr;
|
||||
auto objMgr = OpenRCT2::GetContext()->GetObjectManager();
|
||||
if (objMgr != nullptr)
|
||||
{
|
||||
auto obj = objMgr->GetLoadedObject(OBJECT_TYPE_WALLS, entryIndex);
|
||||
if (obj != nullptr)
|
||||
{
|
||||
result = (rct_scenery_entry *)obj->GetLegacyData();
|
||||
result = (rct_scenery_entry*)obj->GetLegacyData();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
rct_scenery_entry *get_banner_entry(int32_t entryIndex)
|
||||
rct_scenery_entry* get_banner_entry(int32_t entryIndex)
|
||||
{
|
||||
rct_scenery_entry * result = nullptr;
|
||||
rct_scenery_entry* result = nullptr;
|
||||
auto objMgr = OpenRCT2::GetContext()->GetObjectManager();
|
||||
if (objMgr != nullptr)
|
||||
{
|
||||
auto obj = objMgr->GetLoadedObject(OBJECT_TYPE_BANNERS, entryIndex);
|
||||
if (obj != nullptr)
|
||||
{
|
||||
result = (rct_scenery_entry *)obj->GetLegacyData();
|
||||
result = (rct_scenery_entry*)obj->GetLegacyData();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
rct_scenery_entry *get_footpath_item_entry(int32_t entryIndex)
|
||||
rct_scenery_entry* get_footpath_item_entry(int32_t entryIndex)
|
||||
{
|
||||
rct_scenery_entry * result = nullptr;
|
||||
rct_scenery_entry* result = nullptr;
|
||||
auto objMgr = OpenRCT2::GetContext()->GetObjectManager();
|
||||
if (objMgr != nullptr)
|
||||
{
|
||||
auto obj = objMgr->GetLoadedObject(OBJECT_TYPE_PATH_BITS, entryIndex);
|
||||
if (obj != nullptr)
|
||||
{
|
||||
result = (rct_scenery_entry *)obj->GetLegacyData();
|
||||
result = (rct_scenery_entry*)obj->GetLegacyData();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
rct_scenery_group_entry *get_scenery_group_entry(int32_t entryIndex)
|
||||
rct_scenery_group_entry* get_scenery_group_entry(int32_t entryIndex)
|
||||
{
|
||||
rct_scenery_group_entry * result = nullptr;
|
||||
rct_scenery_group_entry* result = nullptr;
|
||||
auto objMgr = OpenRCT2::GetContext()->GetObjectManager();
|
||||
if (objMgr != nullptr)
|
||||
{
|
||||
auto obj = objMgr->GetLoadedObject(OBJECT_TYPE_SCENERY_GROUP, entryIndex);
|
||||
if (obj != nullptr)
|
||||
{
|
||||
result = (rct_scenery_group_entry *)obj->GetLegacyData();
|
||||
result = (rct_scenery_group_entry*)obj->GetLegacyData();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -364,17 +352,24 @@ rct_scenery_group_entry *get_scenery_group_entry(int32_t entryIndex)
|
|||
|
||||
int32_t get_scenery_id_from_entry_index(uint8_t objectType, int32_t entryIndex)
|
||||
{
|
||||
switch (objectType) {
|
||||
case OBJECT_TYPE_SMALL_SCENERY: return entryIndex + SCENERY_SMALL_SCENERY_ID_MIN;
|
||||
case OBJECT_TYPE_PATH_BITS: return entryIndex + SCENERY_PATH_SCENERY_ID_MIN;
|
||||
case OBJECT_TYPE_WALLS: return entryIndex + SCENERY_WALLS_ID_MIN;
|
||||
case OBJECT_TYPE_LARGE_SCENERY: return entryIndex + SCENERY_LARGE_SCENERY_ID_MIN;
|
||||
case OBJECT_TYPE_BANNERS: return entryIndex + SCENERY_BANNERS_ID_MIN;
|
||||
default: return -1;
|
||||
switch (objectType)
|
||||
{
|
||||
case OBJECT_TYPE_SMALL_SCENERY:
|
||||
return entryIndex + SCENERY_SMALL_SCENERY_ID_MIN;
|
||||
case OBJECT_TYPE_PATH_BITS:
|
||||
return entryIndex + SCENERY_PATH_SCENERY_ID_MIN;
|
||||
case OBJECT_TYPE_WALLS:
|
||||
return entryIndex + SCENERY_WALLS_ID_MIN;
|
||||
case OBJECT_TYPE_LARGE_SCENERY:
|
||||
return entryIndex + SCENERY_LARGE_SCENERY_ID_MIN;
|
||||
case OBJECT_TYPE_BANNERS:
|
||||
return entryIndex + SCENERY_BANNERS_ID_MIN;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t wall_entry_get_door_sound(const rct_scenery_entry * wallEntry)
|
||||
int32_t wall_entry_get_door_sound(const rct_scenery_entry* wallEntry)
|
||||
{
|
||||
return (wallEntry->wall.flags2 & WALL_SCENERY_2_DOOR_SOUND_MASK) >> WALL_SCENERY_2_DOOR_SOUND_SHIFT;
|
||||
}
|
||||
|
|
|
@ -10,33 +10,35 @@
|
|||
#ifndef _SCENERY_H_
|
||||
#define _SCENERY_H_
|
||||
|
||||
#include <limits>
|
||||
#include "../common.h"
|
||||
#include "../object/Object.h"
|
||||
#include "../world/Location.hpp"
|
||||
#include "TileElement.h"
|
||||
|
||||
#define SCENERY_SMALL_SCENERY_ID_MIN 0x0
|
||||
#define SCENERY_SMALL_SCENERY_ID_MAX 0xFC
|
||||
#define SCENERY_LARGE_SCENERY_ID_MIN 0x300
|
||||
#define SCENERY_LARGE_SCENERY_ID_MAX 0x380
|
||||
#define SCENERY_WALLS_ID_MIN 0x200
|
||||
#define SCENERY_WALLS_ID_MAX 0x280
|
||||
#define SCENERY_BANNERS_ID_MIN 0x400
|
||||
#define SCENERY_BANNERS_ID_MAX 0x420
|
||||
#define SCENERY_PATH_SCENERY_ID_MIN 0x100
|
||||
#define SCENERY_PATH_SCENERY_ID_MAX 0x10F
|
||||
#define SCENERY_WITHER_AGE_THRESHOLD_1 0x28
|
||||
#define SCENERY_WITHER_AGE_THRESHOLD_2 0x37
|
||||
#include <limits>
|
||||
|
||||
#define SCENERY_SMALL_SCENERY_ID_MIN 0x0
|
||||
#define SCENERY_SMALL_SCENERY_ID_MAX 0xFC
|
||||
#define SCENERY_LARGE_SCENERY_ID_MIN 0x300
|
||||
#define SCENERY_LARGE_SCENERY_ID_MAX 0x380
|
||||
#define SCENERY_WALLS_ID_MIN 0x200
|
||||
#define SCENERY_WALLS_ID_MAX 0x280
|
||||
#define SCENERY_BANNERS_ID_MIN 0x400
|
||||
#define SCENERY_BANNERS_ID_MAX 0x420
|
||||
#define SCENERY_PATH_SCENERY_ID_MIN 0x100
|
||||
#define SCENERY_PATH_SCENERY_ID_MAX 0x10F
|
||||
#define SCENERY_WITHER_AGE_THRESHOLD_1 0x28
|
||||
#define SCENERY_WITHER_AGE_THRESHOLD_2 0x37
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct rct_small_scenery_entry {
|
||||
struct rct_small_scenery_entry
|
||||
{
|
||||
uint32_t flags; // 0x06
|
||||
uint8_t height; // 0x0A
|
||||
uint8_t tool_id; // 0x0B
|
||||
int16_t price; // 0x0C
|
||||
int16_t removal_price; // 0x0E
|
||||
uint8_t *frame_offsets; // 0x10
|
||||
int16_t price; // 0x0C
|
||||
int16_t removal_price; // 0x0E
|
||||
uint8_t* frame_offsets; // 0x10
|
||||
uint16_t animation_delay; // 0x14
|
||||
uint16_t animation_mask; // 0x16
|
||||
uint16_t num_frames; // 0x18
|
||||
|
@ -46,7 +48,8 @@ struct rct_small_scenery_entry {
|
|||
assert_struct_size(rct_small_scenery_entry, 21);
|
||||
#endif
|
||||
|
||||
struct rct_large_scenery_tile {
|
||||
struct rct_large_scenery_tile
|
||||
{
|
||||
int16_t x_offset;
|
||||
int16_t y_offset;
|
||||
int16_t z_offset;
|
||||
|
@ -58,11 +61,12 @@ assert_struct_size(rct_large_scenery_tile, 9);
|
|||
|
||||
enum
|
||||
{
|
||||
LARGE_SCENERY_TILE_FLAG_NO_SUPPORTS = 0x20,
|
||||
LARGE_SCENERY_TILE_FLAG_ALLOW_SUPPORTS_ABOVE = 0x40,
|
||||
LARGE_SCENERY_TILE_FLAG_NO_SUPPORTS = 0x20,
|
||||
LARGE_SCENERY_TILE_FLAG_ALLOW_SUPPORTS_ABOVE = 0x40,
|
||||
};
|
||||
|
||||
struct rct_large_scenery_text_glyph {
|
||||
struct rct_large_scenery_text_glyph
|
||||
{
|
||||
uint8_t image_offset;
|
||||
uint8_t width;
|
||||
uint8_t height;
|
||||
|
@ -70,37 +74,41 @@ struct rct_large_scenery_text_glyph {
|
|||
};
|
||||
assert_struct_size(rct_large_scenery_text_glyph, 4);
|
||||
|
||||
struct rct_large_scenery_text {
|
||||
LocationXY16 offset[2]; // 0x0
|
||||
uint16_t max_width; // 0x8
|
||||
uint16_t pad_A; // 0xA
|
||||
uint8_t flags; // 0xC
|
||||
uint8_t num_images; // 0xD
|
||||
struct rct_large_scenery_text
|
||||
{
|
||||
LocationXY16 offset[2]; // 0x0
|
||||
uint16_t max_width; // 0x8
|
||||
uint16_t pad_A; // 0xA
|
||||
uint8_t flags; // 0xC
|
||||
uint8_t num_images; // 0xD
|
||||
rct_large_scenery_text_glyph glyphs[256]; // 0xE
|
||||
};
|
||||
assert_struct_size(rct_large_scenery_text, 14 + 4 * 256);
|
||||
|
||||
enum LARGE_SCENERY_TEXT_FLAGS {
|
||||
LARGE_SCENERY_TEXT_FLAG_VERTICAL = (1 << 0), // 0x1
|
||||
LARGE_SCENERY_TEXT_FLAG_TWO_LINE = (1 << 1), // 0x2
|
||||
enum LARGE_SCENERY_TEXT_FLAGS
|
||||
{
|
||||
LARGE_SCENERY_TEXT_FLAG_VERTICAL = (1 << 0), // 0x1
|
||||
LARGE_SCENERY_TEXT_FLAG_TWO_LINE = (1 << 1), // 0x2
|
||||
};
|
||||
|
||||
struct rct_large_scenery_entry {
|
||||
uint8_t tool_id; // 0x06
|
||||
uint8_t flags; // 0x07
|
||||
int16_t price; // 0x08
|
||||
int16_t removal_price; // 0x0A
|
||||
struct rct_large_scenery_entry
|
||||
{
|
||||
uint8_t tool_id; // 0x06
|
||||
uint8_t flags; // 0x07
|
||||
int16_t price; // 0x08
|
||||
int16_t removal_price; // 0x0A
|
||||
rct_large_scenery_tile* tiles; // 0x0C
|
||||
uint8_t scenery_tab_id; // 0x10
|
||||
uint8_t scrolling_mode; // 0x11
|
||||
uint8_t scenery_tab_id; // 0x10
|
||||
uint8_t scrolling_mode; // 0x11
|
||||
rct_large_scenery_text* text; // 0x12
|
||||
uint32_t text_image; // 0x16
|
||||
uint32_t text_image; // 0x16
|
||||
};
|
||||
#ifdef PLATFORM_32BIT
|
||||
assert_struct_size(rct_large_scenery_entry, 20);
|
||||
#endif
|
||||
|
||||
enum LARGE_SCENERY_FLAGS {
|
||||
enum LARGE_SCENERY_FLAGS
|
||||
{
|
||||
LARGE_SCENERY_FLAG_HAS_PRIMARY_COLOUR = (1 << 0), // 0x1
|
||||
LARGE_SCENERY_FLAG_HAS_SECONDARY_COLOUR = (1 << 1), // 0x2
|
||||
LARGE_SCENERY_FLAG_3D_TEXT = (1 << 2), // 0x4
|
||||
|
@ -108,58 +116,64 @@ enum LARGE_SCENERY_FLAGS {
|
|||
LARGE_SCENERY_FLAG_PHOTOGENIC = (1 << 4), // 0x10
|
||||
};
|
||||
|
||||
struct rct_wall_scenery_entry {
|
||||
uint8_t tool_id; // 0x06
|
||||
uint8_t flags; // 0x07
|
||||
uint8_t height; // 0x08
|
||||
uint8_t flags2; // 0x09
|
||||
int16_t price; // 0x0A
|
||||
uint8_t scenery_tab_id; // 0x0C
|
||||
uint8_t scrolling_mode; // 0x0D 0xFF if no scrolling
|
||||
struct rct_wall_scenery_entry
|
||||
{
|
||||
uint8_t tool_id; // 0x06
|
||||
uint8_t flags; // 0x07
|
||||
uint8_t height; // 0x08
|
||||
uint8_t flags2; // 0x09
|
||||
int16_t price; // 0x0A
|
||||
uint8_t scenery_tab_id; // 0x0C
|
||||
uint8_t scrolling_mode; // 0x0D 0xFF if no scrolling
|
||||
};
|
||||
assert_struct_size(rct_wall_scenery_entry, 8);
|
||||
|
||||
enum WALL_SCENERY_FLAGS
|
||||
{
|
||||
WALL_SCENERY_HAS_PRIMARY_COLOUR = (1 << 0), // 0x1
|
||||
WALL_SCENERY_HAS_GLASS = (1 << 1), // 0x2
|
||||
WALL_SCENERY_CANT_BUILD_ON_SLOPE = (1 << 2), // 0x4
|
||||
WALL_SCENERY_IS_BANNER = (1 << 3), // 0x8 // Probably indicates translucency
|
||||
WALL_SCENERY_IS_DOOR = (1 << 4), // 0x10
|
||||
WALL_SCENERY_LONG_DOOR_ANIMATION = (1 << 5), // 0x20
|
||||
WALL_SCENERY_HAS_SECONDARY_COLOUR = (1 << 6), // 0x40
|
||||
WALL_SCENERY_HAS_TERNARY_COLOUR = (1 << 7), // 0x80
|
||||
WALL_SCENERY_HAS_PRIMARY_COLOUR = (1 << 0), // 0x1
|
||||
WALL_SCENERY_HAS_GLASS = (1 << 1), // 0x2
|
||||
WALL_SCENERY_CANT_BUILD_ON_SLOPE = (1 << 2), // 0x4
|
||||
WALL_SCENERY_IS_BANNER = (1 << 3), // 0x8 // Probably indicates translucency
|
||||
WALL_SCENERY_IS_DOOR = (1 << 4), // 0x10
|
||||
WALL_SCENERY_LONG_DOOR_ANIMATION = (1 << 5), // 0x20
|
||||
WALL_SCENERY_HAS_SECONDARY_COLOUR = (1 << 6), // 0x40
|
||||
WALL_SCENERY_HAS_TERNARY_COLOUR = (1 << 7), // 0x80
|
||||
};
|
||||
|
||||
enum WALL_SCENERY_2_FLAGS {
|
||||
WALL_SCENERY_2_NO_SELECT_PRIMARY_COLOUR = (1 << 0), // 0x1
|
||||
enum WALL_SCENERY_2_FLAGS
|
||||
{
|
||||
WALL_SCENERY_2_NO_SELECT_PRIMARY_COLOUR = (1 << 0), // 0x1
|
||||
WALL_SCENERY_2_DOOR_SOUND_MASK = 0x6,
|
||||
WALL_SCENERY_2_DOOR_SOUND_SHIFT = 1,
|
||||
WALL_SCENERY_2_IS_OPAQUE = (1 << 3), // 0x8
|
||||
WALL_SCENERY_2_ANIMATED = (1 << 4), // 0x10
|
||||
WALL_SCENERY_2_IS_OPAQUE = (1 << 3), // 0x8
|
||||
WALL_SCENERY_2_ANIMATED = (1 << 4), // 0x10
|
||||
};
|
||||
|
||||
struct rct_path_bit_scenery_entry {
|
||||
uint16_t flags; // 0x06
|
||||
uint8_t draw_type; // 0x08
|
||||
uint8_t tool_id; // 0x09
|
||||
int16_t price; // 0x0A
|
||||
uint8_t scenery_tab_id; // 0x0C
|
||||
struct rct_path_bit_scenery_entry
|
||||
{
|
||||
uint16_t flags; // 0x06
|
||||
uint8_t draw_type; // 0x08
|
||||
uint8_t tool_id; // 0x09
|
||||
int16_t price; // 0x0A
|
||||
uint8_t scenery_tab_id; // 0x0C
|
||||
};
|
||||
assert_struct_size(rct_path_bit_scenery_entry, 7);
|
||||
|
||||
struct rct_banner_scenery_entry {
|
||||
uint8_t scrolling_mode; // 0x06
|
||||
uint8_t flags; // 0x07
|
||||
int16_t price; // 0x08
|
||||
uint8_t scenery_tab_id; // 0x0A
|
||||
struct rct_banner_scenery_entry
|
||||
{
|
||||
uint8_t scrolling_mode; // 0x06
|
||||
uint8_t flags; // 0x07
|
||||
int16_t price; // 0x08
|
||||
uint8_t scenery_tab_id; // 0x0A
|
||||
};
|
||||
assert_struct_size(rct_banner_scenery_entry, 5);
|
||||
|
||||
struct rct_scenery_entry {
|
||||
rct_string_id name; // 0x00
|
||||
uint32_t image; // 0x02
|
||||
union {
|
||||
struct rct_scenery_entry
|
||||
{
|
||||
rct_string_id name; // 0x00
|
||||
uint32_t image; // 0x02
|
||||
union
|
||||
{
|
||||
rct_small_scenery_entry small_scenery;
|
||||
rct_large_scenery_entry large_scenery;
|
||||
rct_wall_scenery_entry wall;
|
||||
|
@ -171,39 +185,43 @@ struct rct_scenery_entry {
|
|||
assert_struct_size(rct_scenery_entry, 6 + 21);
|
||||
#endif
|
||||
|
||||
struct rct_scenery_group_entry {
|
||||
struct rct_scenery_group_entry
|
||||
{
|
||||
rct_string_id name; // 0x00
|
||||
uint32_t image; // 0x02
|
||||
uint16_t scenery_entries[0x80]; // 0x06
|
||||
uint8_t entry_count; // 0x106
|
||||
uint32_t image; // 0x02
|
||||
uint16_t scenery_entries[0x80]; // 0x06
|
||||
uint8_t entry_count; // 0x106
|
||||
uint8_t pad_107;
|
||||
uint8_t priority; // 0x108
|
||||
uint8_t priority; // 0x108
|
||||
uint8_t pad_109;
|
||||
uint32_t entertainer_costumes; // 0x10A
|
||||
uint32_t entertainer_costumes; // 0x10A
|
||||
};
|
||||
assert_struct_size(rct_scenery_group_entry, 14 + 2 * 0x80);
|
||||
#pragma pack(pop)
|
||||
|
||||
enum {
|
||||
PATH_BIT_FLAG_IS_BIN = 1 << 0,
|
||||
PATH_BIT_FLAG_IS_BENCH = 1 << 1,
|
||||
PATH_BIT_FLAG_BREAKABLE = 1 << 2,
|
||||
PATH_BIT_FLAG_LAMP = 1 << 3,
|
||||
PATH_BIT_FLAG_JUMPING_FOUNTAIN_WATER = 1 << 4,
|
||||
PATH_BIT_FLAG_JUMPING_FOUNTAIN_SNOW = 1 << 5,
|
||||
PATH_BIT_FLAG_DONT_ALLOW_ON_QUEUE = 1 << 6,
|
||||
PATH_BIT_FLAG_DONT_ALLOW_ON_SLOPE = 1 << 7,
|
||||
PATH_BIT_FLAG_IS_QUEUE_SCREEN = 1 << 8
|
||||
enum
|
||||
{
|
||||
PATH_BIT_FLAG_IS_BIN = 1 << 0,
|
||||
PATH_BIT_FLAG_IS_BENCH = 1 << 1,
|
||||
PATH_BIT_FLAG_BREAKABLE = 1 << 2,
|
||||
PATH_BIT_FLAG_LAMP = 1 << 3,
|
||||
PATH_BIT_FLAG_JUMPING_FOUNTAIN_WATER = 1 << 4,
|
||||
PATH_BIT_FLAG_JUMPING_FOUNTAIN_SNOW = 1 << 5,
|
||||
PATH_BIT_FLAG_DONT_ALLOW_ON_QUEUE = 1 << 6,
|
||||
PATH_BIT_FLAG_DONT_ALLOW_ON_SLOPE = 1 << 7,
|
||||
PATH_BIT_FLAG_IS_QUEUE_SCREEN = 1 << 8
|
||||
};
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
PATH_BIT_DRAW_TYPE_LIGHTS,
|
||||
PATH_BIT_DRAW_TYPE_BINS,
|
||||
PATH_BIT_DRAW_TYPE_BENCHES,
|
||||
PATH_BIT_DRAW_TYPE_JUMPING_FOUNTAINS
|
||||
};
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
SCENERY_TYPE_SMALL,
|
||||
SCENERY_TYPE_PATH_ITEM,
|
||||
SCENERY_TYPE_WALL,
|
||||
|
@ -211,7 +229,8 @@ enum {
|
|||
SCENERY_TYPE_BANNER
|
||||
};
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
SCENERY_ENTRY_FLAG_0 = (1 << 0),
|
||||
SCENERY_ENTRY_FLAG_1 = (1 << 1),
|
||||
SCENERY_ENTRY_FLAG_2 = (1 << 2),
|
||||
|
@ -219,7 +238,8 @@ enum {
|
|||
SCENERY_ENTRY_FLAG_4 = (1 << 4)
|
||||
};
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
SCENERY_GHOST_FLAG_0 = (1 << SCENERY_TYPE_SMALL),
|
||||
SCENERY_GHOST_FLAG_1 = (1 << SCENERY_TYPE_PATH_ITEM),
|
||||
SCENERY_GHOST_FLAG_2 = (1 << SCENERY_TYPE_WALL),
|
||||
|
@ -245,7 +265,7 @@ extern colour_t gWindowScenerySecondaryColour;
|
|||
extern colour_t gWindowSceneryTertiaryColour;
|
||||
extern bool gWindowSceneryEyedropperEnabled;
|
||||
|
||||
extern rct_tile_element *gSceneryTileElement;
|
||||
extern rct_tile_element* gSceneryTileElement;
|
||||
extern uint8_t gSceneryTileElementType;
|
||||
|
||||
extern money32 gSceneryPlaceCost;
|
||||
|
@ -276,18 +296,18 @@ extern money32 gClearSceneryCost;
|
|||
|
||||
void init_scenery();
|
||||
void scenery_update_tile(int32_t x, int32_t y);
|
||||
void scenery_update_age(int32_t x, int32_t y, rct_tile_element *tileElement);
|
||||
void scenery_update_age(int32_t x, int32_t y, rct_tile_element* tileElement);
|
||||
void scenery_set_default_placement_configuration();
|
||||
void scenery_remove_ghost_tool_placement();
|
||||
|
||||
rct_scenery_entry *get_small_scenery_entry(int32_t entryIndex);
|
||||
rct_scenery_entry *get_large_scenery_entry(int32_t entryIndex);
|
||||
rct_scenery_entry *get_wall_entry(int32_t entryIndex);
|
||||
rct_scenery_entry *get_banner_entry(int32_t entryIndex);
|
||||
rct_scenery_entry *get_footpath_item_entry(int32_t entryIndex);
|
||||
rct_scenery_group_entry *get_scenery_group_entry(int32_t entryIndex);
|
||||
rct_scenery_entry* get_small_scenery_entry(int32_t entryIndex);
|
||||
rct_scenery_entry* get_large_scenery_entry(int32_t entryIndex);
|
||||
rct_scenery_entry* get_wall_entry(int32_t entryIndex);
|
||||
rct_scenery_entry* get_banner_entry(int32_t entryIndex);
|
||||
rct_scenery_entry* get_footpath_item_entry(int32_t entryIndex);
|
||||
rct_scenery_group_entry* get_scenery_group_entry(int32_t entryIndex);
|
||||
|
||||
int32_t get_scenery_id_from_entry_index(uint8_t objectType, int32_t entryIndex);
|
||||
int32_t wall_entry_get_door_sound(const rct_scenery_entry * wallEntry);
|
||||
int32_t wall_entry_get_door_sound(const rct_scenery_entry* wallEntry);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -7,28 +7,30 @@
|
|||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "SmallScenery.h"
|
||||
|
||||
#include "../Cheats.h"
|
||||
#include "../OpenRCT2.h"
|
||||
#include "../management/Finance.h"
|
||||
#include "../network/network.h"
|
||||
#include "../OpenRCT2.h"
|
||||
#include "../ride/TrackDesign.h"
|
||||
#include "Footpath.h"
|
||||
#include "Map.h"
|
||||
#include "MapAnimation.h"
|
||||
#include "Park.h"
|
||||
#include "Scenery.h"
|
||||
#include "SmallScenery.h"
|
||||
#include "MapAnimation.h"
|
||||
#include "Surface.h"
|
||||
|
||||
static money32 SmallSceneryRemove(int16_t x, int16_t y, uint8_t baseHeight, uint8_t quadrant, uint8_t sceneryType, uint8_t flags)
|
||||
static money32
|
||||
SmallSceneryRemove(int16_t x, int16_t y, uint8_t baseHeight, uint8_t quadrant, uint8_t sceneryType, uint8_t flags)
|
||||
{
|
||||
if (!map_is_location_valid({x, y}))
|
||||
if (!map_is_location_valid({ x, y }))
|
||||
{
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
money32 cost;
|
||||
|
||||
rct_scenery_entry *entry = get_small_scenery_entry(sceneryType);
|
||||
rct_scenery_entry* entry = get_small_scenery_entry(sceneryType);
|
||||
if (entry == nullptr)
|
||||
{
|
||||
log_warning("Invalid game command for scenery removal, scenery_type = %u", sceneryType);
|
||||
|
@ -41,17 +43,13 @@ static money32 SmallSceneryRemove(int16_t x, int16_t y, uint8_t baseHeight, uint
|
|||
gCommandPosition.y = y + 16;
|
||||
gCommandPosition.z = baseHeight * 8;
|
||||
|
||||
if (!(flags & GAME_COMMAND_FLAG_GHOST) &&
|
||||
game_is_paused() &&
|
||||
!gCheatsBuildInPauseMode)
|
||||
if (!(flags & GAME_COMMAND_FLAG_GHOST) && game_is_paused() && !gCheatsBuildInPauseMode)
|
||||
{
|
||||
gGameCommandErrorText = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED;
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
if (!(gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) &&
|
||||
!(flags & GAME_COMMAND_FLAG_GHOST) &&
|
||||
!gCheatsSandboxMode)
|
||||
if (!(gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) && !(flags & GAME_COMMAND_FLAG_GHOST) && !gCheatsSandboxMode)
|
||||
{
|
||||
// Check if allowed to remove item
|
||||
if (gParkFlags & PARK_FLAGS_FORBID_TREE_REMOVAL)
|
||||
|
@ -72,7 +70,8 @@ static money32 SmallSceneryRemove(int16_t x, int16_t y, uint8_t baseHeight, uint
|
|||
|
||||
bool sceneryFound = false;
|
||||
rct_tile_element* tileElement = map_get_first_element_at(x / 32, y / 32);
|
||||
do {
|
||||
do
|
||||
{
|
||||
if (tileElement->GetType() != TILE_ELEMENT_TYPE_SMALL_SCENERY)
|
||||
continue;
|
||||
if ((tileElement->type >> 6) != quadrant)
|
||||
|
@ -81,8 +80,7 @@ static money32 SmallSceneryRemove(int16_t x, int16_t y, uint8_t baseHeight, uint
|
|||
continue;
|
||||
if (tileElement->properties.scenery.type != sceneryType)
|
||||
continue;
|
||||
if ((flags & GAME_COMMAND_FLAG_GHOST) &&
|
||||
!(tileElement->flags & TILE_ELEMENT_FLAG_GHOST))
|
||||
if ((flags & GAME_COMMAND_FLAG_GHOST) && !(tileElement->flags & TILE_ELEMENT_FLAG_GHOST))
|
||||
continue;
|
||||
|
||||
sceneryFound = true;
|
||||
|
@ -112,7 +110,15 @@ static money32 SmallSceneryRemove(int16_t x, int16_t y, uint8_t baseHeight, uint
|
|||
return (gParkFlags & PARK_FLAGS_NO_MONEY) ? 0 : cost;
|
||||
}
|
||||
|
||||
static money32 SmallScenerySetColour(int16_t x, int16_t y, uint8_t baseHeight, uint8_t quadrant, uint8_t sceneryType, uint8_t primaryColour, uint8_t secondaryColour, uint8_t flags)
|
||||
static money32 SmallScenerySetColour(
|
||||
int16_t x,
|
||||
int16_t y,
|
||||
uint8_t baseHeight,
|
||||
uint8_t quadrant,
|
||||
uint8_t sceneryType,
|
||||
uint8_t primaryColour,
|
||||
uint8_t secondaryColour,
|
||||
uint8_t flags)
|
||||
{
|
||||
gCommandExpenditureType = RCT_EXPENDITURE_TYPE_LANDSCAPING;
|
||||
int32_t z = baseHeight * 8;
|
||||
|
@ -128,7 +134,7 @@ static money32 SmallScenerySetColour(int16_t x, int16_t y, uint8_t baseHeight, u
|
|||
}
|
||||
}
|
||||
|
||||
rct_tile_element *tileElement = map_get_small_scenery_element_at(x, y, baseHeight, sceneryType, quadrant);
|
||||
rct_tile_element* tileElement = map_get_small_scenery_element_at(x, y, baseHeight, sceneryType, quadrant);
|
||||
|
||||
if (tileElement == nullptr)
|
||||
{
|
||||
|
@ -151,7 +157,8 @@ static money32 SmallScenerySetColour(int16_t x, int16_t y, uint8_t baseHeight, u
|
|||
return 0;
|
||||
}
|
||||
|
||||
static money32 SmallSceneryPlace(int16_t x,
|
||||
static money32 SmallSceneryPlace(
|
||||
int16_t x,
|
||||
int16_t y,
|
||||
int16_t targetHeight,
|
||||
uint8_t quadrant,
|
||||
|
@ -209,10 +216,11 @@ static money32 SmallSceneryPlace(int16_t x,
|
|||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
if (scenery_small_entry_has_flag(sceneryEntry, SMALL_SCENERY_FLAG_FULL_TILE) ||
|
||||
!scenery_small_entry_has_flag(sceneryEntry, SMALL_SCENERY_FLAG_DIAGONAL))
|
||||
if (scenery_small_entry_has_flag(sceneryEntry, SMALL_SCENERY_FLAG_FULL_TILE)
|
||||
|| !scenery_small_entry_has_flag(sceneryEntry, SMALL_SCENERY_FLAG_DIAGONAL))
|
||||
{
|
||||
if (scenery_small_entry_has_flag(sceneryEntry, SMALL_SCENERY_FLAG_DIAGONAL | SMALL_SCENERY_FLAG_HALF_SPACE | SMALL_SCENERY_FLAG_THREE_QUARTERS))
|
||||
if (scenery_small_entry_has_flag(
|
||||
sceneryEntry, SMALL_SCENERY_FLAG_DIAGONAL | SMALL_SCENERY_FLAG_HALF_SPACE | SMALL_SCENERY_FLAG_THREE_QUARTERS))
|
||||
{
|
||||
quadrant = 0;
|
||||
}
|
||||
|
@ -247,11 +255,8 @@ static money32 SmallSceneryPlace(int16_t x,
|
|||
targetHeight = baseHeight;
|
||||
}
|
||||
|
||||
if (!(gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) &&
|
||||
!gCheatsSandboxMode &&
|
||||
!map_is_location_owned(x, y, targetHeight))
|
||||
if (!(gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) && !gCheatsSandboxMode && !map_is_location_owned(x, y, targetHeight))
|
||||
{
|
||||
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
|
@ -264,7 +269,7 @@ static money32 SmallSceneryPlace(int16_t x,
|
|||
}
|
||||
}
|
||||
|
||||
rct_tile_element* surfaceElement = map_get_surface_element_at({x, y});
|
||||
rct_tile_element* surfaceElement = map_get_surface_element_at({ x, y });
|
||||
|
||||
if (surfaceElement != nullptr && !gCheatsDisableClearanceChecks && surface_get_water_height(surfaceElement) > 0)
|
||||
{
|
||||
|
@ -294,36 +299,27 @@ static money32 SmallSceneryPlace(int16_t x,
|
|||
}
|
||||
}
|
||||
|
||||
if (!gCheatsDisableClearanceChecks &&
|
||||
(scenery_small_entry_has_flag(sceneryEntry, SMALL_SCENERY_FLAG_REQUIRE_FLAT_SURFACE)) &&
|
||||
!supportsRequired &&
|
||||
!isOnWater &&
|
||||
surfaceElement != nullptr &&
|
||||
(surfaceElement->properties.surface.slope & TILE_ELEMENT_SURFACE_SLOPE_MASK))
|
||||
if (!gCheatsDisableClearanceChecks && (scenery_small_entry_has_flag(sceneryEntry, SMALL_SCENERY_FLAG_REQUIRE_FLAT_SURFACE))
|
||||
&& !supportsRequired && !isOnWater && surfaceElement != nullptr
|
||||
&& (surfaceElement->properties.surface.slope & TILE_ELEMENT_SURFACE_SLOPE_MASK))
|
||||
{
|
||||
|
||||
gGameCommandErrorText = STR_LEVEL_LAND_REQUIRED;
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
if (!gCheatsDisableSupportLimits &&
|
||||
!(scenery_small_entry_has_flag(sceneryEntry, SMALL_SCENERY_FLAG_STACKABLE)) &&
|
||||
supportsRequired)
|
||||
if (!gCheatsDisableSupportLimits && !(scenery_small_entry_has_flag(sceneryEntry, SMALL_SCENERY_FLAG_STACKABLE))
|
||||
&& supportsRequired)
|
||||
{
|
||||
|
||||
if (!isOnWater)
|
||||
{
|
||||
if (surfaceElement != nullptr)
|
||||
{
|
||||
if (surface_get_water_height(surfaceElement) ||
|
||||
(surfaceElement->base_height * 8) != targetHeight)
|
||||
if (surface_get_water_height(surfaceElement) || (surfaceElement->base_height * 8) != targetHeight)
|
||||
{
|
||||
|
||||
gGameCommandErrorText = STR_LEVEL_LAND_REQUIRED;
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -342,8 +338,8 @@ static money32 SmallSceneryPlace(int16_t x,
|
|||
}
|
||||
if (!(scenery_small_entry_has_flag(sceneryEntry, SMALL_SCENERY_FLAG_HALF_SPACE)))
|
||||
{
|
||||
if (scenery_small_entry_has_flag(sceneryEntry, SMALL_SCENERY_FLAG_DIAGONAL) &&
|
||||
scenery_small_entry_has_flag(sceneryEntry, SMALL_SCENERY_FLAG_FULL_TILE))
|
||||
if (scenery_small_entry_has_flag(sceneryEntry, SMALL_SCENERY_FLAG_DIAGONAL)
|
||||
&& scenery_small_entry_has_flag(sceneryEntry, SMALL_SCENERY_FLAG_FULL_TILE))
|
||||
{
|
||||
if (scenery_small_entry_has_flag(sceneryEntry, SMALL_SCENERY_FLAG_THREE_QUARTERS))
|
||||
{
|
||||
|
@ -364,17 +360,17 @@ static money32 SmallSceneryPlace(int16_t x,
|
|||
blSupports |= 0xF0;
|
||||
}
|
||||
|
||||
if (!gCheatsDisableClearanceChecks &&
|
||||
!map_can_construct_with_clear_at(
|
||||
x,
|
||||
y,
|
||||
zLow,
|
||||
zHigh,
|
||||
&map_place_scenery_clear_func,
|
||||
blSupports | collisionQuadrants,
|
||||
flags,
|
||||
&clearCost,
|
||||
CREATE_CROSSING_MODE_NONE))
|
||||
if (!gCheatsDisableClearanceChecks
|
||||
&& !map_can_construct_with_clear_at(
|
||||
x,
|
||||
y,
|
||||
zLow,
|
||||
zHigh,
|
||||
&map_place_scenery_clear_func,
|
||||
blSupports | collisionQuadrants,
|
||||
flags,
|
||||
&clearCost,
|
||||
CREATE_CROSSING_MODE_NONE))
|
||||
{
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
@ -438,22 +434,16 @@ static money32 SmallSceneryPlace(int16_t x,
|
|||
* rct2: 0x006E0E01
|
||||
*/
|
||||
void game_command_remove_scenery(
|
||||
int32_t * eax,
|
||||
int32_t * ebx,
|
||||
int32_t * ecx,
|
||||
int32_t * edx,
|
||||
[[maybe_unused]] int32_t * esi,
|
||||
[[maybe_unused]] int32_t * edi,
|
||||
[[maybe_unused]] int32_t * ebp)
|
||||
int32_t* eax,
|
||||
int32_t* ebx,
|
||||
int32_t* ecx,
|
||||
int32_t* edx,
|
||||
[[maybe_unused]] int32_t* esi,
|
||||
[[maybe_unused]] int32_t* edi,
|
||||
[[maybe_unused]] int32_t* ebp)
|
||||
{
|
||||
*ebx = SmallSceneryRemove(
|
||||
*eax & 0xFFFF,
|
||||
*ecx & 0xFFFF,
|
||||
*edx & 0xFF,
|
||||
((*ebx >> 8) & 0xFF) >> 6,
|
||||
(*edx >> 8) & 0xFF,
|
||||
*ebx & 0xFF
|
||||
);
|
||||
*eax & 0xFFFF, *ecx & 0xFFFF, *edx & 0xFF, ((*ebx >> 8) & 0xFF) >> 6, (*edx >> 8) & 0xFF, *ebx & 0xFF);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -461,13 +451,13 @@ void game_command_remove_scenery(
|
|||
* rct2: 0x006E0F26
|
||||
*/
|
||||
void game_command_set_scenery_colour(
|
||||
int32_t * eax,
|
||||
int32_t * ebx,
|
||||
int32_t * ecx,
|
||||
int32_t * edx,
|
||||
[[maybe_unused]] int32_t * esi,
|
||||
[[maybe_unused]] int32_t * edi,
|
||||
int32_t * ebp)
|
||||
int32_t* eax,
|
||||
int32_t* ebx,
|
||||
int32_t* ecx,
|
||||
int32_t* edx,
|
||||
[[maybe_unused]] int32_t* esi,
|
||||
[[maybe_unused]] int32_t* edi,
|
||||
int32_t* ebp)
|
||||
{
|
||||
*ebx = SmallScenerySetColour(
|
||||
*eax & 0xFFFF,
|
||||
|
@ -477,8 +467,7 @@ void game_command_set_scenery_colour(
|
|||
(*edx >> 8) & 0xFF,
|
||||
*ebp & 0xFF,
|
||||
(*ebp >> 8) & 0xFF,
|
||||
*ebx & 0xFF
|
||||
);
|
||||
*ebx & 0xFF);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -557,7 +546,7 @@ int32_t map_place_non_scenery_clear_func(rct_tile_element** tile_element, int32_
|
|||
* rct2: 0x006E08F4
|
||||
*/
|
||||
void game_command_place_scenery(
|
||||
int32_t * eax, int32_t * ebx, int32_t * ecx, int32_t * edx, [[maybe_unused]] int32_t * esi, int32_t * edi, int32_t * ebp)
|
||||
int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, [[maybe_unused]] int32_t* esi, int32_t* edi, int32_t* ebp)
|
||||
{
|
||||
*ebx = SmallSceneryPlace(
|
||||
*eax & 0xFFFF,
|
||||
|
@ -568,46 +557,44 @@ void game_command_place_scenery(
|
|||
(*ebx >> 8) & 0xFF,
|
||||
(*edx >> 8) & 0xFF,
|
||||
(*edi >> 16) & 0xFF,
|
||||
*ebx & 0xFF
|
||||
);
|
||||
*ebx & 0xFF);
|
||||
}
|
||||
|
||||
int32_t scenery_small_get_primary_colour(const rct_tile_element * tileElement)
|
||||
int32_t scenery_small_get_primary_colour(const rct_tile_element* tileElement)
|
||||
{
|
||||
return tileElement->properties.scenery.colour_1 & TILE_ELEMENT_COLOUR_MASK;
|
||||
}
|
||||
|
||||
int32_t scenery_small_get_secondary_colour(const rct_tile_element * tileElement)
|
||||
int32_t scenery_small_get_secondary_colour(const rct_tile_element* tileElement)
|
||||
{
|
||||
return tileElement->properties.scenery.colour_2 & TILE_ELEMENT_COLOUR_MASK;
|
||||
}
|
||||
|
||||
void scenery_small_set_primary_colour(rct_tile_element * tileElement, uint32_t colour)
|
||||
void scenery_small_set_primary_colour(rct_tile_element* tileElement, uint32_t colour)
|
||||
{
|
||||
assert(colour <= 31);
|
||||
tileElement->properties.scenery.colour_1 &= ~TILE_ELEMENT_COLOUR_MASK;
|
||||
tileElement->properties.scenery.colour_1 |= colour;
|
||||
}
|
||||
|
||||
void scenery_small_set_secondary_colour(rct_tile_element * tileElement, uint32_t colour)
|
||||
void scenery_small_set_secondary_colour(rct_tile_element* tileElement, uint32_t colour)
|
||||
{
|
||||
assert(colour <= 31);
|
||||
tileElement->properties.scenery.colour_2 &= ~TILE_ELEMENT_COLOUR_MASK;
|
||||
tileElement->properties.scenery.colour_2 |= colour;
|
||||
}
|
||||
|
||||
bool scenery_small_get_supports_needed(const rct_tile_element * tileElement)
|
||||
bool scenery_small_get_supports_needed(const rct_tile_element* tileElement)
|
||||
{
|
||||
return (bool)(tileElement->properties.scenery.colour_1 & MAP_ELEM_SMALL_SCENERY_COLOUR_FLAG_NEEDS_SUPPORTS);
|
||||
}
|
||||
|
||||
void scenery_small_set_supports_needed(rct_tile_element * tileElement)
|
||||
void scenery_small_set_supports_needed(rct_tile_element* tileElement)
|
||||
{
|
||||
tileElement->properties.scenery.colour_1 |= MAP_ELEM_SMALL_SCENERY_COLOUR_FLAG_NEEDS_SUPPORTS;
|
||||
}
|
||||
|
||||
bool scenery_small_entry_has_flag(const rct_scenery_entry * sceneryEntry, uint32_t flags)
|
||||
bool scenery_small_entry_has_flag(const rct_scenery_entry* sceneryEntry, uint32_t flags)
|
||||
{
|
||||
return (bool)(sceneryEntry->small_scenery.flags & flags);
|
||||
}
|
||||
|
||||
|
|
|
@ -15,34 +15,35 @@
|
|||
|
||||
enum SMALL_SCENERY_FLAGS
|
||||
{
|
||||
SMALL_SCENERY_FLAG_FULL_TILE = (1 << 0), // 0x1
|
||||
SMALL_SCENERY_FLAG_VOFFSET_CENTRE = (1 << 1), // 0x2
|
||||
SMALL_SCENERY_FLAG_REQUIRE_FLAT_SURFACE = (1 << 2), // 0x4
|
||||
SMALL_SCENERY_FLAG_ROTATABLE = (1 << 3), // 0x8; when set, user can set rotation, otherwise rotation is automatic
|
||||
SMALL_SCENERY_FLAG_ANIMATED = (1 << 4), // 0x10
|
||||
SMALL_SCENERY_FLAG_CAN_WITHER = (1 << 5), // 0x20
|
||||
SMALL_SCENERY_FLAG_CAN_BE_WATERED = (1 << 6), // 0x40
|
||||
SMALL_SCENERY_FLAG_ANIMATED_FG = (1 << 7), // 0x80
|
||||
SMALL_SCENERY_FLAG_DIAGONAL = (1 << 8), // 0x100
|
||||
SMALL_SCENERY_FLAG_HAS_GLASS = (1 << 9), // 0x200
|
||||
SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR = (1 << 10), // 0x400
|
||||
SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_1 = (1 << 11), // 0x800
|
||||
SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_4 = (1 << 12), // 0x1000
|
||||
SMALL_SCENERY_FLAG_IS_CLOCK = (1 << 13), // 0x2000
|
||||
SMALL_SCENERY_FLAG_SWAMP_GOO = (1 << 14), // 0x4000
|
||||
SMALL_SCENERY_FLAG_HAS_FRAME_OFFSETS = (1 << 15), // 0x8000
|
||||
SMALL_SCENERY_FLAG17 = (1 << 16), // 0x10000
|
||||
SMALL_SCENERY_FLAG_STACKABLE = (1 << 17), // 0x20000; means scenery item can be placed in the air and over water
|
||||
SMALL_SCENERY_FLAG_NO_WALLS = (1 << 18), // 0x40000
|
||||
SMALL_SCENERY_FLAG_FULL_TILE = (1 << 0), // 0x1
|
||||
SMALL_SCENERY_FLAG_VOFFSET_CENTRE = (1 << 1), // 0x2
|
||||
SMALL_SCENERY_FLAG_REQUIRE_FLAT_SURFACE = (1 << 2), // 0x4
|
||||
SMALL_SCENERY_FLAG_ROTATABLE = (1 << 3), // 0x8; when set, user can set rotation, otherwise rotation is automatic
|
||||
SMALL_SCENERY_FLAG_ANIMATED = (1 << 4), // 0x10
|
||||
SMALL_SCENERY_FLAG_CAN_WITHER = (1 << 5), // 0x20
|
||||
SMALL_SCENERY_FLAG_CAN_BE_WATERED = (1 << 6), // 0x40
|
||||
SMALL_SCENERY_FLAG_ANIMATED_FG = (1 << 7), // 0x80
|
||||
SMALL_SCENERY_FLAG_DIAGONAL = (1 << 8), // 0x100
|
||||
SMALL_SCENERY_FLAG_HAS_GLASS = (1 << 9), // 0x200
|
||||
SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR = (1 << 10), // 0x400
|
||||
SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_1 = (1 << 11), // 0x800
|
||||
SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_4 = (1 << 12), // 0x1000
|
||||
SMALL_SCENERY_FLAG_IS_CLOCK = (1 << 13), // 0x2000
|
||||
SMALL_SCENERY_FLAG_SWAMP_GOO = (1 << 14), // 0x4000
|
||||
SMALL_SCENERY_FLAG_HAS_FRAME_OFFSETS = (1 << 15), // 0x8000
|
||||
SMALL_SCENERY_FLAG17 = (1 << 16), // 0x10000
|
||||
SMALL_SCENERY_FLAG_STACKABLE = (1 << 17), // 0x20000; means scenery item can be placed in the air and over water
|
||||
SMALL_SCENERY_FLAG_NO_WALLS = (1 << 18), // 0x40000
|
||||
SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR = (1 << 19), // 0x80000
|
||||
SMALL_SCENERY_FLAG_NO_SUPPORTS = (1 << 20), // 0x100000
|
||||
SMALL_SCENERY_FLAG_VISIBLE_WHEN_ZOOMED = (1 << 21), // 0x200000
|
||||
SMALL_SCENERY_FLAG_COG = (1 << 22), // 0x400000
|
||||
SMALL_SCENERY_FLAG_BUILD_DIRECTLY_ONTOP = (1 << 23), // 0x800000; means supports can be built on this object. Used for base blocks.
|
||||
SMALL_SCENERY_FLAG_HALF_SPACE = (1 << 24), // 0x1000000
|
||||
SMALL_SCENERY_FLAG_THREE_QUARTERS = (1 << 25), // 0x2000000
|
||||
SMALL_SCENERY_FLAG_PAINT_SUPPORTS = (1 << 26), // 0x4000000; used for scenery items which are support structures
|
||||
SMALL_SCENERY_FLAG27 = (1 << 27), // 0x8000000
|
||||
SMALL_SCENERY_FLAG_NO_SUPPORTS = (1 << 20), // 0x100000
|
||||
SMALL_SCENERY_FLAG_VISIBLE_WHEN_ZOOMED = (1 << 21), // 0x200000
|
||||
SMALL_SCENERY_FLAG_COG = (1 << 22), // 0x400000
|
||||
SMALL_SCENERY_FLAG_BUILD_DIRECTLY_ONTOP
|
||||
= (1 << 23), // 0x800000; means supports can be built on this object. Used for base blocks.
|
||||
SMALL_SCENERY_FLAG_HALF_SPACE = (1 << 24), // 0x1000000
|
||||
SMALL_SCENERY_FLAG_THREE_QUARTERS = (1 << 25), // 0x2000000
|
||||
SMALL_SCENERY_FLAG_PAINT_SUPPORTS = (1 << 26), // 0x4000000; used for scenery items which are support structures
|
||||
SMALL_SCENERY_FLAG27 = (1 << 27), // 0x8000000
|
||||
};
|
||||
|
||||
enum
|
||||
|
@ -50,11 +51,11 @@ enum
|
|||
MAP_ELEM_SMALL_SCENERY_COLOUR_FLAG_NEEDS_SUPPORTS = (1 << 5),
|
||||
};
|
||||
|
||||
int32_t scenery_small_get_primary_colour(const rct_tile_element * tileElement);
|
||||
int32_t scenery_small_get_secondary_colour(const rct_tile_element * tileElement);
|
||||
void scenery_small_set_primary_colour(rct_tile_element * tileElement, uint32_t colour);
|
||||
void scenery_small_set_secondary_colour(rct_tile_element * tileElement, uint32_t colour);
|
||||
bool scenery_small_get_supports_needed(const rct_tile_element * tileElement);
|
||||
void scenery_small_set_supports_needed(rct_tile_element * tileElement);
|
||||
int32_t scenery_small_get_primary_colour(const rct_tile_element* tileElement);
|
||||
int32_t scenery_small_get_secondary_colour(const rct_tile_element* tileElement);
|
||||
void scenery_small_set_primary_colour(rct_tile_element* tileElement, uint32_t colour);
|
||||
void scenery_small_set_secondary_colour(rct_tile_element* tileElement, uint32_t colour);
|
||||
bool scenery_small_get_supports_needed(const rct_tile_element* tileElement);
|
||||
void scenery_small_set_supports_needed(rct_tile_element* tileElement);
|
||||
|
||||
bool scenery_small_entry_has_flag(const rct_scenery_entry * sceneryEntry, uint32_t flags);
|
||||
bool scenery_small_entry_has_flag(const rct_scenery_entry* sceneryEntry, uint32_t flags);
|
||||
|
|
|
@ -7,22 +7,24 @@
|
|||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||
*****************************************************************************/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include "../audio/audio.h"
|
||||
#include "Sprite.h"
|
||||
|
||||
#include "../Cheats.h"
|
||||
#include "../Game.h"
|
||||
#include "../OpenRCT2.h"
|
||||
#include "../audio/audio.h"
|
||||
#include "../core/Crypt.h"
|
||||
#include "../core/Guard.hpp"
|
||||
#include "../core/Math.hpp"
|
||||
#include "../core/Util.hpp"
|
||||
#include "../Game.h"
|
||||
#include "../interface/Viewport.h"
|
||||
#include "../localisation/Date.h"
|
||||
#include "../localisation/Localisation.h"
|
||||
#include "../OpenRCT2.h"
|
||||
#include "../scenario/Scenario.h"
|
||||
#include "Fountain.h"
|
||||
#include "Sprite.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
uint16_t gSpriteListHead[6];
|
||||
uint16_t gSpriteListCount[6];
|
||||
|
@ -34,29 +36,27 @@ static bool _spriteFlashingList[MAX_SPRITES];
|
|||
|
||||
uint16_t gSpriteSpatialIndex[0x10001];
|
||||
|
||||
const rct_string_id litterNames[12] = {
|
||||
STR_LITTER_VOMIT,
|
||||
STR_LITTER_VOMIT,
|
||||
STR_SHOP_ITEM_SINGULAR_EMPTY_CAN,
|
||||
STR_SHOP_ITEM_SINGULAR_RUBBISH,
|
||||
STR_SHOP_ITEM_SINGULAR_EMPTY_BURGER_BOX,
|
||||
STR_SHOP_ITEM_SINGULAR_EMPTY_CUP,
|
||||
STR_SHOP_ITEM_SINGULAR_EMPTY_BOX,
|
||||
STR_SHOP_ITEM_SINGULAR_EMPTY_BOTTLE,
|
||||
STR_SHOP_ITEM_SINGULAR_EMPTY_BOWL_RED,
|
||||
STR_SHOP_ITEM_SINGULAR_EMPTY_DRINK_CARTON,
|
||||
STR_SHOP_ITEM_SINGULAR_EMPTY_JUICE_CUP,
|
||||
STR_SHOP_ITEM_SINGULAR_EMPTY_BOWL_BLUE
|
||||
};
|
||||
const rct_string_id litterNames[12] = { STR_LITTER_VOMIT,
|
||||
STR_LITTER_VOMIT,
|
||||
STR_SHOP_ITEM_SINGULAR_EMPTY_CAN,
|
||||
STR_SHOP_ITEM_SINGULAR_RUBBISH,
|
||||
STR_SHOP_ITEM_SINGULAR_EMPTY_BURGER_BOX,
|
||||
STR_SHOP_ITEM_SINGULAR_EMPTY_CUP,
|
||||
STR_SHOP_ITEM_SINGULAR_EMPTY_BOX,
|
||||
STR_SHOP_ITEM_SINGULAR_EMPTY_BOTTLE,
|
||||
STR_SHOP_ITEM_SINGULAR_EMPTY_BOWL_RED,
|
||||
STR_SHOP_ITEM_SINGULAR_EMPTY_DRINK_CARTON,
|
||||
STR_SHOP_ITEM_SINGULAR_EMPTY_JUICE_CUP,
|
||||
STR_SHOP_ITEM_SINGULAR_EMPTY_BOWL_BLUE };
|
||||
|
||||
static LocationXYZ16 _spritelocations1[MAX_SPRITES];
|
||||
static LocationXYZ16 _spritelocations2[MAX_SPRITES];
|
||||
|
||||
static size_t GetSpatialIndexOffset(int32_t x, int32_t y);
|
||||
|
||||
rct_sprite *try_get_sprite(size_t spriteIndex)
|
||||
rct_sprite* try_get_sprite(size_t spriteIndex)
|
||||
{
|
||||
rct_sprite * sprite = nullptr;
|
||||
rct_sprite* sprite = nullptr;
|
||||
if (spriteIndex < MAX_SPRITES)
|
||||
{
|
||||
sprite = &_spriteList[spriteIndex];
|
||||
|
@ -64,7 +64,7 @@ rct_sprite *try_get_sprite(size_t spriteIndex)
|
|||
return sprite;
|
||||
}
|
||||
|
||||
rct_sprite *get_sprite(size_t sprite_idx)
|
||||
rct_sprite* get_sprite(size_t sprite_idx)
|
||||
{
|
||||
openrct2_assert(sprite_idx < MAX_SPRITES, "Tried getting sprite %u", sprite_idx);
|
||||
return &_spriteList[sprite_idx];
|
||||
|
@ -76,20 +76,22 @@ uint16_t sprite_get_first_in_quadrant(int32_t x, int32_t y)
|
|||
return gSpriteSpatialIndex[offset];
|
||||
}
|
||||
|
||||
static void invalidate_sprite_max_zoom(rct_sprite *sprite, int32_t maxZoom)
|
||||
static void invalidate_sprite_max_zoom(rct_sprite* sprite, int32_t maxZoom)
|
||||
{
|
||||
if (sprite->unknown.sprite_left == LOCATION_NULL) return;
|
||||
if (sprite->unknown.sprite_left == LOCATION_NULL)
|
||||
return;
|
||||
|
||||
for (int32_t i = 0; i < MAX_VIEWPORT_COUNT; i++) {
|
||||
rct_viewport *viewport = &g_viewport_list[i];
|
||||
if (viewport->width != 0 && viewport->zoom <= maxZoom) {
|
||||
for (int32_t i = 0; i < MAX_VIEWPORT_COUNT; i++)
|
||||
{
|
||||
rct_viewport* viewport = &g_viewport_list[i];
|
||||
if (viewport->width != 0 && viewport->zoom <= maxZoom)
|
||||
{
|
||||
viewport_invalidate(
|
||||
viewport,
|
||||
sprite->unknown.sprite_left,
|
||||
sprite->unknown.sprite_top,
|
||||
sprite->unknown.sprite_right,
|
||||
sprite->unknown.sprite_bottom
|
||||
);
|
||||
sprite->unknown.sprite_bottom);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -107,7 +109,7 @@ void invalidate_sprite_0(rct_sprite* sprite)
|
|||
* Invalidate sprite if at closest zoom or next zoom up from closest.
|
||||
* rct2: 0x006EC53F
|
||||
*/
|
||||
void invalidate_sprite_1(rct_sprite *sprite)
|
||||
void invalidate_sprite_1(rct_sprite* sprite)
|
||||
{
|
||||
invalidate_sprite_max_zoom(sprite, 1);
|
||||
}
|
||||
|
@ -118,7 +120,7 @@ void invalidate_sprite_1(rct_sprite *sprite)
|
|||
*
|
||||
* @param sprite (esi)
|
||||
*/
|
||||
void invalidate_sprite_2(rct_sprite *sprite)
|
||||
void invalidate_sprite_2(rct_sprite* sprite)
|
||||
{
|
||||
invalidate_sprite_max_zoom(sprite, 2);
|
||||
}
|
||||
|
@ -132,7 +134,8 @@ void reset_sprite_list()
|
|||
gSavedAge = 0;
|
||||
memset(_spriteList, 0, sizeof(rct_sprite) * MAX_SPRITES);
|
||||
|
||||
for (int32_t i = 0; i < NUM_SPRITE_LISTS; i++) {
|
||||
for (int32_t i = 0; i < NUM_SPRITE_LISTS; i++)
|
||||
{
|
||||
gSpriteListHead[i] = SPRITE_INDEX_NULL;
|
||||
gSpriteListCount[i] = 0;
|
||||
_spriteFlashingList[i] = false;
|
||||
|
@ -140,18 +143,21 @@ void reset_sprite_list()
|
|||
|
||||
rct_sprite* previous_spr = (rct_sprite*)SPRITE_INDEX_NULL;
|
||||
|
||||
for (int32_t i = 0; i < MAX_SPRITES; ++i){
|
||||
rct_sprite *spr = get_sprite(i);
|
||||
for (int32_t i = 0; i < MAX_SPRITES; ++i)
|
||||
{
|
||||
rct_sprite* spr = get_sprite(i);
|
||||
spr->unknown.sprite_identifier = SPRITE_IDENTIFIER_NULL;
|
||||
spr->unknown.sprite_index = i;
|
||||
spr->unknown.next = SPRITE_INDEX_NULL;
|
||||
spr->unknown.linked_list_type_offset = 0;
|
||||
|
||||
if (previous_spr != (rct_sprite*)SPRITE_INDEX_NULL){
|
||||
if (previous_spr != (rct_sprite*)SPRITE_INDEX_NULL)
|
||||
{
|
||||
spr->unknown.previous = previous_spr->unknown.sprite_index;
|
||||
previous_spr->unknown.next = i;
|
||||
}
|
||||
else{
|
||||
else
|
||||
{
|
||||
spr->unknown.previous = SPRITE_INDEX_NULL;
|
||||
gSpriteListHead[SPRITE_LIST_NULL] = i;
|
||||
}
|
||||
|
@ -173,9 +179,11 @@ void reset_sprite_list()
|
|||
void reset_sprite_spatial_index()
|
||||
{
|
||||
std::fill_n(gSpriteSpatialIndex, Util::CountOf(gSpriteSpatialIndex), SPRITE_INDEX_NULL);
|
||||
for (size_t i = 0; i < MAX_SPRITES; i++) {
|
||||
rct_sprite *spr = get_sprite(i);
|
||||
if (spr->unknown.sprite_identifier != SPRITE_IDENTIFIER_NULL) {
|
||||
for (size_t i = 0; i < MAX_SPRITES; i++)
|
||||
{
|
||||
rct_sprite* spr = get_sprite(i);
|
||||
if (spr->unknown.sprite_identifier != SPRITE_IDENTIFIER_NULL)
|
||||
{
|
||||
size_t index = GetSpatialIndexOffset(spr->unknown.x, spr->unknown.y);
|
||||
uint16_t nextSpriteId = gSpriteSpatialIndex[index];
|
||||
gSpriteSpatialIndex[index] = spr->unknown.sprite_index;
|
||||
|
@ -187,7 +195,8 @@ void reset_sprite_spatial_index()
|
|||
static size_t GetSpatialIndexOffset(int32_t x, int32_t y)
|
||||
{
|
||||
size_t index = SPATIAL_INDEX_LOCATION_NULL;
|
||||
if (x != LOCATION_NULL) {
|
||||
if (x != LOCATION_NULL)
|
||||
{
|
||||
x = Math::Clamp(0, x, 0xFFFF);
|
||||
y = Math::Clamp(0, y, 0xFFFF);
|
||||
|
||||
|
@ -202,7 +211,7 @@ static size_t GetSpatialIndexOffset(int32_t x, int32_t y)
|
|||
|
||||
#ifndef DISABLE_NETWORK
|
||||
|
||||
const char * sprite_checksum()
|
||||
const char* sprite_checksum()
|
||||
{
|
||||
using namespace Crypt;
|
||||
|
||||
|
@ -222,7 +231,8 @@ const char * sprite_checksum()
|
|||
for (size_t i = 0; i < MAX_SPRITES; i++)
|
||||
{
|
||||
auto sprite = get_sprite(i);
|
||||
if (sprite->unknown.sprite_identifier != SPRITE_IDENTIFIER_NULL && sprite->unknown.sprite_identifier != SPRITE_IDENTIFIER_MISC)
|
||||
if (sprite->unknown.sprite_identifier != SPRITE_IDENTIFIER_NULL
|
||||
&& sprite->unknown.sprite_identifier != SPRITE_IDENTIFIER_MISC)
|
||||
{
|
||||
auto copy = *sprite;
|
||||
copy.unknown.sprite_left = copy.unknown.sprite_right = copy.unknown.sprite_top = copy.unknown.sprite_bottom = 0;
|
||||
|
@ -230,7 +240,8 @@ const char * sprite_checksum()
|
|||
if (copy.unknown.sprite_identifier == SPRITE_IDENTIFIER_PEEP)
|
||||
{
|
||||
// We set this to 0 because as soon the client selects a guest the window will remove the
|
||||
// invalidation flags causing the sprite checksum to be different than on server, the flag does not affect game state.
|
||||
// invalidation flags causing the sprite checksum to be different than on server, the flag does not affect
|
||||
// game state.
|
||||
copy.peep.window_invalidate_flags = 0;
|
||||
}
|
||||
|
||||
|
@ -258,14 +269,14 @@ const char * sprite_checksum()
|
|||
}
|
||||
#else
|
||||
|
||||
const char * sprite_checksum()
|
||||
const char* sprite_checksum()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#endif // DISABLE_NETWORK
|
||||
|
||||
static void sprite_reset(rct_unk_sprite *sprite)
|
||||
static void sprite_reset(rct_unk_sprite* sprite)
|
||||
{
|
||||
// Need to retain how the sprite is linked in lists
|
||||
uint8_t llto = sprite->linked_list_type_offset;
|
||||
|
@ -286,16 +297,17 @@ static void sprite_reset(rct_unk_sprite *sprite)
|
|||
}
|
||||
|
||||
/**
|
||||
* Clears all the unused sprite memory to zero. Probably so that it can be compressed better when saving.
|
||||
* rct2: 0x0069EBA4
|
||||
*/
|
||||
* Clears all the unused sprite memory to zero. Probably so that it can be compressed better when saving.
|
||||
* rct2: 0x0069EBA4
|
||||
*/
|
||||
void sprite_clear_all_unused()
|
||||
{
|
||||
rct_unk_sprite *sprite;
|
||||
rct_unk_sprite* sprite;
|
||||
uint16_t spriteIndex, nextSpriteIndex;
|
||||
|
||||
spriteIndex = gSpriteListHead[SPRITE_LIST_NULL];
|
||||
while (spriteIndex != SPRITE_INDEX_NULL) {
|
||||
while (spriteIndex != SPRITE_INDEX_NULL)
|
||||
{
|
||||
sprite = &get_sprite(spriteIndex)->unknown;
|
||||
nextSpriteIndex = sprite->next;
|
||||
sprite_reset(sprite);
|
||||
|
@ -308,33 +320,40 @@ void sprite_clear_all_unused()
|
|||
// sprite->next_in_quadrant will only end up as zero owing to corruption
|
||||
// most likely due to previous builds not preserving it when resetting sprites
|
||||
// We reset it to SPRITE_INDEX_NULL to prevent cycles in the sprite lists
|
||||
if (sprite->next_in_quadrant == 0) { sprite->next_in_quadrant = SPRITE_INDEX_NULL; }
|
||||
if (sprite->next_in_quadrant == 0)
|
||||
{
|
||||
sprite->next_in_quadrant = SPRITE_INDEX_NULL;
|
||||
}
|
||||
_spriteFlashingList[spriteIndex] = false;
|
||||
spriteIndex = nextSpriteIndex;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* rct2: 0x0069EC6B
|
||||
* bl: if bl & 2 > 0, the sprite ends up in the MISC linked list.
|
||||
*/
|
||||
rct_sprite *create_sprite(uint8_t bl)
|
||||
* rct2: 0x0069EC6B
|
||||
* bl: if bl & 2 > 0, the sprite ends up in the MISC linked list.
|
||||
*/
|
||||
rct_sprite* create_sprite(uint8_t bl)
|
||||
{
|
||||
size_t linkedListTypeOffset = SPRITE_LIST_UNKNOWN * 2;
|
||||
if ((bl & 2) != 0) {
|
||||
if ((bl & 2) != 0)
|
||||
{
|
||||
// 69EC96;
|
||||
uint16_t cx = 0x12C - gSpriteListCount[SPRITE_LIST_MISC];
|
||||
if (cx >= gSpriteListCount[SPRITE_LIST_NULL]) {
|
||||
if (cx >= gSpriteListCount[SPRITE_LIST_NULL])
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
linkedListTypeOffset = SPRITE_LIST_MISC * 2;
|
||||
} else if (gSpriteListCount[SPRITE_LIST_NULL] == 0) {
|
||||
}
|
||||
else if (gSpriteListCount[SPRITE_LIST_NULL] == 0)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
rct_unk_sprite *sprite = &(get_sprite(gSpriteListHead[SPRITE_LIST_NULL]))->unknown;
|
||||
rct_unk_sprite* sprite = &(get_sprite(gSpriteListHead[SPRITE_LIST_NULL]))->unknown;
|
||||
|
||||
move_sprite_to_list((rct_sprite *)sprite, (uint8_t)linkedListTypeOffset);
|
||||
move_sprite_to_list((rct_sprite*)sprite, (uint8_t)linkedListTypeOffset);
|
||||
|
||||
// Need to reset all sprite data, as the uninitialised values
|
||||
// may contain garbage and cause a desync later on.
|
||||
|
@ -363,36 +382,41 @@ rct_sprite *create_sprite(uint8_t bl)
|
|||
* of the desired linked list in a uint16_t array. Known valid values are
|
||||
* 2, 4, 6, 8 or 10 (SPRITE_LIST_... * 2)
|
||||
*/
|
||||
void move_sprite_to_list(rct_sprite *sprite, uint8_t newListOffset)
|
||||
void move_sprite_to_list(rct_sprite* sprite, uint8_t newListOffset)
|
||||
{
|
||||
rct_unk_sprite *unkSprite = &sprite->unknown;
|
||||
rct_unk_sprite* unkSprite = &sprite->unknown;
|
||||
uint8_t oldListOffset = unkSprite->linked_list_type_offset;
|
||||
int32_t oldList = oldListOffset >> 1;
|
||||
int32_t newList = newListOffset >> 1;
|
||||
|
||||
// No need to move if the sprite is already in the desired list
|
||||
if (oldListOffset == newListOffset) {
|
||||
if (oldListOffset == newListOffset)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// If the sprite is currently the head of the list, the
|
||||
// sprite following this one becomes the new head of the list.
|
||||
if (unkSprite->previous == SPRITE_INDEX_NULL) {
|
||||
if (unkSprite->previous == SPRITE_INDEX_NULL)
|
||||
{
|
||||
gSpriteListHead[oldList] = unkSprite->next;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// Hook up sprite->previous->next to sprite->next, removing the sprite from its old list
|
||||
get_sprite(unkSprite->previous)->unknown.next = unkSprite->next;
|
||||
}
|
||||
|
||||
// Similarly, hook up sprite->next->previous to sprite->previous
|
||||
if (unkSprite->next != SPRITE_INDEX_NULL) {
|
||||
if (unkSprite->next != SPRITE_INDEX_NULL)
|
||||
{
|
||||
get_sprite(unkSprite->next)->unknown.previous = unkSprite->previous;
|
||||
}
|
||||
|
||||
unkSprite->previous = SPRITE_INDEX_NULL; // We become the new head of the target list, so there's no previous sprite
|
||||
unkSprite->linked_list_type_offset = newListOffset;
|
||||
|
||||
unkSprite->next = gSpriteListHead[newList]; // This sprite's next sprite is the old head, since we're the new head
|
||||
unkSprite->next = gSpriteListHead[newList]; // This sprite's next sprite is the old head, since we're the new head
|
||||
gSpriteListHead[newList] = unkSprite->sprite_index; // Store this sprite's index as head of its new list
|
||||
|
||||
if (unkSprite->next != SPRITE_INDEX_NULL)
|
||||
|
@ -411,23 +435,20 @@ void move_sprite_to_list(rct_sprite *sprite, uint8_t newListOffset)
|
|||
*
|
||||
* rct2: 0x00673200
|
||||
*/
|
||||
static void sprite_steam_particle_update(rct_steam_particle *steam)
|
||||
static void sprite_steam_particle_update(rct_steam_particle* steam)
|
||||
{
|
||||
invalidate_sprite_2((rct_sprite*)steam);
|
||||
|
||||
// Move up 1 z every 3 ticks (Starts after 4 ticks)
|
||||
steam->time_to_move++;
|
||||
if (steam->time_to_move >= 4) {
|
||||
if (steam->time_to_move >= 4)
|
||||
{
|
||||
steam->time_to_move = 1;
|
||||
sprite_move(
|
||||
steam->x,
|
||||
steam->y,
|
||||
steam->z + 1,
|
||||
(rct_sprite*)steam
|
||||
);
|
||||
sprite_move(steam->x, steam->y, steam->z + 1, (rct_sprite*)steam);
|
||||
}
|
||||
steam->frame += 64;
|
||||
if (steam->frame >= (56 * 64)) {
|
||||
if (steam->frame >= (56 * 64))
|
||||
{
|
||||
sprite_remove((rct_sprite*)steam);
|
||||
}
|
||||
}
|
||||
|
@ -438,8 +459,9 @@ static void sprite_steam_particle_update(rct_steam_particle *steam)
|
|||
*/
|
||||
void sprite_misc_explosion_cloud_create(int32_t x, int32_t y, int32_t z)
|
||||
{
|
||||
rct_unk_sprite *sprite = (rct_unk_sprite*)create_sprite(2);
|
||||
if (sprite != nullptr) {
|
||||
rct_unk_sprite* sprite = (rct_unk_sprite*)create_sprite(2);
|
||||
if (sprite != nullptr)
|
||||
{
|
||||
sprite->sprite_width = 44;
|
||||
sprite->sprite_height_negative = 32;
|
||||
sprite->sprite_height_positive = 34;
|
||||
|
@ -454,11 +476,12 @@ void sprite_misc_explosion_cloud_create(int32_t x, int32_t y, int32_t z)
|
|||
*
|
||||
* rct2: 0x00673385
|
||||
*/
|
||||
static void sprite_misc_explosion_cloud_update(rct_sprite * sprite)
|
||||
static void sprite_misc_explosion_cloud_update(rct_sprite* sprite)
|
||||
{
|
||||
invalidate_sprite_2(sprite);
|
||||
sprite->unknown.frame += 128;
|
||||
if (sprite->unknown.frame >= (36 * 128)) {
|
||||
if (sprite->unknown.frame >= (36 * 128))
|
||||
{
|
||||
sprite_remove(sprite);
|
||||
}
|
||||
}
|
||||
|
@ -469,8 +492,9 @@ static void sprite_misc_explosion_cloud_update(rct_sprite * sprite)
|
|||
*/
|
||||
void sprite_misc_explosion_flare_create(int32_t x, int32_t y, int32_t z)
|
||||
{
|
||||
rct_unk_sprite *sprite = (rct_unk_sprite*)create_sprite(2);
|
||||
if (sprite != nullptr) {
|
||||
rct_unk_sprite* sprite = (rct_unk_sprite*)create_sprite(2);
|
||||
if (sprite != nullptr)
|
||||
{
|
||||
sprite->sprite_width = 25;
|
||||
sprite->sprite_height_negative = 85;
|
||||
sprite->sprite_height_positive = 8;
|
||||
|
@ -485,11 +509,12 @@ void sprite_misc_explosion_flare_create(int32_t x, int32_t y, int32_t z)
|
|||
*
|
||||
* rct2: 0x006733B4
|
||||
*/
|
||||
static void sprite_misc_explosion_flare_update(rct_sprite * sprite)
|
||||
static void sprite_misc_explosion_flare_update(rct_sprite* sprite)
|
||||
{
|
||||
invalidate_sprite_2(sprite);
|
||||
sprite->unknown.frame += 64;
|
||||
if (sprite->unknown.frame >= (124 * 64)) {
|
||||
if (sprite->unknown.frame >= (124 * 64))
|
||||
{
|
||||
sprite_remove(sprite);
|
||||
}
|
||||
}
|
||||
|
@ -498,37 +523,38 @@ static void sprite_misc_explosion_flare_update(rct_sprite * sprite)
|
|||
*
|
||||
* rct2: 0x006731CD
|
||||
*/
|
||||
static void sprite_misc_update(rct_sprite *sprite)
|
||||
static void sprite_misc_update(rct_sprite* sprite)
|
||||
{
|
||||
switch (sprite->unknown.misc_identifier) {
|
||||
case SPRITE_MISC_STEAM_PARTICLE:
|
||||
sprite_steam_particle_update((rct_steam_particle*)sprite);
|
||||
break;
|
||||
case SPRITE_MISC_MONEY_EFFECT:
|
||||
money_effect_update(&sprite->money_effect);
|
||||
break;
|
||||
case SPRITE_MISC_CRASHED_VEHICLE_PARTICLE:
|
||||
crashed_vehicle_particle_update((rct_crashed_vehicle_particle*)sprite);
|
||||
break;
|
||||
case SPRITE_MISC_EXPLOSION_CLOUD:
|
||||
sprite_misc_explosion_cloud_update(sprite);
|
||||
break;
|
||||
case SPRITE_MISC_CRASH_SPLASH:
|
||||
crash_splash_update((rct_crash_splash*)sprite);
|
||||
break;
|
||||
case SPRITE_MISC_EXPLOSION_FLARE:
|
||||
sprite_misc_explosion_flare_update(sprite);
|
||||
break;
|
||||
case SPRITE_MISC_JUMPING_FOUNTAIN_WATER:
|
||||
case SPRITE_MISC_JUMPING_FOUNTAIN_SNOW:
|
||||
jumping_fountain_update(&sprite->jumping_fountain);
|
||||
break;
|
||||
case SPRITE_MISC_BALLOON:
|
||||
balloon_update(&sprite->balloon);
|
||||
break;
|
||||
case SPRITE_MISC_DUCK:
|
||||
duck_update(&sprite->duck);
|
||||
break;
|
||||
switch (sprite->unknown.misc_identifier)
|
||||
{
|
||||
case SPRITE_MISC_STEAM_PARTICLE:
|
||||
sprite_steam_particle_update((rct_steam_particle*)sprite);
|
||||
break;
|
||||
case SPRITE_MISC_MONEY_EFFECT:
|
||||
money_effect_update(&sprite->money_effect);
|
||||
break;
|
||||
case SPRITE_MISC_CRASHED_VEHICLE_PARTICLE:
|
||||
crashed_vehicle_particle_update((rct_crashed_vehicle_particle*)sprite);
|
||||
break;
|
||||
case SPRITE_MISC_EXPLOSION_CLOUD:
|
||||
sprite_misc_explosion_cloud_update(sprite);
|
||||
break;
|
||||
case SPRITE_MISC_CRASH_SPLASH:
|
||||
crash_splash_update((rct_crash_splash*)sprite);
|
||||
break;
|
||||
case SPRITE_MISC_EXPLOSION_FLARE:
|
||||
sprite_misc_explosion_flare_update(sprite);
|
||||
break;
|
||||
case SPRITE_MISC_JUMPING_FOUNTAIN_WATER:
|
||||
case SPRITE_MISC_JUMPING_FOUNTAIN_SNOW:
|
||||
jumping_fountain_update(&sprite->jumping_fountain);
|
||||
break;
|
||||
case SPRITE_MISC_BALLOON:
|
||||
balloon_update(&sprite->balloon);
|
||||
break;
|
||||
case SPRITE_MISC_DUCK:
|
||||
duck_update(&sprite->duck);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -538,11 +564,12 @@ static void sprite_misc_update(rct_sprite *sprite)
|
|||
*/
|
||||
void sprite_misc_update_all()
|
||||
{
|
||||
rct_sprite *sprite;
|
||||
rct_sprite* sprite;
|
||||
uint16_t spriteIndex;
|
||||
|
||||
spriteIndex = gSpriteListHead[SPRITE_LIST_MISC];
|
||||
while (spriteIndex != SPRITE_INDEX_NULL) {
|
||||
while (spriteIndex != SPRITE_INDEX_NULL)
|
||||
{
|
||||
sprite = get_sprite(spriteIndex);
|
||||
spriteIndex = sprite->unknown.next;
|
||||
sprite_misc_update(sprite);
|
||||
|
@ -558,21 +585,26 @@ void sprite_misc_update_all()
|
|||
* @param z (dx)
|
||||
* @param sprite (esi)
|
||||
*/
|
||||
void sprite_move(int16_t x, int16_t y, int16_t z, rct_sprite *sprite)
|
||||
void sprite_move(int16_t x, int16_t y, int16_t z, rct_sprite* sprite)
|
||||
{
|
||||
if (x < 0 || y < 0 || x > 0x1FFF || y > 0x1FFF) {
|
||||
if (x < 0 || y < 0 || x > 0x1FFF || y > 0x1FFF)
|
||||
{
|
||||
x = LOCATION_NULL;
|
||||
}
|
||||
|
||||
size_t newIndex = GetSpatialIndexOffset(x, y);
|
||||
size_t currentIndex = GetSpatialIndexOffset(sprite->unknown.x, sprite->unknown.y);
|
||||
if (newIndex != currentIndex) {
|
||||
uint16_t *spriteIndex = &gSpriteSpatialIndex[currentIndex];
|
||||
if (*spriteIndex != SPRITE_INDEX_NULL) {
|
||||
rct_sprite *sprite2 = get_sprite(*spriteIndex);
|
||||
while (sprite != sprite2) {
|
||||
if (newIndex != currentIndex)
|
||||
{
|
||||
uint16_t* spriteIndex = &gSpriteSpatialIndex[currentIndex];
|
||||
if (*spriteIndex != SPRITE_INDEX_NULL)
|
||||
{
|
||||
rct_sprite* sprite2 = get_sprite(*spriteIndex);
|
||||
while (sprite != sprite2)
|
||||
{
|
||||
spriteIndex = &sprite2->unknown.next_in_quadrant;
|
||||
if (*spriteIndex == SPRITE_INDEX_NULL) {
|
||||
if (*spriteIndex == SPRITE_INDEX_NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
sprite2 = get_sprite(*spriteIndex);
|
||||
|
@ -585,35 +617,40 @@ void sprite_move(int16_t x, int16_t y, int16_t z, rct_sprite *sprite)
|
|||
sprite->unknown.next_in_quadrant = tempSpriteIndex;
|
||||
}
|
||||
|
||||
if (x == LOCATION_NULL) {
|
||||
if (x == LOCATION_NULL)
|
||||
{
|
||||
sprite->unknown.sprite_left = LOCATION_NULL;
|
||||
sprite->unknown.x = x;
|
||||
sprite->unknown.y = y;
|
||||
sprite->unknown.z = z;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
sprite_set_coordinates(x, y, z, sprite);
|
||||
}
|
||||
}
|
||||
|
||||
void sprite_set_coordinates(int16_t x, int16_t y, int16_t z, rct_sprite *sprite){
|
||||
void sprite_set_coordinates(int16_t x, int16_t y, int16_t z, rct_sprite* sprite)
|
||||
{
|
||||
int16_t new_x = x, new_y = y, start_x = x;
|
||||
switch (get_current_rotation()){
|
||||
case 0:
|
||||
new_x = new_y - new_x;
|
||||
new_y = (new_y + start_x) / 2 - z;
|
||||
break;
|
||||
case 1:
|
||||
new_x = -new_y - new_x;
|
||||
new_y = (new_y - start_x) / 2 - z;
|
||||
break;
|
||||
case 2:
|
||||
new_x = -new_y + new_x;
|
||||
new_y = (-new_y - start_x) / 2 - z;
|
||||
break;
|
||||
case 3:
|
||||
new_x = new_y + new_x;
|
||||
new_y = (-new_y + start_x) / 2 - z;
|
||||
break;
|
||||
switch (get_current_rotation())
|
||||
{
|
||||
case 0:
|
||||
new_x = new_y - new_x;
|
||||
new_y = (new_y + start_x) / 2 - z;
|
||||
break;
|
||||
case 1:
|
||||
new_x = -new_y - new_x;
|
||||
new_y = (new_y - start_x) / 2 - z;
|
||||
break;
|
||||
case 2:
|
||||
new_x = -new_y + new_x;
|
||||
new_y = (-new_y - start_x) / 2 - z;
|
||||
break;
|
||||
case 3:
|
||||
new_x = new_y + new_x;
|
||||
new_y = (-new_y + start_x) / 2 - z;
|
||||
break;
|
||||
}
|
||||
|
||||
sprite->unknown.sprite_left = new_x - sprite->unknown.sprite_width;
|
||||
|
@ -629,7 +666,7 @@ void sprite_set_coordinates(int16_t x, int16_t y, int16_t z, rct_sprite *sprite)
|
|||
*
|
||||
* rct2: 0x0069EDB6
|
||||
*/
|
||||
void sprite_remove(rct_sprite *sprite)
|
||||
void sprite_remove(rct_sprite* sprite)
|
||||
{
|
||||
move_sprite_to_list(sprite, SPRITE_LIST_NULL * 2);
|
||||
user_string_free(sprite->unknown.name_string_idx);
|
||||
|
@ -637,8 +674,8 @@ void sprite_remove(rct_sprite *sprite)
|
|||
_spriteFlashingList[sprite->unknown.sprite_index] = false;
|
||||
|
||||
size_t quadrantIndex = GetSpatialIndexOffset(sprite->unknown.x, sprite->unknown.y);
|
||||
uint16_t *spriteIndex = &gSpriteSpatialIndex[quadrantIndex];
|
||||
rct_sprite *quadrantSprite;
|
||||
uint16_t* spriteIndex = &gSpriteSpatialIndex[quadrantIndex];
|
||||
rct_sprite* quadrantSprite;
|
||||
while (*spriteIndex != SPRITE_INDEX_NULL && (quadrantSprite = get_sprite(*spriteIndex)) != sprite)
|
||||
{
|
||||
spriteIndex = &quadrantSprite->unknown.next_in_quadrant;
|
||||
|
@ -648,13 +685,14 @@ void sprite_remove(rct_sprite *sprite)
|
|||
|
||||
static bool litter_can_be_at(int32_t x, int32_t y, int32_t z)
|
||||
{
|
||||
rct_tile_element *tileElement;
|
||||
rct_tile_element* tileElement;
|
||||
|
||||
if (!map_is_location_owned(x & 0xFFE0, y & 0xFFE0, z))
|
||||
return false;
|
||||
|
||||
tileElement = map_get_first_element_at(x >> 5, y >> 5);
|
||||
do {
|
||||
do
|
||||
{
|
||||
if (tileElement->GetType() != TILE_ELEMENT_TYPE_PATH)
|
||||
continue;
|
||||
|
||||
|
@ -685,25 +723,30 @@ void litter_create(int32_t x, int32_t y, int32_t z, int32_t direction, int32_t t
|
|||
if (!litter_can_be_at(x, y, z))
|
||||
return;
|
||||
|
||||
if (gSpriteListCount[SPRITE_LIST_LITTER] >= 500) {
|
||||
rct_litter *newestLitter = nullptr;
|
||||
if (gSpriteListCount[SPRITE_LIST_LITTER] >= 500)
|
||||
{
|
||||
rct_litter* newestLitter = nullptr;
|
||||
uint32_t newestLitterCreationTick = 0;
|
||||
for (uint16_t nextSpriteIndex, spriteIndex = gSpriteListHead[SPRITE_LIST_LITTER]; spriteIndex != SPRITE_INDEX_NULL; spriteIndex = nextSpriteIndex) {
|
||||
rct_litter *litter = &get_sprite(spriteIndex)->litter;
|
||||
for (uint16_t nextSpriteIndex, spriteIndex = gSpriteListHead[SPRITE_LIST_LITTER]; spriteIndex != SPRITE_INDEX_NULL;
|
||||
spriteIndex = nextSpriteIndex)
|
||||
{
|
||||
rct_litter* litter = &get_sprite(spriteIndex)->litter;
|
||||
nextSpriteIndex = litter->next;
|
||||
if (newestLitterCreationTick <= litter->creationTick) {
|
||||
if (newestLitterCreationTick <= litter->creationTick)
|
||||
{
|
||||
newestLitterCreationTick = litter->creationTick;
|
||||
newestLitter = litter;
|
||||
}
|
||||
}
|
||||
|
||||
if (newestLitter != nullptr) {
|
||||
if (newestLitter != nullptr)
|
||||
{
|
||||
invalidate_sprite_0((rct_sprite*)newestLitter);
|
||||
sprite_remove((rct_sprite*)newestLitter);
|
||||
}
|
||||
}
|
||||
|
||||
rct_litter *litter = (rct_litter*)create_sprite(1);
|
||||
rct_litter* litter = (rct_litter*)create_sprite(1);
|
||||
if (litter == nullptr)
|
||||
return;
|
||||
|
||||
|
@ -726,14 +769,18 @@ void litter_create(int32_t x, int32_t y, int32_t z, int32_t direction, int32_t t
|
|||
void litter_remove_at(int32_t x, int32_t y, int32_t z)
|
||||
{
|
||||
uint16_t spriteIndex = sprite_get_first_in_quadrant(x, y);
|
||||
while (spriteIndex != SPRITE_INDEX_NULL) {
|
||||
rct_sprite *sprite = get_sprite(spriteIndex);
|
||||
while (spriteIndex != SPRITE_INDEX_NULL)
|
||||
{
|
||||
rct_sprite* sprite = get_sprite(spriteIndex);
|
||||
uint16_t nextSpriteIndex = sprite->unknown.next_in_quadrant;
|
||||
if (sprite->unknown.linked_list_type_offset == SPRITE_LIST_LITTER * 2) {
|
||||
rct_litter *litter = &sprite->litter;
|
||||
if (sprite->unknown.linked_list_type_offset == SPRITE_LIST_LITTER * 2)
|
||||
{
|
||||
rct_litter* litter = &sprite->litter;
|
||||
|
||||
if (abs(litter->z - z) <= 16) {
|
||||
if (abs(litter->x - x) <= 8 && abs(litter->y - y) <= 8) {
|
||||
if (abs(litter->z - z) <= 16)
|
||||
{
|
||||
if (abs(litter->x - x) <= 8 && abs(litter->y - y) <= 8)
|
||||
{
|
||||
invalidate_sprite_0(sprite);
|
||||
sprite_remove(sprite);
|
||||
}
|
||||
|
@ -746,23 +793,25 @@ void litter_remove_at(int32_t x, int32_t y, int32_t z)
|
|||
/**
|
||||
* Determines whether it's worth tweening a sprite or not when frame smoothing is on.
|
||||
*/
|
||||
static bool sprite_should_tween(rct_sprite *sprite)
|
||||
static bool sprite_should_tween(rct_sprite* sprite)
|
||||
{
|
||||
switch (sprite->unknown.linked_list_type_offset >> 1) {
|
||||
case SPRITE_LIST_TRAIN:
|
||||
case SPRITE_LIST_PEEP:
|
||||
case SPRITE_LIST_UNKNOWN:
|
||||
return true;
|
||||
switch (sprite->unknown.linked_list_type_offset >> 1)
|
||||
{
|
||||
case SPRITE_LIST_TRAIN:
|
||||
case SPRITE_LIST_PEEP:
|
||||
case SPRITE_LIST_UNKNOWN:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void store_sprite_locations(LocationXYZ16 * sprite_locations)
|
||||
static void store_sprite_locations(LocationXYZ16* sprite_locations)
|
||||
{
|
||||
for (uint16_t i = 0; i < MAX_SPRITES; i++) {
|
||||
for (uint16_t i = 0; i < MAX_SPRITES; i++)
|
||||
{
|
||||
// skip going through `get_sprite` to not get stalled on assert,
|
||||
// this can get very expensive for busy parks with uncap FPS option on
|
||||
const rct_sprite *sprite = &_spriteList[i];
|
||||
const rct_sprite* sprite = &_spriteList[i];
|
||||
sprite_locations[i].x = sprite->unknown.x;
|
||||
sprite_locations[i].y = sprite->unknown.y;
|
||||
sprite_locations[i].z = sprite->unknown.z;
|
||||
|
@ -783,20 +832,22 @@ void sprite_position_tween_all(float alpha)
|
|||
{
|
||||
const float inv = (1.0f - alpha);
|
||||
|
||||
for (uint16_t i = 0; i < MAX_SPRITES; i++) {
|
||||
rct_sprite * sprite = get_sprite(i);
|
||||
if (sprite_should_tween(sprite)) {
|
||||
for (uint16_t i = 0; i < MAX_SPRITES; i++)
|
||||
{
|
||||
rct_sprite* sprite = get_sprite(i);
|
||||
if (sprite_should_tween(sprite))
|
||||
{
|
||||
LocationXYZ16 posA = _spritelocations1[i];
|
||||
LocationXYZ16 posB = _spritelocations2[i];
|
||||
if (posA.x == posB.x && posA.y == posB.y && posA.z == posB.z) {
|
||||
if (posA.x == posB.x && posA.y == posB.y && posA.z == posB.z)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
sprite_set_coordinates(
|
||||
std::round(posB.x * alpha + posA.x * inv),
|
||||
std::round(posB.y * alpha + posA.y * inv),
|
||||
std::round(posB.z * alpha + posA.z * inv),
|
||||
sprite
|
||||
);
|
||||
sprite);
|
||||
invalidate_sprite_2(sprite);
|
||||
}
|
||||
}
|
||||
|
@ -807,9 +858,11 @@ void sprite_position_tween_all(float alpha)
|
|||
*/
|
||||
void sprite_position_tween_restore()
|
||||
{
|
||||
for (uint16_t i = 0; i < MAX_SPRITES; i++) {
|
||||
rct_sprite * sprite = get_sprite(i);
|
||||
if (sprite_should_tween(sprite)) {
|
||||
for (uint16_t i = 0; i < MAX_SPRITES; i++)
|
||||
{
|
||||
rct_sprite* sprite = get_sprite(i);
|
||||
if (sprite_should_tween(sprite))
|
||||
{
|
||||
invalidate_sprite_2(sprite);
|
||||
|
||||
LocationXYZ16 pos = _spritelocations2[i];
|
||||
|
@ -820,39 +873,37 @@ void sprite_position_tween_restore()
|
|||
|
||||
void sprite_position_tween_reset()
|
||||
{
|
||||
for (uint16_t i = 0; i < MAX_SPRITES; i++) {
|
||||
rct_sprite * sprite = get_sprite(i);
|
||||
_spritelocations1[i].x =
|
||||
_spritelocations2[i].x = sprite->unknown.x;
|
||||
_spritelocations1[i].y =
|
||||
_spritelocations2[i].y = sprite->unknown.y;
|
||||
_spritelocations1[i].z =
|
||||
_spritelocations2[i].z = sprite->unknown.z;
|
||||
for (uint16_t i = 0; i < MAX_SPRITES; i++)
|
||||
{
|
||||
rct_sprite* sprite = get_sprite(i);
|
||||
_spritelocations1[i].x = _spritelocations2[i].x = sprite->unknown.x;
|
||||
_spritelocations1[i].y = _spritelocations2[i].y = sprite->unknown.y;
|
||||
_spritelocations1[i].z = _spritelocations2[i].z = sprite->unknown.z;
|
||||
}
|
||||
}
|
||||
|
||||
void sprite_set_flashing(rct_sprite *sprite, bool flashing)
|
||||
void sprite_set_flashing(rct_sprite* sprite, bool flashing)
|
||||
{
|
||||
assert(sprite->unknown.sprite_index < MAX_SPRITES);
|
||||
_spriteFlashingList[sprite->unknown.sprite_index] = flashing;
|
||||
}
|
||||
|
||||
bool sprite_get_flashing(rct_sprite *sprite)
|
||||
bool sprite_get_flashing(rct_sprite* sprite)
|
||||
{
|
||||
assert(sprite->unknown.sprite_index < MAX_SPRITES);
|
||||
return _spriteFlashingList[sprite->unknown.sprite_index];
|
||||
}
|
||||
|
||||
static rct_sprite * find_sprite_list_cycle(uint16_t sprite_idx)
|
||||
static rct_sprite* find_sprite_list_cycle(uint16_t sprite_idx)
|
||||
{
|
||||
if (sprite_idx == SPRITE_INDEX_NULL)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
const rct_sprite * fast = get_sprite(sprite_idx);
|
||||
const rct_sprite * slow = fast;
|
||||
const rct_sprite* fast = get_sprite(sprite_idx);
|
||||
const rct_sprite* slow = fast;
|
||||
bool increment_slow = false;
|
||||
rct_sprite * cycle_start = nullptr;
|
||||
rct_sprite* cycle_start = nullptr;
|
||||
while (fast->unknown.sprite_index != SPRITE_INDEX_NULL)
|
||||
{
|
||||
// increment fast every time, unless reached the end
|
||||
|
@ -860,7 +911,8 @@ static rct_sprite * find_sprite_list_cycle(uint16_t sprite_idx)
|
|||
{
|
||||
break;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
fast = get_sprite(fast->unknown.next);
|
||||
}
|
||||
// increment slow only every second iteration
|
||||
|
@ -878,16 +930,16 @@ static rct_sprite * find_sprite_list_cycle(uint16_t sprite_idx)
|
|||
return cycle_start;
|
||||
}
|
||||
|
||||
static rct_sprite * find_sprite_quadrant_cycle(uint16_t sprite_idx)
|
||||
static rct_sprite* find_sprite_quadrant_cycle(uint16_t sprite_idx)
|
||||
{
|
||||
if (sprite_idx == SPRITE_INDEX_NULL)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
const rct_sprite * fast = get_sprite(sprite_idx);
|
||||
const rct_sprite * slow = fast;
|
||||
const rct_sprite* fast = get_sprite(sprite_idx);
|
||||
const rct_sprite* slow = fast;
|
||||
bool increment_slow = false;
|
||||
rct_sprite * cycle_start = nullptr;
|
||||
rct_sprite* cycle_start = nullptr;
|
||||
while (fast->unknown.sprite_index != SPRITE_INDEX_NULL)
|
||||
{
|
||||
// increment fast every time, unless reached the end
|
||||
|
@ -895,7 +947,8 @@ static rct_sprite * find_sprite_quadrant_cycle(uint16_t sprite_idx)
|
|||
{
|
||||
break;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
fast = get_sprite(fast->unknown.next_in_quadrant);
|
||||
}
|
||||
// increment slow only every second iteration
|
||||
|
@ -929,8 +982,9 @@ static bool index_is_in_list(uint16_t index, enum SPRITE_LIST sl)
|
|||
|
||||
int32_t check_for_sprite_list_cycles(bool fix)
|
||||
{
|
||||
for (int32_t i = 0; i < NUM_SPRITE_LISTS; i++) {
|
||||
rct_sprite * cycle_start = find_sprite_list_cycle(gSpriteListHead[i]);
|
||||
for (int32_t i = 0; i < NUM_SPRITE_LISTS; i++)
|
||||
{
|
||||
rct_sprite* cycle_start = find_sprite_list_cycle(gSpriteListHead[i]);
|
||||
if (cycle_start != nullptr)
|
||||
{
|
||||
if (fix)
|
||||
|
@ -949,7 +1003,7 @@ int32_t check_for_sprite_list_cycles(bool fix)
|
|||
// Add each sprite to the list until we encounter one that is already part of the list.
|
||||
while (!index_is_in_list(cycle_next, (SPRITE_LIST)i))
|
||||
{
|
||||
rct_sprite * spr = get_sprite(cycle_next);
|
||||
rct_sprite* spr = get_sprite(cycle_next);
|
||||
|
||||
cycle_start->unknown.next = cycle_next;
|
||||
spr->unknown.previous = cycle_start->unknown.sprite_index;
|
||||
|
@ -957,7 +1011,6 @@ int32_t check_for_sprite_list_cycles(bool fix)
|
|||
spr->unknown.next = SPRITE_INDEX_NULL;
|
||||
cycle_start = spr;
|
||||
}
|
||||
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
@ -975,7 +1028,7 @@ int32_t fix_disjoint_sprites()
|
|||
// Find reachable sprites
|
||||
bool reachable[MAX_SPRITES] = { false };
|
||||
uint16_t sprite_idx = gSpriteListHead[SPRITE_LIST_NULL];
|
||||
rct_sprite * null_list_tail = nullptr;
|
||||
rct_sprite* null_list_tail = nullptr;
|
||||
while (sprite_idx != SPRITE_INDEX_NULL)
|
||||
{
|
||||
reachable[sprite_idx] = true;
|
||||
|
@ -989,7 +1042,7 @@ int32_t fix_disjoint_sprites()
|
|||
// Find all null sprites
|
||||
for (sprite_idx = 0; sprite_idx < MAX_SPRITES; sprite_idx++)
|
||||
{
|
||||
rct_sprite * spr = get_sprite(sprite_idx);
|
||||
rct_sprite* spr = get_sprite(sprite_idx);
|
||||
if (spr->unknown.sprite_identifier == SPRITE_IDENTIFIER_NULL)
|
||||
{
|
||||
openrct2_assert(null_list_tail != nullptr, "Null list is empty, yet found null sprites");
|
||||
|
@ -1011,8 +1064,9 @@ int32_t fix_disjoint_sprites()
|
|||
|
||||
int32_t check_for_spatial_index_cycles(bool fix)
|
||||
{
|
||||
for (int32_t i = 0; i < SPATIAL_INDEX_LOCATION_NULL; i++) {
|
||||
rct_sprite * cycle_start = find_sprite_quadrant_cycle(gSpriteSpatialIndex[i]);
|
||||
for (int32_t i = 0; i < SPATIAL_INDEX_LOCATION_NULL; i++)
|
||||
{
|
||||
rct_sprite* cycle_start = find_sprite_quadrant_cycle(gSpriteSpatialIndex[i]);
|
||||
if (cycle_start != nullptr)
|
||||
{
|
||||
if (fix)
|
||||
|
@ -1027,7 +1081,7 @@ int32_t check_for_spatial_index_cycles(bool fix)
|
|||
// Add each sprite to the list until we encounter one that is already part of the list.
|
||||
while (!index_is_in_list(cycle_next, (SPRITE_LIST)i))
|
||||
{
|
||||
rct_sprite * spr = get_sprite(cycle_next);
|
||||
rct_sprite* spr = get_sprite(cycle_next);
|
||||
|
||||
cycle_start->unknown.next_in_quadrant = cycle_next;
|
||||
cycle_next = spr->unknown.next_in_quadrant;
|
||||
|
|
|
@ -14,11 +14,12 @@
|
|||
#include "../peep/Peep.h"
|
||||
#include "../ride/Vehicle.h"
|
||||
|
||||
#define SPRITE_INDEX_NULL 0xFFFF
|
||||
#define MAX_SPRITES 10000
|
||||
#define NUM_SPRITE_LISTS 6
|
||||
#define SPRITE_INDEX_NULL 0xFFFF
|
||||
#define MAX_SPRITES 10000
|
||||
#define NUM_SPRITE_LISTS 6
|
||||
|
||||
enum SPRITE_IDENTIFIER {
|
||||
enum SPRITE_IDENTIFIER
|
||||
{
|
||||
SPRITE_IDENTIFIER_VEHICLE = 0,
|
||||
SPRITE_IDENTIFIER_PEEP = 1,
|
||||
SPRITE_IDENTIFIER_MISC = 2,
|
||||
|
@ -26,7 +27,8 @@ enum SPRITE_IDENTIFIER {
|
|||
SPRITE_IDENTIFIER_NULL = 255
|
||||
};
|
||||
|
||||
enum SPRITE_LIST {
|
||||
enum SPRITE_LIST
|
||||
{
|
||||
SPRITE_LIST_NULL,
|
||||
SPRITE_LIST_TRAIN,
|
||||
SPRITE_LIST_PEEP,
|
||||
|
@ -36,79 +38,82 @@ enum SPRITE_LIST {
|
|||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct rct_unk_sprite {
|
||||
uint8_t sprite_identifier; // 0x00
|
||||
uint8_t misc_identifier; // 0x01
|
||||
uint16_t next_in_quadrant; // 0x02
|
||||
uint16_t next; // 0x04
|
||||
uint16_t previous; // 0x06
|
||||
uint8_t linked_list_type_offset; // 0x08 Valid values are SPRITE_LINKEDLIST_OFFSET_...
|
||||
struct rct_unk_sprite
|
||||
{
|
||||
uint8_t sprite_identifier; // 0x00
|
||||
uint8_t misc_identifier; // 0x01
|
||||
uint16_t next_in_quadrant; // 0x02
|
||||
uint16_t next; // 0x04
|
||||
uint16_t previous; // 0x06
|
||||
uint8_t linked_list_type_offset; // 0x08 Valid values are SPRITE_LINKEDLIST_OFFSET_...
|
||||
// Height from centre of sprite to bottom
|
||||
uint8_t sprite_height_negative; // 0x09
|
||||
uint16_t sprite_index; // 0x0A
|
||||
uint16_t flags; // 0x0C
|
||||
int16_t x; // 0x0E
|
||||
int16_t y; // 0x10
|
||||
int16_t z; // 0x12
|
||||
uint8_t sprite_height_negative; // 0x09
|
||||
uint16_t sprite_index; // 0x0A
|
||||
uint16_t flags; // 0x0C
|
||||
int16_t x; // 0x0E
|
||||
int16_t y; // 0x10
|
||||
int16_t z; // 0x12
|
||||
// Width from centre of sprite to edge
|
||||
uint8_t sprite_width; // 0x14
|
||||
uint8_t sprite_width; // 0x14
|
||||
// Height from centre of sprite to top
|
||||
uint8_t sprite_height_positive; // 0x15
|
||||
int16_t sprite_left; // 0x16
|
||||
int16_t sprite_top; // 0x18
|
||||
int16_t sprite_right; // 0x1A
|
||||
int16_t sprite_bottom; // 0x1C
|
||||
uint8_t sprite_direction; // 0x1e
|
||||
uint8_t sprite_height_positive; // 0x15
|
||||
int16_t sprite_left; // 0x16
|
||||
int16_t sprite_top; // 0x18
|
||||
int16_t sprite_right; // 0x1A
|
||||
int16_t sprite_bottom; // 0x1C
|
||||
uint8_t sprite_direction; // 0x1e
|
||||
uint8_t pad_1F[3];
|
||||
rct_string_id name_string_idx; // 0x22
|
||||
rct_string_id name_string_idx; // 0x22
|
||||
uint16_t pad_24;
|
||||
uint16_t frame; // 0x26
|
||||
uint16_t frame; // 0x26
|
||||
};
|
||||
assert_struct_size(rct_unk_sprite, 0x28);
|
||||
|
||||
struct rct_litter {
|
||||
uint8_t sprite_identifier; // 0x00
|
||||
uint8_t type; // 0x01
|
||||
uint16_t next_in_quadrant; // 0x02
|
||||
uint16_t next; // 0x04
|
||||
uint16_t previous; // 0x06
|
||||
uint8_t linked_list_type_offset; // 0x08 Valid values are SPRITE_LINKEDLIST_OFFSET_...
|
||||
uint8_t sprite_height_negative; // 0x09
|
||||
uint16_t sprite_index; // 0x0A
|
||||
uint16_t flags; // 0x0C
|
||||
struct rct_litter
|
||||
{
|
||||
uint8_t sprite_identifier; // 0x00
|
||||
uint8_t type; // 0x01
|
||||
uint16_t next_in_quadrant; // 0x02
|
||||
uint16_t next; // 0x04
|
||||
uint16_t previous; // 0x06
|
||||
uint8_t linked_list_type_offset; // 0x08 Valid values are SPRITE_LINKEDLIST_OFFSET_...
|
||||
uint8_t sprite_height_negative; // 0x09
|
||||
uint16_t sprite_index; // 0x0A
|
||||
uint16_t flags; // 0x0C
|
||||
int16_t x; // 0x0E
|
||||
int16_t y; // 0x10
|
||||
int16_t z; // 0x12
|
||||
uint8_t sprite_width; // 0x14
|
||||
uint8_t sprite_height_positive; // 0x15
|
||||
uint8_t sprite_width; // 0x14
|
||||
uint8_t sprite_height_positive; // 0x15
|
||||
uint8_t pad_16[8];
|
||||
uint8_t sprite_direction; // 0x1E
|
||||
uint8_t sprite_direction; // 0x1E
|
||||
uint8_t pad_1F[5];
|
||||
uint32_t creationTick; // 0x24
|
||||
uint32_t creationTick; // 0x24
|
||||
};
|
||||
assert_struct_size(rct_litter, 0x28);
|
||||
|
||||
struct rct_balloon {
|
||||
uint8_t sprite_identifier; // 0x00
|
||||
uint8_t misc_identifier; // 0x01
|
||||
uint16_t next_in_quadrant; // 0x02
|
||||
uint16_t next; // 0x04
|
||||
uint16_t previous; // 0x06
|
||||
uint8_t linked_list_type_offset; // 0x08 Valid values are SPRITE_LINKEDLIST_OFFSET_...
|
||||
uint8_t sprite_height_negative; // 0x09
|
||||
uint16_t sprite_index; // 0x0A
|
||||
uint16_t flags; // 0x0C
|
||||
struct rct_balloon
|
||||
{
|
||||
uint8_t sprite_identifier; // 0x00
|
||||
uint8_t misc_identifier; // 0x01
|
||||
uint16_t next_in_quadrant; // 0x02
|
||||
uint16_t next; // 0x04
|
||||
uint16_t previous; // 0x06
|
||||
uint8_t linked_list_type_offset; // 0x08 Valid values are SPRITE_LINKEDLIST_OFFSET_...
|
||||
uint8_t sprite_height_negative; // 0x09
|
||||
uint16_t sprite_index; // 0x0A
|
||||
uint16_t flags; // 0x0C
|
||||
int16_t x; // 0x0E
|
||||
int16_t y; // 0x10
|
||||
int16_t z; // 0x12
|
||||
uint8_t sprite_width; // 0x14
|
||||
uint8_t sprite_height_positive; // 0x15
|
||||
uint8_t sprite_width; // 0x14
|
||||
uint8_t sprite_height_positive; // 0x15
|
||||
uint8_t pad_16[0xE];
|
||||
uint16_t popped; // 0x24
|
||||
uint8_t time_to_move; // 0x26
|
||||
uint8_t frame; // 0x27
|
||||
uint16_t popped; // 0x24
|
||||
uint8_t time_to_move; // 0x26
|
||||
uint8_t frame; // 0x27
|
||||
uint8_t pad_28[4];
|
||||
uint8_t colour; // 0x2C
|
||||
uint8_t colour; // 0x2C
|
||||
|
||||
void Update();
|
||||
void Pop();
|
||||
|
@ -116,30 +121,31 @@ struct rct_balloon {
|
|||
};
|
||||
assert_struct_size(rct_balloon, 0x2D);
|
||||
|
||||
struct rct_duck {
|
||||
uint8_t sprite_identifier; // 0x00
|
||||
uint8_t misc_identifier; // 0x01
|
||||
uint16_t next_in_quadrant; // 0x02
|
||||
uint16_t next; // 0x04
|
||||
uint16_t previous; // 0x06
|
||||
uint8_t linked_list_type_offset; // 0x08 Valid values are SPRITE_LINKEDLIST_OFFSET_...
|
||||
uint8_t sprite_height_negative; // 0x09
|
||||
uint16_t sprite_index; // 0x0A
|
||||
uint16_t flags; // 0x0C
|
||||
struct rct_duck
|
||||
{
|
||||
uint8_t sprite_identifier; // 0x00
|
||||
uint8_t misc_identifier; // 0x01
|
||||
uint16_t next_in_quadrant; // 0x02
|
||||
uint16_t next; // 0x04
|
||||
uint16_t previous; // 0x06
|
||||
uint8_t linked_list_type_offset; // 0x08 Valid values are SPRITE_LINKEDLIST_OFFSET_...
|
||||
uint8_t sprite_height_negative; // 0x09
|
||||
uint16_t sprite_index; // 0x0A
|
||||
uint16_t flags; // 0x0C
|
||||
int16_t x; // 0x0E
|
||||
int16_t y; // 0x10
|
||||
int16_t z; // 0x12
|
||||
uint8_t sprite_width; // 0x14
|
||||
uint8_t sprite_height_positive; // 0x15
|
||||
uint8_t sprite_width; // 0x14
|
||||
uint8_t sprite_height_positive; // 0x15
|
||||
uint8_t pad_16[0x8];
|
||||
uint8_t sprite_direction; // 0x1E
|
||||
uint8_t sprite_direction; // 0x1E
|
||||
uint8_t pad_1F[0x7];
|
||||
uint16_t frame;
|
||||
uint8_t pad_28[0x8];
|
||||
int16_t target_x; // 0x30
|
||||
int16_t target_y; // 0x32
|
||||
int16_t target_x; // 0x30
|
||||
int16_t target_y; // 0x32
|
||||
uint8_t pad_34[0x14];
|
||||
uint8_t state; // 0x48
|
||||
uint8_t state; // 0x48
|
||||
|
||||
void UpdateFlyToWater();
|
||||
void UpdateSwim();
|
||||
|
@ -150,162 +156,166 @@ struct rct_duck {
|
|||
void Invalidate();
|
||||
void Remove();
|
||||
void MoveTo(int16_t x, int16_t y, int16_t z);
|
||||
|
||||
};
|
||||
assert_struct_size(rct_duck, 0x49);
|
||||
|
||||
struct rct_jumping_fountain {
|
||||
uint8_t sprite_identifier; // 0x00
|
||||
uint8_t misc_identifier; // 0x01
|
||||
uint16_t next_in_quadrant; // 0x02
|
||||
uint16_t next; // 0x04
|
||||
uint16_t previous; // 0x06
|
||||
uint8_t linked_list_type_offset; // 0x08 Valid values are SPRITE_LINKEDLIST_OFFSET_...
|
||||
struct rct_jumping_fountain
|
||||
{
|
||||
uint8_t sprite_identifier; // 0x00
|
||||
uint8_t misc_identifier; // 0x01
|
||||
uint16_t next_in_quadrant; // 0x02
|
||||
uint16_t next; // 0x04
|
||||
uint16_t previous; // 0x06
|
||||
uint8_t linked_list_type_offset; // 0x08 Valid values are SPRITE_LINKEDLIST_OFFSET_...
|
||||
uint8_t sprite_height_negative;
|
||||
uint16_t sprite_index; // 0x0A
|
||||
uint16_t flags; // 0x0C
|
||||
int16_t x; // 0x0E
|
||||
int16_t y; // 0x10
|
||||
int16_t z; // 0x12
|
||||
uint8_t sprite_width; // 0x14
|
||||
uint8_t sprite_height_positive; // 0x15
|
||||
uint16_t sprite_index; // 0x0A
|
||||
uint16_t flags; // 0x0C
|
||||
int16_t x; // 0x0E
|
||||
int16_t y; // 0x10
|
||||
int16_t z; // 0x12
|
||||
uint8_t sprite_width; // 0x14
|
||||
uint8_t sprite_height_positive; // 0x15
|
||||
uint8_t pad_16[0x8];
|
||||
uint8_t sprite_direction; // 0x1E
|
||||
uint8_t sprite_direction; // 0x1E
|
||||
uint8_t pad_1F[0x7];
|
||||
uint8_t num_ticks_alive; // 0x26
|
||||
uint8_t frame; // 0x27
|
||||
uint8_t pad_28[0x7]; // 0x28 Originally var_2E was set to direction but it was unused.
|
||||
uint8_t fountain_flags; // 0x2F
|
||||
int16_t target_x; // 0x30
|
||||
int16_t target_y; // 0x32
|
||||
uint8_t num_ticks_alive; // 0x26
|
||||
uint8_t frame; // 0x27
|
||||
uint8_t pad_28[0x7]; // 0x28 Originally var_2E was set to direction but it was unused.
|
||||
uint8_t fountain_flags; // 0x2F
|
||||
int16_t target_x; // 0x30
|
||||
int16_t target_y; // 0x32
|
||||
uint8_t pad_34[0x12];
|
||||
uint16_t iteration; // 0x46
|
||||
uint16_t iteration; // 0x46
|
||||
};
|
||||
assert_struct_size(rct_jumping_fountain, 0x48);
|
||||
|
||||
struct rct_money_effect {
|
||||
uint8_t sprite_identifier; // 0x00
|
||||
uint8_t misc_identifier; // 0x01
|
||||
uint16_t next_in_quadrant; // 0x02
|
||||
uint16_t next; // 0x04
|
||||
uint16_t previous; // 0x06
|
||||
uint8_t linked_list_type_offset; // 0x08 Valid values are SPRITE_LINKEDLIST_OFFSET_...
|
||||
struct rct_money_effect
|
||||
{
|
||||
uint8_t sprite_identifier; // 0x00
|
||||
uint8_t misc_identifier; // 0x01
|
||||
uint16_t next_in_quadrant; // 0x02
|
||||
uint16_t next; // 0x04
|
||||
uint16_t previous; // 0x06
|
||||
uint8_t linked_list_type_offset; // 0x08 Valid values are SPRITE_LINKEDLIST_OFFSET_...
|
||||
uint8_t sprite_height_negative;
|
||||
uint16_t sprite_index; // 0x0A
|
||||
uint16_t flags; // 0x0C
|
||||
int16_t x; // 0x0E
|
||||
int16_t y; // 0x10
|
||||
int16_t z; // 0x12
|
||||
uint8_t sprite_width; // 0x14
|
||||
uint8_t sprite_height_positive; // 0x15
|
||||
uint16_t sprite_index; // 0x0A
|
||||
uint16_t flags; // 0x0C
|
||||
int16_t x; // 0x0E
|
||||
int16_t y; // 0x10
|
||||
int16_t z; // 0x12
|
||||
uint8_t sprite_width; // 0x14
|
||||
uint8_t sprite_height_positive; // 0x15
|
||||
uint8_t pad_16[0xE];
|
||||
uint16_t move_delay; // 0x24
|
||||
uint8_t num_movements; // 0x26
|
||||
uint16_t move_delay; // 0x24
|
||||
uint8_t num_movements; // 0x26
|
||||
uint8_t vertical;
|
||||
money32 value; // 0x28
|
||||
money32 value; // 0x28
|
||||
uint8_t pad_2C[0x18];
|
||||
int16_t offset_x; // 0x44
|
||||
uint16_t wiggle; // 0x46
|
||||
int16_t offset_x; // 0x44
|
||||
uint16_t wiggle; // 0x46
|
||||
};
|
||||
assert_struct_size(rct_money_effect, 0x48);
|
||||
|
||||
struct rct_crashed_vehicle_particle {
|
||||
uint8_t sprite_identifier; // 0x00
|
||||
uint8_t misc_identifier; // 0x01
|
||||
uint16_t next_in_quadrant; // 0x02
|
||||
uint16_t next; // 0x04
|
||||
uint16_t previous; // 0x06
|
||||
uint8_t linked_list_type_offset; // 0x08 Valid values are SPRITE_LINKEDLIST_OFFSET_...
|
||||
struct rct_crashed_vehicle_particle
|
||||
{
|
||||
uint8_t sprite_identifier; // 0x00
|
||||
uint8_t misc_identifier; // 0x01
|
||||
uint16_t next_in_quadrant; // 0x02
|
||||
uint16_t next; // 0x04
|
||||
uint16_t previous; // 0x06
|
||||
uint8_t linked_list_type_offset; // 0x08 Valid values are SPRITE_LINKEDLIST_OFFSET_...
|
||||
// Height from centre of sprite to bottom
|
||||
uint8_t sprite_height_negative; // 0x09
|
||||
uint16_t sprite_index; // 0x0A
|
||||
uint16_t flags; // 0x0C
|
||||
int16_t x; // 0x0E
|
||||
int16_t y; // 0x10
|
||||
int16_t z; // 0x12
|
||||
uint8_t sprite_height_negative; // 0x09
|
||||
uint16_t sprite_index; // 0x0A
|
||||
uint16_t flags; // 0x0C
|
||||
int16_t x; // 0x0E
|
||||
int16_t y; // 0x10
|
||||
int16_t z; // 0x12
|
||||
// Width from centre of sprite to edge
|
||||
uint8_t sprite_width; // 0x14
|
||||
uint8_t sprite_width; // 0x14
|
||||
// Height from centre of sprite to top
|
||||
uint8_t sprite_height_positive; // 0x15
|
||||
int16_t sprite_left; // 0x16
|
||||
int16_t sprite_top; // 0x18
|
||||
int16_t sprite_right; // 0x1A
|
||||
int16_t sprite_bottom; // 0x1C
|
||||
uint8_t sprite_direction; //direction of sprite? 0x1e
|
||||
uint8_t pad_1F[3]; // 0x1f
|
||||
uint16_t name_string_idx; // 0x22
|
||||
uint16_t time_to_live; // 0x24
|
||||
uint16_t frame; // 0x26
|
||||
uint8_t sprite_height_positive; // 0x15
|
||||
int16_t sprite_left; // 0x16
|
||||
int16_t sprite_top; // 0x18
|
||||
int16_t sprite_right; // 0x1A
|
||||
int16_t sprite_bottom; // 0x1C
|
||||
uint8_t sprite_direction; // direction of sprite? 0x1e
|
||||
uint8_t pad_1F[3]; // 0x1f
|
||||
uint16_t name_string_idx; // 0x22
|
||||
uint16_t time_to_live; // 0x24
|
||||
uint16_t frame; // 0x26
|
||||
uint8_t pad_28[4];
|
||||
uint8_t colour[2];
|
||||
uint16_t crashed_sprite_base; // 0x2E
|
||||
int16_t velocity_x; // 0x30
|
||||
int16_t velocity_y; // 0x32
|
||||
int16_t velocity_z; // 0x34
|
||||
uint16_t crashed_sprite_base; // 0x2E
|
||||
int16_t velocity_x; // 0x30
|
||||
int16_t velocity_y; // 0x32
|
||||
int16_t velocity_z; // 0x34
|
||||
uint16_t pad_36;
|
||||
int32_t acceleration_x; // 0x38
|
||||
int32_t acceleration_y; // 0x3C
|
||||
int32_t acceleration_z; // 0x40
|
||||
int32_t acceleration_x; // 0x38
|
||||
int32_t acceleration_y; // 0x3C
|
||||
int32_t acceleration_z; // 0x40
|
||||
};
|
||||
assert_struct_size(rct_crashed_vehicle_particle, 0x44);
|
||||
|
||||
struct rct_crash_splash {
|
||||
uint8_t sprite_identifier; // 0x00
|
||||
uint8_t misc_identifier; // 0x01
|
||||
uint16_t next_in_quadrant; // 0x02
|
||||
uint16_t next; // 0x04
|
||||
uint16_t previous; // 0x06
|
||||
uint8_t linked_list_type_offset; // 0x08 Valid values are SPRITE_LINKEDLIST_OFFSET_...
|
||||
struct rct_crash_splash
|
||||
{
|
||||
uint8_t sprite_identifier; // 0x00
|
||||
uint8_t misc_identifier; // 0x01
|
||||
uint16_t next_in_quadrant; // 0x02
|
||||
uint16_t next; // 0x04
|
||||
uint16_t previous; // 0x06
|
||||
uint8_t linked_list_type_offset; // 0x08 Valid values are SPRITE_LINKEDLIST_OFFSET_...
|
||||
// Height from centre of sprite to bottom
|
||||
uint8_t sprite_height_negative; // 0x09
|
||||
uint16_t sprite_index; // 0x0A
|
||||
uint16_t flags; // 0x0C
|
||||
int16_t x; // 0x0E
|
||||
int16_t y; // 0x10
|
||||
int16_t z; // 0x12
|
||||
uint8_t sprite_height_negative; // 0x09
|
||||
uint16_t sprite_index; // 0x0A
|
||||
uint16_t flags; // 0x0C
|
||||
int16_t x; // 0x0E
|
||||
int16_t y; // 0x10
|
||||
int16_t z; // 0x12
|
||||
// Width from centre of sprite to edge
|
||||
uint8_t sprite_width; // 0x14
|
||||
uint8_t sprite_width; // 0x14
|
||||
// Height from centre of sprite to top
|
||||
uint8_t sprite_height_positive; // 0x15
|
||||
int16_t sprite_left; // 0x16
|
||||
int16_t sprite_top; // 0x18
|
||||
int16_t sprite_right; // 0x1A
|
||||
int16_t sprite_bottom; // 0x1C
|
||||
uint8_t sprite_direction; //direction of sprite? 0x1e
|
||||
uint8_t pad_1F[3]; // 0x1f
|
||||
uint16_t name_string_idx; // 0x22
|
||||
uint8_t sprite_height_positive; // 0x15
|
||||
int16_t sprite_left; // 0x16
|
||||
int16_t sprite_top; // 0x18
|
||||
int16_t sprite_right; // 0x1A
|
||||
int16_t sprite_bottom; // 0x1C
|
||||
uint8_t sprite_direction; // direction of sprite? 0x1e
|
||||
uint8_t pad_1F[3]; // 0x1f
|
||||
uint16_t name_string_idx; // 0x22
|
||||
uint16_t pad_24;
|
||||
uint16_t frame; // 0x26
|
||||
uint16_t frame; // 0x26
|
||||
};
|
||||
assert_struct_size(rct_crash_splash, 0x28);
|
||||
|
||||
struct rct_steam_particle {
|
||||
uint8_t sprite_identifier; // 0x00
|
||||
uint8_t misc_identifier; // 0x01
|
||||
uint16_t next_in_quadrant; // 0x02
|
||||
uint16_t next; // 0x04
|
||||
uint16_t previous; // 0x06
|
||||
uint8_t linked_list_type_offset; // 0x08 Valid values are SPRITE_LINKEDLIST_OFFSET_...
|
||||
struct rct_steam_particle
|
||||
{
|
||||
uint8_t sprite_identifier; // 0x00
|
||||
uint8_t misc_identifier; // 0x01
|
||||
uint16_t next_in_quadrant; // 0x02
|
||||
uint16_t next; // 0x04
|
||||
uint16_t previous; // 0x06
|
||||
uint8_t linked_list_type_offset; // 0x08 Valid values are SPRITE_LINKEDLIST_OFFSET_...
|
||||
// Height from centre of sprite to bottom
|
||||
uint8_t sprite_height_negative; // 0x09
|
||||
uint16_t sprite_index; // 0x0A
|
||||
uint16_t flags; // 0x0C
|
||||
int16_t x; // 0x0E
|
||||
int16_t y; // 0x10
|
||||
int16_t z; // 0x12
|
||||
uint8_t sprite_height_negative; // 0x09
|
||||
uint16_t sprite_index; // 0x0A
|
||||
uint16_t flags; // 0x0C
|
||||
int16_t x; // 0x0E
|
||||
int16_t y; // 0x10
|
||||
int16_t z; // 0x12
|
||||
// Width from centre of sprite to edge
|
||||
uint8_t sprite_width; // 0x14
|
||||
uint8_t sprite_width; // 0x14
|
||||
// Height from centre of sprite to top
|
||||
uint8_t sprite_height_positive; // 0x15
|
||||
int16_t sprite_left; // 0x16
|
||||
int16_t sprite_top; // 0x18
|
||||
int16_t sprite_right; // 0x1A
|
||||
int16_t sprite_bottom; // 0x1C
|
||||
uint8_t sprite_direction; // 0x1E
|
||||
uint8_t pad_1F[3]; // 0x1F
|
||||
uint16_t name_string_idx; // 0x22
|
||||
uint16_t time_to_move; // 0x24 Moves +1 z every 3 ticks after intitial 4 ticks
|
||||
uint16_t frame; // 0x26
|
||||
uint8_t sprite_height_positive; // 0x15
|
||||
int16_t sprite_left; // 0x16
|
||||
int16_t sprite_top; // 0x18
|
||||
int16_t sprite_right; // 0x1A
|
||||
int16_t sprite_bottom; // 0x1C
|
||||
uint8_t sprite_direction; // 0x1E
|
||||
uint8_t pad_1F[3]; // 0x1F
|
||||
uint16_t name_string_idx; // 0x22
|
||||
uint16_t time_to_move; // 0x24 Moves +1 z every 3 ticks after intitial 4 ticks
|
||||
uint16_t frame; // 0x26
|
||||
};
|
||||
assert_struct_size(rct_steam_particle, 0x28);
|
||||
|
||||
|
@ -313,7 +323,8 @@ assert_struct_size(rct_steam_particle, 0x28);
|
|||
* Sprite structure.
|
||||
* size: 0x0100
|
||||
*/
|
||||
union rct_sprite {
|
||||
union rct_sprite
|
||||
{
|
||||
uint8_t pad_00[0x100];
|
||||
rct_unk_sprite unknown;
|
||||
rct_peep peep;
|
||||
|
@ -330,15 +341,16 @@ union rct_sprite {
|
|||
bool IsBalloon();
|
||||
bool IsDuck();
|
||||
bool IsPeep();
|
||||
rct_balloon * AsBalloon();
|
||||
rct_duck * AsDuck();
|
||||
rct_peep * AsPeep();
|
||||
rct_balloon* AsBalloon();
|
||||
rct_duck* AsDuck();
|
||||
rct_peep* AsPeep();
|
||||
};
|
||||
assert_struct_size(rct_sprite, 0x100);
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
SPRITE_MISC_STEAM_PARTICLE,
|
||||
SPRITE_MISC_MONEY_EFFECT,
|
||||
SPRITE_MISC_CRASHED_VEHICLE_PARTICLE,
|
||||
|
@ -351,13 +363,15 @@ enum {
|
|||
SPRITE_MISC_JUMPING_FOUNTAIN_SNOW
|
||||
};
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
SPRITE_FLAGS_IS_CRASHED_VEHICLE_SPRITE = 1 << 7,
|
||||
SPRITE_FLAGS_PEEP_VISIBLE = 1 << 8, // Peep is eligible to show in summarized guest list window (is inside park?)
|
||||
SPRITE_FLAGS_PEEP_VISIBLE = 1 << 8, // Peep is eligible to show in summarized guest list window (is inside park?)
|
||||
SPRITE_FLAGS_PEEP_FLASHING = 1 << 9, // Deprecated: Use sprite_set_flashing/sprite_get_flashing instead.
|
||||
};
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
LITTER_TYPE_SICK,
|
||||
LITTER_TYPE_SICK_ALT,
|
||||
LITTER_TYPE_EMPTY_CAN,
|
||||
|
@ -372,28 +386,27 @@ enum {
|
|||
LITTER_TYPE_EMPTY_BOWL_BLUE,
|
||||
};
|
||||
|
||||
rct_sprite *try_get_sprite(size_t spriteIndex);
|
||||
rct_sprite *get_sprite(size_t sprite_idx);
|
||||
rct_sprite* try_get_sprite(size_t spriteIndex);
|
||||
rct_sprite* get_sprite(size_t sprite_idx);
|
||||
|
||||
extern uint16_t gSpriteListHead[6];
|
||||
extern uint16_t gSpriteListCount[6];
|
||||
extern uint16_t gSpriteSpatialIndex[0x10001];
|
||||
|
||||
|
||||
extern const rct_string_id litterNames[12];
|
||||
|
||||
rct_sprite *create_sprite(uint8_t bl);
|
||||
rct_sprite* create_sprite(uint8_t bl);
|
||||
void reset_sprite_list();
|
||||
void reset_sprite_spatial_index();
|
||||
void sprite_clear_all_unused();
|
||||
void move_sprite_to_list(rct_sprite *sprite, uint8_t cl);
|
||||
void move_sprite_to_list(rct_sprite* sprite, uint8_t cl);
|
||||
void sprite_misc_update_all();
|
||||
void sprite_move(int16_t x, int16_t y, int16_t z, rct_sprite* sprite);
|
||||
void sprite_set_coordinates(int16_t x, int16_t y, int16_t z, rct_sprite *sprite);
|
||||
void sprite_set_coordinates(int16_t x, int16_t y, int16_t z, rct_sprite* sprite);
|
||||
void invalidate_sprite_0(rct_sprite* sprite);
|
||||
void invalidate_sprite_1(rct_sprite *sprite);
|
||||
void invalidate_sprite_2(rct_sprite *sprite);
|
||||
void sprite_remove(rct_sprite *sprite);
|
||||
void invalidate_sprite_1(rct_sprite* sprite);
|
||||
void invalidate_sprite_2(rct_sprite* sprite);
|
||||
void sprite_remove(rct_sprite* sprite);
|
||||
void litter_create(int32_t x, int32_t y, int32_t z, int32_t direction, int32_t type);
|
||||
void litter_remove_at(int32_t x, int32_t y, int32_t z);
|
||||
void sprite_misc_explosion_cloud_create(int32_t x, int32_t y, int32_t z);
|
||||
|
@ -409,38 +422,39 @@ void sprite_position_tween_reset();
|
|||
// Balloon
|
||||
///////////////////////////////////////////////////////////////
|
||||
void create_balloon(int32_t x, int32_t y, int32_t z, int32_t colour, bool isPopped);
|
||||
void balloon_update(rct_balloon *balloon);
|
||||
void game_command_balloon_press(int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
void balloon_update(rct_balloon* balloon);
|
||||
void game_command_balloon_press(
|
||||
int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Duck
|
||||
///////////////////////////////////////////////////////////////
|
||||
void create_duck(int32_t targetX, int32_t targetY);
|
||||
void duck_update(rct_duck *duck);
|
||||
void duck_press(rct_duck *duck);
|
||||
void duck_update(rct_duck* duck);
|
||||
void duck_press(rct_duck* duck);
|
||||
void duck_remove_all();
|
||||
uint32_t duck_get_frame_image(const rct_duck * duck, int32_t direction);
|
||||
uint32_t duck_get_frame_image(const rct_duck* duck, int32_t direction);
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Money effect
|
||||
///////////////////////////////////////////////////////////////
|
||||
void money_effect_create(money32 value);
|
||||
void money_effect_create_at(money32 value, int32_t x, int32_t y, int32_t z, bool vertical);
|
||||
void money_effect_update(rct_money_effect *moneyEffect);
|
||||
rct_string_id money_effect_get_string_id(const rct_money_effect * sprite, money32 * outValue);
|
||||
void money_effect_update(rct_money_effect* moneyEffect);
|
||||
rct_string_id money_effect_get_string_id(const rct_money_effect* sprite, money32* outValue);
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Crash particles
|
||||
///////////////////////////////////////////////////////////////
|
||||
void crashed_vehicle_particle_create(rct_vehicle_colour colours, int32_t x, int32_t y, int32_t z);
|
||||
void crashed_vehicle_particle_update(rct_crashed_vehicle_particle *particle);
|
||||
void crashed_vehicle_particle_update(rct_crashed_vehicle_particle* particle);
|
||||
void crash_splash_create(int32_t x, int32_t y, int32_t z);
|
||||
void crash_splash_update(rct_crash_splash *splash);
|
||||
void crash_splash_update(rct_crash_splash* splash);
|
||||
|
||||
const char *sprite_checksum();
|
||||
const char* sprite_checksum();
|
||||
|
||||
void sprite_set_flashing(rct_sprite *sprite, bool flashing);
|
||||
bool sprite_get_flashing(rct_sprite *sprite);
|
||||
void sprite_set_flashing(rct_sprite* sprite, bool flashing);
|
||||
bool sprite_get_flashing(rct_sprite* sprite);
|
||||
int32_t check_for_sprite_list_cycles(bool fix);
|
||||
int32_t check_for_spatial_index_cycles(bool fix);
|
||||
int32_t fix_disjoint_sprites();
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
#include "Surface.h"
|
||||
|
||||
int32_t surface_get_terrain(const rct_tile_element * element)
|
||||
int32_t surface_get_terrain(const rct_tile_element* element)
|
||||
{
|
||||
int32_t terrain = (element->properties.surface.terrain >> 5) & 7;
|
||||
if (element->type & 1)
|
||||
|
@ -17,7 +17,7 @@ int32_t surface_get_terrain(const rct_tile_element * element)
|
|||
return terrain;
|
||||
}
|
||||
|
||||
int32_t surface_get_terrain_edge(const rct_tile_element * element)
|
||||
int32_t surface_get_terrain_edge(const rct_tile_element* element)
|
||||
{
|
||||
int32_t terrain_edge = (element->properties.surface.slope >> 5) & 7;
|
||||
if (element->type & 128)
|
||||
|
@ -25,7 +25,7 @@ int32_t surface_get_terrain_edge(const rct_tile_element * element)
|
|||
return terrain_edge;
|
||||
}
|
||||
|
||||
void surface_set_terrain(rct_tile_element * element, int32_t terrain)
|
||||
void surface_set_terrain(rct_tile_element* element, int32_t terrain)
|
||||
{
|
||||
// Bit 3 for terrain is stored in element.type bit 0
|
||||
if (terrain & 8)
|
||||
|
@ -38,7 +38,7 @@ void surface_set_terrain(rct_tile_element * element, int32_t terrain)
|
|||
element->properties.surface.terrain |= (terrain & 7) << 5;
|
||||
}
|
||||
|
||||
void surface_set_terrain_edge(rct_tile_element * element, int32_t terrain)
|
||||
void surface_set_terrain_edge(rct_tile_element* element, int32_t terrain)
|
||||
{
|
||||
// Bit 3 for terrain is stored in element.type bit 7
|
||||
if (terrain & 8)
|
||||
|
@ -51,7 +51,7 @@ void surface_set_terrain_edge(rct_tile_element * element, int32_t terrain)
|
|||
element->properties.surface.slope |= (terrain & 7) << 5;
|
||||
}
|
||||
|
||||
int32_t surface_get_water_height(const rct_tile_element * tileElement)
|
||||
int32_t surface_get_water_height(const rct_tile_element* tileElement)
|
||||
{
|
||||
return tileElement->properties.surface.terrain & TILE_ELEMENT_SURFACE_WATER_HEIGHT_MASK;
|
||||
}
|
||||
|
|
|
@ -12,7 +12,8 @@
|
|||
#include "../common.h"
|
||||
#include "TileElement.h"
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
TERRAIN_GRASS,
|
||||
TERRAIN_SAND,
|
||||
TERRAIN_DIRT,
|
||||
|
@ -32,7 +33,8 @@ enum {
|
|||
TERRAIN_UNDERGROUND_VIEW,
|
||||
};
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
TERRAIN_EDGE_ROCK,
|
||||
TERRAIN_EDGE_WOOD_RED,
|
||||
TERRAIN_EDGE_WOOD_BLACK,
|
||||
|
@ -55,7 +57,8 @@ enum {
|
|||
TERRAIN_EDGE_COUNT
|
||||
};
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
GRASS_LENGTH_MOWED,
|
||||
GRASS_LENGTH_CLEAR_0,
|
||||
GRASS_LENGTH_CLEAR_1,
|
||||
|
@ -65,7 +68,8 @@ enum {
|
|||
GRASS_LENGTH_CLUMPS_2
|
||||
};
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
OWNERSHIP_UNOWNED = 0,
|
||||
OWNERSHIP_CONSTRUCTION_RIGHTS_OWNED = (1 << 4),
|
||||
OWNERSHIP_OWNED = (1 << 5),
|
||||
|
@ -73,7 +77,8 @@ enum {
|
|||
OWNERSHIP_AVAILABLE = (1 << 7)
|
||||
};
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
TILE_ELEMENT_SLOPE_FLAT = 0x00,
|
||||
TILE_ELEMENT_SLOPE_ALL_CORNERS_UP = 0x0F,
|
||||
|
||||
|
@ -98,17 +103,19 @@ enum {
|
|||
};
|
||||
|
||||
// Surface
|
||||
#define TILE_ELEMENT_SURFACE_DIAGONAL_FLAG 0x10 // in rct_tile_element.properties.surface.slope
|
||||
#define TILE_ELEMENT_SURFACE_DIAGONAL_FLAG 0x10 // in rct_tile_element.properties.surface.slope
|
||||
#define TILE_ELEMENT_SURFACE_RAISED_CORNERS_MASK 0x0F // in rct_tile_element.properties.surface.slope
|
||||
#define TILE_ELEMENT_SURFACE_SLOPE_MASK (TILE_ELEMENT_SURFACE_DIAGONAL_FLAG | TILE_ELEMENT_SURFACE_RAISED_CORNERS_MASK) // in rct_tile_element.properties.surface.slope
|
||||
#define TILE_ELEMENT_SURFACE_EDGE_STYLE_MASK 0xE0 // in rct_tile_tile_element_set_terrainelement.properties.surface.slope
|
||||
#define TILE_ELEMENT_SURFACE_WATER_HEIGHT_MASK 0x1F // in rct_tile_element.properties.surface.terrain
|
||||
#define TILE_ELEMENT_SURFACE_TERRAIN_MASK 0xE0 // in rct_tile_element.properties.surface.terrain
|
||||
#define TILE_ELEMENT_SURFACE_SLOPE_MASK \
|
||||
(TILE_ELEMENT_SURFACE_DIAGONAL_FLAG \
|
||||
| TILE_ELEMENT_SURFACE_RAISED_CORNERS_MASK) // in rct_tile_element.properties.surface.slope
|
||||
#define TILE_ELEMENT_SURFACE_EDGE_STYLE_MASK 0xE0 // in rct_tile_tile_element_set_terrainelement.properties.surface.slope
|
||||
#define TILE_ELEMENT_SURFACE_WATER_HEIGHT_MASK 0x1F // in rct_tile_element.properties.surface.terrain
|
||||
#define TILE_ELEMENT_SURFACE_TERRAIN_MASK 0xE0 // in rct_tile_element.properties.surface.terrain
|
||||
|
||||
int32_t surface_get_terrain(const rct_tile_element * element);
|
||||
int32_t surface_get_terrain_edge(const rct_tile_element * element);
|
||||
void surface_set_terrain(rct_tile_element * element, int32_t terrain);
|
||||
void surface_set_terrain_edge(rct_tile_element * element, int32_t terrain);
|
||||
int32_t surface_get_terrain(const rct_tile_element* element);
|
||||
int32_t surface_get_terrain_edge(const rct_tile_element* element);
|
||||
void surface_set_terrain(rct_tile_element* element, int32_t terrain);
|
||||
void surface_set_terrain_edge(rct_tile_element* element, int32_t terrain);
|
||||
|
||||
// ~Oli414: Needs to renamed. This function is specific to the surface object.
|
||||
int32_t surface_get_water_height(const rct_tile_element * tileElement);
|
||||
int32_t surface_get_water_height(const rct_tile_element* tileElement);
|
||||
|
|
|
@ -7,13 +7,14 @@
|
|||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "TileElement.h"
|
||||
|
||||
#include "../core/Guard.hpp"
|
||||
#include "../interface/Window.h"
|
||||
#include "../localisation/Localisation.h"
|
||||
#include "../ride/Track.h"
|
||||
#include "Banner.h"
|
||||
#include "LargeScenery.h"
|
||||
#include "TileElement.h"
|
||||
#include "Scenery.h"
|
||||
|
||||
uint8_t rct_tile_element::GetType() const
|
||||
|
@ -58,24 +59,25 @@ uint8_t rct_tile_element::GetSceneryQuadrant() const
|
|||
return (this->type & TILE_ELEMENT_QUADRANT_MASK) >> 6;
|
||||
}
|
||||
|
||||
int32_t tile_element_get_direction(const rct_tile_element * element)
|
||||
int32_t tile_element_get_direction(const rct_tile_element* element)
|
||||
{
|
||||
return element->GetDirection();
|
||||
}
|
||||
|
||||
int32_t tile_element_get_direction_with_offset(const rct_tile_element * element, uint8_t offset)
|
||||
int32_t tile_element_get_direction_with_offset(const rct_tile_element* element, uint8_t offset)
|
||||
{
|
||||
return element->GetDirectionWithOffset(offset);
|
||||
}
|
||||
|
||||
bool tile_element_is_ghost(const rct_tile_element * element)
|
||||
bool tile_element_is_ghost(const rct_tile_element* element)
|
||||
{
|
||||
return element->IsGhost();
|
||||
}
|
||||
|
||||
bool tile_element_is_underground(rct_tile_element * tileElement)
|
||||
bool tile_element_is_underground(rct_tile_element* tileElement)
|
||||
{
|
||||
do {
|
||||
do
|
||||
{
|
||||
tileElement++;
|
||||
if ((tileElement - 1)->IsLastForTile())
|
||||
return false;
|
||||
|
@ -87,23 +89,24 @@ BannerIndex tile_element_get_banner_index(rct_tile_element* tileElement)
|
|||
{
|
||||
rct_scenery_entry* sceneryEntry;
|
||||
|
||||
switch (tileElement->GetType()) {
|
||||
case TILE_ELEMENT_TYPE_LARGE_SCENERY:
|
||||
sceneryEntry = get_large_scenery_entry(scenery_large_get_type(tileElement));
|
||||
if (sceneryEntry->large_scenery.scrolling_mode == 0xFF)
|
||||
return BANNER_INDEX_NULL;
|
||||
switch (tileElement->GetType())
|
||||
{
|
||||
case TILE_ELEMENT_TYPE_LARGE_SCENERY:
|
||||
sceneryEntry = get_large_scenery_entry(scenery_large_get_type(tileElement));
|
||||
if (sceneryEntry->large_scenery.scrolling_mode == 0xFF)
|
||||
return BANNER_INDEX_NULL;
|
||||
|
||||
return scenery_large_get_banner_id(tileElement);
|
||||
case TILE_ELEMENT_TYPE_WALL:
|
||||
sceneryEntry = get_wall_entry(tileElement->properties.wall.type);
|
||||
if (sceneryEntry == nullptr || sceneryEntry->wall.scrolling_mode == 0xFF)
|
||||
return BANNER_INDEX_NULL;
|
||||
return scenery_large_get_banner_id(tileElement);
|
||||
case TILE_ELEMENT_TYPE_WALL:
|
||||
sceneryEntry = get_wall_entry(tileElement->properties.wall.type);
|
||||
if (sceneryEntry == nullptr || sceneryEntry->wall.scrolling_mode == 0xFF)
|
||||
return BANNER_INDEX_NULL;
|
||||
|
||||
return tileElement->properties.wall.banner_index;
|
||||
case TILE_ELEMENT_TYPE_BANNER:
|
||||
return tileElement->properties.banner.index;
|
||||
default:
|
||||
return BANNER_INDEX_NULL;
|
||||
return tileElement->properties.wall.banner_index;
|
||||
case TILE_ELEMENT_TYPE_BANNER:
|
||||
return tileElement->properties.banner.index;
|
||||
default:
|
||||
return BANNER_INDEX_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,29 +114,30 @@ void tile_element_set_banner_index(rct_tile_element* tileElement, BannerIndex ba
|
|||
{
|
||||
switch (tileElement->GetType())
|
||||
{
|
||||
case TILE_ELEMENT_TYPE_WALL:
|
||||
tileElement->properties.wall.banner_index = bannerIndex;
|
||||
break;
|
||||
case TILE_ELEMENT_TYPE_LARGE_SCENERY:
|
||||
scenery_large_set_banner_id(tileElement, bannerIndex);
|
||||
break;
|
||||
case TILE_ELEMENT_TYPE_BANNER:
|
||||
tileElement->properties.banner.index = bannerIndex;
|
||||
break;
|
||||
default:
|
||||
log_error("Tried to set banner index on unsuitable tile element!");
|
||||
Guard::Assert(false);
|
||||
case TILE_ELEMENT_TYPE_WALL:
|
||||
tileElement->properties.wall.banner_index = bannerIndex;
|
||||
break;
|
||||
case TILE_ELEMENT_TYPE_LARGE_SCENERY:
|
||||
scenery_large_set_banner_id(tileElement, bannerIndex);
|
||||
break;
|
||||
case TILE_ELEMENT_TYPE_BANNER:
|
||||
tileElement->properties.banner.index = bannerIndex;
|
||||
break;
|
||||
default:
|
||||
log_error("Tried to set banner index on unsuitable tile element!");
|
||||
Guard::Assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
void tile_element_remove_banner_entry(rct_tile_element * tileElement)
|
||||
void tile_element_remove_banner_entry(rct_tile_element* tileElement)
|
||||
{
|
||||
BannerIndex bannerIndex = tile_element_get_banner_index(tileElement);
|
||||
if (bannerIndex == BANNER_INDEX_NULL)
|
||||
return;
|
||||
|
||||
rct_banner* banner = &gBanners[bannerIndex];
|
||||
if (banner->type != BANNER_NULL) {
|
||||
if (banner->type != BANNER_NULL)
|
||||
{
|
||||
rct_windownumber windowNumber = bannerIndex;
|
||||
window_close_by_number(WC_BANNER, windowNumber);
|
||||
banner->type = BANNER_NULL;
|
||||
|
@ -141,17 +145,17 @@ void tile_element_remove_banner_entry(rct_tile_element * tileElement)
|
|||
}
|
||||
}
|
||||
|
||||
uint8_t tile_element_get_ride_index(const rct_tile_element * tileElement)
|
||||
uint8_t tile_element_get_ride_index(const rct_tile_element* tileElement)
|
||||
{
|
||||
switch (tileElement->GetType())
|
||||
{
|
||||
case TILE_ELEMENT_TYPE_TRACK:
|
||||
return track_element_get_ride_index(tileElement);
|
||||
case TILE_ELEMENT_TYPE_ENTRANCE:
|
||||
return tileElement->properties.entrance.ride_index;
|
||||
case TILE_ELEMENT_TYPE_PATH:
|
||||
return tileElement->properties.path.ride_index;
|
||||
default:
|
||||
return 0xFF;
|
||||
case TILE_ELEMENT_TYPE_TRACK:
|
||||
return track_element_get_ride_index(tileElement);
|
||||
case TILE_ELEMENT_TYPE_ENTRANCE:
|
||||
return tileElement->properties.entrance.ride_index;
|
||||
case TILE_ELEMENT_TYPE_PATH:
|
||||
return tileElement->properties.path.ride_index;
|
||||
default:
|
||||
return 0xFF;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,29 +12,35 @@
|
|||
#include "../common.h"
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct rct_tile_element_surface_properties {
|
||||
uint8_t slope; //4 0xE0 Edge Style, 0x1F Slope
|
||||
uint8_t terrain; //5 0xE0 Terrain Style, 0x1F Water height
|
||||
uint8_t grass_length; //6
|
||||
uint8_t ownership; //7
|
||||
struct rct_tile_element_surface_properties
|
||||
{
|
||||
uint8_t slope; // 4 0xE0 Edge Style, 0x1F Slope
|
||||
uint8_t terrain; // 5 0xE0 Terrain Style, 0x1F Water height
|
||||
uint8_t grass_length; // 6
|
||||
uint8_t ownership; // 7
|
||||
};
|
||||
assert_struct_size(rct_tile_element_surface_properties, 4);
|
||||
|
||||
struct rct_tile_element_path_properties {
|
||||
uint8_t type; //4 0xF0 Path type, 0x08 Ride sign, 0x04 Set when path is diagonal, 0x03 Rotation
|
||||
uint8_t additions; //5
|
||||
uint8_t edges; //6
|
||||
union {
|
||||
uint8_t addition_status; //7
|
||||
struct rct_tile_element_path_properties
|
||||
{
|
||||
uint8_t type; // 4 0xF0 Path type, 0x08 Ride sign, 0x04 Set when path is diagonal, 0x03 Rotation
|
||||
uint8_t additions; // 5
|
||||
uint8_t edges; // 6
|
||||
union
|
||||
{
|
||||
uint8_t addition_status; // 7
|
||||
uint8_t ride_index;
|
||||
};
|
||||
};
|
||||
assert_struct_size(rct_tile_element_path_properties, 4);
|
||||
|
||||
struct rct_tile_element_track_properties {
|
||||
uint8_t type; //4
|
||||
union {
|
||||
struct {
|
||||
struct rct_tile_element_track_properties
|
||||
{
|
||||
uint8_t type; // 4
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
// The lower 4 bits are the track sequence.
|
||||
// The upper 4 bits are either station bits or on-ride photo bits.
|
||||
//
|
||||
|
@ -46,57 +52,64 @@ struct rct_tile_element_track_properties {
|
|||
// - Bits 7 and 8 are never set
|
||||
// - Bits 5 and 6 are set when a vehicle triggers the on-ride photo and act like a countdown from 3.
|
||||
// - If any of the bits 5-8 are set, the game counts it as a photo being taken.
|
||||
uint8_t sequence; //5.
|
||||
uint8_t colour; //6
|
||||
uint8_t sequence; // 5.
|
||||
uint8_t colour; // 6
|
||||
};
|
||||
uint16_t maze_entry; // 5
|
||||
};
|
||||
uint8_t ride_index; //7
|
||||
uint8_t ride_index; // 7
|
||||
};
|
||||
assert_struct_size(rct_tile_element_track_properties, 4);
|
||||
|
||||
struct rct_tile_element_scenery_properties {
|
||||
uint8_t type; //4
|
||||
uint8_t age; //5
|
||||
uint8_t colour_1; //6
|
||||
uint8_t colour_2; //7
|
||||
struct rct_tile_element_scenery_properties
|
||||
{
|
||||
uint8_t type; // 4
|
||||
uint8_t age; // 5
|
||||
uint8_t colour_1; // 6
|
||||
uint8_t colour_2; // 7
|
||||
};
|
||||
assert_struct_size(rct_tile_element_scenery_properties, 4);
|
||||
|
||||
struct rct_tile_element_entrance_properties {
|
||||
uint8_t type; //4
|
||||
uint8_t index; //5
|
||||
uint8_t path_type; //6
|
||||
uint8_t ride_index; //7
|
||||
struct rct_tile_element_entrance_properties
|
||||
{
|
||||
uint8_t type; // 4
|
||||
uint8_t index; // 5
|
||||
uint8_t path_type; // 6
|
||||
uint8_t ride_index; // 7
|
||||
};
|
||||
assert_struct_size(rct_tile_element_entrance_properties, 4);
|
||||
|
||||
struct rct_tile_element_wall_properties {
|
||||
uint8_t type; //4
|
||||
union {
|
||||
uint8_t colour_3; //5
|
||||
struct rct_tile_element_wall_properties
|
||||
{
|
||||
uint8_t type; // 4
|
||||
union
|
||||
{
|
||||
uint8_t colour_3; // 5
|
||||
BannerIndex banner_index; // 5
|
||||
};
|
||||
uint8_t colour_1; //6 0b_2221_1111 2 = colour_2 (uses flags for rest of colour2), 1 = colour_1
|
||||
uint8_t animation; //7 0b_dfff_ft00 d = direction, f = frame num, t = across track flag (not used)
|
||||
uint8_t colour_1; // 6 0b_2221_1111 2 = colour_2 (uses flags for rest of colour2), 1 = colour_1
|
||||
uint8_t animation; // 7 0b_dfff_ft00 d = direction, f = frame num, t = across track flag (not used)
|
||||
};
|
||||
assert_struct_size(rct_tile_element_wall_properties, 4);
|
||||
|
||||
struct rct_tile_element_scenerymultiple_properties {
|
||||
uint16_t type; //4
|
||||
uint8_t colour[2]; //6
|
||||
struct rct_tile_element_scenerymultiple_properties
|
||||
{
|
||||
uint16_t type; // 4
|
||||
uint8_t colour[2]; // 6
|
||||
};
|
||||
assert_struct_size(rct_tile_element_scenerymultiple_properties, 4);
|
||||
|
||||
struct rct_tile_element_banner_properties {
|
||||
struct rct_tile_element_banner_properties
|
||||
{
|
||||
BannerIndex index; // 4
|
||||
uint8_t position; //5
|
||||
uint8_t flags; //6
|
||||
uint8_t unused; //7
|
||||
uint8_t position; // 5
|
||||
uint8_t flags; // 6
|
||||
uint8_t unused; // 7
|
||||
};
|
||||
assert_struct_size(rct_tile_element_banner_properties, 4);
|
||||
|
||||
union rct_tile_element_properties {
|
||||
union rct_tile_element_properties
|
||||
{
|
||||
rct_tile_element_surface_properties surface;
|
||||
rct_tile_element_path_properties path;
|
||||
rct_tile_element_track_properties track;
|
||||
|
@ -109,36 +122,39 @@ union rct_tile_element_properties {
|
|||
assert_struct_size(rct_tile_element_properties, 4);
|
||||
|
||||
/**
|
||||
* Map element structure
|
||||
* size: 0x08
|
||||
*/
|
||||
struct rct_tile_element {
|
||||
uint8_t type; //0
|
||||
uint8_t flags; //1
|
||||
uint8_t base_height; //2
|
||||
uint8_t clearance_height; //3
|
||||
* Map element structure
|
||||
* size: 0x08
|
||||
*/
|
||||
struct rct_tile_element
|
||||
{
|
||||
uint8_t type; // 0
|
||||
uint8_t flags; // 1
|
||||
uint8_t base_height; // 2
|
||||
uint8_t clearance_height; // 3
|
||||
rct_tile_element_properties properties;
|
||||
|
||||
uint8_t GetType() const;
|
||||
void SetType(uint8_t newType);
|
||||
void SetType(uint8_t newType);
|
||||
uint8_t GetDirection() const;
|
||||
void SetDirection(uint8_t direction);
|
||||
void SetDirection(uint8_t direction);
|
||||
uint8_t GetDirectionWithOffset(uint8_t offset) const;
|
||||
bool IsLastForTile() const;
|
||||
bool IsGhost() const;
|
||||
bool IsLastForTile() const;
|
||||
bool IsGhost() const;
|
||||
uint8_t GetSceneryQuadrant() const;
|
||||
};
|
||||
assert_struct_size(rct_tile_element, 8);
|
||||
#pragma pack(pop)
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
TILE_ELEMENT_QUADRANT_SW,
|
||||
TILE_ELEMENT_QUADRANT_NW,
|
||||
TILE_ELEMENT_QUADRANT_NE,
|
||||
TILE_ELEMENT_QUADRANT_SE
|
||||
};
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
TILE_ELEMENT_TYPE_SURFACE = (0 << 2),
|
||||
TILE_ELEMENT_TYPE_PATH = (1 << 2),
|
||||
TILE_ELEMENT_TYPE_TRACK = (2 << 2),
|
||||
|
@ -152,18 +168,21 @@ enum {
|
|||
TILE_ELEMENT_TYPE_CORRUPT = (8 << 2),
|
||||
};
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
TILE_ELEMENT_TYPE_FLAG_HIGHLIGHT = (1 << 6)
|
||||
};
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
TILE_ELEMENT_DIRECTION_WEST,
|
||||
TILE_ELEMENT_DIRECTION_NORTH,
|
||||
TILE_ELEMENT_DIRECTION_EAST,
|
||||
TILE_ELEMENT_DIRECTION_SOUTH
|
||||
};
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
TILE_ELEMENT_FLAG_GHOST = (1 << 4),
|
||||
TILE_ELEMENT_FLAG_BROKEN = (1 << 5),
|
||||
TILE_ELEMENT_FLAG_BLOCK_BRAKE_CLOSED = (1 << 5),
|
||||
|
@ -172,13 +191,15 @@ enum {
|
|||
TILE_ELEMENT_FLAG_LAST_TILE = (1 << 7)
|
||||
};
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
ENTRANCE_TYPE_RIDE_ENTRANCE,
|
||||
ENTRANCE_TYPE_RIDE_EXIT,
|
||||
ENTRANCE_TYPE_PARK_ENTRANCE
|
||||
};
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
ELEMENT_IS_ABOVE_GROUND = 1 << 0,
|
||||
ELEMENT_IS_UNDERGROUND = 1 << 1,
|
||||
ELEMENT_IS_UNDERWATER = 1 << 2,
|
||||
|
@ -189,27 +210,25 @@ enum
|
|||
MAP_ELEM_TRACK_SEQUENCE_GREEN_LIGHT = (1 << 7),
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define TILE_ELEMENT_QUADRANT_MASK 0b11000000
|
||||
#define TILE_ELEMENT_TYPE_MASK 0b00111100
|
||||
#define TILE_ELEMENT_QUADRANT_MASK 0b11000000
|
||||
#define TILE_ELEMENT_TYPE_MASK 0b00111100
|
||||
#define TILE_ELEMENT_DIRECTION_MASK 0b00000011
|
||||
|
||||
#define TILE_ELEMENT_COLOUR_MASK 0b00011111
|
||||
#define TILE_ELEMENT_COLOUR_MASK 0b00011111
|
||||
|
||||
#define MAP_ELEM_TRACK_SEQUENCE_STATION_INDEX_MASK 0b01110000
|
||||
#define MAP_ELEM_TRACK_SEQUENCE_SEQUENCE_MASK 0b00001111
|
||||
#define MAP_ELEM_TRACK_SEQUENCE_TAKING_PHOTO_MASK 0b11110000
|
||||
#define MAP_ELEM_TRACK_SEQUENCE_SEQUENCE_MASK 0b00001111
|
||||
#define MAP_ELEM_TRACK_SEQUENCE_TAKING_PHOTO_MASK 0b11110000
|
||||
|
||||
int32_t tile_element_get_direction(const rct_tile_element * element);
|
||||
int32_t tile_element_get_direction_with_offset(const rct_tile_element * element, uint8_t offset);
|
||||
int32_t tile_element_get_direction(const rct_tile_element* element);
|
||||
int32_t tile_element_get_direction_with_offset(const rct_tile_element* element, uint8_t offset);
|
||||
BannerIndex tile_element_get_banner_index(rct_tile_element* tileElement);
|
||||
bool tile_element_is_ghost(const rct_tile_element * element);
|
||||
bool tile_element_is_underground(rct_tile_element * tileElement);
|
||||
bool tile_element_is_last_for_tile(const rct_tile_element *element);
|
||||
bool tile_element_is_ghost(const rct_tile_element* element);
|
||||
bool tile_element_is_underground(rct_tile_element* tileElement);
|
||||
bool tile_element_is_last_for_tile(const rct_tile_element* element);
|
||||
|
||||
// ~Oli414: The banner functions should probably be part of banner.
|
||||
void tile_element_set_banner_index(rct_tile_element* tileElement, BannerIndex bannerIndex);
|
||||
void tile_element_remove_banner_entry(rct_tile_element *tileElement);
|
||||
void tile_element_remove_banner_entry(rct_tile_element* tileElement);
|
||||
|
||||
uint8_t tile_element_get_ride_index(const rct_tile_element * tileElement);
|
||||
uint8_t tile_element_get_ride_index(const rct_tile_element* tileElement);
|
||||
|
|
|
@ -7,24 +7,25 @@
|
|||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "Banner.h"
|
||||
#include "../common.h"
|
||||
#include "TileInspector.h"
|
||||
|
||||
#include "../Context.h"
|
||||
#include "../Game.h"
|
||||
#include "../common.h"
|
||||
#include "../core/Guard.hpp"
|
||||
#include "../interface/Window.h"
|
||||
#include "../localisation/Localisation.h"
|
||||
#include "../ride/Station.h"
|
||||
#include "../ride/Track.h"
|
||||
#include "../windows/Intent.h"
|
||||
#include "../windows/tile_inspector.h"
|
||||
#include "Banner.h"
|
||||
#include "Footpath.h"
|
||||
#include "LargeScenery.h"
|
||||
#include "Map.h"
|
||||
#include "Park.h"
|
||||
#include "Scenery.h"
|
||||
#include "Surface.h"
|
||||
#include "TileInspector.h"
|
||||
#include "../ride/Station.h"
|
||||
#include "Park.h"
|
||||
|
||||
using namespace OpenRCT2;
|
||||
|
||||
|
@ -35,8 +36,8 @@ int32_t windowTileInspectorSelectedIndex;
|
|||
|
||||
static bool map_swap_elements_at(int32_t x, int32_t y, int16_t first, int16_t second)
|
||||
{
|
||||
rct_tile_element * const firstElement = map_get_nth_element_at(x, y, first);
|
||||
rct_tile_element * const secondElement = map_get_nth_element_at(x, y, second);
|
||||
rct_tile_element* const firstElement = map_get_nth_element_at(x, y, first);
|
||||
rct_tile_element* const secondElement = map_get_nth_element_at(x, y, second);
|
||||
|
||||
if (firstElement == nullptr)
|
||||
{
|
||||
|
@ -56,8 +57,8 @@ static bool map_swap_elements_at(int32_t x, int32_t y, int16_t first, int16_t se
|
|||
|
||||
// Swap their memory
|
||||
rct_tile_element temp = *firstElement;
|
||||
*firstElement = *secondElement;
|
||||
*secondElement = temp;
|
||||
*firstElement = *secondElement;
|
||||
*secondElement = temp;
|
||||
|
||||
// Swap the 'last map element for tile' flag if either one of them was last
|
||||
if ((firstElement)->IsLastForTile() || (secondElement)->IsLastForTile())
|
||||
|
@ -85,7 +86,7 @@ int32_t tile_inspector_insert_corrupt_at(int32_t x, int32_t y, int16_t elementIn
|
|||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
||||
{
|
||||
// Create new corrupt element
|
||||
rct_tile_element * corruptElement = tile_element_insert(x, y, -1, 0); // Ugly hack: -1 guarantees this to be placed first
|
||||
rct_tile_element* corruptElement = tile_element_insert(x, y, -1, 0); // Ugly hack: -1 guarantees this to be placed first
|
||||
if (corruptElement == nullptr)
|
||||
{
|
||||
log_warning("Failed to insert corrupt element.");
|
||||
|
@ -94,7 +95,7 @@ int32_t tile_inspector_insert_corrupt_at(int32_t x, int32_t y, int16_t elementIn
|
|||
corruptElement->type = TILE_ELEMENT_TYPE_CORRUPT;
|
||||
|
||||
// Set the base height to be the same as the selected element
|
||||
rct_tile_element * const selectedElement = map_get_nth_element_at(x, y, elementIndex + 1);
|
||||
rct_tile_element* const selectedElement = map_get_nth_element_at(x, y, elementIndex + 1);
|
||||
if (!selectedElement)
|
||||
{
|
||||
return MONEY32_UNDEFINED;
|
||||
|
@ -117,8 +118,9 @@ int32_t tile_inspector_insert_corrupt_at(int32_t x, int32_t y, int16_t elementIn
|
|||
map_invalidate_tile_full(x << 5, y << 5);
|
||||
|
||||
// Update the tile inspector's list for everyone who has the tile selected
|
||||
rct_window * const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX && (uint32_t)y == windowTileInspectorTileY)
|
||||
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX
|
||||
&& (uint32_t)y == windowTileInspectorTileY)
|
||||
{
|
||||
windowTileInspectorElementCount++;
|
||||
|
||||
|
@ -147,7 +149,7 @@ int32_t tile_inspector_remove_element_at(int32_t x, int32_t y, int16_t elementIn
|
|||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
||||
{
|
||||
// Forcefully remove the element
|
||||
rct_tile_element * const tileElement = map_get_nth_element_at(x, y, elementIndex);
|
||||
rct_tile_element* const tileElement = map_get_nth_element_at(x, y, elementIndex);
|
||||
if (!tileElement)
|
||||
{
|
||||
return MONEY32_UNDEFINED;
|
||||
|
@ -156,8 +158,9 @@ int32_t tile_inspector_remove_element_at(int32_t x, int32_t y, int16_t elementIn
|
|||
map_invalidate_tile_full(x << 5, y << 5);
|
||||
|
||||
// Update the window
|
||||
rct_window * const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX && (uint32_t)y == windowTileInspectorTileY)
|
||||
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX
|
||||
&& (uint32_t)y == windowTileInspectorTileY)
|
||||
{
|
||||
windowTileInspectorElementCount--;
|
||||
|
||||
|
@ -188,8 +191,9 @@ int32_t tile_inspector_swap_elements_at(int32_t x, int32_t y, int16_t first, int
|
|||
map_invalidate_tile_full(x << 5, y << 5);
|
||||
|
||||
// Update the window
|
||||
rct_window * const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX && (uint32_t)y == windowTileInspectorTileY)
|
||||
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX
|
||||
&& (uint32_t)y == windowTileInspectorTileY)
|
||||
{
|
||||
// If one of them was selected, update selected list item
|
||||
if (windowTileInspectorSelectedIndex == first)
|
||||
|
@ -210,69 +214,69 @@ int32_t tile_inspector_rotate_element_at(int32_t x, int32_t y, int32_t elementIn
|
|||
{
|
||||
uint8_t newRotation, pathEdges, pathCorners;
|
||||
|
||||
rct_tile_element * const tileElement = map_get_nth_element_at(x, y, elementIndex);
|
||||
rct_tile_element* const tileElement = map_get_nth_element_at(x, y, elementIndex);
|
||||
if (!tileElement)
|
||||
{
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
switch (tileElement->GetType())
|
||||
{
|
||||
case TILE_ELEMENT_TYPE_PATH:
|
||||
if (footpath_element_is_sloped(tileElement))
|
||||
case TILE_ELEMENT_TYPE_PATH:
|
||||
if (footpath_element_is_sloped(tileElement))
|
||||
{
|
||||
newRotation = (footpath_element_get_slope_direction(tileElement) + 1) & TILE_ELEMENT_DIRECTION_MASK;
|
||||
tileElement->properties.path.type &= ~TILE_ELEMENT_DIRECTION_MASK;
|
||||
tileElement->properties.path.type |= newRotation;
|
||||
}
|
||||
pathEdges = tileElement->properties.path.edges & 0x0F;
|
||||
pathCorners = tileElement->properties.path.edges & 0xF0;
|
||||
tileElement->properties.path.edges = 0;
|
||||
tileElement->properties.path.edges |= ((pathEdges << 1) | (pathEdges >> 3)) & 0x0F;
|
||||
tileElement->properties.path.edges |= ((pathCorners << 1) | (pathCorners >> 3)) & 0xF0;
|
||||
break;
|
||||
case TILE_ELEMENT_TYPE_ENTRANCE:
|
||||
{
|
||||
newRotation = (footpath_element_get_slope_direction(tileElement) + 1) & TILE_ELEMENT_DIRECTION_MASK;
|
||||
tileElement->properties.path.type &= ~TILE_ELEMENT_DIRECTION_MASK;
|
||||
tileElement->properties.path.type |= newRotation;
|
||||
}
|
||||
pathEdges = tileElement->properties.path.edges & 0x0F;
|
||||
pathCorners = tileElement->properties.path.edges & 0xF0;
|
||||
tileElement->properties.path.edges = 0;
|
||||
tileElement->properties.path.edges |= ((pathEdges << 1) | (pathEdges >> 3)) & 0x0F;
|
||||
tileElement->properties.path.edges |= ((pathCorners << 1) | (pathCorners >> 3)) & 0xF0;
|
||||
break;
|
||||
case TILE_ELEMENT_TYPE_ENTRANCE:
|
||||
{
|
||||
// Update element rotation
|
||||
newRotation = tile_element_get_direction_with_offset(tileElement, 1);
|
||||
tileElement->type &= ~TILE_ELEMENT_DIRECTION_MASK;
|
||||
tileElement->type |= newRotation;
|
||||
// Update element rotation
|
||||
newRotation = tile_element_get_direction_with_offset(tileElement, 1);
|
||||
tileElement->type &= ~TILE_ELEMENT_DIRECTION_MASK;
|
||||
tileElement->type |= newRotation;
|
||||
|
||||
// Update ride's known entrance/exit rotation
|
||||
Ride * ride = get_ride(tileElement->properties.entrance.ride_index);
|
||||
uint8_t stationIndex = tileElement->properties.entrance.index;
|
||||
auto entrance = ride_get_entrance_location(ride, stationIndex);
|
||||
auto exit = ride_get_exit_location(ride, stationIndex);
|
||||
uint8_t entranceType = entrance_element_get_type(tileElement);
|
||||
uint8_t z = tileElement->base_height;
|
||||
// Update ride's known entrance/exit rotation
|
||||
Ride* ride = get_ride(tileElement->properties.entrance.ride_index);
|
||||
uint8_t stationIndex = tileElement->properties.entrance.index;
|
||||
auto entrance = ride_get_entrance_location(ride, stationIndex);
|
||||
auto exit = ride_get_exit_location(ride, stationIndex);
|
||||
uint8_t entranceType = entrance_element_get_type(tileElement);
|
||||
uint8_t z = tileElement->base_height;
|
||||
|
||||
// Make sure this is the correct entrance or exit
|
||||
if (entranceType == ENTRANCE_TYPE_RIDE_ENTRANCE && entrance.x == x && entrance.y == y && entrance.z == z)
|
||||
{
|
||||
ride_set_entrance_location(ride, stationIndex, { entrance.x, entrance.y, entrance.z, newRotation });
|
||||
// Make sure this is the correct entrance or exit
|
||||
if (entranceType == ENTRANCE_TYPE_RIDE_ENTRANCE && entrance.x == x && entrance.y == y && entrance.z == z)
|
||||
{
|
||||
ride_set_entrance_location(ride, stationIndex, { entrance.x, entrance.y, entrance.z, newRotation });
|
||||
}
|
||||
else if (entranceType == ENTRANCE_TYPE_RIDE_EXIT && exit.x == x && exit.y == y && exit.z == z)
|
||||
{
|
||||
ride_set_exit_location(ride, stationIndex, { exit.x, exit.y, exit.z, newRotation });
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (entranceType == ENTRANCE_TYPE_RIDE_EXIT && exit.x == x && exit.y == y && exit.z == z)
|
||||
case TILE_ELEMENT_TYPE_TRACK:
|
||||
case TILE_ELEMENT_TYPE_SMALL_SCENERY:
|
||||
case TILE_ELEMENT_TYPE_WALL:
|
||||
newRotation = tile_element_get_direction_with_offset(tileElement, 1);
|
||||
tileElement->type &= ~TILE_ELEMENT_DIRECTION_MASK;
|
||||
tileElement->type |= newRotation;
|
||||
break;
|
||||
case TILE_ELEMENT_TYPE_BANNER:
|
||||
{
|
||||
ride_set_exit_location(ride, stationIndex, { exit.x, exit.y, exit.z, newRotation });
|
||||
uint8_t unblockedEdges = tileElement->properties.banner.flags & 0xF;
|
||||
unblockedEdges = (unblockedEdges << 1 | unblockedEdges >> 3) & 0xF;
|
||||
tileElement->properties.banner.flags &= ~0xF;
|
||||
tileElement->properties.banner.flags |= unblockedEdges;
|
||||
tileElement->properties.banner.position++;
|
||||
tileElement->properties.banner.position &= 3;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TILE_ELEMENT_TYPE_TRACK:
|
||||
case TILE_ELEMENT_TYPE_SMALL_SCENERY:
|
||||
case TILE_ELEMENT_TYPE_WALL:
|
||||
newRotation = tile_element_get_direction_with_offset(tileElement, 1);
|
||||
tileElement->type &= ~TILE_ELEMENT_DIRECTION_MASK;
|
||||
tileElement->type |= newRotation;
|
||||
break;
|
||||
case TILE_ELEMENT_TYPE_BANNER:
|
||||
{
|
||||
uint8_t unblockedEdges = tileElement->properties.banner.flags & 0xF;
|
||||
unblockedEdges = (unblockedEdges << 1 | unblockedEdges >> 3) & 0xF;
|
||||
tileElement->properties.banner.flags &= ~0xF;
|
||||
tileElement->properties.banner.flags |= unblockedEdges;
|
||||
tileElement->properties.banner.position++;
|
||||
tileElement->properties.banner.position &= 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
map_invalidate_tile_full(x << 5, y << 5);
|
||||
|
@ -306,10 +310,10 @@ int32_t tile_inspector_paste_element_at(int32_t x, int32_t y, rct_tile_element e
|
|||
{
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
rct_banner & newBanner = gBanners[newBannerIndex];
|
||||
newBanner = gBanners[bannerIndex];
|
||||
newBanner.x = x;
|
||||
newBanner.y = y;
|
||||
rct_banner& newBanner = gBanners[newBannerIndex];
|
||||
newBanner = gBanners[bannerIndex];
|
||||
newBanner.x = x;
|
||||
newBanner.y = y;
|
||||
|
||||
// Use the new banner index
|
||||
tile_element_set_banner_index(&element, newBannerIndex);
|
||||
|
@ -329,10 +333,10 @@ int32_t tile_inspector_paste_element_at(int32_t x, int32_t y, rct_tile_element e
|
|||
}
|
||||
}
|
||||
|
||||
rct_tile_element * const pastedElement = tile_element_insert(x, y, element.base_height, 0);
|
||||
rct_tile_element* const pastedElement = tile_element_insert(x, y, element.base_height, 0);
|
||||
|
||||
bool lastForTile = pastedElement->IsLastForTile();
|
||||
*pastedElement = element;
|
||||
*pastedElement = element;
|
||||
pastedElement->flags &= ~TILE_ELEMENT_FLAG_LAST_TILE;
|
||||
if (lastForTile)
|
||||
{
|
||||
|
@ -341,8 +345,9 @@ int32_t tile_inspector_paste_element_at(int32_t x, int32_t y, rct_tile_element e
|
|||
|
||||
map_invalidate_tile_full(x << 5, y << 5);
|
||||
|
||||
rct_window * const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX && (uint32_t)y == windowTileInspectorTileY)
|
||||
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX
|
||||
&& (uint32_t)y == windowTileInspectorTileY)
|
||||
{
|
||||
windowTileInspectorElementCount++;
|
||||
|
||||
|
@ -364,11 +369,11 @@ int32_t tile_inspector_sort_elements_at(int32_t x, int32_t y, int32_t flags)
|
|||
{
|
||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
||||
{
|
||||
const rct_tile_element * const firstElement = map_get_first_element_at(x, y);
|
||||
const rct_tile_element* const firstElement = map_get_first_element_at(x, y);
|
||||
|
||||
// Count elements on tile
|
||||
int32_t numElement = 0;
|
||||
const rct_tile_element * elementIterator = firstElement;
|
||||
int32_t numElement = 0;
|
||||
const rct_tile_element* elementIterator = firstElement;
|
||||
do
|
||||
{
|
||||
numElement++;
|
||||
|
@ -377,15 +382,16 @@ int32_t tile_inspector_sort_elements_at(int32_t x, int32_t y, int32_t flags)
|
|||
// Bubble sort
|
||||
for (int32_t loopStart = 1; loopStart < numElement; loopStart++)
|
||||
{
|
||||
int32_t currentId = loopStart;
|
||||
const rct_tile_element * currentElement = firstElement + currentId;
|
||||
const rct_tile_element * otherElement = currentElement - 1;
|
||||
int32_t currentId = loopStart;
|
||||
const rct_tile_element* currentElement = firstElement + currentId;
|
||||
const rct_tile_element* otherElement = currentElement - 1;
|
||||
|
||||
// While current element's base height is lower, or (when their baseheight is the same) the other map element's
|
||||
// clearance height is lower...
|
||||
while (currentId > 0 && (otherElement->base_height > currentElement->base_height ||
|
||||
(otherElement->base_height == currentElement->base_height &&
|
||||
otherElement->clearance_height > currentElement->clearance_height)))
|
||||
while (currentId > 0
|
||||
&& (otherElement->base_height > currentElement->base_height
|
||||
|| (otherElement->base_height == currentElement->base_height
|
||||
&& otherElement->clearance_height > currentElement->clearance_height)))
|
||||
{
|
||||
if (!map_swap_elements_at(x, y, currentId - 1, currentId))
|
||||
{
|
||||
|
@ -404,8 +410,9 @@ int32_t tile_inspector_sort_elements_at(int32_t x, int32_t y, int32_t flags)
|
|||
map_invalidate_tile_full(x << 5, y << 5);
|
||||
|
||||
// Deselect tile for clients who had it selected
|
||||
rct_window * const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX && (uint32_t)y == windowTileInspectorTileY)
|
||||
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX
|
||||
&& (uint32_t)y == windowTileInspectorTileY)
|
||||
{
|
||||
windowTileInspectorSelectedIndex = -1;
|
||||
window_invalidate(tileInspectorWindow);
|
||||
|
@ -417,11 +424,11 @@ int32_t tile_inspector_sort_elements_at(int32_t x, int32_t y, int32_t flags)
|
|||
|
||||
int32_t tile_inspector_any_base_height_offset(int32_t x, int32_t y, int16_t elementIndex, int8_t heightOffset, int32_t flags)
|
||||
{
|
||||
rct_tile_element * const tileElement = map_get_nth_element_at(x, y, elementIndex);
|
||||
rct_tile_element* const tileElement = map_get_nth_element_at(x, y, elementIndex);
|
||||
if (tileElement == nullptr)
|
||||
return MONEY32_UNDEFINED;
|
||||
|
||||
int16_t newBaseHeight = (int16_t)tileElement->base_height + heightOffset;
|
||||
int16_t newBaseHeight = (int16_t)tileElement->base_height + heightOffset;
|
||||
int16_t newClearanceHeight = (int16_t)tileElement->clearance_height + heightOffset;
|
||||
if (newBaseHeight < 0 || newBaseHeight > 0xff || newClearanceHeight < 0 || newClearanceHeight > 0xff)
|
||||
{
|
||||
|
@ -436,10 +443,10 @@ int32_t tile_inspector_any_base_height_offset(int32_t x, int32_t y, int16_t elem
|
|||
if (entranceType != ENTRANCE_TYPE_PARK_ENTRANCE)
|
||||
{
|
||||
// Update the ride's known entrance or exit height
|
||||
Ride * ride = get_ride(tileElement->properties.entrance.ride_index);
|
||||
uint8_t entranceIndex = tileElement->properties.entrance.index;
|
||||
auto entrance = ride_get_entrance_location(ride, entranceIndex);
|
||||
auto exit = ride_get_exit_location(ride, entranceIndex);
|
||||
Ride* ride = get_ride(tileElement->properties.entrance.ride_index);
|
||||
uint8_t entranceIndex = tileElement->properties.entrance.index;
|
||||
auto entrance = ride_get_entrance_location(ride, entranceIndex);
|
||||
auto exit = ride_get_exit_location(ride, entranceIndex);
|
||||
uint8_t z = tileElement->base_height;
|
||||
|
||||
// Make sure this is the correct entrance or exit
|
||||
|
@ -447,8 +454,7 @@ int32_t tile_inspector_any_base_height_offset(int32_t x, int32_t y, int16_t elem
|
|||
ride_set_entrance_location(
|
||||
ride, entranceIndex, { entrance.x, entrance.y, z + heightOffset, entrance.direction });
|
||||
else if (entranceType == ENTRANCE_TYPE_RIDE_EXIT && exit.x == x && exit.y == y && exit.z == z)
|
||||
ride_set_exit_location(
|
||||
ride, entranceIndex, { exit.x, exit.y, z + heightOffset, exit.direction });
|
||||
ride_set_exit_location(ride, entranceIndex, { exit.x, exit.y, z + heightOffset, exit.direction });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -457,8 +463,9 @@ int32_t tile_inspector_any_base_height_offset(int32_t x, int32_t y, int16_t elem
|
|||
|
||||
map_invalidate_tile_full(x << 5, y << 5);
|
||||
|
||||
rct_window * const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX && (uint32_t)y == windowTileInspectorTileY)
|
||||
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX
|
||||
&& (uint32_t)y == windowTileInspectorTileY)
|
||||
{
|
||||
window_invalidate(tileInspectorWindow);
|
||||
}
|
||||
|
@ -469,7 +476,7 @@ int32_t tile_inspector_any_base_height_offset(int32_t x, int32_t y, int16_t elem
|
|||
|
||||
int32_t tile_inspector_surface_show_park_fences(int32_t x, int32_t y, bool showFences, int32_t flags)
|
||||
{
|
||||
rct_tile_element * const surfaceelement = map_get_surface_element_at(x, y);
|
||||
rct_tile_element* const surfaceelement = map_get_surface_element_at(x, y);
|
||||
|
||||
// No surface element on tile
|
||||
if (surfaceelement == nullptr)
|
||||
|
@ -480,12 +487,13 @@ int32_t tile_inspector_surface_show_park_fences(int32_t x, int32_t y, bool showF
|
|||
if (!showFences)
|
||||
surfaceelement->properties.surface.ownership &= ~0x0F;
|
||||
else
|
||||
update_park_fences({x << 5, y << 5});
|
||||
update_park_fences({ x << 5, y << 5 });
|
||||
|
||||
map_invalidate_tile_full(x << 5, y << 5);
|
||||
|
||||
rct_window * const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX && (uint32_t)y == windowTileInspectorTileY)
|
||||
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX
|
||||
&& (uint32_t)y == windowTileInspectorTileY)
|
||||
{
|
||||
window_invalidate(tileInspectorWindow);
|
||||
}
|
||||
|
@ -496,7 +504,7 @@ int32_t tile_inspector_surface_show_park_fences(int32_t x, int32_t y, bool showF
|
|||
|
||||
int32_t tile_inspector_surface_toggle_corner(int32_t x, int32_t y, int32_t cornerIndex, int32_t flags)
|
||||
{
|
||||
rct_tile_element * const surfaceElement = map_get_surface_element_at(x, y);
|
||||
rct_tile_element* const surfaceElement = map_get_surface_element_at(x, y);
|
||||
|
||||
// No surface element on tile
|
||||
if (surfaceElement == nullptr)
|
||||
|
@ -505,7 +513,7 @@ int32_t tile_inspector_surface_toggle_corner(int32_t x, int32_t y, int32_t corne
|
|||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
||||
{
|
||||
const uint8_t originalSlope = surfaceElement->properties.surface.slope;
|
||||
const bool diagonal = (originalSlope & TILE_ELEMENT_SLOPE_DOUBLE_HEIGHT) >> 4;
|
||||
const bool diagonal = (originalSlope & TILE_ELEMENT_SLOPE_DOUBLE_HEIGHT) >> 4;
|
||||
|
||||
surfaceElement->properties.surface.slope ^= 1 << cornerIndex;
|
||||
if (surfaceElement->properties.surface.slope & TILE_ELEMENT_SLOPE_ALL_CORNERS_UP)
|
||||
|
@ -526,18 +534,18 @@ int32_t tile_inspector_surface_toggle_corner(int32_t x, int32_t y, int32_t corne
|
|||
{
|
||||
switch (originalSlope & TILE_ELEMENT_SLOPE_ALL_CORNERS_UP)
|
||||
{
|
||||
case TILE_ELEMENT_SLOPE_S_CORNER_DN:
|
||||
surfaceElement->properties.surface.slope |= TILE_ELEMENT_SLOPE_N_CORNER_UP;
|
||||
break;
|
||||
case TILE_ELEMENT_SLOPE_W_CORNER_DN:
|
||||
surfaceElement->properties.surface.slope |= TILE_ELEMENT_SLOPE_E_CORNER_UP;
|
||||
break;
|
||||
case TILE_ELEMENT_SLOPE_N_CORNER_DN:
|
||||
surfaceElement->properties.surface.slope |= TILE_ELEMENT_SLOPE_S_CORNER_UP;
|
||||
break;
|
||||
case TILE_ELEMENT_SLOPE_E_CORNER_DN:
|
||||
surfaceElement->properties.surface.slope |= TILE_ELEMENT_SLOPE_W_CORNER_UP;
|
||||
break;
|
||||
case TILE_ELEMENT_SLOPE_S_CORNER_DN:
|
||||
surfaceElement->properties.surface.slope |= TILE_ELEMENT_SLOPE_N_CORNER_UP;
|
||||
break;
|
||||
case TILE_ELEMENT_SLOPE_W_CORNER_DN:
|
||||
surfaceElement->properties.surface.slope |= TILE_ELEMENT_SLOPE_E_CORNER_UP;
|
||||
break;
|
||||
case TILE_ELEMENT_SLOPE_N_CORNER_DN:
|
||||
surfaceElement->properties.surface.slope |= TILE_ELEMENT_SLOPE_S_CORNER_UP;
|
||||
break;
|
||||
case TILE_ELEMENT_SLOPE_E_CORNER_DN:
|
||||
surfaceElement->properties.surface.slope |= TILE_ELEMENT_SLOPE_W_CORNER_UP;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -548,8 +556,9 @@ int32_t tile_inspector_surface_toggle_corner(int32_t x, int32_t y, int32_t corne
|
|||
|
||||
map_invalidate_tile_full(x << 5, y << 5);
|
||||
|
||||
rct_window * const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX && (uint32_t)y == windowTileInspectorTileY)
|
||||
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX
|
||||
&& (uint32_t)y == windowTileInspectorTileY)
|
||||
{
|
||||
window_invalidate(tileInspectorWindow);
|
||||
}
|
||||
|
@ -560,7 +569,7 @@ int32_t tile_inspector_surface_toggle_corner(int32_t x, int32_t y, int32_t corne
|
|||
|
||||
int32_t tile_inspector_surface_toggle_diagonal(int32_t x, int32_t y, int32_t flags)
|
||||
{
|
||||
rct_tile_element * const surfaceElement = map_get_surface_element_at(x, y);
|
||||
rct_tile_element* const surfaceElement = map_get_surface_element_at(x, y);
|
||||
|
||||
// No surface element on tile
|
||||
if (surfaceElement == nullptr)
|
||||
|
@ -584,8 +593,9 @@ int32_t tile_inspector_surface_toggle_diagonal(int32_t x, int32_t y, int32_t fla
|
|||
|
||||
map_invalidate_tile_full(x << 5, y << 5);
|
||||
|
||||
rct_window * const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX && (uint32_t)y == windowTileInspectorTileY)
|
||||
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX
|
||||
&& (uint32_t)y == windowTileInspectorTileY)
|
||||
{
|
||||
window_invalidate(tileInspectorWindow);
|
||||
}
|
||||
|
@ -596,7 +606,7 @@ int32_t tile_inspector_surface_toggle_diagonal(int32_t x, int32_t y, int32_t fla
|
|||
|
||||
int32_t tile_inspector_path_set_sloped(int32_t x, int32_t y, int32_t elementIndex, bool sloped, int32_t flags)
|
||||
{
|
||||
rct_tile_element * const pathElement = map_get_nth_element_at(x, y, elementIndex);
|
||||
rct_tile_element* const pathElement = map_get_nth_element_at(x, y, elementIndex);
|
||||
|
||||
if (pathElement == nullptr || pathElement->GetType() != TILE_ELEMENT_TYPE_PATH)
|
||||
return MONEY32_UNDEFINED;
|
||||
|
@ -611,8 +621,9 @@ int32_t tile_inspector_path_set_sloped(int32_t x, int32_t y, int32_t elementInde
|
|||
|
||||
map_invalidate_tile_full(x << 5, y << 5);
|
||||
|
||||
rct_window * const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX && (uint32_t)y == windowTileInspectorTileY)
|
||||
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX
|
||||
&& (uint32_t)y == windowTileInspectorTileY)
|
||||
{
|
||||
window_invalidate(tileInspectorWindow);
|
||||
}
|
||||
|
@ -623,7 +634,7 @@ int32_t tile_inspector_path_set_sloped(int32_t x, int32_t y, int32_t elementInde
|
|||
|
||||
int32_t tile_inspector_path_toggle_edge(int32_t x, int32_t y, int32_t elementIndex, int32_t edgeIndex, int32_t flags)
|
||||
{
|
||||
rct_tile_element * const pathElement = map_get_nth_element_at(x, y, elementIndex);
|
||||
rct_tile_element* const pathElement = map_get_nth_element_at(x, y, elementIndex);
|
||||
|
||||
if (pathElement == nullptr || pathElement->GetType() != TILE_ELEMENT_TYPE_PATH)
|
||||
return MONEY32_UNDEFINED;
|
||||
|
@ -634,8 +645,9 @@ int32_t tile_inspector_path_toggle_edge(int32_t x, int32_t y, int32_t elementInd
|
|||
|
||||
map_invalidate_tile_full(x << 5, y << 5);
|
||||
|
||||
rct_window * const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX && (uint32_t)y == windowTileInspectorTileY)
|
||||
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX
|
||||
&& (uint32_t)y == windowTileInspectorTileY)
|
||||
{
|
||||
window_invalidate(tileInspectorWindow);
|
||||
}
|
||||
|
@ -646,12 +658,12 @@ int32_t tile_inspector_path_toggle_edge(int32_t x, int32_t y, int32_t elementInd
|
|||
|
||||
int32_t tile_inspector_entrance_make_usable(int32_t x, int32_t y, int32_t elementIndex, int32_t flags)
|
||||
{
|
||||
rct_tile_element * const entranceElement = map_get_nth_element_at(x, y, elementIndex);
|
||||
rct_tile_element* const entranceElement = map_get_nth_element_at(x, y, elementIndex);
|
||||
|
||||
if (entranceElement == nullptr || entranceElement->GetType() != TILE_ELEMENT_TYPE_ENTRANCE)
|
||||
return MONEY32_UNDEFINED;
|
||||
|
||||
Ride * ride = get_ride(entranceElement->properties.entrance.ride_index);
|
||||
Ride* ride = get_ride(entranceElement->properties.entrance.ride_index);
|
||||
|
||||
if (ride == nullptr)
|
||||
return MONEY32_UNDEFINED;
|
||||
|
@ -662,16 +674,23 @@ int32_t tile_inspector_entrance_make_usable(int32_t x, int32_t y, int32_t elemen
|
|||
|
||||
switch (entranceElement->properties.entrance.type)
|
||||
{
|
||||
case ENTRANCE_TYPE_RIDE_ENTRANCE:
|
||||
ride_set_entrance_location(ride, stationIndex, { x, y, entranceElement->base_height, (uint8_t)tile_element_get_direction(entranceElement) });
|
||||
break;
|
||||
case ENTRANCE_TYPE_RIDE_EXIT:
|
||||
ride_set_exit_location(ride, stationIndex, { x, y, entranceElement->base_height, (uint8_t)tile_element_get_direction(entranceElement) });
|
||||
break;
|
||||
case ENTRANCE_TYPE_RIDE_ENTRANCE:
|
||||
ride_set_entrance_location(
|
||||
ride,
|
||||
stationIndex,
|
||||
{ x, y, entranceElement->base_height, (uint8_t)tile_element_get_direction(entranceElement) });
|
||||
break;
|
||||
case ENTRANCE_TYPE_RIDE_EXIT:
|
||||
ride_set_exit_location(
|
||||
ride,
|
||||
stationIndex,
|
||||
{ x, y, entranceElement->base_height, (uint8_t)tile_element_get_direction(entranceElement) });
|
||||
break;
|
||||
}
|
||||
|
||||
rct_window * const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX && (uint32_t)y == windowTileInspectorTileY)
|
||||
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX
|
||||
&& (uint32_t)y == windowTileInspectorTileY)
|
||||
{
|
||||
window_invalidate(tileInspectorWindow);
|
||||
}
|
||||
|
@ -682,7 +701,7 @@ int32_t tile_inspector_entrance_make_usable(int32_t x, int32_t y, int32_t elemen
|
|||
|
||||
int32_t tile_inspector_wall_set_slope(int32_t x, int32_t y, int32_t elementIndex, int32_t slopeValue, int32_t flags)
|
||||
{
|
||||
rct_tile_element * const wallElement = map_get_nth_element_at(x, y, elementIndex);
|
||||
rct_tile_element* const wallElement = map_get_nth_element_at(x, y, elementIndex);
|
||||
|
||||
if (wallElement == nullptr || wallElement->GetType() != TILE_ELEMENT_TYPE_WALL)
|
||||
return MONEY32_UNDEFINED;
|
||||
|
@ -695,8 +714,9 @@ int32_t tile_inspector_wall_set_slope(int32_t x, int32_t y, int32_t elementIndex
|
|||
|
||||
map_invalidate_tile_full(x << 5, y << 5);
|
||||
|
||||
rct_window * const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX && (uint32_t)y == windowTileInspectorTileY)
|
||||
rct_window* const tileInspectorWindow = window_find_by_class(WC_TILE_INSPECTOR);
|
||||
if (tileInspectorWindow != nullptr && (uint32_t)x == windowTileInspectorTileX
|
||||
&& (uint32_t)y == windowTileInspectorTileY)
|
||||
{
|
||||
window_invalidate(tileInspectorWindow);
|
||||
}
|
||||
|
@ -709,7 +729,7 @@ int32_t tile_inspector_wall_set_slope(int32_t x, int32_t y, int32_t elementIndex
|
|||
// Broxzier: Copied from track_remove and stripped of unneeded code, but I think this should be smaller
|
||||
int32_t tile_inspector_track_base_height_offset(int32_t x, int32_t y, int32_t elementIndex, int8_t offset, int32_t flags)
|
||||
{
|
||||
rct_tile_element * const trackElement = map_get_nth_element_at(x, y, elementIndex);
|
||||
rct_tile_element* const trackElement = map_get_nth_element_at(x, y, elementIndex);
|
||||
|
||||
if (offset == 0)
|
||||
return 0;
|
||||
|
@ -719,35 +739,35 @@ int32_t tile_inspector_track_base_height_offset(int32_t x, int32_t y, int32_t el
|
|||
|
||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
||||
{
|
||||
uint8_t type = track_element_get_type(trackElement);
|
||||
int16_t originX = x << 5;
|
||||
int16_t originY = y << 5;
|
||||
int16_t originZ = trackElement->base_height * 8;
|
||||
uint8_t rotation = tile_element_get_direction(trackElement);
|
||||
uint8_t rideIndex = track_element_get_ride_index(trackElement);
|
||||
Ride * ride = get_ride(rideIndex);
|
||||
const rct_preview_track * trackBlock = get_track_def_from_ride(ride, type);
|
||||
uint8_t type = track_element_get_type(trackElement);
|
||||
int16_t originX = x << 5;
|
||||
int16_t originY = y << 5;
|
||||
int16_t originZ = trackElement->base_height * 8;
|
||||
uint8_t rotation = tile_element_get_direction(trackElement);
|
||||
uint8_t rideIndex = track_element_get_ride_index(trackElement);
|
||||
Ride* ride = get_ride(rideIndex);
|
||||
const rct_preview_track* trackBlock = get_track_def_from_ride(ride, type);
|
||||
trackBlock += tile_element_get_track_sequence(trackElement);
|
||||
|
||||
uint8_t originDirection = tile_element_get_direction(trackElement);
|
||||
switch (originDirection)
|
||||
{
|
||||
case 0:
|
||||
originX -= trackBlock->x;
|
||||
originY -= trackBlock->y;
|
||||
break;
|
||||
case 1:
|
||||
originX -= trackBlock->y;
|
||||
originY += trackBlock->x;
|
||||
break;
|
||||
case 2:
|
||||
originX += trackBlock->x;
|
||||
originY += trackBlock->y;
|
||||
break;
|
||||
case 3:
|
||||
originX += trackBlock->y;
|
||||
originY -= trackBlock->x;
|
||||
break;
|
||||
case 0:
|
||||
originX -= trackBlock->x;
|
||||
originY -= trackBlock->y;
|
||||
break;
|
||||
case 1:
|
||||
originX -= trackBlock->y;
|
||||
originY += trackBlock->x;
|
||||
break;
|
||||
case 2:
|
||||
originX += trackBlock->x;
|
||||
originY += trackBlock->y;
|
||||
break;
|
||||
case 3:
|
||||
originX += trackBlock->y;
|
||||
originY -= trackBlock->x;
|
||||
break;
|
||||
}
|
||||
|
||||
originZ -= trackBlock->z;
|
||||
|
@ -759,30 +779,30 @@ int32_t tile_inspector_track_base_height_offset(int32_t x, int32_t y, int32_t el
|
|||
|
||||
switch (originDirection)
|
||||
{
|
||||
case 0:
|
||||
elemX += trackBlock->x;
|
||||
elemY += trackBlock->y;
|
||||
break;
|
||||
case 1:
|
||||
elemX += trackBlock->y;
|
||||
elemY -= trackBlock->x;
|
||||
break;
|
||||
case 2:
|
||||
elemX -= trackBlock->x;
|
||||
elemY -= trackBlock->y;
|
||||
break;
|
||||
case 3:
|
||||
elemX -= trackBlock->y;
|
||||
elemY += trackBlock->x;
|
||||
break;
|
||||
case 0:
|
||||
elemX += trackBlock->x;
|
||||
elemY += trackBlock->y;
|
||||
break;
|
||||
case 1:
|
||||
elemX += trackBlock->y;
|
||||
elemY -= trackBlock->x;
|
||||
break;
|
||||
case 2:
|
||||
elemX -= trackBlock->x;
|
||||
elemY -= trackBlock->y;
|
||||
break;
|
||||
case 3:
|
||||
elemX -= trackBlock->y;
|
||||
elemY += trackBlock->x;
|
||||
break;
|
||||
}
|
||||
|
||||
elemZ += trackBlock->z;
|
||||
|
||||
map_invalidate_tile_full(elemX, elemY);
|
||||
|
||||
bool found = false;
|
||||
rct_tile_element * tileElement = map_get_first_element_at(elemX >> 5, elemY >> 5);
|
||||
bool found = false;
|
||||
rct_tile_element* tileElement = map_get_first_element_at(elemX >> 5, elemY >> 5);
|
||||
do
|
||||
{
|
||||
if (tileElement->base_height != elemZ / 8)
|
||||
|
@ -812,8 +832,8 @@ int32_t tile_inspector_track_base_height_offset(int32_t x, int32_t y, int32_t el
|
|||
|
||||
// track_remove returns here on failure, not sure when this would ever be hit. Only thing I can think of is for when
|
||||
// you decrease the map size.
|
||||
openrct2_assert(map_get_surface_element_at({elemX, elemY}) != nullptr, "No surface at %d,%d", elemX >> 5,
|
||||
elemY >> 5);
|
||||
openrct2_assert(
|
||||
map_get_surface_element_at({ elemX, elemY }) != nullptr, "No surface at %d,%d", elemX >> 5, elemY >> 5);
|
||||
|
||||
// Keep?
|
||||
// invalidate_test_results(rideIndex);
|
||||
|
@ -831,10 +851,10 @@ int32_t tile_inspector_track_base_height_offset(int32_t x, int32_t y, int32_t el
|
|||
|
||||
// Sets chainlift, optionally for an entire track block
|
||||
// Broxzier: Basically a copy of the above function, with just two different lines... should probably be combined somehow
|
||||
int32_t tile_inspector_track_set_chain(int32_t x, int32_t y, int32_t elementIndex, bool entireTrackBlock, bool setChain,
|
||||
int32_t flags)
|
||||
int32_t tile_inspector_track_set_chain(
|
||||
int32_t x, int32_t y, int32_t elementIndex, bool entireTrackBlock, bool setChain, int32_t flags)
|
||||
{
|
||||
rct_tile_element * const trackElement = map_get_nth_element_at(x, y, elementIndex);
|
||||
rct_tile_element* const trackElement = map_get_nth_element_at(x, y, elementIndex);
|
||||
|
||||
if (trackElement == nullptr || trackElement->GetType() != TILE_ELEMENT_TYPE_TRACK)
|
||||
return MONEY32_UNDEFINED;
|
||||
|
@ -852,35 +872,35 @@ int32_t tile_inspector_track_set_chain(int32_t x, int32_t y, int32_t elementInde
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint8_t type = track_element_get_type(trackElement);
|
||||
int16_t originX = x << 5;
|
||||
int16_t originY = y << 5;
|
||||
int16_t originZ = trackElement->base_height * 8;
|
||||
uint8_t rotation = tile_element_get_direction(trackElement);
|
||||
uint8_t rideIndex = track_element_get_ride_index(trackElement);
|
||||
Ride * ride = get_ride(rideIndex);
|
||||
const rct_preview_track * trackBlock = get_track_def_from_ride(ride, type);
|
||||
uint8_t type = track_element_get_type(trackElement);
|
||||
int16_t originX = x << 5;
|
||||
int16_t originY = y << 5;
|
||||
int16_t originZ = trackElement->base_height * 8;
|
||||
uint8_t rotation = tile_element_get_direction(trackElement);
|
||||
uint8_t rideIndex = track_element_get_ride_index(trackElement);
|
||||
Ride* ride = get_ride(rideIndex);
|
||||
const rct_preview_track* trackBlock = get_track_def_from_ride(ride, type);
|
||||
trackBlock += tile_element_get_track_sequence(trackElement);
|
||||
|
||||
uint8_t originDirection = tile_element_get_direction(trackElement);
|
||||
switch (originDirection)
|
||||
{
|
||||
case 0:
|
||||
originX -= trackBlock->x;
|
||||
originY -= trackBlock->y;
|
||||
break;
|
||||
case 1:
|
||||
originX -= trackBlock->y;
|
||||
originY += trackBlock->x;
|
||||
break;
|
||||
case 2:
|
||||
originX += trackBlock->x;
|
||||
originY += trackBlock->y;
|
||||
break;
|
||||
case 3:
|
||||
originX += trackBlock->y;
|
||||
originY -= trackBlock->x;
|
||||
break;
|
||||
case 0:
|
||||
originX -= trackBlock->x;
|
||||
originY -= trackBlock->y;
|
||||
break;
|
||||
case 1:
|
||||
originX -= trackBlock->y;
|
||||
originY += trackBlock->x;
|
||||
break;
|
||||
case 2:
|
||||
originX += trackBlock->x;
|
||||
originY += trackBlock->y;
|
||||
break;
|
||||
case 3:
|
||||
originX += trackBlock->y;
|
||||
originY -= trackBlock->x;
|
||||
break;
|
||||
}
|
||||
|
||||
originZ -= trackBlock->z;
|
||||
|
@ -892,30 +912,30 @@ int32_t tile_inspector_track_set_chain(int32_t x, int32_t y, int32_t elementInde
|
|||
|
||||
switch (originDirection)
|
||||
{
|
||||
case 0:
|
||||
elemX += trackBlock->x;
|
||||
elemY += trackBlock->y;
|
||||
break;
|
||||
case 1:
|
||||
elemX += trackBlock->y;
|
||||
elemY -= trackBlock->x;
|
||||
break;
|
||||
case 2:
|
||||
elemX -= trackBlock->x;
|
||||
elemY -= trackBlock->y;
|
||||
break;
|
||||
case 3:
|
||||
elemX -= trackBlock->y;
|
||||
elemY += trackBlock->x;
|
||||
break;
|
||||
case 0:
|
||||
elemX += trackBlock->x;
|
||||
elemY += trackBlock->y;
|
||||
break;
|
||||
case 1:
|
||||
elemX += trackBlock->y;
|
||||
elemY -= trackBlock->x;
|
||||
break;
|
||||
case 2:
|
||||
elemX -= trackBlock->x;
|
||||
elemY -= trackBlock->y;
|
||||
break;
|
||||
case 3:
|
||||
elemX -= trackBlock->y;
|
||||
elemY += trackBlock->x;
|
||||
break;
|
||||
}
|
||||
|
||||
elemZ += trackBlock->z;
|
||||
|
||||
map_invalidate_tile_full(elemX, elemY);
|
||||
|
||||
bool found = false;
|
||||
rct_tile_element * tileElement = map_get_first_element_at(elemX >> 5, elemY >> 5);
|
||||
bool found = false;
|
||||
rct_tile_element* tileElement = map_get_first_element_at(elemX >> 5, elemY >> 5);
|
||||
do
|
||||
{
|
||||
if (tileElement->base_height != elemZ / 8)
|
||||
|
@ -945,8 +965,8 @@ int32_t tile_inspector_track_set_chain(int32_t x, int32_t y, int32_t elementInde
|
|||
|
||||
// track_remove returns here on failure, not sure when this would ever be hit. Only thing I can think of is for when
|
||||
// you decrease the map size.
|
||||
openrct2_assert(map_get_surface_element_at({elemX, elemY}) != nullptr, "No surface at %d,%d", elemX >> 5,
|
||||
elemY >> 5);
|
||||
openrct2_assert(
|
||||
map_get_surface_element_at({ elemX, elemY }) != nullptr, "No surface at %d,%d", elemX >> 5, elemY >> 5);
|
||||
|
||||
// Keep?
|
||||
// invalidate_test_results(rideIndex);
|
||||
|
@ -964,9 +984,10 @@ int32_t tile_inspector_track_set_chain(int32_t x, int32_t y, int32_t elementInde
|
|||
return 0;
|
||||
}
|
||||
|
||||
int32_t tile_inspector_scenery_set_quarter_location(int32_t x, int32_t y, int32_t elementIndex, int32_t quarterIndex, int32_t flags)
|
||||
int32_t
|
||||
tile_inspector_scenery_set_quarter_location(int32_t x, int32_t y, int32_t elementIndex, int32_t quarterIndex, int32_t flags)
|
||||
{
|
||||
rct_tile_element * const tileElement = map_get_nth_element_at(x, y, elementIndex);
|
||||
rct_tile_element* const tileElement = map_get_nth_element_at(x, y, elementIndex);
|
||||
|
||||
if (tileElement == nullptr || tileElement->GetType() != TILE_ELEMENT_TYPE_SMALL_SCENERY)
|
||||
return MONEY32_UNDEFINED;
|
||||
|
@ -991,9 +1012,10 @@ int32_t tile_inspector_scenery_set_quarter_location(int32_t x, int32_t y, int32_
|
|||
return 0;
|
||||
}
|
||||
|
||||
int32_t tile_inspector_scenery_set_quarter_collision(int32_t x, int32_t y, int32_t elementIndex, int32_t quarterIndex, int32_t flags)
|
||||
int32_t tile_inspector_scenery_set_quarter_collision(
|
||||
int32_t x, int32_t y, int32_t elementIndex, int32_t quarterIndex, int32_t flags)
|
||||
{
|
||||
rct_tile_element * const tileElement = map_get_nth_element_at(x, y, elementIndex);
|
||||
rct_tile_element* const tileElement = map_get_nth_element_at(x, y, elementIndex);
|
||||
|
||||
if (tileElement == nullptr || tileElement->GetType() != TILE_ELEMENT_TYPE_SMALL_SCENERY)
|
||||
return MONEY32_UNDEFINED;
|
||||
|
@ -1014,7 +1036,7 @@ int32_t tile_inspector_scenery_set_quarter_collision(int32_t x, int32_t y, int32
|
|||
|
||||
int32_t tile_inspector_banner_toggle_blocking_edge(int32_t x, int32_t y, int32_t elementIndex, int32_t edgeIndex, int32_t flags)
|
||||
{
|
||||
rct_tile_element * const bannerElement = map_get_nth_element_at(x, y, elementIndex);
|
||||
rct_tile_element* const bannerElement = map_get_nth_element_at(x, y, elementIndex);
|
||||
|
||||
if (bannerElement == nullptr || bannerElement->GetType() != TILE_ELEMENT_TYPE_BANNER)
|
||||
return MONEY32_UNDEFINED;
|
||||
|
@ -1034,7 +1056,7 @@ int32_t tile_inspector_banner_toggle_blocking_edge(int32_t x, int32_t y, int32_t
|
|||
|
||||
int32_t tile_inspector_corrupt_clamp(int32_t x, int32_t y, int32_t elementIndex, int32_t flags)
|
||||
{
|
||||
rct_tile_element * const corruptElement = map_get_nth_element_at(x, y, elementIndex);
|
||||
rct_tile_element* const corruptElement = map_get_nth_element_at(x, y, elementIndex);
|
||||
|
||||
if (corruptElement == nullptr || corruptElement->GetType() != TILE_ELEMENT_TYPE_CORRUPT)
|
||||
return MONEY32_UNDEFINED;
|
||||
|
@ -1044,7 +1066,7 @@ int32_t tile_inspector_corrupt_clamp(int32_t x, int32_t y, int32_t elementIndex,
|
|||
|
||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
||||
{
|
||||
rct_tile_element * const nextElement = corruptElement + 1;
|
||||
rct_tile_element* const nextElement = corruptElement + 1;
|
||||
corruptElement->base_height = corruptElement->clearance_height = nextElement->base_height;
|
||||
|
||||
if ((uint32_t)x == windowTileInspectorTileX && (uint32_t)y == windowTileInspectorTileY)
|
||||
|
|
|
@ -12,7 +12,8 @@
|
|||
#include "../common.h"
|
||||
#include "Map.h"
|
||||
|
||||
enum TILE_INSPECTOR_ELEMENT_TYPE {
|
||||
enum TILE_INSPECTOR_ELEMENT_TYPE
|
||||
{
|
||||
TILE_INSPECTOR_ELEMENT_ANY = 0,
|
||||
TILE_INSPECTOR_ELEMENT_SURFACE,
|
||||
TILE_INSPECTOR_ELEMENT_PATH,
|
||||
|
@ -25,7 +26,8 @@ enum TILE_INSPECTOR_ELEMENT_TYPE {
|
|||
TILE_INSPECTOR_ELEMENT_CORRUPT,
|
||||
};
|
||||
|
||||
enum TILE_INSPECTOR_INSTRUCTION_TYPE {
|
||||
enum TILE_INSPECTOR_INSTRUCTION_TYPE
|
||||
{
|
||||
TILE_INSPECTOR_ANY_REMOVE,
|
||||
TILE_INSPECTOR_ANY_SWAP,
|
||||
TILE_INSPECTOR_ANY_INSERT_CORRUPT,
|
||||
|
@ -63,8 +65,12 @@ int32_t tile_inspector_path_toggle_edge(int32_t x, int32_t y, int32_t elementInd
|
|||
int32_t tile_inspector_entrance_make_usable(int32_t x, int32_t y, int32_t elementIndex, int32_t flags);
|
||||
int32_t tile_inspector_wall_set_slope(int32_t x, int32_t y, int32_t elementIndex, int32_t slopeValue, int32_t flags);
|
||||
int32_t tile_inspector_track_base_height_offset(int32_t x, int32_t y, int32_t elementIndex, int8_t offset, int32_t flags);
|
||||
int32_t tile_inspector_track_set_chain(int32_t x, int32_t y, int32_t elementIndex, bool entireTrackBlock, bool setChain, int32_t flags);
|
||||
int32_t tile_inspector_scenery_set_quarter_location(int32_t x, int32_t y, int32_t elementIndex, int32_t quarterIndex, int32_t flags);
|
||||
int32_t tile_inspector_scenery_set_quarter_collision(int32_t x, int32_t y, int32_t elementIndex, int32_t quarterIndex, int32_t flags);
|
||||
int32_t tile_inspector_banner_toggle_blocking_edge(int32_t x, int32_t y, int32_t elementIndex, int32_t edgeIndex, int32_t flags);
|
||||
int32_t tile_inspector_track_set_chain(
|
||||
int32_t x, int32_t y, int32_t elementIndex, bool entireTrackBlock, bool setChain, int32_t flags);
|
||||
int32_t tile_inspector_scenery_set_quarter_location(
|
||||
int32_t x, int32_t y, int32_t elementIndex, int32_t quarterIndex, int32_t flags);
|
||||
int32_t tile_inspector_scenery_set_quarter_collision(
|
||||
int32_t x, int32_t y, int32_t elementIndex, int32_t quarterIndex, int32_t flags);
|
||||
int32_t
|
||||
tile_inspector_banner_toggle_blocking_edge(int32_t x, int32_t y, int32_t elementIndex, int32_t edgeIndex, int32_t flags);
|
||||
int32_t tile_inspector_corrupt_clamp(int32_t x, int32_t y, int32_t elementIndex, int32_t flags);
|
||||
|
|
|
@ -7,14 +7,16 @@
|
|||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "../common.h"
|
||||
#include "../network/network.h"
|
||||
#include "../OpenRCT2.h"
|
||||
#include "Wall.h"
|
||||
|
||||
#include "../Cheats.h"
|
||||
#include "../Game.h"
|
||||
#include "../OpenRCT2.h"
|
||||
#include "../common.h"
|
||||
#include "../localisation/StringIds.h"
|
||||
#include "../management/Finance.h"
|
||||
#include "../network/network.h"
|
||||
#include "../ride/RideGroupManager.h"
|
||||
#include "../ride/Track.h"
|
||||
#include "../ride/TrackData.h"
|
||||
#include "Banner.h"
|
||||
|
@ -26,7 +28,6 @@
|
|||
#include "SmallScenery.h"
|
||||
#include "Surface.h"
|
||||
#include "Wall.h"
|
||||
#include "../ride/RideGroupManager.h"
|
||||
|
||||
/**
|
||||
* Gets whether the given track type can have a wall placed on the edge of the given direction.
|
||||
|
@ -58,16 +59,13 @@ static bool TrackIsAllowedWallEdges(uint8_t rideType, uint8_t trackType, uint8_t
|
|||
*
|
||||
* rct2: 0x006E5CBA
|
||||
*/
|
||||
static bool WallCheckObstructionWithTrack(rct_scenery_entry * wall,
|
||||
int32_t z0,
|
||||
int32_t edge,
|
||||
rct_tile_element * trackElement,
|
||||
bool * wallAcrossTrack)
|
||||
static bool WallCheckObstructionWithTrack(
|
||||
rct_scenery_entry* wall, int32_t z0, int32_t edge, rct_tile_element* trackElement, bool* wallAcrossTrack)
|
||||
{
|
||||
int32_t trackType = track_element_get_type(trackElement);
|
||||
int32_t sequence = tile_element_get_track_sequence(trackElement);
|
||||
int32_t direction = (edge - tile_element_get_direction(trackElement)) & TILE_ELEMENT_DIRECTION_MASK;
|
||||
Ride * ride = get_ride(track_element_get_ride_index(trackElement));
|
||||
Ride* ride = get_ride(track_element_get_ride_index(trackElement));
|
||||
|
||||
if (TrackIsAllowedWallEdges(ride->type, trackType, sequence, direction))
|
||||
{
|
||||
|
@ -113,7 +111,7 @@ static bool WallCheckObstructionWithTrack(rct_scenery_entry * wall,
|
|||
direction = tile_element_get_direction_with_offset(trackElement, 2);
|
||||
if (direction == edge)
|
||||
{
|
||||
const rct_preview_track * trackBlock = &TrackBlocks[trackType][sequence];
|
||||
const rct_preview_track* trackBlock = &TrackBlocks[trackType][sequence];
|
||||
z = TrackCoordinates[trackType].z_begin;
|
||||
z = trackElement->base_height + ((z - trackBlock->z) * 8);
|
||||
if (z == z0)
|
||||
|
@ -125,7 +123,7 @@ static bool WallCheckObstructionWithTrack(rct_scenery_entry * wall,
|
|||
}
|
||||
}
|
||||
|
||||
const rct_preview_track * trackBlock = &TrackBlocks[trackType][sequence + 1];
|
||||
const rct_preview_track* trackBlock = &TrackBlocks[trackType][sequence + 1];
|
||||
if (trackBlock->index != 0xFF)
|
||||
{
|
||||
return false;
|
||||
|
@ -158,17 +156,12 @@ static bool WallCheckObstructionWithTrack(rct_scenery_entry * wall,
|
|||
*
|
||||
* rct2: 0x006E5C1A
|
||||
*/
|
||||
static bool WallCheckObstruction(rct_scenery_entry * wall,
|
||||
int32_t x,
|
||||
int32_t y,
|
||||
int32_t z0,
|
||||
int32_t z1,
|
||||
int32_t edge,
|
||||
bool * wallAcrossTrack)
|
||||
static bool WallCheckObstruction(
|
||||
rct_scenery_entry* wall, int32_t x, int32_t y, int32_t z0, int32_t z1, int32_t edge, bool* wallAcrossTrack)
|
||||
{
|
||||
int32_t entryType, sequence;
|
||||
rct_scenery_entry * entry;
|
||||
rct_large_scenery_tile * tile;
|
||||
rct_scenery_entry* entry;
|
||||
rct_large_scenery_tile* tile;
|
||||
|
||||
*wallAcrossTrack = false;
|
||||
gMapGroundFlags = ELEMENT_IS_ABOVE_GROUND;
|
||||
|
@ -178,13 +171,16 @@ static bool WallCheckObstruction(rct_scenery_entry * wall,
|
|||
return false;
|
||||
}
|
||||
|
||||
rct_tile_element * tileElement = map_get_first_element_at(x / 32, y / 32);
|
||||
rct_tile_element* tileElement = map_get_first_element_at(x / 32, y / 32);
|
||||
do
|
||||
{
|
||||
int32_t elementType = tileElement->GetType();
|
||||
if (elementType == TILE_ELEMENT_TYPE_SURFACE) continue;
|
||||
if (z0 >= tileElement->clearance_height) continue;
|
||||
if (z1 <= tileElement->base_height) continue;
|
||||
if (elementType == TILE_ELEMENT_TYPE_SURFACE)
|
||||
continue;
|
||||
if (z0 >= tileElement->clearance_height)
|
||||
continue;
|
||||
if (z1 <= tileElement->base_height)
|
||||
continue;
|
||||
if (elementType == TILE_ELEMENT_TYPE_WALL)
|
||||
{
|
||||
int32_t direction = tile_element_get_direction(tileElement);
|
||||
|
@ -195,51 +191,52 @@ static bool WallCheckObstruction(rct_scenery_entry * wall,
|
|||
}
|
||||
continue;
|
||||
}
|
||||
if ((tileElement->flags & 0x0F) == 0) continue;
|
||||
if ((tileElement->flags & 0x0F) == 0)
|
||||
continue;
|
||||
|
||||
switch (elementType) {
|
||||
case TILE_ELEMENT_TYPE_ENTRANCE:
|
||||
map_obstruction_set_error_text(tileElement);
|
||||
return false;
|
||||
case TILE_ELEMENT_TYPE_PATH:
|
||||
if (tileElement->properties.path.edges & (1 << edge))
|
||||
{
|
||||
switch (elementType)
|
||||
{
|
||||
case TILE_ELEMENT_TYPE_ENTRANCE:
|
||||
map_obstruction_set_error_text(tileElement);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case TILE_ELEMENT_TYPE_LARGE_SCENERY:
|
||||
entryType = scenery_large_get_type(tileElement);
|
||||
sequence = scenery_large_get_sequence(tileElement);
|
||||
entry = get_large_scenery_entry(entryType);
|
||||
tile = &entry->large_scenery.tiles[sequence];
|
||||
{
|
||||
int32_t direction = ((edge - tile_element_get_direction(tileElement)) & TILE_ELEMENT_DIRECTION_MASK) + 8;
|
||||
if (!(tile->flags & (1 << direction)))
|
||||
case TILE_ELEMENT_TYPE_PATH:
|
||||
if (tileElement->properties.path.edges & (1 << edge))
|
||||
{
|
||||
map_obstruction_set_error_text(tileElement);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TILE_ELEMENT_TYPE_SMALL_SCENERY:
|
||||
entryType = tileElement->properties.scenery.type;
|
||||
entry = get_small_scenery_entry(entryType);
|
||||
if (scenery_small_entry_has_flag(entry, SMALL_SCENERY_FLAG_NO_WALLS))
|
||||
{
|
||||
map_obstruction_set_error_text(tileElement);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case TILE_ELEMENT_TYPE_TRACK:
|
||||
if (!WallCheckObstructionWithTrack(wall, z0, edge, tileElement, wallAcrossTrack))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case TILE_ELEMENT_TYPE_LARGE_SCENERY:
|
||||
entryType = scenery_large_get_type(tileElement);
|
||||
sequence = scenery_large_get_sequence(tileElement);
|
||||
entry = get_large_scenery_entry(entryType);
|
||||
tile = &entry->large_scenery.tiles[sequence];
|
||||
{
|
||||
int32_t direction = ((edge - tile_element_get_direction(tileElement)) & TILE_ELEMENT_DIRECTION_MASK) + 8;
|
||||
if (!(tile->flags & (1 << direction)))
|
||||
{
|
||||
map_obstruction_set_error_text(tileElement);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TILE_ELEMENT_TYPE_SMALL_SCENERY:
|
||||
entryType = tileElement->properties.scenery.type;
|
||||
entry = get_small_scenery_entry(entryType);
|
||||
if (scenery_small_entry_has_flag(entry, SMALL_SCENERY_FLAG_NO_WALLS))
|
||||
{
|
||||
map_obstruction_set_error_text(tileElement);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case TILE_ELEMENT_TYPE_TRACK:
|
||||
if (!WallCheckObstructionWithTrack(wall, z0, edge, tileElement, wallAcrossTrack))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (!(tileElement++)->IsLastForTile());
|
||||
} while (!(tileElement++)->IsLastForTile());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -297,15 +294,16 @@ static constexpr const uint8_t EdgeSlopes[][4] = {
|
|||
|
||||
#pragma endregion
|
||||
|
||||
static money32 WallPlace(uint8_t wallType,
|
||||
int16_t x,
|
||||
int16_t y,
|
||||
int16_t z,
|
||||
uint8_t edge,
|
||||
uint8_t primaryColour,
|
||||
uint8_t secondaryColour,
|
||||
uint8_t tertiaryColour,
|
||||
uint8_t flags)
|
||||
static money32 WallPlace(
|
||||
uint8_t wallType,
|
||||
int16_t x,
|
||||
int16_t y,
|
||||
int16_t z,
|
||||
uint8_t edge,
|
||||
uint8_t primaryColour,
|
||||
uint8_t secondaryColour,
|
||||
uint8_t tertiaryColour,
|
||||
uint8_t flags)
|
||||
{
|
||||
LocationXYZ16 position = { x, y, z };
|
||||
|
||||
|
@ -325,14 +323,11 @@ static money32 WallPlace(uint8_t wallType,
|
|||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
if (!(gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) &&
|
||||
!(flags & GAME_COMMAND_FLAG_PATH_SCENERY) &&
|
||||
!gCheatsSandboxMode)
|
||||
if (!(gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) && !(flags & GAME_COMMAND_FLAG_PATH_SCENERY) && !gCheatsSandboxMode)
|
||||
{
|
||||
|
||||
if (position.z == 0)
|
||||
{
|
||||
if (!map_is_location_in_park({position.x, position.y}))
|
||||
if (!map_is_location_in_park({ position.x, position.y }))
|
||||
{
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
@ -346,7 +341,7 @@ static money32 WallPlace(uint8_t wallType,
|
|||
uint8_t edgeSlope = 0;
|
||||
if (position.z == 0)
|
||||
{
|
||||
rct_tile_element * surfaceElement = map_get_surface_element_at({position.x, position.y});
|
||||
rct_tile_element* surfaceElement = map_get_surface_element_at({ position.x, position.y });
|
||||
if (surfaceElement == nullptr)
|
||||
{
|
||||
return MONEY32_UNDEFINED;
|
||||
|
@ -362,7 +357,7 @@ static money32 WallPlace(uint8_t wallType,
|
|||
}
|
||||
}
|
||||
|
||||
rct_tile_element * surfaceElement = map_get_surface_element_at({position.x, position.y});
|
||||
rct_tile_element* surfaceElement = map_get_surface_element_at({ position.x, position.y });
|
||||
if (surfaceElement == nullptr)
|
||||
{
|
||||
return MONEY32_UNDEFINED;
|
||||
|
@ -449,7 +444,7 @@ static money32 WallPlace(uint8_t wallType,
|
|||
}
|
||||
}
|
||||
BannerIndex bannerIndex = BANNER_INDEX_NULL;
|
||||
rct_scenery_entry * wallEntry = get_wall_entry(wallType);
|
||||
rct_scenery_entry* wallEntry = get_wall_entry(wallType);
|
||||
|
||||
if (wallEntry == nullptr)
|
||||
{
|
||||
|
@ -465,7 +460,7 @@ static money32 WallPlace(uint8_t wallType,
|
|||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
rct_banner * banner = &gBanners[bannerIndex];
|
||||
rct_banner* banner = &gBanners[bannerIndex];
|
||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
||||
{
|
||||
banner->flags |= BANNER_FLAG_IS_WALL;
|
||||
|
@ -497,13 +492,7 @@ static money32 WallPlace(uint8_t wallType,
|
|||
bool wallAcrossTrack = false;
|
||||
if (!(flags & GAME_COMMAND_FLAG_PATH_SCENERY) && !gCheatsDisableClearanceChecks)
|
||||
{
|
||||
if (!WallCheckObstruction(wallEntry,
|
||||
position.x,
|
||||
position.y,
|
||||
position.z / 8,
|
||||
clearanceHeight,
|
||||
edge,
|
||||
&wallAcrossTrack))
|
||||
if (!WallCheckObstruction(wallEntry, position.x, position.y, position.z / 8, clearanceHeight, edge, &wallAcrossTrack))
|
||||
{
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
@ -525,7 +514,7 @@ static money32 WallPlace(uint8_t wallType,
|
|||
network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord);
|
||||
}
|
||||
|
||||
rct_tile_element * tileElement = tile_element_insert(position.x / 32, position.y / 32, position.z / 8, 0);
|
||||
rct_tile_element* tileElement = tile_element_insert(position.x / 32, position.y / 32, position.z / 8, 0);
|
||||
assert(tileElement != nullptr);
|
||||
|
||||
map_animation_create(MAP_ANIMATION_TYPE_WALL, position.x, position.y, position.z / 8);
|
||||
|
@ -572,14 +561,15 @@ static money32 WallPlace(uint8_t wallType,
|
|||
}
|
||||
}
|
||||
|
||||
static money32 WallSetColour(int16_t x,
|
||||
int16_t y,
|
||||
uint8_t baseHeight,
|
||||
uint8_t direction,
|
||||
uint8_t primaryColour,
|
||||
uint8_t secondaryColour,
|
||||
uint8_t tertiaryColour,
|
||||
uint8_t flags)
|
||||
static money32 WallSetColour(
|
||||
int16_t x,
|
||||
int16_t y,
|
||||
uint8_t baseHeight,
|
||||
uint8_t direction,
|
||||
uint8_t primaryColour,
|
||||
uint8_t secondaryColour,
|
||||
uint8_t tertiaryColour,
|
||||
uint8_t flags)
|
||||
{
|
||||
gCommandExpenditureType = RCT_EXPENDITURE_TYPE_LANDSCAPING;
|
||||
int32_t z = baseHeight * 8;
|
||||
|
@ -588,15 +578,12 @@ static money32 WallSetColour(int16_t x,
|
|||
gCommandPosition.y = y + 16;
|
||||
gCommandPosition.z = z;
|
||||
|
||||
if (!(gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) &&
|
||||
!map_is_location_in_park({x, y}) &&
|
||||
!gCheatsSandboxMode)
|
||||
if (!(gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) && !map_is_location_in_park({ x, y }) && !gCheatsSandboxMode)
|
||||
{
|
||||
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
rct_tile_element * wallElement = map_get_wall_element_at(x, y, baseHeight, direction);
|
||||
rct_tile_element* wallElement = map_get_wall_element_at(x, y, baseHeight, direction);
|
||||
if (wallElement == nullptr)
|
||||
{
|
||||
return 0;
|
||||
|
@ -609,7 +596,7 @@ static money32 WallSetColour(int16_t x,
|
|||
|
||||
if (flags & GAME_COMMAND_FLAG_APPLY)
|
||||
{
|
||||
rct_scenery_entry * scenery_entry = get_wall_entry(wallElement->properties.wall.type);
|
||||
rct_scenery_entry* scenery_entry = get_wall_entry(wallElement->properties.wall.type);
|
||||
wall_set_primary_colour(wallElement, primaryColour);
|
||||
wall_set_secondary_colour(wallElement, secondaryColour);
|
||||
|
||||
|
@ -623,42 +610,42 @@ static money32 WallSetColour(int16_t x,
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint8_t wall_get_animation_frame(const rct_tile_element * wallElement)
|
||||
uint8_t wall_get_animation_frame(const rct_tile_element* wallElement)
|
||||
{
|
||||
return (wallElement->properties.wall.animation >> 3) & 0xF;
|
||||
}
|
||||
|
||||
void wall_set_animation_frame(rct_tile_element * wallElement, uint8_t frameNum)
|
||||
void wall_set_animation_frame(rct_tile_element* wallElement, uint8_t frameNum)
|
||||
{
|
||||
wallElement->properties.wall.animation &= WALL_ANIMATION_FLAG_ALL_FLAGS;
|
||||
wallElement->properties.wall.animation |= (frameNum & 0xF) << 3;
|
||||
}
|
||||
|
||||
colour_t wall_get_primary_colour(const rct_tile_element * tileElement)
|
||||
colour_t wall_get_primary_colour(const rct_tile_element* tileElement)
|
||||
{
|
||||
return tileElement->properties.wall.colour_1 & TILE_ELEMENT_COLOUR_MASK;
|
||||
}
|
||||
|
||||
colour_t wall_get_secondary_colour(const rct_tile_element * wallElement)
|
||||
colour_t wall_get_secondary_colour(const rct_tile_element* wallElement)
|
||||
{
|
||||
uint8_t secondaryColour = (wallElement->properties.wall.colour_1 &~ TILE_ELEMENT_COLOUR_MASK) >> 5;
|
||||
uint8_t secondaryColour = (wallElement->properties.wall.colour_1 & ~TILE_ELEMENT_COLOUR_MASK) >> 5;
|
||||
secondaryColour |= (wallElement->flags & 0x60) >> 2;
|
||||
return secondaryColour;
|
||||
}
|
||||
|
||||
colour_t wall_get_tertiary_colour(const rct_tile_element * tileElement)
|
||||
colour_t wall_get_tertiary_colour(const rct_tile_element* tileElement)
|
||||
{
|
||||
return tileElement->properties.wall.colour_3 & TILE_ELEMENT_COLOUR_MASK;
|
||||
}
|
||||
|
||||
void wall_set_primary_colour(rct_tile_element * tileElement, colour_t colour)
|
||||
void wall_set_primary_colour(rct_tile_element* tileElement, colour_t colour)
|
||||
{
|
||||
assert(colour <= 31);
|
||||
tileElement->properties.wall.colour_1 &= ~TILE_ELEMENT_COLOUR_MASK;
|
||||
tileElement->properties.wall.colour_1 |= colour;
|
||||
}
|
||||
|
||||
void wall_set_secondary_colour(rct_tile_element * wallElement, colour_t secondaryColour)
|
||||
void wall_set_secondary_colour(rct_tile_element* wallElement, colour_t secondaryColour)
|
||||
{
|
||||
wallElement->properties.wall.colour_1 &= TILE_ELEMENT_COLOUR_MASK;
|
||||
wallElement->properties.wall.colour_1 |= (secondaryColour & 0x7) << 5;
|
||||
|
@ -666,7 +653,7 @@ void wall_set_secondary_colour(rct_tile_element * wallElement, colour_t secondar
|
|||
wallElement->flags |= (secondaryColour & 0x18) << 2;
|
||||
}
|
||||
|
||||
void wall_set_tertiary_colour(rct_tile_element * tileElement, colour_t colour)
|
||||
void wall_set_tertiary_colour(rct_tile_element* tileElement, colour_t colour)
|
||||
{
|
||||
assert(colour <= 31);
|
||||
tileElement->properties.wall.colour_3 &= ~TILE_ELEMENT_COLOUR_MASK;
|
||||
|
@ -679,7 +666,7 @@ void wall_set_tertiary_colour(rct_tile_element * tileElement, colour_t colour)
|
|||
*/
|
||||
void wall_remove_at(int32_t x, int32_t y, int32_t z0, int32_t z1)
|
||||
{
|
||||
rct_tile_element * tileElement;
|
||||
rct_tile_element* tileElement;
|
||||
|
||||
z0 /= 8;
|
||||
z1 /= 8;
|
||||
|
@ -698,8 +685,7 @@ repeat:
|
|||
map_invalidate_tile_zoom1(x, y, tileElement->base_height * 8, tileElement->base_height * 8 + 72);
|
||||
tile_element_remove(tileElement);
|
||||
goto repeat;
|
||||
}
|
||||
while (!(tileElement++)->IsLastForTile());
|
||||
} while (!(tileElement++)->IsLastForTile());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -717,7 +703,7 @@ void wall_remove_at_z(int32_t x, int32_t y, int32_t z)
|
|||
*/
|
||||
void wall_remove_intersecting_walls(int32_t x, int32_t y, int32_t z0, int32_t z1, int32_t direction)
|
||||
{
|
||||
rct_tile_element * tileElement;
|
||||
rct_tile_element* tileElement;
|
||||
|
||||
tileElement = map_get_first_element_at(x >> 5, y >> 5);
|
||||
do
|
||||
|
@ -735,21 +721,15 @@ void wall_remove_intersecting_walls(int32_t x, int32_t y, int32_t z0, int32_t z1
|
|||
map_invalidate_tile_zoom1(x, y, tileElement->base_height * 8, tileElement->base_height * 8 + 72);
|
||||
tile_element_remove(tileElement);
|
||||
tileElement--;
|
||||
}
|
||||
while (!(tileElement++)->IsLastForTile());
|
||||
} while (!(tileElement++)->IsLastForTile());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006E519A
|
||||
*/
|
||||
void game_command_place_wall(int32_t * eax,
|
||||
int32_t * ebx,
|
||||
int32_t * ecx,
|
||||
int32_t * edx,
|
||||
[[maybe_unused]] int32_t * esi,
|
||||
int32_t * edi,
|
||||
int32_t * ebp)
|
||||
void game_command_place_wall(
|
||||
int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, [[maybe_unused]] int32_t* esi, int32_t* edi, int32_t* ebp)
|
||||
{
|
||||
*ebx = WallPlace(
|
||||
(*ebx >> 8) & 0xFF,
|
||||
|
@ -760,19 +740,19 @@ void game_command_place_wall(int32_t * eax,
|
|||
(*edx >> 8) & 0xFF,
|
||||
*ebp & 0xFF,
|
||||
(*ebp >> 8) & 0xFF,
|
||||
*ebx & 0xFF
|
||||
);
|
||||
*ebx & 0xFF);
|
||||
}
|
||||
|
||||
money32 wall_place(int32_t type,
|
||||
int32_t x,
|
||||
int32_t y,
|
||||
int32_t z,
|
||||
int32_t edge,
|
||||
int32_t primaryColour,
|
||||
int32_t secondaryColour,
|
||||
int32_t tertiaryColour,
|
||||
int32_t flags)
|
||||
money32 wall_place(
|
||||
int32_t type,
|
||||
int32_t x,
|
||||
int32_t y,
|
||||
int32_t z,
|
||||
int32_t edge,
|
||||
int32_t primaryColour,
|
||||
int32_t secondaryColour,
|
||||
int32_t tertiaryColour,
|
||||
int32_t flags)
|
||||
{
|
||||
int32_t eax = x;
|
||||
int32_t ebx = flags | (type << 8);
|
||||
|
@ -789,13 +769,14 @@ money32 wall_place(int32_t type,
|
|||
*
|
||||
* rct2: 0x006E56B5
|
||||
*/
|
||||
void game_command_set_wall_colour(int32_t * eax,
|
||||
int32_t * ebx,
|
||||
int32_t * ecx,
|
||||
int32_t * edx,
|
||||
[[maybe_unused]] int32_t * esi,
|
||||
[[maybe_unused]] int32_t * edi,
|
||||
int32_t * ebp)
|
||||
void game_command_set_wall_colour(
|
||||
int32_t* eax,
|
||||
int32_t* ebx,
|
||||
int32_t* ecx,
|
||||
int32_t* edx,
|
||||
[[maybe_unused]] int32_t* esi,
|
||||
[[maybe_unused]] int32_t* edi,
|
||||
int32_t* ebp)
|
||||
{
|
||||
*ebx = WallSetColour(
|
||||
*eax & 0xFFFF,
|
||||
|
@ -805,6 +786,5 @@ void game_command_set_wall_colour(int32_t * eax,
|
|||
(*ebx >> 8) & 0xFF,
|
||||
*ebp & 0xFF,
|
||||
(*ebp >> 8) & 0xFF,
|
||||
*ebx & 0xFF
|
||||
);
|
||||
*ebx & 0xFF);
|
||||
}
|
||||
|
|
|
@ -12,20 +12,21 @@
|
|||
#include "../common.h"
|
||||
#include "TileElement.h"
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
WALL_ANIMATION_FLAG_ACROSS_TRACK = (1 << 2),
|
||||
// 3 - 6 animation frame number
|
||||
WALL_ANIMATION_FLAG_DIRECTION_BACKWARD = (1 << 7),
|
||||
WALL_ANIMATION_FLAG_ALL_FLAGS = WALL_ANIMATION_FLAG_ACROSS_TRACK | WALL_ANIMATION_FLAG_DIRECTION_BACKWARD
|
||||
};
|
||||
|
||||
colour_t wall_get_primary_colour(const rct_tile_element * tileElement);
|
||||
colour_t wall_get_secondary_colour(const rct_tile_element * wallElement);
|
||||
colour_t wall_get_tertiary_colour(const rct_tile_element * tileElement);
|
||||
void wall_set_primary_colour(rct_tile_element * tileElement, colour_t colour);
|
||||
void wall_set_secondary_colour(rct_tile_element * wallElement, colour_t secondaryColour);
|
||||
void wall_set_tertiary_colour(rct_tile_element * tileElement, colour_t colour);
|
||||
uint8_t wall_get_animation_frame(const rct_tile_element * fenceElement);
|
||||
void wall_set_animation_frame(rct_tile_element * wallElement, uint8_t frameNum);
|
||||
colour_t wall_get_primary_colour(const rct_tile_element* tileElement);
|
||||
colour_t wall_get_secondary_colour(const rct_tile_element* wallElement);
|
||||
colour_t wall_get_tertiary_colour(const rct_tile_element* tileElement);
|
||||
void wall_set_primary_colour(rct_tile_element* tileElement, colour_t colour);
|
||||
void wall_set_secondary_colour(rct_tile_element* wallElement, colour_t secondaryColour);
|
||||
void wall_set_tertiary_colour(rct_tile_element* tileElement, colour_t colour);
|
||||
uint8_t wall_get_animation_frame(const rct_tile_element* fenceElement);
|
||||
void wall_set_animation_frame(rct_tile_element* wallElement, uint8_t frameNum);
|
||||
|
||||
money32 wall_remove(int16_t x, int16_t y, uint8_t baseHeight, uint8_t direction, uint8_t flags);
|
||||
|
|
|
@ -12,17 +12,19 @@
|
|||
|
||||
#include "../common.h"
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
WATER_FLAGS_ALLOW_DUCKS = (1 << 0)
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct rct_water_type {
|
||||
rct_string_id string_idx; // 0x00
|
||||
uint32_t image_id; // 0x02
|
||||
uint32_t palette_index_1; // 0x06
|
||||
uint32_t palette_index_2; // 0x0A
|
||||
uint16_t flags; // 0x0E
|
||||
struct rct_water_type
|
||||
{
|
||||
rct_string_id string_idx; // 0x00
|
||||
uint32_t image_id; // 0x02
|
||||
uint32_t palette_index_1; // 0x06
|
||||
uint32_t palette_index_2; // 0x0A
|
||||
uint16_t flags; // 0x0E
|
||||
};
|
||||
assert_struct_size(rct_water_type, 16);
|
||||
#pragma pack(pop)
|
||||
|
|
Loading…
Reference in New Issue