mirror of https://github.com/OpenRCT2/OpenRCT2.git
Move more calculation and logic to park class
This commit is contained in:
parent
b705e0ce7a
commit
8929e5533b
|
@ -151,45 +151,6 @@ void park_init()
|
|||
format_string(gS6Info.details, 256, STR_NO_DETAILS_YET, nullptr);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x0066729F
|
||||
*/
|
||||
void park_reset_history()
|
||||
{
|
||||
for (sint32 i = 0; i < 32; i++) {
|
||||
gParkRatingHistory[i] = 255;
|
||||
gGuestsInParkHistory[i] = 255;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x0066A348
|
||||
*/
|
||||
sint32 park_calculate_size()
|
||||
{
|
||||
sint32 tiles;
|
||||
tile_element_iterator it;
|
||||
|
||||
tiles = 0;
|
||||
tile_element_iterator_begin(&it);
|
||||
do {
|
||||
if (it.element->GetType() == TILE_ELEMENT_TYPE_SURFACE) {
|
||||
if (it.element->properties.surface.ownership & (OWNERSHIP_CONSTRUCTION_RIGHTS_OWNED | OWNERSHIP_OWNED)) {
|
||||
tiles++;
|
||||
}
|
||||
}
|
||||
} while (tile_element_iterator_next(&it));
|
||||
|
||||
if (tiles != gParkSize) {
|
||||
gParkSize = tiles;
|
||||
window_invalidate_by_class(WC_PARK_INFORMATION);
|
||||
}
|
||||
|
||||
return tiles;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x00667104
|
||||
|
@ -203,115 +164,6 @@ void reset_park_entry()
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the probability of a new guest. Also sets total ride value and suggested guest maximum.
|
||||
* Total ride value should probably be set elsewhere, as it's not just used for guest generation.
|
||||
* Suggested guest maximum should probably be an output result, not a global.
|
||||
* @returns A probability out of 65535
|
||||
* rct2: 0x0066730A
|
||||
*/
|
||||
static sint32 park_calculate_guest_generation_probability()
|
||||
{
|
||||
uint32 probability;
|
||||
sint32 i, suggestedMaxGuests;
|
||||
money16 totalRideValueForMoney;
|
||||
Ride *ride;
|
||||
|
||||
// Calculate suggested guest maximum (based on ride type) and total ride value
|
||||
suggestedMaxGuests = 0;
|
||||
totalRideValueForMoney = 0;
|
||||
FOR_ALL_RIDES(i, ride) {
|
||||
if (ride->status != RIDE_STATUS_OPEN)
|
||||
continue;
|
||||
if (ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN)
|
||||
continue;
|
||||
if (ride->lifecycle_flags & RIDE_LIFECYCLE_CRASHED)
|
||||
continue;
|
||||
|
||||
// Add guest score for ride type
|
||||
suggestedMaxGuests += rideBonusValue[ride->type];
|
||||
|
||||
// Add ride value
|
||||
if (ride->value != RIDE_VALUE_UNDEFINED) {
|
||||
money16 rideValueForMoney = (money16)(ride->value - ride->price);
|
||||
if (rideValueForMoney > 0) {
|
||||
totalRideValueForMoney += rideValueForMoney * 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If difficult guest generation, extra guests are available for good rides
|
||||
if (gParkFlags & PARK_FLAGS_DIFFICULT_GUEST_GENERATION) {
|
||||
suggestedMaxGuests = std::min(suggestedMaxGuests, 1000);
|
||||
FOR_ALL_RIDES(i, ride) {
|
||||
if (ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN)
|
||||
continue;
|
||||
if (ride->lifecycle_flags & RIDE_LIFECYCLE_CRASHED)
|
||||
continue;
|
||||
|
||||
if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_TRACK))
|
||||
continue;
|
||||
if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_DATA_LOGGING))
|
||||
continue;
|
||||
if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED))
|
||||
continue;
|
||||
if (ride->length[0] < (600 << 16))
|
||||
continue;
|
||||
if (ride->excitement < RIDE_RATING(6,00))
|
||||
continue;
|
||||
|
||||
// Bonus guests for good ride
|
||||
suggestedMaxGuests += rideBonusValue[ride->type] * 2;
|
||||
}
|
||||
}
|
||||
|
||||
suggestedMaxGuests = std::min(suggestedMaxGuests, 65535);
|
||||
gTotalRideValueForMoney = totalRideValueForMoney;
|
||||
_suggestedGuestMaximum = suggestedMaxGuests;
|
||||
|
||||
// Begin with 50 + park rating
|
||||
probability = 50 + Math::Clamp(0, gParkRating - 200, 650);
|
||||
|
||||
// The more guests, the lower the chance of a new one
|
||||
sint32 numGuests = gNumGuestsInPark + gNumGuestsHeadingForPark;
|
||||
if (numGuests > suggestedMaxGuests) {
|
||||
probability /= 4;
|
||||
|
||||
// Even lower for difficult guest generation
|
||||
if (gParkFlags & PARK_FLAGS_DIFFICULT_GUEST_GENERATION)
|
||||
probability /= 4;
|
||||
}
|
||||
|
||||
// Reduces chance for any more than 7000 guests
|
||||
if (numGuests > 7000)
|
||||
probability /= 4;
|
||||
|
||||
// Penalty for overpriced entrance fee relative to total ride value
|
||||
money16 entranceFee = park_get_entrance_fee();
|
||||
if (entranceFee > totalRideValueForMoney) {
|
||||
probability /= 4;
|
||||
|
||||
// Extra penalty for very overpriced entrance fee
|
||||
if (entranceFee / 2 > totalRideValueForMoney)
|
||||
probability /= 4;
|
||||
}
|
||||
|
||||
// Reward or penalties for park awards
|
||||
for (i = 0; i < MAX_AWARDS; i++) {
|
||||
Award *award = &gCurrentAwards[i];
|
||||
if (award->Time == 0)
|
||||
continue;
|
||||
|
||||
// +/- 0.25% of the probability
|
||||
if (award_is_positive(award->Type))
|
||||
probability += probability / 4;
|
||||
else
|
||||
probability -= probability / 4;
|
||||
}
|
||||
|
||||
return probability;
|
||||
}
|
||||
|
||||
/**
|
||||
* Choose a random peep spawn and iterates through until defined spawn is found.
|
||||
*/
|
||||
|
@ -327,30 +179,6 @@ static uint32 get_random_peep_spawn_index()
|
|||
}
|
||||
}
|
||||
|
||||
uint8 calculate_guest_initial_happiness(uint8 percentage) {
|
||||
if (percentage < 15) {
|
||||
// There is a minimum of 15% happiness
|
||||
percentage = 15;
|
||||
}
|
||||
else if (percentage > 98) {
|
||||
// There is a maximum of 98% happiness
|
||||
percentage = 98;
|
||||
}
|
||||
|
||||
/* The percentages follow this sequence:
|
||||
15 17 18 20 21 23 25 26 28 29 31 32 34 36 37 39 40 42 43 45 47 48 50 51 53...
|
||||
|
||||
This sequence can be defined as PI*(9+n)/2 (the value is floored)
|
||||
*/
|
||||
uint8 n;
|
||||
for (n = 1; n < 55; n++) {
|
||||
if ((3.14159*(9 + n)) / 2 >= percentage) {
|
||||
return (9 + n) * 4;
|
||||
}
|
||||
}
|
||||
return 40; // This is the lowest possible value
|
||||
}
|
||||
|
||||
void park_set_open(sint32 open)
|
||||
{
|
||||
game_do_command(0, GAME_COMMAND_FLAG_APPLY, 0, open << 8, GAME_COMMAND_SET_PARK_OPEN, 0, 0);
|
||||
|
@ -683,7 +511,6 @@ void game_command_buy_land_rights(
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void set_forced_park_rating(sint32 rating)
|
||||
{
|
||||
_forcedParkRating = rating;
|
||||
|
@ -776,7 +603,10 @@ void Park::Update()
|
|||
gParkRating = CalculateParkRating();
|
||||
gParkValue = CalculateParkValue();
|
||||
gCompanyValue = CalculateCompanyValue();
|
||||
_guestGenerationProbability = park_calculate_guest_generation_probability();
|
||||
gTotalRideValueForMoney = CalculateTotalRideValue();
|
||||
_suggestedGuestMaximum = CalculateSuggestedMaxGuests();
|
||||
_guestGenerationProbability = CalculateGuestGenerationProbability();
|
||||
|
||||
window_invalidate_by_class(WC_FINANCES);
|
||||
auto intent = Intent(INTENT_ACTION_UPDATE_PARK_RATING);
|
||||
context_broadcast_intent(&intent);
|
||||
|
@ -784,6 +614,31 @@ void Park::Update()
|
|||
GenerateGuests();
|
||||
}
|
||||
|
||||
sint32 Park::CalculateParkSize() const
|
||||
{
|
||||
sint32 tiles;
|
||||
tile_element_iterator it;
|
||||
|
||||
tiles = 0;
|
||||
tile_element_iterator_begin(&it);
|
||||
do {
|
||||
if (it.element->GetType() == TILE_ELEMENT_TYPE_SURFACE)
|
||||
{
|
||||
if (it.element->properties.surface.ownership & (OWNERSHIP_CONSTRUCTION_RIGHTS_OWNED | OWNERSHIP_OWNED))
|
||||
{
|
||||
tiles++;
|
||||
}
|
||||
}
|
||||
} while (tile_element_iterator_next(&it));
|
||||
|
||||
if (tiles != gParkSize) {
|
||||
gParkSize = tiles;
|
||||
window_invalidate_by_class(WC_PARK_INFORMATION);
|
||||
}
|
||||
|
||||
return tiles;
|
||||
}
|
||||
|
||||
sint32 Park::CalculateParkRating() const
|
||||
{
|
||||
if (_forcedParkRating >= 0)
|
||||
|
@ -947,6 +802,145 @@ money32 Park::CalculateCompanyValue() const
|
|||
return finance_get_current_cash() + gParkValue - gBankLoan;
|
||||
}
|
||||
|
||||
money16 Park::CalculateTotalRideValue() const
|
||||
{
|
||||
money16 totalRideValue = 0;
|
||||
sint32 i;
|
||||
Ride * ride;
|
||||
FOR_ALL_RIDES(i, ride)
|
||||
{
|
||||
if (ride->status != RIDE_STATUS_OPEN) continue;
|
||||
if (ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN) continue;
|
||||
if (ride->lifecycle_flags & RIDE_LIFECYCLE_CRASHED) continue;
|
||||
|
||||
// Add ride value
|
||||
if (ride->value != RIDE_VALUE_UNDEFINED)
|
||||
{
|
||||
money16 rideValue = (money16)(ride->value - ride->price);
|
||||
if (rideValue > 0)
|
||||
{
|
||||
totalRideValue += rideValue * 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
return totalRideValue;
|
||||
}
|
||||
|
||||
uint32 Park::CalculateSuggestedMaxGuests() const
|
||||
{
|
||||
uint32 suggestedMaxGuests = 0;
|
||||
|
||||
// TODO combine the two ride loops
|
||||
sint32 i;
|
||||
Ride * ride;
|
||||
FOR_ALL_RIDES(i, ride)
|
||||
{
|
||||
if (ride->status != RIDE_STATUS_OPEN) continue;
|
||||
if (ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN) continue;
|
||||
if (ride->lifecycle_flags & RIDE_LIFECYCLE_CRASHED) continue;
|
||||
|
||||
// Add guest score for ride type
|
||||
suggestedMaxGuests += rideBonusValue[ride->type];
|
||||
}
|
||||
|
||||
// If difficult guest generation, extra guests are available for good rides
|
||||
if (gParkFlags & PARK_FLAGS_DIFFICULT_GUEST_GENERATION)
|
||||
{
|
||||
suggestedMaxGuests = std::min<uint32>(suggestedMaxGuests, 1000);
|
||||
FOR_ALL_RIDES(i, ride)
|
||||
{
|
||||
if (ride->lifecycle_flags & RIDE_LIFECYCLE_CRASHED) continue;
|
||||
if (ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN) continue;
|
||||
if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED)) continue;
|
||||
if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_TRACK)) continue;
|
||||
if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_DATA_LOGGING)) continue;
|
||||
if (ride->length[0] < (600 << 16)) continue;
|
||||
if (ride->excitement < RIDE_RATING(6, 00)) continue;
|
||||
|
||||
// Bonus guests for good ride
|
||||
suggestedMaxGuests += rideBonusValue[ride->type] * 2;
|
||||
}
|
||||
}
|
||||
|
||||
suggestedMaxGuests = std::min<uint32>(suggestedMaxGuests, 65535);
|
||||
return suggestedMaxGuests;
|
||||
}
|
||||
|
||||
uint32 Park::CalculateGuestGenerationProbability() const
|
||||
{
|
||||
// Begin with 50 + park rating
|
||||
uint32 probability = 50 + Math::Clamp(0, gParkRating - 200, 650);
|
||||
|
||||
// The more guests, the lower the chance of a new one
|
||||
sint32 numGuests = gNumGuestsInPark + gNumGuestsHeadingForPark;
|
||||
if (numGuests > _suggestedGuestMaximum)
|
||||
{
|
||||
probability /= 4;
|
||||
// Even lower for difficult guest generation
|
||||
if (gParkFlags & PARK_FLAGS_DIFFICULT_GUEST_GENERATION)
|
||||
{
|
||||
probability /= 4;
|
||||
}
|
||||
}
|
||||
|
||||
// Reduces chance for any more than 7000 guests
|
||||
if (numGuests > 7000)
|
||||
{
|
||||
probability /= 4;
|
||||
}
|
||||
|
||||
// Penalty for overpriced entrance fee relative to total ride value
|
||||
money16 entranceFee = park_get_entrance_fee();
|
||||
if (entranceFee > gTotalRideValueForMoney)
|
||||
{
|
||||
probability /= 4;
|
||||
// Extra penalty for very overpriced entrance fee
|
||||
if (entranceFee / 2 > gTotalRideValueForMoney)
|
||||
{
|
||||
probability /= 4;
|
||||
}
|
||||
}
|
||||
|
||||
// Reward or penalties for park awards
|
||||
for (size_t i = 0; i < MAX_AWARDS; i++)
|
||||
{
|
||||
const auto award = &gCurrentAwards[i];
|
||||
if (award->Time != 0)
|
||||
{
|
||||
// +/- 0.25% of the probability
|
||||
if (award_is_positive(award->Type))
|
||||
{
|
||||
probability += probability / 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
probability -= probability / 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return probability;
|
||||
}
|
||||
|
||||
uint8 Park::CalculateGuestInitialHappiness(uint8 percentage)
|
||||
{
|
||||
percentage = Math::Clamp<uint8>(15, percentage, 98);
|
||||
|
||||
// The percentages follow this sequence:
|
||||
// 15 17 18 20 21 23 25 26 28 29 31 32 34 36 37 39 40 42 43 45 47 48 50 51 53...
|
||||
// This sequence can be defined as PI*(9+n)/2 (the value is floored)
|
||||
for (uint8 n = 1; n < 55; n++)
|
||||
{
|
||||
if ((3.14159 * (9 + n)) / 2 >= percentage)
|
||||
{
|
||||
return (9 + n) * 4;
|
||||
}
|
||||
}
|
||||
|
||||
// This is the lowest possible value:
|
||||
return 40;
|
||||
}
|
||||
|
||||
void Park::GenerateGuests()
|
||||
{
|
||||
// Generate a new guest for some probability
|
||||
|
@ -1019,6 +1013,15 @@ static void HistoryPushRecord(T history[TSize], T newItem)
|
|||
history[0] = newItem;
|
||||
}
|
||||
|
||||
void Park::ResetHistories()
|
||||
{
|
||||
for (size_t i = 0; i < 32; i++)
|
||||
{
|
||||
gParkRatingHistory[i] = 255;
|
||||
gGuestsInParkHistory[i] = 255;
|
||||
}
|
||||
}
|
||||
|
||||
void Park::UpdateHistories()
|
||||
{
|
||||
uint8 guestChangeModifier = 1;
|
||||
|
@ -1059,6 +1062,17 @@ void Park::UpdateHistories()
|
|||
window_invalidate_by_class(WC_FINANCES);
|
||||
}
|
||||
|
||||
sint32 park_calculate_size()
|
||||
{
|
||||
auto tiles = _singleton->CalculateParkSize();
|
||||
if (tiles != gParkSize)
|
||||
{
|
||||
gParkSize = tiles;
|
||||
window_invalidate_by_class(WC_PARK_INFORMATION);
|
||||
}
|
||||
return tiles;
|
||||
}
|
||||
|
||||
sint32 calculate_park_rating()
|
||||
{
|
||||
return _singleton->CalculateParkRating();
|
||||
|
@ -1078,3 +1092,18 @@ rct_peep * park_generate_new_guest()
|
|||
{
|
||||
return _singleton->GenerateGuest();
|
||||
}
|
||||
|
||||
void park_update_histories()
|
||||
{
|
||||
_singleton->UpdateHistories();
|
||||
}
|
||||
|
||||
void park_reset_history()
|
||||
{
|
||||
_singleton->ResetHistories();
|
||||
}
|
||||
|
||||
uint8 calculate_guest_initial_happiness(uint8 percentage)
|
||||
{
|
||||
return Park::CalculateGuestInitialHappiness(percentage);
|
||||
}
|
||||
|
|
|
@ -67,12 +67,18 @@ namespace OpenRCT2
|
|||
|
||||
void Update();
|
||||
|
||||
sint32 CalculateParkSize() const;
|
||||
sint32 CalculateParkRating() const;
|
||||
money32 CalculateParkValue() const;
|
||||
money32 CalculateCompanyValue() const;
|
||||
money16 CalculateTotalRideValue() const;
|
||||
uint32 CalculateSuggestedMaxGuests() const;
|
||||
uint32 CalculateGuestGenerationProbability() const;
|
||||
static uint8 CalculateGuestInitialHappiness(uint8 percentage);
|
||||
|
||||
rct_peep * GenerateGuest();
|
||||
|
||||
void ResetHistories();
|
||||
void UpdateHistories();
|
||||
|
||||
private:
|
||||
|
|
Loading…
Reference in New Issue