mirror of
https://github.com/JGRennison/OpenTTD-patches.git
synced 2024-11-19 15:25:39 +00:00
1a81c1cedd
start off larger, and will grow twice as quickly as other towns. They can also be placed specifically in the scenario editor. Thanks to TheJosh for the initial patch and the idea.
363 lines
11 KiB
C
363 lines
11 KiB
C
/* $Id$ */
|
|
|
|
/** @file town.h */
|
|
|
|
#ifndef TOWN_H
|
|
#define TOWN_H
|
|
|
|
#include "oldpool.h"
|
|
#include "player.h"
|
|
#include "functions.h"
|
|
#include "helpers.hpp"
|
|
|
|
enum {
|
|
HOUSE_NO_CLASS = 0,
|
|
NEW_HOUSE_OFFSET = 110,
|
|
HOUSE_MAX = 512,
|
|
INVALID_TOWN = 0xFFFF,
|
|
INVALID_HOUSE_ID = 0xFFFF,
|
|
|
|
/* There can only be as many classes as there are new houses, plus one for
|
|
* NO_CLASS, as the original houses don't have classes. */
|
|
HOUSE_CLASS_MAX = HOUSE_MAX - NEW_HOUSE_OFFSET + 1,
|
|
};
|
|
|
|
enum BuildingFlags {
|
|
TILE_NO_FLAG = 0,
|
|
TILE_SIZE_1x1 = 1U << 0,
|
|
TILE_NOT_SLOPED = 1U << 1,
|
|
TILE_SIZE_2x1 = 1U << 2,
|
|
TILE_SIZE_1x2 = 1U << 3,
|
|
TILE_SIZE_2x2 = 1U << 4,
|
|
BUILDING_IS_ANIMATED = 1U << 5,
|
|
BUILDING_IS_CHURCH = 1U << 6,
|
|
BUILDING_IS_STADIUM = 1U << 7,
|
|
BUILDING_HAS_1_TILE = TILE_SIZE_1x1 | TILE_SIZE_2x1 | TILE_SIZE_1x2 | TILE_SIZE_2x2,
|
|
BUILDING_2_TILES_X = TILE_SIZE_2x1 | TILE_SIZE_2x2,
|
|
BUILDING_2_TILES_Y = TILE_SIZE_1x2 | TILE_SIZE_2x2,
|
|
BUILDING_HAS_4_TILES = TILE_SIZE_2x2,
|
|
};
|
|
|
|
DECLARE_ENUM_AS_BIT_SET(BuildingFlags)
|
|
|
|
enum HouseZones { ///< Bit Value Meaning
|
|
HZ_NOZNS = 0x0000, ///< 0 This is just to get rid of zeros, meaning none
|
|
HZ_ZON1 = 0x0001, ///< 0..4 1,2,4,8,10 which town zones the building can be built in, Zone1 been the further suburb
|
|
HZ_ZON2 = 0x0002,
|
|
HZ_ZON3 = 0x0004,
|
|
HZ_ZON4 = 0x0008,
|
|
HZ_ZON5 = 0x0010, ///< center of town
|
|
HZ_ZONALL = 0x001F, ///< 1F This is just to englobe all above types at once
|
|
HZ_SUBARTC_ABOVE = 0x0800, ///< 11 800 can appear in sub-arctic climate above the snow line
|
|
HZ_TEMP = 0x1000, ///< 12 1000 can appear in temperate climate
|
|
HZ_SUBARTC_BELOW = 0x2000, ///< 13 2000 can appear in sub-arctic climate below the snow line
|
|
HZ_SUBTROPIC = 0x4000, ///< 14 4000 can appear in subtropical climate
|
|
HZ_TOYLND = 0x8000 ///< 15 8000 can appear in toyland climate
|
|
};
|
|
|
|
DECLARE_ENUM_AS_BIT_SET(HouseZones)
|
|
|
|
enum HouseExtraFlags {
|
|
NO_EXTRA_FLAG = 0,
|
|
BUILDING_IS_HISTORICAL = 1U << 0, ///< this house will only appear during town generation in random games, thus the historical
|
|
BUILDING_IS_PROTECTED = 1U << 1, ///< towns and AI will not remove this house, while human players will be able tp
|
|
SYNCHRONISED_CALLBACK_1B = 1U << 2, ///< synchronized callback 1B will be performed, on multi tile houses
|
|
CALLBACK_1A_RANDOM_BITS = 1U << 3, ///< callback 1A needs random bits
|
|
};
|
|
|
|
DECLARE_ENUM_AS_BIT_SET(HouseExtraFlags)
|
|
|
|
typedef uint16 HouseID;
|
|
typedef uint16 HouseClassID;
|
|
|
|
struct BuildingCounts {
|
|
uint8 id_count[HOUSE_MAX];
|
|
uint8 class_count[HOUSE_CLASS_MAX];
|
|
};
|
|
|
|
struct Town {
|
|
TileIndex xy;
|
|
|
|
/* Current population of people and amount of houses. */
|
|
uint16 num_houses;
|
|
uint32 population;
|
|
|
|
/* Town name */
|
|
uint16 townnametype;
|
|
uint32 townnameparts;
|
|
|
|
/* NOSAVE: Location of name sign, UpdateTownVirtCoord updates this. */
|
|
ViewportSign sign;
|
|
|
|
/* Makes sure we don't build certain house types twice.
|
|
* bit 0 = Building funds received
|
|
* bit 1 = CHURCH
|
|
* bit 2 = STADIUM */
|
|
byte flags12;
|
|
|
|
/* Which players have a statue? */
|
|
byte statues;
|
|
|
|
/* Player ratings as well as a mask that determines which players have a rating. */
|
|
byte have_ratings;
|
|
uint8 unwanted[MAX_PLAYERS]; ///< how many months companies aren't wanted by towns (bribe)
|
|
PlayerByte exclusivity; ///< which player has exslusivity
|
|
uint8 exclusive_counter; ///< months till the exclusivity expires
|
|
int16 ratings[MAX_PLAYERS];
|
|
|
|
/* Maximum amount of passengers and mail that can be transported. */
|
|
uint32 max_pass;
|
|
uint32 max_mail;
|
|
uint32 new_max_pass;
|
|
uint32 new_max_mail;
|
|
uint32 act_pass;
|
|
uint32 act_mail;
|
|
uint32 new_act_pass;
|
|
uint32 new_act_mail;
|
|
|
|
/* Amount of passengers that were transported. */
|
|
byte pct_pass_transported;
|
|
byte pct_mail_transported;
|
|
|
|
/* Amount of food and paper that was transported. Actually a bit mask would be enough. */
|
|
uint16 act_food;
|
|
uint16 act_water;
|
|
uint16 new_act_food;
|
|
uint16 new_act_water;
|
|
|
|
/* Time until we rebuild a house. */
|
|
uint16 time_until_rebuild;
|
|
|
|
/* When to grow town next time. */
|
|
uint16 grow_counter;
|
|
int16 growth_rate;
|
|
|
|
/* Fund buildings program in action? */
|
|
byte fund_buildings_months;
|
|
|
|
/* Fund road reconstruction in action? */
|
|
byte road_build_months;
|
|
|
|
/* Index in town array */
|
|
TownID index;
|
|
|
|
/* If this is a larger town, and should grow more quickly. */
|
|
bool larger_town;
|
|
|
|
/* NOSAVE: UpdateTownRadius updates this given the house count. */
|
|
uint16 radius[5];
|
|
|
|
/* NOSAVE: The number of each type of building in the town. */
|
|
BuildingCounts building_counts;
|
|
};
|
|
|
|
struct HouseSpec {
|
|
/* Standard properties */
|
|
Year min_date; ///< introduction year of the house
|
|
Year max_date; ///< last year it can be built
|
|
byte population; ///< population (Zero on other tiles in multi tile house.)
|
|
byte removal_cost; ///< cost multiplier for removing it
|
|
StringID building_name; ///< building name
|
|
uint16 remove_rating_decrease; ///< rating decrease if removed
|
|
byte mail_generation; ///< mail generation multiplier (tile based, as the acceptances below)
|
|
byte cargo_acceptance[3]; ///< acceptance level for the cargo slots
|
|
CargoID accepts_cargo[3]; ///< 3 input cargo slots
|
|
BuildingFlags building_flags; ///< some flags that describe the house (size, stadium etc...)
|
|
HouseZones building_availability; ///< where can it be built (climates, zones)
|
|
bool enabled; ///< the house is still avaible (by default, true.newgrf can disable it, though)
|
|
|
|
/* NewHouses properties */
|
|
HouseID substitute_id; ///< which house this one is based on
|
|
struct SpriteGroup *spritegroup; ///< pointer to the different sprites of the house
|
|
HouseID override; ///< which house this one replaces
|
|
uint16 callback_mask; ///< House callback flags
|
|
byte random_colour[4]; ///< 4 "random" colours
|
|
byte probability; ///< Relative probability of appearing (16 is the standard value)
|
|
HouseExtraFlags extra_flags; ///< some more flags
|
|
HouseClassID class_id; ///< defines the class this house has (grf file based) @See HouseGetVariable, prop 0x44
|
|
byte animation_frames; ///< number of animation frames
|
|
byte animation_speed; ///< amount of time between each of those frames
|
|
byte processing_time; ///< Periodic refresh multiplier
|
|
|
|
/* grf file related properties*/
|
|
uint8 local_id; ///< id defined by the grf file for this house
|
|
const struct GRFFile *grffile; ///< grf file that introduced this house
|
|
};
|
|
|
|
enum TownSizeMode {
|
|
TSM_RANDOM,
|
|
TSM_FIXED,
|
|
TSM_CITY
|
|
};
|
|
|
|
VARDEF HouseSpec _house_specs[HOUSE_MAX];
|
|
|
|
uint32 GetWorldPopulation();
|
|
|
|
void UpdateTownVirtCoord(Town *t);
|
|
void InitializeTown();
|
|
void ShowTownViewWindow(TownID town);
|
|
void ExpandTown(Town *t);
|
|
Town *CreateRandomTown(uint attempts, TownSizeMode mode, uint size);
|
|
|
|
enum {
|
|
ROAD_REMOVE = 0,
|
|
UNMOVEABLE_REMOVE = 1,
|
|
TUNNELBRIDGE_REMOVE = 1,
|
|
INDUSTRY_REMOVE = 2
|
|
};
|
|
|
|
enum {
|
|
/* These refer to the maximums, so Appalling is -1000 to -400
|
|
* MAXIMUM RATINGS BOUNDARIES */
|
|
RATING_MINIMUM = -1000,
|
|
RATING_APPALLING = -400,
|
|
RATING_VERYPOOR = -200,
|
|
RATING_POOR = 0,
|
|
RATING_MEDIOCRE = 200,
|
|
RATING_GOOD = 400,
|
|
RATING_VERYGOOD = 600,
|
|
RATING_EXCELLENT = 800,
|
|
RATING_OUTSTANDING = 1000, ///< OUTSTANDING
|
|
|
|
RATING_MAXIMUM = RATING_OUTSTANDING,
|
|
|
|
/* RATINGS AFFECTING NUMBERS */
|
|
RATING_TREE_DOWN_STEP = -35,
|
|
RATING_TREE_MINIMUM = RATING_MINIMUM,
|
|
RATING_TREE_UP_STEP = 7,
|
|
RATING_TREE_MAXIMUM = 220,
|
|
|
|
RATING_TUNNEL_BRIDGE_DOWN_STEP = -250,
|
|
RATING_TUNNEL_BRIDGE_MINIMUM = 0,
|
|
|
|
RATING_INDUSTRY_DOWN_STEP = -1500,
|
|
RATING_INDUSTRY_MINIMUM = RATING_MINIMUM,
|
|
|
|
RATING_ROAD_DOWN_STEP = -50,
|
|
RATING_ROAD_MINIMUM = -100,
|
|
RATING_HOUSE_MINIMUM = RATING_MINIMUM,
|
|
|
|
RATING_BRIBE_UP_STEP = 200,
|
|
RATING_BRIBE_MAXIMUM = 800,
|
|
RATING_BRIBE_DOWN_TO = -50 // XXX SHOULD BE SOMETHING LOWER?
|
|
};
|
|
|
|
/** This is the number of ticks between towns being processed for building new
|
|
* houses or roads. This value originally came from the size of the town array
|
|
* in TTD. */
|
|
static const byte TOWN_GROWTH_FREQUENCY = 70;
|
|
|
|
/** Simple value that indicates the house has reached the final stage of
|
|
* construction. */
|
|
static const byte TOWN_HOUSE_COMPLETED = 3;
|
|
|
|
/** This enum is used in conjonction with town->flags12.
|
|
* IT simply states what bit is used for.
|
|
* It is pretty unrealistic (IMHO) to only have one church/stadium
|
|
* per town, NO MATTER the population of it.
|
|
* And there are 5 more bits available on flags12...
|
|
*/
|
|
enum {
|
|
TOWN_IS_FUNDED = 0, ///< Town has received some funds for
|
|
TOWN_HAS_CHURCH = 1, ///< There can be only one church by town.
|
|
TOWN_HAS_STADIUM = 2 ///< There can be only one stadium by town.
|
|
};
|
|
|
|
bool CheckforTownRating(uint32 flags, Town *t, byte type);
|
|
|
|
VARDEF const Town** _town_sort;
|
|
|
|
DECLARE_OLD_POOL(Town, Town, 3, 8000)
|
|
|
|
static inline HouseSpec *GetHouseSpecs(HouseID house_id)
|
|
{
|
|
assert(house_id < HOUSE_MAX);
|
|
return &_house_specs[house_id];
|
|
}
|
|
|
|
/**
|
|
* Check if a Town really exists.
|
|
* @param town to inquiry
|
|
* @return true if it exists
|
|
*/
|
|
static inline bool IsValidTown(const Town* town)
|
|
{
|
|
return town->xy != 0;
|
|
}
|
|
|
|
/**
|
|
* Check if a TownID is valid.
|
|
* @param index to inquiry in the pool of town
|
|
* @return true if it exists
|
|
*/
|
|
static inline bool IsValidTownID(TownID index)
|
|
{
|
|
return index < GetTownPoolSize() && IsValidTown(GetTown(index));
|
|
}
|
|
|
|
VARDEF uint _total_towns;
|
|
|
|
static inline TownID GetMaxTownIndex()
|
|
{
|
|
/* TODO - This isn't the real content of the function, but
|
|
* with the new pool-system this will be replaced with one that
|
|
* _really_ returns the highest index. Now it just returns
|
|
* the next safe value we are sure about everything is below.
|
|
*/
|
|
return GetTownPoolSize() - 1;
|
|
}
|
|
|
|
static inline uint GetNumTowns()
|
|
{
|
|
return _total_towns;
|
|
}
|
|
|
|
/**
|
|
* Return a random valid town.
|
|
*/
|
|
static inline Town *GetRandomTown()
|
|
{
|
|
int num = RandomRange(GetNumTowns());
|
|
TownID index = INVALID_TOWN;
|
|
|
|
while (num >= 0) {
|
|
num--;
|
|
|
|
index++;
|
|
/* Make sure we have a valid town */
|
|
while (!IsValidTownID(index)) {
|
|
index++;
|
|
assert(index <= GetMaxTownIndex());
|
|
}
|
|
}
|
|
|
|
return GetTown(index);
|
|
}
|
|
|
|
void DestroyTown(Town *t);
|
|
|
|
static inline void DeleteTown(Town *t)
|
|
{
|
|
DestroyTown(t);
|
|
t->xy = 0;
|
|
}
|
|
|
|
Town* CalcClosestTownFromTile(TileIndex tile, uint threshold);
|
|
|
|
#define FOR_ALL_TOWNS_FROM(t, start) for (t = GetTown(start); t != NULL; t = (t->index + 1U < GetTownPoolSize()) ? GetTown(t->index + 1U) : NULL) if (IsValidTown(t))
|
|
#define FOR_ALL_TOWNS(t) FOR_ALL_TOWNS_FROM(t, 0)
|
|
|
|
VARDEF bool _town_sort_dirty;
|
|
VARDEF byte _town_sort_order;
|
|
|
|
VARDEF Town *_cleared_town;
|
|
VARDEF int _cleared_town_rating;
|
|
|
|
uint OriginalTileRandomiser(uint x, uint y);
|
|
void ResetHouses();
|
|
|
|
void ClearTownHouse(Town *t, TileIndex tile);
|
|
|
|
#endif /* TOWN_H */
|