mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-08-25 07:29:10 +00:00
Compare commits
691 Commits
12.0-beta2
...
13.0-beta2
Author | SHA1 | Date | |
---|---|---|---|
|
1c82200e0f | ||
a7ffd47c64 | |||
|
35c4af5cb7 | ||
|
8a78fa7121 | ||
|
5e14a20b3b | ||
|
b9ce3de23d | ||
|
b846c574d7 | ||
|
e29547a3a2 | ||
|
d780ca74ed | ||
|
0fc7cdb1e4 | ||
53682b4b6b | |||
|
e85d2603d9 | ||
|
afbad255d3 | ||
|
62125c9e76 | ||
a7adadcf9b | |||
|
a942028803 | ||
a044e8e007 | |||
|
3040efdb10 | ||
60404c3aea | |||
9bf24ec56f | |||
c81c242c5a | |||
6ea3e7e487 | |||
|
bc5cd4eeda | ||
|
d30345edfb | ||
|
cbb2d5303d | ||
|
0d631a6fda | ||
|
adf94d7970 | ||
|
bba1a16836 | ||
|
553e5e6bbe | ||
cea62ef73d | |||
|
89a2d0a605 | ||
|
ced4258969 | ||
dff03124e5 | |||
ecb5393c55 | |||
920e588334 | |||
9666e46739 | |||
13d271217f | |||
ed60c88b0a | |||
062ea68422 | |||
dd90d79e7b | |||
e554fd7808 | |||
890b2666d3 | |||
61da064b82 | |||
123983743f | |||
f0ae111c4a | |||
64a1fc174f | |||
1180c95372 | |||
d35f1d3d06 | |||
23a8222200 | |||
90ce704366 | |||
0bb9a45785 | |||
d0add1e07f | |||
b5693becdc | |||
b6ed595176 | |||
0108e9f387 | |||
68423c40c5 | |||
47f4fc6a70 | |||
dd9f6bc803 | |||
04cbe57d2a | |||
75b222b0d9 | |||
5786d49143 | |||
46a1ab0937 | |||
c9a81fd67b | |||
3ff05321dc | |||
1f1378c129 | |||
cb059fc081 | |||
fea7247072 | |||
6f95e04005 | |||
cb10ed1509 | |||
cd0d5a771d | |||
f5f035a22b | |||
632464a623 | |||
d8e01f8aa5 | |||
17d1fe26c2 | |||
eb4ba1991b | |||
18201dfbc3 | |||
ab55d3e1fa | |||
|
7c3c92f8b8 | ||
|
59645c6733 | ||
|
64b437fa89 | ||
|
0fae0599b7 | ||
|
a962d7476b | ||
|
5d6cdf4385 | ||
|
3f579fa7dc | ||
|
cbac243216 | ||
|
fd4f148c62 | ||
|
27e1d057c5 | ||
|
e2f661b281 | ||
|
0d303d6c3f | ||
|
a8a7f95665 | ||
|
59dbcdb5ba | ||
|
b304c06a4a | ||
|
89cf0d5da8 | ||
|
019dcb7b7b | ||
|
ede0560f9b | ||
|
31d08421ab | ||
|
62a15734fe | ||
|
60ccab3c52 | ||
|
d738cd235f | ||
|
b7abaa55a3 | ||
|
8c4a70e05e | ||
|
b6a899eb2b | ||
|
e931f3061f | ||
|
7711907a6b | ||
22803f997b | |||
|
4dc741a8a0 | ||
|
c294e8b19f | ||
|
0172eb39a2 | ||
|
c719ba560e | ||
|
fea6a34684 | ||
|
21cea308f9 | ||
|
3b3c9c1c3a | ||
|
d48a48b2cf | ||
f24286a1ae | |||
|
accbfd502e | ||
|
0d51460f27 | ||
|
71663bbaee | ||
|
648cd1076b | ||
|
d5aafaee15 | ||
4031894aef | |||
|
35d9cea487 | ||
|
aa06b73137 | ||
|
c19abebf8d | ||
|
c65a2799c9 | ||
|
c4e655b1d4 | ||
|
ac7780af96 | ||
|
b9635c4712 | ||
|
36084684ba | ||
|
bf8dc7b157 | ||
|
191ea087eb | ||
|
8bf56f39f2 | ||
|
f8a7b76675 | ||
|
c5369caa45 | ||
|
25b3ff6423 | ||
|
b0fd51a5ef | ||
|
bfa155eb06 | ||
|
dd44f2139e | ||
|
845174914d | ||
|
0afa6f2424 | ||
|
4052feef1f | ||
b04298f131 | |||
|
3a11a2ed0e | ||
|
1e3e30c096 | ||
ef8322ba25 | |||
|
e7a16f4514 | ||
|
c536bde19e | ||
|
721d98a7d0 | ||
|
a4052ca348 | ||
|
7e7d943526 | ||
|
227626b0b7 | ||
|
a9a21e784d | ||
|
4daad7f348 | ||
|
a394be2780 | ||
|
30ff89cac0 | ||
|
664771d085 | ||
|
520520c11c | ||
|
87d1bd895a | ||
|
8ffe59373f | ||
|
f6530f3c2d | ||
|
864771ca09 | ||
|
7c79a2a767 | ||
|
e660860d4b | ||
|
65530a76f6 | ||
|
93d2d4590f | ||
|
47a998fb0c | ||
|
252111512f | ||
|
35c1aeb6d1 | ||
|
f7eb0ffc37 | ||
|
8e6ed8d5e9 | ||
|
10daaca5ea | ||
|
a0342fb170 | ||
|
3b071f47e4 | ||
|
47456ac672 | ||
|
f9cdb5b610 | ||
|
da1a0d042e | ||
|
c7505539af | ||
|
be7db78767 | ||
|
8d0d45c431 | ||
|
3d45bc4abe | ||
|
bd357656ba | ||
|
e604b76d18 | ||
|
3dda8c9bad | ||
|
45d98f689a | ||
|
bda602f4b0 | ||
|
f4e2a462fe | ||
5cc1a48db7 | |||
ba94efba87 | |||
dc1b84aa1e | |||
0e3400894f | |||
296af146fb | |||
|
db98cedb7e | ||
3e86f337a8 | |||
ccb62c3a55 | |||
edbf99ed17 | |||
33704269bd | |||
686204ff1c | |||
e8edecf6b1 | |||
fc944829e1 | |||
|
887b760c88 | ||
|
9059215b3b | ||
|
24f3022ee0 | ||
|
c482f05616 | ||
|
d0dcb6547e | ||
|
633b903f16 | ||
|
c7f55a058b | ||
af6c4d50ce | |||
8626090b24 | |||
|
f011a559d0 | ||
|
73e5c57e6b | ||
|
f3fd9b5895 | ||
|
d843c8bd48 | ||
|
e5203f3409 | ||
|
bdc17b18e1 | ||
|
faa382beda | ||
|
761105aaa4 | ||
b00e18fe9f | |||
2cdd8b7429 | |||
f6ad8e1c9c | |||
273988551d | |||
0c20a5f39f | |||
|
93b711d70d | ||
|
70d33dc71f | ||
|
2b29f1a181 | ||
d7ceb7efea | |||
69527abb6f | |||
|
1f04cc62d9 | ||
607ef09fa5 | |||
|
548f0496a9 | ||
|
164ec3ac07 | ||
|
07443969f9 | ||
|
6d84b1e108 | ||
|
a4e00c5cb5 | ||
|
5e413c9dcd | ||
|
20f7ff8ac0 | ||
|
0a7ffae0d9 | ||
0bac74ec2b | |||
f59f0195e3 | |||
fa5e2ca276 | |||
8e9ca5ebcb | |||
|
81388d9425 | ||
|
0c8db77154 | ||
|
b38051c9ad | ||
|
984e0b1263 | ||
|
d29289addb | ||
|
57717a20d3 | ||
|
64453cb134 | ||
|
e5643c65c1 | ||
|
129979acf7 | ||
|
039f90d05f | ||
|
e2c46fda3f | ||
|
5c66de860d | ||
|
f7022925d3 | ||
|
a06d323f03 | ||
f279fc5772 | |||
|
0355299639 | ||
|
0c848a9b3b | ||
|
18c210b013 | ||
2d2a5dd966 | |||
8b989d4999 | |||
|
57fa8690df | ||
|
8ac0ab47b0 | ||
|
15f4d7c04c | ||
|
54ac304828 | ||
|
c839950791 | ||
|
9529703cab | ||
|
2fe8a257ac | ||
|
31668b8f94 | ||
|
788b06fe0f | ||
|
3937953f72 | ||
|
5a0dd7e322 | ||
|
4253db28fa | ||
|
db378e746b | ||
|
e6aab701c9 | ||
|
aaab0610eb | ||
|
c6953f13e4 | ||
|
dcdc8d187c | ||
|
acf9d786f1 | ||
|
bba6ad1f4e | ||
|
e9507e7ffa | ||
|
04911822c1 | ||
|
e3968cdf65 | ||
|
882b8f45d9 | ||
|
417f9bb48d | ||
|
88a046a76e | ||
|
be352ce1b6 | ||
|
eb805b77b7 | ||
|
374f0c7d11 | ||
|
6893135fef | ||
|
5a404a17ee | ||
|
6b4fd01eeb | ||
|
b7462934e2 | ||
|
ccb9d99880 | ||
|
e3759931e7 | ||
|
97d79c8e52 | ||
|
d1d7e47896 | ||
|
77a8e3b649 | ||
|
6d154e72dd | ||
|
67608350b6 | ||
|
67331fe946 | ||
|
8f772352ce | ||
|
b199779ad4 | ||
|
77a85e9b4c | ||
|
979704271b | ||
|
055121df80 | ||
|
100aca1848 | ||
|
9957675a66 | ||
|
4651ad94fe | ||
|
6810d09c1b | ||
|
dd93244853 | ||
|
19af139631 | ||
|
f72b9fa767 | ||
|
ffd3c11ba7 | ||
|
68257e0d7d | ||
|
f64cf8679d | ||
|
278c1d06cf | ||
|
79af42e992 | ||
|
4acccc232a | ||
|
814c61a321 | ||
|
470c902bdc | ||
|
2cdb0cb084 | ||
|
0d3756818f | ||
|
8cdf303e72 | ||
|
0a3d5f5ff8 | ||
|
aeeee9f18e | ||
|
675cf7a8ee | ||
|
9fca8af586 | ||
|
a59c19c6c2 | ||
|
5587e439a9 | ||
|
578bb6638f | ||
|
e3a4524133 | ||
|
906613e83a | ||
|
ed1457dca3 | ||
|
992c72c0cb | ||
|
57230c559b | ||
|
d89e7484c8 | ||
|
59f16b1a38 | ||
|
8d8f45f0dd | ||
|
3a2c0531b6 | ||
|
b1e24a0ae3 | ||
|
9d979a6d23 | ||
|
9842e8b762 | ||
|
f8c6034b93 | ||
|
fd1aa154f4 | ||
|
adc76cca54 | ||
|
9bdc1e8f04 | ||
|
19b838dd60 | ||
|
9162ac9d37 | ||
|
2a2f80bb71 | ||
|
33dabc42bb | ||
|
6540948ace | ||
|
fa562ba041 | ||
|
37d318c410 | ||
|
24d7697acc | ||
|
1eed52f294 | ||
|
84aec4fcb8 | ||
|
ebc76a4200 | ||
|
646d160c38 | ||
|
273b33b087 | ||
|
8d51156150 | ||
|
867f6a5964 | ||
|
9c58ea7a37 | ||
|
5e5f864990 | ||
|
0dce7bf85d | ||
|
588fee5473 | ||
|
c6e4fa7df1 | ||
|
146827c458 | ||
|
142321da79 | ||
|
1ed212775c | ||
|
5a6ea11ead | ||
|
5b86bce7b2 | ||
|
345dcd3c7b | ||
|
be72f1e54b | ||
|
b8565d8cac | ||
|
e5c1865e76 | ||
|
7331149dde | ||
|
fb1ac307a4 | ||
|
ec90fb4c99 | ||
|
5ea55f3948 | ||
|
1cfdbb4dea | ||
|
41de69c5b7 | ||
|
f4ca94d3f6 | ||
|
e79724ea22 | ||
|
b3893878bb | ||
|
ed0b0b80d3 | ||
|
4e09dbc86e | ||
|
cc4186410b | ||
|
869b645708 | ||
|
6c161ad18a | ||
|
44713a68ed | ||
|
6204020b6a | ||
|
6cb668955e | ||
|
585e49a597 | ||
|
bcf26f8ec0 | ||
|
98bdf01967 | ||
|
ef4b699f40 | ||
|
a24ba6c264 | ||
|
3cf0e95f6e | ||
|
7c40967c1f | ||
|
385c2f1381 | ||
|
49b8eac2dc | ||
|
1ae34ca62d | ||
|
bd6531d0d0 | ||
|
5dd9400fe2 | ||
|
ee105257ff | ||
|
a6ada35259 | ||
|
c36fc98137 | ||
|
1c580d1612 | ||
|
f92cf38ab5 | ||
|
8537fa7206 | ||
|
148695c571 | ||
|
1bfbcff71e | ||
|
7a97a33598 | ||
|
61c6fd3055 | ||
|
8d54f76539 | ||
|
0d9fdeda8e | ||
|
1a17b6c8f6 | ||
|
08a5478a93 | ||
|
68ec2a7877 | ||
|
d220debc6c | ||
|
fbbc80f79e | ||
|
c73f578e8c | ||
|
2bfceea762 | ||
|
0d8fbf647b | ||
|
acaea776eb | ||
|
1c256a4be7 | ||
|
89dba56782 | ||
|
22f6502b14 | ||
|
36bee83864 | ||
|
e68bf58989 | ||
|
41c40f130b | ||
|
81adc38176 | ||
|
8028794bee | ||
|
a83cd9b4f5 | ||
|
83b6defbfb | ||
|
7f0efbe00e | ||
|
25ae42ae8a | ||
|
b6c5f49379 | ||
|
d9a37c915f | ||
|
09b71c97aa | ||
|
b59acc7e2c | ||
|
4ad6b1e58d | ||
|
30da75941b | ||
|
6ccf020dc2 | ||
|
61abfc9050 | ||
|
9e47df298f | ||
|
b8a8891a86 | ||
|
26ac0c48f0 | ||
|
f6775a2d55 | ||
|
5239018878 | ||
|
15c9191568 | ||
|
8ac3f9a6e1 | ||
|
93e8d4871d | ||
|
ad54d08abd | ||
|
32a4212ef1 | ||
|
8032423bf1 | ||
|
54ce5b28a4 | ||
|
5777649ac4 | ||
|
ffa688a432 | ||
|
d62c5667cf | ||
|
57b992717b | ||
|
69c8ed9965 | ||
|
b351cbe490 | ||
|
f40e82a19d | ||
|
80fc5fb46c | ||
|
4844268d1c | ||
|
21f85cac87 | ||
|
c85557e553 | ||
|
3ed7910cfe | ||
|
a97bce51c2 | ||
|
30d0f06890 | ||
|
f6e6b2c917 | ||
|
afb817fe19 | ||
|
b11bd185e3 | ||
|
9c18236f2c | ||
|
e67124e174 | ||
|
3fede15940 | ||
|
e08a6e2014 | ||
|
e890e7db76 | ||
|
afc3d71fd0 | ||
|
c521b965bd | ||
|
2e39637db2 | ||
|
41fa16f325 | ||
|
57b82e2e99 | ||
|
3e85e833a7 | ||
|
8503854655 | ||
|
d85348b1d1 | ||
|
13528bfcd0 | ||
|
58cff7b081 | ||
|
c6d7b98808 | ||
|
e6e69d5289 | ||
|
1a42a8a5d5 | ||
|
e08b3abe7f | ||
|
46bd2f1ced | ||
|
55170ae703 | ||
|
6fe445e6c0 | ||
|
21675ec7e2 | ||
|
2637c06f88 | ||
|
211c630cbe | ||
|
de45a8729c | ||
|
4f3ea3907e | ||
|
ccefa76a46 | ||
|
6691ee3b96 | ||
|
eab18f06a4 | ||
|
0f64ee5ce1 | ||
|
e740c24eb7 | ||
|
c88b104ec6 | ||
|
996b16de70 | ||
|
a05fd7aa50 | ||
|
b0990fcff7 | ||
|
4fc055d6e9 | ||
|
123c7f99c3 | ||
|
7048e1522f | ||
|
33ca4f2b99 | ||
|
5ddfdc8516 | ||
|
a38bbefe1b | ||
|
549caca39c | ||
|
b6933a2ebd | ||
|
39e8783f4b | ||
|
0c90326ada | ||
|
bc22e9333e | ||
|
762b656b53 | ||
|
ad89601c49 | ||
|
ea4f6bb8b2 | ||
|
9c36c12c85 | ||
|
802ca4e722 | ||
|
6953df7b5e | ||
|
e0a91d7325 | ||
|
ad7bdeb73a | ||
|
20a30825a0 | ||
|
793de48e89 | ||
|
ad90e88ebd | ||
|
54951e39a1 | ||
|
2cb6351af5 | ||
|
0533b666b7 | ||
|
f6886754ff | ||
|
fc58ed9987 | ||
|
cf16f452da | ||
|
0cbe94256e | ||
|
5f6303f985 | ||
|
f8efab4653 | ||
|
2f72eb0657 | ||
|
62795a2e6d | ||
|
4bcbcbc58f | ||
|
7d40cc9291 | ||
|
48c1c7f221 | ||
|
236f71640c | ||
|
0ad40ee868 | ||
|
e9cb9c1135 | ||
|
c38af72978 | ||
|
b4bd7b367e | ||
|
08cb5ba2cd | ||
|
d0655a48ba | ||
|
8c558d74a5 | ||
|
73001ae1a9 | ||
|
95c8467670 | ||
|
6ff0858b38 | ||
|
33ef34189e | ||
|
80e3397f85 | ||
|
9edb75ec0b | ||
|
00a6287f97 | ||
|
ccf70fc4b3 | ||
|
edf7b02ddb | ||
|
488cf26406 | ||
|
4487ad1a5e | ||
|
a0831cec39 | ||
|
279fe11b03 | ||
|
e8bff0ad03 | ||
|
111a47af0d | ||
|
bc984d9af5 | ||
|
bf0210229c | ||
|
b2e83b4da6 | ||
|
08c048e0a1 | ||
|
ae340f415e | ||
|
f2c03a77f0 | ||
|
bc1b84cbbb | ||
|
b043d58b92 | ||
|
eed49d7792 | ||
|
e68a51eced | ||
|
1c0700e0c0 | ||
|
14429bbe8a | ||
|
6289b4dd81 | ||
|
53e17d07d2 | ||
|
5bcdf16dc5 | ||
|
01603d9e47 | ||
|
86c295bb3b | ||
|
e09f251fc6 | ||
|
0853c1979b | ||
|
3b7daca832 | ||
|
78eece71d9 | ||
|
d66dea5d83 | ||
|
4b96244b4d | ||
|
cbe00ec651 | ||
|
207cf7bbdd | ||
|
d0092925c9 | ||
|
7d831be3ab | ||
|
8b157c9bdf | ||
|
d2bc32e94a | ||
|
46123742f5 | ||
|
340a36bf1f | ||
|
3046a6ce39 | ||
|
e404d16929 | ||
|
e4ad632989 | ||
|
2144cd98a3 | ||
|
a53cfeef13 | ||
|
a2cf81e722 | ||
|
585ad9bcab | ||
|
ccd586a736 | ||
|
78d66b7732 | ||
|
41094b6a4a | ||
|
e89be8d97a | ||
|
b4bacff4fe | ||
|
7a48b5597d | ||
|
5e3ed3a05e | ||
|
7aacb2ed8e | ||
|
38a64eb2aa | ||
|
11dece205c | ||
|
14ad424470 | ||
|
9b1651a267 | ||
|
394c749b6b | ||
|
39662aabef | ||
|
66c7d9b8ed | ||
|
4aa63ce8f3 | ||
|
753b1d7e15 | ||
|
16aac9c341 | ||
|
909a83758c | ||
|
7c6b39e189 | ||
|
b5e8b36b5b | ||
|
45edd9f326 | ||
|
31cf9e888b | ||
|
d9f8ed7bdf | ||
7e70ead396 | |||
|
b8f9e24189 | ||
|
0babadfbe4 | ||
|
28d9181d5d | ||
|
cd03bac3dd | ||
|
7acdaaaf2f | ||
|
18247bb3b8 | ||
|
b335b0501c | ||
|
6ce74b2a1b | ||
|
20717ededf | ||
|
6a6dbbaad2 | ||
|
ff6c934916 | ||
|
a53c4f0fb7 | ||
|
19a6513607 | ||
|
a57c2b073a | ||
|
37de878129 | ||
|
c6035158ca | ||
|
c8ab5e58f9 | ||
|
928e6a04e2 | ||
|
d757aa7591 | ||
|
6bd3106681 | ||
|
710b758b81 | ||
|
d4588df9f9 | ||
|
16dca0d7bc | ||
|
ceaff9c9f2 | ||
|
ee57afc285 | ||
|
a8641ea44a | ||
|
9e85f40733 | ||
|
7107e63f8c | ||
|
66620b497b | ||
|
6e3d023e69 | ||
|
7469f00c5b | ||
|
f656b0ae96 | ||
|
9c74dc2468 | ||
|
92559e6f3a | ||
|
63116bd59f | ||
|
2c05412d72 | ||
|
69e9acd702 | ||
|
f87fe395a7 | ||
|
219598a90b | ||
|
80231975e5 | ||
|
d8e870c50c | ||
|
13b53e1290 | ||
|
20ff6fd3f1 | ||
|
8ab267496b | ||
|
8d2162ba2d | ||
|
aa83488fde | ||
|
56d4749ac9 | ||
|
e9f3ddb6ba | ||
|
ef3c4a8737 | ||
|
52d57b17b0 | ||
|
dc5b7b996c | ||
|
e31b5d3870 | ||
|
b2f0491a90 | ||
|
47ce306085 | ||
|
0d26359b5b | ||
|
93fd42b0c3 | ||
|
f939f48cd2 | ||
|
4066a07d8f | ||
|
b83820e723 | ||
|
dd3acccb1b |
1
.github/PULL_REQUEST_TEMPLATE.md
vendored
1
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -39,6 +39,7 @@ Describe here
|
||||
|
||||
Some things are not automated, and forgotten often. This list is a reminder for the reviewers.
|
||||
* The bug fix is important enough to be backported? (label: 'backport requested')
|
||||
* This PR touches english.txt or translations? Check the [guidelines](https://github.com/OpenTTD/OpenTTD/blob/master/docs/eints.md)
|
||||
* This PR affects the save game format? (label 'savegame upgrade')
|
||||
* This PR affects the GS/AI API? (label 'needs review: Script API')
|
||||
* ai_changelog.hpp, gs_changelog.hpp need updating.
|
||||
|
34
.github/stale.yml
vendored
34
.github/stale.yml
vendored
@@ -1,34 +0,0 @@
|
||||
daysUntilClose: 7
|
||||
staleLabel: stale
|
||||
closeComment: false
|
||||
exemptMilestones: true
|
||||
exemptAssignees: true
|
||||
|
||||
issues:
|
||||
daysUntilStale: 60
|
||||
exemptLabels:
|
||||
- pinned
|
||||
- security
|
||||
- "good first issue"
|
||||
- regression
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had any activity in the last two months.
|
||||
|
||||
If you believe the issue is still relevant, please test on the latest nightly and report back.
|
||||
|
||||
It will be closed if no further activity occurs within 7 days.
|
||||
|
||||
Thank you for your contributions.
|
||||
|
||||
pulls:
|
||||
daysUntilStale: 30
|
||||
exemptLabels:
|
||||
- pinned
|
||||
markComment: >
|
||||
This pull request has been automatically marked as stale because it has not had any activity in the last month.
|
||||
|
||||
Please feel free to give a status update now, ping for review, or re-open when it's ready.
|
||||
|
||||
It will be closed if no further activity occurs within 7 days.
|
||||
|
||||
Thank you for your contributions.
|
221
.github/unused-strings.py
vendored
Normal file
221
.github/unused-strings.py
vendored
Normal file
@@ -0,0 +1,221 @@
|
||||
"""
|
||||
Script to scan the OpenTTD source-tree for STR_ entries that are defined but
|
||||
no longer used.
|
||||
|
||||
This is not completely trivial, as OpenTTD references a lot of strings in
|
||||
relation to another string. The most obvious example of this is a list. OpenTTD
|
||||
only references the first entry in the list, and does "+ <var>" to get to the
|
||||
correct string.
|
||||
|
||||
There are other ways OpenTTD does use relative values. This script tries to
|
||||
account for all of them, to give the best approximation we have for "this
|
||||
string is unused".
|
||||
"""
|
||||
|
||||
import glob
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from enum import Enum
|
||||
|
||||
LENGTH_NAME_LOOKUP = {
|
||||
"VEHICLE_TYPES": 4,
|
||||
}
|
||||
|
||||
|
||||
class SkipType(Enum):
|
||||
NONE = 1
|
||||
LENGTH = 2
|
||||
EXTERNAL = 3
|
||||
ZERO_IS_SPECIAL = 4
|
||||
EXPECT_NEWLINE = 5
|
||||
|
||||
|
||||
def read_language_file(filename, strings_found, errors):
|
||||
strings_defined = []
|
||||
|
||||
skip = SkipType.NONE
|
||||
length = 0
|
||||
common_prefix = ""
|
||||
last_tiny_string = ""
|
||||
|
||||
with open(filename) as fp:
|
||||
for line in fp.readlines():
|
||||
if not line.strip():
|
||||
if skip == SkipType.EXPECT_NEWLINE:
|
||||
skip = SkipType.NONE
|
||||
continue
|
||||
|
||||
line = line.strip()
|
||||
|
||||
if skip == SkipType.EXPECT_NEWLINE:
|
||||
# The only thing allowed after a list, is this next marker, or a newline.
|
||||
if line == "###next-name-looks-similar":
|
||||
# "###next-name-looks-similar"
|
||||
# Indicates the common prefix of the last list has a very
|
||||
# similar name to the next entry, but isn't part of the
|
||||
# list. So do not emit a warning about them looking very
|
||||
# similar.
|
||||
|
||||
if length != 0:
|
||||
errors.append(f"ERROR: list around {name} is shorted than indicated by ###length")
|
||||
|
||||
common_prefix = ""
|
||||
else:
|
||||
errors.append(f"ERROR: expected a newline after a list, but didn't find any around {name}. Did you add an entry to the list without increasing the length?")
|
||||
|
||||
skip = SkipType.NONE
|
||||
|
||||
if line[0] == "#":
|
||||
if line.startswith("###length "):
|
||||
# "###length <count>"
|
||||
# Indicates the next few entries are part of a list. Only
|
||||
# the first entry is possibly referenced, and the rest are
|
||||
# indirectly.
|
||||
|
||||
if length != 0:
|
||||
errors.append(f"ERROR: list around {name} is shorted than indicated by ###length")
|
||||
|
||||
length = line.split(" ")[1].strip()
|
||||
|
||||
if length.isnumeric():
|
||||
length = int(length)
|
||||
else:
|
||||
length = LENGTH_NAME_LOOKUP[length]
|
||||
|
||||
skip = SkipType.LENGTH
|
||||
elif line.startswith("###external "):
|
||||
# "###external <count>"
|
||||
# Indicates the next few entries are used outside the
|
||||
# source and will not be referenced.
|
||||
|
||||
if length != 0:
|
||||
errors.append(f"ERROR: list around {name} is shorted than indicated by ###length")
|
||||
|
||||
length = line.split(" ")[1].strip()
|
||||
length = int(length)
|
||||
|
||||
skip = SkipType.EXTERNAL
|
||||
elif line.startswith("###setting-zero-is-special"):
|
||||
# "###setting-zero-is-special"
|
||||
# Indicates the next entry is part of the "zero is special"
|
||||
# flag of settings. These entries are not referenced
|
||||
# directly in the code.
|
||||
|
||||
if length != 0:
|
||||
errors.append(f"ERROR: list around {name} is shorted than indicated by ###length")
|
||||
|
||||
skip = SkipType.ZERO_IS_SPECIAL
|
||||
|
||||
continue
|
||||
|
||||
name = line.split(":")[0].strip()
|
||||
strings_defined.append(name)
|
||||
|
||||
# If a string ends on _TINY or _SMALL, it can be the {TINY} variant.
|
||||
# Check for this by some fuzzy matching.
|
||||
if name.endswith(("_SMALL", "_TINY")):
|
||||
last_tiny_string = name
|
||||
elif last_tiny_string:
|
||||
matching_name = "_".join(last_tiny_string.split("_")[:-1])
|
||||
if name == matching_name:
|
||||
strings_found.add(last_tiny_string)
|
||||
else:
|
||||
last_tiny_string = ""
|
||||
|
||||
if skip == SkipType.EXTERNAL:
|
||||
strings_found.add(name)
|
||||
skip = SkipType.LENGTH
|
||||
|
||||
if skip == SkipType.LENGTH:
|
||||
skip = SkipType.NONE
|
||||
length -= 1
|
||||
common_prefix = name
|
||||
elif skip == SkipType.ZERO_IS_SPECIAL:
|
||||
strings_found.add(name)
|
||||
elif length > 0:
|
||||
strings_found.add(name)
|
||||
length -= 1
|
||||
|
||||
# Find the common prefix of these strings
|
||||
for i in range(len(common_prefix)):
|
||||
if common_prefix[0 : i + 1] != name[0 : i + 1]:
|
||||
common_prefix = common_prefix[0:i]
|
||||
break
|
||||
|
||||
if length == 0:
|
||||
skip = SkipType.EXPECT_NEWLINE
|
||||
|
||||
if len(common_prefix) < 6:
|
||||
errors.append(f"ERROR: common prefix of block including {name} was reduced to {common_prefix}. This means the names in the list are not consistent.")
|
||||
elif common_prefix:
|
||||
if name.startswith(common_prefix):
|
||||
errors.append(f"ERROR: {name} looks a lot like block above with prefix {common_prefix}. This mostly means that the list length was too short. Use '###next-name-looks-similar' if it is not.")
|
||||
common_prefix = ""
|
||||
|
||||
return strings_defined
|
||||
|
||||
|
||||
def scan_source_files(path, strings_found):
|
||||
for new_path in glob.glob(f"{path}/*"):
|
||||
if os.path.isdir(new_path):
|
||||
scan_source_files(new_path, strings_found)
|
||||
continue
|
||||
|
||||
if not new_path.endswith((".c", ".h", ".cpp", ".hpp", ".ini")):
|
||||
continue
|
||||
|
||||
# Most files we can just open, but some use magic, that requires the
|
||||
# G++ preprocessor before we can make sense out of it.
|
||||
if new_path == "src/table/cargo_const.h":
|
||||
p = subprocess.run(["g++", "-E", new_path], stdout=subprocess.PIPE)
|
||||
output = p.stdout.decode()
|
||||
else:
|
||||
with open(new_path) as fp:
|
||||
output = fp.read()
|
||||
|
||||
# Find all the string references.
|
||||
matches = re.findall(r"[^A-Z_](STR_[A-Z0-9_]*)", output)
|
||||
strings_found.update(matches)
|
||||
|
||||
|
||||
def main():
|
||||
strings_found = set()
|
||||
errors = []
|
||||
|
||||
scan_source_files("src", strings_found)
|
||||
strings_defined = read_language_file("src/lang/english.txt", strings_found, errors)
|
||||
|
||||
# STR_LAST_STRINGID is special, and not really a string.
|
||||
strings_found.remove("STR_LAST_STRINGID")
|
||||
# These are mentioned in comments, not really a string.
|
||||
strings_found.remove("STR_XXX")
|
||||
strings_found.remove("STR_NEWS")
|
||||
strings_found.remove("STR_CONTENT_TYPE_")
|
||||
|
||||
# This string is added for completion, but never used.
|
||||
strings_defined.remove("STR_JUST_DATE_SHORT")
|
||||
|
||||
strings_defined = sorted(strings_defined)
|
||||
strings_found = sorted(list(strings_found))
|
||||
|
||||
for string in strings_found:
|
||||
if string not in strings_defined:
|
||||
errors.append(f"ERROR: {string} found but never defined.")
|
||||
|
||||
for string in strings_defined:
|
||||
if string not in strings_found:
|
||||
errors.append(f"ERROR: {string} is (possibly) no longer needed.")
|
||||
|
||||
if errors:
|
||||
for error in errors:
|
||||
print(error)
|
||||
sys.exit(1)
|
||||
else:
|
||||
print("OK")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
35
.github/workflows/ci-build.yml
vendored
35
.github/workflows/ci-build.yml
vendored
@@ -16,17 +16,22 @@ jobs:
|
||||
runs-on: ubuntu-20.04
|
||||
container:
|
||||
# If you change this version, change the number in the cache step too.
|
||||
image: emscripten/emsdk:2.0.10
|
||||
image: emscripten/emsdk:2.0.31
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: /emsdk/upstream/emscripten/cache
|
||||
key: 2.0.10-${{ runner.os }}
|
||||
key: 2.0.31-${{ runner.os }}
|
||||
|
||||
- name: Patch Emscripten to support LZMA
|
||||
run: |
|
||||
cd /emsdk/upstream/emscripten
|
||||
patch -p1 < ${GITHUB_WORKSPACE}/os/emscripten/emsdk-liblzma.patch
|
||||
|
||||
- name: Build (host tools)
|
||||
run: |
|
||||
@@ -77,7 +82,7 @@ jobs:
|
||||
libsdl: libsdl1.2-dev
|
||||
- compiler: gcc
|
||||
cxxcompiler: g++
|
||||
extra-cmake-parameters: -DOPTION_DEDICATED=ON
|
||||
extra-cmake-parameters: -DOPTION_DEDICATED=ON -DCMAKE_CXX_FLAGS_INIT="-DRANDOM_DEBUG"
|
||||
|
||||
runs-on: ubuntu-20.04
|
||||
env:
|
||||
@@ -86,7 +91,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
@@ -161,15 +166,15 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Prepare cache key
|
||||
id: key
|
||||
run: |
|
||||
echo "::set-output name=image::$ImageOS-$ImageVersion"
|
||||
echo "image=$ImageOS-$ImageVersion" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Enable vcpkg cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: /usr/local/share/vcpkg/installed
|
||||
key: ${{ steps.key.outputs.image }}-vcpkg-${{ matrix.arch }}-0 # Increase the number whenever dependencies are modified
|
||||
@@ -232,14 +237,14 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [windows-latest, windows-2016]
|
||||
os: [windows-latest, windows-2019]
|
||||
arch: [x86, x64]
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Prepare cache key
|
||||
id: key
|
||||
@@ -248,10 +253,10 @@ jobs:
|
||||
# Work around caching failure with GNU tar
|
||||
New-Item -Type Junction -Path vcpkg -Target c:\vcpkg
|
||||
|
||||
Write-Output "::set-output name=image::$env:ImageOS-$env:ImageVersion"
|
||||
Write-Output "image=$env:ImageOS-$env:ImageVersion" >> $env:GITHUB_OUTPUT
|
||||
|
||||
- name: Enable vcpkg cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: vcpkg/installed
|
||||
key: ${{ steps.key.outputs.image }}-vcpkg-${{ matrix.arch }}-0 # Increase the number whenever dependencies are modified
|
||||
@@ -333,7 +338,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup MSYS2
|
||||
uses: msys2/setup-msys2@v2
|
||||
@@ -403,4 +408,4 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Check annotations
|
||||
uses: OpenTTD/actions/annotation-check@v2
|
||||
uses: OpenTTD/actions/annotation-check@v3
|
||||
|
2
.github/workflows/commit-checker.yml
vendored
2
.github/workflows/commit-checker.yml
vendored
@@ -10,7 +10,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 4
|
||||
|
||||
|
30
.github/workflows/preview_build.yml
vendored
30
.github/workflows/preview_build.yml
vendored
@@ -12,9 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-20.04
|
||||
container:
|
||||
# If you change this version, change the number in the cache step too.
|
||||
image: emscripten/emsdk:2.0.10
|
||||
# uid=1001(runner) gid=121(docker)
|
||||
options: -u 1001:121
|
||||
image: emscripten/emsdk:2.0.31
|
||||
|
||||
steps:
|
||||
- name: Update deployment status to in progress
|
||||
@@ -33,7 +31,7 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.PREVIEW_GITHUB_TOKEN }}
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.event.client_payload.sha }}
|
||||
|
||||
@@ -43,10 +41,15 @@ jobs:
|
||||
git checkout -b ${name}
|
||||
|
||||
- name: Setup cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: /emsdk/upstream/emscripten/cache
|
||||
key: 2.0.10-${{ runner.os }}
|
||||
key: 2.0.31-${{ runner.os }}
|
||||
|
||||
- name: Patch Emscripten to support LZMA
|
||||
run: |
|
||||
cd /emsdk/upstream/emscripten
|
||||
patch -p1 < ${GITHUB_WORKSPACE}/os/emscripten/emsdk-liblzma.patch
|
||||
|
||||
- name: Build (host tools)
|
||||
run: |
|
||||
@@ -73,7 +76,7 @@ jobs:
|
||||
echo "::group::CMake"
|
||||
emcmake cmake .. \
|
||||
-DHOST_BINARY_DIR=../build-host \
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
# EOF
|
||||
echo "::endgroup::"
|
||||
|
||||
@@ -84,18 +87,15 @@ jobs:
|
||||
|
||||
- name: Publish preview
|
||||
run: |
|
||||
# setuptools is missing in this Docker image, which breaks installing
|
||||
# awscli. So we need to do this in two steps to recover sanity.
|
||||
pip3 install setuptools
|
||||
pip3 install awscli
|
||||
|
||||
~/.local/bin/aws s3 cp --only-show-errors build/openttd.data s3://${{ secrets.PREVIEW_S3_BUCKET }}/${{ github.event.client_payload.folder }}/
|
||||
~/.local/bin/aws s3 cp --only-show-errors build/openttd.html s3://${{ secrets.PREVIEW_S3_BUCKET }}/${{ github.event.client_payload.folder }}/
|
||||
~/.local/bin/aws s3 cp --only-show-errors build/openttd.js s3://${{ secrets.PREVIEW_S3_BUCKET }}/${{ github.event.client_payload.folder }}/
|
||||
~/.local/bin/aws s3 cp --only-show-errors build/openttd.wasm s3://${{ secrets.PREVIEW_S3_BUCKET }}/${{ github.event.client_payload.folder }}/
|
||||
aws s3 cp --only-show-errors build/openttd.data s3://${{ secrets.PREVIEW_S3_BUCKET }}/${{ github.event.client_payload.folder }}/
|
||||
aws s3 cp --only-show-errors build/openttd.html s3://${{ secrets.PREVIEW_S3_BUCKET }}/${{ github.event.client_payload.folder }}/
|
||||
aws s3 cp --only-show-errors build/openttd.js s3://${{ secrets.PREVIEW_S3_BUCKET }}/${{ github.event.client_payload.folder }}/
|
||||
aws s3 cp --only-show-errors build/openttd.wasm s3://${{ secrets.PREVIEW_S3_BUCKET }}/${{ github.event.client_payload.folder }}/
|
||||
|
||||
# Invalidate the cache of the CloudFront distribution
|
||||
~/.local/bin/aws cloudfront create-invalidation --distribution-id ${{ secrets.PREVIEW_CF_DISTRIBUTION_ID }} --paths "/${{ github.event.client_payload.folder }}/*"
|
||||
aws cloudfront create-invalidation --distribution-id ${{ secrets.PREVIEW_CF_DISTRIBUTION_ID }} --paths "/${{ github.event.client_payload.folder }}/*"
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
|
2
.github/workflows/preview_label.yml
vendored
2
.github/workflows/preview_label.yml
vendored
@@ -59,7 +59,7 @@ jobs:
|
||||
|
||||
- if: steps.core_developer.outcome == 'success'
|
||||
name: Trigger 'preview build'
|
||||
uses: peter-evans/repository-dispatch@v1
|
||||
uses: peter-evans/repository-dispatch@v2
|
||||
with:
|
||||
token: ${{ secrets.PREVIEW_GITHUB_TOKEN }}
|
||||
event-type: "Preview build #${{ github.event.number }}"
|
||||
|
2
.github/workflows/preview_push.yml
vendored
2
.github/workflows/preview_push.yml
vendored
@@ -59,7 +59,7 @@ jobs:
|
||||
|
||||
- if: toJson(fromJson(steps.earlier_preview.outputs.data)) != '[]' && contains(fromJson(steps.preview_label.outputs.data).*.name, 'preview')
|
||||
name: Trigger 'preview build'
|
||||
uses: peter-evans/repository-dispatch@v1
|
||||
uses: peter-evans/repository-dispatch@v2
|
||||
with:
|
||||
token: ${{ secrets.PREVIEW_GITHUB_TOKEN }}
|
||||
event-type: "Preview build #${{ github.event.number }}"
|
||||
|
247
.github/workflows/release.yml
vendored
247
.github/workflows/release.yml
vendored
@@ -29,14 +29,14 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout (Release)
|
||||
if: github.event_name == 'release'
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
# We generate a changelog; for this we need the full git log.
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Checkout (Manual)
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.event.inputs.ref }}
|
||||
# We generate a changelog; for this we need the full git log.
|
||||
@@ -44,7 +44,7 @@ jobs:
|
||||
|
||||
- name: Checkout (Trigger)
|
||||
if: github.event_name == 'repository_dispatch'
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.event.client_payload.ref }}
|
||||
# We generate a changelog; for this we need the full git log.
|
||||
@@ -138,10 +138,10 @@ jobs:
|
||||
echo "Folder on CDN: ${FOLDER}"
|
||||
echo "Workflow trigger: ${TRIGGER_TYPE}"
|
||||
|
||||
echo "::set-output name=version::$(cat .version)"
|
||||
echo "::set-output name=is_tag::${IS_TAG}"
|
||||
echo "::set-output name=folder::${FOLDER}"
|
||||
echo "::set-output name=trigger_type::${TRIGGER_TYPE}"
|
||||
echo "version=$(cat .version)" >> $GITHUB_OUTPUT
|
||||
echo "is_tag=${IS_TAG}" >> $GITHUB_OUTPUT
|
||||
echo "folder=${FOLDER}" >> $GITHUB_OUTPUT
|
||||
echo "trigger_type=${TRIGGER_TYPE}" >> $GITHUB_OUTPUT
|
||||
env:
|
||||
NIGHTLIES_BRANCH: master
|
||||
FOLDER_RELEASES: openttd-releases
|
||||
@@ -174,14 +174,14 @@ jobs:
|
||||
echo "::endgroup::"
|
||||
|
||||
- name: Store bundles
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: openttd-source
|
||||
path: build/bundles/*
|
||||
retention-days: 5
|
||||
|
||||
- name: Store source (for other jobs)
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: internal-source
|
||||
path: source.tar.gz
|
||||
@@ -195,7 +195,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Download source
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: internal-source
|
||||
|
||||
@@ -258,7 +258,7 @@ jobs:
|
||||
echo "::endgroup::"
|
||||
|
||||
- name: Store bundles
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: openttd-docs
|
||||
path: build/bundles/*.tar.xz
|
||||
@@ -276,7 +276,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Download source
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: internal-source
|
||||
|
||||
@@ -355,7 +355,7 @@ jobs:
|
||||
echo "::endgroup::"
|
||||
|
||||
- name: Store bundles
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: openttd-linux-generic
|
||||
path: build/bundles
|
||||
@@ -371,17 +371,11 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- container_image: "ubuntu:18.04"
|
||||
bundle_name: "bionic"
|
||||
compiler: "g++-8"
|
||||
- container_image: "ubuntu:20.04"
|
||||
bundle_name: "focal"
|
||||
compiler: "g++"
|
||||
- container_image: "ubuntu:20.10"
|
||||
bundle_name: "groovy"
|
||||
compiler: "g++"
|
||||
- container_image: "debian:buster"
|
||||
bundle_name: "buster"
|
||||
- container_image: "ubuntu:22.04"
|
||||
bundle_name: "jammy"
|
||||
compiler: "g++"
|
||||
- container_image: "debian:bullseye"
|
||||
bundle_name: "bullseye"
|
||||
@@ -393,7 +387,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Download source
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: internal-source
|
||||
|
||||
@@ -463,7 +457,7 @@ jobs:
|
||||
echo "::endgroup::"
|
||||
|
||||
- name: Store bundles
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: openttd-linux-${{ matrix.bundle_name }}
|
||||
path: build/bundles
|
||||
@@ -473,13 +467,13 @@ jobs:
|
||||
name: MacOS
|
||||
needs: source
|
||||
|
||||
runs-on: macos-10.15
|
||||
runs-on: macos-11
|
||||
env:
|
||||
MACOSX_DEPLOYMENT_TARGET: 10.14
|
||||
|
||||
steps:
|
||||
- name: Download source
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: internal-source
|
||||
|
||||
@@ -497,10 +491,10 @@ jobs:
|
||||
- name: Prepare cache key
|
||||
id: key
|
||||
run: |
|
||||
echo "::set-output name=image::$ImageOS-$ImageVersion"
|
||||
echo "image=$ImageOS-$ImageVersion" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Enable vcpkg cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: /usr/local/share/vcpkg/installed
|
||||
key: ${{ steps.key.outputs.image }}-vcpkg-release-0 # Increase the number whenever dependencies are modified
|
||||
@@ -654,7 +648,7 @@ jobs:
|
||||
mv _CPack_Packages/*/Bundle/openttd-*.zip bundles/
|
||||
|
||||
- name: Store bundles
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: openttd-macos-universal
|
||||
path: build-x64/bundles
|
||||
@@ -679,7 +673,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Download source
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: internal-source
|
||||
|
||||
@@ -700,10 +694,10 @@ jobs:
|
||||
# Work around caching failure with GNU tar
|
||||
New-Item -Type Junction -Path vcpkg -Target c:\vcpkg
|
||||
|
||||
Write-Output "::set-output name=image::$env:ImageOS-$env:ImageVersion"
|
||||
Write-Output "image=$env:ImageOS-$env:ImageVersion" >> $env:GITHUB_OUTPUT
|
||||
|
||||
- name: Enable vcpkg cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: vcpkg/installed
|
||||
key: ${{ steps.key.outputs.image }}-vcpkg-${{ matrix.arch }}-0 # Increase the number whenever dependencies are modified
|
||||
@@ -847,12 +841,195 @@ jobs:
|
||||
WINDOWS_CERTIFICATE_COMMON_NAME: ${{ secrets.WINDOWS_CERTIFICATE_COMMON_NAME }}
|
||||
|
||||
- name: Store bundles
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: openttd-windows-${{ matrix.arch }}
|
||||
path: build/bundles
|
||||
retention-days: 5
|
||||
|
||||
windows-appx:
|
||||
name: Windows Store
|
||||
needs:
|
||||
- source
|
||||
- windows
|
||||
|
||||
if: needs.source.outputs.is_tag == 'true'
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- name: Download source
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: internal-source
|
||||
|
||||
- name: Unpack source
|
||||
shell: bash
|
||||
run: |
|
||||
tar -xf source.tar.gz --strip-components=1
|
||||
|
||||
- name: Download x86 build
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: openttd-windows-x86
|
||||
|
||||
- name: Download x64 build
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: openttd-windows-x64
|
||||
|
||||
- name: Download arm64 build
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: openttd-windows-arm64
|
||||
|
||||
- name: Unpack builds
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir builds
|
||||
cd builds
|
||||
|
||||
function extract {
|
||||
mkdir $1
|
||||
|
||||
# Extract the zip version of the release
|
||||
unzip ../openttd-*-windows-$2.zip -d $1
|
||||
|
||||
# Remove the extraneous directory
|
||||
mv $1/openttd-*-windows-$2/* $1/
|
||||
rmdir $1/openttd-*-windows-$2
|
||||
|
||||
# Move the openttd.exe to the '{arch}-binaries' folder
|
||||
mkdir $1-binaries
|
||||
mv $1/openttd.exe $1-binaries/
|
||||
}
|
||||
|
||||
extract x86 win32
|
||||
extract x64 win64
|
||||
extract arm64 arm64
|
||||
|
||||
# Use the "x86" folder as the source of the common binaries (lang files, etc) and remove the others
|
||||
mv x86 common-binaries
|
||||
rm -rf x64 arm64
|
||||
|
||||
- name: Install OpenGFX
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p builds/common-binaries/baseset
|
||||
cd builds/common-binaries/baseset
|
||||
|
||||
echo "::group::Download OpenGFX"
|
||||
curl -L https://cdn.openttd.org/opengfx-releases/7.1/opengfx-7.1-all.zip -o opengfx-all.zip
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Unpack OpenGFX"
|
||||
unzip opengfx-all.zip
|
||||
tar xf opengfx-*.tar
|
||||
echo "::endgroup::"
|
||||
|
||||
rm -f opengfx-all.zip opengfx-*.tar
|
||||
|
||||
- name: Install OpenMSX
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p builds/common-binaries/baseset
|
||||
cd builds/common-binaries/baseset
|
||||
|
||||
echo "::group::Download OpenMSX"
|
||||
curl -L https://cdn.openttd.org/openmsx-releases/0.4.2/openmsx-0.4.2-all.zip -o openmsx-all.zip
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Unpack OpenGFX"
|
||||
unzip openmsx-all.zip
|
||||
tar xf openmsx-*.tar
|
||||
echo "::endgroup::"
|
||||
|
||||
rm -f openmsx-all.zip openmsx-*.tar
|
||||
|
||||
- name: Install OpenSFX
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p builds/common-binaries/baseset/opensfx
|
||||
cd builds/common-binaries/baseset/opensfx
|
||||
|
||||
echo "::group::Download OpenSFX"
|
||||
curl -L https://cdn.openttd.org/opensfx-releases/1.0.3/opensfx-1.0.3-all.zip -o opensfx-all.zip
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Unpack OpenSFX"
|
||||
unzip opensfx-all.zip
|
||||
tar xf opensfx-*.tar
|
||||
echo "::endgroup::"
|
||||
|
||||
rm -f opensfx-all.zip opensfx-*.tar
|
||||
|
||||
- name: Generate signing certificate
|
||||
shell: cmd
|
||||
run: |
|
||||
cd builds
|
||||
|
||||
REM We need to provide a signed .appx to the Windows Store, so generate a certificate with password 'password'
|
||||
call ..\os\windows\winstore\generate-key.bat "CN=78024DA8-4BE4-4C77-B12E-547BBF7359D2" password cert.pfx
|
||||
|
||||
- name: Generate assets
|
||||
shell: cmd
|
||||
run: |
|
||||
cd os\windows\winstore
|
||||
call generate-assets.bat
|
||||
|
||||
- name: Prepare manifests
|
||||
shell: cmd
|
||||
run: |
|
||||
cd builds
|
||||
mkdir manifests
|
||||
|
||||
REM Set the version environment variable
|
||||
call ..\os\windows\winstore\set-version.bat x86-binaries\openttd.exe
|
||||
|
||||
call ..\os\windows\winstore\prepare-manifests.bat manifests "CN=78024DA8-4BE4-4C77-B12E-547BBF7359D2" "57420OpenTTDDevelopers.OpenTTDofficial"
|
||||
|
||||
- name: Prepare binaries
|
||||
shell: bash
|
||||
run: |
|
||||
cd builds
|
||||
|
||||
# Copy the Windows Store assets
|
||||
mkdir common-binaries/Assets
|
||||
cp -R ../os/windows/winstore/assets-common/* common-binaries/Assets/
|
||||
|
||||
mkdir Assets
|
||||
cp -R ../os/windows/winstore/assets/* Assets/
|
||||
|
||||
cp manifests/*.xml .
|
||||
|
||||
- name: Build
|
||||
shell: cmd
|
||||
run: |
|
||||
REM Add the Windows SDK tools to the PATH
|
||||
|
||||
echo|set /p="SET VS_INSTALLDIR=" > _vspath.bat
|
||||
vswhere -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath >> _vspath.bat
|
||||
call _vspath.bat
|
||||
call "%VS_INSTALLDIR%\Common7\Tools\VsDevCmd.bat"
|
||||
|
||||
REM Set the version environment variable
|
||||
call os\windows\winstore\set-version.bat builds\x86-binaries\openttd.exe
|
||||
|
||||
cd builds
|
||||
mkdir output
|
||||
|
||||
REM Build and sign the package
|
||||
makeappx build /v /f PackagingLayout.xml /op output\ /bv %OTTD_VERSION% /pv %OTTD_VERSION% /ca
|
||||
SignTool sign /fd sha256 /a /f cert.pfx /p password "output\OpenTTD.appxbundle"
|
||||
|
||||
- name: Store appx
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: openttd-windows-store
|
||||
path: |
|
||||
builds/output/OpenTTD.appxbundle
|
||||
builds/cert.pfx
|
||||
retention-days: 5
|
||||
|
||||
upload:
|
||||
name: Upload (AWS)
|
||||
needs:
|
||||
@@ -874,7 +1051,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Download all bundles
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
|
||||
- name: Calculate checksums
|
||||
run: |
|
||||
@@ -906,7 +1083,7 @@ jobs:
|
||||
AWS_DEFAULT_REGION: ${{ secrets.AWS_REGION }}
|
||||
|
||||
- name: Trigger 'New OpenTTD release'
|
||||
uses: peter-evans/repository-dispatch@v1
|
||||
uses: peter-evans/repository-dispatch@v2
|
||||
with:
|
||||
token: ${{ secrets.DEPLOYMENT_TOKEN }}
|
||||
repository: OpenTTD/workflows
|
||||
@@ -927,7 +1104,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Download all bundles
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
|
||||
- name: Setup steamcmd
|
||||
uses: CyberAndrii/setup-steamcmd@v1
|
||||
|
18
.github/workflows/unused-strings.yml
vendored
Normal file
18
.github/workflows/unused-strings.yml
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
name: Unused strings
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
unused-strings:
|
||||
name: Unused strings
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Check for unused strings
|
||||
run: |
|
||||
set -ex
|
||||
python3 .github/unused-strings.py
|
@@ -5,7 +5,7 @@ if(NOT BINARY_NAME)
|
||||
endif()
|
||||
|
||||
project(${BINARY_NAME}
|
||||
VERSION 12.0
|
||||
VERSION 13.0
|
||||
)
|
||||
|
||||
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
|
||||
@@ -305,7 +305,7 @@ if(EMSCRIPTEN)
|
||||
add_definitions(-s DISABLE_EXCEPTION_CATCHING=0)
|
||||
|
||||
# Export functions to Javascript.
|
||||
target_link_libraries(WASM::WASM INTERFACE "-s EXPORTED_FUNCTIONS='[\"_main\", \"_em_openttd_add_server\"]' -s EXTRA_EXPORTED_RUNTIME_METHODS='[\"cwrap\"]'")
|
||||
target_link_libraries(WASM::WASM INTERFACE "-s EXPORTED_FUNCTIONS='[\"_main\", \"_em_openttd_add_server\"]' -s EXPORTED_RUNTIME_METHODS='[\"cwrap\"]'")
|
||||
|
||||
# Preload all the files we generate during build.
|
||||
# As we do not compile with FreeType / FontConfig, we also have no way to
|
||||
|
@@ -69,7 +69,7 @@ that comes with vcpkg. After that, you can run something similar to this:
|
||||
```powershell
|
||||
mkdir build
|
||||
cd build
|
||||
cmake.exe .. -G'Visual Studio 16 2019' -DCMAKE_TOOLCHAIN_FILE="<location of vcpkg>\vcpkg\scripts\buildsystems\vcpkg.cmake" -DVCPKG_TARGET_TRIPLET="x64-windows-static"
|
||||
cmake.exe .. -G"Visual Studio 16 2019" -DCMAKE_TOOLCHAIN_FILE="<location of vcpkg>\vcpkg\scripts\buildsystems\vcpkg.cmake" -DVCPKG_TARGET_TRIPLET="x64-windows-static"
|
||||
```
|
||||
|
||||
Change `<location of vcpkg>` to where you have installed vcpkg. After this
|
||||
|
@@ -94,8 +94,8 @@ Although we really appreciate feedback and ideas, we will close feature requests
|
||||
|
||||
Many of those ideas etc do have a place on the [forums](https://www.tt-forums.net); and if enough people like it, someone will stand up and make it.
|
||||
|
||||
It's usually best discuss in [irc](https://wiki.openttd.org/en/Development/IRC%20channel) before opening a feature request or working on a large feature in a fork.
|
||||
Discussion in irc can take time, but it can be productive and avoid disappointment :)
|
||||
It's usually best to discuss on [Discord](https://discord.gg/openttd) before opening a feature request or working on a large feature in a fork.
|
||||
Discussion can take time, but it can be productive and avoid disappointment. :)
|
||||
|
||||
|
||||
## Pull requests
|
||||
@@ -137,7 +137,7 @@ git checkout upstream/master -b <topic-branch-name>
|
||||
```
|
||||
|
||||
4. Commit your changes in logical chunks. Please adhere to these [git commit message guidelines](https://wiki.openttd.org/en/Development/Coding%20style#commit-message) or your code is unlikely to be merged into the main project.
|
||||
Use Git's [interactive rebase](https://help.github.com/articles/interactive-rebase) feature to tidy up your commits before making them public.
|
||||
Use Git's [interactive rebase](https://docs.github.com/en/get-started/using-git/about-git-rebase) feature to tidy up your commits before making them public.
|
||||
|
||||
5. Locally rebase the upstream development branch into your topic branch:
|
||||
|
||||
@@ -212,8 +212,8 @@ When it comes to gameplay features there are at least these groups of interests:
|
||||
- *Control freak:* micromanagement like conditional orders, refitting and loading etc.
|
||||
- *Casual:* automatisation like cargodist, path based signalling etc.
|
||||
|
||||
To please everyone, the official branch tries to stay close to the original gameplay; after all, that is what everyone brought here.
|
||||
The preferred method to alter and extent the gameplay is via add-ons like NewGRF and GameScripts.
|
||||
To please everyone, the official branch tries to stay close to the original gameplay; after all, that is what brought everyone here.
|
||||
The preferred method to alter and extend the gameplay is via add-ons like NewGRF and GameScripts.
|
||||
|
||||
For a long time, the official branch was also open to features which could be enabled/disabled, but the corner-cases that came with some configurations have rendered some parts of the code very complicated.
|
||||
Today, new features have to work with all the already existing features, which is not only challenging in corner cases, but also requires spending considerable more work than just "making it work in the game mode that I play".
|
||||
@@ -265,5 +265,5 @@ If you would not like to accept this risk, please do either commit anonymously o
|
||||
|
||||
### Attribution of this Contributing Guide
|
||||
|
||||
This contributing guide is adapted from [Bootstrap](https://github.com/twbs/bootstrap/blob/master/CONTRIBUTING.md) under the [Creative Commons Attribution 3.0 Unported License](https://github.com/twbs/bootstrap/blob/master/docs/LICENSE) terms for Bootstrap documentation.
|
||||
This contributing guide is adapted from [Bootstrap](https://github.com/twbs/bootstrap/blob/main/.github/CONTRIBUTING.md) under the [Creative Commons Attribution 3.0 Unported License](https://creativecommons.org/licenses/by/3.0/) terms for Bootstrap documentation.
|
||||
The GDPR notice is adapted from [rsyslog](https://github.com/rsyslog/rsyslog/blob/master/CONTRIBUTING.md) under the [GNU General Public License](https://github.com/rsyslog/rsyslog/blob/master/COPYING).
|
||||
|
27
CREDITS.md
27
CREDITS.md
@@ -1,31 +1,32 @@
|
||||
### The OpenTTD team (in alphabetical order):
|
||||
|
||||
- Grzegorz Duczyński (adf88) - General coding (since 1.7.2)
|
||||
- Albert Hofkamp (Alberth) - GUI expert (since 0.7)
|
||||
- Matthijs Kooijman (blathijs) - Pathfinder-guru, Debian port (since 0.3)
|
||||
- Ulf Hermann (fonsinchen) - Cargo Distribution (since 1.3)
|
||||
- Christoph Elsenhans (frosch) - General coding (since 0.6)
|
||||
- Loïc Guilloux (glx) - Windows Expert (since 0.4.5)
|
||||
- Loïc Guilloux (glx) - General / Windows Expert (since 0.4.5)
|
||||
- Charles Pigott (LordAro) - General / Correctness police (since 1.9)
|
||||
- Michael Lutz (michi_cc) - Path based signals (since 0.7)
|
||||
- Michael Lutz (michi_cc) - General / Path based signals (since 0.7)
|
||||
- Niels Martin Hansen (nielsm) - Music system, general coding (since 1.9)
|
||||
- Owen Rudge (orudge) - Forum host, OS/2 port (since 0.1)
|
||||
- Peter Nelson (peter1138) - Spiritual descendant from newGRF gods (since 0.4.5)
|
||||
- Ingo von Borstel (planetmaker) - General coding, Support (since 1.1)
|
||||
- Remko Bijker (Rubidium) - Lead coder and way more (since 0.4.5)
|
||||
- José Soler (Terkhen) - General coding (since 1.0)
|
||||
- Remko Bijker (Rubidium) - Coder and way more (since 0.4.5)
|
||||
- Patric Stout (TrueBrain) - NoProgrammer (since 0.3), sys op
|
||||
- Tyler Trahan (2TallTyler) - General coding (since 13)
|
||||
|
||||
### Inactive Developers:
|
||||
|
||||
- Grzegorz Duczyński (adf88) - General coding (1.7 - 1.8)
|
||||
- Albert Hofkamp (Alberth) - GUI expert (0.7 - 1.9)
|
||||
- Jean-François Claeys (Belugas) - GUI, newindustries and more (0.4.5 - 1.0)
|
||||
- Bjarni Corfitzen (Bjarni) - macOS port, coder and vehicles (0.3 - 0.7)
|
||||
- Victor Fischer (Celestar) - Programming everywhere you need him to (0.3 - 0.6)
|
||||
- Ulf Hermann (fonsinchen) - Cargo Distribution (1.3 - 1.6)
|
||||
- Jaroslav Mazanec (KUDr) - YAPG (Yet Another Pathfinder God) ;) (0.4.5 - 0.6)
|
||||
- Jonathan Coome (Maedhros) - High priest of the NewGRF Temple (0.5 - 0.6)
|
||||
- Attila Bán (MiHaMiX) - WebTranslator 1 and 2 (0.3 - 0.5)
|
||||
- Attila Bán (MiHaMiX) - Developer WebTranslator 1 and 2 (0.3 - 0.5)
|
||||
- Ingo von Borstel (planetmaker) - General coding, Support (1.1 - 1.9)
|
||||
- Zdeněk Sojka (SmatZ) - Bug finder and fixer (0.6 - 1.3)
|
||||
- José Soler (Terkhen) - General coding (1.0 - 1.4)
|
||||
- Christoph Mallon (Tron) - Programmer, code correctness police (0.3 - 0.5)
|
||||
- Patric Stout (TrueBrain) - NoProgrammer (0.3 - 1.2), sys op (active)
|
||||
- Thijs Marinussen (Yexo) - AI Framework, General (0.6 - 1.3)
|
||||
- Leif Linse (Zuu) - AI/Game Script (1.2 - 1.6)
|
||||
|
||||
@@ -33,11 +34,11 @@
|
||||
|
||||
- Tamás Faragó (Darkvater) - Ex-Lead coder (0.3 - 0.5)
|
||||
- Dominik Scherer (dominik81) - Lead programmer, GUI expert (0.3 - 0.3)
|
||||
- Emil Djupfeld (egladil) - macOS port (0.4 - 0.6)
|
||||
- Emil Djupfeld (egladil) - macOS port (0.4.5 - 0.6)
|
||||
- Simon Sasburg (HackyKid) - Bug fixer (0.4 - 0.4.5)
|
||||
- Ludvig Strigeus (ludde) - Original author of OpenTTD, main coder (0.1 - 0.3)
|
||||
- Cian Duffy (MYOB) - BeOS port / manual writing (0.1 - 0.3)
|
||||
- Petr Baudiš (pasky) - Many patches, newgrf support, etc. (0.3 - 0.3)
|
||||
- Petr Baudiš (pasky) - Many patches, newgrf support (0.3 - 0.3)
|
||||
- Benedikt Brüggemeier (skidd13) - Bug fixer and code reworker (0.6 - 0.7)
|
||||
- Serge Paquet (vurlix) - 2nd contributor after ludde (0.1 - 0.3)
|
||||
|
||||
@@ -52,7 +53,7 @@
|
||||
- Alberto Demichelis - Squirrel scripting language
|
||||
- L. Peter Deutsch - MD5 implementation
|
||||
- Michael Blunck - For revolutionizing TTD with awesome graphics
|
||||
- George - Canal graphics
|
||||
- George - Canal/Lock graphics
|
||||
- Andrew Parkhouse (andythenorth) - River graphics
|
||||
- David Dallaston (Pikka) - Tram tracks
|
||||
- All Translators - For their support to make OpenTTD a truly international game
|
||||
|
38
README.md
38
README.md
@@ -77,9 +77,9 @@ For some platforms, you will need to refer to [the installation guide](https://w
|
||||
The free data files, split into OpenGFX for graphics, OpenSFX for sounds and
|
||||
OpenMSX for music can be found at:
|
||||
|
||||
- https://www.openttd.org/downloads/opengfx-releases/ for OpenGFX
|
||||
- https://www.openttd.org/downloads/opensfx-releases/ for OpenSFX
|
||||
- https://www.openttd.org/downloads/openmsx-releases/ for OpenMSX
|
||||
- https://www.openttd.org/downloads/opengfx-releases/latest for OpenGFX
|
||||
- https://www.openttd.org/downloads/opensfx-releases/latest for OpenSFX
|
||||
- https://www.openttd.org/downloads/openmsx-releases/latest for OpenMSX
|
||||
|
||||
Please follow the readme of these packages about the installation procedure.
|
||||
The Windows installer can optionally download and install these packages.
|
||||
@@ -116,35 +116,6 @@ Most types of add-on content can be downloaded within OpenTTD via the 'Check Onl
|
||||
|
||||
Add-on content can also be installed manually, but that's more complicated; the [OpenTTD wiki](https://wiki.openttd.org/) may offer help with that, or the [OpenTTD directory structure guide](./docs/directory_structure.md).
|
||||
|
||||
### 1.5.1) AI opponents
|
||||
|
||||
OpenTTD comes without AI opponents, so if you want to play with AIs you have to download them.
|
||||
|
||||
The easiest way is via the 'Check Online Content' button in the main menu.
|
||||
|
||||
You can select some AIs that you think are compatible with your playing style.
|
||||
|
||||
AI help and discussions may also be found in the [AI section of the forum](https://www.tt-forums.net/viewforum.php?f=65).
|
||||
|
||||
### 1.5.2) Scenarios and height maps
|
||||
|
||||
Scenarios and heightmaps can be added via the 'Check Online Content' button in the main menu.
|
||||
|
||||
### 1.5.3) NewGRFs
|
||||
|
||||
A wide range of add-content is available as NewGRFs, including vehicles, industries, stations, landscape objects, town names and more.
|
||||
|
||||
NewGRFs can be added via the 'Check Online Content' button in the main menu.
|
||||
|
||||
See also the wiki [guide to NewGRFs](https://wiki.openttd.org/en/Manual/NewGRF) and [the forum graphics development section](https://www.tt-forums.net/viewforum.php?f=66).
|
||||
|
||||
### 1.5.4) Game scripts
|
||||
|
||||
Game scripts can provide additional challenges or changes to the standard OpenTTD gameplay, for example setting transport goals, or changing town growth behaviour.
|
||||
|
||||
Game scripts can be added via the 'Check Online Content' button in the main menu.
|
||||
|
||||
See also the wiki [guide to game scripts](https://wiki.openttd.org/en/Manual/Game%20script) and [the forum graphics game script section](https://www.tt-forums.net/viewforum.php?f=65).
|
||||
|
||||
### 1.6) OpenTTD directories
|
||||
|
||||
@@ -162,8 +133,9 @@ If you want to compile OpenTTD from source, instructions can be found in [COMPIL
|
||||
'Official' channels
|
||||
|
||||
- [OpenTTD website](https://www.openttd.org)
|
||||
- [OpenTTD official Discord](https://discord.gg/openttd)
|
||||
- IRC chat using #openttd on irc.oftc.net [more info about our irc channel](https://wiki.openttd.org/en/Development/IRC%20channel)
|
||||
- [OpenTTD on Github](https://github.com/openTTD/) for code repositories and for reporting issues
|
||||
- [OpenTTD on Github](https://github.com/OpenTTD/) for code repositories and for reporting issues
|
||||
- [forum.openttd.org](https://forum.openttd.org/) - the primary community forum site for discussing OpenTTD and related games
|
||||
- [OpenTTD wiki](https://wiki.openttd.org/) community-maintained wiki, including topics like gameplay guide, detailed explanation of some game mechanics, how to use add-on content (mods) and much more
|
||||
|
||||
|
@@ -379,3 +379,16 @@ AIGroup.CreateGroup <- function(vehicle_type)
|
||||
{
|
||||
return AIGroup._CreateGroup(vehicle_type, AIGroup.GROUP_INVALID);
|
||||
}
|
||||
|
||||
/* 13 really checks RoadType against RoadType */
|
||||
AIRoad._HasRoadType <- AIRoad.HasRoadType;
|
||||
AIRoad.HasRoadType <- function(tile, road_type)
|
||||
{
|
||||
local list = AIRoadTypeList(AIRoad.GetRoadTramType(road_type));
|
||||
foreach (rt, _ in list) {
|
||||
if (AIRoad._HasRoadType(tile, rt)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@@ -131,3 +131,16 @@ AIGroup.CreateGroup <- function(vehicle_type)
|
||||
{
|
||||
return AIGroup._CreateGroup(vehicle_type, AIGroup.GROUP_INVALID);
|
||||
}
|
||||
|
||||
/* 13 really checks RoadType against RoadType */
|
||||
AIRoad._HasRoadType <- AIRoad.HasRoadType;
|
||||
AIRoad.HasRoadType <- function(tile, road_type)
|
||||
{
|
||||
local list = AIRoadTypeList(AIRoad.GetRoadTramType(road_type));
|
||||
foreach (rt, _ in list) {
|
||||
if (AIRoad._HasRoadType(tile, rt)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@@ -68,3 +68,16 @@ AIGroup.CreateGroup <- function(vehicle_type)
|
||||
{
|
||||
return AIGroup._CreateGroup(vehicle_type, AIGroup.GROUP_INVALID);
|
||||
}
|
||||
|
||||
/* 13 really checks RoadType against RoadType */
|
||||
AIRoad._HasRoadType <- AIRoad.HasRoadType;
|
||||
AIRoad.HasRoadType <- function(tile, road_type)
|
||||
{
|
||||
local list = AIRoadTypeList(AIRoad.GetRoadTramType(road_type));
|
||||
foreach (rt, _ in list) {
|
||||
if (AIRoad._HasRoadType(tile, rt)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@@ -6,3 +6,16 @@
|
||||
*/
|
||||
|
||||
AILog.Info("1.10 API compatibility in effect.");
|
||||
|
||||
/* 13 really checks RoadType against RoadType */
|
||||
AIRoad._HasRoadType <- AIRoad.HasRoadType;
|
||||
AIRoad.HasRoadType <- function(tile, road_type)
|
||||
{
|
||||
local list = AIRoadTypeList(AIRoad.GetRoadTramType(road_type));
|
||||
foreach (rt, _ in list) {
|
||||
if (AIRoad._HasRoadType(tile, rt)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@@ -6,3 +6,16 @@
|
||||
*/
|
||||
|
||||
AILog.Info("1.11 API compatibility in effect.");
|
||||
|
||||
/* 13 really checks RoadType against RoadType */
|
||||
AIRoad._HasRoadType <- AIRoad.HasRoadType;
|
||||
AIRoad.HasRoadType <- function(tile, road_type)
|
||||
{
|
||||
local list = AIRoadTypeList(AIRoad.GetRoadTramType(road_type));
|
||||
foreach (rt, _ in list) {
|
||||
if (AIRoad._HasRoadType(tile, rt)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@@ -20,3 +20,16 @@ AIGroup.CreateGroup <- function(vehicle_type)
|
||||
{
|
||||
return AIGroup._CreateGroup(vehicle_type, AIGroup.GROUP_INVALID);
|
||||
}
|
||||
|
||||
/* 13 really checks RoadType against RoadType */
|
||||
AIRoad._HasRoadType <- AIRoad.HasRoadType;
|
||||
AIRoad.HasRoadType <- function(tile, road_type)
|
||||
{
|
||||
local list = AIRoadTypeList(AIRoad.GetRoadTramType(road_type));
|
||||
foreach (rt, _ in list) {
|
||||
if (AIRoad._HasRoadType(tile, rt)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@@ -20,3 +20,16 @@ AIGroup.CreateGroup <- function(vehicle_type)
|
||||
{
|
||||
return AIGroup._CreateGroup(vehicle_type, AIGroup.GROUP_INVALID);
|
||||
}
|
||||
|
||||
/* 13 really checks RoadType against RoadType */
|
||||
AIRoad._HasRoadType <- AIRoad.HasRoadType;
|
||||
AIRoad.HasRoadType <- function(tile, road_type)
|
||||
{
|
||||
local list = AIRoadTypeList(AIRoad.GetRoadTramType(road_type));
|
||||
foreach (rt, _ in list) {
|
||||
if (AIRoad._HasRoadType(tile, rt)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@@ -20,3 +20,16 @@ AIGroup.CreateGroup <- function(vehicle_type)
|
||||
{
|
||||
return AIGroup._CreateGroup(vehicle_type, AIGroup.GROUP_INVALID);
|
||||
}
|
||||
|
||||
/* 13 really checks RoadType against RoadType */
|
||||
AIRoad._HasRoadType <- AIRoad.HasRoadType;
|
||||
AIRoad.HasRoadType <- function(tile, road_type)
|
||||
{
|
||||
local list = AIRoadTypeList(AIRoad.GetRoadTramType(road_type));
|
||||
foreach (rt, _ in list) {
|
||||
if (AIRoad._HasRoadType(tile, rt)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@@ -20,3 +20,16 @@ AIGroup.CreateGroup <- function(vehicle_type)
|
||||
{
|
||||
return AIGroup._CreateGroup(vehicle_type, AIGroup.GROUP_INVALID);
|
||||
}
|
||||
|
||||
/* 13 really checks RoadType against RoadType */
|
||||
AIRoad._HasRoadType <- AIRoad.HasRoadType;
|
||||
AIRoad.HasRoadType <- function(tile, road_type)
|
||||
{
|
||||
local list = AIRoadTypeList(AIRoad.GetRoadTramType(road_type));
|
||||
foreach (rt, _ in list) {
|
||||
if (AIRoad._HasRoadType(tile, rt)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@@ -20,3 +20,16 @@ AIGroup.CreateGroup <- function(vehicle_type)
|
||||
{
|
||||
return AIGroup._CreateGroup(vehicle_type, AIGroup.GROUP_INVALID);
|
||||
}
|
||||
|
||||
/* 13 really checks RoadType against RoadType */
|
||||
AIRoad._HasRoadType <- AIRoad.HasRoadType;
|
||||
AIRoad.HasRoadType <- function(tile, road_type)
|
||||
{
|
||||
local list = AIRoadTypeList(AIRoad.GetRoadTramType(road_type));
|
||||
foreach (rt, _ in list) {
|
||||
if (AIRoad._HasRoadType(tile, rt)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@@ -20,3 +20,16 @@ AIGroup.CreateGroup <- function(vehicle_type)
|
||||
{
|
||||
return AIGroup._CreateGroup(vehicle_type, AIGroup.GROUP_INVALID);
|
||||
}
|
||||
|
||||
/* 13 really checks RoadType against RoadType */
|
||||
AIRoad._HasRoadType <- AIRoad.HasRoadType;
|
||||
AIRoad.HasRoadType <- function(tile, road_type)
|
||||
{
|
||||
local list = AIRoadTypeList(AIRoad.GetRoadTramType(road_type));
|
||||
foreach (rt, _ in list) {
|
||||
if (AIRoad._HasRoadType(tile, rt)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@@ -20,3 +20,16 @@ AIGroup.CreateGroup <- function(vehicle_type)
|
||||
{
|
||||
return AIGroup._CreateGroup(vehicle_type, AIGroup.GROUP_INVALID);
|
||||
}
|
||||
|
||||
/* 13 really checks RoadType against RoadType */
|
||||
AIRoad._HasRoadType <- AIRoad.HasRoadType;
|
||||
AIRoad.HasRoadType <- function(tile, road_type)
|
||||
{
|
||||
local list = AIRoadTypeList(AIRoad.GetRoadTramType(road_type));
|
||||
foreach (rt, _ in list) {
|
||||
if (AIRoad._HasRoadType(tile, rt)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@@ -6,3 +6,16 @@
|
||||
*/
|
||||
|
||||
AILog.Info("1.9 API compatibility in effect.");
|
||||
|
||||
/* 13 really checks RoadType against RoadType */
|
||||
AIRoad._HasRoadType <- AIRoad.HasRoadType;
|
||||
AIRoad.HasRoadType <- function(tile, road_type)
|
||||
{
|
||||
local list = AIRoadTypeList(AIRoad.GetRoadTramType(road_type));
|
||||
foreach (rt, _ in list) {
|
||||
if (AIRoad._HasRoadType(tile, rt)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@@ -4,3 +4,18 @@
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
AILog.Info("12 API compatibility in effect.");
|
||||
|
||||
/* 13 really checks RoadType against RoadType */
|
||||
AIRoad._HasRoadType <- AIRoad.HasRoadType;
|
||||
AIRoad.HasRoadType <- function(tile, road_type)
|
||||
{
|
||||
local list = AIRoadTypeList(AIRoad.GetRoadTramType(road_type));
|
||||
foreach (rt, _ in list) {
|
||||
if (AIRoad._HasRoadType(tile, rt)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
6
bin/ai/compat_13.nut
Normal file
6
bin/ai/compat_13.nut
Normal file
@@ -0,0 +1,6 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
@@ -13,3 +13,16 @@ GSCompany.ChangeBankBalance <- function(company, delta, expenses_type)
|
||||
{
|
||||
return GSCompany._ChangeBankBalance(company, delta, expenses_type, GSMap.TILE_INVALID);
|
||||
}
|
||||
|
||||
/* 13 really checks RoadType against RoadType */
|
||||
GSRoad._HasRoadType <- GSRoad.HasRoadType;
|
||||
GSRoad.HasRoadType <- function(tile, road_type)
|
||||
{
|
||||
local list = GSRoadTypeList(GSRoad.GetRoadTramType(road_type));
|
||||
foreach (rt, _ in list) {
|
||||
if (GSRoad._HasRoadType(tile, rt)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@@ -6,3 +6,16 @@
|
||||
*/
|
||||
|
||||
GSLog.Info("1.11 API compatibility in effect.");
|
||||
|
||||
/* 13 really checks RoadType against RoadType */
|
||||
GSRoad._HasRoadType <- GSRoad.HasRoadType;
|
||||
GSRoad.HasRoadType <- function(tile, road_type)
|
||||
{
|
||||
local list = GSRoadTypeList(GSRoad.GetRoadTramType(road_type));
|
||||
foreach (rt, _ in list) {
|
||||
if (GSRoad._HasRoadType(tile, rt)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@@ -35,3 +35,16 @@ GSCompany.ChangeBankBalance <- function(company, delta, expenses_type)
|
||||
{
|
||||
return GSCompany._ChangeBankBalance(company, delta, expenses_type, GSMap.TILE_INVALID);
|
||||
}
|
||||
|
||||
/* 13 really checks RoadType against RoadType */
|
||||
GSRoad._HasRoadType <- GSRoad.HasRoadType;
|
||||
GSRoad.HasRoadType <- function(tile, road_type)
|
||||
{
|
||||
local list = GSRoadTypeList(GSRoad.GetRoadTramType(road_type));
|
||||
foreach (rt, _ in list) {
|
||||
if (GSRoad._HasRoadType(tile, rt)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@@ -35,3 +35,16 @@ GSCompany.ChangeBankBalance <- function(company, delta, expenses_type)
|
||||
{
|
||||
return GSCompany._ChangeBankBalance(company, delta, expenses_type, GSMap.TILE_INVALID);
|
||||
}
|
||||
|
||||
/* 13 really checks RoadType against RoadType */
|
||||
GSRoad._HasRoadType <- GSRoad.HasRoadType;
|
||||
GSRoad.HasRoadType <- function(tile, road_type)
|
||||
{
|
||||
local list = GSRoadTypeList(GSRoad.GetRoadTramType(road_type));
|
||||
foreach (rt, _ in list) {
|
||||
if (GSRoad._HasRoadType(tile, rt)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@@ -28,3 +28,15 @@ GSCompany.ChangeBankBalance <- function(company, delta, expenses_type)
|
||||
return GSCompany._ChangeBankBalance(company, delta, expenses_type, GSMap.TILE_INVALID);
|
||||
}
|
||||
|
||||
/* 13 really checks RoadType against RoadType */
|
||||
GSRoad._HasRoadType <- GSRoad.HasRoadType;
|
||||
GSRoad.HasRoadType <- function(tile, road_type)
|
||||
{
|
||||
local list = GSRoadTypeList(GSRoad.GetRoadTramType(road_type));
|
||||
foreach (rt, _ in list) {
|
||||
if (GSRoad._HasRoadType(tile, rt)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@@ -20,3 +20,16 @@ GSCompany.ChangeBankBalance <- function(company, delta, expenses_type)
|
||||
{
|
||||
return GSCompany._ChangeBankBalance(company, delta, expenses_type, GSMap.TILE_INVALID);
|
||||
}
|
||||
|
||||
/* 13 really checks RoadType against RoadType */
|
||||
GSRoad._HasRoadType <- GSRoad.HasRoadType;
|
||||
GSRoad.HasRoadType <- function(tile, road_type)
|
||||
{
|
||||
local list = GSRoadTypeList(GSRoad.GetRoadTramType(road_type));
|
||||
foreach (rt, _ in list) {
|
||||
if (GSRoad._HasRoadType(tile, rt)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@@ -20,3 +20,16 @@ GSCompany.ChangeBankBalance <- function(company, delta, expenses_type)
|
||||
{
|
||||
return GSCompany._ChangeBankBalance(company, delta, expenses_type, GSMap.TILE_INVALID);
|
||||
}
|
||||
|
||||
/* 13 really checks RoadType against RoadType */
|
||||
GSRoad._HasRoadType <- GSRoad.HasRoadType;
|
||||
GSRoad.HasRoadType <- function(tile, road_type)
|
||||
{
|
||||
local list = GSRoadTypeList(GSRoad.GetRoadTramType(road_type));
|
||||
foreach (rt, _ in list) {
|
||||
if (GSRoad._HasRoadType(tile, rt)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@@ -20,3 +20,16 @@ GSCompany.ChangeBankBalance <- function(company, delta, expenses_type)
|
||||
{
|
||||
return GSCompany._ChangeBankBalance(company, delta, expenses_type, GSMap.TILE_INVALID);
|
||||
}
|
||||
|
||||
/* 13 really checks RoadType against RoadType */
|
||||
GSRoad._HasRoadType <- GSRoad.HasRoadType;
|
||||
GSRoad.HasRoadType <- function(tile, road_type)
|
||||
{
|
||||
local list = GSRoadTypeList(GSRoad.GetRoadTramType(road_type));
|
||||
foreach (rt, _ in list) {
|
||||
if (GSRoad._HasRoadType(tile, rt)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@@ -20,3 +20,16 @@ GSCompany.ChangeBankBalance <- function(company, delta, expenses_type)
|
||||
{
|
||||
return GSCompany._ChangeBankBalance(company, delta, expenses_type, GSMap.TILE_INVALID);
|
||||
}
|
||||
|
||||
/* 13 really checks RoadType against RoadType */
|
||||
GSRoad._HasRoadType <- GSRoad.HasRoadType;
|
||||
GSRoad.HasRoadType <- function(tile, road_type)
|
||||
{
|
||||
local list = GSRoadTypeList(GSRoad.GetRoadTramType(road_type));
|
||||
foreach (rt, _ in list) {
|
||||
if (GSRoad._HasRoadType(tile, rt)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@@ -13,3 +13,16 @@ GSCompany.ChangeBankBalance <- function(company, delta, expenses_type)
|
||||
{
|
||||
return GSCompany._ChangeBankBalance(company, delta, expenses_type, GSMap.TILE_INVALID);
|
||||
}
|
||||
|
||||
/* 13 really checks RoadType against RoadType */
|
||||
GSRoad._HasRoadType <- GSRoad.HasRoadType;
|
||||
GSRoad.HasRoadType <- function(tile, road_type)
|
||||
{
|
||||
local list = GSRoadTypeList(GSRoad.GetRoadTramType(road_type));
|
||||
foreach (rt, _ in list) {
|
||||
if (GSRoad._HasRoadType(tile, rt)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@@ -4,3 +4,18 @@
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
GSLog.Info("12 API compatibility in effect.");
|
||||
|
||||
/* 13 really checks RoadType against RoadType */
|
||||
GSRoad._HasRoadType <- GSRoad.HasRoadType;
|
||||
GSRoad.HasRoadType <- function(tile, road_type)
|
||||
{
|
||||
local list = GSRoadTypeList(GSRoad.GetRoadTramType(road_type));
|
||||
foreach (rt, _ in list) {
|
||||
if (GSRoad._HasRoadType(tile, rt)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
6
bin/game/compat_13.nut
Normal file
6
bin/game/compat_13.nut
Normal file
@@ -0,0 +1,6 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
210
changelog.txt
210
changelog.txt
@@ -1,3 +1,213 @@
|
||||
13.0-beta2 (2022-11-27)
|
||||
------------------------------------------------------------------------
|
||||
Feature: Allow AI/GS to be fully modified in scenario editor (#10152)
|
||||
Feature: Display power-to-weight ratio in ground vehicle details GUI (#10123)
|
||||
Feature: Variable interface scaling (with chunky bevels!) (#10114)
|
||||
Feature: Hotkey to honk a vehicle's horn (#10110)
|
||||
Feature: Split AI/Game Script configuration windows and add them to world gen window (#10058)
|
||||
Feature: [GS] Scriptable league tables (#10001)
|
||||
Feature: Multi-track level crossings (#9931)
|
||||
Feature: Improved local authority action window (#9928)
|
||||
Feature: Automatic console command screenshot numbering with a filename ending in '#' (#9781)
|
||||
Feature: Add buttons to toggle music in the Game Options menu (#9727)
|
||||
Feature: Contextual actions for vehicles grouped by shared orders (#8425)
|
||||
Feature: Add cargo filter support to vehicle list (#8308)
|
||||
Feature: Show the cargoes the vehicles can carry in the vehicle list window (#8304)
|
||||
Change: Allow building canal by area outside editor (#10173)
|
||||
Change: Minor improvements to the new Finance GUI (#10168)
|
||||
Change: Let AI developers edit non-editable AI/Game Script Parameters (#8895)
|
||||
Change: Allow building docks on clearable watered object tiles (#8514)
|
||||
Fix #8770: Center vehicle status bar icon (#10178)
|
||||
Fix: Crash if error message window is too wide for screen. (#10172)
|
||||
Fix #10155: Network games not syncing company settings properly (#10158)
|
||||
Fix #10154: Network game desync related to setting a random company face (#10157)
|
||||
Fix #10011: Incorrect infrastructure totals when overbuilding bay road stop (#10143)
|
||||
Fix #10117: Object burst limit allowed one fewer object than the setting (#10120)
|
||||
Fix #10023: Allow negative input in text fields when needed (#10112)
|
||||
Fix #9908: Fix crash which could occur when a company was deleted when a depot window was open (#9912)
|
||||
|
||||
|
||||
13.0-beta1 (2022-10-31)
|
||||
------------------------------------------------------------------------
|
||||
Feature: Airport construction GUI displays infrastructure cost (#10094)
|
||||
Feature: Purchase land multiple tiles at a time (#10027)
|
||||
Feature: Add sticky pin & shade widgets to Object Selection UI panel (#10019, #10020)
|
||||
Feature: Improved handling of HiDPI and mixed-DPI screens (#9994, #9996, #9997, #10064)
|
||||
Feature: Alternative linkgraph colour schemes (#9866)
|
||||
Feature: Allow Shift+Insert as paste in edit box (#9836)
|
||||
Feature: Setting to make the local town authority rubber-stamp all actions (#9833)
|
||||
Feature: Add/extend console commands to enable screenshot automation (#9771)
|
||||
Feature: [Linkgraph] Show a tooltip with statistics when hovering a link (#9760)
|
||||
Feature: Build objects by area (#9709)
|
||||
Feature: Add setting to hide news about competitors vehicle crash (#9653)
|
||||
Feature: Ctrl-click to remove fully autoreplaced vehicles from list (#9639)
|
||||
Feature: Wide rivers on map generation (#9628)
|
||||
Add: [Script] ScriptCargo::GetWeight to get cargo weights (#9930)
|
||||
Add: Command line option to skip NewGRF scanning (#9879)
|
||||
Add: Show video driver name in Game Options window (#9872)
|
||||
Add: [NewGRF] Map seed as global variable (#9834)
|
||||
Add: [Script] IndustryType::ResolveNewGRFID to resolve industry id from grf_local_id and grfid (#9798)
|
||||
Add: [Script] ObjectType::ResolveNewGRFID to resolve object id from grfid and grf_local_id (#9795)
|
||||
Update: To all the friends we have lost and those we have gained (#10000)
|
||||
Change: Use the Simulation subcategory to openttd.desktop (#10015)
|
||||
Change: Constantly update destination of 'any depot' orders (#9959)
|
||||
Change: Use an indent, not a dash, to list train capacity (#9887)
|
||||
Change: [NewGRF] Increase vehicle sprite stack from 4 layers to 8 (#9863)
|
||||
Change: Don't pay Property Maintenance on stations when Infrastructure Maintenance is disabled (#9828)
|
||||
Change: Improved layout of the finance window (#9827)
|
||||
Change: [Admin] Bump admin port protocol due to command changes (#9754)
|
||||
Change: Suppress vehicle age warnings for stopped vehicles (#9718)
|
||||
Change: Make pf.yapf.rail_firstred_twoway_eol on by default (#9544)
|
||||
Change: Deliver cargo to the closest industry first (#9536)
|
||||
Fix: Lots of fixes to how windows handle resizing (#10040, #10042, #10046, #10051, #10056, #10068, #10070, #10098)
|
||||
Fix: Console commands list_ai output was truncated with a suitably large number of AIs (#10075)
|
||||
Fix #9876: MacBook Touch Bar crash / render issues w/ 32bpp graphics (#10060)
|
||||
Fix: Reduce framerate overhead in Train::Tick (#10055)
|
||||
Fix: Only open scenario editor date query once (#10050)
|
||||
Fix #10048: Don't relocate company HQ on the same exact location (#10049)
|
||||
Fix #10038: Missing upper bounds check when loading custom playlists (#10039)
|
||||
Fix: Wrong string used to determine size of zoomed out station sign (#10036)
|
||||
Fix: Disable "turn around" button for other companies' road vehicles (#10033)
|
||||
Fix: Online Players list mouse hover behaviour (#10031)
|
||||
Fix: [NewGRF] Weirdness of new stations (#10017)
|
||||
Fix #9854: DrawStringMultiLine() could draw beyond its bounding box (#10014)
|
||||
Fix: Incorrect player name in online players window (#10013)
|
||||
Fix #8099: News window zoom level fixes (#10005)
|
||||
Fix: [NewGRF] Upper 16 random bits should be the same for all station tiles in callback 140 (#9992)
|
||||
Fix #9989: £0 Net Profit is neither negative nor positive (#9991)
|
||||
Fix #9804: Only apply sprite_zoom_min setting when sprites available (#9988)
|
||||
Fix #9972: Add missing fill/resize flags on Framerate window widgets (#9982)
|
||||
Fix #9935: Use more selectivity when building SSE specific code (#9980)
|
||||
Fix #9940: Print debuglevel parse errors to console when changed from console (#9979)
|
||||
Fix #9977: Clearing the console with a large number of lines could cause a crash (#9978)
|
||||
Fix #9974: Console command getsysdate did not work due to off-by-one error (#9975)
|
||||
Fix: [NewGRF] Default value of RailVehicleInfo::railveh_type was inconsistent with other default properties (#9967)
|
||||
Fix #8584: Vehicles with shared orders getting invalid or unexpected start dates (#9955)
|
||||
Fix #9951: [NewGRF] Scenario editor random industries button broke NewGRF persistent storage (#9952)
|
||||
Fix: Validation of various internal command parameters that could have allowed a rogue client to crash servers (#9942, #9943, #9944, #9945, #9946, #9947, #9948, #9950)
|
||||
Fix #9937: Station industries_near incorrect after removing part moved sign (#9938)
|
||||
Fix: [Script] ScriptRoad::HasRoadType really check for RoadType (#9934)
|
||||
Fix #9363: Rebuild client list on reinit event (#9929)
|
||||
Fix #9925: Industry tile layout validation for layouts of only one tile (#9926)
|
||||
Fix #9918: Reset industy last production year on scenario start (#9920)
|
||||
Fix #9914: Prevent more useless pathfinder run for blocked vehicles (#9917)
|
||||
Fix: List a max of four share owners instead of three (#9905)
|
||||
Fix: [NewGRF] Industry layouts with zero regular tiles should be invalid (#9902)
|
||||
Fix #9869: Remove docking tile when doing a clear square (#9898)
|
||||
Fix: New player companies use favorite manager face, if saved (#9895)
|
||||
Fix: Towns don't build parallel, redundant bridges (#9891)
|
||||
Fix #9712: Cap town bridge length at original 11-tile limit (#9890)
|
||||
Fix #9883: Show cost/income float over end tile of rail or road construction (#9889)
|
||||
Fix #9870: Don't update infrastructure totals when overbuilding object on canal (#9888)
|
||||
Fix #9877: GS could trigger 'Cost: £0' cost message (#9878)
|
||||
Fix 44f2ef1: [strgen] Allow gender for {CARGO_SHORT} (#9873)
|
||||
Fix #9867: Industry::stations_near not filled at industry creation (#9868)
|
||||
Fix #9853: Incorrect merge of guiflags and flags for osk_activation (#9855)
|
||||
Fix #6544: Don't join AI company when loading network game in singleplayer (#9794)
|
||||
Fix: Company values do not properly account for shares (#9770)
|
||||
Fix #9546: Crash when no industries are present in game (#9726)
|
||||
Fix #9708: [Linkgraph] Don't assume vehicles have a non-zero max speed (#9693)
|
||||
Fix #9665: [Linkgraph] Fix travel times of non-direct journeys (#9693)
|
||||
Fix #8797: Use logical rail length when placing signals (#9652)
|
||||
Cleanup: [NewGRF] Remove unused flag sprites (#10052)
|
||||
|
||||
|
||||
12.2 (2022-04-02)
|
||||
------------------------------------------------------------------------
|
||||
Feature: Remember the last-used signal between games (#9792)
|
||||
Change: [MacOS] Allow touchbar usage on all supported OS versions (#9776)
|
||||
Change: Add a timestamp in name of crash files (#9761)
|
||||
Fix #9736: Duplicate multiplayer window opens upon canceling password entry (#9842)
|
||||
Fix: Removing long roads doesn't prioritise refusal of local authority over other errors (#9831)
|
||||
Fix #9020: Glitchy station coverage highlight when changing selection (#9825)
|
||||
Fix: Correct some Romanian town names (#9819)
|
||||
Fix: Original music playback rate was slightly too fast (#9814)
|
||||
Fix #9811: Use the NewGRF-defined vehicle center when dragging ships and aircraft (#9812)
|
||||
Fix: Do not let shares in the company taking over another company disappear (#9808)
|
||||
Fix #9802: Crash when using lots of NewGRF waypoint types (#9803)
|
||||
Fix #9766: Don't write uninitialised data in config file (#9767)
|
||||
Fix #9743: [MacOS] Don't try to render touchbar sprites with invalid zoom level (#9776)
|
||||
Fix #9774: Building roadstop in estimation mode updates station acceptance (#9775)
|
||||
Fix: If vehicles only refit to cargo-slots >= 32, the default cargo was wrong (#9744)
|
||||
Fix #9735: Possible desync when replacing a depot on same tile (#9738)
|
||||
Fix #9730: [Network] Connections can use an invalid socket due to a race condition (#9731)
|
||||
Fix: Don't show sign edit window for GS-owned signs (#9716)
|
||||
Fix #9702: Display order window for vehicle group on ctrl-click only when using shared orders (#9704)
|
||||
Fix #9680: Crash when loading really old savegames with aircraft in certain places (#9699)
|
||||
Fix: Update last servicing dates when using the date cheat (#9694)
|
||||
Fix: Error message shows about missing glyphs while suitable fallback font is found (#9692)
|
||||
|
||||
|
||||
12.1 (2021-11-08)
|
||||
------------------------------------------------------------------------
|
||||
Feature: Button to toggle showing advanced signal types (#9617)
|
||||
Change: Don't show screenshot GUI in screenshots (#9674)
|
||||
Change: Suppress panning in intro game, while user is interacting with the GUI (#9645)
|
||||
Change: Draw rotor in cursor when dragging helicopters in depots (#9612)
|
||||
Fix: Invalid memory access when loading a currency NewGRF (#9675)
|
||||
Fix #9579: Object and HQ construction is Construction cost, not Property Maintenance (#9673)
|
||||
Fix #9669: Ships exiting a blocked depot/lock could exit in the wrong direction (#9672)
|
||||
Fix: Every 16th client never reconnects after server restart (#9666)
|
||||
Fix #9643: Screenshots were always written as BMP files (#9644)
|
||||
Fix #9630: Intro game could zoom in/out more than allowed by settings (#9633)
|
||||
Fix #9626: Incorrect loading of script saved data (#9629)
|
||||
Fix: Emergency crash save had the wrong NewGRF list saved in it (#9627)
|
||||
Fix #9595: Always use plural forms of cargo for subsidy strings (#9619)
|
||||
Fix #9614: Refresh rate dropdown was still active when vsync was enabled (#9618)
|
||||
Fix: Don't use 'server address' string in server list when displaying an invite code (#9615)
|
||||
|
||||
|
||||
12.0 (2021-10-17)
|
||||
------------------------------------------------------------------------
|
||||
Add: [Network] Keep the refresh button in lowered state while refreshing (#9600)
|
||||
Add: Console command to list search directories for various things (#9583)
|
||||
Fix: Try all possible reverse directions when a ship reaches a dead end (#9610)
|
||||
Fix: Incorrect Romanian own name (#9598)
|
||||
Fix #9591: Update station docking tiles upon placing a water object on a docking tile (#9594)
|
||||
Fix #9548: [Squirrel] Crash during engine cleanup after reaching memory limit on realloc (#9592)
|
||||
Fix #9588: [Squirrel] Reaching memory limit during script registration could prevent further script detections (#9589)
|
||||
Fix: Make ships more likely to find their destination at the cost of slightly worse paths (#9576)
|
||||
Change: Reverse ship when leaving docks if a better path exists (#9610)
|
||||
Change: Allow all tiles around docks to be docking tiles (#9578)
|
||||
|
||||
|
||||
12.0-RC1 (2021-09-25)
|
||||
------------------------------------------------------------------------
|
||||
Feature: Display icon/text whether vehicle is lost in vehicle (list) window (#9543)
|
||||
Feature: [MacOS] Add selected toolbar buttons to MacBook Pro Touch Bar (#9511)
|
||||
Feature: Button to open order window from vehicle shared orders window (#9325)
|
||||
Feature: Ctrl-Clicking shared order vehicle list opens order window (#9325)
|
||||
Feature: Multiple rotating views on title screen (#8980)
|
||||
Feature: Hide block signals in GUI by default (#8688)
|
||||
Add: [Script] Allow GameScripts to build neutral objects (#9568)
|
||||
Add: [Network] Allow sending chat messages via admin port (#9563)
|
||||
Add: [AI/GS] Missing water related functions and objects (#8390)
|
||||
Fix: Industry funding window did not update when changing funding method (#9572)
|
||||
Fix #9562: [NewGRF] Handle case of invalid Action2 with zero results (#9564)
|
||||
Fix: Incorrect error messages when placing water in scenario editor (#9560)
|
||||
Fix #9484: Update locale currencies settings config map (#9559)
|
||||
Fix: Prevent train reversing when entirely inside a train depot (#9557)
|
||||
Fix: [Network] Add back 'Spectate' option to company toolbar menu (#9556)
|
||||
Fix #9463: [Win32] Work around XAudio2 crashes (#9549)
|
||||
Fix #8603: Don't give focus to text filter when opening Object GUI (#9547)
|
||||
Fix #9241: Grove and forest tree brushes did not also create rainforest terrain (#9542)
|
||||
Fix: [Network] Several crashes in our network code (#9534, #9456)
|
||||
Fix #9527: Crash when trying to place multi-tile objects at map edge (#9529)
|
||||
Fix: [Network] SendCmdNames only sent one name per packet (#9528)
|
||||
Fix #9407: Desync when founding a town nearby a station (#9526)
|
||||
Fix #9521: Don't load at just removed docks that were part of a multi-dock station (#9524)
|
||||
Fix: Ships always tried to avoid docking tiles when pathfinding (even if nothing was on them) (#9522)
|
||||
Fix: [Network] Convert server_advertise to server_game_type in config file (#9515)
|
||||
Fix #9490: [Network] A full server couldn't be queried (#9508)
|
||||
Fix: [Network] Don't show GameScript " (v0)" for old servers (#9507)
|
||||
Fix: [Network] Show query errors in the server listing instead of error popup (#9506)
|
||||
Fix: [Network] Crash when last-joined server was no longer available (#9503)
|
||||
Fix #9501: [Network] Crash when more than one game-info query was pending (#9502)
|
||||
Fix: Wrong error message when building canals over ship depots / locks (#9410)
|
||||
Fix: Reduce cost of building canals over objects on sea (#9410)
|
||||
Change: [Linkgraph] Delete links only served by vehicles stopped in depot (#9499)
|
||||
|
||||
|
||||
12.0-beta2 (2021-08-19)
|
||||
------------------------------------------------------------------------
|
||||
Feature: [Linkgraph] Prioritize faster routes for passengers, mail and express cargo (#9457)
|
||||
|
@@ -43,6 +43,11 @@ macro(compile_flags)
|
||||
add_link_options(
|
||||
"$<$<NOT:$<CONFIG:Debug>>:-fstack-protector>" # Prevent undefined references when _FORTIFY_SOURCE > 0
|
||||
)
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
add_compile_options(
|
||||
"$<$<CONFIG:Debug>:-Wa,-mbig-obj>" # Switch to pe-bigobj-x86-64 as x64 Debug builds push pe-x86-64 to the limits (linking errors with ASLR, ...)
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Prepare a generator that checks if we are not a debug, and don't have asserts
|
||||
@@ -51,6 +56,11 @@ macro(compile_flags)
|
||||
|
||||
if(MSVC)
|
||||
add_compile_options(/W3)
|
||||
if(MSVC_VERSION GREATER 1929)
|
||||
# Starting with version 19.30, there is an optimisation bug, see #9966 for details
|
||||
# This flag disables the broken optimisation to work around the bug
|
||||
add_compile_options(/d2ssa-rse-)
|
||||
endif()
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
|
||||
add_compile_options(
|
||||
-W
|
||||
|
@@ -122,6 +122,8 @@ set(CPACK_STRIP_FILES YES)
|
||||
set(CPACK_OUTPUT_FILE_PREFIX "bundles")
|
||||
|
||||
if(APPLE)
|
||||
# Stripping would produce unreadable stacktraces.
|
||||
set(CPACK_STRIP_FILES NO)
|
||||
set(CPACK_GENERATOR "Bundle")
|
||||
include(PackageBundle)
|
||||
|
||||
@@ -129,7 +131,7 @@ if(APPLE)
|
||||
set(CPACK_PACKAGE_FILE_NAME "openttd-#CPACK_PACKAGE_VERSION#-macos-universal")
|
||||
else()
|
||||
set(CPACK_PACKAGE_FILE_NAME "openttd-#CPACK_PACKAGE_VERSION#-macos-${CPACK_SYSTEM_NAME}")
|
||||
endif()
|
||||
endif()
|
||||
elseif(WIN32)
|
||||
set(CPACK_GENERATOR "ZIP")
|
||||
if(OPTION_USE_NSIS)
|
||||
@@ -181,6 +183,10 @@ elseif(UNIX)
|
||||
if(DISTRO_ID STREQUAL "arch")
|
||||
set(PLATFORM "arch")
|
||||
set(CPACK_GENERATOR "TXZ")
|
||||
elseif(DISTRO_ID STREQUAL "fedora" OR DISTRO_ID STREQUAL "rhel")
|
||||
set(PLATFORM "fedora")
|
||||
set(CPACK_GENERATOR "RPM")
|
||||
include(PackageRPM)
|
||||
else()
|
||||
set(UNSUPPORTED_PLATFORM_NAME "Linux distribution '${DISTRO_ID}' from /etc/os-release")
|
||||
endif()
|
||||
|
@@ -18,6 +18,6 @@ function(link_package NAME)
|
||||
message(STATUS "${NAME} found -- -DWITH_${UCNAME} -- ${${NAME}_INCLUDE_DIRS} ${${NAME}_INCLUDE_DIR} -- ${${NAME}_LIBRARIES} ${${NAME}_LIBRARY}")
|
||||
endif()
|
||||
elseif(LP_ENCOURAGED)
|
||||
message(WARNING "${NAME} not found; compiling OpenTTD without ${NAME} is strongly disencouraged")
|
||||
message(WARNING "${NAME} not found; compiling OpenTTD without ${NAME} is strongly discouraged")
|
||||
endif()
|
||||
endfunction()
|
||||
|
@@ -3,6 +3,7 @@
|
||||
source_group("AI Core" REGULAR_EXPRESSION "src/ai/")
|
||||
source_group("Blitters" REGULAR_EXPRESSION "src/blitter/")
|
||||
source_group("Core Source Code" REGULAR_EXPRESSION "src/core/")
|
||||
source_group("Font Cache" REGULAR_EXPRESSION "src/fontcache/")
|
||||
source_group("Game Core" REGULAR_EXPRESSION "src/game/")
|
||||
source_group("MD5" REGULAR_EXPRESSION "src/3rdparty/md5/")
|
||||
source_group("Misc" REGULAR_EXPRESSION "src/misc/")
|
||||
|
1
cmake/PackageRPM.cmake
Normal file
1
cmake/PackageRPM.cmake
Normal file
@@ -0,0 +1 @@
|
||||
set(CPACK_RPM_PACKAGE_ARCHITECTURE "${ARCHITECTURE}")
|
@@ -13,6 +13,7 @@ cmake_minimum_required(VERSION 3.5)
|
||||
# The parameter "enumname" specifies the enumeration to extract. This can also be a regular expression.
|
||||
# The parameter "filename" specifies the relative path to the file, where the enumeration is extracted from. This can also be a glob expression.
|
||||
#
|
||||
# All files where enumerations are extracted from are automatically added via #include
|
||||
#
|
||||
|
||||
if(NOT GENERATE_SOURCE_FILE)
|
||||
@@ -41,6 +42,7 @@ foreach(ENUM IN LISTS ENUM_LINES)
|
||||
|
||||
string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" FILE ${FILE})
|
||||
string(APPEND ${PLACE_HOLDER} "\n${ADD_INDENT}/* automatically generated from ${FILE} */")
|
||||
list(APPEND INCLUDES "#include \"${FILE}\"")
|
||||
|
||||
foreach(LINE IN LISTS SOURCE_LINES)
|
||||
string(REPLACE "${RM_INDENT}" "" LINE "${LINE}")
|
||||
@@ -116,4 +118,7 @@ foreach(ENUM IN LISTS ENUM_LINES)
|
||||
endforeach()
|
||||
endforeach()
|
||||
|
||||
list(REMOVE_DUPLICATES INCLUDES)
|
||||
string(REPLACE ";" "\n" INCLUDES "${INCLUDES}")
|
||||
|
||||
configure_file(${GENERATE_SOURCE_FILE} ${GENERATE_BINARY_FILE})
|
||||
|
@@ -35,6 +35,7 @@ execute_process(COMMAND ${OPENTTD_EXECUTABLE}
|
||||
-vnull:ticks=30000
|
||||
-d script=2
|
||||
-d misc=9
|
||||
-Q
|
||||
OUTPUT_VARIABLE REGRESSION_OUTPUT
|
||||
ERROR_VARIABLE REGRESSION_RESULT
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
|
@@ -12,32 +12,11 @@ endif()
|
||||
if(NOT APIUC)
|
||||
message(FATAL_ERROR "Script needs APIUC defined")
|
||||
endif()
|
||||
if(NOT API_FILES)
|
||||
message(FATAL_ERROR "Script needs API_FILES defined")
|
||||
endif()
|
||||
|
||||
set(ARGC 1)
|
||||
set(ARG_READ NO)
|
||||
|
||||
# For MSVC CMake runs this script from a batch file using || to detect errors,
|
||||
# depending on source path it may quote args, and cause cmd to not understand ||
|
||||
# and pass it as argument to ourself.
|
||||
# Read all the arguments given to CMake; we are looking for -- and everything
|
||||
# that follows, until ||. Those are our api files.
|
||||
while(ARGC LESS CMAKE_ARGC)
|
||||
set(ARG ${CMAKE_ARGV${ARGC}})
|
||||
|
||||
if(ARG STREQUAL "||")
|
||||
set(ARG_READ NO)
|
||||
endif()
|
||||
|
||||
if(ARG_READ)
|
||||
list(APPEND SCRIPT_API_BINARY_FILES "${ARG}")
|
||||
endif()
|
||||
|
||||
if(ARG STREQUAL "--")
|
||||
set(ARG_READ YES)
|
||||
endif()
|
||||
|
||||
math(EXPR ARGC "${ARGC} + 1")
|
||||
endwhile()
|
||||
file(READ "${API_FILES}" SCRIPT_API_BINARY_FILES)
|
||||
|
||||
foreach(FILE IN LISTS SCRIPT_API_BINARY_FILES)
|
||||
file(STRINGS "${FILE}" LINES REGEX "^void SQ${APIUC}.*_Register\\(Squirrel \\*engine\\)$")
|
||||
|
117
docs/eints.md
Normal file
117
docs/eints.md
Normal file
@@ -0,0 +1,117 @@
|
||||
# Translations for OpenTTD
|
||||
|
||||
Eints is [OpenTTD's WebTranslator](https://translator.openttd.org/).
|
||||
|
||||
- Registered translators translate from English to their language.
|
||||
- Eints validates the translations syntactically and that parameter usage matches the English base language.
|
||||
- Eints synchronises translations to OpenTTD's repository every day, shortly before the nightly build.
|
||||
|
||||
When adding or altering strings in english.txt, you should stick to some rules, so translations are handled smoothly by Eints and translators.
|
||||
This document gives some guidelines.
|
||||
|
||||
|
||||
## I want to change a translation.
|
||||
|
||||
### I want to become a regular translator.
|
||||
|
||||
Just [sign up](https://github.com/OpenTTD/team/issues/new/choose) as a translator.
|
||||
|
||||
### I only want to point out some issues / typos in the current translation, or suggest a change.
|
||||
|
||||
[Open an issue](https://github.com/OpenTTD/OpenTTD/issues/new/choose), so it can be assigned to the translation team of the language.
|
||||
The translators will decide whether, where and how to apply your suggestion.
|
||||
|
||||
### I want to submit translations via PR.
|
||||
|
||||
Sorry, we don't offer this option.
|
||||
|
||||
### I want to change the language definition (plural form, genders, cases) of a translation.
|
||||
|
||||
Please [create an issue](https://github.com/OpenTTD/OpenTTD/issues/new/choose) for this.
|
||||
|
||||
### I want to add an entirely new translation language.
|
||||
|
||||
OpenTTD has more than 4000 strings, translating all of them is a lot of work.
|
||||
Despite the initial enthusiasm, only few people have the endurance to get to even 20% translation progress.
|
||||
|
||||
As such, starting a new translation requires the prospect that there is also translation interest in the future.
|
||||
And, frankly, OpenTTD probably already covers all languages to which this applies, and a few more.
|
||||
|
||||
If you still want to make the case, that your language is spoken by several 100 million people, please [create an issue](https://github.com/OpenTTD/OpenTTD/issues/new/choose) for adding a new language.
|
||||
|
||||
|
||||
## I want to change the English base language (english.txt).
|
||||
|
||||
### I want to change the wording / fix a typo in an English string, without changing the meaning (drastically).
|
||||
|
||||
Just change it in your PR.
|
||||
|
||||
Translators will be notified that their translation became "outdated", so they can double-check whether the translation needs updating.
|
||||
|
||||
### I want to add/change/remove parameters from an English string.
|
||||
|
||||
Just change the parameters in english.txt in your PR.
|
||||
Don't touch the translations, please ignore compile warnings about them.
|
||||
|
||||
Translators will be notified that their translation became "invalid", so they can adjust the translation.
|
||||
Eints will remember the old translations for translators to view, but remove them from the git repository, while they are "invalid"; so there won't be any compile warnings after the nightly sync.
|
||||
|
||||
### I want to change the meaning of an English string, so that no existing translation makes any sense anymore.
|
||||
|
||||
In this case, please change the STR_xxx string identifier of the string; basically: remove the old string, add a new one.
|
||||
Don't touch the translations, please ignore compile warnings about them.
|
||||
|
||||
Eints will discard all memory of the old strings in the nightly sync, and translators can start fresh with a new string.
|
||||
|
||||
### I want to add a new string.
|
||||
|
||||
Add the new string somewhere in english.txt, where it fits with the neighbouring strings.
|
||||
Don't touch the translations, even if you can speak some of the languages.
|
||||
|
||||
### I want to remove an unused string.
|
||||
|
||||
Remove the string from english.txt.
|
||||
Don't touch the translations, please ignore compile warnings about them.
|
||||
|
||||
Eints will remove the translations from the git repository in the nightly sync.
|
||||
|
||||
### I want to reorder strings in english.txt without changing them.
|
||||
|
||||
Reorder english.txt as you like. Don't touch the translations.
|
||||
|
||||
Eints will reorder all translations to match english.txt in the nightly sync.
|
||||
|
||||
### I want to add/change '#' comments.
|
||||
|
||||
Change comments in english.txt as you like. Don't touch the translations.
|
||||
|
||||
Eints will replicate comments into all translations in the nightly sync. Comments are not translated.
|
||||
|
||||
### I want to change the STR_xxx string identifier for code style reasons, without changing the English text.
|
||||
|
||||
This is the only case, where your PR should also edit translations.
|
||||
The STR_xxx string identifier is used by Eints as key value to track strings and translations. If you change it, that's the same as deleting a string and adding an unrelated new one.
|
||||
So, to keep translations, you have to replace the STR_xxx for all translations in the PR as well.
|
||||
|
||||
However, you will only be able to keep the translations which are part of the git repository.
|
||||
Translation history and information about translations being "outdated" will be lost.
|
||||
So, keep your code style OCD to a minimum :)
|
||||
|
||||
|
||||
## I want to fight a bot and lose.
|
||||
|
||||
Here are some things, people sometimes want to do, but which won't work.
|
||||
|
||||
### I want to enforce re-translation by clearing current translations.
|
||||
|
||||
You have to change the STR_xxx string identifier, that's the only option.
|
||||
|
||||
You cannot "clear" translations by removing them via PR; eints will reinstall the previous "syntactically perfect valid" translation.
|
||||
|
||||
### I want to revert a broken change, some translator just did via eints.
|
||||
|
||||
You have to revert the translations via the WebTranslator interface.
|
||||
If there are many changes, ask someone with Admin access to eints, so they can manually upload a fixed translation file to eints.
|
||||
|
||||
You cannot revert translations changes via PR. Eints merges translations from git and from web by keeping a translation history, and committing the newest translation to git.
|
||||
If you revert to an old translation in git, eints will simply think git did not yet get the newer translation, and commit it again.
|
@@ -1,225 +1,207 @@
|
||||
# Multiplayer manual for OpenTTD
|
||||
|
||||
Last updated: 2011-02-16
|
||||
|
||||
|
||||
## Table of contents
|
||||
|
||||
- 1.0) [Starting a server](#10-starting-a-server)
|
||||
- 2.0) [Connecting to a server](#20-connecting-to-a-server)
|
||||
- 2.1) [Connecting to a server over the console](#21-connecting-to-a-server-over-the-console)
|
||||
- 2.1) [Connecting to a server over the console](#21-connecting-to-a-server-over-the-console)
|
||||
- 3.0) [Playing internet games](#30-playing-internet-games)
|
||||
- 4.0) [Tips for servers](#40-tips-for-servers)
|
||||
- 4.1)[Imposing landscaping limits](#41-imposing-landscaping-limits)
|
||||
- 4.1)[Imposing landscaping limits](#41-imposing-landscaping-limits)
|
||||
- 5.0) [Some useful things](#50-some-useful-things)
|
||||
- 6.0) [Troubleshooting](#60-troubleshooting)
|
||||
|
||||
|
||||
## 1.0) Starting a server
|
||||
|
||||
- Make sure that you have your firewall of the computer as well as possible
|
||||
routers or modems of the server configured such that:
|
||||
- port 3979 is free for both UDP and TCP connections in- and outgoing
|
||||
- port 3978 is free outbound for UDP in order to advertise with the master
|
||||
server (if desired). Otherwise you'll have to tell players your IP.
|
||||
- port 3977 if use of the admin interface is desired (see admin_network.txt)
|
||||
- Click "multiplayer" on the startup screen
|
||||
- Click "start server"
|
||||
- Type in a game name
|
||||
- Select the type of game ('LAN/Internet' or 'Internet (advertise)'. With the
|
||||
last one other people are able to see you online. Else they need your IP and
|
||||
port to join)
|
||||
- Click "start game", "load game" or "load scenario"
|
||||
- Start playing
|
||||
|
||||
- Click on "Multiplayer" in the Start Menu.
|
||||
- Click on "Start Server".
|
||||
- Give your server a name.
|
||||
- Select the visibility of your server:
|
||||
- "Public": your server will be publicly listed.
|
||||
- "Invite Only": only players who have the invite code for your server can
|
||||
join.
|
||||
- "Local": only players on your local network can join.
|
||||
- (optional) Set a password for your server.
|
||||
- Click "New Game", "Load Game", or "Play Scenario".
|
||||
- Start playing.
|
||||
|
||||
## 2.0) Connecting to a server
|
||||
|
||||
- Click "multiplayer" on the startup screen
|
||||
- If you want to connect to any network game in your LAN click on 'LAN', then
|
||||
on 'Find Server'
|
||||
- If you want to see which servers all online on the Internet, click on
|
||||
'Internet' and 'Find Server'
|
||||
- If there were more than one server
|
||||
- select one in the list below the buttons
|
||||
- click on 'join game'
|
||||
- If you want to play and you have the ip or hostname of the game server you
|
||||
want connect to.
|
||||
- click add server
|
||||
- type in the ip address or hostname
|
||||
- if you want to add a port use :<port>
|
||||
- If you want to play and you have the invite code of the game server you
|
||||
want connect to.
|
||||
- click add server
|
||||
- type in the invite code
|
||||
- Now you can select a company and press: "Join company", to help that company
|
||||
- Or you can press "Spectate game", to spectate the game
|
||||
- Or you can press "New company", and start your own company (if there are
|
||||
slots free)
|
||||
- You see a progressbar how far you are with joining the server.
|
||||
- Happy playing
|
||||
- Click on "Multiplayer" in the Start Menu.
|
||||
- There are three ways to join a server:
|
||||
- If you want to connect to a local server, click "Search LAN".
|
||||
- If you want to connect to a public game, click "Search internet".
|
||||
- If the server-owner shared an invite code with you:
|
||||
- Click "Add Server".
|
||||
- Fill in the invite code, which always starts with a `+`.
|
||||
- Click "OK".
|
||||
- Click on the server you want to join.
|
||||
- Click "Join Game".
|
||||
- If the server has a password, it will ask you for this.
|
||||
- You see a progressbar how far you are with joining the server.
|
||||
- Happy playing.
|
||||
|
||||
## 2.1) Connecting to a server over the console
|
||||
|
||||
- Open the console and type in the following command:
|
||||
connect `<ip/host>:<port>#<company-no>`
|
||||
|
||||
- Open the console and type `connect` for help how to connect via the console.
|
||||
|
||||
## 3.0) Playing internet games
|
||||
|
||||
- Servers with a red dot behind it have a different version then you have. You
|
||||
will not be able to join those servers.
|
||||
- Servers with a red dot behind it have a different version then you have. You
|
||||
will not be able to join those servers.
|
||||
|
||||
- Servers with a yellow dot behind it have NewGRFs that you do not have. You
|
||||
will not be able to join those servers. However, via "NewGRF Settings" and
|
||||
"Find missing content online" you might be able to download the needed
|
||||
NewGRFs after which you can join the server.
|
||||
- Servers with a yellow dot behind it have NewGRFs that you do not have. You
|
||||
will not be able to join those servers. However, via "NewGRF Settings" and
|
||||
"Find missing content online" you might be able to download the needed
|
||||
NewGRFs after which you can join the server.
|
||||
|
||||
- It can happen that a connection is that slow, or you have that many clients
|
||||
connected to your server, that your clients start to loose their connection.
|
||||
Some things you can do about it:
|
||||
- [network] frame_freq:
|
||||
change it in console with: 'set network.frame_freq <number>'
|
||||
the number should be between the 0 and 10, not much higher. It indicates
|
||||
the delay between clicking and showing up. The higher, the more you notice
|
||||
it, but the less bandwidth you use.
|
||||
A good value for Internet-games is 2 or 3.
|
||||
- It can happen that a connection is that slow, or you have that many clients
|
||||
connected to your server, that your clients start to loose their connection.
|
||||
Some things you can do about it:
|
||||
- `[network] frame_freq`:
|
||||
change it in console with: `set network.frame_freq <number>`
|
||||
the number should be between the 0 and 10, not much higher. It indicates
|
||||
the delay between clicking and showing up. The higher, the more you notice
|
||||
it, but the less bandwidth you use.
|
||||
A good value for Internet-games is 2 or 3.
|
||||
|
||||
- [network] sync_freq:
|
||||
change it in console with: 'set network.sync_freq <number>'
|
||||
the number should be between the 50 and 1000, not much lower, not much
|
||||
higher. It indicates the time between sync-frames. A sync-frame is a frame
|
||||
which checks if all clients are still in sync. When the value it too high,
|
||||
clients can desync in 1960, but the server detects it in 1970. Not really
|
||||
handy. The lower the value, the more bandwidth it uses.
|
||||
|
||||
NB: changing frame_freq has more effect on the bandwidth then sync_freq.
|
||||
- `[network] sync_freq`:
|
||||
change it in console with: `set network.sync_freq <number>`
|
||||
the number should be between the 50 and 1000, not much lower, not much
|
||||
higher. It indicates the time between sync-frames. A sync-frame is a frame
|
||||
which checks if all clients are still in sync. When the value it too high,
|
||||
clients can desync in 1960, but the server detects it in 1970. Not really
|
||||
handy. The lower the value, the more bandwidth it uses.
|
||||
|
||||
NB: changing `frame_freq` has more effect on the bandwidth then `sync_freq`.
|
||||
|
||||
## 4.0) Tips for servers
|
||||
|
||||
- You can launch a dedicated server by adding -D as parameter.
|
||||
- In UNIX like systems, you can fork your dedicated server by adding -f as
|
||||
parameter.
|
||||
- You can launch a dedicated server by adding `-D` as parameter.
|
||||
- In UNIX like systems, you can fork your dedicated server by adding `-f` as
|
||||
parameter.
|
||||
|
||||
- You can automatically clean companies that do not have a client connected to
|
||||
them, for, let's say, 3 years. You can do this via: 'set autoclean_companies'
|
||||
and 'set autoclean_protected' and 'set autoclean_unprotected'. Unprotected
|
||||
removes a password from a company when it is not used for more then the
|
||||
defined amount of months. 'set autoclean_novehicles' can be used to remove
|
||||
companies without any vehicles quickly.
|
||||
- You can automatically clean companies that do not have a client connected to
|
||||
them, for, let's say, 3 years. You can do this via: `set autoclean_companies`
|
||||
and `set autoclean_protected` and `set autoclean_unprotected`. Unprotected
|
||||
removes a password from a company when it is not used for more then the
|
||||
defined amount of months. `set autoclean_novehicles` can be used to remove
|
||||
companies without any vehicles quickly.
|
||||
|
||||
- You can also do this manually via the console: 'reset_company'.
|
||||
- You can also do this manually via the console: `reset_company`.
|
||||
|
||||
- You can let your server automatically restart a map when, let's say, year 2030
|
||||
is reached. See 'set restart_game_date' for detail.
|
||||
- You can let your server automatically restart a map when, let's say,
|
||||
year 2030 is reached. See `set restart_game_date` for detail.
|
||||
|
||||
- If you want to be on the server-list, make your server public. You can do
|
||||
this either from the Start Server GUI, via the in-game Online Players GUI,
|
||||
or by typing in the console:
|
||||
'set server_game_type public'.
|
||||
- If you want to be on the server-list, make your server public. You can do
|
||||
this either from the Start Server window, via the in-game Online Players
|
||||
window, or by typing in the console: `set server_game_type public`.
|
||||
|
||||
- You can protect your server with a password via the console: 'set server_pw',
|
||||
or via the Start Server menu.
|
||||
- You can protect your server with a password via the console: `set server_pw`,
|
||||
or via the Start Server menu.
|
||||
|
||||
- When you have many clients connected to your server via Internet, watch your
|
||||
bandwidth (if you have any limit on it, set by your ISP). One client uses
|
||||
about 1.5 kilobytes per second up and down. To decrease this amount, setting
|
||||
'frame_freq' to 1 will reduce it to roughly 1 kilobyte per second per client.
|
||||
- When you have many clients connected to your server via Internet, watch your
|
||||
bandwidth (if you have any limit on it, set by your ISP). One client uses
|
||||
about 1.5 kilobytes per second up and down. To decrease this amount, setting
|
||||
`frame_freq` to 1 will reduce it to roughly 1 kilobyte per second per client.
|
||||
|
||||
- OpenTTD's default settings for maximum number of clients, and amount of data
|
||||
from clients to process are chosen to not influence the normal playing of
|
||||
people, but to prevent or at least make it less likely that someone can
|
||||
perform a (distributed) denial-of-service attack on your server by causing
|
||||
an out-of-memory event by flooding the server with data to send to all
|
||||
clients. The major factor in this is the maximum number of clients; with
|
||||
32 clients "only" sending one chat message causes 1024 messages to be
|
||||
distributed in total, with 64 clients that already quadruples to 4096. Given
|
||||
that upstream bandwidth is usually the limiting factor, a queue of packets
|
||||
that need to be sent will be created.
|
||||
To prevent clients from exploiting this "explosion" of packets to send we
|
||||
limit the number of incoming data, resulting in effectively limiting the
|
||||
amount of data that OpenTTD will send to the clients. Even with the default
|
||||
limits it is possible to generate about 70.000 packets per second, or about
|
||||
7 megabit per second of traffic.
|
||||
Given that OpenTTD kicks clients after they have not reacted within about 9
|
||||
seconds from sending a frame update packet it would be possible that OpenTTD
|
||||
keeps about 600.000 packets in memory, using about 50 megabytes of memory.
|
||||
Given that OpenTTD allows short bursts of packets, you can have slightly
|
||||
more packets in memory in case of a distributed denial of service attack.
|
||||
When increasing the amount of incoming data, or the maximum number of
|
||||
clients the amount of memory OpenTTD needs in case of a distributed denial
|
||||
of service attack is linearly related to the amount of incoming data and
|
||||
quadratic to the amount of clients. In short, a rule of thumb for, the
|
||||
maximum memory usage for packets is:
|
||||
#max_clients * #max_clients * bytes_per_frame * 10 KiB.
|
||||
- OpenTTD's default settings for maximum number of clients, and amount of data
|
||||
from clients to process are chosen to not influence the normal playing of
|
||||
people, but to prevent or at least make it less likely that someone can
|
||||
perform a (distributed) denial-of-service attack on your server by causing
|
||||
an out-of-memory event by flooding the server with data to send to all
|
||||
clients. The major factor in this is the maximum number of clients; with
|
||||
32 clients "only" sending one chat message causes 1024 messages to be
|
||||
distributed in total, with 64 clients that already quadruples to 4096. Given
|
||||
that upstream bandwidth is usually the limiting factor, a queue of packets
|
||||
that need to be sent will be created.
|
||||
To prevent clients from exploiting this "explosion" of packets to send we
|
||||
limit the number of incoming data, resulting in effectively limiting the
|
||||
amount of data that OpenTTD will send to the clients. Even with the default
|
||||
limits it is possible to generate about 70.000 packets per second, or about
|
||||
7 megabit per second of traffic.
|
||||
Given that OpenTTD kicks clients after they have not reacted within about 9
|
||||
seconds from sending a frame update packet it would be possible that OpenTTD
|
||||
keeps about 600.000 packets in memory, using about 50 megabytes of memory.
|
||||
Given that OpenTTD allows short bursts of packets, you can have slightly
|
||||
more packets in memory in case of a distributed denial of service attack.
|
||||
When increasing the amount of incoming data, or the maximum number of
|
||||
clients the amount of memory OpenTTD needs in case of a distributed denial
|
||||
of service attack is linearly related to the amount of incoming data and
|
||||
quadratic to the amount of clients. In short, a rule of thumb for, the
|
||||
maximum memory usage for packets is:
|
||||
`#max_clients * #max_clients * bytes_per_frame * 10 KiB`.
|
||||
|
||||
### 4.1) Imposing landscaping limits
|
||||
|
||||
- You can impose limits on companies by the following 4 settings:
|
||||
- terraform_per_64k_frames
|
||||
- terraform_frame_burst
|
||||
- clear_per_64k_frames
|
||||
- clear_frame_burst
|
||||
- You can impose limits on companies by the following 4 settings:
|
||||
- `terraform_per_64k_frames`
|
||||
- `terraform_frame_burst`
|
||||
- `clear_per_64k_frames`
|
||||
- `clear_frame_burst`
|
||||
|
||||
- Explaining 'per_64K_frames' and 'burst'
|
||||
- 'burst' defines 3 things, the maximum limit, the limit of a single action,
|
||||
and the initial value for the limit assigned to a new company.
|
||||
This setting is fairly simple and requires no math.
|
||||
- Explaining `NNN_burst` and `NNN_per_64K_frames`
|
||||
- `NNN_burst` defines 3 things, the maximum limit, the limit of a single
|
||||
action, and the initial value for the limit assigned to a new company.
|
||||
This setting is fairly simple and requires no math.
|
||||
|
||||
A value of 1 means a single tile can be affected by a single action.
|
||||
This results in having to click 400 times when wanting to cover an area
|
||||
of 20 x 20 tiles.
|
||||
A value of 1 means a single tile can be affected by a single action.
|
||||
This results in having to click 400 times when wanting to cover an area
|
||||
of 20 x 20 tiles.
|
||||
|
||||
The default value 4096 covers an area of 64 x 64 tiles.
|
||||
The default value 4096 covers an area of 64 x 64 tiles.
|
||||
|
||||
- 'per_64k_frames' defines the number of tiles added to each companies limit
|
||||
per frame (however not past the possible maximum value,the 'burst').
|
||||
64k rather resembles the exact number of 65536 frames. So setting this
|
||||
variable to 65536 means: 65536 / 65536 = 1 tile per frame.
|
||||
As a day consists of 74 frames, a company's limit is increased by 74
|
||||
tiles during the course of a single day (2.22 seconds).
|
||||
- `NNN_per_64K_frames` defines the number of tiles added to each companies
|
||||
limit per frame (however not past the possible maximum value,the
|
||||
`NNN_burst`). 64k rather resembles the exact number of 65536 frames. So
|
||||
setting this variable to 65536 means: `65536 / 65536 = 1 tile per frame`.
|
||||
|
||||
To achieve a 1 tile per day increase the following calculation is needed:
|
||||
1 / 74 (frames per day) * 65536 (per_64k_frames) = 885.62...
|
||||
after rounding: a value of 886 means adding a bit over 1 tile per day.
|
||||
As a day consists of 74 frames, a company's limit is increased by 74
|
||||
tiles during the course of a single day (2.22 seconds).
|
||||
To achieve a 1 tile per day increase the following calculation is needed:
|
||||
`1 / 74 (frames per day) * 65536 (per_64k_frames) = 885.62...`.
|
||||
After rounding: a value of 886 means adding a bit over 1 tile per day.
|
||||
|
||||
There is still enough space to scale this value downwards:
|
||||
decreasing this value to 127 results in a bit over 1 tile added to the
|
||||
allowance per week (7 days).
|
||||
There is still enough space to scale this value downwards:
|
||||
decreasing this value to 127 results in a bit over 1 tile added to the
|
||||
allowance per week (7 days).
|
||||
|
||||
To create a setup in which a company gets an initial allowance only,
|
||||
set the value to 0 - no increase of the allowance per frame.
|
||||
|
||||
- Even though construction actions include a clear tile action, they are not
|
||||
affected by the above settings.
|
||||
To create a setup in which a company gets an initial allowance only,
|
||||
set the value to 0 - no increase of the allowance per frame.
|
||||
|
||||
- Even though construction actions include a clear tile action, they are not
|
||||
affected by the above settings.
|
||||
|
||||
## 5.0) Some useful things
|
||||
|
||||
- You can protect your company so nobody else can join uninvited. To do this,
|
||||
set a password in your Company Screen
|
||||
- You can protect your company so nobody else can join uninvited. To do this,
|
||||
set a password in your Company window.
|
||||
|
||||
- You can give other players some money via the ClientList (under the 'head'
|
||||
in the mainbar).
|
||||
|
||||
- You can chat with other players via ENTER or via SHIFT+T or via the ClientList
|
||||
|
||||
- Servers can now kick players, so don't make them use it!
|
||||
- You can chat with other players via ENTER or via SHIFT+T or via the Online
|
||||
Players window
|
||||
|
||||
- Servers can kick players, so don't make them use it!
|
||||
|
||||
## 6.0) Troubleshooting
|
||||
|
||||
- My advertising server does not show up in list at servers.openttd.org
|
||||
Run openttd with the '-d net=2' parameter. That will show which incoming
|
||||
communication is received, whether the replies from the master server or
|
||||
communication from an admin tool reach the programme. See section 1
|
||||
'Starting a server' further up for the ports and protocols used by OpenTTD.
|
||||
The ports can be configured in the config file.
|
||||
### My server does not show up in the serverlist
|
||||
|
||||
- My advertising server warns a lot about getaddrinfo taking N seconds
|
||||
This could be a transient issue with your (local) DNS server, but if the
|
||||
problem persists there is likely a configuration issue in DNS resolving
|
||||
on your computer. This seems to be a common configuration issue for
|
||||
Docker instances, where the DNS resolving waits for a time out of usually
|
||||
5 seconds.
|
||||
Check if the visibility of your server is set to `public`.
|
||||
|
||||
If it is, and your server still isn't showing up, start OpenTTD with
|
||||
`-d net=4` as extra argument. This will show debug message related to the
|
||||
network, including communication to/from the Game Coordinator.
|
||||
|
||||
### My server warns a lot about getaddrinfo taking N seconds
|
||||
|
||||
This could be a transient issue with your (local) DNS server, but if the
|
||||
problem persists there is likely a configuration issue in DNS resolving on
|
||||
your computer.
|
||||
|
||||
#### Running OpenTTD in a Docker container?
|
||||
|
||||
This is an issue with dual-stack Docker containers. If there is no default
|
||||
IPv6 resolver and IPv6 traffic is preferred, DNS requests will time out after
|
||||
5 seconds. To resolve this, use an IPv4 DNS server for your Docker container,
|
||||
for example by adding `--dns 1.1.1.1` to your `docker run` command.
|
||||
|
@@ -17,6 +17,7 @@ set(BASESET_OTHER_SOURCE_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/openttd.grf
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/opntitle.dat
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/orig_extra.grf
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../openttd.32.bmp
|
||||
)
|
||||
|
||||
# Done by the subdirectories, if nforenum / grfcodec is installed
|
||||
|
Binary file not shown.
@@ -1,43 +0,0 @@
|
||||
// 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/>.
|
||||
//
|
||||
-1 * 0 0C "Flag graphics"
|
||||
-1 * 3 05 14 24
|
||||
-1 sprites/flags.png 8bpp 34 8 11 8 0 0 normal
|
||||
-1 sprites/flags.png 8bpp 50 8 11 8 0 0 normal
|
||||
-1 sprites/flags.png 8bpp 66 8 11 8 0 0 normal
|
||||
-1 sprites/flags.png 8bpp 82 8 11 8 0 0 normal
|
||||
-1 sprites/flags.png 8bpp 98 8 11 8 0 0 normal
|
||||
-1 sprites/flags.png 8bpp 114 8 11 8 0 0 normal
|
||||
-1 sprites/flags.png 8bpp 130 8 11 8 0 0 normal
|
||||
-1 sprites/flags.png 8bpp 146 8 11 8 0 0 normal
|
||||
-1 sprites/flags.png 8bpp 162 8 11 8 0 0 normal
|
||||
-1 sprites/flags.png 8bpp 178 8 11 8 0 0 normal
|
||||
-1 sprites/flags.png 8bpp 194 8 11 8 0 0 normal
|
||||
-1 sprites/flags.png 8bpp 210 8 11 8 0 0 normal
|
||||
-1 sprites/flags.png 8bpp 226 8 11 8 0 0 normal
|
||||
-1 sprites/flags.png 8bpp 242 8 11 8 0 0 normal
|
||||
-1 sprites/flags.png 8bpp 258 8 11 8 0 0 normal
|
||||
-1 sprites/flags.png 8bpp 274 8 11 8 0 0 normal
|
||||
-1 sprites/flags.png 8bpp 290 8 11 8 0 0 normal
|
||||
-1 sprites/flags.png 8bpp 306 8 11 8 0 0 normal
|
||||
-1 sprites/flags.png 8bpp 322 8 11 8 0 0 normal
|
||||
-1 sprites/flags.png 8bpp 338 8 11 8 0 0 normal
|
||||
-1 sprites/flags.png 8bpp 354 8 11 8 0 0 normal
|
||||
-1 sprites/flags.png 8bpp 370 8 11 8 0 0 normal
|
||||
-1 sprites/flags.png 8bpp 386 8 11 8 0 0 normal
|
||||
-1 sprites/flags.png 8bpp 402 8 11 8 0 0 normal
|
||||
-1 sprites/flags.png 8bpp 418 8 11 8 0 0 normal
|
||||
-1 sprites/flags.png 8bpp 434 8 11 8 0 0 normal
|
||||
-1 sprites/flags.png 8bpp 450 8 11 8 0 0 normal
|
||||
-1 sprites/flags.png 8bpp 466 8 11 8 0 0 normal
|
||||
-1 sprites/flags.png 8bpp 482 8 11 8 0 0 normal
|
||||
-1 sprites/flags.png 8bpp 498 8 11 8 0 0 normal
|
||||
-1 sprites/flags.png 8bpp 514 8 11 8 0 0 normal
|
||||
-1 sprites/flags.png 8bpp 530 8 11 8 0 0 normal
|
||||
-1 sprites/flags.png 8bpp 546 8 11 8 0 0 normal
|
||||
-1 sprites/flags.png 8bpp 562 8 11 8 0 0 normal
|
||||
-1 sprites/flags.png 8bpp 578 8 11 8 0 0 normal
|
||||
-1 sprites/flags.png 8bpp 594 8 11 8 0 0 normal
|
Binary file not shown.
Before Width: | Height: | Size: 1.7 KiB |
@@ -92,7 +92,6 @@
|
||||
#include "roadstops.nfo"
|
||||
#include "aqueduct.nfo"
|
||||
#include "autorail.nfo"
|
||||
#include "flags.nfo"
|
||||
#include "openttdgui.nfo"
|
||||
#include "airport_preview.nfo"
|
||||
#include "chars.nfo"
|
||||
|
BIN
media/openttd.1024.png
Normal file
BIN
media/openttd.1024.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 66 KiB |
BIN
media/openttd.2048.png
Normal file
BIN
media/openttd.2048.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 148 KiB |
BIN
media/openttd.512.png
Normal file
BIN
media/openttd.512.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
@@ -6,6 +6,6 @@ Name=OpenTTD
|
||||
Icon=${BINARY_NAME}
|
||||
Exec=${BINARY_NAME}
|
||||
Terminal=false
|
||||
Categories=Game;
|
||||
Categories=Game;Simulation;
|
||||
Keywords=game;simulation;transport;tycoon;deluxe;economics;multiplayer;money;train;ship;bus;truck;aircraft;cargo;
|
||||
@Comment_STR_DESKTOP_SHORTCUT_COMMENT@
|
||||
|
@@ -1,4 +1,4 @@
|
||||
FROM emscripten/emsdk:2.0.10
|
||||
FROM emscripten/emsdk:2.0.34
|
||||
|
||||
COPY emsdk-liblzma.patch /
|
||||
RUN cd /emsdk/upstream/emscripten && patch -p1 < /emsdk-liblzma.patch
|
||||
|
@@ -1,6 +1,6 @@
|
||||
## How to build with Emscripten
|
||||
|
||||
Building with Emscripten works with emsdk 2.0.10 and above.
|
||||
Building with Emscripten works with emsdk 2.0.31 and above.
|
||||
|
||||
Currently there is no LibLZMA support upstream; for this we suggest to apply
|
||||
the provided patch in this folder to your emsdk installation.
|
||||
@@ -24,7 +24,7 @@ Next, build the game with emscripten:
|
||||
|
||||
```
|
||||
mkdir build
|
||||
docker run -it --rm -v $(pwd):$(pwd) -u $(id -u):$(id -g) --workdir $(pwd)/build emsdk-lzma emcmake cmake .. -DHOST_BINARY_DIR=$(pwd)/build-host -DCMAKE_BUILD_TYPE=RelWithDebInfo -DOPTION_USE_ASSERTS=OFF
|
||||
docker run -it --rm -v $(pwd):$(pwd) -u $(id -u):$(id -g) --workdir $(pwd)/build emsdk-lzma emcmake cmake .. -DHOST_BINARY_DIR=../build-host -DCMAKE_BUILD_TYPE=Release -DOPTION_USE_ASSERTS=OFF
|
||||
docker run -it --rm -v $(pwd):$(pwd) -u $(id -u):$(id -g) --workdir $(pwd)/build emsdk-lzma emmake make -j5
|
||||
```
|
||||
|
||||
|
@@ -10,44 +10,35 @@ Modifed by OpenTTD to have the bare minimum needed to work. Otherwise there
|
||||
are constantly conflicts when trying to apply this patch to different versions
|
||||
of emsdk.
|
||||
|
||||
diff --git a/embuilder.py b/embuilder.py
|
||||
index 818262190ed..ab7d5adb7b2 100755
|
||||
--- a/embuilder.py
|
||||
+++ b/embuilder.py
|
||||
@@ -60,6 +60,7 @@
|
||||
'harfbuzz',
|
||||
'icu',
|
||||
'libjpeg',
|
||||
+ 'liblzma',
|
||||
'libpng',
|
||||
'ogg',
|
||||
'regal',
|
||||
@@ -197,6 +198,8 @@ def main():
|
||||
build_port('ogg', libname('libogg'))
|
||||
elif what == 'libjpeg':
|
||||
build_port('libjpeg', libname('libjpeg'))
|
||||
+ elif what == 'liblzma':
|
||||
+ build_port('liblzma', libname('liblzma'))
|
||||
elif what == 'libpng':
|
||||
build_port('libpng', libname('libpng'))
|
||||
elif what == 'sdl2':
|
||||
diff --git a/tools/settings.py b/tools/settings.py
|
||||
--- a/tools/settings.py
|
||||
+++ b/tools/settings.py
|
||||
@@ -38,6 +38,7 @@
|
||||
'USE_SDL_NET',
|
||||
'USE_SDL_GFX',
|
||||
'USE_LIBJPEG',
|
||||
+ 'USE_LIBLZMA',
|
||||
'USE_OGG',
|
||||
'USE_REGAL',
|
||||
'USE_BOOST_HEADERS',
|
||||
diff --git a/src/settings.js b/src/settings.js
|
||||
index 61cd98939ba..be6fcb678c6 100644
|
||||
--- a/src/settings.js
|
||||
+++ b/src/settings.js
|
||||
@@ -1197,6 +1197,9 @@ var USE_BZIP2 = 0;
|
||||
@@ -1382,8 +1382,12 @@ var USE_BZIP2 = 0;
|
||||
// 1 = use libjpeg from emscripten-ports
|
||||
// [link]
|
||||
var USE_LIBJPEG = 0;
|
||||
|
||||
+// 1 = use liblzma from emscripten-ports
|
||||
+// [link]
|
||||
+var USE_LIBLZMA = 0;
|
||||
+
|
||||
// 1 = use libpng from emscripten-ports
|
||||
// [link]
|
||||
var USE_LIBPNG = 0;
|
||||
|
||||
diff --git a/tools/ports/liblzma.py b/tools/ports/liblzma.py
|
||||
new file mode 100644
|
||||
index 00000000000..e9567ef36ff
|
||||
--- /dev/null
|
||||
+++ b/tools/ports/liblzma.py
|
||||
@@ -0,0 +1,160 @@
|
||||
@@ -58,6 +49,8 @@ index 00000000000..e9567ef36ff
|
||||
+
|
||||
+import os
|
||||
+import shutil
|
||||
+import logging
|
||||
+from pathlib import Path
|
||||
+
|
||||
+VERSION = '5.2.5'
|
||||
+HASH = '7443674247deda2935220fbc4dfc7665e5bb5a260be8ad858c8bd7d7b9f0f868f04ea45e62eb17c0a5e6a2de7c7500ad2d201e2d668c48ca29bd9eea5a73a3ce'
|
||||
@@ -68,10 +61,11 @@ index 00000000000..e9567ef36ff
|
||||
+
|
||||
+
|
||||
+def get(ports, settings, shared):
|
||||
+ libname = ports.get_lib_name('liblzma')
|
||||
+ ports.fetch_project('liblzma', 'https://tukaani.org/xz/xz-' + VERSION + '.tar.gz', 'xz-' + VERSION, sha512hash=HASH)
|
||||
+
|
||||
+ def create():
|
||||
+ def create(final):
|
||||
+ logging.info('building port: liblzma')
|
||||
+
|
||||
+ ports.clear_project_build('liblzma')
|
||||
+
|
||||
+ source_path = os.path.join(ports.get_dir(), 'liblzma', 'xz-' + VERSION)
|
||||
@@ -88,22 +82,19 @@ index 00000000000..e9567ef36ff
|
||||
+ 'tuklib_exit.c', 'tuklib_mbstr_fw.c', 'tuklib_mbstr_width.c', 'tuklib_open_stdxxx.c', 'tuklib_progname.c']
|
||||
+ include_dirs_rel = ['../common', 'api', 'common', 'check', 'lz', 'rangecoder', 'lzma', 'delta', 'simple']
|
||||
+
|
||||
+ open(os.path.join(dest_path, 'src', 'config.h'), 'w').write(config_h)
|
||||
+ Path(dest_path, os.path.join('src', 'config.h')).write_text(config_h)
|
||||
+
|
||||
+ final = os.path.join(dest_path, libname)
|
||||
+ include_dirs = [os.path.join(dest_path, 'src', 'liblzma', p) for p in include_dirs_rel]
|
||||
+ ports.build_port(os.path.join(dest_path, 'src'), final, flags=build_flags, exclude_dirs=exclude_dirs, exclude_files=exclude_files, includes=include_dirs)
|
||||
+
|
||||
+ ports.install_headers(os.path.join(dest_path, 'src', 'liblzma', 'api'), 'lzma.h')
|
||||
+ ports.install_headers(os.path.join(dest_path, 'src', 'liblzma', 'api', 'lzma'), '*.h', 'lzma')
|
||||
+
|
||||
+ return final
|
||||
+
|
||||
+ return [shared.Cache.get(libname, create, what='port')]
|
||||
+ return [shared.Cache.get_lib('liblzma.a', create, what='port')]
|
||||
+
|
||||
+
|
||||
+def clear(ports, settings, shared):
|
||||
+ shared.Cache.erase_file(ports.get_lib_name('liblzma'))
|
||||
+ shared.Cache.erase_lib('liblzma.a')
|
||||
+
|
||||
+
|
||||
+def process_args(ports):
|
||||
|
@@ -31,5 +31,7 @@
|
||||
<string>NSApplication</string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<string>True</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.14.0</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@@ -10,6 +10,7 @@
|
||||
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<windowsSettings>
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True/PM</dpiAware>
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2,PerMonitor</dpiAwareness>
|
||||
</windowsSettings>
|
||||
</application>
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||
|
@@ -12,7 +12,7 @@ REM URL of the timestamp server
|
||||
IF NOT DEFINED SIGNTOOL_TIMESTAMP_URL (SET SIGNTOOL_TIMESTAMP_URL=http://timestamp.digicert.com)
|
||||
|
||||
REM Sign with SHA-1 for Windows 7 and below
|
||||
"%SIGNTOOL_PATH%" sign -v -n %2 -t %SIGNTOOL_TIMESTAMP_URL% %1
|
||||
"%SIGNTOOL_PATH%" sign -v -n %2 -t %SIGNTOOL_TIMESTAMP_URL% -fd sha1 %1
|
||||
|
||||
REM Sign with SHA-256 for Windows 8 and above
|
||||
"%SIGNTOOL_PATH%" sign -v -n %2 -tr %SIGNTOOL_TIMESTAMP_URL% -fd sha256 -td sha256 -as %1
|
||||
|
2
os/windows/winstore/generate-assets.bat
Normal file
2
os/windows/winstore/generate-assets.bat
Normal file
@@ -0,0 +1,2 @@
|
||||
@echo off
|
||||
powershell -File "%~dp0generate-assets.ps1"
|
48
os/windows/winstore/generate-assets.ps1
Normal file
48
os/windows/winstore/generate-assets.ps1
Normal file
@@ -0,0 +1,48 @@
|
||||
function ResizeImage() {
|
||||
param([String]$sourcePath, [Int]$targetWidth, [Int]$targetHeight, [String]$targetPath)
|
||||
|
||||
Add-Type -AssemblyName "System.Drawing"
|
||||
|
||||
$img = [System.Drawing.Image]::FromFile($sourcePath)
|
||||
|
||||
$ratioX = $targetWidth / $img.Width;
|
||||
$ratioY = $targetHeight / $img.Height;
|
||||
|
||||
$ratio = $ratioY
|
||||
|
||||
if ($ratioX -le $ratioY) {
|
||||
$ratio = $ratioX
|
||||
}
|
||||
|
||||
$newWidth = [int] ($img.Width * $ratio)
|
||||
$newHeight = [int] ($img.Height * $ratio)
|
||||
|
||||
$resizedImage = New-Object System.Drawing.Bitmap($targetWidth, $targetHeight)
|
||||
$graph = [System.Drawing.Graphics]::FromImage($resizedImage)
|
||||
$graph.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic
|
||||
|
||||
$graph.Clear([System.Drawing.Color]::Transparent)
|
||||
$graph.DrawImage($img, $targetWidth / 2 - $newWidth / 2, $targetHeight / 2 - $newHeight / 2, $newWidth, $newHeight)
|
||||
|
||||
$resizedImage.Save($targetPath)
|
||||
$resizedImage.Dispose()
|
||||
$img.Dispose()
|
||||
}
|
||||
|
||||
$logoPath = "..\..\..\media\openttd.2048.png"
|
||||
|
||||
# Create the main image assets required for the Windows Store
|
||||
New-Item -Path "." -Name "assets" -ItemType "directory" -Force
|
||||
ResizeImage $logoPath 1240 1240 "assets\LargeTile.png"
|
||||
ResizeImage $logoPath 284 284 "assets\SmallTile.png"
|
||||
ResizeImage $logoPath 2480 1200 "assets\SplashScreen.png"
|
||||
ResizeImage $logoPath 176 176 "assets\Square44x44Logo.png"
|
||||
Copy-Item "assets\Square44x44Logo.png" -Destination "assets\Square44x44Logo.targetsize-44_altform-unplated.png"
|
||||
ResizeImage $logoPath 600 600 "assets\Square150x150Logo.png"
|
||||
Copy-Item "assets\Square150x150Logo.png" -Destination "assets\Square150x150Logo.targetsize-150_altform-unplated.png"
|
||||
ResizeImage $logoPath 200 200 "assets\StoreLogo.png"
|
||||
ResizeImage $logoPath 1240 600 "assets\Wide310x150Logo.png"
|
||||
|
||||
# Copy the logo for the store for the common package
|
||||
New-Item -Path "." -Name "assets-common" -ItemType "directory" -Force
|
||||
Copy-Item "assets\StoreLogo.png" -Destination "assets-common\StoreLogo.png"
|
2
os/windows/winstore/generate-key.bat
Normal file
2
os/windows/winstore/generate-key.bat
Normal file
@@ -0,0 +1,2 @@
|
||||
@echo off
|
||||
powershell -File "%~dp0generate-key.ps1" %1 %2 %3
|
21
os/windows/winstore/generate-key.ps1
Normal file
21
os/windows/winstore/generate-key.ps1
Normal file
@@ -0,0 +1,21 @@
|
||||
[CmdletBinding()]
|
||||
[Alias()]
|
||||
Param
|
||||
(
|
||||
# Publisher ("CN=xyz")
|
||||
[Parameter(Mandatory=$true, Position=0)]
|
||||
$Publisher,
|
||||
|
||||
# Password
|
||||
[Parameter(Mandatory=$true, Position=1)]
|
||||
$PasswordParam,
|
||||
|
||||
# Filename
|
||||
[Parameter(Mandatory=$true, Position=2)]
|
||||
$OutputFilename
|
||||
)
|
||||
|
||||
$cert = New-SelfSignedCertificate -Type Custom -Subject $Publisher -KeyUsage DigitalSignature -FriendlyName "OpenTTD signing certificate" -CertStoreLocation "Cert:\CurrentUser\My" -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.3", "2.5.29.19={text}")
|
||||
|
||||
$password = ConvertTo-SecureString -String $PasswordParam -Force -AsPlainText
|
||||
Export-PfxCertificate -cert "Cert:\CurrentUser\My\$($cert.Thumbprint)" -FilePath $OutputFilename -Password $password
|
68
os/windows/winstore/manifests/AssetsPackage.appxmanifest
Normal file
68
os/windows/winstore/manifests/AssetsPackage.appxmanifest
Normal file
@@ -0,0 +1,68 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:uap6="http://schemas.microsoft.com/appx/manifest/uap/windows10/6" IgnorableNamespaces="uap uap6">
|
||||
<Identity Name="$IDENTITY_NAME$" Publisher="$PUBLISHER$" Version="$VERSION$" ResourceId="OpenTTD-common" />
|
||||
<Properties>
|
||||
<uap6:AllowExecution>false</uap6:AllowExecution>
|
||||
<DisplayName>OpenTTD (official)</DisplayName>
|
||||
<PublisherDisplayName>OpenTTD Developers</PublisherDisplayName>
|
||||
<Logo>Assets\StoreLogoCommon.png</Logo>
|
||||
</Properties>
|
||||
<Resources>
|
||||
<Resource Language="en-gb" />
|
||||
<Resource Language="en-us" />
|
||||
<Resource Language="en-au" />
|
||||
<Resource Language="af-za" />
|
||||
<Resource Language="ar-eg" />
|
||||
<Resource Language="eu-es" />
|
||||
<Resource Language="be-by" />
|
||||
<Resource Language="pt-br" />
|
||||
<Resource Language="bg-bg" />
|
||||
<Resource Language="ca-es" />
|
||||
<Resource Language="hr-hr" />
|
||||
<Resource Language="cs-cz" />
|
||||
<Resource Language="da-dk" />
|
||||
<Resource Language="nl-nl" />
|
||||
<Resource Language="et-ee" />
|
||||
<Resource Language="fo-fo" />
|
||||
<Resource Language="fr-fr" />
|
||||
<Resource Language="gd-gb" />
|
||||
<Resource Language="gl-es" />
|
||||
<Resource Language="de-de" />
|
||||
<Resource Language="el-gr" />
|
||||
<Resource Language="he-il" />
|
||||
<Resource Language="hu-hu" />
|
||||
<Resource Language="is-is" />
|
||||
<Resource Language="id-id" />
|
||||
<Resource Language="ga-ie" />
|
||||
<Resource Language="it-it" />
|
||||
<Resource Language="ja-jp" />
|
||||
<Resource Language="ko-kr" />
|
||||
<Resource Language="lv-lv" />
|
||||
<Resource Language="lt-lt" />
|
||||
<Resource Language="lb-lu" />
|
||||
<Resource Language="ms-my" />
|
||||
<Resource Language="nb-no" />
|
||||
<Resource Language="no-no" />
|
||||
<Resource Language="pl-pl" />
|
||||
<Resource Language="pt-pt" />
|
||||
<Resource Language="ro-ro" />
|
||||
<Resource Language="ru-ru" />
|
||||
<Resource Language="sr-latn-rs" />
|
||||
<Resource Language="zh-cn" />
|
||||
<Resource Language="sk-sk" />
|
||||
<Resource Language="sl-si" />
|
||||
<Resource Language="es-es" />
|
||||
<Resource Language="es-mx" />
|
||||
<Resource Language="sv-se" />
|
||||
<Resource Language="ta-in" />
|
||||
<Resource Language="th-th" />
|
||||
<Resource Language="zh-tw" />
|
||||
<Resource Language="tr-tr" />
|
||||
<Resource Language="uk-ua" />
|
||||
<Resource Language="vi-vn" />
|
||||
<Resource Language="cy-gb" />
|
||||
</Resources>
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17134.0" MaxVersionTested="10.0.18363.0" />
|
||||
</Dependencies>
|
||||
</Package>
|
83
os/windows/winstore/manifests/Package.appxmanifest
Normal file
83
os/windows/winstore/manifests/Package.appxmanifest
Normal file
@@ -0,0 +1,83 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities" IgnorableNamespaces="uap mp rescap">
|
||||
<Identity Name="$IDENTITY_NAME$" Publisher="$PUBLISHER$" Version="$VERSION$" ProcessorArchitecture="$ARCHITECTURE$" />
|
||||
<Properties>
|
||||
<DisplayName>OpenTTD (official)</DisplayName>
|
||||
<PublisherDisplayName>OpenTTD Developers</PublisherDisplayName>
|
||||
<Logo>Assets\StoreLogo.png</Logo>
|
||||
</Properties>
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17134.0" MaxVersionTested="10.0.18363.0" />
|
||||
</Dependencies>
|
||||
<Resources>
|
||||
<Resource Language="en-gb" />
|
||||
<Resource Language="en-us" />
|
||||
<Resource Language="en-au" />
|
||||
<Resource Language="af-za" />
|
||||
<Resource Language="ar-eg" />
|
||||
<Resource Language="eu-es" />
|
||||
<Resource Language="be-by" />
|
||||
<Resource Language="pt-br" />
|
||||
<Resource Language="bg-bg" />
|
||||
<Resource Language="ca-es" />
|
||||
<Resource Language="hr-hr" />
|
||||
<Resource Language="cs-cz" />
|
||||
<Resource Language="da-dk" />
|
||||
<Resource Language="nl-nl" />
|
||||
<!-- <Resource Language="eo-eo" />-->
|
||||
<Resource Language="et-ee" />
|
||||
<Resource Language="fo-fo" />
|
||||
<!-- <Resource Language="fi-fi" />-->
|
||||
<Resource Language="fr-fr" />
|
||||
<Resource Language="gd-gb" />
|
||||
<Resource Language="gl-es" />
|
||||
<Resource Language="de-de" />
|
||||
<Resource Language="el-gr" />
|
||||
<Resource Language="he-il" />
|
||||
<Resource Language="hu-hu" />
|
||||
<Resource Language="is-is" />
|
||||
<Resource Language="id-id" />
|
||||
<Resource Language="ga-ie" />
|
||||
<Resource Language="it-it" />
|
||||
<Resource Language="ja-jp" />
|
||||
<Resource Language="ko-kr" />
|
||||
<!-- <Resource Language="la-va" />-->
|
||||
<Resource Language="lv-lv" />
|
||||
<Resource Language="lt-lt" />
|
||||
<Resource Language="lb-lu" />
|
||||
<Resource Language="ms-my" />
|
||||
<Resource Language="nb-no" />
|
||||
<Resource Language="no-no" />
|
||||
<Resource Language="pl-pl" />
|
||||
<Resource Language="pt-pt" />
|
||||
<Resource Language="ro-ro" />
|
||||
<Resource Language="ru-ru" />
|
||||
<Resource Language="sr-latn-rs" />
|
||||
<Resource Language="zh-cn" />
|
||||
<Resource Language="sk-sk" />
|
||||
<Resource Language="sl-si" />
|
||||
<Resource Language="es-es" />
|
||||
<Resource Language="es-mx" />
|
||||
<Resource Language="sv-se" />
|
||||
<Resource Language="ta-in" />
|
||||
<Resource Language="th-th" />
|
||||
<Resource Language="zh-tw" />
|
||||
<Resource Language="tr-tr" />
|
||||
<Resource Language="uk-ua" />
|
||||
<Resource Language="vi-vn" />
|
||||
<Resource Language="cy-gb" />
|
||||
</Resources>
|
||||
<Applications>
|
||||
<Application Id="OpenTTD" Executable="openttd.exe" EntryPoint="Windows.FullTrustApplication">
|
||||
<uap:VisualElements DisplayName="OpenTTD (official)" Description="OpenTTD is an open source simulation game based upon Transport Tycoon Deluxe." BackgroundColor="transparent" Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png">
|
||||
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png" Square310x310Logo="Assets\LargeTile.png" Square71x71Logo="Assets\SmallTile.png">
|
||||
</uap:DefaultTile>
|
||||
<uap:SplashScreen Image="Assets\SplashScreen.png" />
|
||||
</uap:VisualElements>
|
||||
</Application>
|
||||
</Applications>
|
||||
<Capabilities>
|
||||
<Capability Name="internetClientServer" />
|
||||
<rescap:Capability Name="runFullTrust" />
|
||||
</Capabilities>
|
||||
</Package>
|
35
os/windows/winstore/manifests/PackagingLayout.xml
Normal file
35
os/windows/winstore/manifests/PackagingLayout.xml
Normal file
@@ -0,0 +1,35 @@
|
||||
<PackagingLayout xmlns="http://schemas.microsoft.com/appx/makeappx/2017">
|
||||
<!-- Main game -->
|
||||
<PackageFamily ID="OpenTTD" FlatBundle="false" ManifestPath="manifests\Package.appxmanifest" ResourceManager="false">
|
||||
<!-- x86 code package-->
|
||||
<Package ID="OpenTTD-x86" ProcessorArchitecture="x86" ManifestPath="manifests\Package-x86.appxmanifest">
|
||||
<Files>
|
||||
<File DestinationPath="**" SourcePath="x86-binaries\**"/>
|
||||
<File DestinationPath="Assets\**" SourcePath="Assets\**"/>
|
||||
</Files>
|
||||
</Package>
|
||||
|
||||
<!-- x64 code package-->
|
||||
<Package ID="OpenTTD-x64" ProcessorArchitecture="x64" ManifestPath="manifests\Package-x64.appxmanifest">
|
||||
<Files>
|
||||
<File DestinationPath="**" SourcePath="x64-binaries\**"/>
|
||||
<File DestinationPath="Assets\**" SourcePath="Assets\**"/>
|
||||
</Files>
|
||||
</Package>
|
||||
|
||||
<!-- ARM64 code package-->
|
||||
<Package ID="OpenTTD-ARM64" ProcessorArchitecture="arm64" ManifestPath="manifests\Package-ARM64.appxmanifest">
|
||||
<Files>
|
||||
<File DestinationPath="**" SourcePath="ARM64-binaries\**"/>
|
||||
<File DestinationPath="Assets\**" SourcePath="Assets\**"/>
|
||||
</Files>
|
||||
</Package>
|
||||
|
||||
<!-- Common asset package-->
|
||||
<AssetPackage ID="OpenTTD-common" AllowExecution="false" ManifestPath="manifests\AssetsPackage.appxmanifest">
|
||||
<Files>
|
||||
<File DestinationPath="**" SourcePath="common-binaries\**"/>
|
||||
</Files>
|
||||
</AssetPackage>
|
||||
</PackageFamily>
|
||||
</PackagingLayout>
|
2
os/windows/winstore/prepare-manifests.bat
Normal file
2
os/windows/winstore/prepare-manifests.bat
Normal file
@@ -0,0 +1,2 @@
|
||||
@echo off
|
||||
powershell -File "%~dp0prepare-manifests.ps1" %1 %2 %3 %OTTD_VERSION%
|
42
os/windows/winstore/prepare-manifests.ps1
Normal file
42
os/windows/winstore/prepare-manifests.ps1
Normal file
@@ -0,0 +1,42 @@
|
||||
[CmdletBinding()]
|
||||
[Alias()]
|
||||
Param
|
||||
(
|
||||
# Output folder
|
||||
[Parameter(Mandatory=$true, Position=0)]
|
||||
$OutputFolder,
|
||||
|
||||
# Publisher ("CN=xyz")
|
||||
[Parameter(Mandatory=$true, Position=1)]
|
||||
$Publisher,
|
||||
|
||||
# IdentityName
|
||||
[Parameter(Mandatory=$true, Position=2)]
|
||||
$IdentityName,
|
||||
|
||||
# Version
|
||||
[Parameter(Mandatory=$true, Position=3)]
|
||||
$AppVersion
|
||||
)
|
||||
|
||||
function Prepare-Manifest {
|
||||
param (
|
||||
$Architecture
|
||||
)
|
||||
|
||||
(Get-Content "$($PSScriptRoot)\manifests\Package.appxmanifest").replace('$PUBLISHER$', $Publisher).replace('$IDENTITY_NAME$', $IdentityName).replace('$VERSION$', $AppVersion).replace('$ARCHITECTURE$', $Architecture) | Set-Content "$($OutputFolder)\Package-$($Architecture).appxmanifest"
|
||||
}
|
||||
|
||||
# Prepare the application binary manifests
|
||||
Prepare-Manifest x86
|
||||
Prepare-Manifest x64
|
||||
Prepare-Manifest arm64
|
||||
|
||||
# Prepare the assets package manifest
|
||||
(Get-Content "$($PSScriptRoot)\manifests\AssetsPackage.appxmanifest").replace('$PUBLISHER$', $Publisher).replace('$IDENTITY_NAME$', $IdentityName).replace('$VERSION$', $AppVersion) | Set-Content "$($OutputFolder)\AssetsPackage.appxmanifest"
|
||||
|
||||
# Prepare the overall package manifest
|
||||
(Get-Content "$($PSScriptRoot)\manifests\Package.appxmanifest").replace('$PUBLISHER$', $Publisher).replace('$IDENTITY_NAME$', $IdentityName).replace('$VERSION$', $AppVersion).replace(' ProcessorArchitecture="$ARCHITECTURE$"', '') | Set-Content "$($OutputFolder)\Package.appxmanifest"
|
||||
|
||||
# Copy the PackagingLayout XML file
|
||||
(Get-Content "$($PSScriptRoot)\manifests\PackagingLayout.xml") | Set-Content "$($OutputFolder)\PackagingLayout.xml"
|
14
os/windows/winstore/set-version.bat
Normal file
14
os/windows/winstore/set-version.bat
Normal file
@@ -0,0 +1,14 @@
|
||||
@echo off
|
||||
if [%1]==[] goto err
|
||||
|
||||
powershell -File "%~dp0set-version.ps1" %1 > "%temp%\ottd-set-version.bat"
|
||||
if not errorlevel 0 goto err
|
||||
call "%temp%\ottd-set-version.bat"
|
||||
del /q "%temp%\ottd-set-version.bat"
|
||||
|
||||
@rem Version number will now be in %OTTD_VERSION%
|
||||
|
||||
goto :eof
|
||||
|
||||
:err
|
||||
echo Please supply the path of openttd.exe as the argument to this batch file.
|
23
os/windows/winstore/set-version.ps1
Normal file
23
os/windows/winstore/set-version.ps1
Normal file
@@ -0,0 +1,23 @@
|
||||
[CmdletBinding()]
|
||||
[Alias()]
|
||||
Param
|
||||
(
|
||||
# EXE path
|
||||
[Parameter(Mandatory=$true, Position=0)]
|
||||
$ExePath
|
||||
)
|
||||
|
||||
try
|
||||
{
|
||||
$versionInfo = (Get-Item "$ExePath").VersionInfo
|
||||
|
||||
# Generate the app version - the build number (MS calls it revision) is always 0 because the Windows Store requires that
|
||||
$AppVersion = "$($versionInfo.FileMajorPart).$($versionInfo.FileMinorPart).$($versionInfo.FileBuildPart).0"
|
||||
|
||||
Write-Output "SET OTTD_VERSION=$($AppVersion)"
|
||||
}
|
||||
catch
|
||||
{
|
||||
Write-Output "@ECHO Error retrieving EXE version - did you provide a path?"
|
||||
exit 1
|
||||
}
|
@@ -4,7 +4,7 @@ class Regression extends AIInfo {
|
||||
function GetShortName() { return "REGR"; }
|
||||
function GetDescription() { return "This runs regression-tests on some commands. On the same map the result should always be the same."; }
|
||||
function GetVersion() { return 1; }
|
||||
function GetAPIVersion() { return "12"; }
|
||||
function GetAPIVersion() { return "13"; }
|
||||
function GetDate() { return "2007-03-18"; }
|
||||
function CreateInstance() { return "Regression"; }
|
||||
function UseAsRandomAI() { return false; }
|
||||
|
@@ -341,6 +341,7 @@ function Regression::Cargo()
|
||||
print(" GetCargoIncome(10, 10): " + AICargo.GetCargoIncome(i, 10, 10));
|
||||
print(" GetCargoIncome(100, 10): " + AICargo.GetCargoIncome(i, 100, 10));
|
||||
print(" GetCargoIncome(10, 100): " + AICargo.GetCargoIncome(i, 10, 100));
|
||||
print(" GetWeight(100): " + AICargo.GetWeight(i, 100));
|
||||
print(" GetRoadVehicleTypeForCargo(): " + AIRoad.GetRoadVehicleTypeForCargo(i));
|
||||
}
|
||||
}
|
||||
@@ -547,6 +548,8 @@ function Regression::Prices()
|
||||
print(" BT_DOCK: " + AIMarine.GetBuildCost(AIMarine.BT_DOCK));
|
||||
print(" BT_DEPOT: " + AIMarine.GetBuildCost(AIMarine.BT_DEPOT));
|
||||
print(" BT_BUOY: " + AIMarine.GetBuildCost(AIMarine.BT_BUOY));
|
||||
print(" BT_LOCK: " + AIMarine.GetBuildCost(AIMarine.BT_LOCK));
|
||||
print(" BT_CANAL: " + AIMarine.GetBuildCost(AIMarine.BT_CANAL));
|
||||
print(" -Tile-");
|
||||
print(" BT_FOUNDATION: " + AITile.GetBuildCost(AITile.BT_FOUNDATION));
|
||||
print(" BT_TERRAFORM: " + AITile.GetBuildCost(AITile.BT_TERRAFORM));
|
||||
@@ -556,6 +559,7 @@ function Regression::Prices()
|
||||
print(" BT_CLEAR_ROCKY: " + AITile.GetBuildCost(AITile.BT_CLEAR_ROCKY));
|
||||
print(" BT_CLEAR_FIELDS: " + AITile.GetBuildCost(AITile.BT_CLEAR_FIELDS));
|
||||
print(" BT_CLEAR_HOUSE: " + AITile.GetBuildCost(AITile.BT_CLEAR_HOUSE));
|
||||
print(" BT_CLEAR_WATER: " + AITile.GetBuildCost(AITile.BT_CLEAR_WATER));
|
||||
}
|
||||
|
||||
function cost_callback(old_path, new_tile, new_direction, self) { if (old_path == null) return 0; return old_path.GetCost() + 1; }
|
||||
@@ -919,6 +923,9 @@ function Regression::Marine()
|
||||
|
||||
print(" BuildWaterDepot(): " + AIMarine.BuildWaterDepot(28479, 28480));
|
||||
print(" BuildDock(): " + AIMarine.BuildDock(29253, AIStation.STATION_JOIN_ADJACENT));
|
||||
print(" BuildBuoy(): " + AIMarine.BuildBuoy(28481));
|
||||
print(" BuildLock(): " + AIMarine.BuildLock(28487));
|
||||
print(" BuildCanal(): " + AIMarine.BuildCanal(28744));
|
||||
}
|
||||
|
||||
function Regression::Order()
|
||||
@@ -1017,6 +1024,30 @@ function Regression::Rail()
|
||||
print(" IsRailTile(): " + AIRail.IsRailTile(10002));
|
||||
print(" BuildRailTrack(): " + AIRail.BuildRailTrack(10002, AIRail.RAILTRACK_NW_SE));
|
||||
print(" BuildSignal(): " + AIRail.BuildSignal(10002, 10258, AIRail.SIGNALTYPE_PBS));
|
||||
print(" GetSignalType(): " + AIRail.GetSignalType(10002, 10258));
|
||||
print(" GetSignalType(): " + AIRail.GetSignalType(10002, 9746));
|
||||
print(" RemoveSignal(): " + AIRail.RemoveSignal(10002, 10258));
|
||||
print(" BuildSignal(): " + AIRail.BuildSignal(10002, 9746, AIRail.SIGNALTYPE_ENTRY));
|
||||
print(" GetSignalType(): " + AIRail.GetSignalType(10002, 10258));
|
||||
print(" GetSignalType(): " + AIRail.GetSignalType(10002, 9746));
|
||||
print(" RemoveSignal(): " + AIRail.RemoveSignal(10002, 9746));
|
||||
print(" BuildSignal(): " + AIRail.BuildSignal(10002, 9746, AIRail.SIGNALTYPE_EXIT_TWOWAY));
|
||||
print(" GetSignalType(): " + AIRail.GetSignalType(10002, 10258));
|
||||
print(" GetSignalType(): " + AIRail.GetSignalType(10002, 9746));
|
||||
print(" RemoveRailTrack(): " + AIRail.RemoveRailTrack(10002, AIRail.RAILTRACK_NW_NE));
|
||||
print(" RemoveRailTrack(): " + AIRail.RemoveRailTrack(10002, AIRail.RAILTRACK_NW_SE));
|
||||
print(" BuildRailTrack(): " + AIRail.BuildRailTrack(10002, AIRail.RAILTRACK_NW_NE));
|
||||
print(" BuildSignal(): " + AIRail.BuildSignal(10002, 10003, AIRail.SIGNALTYPE_PBS));
|
||||
print(" GetSignalType(): " + AIRail.GetSignalType(10002, 10003));
|
||||
print(" GetSignalType(): " + AIRail.GetSignalType(10002, 10001));
|
||||
print(" RemoveSignal(): " + AIRail.RemoveSignal(10002, 10003));
|
||||
print(" BuildSignal(): " + AIRail.BuildSignal(10002, 10001, AIRail.SIGNALTYPE_ENTRY));
|
||||
print(" GetSignalType(): " + AIRail.GetSignalType(10002, 10003));
|
||||
print(" GetSignalType(): " + AIRail.GetSignalType(10002, 10001));
|
||||
print(" RemoveSignal(): " + AIRail.RemoveSignal(10002, 10001));
|
||||
print(" BuildSignal(): " + AIRail.BuildSignal(10002, 10001, AIRail.SIGNALTYPE_EXIT_TWOWAY));
|
||||
print(" GetSignalType(): " + AIRail.GetSignalType(10002, 10003));
|
||||
print(" GetSignalType(): " + AIRail.GetSignalType(10002, 10001));
|
||||
print(" RemoveRailTrack(): " + AIRail.RemoveRailTrack(10002, AIRail.RAILTRACK_NW_NE));
|
||||
print(" RemoveRailTrack(): " + AIRail.RemoveRailTrack(10002, AIRail.RAILTRACK_NW_SE));
|
||||
print(" BuildRail(): " + AIRail.BuildRail(10002, 10003, 10006));
|
||||
@@ -1470,9 +1501,41 @@ function Regression::TileList()
|
||||
print(" " + i + " => " + list.GetValue(i));
|
||||
}
|
||||
|
||||
list.AddRectangle(54421 - 256 * 2, 256 * 2 + 54421 + 8);
|
||||
list.AddRectangle(0x6F3F, 0x7248);
|
||||
list.Valuate(AITile.IsWaterTile);
|
||||
print(" Water(): done");
|
||||
print(" IsWaterTile(): done");
|
||||
print(" Count(): " + list.Count());
|
||||
print(" ListDump:");
|
||||
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||
print(" " + i + " => " + list.GetValue(i));
|
||||
}
|
||||
|
||||
list.Valuate(AITile.IsSeaTile);
|
||||
print(" IsSeaTile(): done");
|
||||
print(" Count(): " + list.Count());
|
||||
print(" ListDump:");
|
||||
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||
print(" " + i + " => " + list.GetValue(i));
|
||||
}
|
||||
|
||||
list.Valuate(AITile.IsRiverTile);
|
||||
print(" IsRiverTile() done");
|
||||
print(" Count(): " + list.Count());
|
||||
print(" ListDump:");
|
||||
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||
print(" " + i + " => " + list.GetValue(i));
|
||||
}
|
||||
|
||||
list.Valuate(AIMarine.IsCanalTile);
|
||||
print(" IsCanalTile() done");
|
||||
print(" Count(): " + list.Count());
|
||||
print(" ListDump:");
|
||||
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||
print(" " + i + " => " + list.GetValue(i));
|
||||
}
|
||||
|
||||
list.Valuate(AITile.IsCoastTile);
|
||||
print(" IsCoastTile() done");
|
||||
print(" Count(): " + list.Count());
|
||||
print(" ListDump:");
|
||||
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||
|
@@ -639,7 +639,7 @@ ERROR: IsEnd() is invalid as Begin() is never called
|
||||
GetQuarterlyCompanyValue(): -1
|
||||
Quarter: 0
|
||||
GetQuarterlyIncome(): 0
|
||||
GetQuarterlyExpenses(): -210
|
||||
GetQuarterlyExpenses(): 0
|
||||
GetQuarterlyCargoDelivered(): 0
|
||||
GetQuarterlyPerformanceRating(): -1
|
||||
GetQuarterlyCompanyValue(): 1
|
||||
@@ -1118,6 +1118,7 @@ ERROR: IsEnd() is invalid as Begin() is never called
|
||||
GetCargoIncome(10, 10): -1
|
||||
GetCargoIncome(100, 10): -1
|
||||
GetCargoIncome(10, 100): -1
|
||||
GetWeight(100): -1
|
||||
GetRoadVehicleTypeForCargo(): 1
|
||||
Cargo 0
|
||||
IsValidCargo(): true
|
||||
@@ -1130,6 +1131,7 @@ ERROR: IsEnd() is invalid as Begin() is never called
|
||||
GetCargoIncome(10, 10): 3
|
||||
GetCargoIncome(100, 10): 38
|
||||
GetCargoIncome(10, 100): 3
|
||||
GetWeight(100): 6
|
||||
GetRoadVehicleTypeForCargo(): 0
|
||||
Cargo 1
|
||||
IsValidCargo(): true
|
||||
@@ -1142,6 +1144,7 @@ ERROR: IsEnd() is invalid as Begin() is never called
|
||||
GetCargoIncome(10, 10): 7
|
||||
GetCargoIncome(100, 10): 71
|
||||
GetCargoIncome(10, 100): 6
|
||||
GetWeight(100): 100
|
||||
GetRoadVehicleTypeForCargo(): 1
|
||||
Cargo 2
|
||||
IsValidCargo(): true
|
||||
@@ -1154,6 +1157,7 @@ ERROR: IsEnd() is invalid as Begin() is never called
|
||||
GetCargoIncome(10, 10): 5
|
||||
GetCargoIncome(100, 10): 55
|
||||
GetCargoIncome(10, 100): 5
|
||||
GetWeight(100): 25
|
||||
GetRoadVehicleTypeForCargo(): 1
|
||||
Cargo 3
|
||||
IsValidCargo(): true
|
||||
@@ -1166,6 +1170,7 @@ ERROR: IsEnd() is invalid as Begin() is never called
|
||||
GetCargoIncome(10, 10): 5
|
||||
GetCargoIncome(100, 10): 53
|
||||
GetCargoIncome(10, 100): 5
|
||||
GetWeight(100): 100
|
||||
GetRoadVehicleTypeForCargo(): 1
|
||||
Cargo 4
|
||||
IsValidCargo(): true
|
||||
@@ -1178,6 +1183,7 @@ ERROR: IsEnd() is invalid as Begin() is never called
|
||||
GetCargoIncome(10, 10): 5
|
||||
GetCargoIncome(100, 10): 52
|
||||
GetCargoIncome(10, 100): 4
|
||||
GetWeight(100): 18
|
||||
GetRoadVehicleTypeForCargo(): 1
|
||||
Cargo 5
|
||||
IsValidCargo(): true
|
||||
@@ -1190,6 +1196,7 @@ ERROR: IsEnd() is invalid as Begin() is never called
|
||||
GetCargoIncome(10, 10): 7
|
||||
GetCargoIncome(100, 10): 74
|
||||
GetCargoIncome(10, 100): 6
|
||||
GetWeight(100): 50
|
||||
GetRoadVehicleTypeForCargo(): 1
|
||||
Cargo 6
|
||||
IsValidCargo(): true
|
||||
@@ -1202,6 +1209,7 @@ ERROR: IsEnd() is invalid as Begin() is never called
|
||||
GetCargoIncome(10, 10): 5
|
||||
GetCargoIncome(100, 10): 58
|
||||
GetCargoIncome(10, 100): 4
|
||||
GetWeight(100): 100
|
||||
GetRoadVehicleTypeForCargo(): 1
|
||||
Cargo 7
|
||||
IsValidCargo(): true
|
||||
@@ -1214,6 +1222,7 @@ ERROR: IsEnd() is invalid as Begin() is never called
|
||||
GetCargoIncome(10, 10): 6
|
||||
GetCargoIncome(100, 10): 60
|
||||
GetCargoIncome(10, 100): 5
|
||||
GetWeight(100): 100
|
||||
GetRoadVehicleTypeForCargo(): 1
|
||||
Cargo 8
|
||||
IsValidCargo(): true
|
||||
@@ -1226,6 +1235,7 @@ ERROR: IsEnd() is invalid as Begin() is never called
|
||||
GetCargoIncome(10, 10): 6
|
||||
GetCargoIncome(100, 10): 62
|
||||
GetCargoIncome(10, 100): 5
|
||||
GetWeight(100): 100
|
||||
GetRoadVehicleTypeForCargo(): 1
|
||||
Cargo 9
|
||||
IsValidCargo(): true
|
||||
@@ -1238,6 +1248,7 @@ ERROR: IsEnd() is invalid as Begin() is never called
|
||||
GetCargoIncome(10, 10): 6
|
||||
GetCargoIncome(100, 10): 69
|
||||
GetCargoIncome(10, 100): 6
|
||||
GetWeight(100): 100
|
||||
GetRoadVehicleTypeForCargo(): 1
|
||||
Cargo 10
|
||||
IsValidCargo(): true
|
||||
@@ -1250,6 +1261,7 @@ ERROR: IsEnd() is invalid as Begin() is never called
|
||||
GetCargoIncome(10, 10): 9
|
||||
GetCargoIncome(100, 10): 90
|
||||
GetCargoIncome(10, 100): 7
|
||||
GetWeight(100): 12
|
||||
GetRoadVehicleTypeForCargo(): 1
|
||||
Cargo 11
|
||||
IsValidCargo(): false
|
||||
@@ -1262,6 +1274,7 @@ ERROR: IsEnd() is invalid as Begin() is never called
|
||||
GetCargoIncome(10, 10): -1
|
||||
GetCargoIncome(100, 10): -1
|
||||
GetCargoIncome(10, 100): -1
|
||||
GetWeight(100): -1
|
||||
GetRoadVehicleTypeForCargo(): 1
|
||||
Cargo 12
|
||||
IsValidCargo(): false
|
||||
@@ -1274,6 +1287,7 @@ ERROR: IsEnd() is invalid as Begin() is never called
|
||||
GetCargoIncome(10, 10): -1
|
||||
GetCargoIncome(100, 10): -1
|
||||
GetCargoIncome(10, 100): -1
|
||||
GetWeight(100): -1
|
||||
GetRoadVehicleTypeForCargo(): 1
|
||||
Cargo 13
|
||||
IsValidCargo(): false
|
||||
@@ -1286,6 +1300,7 @@ ERROR: IsEnd() is invalid as Begin() is never called
|
||||
GetCargoIncome(10, 10): -1
|
||||
GetCargoIncome(100, 10): -1
|
||||
GetCargoIncome(10, 100): -1
|
||||
GetWeight(100): -1
|
||||
GetRoadVehicleTypeForCargo(): 1
|
||||
Cargo 14
|
||||
IsValidCargo(): false
|
||||
@@ -1298,6 +1313,7 @@ ERROR: IsEnd() is invalid as Begin() is never called
|
||||
GetCargoIncome(10, 10): -1
|
||||
GetCargoIncome(100, 10): -1
|
||||
GetCargoIncome(10, 100): -1
|
||||
GetWeight(100): -1
|
||||
GetRoadVehicleTypeForCargo(): 1
|
||||
|
||||
--CargoList--
|
||||
@@ -7365,6 +7381,9 @@ ERROR: IsEnd() is invalid as Begin() is never called
|
||||
GetBankBalance(): 1999959285
|
||||
BuildWaterDepot(): true
|
||||
BuildDock(): true
|
||||
BuildBuoy(): true
|
||||
BuildLock(): true
|
||||
BuildCanal(): true
|
||||
|
||||
--Prices--
|
||||
-Rail-
|
||||
@@ -7391,6 +7410,8 @@ ERROR: IsEnd() is invalid as Begin() is never called
|
||||
BT_DOCK: 262
|
||||
BT_DEPOT: 525
|
||||
BT_BUOY: 262
|
||||
BT_LOCK: 5625
|
||||
BT_CANAL: 3750
|
||||
-Tile-
|
||||
BT_FOUNDATION: 187
|
||||
BT_TERRAFORM: 187
|
||||
@@ -7400,13 +7421,38 @@ ERROR: IsEnd() is invalid as Begin() is never called
|
||||
BT_CLEAR_ROCKY: 150
|
||||
BT_CLEAR_FIELDS: 375
|
||||
BT_CLEAR_HOUSE: 1200
|
||||
BT_CLEAR_WATER: 7500
|
||||
|
||||
--Rail--
|
||||
IsRailTile(): false
|
||||
BuildRailTrack(): true
|
||||
BuildSignal(): true
|
||||
GetSignalType(): 4
|
||||
GetSignalType(): 255
|
||||
RemoveSignal(): true
|
||||
BuildSignal(): true
|
||||
GetSignalType(): 255
|
||||
GetSignalType(): 1
|
||||
RemoveSignal(): true
|
||||
BuildSignal(): true
|
||||
GetSignalType(): 10
|
||||
GetSignalType(): 10
|
||||
RemoveRailTrack(): false
|
||||
RemoveRailTrack(): true
|
||||
BuildRailTrack(): true
|
||||
BuildSignal(): false
|
||||
GetSignalType(): 255
|
||||
GetSignalType(): 255
|
||||
RemoveSignal(): false
|
||||
BuildSignal(): true
|
||||
GetSignalType(): 255
|
||||
GetSignalType(): 1
|
||||
RemoveSignal(): true
|
||||
BuildSignal(): true
|
||||
GetSignalType(): 255
|
||||
GetSignalType(): 10
|
||||
RemoveRailTrack(): true
|
||||
RemoveRailTrack(): false
|
||||
BuildRail(): true
|
||||
HasTransportType(): true
|
||||
HasTransportType(): false
|
||||
@@ -8450,54 +8496,221 @@ ERROR: IsEnd() is invalid as Begin() is never called
|
||||
KeepValue(1): done
|
||||
Count(): 0
|
||||
ListDump:
|
||||
Water(): done
|
||||
Count(): 45
|
||||
IsWaterTile(): done
|
||||
Count(): 40
|
||||
ListDump:
|
||||
54941 => 1
|
||||
54940 => 1
|
||||
54939 => 1
|
||||
54938 => 1
|
||||
54937 => 1
|
||||
54936 => 1
|
||||
54935 => 1
|
||||
54934 => 1
|
||||
54933 => 1
|
||||
54685 => 1
|
||||
54684 => 1
|
||||
54683 => 1
|
||||
54682 => 1
|
||||
54681 => 1
|
||||
54680 => 1
|
||||
54679 => 1
|
||||
54678 => 1
|
||||
54677 => 1
|
||||
54429 => 1
|
||||
54428 => 1
|
||||
54427 => 1
|
||||
54426 => 1
|
||||
54425 => 1
|
||||
54424 => 1
|
||||
54423 => 1
|
||||
54422 => 1
|
||||
54421 => 1
|
||||
54173 => 1
|
||||
54172 => 1
|
||||
54171 => 1
|
||||
54170 => 1
|
||||
54169 => 1
|
||||
54168 => 0
|
||||
54167 => 0
|
||||
54166 => 0
|
||||
54165 => 0
|
||||
53917 => 0
|
||||
53916 => 0
|
||||
53915 => 0
|
||||
53914 => 0
|
||||
53913 => 0
|
||||
53912 => 0
|
||||
53911 => 0
|
||||
53910 => 0
|
||||
53909 => 0
|
||||
29251 => 1
|
||||
29250 => 1
|
||||
29249 => 1
|
||||
29248 => 1
|
||||
29247 => 1
|
||||
28996 => 1
|
||||
28995 => 1
|
||||
28994 => 1
|
||||
28993 => 1
|
||||
28992 => 1
|
||||
28991 => 1
|
||||
28744 => 1
|
||||
28741 => 1
|
||||
28740 => 1
|
||||
28739 => 1
|
||||
28738 => 1
|
||||
28737 => 1
|
||||
28736 => 1
|
||||
28735 => 1
|
||||
28488 => 1
|
||||
28487 => 1
|
||||
28486 => 1
|
||||
28485 => 1
|
||||
28484 => 1
|
||||
28483 => 1
|
||||
28482 => 1
|
||||
28480 => 1
|
||||
28479 => 1
|
||||
29256 => 0
|
||||
29255 => 0
|
||||
29254 => 0
|
||||
29253 => 0
|
||||
29252 => 0
|
||||
29000 => 0
|
||||
28999 => 0
|
||||
28998 => 0
|
||||
28997 => 0
|
||||
28743 => 0
|
||||
28742 => 0
|
||||
28481 => 0
|
||||
IsSeaTile(): done
|
||||
Count(): 40
|
||||
ListDump:
|
||||
29251 => 1
|
||||
29250 => 1
|
||||
29249 => 1
|
||||
29248 => 1
|
||||
29247 => 1
|
||||
28996 => 1
|
||||
28995 => 1
|
||||
28994 => 1
|
||||
28993 => 1
|
||||
28992 => 1
|
||||
28991 => 1
|
||||
28741 => 1
|
||||
28740 => 1
|
||||
28739 => 1
|
||||
28738 => 1
|
||||
28737 => 1
|
||||
28736 => 1
|
||||
28735 => 1
|
||||
28485 => 1
|
||||
28484 => 1
|
||||
28483 => 1
|
||||
28482 => 1
|
||||
29256 => 0
|
||||
29255 => 0
|
||||
29254 => 0
|
||||
29253 => 0
|
||||
29252 => 0
|
||||
29000 => 0
|
||||
28999 => 0
|
||||
28998 => 0
|
||||
28997 => 0
|
||||
28744 => 0
|
||||
28743 => 0
|
||||
28742 => 0
|
||||
28488 => 0
|
||||
28487 => 0
|
||||
28486 => 0
|
||||
28481 => 0
|
||||
28480 => 0
|
||||
28479 => 0
|
||||
IsRiverTile() done
|
||||
Count(): 40
|
||||
ListDump:
|
||||
29256 => 0
|
||||
29255 => 0
|
||||
29254 => 0
|
||||
29253 => 0
|
||||
29252 => 0
|
||||
29251 => 0
|
||||
29250 => 0
|
||||
29249 => 0
|
||||
29248 => 0
|
||||
29247 => 0
|
||||
29000 => 0
|
||||
28999 => 0
|
||||
28998 => 0
|
||||
28997 => 0
|
||||
28996 => 0
|
||||
28995 => 0
|
||||
28994 => 0
|
||||
28993 => 0
|
||||
28992 => 0
|
||||
28991 => 0
|
||||
28744 => 0
|
||||
28743 => 0
|
||||
28742 => 0
|
||||
28741 => 0
|
||||
28740 => 0
|
||||
28739 => 0
|
||||
28738 => 0
|
||||
28737 => 0
|
||||
28736 => 0
|
||||
28735 => 0
|
||||
28488 => 0
|
||||
28487 => 0
|
||||
28486 => 0
|
||||
28485 => 0
|
||||
28484 => 0
|
||||
28483 => 0
|
||||
28482 => 0
|
||||
28481 => 0
|
||||
28480 => 0
|
||||
28479 => 0
|
||||
IsCanalTile() done
|
||||
Count(): 40
|
||||
ListDump:
|
||||
28744 => 1
|
||||
29256 => 0
|
||||
29255 => 0
|
||||
29254 => 0
|
||||
29253 => 0
|
||||
29252 => 0
|
||||
29251 => 0
|
||||
29250 => 0
|
||||
29249 => 0
|
||||
29248 => 0
|
||||
29247 => 0
|
||||
29000 => 0
|
||||
28999 => 0
|
||||
28998 => 0
|
||||
28997 => 0
|
||||
28996 => 0
|
||||
28995 => 0
|
||||
28994 => 0
|
||||
28993 => 0
|
||||
28992 => 0
|
||||
28991 => 0
|
||||
28743 => 0
|
||||
28742 => 0
|
||||
28741 => 0
|
||||
28740 => 0
|
||||
28739 => 0
|
||||
28738 => 0
|
||||
28737 => 0
|
||||
28736 => 0
|
||||
28735 => 0
|
||||
28488 => 0
|
||||
28487 => 0
|
||||
28486 => 0
|
||||
28485 => 0
|
||||
28484 => 0
|
||||
28483 => 0
|
||||
28482 => 0
|
||||
28481 => 0
|
||||
28480 => 0
|
||||
28479 => 0
|
||||
IsCoastTile() done
|
||||
Count(): 40
|
||||
ListDump:
|
||||
28998 => 1
|
||||
28997 => 1
|
||||
28743 => 1
|
||||
28742 => 1
|
||||
29256 => 0
|
||||
29255 => 0
|
||||
29254 => 0
|
||||
29253 => 0
|
||||
29252 => 0
|
||||
29251 => 0
|
||||
29250 => 0
|
||||
29249 => 0
|
||||
29248 => 0
|
||||
29247 => 0
|
||||
29000 => 0
|
||||
28999 => 0
|
||||
28996 => 0
|
||||
28995 => 0
|
||||
28994 => 0
|
||||
28993 => 0
|
||||
28992 => 0
|
||||
28991 => 0
|
||||
28744 => 0
|
||||
28741 => 0
|
||||
28740 => 0
|
||||
28739 => 0
|
||||
28738 => 0
|
||||
28737 => 0
|
||||
28736 => 0
|
||||
28735 => 0
|
||||
28488 => 0
|
||||
28487 => 0
|
||||
28486 => 0
|
||||
28485 => 0
|
||||
28484 => 0
|
||||
28483 => 0
|
||||
28482 => 0
|
||||
28481 => 0
|
||||
28480 => 0
|
||||
28479 => 0
|
||||
|
||||
--TileList_IndustryAccepting--
|
||||
Count(): 47
|
||||
@@ -9139,9 +9352,9 @@ ERROR: IsEnd() is invalid as Begin() is never called
|
||||
GetNumWagons(): 3
|
||||
GetLength(): 24
|
||||
GetWagonEngineType(): 9
|
||||
GetWagonAge(): 1
|
||||
GetWagonAge(): 0
|
||||
GetWagonEngineType(): 27
|
||||
GetWagonAge(): 1
|
||||
GetWagonAge(): 0
|
||||
GetWagonEngineType(): 27
|
||||
GetWagonAge(): 0
|
||||
GetWagonEngineType(): 65535
|
||||
|
@@ -4,7 +4,7 @@ class StationList extends AIInfo {
|
||||
function GetShortName() { return "REGS"; }
|
||||
function GetDescription() { return "This runs stationlist-tests on some commands. On the same map the result should always be the same."; }
|
||||
function GetVersion() { return 1; }
|
||||
function GetAPIVersion() { return "12"; }
|
||||
function GetAPIVersion() { return "13"; }
|
||||
function GetDate() { return "2007-03-18"; }
|
||||
function CreateInstance() { return "StationList"; }
|
||||
function UseAsRandomAI() { return false; }
|
||||
|
18
src/3rdparty/squirrel/squirrel/sqobject.h
vendored
18
src/3rdparty/squirrel/squirrel/sqobject.h
vendored
@@ -62,6 +62,24 @@ struct SQRefCounted
|
||||
SQUnsignedInteger _uiRef;
|
||||
struct SQWeakRef *_weakref;
|
||||
virtual void Release()=0;
|
||||
|
||||
/* Placement new/delete to prevent memory leaks if constructor throws an exception. */
|
||||
inline void *operator new(size_t size, SQRefCounted *place)
|
||||
{
|
||||
place->size = size;
|
||||
return place;
|
||||
}
|
||||
|
||||
inline void operator delete(void *ptr, SQRefCounted *place)
|
||||
{
|
||||
SQ_FREE(ptr, place->size);
|
||||
}
|
||||
|
||||
/* Never used but required. */
|
||||
inline void operator delete(void *ptr) { NOT_REACHED(); }
|
||||
|
||||
private:
|
||||
size_t size;
|
||||
};
|
||||
|
||||
struct SQWeakRef : SQRefCounted
|
||||
|
@@ -10,6 +10,7 @@ add_subdirectory(3rdparty)
|
||||
add_subdirectory(ai)
|
||||
add_subdirectory(blitter)
|
||||
add_subdirectory(core)
|
||||
add_subdirectory(fontcache)
|
||||
add_subdirectory(game)
|
||||
add_subdirectory(lang)
|
||||
add_subdirectory(linkgraph)
|
||||
@@ -29,18 +30,15 @@ add_files(
|
||||
viewport_sprite_sorter_sse4.cpp
|
||||
CONDITION SSE_FOUND
|
||||
)
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
|
||||
set_compile_flags(
|
||||
viewport_sprite_sorter_sse4.cpp
|
||||
COMPILE_FLAGS -msse4.1)
|
||||
endif()
|
||||
|
||||
add_files(
|
||||
aircraft.h
|
||||
aircraft_cmd.cpp
|
||||
aircraft_cmd.h
|
||||
aircraft_gui.cpp
|
||||
airport.cpp
|
||||
airport.h
|
||||
airport_cmd.h
|
||||
airport_gui.cpp
|
||||
animated_tile.cpp
|
||||
animated_tile_func.h
|
||||
@@ -49,6 +47,7 @@ add_files(
|
||||
autoreplace.cpp
|
||||
autoreplace_base.h
|
||||
autoreplace_cmd.cpp
|
||||
autoreplace_cmd.h
|
||||
autoreplace_func.h
|
||||
autoreplace_gui.cpp
|
||||
autoreplace_gui.h
|
||||
@@ -84,12 +83,12 @@ add_files(
|
||||
clear_cmd.cpp
|
||||
clear_func.h
|
||||
clear_map.h
|
||||
cmd_helper.h
|
||||
command.cpp
|
||||
command_func.h
|
||||
command_type.h
|
||||
company_base.h
|
||||
company_cmd.cpp
|
||||
company_cmd.h
|
||||
company_func.h
|
||||
company_gui.cpp
|
||||
company_gui.h
|
||||
@@ -119,6 +118,7 @@ add_files(
|
||||
depot.cpp
|
||||
depot_base.h
|
||||
depot_cmd.cpp
|
||||
depot_cmd.h
|
||||
depot_func.h
|
||||
depot_gui.cpp
|
||||
depot_map.h
|
||||
@@ -127,11 +127,13 @@ add_files(
|
||||
direction_type.h
|
||||
disaster_vehicle.cpp
|
||||
disaster_vehicle.h
|
||||
dock_cmd.h
|
||||
dock_gui.cpp
|
||||
driver.cpp
|
||||
driver.h
|
||||
economy.cpp
|
||||
economy_base.h
|
||||
economy_cmd.h
|
||||
economy_func.h
|
||||
economy_type.h
|
||||
effectvehicle.cpp
|
||||
@@ -141,6 +143,7 @@ add_files(
|
||||
elrail_func.h
|
||||
engine.cpp
|
||||
engine_base.h
|
||||
engine_cmd.h
|
||||
engine_func.h
|
||||
engine_gui.cpp
|
||||
engine_gui.h
|
||||
@@ -155,7 +158,6 @@ add_files(
|
||||
fios_gui.cpp
|
||||
fontcache.cpp
|
||||
fontcache.h
|
||||
fontcache_internal.h
|
||||
fontdetection.h
|
||||
framerate_gui.cpp
|
||||
framerate_type.h
|
||||
@@ -174,6 +176,7 @@ add_files(
|
||||
gfxinit.h
|
||||
goal.cpp
|
||||
goal_base.h
|
||||
goal_cmd.h
|
||||
goal_gui.cpp
|
||||
goal_type.h
|
||||
graph_gui.cpp
|
||||
@@ -182,6 +185,7 @@ add_files(
|
||||
ground_vehicle.hpp
|
||||
group.h
|
||||
group_cmd.cpp
|
||||
group_cmd.h
|
||||
group_gui.cpp
|
||||
group_gui.h
|
||||
group_type.h
|
||||
@@ -198,6 +202,7 @@ add_files(
|
||||
house_type.h
|
||||
industry.h
|
||||
industry_cmd.cpp
|
||||
industry_cmd.h
|
||||
industry_gui.cpp
|
||||
industry_map.h
|
||||
industry_type.h
|
||||
@@ -208,8 +213,15 @@ add_files(
|
||||
intro_gui.cpp
|
||||
landscape.cpp
|
||||
landscape.h
|
||||
landscape_cmd.h
|
||||
landscape_type.h
|
||||
language.h
|
||||
league_base.h
|
||||
league_cmd.h
|
||||
league_cmd.cpp
|
||||
league_gui.h
|
||||
league_gui.cpp
|
||||
league_type.h
|
||||
livery.h
|
||||
main_gui.cpp
|
||||
map.cpp
|
||||
@@ -217,6 +229,7 @@ add_files(
|
||||
map_type.h
|
||||
misc.cpp
|
||||
misc_cmd.cpp
|
||||
misc_cmd.h
|
||||
misc_gui.cpp
|
||||
mixer.cpp
|
||||
mixer.h
|
||||
@@ -277,6 +290,7 @@ add_files(
|
||||
newgrf_town.h
|
||||
newgrf_townname.cpp
|
||||
newgrf_townname.h
|
||||
news_cmd.h
|
||||
news_func.h
|
||||
news_gui.cpp
|
||||
news_gui.h
|
||||
@@ -284,6 +298,7 @@ add_files(
|
||||
object.h
|
||||
object_base.h
|
||||
object_cmd.cpp
|
||||
object_cmd.h
|
||||
object_gui.cpp
|
||||
object_map.h
|
||||
object_type.h
|
||||
@@ -293,6 +308,7 @@ add_files(
|
||||
order_backup.h
|
||||
order_base.h
|
||||
order_cmd.cpp
|
||||
order_cmd.h
|
||||
order_func.h
|
||||
order_gui.cpp
|
||||
order_type.h
|
||||
@@ -305,6 +321,7 @@ add_files(
|
||||
rail.cpp
|
||||
rail.h
|
||||
rail_cmd.cpp
|
||||
rail_cmd.h
|
||||
rail_gui.cpp
|
||||
rail_gui.h
|
||||
rail_map.h
|
||||
@@ -327,6 +344,7 @@ add_files(
|
||||
roadstop_base.h
|
||||
roadveh.h
|
||||
roadveh_cmd.cpp
|
||||
roadveh_cmd.h
|
||||
roadveh_gui.cpp
|
||||
safeguards.h
|
||||
screenshot_gui.cpp
|
||||
@@ -334,6 +352,7 @@ add_files(
|
||||
screenshot.cpp
|
||||
screenshot.h
|
||||
settings.cpp
|
||||
settings_cmd.h
|
||||
settings_func.h
|
||||
settings_gui.cpp
|
||||
settings_gui.h
|
||||
@@ -343,6 +362,7 @@ add_files(
|
||||
settings_type.h
|
||||
ship.h
|
||||
ship_cmd.cpp
|
||||
ship_cmd.h
|
||||
ship_gui.cpp
|
||||
signal.cpp
|
||||
signal_func.h
|
||||
@@ -350,6 +370,7 @@ add_files(
|
||||
signs.cpp
|
||||
signs_base.h
|
||||
signs_cmd.cpp
|
||||
signs_cmd.h
|
||||
signs_func.h
|
||||
signs_gui.cpp
|
||||
signs_type.h
|
||||
@@ -368,6 +389,7 @@ add_files(
|
||||
station.cpp
|
||||
station_base.h
|
||||
station_cmd.cpp
|
||||
station_cmd.h
|
||||
station_func.h
|
||||
station_gui.cpp
|
||||
station_gui.h
|
||||
@@ -379,6 +401,7 @@ add_files(
|
||||
stdafx.h
|
||||
story.cpp
|
||||
story_base.h
|
||||
story_cmd.h
|
||||
story_gui.cpp
|
||||
story_type.h
|
||||
strgen/strgen.h
|
||||
@@ -393,11 +416,13 @@ add_files(
|
||||
strings_type.h
|
||||
subsidy.cpp
|
||||
subsidy_base.h
|
||||
subsidy_cmd.h
|
||||
subsidy_func.h
|
||||
subsidy_gui.cpp
|
||||
subsidy_type.h
|
||||
tar_type.h
|
||||
terraform_cmd.cpp
|
||||
terraform_cmd.h
|
||||
terraform_gui.cpp
|
||||
terraform_gui.h
|
||||
textbuf.cpp
|
||||
@@ -422,11 +447,13 @@ add_files(
|
||||
tilematrix_type.hpp
|
||||
timetable.h
|
||||
timetable_cmd.cpp
|
||||
timetable_cmd.h
|
||||
timetable_gui.cpp
|
||||
toolbar_gui.cpp
|
||||
toolbar_gui.h
|
||||
town.h
|
||||
town_cmd.cpp
|
||||
town_cmd.h
|
||||
town_gui.cpp
|
||||
town_kdtree.h
|
||||
town_map.h
|
||||
@@ -438,22 +465,26 @@ add_files(
|
||||
track_type.h
|
||||
train.h
|
||||
train_cmd.cpp
|
||||
train_cmd.h
|
||||
train_gui.cpp
|
||||
transparency.h
|
||||
transparency_gui.cpp
|
||||
transparency_gui.h
|
||||
transport_type.h
|
||||
tree_cmd.cpp
|
||||
tree_cmd.h
|
||||
tree_gui.cpp
|
||||
tree_map.h
|
||||
tunnel_map.cpp
|
||||
tunnel_map.h
|
||||
tunnelbridge.h
|
||||
tunnelbridge_cmd.cpp
|
||||
tunnelbridge_cmd.h
|
||||
tunnelbridge_map.h
|
||||
vehicle.cpp
|
||||
vehicle_base.h
|
||||
vehicle_cmd.cpp
|
||||
vehicle_cmd.h
|
||||
vehicle_func.h
|
||||
vehicle_gui.cpp
|
||||
vehicle_gui.h
|
||||
@@ -462,6 +493,7 @@ add_files(
|
||||
vehiclelist.cpp
|
||||
vehiclelist.h
|
||||
viewport.cpp
|
||||
viewport_cmd.h
|
||||
viewport_func.h
|
||||
viewport_gui.cpp
|
||||
viewport_kdtree.h
|
||||
@@ -472,10 +504,12 @@ add_files(
|
||||
walltime_func.h
|
||||
water.h
|
||||
water_cmd.cpp
|
||||
water_cmd.h
|
||||
water_map.h
|
||||
waypoint.cpp
|
||||
waypoint_base.h
|
||||
waypoint_cmd.cpp
|
||||
waypoint_cmd.h
|
||||
waypoint_func.h
|
||||
waypoint_gui.cpp
|
||||
widget.cpp
|
||||
|
@@ -139,9 +139,9 @@ public:
|
||||
static int GetStartNextTime();
|
||||
|
||||
/** Wrapper function for AIScanner::GetAIConsoleList */
|
||||
static char *GetConsoleList(char *p, const char *last, bool newest_only = false);
|
||||
static std::string GetConsoleList(bool newest_only = false);
|
||||
/** Wrapper function for AIScanner::GetAIConsoleLibraryList */
|
||||
static char *GetConsoleLibraryList(char *p, const char *last);
|
||||
static std::string GetConsoleLibraryList();
|
||||
/** Wrapper function for AIScanner::GetAIInfoList */
|
||||
static const ScriptInfoList *GetInfoList();
|
||||
/** Wrapper function for AIScanner::GetUniqueAIInfoList */
|
||||
|
@@ -315,14 +315,14 @@
|
||||
return DAYS_IN_YEAR;
|
||||
}
|
||||
|
||||
/* static */ char *AI::GetConsoleList(char *p, const char *last, bool newest_only)
|
||||
/* static */ std::string AI::GetConsoleList(bool newest_only)
|
||||
{
|
||||
return AI::scanner_info->GetConsoleList(p, last, newest_only);
|
||||
return AI::scanner_info->GetConsoleList(newest_only);
|
||||
}
|
||||
|
||||
/* static */ char *AI::GetConsoleLibraryList(char *p, const char *last)
|
||||
/* static */ std::string AI::GetConsoleLibraryList()
|
||||
{
|
||||
return AI::scanner_library->GetConsoleList(p, last, true);
|
||||
return AI::scanner_library->GetConsoleList(true);
|
||||
}
|
||||
|
||||
/* static */ const ScriptInfoList *AI::GetInfoList()
|
||||
|
@@ -28,6 +28,8 @@
|
||||
#include "../hotkeys.h"
|
||||
#include "../core/geometry_func.hpp"
|
||||
#include "../guitimer_func.h"
|
||||
#include "../company_cmd.h"
|
||||
#include "../misc_cmd.h"
|
||||
|
||||
#include "ai.hpp"
|
||||
#include "ai_gui.hpp"
|
||||
@@ -110,7 +112,7 @@ struct AIListWindow : public Window {
|
||||
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
|
||||
{
|
||||
if (widget == WID_AIL_LIST) {
|
||||
this->line_height = FONT_HEIGHT_NORMAL + WD_MATRIX_TOP + WD_MATRIX_BOTTOM;
|
||||
this->line_height = FONT_HEIGHT_NORMAL + padding.height;
|
||||
|
||||
resize->width = 1;
|
||||
resize->height = this->line_height;
|
||||
@@ -123,18 +125,18 @@ struct AIListWindow : public Window {
|
||||
switch (widget) {
|
||||
case WID_AIL_LIST: {
|
||||
/* Draw a list of all available AIs. */
|
||||
int y = this->GetWidget<NWidgetBase>(WID_AIL_LIST)->pos_y;
|
||||
Rect tr = r.Shrink(WidgetDimensions::scaled.matrix);
|
||||
/* First AI in the list is hardcoded to random */
|
||||
if (this->vscroll->IsVisible(0)) {
|
||||
DrawString(r.left + WD_MATRIX_LEFT, r.right - WD_MATRIX_LEFT, y + WD_MATRIX_TOP, this->slot == OWNER_DEITY ? STR_AI_CONFIG_NONE : STR_AI_CONFIG_RANDOM_AI, this->selected == -1 ? TC_WHITE : TC_ORANGE);
|
||||
y += this->line_height;
|
||||
DrawString(tr, this->slot == OWNER_DEITY ? STR_AI_CONFIG_NONE : STR_AI_CONFIG_RANDOM_AI, this->selected == -1 ? TC_WHITE : TC_ORANGE);
|
||||
tr.top += this->line_height;
|
||||
}
|
||||
int i = 0;
|
||||
for (const auto &item : *this->info_list) {
|
||||
i++;
|
||||
if (this->vscroll->IsVisible(i)) {
|
||||
DrawString(r.left + WD_MATRIX_LEFT, r.right - WD_MATRIX_RIGHT, y + WD_MATRIX_TOP, item.second->GetName(), (this->selected == i - 1) ? TC_WHITE : TC_ORANGE);
|
||||
y += this->line_height;
|
||||
DrawString(tr, item.second->GetName(), (this->selected == i - 1) ? TC_WHITE : TC_ORANGE);
|
||||
tr.top += this->line_height;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -148,20 +150,20 @@ struct AIListWindow : public Window {
|
||||
}
|
||||
/* Some info about the currently selected AI. */
|
||||
if (selected_info != nullptr) {
|
||||
int y = r.top + WD_FRAMERECT_TOP;
|
||||
Rect tr = r.Shrink(WidgetDimensions::scaled.frametext, WidgetDimensions::scaled.framerect);
|
||||
SetDParamStr(0, selected_info->GetAuthor());
|
||||
DrawString(r.left + WD_FRAMETEXT_LEFT, r.right - WD_FRAMETEXT_RIGHT, y, STR_AI_LIST_AUTHOR);
|
||||
y += FONT_HEIGHT_NORMAL + WD_PAR_VSEP_NORMAL;
|
||||
DrawString(tr, STR_AI_LIST_AUTHOR);
|
||||
tr.top += FONT_HEIGHT_NORMAL + WidgetDimensions::scaled.vsep_normal;
|
||||
SetDParam(0, selected_info->GetVersion());
|
||||
DrawString(r.left + WD_FRAMETEXT_LEFT, r.right - WD_FRAMETEXT_RIGHT, y, STR_AI_LIST_VERSION);
|
||||
y += FONT_HEIGHT_NORMAL + WD_PAR_VSEP_NORMAL;
|
||||
DrawString(tr, STR_AI_LIST_VERSION);
|
||||
tr.top += FONT_HEIGHT_NORMAL + WidgetDimensions::scaled.vsep_normal;
|
||||
if (selected_info->GetURL() != nullptr) {
|
||||
SetDParamStr(0, selected_info->GetURL());
|
||||
DrawString(r.left + WD_FRAMETEXT_LEFT, r.right - WD_FRAMETEXT_RIGHT, y, STR_AI_LIST_URL);
|
||||
y += FONT_HEIGHT_NORMAL + WD_PAR_VSEP_NORMAL;
|
||||
DrawString(tr, STR_AI_LIST_URL);
|
||||
tr.top += FONT_HEIGHT_NORMAL + WidgetDimensions::scaled.vsep_normal;
|
||||
}
|
||||
SetDParamStr(0, selected_info->GetDescription());
|
||||
DrawStringMultiLine(r.left + WD_FRAMETEXT_LEFT, r.right - WD_FRAMETEXT_RIGHT, y, r.bottom - WD_FRAMERECT_BOTTOM, STR_JUST_RAW_STRING, TC_WHITE);
|
||||
DrawStringMultiLine(tr, STR_JUST_RAW_STRING, TC_WHITE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -180,7 +182,7 @@ struct AIListWindow : public Window {
|
||||
for (int i = 0; i < this->selected; i++) it++;
|
||||
GetConfig(slot)->Change((*it).second->GetName(), (*it).second->GetVersion());
|
||||
}
|
||||
InvalidateWindowData(WC_GAME_OPTIONS, WN_GAME_OPTIONS_AI);
|
||||
InvalidateWindowData(WC_GAME_OPTIONS, slot == OWNER_DEITY ? WN_GAME_OPTIONS_GS : WN_GAME_OPTIONS_AI);
|
||||
InvalidateWindowClassesData(WC_AI_SETTINGS);
|
||||
CloseWindowByClass(WC_QUERY_STRING);
|
||||
InvalidateWindowClassesData(WC_TEXTFILE);
|
||||
@@ -251,7 +253,7 @@ static const NWidgetPart _nested_ai_list_widgets[] = {
|
||||
NWidget(WWT_MATRIX, COLOUR_MAUVE, WID_AIL_LIST), SetMinimalSize(188, 112), SetFill(1, 1), SetResize(1, 1), SetMatrixDataTip(1, 0, STR_AI_LIST_TOOLTIP), SetScrollbar(WID_AIL_SCROLLBAR),
|
||||
NWidget(NWID_VSCROLLBAR, COLOUR_MAUVE, WID_AIL_SCROLLBAR),
|
||||
EndContainer(),
|
||||
NWidget(WWT_PANEL, COLOUR_MAUVE, WID_AIL_INFO_BG), SetMinimalTextLines(8, WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM), SetResize(1, 0),
|
||||
NWidget(WWT_PANEL, COLOUR_MAUVE, WID_AIL_INFO_BG), SetMinimalTextLines(8, WidgetDimensions::unscaled.framerect.Vertical() + WidgetDimensions::unscaled.vsep_normal * 3), SetResize(1, 0),
|
||||
EndContainer(),
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
|
||||
@@ -274,7 +276,7 @@ static WindowDesc _ai_list_desc(
|
||||
* Open the AI list window to chose an AI for the given company slot.
|
||||
* @param slot The slot to change the AI of.
|
||||
*/
|
||||
static void ShowAIListWindow(CompanyID slot)
|
||||
void ShowAIListWindow(CompanyID slot)
|
||||
{
|
||||
CloseWindowByClass(WC_AI_LIST);
|
||||
new AIListWindow(&_ai_list_desc, slot);
|
||||
@@ -294,7 +296,7 @@ struct AISettingsWindow : public Window {
|
||||
int clicked_row; ///< The clicked row of settings.
|
||||
int line_height; ///< Height of a row in the matrix widget.
|
||||
Scrollbar *vscroll; ///< Cache of the vertical scrollbar.
|
||||
typedef std::vector<const ScriptConfigItem *> VisibleSettingsList;
|
||||
typedef std::vector<const ScriptConfigItem *> VisibleSettingsList; ///< typdef for a vector of script settings
|
||||
VisibleSettingsList visible_settings; ///< List of visible AI settings
|
||||
|
||||
/**
|
||||
@@ -318,15 +320,6 @@ struct AISettingsWindow : public Window {
|
||||
this->RebuildVisibleSettings();
|
||||
}
|
||||
|
||||
void SetStringParameters(int widget) const override
|
||||
{
|
||||
switch (widget) {
|
||||
case WID_AIS_CAPTION:
|
||||
SetDParam(0, (this->slot == OWNER_DEITY) ? STR_AI_SETTINGS_CAPTION_GAMESCRIPT : STR_AI_SETTINGS_CAPTION_AI);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rebuilds the list of visible settings. AI settings with the flag
|
||||
* AICONFIG_AI_DEVELOPER set will only be visible if the game setting
|
||||
@@ -349,7 +342,7 @@ struct AISettingsWindow : public Window {
|
||||
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
|
||||
{
|
||||
if (widget == WID_AIS_BACKGROUND) {
|
||||
this->line_height = std::max(SETTING_BUTTON_HEIGHT, FONT_HEIGHT_NORMAL) + WD_MATRIX_TOP + WD_MATRIX_BOTTOM;
|
||||
this->line_height = std::max(SETTING_BUTTON_HEIGHT, FONT_HEIGHT_NORMAL) + padding.height;
|
||||
|
||||
resize->width = 1;
|
||||
resize->height = this->line_height;
|
||||
@@ -366,11 +359,10 @@ struct AISettingsWindow : public Window {
|
||||
int i = 0;
|
||||
for (; !this->vscroll->IsVisible(i); i++) it++;
|
||||
|
||||
Rect ir = r.Shrink(WidgetDimensions::scaled.framerect);
|
||||
bool rtl = _current_text_dir == TD_RTL;
|
||||
uint buttons_left = rtl ? r.right - SETTING_BUTTON_WIDTH - 3 : r.left + 4;
|
||||
uint text_left = r.left + (rtl ? WD_FRAMERECT_LEFT : SETTING_BUTTON_WIDTH + 8);
|
||||
uint text_right = r.right - (rtl ? SETTING_BUTTON_WIDTH + 8 : WD_FRAMERECT_RIGHT);
|
||||
|
||||
Rect br = ir.WithWidth(SETTING_BUTTON_WIDTH, rtl);
|
||||
Rect tr = ir.Indent(SETTING_BUTTON_WIDTH + WidgetDimensions::scaled.hsep_wide, rtl);
|
||||
|
||||
int y = r.top;
|
||||
int button_y_offset = (this->line_height - SETTING_BUTTON_HEIGHT) / 2;
|
||||
@@ -399,13 +391,13 @@ struct AISettingsWindow : public Window {
|
||||
}
|
||||
|
||||
if ((config_item.flags & SCRIPTCONFIG_BOOLEAN) != 0) {
|
||||
DrawBoolButton(buttons_left, y + button_y_offset, current_value != 0, editable);
|
||||
DrawBoolButton(br.left, y + button_y_offset, current_value != 0, editable);
|
||||
SetDParam(idx++, current_value == 0 ? STR_CONFIG_SETTING_OFF : STR_CONFIG_SETTING_ON);
|
||||
} else {
|
||||
if (config_item.complete_labels) {
|
||||
DrawDropDownButton(buttons_left, y + button_y_offset, COLOUR_YELLOW, this->clicked_row == i && clicked_dropdown, editable);
|
||||
DrawDropDownButton(br.left, y + button_y_offset, COLOUR_YELLOW, this->clicked_row == i && clicked_dropdown, editable);
|
||||
} else {
|
||||
DrawArrowButtons(buttons_left, y + button_y_offset, COLOUR_YELLOW, (this->clicked_button == i) ? 1 + (this->clicked_increase != rtl) : 0, editable && current_value > config_item.min_value, editable && current_value < config_item.max_value);
|
||||
DrawArrowButtons(br.left, y + button_y_offset, COLOUR_YELLOW, (this->clicked_button == i) ? 1 + (this->clicked_increase != rtl) : 0, editable && current_value > config_item.min_value, editable && current_value < config_item.max_value);
|
||||
}
|
||||
if (config_item.labels != nullptr && config_item.labels->Contains(current_value)) {
|
||||
SetDParam(idx++, STR_JUST_RAW_STRING);
|
||||
@@ -416,7 +408,7 @@ struct AISettingsWindow : public Window {
|
||||
}
|
||||
}
|
||||
|
||||
DrawString(text_left, text_right, y + text_y_offset, str, colour);
|
||||
DrawString(tr.left, tr.right, y + text_y_offset, str, colour);
|
||||
y += this->line_height;
|
||||
}
|
||||
}
|
||||
@@ -434,8 +426,8 @@ struct AISettingsWindow : public Window {
|
||||
{
|
||||
switch (widget) {
|
||||
case WID_AIS_BACKGROUND: {
|
||||
const NWidgetBase *wid = this->GetWidget<NWidgetBase>(WID_AIS_BACKGROUND);
|
||||
int num = (pt.y - wid->pos_y) / this->line_height + this->vscroll->GetPosition();
|
||||
Rect r = this->GetWidget<NWidgetBase>(widget)->GetCurrentRect().Shrink(WidgetDimensions::scaled.matrix, RectPadding::zero);
|
||||
int num = (pt.y - r.top) / this->line_height + this->vscroll->GetPosition();
|
||||
if (num >= (int)this->visible_settings.size()) break;
|
||||
|
||||
VisibleSettingsList::const_iterator it = this->visible_settings.begin();
|
||||
@@ -452,9 +444,8 @@ struct AISettingsWindow : public Window {
|
||||
|
||||
bool bool_item = (config_item.flags & SCRIPTCONFIG_BOOLEAN) != 0;
|
||||
|
||||
int x = pt.x - wid->pos_x;
|
||||
if (_current_text_dir == TD_RTL) x = wid->current_x - 1 - x;
|
||||
x -= 4;
|
||||
int x = pt.x - r.left;
|
||||
if (_current_text_dir == TD_RTL) x = r.Width() - 1 - x;
|
||||
|
||||
/* One of the arrows is clicked (or green/red rect in case of bool value) */
|
||||
int old_val = this->ai_config->GetSetting(config_item.name);
|
||||
@@ -465,8 +456,7 @@ struct AISettingsWindow : public Window {
|
||||
this->clicked_dropdown = false;
|
||||
this->closing_dropdown = false;
|
||||
} else {
|
||||
const NWidgetBase *wid = this->GetWidget<NWidgetBase>(WID_AIS_BACKGROUND);
|
||||
int rel_y = (pt.y - (int)wid->pos_y) % this->line_height;
|
||||
int rel_y = (pt.y - r.top) % this->line_height;
|
||||
|
||||
Rect wi_rect;
|
||||
wi_rect.left = pt.x - (_current_text_dir == TD_RTL ? SETTING_BUTTON_WIDTH - 1 - x : x);
|
||||
@@ -474,7 +464,7 @@ struct AISettingsWindow : public Window {
|
||||
wi_rect.top = pt.y - rel_y + (this->line_height - SETTING_BUTTON_HEIGHT) / 2;
|
||||
wi_rect.bottom = wi_rect.top + SETTING_BUTTON_HEIGHT - 1;
|
||||
|
||||
/* For dropdowns we also have to check the y position thoroughly, the mouse may not above the just opening dropdown */
|
||||
/* If the mouse is still held but dragged outside of the dropdown list, keep the dropdown open */
|
||||
if (pt.y >= wi_rect.top && pt.y <= wi_rect.bottom) {
|
||||
this->clicked_dropdown = true;
|
||||
this->closing_dropdown = false;
|
||||
@@ -531,24 +521,15 @@ struct AISettingsWindow : public Window {
|
||||
void OnQueryTextFinished(char *str) override
|
||||
{
|
||||
if (StrEmpty(str)) return;
|
||||
VisibleSettingsList::const_iterator it = this->visible_settings.begin();
|
||||
for (int i = 0; i < this->clicked_row; i++) it++;
|
||||
const ScriptConfigItem config_item = **it;
|
||||
if (_game_mode == GM_NORMAL && ((this->slot == OWNER_DEITY) || Company::IsValidID(this->slot)) && (config_item.flags & SCRIPTCONFIG_INGAME) == 0) return;
|
||||
int32 value = atoi(str);
|
||||
this->ai_config->SetSetting(config_item.name, value);
|
||||
this->SetDirty();
|
||||
|
||||
SetValue(value);
|
||||
}
|
||||
|
||||
void OnDropdownSelect(int widget, int index) override
|
||||
{
|
||||
assert(this->clicked_dropdown);
|
||||
VisibleSettingsList::const_iterator it = this->visible_settings.begin();
|
||||
for (int i = 0; i < this->clicked_row; i++) it++;
|
||||
const ScriptConfigItem config_item = **it;
|
||||
if (_game_mode == GM_NORMAL && ((this->slot == OWNER_DEITY) || Company::IsValidID(this->slot)) && (config_item.flags & SCRIPTCONFIG_INGAME) == 0) return;
|
||||
this->ai_config->SetSetting(config_item.name, index);
|
||||
this->SetDirty();
|
||||
SetValue(index);
|
||||
}
|
||||
|
||||
void OnDropdownClose(Point pt, int widget, int index, bool instant_close) override
|
||||
@@ -590,7 +571,21 @@ struct AISettingsWindow : public Window {
|
||||
private:
|
||||
bool IsEditableItem(const ScriptConfigItem &config_item) const
|
||||
{
|
||||
return _game_mode == GM_MENU || ((this->slot != OWNER_DEITY) && !Company::IsValidID(this->slot)) || (config_item.flags & SCRIPTCONFIG_INGAME) != 0;
|
||||
return _game_mode == GM_MENU
|
||||
|| _game_mode == GM_EDITOR
|
||||
|| ((this->slot != OWNER_DEITY) && !Company::IsValidID(this->slot))
|
||||
|| (config_item.flags & SCRIPTCONFIG_INGAME) != 0
|
||||
|| _settings_client.gui.ai_developer_tools;
|
||||
}
|
||||
|
||||
void SetValue(int value)
|
||||
{
|
||||
VisibleSettingsList::const_iterator it = this->visible_settings.begin();
|
||||
for (int i = 0; i < this->clicked_row; i++) it++;
|
||||
const ScriptConfigItem config_item = **it;
|
||||
if (_game_mode == GM_NORMAL && ((this->slot == OWNER_DEITY) || Company::IsValidID(this->slot)) && (config_item.flags & SCRIPTCONFIG_INGAME) == 0) return;
|
||||
this->ai_config->SetSetting(config_item.name, value);
|
||||
this->SetDirty();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -598,7 +593,7 @@ private:
|
||||
static const NWidgetPart _nested_ai_settings_widgets[] = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_MAUVE),
|
||||
NWidget(WWT_CAPTION, COLOUR_MAUVE, WID_AIS_CAPTION), SetDataTip(STR_AI_SETTINGS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||
NWidget(WWT_CAPTION, COLOUR_MAUVE, WID_AIS_CAPTION), SetDataTip(STR_AI_SETTINGS_CAPTION_AI, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||
NWidget(WWT_DEFSIZEBOX, COLOUR_MAUVE),
|
||||
EndContainer(),
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
@@ -678,15 +673,15 @@ void ShowScriptTextfileWindow(TextfileType file_type, CompanyID slot)
|
||||
static const NWidgetPart _nested_ai_config_widgets[] = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_MAUVE),
|
||||
NWidget(WWT_CAPTION, COLOUR_MAUVE), SetDataTip(STR_AI_CONFIG_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||
NWidget(WWT_CAPTION, COLOUR_MAUVE), SetDataTip(STR_AI_CONFIG_CAPTION_AI, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||
EndContainer(),
|
||||
NWidget(WWT_PANEL, COLOUR_MAUVE, WID_AIC_BACKGROUND),
|
||||
NWidget(NWID_VERTICAL), SetPIP(4, 4, 4),
|
||||
NWidget(NWID_HORIZONTAL), SetPIP(7, 0, 7),
|
||||
NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_AIC_DECREASE), SetFill(0, 1), SetDataTip(AWV_DECREASE, STR_NULL),
|
||||
NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_AIC_INCREASE), SetFill(0, 1), SetDataTip(AWV_INCREASE, STR_NULL),
|
||||
NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_AIC_DECREASE), SetDataTip(AWV_DECREASE, STR_NULL),
|
||||
NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_AIC_INCREASE), SetDataTip(AWV_INCREASE, STR_NULL),
|
||||
NWidget(NWID_SPACER), SetMinimalSize(6, 0),
|
||||
NWidget(WWT_TEXT, COLOUR_MAUVE, WID_AIC_NUMBER), SetDataTip(STR_DIFFICULTY_LEVEL_SETTING_MAXIMUM_NO_COMPETITORS, STR_NULL), SetFill(1, 0), SetPadding(1, 0, 0, 0),
|
||||
NWidget(WWT_TEXT, COLOUR_MAUVE, WID_AIC_NUMBER), SetDataTip(STR_AI_CONFIG_MAX_COMPETITORS, STR_NULL), SetFill(1, 0),
|
||||
EndContainer(),
|
||||
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(7, 0, 7),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_AIC_MOVE_UP), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_AI_CONFIG_MOVE_UP, STR_AI_CONFIG_MOVE_UP_TOOLTIP),
|
||||
@@ -700,16 +695,13 @@ static const NWidgetPart _nested_ai_config_widgets[] = {
|
||||
EndContainer(),
|
||||
EndContainer(),
|
||||
NWidget(NWID_SPACER), SetMinimalSize(0, 9),
|
||||
NWidget(WWT_FRAME, COLOUR_MAUVE), SetDataTip(STR_AI_CONFIG_GAMESCRIPT, STR_NULL), SetPadding(0, 5, 4, 5),
|
||||
NWidget(WWT_MATRIX, COLOUR_MAUVE, WID_AIC_GAMELIST), SetMinimalSize(288, 14), SetFill(1, 0), SetMatrixDataTip(1, 1, STR_AI_CONFIG_GAMELIST_TOOLTIP),
|
||||
EndContainer(),
|
||||
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(7, 0, 7),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_AIC_CHANGE), SetFill(1, 0), SetMinimalSize(93, 0), SetDataTip(STR_AI_CONFIG_CHANGE, STR_AI_CONFIG_CHANGE_TOOLTIP),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_AIC_CHANGE), SetFill(1, 0), SetMinimalSize(93, 0), SetDataTip(STR_AI_CONFIG_CHANGE_AI, STR_AI_CONFIG_CHANGE_TOOLTIP),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_AIC_CONFIGURE), SetFill(1, 0), SetMinimalSize(93, 0), SetDataTip(STR_AI_CONFIG_CONFIGURE, STR_AI_CONFIG_CONFIGURE_TOOLTIP),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_AIC_CLOSE), SetFill(1, 0), SetMinimalSize(93, 0), SetDataTip(STR_AI_SETTINGS_CLOSE, STR_NULL),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_AIC_TEXTFILE + TFT_README), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_README, STR_NULL),
|
||||
EndContainer(),
|
||||
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(7, 0, 7),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_AIC_TEXTFILE + TFT_README), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_README, STR_NULL),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_AIC_CLOSE), SetFill(1, 0), SetMinimalSize(93, 0), SetDataTip(STR_AI_SETTINGS_CLOSE, STR_NULL),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_AIC_TEXTFILE + TFT_CHANGELOG), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_CHANGELOG, STR_NULL),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_AIC_TEXTFILE + TFT_LICENSE), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_LICENCE, STR_NULL),
|
||||
EndContainer(),
|
||||
@@ -757,53 +749,22 @@ struct AIConfigWindow : public Window {
|
||||
case WID_AIC_NUMBER:
|
||||
SetDParam(0, GetGameSettings().difficulty.max_no_competitors);
|
||||
break;
|
||||
case WID_AIC_CHANGE:
|
||||
switch (selected_slot) {
|
||||
case OWNER_DEITY:
|
||||
SetDParam(0, STR_AI_CONFIG_CHANGE_GAMESCRIPT);
|
||||
break;
|
||||
|
||||
case INVALID_COMPANY:
|
||||
SetDParam(0, STR_AI_CONFIG_CHANGE_NONE);
|
||||
break;
|
||||
|
||||
default:
|
||||
SetDParam(0, STR_AI_CONFIG_CHANGE_AI);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
|
||||
{
|
||||
switch (widget) {
|
||||
case WID_AIC_GAMELIST:
|
||||
this->line_height = FONT_HEIGHT_NORMAL + WD_MATRIX_TOP + WD_MATRIX_BOTTOM;
|
||||
size->height = 1 * this->line_height;
|
||||
case WID_AIC_DECREASE:
|
||||
case WID_AIC_INCREASE:
|
||||
*size = maxdim(*size, NWidgetScrollbar::GetHorizontalDimension());
|
||||
break;
|
||||
|
||||
case WID_AIC_LIST:
|
||||
this->line_height = FONT_HEIGHT_NORMAL + WD_MATRIX_TOP + WD_MATRIX_BOTTOM;
|
||||
this->line_height = FONT_HEIGHT_NORMAL + padding.height;
|
||||
resize->height = this->line_height;
|
||||
size->height = 8 * this->line_height;
|
||||
break;
|
||||
|
||||
case WID_AIC_CHANGE: {
|
||||
SetDParam(0, STR_AI_CONFIG_CHANGE_GAMESCRIPT);
|
||||
Dimension dim = GetStringBoundingBox(STR_AI_CONFIG_CHANGE);
|
||||
|
||||
SetDParam(0, STR_AI_CONFIG_CHANGE_NONE);
|
||||
dim = maxdim(dim, GetStringBoundingBox(STR_AI_CONFIG_CHANGE));
|
||||
|
||||
SetDParam(0, STR_AI_CONFIG_CHANGE_AI);
|
||||
dim = maxdim(dim, GetStringBoundingBox(STR_AI_CONFIG_CHANGE));
|
||||
|
||||
dim.width += padding.width;
|
||||
dim.height += padding.height;
|
||||
*size = maxdim(*size, dim);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -814,8 +775,6 @@ struct AIConfigWindow : public Window {
|
||||
*/
|
||||
static bool IsEditable(CompanyID slot)
|
||||
{
|
||||
if (slot == OWNER_DEITY) return _game_mode != GM_NORMAL || Game::GetInstance() != nullptr;
|
||||
|
||||
if (_game_mode != GM_NORMAL) {
|
||||
return slot > 0 && slot <= GetGameSettings().difficulty.max_no_competitors;
|
||||
}
|
||||
@@ -831,22 +790,8 @@ struct AIConfigWindow : public Window {
|
||||
void DrawWidget(const Rect &r, int widget) const override
|
||||
{
|
||||
switch (widget) {
|
||||
case WID_AIC_GAMELIST: {
|
||||
StringID text = STR_AI_CONFIG_NONE;
|
||||
|
||||
if (GameConfig::GetConfig()->GetInfo() != nullptr) {
|
||||
SetDParamStr(0, GameConfig::GetConfig()->GetInfo()->GetName());
|
||||
text = STR_JUST_RAW_STRING;
|
||||
}
|
||||
|
||||
DrawString(r.left + 10, r.right - 10, r.top + WD_MATRIX_TOP, text,
|
||||
(this->selected_slot == OWNER_DEITY) ? TC_WHITE : (IsEditable(OWNER_DEITY) ? TC_ORANGE : TC_SILVER));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WID_AIC_LIST: {
|
||||
int y = r.top;
|
||||
Rect tr = r.Shrink(WidgetDimensions::scaled.matrix);
|
||||
for (int i = this->vscroll->GetPosition(); this->vscroll->IsVisible(i) && i < MAX_COMPANIES; i++) {
|
||||
StringID text;
|
||||
|
||||
@@ -858,9 +803,9 @@ struct AIConfigWindow : public Window {
|
||||
} else {
|
||||
text = STR_AI_CONFIG_RANDOM_AI;
|
||||
}
|
||||
DrawString(r.left + 10, r.right - 10, y + WD_MATRIX_TOP, text,
|
||||
DrawString(tr, text,
|
||||
(this->selected_slot == i) ? TC_WHITE : (IsEditable((CompanyID)i) ? TC_ORANGE : TC_SILVER));
|
||||
y += this->line_height;
|
||||
tr.top += this->line_height;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -889,13 +834,6 @@ struct AIConfigWindow : public Window {
|
||||
break;
|
||||
}
|
||||
|
||||
case WID_AIC_GAMELIST: {
|
||||
this->selected_slot = OWNER_DEITY;
|
||||
this->InvalidateData();
|
||||
if (click_count > 1 && this->selected_slot != INVALID_COMPANY && _game_mode != GM_NORMAL) ShowAIListWindow((CompanyID)this->selected_slot);
|
||||
break;
|
||||
}
|
||||
|
||||
case WID_AIC_LIST: { // Select a slot
|
||||
this->selected_slot = (CompanyID)this->vscroll->GetScrolledRowFromWidget(pt.y, this, widget);
|
||||
this->InvalidateData();
|
||||
@@ -937,7 +875,7 @@ struct AIConfigWindow : public Window {
|
||||
if (!_network_available) {
|
||||
ShowErrorMessage(STR_NETWORK_ERROR_NOTAVAILABLE, INVALID_STRING_ID, WL_ERROR);
|
||||
} else {
|
||||
ShowNetworkContentListWindow(nullptr, CONTENT_TYPE_AI, CONTENT_TYPE_GAME);
|
||||
ShowNetworkContentListWindow(nullptr, CONTENT_TYPE_AI);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -958,10 +896,10 @@ struct AIConfigWindow : public Window {
|
||||
|
||||
this->SetWidgetDisabledState(WID_AIC_DECREASE, GetGameSettings().difficulty.max_no_competitors == 0);
|
||||
this->SetWidgetDisabledState(WID_AIC_INCREASE, GetGameSettings().difficulty.max_no_competitors == MAX_COMPANIES - 1);
|
||||
this->SetWidgetDisabledState(WID_AIC_CHANGE, (this->selected_slot == OWNER_DEITY && _game_mode == GM_NORMAL) || this->selected_slot == INVALID_COMPANY);
|
||||
this->SetWidgetDisabledState(WID_AIC_CHANGE, this->selected_slot == INVALID_COMPANY);
|
||||
this->SetWidgetDisabledState(WID_AIC_CONFIGURE, this->selected_slot == INVALID_COMPANY || GetConfig(this->selected_slot)->GetConfigList()->size() == 0);
|
||||
this->SetWidgetDisabledState(WID_AIC_MOVE_UP, this->selected_slot == OWNER_DEITY || this->selected_slot == INVALID_COMPANY || !IsEditable((CompanyID)(this->selected_slot - 1)));
|
||||
this->SetWidgetDisabledState(WID_AIC_MOVE_DOWN, this->selected_slot == OWNER_DEITY || this->selected_slot == INVALID_COMPANY || !IsEditable((CompanyID)(this->selected_slot + 1)));
|
||||
this->SetWidgetDisabledState(WID_AIC_MOVE_UP, this->selected_slot == INVALID_COMPANY || !IsEditable((CompanyID)(this->selected_slot - 1)));
|
||||
this->SetWidgetDisabledState(WID_AIC_MOVE_DOWN, this->selected_slot == INVALID_COMPANY || !IsEditable((CompanyID)(this->selected_slot + 1)));
|
||||
|
||||
for (TextfileType tft = TFT_BEGIN; tft < TFT_END; tft++) {
|
||||
this->SetWidgetDisabledState(WID_AIC_TEXTFILE + tft, this->selected_slot == INVALID_COMPANY || (GetConfig(this->selected_slot)->GetTextfile(tft, this->selected_slot) == nullptr));
|
||||
@@ -1001,9 +939,6 @@ static bool SetScriptButtonColour(NWidgetCore &button, bool dead, bool paused)
|
||||
* Window with everything an AI prints via ScriptLog.
|
||||
*/
|
||||
struct AIDebugWindow : public Window {
|
||||
static const int top_offset; ///< Offset of the text at the top of the WID_AID_LOG_PANEL.
|
||||
static const int bottom_offset; ///< Offset of the text at the bottom of the WID_AID_LOG_PANEL.
|
||||
|
||||
static const uint MAX_BREAK_STR_STRING_LENGTH = 256; ///< Maximum length of the break string.
|
||||
|
||||
static CompanyID ai_debug_company; ///< The AI that is (was last) being debugged.
|
||||
@@ -1107,8 +1042,8 @@ struct AIDebugWindow : public Window {
|
||||
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
|
||||
{
|
||||
if (widget == WID_AID_LOG_PANEL) {
|
||||
resize->height = FONT_HEIGHT_NORMAL + WD_PAR_VSEP_NORMAL;
|
||||
size->height = 14 * resize->height + this->top_offset + this->bottom_offset;
|
||||
resize->height = FONT_HEIGHT_NORMAL + WidgetDimensions::scaled.vsep_normal;
|
||||
size->height = 14 * resize->height + WidgetDimensions::scaled.framerect.Vertical();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1222,7 +1157,8 @@ struct AIDebugWindow : public Window {
|
||||
ScriptLog::LogData *log = this->GetLogPointer();
|
||||
if (log == nullptr) return;
|
||||
|
||||
int y = this->top_offset;
|
||||
Rect br = r.Shrink(WidgetDimensions::scaled.bevel);
|
||||
Rect tr = r.Shrink(WidgetDimensions::scaled.framerect);
|
||||
for (int i = this->vscroll->GetPosition(); this->vscroll->IsVisible(i) && i < log->used; i++) {
|
||||
int pos = (i + log->pos + 1 - log->used + log->count) % log->count;
|
||||
if (log->lines[pos] == nullptr) break;
|
||||
@@ -1239,12 +1175,12 @@ struct AIDebugWindow : public Window {
|
||||
|
||||
/* Check if the current line should be highlighted */
|
||||
if (pos == this->highlight_row) {
|
||||
GfxFillRect(r.left + 1, r.top + y, r.right - 1, r.top + y + this->resize.step_height - WD_PAR_VSEP_NORMAL, PC_BLACK);
|
||||
GfxFillRect(br.left, tr.top, br.right, tr.top + this->resize.step_height - 1, PC_BLACK);
|
||||
if (colour == TC_BLACK) colour = TC_WHITE; // Make black text readable by inverting it to white.
|
||||
}
|
||||
|
||||
DrawString(r.left + 7, r.right - 7, r.top + y, log->lines[pos], colour, SA_LEFT | SA_FORCE);
|
||||
y += this->resize.step_height;
|
||||
DrawString(tr, log->lines[pos], colour, SA_LEFT | SA_FORCE);
|
||||
tr.top += this->resize.step_height;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1290,8 +1226,8 @@ struct AIDebugWindow : public Window {
|
||||
case WID_AID_RELOAD_TOGGLE:
|
||||
if (ai_debug_company == OWNER_DEITY) break;
|
||||
/* First kill the company of the AI, then start a new one. This should start the current AI again */
|
||||
DoCommandP(0, CCA_DELETE | ai_debug_company << 16 | CRR_MANUAL << 24, 0, CMD_COMPANY_CTRL);
|
||||
DoCommandP(0, CCA_NEW_AI | ai_debug_company << 16, 0, CMD_COMPANY_CTRL);
|
||||
Command<CMD_COMPANY_CTRL>::Post(CCA_DELETE, ai_debug_company, CRR_MANUAL, INVALID_CLIENT_ID);
|
||||
Command<CMD_COMPANY_CTRL>::Post(CCA_NEW_AI, ai_debug_company, CRR_NONE, INVALID_CLIENT_ID);
|
||||
break;
|
||||
|
||||
case WID_AID_SETTINGS:
|
||||
@@ -1330,7 +1266,7 @@ struct AIDebugWindow : public Window {
|
||||
}
|
||||
if (all_unpaused) {
|
||||
/* All scripts have been unpaused => unpause the game. */
|
||||
DoCommandP(0, PM_PAUSED_NORMAL, 0, CMD_PAUSE);
|
||||
Command<CMD_PAUSE>::Post(PM_PAUSED_NORMAL, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1379,7 +1315,7 @@ struct AIDebugWindow : public Window {
|
||||
|
||||
/* Pause the game. */
|
||||
if ((_pause_mode & PM_PAUSED_NORMAL) == PM_UNPAUSED) {
|
||||
DoCommandP(0, PM_PAUSED_NORMAL, 1, CMD_PAUSE);
|
||||
Command<CMD_PAUSE>::Post(PM_PAUSED_NORMAL, true);
|
||||
}
|
||||
|
||||
/* Highlight row that matched */
|
||||
@@ -1416,14 +1352,12 @@ struct AIDebugWindow : public Window {
|
||||
|
||||
void OnResize() override
|
||||
{
|
||||
this->vscroll->SetCapacityFromWidget(this, WID_AID_LOG_PANEL);
|
||||
this->vscroll->SetCapacityFromWidget(this, WID_AID_LOG_PANEL, WidgetDimensions::scaled.framerect.Vertical());
|
||||
}
|
||||
|
||||
static HotkeyList hotkeys;
|
||||
};
|
||||
|
||||
const int AIDebugWindow::top_offset = WD_FRAMERECT_TOP + 2;
|
||||
const int AIDebugWindow::bottom_offset = WD_FRAMERECT_BOTTOM;
|
||||
CompanyID AIDebugWindow::ai_debug_company = INVALID_COMPANY;
|
||||
char AIDebugWindow::break_string[MAX_BREAK_STR_STRING_LENGTH] = "";
|
||||
bool AIDebugWindow::break_check_enabled = true;
|
||||
|
@@ -12,8 +12,10 @@
|
||||
|
||||
#include "../company_type.h"
|
||||
|
||||
void ShowAIListWindow(CompanyID slot);
|
||||
Window* ShowAIDebugWindow(CompanyID show_company = INVALID_COMPANY);
|
||||
void ShowAIConfigWindow();
|
||||
void ShowScriptTextfileWindow(TextfileType file_type, CompanyID slot);
|
||||
void ShowAIDebugWindowIfAIError();
|
||||
void InitializeAIGui();
|
||||
|
||||
|
@@ -25,7 +25,7 @@
|
||||
*/
|
||||
static bool CheckAPIVersion(const char *api_version)
|
||||
{
|
||||
static const std::set<std::string> versions = { "0.7", "1.0", "1.1", "1.2", "1.3", "1.4", "1.5", "1.6", "1.7", "1.8", "1.9", "1.10", "1.11", "12" };
|
||||
static const std::set<std::string> versions = { "0.7", "1.0", "1.1", "1.2", "1.3", "1.4", "1.5", "1.6", "1.7", "1.8", "1.9", "1.10", "1.11", "12", "13" };
|
||||
return versions.find(api_version) != versions.end();
|
||||
}
|
||||
|
||||
|
@@ -18,6 +18,7 @@
|
||||
#include "ai.hpp"
|
||||
|
||||
#include "../script/script_storage.hpp"
|
||||
#include "../script/script_cmd.h"
|
||||
#include "ai_info.hpp"
|
||||
#include "ai_instance.hpp"
|
||||
|
||||
@@ -92,13 +93,13 @@ ScriptInfo *AIInstance::FindLibrary(const char *library, int version)
|
||||
|
||||
/**
|
||||
* DoCommand callback function for all commands executed by AIs.
|
||||
* @param cmd cmd as given to DoCommandPInternal.
|
||||
* @param result The result of the command.
|
||||
* @param tile The tile on which the command was executed.
|
||||
* @param p1 p1 as given to DoCommandPInternal.
|
||||
* @param p2 p2 as given to DoCommandPInternal.
|
||||
* @param cmd cmd as given to DoCommandPInternal.
|
||||
* @param data Command data as given to Command<>::Post.
|
||||
* @param result_data Additional returned data from the command.
|
||||
*/
|
||||
void CcAI(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
|
||||
void CcAI(Commands cmd, const CommandCost &result, TileIndex tile, const CommandDataBuffer &data, CommandDataBuffer result_data)
|
||||
{
|
||||
/*
|
||||
* The company might not exist anymore. Check for this.
|
||||
@@ -109,12 +110,12 @@ void CcAI(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint3
|
||||
const Company *c = Company::GetIfValid(_current_company);
|
||||
if (c == nullptr || c->ai_instance == nullptr) return;
|
||||
|
||||
if (c->ai_instance->DoCommandCallback(result, tile, p1, p2, cmd)) {
|
||||
if (c->ai_instance->DoCommandCallback(result, tile, data, std::move(result_data), cmd)) {
|
||||
c->ai_instance->Continue();
|
||||
}
|
||||
}
|
||||
|
||||
CommandCallback *AIInstance::GetDoCommandCallback()
|
||||
CommandCallbackData *AIInstance::GetDoCommandCallback()
|
||||
{
|
||||
return &CcAI;
|
||||
}
|
||||
|
@@ -29,7 +29,7 @@ public:
|
||||
private:
|
||||
void RegisterAPI() override;
|
||||
void Died() override;
|
||||
CommandCallback *GetDoCommandCallback() override;
|
||||
CommandCallbackData *GetDoCommandCallback() override;
|
||||
void LoadDummyScript() override;
|
||||
};
|
||||
|
||||
|
@@ -91,7 +91,7 @@ struct Aircraft FINAL : public SpecializedVehicle<Aircraft, VEH_AIRCRAFT> {
|
||||
|
||||
void MarkDirty();
|
||||
void UpdateDeltaXY();
|
||||
ExpensesType GetExpenseType(bool income) const { return income ? EXPENSES_AIRCRAFT_INC : EXPENSES_AIRCRAFT_RUN; }
|
||||
ExpensesType GetExpenseType(bool income) const { return income ? EXPENSES_AIRCRAFT_REVENUE : EXPENSES_AIRCRAFT_RUN; }
|
||||
bool IsPrimaryVehicle() const { return this->IsNormalAircraft(); }
|
||||
void GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const;
|
||||
int GetDisplaySpeed() const { return this->cur_speed; }
|
||||
|
@@ -37,6 +37,8 @@
|
||||
#include "disaster_vehicle.h"
|
||||
#include "newgrf_airporttiles.h"
|
||||
#include "framerate_type.h"
|
||||
#include "aircraft_cmd.h"
|
||||
#include "vehicle_cmd.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
|
||||
@@ -188,7 +190,7 @@ void GetRotorImage(const Aircraft *v, EngineImageType image_type, VehicleSpriteS
|
||||
|
||||
const Aircraft *w = v->Next()->Next();
|
||||
if (is_custom_sprite(v->spritenum)) {
|
||||
GetCustomRotorSprite(v, false, image_type, result);
|
||||
GetCustomRotorSprite(v, image_type, result);
|
||||
if (result->IsValid()) return;
|
||||
}
|
||||
|
||||
@@ -229,7 +231,7 @@ void DrawAircraftEngine(int left, int right, int preferred_x, int y, EngineID en
|
||||
VehicleSpriteSeq rotor_seq;
|
||||
GetCustomRotorIcon(engine, image_type, &rotor_seq);
|
||||
if (!rotor_seq.IsValid()) rotor_seq.Set(SPR_ROTOR_STOPPED);
|
||||
rotor_seq.Draw(preferred_x, y - ScaleGUITrad(5), PAL_NONE, false);
|
||||
rotor_seq.Draw(preferred_x, y - ScaleSpriteTrad(5), PAL_NONE, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,22 +252,21 @@ void GetAircraftSpriteSize(EngineID engine, uint &width, uint &height, int &xoff
|
||||
Rect rect;
|
||||
seq.GetBounds(&rect);
|
||||
|
||||
width = UnScaleGUI(rect.right - rect.left + 1);
|
||||
height = UnScaleGUI(rect.bottom - rect.top + 1);
|
||||
width = UnScaleGUI(rect.Width());
|
||||
height = UnScaleGUI(rect.Height());
|
||||
xoffs = UnScaleGUI(rect.left);
|
||||
yoffs = UnScaleGUI(rect.top);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an aircraft.
|
||||
* @param tile tile of the depot where aircraft is built.
|
||||
* @param flags type of operation.
|
||||
* @param tile tile of the depot where aircraft is built.
|
||||
* @param e the engine to build.
|
||||
* @param data unused.
|
||||
* @param[out] ret the vehicle that has been built.
|
||||
* @return the cost of this operation or an error.
|
||||
*/
|
||||
CommandCost CmdBuildAircraft(TileIndex tile, DoCommandFlag flags, const Engine *e, uint16 data, Vehicle **ret)
|
||||
CommandCost CmdBuildAircraft(DoCommandFlag flags, TileIndex tile, const Engine *e, Vehicle **ret)
|
||||
{
|
||||
const AircraftVehicleInfo *avi = &e->u.air;
|
||||
const Station *st = Station::GetByTile(tile);
|
||||
@@ -327,8 +328,6 @@ CommandCost CmdBuildAircraft(TileIndex tile, DoCommandFlag flags, const Engine *
|
||||
v->reliability_spd_dec = e->reliability_spd_dec;
|
||||
v->max_age = e->GetLifeLengthInDays();
|
||||
|
||||
_new_vehicle_id = v->index;
|
||||
|
||||
v->pos = GetVehiclePosOnBuild(tile);
|
||||
|
||||
v->state = HANGAR;
|
||||
@@ -1274,7 +1273,7 @@ void HandleMissingAircraftOrders(Aircraft *v)
|
||||
const Station *st = GetTargetAirportIfValid(v);
|
||||
if (st == nullptr) {
|
||||
Backup<CompanyID> cur_company(_current_company, v->owner, FILE_LINE);
|
||||
CommandCost ret = DoCommand(v->tile, v->index, 0, DC_EXEC, CMD_SEND_VEHICLE_TO_DEPOT);
|
||||
CommandCost ret = Command<CMD_SEND_VEHICLE_TO_DEPOT>::Do(DC_EXEC, v->index, DepotCommand::None, {});
|
||||
cur_company.Restore();
|
||||
|
||||
if (ret.Failed()) CrashAirplane(v);
|
||||
@@ -1341,7 +1340,12 @@ static void CrashAirplane(Aircraft *v)
|
||||
AI::NewEvent(v->owner, new ScriptEventVehicleCrashed(v->index, vt, st == nullptr ? ScriptEventVehicleCrashed::CRASH_AIRCRAFT_NO_AIRPORT : ScriptEventVehicleCrashed::CRASH_PLANE_LANDING));
|
||||
Game::NewEvent(new ScriptEventVehicleCrashed(v->index, vt, st == nullptr ? ScriptEventVehicleCrashed::CRASH_AIRCRAFT_NO_AIRPORT : ScriptEventVehicleCrashed::CRASH_PLANE_LANDING));
|
||||
|
||||
AddTileNewsItem(newsitem, NT_ACCIDENT, vt, nullptr, st != nullptr ? st->index : INVALID_STATION);
|
||||
NewsType newstype = NT_ACCIDENT;
|
||||
if (v->owner != _local_company) {
|
||||
newstype = NT_ACCIDENT_OTHER;
|
||||
}
|
||||
|
||||
AddTileNewsItem(newsitem, newstype, vt, nullptr, st != nullptr ? st->index : INVALID_STATION);
|
||||
|
||||
ModifyStationRatingAround(vt, v->owner, -160, 30);
|
||||
if (_settings_client.sound.disaster) SndPlayVehicleFx(SND_12_EXPLOSION, v);
|
||||
@@ -1632,7 +1636,7 @@ static void AircraftEventHandler_HeliTakeOff(Aircraft *v, const AirportFTAClass
|
||||
/* Send the helicopter to a hangar if needed for replacement */
|
||||
if (v->NeedsAutomaticServicing()) {
|
||||
Backup<CompanyID> cur_company(_current_company, v->owner, FILE_LINE);
|
||||
DoCommand(v->tile, v->index | DEPOT_SERVICE | DEPOT_LOCATE_HANGAR, 0, DC_EXEC, CMD_SEND_VEHICLE_TO_DEPOT);
|
||||
Command<CMD_SEND_VEHICLE_TO_DEPOT>::Do(DC_EXEC, v->index, DepotCommand::Service | DepotCommand::LocateHangar, {});
|
||||
cur_company.Restore();
|
||||
}
|
||||
}
|
||||
@@ -1683,7 +1687,7 @@ static void AircraftEventHandler_Landing(Aircraft *v, const AirportFTAClass *apc
|
||||
/* check if the aircraft needs to be replaced or renewed and send it to a hangar if needed */
|
||||
if (v->NeedsAutomaticServicing()) {
|
||||
Backup<CompanyID> cur_company(_current_company, v->owner, FILE_LINE);
|
||||
DoCommand(v->tile, v->index | DEPOT_SERVICE, 0, DC_EXEC, CMD_SEND_VEHICLE_TO_DEPOT);
|
||||
Command<CMD_SEND_VEHICLE_TO_DEPOT>::Do(DC_EXEC, v->index, DepotCommand::Service, {});
|
||||
cur_company.Restore();
|
||||
}
|
||||
}
|
||||
|
19
src/aircraft_cmd.h
Normal file
19
src/aircraft_cmd.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* 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 aircraft_cmd.h Command definitions related to aircraft. */
|
||||
|
||||
#ifndef AIRCRAFT_CMD_H
|
||||
#define AIRCRAFT_CMD_H
|
||||
|
||||
#include "command_type.h"
|
||||
#include "engine_type.h"
|
||||
#include "vehicle_type.h"
|
||||
|
||||
CommandCost CmdBuildAircraft(DoCommandFlag flags, TileIndex tile, const Engine *e, Vehicle **v);
|
||||
|
||||
#endif /* AIRCRAFT_CMD_H */
|
@@ -25,59 +25,58 @@
|
||||
* Draw the details for the given vehicle at the given position
|
||||
*
|
||||
* @param v current vehicle
|
||||
* @param left The left most coordinate to draw
|
||||
* @param right The right most coordinate to draw
|
||||
* @param y The y coordinate
|
||||
* @param r the Rect to draw within
|
||||
*/
|
||||
void DrawAircraftDetails(const Aircraft *v, int left, int right, int y)
|
||||
void DrawAircraftDetails(const Aircraft *v, const Rect &r)
|
||||
{
|
||||
int y_offset = (v->Next()->cargo_cap != 0) ? -(FONT_HEIGHT_NORMAL + 1): 0;
|
||||
Money feeder_share = 0;
|
||||
|
||||
int y = r.top;
|
||||
for (const Aircraft *u = v; u != nullptr; u = u->Next()) {
|
||||
if (u->IsNormalAircraft()) {
|
||||
SetDParam(0, u->engine_type);
|
||||
SetDParam(1, u->build_year);
|
||||
SetDParam(2, u->value);
|
||||
DrawString(left, right, y, STR_VEHICLE_INFO_BUILT_VALUE);
|
||||
DrawString(r.left, r.right, y, STR_VEHICLE_INFO_BUILT_VALUE);
|
||||
y += FONT_HEIGHT_NORMAL;
|
||||
|
||||
SetDParam(0, u->cargo_type);
|
||||
SetDParam(1, u->cargo_cap);
|
||||
SetDParam(2, u->Next()->cargo_type);
|
||||
SetDParam(3, u->Next()->cargo_cap);
|
||||
SetDParam(4, GetCargoSubtypeText(u));
|
||||
DrawString(left, right, y + FONT_HEIGHT_NORMAL, (u->Next()->cargo_cap != 0) ? STR_VEHICLE_INFO_CAPACITY_CAPACITY : STR_VEHICLE_INFO_CAPACITY);
|
||||
DrawString(r.left, r.right, y, (u->Next()->cargo_cap != 0) ? STR_VEHICLE_INFO_CAPACITY_CAPACITY : STR_VEHICLE_INFO_CAPACITY);
|
||||
y += FONT_HEIGHT_NORMAL + WidgetDimensions::scaled.vsep_normal;
|
||||
}
|
||||
|
||||
if (u->cargo_cap != 0) {
|
||||
uint cargo_count = u->cargo.StoredCount();
|
||||
|
||||
y_offset += FONT_HEIGHT_NORMAL + 1;
|
||||
if (cargo_count != 0) {
|
||||
/* Cargo names (fix pluralness) */
|
||||
SetDParam(0, u->cargo_type);
|
||||
SetDParam(1, cargo_count);
|
||||
SetDParam(2, u->cargo.Source());
|
||||
DrawString(left, right, y + 2 * FONT_HEIGHT_NORMAL + 1 + y_offset, STR_VEHICLE_DETAILS_CARGO_FROM);
|
||||
DrawString(r.left, r.right, y, STR_VEHICLE_DETAILS_CARGO_FROM);
|
||||
y += FONT_HEIGHT_NORMAL;
|
||||
feeder_share += u->cargo.FeederShare();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
y += WidgetDimensions::scaled.vsep_normal;
|
||||
SetDParam(0, feeder_share);
|
||||
DrawString(left, right, y + 3 * FONT_HEIGHT_NORMAL + 3 + y_offset, STR_VEHICLE_INFO_FEEDER_CARGO_VALUE);
|
||||
DrawString(r.left, r.right, y, STR_VEHICLE_INFO_FEEDER_CARGO_VALUE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Draws an image of an aircraft
|
||||
* @param v Front vehicle
|
||||
* @param left The minimum horizontal position
|
||||
* @param right The maximum horizontal position
|
||||
* @param y Vertical position to draw at
|
||||
* @param r Rect to draw at
|
||||
* @param selection Selected vehicle to draw a frame around
|
||||
*/
|
||||
void DrawAircraftImage(const Vehicle *v, int left, int right, int y, VehicleID selection, EngineImageType image_type)
|
||||
void DrawAircraftImage(const Vehicle *v, const Rect &r, VehicleID selection, EngineImageType image_type)
|
||||
{
|
||||
bool rtl = _current_text_dir == TD_RTL;
|
||||
|
||||
@@ -87,27 +86,29 @@ void DrawAircraftImage(const Vehicle *v, int left, int right, int y, VehicleID s
|
||||
Rect rect;
|
||||
seq.GetBounds(&rect);
|
||||
|
||||
int width = UnScaleGUI(rect.right - rect.left + 1);
|
||||
int width = UnScaleGUI(rect.Width());
|
||||
int x_offs = UnScaleGUI(rect.left);
|
||||
int x = rtl ? right - width - x_offs : left - x_offs;
|
||||
int x = rtl ? r.right - width - x_offs : r.left - x_offs;
|
||||
/* This magic -1 offset is related to the sprite_y_offsets in build_vehicle_gui.cpp */
|
||||
int y = ScaleSpriteTrad(-1) + CenterBounds(r.top, r.bottom, 0);
|
||||
bool helicopter = v->subtype == AIR_HELICOPTER;
|
||||
|
||||
int y_offs = ScaleGUITrad(10);
|
||||
int heli_offs = 0;
|
||||
|
||||
PaletteID pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v);
|
||||
seq.Draw(x, y + y_offs, pal, (v->vehstatus & VS_CRASHED) != 0);
|
||||
seq.Draw(x, y, pal, (v->vehstatus & VS_CRASHED) != 0);
|
||||
if (helicopter) {
|
||||
const Aircraft *a = Aircraft::From(v);
|
||||
VehicleSpriteSeq rotor_seq;
|
||||
GetCustomRotorSprite(a, true, image_type, &rotor_seq);
|
||||
GetCustomRotorSprite(a, image_type, &rotor_seq);
|
||||
if (!rotor_seq.IsValid()) rotor_seq.Set(SPR_ROTOR_STOPPED);
|
||||
heli_offs = ScaleGUITrad(5);
|
||||
rotor_seq.Draw(x, y + y_offs - heli_offs, PAL_NONE, false);
|
||||
heli_offs = ScaleSpriteTrad(5);
|
||||
rotor_seq.Draw(x, y - heli_offs, PAL_NONE, false);
|
||||
}
|
||||
if (v->index == selection) {
|
||||
x += x_offs;
|
||||
y += UnScaleGUI(rect.top) + y_offs - heli_offs;
|
||||
DrawFrameRect(x - 1, y - 1, x + width + 1, y + UnScaleGUI(rect.bottom - rect.top + 1) + heli_offs + 1, COLOUR_WHITE, FR_BORDERONLY);
|
||||
y += UnScaleGUI(rect.top) - heli_offs;
|
||||
Rect hr = {x, y, x + width - 1, y + UnScaleGUI(rect.Height()) + heli_offs - 1};
|
||||
DrawFrameRect(hr.Expand(WidgetDimensions::scaled.bevel), COLOUR_WHITE, FR_BORDERONLY);
|
||||
}
|
||||
}
|
||||
|
17
src/airport_cmd.h
Normal file
17
src/airport_cmd.h
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* 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 airport_cmd.h Command definitions related to airports. */
|
||||
|
||||
#ifndef AIRPORT_CMD_H
|
||||
#define AIRPORT_CMD_H
|
||||
|
||||
#include "command_type.h"
|
||||
|
||||
CommandCallback CcBuildAirport;
|
||||
|
||||
#endif /* AIRPORT_CMD_H */
|
@@ -8,6 +8,7 @@
|
||||
/** @file airport_gui.cpp The GUI for airports. */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "economy_func.h"
|
||||
#include "window_gui.h"
|
||||
#include "station_gui.h"
|
||||
#include "terraform_gui.h"
|
||||
@@ -26,6 +27,10 @@
|
||||
#include "hotkeys.h"
|
||||
#include "vehicle_func.h"
|
||||
#include "gui.h"
|
||||
#include "command_func.h"
|
||||
#include "airport_cmd.h"
|
||||
#include "station_cmd.h"
|
||||
#include "zoom_func.h"
|
||||
|
||||
#include "widgets/airport_widget.h"
|
||||
|
||||
@@ -40,7 +45,7 @@ static void ShowBuildAirportPicker(Window *parent);
|
||||
|
||||
SpriteID GetCustomAirportSprite(const AirportSpec *as, byte layout);
|
||||
|
||||
void CcBuildAirport(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
|
||||
void CcBuildAirport(Commands cmd, const CommandCost &result, TileIndex tile)
|
||||
{
|
||||
if (result.Failed()) return;
|
||||
|
||||
@@ -55,13 +60,20 @@ void CcBuildAirport(const CommandCost &result, TileIndex tile, uint32 p1, uint32
|
||||
static void PlaceAirport(TileIndex tile)
|
||||
{
|
||||
if (_selected_airport_index == -1) return;
|
||||
uint32 p2 = _ctrl_pressed;
|
||||
SB(p2, 16, 16, INVALID_STATION); // no station to join
|
||||
|
||||
uint32 p1 = AirportClass::Get(_selected_airport_class)->GetSpec(_selected_airport_index)->GetIndex();
|
||||
p1 |= _selected_airport_layout << 8;
|
||||
CommandContainer cmdcont = { tile, p1, p2, CMD_BUILD_AIRPORT | CMD_MSG(STR_ERROR_CAN_T_BUILD_AIRPORT_HERE), CcBuildAirport, "" };
|
||||
ShowSelectStationIfNeeded(cmdcont, TileArea(tile, _thd.size.x / TILE_SIZE, _thd.size.y / TILE_SIZE));
|
||||
byte airport_type = AirportClass::Get(_selected_airport_class)->GetSpec(_selected_airport_index)->GetIndex();
|
||||
byte layout = _selected_airport_layout;
|
||||
bool adjacent = _ctrl_pressed;
|
||||
|
||||
auto proc = [=](bool test, StationID to_join) -> bool {
|
||||
if (test) {
|
||||
return Command<CMD_BUILD_AIRPORT>::Do(CommandFlagsToDCFlags(GetCommandFlags<CMD_BUILD_AIRPORT>()), tile, airport_type, layout, INVALID_STATION, adjacent).Succeeded();
|
||||
} else {
|
||||
return Command<CMD_BUILD_AIRPORT>::Post(STR_ERROR_CAN_T_BUILD_AIRPORT_HERE, CcBuildAirport, tile, airport_type, layout, to_join, adjacent);
|
||||
}
|
||||
};
|
||||
|
||||
ShowSelectStationIfNeeded(TileArea(tile, _thd.size.x / TILE_SIZE, _thd.size.y / TILE_SIZE), proc);
|
||||
}
|
||||
|
||||
/** Airport build toolbar window handler. */
|
||||
@@ -328,10 +340,10 @@ public:
|
||||
const AirportSpec *as = AirportSpec::Get(i);
|
||||
if (!as->enabled) continue;
|
||||
|
||||
size->width = std::max(size->width, GetStringBoundingBox(as->name).width);
|
||||
size->width = std::max(size->width, GetStringBoundingBox(as->name).width + padding.width);
|
||||
}
|
||||
|
||||
this->line_height = FONT_HEIGHT_NORMAL + WD_MATRIX_TOP + WD_MATRIX_BOTTOM;
|
||||
this->line_height = FONT_HEIGHT_NORMAL + padding.height;
|
||||
size->height = 5 * this->line_height;
|
||||
break;
|
||||
}
|
||||
@@ -344,8 +356,8 @@ public:
|
||||
SpriteID sprite = GetCustomAirportSprite(as, layout);
|
||||
if (sprite != 0) {
|
||||
Dimension d = GetSpriteSize(sprite);
|
||||
d.width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
|
||||
d.height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
|
||||
d.width += WidgetDimensions::scaled.framerect.Horizontal();
|
||||
d.height += WidgetDimensions::scaled.framerect.Vertical();
|
||||
*size = maxdim(d, *size);
|
||||
}
|
||||
}
|
||||
@@ -376,15 +388,17 @@ public:
|
||||
{
|
||||
switch (widget) {
|
||||
case WID_AP_AIRPORT_LIST: {
|
||||
int y = r.top;
|
||||
Rect row = r.WithHeight(this->line_height).Shrink(WidgetDimensions::scaled.bevel);
|
||||
Rect text = r.WithHeight(this->line_height).Shrink(WidgetDimensions::scaled.matrix);
|
||||
AirportClass *apclass = AirportClass::Get(_selected_airport_class);
|
||||
for (uint i = this->vscroll->GetPosition(); this->vscroll->IsVisible(i) && i < apclass->GetSpecCount(); i++) {
|
||||
const AirportSpec *as = apclass->GetSpec(i);
|
||||
if (!as->IsAvailable()) {
|
||||
GfxFillRect(r.left + 1, y + 1, r.right - 1, y + this->line_height - 2, PC_BLACK, FILLRECT_CHECKER);
|
||||
GfxFillRect(row, PC_BLACK, FILLRECT_CHECKER);
|
||||
}
|
||||
DrawString(r.left + WD_MATRIX_LEFT, r.right - WD_MATRIX_RIGHT, y + WD_MATRIX_TOP, as->name, ((int)i == _selected_airport_index) ? TC_WHITE : TC_BLACK);
|
||||
y += this->line_height;
|
||||
DrawString(text, as->name, ((int)i == _selected_airport_index) ? TC_WHITE : TC_BLACK);
|
||||
row = row.Translate(0, this->line_height);
|
||||
text = text.Translate(0, this->line_height);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -392,7 +406,7 @@ public:
|
||||
case WID_AP_AIRPORT_SPRITE:
|
||||
if (this->preview_sprite != 0) {
|
||||
Dimension d = GetSpriteSize(this->preview_sprite);
|
||||
DrawSprite(this->preview_sprite, COMPANY_SPRITE_COLOUR(_local_company), (r.left + r.right - d.width) / 2, (r.top + r.bottom - d.height) / 2);
|
||||
DrawSprite(this->preview_sprite, COMPANY_SPRITE_COLOUR(_local_company), CenterBounds(r.left, r.right, d.width), CenterBounds(r.top, r.bottom, d.height));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -413,11 +427,8 @@ public:
|
||||
{
|
||||
this->DrawWidgets();
|
||||
|
||||
uint16 top = this->GetWidget<NWidgetBase>(WID_AP_BTN_DOHILIGHT)->pos_y + this->GetWidget<NWidgetBase>(WID_AP_BTN_DOHILIGHT)->current_y + WD_PAR_VSEP_NORMAL;
|
||||
NWidgetBase *panel_nwi = this->GetWidget<NWidgetBase>(WID_AP_BOTTOMPANEL);
|
||||
|
||||
int right = panel_nwi->pos_x + panel_nwi->current_x;
|
||||
int bottom = panel_nwi->pos_y + panel_nwi->current_y;
|
||||
Rect r = this->GetWidget<NWidgetBase>(WID_AP_ACCEPTANCE)->GetCurrentRect();
|
||||
int top = r.top + WidgetDimensions::scaled.vsep_normal;
|
||||
|
||||
if (_selected_airport_index != -1) {
|
||||
const AirportSpec *as = AirportClass::Get(_selected_airport_class)->GetSpec(_selected_airport_index);
|
||||
@@ -427,20 +438,27 @@ public:
|
||||
if (_settings_game.economy.station_noise_level) {
|
||||
/* show the noise of the selected airport */
|
||||
SetDParam(0, as->noise_level);
|
||||
DrawString(panel_nwi->pos_x + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, top, STR_STATION_BUILD_NOISE);
|
||||
top += FONT_HEIGHT_NORMAL + WD_PAR_VSEP_NORMAL;
|
||||
DrawString(r.left, r.right, top, STR_STATION_BUILD_NOISE);
|
||||
top += FONT_HEIGHT_NORMAL + WidgetDimensions::scaled.vsep_normal;
|
||||
}
|
||||
|
||||
if (_settings_game.economy.infrastructure_maintenance) {
|
||||
Money monthly = _price[PR_INFRASTRUCTURE_AIRPORT] * as->maintenance_cost >> 3;
|
||||
SetDParam(0, monthly * 12);
|
||||
DrawString(r.left, r.right, top, STR_STATION_BUILD_INFRASTRUCTURE_COST);
|
||||
top += FONT_HEIGHT_NORMAL + WidgetDimensions::scaled.vsep_normal;
|
||||
}
|
||||
|
||||
/* strings such as 'Size' and 'Coverage Area' */
|
||||
top = DrawStationCoverageAreaText(panel_nwi->pos_x + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, top, SCT_ALL, rad, false) + WD_PAR_VSEP_NORMAL;
|
||||
top = DrawStationCoverageAreaText(panel_nwi->pos_x + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, top, SCT_ALL, rad, true) + WD_PAR_VSEP_NORMAL;
|
||||
top = DrawStationCoverageAreaText(r.left, r.right, top, SCT_ALL, rad, false) + WidgetDimensions::scaled.vsep_normal;
|
||||
top = DrawStationCoverageAreaText(r.left, r.right, top, SCT_ALL, rad, true) + WidgetDimensions::scaled.vsep_normal;
|
||||
}
|
||||
|
||||
/* Resize background if the window is too small.
|
||||
* Never make the window smaller to avoid oscillating if the size change affects the acceptance.
|
||||
* (This is the case, if making the window bigger moves the mouse into the window.) */
|
||||
if (top > bottom) {
|
||||
ResizeWindow(this, 0, top - bottom, false);
|
||||
if (top > r.bottom) {
|
||||
ResizeWindow(this, 0, top - r.bottom, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -586,8 +604,8 @@ static const NWidgetPart _nested_build_airport_widgets[] = {
|
||||
NWidget(WWT_EMPTY, COLOUR_DARK_GREEN, WID_AP_EXTRA_TEXT), SetFill(1, 0), SetMinimalSize(150, 0),
|
||||
EndContainer(),
|
||||
/* Bottom panel. */
|
||||
NWidget(WWT_PANEL, COLOUR_DARK_GREEN, WID_AP_BOTTOMPANEL), SetPIP(2, 2, 2),
|
||||
NWidget(WWT_LABEL, COLOUR_DARK_GREEN), SetDataTip(STR_STATION_BUILD_COVERAGE_AREA_TITLE, STR_NULL), SetFill(1, 0),
|
||||
NWidget(WWT_PANEL, COLOUR_DARK_GREEN, WID_AP_BOTTOMPANEL),
|
||||
NWidget(WWT_LABEL, COLOUR_DARK_GREEN), SetPadding(WidgetDimensions::unscaled.framerect), SetDataTip(STR_STATION_BUILD_COVERAGE_AREA_TITLE, STR_NULL), SetFill(1, 0),
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(NWID_SPACER), SetMinimalSize(14, 0), SetFill(1, 0),
|
||||
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
|
||||
@@ -598,7 +616,7 @@ static const NWidgetPart _nested_build_airport_widgets[] = {
|
||||
EndContainer(),
|
||||
NWidget(NWID_SPACER), SetMinimalSize(14, 0), SetFill(1, 0),
|
||||
EndContainer(),
|
||||
NWidget(NWID_SPACER), SetMinimalSize(0, 10), SetResize(0, 1), SetFill(1, 0),
|
||||
NWidget(WWT_EMPTY, COLOUR_DARK_GREEN, WID_AP_ACCEPTANCE), SetPadding(WidgetDimensions::unscaled.framerect), SetResize(0, 1), SetFill(1, 0),
|
||||
EndContainer(),
|
||||
};
|
||||
|
||||
|
@@ -22,6 +22,11 @@
|
||||
#include "ai/ai.hpp"
|
||||
#include "news_func.h"
|
||||
#include "strings_func.h"
|
||||
#include "autoreplace_cmd.h"
|
||||
#include "group_cmd.h"
|
||||
#include "order_cmd.h"
|
||||
#include "train_cmd.h"
|
||||
#include "vehicle_cmd.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
|
||||
@@ -206,7 +211,7 @@ static int GetIncompatibleRefitOrderIdForAutoreplace(const Vehicle *v, EngineID
|
||||
const Order *o;
|
||||
const Vehicle *u = (v->type == VEH_TRAIN) ? v->First() : v;
|
||||
|
||||
const OrderList *orders = u->orders.list;
|
||||
const OrderList *orders = u->orders;
|
||||
if (orders == nullptr) return -1;
|
||||
for (VehicleOrderID i = 0; i < orders->GetNumOrders(); i++) {
|
||||
o = orders->GetOrderAt(i);
|
||||
@@ -340,23 +345,24 @@ static CommandCost BuildReplacementVehicle(Vehicle *old_veh, Vehicle **new_vehic
|
||||
}
|
||||
|
||||
/* Build the new vehicle */
|
||||
cost = DoCommand(old_veh->tile, e | (CT_INVALID << 24), 0, DC_EXEC | DC_AUTOREPLACE, GetCmdBuildVeh(old_veh));
|
||||
VehicleID new_veh_id;
|
||||
std::tie(cost, new_veh_id, std::ignore, std::ignore) = Command<CMD_BUILD_VEHICLE>::Do(DC_EXEC | DC_AUTOREPLACE, old_veh->tile, e, true, CT_INVALID, INVALID_CLIENT_ID);
|
||||
if (cost.Failed()) return cost;
|
||||
|
||||
Vehicle *new_veh = Vehicle::Get(_new_vehicle_id);
|
||||
Vehicle *new_veh = Vehicle::Get(new_veh_id);
|
||||
*new_vehicle = new_veh;
|
||||
|
||||
/* Refit the vehicle if needed */
|
||||
if (refit_cargo != CT_NO_REFIT) {
|
||||
byte subtype = GetBestFittingSubType(old_veh, new_veh, refit_cargo);
|
||||
|
||||
cost.AddCost(DoCommand(0, new_veh->index, refit_cargo | (subtype << 8), DC_EXEC, GetCmdRefitVeh(new_veh)));
|
||||
cost.AddCost(std::get<0>(Command<CMD_REFIT_VEHICLE>::Do(DC_EXEC, new_veh->index, refit_cargo, subtype, false, false, 0)));
|
||||
assert(cost.Succeeded()); // This should be ensured by GetNewCargoTypeForReplace()
|
||||
}
|
||||
|
||||
/* Try to reverse the vehicle, but do not care if it fails as the new type might not be reversible */
|
||||
if (new_veh->type == VEH_TRAIN && HasBit(Train::From(old_veh)->flags, VRF_REVERSE_DIRECTION)) {
|
||||
DoCommand(0, new_veh->index, true, DC_EXEC, CMD_REVERSE_TRAIN_DIRECTION);
|
||||
Command<CMD_REVERSE_TRAIN_DIRECTION>::Do(DC_EXEC, new_veh->index, true);
|
||||
}
|
||||
|
||||
return cost;
|
||||
@@ -368,9 +374,9 @@ static CommandCost BuildReplacementVehicle(Vehicle *old_veh, Vehicle **new_vehic
|
||||
* @param evaluate_callback shall the start/stop callback be evaluated?
|
||||
* @return success or error
|
||||
*/
|
||||
static inline CommandCost CmdStartStopVehicle(const Vehicle *v, bool evaluate_callback)
|
||||
static inline CommandCost DoCmdStartStopVehicle(const Vehicle *v, bool evaluate_callback)
|
||||
{
|
||||
return DoCommand(0, v->index, evaluate_callback ? 1 : 0, DC_EXEC | DC_AUTOREPLACE, CMD_START_STOP_VEHICLE);
|
||||
return Command<CMD_START_STOP_VEHICLE>::Do(DC_EXEC | DC_AUTOREPLACE, v->index, evaluate_callback);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -383,7 +389,7 @@ static inline CommandCost CmdStartStopVehicle(const Vehicle *v, bool evaluate_ca
|
||||
*/
|
||||
static inline CommandCost CmdMoveVehicle(const Vehicle *v, const Vehicle *after, DoCommandFlag flags, bool whole_chain)
|
||||
{
|
||||
return DoCommand(0, v->index | (whole_chain ? 1 : 0) << 20, after != nullptr ? after->index : INVALID_VEHICLE, flags | DC_NO_CARGO_CAP_CHECK, CMD_MOVE_RAIL_VEHICLE);
|
||||
return Command<CMD_MOVE_RAIL_VEHICLE>::Do(flags | DC_NO_CARGO_CAP_CHECK, v->index, after != nullptr ? after->index : INVALID_VEHICLE, whole_chain);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -397,19 +403,19 @@ static CommandCost CopyHeadSpecificThings(Vehicle *old_head, Vehicle *new_head,
|
||||
CommandCost cost = CommandCost();
|
||||
|
||||
/* Share orders */
|
||||
if (cost.Succeeded() && old_head != new_head) cost.AddCost(DoCommand(0, new_head->index | CO_SHARE << 30, old_head->index, DC_EXEC, CMD_CLONE_ORDER));
|
||||
if (cost.Succeeded() && old_head != new_head) cost.AddCost(Command<CMD_CLONE_ORDER>::Do(DC_EXEC, CO_SHARE, new_head->index, old_head->index));
|
||||
|
||||
/* Copy group membership */
|
||||
if (cost.Succeeded() && old_head != new_head) cost.AddCost(DoCommand(0, old_head->group_id, new_head->index, DC_EXEC, CMD_ADD_VEHICLE_GROUP));
|
||||
if (cost.Succeeded() && old_head != new_head) cost.AddCost(std::get<0>(Command<CMD_ADD_VEHICLE_GROUP>::Do(DC_EXEC, old_head->group_id, new_head->index, false)));
|
||||
|
||||
/* Perform start/stop check whether the new vehicle suits newgrf restrictions etc. */
|
||||
if (cost.Succeeded()) {
|
||||
/* Start the vehicle, might be denied by certain things */
|
||||
assert((new_head->vehstatus & VS_STOPPED) != 0);
|
||||
cost.AddCost(CmdStartStopVehicle(new_head, true));
|
||||
cost.AddCost(DoCmdStartStopVehicle(new_head, true));
|
||||
|
||||
/* Stop the vehicle again, but do not care about evil newgrfs allowing starting but not stopping :p */
|
||||
if (cost.Succeeded()) cost.AddCost(CmdStartStopVehicle(new_head, false));
|
||||
if (cost.Succeeded()) cost.AddCost(DoCmdStartStopVehicle(new_head, false));
|
||||
}
|
||||
|
||||
/* Last do those things which do never fail (resp. we do not care about), but which are not undo-able */
|
||||
@@ -466,11 +472,11 @@ static CommandCost ReplaceFreeUnit(Vehicle **single_unit, DoCommandFlag flags, b
|
||||
}
|
||||
|
||||
/* Sell the old vehicle */
|
||||
cost.AddCost(DoCommand(0, old_v->index, 0, flags, GetCmdSellVeh(old_v)));
|
||||
cost.AddCost(Command<CMD_SELL_VEHICLE>::Do(flags, old_v->index, false, false, INVALID_CLIENT_ID));
|
||||
|
||||
/* If we are not in DC_EXEC undo everything */
|
||||
if ((flags & DC_EXEC) == 0) {
|
||||
DoCommand(0, new_v->index, 0, DC_EXEC, GetCmdSellVeh(new_v));
|
||||
Command<CMD_SELL_VEHICLE>::Do(DC_EXEC, new_v->index, false, false, INVALID_CLIENT_ID);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -597,7 +603,7 @@ static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlag flags, bool wagon
|
||||
assert(RailVehInfo(wagon->engine_type)->railveh_type == RAILVEH_WAGON);
|
||||
|
||||
/* Sell wagon */
|
||||
[[maybe_unused]] CommandCost ret = DoCommand(0, wagon->index, 0, DC_EXEC, GetCmdSellVeh(wagon));
|
||||
[[maybe_unused]] CommandCost ret = Command<CMD_SELL_VEHICLE>::Do(DC_EXEC, wagon->index, false, false, INVALID_CLIENT_ID);
|
||||
assert(ret.Succeeded());
|
||||
new_vehs[i] = nullptr;
|
||||
|
||||
@@ -629,7 +635,7 @@ static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlag flags, bool wagon
|
||||
/* Sell the vehicle.
|
||||
* Note: This might temporarily construct new trains, so use DC_AUTOREPLACE to prevent
|
||||
* it from failing due to engine limits. */
|
||||
cost.AddCost(DoCommand(0, w->index, 0, flags | DC_AUTOREPLACE, GetCmdSellVeh(w)));
|
||||
cost.AddCost(Command<CMD_SELL_VEHICLE>::Do(flags | DC_AUTOREPLACE, w->index, false, false, INVALID_CLIENT_ID));
|
||||
if ((flags & DC_EXEC) != 0) {
|
||||
old_vehs[i] = nullptr;
|
||||
if (i == 0) old_head = nullptr;
|
||||
@@ -660,7 +666,7 @@ static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlag flags, bool wagon
|
||||
if ((flags & DC_EXEC) == 0) {
|
||||
for (int i = num_units - 1; i >= 0; i--) {
|
||||
if (new_vehs[i] != nullptr) {
|
||||
DoCommand(0, new_vehs[i]->index, 0, DC_EXEC, GetCmdSellVeh(new_vehs[i]));
|
||||
Command<CMD_SELL_VEHICLE>::Do(DC_EXEC, new_vehs[i]->index, false, false, INVALID_CLIENT_ID);
|
||||
new_vehs[i] = nullptr;
|
||||
}
|
||||
}
|
||||
@@ -691,12 +697,12 @@ static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlag flags, bool wagon
|
||||
}
|
||||
|
||||
/* Sell the old vehicle */
|
||||
cost.AddCost(DoCommand(0, old_head->index, 0, flags, GetCmdSellVeh(old_head)));
|
||||
cost.AddCost(Command<CMD_SELL_VEHICLE>::Do(flags, old_head->index, false, false, INVALID_CLIENT_ID));
|
||||
}
|
||||
|
||||
/* If we are not in DC_EXEC undo everything */
|
||||
if ((flags & DC_EXEC) == 0) {
|
||||
DoCommand(0, new_head->index, 0, DC_EXEC, GetCmdSellVeh(new_head));
|
||||
Command<CMD_SELL_VEHICLE>::Do(DC_EXEC, new_head->index, false, false, INVALID_CLIENT_ID);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -707,22 +713,18 @@ static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlag flags, bool wagon
|
||||
/**
|
||||
* Autoreplaces a vehicle
|
||||
* Trains are replaced as a whole chain, free wagons in depot are replaced on their own
|
||||
* @param tile not used
|
||||
* @param flags type of operation
|
||||
* @param p1 Index of vehicle
|
||||
* @param p2 not used
|
||||
* @param text unused
|
||||
* @param veh_id Index of vehicle
|
||||
* @return the cost of this operation or an error
|
||||
*/
|
||||
CommandCost CmdAutoreplaceVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text)
|
||||
CommandCost CmdAutoreplaceVehicle(DoCommandFlag flags, VehicleID veh_id)
|
||||
{
|
||||
Vehicle *v = Vehicle::GetIfValid(p1);
|
||||
Vehicle *v = Vehicle::GetIfValid(veh_id);
|
||||
if (v == nullptr) return CMD_ERROR;
|
||||
|
||||
CommandCost ret = CheckOwnership(v->owner);
|
||||
if (ret.Failed()) return ret;
|
||||
|
||||
if (!v->IsChainInDepot()) return CMD_ERROR;
|
||||
if (v->vehstatus & VS_CRASHED) return CMD_ERROR;
|
||||
|
||||
bool free_wagon = false;
|
||||
@@ -734,6 +736,7 @@ CommandCost CmdAutoreplaceVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1
|
||||
} else {
|
||||
if (!v->IsPrimaryVehicle()) return CMD_ERROR;
|
||||
}
|
||||
if (!v->IsChainInDepot()) return CMD_ERROR;
|
||||
|
||||
const Company *c = Company::Get(_current_company);
|
||||
bool wagon_removal = c->settings.renew_keep_length;
|
||||
@@ -759,7 +762,7 @@ CommandCost CmdAutoreplaceVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1
|
||||
bool was_stopped = free_wagon || ((v->vehstatus & VS_STOPPED) != 0);
|
||||
|
||||
/* Stop the vehicle */
|
||||
if (!was_stopped) cost.AddCost(CmdStartStopVehicle(v, true));
|
||||
if (!was_stopped) cost.AddCost(DoCmdStartStopVehicle(v, true));
|
||||
if (cost.Failed()) return cost;
|
||||
|
||||
assert(free_wagon || v->IsStoppedInDepot());
|
||||
@@ -787,7 +790,7 @@ CommandCost CmdAutoreplaceVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1
|
||||
}
|
||||
|
||||
/* Restart the vehicle */
|
||||
if (!was_stopped) cost.AddCost(CmdStartStopVehicle(v, false));
|
||||
if (!was_stopped) cost.AddCost(DoCmdStartStopVehicle(v, false));
|
||||
}
|
||||
|
||||
if (cost.Succeeded() && nothing_to_do) cost = CommandCost(STR_ERROR_AUTOREPLACE_NOTHING_TO_DO);
|
||||
@@ -796,35 +799,29 @@ CommandCost CmdAutoreplaceVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1
|
||||
|
||||
/**
|
||||
* Change engine renewal parameters
|
||||
* @param tile unused
|
||||
* @param flags operation to perform
|
||||
* @param p1 packed data
|
||||
* - bit 0 = replace when engine gets old?
|
||||
* - bits 16-31 = engine group
|
||||
* @param p2 packed data
|
||||
* - bits 0-15 = old engine type
|
||||
* - bits 16-31 = new engine type
|
||||
* @param text unused
|
||||
* @param id_g engine group
|
||||
* @param old_engine_type old engine type
|
||||
* @param new_engine_type new engine type
|
||||
* @param when_old replace when engine gets old?
|
||||
* @return the cost of this operation or an error
|
||||
*/
|
||||
CommandCost CmdSetAutoReplace(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text)
|
||||
CommandCost CmdSetAutoReplace(DoCommandFlag flags, GroupID id_g, EngineID old_engine_type, EngineID new_engine_type, bool when_old)
|
||||
{
|
||||
Company *c = Company::GetIfValid(_current_company);
|
||||
if (c == nullptr) return CMD_ERROR;
|
||||
|
||||
EngineID old_engine_type = GB(p2, 0, 16);
|
||||
EngineID new_engine_type = GB(p2, 16, 16);
|
||||
GroupID id_g = GB(p1, 16, 16);
|
||||
CommandCost cost;
|
||||
|
||||
if (Group::IsValidID(id_g) ? Group::Get(id_g)->owner != _current_company : !IsAllGroupID(id_g) && !IsDefaultGroupID(id_g)) return CMD_ERROR;
|
||||
if (!Engine::IsValidID(old_engine_type)) return CMD_ERROR;
|
||||
if (Group::IsValidID(id_g) && Group::Get(id_g)->vehicle_type != Engine::Get(old_engine_type)->type) return CMD_ERROR;
|
||||
|
||||
if (new_engine_type != INVALID_ENGINE) {
|
||||
if (!Engine::IsValidID(new_engine_type)) return CMD_ERROR;
|
||||
if (!CheckAutoreplaceValidity(old_engine_type, new_engine_type, _current_company)) return CMD_ERROR;
|
||||
|
||||
cost = AddEngineReplacementForCompany(c, old_engine_type, new_engine_type, id_g, HasBit(p1, 0), flags);
|
||||
cost = AddEngineReplacementForCompany(c, old_engine_type, new_engine_type, id_g, when_old, flags);
|
||||
} else {
|
||||
cost = RemoveEngineReplacementForCompany(c, old_engine_type, id_g, flags);
|
||||
}
|
||||
|
24
src/autoreplace_cmd.h
Normal file
24
src/autoreplace_cmd.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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 autoreplace_cmd.h Command definitions related to autoreplace. */
|
||||
|
||||
#ifndef AUTOREPLACE_CMD_H
|
||||
#define AUTOREPLACE_CMD_H
|
||||
|
||||
#include "command_type.h"
|
||||
#include "vehicle_type.h"
|
||||
#include "engine_type.h"
|
||||
#include "group_type.h"
|
||||
|
||||
CommandCost CmdAutoreplaceVehicle(DoCommandFlag flags, VehicleID veh_id);
|
||||
CommandCost CmdSetAutoReplace(DoCommandFlag flags, GroupID id_g, EngineID old_engine_type, EngineID new_engine_type, bool when_old);
|
||||
|
||||
DEF_CMD_TRAIT(CMD_AUTOREPLACE_VEHICLE, CmdAutoreplaceVehicle, 0, CMDT_VEHICLE_MANAGEMENT)
|
||||
DEF_CMD_TRAIT(CMD_SET_AUTOREPLACE, CmdSetAutoReplace, 0, CMDT_VEHICLE_MANAGEMENT)
|
||||
|
||||
#endif /* AUTOREPLACE_CMD_H */
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user