mirror of https://github.com/OpenTTD/OpenTTD
Compare commits
6 Commits
0b01b220b3
...
36ff01548d
Author | SHA1 | Date |
---|---|---|
|
36ff01548d | |
|
2cdd50f40e | |
|
56942a15c7 | |
|
5eeda026a4 | |
|
edc5b8ea1f | |
|
185ca3a7f5 |
|
@ -7,6 +7,19 @@
|
|||
|
||||
/* This file contains code to downgrade the API from 15 to 14. */
|
||||
|
||||
AIDate <- AIEconomyDate;
|
||||
AIDate.IsValidDate <- function(date) { return AIDate(date).IsValid(); }
|
||||
AIDate.GetCurrentDateCompat14 <- AIDate.GetCurrentDate;
|
||||
AIDate.GetCurrentDate <- function() { return AIDate.GetCurrentDateCompat14().date(); }
|
||||
AIDate.GetYearCompat14 <- AIDate.GetYear;
|
||||
AIDate.GetYear <- function(date) { return AIDate(date).GetYearCompat14(); }
|
||||
AIDate.GetMonthCompat14 <- AIDate.GetMonth;
|
||||
AIDate.GetMonth <- function(date) { return AIDate(date).GetMonthCompat14(); }
|
||||
AIDate.GetDayOfMonthCompat14 <- AIDate.GetDayOfMonth;
|
||||
AIDate.GetDayOfMonth <- function(date) { return AIDate(date).GetDayOfMonthCompat14(); }
|
||||
AIDate.GetDateCompat14 <- AIDate.GetDate;
|
||||
AIDate.GetDate <- function(year, month, day) { return AIDate.GetDateCompat14(year, month, day).date(); }
|
||||
|
||||
AIBridge.GetBridgeID <- AIBridge.GetBridgeType;
|
||||
|
||||
class AICompat14 {
|
||||
|
@ -17,6 +30,8 @@ class AICompat14 {
|
|||
}
|
||||
}
|
||||
|
||||
AIBaseStation.GetConstructionDateCompat14 <- AIBaseStation.GetConstructionDate;
|
||||
AIBaseStation.GetConstructionDate <- function(station_id) { return AIBaseStation.GetConstructionDateCompat14(station_id).date(); }
|
||||
AIBaseStation.SetNameCompat14 <- AIBaseStation.SetName;
|
||||
AIBaseStation.SetName <- function(id, name) { return AIBaseStation.SetNameCompat14(id, AICompat14.Text(name)); }
|
||||
|
||||
|
@ -25,12 +40,18 @@ AICompany.SetName <- function(name) { return AICompany.SetNameCompat14(AICompat1
|
|||
AICompany.SetPresidentNameCompat14 <- AICompany.SetPresidentName;
|
||||
AICompany.SetPresidentName <- function(name) { return AICompany.SetPresidentNameCompat14(AICompat14.Text(name)); }
|
||||
|
||||
AIEngine.GetDesignDateCompat14 <- AIEngine.GetDesignDate;
|
||||
AIEngine.GetDesignDate <- function(engine_id) { return AIEngine.GetDesignDateCompat14(engine_id).date(); }
|
||||
|
||||
AIGroup.SetNameCompat14 <- AIGroup.SetName;
|
||||
AIGroup.SetName <- function(id, name) { return AIGroup.SetNameCompat14(id, AICompat14.Text(name)); }
|
||||
|
||||
AISign.BuildSignCompat14 <- AISign.BuildSign;
|
||||
AISign.BuildSign <- function(id, name) { return AISign.BuildSignCompat14(id, AICompat14.Text(name)); }
|
||||
|
||||
AISubsidy.GetExpireDateCompat14 <- AISubsidy.GetExpireDate;
|
||||
AISubsidy.GetExpireDate <- function(subsidy_id) { return AISubsidy.GetExpireDateCompat14(subsidy_id).date(); }
|
||||
|
||||
AITown.FoundTownCompat14 <- AITown.FoundTown;
|
||||
AITown.FoundTown <- function(tile, size, city, layout, name) { return AITown.FoundTownCompat14(tile, size, city, layout, AICompat14.Text(name)); }
|
||||
|
||||
|
|
|
@ -7,6 +7,19 @@
|
|||
|
||||
/* This file contains code to downgrade the API from 15 to 14. */
|
||||
|
||||
GSDate <- GSEconomyDate;
|
||||
GSDate.IsValidDate <- function(date) { return GSDate(date).IsValid(); }
|
||||
GSDate.GetCurrentDateCompat14 <- GSDate.GetCurrentDate;
|
||||
GSDate.GetCurrentDate <- function() { return GSDate.GetCurrentDateCompat14().date(); }
|
||||
GSDate.GetYearCompat14 <- GSDate.GetYear;
|
||||
GSDate.GetYear <- function(date) { return GSDate(date).GetYearCompat14(); }
|
||||
GSDate.GetMonthCompat14 <- GSDate.GetMonth;
|
||||
GSDate.GetMonth <- function(date) { return GSDate(date).GetMonthCompat14(); }
|
||||
GSDate.GetDayOfMonthCompat14 <- GSDate.GetDayOfMonth;
|
||||
GSDate.GetDayOfMonth <- function(date) { return GSDate(date).GetDayOfMonthCompat14(); }
|
||||
GSDate.GetDateCompat14 <- GSDate.GetDate;
|
||||
GSDate.GetDate <- function(year, month, day) { return GSDate.GetDateCompat14(year, month, day).date(); }
|
||||
|
||||
GSBridge.GetBridgeID <- GSBridge.GetBridgeType;
|
||||
|
||||
/* Emulate old GSText parameter padding behaviour */
|
||||
|
@ -21,6 +34,8 @@ class GSCompat14 {
|
|||
}
|
||||
}
|
||||
|
||||
GSBaseStation.GetConstructionDateCompat14 <- GSBaseStation.GetConstructionDate;
|
||||
GSBaseStation.GetConstructionDate <- function(station_id) { return GSBaseStation.GetConstructionDateCompat14(station_id).date(); }
|
||||
GSBaseStation.SetNameCompat14 <- GSBaseStation.SetName;
|
||||
GSBaseStation.SetName <- function(id, name) { return GSBaseStation.SetNameCompat14(id, GSCompat14.Text(name)); }
|
||||
|
||||
|
@ -29,6 +44,9 @@ GSCompany.SetName <- function(name) { return GSCompany.SetNameCompat14(GSCompat1
|
|||
GSCompany.SetPresidentNameCompat14 <- GSCompany.SetPresidentName;
|
||||
GSCompany.SetPresidentName <- function(name) { return GSCompany.SetPresidentNameCompat14(GSCompat14.Text(name)); }
|
||||
|
||||
GSEngine.GetDesignDateCompat14 <- GSEngine.GetDesignDate;
|
||||
GSEngine.GetDesignDate <- function(engine_id) { return GSEngine.GetDesignDateCompat14(engine_id).date(); }
|
||||
|
||||
GSGoal.NewCompat14 <- GSGoal.New;
|
||||
GSGoal.New <- function(company, goal, type, dest) { return GSGoal.NewCompat14(company, GSCompat14.Text(goal), type, dest); }
|
||||
GSGoal.SetTextCompat14 <- GSGoal.SetText;
|
||||
|
@ -43,6 +61,10 @@ GSGoal.QuestionClient <- function(id, target, is_client, question, type, buttons
|
|||
GSGroup.SetNameCompat14 <- GSGroup.SetName;
|
||||
GSGroup.SetName <- function(id, name) { return GSGroup.SetNameCompat14(id, GSCompat14.Text(name)); }
|
||||
|
||||
GSIndustry.GetConstructionDateCompat14 <- GSIndustry.GetConstructionDate;
|
||||
GSIndustry.GetConstructionDate <- function(industry_id) { return GSIndustry.GetConstructionDateCompat14(industry_id).date(); }
|
||||
GSIndustry.GetCargoLastAcceptedDateCompat14 <- GSIndustry.GetCargoLastAcceptedDate;
|
||||
GSIndustry.GetCargoLastAcceptedDate <- function(industry_id, cargo_type) { return GSIndustry.GetCargoLastAcceptedDateCompat14(industry_id, cargo_type).date(); }
|
||||
GSIndustry.SetTextCompat14 <- GSIndustry.SetText;
|
||||
GSIndustry.SetText <- function(id, text) { return GSIndustry.SetTextCompat14(id, GSCompat14.Text(text)); }
|
||||
GSIndustry.SetProductionLevelCompat14 <- GSIndustry.SetProductionLevel;
|
||||
|
@ -63,15 +85,22 @@ GSNews.Create <- function(type, text, company, ref_type, ref) { return GSNews.Cr
|
|||
GSSign.BuildSignCompat14 <- GSSign.BuildSign;
|
||||
GSSign.BuildSign <- function(id, name) { return GSSign.BuildSignCompat14(id, GSCompat14.Text(name)); }
|
||||
|
||||
GSStoryPage.GetDateCompat14 <- GSStoryPage.GetDate;
|
||||
GSStoryPage.GetDate <- function(story_page_id) { return GSStoryPage.GetDateCompat14(story_page_id).date(); }
|
||||
GSStoryPage.NewCompat14 <- GSStoryPage.New;
|
||||
GSStoryPage.New <- function(company, title) { return GSStoryPage.NewCompat14(company, GSCompat14.Text(title)); }
|
||||
GSStoryPage.NewElementCompat14 <- GSStoryPage.NewElement;
|
||||
GSStoryPage.NewElement <- function(page, type, ref, text) { return GSStoryPage.NewElementCompat14(page, type, ref, GSCompat14.Text(text)); }
|
||||
GSStoryPage.UpdateElementCompat14 <- GSStoryPage.UpdateElement;
|
||||
GSStoryPage.UpdateElement <- function(id, ref, text) { return GSStoryPage.UpdateElementCompat14(id, ref, GSCompat14.Text(text)); }
|
||||
GSStoryPage.SetDateCompat14 <- GSStoryPage.SetDate;
|
||||
GSStoryPage.SetDate <- function(story_page_id, date) { return GSStoryPage.SetDateCompat14(story_page_id, GSCalendarDate(date)); }
|
||||
GSStoryPage.SetTitleCompat14 <- GSStoryPage.SetTitle;
|
||||
GSStoryPage.SetTitle <- function(page, tile) { return GSStoryPage.SetTitleCompat14(page, GSCompat14.Text(title)); }
|
||||
|
||||
GSSubsidy.GetExpireDateCompat14 <- GSSubsidy.GetExpireDate;
|
||||
GSSubsidy.GetExpireDate <- function(subsidy_id) { return GSSubsidy.GetExpireDateCompat14(subsidy_id).date(); }
|
||||
|
||||
GSTown.SetNameCompat14 <- GSTown.SetName;
|
||||
GSTown.SetName <- function(id, name) { return GSTown.SetNameCompat14(id, GSCompat14.Text(name)); }
|
||||
GSTown.SetTextCompat14 <- GSTown.SetText;
|
||||
|
|
|
@ -1067,6 +1067,7 @@ static uint DeliverGoodsToIndustry(const Station *st, CargoType cargo_type, uint
|
|||
|
||||
uint amount = std::min(num_pieces, 0xFFFFu - it->waiting);
|
||||
it->waiting += amount;
|
||||
it->GetOrCreateHistory()[THIS_MONTH].accepted += amount;
|
||||
it->last_accepted = TimerGameEconomy::date;
|
||||
num_pieces -= amount;
|
||||
accepted += amount;
|
||||
|
|
18
src/gfx.cpp
18
src/gfx.cpp
|
@ -580,10 +580,11 @@ static int DrawLayoutLine(const ParagraphLayouter::Line &line, int y, int left,
|
|||
|
||||
const uint shadow_offset = ScaleGUITrad(1);
|
||||
|
||||
auto draw_line = [&](const ParagraphLayouter::Line &line, bool do_shadow, int left, int min_x, int max_x, bool truncation, TextColour &last_colour) {
|
||||
auto draw_line = [&](const ParagraphLayouter::Line &line, bool do_shadow, int left, int min_x, int max_x, bool truncation, TextColour initial_colour) {
|
||||
const DrawPixelInfo *dpi = _cur_dpi;
|
||||
int dpi_left = dpi->left;
|
||||
int dpi_right = dpi->left + dpi->width - 1;
|
||||
TextColour last_colour = initial_colour;
|
||||
|
||||
for (int run_index = 0; run_index < line.CountRuns(); run_index++) {
|
||||
const ParagraphLayouter::VisualRun &run = line.GetVisualRun(run_index);
|
||||
|
@ -593,13 +594,10 @@ static int DrawLayoutLine(const ParagraphLayouter::Line &line, int y, int left,
|
|||
|
||||
FontCache *fc = f->fc;
|
||||
TextColour colour = f->colour;
|
||||
if (colour == TC_INVALID || HasFlag(last_colour, TC_FORCED)) {
|
||||
colour = last_colour;
|
||||
} else {
|
||||
/* Update the last colour for the truncation ellipsis. */
|
||||
last_colour = colour;
|
||||
}
|
||||
if (colour == TC_INVALID || HasFlag(initial_colour, TC_FORCED)) colour = initial_colour;
|
||||
bool colour_has_shadow = (colour & TC_NO_SHADE) == 0 && colour != TC_BLACK;
|
||||
/* Update the last colour for the truncation ellipsis. */
|
||||
last_colour = colour;
|
||||
if (do_shadow && (!fc->GetDrawGlyphShadow() || !colour_has_shadow)) continue;
|
||||
SetColourRemap(do_shadow ? TC_BLACK : colour);
|
||||
|
||||
|
@ -625,16 +623,16 @@ static int DrawLayoutLine(const ParagraphLayouter::Line &line, int y, int left,
|
|||
GfxMainBlitter(sprite, begin_x + (do_shadow ? shadow_offset : 0), top + (do_shadow ? shadow_offset : 0), BlitterMode::ColourRemap);
|
||||
}
|
||||
}
|
||||
return last_colour;
|
||||
};
|
||||
|
||||
/* Draw shadow, then foreground */
|
||||
for (bool do_shadow : {true, false}) {
|
||||
TextColour last_colour = default_colour;
|
||||
draw_line(line, do_shadow, left - offset_x, min_x, max_x, truncation, last_colour);
|
||||
TextColour colour = draw_line(line, do_shadow, left - offset_x, min_x, max_x, truncation, default_colour);
|
||||
|
||||
if (truncation) {
|
||||
int x = (_current_text_dir == TD_RTL) ? left : (right - truncation_width);
|
||||
draw_line(*truncation_layout->front(), do_shadow, x, INT32_MIN, INT32_MAX, false, last_colour);
|
||||
draw_line(*truncation_layout->front(), do_shadow, x, INT32_MIN, INT32_MAX, false, colour);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -182,8 +182,9 @@ protected:
|
|||
static const int MIN_GRAPH_NUM_LINES_Y = 9; ///< Minimal number of horizontal lines to draw.
|
||||
static const int MIN_GRID_PIXEL_SIZE = 20; ///< Minimum distance between graph lines.
|
||||
|
||||
uint64_t excluded_data = 0; ///< bitmask of the datasets that shouldn't be displayed.
|
||||
uint64_t excluded_range = 0; ///< bitmask of ranges that should not be displayed.
|
||||
uint64_t excluded_data = 0; ///< bitmask of datasets hidden by the player.
|
||||
uint64_t excluded_range = 0; ///< bitmask of ranges hidden by the player.
|
||||
uint64_t masked_range = 0; ///< bitmask of ranges that are not available for the current data.
|
||||
uint8_t num_on_x_axis = 0;
|
||||
uint8_t num_vert_lines = GRAPH_NUM_MONTHS;
|
||||
|
||||
|
@ -216,13 +217,20 @@ protected:
|
|||
uint8_t highlight_range = UINT8_MAX; ///< Data range that should be highlighted, or UINT8_MAX for none.
|
||||
bool highlight_state = false; ///< Current state of highlight, toggled every TIMER_BLINK_INTERVAL period.
|
||||
|
||||
template <typename Tprojection>
|
||||
struct Filler {
|
||||
struct BaseFiller {
|
||||
DataSet &dataset; ///< Dataset to fill.
|
||||
|
||||
inline void MakeZero(uint i) const { this->dataset.values[i] = 0; }
|
||||
inline void MakeInvalid(uint i) const { this->dataset.values[i] = INVALID_DATAPOINT; }
|
||||
};
|
||||
|
||||
template <typename Tprojection>
|
||||
struct Filler : BaseFiller {
|
||||
const Tprojection &proj; ///< Projection to apply.
|
||||
|
||||
constexpr Filler(DataSet &dataset, const Tprojection &proj) : BaseFiller(dataset), proj(proj) {}
|
||||
|
||||
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; }
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -675,13 +683,17 @@ public:
|
|||
uint index = 0;
|
||||
Rect line = r.WithHeight(line_height);
|
||||
for (const auto &str : this->ranges) {
|
||||
bool lowered = !HasBit(this->excluded_range, index);
|
||||
bool lowered = !HasBit(this->excluded_range, index) && !HasBit(this->masked_range, index);
|
||||
|
||||
/* Redraw frame if lowered */
|
||||
if (lowered) DrawFrameRect(line, COLOUR_BROWN, FrameFlag::Lowered);
|
||||
|
||||
const Rect text = line.Shrink(WidgetDimensions::scaled.framerect);
|
||||
DrawString(text, str, TC_BLACK, SA_CENTER, false, FS_SMALL);
|
||||
DrawString(text, str, (this->highlight_state && this->highlight_range == index) ? TC_WHITE : TC_BLACK, SA_CENTER, false, FS_SMALL);
|
||||
|
||||
if (HasBit(this->masked_range, index)) {
|
||||
GfxFillRect(line.Shrink(WidgetDimensions::scaled.bevel), GetColourGradient(COLOUR_BROWN, SHADE_DARKER), FILLRECT_CHECKER);
|
||||
}
|
||||
|
||||
line = line.Translate(0, line_height);
|
||||
++index;
|
||||
|
@ -704,6 +716,7 @@ public:
|
|||
case WID_GRAPH_RANGE_MATRIX: {
|
||||
int row = GetRowFromWidget(pt.y, widget, 0, GetCharacterHeight(FS_SMALL) + WidgetDimensions::scaled.framerect.Vertical());
|
||||
|
||||
if (HasBit(this->masked_range, row)) break;
|
||||
ToggleBit(this->excluded_range, row);
|
||||
this->SetDirty();
|
||||
break;
|
||||
|
@ -1115,6 +1128,7 @@ struct BaseCargoGraphWindow : BaseGraphWindow {
|
|||
{
|
||||
this->CreateNestedTree();
|
||||
|
||||
this->excluded_range = this->masked_range;
|
||||
this->cargo_types = this->GetCargoTypes(number);
|
||||
|
||||
this->vscroll = this->GetScrollbar(WID_GRAPH_MATRIX_SCROLLBAR);
|
||||
|
@ -1608,7 +1622,9 @@ CompanyID PerformanceRatingDetailWindow::company = CompanyID::Invalid();
|
|||
struct IndustryProductionGraphWindow : BaseCargoGraphWindow {
|
||||
static inline constexpr StringID RANGE_LABELS[] = {
|
||||
STR_GRAPH_INDUSTRY_RANGE_PRODUCED,
|
||||
STR_GRAPH_INDUSTRY_RANGE_TRANSPORTED
|
||||
STR_GRAPH_INDUSTRY_RANGE_TRANSPORTED,
|
||||
STR_GRAPH_INDUSTRY_RANGE_DELIVERED,
|
||||
STR_GRAPH_INDUSTRY_RANGE_WAITING,
|
||||
};
|
||||
|
||||
static inline CargoTypes excluded_cargo_types{};
|
||||
|
@ -1623,6 +1639,10 @@ struct IndustryProductionGraphWindow : BaseCargoGraphWindow {
|
|||
this->draw_dates = !TimerGameEconomy::UsingWallclockUnits();
|
||||
this->ranges = RANGE_LABELS;
|
||||
|
||||
const Industry *i = Industry::Get(window_number);
|
||||
if (!i->IsCargoProduced()) this->masked_range = (1U << 0) | (1U << 1);
|
||||
if (!i->IsCargoAccepted()) this->masked_range = (1U << 2) | (1U << 3);
|
||||
|
||||
this->InitializeWindow(window_number, STR_GRAPH_LAST_24_MINUTES_TIME_LABEL);
|
||||
}
|
||||
|
||||
|
@ -1630,6 +1650,9 @@ struct IndustryProductionGraphWindow : BaseCargoGraphWindow {
|
|||
{
|
||||
CargoTypes cargo_types{};
|
||||
const Industry *i = Industry::Get(window_number);
|
||||
for (const auto &a : i->accepted) {
|
||||
if (IsValidCargoType(a.cargo)) SetBit(cargo_types, a.cargo);
|
||||
}
|
||||
for (const auto &p : i->produced) {
|
||||
if (IsValidCargoType(p.cargo)) SetBit(cargo_types, p.cargo);
|
||||
}
|
||||
|
@ -1643,7 +1666,7 @@ struct IndustryProductionGraphWindow : BaseCargoGraphWindow {
|
|||
|
||||
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
|
||||
{
|
||||
if (widget == WID_GRAPH_CAPTION) return GetString(STR_GRAPH_INDUSTRY_PRODUCTION_CAPTION, this->window_number);
|
||||
if (widget == WID_GRAPH_CAPTION) return GetString(STR_GRAPH_INDUSTRY_CAPTION, this->window_number);
|
||||
|
||||
return this->Window::GetWidgetString(widget, stringid);
|
||||
}
|
||||
|
@ -1691,6 +1714,33 @@ struct IndustryProductionGraphWindow : BaseCargoGraphWindow {
|
|||
FillFromHistory<GRAPH_NUM_MONTHS>(p.history, i->valid_history, produced_filler, transported_filler);
|
||||
}
|
||||
|
||||
for (const auto &a : i->accepted) {
|
||||
if (!IsValidCargoType(a.cargo)) continue;
|
||||
const CargoSpec *cs = CargoSpec::Get(a.cargo);
|
||||
|
||||
this->data.reserve(this->data.size() + 2);
|
||||
|
||||
DataSet &accepted = this->data.emplace_back();
|
||||
accepted.colour = cs->legend_colour;
|
||||
accepted.exclude_bit = cs->Index();
|
||||
accepted.range_bit = 2;
|
||||
accepted.dash = 1;
|
||||
auto accepted_filler = Filler{accepted, &Industry::AcceptedHistory::accepted};
|
||||
|
||||
DataSet &waiting = this->data.emplace_back();
|
||||
waiting.colour = cs->legend_colour;
|
||||
waiting.exclude_bit = cs->Index();
|
||||
waiting.range_bit = 3;
|
||||
waiting.dash = 4;
|
||||
auto waiting_filler = Filler{waiting, &Industry::AcceptedHistory::waiting};
|
||||
|
||||
if (a.history == nullptr) {
|
||||
FillFromEmpty<GRAPH_NUM_MONTHS>(i->valid_history, accepted_filler, waiting_filler);
|
||||
} else {
|
||||
FillFromHistory<GRAPH_NUM_MONTHS>(*a.history, i->valid_history, accepted_filler, waiting_filler);
|
||||
}
|
||||
}
|
||||
|
||||
this->SetDirty();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -77,10 +77,27 @@ struct Industry : IndustryPool::PoolItem<&_industry_pool> {
|
|||
HistoryData<ProducedHistory> history{}; ///< History of cargo produced and transported for this month and 24 previous months
|
||||
};
|
||||
|
||||
struct AcceptedHistory {
|
||||
uint16_t accepted = 0; /// Total accepted.
|
||||
uint16_t waiting = 0; /// Average waiting.
|
||||
};
|
||||
|
||||
struct AcceptedCargo {
|
||||
CargoType cargo = 0; ///< Cargo type
|
||||
uint16_t waiting = 0; ///< Amount of cargo waiting to processed
|
||||
uint32_t accumulated_waiting = 0; ///< Accumulated waiting total over the last month, used to calculate average.
|
||||
TimerGameEconomy::Date last_accepted{}; ///< Last day cargo was accepted by this industry
|
||||
std::unique_ptr<HistoryData<AcceptedHistory>> history{}; ///< History of accepted and waiting cargo.
|
||||
|
||||
/**
|
||||
* Get history data, creating it if necessary.
|
||||
* @return Accepted history data.
|
||||
*/
|
||||
inline HistoryData<AcceptedHistory> &GetOrCreateHistory()
|
||||
{
|
||||
if (this->history == nullptr) this->history = std::make_unique<HistoryData<AcceptedHistory>>();
|
||||
return *this->history;
|
||||
}
|
||||
};
|
||||
|
||||
using ProducedCargoes = std::vector<ProducedCargo>;
|
||||
|
@ -151,7 +168,7 @@ struct Industry : IndustryPool::PoolItem<&_industry_pool> {
|
|||
*/
|
||||
inline const AcceptedCargo &GetAccepted(size_t slot) const
|
||||
{
|
||||
static const AcceptedCargo empty{INVALID_CARGO, 0, {}};
|
||||
static const AcceptedCargo empty{INVALID_CARGO, 0, 0, {}, {}};
|
||||
return slot < this->accepted.size() ? this->accepted[slot] : empty;
|
||||
}
|
||||
|
||||
|
|
|
@ -1245,6 +1245,10 @@ void OnTick_Industry()
|
|||
|
||||
for (Industry *i : Industry::Iterate()) {
|
||||
ProduceIndustryGoods(i);
|
||||
|
||||
if ((TimerGameTick::counter + i->index) % Ticks::DAY_TICKS == 0) {
|
||||
for (auto &a : i->accepted) a.accumulated_waiting += a.waiting;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2505,6 +2509,14 @@ static void UpdateIndustryStatistics(Industry *i)
|
|||
RotateHistory(p.history);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &a : i->accepted) {
|
||||
if (!IsValidCargoType(a.cargo)) continue;
|
||||
if (a.history == nullptr) continue;
|
||||
|
||||
(*a.history)[THIS_MONTH].waiting = GetAndResetAccumulatedAverage<uint16_t>(a.accumulated_waiting);
|
||||
RotateHistory(*a.history);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -27,6 +27,4 @@ DEF_CMD_TRAIT(CMD_INDUSTRY_SET_EXCLUSIVITY, CmdIndustrySetExclusivity, CommandFl
|
|||
DEF_CMD_TRAIT(CMD_INDUSTRY_SET_TEXT, CmdIndustrySetText, CommandFlags({CommandFlag::Deity, CommandFlag::StrCtrl}), CMDT_OTHER_MANAGEMENT)
|
||||
DEF_CMD_TRAIT(CMD_INDUSTRY_SET_PRODUCTION, CmdIndustrySetProduction, CommandFlag::Deity, CMDT_OTHER_MANAGEMENT)
|
||||
|
||||
void CcBuildIndustry(Commands cmd, const CommandCost &result, TileIndex tile, IndustryType indtype, uint32_t, bool, uint32_t);
|
||||
|
||||
#endif /* INDUSTRY_CMD_H */
|
||||
|
|
|
@ -257,25 +257,6 @@ void SortIndustryTypes()
|
|||
std::sort(_sorted_industry_types.begin(), _sorted_industry_types.end(), IndustryTypeNameSorter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Command callback. In case of failure to build an industry, show an error message.
|
||||
* @param result Result of the command.
|
||||
* @param tile Tile where the industry is placed.
|
||||
* @param indtype Industry type.
|
||||
*/
|
||||
void CcBuildIndustry(Commands, const CommandCost &result, TileIndex tile, IndustryType indtype, uint32_t, bool, uint32_t)
|
||||
{
|
||||
if (result.Succeeded()) return;
|
||||
|
||||
if (indtype < NUM_INDUSTRYTYPES) {
|
||||
const IndustrySpec *indsp = GetIndustrySpec(indtype);
|
||||
if (indsp->enabled) {
|
||||
ShowErrorMessage(GetEncodedString(STR_ERROR_CAN_T_BUILD_HERE, indsp->name),
|
||||
GetEncodedString(result.GetErrorMessage()), WL_INFO, TileX(tile) * TILE_SIZE, TileY(tile) * TILE_SIZE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr NWidgetPart _nested_build_industry_widgets[] = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
|
||||
|
@ -745,7 +726,7 @@ public:
|
|||
AutoRestoreBackup backup_generating_world(_generating_world, true);
|
||||
AutoRestoreBackup backup_ignore_industry_restritions(_ignore_industry_restrictions, true);
|
||||
|
||||
Command<CMD_BUILD_INDUSTRY>::Post(STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY, &CcBuildIndustry, tile, this->selected_type, layout_index, false, seed);
|
||||
Command<CMD_BUILD_INDUSTRY>::Post(STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY, tile, this->selected_type, layout_index, false, seed);
|
||||
} else {
|
||||
success = Command<CMD_BUILD_INDUSTRY>::Post(STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY, tile, this->selected_type, layout_index, false, seed);
|
||||
}
|
||||
|
@ -845,7 +826,7 @@ public:
|
|||
nvp->InitializeViewport(this, Industry::Get(window_number)->location.GetCenterTile(), ScaleZoomGUI(ZoomLevel::Industry));
|
||||
|
||||
const Industry *i = Industry::Get(window_number);
|
||||
if (!i->IsCargoProduced()) this->DisableWidget(WID_IV_GRAPH);
|
||||
if (!i->IsCargoProduced() && !i->IsCargoAccepted()) this->DisableWidget(WID_IV_GRAPH);
|
||||
|
||||
this->InvalidateData();
|
||||
}
|
||||
|
@ -1242,7 +1223,7 @@ static constexpr NWidgetPart _nested_industry_view_widgets[] = {
|
|||
EndContainer(),
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_CREAM, WID_IV_DISPLAY), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_INDUSTRY_DISPLAY_CHAIN, STR_INDUSTRY_DISPLAY_CHAIN_TOOLTIP),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_CREAM, WID_IV_GRAPH), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_INDUSTRY_VIEW_PRODUCTION_GRAPH, STR_INDUSTRY_VIEW_PRODUCTION_GRAPH_TOOLTIP),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_CREAM, WID_IV_GRAPH), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_INDUSTRY_VIEW_CARGO_GRAPH, STR_INDUSTRY_VIEW_CARGO_GRAPH_TOOLTIP),
|
||||
NWidget(WWT_RESIZEBOX, COLOUR_CREAM),
|
||||
EndContainer(),
|
||||
};
|
||||
|
|
|
@ -634,9 +634,11 @@ STR_GRAPH_CARGO_TOOLTIP_DISABLE_ALL :{BLACK}Display
|
|||
STR_GRAPH_CARGO_PAYMENT_TOGGLE_CARGO :{BLACK}Toggle graph of this cargo type
|
||||
STR_GRAPH_CARGO_PAYMENT_CARGO :{TINY_FONT}{BLACK}{STRING}
|
||||
|
||||
STR_GRAPH_INDUSTRY_PRODUCTION_CAPTION :{WHITE}{INDUSTRY} - Production History
|
||||
STR_GRAPH_INDUSTRY_CAPTION :{WHITE}{INDUSTRY} - Cargo History
|
||||
STR_GRAPH_INDUSTRY_RANGE_PRODUCED :Produced
|
||||
STR_GRAPH_INDUSTRY_RANGE_TRANSPORTED :Transported
|
||||
STR_GRAPH_INDUSTRY_RANGE_DELIVERED :Delivered
|
||||
STR_GRAPH_INDUSTRY_RANGE_WAITING :Waiting
|
||||
|
||||
STR_GRAPH_PERFORMANCE_DETAIL_TOOLTIP :{BLACK}Show detailed performance ratings
|
||||
|
||||
|
@ -4024,8 +4026,8 @@ STR_INDUSTRY_VIEW_PRODUCTION_LAST_MONTH_TITLE :{BLACK}Producti
|
|||
STR_INDUSTRY_VIEW_PRODUCTION_LAST_MINUTE_TITLE :{BLACK}Production last minute:
|
||||
STR_INDUSTRY_VIEW_TRANSPORTED :{YELLOW}{CARGO_LONG}{RAW_STRING}{BLACK} ({COMMA}% transported)
|
||||
STR_INDUSTRY_VIEW_LOCATION_TOOLTIP :{BLACK}Centre the main view on industry location. Ctrl+Click to open a new viewport on industry location
|
||||
STR_INDUSTRY_VIEW_PRODUCTION_GRAPH :{BLACK}Production Graph
|
||||
STR_INDUSTRY_VIEW_PRODUCTION_GRAPH_TOOLTIP :{BLACK}Shows the graph of industry production history
|
||||
STR_INDUSTRY_VIEW_CARGO_GRAPH :{BLACK}Cargo Graph
|
||||
STR_INDUSTRY_VIEW_CARGO_GRAPH_TOOLTIP :{BLACK}Shows the graph of industry cargo history
|
||||
STR_INDUSTRY_VIEW_PRODUCTION_LEVEL :{BLACK}Production level: {YELLOW}{COMMA}%
|
||||
STR_INDUSTRY_VIEW_INDUSTRY_ANNOUNCED_CLOSURE :{YELLOW}The industry has announced imminent closure!
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
#define HISTORY_FUNC_HPP
|
||||
|
||||
#include "../core/bitmath_func.hpp"
|
||||
#include "../core/math_func.hpp"
|
||||
#include "../timer/timer_game_economy.h"
|
||||
#include "history_type.hpp"
|
||||
|
||||
/**
|
||||
|
@ -34,6 +36,19 @@ void RotateHistory(HistoryData<T> &history)
|
|||
history[THIS_MONTH] = {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an average value for the previous month, as reset for the next month.
|
||||
* @param total Accrued total to average. Will be reset to zero.
|
||||
* @return Average value for the month.
|
||||
*/
|
||||
template <typename T, typename Taccrued>
|
||||
T GetAndResetAccumulatedAverage(Taccrued &total)
|
||||
{
|
||||
T result = ClampTo<T>(total / std::max(1U, TimerGameEconomy::days_since_last_month));
|
||||
total = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill some data with historical data.
|
||||
* @param history Historical data to fill from.
|
||||
|
@ -53,4 +68,21 @@ void FillFromHistory(const HistoryData<T> &history, ValidHistoryMask valid_histo
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill some data with empty records.
|
||||
* @param valid_history Mask of valid history records.
|
||||
* @param fillers Fillers to fill with history data.
|
||||
*/
|
||||
template <uint N, typename... Tfillers>
|
||||
void FillFromEmpty(ValidHistoryMask valid_history, Tfillers... fillers)
|
||||
{
|
||||
for (uint i = 0; i != N; ++i) {
|
||||
if (HasBit(valid_history, N - i)) {
|
||||
(fillers.MakeZero(i), ...);
|
||||
} else {
|
||||
(fillers.MakeInvalid(i), ...);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HISTORY_FUNC_HPP */
|
||||
|
|
|
@ -79,7 +79,6 @@ static constexpr auto _callback_tuple = std::make_tuple(
|
|||
&CcCreateGroup,
|
||||
&CcFoundRandomTown,
|
||||
&CcRoadStop,
|
||||
&CcBuildIndustry,
|
||||
&CcStartStopVehicle,
|
||||
&CcGame,
|
||||
&CcAddVehicleNewGroup
|
||||
|
|
|
@ -19,12 +19,50 @@
|
|||
|
||||
static OldPersistentStorage _old_ind_persistent_storage;
|
||||
|
||||
class SlIndustryAcceptedHistory : public DefaultSaveLoadHandler<SlIndustryAcceptedHistory, Industry::AcceptedCargo> {
|
||||
public:
|
||||
static inline const SaveLoad description[] = {
|
||||
SLE_VAR(Industry::AcceptedHistory, accepted, SLE_UINT16),
|
||||
SLE_VAR(Industry::AcceptedHistory, waiting, SLE_UINT16),
|
||||
};
|
||||
static inline const SaveLoadCompatTable compat_description = _industry_produced_history_sl_compat;
|
||||
|
||||
void Save(Industry::AcceptedCargo *a) const override
|
||||
{
|
||||
if (!IsValidCargoType(a->cargo) || a->history == nullptr) {
|
||||
/* Don't save any history if cargo slot isn't used. */
|
||||
SlSetStructListLength(0);
|
||||
return;
|
||||
}
|
||||
|
||||
SlSetStructListLength(a->history->size());
|
||||
|
||||
for (auto &h : *a->history) {
|
||||
SlObject(&h, this->GetDescription());
|
||||
}
|
||||
}
|
||||
|
||||
void Load(Industry::AcceptedCargo *a) const override
|
||||
{
|
||||
size_t len = SlGetStructListLength(UINT32_MAX);
|
||||
if (len == 0) return;
|
||||
|
||||
auto &history = a->GetOrCreateHistory();
|
||||
for (auto &h : history) {
|
||||
if (--len > history.size()) break; // unsigned so wraps after hitting zero.
|
||||
SlObject(&h, this->GetDescription());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class SlIndustryAccepted : public VectorSaveLoadHandler<SlIndustryAccepted, Industry, Industry::AcceptedCargo, INDUSTRY_NUM_INPUTS> {
|
||||
public:
|
||||
static inline 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),
|
||||
SLE_CONDVAR(Industry::AcceptedCargo, accumulated_waiting, SLE_UINT32, SLV_INDUSTRY_ACCEPTED_HISTORY, SL_MAX_VERSION),
|
||||
SLEG_CONDSTRUCTLIST("history", SlIndustryAcceptedHistory, SLV_INDUSTRY_ACCEPTED_HISTORY, SL_MAX_VERSION),
|
||||
};
|
||||
static inline const SaveLoadCompatTable compat_description = _industry_accepts_sl_compat;
|
||||
|
||||
|
|
|
@ -858,7 +858,7 @@ static bool LoadOldIndustry(LoadgameState &ls, int num)
|
|||
|
||||
if (i->location.tile != 0) {
|
||||
/* Copy data from old fixed arrays to industry. */
|
||||
std::copy(std::begin(_old_accepted), std::end(_old_accepted), std::back_inserter(i->accepted));
|
||||
std::move(std::begin(_old_accepted), std::end(_old_accepted), std::back_inserter(i->accepted));
|
||||
std::copy(std::begin(_old_produced), std::end(_old_produced), std::back_inserter(i->produced));
|
||||
|
||||
i->town = RemapTown(i->location.tile);
|
||||
|
|
|
@ -405,6 +405,7 @@ enum SaveLoadVersion : uint16_t {
|
|||
|
||||
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.
|
||||
SLV_INDUSTRY_ACCEPTED_HISTORY, ///< 357 PR#14321 Add per-industry history of cargo delivered and waiting.
|
||||
|
||||
SL_MAX_VERSION, ///< Highest possible saveload version
|
||||
};
|
||||
|
|
|
@ -40,13 +40,15 @@ foreach(API "ai;AI" "game;GS" "template;Template")
|
|||
list(GET API 1 APIUC)
|
||||
|
||||
foreach(SCRIPT_API_FILE IN LISTS SCRIPT_API_FILES)
|
||||
if("${SCRIPT_API_FILE}" MATCHES ".*script_controller.*")
|
||||
continue()
|
||||
endif()
|
||||
get_filename_component(SCRIPT_API_FILE_NAME "${SCRIPT_API_FILE}" NAME_WE)
|
||||
string(REPLACE "script_" "${APILC}_" SCRIPT_API_FILE_NAME "${SCRIPT_API_FILE_NAME}")
|
||||
set(SCRIPT_API_BINARY_FILE "${CMAKE_BINARY_DIR}/generated/script/api/${APILC}/${SCRIPT_API_FILE_NAME}.sq.hpp")
|
||||
|
||||
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${APILC}/${SCRIPT_API_FILE_NAME}.sq.hpp")
|
||||
file(REMOVE "${SCRIPT_API_BINARY_FILE}")
|
||||
continue()
|
||||
endif()
|
||||
|
||||
add_custom_command_timestamp(OUTPUT ${SCRIPT_API_BINARY_FILE}
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DSCRIPT_API_SOURCE_FILE=${CMAKE_CURRENT_SOURCE_DIR}/squirrel_export.sq.hpp.in
|
||||
|
@ -74,6 +76,7 @@ foreach(API "ai;AI" "game;GS" "template;Template")
|
|||
|
||||
if(NOT "${APILC}" STREQUAL "template")
|
||||
list(APPEND SCRIPT_${APIUC}_BINARY_FILES "${CMAKE_CURRENT_SOURCE_DIR}/${APILC}/${APILC}_controller.sq.hpp")
|
||||
list(APPEND SCRIPT_${APIUC}_BINARY_FILES "${CMAKE_CURRENT_SOURCE_DIR}/${APILC}/${APILC}_date.sq.hpp")
|
||||
set(INCLUDES_BINARY_FILE "${CMAKE_BINARY_DIR}/generated/script/api/${APILC}/${APILC}_includes.hpp")
|
||||
set(API_FILES "${CMAKE_CURRENT_BINARY_DIR}/${APILC}.files")
|
||||
file(GENERATE OUTPUT ${API_FILES} CONTENT "${SCRIPT_${APIUC}_BINARY_FILES}")
|
||||
|
@ -120,6 +123,7 @@ foreach(API "ai;AI" "game;GS" "template;Template")
|
|||
)
|
||||
endif()
|
||||
else()
|
||||
list(APPEND SCRIPT_Template_BINARY_FILES "${CMAKE_CURRENT_SOURCE_DIR}/template/template_date.sq.hpp")
|
||||
add_dependencies(script_api
|
||||
script_${APILC}
|
||||
)
|
||||
|
@ -233,7 +237,6 @@ add_files(
|
|||
script_company.cpp
|
||||
script_companymode.cpp
|
||||
script_controller.cpp
|
||||
script_date.cpp
|
||||
script_depotlist.cpp
|
||||
script_engine.cpp
|
||||
script_enginelist.cpp
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../script_date.hpp"
|
||||
#include "../template/template_date.sq.hpp"
|
||||
|
||||
|
||||
template <> SQInteger PushClassName<ScriptEconomyDate, ScriptType::AI>(HSQUIRRELVM vm) { sq_pushstring(vm, "AIEconomyDate"); return 1; }
|
||||
template <> SQInteger PushClassName<ScriptCalendarDate, ScriptType::AI>(HSQUIRRELVM vm) { sq_pushstring(vm, "AICalendarDate"); return 1; }
|
||||
|
||||
void SQAIDate_Register(Squirrel &engine)
|
||||
{
|
||||
DefSQClass<ScriptEconomyDate, ScriptType::AI> SQAIEconomyDate("AIEconomyDate");
|
||||
SQAIEconomyDate.PreRegister(engine, "AIObject");
|
||||
SQAIEconomyDate.AddSQAdvancedConstructor(engine);
|
||||
|
||||
SQAIEconomyDate.DefSQConst(engine, ScriptEconomyDate::DATE_INVALID, "DATE_INVALID");
|
||||
|
||||
SQAIEconomyDate.DefSQStaticMethod(engine, &ScriptEconomyDate::GetCurrentDate, "GetCurrentDate", ".");
|
||||
SQAIEconomyDate.DefSQStaticMethod(engine, &ScriptEconomyDate::GetDate, "GetDate", ".iii");
|
||||
|
||||
SQAIEconomyDate.DefSQMethod(engine, &ScriptEconomyDate::IsValid, "IsValid", ".");
|
||||
SQAIEconomyDate.DefSQMethod(engine, &ScriptEconomyDate::GetYear, "GetYear", ".");
|
||||
SQAIEconomyDate.DefSQMethod(engine, &ScriptEconomyDate::GetMonth, "GetMonth", ".");
|
||||
SQAIEconomyDate.DefSQMethod(engine, &ScriptEconomyDate::GetDayOfMonth, "GetDayOfMonth", ".");
|
||||
SQAIEconomyDate.DefSQMethod(engine, &ScriptEconomyDate::date, "date", ".");
|
||||
|
||||
SQAIEconomyDate.DefSQAdvancedMethod(engine, &ScriptEconomyDate::_tostring, "_tostring");
|
||||
SQAIEconomyDate.DefSQAdvancedMethod(engine, &ScriptEconomyDate::_add, "_add");
|
||||
SQAIEconomyDate.DefSQAdvancedMethod(engine, &ScriptEconomyDate::_sub, "_sub");
|
||||
SQAIEconomyDate.DefSQAdvancedMethod(engine, &ScriptEconomyDate::_cmp, "_cmp");
|
||||
|
||||
SQAIEconomyDate.PostRegister(engine);
|
||||
|
||||
|
||||
DefSQClass<ScriptCalendarDate, ScriptType::AI> SQAICalendarDate("AICalendarDate");
|
||||
SQAICalendarDate.PreRegister(engine, "AIObject");
|
||||
SQAICalendarDate.AddSQAdvancedConstructor(engine);
|
||||
|
||||
SQAICalendarDate.DefSQConst(engine, ScriptCalendarDate::DATE_INVALID, "DATE_INVALID");
|
||||
|
||||
SQAICalendarDate.DefSQStaticMethod(engine, &ScriptCalendarDate::GetCurrentDate, "GetCurrentDate", ".");
|
||||
SQAICalendarDate.DefSQStaticMethod(engine, &ScriptCalendarDate::GetDate, "GetDate", ".iii");
|
||||
|
||||
SQAICalendarDate.DefSQMethod(engine, &ScriptCalendarDate::IsValid, "IsValid", ".");
|
||||
SQAICalendarDate.DefSQMethod(engine, &ScriptCalendarDate::GetYear, "GetYear", ".");
|
||||
SQAICalendarDate.DefSQMethod(engine, &ScriptCalendarDate::GetMonth, "GetMonth", ".");
|
||||
SQAICalendarDate.DefSQMethod(engine, &ScriptCalendarDate::GetDayOfMonth, "GetDayOfMonth", ".");
|
||||
SQAICalendarDate.DefSQMethod(engine, &ScriptCalendarDate::date, "date", ".");
|
||||
|
||||
SQAICalendarDate.DefSQAdvancedMethod(engine, &ScriptCalendarDate::_tostring, "_tostring");
|
||||
SQAICalendarDate.DefSQAdvancedMethod(engine, &ScriptCalendarDate::_add, "_add");
|
||||
SQAICalendarDate.DefSQAdvancedMethod(engine, &ScriptCalendarDate::_sub, "_sub");
|
||||
SQAICalendarDate.DefSQAdvancedMethod(engine, &ScriptCalendarDate::_cmp, "_cmp");
|
||||
|
||||
SQAICalendarDate.PostRegister(engine);
|
||||
|
||||
}
|
|
@ -28,6 +28,11 @@
|
|||
* \li AICargo::CC_POTABLE
|
||||
* \li AICargo::CC_NON_POTABLE
|
||||
* \li AIVehicleList_Waypoint
|
||||
* \li AIEconomyDate
|
||||
* \li AICalendarDate
|
||||
*
|
||||
* API removals:
|
||||
* \li AIDate
|
||||
*
|
||||
* Other changes:
|
||||
* \li AIBridge::GetBridgeID renamed to AIBridge::GetBridgeType
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../script_date.hpp"
|
||||
#include "../template/template_date.sq.hpp"
|
||||
|
||||
template <> SQInteger PushClassName<ScriptEconomyDate, ScriptType::GS>(HSQUIRRELVM vm) { sq_pushstring(vm, "GSEconomyDate"); return 1; }
|
||||
template <> SQInteger PushClassName<ScriptCalendarDate, ScriptType::GS>(HSQUIRRELVM vm) { sq_pushstring(vm, "GSCalendarDate"); return 1; }
|
||||
|
||||
void SQGSDate_Register(Squirrel &engine)
|
||||
{
|
||||
DefSQClass<ScriptEconomyDate, ScriptType::GS> SQGSEconomyDate("GSEconomyDate");
|
||||
SQGSEconomyDate.PreRegister(engine, "GSObject");
|
||||
SQGSEconomyDate.AddSQAdvancedConstructor(engine);
|
||||
|
||||
SQGSEconomyDate.DefSQConst(engine, ScriptEconomyDate::DATE_INVALID, "DATE_INVALID");
|
||||
|
||||
SQGSEconomyDate.DefSQStaticMethod(engine, &ScriptEconomyDate::GetCurrentDate, "GetCurrentDate", ".");
|
||||
SQGSEconomyDate.DefSQStaticMethod(engine, &ScriptEconomyDate::GetDate, "GetDate", ".iii");
|
||||
SQGSEconomyDate.DefSQStaticMethod(engine, &ScriptEconomyDate::GetSystemTime, "GetSystemTime", ".");
|
||||
|
||||
SQGSEconomyDate.DefSQMethod(engine, &ScriptEconomyDate::IsValid, "IsValid", ".");
|
||||
SQGSEconomyDate.DefSQMethod(engine, &ScriptEconomyDate::GetYear, "GetYear", ".");
|
||||
SQGSEconomyDate.DefSQMethod(engine, &ScriptEconomyDate::GetMonth, "GetMonth", ".");
|
||||
SQGSEconomyDate.DefSQMethod(engine, &ScriptEconomyDate::GetDayOfMonth, "GetDayOfMonth", ".");
|
||||
SQGSEconomyDate.DefSQMethod(engine, &ScriptEconomyDate::date, "date", ".");
|
||||
|
||||
SQGSEconomyDate.DefSQAdvancedMethod(engine, &ScriptEconomyDate::_tostring, "_tostring");
|
||||
SQGSEconomyDate.DefSQAdvancedMethod(engine, &ScriptEconomyDate::_add, "_add");
|
||||
SQGSEconomyDate.DefSQAdvancedMethod(engine, &ScriptEconomyDate::_sub, "_sub");
|
||||
SQGSEconomyDate.DefSQAdvancedMethod(engine, &ScriptEconomyDate::_cmp, "_cmp");
|
||||
|
||||
SQGSEconomyDate.PostRegister(engine);
|
||||
|
||||
|
||||
DefSQClass<ScriptCalendarDate, ScriptType::GS> SQGSCalendarDate("GSCalendarDate");
|
||||
SQGSCalendarDate.PreRegister(engine, "GSObject");
|
||||
SQGSCalendarDate.AddSQAdvancedConstructor(engine);
|
||||
|
||||
SQGSCalendarDate.DefSQConst(engine, ScriptCalendarDate::DATE_INVALID, "DATE_INVALID");
|
||||
|
||||
SQGSCalendarDate.DefSQStaticMethod(engine, &ScriptCalendarDate::GetCurrentDate, "GetCurrentDate", ".");
|
||||
SQGSCalendarDate.DefSQStaticMethod(engine, &ScriptCalendarDate::GetDate, "GetDate", ".iii");
|
||||
SQGSCalendarDate.DefSQStaticMethod(engine, &ScriptCalendarDate::GetSystemTime, "GetSystemTime", ".");
|
||||
|
||||
SQGSCalendarDate.DefSQMethod(engine, &ScriptCalendarDate::IsValid, "IsValid", ".");
|
||||
SQGSCalendarDate.DefSQMethod(engine, &ScriptCalendarDate::GetYear, "GetYear", ".");
|
||||
SQGSCalendarDate.DefSQMethod(engine, &ScriptCalendarDate::GetMonth, "GetMonth", ".");
|
||||
SQGSCalendarDate.DefSQMethod(engine, &ScriptCalendarDate::GetDayOfMonth, "GetDayOfMonth", ".");
|
||||
SQGSCalendarDate.DefSQMethod(engine, &ScriptCalendarDate::date, "date", ".");
|
||||
|
||||
SQGSCalendarDate.DefSQAdvancedMethod(engine, &ScriptCalendarDate::_tostring, "_tostring");
|
||||
SQGSCalendarDate.DefSQAdvancedMethod(engine, &ScriptCalendarDate::_add, "_add");
|
||||
SQGSCalendarDate.DefSQAdvancedMethod(engine, &ScriptCalendarDate::_sub, "_sub");
|
||||
SQGSCalendarDate.DefSQAdvancedMethod(engine, &ScriptCalendarDate::_cmp, "_cmp");
|
||||
|
||||
SQGSCalendarDate.PostRegister(engine);
|
||||
}
|
|
@ -29,6 +29,11 @@
|
|||
* \li GSCargo::CC_NON_POTABLE
|
||||
* \li GSVehicleList_Waypoint
|
||||
* \li GSBaseStation::GetOwner
|
||||
* \li GSEconomyDate
|
||||
* \li GSCalendarDate
|
||||
*
|
||||
* API removals:
|
||||
* \li GSDate
|
||||
*
|
||||
* Other changes:
|
||||
* \li GSBridge::GetBridgeID renamed to GSBridge::GetBridgeType
|
||||
|
|
|
@ -66,9 +66,9 @@
|
|||
return ::BaseStation::Get(station_id)->xy;
|
||||
}
|
||||
|
||||
/* static */ ScriptDate::Date ScriptBaseStation::GetConstructionDate(StationID station_id)
|
||||
/* static */ ScriptCalendarDate *ScriptBaseStation::GetConstructionDate(StationID station_id)
|
||||
{
|
||||
if (!IsValidBaseStation(station_id)) return ScriptDate::DATE_INVALID;
|
||||
if (!IsValidBaseStation(station_id)) return new ScriptCalendarDate();
|
||||
|
||||
return (ScriptDate::Date)::BaseStation::Get(station_id)->build_date.base();
|
||||
return new ScriptCalendarDate(static_cast<ScriptCalendarDate::Date>(::BaseStation::Get(station_id)->build_date.base()));
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ public:
|
|||
* @return The last calendar-date some part of this station was build.
|
||||
* @see \ref ScriptCalendarTime
|
||||
*/
|
||||
static ScriptDate::Date GetConstructionDate(StationID station_id);
|
||||
static ScriptCalendarDate *GetConstructionDate(StationID station_id);
|
||||
};
|
||||
|
||||
#endif /* SCRIPT_BASESTATION_HPP */
|
||||
|
|
|
@ -46,9 +46,9 @@ static NetworkClientInfo *FindClientInfo(ScriptClient::ClientID client)
|
|||
return ScriptCompany::ToScriptCompanyID(ci->client_playas);
|
||||
}
|
||||
|
||||
/* static */ ScriptDate::Date ScriptClient::GetJoinDate(ScriptClient::ClientID client)
|
||||
/* static */ ScriptEconomyDate *ScriptClient::GetJoinDate(ScriptClient::ClientID client)
|
||||
{
|
||||
NetworkClientInfo *ci = FindClientInfo(client);
|
||||
if (ci == nullptr) return ScriptDate::DATE_INVALID;
|
||||
return (ScriptDate::Date)ci->join_date.base();
|
||||
if (ci == nullptr) return new ScriptEconomyDate();
|
||||
return new ScriptEconomyDate(static_cast<ScriptEconomyDate::Date>(ci->join_date.base()));
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ public:
|
|||
* @return The economy-date when client has joined.
|
||||
* @see \ref ScriptEconomyTime
|
||||
*/
|
||||
static ScriptDate::Date GetJoinDate(ClientID client);
|
||||
static ScriptEconomyDate *GetJoinDate(ClientID client);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @file script_date.cpp Implementation of ScriptDate. */
|
||||
|
||||
#include "../../stdafx.h"
|
||||
#include "script_date.hpp"
|
||||
#include "../../timer/timer_game_economy.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "../../safeguards.h"
|
||||
|
||||
/* static */ bool ScriptDate::IsValidDate(Date date)
|
||||
{
|
||||
return date >= 0;
|
||||
}
|
||||
|
||||
/* static */ ScriptDate::Date ScriptDate::GetCurrentDate()
|
||||
{
|
||||
return (ScriptDate::Date)TimerGameEconomy::date.base();
|
||||
}
|
||||
|
||||
/* static */ SQInteger ScriptDate::GetYear(ScriptDate::Date date)
|
||||
{
|
||||
if (date < 0) return DATE_INVALID;
|
||||
|
||||
::TimerGameEconomy::YearMonthDay ymd = ::TimerGameEconomy::ConvertDateToYMD(::TimerGameEconomy::Date{date});
|
||||
return ymd.year.base();
|
||||
}
|
||||
|
||||
/* static */ SQInteger ScriptDate::GetMonth(ScriptDate::Date date)
|
||||
{
|
||||
if (date < 0) return DATE_INVALID;
|
||||
|
||||
::TimerGameEconomy::YearMonthDay ymd = ::TimerGameEconomy::ConvertDateToYMD(::TimerGameEconomy::Date{date});
|
||||
return ymd.month + 1;
|
||||
}
|
||||
|
||||
/* static */ SQInteger ScriptDate::GetDayOfMonth(ScriptDate::Date date)
|
||||
{
|
||||
if (date < 0) return DATE_INVALID;
|
||||
|
||||
::TimerGameEconomy::YearMonthDay ymd = ::TimerGameEconomy::ConvertDateToYMD(::TimerGameEconomy::Date{date});
|
||||
return ymd.day;
|
||||
}
|
||||
|
||||
/* static */ ScriptDate::Date ScriptDate::GetDate(SQInteger year, SQInteger month, SQInteger day_of_month)
|
||||
{
|
||||
if (month < 1 || month > 12) return DATE_INVALID;
|
||||
if (day_of_month < 1 || day_of_month > 31) return DATE_INVALID;
|
||||
|
||||
::TimerGameEconomy::Year timer_year{ClampTo<int32_t>(year)};
|
||||
if (timer_year < EconomyTime::MIN_YEAR || timer_year > EconomyTime::MAX_YEAR) return DATE_INVALID;
|
||||
|
||||
return static_cast<ScriptDate::Date>(::TimerGameEconomy::ConvertYMDToDate(timer_year, month - 1, day_of_month).base());
|
||||
}
|
||||
|
||||
/* static */ SQInteger ScriptDate::GetSystemTime()
|
||||
{
|
||||
time_t t;
|
||||
time(&t);
|
||||
return t;
|
||||
}
|
|
@ -12,7 +12,175 @@
|
|||
|
||||
#include "script_object.hpp"
|
||||
#include "../../timer/timer_game_economy.h"
|
||||
#include "../squirrel_helper.hpp"
|
||||
|
||||
#ifndef DOXYGEN_API
|
||||
template <size_t N>
|
||||
struct StringLiteral {
|
||||
constexpr StringLiteral(const char (&str)[N])
|
||||
{
|
||||
std::copy_n(str, N, this->value);
|
||||
}
|
||||
|
||||
char value[N];
|
||||
};
|
||||
|
||||
template <class Timer, class Time, StringLiteral Tag>
|
||||
class ScriptDateBase : public ScriptObject {
|
||||
public:
|
||||
using YearMonthDay = Timer::YearMonthDay;
|
||||
using Year = Timer::Year;
|
||||
|
||||
enum Date {
|
||||
DATE_INVALID = Time::INVALID_DATE.base(),
|
||||
};
|
||||
|
||||
ScriptDateBase(Date date = DATE_INVALID) : _date(date) {}
|
||||
ScriptDateBase(HSQUIRRELVM vm) : _date(DATE_INVALID)
|
||||
{
|
||||
int nparam = sq_gettop(vm) - 1;
|
||||
if (nparam >= 1) {
|
||||
SQInteger date;
|
||||
if (SQ_FAILED(sq_getinteger(vm, 2, &date))) {
|
||||
throw sq_throwerror(vm, "Argument must be an integer");
|
||||
}
|
||||
this->_date = static_cast<Date>(date);
|
||||
}
|
||||
}
|
||||
|
||||
bool IsValid()
|
||||
{
|
||||
return this->_date > 0;
|
||||
}
|
||||
|
||||
static ScriptDateBase *GetCurrentDate()
|
||||
{
|
||||
return new ScriptDateBase(static_cast<Date>(Timer::date.base()));
|
||||
}
|
||||
|
||||
SQInteger GetYear()
|
||||
{
|
||||
if (!this->IsValid()) return DATE_INVALID;
|
||||
|
||||
YearMonthDay ymd = Timer::ConvertDateToYMD(static_cast<Timer::Date>(this->_date));
|
||||
return ymd.year.base();
|
||||
}
|
||||
|
||||
SQInteger GetMonth()
|
||||
{
|
||||
if (!this->IsValid()) return DATE_INVALID;
|
||||
|
||||
YearMonthDay ymd = Timer::ConvertDateToYMD(static_cast<Timer::Date>(this->_date));
|
||||
return ymd.month + 1;
|
||||
}
|
||||
|
||||
SQInteger GetDayOfMonth()
|
||||
{
|
||||
if (!this->IsValid()) return DATE_INVALID;
|
||||
|
||||
YearMonthDay ymd = Timer::ConvertDateToYMD(static_cast<Timer::Date>(this->_date));
|
||||
return ymd.day;
|
||||
}
|
||||
|
||||
static ScriptDateBase *GetDate(SQInteger year, SQInteger month, SQInteger day_of_month)
|
||||
{
|
||||
if (month < 1 || month > 12) return new ScriptDateBase();
|
||||
if (day_of_month < 1 || day_of_month > 31) return new ScriptDateBase();
|
||||
|
||||
Year timer_year{ClampTo<int32_t>(year)};
|
||||
if (timer_year < Time::MIN_YEAR || timer_year > Time::MAX_YEAR) return new ScriptDateBase();
|
||||
|
||||
return new ScriptDateBase(static_cast<Date>(Timer::ConvertYMDToDate(timer_year, month - 1, day_of_month).base()));
|
||||
}
|
||||
|
||||
static SQInteger GetSystemTime()
|
||||
{
|
||||
time_t t;
|
||||
time(&t);
|
||||
return t;
|
||||
}
|
||||
|
||||
Date date() { return this->_date; }
|
||||
|
||||
SQInteger _tostring(HSQUIRRELVM vm)
|
||||
{
|
||||
sq_pushstring(vm, fmt::format("{}", this->_date));
|
||||
return 1;
|
||||
}
|
||||
|
||||
SQInteger _add(HSQUIRRELVM vm)
|
||||
{
|
||||
SQInteger days = 0;
|
||||
switch (sq_gettype(vm, 2)) {
|
||||
case OT_INTEGER:
|
||||
sq_getinteger(vm, 2, &days);
|
||||
break;
|
||||
case OT_INSTANCE: {
|
||||
ScriptDateBase *other = static_cast<ScriptDateBase *>(Squirrel::GetRealInstance(vm, 2, Tag.value));
|
||||
if (other == nullptr) return SQ_ERROR;
|
||||
days = other->_date;
|
||||
break;
|
||||
}
|
||||
default: return SQ_ERROR;
|
||||
}
|
||||
ScriptDateBase *res = new ScriptDateBase(static_cast<Date>(this->_date + days));
|
||||
res->AddRef();
|
||||
Squirrel::CreateClassInstanceVM(vm, Tag.value, res, nullptr, SQConvert::DefSQDestructorCallback<ScriptDateBase>, true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
SQInteger _sub(HSQUIRRELVM vm)
|
||||
{
|
||||
SQInteger days = 0;
|
||||
switch (sq_gettype(vm, 2)) {
|
||||
case OT_INTEGER:
|
||||
sq_getinteger(vm, 2, &days);
|
||||
break;
|
||||
case OT_INSTANCE: {
|
||||
ScriptDateBase *other = static_cast<ScriptDateBase *>(Squirrel::GetRealInstance(vm, 2, Tag.value));
|
||||
if (other == nullptr) return SQ_ERROR;
|
||||
days = other->_date;
|
||||
break;
|
||||
}
|
||||
default: return SQ_ERROR;
|
||||
}
|
||||
ScriptDateBase *res = new ScriptDateBase(static_cast<Date>(this->_date - days));
|
||||
res->AddRef();
|
||||
Squirrel::CreateClassInstanceVM(vm, Tag.value, res, nullptr, SQConvert::DefSQDestructorCallback<ScriptDateBase>, true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
SQInteger _cmp(HSQUIRRELVM vm)
|
||||
{
|
||||
ScriptDateBase *other = static_cast<ScriptDateBase *>(Squirrel::GetRealInstance(vm, 2, Tag.value));
|
||||
if (other == nullptr) return SQ_ERROR;
|
||||
sq_pushinteger(vm, this->_date - other->_date);
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool SaveObject(HSQUIRRELVM vm) override
|
||||
{
|
||||
sq_pushstring(vm, Tag.value);
|
||||
sq_pushinteger(vm, this->_date);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LoadObject(HSQUIRRELVM vm) override
|
||||
{
|
||||
if (sq_gettype(vm, -1) != OT_INTEGER) return false;
|
||||
SQInteger val;
|
||||
sq_getinteger(vm, -1, &val);
|
||||
this->_date = static_cast<Date>(val);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
Date _date = DATE_INVALID;
|
||||
};
|
||||
|
||||
using ScriptEconomyDate = ScriptDateBase<TimerGameEconomy, EconomyTime, "EconomyDate">;
|
||||
using ScriptCalendarDate = ScriptDateBase<TimerGameCalendar, CalendarTime, "CalendarDate">;
|
||||
#else
|
||||
/**
|
||||
* Class that handles all date related (calculation) functions.
|
||||
* @api ai game
|
||||
|
@ -48,22 +216,23 @@
|
|||
* Economy-time will use a 360 day calendar (12 months with 30 days each), which runs at a constant speed of one economy-month per realtime-minute.
|
||||
* Calendar-time will use a Gregorian calendar, which can be slowed to stopped via game settings.
|
||||
*/
|
||||
class ScriptDate : public ScriptObject {
|
||||
class ScriptEconomyDate : public ScriptObject {
|
||||
public:
|
||||
/**
|
||||
* Date data type is an integer value. Use ScriptDate::GetDate to
|
||||
* Date data type is an integer value. Use ScriptEconomyDate::GetDate to
|
||||
* compose valid date values for a known year, month and day.
|
||||
*/
|
||||
enum Date {
|
||||
DATE_INVALID = ::EconomyTime::INVALID_DATE.base(), ///< A value representing an invalid date.
|
||||
DATE_INVALID, ///< A value representing an invalid date.
|
||||
};
|
||||
|
||||
ScriptEconomyDate(Date date = DATE_INVALID);
|
||||
|
||||
/**
|
||||
* Validates if a date value represent a valid date.
|
||||
* @param date The date to validate.
|
||||
* @return True if the date is valid, otherwise false
|
||||
*/
|
||||
static bool IsValidDate(Date date);
|
||||
bool IsValid();
|
||||
|
||||
/**
|
||||
* Get the current date.
|
||||
|
@ -72,28 +241,25 @@ public:
|
|||
* 100 but not by 400.
|
||||
* @return The current date.
|
||||
*/
|
||||
static Date GetCurrentDate();
|
||||
static ScriptEconomyDate GetCurrentDate();
|
||||
|
||||
/**
|
||||
* Get the year of the given date.
|
||||
* @param date The date to get the year of.
|
||||
* @return The year.
|
||||
*/
|
||||
static SQInteger GetYear(Date date);
|
||||
SQInteger GetYear();
|
||||
|
||||
/**
|
||||
* Get the month of the given date.
|
||||
* @param date The date to get the month of.
|
||||
* @return The month.
|
||||
*/
|
||||
static SQInteger GetMonth(Date date);
|
||||
SQInteger GetMonth();
|
||||
|
||||
/**
|
||||
* Get the day (of the month) of the given date.
|
||||
* @param date The date to get the day of.
|
||||
* @return The day.
|
||||
*/
|
||||
static SQInteger GetDayOfMonth(Date date);
|
||||
SQInteger GetDayOfMonth();
|
||||
|
||||
/**
|
||||
* Get the date given a year, month and day of month.
|
||||
|
@ -102,7 +268,7 @@ public:
|
|||
* @param day_of_month The day of month of the to-be determined date.
|
||||
* @return The date.
|
||||
*/
|
||||
static Date GetDate(SQInteger year, SQInteger month, SQInteger day_of_month);
|
||||
static ScriptEconomyDate GetDate(SQInteger year, SQInteger month, SQInteger day_of_month);
|
||||
|
||||
/**
|
||||
* Get the time of the host system.
|
||||
|
@ -111,6 +277,84 @@ public:
|
|||
* @note This uses the clock of the host system, which can skew or be set back. Use with caution.
|
||||
*/
|
||||
static SQInteger GetSystemTime();
|
||||
|
||||
/**
|
||||
* Get the date.
|
||||
* @return The date.
|
||||
*/
|
||||
Date date();
|
||||
};
|
||||
|
||||
|
||||
|
||||
class ScriptCalendarDate : public ScriptObject {
|
||||
public:
|
||||
/**
|
||||
* Date data type is an integer value. Use ScriptCalendarDate::GetDate to
|
||||
* compose valid date values for a known year, month and day.
|
||||
*/
|
||||
enum Date {
|
||||
DATE_INVALID, ///< A value representing an invalid date.
|
||||
};
|
||||
|
||||
ScriptCalendarDate(Date date = DATE_INVALID);
|
||||
|
||||
/**
|
||||
* Validates if a date value represent a valid date.
|
||||
* @return True if the date is valid, otherwise false
|
||||
*/
|
||||
bool IsValid();
|
||||
|
||||
/**
|
||||
* Get the current date.
|
||||
* This is the number of days since epoch under the assumption that
|
||||
* there is a leap year every 4 years, except when dividable by
|
||||
* 100 but not by 400.
|
||||
* @return The current date.
|
||||
*/
|
||||
static ScriptCalendarDate GetCurrentDate();
|
||||
|
||||
/**
|
||||
* Get the year of the given date.
|
||||
* @return The year.
|
||||
*/
|
||||
SQInteger GetYear();
|
||||
|
||||
/**
|
||||
* Get the month of the given date.
|
||||
* @return The month.
|
||||
*/
|
||||
SQInteger GetMonth();
|
||||
|
||||
/**
|
||||
* Get the day (of the month) of the given date.
|
||||
* @return The day.
|
||||
*/
|
||||
SQInteger GetDayOfMonth();
|
||||
|
||||
/**
|
||||
* Get the date given a year, month and day of month.
|
||||
* @param year The year of the to-be determined date.
|
||||
* @param month The month of the to-be determined date.
|
||||
* @param day_of_month The day of month of the to-be determined date.
|
||||
* @return The date.
|
||||
*/
|
||||
static ScriptCalendarDate GetDate(SQInteger year, SQInteger month, SQInteger day_of_month);
|
||||
|
||||
/**
|
||||
* Get the time of the host system.
|
||||
* @return The amount of seconds passed since 1 Jan 1970.
|
||||
* @api -ai
|
||||
* @note This uses the clock of the host system, which can skew or be set back. Use with caution.
|
||||
*/
|
||||
static SQInteger GetSystemTime();
|
||||
|
||||
/**
|
||||
* Get the date.
|
||||
* @return The date.
|
||||
*/
|
||||
Date date();
|
||||
};
|
||||
#endif /* DOXYGEN_API */
|
||||
|
||||
#endif /* SCRIPT_DATE_HPP */
|
||||
|
|
|
@ -169,11 +169,11 @@
|
|||
return ::Engine::Get(engine_id)->GetDisplayMaxTractiveEffort() / 1000;
|
||||
}
|
||||
|
||||
/* static */ ScriptDate::Date ScriptEngine::GetDesignDate(EngineID engine_id)
|
||||
/* static */ ScriptCalendarDate *ScriptEngine::GetDesignDate(EngineID engine_id)
|
||||
{
|
||||
if (!IsValidEngine(engine_id)) return ScriptDate::DATE_INVALID;
|
||||
if (!IsValidEngine(engine_id)) return new ScriptCalendarDate();
|
||||
|
||||
return (ScriptDate::Date)::Engine::Get(engine_id)->intro_date.base();
|
||||
return new ScriptCalendarDate(static_cast<ScriptCalendarDate::Date>(::Engine::Get(engine_id)->intro_date.base()));
|
||||
}
|
||||
|
||||
/* static */ ScriptVehicle::VehicleType ScriptEngine::GetVehicleType(EngineID engine_id)
|
||||
|
|
|
@ -173,7 +173,7 @@ public:
|
|||
* @return The calendar-date this engine was designed.
|
||||
* @see \ref ScriptCalendarTime
|
||||
*/
|
||||
static ScriptDate::Date GetDesignDate(EngineID engine_id);
|
||||
static ScriptCalendarDate *GetDesignDate(EngineID engine_id);
|
||||
|
||||
/**
|
||||
* Get the type of an engine.
|
||||
|
|
|
@ -49,11 +49,11 @@
|
|||
return ::StrMakeValid(::GetString(STR_INDUSTRY_NAME, industry_id), {});
|
||||
}
|
||||
|
||||
/* static */ ScriptDate::Date ScriptIndustry::GetConstructionDate(IndustryID industry_id)
|
||||
/* static */ ScriptCalendarDate *ScriptIndustry::GetConstructionDate(IndustryID industry_id)
|
||||
{
|
||||
const Industry *i = Industry::GetIfValid(industry_id);
|
||||
if (i == nullptr) return ScriptDate::DATE_INVALID;
|
||||
return (ScriptDate::Date)i->construction_date.base();
|
||||
if (i == nullptr) return new ScriptCalendarDate();
|
||||
return new ScriptCalendarDate(static_cast<ScriptCalendarDate::Date>(i->construction_date.base()));
|
||||
}
|
||||
|
||||
/* static */ bool ScriptIndustry::SetText(IndustryID industry_id, Text *text)
|
||||
|
@ -226,18 +226,18 @@
|
|||
return i->last_prod_year.base();
|
||||
}
|
||||
|
||||
/* static */ ScriptDate::Date ScriptIndustry::GetCargoLastAcceptedDate(IndustryID industry_id, CargoType cargo_type)
|
||||
/* static */ ScriptEconomyDate *ScriptIndustry::GetCargoLastAcceptedDate(IndustryID industry_id, CargoType cargo_type)
|
||||
{
|
||||
const Industry *i = Industry::GetIfValid(industry_id);
|
||||
if (i == nullptr) return ScriptDate::DATE_INVALID;
|
||||
if (i == nullptr) return new ScriptEconomyDate();
|
||||
|
||||
if (!::IsValidCargoType(cargo_type)) {
|
||||
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.base();
|
||||
return new ScriptEconomyDate(static_cast<ScriptEconomyDate::Date>(it->last_accepted.base()));
|
||||
} else {
|
||||
auto it = i->GetCargoAccepted(cargo_type);
|
||||
if (it == std::end(i->accepted)) return ScriptDate::DATE_INVALID;
|
||||
return (ScriptDate::Date)it->last_accepted.base();
|
||||
if (it == std::end(i->accepted)) return new ScriptEconomyDate();
|
||||
return new ScriptEconomyDate(static_cast<ScriptEconomyDate::Date>(it->last_accepted.base()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -93,7 +93,7 @@ public:
|
|||
* @see \ref ScriptCalendarTime
|
||||
* @api -ai
|
||||
*/
|
||||
static ScriptDate::Date GetConstructionDate(IndustryID industry_id);
|
||||
static ScriptCalendarDate *GetConstructionDate(IndustryID industry_id);
|
||||
|
||||
/**
|
||||
* Set the custom text of an industry, shown in the GUI.
|
||||
|
@ -265,11 +265,11 @@ public:
|
|||
* @param cargo_type The cargo to query, or INVALID_CARGO to query latest of all accepted cargoes.
|
||||
* @pre IsValidIndustry(industry_id).
|
||||
* @pre IsValidCargo(cargo_type) || cargo_type == INVALID_CARGO.
|
||||
* @return Economy-date the industry last received cargo from a delivery, or ScriptDate::DATE_INVALID on error.
|
||||
* @return Economy-date the industry last received cargo from a delivery, ScriptEconomyDate::IsValid() returns false on error.
|
||||
* @see \ref ScriptEconomyTime
|
||||
* @api -ai
|
||||
*/
|
||||
static ScriptDate::Date GetCargoLastAcceptedDate(IndustryID industry_id, CargoType cargo_type);
|
||||
static ScriptEconomyDate *GetCargoLastAcceptedDate(IndustryID industry_id, CargoType cargo_type);
|
||||
|
||||
/**
|
||||
* Get the current control flags for an industry.
|
||||
|
|
|
@ -179,20 +179,21 @@ static inline bool StoryPageElementTypeRequiresText(StoryPageElementType type)
|
|||
return ScriptCompany::ToScriptCompanyID(StoryPage::Get(story_page_id)->company);
|
||||
}
|
||||
|
||||
/* static */ ScriptDate::Date ScriptStoryPage::GetDate(StoryPageID story_page_id)
|
||||
/* static */ ScriptCalendarDate *ScriptStoryPage::GetDate(StoryPageID story_page_id)
|
||||
{
|
||||
EnforcePrecondition(ScriptDate::DATE_INVALID, IsValidStoryPage(story_page_id));
|
||||
EnforceDeityMode(ScriptDate::DATE_INVALID);
|
||||
EnforcePrecondition(new ScriptCalendarDate(), IsValidStoryPage(story_page_id));
|
||||
EnforceDeityMode(new ScriptCalendarDate());
|
||||
|
||||
return (ScriptDate::Date)StoryPage::Get(story_page_id)->date.base();
|
||||
return new ScriptCalendarDate(static_cast<ScriptCalendarDate::Date>(StoryPage::Get(story_page_id)->date.base()));
|
||||
}
|
||||
|
||||
/* static */ bool ScriptStoryPage::SetDate(StoryPageID story_page_id, ScriptDate::Date date)
|
||||
/* static */ bool ScriptStoryPage::SetDate(StoryPageID story_page_id, ScriptCalendarDate *date)
|
||||
{
|
||||
EnforcePrecondition(false, IsValidStoryPage(story_page_id));
|
||||
EnforceDeityMode(false);
|
||||
if (date == nullptr) date = new ScriptCalendarDate();
|
||||
|
||||
return ScriptObject::Command<CMD_SET_STORY_PAGE_DATE>::Do(story_page_id, ::TimerGameCalendar::Date{date});
|
||||
return ScriptObject::Command<CMD_SET_STORY_PAGE_DATE>::Do(story_page_id, ::TimerGameCalendar::Date{date->date()});
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -256,18 +256,18 @@ public:
|
|||
* @pre IsValidStoryPage(story_page_id).
|
||||
* @see \ref ScriptCalendarTime
|
||||
*/
|
||||
static ScriptDate::Date GetDate(StoryPageID story_page_id);
|
||||
static ScriptCalendarDate *GetDate(StoryPageID story_page_id);
|
||||
|
||||
/**
|
||||
* Update date of a story page. The date is shown in the top left of the page
|
||||
* @param story_page_id The story page to set the date for.
|
||||
* @param date Calendar-date to display at the top of story page or ScriptDate::DATE_INVALID to disable showing date on this page. (also, @see ScriptDate)
|
||||
* @param date Calendar-date to display at the top of story page or null to disable showing date on this page. (also, @see ScriptCalendarDate)
|
||||
* @return True if the action succeeded.
|
||||
* @pre ScriptCompanyMode::IsDeity().
|
||||
* @pre IsValidStoryPage(story_page_id).
|
||||
* @see \ref ScriptCalendarTime
|
||||
*/
|
||||
static bool SetDate(StoryPageID story_page_id, ScriptDate::Date date);
|
||||
static bool SetDate(StoryPageID story_page_id, ScriptCalendarDate *date);
|
||||
|
||||
/**
|
||||
* Update title of a story page. The title is shown in the page selector drop down.
|
||||
|
|
|
@ -53,9 +53,9 @@
|
|||
return ScriptCompany::ToScriptCompanyID(::Subsidy::Get(subsidy_id)->awarded);
|
||||
}
|
||||
|
||||
/* static */ ScriptDate::Date ScriptSubsidy::GetExpireDate(SubsidyID subsidy_id)
|
||||
/* static */ ScriptEconomyDate *ScriptSubsidy::GetExpireDate(SubsidyID subsidy_id)
|
||||
{
|
||||
if (!IsValidSubsidy(subsidy_id)) return ScriptDate::DATE_INVALID;
|
||||
if (!IsValidSubsidy(subsidy_id)) return new ScriptEconomyDate();
|
||||
|
||||
TimerGameEconomy::YearMonthDay ymd = TimerGameEconomy::ConvertDateToYMD(TimerGameEconomy::date);
|
||||
ymd.day = 1;
|
||||
|
@ -63,7 +63,7 @@
|
|||
ymd.month = m % 12;
|
||||
ymd.year += TimerGameEconomy::Year{m / 12};
|
||||
|
||||
return (ScriptDate::Date)TimerGameEconomy::ConvertYMDToDate(ymd.year, ymd.month, ymd.day).base();
|
||||
return ScriptEconomyDate::GetDate(ymd.year.base(), ymd.month + 1, ymd.day);
|
||||
}
|
||||
|
||||
/* static */ CargoType ScriptSubsidy::GetCargoType(SubsidyID subsidy_id)
|
||||
|
|
|
@ -85,7 +85,7 @@ public:
|
|||
* awarded.
|
||||
* @see \ref ScriptEconomyTime
|
||||
*/
|
||||
static ScriptDate::Date GetExpireDate(SubsidyID subsidy_id);
|
||||
static ScriptEconomyDate *GetExpireDate(SubsidyID subsidy_id);
|
||||
|
||||
/**
|
||||
* Get the cargo type that has to be transported in order to be awarded this
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../script_date.hpp"
|
||||
|
||||
namespace SQConvert {
|
||||
/* Allow ScriptEconomyDate to be used as Squirrel parameter */
|
||||
template <> struct Param<ScriptEconomyDate *> { static inline ScriptEconomyDate *Get(HSQUIRRELVM vm, int index) { return static_cast<ScriptEconomyDate *>(sq_gettype(vm, index) == OT_NULL ? nullptr : Squirrel::GetRealInstance(vm, index, "EconomyDate")); } };
|
||||
template <> struct Param<ScriptEconomyDate &> { static inline ScriptEconomyDate &Get(HSQUIRRELVM vm, int index) { return *static_cast<ScriptEconomyDate *>(Squirrel::GetRealInstance(vm, index, "EconomyDate")); } };
|
||||
template <> struct Param<const ScriptEconomyDate *> { static inline const ScriptEconomyDate *Get(HSQUIRRELVM vm, int index) { return static_cast<ScriptEconomyDate *>(sq_gettype(vm, index) == OT_NULL ? nullptr : Squirrel::GetRealInstance(vm, index, "EconomyDate")); } };
|
||||
template <> struct Param<const ScriptEconomyDate &> { static inline const ScriptEconomyDate &Get(HSQUIRRELVM vm, int index) { return *static_cast<ScriptEconomyDate *>(Squirrel::GetRealInstance(vm, index, "EconomyDate")); } };
|
||||
template <> struct Return<ScriptEconomyDate *> { static inline int Set(HSQUIRRELVM vm, ScriptEconomyDate *res) { if (res == nullptr) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "EconomyDate", res, nullptr, DefSQDestructorCallback<ScriptEconomyDate>, true); return 1; } };
|
||||
|
||||
/* Allow ScriptCalendarDate to be used as Squirrel parameter */
|
||||
template <> struct Param<ScriptCalendarDate *> { static inline ScriptCalendarDate *Get(HSQUIRRELVM vm, int index) { return static_cast<ScriptCalendarDate *>(sq_gettype(vm, index) == OT_NULL ? nullptr : Squirrel::GetRealInstance(vm, index, "CalendarDate")); } };
|
||||
template <> struct Param<ScriptCalendarDate &> { static inline ScriptCalendarDate &Get(HSQUIRRELVM vm, int index) { return *static_cast<ScriptCalendarDate *>(Squirrel::GetRealInstance(vm, index, "CalendarDate")); } };
|
||||
template <> struct Param<const ScriptCalendarDate *> { static inline const ScriptCalendarDate *Get(HSQUIRRELVM vm, int index) { return static_cast<ScriptCalendarDate *>(sq_gettype(vm, index) == OT_NULL ? nullptr : Squirrel::GetRealInstance(vm, index, "CalendarDate")); } };
|
||||
template <> struct Param<const ScriptCalendarDate &> { static inline const ScriptCalendarDate &Get(HSQUIRRELVM vm, int index) { return *static_cast<ScriptCalendarDate *>(Squirrel::GetRealInstance(vm, index, "CalendarDate")); } };
|
||||
template <> struct Return<ScriptCalendarDate *> { static inline int Set(HSQUIRRELVM vm, ScriptCalendarDate *res) { if (res == nullptr) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "CalendarDate", res, nullptr, DefSQDestructorCallback<ScriptCalendarDate>, true); return 1; } };
|
||||
} // namespace SQConvert
|
|
@ -37,6 +37,7 @@ TimerGameEconomy::Year TimerGameEconomy::year = {};
|
|||
TimerGameEconomy::Month TimerGameEconomy::month = {};
|
||||
TimerGameEconomy::Date TimerGameEconomy::date = {};
|
||||
TimerGameEconomy::DateFract TimerGameEconomy::date_fract = {};
|
||||
uint TimerGameEconomy::days_since_last_month = {};
|
||||
|
||||
/**
|
||||
* Converts a Date to a Year, Month & Day.
|
||||
|
@ -133,6 +134,7 @@ bool TimerManager<TimerGameEconomy>::Elapsed([[maybe_unused]] TimerGameEconomy::
|
|||
|
||||
/* increase day counter */
|
||||
TimerGameEconomy::date++;
|
||||
++TimerGameEconomy::days_since_last_month;
|
||||
|
||||
TimerGameEconomy::YearMonthDay ymd = TimerGameEconomy::ConvertDateToYMD(TimerGameEconomy::date);
|
||||
|
||||
|
@ -177,6 +179,8 @@ bool TimerManager<TimerGameEconomy>::Elapsed([[maybe_unused]] TimerGameEconomy::
|
|||
}
|
||||
}
|
||||
|
||||
if (new_month) TimerGameEconomy::days_since_last_month = 0;
|
||||
|
||||
/* check if we reached the maximum year, decrement dates by a year */
|
||||
if (TimerGameEconomy::year == EconomyTime::MAX_YEAR + 1) {
|
||||
TimerGameEconomy::year--;
|
||||
|
|
|
@ -37,6 +37,8 @@ public:
|
|||
static Date date; ///< Current date in days (day counter).
|
||||
static DateFract date_fract; ///< Fractional part of the day.
|
||||
|
||||
static uint days_since_last_month; ///< Number of days that have elapsed since the last month.
|
||||
|
||||
static YearMonthDay ConvertDateToYMD(Date date);
|
||||
static Date ConvertYMDToDate(Year year, Month month, Day day);
|
||||
static void SetDate(Date date, DateFract fract);
|
||||
|
|
Loading…
Reference in New Issue