From ec0f4126b068e71322433beba5713d5edbefbb91 Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Tue, 15 Jul 2025 12:02:37 +0200 Subject: [PATCH] Let security guards alternate between slow and fast walking (#24730) * Let security guards alternate between slow and fast walking * Alternate based on amount of nearby guests instead * Optimise loop to exit early once threshold has been reached * Only count walking guests for security crowdedness * Update replay bundle to v0.0.89 * Update NetworkBase.cpp --- CMakeLists.txt | 4 +-- distribution/changelog.txt | 1 + openrct2.deps.targets | 4 +-- src/openrct2/entity/Staff.cpp | 53 +++++++++++++++++++++++++--- src/openrct2/entity/Staff.h | 1 + src/openrct2/network/NetworkBase.cpp | 2 +- 6 files changed, 56 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ac9bb20326..157b42d358 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,9 +82,9 @@ set(OPENMSX_VERSION "1.6") set(OPENMSX_URL "https://github.com/OpenRCT2/OpenMusic/releases/download/v${OPENMSX_VERSION}/openmusic.zip") set(OPENMSX_SHA1 "ba170fa6d777b309c15420f4b6eb3fa25082a9d1") -set(REPLAYS_VERSION "0.0.87") +set(REPLAYS_VERSION "0.0.89") set(REPLAYS_URL "https://github.com/OpenRCT2/replays/releases/download/v${REPLAYS_VERSION}/replays.zip") -set(REPLAYS_SHA1 "6061B53DE346BD853BB997E635AC7374B1A7D2F0") +set(REPLAYS_SHA1 "089CB8EEA76A98028367FDDE72675E9309AB9036") option(FORCE32 "Force 32-bit build. It will add `-m32` to compiler flags.") option(WITH_TESTS "Build tests") diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 4b3f544237..c41e9826ad 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -2,6 +2,7 @@ ------------------------------------------------------------------------ - Feature: [#24468] [Plugin] Add awards to plugin API. - Feature: [#24702] [Plugin] Add bindings for missing cheats (forcedParkRating, ignoreRidePrice, makeAllDestructible). +- Change: [#25967] Security guards now only walk slowly in crowded areas. - Fix: [#24598] Cannot load .park files that use official legacy footpaths by accident. 0.4.24 (2025-07-05) diff --git a/openrct2.deps.targets b/openrct2.deps.targets index 9c2bb75b5f..8f428cde8d 100644 --- a/openrct2.deps.targets +++ b/openrct2.deps.targets @@ -224,8 +224,8 @@ b1b1f1b241d2cbff63a1889c4dc5a09bdf769bfb https://github.com/OpenRCT2/OpenMusic/releases/download/v1.6/openmusic.zip ba170fa6d777b309c15420f4b6eb3fa25082a9d1 - https://github.com/OpenRCT2/replays/releases/download/v0.0.87/replays.zip - 6061B53DE346BD853BB997E635AC7374B1A7D2F0 + https://github.com/OpenRCT2/replays/releases/download/v0.0.89/replays.zip + 089CB8EEA76A98028367FDDE72675E9309AB9036 diff --git a/src/openrct2/entity/Staff.cpp b/src/openrct2/entity/Staff.cpp index 2e81d1353e..faf690a9c1 100644 --- a/src/openrct2/entity/Staff.cpp +++ b/src/openrct2/entity/Staff.cpp @@ -889,7 +889,7 @@ void Staff::EntertainerUpdateNearbyPeeps() const continue; int16_t z_dist = std::abs(z - guest->z); - if (z_dist > 48) + if (z_dist > kTileRadius / 2) continue; int16_t x_dist = std::abs(x - guest->x); @@ -1644,14 +1644,58 @@ bool Staff::UpdatePatrollingFindSweeping() return false; } +bool Staff::SecurityGuardPathIsCrowded() const +{ + // Iterate over tiles within a 3-tile radius (96 units) + constexpr auto kTileRadius = 3; + constexpr auto kLookupRadius = kCoordsXYStep * kTileRadius; + constexpr auto kSecurityPathCrowdedThreshold = 20; + + int16_t guestCount = 0; + + for (int32_t tileX = x - kLookupRadius; tileX <= x + kLookupRadius; tileX += kCoordsXYStep) + { + for (int32_t tileY = y - kLookupRadius; tileY <= y + kLookupRadius; tileY += kCoordsXYStep) + { + for (auto* guest : EntityTileList({ tileX, tileY })) + { + if (guest->x == kLocationNull) + continue; + + int16_t zDist = std::abs(z - guest->z); + if (zDist > kTileRadius / 2) + continue; + + int16_t xDist = std::abs(x - guest->x); + if (xDist > kLookupRadius) + continue; + + int16_t yDist = std::abs(y - guest->y); + if (yDist > kLookupRadius) + continue; + + if (!guest->IsActionWalking()) + continue; + + guestCount++; + if (guestCount >= kSecurityPathCrowdedThreshold) + return true; + } + } + } + + return false; +} + void Staff::Tick128UpdateStaff() { if (AssignedStaffType != StaffType::Security) return; - PeepAnimationGroup newAnimationGroup = PeepAnimationGroup::Alternate; - if (State != PeepState::Patrolling) - newAnimationGroup = PeepAnimationGroup::Normal; + // Alternate between walking animations based on crowd size + auto newAnimationGroup = PeepAnimationGroup::Normal; + if (State == PeepState::Patrolling && SecurityGuardPathIsCrowded()) + newAnimationGroup = PeepAnimationGroup::Alternate; if (AnimationGroup == newAnimationGroup) return; @@ -1665,6 +1709,7 @@ void Staff::Tick128UpdateStaff() auto& objManager = GetContext()->GetObjectManager(); auto* animObj = objManager.GetLoadedObject(AnimationObjectIndex); + // NB: security staff have two animations groups: one regular, and one slow-walking PeepFlags &= ~PEEP_FLAGS_SLOW_WALK; if (animObj->IsSlowWalking(newAnimationGroup)) { diff --git a/src/openrct2/entity/Staff.h b/src/openrct2/entity/Staff.h index 301b9c51db..b9e7bd0c43 100644 --- a/src/openrct2/entity/Staff.h +++ b/src/openrct2/entity/Staff.h @@ -112,6 +112,7 @@ private: Direction HandymanDirectionRandSurface(uint8_t validDirections) const; void EntertainerUpdateNearbyPeeps() const; + bool SecurityGuardPathIsCrowded() const; uint8_t GetValidPatrolDirections(const CoordsXY& loc) const; Direction HandymanDirectionToNearestLitter() const; diff --git a/src/openrct2/network/NetworkBase.cpp b/src/openrct2/network/NetworkBase.cpp index bf50997b2a..3c971727ab 100644 --- a/src/openrct2/network/NetworkBase.cpp +++ b/src/openrct2/network/NetworkBase.cpp @@ -49,7 +49,7 @@ using namespace OpenRCT2; // It is used for making sure only compatible builds get connected, even within // single OpenRCT2 version. -constexpr uint8_t kNetworkStreamVersion = 0; +constexpr uint8_t kNetworkStreamVersion = 1; const std::string kNetworkStreamID = std::string(kOpenRCT2Version) + "-" + std::to_string(kNetworkStreamVersion);