1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2025-12-10 09:32:29 +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, FountainType);
COMPARE_FIELD(JumpingFountain, NumTicksAlive);
COMPARE_FIELD(JumpingFountain, FountainFlags);
COMPARE_FIELD(JumpingFountain, fountainFlags);
COMPARE_FIELD(JumpingFountain, TargetX);
COMPARE_FIELD(JumpingFountain, TargetY);
COMPARE_FIELD(JumpingFountain, Iteration);

View File

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

View File

@@ -9,12 +9,27 @@
#pragma once
#include "../core/FlagHolder.hpp"
#include "../world/Map.h"
#include "EntityBase.h"
class DataSerialiser;
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
{
Water,
@@ -28,7 +43,7 @@ struct JumpingFountain : EntityBase
uint16_t frame;
JumpingFountainType FountainType;
uint8_t NumTicksAlive;
uint8_t FountainFlags;
OpenRCT2::FountainFlags fountainFlags;
int16_t TargetX;
int16_t TargetY;
uint16_t Iteration;
@@ -46,16 +61,7 @@ private:
void Random(const CoordsXYZ& newLoc, int32_t availableDirections) const;
void CreateNext(const CoordsXYZ& newLoc, int32_t direction) const;
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);
};
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);
cs.ReadWrite(fountain.NumTicksAlive);
cs.ReadWrite(fountain.frame);
cs.ReadWrite(fountain.FountainFlags);
cs.ReadWrite(fountain.fountainFlags.holder);
cs.ReadWrite(fountain.TargetX);
cs.ReadWrite(fountain.TargetY);
cs.ReadWrite(fountain.TargetY);

View File

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

View File

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

View File

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

View File

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

View File

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