mirror of https://github.com/OpenTTD/OpenTTD
Fix #14396: Industry production graph showed zero instead of N/A.
Record the number of valid history records per industry so that the graph avoids showing values which are not present as zero.pull/14321/head
parent
9b55ad5b8d
commit
290144c5c9
|
@ -222,6 +222,7 @@ protected:
|
|||
const Tprojection &proj; ///< Projection to apply.
|
||||
|
||||
inline void Fill(uint i, const auto &data) const { this->dataset.values[i] = std::invoke(this->proj, data); }
|
||||
inline void MakeInvalid(uint i) const { this->dataset.values[i] = INVALID_DATAPOINT; }
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1685,7 +1686,7 @@ struct IndustryProductionGraphWindow : BaseCargoGraphWindow {
|
|||
transported.dash = 2;
|
||||
auto transported_filler = Filler{transported, &Industry::ProducedHistory::transported};
|
||||
|
||||
FillFromHistory<GRAPH_NUM_MONTHS>(p.history, produced_filler, transported_filler);
|
||||
FillFromHistory<GRAPH_NUM_MONTHS>(p.history, i->valid_history, produced_filler, transported_filler);
|
||||
}
|
||||
|
||||
this->SetDirty();
|
||||
|
|
|
@ -89,6 +89,7 @@ struct Industry : IndustryPool::PoolItem<&_industry_pool> {
|
|||
TileArea location{INVALID_TILE, 0, 0}; ///< Location of the industry
|
||||
Town *town = nullptr; ///< Nearest town
|
||||
Station *neutral_station = nullptr; ///< Associated neutral station
|
||||
ValidHistoryMask valid_history = 0; ///< Mask of valid history records.
|
||||
ProducedCargoes produced{}; ///< produced cargo slots
|
||||
AcceptedCargoes accepted{}; ///< accepted cargo slots
|
||||
uint8_t prod_level = 0; ///< general production level
|
||||
|
|
|
@ -1837,6 +1837,8 @@ static void DoCreateNewIndustry(Industry *i, TileIndex tile, IndustryType type,
|
|||
for (auto &p : i->produced) {
|
||||
p.history[LAST_MONTH].production += ScaleByCargoScale(p.rate * 8, false);
|
||||
}
|
||||
|
||||
UpdateValidHistory(i->valid_history);
|
||||
}
|
||||
|
||||
if (indspec->callback_mask.Test(IndustryCallbackMask::DecideColour)) {
|
||||
|
@ -2494,6 +2496,8 @@ void GenerateIndustries()
|
|||
*/
|
||||
static void UpdateIndustryStatistics(Industry *i)
|
||||
{
|
||||
UpdateValidHistory(i->valid_history);
|
||||
|
||||
for (auto &p : i->produced) {
|
||||
if (IsValidCargoType(p.cargo)) {
|
||||
if (p.history[THIS_MONTH].production != 0) i->last_prod_year = TimerGameEconomy::year;
|
||||
|
|
|
@ -10,8 +10,18 @@
|
|||
#ifndef HISTORY_FUNC_HPP
|
||||
#define HISTORY_FUNC_HPP
|
||||
|
||||
#include "../core/bitmath_func.hpp"
|
||||
#include "history_type.hpp"
|
||||
|
||||
/**
|
||||
* Update mask of valid history records.
|
||||
* @param[in,out] valid_history Valid history records.
|
||||
*/
|
||||
inline void UpdateValidHistory(ValidHistoryMask &valid_history)
|
||||
{
|
||||
SB(valid_history, LAST_MONTH, HISTORY_RECORDS - LAST_MONTH, GB(valid_history, LAST_MONTH, HISTORY_RECORDS - LAST_MONTH) << 1ULL | 1ULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotate history.
|
||||
* @tparam T type of history data element.
|
||||
|
@ -27,14 +37,19 @@ void RotateHistory(HistoryData<T> &history)
|
|||
/**
|
||||
* Fill some data with historical data.
|
||||
* @param history Historical data to fill from.
|
||||
* @param valid_history Mask of valid history records.
|
||||
* @param fillers Fillers to fill with history data.
|
||||
*/
|
||||
template <uint N, typename T, typename... Tfillers>
|
||||
void FillFromHistory(const HistoryData<T> &history, Tfillers... fillers)
|
||||
void FillFromHistory(const HistoryData<T> &history, ValidHistoryMask valid_history, Tfillers... fillers)
|
||||
{
|
||||
for (uint i = 0; i != N; ++i) {
|
||||
auto &data = history[N - i];
|
||||
(fillers.Fill(i, data), ...);
|
||||
if (HasBit(valid_history, N - i)) {
|
||||
auto &data = history[N - i];
|
||||
(fillers.Fill(i, data), ...);
|
||||
} else {
|
||||
(fillers.MakeInvalid(i), ...);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,4 +22,7 @@ static constexpr uint8_t LAST_MONTH = 1;
|
|||
template <typename T>
|
||||
using HistoryData = std::array<T, HISTORY_RECORDS>;
|
||||
|
||||
/** Mask of valid history records. */
|
||||
using ValidHistoryMask = uint64_t;
|
||||
|
||||
#endif /* HISTORY_TYPE_HPP */
|
||||
|
|
|
@ -162,6 +162,8 @@ 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),
|
||||
|
||||
SLE_CONDVAR(Industry, valid_history, SLE_UINT64, SLV_INDUSTRY_NUM_VALID_HISTORY, 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),
|
||||
};
|
||||
|
@ -228,6 +230,24 @@ struct INDYChunkHandler : ChunkHandler {
|
|||
} else if (IsSavegameVersionBefore(SLV_INDUSTRY_CARGO_REORGANISE)) {
|
||||
LoadMoveAcceptsProduced(i, INDUSTRY_NUM_INPUTS, INDUSTRY_NUM_OUTPUTS);
|
||||
}
|
||||
|
||||
if (IsSavegameVersionBefore(SLV_INDUSTRY_NUM_VALID_HISTORY)) {
|
||||
/* The last month has always been recorded. */
|
||||
size_t oldest_valid = LAST_MONTH;
|
||||
if (!IsSavegameVersionBefore(SLV_PRODUCTION_HISTORY)) {
|
||||
/* History was extended but we did not keep track of valid history, so assume it from the oldest non-zero value. */
|
||||
for (const auto &p : i->produced) {
|
||||
if (!IsValidCargoType(p.cargo)) continue;
|
||||
for (size_t n = LAST_MONTH; n < std::size(p.history); ++n) {
|
||||
if (p.history[n].production == 0 && p.history[n].transported == 0) continue;
|
||||
oldest_valid = std::max(oldest_valid, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Set mask bits up to and including the oldest valid record. */
|
||||
i->valid_history = (std::numeric_limits<uint64_t>::max() >> (std::numeric_limits<uint64_t>::digits - (oldest_valid + 1 - LAST_MONTH))) << LAST_MONTH;
|
||||
}
|
||||
|
||||
Industry::industries[i->type].insert(i->index);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -404,6 +404,7 @@ enum SaveLoadVersion : uint16_t {
|
|||
SLV_ORDERS_OWNED_BY_ORDERLIST, ///< 354 PR#13948 Orders stored in OrderList, pool removed.
|
||||
|
||||
SLV_FACE_STYLES, ///< 355 PR#14319 Addition of face styles, replacing gender and ethnicity.
|
||||
SLV_INDUSTRY_NUM_VALID_HISTORY, ///< 356 PR#14416 Store number of valid history records for industries.
|
||||
|
||||
SL_MAX_VERSION, ///< Highest possible saveload version
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue