Update to 14.0-beta1
This commit is contained in:
@@ -23,7 +23,6 @@
|
||||
#include "company_manager_face.h"
|
||||
#include "window_func.h"
|
||||
#include "strings_func.h"
|
||||
#include "date_func.h"
|
||||
#include "sound_func.h"
|
||||
#include "rail.h"
|
||||
#include "core/pool_func.hpp"
|
||||
@@ -36,18 +35,21 @@
|
||||
#include "story_base.h"
|
||||
#include "widgets/statusbar_widget.h"
|
||||
#include "company_cmd.h"
|
||||
#include "timer/timer.h"
|
||||
#include "timer/timer_game_economy.h"
|
||||
#include "timer/timer_game_tick.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
|
||||
uint _next_competitor_start; ///< the number of ticks before the next AI is started
|
||||
uint _cur_company_tick_index; ///< used to generate a name for one company that doesn't have a name yet per tick
|
||||
|
||||
CompanyPool _company_pool("Company"); ///< Pool of companies.
|
||||
@@ -58,17 +60,16 @@ INSTANTIATE_POOL_METHODS(Company)
|
||||
* @param name_1 Name of the company.
|
||||
* @param is_ai A computer program is running for this company.
|
||||
*/
|
||||
Company::Company(uint16 name_1, bool is_ai)
|
||||
Company::Company(uint16_t name_1, bool is_ai)
|
||||
{
|
||||
this->name_1 = name_1;
|
||||
this->location_of_HQ = INVALID_TILE;
|
||||
this->is_ai = is_ai;
|
||||
this->terraform_limit = (uint32)_settings_game.construction.terraform_frame_burst << 16;
|
||||
this->clear_limit = (uint32)_settings_game.construction.clear_frame_burst << 16;
|
||||
this->tree_limit = (uint32)_settings_game.construction.tree_frame_burst << 16;
|
||||
this->build_object_limit = (uint32)_settings_game.construction.build_object_frame_burst << 16;
|
||||
this->terraform_limit = (uint32_t)_settings_game.construction.terraform_frame_burst << 16;
|
||||
this->clear_limit = (uint32_t)_settings_game.construction.clear_frame_burst << 16;
|
||||
this->tree_limit = (uint32_t)_settings_game.construction.tree_frame_burst << 16;
|
||||
this->build_object_limit = (uint32_t)_settings_game.construction.build_object_frame_burst << 16;
|
||||
|
||||
std::fill(this->share_owners.begin(), this->share_owners.end(), INVALID_OWNER);
|
||||
InvalidateWindowData(WC_PERFORMANCE_DETAIL, 0, INVALID_COMPANY);
|
||||
}
|
||||
|
||||
@@ -94,6 +95,16 @@ void Company::PostDestructor(size_t index)
|
||||
InvalidateWindowData(WC_ERRMSG, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the max allowed loan for this company.
|
||||
* @return the max loan amount.
|
||||
*/
|
||||
Money Company::GetMaxLoan() const
|
||||
{
|
||||
if (this->max_loan == COMPANY_MAX_LOAN_DEFAULT) return _economy.max_loan;
|
||||
return this->max_loan;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the local company and updates the settings that are set on a
|
||||
* per-company basis to reflect the core's state in the GUI.
|
||||
@@ -192,20 +203,48 @@ void InvalidateCompanyWindows(const Company *company)
|
||||
SetWindowDirty(WC_FINANCES, cid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the amount of money that a company has available, or INT64_MAX
|
||||
* if there is no such valid company.
|
||||
*
|
||||
* @param company Company to check
|
||||
* @return The available money of the company or INT64_MAX
|
||||
*/
|
||||
Money GetAvailableMoney(CompanyID company)
|
||||
{
|
||||
if (_settings_game.difficulty.infinite_money) return INT64_MAX;
|
||||
if (!Company::IsValidID(company)) return INT64_MAX;
|
||||
return Company::Get(company)->money;
|
||||
}
|
||||
|
||||
/**
|
||||
* This functions returns the money which can be used to execute a command.
|
||||
* This is either the money of the current company, or INT64_MAX if infinite money
|
||||
* is enabled or there is no such a company "at the moment" like the server itself.
|
||||
*
|
||||
* @return The available money of the current company or INT64_MAX
|
||||
*/
|
||||
Money GetAvailableMoneyForCommand()
|
||||
{
|
||||
return GetAvailableMoney(_current_company);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify whether the company can pay the bill.
|
||||
* @param[in,out] cost Money to pay, is changed to an error if the company does not have enough money.
|
||||
* @return Function returns \c true if the company has enough money, else it returns \c false.
|
||||
* @return Function returns \c true if the company has enough money or infinite money is enabled,
|
||||
* else it returns \c false.
|
||||
*/
|
||||
bool CheckCompanyHasMoney(CommandCost &cost)
|
||||
{
|
||||
if (cost.GetCost() > 0) {
|
||||
const Company *c = Company::GetIfValid(_current_company);
|
||||
if (c != nullptr && cost.GetCost() > c->money) {
|
||||
SetDParam(0, cost.GetCost());
|
||||
cost.MakeError(STR_ERROR_NOT_ENOUGH_CASH_REQUIRES_CURRENCY);
|
||||
return false;
|
||||
}
|
||||
if (cost.GetCost() <= 0) return true;
|
||||
if (_settings_game.difficulty.infinite_money) return true;
|
||||
|
||||
const Company *c = Company::GetIfValid(_current_company);
|
||||
if (c != nullptr && cost.GetCost() > c->money) {
|
||||
SetDParam(0, cost.GetCost());
|
||||
cost.MakeError(STR_ERROR_NOT_ENOUGH_CASH_REQUIRES_CURRENCY);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -267,26 +306,31 @@ void SubtractMoneyFromCompanyFract(CompanyID company, const CommandCost &cst)
|
||||
if (cost != 0) SubtractMoneyFromAnyCompany(c, CommandCost(cst.GetExpensesType(), cost));
|
||||
}
|
||||
|
||||
static constexpr void UpdateLandscapingLimit(uint32_t &limit, uint64_t per_64k_frames, uint64_t burst)
|
||||
{
|
||||
limit = static_cast<uint32_t>(std::min<uint64_t>(limit + per_64k_frames, burst << 16));
|
||||
}
|
||||
|
||||
/** Update the landscaping limits per company. */
|
||||
void UpdateLandscapingLimits()
|
||||
{
|
||||
for (Company *c : Company::Iterate()) {
|
||||
c->terraform_limit = std::min<uint64>((uint64)c->terraform_limit + _settings_game.construction.terraform_per_64k_frames, (uint64)_settings_game.construction.terraform_frame_burst << 16);
|
||||
c->clear_limit = std::min<uint64>((uint64)c->clear_limit + _settings_game.construction.clear_per_64k_frames, (uint64)_settings_game.construction.clear_frame_burst << 16);
|
||||
c->tree_limit = std::min<uint64>((uint64)c->tree_limit + _settings_game.construction.tree_per_64k_frames, (uint64)_settings_game.construction.tree_frame_burst << 16);
|
||||
c->build_object_limit = std::min<uint64>((uint64)c->build_object_limit + _settings_game.construction.build_object_per_64k_frames, (uint64)_settings_game.construction.build_object_frame_burst << 16);
|
||||
UpdateLandscapingLimit(c->terraform_limit, _settings_game.construction.terraform_per_64k_frames, _settings_game.construction.terraform_frame_burst);
|
||||
UpdateLandscapingLimit(c->clear_limit, _settings_game.construction.clear_per_64k_frames, _settings_game.construction.clear_frame_burst);
|
||||
UpdateLandscapingLimit(c->tree_limit, _settings_game.construction.tree_per_64k_frames, _settings_game.construction.tree_frame_burst);
|
||||
UpdateLandscapingLimit(c->build_object_limit, _settings_game.construction.build_object_per_64k_frames, _settings_game.construction.build_object_frame_burst);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the right DParams to get the name of an owner.
|
||||
* Set the right DParams for STR_ERROR_OWNED_BY.
|
||||
* @param owner the owner to get the name of.
|
||||
* @param tile optional tile to get the right town.
|
||||
* @pre if tile == 0, then owner can't be OWNER_TOWN.
|
||||
*/
|
||||
void GetNameOfOwner(Owner owner, TileIndex tile)
|
||||
void SetDParamsForOwnedBy(Owner owner, TileIndex tile)
|
||||
{
|
||||
SetDParam(2, owner);
|
||||
SetDParam(OWNED_BY_OWNER_IN_PARAMETERS_OFFSET, owner);
|
||||
|
||||
if (owner != OWNER_TOWN) {
|
||||
if (!Company::IsValidID(owner)) {
|
||||
@@ -320,7 +364,7 @@ CommandCost CheckOwnership(Owner owner, TileIndex tile)
|
||||
|
||||
if (owner == _current_company) return CommandCost();
|
||||
|
||||
GetNameOfOwner(owner, tile);
|
||||
SetDParamsForOwnedBy(owner, tile);
|
||||
return_cmd_error(STR_ERROR_OWNED_BY);
|
||||
}
|
||||
|
||||
@@ -340,7 +384,7 @@ CommandCost CheckTileOwnership(TileIndex tile)
|
||||
if (owner == _current_company) return CommandCost();
|
||||
|
||||
/* no need to get the name of the owner unless we're the local company (saves some time) */
|
||||
if (IsLocalCompany()) GetNameOfOwner(owner, tile);
|
||||
if (IsLocalCompany()) SetDParamsForOwnedBy(owner, tile);
|
||||
return_cmd_error(STR_ERROR_OWNED_BY);
|
||||
}
|
||||
|
||||
@@ -350,17 +394,14 @@ CommandCost CheckTileOwnership(TileIndex tile)
|
||||
*/
|
||||
static void GenerateCompanyName(Company *c)
|
||||
{
|
||||
/* Reserve space for extra unicode character. We need to do this to be able
|
||||
* to detect too long company name. */
|
||||
char buffer[(MAX_LENGTH_COMPANY_NAME_CHARS + 1) * MAX_CHAR_LENGTH];
|
||||
|
||||
if (c->name_1 != STR_SV_UNNAMED) return;
|
||||
if (c->last_build_coordinate == 0) return;
|
||||
|
||||
Town *t = ClosestTownFromTile(c->last_build_coordinate, UINT_MAX);
|
||||
|
||||
StringID str;
|
||||
uint32 strp;
|
||||
uint32_t strp;
|
||||
std::string name;
|
||||
if (t->name.empty() && IsInsideMM(t->townnametype, SPECSTR_TOWNNAME_START, SPECSTR_TOWNNAME_LAST + 1)) {
|
||||
str = t->townnametype - SPECSTR_TOWNNAME_START + SPECSTR_COMPANY_NAME_START;
|
||||
strp = t->townnameparts;
|
||||
@@ -371,8 +412,9 @@ verify_name:;
|
||||
if (cc->name_1 == str && cc->name_2 == strp) goto bad_town_name;
|
||||
}
|
||||
|
||||
GetString(buffer, str, lastof(buffer));
|
||||
if (Utf8StringLength(buffer) >= MAX_LENGTH_COMPANY_NAME_CHARS) goto bad_town_name;
|
||||
SetDParam(0, strp);
|
||||
name = GetString(str);
|
||||
if (Utf8StringLength(name) >= MAX_LENGTH_COMPANY_NAME_CHARS) goto bad_town_name;
|
||||
|
||||
set_name:;
|
||||
c->name_1 = str;
|
||||
@@ -386,7 +428,7 @@ set_name:;
|
||||
SetDParam(1, STR_NEWS_COMPANY_LAUNCH_DESCRIPTION);
|
||||
SetDParamStr(2, cni->company_name);
|
||||
SetDParam(3, t->index);
|
||||
AddNewsItem(STR_MESSAGE_NEWS_FORMAT, NT_COMPANY_INFO, NF_COMPANY, NR_TILE, c->last_build_coordinate, NR_NONE, UINT32_MAX, cni);
|
||||
AddNewsItem(STR_MESSAGE_NEWS_FORMAT, NT_COMPANY_INFO, NF_COMPANY, NR_TILE, c->last_build_coordinate.base(), NR_NONE, UINT32_MAX, cni);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -453,7 +495,7 @@ static Colours GenerateCompanyColour()
|
||||
|
||||
/* Move the colours that look similar to each company's colour to the side */
|
||||
for (const Company *c : Company::Iterate()) {
|
||||
Colours pcolour = (Colours)c->colour;
|
||||
Colours pcolour = c->colour;
|
||||
|
||||
for (uint i = 0; i < COLOUR_END; i++) {
|
||||
if (colours[i] == pcolour) {
|
||||
@@ -493,18 +535,15 @@ restart:;
|
||||
|
||||
/* Reserve space for extra unicode character. We need to do this to be able
|
||||
* to detect too long president name. */
|
||||
char buffer[(MAX_LENGTH_PRESIDENT_NAME_CHARS + 1) * MAX_CHAR_LENGTH];
|
||||
SetDParam(0, c->index);
|
||||
GetString(buffer, STR_PRESIDENT_NAME, lastof(buffer));
|
||||
if (Utf8StringLength(buffer) >= MAX_LENGTH_PRESIDENT_NAME_CHARS) continue;
|
||||
std::string name = GetString(STR_PRESIDENT_NAME);
|
||||
if (Utf8StringLength(name) >= MAX_LENGTH_PRESIDENT_NAME_CHARS) continue;
|
||||
|
||||
for (const Company *cc : Company::Iterate()) {
|
||||
if (c != cc) {
|
||||
/* Reserve extra space so even overlength president names can be compared. */
|
||||
char buffer2[(MAX_LENGTH_PRESIDENT_NAME_CHARS + 1) * MAX_CHAR_LENGTH];
|
||||
SetDParam(0, cc->index);
|
||||
GetString(buffer2, STR_PRESIDENT_NAME, lastof(buffer2));
|
||||
if (strcmp(buffer2, buffer) == 0) goto restart;
|
||||
std::string other_name = GetString(STR_PRESIDENT_NAME);
|
||||
if (name == other_name) goto restart;
|
||||
}
|
||||
}
|
||||
return;
|
||||
@@ -558,23 +597,21 @@ Company *DoStartupNewCompany(bool is_ai, CompanyID company = INVALID_COMPANY)
|
||||
c->colour = colour;
|
||||
|
||||
ResetCompanyLivery(c);
|
||||
_company_colours[c->index] = (Colours)c->colour;
|
||||
_company_colours[c->index] = c->colour;
|
||||
|
||||
/* Scale the initial loan based on the inflation rounded down to the loan interval. The maximum loan has already been inflation adjusted. */
|
||||
c->money = c->current_loan = std::min<int64>((INITIAL_LOAN * _economy.inflation_prices >> 16) / LOAN_INTERVAL * LOAN_INTERVAL, _economy.max_loan);
|
||||
c->money = c->current_loan = std::min<int64_t>((INITIAL_LOAN * _economy.inflation_prices >> 16) / LOAN_INTERVAL * LOAN_INTERVAL, _economy.max_loan);
|
||||
|
||||
std::fill(c->share_owners.begin(), c->share_owners.end(), INVALID_OWNER);
|
||||
|
||||
c->avail_railtypes = GetCompanyRailtypes(c->index);
|
||||
c->avail_railtypes = GetCompanyRailTypes(c->index);
|
||||
c->avail_roadtypes = GetCompanyRoadTypes(c->index);
|
||||
c->inaugurated_year = _cur_year;
|
||||
c->inaugurated_year = TimerGameEconomy::year;
|
||||
|
||||
/* 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. */
|
||||
if (_company_manager_face != 0 && !is_ai && !_networking) {
|
||||
c->face = _company_manager_face;
|
||||
} else {
|
||||
RandomCompanyManagerFaceBits(c->face, (GenderEthnicity)Random(), false, false);
|
||||
RandomCompanyManagerFaceBits(c->face, (GenderEthnicity)Random(), false, _random);
|
||||
}
|
||||
|
||||
SetDefaultCompanySettings(c->index);
|
||||
@@ -596,30 +633,29 @@ Company *DoStartupNewCompany(bool is_ai, CompanyID company = INVALID_COMPANY)
|
||||
return c;
|
||||
}
|
||||
|
||||
/** Start the next competitor now. */
|
||||
void StartupCompanies()
|
||||
{
|
||||
_next_competitor_start = 0;
|
||||
}
|
||||
|
||||
/** Start a new competitor company if possible. */
|
||||
static bool MaybeStartNewCompany()
|
||||
{
|
||||
if (_networking && Company::GetNumItems() >= _settings_client.network.max_companies) return false;
|
||||
TimeoutTimer<TimerGameTick> _new_competitor_timeout(0, []() {
|
||||
if (_game_mode == GM_MENU || !AI::CanStartNew()) return;
|
||||
if (_networking && Company::GetNumItems() >= _settings_client.network.max_companies) return;
|
||||
|
||||
/* count number of competitors */
|
||||
uint n = 0;
|
||||
uint8_t n = 0;
|
||||
for (const Company *c : Company::Iterate()) {
|
||||
if (c->is_ai) n++;
|
||||
}
|
||||
|
||||
if (n < (uint)_settings_game.difficulty.max_no_competitors) {
|
||||
/* Send a command to all clients to start up a new AI.
|
||||
* Works fine for Multiplayer and Singleplayer */
|
||||
return Command<CMD_COMPANY_CTRL>::Post(CCA_NEW_AI, INVALID_COMPANY, CRR_NONE, INVALID_CLIENT_ID );
|
||||
}
|
||||
if (n >= _settings_game.difficulty.max_no_competitors) return;
|
||||
|
||||
return false;
|
||||
/* Send a command to all clients to start up a new AI.
|
||||
* Works fine for Multiplayer and Singleplayer */
|
||||
Command<CMD_COMPANY_CTRL>::Post(CCA_NEW_AI, INVALID_COMPANY, CRR_NONE, INVALID_CLIENT_ID);
|
||||
});
|
||||
|
||||
/** Start of a new game. */
|
||||
void StartupCompanies()
|
||||
{
|
||||
/* Ensure the timeout is aborted, so it doesn't fire based on information of the last game. */
|
||||
_new_competitor_timeout.Abort();
|
||||
}
|
||||
|
||||
/** Initialize the pool of companies. */
|
||||
@@ -662,7 +698,7 @@ static void HandleBankruptcyTakeover(Company *c)
|
||||
* number of companies. The minimum number of days in a quarter
|
||||
* is 90: 31 in January, 28 in February and 31 in March.
|
||||
* Note that the company going bankrupt can't buy itself. */
|
||||
static const int TAKE_OVER_TIMEOUT = 3 * 30 * DAY_TICKS / (MAX_COMPANIES - 1);
|
||||
static const int TAKE_OVER_TIMEOUT = 3 * 30 * Ticks::DAY_TICKS / (MAX_COMPANIES - 1);
|
||||
|
||||
assert(c->bankrupt_asked != 0);
|
||||
|
||||
@@ -679,7 +715,7 @@ static void HandleBankruptcyTakeover(Company *c)
|
||||
if (c->bankrupt_asked == MAX_UVALUE(CompanyMask)) return;
|
||||
|
||||
Company *best = nullptr;
|
||||
int32 best_performance = -1;
|
||||
int32_t best_performance = -1;
|
||||
|
||||
/* Ask the company with the highest performance history first */
|
||||
for (Company *c2 : Company::Iterate()) {
|
||||
@@ -701,10 +737,10 @@ static void HandleBankruptcyTakeover(Company *c)
|
||||
SetBit(c->bankrupt_asked, best->index);
|
||||
|
||||
c->bankrupt_timeout = TAKE_OVER_TIMEOUT;
|
||||
if (best->is_ai) {
|
||||
AI::NewEvent(best->index, new ScriptEventCompanyAskMerger(c->index, ClampToI32(c->bankrupt_value)));
|
||||
} else if (IsInteractiveCompany(best->index)) {
|
||||
ShowBuyCompanyDialog(c->index);
|
||||
|
||||
AI::NewEvent(best->index, new ScriptEventCompanyAskMerger(c->index, c->bankrupt_value));
|
||||
if (IsInteractiveCompany(best->index)) {
|
||||
ShowBuyCompanyDialog(c->index, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -719,20 +755,27 @@ void OnTick_Companies()
|
||||
if (c->bankrupt_asked != 0) HandleBankruptcyTakeover(c);
|
||||
}
|
||||
|
||||
if (_next_competitor_start == 0) {
|
||||
/* AI::GetStartNextTime() can return 0. */
|
||||
_next_competitor_start = std::max(1, AI::GetStartNextTime() * DAY_TICKS);
|
||||
}
|
||||
if (_new_competitor_timeout.HasFired() && _game_mode != GM_MENU && AI::CanStartNew()) {
|
||||
int32_t timeout = _settings_game.difficulty.competitors_interval * 60 * Ticks::TICKS_PER_SECOND;
|
||||
/* If the interval is zero, start as many competitors as needed then check every ~10 minutes if a company went bankrupt and needs replacing. */
|
||||
if (timeout == 0) {
|
||||
/* count number of competitors */
|
||||
uint8_t n = 0;
|
||||
for (const Company *cc : Company::Iterate()) {
|
||||
if (cc->is_ai) n++;
|
||||
}
|
||||
|
||||
if (_game_mode != GM_MENU && AI::CanStartNew() && --_next_competitor_start == 0) {
|
||||
/* Allow multiple AIs to possibly start in the same tick. */
|
||||
do {
|
||||
if (!MaybeStartNewCompany()) break;
|
||||
for (auto i = 0; i < _settings_game.difficulty.max_no_competitors; i++) {
|
||||
if (_networking && Company::GetNumItems() >= _settings_client.network.max_companies) break;
|
||||
if (n++ >= _settings_game.difficulty.max_no_competitors) break;
|
||||
Command<CMD_COMPANY_CTRL>::Post(CCA_NEW_AI, INVALID_COMPANY, CRR_NONE, INVALID_CLIENT_ID);
|
||||
}
|
||||
timeout = 10 * 60 * Ticks::TICKS_PER_SECOND;
|
||||
}
|
||||
/* Randomize a bit when the AI is actually going to start; ranges from 87.5% .. 112.5% of indicated value. */
|
||||
timeout += ScriptObject::GetRandomizer(OWNER_NONE).Next(timeout / 4) - timeout / 8;
|
||||
|
||||
/* In networking mode, we can only send a command to start but it
|
||||
* didn't execute yet, so we cannot loop. */
|
||||
if (_networking) break;
|
||||
} while (AI::GetStartNextTime() == 0);
|
||||
_new_competitor_timeout.Reset(std::max(1, timeout));
|
||||
}
|
||||
|
||||
_cur_company_tick_index = (_cur_company_tick_index + 1) % MAX_COMPANIES;
|
||||
@@ -742,12 +785,13 @@ void OnTick_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<TimerGameEconomy> _economy_companies_yearly({TimerGameEconomy::YEAR, TimerGameEconomy::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]));
|
||||
/* 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] = {};
|
||||
SetWindowDirty(WC_FINANCES, c->index);
|
||||
}
|
||||
|
||||
@@ -760,7 +804,7 @@ void CompaniesYearlyLoop()
|
||||
if (_settings_client.sound.new_year) SndPlayFx(SND_00_GOOD_YEAR);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Fill the CompanyNewsInformation struct with the required data.
|
||||
@@ -921,8 +965,8 @@ CommandCost CmdCompanyCtrl(DoCommandFlag flags, CompanyCtrlAction cca, CompanyID
|
||||
}
|
||||
|
||||
InvalidateWindowClassesData(WC_GAME_OPTIONS);
|
||||
InvalidateWindowClassesData(WC_AI_SETTINGS);
|
||||
InvalidateWindowClassesData(WC_AI_LIST);
|
||||
InvalidateWindowClassesData(WC_SCRIPT_SETTINGS);
|
||||
InvalidateWindowClassesData(WC_SCRIPT_LIST);
|
||||
|
||||
return CommandCost();
|
||||
}
|
||||
@@ -944,6 +988,20 @@ CommandCost CmdSetCompanyManagerFace(DoCommandFlag flags, CompanyManagerFace cmf
|
||||
return CommandCost();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update liveries for a company. This is called when the LS_DEFAULT scheme is changed, to update schemes with colours
|
||||
* set to default.
|
||||
* @param c Company to update.
|
||||
*/
|
||||
void UpdateCompanyLiveries(Company *c)
|
||||
{
|
||||
for (int i = 1; i < LS_END; i++) {
|
||||
if (!HasBit(c->livery[i].in_use, 0)) c->livery[i].colour1 = c->livery[LS_DEFAULT].colour1;
|
||||
if (!HasBit(c->livery[i].in_use, 1)) c->livery[i].colour2 = c->livery[LS_DEFAULT].colour2;
|
||||
}
|
||||
UpdateCompanyGroupLiveries(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the company's company-colour
|
||||
* @param flags operation to perform
|
||||
@@ -971,28 +1029,24 @@ CommandCost CmdSetCompanyColour(DoCommandFlag flags, LiveryScheme scheme, bool p
|
||||
if (flags & DC_EXEC) {
|
||||
if (primary) {
|
||||
if (scheme != LS_DEFAULT) SB(c->livery[scheme].in_use, 0, 1, colour != INVALID_COLOUR);
|
||||
if (colour == INVALID_COLOUR) colour = (Colours)c->livery[LS_DEFAULT].colour1;
|
||||
if (colour == INVALID_COLOUR) colour = c->livery[LS_DEFAULT].colour1;
|
||||
c->livery[scheme].colour1 = colour;
|
||||
|
||||
/* If setting the first colour of the default scheme, adjust the
|
||||
* original and cached company colours too. */
|
||||
if (scheme == LS_DEFAULT) {
|
||||
for (int i = 1; i < LS_END; i++) {
|
||||
if (!HasBit(c->livery[i].in_use, 0)) c->livery[i].colour1 = colour;
|
||||
}
|
||||
UpdateCompanyLiveries(c);
|
||||
_company_colours[_current_company] = colour;
|
||||
c->colour = colour;
|
||||
CompanyAdminUpdate(c);
|
||||
}
|
||||
} else {
|
||||
if (scheme != LS_DEFAULT) SB(c->livery[scheme].in_use, 1, 1, colour != INVALID_COLOUR);
|
||||
if (colour == INVALID_COLOUR) colour = (Colours)c->livery[LS_DEFAULT].colour2;
|
||||
if (colour == INVALID_COLOUR) colour = c->livery[LS_DEFAULT].colour2;
|
||||
c->livery[scheme].colour2 = colour;
|
||||
|
||||
if (scheme == LS_DEFAULT) {
|
||||
for (int i = 1; i < LS_END; i++) {
|
||||
if (!HasBit(c->livery[i].in_use, 1)) c->livery[i].colour2 = colour;
|
||||
}
|
||||
UpdateCompanyGroupLiveries(c);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1030,7 +1084,6 @@ CommandCost CmdSetCompanyColour(DoCommandFlag flags, LiveryScheme scheme, bool p
|
||||
if (v->owner == _current_company) v->InvalidateNewGRFCache();
|
||||
}
|
||||
|
||||
extern void UpdateObjectColours(const Company *c);
|
||||
UpdateObjectColours(c);
|
||||
}
|
||||
return CommandCost();
|
||||
@@ -1150,9 +1203,9 @@ int CompanyServiceInterval(const Company *c, VehicleType type)
|
||||
* Get total sum of all owned road bits.
|
||||
* @return Combined total road road bits.
|
||||
*/
|
||||
uint32 CompanyInfrastructure::GetRoadTotal() const
|
||||
uint32_t CompanyInfrastructure::GetRoadTotal() const
|
||||
{
|
||||
uint32 total = 0;
|
||||
uint32_t total = 0;
|
||||
for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) {
|
||||
if (RoadTypeIsRoad(rt)) total += this->road[rt];
|
||||
}
|
||||
@@ -1163,9 +1216,9 @@ uint32 CompanyInfrastructure::GetRoadTotal() const
|
||||
* Get total sum of all owned tram bits.
|
||||
* @return Combined total of tram road bits.
|
||||
*/
|
||||
uint32 CompanyInfrastructure::GetTramTotal() const
|
||||
uint32_t CompanyInfrastructure::GetTramTotal() const
|
||||
{
|
||||
uint32 total = 0;
|
||||
uint32_t total = 0;
|
||||
for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) {
|
||||
if (RoadTypeIsTram(rt)) total += this->road[rt];
|
||||
}
|
||||
@@ -1182,7 +1235,7 @@ uint32 CompanyInfrastructure::GetTramTotal() const
|
||||
* @param dest_company the company to transfer the money to
|
||||
* @return the cost of this operation or an error
|
||||
*/
|
||||
CommandCost CmdGiveMoney(DoCommandFlag flags, uint32 money, CompanyID dest_company)
|
||||
CommandCost CmdGiveMoney(DoCommandFlag flags, Money money, CompanyID dest_company)
|
||||
{
|
||||
if (!_settings_game.economy.give_money) return CMD_ERROR;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user