OpenTTD Source 20260731-master-g77ba2b244a
company_cmd.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * 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 <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
9
10#include "stdafx.h"
11#include "company_base.h"
12#include "company_func.h"
13#include "company_gui.h"
14#include "core/backup_type.hpp"
15#include "town.h"
16#include "news_func.h"
17#include "command_func.h"
18#include "network/network.h"
22#include "ai/ai.hpp"
23#include "ai/ai_instance.hpp"
24#include "ai/ai_config.hpp"
26#include "window_func.h"
27#include "strings_func.h"
28#include "sound_func.h"
29#include "rail.h"
30#include "core/pool_func.hpp"
32#include "settings_func.h"
33#include "vehicle_base.h"
34#include "vehicle_func.h"
35#include "smallmap_gui.h"
36#include "game/game.hpp"
37#include "goal_base.h"
38#include "story_base.h"
39#include "company_cmd.h"
40#include "script/api/script_event_types.hpp"
41#include "timer/timer.h"
44#include "timer/timer_window.h"
45#include "road_gui.h"
46
49
50#include "table/strings.h"
51#include "table/company_face.h"
52
53#include "safeguards.h"
54
55void ClearEnginesHiddenFlagOfCompany(CompanyID cid);
56void UpdateObjectColours(const Company *c);
57
58CompanyID _local_company;
63
64CompanyPool _company_pool("Company");
66
67
73Company::Company(CompanyID index, StringID name_1, bool is_ai) : CompanyPool::PoolItem<&_company_pool>(index)
74{
75 this->name_1 = name_1;
76 this->is_ai = is_ai;
77 this->terraform_limit = (uint32_t)_settings_game.construction.terraform_frame_burst << 16;
78 this->clear_limit = (uint32_t)_settings_game.construction.clear_frame_burst << 16;
79 this->tree_limit = (uint32_t)_settings_game.construction.tree_frame_burst << 16;
80 this->build_object_limit = (uint32_t)_settings_game.construction.build_object_frame_burst << 16;
81
82 InvalidateWindowData(WindowClass::PerformanceDetail, 0, CompanyID::Invalid());
83}
84
87{
88 if (CleaningPool()) return;
89
91}
92
98{
99 InvalidateWindowData(WindowClass::GraphLegend, 0, static_cast<int>(index));
100 InvalidateWindowData(WindowClass::PerformanceDetail, 0, static_cast<int>(index));
101 InvalidateWindowData(WindowClass::CompanyLeague, 0, 0);
102 InvalidateWindowData(WindowClass::LinkGraphLegend, 0);
103 /* If the currently shown error message has this company in it, then close it. */
104 InvalidateWindowData(WindowClass::ErrorMessage, 0);
105}
106
112{
113 if (this->max_loan == COMPANY_MAX_LOAN_DEFAULT) return _economy.max_loan;
114 return this->max_loan;
115}
116
124void SetLocalCompany(CompanyID new_company, bool switching_game)
125{
126 /* company could also be COMPANY_SPECTATOR or OWNER_NONE */
127 assert(Company::IsValidID(new_company) || new_company == COMPANY_SPECTATOR || new_company == OWNER_NONE);
128
129 /* If actually changing to another company, several windows need closing */
130 bool switching_company = _local_company != new_company;
131
132 /* Delete the chat window, if you were team chatting. */
133 if (switching_company) InvalidateWindowData(WindowClass::NetworkChat, NetworkChatDestinationType::Team, _local_company);
134
135 assert(IsLocalCompany());
136
137 _current_company = _local_company = new_company;
138
139 if (switching_company) {
140 InvalidateWindowClassesData(WindowClass::Company);
141 InvalidateWindowClassesData(WindowClass::VehicleView);
142 /* Delete any construction windows... */
144 }
145
146 if (switching_company || switching_game) {
147 /* Update the default rail and road types */
150 }
151
152 if (!switching_game) {
153 /* ... and redraw the whole screen. */
155 InvalidateWindowClassesData(WindowClass::SignList, -1);
156 InvalidateWindowClassesData(WindowClass::GoalList);
157 InvalidateWindowClassesData(WindowClass::CompanyLivery, -1);
158 ResetVehicleColourMap();
159 }
160}
161
172
178PaletteID GetCompanyPalette(CompanyID company)
179{
180 return GetColourPalette(_company_colours[company]);
181}
182
189void DrawCompanyIcon(CompanyID c, int x, int y)
190{
192}
193
201{
202 if (cmf.style >= GetNumCompanyManagerFaceStyles()) return false;
203
204 /* Test if each enabled part is valid. */
205 FaceVars vars = GetCompanyManagerFaceVars(cmf.style);
206 for (uint var : SetBitIterator(GetActiveFaceVars(cmf, vars))) {
207 if (!vars[var].IsValid(cmf)) return false;
208 }
209
210 return true;
211}
212
214
221{
222 CompanyID cid = company->index;
224}
225
229static const IntervalTimer<TimerWindow> invalidate_company_windows_interval(std::chrono::milliseconds(1), [](auto) {
230 for (CompanyID cid : _dirty_company_finances) {
231 if (cid == _local_company) SetWindowWidgetDirty(WindowClass::Statusbar, 0, WID_S_RIGHT);
232 Window *w = FindWindowById(WindowClass::Finances, cid);
233 if (w != nullptr) {
239 }
240 SetWindowWidgetDirty(WindowClass::Company, cid, WID_C_DESC_COMPANY_VALUE);
241 }
243});
244
252Money GetAvailableMoney(CompanyID company)
253{
254 if (_settings_game.difficulty.infinite_money) return INT64_MAX;
255 if (!Company::IsValidID(company)) return INT64_MAX;
256 return Company::Get(company)->money;
257}
258
270
278{
279 if (cost.GetCost() <= 0) return true;
280 if (_settings_game.difficulty.infinite_money) return true;
281
283 if (c != nullptr && cost.GetCost() > c->money) {
284 cost.MakeError(STR_ERROR_NOT_ENOUGH_CASH_REQUIRES_CURRENCY);
285 if (IsLocalCompany()) {
286 cost.SetEncodedMessage(GetEncodedString(STR_ERROR_NOT_ENOUGH_CASH_REQUIRES_CURRENCY, cost.GetCost()));
287 }
288 return false;
289 }
290 return true;
291}
292
298static void SubtractMoneyFromCompany(Company *c, const CommandCost &cost)
299{
300 using ExpensesTypes = EnumBitSet<ExpensesType, uint16_t>;
301 static constexpr ExpensesTypes EXPENSESTYPES_INCOME{
306 };
307 static constexpr ExpensesTypes EXPENSESTYPES_EXPENSES{
314 };
315
316 if (cost.GetCost() == 0) return;
317 assert(cost.GetExpensesType() != ExpensesType::Invalid);
318
319 c->money -= cost.GetCost();
320 c->yearly_expenses[0][cost.GetExpensesType()] += cost.GetCost();
321
322 if (EXPENSESTYPES_INCOME.Test(cost.GetExpensesType())) {
323 c->cur_economy.income -= cost.GetCost();
324 } else if (EXPENSESTYPES_EXPENSES.Test(cost.GetExpensesType())) {
325 c->cur_economy.expenses -= cost.GetCost();
326 }
327
329}
330
336void SubtractMoneyFromCompany(CompanyID company, const CommandCost &cost)
337{
338 Company *c = Company::GetIfValid(company);
339 if (c != nullptr) SubtractMoneyFromCompany(c, cost);
340}
341
347void SubtractMoneyFromCompanyFract(CompanyID company, const CommandCost &cst)
348{
349 Company *c = Company::Get(company);
350 uint8_t m = c->money_fraction;
351 Money cost = cst.GetCost();
352
353 c->money_fraction = m - (uint8_t)cost;
354 cost >>= 8;
355 if (c->money_fraction > m) cost++;
356 if (cost != 0) SubtractMoneyFromCompany(c, CommandCost(cst.GetExpensesType(), cost));
357}
358
359static constexpr void UpdateLandscapingLimit(uint32_t &limit, uint64_t per_64k_frames, uint64_t burst)
360{
361 limit = static_cast<uint32_t>(std::min<uint64_t>(limit + per_64k_frames, burst << 16));
362}
363
366{
367 for (Company *c : Company::Iterate()) {
368 UpdateLandscapingLimit(c->terraform_limit, _settings_game.construction.terraform_per_64k_frames, _settings_game.construction.terraform_frame_burst);
369 UpdateLandscapingLimit(c->clear_limit, _settings_game.construction.clear_per_64k_frames, _settings_game.construction.clear_frame_burst);
370 UpdateLandscapingLimit(c->tree_limit, _settings_game.construction.tree_per_64k_frames, _settings_game.construction.tree_frame_burst);
371 UpdateLandscapingLimit(c->build_object_limit, _settings_game.construction.build_object_per_64k_frames, _settings_game.construction.build_object_frame_burst);
372 }
373}
374
382std::array<StringParameter, 2> GetParamsForOwnedBy(Owner owner, TileIndex tile)
383{
384 if (owner == OWNER_TOWN) {
385 assert(tile != 0);
386 const Town *t = ClosestTownFromTile(tile, UINT_MAX);
387 return {STR_TOWN_NAME, t->index};
388 }
389
390 if (!Company::IsValidID(owner)) {
391 return {STR_COMPANY_SOMEONE, std::monostate{}};
392 }
393
394 return {STR_COMPANY_NAME, owner};
395}
396
406{
407 assert(owner < OWNER_END);
408 assert(owner != OWNER_TOWN || tile != 0);
409
410 if (owner == _current_company) return CommandCost();
411
412 CommandCost error{STR_ERROR_OWNED_BY};
413 if (IsLocalCompany()) {
414 auto params = GetParamsForOwnedBy(owner, tile);
415 error.SetEncodedMessage(GetEncodedStringWithArgs(STR_ERROR_OWNED_BY, params));
416 if (owner != OWNER_TOWN) error.SetErrorOwner(owner);
417 }
418 return error;
419}
420
429{
430 return CheckOwnership(GetTileOwner(tile), tile);
431}
432
442static bool SetCompanyName(std::span<const std::string> other_names, Company *c, const Town *t, StringID str, uint32_t strp)
443{
444 assert(c != nullptr);
445 assert(t != nullptr);
446
447 /* Name must not be too long. */
448 std::string name = GetString(str, strp);
449 if (Utf8StringLength(name) >= MAX_LENGTH_COMPANY_NAME_CHARS) return false;
450
451 /* No companies must have this name already. */
452 if (std::ranges::find(other_names, name) != other_names.end()) return false;
453
454 c->name_1 = str;
455 c->name_2 = strp;
456
458 AI::BroadcastNewEvent(new ScriptEventCompanyRenamed(c->index, name));
459 Game::NewEvent(new ScriptEventCompanyRenamed(c->index, name));
460
461 if (!c->is_ai) return true;
462
463 auto cni = std::make_unique<CompanyNewsInformation>(STR_NEWS_COMPANY_LAUNCH_TITLE, c);
464 EncodedString headline = GetEncodedString(STR_NEWS_COMPANY_LAUNCH_DESCRIPTION, cni->company_name, t->index);
465 AddNewsItem(std::move(headline),
467
468 return true;
469}
470
476{
477 if (c->name_1 != STR_SV_UNNAMED) return;
478 if (c->last_build_coordinate == 0) return;
479
480 /* Collect existing company names. */
481 std::vector<std::string> other_names;
482 for (const Company *cc : Company::Iterate()) {
483 if (cc != c) other_names.emplace_back(GetString(STR_COMPANY_NAME, cc->index));
484 }
485
486 const Town *t = ClosestTownFromTile(c->last_build_coordinate, UINT_MAX);
487
488 if (t->name.empty() && IsInsideMM(t->townnametype, SPECSTR_TOWNNAME_START, SPECSTR_TOWNNAME_END)) {
490 }
491
493 if (SetCompanyName(other_names, c, t, SPECSTR_ANDCO_NAME, c->president_name_2)) return;
494 }
495
496 for (;;) {
497 if (SetCompanyName(other_names, c, t, SPECSTR_ANDCO_NAME, Random())) return;
498 }
499}
500
502static const EnumIndexArray<uint8_t, Colours, Colours::End> _colour_sort{2, 2, 3, 2, 3, 2, 3, 2, 3, 2, 2, 2, 3, 1, 1, 1};
504static const std::initializer_list<Colours> _similar_colour[to_underlying(Colours::End)] = {
505 {Colours::Blue, Colours::LightBlue }, // Colours::DarkBlue
506 {Colours::Green, Colours::DarkGreen }, // Colours::PaleGreen
507 {}, // Colours::Pink
508 {Colours::Orange}, // Colours::Yellow
509 {}, // Colours::Red
510 {Colours::DarkBlue, Colours::Blue }, // Colours::LightBlue
511 {Colours::PaleGreen, Colours::DarkGreen }, // Colours::Green
512 {Colours::PaleGreen, Colours::Green }, // Colours::DarkGreen
513 {Colours::DarkBlue, Colours::LightBlue }, // Colours::Blue
514 {Colours::Brown, Colours::Orange }, // Colours::Cream
515 {Colours::Purple}, // Colours::Mauve
516 {Colours::Mauve}, // Colours::Purple
517 {Colours::Yellow, Colours::Cream }, // Colours::Orange
518 {Colours::Cream}, // Colours::Brown
519 {Colours::White}, // Colours::Grey
520 {Colours::Grey}, // Colours::White
521};
522
528{
529 /* Initialize colour table. */
530 std::vector<Colours> colours(to_underlying(Colours::End));
531 std::iota(colours.begin(), colours.end(), Colours::Begin);
532
533 /* And randomize it */
534 for (uint i = 0; i < 100; i++) {
535 uint r = Random();
536 std::swap(colours[GB(r, 0, 4)], colours[GB(r, 4, 4)]);
537 }
538
539 /* Sort it according to the values in _colour_sort. */
540 std::ranges::stable_sort(colours, {}, [](auto &i) { return _colour_sort[i]; });
541
542 /* Move the colours that look similar to each company's colour to the side */
543 for (const Company *c : Company::Iterate()) {
544 /* This company's colour is not available at all. */
545 std::erase(colours, c->colour);
546
547 for (Colours similar : _similar_colour[to_underlying(c->colour)]) {
548 auto it = std::ranges::find(colours, similar);
549 if (it != colours.end()) std::rotate(it, it + 1, colours.end());
550 }
551 }
552
553 /* Return the first available colour */
554 return colours.at(0);
555}
556
564static bool SetPresidentName(std::span<const std::string> other_names, Company *c, uint32_t seed)
565{
566 assert(c != nullptr);
567
569 c->president_name_2 = seed;
570
571 /* President name must not be too long. */
572 std::string name = GetString(STR_PRESIDENT_NAME, c->index);
573 if (Utf8StringLength(name) >= MAX_LENGTH_PRESIDENT_NAME_CHARS) return false;
574
575 /* No presidents must have this name already. */
576 if (std::ranges::find(other_names, name) != other_names.end()) return false;
577
578 return true;
579}
580
586{
587 /* Collect existing president names. */
588 std::vector<std::string> other_names;
589 for (const Company *cc : Company::Iterate()) {
590 if (cc != c) other_names.emplace_back(GetString(STR_PRESIDENT_NAME, cc->index));
591 }
592
593 for (;;) {
594 if (SetPresidentName(other_names, c, Random())) return;
595 }
596}
597
604{
606 c->livery[scheme].in_use.Reset();
607 c->livery[scheme].colour1 = c->colour;
608 c->livery[scheme].colour2 = c->colour;
609 }
610
611 for (Group *g : Group::Iterate()) {
612 if (g->owner == c->index) {
613 g->livery.in_use.Reset();
614 g->livery.colour1 = c->colour;
615 g->livery.colour2 = c->colour;
616 }
617 }
618}
619
627Company *DoStartupNewCompany(bool is_ai, CompanyID company = CompanyID::Invalid())
628{
629 if (!Company::CanAllocateItem()) return nullptr;
630
631 /* we have to generate colour before this company is valid */
633
634 Company *c;
635 if (company == CompanyID::Invalid()) {
636 c = Company::Create(STR_SV_UNNAMED, is_ai);
637 } else {
638 if (Company::IsValidID(company)) return nullptr;
639 c = Company::CreateAtIndex(company, STR_SV_UNNAMED, is_ai);
640 }
641
642 c->colour = colour;
643
645 _company_colours[c->index] = c->colour;
646
647 /* Scale the initial loan based on the inflation rounded down to the loan interval. The maximum loan has already been inflation adjusted. */
648 c->money = c->current_loan = std::min<int64_t>((INITIAL_LOAN * _economy.inflation_prices >> 16) / LOAN_INTERVAL * LOAN_INTERVAL, _economy.max_loan);
649
654
655 /* If starting a player company in singleplayer and a favourite company manager face is selected, choose it. Otherwise, use a random face.
656 * In a network game, we'll choose the favourite face later in CmdCompanyCtrl to sync it to all clients. */
657 bool randomise_face = true;
658 if (!_company_manager_face.empty() && !is_ai && !_networking) {
660 if (cmf.has_value()) {
661 randomise_face = false;
662 c->face = std::move(*cmf);
663 }
664 }
665 if (randomise_face) RandomiseCompanyManagerFace(c->face, _random);
666
669
671
672 SetWindowDirty(WindowClass::GraphLegend, 0);
673 InvalidateWindowData(WindowClass::NetworkClientList, 0);
674 InvalidateWindowData(WindowClass::LinkGraphLegend, 0);
676 InvalidateWindowData(WindowClass::SmallMap, 0, 1);
677
678 if (is_ai && (!_networking || _network_server)) AI::StartNew(c->index);
679
680 AI::BroadcastNewEvent(new ScriptEventCompanyNew(c->index), c->index);
681 Game::NewEvent(new ScriptEventCompanyNew(c->index));
682
683 return c;
684}
685
688 if (_game_mode == GameMode::Menu || !AI::CanStartNew()) return;
689 if (_networking && Company::GetNumItems() >= _settings_client.network.max_companies) return;
690 if (_settings_game.difficulty.competitors_interval == 0) return;
691
692 /* count number of competitors */
693 uint8_t n = 0;
694 for (const Company *c : Company::Iterate()) {
695 if (c->is_ai) n++;
696 }
697
698 if (n >= _settings_game.difficulty.max_no_competitors) return;
699
700 /* Send a command to all clients to start up a new AI.
701 * Works fine for Multiplayer and Singleplayer */
702 Command<Commands::CompanyControl>::Post(CompanyCtrlAction::NewAI, CompanyID::Invalid(), CompanyRemoveReason::None, ClientID::Invalid);
703});
704
707{
708 /* Ensure the timeout is aborted, so it doesn't fire based on information of the last game. */
710}
711
717
724bool CheckTakeoverVehicleLimit(CompanyID cbig, CompanyID csmall)
725{
726 const Company *c1 = Company::Get(cbig);
727 const Company *c2 = Company::Get(csmall);
728
729 /* Do the combined vehicle counts stay within the limits? */
730 return c1->group_all[VehicleType::Train].num_vehicle + c2->group_all[VehicleType::Train].num_vehicle <= _settings_game.vehicle.max_trains &&
731 c1->group_all[VehicleType::Road].num_vehicle + c2->group_all[VehicleType::Road].num_vehicle <= _settings_game.vehicle.max_roadveh &&
732 c1->group_all[VehicleType::Ship].num_vehicle + c2->group_all[VehicleType::Ship].num_vehicle <= _settings_game.vehicle.max_ships &&
733 c1->group_all[VehicleType::Aircraft].num_vehicle + c2->group_all[VehicleType::Aircraft].num_vehicle <= _settings_game.vehicle.max_aircraft;
734}
735
746{
747 /* Amount of time out for each company to take over a company;
748 * Timeout is a quarter (3 months of 30 days) divided over the
749 * number of companies. The minimum number of days in a quarter
750 * is 90: 31 in January, 28 in February and 31 in March.
751 * Note that the company going bankrupt can't buy itself. */
752 static const int TAKE_OVER_TIMEOUT = 3 * 30 * Ticks::DAY_TICKS / (MAX_COMPANIES - 1);
753
754 assert(c->bankrupt_asked.Any());
755
756 /* We're currently asking some company to buy 'us' */
757 if (c->bankrupt_timeout != 0) {
758 c->bankrupt_timeout -= MAX_COMPANIES;
759 if (c->bankrupt_timeout > 0) return;
760 c->bankrupt_timeout = 0;
761
762 return;
763 }
764
765 /* Did we ask everyone for bankruptcy? If so, bail out. */
766 if (c->bankrupt_asked.All()) return;
767
768 Company *best = nullptr;
769 int32_t best_performance = -1;
770
771 /* Ask the company with the highest performance history first */
772 for (Company *c2 : Company::Iterate()) {
773 if (c2->bankrupt_asked.None() && // Don't ask companies going bankrupt themselves
774 !c->bankrupt_asked.Test(c2->index) &&
775 best_performance < c2->old_economy[1].performance_history &&
776 CheckTakeoverVehicleLimit(c2->index, c->index)) {
777 best_performance = c2->old_economy[1].performance_history;
778 best = c2;
779 }
780 }
781
782 /* Asked all companies? */
783 if (best_performance == -1) {
784 c->bankrupt_asked.Set();
785 return;
786 }
787
788 c->bankrupt_asked.Set(best->index);
789
790 c->bankrupt_timeout = TAKE_OVER_TIMEOUT;
791
792 AI::NewEvent(best->index, new ScriptEventCompanyAskMerger(c->index, c->bankrupt_value));
793 if (IsInteractiveCompany(best->index)) {
794 ShowBuyCompanyDialog(c->index, false);
795 }
796}
797
800{
801 if (_game_mode == GameMode::Editor) return;
802
804 if (c != nullptr) {
805 if (c->name_1 != 0) GenerateCompanyName(c);
807 }
808
809 if (_new_competitor_timeout.HasFired() && _game_mode != GameMode::Menu && AI::CanStartNew()) {
810 int32_t timeout = _settings_game.difficulty.competitors_interval * 60 * Ticks::TICKS_PER_SECOND;
811 /* If the interval is zero, start as many competitors as needed then check every ~10 minutes if a company went bankrupt and needs replacing. */
812 if (timeout == 0) {
813 /* count number of competitors */
814 uint8_t num_ais = 0;
815 for (const Company *cc : Company::Iterate()) {
816 if (cc->is_ai) num_ais++;
817 }
818
819 size_t num_companies = Company::GetNumItems();
820 for (auto i = 0; i < _settings_game.difficulty.max_no_competitors; i++) {
821 if (_networking && num_companies++ >= _settings_client.network.max_companies) break;
822 if (num_ais++ >= _settings_game.difficulty.max_no_competitors) break;
823 Command<Commands::CompanyControl>::Post(CompanyCtrlAction::NewAI, CompanyID::Invalid(), {}, ClientID::Invalid);
824 }
825 timeout = 10 * 60 * Ticks::TICKS_PER_SECOND;
826 }
827 /* Randomize a bit when the AI is actually going to start; ranges from 87.5% .. 112.5% of indicated value. */
828 timeout += ScriptObject::GetRandomizer(OWNER_NONE).Next(timeout / 4) - timeout / 8;
829
830 _new_competitor_timeout.Reset({ TimerGameTick::Priority::CompetitorTimeout, static_cast<uint>(std::max(1, timeout)) });
831 }
832
833 _cur_company_tick_index = (_cur_company_tick_index + 1) % MAX_COMPANIES;
834}
835
840static const IntervalTimer<TimerGameEconomy> _economy_companies_yearly({TimerGameEconomy::Trigger::Year, TimerGameEconomy::Priority::Company}, [](auto)
841{
842 /* Copy statistics */
843 for (Company *c : Company::Iterate()) {
844 /* Move expenses to previous years. */
845 std::rotate(std::rbegin(c->yearly_expenses), std::rbegin(c->yearly_expenses) + 1, std::rend(c->yearly_expenses));
846 c->yearly_expenses[0].fill(0);
847 InvalidateWindowData(WindowClass::Finances, c->index);
848 }
849
850 if (_settings_client.gui.show_finances && _local_company != COMPANY_SPECTATOR) {
853 if (c->num_valid_stat_ent > 5 && c->old_economy[0].performance_history < c->old_economy[4].performance_history) {
854 if (_settings_client.sound.new_year) SndPlayFx(SND_01_BAD_YEAR);
855 } else {
856 if (_settings_client.sound.new_year) SndPlayFx(SND_00_GOOD_YEAR);
857 }
858 }
859});
860
868{
869 this->company_name = GetString(STR_COMPANY_NAME, c->index);
870
871 if (other != nullptr) {
872 this->other_company_name = GetString(STR_COMPANY_NAME, other->index);
873 c = other;
874 }
875
876 this->president_name = GetString(STR_PRESIDENT_NAME_MANAGER, c->index);
877
878 this->title = title;
879 this->colour = c->colour;
880 this->face = c->face;
881
882}
883
888void CompanyAdminUpdate(const Company *company)
889{
891}
892
898void CompanyAdminRemove(CompanyID company_id, CompanyRemoveReason reason)
899{
900 if (_network_server) NetworkAdminCompanyRemove(company_id, static_cast<AdminCompanyRemoveReason>(reason));
901}
902
912CommandCost CmdCompanyCtrl(DoCommandFlags flags, CompanyCtrlAction cca, CompanyID company_id, CompanyRemoveReason reason, ClientID client_id)
913{
914 InvalidateWindowData(WindowClass::CompanyLeague, 0, 0);
915
916 switch (cca) {
917 case CompanyCtrlAction::New: { // Create a new company
918 /* This command is only executed in a multiplayer game */
919 if (!_networking) return CMD_ERROR;
920
921 /* Has the network client a correct ClientID? */
922 if (!flags.Test(DoCommandFlag::Execute)) return CommandCost();
923
925
926 /* Delete multiplayer progress bar */
927 CloseWindowById(WindowClass::NetworkStatus, NetworkStatusWindowNumber::Join);
928
929 Company *c = DoStartupNewCompany(false);
930
931 /* A new company could not be created, revert to being a spectator */
932 if (c == nullptr) {
933 /* We check for "ci != nullptr" as a client could have left by
934 * the time we execute this command. */
935 if (_network_server && ci != nullptr) {
938 }
939 break;
940 }
941
944
945 /* This is the client (or non-dedicated server) who wants a new company */
946 if (client_id == _network_own_client_id) {
948 SetLocalCompany(c->index);
949
950 /*
951 * If a favourite company manager face is selected, choose it. Otherwise, use a random face.
952 * Because this needs to be synchronised over the network, only the client knows
953 * its configuration and we are currently in the execution of a command, we have
954 * to circumvent the normal ::Post logic for commands and just send the command.
955 */
956 if (!_company_manager_face.empty()) {
958 if (cmf.has_value()) {
959 Command<Commands::SetCompanyManagerFace>::SendNet(STR_NULL, c->index, cmf->style, cmf->bits);
960 }
961 }
962
963 /* Now that we have a new company, broadcast our company settings to
964 * all clients so everything is in sync */
966
968 }
969 break;
970 }
971
972 case CompanyCtrlAction::NewAI: { // Make a new AI company
973 if (company_id != CompanyID::Invalid() && company_id >= MAX_COMPANIES) return CMD_ERROR;
974
975 /* For network games, company deletion is delayed. */
976 if (!_networking && company_id != CompanyID::Invalid() && Company::IsValidID(company_id)) return CMD_ERROR;
977
978 if (!flags.Test(DoCommandFlag::Execute)) return CommandCost();
979
980 /* For network game, just assume deletion happened. */
981 assert(company_id == CompanyID::Invalid() || !Company::IsValidID(company_id));
982
983 Company *c = DoStartupNewCompany(true, company_id);
984 if (c != nullptr) {
986 NetworkServerNewCompany(c, nullptr);
987 }
988 break;
989 }
990
991 case CompanyCtrlAction::Delete: { // Delete a company
992 if (reason >= CompanyRemoveReason::End) return CMD_ERROR;
993
994 /* We can't delete the last existing company in singleplayer mode. */
995 if (!_networking && Company::GetNumItems() == 1) return CMD_ERROR;
996
997 Company *c = Company::GetIfValid(company_id);
998 if (c == nullptr) return CMD_ERROR;
999
1000 if (!flags.Test(DoCommandFlag::Execute)) return CommandCost();
1001
1002 /* Show the bankrupt news */
1003 auto cni = std::make_unique<CompanyNewsInformation>(STR_NEWS_COMPANY_BANKRUPT_TITLE, c);
1004 EncodedString headline = GetEncodedString(STR_NEWS_COMPANY_BANKRUPT_DESCRIPTION, cni->company_name);
1005 AddCompanyNewsItem(std::move(headline), std::move(cni));
1006
1007 /* Remove the company */
1009 if (c->is_ai) AI::Stop(c->index);
1010
1011 CompanyID c_index = c->index;
1012 delete c;
1013 AI::BroadcastNewEvent(new ScriptEventCompanyBankrupt(c_index));
1014 Game::NewEvent(new ScriptEventCompanyBankrupt(c_index));
1015 CompanyAdminRemove(c_index, (CompanyRemoveReason)reason);
1016
1017 if (StoryPage::GetNumItems() == 0 || Goal::GetNumItems() == 0) InvalidateWindowData(WindowClass::MainToolbar, 0);
1018 InvalidateWindowData(WindowClass::NetworkClientList, 0);
1019
1020 break;
1021 }
1022
1023 default: return CMD_ERROR;
1024 }
1025
1026 InvalidateWindowClassesData(WindowClass::GameOptions);
1027 InvalidateWindowClassesData(WindowClass::ScriptSettings);
1028 InvalidateWindowClassesData(WindowClass::ScriptList);
1029
1030 return CommandCost();
1031}
1032
1033static bool ExecuteAllowListCtrlAction(CompanyAllowListCtrlAction action, Company *c, const std::string &public_key)
1034{
1035 switch (action) {
1037 return c->allow_list.Add(public_key);
1038
1040 return c->allow_list.Remove(public_key);
1041
1043 if (c->allow_any) return false;
1044 c->allow_any = true;
1045 return true;
1046
1048 if (!c->allow_any) return false;
1049 c->allow_any = false;
1050 return true;
1051
1052 default:
1053 NOT_REACHED();
1054 }
1055}
1056
1065{
1067 if (c == nullptr) return CMD_ERROR;
1068
1069 switch (action) {
1072 /* The public key length includes the '\0'. */
1073 if (public_key.size() != NETWORK_PUBLIC_KEY_LENGTH - 1) return CMD_ERROR;
1074 break;
1075
1078 if (public_key.size() != 0) return CMD_ERROR;
1079 break;
1080
1081 default:
1082 return CMD_ERROR;
1083 }
1084
1085 if (flags.Test(DoCommandFlag::Execute)) {
1086 if (ExecuteAllowListCtrlAction(action, c, public_key)) {
1087 InvalidateWindowData(WindowClass::NetworkClientList, 0);
1088 SetWindowDirty(WindowClass::Company, _current_company);
1089 }
1090 }
1091
1092 return CommandCost();
1093}
1094
1102CommandCost CmdSetCompanyManagerFace(DoCommandFlags flags, uint style, uint32_t bits)
1103{
1104 CompanyManagerFace tmp_face{style, bits, {}};
1105 if (!IsValidCompanyManagerFace(tmp_face)) return CMD_ERROR;
1106
1107 if (flags.Test(DoCommandFlag::Execute)) {
1109 SetCompanyManagerFaceStyle(cmf, style);
1110 cmf.bits = tmp_face.bits;
1111
1113 }
1114 return CommandCost();
1115}
1116
1123{
1125 if (!c->livery[i].in_use.Test(Livery::Flag::Primary)) c->livery[i].colour1 = c->livery[LiveryScheme::Default].colour1;
1126 if (!c->livery[i].in_use.Test(Livery::Flag::Secondary)) c->livery[i].colour2 = c->livery[LiveryScheme::Default].colour2;
1127 }
1129}
1130
1140{
1141 if (scheme >= LiveryScheme::End || (colour >= Colours::End && colour != Colours::Invalid)) return CMD_ERROR;
1142
1143 /* Default scheme can't be reset to invalid. */
1144 if (scheme == LiveryScheme::Default && colour == Colours::Invalid) return CMD_ERROR;
1145
1147
1148 /* Ensure no two companies have the same primary colour */
1149 if (scheme == LiveryScheme::Default && primary) {
1150 for (const Company *cc : Company::Iterate()) {
1151 if (cc != c && cc->colour == colour) return CMD_ERROR;
1152 }
1153 }
1154
1155 if (flags.Test(DoCommandFlag::Execute)) {
1156 if (primary) {
1157 if (scheme != LiveryScheme::Default) c->livery[scheme].in_use.Set(Livery::Flag::Primary, colour != Colours::Invalid);
1158 if (colour == Colours::Invalid) colour = c->livery[LiveryScheme::Default].colour1;
1159 c->livery[scheme].colour1 = colour;
1160
1161 /* If setting the first colour of the default scheme, adjust the
1162 * original and cached company colours too. */
1163 if (scheme == LiveryScheme::Default) {
1166 c->colour = colour;
1168 }
1169 } else {
1170 if (scheme != LiveryScheme::Default) c->livery[scheme].in_use.Set(Livery::Flag::Secondary, colour != Colours::Invalid);
1171 if (colour == Colours::Invalid) colour = c->livery[LiveryScheme::Default].colour2;
1172 c->livery[scheme].colour2 = colour;
1173
1174 if (scheme == LiveryScheme::Default) {
1176 }
1177 }
1178
1179 if (c->livery[scheme].in_use.Any({Livery::Flag::Primary, Livery::Flag::Secondary})) {
1180 /* If enabling a scheme, set the default scheme to be in use too */
1181 c->livery[LiveryScheme::Default].in_use.Set(Livery::Flag::Primary);
1182 } else {
1183 /* Else loop through all schemes to see if any are left enabled.
1184 * If not, disable the default scheme too. */
1186 for (LiveryScheme other_scheme : EnumRange(LiveryScheme::End)) {
1187 if (c->livery[other_scheme].in_use.Any({Livery::Flag::Primary, Livery::Flag::Secondary})) {
1188 c->livery[LiveryScheme::Default].in_use.Set(Livery::Flag::Primary);
1189 break;
1190 }
1191 }
1192 }
1193
1194 ResetVehicleColourMap();
1196
1197 /* All graph related to companies use the company colour. */
1198 InvalidateWindowData(WindowClass::IncomeGraph, 0);
1199 InvalidateWindowData(WindowClass::OperatingProfitGraph, 0);
1200 InvalidateWindowData(WindowClass::DeliveredCargoGraph, 0);
1201 InvalidateWindowData(WindowClass::PerformanceGraph, 0);
1202 InvalidateWindowData(WindowClass::CompanyValueGraph, 0);
1203 InvalidateWindowData(WindowClass::LinkGraphLegend, 0);
1204 /* The smallmap owner view also stores the company colours. */
1206 InvalidateWindowData(WindowClass::SmallMap, 0, 1);
1207
1208 /* Company colour data is indirectly cached. */
1209 for (Vehicle *v : Vehicle::Iterate()) {
1210 if (v->owner == _current_company) v->InvalidateNewGRFCache();
1211 }
1212
1214 }
1215 return CommandCost();
1216}
1217
1223static bool IsUniqueCompanyName(const std::string &name)
1224{
1225 for (const Company *c : Company::Iterate()) {
1226 if (!c->name.empty() && c->name == name) return false;
1227 }
1228
1229 return true;
1230}
1231
1238CommandCost CmdRenameCompany(DoCommandFlags flags, const std::string &text)
1239{
1240 bool reset = text.empty();
1241
1242 if (!reset) {
1244 if (!IsUniqueCompanyName(text)) return CommandCost(STR_ERROR_NAME_MUST_BE_UNIQUE);
1245 }
1246
1247 if (flags.Test(DoCommandFlag::Execute)) {
1249 if (reset) {
1250 c->name.clear();
1251 } else {
1252 c->name = text;
1253 }
1254
1255 InvalidateWindowClassesData(WindowClass::Company, WID_C_COMPANY_NAME);
1258
1259 std::string new_name = GetString(STR_COMPANY_NAME, c->index);
1260 AI::BroadcastNewEvent(new ScriptEventCompanyRenamed(c->index, new_name));
1261 Game::NewEvent(new ScriptEventCompanyRenamed(c->index, new_name));
1262 }
1263
1264 return CommandCost();
1265}
1266
1272static bool IsUniquePresidentName(const std::string &name)
1273{
1274 for (const Company *c : Company::Iterate()) {
1275 if (!c->president_name.empty() && c->president_name == name) return false;
1276 }
1277
1278 return true;
1279}
1280
1287CommandCost CmdRenamePresident(DoCommandFlags flags, const std::string &text)
1288{
1289 bool reset = text.empty();
1290
1291 if (!reset) {
1293 if (!IsUniquePresidentName(text)) return CommandCost(STR_ERROR_NAME_MUST_BE_UNIQUE);
1294 }
1295
1296 if (flags.Test(DoCommandFlag::Execute)) {
1298
1299 if (reset) {
1300 c->president_name.clear();
1301 } else {
1302 c->president_name = text;
1303
1304 if (c->name_1 == STR_SV_UNNAMED && c->name.empty()) {
1305 Command<Commands::RenameCompany>::Do(DoCommandFlag::Execute, text + " Transport");
1306 }
1307 }
1308
1312
1313 std::string new_name = GetString(STR_PRESIDENT_NAME, c->index);
1314 AI::BroadcastNewEvent(new ScriptEventPresidentRenamed(c->index, new_name));
1315 Game::NewEvent(new ScriptEventPresidentRenamed(c->index, new_name));
1316 }
1317
1318 return CommandCost();
1319}
1320
1328{
1329 const VehicleDefaultSettings *vds = (c == nullptr) ? &_settings_client.company.vehicle : &c->settings.vehicle;
1330 switch (type) {
1331 default: NOT_REACHED();
1332 case VehicleType::Train: return vds->servint_trains;
1333 case VehicleType::Road: return vds->servint_roadveh;
1334 case VehicleType::Aircraft: return vds->servint_aircraft;
1335 case VehicleType::Ship: return vds->servint_ships;
1336 }
1337}
1338
1345{
1346 uint32_t total = 0;
1347 for (RoadType rt : GetMaskForRoadTramType(rtt)) {
1348 total += this->road[rt];
1349 }
1350 return total;
1351}
1352
1363CommandCost CmdGiveMoney(DoCommandFlags flags, Money money, CompanyID dest_company)
1364{
1365 if (!_settings_game.economy.give_money) return CMD_ERROR;
1366
1368 CommandCost amount(ExpensesType::Other, std::min<Money>(money, 20000000LL));
1369
1370 /* You can only transfer funds that is in excess of your loan */
1371 if (c->money - c->current_loan < amount.GetCost() || amount.GetCost() < 0) return CommandCost(STR_ERROR_INSUFFICIENT_FUNDS);
1372 if (!Company::IsValidID(dest_company)) return CMD_ERROR;
1373
1374 if (flags.Test(DoCommandFlag::Execute)) {
1375 /* Add money to company */
1377
1378 if (_networking) {
1379 std::string dest_company_name = GetString(STR_COMPANY_NAME, dest_company);
1380 std::string from_company_name = GetString(STR_COMPANY_NAME, _current_company);
1381
1382 NetworkTextMessage(NetworkAction::GiveMoney, GetDrawStringCompanyColour(_current_company), false, from_company_name, dest_company_name, amount.GetCost());
1383 }
1384 }
1385
1386 /* Subtract money from local-company */
1387 return amount;
1388}
1389
1400{
1401 for (Company *c : Company::Iterate()) {
1402 if (Company::IsHumanID(c->index)) {
1403 return c->index;
1404 }
1405 }
1406
1408 for (CompanyID c = CompanyID::Begin(); c < MAX_COMPANIES; ++c) {
1409 if (!Company::IsValidID(c)) {
1410 return c;
1411 }
1412 }
1413 }
1414
1415 return CompanyID::Begin();
1416}
1417
1418static std::vector<FaceSpec> _faces;
1419
1424{
1425 _faces.clear();
1426 _faces.assign(std::begin(_original_faces), std::end(_original_faces));
1427}
1428
1434{
1435 return static_cast<uint>(std::size(_faces));
1436}
1437
1443const FaceSpec *GetCompanyManagerFaceSpec(uint style_index)
1444{
1445 if (style_index < GetNumCompanyManagerFaceStyles()) return &_faces[style_index];
1446 return nullptr;
1447}
1448
1454std::optional<uint> FindCompanyManagerFaceLabel(std::string_view label)
1455{
1456 auto it = std::ranges::find(_faces, label, &FaceSpec::label);
1457 if (it == std::end(_faces)) return std::nullopt;
1458
1459 return static_cast<uint>(std::distance(std::begin(_faces), it));
1460}
1461
1467FaceVars GetCompanyManagerFaceVars(uint style)
1468{
1469 const FaceSpec *spec = GetCompanyManagerFaceSpec(style);
1470 if (spec == nullptr) return {};
1471 return spec->GetFaceVars();
1472}
1473
1481{
1482 const FaceSpec *spec = GetCompanyManagerFaceSpec(style);
1483 assert(spec != nullptr);
1484
1485 cmf.style = style;
1486 cmf.style_label = spec->label;
1487}
1488
1500
1508uint32_t MaskCompanyManagerFaceBits(const CompanyManagerFace &cmf, FaceVars vars)
1509{
1510 CompanyManagerFace face{};
1511
1512 for (auto var : SetBitIterator(GetActiveFaceVars(cmf, vars))) {
1513 vars[var].SetBits(face, vars[var].GetBits(cmf));
1514 }
1515
1516 return face.bits;
1517}
1518
1525{
1526 uint32_t masked_face_bits = MaskCompanyManagerFaceBits(cmf, GetCompanyManagerFaceVars(cmf.style));
1527 return fmt::format("{}:{}", cmf.style_label, masked_face_bits);
1528}
1529
1535std::optional<CompanyManagerFace> ParseCompanyManagerFaceCode(std::string_view str)
1536{
1537 if (str.empty()) return std::nullopt;
1538
1540 StringConsumer consumer{str};
1541 if (consumer.FindChar(':') != StringConsumer::npos) {
1542 auto label = consumer.ReadUntilChar(':', StringConsumer::SKIP_ONE_SEPARATOR);
1543
1544 /* Read numeric part and ensure it's valid. */
1545 auto bits = consumer.TryReadIntegerBase<uint32_t>(10, true);
1546 if (!bits.has_value() || consumer.AnyBytesLeft()) return std::nullopt;
1547
1548 /* Ensure style label is valid. */
1549 auto style = FindCompanyManagerFaceLabel(label);
1550 if (!style.has_value()) return std::nullopt;
1551
1552 SetCompanyManagerFaceStyle(cmf, *style);
1553 cmf.bits = *bits;
1554 } else {
1555 /* No ':' included, treat as numeric-only. This allows old-style codes to be entered. */
1556 auto bits = ParseInteger(str, 10, true);
1557 if (!bits.has_value()) return std::nullopt;
1558
1559 /* Old codes use bits 0..1 to represent face style. These map directly to the default face styles. */
1560 SetCompanyManagerFaceStyle(cmf, GB(*bits, 0, 2));
1561 cmf.bits = *bits;
1562 }
1563
1564 /* Force the face bits to be valid. */
1565 FaceVars vars = GetCompanyManagerFaceVars(cmf.style);
1567 cmf.bits = MaskCompanyManagerFaceBits(cmf, vars);
1568
1569 return cmf;
1570}
Base functions for all AIs.
AIConfig stores the configuration settings of every AI.
The AIInstance tracks an AI.
Class for backupping variables and making sure they are restored later.
static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
static void BroadcastNewEvent(ScriptEvent *event, CompanyID skip_company=CompanyID::Invalid())
Broadcast a new event to all active AIs.
Definition ai_core.cpp:250
static bool CanStartNew()
Is it possible to start a new AI company?
Definition ai_core.cpp:30
static void StartNew(CompanyID company)
Start a new AI company.
Definition ai_core.cpp:36
static void Stop(CompanyID company)
Stop a company to be controlled by an AI.
Definition ai_core.cpp:113
static void NewEvent(CompanyID company, ScriptEvent *event)
Queue a new event for an AI.
Definition ai_core.cpp:231
constexpr bool All(const Timpl &other) const
Test if all of the values are set.
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
constexpr Timpl & Set()
Set all bits.
constexpr bool Any(const Timpl &other) const
Test if any of the given values are set.
Common return value for all commands.
ExpensesType GetExpensesType() const
The expense type of the cost.
void MakeError(StringID message)
Makes this CommandCost behave like an error command.
Money GetCost() const
The costs as made up to this moment.
void SetEncodedMessage(EncodedString &&message)
Set the encoded message string.
void SetErrorOwner(Owner owner)
Set the 'owner' (the originator) of this error message.
Container for an encoded string, created by GetEncodedString.
Enum-as-bit-set wrapper.
Iterate a range of enum values.
static void NewEvent(class ScriptEvent *event)
Queue a new event for the game script.
An interval timer will fire every interval, and will continue to fire until it is deleted.
Definition timer.h:76
bool Add(std::string_view key)
Add the given key to the authorized keys, when it is not already contained.
Definition network.cpp:190
bool Remove(std::string_view key)
Remove the given key from the authorized keys, when it is exists.
Definition network.cpp:206
Parse data from a string / buffer.
std::optional< T > TryReadIntegerBase(int base, bool clamp=false)
Try to read and parse an integer in number 'base', and then advance the reader.
std::string_view ReadUntilChar(char c, SeparatorUsage sep)
Read data until the first occurrence of 8-bit char 'c', and advance reader.
size_type FindChar(char c) const
Find first occurrence of 8-bit char 'c'.
@ SKIP_ONE_SEPARATOR
Read and discard one separator, do not include it in the result.
bool AnyBytesLeft() const noexcept
Check whether any bytes left to read.
static constexpr size_type npos
Special value for "end of data".
static constexpr TimerGameTick::Ticks DAY_TICKS
1 day is 74 ticks; TimerGameCalendar::date_fract used to be uint16_t and incremented by 885.
static constexpr TimerGameTick::Ticks TICKS_PER_SECOND
Estimation of how many ticks fit in a single second.
A timeout timer will fire once after the interval.
Definition timer.h:116
static Year year
Current year, starting at 0.
static Year year
Current year, starting at 0.
@ CompetitorTimeout
Considering starting a new competitor/AI.
A sort-of mixin that implements 'at(pos)' and 'operator[](pos)' only for a specific type.
Functions related to commands.
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
@ Execute
execute the given command
EnumBitSet< DoCommandFlag, uint16_t > DoCommandFlags
Bitset of DoCommandFlag elements.
Definition of stuff that is very close to a company, like the company struct itself.
uint _cur_company_tick_index
used to generate a name for one company that doesn't have a name yet per tick
void ClearEnginesHiddenFlagOfCompany(CompanyID cid)
Clear the 'hidden' flag for all engines of a new company.
Definition engine.cpp:1042
void UpdateObjectColours(const Company *c)
Updates the colour of the object whenever a company changes.
std::optional< CompanyManagerFace > ParseCompanyManagerFaceCode(std::string_view str)
Parse a face code into a company manager face.
static void GenerateCompanyName(Company *c)
Generate the name of a company from the last build coordinate.
static bool IsValidCompanyManagerFace(CompanyManagerFace cmf)
Checks whether a company manager's face is a valid encoding.
const FaceSpec * GetCompanyManagerFaceSpec(uint style_index)
Get the definition of a company manager face style.
void OnTick_Companies()
Called every tick for updating some company info.
std::array< StringParameter, 2 > GetParamsForOwnedBy(Owner owner, TileIndex tile)
Get the right StringParameters for STR_ERROR_OWNED_BY.
FaceVars GetCompanyManagerFaceVars(uint style)
Get the face variables for a face style.
CommandCost CmdCompanyAllowListCtrl(DoCommandFlags flags, CompanyAllowListCtrlAction action, const std::string &public_key)
Add or remove the given public key to the allow list of this company.
void RandomiseCompanyManagerFace(CompanyManagerFace &cmf, Randomizer &randomizer)
Completely randomise a company manager face, including style.
void ResetFaces()
Reset company manager face styles to default.
Company * DoStartupNewCompany(bool is_ai, CompanyID company=CompanyID::Invalid())
Create a new company and sets all company variables default values.
void DrawCompanyIcon(CompanyID c, int x, int y)
Draw the icon of a company.
uint32_t MaskCompanyManagerFaceBits(const CompanyManagerFace &cmf, FaceVars vars)
Mask company manager face bits to ensure they are all within range.
static const std::initializer_list< Colours > _similar_colour[to_underlying(Colours::End)]
Similar colours, so we can try to prevent same coloured companies.
TimeoutTimer< TimerGameTick > _new_competitor_timeout({ TimerGameTick::Priority::CompetitorTimeout, 0 }, []() { if(_game_mode==GameMode::Menu||!AI::CanStartNew()) return;if(_networking &&Company::GetNumItems() >=_settings_client.network.max_companies) return;if(_settings_game.difficulty.competitors_interval==0) return;uint8_t n=0;for(const Company *c :Company::Iterate()) { if(c->is_ai) n++;} if(n >=_settings_game.difficulty.max_no_competitors) return;Command< Commands::CompanyControl >::Post(CompanyCtrlAction::NewAI, CompanyID::Invalid(), CompanyRemoveReason::None, ClientID::Invalid);})
Start a new competitor company if possible.
std::string _company_manager_face
for company manager face storage in openttd.cfg
static Colours GenerateCompanyColour()
Generate a company colour.
static void GeneratePresidentName(Company *c)
Generate a random president name of a company.
TypedIndexContainer< std::array< Colours, MAX_COMPANIES >, CompanyID > _company_colours
NOSAVE: can be determined from company structs.
void ResetCompanyLivery(Company *c)
Reset the livery schemes to the company's primary colour.
void UpdateCompanyLiveries(Company *c)
Update liveries for a company.
CommandCost CheckTileOwnership(TileIndex tile)
Check whether the current owner owns the stuff on the given tile.
CommandCost CmdSetCompanyColour(DoCommandFlags flags, LiveryScheme scheme, bool primary, Colours colour)
Change the company's company-colour.
CommandCost CmdCompanyCtrl(DoCommandFlags flags, CompanyCtrlAction cca, CompanyID company_id, CompanyRemoveReason reason, ClientID client_id)
Control the companies: add, delete, etc.
static std::vector< FaceSpec > _faces
All company manager face styles.
void InvalidateCompanyWindows(const Company *company)
Mark all finance windows owned by a company as needing a refresh.
int CompanyServiceInterval(const Company *c, VehicleType type)
Get the service interval for the given company and vehicle type.
PaletteID GetCompanyPalette(CompanyID company)
Get the palette for recolouring with a company colour.
void SetCompanyManagerFaceStyle(CompanyManagerFace &cmf, uint style)
Set a company face style.
bool CheckCompanyHasMoney(CommandCost &cost)
Verify whether the company can pay the bill.
static void SubtractMoneyFromCompany(Company *c, const CommandCost &cost)
Deduct costs of a command from the money of a company.
static const IntervalTimer< TimerWindow > invalidate_company_windows_interval(std::chrono::milliseconds(1), [](auto) { for(CompanyID cid :_dirty_company_finances) { if(cid==_local_company) SetWindowWidgetDirty(WindowClass::Statusbar, 0, WID_S_RIGHT);Window *w=FindWindowById(WindowClass::Finances, cid);if(w !=nullptr) { w->SetWidgetDirty(WID_CF_EXPS_PRICE3);w->SetWidgetDirty(WID_CF_OWN_VALUE);w->SetWidgetDirty(WID_CF_LOAN_VALUE);w->SetWidgetDirty(WID_CF_BALANCE_VALUE);w->SetWidgetDirty(WID_CF_MAXLOAN_VALUE);} SetWindowWidgetDirty(WindowClass::Company, cid, WID_C_DESC_COMPANY_VALUE);} _dirty_company_finances.Reset();})
Refresh all company finance windows previously marked dirty.
CompanyID GetFirstPlayableCompanyID()
Get the index of the first available company.
static CompanyMask _dirty_company_finances
Bitmask of company finances that should be marked dirty.
CommandCost CmdSetCompanyManagerFace(DoCommandFlags flags, uint style, uint32_t bits)
Change the company manager's face.
void SetLocalCompany(CompanyID new_company, bool switching_game)
Sets the local company and updates the settings that are set on a per-company basis to reflect the co...
Money GetAvailableMoneyForCommand()
This functions returns the money which can be used to execute a command.
void CompanyAdminUpdate(const Company *company)
Called whenever company related information changes in order to notify admins.
std::optional< uint > FindCompanyManagerFaceLabel(std::string_view label)
Find a company manager face style by label.
CommandCost CheckOwnership(Owner owner, TileIndex tile)
Check whether the current owner owns something.
void CompanyAdminRemove(CompanyID company_id, CompanyRemoveReason reason)
Called whenever a company is removed in order to notify admins.
static const EnumIndexArray< uint8_t, Colours, Colours::End > _colour_sort
Sorting weights for the company colours.
CommandCost CmdRenamePresident(DoCommandFlags flags, const std::string &text)
Change the name of the president.
static bool SetCompanyName(std::span< const std::string > other_names, Company *c, const Town *t, StringID str, uint32_t strp)
Set a company name based on type and seed, if the name is unique and shorter than the max length.
CompanyPool _company_pool("Company")
Pool of companies.
uint GetNumCompanyManagerFaceStyles()
Get the number of company manager face styles.
std::string FormatCompanyManagerFaceCode(const CompanyManagerFace &cmf)
Get a face code representation of a company manager face.
Money GetAvailableMoney(CompanyID company)
Get the amount of money that a company has available, or INT64_MAX if there is no such valid company.
void UpdateLandscapingLimits()
Update the landscaping limits per company.
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
void InitializeCompanies()
Initialize the pool of companies.
void StartupCompanies()
Start of a new game.
bool CheckTakeoverVehicleLimit(CompanyID cbig, CompanyID csmall)
Can company cbig buy company csmall without exceeding vehicle limits?
static bool IsUniqueCompanyName(const std::string &name)
Is the given name in use as name of a company?
static bool IsUniquePresidentName(const std::string &name)
Is the given name in use as president name of a company?
CompanyID _current_company
Company currently doing an action.
CommandCost CmdGiveMoney(DoCommandFlags flags, Money money, CompanyID dest_company)
Transfer funds (money) from one company to another.
static const IntervalTimer< TimerGameEconomy > _economy_companies_yearly({TimerGameEconomy::Trigger::Year, TimerGameEconomy::Priority::Company}, [](auto) { for(Company *c :Company::Iterate()) { std::rotate(std::rbegin(c->yearly_expenses), std::rbegin(c->yearly_expenses)+1, std::rend(c->yearly_expenses));c->yearly_expenses[0].fill(0);InvalidateWindowData(WindowClass::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);} } })
A year has passed, update the economic data of all companies, and perhaps show the financial overview...
static void HandleBankruptcyTakeover(Company *c)
Handle the bankruptcy take over of a company.
ExtendedTextColour GetDrawStringCompanyColour(CompanyID company)
Get the colour for DrawString-subroutines which matches the colour of the company.
CommandCost CmdRenameCompany(DoCommandFlags flags, const std::string &text)
Change the name of the company.
void SubtractMoneyFromCompanyFract(CompanyID company, const CommandCost &cst)
Subtract money from a company, including the money fraction.
static bool SetPresidentName(std::span< const std::string > other_names, Company *c, uint32_t seed)
Set a company's president name based on seed, if the name is unique and shorter than the max length.
Command definitions related to companies.
This file contains all definitions for default company faces.
static FaceSpec _original_faces[]
Original face styles.
Functions related to companies.
bool IsInteractiveCompany(CompanyID company)
Is the user representing company?
void ChangeOwnershipOfCompanyItems(Owner old_owner, Owner new_owner)
Change the ownership of all the items of a company.
Definition economy.cpp:323
void ShowBuyCompanyDialog(CompanyID company, bool hostile_takeover)
Show the query to buy another company.
bool IsLocalCompany()
Is the current company the local company?
void ShowCompanyFinances(CompanyID company)
Open the finances window of a company.
GUI Functions related to companies.
void CloseCompanyWindows(CompanyID company)
Close all windows of a company.
Definition window.cpp:1233
Functionality related to the company manager's face.
void RandomiseCompanyManagerFaceBits(CompanyManagerFace &cmf, FaceVars vars, Randomizer &randomizer)
Make a random new face without changing the face style.
uint64_t GetActiveFaceVars(const CompanyManagerFace &cmf, FaceVars vars)
Get a bitmask of currently active face variables.
void ScaleAllCompanyManagerFaceBits(CompanyManagerFace &cmf, FaceVars vars)
Scales all company manager's face bits to the correct scope.
static const uint MAX_LENGTH_PRESIDENT_NAME_CHARS
The maximum length of a president name in characters including '\0'.
static const uint MAX_LENGTH_COMPANY_NAME_CHARS
The maximum length of a company name in characters including '\0'.
CompanyCtrlAction
The action to do with Commands::CompanyControl.
@ New
Create a new company.
@ NewAI
Create a new AI company.
@ Delete
Delete a company.
static constexpr CompanyID COMPANY_SPECTATOR
The client is spectating.
static constexpr Owner OWNER_END
Last + 1 owner.
CompanyAllowListCtrlAction
The action to do with Commands::CompanyAllowListControl.
@ RemoveKey
Remove a public key.
@ AddKey
Create a public key.
@ AllowListed
Allow only listed keys to join the company.
@ AllowAny
Allow joining the company without a key.
static constexpr Owner OWNER_TOWN
A town owns the tile, or a town is expanding.
static constexpr Owner OWNER_NONE
The tile has no ownership.
static constexpr Owner INVALID_OWNER
An invalid owner.
CompanyRemoveReason
The reason why the company was removed.
@ None
Dummy reason for actions that don't need one.
@ End
Sentinel for end.
Types related to the company widgets.
@ WID_CF_OWN_VALUE
Own funds, not including loan.
@ WID_CF_LOAN_VALUE
Loan.
@ WID_CF_BALANCE_VALUE
Bank balance value.
@ WID_CF_EXPS_PRICE3
Column for year Y expenses.
@ WID_CF_MAXLOAN_VALUE
Max loan widget.
@ WID_C_DESC_COMPANY_VALUE
Company value.
@ WID_C_PRESIDENT_NAME
Button to change president name.
@ WID_C_COMPANY_NAME
Button to change company name.
static const uint NETWORK_PUBLIC_KEY_LENGTH
The maximum length of the hexadecimal encoded public keys, in bytes including '\0'.
Definition config.h:99
@ LoanInterest
Interest payments over the loan.
@ TrainRun
Running costs trains.
@ AircraftRevenue
Revenue from aircraft.
@ Invalid
Invalid expense type.
@ Property
Property costs.
@ Other
Other expenses.
@ RoadVehRevenue
Revenue from road vehicles.
@ AircraftRun
Running costs aircraft.
@ RoadVehRun
Running costs road vehicles.
@ ShipRevenue
Revenue from ships.
@ TrainRevenue
Revenue from trains.
@ ShipRun
Running costs ships.
static const int LOAN_INTERVAL
The "steps" in loan size, in British Pounds!
static const int64_t INITIAL_LOAN
The size of loan for a new company, in British Pounds!
constexpr std::underlying_type_t< enum_type > to_underlying(enum_type e)
Implementation of std::to_underlying (from C++23).
Definition enum_type.hpp:21
EnumClassIndexContainer< std::array< T, to_underlying(N)>, Index > EnumIndexArray
A typedef for EnumClassIndexContainer using std::array as the backing container type.
Base functions for all Games.
void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub, ZoomLevel zoom)
Draw a sprite, not in a viewport.
Definition gfx.cpp:1037
uint32_t PaletteID
The number of the palette.
Definition gfx_type.h:18
Colours
One of 16 base colours used for companies and windows/widgets.
Definition gfx_type.h:283
@ Begin
Begin marker.
Definition gfx_type.h:284
@ White
White.
Definition gfx_type.h:300
@ PaleGreen
Pale green.
Definition gfx_type.h:286
@ Mauve
Mauve.
Definition gfx_type.h:295
@ Invalid
Invalid marker.
Definition gfx_type.h:302
@ LightBlue
Light blue.
Definition gfx_type.h:290
@ Yellow
Yellow.
Definition gfx_type.h:288
@ End
End-of-array marker.
Definition gfx_type.h:301
@ DarkBlue
Dark blue.
Definition gfx_type.h:285
@ Orange
Orange.
Definition gfx_type.h:297
@ Blue
Blue.
Definition gfx_type.h:293
@ Purple
Purple.
Definition gfx_type.h:296
@ Grey
Grey.
Definition gfx_type.h:299
@ Green
Green.
Definition gfx_type.h:291
@ Cream
Cream.
Definition gfx_type.h:294
@ Brown
Brown.
Definition gfx_type.h:298
@ DarkGreen
Dark green.
Definition gfx_type.h:292
Goal base class.
void UpdateCompanyGroupLiveries(const Company *c)
Update group liveries for a company.
void MarkWholeScreenDirty()
This function mark the whole screen as dirty.
Definition gfx.cpp:1553
LiveryScheme
List of different livery schemes.
Definition livery.h:22
@ Steam
Steam engines.
Definition livery.h:27
@ Default
Default scheme.
Definition livery.h:24
@ End
End marker.
Definition livery.h:58
constexpr bool IsInsideMM(const size_t x, const size_t min, const size_t max) noexcept
Checks if a value is in an interval.
bool _networking
are we in networking mode?
Definition network.cpp:67
bool _network_server
network-server is active
Definition network.cpp:68
ClientID _network_own_client_id
Our client identifier.
Definition network.cpp:72
void NetworkTextMessage(NetworkAction action, ExtendedTextColour colour, bool self_send, std::string_view name, std::string_view str, StringParameter &&data)
Writes a text-message to the console and the chat box.
Definition network.cpp:244
Basic functions/variables used all over the place.
void NetworkAdminCompanyUpdate(const Company *company)
Notify the admin network of company updates.
void NetworkAdminCompanyNew(const Company *company)
Notify the admin network of a new company.
void NetworkAdminCompanyRemove(CompanyID company_id, AdminCompanyRemoveReason bcrr)
Notify the admin network of a company to be removed (including the reason why).
Server part of the admin network protocol.
Base core network types and some helper functions to access them.
Network functions used by other parts of OpenTTD.
void NetworkServerNewCompany(const Company *company, NetworkClientInfo *ci)
Perform all the server specific administration of a new company.
void NetworkUpdateClientInfo(ClientID client_id)
Send updated client info of a particular client.
@ GiveMoney
A company was given money.
@ Team
Send message/notice to everyone playing the same company (Team).
ClientID
'Unique' identifier to be given to clients
@ Invalid
Client is not part of anything.
Functions related to news.
void AddNewsItem(EncodedString &&headline, NewsType type, NewsStyle style, NewsFlags flags, NewsReference ref1={}, NewsReference ref2={}, std::unique_ptr< NewsAllocatedData > &&data=nullptr, AdviceType advice_type=AdviceType::Invalid)
Add a new newsitem to be shown.
Definition news_gui.cpp:917
@ CompanyInfo
Company info (new companies, bankruptcy messages).
Definition news_type.h:34
@ Company
Company news item. (Newspaper with face).
Definition news_type.h:82
@ Editor
In the scenario editor.
Definition openttd.h:21
@ Menu
In the main menu.
Definition openttd.h:19
PixelColour GetColourGradient(Colours colour, Shade shade)
Get colour gradient palette index.
Definition palette.cpp:393
@ Normal
Normal colour shade.
Some methods of Pool are placed here in order to reduce compilation time and binary size.
#define INSTANTIATE_POOL_METHODS(name)
Force instantiation of pool methods so we don't get linker errors.
RailTypes GetCompanyRailTypes(CompanyID company, bool introduces)
Get the rail types the given company can build.
Definition rail.cpp:137
Rail specific functions.
void SetDefaultRailGui()
Set the initial (default) railtype to use.
Randomizer _random
Random used in the game state calculations.
RoadTypes GetCompanyRoadTypes(CompanyID company, bool introduces)
Get the road types the given company can build.
Definition road.cpp:210
RoadTypes GetMaskForRoadTramType(RoadTramType rtt)
Get the mask for road types of the given RoadTramType.
Definition road.h:185
void SetDefaultRoadGui()
Set the initial (default) road & tram type to use.
Functions/types related to the road GUIs.
RoadType
The different roadtypes we support.
Definition road_type.h:24
RoadTramType
The different types of road type.
Definition road_type.h:38
A number of safeguards to prevent using unsafe methods.
void SyncCompanySettings()
Sync all company settings in a multiplayer game.
void SetDefaultCompanySettings(CompanyID cid)
Set the company settings for a new company to their default values.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition settings.cpp:61
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:60
Functions related to setting/changing the settings.
void BuildOwnerLegend()
Completes the array for the owned property legend.
Smallmap GUI functions.
Functions related to sound.
@ SND_01_BAD_YEAR
40 == 0x28 New year: performance declined
Definition sound_type.h:88
@ SND_00_GOOD_YEAR
39 == 0x27 New year: performance improved
Definition sound_type.h:87
static PaletteID GetColourPalette(Colours colour)
Get recolour palette for a colour.
Definition sprite.h:221
static const SpriteID SPR_COMPANY_ICON
Icon showing company colour.
Definition sprites.h:385
Types related to the statusbar widgets.
@ WID_S_RIGHT
Right part; bank balance.
Definition of base types and functions in a cross-platform compatible way.
StoryPage base class.
size_t Utf8StringLength(std::string_view str)
Get the length of an UTF-8 encoded string in number of characters and thus not the number of bytes th...
Definition string.cpp:351
Parse strings.
static std::optional< T > ParseInteger(std::string_view arg, int base=10, bool clamp=false)
Change a string into its number representation.
EncodedString GetEncodedStringWithArgs(StringID str, std::span< const StringParameter > params)
Encode a string with its parameters into an encoded string.
Definition strings.cpp:102
EncodedString GetEncodedString(StringID str)
Encode a string with no parameters into an encoded string.
Definition strings.cpp:90
std::string GetString(StringID string)
Resolve the given StringID into a std::string with formatting but no parameters.
Definition strings.cpp:424
Functions related to OTTD's strings.
static constexpr StringID SPECSTR_COMPANY_NAME_START
Special strings for company names on the form "TownName transport".
static constexpr uint16_t SPECSTR_TOWNNAME_START
Special strings for town names.
static constexpr StringID SPECSTR_ANDCO_NAME
Special string for Surname & Co company names.
static constexpr StringID SPECSTR_PRESIDENT_NAME
Special string for the president's name.
StrongType::Typedef< uint32_t, struct StringIDTag, StrongType::Compare, StrongType::Integer > StringID
Numeric value that represents a string, independent of the selected language.
Money income
The amount of income.
Money expenses
The amount of expenses.
uint32_t GetRoadTramTotal(RoadTramType rtt) const
Get total sum of all owned road bits.
std::array< uint32_t, ROADTYPE_END > road
Count of company owned track bits for each road type.
uint32_t bits
Company manager face bits, meaning is dependent on style.
uint style
Company manager face style.
std::string style_label
Face style label.
CompanyManagerFace face
The face of the president.
Definition news_type.h:171
Colours colour
The colour related to the company.
Definition news_type.h:172
CompanyNewsInformation(StringID title, const struct Company *c, const struct Company *other=nullptr)
Fill the CompanyNewsInformation struct with the required data.
std::string president_name
The name of the president.
Definition news_type.h:167
std::string company_name
The name of the company.
Definition news_type.h:166
std::string other_company_name
The name of the company taking over this one.
Definition news_type.h:168
uint32_t clear_limit
Amount of tiles we can (still) clear (times 65536).
CompanyMask bankrupt_asked
which companies were asked about buying it?
std::string president_name
Name of the president if the user changed it.
int16_t bankrupt_timeout
If bigger than 0, amount of time to wait for an answer on an offer to buy this company.
CompanySettings settings
settings specific for each company
NetworkAuthorizedKeys allow_list
Public keys of clients that are allowed to join this company.
bool allow_any
Set if anyone is allowed to join this company.
uint32_t build_object_limit
Amount of tiles we can (still) build objects on (times 65536). Also applies to buying land and placin...
uint32_t name_2
Parameter of name_1.
uint8_t money_fraction
Fraction of money of the company, too small to represent in money.
bool is_ai
If true, the company is (also) controlled by the computer (a NoAI program).
uint32_t president_name_2
Parameter of president_name_1.
StringID name_1
Name of the company if the user did not change it.
Money current_loan
Amount of money borrowed from the bank.
TimerGameCalendar::Year inaugurated_year_calendar
Calendar year of starting the company. Used to display proper Inauguration year while in wallclock mo...
uint32_t terraform_limit
Amount of tileheights we can (still) terraform (times 65536).
TimerGameEconomy::Year inaugurated_year
Economy year of starting the company.
CompanyEconomyEntry cur_economy
Economic data of the company of this quarter.
Colours colour
Company colour.
uint32_t tree_limit
Amount of trees we can (still) plant (times 65536).
std::array< CompanyEconomyEntry, MAX_HISTORY_QUARTERS > old_economy
Economic data of the company of the last MAX_HISTORY_QUARTERS quarters.
CompanyManagerFace face
Face description of the president.
Money max_loan
Max allowed amount of the loan or COMPANY_MAX_LOAN_DEFAULT.
std::array< Expenses, 3 > yearly_expenses
Expenses of the company for the last three years.
TileIndex last_build_coordinate
Coordinate of the last build thing by this company.
StringID president_name_1
Name of the president if the user did not change it.
std::string name
Name of the company if the user changed it.
Money money
Money owned by the company.
uint8_t num_valid_stat_ent
Number of valid statistical entries in old_economy.
VehicleDefaultSettings vehicle
default settings for vehicles
Money GetMaxLoan() const
Calculate the max allowed loan for this company.
VehicleTypeIndexArray< GroupStatistics > group_all
NOSAVE: Statistics for the ALL_GROUP group.
static bool IsHumanID(auto index)
Is this company a company not controlled by a NoAI program?
RoadTypes avail_roadtypes
Road types available to this company.
~Company()
Close the associated company windows.
RailTypes avail_railtypes
Rail types available to this company.
static void PostDestructor(size_t index)
Invalidating some stuff after removing item from the pool.
Company(CompanyID index, StringID name_1={}, bool is_ai=false)
Constructor.
Container for the text colour and some text colour related flags for drawing.
Definition gfx_type.h:349
Group data.
Definition group.h:76
@ Primary
Primary colour is set.
Definition livery.h:85
@ Secondary
Secondary colour is set.
Definition livery.h:86
Container for all information known about a client.
static NetworkClientInfo * GetByClientID(ClientID client_id)
Return the CI given it's client-identifier.
Definition network.cpp:118
CompanyID client_playas
As which company is this client playing (CompanyID).
ClientID client_id
Client identifier (same as ClientState->client_id).
static Pool::IterateWrapper< Company > Iterate(size_t from=0)
static T * Create(Targs &&... args)
static T * CreateAtIndex(CompanyID index, Targs &&... args)
static Company * Get(auto index)
static bool CanAllocateItem(size_t n=1)
static Company * GetIfValid(auto index)
Structure to encapsulate the pseudo random number generators.
uint32_t Next()
Generate the next pseudo random number.
Iterable ensemble of each set bit in a value.
Town data structure.
Definition town.h:64
std::string name
Custom town name. If empty, the town was not renamed and uses the generated name.
Definition town.h:74
uint32_t townnameparts
Random number that give unique town name when passed to generator.
Definition town.h:73
uint16_t townnametype
The style of the name.
Definition town.h:72
Default settings for vehicles.
uint16_t servint_aircraft
service interval for aircraft
uint16_t servint_roadveh
service interval for road vehicles
uint16_t servint_ships
service interval for ships
uint16_t servint_trains
service interval for trains
Vehicle data structure.
Data structure for an opened window.
Definition window_gui.h:273
void SetWidgetDirty(WidgetID widget_index) const
Invalidate a widget, i.e.
Definition window.cpp:565
AdminCompanyRemoveReason
Reasons for removing a company - communicated to admins.
Definition tcp_admin.h:107
Owner GetTileOwner(Tile tile)
Returns the owner of a tile.
Definition tile_map.h:178
StrongType::Typedef< uint32_t, struct TileIndexTag, StrongType::Compare, StrongType::Integer, StrongType::Compatible< int32_t >, StrongType::Compatible< int64_t > > TileIndex
The index/ID of a Tile.
Definition tile_type.h:92
Definition of Interval and OneShot timers.
Definition of the game-economy-timer.
Definition of the tick-based game-timer.
Definition of the Window system.
Base of the town class.
Town * ClosestTownFromTile(TileIndex tile, uint threshold)
Return the town closest (in distance or ownership) to a given tile, within a given threshold.
Base class for all vehicles.
Functions related to vehicles.
VehicleType
Available vehicle types.
@ Ship
Ship vehicle type.
@ Aircraft
Aircraft vehicle type.
@ Road
Road vehicle type.
@ Train
Train vehicle type.
void CloseConstructionWindows()
Close all windows that are used for construction of vehicle etc.
Definition window.cpp:3405
void CloseWindowById(WindowClass cls, WindowNumber number, bool force, int data)
Close a window by its class and window number (if it is open).
Definition window.cpp:1204
void InvalidateWindowData(WindowClass cls, WindowNumber number, int data, bool gui_scope)
Mark window data of the window of a given class and specific window number as invalid (in need of re-...
Definition window.cpp:3318
Window * FindWindowById(WindowClass cls, WindowNumber number)
Find a window by its class and window number.
Definition window.cpp:1161
void SetWindowWidgetDirty(WindowClass cls, WindowNumber number, WidgetID widget_index)
Mark a particular widget in a particular window as dirty (in need of repainting).
Definition window.cpp:3212
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting).
Definition window.cpp:3196
void InvalidateWindowClassesData(WindowClass cls, int data, bool gui_scope)
Mark window data of all windows of a given class as invalid (in need of re-computing) Note that by de...
Definition window.cpp:3336
Window functions not directly related to making/drawing windows.
@ Join
Network join status.
Definition window_type.h:56