Changeset - r27090:1ea30951c0f3
[Not reviewed]
master
0 25 0
Patric Stout - 20 months ago 2023-04-13 11:56:00
truebrain@openttd.org
Codechange: migrate all game-time-related timers to the new framework
25 files changed with 168 insertions and 147 deletions:
0 comments (0 inline, 0 general)
src/airport_gui.cpp
Show inline comments
 
@@ -22,24 +22,26 @@
 
#include "station_type.h"
 
#include "newgrf_airport.h"
 
#include "newgrf_callbacks.h"
 
#include "widgets/dropdown_type.h"
 
#include "core/geometry_func.hpp"
 
#include "hotkeys.h"
 
#include "vehicle_func.h"
 
#include "gui.h"
 
#include "command_func.h"
 
#include "airport_cmd.h"
 
#include "station_cmd.h"
 
#include "zoom_func.h"
 
#include "timer/timer.h"
 
#include "timer/timer_game_calendar.h"
 

	
 
#include "widgets/airport_widget.h"
 

	
 
#include "safeguards.h"
 

	
 

	
 
static AirportClassID _selected_airport_class; ///< the currently visible airport class
 
static int _selected_airport_index;            ///< the index of the selected airport in the current class or -1
 
static byte _selected_airport_layout;          ///< selected airport layout number.
 

	
 
static void ShowBuildAirportPicker(Window *parent);
 

	
 
@@ -572,24 +574,28 @@ public:
 
	void OnDropdownSelect(int widget, int index) override
 
	{
 
		assert(widget == WID_AP_CLASS_DROPDOWN);
 
		_selected_airport_class = (AirportClassID)index;
 
		this->vscroll->SetCount(AirportClass::Get(_selected_airport_class)->GetSpecCount());
 
		this->SelectFirstAvailableAirport(false);
 
	}
 

	
 
	void OnRealtimeTick(uint delta_ms) override
 
	{
 
		CheckRedrawStationCoverage(this);
 
	}
 

	
 
	IntervalTimer<TimerGameCalendar> yearly_interval = {{TimerGameCalendar::YEAR, TimerGameCalendar::Priority::NONE}, [this](auto) {
 
		this->InvalidateData();
 
	}};
 
};
 

	
 
static const NWidgetPart _nested_build_airport_widgets[] = {
 
	NWidget(NWID_HORIZONTAL),
 
		NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
 
		NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetDataTip(STR_STATION_BUILD_AIRPORT_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
 
	EndContainer(),
 
	NWidget(WWT_PANEL, COLOUR_DARK_GREEN), SetFill(1, 0), SetPIP(2, 0, 2),
 
		NWidget(WWT_LABEL, COLOUR_DARK_GREEN), SetDataTip(STR_STATION_BUILD_AIRPORT_CLASS_LABEL, STR_NULL), SetFill(1, 0),
 
		NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_AP_CLASS_DROPDOWN), SetFill(1, 0), SetDataTip(STR_BLACK_STRING, STR_STATION_BUILD_AIRPORT_TOOLTIP),
 
		NWidget(WWT_EMPTY, COLOUR_DARK_GREEN, WID_AP_AIRPORT_SPRITE), SetFill(1, 0),
 
		NWidget(NWID_HORIZONTAL),
src/cheat_gui.cpp
Show inline comments
 
@@ -21,24 +21,26 @@
 
#include "strings_func.h"
 
#include "window_func.h"
 
#include "rail_gui.h"
 
#include "settings_gui.h"
 
#include "company_gui.h"
 
#include "linkgraph/linkgraphschedule.h"
 
#include "map_func.h"
 
#include "tile_map.h"
 
#include "newgrf.h"
 
#include "error.h"
 
#include "misc_cmd.h"
 
#include "core/geometry_func.hpp"
 
#include "timer/timer.h"
 
#include "timer/timer_game_calendar.h"
 

	
 
#include "widgets/cheat_widget.h"
 

	
 
#include "table/sprites.h"
 

	
 
#include "safeguards.h"
 

	
 

	
 
/**
 
 * The 'amount' to cheat with.
 
 * This variable is semantically a constant value, but because the cheat
 
 * code requires to be able to write to the variable it is not constified.
 
@@ -408,24 +410,28 @@ struct CheatWindow : Window {
 
		/* Was 'cancel' pressed or nothing entered? */
 
		if (str == nullptr || StrEmpty(str)) return;
 

	
 
		const CheatEntry *ce = &_cheats_ui[clicked_widget];
 
		int oldvalue = (int32)ReadValue(ce->variable, ce->type);
 
		int value = atoi(str);
 
		*ce->been_used = true;
 
		value = ce->proc(value, value - oldvalue);
 

	
 
		if (value != oldvalue) WriteValue(ce->variable, ce->type, (int64)value);
 
		this->SetDirty();
 
	}
 

	
 
	IntervalTimer<TimerGameCalendar> daily_interval = {{TimerGameCalendar::MONTH, TimerGameCalendar::Priority::NONE}, [this](auto) {
 
		this->SetDirty();
 
	}};
 
};
 

	
 
/** Window description of the cheats GUI. */
 
static WindowDesc _cheats_desc(
 
	WDP_AUTO, "cheats", 0, 0,
 
	WC_CHEATS, WC_NONE,
 
	0,
 
	_nested_cheat_widgets, lengthof(_nested_cheat_widgets)
 
);
 

	
 
/** Open cheat window. */
 
void ShowCheatWindow()
src/company_cmd.cpp
Show inline comments
 
@@ -27,24 +27,26 @@
 
#include "sound_func.h"
 
#include "rail.h"
 
#include "core/pool_func.hpp"
 
#include "settings_func.h"
 
#include "vehicle_base.h"
 
#include "vehicle_func.h"
 
#include "smallmap_gui.h"
 
#include "game/game.hpp"
 
#include "goal_base.h"
 
#include "story_base.h"
 
#include "widgets/statusbar_widget.h"
 
#include "company_cmd.h"
 
#include "timer/timer.h"
 
#include "timer/timer_game_calendar.h"
 

	
 
#include "table/strings.h"
 

	
 
#include "safeguards.h"
 

	
 
void ClearEnginesHiddenFlagOfCompany(CompanyID cid);
 
void UpdateObjectColours(const Company *c);
 

	
 
CompanyID _local_company;   ///< Company controlled by the human player at this client. Can also be #COMPANY_SPECTATOR.
 
CompanyID _current_company; ///< Company currently doing an action.
 
Colours _company_colours[MAX_COMPANIES];  ///< NOSAVE: can be determined from company structs.
 
CompanyManagerFace _company_manager_face; ///< for company manager face storage in openttd.cfg
 
@@ -734,43 +736,43 @@ void OnTick_Companies()
 
			 * didn't execute yet, so we cannot loop. */
 
			if (_networking) break;
 
		} while (AI::GetStartNextTime() == 0);
 
	}
 

	
 
	_cur_company_tick_index = (_cur_company_tick_index + 1) % MAX_COMPANIES;
 
}
 

	
 
/**
 
 * A year has passed, update the economic data of all companies, and perhaps show the
 
 * financial overview window of the local company.
 
 */
 
void CompaniesYearlyLoop()
 
static IntervalTimer<TimerGameCalendar> _companies_yearly({TimerGameCalendar::YEAR, TimerGameCalendar::Priority::COMPANY}, [](auto)
 
{
 
	/* Copy statistics */
 
	for (Company *c : Company::Iterate()) {
 
		memmove(&c->yearly_expenses[1], &c->yearly_expenses[0], sizeof(c->yearly_expenses) - sizeof(c->yearly_expenses[0]));
 
		memset(&c->yearly_expenses[0], 0, sizeof(c->yearly_expenses[0]));
 
		SetWindowDirty(WC_FINANCES, c->index);
 
	}
 

	
 
	if (_settings_client.gui.show_finances && _local_company != COMPANY_SPECTATOR) {
 
		ShowCompanyFinances(_local_company);
 
		Company *c = Company::Get(_local_company);
 
		if (c->num_valid_stat_ent > 5 && c->old_economy[0].performance_history < c->old_economy[4].performance_history) {
 
			if (_settings_client.sound.new_year) SndPlayFx(SND_01_BAD_YEAR);
 
		} else {
 
			if (_settings_client.sound.new_year) SndPlayFx(SND_00_GOOD_YEAR);
 
		}
 
	}
 
}
 
});
 

	
 
/**
 
 * Fill the CompanyNewsInformation struct with the required data.
 
 * @param c the current company.
 
 * @param other the other company (use \c nullptr if not relevant).
 
 */
 
CompanyNewsInformation::CompanyNewsInformation(const Company *c, const Company *other)
 
{
 
	SetDParam(0, c->index);
 
	this->company_name = GetString(STR_COMPANY_NAME);
 

	
 
	if (other != nullptr) {
src/currency.cpp
Show inline comments
 
@@ -6,24 +6,26 @@
 
 */
 

	
 
/** @file currency.cpp Support for different currencies. */
 

	
 
#include "stdafx.h"
 
#include "core/bitmath_func.hpp"
 

	
 
#include "currency.h"
 
#include "news_func.h"
 
#include "settings_type.h"
 
#include "date_func.h"
 
#include "string_type.h"
 
#include "timer/timer.h"
 
#include "timer/timer_game_calendar.h"
 

	
 
#include "table/strings.h"
 

	
 
#include "safeguards.h"
 

	
 
	/*   exchange rate    prefix                         symbol_pos
 
	 *   |  separator        |           postfix             |
 
	 *   |   |   Euro year   |              |                | name
 
	 *   |   |    |          |              |                |  | */
 
/** The original currency specifications. */
 
static const CurrencySpec origin_currency_specs[CURRENCY_END] = {
 
	{    1, "", CF_NOEURO, u8"\u00a3",     "",               0, STR_GAME_OPTIONS_CURRENCY_GBP    }, ///< british pound
 
@@ -129,33 +131,33 @@ uint64 GetMaskOfAllowedCurrencies()
 

	
 
		if (to_euro != CF_NOEURO && to_euro != CF_ISEURO && _cur_year >= to_euro) continue;
 
		if (to_euro == CF_ISEURO && _cur_year < 2000) continue;
 
		SetBit(mask, i);
 
	}
 
	SetBit(mask, CURRENCY_CUSTOM); // always allow custom currency
 
	return mask;
 
}
 

	
 
/**
 
 * Verify if the currency chosen by the user is about to be converted to Euro
 
 */
 
void CheckSwitchToEuro()
 
static IntervalTimer<TimerGameCalendar> _check_switch_to_euro({TimerGameCalendar::YEAR, TimerGameCalendar::Priority::NONE}, [](auto)
 
{
 
	if (_currency_specs[_settings_game.locale.currency].to_euro != CF_NOEURO &&
 
			_currency_specs[_settings_game.locale.currency].to_euro != CF_ISEURO &&
 
			_cur_year >= _currency_specs[_settings_game.locale.currency].to_euro) {
 
		_settings_game.locale.currency = 2; // this is the index of euro above.
 
		AddNewsItem(STR_NEWS_EURO_INTRODUCTION, NT_ECONOMY, NF_NORMAL);
 
	}
 
}
 
});
 

	
 
/**
 
 * Will fill _currency_specs array with
 
 * default values from origin_currency_specs
 
 * Called only from newgrf.cpp and settings.cpp.
 
 * @param preserve_custom will not reset custom currency
 
 */
 
void ResetCurrencies(bool preserve_custom)
 
{
 
	for (uint i = 0; i < CURRENCY_END; i++) {
 
		if (preserve_custom && i == CURRENCY_CUSTOM) continue;
 
		_currency_specs[i] = origin_currency_specs[i];
src/currency.h
Show inline comments
 
@@ -93,18 +93,17 @@ struct CurrencySpec {
 
		rate(rate), separator(separator), to_euro(to_euro), prefix(prefix), suffix(suffix), symbol_pos(symbol_pos), name(name)
 
	{
 
	}
 
};
 

	
 
extern CurrencySpec _currency_specs[CURRENCY_END];
 

	
 
/* XXX small hack, but makes the rest of the code a bit nicer to read */
 
#define _custom_currency (_currency_specs[CURRENCY_CUSTOM])
 
#define _currency ((const CurrencySpec*)&_currency_specs[GetGameSettings().locale.currency])
 

	
 
uint64 GetMaskOfAllowedCurrencies();
 
void CheckSwitchToEuro();
 
void ResetCurrencies(bool preserve_custom = true);
 
StringID *BuildCurrencyDropdown();
 
byte GetNewgrfCurrencyIdConverted(byte grfcurr_id);
 

	
 
#endif /* CURRENCY_H */
src/date.cpp
Show inline comments
 
@@ -149,120 +149,12 @@ void ConvertDateToYMD(Date date, YearMon
 
 * @param day   is a number between 1..31
 
 */
 
Date ConvertYMDToDate(Year year, Month month, Day day)
 
{
 
	/* Day-offset in a leap year */
 
	int days = _accum_days_for_month[month] + day - 1;
 

	
 
	/* Account for the missing of the 29th of February in non-leap years */
 
	if (!IsLeapYear(year) && days >= ACCUM_MAR) days--;
 

	
 
	return DAYS_TILL(year) + days;
 
}
 

	
 
/** Functions used by the IncreaseDate function */
 

	
 
extern void EnginesDailyLoop();
 
extern void DisasterDailyLoop();
 
extern void IndustryDailyLoop();
 

	
 
extern void CompaniesMonthlyLoop();
 
extern void EnginesMonthlyLoop();
 
extern void TownsMonthlyLoop();
 
extern void IndustryMonthlyLoop();
 
extern void StationMonthlyLoop();
 
extern void SubsidyMonthlyLoop();
 

	
 
extern void CompaniesYearlyLoop();
 
extern void VehiclesYearlyLoop();
 
extern void TownsYearlyLoop();
 

	
 
extern void ShowEndGameChart();
 

	
 

	
 
/** Available settings for autosave intervals. */
 
static const Month _autosave_months[] = {
 
	 0, ///< never
 
	 1, ///< every month
 
	 3, ///< every 3 months
 
	 6, ///< every 6 months
 
	12, ///< every 12 months
 
};
 

	
 
/**
 
 * Runs various procedures that have to be done yearly
 
 */
 
static IntervalTimer<TimerGameCalendar> _on_new_year({TimerGameCalendar::YEAR, TimerGameCalendar::Priority::NONE}, [](auto)
 
{
 
	CompaniesYearlyLoop();
 
	VehiclesYearlyLoop();
 
	TownsYearlyLoop();
 
	InvalidateWindowClassesData(WC_BUILD_STATION);
 
	InvalidateWindowClassesData(WC_BUS_STATION);
 
	InvalidateWindowClassesData(WC_TRUCK_STATION);
 
	if (_network_server) NetworkServerYearlyLoop();
 

	
 
	if (_cur_year == _settings_client.gui.semaphore_build_before) ResetSignalVariant();
 

	
 
	/* check if we reached end of the game (end of ending year); 0 = never */
 
	if (_cur_year == _settings_game.game_creation.ending_year + 1 && _settings_game.game_creation.ending_year != 0) {
 
		ShowEndGameChart();
 
	}
 

	
 
	/* check if we reached the maximum year, decrement dates by a year */
 
	if (_cur_year == MAX_YEAR + 1) {
 
		int days_this_year;
 

	
 
		_cur_year--;
 
		days_this_year = IsLeapYear(_cur_year) ? DAYS_IN_LEAP_YEAR : DAYS_IN_YEAR;
 
		_date -= days_this_year;
 
		for (Vehicle *v : Vehicle::Iterate()) v->ShiftDates(-days_this_year);
 
		for (LinkGraph *lg : LinkGraph::Iterate()) lg->ShiftDates(-days_this_year);
 

	
 
		/* Because the _date wraps here, and text-messages expire by game-days, we have to clean out
 
		 *  all of them if the date is set back, else those messages will hang for ever */
 
		NetworkInitChatMessage();
 
	}
 

	
 
	if (_settings_client.gui.auto_euro) CheckSwitchToEuro();
 
});
 

	
 
/**
 
 * Runs various procedures that have to be done monthly
 
 */
 
static IntervalTimer<TimerGameCalendar> _on_new_month({TimerGameCalendar::MONTH, TimerGameCalendar::Priority::NONE}, [](auto)
 
{
 
	if (_settings_client.gui.autosave != 0 && (_cur_month % _autosave_months[_settings_client.gui.autosave]) == 0) {
 
		_do_autosave = true;
 
		SetWindowDirty(WC_STATUS_BAR, 0);
 
	}
 

	
 
	SetWindowClassesDirty(WC_CHEATS);
 
	CompaniesMonthlyLoop();
 
	EnginesMonthlyLoop();
 
	TownsMonthlyLoop();
 
	IndustryMonthlyLoop();
 
	SubsidyMonthlyLoop();
 
	StationMonthlyLoop();
 
	if (_network_server) NetworkServerMonthlyLoop();
 
});
 

	
 
/**
 
 * Runs various procedures that have to be done daily
 
 */
 
static IntervalTimer<TimerGameCalendar> _on_new_day({TimerGameCalendar::DAY, TimerGameCalendar::Priority::NONE}, [](auto)
 
{
 
	if (!_newgrf_profilers.empty() && _newgrf_profile_end_date <= _date) {
 
		NewGRFProfiler::FinishAll();
 
	}
 

	
 
	if (_network_server) NetworkServerDailyLoop();
 

	
 
	DisasterDailyLoop();
 
	IndustryDailyLoop();
 

	
 
	SetWindowWidgetDirty(WC_STATUS_BAR, 0, WID_S_LEFT);
 
	EnginesDailyLoop();
 

	
 
	/* Refresh after possible snowline change */
 
	SetWindowClassesDirty(WC_TOWN_VIEW);
 
});
src/disaster_vehicle.cpp
Show inline comments
 
@@ -38,24 +38,26 @@
 
#include "viewport_func.h"
 
#include "vehicle_func.h"
 
#include "sound_func.h"
 
#include "effectvehicle_func.h"
 
#include "roadveh.h"
 
#include "train.h"
 
#include "ai/ai.hpp"
 
#include "game/game.hpp"
 
#include "company_base.h"
 
#include "core/random_func.hpp"
 
#include "core/backup_type.hpp"
 
#include "landscape_cmd.h"
 
#include "timer/timer.h"
 
#include "timer/timer_game_calendar.h"
 

	
 
#include "table/strings.h"
 

	
 
#include "safeguards.h"
 

	
 
/** Delay counter for considering the next disaster. */
 
uint16 _disaster_delay;
 

	
 
static void DisasterClearSquare(TileIndex tile)
 
{
 
	if (EnsureNoVehicleOnGround(tile).Failed()) return;
 

	
 
@@ -926,32 +928,32 @@ static void DoDisaster()
 

	
 
	if (j == 0) return;
 

	
 
	_disasters[buf[RandomRange(j)]].init_proc();
 
}
 

	
 

	
 
static void ResetDisasterDelay()
 
{
 
	_disaster_delay = GB(Random(), 0, 9) + 730;
 
}
 

	
 
void DisasterDailyLoop()
 
static IntervalTimer<TimerGameCalendar> _disaster_daily({TimerGameCalendar::DAY, TimerGameCalendar::Priority::DISASTER}, [](auto)
 
{
 
	if (--_disaster_delay != 0) return;
 

	
 
	ResetDisasterDelay();
 

	
 
	if (_settings_game.difficulty.disasters != 0) DoDisaster();
 
}
 
});
 

	
 
void StartupDisasters()
 
{
 
	ResetDisasterDelay();
 
}
 

	
 
/**
 
 * Marks all disasters targeting this industry in such a way
 
 * they won't call Industry::Get(v->dest_tile) on invalid industry anymore.
 
 * @param i deleted industry
 
 */
 
void ReleaseDisastersTargetingIndustry(IndustryID i)
src/dock_gui.cpp
Show inline comments
 
@@ -21,24 +21,26 @@
 
#include "company_func.h"
 
#include "slope_func.h"
 
#include "tilehighlight_func.h"
 
#include "company_base.h"
 
#include "hotkeys.h"
 
#include "gui.h"
 
#include "zoom_func.h"
 
#include "tunnelbridge_cmd.h"
 
#include "dock_cmd.h"
 
#include "station_cmd.h"
 
#include "water_cmd.h"
 
#include "waypoint_cmd.h"
 
#include "timer/timer.h"
 
#include "timer/timer_game_calendar.h"
 

	
 
#include "widgets/dock_widget.h"
 

	
 
#include "table/sprites.h"
 
#include "table/strings.h"
 

	
 
#include "safeguards.h"
 

	
 
static void ShowBuildDockStationPicker(Window *parent);
 
static void ShowBuildDocksDepotPicker(Window *parent);
 

	
 
static Axis _ship_depot_direction;
 
@@ -468,24 +470,28 @@ public:
 
				this->LowerWidget(_settings_client.gui.station_show_coverage + BDSW_LT_OFF);
 
				if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
 
				this->SetDirty();
 
				SetViewportCatchmentStation(nullptr, true);
 
				break;
 
		}
 
	}
 

	
 
	void OnRealtimeTick(uint delta_ms) override
 
	{
 
		CheckRedrawStationCoverage(this);
 
	}
 

	
 
	IntervalTimer<TimerGameCalendar> yearly_interval = {{TimerGameCalendar::YEAR, TimerGameCalendar::Priority::NONE}, [this](auto) {
 
		this->InvalidateData();
 
	}};
 
};
 

	
 
/** Nested widget parts of a build dock station window. */
 
static const NWidgetPart _nested_build_dock_station_widgets[] = {
 
	NWidget(NWID_HORIZONTAL),
 
		NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
 
		NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetDataTip(STR_STATION_BUILD_DOCK_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
 
	EndContainer(),
 
	NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BDSW_BACKGROUND),
 
		NWidget(WWT_LABEL, COLOUR_DARK_GREEN, BDSW_INFO), SetPadding(WidgetDimensions::unscaled.framerect), SetDataTip(STR_STATION_BUILD_COVERAGE_AREA_TITLE, STR_NULL), SetFill(1, 0),
 
		NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(14, 0, 14),
 
			NWidget(WWT_TEXTBTN, COLOUR_GREY, BDSW_LT_OFF), SetMinimalSize(60, 12), SetFill(1, 0), SetDataTip(STR_STATION_BUILD_COVERAGE_OFF, STR_STATION_BUILD_COVERAGE_AREA_OFF_TOOLTIP),
src/economy.cpp
Show inline comments
 
@@ -43,24 +43,26 @@
 
#include "core/pool_func.hpp"
 
#include "core/backup_type.hpp"
 
#include "cargo_type.h"
 
#include "water.h"
 
#include "game/game.hpp"
 
#include "cargomonitor.h"
 
#include "goal_base.h"
 
#include "story_base.h"
 
#include "linkgraph/refresh.h"
 
#include "company_cmd.h"
 
#include "economy_cmd.h"
 
#include "vehicle_cmd.h"
 
#include "timer/timer.h"
 
#include "timer/timer_game_calendar.h"
 

	
 
#include "table/strings.h"
 
#include "table/pricebase.h"
 

	
 
#include "safeguards.h"
 

	
 

	
 
/* Initialize the cargo payment-pool */
 
CargoPaymentPool _cargo_payment_pool("CargoPayment");
 
INSTANTIATE_POOL_METHODS(CargoPayment)
 

	
 
/**
 
@@ -1974,34 +1976,34 @@ void LoadUnloadStation(Station *st)
 
	}
 

	
 
	/* Call the production machinery of industries */
 
	for (Industry *iid : _cargo_delivery_destinations) {
 
		TriggerIndustryProduction(iid);
 
	}
 
	_cargo_delivery_destinations.clear();
 
}
 

	
 
/**
 
 * Monthly update of the economic data (of the companies as well as economic fluctuations).
 
 */
 
void CompaniesMonthlyLoop()
 
static IntervalTimer<TimerGameCalendar> _companies_monthly({TimerGameCalendar::MONTH, TimerGameCalendar::Priority::COMPANY}, [](auto)
 
{
 
	CompaniesGenStatistics();
 
	if (_settings_game.economy.inflation) {
 
		AddInflation();
 
		RecomputePrices();
 
	}
 
	CompaniesPayInterest();
 
	HandleEconomyFluctuations();
 
}
 
});
 

	
 
static void DoAcquireCompany(Company *c)
 
{
 
	CompanyID ci = c->index;
 

	
 
	CompanyNewsInformation *cni = new CompanyNewsInformation(c, Company::Get(_current_company));
 

	
 
	SetDParam(0, STR_NEWS_COMPANY_MERGER_TITLE);
 
	SetDParam(1, c->bankrupt_value == 0 ? STR_NEWS_MERGER_TAKEOVER_TITLE : STR_NEWS_COMPANY_MERGER_DESCRIPTION);
 
	SetDParamStr(2, cni->company_name);
 
	SetDParamStr(3, cni->other_company_name);
 
	SetDParam(4, c->bankrupt_value);
src/engine.cpp
Show inline comments
 
@@ -21,24 +21,26 @@
 
#include "autoreplace_gui.h"
 
#include "string_func.h"
 
#include "ai/ai.hpp"
 
#include "core/pool_func.hpp"
 
#include "engine_gui.h"
 
#include "engine_func.h"
 
#include "engine_base.h"
 
#include "company_base.h"
 
#include "vehicle_func.h"
 
#include "articulated_vehicles.h"
 
#include "error.h"
 
#include "engine_base.h"
 
#include "timer/timer.h"
 
#include "timer/timer_game_calendar.h"
 

	
 
#include "table/strings.h"
 
#include "table/engines.h"
 

	
 
#include "safeguards.h"
 

	
 
EnginePool _engine_pool("Engine");
 
INSTANTIATE_POOL_METHODS(Engine)
 

	
 
EngineOverrideManager _engine_mngr;
 

	
 
/**
 
@@ -869,25 +871,25 @@ static bool IsVehicleTypeDisabled(Vehicl
 
{
 
	switch (type) {
 
		case VEH_TRAIN:    return _settings_game.vehicle.max_trains == 0   || (ai && _settings_game.ai.ai_disable_veh_train);
 
		case VEH_ROAD:     return _settings_game.vehicle.max_roadveh == 0  || (ai && _settings_game.ai.ai_disable_veh_roadveh);
 
		case VEH_SHIP:     return _settings_game.vehicle.max_ships == 0    || (ai && _settings_game.ai.ai_disable_veh_ship);
 
		case VEH_AIRCRAFT: return _settings_game.vehicle.max_aircraft == 0 || (ai && _settings_game.ai.ai_disable_veh_aircraft);
 

	
 
		default: NOT_REACHED();
 
	}
 
}
 

	
 
/** Daily check to offer an exclusive engine preview to the companies. */
 
void EnginesDailyLoop()
 
static IntervalTimer<TimerGameCalendar> _engines_daily({TimerGameCalendar::DAY, TimerGameCalendar::Priority::ENGINE}, [](auto)
 
{
 
	for (Company *c : Company::Iterate()) {
 
		c->avail_railtypes = AddDateIntroducedRailTypes(c->avail_railtypes, _date);
 
		c->avail_roadtypes = AddDateIntroducedRoadTypes(c->avail_roadtypes, _date);
 
	}
 

	
 
	if (_cur_year >= _year_engine_aging_stops) return;
 

	
 
	for (Engine *e : Engine::Iterate()) {
 
		EngineID i = e->index;
 
		if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) {
 
			if (e->preview_company != INVALID_COMPANY) {
 
@@ -906,25 +908,25 @@ void EnginesDailyLoop()
 
				SetBit(e->preview_asked, e->preview_company);
 
				e->preview_wait = 20;
 
				/* AIs are intentionally not skipped for preview even if they cannot build a certain
 
				 * vehicle type. This is done to not give poor performing human companies an "unfair"
 
				 * boost that they wouldn't have gotten against other human companies. The check on
 
				 * the line below is just to make AIs not notice that they have a preview if they
 
				 * cannot build the vehicle. */
 
				if (!IsVehicleTypeDisabled(e->type, true)) AI::NewEvent(e->preview_company, new ScriptEventEnginePreview(i));
 
				if (IsInteractiveCompany(e->preview_company)) ShowEnginePreviewWindow(i);
 
			}
 
		}
 
	}
 
}
 
});
 

	
 
/**
 
 * Clear the 'hidden' flag for all engines of a new company.
 
 * @param cid Company being created.
 
 */
 
void ClearEnginesHiddenFlagOfCompany(CompanyID cid)
 
{
 
	for (Engine *e : Engine::Iterate()) {
 
		SB(e->company_hidden, cid, 1, 0);
 
	}
 
}
 

	
 
@@ -1101,24 +1103,29 @@ void EnginesMonthlyLoop()
 
			}
 
		}
 

	
 
		InvalidateWindowClassesData(WC_BUILD_VEHICLE); // rebuild the purchase list (esp. when sorted by reliability)
 

	
 
		if (refresh) {
 
			SetWindowClassesDirty(WC_BUILD_VEHICLE);
 
			SetWindowClassesDirty(WC_REPLACE_VEHICLE);
 
		}
 
	}
 
}
 

	
 
static IntervalTimer<TimerGameCalendar> _engines_monthly({TimerGameCalendar::MONTH, TimerGameCalendar::Priority::ENGINE}, [](auto)
 
{
 
	EnginesMonthlyLoop();
 
});
 

	
 
/**
 
 * Is \a name still free as name for an engine?
 
 * @param name New name of an engine.
 
 * @return \c false if the name is being used already, else \c true.
 
 */
 
static bool IsUniqueEngineName(const std::string &name)
 
{
 
	for (const Engine *e : Engine::Iterate()) {
 
		if (!e->name.empty() && e->name == name) return false;
 
	}
 

	
 
	return true;
src/highscore_gui.cpp
Show inline comments
 
@@ -13,24 +13,27 @@
 
#include "gfx_func.h"
 
#include "table/sprites.h"
 
#include "window_gui.h"
 
#include "window_func.h"
 
#include "network/network.h"
 
#include "command_func.h"
 
#include "company_func.h"
 
#include "company_base.h"
 
#include "strings_func.h"
 
#include "hotkeys.h"
 
#include "zoom_func.h"
 
#include "misc_cmd.h"
 
#include "timer/timer.h"
 
#include "timer/timer_game_calendar.h"
 
#include "date_func.h"
 

	
 
#include "widgets/highscore_widget.h"
 

	
 
#include "safeguards.h"
 

	
 
struct EndGameHighScoreBaseWindow : Window {
 
	uint32 background_img;
 
	int8 rank;
 

	
 
	EndGameHighScoreBaseWindow(WindowDesc *desc) : Window(desc)
 
	{
 
		this->InitNested();
 
@@ -241,12 +244,23 @@ void ShowHighscoreTable(int difficulty, 
 
 * Show the endgame victory screen in 2050. Update the new highscore
 
 * if it was high enough
 
 */
 
void ShowEndGameChart()
 
{
 
	/* Dedicated server doesn't need the highscore window and neither does -v null. */
 
	if (_network_dedicated || (!_networking && !Company::IsValidID(_local_company))) return;
 

	
 
	HideVitalWindows();
 
	CloseWindowByClass(WC_ENDSCREEN);
 
	new EndGameWindow(&_endgame_desc);
 
}
 

	
 
static IntervalTimer<TimerGameCalendar> _check_end_game({TimerGameCalendar::YEAR, TimerGameCalendar::Priority::NONE}, [](auto)
 
{
 
	/* 0 = never */
 
	if (_settings_game.game_creation.ending_year == 0) return;
 

	
 
	/* Show the end-game chart at the end of the ending year (hence the + 1). */
 
	if (_cur_year == _settings_game.game_creation.ending_year + 1) {
 
		ShowEndGameChart();
 
	}
 
});
src/industry_cmd.cpp
Show inline comments
 
@@ -35,24 +35,26 @@
 
#include "effectvehicle_base.h"
 
#include "ai/ai.hpp"
 
#include "core/pool_func.hpp"
 
#include "subsidy_func.h"
 
#include "core/backup_type.hpp"
 
#include "object_base.h"
 
#include "game/game.hpp"
 
#include "error.h"
 
#include "string_func.h"
 
#include "industry_cmd.h"
 
#include "landscape_cmd.h"
 
#include "terraform_cmd.h"
 
#include "timer/timer.h"
 
#include "timer/timer_game_calendar.h"
 

	
 
#include "table/strings.h"
 
#include "table/industry_land.h"
 
#include "table/build_industry.h"
 

	
 
#include "safeguards.h"
 

	
 
IndustryPool _industry_pool("Industry");
 
INSTANTIATE_POOL_METHODS(Industry)
 

	
 
void ShowIndustryViewWindow(int industry);
 
void BuildOilRig(TileIndex tile);
 
@@ -2938,25 +2940,25 @@ static void ChangeIndustryProduction(Ind
 
			AddIndustryNewsItem(str, nt, i->index);
 
		}
 
	}
 
}
 

	
 
/**
 
 * Daily handler for the industry changes
 
 * Taking the original map size of 256*256, the number of random changes was always of just one unit.
 
 * But it cannot be the same on smaller or bigger maps. That number has to be scaled up or down.
 
 * For small maps, it implies that less than one change per month is required, while on bigger maps,
 
 * it would be way more. The daily loop handles those changes.
 
 */
 
void IndustryDailyLoop()
 
static IntervalTimer<TimerGameCalendar> _industries_daily({TimerGameCalendar::DAY, TimerGameCalendar::Priority::INDUSTRY}, [](auto)
 
{
 
	_economy.industry_daily_change_counter += _economy.industry_daily_increment;
 

	
 
	/* Bits 16-31 of industry_construction_counter contain the number of industries to change/create today,
 
	 * the lower 16 bit are a fractional part that might accumulate over several days until it
 
	 * is sufficient for an industry. */
 
	uint16 change_loop = _economy.industry_daily_change_counter >> 16;
 

	
 
	/* Reset the active part of the counter, just keeping the "fractional part" */
 
	_economy.industry_daily_change_counter &= 0xFFFF;
 

	
 
	if (change_loop == 0) {
 
@@ -2978,47 +2980,47 @@ void IndustryDailyLoop()
 
			Industry *i = Industry::GetRandom();
 
			if (i != nullptr) {
 
				ChangeIndustryProduction(i, false);
 
				SetWindowDirty(WC_INDUSTRY_VIEW, i->index);
 
			}
 
		}
 
	}
 

	
 
	cur_company.Restore();
 

	
 
	/* production-change */
 
	InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, IDIWD_PRODUCTION_CHANGE);
 
}
 

	
 
void IndustryMonthlyLoop()
 
});
 

	
 
static IntervalTimer<TimerGameCalendar> _industries_monthly({TimerGameCalendar::MONTH, TimerGameCalendar::Priority::INDUSTRY}, [](auto)
 
{
 
	Backup<CompanyID> cur_company(_current_company, OWNER_NONE, FILE_LINE);
 

	
 
	_industry_builder.MonthlyLoop();
 

	
 
	for (Industry *i : Industry::Iterate()) {
 
		UpdateIndustryStatistics(i);
 
		if (i->prod_level == PRODLEVEL_CLOSURE) {
 
			delete i;
 
		} else {
 
			ChangeIndustryProduction(i, true);
 
			SetWindowDirty(WC_INDUSTRY_VIEW, i->index);
 
		}
 
	}
 

	
 
	cur_company.Restore();
 

	
 
	/* production-change */
 
	InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, IDIWD_PRODUCTION_CHANGE);
 
}
 
});
 

	
 

	
 
void InitializeIndustries()
 
{
 
	Industry::ResetIndustryCounts();
 
	_industry_sound_tile = 0;
 

	
 
	_industry_builder.Reset();
 
}
 

	
 
/** Verify whether the generated industries are complete, and warn the user if not. */
 
void CheckIndustries()
src/network/network_func.h
Show inline comments
 
@@ -56,27 +56,24 @@ bool NetworkClientConnectGame(const std:
 
void NetworkClientJoinGame();
 
void NetworkClientRequestMove(CompanyID company, const std::string &pass = "");
 
void NetworkClientSendRcon(const std::string &password, const std::string &command);
 
void NetworkClientSendChat(NetworkAction action, DestType type, int dest, const std::string &msg, int64 data = 0);
 
bool NetworkClientPreferTeamChat(const NetworkClientInfo *cio);
 
bool NetworkCompanyIsPassworded(CompanyID company_id);
 
uint NetworkMaxCompaniesAllowed();
 
bool NetworkMaxCompaniesReached();
 
void NetworkPrintClients();
 
void NetworkHandlePauseChange(PauseMode prev_mode, PauseMode changed_mode);
 

	
 
/*** Commands ran by the server ***/
 
void NetworkServerDailyLoop();
 
void NetworkServerMonthlyLoop();
 
void NetworkServerYearlyLoop();
 
void NetworkServerSendConfigUpdate();
 
void NetworkServerUpdateGameInfo();
 
void NetworkServerShowStatusToConsole();
 
bool NetworkServerStart();
 
void NetworkServerNewCompany(const Company *company, NetworkClientInfo *ci);
 
bool NetworkServerChangeClientName(ClientID client_id, const std::string &new_name);
 

	
 

	
 
void NetworkServerDoMove(ClientID client_id, CompanyID company_id);
 
void NetworkServerSendRcon(ClientID client_id, TextColour colour_code, const std::string &string);
 
void NetworkServerSendChat(NetworkAction action, DestType type, int dest, const std::string &msg, ClientID from_id, int64 data = 0, bool from_admin = false);
 
void NetworkServerSendExternalChat(const std::string &source, TextColour colour, const std::string &user, const std::string &msg);
src/network/network_server.cpp
Show inline comments
 
@@ -22,24 +22,26 @@
 
#include "../saveload/saveload_filter.h"
 
#include "../station_base.h"
 
#include "../genworld.h"
 
#include "../company_func.h"
 
#include "../company_gui.h"
 
#include "../company_cmd.h"
 
#include "../roadveh.h"
 
#include "../order_backup.h"
 
#include "../core/pool_func.hpp"
 
#include "../core/random_func.hpp"
 
#include "../company_cmd.h"
 
#include "../rev.h"
 
#include "../timer/timer.h"
 
#include "../timer/timer_game_calendar.h"
 
#include <mutex>
 
#include <condition_variable>
 

	
 
#include "../safeguards.h"
 

	
 

	
 
/* This file handles all the server-commands */
 

	
 
DECLARE_POSTFIX_INCREMENT(ClientID)
 
/** The identifier counter for new clients (is never decreased) */
 
static ClientID _network_client_id = CLIENT_ID_FIRST;
 

	
 
@@ -1803,44 +1805,50 @@ void NetworkServer_Tick(bool send_frame)
 
			/* Send an updated _frame_counter_max to the client */
 
			if (send_frame) cs->SendFrame();
 

	
 
#ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
 
			/* Send a sync-check packet */
 
			if (send_sync) cs->SendSync();
 
#endif
 
		}
 
	}
 
}
 

	
 
/** Yearly "callback". Called whenever the year changes. */
 
void NetworkServerYearlyLoop()
 
static IntervalTimer<TimerGameCalendar> _network_yearly({TimerGameCalendar::YEAR, TimerGameCalendar::Priority::NONE}, [](auto)
 
{
 
	if (!_network_server) return;
 

	
 
	NetworkCheckRestartMap();
 
	NetworkAdminUpdate(ADMIN_FREQUENCY_ANUALLY);
 
}
 
});
 

	
 
/** Monthly "callback". Called whenever the month changes. */
 
void NetworkServerMonthlyLoop()
 
static IntervalTimer<TimerGameCalendar> _network_monthly({TimerGameCalendar::MONTH, TimerGameCalendar::Priority::NONE}, [](auto)
 
{
 
	if (!_network_server) return;
 

	
 
	NetworkAutoCleanCompanies();
 
	NetworkAdminUpdate(ADMIN_FREQUENCY_MONTHLY);
 
	if ((_cur_month % 3) == 0) NetworkAdminUpdate(ADMIN_FREQUENCY_QUARTERLY);
 
}
 
});
 

	
 
/** Daily "callback". Called whenever the date changes. */
 
void NetworkServerDailyLoop()
 
static IntervalTimer<TimerGameCalendar> _network_daily({TimerGameCalendar::DAY, TimerGameCalendar::Priority::NONE}, [](auto)
 
{
 
	if (!_network_server) return;
 

	
 
	NetworkAdminUpdate(ADMIN_FREQUENCY_DAILY);
 
	if ((_date % 7) == 3) NetworkAdminUpdate(ADMIN_FREQUENCY_WEEKLY);
 
}
 
});
 

	
 
/**
 
 * Get the IP address/hostname of the connected client.
 
 * @return The IP address.
 
 */
 
const std::string &ServerNetworkGameSocketHandler::GetClientIP()
 
{
 
	return this->client_address.GetHostname();
 
}
 

	
 
/** Show the status message of all clients on the console. */
 
void NetworkServerShowStatusToConsole()
src/newgrf_profiling.cpp
Show inline comments
 
@@ -5,24 +5,26 @@
 
 * 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 newgrf_profiling.cpp Profiling of NewGRF action 2 handling. */
 

	
 
#include "newgrf_profiling.h"
 
#include "date_func.h"
 
#include "fileio_func.h"
 
#include "string_func.h"
 
#include "console_func.h"
 
#include "spritecache.h"
 
#include "walltime_func.h"
 
#include "timer/timer.h"
 
#include "timer/timer_game_calendar.h"
 

	
 
#include <chrono>
 

	
 

	
 
std::vector<NewGRFProfiler> _newgrf_profilers;
 
Date _newgrf_profile_end_date;
 

	
 

	
 
/**
 
 * Create profiler object and begin profiling session.
 
 * @param grffile   The GRF file to collect profiling data on
 
 * @param end_date  Game date to end profiling on
 
@@ -149,12 +151,22 @@ uint32 NewGRFProfiler::FinishAll()
 
			max_ticks = std::max(max_ticks, _tick_counter - pr.start_tick);
 
		}
 
	}
 

	
 
	if (total_microseconds > 0 && max_ticks > 0) {
 
		IConsolePrint(CC_DEBUG, "Total NewGRF callback processing: {} microseconds over {} ticks.", total_microseconds, max_ticks);
 
	}
 

	
 
	_newgrf_profile_end_date = MAX_DAY;
 

	
 
	return total_microseconds;
 
}
 

	
 
/**
 
 * Check whether profiling is active and should be finished.
 
 */
 
static IntervalTimer<TimerGameCalendar> _check_profiling_finished({TimerGameCalendar::DAY, TimerGameCalendar::Priority::NONE}, [](auto)
 
{
 
	if (_newgrf_profilers.empty() || _newgrf_profile_end_date > _date) return;
 

	
 
	NewGRFProfiler::FinishAll();
 
});
src/openttd.cpp
Show inline comments
 
@@ -92,24 +92,33 @@ bool HandleBootstrap();
 

	
 
extern void AfterLoadCompanyStats();
 
extern Company *DoStartupNewCompany(bool is_ai, CompanyID company = INVALID_COMPANY);
 
extern void OSOpenBrowser(const char *url);
 
extern void RebuildTownCaches();
 
extern void ShowOSErrorBox(const char *buf, bool system);
 
extern std::string _config_file;
 

	
 
bool _save_config = false;
 
bool _request_newgrf_scan = false;
 
NewGRFScanCallback *_request_newgrf_scan_callback = nullptr;
 

	
 
/** Available settings for autosave intervals. */
 
static const Month _autosave_months[] = {
 
	 0, ///< never
 
	 1, ///< every month
 
	 3, ///< every 3 months
 
	 6, ///< every 6 months
 
	12, ///< every 12 months
 
};
 

	
 
/**
 
 * Error handling for fatal user errors.
 
 * @param s the string to print.
 
 * @note Does NEVER return.
 
 */
 
void CDECL usererror(const char *s, ...)
 
{
 
	va_list va;
 
	char buf[512];
 

	
 
	va_start(va, s);
 
	vseprintf(buf, lastof(buf), s, va);
 
@@ -1423,24 +1432,33 @@ void StateGameLoop()
 
		}
 
#endif
 
		UpdateLandscapingLimits();
 

	
 
		CallWindowGameTickEvent();
 
		NewsLoop();
 
		cur_company.Restore();
 
	}
 

	
 
	assert(IsLocalCompany());
 
}
 

	
 
static IntervalTimer<TimerGameCalendar> _autosave_interval({TimerGameCalendar::MONTH, TimerGameCalendar::Priority::AUTOSAVE}, [](auto)
 
{
 
	if (_settings_client.gui.autosave == 0) return;
 
	if ((_cur_month % _autosave_months[_settings_client.gui.autosave]) != 0) return;
 

	
 
	_do_autosave = true;
 
	SetWindowDirty(WC_STATUS_BAR, 0);
 
});
 

	
 
/**
 
 * Create an autosave. The default name is "autosave#.sav". However with
 
 * the setting 'keep_all_autosave' the name defaults to company-name + date
 
 */
 
static void DoAutosave()
 
{
 
	static FiosNumberedSaveName _autosave_ctr("autosave");
 
	DoAutoOrNetsave(_autosave_ctr);
 
}
 

	
 
/**
 
 * Request a new NewGRF scan. This will be executed on the next game-tick.
src/rail_gui.cpp
Show inline comments
 
@@ -31,24 +31,26 @@
 
#include "engine_base.h"
 
#include "vehicle_func.h"
 
#include "zoom_func.h"
 
#include "rail_gui.h"
 
#include "querystring_gui.h"
 
#include "sortlist_type.h"
 
#include "stringfilter_type.h"
 
#include "string_func.h"
 
#include "station_cmd.h"
 
#include "tunnelbridge_cmd.h"
 
#include "waypoint_cmd.h"
 
#include "rail_cmd.h"
 
#include "timer/timer.h"
 
#include "timer/timer_game_calendar.h"
 

	
 
#include "station_map.h"
 
#include "tunnelbridge_map.h"
 

	
 
#include "widgets/rail_widget.h"
 

	
 
#include "safeguards.h"
 

	
 

	
 
static RailType _cur_railtype;               ///< Rail type of the current build-rail toolbar.
 
static bool _remove_button_clicked;          ///< Flag whether 'remove' toggle-button is currently enabled
 
static DiagDirection _build_depot_direction; ///< Currently selected depot direction
 
@@ -1496,24 +1498,28 @@ public:
 
				this->SetDirty();
 
				CloseWindowById(WC_SELECT_STATION, 0);
 
				break;
 
			}
 
		}
 
	}
 

	
 
	void OnRealtimeTick(uint delta_ms) override
 
	{
 
		CheckRedrawStationCoverage(this);
 
	}
 

	
 
	IntervalTimer<TimerGameCalendar> yearly_interval = {{TimerGameCalendar::YEAR, TimerGameCalendar::Priority::NONE}, [this](auto) {
 
		this->SetDirty();
 
	}};
 

	
 
	static HotkeyList hotkeys;
 
};
 

	
 
/**
 
 * Handler for global hotkeys of the BuildRailStationWindow.
 
 * @param hotkey Hotkey
 
 * @return ES_HANDLED if hotkey was accepted.
 
 */
 
static EventState BuildRailStationGlobalHotkeys(int hotkey)
 
{
 
	if (_game_mode == GM_MENU) return ES_NOT_HANDLED;
 
	Window *w = ShowStationBuilder(FindWindowById(WC_BUILD_TOOLBAR, TRANSPORT_RAIL));
 
@@ -2192,24 +2198,31 @@ void ResetSignalVariant(int32 new_value)
 
	SignalVariant new_variant = (_cur_year < _settings_client.gui.semaphore_build_before ? SIG_SEMAPHORE : SIG_ELECTRIC);
 

	
 
	if (new_variant != _cur_signal_variant) {
 
		Window *w = FindWindowById(WC_BUILD_SIGNAL, 0);
 
		if (w != nullptr) {
 
			w->SetDirty();
 
			w->RaiseWidget((_cur_signal_variant == SIG_ELECTRIC ? WID_BS_ELECTRIC_NORM : WID_BS_SEMAPHORE_NORM) + _cur_signal_type);
 
		}
 
		_cur_signal_variant = new_variant;
 
	}
 
}
 

	
 
static IntervalTimer<TimerGameCalendar> _check_reset_signal({TimerGameCalendar::YEAR, TimerGameCalendar::Priority::NONE}, [](auto)
 
{
 
	if (_cur_year != _settings_client.gui.semaphore_build_before) return;
 

	
 
	ResetSignalVariant();
 
});
 

	
 
/**
 
 * Resets the rail GUI - sets default railtype to build
 
 * and resets the signal GUI
 
 */
 
void InitializeRailGUI()
 
{
 
	SetDefaultRailGui();
 

	
 
	_convert_signal_button = false;
 
	_cur_signal_type = _settings_client.gui.default_signal_type;
 
	ResetSignalVariant();
 
}
src/road_gui.cpp
Show inline comments
 
@@ -30,24 +30,26 @@
 
#include "engine_base.h"
 
#include "strings_func.h"
 
#include "core/geometry_func.hpp"
 
#include "date_func.h"
 
#include "station_cmd.h"
 
#include "road_cmd.h"
 
#include "tunnelbridge_cmd.h"
 
#include "newgrf_roadstop.h"
 
#include "querystring_gui.h"
 
#include "sortlist_type.h"
 
#include "stringfilter_type.h"
 
#include "string_func.h"
 
#include "timer/timer.h"
 
#include "timer/timer_game_calendar.h"
 

	
 
#include "widgets/road_widget.h"
 

	
 
#include "table/strings.h"
 

	
 
#include "safeguards.h"
 

	
 
static void ShowRVStationPicker(Window *parent, RoadStopType rs);
 
static void ShowRoadDepotPicker(Window *parent);
 

	
 
static bool _remove_button_clicked;
 
static bool _one_way_button_clicked;
 
@@ -1577,24 +1579,28 @@ public:
 
			}
 

	
 
			default:
 
				break;
 
		}
 
	}
 

	
 
	void OnRealtimeTick(uint delta_ms) override
 
	{
 
		CheckRedrawStationCoverage(this);
 
	}
 

	
 
	IntervalTimer<TimerGameCalendar> yearly_interval = {{TimerGameCalendar::YEAR, TimerGameCalendar::Priority::NONE}, [this](auto) {
 
		this->InvalidateData();
 
	}};
 

	
 
	static HotkeyList hotkeys;
 
};
 

	
 
static Hotkey buildroadstop_hotkeys[] = {
 
	Hotkey('F', "focus_filter_box", BROSHK_FOCUS_FILTER_BOX),
 
	HOTKEY_LIST_END
 
};
 
HotkeyList BuildRoadStationWindow::hotkeys("buildroadstop", buildroadstop_hotkeys);
 

	
 
Listing BuildRoadStationWindow::last_sorting = { false, 0 };
 
Filtering BuildRoadStationWindow::last_filtering = { false, 0 };
 

	
src/station_cmd.cpp
Show inline comments
 
@@ -51,24 +51,26 @@
 
#include "order_backup.h"
 
#include "newgrf_house.h"
 
#include "company_gui.h"
 
#include "linkgraph/linkgraph_base.h"
 
#include "linkgraph/refresh.h"
 
#include "widgets/station_widget.h"
 
#include "tunnelbridge_map.h"
 
#include "station_cmd.h"
 
#include "waypoint_cmd.h"
 
#include "landscape_cmd.h"
 
#include "rail_cmd.h"
 
#include "newgrf_roadstop.h"
 
#include "timer/timer.h"
 
#include "timer/timer_game_calendar.h"
 

	
 
#include "table/strings.h"
 

	
 
#include "safeguards.h"
 

	
 
/**
 
 * Static instance of FlowStat::SharesMap.
 
 * Note: This instance is created on task start.
 
 *       Lazy creation on first usage results in a data race between the CDist threads.
 
 */
 
/* static */ const FlowStat::SharesMap FlowStat::empty_sharesmap;
 

	
 
@@ -3998,35 +4000,34 @@ void OnTick_Station()
 
		 * at the same time. */
 
		if ((_tick_counter + st->index) % STATION_ACCEPTANCE_TICKS == 0) {
 
			/* Stop processing this station if it was deleted */
 
			if (!StationHandleBigTick(st)) continue;
 
			TriggerStationAnimation(st, st->xy, SAT_250_TICKS);
 
			TriggerRoadStopAnimation(st, st->xy, SAT_250_TICKS);
 
			if (Station::IsExpected(st)) AirportAnimationTrigger(Station::From(st), AAT_STATION_250_TICKS);
 
		}
 
	}
 
}
 

	
 
/** Monthly loop for stations. */
 
void StationMonthlyLoop()
 
static IntervalTimer<TimerGameCalendar> _stations_monthly({TimerGameCalendar::MONTH, TimerGameCalendar::Priority::STATION}, [](auto)
 
{
 
	for (Station *st : Station::Iterate()) {
 
		for (CargoID i = 0; i < NUM_CARGO; i++) {
 
			GoodsEntry *ge = &st->goods[i];
 
			SB(ge->status, GoodsEntry::GES_LAST_MONTH, 1, GB(ge->status, GoodsEntry::GES_CURRENT_MONTH, 1));
 
			ClrBit(ge->status, GoodsEntry::GES_CURRENT_MONTH);
 
		}
 
	}
 
}
 

	
 
});
 

	
 
void ModifyStationRatingAround(TileIndex tile, Owner owner, int amount, uint radius)
 
{
 
	ForAllStationsRadius(tile, radius, [&](Station *st) {
 
		if (st->owner == owner && DistanceManhattan(tile, st->xy) <= radius) {
 
			for (CargoID i = 0; i < NUM_CARGO; i++) {
 
				GoodsEntry *ge = &st->goods[i];
 

	
 
				if (ge->status != 0) {
 
					ge->rating = Clamp(ge->rating + amount, 0, 255);
 
				}
 
			}
src/statusbar_gui.cpp
Show inline comments
 
@@ -18,24 +18,25 @@
 
#include "company_base.h"
 
#include "tilehighlight_func.h"
 
#include "news_gui.h"
 
#include "company_gui.h"
 
#include "window_gui.h"
 
#include "saveload/saveload.h"
 
#include "window_func.h"
 
#include "statusbar_gui.h"
 
#include "toolbar_gui.h"
 
#include "core/geometry_func.hpp"
 
#include "zoom_func.h"
 
#include "timer/timer.h"
 
#include "timer/timer_game_calendar.h"
 
#include "timer/timer_window.h"
 

	
 
#include "widgets/statusbar_widget.h"
 

	
 
#include "table/strings.h"
 
#include "table/sprites.h"
 

	
 
#include "safeguards.h"
 

	
 
static bool DrawScrollingStatusText(const NewsItem *ni, int scroll_pos, int left, int right, int top, int bottom)
 
{
 
	CopyInDParam(0, ni->params, lengthof(ni->params));
 
@@ -224,24 +225,28 @@ struct StatusBarWindow : Window {
 
	IntervalTimer<TimerWindow> ticker_scroll_interval = {std::chrono::milliseconds(15), [this](uint count) {
 
		if (_pause_mode != PM_UNPAUSED) return;
 

	
 
		if (this->ticker_scroll < TICKER_STOP) {
 
			this->ticker_scroll += count;
 
			this->SetWidgetDirty(WID_S_MIDDLE);
 
		}
 
	}};
 

	
 
	TimeoutTimer<TimerWindow> reminder_timeout = {REMINDER_START, [this]() {
 
		this->SetWidgetDirty(WID_S_MIDDLE);
 
	}};
 

	
 
	IntervalTimer<TimerGameCalendar> daily_interval = {{TimerGameCalendar::DAY, TimerGameCalendar::Priority::NONE}, [this](auto) {
 
		this->SetWidgetDirty(WID_S_LEFT);
 
	}};
 
};
 

	
 
static const NWidgetPart _nested_main_status_widgets[] = {
 
	NWidget(NWID_HORIZONTAL),
 
		NWidget(WWT_PANEL, COLOUR_GREY, WID_S_LEFT), SetMinimalSize(140, 12), EndContainer(),
 
		NWidget(WWT_PUSHBTN, COLOUR_GREY, WID_S_MIDDLE), SetMinimalSize(40, 12), SetDataTip(0x0, STR_STATUSBAR_TOOLTIP_SHOW_LAST_NEWS), SetResize(1, 0),
 
		NWidget(WWT_PUSHBTN, COLOUR_GREY, WID_S_RIGHT), SetMinimalSize(140, 12),
 
	EndContainer(),
 
};
 

	
 
static WindowDesc _main_status_desc(
 
	WDP_MANUAL, nullptr, 0, 0,
src/subsidy.cpp
Show inline comments
 
@@ -16,24 +16,26 @@
 
#include "station_base.h"
 
#include "strings_func.h"
 
#include "window_func.h"
 
#include "subsidy_base.h"
 
#include "subsidy_func.h"
 
#include "core/pool_func.hpp"
 
#include "core/random_func.hpp"
 
#include "game/game.hpp"
 
#include "command_func.h"
 
#include "string_func.h"
 
#include "tile_cmd.h"
 
#include "subsidy_cmd.h"
 
#include "timer/timer.h"
 
#include "timer/timer_game_calendar.h"
 

	
 
#include "table/strings.h"
 

	
 
#include "safeguards.h"
 

	
 
SubsidyPool _subsidy_pool("Subsidy"); ///< Pool for the subsidies.
 
INSTANTIATE_POOL_METHODS(Subsidy)
 

	
 
/**
 
 * Marks subsidy as awarded, creates news and AI event
 
 * @param company awarded company
 
 */
 
@@ -468,25 +470,25 @@ bool FindSubsidyCargoDestination(CargoID
 
	/* Check distance between source and destination. */
 
	if (!CheckSubsidyDistance(src_type, src, dst_type, dst)) return false;
 

	
 
	/* Avoid duplicate subsidies. */
 
	if (CheckSubsidyDuplicate(cid, src_type, src, dst_type, dst)) return false;
 

	
 
	CreateSubsidy(cid, src_type, src, dst_type, dst);
 

	
 
	return true;
 
}
 

	
 
/** Perform the monthly update of open subsidies, and try to create a new one. */
 
void SubsidyMonthlyLoop()
 
static IntervalTimer<TimerGameCalendar> _subsidies_monthly({TimerGameCalendar::MONTH, TimerGameCalendar::Priority::SUBSIDY}, [](auto)
 
{
 
	bool modified = false;
 

	
 
	for (Subsidy *s : Subsidy::Iterate()) {
 
		if (--s->remaining == 0) {
 
			if (!s->IsAwarded()) {
 
				std::pair<NewsReferenceType, NewsReferenceType> reftype = SetupSubsidyDecodeParam(s, SubsidyDecodeParamType::NewsWithdrawn);
 
				AddNewsItem(STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED, NT_SUBSIDIES, NF_NORMAL, reftype.first, s->src, reftype.second, s->dst);
 
				AI::BroadcastNewEvent(new ScriptEventSubsidyOfferExpired(s->index));
 
				Game::NewEvent(new ScriptEventSubsidyOfferExpired(s->index));
 
			} else {
 
				if (s->awarded == _local_company) {
 
@@ -538,25 +540,25 @@ void SubsidyMonthlyLoop()
 
	} else if (random_chance == 3) {
 
		/* Cargo subsidies with an industry as a source have a 1/16 chance. */
 
		int n = 1000;
 

	
 
		do {
 
			industry_subsidy = FindSubsidyIndustryCargoRoute();
 
		} while (!industry_subsidy && n--);
 
	}
 

	
 
	modified |= passenger_subsidy || town_subsidy || industry_subsidy;
 

	
 
	if (modified) InvalidateWindowData(WC_SUBSIDIES_LIST, 0);
 
}
 
});
 

	
 
/**
 
 * Tests whether given delivery is subsidised and possibly awards the subsidy to delivering company
 
 * @param cargo_type type of cargo
 
 * @param company company delivering the cargo
 
 * @param src_type type of \a src
 
 * @param src index of source
 
 * @param st station where the cargo is delivered to
 
 * @return is the delivery subsidised?
 
 */
 
bool CheckSubsidised(CargoID cargo_type, CompanyID company, SourceType src_type, SourceID src, const Station *st)
 
{
src/timer/timer_game_calendar.cpp
Show inline comments
 
@@ -77,13 +77,24 @@ void TimerManager<TimerGameCalendar>::El
 

	
 
	if (new_month) {
 
		for (auto timer : timers) {
 
			timer->Elapsed(TimerGameCalendar::MONTH);
 
		}
 
	}
 

	
 
	if (new_year) {
 
		for (auto timer : timers) {
 
			timer->Elapsed(TimerGameCalendar::YEAR);
 
		}
 
	}
 

	
 
	/* check if we reached the maximum year, decrement dates by a year */
 
	if (_cur_year == MAX_YEAR + 1) {
 
		int days_this_year;
 

	
 
		_cur_year--;
 
		days_this_year = IsLeapYear(_cur_year) ? DAYS_IN_LEAP_YEAR : DAYS_IN_YEAR;
 
		_date -= days_this_year;
 
		for (Vehicle *v : Vehicle::Iterate()) v->ShiftDates(-days_this_year);
 
		for (LinkGraph *lg : LinkGraph::Iterate()) lg->ShiftDates(-days_this_year);
 
	}
 
}
src/town_cmd.cpp
Show inline comments
 
@@ -43,24 +43,26 @@
 
#include "core/random_func.hpp"
 
#include "core/backup_type.hpp"
 
#include "depot_base.h"
 
#include "object_map.h"
 
#include "object_base.h"
 
#include "ai/ai.hpp"
 
#include "game/game.hpp"
 
#include "town_cmd.h"
 
#include "landscape_cmd.h"
 
#include "road_cmd.h"
 
#include "terraform_cmd.h"
 
#include "tunnelbridge_cmd.h"
 
#include "timer/timer.h"
 
#include "timer/timer_game_calendar.h"
 

	
 
#include "table/strings.h"
 
#include "table/town_land.h"
 

	
 
#include "safeguards.h"
 

	
 
/* Initialize the town-pool */
 
TownPool _town_pool("Town");
 
INSTANTIATE_POOL_METHODS(Town)
 

	
 

	
 
TownKdtree _town_kdtree(&Kdtree_TownXYFunc);
 
@@ -3747,49 +3749,48 @@ CommandCost CheckforTownRating(DoCommand
 
	 * difficulty setting. Minimum town rating selected by difficulty level
 
	 */
 
	int needed = needed_rating[_settings_game.difficulty.town_council_tolerance][type];
 

	
 
	if (GetRating(t) < needed) {
 
		SetDParam(0, t->index);
 
		return_cmd_error(STR_ERROR_LOCAL_AUTHORITY_REFUSES_TO_ALLOW_THIS);
 
	}
 

	
 
	return CommandCost();
 
}
 

	
 
void TownsMonthlyLoop()
 
static IntervalTimer<TimerGameCalendar> _towns_monthly({TimerGameCalendar::MONTH, TimerGameCalendar::Priority::TOWN}, [](auto)
 
{
 
	for (Town *t : Town::Iterate()) {
 
		if (t->road_build_months != 0) t->road_build_months--;
 

	
 
		if (t->exclusive_counter != 0) {
 
			if (--t->exclusive_counter == 0) t->exclusivity = INVALID_COMPANY;
 
		}
 

	
 
		UpdateTownAmounts(t);
 
		UpdateTownGrowth(t);
 
		UpdateTownRating(t);
 
		UpdateTownUnwanted(t);
 
	}
 

	
 
}
 

	
 
void TownsYearlyLoop()
 
});
 

	
 
static IntervalTimer<TimerGameCalendar> _towns_yearly({TimerGameCalendar::YEAR, TimerGameCalendar::Priority::TOWN}, [](auto)
 
{
 
	/* Increment house ages */
 
	for (TileIndex t = 0; t < Map::Size(); t++) {
 
		if (!IsTileType(t, MP_HOUSE)) continue;
 
		IncrementHouseAge(t);
 
	}
 
}
 
});
 

	
 
static CommandCost TerraformTile_Town(TileIndex tile, DoCommandFlag flags, int z_new, Slope tileh_new)
 
{
 
	if (AutoslopeEnabled()) {
 
		HouseID house = GetHouseType(tile);
 
		GetHouseNorthPart(house); // modifies house to the ID of the north tile
 
		const HouseSpec *hs = HouseSpec::Get(house);
 

	
 
		/* Here we differ from TTDP by checking TILE_NOT_SLOPED */
 
		if (((hs->building_flags & TILE_NOT_SLOPED) == 0) && !IsSteepSlope(tileh_new) &&
 
				(GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new))) {
 
			bool allow_terraform = true;
src/town_gui.cpp
Show inline comments
 
@@ -26,24 +26,25 @@
 
#include "landscape.h"
 
#include "querystring_gui.h"
 
#include "window_func.h"
 
#include "townname_func.h"
 
#include "core/backup_type.hpp"
 
#include "core/geometry_func.hpp"
 
#include "genworld.h"
 
#include "stringfilter_type.h"
 
#include "widgets/dropdown_func.h"
 
#include "town_kdtree.h"
 
#include "town_cmd.h"
 
#include "timer/timer.h"
 
#include "timer/timer_game_calendar.h"
 
#include "timer/timer_window.h"
 

	
 
#include "widgets/town_widget.h"
 

	
 
#include "table/strings.h"
 

	
 
#include "safeguards.h"
 
#include "zoom_func.h"
 

	
 
TownKdtree _town_local_authority_kdtree(&Kdtree_TownXYFunc);
 

	
 
typedef GUIList<const Town*> GUITownList;
 
@@ -587,24 +588,29 @@ public:
 
		if (!gui_scope) return;
 
		/* Called when setting station noise or required cargoes have changed, in order to resize the window */
 
		this->SetDirty(); // refresh display for current size. This will allow to avoid glitches when downgrading
 
		this->ResizeWindowAsNeeded();
 
	}
 

	
 
	void OnQueryTextFinished(char *str) override
 
	{
 
		if (str == nullptr) return;
 

	
 
		Command<CMD_RENAME_TOWN>::Post(STR_ERROR_CAN_T_RENAME_TOWN, this->window_number, str);
 
	}
 

	
 
	IntervalTimer<TimerGameCalendar> daily_interval = {{TimerGameCalendar::DAY, TimerGameCalendar::Priority::NONE}, [this](auto) {
 
		/* Refresh after possible snowline change */
 
		this->SetDirty();
 
	}};
 
};
 

	
 
static const NWidgetPart _nested_town_game_view_widgets[] = {
 
	NWidget(NWID_HORIZONTAL),
 
		NWidget(WWT_CLOSEBOX, COLOUR_BROWN),
 
		NWidget(WWT_PUSHIMGBTN, COLOUR_BROWN, WID_TV_CHANGE_NAME), SetMinimalSize(12, 14), SetDataTip(SPR_RENAME, STR_TOWN_VIEW_RENAME_TOOLTIP),
 
		NWidget(WWT_CAPTION, COLOUR_BROWN, WID_TV_CAPTION), SetDataTip(STR_TOWN_VIEW_TOWN_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
 
		NWidget(WWT_PUSHIMGBTN, COLOUR_BROWN, WID_TV_CENTER_VIEW), SetMinimalSize(12, 14), SetDataTip(SPR_GOTO_LOCATION, STR_TOWN_VIEW_CENTER_TOOLTIP),
 
		NWidget(WWT_SHADEBOX, COLOUR_BROWN),
 
		NWidget(WWT_DEFSIZEBOX, COLOUR_BROWN),
 
		NWidget(WWT_STICKYBOX, COLOUR_BROWN),
 
	EndContainer(),
src/vehicle.cpp
Show inline comments
 
@@ -47,24 +47,26 @@
 
#include "bridge_map.h"
 
#include "tunnel_map.h"
 
#include "depot_map.h"
 
#include "gamelog.h"
 
#include "linkgraph/linkgraph.h"
 
#include "linkgraph/refresh.h"
 
#include "framerate_type.h"
 
#include "autoreplace_cmd.h"
 
#include "misc_cmd.h"
 
#include "train_cmd.h"
 
#include "vehicle_cmd.h"
 
#include "newgrf_roadstop.h"
 
#include "timer/timer.h"
 
#include "timer/timer_game_calendar.h"
 

	
 
#include "table/strings.h"
 

	
 
#include "safeguards.h"
 

	
 
/* Number of bits in the hash to use from each vehicle coord */
 
static const uint GEN_HASHX_BITS = 6;
 
static const uint GEN_HASHY_BITS = 6;
 

	
 
/* Size of each hash bucket */
 
static const uint GEN_HASHX_BUCKET_BITS = 7;
 
static const uint GEN_HASHY_BUCKET_BITS = 6;
 
@@ -2817,51 +2819,50 @@ void Vehicle::RemoveFromShared()
 
		CloseWindowById(GetWindowClassForVehicleType(this->type), vli.Pack());
 
		InvalidateVehicleOrder(this->FirstShared(), VIWD_MODIFY_ORDERS);
 
	} else if (were_first) {
 
		/* If we were the first one, update to the new first one.
 
		 * Note: FirstShared() is already the new first */
 
		InvalidateWindowData(GetWindowClassForVehicleType(this->type), vli.Pack(), this->FirstShared()->index | (1U << 31));
 
	}
 

	
 
	this->next_shared     = nullptr;
 
	this->previous_shared = nullptr;
 
}
 

	
 
void VehiclesYearlyLoop()
 
static IntervalTimer<TimerGameCalendar> _vehicles_yearly({TimerGameCalendar::YEAR, TimerGameCalendar::Priority::VEHICLE}, [](auto)
 
{
 
	for (Vehicle *v : Vehicle::Iterate()) {
 
		if (v->IsPrimaryVehicle()) {
 
			/* show warning if vehicle is not generating enough income last 2 years (corresponds to a red icon in the vehicle list) */
 
			Money profit = v->GetDisplayProfitThisYear();
 
			if (v->age >= 730 && profit < 0) {
 
				if (_settings_client.gui.vehicle_income_warn && v->owner == _local_company) {
 
					SetDParam(0, v->index);
 
					SetDParam(1, profit);
 
					AddVehicleAdviceNewsItem(STR_NEWS_VEHICLE_IS_UNPROFITABLE, v->index);
 
				}
 
				AI::NewEvent(v->owner, new ScriptEventVehicleUnprofitable(v->index));
 
			}
 

	
 
			v->profit_last_year = v->profit_this_year;
 
			v->profit_this_year = 0;
 
			SetWindowDirty(WC_VEHICLE_DETAILS, v->index);
 
		}
 
	}
 
	GroupStatistics::UpdateProfits();
 
	SetWindowClassesDirty(WC_TRAINS_LIST);
 
	SetWindowClassesDirty(WC_SHIPS_LIST);
 
	SetWindowClassesDirty(WC_ROADVEH_LIST);
 
	SetWindowClassesDirty(WC_AIRCRAFT_LIST);
 
}
 

	
 
});
 

	
 
/**
 
 * Can this station be used by the given engine type?
 
 * @param engine_type the type of vehicles to test
 
 * @param st the station to test for
 
 * @return true if and only if the vehicle of the type can use this station.
 
 * @note For road vehicles the Vehicle is needed to determine whether it can
 
 *       use the station. This function will return true for road vehicles
 
 *       when at least one of the facilities is available.
 
 */
 
bool CanVehicleUseStation(EngineID engine_type, const Station *st)
 
{
0 comments (0 inline, 0 general)