1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2025-12-21 06:43:04 +01:00

Refactor fountain flags

This commit is contained in:
Gymnasiast
2025-03-26 00:45:30 +01:00
parent 74758c77b6
commit 15707d64ec
10 changed files with 80 additions and 66 deletions

View File

@@ -525,7 +525,7 @@ struct GameStateSnapshots final : public IGameStateSnapshots
COMPARE_FIELD(JumpingFountain, frame); COMPARE_FIELD(JumpingFountain, frame);
COMPARE_FIELD(JumpingFountain, FountainType); COMPARE_FIELD(JumpingFountain, FountainType);
COMPARE_FIELD(JumpingFountain, NumTicksAlive); COMPARE_FIELD(JumpingFountain, NumTicksAlive);
COMPARE_FIELD(JumpingFountain, FountainFlags); COMPARE_FIELD(JumpingFountain, fountainFlags);
COMPARE_FIELD(JumpingFountain, TargetX); COMPARE_FIELD(JumpingFountain, TargetX);
COMPARE_FIELD(JumpingFountain, TargetY); COMPARE_FIELD(JumpingFountain, TargetY);
COMPARE_FIELD(JumpingFountain, Iteration); COMPARE_FIELD(JumpingFountain, Iteration);

View File

@@ -19,7 +19,7 @@ struct FlagHolder
FlagHolder() = default; FlagHolder() = default;
template<typename... TTypes> template<typename... TTypes>
FlagHolder(TTypes... types) constexpr FlagHolder(TTypes... types)
: holder(EnumsToFlags(types...)) : holder(EnumsToFlags(types...))
{ {
} }
@@ -85,4 +85,11 @@ struct FlagHolder
{ {
holder ^= EnumToFlag(flag); holder ^= EnumToFlag(flag);
} }
constexpr FlagHolder operator|(const FlagHolder& other) const noexcept
{
FlagHolder res = *this;
res.holder |= other.holder;
return res;
}
}; };

View File

@@ -24,16 +24,16 @@
using namespace OpenRCT2; using namespace OpenRCT2;
enum class PATTERN enum class Pattern
{ {
CYCLIC_SQUARES, cyclicSquares,
CONTINUOUS_CHASERS, continuousChasers,
BOUNCING_PAIRS, bouncingPairs,
SPROUTING_BLOOMS, sproutingBlooms,
RACING_PAIRS, racingPairs,
SPLITTING_CHASERS, splittingChasers,
DOPEY_JUMPERS, dopeyJumpers,
FAST_RANDOM_CHASERS, fastRandomChasers,
}; };
static constexpr std::array _fountainDirectionsNegative = { static constexpr std::array _fountainDirectionsNegative = {
@@ -66,20 +66,20 @@ const uint8_t _fountainDirections[] = {
}; };
// rct2: 0x0097F048 // rct2: 0x0097F048
const uint8_t _fountainDirectionFlags[] = { const FountainFlags _fountainDirectionFlags[] = {
0, 0, FOUNTAIN_FLAG::DIRECTION, FOUNTAIN_FLAG::DIRECTION, FOUNTAIN_FLAG::DIRECTION, FOUNTAIN_FLAG::DIRECTION, 0, 0, {}, {}, FountainFlag::direction, FountainFlag::direction, FountainFlag::direction, FountainFlag::direction, {}, {},
}; };
// rct2: 0x0097F050 // rct2: 0x0097F050
const uint8_t _fountainPatternFlags[] = { const FountainFlags _fountainPatternFlags[] = {
FOUNTAIN_FLAG::TERMINATE, // CYCLIC_SQUARES { FountainFlag::terminate }, // cyclicSquares
FOUNTAIN_FLAG::FAST | FOUNTAIN_FLAG::GOTO_EDGE, // CONTINUOUS_CHASERS { FountainFlag::fast, FountainFlag::goToEdge }, // continuousChasers
FOUNTAIN_FLAG::BOUNCE, // BOUNCING_PAIRS { FountainFlag::bounce }, // bouncingPairs
FOUNTAIN_FLAG::FAST | FOUNTAIN_FLAG::SPLIT, // SPROUTING_BLOOMS { FountainFlag::fast, FountainFlag::split }, // sproutingBlooms
FOUNTAIN_FLAG::GOTO_EDGE, // RACING_PAIRS { FountainFlag::goToEdge }, // racingPairs
FOUNTAIN_FLAG::FAST | FOUNTAIN_FLAG::GOTO_EDGE | FOUNTAIN_FLAG::SPLIT, // SPLITTING_CHASERS { FountainFlag::fast, FountainFlag::goToEdge, FountainFlag::split }, // splittingChasers
0, // DOPEY_JUMPERS {}, // dopeyJumpers
FOUNTAIN_FLAG::FAST, // FAST_RANDOM_CHASERS { FountainFlag::fast }, // fastRandomChasers
}; };
template<> template<>
@@ -97,9 +97,9 @@ void JumpingFountain::StartAnimation(const JumpingFountainType newType, const Co
// Change pattern approximately every 51 seconds // Change pattern approximately every 51 seconds
uint32_t pattern = (currentTicks >> 11) & 7; uint32_t pattern = (currentTicks >> 11) & 7;
switch (static_cast<PATTERN>(pattern)) switch (static_cast<Pattern>(pattern))
{ {
case PATTERN::CYCLIC_SQUARES: case Pattern::cyclicSquares:
// 0, 1, 2, 3 // 0, 1, 2, 3
for (int32_t i = 0; i < kNumOrthogonalDirections; i++) for (int32_t i = 0; i < kNumOrthogonalDirections; i++)
{ {
@@ -108,7 +108,7 @@ void JumpingFountain::StartAnimation(const JumpingFountainType newType, const Co
_fountainDirectionFlags[i] | _fountainPatternFlags[pattern], 0); _fountainDirectionFlags[i] | _fountainPatternFlags[pattern], 0);
} }
break; break;
case PATTERN::BOUNCING_PAIRS: case Pattern::bouncingPairs:
// random [0, 2 or 1, 3] // random [0, 2 or 1, 3]
randomIndex = ScenarioRand() & 1; randomIndex = ScenarioRand() & 1;
for (int32_t i = randomIndex; i < kNumOrthogonalDirections; i += 2) for (int32_t i = randomIndex; i < kNumOrthogonalDirections; i += 2)
@@ -118,7 +118,7 @@ void JumpingFountain::StartAnimation(const JumpingFountainType newType, const Co
_fountainDirectionFlags[i] | _fountainPatternFlags[pattern], 0); _fountainDirectionFlags[i] | _fountainPatternFlags[pattern], 0);
} }
break; break;
case PATTERN::RACING_PAIRS: case Pattern::racingPairs:
// random [0 - 3 and 4 - 7] // random [0 - 3 and 4 - 7]
randomIndex = ScenarioRand() & 3; randomIndex = ScenarioRand() & 3;
JumpingFountain::Create( JumpingFountain::Create(
@@ -140,14 +140,14 @@ void JumpingFountain::StartAnimation(const JumpingFountainType newType, const Co
} }
void JumpingFountain::Create( void JumpingFountain::Create(
const JumpingFountainType newType, const CoordsXYZ& newLoc, const int32_t direction, const int32_t newFlags, const JumpingFountainType newType, const CoordsXYZ& newLoc, const int32_t direction, const OpenRCT2::FountainFlags newFlags,
const int32_t iteration) const int32_t iteration)
{ {
auto* jumpingFountain = CreateEntity<JumpingFountain>(); auto* jumpingFountain = CreateEntity<JumpingFountain>();
if (jumpingFountain != nullptr) if (jumpingFountain != nullptr)
{ {
jumpingFountain->Iteration = iteration; jumpingFountain->Iteration = iteration;
jumpingFountain->FountainFlags = newFlags; jumpingFountain->fountainFlags = newFlags;
jumpingFountain->Orientation = direction << 3; jumpingFountain->Orientation = direction << 3;
jumpingFountain->SpriteData.Width = 33; jumpingFountain->SpriteData.Width = 33;
jumpingFountain->SpriteData.HeightMin = 36; jumpingFountain->SpriteData.HeightMin = 36;
@@ -177,11 +177,11 @@ void JumpingFountain::Update()
switch (FountainType) switch (FountainType)
{ {
case JumpingFountainType::Water: case JumpingFountainType::Water:
if (frame == 11 && (FountainFlags & FOUNTAIN_FLAG::FAST)) if (frame == 11 && (fountainFlags.has(FountainFlag::fast)))
{ {
AdvanceAnimation(); AdvanceAnimation();
} }
if (frame == 16 && !(FountainFlags & FOUNTAIN_FLAG::FAST)) if (frame == 16 && !(fountainFlags.has(FountainFlag::fast)))
{ {
AdvanceAnimation(); AdvanceAnimation();
} }
@@ -227,24 +227,24 @@ void JumpingFountain::AdvanceAnimation()
return; return;
} }
if (FountainFlags & FOUNTAIN_FLAG::TERMINATE) if (fountainFlags.has(FountainFlag::terminate))
{ {
return; return;
} }
if (FountainFlags & FOUNTAIN_FLAG::GOTO_EDGE) if (fountainFlags.has(FountainFlag::goToEdge))
{ {
GoToEdge({ newLoc, z }, availableDirections); GoToEdge({ newLoc, z }, availableDirections);
return; return;
} }
if (FountainFlags & FOUNTAIN_FLAG::BOUNCE) if (fountainFlags.has(FountainFlag::bounce))
{ {
Bounce({ newLoc, z }, availableDirections); Bounce({ newLoc, z }, availableDirections);
return; return;
} }
if (FountainFlags & FOUNTAIN_FLAG::SPLIT) if (fountainFlags.has(FountainFlag::split))
{ {
Split({ newLoc, z }, availableDirections); Split({ newLoc, z }, availableDirections);
return; return;
@@ -304,7 +304,7 @@ void JumpingFountain::GoToEdge(const CoordsXYZ& newLoc, const int32_t availableD
return; return;
} }
if (FountainFlags & FOUNTAIN_FLAG::SPLIT) if (fountainFlags.has(FountainFlag::split))
{ {
Split(newLoc, availableDirections); Split(newLoc, availableDirections);
return; return;
@@ -353,14 +353,16 @@ void JumpingFountain::Split(const CoordsXYZ& newLoc, int32_t availableDirections
{ {
if (availableDirections & (1 << direction)) if (availableDirections & (1 << direction))
{ {
JumpingFountain::Create( auto copiedFlags = fountainFlags;
newType, newLoc, direction >> 1, FountainFlags & ~FOUNTAIN_FLAG::DIRECTION, Iteration + 1); copiedFlags.unset(FountainFlag::direction);
JumpingFountain::Create(newType, newLoc, direction >> 1, copiedFlags, Iteration + 1);
} }
direction++; direction++;
if (availableDirections & (1 << direction)) if (availableDirections & (1 << direction))
{ {
JumpingFountain::Create( auto copiedFlags = fountainFlags;
newType, newLoc, direction >> 1, FountainFlags | FOUNTAIN_FLAG::DIRECTION, Iteration + 1); copiedFlags.set(FountainFlag::direction);
JumpingFountain::Create(newType, newLoc, direction >> 1, copiedFlags, Iteration + 1);
} }
} }
} }
@@ -383,11 +385,8 @@ void JumpingFountain::Random(const CoordsXYZ& newLoc, int32_t availableDirection
void JumpingFountain::CreateNext(const CoordsXYZ& newLoc, int32_t direction) const void JumpingFountain::CreateNext(const CoordsXYZ& newLoc, int32_t direction) const
{ {
const auto newType = GetType(); const auto newType = GetType();
int32_t newFlags = FountainFlags & ~FOUNTAIN_FLAG::DIRECTION; auto newFlags = fountainFlags;
if (direction & 1) newFlags.set(FountainFlag::direction, !!(direction & 1));
{
newFlags |= FOUNTAIN_FLAG::DIRECTION;
}
JumpingFountain::Create(newType, newLoc, direction >> 1, newFlags, Iteration); JumpingFountain::Create(newType, newLoc, direction >> 1, newFlags, Iteration);
} }
@@ -397,7 +396,7 @@ void JumpingFountain::Serialise(DataSerialiser& stream)
stream << frame; stream << frame;
stream << FountainType; stream << FountainType;
stream << NumTicksAlive; stream << NumTicksAlive;
stream << FountainFlags; stream << fountainFlags.holder;
stream << TargetX; stream << TargetX;
stream << TargetY; stream << TargetY;
stream << Iteration; stream << Iteration;
@@ -421,7 +420,7 @@ void JumpingFountain::Paint(PaintSession& session, int32_t imageDirection) const
imageDirection = imageDirection / 8; imageDirection = imageDirection / 8;
// Fountain is firing anti clockwise // Fountain is firing anti clockwise
bool reversed = (FountainFlags & FOUNTAIN_FLAG::DIRECTION); bool reversed = fountainFlags.has(FountainFlag::direction);
// Fountain rotation // Fountain rotation
bool rotated = (Orientation / 16) & 1; bool rotated = (Orientation / 16) & 1;
bool isAntiClockwise = (imageDirection / 2) & 1; // Clockwise or Anti-clockwise bool isAntiClockwise = (imageDirection / 2) & 1; // Clockwise or Anti-clockwise

View File

@@ -9,12 +9,27 @@
#pragma once #pragma once
#include "../core/FlagHolder.hpp"
#include "../world/Map.h" #include "../world/Map.h"
#include "EntityBase.h" #include "EntityBase.h"
class DataSerialiser; class DataSerialiser;
struct PaintSession; struct PaintSession;
namespace OpenRCT2
{
enum class FountainFlag : uint8_t
{
fast,
goToEdge,
split,
terminate,
bounce,
direction = 7,
};
using FountainFlags = FlagHolder<uint8_t, FountainFlag>;
} // namespace OpenRCT2
enum class JumpingFountainType : uint8_t enum class JumpingFountainType : uint8_t
{ {
Water, Water,
@@ -28,7 +43,7 @@ struct JumpingFountain : EntityBase
uint16_t frame; uint16_t frame;
JumpingFountainType FountainType; JumpingFountainType FountainType;
uint8_t NumTicksAlive; uint8_t NumTicksAlive;
uint8_t FountainFlags; OpenRCT2::FountainFlags fountainFlags;
int16_t TargetX; int16_t TargetX;
int16_t TargetY; int16_t TargetY;
uint16_t Iteration; uint16_t Iteration;
@@ -46,16 +61,7 @@ private:
void Random(const CoordsXYZ& newLoc, int32_t availableDirections) const; void Random(const CoordsXYZ& newLoc, int32_t availableDirections) const;
void CreateNext(const CoordsXYZ& newLoc, int32_t direction) const; void CreateNext(const CoordsXYZ& newLoc, int32_t direction) const;
static void Create( static void Create(
JumpingFountainType newType, const CoordsXYZ& newLoc, int32_t direction, int32_t newFlags, int32_t iteration); JumpingFountainType newType, const CoordsXYZ& newLoc, int32_t direction, OpenRCT2::FountainFlags newFlags,
int32_t iteration);
static bool IsJumpingFountain(JumpingFountainType newType, const CoordsXYZ& newLoc); static bool IsJumpingFountain(JumpingFountainType newType, const CoordsXYZ& newLoc);
}; };
namespace OpenRCT2::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;
}; // namespace OpenRCT2::FOUNTAIN_FLAG

View File

@@ -2557,7 +2557,7 @@ namespace OpenRCT2
ReadWriteEntityCommon(cs, fountain); ReadWriteEntityCommon(cs, fountain);
cs.ReadWrite(fountain.NumTicksAlive); cs.ReadWrite(fountain.NumTicksAlive);
cs.ReadWrite(fountain.frame); cs.ReadWrite(fountain.frame);
cs.ReadWrite(fountain.FountainFlags); cs.ReadWrite(fountain.fountainFlags.holder);
cs.ReadWrite(fountain.TargetX); cs.ReadWrite(fountain.TargetX);
cs.ReadWrite(fountain.TargetY); cs.ReadWrite(fountain.TargetY);
cs.ReadWrite(fountain.TargetY); cs.ReadWrite(fountain.TargetY);

View File

@@ -703,7 +703,7 @@ namespace OpenRCT2::RCT1
RCT12EntityLitter Litter; RCT12EntityLitter Litter;
RCT12EntityBalloon Balloon; RCT12EntityBalloon Balloon;
RCT12EntityDuck Duck; RCT12EntityDuck Duck;
RCT12EntityJumpingFountain JumpingFountain; RCT12EntityJumpingFountain JumpingFountain{};
RCT12EntityMoneyEffect MoneyEffect; RCT12EntityMoneyEffect MoneyEffect;
RCT12EntityCrashedVehicleParticle CrashedVehicleParticle; RCT12EntityCrashedVehicleParticle CrashedVehicleParticle;
RCT12EntityCrashSplash CrashSplash; RCT12EntityCrashSplash CrashSplash;

View File

@@ -3089,7 +3089,7 @@ namespace OpenRCT2::RCT1
dst->frame = src->Frame; dst->frame = src->Frame;
dst->FountainType = fountainType; dst->FountainType = fountainType;
dst->NumTicksAlive = src->NumTicksAlive; dst->NumTicksAlive = src->NumTicksAlive;
dst->FountainFlags = src->FountainFlags; dst->fountainFlags = src->fountainFlags;
dst->TargetX = src->TargetX; dst->TargetX = src->TargetX;
dst->TargetY = src->TargetY; dst->TargetY = src->TargetY;
dst->Iteration = src->Iteration; dst->Iteration = src->Iteration;

View File

@@ -12,7 +12,9 @@
// Structures shared between both RCT1 and RCT2. // Structures shared between both RCT1 and RCT2.
#include "../core/EnumUtils.hpp" #include "../core/EnumUtils.hpp"
#include "../core/FlagHolder.hpp"
#include "../core/Money.hpp" #include "../core/Money.hpp"
#include "../entity/Fountain.h"
#include "../management/Research.h" #include "../management/Research.h"
#include "../object/Object.h" #include "../object/Object.h"
#include "../ride/RideTypes.h" #include "../ride/RideTypes.h"
@@ -1116,7 +1118,7 @@ struct RCT12EntityJumpingFountain : RCT12EntityBase
uint8_t NumTicksAlive; // 0x26 uint8_t NumTicksAlive; // 0x26
uint8_t Frame; // 0x27 uint8_t Frame; // 0x27
uint8_t Pad28[0x2F - 0x28]; uint8_t Pad28[0x2F - 0x28];
uint8_t FountainFlags; // 0x2F OpenRCT2::FountainFlags fountainFlags{}; // 0x2F
int16_t TargetX; // 0x30 int16_t TargetX; // 0x30
int16_t TargetY; // 0x32 int16_t TargetY; // 0x32
uint8_t Pad34[0x46 - 0x34]; uint8_t Pad34[0x46 - 0x34];

View File

@@ -708,7 +708,7 @@ namespace OpenRCT2::RCT2
RCT12EntityLitter Litter; RCT12EntityLitter Litter;
RCT12EntityBalloon Balloon; RCT12EntityBalloon Balloon;
RCT12EntityDuck Duck; RCT12EntityDuck Duck;
RCT12EntityJumpingFountain JumpingFountain; RCT12EntityJumpingFountain JumpingFountain{};
RCT12EntityMoneyEffect MoneyEffect; RCT12EntityMoneyEffect MoneyEffect;
RCT12EntityCrashedVehicleParticle CrashedVehicleParticle; RCT12EntityCrashedVehicleParticle CrashedVehicleParticle;
RCT12EntityCrashSplash CrashSplash; RCT12EntityCrashSplash CrashSplash;

View File

@@ -2231,7 +2231,7 @@ namespace OpenRCT2::RCT2
ImportEntityCommonProperties(dst, src); ImportEntityCommonProperties(dst, src);
dst->NumTicksAlive = src->NumTicksAlive; dst->NumTicksAlive = src->NumTicksAlive;
dst->frame = src->Frame; dst->frame = src->Frame;
dst->FountainFlags = src->FountainFlags; dst->fountainFlags = src->fountainFlags;
dst->TargetX = src->TargetX; dst->TargetX = src->TargetX;
dst->TargetY = src->TargetY; dst->TargetY = src->TargetY;
dst->Iteration = src->Iteration; dst->Iteration = src->Iteration;