1
0
Fork 0

Add: Houses can accept up to 16 different cargo types via NewGRF.

New Action0 property 23 for feature 07, variable length, format B n*(B B). Initial byte is number of structures following. First byte in structure is cargo id, second is acceptance level in 1/8 units.
pull/7079/head
Niels Martin Hansen 2018-07-28 23:28:24 +02:00
parent 9ce92521c1
commit 48b334cf97
4 changed files with 56 additions and 25 deletions

View File

@ -31,6 +31,8 @@ static const HouseID NEW_HOUSE_OFFSET = 110; ///< Offset for new houses.
static const HouseID NUM_HOUSES = 512; ///< Total number of houses. static const HouseID NUM_HOUSES = 512; ///< Total number of houses.
static const HouseID INVALID_HOUSE_ID = 0xFFFF; static const HouseID INVALID_HOUSE_ID = 0xFFFF;
static const uint HOUSE_NUM_ACCEPTS = 16; ///< Max number of cargoes accepted by a tile
/** /**
* There can only be as many classes as there are new houses, plus one for * 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. * NO_CLASS, as the original houses don't have classes.
@ -97,30 +99,30 @@ DECLARE_ENUM_AS_BIT_SET(HouseExtraFlags)
struct HouseSpec { struct HouseSpec {
/* Standard properties */ /* Standard properties */
Year min_year; ///< introduction year of the house Year min_year; ///< introduction year of the house
Year max_year; ///< last year it can be built Year max_year; ///< last year it can be built
byte population; ///< population (Zero on other tiles in multi tile house.) byte population; ///< population (Zero on other tiles in multi tile house.)
byte removal_cost; ///< cost multiplier for removing it byte removal_cost; ///< cost multiplier for removing it
StringID building_name; ///< building name StringID building_name; ///< building name
uint16 remove_rating_decrease; ///< rating decrease if removed uint16 remove_rating_decrease; ///< rating decrease if removed
byte mail_generation; ///< mail generation multiplier (tile based, as the acceptances below) byte mail_generation; ///< mail generation multiplier (tile based, as the acceptances below)
byte cargo_acceptance[3]; ///< acceptance level for the cargo slots byte cargo_acceptance[HOUSE_NUM_ACCEPTS]; ///< acceptance level for the cargo slots
CargoID accepts_cargo[3]; ///< 3 input cargo slots CargoID accepts_cargo[HOUSE_NUM_ACCEPTS]; ///< input cargo slots
BuildingFlags building_flags; ///< some flags that describe the house (size, stadium etc...) BuildingFlags building_flags; ///< some flags that describe the house (size, stadium etc...)
HouseZones building_availability; ///< where can it be built (climates, zones) HouseZones building_availability; ///< where can it be built (climates, zones)
bool enabled; ///< the house is available to build (true by default, but can be disabled by newgrf) bool enabled; ///< the house is available to build (true by default, but can be disabled by newgrf)
/* NewHouses properties */ /* NewHouses properties */
GRFFileProps grf_prop; ///< Properties related the the grf file GRFFileProps grf_prop; ///< Properties related the the grf file
uint16 callback_mask; ///< Bitmask of house callbacks that have to be called uint16 callback_mask; ///< Bitmask of house callbacks that have to be called
byte random_colour[4]; ///< 4 "random" colours byte random_colour[4]; ///< 4 "random" colours
byte probability; ///< Relative probability of appearing (16 is the standard value) byte probability; ///< Relative probability of appearing (16 is the standard value)
HouseExtraFlags extra_flags; ///< some more flags HouseExtraFlags extra_flags; ///< some more flags
HouseClassID class_id; ///< defines the class this house has (not grf file based) HouseClassID class_id; ///< defines the class this house has (not grf file based)
AnimationInfo animation; ///< information about the animation. AnimationInfo animation; ///< information about the animation.
byte processing_time; ///< Periodic refresh multiplier byte processing_time; ///< Periodic refresh multiplier
byte minimum_life; ///< The minimum number of years this house will survive before the town rebuilds it byte minimum_life; ///< The minimum number of years this house will survive before the town rebuilds it
CargoTypes watched_cargoes; ///< Cargo types watched for acceptance. CargoTypes watched_cargoes; ///< Cargo types watched for acceptance.
Money GetRemovalCost() const; Money GetRemovalCost() const;

View File

@ -2294,6 +2294,10 @@ static ChangeInfoResult IgnoreTownHouseProperty(int prop, ByteReader *buf)
break; break;
} }
case 0x23:
buf->Skip(buf->ReadByte() * 2);
break;
default: default:
ret = CIR_UNKNOWN; ret = CIR_UNKNOWN;
break; break;
@ -2526,6 +2530,28 @@ static ChangeInfoResult TownHouseChangeInfo(uint hid, int numinfo, int prop, Byt
housespec->max_year = buf->ReadWord(); housespec->max_year = buf->ReadWord();
break; break;
case 0x23: { // variable length cargo types accepted
uint count = buf->ReadByte();
if (count > lengthof(housespec->accepts_cargo)) {
GRFError *error = DisableGrf(STR_NEWGRF_ERROR_LIST_PROPERTY_TOO_LONG);
error->param_value[1] = prop;
return CIR_DISABLED;
}
/* Always write the full accepts_cargo array, and check each index for being inside the
* provided data. This ensures all values are properly initialized, and also avoids
* any risks of array overrun. */
for (uint i = 0; i < lengthof(housespec->accepts_cargo); i++) {
if (i < count) {
housespec->accepts_cargo[i] = GetCargoTranslation(buf->ReadByte(), _cur.grffile);
housespec->cargo_acceptance[i] = buf->ReadByte();
} else {
housespec->accepts_cargo[i] = CT_INVALID;
housespec->cargo_acceptance[i] = 0;
}
}
break;
}
default: default:
ret = CIR_UNKNOWN; ret = CIR_UNKNOWN;
break; break;

View File

@ -1812,8 +1812,11 @@ assert_compile(lengthof(_town_draw_tile_data) == (NEW_HOUSE_OFFSET) * 4 * 4);
* @see HouseSpec * @see HouseSpec
*/ */
#define MS(mnd, mxd, p, rc, bn, rr, mg, ca1, ca2, ca3, bf, ba, cg1, cg2, cg3) \ #define MS(mnd, mxd, p, rc, bn, rr, mg, ca1, ca2, ca3, bf, ba, cg1, cg2, cg3) \
{mnd, mxd, p, rc, bn, rr, mg, {ca1, ca2, ca3}, {cg1, cg2, cg3}, bf, ba, true, \ {mnd, mxd, p, rc, bn, rr, mg, \
GRFFileProps(INVALID_HOUSE_ID), 0, {0, 0, 0, 0}, 16, NO_EXTRA_FLAG, HOUSE_NO_CLASS, {0, 2, 0, 0}, 0, 0, 0} {ca1, ca2, ca3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
{cg1, cg2, cg3, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID}, \
bf, ba, true, GRFFileProps(INVALID_HOUSE_ID), 0, {0, 0, 0, 0}, \
16, NO_EXTRA_FLAG, HOUSE_NO_CLASS, {0, 2, 0, 0}, 0, 0, 0}
/** House specifications from original data */ /** House specifications from original data */
static const HouseSpec _original_house_specs[] = { static const HouseSpec _original_house_specs[] = {
/** /**

View File

@ -611,7 +611,7 @@ static inline void AddAcceptedCargoSetMask(CargoID cargo, uint amount, CargoArra
static void AddAcceptedCargo_Town(TileIndex tile, CargoArray &acceptance, CargoTypes *always_accepted) static void AddAcceptedCargo_Town(TileIndex tile, CargoArray &acceptance, CargoTypes *always_accepted)
{ {
const HouseSpec *hs = HouseSpec::Get(GetHouseType(tile)); const HouseSpec *hs = HouseSpec::Get(GetHouseType(tile));
CargoID accepts[3]; CargoID accepts[lengthof(hs->accepts_cargo)];
/* Set the initial accepted cargo types */ /* Set the initial accepted cargo types */
for (uint8 i = 0; i < lengthof(accepts); i++) { for (uint8 i = 0; i < lengthof(accepts); i++) {