Adjust handling of year display in wallclock mode and company inauguration years

See: #657
pull/661/head
Jonathan G Rennison 2 months ago
parent 1bfcbf823c
commit 090656bd7f

@ -120,6 +120,7 @@ static int32_t ClickChangeDateCheat(int32_t p1, int32_t p2)
/* Shift cached dates. */
LinkGraphSchedule::instance.ShiftDates(new_econ_date - EconTime::CurDate());
ShiftVehicleDates(new_econ_date - EconTime::CurDate());
EconTime::Detail::period_display_offset -= (p1 - EconTime::CurYear().base());
EconTime::Detail::SetDate(new_econ_date, new_econ_date_fract);
UpdateOrderUIOnDateChange();

@ -89,6 +89,8 @@ struct CompanyProperties {
std::array<Owner, MAX_COMPANY_SHARE_OWNERS> share_owners; ///< Owners of the shares of the company. #INVALID_OWNER if nobody has bought them yet.
CalTime::Year inaugurated_year; ///< Year of starting the company.
int32_t display_inaugurated_period;///< Wallclock display period of starting the company.
YearDelta age_years; ///< Number of economy years that the company has been operational.
byte months_of_bankruptcy; ///< Number of months that the company is unable to pay its debts
CompanyID bankrupt_last_asked; ///< Which company was most recently asked about buying it?
@ -123,9 +125,14 @@ struct CompanyProperties {
CompanyProperties()
: name_2(0), name_1(0), president_name_1(0), president_name_2(0),
face(0), money(0), money_fraction(0), current_loan(0), max_loan(COMPANY_MAX_LOAN_DEFAULT), colour(COLOUR_BEGIN),
block_preview(0), location_of_HQ(0), last_build_coordinate(0), share_owners(), inaugurated_year(0),
block_preview(0), location_of_HQ(0), last_build_coordinate(0), share_owners(), inaugurated_year(0), display_inaugurated_period(0), age_years(0),
months_of_bankruptcy(0), bankrupt_last_asked(INVALID_COMPANY), bankrupt_flags(CBRF_NONE), bankrupt_asked(0), bankrupt_timeout(0), bankrupt_value(0),
terraform_limit(0), clear_limit(0), tree_limit(0), purchase_land_limit(0), build_object_limit(0), is_ai(false), engine_renew_list(nullptr) {}
int32_t InauguratedDisplayYear() const
{
return EconTime::UsingWallclockUnits() ? this->display_inaugurated_period : this->inaugurated_year.base();
}
};
struct Company : CompanyPool::PoolItem<&_company_pool>, CompanyProperties {

@ -636,6 +636,7 @@ Company *DoStartupNewCompany(DoStartupNewCompanyFlag flags, CompanyID company)
c->avail_railtypes = GetCompanyRailTypes(c->index);
c->avail_roadtypes = GetCompanyRoadTypes(c->index);
c->inaugurated_year = CalTime::CurYear();
c->display_inaugurated_period = EconTime::Detail::WallClockYearToDisplay(EconTime::CurYear());
/* If starting a player company in singleplayer and a favorite company manager face is selected, choose it. Otherwise, use a random face.
* In a network game, we'll choose the favorite face later in CmdCompanyCtrl to sync it to all clients. */
@ -864,6 +865,7 @@ void CompaniesYearlyLoop()
/* Move expenses to previous years. */
std::rotate(std::rbegin(c->yearly_expenses), std::rbegin(c->yearly_expenses) + 1, std::rend(c->yearly_expenses));
c->yearly_expenses[0] = {};
c->age_years++;
SetWindowDirty(WC_FINANCES, c->index);
}

@ -424,10 +424,10 @@ struct CompanyFinancesWindow : Window {
case WID_CF_EXPS_PRICE2:
case WID_CF_EXPS_PRICE3: {
const Company *c = Company::Get((CompanyID)this->window_number);
YearDelta age = std::min<YearDelta>(CalTime::CurYear() - c->inaugurated_year, 2);
YearDelta age = std::min<YearDelta>(c->age_years, 2);
int wid_offset = widget - WID_CF_EXPS_PRICE1;
if (wid_offset <= age.base()) {
DrawYearColumn(r, CalTime::CurYear().base() - (age.base() - wid_offset), c->yearly_expenses[age.base() - wid_offset]);
DrawYearColumn(r, EconTime::YearToDisplay(EconTime::CurYear().base() - (age.base() - wid_offset)), c->yearly_expenses[age.base() - wid_offset]);
}
break;
}
@ -2595,7 +2595,7 @@ struct CompanyWindow : Window
break;
case WID_C_DESC_INAUGURATION:
SetDParam(0, Company::Get((CompanyID)this->window_number)->inaugurated_year);
SetDParam(0, Company::Get((CompanyID)this->window_number)->InauguratedDisplayYear());
break;
case WID_C_DESC_COMPANY_VALUE:

@ -2008,9 +2008,9 @@ DEF_CONSOLE_CMD(ConCompanies)
password_state = _network_company_states[c->index].password.empty() ? "unprotected" : "protected";
}
IConsolePrintF(CC_INFO, "#:%d(%s) Company Name: '%s' Year Founded: %d Money: " OTTD_PRINTF64 " Loan: " OTTD_PRINTF64 " Value: " OTTD_PRINTF64 " (T:%d, R:%d, P:%d, S:%d) %s",
IConsolePrintF(CC_INFO, "#:%d(%s) Company Name: '%s' Year Founded: %d Age: %d Money: " OTTD_PRINTF64 " Loan: " OTTD_PRINTF64 " Value: " OTTD_PRINTF64 " (T:%d, R:%d, P:%d, S:%d) %s",
c->index + 1, GetStringPtr(STR_COLOUR_DARK_BLUE + _company_colours[c->index]), company_name.c_str(),
c->inaugurated_year.base(), (int64_t)c->money, (int64_t)c->current_loan, (int64_t)CalculateCompanyValue(c),
c->InauguratedDisplayYear(), c->age_years.base(), (int64_t)c->money, (int64_t)c->current_loan, (int64_t)CalculateCompanyValue(c),
c->group_all[VEH_TRAIN].num_vehicle,
c->group_all[VEH_ROAD].num_vehicle,
c->group_all[VEH_AIRCRAFT].num_vehicle,
@ -2693,6 +2693,8 @@ DEF_CONSOLE_CMD(ConGetFullDate)
IConsolePrintF(CC_DEFAULT, "Calendar Date: %04d-%02d-%02d (%d), fract: %i, sub_fract: %i", CalTime::CurYear().base(), CalTime::CurMonth() + 1, CalTime::CurDay(), CalTime::CurDate().base(), CalTime::CurDateFract(), CalTime::Detail::now.sub_date_fract);
IConsolePrintF(CC_DEFAULT, "Economy Date: %04d-%02d-%02d (%d), fract: %i, tick skip: %i", EconTime::CurYear().base(), EconTime::CurMonth() + 1, EconTime::CurDay(), EconTime::CurDate().base(), EconTime::CurDateFract(), TickSkipCounter());
IConsolePrintF(CC_DEFAULT, "Period display offset: %d", EconTime::Detail::period_display_offset.base());
IConsolePrintF(CC_DEFAULT, "Elapsed years: %d", EconTime::Detail::years_elapsed.base());
IConsolePrintF(CC_DEFAULT, "Tick counter: " OTTD_PRINTF64, _tick_counter);
IConsolePrintF(CC_DEFAULT, "Tick counter (scaled): " OTTD_PRINTF64, _scaled_tick_counter);
IConsolePrintF(CC_DEFAULT, "State ticks: " OTTD_PRINTF64 " (offset: " OTTD_PRINTF64 ")", _state_ticks.base(), DateDetail::_state_ticks_offset.base());

@ -34,6 +34,8 @@ uint32_t _quit_after_days; ///< Quit after this many days of run
CalTime::State CalTime::Detail::now;
EconTime::State EconTime::Detail::now;
YearDelta EconTime::Detail::years_elapsed;
YearDelta EconTime::Detail::period_display_offset;
namespace DateDetail {
StateTicksDelta _state_ticks_offset; ///< Offset to add when calculating a StateTicks value from an economy date, date fract and tick skip counter
@ -111,6 +113,11 @@ EconTime::State EconTime::Detail::NewState(EconTime::Year year)
return state;
}
int32_t EconTime::Detail::WallClockYearToDisplay(EconTime::Year year)
{
return (year + EconTime::Detail::period_display_offset).base();
}
StateTicks GetStateTicksFromDateWithoutOffset(EconTime::Date date, EconTime::DateFract date_fract)
{
return ((int64_t)(EconTime::DateToDateTicks(date, date_fract).base()) * DayLengthFactor()) + TickSkipCounter();
@ -379,6 +386,7 @@ static void OnNewCalendarYear()
*/
static void OnNewEconomyYear()
{
EconTime::Detail::years_elapsed++;
CompaniesYearlyLoop();
VehiclesYearlyLoop();
TownsYearlyLoop();
@ -386,6 +394,7 @@ static void OnNewEconomyYear()
/* check if we reached the maximum year, decrement dates by a year */
if (EconTime::CurYear() == EconTime::MAX_YEAR + 1) {
EconTime::Detail::period_display_offset++;
EconTime::Detail::now.econ_ymd.year--;
int days_this_year = EconTime::IsLeapYear(EconTime::Detail::now.econ_ymd.year) ? DAYS_IN_LEAP_YEAR : DAYS_IN_YEAR;
EconTime::Detail::now.econ_date -= days_this_year;

@ -240,9 +240,12 @@ struct EconTime : public DateDetail::BaseTime<struct EconTimeTag> {
/* Use a detail struct/namespace to more easily control writes */
struct Detail {
static State now;
static YearDelta years_elapsed;
static YearDelta period_display_offset;
static void SetDate(Date date, DateFract fract);
static State NewState(Year year);
static int32_t WallClockYearToDisplay(Year year);
/**
* Calculate the date of the first day of a given year.
@ -289,6 +292,12 @@ struct EconTime : public DateDetail::BaseTime<struct EconTimeTag> {
if (UsingWallclockUnits()) return Detail::DateAtStartOfWallclockModeYear(year);
return ParentBaseTime::Detail::DateAtStartOfCalendarYear(year);
}
static inline int32_t YearToDisplay(Year year)
{
if (UsingWallclockUnits()) return Detail::WallClockYearToDisplay(year);
return year.base();
}
};
namespace DateDetail {

@ -2532,7 +2532,7 @@ CommandCost CmdBuyShareInCompany(TileIndex tile, DoCommandFlag flags, uint32_t p
if (c == nullptr || !_settings_game.economy.allow_shares || _current_company == target_company) return CMD_ERROR;
/* Protect new companies from hostile takeovers */
if (CalTime::CurYear() - c->inaugurated_year < _settings_game.economy.min_years_for_shares) return_cmd_error(STR_ERROR_PROTECTED);
if (c->age_years < _settings_game.economy.min_years_for_shares) return_cmd_error(STR_ERROR_PROTECTED);
/* Those lines are here for network-protection (clients can be slow) */
if (GetAmountOwnedBy(c, COMPANY_SPECTATOR) == 0) return cost;

@ -130,6 +130,7 @@ void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settin
_pause_countdown = 0;
_game_speed = 100;
CalTime::Detail::now.sub_date_fract = 0;
EconTime::Detail::years_elapsed = 0;
_tick_counter = 0;
DateDetail::_tick_skip_counter = 0;
_scaled_tick_counter = 0;
@ -168,6 +169,7 @@ void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settin
} else {
EconTime::Detail::SetDate(CalTime::CurDate().base(), 0);
}
EconTime::Detail::period_display_offset = 1 - EconTime::CurYear();
InitializeOldNames();
} else {
RecalculateStateTicksOffset();

@ -330,7 +330,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyInfo(const Company
p->Send_string(GetString(STR_PRESIDENT_NAME));
p->Send_uint8 (c->colour);
p->Send_bool (NetworkCompanyIsPassworded(c->index));
p->Send_uint32(c->inaugurated_year.base());
p->Send_uint32(c->InauguratedDisplayYear());
p->Send_bool (c->is_ai);
p->Send_uint8 (CeilDiv(c->months_of_bankruptcy, 3)); // send as quarters_of_bankruptcy

@ -279,6 +279,8 @@ static void InitializeWindowsAndCaches()
* thus the MIN_YEAR (which is really nothing more than Zero, initialized value) test */
if (_file_to_saveload.abstract_ftype == FT_SCENARIO && c->inaugurated_year != CalTime::MIN_YEAR) {
c->inaugurated_year = CalTime::CurYear();
c->display_inaugurated_period = EconTime::Detail::WallClockYearToDisplay(EconTime::CurYear());
c->age_years = 0;
}
}
@ -1830,7 +1832,7 @@ bool AfterLoadGame()
for (Waypoint *wp : Waypoint::Iterate()) wp->build_date += CalTime::DAYS_TILL_ORIGINAL_BASE_YEAR.AsDelta();
for (Engine *e : Engine::Iterate()) e->intro_date += CalTime::DAYS_TILL_ORIGINAL_BASE_YEAR.AsDelta();
for (Company *c : Company::Iterate()) c->inaugurated_year += CalTime::ORIGINAL_BASE_YEAR.AsDelta();
for (Industry *i : Industry::Iterate()) i->last_prod_year += CalTime::ORIGINAL_BASE_YEAR.AsDelta();
for (Industry *i : Industry::Iterate()) i->last_prod_year += EconTime::ORIGINAL_BASE_YEAR.AsDelta();
for (Vehicle *v : Vehicle::Iterate()) {
v->date_of_last_service += EconTime::DAYS_TILL_ORIGINAL_BASE_YEAR.AsDelta();
@ -1838,6 +1840,22 @@ bool AfterLoadGame()
}
}
if (SlXvIsFeatureMissing(XSLFI_VARIABLE_DAY_LENGTH, 6)) {
EconTime::Detail::years_elapsed = EconTime::CurYear().base() - 1;
EconTime::Detail::period_display_offset = 0;
for (Company *c : Company::Iterate()) {
if (SlXvIsFeaturePresent(XSLFI_VARIABLE_DAY_LENGTH, 5, 5)) {
/* inaugurated_year is calendar time in XSLFI_VARIABLE_DAY_LENGTH version 5 */
c->age_years = std::max<YearDelta>(0, CalTime::CurYear() - c->inaugurated_year);
c->display_inaugurated_period = EconTime::Detail::WallClockYearToDisplay(c->inaugurated_year.base() + EconTime::CurYear().base() - CalTime::CurYear().base());
} else {
c->age_years = std::max<YearDelta>(0, EconTime::CurYear().base() - c->inaugurated_year.base());
c->display_inaugurated_period = EconTime::Detail::WallClockYearToDisplay(c->inaugurated_year.base());
c->inaugurated_year += CalTime::CurYear().base() - EconTime::CurYear().base();
}
}
}
/* From 32 on we save the industry who made the farmland.
* To give this prettiness to old savegames, we remove all farmfields and
* plant new ones. */

@ -1268,6 +1268,7 @@ static void ChangeTimekeepingUnits(int32_t)
/* If the new mode is calendar units, sync the economy date with the calendar date. */
new_economy_date = CalTime::CurDate().base();
new_economy_date_fract = CalTime::CurDateFract();
EconTime::Detail::period_display_offset -= (CalTime::CurYear().base() - EconTime::CurYear().base());
}
/* Update link graphs and vehicles, as these include stored economy dates. */

@ -276,6 +276,8 @@ static const SaveLoad _company_desc[] = {
SLE_CONDVAR(CompanyProperties, last_build_coordinate, SLE_UINT32, SLV_6, SL_MAX_VERSION),
SLE_CONDVAR(CompanyProperties, inaugurated_year, SLE_FILE_U8 | SLE_VAR_I32, SL_MIN_VERSION, SLV_31),
SLE_CONDVAR(CompanyProperties, inaugurated_year, SLE_INT32, SLV_31, SL_MAX_VERSION),
SLE_CONDVAR_X(CompanyProperties, display_inaugurated_period, SLE_INT32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VARIABLE_DAY_LENGTH, 6)),
SLE_CONDVAR_X(CompanyProperties, age_years, SLE_INT32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VARIABLE_DAY_LENGTH, 6)),
SLE_ARR(CompanyProperties, share_owners, SLE_UINT8, 4),

@ -103,7 +103,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
{ XSLFI_VEHICLE_REPAIR_COST, XSCF_NULL, 2, 2, "vehicle_repair_cost", nullptr, nullptr, nullptr },
{ XSLFI_ENH_VIEWPORT_PLANS, XSCF_IGNORABLE_ALL, 4, 4, "enh_viewport_plans", nullptr, nullptr, "PLAN" },
{ XSLFI_INFRA_SHARING, XSCF_NULL, 2, 2, "infra_sharing", nullptr, nullptr, "CPDP" },
{ XSLFI_VARIABLE_DAY_LENGTH, XSCF_NULL, 5, 5, "variable_day_length", nullptr, nullptr, nullptr },
{ XSLFI_VARIABLE_DAY_LENGTH, XSCF_NULL, 6, 6, "variable_day_length", nullptr, nullptr, nullptr },
{ XSLFI_ORDER_OCCUPANCY, XSCF_NULL, 2, 2, "order_occupancy", nullptr, nullptr, nullptr },
{ XSLFI_MORE_COND_ORDERS, XSCF_NULL, 17, 17, "more_cond_orders", nullptr, nullptr, nullptr },
{ XSLFI_EXTRA_LARGE_MAP, XSCF_NULL, 0, 1, "extra_large_map", nullptr, nullptr, nullptr },

@ -125,6 +125,8 @@ static const NamedSaveLoad _date_desc[] = {
NSLT("economy_date", SLEG_CONDVAR_X(EconTime::Detail::now.econ_date, SLE_INT32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VARIABLE_DAY_LENGTH, 5))),
NSLT("economy_date_fract", SLEG_CONDVAR_X(EconTime::Detail::now.econ_date_fract, SLE_UINT16, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VARIABLE_DAY_LENGTH, 5))),
NSLT("calendar_sub_date_fract", SLEG_CONDVAR_X(CalTime::Detail::now.sub_date_fract, SLE_UINT16, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VARIABLE_DAY_LENGTH, 5))),
NSLT("economy_years_elapsed", SLEG_CONDVAR_X(EconTime::Detail::years_elapsed, SLE_INT32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VARIABLE_DAY_LENGTH, 6))),
NSLT("period_display_offset", SLEG_CONDVAR_X(EconTime::Detail::period_display_offset, SLE_INT32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VARIABLE_DAY_LENGTH, 6))),
};
static const NamedSaveLoad _date_check_desc[] = {

@ -1258,14 +1258,19 @@ void SetStartingYear(CalTime::Year year)
{
_settings_game.game_creation.starting_year = Clamp(year, CalTime::MIN_YEAR, CalTime::MAX_YEAR);
CalTime::Date new_date = CalTime::ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1);
EconTime::Date new_economy_date = new_date.base();
/* If you open a savegame as scenario there may already be link graphs.*/
LinkGraphSchedule::instance.ShiftDates(new_economy_date - EconTime::CurDate());
ShiftVehicleDates(new_economy_date - EconTime::CurDate());
if (EconTime::UsingWallclockUnits()) {
EconTime::Date new_economy_date = new_date.base();
/* If you open a savegame as scenario there may already be link graphs.*/
LinkGraphSchedule::instance.ShiftDates(new_economy_date - EconTime::CurDate());
ShiftVehicleDates(new_economy_date - EconTime::CurDate());
EconTime::Detail::period_display_offset -= (year.base() - EconTime::CurYear().base());
EconTime::Detail::SetDate(new_economy_date, 0);
}
CalTime::Detail::SetDate(new_date, 0);
EconTime::Detail::SetDate(new_economy_date, 0);
UpdateOrderUIOnDateChange();
}

Loading…
Cancel
Save