Files
@ r28549:6bc33bc6ee38
Branch filter:
Location: cpp/openttd-patchpack/source/src/company_cmd.cpp - annotation
r28549:6bc33bc6ee38
40.7 KiB
text/x-c
Codechange: Split dates and timers into Economy and Calendar time (#10700)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 | r12768:980ae0491352 r12768:980ae0491352 r12768:980ae0491352 r12768:980ae0491352 r12768:980ae0491352 r12768:980ae0491352 r12768:980ae0491352 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r15604:1622d4de58e8 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r24582:1447201ea3e3 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r18882:b2227172c2cf r18882:b2227172c2cf r10468:83faa36bfb14 r16259:4ee91980c70f r10696:8dfe83e30d01 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r11967:df0600d2c7e7 r12021:fc44a6d83fbe r14174:6999d5f69ce1 r14174:6999d5f69ce1 r16972:dc573ed68f9a r18764:f6e8611401f3 r20722:e079a68ef179 r20722:e079a68ef179 r24824:25e416ad7835 r26094:7572e88decb3 r27090:1ea30951c0f3 r28549:6bc33bc6ee38 r27104:635f8101e375 r10208:ef8fcc3dc4ca r18882:b2227172c2cf r10208:ef8fcc3dc4ca r21383:942c32fb8b0e r21383:942c32fb8b0e r21664:0999bd2815df r26832:a6bd9039c80b r21664:0999bd2815df r23674:a5bafa1a02c5 r23674:a5bafa1a02c5 r15606:aa81fc543ca1 r10208:ef8fcc3dc4ca r11230:fd38dc6041aa r10208:ef8fcc3dc4ca r15606:aa81fc543ca1 r11967:df0600d2c7e7 r10208:ef8fcc3dc4ca r15643:20875bb0d1bd r15643:20875bb0d1bd r15643:20875bb0d1bd r15643:20875bb0d1bd r15643:20875bb0d1bd r27737:728d55b97775 r10208:ef8fcc3dc4ca r15328:95a3e6ee8244 r15328:95a3e6ee8244 r15328:95a3e6ee8244 r27737:728d55b97775 r27737:728d55b97775 r27737:728d55b97775 r27737:728d55b97775 r16982:4a4e85b95d1e r12902:040f4bdcaecf r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r15643:20875bb0d1bd r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r25565:6a5de7df7ea1 r12969:5e7f0342aa53 r12969:5e7f0342aa53 r12969:5e7f0342aa53 r12969:5e7f0342aa53 r12969:5e7f0342aa53 r12969:5e7f0342aa53 r12969:5e7f0342aa53 r12969:5e7f0342aa53 r12983:fb761e9d5cea r12983:fb761e9d5cea r13578:aa891d62e8b0 r20256:42e6a81c0ced r15594:ba7e42fbae24 r14760:6829705b5544 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r11069:3f09c162966b r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r11919:363b629324b9 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r11919:363b629324b9 r10208:ef8fcc3dc4ca r23828:600da003c21e r23828:600da003c21e r23828:600da003c21e r13220:c788cc7e3fde r23828:600da003c21e r13220:c788cc7e3fde r15596:0df53125af8a r15284:a975e22a01ee r15284:a975e22a01ee r10208:ef8fcc3dc4ca r26516:d2c5d77e0db5 r26516:d2c5d77e0db5 r26516:d2c5d77e0db5 r26516:d2c5d77e0db5 r26516:d2c5d77e0db5 r10998:94dcb82c0e64 r10998:94dcb82c0e64 r10998:94dcb82c0e64 r18869:a4323c172531 r25010:cc3b6b985580 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r15606:aa81fc543ca1 r15606:aa81fc543ca1 r15606:aa81fc543ca1 r15606:aa81fc543ca1 r15606:aa81fc543ca1 r16954:6d8610a72e63 r10208:ef8fcc3dc4ca r16954:6d8610a72e63 r16954:6d8610a72e63 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r15606:aa81fc543ca1 r15606:aa81fc543ca1 r15606:aa81fc543ca1 r15606:aa81fc543ca1 r15606:aa81fc543ca1 r15606:aa81fc543ca1 r10225:b90a4df1bfeb r10208:ef8fcc3dc4ca r13436:8c37cd6574ae r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r15991:9b390068ea00 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r22672:3473f7daf422 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r15606:aa81fc543ca1 r15606:aa81fc543ca1 r15606:aa81fc543ca1 r15606:aa81fc543ca1 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r24824:25e416ad7835 r13024:48c81d0b078a r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r14813:2dc255bde71a r14813:2dc255bde71a r23023:7b8669afd1db r14813:2dc255bde71a r14813:2dc255bde71a r14222:128de2aca190 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r11944:3b8f9f948e8d r23607:36c15679007d r10208:ef8fcc3dc4ca r14222:128de2aca190 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r15606:aa81fc543ca1 r15606:aa81fc543ca1 r15606:aa81fc543ca1 r15606:aa81fc543ca1 r15606:aa81fc543ca1 r24112:408bc46a0f12 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r26228:5af29289e582 r26228:5af29289e582 r26228:5af29289e582 r26228:5af29289e582 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r26228:5af29289e582 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r15606:aa81fc543ca1 r15606:aa81fc543ca1 r15606:aa81fc543ca1 r15606:aa81fc543ca1 r24112:408bc46a0f12 r10208:ef8fcc3dc4ca r11944:3b8f9f948e8d r23607:36c15679007d r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r15606:aa81fc543ca1 r15606:aa81fc543ca1 r15606:aa81fc543ca1 r15606:aa81fc543ca1 r15606:aa81fc543ca1 r24112:408bc46a0f12 r10208:ef8fcc3dc4ca r11917:612c11f7ab47 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r27268:0f3ade585831 r27268:0f3ade585831 r27268:0f3ade585831 r27268:0f3ade585831 r27268:0f3ade585831 r16982:4a4e85b95d1e r16982:4a4e85b95d1e r16982:4a4e85b95d1e r23953:ba75d2f3b530 r27268:0f3ade585831 r27268:0f3ade585831 r27268:0f3ade585831 r27268:0f3ade585831 r16982:4a4e85b95d1e r16982:4a4e85b95d1e r16982:4a4e85b95d1e r14152:d949117093c2 r27568:cd0d4a85628d r14152:d949117093c2 r14152:d949117093c2 r14152:d949117093c2 r14152:d949117093c2 r27568:cd0d4a85628d r10208:ef8fcc3dc4ca r27568:cd0d4a85628d r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r11919:363b629324b9 r11725:57bc99fdc1bc r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r14152:d949117093c2 r10236:993bcc06ffa8 r10208:ef8fcc3dc4ca r12442:2de615d6604d r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r14152:d949117093c2 r14152:d949117093c2 r14152:d949117093c2 r14152:d949117093c2 r14152:d949117093c2 r14152:d949117093c2 r14805:8c416234ced2 r14152:d949117093c2 r14805:8c416234ced2 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r14152:d949117093c2 r10208:ef8fcc3dc4ca r14805:8c416234ced2 r14805:8c416234ced2 r27568:cd0d4a85628d r14805:8c416234ced2 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r14152:d949117093c2 r14152:d949117093c2 r14152:d949117093c2 r14152:d949117093c2 r14152:d949117093c2 r14774:6075f6397e6f r14152:d949117093c2 r14774:6075f6397e6f r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r14774:6075f6397e6f r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r27568:cd0d4a85628d r14774:6075f6397e6f r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r15606:aa81fc543ca1 r15606:aa81fc543ca1 r15606:aa81fc543ca1 r15606:aa81fc543ca1 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r15642:8b9b2e97124a r10208:ef8fcc3dc4ca r15642:8b9b2e97124a r10208:ef8fcc3dc4ca r15642:8b9b2e97124a r27737:728d55b97775 r27413:b706f5407370 r24214:a65c412aafcc r18122:623505749ded r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r23953:ba75d2f3b530 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r28396:ef195b601c72 r27413:b706f5407370 r27413:b706f5407370 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r12138:e93d2e409e78 r25744:540e044a54a1 r11725:57bc99fdc1bc r11725:57bc99fdc1bc r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r28112:bca7556a6bb6 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r17632:92f095eb81a2 r10208:ef8fcc3dc4ca r17632:92f095eb81a2 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r15606:aa81fc543ca1 r15606:aa81fc543ca1 r15606:aa81fc543ca1 r15606:aa81fc543ca1 r10942:52ba61ff5851 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r17056:6d2c96219506 r10208:ef8fcc3dc4ca r11085:c87a330fb4c2 r23953:ba75d2f3b530 r28535:cfbb61dd2d47 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r11085:c87a330fb4c2 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r15606:aa81fc543ca1 r15606:aa81fc543ca1 r15606:aa81fc543ca1 r15606:aa81fc543ca1 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r13099:96cb24edd6f2 r13099:96cb24edd6f2 r10208:ef8fcc3dc4ca r27413:b706f5407370 r27413:b706f5407370 r10208:ef8fcc3dc4ca r23953:ba75d2f3b530 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r27413:b706f5407370 r27413:b706f5407370 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r17098:afa706d65a49 r17098:afa706d65a49 r17098:afa706d65a49 r17098:afa706d65a49 r17098:afa706d65a49 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r23241:d2e564fdfd80 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r23241:d2e564fdfd80 r23961:d62b62a4184a r23241:d2e564fdfd80 r23241:d2e564fdfd80 r23241:d2e564fdfd80 r23241:d2e564fdfd80 r23241:d2e564fdfd80 r23241:d2e564fdfd80 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r15594:ba7e42fbae24 r12800:400b68836df9 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r12800:400b68836df9 r10208:ef8fcc3dc4ca r23607:36c15679007d r10208:ef8fcc3dc4ca r10942:52ba61ff5851 r10942:52ba61ff5851 r10942:52ba61ff5851 r12800:400b68836df9 r12800:400b68836df9 r12800:400b68836df9 r12800:400b68836df9 r23607:36c15679007d r12800:400b68836df9 r12800:400b68836df9 r10208:ef8fcc3dc4ca r10942:52ba61ff5851 r10942:52ba61ff5851 r10208:ef8fcc3dc4ca r28535:cfbb61dd2d47 r10208:ef8fcc3dc4ca r26848:319b6ad2b742 r27737:728d55b97775 r10208:ef8fcc3dc4ca r27896:3f48fccebe5f r23698:1872cc5b7dd7 r28549:6bc33bc6ee38 r26349:89c1e28eb0f3 r26349:89c1e28eb0f3 r26586:7489a53f5521 r26586:7489a53f5521 r26349:89c1e28eb0f3 r26349:89c1e28eb0f3 r26758:f6e631eabddf r26349:89c1e28eb0f3 r10208:ef8fcc3dc4ca r12032:8eefa482e9a8 r21664:0999bd2815df r11909:ed0a218be8e2 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r13024:48c81d0b078a r25254:2fb698f75978 r20256:42e6a81c0ced r16972:dc573ed68f9a r16972:dc573ed68f9a r10208:ef8fcc3dc4ca r10696:8dfe83e30d01 r10208:ef8fcc3dc4ca r18544:f85050db80c8 r18764:f6e8611401f3 r18544:f85050db80c8 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r15606:aa81fc543ca1 r27104:635f8101e375 r27104:635f8101e375 r27104:635f8101e375 r10959:4b345c618e31 r10208:ef8fcc3dc4ca r27783:c758f11112e0 r23953:ba75d2f3b530 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r27783:c758f11112e0 r27104:635f8101e375 r27104:635f8101e375 r27104:635f8101e375 r27104:635f8101e375 r27104:635f8101e375 r27104:635f8101e375 r27104:635f8101e375 r27104:635f8101e375 r27104:635f8101e375 r27104:635f8101e375 r27104:635f8101e375 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r15606:aa81fc543ca1 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r12845:8860291369ea r15715:f75fbcec842f r15715:f75fbcec842f r15715:f75fbcec842f r15715:f75fbcec842f r15715:f75fbcec842f r15715:f75fbcec842f r15715:f75fbcec842f r18147:1f8d7928a7f1 r18147:1f8d7928a7f1 r15715:f75fbcec842f r15715:f75fbcec842f r18147:1f8d7928a7f1 r18147:1f8d7928a7f1 r18147:1f8d7928a7f1 r18147:1f8d7928a7f1 r15715:f75fbcec842f r15715:f75fbcec842f r15715:f75fbcec842f r12845:8860291369ea r12845:8860291369ea r12845:8860291369ea r12845:8860291369ea r12845:8860291369ea r12845:8860291369ea r12845:8860291369ea r12845:8860291369ea r12845:8860291369ea r12845:8860291369ea r12845:8860291369ea r12845:8860291369ea r12845:8860291369ea r12845:8860291369ea r12845:8860291369ea r27883:ddbd33508a8a r12845:8860291369ea r12845:8860291369ea r12845:8860291369ea r12845:8860291369ea r12845:8860291369ea r12845:8860291369ea r12845:8860291369ea r12845:8860291369ea r12845:8860291369ea r12845:8860291369ea r12845:8860291369ea r12845:8860291369ea r12845:8860291369ea r12845:8860291369ea r12845:8860291369ea r23953:ba75d2f3b530 r27737:728d55b97775 r12845:8860291369ea r12845:8860291369ea r23953:ba75d2f3b530 r12845:8860291369ea r12845:8860291369ea r15715:f75fbcec842f r15715:f75fbcec842f r12845:8860291369ea r12845:8860291369ea r12845:8860291369ea r12845:8860291369ea r12845:8860291369ea r12845:8860291369ea r12845:8860291369ea r12845:8860291369ea r12845:8860291369ea r12845:8860291369ea r12845:8860291369ea r12845:8860291369ea r12845:8860291369ea r15011:acd1a8b391ed r26870:4f6a4f56e921 r26870:4f6a4f56e921 r26870:4f6a4f56e921 r27525:731028285759 r12845:8860291369ea r12845:8860291369ea r12845:8860291369ea r17632:92f095eb81a2 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r11944:3b8f9f948e8d r23607:36c15679007d r12845:8860291369ea r12845:8860291369ea r10730:c4f9653e3345 r10208:ef8fcc3dc4ca r27104:635f8101e375 r27883:ddbd33508a8a r27756:c44abd4e455f r27756:c44abd4e455f r27783:c758f11112e0 r27783:c758f11112e0 r27783:c758f11112e0 r27783:c758f11112e0 r27783:c758f11112e0 r27783:c758f11112e0 r27756:c44abd4e455f r27756:c44abd4e455f r27783:c758f11112e0 r27756:c44abd4e455f r27756:c44abd4e455f r27883:ddbd33508a8a r27756:c44abd4e455f r27104:635f8101e375 r27104:635f8101e375 r23280:382c4bba9365 r27104:635f8101e375 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r15606:aa81fc543ca1 r15606:aa81fc543ca1 r15606:aa81fc543ca1 r15606:aa81fc543ca1 r28549:6bc33bc6ee38 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r23953:ba75d2f3b530 r27872:bb4e800961d7 r27872:bb4e800961d7 r27872:bb4e800961d7 r13024:48c81d0b078a r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r23953:ba75d2f3b530 r10208:ef8fcc3dc4ca r19891:7fd9bf0868c4 r10208:ef8fcc3dc4ca r19891:7fd9bf0868c4 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r27090:1ea30951c0f3 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r12667:76618753be39 r23607:36c15679007d r10208:ef8fcc3dc4ca r25744:540e044a54a1 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r25744:540e044a54a1 r10208:ef8fcc3dc4ca r25744:540e044a54a1 r10208:ef8fcc3dc4ca r25744:540e044a54a1 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r25744:540e044a54a1 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r15610:623a23fb6560 r16259:4ee91980c70f r16259:4ee91980c70f r16259:4ee91980c70f r16259:4ee91980c70f r16259:4ee91980c70f r16259:4ee91980c70f r16259:4ee91980c70f r16259:4ee91980c70f r16259:4ee91980c70f r18192:da213da57034 r18192:da213da57034 r18192:da213da57034 r16259:4ee91980c70f r18192:da213da57034 r16259:4ee91980c70f r18192:da213da57034 r16259:4ee91980c70f r16259:4ee91980c70f r16259:4ee91980c70f r15610:623a23fb6560 r26095:00c14d52e378 r26107:59139eb8d51a r26107:59139eb8d51a r26107:59139eb8d51a r13057:58af81fcdcf8 r10208:ef8fcc3dc4ca r26107:59139eb8d51a r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r26107:59139eb8d51a r23277:e325d63c510f r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10454:ba5e39738ffa r10208:ef8fcc3dc4ca r23307:4227056d7788 r17588:0297fca9cfa3 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r25565:6a5de7df7ea1 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r23607:36c15679007d r24968:089fed249fe7 r24968:089fed249fe7 r24968:089fed249fe7 r10208:ef8fcc3dc4ca r10454:ba5e39738ffa r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10907:3616576a3216 r15850:2444eb8842d1 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r25461:f4423b696b95 r25478:0c7266566a47 r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r26349:89c1e28eb0f3 r26349:89c1e28eb0f3 r26386:6d8cd5a6e076 r26349:89c1e28eb0f3 r12021:fc44a6d83fbe r11356:ae9277304002 r12021:fc44a6d83fbe r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r21467:8b87202cc00f r15608:7b580ec7448a r15608:7b580ec7448a r10208:ef8fcc3dc4ca r23277:e325d63c510f r24693:a7a1c9d9241f r24693:a7a1c9d9241f r24693:a7a1c9d9241f r24693:a7a1c9d9241f r24693:a7a1c9d9241f r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r24693:a7a1c9d9241f r24693:a7a1c9d9241f r24693:a7a1c9d9241f r21467:8b87202cc00f r23607:36c15679007d r10208:ef8fcc3dc4ca r21467:8b87202cc00f r10208:ef8fcc3dc4ca r23277:e325d63c510f r18192:da213da57034 r18192:da213da57034 r24695:05e093ea8aec r24693:a7a1c9d9241f r24693:a7a1c9d9241f r15850:2444eb8842d1 r23607:36c15679007d r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r25744:540e044a54a1 r10208:ef8fcc3dc4ca r10696:8dfe83e30d01 r11725:57bc99fdc1bc r11725:57bc99fdc1bc r10696:8dfe83e30d01 r19366:08e6508de827 r10208:ef8fcc3dc4ca r10696:8dfe83e30d01 r10696:8dfe83e30d01 r12138:e93d2e409e78 r10208:ef8fcc3dc4ca r10696:8dfe83e30d01 r10696:8dfe83e30d01 r18501:8e3d905ea4bc r18764:f6e8611401f3 r18192:da213da57034 r20722:e079a68ef179 r20722:e079a68ef179 r25255:d399237bfabe r25255:d399237bfabe r15608:7b580ec7448a r15608:7b580ec7448a r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r16950:9855f8364bec r26856:c988753485d9 r26856:c988753485d9 r16950:9855f8364bec r10208:ef8fcc3dc4ca r10208:ef8fcc3dc4ca r14174:6999d5f69ce1 r15610:623a23fb6560 r15610:623a23fb6560 r26095:00c14d52e378 r26120:15c912177c88 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r26120:15c912177c88 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r15610:623a23fb6560 r28345:d8c125d15395 r28345:d8c125d15395 r28345:d8c125d15395 r28345:d8c125d15395 r28345:d8c125d15395 r28345:d8c125d15395 r28345:d8c125d15395 r28345:d8c125d15395 r28345:d8c125d15395 r28345:d8c125d15395 r28345:d8c125d15395 r28345:d8c125d15395 r28345:d8c125d15395 r28345:d8c125d15395 r15610:623a23fb6560 r26095:00c14d52e378 r26120:15c912177c88 r26120:15c912177c88 r26120:15c912177c88 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r26120:15c912177c88 r14174:6999d5f69ce1 r23241:d2e564fdfd80 r23241:d2e564fdfd80 r23241:d2e564fdfd80 r23241:d2e564fdfd80 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r26120:15c912177c88 r23953:ba75d2f3b530 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r26120:15c912177c88 r23241:d2e564fdfd80 r28535:cfbb61dd2d47 r23241:d2e564fdfd80 r14174:6999d5f69ce1 r23241:d2e564fdfd80 r23241:d2e564fdfd80 r23241:d2e564fdfd80 r28345:d8c125d15395 r23241:d2e564fdfd80 r23241:d2e564fdfd80 r23241:d2e564fdfd80 r23241:d2e564fdfd80 r23241:d2e564fdfd80 r23241:d2e564fdfd80 r28535:cfbb61dd2d47 r23241:d2e564fdfd80 r14174:6999d5f69ce1 r23241:d2e564fdfd80 r28345:d8c125d15395 r23241:d2e564fdfd80 r23241:d2e564fdfd80 r14174:6999d5f69ce1 r23241:d2e564fdfd80 r23241:d2e564fdfd80 r23241:d2e564fdfd80 r23241:d2e564fdfd80 r23241:d2e564fdfd80 r23241:d2e564fdfd80 r23241:d2e564fdfd80 r23241:d2e564fdfd80 r23241:d2e564fdfd80 r23241:d2e564fdfd80 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r23241:d2e564fdfd80 r23241:d2e564fdfd80 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14993:43e9f15bd64b r14993:43e9f15bd64b r14993:43e9f15bd64b r14993:43e9f15bd64b r14993:43e9f15bd64b r14993:43e9f15bd64b r20256:42e6a81c0ced r17329:078c0f7022e9 r17329:078c0f7022e9 r17329:078c0f7022e9 r14993:43e9f15bd64b r14174:6999d5f69ce1 r23966:9de0a0960701 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r16208:fb601446b60b r16208:fb601446b60b r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r15606:aa81fc543ca1 r15606:aa81fc543ca1 r15606:aa81fc543ca1 r15606:aa81fc543ca1 r15606:aa81fc543ca1 r25561:3defb050f30b r14174:6999d5f69ce1 r23953:ba75d2f3b530 r24214:a65c412aafcc r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r15610:623a23fb6560 r15610:623a23fb6560 r26095:00c14d52e378 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r26120:15c912177c88 r14174:6999d5f69ce1 r25562:30716ba6a396 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r16671:bbf8280610d0 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r24214:a65c412aafcc r24214:a65c412aafcc r24214:a65c412aafcc r24214:a65c412aafcc r24214:a65c412aafcc r14174:6999d5f69ce1 r16259:4ee91980c70f r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r15606:aa81fc543ca1 r15606:aa81fc543ca1 r15606:aa81fc543ca1 r15606:aa81fc543ca1 r15606:aa81fc543ca1 r25561:3defb050f30b r14174:6999d5f69ce1 r23953:ba75d2f3b530 r24214:a65c412aafcc r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r15610:623a23fb6560 r15610:623a23fb6560 r26095:00c14d52e378 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r26120:15c912177c88 r14174:6999d5f69ce1 r25562:30716ba6a396 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r16667:057c627d0a47 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r24214:a65c412aafcc r14174:6999d5f69ce1 r24214:a65c412aafcc r14174:6999d5f69ce1 r24214:a65c412aafcc r26120:15c912177c88 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r16259:4ee91980c70f r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r14174:6999d5f69ce1 r20038:7e99f805aa24 r20038:7e99f805aa24 r20038:7e99f805aa24 r23607:36c15679007d r20038:7e99f805aa24 r20038:7e99f805aa24 r20038:7e99f805aa24 r20038:7e99f805aa24 r20038:7e99f805aa24 r23607:36c15679007d r20038:7e99f805aa24 r20038:7e99f805aa24 r20038:7e99f805aa24 r20038:7e99f805aa24 r20038:7e99f805aa24 r20038:7e99f805aa24 r20038:7e99f805aa24 r20038:7e99f805aa24 r23698:1872cc5b7dd7 r23698:1872cc5b7dd7 r23698:1872cc5b7dd7 r23698:1872cc5b7dd7 r23698:1872cc5b7dd7 r27737:728d55b97775 r23698:1872cc5b7dd7 r27737:728d55b97775 r23698:1872cc5b7dd7 r23698:1872cc5b7dd7 r23698:1872cc5b7dd7 r23698:1872cc5b7dd7 r23698:1872cc5b7dd7 r23698:1872cc5b7dd7 r23698:1872cc5b7dd7 r23698:1872cc5b7dd7 r23698:1872cc5b7dd7 r23698:1872cc5b7dd7 r27737:728d55b97775 r23698:1872cc5b7dd7 r27737:728d55b97775 r23698:1872cc5b7dd7 r23698:1872cc5b7dd7 r23698:1872cc5b7dd7 r23698:1872cc5b7dd7 r23698:1872cc5b7dd7 r24582:1447201ea3e3 r24582:1447201ea3e3 r24582:1447201ea3e3 r24582:1447201ea3e3 r24582:1447201ea3e3 r24582:1447201ea3e3 r26095:00c14d52e378 r26120:15c912177c88 r26120:15c912177c88 r24582:1447201ea3e3 r24582:1447201ea3e3 r27269:671153a97afa r24582:1447201ea3e3 r24582:1447201ea3e3 r24582:1447201ea3e3 r24582:1447201ea3e3 r26120:15c912177c88 r24582:1447201ea3e3 r24582:1447201ea3e3 r24582:1447201ea3e3 r24582:1447201ea3e3 r24582:1447201ea3e3 r24582:1447201ea3e3 r24582:1447201ea3e3 r24582:1447201ea3e3 r24582:1447201ea3e3 r24582:1447201ea3e3 r24582:1447201ea3e3 r24582:1447201ea3e3 r24582:1447201ea3e3 r25487:e8c958a8b290 r24582:1447201ea3e3 r24582:1447201ea3e3 r25487:e8c958a8b290 r24582:1447201ea3e3 r24582:1447201ea3e3 r24582:1447201ea3e3 r24582:1447201ea3e3 r24582:1447201ea3e3 r24582:1447201ea3e3 r24582:1447201ea3e3 r24582:1447201ea3e3 r26232:7108ff70a949 r26232:7108ff70a949 r26232:7108ff70a949 r26232:7108ff70a949 r26232:7108ff70a949 r26232:7108ff70a949 r26232:7108ff70a949 r26232:7108ff70a949 r26232:7108ff70a949 r26232:7108ff70a949 r26232:7108ff70a949 r26232:7108ff70a949 r26232:7108ff70a949 r26232:7108ff70a949 r26232:7108ff70a949 r26232:7108ff70a949 r26232:7108ff70a949 r26232:7108ff70a949 r26232:7108ff70a949 r26232:7108ff70a949 r26232:7108ff70a949 r26232:7108ff70a949 r26232:7108ff70a949 r26232:7108ff70a949 r26232:7108ff70a949 r26232:7108ff70a949 r26232:7108ff70a949 r26232:7108ff70a949 | /*
* This file is part of OpenTTD.
* 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.
* 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.
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file company_cmd.cpp Handling of companies. */
#include "stdafx.h"
#include "company_base.h"
#include "company_func.h"
#include "company_gui.h"
#include "core/backup_type.hpp"
#include "town.h"
#include "news_func.h"
#include "command_func.h"
#include "network/network.h"
#include "network/network_func.h"
#include "network/network_base.h"
#include "network/network_admin.h"
#include "ai/ai.hpp"
#include "company_manager_face.h"
#include "window_func.h"
#include "strings_func.h"
#include "sound_func.h"
#include "rail.h"
#include "core/pool_func.hpp"
#include "settings_func.h"
#include "vehicle_base.h"
#include "vehicle_func.h"
#include "smallmap_gui.h"
#include "game/game.hpp"
#include "goal_base.h"
#include "story_base.h"
#include "widgets/statusbar_widget.h"
#include "company_cmd.h"
#include "timer/timer.h"
#include "timer/timer_game_economy.h"
#include "timer/timer_game_tick.h"
#include "table/strings.h"
#include "safeguards.h"
void ClearEnginesHiddenFlagOfCompany(CompanyID cid);
void UpdateObjectColours(const Company *c);
CompanyID _local_company; ///< Company controlled by the human player at this client. Can also be #COMPANY_SPECTATOR.
CompanyID _current_company; ///< Company currently doing an action.
Colours _company_colours[MAX_COMPANIES]; ///< NOSAVE: can be determined from company structs.
CompanyManagerFace _company_manager_face; ///< for company manager face storage in openttd.cfg
uint _cur_company_tick_index; ///< used to generate a name for one company that doesn't have a name yet per tick
CompanyPool _company_pool("Company"); ///< Pool of companies.
INSTANTIATE_POOL_METHODS(Company)
/**
* Constructor.
* @param name_1 Name of the company.
* @param is_ai A computer program is running for this company.
*/
Company::Company(uint16_t name_1, bool is_ai)
{
this->name_1 = name_1;
this->location_of_HQ = INVALID_TILE;
this->is_ai = is_ai;
this->terraform_limit = (uint32_t)_settings_game.construction.terraform_frame_burst << 16;
this->clear_limit = (uint32_t)_settings_game.construction.clear_frame_burst << 16;
this->tree_limit = (uint32_t)_settings_game.construction.tree_frame_burst << 16;
this->build_object_limit = (uint32_t)_settings_game.construction.build_object_frame_burst << 16;
InvalidateWindowData(WC_PERFORMANCE_DETAIL, 0, INVALID_COMPANY);
}
/** Destructor. */
Company::~Company()
{
if (CleaningPool()) return;
CloseCompanyWindows(this->index);
}
/**
* Invalidating some stuff after removing item from the pool.
* @param index index of deleted item
*/
void Company::PostDestructor(size_t index)
{
InvalidateWindowData(WC_GRAPH_LEGEND, 0, (int)index);
InvalidateWindowData(WC_PERFORMANCE_DETAIL, 0, (int)index);
InvalidateWindowData(WC_COMPANY_LEAGUE, 0, 0);
InvalidateWindowData(WC_LINKGRAPH_LEGEND, 0);
/* If the currently shown error message has this company in it, then close it. */
InvalidateWindowData(WC_ERRMSG, 0);
}
/**
* Sets the local company and updates the settings that are set on a
* per-company basis to reflect the core's state in the GUI.
* @param new_company the new company
* @pre Company::IsValidID(new_company) || new_company == COMPANY_SPECTATOR || new_company == OWNER_NONE
*/
void SetLocalCompany(CompanyID new_company)
{
/* company could also be COMPANY_SPECTATOR or OWNER_NONE */
assert(Company::IsValidID(new_company) || new_company == COMPANY_SPECTATOR || new_company == OWNER_NONE);
/* If actually changing to another company, several windows need closing */
bool switching_company = _local_company != new_company;
/* Delete the chat window, if you were team chatting. */
if (switching_company) InvalidateWindowData(WC_SEND_NETWORK_MSG, DESTTYPE_TEAM, _local_company);
assert(IsLocalCompany());
_current_company = _local_company = new_company;
if (switching_company) {
InvalidateWindowClassesData(WC_COMPANY);
/* Delete any construction windows... */
CloseConstructionWindows();
}
/* ... and redraw the whole screen. */
MarkWholeScreenDirty();
InvalidateWindowClassesData(WC_SIGN_LIST, -1);
InvalidateWindowClassesData(WC_GOALS_LIST);
}
/**
* Get the colour for DrawString-subroutines which matches the colour of the company.
* @param company Company to get the colour of.
* @return Colour of \a company.
*/
TextColour GetDrawStringCompanyColour(CompanyID company)
{
if (!Company::IsValidID(company)) return (TextColour)_colour_gradient[COLOUR_WHITE][4] | TC_IS_PALETTE_COLOUR;
return (TextColour)_colour_gradient[_company_colours[company]][4] | TC_IS_PALETTE_COLOUR;
}
/**
* Draw the icon of a company.
* @param c Company that needs its icon drawn.
* @param x Horizontal coordinate of the icon.
* @param y Vertical coordinate of the icon.
*/
void DrawCompanyIcon(CompanyID c, int x, int y)
{
DrawSprite(SPR_COMPANY_ICON, COMPANY_SPRITE_COLOUR(c), x, y);
}
/**
* Checks whether a company manager's face is a valid encoding.
* Unused bits are not enforced to be 0.
* @param cmf the fact to check
* @return true if and only if the face is valid
*/
static bool IsValidCompanyManagerFace(CompanyManagerFace cmf)
{
if (!AreCompanyManagerFaceBitsValid(cmf, CMFV_GEN_ETHN, GE_WM)) return false;
GenderEthnicity ge = (GenderEthnicity)GetCompanyManagerFaceBits(cmf, CMFV_GEN_ETHN, GE_WM);
bool has_moustache = !HasBit(ge, GENDER_FEMALE) && GetCompanyManagerFaceBits(cmf, CMFV_HAS_MOUSTACHE, ge) != 0;
bool has_tie_earring = !HasBit(ge, GENDER_FEMALE) || GetCompanyManagerFaceBits(cmf, CMFV_HAS_TIE_EARRING, ge) != 0;
bool has_glasses = GetCompanyManagerFaceBits(cmf, CMFV_HAS_GLASSES, ge) != 0;
if (!AreCompanyManagerFaceBitsValid(cmf, CMFV_EYE_COLOUR, ge)) return false;
for (CompanyManagerFaceVariable cmfv = CMFV_CHEEKS; cmfv < CMFV_END; cmfv++) {
switch (cmfv) {
case CMFV_MOUSTACHE: if (!has_moustache) continue; break;
case CMFV_LIPS:
case CMFV_NOSE: if (has_moustache) continue; break;
case CMFV_TIE_EARRING: if (!has_tie_earring) continue; break;
case CMFV_GLASSES: if (!has_glasses) continue; break;
default: break;
}
if (!AreCompanyManagerFaceBitsValid(cmf, cmfv, ge)) return false;
}
return true;
}
/**
* Refresh all windows owned by a company.
* @param company Company that changed, and needs its windows refreshed.
*/
void InvalidateCompanyWindows(const Company *company)
{
CompanyID cid = company->index;
if (cid == _local_company) SetWindowWidgetDirty(WC_STATUS_BAR, 0, WID_S_RIGHT);
SetWindowDirty(WC_FINANCES, cid);
}
/**
* Verify whether the company can pay the bill.
* @param[in,out] cost Money to pay, is changed to an error if the company does not have enough money.
* @return Function returns \c true if the company has enough money, else it returns \c false.
*/
bool CheckCompanyHasMoney(CommandCost &cost)
{
if (cost.GetCost() > 0) {
const Company *c = Company::GetIfValid(_current_company);
if (c != nullptr && cost.GetCost() > c->money) {
SetDParam(0, cost.GetCost());
cost.MakeError(STR_ERROR_NOT_ENOUGH_CASH_REQUIRES_CURRENCY);
return false;
}
}
return true;
}
/**
* Deduct costs of a command from the money of a company.
* @param c Company to pay the bill.
* @param cost Money to pay.
*/
static void SubtractMoneyFromAnyCompany(Company *c, const CommandCost &cost)
{
if (cost.GetCost() == 0) return;
assert(cost.GetExpensesType() != INVALID_EXPENSES);
c->money -= cost.GetCost();
c->yearly_expenses[0][cost.GetExpensesType()] += cost.GetCost();
if (HasBit(1 << EXPENSES_TRAIN_REVENUE |
1 << EXPENSES_ROADVEH_REVENUE |
1 << EXPENSES_AIRCRAFT_REVENUE |
1 << EXPENSES_SHIP_REVENUE, cost.GetExpensesType())) {
c->cur_economy.income -= cost.GetCost();
} else if (HasBit(1 << EXPENSES_TRAIN_RUN |
1 << EXPENSES_ROADVEH_RUN |
1 << EXPENSES_AIRCRAFT_RUN |
1 << EXPENSES_SHIP_RUN |
1 << EXPENSES_PROPERTY |
1 << EXPENSES_LOAN_INTEREST, cost.GetExpensesType())) {
c->cur_economy.expenses -= cost.GetCost();
}
InvalidateCompanyWindows(c);
}
/**
* Subtract money from the #_current_company, if the company is valid.
* @param cost Money to pay.
*/
void SubtractMoneyFromCompany(const CommandCost &cost)
{
Company *c = Company::GetIfValid(_current_company);
if (c != nullptr) SubtractMoneyFromAnyCompany(c, cost);
}
/**
* Subtract money from a company, including the money fraction.
* @param company Company paying the bill.
* @param cst Cost of a command.
*/
void SubtractMoneyFromCompanyFract(CompanyID company, const CommandCost &cst)
{
Company *c = Company::Get(company);
byte m = c->money_fraction;
Money cost = cst.GetCost();
c->money_fraction = m - (byte)cost;
cost >>= 8;
if (c->money_fraction > m) cost++;
if (cost != 0) SubtractMoneyFromAnyCompany(c, CommandCost(cst.GetExpensesType(), cost));
}
static constexpr void UpdateLandscapingLimit(uint32_t &limit, uint64_t per_64k_frames, uint64_t burst)
{
limit = static_cast<uint32_t>(std::min<uint64_t>(limit + per_64k_frames, burst << 16));
}
/** Update the landscaping limits per company. */
void UpdateLandscapingLimits()
{
for (Company *c : Company::Iterate()) {
UpdateLandscapingLimit(c->terraform_limit, _settings_game.construction.terraform_per_64k_frames, _settings_game.construction.terraform_frame_burst);
UpdateLandscapingLimit(c->clear_limit, _settings_game.construction.clear_per_64k_frames, _settings_game.construction.clear_frame_burst);
UpdateLandscapingLimit(c->tree_limit, _settings_game.construction.tree_per_64k_frames, _settings_game.construction.tree_frame_burst);
UpdateLandscapingLimit(c->build_object_limit, _settings_game.construction.build_object_per_64k_frames, _settings_game.construction.build_object_frame_burst);
}
}
/**
* Set the right DParams for STR_ERROR_OWNED_BY.
* @param owner the owner to get the name of.
* @param tile optional tile to get the right town.
* @pre if tile == 0, then owner can't be OWNER_TOWN.
*/
void SetDParamsForOwnedBy(Owner owner, TileIndex tile)
{
SetDParam(OWNED_BY_OWNER_IN_PARAMETERS_OFFSET, owner);
if (owner != OWNER_TOWN) {
if (!Company::IsValidID(owner)) {
SetDParam(0, STR_COMPANY_SOMEONE);
} else {
SetDParam(0, STR_COMPANY_NAME);
SetDParam(1, owner);
}
} else {
assert(tile != 0);
const Town *t = ClosestTownFromTile(tile, UINT_MAX);
SetDParam(0, STR_TOWN_NAME);
SetDParam(1, t->index);
}
}
/**
* Check whether the current owner owns something.
* If that isn't the case an appropriate error will be given.
* @param owner the owner of the thing to check.
* @param tile optional tile to get the right town.
* @pre if tile == 0 then the owner can't be OWNER_TOWN.
* @return A succeeded command iff it's owned by the current company, else a failed command.
*/
CommandCost CheckOwnership(Owner owner, TileIndex tile)
{
assert(owner < OWNER_END);
assert(owner != OWNER_TOWN || tile != 0);
if (owner == _current_company) return CommandCost();
SetDParamsForOwnedBy(owner, tile);
return_cmd_error(STR_ERROR_OWNED_BY);
}
/**
* Check whether the current owner owns the stuff on
* the given tile. If that isn't the case an
* appropriate error will be given.
* @param tile the tile to check.
* @return A succeeded command iff it's owned by the current company, else a failed command.
*/
CommandCost CheckTileOwnership(TileIndex tile)
{
Owner owner = GetTileOwner(tile);
assert(owner < OWNER_END);
if (owner == _current_company) return CommandCost();
/* no need to get the name of the owner unless we're the local company (saves some time) */
if (IsLocalCompany()) SetDParamsForOwnedBy(owner, tile);
return_cmd_error(STR_ERROR_OWNED_BY);
}
/**
* Generate the name of a company from the last build coordinate.
* @param c Company to give a name.
*/
static void GenerateCompanyName(Company *c)
{
if (c->name_1 != STR_SV_UNNAMED) return;
if (c->last_build_coordinate == 0) return;
Town *t = ClosestTownFromTile(c->last_build_coordinate, UINT_MAX);
StringID str;
uint32_t strp;
std::string name;
if (t->name.empty() && IsInsideMM(t->townnametype, SPECSTR_TOWNNAME_START, SPECSTR_TOWNNAME_LAST + 1)) {
str = t->townnametype - SPECSTR_TOWNNAME_START + SPECSTR_COMPANY_NAME_START;
strp = t->townnameparts;
verify_name:;
/* No companies must have this name already */
for (const Company *cc : Company::Iterate()) {
if (cc->name_1 == str && cc->name_2 == strp) goto bad_town_name;
}
SetDParam(0, strp);
name = GetString(str);
if (Utf8StringLength(name) >= MAX_LENGTH_COMPANY_NAME_CHARS) goto bad_town_name;
set_name:;
c->name_1 = str;
c->name_2 = strp;
MarkWholeScreenDirty();
if (c->is_ai) {
CompanyNewsInformation *cni = new CompanyNewsInformation(c);
SetDParam(0, STR_NEWS_COMPANY_LAUNCH_TITLE);
SetDParam(1, STR_NEWS_COMPANY_LAUNCH_DESCRIPTION);
SetDParamStr(2, cni->company_name);
SetDParam(3, t->index);
AddNewsItem(STR_MESSAGE_NEWS_FORMAT, NT_COMPANY_INFO, NF_COMPANY, NR_TILE, c->last_build_coordinate.base(), NR_NONE, UINT32_MAX, cni);
}
return;
}
bad_town_name:;
if (c->president_name_1 == SPECSTR_PRESIDENT_NAME) {
str = SPECSTR_ANDCO_NAME;
strp = c->president_name_2;
goto set_name;
} else {
str = SPECSTR_ANDCO_NAME;
strp = Random();
goto verify_name;
}
}
/** Sorting weights for the company colours. */
static const byte _colour_sort[COLOUR_END] = {2, 2, 3, 2, 3, 2, 3, 2, 3, 2, 2, 2, 3, 1, 1, 1};
/** Similar colours, so we can try to prevent same coloured companies. */
static const Colours _similar_colour[COLOUR_END][2] = {
{ COLOUR_BLUE, COLOUR_LIGHT_BLUE }, // COLOUR_DARK_BLUE
{ COLOUR_GREEN, COLOUR_DARK_GREEN }, // COLOUR_PALE_GREEN
{ INVALID_COLOUR, INVALID_COLOUR }, // COLOUR_PINK
{ COLOUR_ORANGE, INVALID_COLOUR }, // COLOUR_YELLOW
{ INVALID_COLOUR, INVALID_COLOUR }, // COLOUR_RED
{ COLOUR_DARK_BLUE, COLOUR_BLUE }, // COLOUR_LIGHT_BLUE
{ COLOUR_PALE_GREEN, COLOUR_DARK_GREEN }, // COLOUR_GREEN
{ COLOUR_PALE_GREEN, COLOUR_GREEN }, // COLOUR_DARK_GREEN
{ COLOUR_DARK_BLUE, COLOUR_LIGHT_BLUE }, // COLOUR_BLUE
{ COLOUR_BROWN, COLOUR_ORANGE }, // COLOUR_CREAM
{ COLOUR_PURPLE, INVALID_COLOUR }, // COLOUR_MAUVE
{ COLOUR_MAUVE, INVALID_COLOUR }, // COLOUR_PURPLE
{ COLOUR_YELLOW, COLOUR_CREAM }, // COLOUR_ORANGE
{ COLOUR_CREAM, INVALID_COLOUR }, // COLOUR_BROWN
{ COLOUR_WHITE, INVALID_COLOUR }, // COLOUR_GREY
{ COLOUR_GREY, INVALID_COLOUR }, // COLOUR_WHITE
};
/**
* Generate a company colour.
* @return Generated company colour.
*/
static Colours GenerateCompanyColour()
{
Colours colours[COLOUR_END];
/* Initialize array */
for (uint i = 0; i < COLOUR_END; i++) colours[i] = (Colours)i;
/* And randomize it */
for (uint i = 0; i < 100; i++) {
uint r = Random();
Swap(colours[GB(r, 0, 4)], colours[GB(r, 4, 4)]);
}
/* Bubble sort it according to the values in table 1 */
for (uint i = 0; i < COLOUR_END; i++) {
for (uint j = 1; j < COLOUR_END; j++) {
if (_colour_sort[colours[j - 1]] < _colour_sort[colours[j]]) {
Swap(colours[j - 1], colours[j]);
}
}
}
/* Move the colours that look similar to each company's colour to the side */
for (const Company *c : Company::Iterate()) {
Colours pcolour = c->colour;
for (uint i = 0; i < COLOUR_END; i++) {
if (colours[i] == pcolour) {
colours[i] = INVALID_COLOUR;
break;
}
}
for (uint j = 0; j < 2; j++) {
Colours similar = _similar_colour[pcolour][j];
if (similar == INVALID_COLOUR) break;
for (uint i = 1; i < COLOUR_END; i++) {
if (colours[i - 1] == similar) Swap(colours[i - 1], colours[i]);
}
}
}
/* Return the first available colour */
for (uint i = 0; i < COLOUR_END; i++) {
if (colours[i] != INVALID_COLOUR) return colours[i];
}
NOT_REACHED();
}
/**
* Generate a random president name of a company.
* @param c Company that needs a new president name.
*/
static void GeneratePresidentName(Company *c)
{
for (;;) {
restart:;
c->president_name_2 = Random();
c->president_name_1 = SPECSTR_PRESIDENT_NAME;
/* Reserve space for extra unicode character. We need to do this to be able
* to detect too long president name. */
SetDParam(0, c->index);
std::string name = GetString(STR_PRESIDENT_NAME);
if (Utf8StringLength(name) >= MAX_LENGTH_PRESIDENT_NAME_CHARS) continue;
for (const Company *cc : Company::Iterate()) {
if (c != cc) {
SetDParam(0, cc->index);
std::string other_name = GetString(STR_PRESIDENT_NAME);
if (name == other_name) goto restart;
}
}
return;
}
}
/**
* Reset the livery schemes to the company's primary colour.
* This is used on loading games without livery information and on new company start up.
* @param c Company to reset.
*/
void ResetCompanyLivery(Company *c)
{
for (LiveryScheme scheme = LS_BEGIN; scheme < LS_END; scheme++) {
c->livery[scheme].in_use = 0;
c->livery[scheme].colour1 = c->colour;
c->livery[scheme].colour2 = c->colour;
}
for (Group *g : Group::Iterate()) {
if (g->owner == c->index) {
g->livery.in_use = 0;
g->livery.colour1 = c->colour;
g->livery.colour2 = c->colour;
}
}
}
/**
* Create a new company and sets all company variables default values
*
* @param is_ai is an AI company?
* @param company CompanyID to use for the new company
* @return the company struct
*/
Company *DoStartupNewCompany(bool is_ai, CompanyID company = INVALID_COMPANY)
{
if (!Company::CanAllocateItem()) return nullptr;
/* we have to generate colour before this company is valid */
Colours colour = GenerateCompanyColour();
Company *c;
if (company == INVALID_COMPANY) {
c = new Company(STR_SV_UNNAMED, is_ai);
} else {
if (Company::IsValidID(company)) return nullptr;
c = new (company) Company(STR_SV_UNNAMED, is_ai);
}
c->colour = colour;
ResetCompanyLivery(c);
_company_colours[c->index] = c->colour;
/* Scale the initial loan based on the inflation rounded down to the loan interval. The maximum loan has already been inflation adjusted. */
c->money = c->current_loan = std::min<int64_t>((INITIAL_LOAN * _economy.inflation_prices >> 16) / LOAN_INTERVAL * LOAN_INTERVAL, _economy.max_loan);
c->avail_railtypes = GetCompanyRailTypes(c->index);
c->avail_roadtypes = GetCompanyRoadTypes(c->index);
c->inaugurated_year = TimerGameEconomy::year;
/* If starting a player company in singleplayer and a favorite company manager face is selected, choose it. Otherwise, use a random face.
* In a network game, we'll choose the favorite face later in CmdCompanyCtrl to sync it to all clients. */
if (_company_manager_face != 0 && !is_ai && !_networking) {
c->face = _company_manager_face;
} else {
RandomCompanyManagerFaceBits(c->face, (GenderEthnicity)Random(), false, _random);
}
SetDefaultCompanySettings(c->index);
ClearEnginesHiddenFlagOfCompany(c->index);
GeneratePresidentName(c);
SetWindowDirty(WC_GRAPH_LEGEND, 0);
InvalidateWindowData(WC_CLIENT_LIST, 0);
InvalidateWindowData(WC_LINKGRAPH_LEGEND, 0);
BuildOwnerLegend();
InvalidateWindowData(WC_SMALLMAP, 0, 1);
if (is_ai && (!_networking || _network_server)) AI::StartNew(c->index);
AI::BroadcastNewEvent(new ScriptEventCompanyNew(c->index), c->index);
Game::NewEvent(new ScriptEventCompanyNew(c->index));
return c;
}
/** Start a new competitor company if possible. */
TimeoutTimer<TimerGameTick> _new_competitor_timeout(0, []() {
if (_game_mode == GM_MENU || !AI::CanStartNew()) return;
if (_networking && Company::GetNumItems() >= _settings_client.network.max_companies) return;
/* count number of competitors */
uint8_t n = 0;
for (const Company *c : Company::Iterate()) {
if (c->is_ai) n++;
}
if (n >= _settings_game.difficulty.max_no_competitors) return;
/* Send a command to all clients to start up a new AI.
* Works fine for Multiplayer and Singleplayer */
Command<CMD_COMPANY_CTRL>::Post(CCA_NEW_AI, INVALID_COMPANY, CRR_NONE, INVALID_CLIENT_ID);
});
/** Start of a new game. */
void StartupCompanies()
{
/* Ensure the timeout is aborted, so it doesn't fire based on information of the last game. */
_new_competitor_timeout.Abort();
}
/** Initialize the pool of companies. */
void InitializeCompanies()
{
_cur_company_tick_index = 0;
}
/**
* May company \a cbig buy company \a csmall?
* @param cbig Company buying \a csmall.
* @param csmall Company getting bought.
* @return Return \c true if it is allowed.
*/
bool MayCompanyTakeOver(CompanyID cbig, CompanyID csmall)
{
const Company *c1 = Company::Get(cbig);
const Company *c2 = Company::Get(csmall);
/* Do the combined vehicle counts stay within the limits? */
return c1->group_all[VEH_TRAIN].num_vehicle + c2->group_all[VEH_TRAIN].num_vehicle <= _settings_game.vehicle.max_trains &&
c1->group_all[VEH_ROAD].num_vehicle + c2->group_all[VEH_ROAD].num_vehicle <= _settings_game.vehicle.max_roadveh &&
c1->group_all[VEH_SHIP].num_vehicle + c2->group_all[VEH_SHIP].num_vehicle <= _settings_game.vehicle.max_ships &&
c1->group_all[VEH_AIRCRAFT].num_vehicle + c2->group_all[VEH_AIRCRAFT].num_vehicle <= _settings_game.vehicle.max_aircraft;
}
/**
* Handle the bankruptcy take over of a company.
* Companies going bankrupt will ask the other companies in order of their
* performance rating, so better performing companies get the 'do you want to
* merge with Y' question earlier. The question will then stay till either the
* company has gone bankrupt or got merged with a company.
*
* @param c the company that is going bankrupt.
*/
static void HandleBankruptcyTakeover(Company *c)
{
/* Amount of time out for each company to take over a company;
* Timeout is a quarter (3 months of 30 days) divided over the
* number of companies. The minimum number of days in a quarter
* is 90: 31 in January, 28 in February and 31 in March.
* Note that the company going bankrupt can't buy itself. */
static const int TAKE_OVER_TIMEOUT = 3 * 30 * Ticks::DAY_TICKS / (MAX_COMPANIES - 1);
assert(c->bankrupt_asked != 0);
/* We're currently asking some company to buy 'us' */
if (c->bankrupt_timeout != 0) {
c->bankrupt_timeout -= MAX_COMPANIES;
if (c->bankrupt_timeout > 0) return;
c->bankrupt_timeout = 0;
return;
}
/* Did we ask everyone for bankruptcy? If so, bail out. */
if (c->bankrupt_asked == MAX_UVALUE(CompanyMask)) return;
Company *best = nullptr;
int32_t best_performance = -1;
/* Ask the company with the highest performance history first */
for (Company *c2 : Company::Iterate()) {
if (c2->bankrupt_asked == 0 && // Don't ask companies going bankrupt themselves
!HasBit(c->bankrupt_asked, c2->index) &&
best_performance < c2->old_economy[1].performance_history &&
MayCompanyTakeOver(c2->index, c->index)) {
best_performance = c2->old_economy[1].performance_history;
best = c2;
}
}
/* Asked all companies? */
if (best_performance == -1) {
c->bankrupt_asked = MAX_UVALUE(CompanyMask);
return;
}
SetBit(c->bankrupt_asked, best->index);
c->bankrupt_timeout = TAKE_OVER_TIMEOUT;
AI::NewEvent(best->index, new ScriptEventCompanyAskMerger(c->index, c->bankrupt_value));
if (IsInteractiveCompany(best->index)) {
ShowBuyCompanyDialog(c->index, false);
}
}
/** Called every tick for updating some company info. */
void OnTick_Companies()
{
if (_game_mode == GM_EDITOR) return;
Company *c = Company::GetIfValid(_cur_company_tick_index);
if (c != nullptr) {
if (c->name_1 != 0) GenerateCompanyName(c);
if (c->bankrupt_asked != 0) HandleBankruptcyTakeover(c);
}
if (_new_competitor_timeout.HasFired() && _game_mode != GM_MENU && AI::CanStartNew()) {
int32_t timeout = _settings_game.difficulty.competitors_interval * 60 * Ticks::TICKS_PER_SECOND;
/* If the interval is zero, start as many competitors as needed then check every ~10 minutes if a company went bankrupt and needs replacing. */
if (timeout == 0) {
/* count number of competitors */
uint8_t n = 0;
for (const Company *cc : Company::Iterate()) {
if (cc->is_ai) n++;
}
for (auto i = 0; i < _settings_game.difficulty.max_no_competitors; i++) {
if (_networking && Company::GetNumItems() >= _settings_client.network.max_companies) break;
if (n++ >= _settings_game.difficulty.max_no_competitors) break;
Command<CMD_COMPANY_CTRL>::Post(CCA_NEW_AI, INVALID_COMPANY, CRR_NONE, INVALID_CLIENT_ID);
}
timeout = 10 * 60 * Ticks::TICKS_PER_SECOND;
}
/* Randomize a bit when the AI is actually going to start; ranges from 87.5% .. 112.5% of indicated value. */
timeout += ScriptObject::GetRandomizer(OWNER_NONE).Next(timeout / 4) - timeout / 8;
_new_competitor_timeout.Reset(std::max(1, timeout));
}
_cur_company_tick_index = (_cur_company_tick_index + 1) % MAX_COMPANIES;
}
/**
* A year has passed, update the economic data of all companies, and perhaps show the
* financial overview window of the local company.
*/
static IntervalTimer<TimerGameEconomy> _economy_companies_yearly({TimerGameEconomy::YEAR, TimerGameEconomy::Priority::COMPANY}, [](auto)
{
/* Copy statistics */
for (Company *c : Company::Iterate()) {
/* Move expenses to previous years. */
std::rotate(std::rbegin(c->yearly_expenses), std::rbegin(c->yearly_expenses) + 1, std::rend(c->yearly_expenses));
c->yearly_expenses[0] = {};
SetWindowDirty(WC_FINANCES, c->index);
}
if (_settings_client.gui.show_finances && _local_company != COMPANY_SPECTATOR) {
ShowCompanyFinances(_local_company);
Company *c = Company::Get(_local_company);
if (c->num_valid_stat_ent > 5 && c->old_economy[0].performance_history < c->old_economy[4].performance_history) {
if (_settings_client.sound.new_year) SndPlayFx(SND_01_BAD_YEAR);
} else {
if (_settings_client.sound.new_year) SndPlayFx(SND_00_GOOD_YEAR);
}
}
});
/**
* Fill the CompanyNewsInformation struct with the required data.
* @param c the current company.
* @param other the other company (use \c nullptr if not relevant).
*/
CompanyNewsInformation::CompanyNewsInformation(const Company *c, const Company *other)
{
SetDParam(0, c->index);
this->company_name = GetString(STR_COMPANY_NAME);
if (other != nullptr) {
SetDParam(0, other->index);
this->other_company_name = GetString(STR_COMPANY_NAME);
c = other;
}
SetDParam(0, c->index);
this->president_name = GetString(STR_PRESIDENT_NAME_MANAGER);
this->colour = c->colour;
this->face = c->face;
}
/**
* Called whenever company related information changes in order to notify admins.
* @param company The company data changed of.
*/
void CompanyAdminUpdate(const Company *company)
{
if (_network_server) NetworkAdminCompanyUpdate(company);
}
/**
* Called whenever a company is removed in order to notify admins.
* @param company_id The company that was removed.
* @param reason The reason the company was removed.
*/
void CompanyAdminRemove(CompanyID company_id, CompanyRemoveReason reason)
{
if (_network_server) NetworkAdminCompanyRemove(company_id, (AdminCompanyRemoveReason)reason);
}
/**
* Control the companies: add, delete, etc.
* @param flags operation to perform
* @param cca action to perform
* @param company_id company to perform the action on
* @param client_id ClientID
* @return the cost of this operation or an error
*/
CommandCost CmdCompanyCtrl(DoCommandFlag flags, CompanyCtrlAction cca, CompanyID company_id, CompanyRemoveReason reason, ClientID client_id)
{
InvalidateWindowData(WC_COMPANY_LEAGUE, 0, 0);
switch (cca) {
case CCA_NEW: { // Create a new company
/* This command is only executed in a multiplayer game */
if (!_networking) return CMD_ERROR;
/* Has the network client a correct ClientIndex? */
if (!(flags & DC_EXEC)) return CommandCost();
NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id);
/* Delete multiplayer progress bar */
CloseWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN);
Company *c = DoStartupNewCompany(false);
/* A new company could not be created, revert to being a spectator */
if (c == nullptr) {
/* We check for "ci != nullptr" as a client could have left by
* the time we execute this command. */
if (_network_server && ci != nullptr) {
ci->client_playas = COMPANY_SPECTATOR;
NetworkUpdateClientInfo(ci->client_id);
}
break;
}
/* This is the client (or non-dedicated server) who wants a new company */
if (client_id == _network_own_client_id) {
assert(_local_company == COMPANY_SPECTATOR);
SetLocalCompany(c->index);
if (!_settings_client.network.default_company_pass.empty()) {
NetworkChangeCompanyPassword(_local_company, _settings_client.network.default_company_pass);
}
/* In network games, we need to try setting the company manager face here to sync it to all clients.
* If a favorite company manager face is selected, choose it. Otherwise, use a random face. */
if (_company_manager_face != 0) Command<CMD_SET_COMPANY_MANAGER_FACE>::SendNet(STR_NULL, c->index, _company_manager_face);
/* Now that we have a new company, broadcast our company settings to
* all clients so everything is in sync */
SyncCompanySettings();
MarkWholeScreenDirty();
}
NetworkServerNewCompany(c, ci);
break;
}
case CCA_NEW_AI: { // Make a new AI company
if (company_id != INVALID_COMPANY && company_id >= MAX_COMPANIES) return CMD_ERROR;
/* For network games, company deletion is delayed. */
if (!_networking && company_id != INVALID_COMPANY && Company::IsValidID(company_id)) return CMD_ERROR;
if (!(flags & DC_EXEC)) return CommandCost();
/* For network game, just assume deletion happened. */
assert(company_id == INVALID_COMPANY || !Company::IsValidID(company_id));
Company *c = DoStartupNewCompany(true, company_id);
if (c != nullptr) NetworkServerNewCompany(c, nullptr);
break;
}
case CCA_DELETE: { // Delete a company
if (reason >= CRR_END) return CMD_ERROR;
/* We can't delete the last existing company in singleplayer mode. */
if (!_networking && Company::GetNumItems() == 1) return CMD_ERROR;
Company *c = Company::GetIfValid(company_id);
if (c == nullptr) return CMD_ERROR;
if (!(flags & DC_EXEC)) return CommandCost();
CompanyNewsInformation *cni = new CompanyNewsInformation(c);
/* Show the bankrupt news */
SetDParam(0, STR_NEWS_COMPANY_BANKRUPT_TITLE);
SetDParam(1, STR_NEWS_COMPANY_BANKRUPT_DESCRIPTION);
SetDParamStr(2, cni->company_name);
AddCompanyNewsItem(STR_MESSAGE_NEWS_FORMAT, cni);
/* Remove the company */
ChangeOwnershipOfCompanyItems(c->index, INVALID_OWNER);
if (c->is_ai) AI::Stop(c->index);
CompanyID c_index = c->index;
delete c;
AI::BroadcastNewEvent(new ScriptEventCompanyBankrupt(c_index));
Game::NewEvent(new ScriptEventCompanyBankrupt(c_index));
CompanyAdminRemove(c_index, (CompanyRemoveReason)reason);
if (StoryPage::GetNumItems() == 0 || Goal::GetNumItems() == 0) InvalidateWindowData(WC_MAIN_TOOLBAR, 0);
InvalidateWindowData(WC_CLIENT_LIST, 0);
break;
}
default: return CMD_ERROR;
}
InvalidateWindowClassesData(WC_GAME_OPTIONS);
InvalidateWindowClassesData(WC_SCRIPT_SETTINGS);
InvalidateWindowClassesData(WC_SCRIPT_LIST);
return CommandCost();
}
/**
* Change the company manager's face.
* @param flags operation to perform
* @param cmf face bitmasked
* @return the cost of this operation or an error
*/
CommandCost CmdSetCompanyManagerFace(DoCommandFlag flags, CompanyManagerFace cmf)
{
if (!IsValidCompanyManagerFace(cmf)) return CMD_ERROR;
if (flags & DC_EXEC) {
Company::Get(_current_company)->face = cmf;
MarkWholeScreenDirty();
}
return CommandCost();
}
/**
* Update liveries for a company. This is called when the LS_DEFAULT scheme is changed, to update schemes with colours
* set to default.
* @param c Company to update.
*/
void UpdateCompanyLiveries(Company *c)
{
for (int i = 1; i < LS_END; i++) {
if (!HasBit(c->livery[i].in_use, 0)) c->livery[i].colour1 = c->livery[LS_DEFAULT].colour1;
if (!HasBit(c->livery[i].in_use, 1)) c->livery[i].colour2 = c->livery[LS_DEFAULT].colour2;
}
UpdateCompanyGroupLiveries(c);
}
/**
* Change the company's company-colour
* @param flags operation to perform
* @param scheme scheme to set
* @param primary set first/second colour
* @param colour new colour for vehicles, property, etc.
* @return the cost of this operation or an error
*/
CommandCost CmdSetCompanyColour(DoCommandFlag flags, LiveryScheme scheme, bool primary, Colours colour)
{
if (scheme >= LS_END || (colour >= COLOUR_END && colour != INVALID_COLOUR)) return CMD_ERROR;
/* Default scheme can't be reset to invalid. */
if (scheme == LS_DEFAULT && colour == INVALID_COLOUR) return CMD_ERROR;
Company *c = Company::Get(_current_company);
/* Ensure no two companies have the same primary colour */
if (scheme == LS_DEFAULT && primary) {
for (const Company *cc : Company::Iterate()) {
if (cc != c && cc->colour == colour) return CMD_ERROR;
}
}
if (flags & DC_EXEC) {
if (primary) {
if (scheme != LS_DEFAULT) SB(c->livery[scheme].in_use, 0, 1, colour != INVALID_COLOUR);
if (colour == INVALID_COLOUR) colour = c->livery[LS_DEFAULT].colour1;
c->livery[scheme].colour1 = colour;
/* If setting the first colour of the default scheme, adjust the
* original and cached company colours too. */
if (scheme == LS_DEFAULT) {
UpdateCompanyLiveries(c);
_company_colours[_current_company] = colour;
c->colour = colour;
CompanyAdminUpdate(c);
}
} else {
if (scheme != LS_DEFAULT) SB(c->livery[scheme].in_use, 1, 1, colour != INVALID_COLOUR);
if (colour == INVALID_COLOUR) colour = c->livery[LS_DEFAULT].colour2;
c->livery[scheme].colour2 = colour;
if (scheme == LS_DEFAULT) {
UpdateCompanyGroupLiveries(c);
}
}
if (c->livery[scheme].in_use != 0) {
/* If enabling a scheme, set the default scheme to be in use too */
c->livery[LS_DEFAULT].in_use = 1;
} else {
/* Else loop through all schemes to see if any are left enabled.
* If not, disable the default scheme too. */
c->livery[LS_DEFAULT].in_use = 0;
for (scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
if (c->livery[scheme].in_use != 0) {
c->livery[LS_DEFAULT].in_use = 1;
break;
}
}
}
ResetVehicleColourMap();
MarkWholeScreenDirty();
/* All graph related to companies use the company colour. */
InvalidateWindowData(WC_INCOME_GRAPH, 0);
InvalidateWindowData(WC_OPERATING_PROFIT, 0);
InvalidateWindowData(WC_DELIVERED_CARGO, 0);
InvalidateWindowData(WC_PERFORMANCE_HISTORY, 0);
InvalidateWindowData(WC_COMPANY_VALUE, 0);
InvalidateWindowData(WC_LINKGRAPH_LEGEND, 0);
/* The smallmap owner view also stores the company colours. */
BuildOwnerLegend();
InvalidateWindowData(WC_SMALLMAP, 0, 1);
/* Company colour data is indirectly cached. */
for (Vehicle *v : Vehicle::Iterate()) {
if (v->owner == _current_company) v->InvalidateNewGRFCache();
}
UpdateObjectColours(c);
}
return CommandCost();
}
/**
* Is the given name in use as name of a company?
* @param name Name to search.
* @return \c true if the name us unique (that is, not in use), else \c false.
*/
static bool IsUniqueCompanyName(const std::string &name)
{
for (const Company *c : Company::Iterate()) {
if (!c->name.empty() && c->name == name) return false;
}
return true;
}
/**
* Change the name of the company.
* @param flags operation to perform
* @param text the new name or an empty string when resetting to the default
* @return the cost of this operation or an error
*/
CommandCost CmdRenameCompany(DoCommandFlag flags, const std::string &text)
{
bool reset = text.empty();
if (!reset) {
if (Utf8StringLength(text) >= MAX_LENGTH_COMPANY_NAME_CHARS) return CMD_ERROR;
if (!IsUniqueCompanyName(text)) return_cmd_error(STR_ERROR_NAME_MUST_BE_UNIQUE);
}
if (flags & DC_EXEC) {
Company *c = Company::Get(_current_company);
if (reset) {
c->name.clear();
} else {
c->name = text;
}
MarkWholeScreenDirty();
CompanyAdminUpdate(c);
}
return CommandCost();
}
/**
* Is the given name in use as president name of a company?
* @param name Name to search.
* @return \c true if the name us unique (that is, not in use), else \c false.
*/
static bool IsUniquePresidentName(const std::string &name)
{
for (const Company *c : Company::Iterate()) {
if (!c->president_name.empty() && c->president_name == name) return false;
}
return true;
}
/**
* Change the name of the president.
* @param flags operation to perform
* @param text the new name or an empty string when resetting to the default
* @return the cost of this operation or an error
*/
CommandCost CmdRenamePresident(DoCommandFlag flags, const std::string &text)
{
bool reset = text.empty();
if (!reset) {
if (Utf8StringLength(text) >= MAX_LENGTH_PRESIDENT_NAME_CHARS) return CMD_ERROR;
if (!IsUniquePresidentName(text)) return_cmd_error(STR_ERROR_NAME_MUST_BE_UNIQUE);
}
if (flags & DC_EXEC) {
Company *c = Company::Get(_current_company);
if (reset) {
c->president_name.clear();
} else {
c->president_name = text;
if (c->name_1 == STR_SV_UNNAMED && c->name.empty()) {
Command<CMD_RENAME_COMPANY>::Do(DC_EXEC, text + " Transport");
}
}
MarkWholeScreenDirty();
CompanyAdminUpdate(c);
}
return CommandCost();
}
/**
* Get the service interval for the given company and vehicle type.
* @param c The company, or nullptr for client-default settings.
* @param type The vehicle type to get the interval for.
* @return The service interval.
*/
int CompanyServiceInterval(const Company *c, VehicleType type)
{
const VehicleDefaultSettings *vds = (c == nullptr) ? &_settings_client.company.vehicle : &c->settings.vehicle;
switch (type) {
default: NOT_REACHED();
case VEH_TRAIN: return vds->servint_trains;
case VEH_ROAD: return vds->servint_roadveh;
case VEH_AIRCRAFT: return vds->servint_aircraft;
case VEH_SHIP: return vds->servint_ships;
}
}
/**
* Get total sum of all owned road bits.
* @return Combined total road road bits.
*/
uint32_t CompanyInfrastructure::GetRoadTotal() const
{
uint32_t total = 0;
for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) {
if (RoadTypeIsRoad(rt)) total += this->road[rt];
}
return total;
}
/**
* Get total sum of all owned tram bits.
* @return Combined total of tram road bits.
*/
uint32_t CompanyInfrastructure::GetTramTotal() const
{
uint32_t total = 0;
for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) {
if (RoadTypeIsTram(rt)) total += this->road[rt];
}
return total;
}
/**
* Transfer funds (money) from one company to another.
* To prevent abuse in multiplayer games you can only send money to other
* companies if you have paid off your loan (either explicitly, or implicitly
* given the fact that you have more money than loan).
* @param flags operation to perform
* @param money the amount of money to transfer; max 20.000.000
* @param dest_company the company to transfer the money to
* @return the cost of this operation or an error
*/
CommandCost CmdGiveMoney(DoCommandFlag flags, Money money, CompanyID dest_company)
{
if (!_settings_game.economy.give_money) return CMD_ERROR;
const Company *c = Company::Get(_current_company);
CommandCost amount(EXPENSES_OTHER, std::min<Money>(money, 20000000LL));
/* You can only transfer funds that is in excess of your loan */
if (c->money - c->current_loan < amount.GetCost() || amount.GetCost() < 0) return_cmd_error(STR_ERROR_INSUFFICIENT_FUNDS);
if (!Company::IsValidID(dest_company)) return CMD_ERROR;
if (flags & DC_EXEC) {
/* Add money to company */
Backup<CompanyID> cur_company(_current_company, dest_company, FILE_LINE);
SubtractMoneyFromCompany(CommandCost(EXPENSES_OTHER, -amount.GetCost()));
cur_company.Restore();
if (_networking) {
SetDParam(0, dest_company);
std::string dest_company_name = GetString(STR_COMPANY_NAME);
SetDParam(0, _current_company);
std::string from_company_name = GetString(STR_COMPANY_NAME);
NetworkTextMessage(NETWORK_ACTION_GIVE_MONEY, GetDrawStringCompanyColour(_current_company), false, from_company_name, dest_company_name, amount.GetCost());
}
}
/* Subtract money from local-company */
return amount;
}
/**
* Get the index of the first available company. It attempts,
* from first to last, and as soon as the attempt succeeds,
* to get the index of the company:
* 1st - get the first existing human company.
* 2nd - get the first non-existing company.
* 3rd - get COMPANY_FIRST.
* @return the index of the first available company.
*/
CompanyID GetFirstPlayableCompanyID()
{
for (Company *c : Company::Iterate()) {
if (Company::IsHumanID(c->index)) {
return c->index;
}
}
if (Company::CanAllocateItem()) {
for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
if (!Company::IsValidID(c)) {
return c;
}
}
}
return COMPANY_FIRST;
}
|