2014-05-27 16:14:45 +02:00
|
|
|
/*****************************************************************************
|
|
|
|
* Copyright (c) 2014 Ted John
|
|
|
|
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
|
|
|
*
|
|
|
|
* This file is part of OpenRCT2.
|
|
|
|
*
|
|
|
|
* OpenRCT2 is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
#include "addresses.h"
|
|
|
|
#include "award.h"
|
|
|
|
#include "news_item.h"
|
2014-05-27 19:03:25 +02:00
|
|
|
#include "peep.h"
|
2014-05-27 16:14:45 +02:00
|
|
|
#include "ride.h"
|
|
|
|
#include "scenario.h"
|
2014-05-27 19:03:25 +02:00
|
|
|
#include "sprite.h"
|
2014-05-27 16:14:45 +02:00
|
|
|
#include "window.h"
|
|
|
|
|
|
|
|
#define NEGATIVE 0
|
|
|
|
#define POSITIVE 1
|
|
|
|
|
|
|
|
int _awardPositiveMap[] = {
|
|
|
|
NEGATIVE, // PARK_AWARD_MOST_UNTIDY
|
|
|
|
POSITIVE, // PARK_AWARD_MOST_TIDY
|
|
|
|
POSITIVE, // PARK_AWARD_BEST_ROLLERCOASTERS
|
|
|
|
POSITIVE, // PARK_AWARD_BEST_VALUE
|
|
|
|
POSITIVE, // PARK_AWARD_MOST_BEAUTIFUL
|
|
|
|
NEGATIVE, // PARK_AWARD_WORST_VALUE
|
|
|
|
POSITIVE, // PARK_AWARD_SAFEST
|
|
|
|
POSITIVE, // PARK_AWARD_BEST_STAFF
|
|
|
|
POSITIVE, // PARK_AWARD_BEST_FOOD
|
|
|
|
NEGATIVE, // PARK_AWARD_WORST_FOOD
|
|
|
|
POSITIVE, // PARK_AWARD_BEST_RESTROOMS
|
|
|
|
NEGATIVE, // PARK_AWARD_MOST_DISAPPOINTING
|
|
|
|
POSITIVE, // PARK_AWARD_BEST_WATER_RIDES
|
|
|
|
POSITIVE, // PARK_AWARD_BEST_CUSTOM_DESIGNED_RIDES
|
|
|
|
POSITIVE, // PARK_AWARD_MOST_DAZZLING_RIDE_COLOURS
|
|
|
|
NEGATIVE, // PARK_AWARD_MOST_CONFUSING_LAYOUT
|
|
|
|
POSITIVE, // PARK_AWARD_BEST_GENTLE_RIDES
|
|
|
|
};
|
|
|
|
|
|
|
|
int award_is_positive(int type)
|
|
|
|
{
|
|
|
|
return _awardPositiveMap[type];
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma region Award checks
|
|
|
|
|
2014-05-27 21:45:40 +02:00
|
|
|
/** More than 1/16 of the total guests must be thinking untidy thoughts. */
|
2014-05-27 16:14:45 +02:00
|
|
|
static int award_is_deserved_most_untidy(int awardType, int activeAwardTypes)
|
|
|
|
{
|
2014-05-27 21:45:40 +02:00
|
|
|
uint16 spriteIndex;
|
|
|
|
rct_peep *peep;
|
|
|
|
int negativeCount;
|
|
|
|
|
|
|
|
if (activeAwardTypes & (1 << PARK_AWARD_MOST_BEAUTIFUL))
|
|
|
|
return 0;
|
|
|
|
if (activeAwardTypes & (1 << PARK_AWARD_BEST_STAFF))
|
|
|
|
return 0;
|
|
|
|
if (activeAwardTypes & (1 << PARK_AWARD_MOST_TIDY))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
negativeCount = 0;
|
|
|
|
FOR_ALL_GUESTS(spriteIndex, peep) {
|
|
|
|
if (peep->var_2A != 0)
|
|
|
|
continue;
|
|
|
|
|
2014-05-31 00:27:11 +02:00
|
|
|
if (peep->thoughts[0].var_2 > 5)
|
2014-05-27 21:45:40 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
if (peep->thoughts[0].type == PEEP_THOUGHT_TYPE_BAD_LITTER ||
|
|
|
|
peep->thoughts[0].type == PEEP_THOUGHT_TYPE_PATH_DISGUSTING ||
|
|
|
|
peep->thoughts[0].type == PEEP_THOUGHT_TYPE_VANDALISM
|
|
|
|
) {
|
|
|
|
negativeCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (negativeCount > RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_IN_PARK, uint16) / 16);
|
2014-05-27 16:14:45 +02:00
|
|
|
}
|
|
|
|
|
2014-05-27 21:45:40 +02:00
|
|
|
/** More than 1/64 of the total guests must be thinking tidy thoughts and less than 6 guests thinking untidy thoughts. */
|
2014-05-27 16:14:45 +02:00
|
|
|
static int award_is_deserved_most_tidy(int awardType, int activeAwardTypes)
|
|
|
|
{
|
2014-05-27 21:45:40 +02:00
|
|
|
uint16 spriteIndex;
|
|
|
|
rct_peep *peep;
|
|
|
|
int positiveCount;
|
|
|
|
int negativeCount;
|
|
|
|
|
|
|
|
if (activeAwardTypes & (1 << PARK_AWARD_MOST_UNTIDY))
|
|
|
|
return 0;
|
|
|
|
if (activeAwardTypes & (1 << PARK_AWARD_MOST_DISAPPOINTING))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
positiveCount = 0;
|
|
|
|
negativeCount = 0;
|
|
|
|
FOR_ALL_GUESTS(spriteIndex, peep) {
|
|
|
|
if (peep->var_2A != 0)
|
|
|
|
continue;
|
|
|
|
|
2014-05-31 00:27:11 +02:00
|
|
|
if (peep->thoughts[0].var_2 > 5)
|
2014-05-27 21:45:40 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
if (peep->thoughts[0].type == PEEP_THOUGHT_VERY_CLEAN)
|
|
|
|
positiveCount++;
|
|
|
|
|
|
|
|
if (peep->thoughts[0].type == PEEP_THOUGHT_TYPE_BAD_LITTER ||
|
|
|
|
peep->thoughts[0].type == PEEP_THOUGHT_TYPE_PATH_DISGUSTING ||
|
|
|
|
peep->thoughts[0].type == PEEP_THOUGHT_TYPE_VANDALISM
|
|
|
|
) {
|
|
|
|
negativeCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (negativeCount <= 5 && positiveCount > RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_IN_PARK, uint16) / 64);
|
2014-05-27 16:14:45 +02:00
|
|
|
}
|
|
|
|
|
2014-05-27 19:03:25 +02:00
|
|
|
/** At least 6 open roller coasters. */
|
2014-05-27 16:14:45 +02:00
|
|
|
static int award_is_deserved_best_rollercoasters(int awardType, int activeAwardTypes)
|
|
|
|
{
|
|
|
|
int i, rollerCoasters;
|
|
|
|
rct_ride *ride;
|
|
|
|
char *object;
|
|
|
|
|
|
|
|
rollerCoasters = 0;
|
|
|
|
FOR_ALL_RIDES(i, ride) {
|
|
|
|
object = RCT2_ADDRESS(0x009ACFA4, char*)[ride->subtype];
|
|
|
|
if (RCT2_GLOBAL(object + 0x1BE, uint8) != RIDE_GROUP_ROLLERCOASTER && RCT2_GLOBAL(object + 0x1BF, uint8) != RIDE_GROUP_ROLLERCOASTER)
|
|
|
|
continue;
|
|
|
|
|
2014-05-27 19:03:25 +02:00
|
|
|
if (ride->status != RIDE_STATUS_OPEN || (ride->lifecycle_flags & 0x400))
|
2014-05-27 16:14:45 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
rollerCoasters++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (rollerCoasters >= 6);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Entrance fee is 0.10 less than half of the total ride value. */
|
|
|
|
static int award_is_deserved_best_value(int awardType, int activeAwardTypes)
|
|
|
|
{
|
|
|
|
if (activeAwardTypes & (1 << PARK_AWARD_WORST_VALUE))
|
|
|
|
return 0;
|
|
|
|
if (activeAwardTypes & (1 << PARK_AWARD_MOST_DISAPPOINTING))
|
|
|
|
return 0;
|
|
|
|
if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & (PARK_FLAGS_11 | PARK_FLAGS_PARK_FREE_ENTRY))
|
|
|
|
return 0;
|
|
|
|
if (RCT2_GLOBAL(RCT2_TOTAL_RIDE_VALUE, money16) < MONEY(10, 00))
|
|
|
|
return 0;
|
|
|
|
if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_ENTRANCE_FEE, money16) + MONEY(0, 10) >= RCT2_GLOBAL(RCT2_TOTAL_RIDE_VALUE, money16) / 2)
|
|
|
|
return 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2014-05-27 21:45:40 +02:00
|
|
|
/** More than 1/128 of the total guests must be thinking scenic thoughts and less than 16 untidy thoughts. */
|
2014-05-27 16:14:45 +02:00
|
|
|
static int award_is_deserved_most_beautiful(int awardType, int activeAwardTypes)
|
|
|
|
{
|
2014-05-27 21:45:40 +02:00
|
|
|
uint16 spriteIndex;
|
|
|
|
rct_peep *peep;
|
|
|
|
int positiveCount;
|
|
|
|
int negativeCount;
|
|
|
|
|
|
|
|
if (activeAwardTypes & (1 << PARK_AWARD_MOST_UNTIDY))
|
|
|
|
return 0;
|
|
|
|
if (activeAwardTypes & (1 << PARK_AWARD_MOST_DISAPPOINTING))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
positiveCount = 0;
|
|
|
|
negativeCount = 0;
|
|
|
|
FOR_ALL_GUESTS(spriteIndex, peep) {
|
|
|
|
if (peep->var_2A != 0)
|
|
|
|
continue;
|
|
|
|
|
2014-05-31 00:27:11 +02:00
|
|
|
if (peep->thoughts[0].var_2 > 5)
|
2014-05-27 21:45:40 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
if (peep->thoughts[0].type == PEEP_THOUGHT_TYPE_SCENERY)
|
|
|
|
positiveCount++;
|
|
|
|
|
|
|
|
if (peep->thoughts[0].type == PEEP_THOUGHT_TYPE_BAD_LITTER ||
|
|
|
|
peep->thoughts[0].type == PEEP_THOUGHT_TYPE_PATH_DISGUSTING ||
|
|
|
|
peep->thoughts[0].type == PEEP_THOUGHT_TYPE_VANDALISM
|
|
|
|
) {
|
|
|
|
negativeCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (negativeCount <= 15 && positiveCount > RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_IN_PARK, uint16) / 128);
|
2014-05-27 16:14:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Entrance fee is more than total ride value. */
|
|
|
|
static int award_is_deserved_worse_value(int awardType, int activeAwardTypes)
|
|
|
|
{
|
|
|
|
if (activeAwardTypes & (1 << PARK_AWARD_BEST_VALUE))
|
|
|
|
return 0;
|
|
|
|
if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_11)
|
|
|
|
return 0;
|
|
|
|
if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_ENTRANCE_FEE, money16) == MONEY(0, 00))
|
|
|
|
return 0;
|
|
|
|
if (RCT2_GLOBAL(RCT2_TOTAL_RIDE_VALUE, money16) >= RCT2_GLOBAL(RCT2_ADDRESS_PARK_ENTRANCE_FEE, money16))
|
|
|
|
return 0;
|
|
|
|
return 1;
|
|
|
|
}
|
2014-05-27 19:03:25 +02:00
|
|
|
|
|
|
|
/** No more than 2 people who think the vandalism is bad and no crashes. */
|
2014-05-27 16:14:45 +02:00
|
|
|
static int award_is_deserved_safest(int awardType, int activeAwardTypes)
|
|
|
|
{
|
2014-05-27 21:45:40 +02:00
|
|
|
int i, peepsWhoDislikeVandalism;
|
2014-05-27 19:03:25 +02:00
|
|
|
uint16 spriteIndex;
|
|
|
|
rct_peep *peep;
|
|
|
|
rct_ride *ride;
|
|
|
|
|
2014-05-27 21:45:40 +02:00
|
|
|
peepsWhoDislikeVandalism = 0;
|
2014-05-27 19:03:25 +02:00
|
|
|
FOR_ALL_GUESTS(spriteIndex, peep) {
|
|
|
|
if (peep->var_2A != 0)
|
|
|
|
continue;
|
2014-05-31 00:27:11 +02:00
|
|
|
if (peep->thoughts[0].var_2 <= 5 && peep->thoughts[0].type == PEEP_THOUGHT_TYPE_VANDALISM)
|
2014-05-27 19:03:25 +02:00
|
|
|
peepsWhoDislikeVandalism++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (peepsWhoDislikeVandalism > 2)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// Check for rides that have crashed maybe?
|
|
|
|
FOR_ALL_RIDES(i, ride)
|
|
|
|
if (ride->var_1AE != 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return 1;
|
2014-05-27 16:14:45 +02:00
|
|
|
}
|
|
|
|
|
2014-05-27 21:45:40 +02:00
|
|
|
/** All staff types, at least 20 staff, one staff per 32 peeps. */
|
2014-05-27 16:14:45 +02:00
|
|
|
static int award_is_deserved_best_staff(int awardType, int activeAwardTypes)
|
|
|
|
{
|
2014-05-27 21:45:40 +02:00
|
|
|
uint16 spriteIndex;
|
|
|
|
rct_peep *peep;
|
|
|
|
int peepCount, staffCount;
|
|
|
|
int staffTypeFlags;
|
|
|
|
|
|
|
|
if (activeAwardTypes & (1 << PARK_AWARD_MOST_UNTIDY))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
peepCount = 0;
|
|
|
|
staffCount = 0;
|
|
|
|
staffTypeFlags = 0;
|
|
|
|
FOR_ALL_PEEPS(spriteIndex, peep) {
|
|
|
|
if (peep->type == PEEP_TYPE_STAFF) {
|
|
|
|
staffCount++;
|
|
|
|
staffTypeFlags |= (1 << peep->staff_type);
|
|
|
|
} else {
|
|
|
|
peepCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ((staffTypeFlags & 0xF) && staffCount >= 20 && staffCount >= peepCount / 32);
|
|
|
|
|
2014-05-27 16:14:45 +02:00
|
|
|
}
|
|
|
|
|
2014-05-27 21:45:40 +02:00
|
|
|
/** At least 7 shops, 4 unique, one shop per 128 guests and no more than 12 hungry guests. */
|
2014-05-27 16:14:45 +02:00
|
|
|
static int award_is_deserved_best_food(int awardType, int activeAwardTypes)
|
|
|
|
{
|
2014-05-27 21:45:40 +02:00
|
|
|
int i, hungryPeeps, shops, uniqueShops;
|
|
|
|
uint64 shopTypes;
|
|
|
|
rct_ride *ride;
|
|
|
|
char *object;
|
|
|
|
uint16 spriteIndex;
|
|
|
|
rct_peep *peep;
|
|
|
|
|
|
|
|
if (activeAwardTypes & (1 << PARK_AWARD_WORST_FOOD))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
shops = 0;
|
|
|
|
uniqueShops = 0;
|
|
|
|
shopTypes = 0;
|
|
|
|
FOR_ALL_RIDES(i, ride) {
|
|
|
|
if (ride->status != RIDE_STATUS_OPEN)
|
|
|
|
continue;
|
2014-07-18 22:03:33 +02:00
|
|
|
if (!(RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32) & 0x800000))
|
2014-05-27 21:45:40 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
shops++;
|
|
|
|
object = RCT2_ADDRESS(0x009ACFA4, char*)[ride->subtype];
|
|
|
|
if (!(shopTypes & (1ULL << RCT2_GLOBAL(object + 0x1C0, uint8)))) {
|
|
|
|
shopTypes |= (1ULL << RCT2_GLOBAL(object + 0x1C0, uint8));
|
|
|
|
uniqueShops++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (shops < 7 || uniqueShops < 4 || shops < RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_IN_PARK, uint16) / 128)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// Count hungry peeps
|
|
|
|
hungryPeeps = 0;
|
|
|
|
FOR_ALL_GUESTS(spriteIndex, peep) {
|
|
|
|
if (peep->var_2A != 0)
|
|
|
|
continue;
|
|
|
|
|
2014-05-31 00:27:11 +02:00
|
|
|
if (peep->thoughts[0].var_2 <= 5 && peep->thoughts[0].type == PEEP_THOUGHT_TYPE_HUNGRY)
|
2014-05-27 21:45:40 +02:00
|
|
|
hungryPeeps++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (hungryPeeps <= 12);
|
2014-05-27 16:14:45 +02:00
|
|
|
}
|
|
|
|
|
2014-05-27 21:45:40 +02:00
|
|
|
/** No more than 2 unique shops, less than one shop per 256 guests and more than 15 hungry guests. */
|
2014-05-27 16:14:45 +02:00
|
|
|
static int award_is_deserved_worst_food(int awardType, int activeAwardTypes)
|
|
|
|
{
|
2014-05-27 21:45:40 +02:00
|
|
|
int i, hungryPeeps, shops, uniqueShops;
|
|
|
|
uint64 shopTypes;
|
|
|
|
rct_ride *ride;
|
|
|
|
char *object;
|
|
|
|
uint16 spriteIndex;
|
|
|
|
rct_peep *peep;
|
|
|
|
|
|
|
|
if (activeAwardTypes & (1 << PARK_AWARD_BEST_FOOD))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
shops = 0;
|
|
|
|
uniqueShops = 0;
|
|
|
|
shopTypes = 0;
|
|
|
|
FOR_ALL_RIDES(i, ride) {
|
|
|
|
if (ride->status != RIDE_STATUS_OPEN)
|
|
|
|
continue;
|
2014-07-18 22:03:33 +02:00
|
|
|
if (!(RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32) & 0x800000))
|
2014-05-27 21:45:40 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
shops++;
|
|
|
|
object = RCT2_ADDRESS(0x009ACFA4, char*)[ride->subtype];
|
|
|
|
if (!(shopTypes & (1ULL << RCT2_GLOBAL(object + 0x1C0, uint8)))) {
|
|
|
|
shopTypes |= (1ULL << RCT2_GLOBAL(object + 0x1C0, uint8));
|
|
|
|
uniqueShops++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (uniqueShops > 2 || shops > RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_IN_PARK, uint16) / 256)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// Count hungry peeps
|
|
|
|
hungryPeeps = 0;
|
|
|
|
FOR_ALL_GUESTS(spriteIndex, peep) {
|
|
|
|
if (peep->var_2A != 0)
|
|
|
|
continue;
|
|
|
|
|
2014-05-31 00:27:11 +02:00
|
|
|
if (peep->thoughts[0].var_2 <= 5 && peep->thoughts[0].type == PEEP_THOUGHT_TYPE_HUNGRY)
|
2014-05-27 21:45:40 +02:00
|
|
|
hungryPeeps++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (hungryPeeps > 15);
|
2014-05-27 16:14:45 +02:00
|
|
|
}
|
|
|
|
|
2014-05-27 19:03:25 +02:00
|
|
|
/** At least 4 restrooms, 1 restroom per 128 guests and no more than 16 guests who think they need the restroom. */
|
2014-05-27 16:14:45 +02:00
|
|
|
static int award_is_deserved_best_restrooms(int awardType, int activeAwardTypes)
|
|
|
|
{
|
2014-05-27 19:03:25 +02:00
|
|
|
unsigned int i, numRestrooms, guestsWhoNeedRestroom;
|
|
|
|
rct_ride *ride;
|
|
|
|
uint16 spriteIndex;
|
|
|
|
rct_peep *peep;
|
|
|
|
|
|
|
|
// Count open restrooms
|
|
|
|
numRestrooms = 0;
|
|
|
|
FOR_ALL_RIDES(i, ride)
|
|
|
|
if (ride->type == RIDE_TYPE_BATHROOM && ride->status == RIDE_STATUS_OPEN)
|
|
|
|
numRestrooms++;
|
|
|
|
|
|
|
|
// At least 4 open restrooms
|
|
|
|
if (numRestrooms < 4)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// At least one open restroom for every 128 guests
|
|
|
|
if (numRestrooms < RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_IN_PARK, uint16) / 128U)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// Count number of guests who are thinking they need the restroom
|
|
|
|
guestsWhoNeedRestroom = 0;
|
|
|
|
FOR_ALL_GUESTS(spriteIndex, peep) {
|
|
|
|
if (peep->var_2A != 0)
|
|
|
|
continue;
|
|
|
|
|
2014-05-31 00:27:11 +02:00
|
|
|
if (peep->thoughts[0].var_2 <= 5 && peep->thoughts[0].type == PEEP_THOUGHT_TYPE_BATHROOM)
|
2014-05-27 19:03:25 +02:00
|
|
|
guestsWhoNeedRestroom++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (guestsWhoNeedRestroom <= 16);
|
2014-05-27 16:14:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/** More than half of the rides have satisfication <= 6 and park rating <= 650. */
|
|
|
|
static int award_is_deserved_most_disappointing(int awardType, int activeAwardTypes)
|
|
|
|
{
|
|
|
|
unsigned int i, countedRides, disappointingRides;
|
|
|
|
rct_ride *ride;
|
|
|
|
|
|
|
|
if (activeAwardTypes & (1 << PARK_AWARD_BEST_VALUE))
|
|
|
|
return 0;
|
|
|
|
if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PARK_RATING, uint16) > 650)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// Count the number of disappointing rides
|
|
|
|
countedRides = 0;
|
|
|
|
disappointingRides = 0;
|
|
|
|
|
|
|
|
FOR_ALL_RIDES(i, ride) {
|
|
|
|
if (ride->excitement == 0xFFFF || ride->var_158 == 0xFF)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
countedRides++;
|
|
|
|
|
|
|
|
// Satification maybe?
|
|
|
|
if (ride->var_158 <= 6)
|
|
|
|
disappointingRides++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Half of the rides are disappointing
|
|
|
|
return (disappointingRides >= countedRides / 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** At least 6 open water rides. */
|
|
|
|
static int award_is_deserved_best_water_rides(int awardType, int activeAwardTypes)
|
|
|
|
{
|
|
|
|
int i, waterRides;
|
|
|
|
rct_ride *ride;
|
|
|
|
char *object;
|
|
|
|
|
|
|
|
waterRides = 0;
|
|
|
|
FOR_ALL_RIDES(i, ride) {
|
|
|
|
object = RCT2_ADDRESS(0x009ACFA4, char*)[ride->subtype];
|
|
|
|
if (RCT2_GLOBAL(object + 0x1BE, uint8) != RIDE_GROUP_WATER && RCT2_GLOBAL(object + 0x1BF, uint8) != RIDE_GROUP_WATER)
|
|
|
|
continue;
|
|
|
|
|
2014-05-27 19:03:25 +02:00
|
|
|
if (ride->status != RIDE_STATUS_OPEN || (ride->lifecycle_flags & 0x400))
|
2014-05-27 16:14:45 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
waterRides++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (waterRides >= 6);
|
|
|
|
}
|
|
|
|
|
2014-05-27 19:03:25 +02:00
|
|
|
/** At least 6 custom designed rides. */
|
2014-05-27 16:14:45 +02:00
|
|
|
static int award_is_deserved_best_custom_designed_rides(int awardType, int activeAwardTypes)
|
|
|
|
{
|
2014-05-27 19:03:25 +02:00
|
|
|
int i, customDesignedRides;
|
|
|
|
rct_ride *ride;
|
|
|
|
|
|
|
|
if (activeAwardTypes & (1 << PARK_AWARD_MOST_DISAPPOINTING))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
customDesignedRides = 0;
|
|
|
|
FOR_ALL_RIDES(i, ride) {
|
2014-07-18 22:03:33 +02:00
|
|
|
if (!(RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32) & 0x10000000))
|
2014-05-27 19:03:25 +02:00
|
|
|
continue;
|
|
|
|
if (ride->lifecycle_flags & 0x40000)
|
|
|
|
continue;
|
|
|
|
if (ride->excitement < RIDE_RATING(5, 50))
|
|
|
|
continue;
|
|
|
|
if (ride->status != RIDE_STATUS_OPEN || (ride->lifecycle_flags & 0x400))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
customDesignedRides++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (customDesignedRides >= 6);
|
2014-05-27 16:14:45 +02:00
|
|
|
}
|
|
|
|
|
2014-05-27 19:03:25 +02:00
|
|
|
/** At least 5 colourful rides and more than half of the rides are colourful. */
|
2014-05-27 16:14:45 +02:00
|
|
|
static int award_is_deserved_most_dazzling_ride_colours(int awardType, int activeAwardTypes)
|
|
|
|
{
|
2014-05-27 19:03:25 +02:00
|
|
|
int i, countedRides, colourfulRides;
|
|
|
|
rct_ride *ride;
|
|
|
|
|
|
|
|
if (activeAwardTypes & (1 << PARK_AWARD_MOST_DISAPPOINTING))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
countedRides = 0;
|
|
|
|
colourfulRides = 0;
|
|
|
|
FOR_ALL_RIDES(i, ride) {
|
2014-07-18 22:03:33 +02:00
|
|
|
if (!(RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32) & 0x10000000))
|
2014-05-27 19:03:25 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
countedRides++;
|
|
|
|
if (ride->var_1BC == 5 || ride->var_1BC == 14 || ride->var_1BC == 20 || ride->var_1BC == 30)
|
|
|
|
colourfulRides++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (colourfulRides >= 5 && colourfulRides >= countedRides - colourfulRides);
|
2014-05-27 16:14:45 +02:00
|
|
|
}
|
|
|
|
|
2014-05-27 19:03:25 +02:00
|
|
|
/** At least 10 peeps and more than 1/64 of total guests are lost or can't find something. */
|
2014-05-27 16:14:45 +02:00
|
|
|
static int award_is_deserved_most_confusing_layout(int awardType, int activeAwardTypes)
|
|
|
|
{
|
2014-05-27 19:03:25 +02:00
|
|
|
unsigned int peepsCounted, peepsLost;
|
|
|
|
uint16 spriteIndex;
|
|
|
|
rct_peep *peep;
|
|
|
|
|
|
|
|
peepsCounted = 0;
|
|
|
|
peepsLost = 0;
|
|
|
|
FOR_ALL_GUESTS(spriteIndex, peep) {
|
|
|
|
if (peep->var_2A != 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
peepsCounted++;
|
2014-05-31 00:27:11 +02:00
|
|
|
if (peep->thoughts[0].var_2 <= 5 && peep->thoughts[0].type == PEEP_THOUGHT_TYPE_LOST || peep->thoughts[0].type == PEEP_THOUGHT_TYPE_CANT_FIND)
|
2014-05-27 19:03:25 +02:00
|
|
|
peepsLost++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (peepsLost >= 10 && peepsLost >= peepsCounted / 64);
|
2014-05-27 16:14:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/** At least 10 open gentle rides. */
|
|
|
|
static int award_is_deserved_best_gentle_rides(int awardType, int activeAwardTypes)
|
|
|
|
{
|
|
|
|
int i, gentleRides;
|
|
|
|
rct_ride *ride;
|
|
|
|
char *object;
|
|
|
|
|
|
|
|
gentleRides = 0;
|
|
|
|
FOR_ALL_RIDES(i, ride) {
|
|
|
|
object = RCT2_ADDRESS(0x009ACFA4, char*)[ride->subtype];
|
|
|
|
if (RCT2_GLOBAL(object + 0x1BE, uint8) != RIDE_GROUP_GENTLE && RCT2_GLOBAL(object + 0x1BF, uint8) != RIDE_GROUP_GENTLE)
|
|
|
|
continue;
|
|
|
|
|
2014-05-27 19:03:25 +02:00
|
|
|
if (ride->status != RIDE_STATUS_OPEN || (ride->lifecycle_flags & 0x400))
|
2014-05-27 16:14:45 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
gentleRides++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (gentleRides >= 10);
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef int (*award_deserved_check)(int, int);
|
|
|
|
|
|
|
|
award_deserved_check _awardChecks[] = {
|
|
|
|
award_is_deserved_most_untidy,
|
|
|
|
award_is_deserved_most_tidy,
|
|
|
|
award_is_deserved_best_rollercoasters,
|
|
|
|
award_is_deserved_best_value,
|
|
|
|
award_is_deserved_most_beautiful,
|
|
|
|
award_is_deserved_worse_value,
|
|
|
|
award_is_deserved_safest,
|
|
|
|
award_is_deserved_best_staff,
|
|
|
|
award_is_deserved_best_food,
|
|
|
|
award_is_deserved_worst_food,
|
|
|
|
award_is_deserved_best_restrooms,
|
|
|
|
award_is_deserved_most_disappointing,
|
|
|
|
award_is_deserved_best_water_rides,
|
|
|
|
award_is_deserved_best_custom_designed_rides,
|
|
|
|
award_is_deserved_most_dazzling_ride_colours,
|
|
|
|
award_is_deserved_most_confusing_layout,
|
|
|
|
award_is_deserved_best_gentle_rides
|
|
|
|
};
|
|
|
|
|
|
|
|
static int award_is_deserved(int awardType, int activeAwardTypes)
|
|
|
|
{
|
|
|
|
return _awardChecks[awardType](awardType, activeAwardTypes);
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma endregion
|
|
|
|
|
2014-05-28 02:50:50 +02:00
|
|
|
void award_reset()
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < MAX_AWARDS; i++)
|
|
|
|
RCT2_ADDRESS(RCT2_ADDRESS_AWARD_LIST, rct_award)[i].time = 0;
|
|
|
|
}
|
|
|
|
|
2014-05-27 16:14:45 +02:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* rct2: 0x0066A86C
|
|
|
|
*/
|
|
|
|
void award_update_all()
|
|
|
|
{
|
|
|
|
int i, activeAwardTypes, freeAwardEntryIndex;
|
|
|
|
rct_award *awards;
|
|
|
|
|
|
|
|
awards = RCT2_ADDRESS(RCT2_ADDRESS_AWARD_LIST, rct_award);
|
|
|
|
|
|
|
|
// Only add new awards if park is open
|
|
|
|
if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_PARK_OPEN) {
|
|
|
|
// Set active award types as flags
|
|
|
|
activeAwardTypes = 0;
|
|
|
|
freeAwardEntryIndex = -1;
|
|
|
|
for (i = 0; i < MAX_AWARDS; i++) {
|
|
|
|
if (awards[i].time != 0)
|
|
|
|
activeAwardTypes |= (1 << awards[i].type);
|
2014-05-27 22:02:20 +02:00
|
|
|
else if (freeAwardEntryIndex == -1)
|
2014-05-27 16:14:45 +02:00
|
|
|
freeAwardEntryIndex = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if there was a free award entry
|
|
|
|
if (freeAwardEntryIndex != -1) {
|
|
|
|
// Get a random award type not already active
|
|
|
|
int awardType;
|
|
|
|
do {
|
|
|
|
awardType = (((scenario_rand() & 0xFF) * 17) >> 8) & 0xFF;
|
|
|
|
} while (activeAwardTypes & (1 << awardType));
|
|
|
|
|
|
|
|
// Check if award is deserved
|
|
|
|
if (award_is_deserved(awardType, activeAwardTypes)) {
|
|
|
|
// Add award
|
|
|
|
awards[freeAwardEntryIndex].type = awardType;
|
|
|
|
awards[freeAwardEntryIndex].time = 5;
|
|
|
|
news_item_add_to_queue(NEWS_ITEM_AWARD, STR_NEWS_ITEM_AWARD_MOST_UNTIDY + awardType, 0);
|
|
|
|
window_invalidate_by_id(WC_PARK_INFORMATION, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Decrease award times
|
|
|
|
for (i = 0; i < MAX_AWARDS; i++)
|
|
|
|
if (awards[i].time != 0)
|
|
|
|
if (--awards[i].time == 0)
|
|
|
|
window_invalidate_by_id(WC_PARK_INFORMATION, 0);
|
|
|
|
}
|