Changeset - r27438:22e72ba90974
[Not reviewed]
master
0 16 0
PeterN - 18 months ago 2023-05-25 20:25:46
peter1138@openttd.org
Change: Reorganise industry accept/produce arrays. (#10853)

Use a array of struct for each cargo instead of an array for each statistic.
This makes iterating for acceptance and production much simpler.
pct_transported is now calculated when needed.
16 files changed with 531 insertions and 359 deletions:
0 comments (0 inline, 0 general)
src/economy.cpp
Show inline comments
 
@@ -1017,9 +1017,9 @@ static uint DeliverGoodsToIndustry(const
 
		Industry *ind = i.industry;
 
		if (ind->index == source) continue;
 

	
 
		int cargo_index = ind->GetCargoAcceptedIndex(cargo_type);
 
		auto it = ind->GetCargoAccepted(cargo_type);
 
		/* Check if matching cargo has been found */
 
		if (cargo_index < 0) continue;
 
		if (it == std::end(ind->accepted)) continue;
 

	
 
		/* Check if industry temporarily refuses acceptance */
 
		if (IndustryTemporarilyRefusesCargo(ind, cargo_type)) continue;
 
@@ -1029,9 +1029,9 @@ static uint DeliverGoodsToIndustry(const
 
		/* Insert the industry into _cargo_delivery_destinations, if not yet contained */
 
		include(_cargo_delivery_destinations, ind);
 

	
 
		uint amount = std::min(num_pieces, 0xFFFFu - ind->incoming_cargo_waiting[cargo_index]);
 
		ind->incoming_cargo_waiting[cargo_index] += amount;
 
		ind->last_cargo_accepted_at[cargo_index] = TimerGameCalendar::date;
 
		uint amount = std::min(num_pieces, 0xFFFFu - it->waiting);
 
		it->waiting += amount;
 
		it->last_accepted = TimerGameCalendar::date;
 
		num_pieces -= amount;
 
		accepted += amount;
 

	
 
@@ -1119,15 +1119,14 @@ static void TriggerIndustryProduction(In
 
			SetWindowDirty(WC_INDUSTRY_VIEW, i->index);
 
		}
 
	} else {
 
		for (uint ci_in = 0; ci_in < lengthof(i->incoming_cargo_waiting); ci_in++) {
 
			uint cargo_waiting = i->incoming_cargo_waiting[ci_in];
 
			if (cargo_waiting == 0) continue;
 
		for (auto ita = std::begin(i->accepted); ita != std::end(i->accepted); ++ita) {
 
			if (ita->waiting == 0) continue;
 

	
 
			for (uint ci_out = 0; ci_out < lengthof(i->produced_cargo_waiting); ci_out++) {
 
				i->produced_cargo_waiting[ci_out] = ClampTo<uint16_t>(i->produced_cargo_waiting[ci_out] + (cargo_waiting * indspec->input_cargo_multiplier[ci_in][ci_out] / 256));
 
			for (auto itp = std::begin(i->produced); itp != std::end(i->produced); ++itp) {
 
				itp->waiting = ClampTo<uint16_t>(itp->waiting + (ita->waiting * indspec->input_cargo_multiplier[ita - std::begin(i->accepted)][itp - std::begin(i->produced)] / 256));
 
			}
 

	
 
			i->incoming_cargo_waiting[ci_in] = 0;
 
			ita->waiting = 0;
 
		}
 
	}
 

	
src/industry.h
Show inline comments
 
@@ -56,24 +56,46 @@ enum IndustryControlFlags : byte {
 
};
 
DECLARE_ENUM_AS_BIT_SET(IndustryControlFlags);
 

	
 
static const int THIS_MONTH = 0;
 
static const int LAST_MONTH = 1;
 

	
 
/**
 
 * Defines the internal data of a functional industry.
 
 */
 
struct Industry : IndustryPool::PoolItem<&_industry_pool> {
 
	struct ProducedHistory {
 
		uint16_t production; ///< Total produced
 
		uint16_t transported; ///< Total transported
 

	
 
		uint8_t PctTransported() const
 
		{
 
			if (this->production == 0) return 0;
 
			return ClampTo<uint8_t>(this->transported * 256 / this->production);
 
		}
 
	};
 

	
 
	struct ProducedCargo {
 
		CargoID cargo; ///< Cargo type
 
		uint16_t waiting; ///< Amount of cargo produced
 
		uint8_t rate; ///< Production rate
 
		std::array<ProducedHistory, 2> history; ///< History of cargo produced and transported
 
	};
 

	
 
	struct AcceptedCargo {
 
		CargoID cargo; ///< Cargo type
 
		uint16_t waiting; ///< Amount of cargo waiting to processed
 
		TimerGameCalendar::Date last_accepted; ///< Last day cargo was accepted by this industry
 
	};
 

	
 
	using ProducedCargoArray = std::array<ProducedCargo, INDUSTRY_NUM_OUTPUTS>;
 
	using AcceptedCargoArray = std::array<AcceptedCargo, INDUSTRY_NUM_INPUTS>;
 

	
 
	TileArea location;                                     ///< Location of the industry
 
	Town *town;                                            ///< Nearest town
 
	Station *neutral_station;                              ///< Associated neutral station
 
	CargoID produced_cargo[INDUSTRY_NUM_OUTPUTS];          ///< 16 production cargo slots
 
	uint16 produced_cargo_waiting[INDUSTRY_NUM_OUTPUTS];   ///< amount of cargo produced per cargo
 
	uint16 incoming_cargo_waiting[INDUSTRY_NUM_INPUTS];    ///< incoming cargo waiting to be processed
 
	byte production_rate[INDUSTRY_NUM_OUTPUTS];            ///< production rate for each cargo
 
	ProducedCargoArray produced; ///< INDUSTRY_NUM_OUTPUTS production cargo slots
 
	AcceptedCargoArray accepted; ///< INDUSTRY_NUM_INPUTS input cargo slots
 
	byte prod_level;                                       ///< general production level
 
	CargoID accepts_cargo[INDUSTRY_NUM_INPUTS];            ///< 16 input cargo slots
 
	uint16 this_month_production[INDUSTRY_NUM_OUTPUTS];    ///< stats of this month's production per cargo
 
	uint16 this_month_transported[INDUSTRY_NUM_OUTPUTS];   ///< stats of this month's transport per cargo
 
	byte last_month_pct_transported[INDUSTRY_NUM_OUTPUTS]; ///< percentage transported per cargo in the last full month
 
	uint16 last_month_production[INDUSTRY_NUM_OUTPUTS];    ///< total units produced per cargo in the last full month
 
	uint16 last_month_transported[INDUSTRY_NUM_OUTPUTS];   ///< total units transported per cargo in the last full month
 
	uint16 counter;                                        ///< used for animation and/or production (if available cargo)
 

	
 
	IndustryType type;             ///< type of industry.
 
@@ -90,7 +112,6 @@ struct Industry : IndustryPool::PoolItem
 
	Owner founder;                 ///< Founder of the industry
 
	TimerGameCalendar::Date construction_date; ///< Date of the construction of the industry
 
	uint8 construction_type;       ///< Way the industry was constructed (@see IndustryConstructionType)
 
	TimerGameCalendar::Date last_cargo_accepted_at[INDUSTRY_NUM_INPUTS]; ///< Last day each cargo type was accepted by this industry
 
	byte selected_layout;          ///< Which tile layout was used when creating the industry
 
	Owner exclusive_supplier;      ///< Which company has exclusive rights to deliver cargo (INVALID_OWNER = anyone)
 
	Owner exclusive_consumer;      ///< Which company has exclusive rights to take cargo (INVALID_OWNER = anyone)
 
@@ -115,43 +136,39 @@ struct Industry : IndustryPool::PoolItem
 
		return IsTileType(tile, MP_INDUSTRY) && GetIndustryIndex(tile) == this->index;
 
	}
 

	
 
	inline int GetCargoProducedIndex(CargoID cargo) const
 
	inline ProducedCargoArray::iterator GetCargoProduced(CargoID cargo)
 
	{
 
		if (!IsValidCargoID(cargo)) return -1;
 
		const CargoID *pos = std::find(this->produced_cargo, endof(this->produced_cargo), cargo);
 
		if (pos == endof(this->produced_cargo)) return -1;
 
		return pos - this->produced_cargo;
 
		if (!IsValidCargoID(cargo)) return std::end(this->produced);
 
		return std::find_if(std::begin(this->produced), std::end(this->produced), [&cargo](const auto &p) { return p.cargo == cargo; });
 
	}
 

	
 
	inline int GetCargoAcceptedIndex(CargoID cargo) const
 
	inline AcceptedCargoArray::iterator GetCargoAccepted(CargoID cargo)
 
	{
 
		if (!IsValidCargoID(cargo)) return -1;
 
		const CargoID *pos = std::find(this->accepts_cargo, endof(this->accepts_cargo), cargo);
 
		if (pos == endof(this->accepts_cargo)) return -1;
 
		return pos - this->accepts_cargo;
 
		if (!IsValidCargoID(cargo)) return std::end(this->accepted);
 
		return std::find_if(std::begin(this->accepted), std::end(this->accepted), [&cargo](const auto &a) { return a.cargo == cargo; });
 
	}
 

	
 
	/** Test if this industry accepts any cargo.
 
	 * @return true iff the industry accepts any cargo.
 
	 */
 
	bool IsCargoAccepted() const { return std::any_of(std::begin(this->accepts_cargo), std::end(this->accepts_cargo), [](const auto &cargo) { return IsValidCargoID(cargo); }); }
 
	bool IsCargoAccepted() const { return std::any_of(std::begin(this->accepted), std::end(this->accepted), [](const auto &a) { return IsValidCargoID(a.cargo); }); }
 

	
 
	/** Test if this industry produces any cargo.
 
	 * @return true iff the industry produces any cargo.
 
	 */
 
	bool IsCargoProduced() const { return std::any_of(std::begin(this->produced_cargo), std::end(this->produced_cargo), [](const auto &cargo) { return IsValidCargoID(cargo); }); }
 
	bool IsCargoProduced() const { return std::any_of(std::begin(this->produced), std::end(this->produced), [](const auto &p) { return IsValidCargoID(p.cargo); }); }
 

	
 
	/** Test if this industry accepts a specific cargo.
 
	 * @param cargo Cargo type to test.
 
	 * @return true iff the industry accepts the given cargo type.
 
	 */
 
	bool IsCargoAccepted(CargoID cargo) const { return std::any_of(std::begin(this->accepts_cargo), std::end(this->accepts_cargo), [&cargo](const auto &cid) { return cid == cargo; }); }
 
	bool IsCargoAccepted(CargoID cargo) const { return std::any_of(std::begin(this->accepted), std::end(this->accepted), [&cargo](const auto &a) { return a.cargo == cargo; }); }
 

	
 
	/** Test if this industry produces a specific cargo.
 
	 * @param cargo Cargo type to test.
 
	 * @return true iff the industry produces the given cargo types.
 
	 */
 
	bool IsCargoProduced(CargoID cargo) const { return std::any_of(std::begin(this->produced_cargo), std::end(this->produced_cargo), [&cargo](const auto &cid) { return cid == cargo; }); }
 
	bool IsCargoProduced(CargoID cargo) const { return std::any_of(std::begin(this->produced), std::end(this->produced), [&cargo](const auto &p) { return p.cargo == cargo; }); }
 

	
 
	/**
 
	 * Get the industry of the given tile
src/industry_cmd.cpp
Show inline comments
 
@@ -420,13 +420,13 @@ static void AddAcceptedCargo_Industry(Ti
 

	
 
	if (itspec->special_flags & INDTILE_SPECIAL_ACCEPTS_ALL_CARGO) {
 
		/* Copy all accepted cargoes from industry itself */
 
		for (uint i = 0; i < lengthof(ind->accepts_cargo); i++) {
 
			CargoID *pos = std::find(accepts_cargo, endof(accepts_cargo), ind->accepts_cargo[i]);
 
		for (const auto &a : ind->accepted) {
 
			CargoID *pos = std::find(accepts_cargo, endof(accepts_cargo), a.cargo);
 
			if (pos == endof(accepts_cargo)) {
 
				/* Not found, insert */
 
				pos = std::find(accepts_cargo, endof(accepts_cargo), CT_INVALID);
 
				if (pos == endof(accepts_cargo)) continue; // nowhere to place, give up on this one
 
				*pos = ind->accepts_cargo[i];
 
				*pos = a.cargo;
 
			}
 
			cargo_acceptance[pos - accepts_cargo] += 8;
 
		}
 
@@ -524,18 +524,18 @@ static bool TransportIndustryGoods(TileI
 
	const IndustrySpec *indspec = GetIndustrySpec(i->type);
 
	bool moved_cargo = false;
 

	
 
	for (uint j = 0; j < lengthof(i->produced_cargo_waiting); j++) {
 
		uint cw = ClampTo<uint8_t>(i->produced_cargo_waiting[j]);
 
		if (cw > indspec->minimal_cargo && IsValidCargoID(i->produced_cargo[j])) {
 
			i->produced_cargo_waiting[j] -= cw;
 
	for (auto &p : i->produced) {
 
		uint cw = ClampTo<uint8_t>(p.waiting);
 
		if (cw > indspec->minimal_cargo && IsValidCargoID(p.cargo)) {
 
			p.waiting -= cw;
 

	
 
			/* fluctuating economy? */
 
			if (EconomyIsInRecession()) cw = (cw + 1) / 2;
 

	
 
			i->this_month_production[j] += cw;
 

	
 
			uint am = MoveGoodsToStation(i->produced_cargo[j], cw, SourceType::Industry, i->index, &i->stations_near, i->exclusive_consumer);
 
			i->this_month_transported[j] += am;
 
			p.history[THIS_MONTH].production += cw;
 

	
 
			uint am = MoveGoodsToStation(p.cargo, cw, SourceType::Industry, i->index, &i->stations_near, i->exclusive_consumer);
 
			p.history[THIS_MONTH].transported += am;
 

	
 
			moved_cargo |= (am != 0);
 
		}
 
@@ -981,12 +981,7 @@ bool IsTileForestIndustry(TileIndex tile
 
	if ((GetIndustrySpec(ind->type)->life_type & INDUSTRYLIFE_ORGANIC) == 0) return false;
 

	
 
	/* Check for wood production */
 
	for (uint i = 0; i < lengthof(ind->produced_cargo); i++) {
 
		/* The industry produces wood. */
 
		if (IsValidCargoID(ind->produced_cargo[i]) && CargoSpec::Get(ind->produced_cargo[i])->label == 'WOOD') return true;
 
	}
 

	
 
	return false;
 
	return std::any_of(std::begin(ind->produced), std::end(ind->produced), [](const auto &p) { return IsValidCargoID(p.cargo) && CargoSpec::Get(p.cargo)->label == 'WOOD'; });
 
}
 

	
 
static const byte _plantfarmfield_type[] = {1, 1, 1, 1, 1, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6};
 
@@ -1134,7 +1129,7 @@ static void ChopLumberMillTrees(Industry
 

	
 
	TileIndex tile = i->location.tile;
 
	if (CircularTileSearch(&tile, 40, SearchLumberMillTrees, nullptr)) { // 40x40 tiles  to search.
 
		i->produced_cargo_waiting[0] = ClampTo<uint16_t>(i->produced_cargo_waiting[0] + 45); // Found a tree, add according value to waiting cargo.
 
		i->produced[0].waiting = ClampTo<uint16_t>(i->produced[0].waiting + 45); // Found a tree, add according value to waiting cargo.
 
	}
 
}
 

	
 
@@ -1146,14 +1141,11 @@ static void ProduceIndustryGoods(Industr
 
	if ((i->counter & 0x3F) == 0) {
 
		uint32 r;
 
		if (Chance16R(1, 14, r) && indsp->number_of_sounds != 0 && _settings_client.sound.ambient) {
 
			for (size_t j = 0; j < lengthof(i->last_month_production); j++) {
 
				if (i->last_month_production[j] > 0) {
 
					/* Play sound since last month had production */
 
					SndPlayTileFx(
 
						(SoundFx)(indsp->random_sounds[((r >> 16) * indsp->number_of_sounds) >> 16]),
 
						i->location.tile);
 
					break;
 
				}
 
			if (std::any_of(std::begin(i->produced), std::end(i->produced), [](const auto &p) { return p.history[LAST_MONTH].production > 0; })) {
 
				/* Play sound since last month had production */
 
				SndPlayTileFx(
 
					(SoundFx)(indsp->random_sounds[((r >> 16) * indsp->number_of_sounds) >> 16]),
 
					i->location.tile);
 
			}
 
		}
 
	}
 
@@ -1165,8 +1157,8 @@ static void ProduceIndustryGoods(Industr
 
		if (HasBit(indsp->callback_mask, CBM_IND_PRODUCTION_256_TICKS)) IndustryProductionCallback(i, 1);
 

	
 
		IndustryBehaviour indbehav = indsp->behaviour;
 
		for (size_t j = 0; j < lengthof(i->produced_cargo_waiting); j++) {
 
			i->produced_cargo_waiting[j] = ClampTo<uint16_t>(i->produced_cargo_waiting[j] + i->production_rate[j]);
 
		for (auto &p : i->produced) {
 
			p.waiting = ClampTo<uint16_t>(p.waiting + p.rate);
 
		}
 

	
 
		if ((indbehav & INDUSTRYBEH_PLANT_FIELDS) != 0) {
 
@@ -1762,22 +1754,21 @@ static void DoCreateNewIndustry(Industry
 
	i->type = type;
 
	Industry::IncIndustryTypeCount(type);
 

	
 
	MemCpyT(i->produced_cargo,  indspec->produced_cargo,  lengthof(i->produced_cargo));
 
	MemCpyT(i->production_rate, indspec->production_rate, lengthof(i->production_rate));
 
	MemCpyT(i->accepts_cargo,   indspec->accepts_cargo,   lengthof(i->accepts_cargo));
 

	
 
	MemSetT(i->produced_cargo_waiting,     0, lengthof(i->produced_cargo_waiting));
 
	MemSetT(i->this_month_production,      0, lengthof(i->this_month_production));
 
	MemSetT(i->this_month_transported,     0, lengthof(i->this_month_transported));
 
	MemSetT(i->last_month_pct_transported, 0, lengthof(i->last_month_pct_transported));
 
	MemSetT(i->last_month_transported,     0, lengthof(i->last_month_transported));
 
	MemSetT(i->incoming_cargo_waiting,     0, lengthof(i->incoming_cargo_waiting));
 
	MemSetT(i->last_cargo_accepted_at,     0, lengthof(i->last_cargo_accepted_at));
 
	for (auto it = std::begin(i->produced); it != std::end(i->produced); ++it) {
 
		size_t index = it - std::begin(i->produced);
 
		it->cargo = indspec->produced_cargo[index];
 
		it->rate = indspec->production_rate[index];
 
	}
 

	
 
	for (auto it = std::begin(i->accepted); it != std::end(i->accepted); ++it) {
 
		size_t index = it - std::begin(i->accepted);
 
		it->cargo = indspec->accepts_cargo[index];
 
	}
 

	
 
	/* Randomize inital production if non-original economy is used and there are no production related callbacks. */
 
	if (!indspec->UsesOriginalEconomy()) {
 
		for (size_t ci = 0; ci < lengthof(i->production_rate); ci++) {
 
			i->production_rate[ci] = ClampTo<byte>((RandomRange(256) + 128) * i->production_rate[ci] >> 8);
 
		for (auto &p : i->produced) {
 
			p.rate = ClampTo<byte>((RandomRange(256) + 128) * p.rate >> 8);
 
		}
 
	}
 

	
 
@@ -1824,14 +1815,14 @@ static void DoCreateNewIndustry(Industry
 
	if (_generating_world) {
 
		if (HasBit(indspec->callback_mask, CBM_IND_PRODUCTION_256_TICKS)) {
 
			IndustryProductionCallback(i, 1);
 
			for (size_t ci = 0; ci < lengthof(i->last_month_production); ci++) {
 
				i->last_month_production[ci] = i->produced_cargo_waiting[ci] * 8;
 
				i->produced_cargo_waiting[ci] = 0;
 
			for (auto &p : i->produced) {
 
				p.history[LAST_MONTH].production = p.waiting * 8;
 
				p.waiting = 0;
 
			}
 
		}
 

	
 
		for (size_t ci = 0; ci < lengthof(i->last_month_production); ci++) {
 
			i->last_month_production[ci] += i->production_rate[ci] * 8;
 
		for (auto &p : i->produced) {
 
			p.history[LAST_MONTH].production += p.rate * 8;
 
		}
 
	}
 

	
 
@@ -1845,9 +1836,9 @@ static void DoCreateNewIndustry(Industry
 

	
 
	if (HasBit(indspec->callback_mask, CBM_IND_INPUT_CARGO_TYPES)) {
 
		/* Clear all input cargo types */
 
		for (uint j = 0; j < lengthof(i->accepts_cargo); j++) i->accepts_cargo[j] = CT_INVALID;
 
		for (auto &a : i->accepted) a.cargo = CT_INVALID;
 
		/* Query actual types */
 
		uint maxcargoes = (indspec->behaviour & INDUSTRYBEH_CARGOTYPES_UNLIMITED) ? lengthof(i->accepts_cargo) : 3;
 
		uint maxcargoes = (indspec->behaviour & INDUSTRYBEH_CARGOTYPES_UNLIMITED) ? static_cast<uint>(i->accepted.size()) : 3;
 
		for (uint j = 0; j < maxcargoes; j++) {
 
			uint16 res = GetIndustryCallback(CBID_INDUSTRY_INPUT_CARGO_TYPES, j, 0, i, type, INVALID_TILE);
 
			if (res == CALLBACK_FAILED || GB(res, 0, 8) == CT_INVALID) break;
 
@@ -1866,20 +1857,20 @@ static void DoCreateNewIndustry(Industry
 
				ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_INPUT_CARGO_TYPES, res);
 
				break;
 
			}
 
			if (std::find(i->accepts_cargo, i->accepts_cargo + j, cargo) != i->accepts_cargo + j) {
 
			if (std::any_of(std::begin(i->accepted), std::begin(i->accepted) + j, [&cargo](const auto &a) { return a.cargo == cargo; })) {
 
				/* Duplicate cargo */
 
				ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_INPUT_CARGO_TYPES, res);
 
				break;
 
			}
 
			i->accepts_cargo[j] = cargo;
 
			i->accepted[j].cargo = cargo;
 
		}
 
	}
 

	
 
	if (HasBit(indspec->callback_mask, CBM_IND_OUTPUT_CARGO_TYPES)) {
 
		/* Clear all output cargo types */
 
		for (uint j = 0; j < lengthof(i->produced_cargo); j++) i->produced_cargo[j] = CT_INVALID;
 
		for (auto &p : i->produced) p.cargo = CT_INVALID;
 
		/* Query actual types */
 
		uint maxcargoes = (indspec->behaviour & INDUSTRYBEH_CARGOTYPES_UNLIMITED) ? lengthof(i->produced_cargo) : 2;
 
		uint maxcargoes = (indspec->behaviour & INDUSTRYBEH_CARGOTYPES_UNLIMITED) ? static_cast<uint>(i->produced.size()) : 2;
 
		for (uint j = 0; j < maxcargoes; j++) {
 
			uint16 res = GetIndustryCallback(CBID_INDUSTRY_OUTPUT_CARGO_TYPES, j, 0, i, type, INVALID_TILE);
 
			if (res == CALLBACK_FAILED || GB(res, 0, 8) == CT_INVALID) break;
 
@@ -1896,12 +1887,12 @@ static void DoCreateNewIndustry(Industry
 
				ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_OUTPUT_CARGO_TYPES, res);
 
				break;
 
			}
 
			if (std::find(i->produced_cargo, i->produced_cargo + j, cargo) != i->produced_cargo + j) {
 
			if (std::any_of(std::begin(i->produced), std::begin(i->produced) + j, [&cargo](const auto &p) { return p.cargo == cargo; })) {
 
				/* Duplicate cargo */
 
				ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_OUTPUT_CARGO_TYPES, res);
 
				break;
 
			}
 
			i->produced_cargo[j] = cargo;
 
			i->produced[j].cargo = cargo;
 
		}
 
	}
 

	
 
@@ -2411,20 +2402,14 @@ void GenerateIndustries()
 
 */
 
static void UpdateIndustryStatistics(Industry *i)
 
{
 
	for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
 
		if (IsValidCargoID(i->produced_cargo[j])) {
 
			byte pct = 0;
 
			if (i->this_month_production[j] != 0) {
 
				i->last_prod_year = TimerGameCalendar::year;
 
				pct = ClampTo<byte>(i->this_month_transported[j] * 256 / i->this_month_production[j]);
 
			}
 
			i->last_month_pct_transported[j] = pct;
 

	
 
			i->last_month_production[j] = i->this_month_production[j];
 
			i->this_month_production[j] = 0;
 

	
 
			i->last_month_transported[j] = i->this_month_transported[j];
 
			i->this_month_transported[j] = 0;
 
	for (auto &p : i->produced) {
 
		if (IsValidCargoID(p.cargo)) {
 
			if (p.history[THIS_MONTH].production != 0) i->last_prod_year = TimerGameCalendar::year;
 

	
 
			/* Move history from this month to last month. */
 
			std::rotate(std::rbegin(p.history), std::rbegin(p.history) + 1, std::rend(p.history));
 
			p.history[THIS_MONTH].production = 0;
 
			p.history[THIS_MONTH].transported = 0;
 
		}
 
	}
 
}
 
@@ -2439,8 +2424,8 @@ void Industry::RecomputeProductionMultip
 
	assert(indspec->UsesOriginalEconomy());
 

	
 
	/* Rates are rounded up, so e.g. oilrig always produces some passengers */
 
	for (size_t i = 0; i < lengthof(this->production_rate); i++) {
 
		this->production_rate[i] = ClampTo<byte>(CeilDiv(indspec->production_rate[i] * this->prod_level, PRODLEVEL_DEFAULT));
 
	for (auto &p : this->produced) {
 
		p.rate = ClampTo<uint8_t>(CeilDiv(indspec->production_rate[&p - this->produced.data()] * this->prod_level, PRODLEVEL_DEFAULT));
 
	}
 
}
 

	
 
@@ -2773,7 +2758,7 @@ static void ChangeIndustryProduction(Ind
 
		if (original_economy) {
 
			if (only_decrease || Chance16(1, 3)) {
 
				/* If more than 60% transported, 66% chance of increase, else 33% chance of increase */
 
				if (!only_decrease && (i->last_month_pct_transported[0] > PERCENT_TRANSPORTED_60) != Chance16(1, 3)) {
 
				if (!only_decrease && (i->produced[0].history[LAST_MONTH].PctTransported() > PERCENT_TRANSPORTED_60) != Chance16(1, 3)) {
 
					mul = 1; // Increase production
 
				} else {
 
					div = 1; // Decrease production
 
@@ -2781,14 +2766,14 @@ static void ChangeIndustryProduction(Ind
 
			}
 
		} else if (_settings_game.economy.type == ET_SMOOTH) {
 
			closeit = !(i->ctlflags & (INDCTL_NO_CLOSURE | INDCTL_NO_PRODUCTION_DECREASE));
 
			for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
 
				if (!IsValidCargoID(i->produced_cargo[j])) continue;
 
			for (auto &p : i->produced) {
 
				if (!IsValidCargoID(p.cargo)) continue;
 
				uint32 r = Random();
 
				int old_prod, new_prod, percent;
 
				/* If over 60% is transported, mult is 1, else mult is -1. */
 
				int mult = (i->last_month_pct_transported[j] > PERCENT_TRANSPORTED_60) ? 1 : -1;
 

	
 
				new_prod = old_prod = i->production_rate[j];
 
				int mult = (p.history[LAST_MONTH].PctTransported() > PERCENT_TRANSPORTED_60) ? 1 : -1;
 

	
 
				new_prod = old_prod = p.rate;
 

	
 
				/* For industries with only_decrease flags (temperate terrain Oil Wells),
 
				 * the multiplier will always be -1 so they will only decrease. */
 
@@ -2796,7 +2781,7 @@ static void ChangeIndustryProduction(Ind
 
					mult = -1;
 
				/* For normal industries, if over 60% is transported, 33% chance for decrease.
 
				 * Bonus for very high station ratings (over 80%): 16% chance for decrease. */
 
				} else if (Chance16I(1, ((i->last_month_pct_transported[j] > PERCENT_TRANSPORTED_80) ? 6 : 3), r)) {
 
				} else if (Chance16I(1, ((p.history[LAST_MONTH].PctTransported() > PERCENT_TRANSPORTED_80) ? 6 : 3), r)) {
 
					mult *= -1;
 
				}
 

	
 
@@ -2808,7 +2793,7 @@ static void ChangeIndustryProduction(Ind
 

	
 
				/* Prevent production to overflow or Oil Rig passengers to be over-"produced" */
 
				new_prod = Clamp(new_prod, 1, 255);
 
				if (i->produced_cargo[j] == CT_PASSENGERS && !(indspec->behaviour & INDUSTRYBEH_NO_PAX_PROD_CLAMP)) {
 
				if (p.cargo == CT_PASSENGERS && !(indspec->behaviour & INDUSTRYBEH_NO_PAX_PROD_CLAMP)) {
 
					new_prod = Clamp(new_prod, 0, 16);
 
				}
 

	
 
@@ -2823,13 +2808,13 @@ static void ChangeIndustryProduction(Ind
 
				}
 

	
 
				percent = (old_prod == 0) ? 100 : (new_prod * 100 / old_prod - 100);
 
				i->production_rate[j] = new_prod;
 
				p.rate = new_prod;
 

	
 
				/* Close the industry when it has the lowest possible production rate */
 
				if (new_prod > 1) closeit = false;
 

	
 
				if (abs(percent) >= 10) {
 
					ReportNewsProductionChangeIndustry(i, i->produced_cargo[j], percent);
 
					ReportNewsProductionChangeIndustry(i, p.cargo, percent);
 
				}
 
			}
 
		}
src/industry_gui.cpp
Show inline comments
 
@@ -189,6 +189,33 @@ static inline void GetAllCargoSuffixes(C
 
	}
 
}
 

	
 
/**
 
 * Gets the strings to display after the cargo of industries (using callback 37)
 
 * @param use_input get suffixes for output cargo or input cargo?
 
 * @param cst the cargo suffix type (for which window is it requested). @see CargoSuffixType
 
 * @param ind the industry (nullptr if in fund window)
 
 * @param ind_type the industry type
 
 * @param indspec the industry spec
 
 * @param cargo cargotype. for CT_INVALID no suffix will be determined
 
 * @param slot accepts/produced slot number, used for old-style 3-in/2-out industries.
 
 * @param suffix is filled with the suffix
 
 */
 
void GetCargoSuffix(CargoSuffixInOut use_input, CargoSuffixType cst, const Industry *ind, IndustryType ind_type, const IndustrySpec *indspec, CargoID cargo, uint8_t slot, CargoSuffix &suffix)
 
{
 
	suffix.text[0] = '\0';
 
	suffix.display = CSD_CARGO;
 
	if (!IsValidCargoID(cargo)) return;
 
	if (indspec->behaviour & INDUSTRYBEH_CARGOTYPES_UNLIMITED) {
 
		byte local_id = indspec->grf_prop.grffile->cargo_map[cargo]; // should we check the value for valid?
 
		uint cargotype = local_id << 16 | use_input;
 
		GetCargoSuffix(cargotype, cst, ind, ind_type, indspec, suffix);
 
	} else if (use_input == CARGOSUFFIX_IN) {
 
		if (slot < 3) GetCargoSuffix(slot, cst, ind, ind_type, indspec, suffix);
 
	} else if (use_input == CARGOSUFFIX_OUT) {
 
		if (slot < 2) GetCargoSuffix(slot + 3, cst, ind, ind_type, indspec, suffix);
 
	}
 
}
 

	
 
std::array<IndustryType, NUM_INDUSTRYTYPES> _sorted_industry_types; ///< Industry types sorted by name.
 

	
 
/** Sort industry types by their name. */
 
@@ -840,33 +867,35 @@ public:
 
			ir.top += FONT_HEIGHT_NORMAL + WidgetDimensions::scaled.vsep_wide;
 
		}
 

	
 
		CargoSuffix cargo_suffix[lengthof(i->accepts_cargo)];
 
		GetAllCargoSuffixes(CARGOSUFFIX_IN, CST_VIEW, i, i->type, ind, i->accepts_cargo, cargo_suffix);
 
		bool stockpiling = HasBit(ind->callback_mask, CBM_IND_PRODUCTION_CARGO_ARRIVAL) || HasBit(ind->callback_mask, CBM_IND_PRODUCTION_256_TICKS);
 

	
 
		for (byte j = 0; j < lengthof(i->accepts_cargo); j++) {
 
			if (!IsValidCargoID(i->accepts_cargo[j])) continue;
 
		for (const auto &a : i->accepted) {
 
			if (!IsValidCargoID(a.cargo)) continue;
 
			has_accept = true;
 
			if (first) {
 
				DrawString(ir, STR_INDUSTRY_VIEW_REQUIRES);
 
				ir.top += FONT_HEIGHT_NORMAL;
 
				first = false;
 
			}
 
			SetDParam(0, CargoSpec::Get(i->accepts_cargo[j])->name);
 
			SetDParam(1, i->accepts_cargo[j]);
 
			SetDParam(2, i->incoming_cargo_waiting[j]);
 

	
 
			CargoSuffix suffix;
 
			GetCargoSuffix(CARGOSUFFIX_IN, CST_VIEW, i, i->type, ind, a.cargo, &a - i->accepted.data(), suffix);
 

	
 
			SetDParam(0, CargoSpec::Get(a.cargo)->name);
 
			SetDParam(1, a.cargo);
 
			SetDParam(2, a.waiting);
 
			SetDParamStr(3, "");
 
			StringID str = STR_NULL;
 
			switch (cargo_suffix[j].display) {
 
			switch (suffix.display) {
 
				case CSD_CARGO_AMOUNT_TEXT:
 
					SetDParamStr(3, cargo_suffix[j].text);
 
					SetDParamStr(3, suffix.text);
 
					FALLTHROUGH;
 
				case CSD_CARGO_AMOUNT:
 
					str = stockpiling ? STR_INDUSTRY_VIEW_ACCEPT_CARGO_AMOUNT : STR_INDUSTRY_VIEW_ACCEPT_CARGO;
 
					break;
 

	
 
				case CSD_CARGO_TEXT:
 
					SetDParamStr(3, cargo_suffix[j].text);
 
					SetDParamStr(3, suffix.text);
 
					FALLTHROUGH;
 
				case CSD_CARGO:
 
					str = STR_INDUSTRY_VIEW_ACCEPT_CARGO;
 
@@ -879,13 +908,12 @@ public:
 
			ir.top += FONT_HEIGHT_NORMAL;
 
		}
 

	
 
		GetAllCargoSuffixes(CARGOSUFFIX_OUT, CST_VIEW, i, i->type, ind, i->produced_cargo, cargo_suffix);
 
		int line_height = this->editable == EA_RATE ? this->cheat_line_height : FONT_HEIGHT_NORMAL;
 
		int text_y_offset = (line_height - FONT_HEIGHT_NORMAL) / 2;
 
		int button_y_offset = (line_height - SETTING_BUTTON_HEIGHT) / 2;
 
		first = true;
 
		for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
 
			if (!IsValidCargoID(i->produced_cargo[j])) continue;
 
		for (const auto &p : i->produced) {
 
			if (!IsValidCargoID(p.cargo)) continue;
 
			if (first) {
 
				if (has_accept) ir.top += WidgetDimensions::scaled.vsep_wide;
 
				DrawString(ir, STR_INDUSTRY_VIEW_PRODUCTION_LAST_MONTH_TITLE);
 
@@ -894,15 +922,18 @@ public:
 
				first = false;
 
			}
 

	
 
			SetDParam(0, i->produced_cargo[j]);
 
			SetDParam(1, i->last_month_production[j]);
 
			SetDParamStr(2, cargo_suffix[j].text);
 
			SetDParam(3, ToPercent8(i->last_month_pct_transported[j]));
 
			CargoSuffix suffix;
 
			GetCargoSuffix(CARGOSUFFIX_OUT, CST_VIEW, i, i->type, ind, p.cargo, &p - i->produced.data(), suffix);
 

	
 
			SetDParam(0, p.cargo);
 
			SetDParam(1, p.history[LAST_MONTH].production);
 
			SetDParamStr(2, suffix.text);
 
			SetDParam(3, ToPercent8(p.history[LAST_MONTH].PctTransported()));
 
			DrawString(ir.Indent(WidgetDimensions::scaled.hsep_indent + (this->editable == EA_RATE ? SETTING_BUTTON_WIDTH + WidgetDimensions::scaled.hsep_normal : 0), rtl).Translate(0, text_y_offset), STR_INDUSTRY_VIEW_TRANSPORTED);
 
			/* Let's put out those buttons.. */
 
			if (this->editable == EA_RATE) {
 
				DrawArrowButtons(ir.Indent(WidgetDimensions::scaled.hsep_indent, rtl).WithWidth(SETTING_BUTTON_WIDTH, rtl).left, ir.top + button_y_offset, COLOUR_YELLOW, (this->clicked_line == IL_RATE1 + j) ? this->clicked_button : 0,
 
						i->production_rate[j] > 0, i->production_rate[j] < 255);
 
				DrawArrowButtons(ir.Indent(WidgetDimensions::scaled.hsep_indent, rtl).WithWidth(SETTING_BUTTON_WIDTH, rtl).left, ir.top + button_y_offset, COLOUR_YELLOW, (this->clicked_line == IL_RATE1 + (&p - i->produced.data())) ? this->clicked_button : 0,
 
						p.rate > 0, p.rate < 255);
 
			}
 
			ir.top += line_height;
 
		}
 
@@ -980,11 +1011,11 @@ public:
 
					case EA_RATE:
 
						if (pt.y >= this->production_offset_y) {
 
							int row = (pt.y - this->production_offset_y) / this->cheat_line_height;
 
							for (uint j = 0; j < lengthof(i->produced_cargo); j++) {
 
								if (!IsValidCargoID(i->produced_cargo[j])) continue;
 
							for (auto itp = std::begin(i->produced); itp != std::end(i->produced); ++itp) {
 
								if (!IsValidCargoID(itp->cargo)) continue;
 
								row--;
 
								if (row < 0) {
 
									line = (InfoLine)(IL_RATE1 + j);
 
									line = (InfoLine)(IL_RATE1 + (itp - std::begin(i->produced)));
 
									break;
 
								}
 
							}
 
@@ -1012,13 +1043,13 @@ public:
 

	
 
						case EA_RATE:
 
							if (decrease) {
 
								if (i->production_rate[line - IL_RATE1] <= 0) return;
 
								i->production_rate[line - IL_RATE1] = std::max(i->production_rate[line - IL_RATE1] / 2, 0);
 
								if (i->produced[line - IL_RATE1].rate <= 0) return;
 
								i->produced[line - IL_RATE1].rate = std::max(i->produced[line - IL_RATE1].rate / 2, 0);
 
							} else {
 
								if (i->production_rate[line - IL_RATE1] >= 255) return;
 
								if (i->produced[line - IL_RATE1].rate >= 255) return;
 
								/* a zero production industry is unlikely to give anything but zero, so push it a little bit */
 
								int new_prod = i->production_rate[line - IL_RATE1] == 0 ? 1 : i->production_rate[line - IL_RATE1] * 2;
 
								i->production_rate[line - IL_RATE1] = ClampTo<byte>(new_prod);
 
								int new_prod = i->produced[line - IL_RATE1].rate == 0 ? 1 : i->produced[line - IL_RATE1].rate * 2;
 
								i->produced[line - IL_RATE1].rate = ClampTo<byte>(new_prod);
 
							}
 
							break;
 

	
 
@@ -1040,7 +1071,7 @@ public:
 
							break;
 

	
 
						case EA_RATE:
 
							SetDParam(0, i->production_rate[line - IL_RATE1] * 8);
 
							SetDParam(0, i->produced[line - IL_RATE1].rate * 8);
 
							ShowQueryString(STR_JUST_INT, STR_CONFIG_GAME_PRODUCTION, 10, this, CS_ALPHANUMERAL, QSF_NONE);
 
							break;
 

	
 
@@ -1099,7 +1130,7 @@ public:
 
				break;
 

	
 
			default:
 
				i->production_rate[this->editbox_line - IL_RATE1] = ClampU(RoundDivSU(value, 8), 0, 255);
 
				i->produced[this->editbox_line - IL_RATE1].rate = ClampU(RoundDivSU(value, 8), 0, 255);
 
				break;
 
		}
 
		UpdateIndustryProduction(i);
 
@@ -1139,9 +1170,9 @@ static void UpdateIndustryProduction(Ind
 
	const IndustrySpec *indspec = GetIndustrySpec(i->type);
 
	if (indspec->UsesOriginalEconomy()) i->RecomputeProductionMultipliers();
 

	
 
	for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
 
		if (IsValidCargoID(i->produced_cargo[j])) {
 
			i->last_month_production[j] = 8 * i->production_rate[j];
 
	for (auto &p : i->produced) {
 
		if (IsValidCargoID(p.cargo)) {
 
			p.history[LAST_MONTH].production = 8 * p.rate;
 
		}
 
	}
 
}
 
@@ -1415,12 +1446,10 @@ protected:
 
	 * @param id cargo slot
 
	 * @return percents of cargo transported, or -1 if industry doesn't use this cargo slot
 
	 */
 
	static inline int GetCargoTransportedPercentsIfValid(const Industry *i, uint id)
 
	static inline int GetCargoTransportedPercentsIfValid(const Industry::ProducedCargo &p)
 
	{
 
		assert(id < lengthof(i->produced_cargo));
 

	
 
		if (!IsValidCargoID(i->produced_cargo[id])) return -1;
 
		return ToPercent8(i->last_month_pct_transported[id]);
 
		if (!IsValidCargoID(p.cargo)) return -1;
 
		return ToPercent8(p.history[LAST_MONTH].PctTransported());
 
	}
 

	
 
	/**
 
@@ -1436,18 +1465,18 @@ protected:
 
		if (filter == CF_NONE) return 0;
 

	
 
		int percentage = 0, produced_cargo_count = 0;
 
		for (uint id = 0; id < lengthof(i->produced_cargo); id++) {
 
		for (const auto &p : i->produced) {
 
			if (filter == CF_ANY) {
 
				int transported = GetCargoTransportedPercentsIfValid(i, id);
 
				int transported = GetCargoTransportedPercentsIfValid(p);
 
				if (transported != -1) {
 
					produced_cargo_count++;
 
					percentage += transported;
 
				}
 
				if (produced_cargo_count == 0 && id == lengthof(i->produced_cargo) - 1 && percentage == 0) {
 
				if (produced_cargo_count == 0 && &p == &i->produced.back() && percentage == 0) {
 
					return transported;
 
				}
 
			} else if (filter == i->produced_cargo[id]) {
 
				return GetCargoTransportedPercentsIfValid(i, id);
 
			} else if (filter == p.cargo) {
 
				return GetCargoTransportedPercentsIfValid(p);
 
			}
 
		}
 

	
 
@@ -1481,13 +1510,13 @@ protected:
 
		if (filter == CF_NONE) return IndustryTypeSorter(a, b);
 

	
 
		uint prod_a = 0, prod_b = 0;
 
		for (uint i = 0; i < lengthof(a->produced_cargo); i++) {
 
		for (auto ita = std::begin(a->produced), itb = std::begin(b->produced); ita != std::end(a->produced) && itb != std::end(b->produced); ++ita, ++itb) {
 
			if (filter == CF_ANY) {
 
				if (IsValidCargoID(a->produced_cargo[i])) prod_a += a->last_month_production[i];
 
				if (IsValidCargoID(b->produced_cargo[i])) prod_b += b->last_month_production[i];
 
				if (IsValidCargoID(ita->cargo)) prod_a += ita->history[LAST_MONTH].production;
 
				if (IsValidCargoID(itb->cargo)) prod_b += ita->history[LAST_MONTH].production;
 
			} else {
 
				if (a->produced_cargo[i] == filter) prod_a += a->last_month_production[i];
 
				if (b->produced_cargo[i] == filter) prod_b += b->last_month_production[i];
 
				if (ita->cargo == filter) prod_a += ita->history[LAST_MONTH].production;
 
				if (itb->cargo == filter) prod_b += itb->history[LAST_MONTH].production;
 
			}
 
		}
 
		int r = prod_a - prod_b;
 
@@ -1515,8 +1544,7 @@ protected:
 
		/* Industry name */
 
		SetDParam(p++, i->index);
 

	
 
		static CargoSuffix cargo_suffix[lengthof(i->produced_cargo)];
 
		GetAllCargoSuffixes(CARGOSUFFIX_OUT, CST_DIR, i, i->type, indsp, i->produced_cargo, cargo_suffix);
 
		static CargoSuffix cargo_suffix[INDUSTRY_NUM_OUTPUTS];
 

	
 
		/* Get industry productions (CargoID, production, suffix, transported) */
 
		struct CargoInfo {
 
@@ -1527,9 +1555,10 @@ protected:
 
		};
 
		std::vector<CargoInfo> cargos;
 

	
 
		for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
 
			if (!IsValidCargoID(i->produced_cargo[j])) continue;
 
			cargos.push_back({ i->produced_cargo[j], i->last_month_production[j], cargo_suffix[j].text.c_str(), ToPercent8(i->last_month_pct_transported[j]) });
 
		for (auto itp = std::begin(i->produced); itp != std::end(i->produced); ++itp) {
 
			if (!IsValidCargoID(itp->cargo)) continue;
 
			GetCargoSuffix(CARGOSUFFIX_OUT, CST_DIR, i, i->type, indsp, itp->cargo, itp - std::begin(i->produced), cargo_suffix[itp - std::begin(i->produced)]);
 
			cargos.push_back({ itp->cargo, itp->history[LAST_MONTH].production, cargo_suffix[itp - std::begin(i->produced)].text.c_str(), ToPercent8(itp->history[LAST_MONTH].PctTransported()) });
 
		}
 

	
 
		switch (static_cast<IndustryDirectoryWindow::SorterType>(this->industries.SortType())) {
src/newgrf_industries.cpp
Show inline comments
 
@@ -214,9 +214,9 @@ static uint32 GetCountAndDistanceOfClose
 
			if (HasBit(callback, CBM_IND_PRODUCTION_CARGO_ARRIVAL) || HasBit(callback, CBM_IND_PRODUCTION_256_TICKS)) {
 
				if ((indspec->behaviour & INDUSTRYBEH_PROD_MULTI_HNDLING) != 0) {
 
					if (this->industry->prod_level == 0) return 0;
 
					return ClampTo<uint16>(this->industry->incoming_cargo_waiting[variable - 0x40] / this->industry->prod_level);
 
					return ClampTo<uint16>(this->industry->accepted[variable - 0x40].waiting / this->industry->prod_level);
 
				} else {
 
					return ClampTo<uint16>(this->industry->incoming_cargo_waiting[variable - 0x40]);
 
					return ClampTo<uint16>(this->industry->accepted[variable - 0x40].waiting);
 
				}
 
			} else {
 
				return 0;
 
@@ -317,16 +317,16 @@ static uint32 GetCountAndDistanceOfClose
 
		case 0x71: {
 
			CargoID cargo = GetCargoTranslation(parameter, this->ro.grffile);
 
			if (!IsValidCargoID(cargo)) return 0;
 
			int index = this->industry->GetCargoProducedIndex(cargo);
 
			if (index < 0) return 0; // invalid cargo
 
			auto it = this->industry->GetCargoProduced(cargo);
 
			if (it == std::end(this->industry->produced)) return 0; // invalid cargo
 
			switch (variable) {
 
				case 0x69: return this->industry->produced_cargo_waiting[index];
 
				case 0x6A: return this->industry->this_month_production[index];
 
				case 0x6B: return this->industry->this_month_transported[index];
 
				case 0x6C: return this->industry->last_month_production[index];
 
				case 0x6D: return this->industry->last_month_transported[index];
 
				case 0x70: return this->industry->production_rate[index];
 
				case 0x71: return this->industry->last_month_pct_transported[index];
 
				case 0x69: return it->waiting;
 
				case 0x6A: return it->history[THIS_MONTH].production;
 
				case 0x6B: return it->history[THIS_MONTH].transported;
 
				case 0x6C: return it->history[LAST_MONTH].production;
 
				case 0x6D: return it->history[LAST_MONTH].transported;
 
				case 0x70: return it->rate;
 
				case 0x71: return it->history[LAST_MONTH].PctTransported();
 
				default: NOT_REACHED();
 
			}
 
		}
 
@@ -336,10 +336,10 @@ static uint32 GetCountAndDistanceOfClose
 
		case 0x6F: {
 
			CargoID cargo = GetCargoTranslation(parameter, this->ro.grffile);
 
			if (!IsValidCargoID(cargo)) return 0;
 
			int index = this->industry->GetCargoAcceptedIndex(cargo);
 
			if (index < 0) return 0; // invalid cargo
 
			if (variable == 0x6E) return this->industry->last_cargo_accepted_at[index];
 
			if (variable == 0x6F) return this->industry->incoming_cargo_waiting[index];
 
			auto it = this->industry->GetCargoAccepted(cargo);
 
			if (it == std::end(this->industry->accepted)) return 0; // invalid cargo
 
			if (variable == 0x6E) return it->last_accepted;
 
			if (variable == 0x6F) return it->waiting;
 
			NOT_REACHED();
 
		}
 

	
 
@@ -358,40 +358,40 @@ static uint32 GetCountAndDistanceOfClose
 
		case 0x87: return this->industry->location.h;// xy dimensions
 

	
 
		case 0x88:
 
		case 0x89: return this->industry->produced_cargo[variable - 0x88];
 
		case 0x8A: return this->industry->produced_cargo_waiting[0];
 
		case 0x8B: return GB(this->industry->produced_cargo_waiting[0], 8, 8);
 
		case 0x8C: return this->industry->produced_cargo_waiting[1];
 
		case 0x8D: return GB(this->industry->produced_cargo_waiting[1], 8, 8);
 
		case 0x89: return this->industry->produced[variable - 0x88].cargo;
 
		case 0x8A: return this->industry->produced[0].waiting;
 
		case 0x8B: return GB(this->industry->produced[0].waiting, 8, 8);
 
		case 0x8C: return this->industry->produced[1].waiting;
 
		case 0x8D: return GB(this->industry->produced[1].waiting, 8, 8);
 
		case 0x8E:
 
		case 0x8F: return this->industry->production_rate[variable - 0x8E];
 
		case 0x8F: return this->industry->produced[variable - 0x8E].rate;
 
		case 0x90:
 
		case 0x91:
 
		case 0x92: return this->industry->accepts_cargo[variable - 0x90];
 
		case 0x92: return this->industry->accepted[variable - 0x90].cargo;
 
		case 0x93: return this->industry->prod_level;
 
		/* amount of cargo produced so far THIS month. */
 
		case 0x94: return this->industry->this_month_production[0];
 
		case 0x95: return GB(this->industry->this_month_production[0], 8, 8);
 
		case 0x96: return this->industry->this_month_production[1];
 
		case 0x97: return GB(this->industry->this_month_production[1], 8, 8);
 
		case 0x94: return this->industry->produced[0].history[THIS_MONTH].production;
 
		case 0x95: return GB(this->industry->produced[0].history[THIS_MONTH].production, 8, 8);
 
		case 0x96: return this->industry->produced[1].history[THIS_MONTH].production;
 
		case 0x97: return GB(this->industry->produced[1].history[THIS_MONTH].production, 8, 8);
 
		/* amount of cargo transported so far THIS month. */
 
		case 0x98: return this->industry->this_month_transported[0];
 
		case 0x99: return GB(this->industry->this_month_transported[0], 8, 8);
 
		case 0x9A: return this->industry->this_month_transported[1];
 
		case 0x9B: return GB(this->industry->this_month_transported[1], 8, 8);
 
		case 0x98: return this->industry->produced[0].history[THIS_MONTH].transported;
 
		case 0x99: return GB(this->industry->produced[0].history[THIS_MONTH].transported, 8, 8);
 
		case 0x9A: return this->industry->produced[1].history[THIS_MONTH].transported;
 
		case 0x9B: return GB(this->industry->produced[1].history[THIS_MONTH].transported, 8, 8);
 
		/* fraction of cargo transported LAST month. */
 
		case 0x9C:
 
		case 0x9D: return this->industry->last_month_pct_transported[variable - 0x9C];
 
		case 0x9D: return this->industry->produced[variable - 0x9C].history[LAST_MONTH].PctTransported();
 
		/* amount of cargo produced LAST month. */
 
		case 0x9E: return this->industry->last_month_production[0];
 
		case 0x9F: return GB(this->industry->last_month_production[0], 8, 8);
 
		case 0xA0: return this->industry->last_month_production[1];
 
		case 0xA1: return GB(this->industry->last_month_production[1], 8, 8);
 
		case 0x9E: return this->industry->produced[0].history[LAST_MONTH].production;
 
		case 0x9F: return GB(this->industry->produced[0].history[LAST_MONTH].production, 8, 8);
 
		case 0xA0: return this->industry->produced[1].history[LAST_MONTH].production;
 
		case 0xA1: return GB(this->industry->produced[1].history[LAST_MONTH].production, 8, 8);
 
		/* amount of cargo transported last month. */
 
		case 0xA2: return this->industry->last_month_transported[0];
 
		case 0xA3: return GB(this->industry->last_month_transported[0], 8, 8);
 
		case 0xA4: return this->industry->last_month_transported[1];
 
		case 0xA5: return GB(this->industry->last_month_transported[1], 8, 8);
 
		case 0xA2: return this->industry->produced[0].history[LAST_MONTH].transported;
 
		case 0xA3: return GB(this->industry->produced[0].history[LAST_MONTH].transported, 8, 8);
 
		case 0xA4: return this->industry->produced[1].history[LAST_MONTH].transported;
 
		case 0xA5: return GB(this->industry->produced[1].history[LAST_MONTH].transported, 8, 8);
 

	
 
		case 0xA6: return indspec->grf_prop.local_id;
 
		case 0xA7: return this->industry->founder;
 
@@ -404,8 +404,8 @@ static uint32 GetCountAndDistanceOfClose
 
		case 0xB0: return ClampTo<uint16_t>(this->industry->construction_date - DAYS_TILL_ORIGINAL_BASE_YEAR); // Date when built since 1920 (in days)
 
		case 0xB3: return this->industry->construction_type; // Construction type
 
		case 0xB4: {
 
			TimerGameCalendar::Date *latest = std::max_element(this->industry->last_cargo_accepted_at, endof(this->industry->last_cargo_accepted_at));
 
			return ClampTo<uint16_t>((*latest) - DAYS_TILL_ORIGINAL_BASE_YEAR); // Date last cargo accepted since 1920 (in days)
 
			auto it = std::max_element(std::begin(this->industry->accepted), std::end(this->industry->accepted), [](const auto &a, const auto &b) { return a.last_accepted < b.last_accepted; });
 
			return ClampTo<uint16_t>(it->last_accepted - DAYS_TILL_ORIGINAL_BASE_YEAR); // Date last cargo accepted since 1920 (in days)
 
		}
 
	}
 

	
 
@@ -643,22 +643,22 @@ void IndustryProductionCallback(Industry
 
		if (group->version < 2) {
 
			/* Callback parameters map directly to industry cargo slot indices */
 
			for (uint i = 0; i < group->num_input; i++) {
 
				ind->incoming_cargo_waiting[i] = ClampTo<uint16_t>(ind->incoming_cargo_waiting[i] - DerefIndProd(group->subtract_input[i], deref) * multiplier);
 
				ind->accepted[i].waiting = ClampTo<uint16_t>(ind->accepted[i].waiting - DerefIndProd(group->subtract_input[i], deref) * multiplier);
 
			}
 
			for (uint i = 0; i < group->num_output; i++) {
 
				ind->produced_cargo_waiting[i] = ClampTo<uint16_t>(ind->produced_cargo_waiting[i] + std::max(DerefIndProd(group->add_output[i], deref), 0) * multiplier);
 
				ind->produced[i].waiting = ClampTo<uint16_t>(ind->produced[i].waiting + std::max(DerefIndProd(group->add_output[i], deref), 0) * multiplier);
 
			}
 
		} else {
 
			/* Callback receives list of cargos to apply for, which need to have their cargo slots in industry looked up */
 
			for (uint i = 0; i < group->num_input; i++) {
 
				int cargo_index = ind->GetCargoAcceptedIndex(group->cargo_input[i]);
 
				if (cargo_index < 0) continue;
 
				ind->incoming_cargo_waiting[cargo_index] = ClampTo<uint16_t>(ind->incoming_cargo_waiting[cargo_index] - DerefIndProd(group->subtract_input[i], deref) * multiplier);
 
				auto it = ind->GetCargoAccepted(group->cargo_input[i]);
 
				if (it == std::end(ind->accepted)) continue;
 
				it->waiting = ClampTo<uint16_t>(it->waiting - DerefIndProd(group->subtract_input[i], deref) * multiplier);
 
			}
 
			for (uint i = 0; i < group->num_output; i++) {
 
				int cargo_index = ind->GetCargoProducedIndex(group->cargo_output[i]);
 
				if (cargo_index < 0) continue;
 
				ind->produced_cargo_waiting[cargo_index] = ClampTo<uint16_t>(ind->produced_cargo_waiting[cargo_index] + std::max(DerefIndProd(group->add_output[i], deref), 0) * multiplier);
 
				auto it = ind->GetCargoProduced(group->cargo_output[i]);
 
				if (it == std::end(ind->produced)) continue;
 
				it->waiting = ClampTo<uint16_t>(it->waiting + std::max(DerefIndProd(group->add_output[i], deref), 0) * multiplier);
 
			}
 
		}
 

	
src/saveload/afterload.cpp
Show inline comments
 
@@ -1700,11 +1700,11 @@ bool AfterLoadGame()
 
		uint j;
 
		for (Industry * i : Industry::Iterate()) {
 
			const IndustrySpec *indsp = GetIndustrySpec(i->type);
 
			for (j = 0; j < lengthof(i->produced_cargo); j++) {
 
				i->produced_cargo[j] = indsp->produced_cargo[j];
 
			for (j = 0; j < lengthof(i->produced); j++) {
 
				i->produced[j].cargo = indsp->produced_cargo[j];
 
			}
 
			for (j = 0; j < lengthof(i->accepts_cargo); j++) {
 
				i->accepts_cargo[j] = indsp->accepts_cargo[j];
 
			for (j = 0; j < lengthof(i->accepted); j++) {
 
				i->accepted[j].cargo = indsp->accepts_cargo[j];
 
			}
 
		}
 
	}
 
@@ -3006,27 +3006,23 @@ bool AfterLoadGame()
 
	if (IsSavegameVersionBefore(SLV_EXTEND_INDUSTRY_CARGO_SLOTS)) {
 
		/* Make sure added industry cargo slots are cleared */
 
		for (Industry *i : Industry::Iterate()) {
 
			for (size_t ci = 2; ci < lengthof(i->produced_cargo); ci++) {
 
				i->produced_cargo[ci] = CT_INVALID;
 
				i->produced_cargo_waiting[ci] = 0;
 
				i->production_rate[ci] = 0;
 
				i->last_month_production[ci] = 0;
 
				i->last_month_transported[ci] = 0;
 
				i->last_month_pct_transported[ci] = 0;
 
				i->this_month_production[ci] = 0;
 
				i->this_month_transported[ci] = 0;
 
			for (auto it = std::begin(i->produced) + 2; it != std::end(i->produced); ++it) {
 
				it->cargo = CT_INVALID;
 
				it->waiting = 0;
 
				it->rate = 0;
 
				it->history = {};
 
			}
 
			for (size_t ci = 3; ci < lengthof(i->accepts_cargo); ci++) {
 
				i->accepts_cargo[ci] = CT_INVALID;
 
				i->incoming_cargo_waiting[ci] = 0;
 
			for (auto it = std::begin(i->accepted) + 3; it != std::end(i->accepted); ++it) {
 
				it->cargo = CT_INVALID;
 
				it->waiting = 0;
 
			}
 
			/* Make sure last_cargo_accepted_at is copied to elements for every valid input cargo.
 
			 * The loading routine should put the original singular value into the first array element. */
 
			for (size_t ci = 0; ci < lengthof(i->accepts_cargo); ci++) {
 
				if (IsValidCargoID(i->accepts_cargo[ci])) {
 
					i->last_cargo_accepted_at[ci] = i->last_cargo_accepted_at[0];
 
			for (auto &a : i->accepted) {
 
				if (IsValidCargoID(a.cargo)) {
 
					a.last_accepted = i->accepted[0].last_accepted;
 
				} else {
 
					i->last_cargo_accepted_at[ci] = 0;
 
					a.last_accepted = 0;
 
				}
 
			}
 
		}
src/saveload/compat/industry_sl_compat.h
Show inline comments
 
@@ -12,6 +12,23 @@
 

	
 
#include "../saveload.h"
 

	
 
const SaveLoadCompat _industry_accepts_sl_compat[] = {
 
	SLC_VAR("cargo"),
 
	SLC_VAR("waiting"),
 
	SLC_VAR("last_accepted"),
 
};
 

	
 
const SaveLoadCompat _industry_produced_history_sl_compat[] = {
 
	SLC_VAR("production"),
 
	SLC_VAR("transported"),
 
};
 

	
 
const SaveLoadCompat _industry_produced_sl_compat[] = {
 
	SLC_VAR("cargo"),
 
	SLC_VAR("waiting"),
 
	SLC_VAR("rate"),
 
};
 

	
 
/** Original field order for _industry_desc. */
 
const SaveLoadCompat _industry_sl_compat[] = {
 
	SLC_VAR("location.tile"),
 
@@ -29,7 +46,8 @@ const SaveLoadCompat _industry_sl_compat
 
	SLC_VAR("prod_level"),
 
	SLC_VAR("this_month_production"),
 
	SLC_VAR("this_month_transported"),
 
	SLC_VAR("last_month_pct_transported"),
 
	SLC_NULL(2, SL_MIN_VERSION, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
 
	SLC_NULL(16, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SLV_INDUSTRY_CARGO_REORGANISE),
 
	SLC_VAR("last_month_production"),
 
	SLC_VAR("last_month_transported"),
 
	SLC_VAR("counter"),
src/saveload/industry_sl.cpp
Show inline comments
 
@@ -19,6 +19,119 @@
 

	
 
static OldPersistentStorage _old_ind_persistent_storage;
 

	
 
class SlIndustryAccepted : public DefaultSaveLoadHandler<SlIndustryAccepted, Industry> {
 
public:
 
	inline static const SaveLoad description[] = {
 
		 SLE_VAR(Industry::AcceptedCargo, cargo, SLE_UINT8),
 
		 SLE_VAR(Industry::AcceptedCargo, waiting, SLE_UINT16),
 
		 SLE_VAR(Industry::AcceptedCargo, last_accepted, SLE_INT32),
 
	};
 
	inline const static SaveLoadCompatTable compat_description = _industry_accepts_sl_compat;
 

	
 
	void Save(Industry *i) const override
 
	{
 
		SlSetStructListLength(i->accepted.size());
 

	
 
		for (auto &a : i->accepted) {
 
			SlObject(&a, this->GetDescription());
 
		}
 
	}
 

	
 
	void Load(Industry *i) const override
 
	{
 
		size_t len = SlGetStructListLength(i->accepted.size());
 

	
 
		for (auto &a : i->accepted) {
 
			if (--len > i->accepted.size()) break; // unsigned so wraps after hitting zero.
 
			SlObject(&a, this->GetDescription());
 
		}
 
	}
 

	
 
	/* Old array structure used for savegames before SLV_INDUSTRY_CARGO_REORGANISE. */
 
	static CargoID old_cargo[INDUSTRY_NUM_INPUTS];
 
	static uint16_t old_waiting[INDUSTRY_NUM_INPUTS];
 
	static TimerGameCalendar::Date old_last_accepted[INDUSTRY_NUM_INPUTS];
 
};
 

	
 
/* static */ CargoID SlIndustryAccepted::old_cargo[INDUSTRY_NUM_INPUTS];
 
/* static */ uint16_t SlIndustryAccepted::old_waiting[INDUSTRY_NUM_INPUTS];
 
/* static */ TimerGameCalendar::Date SlIndustryAccepted::old_last_accepted[INDUSTRY_NUM_INPUTS];
 

	
 
class SlIndustryProducedHistory : public DefaultSaveLoadHandler<SlIndustryProducedHistory, Industry::ProducedCargo> {
 
public:
 
	inline static const SaveLoad description[] = {
 
		 SLE_VAR(Industry::ProducedHistory, production, SLE_UINT16),
 
		 SLE_VAR(Industry::ProducedHistory, transported, SLE_UINT16),
 
	};
 
	inline const static SaveLoadCompatTable compat_description = _industry_produced_history_sl_compat;
 

	
 
	void Save(Industry::ProducedCargo *p) const override
 
	{
 
		SlSetStructListLength(p->history.size());
 

	
 
		for (auto &h : p->history) {
 
			SlObject(&h, this->GetDescription());
 
		}
 
	}
 

	
 
	void Load(Industry::ProducedCargo *p) const override
 
	{
 
		size_t len = SlGetStructListLength(p->history.size());
 

	
 
		for (auto &h : p->history) {
 
			if (--len > p->history.size()) break; // unsigned so wraps after hitting zero.
 
			SlObject(&h, this->GetDescription());
 
		}
 
	}
 
};
 

	
 
class SlIndustryProduced : public DefaultSaveLoadHandler<SlIndustryProduced, Industry> {
 
public:
 
	inline static const SaveLoad description[] = {
 
		 SLE_VAR(Industry::ProducedCargo, cargo, SLE_UINT8),
 
		 SLE_VAR(Industry::ProducedCargo, waiting, SLE_UINT16),
 
		 SLE_VAR(Industry::ProducedCargo, rate, SLE_UINT8),
 
		SLEG_STRUCTLIST("history", SlIndustryProducedHistory),
 
	};
 
	inline const static SaveLoadCompatTable compat_description = _industry_produced_sl_compat;
 

	
 
	void Save(Industry *i) const override
 
	{
 
		SlSetStructListLength(i->produced.size());
 

	
 
		for (auto &p : i->produced) {
 
			SlObject(&p, this->GetDescription());
 
		}
 
	}
 

	
 
	void Load(Industry *i) const override
 
	{
 
		size_t len = SlGetStructListLength(i->produced.size());
 

	
 
		for (auto &p : i->produced) {
 
			if (--len > i->produced.size()) break; // unsigned so wraps after hitting zero.
 
			SlObject(&p, this->GetDescription());
 
		}
 
	}
 

	
 
	/* Old array structure used for savegames before SLV_INDUSTRY_CARGO_REORGANISE. */
 
	static CargoID old_cargo[INDUSTRY_NUM_OUTPUTS];
 
	static uint16_t old_waiting[INDUSTRY_NUM_OUTPUTS];
 
	static uint8_t old_rate[INDUSTRY_NUM_OUTPUTS];
 
	static uint16_t old_this_month_production[INDUSTRY_NUM_OUTPUTS];
 
	static uint16_t old_this_month_transported[INDUSTRY_NUM_OUTPUTS];
 
	static uint16_t old_last_month_production[INDUSTRY_NUM_OUTPUTS];
 
	static uint16_t old_last_month_transported[INDUSTRY_NUM_OUTPUTS];
 
};
 

	
 
/* static */ CargoID SlIndustryProduced::old_cargo[INDUSTRY_NUM_OUTPUTS];
 
/* static */ uint16_t SlIndustryProduced::old_waiting[INDUSTRY_NUM_OUTPUTS];
 
/* static */ uint8_t SlIndustryProduced::old_rate[INDUSTRY_NUM_OUTPUTS];
 
/* static */ uint16_t SlIndustryProduced::old_this_month_production[INDUSTRY_NUM_OUTPUTS];
 
/* static */ uint16_t SlIndustryProduced::old_this_month_transported[INDUSTRY_NUM_OUTPUTS];
 
/* static */ uint16_t SlIndustryProduced::old_last_month_production[INDUSTRY_NUM_OUTPUTS];
 
/* static */ uint16_t SlIndustryProduced::old_last_month_transported[INDUSTRY_NUM_OUTPUTS];
 

	
 
static const SaveLoad _industry_desc[] = {
 
	SLE_CONDVAR(Industry, location.tile,              SLE_FILE_U16 | SLE_VAR_U32,  SL_MIN_VERSION, SLV_6),
 
	SLE_CONDVAR(Industry, location.tile,              SLE_UINT32,                  SLV_6, SL_MAX_VERSION),
 
@@ -26,27 +139,25 @@ static const SaveLoad _industry_desc[] =
 
	    SLE_VAR(Industry, location.h,                 SLE_FILE_U8 | SLE_VAR_U16),
 
	    SLE_REF(Industry, town,                       REF_TOWN),
 
	SLE_CONDREF(Industry, neutral_station,            REF_STATION,                SLV_SERVE_NEUTRAL_INDUSTRIES, SL_MAX_VERSION),
 
	SLE_CONDARR(Industry, produced_cargo,             SLE_UINT8,   2,              SLV_78, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
 
	SLE_CONDARR(Industry, produced_cargo,             SLE_UINT8,  16,             SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SL_MAX_VERSION),
 
	SLE_CONDARR(Industry, incoming_cargo_waiting,     SLE_UINT16,  3,              SLV_70, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
 
	SLE_CONDARR(Industry, incoming_cargo_waiting,     SLE_UINT16, 16,             SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SL_MAX_VERSION),
 
	SLE_CONDARR(Industry, produced_cargo_waiting,     SLE_UINT16,  2,               SL_MIN_VERSION, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
 
	SLE_CONDARR(Industry, produced_cargo_waiting,     SLE_UINT16, 16,             SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SL_MAX_VERSION),
 
	SLE_CONDARR(Industry, production_rate,            SLE_UINT8,   2,               SL_MIN_VERSION, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
 
	SLE_CONDARR(Industry, production_rate,            SLE_UINT8,  16,             SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SL_MAX_VERSION),
 
	SLE_CONDARR(Industry, accepts_cargo,              SLE_UINT8,   3,              SLV_78, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
 
	SLE_CONDARR(Industry, accepts_cargo,              SLE_UINT8,  16,             SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SL_MAX_VERSION),
 
	SLEG_CONDARR("produced_cargo",             SlIndustryProduced::old_cargo,                  SLE_UINT8,   2, SLV_78, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
 
	SLEG_CONDARR("produced_cargo",             SlIndustryProduced::old_cargo,                  SLE_UINT8,  16, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SLV_INDUSTRY_CARGO_REORGANISE),
 
	SLEG_CONDARR("incoming_cargo_waiting",     SlIndustryAccepted::old_waiting,                SLE_UINT16,  3, SLV_70, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
 
	SLEG_CONDARR("incoming_cargo_waiting",     SlIndustryAccepted::old_waiting,                SLE_UINT16, 16, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SLV_INDUSTRY_CARGO_REORGANISE),
 
	SLEG_CONDARR("produced_cargo_waiting",     SlIndustryProduced::old_waiting,                SLE_UINT16,  2, SL_MIN_VERSION, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
 
	SLEG_CONDARR("produced_cargo_waiting",     SlIndustryProduced::old_waiting,                SLE_UINT16, 16, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SLV_INDUSTRY_CARGO_REORGANISE),
 
	SLEG_CONDARR("production_rate",            SlIndustryProduced::old_rate,                   SLE_UINT8,   2, SL_MIN_VERSION, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
 
	SLEG_CONDARR("production_rate",            SlIndustryProduced::old_rate,                   SLE_UINT8,  16, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SLV_INDUSTRY_CARGO_REORGANISE),
 
	SLEG_CONDARR("accepts_cargo",              SlIndustryAccepted::old_cargo,                  SLE_UINT8,   3, SLV_78, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
 
	SLEG_CONDARR("accepts_cargo",              SlIndustryAccepted::old_cargo,                  SLE_UINT8,  16, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SLV_INDUSTRY_CARGO_REORGANISE),
 
	    SLE_VAR(Industry, prod_level,                 SLE_UINT8),
 
	SLE_CONDARR(Industry, this_month_production,      SLE_UINT16,  2,               SL_MIN_VERSION, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
 
	SLE_CONDARR(Industry, this_month_production,      SLE_UINT16, 16,             SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SL_MAX_VERSION),
 
	SLE_CONDARR(Industry, this_month_transported,     SLE_UINT16,  2,               SL_MIN_VERSION, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
 
	SLE_CONDARR(Industry, this_month_transported,     SLE_UINT16, 16,             SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SL_MAX_VERSION),
 
	SLE_CONDARR(Industry, last_month_pct_transported, SLE_UINT8,   2,               SL_MIN_VERSION, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
 
	SLE_CONDARR(Industry, last_month_pct_transported, SLE_UINT8,  16,             SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SL_MAX_VERSION),
 
	SLE_CONDARR(Industry, last_month_production,      SLE_UINT16,  2,               SL_MIN_VERSION, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
 
	SLE_CONDARR(Industry, last_month_production,      SLE_UINT16, 16,             SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SL_MAX_VERSION),
 
	SLE_CONDARR(Industry, last_month_transported,     SLE_UINT16,  2,               SL_MIN_VERSION, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
 
	SLE_CONDARR(Industry, last_month_transported,     SLE_UINT16, 16,             SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SL_MAX_VERSION),
 
	SLEG_CONDARR("this_month_production",      SlIndustryProduced::old_this_month_production,  SLE_UINT16,  2, SL_MIN_VERSION, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
 
	SLEG_CONDARR("this_month_production",      SlIndustryProduced::old_this_month_production,  SLE_UINT16, 16, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SLV_INDUSTRY_CARGO_REORGANISE),
 
	SLEG_CONDARR("this_month_transported",     SlIndustryProduced::old_this_month_transported, SLE_UINT16,  2, SL_MIN_VERSION, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
 
	SLEG_CONDARR("this_month_transported",     SlIndustryProduced::old_this_month_transported, SLE_UINT16, 16, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SLV_INDUSTRY_CARGO_REORGANISE),
 
	SLEG_CONDARR("last_month_production",      SlIndustryProduced::old_last_month_production,  SLE_UINT16,  2, SL_MIN_VERSION, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
 
	SLEG_CONDARR("last_month_production",      SlIndustryProduced::old_last_month_production,  SLE_UINT16, 16, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SLV_INDUSTRY_CARGO_REORGANISE),
 
	SLEG_CONDARR("last_month_transported",     SlIndustryProduced::old_last_month_transported, SLE_UINT16,  2, SL_MIN_VERSION, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
 
	SLEG_CONDARR("last_month_transported",     SlIndustryProduced::old_last_month_transported, SLE_UINT16, 16, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SLV_INDUSTRY_CARGO_REORGANISE),
 

	
 
	    SLE_VAR(Industry, counter,                    SLE_UINT16),
 

	
 
@@ -61,8 +172,8 @@ static const SaveLoad _industry_desc[] =
 
	SLE_CONDVAR(Industry, founder,                    SLE_UINT8,                 SLV_70, SL_MAX_VERSION),
 
	SLE_CONDVAR(Industry, construction_date,          SLE_INT32,                 SLV_70, SL_MAX_VERSION),
 
	SLE_CONDVAR(Industry, construction_type,          SLE_UINT8,                 SLV_70, SL_MAX_VERSION),
 
	SLE_CONDVAR(Industry, last_cargo_accepted_at[0],  SLE_INT32,                 SLV_70, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
 
	SLE_CONDARR(Industry, last_cargo_accepted_at,     SLE_INT32, 16,            SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SL_MAX_VERSION),
 
	SLEG_CONDVAR("last_cargo_accepted_at[0]",  SlIndustryAccepted::old_last_accepted[0], SLE_INT32,     SLV_70, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
 
	SLEG_CONDARR("last_cargo_accepted_at",     SlIndustryAccepted::old_last_accepted,    SLE_INT32, 16, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SLV_INDUSTRY_CARGO_REORGANISE),
 
	SLE_CONDVAR(Industry, selected_layout,            SLE_UINT8,                 SLV_73, SL_MAX_VERSION),
 
	SLE_CONDVAR(Industry, exclusive_supplier,         SLE_UINT8,                 SLV_GS_INDUSTRY_CONTROL, SL_MAX_VERSION),
 
	SLE_CONDVAR(Industry, exclusive_consumer,         SLE_UINT8,                 SLV_GS_INDUSTRY_CONTROL, SL_MAX_VERSION),
 
@@ -72,6 +183,9 @@ static const SaveLoad _industry_desc[] =
 

	
 
	SLE_CONDVAR(Industry, random,                     SLE_UINT16,                SLV_82, SL_MAX_VERSION),
 
	SLE_CONDSSTR(Industry, text,     SLE_STR | SLF_ALLOW_CONTROL,     SLV_INDUSTRY_TEXT, SL_MAX_VERSION),
 

	
 
	SLEG_CONDSTRUCTLIST("accepted", SlIndustryAccepted,                          SLV_INDUSTRY_CARGO_REORGANISE, SL_MAX_VERSION),
 
	SLEG_CONDSTRUCTLIST("produced", SlIndustryProduced,                          SLV_INDUSTRY_CARGO_REORGANISE, SL_MAX_VERSION),
 
};
 

	
 
struct INDYChunkHandler : ChunkHandler {
 
@@ -88,6 +202,27 @@ struct INDYChunkHandler : ChunkHandler {
 
		}
 
	}
 

	
 
	void LoadMoveAcceptsProduced(Industry *i) const
 
	{
 
		for (uint j = 0; j != INDUSTRY_NUM_INPUTS; ++j) {
 
			auto &a = i->accepted[j];
 
			a.cargo = SlIndustryAccepted::old_cargo[j];
 
			a.waiting = SlIndustryAccepted::old_waiting[j];
 
			a.last_accepted = SlIndustryAccepted::old_last_accepted[j];
 
		}
 

	
 
		for (uint j = 0; j != INDUSTRY_NUM_OUTPUTS; ++j) {
 
			auto &p = i->produced[j];
 
			p.cargo = SlIndustryProduced::old_cargo[j];
 
			p.waiting = SlIndustryProduced::old_waiting[j];
 
			p.rate = SlIndustryProduced::old_rate[j];
 
			p.history[THIS_MONTH].production = SlIndustryProduced::old_this_month_production[j];
 
			p.history[THIS_MONTH].transported = SlIndustryProduced::old_this_month_transported[j];
 
			p.history[LAST_MONTH].production = SlIndustryProduced::old_last_month_production[j];
 
			p.history[LAST_MONTH].transported = SlIndustryProduced::old_last_month_transported[j];
 
		}
 
	}
 

	
 
	void Load() const override
 
	{
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(_industry_desc, _industry_sl_compat);
 
@@ -107,6 +242,7 @@ struct INDYChunkHandler : ChunkHandler {
 
				i->psa = new PersistentStorage(0, 0, 0);
 
				memcpy(i->psa->storage, _old_ind_persistent_storage.storage, sizeof(_old_ind_persistent_storage.storage));
 
			}
 
			if (IsSavegameVersionBefore(SLV_INDUSTRY_CARGO_REORGANISE)) LoadMoveAcceptsProduced(i);
 
			Industry::IncIndustryTypeCount(i->type);
 
		}
 
	}
src/saveload/oldloader_sl.cpp
Show inline comments
 
@@ -795,30 +795,29 @@ static const OldChunks industry_chunk[] 
 
	OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Industry, location.h ),
 
	OCL_NULL( 2 ),  ///< used to be industry's produced_cargo
 

	
 
	OCL_SVAR( OC_TTD | OC_UINT16, Industry, produced_cargo_waiting[0] ),
 
	OCL_SVAR( OC_TTD | OC_UINT16, Industry, produced_cargo_waiting[1] ),
 
	OCL_SVAR( OC_TTO | OC_FILE_U8 | OC_VAR_U16, Industry, produced_cargo_waiting[0] ),
 
	OCL_SVAR( OC_TTO | OC_FILE_U8 | OC_VAR_U16, Industry, produced_cargo_waiting[1] ),
 
	OCL_SVAR( OC_TTD | OC_UINT16, Industry, produced[0].waiting ),
 
	OCL_SVAR( OC_TTD | OC_UINT16, Industry, produced[1].waiting ),
 
	OCL_SVAR( OC_TTO | OC_FILE_U8 | OC_VAR_U16, Industry, produced[0].waiting ),
 
	OCL_SVAR( OC_TTO | OC_FILE_U8 | OC_VAR_U16, Industry, produced[1].waiting ),
 

	
 
	OCL_SVAR(  OC_UINT8, Industry, production_rate[0] ),
 
	OCL_SVAR(  OC_UINT8, Industry, production_rate[1] ),
 
	OCL_SVAR(  OC_UINT8, Industry, produced[0].rate ),
 
	OCL_SVAR(  OC_UINT8, Industry, produced[1].rate ),
 

	
 
	OCL_NULL( 3 ),  ///< used to be industry's accepts_cargo
 

	
 
	OCL_SVAR(  OC_UINT8, Industry, prod_level ),
 

	
 
	OCL_SVAR( OC_UINT16, Industry, this_month_production[0] ),
 
	OCL_SVAR( OC_UINT16, Industry, this_month_production[1] ),
 
	OCL_SVAR( OC_UINT16, Industry, this_month_transported[0] ),
 
	OCL_SVAR( OC_UINT16, Industry, this_month_transported[1] ),
 
	OCL_SVAR( OC_UINT16, Industry, produced[0].history[THIS_MONTH].production ),
 
	OCL_SVAR( OC_UINT16, Industry, produced[1].history[THIS_MONTH].production ),
 
	OCL_SVAR( OC_UINT16, Industry, produced[0].history[THIS_MONTH].transported ),
 
	OCL_SVAR( OC_UINT16, Industry, produced[1].history[THIS_MONTH].transported ),
 

	
 
	OCL_SVAR(  OC_UINT8, Industry, last_month_pct_transported[0] ),
 
	OCL_SVAR(  OC_UINT8, Industry, last_month_pct_transported[1] ),
 
	OCL_NULL( 2 ), ///< last_month_pct_transported, now computed on the fly
 

	
 
	OCL_SVAR( OC_UINT16, Industry, last_month_production[0] ),
 
	OCL_SVAR( OC_UINT16, Industry, last_month_production[1] ),
 
	OCL_SVAR( OC_UINT16, Industry, last_month_transported[0] ),
 
	OCL_SVAR( OC_UINT16, Industry, last_month_transported[1] ),
 
	OCL_SVAR( OC_UINT16, Industry, produced[0].history[LAST_MONTH].production ),
 
	OCL_SVAR( OC_UINT16, Industry, produced[1].history[LAST_MONTH].production ),
 
	OCL_SVAR( OC_UINT16, Industry, produced[0].history[LAST_MONTH].transported ),
 
	OCL_SVAR( OC_UINT16, Industry, produced[1].history[LAST_MONTH].transported ),
 

	
 
	OCL_SVAR(  OC_UINT8, Industry, type ),
 
	OCL_SVAR( OC_TTO | OC_FILE_U8 | OC_VAR_U16, Industry, counter ),
src/saveload/saveload.h
Show inline comments
 
@@ -356,6 +356,8 @@ enum SaveLoadVersion : uint16 {
 
	SLV_SAVEGAME_ID,                        ///< 313  PR#10719 Add an unique ID to every savegame (used to deduplicate surveys).
 
	SLV_STRING_GAMELOG,                     ///< 314  PR#10801 Use std::string in gamelog.
 

	
 
	SLV_INDUSTRY_CARGO_REORGANISE,          ///< 315  PR#10853 Industry accepts/produced data reorganised.
 

	
 
	SL_MAX_VERSION,                         ///< Highest possible saveload version
 
};
 

	
src/script/api/script_cargolist.cpp
Show inline comments
 
@@ -29,10 +29,9 @@ ScriptCargoList_IndustryAccepting::Scrip
 
	if (!ScriptIndustry::IsValidIndustry(industry_id)) return;
 

	
 
	Industry *ind = ::Industry::Get(industry_id);
 
	for (uint i = 0; i < lengthof(ind->accepts_cargo); i++) {
 
		CargoID cargo_id = ind->accepts_cargo[i];
 
		if (::IsValidCargoID(cargo_id)) {
 
			this->AddItem(cargo_id);
 
	for (const auto &a : ind->accepted) {
 
		if (::IsValidCargoID(a.cargo)) {
 
			this->AddItem(a.cargo);
 
		}
 
	}
 
}
 
@@ -42,10 +41,9 @@ ScriptCargoList_IndustryProducing::Scrip
 
	if (!ScriptIndustry::IsValidIndustry(industry_id)) return;
 

	
 
	Industry *ind = ::Industry::Get(industry_id);
 
	for (uint i = 0; i < lengthof(ind->produced_cargo); i++) {
 
		CargoID cargo_id = ind->produced_cargo[i];
 
		if (::IsValidCargoID(cargo_id)) {
 
			this->AddItem(cargo_id);
 
	for (const auto &p : ind->produced) {
 
		if (::IsValidCargoID(p.cargo)) {
 
			this->AddItem(p.cargo);
 
		}
 
	}
 
}
src/script/api/script_industry.cpp
Show inline comments
 
@@ -80,10 +80,10 @@
 

	
 
	Industry *i = ::Industry::Get(industry_id);
 

	
 
	int j = i->GetCargoAcceptedIndex(cargo_id);
 
	if (j < 0) return -1;
 
	auto it = i->GetCargoAccepted(cargo_id);
 
	if (it == std::end(i->accepted)) return -1;
 

	
 
	return i->incoming_cargo_waiting[j];
 
	return it->waiting;
 
}
 

	
 
/* static */ SQInteger ScriptIndustry::GetLastMonthProduction(IndustryID industry_id, CargoID cargo_id)
 
@@ -91,12 +91,12 @@
 
	if (!IsValidIndustry(industry_id)) return -1;
 
	if (!ScriptCargo::IsValidCargo(cargo_id)) return -1;
 

	
 
	const Industry *i = ::Industry::Get(industry_id);
 
	Industry *i = ::Industry::Get(industry_id);
 

	
 
	int j = i->GetCargoProducedIndex(cargo_id);
 
	if (j < 0) return -1;
 
	auto it = i->GetCargoProduced(cargo_id);
 
	if (it == std::end(i->produced)) return -1;
 

	
 
	return i->last_month_production[j];
 
	return it->history[LAST_MONTH].production;
 
}
 

	
 
/* static */ SQInteger ScriptIndustry::GetLastMonthTransported(IndustryID industry_id, CargoID cargo_id)
 
@@ -104,12 +104,12 @@
 
	if (!IsValidIndustry(industry_id)) return -1;
 
	if (!ScriptCargo::IsValidCargo(cargo_id)) return -1;
 

	
 
	const Industry *i = ::Industry::Get(industry_id);
 
	Industry *i = ::Industry::Get(industry_id);
 

	
 
	int j = i->GetCargoProducedIndex(cargo_id);
 
	if (j < 0) return -1;
 
	auto it = i->GetCargoProduced(cargo_id);
 
	if (it == std::end(i->produced)) return -1;
 

	
 
	return i->last_month_transported[j];
 
	return it->history[LAST_MONTH].transported;
 
}
 

	
 
/* static */ SQInteger ScriptIndustry::GetLastMonthTransportedPercentage(IndustryID industry_id, CargoID cargo_id)
 
@@ -117,12 +117,12 @@
 
	if (!IsValidIndustry(industry_id)) return -1;
 
	if (!ScriptCargo::IsValidCargo(cargo_id)) return -1;
 

	
 
	const Industry *i = ::Industry::Get(industry_id);
 
	Industry *i = ::Industry::Get(industry_id);
 

	
 
	int j = i->GetCargoProducedIndex(cargo_id);
 
	if (j < 0) return -1;
 
	auto it = i->GetCargoProduced(cargo_id);
 
	if (it == std::end(i->produced)) return -1;
 

	
 
	return ::ToPercent8(i->last_month_pct_transported[j]);
 
	return ::ToPercent8(it->history[LAST_MONTH].PctTransported());
 
}
 

	
 
/* static */ TileIndex ScriptIndustry::GetLocation(IndustryID industry_id)
 
@@ -225,11 +225,12 @@
 
	if (i == nullptr) return ScriptDate::DATE_INVALID;
 

	
 
	if (!::IsValidCargoID(cargo_type)) {
 
		return (ScriptDate::Date)std::accumulate(std::begin(i->last_cargo_accepted_at), std::end(i->last_cargo_accepted_at), 0, [](TimerGameCalendar::Date a, TimerGameCalendar::Date b) { return std::max(a, b); });
 
		auto it = std::max_element(std::begin(i->accepted), std::end(i->accepted), [](const auto &a, const auto &b) { return a.last_accepted < b.last_accepted; });
 
		return (ScriptDate::Date)it->last_accepted;
 
	} else {
 
		int index = i->GetCargoAcceptedIndex(cargo_type);
 
		if (index < 0) return ScriptDate::DATE_INVALID;
 
		return (ScriptDate::Date)i->last_cargo_accepted_at[index];
 
		auto it = i->GetCargoAccepted(cargo_type);
 
		if (it == std::end(i->accepted)) return ScriptDate::DATE_INVALID;
 
		return (ScriptDate::Date)it->last_accepted;
 
	}
 
}
 

	
src/script/api/script_tilelist.cpp
Show inline comments
 
@@ -95,13 +95,7 @@ ScriptTileList_IndustryAccepting::Script
 
		/* Only add the tile if it accepts the cargo (sometimes just 1 tile of an
 
		 *  industry triggers the acceptance). */
 
		CargoArray acceptance = ::GetAcceptanceAroundTiles(cur_tile, 1, 1, radius);
 
		{
 
			bool cargo_accepts = false;
 
			for (byte j = 0; j < lengthof(i->accepts_cargo); j++) {
 
				if (::IsValidCargoID(i->accepts_cargo[j]) && acceptance[i->accepts_cargo[j]] != 0) cargo_accepts = true;
 
			}
 
			if (!cargo_accepts) continue;
 
		}
 
		if (std::none_of(std::begin(i->accepted), std::end(i->accepted), [&acceptance](const auto &a) { return ::IsValidCargoID(a.cargo) && acceptance[a.cargo] != 0; })) continue;
 

	
 
		this->AddTile(cur_tile);
 
	}
src/station_cmd.cpp
Show inline comments
 
@@ -170,11 +170,11 @@ static bool CMSAMine(TileIndex tile)
 
	/* No extractive industry */
 
	if ((GetIndustrySpec(ind->type)->life_type & INDUSTRYLIFE_EXTRACTIVE) == 0) return false;
 

	
 
	for (uint i = 0; i < lengthof(ind->produced_cargo); i++) {
 
	for (const auto &p : ind->produced) {
 
		/* The industry extracts something non-liquid, i.e. no oil or plastic, so it is a mine.
 
		 * Also the production of passengers and mail is ignored. */
 
		if (IsValidCargoID(ind->produced_cargo[i]) &&
 
				(CargoSpec::Get(ind->produced_cargo[i])->classes & (CC_LIQUID | CC_PASSENGERS | CC_MAIL)) == 0) {
 
		if (IsValidCargoID(p.cargo) &&
 
				(CargoSpec::Get(p.cargo)->classes & (CC_LIQUID | CC_PASSENGERS | CC_MAIL)) == 0) {
 
			return true;
 
		}
 
	}
 
@@ -532,9 +532,8 @@ CargoArray GetProductionAroundTiles(Tile
 
		/* Skip industry with neutral station */
 
		if (i->neutral_station != nullptr && !_settings_game.station.serve_neutral_industries) continue;
 

	
 
		for (uint j = 0; j < lengthof(i->produced_cargo); j++) {
 
			CargoID cargo = i->produced_cargo[j];
 
			if (IsValidCargoID(cargo)) produced[cargo]++;
 
		for (const auto &p : i->produced) {
 
			if (IsValidCargoID(p.cargo)) produced[p.cargo]++;
 
		}
 
	}
 

	
src/subsidy.cpp
Show inline comments
 
@@ -382,21 +382,20 @@ bool FindSubsidyIndustryCargoRoute()
 
	CargoID cid;
 

	
 
	/* Randomize cargo type */
 
	int num_cargos = 0;
 
	uint cargo_index;
 
	for (cargo_index = 0; cargo_index < lengthof(src_ind->produced_cargo); cargo_index++) {
 
		if (IsValidCargoID(src_ind->produced_cargo[cargo_index])) num_cargos++;
 
	}
 
	int num_cargos = std::count_if(std::begin(src_ind->produced), std::end(src_ind->produced), [](const auto &p) { return IsValidCargoID(p.cargo); });
 
	if (num_cargos == 0) return false; // industry produces nothing
 
	int cargo_num = RandomRange(num_cargos) + 1;
 
	for (cargo_index = 0; cargo_index < lengthof(src_ind->produced_cargo); cargo_index++) {
 
		if (IsValidCargoID(src_ind->produced_cargo[cargo_index])) cargo_num--;
 

	
 
	auto it = std::begin(src_ind->produced);
 
	for (/* nothing */; it != std::end(src_ind->produced); ++it) {
 
		if (IsValidCargoID(it->cargo)) cargo_num--;
 
		if (cargo_num == 0) break;
 
	}
 
	assert(cargo_num == 0); // indicates loop didn't break as intended
 
	cid = src_ind->produced_cargo[cargo_index];
 
	trans = src_ind->last_month_pct_transported[cargo_index];
 
	total = src_ind->last_month_production[cargo_index];
 
	assert(it != std::end(src_ind->produced)); // indicates loop didn't end as intended
 

	
 
	cid = it->cargo;
 
	trans = it->history[LAST_MONTH].PctTransported();
 
	total = it->history[LAST_MONTH].production;
 

	
 
	/* Quit if no production in this industry
 
	 * or if the pct transported is already large enough
src/table/newgrf_debug_data.h
Show inline comments
 
@@ -275,38 +275,38 @@ static const NIFeature _nif_industrytile
 
/*** NewGRF industries ***/
 

	
 
static const NIProperty _nip_industries[] = {
 
	NIP(0x25, Industry, produced_cargo[ 0], NIT_CARGO, "produced cargo 0"),
 
	NIP(0x25, Industry, produced_cargo[ 1], NIT_CARGO, "produced cargo 1"),
 
	NIP(0x25, Industry, produced_cargo[ 2], NIT_CARGO, "produced cargo 2"),
 
	NIP(0x25, Industry, produced_cargo[ 3], NIT_CARGO, "produced cargo 3"),
 
	NIP(0x25, Industry, produced_cargo[ 4], NIT_CARGO, "produced cargo 4"),
 
	NIP(0x25, Industry, produced_cargo[ 5], NIT_CARGO, "produced cargo 5"),
 
	NIP(0x25, Industry, produced_cargo[ 6], NIT_CARGO, "produced cargo 6"),
 
	NIP(0x25, Industry, produced_cargo[ 7], NIT_CARGO, "produced cargo 7"),
 
	NIP(0x25, Industry, produced_cargo[ 8], NIT_CARGO, "produced cargo 8"),
 
	NIP(0x25, Industry, produced_cargo[ 9], NIT_CARGO, "produced cargo 9"),
 
	NIP(0x25, Industry, produced_cargo[10], NIT_CARGO, "produced cargo 10"),
 
	NIP(0x25, Industry, produced_cargo[11], NIT_CARGO, "produced cargo 11"),
 
	NIP(0x25, Industry, produced_cargo[12], NIT_CARGO, "produced cargo 12"),
 
	NIP(0x25, Industry, produced_cargo[13], NIT_CARGO, "produced cargo 13"),
 
	NIP(0x25, Industry, produced_cargo[14], NIT_CARGO, "produced cargo 14"),
 
	NIP(0x25, Industry, produced_cargo[15], NIT_CARGO, "produced cargo 15"),
 
	NIP(0x26, Industry, accepts_cargo[ 0],  NIT_CARGO, "accepted cargo 0"),
 
	NIP(0x26, Industry, accepts_cargo[ 1],  NIT_CARGO, "accepted cargo 1"),
 
	NIP(0x26, Industry, accepts_cargo[ 2],  NIT_CARGO, "accepted cargo 2"),
 
	NIP(0x26, Industry, accepts_cargo[ 3],  NIT_CARGO, "accepted cargo 3"),
 
	NIP(0x26, Industry, accepts_cargo[ 4],  NIT_CARGO, "accepted cargo 4"),
 
	NIP(0x26, Industry, accepts_cargo[ 5],  NIT_CARGO, "accepted cargo 5"),
 
	NIP(0x26, Industry, accepts_cargo[ 6],  NIT_CARGO, "accepted cargo 6"),
 
	NIP(0x26, Industry, accepts_cargo[ 7],  NIT_CARGO, "accepted cargo 7"),
 
	NIP(0x26, Industry, accepts_cargo[ 8],  NIT_CARGO, "accepted cargo 8"),
 
	NIP(0x26, Industry, accepts_cargo[ 9],  NIT_CARGO, "accepted cargo 9"),
 
	NIP(0x26, Industry, accepts_cargo[10],  NIT_CARGO, "accepted cargo 10"),
 
	NIP(0x26, Industry, accepts_cargo[11],  NIT_CARGO, "accepted cargo 11"),
 
	NIP(0x26, Industry, accepts_cargo[12],  NIT_CARGO, "accepted cargo 12"),
 
	NIP(0x26, Industry, accepts_cargo[13],  NIT_CARGO, "accepted cargo 13"),
 
	NIP(0x26, Industry, accepts_cargo[14],  NIT_CARGO, "accepted cargo 14"),
 
	NIP(0x26, Industry, accepts_cargo[15],  NIT_CARGO, "accepted cargo 15"),
 
	NIP(0x25, Industry, produced[ 0].cargo, NIT_CARGO, "produced cargo 0"),
 
	NIP(0x25, Industry, produced[ 1].cargo, NIT_CARGO, "produced cargo 1"),
 
	NIP(0x25, Industry, produced[ 2].cargo, NIT_CARGO, "produced cargo 2"),
 
	NIP(0x25, Industry, produced[ 3].cargo, NIT_CARGO, "produced cargo 3"),
 
	NIP(0x25, Industry, produced[ 4].cargo, NIT_CARGO, "produced cargo 4"),
 
	NIP(0x25, Industry, produced[ 5].cargo, NIT_CARGO, "produced cargo 5"),
 
	NIP(0x25, Industry, produced[ 6].cargo, NIT_CARGO, "produced cargo 6"),
 
	NIP(0x25, Industry, produced[ 7].cargo, NIT_CARGO, "produced cargo 7"),
 
	NIP(0x25, Industry, produced[ 8].cargo, NIT_CARGO, "produced cargo 8"),
 
	NIP(0x25, Industry, produced[ 9].cargo, NIT_CARGO, "produced cargo 9"),
 
	NIP(0x25, Industry, produced[10].cargo, NIT_CARGO, "produced cargo 10"),
 
	NIP(0x25, Industry, produced[11].cargo, NIT_CARGO, "produced cargo 11"),
 
	NIP(0x25, Industry, produced[12].cargo, NIT_CARGO, "produced cargo 12"),
 
	NIP(0x25, Industry, produced[13].cargo, NIT_CARGO, "produced cargo 13"),
 
	NIP(0x25, Industry, produced[14].cargo, NIT_CARGO, "produced cargo 14"),
 
	NIP(0x25, Industry, produced[15].cargo, NIT_CARGO, "produced cargo 15"),
 
	NIP(0x26, Industry, accepted[ 0].cargo, NIT_CARGO, "accepted cargo 0"),
 
	NIP(0x26, Industry, accepted[ 1].cargo, NIT_CARGO, "accepted cargo 1"),
 
	NIP(0x26, Industry, accepted[ 2].cargo, NIT_CARGO, "accepted cargo 2"),
 
	NIP(0x26, Industry, accepted[ 3].cargo, NIT_CARGO, "accepted cargo 3"),
 
	NIP(0x26, Industry, accepted[ 4].cargo, NIT_CARGO, "accepted cargo 4"),
 
	NIP(0x26, Industry, accepted[ 5].cargo, NIT_CARGO, "accepted cargo 5"),
 
	NIP(0x26, Industry, accepted[ 6].cargo, NIT_CARGO, "accepted cargo 6"),
 
	NIP(0x26, Industry, accepted[ 7].cargo, NIT_CARGO, "accepted cargo 7"),
 
	NIP(0x26, Industry, accepted[ 8].cargo, NIT_CARGO, "accepted cargo 8"),
 
	NIP(0x26, Industry, accepted[ 9].cargo, NIT_CARGO, "accepted cargo 9"),
 
	NIP(0x26, Industry, accepted[10].cargo, NIT_CARGO, "accepted cargo 10"),
 
	NIP(0x26, Industry, accepted[11].cargo, NIT_CARGO, "accepted cargo 11"),
 
	NIP(0x26, Industry, accepted[12].cargo, NIT_CARGO, "accepted cargo 12"),
 
	NIP(0x26, Industry, accepted[13].cargo, NIT_CARGO, "accepted cargo 13"),
 
	NIP(0x26, Industry, accepted[14].cargo, NIT_CARGO, "accepted cargo 14"),
 
	NIP(0x26, Industry, accepted[15].cargo, NIT_CARGO, "accepted cargo 15"),
 
	NIP_END()
 
};
 

	
0 comments (0 inline, 0 general)