From ed6bde7d5600e3f7a5beec3b54c398b0330bcde7 Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Sat, 29 Jun 2024 14:42:09 +0200 Subject: [PATCH 1/7] Introduce peep flags for static positions and animations --- distribution/openrct2.d.ts | 4 +++- src/openrct2/entity/Guest.cpp | 10 +++++++++- src/openrct2/entity/Peep.cpp | 5 +++++ src/openrct2/entity/Peep.h | 2 ++ src/openrct2/scripting/bindings/entity/ScPeep.hpp | 2 ++ 5 files changed, 21 insertions(+), 2 deletions(-) diff --git a/distribution/openrct2.d.ts b/distribution/openrct2.d.ts index f335ab7716..e1bcce131a 100644 --- a/distribution/openrct2.d.ts +++ b/distribution/openrct2.d.ts @@ -2743,7 +2743,9 @@ declare global { "joy" | "angry" | "iceCream" | - "hereWeAre"; + "hereWeAre" | + "positionFrozen" | + "animationFrozen"; /** * @deprecated since version 34, use EntityType instead. diff --git a/src/openrct2/entity/Guest.cpp b/src/openrct2/entity/Guest.cpp index 85b1b7e48a..5e4b89230e 100644 --- a/src/openrct2/entity/Guest.cpp +++ b/src/openrct2/entity/Guest.cpp @@ -979,7 +979,10 @@ void Guest::Tick128UpdateGuest(uint32_t index) } } - UpdateSpriteType(); + if (!(PeepFlags & PEEP_FLAGS_ANIMATION_FROZEN)) + { + UpdateSpriteType(); + } if (State == PeepState::OnRide || State == PeepState::EnteringRide) { @@ -1009,6 +1012,11 @@ void Guest::Tick128UpdateGuest(uint32_t index) } } + if (PeepFlags & PEEP_FLAGS_POSITION_FROZEN) + { + return; + } + if (State == PeepState::Walking && !OutsideOfPark && !(PeepFlags & PEEP_FLAGS_LEAVING_PARK) && GuestNumRides == 0 && GuestHeadingToRideId.IsNull()) { diff --git a/src/openrct2/entity/Peep.cpp b/src/openrct2/entity/Peep.cpp index d1a2a7cb33..53868dc28e 100644 --- a/src/openrct2/entity/Peep.cpp +++ b/src/openrct2/entity/Peep.cpp @@ -956,6 +956,11 @@ static void GuestUpdateThoughts(Guest* peep) */ void Peep::Update() { + if (PeepFlags & PEEP_FLAGS_POSITION_FROZEN) + { + return; + } + auto* guest = As(); if (guest != nullptr) { diff --git a/src/openrct2/entity/Peep.h b/src/openrct2/entity/Peep.h index ae934c8522..b559ae7be5 100644 --- a/src/openrct2/entity/Peep.h +++ b/src/openrct2/entity/Peep.h @@ -227,6 +227,8 @@ enum PeepFlags : uint32_t PEEP_FLAGS_INTAMIN_DEPRECATED = (1 << 27), // Used to make the peep think "I'm so excited - It's an Intamin ride!" while // riding on a Intamin ride. PEEP_FLAGS_HERE_WE_ARE = (1 << 28), // Makes the peep think "...and here we are on X!" while riding a ride + PEEP_FLAGS_POSITION_FROZEN = (1 << 29), // Prevents the peep from moving around, thus keeping them in place + PEEP_FLAGS_ANIMATION_FROZEN = (1 << 30), // Prevents the peep sprite from updating PEEP_FLAGS_TWITCH_DEPRECATED = (1u << 31), // Formerly used for twitch integration }; diff --git a/src/openrct2/scripting/bindings/entity/ScPeep.hpp b/src/openrct2/scripting/bindings/entity/ScPeep.hpp index 2ccbb5f4d7..9ad34699f3 100644 --- a/src/openrct2/scripting/bindings/entity/ScPeep.hpp +++ b/src/openrct2/scripting/bindings/entity/ScPeep.hpp @@ -41,6 +41,8 @@ namespace OpenRCT2::Scripting { "angry", PEEP_FLAGS_ANGRY }, { "iceCream", PEEP_FLAGS_ICE_CREAM }, { "hereWeAre", PEEP_FLAGS_HERE_WE_ARE }, + { "positionFrozen", PEEP_FLAGS_POSITION_FROZEN }, + { "animationFrozen", PEEP_FLAGS_ANIMATION_FROZEN }, }); class ScPeep : public ScEntity From 0efbf7f5ea3c5520a2829b5d1be961217da78c7d Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Sat, 29 Jun 2024 15:25:40 +0200 Subject: [PATCH 2/7] Split off Update{Action,Walking}Animation and use for frozen peeps --- src/openrct2/entity/Peep.cpp | 42 +++++++++++++++++++++++++++++------- src/openrct2/entity/Peep.h | 2 ++ 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/openrct2/entity/Peep.cpp b/src/openrct2/entity/Peep.cpp index 53868dc28e..cbbd245525 100644 --- a/src/openrct2/entity/Peep.cpp +++ b/src/openrct2/entity/Peep.cpp @@ -428,18 +428,13 @@ std::optional Peep::UpdateAction(int16_t& xy_distance) return UpdateWalkingAction(differenceLoc, xy_distance); } - const PeepAnimation& peepAnimation = GetPeepAnimation(SpriteType, ActionSpriteType); - ActionFrame++; - - // If last frame of action - if (ActionFrame >= peepAnimation.frame_offsets.size()) + if (!UpdateActionAnimation()) { ActionSpriteImageOffset = 0; Action = PeepActionType::Walking; UpdateCurrentActionSpriteType(); return { { x, y } }; } - ActionSpriteImageOffset = peepAnimation.frame_offsets[ActionFrame]; // Should we throw up, and are we at the frame where sick appears? auto* guest = As(); @@ -451,6 +446,21 @@ std::optional Peep::UpdateAction(int16_t& xy_distance) return { { x, y } }; } +bool Peep::UpdateActionAnimation() +{ + const PeepAnimation& peepAnimation = GetPeepAnimation(SpriteType, ActionSpriteType); + ActionFrame++; + + // If last frame of action + if (ActionFrame >= peepAnimation.frame_offsets.size()) + { + return false; + } + + ActionSpriteImageOffset = peepAnimation.frame_offsets[ActionFrame]; + return true; +} + std::optional Peep::UpdateWalkingAction(const CoordsXY& differenceLoc, int16_t& xy_distance) { if (!IsActionWalking()) @@ -489,6 +499,13 @@ std::optional Peep::UpdateWalkingAction(const CoordsXY& differenceLoc, CoordsXY loc = { x, y }; loc += walkingOffsetByDirection[nextDirection]; + UpdateWalkingAnimation(); + + return loc; +} + +void Peep::UpdateWalkingAnimation() +{ WalkingFrameNum++; const PeepAnimation& peepAnimation = GetPeepAnimation(SpriteType, ActionSpriteType); if (WalkingFrameNum >= peepAnimation.frame_offsets.size()) @@ -496,8 +513,6 @@ std::optional Peep::UpdateWalkingAction(const CoordsXY& differenceLoc, WalkingFrameNum = 0; } ActionSpriteImageOffset = peepAnimation.frame_offsets[WalkingFrameNum]; - - return loc; } void Peep::ThrowUp() @@ -958,6 +973,17 @@ void Peep::Update() { if (PeepFlags & PEEP_FLAGS_POSITION_FROZEN) { + if (!(PeepFlags & PEEP_FLAGS_ANIMATION_FROZEN)) + { + // This is circumventing other logic, so only update every few ticks + if ((GetGameState().CurrentTicks & 3) == 0) + { + if (IsActionWalking()) + UpdateWalkingAnimation(); + else + UpdateActionAnimation(); + } + } return; } diff --git a/src/openrct2/entity/Peep.h b/src/openrct2/entity/Peep.h index b559ae7be5..7aaa2ba79d 100644 --- a/src/openrct2/entity/Peep.h +++ b/src/openrct2/entity/Peep.h @@ -377,7 +377,9 @@ public: // Peep void Update(); std::optional UpdateAction(int16_t& xy_distance); std::optional UpdateAction(); + bool UpdateActionAnimation(); std::optional UpdateWalkingAction(const CoordsXY& differenceLoc, int16_t& xy_distance); + void UpdateWalkingAnimation(); void ThrowUp(); void SetState(PeepState new_state); void Remove(); From 666e8a15183d04f56ac869a13e337d143b691d0f Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Sat, 29 Jun 2024 16:05:54 +0200 Subject: [PATCH 3/7] Prevent assigning invalid energy values to peeps --- src/openrct2/scripting/bindings/entity/ScPeep.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/openrct2/scripting/bindings/entity/ScPeep.hpp b/src/openrct2/scripting/bindings/entity/ScPeep.hpp index 9ad34699f3..54b92a8e4d 100644 --- a/src/openrct2/scripting/bindings/entity/ScPeep.hpp +++ b/src/openrct2/scripting/bindings/entity/ScPeep.hpp @@ -151,6 +151,7 @@ namespace OpenRCT2::Scripting auto peep = GetPeep(); if (peep != nullptr) { + value = std::clamp(value, kPeepMinEnergy, kPeepMaxEnergy); peep->Energy = value; } } @@ -166,6 +167,7 @@ namespace OpenRCT2::Scripting auto peep = GetPeep(); if (peep != nullptr) { + value = std::clamp(value, kPeepMinEnergy, kPeepMaxEnergyTarget); peep->EnergyTarget = value; } } From 7dcedfb260b7f4a2f34f4cb3f860072e3af235ca Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Wed, 3 Jul 2024 23:09:56 +0200 Subject: [PATCH 4/7] Prevent having ANIMATION_FROZEN set while POSITION_FROZEN is not --- src/openrct2/entity/Peep.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/openrct2/entity/Peep.cpp b/src/openrct2/entity/Peep.cpp index cbbd245525..c928b29bfd 100644 --- a/src/openrct2/entity/Peep.cpp +++ b/src/openrct2/entity/Peep.cpp @@ -986,6 +986,13 @@ void Peep::Update() } return; } + else if (PeepFlags & PEEP_FLAGS_ANIMATION_FROZEN) + { + // Animation is frozen while position is not. This allows a peep to walk + // around without its sprite being updated, which looks very glitchy. + // We'll just remove the flag and continue as normal, in this case. + PeepFlags &= ~PEEP_FLAGS_ANIMATION_FROZEN; + } auto* guest = As(); if (guest != nullptr) From f2c266d31013e8e17109fa79c7b1b899cdf5c02f Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Fri, 5 Jul 2024 15:46:03 +0200 Subject: [PATCH 5/7] Allow scripts to manipulate peep directions --- distribution/openrct2.d.ts | 5 +++++ .../scripting/bindings/entity/ScPeep.hpp | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/distribution/openrct2.d.ts b/distribution/openrct2.d.ts index e1bcce131a..a1a9cfb76e 100644 --- a/distribution/openrct2.d.ts +++ b/distribution/openrct2.d.ts @@ -2694,6 +2694,11 @@ declare global { */ destination: CoordsXY; + /** + * The peep's orthogonal direction, from 0 to 3. + */ + direction: Direction; + /** * How tired the guest is between 32 and 128 where lower is more tired. */ diff --git a/src/openrct2/scripting/bindings/entity/ScPeep.hpp b/src/openrct2/scripting/bindings/entity/ScPeep.hpp index 54b92a8e4d..8cc4d4287a 100644 --- a/src/openrct2/scripting/bindings/entity/ScPeep.hpp +++ b/src/openrct2/scripting/bindings/entity/ScPeep.hpp @@ -59,6 +59,7 @@ namespace OpenRCT2::Scripting dukglue_register_property(ctx, &ScPeep::peepType_get, nullptr, "peepType"); dukglue_register_property(ctx, &ScPeep::name_get, &ScPeep::name_set, "name"); dukglue_register_property(ctx, &ScPeep::destination_get, &ScPeep::destination_set, "destination"); + dukglue_register_property(ctx, &ScPeep::direction_get, &ScPeep::direction_set, "direction"); dukglue_register_property(ctx, &ScPeep::energy_get, &ScPeep::energy_set, "energy"); dukglue_register_property(ctx, &ScPeep::energyTarget_get, &ScPeep::energyTarget_set, "energyTarget"); dukglue_register_method(ctx, &ScPeep::getFlag, "getFlag"); @@ -140,6 +141,23 @@ namespace OpenRCT2::Scripting } } + uint8_t direction_get() const + { + auto peep = GetPeep(); + return peep != nullptr ? peep->PeepDirection : 0; + } + + void direction_set(const uint8_t value) + { + ThrowIfGameStateNotMutable(); + auto peep = GetPeep(); + if (peep != nullptr && value < kNumOrthogonalDirections) + { + peep->PeepDirection = value; + peep->Orientation = value << 3; + } + } + uint8_t energy_get() const { auto peep = GetPeep(); From 83e5aeb9c5ee851256aa838e3fbb40b5190bdb84 Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Sat, 6 Jul 2024 15:14:12 +0200 Subject: [PATCH 6/7] Increment versions for park format, script engine, network for new flags --- src/openrct2/network/NetworkBase.cpp | 2 +- src/openrct2/park/ParkFile.h | 2 +- src/openrct2/scripting/ScriptEngine.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/openrct2/network/NetworkBase.cpp b/src/openrct2/network/NetworkBase.cpp index d937276c54..07cd6958d8 100644 --- a/src/openrct2/network/NetworkBase.cpp +++ b/src/openrct2/network/NetworkBase.cpp @@ -47,7 +47,7 @@ using namespace OpenRCT2; // It is used for making sure only compatible builds get connected, even within // single OpenRCT2 version. -constexpr uint8_t kNetworkStreamVersion = 2; +constexpr uint8_t kNetworkStreamVersion = 3; const std::string kNetworkStreamID = std::string(OPENRCT2_VERSION) + "-" + std::to_string(kNetworkStreamVersion); diff --git a/src/openrct2/park/ParkFile.h b/src/openrct2/park/ParkFile.h index 3aef7d103b..da6bf79e7c 100644 --- a/src/openrct2/park/ParkFile.h +++ b/src/openrct2/park/ParkFile.h @@ -11,7 +11,7 @@ namespace OpenRCT2 struct GameState_t; // Current version that is saved. - constexpr uint32_t PARK_FILE_CURRENT_VERSION = 33; + constexpr uint32_t PARK_FILE_CURRENT_VERSION = 34; // The minimum version that is forwards compatible with the current version. constexpr uint32_t PARK_FILE_MIN_VERSION = 33; diff --git a/src/openrct2/scripting/ScriptEngine.h b/src/openrct2/scripting/ScriptEngine.h index f54e969390..0ccdce54a5 100644 --- a/src/openrct2/scripting/ScriptEngine.h +++ b/src/openrct2/scripting/ScriptEngine.h @@ -47,7 +47,7 @@ namespace OpenRCT2 namespace OpenRCT2::Scripting { - static constexpr int32_t OPENRCT2_PLUGIN_API_VERSION = 93; + static constexpr int32_t OPENRCT2_PLUGIN_API_VERSION = 94; // Versions marking breaking changes. static constexpr int32_t API_VERSION_33_PEEP_DEPRECATION = 33; From 7adf817fa69fa469da38c3e562b8313460509a6a Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Sat, 6 Jul 2024 15:16:08 +0200 Subject: [PATCH 7/7] Amend changelog --- distribution/changelog.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 81e2ebcdf4..7b00e66426 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -12,6 +12,8 @@ - Feature: [#22090] [Plugin] Allow writing of paused state in non-networked settings. - Feature: [#22140] Add option to automatically close dropdown menus if Enlarged UI is enabled. - Feature: [#22150] [Plugin] Expose monthly expenditure history to the plugin API. +- Feature: [#22210] [Plugin] Peeps can now be made stationary or completely frozen. +- Feature: [#22210] [Plugin] The direction in which a peep is facing can now be manipulated. - Improved: [#19870] Allow using new colours in UI themes. - Improved: [#21774] The Alpine Coaster now supports using the alternative colour schemes. - Improved: [#21853] Dropdowns now automatically use multiple columns if they are too tall for the screen.