1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-06 06:32:56 +01:00

Fix #15193: Crash when rides/stalls are demolished

This commit is contained in:
ζeh Matt
2021-08-15 05:28:08 -07:00
committed by GitHub
parent d6ad9b67e7
commit 175394f15b
4 changed files with 115 additions and 83 deletions

View File

@@ -13,6 +13,7 @@
- Fix: [#15148] Track Designs Manager delete confirmation window doesn't display properly.
- Fix: [#15170] Plugin: incorrect label text alignment.
- Fix: [#15184] Crash when hovering over water types in Object Selection.
- Fix: [#15193] Crash when rides/stalls are demolished.
- Improved: [#3417] Crash dumps are now placed in their own folder.
- Change: [#8601] Revert ToonTower base block fix to re-enable support blocking.
- Change: [#15174] [Plugin] Deprecate the type "peep" and add support to target a specific scripting api version.

View File

@@ -136,89 +136,7 @@ GameActions::Result::Ptr RideDemolishAction::DemolishRide(Ride* ride) const
for (auto peep : EntityList<Guest>())
{
uint8_t ride_id_bit = _rideIndex % 8;
uint8_t ride_id_offset = _rideIndex / 8;
// clear ride from potentially being in RidesBeenOn
peep->RidesBeenOn[ride_id_offset] &= ~(1 << ride_id_bit);
if (peep->State == PeepState::Watching)
{
if (peep->CurrentRide == _rideIndex)
{
peep->CurrentRide = RIDE_ID_NULL;
if (peep->TimeToStand >= 50)
{
// make peep stop watching the ride
peep->TimeToStand = 50;
}
}
}
// remove any free voucher for this ride from peep
if (peep->HasItem(ShopItem::Voucher))
{
if (peep->VoucherType == VOUCHER_TYPE_RIDE_FREE && peep->VoucherRideId == _rideIndex)
{
peep->RemoveItem(ShopItem::Voucher);
}
}
// remove any photos of this ride from peep
if (peep->HasItem(ShopItem::Photo))
{
if (peep->Photo1RideRef == _rideIndex)
{
peep->RemoveItem(ShopItem::Photo);
}
}
if (peep->HasItem(ShopItem::Photo2))
{
if (peep->Photo2RideRef == _rideIndex)
{
peep->RemoveItem(ShopItem::Photo2);
}
}
if (peep->HasItem(ShopItem::Photo3))
{
if (peep->Photo3RideRef == _rideIndex)
{
peep->RemoveItem(ShopItem::Photo3);
}
}
if (peep->HasItem(ShopItem::Photo4))
{
if (peep->Photo4RideRef == _rideIndex)
{
peep->RemoveItem(ShopItem::Photo4);
}
}
if (peep->GuestHeadingToRideId == _rideIndex)
{
peep->GuestHeadingToRideId = RIDE_ID_NULL;
}
if (peep->FavouriteRide == _rideIndex)
{
peep->FavouriteRide = RIDE_ID_NULL;
}
for (int32_t i = 0; i < PEEP_MAX_THOUGHTS; i++)
{
// Don't touch items after the first NONE thought as they are not valid
// fixes issues with clearing out bad thought data in multiplayer
if (peep->Thoughts[i].type == PeepThoughtType::None)
break;
if (peep->Thoughts[i].type != PeepThoughtType::None && peep->Thoughts[i].item == _rideIndex)
{
// Clear top thought, push others up
memmove(&peep->Thoughts[i], &peep->Thoughts[i + 1], sizeof(rct_peep_thought) * (PEEP_MAX_THOUGHTS - i - 1));
peep->Thoughts[PEEP_MAX_THOUGHTS - 1].type = PeepThoughtType::None;
peep->Thoughts[PEEP_MAX_THOUGHTS - 1].item = PEEP_THOUGHT_ITEM_NONE;
// Next iteration, check the new thought at this index
i--;
}
}
peep->RemoveRideFromMemory(_rideIndex);
}
MarketingCancelCampaignsForRide(_rideIndex);

View File

@@ -7356,3 +7356,112 @@ bool Guest::HasItem(ShopItem peepItem) const
{
return GetItemFlags() & EnumToFlag(peepItem);
}
static bool IsThoughtShopItemRelated(const PeepThoughtType type)
{
switch (type)
{
case PeepThoughtType::AlreadyGot:
case PeepThoughtType::HaventFinished:
case PeepThoughtType::CantAffordItem:
return true;
default:
break;
}
return false;
}
void Guest::RemoveRideFromMemory(ride_id_t rideId)
{
uint8_t ride_id_bit = rideId % 8;
uint8_t ride_id_offset = rideId / 8;
// clear ride from potentially being in RidesBeenOn
RidesBeenOn[ride_id_offset] &= ~(1 << ride_id_bit);
if (State == PeepState::Watching)
{
if (CurrentRide == rideId)
{
CurrentRide = RIDE_ID_NULL;
if (TimeToStand >= 50)
{
// make peep stop watching the ride
TimeToStand = 50;
}
}
}
// remove any free voucher for this ride from peep
if (HasItem(ShopItem::Voucher))
{
if (VoucherType == VOUCHER_TYPE_RIDE_FREE && VoucherRideId == rideId)
{
RemoveItem(ShopItem::Voucher);
}
}
// remove any photos of this ride from peep
if (HasItem(ShopItem::Photo))
{
if (Photo1RideRef == rideId)
{
RemoveItem(ShopItem::Photo);
}
}
if (HasItem(ShopItem::Photo2))
{
if (Photo2RideRef == rideId)
{
RemoveItem(ShopItem::Photo2);
}
}
if (HasItem(ShopItem::Photo3))
{
if (Photo3RideRef == rideId)
{
RemoveItem(ShopItem::Photo3);
}
}
if (HasItem(ShopItem::Photo4))
{
if (Photo4RideRef == rideId)
{
RemoveItem(ShopItem::Photo4);
}
}
if (GuestHeadingToRideId == rideId)
{
GuestHeadingToRideId = RIDE_ID_NULL;
}
if (FavouriteRide == rideId)
{
FavouriteRide = RIDE_ID_NULL;
}
// Erase all thoughts that contain the ride.
for (auto it = std::begin(Thoughts); it != std::end(Thoughts);)
{
const auto& entry = *it;
if (entry.type == PeepThoughtType::None)
break;
// Ride ids and shop item ids might have the same value, look only for ride thoughts.
if (IsThoughtShopItemRelated(entry.type) || entry.item != rideId)
{
it++;
continue;
}
if (auto itNext = std::next(it); itNext != std::end(Thoughts))
{
// Overwrite this entry by shifting all entries that follow.
std::rotate(it, itNext, std::end(Thoughts));
}
// Last slot is now free.
auto& lastEntry = Thoughts.back();
lastEntry.type = PeepThoughtType::None;
lastEntry.item = PEEP_THOUGHT_ITEM_NONE;
}
}

View File

@@ -784,6 +784,10 @@ public:
bool HasItem(ShopItem peepItem) const;
void Serialise(DataSerialiser& stream);
// Removes the ride from the guests memory, this includes
// the history, thoughts, etc.
void RemoveRideFromMemory(ride_id_t rideId);
private:
void UpdateRide();
void UpdateOnRide(){}; // TODO