OpenTTD Source 20250717-master-g55605ae8f2
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 <http://www.gnu.org/licenses/>.
6 */
7
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 "timer/timer.h"
43#include "timer/timer_window.h"
44
46
47#include "table/strings.h"
48#include "table/company_face.h"
49
50#include "safeguards.h"
51
53void UpdateObjectColours(const Company *c);
54
60
63
64
69Company::Company(StringID name_1, bool is_ai)
70{
71 this->name_1 = name_1;
72 this->is_ai = is_ai;
73 this->terraform_limit = (uint32_t)_settings_game.construction.terraform_frame_burst << 16;
74 this->clear_limit = (uint32_t)_settings_game.construction.clear_frame_burst << 16;
75 this->tree_limit = (uint32_t)_settings_game.construction.tree_frame_burst << 16;
76 this->build_object_limit = (uint32_t)_settings_game.construction.build_object_frame_burst << 16;
77
78 InvalidateWindowData(WC_PERFORMANCE_DETAIL, 0, CompanyID::Invalid());
79}
80
83{
84 if (CleaningPool()) return;
85
87}
88
93void Company::PostDestructor(size_t index)
94{
99 /* If the currently shown error message has this company in it, then close it. */
101}
102
108{
109 if (this->max_loan == COMPANY_MAX_LOAN_DEFAULT) return _economy.max_loan;
110 return this->max_loan;
111}
112
119void SetLocalCompany(CompanyID new_company)
120{
121 /* company could also be COMPANY_SPECTATOR or OWNER_NONE */
122 assert(Company::IsValidID(new_company) || new_company == COMPANY_SPECTATOR || new_company == OWNER_NONE);
123
124 /* If actually changing to another company, several windows need closing */
125 bool switching_company = _local_company != new_company;
126
127 /* Delete the chat window, if you were team chatting. */
129
130 assert(IsLocalCompany());
131
132 _current_company = _local_company = new_company;
133
134 if (switching_company) {
136 /* Delete any construction windows... */
138 }
139
140 /* ... and redraw the whole screen. */
144}
145
152{
153 if (!Company::IsValidID(company)) return (TextColour)GetColourGradient(COLOUR_WHITE, SHADE_NORMAL) | TC_IS_PALETTE_COLOUR;
154 return (TextColour)GetColourGradient(_company_colours[company], SHADE_NORMAL) | TC_IS_PALETTE_COLOUR;
155}
156
166
173void DrawCompanyIcon(CompanyID c, int x, int y)
174{
175 DrawSprite(SPR_COMPANY_ICON, GetCompanyPalette(c), x, y);
176}
177
185{
186 if (cmf.style >= GetNumCompanyManagerFaceStyles()) return false;
187
188 /* Test if each enabled part is valid. */
189 FaceVars vars = GetCompanyManagerFaceVars(cmf.style);
190 for (uint var : SetBitIterator(GetActiveFaceVars(cmf, vars))) {
191 if (!vars[var].IsValid(cmf)) return false;
192 }
193
194 return true;
195}
196
198
205{
206 CompanyID cid = company->index;
208}
209
213static const IntervalTimer<TimerWindow> invalidate_company_windows_interval(std::chrono::milliseconds(1), [](auto) {
217 if (w != nullptr) {
223 }
225 }
227});
228
237{
238 if (_settings_game.difficulty.infinite_money) return INT64_MAX;
239 if (!Company::IsValidID(company)) return INT64_MAX;
240 return Company::Get(company)->money;
241}
242
254
262{
263 if (cost.GetCost() <= 0) return true;
265
267 if (c != nullptr && cost.GetCost() > c->money) {
268 cost.MakeError(STR_ERROR_NOT_ENOUGH_CASH_REQUIRES_CURRENCY);
269 if (IsLocalCompany()) {
270 cost.SetEncodedMessage(GetEncodedString(STR_ERROR_NOT_ENOUGH_CASH_REQUIRES_CURRENCY, cost.GetCost()));
271 }
272 return false;
273 }
274 return true;
275}
276
283{
284 if (cost.GetCost() == 0) return;
285 assert(cost.GetExpensesType() != INVALID_EXPENSES);
286
287 c->money -= cost.GetCost();
288 c->yearly_expenses[0][cost.GetExpensesType()] += cost.GetCost();
289
294 c->cur_economy.income -= cost.GetCost();
295 } else if (HasBit(1 << EXPENSES_TRAIN_RUN |
298 1 << EXPENSES_SHIP_RUN |
299 1 << EXPENSES_PROPERTY |
301 c->cur_economy.expenses -= cost.GetCost();
302 }
303
305}
306
312{
314 if (c != nullptr) SubtractMoneyFromAnyCompany(c, cost);
315}
316
323{
324 Company *c = Company::Get(company);
325 uint8_t m = c->money_fraction;
326 Money cost = cst.GetCost();
327
328 c->money_fraction = m - (uint8_t)cost;
329 cost >>= 8;
330 if (c->money_fraction > m) cost++;
331 if (cost != 0) SubtractMoneyFromAnyCompany(c, CommandCost(cst.GetExpensesType(), cost));
332}
333
334static constexpr void UpdateLandscapingLimit(uint32_t &limit, uint64_t per_64k_frames, uint64_t burst)
335{
336 limit = static_cast<uint32_t>(std::min<uint64_t>(limit + per_64k_frames, burst << 16));
337}
338
349
356std::array<StringParameter, 2> GetParamsForOwnedBy(Owner owner, TileIndex tile)
357{
358 if (owner == OWNER_TOWN) {
359 assert(tile != 0);
360 const Town *t = ClosestTownFromTile(tile, UINT_MAX);
361 return {STR_TOWN_NAME, t->index};
362 }
363
364 if (!Company::IsValidID(owner)) {
365 return {STR_COMPANY_SOMEONE, std::monostate{}};
366 }
367
368 return {STR_COMPANY_NAME, owner};
369}
370
380{
381 assert(owner < OWNER_END);
382 assert(owner != OWNER_TOWN || tile != 0);
383
384 if (owner == _current_company) return CommandCost();
385
386 CommandCost error{STR_ERROR_OWNED_BY};
387 if (IsLocalCompany()) {
388 auto params = GetParamsForOwnedBy(owner, tile);
389 error.SetEncodedMessage(GetEncodedStringWithArgs(STR_ERROR_OWNED_BY, params));
390 if (owner != OWNER_TOWN) error.SetErrorOwner(owner);
391 }
392 return error;
393}
394
403{
404 return CheckOwnership(GetTileOwner(tile), tile);
405}
406
412{
413 if (c->name_1 != STR_SV_UNNAMED) return;
414 if (c->last_build_coordinate == 0) return;
415
417
418 StringID str;
419 uint32_t strp;
420 std::string name;
421 if (t->name.empty() && IsInsideMM(t->townnametype, SPECSTR_TOWNNAME_START, SPECSTR_TOWNNAME_END)) {
422 str = t->townnametype - SPECSTR_TOWNNAME_START + SPECSTR_COMPANY_NAME_START;
423 strp = t->townnameparts;
424
425verify_name:;
426 /* No companies must have this name already */
427 for (const Company *cc : Company::Iterate()) {
428 if (cc->name_1 == str && cc->name_2 == strp) goto bad_town_name;
429 }
430
431 name = GetString(str, strp);
432 if (Utf8StringLength(name) >= MAX_LENGTH_COMPANY_NAME_CHARS) goto bad_town_name;
433
434set_name:;
435 c->name_1 = str;
436 c->name_2 = strp;
437
439 AI::BroadcastNewEvent(new ScriptEventCompanyRenamed(c->index, name));
440 Game::NewEvent(new ScriptEventCompanyRenamed(c->index, name));
441
442 if (c->is_ai) {
443 auto cni = std::make_unique<CompanyNewsInformation>(STR_NEWS_COMPANY_LAUNCH_TITLE, c);
444 EncodedString headline = GetEncodedString(STR_NEWS_COMPANY_LAUNCH_DESCRIPTION, cni->company_name, t->index);
445 AddNewsItem(std::move(headline),
447 }
448 return;
449 }
450bad_town_name:;
451
453 str = SPECSTR_ANDCO_NAME;
454 strp = c->president_name_2;
455 name = GetString(str, strp);
456 goto set_name;
457 } else {
458 str = SPECSTR_ANDCO_NAME;
459 strp = Random();
460 goto verify_name;
461 }
462}
463
465static const uint8_t _colour_sort[COLOUR_END] = {2, 2, 3, 2, 3, 2, 3, 2, 3, 2, 2, 2, 3, 1, 1, 1};
467static const Colours _similar_colour[COLOUR_END][2] = {
468 { COLOUR_BLUE, COLOUR_LIGHT_BLUE }, // COLOUR_DARK_BLUE
469 { COLOUR_GREEN, COLOUR_DARK_GREEN }, // COLOUR_PALE_GREEN
470 { INVALID_COLOUR, INVALID_COLOUR }, // COLOUR_PINK
471 { COLOUR_ORANGE, INVALID_COLOUR }, // COLOUR_YELLOW
472 { INVALID_COLOUR, INVALID_COLOUR }, // COLOUR_RED
473 { COLOUR_DARK_BLUE, COLOUR_BLUE }, // COLOUR_LIGHT_BLUE
474 { COLOUR_PALE_GREEN, COLOUR_DARK_GREEN }, // COLOUR_GREEN
475 { COLOUR_PALE_GREEN, COLOUR_GREEN }, // COLOUR_DARK_GREEN
476 { COLOUR_DARK_BLUE, COLOUR_LIGHT_BLUE }, // COLOUR_BLUE
477 { COLOUR_BROWN, COLOUR_ORANGE }, // COLOUR_CREAM
478 { COLOUR_PURPLE, INVALID_COLOUR }, // COLOUR_MAUVE
479 { COLOUR_MAUVE, INVALID_COLOUR }, // COLOUR_PURPLE
480 { COLOUR_YELLOW, COLOUR_CREAM }, // COLOUR_ORANGE
481 { COLOUR_CREAM, INVALID_COLOUR }, // COLOUR_BROWN
482 { COLOUR_WHITE, INVALID_COLOUR }, // COLOUR_GREY
483 { COLOUR_GREY, INVALID_COLOUR }, // COLOUR_WHITE
484};
485
490static Colours GenerateCompanyColour()
491{
492 Colours colours[COLOUR_END];
493
494 /* Initialize array */
495 for (uint i = 0; i < COLOUR_END; i++) colours[i] = static_cast<Colours>(i);
496
497 /* And randomize it */
498 for (uint i = 0; i < 100; i++) {
499 uint r = Random();
500 std::swap(colours[GB(r, 0, 4)], colours[GB(r, 4, 4)]);
501 }
502
503 /* Bubble sort it according to the values in table 1 */
504 for (uint i = 0; i < COLOUR_END; i++) {
505 for (uint j = 1; j < COLOUR_END; j++) {
506 if (_colour_sort[colours[j - 1]] < _colour_sort[colours[j]]) {
507 std::swap(colours[j - 1], colours[j]);
508 }
509 }
510 }
511
512 /* Move the colours that look similar to each company's colour to the side */
513 for (const Company *c : Company::Iterate()) {
514 Colours pcolour = c->colour;
515
516 for (uint i = 0; i < COLOUR_END; i++) {
517 if (colours[i] == pcolour) {
518 colours[i] = INVALID_COLOUR;
519 break;
520 }
521 }
522
523 for (uint j = 0; j < 2; j++) {
524 Colours similar = _similar_colour[pcolour][j];
525 if (similar == INVALID_COLOUR) break;
526
527 for (uint i = 1; i < COLOUR_END; i++) {
528 if (colours[i - 1] == similar) std::swap(colours[i - 1], colours[i]);
529 }
530 }
531 }
532
533 /* Return the first available colour */
534 for (uint i = 0; i < COLOUR_END; i++) {
535 if (colours[i] != INVALID_COLOUR) return colours[i];
536 }
537
538 NOT_REACHED();
539}
540
546{
547 for (;;) {
548restart:;
551
552 /* Reserve space for extra unicode character. We need to do this to be able
553 * to detect too long president name. */
554 std::string name = GetString(STR_PRESIDENT_NAME, c->index);
556
557 for (const Company *cc : Company::Iterate()) {
558 if (c != cc) {
559 std::string other_name = GetString(STR_PRESIDENT_NAME, cc->index);
560 if (name == other_name) goto restart;
561 }
562 }
563 return;
564 }
565}
566
573{
574 for (LiveryScheme scheme = LS_BEGIN; scheme < LS_END; scheme++) {
575 c->livery[scheme].in_use = 0;
576 c->livery[scheme].colour1 = c->colour;
577 c->livery[scheme].colour2 = c->colour;
578 }
579
580 for (Group *g : Group::Iterate()) {
581 if (g->owner == c->index) {
582 g->livery.in_use = 0;
583 g->livery.colour1 = c->colour;
584 g->livery.colour2 = c->colour;
585 }
586 }
587}
588
596Company *DoStartupNewCompany(bool is_ai, CompanyID company = CompanyID::Invalid())
597{
598 if (!Company::CanAllocateItem()) return nullptr;
599
600 /* we have to generate colour before this company is valid */
601 Colours colour = GenerateCompanyColour();
602
603 Company *c;
604 if (company == CompanyID::Invalid()) {
605 c = new Company(STR_SV_UNNAMED, is_ai);
606 } else {
607 if (Company::IsValidID(company)) return nullptr;
608 c = new (company) Company(STR_SV_UNNAMED, is_ai);
609 }
610
611 c->colour = colour;
612
615
616 /* Scale the initial loan based on the inflation rounded down to the loan interval. The maximum loan has already been inflation adjusted. */
617 c->money = c->current_loan = std::min<int64_t>((INITIAL_LOAN * _economy.inflation_prices >> 16) / LOAN_INTERVAL * LOAN_INTERVAL, _economy.max_loan);
618
623
624 /* If starting a player company in singleplayer and a favorite company manager face is selected, choose it. Otherwise, use a random face.
625 * In a network game, we'll choose the favorite face later in CmdCompanyCtrl to sync it to all clients. */
626 bool randomise_face = true;
627 if (!_company_manager_face.empty() && !is_ai && !_networking) {
629 if (cmf.has_value()) {
630 randomise_face = false;
631 c->face = std::move(*cmf);
632 }
633 }
634 if (randomise_face) RandomiseCompanyManagerFace(c->face, _random);
635
638
640
646
647 if (is_ai && (!_networking || _network_server)) AI::StartNew(c->index);
648
649 AI::BroadcastNewEvent(new ScriptEventCompanyNew(c->index), c->index);
650 Game::NewEvent(new ScriptEventCompanyNew(c->index));
651
652 return c;
653}
654
656TimeoutTimer<TimerGameTick> _new_competitor_timeout({ TimerGameTick::Priority::COMPETITOR_TIMEOUT, 0 }, []() {
657 if (_game_mode == GM_MENU || !AI::CanStartNew()) return;
660
661 /* count number of competitors */
662 uint8_t n = 0;
663 for (const Company *c : Company::Iterate()) {
664 if (c->is_ai) n++;
665 }
666
668
669 /* Send a command to all clients to start up a new AI.
670 * Works fine for Multiplayer and Singleplayer */
672});
673
676{
677 /* Ensure the timeout is aborted, so it doesn't fire based on information of the last game. */
679}
680
686
694{
695 const Company *c1 = Company::Get(cbig);
696 const Company *c2 = Company::Get(csmall);
697
698 /* Do the combined vehicle counts stay within the limits? */
699 return c1->group_all[VEH_TRAIN].num_vehicle + c2->group_all[VEH_TRAIN].num_vehicle <= _settings_game.vehicle.max_trains &&
700 c1->group_all[VEH_ROAD].num_vehicle + c2->group_all[VEH_ROAD].num_vehicle <= _settings_game.vehicle.max_roadveh &&
701 c1->group_all[VEH_SHIP].num_vehicle + c2->group_all[VEH_SHIP].num_vehicle <= _settings_game.vehicle.max_ships &&
702 c1->group_all[VEH_AIRCRAFT].num_vehicle + c2->group_all[VEH_AIRCRAFT].num_vehicle <= _settings_game.vehicle.max_aircraft;
703}
704
715{
716 /* Amount of time out for each company to take over a company;
717 * Timeout is a quarter (3 months of 30 days) divided over the
718 * number of companies. The minimum number of days in a quarter
719 * is 90: 31 in January, 28 in February and 31 in March.
720 * Note that the company going bankrupt can't buy itself. */
721 static const int TAKE_OVER_TIMEOUT = 3 * 30 * Ticks::DAY_TICKS / (MAX_COMPANIES - 1);
722
723 assert(c->bankrupt_asked.Any());
724
725 /* We're currently asking some company to buy 'us' */
726 if (c->bankrupt_timeout != 0) {
727 c->bankrupt_timeout -= MAX_COMPANIES;
728 if (c->bankrupt_timeout > 0) return;
729 c->bankrupt_timeout = 0;
730
731 return;
732 }
733
734 /* Did we ask everyone for bankruptcy? If so, bail out. */
735 if (c->bankrupt_asked.All()) return;
736
737 Company *best = nullptr;
738 int32_t best_performance = -1;
739
740 /* Ask the company with the highest performance history first */
741 for (Company *c2 : Company::Iterate()) {
742 if (c2->bankrupt_asked.None() && // Don't ask companies going bankrupt themselves
743 !c->bankrupt_asked.Test(c2->index) &&
744 best_performance < c2->old_economy[1].performance_history &&
745 CheckTakeoverVehicleLimit(c2->index, c->index)) {
746 best_performance = c2->old_economy[1].performance_history;
747 best = c2;
748 }
749 }
750
751 /* Asked all companies? */
752 if (best_performance == -1) {
753 c->bankrupt_asked.Set();
754 return;
755 }
756
757 c->bankrupt_asked.Set(best->index);
758
759 c->bankrupt_timeout = TAKE_OVER_TIMEOUT;
760
761 AI::NewEvent(best->index, new ScriptEventCompanyAskMerger(c->index, c->bankrupt_value));
762 if (IsInteractiveCompany(best->index)) {
763 ShowBuyCompanyDialog(c->index, false);
764 }
765}
766
769{
770 if (_game_mode == GM_EDITOR) return;
771
773 if (c != nullptr) {
774 if (c->name_1 != 0) GenerateCompanyName(c);
776 }
777
778 if (_new_competitor_timeout.HasFired() && _game_mode != GM_MENU && AI::CanStartNew()) {
780 /* If the interval is zero, start as many competitors as needed then check every ~10 minutes if a company went bankrupt and needs replacing. */
781 if (timeout == 0) {
782 /* count number of competitors */
783 uint8_t num_ais = 0;
784 for (const Company *cc : Company::Iterate()) {
785 if (cc->is_ai) num_ais++;
786 }
787
788 size_t num_companies = Company::GetNumItems();
789 for (auto i = 0; i < _settings_game.difficulty.max_no_competitors; i++) {
790 if (_networking && num_companies++ >= _settings_client.network.max_companies) break;
791 if (num_ais++ >= _settings_game.difficulty.max_no_competitors) break;
793 }
794 timeout = 10 * 60 * Ticks::TICKS_PER_SECOND;
795 }
796 /* Randomize a bit when the AI is actually going to start; ranges from 87.5% .. 112.5% of indicated value. */
797 timeout += ScriptObject::GetRandomizer(OWNER_NONE).Next(timeout / 4) - timeout / 8;
798
799 _new_competitor_timeout.Reset({ TimerGameTick::Priority::COMPETITOR_TIMEOUT, static_cast<uint>(std::max(1, timeout)) });
800 }
801
802 _cur_company_tick_index = (_cur_company_tick_index + 1) % MAX_COMPANIES;
803}
804
809static const IntervalTimer<TimerGameEconomy> _economy_companies_yearly({TimerGameEconomy::YEAR, TimerGameEconomy::Priority::COMPANY}, [](auto)
810{
811 /* Copy statistics */
812 for (Company *c : Company::Iterate()) {
813 /* Move expenses to previous years. */
814 std::rotate(std::rbegin(c->yearly_expenses), std::rbegin(c->yearly_expenses) + 1, std::rend(c->yearly_expenses));
815 c->yearly_expenses[0].fill(0);
817 }
818
822 if (c->num_valid_stat_ent > 5 && c->old_economy[0].performance_history < c->old_economy[4].performance_history) {
824 } else {
826 }
827 }
828});
829
836{
837 this->company_name = GetString(STR_COMPANY_NAME, c->index);
838
839 if (other != nullptr) {
840 this->other_company_name = GetString(STR_COMPANY_NAME, other->index);
841 c = other;
842 }
843
844 this->president_name = GetString(STR_PRESIDENT_NAME_MANAGER, c->index);
845
846 this->title = title;
847 this->colour = c->colour;
848 this->face = c->face;
849
850}
851
856void CompanyAdminUpdate(const Company *company)
857{
859}
860
870
880{
882
883 switch (cca) {
884 case CCA_NEW: { // Create a new company
885 /* This command is only executed in a multiplayer game */
886 if (!_networking) return CMD_ERROR;
887
888 /* Has the network client a correct ClientID? */
889 if (!flags.Test(DoCommandFlag::Execute)) return CommandCost();
890
892
893 /* Delete multiplayer progress bar */
895
896 Company *c = DoStartupNewCompany(false);
897
898 /* A new company could not be created, revert to being a spectator */
899 if (c == nullptr) {
900 /* We check for "ci != nullptr" as a client could have left by
901 * the time we execute this command. */
902 if (_network_server && ci != nullptr) {
905 }
906 break;
907 }
908
911
912 /* This is the client (or non-dedicated server) who wants a new company */
913 if (client_id == _network_own_client_id) {
916
917 /*
918 * If a favorite company manager face is selected, choose it. Otherwise, use a random face.
919 * Because this needs to be synchronised over the network, only the client knows
920 * its configuration and we are currently in the execution of a command, we have
921 * to circumvent the normal ::Post logic for commands and just send the command.
922 */
923 if (!_company_manager_face.empty()) {
925 if (cmf.has_value()) {
926 Command<CMD_SET_COMPANY_MANAGER_FACE>::SendNet(STR_NULL, c->index, cmf->bits, cmf->style);
927 }
928 }
929
930 /* Now that we have a new company, broadcast our company settings to
931 * all clients so everything is in sync */
933
935 }
936 break;
937 }
938
939 case CCA_NEW_AI: { // Make a new AI company
940 if (company_id != CompanyID::Invalid() && company_id >= MAX_COMPANIES) return CMD_ERROR;
941
942 /* For network games, company deletion is delayed. */
943 if (!_networking && company_id != CompanyID::Invalid() && Company::IsValidID(company_id)) return CMD_ERROR;
944
945 if (!flags.Test(DoCommandFlag::Execute)) return CommandCost();
946
947 /* For network game, just assume deletion happened. */
948 assert(company_id == CompanyID::Invalid() || !Company::IsValidID(company_id));
949
950 Company *c = DoStartupNewCompany(true, company_id);
951 if (c != nullptr) {
953 NetworkServerNewCompany(c, nullptr);
954 }
955 break;
956 }
957
958 case CCA_DELETE: { // Delete a company
959 if (reason >= CRR_END) return CMD_ERROR;
960
961 /* We can't delete the last existing company in singleplayer mode. */
962 if (!_networking && Company::GetNumItems() == 1) return CMD_ERROR;
963
964 Company *c = Company::GetIfValid(company_id);
965 if (c == nullptr) return CMD_ERROR;
966
967 if (!flags.Test(DoCommandFlag::Execute)) return CommandCost();
968
969 /* Show the bankrupt news */
970 auto cni = std::make_unique<CompanyNewsInformation>(STR_NEWS_COMPANY_BANKRUPT_TITLE, c);
971 EncodedString headline = GetEncodedString(STR_NEWS_COMPANY_BANKRUPT_DESCRIPTION, cni->company_name);
972 AddCompanyNewsItem(std::move(headline), std::move(cni));
973
974 /* Remove the company */
976 if (c->is_ai) AI::Stop(c->index);
977
978 CompanyID c_index = c->index;
979 delete c;
980 AI::BroadcastNewEvent(new ScriptEventCompanyBankrupt(c_index));
981 Game::NewEvent(new ScriptEventCompanyBankrupt(c_index));
982 CompanyAdminRemove(c_index, (CompanyRemoveReason)reason);
983
986
987 break;
988 }
989
990 default: return CMD_ERROR;
991 }
992
996
997 return CommandCost();
998}
999
1000static bool ExecuteAllowListCtrlAction(CompanyAllowListCtrlAction action, Company *c, const std::string &public_key)
1001{
1002 switch (action) {
1003 case CALCA_ADD:
1004 return c->allow_list.Add(public_key);
1005
1006 case CALCA_REMOVE:
1007 return c->allow_list.Remove(public_key);
1008
1009 default:
1010 NOT_REACHED();
1011 }
1012}
1013
1022{
1024 if (c == nullptr) return CMD_ERROR;
1025
1026 /* The public key length includes the '\0'. */
1027 if (public_key.size() != NETWORK_PUBLIC_KEY_LENGTH - 1) return CMD_ERROR;
1028
1029 switch (action) {
1030 case CALCA_ADD:
1031 case CALCA_REMOVE:
1032 break;
1033
1034 default:
1035 return CMD_ERROR;
1036 }
1037
1038 if (flags.Test(DoCommandFlag::Execute)) {
1039 if (ExecuteAllowListCtrlAction(action, c, public_key)) {
1042 }
1043 }
1044
1045 return CommandCost();
1046}
1047
1055CommandCost CmdSetCompanyManagerFace(DoCommandFlags flags, uint32_t bits, uint style)
1056{
1057 CompanyManagerFace tmp_face{style, bits, {}};
1058 if (!IsValidCompanyManagerFace(tmp_face)) return CMD_ERROR;
1059
1060 if (flags.Test(DoCommandFlag::Execute)) {
1062 SetCompanyManagerFaceStyle(cmf, style);
1063 cmf.bits = tmp_face.bits;
1064
1066 }
1067 return CommandCost();
1068}
1069
1076{
1077 for (int i = 1; i < LS_END; i++) {
1078 if (!HasBit(c->livery[i].in_use, 0)) c->livery[i].colour1 = c->livery[LS_DEFAULT].colour1;
1079 if (!HasBit(c->livery[i].in_use, 1)) c->livery[i].colour2 = c->livery[LS_DEFAULT].colour2;
1080 }
1082}
1083
1092CommandCost CmdSetCompanyColour(DoCommandFlags flags, LiveryScheme scheme, bool primary, Colours colour)
1093{
1094 if (scheme >= LS_END || (colour >= COLOUR_END && colour != INVALID_COLOUR)) return CMD_ERROR;
1095
1096 /* Default scheme can't be reset to invalid. */
1097 if (scheme == LS_DEFAULT && colour == INVALID_COLOUR) return CMD_ERROR;
1098
1100
1101 /* Ensure no two companies have the same primary colour */
1102 if (scheme == LS_DEFAULT && primary) {
1103 for (const Company *cc : Company::Iterate()) {
1104 if (cc != c && cc->colour == colour) return CMD_ERROR;
1105 }
1106 }
1107
1108 if (flags.Test(DoCommandFlag::Execute)) {
1109 if (primary) {
1110 if (scheme != LS_DEFAULT) AssignBit(c->livery[scheme].in_use, 0, colour != INVALID_COLOUR);
1111 if (colour == INVALID_COLOUR) colour = c->livery[LS_DEFAULT].colour1;
1112 c->livery[scheme].colour1 = colour;
1113
1114 /* If setting the first colour of the default scheme, adjust the
1115 * original and cached company colours too. */
1116 if (scheme == LS_DEFAULT) {
1119 c->colour = colour;
1121 }
1122 } else {
1123 if (scheme != LS_DEFAULT) AssignBit(c->livery[scheme].in_use, 1, colour != INVALID_COLOUR);
1124 if (colour == INVALID_COLOUR) colour = c->livery[LS_DEFAULT].colour2;
1125 c->livery[scheme].colour2 = colour;
1126
1127 if (scheme == LS_DEFAULT) {
1129 }
1130 }
1131
1132 if (c->livery[scheme].in_use != 0) {
1133 /* If enabling a scheme, set the default scheme to be in use too */
1134 c->livery[LS_DEFAULT].in_use = 1;
1135 } else {
1136 /* Else loop through all schemes to see if any are left enabled.
1137 * If not, disable the default scheme too. */
1138 c->livery[LS_DEFAULT].in_use = 0;
1139 for (scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
1140 if (c->livery[scheme].in_use != 0) {
1141 c->livery[LS_DEFAULT].in_use = 1;
1142 break;
1143 }
1144 }
1145 }
1146
1147 ResetVehicleColourMap();
1149
1150 /* All graph related to companies use the company colour. */
1157 /* The smallmap owner view also stores the company colours. */
1160
1161 /* Company colour data is indirectly cached. */
1162 for (Vehicle *v : Vehicle::Iterate()) {
1163 if (v->owner == _current_company) v->InvalidateNewGRFCache();
1164 }
1165
1167 }
1168 return CommandCost();
1169}
1170
1176static bool IsUniqueCompanyName(const std::string &name)
1177{
1178 for (const Company *c : Company::Iterate()) {
1179 if (!c->name.empty() && c->name == name) return false;
1180 }
1181
1182 return true;
1183}
1184
1191CommandCost CmdRenameCompany(DoCommandFlags flags, const std::string &text)
1192{
1193 bool reset = text.empty();
1194
1195 if (!reset) {
1197 if (!IsUniqueCompanyName(text)) return CommandCost(STR_ERROR_NAME_MUST_BE_UNIQUE);
1198 }
1199
1200 if (flags.Test(DoCommandFlag::Execute)) {
1202 if (reset) {
1203 c->name.clear();
1204 } else {
1205 c->name = text;
1206 }
1209
1210 std::string new_name = GetString(STR_COMPANY_NAME, c->index);
1211 AI::BroadcastNewEvent(new ScriptEventCompanyRenamed(c->index, new_name));
1212 Game::NewEvent(new ScriptEventCompanyRenamed(c->index, new_name));
1213 }
1214
1215 return CommandCost();
1216}
1217
1223static bool IsUniquePresidentName(const std::string &name)
1224{
1225 for (const Company *c : Company::Iterate()) {
1226 if (!c->president_name.empty() && c->president_name == name) return false;
1227 }
1228
1229 return true;
1230}
1231
1238CommandCost CmdRenamePresident(DoCommandFlags flags, const std::string &text)
1239{
1240 bool reset = text.empty();
1241
1242 if (!reset) {
1244 if (!IsUniquePresidentName(text)) return CommandCost(STR_ERROR_NAME_MUST_BE_UNIQUE);
1245 }
1246
1247 if (flags.Test(DoCommandFlag::Execute)) {
1249
1250 if (reset) {
1251 c->president_name.clear();
1252 } else {
1253 c->president_name = text;
1254
1255 if (c->name_1 == STR_SV_UNNAMED && c->name.empty()) {
1257 }
1258 }
1259
1263
1264 std::string new_name = GetString(STR_PRESIDENT_NAME, c->index);
1265 AI::BroadcastNewEvent(new ScriptEventPresidentRenamed(c->index, new_name));
1266 Game::NewEvent(new ScriptEventPresidentRenamed(c->index, new_name));
1267 }
1268
1269 return CommandCost();
1270}
1271
1279{
1280 const VehicleDefaultSettings *vds = (c == nullptr) ? &_settings_client.company.vehicle : &c->settings.vehicle;
1281 switch (type) {
1282 default: NOT_REACHED();
1283 case VEH_TRAIN: return vds->servint_trains;
1284 case VEH_ROAD: return vds->servint_roadveh;
1285 case VEH_AIRCRAFT: return vds->servint_aircraft;
1286 case VEH_SHIP: return vds->servint_ships;
1287 }
1288}
1289
1295{
1296 uint32_t total = 0;
1297 for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) {
1298 if (RoadTypeIsRoad(rt)) total += this->road[rt];
1299 }
1300 return total;
1301}
1302
1308{
1309 uint32_t total = 0;
1310 for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) {
1311 if (RoadTypeIsTram(rt)) total += this->road[rt];
1312 }
1313 return total;
1314}
1315
1327{
1329
1331 CommandCost amount(EXPENSES_OTHER, std::min<Money>(money, 20000000LL));
1332
1333 /* You can only transfer funds that is in excess of your loan */
1334 if (c->money - c->current_loan < amount.GetCost() || amount.GetCost() < 0) return CommandCost(STR_ERROR_INSUFFICIENT_FUNDS);
1335 if (!Company::IsValidID(dest_company)) return CMD_ERROR;
1336
1337 if (flags.Test(DoCommandFlag::Execute)) {
1338 /* Add money to company */
1339 Backup<CompanyID> cur_company(_current_company, dest_company);
1341 cur_company.Restore();
1342
1343 if (_networking) {
1344 std::string dest_company_name = GetString(STR_COMPANY_NAME, dest_company);
1345 std::string from_company_name = GetString(STR_COMPANY_NAME, _current_company);
1346
1347 NetworkTextMessage(NETWORK_ACTION_GIVE_MONEY, GetDrawStringCompanyColour(_current_company), false, from_company_name, dest_company_name, amount.GetCost());
1348 }
1349 }
1350
1351 /* Subtract money from local-company */
1352 return amount;
1353}
1354
1365{
1366 for (Company *c : Company::Iterate()) {
1367 if (Company::IsHumanID(c->index)) {
1368 return c->index;
1369 }
1370 }
1371
1373 for (CompanyID c = CompanyID::Begin(); c < MAX_COMPANIES; ++c) {
1374 if (!Company::IsValidID(c)) {
1375 return c;
1376 }
1377 }
1378 }
1379
1380 return CompanyID::Begin();
1381}
1382
1383static std::vector<FaceSpec> _faces;
1384
1389{
1390 _faces.clear();
1391 _faces.assign(std::begin(_original_faces), std::end(_original_faces));
1392}
1393
1399{
1400 return static_cast<uint>(std::size(_faces));
1401}
1402
1408const FaceSpec *GetCompanyManagerFaceSpec(uint style_index)
1409{
1410 if (style_index < GetNumCompanyManagerFaceStyles()) return &_faces[style_index];
1411 return nullptr;
1412}
1413
1419std::optional<uint> FindCompanyManagerFaceLabel(std::string_view label)
1420{
1421 auto it = std::ranges::find(_faces, label, &FaceSpec::label);
1422 if (it == std::end(_faces)) return std::nullopt;
1423
1424 return static_cast<uint>(std::distance(std::begin(_faces), it));
1425}
1426
1432FaceVars GetCompanyManagerFaceVars(uint style)
1433{
1434 const FaceSpec *spec = GetCompanyManagerFaceSpec(style);
1435 if (spec == nullptr) return {};
1436 return spec->GetFaceVars();
1437}
1438
1446{
1447 const FaceSpec *spec = GetCompanyManagerFaceSpec(style);
1448 assert(spec != nullptr);
1449
1450 cmf.style = style;
1451 cmf.style_label = spec->label;
1452}
1453
1465
1473uint32_t MaskCompanyManagerFaceBits(const CompanyManagerFace &cmf, FaceVars vars)
1474{
1475 CompanyManagerFace face{};
1476
1477 for (auto var : SetBitIterator(GetActiveFaceVars(cmf, vars))) {
1478 vars[var].SetBits(face, vars[var].GetBits(cmf));
1479 }
1480
1481 return face.bits;
1482}
1483
1490{
1491 uint32_t masked_face_bits = MaskCompanyManagerFaceBits(cmf, GetCompanyManagerFaceVars(cmf.style));
1492 return fmt::format("{}:{}", cmf.style_label, masked_face_bits);
1493}
1494
1500std::optional<CompanyManagerFace> ParseCompanyManagerFaceCode(std::string_view str)
1501{
1502 if (str.empty()) return std::nullopt;
1503
1505 StringConsumer consumer{str};
1506 if (consumer.FindChar(':') != StringConsumer::npos) {
1507 auto label = consumer.ReadUntilChar(':', StringConsumer::SKIP_ONE_SEPARATOR);
1508
1509 /* Read numeric part and ensure it's valid. */
1510 auto bits = consumer.TryReadIntegerBase<uint32_t>(10, true);
1511 if (!bits.has_value() || consumer.AnyBytesLeft()) return std::nullopt;
1512
1513 /* Ensure style laberl is valid. */
1514 auto style = FindCompanyManagerFaceLabel(label);
1515 if (!style.has_value()) return std::nullopt;
1516
1517 SetCompanyManagerFaceStyle(cmf, *style);
1518 cmf.bits = *bits;
1519 } else {
1520 /* No ':' included, treat as numeric-only. This allows old-style codes to be entered. */
1521 auto bits = ParseInteger(str, 10, true);
1522 if (!bits.has_value()) return std::nullopt;
1523
1524 /* Old codes use bits 0..1 to represent face style. These map directly to the default face styles. */
1525 SetCompanyManagerFaceStyle(cmf, GB(*bits, 0, 2));
1526 cmf.bits = *bits;
1527 }
1528
1529 /* Force the face bits to be valid. */
1530 FaceVars vars = GetCompanyManagerFaceVars(cmf.style);
1532 cmf.bits = MaskCompanyManagerFaceBits(cmf, vars);
1533
1534 return cmf;
1535}
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.
debug_inline constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
constexpr T AssignBit(T &x, const uint8_t y, bool value)
Assigns a bit in a variable.
debug_inline 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:255
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:107
static void NewEvent(CompanyID company, ScriptEvent *event)
Queue a new event for an AI.
Definition ai_core.cpp:235
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 & Reset()
Reset all bits.
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.
Container for an encoded string, created by GetEncodedString.
Enum-as-bit-set wrapper.
static void NewEvent(class ScriptEvent *event)
Queue a new event for a 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::string_view ReadUntilChar(char c, SeparatorUsage sep)
Read data until the first occurrence of 8-bit char 'c', and advance reader.
@ SKIP_ONE_SEPARATOR
Read and discard one separator, do not include it in the result.
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
void Abort()
Abort the timer so it doesn't fire if it hasn't yet.
Definition timer.h:161
static Year year
Current year, starting at 0.
static Year year
Current year, starting at 0.
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
Definition of stuff that is very close to a company, like the company struct itself.
void ClearEnginesHiddenFlagOfCompany(CompanyID cid)
Clear the 'hidden' flag for all engines of a new company.
Definition engine.cpp:1005
void UpdateObjectColours(const Company *c)
Updates the colour of the object whenever a company changes.
TimeoutTimer< TimerGameTick > _new_competitor_timeout({ TimerGameTick::Priority::COMPETITOR_TIMEOUT, 0 }, []() { if(_game_mode==GM_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< CMD_COMPANY_CTRL >::Post(CCA_NEW_AI, CompanyID::Invalid(), CRR_NONE, INVALID_CLIENT_ID);})
Start a new competitor company if possible.
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.
static void SubtractMoneyFromAnyCompany(Company *c, const CommandCost &cost)
Deduct costs of a command from the money of a company.
std::array< StringParameter, 2 > GetParamsForOwnedBy(Owner owner, TileIndex tile)
Set the right DParams 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.
CommandCost CmdSetCompanyManagerFace(DoCommandFlags flags, uint32_t bits, uint style)
Change the company manager's face.
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.
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.
static const Colours _similar_colour[COLOUR_END][2]
Similar colours, so we can try to prevent same coloured companies.
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.
CompanyID GetFirstPlayableCompanyID()
Get the index of the first available company.
static CompanyMask _dirty_company_finances
Bitmask of compamy finances that should be marked dirty.
TextColour GetDrawStringCompanyColour(CompanyID company)
Get the colour for DrawString-subroutines which matches the colour of the company.
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.
CommandCost CmdRenamePresident(DoCommandFlags flags, const std::string &text)
Change the name of the president.
void SubtractMoneyFromCompany(const CommandCost &cost)
Subtract money from the _current_company, if the company is valid.
CompanyPool _company_pool("Company")
Pool of companies.
static const IntervalTimer< TimerGameEconomy > _economy_companies_yearly({TimerGameEconomy::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(WC_FINANCES, c->index);} if(_settings_client.gui.show_finances &&_local_company !=COMPANY_SPECTATOR) { ShowCompanyFinances(_local_company);Company *c=Company::Get(_local_company);if(c->num_valid_stat_ent > 5 &&c->old_economy[0].performance_history< c->old_economy[4].performance_history) { if(_settings_client.sound.new_year) SndPlayFx(SND_01_BAD_YEAR);} else { if(_settings_client.sound.new_year) SndPlayFx(SND_00_GOOD_YEAR);} } })
A year has passed, update the economic data of all companies, and perhaps show the financial overview...
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.
uint _cur_company_tick_index
used to generate a name for one company that doesn't have a name yet per tick
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?
void SetLocalCompany(CompanyID new_company)
Sets the local company and updates the settings that are set on a per-company basis to reflect the co...
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 void HandleBankruptcyTakeover(Company *c)
Handle the bankruptcy take over of a 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 const IntervalTimer< TimerWindow > invalidate_company_windows_interval(std::chrono::milliseconds(1), [](auto) { for(CompanyID cid :_dirty_company_finances) { if(cid==_local_company) SetWindowWidgetDirty(WC_STATUS_BAR, 0, WID_S_RIGHT);Window *w=FindWindowById(WC_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(WC_COMPANY, cid, WID_C_DESC_COMPANY_VALUE);} _dirty_company_finances.Reset();})
Refresh all company finance windows previously marked dirty.
static const uint8_t _colour_sort[COLOUR_END]
Sorting weights for the company colours.
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:322
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:1210
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 CMD_COMPANY_CTRL.
@ CCA_NEW_AI
Create a new AI company.
@ CCA_DELETE
Delete a company.
@ CCA_NEW
Create a new company.
static constexpr CompanyID COMPANY_SPECTATOR
The client is spectating.
static constexpr Owner OWNER_END
Last + 1 owner.
CompanyAllowListCtrlAction
The action to do with CMD_COMPANY_ALLOW_LIST_CTRL.
@ CALCA_REMOVE
Remove a public key.
@ CALCA_ADD
Create a public 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.
@ CRR_END
Sentinel for end.
@ CRR_NONE
Dummy reason for actions that don't need one.
@ 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.
static const uint NETWORK_PUBLIC_KEY_LENGTH
The maximum length of the hexadecimal encoded public keys, in bytes including '\0'.
Definition config.h:101
@ EXPENSES_ROADVEH_RUN
Running costs road vehicles.
@ EXPENSES_TRAIN_RUN
Running costs trains.
@ EXPENSES_AIRCRAFT_REVENUE
Revenue from aircraft.
@ EXPENSES_AIRCRAFT_RUN
Running costs aircraft.
@ EXPENSES_ROADVEH_REVENUE
Revenue from road vehicles.
@ EXPENSES_PROPERTY
Property costs.
@ EXPENSES_OTHER
Other expenses.
@ EXPENSES_SHIP_REVENUE
Revenue from ships.
@ EXPENSES_LOAN_INTEREST
Interest payments over the loan.
@ EXPENSES_TRAIN_REVENUE
Revenue from trains.
@ EXPENSES_SHIP_RUN
Running costs ships.
@ INVALID_EXPENSES
Invalid expense type.
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!
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:1024
uint32_t PaletteID
The number of the palette.
Definition gfx_type.h:18
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
Definition gfx_type.h:302
@ TC_IS_PALETTE_COLOUR
Colour value is already a real palette colour index, not an index of a StringColour.
Definition gfx_type.h:325
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:1535
@ Random
Randomise borders.
LiveryScheme
List of different livery schemes.
Definition livery.h:21
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
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.
@ DESTTYPE_TEAM
Send message/notice to everyone playing the same company (Team)
ClientID
'Unique' identifier to be given to clients
@ INVALID_CLIENT_ID
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:902
@ CompanyInfo
Company info (new companies, bankruptcy messages)
@ Company
Company news item. (Newspaper with face)
uint8_t GetColourGradient(Colours colour, ColourShade shade)
Get colour gradient palette index.
Definition palette.cpp:388
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:253
Rail specific functions.
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:198
RoadType
The different roadtypes we support.
Definition road_type.h:23
@ ROADTYPE_END
Used for iterations.
Definition road_type.h:27
@ ROADTYPE_BEGIN
Used for iterations.
Definition road_type.h:24
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:87
@ SND_00_GOOD_YEAR
39 == 0x27 New year: performance improved
Definition sound_type.h:86
static PaletteID GetColourPalette(Colours colour)
Get recolour palette for a colour.
Definition sprite.h:184
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:347
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:103
EncodedString GetEncodedString(StringID str)
Encode a string with no parameters into an encoded string.
Definition strings.cpp:91
std::string GetString(StringID string)
Resolve the given StringID into a std::string with formatting but no parameters.
Definition strings.cpp:425
Functions related to OTTD's strings.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
static constexpr StringID SPECSTR_COMPANY_NAME_START
Special strings for company names on the form "TownName transport".
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.
static constexpr StringID SPECSTR_TOWNNAME_START
Special strings for town names.
Class to backup a specific variable and restore it later.
void Restore()
Restore the variable.
CompanySettings company
default values for per-company settings
NetworkSettings network
settings related to the network
SoundSettings sound
sound effect settings
GUISettings gui
settings related to the GUI
Money income
The amount of income.
Money expenses
The amount of expenses.
std::array< uint32_t, ROADTYPE_END > road
Count of company owned track bits for each road type.
uint32_t GetRoadTotal() const
Get total sum of all owned road bits.
uint32_t GetTramTotal() const
Get total sum of all owned tram bits.
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:168
Colours colour
The colour related to the company.
Definition news_type.h:169
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:164
std::string company_name
The name of the company.
Definition news_type.h:163
std::string other_company_name
The name of the company taking over this one.
Definition news_type.h:165
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.
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...
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.
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.
static bool IsHumanID(auto index)
Is this company a company not controlled by a NoAI program?
std::array< GroupStatistics, VEH_COMPANY_END > group_all
NOSAVE: Statistics for the ALL_GROUP group.
RoadTypes avail_roadtypes
Road types available to this company.
~Company()
Destructor.
RailTypes avail_railtypes
Rail types available to this company.
static void PostDestructor(size_t index)
Invalidating some stuff after removing item from the pool.
uint32_t clear_per_64k_frames
how many tiles may, over a long period, be cleared per 65536 frames?
uint32_t tree_per_64k_frames
how many trees may, over a long period, be planted per 65536 frames?
uint16_t terraform_frame_burst
how many tile heights may, over a short period, be terraformed?
uint16_t tree_frame_burst
how many trees may, over a short period, be planted?
uint16_t build_object_frame_burst
how many tiles may, over a short period, be purchased or have objects built on them?
uint32_t build_object_per_64k_frames
how many tiles may, over a long period, be purchased or have objects built on them per 65536 frames?
uint32_t terraform_per_64k_frames
how many tile heights may, over a long period, be terraformed per 65536 frames?
uint16_t clear_frame_burst
how many tiles may, over a short period, be cleared?
uint8_t max_no_competitors
the number of competitors (AIs)
bool infinite_money
whether spending money despite negative balance is allowed
uint16_t competitors_interval
the interval (in minutes) between adding competitors
bool give_money
allow giving other companies money
uint64_t inflation_prices
Cumulated inflation of prices since game start; 16 bit fractional part.
Money max_loan
NOSAVE: Maximum possible loan.
bool show_finances
show finances at end of year
EconomySettings economy
settings to change the economy
ConstructionSettings construction
construction of things in-game
DifficultySettings difficulty
settings related to the difficulty
VehicleSettings vehicle
options for vehicles
Group data.
Definition group.h:73
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)
uint8_t max_companies
maximum amount of companies
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
static Titem * Get(auto index)
Returns Titem with given index.
static size_t GetNumItems()
Returns number of valid items in the pool.
Tindex index
Index of this pool item.
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function()
static bool IsValidID(auto index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
static bool CleaningPool()
Returns current state of pool cleaning - yes or no.
static Titem * GetIfValid(auto index)
Returns Titem with given index.
Base class for all pools.
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.
bool new_year
Play sound on new year, summarising the performance during the last year.
Town data structure.
Definition town.h:52
std::string name
Custom town name. If empty, the town was not renamed and uses the generated name.
Definition town.h:61
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
UnitID max_ships
max ships in game per company
UnitID max_trains
max trains in game per company
UnitID max_aircraft
max planes in game per company
UnitID max_roadveh
max trucks in game per company
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:555
AdminCompanyRemoveReason
Reasons for removing a company - communicated to admins.
Definition tcp_admin.h:108
Owner GetTileOwner(Tile tile)
Returns the owner of a tile.
Definition tile_map.h:178
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.
@ VEH_ROAD
Road vehicle type.
@ VEH_AIRCRAFT
Aircraft vehicle type.
@ VEH_SHIP
Ship vehicle type.
@ VEH_TRAIN
Train vehicle type.
void CloseConstructionWindows()
Close all windows that are used for construction of vehicle etc.
Definition window.cpp:3351
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:1182
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:3265
Window * FindWindowById(WindowClass cls, WindowNumber number)
Find a window by its class and window number.
Definition window.cpp:1140
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:3160
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition window.cpp:3147
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:3282
Window functions not directly related to making/drawing windows.
@ WN_NETWORK_STATUS_WINDOW_JOIN
Network join status.
Definition window_type.h:41
@ WC_PERFORMANCE_HISTORY
Performance history graph; Window numbers:
@ WC_COMPANY_LEAGUE
Company league window; Window numbers:
@ WC_SIGN_LIST
Sign list; Window numbers:
@ WC_PERFORMANCE_DETAIL
Performance detail window; Window numbers:
@ WC_GRAPH_LEGEND
Legend for graphs; Window numbers:
@ WC_LINKGRAPH_LEGEND
Linkgraph legend; Window numbers:
@ WC_STATUS_BAR
Statusbar (at the bottom of your screen); Window numbers:
Definition window_type.h:66
@ WC_SEND_NETWORK_MSG
Chatbox; Window numbers:
@ WC_ERRMSG
Error message; Window numbers:
@ WC_SCRIPT_SETTINGS
Script settings; Window numbers:
@ WC_SCRIPT_LIST
Scripts list; Window numbers:
@ WC_GOALS_LIST
Goals list; Window numbers:
@ WC_OPERATING_PROFIT
Operating profit graph; Window numbers:
@ WC_CLIENT_LIST
Client list; Window numbers:
@ WC_GAME_OPTIONS
Game options window; Window numbers:
@ WC_FINANCES
Finances of a company; Window numbers:
@ WC_INCOME_GRAPH
Income graph; Window numbers:
@ WC_SMALLMAP
Small map; Window numbers:
@ WC_DELIVERED_CARGO
Delivered cargo graph; Window numbers:
@ WC_COMPANY_VALUE
Company value graph; Window numbers:
@ WC_MAIN_TOOLBAR
Main toolbar (the long bar at the top); Window numbers:
Definition window_type.h:60
@ WC_COMPANY
Company view; Window numbers:
@ WC_NETWORK_STATUS_WINDOW
Network status window; Window numbers: