Fix #10547: RCT1 parks have too many rides available (#10556)

This commit is contained in:
Michael Steenbeek 2020-01-13 19:23:05 +01:00 committed by GitHub
parent 2242a72b29
commit 0f306d6f5c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 90 additions and 115 deletions

View File

@ -14,6 +14,7 @@
- Fix: [#10477] Large Scenery cannot be placed higher using SHIFT. - Fix: [#10477] Large Scenery cannot be placed higher using SHIFT.
- Fix: [#10489] Hosts last player action not being synchronized. - Fix: [#10489] Hosts last player action not being synchronized.
- Fix: [#10543] Secondary shop item prices are not imported correctly from RCT1 saves. - Fix: [#10543] Secondary shop item prices are not imported correctly from RCT1 saves.
- Fix: [#10547] RCT1 parks have too many rides available.
- Removed: [#6898] LOADMM and LOADRCT1 title sequence commands (use LOADSC instead). - Removed: [#6898] LOADMM and LOADRCT1 title sequence commands (use LOADSC instead).
0.2.4 (2019-10-28) 0.2.4 (2019-10-28)

View File

@ -429,71 +429,15 @@ private:
AddEntriesForSceneryTheme(researchItem->item); AddEntriesForSceneryTheme(researchItem->item);
break; break;
case RCT1_RESEARCH_TYPE_RIDE: case RCT1_RESEARCH_TYPE_RIDE:
{ AddEntryForRideType(researchItem->item);
uint8_t rideType = researchItem->item;
// Add all vehicles for this ride type
uint32_t numVehicles = 0;
for (size_t j = 0; j < researchListCount; j++)
{
const rct1_research_item* researchItem2 = &researchList[j];
if (researchItem2->flags == RCT1_RESEARCH_FLAGS_SEPARATOR)
{
if (researchItem2->item == RCT1_RESEARCH_END_RESEARCHABLE
|| researchItem2->item == RCT1_RESEARCH_END_AVAILABLE)
{
continue;
}
else if (researchItem2->item == RCT1_RESEARCH_END)
{
break; break;
} case RCT1_RESEARCH_TYPE_VEHICLE:
} AddEntryForVehicleType(researchItem->related_ride, researchItem->item);
if (researchItem2->type == RCT1_RESEARCH_TYPE_VEHICLE && researchItem2->related_ride == rideType)
{
AddEntryForVehicleType(rideType, researchItem2->item);
numVehicles++;
}
}
// If no vehicles found so just add the default for this ride
if (numVehicles == 0)
{
AddEntryForRideType(rideType);
}
break; break;
} }
} }
} }
// In addition to the research list, there is also a list of invented ride/vehicles in general.
// This is especially useful if the research list is damaged or if the save is hacked.
for (int32_t rideType = 0; rideType < RCT1_RIDE_TYPE_COUNT; rideType++)
{
int32_t quadIndex = rideType >> 5;
int32_t bitIndex = rideType & 0x1F;
bool invented = (_s4.available_rides[quadIndex] & ((uint32_t)1 << bitIndex));
if (invented)
{
AddEntryForRideType(rideType);
}
}
for (int32_t vehicleType = 0; vehicleType < RCT1_VEHICLE_TYPE_COUNT; vehicleType++)
{
int32_t quadIndex = vehicleType >> 5;
int32_t bitIndex = vehicleType & 0x1F;
bool invented = (_s4.available_vehicles[quadIndex] & ((uint32_t)1 << bitIndex));
if (invented)
{
AddEntryForVehicleType(RIDE_TYPE_NULL, vehicleType);
}
}
}
void AddAvailableEntriesFromMap() void AddAvailableEntriesFromMap()
{ {
size_t maxTiles = 128 * 128; size_t maxTiles = 128 * 128;
@ -597,7 +541,7 @@ private:
{ {
const char* entryName; const char* entryName;
if (_s4.game_version < FILE_VERSION_RCT1_LL) if (_gameVersion < FILE_VERSION_RCT1_LL)
{ {
entryName = RCT1::GetWaterObject(RCT1_WATER_CYAN); entryName = RCT1::GetWaterObject(RCT1_WATER_CYAN);
} }
@ -635,7 +579,7 @@ private:
_vehicleTypeToRideEntryMap[vehicleType] = (uint8_t)entryIndex; _vehicleTypeToRideEntryMap[vehicleType] = (uint8_t)entryIndex;
if (rideType != RIDE_TYPE_NULL) if (rideType != RIDE_TYPE_NULL)
_rideTypeToRideEntryMap[rideType] = (uint8_t)entryIndex; AddEntryForRideType(rideType);
} }
} }
} }
@ -2291,6 +2235,9 @@ private:
} }
bool researched = true; bool researched = true;
std::bitset<RCT1_RIDE_TYPE_COUNT> rideTypeInResearch = GetRideTypesPresentInResearchList(
researchList, researchListCount);
std::vector<rct1_research_item> vehiclesWithMissingRideTypes;
for (size_t i = 0; i < researchListCount; i++) for (size_t i = 0; i < researchListCount; i++)
{ {
const rct1_research_item* researchItem = &researchList[i]; const rct1_research_item* researchItem = &researchList[i];
@ -2301,11 +2248,8 @@ private:
researched = false; researched = false;
continue; continue;
} }
else if (researchItem->item == RCT1_RESEARCH_END_RESEARCHABLE) // We don't import the random items yet.
{ else if (researchItem->item == RCT1_RESEARCH_END_RESEARCHABLE || researchItem->item == RCT1_RESEARCH_END)
continue;
}
else if (researchItem->item == RCT1_RESEARCH_END)
{ {
break; break;
} }
@ -2328,82 +2272,83 @@ private:
uint8_t rct1RideType = researchItem->item; uint8_t rct1RideType = researchItem->item;
_researchRideTypeUsed[rct1RideType] = true; _researchRideTypeUsed[rct1RideType] = true;
auto ownRideEntryIndex = _rideTypeToRideEntryMap[rct1RideType];
Guard::Assert(ownRideEntryIndex != RIDE_ENTRY_INDEX_NULL, "ownRideEntryIndex was RIDE_ENTRY_INDEX_NULL");
bool foundOwnType = false;
// If the ride type does not use vehicles, no point looking for them in the research list.
if (RCT1::RideTypeUsesVehicles(rct1RideType))
{
// Add all vehicles for this ride type that are researched or before this research item // Add all vehicles for this ride type that are researched or before this research item
uint32_t numVehicles = 0;
for (size_t j = 0; j < researchListCount; j++) for (size_t j = 0; j < researchListCount; j++)
{ {
const rct1_research_item* researchItem2 = &researchList[j]; const rct1_research_item* researchItem2 = &researchList[j];
if (researchItem2->flags == RCT1_RESEARCH_FLAGS_SEPARATOR if (researchItem2->flags == RCT1_RESEARCH_FLAGS_SEPARATOR)
&& (researchItem2->item == RCT1_RESEARCH_END_RESEARCHABLE
|| researchItem2->item == RCT1_RESEARCH_END_AVAILABLE))
{ {
if (researchItem2->item == RCT1_RESEARCH_END_RESEARCHABLE
|| researchItem2->item == RCT1_RESEARCH_END)
{
break;
}
continue; continue;
} }
if (researchItem2->type == RCT1_RESEARCH_TYPE_VEHICLE && researchItem2->related_ride == rct1RideType) if (researchItem2->type == RCT1_RESEARCH_TYPE_VEHICLE
&& researchItem2->related_ride == rct1RideType)
{ {
auto rideEntryIndex2 = _vehicleTypeToRideEntryMap[researchItem2->item];
bool isOwnType = (ownRideEntryIndex == rideEntryIndex2);
if (isOwnType)
{
foundOwnType = true;
}
// Only add the vehicles that were listed before this ride, otherwise we might // Only add the vehicles that were listed before this ride, otherwise we might
// change the research order // change the research order
if (j < i) if (j < i && (researched || isOwnType))
{ {
InsertResearchVehicle(researchItem2, researched); InsertResearchVehicle(researchItem2, researched);
} }
numVehicles++; }
} }
} }
if (numVehicles == 0) if (!foundOwnType)
{ {
// No vehicles found so just add the default for this ride if (!_researchRideEntryUsed[ownRideEntryIndex])
uint8_t rideEntryIndex = _rideTypeToRideEntryMap[rct1RideType];
Guard::Assert(rideEntryIndex != RIDE_ENTRY_INDEX_NULL, "rideEntryIndex was RIDE_ENTRY_INDEX_NULL");
if (!_researchRideEntryUsed[rideEntryIndex])
{ {
_researchRideEntryUsed[rideEntryIndex] = true; _researchRideEntryUsed[ownRideEntryIndex] = true;
research_insert_ride_entry(rideEntryIndex, researched); research_insert_ride_entry(ownRideEntryIndex, researched);
} }
} }
break; break;
} }
case RCT1_RESEARCH_TYPE_VEHICLE: case RCT1_RESEARCH_TYPE_VEHICLE:
{
// Only add vehicle if the related ride has been seen, this to make sure that vehicles // Only add vehicle if the related ride has been seen, this to make sure that vehicles
// are researched only after the ride has been researched // are researched only after the ride has been researched. Otherwise, remove them from the research list,
// so that they are automatically co-invented when their master ride is invented.
if (_researchRideTypeUsed[researchItem->related_ride]) if (_researchRideTypeUsed[researchItem->related_ride])
{ {
InsertResearchVehicle(researchItem, researched); InsertResearchVehicle(researchItem, researched);
} }
else if (!rideTypeInResearch[researchItem->related_ride] && _gameVersion == FILE_VERSION_RCT1_LL)
{
vehiclesWithMissingRideTypes.push_back(*researchItem);
}
break; break;
}
case RCT1_RESEARCH_TYPE_SPECIAL: case RCT1_RESEARCH_TYPE_SPECIAL:
// Not supported // Not supported
break; break;
} }
} }
for (const rct1_research_item& researchItem : vehiclesWithMissingRideTypes)
// Also import the tables that register the invented status, in case the research list is damaged.
for (int32_t rideType = 0; rideType < RCT1_RIDE_TYPE_COUNT; rideType++)
{ {
int32_t quadIndex = rideType >> 5; InsertResearchVehicle(&researchItem, false);
int32_t bitIndex = rideType & 0x1F;
bool invented = (_s4.available_rides[quadIndex] & ((uint32_t)1 << bitIndex));
if (invented)
{
ride_type_set_invented(RCT1::GetRideType(rideType));
}
}
for (int32_t vehicleType = 0; vehicleType < RCT1_VEHICLE_TYPE_COUNT; vehicleType++)
{
int32_t quadIndex = vehicleType >> 5;
int32_t bitIndex = vehicleType & 0x1F;
bool invented = (_s4.available_vehicles[quadIndex] & ((uint32_t)1 << bitIndex));
if (invented)
{
ride_entry_set_invented(_vehicleTypeToRideEntryMap[vehicleType]);
}
} }
// Research funding / priority // Research funding / priority
@ -2452,6 +2397,35 @@ private:
ConvertResearchEntry(&gResearchLastItem, _s4.last_research_item, _s4.last_research_type); ConvertResearchEntry(&gResearchLastItem, _s4.last_research_item, _s4.last_research_type);
} }
static std::bitset<RCT1_RIDE_TYPE_COUNT> GetRideTypesPresentInResearchList(
const rct1_research_item* researchList, size_t researchListCount)
{
std::bitset<RCT1_RIDE_TYPE_COUNT> ret = {};
for (size_t i = 0; i < researchListCount; i++)
{
const rct1_research_item* researchItem = &researchList[i];
if (researchItem->flags == RCT1_RESEARCH_FLAGS_SEPARATOR)
{
if (researchItem->item == RCT1_RESEARCH_END_AVAILABLE || researchItem->item == RCT1_RESEARCH_END_RESEARCHABLE)
{
continue;
}
else if (researchItem->item == RCT1_RESEARCH_END)
{
break;
}
}
if (researchItem->type == RCT1_RESEARCH_TYPE_RIDE)
{
ret[researchItem->item] = true;
}
}
return ret;
}
void InsertResearchVehicle(const rct1_research_item* researchItem, bool researched) void InsertResearchVehicle(const rct1_research_item* researchItem, bool researched)
{ {
uint8_t vehicle = researchItem->item; uint8_t vehicle = researchItem->item;