mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2026-07-16 23:59:41 +00:00
Compare commits
1598 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 001b12b742 | |||
| 54bc10515f | |||
| a893485be1 | |||
| 519c4161d5 | |||
| 1ab7238c15 | |||
| 0b89bbaa3c | |||
| 1b2b0d5b79 | |||
| cdb81c660c | |||
| 9fb4b2ef55 | |||
| 70e2e79c45 | |||
| cb5107f97f | |||
| d3ce687daf | |||
| 1c22cea02d | |||
| 21d9e2c934 | |||
| 90ca24f7b6 | |||
| a5612ab10a | |||
| 54b7fb0203 | |||
| 166c1badc9 | |||
| 143dd26ef5 | |||
| 391c34c12b | |||
| f48fdba12c | |||
| 7daaf1f100 | |||
| effbba74f5 | |||
| 653000bdd6 | |||
| 4554daa130 | |||
| 3bd76dad5b | |||
| b18e4d1a8d | |||
| ff52fc8267 | |||
| 2bc9764fcf | |||
| 7dc5c5d1b1 | |||
| fea5965679 | |||
| 6cd410afbb | |||
| 3fd39ec630 | |||
| 89587c1d51 | |||
| 2151550631 | |||
| 14996be3ef | |||
| 5501f25084 | |||
| 0ddf93956e | |||
| 6f06930ee3 | |||
| 788286e9d3 | |||
| 4c0c553a8f | |||
| 220e5be863 | |||
| 32bb69ef1c | |||
| 0269361b28 | |||
| 2aa94201dc | |||
| d99dddc704 | |||
| 2bf3d14dfc | |||
| fbb794d450 | |||
| 5174d3adfe | |||
| 3a4bedaad6 | |||
| 950dcd47eb | |||
| 0ff942f560 | |||
| d19438f858 | |||
| 31f8f6a7b5 | |||
| 033995ec6e | |||
| 56e7e4cf25 | |||
| c626555f68 | |||
| 921cc4e94a | |||
| f3b217db9d | |||
| a72c06d845 | |||
| 729066e407 | |||
| aa4f2d2db2 | |||
| 268968a8b4 | |||
| 6cdb9580e2 | |||
| 5e6923e936 | |||
| fe223eccf4 | |||
| ab954a934a | |||
| 4ad80ae872 | |||
| edd8c87502 | |||
| 2b96754673 | |||
| 5f6de3e47c | |||
| 74671bd2c9 | |||
| 8d392cf5c7 | |||
| 0e08878a68 | |||
| f2bc27718a | |||
| 3ad11e0ad4 | |||
| b90e9d49ca | |||
| 0618a6d0df | |||
| 81474c2623 | |||
| 18bc5ae77e | |||
| adf929fef5 | |||
| 61ca460457 | |||
| 69a09c6f77 | |||
| d17476b058 | |||
| 203a84dd0b | |||
| 42eb63a7de | |||
| df21566f9f | |||
| c85f049f52 | |||
| b12c6bac57 | |||
| effca9f6ec | |||
| 95c040b723 | |||
| b2efecd9b4 | |||
| 0699c54c45 | |||
| 24943a4759 | |||
| 9b8aa4c101 | |||
| ad6b37a423 | |||
| a1e27b1606 | |||
| b22ebeda61 | |||
| 6eb094c726 | |||
| 2ab5eee78b | |||
| d26052c7df | |||
| 3b3a2b890f | |||
| 5a35c8cc4e | |||
| ece616ff22 | |||
| 4e1fbe54b2 | |||
| 5a69201451 | |||
| 63784c5b5a | |||
| 8f6b3154e5 | |||
| ab0a6f2e73 | |||
| 57dbe50597 | |||
| 2cc10f829f | |||
| d102d0c26d | |||
| 7a012a3465 | |||
| 639b6e780f | |||
| cf5370eb22 | |||
| 7b68c6cefe | |||
| e32aa54a41 | |||
| cdb896b790 | |||
| 13f07582b0 | |||
| d7e6f468e9 | |||
| 6ff8340619 | |||
| 0ec5775ded | |||
| 974c19a51c | |||
| 6f9c6effaf | |||
| 27dbc4ba09 | |||
| a1143a53f0 | |||
| 11dc0e1777 | |||
| 762b5f7a75 | |||
| 5d192d7150 | |||
| facd3d1af1 | |||
| 176c155193 | |||
| 566df8dc65 | |||
| 6ceeedfd3c | |||
| 591217da4a | |||
| 403845c9ca | |||
| 1265478a98 | |||
| c731091941 | |||
| c8f07a2dd9 | |||
| 1b312083fc | |||
| 29347840c2 | |||
| cc65bd1702 | |||
| 0f08e83553 | |||
| 51c56287f0 | |||
| 972448d5ae | |||
| 878cebaa70 | |||
| 0fa9c23225 | |||
| 6edd6a850a | |||
| 7a787a672d | |||
| 31dfae8aa2 | |||
| 19dc0a8561 | |||
| bb22f72ad9 | |||
| 3c3507c822 | |||
| 4eeac3ea75 | |||
| 174030a15f | |||
| 2e58ce2fd9 | |||
| d5bcf62e5c | |||
| 3e470708a6 | |||
| 5572a92c58 | |||
| ecc0cd37f4 | |||
| cada1e24b5 | |||
| 3b9931fcba | |||
| 3a4c1ce351 | |||
| febae668fe | |||
| 7f4b636559 | |||
| 860242b811 | |||
| 02f5818912 | |||
| 277d9d237b | |||
| e00785a855 | |||
| 8724ba8e01 | |||
| 4601cd1366 | |||
| 2397ff86e6 | |||
| 90cc36f7e2 | |||
| f5d9cb58eb | |||
| b02dde1982 | |||
| a714444a8e | |||
| 6409e6efaf | |||
| e82f724e9a | |||
| 9876fb54bd | |||
| 4dbf5b37cc | |||
| 41f38775a1 | |||
| 6f15593ce2 | |||
| 91d44ef577 | |||
| 5a65140cb4 | |||
| 13969f5940 | |||
| 4af271c494 | |||
| 5d02a2c295 | |||
| 7ef681eaed | |||
| a9c52454c8 | |||
| 5e4961d902 | |||
| da3621c180 | |||
| 9c3813e213 | |||
| a3293be124 | |||
| 68138d6a31 | |||
| 081ff24282 | |||
| 5a78c32a23 | |||
| 4bd95d756e | |||
| 7f941818a8 | |||
| 5109df6f55 | |||
| 93c61b9e8f | |||
| 13fc3271f4 | |||
| 92fe22382a | |||
| dfe6c34bf1 | |||
| 22d36985cd | |||
| 4aa7cf8e9f | |||
| 8153a56aa4 | |||
| 42eae13270 | |||
| ead34df653 | |||
| 6c825df8f7 | |||
| 00c819c0d5 | |||
| b2c7543204 | |||
| 2ac7077571 | |||
| 31381af8a0 | |||
| fc411d3675 | |||
| f00d0d8ea8 | |||
| 83d62b1aa2 | |||
| 587106a869 | |||
| 5d937e4a23 | |||
| 64533d53dc | |||
| f35b59aded | |||
| 3bfda758db | |||
| 0f830b79e1 | |||
| edd301d364 | |||
| 10e4c9bfab | |||
| ad7f157ac4 | |||
| 2d0698633d | |||
| 8d09a1ae87 | |||
| bfe31c32c0 | |||
| 71b0622cec | |||
| d35f965c47 | |||
| f053bbb4f4 | |||
| 65ed56e970 | |||
| 018f6f6f85 | |||
| 1379dc298e | |||
| 5a527daac9 | |||
| 1d0e0b22e4 | |||
| 2857b71214 | |||
| 35ff9d850c | |||
| 043ac73b19 | |||
| ada6f0be8b | |||
| 3d6d4b1bfd | |||
| 725060b353 | |||
| c6f56edcff | |||
| 66989faab6 | |||
| 16a64d7000 | |||
| 7ff930af04 | |||
| 95541fa52d | |||
| d97ff67129 | |||
| e7937998d6 | |||
| 508738f836 | |||
| c68cfdeeca | |||
| 3a8665f796 | |||
| eb96f89960 | |||
| 9d2406729e | |||
| 6ec727d15c | |||
| 6bca4c041a | |||
| 4573a9f872 | |||
| e4cb9dbb77 | |||
| 51eeea477b | |||
| f42d17c6b3 | |||
| bba102e624 | |||
| ae359d0d02 | |||
| 9e53b86dca | |||
| a494f96cfe | |||
| c4133f2535 | |||
| 31c36d3dd4 | |||
| aafb136cd0 | |||
| 04dc6441aa | |||
| 60bb2374d6 | |||
| 8acc24f000 | |||
| 0659f34aa6 | |||
| aba225c88d | |||
| e01338fcf5 | |||
| a0f9a7597c | |||
| bf1fd0379c | |||
| 0c5d61bd56 | |||
| e416fe8066 | |||
| 45425bedca | |||
| 8efcba81d7 | |||
| 742513d708 | |||
| cef2e24ec4 | |||
| f89984642e | |||
| d4b3469e2f | |||
| 7340aa5b8e | |||
| 67d2ada020 | |||
| b909a1f775 | |||
| 3855c7f92f | |||
| c4f1d4dfed | |||
| 5ce3537ef0 | |||
| 7da3b3b92d | |||
| 05dbeaeba4 | |||
| 339785dad7 | |||
| 7fceb7ea86 | |||
| 44f3702919 | |||
| e94a921c2b | |||
| 9832a691fe | |||
| 6d75cce924 | |||
| 1eab014524 | |||
| 0c325e10da | |||
| 9cde836d08 | |||
| 6e142d523e | |||
| 75bc6cd7e7 | |||
| b721a08ef2 | |||
| 602fda327f | |||
| 62b8355af0 | |||
| 16a3bc35c0 | |||
| 9791068844 | |||
| 2423eaac2c | |||
| 5972d84c82 | |||
| 83637d164e | |||
| f86318407c | |||
| 1536c3ae5a | |||
| 9b1e6e6d3e | |||
| fbb11ea366 | |||
| 88ef277dc3 | |||
| ccd6a0614f | |||
| bfc1d43a27 | |||
| 71dba5f511 | |||
| 22c4924040 | |||
| 04087c9ac9 | |||
| b19553574e | |||
| fbc2eacade | |||
| 087d78d465 | |||
| 1990c139d5 | |||
| f179dc7acc | |||
| f41be0b25a | |||
| 6bd06dbc33 | |||
| fe8313159a | |||
| d2ae7dd186 | |||
| d6b8375504 | |||
| b3b6eafe1d | |||
| acb1fb2e30 | |||
| e12bb5504a | |||
| e5036891f6 | |||
| ad579912f4 | |||
| cb084f59c2 | |||
| f1f70501db | |||
| 195e515de1 | |||
| dad3d12406 | |||
| 42cd07a2e2 | |||
| 61e0dd439f | |||
| f91f8d9559 | |||
| cf43c7a0e6 | |||
| 3763ec7652 | |||
| cc99c3e262 | |||
| 2c762a67ab | |||
| 6cbf73a666 | |||
| 038e711af2 | |||
| c2fea7b3c6 | |||
| d631b1fa8c | |||
| de47d0935f | |||
| 010d1a9be3 | |||
| c3f9f5efaf | |||
| 1cb9ea5c46 | |||
| 39305c1a7c | |||
| f04780e66d | |||
| 70be35f319 | |||
| e76912303c | |||
| 2d9611f948 | |||
| bf8965a615 | |||
| e003532701 | |||
| 89d1c60c3f | |||
| f820aa3f60 | |||
| 83df863b6c | |||
| fea811a4b7 | |||
| d755b7908e | |||
| eab8b9a116 | |||
| e98a7ff239 | |||
| 0b82467cf1 | |||
| a0ef37e7bc | |||
| 8064254eaf | |||
| 8982342c54 | |||
| c26177d14f | |||
| ba89c8d580 | |||
| 4bf173e9c1 | |||
| e6feb22411 | |||
| e5121e70d0 | |||
| 9bd079d425 | |||
| 9bc68d209f | |||
| e6e3e69da4 | |||
| 750a265531 | |||
| 95fafc7c25 | |||
| 0f3bb838d8 | |||
| 11ba413c4a | |||
| 6e1e4f1dc2 | |||
| 34f14e657d | |||
| a571f31c95 | |||
| b7747b50ce | |||
| 0e367ba541 | |||
| 83d3f85636 | |||
| 4206d8f955 | |||
| aea57f2026 | |||
| 232e41f2ff | |||
| d781d7ec00 | |||
| 3e51317236 | |||
| 9c7d3f7f67 | |||
| 7473cef063 | |||
| bcc9dcd210 | |||
| f2e45daf54 | |||
| b43a52128f | |||
| 0e4828e732 | |||
| 771bd349cb | |||
| 6c60ff92ff | |||
| f1f1783aa8 | |||
| 028ef2b5b5 | |||
| 6902a8b294 | |||
| feb907d225 | |||
| bb5b89eb26 | |||
| a0c157eea8 | |||
| 4a6a7028a9 | |||
| eb3671b647 | |||
| 97b2635e7d | |||
| 39743082b4 | |||
| 2e3465cb49 | |||
| 7ee6d0fa62 | |||
| 0ae7df4a95 | |||
| 3e142a6297 | |||
| aee2b0c50a | |||
| 9973e97b84 | |||
| e748280622 | |||
| a4a09e73d5 | |||
| a747e2bb97 | |||
| 4c9b6b44d5 | |||
| 71906d09b7 | |||
| fb98c932b2 | |||
| 2a78d3efa9 | |||
| d0f9cc27a3 | |||
| 4325f13f74 | |||
| 3aa99a660e | |||
| 01fd7eb861 | |||
| b5a96ff9c1 | |||
| 6f184a0471 | |||
| 0067f68117 | |||
| 232fffffac | |||
| 0c3927ce4a | |||
| ae4995c671 | |||
| 862faa16c0 | |||
| 6519d3bc97 | |||
| ccbb6263ea | |||
| 053d1bade3 | |||
| 694741f441 | |||
| 6fd4347c6c | |||
| e25dd2c2c3 | |||
| ef24a3caa8 | |||
| 9efcfc65af | |||
| f55bde6ee4 | |||
| 50ac80cb4c | |||
| d51e9e3d03 | |||
| 0abd611c0a | |||
| 0ddbc1304b | |||
| 1f66d60272 | |||
| 6805abe0f3 | |||
| 20b8c48440 | |||
| c2a6d182d7 | |||
| 7746c4722b | |||
| aa55bc1559 | |||
| 5b261af659 | |||
| 51eef8c5b7 | |||
| f22eab5544 | |||
| fbe47d912a | |||
| 33ae18b8b3 | |||
| d865c55007 | |||
| 0d8dcacee2 | |||
| ae2cfeefe3 | |||
| d06f52a7f0 | |||
| 2de3dc2735 | |||
| bf5e0c10ce | |||
| b973ad1df9 | |||
| eff3252095 | |||
| 4a4b9d145d | |||
| 9f4e45d333 | |||
| 431447ef87 | |||
| 73c0f21363 | |||
| f7991303e8 | |||
| fe6f9e9a65 | |||
| 7678a937e4 | |||
| 7a690eb5fb | |||
| 9cfe28aee8 | |||
| c17c743ed4 | |||
| 4102982ef4 | |||
| 5ff839732e | |||
| e2359c11ae | |||
| 8fea0f0a8f | |||
| d449145799 | |||
| 9e847075fa | |||
| fac25561bc | |||
| 1ef2ad611f | |||
| 9f7074a706 | |||
| 204d08140a | |||
| 77d26759e3 | |||
| 58c46bed40 | |||
| ac6857ee28 | |||
| 6b83a05ada | |||
| ac758b6875 | |||
| 9c99c7d11a | |||
| 3a93a250b7 | |||
| f03b8859ed | |||
| 5c946cdbd8 | |||
| 1b617b28fc | |||
| 33cf096b03 | |||
| 9031e0369e | |||
| 94c75f33bb | |||
| 2a151d9354 | |||
| 092e72d60d | |||
| 297223cc21 | |||
| 4b2e34e0aa | |||
| 8aee833024 | |||
| d1fb165ad2 | |||
| 1afad51ee2 | |||
| 0525b08612 | |||
| 8867c00d68 | |||
| c1a2be0d05 | |||
| 5df36d4ead | |||
| be840ccd00 | |||
| f758bd769b | |||
| b1baa4ed8b | |||
| f8d97a5f61 | |||
| ad837c2069 | |||
| 9198522307 | |||
| 552d84884f | |||
| 7c38b7bc01 | |||
| c5c5c9b17c | |||
| eed181245d | |||
| 27dc506a03 | |||
| cc8fc19d4a | |||
| 2bd8df54e1 | |||
| bedc63d75d | |||
| d48261aa23 | |||
| 2fb453a4a5 | |||
| eb28e8b322 | |||
| c513c4da96 | |||
| b0d6d59be5 | |||
| 92d1b6060c | |||
| d11cc22536 | |||
| b2ae5b197e | |||
| 498ccae27a | |||
| ccf3c71903 | |||
| 020c1e9b6c | |||
| e9c93f9c0c | |||
| 6493e12bfb | |||
| 1d5c516780 | |||
| ff3bc3cc94 | |||
| 0381073e56 | |||
| 0b8876e946 | |||
| ccb80ab09d | |||
| 80776172a5 | |||
| 31e098e64e | |||
| 7aae12d55d | |||
| 4d62bbf857 | |||
| 7d3a576a7b | |||
| 17ca2c49a5 | |||
| 7278f72157 | |||
| f0f85a7ef3 | |||
| 77b3a76919 | |||
| 0ec4ee5963 | |||
| 6932461e63 | |||
| 422ebcf8e0 | |||
| 4b71f9126e | |||
| b4c3f9aaf0 | |||
| 50df3ec103 | |||
| 54a84a6e6e | |||
| 2ff6cc3135 | |||
| f8f6132006 | |||
| 8eda8113d9 | |||
| 04921a9015 | |||
| e2dab60ad1 | |||
| 093ae2b4b4 | |||
| 10adda0d73 | |||
| 4f5255c36e | |||
| 97728357e4 | |||
| 7be92db76f | |||
| 7241f42e9d | |||
| 42f98c7eec | |||
| 88ebe22d8b | |||
| a5ffbbee2d | |||
| 08f2a395a3 | |||
| 5e1364daeb | |||
| f42e8ac3d2 | |||
| 0601293edb | |||
| 1938a73c90 | |||
| f1d4a85f59 | |||
| ae3638121c | |||
| 74df79331d | |||
| 3f45338cc9 | |||
| 83a889d678 | |||
| ab3ed5c431 | |||
| 944bba1031 | |||
| 30a328705e | |||
| 03095f85bc | |||
| 5c43906b24 | |||
| 0be987391b | |||
| 777dd99585 | |||
| 6d5fdc2b68 | |||
| c02c35e256 | |||
| 20d1f357dd | |||
| a00571a1d7 | |||
| cf5dd15213 | |||
| 8dc84b3deb | |||
| ff973f7992 | |||
| aa592190dc | |||
| af3605705f | |||
| 35cb4fbf8c | |||
| b344d30792 | |||
| 9776f2350b | |||
| a2dec6c32a | |||
| b64c375f2f | |||
| 7bbcf5875c | |||
| e1c19367f0 | |||
| 4cc0952736 | |||
| f4ffba1a6e | |||
| 25f514ab6d | |||
| 6955f80c6e | |||
| b312055c80 | |||
| 1c109afdaa | |||
| 73c0cc5203 | |||
| 94f6208bde | |||
| 55e1eab1a2 | |||
| e3287ad303 | |||
| 7526afdae0 | |||
| 5f05703206 | |||
| 6d1ee15b9a | |||
| 1527ef3db0 | |||
| 8580e73b65 | |||
| f838448552 | |||
| abf2ae3f80 | |||
| 307c27892d | |||
| 961ba55e85 | |||
| e8f4b7cf19 | |||
| 5987455d35 | |||
| cc7f7220c0 | |||
| c16c7312cf | |||
| b18851e0b9 | |||
| b29877e14c | |||
| 3a89108a55 | |||
| 752b3f0dd6 | |||
| 885fd2b15c | |||
| 2005495bfb | |||
| 97ae59fe1a | |||
| 797355cb7e | |||
| f2af1ed332 | |||
| f08d102ac2 | |||
| a2de96abc0 | |||
| 5885b31bb4 | |||
| 3b6901f7fd | |||
| 849ffd59ec | |||
| db4721a31d | |||
| 27cd24c316 | |||
| 41ca1be4ff | |||
| dce0bbad6c | |||
| 3617d24318 | |||
| 4e6d6578e4 | |||
| 5856325e5a | |||
| b4b134e527 | |||
| c8d084a85e | |||
| 3e0dcfd47f | |||
| 99338d278d | |||
| 1ae9e7b448 | |||
| 14f0cb2704 | |||
| eebb2f196d | |||
| 63653bd6af | |||
| 6eec07257a | |||
| 1bdd01867a | |||
| 1fd8c45c55 | |||
| 0470fe9f89 | |||
| 54549adc66 | |||
| f84607af52 | |||
| ecb954fd9d | |||
| 8742b63fa1 | |||
| ac0ea378ff | |||
| d580d4e46c | |||
| a2971d0449 | |||
| 478e001d0e | |||
| efcd72a2ef | |||
| 5665d51bb3 | |||
| 518034d28d | |||
| 7874c86cb2 | |||
| 6d23dac1f6 | |||
| 993a106679 | |||
| 8e5e2e52fd | |||
| 346d10172b | |||
| 085ae9cab2 | |||
| 6497f08ad4 | |||
| 85248d7850 | |||
| 3276c46c72 | |||
| 76e1dd515f | |||
| 568dff40b6 | |||
| d439221c62 | |||
| 03ba24dd65 | |||
| 75045328ec | |||
| 6e532184bb | |||
| 1054ec7749 | |||
| 001fa99741 | |||
| 3482605b1a | |||
| 6a66bb2314 | |||
| 212ecff33b | |||
| ae7bdefc33 | |||
| 66166bd7f7 | |||
| 4cc23f6608 | |||
| 7150dd66cd | |||
| 5666efe66b | |||
| e006f89aa3 | |||
| ffb2c4de77 | |||
| 19c55cbb75 | |||
| 720b906a74 | |||
| e05f961eed | |||
| 6151c1044a | |||
| aad7995648 | |||
| 700862295f | |||
| b9c13283a4 | |||
| f08983a948 | |||
| 7a5ce1cb34 | |||
| 7f14b69022 | |||
| 6e2abeba5e | |||
| eae329f332 | |||
| ef3961448f | |||
| 9139f4ba84 | |||
| 6dc99f7738 | |||
| b4c4daf775 | |||
| ad6cc5a12d | |||
| a9e789fa02 | |||
| 590bbd7e21 | |||
| 29e0ded977 | |||
| 6912223444 | |||
| 6510b12203 | |||
| dd6a6fa7ec | |||
| 94dc25b45f | |||
| f1c151f157 | |||
| f31d8bb9a1 | |||
| 660f130d2b | |||
| a2619da37e | |||
| 24a34936db | |||
| 8edff76765 | |||
| 2cf65953db | |||
| 62e8c573e8 | |||
| 88c10e02ff | |||
| 1a92141896 | |||
| 53d1c3f117 | |||
| 9a96f5b64e | |||
| 52ec917125 | |||
| ae792cedde | |||
| bb276ef5a9 | |||
| 7d0468aaa4 | |||
| 44f48ce915 | |||
| 80131e1e4a | |||
| a11eddd04b | |||
| 8fe9bc6439 | |||
| 9f60324821 | |||
| fd25a53d1b | |||
| 322bd934be | |||
| 720b183017 | |||
| 7243369333 | |||
| f83828d944 | |||
| c7502c6eb3 | |||
| 8e7d88c85b | |||
| 6027e777c8 | |||
| 8313879b3c | |||
| e5cd6b6193 | |||
| e75c48ec7a | |||
| 189ca73707 | |||
| 7984a9a500 | |||
| 54e78e114c | |||
| 6fb79d5f33 | |||
| b49547b2b5 | |||
| c0a0d1bb22 | |||
| f40ff3c134 | |||
| 7c28bafba9 | |||
| 6e17ee9fe2 | |||
| 5d443a2482 | |||
| 4ce10986b5 | |||
| 0a944dc950 | |||
| 5290d5f667 | |||
| 962dd27a8c | |||
| 2f4959dcd8 | |||
| ef93fcfe48 | |||
| c245d93e7d | |||
| 2e0d576e6b | |||
| 44dae05c3d | |||
| 1af764c4d0 | |||
| f8345b3fe6 | |||
| f0e616ea2b | |||
| e9c25f8274 | |||
| aaf09ceb26 | |||
| 28df4a0e25 | |||
| 7837be0575 | |||
| 2fd3553d78 | |||
| e4a3d284b2 | |||
| 15630855dd | |||
| 941da5dc94 | |||
| a6d1544447 | |||
| 69065b53c8 | |||
| f09b0def11 | |||
| b1c4b0f07d | |||
| 31d6f87d80 | |||
| 64b08311b9 | |||
| 389a4bf44d | |||
| eaa6bf3f42 | |||
| 5bcf3d2bc0 | |||
| 4559279686 | |||
| e0471187d0 | |||
| 9fadf6cf84 | |||
| f4f705e723 | |||
| 1847b99461 | |||
| 5adad6c1b4 | |||
| fb0c3c8061 | |||
| d4beff7954 | |||
| a1e94b67d5 | |||
| 8521367373 | |||
| 022b8cea37 | |||
| 8e404a26f6 | |||
| be5a832db3 | |||
| ef923fae44 | |||
| b119b6c474 | |||
| 340a9ab6be | |||
| 8efc7866dd | |||
| 37f56fa324 | |||
| 208a9b8547 | |||
| ae796740aa | |||
| d2643dc483 | |||
| efecea001a | |||
| 1955371a71 | |||
| d41a003bcc | |||
| 6e07bad728 | |||
| 971d844266 | |||
| 633786f55e | |||
| 1b00f36520 | |||
| 24c9e6ff66 | |||
| e6d31cb89c | |||
| d275109e79 | |||
| 732c362dea | |||
| ef3b9161f8 | |||
| 559317f9d0 | |||
| 02ed8410a2 | |||
| 3279a7c9a2 | |||
| 7f7c6297f7 | |||
| f9b5f704b1 | |||
| 75474e5bf1 | |||
| c3a40dba68 | |||
| 976ed5e396 | |||
| 83b00ad861 | |||
| dd27968460 | |||
| e9a57c56b7 | |||
| 3a838447a8 | |||
| 4136f395bf | |||
| 9d1f7e7348 | |||
| 34db065631 | |||
| 314a4245a9 | |||
| febac23b25 | |||
| 9e10458209 | |||
| 352cf002b2 | |||
| 7dddb6cf7a | |||
| 237732d0a1 | |||
| 6dd2e2f06d | |||
| 61cae70fe5 | |||
| 06cc62f40d | |||
| 0074496ea4 | |||
| 131f4c50fd | |||
| 253a02e712 | |||
| f062187e47 | |||
| 45233a7e16 | |||
| fd19404b6f | |||
| 747eab12d9 | |||
| 7ec997afce | |||
| f25bec9132 | |||
| a243285af4 | |||
| ff23795f5b | |||
| 1a450b0b39 | |||
| 4873c0b1ea | |||
| 1feae2083d | |||
| 5fac6142e8 | |||
| 085563653f | |||
| 38da06301d | |||
| ae72661742 | |||
| 05a3a83b6c | |||
| 46d0e2f892 | |||
| 70f9921423 | |||
| 02e020c05e | |||
| 1fc77885c2 | |||
| 2c6e2a68b7 | |||
| 52de6766c7 | |||
| c0b82db752 | |||
| 83b2abb6d6 | |||
| 29b4ab04c3 | |||
| fae367ab31 | |||
| 1261a44cec | |||
| 49e7939a10 | |||
| 53bd40ebaf | |||
| cd4e73193d | |||
| b9fed3391b | |||
| aacb89ed53 | |||
| 52bfa90d5e | |||
| aa261049f4 | |||
| c77e9231ef | |||
| 49584082a0 | |||
| c6c86abeee | |||
| fbcc84bdcf | |||
| 97479f9613 | |||
| 55e6b4f928 | |||
| 32f480a4ae | |||
| 9853d4e0d4 | |||
| 598addff94 | |||
| 86c3bfd66d | |||
| e17a8989cf | |||
| 13dda25334 | |||
| 0f339f3a6b | |||
| 5edecb9495 | |||
| bfc670b4d9 | |||
| 4b6a846d9c | |||
| 5110ffeef4 | |||
| ead1aa8dfc | |||
| d4d4a46436 | |||
| 788f543bc3 | |||
| 3be9515d84 | |||
| 4972b3722e | |||
| dcca3cf80b | |||
| 90871eeb9e | |||
| 634c395a6f | |||
| 69a4df909c | |||
| 3f7da833d1 | |||
| db4668c057 | |||
| b11f7c7817 | |||
| 2da54df9df | |||
| 116789022c | |||
| b78b576b21 | |||
| 76c7f3b14e | |||
| 35972e68e1 | |||
| 7ca6b2b8b0 | |||
| f5c33e5073 | |||
| 9a4465f9c0 | |||
| e58739c559 | |||
| 8ed132a5b9 | |||
| a6ba0d3fbe | |||
| a3c0e81230 | |||
| 63e97754fb | |||
| a4111363c0 | |||
| deabdb666f | |||
| 57aebadb15 | |||
| 8b7c1e94e1 | |||
| 2c9cd8f68c | |||
| 8e58dd8dec | |||
| c06dd27c33 | |||
| becd9c224e | |||
| 5b7e224f46 | |||
| f8c95a1dbe | |||
| 790b03c707 | |||
| 1e99155d61 | |||
| cc465f0f35 | |||
| 5583fd89b3 | |||
| 2cdc210193 | |||
| 523a6a1cff | |||
| f1e9fdf76d | |||
| 6735135773 | |||
| 67161506ad | |||
| 2543158c8e | |||
| 61761cfab1 | |||
| 87e5984ae2 | |||
| 9294d33611 | |||
| e31da8532e | |||
| c4b682f996 | |||
| 4c5f6fe360 | |||
| 0fe19ed2ac | |||
| 2af42f48b9 | |||
| 29d2f6ed6c | |||
| 6edb21231e | |||
| 88b8a01da6 | |||
| 101ccce895 | |||
| 27df6c86fc | |||
| c5d6230c66 | |||
| 4f496b8681 | |||
| 86fa7720f9 | |||
| a9b3d8c998 | |||
| cdfb3d5113 | |||
| 3a48ab4c54 | |||
| 5a9478cdba | |||
| 39bb863024 | |||
| 2f2688b829 | |||
| 579d51b1b2 | |||
| f6c4e3eb1c | |||
| 9a49fda8e6 | |||
| d922ca68e7 | |||
| 52c87a0330 | |||
| 1ee725ef35 | |||
| ad24d6cb04 | |||
| e0c4e144b9 | |||
| 363dd7bdf0 | |||
| a94fe04a9a | |||
| 5b6be88587 | |||
| 79d29b7633 | |||
| afb6e5441d | |||
| c0702318d2 | |||
| d382463f8a | |||
| a72d993e65 | |||
| 3ee8697bbf | |||
| ca1b3a80ae | |||
| d317a93e0f | |||
| 39f8b82640 | |||
| 32bfe0dddd | |||
| 4c14afba4e | |||
| 288c52b688 | |||
| 2cb37408a3 | |||
| 60ba9c3280 | |||
| 7e89cd8643 | |||
| 6c4840fa50 | |||
| 29e71638ce | |||
| 608cdbe3f6 | |||
| 09dd8053a9 | |||
| ae336f146d | |||
| 6a6cbdd9b4 | |||
| efc2702491 | |||
| 2351271889 | |||
| 29d8c5bb50 | |||
| a11f46fed4 | |||
| 5d06584545 | |||
| a0716c39de | |||
| 461ca703ff | |||
| 36333076d5 | |||
| 2ebc5011f3 | |||
| 92ac503b74 | |||
| 1fef394fde | |||
| d76ecbba7c | |||
| 6c1e2989b1 | |||
| 4b38004a49 | |||
| 546fcfa3ec | |||
| 32c3fbd18e | |||
| 635b854c29 | |||
| bcc3b1cbb5 | |||
| 57852f6498 | |||
| 14dfb539b0 | |||
| fe08f457bc | |||
| e24c0ec9df | |||
| 37a18c858f | |||
| 6735bffd39 | |||
| e6a59be8c0 | |||
| c4d073a4de | |||
| 5b8c604f47 | |||
| c2ee8d70e4 | |||
| 41201f488c | |||
| c531739602 | |||
| a5a811f767 | |||
| 15d188d7f8 | |||
| 8dcbf2675b | |||
| 96b36ec01e | |||
| 1f4c1e8821 | |||
| f3c8f40c51 | |||
| b01382c20b | |||
| e4ee040a04 | |||
| c575939ef4 | |||
| c5cca49117 | |||
| 7e0f47ff15 | |||
| 4972ba9a78 | |||
| 4ec9356ba2 | |||
| de597eb7d2 | |||
| 7d18544b04 | |||
| 3b60676e64 | |||
| d7bc1d776c | |||
| 1e8cfa10bf | |||
| b249954538 | |||
| dda14faac5 | |||
| 6788a614d1 | |||
| 97ec7de9e6 | |||
| ffed7d6834 | |||
| c330e4203e | |||
| 0533d9ff6e | |||
| f5b68e2d9d | |||
| 58c153b9ac | |||
| 60052ffb45 | |||
| 1558948b9b | |||
| c9645885d0 | |||
| 3672ae1118 | |||
| c48ba54a09 | |||
| 3f87f29a81 | |||
| a9bb5be49d | |||
| d91326fb4a | |||
| a14a78de34 | |||
| 533e7a97ef | |||
| b4c80052fe | |||
| 79bbc37daa | |||
| 3a98db672b | |||
| 28c1dc3e39 | |||
| c4836bbd70 | |||
| 0e3399177e | |||
| 39727d6a81 | |||
| fb345e983e | |||
| 64e153fc34 | |||
| e297eada07 | |||
| 51cbbd0438 | |||
| 51257991c0 | |||
| d66adc937d | |||
| 90b2b2144b | |||
| ed0a42f940 | |||
| b7f71b026d | |||
| 5c7decc27d | |||
| 68e1cdbdea | |||
| 4f4fa940d8 | |||
| 46af99b8c0 | |||
| f55303b0a8 | |||
| 222d6ca952 | |||
| 160a0a5ee1 | |||
| 9a0c994fa8 | |||
| 91d1805fb1 | |||
| af4f4069ee | |||
| d9199657c1 | |||
| 8bf52f8c0f | |||
| 1e1eac5f17 | |||
| 19e3842615 | |||
| 8ab0190c29 | |||
| 07d0fd6719 | |||
| 9044110096 | |||
| d8709b18c6 | |||
| 8ee37e7b47 | |||
| 24853eb42c | |||
| c136432978 | |||
| 245bc59c68 | |||
| 97865f03f6 | |||
| 7cfaa8a418 | |||
| 3bbea05a93 | |||
| 3d0cd51f27 | |||
| 9b237345d1 | |||
| 5f25a0788a | |||
| 7460764d91 | |||
| 36ce6a7e4f | |||
| 7e61a04785 | |||
| 28d34b0f56 | |||
| 5caca8d64e | |||
| 123acd5a73 | |||
| 110b410af4 | |||
| 862370f232 | |||
| 7182b2508d | |||
| 0807891501 | |||
| 60204bd309 | |||
| db16262698 | |||
| 96c1e88d56 | |||
| 9bd54b592d | |||
| 8c6c4e5262 | |||
| 18dd7ebae2 | |||
| 4d94803d32 | |||
| 0e19f74c16 | |||
| bb5dca016d | |||
| cf89cb12cd | |||
| f18b913493 | |||
| 61d744c38a | |||
| 453c85e61d | |||
| 853c11d301 | |||
| b9779176d5 | |||
| c7b5cc3787 | |||
| 158a4d897b | |||
| 1fd06cf773 | |||
| 74a0d26d0e | |||
| 17a613546c | |||
| 3f2d2d8f37 | |||
| 88b94c3c67 | |||
| 80a9fa962d | |||
| a4e5ed68fd | |||
| 376c5adb7c | |||
| 64f98e058d | |||
| 9d05289147 | |||
| ef89eb019a | |||
| e75954a7ab | |||
| 52685ad50c | |||
| da24f97483 | |||
| f04d49ca17 | |||
| f6e23d726f | |||
| 5e28fb8f97 | |||
| 89fd12692f | |||
| 74a149127d | |||
| dccd3adb9b | |||
| 523ba1ff50 | |||
| 693d074d76 | |||
| c5770907ac | |||
| e5a2abb872 | |||
| 83981e40b5 | |||
| ec94450aef | |||
| 76363231be | |||
| 765ecfed84 | |||
| 736718ef53 | |||
| 15265ac40a | |||
| 37192a99a6 | |||
| 5f51b42c99 | |||
| 88862fcdb6 | |||
| 2d5a938621 | |||
| ce4bff7fa5 | |||
| 39b3e71239 | |||
| fa1f026367 | |||
| 9595ee80e3 | |||
| 015fb81810 | |||
| d867a845fd | |||
| d7d3ff4849 | |||
| a4a3d829be | |||
| b615e854e1 | |||
| f1b6b1711b | |||
| 29b844a408 | |||
| c8ca2a8604 | |||
| f3ca6a9180 | |||
| c58549d512 | |||
| 6cb53e7d34 | |||
| af9dc1f817 | |||
| b6c74c1c20 | |||
| 52aeaebde0 | |||
| 20f36f8c88 | |||
| 967762e5ef | |||
| 55f3347514 | |||
| 23612e41f2 | |||
| a94da5937c | |||
| 7196860373 | |||
| 833ce98409 | |||
| 1fcf823d66 | |||
| 043b8bc5ad | |||
| 1b386f46b4 | |||
| a9972399c5 | |||
| 77e882c3bd | |||
| 2b13b2d239 | |||
| 27e008d3f7 | |||
| 9aeb0e1d30 | |||
| def5fc3ff7 | |||
| db6a545203 | |||
| cf205d059f | |||
| c185adf780 | |||
| 5b2cd5fae0 | |||
| 551d0622c5 | |||
| 92b8ec9ff8 | |||
| d1d33372ff | |||
| d6e4999f1f | |||
| 2e7f669153 | |||
| 9ced62e239 | |||
| 382b924b41 | |||
| b153236503 | |||
| 549dafc241 | |||
| e7886b6a34 | |||
| 25dfbc3134 | |||
| bff8c0af61 | |||
| 1c4c5ae370 | |||
| c0247e66e8 | |||
| 4d7c2e9d90 | |||
| f80094deb7 | |||
| c0603e4768 | |||
| 523b37a3e9 | |||
| 2690ba03b2 | |||
| 9e3ca26ae6 | |||
| 52134822b8 | |||
| 3c3ba97d11 | |||
| 99f0cda875 | |||
| 7188778c81 | |||
| 625b0ffec0 | |||
| 532aa593a6 | |||
| 3887747e4a | |||
| c8452c5195 | |||
| 6d8a0c52f5 | |||
| 8057dd2214 | |||
| 96bf7074e3 | |||
| 8f7373427e | |||
| 0e79314353 | |||
| 5221f35182 | |||
| a65302dafe | |||
| 397bd915a3 | |||
| e027fa76b1 | |||
| 920a93071b | |||
| 5b72167c8c | |||
| 7559b9fed1 | |||
| f995fd08a1 | |||
| 0ba5123cef | |||
| 5a3ef18c94 | |||
| 8dc2405ad6 | |||
| 72559a785e | |||
| 88cdb99ff7 | |||
| 5b0915e677 | |||
| 55bac62c5a | |||
| 38f5ef6bd4 | |||
| bd1d21911d | |||
| ea8311301e | |||
| c669c94ba3 | |||
| 625332a686 | |||
| 6bc9b64421 | |||
| 74619675d5 | |||
| 416e2b67b1 | |||
| 02bf3ed5c0 | |||
| 93a4dbda4b | |||
| 4a818ecbb6 | |||
| 416953f6dc | |||
| 9ec6e0a501 | |||
| 22951f5523 | |||
| ec40598d4c | |||
| 2bb5145a20 | |||
| ecf7e8e9a7 | |||
| 1f31bee5e4 | |||
| 5b0743d66b | |||
| 6fd3fc10e3 | |||
| 547a2d1f9f | |||
| 7938c1b884 | |||
| 253ec52c01 | |||
| 701e58e157 | |||
| bad25dec0e | |||
| 051134ac9f | |||
| a3a2f0617c | |||
| 293d5bffa8 | |||
| c8d83ce557 | |||
| 860a39af2a | |||
| 78b651c2c9 | |||
| 7c2448ecea | |||
| 1de8e294d8 | |||
| cef5ac8c8b | |||
| 6e49b85703 | |||
| 14a025a6bf | |||
| e7ee76dc56 | |||
| 47713d05e3 | |||
| 40121d60cd | |||
| 43e495045c | |||
| 581302e147 | |||
| 00168d4660 | |||
| 39382a16f3 | |||
| b8f6d41418 | |||
| 0434287ef8 | |||
| e56c3cddd8 | |||
| d036559e0e | |||
| aa183e35d8 | |||
| 56dd31f33b | |||
| 5149373467 | |||
| c00258237e | |||
| b7f0b278fb | |||
| fdb447ac55 | |||
| 2c88f958ed | |||
| a317cbdc09 | |||
| 5a458590b8 | |||
| e9b49ebf8e | |||
| c925f452e7 | |||
| 2fc6077a68 | |||
| ec7586dac3 | |||
| 00d6b3609f | |||
| a580b4c21e | |||
| ccd731a2ce | |||
| d701668f50 | |||
| 5733ad3e32 | |||
| 29cec910fc | |||
| 9be1dadb04 | |||
| d542f5624a | |||
| 6b9a744b2d | |||
| 12d6d679b0 | |||
| 97c533eb9c | |||
| 0554031514 | |||
| 908adfc191 | |||
| 08e16d966a | |||
| daa599c135 | |||
| 1c86acd8ba | |||
| 7b8bf96c2b | |||
| d801ca16a3 | |||
| a295166754 | |||
| acbd1801c7 | |||
| 908d2471ec | |||
| b07357373f | |||
| e35a0b1c44 | |||
| 669368cf21 | |||
| 372340b731 | |||
| 3ef3f05288 | |||
| fca55e3741 | |||
| 0ea87b6473 | |||
| aceb89fb7d | |||
| e8537f5512 | |||
| 06158be674 | |||
| 0b3cceb21d | |||
| c5b0ecac4f | |||
| a3cb5499bf | |||
| ca0f5ffe60 | |||
| 2214a9df5c | |||
| 34c89d6896 | |||
| f012e15c95 | |||
| b2e973056a | |||
| 4beb4ae2bc | |||
| bf587e9aac | |||
| 3ee0dee12a | |||
| d4b723a7c9 | |||
| d51887fbed | |||
| 8a3d7cce1c | |||
| a744e8e375 | |||
| 40a04816a4 | |||
| 6d81770985 | |||
| 4e41cf9e2b | |||
| 485102814f | |||
| 17cfda1a98 | |||
| 7fea17457d | |||
| 2a3969695b | |||
| 57adc97733 | |||
| 75d002690a | |||
| 4bba1273aa | |||
| bf6dace925 | |||
| 32f69dab0e | |||
| 578bde9aae | |||
| e1c1036648 | |||
| 5650257c0c | |||
| 7a8fb5d2fd | |||
| d9096f9ea4 | |||
| 989fd10d06 | |||
| ad068622fb | |||
| 0f7e48ead2 | |||
| 249438be88 | |||
| d51daeab1a | |||
| 3f91aff573 | |||
| 83ffb9c7fa | |||
| 258ffc1382 | |||
| 8d91459f37 | |||
| 9dd7c284f0 | |||
| 31184f974e | |||
| 4612dcdb48 | |||
| 0f24c74b14 | |||
| d753aeea58 | |||
| 3a7abc2a35 | |||
| c4e9896851 | |||
| 155f20329b | |||
| 87adce3ca0 | |||
| 13f0b6c0cf | |||
| 0086bb9d06 | |||
| 2760ed80fd | |||
| 4fb8338fa6 | |||
| dd90693a4c | |||
| 46dddda22f | |||
| e2f3634db3 | |||
| 86d19cb577 | |||
| cd6cb84889 | |||
| 60184e1495 | |||
| cc428ef6cf | |||
| 69159b6e52 | |||
| b65bda506c | |||
| 61103119fb | |||
| f1a3b32dc4 | |||
| 450c669eb2 | |||
| fb4b5fa841 | |||
| 6da3e44fc7 | |||
| a0b4161a32 | |||
| 2f35fea097 | |||
| 57c472e093 | |||
| 01e88bb61d | |||
| 95a3e4fe1f | |||
| 747d0fcca9 | |||
| 5a07c9bd71 | |||
| 4852474343 | |||
| afca207cf0 | |||
| 5914888ad6 | |||
| d99b89ab29 | |||
| 363a92bd43 | |||
| fb64b4e499 | |||
| 051e094921 | |||
| ec434b208e | |||
| c2193ce1a8 | |||
| 0bcc9b7573 | |||
| 249a170ace | |||
| 200d3fdbe8 | |||
| 183c33931d | |||
| a348f74c65 | |||
| ea48b0d05c | |||
| e656a91736 | |||
| a415b8ecce | |||
| 5fcd71cf28 | |||
| 2b5b1f4e06 | |||
| 80f787e60a | |||
| 5847317526 | |||
| ccc496ba2c | |||
| 5663926aaf | |||
| 770eb4c8c3 | |||
| 552689b7fe | |||
| 397cc50f61 | |||
| 8946e92468 | |||
| 989289fadd | |||
| 4f6fa3b468 | |||
| a9a7957eaa | |||
| 2f56162f35 | |||
| eb50427670 | |||
| a9a852a4d6 | |||
| 37cbae0370 | |||
| 84d1041edf | |||
| 7a2a973b48 | |||
| 7930faace9 | |||
| e9ef930155 | |||
| 1f12dee3a0 | |||
| 0a2f28c2f2 | |||
| e260aa3870 | |||
| e31f37d578 | |||
| 20e9a8061d | |||
| dae7b4ae21 | |||
| 7690093b4c | |||
| b5e1240a8a | |||
| b8327e0457 | |||
| 6db750373a | |||
| 04748217d1 | |||
| 3df0ff7854 | |||
| 53116247c3 | |||
| 22f627c8e1 | |||
| 76341a9173 | |||
| 2ab4669251 | |||
| 27b48faad2 | |||
| 015cb74dd9 | |||
| 7accdb9003 | |||
| 2aae43a848 | |||
| c53cf38ffd | |||
| 16f8a7b2d2 | |||
| a2869639b2 | |||
| fd80b53f39 | |||
| e7441c39e3 | |||
| acaff32984 | |||
| aac4fbc220 | |||
| 5d6c0a8220 | |||
| 65058d0d57 | |||
| 7a97e54559 | |||
| 95fdf39bca | |||
| 315006a28e | |||
| 872f49ae8a | |||
| 603618a75b | |||
| b78bbf80bf | |||
| 72880f2dad | |||
| 2cf5b77d0b | |||
| 37e199cd2b | |||
| 21b1607fb5 | |||
| f1d552c5b6 | |||
| 6909bba290 | |||
| 476dfd9f12 | |||
| 9c1aa0b75f | |||
| 92d1dd153f | |||
| 0a422b06a5 | |||
| d641175e3c | |||
| 8348068f5f | |||
| f2a858c6a5 | |||
| f7485d586e | |||
| fe1ccdf834 | |||
| 2eb00c0bd3 | |||
| f6690500bf | |||
| 49d0f082f8 | |||
| 9947627df9 | |||
| 034b0b5aef | |||
| 1fd2edf29a | |||
| 88e3ef36a4 | |||
| 385da141e6 | |||
| 98b60a605f | |||
| 9c3b9fd40d | |||
| 884fd51b68 | |||
| af3348fe94 | |||
| 43ca0548da | |||
| a99ac0d057 | |||
| edf841fb6f | |||
| 0dbe38fba7 | |||
| 35c13ef965 | |||
| 12c91671bf | |||
| 3dc8dcf312 | |||
| 75a54521e8 | |||
| 773737930a | |||
| 4449917a7c | |||
| 67f385ded8 | |||
| cee5cd6cc7 | |||
| 36f18e7f40 | |||
| 198f841c7e | |||
| f3758d133a | |||
| d72abf6c3e | |||
| 408a27a64e | |||
| db516f667e | |||
| f7fee73752 | |||
| cd01b3890a | |||
| 475ef74ab7 | |||
| 93d9afca4b | |||
| 493df26058 | |||
| 0ba58f25a4 | |||
| 807da4e722 | |||
| be726e5ec4 | |||
| e0d671ab5f | |||
| 72bd3bd170 | |||
| eb445b5189 | |||
| a38e2d046a | |||
| 6cad1071c8 | |||
| e2c1370d60 | |||
| 089a2a7847 | |||
| b7fd924806 | |||
| c62f670bca | |||
| d1a88cbbca | |||
| f5a50c0007 | |||
| 894bb262ad | |||
| ebc18e3957 | |||
| da80dabe6b | |||
| 431363908e | |||
| 7e882e8fa3 | |||
| 9d1bf52ce3 | |||
| 345003d49f | |||
| f7eccfc6fe | |||
| e049bd9b2b | |||
| f7cfd47261 | |||
| 7693c58e28 | |||
| 78b02129c1 | |||
| 0e08a8f61c | |||
| 5b145f4d7c | |||
| dae15e81d8 | |||
| e63f6efaef | |||
| 11545f1c4d | |||
| 1cfc877088 | |||
| 21b905e963 | |||
| 19533f8992 | |||
| 09fcc36c9c | |||
| 25b5a727e8 | |||
| cbcf002a91 | |||
| a69e422cdd | |||
| 0346fec1ca | |||
| f15c85d508 | |||
| 39f1c6dda3 | |||
| 9dcf10eb6c | |||
| eaeca76e5a | |||
| a43bc5f82e | |||
| 937aafd6d2 |
-163
@@ -1,163 +0,0 @@
|
||||
CFILES = ai.c aircraft_cmd.c aircraft_gui.c airport_gui.c
|
||||
bridge_gui.c clear_cmd.c command.c disaster_cmd.c
|
||||
dock_gui.c dummy_land.c economy.c engine.c engine_gui.c
|
||||
fileio.c gfx.c graph_gui.c industry_cmd.c industry_gui.c
|
||||
intro_gui.c landscape.c main_gui.c minilzo.c misc.c
|
||||
misc_cmd.c misc_gui.c music_gui.c namegen.c network.c
|
||||
news_gui.c oldloader.c order_cmd.c order_gui.c pathfind.c
|
||||
player_gui.c players.c rail_cmd.c rail_gui.c road_cmd.c
|
||||
road_gui.c roadveh_cmd.c roadveh_gui.c saveload.c sdl.c
|
||||
settings.c settings_gui.c ship_cmd.c ship_gui.c smallmap_gui.c
|
||||
sound.c spritecache.c station_cmd.c station_gui.c
|
||||
strings.c subsidy_gui.c texteff.c town_cmd.c town_gui.c
|
||||
train_cmd.c train_gui.c tree_cmd.c ttd.c
|
||||
tunnelbridge_cmd.c unmovable_cmd.c vehicle.c
|
||||
viewport.c water_cmd.c widget.c window.c screenshot.c
|
||||
airport.c grfspecial.c terraform_gui.c ;
|
||||
|
||||
|
||||
LANGFILES = english.txt swedish.txt french.txt german.txt italian.txt slovak.txt hungarian.txt norwegian.txt danish.txt czech.txt galician.txt polish.txt romanian.txt;
|
||||
|
||||
####################
|
||||
# On UNIX we use gcc
|
||||
####################
|
||||
if $(UNIX) {
|
||||
SDL_CONFIG_CFLAGS = `XX_SDL_CONFIG_PLACEHOLDER_XX --cflags` ;
|
||||
SDL_CONFIG_LIBS = `XX_SDL_CONFIG_PLACEHOLDER_XX --libs` ;
|
||||
|
||||
LINKFLAGS += $(SDL_CONFIG_LIBS) ;
|
||||
CC = gcc ;
|
||||
CCFLAGS += -Wall -Wno-multichar -DUNIX -DWITH_SDL ;
|
||||
|
||||
OPTIMFLAGS = -O2 -fomit-frame-pointer ;
|
||||
DEBUGFLAGS = -g ;
|
||||
|
||||
# also include extmidi
|
||||
CFILES += extmidi.c unix.c ;
|
||||
|
||||
# compile in PNG support?
|
||||
if $(WITH_PNG) {
|
||||
CCFLAGS += -DWITH_PNG -I$(WITH_PNG) ;
|
||||
LINKFLAGS += -lpng ;
|
||||
}
|
||||
|
||||
# compile in zlib support?
|
||||
if $(WITH_ZLIB) {
|
||||
CCFLAGS += -DWITH_ZLIB ;
|
||||
LINKFLAGS += -lz ;
|
||||
}
|
||||
# compile for BeOS 5.1 and higher
|
||||
if $(WITH_BONE_NETWORKING) {
|
||||
CCFLAGS += -DENABLE_NETWORK ;
|
||||
LINKFLAGS += -lsocket -lbind ;
|
||||
}
|
||||
# link in BeOS MIDI and Be API libraries
|
||||
if $(BEOS_MIDI) {
|
||||
CCFLAGS += -DBEOS_MIDI ;
|
||||
LINKFLAGS += -lbe -lmidi ;
|
||||
CFILES += bemidi.cpp ;
|
||||
}
|
||||
}
|
||||
|
||||
####################
|
||||
# MSVC on Win32
|
||||
####################
|
||||
|
||||
actions ActWin32Res {
|
||||
$(VISUALC)\\..\\common\\msdev98\\bin\\rc /r /i $(STDHDRS) /fo $(<) $(>)
|
||||
}
|
||||
|
||||
rule Win32Res { ActWin32Res $(<) : $(>) ; DEPENDS $(<) : $(>) ; }
|
||||
|
||||
if $(TOOLSET) = VISUALC {
|
||||
OPTIMFLAGS = /Oa /Os /Ow /Oy /Oi /Og /Ox /Gr /Gf /Gy /Zp4 /J /WX /W3 -DNDEBUG ;
|
||||
|
||||
CCFLAGS += -DWIN32 -DWIN32_EXCEPTION_TRACKER ;
|
||||
CFILES += win32.c ;
|
||||
LINKFLAGS += /opt:nowin98 /LIBPATH:$(VISUALC)\\lib ;
|
||||
|
||||
LINKLIBS = ws2_32.lib winmm.lib user32.lib gdi32.lib ;
|
||||
|
||||
# compile resources too
|
||||
EOBJ = ttd.res ;
|
||||
Win32Res ttd.res : ttd.rc ;
|
||||
|
||||
# png screenshots?
|
||||
if $(WITH_PNG) {
|
||||
CCFLAGS += -DWITH_PNG -I$(WITH_PNG) ;
|
||||
LINKLIBS += libpng.lib ;
|
||||
}
|
||||
|
||||
# zlib savegames?
|
||||
if $(WITH_ZLIB) {
|
||||
CCFLAGS += -DWITH_ZLIB ;
|
||||
LINKLIBS += zlibstat.lib ;
|
||||
}
|
||||
|
||||
# build release by default
|
||||
RELEASE = 1 ;
|
||||
}
|
||||
|
||||
|
||||
####################
|
||||
# Common
|
||||
####################
|
||||
rule MyObjects {
|
||||
local _i _t _s ;
|
||||
|
||||
_t = $(OUTDIR)/$(>:S=$(SUFOBJ)) ;
|
||||
OPTIM on $(_t) = $(3) ;
|
||||
|
||||
MkDir $(OUTDIR) ;
|
||||
Depends $(_t) : $(OUTDIR) ;
|
||||
|
||||
for _i in $(>) {
|
||||
_s = $(OUTDIR)/$(_i:S=$(SUFOBJ)) ;
|
||||
Object $(_s) : $(_i) ;
|
||||
|
||||
# special handling for sdl.c and unix.c
|
||||
if $(_i) = sdl.c || $(_i) = unix.c { CCFLAGS on $(_s) += $(SDL_CONFIG_CFLAGS) ; }
|
||||
}
|
||||
MainFromObjects $(OUTDIR)/$(<) : $(_t) $(EOBJ) ;
|
||||
}
|
||||
|
||||
rule MyMain {
|
||||
if $(RELEASE) {
|
||||
OUTDIR = release ;
|
||||
MyObjects ttd : $(>) : $(OPTIMFLAGS) ;
|
||||
} else {
|
||||
OUTDIR = debug ;
|
||||
MyObjects ttd : $(>) : -D_DEBUG $(DEBUGFLAGS) ;
|
||||
}
|
||||
}
|
||||
|
||||
actions CompileLang {
|
||||
strgen$(SLASH)strgen $(>)
|
||||
}
|
||||
|
||||
rule LangFile {
|
||||
if $(>) = lang/english.txt {
|
||||
CompileLang $(<) table/strings.h : ;
|
||||
DEPENDS table/string.h : $(>) ;
|
||||
} else {
|
||||
CompileLang $(<) : $(>) ;
|
||||
}
|
||||
|
||||
Clean clean : $(<) ;
|
||||
DEPENDS $(<) : $(>) ;
|
||||
DEPENDS all : $(<) ;
|
||||
DEPENDS $(<) : strgen/strgen ;
|
||||
}
|
||||
|
||||
rule LangFiles {
|
||||
local _i ;
|
||||
for _i in $(<) { LangFile $(_i:S=.lng) : $(_i) ; }
|
||||
Clean clean : table/strings.h ;
|
||||
}
|
||||
|
||||
LangFiles lang/$(LANGFILES) ;
|
||||
|
||||
Main strgen/strgen : strgen/strgen.c ;
|
||||
|
||||
MyMain ttd : $(CFILES) ;
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
#define AI_PATHFINDER_PENALTY 150
|
||||
// The penalty given to a tile that is going up
|
||||
#define AI_PATHFINDER_TILE_GOES_UP_PENALTY 450
|
||||
// The penalty given to a tile which would have to use fundation
|
||||
#define AI_PATHFINDER_FOUNDATION_PENALTY 100
|
||||
// Changing direction is a penalty, to prevent curved ways (with that: slow ways)
|
||||
#define AI_PATHFINDER_DIRECTION_CHANGE_PENALTY 200
|
||||
// Same penalty, only for when road already exists
|
||||
@@ -71,7 +73,7 @@
|
||||
#define AI_LOCATE_ROUTE_MAX_COUNTER 200
|
||||
|
||||
// How many days must there be between building the first station and the second station
|
||||
// within one city. This number is in days and should be more then 4 months.
|
||||
// within one city. This number is in days and should be more than 4 months.
|
||||
#define AI_CHECKCITY_DATE_BETWEEN 180
|
||||
|
||||
// How many cargo is needed for one station in a city?
|
||||
@@ -130,7 +132,7 @@
|
||||
// reuse the station instead of building a new one!
|
||||
#define AI_STATION_REUSE_MULTIPLER 2
|
||||
|
||||
// No more then this amount of vehicles per station..
|
||||
// No more than this amount of vehicles per station..
|
||||
#define AI_CHECK_MAX_VEHICLE_PER_STATION 10
|
||||
|
||||
// How many thick between building 2 vehicles
|
||||
@@ -149,7 +151,7 @@
|
||||
// while old vehicles stay longer, because we do get less in return.
|
||||
#define AI_MINIMUM_ROUTE_PROFIT 1000
|
||||
|
||||
// A vehicle is considered lost when he his cargo is more then 180 days old
|
||||
// A vehicle is considered lost when he his cargo is more than 180 days old
|
||||
#define AI_VEHICLE_LOST_DAYS 180
|
||||
|
||||
// How many times may the AI try to find a route before it gives up
|
||||
@@ -168,13 +170,6 @@ static const byte _illegal_curves[6] = {
|
||||
3, // upright and downright are not valid
|
||||
};
|
||||
|
||||
static const TileIndexDiff _tiles_around[4] = {
|
||||
TILE_XY(-1,0),
|
||||
TILE_XY(0,1),
|
||||
TILE_XY(1,0),
|
||||
TILE_XY(0,-1),
|
||||
};
|
||||
|
||||
enum {
|
||||
AI_STATE_STARTUP = 0,
|
||||
AI_STATE_FIRST_TIME,
|
||||
@@ -227,7 +222,7 @@ enum {
|
||||
|
||||
#define AI_NO_CARGO 0xFF // Means that there is no cargo defined yet (used for industry)
|
||||
#define AI_NEED_CARGO 0xFE // Used when the AI needs to find out a cargo for the route
|
||||
#define AI_STATION_RANGE TILE_XY(TILE_X_MAX, TILE_Y_MAX)
|
||||
#define AI_STATION_RANGE TILE_XY(MapMaxX(), MapMaxY())
|
||||
|
||||
#define AI_PATHFINDER_NO_DIRECTION (byte)-1
|
||||
|
||||
@@ -235,13 +230,6 @@ enum {
|
||||
#define AI_PATHFINDER_FLAG_BRIDGE 1
|
||||
#define AI_PATHFINDER_FLAG_TUNNEL 2
|
||||
|
||||
// A macro for mp_street, where 0x20 is depot
|
||||
// mp_tunnelbridge, where 0xf0 is a bridge, and 0x4/0x2 means: roadtunnel/bridge
|
||||
#define AI_PATHFINDER_IS_ROAD(tile) ((IS_TILETYPE(tile, MP_STREET) && !(_map5[tile] & 0x20)) || \
|
||||
(IS_TILETYPE(tile, MP_TUNNELBRIDGE) && \
|
||||
(((_map5[tile] & 0x80) == 0 && (_map5[tile] & 0x4) == 0x4) || \
|
||||
((_map5[tile] & 0x80) != 0 && (_map5[tile] & 0x2) == 0x2))))
|
||||
|
||||
typedef void AiNew_StateFunction(Player *p);
|
||||
|
||||
// ai_new.c
|
||||
|
||||
+45
-42
@@ -1,14 +1,18 @@
|
||||
#include "stdafx.h"
|
||||
#include "ttd.h"
|
||||
#include "debug.h"
|
||||
#include "map.h"
|
||||
#include "tile.h"
|
||||
#include "command.h"
|
||||
#include "ai.h"
|
||||
#include "engine.h"
|
||||
#include "station.h"
|
||||
|
||||
// Build HQ
|
||||
// Params:
|
||||
// tile : tile where HQ is going to be build
|
||||
bool AiNew_Build_CompanyHQ(Player *p, uint tile) {
|
||||
if (DoCommandByTile(tile, 0, 0, DC_AUTO | DC_NO_WATER, CMD_BUILD_COMPANY_HQ) == CMD_ERROR)
|
||||
if (CmdFailed(DoCommandByTile(tile, 0, 0, DC_AUTO | DC_NO_WATER, CMD_BUILD_COMPANY_HQ)))
|
||||
return false;
|
||||
DoCommandByTile(tile, 0, 0, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_BUILD_COMPANY_HQ);
|
||||
return true;
|
||||
@@ -25,10 +29,11 @@ bool AiNew_Build_CompanyHQ(Player *p, uint tile) {
|
||||
int AiNew_Build_Station(Player *p, byte type, uint tile, byte length, byte numtracks, byte direction, byte flag) {
|
||||
if (type == AI_TRAIN)
|
||||
return DoCommandByTile(tile, direction + (numtracks << 8) + (length << 16), 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_RAILROAD_STATION);
|
||||
else if (type == AI_BUS)
|
||||
return DoCommandByTile(tile, direction, 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_BUS_STATION);
|
||||
else
|
||||
return DoCommandByTile(tile, direction, 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_TRUCK_STATION);
|
||||
|
||||
if (type == AI_BUS)
|
||||
return DoCommandByTile(tile, direction, RS_BUS, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD_STOP);
|
||||
|
||||
return DoCommandByTile(tile, direction, RS_TRUCK, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD_STOP);
|
||||
}
|
||||
|
||||
// Builds a brdige. The second best out of the ones available for this player
|
||||
@@ -57,8 +62,8 @@ int AiNew_Build_Bridge(Player *p, uint tile_a, uint tile_b, byte flag) {
|
||||
// Now, simply, build the bridge!
|
||||
if (p->ainew.tbt == AI_TRAIN)
|
||||
return DoCommandByTile(tile_a, tile_b, (0<<8) + type2, flag | DC_AUTO, CMD_BUILD_BRIDGE);
|
||||
else
|
||||
return DoCommandByTile(tile_a, tile_b, (0x80 << 8) + type2, flag | DC_AUTO, CMD_BUILD_BRIDGE);
|
||||
|
||||
return DoCommandByTile(tile_a, tile_b, (0x80 << 8) + type2, flag | DC_AUTO, CMD_BUILD_BRIDGE);
|
||||
}
|
||||
|
||||
|
||||
@@ -93,7 +98,7 @@ int AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo, byte fla
|
||||
cost += DoCommandByTile(route[part], 0, 0, flag, CMD_BUILD_TUNNEL);
|
||||
PathFinderInfo->position++;
|
||||
// TODO: problems!
|
||||
if (cost == CMD_ERROR) {
|
||||
if (CmdFailed(cost)) {
|
||||
DEBUG(ai,0)("[AiNew - BuildPath] We have a serious problem: tunnel could not be build!");
|
||||
return 0;
|
||||
}
|
||||
@@ -104,7 +109,7 @@ int AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo, byte fla
|
||||
cost += AiNew_Build_Bridge(p, route[part], route[part-1], flag);
|
||||
PathFinderInfo->position++;
|
||||
// TODO: problems!
|
||||
if (cost == CMD_ERROR) {
|
||||
if (CmdFailed(cost)) {
|
||||
DEBUG(ai,0)("[AiNew - BuildPath] We have a serious problem: bridge could not be build!");
|
||||
return 0;
|
||||
}
|
||||
@@ -122,7 +127,7 @@ int AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo, byte fla
|
||||
old_dir = dir;
|
||||
// Build the tile
|
||||
res = DoCommandByTile(route[part], 0, dir, flag, CMD_BUILD_SINGLE_RAIL);
|
||||
if (res == CMD_ERROR) {
|
||||
if (CmdFailed(res)) {
|
||||
// Problem.. let's just abort it all!
|
||||
p->ainew.state = AI_STATE_NOTHING;
|
||||
return 0;
|
||||
@@ -143,7 +148,7 @@ int AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo, byte fla
|
||||
cost += DoCommandByTile(route[part], 0x200, 0, flag, CMD_BUILD_TUNNEL);
|
||||
PathFinderInfo->position++;
|
||||
// TODO: problems!
|
||||
if (cost == CMD_ERROR) {
|
||||
if (CmdFailed(cost)) {
|
||||
DEBUG(ai,0)("[AiNew - BuildPath] We have a serious problem: tunnel could not be build!");
|
||||
return 0;
|
||||
}
|
||||
@@ -154,7 +159,7 @@ int AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo, byte fla
|
||||
cost += AiNew_Build_Bridge(p, route[part], route[part+1], flag);
|
||||
PathFinderInfo->position++;
|
||||
// TODO: problems!
|
||||
if (cost == CMD_ERROR) {
|
||||
if (CmdFailed(cost)) {
|
||||
DEBUG(ai,0)("[AiNew - BuildPath] We have a serious problem: bridge could not be build!");
|
||||
return 0;
|
||||
}
|
||||
@@ -173,19 +178,18 @@ int AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo, byte fla
|
||||
if (old_dir != -1 && old_dir != dir) break;
|
||||
old_dir = dir;
|
||||
// There is already some road, and it is a bridge.. don't build!!!
|
||||
if (!IS_TILETYPE(route[part], MP_TUNNELBRIDGE)) {
|
||||
if (!IsTileType(route[part], MP_TUNNELBRIDGE)) {
|
||||
// Build the tile
|
||||
res = DoCommandByTile(route[part], dir, 0, flag | DC_NO_WATER, CMD_BUILD_ROAD);
|
||||
// Currently, we ignore CMD_ERRORs!
|
||||
if (res == CMD_ERROR && flag == DC_EXEC && !IS_TILETYPE(route[part], MP_STREET) && !EnsureNoVehicle(route[part])) {
|
||||
// Problem.. let's just abort it all!
|
||||
DEBUG(ai,0)("Darn, the route could not be builded.. aborting!");
|
||||
p->ainew.state = AI_STATE_NOTHING;
|
||||
return 0;
|
||||
} else {
|
||||
if (res != CMD_ERROR)
|
||||
cost += res;
|
||||
}
|
||||
if (CmdFailed(res) && flag == DC_EXEC && !IsTileType(route[part], MP_STREET) && !EnsureNoVehicle(route[part])) {
|
||||
// Problem.. let's just abort it all!
|
||||
DEBUG(ai,0)("Darn, the route could not be builded.. aborting!");
|
||||
p->ainew.state = AI_STATE_NOTHING;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!CmdFailed(res)) cost += res;
|
||||
}
|
||||
// Go to the next tile
|
||||
part++;
|
||||
@@ -209,7 +213,7 @@ int AiNew_PickVehicle(Player *p) {
|
||||
// Not supported yet
|
||||
return -1;
|
||||
} else {
|
||||
int start, count, i, r = CMD_ERROR;
|
||||
int start, count, i, ret = CMD_ERROR;
|
||||
start = _cargoc.ai_roadveh_start[p->ainew.cargo];
|
||||
count = _cargoc.ai_roadveh_count[p->ainew.cargo];
|
||||
|
||||
@@ -219,11 +223,11 @@ int AiNew_PickVehicle(Player *p) {
|
||||
// Also, check if the reliability of the vehicle is above the AI_VEHICLE_MIN_RELIABILTY
|
||||
if (!HASBIT(_engines[i].player_avail, _current_player) || _engines[i].reliability * 100 < AI_VEHICLE_MIN_RELIABILTY << 16) continue;
|
||||
// Can we build it?
|
||||
r = DoCommandByTile(0, i, 0, DC_QUERY_COST, CMD_BUILD_ROAD_VEH);
|
||||
if (r != CMD_ERROR) break;
|
||||
ret = DoCommandByTile(0, i, 0, DC_QUERY_COST, CMD_BUILD_ROAD_VEH);
|
||||
if (!CmdFailed(ret)) break;
|
||||
}
|
||||
// We did not find a vehicle :(
|
||||
if (r == CMD_ERROR) { return -1; }
|
||||
if (CmdFailed(ret)) { return -1; }
|
||||
return i;
|
||||
}
|
||||
}
|
||||
@@ -233,25 +237,24 @@ int AiNew_Build_Vehicle(Player *p, uint tile, byte flag) {
|
||||
int i = AiNew_PickVehicle(p);
|
||||
if (i == -1) return CMD_ERROR;
|
||||
|
||||
if (p->ainew.tbt == AI_TRAIN) {
|
||||
if (p->ainew.tbt == AI_TRAIN)
|
||||
return CMD_ERROR;
|
||||
} else {
|
||||
return DoCommandByTile(tile, i, 0, flag, CMD_BUILD_ROAD_VEH);
|
||||
}
|
||||
|
||||
return DoCommandByTile(tile, i, 0, flag, CMD_BUILD_ROAD_VEH);
|
||||
}
|
||||
|
||||
int AiNew_Build_Depot(Player *p, uint tile, byte direction, byte flag) {
|
||||
int AiNew_Build_Depot(Player *p, uint tile, byte direction, byte flag)
|
||||
{
|
||||
static const byte _roadbits_by_dir[4] = {2,1,8,4};
|
||||
int r, r2;
|
||||
if (p->ainew.tbt == AI_TRAIN) {
|
||||
int ret, ret2;
|
||||
if (p->ainew.tbt == AI_TRAIN)
|
||||
return DoCommandByTile(tile, 0, direction, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_TRAIN_DEPOT);
|
||||
} else {
|
||||
r = DoCommandByTile(tile, direction, 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD_DEPOT);
|
||||
if (r == CMD_ERROR) return r;
|
||||
// Try to build the road from the depot
|
||||
r2 = DoCommandByTile(tile + _tileoffs_by_dir[direction], _roadbits_by_dir[direction], 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD);
|
||||
// If it fails, ignore it..
|
||||
if (r2 == CMD_ERROR) return r;
|
||||
return r + r2;
|
||||
}
|
||||
|
||||
ret = DoCommandByTile(tile, direction, 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD_DEPOT);
|
||||
if (CmdFailed(ret)) return ret;
|
||||
// Try to build the road from the depot
|
||||
ret2 = DoCommandByTile(tile + TileOffsByDir(direction), _roadbits_by_dir[direction], 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD);
|
||||
// If it fails, ignore it..
|
||||
if (CmdFailed(ret2)) return ret;
|
||||
return ret + ret2;
|
||||
}
|
||||
|
||||
@@ -9,12 +9,18 @@
|
||||
// TODO: als er iets in path komt, bouwt AI gewoon verder :(
|
||||
// TODO: mail routes
|
||||
|
||||
// FIXME: This code is horrible. Indisputably from the style POV, at least. --pasky
|
||||
|
||||
/*
|
||||
* End of Dutch part
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "ttd.h"
|
||||
#include "debug.h"
|
||||
#include "table/strings.h"
|
||||
#include "map.h"
|
||||
#include "tile.h"
|
||||
#include "command.h"
|
||||
#include "ai.h"
|
||||
#include "town.h"
|
||||
@@ -22,6 +28,7 @@
|
||||
#include "station.h"
|
||||
#include "engine.h"
|
||||
#include "gui.h"
|
||||
#include "depot.h"
|
||||
|
||||
// This function is called after StartUp. It is the init of an AI
|
||||
static void AiNew_State_FirstTime(Player *p) {
|
||||
@@ -79,15 +86,15 @@ static void AiNew_State_Nothing(Player *p) {
|
||||
// - Check route
|
||||
// - Build HQ
|
||||
static void AiNew_State_WakeUp(Player *p) {
|
||||
int32 money;
|
||||
int c;
|
||||
assert(p->ainew.state == AI_STATE_WAKE_UP);
|
||||
int32 money;
|
||||
int c;
|
||||
assert(p->ainew.state == AI_STATE_WAKE_UP);
|
||||
// First, check if we have a HQ
|
||||
if (p->location_of_house == 0) {
|
||||
// We have no HQ yet, build one on a random place
|
||||
// Random till we found a place for it!
|
||||
// TODO: this should not be on a random place..
|
||||
while (!AiNew_Build_CompanyHQ(p, (Random()&0xFFFF))) { }
|
||||
AiNew_Build_CompanyHQ(p, Random() % MapSize());
|
||||
// Enough for now, but we want to come back here the next time
|
||||
// so we do not change any status
|
||||
return;
|
||||
@@ -176,16 +183,16 @@ static void AiNew_State_WakeUp(Player *p) {
|
||||
}
|
||||
|
||||
static void AiNew_State_ActionDone(Player *p) {
|
||||
p->ainew.action = AI_ACTION_NONE;
|
||||
p->ainew.state = AI_STATE_NOTHING;
|
||||
p->ainew.action = AI_ACTION_NONE;
|
||||
p->ainew.state = AI_STATE_NOTHING;
|
||||
}
|
||||
|
||||
// Check if a city or industry is good enough to start a route there
|
||||
static bool AiNew_Check_City_or_Industry(Player *p, int ic, byte type) {
|
||||
if (type == AI_CITY) {
|
||||
Town *t = DEREF_TOWN(ic);
|
||||
Town *t = GetTown(ic);
|
||||
Station *st;
|
||||
int count = 0;
|
||||
uint count = 0;
|
||||
int j = 0;
|
||||
|
||||
// We don't like roadconstructions, don't even true such a city
|
||||
@@ -221,7 +228,7 @@ static bool AiNew_Check_City_or_Industry(Player *p, int ic, byte type) {
|
||||
// to build there
|
||||
if (!st->goods[CT_PASSENGERS].last_speed) continue;
|
||||
// Is it around our city
|
||||
if (GetTileDist(st->xy, t->xy) > 10) continue;
|
||||
if (DistanceManhattan(st->xy, t->xy) > 10) continue;
|
||||
// It does take this cargo.. what is his rating?
|
||||
if (st->goods[CT_PASSENGERS].rating < AI_CHECKCITY_CARGO_RATING) continue;
|
||||
j++;
|
||||
@@ -245,7 +252,7 @@ static bool AiNew_Check_City_or_Industry(Player *p, int ic, byte type) {
|
||||
return true;
|
||||
}
|
||||
if (type == AI_INDUSTRY) {
|
||||
Industry *i = DEREF_INDUSTRY(ic);
|
||||
Industry *i = GetIndustry(ic);
|
||||
Station *st;
|
||||
int count = 0;
|
||||
int j = 0;
|
||||
@@ -284,7 +291,7 @@ static bool AiNew_Check_City_or_Industry(Player *p, int ic, byte type) {
|
||||
// It does not take this cargo
|
||||
if (!st->goods[i->produced_cargo[0]].last_speed) continue;
|
||||
// Is it around our industry
|
||||
if (GetTileDist(st->xy, i->xy) > 5) continue;
|
||||
if (DistanceManhattan(st->xy, i->xy) > 5) continue;
|
||||
// It does take this cargo.. what is his rating?
|
||||
if (st->goods[i->produced_cargo[0]].rating < AI_CHECKCITY_CARGO_RATING) continue;
|
||||
j++;
|
||||
@@ -363,11 +370,11 @@ static void AiNew_State_LocateRoute(Player *p) {
|
||||
// increase the temp with one, and return. We will come back later here
|
||||
// to try again
|
||||
p->ainew.temp++;
|
||||
if (p->ainew.from_type == AI_CITY) {
|
||||
if (p->ainew.temp >= _total_towns) p->ainew.temp = 0;
|
||||
} else {
|
||||
if (p->ainew.temp >= _total_industries) p->ainew.temp = 0;
|
||||
}
|
||||
if (p->ainew.from_type == AI_CITY) {
|
||||
if (p->ainew.temp >= (int)_total_towns) p->ainew.temp = 0;
|
||||
} else {
|
||||
if (p->ainew.temp >= _total_industries) p->ainew.temp = 0;
|
||||
}
|
||||
|
||||
// Don't do an attempt if we are trying the same id as the last time...
|
||||
if (p->ainew.last_id == p->ainew.temp) return;
|
||||
@@ -403,16 +410,21 @@ static void AiNew_State_LocateRoute(Player *p) {
|
||||
// is.
|
||||
|
||||
if (p->ainew.from_type == AI_CITY && p->ainew.tbt == AI_BUS) {
|
||||
int max_cargo = DEREF_TOWN(p->ainew.from_ic)->max_pass + DEREF_TOWN(p->ainew.temp)->max_pass;
|
||||
max_cargo -= DEREF_TOWN(p->ainew.from_ic)->act_pass + DEREF_TOWN(p->ainew.temp)->act_pass;
|
||||
int max_cargo = GetTown(p->ainew.from_ic)->max_pass + GetTown(p->ainew.temp)->max_pass;
|
||||
max_cargo -= GetTown(p->ainew.from_ic)->act_pass + GetTown(p->ainew.temp)->act_pass;
|
||||
// max_cargo is now the amount of cargo we can move between the two cities
|
||||
// If it is more then the distance, we allow it
|
||||
if (GetTileDist(DEREF_TOWN(p->ainew.from_ic)->xy, DEREF_TOWN(p->ainew.temp)->xy) <= max_cargo * AI_LOCATEROUTE_BUS_CARGO_DISTANCE) {
|
||||
// If it is more than the distance, we allow it
|
||||
if (DistanceManhattan(GetTown(p->ainew.from_ic)->xy, GetTown(p->ainew.temp)->xy) <= max_cargo * AI_LOCATEROUTE_BUS_CARGO_DISTANCE) {
|
||||
// We found a good city/industry, save the data of it
|
||||
p->ainew.to_ic = p->ainew.temp;
|
||||
p->ainew.state = AI_STATE_FIND_STATION;
|
||||
|
||||
DEBUG(ai,1)("[AiNew - LocateRoute] Found bus-route of %d tiles long (from %d to %d)",GetTileDist(DEREF_TOWN(p->ainew.from_ic)->xy, DEREF_TOWN(p->ainew.temp)->xy), p->ainew.from_ic, p->ainew.temp);
|
||||
DEBUG(ai,1)(
|
||||
"[AiNew - LocateRoute] Found bus-route of %d tiles long (from %d to %d)",
|
||||
DistanceManhattan(GetTown(p->ainew.from_ic)->xy, GetTown(p->ainew.temp)->xy),
|
||||
p->ainew.from_ic,
|
||||
p->ainew.temp
|
||||
);
|
||||
|
||||
p->ainew.from_tile = 0;
|
||||
p->ainew.to_tile = 0;
|
||||
@@ -425,12 +437,12 @@ static void AiNew_State_LocateRoute(Player *p) {
|
||||
int i;
|
||||
// TODO: in max_cargo, also check other cargo (beside [0])
|
||||
// First we check if the from_ic produces cargo that this ic accepts
|
||||
if (DEREF_INDUSTRY(p->ainew.from_ic)->produced_cargo[0] != 0xFF && DEREF_INDUSTRY(p->ainew.from_ic)->total_production[0] != 0) {
|
||||
if (GetIndustry(p->ainew.from_ic)->produced_cargo[0] != 0xFF && GetIndustry(p->ainew.from_ic)->total_production[0] != 0) {
|
||||
for (i=0;i<3;i++) {
|
||||
if (DEREF_INDUSTRY(p->ainew.temp)->accepts_cargo[i] == 0xFF) break;
|
||||
if (DEREF_INDUSTRY(p->ainew.from_ic)->produced_cargo[0] == DEREF_INDUSTRY(p->ainew.temp)->accepts_cargo[i]) {
|
||||
if (GetIndustry(p->ainew.temp)->accepts_cargo[i] == 0xFF) break;
|
||||
if (GetIndustry(p->ainew.from_ic)->produced_cargo[0] == GetIndustry(p->ainew.temp)->accepts_cargo[i]) {
|
||||
// Found a compatbiel industry
|
||||
max_cargo = DEREF_INDUSTRY(p->ainew.from_ic)->total_production[0] - DEREF_INDUSTRY(p->ainew.from_ic)->total_transported[0];
|
||||
max_cargo = GetIndustry(p->ainew.from_ic)->total_production[0] - GetIndustry(p->ainew.from_ic)->total_transported[0];
|
||||
found = true;
|
||||
p->ainew.from_deliver = true;
|
||||
p->ainew.to_deliver = false;
|
||||
@@ -438,14 +450,14 @@ static void AiNew_State_LocateRoute(Player *p) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found && DEREF_INDUSTRY(p->ainew.temp)->produced_cargo[0] != 0xFF && DEREF_INDUSTRY(p->ainew.temp)->total_production[0] != 0) {
|
||||
if (!found && GetIndustry(p->ainew.temp)->produced_cargo[0] != 0xFF && GetIndustry(p->ainew.temp)->total_production[0] != 0) {
|
||||
// If not check if the current ic produces cargo that the from_ic accepts
|
||||
for (i=0;i<3;i++) {
|
||||
if (DEREF_INDUSTRY(p->ainew.from_ic)->accepts_cargo[i] == 0xFF) break;
|
||||
if (DEREF_INDUSTRY(p->ainew.temp)->produced_cargo[0] == DEREF_INDUSTRY(p->ainew.from_ic)->accepts_cargo[i]) {
|
||||
if (GetIndustry(p->ainew.from_ic)->accepts_cargo[i] == 0xFF) break;
|
||||
if (GetIndustry(p->ainew.temp)->produced_cargo[0] == GetIndustry(p->ainew.from_ic)->accepts_cargo[i]) {
|
||||
// Found a compatbiel industry
|
||||
found = true;
|
||||
max_cargo = DEREF_INDUSTRY(p->ainew.temp)->total_production[0] - DEREF_INDUSTRY(p->ainew.from_ic)->total_transported[0];
|
||||
max_cargo = GetIndustry(p->ainew.temp)->total_production[0] - GetIndustry(p->ainew.from_ic)->total_transported[0];
|
||||
p->ainew.from_deliver = false;
|
||||
p->ainew.to_deliver = true;
|
||||
break;
|
||||
@@ -455,17 +467,22 @@ static void AiNew_State_LocateRoute(Player *p) {
|
||||
if (found) {
|
||||
// Yeah, they are compatible!!!
|
||||
// Check the length against the amount of goods
|
||||
if (GetTileDist(DEREF_INDUSTRY(p->ainew.from_ic)->xy, DEREF_INDUSTRY(p->ainew.temp)->xy) > AI_LOCATEROUTE_TRUCK_MIN_DISTANCE &&
|
||||
GetTileDist(DEREF_INDUSTRY(p->ainew.from_ic)->xy, DEREF_INDUSTRY(p->ainew.temp)->xy) <= max_cargo * AI_LOCATEROUTE_TRUCK_CARGO_DISTANCE) {
|
||||
if (DistanceManhattan(GetIndustry(p->ainew.from_ic)->xy, GetIndustry(p->ainew.temp)->xy) > AI_LOCATEROUTE_TRUCK_MIN_DISTANCE &&
|
||||
DistanceManhattan(GetIndustry(p->ainew.from_ic)->xy, GetIndustry(p->ainew.temp)->xy) <= max_cargo * AI_LOCATEROUTE_TRUCK_CARGO_DISTANCE) {
|
||||
p->ainew.to_ic = p->ainew.temp;
|
||||
if (p->ainew.from_deliver) {
|
||||
p->ainew.cargo = DEREF_INDUSTRY(p->ainew.from_ic)->produced_cargo[0];
|
||||
p->ainew.cargo = GetIndustry(p->ainew.from_ic)->produced_cargo[0];
|
||||
} else {
|
||||
p->ainew.cargo = DEREF_INDUSTRY(p->ainew.temp)->produced_cargo[0];
|
||||
p->ainew.cargo = GetIndustry(p->ainew.temp)->produced_cargo[0];
|
||||
}
|
||||
p->ainew.state = AI_STATE_FIND_STATION;
|
||||
|
||||
DEBUG(ai,1)("[AiNew - LocateRoute] Found truck-route of %d tiles long (from %d to %d)",GetTileDist(DEREF_INDUSTRY(p->ainew.from_ic)->xy, DEREF_INDUSTRY(p->ainew.temp)->xy), p->ainew.from_ic, p->ainew.temp);
|
||||
DEBUG(ai,1)(
|
||||
"[AiNew - LocateRoute] Found truck-route of %d tiles long (from %d to %d)",
|
||||
DistanceManhattan(GetIndustry(p->ainew.from_ic)->xy, GetIndustry(p->ainew.temp)->xy),
|
||||
p->ainew.from_ic,
|
||||
p->ainew.temp
|
||||
);
|
||||
|
||||
p->ainew.from_tile = 0;
|
||||
p->ainew.to_tile = 0;
|
||||
@@ -476,36 +493,35 @@ static void AiNew_State_LocateRoute(Player *p) {
|
||||
}
|
||||
}
|
||||
|
||||
// It was not a valid city
|
||||
// increase the temp with one, and return. We will come back later here
|
||||
// to try again
|
||||
p->ainew.temp++;
|
||||
if (p->ainew.to_type == AI_CITY) {
|
||||
if (p->ainew.temp >= _total_towns) p->ainew.temp = 0;
|
||||
} else {
|
||||
if (p->ainew.temp >= _total_industries) p->ainew.temp = 0;
|
||||
}
|
||||
// It was not a valid city
|
||||
// increase the temp with one, and return. We will come back later here
|
||||
// to try again
|
||||
p->ainew.temp++;
|
||||
if (p->ainew.to_type == AI_CITY) {
|
||||
if (p->ainew.temp >= (int)_total_towns) p->ainew.temp = 0;
|
||||
} else {
|
||||
if (p->ainew.temp >= _total_industries) p->ainew.temp = 0;
|
||||
}
|
||||
|
||||
// Don't do an attempt if we are trying the same id as the last time...
|
||||
if (p->ainew.last_id == p->ainew.temp) return;
|
||||
p->ainew.last_id = p->ainew.temp;
|
||||
}
|
||||
|
||||
// Check if there are not more then a certain amount of vehicles pointed to a certain
|
||||
// Check if there are not more than a certain amount of vehicles pointed to a certain
|
||||
// station. This to prevent 10 busses going to one station, which gives... problems ;)
|
||||
static bool AiNew_CheckVehicleStation(Player *p, Station *st) {
|
||||
int count = 0;
|
||||
Vehicle *v;
|
||||
uint16 *sched;
|
||||
uint16 ord;
|
||||
|
||||
// Also check if we don't have already a lot of busses to this city...
|
||||
FOR_ALL_VEHICLES(v) {
|
||||
if (v->owner == _current_player) {
|
||||
sched = v->schedule_ptr;
|
||||
while (sched != NULL && (ord=*sched++) != 0) {
|
||||
if ((ord & OT_MASK) == OT_GOTO_STATION && DEREF_STATION(ord >> 8) == st) {
|
||||
// This vehicle has this city in his list
|
||||
const Order *order;
|
||||
|
||||
FOR_VEHICLE_ORDERS(v, order) {
|
||||
if (order->type == OT_GOTO_STATION && GetStation(order->station) == st) {
|
||||
// This vehicle has this city in its list
|
||||
count++;
|
||||
}
|
||||
}
|
||||
@@ -516,9 +532,6 @@ static bool AiNew_CheckVehicleStation(Player *p, Station *st) {
|
||||
return true;
|
||||
}
|
||||
|
||||
extern const byte _roadveh_speed[88];
|
||||
extern const byte _roadveh_capacity[88];
|
||||
|
||||
// This function finds a good spot for a station
|
||||
static void AiNew_State_FindStation(Player *p) {
|
||||
TileIndex tile;
|
||||
@@ -533,19 +546,19 @@ static void AiNew_State_FindStation(Player *p) {
|
||||
if (p->ainew.from_tile == 0) {
|
||||
// First we scan for a station in the from-city
|
||||
if (p->ainew.from_type == AI_CITY) {
|
||||
town = DEREF_TOWN(p->ainew.from_ic);
|
||||
town = GetTown(p->ainew.from_ic);
|
||||
tile = town->xy;
|
||||
} else {
|
||||
industry = DEREF_INDUSTRY(p->ainew.from_ic);
|
||||
industry = GetIndustry(p->ainew.from_ic);
|
||||
tile = industry->xy;
|
||||
}
|
||||
} else if (p->ainew.to_tile == 0) {
|
||||
// Second we scan for a station in the to-city
|
||||
if (p->ainew.to_type == AI_CITY) {
|
||||
town = DEREF_TOWN(p->ainew.to_ic);
|
||||
town = GetTown(p->ainew.to_ic);
|
||||
tile = town->xy;
|
||||
} else {
|
||||
industry = DEREF_INDUSTRY(p->ainew.to_ic);
|
||||
industry = GetIndustry(p->ainew.to_ic);
|
||||
tile = industry->xy;
|
||||
}
|
||||
} else {
|
||||
@@ -558,7 +571,7 @@ static void AiNew_State_FindStation(Player *p) {
|
||||
|
||||
// First, we are going to look at the stations that already exist inside the city
|
||||
// If there is enough cargo left in the station, we take that station
|
||||
// If that is not possible, and there are more then 2 stations in the city, abort
|
||||
// If that is not possible, and there are more than 2 stations in the city, abort
|
||||
i = AiNew_PickVehicle(p);
|
||||
// Euhmz, this should not happen _EVER_
|
||||
// Quit finding a route...
|
||||
@@ -570,7 +583,7 @@ static void AiNew_State_FindStation(Player *p) {
|
||||
if (p->ainew.tbt == AI_BUS && (FACIL_BUS_STOP & st->facilities) == FACIL_BUS_STOP) {
|
||||
if (st->town == town) {
|
||||
// Check how much cargo there is left in the station
|
||||
if ((st->goods[p->ainew.cargo].waiting_acceptance & 0xFFF) > _roadveh_capacity[i-ROAD_ENGINES_INDEX] * AI_STATION_REUSE_MULTIPLER) {
|
||||
if ((st->goods[p->ainew.cargo].waiting_acceptance & 0xFFF) > RoadVehInfo(i)->capacity * AI_STATION_REUSE_MULTIPLER) {
|
||||
if (AiNew_CheckVehicleStation(p, st)) {
|
||||
// We did found a station that was good enough!
|
||||
new_tile = st->xy;
|
||||
@@ -588,7 +601,7 @@ static void AiNew_State_FindStation(Player *p) {
|
||||
}
|
||||
// We are going to add a new station...
|
||||
if (new_tile == 0) count++;
|
||||
// No more then 2 stations allowed in a city
|
||||
// No more than 2 stations allowed in a city
|
||||
// This is because only the best 2 stations of one cargo do get any cargo
|
||||
if (count > 2) {
|
||||
p->ainew.state = AI_STATE_NOTHING;
|
||||
@@ -606,13 +619,14 @@ static void AiNew_State_FindStation(Player *p) {
|
||||
// where we get the most cargo and where it is buildable.
|
||||
// TODO: also check for station of myself and make sure we are not
|
||||
// taking eachothers passangers away (bad result when it does not)
|
||||
for (x = GET_TILE_X(tile) - AI_FINDSTATION_TILE_RANGE; x <= GET_TILE_X(tile) + AI_FINDSTATION_TILE_RANGE; x++) {
|
||||
for (y = GET_TILE_Y(tile) - AI_FINDSTATION_TILE_RANGE; y <= GET_TILE_Y(tile) + AI_FINDSTATION_TILE_RANGE; y++) {
|
||||
for (x = TileX(tile) - AI_FINDSTATION_TILE_RANGE; x <= TileX(tile) + AI_FINDSTATION_TILE_RANGE; x++) {
|
||||
for (y = TileY(tile) - AI_FINDSTATION_TILE_RANGE; y <= TileY(tile) + AI_FINDSTATION_TILE_RANGE; y++) {
|
||||
new_tile = TILE_XY(x,y);
|
||||
if (IS_TILETYPE(new_tile, MP_CLEAR) || IS_TILETYPE(new_tile, MP_TREES)) {
|
||||
if (IsTileType(new_tile, MP_CLEAR) || IsTileType(new_tile, MP_TREES)) {
|
||||
// This tile we can build on!
|
||||
// Check acceptance
|
||||
GetAcceptanceAroundTiles(accepts, new_tile, 1, 1);
|
||||
// XXX - Get the catchment area
|
||||
GetAcceptanceAroundTiles(accepts, new_tile, 1, 1, 4);
|
||||
// >> 3 == 0 means no cargo
|
||||
if (accepts[p->ainew.cargo] >> 3 == 0) continue;
|
||||
// See if we can build the station
|
||||
@@ -637,7 +651,7 @@ static void AiNew_State_FindStation(Player *p) {
|
||||
|
||||
for (x=0;x<i;x++) {
|
||||
if (found_best[x] > best ||
|
||||
(found_best[x] == best && GetTileDist(tile, new_tile) > GetTileDist(tile, found_spot[x]))) {
|
||||
(found_best[x] == best && DistanceManhattan(tile, new_tile) > DistanceManhattan(tile, found_spot[x]))) {
|
||||
new_tile = found_spot[x];
|
||||
best = found_best[x];
|
||||
}
|
||||
@@ -681,8 +695,8 @@ static void AiNew_State_FindPath(Player *p) {
|
||||
// Init path_info
|
||||
if (p->ainew.from_tile == AI_STATION_RANGE) {
|
||||
// For truck routes we take a range around the industry
|
||||
p->ainew.path_info.start_tile_tl = DEREF_INDUSTRY(p->ainew.from_ic)->xy - TILE_XY(1,1);
|
||||
p->ainew.path_info.start_tile_br = DEREF_INDUSTRY(p->ainew.from_ic)->xy + TILE_XY(DEREF_INDUSTRY(p->ainew.from_ic)->width, DEREF_INDUSTRY(p->ainew.from_ic)->height) + TILE_XY(1,1);
|
||||
p->ainew.path_info.start_tile_tl = GetIndustry(p->ainew.from_ic)->xy - TILE_XY(1,1);
|
||||
p->ainew.path_info.start_tile_br = GetIndustry(p->ainew.from_ic)->xy + TILE_XY(GetIndustry(p->ainew.from_ic)->width, GetIndustry(p->ainew.from_ic)->height) + TILE_XY(1,1);
|
||||
p->ainew.path_info.start_direction = p->ainew.from_direction;
|
||||
} else {
|
||||
p->ainew.path_info.start_tile_tl = p->ainew.from_tile;
|
||||
@@ -691,8 +705,8 @@ static void AiNew_State_FindPath(Player *p) {
|
||||
}
|
||||
|
||||
if (p->ainew.to_tile == AI_STATION_RANGE) {
|
||||
p->ainew.path_info.end_tile_tl = DEREF_INDUSTRY(p->ainew.to_ic)->xy - TILE_XY(1,1);
|
||||
p->ainew.path_info.end_tile_br = DEREF_INDUSTRY(p->ainew.to_ic)->xy + TILE_XY(DEREF_INDUSTRY(p->ainew.to_ic)->width, DEREF_INDUSTRY(p->ainew.to_ic)->height) + TILE_XY(1,1);
|
||||
p->ainew.path_info.end_tile_tl = GetIndustry(p->ainew.to_ic)->xy - TILE_XY(1,1);
|
||||
p->ainew.path_info.end_tile_br = GetIndustry(p->ainew.to_ic)->xy + TILE_XY(GetIndustry(p->ainew.to_ic)->width, GetIndustry(p->ainew.to_ic)->height) + TILE_XY(1,1);
|
||||
p->ainew.path_info.end_direction = p->ainew.to_direction;
|
||||
} else {
|
||||
p->ainew.path_info.end_tile_tl = p->ainew.to_tile;
|
||||
@@ -744,16 +758,16 @@ static void AiNew_State_FindDepot(Player *p) {
|
||||
|
||||
for (i=2;i<p->ainew.path_info.route_length-2;i++) {
|
||||
tile = p->ainew.path_info.route[i];
|
||||
for (j=0;j<lengthof(_tileoffs_by_dir);j++) {
|
||||
if (IS_TILETYPE(tile + _tileoffs_by_dir[j], MP_STREET)) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
if (IsTileType(tile + TileOffsByDir(j), MP_STREET)) {
|
||||
// Its a street, test if it is a depot
|
||||
if (_map5[tile + _tileoffs_by_dir[j]] & 0x20) {
|
||||
if (_map5[tile + TileOffsByDir(j)] & 0x20) {
|
||||
// We found a depot, is it ours? (TELL ME!!!)
|
||||
if (_map_owner[tile + _tileoffs_by_dir[j]] == _current_player) {
|
||||
if (_map_owner[tile + TileOffsByDir(j)] == _current_player) {
|
||||
// Now, is it pointing to the right direction.........
|
||||
if ((_map5[tile + _tileoffs_by_dir[j]] & 3) == (j ^ 2)) {
|
||||
if ((_map5[tile + TileOffsByDir(j)] & 3) == (j ^ 2)) {
|
||||
// Yeah!!!
|
||||
p->ainew.depot_tile = tile + _tileoffs_by_dir[j];
|
||||
p->ainew.depot_tile = tile + TileOffsByDir(j);
|
||||
p->ainew.depot_direction = j ^ 2; // Reverse direction
|
||||
p->ainew.state = AI_STATE_VERIFY_ROUTE;
|
||||
return;
|
||||
@@ -780,28 +794,28 @@ static void AiNew_State_FindDepot(Player *p) {
|
||||
|
||||
tile = p->ainew.path_info.route[i];
|
||||
|
||||
for (j=0;j<lengthof(_tileoffs_by_dir);j++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
// It may not be placed on the road/rail itself
|
||||
// And because it is not build yet, we can't see it on the tile..
|
||||
// So check the surrounding tiles :)
|
||||
if (tile + _tileoffs_by_dir[j] == p->ainew.path_info.route[i-1] ||
|
||||
tile + _tileoffs_by_dir[j] == p->ainew.path_info.route[i+1]) continue;
|
||||
if (tile + TileOffsByDir(j) == p->ainew.path_info.route[i-1] ||
|
||||
tile + TileOffsByDir(j) == p->ainew.path_info.route[i+1]) continue;
|
||||
// Not around a bridge?
|
||||
if (p->ainew.path_info.route_extra[i] != 0) continue;
|
||||
if (IS_TILETYPE(tile, MP_TUNNELBRIDGE)) continue;
|
||||
if (IsTileType(tile, MP_TUNNELBRIDGE)) continue;
|
||||
// Is the terrain clear?
|
||||
if (IS_TILETYPE(tile + _tileoffs_by_dir[j], MP_CLEAR) ||
|
||||
IS_TILETYPE(tile + _tileoffs_by_dir[j], MP_TREES)) {
|
||||
if (IsTileType(tile + TileOffsByDir(j), MP_CLEAR) ||
|
||||
IsTileType(tile + TileOffsByDir(j), MP_TREES)) {
|
||||
TileInfo ti;
|
||||
FindLandscapeHeightByTile(&ti, tile);
|
||||
// If the current tile is on a slope (tileh != 0) then we do not allow this
|
||||
if (ti.tileh != 0) continue;
|
||||
// Check if everything went okay..
|
||||
r = AiNew_Build_Depot(p, tile + _tileoffs_by_dir[j], j ^ 2, 0);
|
||||
r = AiNew_Build_Depot(p, tile + TileOffsByDir(j), j ^ 2, 0);
|
||||
if (r == CMD_ERROR) continue;
|
||||
// Found a spot!
|
||||
p->ainew.new_cost += r;
|
||||
p->ainew.depot_tile = tile + _tileoffs_by_dir[j];
|
||||
p->ainew.depot_tile = tile + TileOffsByDir(j);
|
||||
p->ainew.depot_direction = j ^ 2; // Reverse direction
|
||||
p->ainew.state = AI_STATE_VERIFY_ROUTE;
|
||||
return;
|
||||
@@ -829,11 +843,10 @@ static int AiNew_HowManyVehicles(Player *p) {
|
||||
// Passenger run.. how long is the route?
|
||||
length = p->ainew.path_info.route_length;
|
||||
// Calculating tiles a day a vehicle moves is not easy.. this is how it must be done!
|
||||
// ROAD_ENGINES_INDEX is because the first roadveh engine is ROAD_ENGINES_INDEX, and _roadveh_speed starts from 0
|
||||
tiles_a_day = _roadveh_speed[i-ROAD_ENGINES_INDEX] * DAY_TICKS / 256 / 16;
|
||||
tiles_a_day = RoadVehInfo(i)->max_speed * DAY_TICKS / 256 / 16;
|
||||
// We want a vehicle in a station once a month at least, so, calculate it!
|
||||
// (the * 2 is because we have 2 stations ;))
|
||||
amount = ((int)(((float)length / (float)tiles_a_day / 30 * 2))) * 2;
|
||||
amount = length * 2 * 2 / tiles_a_day / 30;
|
||||
if (amount == 0) amount = 1;
|
||||
return amount;
|
||||
} else if (p->ainew.tbt == AI_TRUCK) {
|
||||
@@ -845,19 +858,18 @@ static int AiNew_HowManyVehicles(Player *p) {
|
||||
// Passenger run.. how long is the route?
|
||||
length = p->ainew.path_info.route_length;
|
||||
// Calculating tiles a day a vehicle moves is not easy.. this is how it must be done!
|
||||
// ROAD_ENGINES_INDEX is because the first roadveh engine is ROAD_ENGINES_INDEX, and _roadveh_speed starts from 0
|
||||
tiles_a_day = _roadveh_speed[i-ROAD_ENGINES_INDEX] * DAY_TICKS / 256 / 16;
|
||||
tiles_a_day = RoadVehInfo(i)->max_speed * DAY_TICKS / 256 / 16;
|
||||
if (p->ainew.from_deliver)
|
||||
max_cargo = DEREF_INDUSTRY(p->ainew.from_ic)->total_production[0];
|
||||
max_cargo = GetIndustry(p->ainew.from_ic)->total_production[0];
|
||||
else
|
||||
max_cargo = DEREF_INDUSTRY(p->ainew.to_ic)->total_production[0];
|
||||
max_cargo = GetIndustry(p->ainew.to_ic)->total_production[0];
|
||||
|
||||
// This is because moving 60% is more then we can dream of!
|
||||
// This is because moving 60% is more than we can dream of!
|
||||
max_cargo *= 0.6;
|
||||
// We want all the cargo to be gone in a month.. so, we know the cargo it delivers
|
||||
// we know what the vehicle takes with him, and we know the time it takes him
|
||||
// to get back here.. now let's do some math!
|
||||
amount = (int)(((float)length / (float)tiles_a_day / 30 * 2) * ((float)max_cargo / (float)_roadveh_capacity[i-ROAD_ENGINES_INDEX]));
|
||||
amount = 2 * length * max_cargo / tiles_a_day / 30 / RoadVehInfo(i)->capacity;
|
||||
amount += 1;
|
||||
return amount;
|
||||
} else {
|
||||
@@ -932,11 +944,11 @@ static void AiNew_State_BuildStation(Player *p) {
|
||||
int res = 0;
|
||||
assert(p->ainew.state == AI_STATE_BUILD_STATION);
|
||||
if (p->ainew.temp == 0) {
|
||||
if (!IS_TILETYPE(p->ainew.from_tile, MP_STATION))
|
||||
if (!IsTileType(p->ainew.from_tile, MP_STATION))
|
||||
res = AiNew_Build_Station(p, p->ainew.tbt, p->ainew.from_tile, 0, 0, p->ainew.from_direction, DC_EXEC);
|
||||
}
|
||||
else {
|
||||
if (!IS_TILETYPE(p->ainew.to_tile, MP_STATION))
|
||||
if (!IsTileType(p->ainew.to_tile, MP_STATION))
|
||||
res = AiNew_Build_Station(p, p->ainew.tbt, p->ainew.to_tile, 0, 0, p->ainew.to_direction, DC_EXEC);
|
||||
p->ainew.state = AI_STATE_BUILD_PATH;
|
||||
}
|
||||
@@ -982,17 +994,17 @@ static void AiNew_State_BuildPath(Player *p) {
|
||||
// We don't want that, so try building some road left or right of the station
|
||||
int dir1, dir2, dir3;
|
||||
TileIndex tile;
|
||||
int i, r;
|
||||
int i, ret;
|
||||
for (i=0;i<2;i++) {
|
||||
if (i == 0) {
|
||||
tile = p->ainew.from_tile + _tileoffs_by_dir[p->ainew.from_direction];
|
||||
tile = p->ainew.from_tile + TileOffsByDir(p->ainew.from_direction);
|
||||
dir1 = p->ainew.from_direction - 1;
|
||||
if (dir1 < 0) dir1 = 3;
|
||||
dir2 = p->ainew.from_direction + 1;
|
||||
if (dir2 > 3) dir2 = 0;
|
||||
dir3 = p->ainew.from_direction;
|
||||
} else {
|
||||
tile = p->ainew.to_tile + _tileoffs_by_dir[p->ainew.to_direction];
|
||||
tile = p->ainew.to_tile + TileOffsByDir(p->ainew.to_direction);
|
||||
dir1 = p->ainew.to_direction - 1;
|
||||
if (dir1 < 0) dir1 = 3;
|
||||
dir2 = p->ainew.to_direction + 1;
|
||||
@@ -1000,37 +1012,37 @@ static void AiNew_State_BuildPath(Player *p) {
|
||||
dir3 = p->ainew.to_direction;
|
||||
}
|
||||
|
||||
r = DoCommandByTile(tile, _roadbits_by_dir[dir1], 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
|
||||
if (r != CMD_ERROR) {
|
||||
dir1 = _tileoffs_by_dir[dir1];
|
||||
if (IS_TILETYPE(tile+dir1, MP_CLEAR) || IS_TILETYPE(tile+dir1, MP_TREES)) {
|
||||
r = DoCommandByTile(tile+dir1, AiNew_GetRoadDirection(tile, tile+dir1, tile+dir1+dir1), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
|
||||
if (r != CMD_ERROR) {
|
||||
if (IS_TILETYPE(tile+dir1+dir1, MP_CLEAR) || IS_TILETYPE(tile+dir1+dir1, MP_TREES))
|
||||
ret = DoCommandByTile(tile, _roadbits_by_dir[dir1], 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
|
||||
if (!CmdFailed(ret)) {
|
||||
dir1 = TileOffsByDir(dir1);
|
||||
if (IsTileType(tile + dir1, MP_CLEAR) || IsTileType(tile + dir1, MP_TREES)) {
|
||||
ret = DoCommandByTile(tile+dir1, AiNew_GetRoadDirection(tile, tile+dir1, tile+dir1+dir1), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
|
||||
if (!CmdFailed(ret)) {
|
||||
if (IsTileType(tile + dir1 + dir1, MP_CLEAR) || IsTileType(tile + dir1 + dir1, MP_TREES))
|
||||
DoCommandByTile(tile+dir1+dir1, AiNew_GetRoadDirection(tile+dir1, tile+dir1+dir1, tile+dir1+dir1+dir1), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
r = DoCommandByTile(tile, _roadbits_by_dir[dir2], 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
|
||||
if (r != CMD_ERROR) {
|
||||
dir2 = _tileoffs_by_dir[dir2];
|
||||
if (IS_TILETYPE(tile+dir2, MP_CLEAR) || IS_TILETYPE(tile+dir2, MP_TREES)) {
|
||||
r = DoCommandByTile(tile+dir2, AiNew_GetRoadDirection(tile, tile+dir2, tile+dir2+dir2), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
|
||||
if (r != CMD_ERROR) {
|
||||
if (IS_TILETYPE(tile+dir2+dir2, MP_CLEAR) || IS_TILETYPE(tile+dir2+dir2, MP_TREES))
|
||||
ret = DoCommandByTile(tile, _roadbits_by_dir[dir2], 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
|
||||
if (!CmdFailed(ret)) {
|
||||
dir2 = TileOffsByDir(dir2);
|
||||
if (IsTileType(tile + dir2, MP_CLEAR) || IsTileType(tile + dir2, MP_TREES)) {
|
||||
ret = DoCommandByTile(tile+dir2, AiNew_GetRoadDirection(tile, tile+dir2, tile+dir2+dir2), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
|
||||
if (!CmdFailed(ret)) {
|
||||
if (IsTileType(tile + dir2 + dir2, MP_CLEAR) || IsTileType(tile + dir2 + dir2, MP_TREES))
|
||||
DoCommandByTile(tile+dir2+dir2, AiNew_GetRoadDirection(tile+dir2, tile+dir2+dir2, tile+dir2+dir2+dir2), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
r = DoCommandByTile(tile, _roadbits_by_dir[dir3^2], 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
|
||||
if (r != CMD_ERROR) {
|
||||
dir3 = _tileoffs_by_dir[dir3];
|
||||
if (IS_TILETYPE(tile+dir3, MP_CLEAR) || IS_TILETYPE(tile+dir3, MP_TREES)) {
|
||||
r = DoCommandByTile(tile+dir3, AiNew_GetRoadDirection(tile, tile+dir3, tile+dir3+dir3), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
|
||||
if (r != CMD_ERROR) {
|
||||
if (IS_TILETYPE(tile+dir3+dir3, MP_CLEAR) || IS_TILETYPE(tile+dir3+dir3, MP_TREES))
|
||||
ret = DoCommandByTile(tile, _roadbits_by_dir[dir3^2], 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
|
||||
if (!CmdFailed(ret)) {
|
||||
dir3 = TileOffsByDir(dir3);
|
||||
if (IsTileType(tile + dir3, MP_CLEAR) || IsTileType(tile + dir3, MP_TREES)) {
|
||||
ret = DoCommandByTile(tile+dir3, AiNew_GetRoadDirection(tile, tile+dir3, tile+dir3+dir3), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
|
||||
if (!CmdFailed(ret)) {
|
||||
if (IsTileType(tile + dir3 + dir3, MP_CLEAR) || IsTileType(tile + dir3 + dir3, MP_TREES))
|
||||
DoCommandByTile(tile+dir3+dir3, AiNew_GetRoadDirection(tile+dir3, tile+dir3+dir3, tile+dir3+dir3+dir3), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
|
||||
}
|
||||
}
|
||||
@@ -1049,7 +1061,7 @@ static void AiNew_State_BuildDepot(Player *p) {
|
||||
int res = 0;
|
||||
assert(p->ainew.state == AI_STATE_BUILD_DEPOT);
|
||||
|
||||
if (IS_TILETYPE(p->ainew.depot_tile, MP_STREET) && _map5[p->ainew.depot_tile] & 0x20) {
|
||||
if (IsTileType(p->ainew.depot_tile, MP_STREET) && _map5[p->ainew.depot_tile] & 0x20) {
|
||||
if (_map_owner[p->ainew.depot_tile] == _current_player) {
|
||||
// The depot is already builded!
|
||||
p->ainew.state = AI_STATE_BUILD_VEHICLE;
|
||||
@@ -1062,7 +1074,7 @@ static void AiNew_State_BuildDepot(Player *p) {
|
||||
}
|
||||
|
||||
// There is a bus on the tile we want to build road on... idle till he is gone! (BAD PERSON! :p)
|
||||
if (!EnsureNoVehicle(p->ainew.depot_tile + _tileoffs_by_dir[p->ainew.depot_direction]))
|
||||
if (!EnsureNoVehicle(p->ainew.depot_tile + TileOffsByDir(p->ainew.depot_direction)))
|
||||
return;
|
||||
|
||||
res = AiNew_Build_Depot(p, p->ainew.depot_tile, p->ainew.depot_direction, DC_EXEC);
|
||||
@@ -1117,7 +1129,9 @@ static void AiNew_State_BuildVehicle(Player *p) {
|
||||
|
||||
// Put the stations in the order list
|
||||
static void AiNew_State_GiveOrders(Player *p) {
|
||||
int order, flags;
|
||||
int idx;
|
||||
Order order;
|
||||
|
||||
assert(p->ainew.state == AI_STATE_GIVE_ORDERS);
|
||||
|
||||
if (p->ainew.veh_main_id != (VehicleID)-1) {
|
||||
@@ -1133,24 +1147,30 @@ static void AiNew_State_GiveOrders(Player *p) {
|
||||
p->ainew.veh_main_id = p->ainew.veh_id;
|
||||
}
|
||||
|
||||
// When more then 1 vehicle, we send them to different directions
|
||||
order = 0;
|
||||
flags = (_map2[p->ainew.from_tile] << 8) | OT_GOTO_STATION;
|
||||
// When more than 1 vehicle, we send them to different directions
|
||||
idx = 0;
|
||||
order.type = OT_GOTO_STATION;
|
||||
order.flags = 0;
|
||||
order.station = _map2[p->ainew.from_tile];
|
||||
if (p->ainew.tbt == AI_TRUCK && p->ainew.from_deliver)
|
||||
flags |= OF_FULL_LOAD;
|
||||
DoCommandByTile(0, p->ainew.veh_id + (order << 16), flags, DC_EXEC, CMD_INSERT_ORDER);
|
||||
order.flags |= OF_FULL_LOAD;
|
||||
DoCommandByTile(0, p->ainew.veh_id + (idx << 16), PackOrder(&order), DC_EXEC, CMD_INSERT_ORDER);
|
||||
|
||||
order = 1;
|
||||
flags = (_map2[p->ainew.to_tile] << 8) | OT_GOTO_STATION;
|
||||
idx = 1;
|
||||
order.type = OT_GOTO_STATION;
|
||||
order.flags = 0;
|
||||
order.station = _map2[p->ainew.to_tile];
|
||||
if (p->ainew.tbt == AI_TRUCK && p->ainew.to_deliver)
|
||||
flags |= OF_FULL_LOAD;
|
||||
DoCommandByTile(0, p->ainew.veh_id + (order << 16), flags, DC_EXEC, CMD_INSERT_ORDER);
|
||||
order.flags |= OF_FULL_LOAD;
|
||||
DoCommandByTile(0, p->ainew.veh_id + (idx << 16), PackOrder(&order), DC_EXEC, CMD_INSERT_ORDER);
|
||||
|
||||
// Very handy for AI, goto depot.. but yeah, it needs to be activated ;)
|
||||
if (_patches.gotodepot) {
|
||||
order = 2;
|
||||
flags = (GetDepotByTile(p->ainew.depot_tile) << 8) | OT_GOTO_DEPOT | OF_UNLOAD;
|
||||
DoCommandByTile(0, p->ainew.veh_id + (order << 16), flags, DC_EXEC, CMD_INSERT_ORDER);
|
||||
idx = 2;
|
||||
order.type = OT_GOTO_DEPOT;
|
||||
order.flags = OF_UNLOAD;
|
||||
order.station = GetDepotByTile(p->ainew.depot_tile)->index;
|
||||
DoCommandByTile(0, p->ainew.veh_id + (idx << 16), PackOrder(&order), DC_EXEC, CMD_INSERT_ORDER);
|
||||
}
|
||||
|
||||
// Start the engines!
|
||||
@@ -1171,7 +1191,7 @@ static void AiNew_State_StartVehicle(Player *p) {
|
||||
static void AiNew_State_RepayMoney(Player *p) {
|
||||
int i;
|
||||
for (i=0;i<AI_LOAN_REPAY;i++)
|
||||
DoCommandByTile(0, _current_player, 0, DC_EXEC, CMD_DECREASE_LOAN);
|
||||
DoCommandByTile(0, 0, 0, DC_EXEC, CMD_DECREASE_LOAN);
|
||||
p->ainew.state = AI_STATE_ACTION_DONE;
|
||||
}
|
||||
|
||||
@@ -1181,7 +1201,7 @@ static void AiNew_CheckVehicle(Player *p, Vehicle *v) {
|
||||
|
||||
// When a vehicle is older then 1 year, it should make money...
|
||||
if (v->age > 360) {
|
||||
// If both years together are not more then AI_MINIMUM_ROUTE_PROFIT,
|
||||
// If both years together are not more than AI_MINIMUM_ROUTE_PROFIT,
|
||||
// it is not worth the line I guess...
|
||||
if (v->profit_last_year + v->profit_this_year < AI_MINIMUM_ROUTE_PROFIT ||
|
||||
(v->reliability * 100 >> 16) < 40) {
|
||||
@@ -1195,7 +1215,7 @@ static void AiNew_CheckVehicle(Player *p, Vehicle *v) {
|
||||
|
||||
// We are already sending him back
|
||||
if (AiNew_GetSpecialVehicleFlag(p, v) & AI_VEHICLEFLAG_SELL) {
|
||||
if (v->type == VEH_Road && IsRoadDepotTile(v->tile) &&
|
||||
if (v->type == VEH_Road && IsTileDepotType(v->tile, TRANSPORT_ROAD) &&
|
||||
(v->vehstatus&VS_STOPPED)) {
|
||||
// We are at the depot, sell the vehicle
|
||||
DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_SELL_ROAD_VEH);
|
||||
@@ -1205,11 +1225,11 @@ static void AiNew_CheckVehicle(Player *p, Vehicle *v) {
|
||||
|
||||
if (!AiNew_SetSpecialVehicleFlag(p, v, AI_VEHICLEFLAG_SELL)) return;
|
||||
{
|
||||
int res = 0;
|
||||
int ret = 0;
|
||||
if (v->type == VEH_Road)
|
||||
res = DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_SEND_ROADVEH_TO_DEPOT);
|
||||
ret = DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_SEND_ROADVEH_TO_DEPOT);
|
||||
// This means we can not find a depot :s
|
||||
// if (res == CMD_ERROR)
|
||||
// if (CmdFailed(ret))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+235
-192
@@ -1,55 +1,77 @@
|
||||
#include "stdafx.h"
|
||||
#include "ttd.h"
|
||||
#include "debug.h"
|
||||
#include "map.h"
|
||||
#include "tile.h"
|
||||
#include "command.h"
|
||||
#include "ai.h"
|
||||
#include "depot.h"
|
||||
|
||||
#define TEST_STATION_NO_DIR 0xFF
|
||||
|
||||
// Tests if a station can be build on the given spot
|
||||
// TODO: make it train compatible
|
||||
bool TestCanBuildStationHere(uint tile, byte dir) {
|
||||
Player *p = DEREF_PLAYER(_current_player);
|
||||
if (dir == TEST_STATION_NO_DIR) {
|
||||
// TODO: currently we only allow spots that can be access from al 4 directions...
|
||||
// should be fixed!!!
|
||||
for (dir=0;dir<4;dir++) {
|
||||
int res = AiNew_Build_Station(p, p->ainew.tbt, tile, 1, 1, dir, DC_QUERY_COST);
|
||||
if (res != CMD_ERROR)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
int res = AiNew_Build_Station(p, p->ainew.tbt, tile, 1, 1, dir, DC_QUERY_COST);
|
||||
if (res == CMD_ERROR)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
static bool TestCanBuildStationHere(uint tile, byte dir)
|
||||
{
|
||||
Player *p = DEREF_PLAYER(_current_player);
|
||||
|
||||
if (dir == TEST_STATION_NO_DIR) {
|
||||
int32 ret;
|
||||
// TODO: currently we only allow spots that can be access from al 4 directions...
|
||||
// should be fixed!!!
|
||||
for (dir = 0; dir < 4; dir++) {
|
||||
ret = AiNew_Build_Station(p, p->ainew.tbt, tile, 1, 1, dir, DC_QUERY_COST);
|
||||
if (!CmdFailed(ret)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// return true if command succeeded, so the inverse of CmdFailed()
|
||||
return !CmdFailed(AiNew_Build_Station(p, p->ainew.tbt, tile, 1, 1, dir, DC_QUERY_COST));
|
||||
}
|
||||
|
||||
|
||||
static bool IsRoad(TileIndex tile)
|
||||
{
|
||||
return
|
||||
// MP_STREET, but not a road depot?
|
||||
(IsTileType(tile, MP_STREET) && !IsTileDepotType(tile, TRANSPORT_ROAD)) ||
|
||||
(IsTileType(tile, MP_TUNNELBRIDGE) && (
|
||||
// road tunnel?
|
||||
((_map5[tile] & 0x80) == 0 && (_map5[tile] & 0x4) == 0x4) ||
|
||||
// road bridge?
|
||||
((_map5[tile] & 0x80) != 0 && (_map5[tile] & 0x2) == 0x2)
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
// Checks if a tile 'a' is between the tiles 'b' and 'c'
|
||||
#define TILES_BETWEEN(a,b,c) (GET_TILE_X(a) >= GET_TILE_X(b) && GET_TILE_X(a) <= GET_TILE_X(c) && GET_TILE_Y(a) >= GET_TILE_Y(b) && GET_TILE_Y(a) <= GET_TILE_Y(c))
|
||||
#define TILES_BETWEEN(a, b, c) (TileX(a) >= TileX(b) && TileX(a) <= TileX(c) && TileY(a) >= TileY(b) && TileY(a) <= TileY(c))
|
||||
|
||||
// Check if the current tile is in our end-area
|
||||
int32 AyStar_AiPathFinder_EndNodeCheck(AyStar *aystar, OpenListNode *current) {
|
||||
static int32 AyStar_AiPathFinder_EndNodeCheck(AyStar *aystar, OpenListNode *current)
|
||||
{
|
||||
Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
|
||||
// It is not allowed to have a station on the end of a bridge or tunnel ;)
|
||||
if (current->path.node.user_data[0] != 0) return AYSTAR_DONE;
|
||||
if (TILES_BETWEEN(current->path.node.tile, PathFinderInfo->end_tile_tl, PathFinderInfo->end_tile_br))
|
||||
if (IS_TILETYPE(current->path.node.tile, MP_CLEAR) || IS_TILETYPE(current->path.node.tile, MP_TREES))
|
||||
if (current->path.parent == NULL || TestCanBuildStationHere(current->path.node.tile,AiNew_GetDirection(current->path.parent->node.tile, current->path.node.tile)))
|
||||
return AYSTAR_FOUND_END_NODE;
|
||||
if (IsTileType(current->path.node.tile, MP_CLEAR) || IsTileType(current->path.node.tile, MP_TREES))
|
||||
if (current->path.parent == NULL || TestCanBuildStationHere(current->path.node.tile, AiNew_GetDirection(current->path.parent->node.tile, current->path.node.tile)))
|
||||
return AYSTAR_FOUND_END_NODE;
|
||||
|
||||
return AYSTAR_DONE;
|
||||
}
|
||||
|
||||
// Calculates the hash
|
||||
// Currently it is a 10 bit hash, so the hash array has a max depth of 6 bits (so 64)
|
||||
uint AiPathFinder_Hash(uint key1, uint key2) {
|
||||
return (GET_TILE_X(key1) & 0x1F) + ((GET_TILE_Y(key1) & 0x1F) << 5);
|
||||
static uint AiPathFinder_Hash(uint key1, uint key2)
|
||||
{
|
||||
return (TileX(key1) & 0x1F) + ((TileY(key1) & 0x1F) << 5);
|
||||
}
|
||||
|
||||
// Clear the memory of all the things
|
||||
void AyStar_AiPathFinder_Free(AyStar *aystar) {
|
||||
static void AyStar_AiPathFinder_Free(AyStar *aystar)
|
||||
{
|
||||
AyStarMain_Free(aystar);
|
||||
free(aystar);
|
||||
}
|
||||
@@ -60,9 +82,11 @@ static void AyStar_AiPathFinder_FoundEndNode(AyStar *aystar, OpenListNode *curre
|
||||
static void AyStar_AiPathFinder_GetNeighbours(AyStar *aystar, OpenListNode *current);
|
||||
|
||||
// This creates the AiPathFinder
|
||||
AyStar *new_AyStar_AiPathFinder(int max_tiles_around, Ai_PathFinderInfo *PathFinderInfo) {
|
||||
AyStar *new_AyStar_AiPathFinder(int max_tiles_around, Ai_PathFinderInfo *PathFinderInfo)
|
||||
{
|
||||
PathNode start_node;
|
||||
uint x,y;
|
||||
uint x;
|
||||
uint y;
|
||||
// Create AyStar
|
||||
AyStar *result = malloc(sizeof(AyStar));
|
||||
init_AyStar(result, AiPathFinder_Hash, 1 << 10);
|
||||
@@ -89,10 +113,10 @@ AyStar *new_AyStar_AiPathFinder(int max_tiles_around, Ai_PathFinderInfo *PathFin
|
||||
start_node.node.user_data[0] = 0;
|
||||
|
||||
// Now we add all the starting tiles
|
||||
for (x=GET_TILE_X(PathFinderInfo->start_tile_tl);x<=GET_TILE_X(PathFinderInfo->start_tile_br);x++) {
|
||||
for (y=GET_TILE_Y(PathFinderInfo->start_tile_tl);y<=GET_TILE_Y(PathFinderInfo->start_tile_br);y++) {
|
||||
start_node.node.tile = TILE_XY(x,y);
|
||||
result->addstart(result, &start_node.node);
|
||||
for (x = TileX(PathFinderInfo->start_tile_tl); x <= TileX(PathFinderInfo->start_tile_br); x++) {
|
||||
for (y = TileY(PathFinderInfo->start_tile_tl); y <= TileY(PathFinderInfo->start_tile_br); y++) {
|
||||
start_node.node.tile = TILE_XY(x, y);
|
||||
result->addstart(result, &start_node.node, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,9 +124,11 @@ AyStar *new_AyStar_AiPathFinder(int max_tiles_around, Ai_PathFinderInfo *PathFin
|
||||
}
|
||||
|
||||
// To reuse AyStar we sometimes have to clean all the memory
|
||||
void clean_AyStar_AiPathFinder(AyStar *aystar, Ai_PathFinderInfo *PathFinderInfo) {
|
||||
void clean_AyStar_AiPathFinder(AyStar *aystar, Ai_PathFinderInfo *PathFinderInfo)
|
||||
{
|
||||
PathNode start_node;
|
||||
uint x,y;
|
||||
uint x;
|
||||
uint y;
|
||||
|
||||
aystar->clear(aystar);
|
||||
|
||||
@@ -116,221 +142,230 @@ void clean_AyStar_AiPathFinder(AyStar *aystar, Ai_PathFinderInfo *PathFinderInfo
|
||||
start_node.node.tile = PathFinderInfo->start_tile_tl;
|
||||
|
||||
// Now we add all the starting tiles
|
||||
for (x=GET_TILE_X(PathFinderInfo->start_tile_tl);x<=GET_TILE_X(PathFinderInfo->start_tile_br);x++) {
|
||||
for (y=GET_TILE_Y(PathFinderInfo->start_tile_tl);y<=GET_TILE_Y(PathFinderInfo->start_tile_br);y++) {
|
||||
if (!(IS_TILETYPE(TILE_XY(x,y), MP_CLEAR) || IS_TILETYPE(TILE_XY(x,y), MP_TREES))) continue;
|
||||
if (!TestCanBuildStationHere(TILE_XY(x,y),TEST_STATION_NO_DIR)) continue;
|
||||
start_node.node.tile = TILE_XY(x,y);
|
||||
aystar->addstart(aystar, &start_node.node);
|
||||
for (x = TileX(PathFinderInfo->start_tile_tl); x <= TileX(PathFinderInfo->start_tile_br); x++) {
|
||||
for (y = TileY(PathFinderInfo->start_tile_tl); y <= TileY(PathFinderInfo->start_tile_br); y++) {
|
||||
if (!(IsTileType(TILE_XY(x, y), MP_CLEAR) || IsTileType(TILE_XY(x, y), MP_TREES))) continue;
|
||||
if (!TestCanBuildStationHere(TILE_XY(x, y), TEST_STATION_NO_DIR)) continue;
|
||||
start_node.node.tile = TILE_XY(x, y);
|
||||
aystar->addstart(aystar, &start_node.node, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The h-value, simple calculation
|
||||
static int32 AyStar_AiPathFinder_CalculateH(AyStar *aystar, AyStarNode *current, OpenListNode *parent) {
|
||||
static int32 AyStar_AiPathFinder_CalculateH(AyStar *aystar, AyStarNode *current, OpenListNode *parent)
|
||||
{
|
||||
Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
|
||||
int r, r2;
|
||||
if (PathFinderInfo->end_direction != AI_PATHFINDER_NO_DIRECTION) {
|
||||
// The station is pointing to a direction, add a tile towards that direction, so the H-value is more accurate
|
||||
r = GetTileDist(current->tile, PathFinderInfo->end_tile_tl + _tiles_around[PathFinderInfo->end_direction]);
|
||||
r2 = GetTileDist(current->tile, PathFinderInfo->end_tile_br + _tiles_around[PathFinderInfo->end_direction]);
|
||||
r = DistanceManhattan(current->tile, PathFinderInfo->end_tile_tl + TileOffsByDir(PathFinderInfo->end_direction));
|
||||
r2 = DistanceManhattan(current->tile, PathFinderInfo->end_tile_br + TileOffsByDir(PathFinderInfo->end_direction));
|
||||
} else {
|
||||
// No direction, so just get the fastest route to the station
|
||||
r = GetTileDist(current->tile, PathFinderInfo->end_tile_tl);
|
||||
r2 = GetTileDist(current->tile, PathFinderInfo->end_tile_br);
|
||||
r = DistanceManhattan(current->tile, PathFinderInfo->end_tile_tl);
|
||||
r2 = DistanceManhattan(current->tile, PathFinderInfo->end_tile_br);
|
||||
}
|
||||
// See if the bottomright is faster then the topleft..
|
||||
// See if the bottomright is faster than the topleft..
|
||||
if (r2 < r) r = r2;
|
||||
return r * AI_PATHFINDER_H_MULTIPLER;
|
||||
}
|
||||
|
||||
// We found the end.. let's get the route back and put it in an array
|
||||
static void AyStar_AiPathFinder_FoundEndNode(AyStar *aystar, OpenListNode *current) {
|
||||
static void AyStar_AiPathFinder_FoundEndNode(AyStar *aystar, OpenListNode *current)
|
||||
{
|
||||
Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
|
||||
int i = 0;
|
||||
uint i = 0;
|
||||
PathNode *parent = ¤t->path;
|
||||
|
||||
do {
|
||||
PathFinderInfo->route_extra[i] = parent->node.user_data[0];
|
||||
PathFinderInfo->route_extra[i] = parent->node.user_data[0];
|
||||
PathFinderInfo->route[i++] = parent->node.tile;
|
||||
if (i > lengthof(PathFinderInfo->route)) {
|
||||
// We ran out of space for the PathFinder
|
||||
DEBUG(ai,0)("[AiPathFinder] Ran out of spacein the route[] array!!!");
|
||||
DEBUG(ai, 0)("[AiPathFinder] Ran out of space in the route[] array!!!");
|
||||
PathFinderInfo->route_length = -1; // -1 indicates out of space
|
||||
return;
|
||||
}
|
||||
parent = parent->parent;
|
||||
} while (parent != NULL);
|
||||
PathFinderInfo->route_length = i;
|
||||
DEBUG(ai,1)("[Ai-PathFinding] Found route of %d nodes long in %d nodes of searching",i,Hash_Size(&aystar->ClosedListHash));
|
||||
DEBUG(ai, 1)("[Ai-PathFinding] Found route of %d nodes long in %d nodes of searching", i, Hash_Size(&aystar->ClosedListHash));
|
||||
}
|
||||
|
||||
// What tiles are around us.
|
||||
static void AyStar_AiPathFinder_GetNeighbours(AyStar *aystar, OpenListNode *current) {
|
||||
int i, r, dir;
|
||||
Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
|
||||
static void AyStar_AiPathFinder_GetNeighbours(AyStar *aystar, OpenListNode *current)
|
||||
{
|
||||
uint i;
|
||||
int ret;
|
||||
int dir;
|
||||
|
||||
aystar->num_neighbours = 0;
|
||||
Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
|
||||
|
||||
// Go through all surrounding tiles and check if they are within the limits
|
||||
for (i=0;i<4;i++) {
|
||||
if (GET_TILE_X(_tiles_around[i] + current->path.node.tile) > 1 && GET_TILE_X(_tiles_around[i] + current->path.node.tile) < TILE_X_MAX - 1 &&
|
||||
GET_TILE_Y(_tiles_around[i] + current->path.node.tile) > 1 && GET_TILE_Y(_tiles_around[i] + current->path.node.tile) < TILE_Y_MAX - 1) {
|
||||
// We also directly test if the current tile can connect to this tile..
|
||||
// We do this simply by just building the tile!
|
||||
aystar->num_neighbours = 0;
|
||||
|
||||
// If the next step is a bridge, we have to enter it the right way
|
||||
if (!PathFinderInfo->rail_or_road && AI_PATHFINDER_IS_ROAD(current->path.node.tile + _tiles_around[i])) {
|
||||
if (IS_TILETYPE(current->path.node.tile + _tiles_around[i], MP_TUNNELBRIDGE)) {
|
||||
// An existing bridge... let's test the direction ;)
|
||||
if ((_map5[current->path.node.tile + _tiles_around[i]] & 1) != (i & 1)) continue;
|
||||
// This problem only is valid for tunnels:
|
||||
// When the last tile was not yet a tunnel, check if we enter from the right side..
|
||||
if (!IS_TILETYPE(current->path.node.tile, MP_TUNNELBRIDGE) && (_map5[current->path.node.tile + _tiles_around[i]] & 0x80) == 0) {
|
||||
if (i != (_map5[current->path.node.tile + _tiles_around[i]] & 3)) continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
// But also if we are on a bridge, we can only move a certain direction
|
||||
if (!PathFinderInfo->rail_or_road && AI_PATHFINDER_IS_ROAD(current->path.node.tile)) {
|
||||
if (IS_TILETYPE(current->path.node.tile, MP_TUNNELBRIDGE)) {
|
||||
// An existing bridge/tunnel... let's test the direction ;)
|
||||
if ((_map5[current->path.node.tile] & 1) != (i & 1)) continue;
|
||||
}
|
||||
}
|
||||
// Go through all surrounding tiles and check if they are within the limits
|
||||
for (i = 0; i < 4; i++) {
|
||||
TileIndex ctile = current->path.node.tile; // Current tile
|
||||
TileIndex atile = ctile + TileOffsByDir(i); // Adjacent tile
|
||||
|
||||
if ((AI_PATHFINDER_FLAG_BRIDGE & current->path.node.user_data[0]) != 0 ||
|
||||
(AI_PATHFINDER_FLAG_TUNNEL & current->path.node.user_data[0]) != 0) {
|
||||
// We are a bridge/tunnel, how cool!!
|
||||
// This means we can only point forward.. get the direction from the user_data
|
||||
if (i != (current->path.node.user_data[0] >> 8)) continue;
|
||||
}
|
||||
dir = 0;
|
||||
if (TileX(atile) > 1 && TileX(atile) < MapMaxX() - 1 &&
|
||||
TileY(atile) > 1 && TileY(atile) < MapMaxY() - 1) {
|
||||
// We also directly test if the current tile can connect to this tile..
|
||||
// We do this simply by just building the tile!
|
||||
|
||||
// First, check if we have a parent
|
||||
if (current->path.parent == NULL && current->path.node.user_data[0] == 0) {
|
||||
// If not, this means we are at the starting station
|
||||
if (PathFinderInfo->start_direction != AI_PATHFINDER_NO_DIRECTION) {
|
||||
// We do need a direction?
|
||||
if (AiNew_GetDirection(current->path.node.tile, current->path.node.tile + _tiles_around[i]) != PathFinderInfo->start_direction)
|
||||
// We are not pointing the right way, invalid tile
|
||||
continue;
|
||||
}
|
||||
} else if (current->path.node.user_data[0] == 0) {
|
||||
if (PathFinderInfo->rail_or_road) {
|
||||
// Rail check
|
||||
dir = AiNew_GetRailDirection(current->path.parent->node.tile, current->path.node.tile, current->path.node.tile + _tiles_around[i]);
|
||||
r = DoCommandByTile(current->path.node.tile, 0, dir, DC_AUTO | DC_NO_WATER, CMD_BUILD_SINGLE_RAIL);
|
||||
if (r == CMD_ERROR) continue;
|
||||
// If the next step is a bridge, we have to enter it the right way
|
||||
if (!PathFinderInfo->rail_or_road && IsRoad(atile)) {
|
||||
if (IsTileType(atile, MP_TUNNELBRIDGE)) {
|
||||
// An existing bridge... let's test the direction ;)
|
||||
if ((_map5[atile] & 1U) != (i & 1)) continue;
|
||||
// This problem only is valid for tunnels:
|
||||
// When the last tile was not yet a tunnel, check if we enter from the right side..
|
||||
if ((_map5[atile] & 0x80) == 0) {
|
||||
if (i != (_map5[atile] & 3U)) continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
// But also if we are on a bridge, we can only move a certain direction
|
||||
if (!PathFinderInfo->rail_or_road && IsRoad(ctile)) {
|
||||
if (IsTileType(ctile, MP_TUNNELBRIDGE)) {
|
||||
// An existing bridge/tunnel... let's test the direction ;)
|
||||
if ((_map5[ctile] & 1U) != (i & 1)) continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ((AI_PATHFINDER_FLAG_BRIDGE & current->path.node.user_data[0]) != 0 ||
|
||||
(AI_PATHFINDER_FLAG_TUNNEL & current->path.node.user_data[0]) != 0) {
|
||||
// We are a bridge/tunnel, how cool!!
|
||||
// This means we can only point forward.. get the direction from the user_data
|
||||
if (i != (current->path.node.user_data[0] >> 8)) continue;
|
||||
}
|
||||
dir = 0;
|
||||
|
||||
// First, check if we have a parent
|
||||
if (current->path.parent == NULL && current->path.node.user_data[0] == 0) {
|
||||
// If not, this means we are at the starting station
|
||||
if (PathFinderInfo->start_direction != AI_PATHFINDER_NO_DIRECTION) {
|
||||
// We do need a direction?
|
||||
if (AiNew_GetDirection(ctile, atile) != PathFinderInfo->start_direction) {
|
||||
// We are not pointing the right way, invalid tile
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else if (current->path.node.user_data[0] == 0) {
|
||||
if (PathFinderInfo->rail_or_road) {
|
||||
// Rail check
|
||||
dir = AiNew_GetRailDirection(current->path.parent->node.tile, ctile, atile);
|
||||
ret = DoCommandByTile(ctile, 0, dir, DC_AUTO | DC_NO_WATER, CMD_BUILD_SINGLE_RAIL);
|
||||
if (CmdFailed(ret)) continue;
|
||||
#ifdef AI_PATHFINDER_NO_90DEGREES_TURN
|
||||
if (current->path.parent->parent != NULL) {
|
||||
// Check if we don't make a 90degree curve
|
||||
int dir1 = AiNew_GetRailDirection(current->path.parent->parent->node.tile, current->path.parent->node.tile, current->path.node.tile);
|
||||
if (_illegal_curves[dir1] == dir || _illegal_curves[dir] == dir1) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (current->path.parent->parent != NULL) {
|
||||
// Check if we don't make a 90degree curve
|
||||
int dir1 = AiNew_GetRailDirection(current->path.parent->parent->node.tile, current->path.parent->node.tile, ctile);
|
||||
if (_illegal_curves[dir1] == dir || _illegal_curves[dir] == dir1) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
// Road check
|
||||
dir = AiNew_GetRoadDirection(current->path.parent->node.tile, current->path.node.tile, current->path.node.tile + _tiles_around[i]);
|
||||
if (AI_PATHFINDER_IS_ROAD(current->path.node.tile)) {
|
||||
if (IS_TILETYPE(current->path.node.tile, MP_TUNNELBRIDGE)) {
|
||||
// We have a bridge, how nicely! We should mark it...
|
||||
dir = 0;
|
||||
} else {
|
||||
// It already has road.. check if we miss any bits!
|
||||
if ((_map5[current->path.node.tile] & dir) != dir) {
|
||||
// We do miss some pieces :(
|
||||
dir &= ~_map5[current->path.node.tile];
|
||||
} else {
|
||||
dir = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Only destruct things if it is MP_CLEAR of MP_TREES
|
||||
if (dir != 0) {
|
||||
r = DoCommandByTile(current->path.node.tile, dir, 0, DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD);
|
||||
if (r == CMD_ERROR) continue;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
// Road check
|
||||
dir = AiNew_GetRoadDirection(current->path.parent->node.tile, ctile, atile);
|
||||
if (IsRoad(ctile)) {
|
||||
if (IsTileType(ctile, MP_TUNNELBRIDGE)) {
|
||||
// We have a bridge, how nicely! We should mark it...
|
||||
dir = 0;
|
||||
} else {
|
||||
// It already has road.. check if we miss any bits!
|
||||
if ((_map5[ctile] & dir) != dir) {
|
||||
// We do miss some pieces :(
|
||||
dir &= ~_map5[ctile];
|
||||
} else {
|
||||
dir = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Only destruct things if it is MP_CLEAR of MP_TREES
|
||||
if (dir != 0) {
|
||||
ret = DoCommandByTile(ctile, dir, 0, DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD);
|
||||
if (CmdFailed(ret)) continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The tile can be connected
|
||||
aystar->neighbours[aystar->num_neighbours].tile = _tiles_around[i] + current->path.node.tile;
|
||||
aystar->neighbours[aystar->num_neighbours].user_data[0] = 0;
|
||||
aystar->neighbours[aystar->num_neighbours++].direction = 0;
|
||||
}
|
||||
}
|
||||
aystar->neighbours[aystar->num_neighbours].tile = atile;
|
||||
aystar->neighbours[aystar->num_neighbours].user_data[0] = 0;
|
||||
aystar->neighbours[aystar->num_neighbours++].direction = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Next step, check for bridges and tunnels
|
||||
if (current->path.parent != NULL && current->path.node.user_data[0] == 0) {
|
||||
// Next step, check for bridges and tunnels
|
||||
if (current->path.parent != NULL && current->path.node.user_data[0] == 0) {
|
||||
TileInfo ti;
|
||||
// First we get the dir from this tile and his parent
|
||||
int dir = AiNew_GetDirection(current->path.parent->node.tile, current->path.node.tile);
|
||||
// It means we can only walk with the track, so the bridge has to be in the same direction
|
||||
TileIndex tile = current->path.node.tile;
|
||||
TileIndex new_tile = tile;
|
||||
|
||||
TileInfo ti;
|
||||
// First we get the dir from this tile and his parent
|
||||
int dir = AiNew_GetDirection(current->path.parent->node.tile, current->path.node.tile);
|
||||
// It means we can only walk with the track, so the bridge has to be in the same direction
|
||||
TileIndex tile = current->path.node.tile;
|
||||
TileIndex new_tile = tile;
|
||||
FindLandscapeHeightByTile(&ti, tile);
|
||||
|
||||
FindLandscapeHeightByTile(&ti, tile);
|
||||
// Bridges can only be build on land that is not flat
|
||||
// And if there is a road or rail blocking
|
||||
if (ti.tileh != 0 ||
|
||||
(PathFinderInfo->rail_or_road && IsTileType(tile + TileOffsByDir(dir), MP_STREET)) ||
|
||||
(!PathFinderInfo->rail_or_road && IsTileType(tile + TileOffsByDir(dir), MP_RAILWAY))) {
|
||||
|
||||
// Bridges can only be build on land that is not flat
|
||||
// And if there is a road or rail blocking
|
||||
if (ti.tileh != 0 ||
|
||||
(PathFinderInfo->rail_or_road && IS_TILETYPE(tile + _tiles_around[dir], MP_STREET)) ||
|
||||
(!PathFinderInfo->rail_or_road && IS_TILETYPE(tile + _tiles_around[dir], MP_RAILWAY))) {
|
||||
for (;;) {
|
||||
new_tile += TileOffsByDir(dir);
|
||||
|
||||
for (;;) {
|
||||
new_tile += _tiles_around[dir];
|
||||
// Precheck, is the length allowed?
|
||||
if (!CheckBridge_Stuff(0, GetBridgeLength(tile, new_tile))) break;
|
||||
|
||||
// Precheck, is the length allowed?
|
||||
if (!CheckBridge_Stuff(0,GetBridgeLength(tile, new_tile))) break;
|
||||
// Check if we hit the station-tile.. we don't like that!
|
||||
if (TILES_BETWEEN(new_tile, PathFinderInfo->end_tile_tl, PathFinderInfo->end_tile_br)) break;
|
||||
|
||||
// Check if we hit the station-tile.. we don't like that!
|
||||
if (TILES_BETWEEN(new_tile,PathFinderInfo->end_tile_tl,PathFinderInfo->end_tile_br)) break;
|
||||
|
||||
// Try building the bridge..
|
||||
r = DoCommandByTile(tile, new_tile, (0<<8) + (MAX_BRIDGES / 2), DC_AUTO, CMD_BUILD_BRIDGE);
|
||||
if (r == CMD_ERROR) continue;
|
||||
// We can build a bridge here.. add him to the neighbours
|
||||
aystar->neighbours[aystar->num_neighbours].tile = new_tile;
|
||||
aystar->neighbours[aystar->num_neighbours].user_data[0] = AI_PATHFINDER_FLAG_BRIDGE + (dir << 8);
|
||||
aystar->neighbours[aystar->num_neighbours++].direction = 0;
|
||||
// Try building the bridge..
|
||||
ret = DoCommandByTile(tile, new_tile, (0 << 8) + (MAX_BRIDGES / 2), DC_AUTO, CMD_BUILD_BRIDGE);
|
||||
if (CmdFailed(ret)) continue;
|
||||
// We can build a bridge here.. add him to the neighbours
|
||||
aystar->neighbours[aystar->num_neighbours].tile = new_tile;
|
||||
aystar->neighbours[aystar->num_neighbours].user_data[0] = AI_PATHFINDER_FLAG_BRIDGE + (dir << 8);
|
||||
aystar->neighbours[aystar->num_neighbours++].direction = 0;
|
||||
// We can only have 12 neighbours, and we need 1 left for tunnels
|
||||
if (aystar->num_neighbours == 11) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Next, check for tunnels!
|
||||
// Tunnels can only be build with tileh of 3, 6, 9 or 12, depending on the direction
|
||||
// For now, we check both sides for this tile.. terraforming gives fuzzy result
|
||||
if ((dir == 0 && ti.tileh == 12) ||
|
||||
(dir == 1 && ti.tileh == 6) ||
|
||||
(dir == 2 && ti.tileh == 3) ||
|
||||
(dir == 3 && ti.tileh == 9)) {
|
||||
// Now simply check if a tunnel can be build
|
||||
r = DoCommandByTile(tile, (PathFinderInfo->rail_or_road?0:0x200), 0, DC_AUTO, CMD_BUILD_TUNNEL);
|
||||
FindLandscapeHeightByTile(&ti, _build_tunnel_endtile);
|
||||
if (r != CMD_ERROR && (ti.tileh == 3 || ti.tileh == 6 || ti.tileh == 9 || ti.tileh == 12)) {
|
||||
aystar->neighbours[aystar->num_neighbours].tile = _build_tunnel_endtile;
|
||||
aystar->neighbours[aystar->num_neighbours].user_data[0] = AI_PATHFINDER_FLAG_TUNNEL + (dir << 8);
|
||||
aystar->neighbours[aystar->num_neighbours++].direction = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Next, check for tunnels!
|
||||
// Tunnels can only be build with tileh of 3, 6, 9 or 12, depending on the direction
|
||||
// For now, we check both sides for this tile.. terraforming gives fuzzy result
|
||||
if ((dir == 0 && ti.tileh == 12) ||
|
||||
(dir == 1 && ti.tileh == 6) ||
|
||||
(dir == 2 && ti.tileh == 3) ||
|
||||
(dir == 3 && ti.tileh == 9)) {
|
||||
// Now simply check if a tunnel can be build
|
||||
ret = DoCommandByTile(tile, (PathFinderInfo->rail_or_road?0:0x200), 0, DC_AUTO, CMD_BUILD_TUNNEL);
|
||||
FindLandscapeHeightByTile(&ti, _build_tunnel_endtile);
|
||||
if (!CmdFailed(ret) && (ti.tileh == 3 || ti.tileh == 6 || ti.tileh == 9 || ti.tileh == 12)) {
|
||||
aystar->neighbours[aystar->num_neighbours].tile = _build_tunnel_endtile;
|
||||
aystar->neighbours[aystar->num_neighbours].user_data[0] = AI_PATHFINDER_FLAG_TUNNEL + (dir << 8);
|
||||
aystar->neighbours[aystar->num_neighbours++].direction = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern uint GetRailFoundation(uint tileh, uint bits);
|
||||
extern uint GetRoadFoundation(uint tileh, uint bits);
|
||||
extern uint GetBridgeFoundation(uint tileh, byte direction);
|
||||
enum {
|
||||
BRIDGE_NO_FOUNDATION = 1 << 0 | 1 << 3 | 1 << 6 | 1 << 9 | 1 << 12,
|
||||
BRIDGE_NO_FOUNDATION = 1 << 0 | 1 << 3 | 1 << 6 | 1 << 9 | 1 << 12,
|
||||
};
|
||||
|
||||
// The most important function: it calculates the g-value
|
||||
static int32 AyStar_AiPathFinder_CalculateG(AyStar *aystar, AyStarNode *current, OpenListNode *parent) {
|
||||
static int32 AyStar_AiPathFinder_CalculateG(AyStar *aystar, AyStarNode *current, OpenListNode *parent)
|
||||
{
|
||||
Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
|
||||
int r, res = 0;
|
||||
TileInfo ti, parent_ti;
|
||||
@@ -340,7 +375,7 @@ static int32 AyStar_AiPathFinder_CalculateG(AyStar *aystar, AyStarNode *current,
|
||||
FindLandscapeHeightByTile(&parent_ti, parent->path.node.tile);
|
||||
|
||||
// Check if we hit the end-tile
|
||||
if (TILES_BETWEEN(current->tile,PathFinderInfo->end_tile_tl,PathFinderInfo->end_tile_br)) {
|
||||
if (TILES_BETWEEN(current->tile, PathFinderInfo->end_tile_tl, PathFinderInfo->end_tile_br)) {
|
||||
// We are at the end-tile, check if we had a direction or something...
|
||||
if (PathFinderInfo->end_direction != AI_PATHFINDER_NO_DIRECTION && AiNew_GetDirection(current->tile, parent->path.node.tile) != PathFinderInfo->end_direction)
|
||||
// We are not pointing the right way, invalid tile
|
||||
@@ -355,13 +390,17 @@ static int32 AyStar_AiPathFinder_CalculateG(AyStar *aystar, AyStarNode *current,
|
||||
if (!PathFinderInfo->rail_or_road) {
|
||||
// Road has the lovely advantage it can use other road... check if
|
||||
// the current tile is road, and if so, give a good bonus
|
||||
if (AI_PATHFINDER_IS_ROAD(current->tile)) {
|
||||
if (IsRoad(current->tile)) {
|
||||
res -= AI_PATHFINDER_ROAD_ALREADY_EXISTS_BONUS;
|
||||
}
|
||||
}
|
||||
|
||||
// We should give a penalty when the tile is going up or down.. this is one way to do so!
|
||||
// Too bad we have to count it from the parent.. but that is not so bad
|
||||
// Too bad we have to count it from the parent.. but that is not so bad.
|
||||
// We also dislike long routes on slopes, since they do not look too realistic
|
||||
// when there is a flat land all around, they are more expensive to build, and
|
||||
// especially they essentially block the ability to connect or cross the road
|
||||
// from one side.
|
||||
if (parent_ti.tileh != 0 && parent->path.parent != NULL) {
|
||||
// Skip if the tile was from a bridge or tunnel
|
||||
if (parent->path.node.user_data[0] == 0 && current->user_data[0] == 0) {
|
||||
@@ -370,12 +409,16 @@ static int32 AyStar_AiPathFinder_CalculateG(AyStar *aystar, AyStarNode *current,
|
||||
// Maybe is BRIDGE_NO_FOUNDATION a bit strange here, but it contains just the right information..
|
||||
if (r >= 15 || (r == 0 && (BRIDGE_NO_FOUNDATION & (1 << ti.tileh)))) {
|
||||
res += AI_PATHFINDER_TILE_GOES_UP_PENALTY;
|
||||
} else {
|
||||
res += AI_PATHFINDER_FOUNDATION_PENALTY;
|
||||
}
|
||||
} else {
|
||||
if (!(AI_PATHFINDER_IS_ROAD(parent->path.node.tile) && IS_TILETYPE(parent->path.node.tile, MP_TUNNELBRIDGE))) {
|
||||
if (!(IsRoad(parent->path.node.tile) && IsTileType(parent->path.node.tile, MP_TUNNELBRIDGE))) {
|
||||
r = GetRoadFoundation(parent_ti.tileh, AiNew_GetRoadDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile));
|
||||
if (r >= 15 || r == 0)
|
||||
res += AI_PATHFINDER_TILE_GOES_UP_PENALTY;
|
||||
else
|
||||
res += AI_PATHFINDER_FOUNDATION_PENALTY;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -417,7 +460,7 @@ static int32 AyStar_AiPathFinder_CalculateG(AyStar *aystar, AyStarNode *current,
|
||||
if (parent->path.parent != NULL &&
|
||||
AiNew_GetDirection(current->tile, parent->path.node.tile) != AiNew_GetDirection(parent->path.node.tile, parent->path.parent->node.tile)) {
|
||||
// When road exists, we don't like turning, but its free, so don't be to piggy about it
|
||||
if (AI_PATHFINDER_IS_ROAD(parent->path.node.tile))
|
||||
if (IsRoad(parent->path.node.tile))
|
||||
res += AI_PATHFINDER_DIRECTION_CHANGE_ON_EXISTING_ROAD_PENALTY;
|
||||
else
|
||||
res += AI_PATHFINDER_DIRECTION_CHANGE_PENALTY;
|
||||
@@ -428,7 +471,7 @@ static int32 AyStar_AiPathFinder_CalculateG(AyStar *aystar, AyStarNode *current,
|
||||
if (parent->path.parent != NULL && parent->path.parent->parent != NULL) {
|
||||
int dir1 = AiNew_GetRailDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile);
|
||||
int dir2 = AiNew_GetRailDirection(parent->path.parent->parent->node.tile, parent->path.parent->node.tile, parent->path.node.tile);
|
||||
// First, see if we are on diagonal path, that is better then straight path
|
||||
// First, see if we are on diagonal path, that is better than straight path
|
||||
if (dir1 > 1) { res -= AI_PATHFINDER_DIAGONAL_BONUS; }
|
||||
|
||||
// First see if they are different
|
||||
|
||||
+17
-15
@@ -1,5 +1,7 @@
|
||||
#include "stdafx.h"
|
||||
#include "ttd.h"
|
||||
#include "debug.h"
|
||||
#include "map.h"
|
||||
#include "ai.h"
|
||||
#include "vehicle.h"
|
||||
|
||||
@@ -14,13 +16,13 @@ int AiNew_GetRailDirection(uint tile_a, uint tile_b, uint tile_c) {
|
||||
int x1, x2, x3;
|
||||
int y1, y2, y3;
|
||||
|
||||
x1 = GET_TILE_X(tile_a);
|
||||
x2 = GET_TILE_X(tile_b);
|
||||
x3 = GET_TILE_X(tile_c);
|
||||
x1 = TileX(tile_a);
|
||||
x2 = TileX(tile_b);
|
||||
x3 = TileX(tile_c);
|
||||
|
||||
y1 = GET_TILE_Y(tile_a);
|
||||
y2 = GET_TILE_Y(tile_b);
|
||||
y3 = GET_TILE_Y(tile_c);
|
||||
y1 = TileY(tile_a);
|
||||
y2 = TileY(tile_b);
|
||||
y3 = TileY(tile_c);
|
||||
|
||||
if (y1 == y2 && y2 == y3) return 0;
|
||||
if (x1 == x2 && x2 == x3) return 1;
|
||||
@@ -49,13 +51,13 @@ int AiNew_GetRoadDirection(uint tile_a, uint tile_b, uint tile_c) {
|
||||
int y1, y2, y3;
|
||||
int r;
|
||||
|
||||
x1 = GET_TILE_X(tile_a);
|
||||
x2 = GET_TILE_X(tile_b);
|
||||
x3 = GET_TILE_X(tile_c);
|
||||
x1 = TileX(tile_a);
|
||||
x2 = TileX(tile_b);
|
||||
x3 = TileX(tile_c);
|
||||
|
||||
y1 = GET_TILE_Y(tile_a);
|
||||
y2 = GET_TILE_Y(tile_b);
|
||||
y3 = GET_TILE_Y(tile_c);
|
||||
y1 = TileY(tile_a);
|
||||
y2 = TileY(tile_b);
|
||||
y3 = TileY(tile_c);
|
||||
|
||||
r = 0;
|
||||
|
||||
@@ -74,9 +76,9 @@ int AiNew_GetRoadDirection(uint tile_a, uint tile_b, uint tile_c) {
|
||||
|
||||
// Get's the direction between 2 tiles seen from tile_a
|
||||
int AiNew_GetDirection(uint tile_a, uint tile_b) {
|
||||
if (GET_TILE_Y(tile_a) < GET_TILE_Y(tile_b)) return 1;
|
||||
if (GET_TILE_Y(tile_a) > GET_TILE_Y(tile_b)) return 3;
|
||||
if (GET_TILE_X(tile_a) < GET_TILE_X(tile_b)) return 2;
|
||||
if (TileY(tile_a) < TileY(tile_b)) return 1;
|
||||
if (TileY(tile_a) > TileY(tile_b)) return 3;
|
||||
if (TileX(tile_a) < TileX(tile_b)) return 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+523
-338
File diff suppressed because it is too large
Load Diff
+385
-417
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,7 @@
|
||||
#include "stdafx.h"
|
||||
#include "ttd.h"
|
||||
#include "debug.h"
|
||||
#include "map.h"
|
||||
#include "airport.h"
|
||||
|
||||
AirportFTAClass *CountryAirport;
|
||||
@@ -9,11 +11,10 @@ AirportFTAClass *MetropolitanAirport;
|
||||
AirportFTAClass *InternationalAirport;
|
||||
|
||||
static void AirportFTAClass_Constructor(AirportFTAClass *Airport,
|
||||
const byte nofterminals, const byte nofterminalgroups,
|
||||
const byte nofhelipads, const byte nofhelipadgroups,
|
||||
const byte *terminals, const byte *helipads,
|
||||
const byte entry_point, const byte acc_planes,
|
||||
const AirportFTAbuildup *FA,
|
||||
const TileIndex *depots);
|
||||
const TileIndexDiffC *depots, const byte nof_depots);
|
||||
static void AirportFTAClass_Destructor(AirportFTAClass *Airport);
|
||||
|
||||
static uint16 AirportGetNofElements(const AirportFTAbuildup *FA);
|
||||
@@ -22,31 +23,82 @@ static byte AirportTestFTA(const AirportFTAClass *Airport);
|
||||
/*static void AirportPrintOut(const AirportFTAClass *Airport, const bool full_report);
|
||||
static byte AirportBlockToString(uint32 block);*/
|
||||
|
||||
void InitializeAirports()
|
||||
void InitializeAirports(void)
|
||||
{
|
||||
// country airport
|
||||
CountryAirport = (AirportFTAClass *)malloc(sizeof(AirportFTAClass));
|
||||
AirportFTAClass_Constructor(CountryAirport, 2, 1, 0, 0, 16, ALL, _airport_fta_country, _airport_depots_country);
|
||||
CountryAirport = malloc(sizeof(AirportFTAClass));
|
||||
|
||||
AirportFTAClass_Constructor(
|
||||
CountryAirport,
|
||||
_airport_terminal_country,
|
||||
NULL,
|
||||
16,
|
||||
ALL,
|
||||
_airport_fta_country,
|
||||
_airport_depots_country,
|
||||
lengthof(_airport_depots_country)
|
||||
);
|
||||
|
||||
// city airport
|
||||
CityAirport = (AirportFTAClass *)malloc(sizeof(AirportFTAClass));
|
||||
AirportFTAClass_Constructor(CityAirport, 3, 1, 0, 0, 19, ALL, _airport_fta_city, _airport_depots_city);
|
||||
CityAirport = malloc(sizeof(AirportFTAClass));
|
||||
|
||||
AirportFTAClass_Constructor(
|
||||
CityAirport,
|
||||
_airport_terminal_city,
|
||||
NULL,
|
||||
19,
|
||||
ALL,
|
||||
_airport_fta_city,
|
||||
_airport_depots_city,
|
||||
lengthof(_airport_depots_city)
|
||||
);
|
||||
|
||||
// metropolitan airport
|
||||
MetropolitanAirport = (AirportFTAClass *)malloc(sizeof(AirportFTAClass));
|
||||
AirportFTAClass_Constructor(MetropolitanAirport, 3, 1, 0, 0, 20, ALL, _airport_fta_metropolitan, _airport_depots_metropolitan);
|
||||
MetropolitanAirport = malloc(sizeof(AirportFTAClass));
|
||||
|
||||
AirportFTAClass_Constructor(
|
||||
MetropolitanAirport,
|
||||
_airport_terminal_metropolitan,
|
||||
NULL,
|
||||
20,
|
||||
ALL,
|
||||
_airport_fta_metropolitan,
|
||||
_airport_depots_metropolitan,
|
||||
lengthof(_airport_depots_metropolitan)
|
||||
);
|
||||
|
||||
// international airport
|
||||
InternationalAirport = (AirportFTAClass *)malloc(sizeof(AirportFTAClass));
|
||||
AirportFTAClass_Constructor(InternationalAirport, 6, 2, 2, 1, 37, ALL, _airport_fta_international, _airport_depots_international);
|
||||
|
||||
AirportFTAClass_Constructor(
|
||||
InternationalAirport,
|
||||
_airport_terminal_international,
|
||||
_airport_helipad_international,
|
||||
37,
|
||||
ALL,
|
||||
_airport_fta_international,
|
||||
_airport_depots_international,
|
||||
lengthof(_airport_depots_international)
|
||||
);
|
||||
|
||||
// heliport, oilrig
|
||||
Heliport = (AirportFTAClass *)malloc(sizeof(AirportFTAClass));
|
||||
AirportFTAClass_Constructor(Heliport, 0, 0, 1, 1, 7, HELICOPTERS_ONLY, _airport_fta_heliport_oilrig, _airport_depots_heliport_oilrig);
|
||||
|
||||
AirportFTAClass_Constructor(
|
||||
Heliport,
|
||||
NULL,
|
||||
_airport_helipad_heliport_oilrig,
|
||||
7,
|
||||
HELICOPTERS_ONLY,
|
||||
_airport_fta_heliport_oilrig,
|
||||
NULL,
|
||||
0
|
||||
);
|
||||
|
||||
Oilrig = Heliport; // exactly the same structure for heliport/oilrig, so share state machine
|
||||
}
|
||||
|
||||
void UnInitializeAirports()
|
||||
void UnInitializeAirports(void)
|
||||
{
|
||||
AirportFTAClass_Destructor(CountryAirport);
|
||||
AirportFTAClass_Destructor(CityAirport);
|
||||
@@ -56,12 +108,46 @@ void UnInitializeAirports()
|
||||
}
|
||||
|
||||
static void AirportFTAClass_Constructor(AirportFTAClass *Airport,
|
||||
const byte nofterminals, const byte nofterminalgroups,
|
||||
const byte nofhelipads, const byte nofhelipadgroups,
|
||||
const byte *terminals, const byte *helipads,
|
||||
const byte entry_point, const byte acc_planes,
|
||||
const AirportFTAbuildup *FA,
|
||||
const TileIndex *depots)
|
||||
const TileIndexDiffC *depots, const byte nof_depots)
|
||||
{
|
||||
byte nofterminals, nofhelipads;
|
||||
byte nofterminalgroups = 0;
|
||||
byte nofhelipadgroups = 0;
|
||||
const byte * curr;
|
||||
int i;
|
||||
nofterminals = nofhelipads = 0;
|
||||
|
||||
//now we read the number of terminals we have
|
||||
if (terminals != NULL) {
|
||||
i = terminals[0];
|
||||
nofterminalgroups = i;
|
||||
curr = terminals;
|
||||
while (i-- > 0) {
|
||||
curr++;
|
||||
assert(*curr != 0); //we don't want to have an empty group
|
||||
nofterminals += *curr;
|
||||
}
|
||||
|
||||
}
|
||||
Airport->terminals = terminals;
|
||||
|
||||
//read helipads
|
||||
if (helipads != NULL) {
|
||||
i = helipads[0];
|
||||
nofhelipadgroups = i;
|
||||
curr = helipads;
|
||||
while (i-- > 0) {
|
||||
curr++;
|
||||
assert(*curr != 0); //no empty groups please
|
||||
nofhelipads += *curr;
|
||||
}
|
||||
|
||||
}
|
||||
Airport->helipads = helipads;
|
||||
|
||||
// if there are more terminals than 6, internal variables have to be changed, so don't allow that
|
||||
// same goes for helipads
|
||||
if (nofterminals > MAX_TERMINALS) { printf("Currently only maximum of %2d terminals are supported (you wanted %2d)\n", MAX_TERMINALS, nofterminals);}
|
||||
@@ -69,32 +155,25 @@ static void AirportFTAClass_Constructor(AirportFTAClass *Airport,
|
||||
// terminals/helipads are divided into groups. Groups are computed by dividing the number
|
||||
// of terminals by the number of groups. Half in half. If #terminals is uneven, first group
|
||||
// will get the less # of terminals
|
||||
if (nofterminalgroups > nofterminals) { printf("# of terminalgroups (%2d) must be less or equal to terminals (%2d)", nofterminals, nofterminalgroups);}
|
||||
if (nofhelipadgroups > nofhelipads) { printf("# of helipadgroups (%2d) must be less or equal to helipads (%2d)", nofhelipads, nofhelipadgroups);}
|
||||
|
||||
assert(nofterminals <= MAX_TERMINALS);
|
||||
assert(nofhelipads <= MAX_HELIPADS);
|
||||
assert(nofterminalgroups <= nofterminals);
|
||||
assert(nofhelipadgroups <= nofhelipads);
|
||||
|
||||
Airport->nofelements = AirportGetNofElements(FA);
|
||||
// check
|
||||
if (entry_point >= Airport->nofelements) {printf("Entry point (%2d) must be within the airport positions (which is max %2d)\n", entry_point, Airport->nofelements);}
|
||||
assert(entry_point < Airport->nofelements);
|
||||
|
||||
Airport->nofterminals = nofterminals;
|
||||
Airport->nofterminalgroups = nofterminalgroups;
|
||||
Airport->nofhelipads = nofhelipads;
|
||||
Airport->nofhelipadgroups = nofhelipadgroups;
|
||||
Airport->acc_planes = acc_planes;
|
||||
Airport->entry_point = entry_point;
|
||||
Airport->airport_depots = (const uint16*)depots;
|
||||
Airport->airport_depots = depots;
|
||||
Airport->nof_depots = nof_depots;
|
||||
|
||||
|
||||
// build the state machine
|
||||
AirportBuildAutomata(Airport, FA);
|
||||
DEBUG(misc, 1) ("#Elements %2d; #Terminals %2d in %d group(s); #Helipads %2d in %d group(s)", Airport->nofelements,
|
||||
Airport->nofterminals, Airport->nofterminalgroups, Airport->nofhelipads, Airport->nofhelipadgroups);
|
||||
DEBUG(misc, 1) ("#Elements %2d; #Terminals %2d in %d group(s); #Helipads %2d in %d group(s); Entry Point %d", Airport->nofelements,
|
||||
nofterminals, nofterminalgroups, nofhelipads, nofhelipadgroups, Airport->entry_point);
|
||||
|
||||
|
||||
{
|
||||
|
||||
@@ -13,7 +13,7 @@ enum {
|
||||
AT_HELIPORT = 2,
|
||||
AT_METROPOLITAN = 3,
|
||||
AT_INTERNATIONAL = 4,
|
||||
AT_OILRIG = 5
|
||||
AT_OILRIG = 15
|
||||
};
|
||||
|
||||
// do not change unless you change v->subtype too. This aligns perfectly with its current setting
|
||||
@@ -26,13 +26,12 @@ enum {
|
||||
// Finite sTate mAchine --> FTA
|
||||
typedef struct AirportFTAClass {
|
||||
byte nofelements; // number of positions the airport consists of
|
||||
byte nofterminals; // number of terminals this airport has
|
||||
byte nofterminalgroups; // terminals belong to so many groups (MAX is the nofterminals)
|
||||
byte nofhelipads; // number of helipads this airport has
|
||||
byte nofhelipadgroups; // helipads belong to so many groups (MAX is the nofhelipads)
|
||||
const byte *terminals;
|
||||
const byte *helipads;
|
||||
byte entry_point; // when an airplane arrives at this airport, enter it at position entry_point
|
||||
byte acc_planes; // accept airplanes or helicopters or both
|
||||
const uint16 *airport_depots; // gives the position of the depots on the airports
|
||||
const TileIndexDiffC *airport_depots; // gives the position of the depots on the airports
|
||||
byte nof_depots; // number of depots this airport has
|
||||
struct AirportFTA *layout; // state machine for airport
|
||||
} AirportFTAClass;
|
||||
|
||||
@@ -45,8 +44,24 @@ typedef struct AirportFTA {
|
||||
struct AirportFTA *next_in_chain; // possible extra movement choices from this position
|
||||
} AirportFTA;
|
||||
|
||||
void InitializeAirports();
|
||||
void UnInitializeAirports();
|
||||
void InitializeAirports(void);
|
||||
void UnInitializeAirports(void);
|
||||
const AirportFTAClass* GetAirport(const byte airport_type);
|
||||
|
||||
/** Get buildable airport bitmask.
|
||||
* @return get all buildable airports at this given time, bitmasked.
|
||||
* Bit 0 means the small airport is buildable, etc.
|
||||
* @todo set availability of airports by year, instead of airplane
|
||||
*/
|
||||
static inline uint32 GetValidAirports(void)
|
||||
{
|
||||
uint32 bytemask = _avail_aircraft; /// sets the first 3 bytes, 0 - 2, @see AdjustAvailAircraft()
|
||||
|
||||
// 1980-1-1 is --> 21915
|
||||
// 1990-1-1 is --> 25568
|
||||
if (_date >= 21915) {SETBIT(bytemask, 3);} // metropilitan airport 1980
|
||||
if (_date >= 25568) {SETBIT(bytemask, 4);} // international airport 1990
|
||||
return bytemask;
|
||||
}
|
||||
|
||||
#endif /* AIRPORT_H */
|
||||
|
||||
+83
-65
@@ -1,24 +1,28 @@
|
||||
#include "stdafx.h"
|
||||
#include "ttd.h"
|
||||
|
||||
#include "table/sprites.h"
|
||||
#include "table/strings.h"
|
||||
#include "map.h"
|
||||
#include "window.h"
|
||||
#include "gui.h"
|
||||
#include "viewport.h"
|
||||
#include "gfx.h"
|
||||
#include "sound.h"
|
||||
#include "command.h"
|
||||
#include "vehicle.h"
|
||||
#include "station.h"
|
||||
#include "airport.h"
|
||||
#include "depot.h"
|
||||
|
||||
static byte _selected_airport_type;
|
||||
|
||||
static void ShowBuildAirportPicker();
|
||||
static void ShowBuildAirportPicker(void);
|
||||
|
||||
|
||||
static void CcBuildAirport(bool success, uint tile, uint32 p1, uint32 p2)
|
||||
void CcBuildAirport(bool success, uint tile, uint32 p1, uint32 p2)
|
||||
{
|
||||
if (success) {
|
||||
SndPlayTileFx(0x1D, tile);
|
||||
SndPlayTileFx(SND_1F_SPLAT, tile);
|
||||
ResetObjectToPlace();
|
||||
}
|
||||
}
|
||||
@@ -36,36 +40,24 @@ static void PlaceAir_DemolishArea(uint tile)
|
||||
|
||||
static void BuildAirClick_Airport(Window *w)
|
||||
{
|
||||
if (HandlePlacePushButton(w, 2, 0xAA4, 1, PlaceAirport)) ShowBuildAirportPicker();
|
||||
if (HandlePlacePushButton(w, 3, 0xAA4, 1, PlaceAirport)) ShowBuildAirportPicker();
|
||||
}
|
||||
|
||||
static void BuildAirClick_Demolish(Window *w)
|
||||
{
|
||||
HandlePlacePushButton(w, 3, ANIMCURSOR_DEMOLISH, 1, PlaceAir_DemolishArea);
|
||||
HandlePlacePushButton(w, 4, ANIMCURSOR_DEMOLISH, 1, PlaceAir_DemolishArea);
|
||||
}
|
||||
|
||||
static void BuildAirClick_Lower(Window *w)
|
||||
static void BuildAirClick_Landscaping(Window *w)
|
||||
{
|
||||
HandlePlacePushButton(w, 4, ANIMCURSOR_LOWERLAND, 2, PlaceProc_LowerLand);
|
||||
}
|
||||
|
||||
static void BuildAirClick_Raise(Window *w)
|
||||
{
|
||||
HandlePlacePushButton(w, 5, ANIMCURSOR_RAISELAND, 2, PlaceProc_RaiseLand);
|
||||
}
|
||||
|
||||
static void BuildAirClick_Purchase(Window *w)
|
||||
{
|
||||
HandlePlacePushButton(w, 6, 0x12B8, 1, PlaceProc_BuyLand);
|
||||
ShowTerraformToolbar();
|
||||
}
|
||||
|
||||
typedef void OnButtonClick(Window *w);
|
||||
static OnButtonClick * const _build_air_button_proc[] = {
|
||||
BuildAirClick_Airport,
|
||||
BuildAirClick_Demolish,
|
||||
BuildAirClick_Lower,
|
||||
BuildAirClick_Raise,
|
||||
BuildAirClick_Purchase,
|
||||
BuildAirClick_Landscaping,
|
||||
};
|
||||
|
||||
static void BuildAirToolbWndProc(Window *w, WindowEvent *e)
|
||||
@@ -76,10 +68,20 @@ static void BuildAirToolbWndProc(Window *w, WindowEvent *e)
|
||||
break;
|
||||
|
||||
case WE_CLICK:
|
||||
if (e->click.widget-2 >= 0)
|
||||
_build_air_button_proc[e->click.widget - 2](w);
|
||||
if (e->click.widget - 3 >= 0)
|
||||
_build_air_button_proc[e->click.widget - 3](w);
|
||||
break;
|
||||
|
||||
case WE_KEYPRESS: {
|
||||
switch (e->keypress.keycode) {
|
||||
case '1': BuildAirClick_Airport(w); break;
|
||||
case '2': BuildAirClick_Demolish(w); break;
|
||||
case 'l': BuildAirClick_Landscaping(w); break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
} break;
|
||||
|
||||
case WE_PLACE_OBJ:
|
||||
_place_proc(e->place.tile);
|
||||
break;
|
||||
@@ -96,7 +98,7 @@ static void BuildAirToolbWndProc(Window *w, WindowEvent *e)
|
||||
break;
|
||||
|
||||
case WE_ABORT_PLACE_OBJ:
|
||||
w->click_state = 0;
|
||||
UnclickWindowButtons(w);
|
||||
SetWindowDirty(w);
|
||||
w = FindWindowById(WC_BUILD_STATION, 0);
|
||||
if (w != 0)
|
||||
@@ -106,77 +108,88 @@ static void BuildAirToolbWndProc(Window *w, WindowEvent *e)
|
||||
}
|
||||
|
||||
static const Widget _air_toolbar_widgets[] = {
|
||||
{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, 7, 11, 129, 0, 13, STR_A000_AIRPORT_CONSTRUCT, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_PANEL, 7, 0, 41, 14, 35, 0x2E8, STR_A01E_BUILD_AIRPORT},
|
||||
{ WWT_PANEL, 7, 42, 63, 14, 35, 0x2BF, STR_018D_DEMOLISH_BUILDINGS_ETC},
|
||||
{ WWT_PANEL, 7, 64, 85, 14, 35, 0x2B7, STR_018E_LOWER_A_CORNER_OF_LAND},
|
||||
{ WWT_PANEL, 7, 86, 107, 14, 35, 0x2B6, STR_018F_RAISE_A_CORNER_OF_LAND},
|
||||
{ WWT_PANEL, 7, 108, 129, 14, 35, 0x12B7, STR_0329_PURCHASE_LAND_FOR_FUTURE},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 73, 0, 13, STR_A000_AIRPORTS, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_STICKYBOX, RESIZE_NONE, 7, 74, 85, 0, 13, 0x0, STR_STICKY_BUTTON},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 0, 41, 14, 35, 0x2E8, STR_A01E_BUILD_AIRPORT},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 42, 63, 14, 35, 0x2BF, STR_018D_DEMOLISH_BUILDINGS_ETC},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 64, 85, 14, 35, SPR_IMG_LANDSCAPING, STR_LANDSCAPING_TOOLBAR_TIP},
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
|
||||
static const WindowDesc _air_toolbar_desc = {
|
||||
510, 22, 130, 36,
|
||||
640-86, 22, 86, 36,
|
||||
WC_BUILD_TOOLBAR,0,
|
||||
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
|
||||
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
|
||||
_air_toolbar_widgets,
|
||||
BuildAirToolbWndProc
|
||||
};
|
||||
|
||||
void ShowBuildAirToolbar()
|
||||
void ShowBuildAirToolbar(void)
|
||||
{
|
||||
if (_current_player == OWNER_SPECTATOR) return;
|
||||
DeleteWindowById(WC_BUILD_TOOLBAR, 0);
|
||||
AllocateWindowDescFront(&_air_toolbar_desc, 0);
|
||||
}
|
||||
|
||||
static void BuildAirportPickerWndProc(Window *w, WindowEvent *e)
|
||||
{
|
||||
switch(e->event) {
|
||||
switch (e->event) {
|
||||
case WE_PAINT: {
|
||||
int sel;
|
||||
int rad = 4; // default catchment radious
|
||||
uint32 avail_airports;
|
||||
|
||||
if (WP(w,def_d).close)
|
||||
return;
|
||||
w->disabled_state = 0;
|
||||
if (WP(w,def_d).close) return;
|
||||
|
||||
sel = _selected_airport_type;
|
||||
// FIXME -- BuildAirportPickerWndProc - set availability of airports by year, instead of airplane
|
||||
if (!(_avail_aircraft & 1)) { w->disabled_state |= (1<<3); if (sel == AT_SMALL) sel = AT_LARGE; }
|
||||
if (!(_avail_aircraft & 2)) { w->disabled_state |= (1<<4); if (sel == AT_LARGE) sel = AT_SMALL; }
|
||||
if (!(_avail_aircraft & 4)) { w->disabled_state |= (1<<5); } // heliport
|
||||
// 1980-1-1 is --> 21915
|
||||
// 1990-1-1 is --> 25568
|
||||
if (_date < 21915) {w->disabled_state |= (1<<6);} // metropilitan airport 1980
|
||||
if (_date < 25568) {w->disabled_state |= (1<<7);} // international airport 1990
|
||||
avail_airports = GetValidAirports();
|
||||
|
||||
if (!HASBIT(avail_airports, 0) && sel == AT_SMALL) sel = AT_LARGE;
|
||||
if (!HASBIT(avail_airports, 1) && sel == AT_LARGE) sel = AT_SMALL;
|
||||
|
||||
/* 'Country Airport' starts at widget 3, and if its bit is set, it is available,
|
||||
* so take its opposite value to set the disabled_state. There are only 5 available
|
||||
* airports, so XOr with 0x1F (1 1111) */
|
||||
w->disabled_state = (avail_airports ^ 0x1F) << 3;
|
||||
|
||||
_selected_airport_type = sel;
|
||||
// select default the coverage area to 'Off' (8)
|
||||
w->click_state = ((1<<3) << sel) | ((1<<8) << _station_show_coverage);
|
||||
SetTileSelectSize(_airport_size_x[sel],_airport_size_y[sel]);
|
||||
if (_station_show_coverage) SetTileSelectBigSize(-4, -4, 8, 8);
|
||||
|
||||
if (_patches.modified_catchment) {
|
||||
switch (sel) {
|
||||
case AT_OILRIG: rad = CA_AIR_OILPAD; break;
|
||||
case AT_HELIPORT: rad = CA_AIR_HELIPORT; break;
|
||||
case AT_SMALL: rad = CA_AIR_SMALL; break;
|
||||
case AT_LARGE: rad = CA_AIR_LARGE; break;
|
||||
case AT_METROPOLITAN: rad = CA_AIR_METRO; break;
|
||||
case AT_INTERNATIONAL: rad = CA_AIR_INTER; break;
|
||||
}
|
||||
}
|
||||
|
||||
if (_station_show_coverage) SetTileSelectBigSize(-rad, -rad, 2 * rad, 2 * rad);
|
||||
|
||||
DrawWindowWidgets(w);
|
||||
// strings such as 'Size' and 'Coverage Area'
|
||||
DrawStringCentered(74, 16, STR_305B_SIZE, 0);
|
||||
DrawStringCentered(74, 78, STR_3066_COVERAGE_AREA_HIGHLIGHT, 0);
|
||||
DrawStationCoverageAreaText(2, 104, (uint)-1);
|
||||
DrawStationCoverageAreaText(2, 104, (uint)-1, rad);
|
||||
break;
|
||||
}
|
||||
|
||||
case WE_CLICK: {
|
||||
switch(e->click.widget) {
|
||||
case 0:
|
||||
ResetObjectToPlace();
|
||||
break;
|
||||
case 3: case 4: case 5: case 6: case 7:
|
||||
_selected_airport_type = e->click.widget - 3;
|
||||
SndPlayFx(0x13);
|
||||
SndPlayFx(SND_15_BEEP);
|
||||
SetWindowDirty(w);
|
||||
break;
|
||||
case 8: case 9:
|
||||
_station_show_coverage = e->click.widget - 8;
|
||||
SndPlayFx(0x13);
|
||||
SndPlayFx(SND_15_BEEP);
|
||||
SetWindowDirty(w);
|
||||
break;
|
||||
}
|
||||
@@ -190,20 +203,25 @@ static void BuildAirportPickerWndProc(Window *w, WindowEvent *e)
|
||||
|
||||
CheckRedrawStationCoverage(w);
|
||||
} break;
|
||||
|
||||
case WE_DESTROY:
|
||||
if (!WP(w,def_d).close)
|
||||
ResetObjectToPlace();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const Widget _build_airport_picker_widgets[] = {
|
||||
{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, 7, 11, 147, 0, 13, STR_3001_AIRPORT_SELECTION, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_PANEL, 7, 0, 147, 14, 130, 0x0, STR_NULL},
|
||||
{WWT_NODISTXTBTN, 14, 2, 73, 27, 38, STR_3059_SMALL, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
|
||||
{WWT_NODISTXTBTN, 14, 74, 145, 27, 38, STR_305A_LARGE, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
|
||||
{WWT_NODISTXTBTN, 14, 2, 145, 63, 74, STR_306B_HELIPORT, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
|
||||
{WWT_NODISTXTBTN, 14, 2, 145, 39, 50, STR_305AA_LARGE, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
|
||||
{WWT_NODISTXTBTN, 14, 2, 145, 51, 62, STR_305AB_LARGE, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
|
||||
{ WWT_CLOSEBOX, 14, 14, 73, 88, 98, STR_02DB_OFF, STR_3065_DON_T_HIGHLIGHT_COVERAGE},
|
||||
{ WWT_CLOSEBOX, 14, 74, 133, 88, 98, STR_02DA_ON, STR_3064_HIGHLIGHT_COVERAGE_AREA},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 147, 0, 13, STR_3001_AIRPORT_SELECTION, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 0, 147, 14, 130, 0x0, STR_NULL},
|
||||
{WWT_NODISTXTBTN, RESIZE_NONE, 14, 2, 73, 27, 38, STR_3059_SMALL, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
|
||||
{WWT_NODISTXTBTN, RESIZE_NONE, 14, 74, 145, 27, 38, STR_305A_LARGE, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
|
||||
{WWT_NODISTXTBTN, RESIZE_NONE, 14, 2, 145, 63, 74, STR_306B_HELIPORT, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
|
||||
{WWT_NODISTXTBTN, RESIZE_NONE, 14, 2, 145, 39, 50, STR_305AA_LARGE, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
|
||||
{WWT_NODISTXTBTN, RESIZE_NONE, 14, 2, 145, 51, 62, STR_305AB_LARGE, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 14, 73, 88, 98, STR_02DB_OFF, STR_3065_DON_T_HIGHLIGHT_COVERAGE},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 74, 133, 88, 98, STR_02DA_ON, STR_3064_HIGHLIGHT_COVERAGE_AREA},
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
@@ -215,12 +233,12 @@ static const WindowDesc _build_airport_desc = {
|
||||
BuildAirportPickerWndProc
|
||||
};
|
||||
|
||||
static void ShowBuildAirportPicker()
|
||||
static void ShowBuildAirportPicker(void)
|
||||
{
|
||||
AllocateWindowDesc(&_build_airport_desc);
|
||||
}
|
||||
|
||||
void InitializeAirportGui()
|
||||
void InitializeAirportGui(void)
|
||||
{
|
||||
_selected_airport_type = AT_SMALL;
|
||||
_last_built_aircraft_depot_tile = 0;
|
||||
|
||||
+22
-10
@@ -4,10 +4,6 @@
|
||||
#include "stdafx.h"
|
||||
#include "macros.h"
|
||||
|
||||
// don't forget to change the airport_depots too for larger mapsizes. TILE_X_BITS 16
|
||||
// won't fit in uint16 for example and overflow will occur in the checking code!
|
||||
// TrueLight -- So make it a TileIndex..
|
||||
|
||||
typedef struct AirportMovingData {
|
||||
int x,y;
|
||||
byte flag;
|
||||
@@ -267,7 +263,8 @@ static const AirportMovingData _airport_moving_data_oilrig[9] = {
|
||||
/////**********Movement Machine on Airports*********************///////
|
||||
// first element of depots array tells us how many depots there are (to know size of array)
|
||||
// this may be changed later when airports are moved to external file
|
||||
static const TileIndex _airport_depots_country[] = {1, TILE_XY(3,0)};
|
||||
static const TileIndexDiffC _airport_depots_country[] = {{3, 0}};
|
||||
static const byte _airport_terminal_country[] = {1, 2};
|
||||
static const AirportFTAbuildup _airport_fta_country[] = {
|
||||
{ 0,HANGAR,NOTHING_block,1},
|
||||
{ 1,255,AIRPORT_BUSY_block,0}, {1,HANGAR,0,0}, {1,TERM1,TERM1_block,2}, {1,TERM2,0,4}, {1,HELITAKEOFF,0,19}, {1,0,0,6},
|
||||
@@ -297,7 +294,8 @@ static const AirportFTAbuildup _airport_fta_country[] = {
|
||||
{MAX_ELEMENTS,0,0,0} // end marker. DO NOT REMOVE
|
||||
};
|
||||
|
||||
static const TileIndex _airport_depots_city[] = {1, TILE_XY(5,0)};
|
||||
static const TileIndexDiffC _airport_depots_city[] = {{5, 0}};
|
||||
static const byte _airport_terminal_city[] = {1, 3};
|
||||
static const AirportFTAbuildup _airport_fta_city[] = {
|
||||
{ 0,HANGAR,NOTHING_block,1}, {0,TAKEOFF,OUT_WAY_block,1}, {0,0,0,1},
|
||||
{ 1,255,TAXIWAY_BUSY_block,0}, {1,HANGAR,0,0}, {1,TERM2,0,6}, {1,TERM3,0,6}, {1,0,0,7}, // for all else, go to 7
|
||||
@@ -331,7 +329,8 @@ static const AirportFTAbuildup _airport_fta_city[] = {
|
||||
{MAX_ELEMENTS,0,0,0} // end marker. DO NOT REMOVE
|
||||
};
|
||||
|
||||
static const TileIndex _airport_depots_metropolitan[] = {1, TILE_XY(5,0)};
|
||||
static const TileIndexDiffC _airport_depots_metropolitan[] = {{5, 0}};
|
||||
static const byte _airport_terminal_metropolitan[] = {1, 3};
|
||||
static const AirportFTAbuildup _airport_fta_metropolitan[] = {
|
||||
{ 0,HANGAR,NOTHING_block,1},
|
||||
{ 1,255,TAXIWAY_BUSY_block,0}, {1,HANGAR,0,0}, {1,TERM2,0,6}, {1,TERM3,0,6}, {1,0,0,7}, // for all else, go to 7
|
||||
@@ -367,7 +366,9 @@ static const AirportFTAbuildup _airport_fta_metropolitan[] = {
|
||||
{MAX_ELEMENTS,0,0,0} // end marker. DO NOT REMOVE
|
||||
};
|
||||
|
||||
static const TileIndex _airport_depots_international[] = {2, TILE_XY(0,3), TILE_XY(6,1)};
|
||||
static const TileIndexDiffC _airport_depots_international[] = {{0, 3}, {6, 1}};
|
||||
static const byte _airport_terminal_international[] = {2, 3, 3};
|
||||
static const byte _airport_helipad_international[] = {1, 2};
|
||||
static const AirportFTAbuildup _airport_fta_international[] = {
|
||||
{ 0,HANGAR,NOTHING_block,2}, {0,255,TERM_GROUP1_block,0}, {0,255,TERM_GROUP2_ENTER1_block,1}, {0,HELITAKEOFF,HELIPAD1_block,2}, {0,0,0,2},
|
||||
{ 1,HANGAR,NOTHING_block,3}, {1,255,HANGAR2_AREA_block,1}, {1,HELITAKEOFF,HELIPAD2_block,3}, {1,0,0,3},
|
||||
@@ -429,7 +430,8 @@ static const AirportFTAbuildup _airport_fta_international[] = {
|
||||
{MAX_ELEMENTS,0,0,0} // end marker. DO NOT REMOVE
|
||||
};
|
||||
|
||||
static const TileIndex _airport_depots_heliport_oilrig[] = {0};
|
||||
// heliports, oilrigs don't have depots
|
||||
static const byte _airport_helipad_heliport_oilrig[] = {1, 1};
|
||||
static const AirportFTAbuildup _airport_fta_heliport_oilrig[] = {
|
||||
{0,HELIPAD1,HELIPAD1_block,1},
|
||||
{1,HELITAKEOFF,NOTHING_block,0}, // takeoff
|
||||
@@ -444,12 +446,22 @@ static const AirportFTAbuildup _airport_fta_heliport_oilrig[] = {
|
||||
{MAX_ELEMENTS,0,0,0} // end marker. DO NOT REMOVE
|
||||
};
|
||||
|
||||
static const AirportMovingData * const _airport_moving_datas[6] = {
|
||||
static const AirportMovingData * const _airport_moving_datas[] = {
|
||||
_airport_moving_data_country, // Country Airfield (small) 4x3
|
||||
_airport_moving_data_town, // City Airport (large) 6x6
|
||||
_airport_moving_data_heliport, // Heliport
|
||||
_airport_moving_data_metropolitan, // Metropolitain Airport (large) - 2 runways
|
||||
_airport_moving_data_international, // International Airport (xlarge) - 2 runways
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
_airport_moving_data_oilrig // Oilrig
|
||||
};
|
||||
|
||||
|
||||
@@ -19,13 +19,15 @@
|
||||
#include "aystar.h"
|
||||
// This looks in the Hash if a node exists in ClosedList
|
||||
// If so, it returns the PathNode, else NULL
|
||||
PathNode *AyStarMain_ClosedList_IsInList(AyStar *aystar, AyStarNode *node) {
|
||||
static PathNode *AyStarMain_ClosedList_IsInList(AyStar *aystar, AyStarNode *node)
|
||||
{
|
||||
return (PathNode*)Hash_Get(&aystar->ClosedListHash, node->tile, node->direction);
|
||||
}
|
||||
|
||||
// This adds a node to the ClosedList
|
||||
// It makes a copy of the data
|
||||
void AyStarMain_ClosedList_Add(AyStar *aystar, PathNode *node) {
|
||||
static void AyStarMain_ClosedList_Add(AyStar *aystar, PathNode *node)
|
||||
{
|
||||
// Add a node to the ClosedList
|
||||
PathNode *new_node = malloc(sizeof(PathNode));
|
||||
*new_node = *node;
|
||||
@@ -34,14 +36,16 @@ void AyStarMain_ClosedList_Add(AyStar *aystar, PathNode *node) {
|
||||
|
||||
// Checks if a node is in the OpenList
|
||||
// If so, it returns the OpenListNode, else NULL
|
||||
OpenListNode *AyStarMain_OpenList_IsInList(AyStar *aystar, AyStarNode *node) {
|
||||
static OpenListNode *AyStarMain_OpenList_IsInList(AyStar *aystar, AyStarNode *node)
|
||||
{
|
||||
return (OpenListNode*)Hash_Get(&aystar->OpenListHash, node->tile, node->direction);
|
||||
}
|
||||
|
||||
// Gets the best node from OpenList
|
||||
// returns the best node, or NULL of none is found
|
||||
// Also it deletes the node from the OpenList
|
||||
OpenListNode *AyStarMain_OpenList_Pop(AyStar *aystar) {
|
||||
static OpenListNode *AyStarMain_OpenList_Pop(AyStar *aystar)
|
||||
{
|
||||
// Return the item the Queue returns.. the best next OpenList item.
|
||||
OpenListNode* res = (OpenListNode*)aystar->OpenListQueue.pop(&aystar->OpenListQueue);
|
||||
if (res != NULL)
|
||||
@@ -52,7 +56,8 @@ OpenListNode *AyStarMain_OpenList_Pop(AyStar *aystar) {
|
||||
|
||||
// Adds a node to the OpenList
|
||||
// It makes a copy of node, and puts the pointer of parent in the struct
|
||||
void AyStarMain_OpenList_Add(AyStar *aystar, PathNode *parent, AyStarNode *node, int f, int g, int userdata) {
|
||||
static void AyStarMain_OpenList_Add(AyStar *aystar, PathNode *parent, AyStarNode *node, int f, int g)
|
||||
{
|
||||
// Add a new Node to the OpenList
|
||||
OpenListNode* new_node = malloc(sizeof(OpenListNode));
|
||||
new_node->g = g;
|
||||
@@ -101,7 +106,7 @@ int AyStarMain_CheckTile(AyStar *aystar, AyStarNode *current, OpenListNode *pare
|
||||
|
||||
// Check if this item is already in the OpenList
|
||||
if ((check = AyStarMain_OpenList_IsInList(aystar, current)) != NULL) {
|
||||
int i;
|
||||
uint i;
|
||||
// Yes, check if this g value is lower..
|
||||
if (new_g > check->g) return AYSTAR_DONE;
|
||||
aystar->OpenListQueue.del(&aystar->OpenListQueue, check, 0);
|
||||
@@ -115,7 +120,7 @@ int AyStarMain_CheckTile(AyStar *aystar, AyStarNode *current, OpenListNode *pare
|
||||
aystar->OpenListQueue.push(&aystar->OpenListQueue, check, new_f);
|
||||
} else {
|
||||
// A new node, add him to the OpenList
|
||||
AyStarMain_OpenList_Add(aystar, closedlist_parent, current, new_f, new_g, 0);
|
||||
AyStarMain_OpenList_Add(aystar, closedlist_parent, current, new_f, new_g);
|
||||
}
|
||||
|
||||
return AYSTAR_DONE;
|
||||
@@ -215,7 +220,7 @@ void AyStarMain_Clear(AyStar *aystar) {
|
||||
int AyStarMain_Main(AyStar *aystar) {
|
||||
int r, i = 0;
|
||||
// Loop through the OpenList
|
||||
// Quit if result is no AYSTAR_STILL_BUSY or is more then loops_per_tick
|
||||
// Quit if result is no AYSTAR_STILL_BUSY or is more than loops_per_tick
|
||||
while ((r = aystar->loop(aystar)) == AYSTAR_STILL_BUSY && (aystar->loops_per_tick == 0 || ++i < aystar->loops_per_tick)) { }
|
||||
#ifdef AYSTAR_DEBUG
|
||||
if (r == AYSTAR_FOUND_END_NODE)
|
||||
@@ -243,12 +248,14 @@ int AyStarMain_Main(AyStar *aystar) {
|
||||
* if wanted. You should make sure that clear() is called before adding nodes
|
||||
* if the AyStar has been used before (though the normal main loop calls
|
||||
* clear() automatically when the algorithm finishes
|
||||
* g is the cost for starting with this node.
|
||||
*/
|
||||
void AyStarMain_AddStartNode(AyStar *aystar, AyStarNode *start_node) {
|
||||
void AyStarMain_AddStartNode(AyStar *aystar, AyStarNode *start_node, uint g) {
|
||||
#ifdef AYSTAR_DEBUG
|
||||
printf("[AyStar] Starting A* Algorithm from node (%d, %d, %d)\n", GET_TILE_X(start_node->tile), GET_TILE_Y(start_node->tile), start_node->direction);
|
||||
printf("[AyStar] Starting A* Algorithm from node (%d, %d, %d)\n",
|
||||
TileX(start_node->tile), TileY(start_node->tile), start_node->direction);
|
||||
#endif
|
||||
AyStarMain_OpenList_Add(aystar, NULL, start_node, 0, 0, 0);
|
||||
AyStarMain_OpenList_Add(aystar, NULL, start_node, 0, g);
|
||||
}
|
||||
|
||||
void init_AyStar(AyStar* aystar, Hash_HashProc hash, uint num_buckets) {
|
||||
|
||||
@@ -56,6 +56,14 @@ typedef struct AyStar AyStar;
|
||||
* AYSTAR_FOUND_END_NODE : indicates this is the end tile
|
||||
* AYSTAR_DONE : indicates this is not the end tile (or direction was wrong)
|
||||
*/
|
||||
/*
|
||||
* The 2nd parameter should be OpenListNode, and NOT AyStarNode. AyStarNode is
|
||||
* part of OpenListNode and so it could be accessed without any problems.
|
||||
* The good part about OpenListNode is, and how AIs use it, that you can
|
||||
* access the parent of the current node, and so check if you, for example
|
||||
* don't try to enter the file tile with a 90-degree curve. So please, leave
|
||||
* this an OpenListNode, it works just fine -- TrueLight
|
||||
*/
|
||||
typedef int32 AyStar_EndNodeCheck(AyStar *aystar, OpenListNode *current);
|
||||
|
||||
/*
|
||||
@@ -89,7 +97,7 @@ typedef void AyStar_GetNeighbours(AyStar *aystar, OpenListNode *current);
|
||||
typedef void AyStar_FoundEndNode(AyStar *aystar, OpenListNode *current);
|
||||
|
||||
// For internal use, see aystar.c
|
||||
typedef void AyStar_AddStartNode(AyStar *aystar, AyStarNode* start_node);
|
||||
typedef void AyStar_AddStartNode(AyStar *aystar, AyStarNode* start_node, uint g);
|
||||
typedef int AyStar_Main(AyStar *aystar);
|
||||
typedef int AyStar_Loop(AyStar *aystar);
|
||||
typedef int AyStar_CheckTile(AyStar *aystar, AyStarNode *current, OpenListNode *parent);
|
||||
@@ -153,7 +161,7 @@ struct AyStar {
|
||||
};
|
||||
|
||||
|
||||
void AyStarMain_AddStartNode(AyStar *aystar, AyStarNode *start_node);
|
||||
void AyStarMain_AddStartNode(AyStar *aystar, AyStarNode *start_node, uint g);
|
||||
int AyStarMain_Main(AyStar *aystar);
|
||||
int AyStarMain_Loop(AyStar *aystar);
|
||||
int AyStarMain_CheckTile(AyStar *aystar, AyStarNode *current, OpenListNode *parent);
|
||||
|
||||
+17
-15
@@ -1,11 +1,13 @@
|
||||
#include "stdafx.h"
|
||||
#include "ttd.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
#include "map.h"
|
||||
#include "window.h"
|
||||
#include "gui.h"
|
||||
#include "viewport.h"
|
||||
#include "gfx.h"
|
||||
#include "command.h"
|
||||
#include "sound.h"
|
||||
|
||||
static struct BridgeData {
|
||||
int count;
|
||||
@@ -22,9 +24,9 @@ extern const PalSpriteID _bridge_sprites[MAX_BRIDGES];
|
||||
extern const uint16 _bridge_speeds[MAX_BRIDGES];
|
||||
extern const StringID _bridge_material[MAX_BRIDGES];
|
||||
|
||||
static void CcBuildBridge(bool success, uint tile, uint32 p1, uint32 p2)
|
||||
void CcBuildBridge(bool success, uint tile, uint32 p1, uint32 p2)
|
||||
{
|
||||
if (success) { SndPlayTileFx(0x25, tile); }
|
||||
if (success) SndPlayTileFx(SND_27_BLACKSMITH_ANVIL, tile);
|
||||
}
|
||||
|
||||
static void BuildBridge(Window *w, int i)
|
||||
@@ -45,9 +47,9 @@ static void BuildBridgeWndProc(Window *w, WindowEvent *e)
|
||||
for(i=0; i < 4 && i + w->vscroll.pos < _bridge.count; i++) {
|
||||
int ind = _bridge.indexes[i + w->vscroll.pos];
|
||||
|
||||
SET_DPARAM32(2, _bridge.costs[i + w->vscroll.pos]);
|
||||
SET_DPARAM16(1, (_bridge_speeds[ind] >> 4) * 10);
|
||||
SET_DPARAM16(0, _bridge_material[ind]);
|
||||
SetDParam(2, _bridge.costs[i + w->vscroll.pos]);
|
||||
SetDParam(1, (_bridge_speeds[ind] >> 4) * 10);
|
||||
SetDParam(0, _bridge_material[ind]);
|
||||
DrawSprite(_bridge_sprites[ind], 3, 15 + i * 22);
|
||||
|
||||
DrawString(44, 15 + i*22 , STR_500D, 0);
|
||||
@@ -75,10 +77,10 @@ static void BuildBridgeWndProc(Window *w, WindowEvent *e)
|
||||
}
|
||||
|
||||
static const Widget _build_bridge_widgets[] = {
|
||||
{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, 7, 11, 199, 0, 13, STR_100D_SELECT_RAIL_BRIDGE, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_MATRIX, 7, 0, 188, 14, 101, 0x401, STR_101F_BRIDGE_SELECTION_CLICK},
|
||||
{ WWT_SCROLLBAR, 7, 189, 199, 14, 101, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 199, 0, 13, STR_100D_SELECT_RAIL_BRIDGE, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_MATRIX, RESIZE_NONE, 7, 0, 187, 14, 101, 0x401, STR_101F_BRIDGE_SELECTION_CLICK},
|
||||
{ WWT_SCROLLBAR, RESIZE_NONE, 7, 188, 199, 14, 101, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
@@ -92,10 +94,10 @@ static const WindowDesc _build_bridge_desc = {
|
||||
|
||||
|
||||
static const Widget _build_road_bridge_widgets[] = {
|
||||
{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, 7, 11, 199, 0, 13, STR_1803_SELECT_ROAD_BRIDGE, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_MATRIX, 7, 0, 188, 14, 101, 0x401, STR_101F_BRIDGE_SELECTION_CLICK},
|
||||
{ WWT_SCROLLBAR, 7, 189, 199, 14, 101, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 199, 0, 13, STR_1803_SELECT_ROAD_BRIDGE, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_MATRIX, RESIZE_NONE, 7, 0, 187, 14, 101, 0x401, STR_101F_BRIDGE_SELECTION_CLICK},
|
||||
{ WWT_SCROLLBAR, RESIZE_NONE, 7, 188, 199, 14, 101, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
@@ -159,6 +161,6 @@ void ShowBuildBridgeWindow(uint start, uint end, byte bridge_type)
|
||||
w->vscroll.cap = 4;
|
||||
w->vscroll.count = (byte)j;
|
||||
} else {
|
||||
ShowErrorMessage(errmsg, STR_5015_CAN_T_BUILD_BRIDGE_HERE, GET_TILE_X(end) * 16, GET_TILE_Y(end) * 16);
|
||||
ShowErrorMessage(errmsg, STR_5015_CAN_T_BUILD_BRIDGE_HERE, TileX(end) * 16, TileY(end) * 16);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
#include "stdafx.h"
|
||||
#include "ttd.h"
|
||||
#include "functions.h"
|
||||
|
||||
// If you add a callback for DoCommandP, also add the callback in here
|
||||
// see below for the full list!
|
||||
// If you don't do it, it won't work across the network!!
|
||||
|
||||
/* aircraft_gui.c */
|
||||
CommandCallback CcBuildAircraft;
|
||||
|
||||
/* airport_gui.c */
|
||||
CommandCallback CcBuildAirport;
|
||||
|
||||
/* bridge_gui.c */
|
||||
CommandCallback CcBuildBridge;
|
||||
|
||||
/* dock_gui.c */
|
||||
CommandCallback CcBuildDocks;
|
||||
CommandCallback CcBuildCanal;
|
||||
|
||||
/* main_gui.c */
|
||||
CommandCallback CcPlaySound10;
|
||||
CommandCallback CcPlaceSign;
|
||||
CommandCallback CcTerraform;
|
||||
//CommandCallback CcDemolish;
|
||||
CommandCallback CcBuildTown;
|
||||
|
||||
/* rail_gui.c */
|
||||
CommandCallback CcPlaySound1E;
|
||||
CommandCallback CcRailDepot;
|
||||
CommandCallback CcStation;
|
||||
CommandCallback CcBuildRailTunnel;
|
||||
|
||||
/* road_gui.c */
|
||||
CommandCallback CcPlaySound1D;
|
||||
CommandCallback CcBuildRoadTunnel;
|
||||
CommandCallback CcRoadDepot;
|
||||
|
||||
/* roadveh_gui.c */
|
||||
CommandCallback CcBuildRoadVeh;
|
||||
|
||||
/* ship_gui.c */
|
||||
CommandCallback CcBuildShip;
|
||||
|
||||
/* train_gui.c */
|
||||
CommandCallback CcBuildWagon;
|
||||
CommandCallback CcBuildLoco;
|
||||
|
||||
CommandCallback *_callback_table[] = {
|
||||
/* 0x00 */ NULL,
|
||||
/* 0x01 */ CcBuildAircraft,
|
||||
/* 0x02 */ CcBuildAirport,
|
||||
/* 0x03 */ CcBuildBridge,
|
||||
/* 0x04 */ CcBuildCanal,
|
||||
/* 0x05 */ CcBuildDocks,
|
||||
/* 0x06 */ CcBuildLoco,
|
||||
/* 0x07 */ CcBuildRoadVeh,
|
||||
/* 0x08 */ CcBuildShip,
|
||||
/* 0x09 */ CcBuildTown,
|
||||
/* 0x0A */ CcBuildRoadTunnel,
|
||||
/* 0x0B */ CcBuildRailTunnel,
|
||||
/* 0x0C */ CcBuildWagon,
|
||||
/* 0x0D */ CcRoadDepot,
|
||||
/* 0x0E */ CcRailDepot,
|
||||
/* 0x0F */ CcPlaceSign,
|
||||
/* 0x10 */ CcPlaySound10,
|
||||
/* 0x11 */ CcPlaySound1D,
|
||||
/* 0x12 */ CcPlaySound1E,
|
||||
/* 0x13 */ CcStation,
|
||||
/* 0x14 */ CcTerraform
|
||||
};
|
||||
|
||||
const int _callback_table_count = lengthof(_callback_table);
|
||||
@@ -0,0 +1,7 @@
|
||||
#ifndef CALLBACK_TABLE_H
|
||||
#define CALLBACK_TABLE_H
|
||||
|
||||
extern CommandCallback *_callback_table[];
|
||||
extern const int _callback_table_count;
|
||||
|
||||
#endif
|
||||
+330
@@ -1,3 +1,333 @@
|
||||
0.4.0.1 (2005-05-21)
|
||||
------------------------------------------------------------------------
|
||||
|
||||
- Feature: Add 'clear' command and CTRL+L to empty console window
|
||||
- Feature: add the possibility to print out the current debug-level
|
||||
- Fix: [MacOSX] default path for midi player on mac is now correct again
|
||||
- Fix: Updated makefile for FreeBSD
|
||||
- Fix: Text overflows in about box
|
||||
- Fix: Link error while compiling as dedicated server
|
||||
- Fix: Do not execute empty commands
|
||||
- Fix: Make OpenTTD icon look good on Win2K and earlier
|
||||
- Fix: NetworkUDPRemoveAdvertise wasn't completely correct
|
||||
- Fix: Signs in multiplayer didn't work
|
||||
- Fix: Dedicated server desyncs
|
||||
- Fix: [ 1197216 ] Error: !invalid string id 0 in GetString, dedicated server endgame crash
|
||||
- Fix: Don't allow things to be renamed to nothing
|
||||
- Fix: Windows installer deletes spritecache files on uninstall
|
||||
- Fix: Depot window did not get redrawn when a non-train-engine was sold
|
||||
- Fix: Do not scroll the game with the arrow keys when the chatbox is open
|
||||
- Fix: Remove warning from release build when assertions are no longer active
|
||||
- Fix: It was possible to open more than one tree window
|
||||
|
||||
|
||||
0.4.0 (2005-05-15)
|
||||
------------------------------------------------------------------------
|
||||
- Feature: Bigger maps. Enjoy playing up to 2028x2048 (64 times as big as you were used to!)
|
||||
- Feature: New realistic acceleration; should be much better. Inlcudes gigger penalty on narrow curves and speedlimits in depots/stations
|
||||
- Feature: It is now possible to build multiple road stations (up to 8) on a single station (multibus).
|
||||
- Feature: New PathFinder (NPF). Support for train/road and ship based on A*. No more braindead pathfinding
|
||||
- Feature: Dynamic towns/industries/stations/vehicles/signs/orders/everything, up to 64K
|
||||
- Feature: Brand new OldLoader so OpenTTD is TTD(Patch) compatible again. Also endian safe
|
||||
- Feature: Even better newgrf support, except for callbacks, everything works (ok, almost)
|
||||
- Feature: Improved multiplayer. More console options, less desyncs and more fun
|
||||
- Feature: Protected OpenTTD from interference of hacked clients, so it should be safe to play again.
|
||||
- Feature: [ 1093261 ] Saving vehicle sorting criteria for each vehicle type
|
||||
- Feature: [ 1107690 ] Resizable orders GUI
|
||||
- Feature: [ 1166978 ] Focus keyboard on input-box in Multiplayer Menu
|
||||
- Feature: [ 1174313 ] terrain hotkeys nonfunctional in scenario editor (D,Q,W,E,R,T,Y,U fltr)
|
||||
- Feature: Complete rework of console and new commands like ls, save, load, help, etc.
|
||||
- Feature: Signs are shown in the colour of the player who created them
|
||||
- Feature: Add cheat option to set production of raw-material industries in game
|
||||
- Feature: Replace trian GUI remembers railtype selected from the dropdown menu
|
||||
- Feature: Improved Autoreplace
|
||||
- Feature: many more smaller features :D
|
||||
- Fix: [ 1108618 ] A wrong error message was displayed when trying to
|
||||
- Fix: [ 1110407 ] Game does not crash any more when a newgrf file doesn't exist
|
||||
- Fix: [ 1112469 ] Clearing land for free by reallocating HQ
|
||||
- Fix: [ 1112469 ] Clearing land for free by reallocating HQ
|
||||
- Fix: [ 1113037 ] crash when accessing hi-scores in editor, it is now disabled.
|
||||
- Fix: [ 1113399 ] Game no longer crashes when right-clicking a disabled Full Load button
|
||||
- Fix: [ 1114100 ] Dedicated server boots again
|
||||
- Fix: [ 1114950 ] Game crashed sometimes when there were no industries in the map
|
||||
- Fix: [ 1115200 ] In the main menu, when starting a new game while the load game dialog is open, openttd asserts.
|
||||
- Fix: [ 1117538 ] non-stop orders are no longer accidently skipped
|
||||
- Fix: [ 1116619 ] Generate the correct smoke type for diesel trains
|
||||
- Fix: [ 1119308 ] Max passengers / mail variables are now 32 bit
|
||||
- Fix: [ 1109400 ] Better test if a string actually contains any console command
|
||||
- Fix: [ 1108637 ] 'Play scenario' now loads game options and difficulty, 'Load game' starts game with user-selected values.
|
||||
- Fix: [ 1143587 ] carriages of newgrfs can be refitted again
|
||||
- Fix: [ 1117730 ] Production values of temperate-climate banks can now be altered
|
||||
- Fix: [ 1118810 ] openttd: ship_cmd.c:642 ... Assertion failed. Mapwrap fixed in ship_cmd.c (was implicitely ok before biggermaps).
|
||||
- Fix: [ 1117327 ] Assertion error on kick. When a company is cleaned all its windows need to be closed. For global vehicle lists, the no-staiton index of -1 was not taken into account
|
||||
- Fix: [ 1114261 ] Speeding up when pressing ALT+TAB (Windows)
|
||||
- Fix: [ 1149403 ] Signals dissaper after typing text and pressing enter!. Signs in Scenario Editor have no owner so ignore that.
|
||||
- Fix: [ 1149766 ] Single tile Bridge in Volcano City scenario. Some bridges still had the old single-tile bridge bug that was caused by improper town growth in combination with DC_AUTO. Fixed the scenario.
|
||||
- Fix: [ 1119147 ] Stop startup memory corruption crash using optimized MSVC6. MSVC6 workaround as it's too stupid again for its own good
|
||||
- Fix: [ 1101874 ] Dedicated server now accepts '-g' (load game) as param
|
||||
- Fix: [ 1155696 ] Crash with german umlauts in station names.
|
||||
- Fix: [ 1158618 ] Segmentation fault when loading savegame, out of bounds array check.
|
||||
- Fix: [ 1149487 ] Autosave ignoring settings
|
||||
- Fix: [ 1024703 ] Infinite access for A:\ (win32). Patch [1171208]. Only requery drive(s) if the user changes a directory, also surpress the OS error box that pops up on some windows machines.
|
||||
- Fix: [ 1095110 ] Create Lake and draggable Create Desert tools
|
||||
- Fix: [ 1172878 ] Trains "Go to depot" button: click twice skip to next order
|
||||
- Fix: [ 1146215 ] Engine power not updated w/auto replace" autoreplace now forces an update of the cache.
|
||||
- Fix: [ 1173690 ] Path displaying as "C:\\" in saveload window win32-only
|
||||
- Fix: [ 1179892 ] click & drag removal of road assertion fail.
|
||||
- Fix: [ 1174237 ] Max loan always in euros, use _opt_ptr instead of _opt
|
||||
- Fix: [ 1184201 ] AI orders its vehicles to a competitor's truck stop.
|
||||
- Fix: [ 1188986 ] Song in main menu screen should loop when it ends.
|
||||
- Fix: [ 1188777 ] Non-existing sprite #5125 (presignal). The DOS grf file trgi.grf has 6 less sprites than the windows one.
|
||||
- Fix: [ 1190625 ] Changing mapsize crashes game with highlighting.
|
||||
- Fix: [ 1190896 1184378 ] [NPF] Trains ignoring their railtype (mono, maglev)
|
||||
- Fix: [ 1202115 ] Clicking shipslist on bouy asserts GetPlayer().
|
||||
- Fix: [ 1187613 ] No HQ present for competitor, disable 'View HQ' button
|
||||
- Fix: [ 1193048 ] Pre-signal stays red when there is only a single exit signal
|
||||
- Fix: [ 1185176 ] Train in tunnel is not properly detected by signal code
|
||||
- Fix: [newgrf] rotors of custom helicopters are displayed correctly in the hangar window
|
||||
- Fix: Scenario Editor now handles human-made roads better (try to build a city layout before placing the city, finally that works very nice)
|
||||
- Fix: [Newgrf] helicopters are correctly recognized
|
||||
- Fix: [autoreplace] made sure that planes only show planes in replace GUI and helicopters only show helicopters
|
||||
- Fix: (Work around?) crash when generating tropical maps
|
||||
- Fix: [autoreplace] Cheaters can no longer exploit autoreplace to get vehicles, that's not invented yet
|
||||
- Fix: [autoreplace] Fixed a stupid bug introduced in r1687, that made a crash if anybody tried to autoreplace anything but an aircraft
|
||||
- Fix: expand railroad stations beyond maximum spread
|
||||
- Fix: [autoreplace] fixed a typo that could prevent autoreplaced aircraft from automatically go to a hangar
|
||||
- Fix: Hacked clients can no longer be used to build vehicles that are not available yet
|
||||
- Fix: Minimum profit of vehicles was calculated wrong for Performance Rating
|
||||
- Fix: no longer a station where you only unload is bad for your town-rating
|
||||
- Fix: Crash in scenario-editor with terraforming out-of-map bounds.
|
||||
- Fix: Game would crash if you full-screened with the 'fullscreen' button than chose a resolution from the dropdown box that was no longer valid.
|
||||
- Fix: Scrolling with the arrow keys is now smooth and it now also scrolls exactly in tile direction if e.g. up and left are pressed
|
||||
- Fix: many more fixes but I am too tired to list them all
|
||||
|
||||
|
||||
0.3.6 (2005-01-24)
|
||||
------------------------------------------------------------------------
|
||||
- Feature: resizable windows. All useful windows are already made resizable.
|
||||
- Feature: highscore chart (accessible from the difficulty window) with top5 companies for a given difficulty (select the difficulty in the menu)
|
||||
- Feature: endgame score on 1 jan 2051 where you are added to the highscore if sufficiently large points have been accumulated. Game is paused while
|
||||
- Feature: Visually enhanced autorail placing
|
||||
When using the autorail tool, the rail pieces which are going to be build are highlighted.
|
||||
If a piece is shown in red, this indicates that the slope/rail combination is impossible. It does not tell you if
|
||||
the rail line construction might not be possible because of other obstacles, e.g. houses or water.
|
||||
- Feature: Autoreplace Vehicles (accessible from the vehicle lists)
|
||||
This feature works much like autorenew, but it will get you a new engine type instead of a new one of the same type. Once
|
||||
ordered, it will automatically replace the engines while they visits a depot. The GUI for setting this up have been added on the
|
||||
vehicle overview windows (Bjarni)
|
||||
- Feature: A counter to tell how many engines you have of each type to the autoreplace vehicle windows (Bjarni)
|
||||
- Feature: A display for the total map population to the town display
|
||||
- Feature: [network] RCon (Remote Connection).
|
||||
A server can set: 'set rcon_pw <password>' to enable rcon
|
||||
A client can now do: 'rcon <password> "<command>"'
|
||||
!!Warning!!: do not give your rcon password to people you do not thrust!
|
||||
- Feature: hotkeys for dock and airport toolbar (see http://wiki.openttd.org/index.php/Hotkeys)
|
||||
- Feature: [Network] banning system (mostly tnx to guru3) A server can ban people via ClientList using 'ban', 'unban', 'banlist'.
|
||||
- Feature: [Network] server can now pause and unpause a game through the console. Use 'pause' and 'unpause'
|
||||
- Feature: [OS/2] OS/2 support is now finished (Fixes for networking, file selection, keyboard input, plus many other minor issues)
|
||||
- Feature: [SDL] Show revision number in window title
|
||||
- Feature: [Unix] Check which gcc version is present and only set available compiler flags
|
||||
- Feature: [Windows] CTRL+V (Paste) now works on all editboxes. This includes 'Add Server', chat, etc.
|
||||
- Feature: [Windows] dedicated server is now functioning correctly
|
||||
- Feature: Addded keyboard shortcuts for the order window
|
||||
- Feature: Aircraft refit options have been restricted to "sane" values.
|
||||
- Feature: allows setting the production values of the rawmaterial producing industries in the editor
|
||||
- Feature: console support for loading maps. Use 'load', 'list_files' and 'goto_dir' to navigate and load games.
|
||||
- Feature: Display server port in the multiplayer game info window
|
||||
- Feature: dynamite in landscaping toolbar (hotkey 'D')
|
||||
- Feature: Improved Network Lobby GUI with a green dot if company income is positive (else red dot) and lock icon if company is password protected
|
||||
- Feature: Make ottd compile on Zeta
|
||||
- Feature: MD5 hash check for TTD files (The original TTD files are now checked with a MD5 sum to determine which version of the grf files is used and to warn about possible file corruptions. Thanks to ledow for the original patch)
|
||||
- Feature: New companies receive a 5-year protection period against buying-up
|
||||
- Feature: norwegian townnames (Simen Graaten)
|
||||
- Feature: Order Checking is only execute for ONE vehicle in an order-share system
|
||||
- Feature: Passengers aircraft now ignore the amount of mail for "full load any" options
|
||||
- Feature: place multiple accepting industies nearby in the editor mode if the appropriate patches are set
|
||||
- Feature: population in label of the town (patch setting)
|
||||
- Feature: scrolling credits list (in alphabetical order)
|
||||
- Feature: Train window now shows the number of vehicles per row (mpetrov)
|
||||
- Feature: [ 1039061 ] Swiss town-names (vulvulune)
|
||||
- Feature: [ 1090950 ] Adding 16:10 resolutions for mainly laptops (doode)
|
||||
- Feature: [ 1098254 ] (dis)Allow Shares. Add patch options to allow buying/selling of shares (Hackykid)
|
||||
- Fix: [ 1031451 ] Catchment area shows when buying sign
|
||||
- Fix: [ 1040119 ] Flood and wagons in depot
|
||||
- Fix: [ 1050990 ] Buying trains sometimes accounted for incorrectly.
|
||||
- Fix: [ 1084074 ] Delayed news messages
|
||||
- Fix: [ 1090495 ] Slopes under high bridges weren't flooded
|
||||
- Fix: [ 1092473 ] In scenario editor, when trees are placed randomly, they are no longer placed on farmland
|
||||
- Fix: [ 1092661 ] On create, the scrollbar of the server-list was not updated
|
||||
- Fix: [ 1092707 ] placing rocks in scenario editor. You can place rocks on trees and vice versa
|
||||
- Fix: [ 1093200 ] Drive side in new games. Setting the driver side is possible during the game until someone buys road vehicles. In networked games only the server can change it.
|
||||
- Fix: [ 1093466 ] no more glitches with many maps in the scenario list when creating server
|
||||
- Fix: [ 1093485 ] Dissappearing rocks in Scenario Editor
|
||||
- Fix: [ 1094092 ] Toolbars accessible via keyboard in spectator mode
|
||||
- Fix: [ 1095020 ] When all stations in an aircraft's order list are demolished, the plane eventually crashes (running out of fuel)
|
||||
- Fix: [ 1095143 ] Servers list now also saves the port
|
||||
- Fix: [ 1098553 ] Crash when all vehicles from a vehicles per station list had been removed
|
||||
- Fix: [ 1099101 ] starting year patch goes out of range. Clamped year between 1920-2090
|
||||
- Fix: [ 1099225 ] Bug Fix - Vehicle Lists not updated at Acqusition (thx tamlin and mpetrov)
|
||||
- Fix: [ 1099451 ] Game crashes after the click on Rename (see also Bug 10992). There was no check for non-selected engine
|
||||
- Fix: [ 1100736 ] wrong tooltip for place desert button
|
||||
- Fix: [ 1100767 ] fast forward in main menu
|
||||
- Fix: [ 1101179 ] Crash if generating land while industry window is open. This also happened for towns and the land information window
|
||||
- Fix: [ 1101906 ] Configure Patches window text overflow
|
||||
- Fix: [ 1101963 ] console in dedicated server
|
||||
- Fix: [ 1102275 ] Game crashed when clicking "new face" or "company color" twice
|
||||
- Fix: [ 1102776 ], [ 1099535 ] Vehicle lists are now redrawn when a vehicle arrives in a depot. Station-specific vehicle lists are now redrawn daily as well (not only the master list)
|
||||
- Fix: [ 1103113 ] font size changing. Dedicated server did not have code filtering, 'tab' could result in bigger fonts
|
||||
- Fix: [ 1103187 ] Order Check messages are now validated before displayed
|
||||
- Fix: [ 1103301 ] Railroad tracks on slopes weren't flooded
|
||||
- Fix: [ 1104350 ] Crashed trains do not initiate the lost vehicle message anymore
|
||||
- Fix: [ 110452 ] On horizontal/vertical tracks you are also charged for building/removing signals on the parallel track on the same tile.
|
||||
- Fix: [ 1104969 ] Aircraft in hangar messages are now revalidated before display
|
||||
- Fix: [ 1105112 ] Destroyed train locks crossings
|
||||
- Fix: [ 1105281 ] upgrade rail fails when train under bridge
|
||||
- Fix: [ 1105959 ] Trains don't think they're on a slope any more while they drive around in a tunnel
|
||||
- Fix: [ 1105963 ] Buoys can now only be removed if no ship has it in their schedule. (This makes buoys more useable in multiplayer games again, as buoys can't be deleted by other players if they are used.)
|
||||
- Fix: [ 1106354 ] Graph's keys get confused
|
||||
- Fix: [ 1106930 ] placing signals with 2x1 drags is treated as placing a single signal
|
||||
- Fix: [ 1107350 ] console ignoring return character occasionally.
|
||||
- Fix: [ 1108008 ] Scenario creation bug; engines are of correct year when scenario is saved
|
||||
- Fix: [ 1092474 ] little red box in scenario editor
|
||||
- Fix: [ 1099197 ] scrolling through console sometimes crashed the whole game.
|
||||
- Fix: [ 1099209 ] Catchment area with drag&drop stations
|
||||
- Fix: [Network] 'kick 1' did crash dedicated servers
|
||||
- Fix: [Network] A server no longer crashes when a client sends an invalid DoCommand, but drops the client instead.
|
||||
- Fix: [Network] Added packet protection. No longer a client or server
|
||||
- Fix: [Network] Bug in bind system. Advertising failed on systems with more then 1 ip, and server_bind active to one of them.
|
||||
- Fix: [Network] Disabled 'money-cheat' (read: bug which could give people a lot of money)
|
||||
- Fix: [SDL] now the binary never links to SDL if DEDICATED is set.
|
||||
- Fix: [Windows] somehow mousewheel was disabled on windows using SDL; reenabled again
|
||||
- Fix: a modified client could try to replace a vehicle to an invalid engine ID and crash the server.
|
||||
- Fix: autoreplace vehicle lists are now redrawn when a new vehicle becomes available
|
||||
- Fix: Buy Vehicle GUI now shows HPs bigger than 32000 correctly
|
||||
- Fix: Console alias, load_game functionality and load fix
|
||||
- Fix: correct error message for when trying to build a railroad station over a bus/truck/etc-station.
|
||||
- Fix: Correct landscaping buttons in monorail and maglev toolbars
|
||||
- Fix: dedicated server also writes to log file if active
|
||||
- Fix: Desert-landscape does no longer crash
|
||||
- Fix: Expand town is a bit more agressive
|
||||
- Fix: finally zooming in/out always works.
|
||||
- Fix: fixed chat-bug (that from a certain moment, nobody could talk)
|
||||
- Fix: fixed weight for double-head trains and with that the acceleration (now maglev lvl4 can reach their top speed, and are faster than lvl3)
|
||||
- Fix: Full-Loading trains no longer get "lost" after a while (Hackykid)
|
||||
- Fix: Graphs were not updated correctly when one graph with a certain selection was already open and another graph window was opened
|
||||
- Fix: in multiplayer clientlist can only be opened once
|
||||
- Fix: Loan does not count against the company value
|
||||
- Fix: nasty bug where one could build one station OVER the other
|
||||
- Fix: No crash when creating a game with New English town names any more
|
||||
- Fix: now helicopters will use a hangar in schedule to be replaced in, even if they are only set to service there. Since helicopters are serviced at helipads, they will only go there if they needs to be replaced or renewed. They will also use a hangar in an airport in the schedule if needed. (Bjarni)
|
||||
- Fix: only a server can rename a town in a MP game
|
||||
- Fix: really old maps do load again (Darkvater / TrueLight)
|
||||
- Fix: Refit engine button is now disabled when cargo capacity equals zero
|
||||
- Fix: server issue where some company names were wrong
|
||||
- Fix: Ship Vehicle Lists are now redrawn correctly
|
||||
- Fix: signal stays red if a track is removed (Darkvater / Tron / TrueLight)
|
||||
- Fix: solve AI related order-problem
|
||||
- Fix: starting openttd with -g <invalid_name> now acts normal
|
||||
- Fix: The cost for an autorenew was not always send to the right player ;)
|
||||
- Fix: Autorenewing multiheaded train engines now costs the correct amount. Used to be twice the correct price
|
||||
- Fix: the scrollbar in the network gui (server list) now updates when scrolling (HackyKid)
|
||||
- Fix: Train crashes should no longer desync the game.
|
||||
- Fix: When deleting an order, the next pointer was not cleared, resulting in some unusual behavoir from time to time
|
||||
- Fix: You can now also delete automatically found servers by pressing "del"
|
||||
- Fix: You should no longer be able to delete bridges on any type of underground when there is a vehicle on it
|
||||
- Add: A brand new set of icons.
|
||||
- Change: AutoRenew is now a client-side patch instead of a game-side patch
|
||||
- Change: Removed the 'close ALL windows' from the toolbar since shift+del does this.
|
||||
- Language: Updated all languages
|
||||
- Fix: Many more things....
|
||||
|
||||
|
||||
0.3.5 (2004-12-24)
|
||||
------------------------------------------------------------------------
|
||||
- Feature: [Network] New network, very stable, a lot of new features
|
||||
- Feature: [Network] Ingame Serverlist (with online game-servers to join)
|
||||
- Feature: [Network] Webbased Serverlist: http://servers.openttd.org/
|
||||
- Feature: [Network] Added dedicated server support
|
||||
- Feature: [Network] Cheat protection in MultiPlayer
|
||||
- Feature: [Network] Patch settings are also synced with the server
|
||||
- Feature: [Network] Chat
|
||||
- Feature: Custom currency settings
|
||||
- Feature: Per-station vehicle lists
|
||||
- Feature: More realistically sized catchment areas
|
||||
- Feature: Sticky windows
|
||||
- Feature: Even better support for newgrf-files
|
||||
- Feature: Implement improved vehicle loading algorithm
|
||||
- Feature: Even more advanced console
|
||||
- Feature: Game compiles under BEOS_SERVER
|
||||
- Feature: Game compiles under OS/2 (no network-support)
|
||||
- Feature: OpenTTD runs with the grf files of the DOS version
|
||||
- Feature: [Big Endian computers, which are mac and MorphOS]: are able to load savegames by TTD(Patch)
|
||||
- Feature: Many more new things...
|
||||
- Add: 'l' openes the landscaping toolbar globally
|
||||
- Add: Make the town sometimes build streets on slopes
|
||||
- Add: Manpage
|
||||
- Add: New checkpoint grahpics
|
||||
- Add: SHIFT+DEL now deletes all non-vital windows (only status bar and main bar remain)
|
||||
- Add: Windows now shows revision, release information in title bar
|
||||
- Add: Windows snap at each other
|
||||
- Change: [OSX build] Moved data and lang folders inside OpenTTD. This got rid of the package system too, making installing/updating easier
|
||||
- Fix: [OSX build] Music is now on by default again
|
||||
- Fix: [OSX build] Made error opens the console
|
||||
- Fix: [SDL] Added a confirmation dialog when quitting the game
|
||||
- Fix: A train can leave and enter the same depot at the same time, then the trai simply got stuck
|
||||
- Fix: Crash when making png screenshot with odd resolution (Tron)
|
||||
- Fix: Directories in *nix are now sorted alphabetically in ascending order (Tron).
|
||||
- Fix: Do not consider a road station as street when growing the town
|
||||
- Fix: Engines from other climates do not appear any more when never_expire_vehicles is enabled
|
||||
- Fix: Game options (like drive side) are not taken from the scenario when using 'new game' command
|
||||
- Fix: Order checker now correctly detects station with invalid facilities
|
||||
- Fix: Polished GUI in a lot of ways
|
||||
- Fix: Saving or loading a map doesnt pauses the game anymore
|
||||
- Fix: Some bridge part isn't displayed transparent in transparent mode
|
||||
- Fix: Starting with -r option allows all resolutions (Tron)
|
||||
- Fix: The pathfinder no longer sees rail with an other owner as a possible route.
|
||||
- Fix: Unable to select other screenshot format in Game Option
|
||||
- Fix: Unwanted town renaming
|
||||
- Fix: Vehicles slow down under bridge if the track is on a foundation
|
||||
- Fix: You can no longer change name of waypoints whom are owned by somebody else
|
||||
- Fix: [ 1090313 ] Shares are now also sold when a company goes bankrupt
|
||||
- Fix: [ 1087701 ] It is no longer possible to crash trains of other companies by building a depot close to a station. (even more: trains do no longer enter tiles that do not belong to his owner)
|
||||
- Fix: [ 1087403 ] Crashed trains aren't reported to have too few orders any more
|
||||
- Fix: [ 1086375 ] Backup-order-list was not closed with an OT_NOTHING,
|
||||
- Fix: [ 1085255 ] Docks now have a button to display the catchment area
|
||||
- Fix: [ 1070274 ] Invisible trains. Weird macros and MSVC optimizing don't always mix. (Tron)
|
||||
- Fix: [ 1068269 ] Number of passangers and mail in exclusive test offer window is swapped
|
||||
- Fix: [ 1066504 ] Pause key pauses the game
|
||||
- Fix: [ 1066121 ] Resetting file name after deleting a file (dannys9)
|
||||
- Fix: [ 1066114 ] Code error in win32.c Thanks Shai
|
||||
- Fix: [ 1065247 ] Windows can be placed behind toolbar
|
||||
- Fix: [ 1064742 ] Editor Map-Menu wrong String
|
||||
- Fix: [ 1058809 ] Always report a bus/lorry station as unpassable
|
||||
- Fix: [ 1053397 ] Refit train window stays open
|
||||
- Fix: [ 1050993 ] Incorrect Tooltip in Road Vehicle List.
|
||||
- Fix: [ 1048596 ] Monorail and Maglev sounds are swapped
|
||||
- Fix: [ 1040119 ] Flooded wagons in depots don't keep constantly exploding any more
|
||||
- Fix: [ 1035303 ] Bug about lowering tracks built on slopes
|
||||
- Fix: [ 1035066 ] 'Allow goto depot' turned off, no checkpoints in orders
|
||||
- Fix: [ 1034318 ] Place sign and blue message box
|
||||
- Fix: [ 1033947 ] Wrong mapping between music titles and songs
|
||||
- Fix: [ 1030393 ] Some screensizes crashes OTTD. Fix in general bug that only allows resolutions which were multiple of 8 in width and height. Also use closest possible resolution in fullscreen if window size is not a valid resolution (Tron)
|
||||
- Fix: [ 1030275 ] 'Service at' orders ignored after 2090. After 2090 year is reset to 1. Jan 2090, so most of the time, last service was in the future and no service ensured.
|
||||
- Fix: [ 1029064 ] Building a station acted weird in some rare situations
|
||||
- Fix: [ 1022227 ] Ships could unload cargo at stations without docks
|
||||
- Fix: [ 999669 ] Wrong trees (toyland's) in sub-tropical landscape style
|
||||
- Fix: [ 993500 ] High bridge rendering error
|
||||
- Fix: [ 991101 ] Disabled buttons flicker no more
|
||||
- Fix: [ 985925 ] Start/stop flag in train depots always works, regardless of the horizontal scroll position
|
||||
- Fix: [ 985439 ] Un-owned rail. Trains could cross competitor's tracks if there was a road-crossing over it.
|
||||
- Fix: [ 982611 ] Pathfinding bug; train likes the roundabout. If train needs servicing it will now look 16 tiles along the track instead of 12 tiles manhattan style (blathijs)
|
||||
- Fix: [ 967096 ] Fullscreen. New button 'Fullscreen' in 'Game Options' menu which lets you set fullscreen ingame.
|
||||
- Fix: [ 958098 ] No longer road/rail crossing signals hang when a train is reversed at the wrong moment (Yeah, our longest open bug finally fixed :) :) :))
|
||||
- Fix: [ 926105 ] Ctrl + d bug. Longest outstanding bug has been fixed \o/ 2004-03-30 (Tron)
|
||||
- Language: Added Spanish
|
||||
- Language: Added Catalan
|
||||
- Language: Added Icelandic
|
||||
- Language: Updated most languages
|
||||
- Fix: Many more things....
|
||||
|
||||
|
||||
0.3.4 (2004-09-14)
|
||||
------------------------------------------------------------------------
|
||||
- Add: Dutch translation
|
||||
|
||||
+147
-95
@@ -1,5 +1,8 @@
|
||||
#include "stdafx.h"
|
||||
#include "ttd.h"
|
||||
#include "table/strings.h"
|
||||
#include "map.h"
|
||||
#include "tile.h"
|
||||
#include "viewport.h"
|
||||
#include "command.h"
|
||||
|
||||
@@ -28,7 +31,7 @@ static int TerraformAllowTileProcess(TerraformerState *ts, TileIndex tile)
|
||||
TileIndex *t;
|
||||
int count;
|
||||
|
||||
if ((GET_TILE_X(tile) == TILE_X_MAX) || (GET_TILE_Y(tile) == TILE_Y_MAX))
|
||||
if (TileX(tile) == MapMaxX() || TileY(tile) == MapMaxY())
|
||||
return -1;
|
||||
|
||||
t = ts->tile_table;
|
||||
@@ -50,7 +53,7 @@ static int TerraformGetHeightOfTile(TerraformerState *ts, TileIndex tile)
|
||||
return mod->height;
|
||||
}
|
||||
|
||||
return _map_type_and_height[tile] & 0xF;
|
||||
return TileHeight(tile);
|
||||
}
|
||||
|
||||
static void TerraformAddDirtyTile(TerraformerState *ts, TileIndex tile)
|
||||
@@ -84,19 +87,23 @@ static int TerraformProc(TerraformerState *ts, uint tile, int mode)
|
||||
int r;
|
||||
int32 ret;
|
||||
|
||||
assert(tile < TILES_X * TILES_Y);
|
||||
assert(tile < MapSize());
|
||||
|
||||
if ((r=TerraformAllowTileProcess(ts, tile)) <= 0)
|
||||
return r;
|
||||
|
||||
if ((_map_type_and_height[tile] >> 4) == MP_RAILWAY) {
|
||||
if (IsTileType(tile, MP_RAILWAY)) {
|
||||
static const byte _railway_modes[4] = {8, 0x10, 4, 0x20};
|
||||
static const byte _railway_dangslopes[4] = {0xd, 0xe, 7, 0xb};
|
||||
static const byte _railway_dangslopes2[4] = {0x2, 0x1, 0x8, 0x4};
|
||||
|
||||
// Nothing could be built at the steep slope - this avoids a bug
|
||||
// when you have a single diagonal track in one corner on a
|
||||
// basement and then you raise the other corner.
|
||||
if ((GetTileSlope(tile, NULL)&0xF) == _railway_dangslopes[mode]) {
|
||||
// basement and then you raise/lower the other corner.
|
||||
int tileh = GetTileSlope(tile, NULL) & 0xF;
|
||||
if (tileh == _railway_dangslopes[mode] ||
|
||||
tileh == _railway_dangslopes2[mode]) {
|
||||
_terraform_err_tile = tile;
|
||||
_error_message = STR_1008_MUST_REMOVE_RAILROAD_TRACK;
|
||||
return -1;
|
||||
}
|
||||
@@ -129,7 +136,7 @@ static bool TerraformTileHeight(TerraformerState *ts, uint tile, int height)
|
||||
TerraformerHeightMod *mod;
|
||||
int count;
|
||||
|
||||
assert(tile < TILES_X * TILES_Y);
|
||||
assert(tile < MapSize());
|
||||
|
||||
if (height < 0) {
|
||||
_error_message = STR_1003_ALREADY_AT_SEA_LEVEL;
|
||||
@@ -180,12 +187,17 @@ static bool TerraformTileHeight(TerraformerState *ts, uint tile, int height)
|
||||
|
||||
{
|
||||
int direction = ts->direction, r;
|
||||
const TileIndexDiff *ttm;
|
||||
const TileIndexDiffC *ttm;
|
||||
|
||||
static const TileIndexDiff _terraform_tilepos[5] = {TILE_XY(1,0), TILE_XY(-2,0), TILE_XY(1,1), TILE_XY(0,-2), 0 };
|
||||
static const TileIndexDiffC _terraform_tilepos[] = {
|
||||
{ 1, 0},
|
||||
{-2, 0},
|
||||
{ 1, 1},
|
||||
{ 0, -2}
|
||||
};
|
||||
|
||||
for(ttm = _terraform_tilepos; *ttm != 0; ttm++) {
|
||||
tile += *ttm;
|
||||
for(ttm = _terraform_tilepos; ttm != endof(_terraform_tilepos); ttm++) {
|
||||
tile += ToTileIndexDiff(*ttm);
|
||||
|
||||
r = TerraformGetHeightOfTile(ts, tile);
|
||||
if (r != height && r-direction != height && r+direction != height) {
|
||||
@@ -198,15 +210,15 @@ static bool TerraformTileHeight(TerraformerState *ts, uint tile, int height)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Terraform land
|
||||
* p1 - corners
|
||||
* p2 - direction
|
||||
/** Terraform land
|
||||
* @param x,y coordinates to terraform
|
||||
* @param p1 corners to terraform.
|
||||
* @param p2 direction; eg up or down
|
||||
*/
|
||||
|
||||
int32 CmdTerraformLand(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
TerraformerState ts;
|
||||
uint tile;
|
||||
TileIndex tile;
|
||||
int direction;
|
||||
|
||||
TerraformerHeightMod modheight_data[576];
|
||||
@@ -228,25 +240,25 @@ int32 CmdTerraformLand(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
|
||||
if (p1 & 1) {
|
||||
if (!TerraformTileHeight(&ts, tile+TILE_XY(1,0),
|
||||
(_map_type_and_height[tile+TILE_XY(1,0)]&0xF) + direction))
|
||||
TileHeight(tile + TILE_XY(1, 0)) + direction))
|
||||
return CMD_ERROR;
|
||||
}
|
||||
|
||||
if (p1 & 2) {
|
||||
if (!TerraformTileHeight(&ts, tile+TILE_XY(1,1),
|
||||
(_map_type_and_height[tile+TILE_XY(1,1)]&0xF) + direction))
|
||||
TileHeight(tile + TILE_XY(1, 1)) + direction))
|
||||
return CMD_ERROR;
|
||||
}
|
||||
|
||||
if (p1 & 4) {
|
||||
if (!TerraformTileHeight(&ts, tile+TILE_XY(0,1),
|
||||
(_map_type_and_height[tile+TILE_XY(0,1)]&0xF) + direction))
|
||||
TileHeight(tile + TILE_XY(0, 1)) + direction))
|
||||
return CMD_ERROR;
|
||||
}
|
||||
|
||||
if (p1 & 8) {
|
||||
if (!TerraformTileHeight(&ts, tile+TILE_XY(0,0),
|
||||
(_map_type_and_height[tile+TILE_XY(0,0)]&0xF) + direction))
|
||||
TileHeight(tile + TILE_XY(0, 0)) + direction))
|
||||
return CMD_ERROR;
|
||||
}
|
||||
|
||||
@@ -255,7 +267,7 @@ int32 CmdTerraformLand(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
int count;
|
||||
TileIndex *ti = ts.tile_table;
|
||||
|
||||
for(count = ts.tile_table_count; count != 0; count--, ti++) {
|
||||
for (count = ts.tile_table_count; count != 0; count--, ti++) {
|
||||
uint z, t;
|
||||
uint tile = *ti;
|
||||
|
||||
@@ -277,7 +289,7 @@ int32 CmdTerraformLand(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
int count;
|
||||
TileIndex *ti = ts.tile_table;
|
||||
for(count = ts.tile_table_count; count != 0; count--, ti++) {
|
||||
for (count = ts.tile_table_count; count != 0; count--, ti++) {
|
||||
DoCommandByTile(*ti, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
|
||||
}
|
||||
}
|
||||
@@ -289,12 +301,10 @@ int32 CmdTerraformLand(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
uint til;
|
||||
|
||||
mod = ts.modheight;
|
||||
for(count = ts.modheight_count; count != 0; count--, mod++) {
|
||||
for (count = ts.modheight_count; count != 0; count--, mod++) {
|
||||
til = mod->tile;
|
||||
|
||||
// Change tile height
|
||||
_map_type_and_height[til] = (_map_type_and_height[til]&~0x0F)|mod->height;
|
||||
|
||||
SetTileHeight(til, mod->height);
|
||||
TerraformAddDirtyTileAround(&ts, til);
|
||||
}
|
||||
}
|
||||
@@ -303,7 +313,7 @@ int32 CmdTerraformLand(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
int count;
|
||||
TileIndex *ti = ts.tile_table;
|
||||
for(count = ts.tile_table_count; count != 0; count--, ti++) {
|
||||
for (count = ts.tile_table_count; count != 0; count--, ti++) {
|
||||
MarkTileDirtyByTile(*ti);
|
||||
}
|
||||
}
|
||||
@@ -312,26 +322,31 @@ int32 CmdTerraformLand(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* p1 - start
|
||||
/** Levels a selected (rectangle) area of land
|
||||
* @param x,y end tile of area-drag
|
||||
* @param p1 start tile of area drag
|
||||
* @param p2 unused
|
||||
*/
|
||||
|
||||
int32 CmdLevelLand(int ex, int ey, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
int size_x, size_y;
|
||||
int sx, sy;
|
||||
uint h, curh;
|
||||
uint tile;
|
||||
TileIndex tile;
|
||||
int32 ret, cost, money;
|
||||
|
||||
if (p1 > MapSize()) return CMD_ERROR;
|
||||
|
||||
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
|
||||
|
||||
// remember level height
|
||||
h = _map_type_and_height[p1]&0xF;
|
||||
h = TileHeight(p1);
|
||||
|
||||
ex >>= 4; ey >>= 4;
|
||||
|
||||
// make sure sx,sy are smaller than ex,ey
|
||||
sx = GET_TILE_X(p1);
|
||||
sy = GET_TILE_Y(p1);
|
||||
sx = TileX(p1);
|
||||
sy = TileY(p1);
|
||||
if (ex < sx) intswap(ex, sx);
|
||||
if (ey < sy) intswap(ey, sy);
|
||||
tile = TILE_XY(sx,sy);
|
||||
@@ -342,11 +357,11 @@ int32 CmdLevelLand(int ex, int ey, uint32 flags, uint32 p1, uint32 p2)
|
||||
money = GetAvailableMoneyForCommand();
|
||||
cost = 0;
|
||||
|
||||
BEGIN_TILE_LOOP(tile2, size_x, size_y, tile)
|
||||
curh = _map_type_and_height[tile2]&0xF;
|
||||
BEGIN_TILE_LOOP(tile2, size_x, size_y, tile) {
|
||||
curh = TileHeight(tile2);
|
||||
while (curh != h) {
|
||||
ret = DoCommandByTile(tile2, 8, (curh > h)?0:1, flags & ~DC_EXEC, CMD_TERRAFORM_LAND);
|
||||
if (ret == CMD_ERROR) break;
|
||||
ret = DoCommandByTile(tile2, 8, (curh > h) ? 0 : 1, flags & ~DC_EXEC, CMD_TERRAFORM_LAND);
|
||||
if (CmdFailed(ret)) break;
|
||||
cost += ret;
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
@@ -354,42 +369,38 @@ int32 CmdLevelLand(int ex, int ey, uint32 flags, uint32 p1, uint32 p2)
|
||||
_additional_cash_required = ret;
|
||||
return cost - ret;
|
||||
}
|
||||
DoCommandByTile(tile2, 8, (curh > h)?0:1, flags, CMD_TERRAFORM_LAND);
|
||||
DoCommandByTile(tile2, 8, (curh > h) ? 0 : 1, flags, CMD_TERRAFORM_LAND);
|
||||
}
|
||||
|
||||
curh += (curh > h) ? -1 : 1;
|
||||
}
|
||||
END_TILE_LOOP(tile2, size_x, size_y, tile)
|
||||
} END_TILE_LOOP(tile2, size_x, size_y, tile)
|
||||
|
||||
if (cost == 0) return CMD_ERROR;
|
||||
return cost;
|
||||
return (cost == 0) ? CMD_ERROR : cost;
|
||||
}
|
||||
|
||||
/* Purchase a land area
|
||||
* p1 = unused
|
||||
* p2 = unused
|
||||
/** Purchase a land area. Actually you only purchase one tile, so
|
||||
* the name is a bit confusing ;p
|
||||
* @param x,y the tile the player is purchasing
|
||||
* @param p1 unused
|
||||
* @param p2 unused
|
||||
*/
|
||||
|
||||
int32 CmdPurchaseLandArea(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
uint tile;
|
||||
TileIndex tile;
|
||||
int32 cost;
|
||||
|
||||
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
|
||||
|
||||
tile = TILE_FROM_XY(x,y);
|
||||
|
||||
if (!EnsureNoVehicle(tile))
|
||||
return CMD_ERROR;
|
||||
if (!EnsureNoVehicle(tile)) return CMD_ERROR;
|
||||
|
||||
if (IS_TILETYPE(tile, MP_UNMOVABLE) &&
|
||||
_map5[tile] == 3 &&
|
||||
_map_owner[tile] == _current_player)
|
||||
if (IsTileType(tile, MP_UNMOVABLE) && _map5[tile] == 3 && _map_owner[tile] == _current_player)
|
||||
return_cmd_error(STR_5807_YOU_ALREADY_OWN_IT);
|
||||
|
||||
cost = DoCommandByTile(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
|
||||
if (cost == CMD_ERROR)
|
||||
return CMD_ERROR;
|
||||
if (CmdFailed(cost)) return CMD_ERROR;
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
ModifyTile(tile,
|
||||
@@ -402,7 +413,8 @@ int32 CmdPurchaseLandArea(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
}
|
||||
|
||||
|
||||
int32 ClearTile_Clear(uint tile, byte flags) {
|
||||
static int32 ClearTile_Clear(uint tile, byte flags)
|
||||
{
|
||||
static const int32 * _clear_price_table[] = {
|
||||
NULL,
|
||||
&_price.clear_1, &_price.clear_1,&_price.clear_1,
|
||||
@@ -423,9 +435,15 @@ int32 ClearTile_Clear(uint tile, byte flags) {
|
||||
return *price;
|
||||
}
|
||||
|
||||
/** Sell a land area. Actually you only sell one tile, so
|
||||
* the name is a bit confusing ;p
|
||||
* @param x,y the tile the player is selling
|
||||
* @param p1 unused
|
||||
* @param p2 unused
|
||||
*/
|
||||
int32 CmdSellLandArea(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
uint tile;
|
||||
TileIndex tile;
|
||||
|
||||
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
|
||||
|
||||
@@ -434,13 +452,12 @@ int32 CmdSellLandArea(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
if (!CheckTileOwnership(tile) && _current_player != OWNER_WATER)
|
||||
return CMD_ERROR;
|
||||
|
||||
if (!EnsureNoVehicle(tile))
|
||||
return CMD_ERROR;
|
||||
if (!EnsureNoVehicle(tile)) return CMD_ERROR;
|
||||
|
||||
if (flags & DC_EXEC)
|
||||
DoClearSquare(tile);
|
||||
|
||||
return - _price.purchase_land*2;
|
||||
return - _price.purchase_land * 2;
|
||||
}
|
||||
|
||||
|
||||
@@ -512,14 +529,17 @@ static void DrawTile_Clear(TileInfo *ti)
|
||||
DrawClearLandFence(ti, _map3_hi[ti->tile] >> 2);
|
||||
}
|
||||
|
||||
uint GetSlopeZ_Clear(TileInfo *ti) { return GetPartialZ(ti->x&0xF, ti->y&0xF, ti->tileh) + ti->z; }
|
||||
static uint GetSlopeZ_Clear(TileInfo *ti)
|
||||
{
|
||||
return GetPartialZ(ti->x & 0xF, ti->y & 0xF, ti->tileh) + ti->z;
|
||||
}
|
||||
|
||||
uint GetSlopeTileh_Clear(TileInfo *ti)
|
||||
static uint GetSlopeTileh_Clear(TileInfo *ti)
|
||||
{
|
||||
return ti->tileh;
|
||||
}
|
||||
|
||||
static void GetAcceptedCargo_Clear(uint tile, AcceptedCargo *ac)
|
||||
static void GetAcceptedCargo_Clear(uint tile, AcceptedCargo ac)
|
||||
{
|
||||
/* unused */
|
||||
}
|
||||
@@ -529,28 +549,49 @@ static void AnimateTile_Clear(uint tile)
|
||||
/* unused */
|
||||
}
|
||||
|
||||
void TileLoopClearHelper(uint tile)
|
||||
void TileLoopClearHelper(TileIndex tile)
|
||||
{
|
||||
byte img_1, img_2;
|
||||
static byte img_by_map5[8] = { 0,0,0,2, 1,1,0,0, };
|
||||
uint dirty = -1;
|
||||
byte img_1;
|
||||
byte img_2;
|
||||
static const byte img_by_map5[] = { 0, 0, 0, 2, 1, 1, 0, 0 };
|
||||
TileIndex dirty = INVALID_TILE;
|
||||
|
||||
img_1 = 0;
|
||||
if (IS_TILETYPE(tile, MP_CLEAR)) {
|
||||
img_1 = img_by_map5[(_map5[tile] & 0x1C) >> 2];
|
||||
} else if (IS_TILETYPE(tile, MP_TREES) && (_map2[tile] & 0x30) == 0x20) {
|
||||
img_1 = 1;
|
||||
switch (GetTileType(tile)) {
|
||||
case MP_CLEAR:
|
||||
img_1 = img_by_map5[(_map5[tile] & 0x1C) >> 2];
|
||||
break;
|
||||
|
||||
case MP_TREES:
|
||||
if ((_map2[tile] & 0x30) == 0x20)
|
||||
img_1 = 1;
|
||||
else
|
||||
img_1 = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
img_1 = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
img_2 = 0;
|
||||
if (IS_TILETYPE(TILE_ADDXY(tile, 1, 0), MP_CLEAR)) {
|
||||
img_2 = img_by_map5[(_map5[TILE_ADDXY(tile, 1, 0)] & 0x1C) >> 2];
|
||||
} else if (IS_TILETYPE(TILE_ADDXY(tile, 1, 0), MP_TREES) && (_map2[TILE_ADDXY(tile, 1, 0)] & 0x30) == 0x20) {
|
||||
img_2 = 1;
|
||||
switch (GetTileType(TILE_ADDXY(tile, 1, 0))) {
|
||||
case MP_CLEAR:
|
||||
img_2 = img_by_map5[(_map5[TILE_ADDXY(tile, 1, 0)] & 0x1C) >> 2];
|
||||
break;
|
||||
|
||||
case MP_TREES:
|
||||
if ((_map2[TILE_ADDXY(tile, 1, 0)] & 0x30) == 0x20)
|
||||
img_2 = 1;
|
||||
else
|
||||
img_2 = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
img_2 = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(_map3_hi[tile] & 0xE0)) {
|
||||
if ( (img_1&2) != (img_2&2) ) {
|
||||
if ((_map3_hi[tile] & 0xE0) == 0) {
|
||||
if ((img_1 & 2) != (img_2 & 2)) {
|
||||
_map3_hi[tile] |= 3 << 5;
|
||||
dirty = tile;
|
||||
}
|
||||
@@ -561,15 +602,25 @@ void TileLoopClearHelper(uint tile)
|
||||
}
|
||||
}
|
||||
|
||||
img_2 = 0;
|
||||
if (IS_TILETYPE(TILE_ADDXY(tile, 0, 1), MP_CLEAR)) {
|
||||
img_2 = img_by_map5[(_map5[TILE_ADDXY(tile, 0, 1)] & 0x1C) >> 2];
|
||||
} else if (IS_TILETYPE(TILE_ADDXY(tile, 0, 1), MP_TREES) && (_map2[TILE_ADDXY(tile, 0, 1)] & 0x30) == 0x20) {
|
||||
img_2 = 1;
|
||||
switch (GetTileType(TILE_ADDXY(tile, 0, 1))) {
|
||||
case MP_CLEAR:
|
||||
img_2 = img_by_map5[(_map5[TILE_ADDXY(tile, 0, 1)] & 0x1C) >> 2];
|
||||
break;
|
||||
|
||||
case MP_TREES:
|
||||
if ((_map2[TILE_ADDXY(tile, 0, 1)] & 0x30) == 0x20)
|
||||
img_2 = 1;
|
||||
else
|
||||
img_2 = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
img_2 = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(_map3_hi[tile] & 0x1C)) {
|
||||
if ( (img_1&2) != (img_2&2) ) {
|
||||
if ((_map3_hi[tile] & 0x1C) == 0) {
|
||||
if ((img_1 & 2) != (img_2 & 2)) {
|
||||
_map3_hi[tile] |= 3 << 2;
|
||||
dirty = tile;
|
||||
}
|
||||
@@ -580,7 +631,7 @@ void TileLoopClearHelper(uint tile)
|
||||
}
|
||||
}
|
||||
|
||||
if (dirty != -1)
|
||||
if (dirty != INVALID_TILE)
|
||||
MarkTileDirtyByTile(dirty);
|
||||
}
|
||||
|
||||
@@ -718,33 +769,33 @@ static void TileLoop_Clear(uint tile)
|
||||
MarkTileDirtyByTile(tile);
|
||||
}
|
||||
|
||||
void GenerateClearTile()
|
||||
void GenerateClearTile(void)
|
||||
{
|
||||
int i,j;
|
||||
uint tile,tile_new;
|
||||
uint32 r;
|
||||
|
||||
/* add hills */
|
||||
i = (Random() & 0x3FF) | 0x400;
|
||||
i = ScaleByMapSize((Random() & 0x3FF) + 0x400);
|
||||
do {
|
||||
tile = TILE_MASK(Random());
|
||||
if (IS_TILETYPE(tile, MP_CLEAR))
|
||||
if (IsTileType(tile, MP_CLEAR))
|
||||
_map5[tile] = (byte)((_map5[tile] & ~(3<<2)) | (1<<2));
|
||||
} while (--i);
|
||||
|
||||
/* add grey squares */
|
||||
i = (Random() & 0x7F) | 0x80;
|
||||
i = ScaleByMapSize((Random() & 0x7F) + 0x80);
|
||||
do {
|
||||
r = Random();
|
||||
tile = TILE_MASK(r);
|
||||
if (IS_TILETYPE(tile, MP_CLEAR)) {
|
||||
if (IsTileType(tile, MP_CLEAR)) {
|
||||
j = ((r >> 16) & 0xF) + 5;
|
||||
for(;;) {
|
||||
_map5[tile] = (byte)((_map5[tile] & ~(3<<2)) | (2<<2));
|
||||
do {
|
||||
if (--j == 0) goto get_out;
|
||||
tile_new = tile + _tileoffs_by_dir[Random() & 3];
|
||||
} while (!IS_TILETYPE(tile_new, MP_CLEAR));
|
||||
tile_new = tile + TileOffsByDir(Random() & 3);
|
||||
} while (!IsTileType(tile_new, MP_CLEAR));
|
||||
tile = tile_new;
|
||||
}
|
||||
get_out:;
|
||||
@@ -757,7 +808,7 @@ static void ClickTile_Clear(uint tile)
|
||||
/* not used */
|
||||
}
|
||||
|
||||
uint32 GetTileTrackStatus_Clear(uint tile, TransportType mode)
|
||||
static uint32 GetTileTrackStatus_Clear(uint tile, TransportType mode)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -790,7 +841,8 @@ static void ChangeTileOwner_Clear(uint tile, byte old_player, byte new_player)
|
||||
return;
|
||||
}
|
||||
|
||||
void InitializeClearLand() {
|
||||
void InitializeClearLand(void)
|
||||
{
|
||||
_opt.snow_line = _patches.snow_line_height * 8;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
#include "stdafx.h"
|
||||
#include "ttd.h"
|
||||
#include "table/strings.h"
|
||||
#include "map.h"
|
||||
#include "gui.h"
|
||||
#include "command.h"
|
||||
#include "player.h"
|
||||
#include "network.h"
|
||||
|
||||
const char* _cmd_text = NULL;
|
||||
|
||||
#define DEF_COMMAND(yyyy) int32 yyyy(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
|
||||
@@ -19,8 +24,8 @@ DEF_COMMAND(CmdBuildRailroadStation);
|
||||
DEF_COMMAND(CmdRemoveFromRailroadStation);
|
||||
DEF_COMMAND(CmdConvertRail);
|
||||
|
||||
DEF_COMMAND(CmdBuildSignals);
|
||||
DEF_COMMAND(CmdRemoveSignals);
|
||||
DEF_COMMAND(CmdBuildSingleSignal);
|
||||
DEF_COMMAND(CmdRemoveSingleSignal);
|
||||
|
||||
DEF_COMMAND(CmdTerraformLand);
|
||||
|
||||
@@ -30,13 +35,11 @@ DEF_COMMAND(CmdSellLandArea);
|
||||
DEF_COMMAND(CmdBuildTunnel);
|
||||
|
||||
DEF_COMMAND(CmdBuildTrainDepot);
|
||||
DEF_COMMAND(CmdBuildTrainCheckpoint);
|
||||
DEF_COMMAND(CmdRenameCheckpoint);
|
||||
DEF_COMMAND(CmdRemoveTrainCheckpoint);
|
||||
DEF_COMMAND(CmdBuildTrainWaypoint);
|
||||
DEF_COMMAND(CmdRenameWaypoint);
|
||||
DEF_COMMAND(CmdRemoveTrainWaypoint);
|
||||
|
||||
DEF_COMMAND(CmdBuildTruckStation);
|
||||
|
||||
DEF_COMMAND(CmdBuildBusStation);
|
||||
DEF_COMMAND(CmdBuildRoadStop);
|
||||
|
||||
DEF_COMMAND(CmdBuildLongRoad);
|
||||
DEF_COMMAND(CmdRemoveLongRoad);
|
||||
@@ -62,7 +65,7 @@ DEF_COMMAND(CmdStartStopTrain);
|
||||
|
||||
DEF_COMMAND(CmdSellRailWagon);
|
||||
|
||||
DEF_COMMAND(CmdTrainGotoDepot);
|
||||
DEF_COMMAND(CmdSendTrainToDepot);
|
||||
DEF_COMMAND(CmdForceTrainProceed);
|
||||
DEF_COMMAND(CmdReverseTrainDirection);
|
||||
|
||||
@@ -74,10 +77,8 @@ DEF_COMMAND(CmdChangeTrainServiceInt);
|
||||
DEF_COMMAND(CmdRestoreOrderIndex);
|
||||
|
||||
DEF_COMMAND(CmdBuildIndustry);
|
||||
//DEF_COMMAND(CmdDestroyIndustry);
|
||||
|
||||
DEF_COMMAND(CmdBuildCompanyHQ);
|
||||
DEF_COMMAND(CmdDestroyCompanyHQ);
|
||||
DEF_COMMAND(CmdSetPlayerFace);
|
||||
DEF_COMMAND(CmdSetPlayerColor);
|
||||
|
||||
@@ -112,7 +113,6 @@ DEF_COMMAND(CmdTurnRoadVeh);
|
||||
DEF_COMMAND(CmdChangeRoadVehServiceInt);
|
||||
|
||||
DEF_COMMAND(CmdPause);
|
||||
DEF_COMMAND(CmdResume);
|
||||
|
||||
DEF_COMMAND(CmdBuyShareInCompany);
|
||||
DEF_COMMAND(CmdSellShareInCompany);
|
||||
@@ -124,9 +124,9 @@ DEF_COMMAND(CmdRenameTown);
|
||||
DEF_COMMAND(CmdDoTownAction);
|
||||
|
||||
DEF_COMMAND(CmdSetRoadDriveSide);
|
||||
DEF_COMMAND(CmdSetTownNameType);
|
||||
|
||||
DEF_COMMAND(CmdChangeDifficultyLevel);
|
||||
DEF_COMMAND(CmdChangePatchSetting);
|
||||
|
||||
DEF_COMMAND(CmdStartStopShip);
|
||||
DEF_COMMAND(CmdSellShip);
|
||||
@@ -135,19 +135,11 @@ DEF_COMMAND(CmdSendShipToDepot);
|
||||
DEF_COMMAND(CmdChangeShipServiceInt);
|
||||
DEF_COMMAND(CmdRefitShip);
|
||||
|
||||
|
||||
DEF_COMMAND(CmdStartNewGame);
|
||||
DEF_COMMAND(CmdLoadGame);
|
||||
DEF_COMMAND(CmdCreateScenario);
|
||||
DEF_COMMAND(CmdSetSinglePlayer);
|
||||
|
||||
DEF_COMMAND(CmdSetNewLandscapeType);
|
||||
|
||||
DEF_COMMAND(CmdGenRandomNewGame);
|
||||
DEF_COMMAND(CmdCloneOrder);
|
||||
|
||||
DEF_COMMAND(CmdClearArea);
|
||||
|
||||
DEF_COMMAND(CmdGiveMoney);
|
||||
DEF_COMMAND(CmdMoneyCheat);
|
||||
DEF_COMMAND(CmdBuildCanal);
|
||||
DEF_COMMAND(CmdBuildLock);
|
||||
@@ -158,153 +150,170 @@ DEF_COMMAND(CmdLevelLand);
|
||||
|
||||
DEF_COMMAND(CmdRefitRailVehicle);
|
||||
|
||||
DEF_COMMAND(CmdStartScenario);
|
||||
DEF_COMMAND(CmdBuildSignalTrack);
|
||||
DEF_COMMAND(CmdRemoveSignalTrack);
|
||||
|
||||
DEF_COMMAND(CmdBuildManySignals);
|
||||
DEF_COMMAND(CmdReplaceVehicle);
|
||||
|
||||
/* The master command table */
|
||||
static CommandProc * const _command_proc_table[] = {
|
||||
CmdBuildRailroadTrack, /* 0 */
|
||||
CmdRemoveRailroadTrack, /* 1 */
|
||||
CmdBuildSingleRail, /* 2 */
|
||||
CmdRemoveSingleRail, /* 3 */
|
||||
CmdLandscapeClear, /* 4 */
|
||||
CmdBuildBridge, /* 5 */
|
||||
CmdBuildRailroadStation, /* 6 */
|
||||
CmdBuildTrainDepot, /* 7 */
|
||||
CmdBuildSignals, /* 8 */
|
||||
CmdRemoveSignals, /* 9 */
|
||||
CmdTerraformLand, /* 10 */
|
||||
CmdPurchaseLandArea, /* 11 */
|
||||
CmdSellLandArea, /* 12 */
|
||||
CmdBuildTunnel, /* 13 */
|
||||
CmdRemoveFromRailroadStation, /* 14 */
|
||||
CmdConvertRail, /* 15 */
|
||||
CmdBuildTrainCheckpoint, /* 16 */
|
||||
CmdRenameCheckpoint, /* 17 */
|
||||
CmdRemoveTrainCheckpoint, /* 18 */
|
||||
CmdBuildTruckStation, /* 19 */
|
||||
NULL, /* 20 */
|
||||
CmdBuildBusStation, /* 21 */
|
||||
NULL, /* 22 */
|
||||
CmdBuildLongRoad, /* 23 */
|
||||
CmdRemoveLongRoad, /* 24 */
|
||||
CmdBuildRoad, /* 25 */
|
||||
CmdRemoveRoad, /* 26 */
|
||||
CmdBuildRoadDepot, /* 27 */
|
||||
NULL, /* 28 */
|
||||
CmdBuildAirport, /* 29 */
|
||||
CmdBuildDock, /* 30 */
|
||||
CmdBuildShipDepot, /* 31 */
|
||||
CmdBuildBuoy, /* 32 */
|
||||
CmdPlantTree, /* 33 */
|
||||
CmdBuildRailVehicle, /* 34 */
|
||||
CmdMoveRailVehicle, /* 35 */
|
||||
CmdStartStopTrain, /* 36 */
|
||||
NULL, /* 37 */
|
||||
CmdSellRailWagon, /* 38 */
|
||||
CmdTrainGotoDepot, /* 39 */
|
||||
CmdForceTrainProceed, /* 40 */
|
||||
CmdReverseTrainDirection, /* 41 */
|
||||
static const Command _command_proc_table[] = {
|
||||
{CmdBuildRailroadTrack, 0}, /* 0 */
|
||||
{CmdRemoveRailroadTrack, 0}, /* 1 */
|
||||
{CmdBuildSingleRail, 0}, /* 2 */
|
||||
{CmdRemoveSingleRail, 0}, /* 3 */
|
||||
{CmdLandscapeClear, 0}, /* 4 */
|
||||
{CmdBuildBridge, 0}, /* 5 */
|
||||
{CmdBuildRailroadStation, 0}, /* 6 */
|
||||
{CmdBuildTrainDepot, 0}, /* 7 */
|
||||
{CmdBuildSingleSignal, 0}, /* 8 */
|
||||
{CmdRemoveSingleSignal, 0}, /* 9 */
|
||||
{CmdTerraformLand, 0}, /* 10 */
|
||||
{CmdPurchaseLandArea, 0}, /* 11 */
|
||||
{CmdSellLandArea, 0}, /* 12 */
|
||||
{CmdBuildTunnel, 0}, /* 13 */
|
||||
{CmdRemoveFromRailroadStation, 0}, /* 14 */
|
||||
{CmdConvertRail, 0}, /* 15 */
|
||||
{CmdBuildTrainWaypoint, 0}, /* 16 */
|
||||
{CmdRenameWaypoint, 0}, /* 17 */
|
||||
{CmdRemoveTrainWaypoint, 0}, /* 18 */
|
||||
{NULL, 0}, /* 19 */
|
||||
{NULL, 0}, /* 20 */
|
||||
{CmdBuildRoadStop, 0}, /* 21 */
|
||||
{NULL, 0}, /* 22 */
|
||||
{CmdBuildLongRoad, 0}, /* 23 */
|
||||
{CmdRemoveLongRoad, 0}, /* 24 */
|
||||
{CmdBuildRoad, 0}, /* 25 */
|
||||
{CmdRemoveRoad, 0}, /* 26 */
|
||||
{CmdBuildRoadDepot, 0}, /* 27 */
|
||||
{NULL, 0}, /* 28 */
|
||||
{CmdBuildAirport, 0}, /* 29 */
|
||||
{CmdBuildDock, 0}, /* 30 */
|
||||
{CmdBuildShipDepot, 0}, /* 31 */
|
||||
{CmdBuildBuoy, 0}, /* 32 */
|
||||
{CmdPlantTree, 0}, /* 33 */
|
||||
{CmdBuildRailVehicle, 0}, /* 34 */
|
||||
{CmdMoveRailVehicle, 0}, /* 35 */
|
||||
{CmdStartStopTrain, 0}, /* 36 */
|
||||
{NULL, 0}, /* 37 */
|
||||
{CmdSellRailWagon, 0}, /* 38 */
|
||||
{CmdSendTrainToDepot, 0}, /* 39 */
|
||||
{CmdForceTrainProceed, 0}, /* 40 */
|
||||
{CmdReverseTrainDirection, 0}, /* 41 */
|
||||
|
||||
CmdModifyOrder, /* 42 */
|
||||
CmdSkipOrder, /* 43 */
|
||||
CmdDeleteOrder, /* 44 */
|
||||
CmdInsertOrder, /* 45 */
|
||||
{CmdModifyOrder, 0}, /* 42 */
|
||||
{CmdSkipOrder, 0}, /* 43 */
|
||||
{CmdDeleteOrder, 0}, /* 44 */
|
||||
{CmdInsertOrder, 0}, /* 45 */
|
||||
|
||||
CmdChangeTrainServiceInt, /* 46 */
|
||||
{CmdChangeTrainServiceInt, 0}, /* 46 */
|
||||
|
||||
CmdBuildIndustry, /* 47 */
|
||||
CmdBuildCompanyHQ, /* 48 */
|
||||
CmdSetPlayerFace, /* 49 */
|
||||
CmdSetPlayerColor, /* 50 */
|
||||
{CmdBuildIndustry, 0}, /* 47 */
|
||||
{CmdBuildCompanyHQ, 0}, /* 48 */
|
||||
{CmdSetPlayerFace, 0}, /* 49 */
|
||||
{CmdSetPlayerColor, 0}, /* 50 */
|
||||
|
||||
CmdIncreaseLoan, /* 51 */
|
||||
CmdDecreaseLoan, /* 52 */
|
||||
{CmdIncreaseLoan, 0}, /* 51 */
|
||||
{CmdDecreaseLoan, 0}, /* 52 */
|
||||
|
||||
CmdWantEnginePreview, /* 53 */
|
||||
{CmdWantEnginePreview, 0}, /* 53 */
|
||||
|
||||
CmdNameVehicle, /* 54 */
|
||||
CmdRenameEngine, /* 55 */
|
||||
{CmdNameVehicle, 0}, /* 54 */
|
||||
{CmdRenameEngine, 0}, /* 55 */
|
||||
|
||||
CmdChangeCompanyName, /* 56 */
|
||||
CmdChangePresidentName, /* 57 */
|
||||
{CmdChangeCompanyName, 0}, /* 56 */
|
||||
{CmdChangePresidentName, 0}, /* 57 */
|
||||
|
||||
CmdRenameStation, /* 58 */
|
||||
{CmdRenameStation, 0}, /* 58 */
|
||||
|
||||
CmdSellAircraft, /* 59 */
|
||||
CmdStartStopAircraft, /* 60 */
|
||||
CmdBuildAircraft, /* 61 */
|
||||
CmdSendAircraftToHangar, /* 62 */
|
||||
CmdChangeAircraftServiceInt, /* 63 */
|
||||
CmdRefitAircraft, /* 64 */
|
||||
{CmdSellAircraft, 0}, /* 59 */
|
||||
{CmdStartStopAircraft, 0}, /* 60 */
|
||||
|
||||
CmdPlaceSign, /* 65 */
|
||||
CmdRenameSign, /* 66 */
|
||||
{CmdBuildAircraft, 0}, /* 61 */
|
||||
{CmdSendAircraftToHangar, 0}, /* 62 */
|
||||
{CmdChangeAircraftServiceInt, 0}, /* 63 */
|
||||
{CmdRefitAircraft, 0}, /* 64 */
|
||||
|
||||
CmdBuildRoadVeh, /* 67 */
|
||||
CmdStartStopRoadVeh, /* 68 */
|
||||
CmdSellRoadVeh, /* 69 */
|
||||
CmdSendRoadVehToDepot, /* 70 */
|
||||
CmdTurnRoadVeh, /* 71 */
|
||||
CmdChangeRoadVehServiceInt, /* 72 */
|
||||
{CmdPlaceSign, 0}, /* 65 */
|
||||
{CmdRenameSign, 0}, /* 66 */
|
||||
|
||||
CmdPause, /* 73 */
|
||||
{CmdBuildRoadVeh, 0}, /* 67 */
|
||||
{CmdStartStopRoadVeh, 0}, /* 68 */
|
||||
{CmdSellRoadVeh, 0}, /* 69 */
|
||||
{CmdSendRoadVehToDepot, 0}, /* 70 */
|
||||
{CmdTurnRoadVeh, 0}, /* 71 */
|
||||
{CmdChangeRoadVehServiceInt, 0}, /* 72 */
|
||||
|
||||
CmdBuyShareInCompany, /* 74 */
|
||||
CmdSellShareInCompany, /* 75 */
|
||||
CmdBuyCompany, /* 76 */
|
||||
{CmdPause, CMD_SERVER}, /* 73 */
|
||||
|
||||
CmdBuildTown, /* 77 */
|
||||
NULL, /* 78 */
|
||||
NULL, /* 79 */
|
||||
CmdRenameTown, /* 80 */
|
||||
CmdDoTownAction, /* 81 */
|
||||
{CmdBuyShareInCompany, 0}, /* 74 */
|
||||
{CmdSellShareInCompany, 0}, /* 75 */
|
||||
{CmdBuyCompany, 0}, /* 76 */
|
||||
|
||||
CmdSetRoadDriveSide, /* 82 */
|
||||
CmdSetTownNameType, /* 83 */
|
||||
NULL, /* 84 */
|
||||
CmdChangeDifficultyLevel, /* 85 */
|
||||
{CmdBuildTown, CMD_OFFLINE}, /* 77 */
|
||||
{NULL, 0}, /* 78 */
|
||||
{NULL, 0}, /* 79 */
|
||||
{CmdRenameTown, CMD_SERVER}, /* 80 */
|
||||
{CmdDoTownAction, 0}, /* 81 */
|
||||
|
||||
CmdStartStopShip, /* 86 */
|
||||
CmdSellShip, /* 87 */
|
||||
CmdBuildShip, /* 88 */
|
||||
CmdSendShipToDepot, /* 89 */
|
||||
CmdChangeShipServiceInt, /* 90 */
|
||||
CmdRefitShip, /* 91 */
|
||||
{CmdSetRoadDriveSide, CMD_SERVER}, /* 82 */
|
||||
{NULL, 0}, /* 83 */
|
||||
{NULL, 0}, /* 84 */
|
||||
{CmdChangeDifficultyLevel, CMD_SERVER}, /* 85 */
|
||||
|
||||
CmdStartNewGame, /* 92 */
|
||||
CmdLoadGame, /* 93 */
|
||||
CmdCreateScenario, /* 94 */
|
||||
CmdSetSinglePlayer, /* 95 */
|
||||
NULL, /* 96 */
|
||||
CmdSetNewLandscapeType, /* 97 */
|
||||
{CmdStartStopShip, 0}, /* 86 */
|
||||
{CmdSellShip, 0}, /* 87 */
|
||||
{CmdBuildShip, 0}, /* 88 */
|
||||
{CmdSendShipToDepot, 0}, /* 89 */
|
||||
{CmdChangeShipServiceInt, 0}, /* 90 */
|
||||
{CmdRefitShip, 0}, /* 91 */
|
||||
|
||||
CmdGenRandomNewGame, /* 98 */
|
||||
{NULL, 0}, /* 92 */
|
||||
{NULL, 0}, /* 93 */
|
||||
{NULL, 0}, /* 94 */
|
||||
{NULL, 0}, /* 95 */
|
||||
{NULL, 0}, /* 96 */
|
||||
{NULL, 0}, /* 97 */
|
||||
{NULL, 0}, /* 98 */
|
||||
|
||||
CmdCloneOrder, /* 99 */
|
||||
{CmdCloneOrder, 0}, /* 99 */
|
||||
|
||||
CmdClearArea, /* 100 */
|
||||
CmdResume, /* 101 */
|
||||
{CmdClearArea, 0}, /* 100 */
|
||||
{NULL, 0}, /* 101 */
|
||||
|
||||
CmdMoneyCheat, /* 102 */
|
||||
CmdBuildCanal, /* 103 */
|
||||
CmdPlayerCtrl, /* 104 */
|
||||
{CmdMoneyCheat, CMD_OFFLINE}, /* 102 */
|
||||
{CmdBuildCanal, 0}, /* 103 */
|
||||
{CmdPlayerCtrl, 0}, /* 104 */
|
||||
|
||||
CmdLevelLand, /* 105 */
|
||||
{CmdLevelLand, 0}, /* 105 */
|
||||
|
||||
CmdRefitRailVehicle, /* 106 */
|
||||
CmdRestoreOrderIndex, /* 107 */
|
||||
CmdBuildLock, /* 108 */
|
||||
CmdStartScenario, /* 109 */
|
||||
CmdBuildManySignals, /* 110 */
|
||||
//CmdDestroyIndustry, /* 109 */
|
||||
CmdDestroyCompanyHQ, /* 111 */
|
||||
{CmdRefitRailVehicle, 0}, /* 106 */
|
||||
{CmdRestoreOrderIndex, 0}, /* 107 */
|
||||
{CmdBuildLock, 0}, /* 108 */
|
||||
{NULL, 0}, /* 109 */
|
||||
{CmdBuildSignalTrack, 0}, /* 110 */
|
||||
{CmdRemoveSignalTrack, 0}, /* 111 */
|
||||
{NULL, 0}, /* 112 */
|
||||
{CmdGiveMoney, 0}, /* 113 */
|
||||
{CmdChangePatchSetting, CMD_SERVER}, /* 114 */
|
||||
{CmdReplaceVehicle, 0}, /* 115 */
|
||||
};
|
||||
|
||||
/* This function range-checks a cmd, and checks if the cmd is not NULL */
|
||||
bool IsValidCommand(uint cmd)
|
||||
{
|
||||
cmd = cmd & 0xFF;
|
||||
|
||||
if (cmd >= lengthof(_command_proc_table) || _command_proc_table[cmd].proc == NULL)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
byte GetCommandFlags(uint cmd) {return _command_proc_table[cmd & 0xFF].flags;}
|
||||
|
||||
int32 DoCommandByTile(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc)
|
||||
{
|
||||
return DoCommand(GET_TILE_X(tile)*16, GET_TILE_Y(tile)*16, p1, p2, flags, procc);
|
||||
return DoCommand(TileX(tile) * 16, TileY(tile) * 16, p1, p2, flags, procc);
|
||||
}
|
||||
|
||||
|
||||
@@ -315,7 +324,13 @@ int32 DoCommand(int x, int y, uint32 p1, uint32 p2, uint32 flags, uint procc)
|
||||
int32 res;
|
||||
CommandProc *proc;
|
||||
|
||||
proc = _command_proc_table[procc];
|
||||
/* Do not even think about executing out-of-bounds tile-commands */
|
||||
if (TILE_FROM_XY(x,y) > MapSize()) {
|
||||
_cmd_text = NULL;
|
||||
return CMD_ERROR;
|
||||
}
|
||||
|
||||
proc = _command_proc_table[procc].proc;
|
||||
|
||||
if (_docommand_recursive == 0) {
|
||||
_error_message = INVALID_STRING_ID;
|
||||
@@ -330,7 +345,7 @@ int32 DoCommand(int x, int y, uint32 p1, uint32 p2, uint32 flags, uint procc)
|
||||
// only execute the test call if it's toplevel, or we're not execing.
|
||||
if (_docommand_recursive == 1 || !(flags & DC_EXEC) || (flags & DC_FORCETEST) ) {
|
||||
res = proc(x, y, flags&~DC_EXEC, p1, p2);
|
||||
if ((uint32)res >> 16 == 0x8000) {
|
||||
if (CmdFailed(res)) {
|
||||
if (res & 0xFFFF) _error_message = res & 0xFFFF;
|
||||
goto error;
|
||||
}
|
||||
@@ -342,17 +357,19 @@ int32 DoCommand(int x, int y, uint32 p1, uint32 p2, uint32 flags, uint procc)
|
||||
|
||||
if (!(flags & DC_EXEC)) {
|
||||
_docommand_recursive--;
|
||||
_cmd_text = NULL;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
// execute the command here.
|
||||
_yearly_expenses_type = 0;
|
||||
/* Execute the command here. All cost-relevant functions set the expenses type
|
||||
* themselves with "SET_EXPENSES_TYPE(...);" at the beginning of the function */
|
||||
res = proc(x, y, flags, p1, p2);
|
||||
if ((uint32)res >> 16 == 0x8000) {
|
||||
if (CmdFailed(res)) {
|
||||
if (res & 0xFFFF) _error_message = res & 0xFFFF;
|
||||
error:
|
||||
_docommand_recursive--;
|
||||
_cmd_text = NULL;
|
||||
return CMD_ERROR;
|
||||
}
|
||||
|
||||
@@ -361,12 +378,13 @@ error:
|
||||
SubtractMoneyFromPlayer(res);
|
||||
}
|
||||
|
||||
_cmd_text = NULL;
|
||||
return res;
|
||||
}
|
||||
|
||||
int32 GetAvailableMoneyForCommand()
|
||||
int32 GetAvailableMoneyForCommand(void)
|
||||
{
|
||||
uint pid = _current_player;
|
||||
PlayerID pid = _current_player;
|
||||
if (pid >= MAX_PLAYERS) return 0x7FFFFFFF; // max int
|
||||
return DEREF_PLAYER(pid)->player_money;
|
||||
}
|
||||
@@ -380,27 +398,26 @@ bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback,
|
||||
uint32 flags;
|
||||
bool notest;
|
||||
|
||||
int x = GET_TILE_X(tile)*16;
|
||||
int y = GET_TILE_Y(tile)*16;
|
||||
int x = TileX(tile) * 16;
|
||||
int y = TileY(tile) * 16;
|
||||
|
||||
/* Do not even think about executing out-of-bounds tile-commands */
|
||||
if (tile > MapSize()) {
|
||||
_cmd_text = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
assert(_docommand_recursive == 0);
|
||||
|
||||
if (_networking && !(cmd & CMD_NET_INSTANT) && _pause) {
|
||||
// When the game is paused, and we are in a network game
|
||||
// we do not allow any commands. This is because
|
||||
// of some technical reasons
|
||||
ShowErrorMessage(-1, STR_MULTIPLAYER_PAUSED, x, y);
|
||||
_docommand_recursive = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
_error_message = INVALID_STRING_ID;
|
||||
_error_message_2 = cmd >> 16;
|
||||
_additional_cash_required = 0;
|
||||
|
||||
// spectator has no rights.
|
||||
if (_current_player == OWNER_SPECTATOR) {
|
||||
/** Spectator has no rights except for the dedicated server which
|
||||
* is a spectator but is the server, so can do anything */
|
||||
if (_current_player == OWNER_SPECTATOR && !_network_dedicated) {
|
||||
ShowErrorMessage(_error_message, _error_message_2, x, y);
|
||||
_cmd_text = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -410,24 +427,31 @@ bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback,
|
||||
|
||||
// get pointer to command handler
|
||||
assert((cmd & 0xFF) < lengthof(_command_proc_table));
|
||||
proc = _command_proc_table[cmd & 0xFF];
|
||||
proc = _command_proc_table[cmd & 0xFF].proc;
|
||||
|
||||
// this command is a notest command?
|
||||
// Some commands have a different output in dryrun than the realrun
|
||||
// e.g.: if you demolish a whole town, the dryrun would say okay.
|
||||
// but by really destroying, your rating drops and at a certain point
|
||||
// it will fail. so res and res2 are different
|
||||
// CMD_REMOVE_ROAD: This command has special local authority
|
||||
// restrictions which may cause the test run to fail (the previous
|
||||
// road fragments still stay there and the town won't let you
|
||||
// disconnect the road system), but the exec will succeed and this
|
||||
// fact will trigger an assertion failure. --pasky
|
||||
notest =
|
||||
(cmd & 0xFF) == CMD_CLEAR_AREA ||
|
||||
(cmd & 0xFF) == CMD_CONVERT_RAIL ||
|
||||
(cmd & 0xFF) == CMD_LEVEL_LAND ||
|
||||
(cmd & 0xFF) == CMD_TRAIN_GOTO_DEPOT;
|
||||
|
||||
if (_networking && (cmd & CMD_ASYNC)) notest = true;
|
||||
(cmd & 0xFF) == CMD_REMOVE_ROAD ||
|
||||
(cmd & 0xFF) == CMD_REMOVE_LONG_ROAD;
|
||||
|
||||
_docommand_recursive = 1;
|
||||
|
||||
// cost estimation only?
|
||||
if (_shift_pressed && _current_player == _local_player && !(cmd & CMD_DONT_NETWORK)) {
|
||||
if (_shift_pressed && _current_player == _local_player && !(cmd & (CMD_NETWORK_COMMAND | CMD_SHOW_NO_ERROR))) {
|
||||
// estimate the cost.
|
||||
res = proc(x, y, flags, p1, p2);
|
||||
if ((uint32)res >> 16 == 0x8000) {
|
||||
if (CmdFailed(res)) {
|
||||
if (res & 0xFFFF) _error_message = res & 0xFFFF;
|
||||
ShowErrorMessage(_error_message, _error_message_2, x, y);
|
||||
} else {
|
||||
@@ -435,46 +459,53 @@ bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback,
|
||||
}
|
||||
|
||||
_docommand_recursive = 0;
|
||||
_cmd_text = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// unless the command is a notest command, check if it can be executed.
|
||||
if (!notest) {
|
||||
if (!((cmd & CMD_NO_TEST_IF_IN_NETWORK) && _networking)) {
|
||||
// first test if the command can be executed.
|
||||
res = proc(x,y, flags, p1, p2);
|
||||
if ((uint32)res >> 16 == 0x8000) {
|
||||
if (CmdFailed(res)) {
|
||||
if (res & 0xFFFF) _error_message = res & 0xFFFF;
|
||||
goto show_error;
|
||||
}
|
||||
// no money?
|
||||
if (res != 0 && !CheckPlayerHasMoney(res)) goto show_error;
|
||||
// no money? Only check if notest is off
|
||||
if (!notest && res != 0 && !CheckPlayerHasMoney(res)) goto show_error;
|
||||
}
|
||||
|
||||
// put the command in a network queue and execute it later?
|
||||
if (_networking && !(cmd & CMD_DONT_NETWORK)) {
|
||||
if (!(cmd & CMD_NET_INSTANT)) {
|
||||
NetworkSendCommand(tile, p1, p2, cmd, callback);
|
||||
_docommand_recursive = 0;
|
||||
return true;
|
||||
} else {
|
||||
// Instant Command ... Relay and Process then
|
||||
NetworkSendCommand(tile, p1, p2, cmd, callback);
|
||||
}
|
||||
#ifdef ENABLE_NETWORK
|
||||
/** If we are in network, and the command is not from the network
|
||||
* send it to the command-queue and abort execution
|
||||
* If we are a dedicated server temporarily switch local player, otherwise
|
||||
* the other parties won't be able to execute our command and will desync.
|
||||
* @todo Rewrite dedicated server to something more than a dirty hack!
|
||||
*/
|
||||
if (_networking && !(cmd & CMD_NETWORK_COMMAND)) {
|
||||
if (_network_dedicated) _local_player = 0;
|
||||
NetworkSend_Command(tile, p1, p2, cmd, callback);
|
||||
if (_network_dedicated) _local_player = OWNER_SPECTATOR;
|
||||
_docommand_recursive = 0;
|
||||
_cmd_text = NULL;
|
||||
return true;
|
||||
}
|
||||
#endif /* ENABLE_NETWORK */
|
||||
|
||||
// update last build coordinate of player.
|
||||
if ( tile != 0 && _current_player < MAX_PLAYERS) DEREF_PLAYER(_current_player)->last_build_coordinate = tile;
|
||||
|
||||
// actually try and execute the command.
|
||||
_yearly_expenses_type = 0;
|
||||
/* Actually try and execute the command. If no cost-type is given
|
||||
* use the construction one */
|
||||
_yearly_expenses_type = EXPENSES_CONSTRUCTION;
|
||||
res2 = proc(x,y, flags|DC_EXEC, p1, p2);
|
||||
|
||||
if (!notest) {
|
||||
// If notest is on, it means the result of the test can be different than
|
||||
// the real command.. so ignore the test
|
||||
if (!notest && !((cmd & CMD_NO_TEST_IF_IN_NETWORK) && _networking)) {
|
||||
assert(res == res2); // sanity check
|
||||
} else {
|
||||
if ((uint32)res2 >> 16 == 0x8000) {
|
||||
if (CmdFailed(res2)) {
|
||||
if (res2 & 0xFFFF) _error_message = res2 & 0xFFFF;
|
||||
goto show_error;
|
||||
}
|
||||
@@ -486,7 +517,7 @@ bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback,
|
||||
if (res2 != 0)
|
||||
ShowCostOrIncomeAnimation(x, y, GetSlopeZ(x, y), res2);
|
||||
if (_additional_cash_required) {
|
||||
SET_DPARAM32(0, _additional_cash_required);
|
||||
SetDParam(0, _additional_cash_required);
|
||||
ShowErrorMessage(STR_0003_NOT_ENOUGH_CASH_REQUIRES, _error_message_2, x,y);
|
||||
if (res2 == 0) goto callb_err;
|
||||
}
|
||||
@@ -495,6 +526,7 @@ bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback,
|
||||
_docommand_recursive = 0;
|
||||
|
||||
if (callback) callback(true, tile, p1, p2);
|
||||
_cmd_text = NULL;
|
||||
return true;
|
||||
|
||||
show_error:
|
||||
@@ -506,5 +538,6 @@ callb_err:
|
||||
_docommand_recursive = 0;
|
||||
|
||||
if (callback) callback(false, tile, p1, p2);
|
||||
_cmd_text = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -20,12 +20,11 @@ enum {
|
||||
CMD_REMOVE_FROM_RAILROAD_STATION = 14,
|
||||
CMD_CONVERT_RAIL = 15,
|
||||
|
||||
CMD_BUILD_TRAIN_CHECKPOINT = 16,
|
||||
CMD_RENAME_CHECKPOINT = 17,
|
||||
CMD_REMOVE_TRAIN_CHECKPOINT = 18,
|
||||
CMD_BUILD_TRAIN_WAYPOINT = 16,
|
||||
CMD_RENAME_WAYPOINT = 17,
|
||||
CMD_REMOVE_TRAIN_WAYPOINT = 18,
|
||||
|
||||
CMD_BUILD_TRUCK_STATION = 19,
|
||||
CMD_BUILD_BUS_STATION = 21,
|
||||
CMD_BUILD_ROAD_STOP = 21,
|
||||
CMD_BUILD_LONG_ROAD = 23,
|
||||
CMD_REMOVE_LONG_ROAD = 24,
|
||||
CMD_BUILD_ROAD = 25,
|
||||
@@ -105,8 +104,6 @@ enum {
|
||||
CMD_DO_TOWN_ACTION = 81,
|
||||
|
||||
CMD_SET_ROAD_DRIVE_SIDE = 82,
|
||||
CMD_SET_TOWN_NAME_TYPE = 83,
|
||||
|
||||
|
||||
CMD_CHANGE_DIFFICULTY_LEVEL = 85,
|
||||
|
||||
@@ -117,20 +114,9 @@ enum {
|
||||
CMD_CHANGE_SHIP_SERVICE_INT = 90,
|
||||
CMD_REFIT_SHIP = 91,
|
||||
|
||||
CMD_START_NEW_GAME = 92,
|
||||
CMD_LOAD_GAME = 93,
|
||||
CMD_CREATE_SCENARIO = 94,
|
||||
CMD_SET_SINGLE_PLAYER = 95,
|
||||
|
||||
CMD_SET_NEW_LANDSCAPE_TYPE = 97,
|
||||
|
||||
CMD_GEN_RANDOM_NEW_GAME = 98,
|
||||
|
||||
CMD_CLONE_ORDER = 99,
|
||||
CMD_CLEAR_AREA = 100,
|
||||
|
||||
CMD_RESUME = 101,
|
||||
|
||||
CMD_MONEY_CHEAT = 102,
|
||||
CMD_BUILD_CANAL = 103,
|
||||
|
||||
@@ -141,11 +127,13 @@ enum {
|
||||
CMD_RESTORE_ORDER_INDEX = 107,
|
||||
CMD_BUILD_LOCK = 108,
|
||||
|
||||
CMD_START_SCENARIO = 109,
|
||||
CMD_BUILD_MANY_SIGNALS = 110,
|
||||
CMD_BUILD_SIGNAL_TRACK = 110,
|
||||
CMD_REMOVE_SIGNAL_TRACK = 111,
|
||||
|
||||
//CMD_DESTROY_INDUSTRY = 109,
|
||||
CMD_DESTROY_COMPANY_HQ = 111,
|
||||
CMD_GIVE_MONEY = 113,
|
||||
CMD_CHANGE_PATCH_SETTING = 114,
|
||||
|
||||
CMD_REPLACE_VEHICLE = 115,
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -166,18 +154,46 @@ enum {
|
||||
enum {
|
||||
CMD_AUTO = 0x200,
|
||||
CMD_NO_WATER = 0x400,
|
||||
CMD_DONT_NETWORK = 0x800, // execute the command without sending it on the network
|
||||
CMD_ASYNC = 0x1000, // execute the command asynchronously without testing first in networking
|
||||
CMD_NET_INSTANT = 0x2000,
|
||||
CMD_NETWORK_COMMAND = 0x800, // execute the command without sending it on the network
|
||||
CMD_NO_TEST_IF_IN_NETWORK = 0x1000, // When enabled, the command will bypass the no-DC_EXEC round if in network
|
||||
CMD_SHOW_NO_ERROR = 0x2000,
|
||||
};
|
||||
|
||||
/** Command flags for the command table
|
||||
* @see _command_proc_table
|
||||
*/
|
||||
enum {
|
||||
CMD_SERVER = 0x1, /// the command can only be initiated by the server
|
||||
CMD_OFFLINE = 0x2, /// the command cannot be executed in a multiplayer game; single-player only
|
||||
};
|
||||
|
||||
typedef struct Command {
|
||||
CommandProc *proc;
|
||||
byte flags;
|
||||
} Command;
|
||||
|
||||
//#define return_cmd_error(errcode) do { _error_message=(errcode); return CMD_ERROR; } while(0)
|
||||
#define return_cmd_error(errcode) do { return CMD_ERROR | (errcode); } while (0)
|
||||
|
||||
/**
|
||||
* Check the return value of a DoCommand*() function
|
||||
* @param res the resulting value from the command to be checked
|
||||
* @return Return true if the command failed, false otherwise
|
||||
*/
|
||||
static inline bool CmdFailed(int32 res)
|
||||
{
|
||||
// lower 16bits are the StringID of the possible error
|
||||
return res <= (CMD_ERROR | INVALID_STRING_ID);
|
||||
}
|
||||
|
||||
/* command.c */
|
||||
int32 DoCommand(int x, int y, uint32 p1, uint32 p2, uint32 flags, uint procc);
|
||||
int32 DoCommandByTile(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc);
|
||||
|
||||
int32 GetAvailableMoneyForCommand();
|
||||
extern const char* _cmd_text; // Text, which gets sent with a command
|
||||
|
||||
bool IsValidCommand(uint cmd);
|
||||
byte GetCommandFlags(uint cmd);
|
||||
int32 GetAvailableMoneyForCommand(void);
|
||||
|
||||
#endif /* COMMAND_H */
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
#!/bin/sh -
|
||||
|
||||
SDLCONFIG=`which sdl-config || which sdl11-config || which sdl12-config || echo `
|
||||
if [ -n "$SDLCONFIG" ] ; then
|
||||
echo "SDL config is located at: $SDLCONFIG"
|
||||
sed -e"s@XX_SDL_CONFIG_PLACEHOLDER_XX@$SDLCONFIG@g" < Jamfile.next > tmp && mv tmp Jamfile
|
||||
else
|
||||
echo "********************************"
|
||||
echo "ERROR! SDL CONFIG WAS NOT FOUND!"
|
||||
echo "********************************"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Configure complete. Now use 'jam' to build"
|
||||
echo "Add -sWITH_PNG=<dir to png.h> to build with PNG support"
|
||||
echo "Add -sWITH_ZLIB=1 to enable zlib savegame support"
|
||||
echo "Add -sRELEASE=1 to build an optimized executable"
|
||||
echo "Add -sWITH_BONE_NETWORKING=1 to build with BeOS BONE networking support"
|
||||
echo "Add -sBEOS_MIDI=1 to enable BeOS native MIDI (libmidi.so) music output"
|
||||
echo ""
|
||||
echo "For people using make:"
|
||||
echo "write make (or gmake)"
|
||||
echo "configure have nothing to do with the makefile"
|
||||
|
||||
@@ -1,129 +1,163 @@
|
||||
#ifndef CONSOLE_H
|
||||
#define CONSOLE_H
|
||||
|
||||
// ** console ** //
|
||||
// maximum length of a typed in command
|
||||
#define ICON_CMDLN_SIZE 255
|
||||
// maximum length of a totally expanded command
|
||||
#define ICON_MAX_STREAMSIZE 1024
|
||||
|
||||
enum {
|
||||
ICONSOLE_OPENED=0,
|
||||
ICONSOLE_CLOSED,
|
||||
} _iconsole_modes;
|
||||
|
||||
// ** console parser ** //
|
||||
|
||||
enum {
|
||||
ICONSOLE_VAR_NONE=0,
|
||||
typedef enum IConsoleVarTypes {
|
||||
ICONSOLE_VAR_BOOLEAN,
|
||||
ICONSOLE_VAR_BYTE,
|
||||
ICONSOLE_VAR_UINT16,
|
||||
ICONSOLE_VAR_UINT32,
|
||||
ICONSOLE_VAR_INT16,
|
||||
ICONSOLE_VAR_INT32,
|
||||
ICONSOLE_VAR_STRING,
|
||||
ICONSOLE_VAR_POINTER,
|
||||
ICONSOLE_VAR_REFERENCE,
|
||||
ICONSOLE_VAR_UNKNOWN,
|
||||
} _iconsole_var_types;
|
||||
ICONSOLE_VAR_STRING
|
||||
} IConsoleVarTypes;
|
||||
|
||||
enum {
|
||||
typedef enum IConsoleModes {
|
||||
ICONSOLE_FULL,
|
||||
ICONSOLE_OPENED,
|
||||
ICONSOLE_CLOSED
|
||||
} IConsoleModes;
|
||||
|
||||
typedef enum IConsoleHookTypes {
|
||||
ICONSOLE_HOOK_ACCESS,
|
||||
ICONSOLE_HOOK_BEFORE_CHANGE,
|
||||
ICONSOLE_HOOK_BEFORE_EXEC,
|
||||
ICONSOLE_HOOK_AFTER_CHANGE,
|
||||
ICONSOLE_HOOK_AFTER_EXEC,
|
||||
} _iconsole_hook_types;
|
||||
ICONSOLE_HOOK_PRE_ACTION,
|
||||
ICONSOLE_HOOK_POST_ACTION
|
||||
} IConsoleHookTypes;
|
||||
|
||||
typedef struct {
|
||||
// -------------- //
|
||||
void * addr;
|
||||
byte * name;
|
||||
// -------------- //
|
||||
void * hook_access;
|
||||
void * hook_before_exec;
|
||||
void * hook_after_exec;
|
||||
// -------------- //
|
||||
void * _next;
|
||||
} _iconsole_cmd;
|
||||
/** --Hooks--
|
||||
* Hooks are certain triggers get get accessed/executed on either
|
||||
* access, before execution/change or after execution/change. This allows
|
||||
* for general flow of permissions or special action needed in some cases
|
||||
*/
|
||||
typedef bool IConsoleHook(void);
|
||||
typedef struct IConsoleHooks{
|
||||
IConsoleHook *access; // trigger when accessing the variable/command
|
||||
IConsoleHook *pre; // trigger before the variable/command is changed/executed
|
||||
IConsoleHook *post; // trigger after the variable/command is changed/executed
|
||||
} IConsoleHooks;
|
||||
|
||||
typedef struct {
|
||||
// --------------- //
|
||||
void * addr;
|
||||
const byte * name;
|
||||
byte type;
|
||||
// -------------- //
|
||||
void * hook_access;
|
||||
void * hook_before_change;
|
||||
void * hook_after_change;
|
||||
// -------------- //
|
||||
void * _next;
|
||||
bool _malloc;
|
||||
} _iconsole_var;
|
||||
/** --Commands--
|
||||
* Commands are commands, or functions. They get executed once and any
|
||||
* effect they produce are carried out. The arguments to the commands
|
||||
* are given to them, each input word seperated by a double-quote (") is an argument
|
||||
* If you want to handle multiple words as one, enclose them in double-quotes
|
||||
* eg. 'say "hello sexy boy"'
|
||||
*/
|
||||
typedef bool (IConsoleCmdProc)(byte argc, char *argv[]);
|
||||
|
||||
struct IConsoleCmd;
|
||||
typedef struct IConsoleCmd {
|
||||
char *name; // name of command
|
||||
struct IConsoleCmd *next; // next command in list
|
||||
|
||||
IConsoleCmdProc *proc; // process executed when command is typed
|
||||
IConsoleHooks hook; // any special trigger action that needs executing
|
||||
} IConsoleCmd;
|
||||
|
||||
/** --Variables--
|
||||
* Variables are pointers to real ingame variables which allow for
|
||||
* changing while ingame. After changing they keep their new value
|
||||
* and can be used for debugging, gameplay, etc. It accepts:
|
||||
* - no arguments; just print out current value
|
||||
* - '= <new value>' to assign a new value to the variable
|
||||
* - '++' to increase value by one
|
||||
* - '--' to decrease value by one
|
||||
*/
|
||||
struct IConsoleVar;
|
||||
typedef struct IConsoleVar {
|
||||
char *name; // name of the variable
|
||||
struct IConsoleVar *next; // next variable in list
|
||||
|
||||
void *addr; // the address where the variable is pointing at
|
||||
uint32 size; // size of the variable, used for strings
|
||||
char *help; // the optional help string shown when requesting information
|
||||
IConsoleVarTypes type; // type of variable (for correct assignment/output)
|
||||
IConsoleCmdProc *proc; // some variables need really special handling, use a callback function for that
|
||||
IConsoleHooks hook; // any special trigger action that needs executing
|
||||
} IConsoleVar;
|
||||
|
||||
/** --Aliases--
|
||||
* Aliases are like shortcuts for complex functions, variable assignments,
|
||||
* etc. You can use a simple alias to rename a longer command (eg 'lv' for
|
||||
* 'list_vars' for example), or concatenate more commands into one
|
||||
* (eg. 'ng' for 'load %A; unpause; debug_level 5'). Aliases can parse the arguments
|
||||
* given to them in the command line.
|
||||
* - "%A - %Z" substitute arguments 1 t/m 26
|
||||
* - "%+" lists all parameters keeping them seperated
|
||||
* - "%!" also lists all parameters but presenting them to the aliased command as one argument
|
||||
* - ";" allows for combining commands (see example 'ng')
|
||||
*/
|
||||
struct IConsoleAlias;
|
||||
typedef struct IConsoleAlias {
|
||||
char *name; // name of the alias
|
||||
struct IConsoleAlias *next; // next alias in list
|
||||
|
||||
char *cmdline; // command(s) that is/are being aliased
|
||||
} IConsoleAlias;
|
||||
|
||||
// ** console parser ** //
|
||||
IConsoleCmd *_iconsole_cmds; // list of registred commands
|
||||
IConsoleVar *_iconsole_vars; // list of registred vars
|
||||
IConsoleAlias *_iconsole_aliases; // list of registred aliases
|
||||
|
||||
_iconsole_cmd * _iconsole_cmds; // list of registred commands
|
||||
_iconsole_var * _iconsole_vars; // list of registred vars
|
||||
|
||||
// ** console colors ** //
|
||||
VARDEF byte _iconsole_color_default;
|
||||
VARDEF byte _iconsole_color_error;
|
||||
VARDEF byte _iconsole_color_warning;
|
||||
VARDEF byte _iconsole_color_debug;
|
||||
VARDEF byte _iconsole_color_commands;
|
||||
|
||||
// ** ttd.c functions ** //
|
||||
|
||||
void SetDebugString(const char *s);
|
||||
// ** console colors/modes ** //
|
||||
VARDEF byte _icolour_def;
|
||||
VARDEF byte _icolour_err;
|
||||
VARDEF byte _icolour_warn;
|
||||
VARDEF byte _icolour_dbg;
|
||||
VARDEF byte _icolour_cmd;
|
||||
VARDEF IConsoleModes _iconsole_mode;
|
||||
|
||||
// ** console functions ** //
|
||||
|
||||
void IConsoleClearCommand();
|
||||
void IConsoleInit();
|
||||
void IConsoleClear();
|
||||
void IConsoleFree();
|
||||
void IConsoleResize();
|
||||
void IConsoleSwitch();
|
||||
void IConsoleClose();
|
||||
void IConsoleOpen();
|
||||
void IConsoleInit(void);
|
||||
void IConsoleFree(void);
|
||||
void IConsoleClearBuffer(void);
|
||||
void IConsoleResize(void);
|
||||
void IConsoleSwitch(void);
|
||||
void IConsoleClose(void);
|
||||
void IConsoleOpen(void);
|
||||
|
||||
// ** console cmd buffer ** //
|
||||
void IConsoleCmdBufferAdd(const byte *cmd);
|
||||
void IConsoleCmdBufferNavigate(signed char direction);
|
||||
void IConsoleHistoryAdd(const char *cmd);
|
||||
void IConsoleHistoryNavigate(signed char direction);
|
||||
|
||||
// ** console output ** //
|
||||
void IConsolePrint(byte color_code, const byte* string);
|
||||
void CDECL IConsolePrintF(byte color_code, const char *s, ...);
|
||||
void IConsoleDebug(byte* string);
|
||||
void IConsoleError(const byte* string);
|
||||
void IConsoleWarning(const byte* string);
|
||||
void IConsolePrint(uint16 color_code, const char *string);
|
||||
void CDECL IConsolePrintF(uint16 color_code, const char *s, ...);
|
||||
void IConsoleDebug(const char *string);
|
||||
void IConsoleWarning(const char *string);
|
||||
void IConsoleError(const char *string);
|
||||
|
||||
// *** Commands *** //
|
||||
|
||||
void IConsoleCmdRegister(const byte * name, void * addr);
|
||||
_iconsole_cmd * IConsoleCmdGet(const byte * name);
|
||||
void IConsoleCmdRegister(const char *name, IConsoleCmdProc *proc);
|
||||
void IConsoleAliasRegister(const char *name, const char *cmd);
|
||||
IConsoleCmd *IConsoleCmdGet(const char *name);
|
||||
IConsoleAlias *IConsoleAliasGet(const char *name);
|
||||
|
||||
// *** Variables *** //
|
||||
|
||||
void IConsoleVarRegister(const byte * name, void * addr, byte type);
|
||||
void IConsoleVarMemRegister(const byte * name, byte type);
|
||||
void IConsoleVarInsert(_iconsole_var * var, const byte * name);
|
||||
_iconsole_var * IConsoleVarGet(const byte * name);
|
||||
_iconsole_var * IConsoleVarAlloc(byte type);
|
||||
void IConsoleVarFree(_iconsole_var * var);
|
||||
void IConsoleVarSetString(_iconsole_var * var, const byte * string);
|
||||
void IConsoleVarSetValue(_iconsole_var * var, int value);
|
||||
void IConsoleVarDump(_iconsole_var * var, const byte * dump_desc);
|
||||
void IConsoleVarRegister(const char *name, void *addr, IConsoleVarTypes type, const char *help);
|
||||
void IConsoleVarStringRegister(const char *name, void *addr, uint32 size, const char *help);
|
||||
IConsoleVar* IConsoleVarGet(const char *name);
|
||||
void IConsoleVarPrintGetValue(const IConsoleVar *var);
|
||||
void IConsoleVarPrintSetValue(const IConsoleVar *var);
|
||||
|
||||
// *** Parser *** //
|
||||
void IConsoleCmdExec(const char *cmdstr);
|
||||
void IConsoleVarExec(const IConsoleVar *var, byte tokencount, char *token[]);
|
||||
void IConsoleAliasExec(const IConsoleAlias *alias, byte tokencount, char *tokens[]);
|
||||
|
||||
void IConsoleCmdExec(const byte* cmdstr);
|
||||
// ** console std lib (register ingame commands/aliases/variables) ** //
|
||||
void IConsoleStdLibRegister(void);
|
||||
|
||||
// ** console std lib ** //
|
||||
void IConsoleStdLibRegister();
|
||||
|
||||
// ** hook code ** //
|
||||
void IConsoleVarHook(const byte * name, byte type, void * proc);
|
||||
void IConsoleCmdHook(const byte * name, byte type, void * proc);
|
||||
bool IConsoleVarHookHandle(_iconsole_var * hook_var, byte type);
|
||||
bool IConsoleCmdHookHandle(_iconsole_cmd * hook_cmd, byte type);
|
||||
// ** Hooking code ** //
|
||||
void IConsoleCmdHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *proc);
|
||||
void IConsoleVarHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *proc);
|
||||
void IConsoleVarProcAdd(const char *name, IConsoleCmdProc *proc);
|
||||
|
||||
// ** Supporting functions **//
|
||||
bool GetArgumentInteger(uint32 *value, const char *arg);
|
||||
#endif /* CONSOLE_H */
|
||||
|
||||
+1160
-287
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,120 @@
|
||||
#include "stdafx.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include "ttd.h"
|
||||
#include "console.h"
|
||||
#include "debug.h"
|
||||
#include "string.h"
|
||||
|
||||
int _debug_ai_level;
|
||||
int _debug_grf_level;
|
||||
int _debug_map_level;
|
||||
int _debug_misc_level;
|
||||
int _debug_ms_level;
|
||||
int _debug_net_level;
|
||||
int _debug_spritecache_level;
|
||||
int _debug_oldloader_level;
|
||||
int _debug_npf_level;
|
||||
|
||||
|
||||
void CDECL debug(const char *s, ...)
|
||||
{
|
||||
va_list va;
|
||||
char buf[1024];
|
||||
|
||||
va_start(va, s);
|
||||
vsnprintf(buf, lengthof(buf), s, va);
|
||||
va_end(va);
|
||||
fprintf(stderr, "dbg: %s\n", buf);
|
||||
IConsoleDebug(buf);
|
||||
}
|
||||
|
||||
typedef struct DebugLevel {
|
||||
const char *name;
|
||||
int *level;
|
||||
} DebugLevel;
|
||||
|
||||
#define DEBUG_LEVEL(x) { #x, &_debug_##x##_level }
|
||||
static const DebugLevel debug_level[] = {
|
||||
DEBUG_LEVEL(ai),
|
||||
DEBUG_LEVEL(grf),
|
||||
DEBUG_LEVEL(map),
|
||||
DEBUG_LEVEL(misc),
|
||||
DEBUG_LEVEL(ms),
|
||||
DEBUG_LEVEL(net),
|
||||
DEBUG_LEVEL(spritecache),
|
||||
DEBUG_LEVEL(oldloader),
|
||||
DEBUG_LEVEL(npf)
|
||||
};
|
||||
#undef DEBUG_LEVEL
|
||||
|
||||
void SetDebugString(const char *s)
|
||||
{
|
||||
int v;
|
||||
char *end;
|
||||
const char *t;
|
||||
|
||||
// global debugging level?
|
||||
if (*s >= '0' && *s <= '9') {
|
||||
const DebugLevel *i;
|
||||
|
||||
v = strtoul(s, &end, 0);
|
||||
s = end;
|
||||
|
||||
for (i = debug_level; i != endof(debug_level); ++i)
|
||||
*i->level = v;
|
||||
}
|
||||
|
||||
// individual levels
|
||||
for(;;) {
|
||||
const DebugLevel *i;
|
||||
int *p;
|
||||
|
||||
// skip delimiters
|
||||
while (*s == ' ' || *s == ',' || *s == '\t') s++;
|
||||
if (*s == '\0') break;
|
||||
|
||||
t = s;
|
||||
while (*s >= 'a' && *s <= 'z') s++;
|
||||
|
||||
// check debugging levels
|
||||
p = NULL;
|
||||
for (i = debug_level; i != endof(debug_level); ++i)
|
||||
if (s == t + strlen(i->name) && strncmp(t, i->name, s - t) == 0) {
|
||||
p = i->level;
|
||||
break;
|
||||
}
|
||||
|
||||
if (*s == '=') s++;
|
||||
v = strtoul(s, &end, 0);
|
||||
s = end;
|
||||
if (p != NULL)
|
||||
*p = v;
|
||||
else {
|
||||
ShowInfoF("Unknown debug level '%.*s'", s - t, t);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Print out the current debug-level
|
||||
* Just return a string with the values of all the debug categorites
|
||||
* @return string with debug-levels
|
||||
*/
|
||||
const char *GetDebugString(void)
|
||||
{
|
||||
const DebugLevel *i;
|
||||
static char dbgstr[100];
|
||||
char dbgval[20];
|
||||
|
||||
memset(dbgstr, 0, sizeof(dbgstr));
|
||||
i = debug_level;
|
||||
snprintf(dbgstr, sizeof(dbgstr), "%s=%d", i->name, *i->level);
|
||||
|
||||
for (i++; i != endof(debug_level); i++) {
|
||||
snprintf(dbgval, sizeof(dbgval), ", %s=%d", i->name, *i->level);
|
||||
ttd_strlcat(dbgstr, dbgval, sizeof(dbgstr));
|
||||
}
|
||||
|
||||
return dbgstr;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef DEBUG_H
|
||||
#define DEBUG_H
|
||||
|
||||
#ifdef NO_DEBUG_MESSAGES
|
||||
#define DEBUG(name, level)
|
||||
#else
|
||||
#define DEBUG(name, level) if (level == 0 || _debug_ ## name ## _level >= level) debug
|
||||
|
||||
extern int _debug_ai_level;
|
||||
extern int _debug_grf_level;
|
||||
extern int _debug_map_level;
|
||||
extern int _debug_misc_level;
|
||||
extern int _debug_ms_level;
|
||||
extern int _debug_net_level;
|
||||
extern int _debug_spritecache_level;
|
||||
extern int _debug_oldloader_level;
|
||||
extern int _debug_npf_level;
|
||||
#endif
|
||||
|
||||
void CDECL debug(const char *s, ...);
|
||||
|
||||
void SetDebugString(const char *s);
|
||||
const char *GetDebugString(void);
|
||||
|
||||
#endif
|
||||
+356
@@ -0,0 +1,356 @@
|
||||
#include "stdafx.h"
|
||||
#include "ttd.h"
|
||||
#include "debug.h"
|
||||
#include "network.h"
|
||||
#include "hal.h"
|
||||
|
||||
#ifdef ENABLE_NETWORK
|
||||
|
||||
#include "gfx.h"
|
||||
#include "window.h"
|
||||
#include "command.h"
|
||||
#include "console.h"
|
||||
#ifdef WIN32
|
||||
# include <windows.h> /* GetTickCount */
|
||||
# include <conio.h>
|
||||
#endif
|
||||
|
||||
#ifdef __OS2__
|
||||
# include <sys/time.h> /* gettimeofday */
|
||||
# include <sys/types.h>
|
||||
# include <unistd.h>
|
||||
# include <conio.h>
|
||||
# define STDIN 0 /* file descriptor for standard input */
|
||||
|
||||
extern void OS2_SwitchToConsoleMode();
|
||||
#endif
|
||||
|
||||
#ifdef UNIX
|
||||
# include <sys/time.h> /* gettimeofday */
|
||||
# include <sys/types.h>
|
||||
# include <unistd.h>
|
||||
# include <signal.h>
|
||||
# define STDIN 0 /* file descriptor for standard input */
|
||||
#endif
|
||||
#ifdef __MORPHOS__
|
||||
/* Voids the fork, option will be disabled for MorphOS build anyway, because
|
||||
* MorphOS doesn't support forking (could only implemented with lots of code
|
||||
* changes here). */
|
||||
int fork(void) { return -1; }
|
||||
int dup2(int oldd, int newd) { return -1; }
|
||||
#endif
|
||||
|
||||
// This file handles all dedicated-server in- and outputs
|
||||
|
||||
static void *_dedicated_video_mem;
|
||||
|
||||
extern bool SafeSaveOrLoad(const char *filename, int mode, int newgm);
|
||||
extern void SwitchMode(int new_mode);
|
||||
|
||||
#ifdef UNIX
|
||||
/* We want to fork our dedicated server */
|
||||
void DedicatedFork(void)
|
||||
{
|
||||
/* Fork the program */
|
||||
pid_t pid = fork();
|
||||
switch (pid) {
|
||||
case -1:
|
||||
perror("Unable to fork");
|
||||
exit(1);
|
||||
case 0:
|
||||
// We're the child
|
||||
|
||||
/* Open the log-file to log all stuff too */
|
||||
_log_file_fd = fopen(_log_file, "a");
|
||||
if (!_log_file_fd) {
|
||||
perror("Unable to open logfile");
|
||||
exit(1);
|
||||
}
|
||||
/* Redirect stdout and stderr to log-file */
|
||||
if (dup2(fileno(_log_file_fd), fileno(stdout)) == -1) {
|
||||
perror("Rerouting stdout");
|
||||
exit(1);
|
||||
}
|
||||
if (dup2(fileno(_log_file_fd), fileno(stderr)) == -1) {
|
||||
perror("Rerouting stderr");
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// We're the parent
|
||||
printf("Loading dedicated server...\n");
|
||||
printf(" - Forked to background with pid %d\n", pid);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Signal handlers */
|
||||
static void DedicatedSignalHandler(int sig)
|
||||
{
|
||||
_exit_game = true;
|
||||
signal(sig, DedicatedSignalHandler);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#include <time.h>
|
||||
HANDLE hEvent;
|
||||
static HANDLE hThread; // Thread to close
|
||||
static char _win_console_thread_buffer[200];
|
||||
|
||||
/* Windows Console thread. Just loop and signal when input has been received */
|
||||
void WINAPI CheckForConsoleInput(void)
|
||||
{
|
||||
while (true) {
|
||||
fgets(_win_console_thread_buffer, lengthof(_win_console_thread_buffer), stdin);
|
||||
SetEvent(hEvent); // signal input waiting that the line is ready
|
||||
}
|
||||
}
|
||||
|
||||
void CreateWindowsConsoleThread(void)
|
||||
{
|
||||
static char tbuffer[9];
|
||||
DWORD dwThreadId;
|
||||
/* Create event to signal when console input is ready */
|
||||
hEvent = CreateEvent(NULL, false, false, _strtime(tbuffer));
|
||||
if (hEvent == NULL)
|
||||
error("Cannot create console event!");
|
||||
|
||||
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CheckForConsoleInput, NULL, 0, &dwThreadId);
|
||||
if (hThread == NULL)
|
||||
error("Cannot create console thread!");
|
||||
|
||||
DEBUG(misc, 0) ("Windows console thread started...");
|
||||
}
|
||||
|
||||
void CloseWindowsConsoleThread(void)
|
||||
{
|
||||
CloseHandle(hThread);
|
||||
CloseHandle(hEvent);
|
||||
DEBUG(misc, 0) ("Windows console thread shut down...");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static const char *DedicatedVideoStart(const char * const *parm)
|
||||
{
|
||||
_screen.width = _screen.pitch = _cur_resolution[0];
|
||||
_screen.height = _cur_resolution[1];
|
||||
_dedicated_video_mem = malloc(_cur_resolution[0]*_cur_resolution[1]);
|
||||
|
||||
_debug_net_level = 6;
|
||||
_debug_misc_level = 0;
|
||||
|
||||
#ifdef WIN32
|
||||
// For win32 we need to allocate an console (debug mode does the same)
|
||||
CreateConsole();
|
||||
CreateWindowsConsoleThread();
|
||||
SetConsoleTitle("OpenTTD Dedicated Server");
|
||||
#endif
|
||||
|
||||
#ifdef __OS2__
|
||||
// For OS/2 we also need to switch to console mode instead of PM mode
|
||||
OS2_SwitchToConsoleMode();
|
||||
#endif
|
||||
|
||||
DEBUG(misc,0)("Loading dedicated server...");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void DedicatedVideoStop(void)
|
||||
{
|
||||
#ifdef WIN32
|
||||
CloseWindowsConsoleThread();
|
||||
#endif
|
||||
free(_dedicated_video_mem);
|
||||
}
|
||||
|
||||
static void DedicatedVideoMakeDirty(int left, int top, int width, int height) {}
|
||||
static bool DedicatedVideoChangeRes(int w, int h) { return false; }
|
||||
static void DedicatedVideoFullScreen(bool fs) {}
|
||||
|
||||
#if defined(UNIX) || defined(__OS2__)
|
||||
static bool InputWaiting(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
fd_set readfds;
|
||||
byte ret;
|
||||
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 1;
|
||||
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(STDIN, &readfds);
|
||||
|
||||
/* don't care about writefds and exceptfds: */
|
||||
ret = select(STDIN + 1, &readfds, NULL, NULL, &tv);
|
||||
|
||||
if (ret > 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
static bool InputWaiting(void)
|
||||
{
|
||||
if (WaitForSingleObject(hEvent, 1) == WAIT_OBJECT_0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void DedicatedHandleKeyInput(void)
|
||||
{
|
||||
static char input_line[200] = "";
|
||||
|
||||
if (!InputWaiting())
|
||||
return;
|
||||
|
||||
if (_exit_game)
|
||||
return;
|
||||
|
||||
#if defined(UNIX) || defined(__OS2__)
|
||||
fgets(input_line, lengthof(input_line), stdin);
|
||||
#else
|
||||
strncpy(input_line, _win_console_thread_buffer, lengthof(input_line));
|
||||
#endif
|
||||
|
||||
/* XXX - strtok() does not 'forget' \n\r if it is the first character! */
|
||||
strtok(input_line, "\r\n"); // Forget about the final \n (or \r)
|
||||
{ /* Remove any special control characters */
|
||||
uint i;
|
||||
for (i = 0; i < lengthof(input_line); i++) {
|
||||
if (input_line[i] == '\n' || input_line[i] == '\r') // cut missed beginning '\0'
|
||||
input_line[i] = '\0';
|
||||
|
||||
if (input_line[i] == '\0')
|
||||
break;
|
||||
|
||||
if (!IS_INT_INSIDE(input_line[i], ' ', 256))
|
||||
input_line[i] = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
IConsoleCmdExec(input_line); // execute command
|
||||
}
|
||||
|
||||
static int DedicatedVideoMainLoop(void)
|
||||
{
|
||||
#ifndef WIN32
|
||||
struct timeval tim;
|
||||
#endif
|
||||
uint32 next_tick;
|
||||
uint32 cur_ticks;
|
||||
|
||||
#ifdef WIN32
|
||||
next_tick = GetTickCount() + 30;
|
||||
#else
|
||||
gettimeofday(&tim, NULL);
|
||||
next_tick = (tim.tv_usec / 1000) + 30 + (tim.tv_sec * 1000);
|
||||
#endif
|
||||
|
||||
/* Signal handlers */
|
||||
#ifdef UNIX
|
||||
signal(SIGTERM, DedicatedSignalHandler);
|
||||
signal(SIGINT, DedicatedSignalHandler);
|
||||
signal(SIGQUIT, DedicatedSignalHandler);
|
||||
#endif
|
||||
|
||||
// Load the dedicated server stuff
|
||||
_is_network_server = true;
|
||||
_network_dedicated = true;
|
||||
_network_playas = OWNER_SPECTATOR;
|
||||
_local_player = OWNER_SPECTATOR;
|
||||
|
||||
/* If SwitchMode is SM_LOAD, it means that the user used the '-g' options */
|
||||
if (_switch_mode != SM_LOAD) {
|
||||
_switch_mode = SM_NONE;
|
||||
GenRandomNewGame(Random(), InteractiveRandom());
|
||||
} else {
|
||||
_switch_mode = SM_NONE;
|
||||
/* First we need to test if the savegame can be loaded, else we will end up playing the
|
||||
* intro game... */
|
||||
if (!SafeSaveOrLoad(_file_to_saveload.name, _file_to_saveload.mode, GM_NORMAL)) {
|
||||
/* Loading failed, pop out.. */
|
||||
DEBUG(net, 0)("Loading requested map failed. Aborting.");
|
||||
_networking = false;
|
||||
} else {
|
||||
/* We can load this game, so go ahead */
|
||||
SwitchMode(SM_LOAD);
|
||||
}
|
||||
}
|
||||
|
||||
// Done loading, start game!
|
||||
|
||||
if (!_networking) {
|
||||
DEBUG(net, 1)("Dedicated server could not be launched. Aborting.");
|
||||
return ML_QUIT;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
InteractiveRandom(); // randomness
|
||||
|
||||
if (_exit_game) return ML_QUIT;
|
||||
|
||||
if (!_dedicated_forks)
|
||||
DedicatedHandleKeyInput();
|
||||
|
||||
#ifdef WIN32
|
||||
cur_ticks = GetTickCount();
|
||||
#else
|
||||
gettimeofday(&tim, NULL);
|
||||
cur_ticks = (tim.tv_usec / 1000) + (tim.tv_sec * 1000);
|
||||
#endif
|
||||
|
||||
if (cur_ticks >= next_tick) {
|
||||
next_tick += 30;
|
||||
|
||||
GameLoop();
|
||||
_screen.dst_ptr = _dedicated_video_mem;
|
||||
UpdateWindows();
|
||||
}
|
||||
CSleep(1);
|
||||
}
|
||||
|
||||
return ML_QUIT;
|
||||
}
|
||||
|
||||
|
||||
const HalVideoDriver _dedicated_video_driver = {
|
||||
DedicatedVideoStart,
|
||||
DedicatedVideoStop,
|
||||
DedicatedVideoMakeDirty,
|
||||
DedicatedVideoMainLoop,
|
||||
DedicatedVideoChangeRes,
|
||||
DedicatedVideoFullScreen,
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
static void *_dedicated_video_mem;
|
||||
|
||||
static const char *DedicatedVideoStart(const char * const *parm)
|
||||
{
|
||||
DEBUG(misc, 0) ("OpenTTD compiled without network support, exiting.");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void DedicatedFork(void) {}
|
||||
static void DedicatedVideoStop(void) { free(_dedicated_video_mem); }
|
||||
static void DedicatedVideoMakeDirty(int left, int top, int width, int height) {}
|
||||
static bool DedicatedVideoChangeRes(int w, int h) { return false; }
|
||||
static void DedicatedVideoFullScreen(bool fs) {}
|
||||
static int DedicatedVideoMainLoop(void) { return ML_QUIT; }
|
||||
|
||||
const HalVideoDriver _dedicated_video_driver = {
|
||||
DedicatedVideoStart,
|
||||
DedicatedVideoStop,
|
||||
DedicatedVideoMakeDirty,
|
||||
DedicatedVideoMainLoop,
|
||||
DedicatedVideoChangeRes,
|
||||
DedicatedVideoFullScreen,
|
||||
};
|
||||
|
||||
#endif /* ENABLE_NETWORK */
|
||||
@@ -0,0 +1,142 @@
|
||||
#include "stdafx.h"
|
||||
#include "ttd.h"
|
||||
#include "depot.h"
|
||||
#include "tile.h"
|
||||
#include "map.h"
|
||||
#include "table/strings.h"
|
||||
#include "saveload.h"
|
||||
#include "order.h"
|
||||
|
||||
enum {
|
||||
/* Max depots: 64000 (8 * 8000) */
|
||||
DEPOT_POOL_BLOCK_SIZE_BITS = 3, /* In bits, so (1 << 3) == 8 */
|
||||
DEPOT_POOL_MAX_BLOCKS = 8000,
|
||||
};
|
||||
|
||||
/**
|
||||
* Called if a new block is added to the depot-pool
|
||||
*/
|
||||
static void DepotPoolNewBlock(uint start_item)
|
||||
{
|
||||
Depot *depot;
|
||||
|
||||
FOR_ALL_DEPOTS_FROM(depot, start_item)
|
||||
depot->index = start_item++;
|
||||
}
|
||||
|
||||
/* Initialize the town-pool */
|
||||
MemoryPool _depot_pool = { "Depots", DEPOT_POOL_MAX_BLOCKS, DEPOT_POOL_BLOCK_SIZE_BITS, sizeof(Depot), &DepotPoolNewBlock, 0, 0, NULL };
|
||||
|
||||
|
||||
/**
|
||||
* Gets a depot from a tile
|
||||
*
|
||||
* @return Returns the depot if the tile had a depot, else it returns NULL
|
||||
*/
|
||||
Depot *GetDepotByTile(uint tile)
|
||||
{
|
||||
Depot *depot;
|
||||
|
||||
FOR_ALL_DEPOTS(depot) {
|
||||
if (depot->xy == tile)
|
||||
return depot;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate a new depot
|
||||
*/
|
||||
Depot *AllocateDepot(void)
|
||||
{
|
||||
Depot *depot;
|
||||
|
||||
FOR_ALL_DEPOTS(depot) {
|
||||
if (!IsValidDepot(depot)) {
|
||||
uint index = depot->index;
|
||||
|
||||
memset(depot, 0, sizeof(Depot));
|
||||
depot->index = index;
|
||||
|
||||
return depot;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if we can add a block to the pool */
|
||||
if (AddBlockToPool(&_depot_pool))
|
||||
return AllocateDepot();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a depot
|
||||
*/
|
||||
void DoDeleteDepot(uint tile)
|
||||
{
|
||||
Order order;
|
||||
Depot *depot;
|
||||
|
||||
/* Get the depot */
|
||||
depot = GetDepotByTile(tile);
|
||||
|
||||
/* Clear the tile */
|
||||
DoClearSquare(tile);
|
||||
|
||||
/* Clear the depot */
|
||||
depot->xy = 0;
|
||||
|
||||
/* Clear the depot from all order-lists */
|
||||
order.type = OT_GOTO_DEPOT;
|
||||
order.station = depot->index;
|
||||
DeleteDestinationFromVehicleOrder(order);
|
||||
|
||||
/* Delete the depot-window */
|
||||
DeleteWindowById(WC_VEHICLE_DEPOT, tile);
|
||||
}
|
||||
|
||||
void InitializeDepot(void)
|
||||
{
|
||||
CleanPool(&_depot_pool);
|
||||
AddBlockToPool(&_depot_pool);
|
||||
}
|
||||
|
||||
|
||||
static const byte _depot_desc[] = {
|
||||
SLE_CONDVAR(Depot, xy, SLE_FILE_U16 | SLE_VAR_U32, 0, 5),
|
||||
SLE_CONDVAR(Depot, xy, SLE_UINT32, 6, 255),
|
||||
SLE_VAR(Depot,town_index, SLE_UINT16),
|
||||
SLE_END()
|
||||
};
|
||||
|
||||
static void Save_DEPT(void)
|
||||
{
|
||||
Depot *depot;
|
||||
|
||||
FOR_ALL_DEPOTS(depot) {
|
||||
if (IsValidDepot(depot)) {
|
||||
SlSetArrayIndex(depot->index);
|
||||
SlObject(depot, _depot_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Load_DEPT(void)
|
||||
{
|
||||
int index;
|
||||
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
Depot *depot;
|
||||
|
||||
if (!AddBlockIfNeeded(&_depot_pool, index))
|
||||
error("Depots: failed loading savegame: too many depots");
|
||||
|
||||
depot = GetDepot(index);
|
||||
SlObject(depot, _depot_desc);
|
||||
}
|
||||
}
|
||||
|
||||
const ChunkHandler _depot_chunk_handlers[] = {
|
||||
{ 'DEPT', Save_DEPT, Load_DEPT, CH_ARRAY | CH_LAST},
|
||||
};
|
||||
@@ -0,0 +1,120 @@
|
||||
#ifndef DEPOT_H
|
||||
#define DEPOT_H
|
||||
|
||||
#include "pool.h"
|
||||
#include "tile.h"
|
||||
|
||||
struct Depot {
|
||||
TileIndex xy;
|
||||
uint16 town_index;
|
||||
uint16 index;
|
||||
};
|
||||
|
||||
extern MemoryPool _depot_pool;
|
||||
|
||||
/**
|
||||
* Get the pointer to the depot with index 'index'
|
||||
*/
|
||||
static inline Depot *GetDepot(uint index)
|
||||
{
|
||||
return (Depot*)GetItemFromPool(&_depot_pool, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current size of the DepotPool
|
||||
*/
|
||||
static inline uint16 GetDepotPoolSize(void)
|
||||
{
|
||||
return _depot_pool.total_items;
|
||||
}
|
||||
|
||||
static inline bool IsDepotIndex(uint index)
|
||||
{
|
||||
return index < GetDepotPoolSize();
|
||||
}
|
||||
|
||||
#define FOR_ALL_DEPOTS_FROM(d, start) for (d = GetDepot(start); d != NULL; d = (d->index + 1 < GetDepotPoolSize()) ? GetDepot(d->index + 1) : NULL)
|
||||
#define FOR_ALL_DEPOTS(d) FOR_ALL_DEPOTS_FROM(d, 0)
|
||||
|
||||
#define MIN_SERVINT_PERCENT 5
|
||||
#define MAX_SERVINT_PERCENT 90
|
||||
#define MIN_SERVINT_DAYS 30
|
||||
#define MAX_SERVINT_DAYS 800
|
||||
|
||||
/** Get the service interval domain.
|
||||
* Get the new proposed service interval for the vehicle is indeed, clamped
|
||||
* within the given bounds. @see MIN_SERVINT_PERCENT ,etc.
|
||||
* @param index proposed service interval
|
||||
*/
|
||||
static inline uint16 GetServiceIntervalClamped(uint index)
|
||||
{
|
||||
return (_patches.servint_ispercent) ? clamp(index, MIN_SERVINT_PERCENT, MAX_SERVINT_PERCENT) : clamp(index, MIN_SERVINT_DAYS, MAX_SERVINT_DAYS);
|
||||
}
|
||||
|
||||
VARDEF TileIndex _last_built_train_depot_tile;
|
||||
VARDEF TileIndex _last_built_road_depot_tile;
|
||||
VARDEF TileIndex _last_built_aircraft_depot_tile;
|
||||
VARDEF TileIndex _last_built_ship_depot_tile;
|
||||
|
||||
/**
|
||||
* Check if a depot really exists.
|
||||
*/
|
||||
static inline bool IsValidDepot(const Depot* depot)
|
||||
{
|
||||
return depot->xy != 0; /* XXX: Replace by INVALID_TILE someday */
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a tile is a depot of the given type.
|
||||
*/
|
||||
static inline bool IsTileDepotType(TileIndex tile, TransportType type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case TRANSPORT_RAIL:
|
||||
return IsTileType(tile, MP_RAILWAY) && (_map5[tile] & 0xFC) == 0xC0;
|
||||
break;
|
||||
case TRANSPORT_ROAD:
|
||||
return IsTileType(tile, MP_STREET) && (_map5[tile] & 0xF0) == 0x20;
|
||||
break;
|
||||
case TRANSPORT_WATER:
|
||||
return IsTileType(tile, MP_WATER) && (_map5[tile] & ~3) == 0x80;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the direction the exit of the depot on the given tile is facing.
|
||||
*/
|
||||
static inline uint GetDepotDirection(TileIndex tile, TransportType type)
|
||||
{
|
||||
assert(IsTileDepotType(tile, type));
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case TRANSPORT_RAIL:
|
||||
case TRANSPORT_ROAD:
|
||||
/* Rail and road store a diagonal direction in bits 0 and 1 */
|
||||
return _map5[tile] & 3;
|
||||
case TRANSPORT_WATER:
|
||||
/* Water is stubborn, it stores the directions in a different order. */
|
||||
switch (_map5[tile] & 3) {
|
||||
case 0: return 0;
|
||||
case 1: return 2;
|
||||
case 2: return 3;
|
||||
case 3: return 1;
|
||||
}
|
||||
default:
|
||||
return 0; /* Not reached */
|
||||
}
|
||||
}
|
||||
|
||||
Depot *GetDepotByTile(uint tile);
|
||||
void InitializeDepot(void);
|
||||
Depot *AllocateDepot(void);
|
||||
void DoDeleteDepot(uint tile);
|
||||
|
||||
#endif /* DEPOT_H */
|
||||
+153
-133
@@ -1,5 +1,8 @@
|
||||
#include "stdafx.h"
|
||||
#include "ttd.h"
|
||||
#include "table/strings.h"
|
||||
#include "map.h"
|
||||
#include "tile.h"
|
||||
#include "vehicle.h"
|
||||
#include "command.h"
|
||||
#include "news.h"
|
||||
@@ -9,26 +12,33 @@
|
||||
#include "industry.h"
|
||||
#include "player.h"
|
||||
#include "airport_movement.h"
|
||||
#include "sound.h"
|
||||
|
||||
static void DisasterClearSquare(uint tile)
|
||||
static void DisasterClearSquare(TileIndex tile)
|
||||
{
|
||||
int type;
|
||||
|
||||
if (!EnsureNoVehicle(tile))
|
||||
return;
|
||||
|
||||
type = _map_type_and_height[tile] >> 4;
|
||||
switch (GetTileType(tile)) {
|
||||
case MP_RAILWAY:
|
||||
if (IS_HUMAN_PLAYER(_map_owner[tile])) DoClearSquare(tile);
|
||||
break;
|
||||
|
||||
if (type == MP_RAILWAY) {
|
||||
if (IS_HUMAN_PLAYER(_map_owner[tile]))
|
||||
case MP_HOUSE: {
|
||||
byte p = _current_player;
|
||||
_current_player = OWNER_NONE;
|
||||
DoCommandByTile(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
|
||||
_current_player = p;
|
||||
break;
|
||||
}
|
||||
|
||||
case MP_TREES:
|
||||
case MP_CLEAR:
|
||||
DoClearSquare(tile);
|
||||
} else if (type == MP_HOUSE) {
|
||||
byte p = _current_player;
|
||||
_current_player = OWNER_NONE;
|
||||
DoCommandByTile(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
|
||||
_current_player = p;
|
||||
} else if (type == MP_TREES || type == MP_CLEAR) {
|
||||
DoClearSquare(tile);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +87,9 @@ static void InitializeDisasterVehicle(Vehicle *v, int x, int y, byte z, byte dir
|
||||
v->owner = OWNER_NONE;
|
||||
v->vehstatus = VS_UNCLICKABLE;
|
||||
v->u.disaster.image_override = 0;
|
||||
v->next_order = 0;
|
||||
v->current_order.type = OT_NOTHING;
|
||||
v->current_order.flags = 0;
|
||||
v->current_order.station = 0;
|
||||
|
||||
DisasterVehicleUpdateImage(v);
|
||||
VehiclePositionChanged(v);
|
||||
@@ -139,7 +151,7 @@ static void DisasterTick_Zeppeliner(Vehicle *v)
|
||||
|
||||
++v->tick_counter;
|
||||
|
||||
if (v->next_order < 2) {
|
||||
if (v->current_order.station < 2) {
|
||||
if (v->tick_counter&1)
|
||||
return;
|
||||
|
||||
@@ -147,48 +159,50 @@ static void DisasterTick_Zeppeliner(Vehicle *v)
|
||||
|
||||
SetDisasterVehiclePos(v, gp.x, gp.y, v->z_pos);
|
||||
|
||||
if (v->next_order == 1) {
|
||||
if (v->current_order.station == 1) {
|
||||
if (++v->age == 38) {
|
||||
v->next_order = 2;
|
||||
v->current_order.station = 2;
|
||||
v->age = 0;
|
||||
}
|
||||
|
||||
if ((v->tick_counter&7)==0) {
|
||||
CreateEffectVehicleRel(v, 0, -17, 2, EV_SMOKE_3);
|
||||
CreateEffectVehicleRel(v, 0, -17, 2, EV_SMOKE);
|
||||
}
|
||||
} else if (v->next_order == 0) {
|
||||
} else if (v->current_order.station == 0) {
|
||||
tile = v->tile; /**/
|
||||
|
||||
if (IS_TILETYPE(tile, MP_STATION) &&
|
||||
if (IsValidTile(tile) &&
|
||||
IsTileType(tile, MP_STATION) &&
|
||||
IS_BYTE_INSIDE(_map5[tile], 8, 0x43) &&
|
||||
IS_HUMAN_PLAYER(_map_owner[tile])) {
|
||||
|
||||
v->next_order = 1;
|
||||
v->current_order.station = 1;
|
||||
v->age = 0;
|
||||
|
||||
SET_DPARAM16(0, _map2[tile]);
|
||||
SetDParam(0, _map2[tile]);
|
||||
AddNewsItem(STR_B000_ZEPPELIN_DISASTER_AT,
|
||||
NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ACCIDENT, 0),
|
||||
v->index,
|
||||
0);
|
||||
}
|
||||
}
|
||||
if (v->y_pos >= (TILES_Y+9) * 16 - 1)
|
||||
if (v->y_pos >= ((int)MapSizeY() + 9) * 16 - 1)
|
||||
DeleteDisasterVeh(v);
|
||||
return;
|
||||
}
|
||||
|
||||
if (v->next_order > 2) {
|
||||
if (v->current_order.station > 2) {
|
||||
if (++v->age <= 13320)
|
||||
return;
|
||||
|
||||
tile = v->tile; /**/
|
||||
|
||||
if (IS_TILETYPE(tile, MP_STATION) &&
|
||||
if (IsValidTile(tile) &&
|
||||
IsTileType(tile, MP_STATION) &&
|
||||
IS_BYTE_INSIDE(_map5[tile], 8, 0x43) &&
|
||||
IS_HUMAN_PLAYER(_map_owner[tile])) {
|
||||
|
||||
st = DEREF_STATION(_map2[tile]);
|
||||
st = GetStation(_map2[tile]);
|
||||
CLRBITS(st->airport_flags, RUNWAY_IN_block);
|
||||
}
|
||||
|
||||
@@ -205,8 +219,8 @@ static void DisasterTick_Zeppeliner(Vehicle *v)
|
||||
SetDisasterVehiclePos(v, x, y, z);
|
||||
|
||||
if (++v->age == 1) {
|
||||
CreateEffectVehicleRel(v, 0, 7, 8, EV_CRASHED_SMOKE);
|
||||
SndPlayVehicleFx(0x10, v);
|
||||
CreateEffectVehicleRel(v, 0, 7, 8, EV_EXPLOSION_LARGE);
|
||||
SndPlayVehicleFx(SND_12_EXPLOSION, v);
|
||||
v->u.disaster.image_override = 0xF42;
|
||||
} else if (v->age == 70) {
|
||||
v->u.disaster.image_override = 0xF43;
|
||||
@@ -218,19 +232,20 @@ static void DisasterTick_Zeppeliner(Vehicle *v)
|
||||
-7 + (r&0xF),
|
||||
-7 + (r>>4&0xF),
|
||||
5 + (r>>8&0x7),
|
||||
EV_DEMOLISH);
|
||||
EV_EXPLOSION_SMALL);
|
||||
}
|
||||
} else if (v->age == 350) {
|
||||
v->next_order = 3;
|
||||
v->current_order.station = 3;
|
||||
v->age = 0;
|
||||
}
|
||||
|
||||
tile = v->tile;/**/
|
||||
if (IS_TILETYPE(tile, MP_STATION) &&
|
||||
if (IsValidTile(tile) &&
|
||||
IsTileType(tile, MP_STATION) &&
|
||||
IS_BYTE_INSIDE(_map5[tile], 8, 0x43) &&
|
||||
IS_HUMAN_PLAYER(_map_owner[tile])) {
|
||||
|
||||
st = DEREF_STATION(_map2[tile]);
|
||||
st = GetStation(_map2[tile]);
|
||||
SETBITS(st->airport_flags, RUNWAY_IN_block);
|
||||
}
|
||||
}
|
||||
@@ -246,10 +261,10 @@ static void DisasterTick_UFO(Vehicle *v)
|
||||
|
||||
v->u.disaster.image_override = (++v->tick_counter & 8) ? 0xF45 : 0xF44;
|
||||
|
||||
if (v->next_order == 0) {
|
||||
if (v->current_order.station == 0) {
|
||||
// fly around randomly
|
||||
int x = GET_TILE_X(v->dest_tile)*16;
|
||||
int y = GET_TILE_Y(v->dest_tile)*16;
|
||||
int x = TileX(v->dest_tile) * 16;
|
||||
int y = TileY(v->dest_tile) * 16;
|
||||
if (abs(x - v->x_pos) + abs(y - v->y_pos) >= 16) {
|
||||
v->direction = GetDirectionTowards(v, x, y);
|
||||
GetNewVehiclePos(v, &gp);
|
||||
@@ -260,7 +275,7 @@ static void DisasterTick_UFO(Vehicle *v)
|
||||
v->dest_tile = TILE_MASK(Random());
|
||||
return;
|
||||
}
|
||||
v->next_order = 1;
|
||||
v->current_order.station = 1;
|
||||
|
||||
FOR_ALL_VEHICLES(u) {
|
||||
if (u->type == VEH_Road && IS_HUMAN_PLAYER(u->owner)) {
|
||||
@@ -273,7 +288,7 @@ static void DisasterTick_UFO(Vehicle *v)
|
||||
DeleteDisasterVeh(v);
|
||||
} else {
|
||||
// target a vehicle
|
||||
u = &_vehicles[v->dest_tile];
|
||||
u = GetVehicle(v->dest_tile);
|
||||
if (u->type != VEH_Road) {
|
||||
DeleteDisasterVeh(v);
|
||||
return;
|
||||
@@ -308,8 +323,8 @@ static void DisasterTick_UFO(Vehicle *v)
|
||||
|
||||
// destroy?
|
||||
if (v->age > 50) {
|
||||
CreateEffectVehicleRel(v, 0, 7, 8, EV_CRASHED_SMOKE);
|
||||
SndPlayVehicleFx(0x10, v);
|
||||
CreateEffectVehicleRel(v, 0, 7, 8, EV_EXPLOSION_LARGE);
|
||||
SndPlayVehicleFx(SND_12_EXPLOSION, v);
|
||||
DeleteDisasterVeh(v);
|
||||
}
|
||||
}
|
||||
@@ -318,10 +333,9 @@ static void DisasterTick_UFO(Vehicle *v)
|
||||
static void DestructIndustry(Industry *i)
|
||||
{
|
||||
uint tile;
|
||||
byte index = i - _industries;
|
||||
|
||||
for(tile=0; tile != TILES_X*TILES_Y; tile++) {
|
||||
if (IS_TILETYPE(tile, MP_INDUSTRY) && _map2[tile] == index) {
|
||||
for(tile=0; tile != MapSize(); tile++) {
|
||||
if (IsTileType(tile, MP_INDUSTRY) && _map2[tile] == i->index) {
|
||||
_map_owner[tile] = 0;
|
||||
MarkTileDirtyByTile(tile);
|
||||
}
|
||||
@@ -334,7 +348,8 @@ static void DisasterTick_2(Vehicle *v)
|
||||
GetNewVehiclePosResult gp;
|
||||
|
||||
v->tick_counter++;
|
||||
v->u.disaster.image_override = (v->next_order == 1 && v->tick_counter&4) ? 0xF4F : 0;
|
||||
v->u.disaster.image_override =
|
||||
(v->current_order.station == 1 && v->tick_counter&4) ? 0xF4F : 0;
|
||||
|
||||
GetNewVehiclePos(v, &gp);
|
||||
SetDisasterVehiclePos(v, gp.x, gp.y, v->z_pos);
|
||||
@@ -344,37 +359,37 @@ static void DisasterTick_2(Vehicle *v)
|
||||
return;
|
||||
}
|
||||
|
||||
if (v->next_order == 2) {
|
||||
if (v->current_order.station == 2) {
|
||||
if (!(v->tick_counter&3)) {
|
||||
Industry *i = DEREF_INDUSTRY(v->dest_tile);
|
||||
int x = GET_TILE_X(i->xy)*16;
|
||||
int y = GET_TILE_Y(i->xy)*16;
|
||||
Industry *i = GetIndustry(v->dest_tile);
|
||||
int x = TileX(i->xy) * 16;
|
||||
int y = TileY(i->xy) * 16;
|
||||
uint32 r = Random();
|
||||
|
||||
CreateEffectVehicleAbove(
|
||||
x + (r & 0x3F),
|
||||
y + (r >> 6 & 0x3F),
|
||||
(r >> 12 & 0xF),
|
||||
EV_DEMOLISH);
|
||||
EV_EXPLOSION_SMALL);
|
||||
|
||||
if (++v->age >= 55)
|
||||
v->next_order = 3;
|
||||
v->current_order.station = 3;
|
||||
}
|
||||
} else if (v->next_order == 1) {
|
||||
} else if (v->current_order.station == 1) {
|
||||
if (++v->age == 112) {
|
||||
Industry *i;
|
||||
|
||||
v->next_order = 2;
|
||||
v->current_order.station = 2;
|
||||
v->age = 0;
|
||||
|
||||
i = DEREF_INDUSTRY(v->dest_tile);
|
||||
i = GetIndustry(v->dest_tile);
|
||||
DestructIndustry(i);
|
||||
|
||||
SET_DPARAM16(0, i->town->index);
|
||||
SetDParam(0, i->town->index);
|
||||
AddNewsItem(STR_B002_OIL_REFINERY_EXPLOSION, NEWS_FLAGS(NM_THIN,NF_VIEWPORT|NF_TILE,NT_ACCIDENT,0), i->xy, 0);
|
||||
SndPlayTileFx(0x10, i->xy);
|
||||
SndPlayTileFx(SND_12_EXPLOSION, i->xy);
|
||||
}
|
||||
} else if (v->next_order == 0) {
|
||||
} else if (v->current_order.station == 0) {
|
||||
int x,y;
|
||||
uint tile;
|
||||
int ind;
|
||||
@@ -382,17 +397,17 @@ static void DisasterTick_2(Vehicle *v)
|
||||
x = v->x_pos - 15*16;
|
||||
y = v->y_pos;
|
||||
|
||||
if ( (uint)x > (TILES_X-1) * 16-1)
|
||||
if ( (uint)x > MapMaxX() * 16-1)
|
||||
return;
|
||||
|
||||
tile = TILE_FROM_XY(x,y);
|
||||
if (!IS_TILETYPE(tile, MP_INDUSTRY))
|
||||
if (!IsTileType(tile, MP_INDUSTRY))
|
||||
return;
|
||||
|
||||
v->dest_tile = ind = _map2[tile];
|
||||
|
||||
if (DEREF_INDUSTRY(ind)->type == IT_OIL_REFINERY) {
|
||||
v->next_order = 1;
|
||||
if (GetIndustry(ind)->type == IT_OIL_REFINERY) {
|
||||
v->current_order.station = 1;
|
||||
v->age = 0;
|
||||
}
|
||||
}
|
||||
@@ -404,47 +419,48 @@ static void DisasterTick_3(Vehicle *v)
|
||||
GetNewVehiclePosResult gp;
|
||||
|
||||
v->tick_counter++;
|
||||
v->u.disaster.image_override = (v->next_order == 1 && v->tick_counter&4) ? 0xF53 : 0;
|
||||
v->u.disaster.image_override =
|
||||
(v->current_order.station == 1 && v->tick_counter&4) ? 0xF53 : 0;
|
||||
|
||||
GetNewVehiclePos(v, &gp);
|
||||
SetDisasterVehiclePos(v, gp.x, gp.y, v->z_pos);
|
||||
|
||||
if (gp.x > TILES_X * 16 + 9*16 - 1) {
|
||||
if (gp.x > (int)MapSizeX() * 16 + 9*16 - 1) {
|
||||
DeleteDisasterVeh(v);
|
||||
return;
|
||||
}
|
||||
|
||||
if (v->next_order == 2) {
|
||||
if (v->current_order.station == 2) {
|
||||
if (!(v->tick_counter&3)) {
|
||||
Industry *i = DEREF_INDUSTRY(v->dest_tile);
|
||||
int x = GET_TILE_X(i->xy)*16;
|
||||
int y = GET_TILE_Y(i->xy)*16;
|
||||
Industry *i = GetIndustry(v->dest_tile);
|
||||
int x = TileX(i->xy) * 16;
|
||||
int y = TileY(i->xy) * 16;
|
||||
uint32 r = Random();
|
||||
|
||||
CreateEffectVehicleAbove(
|
||||
x + (r & 0x3F),
|
||||
y + (r >> 6 & 0x3F),
|
||||
(r >> 12 & 0xF),
|
||||
EV_DEMOLISH);
|
||||
EV_EXPLOSION_SMALL);
|
||||
|
||||
if (++v->age >= 55)
|
||||
v->next_order = 3;
|
||||
v->current_order.station = 3;
|
||||
}
|
||||
} else if (v->next_order == 1) {
|
||||
} else if (v->current_order.station == 1) {
|
||||
if (++v->age == 112) {
|
||||
Industry *i;
|
||||
|
||||
v->next_order = 2;
|
||||
v->current_order.station = 2;
|
||||
v->age = 0;
|
||||
|
||||
i = DEREF_INDUSTRY(v->dest_tile);
|
||||
i = GetIndustry(v->dest_tile);
|
||||
DestructIndustry(i);
|
||||
|
||||
SET_DPARAM16(0, i->town->index);
|
||||
SetDParam(0, i->town->index);
|
||||
AddNewsItem(STR_B003_FACTORY_DESTROYED_IN_SUSPICIOUS, NEWS_FLAGS(NM_THIN,NF_VIEWPORT|NF_TILE,NT_ACCIDENT,0), i->xy, 0);
|
||||
SndPlayTileFx(0x10, i->xy);
|
||||
SndPlayTileFx(SND_12_EXPLOSION, i->xy);
|
||||
}
|
||||
} else if (v->next_order == 0) {
|
||||
} else if (v->current_order.station == 0) {
|
||||
int x,y;
|
||||
uint tile;
|
||||
int ind;
|
||||
@@ -452,17 +468,17 @@ static void DisasterTick_3(Vehicle *v)
|
||||
x = v->x_pos - 15*16;
|
||||
y = v->y_pos;
|
||||
|
||||
if ( (uint)x > (TILES_X-1) * 16-1)
|
||||
if ( (uint)x > MapMaxX() * 16-1)
|
||||
return;
|
||||
|
||||
tile = TILE_FROM_XY(x,y);
|
||||
if (!IS_TILETYPE(tile, MP_INDUSTRY))
|
||||
if (!IsTileType(tile, MP_INDUSTRY))
|
||||
return;
|
||||
|
||||
v->dest_tile = ind = _map2[tile];
|
||||
|
||||
if (DEREF_INDUSTRY(ind)->type == IT_FACTORY) {
|
||||
v->next_order = 1;
|
||||
if (GetIndustry(ind)->type == IT_FACTORY) {
|
||||
v->current_order.station = 1;
|
||||
v->age = 0;
|
||||
}
|
||||
}
|
||||
@@ -494,9 +510,9 @@ static void DisasterTick_4(Vehicle *v)
|
||||
|
||||
v->tick_counter++;
|
||||
|
||||
if (v->next_order == 1) {
|
||||
int x = GET_TILE_X(v->dest_tile)*16 + 8;
|
||||
int y = GET_TILE_Y(v->dest_tile)*16 + 8;
|
||||
if (v->current_order.station == 1) {
|
||||
int x = TileX(v->dest_tile) * 16 + 8;
|
||||
int y = TileY(v->dest_tile) * 16 + 8;
|
||||
if (abs(v->x_pos - x) + abs(v->y_pos - y) >= 8) {
|
||||
v->direction = GetDirectionTowards(v, x, y);
|
||||
|
||||
@@ -511,7 +527,7 @@ static void DisasterTick_4(Vehicle *v)
|
||||
return;
|
||||
}
|
||||
|
||||
v->next_order = 2;
|
||||
v->current_order.station = 2;
|
||||
|
||||
FOR_ALL_VEHICLES(u) {
|
||||
if (u->type == VEH_Train || u->type == VEH_Road) {
|
||||
@@ -523,7 +539,7 @@ static void DisasterTick_4(Vehicle *v)
|
||||
}
|
||||
|
||||
t = ClosestTownFromTile(v->dest_tile, (uint)-1);
|
||||
SET_DPARAM16(0, t->index);
|
||||
SetDParam(0, t->index);
|
||||
AddNewsItem(STR_B004_UFO_LANDS_NEAR,
|
||||
NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_TILE, NT_ACCIDENT, 0),
|
||||
v->tile,
|
||||
@@ -545,10 +561,10 @@ static void DisasterTick_4(Vehicle *v)
|
||||
u->next = w;
|
||||
InitializeDisasterVehicle(w, -6*16, v->y_pos, 0, 5, 12);
|
||||
w->vehstatus |= VS_DISASTER;
|
||||
} else if (v->next_order < 1) {
|
||||
} else if (v->current_order.station < 1) {
|
||||
|
||||
int x = GET_TILE_X(v->dest_tile)*16;
|
||||
int y = GET_TILE_Y(v->dest_tile)*16;
|
||||
int x = TileX(v->dest_tile) * 16;
|
||||
int y = TileY(v->dest_tile) * 16;
|
||||
if (abs(x - v->x_pos) + abs(y - v->y_pos) >= 16) {
|
||||
v->direction = GetDirectionTowards(v, x, y);
|
||||
GetNewVehiclePos(v, &gp);
|
||||
@@ -560,11 +576,11 @@ static void DisasterTick_4(Vehicle *v)
|
||||
v->dest_tile = TILE_MASK(Random());
|
||||
return;
|
||||
}
|
||||
v->next_order = 1;
|
||||
v->current_order.station = 1;
|
||||
|
||||
tile_org = tile = TILE_MASK(Random());
|
||||
do {
|
||||
if (IS_TILETYPE(tile, MP_RAILWAY) &&
|
||||
if (IsTileType(tile, MP_RAILWAY) &&
|
||||
(_map5[tile]&~3)!=0xC0 && IS_HUMAN_PLAYER(_map_owner[tile]))
|
||||
break;
|
||||
tile = TILE_MASK(tile+1);
|
||||
@@ -587,19 +603,19 @@ static void DisasterTick_4b(Vehicle *v)
|
||||
GetNewVehiclePos(v, &gp);
|
||||
SetDisasterVehiclePos(v, gp.x, gp.y, v->z_pos);
|
||||
|
||||
if (gp.x > TILES_X * 16 + 9*16 - 1) {
|
||||
if (gp.x > (int)MapSizeX() * 16 + 9*16 - 1) {
|
||||
DeleteDisasterVeh(v);
|
||||
return;
|
||||
}
|
||||
|
||||
if (v->next_order == 0) {
|
||||
u = &_vehicles[v->u.disaster.unk2];
|
||||
if (v->current_order.station == 0) {
|
||||
u = GetVehicle(v->u.disaster.unk2);
|
||||
if (abs(v->x_pos - u->x_pos) > 16)
|
||||
return;
|
||||
v->next_order = 1;
|
||||
v->current_order.station = 1;
|
||||
|
||||
CreateEffectVehicleRel(u, 0, 7, 8, EV_CRASHED_SMOKE);
|
||||
SndPlayVehicleFx(0x10, u);
|
||||
CreateEffectVehicleRel(u, 0, 7, 8, EV_EXPLOSION_LARGE);
|
||||
SndPlayVehicleFx(SND_12_EXPLOSION, u);
|
||||
|
||||
DeleteDisasterVeh(u);
|
||||
|
||||
@@ -609,7 +625,7 @@ static void DisasterTick_4b(Vehicle *v)
|
||||
v->x_pos-32+(r&0x3F),
|
||||
v->y_pos-32+(r>>5&0x3F),
|
||||
0,
|
||||
EV_DEMOLISH);
|
||||
EV_EXPLOSION_SMALL);
|
||||
}
|
||||
|
||||
BEGIN_TILE_LOOP(tile,6,6,v->tile - TILE_XY(3,3))
|
||||
@@ -639,7 +655,7 @@ static void DisasterTick_5_and_6(Vehicle *v)
|
||||
if (!(v->tick_counter&1))
|
||||
return;
|
||||
|
||||
tile = v->tile + _tileoffs_by_dir[v->direction >> 1];
|
||||
tile = v->tile + TileOffsByDir(v->direction >> 1);
|
||||
if (IsValidTile(tile) &&
|
||||
(r=GetTileTrackStatus(tile,TRANSPORT_WATER),(byte)(r+(r >> 8)) == 0x3F) &&
|
||||
!CHANCE16(1,90)) {
|
||||
@@ -682,10 +698,10 @@ void OnNewDay_DisasterVehicle(Vehicle *v)
|
||||
// not used
|
||||
}
|
||||
|
||||
typedef void DisasterInitProc();
|
||||
typedef void DisasterInitProc(void);
|
||||
|
||||
// Zeppeliner which crashes on a small airport
|
||||
static void Disaster0_Init()
|
||||
static void Disaster0_Init(void)
|
||||
{
|
||||
Vehicle *v = ForceAllocateSpecialVehicle(), *u;
|
||||
Station *st;
|
||||
@@ -694,16 +710,15 @@ static void Disaster0_Init()
|
||||
if (v == NULL)
|
||||
return;
|
||||
|
||||
for(st=_stations;;) {
|
||||
/* Pick a random place, unless we find
|
||||
a small airport */
|
||||
x = TileX(Random()) * 16 + 8;
|
||||
|
||||
FOR_ALL_STATIONS(st) {
|
||||
if (st->xy && st->airport_tile != 0 &&
|
||||
st->airport_type <= 1 &&
|
||||
IS_HUMAN_PLAYER(st->owner)) {
|
||||
x = (GET_TILE_X(st->xy) + 2) * 16;
|
||||
break;
|
||||
}
|
||||
|
||||
if (++st == endof(_stations)) {
|
||||
x = (GET_TILE_X(Random())) * 16 + 8;
|
||||
x = (TileX(st->xy) + 2) * 16;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -714,12 +729,12 @@ static void Disaster0_Init()
|
||||
u = ForceAllocateSpecialVehicle();
|
||||
if (u != NULL) {
|
||||
v->next = u;
|
||||
InitializeDisasterVehicle(u,x,0,0,3,1);
|
||||
InitializeDisasterVehicle(u, x, 0, 0, 3, 1);
|
||||
u->vehstatus |= VS_DISASTER;
|
||||
}
|
||||
}
|
||||
|
||||
static void Disaster1_Init()
|
||||
static void Disaster1_Init(void)
|
||||
{
|
||||
Vehicle *v = ForceAllocateSpecialVehicle(), *u;
|
||||
int x;
|
||||
@@ -727,10 +742,10 @@ static void Disaster1_Init()
|
||||
if (v == NULL)
|
||||
return;
|
||||
|
||||
x = (GET_TILE_X(Random())) * 16 + 8;
|
||||
x = TileX(Random()) * 16 + 8;
|
||||
|
||||
InitializeDisasterVehicle(v, x, 0, 135, 3, 2);
|
||||
v->dest_tile = TILE_XY(TILES_X/2,TILES_Y/2);
|
||||
v->dest_tile = TILE_XY(MapSizeX() / 2, MapSizeY() / 2);
|
||||
v->age = 0;
|
||||
|
||||
// Allocate shadow too?
|
||||
@@ -742,13 +757,15 @@ static void Disaster1_Init()
|
||||
}
|
||||
}
|
||||
|
||||
static void Disaster2_Init()
|
||||
static void Disaster2_Init(void)
|
||||
{
|
||||
Industry *i, *found;
|
||||
Vehicle *v,*u;
|
||||
int x,y;
|
||||
|
||||
for(found=NULL,i=_industries; i != endof(_industries); i++) {
|
||||
found = NULL;
|
||||
|
||||
FOR_ALL_INDUSTRIES(i) {
|
||||
if (i->xy != 0 &&
|
||||
i->type == IT_OIL_REFINERY &&
|
||||
(found==NULL || CHANCE16(1,2))) {
|
||||
@@ -763,8 +780,8 @@ static void Disaster2_Init()
|
||||
if (v == NULL)
|
||||
return;
|
||||
|
||||
x = (TILES_X+9) * 16 - 1;
|
||||
y = GET_TILE_Y(found->xy)*16 + 37;
|
||||
x = (MapSizeX() + 9) * 16 - 1;
|
||||
y = TileY(found->xy) * 16 + 37;
|
||||
|
||||
InitializeDisasterVehicle(v,x,y, 135,1,4);
|
||||
|
||||
@@ -776,13 +793,15 @@ static void Disaster2_Init()
|
||||
}
|
||||
}
|
||||
|
||||
static void Disaster3_Init()
|
||||
static void Disaster3_Init(void)
|
||||
{
|
||||
Industry *i, *found;
|
||||
Vehicle *v,*u,*w;
|
||||
int x,y;
|
||||
|
||||
for(found=NULL,i=_industries; i != endof(_industries); i++) {
|
||||
found = NULL;
|
||||
|
||||
FOR_ALL_INDUSTRIES(i) {
|
||||
if (i->xy != 0 &&
|
||||
i->type == IT_FACTORY &&
|
||||
(found==NULL || CHANCE16(1,2))) {
|
||||
@@ -798,7 +817,7 @@ static void Disaster3_Init()
|
||||
return;
|
||||
|
||||
x = -16 * 16;
|
||||
y = GET_TILE_Y(found->xy)*16 + 37;
|
||||
y = TileY(found->xy) * 16 + 37;
|
||||
|
||||
InitializeDisasterVehicle(v,x,y, 135,5,6);
|
||||
|
||||
@@ -816,7 +835,7 @@ static void Disaster3_Init()
|
||||
}
|
||||
}
|
||||
|
||||
static void Disaster4_Init()
|
||||
static void Disaster4_Init(void)
|
||||
{
|
||||
Vehicle *v = ForceAllocateSpecialVehicle(), *u;
|
||||
int x,y;
|
||||
@@ -824,11 +843,11 @@ static void Disaster4_Init()
|
||||
if (v == NULL)
|
||||
return;
|
||||
|
||||
x = (GET_TILE_X(Random())) * 16 + 8;
|
||||
x = TileX(Random()) * 16 + 8;
|
||||
|
||||
y = (TILES_X-1)*16-1;
|
||||
y = MapMaxX() * 16 - 1;
|
||||
InitializeDisasterVehicle(v, x, y, 135, 7, 9);
|
||||
v->dest_tile = TILE_XY(TILES_X/2,TILES_Y/2);
|
||||
v->dest_tile = TILE_XY(MapSizeX() / 2, MapSizeY() / 2);
|
||||
v->age = 0;
|
||||
|
||||
// Allocate shadow too?
|
||||
@@ -841,7 +860,7 @@ static void Disaster4_Init()
|
||||
}
|
||||
|
||||
// Submarine type 1
|
||||
static void Disaster5_Init()
|
||||
static void Disaster5_Init(void)
|
||||
{
|
||||
Vehicle *v = ForceAllocateSpecialVehicle();
|
||||
int x,y;
|
||||
@@ -852,17 +871,17 @@ static void Disaster5_Init()
|
||||
return;
|
||||
|
||||
r = Random();
|
||||
x = (GET_TILE_X(r)) * 16 + 8;
|
||||
x = TileX(r) * 16 + 8;
|
||||
|
||||
y = 8;
|
||||
dir = 3;
|
||||
if (r & 0x80000000) { y = (TILES_X-1) * 16 - 8 - 1; dir = 7; }
|
||||
if (r & 0x80000000) { y = MapMaxX() * 16 - 8 - 1; dir = 7; }
|
||||
InitializeDisasterVehicle(v, x, y, 0, dir,13);
|
||||
v->age = 0;
|
||||
}
|
||||
|
||||
// Submarine type 2
|
||||
static void Disaster6_Init()
|
||||
static void Disaster6_Init(void)
|
||||
{
|
||||
Vehicle *v = ForceAllocateSpecialVehicle();
|
||||
int x,y;
|
||||
@@ -873,32 +892,32 @@ static void Disaster6_Init()
|
||||
return;
|
||||
|
||||
r = Random();
|
||||
x = (GET_TILE_X(r)) * 16 + 8;
|
||||
x = TileX(r) * 16 + 8;
|
||||
|
||||
y = 8;
|
||||
dir = 3;
|
||||
if (r & 0x80000000) { y = (TILES_X-1) * 16 - 8 - 1; dir = 7; }
|
||||
if (r & 0x80000000) { y = MapMaxX() * 16 - 8 - 1; dir = 7; }
|
||||
InitializeDisasterVehicle(v, x, y, 0, dir,14);
|
||||
v->age = 0;
|
||||
}
|
||||
|
||||
static void Disaster7_Init()
|
||||
static void Disaster7_Init(void)
|
||||
{
|
||||
Industry *i;
|
||||
int maxloop = 15;
|
||||
int index = Random() & 0xF;
|
||||
|
||||
do {
|
||||
for(i=_industries; i != endof(_industries); i++) {
|
||||
FOR_ALL_INDUSTRIES(i) {
|
||||
if (i->xy != 0 && i->type == IT_COAL_MINE && --index < 0) {
|
||||
|
||||
SET_DPARAM16(0, i->town->index);
|
||||
SetDParam(0, i->town->index);
|
||||
AddNewsItem(STR_B005_COAL_MINE_SUBSIDENCE_LEAVES,
|
||||
NEWS_FLAGS(NM_THIN,NF_VIEWPORT|NF_TILE,NT_ACCIDENT,0), i->xy + TILE_XY(1,1), 0);
|
||||
|
||||
{
|
||||
uint tile = i->xy;
|
||||
int step = _tileoffs_by_dir[Random() & 3];
|
||||
TileIndexDiff step = TileOffsByDir(Random() & 3);
|
||||
int count = 30;
|
||||
do {
|
||||
DisasterClearSquare(tile);
|
||||
@@ -939,7 +958,7 @@ static const DisasterYears _dis_years[8] = {
|
||||
};
|
||||
|
||||
|
||||
void DoDisaster()
|
||||
static void DoDisaster(void)
|
||||
{
|
||||
byte buf[8];
|
||||
byte year = _cur_year;
|
||||
@@ -958,12 +977,12 @@ void DoDisaster()
|
||||
}
|
||||
|
||||
|
||||
static void ResetDisasterDelay()
|
||||
static void ResetDisasterDelay(void)
|
||||
{
|
||||
_disaster_delay = (int)(Random() & 0x1FF) + 730;
|
||||
}
|
||||
|
||||
void DisasterDailyLoop()
|
||||
void DisasterDailyLoop(void)
|
||||
{
|
||||
if (--_disaster_delay != 0)
|
||||
return;
|
||||
@@ -974,7 +993,8 @@ void DisasterDailyLoop()
|
||||
DoDisaster();
|
||||
}
|
||||
|
||||
void StartupDisasters() {
|
||||
void StartupDisasters(void)
|
||||
{
|
||||
ResetDisasterDelay();
|
||||
}
|
||||
|
||||
|
||||
+128
-92
@@ -1,28 +1,32 @@
|
||||
#include "stdafx.h"
|
||||
#include "ttd.h"
|
||||
|
||||
#include "table/sprites.h"
|
||||
#include "table/strings.h"
|
||||
#include "map.h"
|
||||
#include "window.h"
|
||||
#include "station.h"
|
||||
#include "gui.h"
|
||||
#include "viewport.h"
|
||||
#include "gfx.h"
|
||||
#include "sound.h"
|
||||
#include "command.h"
|
||||
|
||||
static void ShowBuildDockStationPicker();
|
||||
static void ShowBuildDocksDepotPicker();
|
||||
static void ShowBuildDockStationPicker(void);
|
||||
static void ShowBuildDocksDepotPicker(void);
|
||||
|
||||
static byte _ship_depot_direction;
|
||||
|
||||
static void CcBuildDocks(bool success, uint tile, uint32 p1, uint32 p2)
|
||||
void CcBuildDocks(bool success, uint tile, uint32 p1, uint32 p2)
|
||||
{
|
||||
if (success) {
|
||||
SndPlayTileFx(0, tile);
|
||||
SndPlayTileFx(SND_02_SPLAT, tile);
|
||||
ResetObjectToPlace();
|
||||
}
|
||||
}
|
||||
|
||||
static void CcBuildCanal(bool success, uint tile, uint32 p1, uint32 p2)
|
||||
void CcBuildCanal(bool success, uint tile, uint32 p1, uint32 p2)
|
||||
{
|
||||
if (success) { SndPlayTileFx(0, tile); }
|
||||
if (success) SndPlayTileFx(SND_02_SPLAT, tile);
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +47,7 @@ static void PlaceDocks_Buoy(uint tile)
|
||||
|
||||
static void PlaceDocks_DemolishArea(uint tile)
|
||||
{
|
||||
VpStartPlaceSizing(tile, VPM_X_AND_Y);
|
||||
VpStartPlaceSizing(tile, VPM_X_AND_Y | GUI_PlaceProc_DemolishArea);
|
||||
}
|
||||
|
||||
static void PlaceDocks_BuildCanal(uint tile)
|
||||
@@ -57,63 +61,52 @@ static void PlaceDocks_BuildLock(uint tile)
|
||||
}
|
||||
|
||||
|
||||
static void BuildDocksClick_Dock(Window *w)
|
||||
{
|
||||
|
||||
if (HandlePlacePushButton(w, 2, 0xE54, 3, PlaceDocks_Dock)) ShowBuildDockStationPicker();
|
||||
}
|
||||
|
||||
static void BuildDocksClick_Depot(Window *w)
|
||||
{
|
||||
if (HandlePlacePushButton(w, 3, 0x2D1, 1, PlaceDocks_Depot)) ShowBuildDocksDepotPicker();
|
||||
}
|
||||
|
||||
static void BuildDocksClick_Buoy(Window *w)
|
||||
{
|
||||
HandlePlacePushButton(w, 4, 0x2BE, 1, PlaceDocks_Buoy);
|
||||
}
|
||||
|
||||
static void BuildDocksClick_Demolish(Window *w)
|
||||
{
|
||||
HandlePlacePushButton(w, 5, ANIMCURSOR_DEMOLISH, 1, PlaceDocks_DemolishArea);
|
||||
}
|
||||
|
||||
static void BuildDocksClick_Lower(Window *w)
|
||||
{
|
||||
HandlePlacePushButton(w, 6, ANIMCURSOR_LOWERLAND, 2, PlaceProc_LowerLand);
|
||||
}
|
||||
|
||||
static void BuildDocksClick_Raise(Window *w)
|
||||
{
|
||||
HandlePlacePushButton(w, 7, ANIMCURSOR_RAISELAND, 2, PlaceProc_RaiseLand);
|
||||
}
|
||||
|
||||
static void BuildDocksClick_Purchase(Window *w)
|
||||
{
|
||||
HandlePlacePushButton(w, 8, 0x12B8, 1, PlaceProc_BuyLand);
|
||||
}
|
||||
|
||||
static void BuildDocksClick_Canal(Window *w)
|
||||
{
|
||||
HandlePlacePushButton(w, 9, SPR_OPENTTD_BASE + 11, 1, PlaceDocks_BuildCanal);
|
||||
HandlePlacePushButton(w, 3, SPR_OPENTTD_BASE + 11, 1, PlaceDocks_BuildCanal);
|
||||
}
|
||||
|
||||
static void BuildDocksClick_Lock(Window *w)
|
||||
{
|
||||
HandlePlacePushButton(w, 10, SPR_OPENTTD_BASE + 64, 1, PlaceDocks_BuildLock);
|
||||
HandlePlacePushButton(w, 4, SPR_OPENTTD_BASE + 64, 1, PlaceDocks_BuildLock);
|
||||
}
|
||||
|
||||
static void BuildDocksClick_Demolish(Window *w)
|
||||
{
|
||||
HandlePlacePushButton(w, 6, ANIMCURSOR_DEMOLISH, 1, PlaceDocks_DemolishArea);
|
||||
}
|
||||
|
||||
static void BuildDocksClick_Depot(Window *w)
|
||||
{
|
||||
if (HandlePlacePushButton(w, 7, 0x2D1, 1, PlaceDocks_Depot)) ShowBuildDocksDepotPicker();
|
||||
}
|
||||
|
||||
static void BuildDocksClick_Dock(Window *w)
|
||||
{
|
||||
|
||||
if (HandlePlacePushButton(w, 8, 0xE54, 3, PlaceDocks_Dock)) ShowBuildDockStationPicker();
|
||||
}
|
||||
|
||||
static void BuildDocksClick_Buoy(Window *w)
|
||||
{
|
||||
HandlePlacePushButton(w, 9, 0x2BE, 1, PlaceDocks_Buoy);
|
||||
}
|
||||
|
||||
static void BuildDocksClick_Landscaping(Window *w)
|
||||
{
|
||||
ShowTerraformToolbar();
|
||||
}
|
||||
|
||||
typedef void OnButtonClick(Window *w);
|
||||
static OnButtonClick * const _build_docks_button_proc[] = {
|
||||
BuildDocksClick_Dock,
|
||||
BuildDocksClick_Depot,
|
||||
BuildDocksClick_Buoy,
|
||||
BuildDocksClick_Demolish,
|
||||
BuildDocksClick_Lower,
|
||||
BuildDocksClick_Raise,
|
||||
BuildDocksClick_Purchase,
|
||||
BuildDocksClick_Canal,
|
||||
BuildDocksClick_Lock,
|
||||
0,
|
||||
BuildDocksClick_Demolish,
|
||||
BuildDocksClick_Depot,
|
||||
BuildDocksClick_Dock,
|
||||
BuildDocksClick_Buoy,
|
||||
BuildDocksClick_Landscaping,
|
||||
};
|
||||
|
||||
static void BuildDocksToolbWndProc(Window *w, WindowEvent *e)
|
||||
@@ -124,7 +117,21 @@ static void BuildDocksToolbWndProc(Window *w, WindowEvent *e)
|
||||
break;
|
||||
|
||||
case WE_CLICK: {
|
||||
if (e->click.widget - 2 >= 0) _build_docks_button_proc[e->click.widget - 2](w);
|
||||
if (e->click.widget - 3 >= 0 && e->click.widget != 5) _build_docks_button_proc[e->click.widget - 3](w);
|
||||
} break;
|
||||
|
||||
case WE_KEYPRESS: {
|
||||
switch(e->keypress.keycode) {
|
||||
case '1': BuildDocksClick_Canal(w); break;
|
||||
case '2': BuildDocksClick_Lock(w); break;
|
||||
case '3': BuildDocksClick_Demolish(w); break;
|
||||
case '4': BuildDocksClick_Depot(w); break;
|
||||
case '5': BuildDocksClick_Dock(w); break;
|
||||
case '6': BuildDocksClick_Buoy(w); break;
|
||||
case 'l': BuildDocksClick_Landscaping(w); break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
} break;
|
||||
|
||||
case WE_PLACE_OBJ:
|
||||
@@ -138,15 +145,15 @@ static void BuildDocksToolbWndProc(Window *w, WindowEvent *e)
|
||||
|
||||
case WE_PLACE_MOUSEUP:
|
||||
if (e->click.pt.x != -1) {
|
||||
if (e->place.userdata == VPM_X_AND_Y)
|
||||
DoCommandP(e->place.tile, e->place.starttile, 0, CcPlaySound10, CMD_CLEAR_AREA | CMD_MSG(STR_00B5_CAN_T_CLEAR_THIS_AREA));
|
||||
else if(e->place.userdata == VPM_X_OR_Y)
|
||||
if ((e->place.userdata & 0xF) == VPM_X_AND_Y) { // dragged actions
|
||||
GUIPlaceProcDragXY(e);
|
||||
} else if(e->place.userdata == VPM_X_OR_Y)
|
||||
DoCommandP(e->place.tile, e->place.starttile, 0, CcBuildCanal, CMD_BUILD_CANAL | CMD_AUTO | CMD_MSG(STR_CANT_BUILD_CANALS));
|
||||
}
|
||||
break;
|
||||
|
||||
case WE_ABORT_PLACE_OBJ:
|
||||
w->click_state = 0;
|
||||
UnclickWindowButtons(w);
|
||||
SetWindowDirty(w);
|
||||
|
||||
w = FindWindowById(WC_BUILD_STATION, 0);
|
||||
@@ -172,47 +179,67 @@ static void BuildDocksToolbWndProc(Window *w, WindowEvent *e)
|
||||
}
|
||||
|
||||
static const Widget _build_docks_toolb_widgets[] = {
|
||||
{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, 7, 11, 197, 0, 13, STR_9801_DOCK_CONSTRUCTION, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_PANEL, 7, 0, 21, 14, 35, 746, STR_981D_BUILD_SHIP_DOCK},
|
||||
{ WWT_PANEL, 7, 22, 43, 14, 35, 748, STR_981E_BUILD_SHIP_DEPOT_FOR_BUILDING},
|
||||
{ WWT_PANEL, 7, 44, 65, 14, 35, 693, STR_9834_POSITION_BUOY_WHICH_CAN},
|
||||
{ WWT_PANEL, 7, 66, 87, 14, 35, 703, STR_018D_DEMOLISH_BUILDINGS_ETC},
|
||||
{ WWT_PANEL, 7, 88, 109, 14, 35, 695, STR_018E_LOWER_A_CORNER_OF_LAND},
|
||||
{ WWT_PANEL, 7, 110, 131, 14, 35, 694, STR_018F_RAISE_A_CORNER_OF_LAND},
|
||||
{ WWT_PANEL, 7, 132, 153, 14, 35, 4791, STR_0329_PURCHASE_LAND_FOR_FUTURE},
|
||||
{ WWT_PANEL, 7, 154, 175, 14, 35, SPR_OPENTTD_BASE+65, STR_BUILD_CANALS_TIP},
|
||||
{ WWT_PANEL, 7, 176, 197, 14, 35, SPR_CANALS_BASE+69, STR_BUILD_LOCKS_TIP},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 145, 0, 13, STR_9801_DOCK_CONSTRUCTION, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_STICKYBOX, RESIZE_NONE, 7, 146, 157, 0, 13, 0x0, STR_STICKY_BUTTON},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 0, 21, 14, 35, SPR_IMG_BUILD_CANAL, STR_BUILD_CANALS_TIP},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 22, 43, 14, 35, SPR_IMG_BUILD_LOCK, STR_BUILD_LOCKS_TIP},
|
||||
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 44, 47, 14, 35, 0x0, STR_NULL},
|
||||
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 48, 69, 14, 35, 703, STR_018D_DEMOLISH_BUILDINGS_ETC},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 70, 91, 14, 35, 748, STR_981E_BUILD_SHIP_DEPOT_FOR_BUILDING},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 92, 113, 14, 35, 746, STR_981D_BUILD_SHIP_DOCK},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 114, 135, 14, 35, 693, STR_9834_POSITION_BUOY_WHICH_CAN},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 136, 157, 14, 35, SPR_IMG_LANDSCAPING, STR_LANDSCAPING_TOOLBAR_TIP},
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
static const WindowDesc _build_docks_toolbar_desc = {
|
||||
640-197, 22, 198, 36,
|
||||
640-158, 22, 158, 36,
|
||||
WC_BUILD_TOOLBAR,0,
|
||||
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
|
||||
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
|
||||
_build_docks_toolb_widgets,
|
||||
BuildDocksToolbWndProc
|
||||
};
|
||||
|
||||
void ShowBuildDocksToolbar()
|
||||
void ShowBuildDocksToolbar(void)
|
||||
{
|
||||
if (_current_player == OWNER_SPECTATOR) return;
|
||||
DeleteWindowById(WC_BUILD_TOOLBAR, 0);
|
||||
AllocateWindowDesc(&_build_docks_toolbar_desc);
|
||||
}
|
||||
|
||||
static void BuildDockStationWndProc(Window *w, WindowEvent *e)
|
||||
{
|
||||
int rad;
|
||||
|
||||
switch(e->event) {
|
||||
case WE_PAINT: {
|
||||
if (WP(w,def_d).close)
|
||||
return;
|
||||
w->click_state = (1<<3) << _station_show_coverage;
|
||||
DrawWindowWidgets(w);
|
||||
DrawStationCoverageAreaText(2, 15, (uint)-1);
|
||||
if (_patches.modified_catchment) {
|
||||
rad = CA_DOCK;
|
||||
} else {
|
||||
rad = 4;
|
||||
}
|
||||
|
||||
if (_station_show_coverage) SetTileSelectBigSize(-rad, -rad, 2 * rad, 2 * rad);
|
||||
else SetTileSelectBigSize(0, 0, 0, 0);
|
||||
|
||||
DrawStringCentered(74, 17, STR_3066_COVERAGE_AREA_HIGHLIGHT, 0);
|
||||
DrawStationCoverageAreaText(4, 50, (uint)-1, rad);
|
||||
} break;
|
||||
|
||||
case WE_CLICK: {
|
||||
if (e->click.widget == 0) {
|
||||
ResetObjectToPlace();
|
||||
switch(e->click.widget) {
|
||||
case 3: case 4:
|
||||
_station_show_coverage = e->click.widget - 3;
|
||||
SndPlayFx(SND_15_BEEP);
|
||||
SetWindowDirty(w);
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
|
||||
@@ -225,30 +252,37 @@ static void BuildDockStationWndProc(Window *w, WindowEvent *e)
|
||||
CheckRedrawStationCoverage(w);
|
||||
break;
|
||||
}
|
||||
|
||||
case WE_DESTROY:
|
||||
if (!WP(w,def_d).close)
|
||||
ResetObjectToPlace();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const Widget _build_dock_station_widgets[] = {
|
||||
{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, 7, 11, 147, 0, 13, STR_3068_DOCK, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_PANEL, 7, 0, 147, 14, 45, 0x0, STR_NULL},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 147, 0, 13, STR_3068_DOCK, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 0, 147, 14, 74, 0x0, STR_NULL},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 14, 73, 30, 40, STR_02DB_OFF, STR_3065_DON_T_HIGHLIGHT_COVERAGE},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 74, 133, 30, 40, STR_02DA_ON, STR_3064_HIGHLIGHT_COVERAGE_AREA},
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
static const WindowDesc _build_dock_station_desc = {
|
||||
-1, -1, 148, 46,
|
||||
-1, -1, 148, 75,
|
||||
WC_BUILD_STATION,WC_BUILD_TOOLBAR,
|
||||
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
|
||||
_build_dock_station_widgets,
|
||||
BuildDockStationWndProc
|
||||
};
|
||||
|
||||
static void ShowBuildDockStationPicker()
|
||||
static void ShowBuildDockStationPicker(void)
|
||||
{
|
||||
AllocateWindowDesc(&_build_dock_station_desc);
|
||||
}
|
||||
|
||||
static void UpdateDocksDirection()
|
||||
static void UpdateDocksDirection(void)
|
||||
{
|
||||
if (_ship_depot_direction != 0) {
|
||||
SetTileSelectSize(1, 2);
|
||||
@@ -272,13 +306,10 @@ static void BuildDocksDepotWndProc(Window *w, WindowEvent *e)
|
||||
|
||||
case WE_CLICK: {
|
||||
switch(e->click.widget) {
|
||||
case 0:
|
||||
ResetObjectToPlace();
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
_ship_depot_direction = e->click.widget - 3;
|
||||
SndPlayFx(0x13);
|
||||
SndPlayFx(SND_15_BEEP);
|
||||
UpdateDocksDirection();
|
||||
SetWindowDirty(w);
|
||||
break;
|
||||
@@ -289,15 +320,20 @@ static void BuildDocksDepotWndProc(Window *w, WindowEvent *e)
|
||||
if (WP(w,def_d).close)
|
||||
DeleteWindow(w);
|
||||
break;
|
||||
|
||||
case WE_DESTROY:
|
||||
if (!WP(w,def_d).close)
|
||||
ResetObjectToPlace();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const Widget _build_docks_depot_widgets[] = {
|
||||
{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, 7, 11, 203, 0, 13, STR_3800_SHIP_DEPOT_ORIENTATION, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_PANEL, 7, 0, 203, 14, 85, 0x0, STR_NULL},
|
||||
{ WWT_PANEL, 14, 3, 100, 17, 82, 0x0, STR_3803_SELECT_SHIP_DEPOT_ORIENTATION},
|
||||
{ WWT_PANEL, 14, 103, 200, 17, 82, 0x0, STR_3803_SELECT_SHIP_DEPOT_ORIENTATION},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 203, 0, 13, STR_3800_SHIP_DEPOT_ORIENTATION, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 0, 203, 14, 85, 0x0, STR_NULL},
|
||||
{ WWT_PANEL, RESIZE_NONE, 14, 3, 100, 17, 82, 0x0, STR_3803_SELECT_SHIP_DEPOT_ORIENTATION},
|
||||
{ WWT_PANEL, RESIZE_NONE, 14, 103, 200, 17, 82, 0x0, STR_3803_SELECT_SHIP_DEPOT_ORIENTATION},
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
@@ -310,14 +346,14 @@ static const WindowDesc _build_docks_depot_desc = {
|
||||
};
|
||||
|
||||
|
||||
static void ShowBuildDocksDepotPicker()
|
||||
static void ShowBuildDocksDepotPicker(void)
|
||||
{
|
||||
AllocateWindowDesc(&_build_docks_depot_desc);
|
||||
UpdateDocksDirection();
|
||||
}
|
||||
|
||||
|
||||
void InitializeDockGui()
|
||||
void InitializeDockGui(void)
|
||||
{
|
||||
_ship_depot_direction = 0;
|
||||
}
|
||||
|
||||
+2
-1
@@ -24,6 +24,7 @@ On BeOS, run ./configure and then use jam. There are a variaty of options you ca
|
||||
On Windows, insert your "Transport Tycoon Deluxe for Windows 95" disk. You can use a DOS version, but your graphics will be purple. NB: Even if your version of Transport Tycoon Deluxe ran on Windows 95, it may still be the DOS version. Then run the OpenTTD installer.
|
||||
|
||||
On UNIX platforms; decompress your OpenTTD archive, or otherwise run the installer. You should be left with an OpenTTD directory on your system. In this directory, make a subdirectory called 'data', and into this place the sample.cat file and all the .grf files from the install CD of 'Transport Tycoon Deluxe for Windows 95".
|
||||
(Alternatively you can use the TTD GRF files from the DOS version: TRG1.GRF, TRGC.GRF, TRGH.GRF, TRGI.GRF, TRGT.GRF. A few minor graphical glitches with the DOS graphics remain. E.g. the autorail button in the rail toolbar doesn't look as nice as with the Windows graphics.)
|
||||
|
||||
If you want MIDI music, copy the 'gm' folder from the original game directory/CD to the OpenTTD folder.
|
||||
|
||||
@@ -90,7 +91,7 @@ Virtually any settings - train numbers, start date, what vehicles your competito
|
||||
|
||||
2.11 Network Play
|
||||
|
||||
OpenTTD now supports rudimentary TCP/IP based network play. This is not supported on all platforms. To start a server, use the '-n' CLI switch, and start a client with '-n' and the servers IP adress. The OpenTTD network play runs over port 12345, so you may need to open this on your firewall.
|
||||
See multiplayer.txt for more info.
|
||||
|
||||
2.12 Rail Recycling.
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
It's gone
|
||||
|
||||
The main goal with the package system was to make it as simple as possible to update. The problem was that some files inside the data folder should be updated and not others. Now the data files have been moved inside OpenTTD itself and to make it even easier, the same goes for the lang dir. There will no longer be an issue where people have different versions of grf files, language files and OpenTTD.
|
||||
|
||||
To install simply copy OpenTTD into the folder you want
|
||||
If it is your current folder with outdated grf files, you should remove
|
||||
canalsw.grf
|
||||
openttd.grf
|
||||
opntitle.dat
|
||||
signalsw.grf
|
||||
trkfoundw.grf
|
||||
|
||||
THE TTD GRF FILES ARE STILL NEEDED!
|
||||
They need to be inside a folder called "data" in the same folder as OpenTTD. Create it if you have none. It should contain:
|
||||
sample.cat
|
||||
trg1r.grf
|
||||
trgcr.grf
|
||||
trghr.grf
|
||||
trgir.grf
|
||||
trgtr.grf
|
||||
|
||||
(Alternatively you can use the TTD GRF files from the DOS version: TRG1.GRF, TRGC.GRF, TRGH.GRF, TRGI.GRF, TRGT.GRF. A few minor graphical glitches with the DOS graphics remain. E.g. the autorail button in the rail toolbar doesn't look as nice as with the Windows graphics.)
|
||||
|
||||
You should also use the data folder to add any custom grf files if you like
|
||||
@@ -2,10 +2,8 @@ Since you are reading this, OpenTTD have crashed. This file tells you how
|
||||
to fix the most common problems or make to make a bug report, that the
|
||||
developers can use to track down the problem
|
||||
|
||||
The first thing you need to do is to get the error message. You can access OSX's build-in log by double-clicking Crash_Log_Opener. OTTD will do that if that file is present in the same folder as OTTD and is not renamed. However, major crashes can prevent the autoopen feature and you have to do it manually then
|
||||
If Crash_Log_Opener doesn't work you can view the log by opening Console inside Applications/utilities.
|
||||
|
||||
If you use the Console app, you should look at the buttom of the console.log window
|
||||
If it is an assert, OpenTTD will open the console for you, if it is truly a crash, you have to do it yourself. The Console is located at /Applications/Utilities/Console.
|
||||
The problem is near the button of the page
|
||||
|
||||
The problems are as follows:
|
||||
NOTE: build from source means to download the source and compile
|
||||
|
||||
@@ -31,14 +31,16 @@ You can undo changes to a file with
|
||||
|
||||
3.) Required data files:
|
||||
|
||||
Copy the following files from the WINDOWS version of Transport Tycoon Deluxe to openttd/data/
|
||||
Copy the following files from Transport Tycoon Deluxe to openttd/data/
|
||||
sample.cat
|
||||
trg1r.grf
|
||||
trgcr.grf
|
||||
trghr.grf
|
||||
trgir.grf
|
||||
trgtr.grf
|
||||
|
||||
|
||||
(Alternatively you can use the TTD GRF files from the DOS version: TRG1.GRF, TRGC.GRF, TRGH.GRF, TRGI.GRF, TRGT.GRF. A few minor graphical glitches with the DOS graphics remain. E.g. the autorail button in the rail toolbar doesn't look as nice as with the Windows graphics.)
|
||||
|
||||
|
||||
4.) Compiling and running:
|
||||
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
OpenTTD: OS/2 version
|
||||
=====================
|
||||
|
||||
OpenTTD has been ported to work on OS/2 4.x or later (including
|
||||
eComStation). The game should work as well as it does on Windows
|
||||
or other platforms: the main issues you may encounter are graphics
|
||||
card problems, but that is really the fault of SDL.
|
||||
|
||||
=========================
|
||||
USING OPENTTD FOR OS/2
|
||||
=========================
|
||||
|
||||
LIBRARIES REQUIRED FOR END USERS
|
||||
--------------------------------
|
||||
|
||||
SDL.DLL (SDL 1.2.7) and FSLib.dll are required to use this program:
|
||||
these can be downloaded from the Files section at
|
||||
http://sourceforge.net/projects/openttd/ - see "os2-useful.zip".
|
||||
(Note that a newer version of SDL is now available at
|
||||
ftp://ftp.netlabs.org/pub/sdl/sdl-dev-os2-2004-12-22.zip which may
|
||||
help solve some problems).
|
||||
|
||||
Please note that SDL release 2005-03-30 does NOT work with OpenTTD,
|
||||
at least in my experience and the experience of a couple of other
|
||||
users. If you experience problems with OpenTTD, please try downgrading
|
||||
to SDL 2004-12-22.
|
||||
|
||||
Note that to actually play the game, I have found in my own
|
||||
experience that a version of the Scitech Display Drivers or its later
|
||||
incarnation (see www.scitech.com) are necessary for it to work. If
|
||||
you have trouble with your native drivers, try the Scitech drivers
|
||||
and see if they help the problem.
|
||||
|
||||
KNOWN ISSUES
|
||||
------------
|
||||
|
||||
- If an error occurs during loading, the OS/2 error message window
|
||||
is not always displayed.
|
||||
|
||||
A NOTE ABOUT MUSIC
|
||||
------------------
|
||||
|
||||
OpenTTD includes a music driver which uses the MCI MIDI system. Unfortunately,
|
||||
due to the lack of proper MIDI hardware myself, I have been unable to test it,
|
||||
but during testing, I found that when MIDI was enabled, I got no sound
|
||||
effects. I therefore decided to DISABLE music by default.
|
||||
|
||||
To enable music, start OpenTTD with the command line:
|
||||
|
||||
openttd -m os2
|
||||
|
||||
If I hear enough responses that both music and sound work together (it might
|
||||
just be my system), I'll have the defaults changed.
|
||||
|
||||
A NOTE ABOUT DEDICATED MULTIPLAYER SERVERS
|
||||
------------------------------------------
|
||||
|
||||
To start a dedicated multiplayer server, you should run the dedicated.cmd
|
||||
file. This enables OpenTTD to open up a VIO console window to display
|
||||
its output and gather any necessary input. Running "openttd -D"
|
||||
directly will result in the console not being displayed. You may
|
||||
still pass any other parameters ('-D' is already passed) to
|
||||
dedicated.cmd.
|
||||
|
||||
=========================
|
||||
BUILDING THE OS/2 VERSION
|
||||
=========================
|
||||
|
||||
Compiler
|
||||
--------
|
||||
|
||||
Open Watcom 1.3 was used to build OpenTTD (earlier versions will
|
||||
NOT work). See http://www.openwatcom.org/ to download it. It may
|
||||
also be possible to build OpenTTD with GCC: I attempted this
|
||||
before using Open Watcom, but found the tools available for OS/2
|
||||
at the time to be a bit more tricky to get working.
|
||||
|
||||
Due to complexities in my set-up, I actually used the Win32 version
|
||||
of Open Watcom to initially compile OpenTTD for OS/2. There should
|
||||
be no reason of course why the OS/2 version cannot be used, and I
|
||||
have subsequently built OpenTTD successfully this way.
|
||||
|
||||
Libraries Required
|
||||
------------------
|
||||
|
||||
The following libraries are required. To build zlib and libpng, I
|
||||
simply added the required files (watch out for sample programs, etc)
|
||||
to an IDE project file and built a library. Do not use the makefiles
|
||||
provided, they are not designed for Watcom (apart from SDL):
|
||||
|
||||
- zlib
|
||||
http://www.zlib.org/ - contains a makefile for OS/2, but is out
|
||||
of date and uses EMX, ignore this
|
||||
|
||||
- libpng
|
||||
http://www.libpng.org/ - contains an EMX/gcc makefile, ignore this
|
||||
|
||||
- SDL for OS/2
|
||||
For 0.3.5, I used ftp://ftp.netlabs.org/pub/sdl/SDL-1.2.7-src-20040908a.zip -
|
||||
take SDL.dll and SDL.lib from the src/ directory. Note that 20041222 is
|
||||
out now, which is recommended for stability updates.
|
||||
|
||||
If you do not wish to build the libraries yourself, pre-built versions
|
||||
can be downloaded from the Files section at
|
||||
http://sourceforge.net/projects/openttd/ - see "os2-useful.zip".
|
||||
|
||||
A Note About Subversion Revision Numbers
|
||||
----------------------------------------
|
||||
|
||||
The project file uses a bit of a hack to find out the SVN revision number and
|
||||
create an appropriate rev.c file. You'll need the SVN tools in your path
|
||||
(specifically, "svnversion"). If "svnversion" can't be found, a generic rev.c
|
||||
with the revision set to "norev000" will be created. To specifically force a
|
||||
version number, set the environment variable "RELEASE" to the number (eg, "0.3.6")
|
||||
-before- starting the Open Watcom IDE (which must be launched from the same shell
|
||||
session). Also, beware, as you WILL cause incompatibilities if you try to
|
||||
play a multiplayer game with a different version.
|
||||
|
||||
Compiling
|
||||
---------
|
||||
|
||||
To compile, open the os/os2/openttd.wpj file in the IDE and first build
|
||||
the strgen.exe target. This will build the .lng file generator, and will
|
||||
also attempt to build all the language files (plus the table\strings.h
|
||||
file which is required for openttd.exe to be built). Once strgen.exe and
|
||||
the language files are built successfully, you can build the openttd.exe
|
||||
target.
|
||||
|
||||
Contact Information
|
||||
-------------------
|
||||
|
||||
If you have any questions regarding OS/2 issues, please contact me
|
||||
(owen@owenrudge.net) and I'll try to help you out. For general OpenTTD
|
||||
issues, see the Contacting section of readme.txt.
|
||||
|
||||
- Owen Rudge
|
||||
+105
-89
@@ -1,89 +1,105 @@
|
||||
Compilung OpenTTD using MS VC6.0
|
||||
|
||||
|
||||
Step 1
|
||||
------------------
|
||||
Downloaded:
|
||||
Useful.zip http://sourceforge.net/project/showfiles.php?group_id=103924&package_id=114307&release_id=228633
|
||||
SDL.zip http://www.libsdl.org/release/SDL-1.2.7-win32.zip
|
||||
DirectX7.0 SDK http://www.tt-forums.net/download.php?id=15989
|
||||
(or alternatively the latest DirectX SDK from Microsoft)
|
||||
afxres.h http://www-d0.fnal.gov/d0dist/dist/packages/d0ve/devel/windows/AFXRES.H
|
||||
|
||||
|
||||
Step 2
|
||||
------------------
|
||||
Put the newly downloaded files in the VC lib and include directories
|
||||
(Where D:\program files\ is your local location of VC)
|
||||
|
||||
|
||||
* zconf.h [useful.zip]
|
||||
* zlib.h [useful.zip]
|
||||
* afxres.h
|
||||
in
|
||||
D:\Program Files\Microsoft Visual Studio\VC98\Include
|
||||
|
||||
* zlibstat.lib [usefull.zip]
|
||||
* SDL.lib [SDL.zip
|
||||
* libpng.lib [usefull.zip]
|
||||
in
|
||||
D:\Program Files\Microsoft Visual Studio\VC98\Lib
|
||||
|
||||
You can also make custum directories, for libraries (.lib) and includes/header files (.h) and
|
||||
add it to the VC paths via:
|
||||
Tools -> Options -> Directories -> show directories for:
|
||||
a) include files (the include dir: D:\Program Files\Microsoft Visual Studio\VC98\DirectX 7 SDK\include )
|
||||
b) library files (the lib dir, D:\Program Files\Microsoft Visual Studio\VC98\DirectX 7 SDK\lib )
|
||||
|
||||
|
||||
Step 3: DirextX SDK
|
||||
------------------
|
||||
(This should work with the latest DirectX SDK as well.)
|
||||
The installation with DirectX 7 was odd, so you'd better use the version available via the forum, see also
|
||||
the download link on top.
|
||||
|
||||
Copy the DirectX 7 SDK files, leaving the directory stucture intact, to the directory:
|
||||
D:\Program Files\Microsoft Visual Studio\VC98\
|
||||
thus resulting in
|
||||
D:\Program Files\Microsoft Visual Studio\VC98\DirectX 7 SDK\include and
|
||||
D:\Program Files\Microsoft Visual Studio\VC98\DirectX 7 SDK\lib
|
||||
|
||||
Step 3.1
|
||||
|
||||
Add these two folders to the search path of VC.
|
||||
In VC6.0: Tools -> Options -> Directories -> show directories for:
|
||||
a) include files (the include dir: D:\Program Files\Microsoft Visual Studio\VC98\DirectX 7 SDK\include )
|
||||
b) libraru files (the lib dir, D:\Program Files\Microsoft Visual Studio\VC98\DirectX 7 SDK\lib )
|
||||
|
||||
|
||||
Step 4
|
||||
-----------------
|
||||
Copy the following files from the WINDOWS version of Transport Tycoon Deluxe to the data folder
|
||||
sample.cat
|
||||
trg1r.grf
|
||||
trgcr.grf
|
||||
trghr.grf
|
||||
trgir.grf
|
||||
trgtr.grf
|
||||
|
||||
|
||||
|
||||
Step 5
|
||||
-----------------
|
||||
Compile ...
|
||||
|
||||
|
||||
Step 6
|
||||
-----------------
|
||||
|
||||
Now it should work, it worked for me :)
|
||||
|
||||
Go ahead and make that patch!
|
||||
|
||||
Happy Hacking!
|
||||
|
||||
|
||||
|
||||
------------------
|
||||
written by Dribbel
|
||||
|
||||
Compiling OpenTTD using Microsoft Visual C++ 6.0
|
||||
|
||||
|
||||
---Step 1
|
||||
|
||||
Download the following files:
|
||||
|
||||
* Useful.zip (http://sourceforge.net/project/showfiles.php?group_id=103924&package_id=114307&release_id=228633)
|
||||
* SDL-1.2.8-VC6.zip (http://www.libsdl.org/release/SDL-devel-1.2.8-VC6.zip)
|
||||
* DirectX7.0 SDK (http://www.tt-forums.net/download.php?id=15989) (or alternatively the latest DirectX SDK from Microsoft)
|
||||
* afxres.h (http://www-d0.fnal.gov/d0dist/dist/packages/d0ve/devel/windows/AFXRES.H)
|
||||
|
||||
...and of course the newest source from svn://svn.openttd.com/trunk
|
||||
|
||||
(The alpha version of the new map array can be found at svn://svn.openttd.com/branch/map)
|
||||
|
||||
You have to have and SVN-client to download the source:
|
||||
|
||||
* Command line version (http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91)
|
||||
* TortoiseSVN (http://tortoisesvn.tigris.org/download.html)
|
||||
|
||||
|
||||
---Step 2
|
||||
|
||||
Put the newly downloaded files in the VC lib and include directories (Where C:\program files\ is your local location of VC)
|
||||
|
||||
|
||||
* zconf.h [useful.zip]
|
||||
* zlib.h [useful.zip]
|
||||
* png.h [useful.zip]
|
||||
* pngconf.h [useful.zip]
|
||||
* afxres.h
|
||||
|
||||
in
|
||||
|
||||
C:\Program Files\Microsoft Visual Studio\VC98\Include
|
||||
|
||||
and
|
||||
|
||||
* zlibstat.lib [useful.zip]
|
||||
* SDL.lib [SDL.zip]
|
||||
* libpng.lib [useful.zip]
|
||||
|
||||
in
|
||||
|
||||
C:\Program Files\Microsoft Visual Studio\VC98\Lib
|
||||
|
||||
|
||||
---Step 3: DirectX SDK
|
||||
|
||||
(This should work with the latest DirectX SDK as well.) The installation with DirectX 7 was odd, so you'd better use the version available via the forum, see also the download link on top.
|
||||
|
||||
There are 2 folder in the compressed file: Include and Lib
|
||||
|
||||
Copy all files from Include folder to
|
||||
|
||||
C:\Program Files\Microsoft Visual Studio\VC98\Include
|
||||
|
||||
and all files from Lib folder to
|
||||
|
||||
C:\Program Files\Microsoft Visual Studio\VC98\Lib
|
||||
|
||||
|
||||
|
||||
You can also make custom directories, for libraries (.lib) and includes/header files (.h) and add it to the VC paths via:
|
||||
|
||||
Tools -> Options -> Directories -> show directories for:
|
||||
|
||||
a) include files (the include dir: C:\Program Files\Microsoft Visual Studio\VC98\DirectX 7 SDK\include )
|
||||
|
||||
b) library files (the lib dir, C:\Program Files\Microsoft Visual Studio\VC98\DirectX 7 SDK\lib )
|
||||
|
||||
|
||||
---Step 4
|
||||
|
||||
Copy the following files from Transport Tycoon Deluxe to the data folder
|
||||
|
||||
* sample.cat
|
||||
* trg1r.grf
|
||||
* trgcr.grf
|
||||
* trghr.grf
|
||||
* trgir.grf
|
||||
* trgtr.grf
|
||||
|
||||
|
||||
---Step 5
|
||||
|
||||
Open trunk/ttd.dsw
|
||||
|
||||
Build menu > Set active configuration > Select: "ttd - Win32 Release with PNG"
|
||||
|
||||
Compile...
|
||||
|
||||
|
||||
Now it should work, it worked for me :)
|
||||
|
||||
From r1319 you can compile branch/map in Debug mode (by Bociusz)
|
||||
|
||||
If it's not working, and you checked that you using the newest SVN (!) report to Bociusz on IRC (irc://irc.freenode.net/#openttd)
|
||||
|
||||
Go ahead and make that patch! Happy Hacking! :)
|
||||
|
||||
Originally written by Dribbel
|
||||
|
||||
Project file updating by Bociusz
|
||||
+11
-7
@@ -1,8 +1,12 @@
|
||||
OPENTTD INGAME CONSOLE DOCUMENTATION
|
||||
====================================
|
||||
http://openttd.rulez.org/wiki2/index.php/OpenTTDDevBlackBook
|
||||
http://wiki.openttd.org/index.php/OpenTTDDevBlackBook
|
||||
for detailed information
|
||||
|
||||
*** WARNING **
|
||||
This document is out of date
|
||||
*** WARNING **
|
||||
|
||||
HOTKEY: BACKQUOTE (aka tilde, the key left to "1")
|
||||
|
||||
COMMANDS:
|
||||
@@ -34,19 +38,19 @@ VARIABLES:
|
||||
-> 2 = console error and debug output
|
||||
|
||||
*cursor_rate
|
||||
-> 1-12 = defines the cursor blink interval
|
||||
-> 1-12 = defines the cursor blink interval
|
||||
|
||||
|
||||
VARIABLE HANDLING:
|
||||
------------------
|
||||
|
||||
*developer = 0
|
||||
*developer ++
|
||||
developer = 0
|
||||
developer ++
|
||||
|
||||
*temp_string = test
|
||||
*temp_string = "my little"
|
||||
temp_string = test
|
||||
temp_string = "my little"
|
||||
|
||||
printf "%s world" *temp_string
|
||||
printf "%s world" temp_string
|
||||
|
||||
|
||||
---------------------------------------------------
|
||||
|
||||
+19
-19
@@ -1,20 +1,20 @@
|
||||
Notes about DirectMusic driver for Win32
|
||||
----------------------------------------
|
||||
|
||||
If compiling under MinGW32, you require the DirectX 7.0 files for MinGW32, available from
|
||||
http://alleg.sourceforge.net/files/dx70_mgw.zip.
|
||||
|
||||
If compiling under MSVC 6.0, you require the equivalent for MSVC, available from
|
||||
http://alleg.sourceforge.net/files/dx70_min.zip. MSVC 7.0/7.1 include header files that
|
||||
are recent enough.
|
||||
|
||||
If you do not want to compile the DirectMusic driver, undefine WIN32_ENABLE_DIRECTMUSIC_SUPPORT
|
||||
in stdafx.h.
|
||||
|
||||
Bugs, etc
|
||||
---------
|
||||
|
||||
- The volume control doesn't work properly. I'll fix this soon.
|
||||
|
||||
Owen Rudge
|
||||
Notes about DirectMusic driver for Win32
|
||||
----------------------------------------
|
||||
|
||||
If compiling under MinGW32, you require the DirectX 7.0 files for MinGW32, available from
|
||||
http://alleg.sourceforge.net/files/dx70_mgw.zip.
|
||||
|
||||
If compiling under MSVC 6.0, you require the equivalent for MSVC, available from
|
||||
http://alleg.sourceforge.net/files/dx70_min.zip. MSVC 7.0/7.1 include header files that
|
||||
are recent enough.
|
||||
|
||||
If you do not want to compile the DirectMusic driver, undefine WIN32_ENABLE_DIRECTMUSIC_SUPPORT
|
||||
in stdafx.h.
|
||||
|
||||
Bugs, etc
|
||||
---------
|
||||
|
||||
- The volume control doesn't work properly. I'll fix this soon.
|
||||
|
||||
Owen Rudge
|
||||
14th March 2004
|
||||
+616
-611
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,239 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<meta content="text/html; charset=UTF-8" http-equiv="content-type">
|
||||
<meta name="Description" content="Structure of OpenTTD (OTTD) landscape arrays #2">
|
||||
<title>OpenTTD Landscape Internals - #2</title>
|
||||
<style type="text/css">
|
||||
.freebits { background-color: rgb(30, 178, 54);}
|
||||
.abuse { background-color: rgb(255, 58, 31);}
|
||||
</style>
|
||||
</head>
|
||||
<body style="direction: ltr;">
|
||||
<h3 style="font-weight: bold;">Landscape</h3>
|
||||
<span style="font-weight: bold;"></span>Five arrays are used to encode the information of the contents of the tile.
|
||||
This can be seen in the <a href="landscape.html">Landscape</a> document. This page tries to give an overview of used and free bits of
|
||||
the array so you can quickly see what is used and what is not.
|
||||
<ul>
|
||||
<li><span style="font-weight: bold;"><span class="freebits">O</span></span> - bit is free</li>
|
||||
<li><span style="font-weight: bold;">X</span> - bit is used</li>
|
||||
<li><span style="font-weight: bold;"><span class="abuse"> </span></span> - bit of _map_* is abused for different purposes</li>
|
||||
</ul>
|
||||
<p>
|
||||
<ul>
|
||||
<li><span style="font-weight: bold;">_map_owner[]</span> - 8 bits in size, used to identify the owner of that tile (eg piece of rail, bridge, etc.).</li>
|
||||
<li><span style="font-weight: bold;">_map2[]</span> - 16 bits in size, used to identify the index of the given tile (object) in the (object-)array.</li>
|
||||
<li><span style="font-weight: bold;">_map3[]</span> - 16 bits in size, which is split up into _map3lo[] and _map3hi[] is used for general storage.</li>
|
||||
<li><span style="font-weight: bold;">_map_type_and_height[]</span> - 8 bits in size, stores tile height (lower 4 bits) and tile class (upper 4 bits).</li>
|
||||
<li><span style="font-weight: bold;">_map5[]</span> - 8 bits in size, is used for general storage.</li>
|
||||
</ul>
|
||||
|
||||
<table style="text-align: left;" border="1" cellpadding="2"
|
||||
cellspacing="2" width="100%">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th style="white-space: nowrap; text-align: left;">class</th>
|
||||
<th style="white-space: nowrap; text-align: center;">_map_owner[L1] (8)</th>
|
||||
<th style="white-space: nowrap; text-align: center;">_map2[L2] (16)</th>
|
||||
<th style="white-space: nowrap; text-align: center;">_map3[lo& hi,L3] (16)</th>
|
||||
<th style="white-space: nowrap; text-align: center;">_map_type_and_height[L4] (8)</th>
|
||||
<th style="white-space: nowrap; text-align: center;">_map5[L5] (8)</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="white-space: nowrap; text-align: left;">(0) ground</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
|
||||
<td style="white-space: nowrap; text-align: center;"><span class="freebits">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX <span class="freebits">OOOO OO</span>XX XXXX</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX X<span class="freebits">O</span>XX</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="white-space: nowrap; text-align: left;">(1) rail</td>
|
||||
<td style="white-space: nowrap; text-align: center;"><span class="abuse">XXXX XXXX</span></td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX <span class="freebits">OOOO OOOO</span><br>
|
||||
</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX XXX<span class="freebits">O OOOO</span><br>
|
||||
</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<ul>
|
||||
<li style="white-space: nowrap; text-align: left;">depot/checkpoint</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;"><span class="freebits">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td style="text-align: center;">XXXX X<span class="freebits">OOO</span> XXXX XXXX</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXX<span class="freebits">O OO</span>XX</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="white-space: nowrap; text-align: left;">(2) road</td>
|
||||
<td style="text-align: center;">XXXX XXXX</td>
|
||||
<td style="text-align: center;"><span class="abuse">XXXX XXXX XXXX XXXX</span></td>
|
||||
<td style="text-align: center;"><span class="freebits">OOOO OOOO</span> XXXX XXXX</td>
|
||||
<td style="text-align: center;">XXXX XXXX</td>
|
||||
<td style="text-align: center;">XXXX XXXX</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<ul>
|
||||
<li style="white-space: nowrap; text-align: left;">level crossing</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;"><span class="abuse">XXXX XXXX XXXX XXXX</span></td>
|
||||
<td style="text-align: center;">XXXX XXXX XXXX XXXX</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;"><span class="freebits">OO</span>XX XXXX</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<ul>
|
||||
<li style="white-space: nowrap; text-align: left;">road depot</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;"><span class="freebits">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td style="text-align: center;"><span class="freebits">OOOO OOOO OOOO OOO</span>X</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;">XXXX XXXX</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="white-space: nowrap; text-align: left;">(3) town</td>
|
||||
<td style="white-space: nowrap; text-align: center;"><span class="abuse">XXXX XXXX</span></td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX XXXX XXXX<br>
|
||||
</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX XXXX XXXX<br>
|
||||
</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XX<span class="freebits">O</span>X</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="white-space: nowrap; text-align: left;">(4) trees</td>
|
||||
<td style="white-space: nowrap; text-align: center;"><span class="abuse">XXXX XXXX</span></td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XX<span class="freebits">OO OOOO OOOO</span></td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX <span class="freebits">OO</span>XX XXXX</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXX<span class="freebits">O OO</span>XX</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="white-space: nowrap; text-align: left;">(5) station</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX XXXX XXXX</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX X<span class="freebits">OOO</span> XXXX XXXX</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="white-space: nowrap; text-align: left;">(6) water</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
|
||||
<td style="white-space: nowrap; text-align: center;"><span class="freebits">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td style="white-space: nowrap; text-align: center;"><span class="freebits">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="white-space: nowrap; text-align: left;">(8) industry</td>
|
||||
<td style="white-space: nowrap; text-align: center;"><span class="abuse">XXXX X</span><span class="freebits">OO</span><span class="abuse">X</span></td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX XXXX XXXX</td>
|
||||
<td style="white-space: nowrap; text-align: center;"><span class="freebits">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<ul>
|
||||
<li style="white-space: nowrap; text-align: left;">bubble/sugar/toffee</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;">XXXX XXXX <span class="freebits">OOOO OOOO</span></td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<ul>
|
||||
<li style="white-space: nowrap; text-align: left;">toy factory</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;">XXXX XXXX XXXX XXXX</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<ul>
|
||||
<li style="white-space: nowrap; text-align: left;">gold/copper/coal</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td style="text-align: center;">XXXX XXXX</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<ul>
|
||||
<li style="white-space: nowrap; text-align: left;">oil wells</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<ul>
|
||||
<li style="white-space: nowrap; text-align: left;">power station</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td style="text-align: center;">XXXX XX<span class="freebits">O</span>X</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="white-space: nowrap; text-align: left;">(9) tunnel</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
|
||||
<td style="white-space: nowrap; text-align: center;"><span class="freebits">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX <span class="freebits">OOOO OOOO OOO</span>X</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<ul>
|
||||
<li style="white-space: nowrap; text-align: left;">bridge</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td style="text-align: center;">XXXX XXXX</td>
|
||||
<td style="text-align: center;"><span class="abuse">XXXX XXXX</span> <span class="freebits">OOOO OOOO</span></td>
|
||||
<td style="text-align: center;">XXXX XXXX <span class="freebits">OOOO OOO</span>X</td>
|
||||
<td style="text-align: center;">XXXX XXXX</td>
|
||||
<td style="text-align: center;">XXXX XXXX</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="white-space: nowrap; text-align: left;">(10) various (HQ)</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
|
||||
<td style="white-space: nowrap; text-align: center;"><span class="freebits">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td style="white-space: nowrap; text-align: center;"><span class="freebits">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
+99
-57
@@ -1,70 +1,112 @@
|
||||
Multiplayer Manual for OpenTTD
|
||||
----------------------------------------
|
||||
Multiplayer Manual for OpenTTD (0.3.5)
|
||||
=======================================
|
||||
|
||||
1. Starting a Server
|
||||
---------------------
|
||||
|
||||
- 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 "multiplayer" on the startup screen
|
||||
- click "start server"
|
||||
- type in a game name
|
||||
- click "start game" ,"load game" or "load scenario"
|
||||
|
||||
2. Connecting to a Server
|
||||
|
||||
- click "multiplayer" on the startup screen
|
||||
|
||||
- if you want to connect to any network game in your LAN click "find server"
|
||||
|
||||
- if there were more then one server
|
||||
- select one in the list below the buttons
|
||||
- click on "join game".
|
||||
--------------------------
|
||||
|
||||
- if you want to play over the internet you should have the ip of the game server you want connect to.
|
||||
- click direct connect
|
||||
- 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 then 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 connect as an special player use #<player-no>
|
||||
|
||||
3. Connecting to a Server over the Console
|
||||
|
||||
- open the console and type in the following command:
|
||||
|
||||
- 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
|
||||
|
||||
|
||||
3. Connecting to a Server over the Console
|
||||
-------------------------------------------
|
||||
|
||||
- Open the console and type in the following command:
|
||||
|
||||
]connect <ip/host>:<port>#<player-no>
|
||||
|
||||
|
||||
4. Playing Internet-Games
|
||||
--------------------------
|
||||
|
||||
- since OpenTTD 0.3.4 you can also play internet games over higher latency connections.
|
||||
- to do this the gameservers sync frequency should be highered to a decent value.
|
||||
- open the console [on the server]
|
||||
- type in the following command:
|
||||
|
||||
] *net_sync_freq = <4-80>
|
||||
|
||||
default value: 4
|
||||
|
||||
- this is lowering the sync frequency of the server and your game should be less laggy.
|
||||
- this is a server variable: it has nothing to do with the clients
|
||||
|
||||
- you can also change when the clients ready packet is sent if you still have lags.
|
||||
- open the console
|
||||
- type in the following command:
|
||||
|
||||
] *net_ready_ahead = <1-8>
|
||||
|
||||
default value: 1
|
||||
|
||||
- in that way your client is sending its "i am ready for next sync" a bit earlier
|
||||
thats quite good for games where some players have higher latencies than the others.
|
||||
- this is a client variable: it has nothing to do with the server
|
||||
|
||||
- to change the client timeout time
|
||||
- open the console [on the server]
|
||||
- type in the following command:
|
||||
|
||||
] *net_client_timeout = <30-x>
|
||||
|
||||
default value: 300
|
||||
|
||||
- warning: a too low value will disconnect your clients if they have a short lag
|
||||
|
||||
|
||||
- Since OpenTTD 0.3.5 the network protocol has been rewritten and is very stable, even over slow connections.
|
||||
|
||||
- Server with a red dot behind it have a different version then you have. You will not be able to join those servers.
|
||||
|
||||
- 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:
|
||||
|
||||
- net_frame_freq:
|
||||
change it in console with: net_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.
|
||||
|
||||
- net_sync_freq:
|
||||
change it in console with: net_sync_freq = <number>
|
||||
the number should be between the 50 and 1000, not much lower, not much higer. 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 net_frame_freq has more effect on the bandwidth then net_sync_freq. You should never change net_sync_freq!
|
||||
|
||||
|
||||
5. 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 automaticly 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.
|
||||
- You can also do this manually via the console: 'reset_company'.
|
||||
Both ways, the company will go bankrupt.
|
||||
|
||||
- You can let your server automaticly 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, enable Advertising. To do this, select 'Internet (advertise)'
|
||||
in the Start Server menu, or type in console: 'set server_advertise 1'.
|
||||
|
||||
- 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). 1 client uses +/- 3 kb/s up and down. To decrease
|
||||
this amount, set 'net_frame_freq' to 1 for example. This will reduce it to 1.5 kb/s per client.
|
||||
|
||||
|
||||
6. Some useful things
|
||||
----------------------
|
||||
|
||||
- You can protect your company so nobody else can join uninvited. To do this, check your Company Screen
|
||||
|
||||
- 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!
|
||||
|
||||
- From 0.3.5, desyncs should not happen anymore
|
||||
|
||||
- From 0.3.5, patch-settings are also synced. You can now play without deleting openttd.cfg, and with, for example, extra large trains enabled.
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
.\" Hey, EMACS: -*- nroff -*-
|
||||
.\" First parameter, NAME, should be all caps
|
||||
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
||||
.\" other parameters are allowed: see man(7), man(1)
|
||||
.TH OPENTTD 6 "September 16, 2004"
|
||||
.\" Please adjust this date whenever revising the manpage.
|
||||
.\"
|
||||
.\" Some roff macros, for reference:
|
||||
.\" .nh disable hyphenation
|
||||
.\" .hy enable hyphenation
|
||||
.\" .ad l left justify
|
||||
.\" .ad b justify to both left and right margins
|
||||
.\" .nf disable filling
|
||||
.\" .fi enable filling
|
||||
.\" .br insert line break
|
||||
.\" .sp <n> insert n+1 empty lines
|
||||
.\" for manpage-specific macros, see man(7)
|
||||
.SH NAME
|
||||
openttd \- An open source clone of the Microprose game "Transport Tycoon Deluxe"
|
||||
.SH SYNOPSIS
|
||||
.B openttd
|
||||
.RI [ options ]
|
||||
.br
|
||||
.SH DESCRIPTION
|
||||
Unfortunately, there is no real manpage for openttd yet. Hopefully someone
|
||||
will write one soon. For now you should use
|
||||
.B openttd -h
|
||||
for more information, or check our Wiki manual: http://wiki.openttd.org/
|
||||
.PP
|
||||
.\" TeX users may be more comfortable with the \fB<whatever>\fP and
|
||||
.\" \fI<whatever>\fP escape sequences to invoke bold face and italics,
|
||||
.\" respectively.
|
||||
.\" \fBopenttd\fP is a program that...
|
||||
.SH OPTIONS
|
||||
Wouldn't we like to have something here?
|
||||
.\" below are commented out, to serve as layout examples for when somebody
|
||||
.\" does actually fill this page
|
||||
.\" .TP
|
||||
.\" .B \-h, \-\-help
|
||||
.\" Show summary of options.
|
||||
.\" .TP
|
||||
.\" .B \-v, \-\-version
|
||||
.\" Show version of program.
|
||||
.\" .SH SEE ALSO
|
||||
.\" .BR bar (1),
|
||||
.\" .BR baz (1).
|
||||
.br
|
||||
.SH AUTHOR
|
||||
This manual page was written by Matthijs Kooijman <matthijs@katherina.student.utwente.nl>,
|
||||
for the Debian project (but may be used by others).
|
||||
+38
-38
@@ -1,38 +1,38 @@
|
||||
0,9,10,2,3,13,9,9,0,10,4,15,6,11,14,1
|
||||
dark blue=0 =0
|
||||
pale_green=1 =9
|
||||
pink=2 =10
|
||||
yellow=3 =2
|
||||
red=4 =3
|
||||
light blue=5 =13
|
||||
green=6 =9
|
||||
dark green=7 =9
|
||||
blue=8 =0
|
||||
cream=9 =10
|
||||
mauve=10 =4
|
||||
purple=11 =15
|
||||
orange=12 =6
|
||||
brown=13 =11
|
||||
grey=14 =14
|
||||
white=15 =1
|
||||
|
||||
|
||||
=blue=0
|
||||
=white=1
|
||||
=yellow=2
|
||||
=red=3
|
||||
=blue=4
|
||||
=grey=5
|
||||
=orange=6
|
||||
=green=7
|
||||
=light yellow=8
|
||||
=light green=9
|
||||
=cream=10
|
||||
=brown=11
|
||||
=white=12
|
||||
=light blue=13
|
||||
=dark grey=14
|
||||
=purple=15
|
||||
=black=16
|
||||
=dark green=17=not good
|
||||
=dark grey=21
|
||||
0,9,10,2,3,13,9,9,0,10,4,15,6,11,14,1
|
||||
dark blue=0 =0
|
||||
pale_green=1 =9
|
||||
pink=2 =10
|
||||
yellow=3 =2
|
||||
red=4 =3
|
||||
light blue=5 =13
|
||||
green=6 =9
|
||||
dark green=7 =9
|
||||
blue=8 =0
|
||||
cream=9 =10
|
||||
mauve=10 =4
|
||||
purple=11 =15
|
||||
orange=12 =6
|
||||
brown=13 =11
|
||||
grey=14 =14
|
||||
white=15 =1
|
||||
|
||||
|
||||
=blue=0
|
||||
=white=1
|
||||
=yellow=2
|
||||
=red=3
|
||||
=blue=4
|
||||
=grey=5
|
||||
=orange=6
|
||||
=green=7
|
||||
=light yellow=8
|
||||
=light green=9
|
||||
=cream=10
|
||||
=brown=11
|
||||
=white=12
|
||||
=light blue=13
|
||||
=dark grey=14
|
||||
=purple=15
|
||||
=black=16
|
||||
=dark green=17=not good
|
||||
=dark grey=21
|
||||
|
||||
+2
-1
@@ -1,5 +1,6 @@
|
||||
#include "stdafx.h"
|
||||
#include "ttd.h"
|
||||
#include "table/strings.h"
|
||||
#include "viewport.h"
|
||||
#include "command.h"
|
||||
|
||||
@@ -22,7 +23,7 @@ static int32 ClearTile_Dummy(uint tile, byte flags) {
|
||||
}
|
||||
|
||||
|
||||
static void GetAcceptedCargo_Dummy(uint tile, AcceptedCargo *ac)
|
||||
static void GetAcceptedCargo_Dummy(uint tile, AcceptedCargo ac)
|
||||
{
|
||||
/* not used */
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@ VARDEF Economy _economy;
|
||||
typedef struct Subsidy {
|
||||
byte cargo_type;
|
||||
byte age;
|
||||
byte from;
|
||||
byte to;
|
||||
uint16 from;
|
||||
uint16 to;
|
||||
} Subsidy;
|
||||
|
||||
|
||||
@@ -68,8 +68,8 @@ void UpdatePlayerHouse(Player *p, uint score);
|
||||
|
||||
VARDEF Subsidy _subsidies[MAX_PLAYERS];
|
||||
Pair SetupSubsidyDecodeParam(Subsidy *s, bool mode);
|
||||
void DeleteSubsidyWithIndustry(byte index);
|
||||
void DeleteSubsidyWithStation(byte index);
|
||||
void DeleteSubsidyWithIndustry(uint16 index);
|
||||
void DeleteSubsidyWithStation(uint16 index);
|
||||
void RemoteSubsidyAdd(Subsidy *s_new);
|
||||
|
||||
int32 GetTransportedGoodsIncome(uint num_pieces, uint dist, byte transit_days, byte cargo_type);
|
||||
|
||||
+10
-2
@@ -8,10 +8,18 @@
|
||||
// that says or TTD_LITTLE_ENDIAN, or TTD_BIG_ENDIAN. Makefile takes
|
||||
// care of the real writing to the file.
|
||||
|
||||
int main () {
|
||||
int main (int argc, char *argv[]) {
|
||||
unsigned char EndianTest[2] = { 1, 0 };
|
||||
int force_BE = 0, force_LE = 0;
|
||||
|
||||
if (argc > 1 && strcmp(argv[1], "BE") == 0)
|
||||
force_BE = 1;
|
||||
if (argc > 1 && strcmp(argv[1], "LE") == 0)
|
||||
force_LE = 1;
|
||||
|
||||
printf("#ifndef ENDIAN_H\n#define ENDIAN_H\n");
|
||||
if( *(short *) EndianTest == 1 )
|
||||
|
||||
if ( (*(short *) EndianTest == 1 && force_BE != 1) || force_LE == 1)
|
||||
printf("#define TTD_LITTLE_ENDIAN\n");
|
||||
else
|
||||
printf("#define TTD_BIG_ENDIAN\n");
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
#include "stdafx.h"
|
||||
#include "ttd.h"
|
||||
#include "debug.h"
|
||||
#include "table/strings.h"
|
||||
#include "engine.h"
|
||||
#include "table/engines.h"
|
||||
#include "gfx.h"
|
||||
#include "player.h"
|
||||
#include "command.h"
|
||||
#include "vehicle.h"
|
||||
#include "news.h"
|
||||
#include "saveload.h"
|
||||
#include "sprite.h"
|
||||
|
||||
#define UPDATE_PLAYER_RAILTYPE(e,p) if ((byte)(e->railtype + 1) > p->max_railtype) p->max_railtype = e->railtype + 1;
|
||||
|
||||
@@ -16,43 +20,83 @@ enum {
|
||||
ENGINE_PREVIEWING = 4,
|
||||
};
|
||||
|
||||
/* This maps per-landscape cargo ids to globally unique cargo ids usable ie. in
|
||||
* the custom GRF files. It is basically just a transcribed table from
|
||||
* TTDPatch's newgrf.txt. */
|
||||
byte _global_cargo_id[NUM_LANDSCAPE][NUM_CARGO] = {
|
||||
/* LT_NORMAL */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12 },
|
||||
/* LT_HILLY */ { 0, 1, 2, 3, 4, 5, 6, 7, 28, 11, 10, 12 },
|
||||
/* LT_DESERT */ { 0, 16, 2, 3, 13, 5, 6, 7, 14, 15, 10, 12 },
|
||||
/* LT_CANDY */ { 0, 17, 2, 18, 19, 20, 21, 22, 23, 24, 25, 26 },
|
||||
// 27 is paper in temperate climate in TTDPatch
|
||||
// Following can be renumbered:
|
||||
// 29 is the default cargo for the purpose of spritesets
|
||||
// 30 is the purchase list image (the equivalent of 0xff) for the purpose of spritesets
|
||||
/** TRANSLATE FROM LOCAL CARGO TO GLOBAL CARGO ID'S.
|
||||
* This maps the per-landscape cargo ID's to globally unique cargo ID's usable ie. in
|
||||
* the custom GRF files. It is basically just a transcribed table from TTDPatch's newgrf.txt.
|
||||
*/
|
||||
const CargoID _global_cargo_id[NUM_LANDSCAPE][NUM_CARGO] = {
|
||||
/* LT_NORMAL */ {GC_PASSENGERS, GC_COAL, GC_MAIL, GC_OIL, GC_LIVESTOCK, GC_GOODS, GC_GRAIN, GC_WOOD, GC_IRON_ORE, GC_STEEL, GC_VALUABLES, GC_PAPER_TEMP},
|
||||
/* LT_HILLY */ {GC_PASSENGERS, GC_COAL, GC_MAIL, GC_OIL, GC_LIVESTOCK, GC_GOODS, GC_GRAIN, GC_WOOD, GC_INVALID, GC_PAPER, GC_VALUABLES, GC_FOOD },
|
||||
/* LT_DESERT */ {GC_PASSENGERS, GC_RUBBER,GC_MAIL, GC_OIL, GC_FRUIT, GC_GOODS, GC_GRAIN, GC_WOOD, GC_COPPER_ORE, GC_WATER, GC_VALUABLES, GC_FOOD },
|
||||
/* LT_CANDY */ {GC_PASSENGERS, GC_SUGAR, GC_MAIL, GC_TOYS,GC_BATTERIES, GC_CANDY, GC_TOFFEE,GC_COLA, GC_COTTON_CANDY,GC_BUBBLES,GC_PLASTIC, GC_FIZZY_DRINKS },
|
||||
/**
|
||||
* - GC_INVALID (255) means that cargo is not available for that climate
|
||||
* - GC_PAPER_TEMP (27) is paper in temperate climate in TTDPatch
|
||||
* Following can be renumbered:
|
||||
* - GC_DEFAULT (29) is the defa ult cargo for the purpose of spritesets
|
||||
* - GC_PURCHASE (30) is the purchase list image (the equivalent of 0xff) for the purpose of spritesets
|
||||
*/
|
||||
};
|
||||
|
||||
/* These two arrays provide a reverse mapping. */
|
||||
byte _local_cargo_id_ctype[NUM_CID] = {
|
||||
CT_PASSENGERS, CT_COAL, CT_MAIL, CT_OIL, CT_LIVESTOCK, CT_GOODS, CT_GRAIN, CT_WOOD, // 0-7
|
||||
CT_IRON_ORE, CT_STEEL, CT_VALUABLES, CT_PAPER, CT_FOOD, CT_FRUIT, CT_COPPER_ORE, CT_WATER, // 8-15
|
||||
CT_RUBBER, CT_SUGAR, CT_TOYS, CT_BATTERIES, CT_CANDY, CT_TOFFEE, CT_COLA, CT_COTTON_CANDY, // 16-23
|
||||
CT_BUBBLES, CT_PLASTIC, CT_FIZZY_DRINKS, CT_PAPER /* unsup. */, CT_HILLY_UNUSED // 24-28
|
||||
/** BEGIN --- TRANSLATE FROM GLOBAL CARGO TO LOCAL CARGO ID'S **/
|
||||
/** Map global cargo ID's to local-cargo ID's */
|
||||
const CargoID _local_cargo_id_ctype[NUM_GLOBAL_CID] = {
|
||||
CT_PASSENGERS,CT_COAL, CT_MAIL, CT_OIL, CT_LIVESTOCK,CT_GOODS, CT_GRAIN, CT_WOOD, /* 0- 7 */
|
||||
CT_IRON_ORE, CT_STEEL, CT_VALUABLES, CT_PAPER, CT_FOOD, CT_FRUIT, CT_COPPER_ORE, CT_WATER, /* 8-15 */
|
||||
CT_RUBBER, CT_SUGAR, CT_TOYS, CT_BATTERIES,CT_CANDY, CT_TOFFEE, CT_COLA, CT_COTTON_CANDY, /* 16-23 */
|
||||
CT_BUBBLES, CT_PLASTIC,CT_FIZZY_DRINKS,CT_PAPER /* unsup. */,CT_HILLY_UNUSED, /* 24-28 */
|
||||
CT_INVALID, CT_INVALID /* 29-30 */
|
||||
};
|
||||
|
||||
/* LT'th bit is set of the particular landscape if cargo available there.
|
||||
* 1: LT_NORMAL, 2: LT_HILLY, 4: LT_DESERT, 8: LT_CANDY */
|
||||
byte _local_cargo_id_landscape[NUM_CID] = {
|
||||
15, 3, 15, 7, 3, 7, 7, 7, 1, 1, 7, 2, 7, // 0-12
|
||||
4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 1, 2, // 13-28
|
||||
#define MC(cargo) (1 << cargo)
|
||||
/** Bitmasked value where the global cargo ID is available in landscape
|
||||
* 0: LT_NORMAL, 1: LT_HILLY, 2: LT_DESERT, 3: LT_CANDY */
|
||||
const uint32 _landscape_global_cargo_mask[NUM_LANDSCAPE] =
|
||||
{ /* LT_NORMAL: temperate */
|
||||
MC(GC_PASSENGERS)|MC(GC_COAL)|MC(GC_MAIL)|MC(GC_OIL)|MC(GC_LIVESTOCK)|MC(GC_GOODS)|MC(GC_GRAIN)|MC(GC_WOOD)|
|
||||
MC(GC_IRON_ORE)|MC(GC_STEEL)|MC(GC_VALUABLES)|MC(GC_FOOD)|MC(GC_UNDEFINED),
|
||||
/* LT_HILLY: arctic */
|
||||
MC(GC_PASSENGERS)|MC(GC_COAL)|MC(GC_MAIL)|MC(GC_OIL)|MC(GC_LIVESTOCK)|MC(GC_GOODS)|
|
||||
MC(GC_GRAIN)|MC(GC_WOOD)|MC(GC_VALUABLES)|MC(GC_PAPER)|MC(GC_FOOD)|MC(GC_UNDEFINED),
|
||||
/* LT_DESERT: rainforest/desert */
|
||||
MC(GC_PASSENGERS)|MC(GC_MAIL)|MC(GC_OIL)|MC(GC_GOODS)|MC(GC_GRAIN)|MC(GC_WOOD)|
|
||||
MC(GC_VALUABLES)|MC(GC_FOOD)|MC(GC_FRUIT)|MC(GC_COPPER_ORE)|MC(GC_WATER)|MC(GC_RUBBER),
|
||||
/* LT_CANDY: toyland */
|
||||
MC(GC_PASSENGERS)|MC(GC_MAIL)|MC(GC_SUGAR)|MC(GC_TOYS)|MC(GC_BATTERIES)|MC(GC_CANDY)|
|
||||
MC(GC_TOFFEE)|MC(GC_COLA)|MC(GC_COTTON_CANDY)|MC(GC_BUBBLES)|MC(GC_PLASTIC)|MC(GC_FIZZY_DRINKS)
|
||||
};
|
||||
/** END --- TRANSLATE FROM GLOBAL CARGO TO LOCAL CARGO ID'S **/
|
||||
|
||||
/** Bitmasked values of what type of cargo is refittable for the given vehicle-type.
|
||||
* This coupled with the landscape information (_landscape_global_cargo_mask) gives
|
||||
* us exactly what is refittable and what is not */
|
||||
const uint32 _default_refitmasks[NUM_VEHICLE_TYPES] = {
|
||||
/* Trains */
|
||||
MC(GC_PASSENGERS)|MC(GC_COAL)|MC(GC_MAIL)|MC(GC_LIVESTOCK)|MC(GC_GOODS)|MC(GC_GRAIN)|MC(GC_WOOD)|MC(GC_IRON_ORE)|
|
||||
MC(GC_STEEL)|MC(GC_VALUABLES)|MC(GC_PAPER)|MC(GC_FOOD)|MC(GC_FRUIT)|MC(GC_COPPER_ORE)|MC(GC_WATER)|MC(GC_SUGAR)|
|
||||
MC(GC_TOYS)|MC(GC_CANDY)|MC(GC_TOFFEE)|MC(GC_COLA)|MC(GC_COTTON_CANDY)|MC(GC_BUBBLES)|MC(GC_PLASTIC)|MC(GC_FIZZY_DRINKS),
|
||||
/* Road vehicles (not refittable by default) */
|
||||
0,
|
||||
/* Ships */
|
||||
MC(GC_COAL)|MC(GC_MAIL)|MC(GC_LIVESTOCK)|MC(GC_GOODS)|MC(GC_GRAIN)|MC(GC_WOOD)|MC(GC_IRON_ORE)|MC(GC_STEEL)|MC(GC_VALUABLES)|
|
||||
MC(GC_PAPER)|MC(GC_FOOD)|MC(GC_FRUIT)|MC(GC_COPPER_ORE)|MC(GC_WATER)|MC(GC_RUBBER)|MC(GC_SUGAR)|MC(GC_TOYS)|MC(GC_BATTERIES)|
|
||||
MC(GC_CANDY)|MC(GC_TOFFEE)|MC(GC_COLA)|MC(GC_COTTON_CANDY)|MC(GC_BUBBLES)|MC(GC_PLASTIC)|MC(GC_FIZZY_DRINKS),
|
||||
/* Aircraft */
|
||||
MC(GC_PASSENGERS)|MC(GC_MAIL)|MC(GC_GOODS)|MC(GC_VALUABLES)|MC(GC_FOOD)|MC(GC_FRUIT)|MC(GC_SUGAR)|MC(GC_TOYS)|
|
||||
MC(GC_BATTERIES)|MC(GC_CANDY)|MC(GC_TOFFEE)|MC(GC_COLA)|MC(GC_COTTON_CANDY)|MC(GC_BUBBLES)|MC(GC_PLASTIC)|MC(GC_FIZZY_DRINKS),
|
||||
/* Special/Disaster */
|
||||
0,0
|
||||
};
|
||||
#undef MC
|
||||
|
||||
void ShowEnginePreviewWindow(int engine);
|
||||
|
||||
void DeleteCustomEngineNames()
|
||||
void DeleteCustomEngineNames(void)
|
||||
{
|
||||
uint i;
|
||||
StringID old;
|
||||
|
||||
for(i=0; i!=TOTAL_NUM_ENGINES; i++) {
|
||||
for (i = 0; i != TOTAL_NUM_ENGINES; i++) {
|
||||
old = _engine_name_strings[i];
|
||||
_engine_name_strings[i] = i + STR_8000_KIRBY_PAUL_TANK_STEAM;
|
||||
DeleteName(old);
|
||||
@@ -61,24 +105,24 @@ void DeleteCustomEngineNames()
|
||||
_vehicle_design_names &= ~1;
|
||||
}
|
||||
|
||||
void LoadCustomEngineNames()
|
||||
void LoadCustomEngineNames(void)
|
||||
{
|
||||
// XXX: not done */
|
||||
DEBUG(misc, 1) ("LoadCustomEngineNames: not done");
|
||||
}
|
||||
|
||||
static void SetupEngineNames()
|
||||
static void SetupEngineNames(void)
|
||||
{
|
||||
uint i;
|
||||
StringID *name;
|
||||
|
||||
for(i=0; i!=TOTAL_NUM_ENGINES; i++)
|
||||
_engine_name_strings[i] = STR_SV_EMPTY;
|
||||
for (name = _engine_name_strings; name != endof(_engine_name_strings); name++)
|
||||
*name = STR_SV_EMPTY;
|
||||
|
||||
DeleteCustomEngineNames();
|
||||
LoadCustomEngineNames();
|
||||
}
|
||||
|
||||
static void AdjustAvailAircraft()
|
||||
static void AdjustAvailAircraft(void)
|
||||
{
|
||||
uint16 date = _date;
|
||||
byte avail = 0;
|
||||
@@ -105,21 +149,47 @@ static void CalcEngineReliability(Engine *e)
|
||||
uint max = e->reliability_max;
|
||||
e->reliability = (int)age * (int)(e->reliability_final - max) / e->duration_phase_3 + max;
|
||||
} else {
|
||||
e->player_avail = _patches.never_expire_vehicles ? -1 : 0;
|
||||
// time's up for this engine
|
||||
// make it either available to all players (if never_expire_vehicles is enabled and if it was available earlier)
|
||||
// or disable this engine completely
|
||||
e->player_avail = (_patches.never_expire_vehicles && e->player_avail)? -1 : 0;
|
||||
e->reliability = e->reliability_final;
|
||||
}
|
||||
}
|
||||
|
||||
void StartupEngines()
|
||||
void AddTypeToEngines(void)
|
||||
{
|
||||
Engine *e;
|
||||
uint32 counter = 0;
|
||||
|
||||
for(e=_engines; e != endof(_engines); e++, counter++) {
|
||||
|
||||
e->type = VEH_Train;
|
||||
if (counter >= ROAD_ENGINES_INDEX) {
|
||||
e->type = VEH_Road;
|
||||
if (counter >= SHIP_ENGINES_INDEX) {
|
||||
e->type = VEH_Ship;
|
||||
if (counter >= AIRCRAFT_ENGINES_INDEX) {
|
||||
e->type = VEH_Aircraft;
|
||||
if (counter >= TOTAL_NUM_ENGINES) {
|
||||
e->type = VEH_Special;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StartupEngines(void)
|
||||
{
|
||||
Engine *e;
|
||||
const EngineInfo *ei;
|
||||
uint32 r;
|
||||
uint32 r, counter = 0;
|
||||
|
||||
SetupEngineNames();
|
||||
|
||||
for(e=_engines, ei=_engine_info; e != endof(_engines); e++, ei++, counter++) {
|
||||
|
||||
for(e=_engines, ei=_engine_info; e != endof(_engines); e++,ei++) {
|
||||
e->age = 0;
|
||||
e->railtype = ei->railtype_climates >> 4;
|
||||
e->flags = 0;
|
||||
@@ -159,109 +229,338 @@ void StartupEngines()
|
||||
e->flags |= ENGINE_AVAILABLE;
|
||||
e->player_avail = 0;
|
||||
}
|
||||
|
||||
/* This sets up type for the engine
|
||||
It is needed if you want to ask the engine what type it is
|
||||
It should hopefully be the same as when you ask a vehicle what it is
|
||||
but using this, you can ask what type an engine number is
|
||||
even if it is not a vehicle (yet)*/
|
||||
}
|
||||
|
||||
AdjustAvailAircraft();
|
||||
}
|
||||
|
||||
uint32 _engine_refit_masks[256];
|
||||
uint32 _engine_refit_masks[TOTAL_NUM_ENGINES];
|
||||
|
||||
|
||||
// TODO: We don't support cargo-specific wagon overrides. Pretty exotic... ;-) --pasky
|
||||
|
||||
struct WagonOverride {
|
||||
typedef struct WagonOverride {
|
||||
byte *train_id;
|
||||
int trains;
|
||||
struct SpriteSuperSet superset;
|
||||
};
|
||||
SpriteGroup group;
|
||||
} WagonOverride;
|
||||
|
||||
static struct WagonOverrides {
|
||||
typedef struct WagonOverrides {
|
||||
int overrides_count;
|
||||
struct WagonOverride *overrides;
|
||||
} _engine_wagon_overrides[256];
|
||||
WagonOverride *overrides;
|
||||
} WagonOverrides;
|
||||
|
||||
void SetWagonOverrideSprites(byte engine, struct SpriteSuperSet *superset,
|
||||
byte *train_id, int trains)
|
||||
static WagonOverrides _engine_wagon_overrides[TOTAL_NUM_ENGINES];
|
||||
|
||||
void SetWagonOverrideSprites(byte engine, SpriteGroup *group, byte *train_id,
|
||||
int trains)
|
||||
{
|
||||
struct WagonOverrides *wos;
|
||||
struct WagonOverride *wo;
|
||||
WagonOverrides *wos;
|
||||
WagonOverride *wo;
|
||||
|
||||
wos = &_engine_wagon_overrides[engine];
|
||||
wos->overrides_count++;
|
||||
wos->overrides = realloc(wos->overrides,
|
||||
wos->overrides_count * sizeof(struct WagonOverride));
|
||||
wos->overrides_count * sizeof(*wos->overrides));
|
||||
|
||||
wo = &wos->overrides[wos->overrides_count - 1];
|
||||
wo->superset = *superset;
|
||||
/* FIXME: If we are replacing an override, release original SpriteGroup
|
||||
* to prevent leaks. But first we need to refcount the SpriteGroup.
|
||||
* --pasky */
|
||||
wo->group = *group;
|
||||
wo->trains = trains;
|
||||
wo->train_id = malloc(trains);
|
||||
memcpy(wo->train_id, train_id, trains);
|
||||
}
|
||||
|
||||
static struct SpriteSuperSet *GetWagonOverrideSpriteSet(byte engine, byte overriding_engine)
|
||||
static SpriteGroup *GetWagonOverrideSpriteSet(byte engine, byte overriding_engine)
|
||||
{
|
||||
struct WagonOverrides *wos = &_engine_wagon_overrides[engine];
|
||||
WagonOverrides *wos = &_engine_wagon_overrides[engine];
|
||||
int i;
|
||||
|
||||
// XXX: This could turn out to be a timesink on profiles. We could always just
|
||||
// dedicate 65535 bytes for an [engine][train] trampoline.
|
||||
// XXX: This could turn out to be a timesink on profiles. We could
|
||||
// always just dedicate 65535 bytes for an [engine][train] trampoline
|
||||
// for O(1). Or O(logMlogN) and searching binary tree or smt. like
|
||||
// that. --pasky
|
||||
|
||||
for (i = 0; i < wos->overrides_count; i++) {
|
||||
struct WagonOverride *wo = &wos->overrides[i];
|
||||
WagonOverride *wo = &wos->overrides[i];
|
||||
int j;
|
||||
|
||||
for (j = 0; j < wo->trains; j++) {
|
||||
if (wo->train_id[j] == overriding_engine)
|
||||
return &wo->superset;
|
||||
return &wo->group;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
byte _engine_original_sprites[256];
|
||||
byte _engine_original_sprites[TOTAL_NUM_ENGINES];
|
||||
// 0 - 28 are cargos, 29 is default, 30 is the advert (purchase list)
|
||||
// (It isn't and shouldn't be like this in the GRF files since new cargo types
|
||||
// may appear in future - however it's more convenient to store it like this in
|
||||
// memory. --pasky)
|
||||
static struct SpriteSuperSet _engine_custom_sprites[256][NUM_CID];
|
||||
static SpriteGroup _engine_custom_sprites[TOTAL_NUM_ENGINES][NUM_GLOBAL_CID];
|
||||
|
||||
void SetCustomEngineSprites(byte engine, byte cargo, struct SpriteSuperSet *superset)
|
||||
void SetCustomEngineSprites(byte engine, byte cargo, SpriteGroup *group)
|
||||
{
|
||||
assert(superset->sprites_per_set == 4 || superset->sprites_per_set == 8);
|
||||
_engine_custom_sprites[engine][cargo] = *superset;
|
||||
/* FIXME: If we are replacing an override, release original SpriteGroup
|
||||
* to prevent leaks. But first we need to refcount the SpriteGroup.
|
||||
* --pasky */
|
||||
_engine_custom_sprites[engine][cargo] = *group;
|
||||
}
|
||||
|
||||
int GetCustomEngineSprite(byte engine, uint16 overriding_engine, byte cargo,
|
||||
byte loaded, byte in_motion, byte direction)
|
||||
typedef RealSpriteGroup *(*resolve_callback)(SpriteGroup *spritegroup,
|
||||
const Vehicle *veh, void *callback); /* XXX data pointer used as function pointer */
|
||||
|
||||
static RealSpriteGroup* ResolveVehicleSpriteGroup(SpriteGroup *spritegroup,
|
||||
const Vehicle *veh, resolve_callback callback)
|
||||
{
|
||||
struct SpriteSuperSet *superset = &_engine_custom_sprites[engine][cargo];
|
||||
//debug("spgt %d", spritegroup->type);
|
||||
switch (spritegroup->type) {
|
||||
case SGT_REAL:
|
||||
return &spritegroup->g.real;
|
||||
|
||||
case SGT_DETERMINISTIC: {
|
||||
DeterministicSpriteGroup *dsg = &spritegroup->g.determ;
|
||||
SpriteGroup *target;
|
||||
int value = -1;
|
||||
|
||||
//debug("[%p] Having fun resolving variable %x", veh, dsg->variable);
|
||||
|
||||
if ((dsg->variable >> 6) == 0) {
|
||||
/* General property */
|
||||
value = GetDeterministicSpriteValue(dsg->variable);
|
||||
} else {
|
||||
/* Vehicle-specific property. */
|
||||
|
||||
if (veh == NULL) {
|
||||
/* We are in a purchase list of something,
|
||||
* and we are checking for something undefined.
|
||||
* That means we should get the first target
|
||||
* (NOT the default one). */
|
||||
if (dsg->num_ranges > 0) {
|
||||
target = &dsg->ranges[0].group;
|
||||
} else {
|
||||
target = dsg->default_group;
|
||||
}
|
||||
return callback(target, NULL, callback);
|
||||
}
|
||||
|
||||
if (dsg->var_scope == VSG_SCOPE_PARENT) {
|
||||
/* First engine in the vehicle chain */
|
||||
if (veh->type == VEH_Train)
|
||||
veh = GetFirstVehicleInChain(veh);
|
||||
}
|
||||
|
||||
if (dsg->variable == 0x40) {
|
||||
if (veh->type == VEH_Train) {
|
||||
Vehicle *u = GetFirstVehicleInChain(veh);
|
||||
byte chain_before = 0, chain_after = 0;
|
||||
|
||||
while (u != veh) {
|
||||
u = u->next;
|
||||
chain_before++;
|
||||
}
|
||||
while (u->next != NULL) {
|
||||
u = u->next;
|
||||
chain_after++;
|
||||
};
|
||||
|
||||
value = chain_before | chain_after << 8
|
||||
| (chain_before + chain_after) << 16;
|
||||
} else {
|
||||
value = 1; /* 1 vehicle in the chain */
|
||||
}
|
||||
|
||||
} else {
|
||||
// TTDPatch runs on little-endian arch;
|
||||
// Variable is 0x80 + offset in TTD's vehicle structure
|
||||
switch (dsg->variable - 0x80) {
|
||||
#define veh_prop(id_, value_) case (id_): value = (value_); break
|
||||
veh_prop(0x00, veh->type);
|
||||
veh_prop(0x01, veh->subtype);
|
||||
veh_prop(0x04, veh->index);
|
||||
veh_prop(0x05, veh->index & 0xFF);
|
||||
/* XXX? Is THIS right? */
|
||||
veh_prop(0x0A, PackOrder(&veh->current_order));
|
||||
veh_prop(0x0B, PackOrder(&veh->current_order) & 0xff);
|
||||
veh_prop(0x0C, veh->num_orders);
|
||||
veh_prop(0x0D, veh->cur_order_index);
|
||||
veh_prop(0x10, veh->load_unload_time_rem);
|
||||
veh_prop(0x11, veh->load_unload_time_rem & 0xFF);
|
||||
veh_prop(0x12, veh->date_of_last_service);
|
||||
veh_prop(0x13, veh->date_of_last_service & 0xFF);
|
||||
veh_prop(0x14, veh->service_interval);
|
||||
veh_prop(0x15, veh->service_interval & 0xFF);
|
||||
veh_prop(0x16, veh->last_station_visited);
|
||||
veh_prop(0x17, veh->tick_counter);
|
||||
veh_prop(0x18, veh->max_speed);
|
||||
veh_prop(0x19, veh->max_speed & 0xFF);
|
||||
veh_prop(0x1F, veh->direction);
|
||||
veh_prop(0x28, veh->cur_image);
|
||||
veh_prop(0x29, veh->cur_image & 0xFF);
|
||||
veh_prop(0x32, veh->vehstatus);
|
||||
veh_prop(0x33, veh->vehstatus);
|
||||
veh_prop(0x34, veh->cur_speed);
|
||||
veh_prop(0x35, veh->cur_speed & 0xFF);
|
||||
veh_prop(0x36, veh->subspeed);
|
||||
veh_prop(0x37, veh->acceleration);
|
||||
veh_prop(0x39, veh->cargo_type);
|
||||
veh_prop(0x3A, veh->cargo_cap);
|
||||
veh_prop(0x3B, veh->cargo_cap & 0xFF);
|
||||
veh_prop(0x3C, veh->cargo_count);
|
||||
veh_prop(0x3D, veh->cargo_count & 0xFF);
|
||||
veh_prop(0x3E, veh->cargo_source); // Probably useless; so what
|
||||
veh_prop(0x3F, veh->cargo_days);
|
||||
veh_prop(0x40, veh->age);
|
||||
veh_prop(0x41, veh->age & 0xFF);
|
||||
veh_prop(0x42, veh->max_age);
|
||||
veh_prop(0x43, veh->max_age & 0xFF);
|
||||
veh_prop(0x44, veh->build_year);
|
||||
veh_prop(0x45, veh->unitnumber);
|
||||
veh_prop(0x46, veh->engine_type);
|
||||
veh_prop(0x47, veh->engine_type & 0xFF);
|
||||
veh_prop(0x48, veh->spritenum);
|
||||
veh_prop(0x49, veh->day_counter);
|
||||
veh_prop(0x4A, veh->breakdowns_since_last_service);
|
||||
veh_prop(0x4B, veh->breakdown_ctr);
|
||||
veh_prop(0x4C, veh->breakdown_delay);
|
||||
veh_prop(0x4D, veh->breakdown_chance);
|
||||
veh_prop(0x4E, veh->reliability);
|
||||
veh_prop(0x4F, veh->reliability & 0xFF);
|
||||
veh_prop(0x50, veh->reliability_spd_dec);
|
||||
veh_prop(0x51, veh->reliability_spd_dec & 0xFF);
|
||||
veh_prop(0x52, veh->profit_this_year);
|
||||
veh_prop(0x53, veh->profit_this_year & 0xFFFFFF);
|
||||
veh_prop(0x54, veh->profit_this_year & 0xFFFF);
|
||||
veh_prop(0x55, veh->profit_this_year & 0xFF);
|
||||
veh_prop(0x56, veh->profit_last_year);
|
||||
veh_prop(0x57, veh->profit_last_year & 0xFF);
|
||||
veh_prop(0x58, veh->profit_last_year);
|
||||
veh_prop(0x59, veh->profit_last_year & 0xFF);
|
||||
/* veh_prop(0x5A, veh->next_in_chain_old);
|
||||
veh_prop(0x5B, veh->next_in_chain_old & 0xFF);*/
|
||||
veh_prop(0x5C, veh->value);
|
||||
veh_prop(0x5D, veh->value & 0xFFFFFF);
|
||||
veh_prop(0x5E, veh->value & 0xFFFF);
|
||||
veh_prop(0x5F, veh->value & 0xFF);
|
||||
veh_prop(0x60, veh->string_id);
|
||||
veh_prop(0x61, veh->string_id & 0xFF);
|
||||
/* 00h..07h=sub image? 40h=in tunnel; actually some kind of status
|
||||
* aircraft: >=13h when in flight
|
||||
* train, ship: 80h=in depot
|
||||
* rv: 0feh=in depot */
|
||||
/* TODO veh_prop(0x62, veh->???); */
|
||||
|
||||
/* TODO: The rest is per-vehicle, I hope no GRF file looks so far.
|
||||
* But they won't let us have an easy ride so surely *some* GRF
|
||||
* file does. So someone needs to do this too. --pasky */
|
||||
|
||||
#undef veh_prop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
target = value != -1 ? EvalDeterministicSpriteGroup(dsg, value) : dsg->default_group;
|
||||
//debug("Resolved variable %x: %d, %p", dsg->variable, value, callback);
|
||||
return callback(target, veh, callback);
|
||||
}
|
||||
|
||||
case SGT_RANDOMIZED: {
|
||||
RandomizedSpriteGroup *rsg = &spritegroup->g.random;
|
||||
|
||||
if (veh == NULL) {
|
||||
/* Purchase list of something. Show the first one. */
|
||||
assert(rsg->num_groups > 0);
|
||||
//debug("going for %p: %d", rsg->groups[0], rsg->groups[0].type);
|
||||
return callback(&rsg->groups[0], NULL, callback);
|
||||
}
|
||||
|
||||
if (rsg->var_scope == VSG_SCOPE_PARENT) {
|
||||
/* First engine in the vehicle chain */
|
||||
if (veh->type == VEH_Train)
|
||||
veh = GetFirstVehicleInChain(veh);
|
||||
}
|
||||
|
||||
return callback(EvalRandomizedSpriteGroup(rsg, veh->random_bits), veh, callback);
|
||||
}
|
||||
|
||||
default:
|
||||
error("I don't know how to handle such a spritegroup %d!", spritegroup->type);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static SpriteGroup *GetVehicleSpriteGroup(byte engine, const Vehicle *v)
|
||||
{
|
||||
SpriteGroup *group;
|
||||
byte cargo = GC_PURCHASE;
|
||||
|
||||
if (v != NULL) {
|
||||
cargo = _global_cargo_id[_opt.landscape][v->cargo_type];
|
||||
assert(cargo != GC_INVALID);
|
||||
}
|
||||
|
||||
group = &_engine_custom_sprites[engine][cargo];
|
||||
|
||||
if (v != NULL && v->type == VEH_Train) {
|
||||
SpriteGroup *overset = GetWagonOverrideSpriteSet(engine, v->u.rail.first_engine);
|
||||
|
||||
if (overset != NULL) group = overset;
|
||||
}
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
int GetCustomEngineSprite(byte engine, const Vehicle *v, byte direction)
|
||||
{
|
||||
SpriteGroup *group;
|
||||
RealSpriteGroup *rsg;
|
||||
byte cargo = GC_PURCHASE;
|
||||
byte loaded = 0;
|
||||
bool in_motion = 0;
|
||||
int totalsets, spriteset;
|
||||
int r;
|
||||
|
||||
if (overriding_engine != 0xffff) {
|
||||
struct SpriteSuperSet *overset;
|
||||
if (v != NULL) {
|
||||
int capacity = v->cargo_cap;
|
||||
|
||||
overset = GetWagonOverrideSpriteSet(engine, overriding_engine);
|
||||
if (overset) superset = overset;
|
||||
cargo = _global_cargo_id[_opt.landscape][v->cargo_type];
|
||||
assert(cargo != GC_INVALID);
|
||||
|
||||
if (capacity == 0) capacity = 1;
|
||||
loaded = (v->cargo_count * 100) / capacity;
|
||||
in_motion = (v->cur_speed != 0);
|
||||
}
|
||||
|
||||
if (!superset->sprites_per_set && cargo != 29) {
|
||||
// This superset is empty but perhaps there'll be a default one.
|
||||
superset = &_engine_custom_sprites[engine][29];
|
||||
group = GetVehicleSpriteGroup(engine, v);
|
||||
rsg = ResolveVehicleSpriteGroup(group, v, (resolve_callback) ResolveVehicleSpriteGroup);
|
||||
|
||||
if (rsg->sprites_per_set == 0 && cargo != 29) { /* XXX magic number */
|
||||
// This group is empty but perhaps there'll be a default one.
|
||||
rsg = ResolveVehicleSpriteGroup(&_engine_custom_sprites[engine][29], v,
|
||||
(resolve_callback) ResolveVehicleSpriteGroup);
|
||||
}
|
||||
|
||||
if (!superset->sprites_per_set) {
|
||||
// This superset is empty. This function users should therefore
|
||||
if (!rsg->sprites_per_set) {
|
||||
// This group is empty. This function users should therefore
|
||||
// look up the sprite number in _engine_original_sprites.
|
||||
return 0;
|
||||
}
|
||||
|
||||
direction %= 8;
|
||||
if (superset->sprites_per_set == 4)
|
||||
if (rsg->sprites_per_set == 4)
|
||||
direction %= 4;
|
||||
|
||||
totalsets = in_motion ? superset->loaded_count : superset->loading_count;
|
||||
totalsets = in_motion ? rsg->loaded_count : rsg->loading_count;
|
||||
|
||||
// My aim here is to make it possible to visually determine absolutely
|
||||
// empty and totally full vehicles. --pasky
|
||||
@@ -278,106 +577,221 @@ int GetCustomEngineSprite(byte engine, uint16 overriding_engine, byte cargo,
|
||||
spriteset--;
|
||||
}
|
||||
|
||||
r = (in_motion ? superset->loaded[spriteset] : superset->loading[spriteset]) + direction;
|
||||
r = (in_motion ? rsg->loaded[spriteset] : rsg->loading[spriteset]) + direction;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
static char *_engine_custom_names[256];
|
||||
// Global variables are evil, yes, but we would end up with horribly overblown
|
||||
// calling convention otherwise and this should be 100% reentrant.
|
||||
static byte _vsg_random_triggers;
|
||||
static byte _vsg_bits_to_reseed;
|
||||
|
||||
void SetCustomEngineName(int engine, char *name)
|
||||
extern int _custom_sprites_base;
|
||||
|
||||
static RealSpriteGroup *TriggerVehicleSpriteGroup(SpriteGroup *spritegroup,
|
||||
Vehicle *veh, resolve_callback callback)
|
||||
{
|
||||
if (spritegroup->type == SGT_RANDOMIZED) {
|
||||
_vsg_bits_to_reseed |= RandomizedSpriteGroupTriggeredBits(
|
||||
&spritegroup->g.random,
|
||||
_vsg_random_triggers,
|
||||
&veh->waiting_triggers
|
||||
);
|
||||
}
|
||||
|
||||
return ResolveVehicleSpriteGroup(spritegroup, veh, callback);
|
||||
}
|
||||
|
||||
static void DoTriggerVehicle(Vehicle *veh, VehicleTrigger trigger, byte base_random_bits, bool first)
|
||||
{
|
||||
RealSpriteGroup *rsg;
|
||||
byte new_random_bits;
|
||||
|
||||
_vsg_random_triggers = trigger;
|
||||
_vsg_bits_to_reseed = 0;
|
||||
rsg = TriggerVehicleSpriteGroup(GetVehicleSpriteGroup(veh->engine_type, veh), veh,
|
||||
(resolve_callback) TriggerVehicleSpriteGroup);
|
||||
if (rsg->sprites_per_set == 0 && veh->cargo_type != 29) { /* XXX magic number */
|
||||
// This group turned out to be empty but perhaps there'll be a default one.
|
||||
rsg = TriggerVehicleSpriteGroup(&_engine_custom_sprites[veh->engine_type][29], veh,
|
||||
(resolve_callback) TriggerVehicleSpriteGroup);
|
||||
}
|
||||
new_random_bits = Random();
|
||||
veh->random_bits &= ~_vsg_bits_to_reseed;
|
||||
veh->random_bits |= (first ? new_random_bits : base_random_bits) & _vsg_bits_to_reseed;
|
||||
|
||||
switch (trigger) {
|
||||
case VEHICLE_TRIGGER_NEW_CARGO:
|
||||
/* All vehicles in chain get ANY_NEW_CARGO trigger now.
|
||||
* So we call it for the first one and they will recurse. */
|
||||
/* Indexing part of vehicle random bits needs to be
|
||||
* same for all triggered vehicles in the chain (to get
|
||||
* all the random-cargo wagons carry the same cargo,
|
||||
* i.e.), so we give them all the NEW_CARGO triggered
|
||||
* vehicle's portion of random bits. */
|
||||
assert(first);
|
||||
DoTriggerVehicle(GetFirstVehicleInChain(veh), VEHICLE_TRIGGER_ANY_NEW_CARGO, new_random_bits, false);
|
||||
break;
|
||||
case VEHICLE_TRIGGER_DEPOT:
|
||||
/* We now trigger the next vehicle in chain recursively.
|
||||
* The random bits portions may be different for each
|
||||
* vehicle in chain. */
|
||||
if (veh->next != NULL)
|
||||
DoTriggerVehicle(veh->next, trigger, 0, true);
|
||||
break;
|
||||
case VEHICLE_TRIGGER_EMPTY:
|
||||
/* We now trigger the next vehicle in chain
|
||||
* recursively. The random bits portions must be same
|
||||
* for each vehicle in chain, so we give them all
|
||||
* first chained vehicle's portion of random bits. */
|
||||
if (veh->next != NULL)
|
||||
DoTriggerVehicle(veh->next, trigger, first ? new_random_bits : base_random_bits, false);
|
||||
break;
|
||||
case VEHICLE_TRIGGER_ANY_NEW_CARGO:
|
||||
/* Now pass the trigger recursively to the next vehicle
|
||||
* in chain. */
|
||||
assert(!first);
|
||||
if (veh->next != NULL)
|
||||
DoTriggerVehicle(veh->next, VEHICLE_TRIGGER_ANY_NEW_CARGO, base_random_bits, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void TriggerVehicle(Vehicle *veh, VehicleTrigger trigger)
|
||||
{
|
||||
DoTriggerVehicle(veh, trigger, 0, true);
|
||||
}
|
||||
|
||||
static char *_engine_custom_names[TOTAL_NUM_ENGINES];
|
||||
|
||||
void SetCustomEngineName(int engine, const char *name)
|
||||
{
|
||||
_engine_custom_names[engine] = strdup(name);
|
||||
}
|
||||
|
||||
void UnInitNewgrEngines(void)
|
||||
{
|
||||
char **i;
|
||||
for (i = _engine_custom_names; i != endof(_engine_custom_names); i++) {
|
||||
free(*i);
|
||||
*i = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
StringID GetCustomEngineName(int engine)
|
||||
{
|
||||
if (!_engine_custom_names[engine])
|
||||
return _engine_name_strings[engine];
|
||||
strcpy(_userstring, _engine_custom_names[engine]);
|
||||
strncpy(_userstring, _engine_custom_names[engine], USERSTRING_LEN);
|
||||
_userstring[USERSTRING_LEN - 1] = '\0';
|
||||
return STR_SPEC_USERSTRING;
|
||||
}
|
||||
|
||||
|
||||
void AcceptEnginePreview(Engine *e, int player)
|
||||
void AcceptEnginePreview(Engine *e, PlayerID player)
|
||||
{
|
||||
Player *p;
|
||||
Player *p = DEREF_PLAYER(player);
|
||||
|
||||
SETBIT(e->player_avail, player);
|
||||
|
||||
p = DEREF_PLAYER(player);
|
||||
|
||||
UPDATE_PLAYER_RAILTYPE(e,p);
|
||||
UPDATE_PLAYER_RAILTYPE(e, p);
|
||||
|
||||
e->preview_player = 0xFF;
|
||||
InvalidateWindowClasses(WC_BUILD_VEHICLE);
|
||||
InvalidateWindowClasses(WC_REPLACE_VEHICLE);
|
||||
}
|
||||
|
||||
void EnginesDailyLoop()
|
||||
static PlayerID GetBestPlayer(PlayerID pp)
|
||||
{
|
||||
const Player *p;
|
||||
int32 best_hist;
|
||||
PlayerID best_player;
|
||||
uint mask = 0;
|
||||
|
||||
do {
|
||||
best_hist = -1;
|
||||
best_player = -1;
|
||||
FOR_ALL_PLAYERS(p) {
|
||||
if (p->is_active && p->block_preview == 0 && !HASBIT(mask, p->index) &&
|
||||
p->old_economy[0].performance_history > best_hist) {
|
||||
best_hist = p->old_economy[0].performance_history;
|
||||
best_player = p->index;
|
||||
}
|
||||
}
|
||||
|
||||
if (best_player == (PlayerID)-1) return -1;
|
||||
|
||||
SETBIT(mask, best_player);
|
||||
} while (--pp != 0);
|
||||
|
||||
return best_player;
|
||||
}
|
||||
|
||||
void EnginesDailyLoop(void)
|
||||
{
|
||||
Engine *e;
|
||||
int i,num;
|
||||
Player *p;
|
||||
uint mask;
|
||||
int32 best_hist;
|
||||
int best_player;
|
||||
int i;
|
||||
|
||||
if (_cur_year >= 130)
|
||||
return;
|
||||
if (_cur_year >= 130) return;
|
||||
|
||||
for(e=_engines,i=0; i!=TOTAL_NUM_ENGINES; e++,i++) {
|
||||
for (e = _engines, i = 0; i != TOTAL_NUM_ENGINES; e++, i++) {
|
||||
if (e->flags & ENGINE_INTRODUCING) {
|
||||
if (e->flags & ENGINE_PREVIEWING) {
|
||||
if (!--e->preview_wait) {
|
||||
if (e->preview_player != 0xFF && !--e->preview_wait) {
|
||||
e->flags &= ~ENGINE_PREVIEWING;
|
||||
DeleteWindowById(WC_ENGINE_PREVIEW, i);
|
||||
e->preview_player++;
|
||||
}
|
||||
} else if (e->preview_player != 0xFF) {
|
||||
num = e->preview_player;
|
||||
mask = 0;
|
||||
do {
|
||||
best_hist = -1;
|
||||
best_player = -1;
|
||||
FOR_ALL_PLAYERS(p) {
|
||||
if (p->is_active && p->block_preview == 0 && !HASBIT(mask,p->index) &&
|
||||
p->old_economy[0].performance_history > best_hist) {
|
||||
best_hist = p->old_economy[0].performance_history;
|
||||
best_player = p->index;
|
||||
}
|
||||
}
|
||||
if (best_player == -1) {
|
||||
e->preview_player = 0xFF;
|
||||
goto next_engine;
|
||||
}
|
||||
mask |= (1 << best_player);
|
||||
} while (--num != 0);
|
||||
} else if (e->preview_player != 0xFF) {
|
||||
PlayerID best_player = GetBestPlayer(e->preview_player);
|
||||
|
||||
if (best_player == (PlayerID)-1) {
|
||||
e->preview_player = 0xFF;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!IS_HUMAN_PLAYER(best_player)) {
|
||||
/* TTDBUG: TTD has a bug here */
|
||||
/* XXX - TTDBUG: TTD has a bug here ???? */
|
||||
AcceptEnginePreview(e, best_player);
|
||||
} else {
|
||||
e->flags |= ENGINE_PREVIEWING;
|
||||
e->preview_wait = 20;
|
||||
if (IS_INTERACTIVE_PLAYER(best_player)) {
|
||||
if (IS_INTERACTIVE_PLAYER(best_player))
|
||||
ShowEnginePreviewWindow(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
next_engine:;
|
||||
}
|
||||
}
|
||||
|
||||
/** Accept an engine prototype. XXX - it is possible that the top-player
|
||||
* changes while you are waiting to accept the offer? Then it becomes invalid
|
||||
* @param x,y unused
|
||||
* @param p1 engine-prototype offered
|
||||
* @param p2 unused
|
||||
*/
|
||||
int32 CmdWantEnginePreview(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
if (flags & DC_EXEC) {
|
||||
AcceptEnginePreview(&_engines[p1], _current_player);
|
||||
}
|
||||
Engine *e;
|
||||
if (!IsEngineIndex(p1)) return CMD_ERROR;
|
||||
|
||||
e = DEREF_ENGINE(p1);
|
||||
if (GetBestPlayer(e->preview_player) != _current_player) return CMD_ERROR;
|
||||
|
||||
if (flags & DC_EXEC)
|
||||
AcceptEnginePreview(e, _current_player);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void NewVehicleAvailable(Engine *e)
|
||||
// Determine if an engine type is a wagon (and not a loco)
|
||||
static bool IsWagon(byte index)
|
||||
{
|
||||
return index < NUM_TRAIN_ENGINES && RailVehInfo(index)->flags & RVI_WAGON;
|
||||
}
|
||||
|
||||
static void NewVehicleAvailable(Engine *e)
|
||||
{
|
||||
Vehicle *v;
|
||||
Player *p;
|
||||
@@ -387,17 +801,22 @@ void NewVehicleAvailable(Engine *e)
|
||||
// prevent that player from getting future intro periods for a while.
|
||||
if (e->flags&ENGINE_INTRODUCING) {
|
||||
FOR_ALL_PLAYERS(p) {
|
||||
uint block_preview = p->block_preview;
|
||||
|
||||
if (!HASBIT(e->player_avail,p->index))
|
||||
continue;
|
||||
|
||||
for(v=_vehicles;;) {
|
||||
/* We assume the user did NOT build it.. prove me wrong ;) */
|
||||
p->block_preview = 20;
|
||||
|
||||
FOR_ALL_VEHICLES(v) {
|
||||
if (v->type == VEH_Train || v->type == VEH_Road || v->type == VEH_Ship ||
|
||||
(v->type == VEH_Aircraft && v->subtype <= 2)) {
|
||||
if (v->owner == p->index && v->engine_type == index) break;
|
||||
}
|
||||
if (++v == endof(_vehicles)) {
|
||||
p->block_preview = 20;
|
||||
break;
|
||||
if (v->owner == p->index && v->engine_type == index) {
|
||||
/* The user did prove me wrong, so restore old value */
|
||||
p->block_preview = block_preview;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -405,16 +824,14 @@ void NewVehicleAvailable(Engine *e)
|
||||
|
||||
e->flags = (e->flags & ~ENGINE_INTRODUCING) | ENGINE_AVAILABLE;
|
||||
InvalidateWindowClasses(WC_BUILD_VEHICLE);
|
||||
InvalidateWindowClasses(WC_REPLACE_VEHICLE);
|
||||
|
||||
// Now available for all players
|
||||
e->player_avail = (byte)-1;
|
||||
|
||||
// Do not introduce new rail wagons
|
||||
if ((byte)index < NUM_TRAIN_ENGINES) {
|
||||
const RailVehicleInfo *rvi = &_rail_vehicle_info[index];
|
||||
if(rvi->flags & RVI_WAGON)
|
||||
return;
|
||||
}
|
||||
if (IsWagon(index))
|
||||
return;
|
||||
|
||||
// make maglev / monorail available
|
||||
FOR_ALL_PLAYERS(p) {
|
||||
@@ -433,7 +850,7 @@ void NewVehicleAvailable(Engine *e)
|
||||
}
|
||||
}
|
||||
|
||||
void EnginesMonthlyLoop()
|
||||
void EnginesMonthlyLoop(void)
|
||||
{
|
||||
Engine *e;
|
||||
|
||||
@@ -451,20 +868,29 @@ void EnginesMonthlyLoop()
|
||||
} else if (!(e->flags & (ENGINE_AVAILABLE|ENGINE_INTRODUCING)) && _date >= e->intro_date) {
|
||||
// Introduction date has passed.. show introducing dialog to one player.
|
||||
e->flags |= ENGINE_INTRODUCING;
|
||||
e->preview_player = 1; // Give to the player with the highest rating.
|
||||
|
||||
// Do not introduce new rail wagons
|
||||
if (!IsWagon(e - _engines))
|
||||
e->preview_player = 1; // Give to the player with the highest rating.
|
||||
}
|
||||
}
|
||||
}
|
||||
AdjustAvailAircraft();
|
||||
}
|
||||
|
||||
/** Rename an engine.
|
||||
* @param x,y unused
|
||||
* @param p1 engine ID to rename
|
||||
* @param p2 unused
|
||||
*/
|
||||
int32 CmdRenameEngine(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
StringID str;
|
||||
|
||||
str = AllocateName((byte*)_decode_parameters, 0);
|
||||
if (str == 0)
|
||||
return CMD_ERROR;
|
||||
if (!IsEngineIndex(p1) || _cmd_text[0] == '\0') return CMD_ERROR;
|
||||
|
||||
str = AllocateNameUnique(_cmd_text, 0);
|
||||
if (str == 0) return CMD_ERROR;
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
StringID old_str = _engine_name_strings[p1];
|
||||
@@ -525,7 +951,7 @@ static const byte _engine_desc[] = {
|
||||
SLE_END()
|
||||
};
|
||||
|
||||
static void Save_ENGN()
|
||||
static void Save_ENGN(void)
|
||||
{
|
||||
Engine *e;
|
||||
int i;
|
||||
@@ -535,7 +961,7 @@ static void Save_ENGN()
|
||||
}
|
||||
}
|
||||
|
||||
static void Load_ENGN()
|
||||
static void Load_ENGN(void)
|
||||
{
|
||||
int index;
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
@@ -543,7 +969,7 @@ static void Load_ENGN()
|
||||
}
|
||||
}
|
||||
|
||||
static void LoadSave_ENGS()
|
||||
static void LoadSave_ENGS(void)
|
||||
{
|
||||
SlArray(_engine_name_strings, lengthof(_engine_name_strings), SLE_STRINGID);
|
||||
}
|
||||
@@ -554,4 +980,27 @@ const ChunkHandler _engine_chunk_handlers[] = {
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* returns true if an engine is valid, of the specified type, and buildable by
|
||||
* the current player, false otherwise
|
||||
*
|
||||
* engine = index of the engine to check
|
||||
* type = the type the engine should be of (VEH_xxx)
|
||||
*/
|
||||
bool IsEngineBuildable(uint engine, byte type)
|
||||
{
|
||||
const Engine *e;
|
||||
|
||||
// check if it's an engine that is in the engine array
|
||||
if (!IsEngineIndex(engine)) return false;
|
||||
|
||||
e = DEREF_ENGINE(engine);
|
||||
|
||||
// check if it's an engine of specified type
|
||||
if (e->type != type) return false;
|
||||
|
||||
// check if it's available
|
||||
if (!HASBIT(e->player_avail, _current_player)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef ENGINE_H
|
||||
#define ENGINE_H
|
||||
|
||||
#include "sprite.h"
|
||||
|
||||
typedef struct RailVehicleInfo {
|
||||
byte image_index;
|
||||
byte flags; /* 1=multihead engine, 2=wagon */
|
||||
@@ -25,6 +27,27 @@ typedef struct ShipVehicleInfo {
|
||||
byte refittable;
|
||||
} ShipVehicleInfo;
|
||||
|
||||
typedef struct AircraftVehicleInfo {
|
||||
byte image_index;
|
||||
byte base_cost;
|
||||
byte running_cost;
|
||||
byte subtype;
|
||||
byte sfx;
|
||||
byte acceleration;
|
||||
byte max_speed;
|
||||
byte mail_capacity;
|
||||
uint16 passenger_capacity;
|
||||
} AircraftVehicleInfo;
|
||||
|
||||
typedef struct RoadVehicleInfo {
|
||||
byte image_index;
|
||||
byte base_cost;
|
||||
byte running_cost;
|
||||
byte sfx;
|
||||
byte max_speed;
|
||||
byte capacity;
|
||||
byte cargo_type;
|
||||
} RoadVehicleInfo;
|
||||
|
||||
typedef struct EngineInfo {
|
||||
uint16 base_intro;
|
||||
@@ -43,10 +66,11 @@ typedef struct Engine {
|
||||
uint16 duration_phase_1, duration_phase_2, duration_phase_3;
|
||||
byte lifelength;
|
||||
byte flags;
|
||||
byte preview_player;
|
||||
PlayerID preview_player;
|
||||
byte preview_wait;
|
||||
byte railtype;
|
||||
byte player_avail;
|
||||
PlayerID player_avail;
|
||||
byte type; // type, ie VEH_Road, VEH_Train, etc. Same as in vehicle.h
|
||||
} Engine;
|
||||
|
||||
|
||||
@@ -55,45 +79,75 @@ enum {
|
||||
RVI_WAGON = 2,
|
||||
};
|
||||
|
||||
|
||||
void StartupEngines();
|
||||
|
||||
|
||||
struct SpriteSuperSet {
|
||||
// XXX: Would anyone ever need more than 16 spritesets? Maybe we should
|
||||
// use even less, now we take whole 8kb for custom sprites table, oh my!
|
||||
byte sprites_per_set; // means number of directions - 4 or 8
|
||||
// Loaded = in motion, loading = not moving
|
||||
// Each superset contains several spritesets, for various loading stages
|
||||
byte loaded_count;
|
||||
uint16 loaded[16]; // sprite ids
|
||||
byte loading_count;
|
||||
uint16 loading[16]; // sprite ids
|
||||
};
|
||||
|
||||
extern byte _global_cargo_id[NUM_LANDSCAPE][NUM_CARGO];
|
||||
enum {
|
||||
CID_DEFAULT = 29,
|
||||
CID_PURCHASE = 30,
|
||||
NUM_CID = 31,
|
||||
NUM_VEHICLE_TYPES = 6
|
||||
};
|
||||
extern byte _local_cargo_id_ctype[NUM_CID];
|
||||
extern byte _local_cargo_id_landscape[NUM_CID];
|
||||
|
||||
extern uint32 _engine_refit_masks[256];
|
||||
void AddTypeToEngines(void);
|
||||
void StartupEngines(void);
|
||||
|
||||
extern byte _engine_original_sprites[256];
|
||||
void SetWagonOverrideSprites(byte engine, struct SpriteSuperSet *superset, byte *train_id, int trains);
|
||||
void SetCustomEngineSprites(byte engine, byte cargo, struct SpriteSuperSet *superset);
|
||||
enum GlobalCargo {
|
||||
GC_PASSENGERS = 0,
|
||||
GC_COAL = 1,
|
||||
GC_MAIL = 2,
|
||||
GC_OIL = 3,
|
||||
GC_LIVESTOCK = 4,
|
||||
GC_GOODS = 5,
|
||||
GC_GRAIN = 6, // GC_WHEAT / GC_MAIZE
|
||||
GC_WOOD = 7,
|
||||
GC_IRON_ORE = 8,
|
||||
GC_STEEL = 9,
|
||||
GC_VALUABLES = 10, // GC_GOLD / GC_DIAMONDS
|
||||
GC_PAPER = 11,
|
||||
GC_FOOD = 12,
|
||||
GC_FRUIT = 13,
|
||||
GC_COPPER_ORE = 14,
|
||||
GC_WATER = 15,
|
||||
GC_RUBBER = 16,
|
||||
GC_SUGAR = 17,
|
||||
GC_TOYS = 18,
|
||||
GC_BATTERIES = 19,
|
||||
GC_CANDY = 20,
|
||||
GC_TOFFEE = 21,
|
||||
GC_COLA = 22,
|
||||
GC_COTTON_CANDY = 23,
|
||||
GC_BUBBLES = 24,
|
||||
GC_PLASTIC = 25,
|
||||
GC_FIZZY_DRINKS = 26,
|
||||
GC_PAPER_TEMP = 27,
|
||||
GC_UNDEFINED = 28, // undefined; unused slot in arctic climate
|
||||
GC_DEFAULT = 29,
|
||||
GC_PURCHASE = 30,
|
||||
GC_INVALID = 255,
|
||||
NUM_GLOBAL_CID = 31
|
||||
};
|
||||
|
||||
VARDEF const uint32 _default_refitmasks[NUM_VEHICLE_TYPES];
|
||||
VARDEF const CargoID _global_cargo_id[NUM_LANDSCAPE][NUM_CARGO];
|
||||
VARDEF const uint32 _landscape_global_cargo_mask[NUM_LANDSCAPE];
|
||||
VARDEF const CargoID _local_cargo_id_ctype[NUM_GLOBAL_CID];
|
||||
|
||||
VARDEF uint32 _engine_refit_masks[256];
|
||||
VARDEF byte _engine_original_sprites[256];
|
||||
void SetWagonOverrideSprites(byte engine, struct SpriteGroup *group, byte *train_id, int trains);
|
||||
void SetCustomEngineSprites(byte engine, byte cargo, struct SpriteGroup *group);
|
||||
// loaded is in percents, overriding_engine 0xffff is none
|
||||
int GetCustomEngineSprite(byte engine, uint16 overriding_engine, byte cargo, byte loaded, byte in_motion, byte direction);
|
||||
#define GetCustomVehicleSprite(v, direction) \
|
||||
GetCustomEngineSprite(v->engine_type, v->type == VEH_Train ? v->u.rail.first_engine : -1, \
|
||||
_global_cargo_id[_opt.landscape][v->cargo_type], \
|
||||
((v->cargo_count + 1) * 100) / (v->cargo_cap + 1), \
|
||||
!!v->cur_speed, direction);
|
||||
int GetCustomEngineSprite(byte engine, const Vehicle *v, byte direction);
|
||||
#define GetCustomVehicleSprite(v, direction) GetCustomEngineSprite(v->engine_type, v, direction)
|
||||
#define GetCustomVehicleIcon(et, direction) GetCustomEngineSprite(et, NULL, direction)
|
||||
|
||||
void SetCustomEngineName(int engine, char *name);
|
||||
typedef enum VehicleTrigger {
|
||||
VEHICLE_TRIGGER_NEW_CARGO = 1,
|
||||
// Externally triggered only for the first vehicle in chain
|
||||
VEHICLE_TRIGGER_DEPOT = 2,
|
||||
// Externally triggered only for the first vehicle in chain, only if whole chain is empty
|
||||
VEHICLE_TRIGGER_EMPTY = 4,
|
||||
// Not triggered externally (called for the whole chain if we got NEW_CARGO)
|
||||
VEHICLE_TRIGGER_ANY_NEW_CARGO = 8,
|
||||
} VehicleTrigger;
|
||||
void TriggerVehicle(Vehicle *veh, VehicleTrigger trigger);
|
||||
|
||||
void SetCustomEngineName(int engine, const char *name);
|
||||
StringID GetCustomEngineName(int engine);
|
||||
|
||||
|
||||
@@ -107,11 +161,13 @@ void DrawRoadVehEngineInfo(int engine, int x, int y, int maxw);
|
||||
void DrawShipEngineInfo(int engine, int x, int y, int maxw);
|
||||
void DrawAircraftEngineInfo(int engine, int x, int y, int maxw);
|
||||
|
||||
void AcceptEnginePreview(Engine *e, int player);
|
||||
void AcceptEnginePreview(Engine *e, PlayerID player);
|
||||
|
||||
void LoadCustomEngineNames();
|
||||
void DeleteCustomEngineNames();
|
||||
void LoadCustomEngineNames(void);
|
||||
void DeleteCustomEngineNames(void);
|
||||
|
||||
bool IsEngineBuildable(uint engine, byte type);
|
||||
void UnInitNewgrEngines(void);
|
||||
|
||||
enum {
|
||||
NUM_NORMAL_RAIL_ENGINES = 54,
|
||||
@@ -121,17 +177,57 @@ enum {
|
||||
NUM_ROAD_ENGINES = 88,
|
||||
NUM_SHIP_ENGINES = 11,
|
||||
NUM_AIRCRAFT_ENGINES = 41,
|
||||
TOTAL_NUM_ENGINES = NUM_NORMAL_RAIL_ENGINES+NUM_MONORAIL_ENGINES+NUM_MAGLEV_ENGINES+NUM_ROAD_ENGINES+NUM_SHIP_ENGINES+NUM_AIRCRAFT_ENGINES,
|
||||
TOTAL_NUM_ENGINES = NUM_TRAIN_ENGINES + NUM_ROAD_ENGINES + NUM_SHIP_ENGINES + NUM_AIRCRAFT_ENGINES,
|
||||
AIRCRAFT_ENGINES_INDEX = NUM_TRAIN_ENGINES + NUM_ROAD_ENGINES + NUM_SHIP_ENGINES,
|
||||
SHIP_ENGINES_INDEX = NUM_TRAIN_ENGINES + NUM_ROAD_ENGINES,
|
||||
ROAD_ENGINES_INDEX = NUM_TRAIN_ENGINES,
|
||||
};
|
||||
VARDEF Engine _engines[TOTAL_NUM_ENGINES];
|
||||
#define FOR_ALL_ENGINES(e) for (e = _engines; e != endof(_engines); e++)
|
||||
#define DEREF_ENGINE(i) (GetEngine(i))
|
||||
static inline Engine* GetEngine(uint i)
|
||||
{
|
||||
assert(i < lengthof(_engines));
|
||||
return &_engines[i];
|
||||
}
|
||||
|
||||
VARDEF StringID _engine_name_strings[TOTAL_NUM_ENGINES];
|
||||
|
||||
static inline bool IsEngineIndex(uint index)
|
||||
{
|
||||
return index < TOTAL_NUM_ENGINES;
|
||||
}
|
||||
|
||||
/* Access Vehicle Data */
|
||||
//#include "table/engines.h"
|
||||
extern EngineInfo _engine_info[TOTAL_NUM_ENGINES];
|
||||
extern RailVehicleInfo _rail_vehicle_info[];
|
||||
#define ship_vehicle_info(e) _ship_vehicle_info[e - SHIP_ENGINES_INDEX]
|
||||
extern ShipVehicleInfo _ship_vehicle_info[];
|
||||
extern RailVehicleInfo _rail_vehicle_info[NUM_TRAIN_ENGINES];
|
||||
extern ShipVehicleInfo _ship_vehicle_info[NUM_SHIP_ENGINES];
|
||||
extern AircraftVehicleInfo _aircraft_vehicle_info[NUM_AIRCRAFT_ENGINES];
|
||||
extern RoadVehicleInfo _road_vehicle_info[NUM_ROAD_ENGINES];
|
||||
|
||||
static inline RailVehicleInfo *RailVehInfo(uint e)
|
||||
{
|
||||
assert(e < lengthof(_rail_vehicle_info));
|
||||
return &_rail_vehicle_info[e];
|
||||
}
|
||||
|
||||
static inline ShipVehicleInfo *ShipVehInfo(uint e)
|
||||
{
|
||||
assert(e - SHIP_ENGINES_INDEX < lengthof(_ship_vehicle_info));
|
||||
return &_ship_vehicle_info[e - SHIP_ENGINES_INDEX];
|
||||
}
|
||||
|
||||
static inline AircraftVehicleInfo *AircraftVehInfo(uint e)
|
||||
{
|
||||
assert(e - AIRCRAFT_ENGINES_INDEX < lengthof(_aircraft_vehicle_info));
|
||||
return &_aircraft_vehicle_info[e - AIRCRAFT_ENGINES_INDEX];
|
||||
}
|
||||
|
||||
static inline RoadVehicleInfo *RoadVehInfo(uint e)
|
||||
{
|
||||
assert(e - ROAD_ENGINES_INDEX < lengthof(_road_vehicle_info));
|
||||
return &_road_vehicle_info[e - ROAD_ENGINES_INDEX];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+32
-33
@@ -1,6 +1,6 @@
|
||||
#include "stdafx.h"
|
||||
#include "ttd.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
#include "window.h"
|
||||
#include "gui.h"
|
||||
#include "viewport.h"
|
||||
@@ -9,20 +9,19 @@
|
||||
#include "command.h"
|
||||
#include "news.h"
|
||||
|
||||
void DrawShipEngine(int x, int y, int engine, uint32 image_ormod);
|
||||
void DrawShipEngineInfo(int engine, int x, int y, int maxw);
|
||||
|
||||
|
||||
StringID GetEngineCategoryName(byte engine)
|
||||
static StringID GetEngineCategoryName(byte engine)
|
||||
{
|
||||
if (engine < NUM_NORMAL_RAIL_ENGINES)
|
||||
return STR_8102_RAILROAD_LOCOMOTIVE;
|
||||
|
||||
if (engine < NUM_NORMAL_RAIL_ENGINES + NUM_MONORAIL_ENGINES)
|
||||
return STR_8106_MONORAIL_LOCOMOTIVE;
|
||||
|
||||
if (engine < NUM_TRAIN_ENGINES)
|
||||
return STR_8107_MAGLEV_LOCOMOTIVE;
|
||||
if (engine < NUM_TRAIN_ENGINES) {
|
||||
switch (_engines[engine].railtype) {
|
||||
case 0:
|
||||
return STR_8102_RAILROAD_LOCOMOTIVE;
|
||||
case 1:
|
||||
return STR_8106_MONORAIL_LOCOMOTIVE;
|
||||
case 2:
|
||||
return STR_8107_MAGLEV_LOCOMOTIVE;
|
||||
}
|
||||
}
|
||||
|
||||
if (engine < NUM_TRAIN_ENGINES + NUM_ROAD_ENGINES)
|
||||
return STR_8103_ROAD_VEHICLE;
|
||||
@@ -34,11 +33,11 @@ StringID GetEngineCategoryName(byte engine)
|
||||
}
|
||||
|
||||
static const Widget _engine_preview_widgets[] = {
|
||||
{ WWT_TEXTBTN, 5, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, 5, 11, 299, 0, 13, STR_8100_MESSAGE_FROM_VEHICLE_MANUFACTURE, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_IMGBTN, 5, 0, 299, 14, 191, 0x0, STR_NULL},
|
||||
{ WWT_PUSHTXTBTN, 5, 85, 144, 172, 183, STR_00C9_NO, STR_NULL},
|
||||
{ WWT_PUSHTXTBTN, 5, 155, 214, 172, 183, STR_00C8_YES, STR_NULL},
|
||||
{ WWT_TEXTBTN, RESIZE_NONE, 5, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 5, 11, 299, 0, 13, STR_8100_MESSAGE_FROM_VEHICLE_MANUFACTURE, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_IMGBTN, RESIZE_NONE, 5, 0, 299, 14, 191, 0x0, STR_NULL},
|
||||
{ WWT_PUSHTXTBTN, RESIZE_NONE, 5, 85, 144, 172, 183, STR_00C9_NO, STR_NULL},
|
||||
{ WWT_PUSHTXTBTN, RESIZE_NONE, 5, 155, 214, 172, 183, STR_00C8_YES, STR_NULL},
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
@@ -69,7 +68,7 @@ static void EnginePreviewWndProc(Window *w, WindowEvent *e)
|
||||
DrawWindowWidgets(w);
|
||||
engine = w->window_number;
|
||||
|
||||
SET_DPARAM16(0, GetEngineCategoryName(engine));
|
||||
SetDParam(0, GetEngineCategoryName(engine));
|
||||
DrawStringMultiCenter(150, 44, STR_8101_WE_HAVE_JUST_DESIGNED_A, 296);
|
||||
|
||||
DrawStringCentered(w->width >> 1, 80, GetCustomEngineName(engine), 0x10);
|
||||
@@ -121,12 +120,12 @@ void DrawNewsNewTrainAvail(Window *w)
|
||||
DrawNewsBorder(w);
|
||||
|
||||
engine = WP(w,news_d).ni->string_id;
|
||||
SET_DPARAM16(0, GetEngineCategoryName(engine));
|
||||
SetDParam(0, GetEngineCategoryName(engine));
|
||||
DrawStringMultiCenter(w->width >> 1, 20, STR_8859_NEW_NOW_AVAILABLE, w->width - 2);
|
||||
|
||||
GfxFillRect(25, 56, w->width - 25, w->height - 2, 10);
|
||||
|
||||
SET_DPARAM16(0, GetCustomEngineName(engine));
|
||||
SetDParam(0, GetCustomEngineName(engine));
|
||||
DrawStringMultiCenter(w->width >> 1, 57, STR_885A, w->width - 2);
|
||||
|
||||
DrawTrainEngine(w->width >> 1, 88, engine, 0);
|
||||
@@ -137,9 +136,9 @@ void DrawNewsNewTrainAvail(Window *w)
|
||||
StringID GetNewsStringNewTrainAvail(NewsItem *ni)
|
||||
{
|
||||
int engine = ni->string_id;
|
||||
SET_DPARAM16(0, STR_8859_NEW_NOW_AVAILABLE);
|
||||
SET_DPARAM16(1, GetEngineCategoryName(engine));
|
||||
SET_DPARAM16(2, GetCustomEngineName(engine));
|
||||
SetDParam(0, STR_8859_NEW_NOW_AVAILABLE);
|
||||
SetDParam(1, GetEngineCategoryName(engine));
|
||||
SetDParam(2, GetCustomEngineName(engine));
|
||||
return STR_02B6;
|
||||
}
|
||||
|
||||
@@ -154,7 +153,7 @@ void DrawNewsNewAircraftAvail(Window *w)
|
||||
DrawStringMultiCenter(w->width >> 1, 20, STR_A02C_NEW_AIRCRAFT_NOW_AVAILABLE, w->width - 2);
|
||||
GfxFillRect(25, 56, w->width - 25, w->height - 2, 10);
|
||||
|
||||
SET_DPARAM16(0, GetCustomEngineName(engine));
|
||||
SetDParam(0, GetCustomEngineName(engine));
|
||||
DrawStringMultiCenter(w->width >> 1, 57, STR_A02D, w->width - 2);
|
||||
|
||||
DrawAircraftEngine(w->width >> 1, 93, engine, 0);
|
||||
@@ -165,8 +164,8 @@ void DrawNewsNewAircraftAvail(Window *w)
|
||||
StringID GetNewsStringNewAircraftAvail(NewsItem *ni)
|
||||
{
|
||||
int engine = ni->string_id;
|
||||
SET_DPARAM16(0, STR_A02C_NEW_AIRCRAFT_NOW_AVAILABLE);
|
||||
SET_DPARAM16(1, GetCustomEngineName(engine));
|
||||
SetDParam(0, STR_A02C_NEW_AIRCRAFT_NOW_AVAILABLE);
|
||||
SetDParam(1, GetCustomEngineName(engine));
|
||||
return STR_02B6;
|
||||
}
|
||||
|
||||
@@ -180,7 +179,7 @@ void DrawNewsNewRoadVehAvail(Window *w)
|
||||
DrawStringMultiCenter(w->width >> 1, 20, STR_9028_NEW_ROAD_VEHICLE_NOW_AVAILABLE, w->width - 2);
|
||||
GfxFillRect(25, 56, w->width - 25, w->height - 2, 10);
|
||||
|
||||
SET_DPARAM16(0, GetCustomEngineName(engine));
|
||||
SetDParam(0, GetCustomEngineName(engine));
|
||||
DrawStringMultiCenter(w->width >> 1, 57, STR_9029, w->width - 2);
|
||||
|
||||
DrawRoadVehEngine(w->width >> 1, 88, engine, 0);
|
||||
@@ -191,8 +190,8 @@ void DrawNewsNewRoadVehAvail(Window *w)
|
||||
StringID GetNewsStringNewRoadVehAvail(NewsItem *ni)
|
||||
{
|
||||
int engine = ni->string_id;
|
||||
SET_DPARAM16(0, STR_9028_NEW_ROAD_VEHICLE_NOW_AVAILABLE);
|
||||
SET_DPARAM16(1, GetCustomEngineName(engine));
|
||||
SetDParam(0, STR_9028_NEW_ROAD_VEHICLE_NOW_AVAILABLE);
|
||||
SetDParam(1, GetCustomEngineName(engine));
|
||||
return STR_02B6;
|
||||
}
|
||||
|
||||
@@ -207,7 +206,7 @@ void DrawNewsNewShipAvail(Window *w)
|
||||
DrawStringMultiCenter(w->width >> 1, 20, STR_982C_NEW_SHIP_NOW_AVAILABLE, w->width - 2);
|
||||
GfxFillRect(25, 56, w->width - 25, w->height - 2, 10);
|
||||
|
||||
SET_DPARAM16(0, GetCustomEngineName(engine));
|
||||
SetDParam(0, GetCustomEngineName(engine));
|
||||
DrawStringMultiCenter(w->width >> 1, 57, STR_982D, w->width - 2);
|
||||
|
||||
DrawShipEngine(w->width >> 1, 93, engine, 0);
|
||||
@@ -218,7 +217,7 @@ void DrawNewsNewShipAvail(Window *w)
|
||||
StringID GetNewsStringNewShipAvail(NewsItem *ni)
|
||||
{
|
||||
int engine = ni->string_id;
|
||||
SET_DPARAM16(0, STR_982C_NEW_SHIP_NOW_AVAILABLE);
|
||||
SET_DPARAM16(1, GetCustomEngineName(engine));
|
||||
SetDParam(0, STR_982C_NEW_SHIP_NOW_AVAILABLE);
|
||||
SetDParam(1, GetCustomEngineName(engine));
|
||||
return STR_02B6;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
|
||||
#include "ttd.h"
|
||||
#include "hal.h"
|
||||
#include "sound.h"
|
||||
#include "string.h"
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
@@ -11,93 +14,98 @@
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef EXTERNAL_PLAYER
|
||||
#define EXTERNAL_PLAYER "/usr/bin/timidity"
|
||||
#endif
|
||||
static struct {
|
||||
char song[MAX_PATH];
|
||||
int pid;
|
||||
} _midi;
|
||||
|
||||
static pid_t _pid;
|
||||
static void DoPlay(void);
|
||||
static void DoStop(void);
|
||||
|
||||
static void extmidi_kill(void) {
|
||||
if(_pid > 0) {
|
||||
kill(_pid, SIGKILL);
|
||||
while(waitpid(_pid, NULL, WNOHANG) != _pid);
|
||||
}
|
||||
_pid = 0;
|
||||
static const char* ExtMidiStart(const char* const * parm)
|
||||
{
|
||||
_midi.song[0] = '\0';
|
||||
_midi.pid = -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *extmidi_start(char **parm) {
|
||||
_pid = 0;
|
||||
|
||||
return NULL;
|
||||
static void ExtMidiStop(void)
|
||||
{
|
||||
_midi.song[0] = '\0';
|
||||
DoStop();
|
||||
}
|
||||
|
||||
static void extmidi_stop(void) {
|
||||
extmidi_kill();
|
||||
static void ExtMidiPlaySong(const char* filename)
|
||||
{
|
||||
ttd_strlcpy(_midi.song, filename, lengthof(_midi.song));
|
||||
DoStop();
|
||||
}
|
||||
|
||||
static void extmidi_play_song(const char *filename) {
|
||||
extmidi_kill();
|
||||
|
||||
_pid = fork();
|
||||
if(_pid < 0) {
|
||||
fprintf(stderr, "extmidi: couldn't fork: %s\n", strerror(errno));
|
||||
_pid = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if(_pid == 0) {
|
||||
#if defined(MIDI_ARG)
|
||||
execl(EXTERNAL_PLAYER, "extmidi", MIDI_ARG, filename, NULL);
|
||||
#else
|
||||
execl(EXTERNAL_PLAYER, "extmidi", filename, NULL);
|
||||
#endif
|
||||
|
||||
fprintf(stderr, "extmidi: couldn't execl: %s\n", strerror(errno));
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
usleep(500);
|
||||
|
||||
|
||||
if(_pid == waitpid(_pid, NULL, WNOHANG)) {
|
||||
fprintf(stderr, "extmidi: play song failed\n");
|
||||
_pid = 0;
|
||||
|
||||
usleep(5000);
|
||||
|
||||
}
|
||||
static void ExtMidiStopSong(void)
|
||||
{
|
||||
_midi.song[0] = '\0';
|
||||
DoStop();
|
||||
}
|
||||
|
||||
static void extmidi_stop_song(void) {
|
||||
extmidi_kill();
|
||||
static bool ExtMidiIsPlaying(void)
|
||||
{
|
||||
if (_midi.pid != -1 && waitpid(_midi.pid, NULL, WNOHANG) == _midi.pid)
|
||||
_midi.pid = -1;
|
||||
if (_midi.pid == -1 && _midi.song[0] != '\0') DoPlay();
|
||||
return _midi.pid != -1;
|
||||
}
|
||||
|
||||
static bool extmidi_is_playing(void) {
|
||||
if(_pid == 0)
|
||||
return 0;
|
||||
|
||||
if(waitpid(_pid, NULL, WNOHANG) == _pid) {
|
||||
_pid = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
static void ExtMidiSetVolume(byte vol)
|
||||
{
|
||||
fprintf(stderr, "extmidi: set volume not implemented\n");
|
||||
}
|
||||
|
||||
static void extmidi_set_volume(byte vol) {
|
||||
fprintf(stderr, "extmidi: set volume not implemented\n");
|
||||
static void DoPlay(void)
|
||||
{
|
||||
_midi.pid = fork();
|
||||
switch (_midi.pid) {
|
||||
case 0: {
|
||||
int d;
|
||||
|
||||
close(0);
|
||||
close(1);
|
||||
close(2);
|
||||
d = open("/dev/null", O_RDONLY);
|
||||
if (d != -1) {
|
||||
if (dup2(d, 1) != -1 && dup2(d, 2) != -1) {
|
||||
#if defined(MIDI_ARG)
|
||||
execlp(msf.extmidi, "extmidi", MIDI_ARG, _midi.song, NULL);
|
||||
#else
|
||||
execlp(msf.extmidi, "extmidi", _midi.song, NULL);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
case -1:
|
||||
fprintf(stderr, "extmidi: couldn't fork: %s\n", strerror(errno));
|
||||
/* FALLTHROUGH */
|
||||
|
||||
default:
|
||||
_midi.song[0] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void DoStop(void)
|
||||
{
|
||||
if (_midi.pid != -1) kill(_midi.pid, SIGTERM);
|
||||
}
|
||||
|
||||
const HalMusicDriver _extmidi_music_driver = {
|
||||
extmidi_start,
|
||||
extmidi_stop,
|
||||
extmidi_play_song,
|
||||
extmidi_stop_song,
|
||||
extmidi_is_playing,
|
||||
extmidi_set_volume,
|
||||
ExtMidiStart,
|
||||
ExtMidiStop,
|
||||
ExtMidiPlaySong,
|
||||
ExtMidiStopSong,
|
||||
ExtMidiIsPlaying,
|
||||
ExtMidiSetVolume,
|
||||
};
|
||||
|
||||
#endif /* __MORPHOS__ */
|
||||
#endif /* __BEOS__ */
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "stdafx.h"
|
||||
#include "ttd.h"
|
||||
#if defined(UNIX)
|
||||
#include "fileio.h"
|
||||
#if defined(UNIX) || defined(__OS2__)
|
||||
#include <ctype.h> // required for tolower()
|
||||
#endif
|
||||
|
||||
@@ -21,7 +22,7 @@ typedef struct {
|
||||
static Fio _fio;
|
||||
|
||||
// Get current position in file
|
||||
uint32 FioGetPos()
|
||||
uint32 FioGetPos(void)
|
||||
{
|
||||
return _fio.pos + (_fio.buffer - _fio.buffer_start) - FIO_BUFFER_SIZE;
|
||||
}
|
||||
@@ -42,7 +43,7 @@ void FioSeekToFile(uint32 pos)
|
||||
FioSeekTo(pos & 0xFFFFFF, SEEK_SET);
|
||||
}
|
||||
|
||||
byte FioReadByte()
|
||||
byte FioReadByte(void)
|
||||
{
|
||||
if (_fio.buffer == _fio.buffer_end) {
|
||||
_fio.pos += FIO_BUFFER_SIZE;
|
||||
@@ -64,13 +65,13 @@ void FioSkipBytes(int n)
|
||||
}
|
||||
|
||||
|
||||
uint16 FioReadWord()
|
||||
uint16 FioReadWord(void)
|
||||
{
|
||||
byte b = FioReadByte();
|
||||
return (FioReadByte() << 8) | b;
|
||||
}
|
||||
|
||||
uint32 FioReadDword()
|
||||
uint32 FioReadDword(void)
|
||||
{
|
||||
uint b = FioReadWord();
|
||||
return (FioReadWord() << 16) | b;
|
||||
@@ -83,15 +84,55 @@ void FioReadBlock(void *ptr, uint size)
|
||||
fread(ptr, 1, size, _fio.cur_fh);
|
||||
}
|
||||
|
||||
void FioCloseAll()
|
||||
static inline void FioCloseFile(int slot)
|
||||
{
|
||||
if (_fio.handles[slot] != NULL) {
|
||||
fclose(_fio.handles[slot]);
|
||||
_fio.handles[slot] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void FioCloseAll(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i!=lengthof(_fio.handles); i++) {
|
||||
if (_fio.handles[i] != NULL) {
|
||||
fclose(_fio.handles[i]);
|
||||
_fio.handles[i] = NULL;
|
||||
for (i = 0; i != lengthof(_fio.handles); i++)
|
||||
FioCloseFile(i);
|
||||
}
|
||||
|
||||
bool FiosCheckFileExists(const char *filename)
|
||||
{
|
||||
FILE *f;
|
||||
char buf[MAX_PATH];
|
||||
|
||||
sprintf(buf, "%s%s", _path.data_dir, filename);
|
||||
|
||||
f = fopen(buf, "rb");
|
||||
#if !defined(WIN32)
|
||||
if (f == NULL) {
|
||||
char *s;
|
||||
// Make lower case and try again
|
||||
for(s=buf + strlen(_path.data_dir) - 1; *s != 0; s++)
|
||||
*s = tolower(*s);
|
||||
f = fopen(buf, "rb");
|
||||
|
||||
#if defined SECOND_DATA_DIR
|
||||
// tries in the 2nd data directory
|
||||
if (f == NULL) {
|
||||
sprintf(buf, "%s%s", _path.second_data_dir, filename);
|
||||
for(s=buf + strlen(_path.second_data_dir) - 1; *s != 0; s++)
|
||||
*s = tolower(*s);
|
||||
f = fopen(buf, "rb");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
if (f == NULL)
|
||||
return false;
|
||||
else {
|
||||
fclose(f);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,12 +151,23 @@ void FioOpenFile(int slot, const char *filename)
|
||||
for(s=buf + strlen(_path.data_dir) - 1; *s != 0; s++)
|
||||
*s = tolower(*s);
|
||||
f = fopen(buf, "rb");
|
||||
|
||||
#if defined SECOND_DATA_DIR
|
||||
// tries in the 2nd data directory
|
||||
if (f == NULL) {
|
||||
sprintf(buf, "%s%s", _path.second_data_dir, filename);
|
||||
for(s=buf + strlen(_path.second_data_dir) - 1; *s != 0; s++)
|
||||
*s = tolower(*s);
|
||||
f = fopen(buf, "rb");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
if (f == NULL)
|
||||
error("Cannot open file '%s'", buf);
|
||||
|
||||
FioCloseFile(slot); // if file was opened before, close it
|
||||
_fio.handles[slot] = f;
|
||||
FioSeekToFile(slot << 24);
|
||||
}
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
|
||||
void FioSeekTo(uint32 pos, int mode);
|
||||
void FioSeekToFile(uint32 pos);
|
||||
uint32 FioGetPos();
|
||||
byte FioReadByte();
|
||||
uint16 FioReadWord();
|
||||
uint32 FioReadDword();
|
||||
void FioCloseAll();
|
||||
uint32 FioGetPos(void);
|
||||
byte FioReadByte(void);
|
||||
uint16 FioReadWord(void);
|
||||
uint32 FioReadDword(void);
|
||||
void FioCloseAll(void);
|
||||
void FioOpenFile(int slot, const char *filename);
|
||||
void FioReadBlock(void *ptr, uint size);
|
||||
void FioSkipBytes(int n);
|
||||
bool FiosCheckFileExists(const char *filename);
|
||||
|
||||
#endif /* FILEIO_H */
|
||||
|
||||
+106
-123
@@ -1,8 +1,6 @@
|
||||
#ifndef FUNCTIONS_H
|
||||
#define FUNCTIONS_H
|
||||
|
||||
#include "network.h"
|
||||
|
||||
/* vehicle.c */
|
||||
|
||||
/* window.c */
|
||||
@@ -10,61 +8,50 @@
|
||||
|
||||
/* landscape.c */
|
||||
void FindLandscapeHeight(TileInfo *ti, uint x, uint y);
|
||||
void FindLandscapeHeightByTile(TileInfo *ti, uint tile);
|
||||
uint GetTileSlope(uint tile, int *h);
|
||||
int GetTileZ(uint tile);
|
||||
void FindLandscapeHeightByTile(TileInfo *ti, TileIndex tile);
|
||||
|
||||
void DoClearSquare(uint tile);
|
||||
void CDECL ModifyTile(uint tile, uint flags, ...);
|
||||
void SetMapExtraBits(uint tile, byte flags);
|
||||
uint GetMapExtraBits(uint tile);
|
||||
void RunTileLoop();
|
||||
void DoClearSquare(TileIndex tile);
|
||||
void CDECL ModifyTile(TileIndex tile, uint flags, ...);
|
||||
void RunTileLoop(void);
|
||||
|
||||
uint GetPartialZ(int x, int y, int corners);
|
||||
uint GetSlopeZ(int x, int y);
|
||||
uint32 GetTileTrackStatus(uint tile, TransportType mode);
|
||||
void GetAcceptedCargo(uint tile, AcceptedCargo *ac);
|
||||
void ChangeTileOwner(uint tile, byte old_player, byte new_player);
|
||||
void AnimateTile(uint tile);
|
||||
void ClickTile(uint tile);
|
||||
void GetTileDesc(uint tile, TileDesc *td);
|
||||
uint32 GetTileTrackStatus(TileIndex tile, TransportType mode);
|
||||
void GetAcceptedCargo(TileIndex tile, AcceptedCargo ac);
|
||||
void ChangeTileOwner(TileIndex tile, byte old_player, byte new_player);
|
||||
void AnimateTile(TileIndex tile);
|
||||
void ClickTile(TileIndex tile);
|
||||
void GetTileDesc(TileIndex tile, TileDesc *td);
|
||||
void DrawTile(TileInfo *ti);
|
||||
void UpdateTownMaxPass(Town *t);
|
||||
|
||||
uint TileAddWrap(TileIndex tile, int addx, int addy);
|
||||
enum {
|
||||
TILE_WRAPPED = (uint)-1
|
||||
};
|
||||
|
||||
bool IsValidTile(uint tile);
|
||||
bool IsValidTile(TileIndex tile);
|
||||
|
||||
static inline Point RemapCoords(int x, int y, int z)
|
||||
{
|
||||
#if !defined(NEW_ROTATION)
|
||||
static Point FORCEINLINE RemapCoords(int x, int y, int z) { Point pt = { (y-x)*2, y + x -z }; return pt; }
|
||||
Point pt;
|
||||
pt.x = (y - x) * 2;
|
||||
pt.y = y + x - z;
|
||||
#else
|
||||
static Point FORCEINLINE RemapCoords(int x, int y, int z) { Point pt = { (x + y)*2, x - y -z }; return pt; }
|
||||
Point pt;
|
||||
pt.x = (x + y) * 2;
|
||||
pt.y = x - y - z;
|
||||
#endif
|
||||
return pt;
|
||||
}
|
||||
|
||||
static Point FORCEINLINE RemapCoords2(int x, int y) { return RemapCoords(x, y, GetSlopeZ(x, y)); }
|
||||
static inline Point RemapCoords2(int x, int y)
|
||||
{
|
||||
return RemapCoords(x, y, GetSlopeZ(x, y));
|
||||
}
|
||||
|
||||
/* game.c */
|
||||
byte *GetString(byte *buffr, uint16 string);
|
||||
void InjectDparam(int amount);
|
||||
|
||||
int32 GetParamInt32();
|
||||
int GetParamInt16();
|
||||
int GetParamInt8();
|
||||
int GetParamUint16();
|
||||
|
||||
|
||||
/* sound.c */
|
||||
void SndPlayTileFx(int sound, TileIndex tile);
|
||||
void SndPlayVehicleFx(int sound, Vehicle *v);
|
||||
void SndPlayFx(int sound);
|
||||
|
||||
/* clear_land.c */
|
||||
void DrawHillyLandTile(TileInfo *ti);
|
||||
void DrawClearLandTile(TileInfo *ti, byte set);
|
||||
void DrawClearLandFence(TileInfo *ti, byte img);
|
||||
void TileLoopClearHelper(uint tile);
|
||||
void TileLoopClearHelper(TileIndex tile);
|
||||
|
||||
/* station_land.c */
|
||||
void StationPickerDrawSprite(int x, int y, int railtype, int image);
|
||||
@@ -91,15 +78,34 @@ StringID GetPlayerNameString(byte player, byte index);
|
||||
void ShowInfo(const char *str);
|
||||
void CDECL ShowInfoF(const char *str, ...);
|
||||
void NORETURN CDECL error(const char *str, ...);
|
||||
void memswap(void *a, void *b, size_t size);
|
||||
|
||||
/* ttd.c */
|
||||
uint32 Random();
|
||||
uint RandomRange(uint max);
|
||||
|
||||
void InitPlayerRandoms();
|
||||
// **************
|
||||
// * Warning: DO NOT enable this unless you understand what it does
|
||||
// *
|
||||
// * If enabled, in a network game all randoms will be dumped to the
|
||||
// * stdout if the first client joins (or if you are a client). This
|
||||
// * is to help finding desync problems.
|
||||
// *
|
||||
// * Warning: DO NOT enable this unless you understand what it does
|
||||
// **************
|
||||
|
||||
uint32 InteractiveRandom(); /* Used for random sequences that are not the same on the other end of the multiplayer link */
|
||||
//#define RANDOM_DEBUG
|
||||
|
||||
#ifdef RANDOM_DEBUG
|
||||
#define Random() DoRandom(__LINE__, __FILE__)
|
||||
uint32 DoRandom(int line, const char *file);
|
||||
#define RandomRange(max) DoRandomRange(max, __LINE__, __FILE__)
|
||||
uint DoRandomRange(uint max, int line, const char *file);
|
||||
#else
|
||||
uint32 Random(void);
|
||||
uint RandomRange(uint max);
|
||||
#endif
|
||||
|
||||
void InitPlayerRandoms(void);
|
||||
|
||||
uint32 InteractiveRandom(void); /* Used for random sequences that are not the same on the other end of the multiplayer link */
|
||||
uint InteractiveRandomRange(uint max);
|
||||
|
||||
void SetDate(uint date);
|
||||
@@ -107,15 +113,21 @@ void SetDate(uint date);
|
||||
void DrawPlayerFace(uint32 face, int color, int x, int y);
|
||||
|
||||
/* texteff.c */
|
||||
void MoveAllTextEffects();
|
||||
void MoveAllTextEffects(void);
|
||||
void AddTextEffect(StringID msg, int x, int y, uint16 duration);
|
||||
void InitTextEffects();
|
||||
void InitTextEffects(void);
|
||||
void DrawTextEffects(DrawPixelInfo *dpi);
|
||||
|
||||
void InitTextMessage(void);
|
||||
void DrawTextMessage(void);
|
||||
void CDECL AddTextMessage(uint16 color, uint8 duration, const char *message, ...);
|
||||
void UndrawTextMessage(void);
|
||||
void TextMessageDailyLoop(void);
|
||||
|
||||
bool AddAnimatedTile(uint tile);
|
||||
void DeleteAnimatedTile(uint tile);
|
||||
void AnimateAnimatedTiles();
|
||||
void InitializeAnimatedTiles();
|
||||
void AnimateAnimatedTiles(void);
|
||||
void InitializeAnimatedTiles(void);
|
||||
|
||||
/* tunnelbridge_cmd.c */
|
||||
bool CheckTunnelInWay(uint tile, int z);
|
||||
@@ -123,68 +135,39 @@ bool CheckBridge_Stuff(byte bridge_type, int bridge_len);
|
||||
uint32 GetBridgeLength(TileIndex begin, TileIndex end);
|
||||
int CalcBridgeLenCostFactor(int x);
|
||||
|
||||
/* network.c */
|
||||
typedef void CommandCallback(bool success, uint tile, uint32 p1, uint32 p2);
|
||||
bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback, uint32 cmd);
|
||||
|
||||
void NetworkReceive();
|
||||
void NetworkSend();
|
||||
void NetworkProcessCommands();
|
||||
void NetworkListen();
|
||||
void NetworkInitialize();
|
||||
void NetworkShutdown();
|
||||
void NetworkSendCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback);
|
||||
void NetworkSendEvent(uint16 type, uint16 data_len, void * data);
|
||||
void NetworkStartSync(bool fcreset);
|
||||
void NetworkClose(bool client);
|
||||
void NetworkSendReadyPacket();
|
||||
void NetworkSendSyncPackets();
|
||||
void NetworkSendFrameSyncPackets();
|
||||
bool NetworkCheckClientReady();
|
||||
|
||||
void NetworkIPListInit();
|
||||
|
||||
void NetworkCoreInit();
|
||||
void NetworkCoreShutdown();
|
||||
void NetworkCoreDisconnect();
|
||||
void NetworkCoreLoop(bool incomming);
|
||||
bool NetworkCoreConnectGame(const byte* b, unsigned short port);
|
||||
bool NetworkCoreConnectGameStruct(NetworkGameList * item);
|
||||
bool NetworkCoreStartGame();
|
||||
|
||||
void NetworkLobbyShutdown();
|
||||
void NetworkLobbyInit();
|
||||
|
||||
void NetworkGameListClear();
|
||||
NetworkGameList * NetworkGameListAdd();
|
||||
void NetworkGameListFromLAN();
|
||||
void NetworkGameListFromInternet();
|
||||
NetworkGameList * NetworkGameListItem(uint16 index);
|
||||
|
||||
void NetworkGameFillDefaults();
|
||||
void NetworkGameChangeDate(uint16 newdate);
|
||||
/* network.c */
|
||||
void NetworkUDPClose(void);
|
||||
void NetworkStartUp(void);
|
||||
void NetworkShutDown(void);
|
||||
void NetworkGameLoop(void);
|
||||
void NetworkUDPGameLoop(void);
|
||||
bool NetworkServerStart(void);
|
||||
bool NetworkClientConnectGame(const char* host, unsigned short port);
|
||||
void NetworkReboot(void);
|
||||
void NetworkDisconnect(void);
|
||||
void NetworkSend_Command(uint32 tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback);
|
||||
|
||||
/* misc_cmd.c */
|
||||
void PlaceTreesRandomly();
|
||||
|
||||
uint GetTileDist(TileIndex xy1, TileIndex xy2);
|
||||
uint GetTileDist1D(TileIndex xy1, TileIndex xy2);
|
||||
uint GetTileDist1Db(TileIndex xy1, TileIndex xy2);
|
||||
uint GetTileDistAdv(TileIndex xy1, TileIndex xy2);
|
||||
bool CheckDistanceFromEdge(TileIndex tile, uint distance);
|
||||
void PlaceTreesRandomly(void);
|
||||
|
||||
void InitializeLandscapeVariables(bool only_constants);
|
||||
|
||||
/* misc.c */
|
||||
void DeleteName(StringID id);
|
||||
byte *GetName(int id, byte *buff);
|
||||
StringID AllocateName(const byte *name, byte skip);
|
||||
char *GetName(int id, char *buff);
|
||||
|
||||
// AllocateNameUnique also tests if the name used is not used anywere else
|
||||
// and if it is used, it returns an error.
|
||||
#define AllocateNameUnique(name, skip) RealAllocateName(name, skip, true)
|
||||
#define AllocateName(name, skip) RealAllocateName(name, skip, false)
|
||||
StringID RealAllocateName(const char *name, byte skip, bool check_double);
|
||||
void ConvertDayToYMD(YearMonthDay *ymd, uint16 date);
|
||||
uint ConvertYMDToDay(uint year, uint month, uint day);
|
||||
uint ConvertIntDate(uint date);
|
||||
|
||||
|
||||
|
||||
/* misc functions */
|
||||
void MarkTileDirty(int x, int y);
|
||||
void MarkTileDirtyByTile(TileIndex tile);
|
||||
@@ -192,11 +175,12 @@ void InvalidateWindow(byte cls, WindowNumber number);
|
||||
void InvalidateWindowWidget(byte cls, WindowNumber number, byte widget_index);
|
||||
void InvalidateWindowClasses(byte cls);
|
||||
void DeleteWindowById(WindowClass cls, WindowNumber number);
|
||||
void DeleteWindowByClass(WindowClass cls);
|
||||
|
||||
void SetObjectToPlaceWnd(int icon, byte mode, Window *w);
|
||||
void SetObjectToPlace(int icon, byte mode, byte window_class, uint16 window_num);
|
||||
void SetObjectToPlace(int icon, byte mode, WindowClass window_class, WindowNumber window_num);
|
||||
|
||||
void ResetObjectToPlace();
|
||||
void ResetObjectToPlace(void);
|
||||
|
||||
bool ScrollWindowToTile(TileIndex tile, Window * w);
|
||||
bool ScrollWindowTo(int x, int y, Window * w);
|
||||
@@ -204,11 +188,11 @@ bool ScrollWindowTo(int x, int y, Window * w);
|
||||
bool ScrollMainWindowToTile(TileIndex tile);
|
||||
bool ScrollMainWindowTo(int x, int y);
|
||||
void DrawSprite(uint32 img, int x, int y);
|
||||
uint GetCorrectTileHeight(TileIndex tile);
|
||||
bool EnsureNoVehicle(TileIndex tile);
|
||||
bool EnsureNoVehicleZ(TileIndex tile, byte z);
|
||||
void MarkAllViewportsDirty(int left, int top, int right, int bottom);
|
||||
void ShowCostOrIncomeAnimation(int x, int y, int z, int32 cost);
|
||||
void MarkWholeScreenDirty();
|
||||
|
||||
void DrawFoundation(TileInfo *ti, uint f);
|
||||
|
||||
@@ -218,11 +202,13 @@ void ChangeTownRating(Town *t, int add, int max);
|
||||
|
||||
uint GetRoadBitsByTile(TileIndex tile);
|
||||
int GetTownRadiusGroup(Town *t, uint tile);
|
||||
int32 GetTransportedGoodsIncome(uint num_pieces, uint dist, byte transit_days, byte cargo_type);
|
||||
void ShowRenameSignWindow(SignStruct *ss);
|
||||
void ShowRenameCheckpointWindow(Checkpoint *cp);
|
||||
void ShowNetworkChatQueryWindow(byte desttype, byte dest);
|
||||
void ShowNetworkGiveMoneyWindow(byte player);
|
||||
void ShowNetworkNeedGamePassword(void);
|
||||
void ShowNetworkNeedCompanyPassword(void);
|
||||
int FindFirstBit(uint32 x);
|
||||
void ShowHighscoreTable(int tbl);
|
||||
void ShowHighscoreTable(int difficulty, int8 rank);
|
||||
void ShowEndGameChart(void);
|
||||
TileIndex AdjustTileCoordRandomly(TileIndex a, byte rng);
|
||||
|
||||
enum SaveOrLoadResult {
|
||||
@@ -239,11 +225,13 @@ enum SaveOrLoadMode {
|
||||
|
||||
int SaveOrLoad(const char *filename, int mode);
|
||||
|
||||
void AfterLoadTown();
|
||||
void AskExitGame();
|
||||
void AskExitToGameMenu();
|
||||
void AfterLoadTown(void);
|
||||
void GenRandomNewGame(uint32 rnd1, uint32 rnd2);
|
||||
void StartScenarioEditor(uint32 rnd1, uint32 rnd2);
|
||||
void AskExitGame(void);
|
||||
void AskExitToGameMenu(void);
|
||||
|
||||
void RedrawAutosave();
|
||||
void RedrawAutosave(void);
|
||||
|
||||
StringID RemapOldStringID(StringID s);
|
||||
|
||||
@@ -258,29 +246,24 @@ enum {
|
||||
};
|
||||
void ShowSaveLoadDialog(int mode);
|
||||
|
||||
void ttd_strlcpy(char *dst, const char *src, size_t len);
|
||||
|
||||
// callback from drivers that is called if the game size changes dynamically
|
||||
void GameSizeChanged();
|
||||
bool MakeScreenshot();
|
||||
bool MakeWorldScreenshot(int left, int top, int width, int height, int zoom);
|
||||
void GameSizeChanged(void);
|
||||
bool FileExists(const char *filename);
|
||||
bool ReadLanguagePack(int index);
|
||||
void InitializeLanguagePacks();
|
||||
byte *ReadFileToMem(const char *filename, size_t *lenp, size_t maxsize);
|
||||
void InitializeLanguagePacks(void);
|
||||
void *ReadFileToMem(const char *filename, size_t *lenp, size_t maxsize);
|
||||
int GetLanguageList(char **languages, int max);
|
||||
|
||||
const char *GetScreenshotFormatDesc(int i);
|
||||
void InitializeScreenshotFormats();
|
||||
void SetScreenshotFormat(int i);
|
||||
void CheckSwitchToEuro();
|
||||
void CheckSwitchToEuro(void);
|
||||
|
||||
void LoadFromConfig();
|
||||
void SaveToConfig();
|
||||
void LoadFromConfig(void);
|
||||
void SaveToConfig(void);
|
||||
void CheckConfig(void);
|
||||
int ttd_main(int argc, char* argv[]);
|
||||
byte GetOSVersion();
|
||||
byte GetOSVersion(void);
|
||||
|
||||
void DeterminePaths();
|
||||
void DeterminePaths(void);
|
||||
char * CDECL str_fmt(const char *str, ...);
|
||||
|
||||
void bubblesort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *));
|
||||
#endif /* FUNCTIONS_H */
|
||||
|
||||
@@ -1,33 +1,35 @@
|
||||
#include "stdafx.h"
|
||||
#include "ttd.h"
|
||||
#include "spritecache.h"
|
||||
#include "strings.h"
|
||||
#include "gfx.h"
|
||||
#include "table/palettes.h"
|
||||
#include "hal.h"
|
||||
|
||||
static void GfxMainBlitter(byte *sprite, int x, int y, int mode);
|
||||
void GfxInitPalettes();
|
||||
static void GfxMainBlitter(const Sprite *sprite, int x, int y, int mode);
|
||||
|
||||
static int _stringwidth_out;
|
||||
static byte _cursor_backup[64*64];
|
||||
static Rect _invalid_rect;
|
||||
static byte *_color_remap_ptr;
|
||||
static const byte *_color_remap_ptr;
|
||||
static byte _string_colorremap[3];
|
||||
|
||||
#define DIRTY_BYTES_PER_LINE (MAX_SCREEN_WIDTH/64)
|
||||
static byte _dirty_blocks[DIRTY_BYTES_PER_LINE * MAX_SCREEN_HEIGHT / 8];
|
||||
|
||||
|
||||
static void memcpy_pitch(void *d, void *s, int w, int h, int spitch, int dpitch)
|
||||
|
||||
void memcpy_pitch(void *d, void *s, int w, int h, int spitch, int dpitch)
|
||||
{
|
||||
byte *dp = (byte*)d;
|
||||
byte *sp = (byte*)s;
|
||||
|
||||
assert(h >= 0);
|
||||
if (h != 0) do {
|
||||
for (; h != 0; --h) {
|
||||
memcpy(dp, sp, w);
|
||||
dp += dpitch;
|
||||
sp += spitch;
|
||||
} while (--h);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,12 +43,13 @@ void GfxScroll(int left, int top, int width, int height, int xo, int yo) {
|
||||
|
||||
if (_cursor.visible)
|
||||
UndrawMouseCursor();
|
||||
UndrawTextMessage();
|
||||
|
||||
p = _screen.pitch;
|
||||
|
||||
if (yo > 0 || (yo == 0 && xo > 0)) {
|
||||
if (yo > 0) {
|
||||
// Calculate pointers
|
||||
dst = _screen.dst_ptr + (top+height-1) * p + (left+width-1);
|
||||
dst = _screen.dst_ptr + (top + height - 1) * p + left;
|
||||
src = dst - yo * p;
|
||||
|
||||
// Decrease height and increase top
|
||||
@@ -56,31 +59,21 @@ void GfxScroll(int left, int top, int width, int height, int xo, int yo) {
|
||||
|
||||
// Adjust left & width
|
||||
if (xo >= 0) {
|
||||
dst += xo;
|
||||
left += xo;
|
||||
src -= xo;
|
||||
width -= xo;
|
||||
} else {
|
||||
dst += xo;
|
||||
src -= xo;
|
||||
width += xo;
|
||||
}
|
||||
|
||||
// Offset pointers to fit into the memmove call
|
||||
dst += -width + 1;
|
||||
src += -width + 1;
|
||||
ht = height;
|
||||
|
||||
do {
|
||||
memmove(dst, src, width);
|
||||
for (ht = height; ht > 0; --ht) {
|
||||
memcpy(dst, src, width);
|
||||
src -= p;
|
||||
dst -= p;
|
||||
} while (--ht);
|
||||
|
||||
|
||||
// This part of the screen is now dirty.
|
||||
_video_driver->make_dirty(left, top, width, height);
|
||||
|
||||
}
|
||||
} else {
|
||||
// Calculate pointers to mem.
|
||||
// Calculate pointers
|
||||
dst = _screen.dst_ptr + top * p + left;
|
||||
src = dst - yo * p;
|
||||
|
||||
@@ -98,23 +91,24 @@ void GfxScroll(int left, int top, int width, int height, int xo, int yo) {
|
||||
width += xo;
|
||||
}
|
||||
|
||||
ht = height;
|
||||
|
||||
do {
|
||||
memcpy(dst, src, width);
|
||||
// the y-displacement may be 0 therefore we have to use memmove,
|
||||
// because source and destination may overlap
|
||||
for (ht = height; ht > 0; --ht) {
|
||||
memmove(dst, src, width);
|
||||
src += p;
|
||||
dst += p;
|
||||
} while (--ht);
|
||||
|
||||
// This part of the screen is now dirty.
|
||||
_video_driver->make_dirty(left, top, width, height);
|
||||
}
|
||||
}
|
||||
// This part of the screen is now dirty.
|
||||
_video_driver->make_dirty(left, top, width, height);
|
||||
}
|
||||
|
||||
|
||||
void GfxFillRect(int left, int top, int right, int bottom, int color) {
|
||||
DrawPixelInfo *dpi = _cur_dpi;
|
||||
byte *dst,*ctab;
|
||||
byte *dst;
|
||||
const int otop = top;
|
||||
const int oleft = left;
|
||||
|
||||
if (dpi->zoom != 0)
|
||||
return;
|
||||
@@ -150,7 +144,8 @@ void GfxFillRect(int left, int top, int right, int bottom, int color) {
|
||||
} while (--bottom);
|
||||
} else {
|
||||
/* use colortable mode */
|
||||
ctab = GetSpritePtr(color & 0x3FFF) + 1;
|
||||
const byte* ctab = GetNonSprite(color & 0x3FFF) + 1;
|
||||
|
||||
do {
|
||||
int i;
|
||||
for(i=0; i!=right;i++)
|
||||
@@ -159,19 +154,17 @@ void GfxFillRect(int left, int top, int right, int bottom, int color) {
|
||||
} while (--bottom);
|
||||
}
|
||||
} else {
|
||||
byte bo = 0;
|
||||
byte bo = (oleft - left + dpi->left + otop - top + dpi->top) & 1;
|
||||
do {
|
||||
int i;
|
||||
byte b = (bo^=1);
|
||||
for(i=0; i!=right;i++)
|
||||
if ((b^=1) != 0)
|
||||
dst[i] = (byte)color;
|
||||
for (i = (bo ^= 1); i < right; i += 2)
|
||||
dst[i] = (byte)color;
|
||||
dst += dpi->pitch;
|
||||
} while (--bottom);
|
||||
} while (--bottom > 0);
|
||||
}
|
||||
}
|
||||
|
||||
void GfxSetPixel(int x, int y, int color)
|
||||
static void GfxSetPixel(int x, int y, int color)
|
||||
{
|
||||
DrawPixelInfo *dpi = _cur_dpi;
|
||||
if ((x-=dpi->left) < 0 || x>=dpi->width || (y-=dpi->top)<0 || y>=dpi->height)
|
||||
@@ -251,8 +244,6 @@ void GfxDrawLine(int x, int y, int x2, int y2, int color)
|
||||
|
||||
|
||||
enum {
|
||||
ASCII_LETTERSTART = 32,
|
||||
|
||||
ASCII_SETX = 1,
|
||||
ASCII_SETXY = 2,
|
||||
|
||||
@@ -265,46 +256,49 @@ enum {
|
||||
|
||||
|
||||
/* returns right coordinate */
|
||||
int DrawString(int x, int y, uint16 str, byte color)
|
||||
int DrawString(int x, int y, uint16 str, uint16 color)
|
||||
{
|
||||
GetString(str_buffr, str);
|
||||
assert(strlen(str_buffr) < sizeof(str_buffr) - 1);
|
||||
return DoDrawString(str_buffr, x, y, color);
|
||||
char buffer[512];
|
||||
|
||||
GetString(buffer, str);
|
||||
return DoDrawString(buffer, x, y, color);
|
||||
}
|
||||
|
||||
|
||||
void DrawStringRightAligned(int x, int y, uint16 str, byte color)
|
||||
void DrawStringRightAligned(int x, int y, uint16 str, uint16 color)
|
||||
{
|
||||
GetString(str_buffr, str);
|
||||
assert(strlen(str_buffr) < sizeof(str_buffr) - 1);
|
||||
DoDrawString(str_buffr, x - GetStringWidth(str_buffr), y, color);
|
||||
char buffer[512];
|
||||
|
||||
GetString(buffer, str);
|
||||
DoDrawString(buffer, x - GetStringWidth(buffer), y, color);
|
||||
}
|
||||
|
||||
|
||||
int DrawStringCentered(int x, int y, uint16 str, byte color)
|
||||
int DrawStringCentered(int x, int y, uint16 str, uint16 color)
|
||||
{
|
||||
char buffer[512];
|
||||
int w;
|
||||
|
||||
GetString(str_buffr, str);
|
||||
assert(strlen(str_buffr) < sizeof(str_buffr) - 1);
|
||||
GetString(buffer, str);
|
||||
|
||||
w = GetStringWidth(str_buffr);
|
||||
DoDrawString(str_buffr, x - (w>>1), y, color);
|
||||
w = GetStringWidth(buffer);
|
||||
DoDrawString(buffer, x - w / 2, y, color);
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
void DrawStringCenterUnderline(int x, int y, uint16 str, byte color)
|
||||
void DrawStringCenterUnderline(int x, int y, uint16 str, uint16 color)
|
||||
{
|
||||
int w = DrawStringCentered(x, y, str, color);
|
||||
GfxFillRect(x-(w>>1), y+10, x-(w>>1)+w, y+10, _string_colorremap[1]);
|
||||
}
|
||||
|
||||
uint32 FormatStringLinebreaks(byte *str, int maxw) {
|
||||
static uint32 FormatStringLinebreaks(char *str, int maxw)
|
||||
{
|
||||
int num = 0;
|
||||
int base = _stringwidth_base;
|
||||
int w;
|
||||
byte *last_space;
|
||||
char *last_space;
|
||||
byte c;
|
||||
|
||||
for(;;) {
|
||||
@@ -313,10 +307,10 @@ uint32 FormatStringLinebreaks(byte *str, int maxw) {
|
||||
|
||||
for(;;) {
|
||||
c = *str++;
|
||||
if (c == ' ') last_space = str;
|
||||
if (c == ASCII_LETTERSTART) last_space = str;
|
||||
|
||||
if (c >= ASCII_LETTERSTART) {
|
||||
w += _stringwidth_table[base + ((byte)c) - 0x20];
|
||||
w += GetCharacterWidth(base + (byte)c);
|
||||
if (w > maxw) {
|
||||
str = last_space;
|
||||
if (str == NULL)
|
||||
@@ -342,15 +336,15 @@ uint32 FormatStringLinebreaks(byte *str, int maxw) {
|
||||
|
||||
void DrawStringMultiCenter(int x, int y, uint16 str, int maxw)
|
||||
{
|
||||
char buffer[512];
|
||||
uint32 tmp;
|
||||
int num, w, mt, t;
|
||||
byte *src;
|
||||
const char *src;
|
||||
byte c;
|
||||
|
||||
GetString(str_buffr, str);
|
||||
assert(strlen(str_buffr) < sizeof(str_buffr) - 1);
|
||||
GetString(buffer, str);
|
||||
|
||||
tmp = FormatStringLinebreaks(str_buffr, maxw);
|
||||
tmp = FormatStringLinebreaks(buffer, maxw);
|
||||
num = (uint16)tmp;
|
||||
t = tmp >> 16;
|
||||
|
||||
@@ -362,7 +356,7 @@ void DrawStringMultiCenter(int x, int y, uint16 str, int maxw)
|
||||
|
||||
y -= (mt >> 1) * num;
|
||||
|
||||
src = str_buffr;
|
||||
src = buffer;
|
||||
|
||||
for(;;) {
|
||||
w = GetStringWidth(src);
|
||||
@@ -388,15 +382,15 @@ void DrawStringMultiCenter(int x, int y, uint16 str, int maxw)
|
||||
}
|
||||
|
||||
void DrawStringMultiLine(int x, int y, uint16 str, int maxw) {
|
||||
char buffer[512];
|
||||
uint32 tmp;
|
||||
int num, w, mt, t;
|
||||
byte *src;
|
||||
const char *src;
|
||||
byte c;
|
||||
|
||||
GetString(str_buffr, str);
|
||||
assert(strlen(str_buffr) < sizeof(str_buffr) - 1);
|
||||
GetString(buffer, str);
|
||||
|
||||
tmp = FormatStringLinebreaks(str_buffr, maxw);
|
||||
tmp = FormatStringLinebreaks(buffer, maxw);
|
||||
num = (uint16)tmp;
|
||||
t = tmp >> 16;
|
||||
mt = 10;
|
||||
@@ -405,7 +399,7 @@ void DrawStringMultiLine(int x, int y, uint16 str, int maxw) {
|
||||
if (t != 244) mt = 18;
|
||||
}
|
||||
|
||||
src = str_buffr;
|
||||
src = buffer;
|
||||
|
||||
for(;;) {
|
||||
w = GetStringWidth(src);
|
||||
@@ -430,17 +424,14 @@ void DrawStringMultiLine(int x, int y, uint16 str, int maxw) {
|
||||
}
|
||||
}
|
||||
|
||||
int GetStringWidth(const byte *str) {
|
||||
int w = -1;
|
||||
int GetStringWidth(const char *str)
|
||||
{
|
||||
int w = 0;
|
||||
byte c;
|
||||
int base = _stringwidth_base;
|
||||
|
||||
for(;;) {
|
||||
c = *str++;
|
||||
if (c == 0)
|
||||
return w;
|
||||
for (c = *str; c != '\0'; c = *(++str)) {
|
||||
if (c >= ASCII_LETTERSTART) {
|
||||
w += _stringwidth_table[base + c - ASCII_LETTERSTART];
|
||||
w += GetCharacterWidth(base + c);
|
||||
} else {
|
||||
if (c == ASCII_SETX) str++;
|
||||
else if (c == ASCII_SETXY) str += 2;
|
||||
@@ -448,6 +439,7 @@ int GetStringWidth(const byte *str) {
|
||||
else if (c == ASCII_BIGFONT) base = 448;
|
||||
}
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
||||
void DrawFrameRect(int left, int top, int right, int bottom, int ctab, int flags) {
|
||||
@@ -483,12 +475,16 @@ void DrawFrameRect(int left, int top, int right, int bottom, int ctab, int flags
|
||||
}
|
||||
}
|
||||
|
||||
int DoDrawString(const byte *string, int x, int y, byte color) {
|
||||
int DoDrawString(const char *string, int x, int y, uint16 real_color)
|
||||
{
|
||||
DrawPixelInfo *dpi = _cur_dpi;
|
||||
int base = _stringwidth_base;
|
||||
byte c, *b;
|
||||
byte c;
|
||||
byte color;
|
||||
int xo = x, yo = y;
|
||||
|
||||
color = real_color & 0xFF;
|
||||
|
||||
if (color != 0xFE) {
|
||||
if (x >= dpi->left + dpi->width ||
|
||||
x + _screen.width*2 <= dpi->left ||
|
||||
@@ -498,9 +494,13 @@ int DoDrawString(const byte *string, int x, int y, byte color) {
|
||||
|
||||
if (color != 0xFF) {
|
||||
switch_color:;
|
||||
b = GetSpritePtr(674);
|
||||
_string_colorremap[1] = b[color*2+8];
|
||||
_string_colorremap[2] = b[color*2+9];
|
||||
if (real_color & IS_PALETTE_COLOR) {
|
||||
_string_colorremap[1] = color;
|
||||
_string_colorremap[2] = 215;
|
||||
} else {
|
||||
_string_colorremap[1] = _string_colormap[color].text;
|
||||
_string_colorremap[2] = _string_colormap[color].shadow;
|
||||
}
|
||||
_color_remap_ptr = _string_colorremap;
|
||||
}
|
||||
}
|
||||
@@ -524,9 +524,9 @@ skip_cont:;
|
||||
if (c >= ASCII_LETTERSTART) {
|
||||
if (x >= dpi->left + dpi->width) goto skip_char;
|
||||
if (x + 26 >= dpi->left) {
|
||||
GfxMainBlitter(GetSpritePtr(base + 2 + c - ASCII_LETTERSTART), x, y, 1);
|
||||
GfxMainBlitter(GetSprite(base + 2 + c - ASCII_LETTERSTART), x, y, 1);
|
||||
}
|
||||
x += _stringwidth_table[base + c - ' '];
|
||||
x += GetCharacterWidth(base + c);
|
||||
} else if (c == ASCII_NL) { // newline = {}
|
||||
x = xo;
|
||||
y += 10;
|
||||
@@ -540,10 +540,10 @@ skip_cont:;
|
||||
color = (byte)(c - ASCII_COLORSTART);
|
||||
goto switch_color;
|
||||
} else if (c == ASCII_SETX) { // {SETX}
|
||||
x = xo + *string++;
|
||||
x = xo + (byte)*string++;
|
||||
} else if (c == ASCII_SETXY) {// {SETXY}
|
||||
x = xo + *string++;
|
||||
y = yo + *string++;
|
||||
x = xo + (byte)*string++;
|
||||
y = yo + (byte)*string++;
|
||||
} else if (c == ASCII_TINYFONT) { // {TINYFONT}
|
||||
base = 0xE0;
|
||||
} else if (c == ASCII_BIGFONT) { // {BIGFONT}
|
||||
@@ -556,19 +556,20 @@ skip_cont:;
|
||||
|
||||
void DrawSprite(uint32 img, int x, int y) {
|
||||
if (img & 0x8000) {
|
||||
_color_remap_ptr = GetSpritePtr(img >> 16) + 1;
|
||||
GfxMainBlitter(GetSpritePtr(img & 0x3FFF), x, y, 1);
|
||||
_color_remap_ptr = GetNonSprite(img >> 16) + 1;
|
||||
GfxMainBlitter(GetSprite(img & 0x3FFF), x, y, 1);
|
||||
} else if (img & 0x4000) {
|
||||
_color_remap_ptr = GetSpritePtr(img >> 16) + 1;
|
||||
GfxMainBlitter(GetSpritePtr(img & 0x3FFF), x, y, 2);
|
||||
_color_remap_ptr = GetNonSprite(img >> 16) + 1;
|
||||
GfxMainBlitter(GetSprite(img & 0x3FFF), x, y, 2);
|
||||
} else {
|
||||
GfxMainBlitter(GetSpritePtr(img & 0x3FFF), x, y, 0);
|
||||
GfxMainBlitter(GetSprite(img & 0x3FFF), x, y, 0);
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct BlitterParams {
|
||||
int start_x, start_y;
|
||||
byte *sprite, *sprite_org;
|
||||
const byte* sprite;
|
||||
const byte* sprite_org;
|
||||
byte *dst;
|
||||
int mode;
|
||||
int width, height;
|
||||
@@ -579,10 +580,12 @@ typedef struct BlitterParams {
|
||||
|
||||
static void GfxBlitTileZoomIn(BlitterParams *bp)
|
||||
{
|
||||
byte *src_o = bp->sprite, *src;
|
||||
const byte* src_o = bp->sprite;
|
||||
const byte* src;
|
||||
int num, skip;
|
||||
byte done;
|
||||
byte *dst, *ctab;
|
||||
byte *dst;
|
||||
const byte* ctab;
|
||||
|
||||
if (bp->mode & 1) {
|
||||
src_o += READ_LE_UINT16(src_o + bp->start_y * 2);
|
||||
@@ -721,7 +724,7 @@ static void GfxBlitTileZoomIn(BlitterParams *bp)
|
||||
|
||||
static void GfxBlitZoomInUncomp(BlitterParams *bp)
|
||||
{
|
||||
byte *src = bp->sprite;
|
||||
const byte *src = bp->sprite;
|
||||
byte *dst = bp->dst;
|
||||
int height = bp->height;
|
||||
int width = bp->width;
|
||||
@@ -732,7 +735,7 @@ static void GfxBlitZoomInUncomp(BlitterParams *bp)
|
||||
|
||||
if (bp->mode & 1) {
|
||||
if (bp->info & 1) {
|
||||
byte *ctab = _color_remap_ptr;
|
||||
const byte *ctab = _color_remap_ptr;
|
||||
byte b;
|
||||
|
||||
do {
|
||||
@@ -746,7 +749,8 @@ static void GfxBlitZoomInUncomp(BlitterParams *bp)
|
||||
}
|
||||
} else if (bp->mode & 2) {
|
||||
if (bp->info & 1) {
|
||||
byte *ctab = _color_remap_ptr;
|
||||
const byte *ctab = _color_remap_ptr;
|
||||
|
||||
do {
|
||||
for(i=0; i!=width; i++)
|
||||
if (src[i])
|
||||
@@ -793,10 +797,12 @@ static void GfxBlitZoomInUncomp(BlitterParams *bp)
|
||||
|
||||
static void GfxBlitTileZoomMedium(BlitterParams *bp)
|
||||
{
|
||||
byte *src_o = bp->sprite, *src;
|
||||
const byte* src_o = bp->sprite;
|
||||
const byte* src;
|
||||
int num, skip;
|
||||
byte done;
|
||||
byte *dst, *ctab;
|
||||
byte *dst;
|
||||
const byte* ctab;
|
||||
|
||||
if (bp->mode & 1) {
|
||||
src_o += READ_LE_UINT16(src_o + bp->start_y * 2);
|
||||
@@ -969,7 +975,7 @@ static void GfxBlitTileZoomMedium(BlitterParams *bp)
|
||||
|
||||
static void GfxBlitZoomMediumUncomp(BlitterParams *bp)
|
||||
{
|
||||
byte *src = bp->sprite;
|
||||
const byte *src = bp->sprite;
|
||||
byte *dst = bp->dst;
|
||||
int height = bp->height;
|
||||
int width = bp->width;
|
||||
@@ -980,7 +986,9 @@ static void GfxBlitZoomMediumUncomp(BlitterParams *bp)
|
||||
|
||||
if (bp->mode & 1) {
|
||||
if (bp->info & 1) {
|
||||
byte *ctab = _color_remap_ptr,b;
|
||||
const byte *ctab = _color_remap_ptr;
|
||||
byte b;
|
||||
|
||||
height >>= 1;
|
||||
if (height) do {
|
||||
for(i=0; i!=width>>1; i++)
|
||||
@@ -992,7 +1000,8 @@ static void GfxBlitZoomMediumUncomp(BlitterParams *bp)
|
||||
}
|
||||
} else if (bp->mode & 2) {
|
||||
if (bp->info & 1) {
|
||||
byte *ctab = _color_remap_ptr;
|
||||
const byte *ctab = _color_remap_ptr;
|
||||
|
||||
height >>= 1;
|
||||
if (height) do {
|
||||
for(i=0; i!=width>>1; i++)
|
||||
@@ -1018,10 +1027,12 @@ static void GfxBlitZoomMediumUncomp(BlitterParams *bp)
|
||||
|
||||
static void GfxBlitTileZoomOut(BlitterParams *bp)
|
||||
{
|
||||
byte *src_o = bp->sprite, *src;
|
||||
const byte* src_o = bp->sprite;
|
||||
const byte* src;
|
||||
int num, skip;
|
||||
byte done;
|
||||
byte *dst, *ctab;
|
||||
byte *dst;
|
||||
const byte* ctab;
|
||||
|
||||
if (bp->mode & 1) {
|
||||
src_o += READ_LE_UINT16(src_o + bp->start_y * 2);
|
||||
@@ -1260,7 +1271,7 @@ static void GfxBlitTileZoomOut(BlitterParams *bp)
|
||||
|
||||
static void GfxBlitZoomOutUncomp(BlitterParams *bp)
|
||||
{
|
||||
byte *src = bp->sprite;
|
||||
const byte* src = bp->sprite;
|
||||
byte *dst = bp->dst;
|
||||
int height = bp->height;
|
||||
int width = bp->width;
|
||||
@@ -1271,7 +1282,9 @@ static void GfxBlitZoomOutUncomp(BlitterParams *bp)
|
||||
|
||||
if (bp->mode & 1) {
|
||||
if (bp->info & 1) {
|
||||
byte *ctab = _color_remap_ptr,b;
|
||||
const byte *ctab = _color_remap_ptr;
|
||||
byte b;
|
||||
|
||||
height >>= 2;
|
||||
if (height) do {
|
||||
for(i=0; i!=width>>2; i++)
|
||||
@@ -1283,7 +1296,8 @@ static void GfxBlitZoomOutUncomp(BlitterParams *bp)
|
||||
}
|
||||
} else if (bp->mode & 2) {
|
||||
if (bp->info & 1) {
|
||||
byte *ctab = _color_remap_ptr;
|
||||
const byte *ctab = _color_remap_ptr;
|
||||
|
||||
height >>= 2;
|
||||
if (height) do {
|
||||
for(i=0; i!=width>>2; i++)
|
||||
@@ -1309,7 +1323,7 @@ static void GfxBlitZoomOutUncomp(BlitterParams *bp)
|
||||
|
||||
typedef void (*BlitZoomFunc)(BlitterParams *bp);
|
||||
|
||||
static void GfxMainBlitter(byte *sprite, int x, int y, int mode)
|
||||
static void GfxMainBlitter(const Sprite* sprite, int x, int y, int mode)
|
||||
{
|
||||
DrawPixelInfo *dpi = _cur_dpi;
|
||||
int start_x, start_y;
|
||||
@@ -1331,13 +1345,13 @@ static void GfxMainBlitter(byte *sprite, int x, int y, int mode)
|
||||
};
|
||||
|
||||
/* decode sprite header */
|
||||
x += (int16)READ_LE_UINT16(&((SpriteHdr*)sprite)->x_offs);
|
||||
y += (int16)READ_LE_UINT16(&((SpriteHdr*)sprite)->y_offs);
|
||||
bp.width_org = bp.width = READ_LE_UINT16(&((SpriteHdr*)sprite)->width);
|
||||
bp.height_org = bp.height = ((SpriteHdr*)sprite)->height;
|
||||
info = ((SpriteHdr*)sprite)->info;
|
||||
x += sprite->x_offs;
|
||||
y += sprite->y_offs;
|
||||
bp.width_org = bp.width = sprite->width;
|
||||
bp.height_org = bp.height = sprite->height;
|
||||
info = sprite->info;
|
||||
bp.info = info;
|
||||
bp.sprite_org = bp.sprite = sprite + sizeof(SpriteHdr);
|
||||
bp.sprite_org = bp.sprite = sprite->data;
|
||||
bp.dst = dpi->dst_ptr;
|
||||
bp.mode = mode;
|
||||
bp.pitch = dpi->pitch;
|
||||
@@ -1434,10 +1448,10 @@ static void GfxMainBlitter(byte *sprite, int x, int y, int mode)
|
||||
if (info&2) {
|
||||
int totpix = bp.height_org * bp.width_org;
|
||||
byte *dst = (byte*)alloca(totpix);
|
||||
byte *src = bp.sprite_org;
|
||||
const byte *src = bp.sprite_org;
|
||||
signed char b;
|
||||
|
||||
bp.sprite += (dst - src);
|
||||
bp.sprite = dst + (bp.sprite - bp.sprite_org);
|
||||
|
||||
while (totpix != 0) {
|
||||
assert(totpix > 0);
|
||||
@@ -1465,8 +1479,8 @@ static void GfxMainBlitter(byte *sprite, int x, int y, int mode)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GfxScalePalette(int pal, byte scaling)
|
||||
#if 0
|
||||
static void GfxScalePalette(int pal, byte scaling)
|
||||
{
|
||||
byte *dst, *src;
|
||||
size_t count;
|
||||
@@ -1484,30 +1498,39 @@ void GfxScalePalette(int pal, byte scaling)
|
||||
src += 3;
|
||||
} while (--count);
|
||||
}
|
||||
#endif
|
||||
|
||||
void GfxInitPalettes()
|
||||
void DoPaletteAnimations(void);
|
||||
|
||||
void GfxInitPalettes(void)
|
||||
{
|
||||
memcpy(_cur_palette, _palettes[0], 256*3);
|
||||
int pal = _use_dos_palette?1:0;
|
||||
memcpy(_cur_palette, _palettes[pal], 256*3);
|
||||
|
||||
_pal_first_dirty = 0;
|
||||
_pal_last_dirty = 255;
|
||||
DoPaletteAnimations();
|
||||
}
|
||||
|
||||
|
||||
#define EXTR(p,q) (((uint16)(_timer_counter * (p)) * (q)) >> 16)
|
||||
#define EXTR2(p,q) (((uint16)(~_timer_counter * (p)) * (q)) >> 16)
|
||||
#define COPY_TRIPLET do {d[0]=s[0+j]; d[1]=s[1+j]; d[2]=s[2+j];d+=3;}while(0)
|
||||
|
||||
void DoPaletteAnimations()
|
||||
void DoPaletteAnimations(void)
|
||||
{
|
||||
const byte *s;
|
||||
byte *d;
|
||||
/* Amount of colors to be rotated.
|
||||
* A few more for the DOS palette, because the water colors are
|
||||
* 245-254 for DOS and 217-226 for Windows. */
|
||||
int c = _use_dos_palette?38:28;
|
||||
int j;
|
||||
int i;
|
||||
const ExtraPaletteValues *ev = &_extra_palette_values;
|
||||
byte old_val[28*3];
|
||||
byte old_val[114]; // max(c*(38:28)) = 114
|
||||
|
||||
d = _cur_palette + 217*3;
|
||||
memcpy(old_val, d, 28*3);
|
||||
memcpy(old_val, d, c*3);
|
||||
|
||||
// Dark blue water
|
||||
s = ev->a;
|
||||
@@ -1576,14 +1599,37 @@ void DoPaletteAnimations()
|
||||
if (j == 3*4) j = 0;
|
||||
}
|
||||
|
||||
if (memcmp(old_val, _cur_palette + 217*3, 28*3)) {
|
||||
// Animate water for old DOS graphics
|
||||
if(_use_dos_palette) {
|
||||
// Dark blue water DOS
|
||||
s = ev->a;
|
||||
if (_opt.landscape == LT_CANDY) s = ev->ac;
|
||||
j = EXTR(320,5) * 3;
|
||||
for(i=0; i!=5; i++) {
|
||||
COPY_TRIPLET;
|
||||
j+=3;
|
||||
if (j == 15) j = 0;
|
||||
}
|
||||
|
||||
// Glittery water DOS
|
||||
s = ev->b;
|
||||
if (_opt.landscape == LT_CANDY) s = ev->bc;
|
||||
j = EXTR(128, 15) * 3;
|
||||
for(i=0; i!=5; i++) {
|
||||
COPY_TRIPLET;
|
||||
j += 9;
|
||||
if (j >= 45) j -= 45;
|
||||
}
|
||||
}
|
||||
|
||||
if (memcmp(old_val, _cur_palette + 217*3, c*3)) {
|
||||
if (_pal_first_dirty > 217) _pal_first_dirty = 217;
|
||||
if (_pal_last_dirty < 217+29-1) _pal_last_dirty = 217+29-1;
|
||||
if (_pal_last_dirty < 217+c) _pal_last_dirty = 217+c;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LoadStringWidthTable()
|
||||
void LoadStringWidthTable(void)
|
||||
{
|
||||
int i;
|
||||
byte *b;
|
||||
@@ -1592,19 +1638,19 @@ void LoadStringWidthTable()
|
||||
|
||||
// 2 equals space.
|
||||
for(i=2; i != 0xE2; i++) {
|
||||
*b++ = (byte)((i < 93 || i >= 129 || i == 98) ? GetSpritePtr(i)[2] : 0);
|
||||
*b++ = (byte)((i < 93 || i >= 129 || i == 98) ? GetSprite(i)->width : 0);
|
||||
}
|
||||
|
||||
for(i=0xE2; i != 0x1C2; i++) {
|
||||
*b++ = (byte)((i < 317 || i >= 353) ? GetSpritePtr(i)[2]+1 : 0);
|
||||
*b++ = (byte)((i < 317 || i >= 353) ? GetSprite(i)->width + 1 : 0);
|
||||
}
|
||||
|
||||
for(i=0x1C2; i != 0x2A2; i++) {
|
||||
*b++ = (byte)((i < 541 || i >= 577) ? GetSpritePtr(i)[2]+1 : 0);
|
||||
*b++ = (byte)((i < 541 || i >= 577) ? GetSprite(i)->width + 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenSizeChanged()
|
||||
void ScreenSizeChanged(void)
|
||||
{
|
||||
// check the dirty rect
|
||||
if (_invalid_rect.right >= _screen.width) _invalid_rect.right = _screen.width;
|
||||
@@ -1614,7 +1660,7 @@ void ScreenSizeChanged()
|
||||
_cursor.visible = false;
|
||||
}
|
||||
|
||||
void UndrawMouseCursor()
|
||||
void UndrawMouseCursor(void)
|
||||
{
|
||||
if (_cursor.visible) {
|
||||
_cursor.visible = false;
|
||||
@@ -1627,7 +1673,7 @@ void UndrawMouseCursor()
|
||||
}
|
||||
}
|
||||
|
||||
void DrawMouseCursor()
|
||||
void DrawMouseCursor(void)
|
||||
{
|
||||
int x,y,w,h;
|
||||
|
||||
@@ -1654,13 +1700,13 @@ void DrawMouseCursor()
|
||||
_cursor.draw_pos.y = y;
|
||||
_cursor.draw_size.y = h;
|
||||
|
||||
assert(w*h < sizeof(_cursor_backup));
|
||||
assert(w*h < (int) sizeof(_cursor_backup));
|
||||
|
||||
// Make backup of stuff below cursor
|
||||
memcpy_pitch(
|
||||
_cursor_backup,
|
||||
_screen.dst_ptr + _cursor.draw_pos.x + _cursor.draw_pos.y * _screen.pitch,
|
||||
_cursor.draw_size.x, _cursor.draw_size.y, _screen.width, _cursor.draw_size.x);
|
||||
_cursor.draw_size.x, _cursor.draw_size.y, _screen.pitch, _cursor.draw_size.x);
|
||||
|
||||
// Draw cursor on screen
|
||||
_cur_dpi = &_screen;
|
||||
@@ -1672,7 +1718,8 @@ void DrawMouseCursor()
|
||||
_cursor.dirty = false;
|
||||
}
|
||||
|
||||
void DbgScreenRect(int left, int top, int right, int bottom)
|
||||
#if defined(_DEBUG)
|
||||
static void DbgScreenRect(int left, int top, int right, int bottom)
|
||||
{
|
||||
DrawPixelInfo dp,*old;
|
||||
|
||||
@@ -1682,6 +1729,7 @@ void DbgScreenRect(int left, int top, int right, int bottom)
|
||||
GfxFillRect(left, top, right-1, bottom-1, rand() & 255);
|
||||
_cur_dpi = old;
|
||||
}
|
||||
#endif
|
||||
|
||||
extern bool _dbg_screen_rect;
|
||||
|
||||
@@ -1696,6 +1744,7 @@ void RedrawScreenRect(int left, int top, int right, int bottom)
|
||||
UndrawMouseCursor();
|
||||
}
|
||||
}
|
||||
UndrawTextMessage();
|
||||
|
||||
#if defined(_DEBUG)
|
||||
if (_dbg_screen_rect)
|
||||
@@ -1707,12 +1756,12 @@ void RedrawScreenRect(int left, int top, int right, int bottom)
|
||||
_video_driver->make_dirty(left, top, right-left, bottom-top);
|
||||
}
|
||||
|
||||
void DrawDirtyBlocks()
|
||||
void DrawDirtyBlocks(void)
|
||||
{
|
||||
byte *b = _dirty_blocks;
|
||||
int x=0,y=0;
|
||||
int w = (_screen.width + 63) & ~63;
|
||||
int h = _screen.height;
|
||||
const int w = (_screen.width + 63) & ~63;
|
||||
const int h = (_screen.height + 7) & ~7;
|
||||
|
||||
do {
|
||||
if (*b != 0) {
|
||||
@@ -1813,7 +1862,7 @@ void SetDirtyBlocks(int left, int top, int right, int bottom)
|
||||
} while (--height);
|
||||
}
|
||||
|
||||
void MarkWholeScreenDirty()
|
||||
void MarkWholeScreenDirty(void)
|
||||
{
|
||||
SetDirtyBlocks(0, 0, _screen.width, _screen.height);
|
||||
}
|
||||
@@ -1867,22 +1916,22 @@ bool FillDrawPixelInfo(DrawPixelInfo *n, DrawPixelInfo *o, int left, int top, in
|
||||
static void SetCursorSprite(uint cursor)
|
||||
{
|
||||
CursorVars *cv = &_cursor;
|
||||
byte *p;
|
||||
const Sprite *p;
|
||||
|
||||
if (cv->sprite == cursor)
|
||||
return;
|
||||
|
||||
p = GetSpritePtr(cursor & 0x3FFF);
|
||||
p = GetSprite(cursor & 0x3FFF);
|
||||
cv->sprite = cursor;
|
||||
cv->size.y = *(byte*)(p+1);
|
||||
cv->size.x = READ_LE_UINT16(p+2);
|
||||
cv->offs.x = (int16)READ_LE_UINT16(p+4);
|
||||
cv->offs.y = (int16)READ_LE_UINT16(p+6);
|
||||
cv->size.y = p->height;
|
||||
cv->size.x = p->width;
|
||||
cv->offs.x = p->x_offs;
|
||||
cv->offs.y = p->y_offs;
|
||||
|
||||
cv->dirty = true;
|
||||
}
|
||||
|
||||
static void SwitchAnimatedCursor()
|
||||
static void SwitchAnimatedCursor(void)
|
||||
{
|
||||
CursorVars *cv = &_cursor;
|
||||
const uint16 *cur;
|
||||
@@ -1898,7 +1947,8 @@ static void SwitchAnimatedCursor()
|
||||
SetCursorSprite(sprite);
|
||||
}
|
||||
|
||||
void CursorTick() {
|
||||
void CursorTick(void)
|
||||
{
|
||||
CursorVars *cv = &_cursor;
|
||||
if (cv->animate_timeout && !--cv->animate_timeout)
|
||||
SwitchAnimatedCursor();
|
||||
@@ -1928,3 +1978,26 @@ bool ChangeResInGame(int w, int h)
|
||||
_cur_resolution[1] = h;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ToggleFullScreen(bool fs) {_video_driver->toggle_fullscreen(fs);}
|
||||
|
||||
static int CDECL compare_res(const void *pa, const void *pb)
|
||||
{
|
||||
int x = ((const uint16*)pa)[0] - ((const uint16*)pb)[0];
|
||||
if (x != 0) return x;
|
||||
return ((const uint16*)pa)[1] - ((const uint16*)pb)[1];
|
||||
}
|
||||
|
||||
void SortResolutions(int count)
|
||||
{
|
||||
qsort(_resolutions, count, sizeof(_resolutions[0]), compare_res);
|
||||
}
|
||||
|
||||
uint16 GetDrawStringPlayerColor(byte player)
|
||||
{
|
||||
// Get the color for DrawString-subroutines which matches the color
|
||||
// of the player
|
||||
if (player == OWNER_SPECTATOR || player == OWNER_SPECTATOR - 1)
|
||||
return 1;
|
||||
return (_color_list[_player_colors[player]].window_color_1b) | IS_PALETTE_COLOR;
|
||||
}
|
||||
|
||||
@@ -17,14 +17,6 @@ struct DrawPixelInfo {
|
||||
};
|
||||
|
||||
|
||||
typedef struct SpriteHdr {
|
||||
byte info;
|
||||
byte height;
|
||||
uint16 width;
|
||||
int16 x_offs, y_offs;
|
||||
} SpriteHdr;
|
||||
assert_compile(sizeof(SpriteHdr) == 8);
|
||||
|
||||
typedef struct CursorVars {
|
||||
Point pos, size, offs, delta;
|
||||
Point draw_pos, draw_size;
|
||||
@@ -42,53 +34,50 @@ typedef struct CursorVars {
|
||||
|
||||
void RedrawScreenRect(int left, int top, int right, int bottom);
|
||||
void GfxScroll(int left, int top, int width, int height, int xo, int yo);
|
||||
int DrawStringCentered(int x, int y, uint16 str, byte color);
|
||||
int DrawString(int x, int y, uint16 str, byte color);
|
||||
void DrawStringCenterUnderline(int x, int y, uint16 str, byte color);
|
||||
int DoDrawString(const byte *string, int x, int y, byte color);
|
||||
void DrawStringRightAligned(int x, int y, uint16 str, byte color);
|
||||
int DrawStringCentered(int x, int y, uint16 str, uint16 color);
|
||||
int DrawString(int x, int y, uint16 str, uint16 color);
|
||||
void DrawStringCenterUnderline(int x, int y, uint16 str, uint16 color);
|
||||
int DoDrawString(const char *string, int x, int y, uint16 color);
|
||||
void DrawStringRightAligned(int x, int y, uint16 str, uint16 color);
|
||||
void GfxFillRect(int left, int top, int right, int bottom, int color);
|
||||
void GfxDrawLine(int left, int top, int right, int bottom, int color);
|
||||
void DrawFrameRect(int left, int top, int right, int bottom, int color, int flags);
|
||||
uint16 GetDrawStringPlayerColor(byte player);
|
||||
|
||||
int GetStringWidth(const byte *str);
|
||||
void LoadStringWidthTable();
|
||||
int GetStringWidth(const char *str);
|
||||
void LoadStringWidthTable(void);
|
||||
void DrawStringMultiCenter(int x, int y, uint16 str, int maxw);
|
||||
void DrawStringMultiLine(int x, int y, uint16 str, int maxw);
|
||||
void DrawDirtyBlocks();
|
||||
void DrawDirtyBlocks(void);
|
||||
void SetDirtyBlocks(int left, int top, int right, int bottom);
|
||||
void MarkWholeScreenDirty();
|
||||
void MarkWholeScreenDirty(void);
|
||||
|
||||
void GfxInitPalettes();
|
||||
void GfxInitPalettes(void);
|
||||
|
||||
bool FillDrawPixelInfo(DrawPixelInfo *n, DrawPixelInfo *o, int left, int top, int width, int height);
|
||||
|
||||
/* window.c */
|
||||
void DrawOverlappedWindowForAll(int left, int top, int right, int bottom);
|
||||
|
||||
/* spritecache.c */
|
||||
byte *GetSpritePtr(uint sprite);
|
||||
void GfxInitSpriteMem(byte *ptr, uint32 size);
|
||||
void GfxLoadSprites();
|
||||
|
||||
void SetMouseCursor(uint cursor);
|
||||
void SetAnimatedMouseCursor(const uint16 *table);
|
||||
void CursorTick();
|
||||
void DrawMouseCursor();
|
||||
void ScreenSizeChanged();
|
||||
void UndrawMouseCursor();
|
||||
void CursorTick(void);
|
||||
void DrawMouseCursor(void);
|
||||
void ScreenSizeChanged(void);
|
||||
void UndrawMouseCursor(void);
|
||||
bool ChangeResInGame(int w, int h);
|
||||
|
||||
typedef struct {
|
||||
int xoffs, yoffs;
|
||||
int xsize, ysize;
|
||||
} SpriteDimension;
|
||||
|
||||
const SpriteDimension *GetSpriteDimension(uint sprite);
|
||||
void SortResolutions(int count);
|
||||
void ToggleFullScreen(bool fs);
|
||||
|
||||
/* gfx.c */
|
||||
#define ASCII_LETTERSTART 32
|
||||
VARDEF int _stringwidth_base;
|
||||
VARDEF byte _stringwidth_table[0x2A0];
|
||||
static inline byte GetCharacterWidth(uint key)
|
||||
{
|
||||
assert(key >= ASCII_LETTERSTART && key - ASCII_LETTERSTART < lengthof(_stringwidth_table));
|
||||
return _stringwidth_table[key - ASCII_LETTERSTART];
|
||||
}
|
||||
|
||||
VARDEF DrawPixelInfo _screen;
|
||||
VARDEF DrawPixelInfo *_cur_dpi;
|
||||
@@ -98,6 +87,8 @@ VARDEF CursorVars _cursor;
|
||||
VARDEF int _pal_first_dirty;
|
||||
VARDEF int _pal_last_dirty;
|
||||
|
||||
VARDEF bool _use_dos_palette;
|
||||
|
||||
/* spritecache.c */
|
||||
//enum { NUM_SPRITES = 0x1320 };
|
||||
//enum { NUM_SPRITES = 0x1500 };
|
||||
@@ -107,4 +98,9 @@ enum { NUM_SPRITES = 0x3500 }; // 1500 + space for custom GRF sets
|
||||
extern byte _palettes[4][256 * 3];
|
||||
VARDEF byte _cur_palette[768];
|
||||
|
||||
|
||||
typedef enum StringColorFlags {
|
||||
IS_PALETTE_COLOR = 0x100, // color value is already a real palette color index, not an index of a StringColor
|
||||
} StringColorFlags;
|
||||
|
||||
#endif
|
||||
|
||||
+571
-425
File diff suppressed because it is too large
Load Diff
-1072
File diff suppressed because it is too large
Load Diff
@@ -4,36 +4,39 @@
|
||||
#include "window.h"
|
||||
|
||||
/* main_gui.c */
|
||||
void SetupColorsAndInitialWindow();
|
||||
void SetupColorsAndInitialWindow(void);
|
||||
void CcPlaySound10(bool success, uint tile, uint32 p1, uint32 p2);
|
||||
void PlaceProc_Sign(uint tile);
|
||||
void CcBuildCanal(bool success, uint tile, uint32 p1, uint32 p2);
|
||||
void CcTerraform(bool success, uint tile, uint32 p1, uint32 p2);
|
||||
|
||||
/* settings_gui.c */
|
||||
void ShowGameOptions();
|
||||
void ShowGameDifficulty();
|
||||
void ShowPatchesSelection();
|
||||
void ShowGameOptions(void);
|
||||
void ShowGameDifficulty(void);
|
||||
void ShowPatchesSelection(void);
|
||||
void ShowNewgrf(void);
|
||||
void ShowCustCurrency(void);
|
||||
|
||||
/* graph_gui.c */
|
||||
void ShowOperatingProfitGraph();
|
||||
void ShowIncomeGraph();
|
||||
void ShowDeliveredCargoGraph();
|
||||
void ShowPerformanceHistoryGraph();
|
||||
void ShowCompanyValueGraph();
|
||||
void ShowCargoPaymentRates();
|
||||
void ShowCompanyLeagueTable();
|
||||
void ShowPerformanceRatingDetail();
|
||||
void ShowOperatingProfitGraph(void);
|
||||
void ShowIncomeGraph(void);
|
||||
void ShowDeliveredCargoGraph(void);
|
||||
void ShowPerformanceHistoryGraph(void);
|
||||
void ShowCompanyValueGraph(void);
|
||||
void ShowCargoPaymentRates(void);
|
||||
void ShowCompanyLeagueTable(void);
|
||||
void ShowPerformanceRatingDetail(void);
|
||||
|
||||
/* news_gui.c */
|
||||
void ShowLastNewsMessage();
|
||||
void ShowMessageOptions();
|
||||
void ShowMessageHistory();
|
||||
void ShowLastNewsMessage(void);
|
||||
void ShowMessageOptions(void);
|
||||
void ShowMessageHistory(void);
|
||||
|
||||
/* traintoolb_gui.c */
|
||||
void ShowBuildRailToolbar(int index, int button);
|
||||
void PlaceProc_BuyLand(uint tile);
|
||||
|
||||
/* train_gui.c */
|
||||
void ShowPlayerTrains(int player);
|
||||
void ShowPlayerTrains(int player, int station);
|
||||
void ShowTrainViewWindow(Vehicle *v);
|
||||
void ShowTrainDetailsWindow(Vehicle *v);
|
||||
void ShowOrdersWindow(Vehicle *v);
|
||||
@@ -41,61 +44,88 @@ void ShowOrdersWindow(Vehicle *v);
|
||||
void ShowRoadVehViewWindow(Vehicle *v);
|
||||
|
||||
/* road_gui.c */
|
||||
void ShowBuildRoadToolbar();
|
||||
void ShowBuildRoadScenToolbar();
|
||||
void ShowPlayerRoadVehicles(int player);
|
||||
void ShowBuildRoadToolbar(void);
|
||||
void ShowBuildRoadScenToolbar(void);
|
||||
void ShowPlayerRoadVehicles(int player, int station);
|
||||
|
||||
/* dock_gui.c */
|
||||
void ShowBuildDocksToolbar();
|
||||
void ShowPlayerShips(int player);
|
||||
void ShowBuildDocksToolbar(void);
|
||||
void ShowPlayerShips(int player, int station);
|
||||
|
||||
void ShowShipViewWindow(Vehicle *v);
|
||||
|
||||
/* aircraft_gui.c */
|
||||
void ShowBuildAirToolbar();
|
||||
void ShowPlayerAircraft(int player);
|
||||
void ShowBuildAirToolbar(void);
|
||||
void ShowPlayerAircraft(int player, int station);
|
||||
|
||||
/* terraform_gui.c */
|
||||
void ShowTerraformToolbar(void);
|
||||
|
||||
void PlaceProc_DemolishArea(uint tile);
|
||||
void PlaceProc_LowerLand(uint tile);
|
||||
void PlaceProc_RaiseLand(uint tile);
|
||||
void PlaceProc_LevelLand(uint tile);
|
||||
void ShowTerraformToolbar();
|
||||
bool GUIPlaceProcDragXY(const WindowEvent *we);
|
||||
|
||||
enum { // max 32 - 4 = 28 types
|
||||
GUI_PlaceProc_DemolishArea = 0 << 4,
|
||||
GUI_PlaceProc_LevelArea = 1 << 4,
|
||||
GUI_PlaceProc_DesertArea = 2 << 4,
|
||||
GUI_PlaceProc_WaterArea = 3 << 4,
|
||||
GUI_PlaceProc_ConvertRailArea = 4 << 4
|
||||
};
|
||||
|
||||
/* misc_gui.c */
|
||||
void PlaceLandBlockInfo();
|
||||
void ShowAboutWindow();
|
||||
void ShowBuildTreesToolbar();
|
||||
void ShowBuildTreesScenToolbar();
|
||||
void ShowTownDirectory();
|
||||
void ShowIndustryDirectory();
|
||||
void ShowSubsidiesList();
|
||||
void PlaceLandBlockInfo(void);
|
||||
void ShowAboutWindow(void);
|
||||
void ShowBuildTreesToolbar(void);
|
||||
void ShowBuildTreesScenToolbar(void);
|
||||
void ShowTownDirectory(void);
|
||||
void ShowIndustryDirectory(void);
|
||||
void ShowSubsidiesList(void);
|
||||
void ShowPlayerStations(int player);
|
||||
void ShowPlayerFinances(int player);
|
||||
void ShowPlayerCompany(int player);
|
||||
void ShowSignList(void);
|
||||
|
||||
void ShowEstimatedCostOrIncome(int32 cost, int x, int y);
|
||||
void ShowErrorMessage(StringID msg_1, StringID msg_2, int x, int y);
|
||||
|
||||
void DrawStationCoverageAreaText(int sx, int sy, uint mask);
|
||||
void DrawStationCoverageAreaText(int sx, int sy, uint mask,int rad);
|
||||
void CheckRedrawStationCoverage(Window *w);
|
||||
|
||||
void ShowSmallMap();
|
||||
void ShowExtraViewPortWindow();
|
||||
void ShowSmallMap(void);
|
||||
void ShowExtraViewPortWindow(void);
|
||||
void SetVScrollCount(Window *w, int num);
|
||||
void SetVScroll2Count(Window *w, int num);
|
||||
void SetHScrollCount(Window *w, int num);
|
||||
int HandleEditBoxKey(Window *w, int wid, WindowEvent *we);
|
||||
|
||||
void ShowCheatWindow();
|
||||
void AskForNewGameToStart();
|
||||
void ShowCheatWindow(void);
|
||||
void AskForNewGameToStart(void);
|
||||
|
||||
void DrawEditBox(Window *w, int wid);
|
||||
void HandleEditBox(Window *w, int wid);
|
||||
int HandleEditBoxKey(Window *w, int wid, WindowEvent *we);
|
||||
bool HandleCaret(Textbuf *tb);
|
||||
|
||||
bool DeleteTextBufferChar(Textbuf *tb, int delmode);
|
||||
bool InsertTextBufferChar(Textbuf *tb, byte key);
|
||||
bool InsertTextBufferClipboard(Textbuf *tb);
|
||||
bool MoveTextBufferPos(Textbuf *tb, int navmode);
|
||||
void UpdateTextBufferSize(Textbuf *tb);
|
||||
/* IS_INT_INSIDE = filter for ascii-function codes like BELL and so on [we need an special filter here later] */
|
||||
static inline bool IsValidAsciiChar(byte key) {return IS_INT_INSIDE(key, ' ', 256);}
|
||||
|
||||
void BuildFileList(void);
|
||||
void SetFiosType(const byte fiostype);
|
||||
|
||||
/* FIOS_TYPE_FILE, FIOS_TYPE_OLDFILE etc. different colours */
|
||||
static const byte _fios_colors[] = {13, 9, 9, 6, 5, 6, 5};
|
||||
|
||||
|
||||
/* network gui */
|
||||
void ShowNetworkGameWindow();
|
||||
|
||||
void ShowNetworkGameWindow(void);
|
||||
void ShowChatWindow(StringID str, StringID caption, int maxlen, int maxwidth, byte window_class, uint16 window_number);
|
||||
|
||||
/* bridge_gui.c */
|
||||
void ShowBuildBridgeWindow(uint start, uint end, byte type);
|
||||
@@ -107,15 +137,17 @@ enum {
|
||||
};
|
||||
|
||||
bool DoZoomInOutWindow(int how, Window * w);
|
||||
void ShowBuildIndustryWindow();
|
||||
void ShowQueryString(StringID str, StringID caption, int maxlen, int maxwidth, byte window_class, uint16 window_number);
|
||||
void ShowMusicWindow();
|
||||
void ShowBuildIndustryWindow(void);
|
||||
void ShowQueryString(StringID str, StringID caption, uint maxlen, uint maxwidth, WindowClass window_class, WindowNumber window_number);
|
||||
void ShowMusicWindow(void);
|
||||
|
||||
/* main_gui.c */
|
||||
VARDEF byte _newspaper_flag;
|
||||
VARDEF byte _construct_mode;
|
||||
VARDEF byte _station_show_coverage;
|
||||
VARDEF PlaceProc *_place_proc;
|
||||
VARDEF bool _no_button_sound;
|
||||
|
||||
/* vehicle_gui.c */
|
||||
void InitializeGUI(void);
|
||||
|
||||
#endif /* GUI_H */
|
||||
|
||||
@@ -2,16 +2,17 @@
|
||||
#define HAL_H
|
||||
|
||||
typedef struct {
|
||||
char *(*start)(char **parm);
|
||||
void (*stop)();
|
||||
const char *(*start)(const char * const *parm);
|
||||
void (*stop)(void);
|
||||
} HalCommonDriver;
|
||||
|
||||
typedef struct {
|
||||
const char *(*start)(char **parm);
|
||||
void (*stop)();
|
||||
const char *(*start)(const char * const *parm);
|
||||
void (*stop)(void);
|
||||
void (*make_dirty)(int left, int top, int width, int height);
|
||||
int (*main_loop)();
|
||||
int (*main_loop)(void);
|
||||
bool (*change_resolution)(int w, int h);
|
||||
void (*toggle_fullscreen)(bool fullscreen);
|
||||
} HalVideoDriver;
|
||||
|
||||
enum {
|
||||
@@ -20,17 +21,17 @@ enum {
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
char *(*start)(char **parm);
|
||||
void (*stop)();
|
||||
const char *(*start)(const char * const *parm);
|
||||
void (*stop)(void);
|
||||
} HalSoundDriver;
|
||||
|
||||
typedef struct {
|
||||
char *(*start)(char **parm);
|
||||
void (*stop)();
|
||||
const char *(*start)(const char * const *parm);
|
||||
void (*stop)(void);
|
||||
|
||||
void (*play_song)(const char *filename);
|
||||
void (*stop_song)();
|
||||
bool (*is_song_playing)();
|
||||
void (*stop_song)(void);
|
||||
bool (*is_song_playing)(void);
|
||||
void (*set_volume)(byte vol);
|
||||
} HalMusicDriver;
|
||||
|
||||
@@ -71,20 +72,26 @@ extern const HalMusicDriver _extmidi_music_driver;
|
||||
extern const HalMusicDriver _bemidi_music_driver;
|
||||
#endif
|
||||
|
||||
#if defined(__OS2__)
|
||||
extern const HalMusicDriver _os2_music_driver;
|
||||
#endif
|
||||
|
||||
extern const HalVideoDriver _dedicated_video_driver;
|
||||
|
||||
enum DriverType {
|
||||
VIDEO_DRIVER = 0,
|
||||
SOUND_DRIVER = 1,
|
||||
MUSIC_DRIVER = 2,
|
||||
};
|
||||
|
||||
extern void GameLoop();
|
||||
extern void GameLoop(void);
|
||||
extern bool _dbg_screen_rect;
|
||||
|
||||
void LoadDriver(int driver, const char *name);
|
||||
|
||||
char *GetDriverParam(char **parm, const char *name);
|
||||
bool GetDriverParamBool(char **parm, const char *name);
|
||||
int GetDriverParamInt(char **parm, const char *name, int def);
|
||||
const char *GetDriverParam(const char * const *parm, const char *name);
|
||||
bool GetDriverParamBool(const char * const *parm, const char *name);
|
||||
int GetDriverParamInt(const char * const *parm, const char *name, int def);
|
||||
|
||||
|
||||
|
||||
@@ -95,20 +102,8 @@ typedef struct {
|
||||
uint64 mtime;
|
||||
char title[64];
|
||||
char name[256-12-64];
|
||||
int old_extension;
|
||||
} FiosItem;
|
||||
|
||||
// extensions of old savegames, scenarios
|
||||
static const char* const _old_extensions[] = {
|
||||
// old savegame types
|
||||
"ss1", // Transport Tycoon Deluxe preset game
|
||||
"sv1", // Transport Tycoon Deluxe (Patch) saved game
|
||||
"sv2", // Transport Tycoon Deluxe (Patch) saved 2-player game
|
||||
// old scenario game type
|
||||
"sv0", // Transport Tycoon Deluxe (Patch) scenario
|
||||
"ss0", // Transport Tycoon Deluxe preset scenario
|
||||
};
|
||||
|
||||
enum {
|
||||
FIOS_TYPE_DRIVE = 0,
|
||||
FIOS_TYPE_PARENT = 1,
|
||||
@@ -119,6 +114,12 @@ enum {
|
||||
FIOS_TYPE_OLD_SCENARIO = 6,
|
||||
};
|
||||
|
||||
|
||||
// Variables to display file lists
|
||||
FiosItem *_fios_list;
|
||||
int _fios_num;
|
||||
int _saveload_mode;
|
||||
|
||||
// get the name of an oldstyle savegame
|
||||
void GetOldSaveGameName(char *title, const char *file);
|
||||
// get the name of an oldstyle scenario
|
||||
@@ -129,18 +130,18 @@ FiosItem *FiosGetSavegameList(int *num, int mode);
|
||||
// Get a list of scenarios
|
||||
FiosItem *FiosGetScenarioList(int *num, int mode);
|
||||
// Free the list of savegames
|
||||
void FiosFreeSavegameList();
|
||||
void FiosFreeSavegameList(void);
|
||||
// Browse to. Returns a filename w/path if we reached a file.
|
||||
char *FiosBrowseTo(const FiosItem *item);
|
||||
// Get descriptive texts.
|
||||
// Returns a path as well as a
|
||||
// string describing the path.
|
||||
StringID FiosGetDescText(const char **path);
|
||||
// Return path, free space and stringID
|
||||
StringID FiosGetDescText(const char **path, uint32 *tot);
|
||||
// Delete a name
|
||||
void FiosDelete(const char *name);
|
||||
// Make a filename from a name
|
||||
void FiosMakeSavegameName(char *buf, const char *name);
|
||||
|
||||
void CreateConsole();
|
||||
int CDECL compare_FiosItems(const void *a, const void *b);
|
||||
|
||||
void CreateConsole(void);
|
||||
|
||||
#endif /* HAL_H */
|
||||
|
||||
+36
-2
@@ -1,6 +1,8 @@
|
||||
#ifndef INDUSTRY_H
|
||||
#define INDUSTRY_H
|
||||
|
||||
#include "pool.h"
|
||||
|
||||
struct Industry {
|
||||
TileIndex xy;
|
||||
byte width; /* swapped order of w/h with town */
|
||||
@@ -23,12 +25,44 @@ struct Industry {
|
||||
byte color_map;
|
||||
byte last_prod_year;
|
||||
byte was_cargo_delivered;
|
||||
|
||||
uint16 index;
|
||||
};
|
||||
|
||||
extern MemoryPool _industry_pool;
|
||||
|
||||
/**
|
||||
* Check if an Industry really exists.
|
||||
*/
|
||||
static inline bool IsValidIndustry(Industry* industry)
|
||||
{
|
||||
return industry->xy != 0; /* XXX: Replace by INVALID_TILE someday */
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the pointer to the industry with index 'index'
|
||||
*/
|
||||
static inline Industry *GetIndustry(uint index)
|
||||
{
|
||||
return (Industry*)GetItemFromPool(&_industry_pool, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current size of the IndustryPool
|
||||
*/
|
||||
static inline uint16 GetIndustryPoolSize(void)
|
||||
{
|
||||
return _industry_pool.total_items;
|
||||
}
|
||||
|
||||
#define FOR_ALL_INDUSTRIES_FROM(i, start) for (i = GetIndustry(start); i != NULL; i = (i->index + 1 < GetIndustryPoolSize()) ? GetIndustry(i->index + 1) : NULL)
|
||||
#define FOR_ALL_INDUSTRIES(i) FOR_ALL_INDUSTRIES_FROM(i, 0)
|
||||
|
||||
VARDEF int _total_industries; // For the AI: the amount of industries active
|
||||
VARDEF Industry _industries[90];
|
||||
#define DEREF_INDUSTRY(i) (&_industries[i])
|
||||
|
||||
VARDEF uint16 *_industry_sort;
|
||||
VARDEF bool _industry_sort_dirty;
|
||||
|
||||
void DeleteIndustry(Industry *is);
|
||||
|
||||
enum {
|
||||
|
||||
+389
-279
File diff suppressed because it is too large
Load Diff
+295
-197
@@ -1,6 +1,10 @@
|
||||
#include "stdafx.h"
|
||||
#include "ttd.h"
|
||||
//#include "gui.h"
|
||||
#include "debug.h"
|
||||
#include "strings.h"
|
||||
#include "table/strings.h"
|
||||
#include "map.h"
|
||||
#include "gui.h"
|
||||
#include "window.h"
|
||||
#include "gfx.h"
|
||||
#include "command.h"
|
||||
@@ -8,24 +12,22 @@
|
||||
#include "industry.h"
|
||||
#include "town.h"
|
||||
|
||||
static const byte _build_industry_types[4][12] = {
|
||||
{ 1, 2, 4, 6, 8, 0, 3, 5, 9, 11, 18 },
|
||||
{ 1, 14, 4, 13, 7, 0, 3, 9, 11, 15 },
|
||||
{ 25, 13, 4, 23, 22, 11, 17, 10, 24, 19, 20, 21 },
|
||||
{ 27, 30, 31, 33, 26, 28, 29, 32, 34, 35, 36 },
|
||||
};
|
||||
|
||||
/* Present in table/build_industry.h" */
|
||||
extern const byte _build_industry_types[4][12];
|
||||
extern const byte _industry_type_costs[37];
|
||||
|
||||
static void UpdateIndustryProduction(Industry *i);
|
||||
extern void DrawArrowButtons(int x, int y, int state);
|
||||
|
||||
static void BuildIndustryWndProc(Window *w, WindowEvent *e)
|
||||
{
|
||||
switch(e->event) {
|
||||
case WE_PAINT:
|
||||
DrawWindowWidgets(w);
|
||||
if (_thd.place_mode == 1 && _thd.window_class == WC_BUILD_INDUSTRY) {
|
||||
int ind_type = _build_industry_types[_opt.landscape][WP(w,def_d).data_1];
|
||||
int ind_type = _build_industry_types[_opt_ptr->landscape][WP(w,def_d).data_1];
|
||||
|
||||
SET_DPARAM32(0, (_price.build_industry >> 5) * _industry_type_costs[ind_type]);
|
||||
SetDParam(0, (_price.build_industry >> 5) * _industry_type_costs[ind_type]);
|
||||
DrawStringCentered(85, w->height - 21, STR_482F_COST, 0);
|
||||
}
|
||||
break;
|
||||
@@ -39,7 +41,7 @@ static void BuildIndustryWndProc(Window *w, WindowEvent *e)
|
||||
} break;
|
||||
|
||||
case WE_PLACE_OBJ:
|
||||
if (DoCommandP(e->place.tile, _build_industry_types[_opt.landscape][WP(w,def_d).data_1], 0, NULL, CMD_BUILD_INDUSTRY | CMD_MSG(STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY)))
|
||||
if (DoCommandP(e->place.tile, _build_industry_types[_opt_ptr->landscape][WP(w,def_d).data_1], 0, NULL, CMD_BUILD_INDUSTRY | CMD_MSG(STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY)))
|
||||
ResetObjectToPlace();
|
||||
break;
|
||||
|
||||
@@ -51,130 +53,130 @@ static void BuildIndustryWndProc(Window *w, WindowEvent *e)
|
||||
}
|
||||
|
||||
static const Widget _build_industry_land0_widgets[] = {
|
||||
{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, 7, 11, 169, 0, 13, STR_0314_FUND_NEW_INDUSTRY, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_PANEL, 7, 0, 169, 14, 115, 0x0, STR_NULL},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 16, 27, STR_0241_POWER_STATION, STR_0263_CONSTRUCT_POWER_STATION},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 29, 40, STR_0242_SAWMILL, STR_0264_CONSTRUCT_SAWMILL},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 42, 53, STR_0244_OIL_REFINERY, STR_0266_CONSTRUCT_OIL_REFINERY},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 55, 66, STR_0246_FACTORY, STR_0268_CONSTRUCT_FACTORY},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 68, 79, STR_0247_STEEL_MILL, STR_0269_CONSTRUCT_STEEL_MILL},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 169, 0, 13, STR_0314_FUND_NEW_INDUSTRY, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 0, 169, 14, 115, 0x0, STR_NULL},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 16, 27, STR_0241_POWER_STATION, STR_0263_CONSTRUCT_POWER_STATION},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 29, 40, STR_0242_SAWMILL, STR_0264_CONSTRUCT_SAWMILL},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 42, 53, STR_0244_OIL_REFINERY, STR_0266_CONSTRUCT_OIL_REFINERY},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 55, 66, STR_0246_FACTORY, STR_0268_CONSTRUCT_FACTORY},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 68, 79, STR_0247_STEEL_MILL, STR_0269_CONSTRUCT_STEEL_MILL},
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
static const Widget _build_industry_land1_widgets[] = {
|
||||
{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, 7, 11, 169, 0, 13, STR_0314_FUND_NEW_INDUSTRY, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_PANEL, 7, 0, 169, 14, 115, 0x0, STR_NULL},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 16, 27, STR_0241_POWER_STATION, STR_0263_CONSTRUCT_POWER_STATION},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 29, 40, STR_024C_PAPER_MILL, STR_026E_CONSTRUCT_PAPER_MILL},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 42, 53, STR_0244_OIL_REFINERY, STR_0266_CONSTRUCT_OIL_REFINERY},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 55, 66, STR_024D_FOOD_PROCESSING_PLANT,STR_026F_CONSTRUCT_FOOD_PROCESSING},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 68, 79, STR_024E_PRINTING_WORKS, STR_0270_CONSTRUCT_PRINTING_WORKS},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 169, 0, 13, STR_0314_FUND_NEW_INDUSTRY, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 0, 169, 14, 115, 0x0, STR_NULL},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 16, 27, STR_0241_POWER_STATION, STR_0263_CONSTRUCT_POWER_STATION},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 29, 40, STR_024C_PAPER_MILL, STR_026E_CONSTRUCT_PAPER_MILL},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 42, 53, STR_0244_OIL_REFINERY, STR_0266_CONSTRUCT_OIL_REFINERY},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 55, 66, STR_024D_FOOD_PROCESSING_PLANT,STR_026F_CONSTRUCT_FOOD_PROCESSING},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 68, 79, STR_024E_PRINTING_WORKS, STR_0270_CONSTRUCT_PRINTING_WORKS},
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
static const Widget _build_industry_land2_widgets[] = {
|
||||
{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, 7, 11, 169, 0, 13, STR_0314_FUND_NEW_INDUSTRY, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_PANEL, 7, 0, 169, 14, 115, 0x0, STR_NULL},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 16, 27, STR_0250_LUMBER_MILL, STR_0273_CONSTRUCT_LUMBER_MILL_TO},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 29, 40, STR_024D_FOOD_PROCESSING_PLANT,STR_026F_CONSTRUCT_FOOD_PROCESSING},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 42, 53, STR_0244_OIL_REFINERY, STR_0266_CONSTRUCT_OIL_REFINERY},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 55, 66, STR_0246_FACTORY, STR_0268_CONSTRUCT_FACTORY},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 68, 79, STR_0254_WATER_TOWER, STR_0277_CONSTRUCT_WATER_TOWER_CAN},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 169, 0, 13, STR_0314_FUND_NEW_INDUSTRY, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 0, 169, 14, 115, 0x0, STR_NULL},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 16, 27, STR_0250_LUMBER_MILL, STR_0273_CONSTRUCT_LUMBER_MILL_TO},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 29, 40, STR_024D_FOOD_PROCESSING_PLANT,STR_026F_CONSTRUCT_FOOD_PROCESSING},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 42, 53, STR_0244_OIL_REFINERY, STR_0266_CONSTRUCT_OIL_REFINERY},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 55, 66, STR_0246_FACTORY, STR_0268_CONSTRUCT_FACTORY},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 68, 79, STR_0254_WATER_TOWER, STR_0277_CONSTRUCT_WATER_TOWER_CAN},
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
static const Widget _build_industry_land3_widgets[] = {
|
||||
{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, 7, 11, 169, 0, 13, STR_0314_FUND_NEW_INDUSTRY, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_PANEL, 7, 0, 169, 14, 115, 0x0, STR_NULL},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 16, 27, STR_0258_CANDY_FACTORY, STR_027B_CONSTRUCT_CANDY_FACTORY},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 29, 40, STR_025B_TOY_SHOP, STR_027E_CONSTRUCT_TOY_SHOP},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 42, 53, STR_025C_TOY_FACTORY, STR_027F_CONSTRUCT_TOY_FACTORY},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 55, 66, STR_025E_FIZZY_DRINK_FACTORY, STR_0281_CONSTRUCT_FIZZY_DRINK_FACTORY},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 169, 0, 13, STR_0314_FUND_NEW_INDUSTRY, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 0, 169, 14, 115, 0x0, STR_NULL},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 16, 27, STR_0258_CANDY_FACTORY, STR_027B_CONSTRUCT_CANDY_FACTORY},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 29, 40, STR_025B_TOY_SHOP, STR_027E_CONSTRUCT_TOY_SHOP},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 42, 53, STR_025C_TOY_FACTORY, STR_027F_CONSTRUCT_TOY_FACTORY},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 55, 66, STR_025E_FIZZY_DRINK_FACTORY, STR_0281_CONSTRUCT_FIZZY_DRINK_FACTORY},
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
static const Widget _build_industry_land0_widgets_extra[] = {
|
||||
{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, 7, 11, 169, 0, 13, STR_0314_FUND_NEW_INDUSTRY,STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_PANEL, 7, 0, 169, 14, 187, 0x0, STR_NULL},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 169, 0, 13, STR_0314_FUND_NEW_INDUSTRY,STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 0, 169, 14, 187, 0x0, STR_NULL},
|
||||
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 16, 27, STR_0241_POWER_STATION,STR_0263_CONSTRUCT_POWER_STATION},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 29, 40, STR_0242_SAWMILL, STR_0264_CONSTRUCT_SAWMILL},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 42, 53, STR_0244_OIL_REFINERY, STR_0266_CONSTRUCT_OIL_REFINERY},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 55, 66, STR_0246_FACTORY, STR_0268_CONSTRUCT_FACTORY},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 68, 79, STR_0247_STEEL_MILL, STR_0269_CONSTRUCT_STEEL_MILL},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 16, 27, STR_0241_POWER_STATION,STR_0263_CONSTRUCT_POWER_STATION},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 29, 40, STR_0242_SAWMILL, STR_0264_CONSTRUCT_SAWMILL},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 42, 53, STR_0244_OIL_REFINERY, STR_0266_CONSTRUCT_OIL_REFINERY},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 55, 66, STR_0246_FACTORY, STR_0268_CONSTRUCT_FACTORY},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 68, 79, STR_0247_STEEL_MILL, STR_0269_CONSTRUCT_STEEL_MILL},
|
||||
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 84, 95, STR_0240_COAL_MINE, STR_CONSTRUCT_COAL_MINE_TIP},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 97, 108, STR_0243_FOREST, STR_CONSTRUCT_FOREST_TIP},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 110, 121, STR_0245_OIL_RIG, STR_CONSTRUCT_OIL_RIG_TIP},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 123, 134, STR_0248_FARM, STR_CONSTRUCT_FARM_TIP},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 136, 147, STR_024A_OIL_WELLS, STR_CONSTRUCT_OIL_WELLS_TIP},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 149, 160, STR_0249_IRON_ORE_MINE, STR_CONSTRUCT_IRON_ORE_MINE_TIP},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 84, 95, STR_0240_COAL_MINE, STR_CONSTRUCT_COAL_MINE_TIP},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 97, 108, STR_0243_FOREST, STR_CONSTRUCT_FOREST_TIP},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 110, 121, STR_0245_OIL_RIG, STR_CONSTRUCT_OIL_RIG_TIP},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 123, 134, STR_0248_FARM, STR_CONSTRUCT_FARM_TIP},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 136, 147, STR_024A_OIL_WELLS, STR_CONSTRUCT_OIL_WELLS_TIP},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 149, 160, STR_0249_IRON_ORE_MINE, STR_CONSTRUCT_IRON_ORE_MINE_TIP},
|
||||
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
static const Widget _build_industry_land1_widgets_extra[] = {
|
||||
{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, 7, 11, 169, 0, 13, STR_0314_FUND_NEW_INDUSTRY, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_PANEL, 7, 0, 169, 14, 174, 0x0, STR_NULL},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 169, 0, 13, STR_0314_FUND_NEW_INDUSTRY, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 0, 169, 14, 174, 0x0, STR_NULL},
|
||||
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 16, 27, STR_0241_POWER_STATION, STR_0263_CONSTRUCT_POWER_STATION},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 29, 40, STR_024C_PAPER_MILL, STR_026E_CONSTRUCT_PAPER_MILL},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 42, 53, STR_0244_OIL_REFINERY, STR_0266_CONSTRUCT_OIL_REFINERY},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 55, 66, STR_024D_FOOD_PROCESSING_PLANT,STR_026F_CONSTRUCT_FOOD_PROCESSING},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 68, 79, STR_024E_PRINTING_WORKS, STR_0270_CONSTRUCT_PRINTING_WORKS},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 16, 27, STR_0241_POWER_STATION, STR_0263_CONSTRUCT_POWER_STATION},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 29, 40, STR_024C_PAPER_MILL, STR_026E_CONSTRUCT_PAPER_MILL},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 42, 53, STR_0244_OIL_REFINERY, STR_0266_CONSTRUCT_OIL_REFINERY},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 55, 66, STR_024D_FOOD_PROCESSING_PLANT,STR_026F_CONSTRUCT_FOOD_PROCESSING},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 68, 79, STR_024E_PRINTING_WORKS, STR_0270_CONSTRUCT_PRINTING_WORKS},
|
||||
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 81+3, 92+3, STR_0240_COAL_MINE, STR_CONSTRUCT_COAL_MINE_TIP},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 94+3, 105+3, STR_0243_FOREST, STR_CONSTRUCT_FOREST_TIP},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 107+3, 118+3, STR_0248_FARM, STR_CONSTRUCT_FARM_TIP},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 120+3, 131+3, STR_024A_OIL_WELLS, STR_CONSTRUCT_OIL_WELLS_TIP},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 133+3, 144+3, STR_024F_GOLD_MINE, STR_CONSTRUCT_GOLD_MINE_TIP},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 81+3, 92+3, STR_0240_COAL_MINE, STR_CONSTRUCT_COAL_MINE_TIP},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 94+3, 105+3, STR_0243_FOREST, STR_CONSTRUCT_FOREST_TIP},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 107+3, 118+3, STR_0248_FARM, STR_CONSTRUCT_FARM_TIP},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 120+3, 131+3, STR_024A_OIL_WELLS, STR_CONSTRUCT_OIL_WELLS_TIP},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 133+3, 144+3, STR_024F_GOLD_MINE, STR_CONSTRUCT_GOLD_MINE_TIP},
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
static const Widget _build_industry_land2_widgets_extra[] = {
|
||||
{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, 7, 11, 169, 0, 13, STR_0314_FUND_NEW_INDUSTRY, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_PANEL, 7, 0, 169, 14, 200, 0x0, STR_NULL},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 169, 0, 13, STR_0314_FUND_NEW_INDUSTRY, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 0, 169, 14, 200, 0x0, STR_NULL},
|
||||
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 16, 27, STR_0250_LUMBER_MILL, STR_0273_CONSTRUCT_LUMBER_MILL_TO},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 29, 40, STR_024D_FOOD_PROCESSING_PLANT,STR_026F_CONSTRUCT_FOOD_PROCESSING},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 42, 53, STR_0244_OIL_REFINERY, STR_0266_CONSTRUCT_OIL_REFINERY},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 55, 66, STR_0246_FACTORY, STR_0268_CONSTRUCT_FACTORY},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 68, 79, STR_0254_WATER_TOWER, STR_0277_CONSTRUCT_WATER_TOWER_CAN},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 16, 27, STR_0250_LUMBER_MILL, STR_0273_CONSTRUCT_LUMBER_MILL_TO},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 29, 40, STR_024D_FOOD_PROCESSING_PLANT,STR_026F_CONSTRUCT_FOOD_PROCESSING},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 42, 53, STR_0244_OIL_REFINERY, STR_0266_CONSTRUCT_OIL_REFINERY},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 55, 66, STR_0246_FACTORY, STR_0268_CONSTRUCT_FACTORY},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 68, 79, STR_0254_WATER_TOWER, STR_0277_CONSTRUCT_WATER_TOWER_CAN},
|
||||
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 81+3, 92+3, STR_024A_OIL_WELLS,STR_CONSTRUCT_OIL_WELLS_TIP},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 94+3, 105+3, STR_0255_DIAMOND_MINE, STR_CONSTRUCT_DIAMOND_MINE_TIP},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 107+3, 118+3, STR_0256_COPPER_ORE_MINE, STR_CONSTRUCT_COPPER_ORE_MINE_TIP},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 120+3, 131+3, STR_0248_FARM, STR_CONSTRUCT_FARM_TIP},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 133+3, 144+3, STR_0251_FRUIT_PLANTATION, STR_CONSTRUCT_FRUIT_PLANTATION_TIP},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 146+3, 157+3, STR_0252_RUBBER_PLANTATION,STR_CONSTRUCT_RUBBER_PLANTATION_TIP},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 159+3, 170+3, STR_0253_WATER_SUPPLY, STR_CONSTRUCT_WATER_SUPPLY_TIP},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 81+3, 92+3, STR_024A_OIL_WELLS,STR_CONSTRUCT_OIL_WELLS_TIP},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 94+3, 105+3, STR_0255_DIAMOND_MINE, STR_CONSTRUCT_DIAMOND_MINE_TIP},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 107+3, 118+3, STR_0256_COPPER_ORE_MINE, STR_CONSTRUCT_COPPER_ORE_MINE_TIP},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 120+3, 131+3, STR_0248_FARM, STR_CONSTRUCT_FARM_TIP},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 133+3, 144+3, STR_0251_FRUIT_PLANTATION, STR_CONSTRUCT_FRUIT_PLANTATION_TIP},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 146+3, 157+3, STR_0252_RUBBER_PLANTATION,STR_CONSTRUCT_RUBBER_PLANTATION_TIP},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 159+3, 170+3, STR_0253_WATER_SUPPLY, STR_CONSTRUCT_WATER_SUPPLY_TIP},
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
static const Widget _build_industry_land3_widgets_extra[] = {
|
||||
{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, 7, 11, 169, 0, 13, STR_0314_FUND_NEW_INDUSTRY, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_PANEL, 7, 0, 169, 14, 187, 0x0, STR_NULL},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 169, 0, 13, STR_0314_FUND_NEW_INDUSTRY, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 0, 169, 14, 187, 0x0, STR_NULL},
|
||||
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 16, 27, STR_0258_CANDY_FACTORY, STR_027B_CONSTRUCT_CANDY_FACTORY},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 29, 40, STR_025B_TOY_SHOP, STR_027E_CONSTRUCT_TOY_SHOP},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 42, 53, STR_025C_TOY_FACTORY, STR_027F_CONSTRUCT_TOY_FACTORY},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 55, 66, STR_025E_FIZZY_DRINK_FACTORY, STR_0281_CONSTRUCT_FIZZY_DRINK_FACTORY},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 16, 27, STR_0258_CANDY_FACTORY, STR_027B_CONSTRUCT_CANDY_FACTORY},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 29, 40, STR_025B_TOY_SHOP, STR_027E_CONSTRUCT_TOY_SHOP},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 42, 53, STR_025C_TOY_FACTORY, STR_027F_CONSTRUCT_TOY_FACTORY},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 55, 66, STR_025E_FIZZY_DRINK_FACTORY, STR_0281_CONSTRUCT_FIZZY_DRINK_FACTORY},
|
||||
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 68+3, 79+3, STR_0257_COTTON_CANDY_FOREST,STR_CONSTRUCT_COTTON_CANDY_TIP},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 81+3, 92+3, STR_0259_BATTERY_FARM, STR_CONSTRUCT_BATTERY_FARM_TIP},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 94+3, 105+3, STR_025A_COLA_WELLS, STR_CONSTRUCT_COLA_WELLS_TIP},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 107+3, 118+3, STR_025D_PLASTIC_FOUNTAINS,STR_CONSTRUCT_PLASTIC_FOUNTAINS_TIP},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 120+3, 131+3, STR_025F_BUBBLE_GENERATOR, STR_CONSTRUCT_BUBBLE_GENERATOR_TIP},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 133+3, 144+3, STR_0260_TOFFEE_QUARRY, STR_CONSTRUCT_TOFFEE_QUARRY_TIP},
|
||||
{ WWT_CLOSEBOX, 14, 2, 167, 146+3, 157+3, STR_0261_SUGAR_MINE, STR_CONSTRUCT_SUGAR_MINE_TIP},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 68+3, 79+3, STR_0257_COTTON_CANDY_FOREST,STR_CONSTRUCT_COTTON_CANDY_TIP},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 81+3, 92+3, STR_0259_BATTERY_FARM, STR_CONSTRUCT_BATTERY_FARM_TIP},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 94+3, 105+3, STR_025A_COLA_WELLS, STR_CONSTRUCT_COLA_WELLS_TIP},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 107+3, 118+3, STR_025D_PLASTIC_FOUNTAINS,STR_CONSTRUCT_PLASTIC_FOUNTAINS_TIP},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 120+3, 131+3, STR_025F_BUBBLE_GENERATOR, STR_CONSTRUCT_BUBBLE_GENERATOR_TIP},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 133+3, 144+3, STR_0260_TOFFEE_QUARRY, STR_CONSTRUCT_TOFFEE_QUARRY_TIP},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 167, 146+3, 157+3, STR_0261_SUGAR_MINE, STR_CONSTRUCT_SUGAR_MINE_TIP},
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
@@ -258,98 +260,179 @@ static const WindowDesc * const _industry_window_desc[2][4] = {
|
||||
},
|
||||
};
|
||||
|
||||
void ShowBuildIndustryWindow()
|
||||
void ShowBuildIndustryWindow(void)
|
||||
{
|
||||
AllocateWindowDescFront(_industry_window_desc[_patches.build_rawmaterial_ind][_opt.landscape],0);
|
||||
AllocateWindowDescFront(_industry_window_desc[_patches.build_rawmaterial_ind][_opt_ptr->landscape],0);
|
||||
}
|
||||
|
||||
#define NEED_ALTERB ((_game_mode == GM_EDITOR || _cheats.setup_prod.value) && (i->accepts_cargo[0] == CT_INVALID || i->accepts_cargo[0] == CT_VALUABLES))
|
||||
static void IndustryViewWndProc(Window *w, WindowEvent *e)
|
||||
{
|
||||
Industry *i;
|
||||
StringID str;
|
||||
// WP(w,vp2_d).data_1 is for the editbox line
|
||||
// WP(w,vp2_d).data_2 is for the clickline
|
||||
// WP(w,vp2_d).data_3 is for the click pos (left or right)
|
||||
|
||||
switch(e->event) {
|
||||
case WE_PAINT:
|
||||
case WE_PAINT: {
|
||||
const Industry *i;
|
||||
StringID str;
|
||||
// in editor, use bulldoze to destroy industry
|
||||
// Destroy Industry button costing money removed per request of dominik
|
||||
//w->disabled_state = (_patches.extra_dynamite && !_networking && _game_mode != GM_EDITOR) ? 0 : (1 << 6);
|
||||
i = DEREF_INDUSTRY(w->window_number);
|
||||
SET_DPARAM16(0, i->town->index);
|
||||
SET_DPARAM16(1, i->type + STR_4802_COAL_MINE);
|
||||
i = GetIndustry(w->window_number);
|
||||
SetDParam(0, i->town->index);
|
||||
SetDParam(1, i->type + STR_4802_COAL_MINE);
|
||||
DrawWindowWidgets(w);
|
||||
|
||||
if (i->accepts_cargo[0] != 0xFF) {
|
||||
SET_DPARAM16(0, _cargoc.names_s[i->accepts_cargo[0]]);
|
||||
if (i->accepts_cargo[0] != CT_INVALID) {
|
||||
SetDParam(0, _cargoc.names_s[i->accepts_cargo[0]]);
|
||||
str = STR_4827_REQUIRES;
|
||||
if (i->accepts_cargo[1] != 0xFF) {
|
||||
SET_DPARAM16(1, _cargoc.names_s[i->accepts_cargo[1]]);
|
||||
if (i->accepts_cargo[1] != CT_INVALID) {
|
||||
SetDParam(1, _cargoc.names_s[i->accepts_cargo[1]]);
|
||||
str++;
|
||||
if (i->accepts_cargo[2] != 0xFF) {
|
||||
SET_DPARAM16(2, _cargoc.names_s[i->accepts_cargo[2]]);
|
||||
if (i->accepts_cargo[2] != CT_INVALID) {
|
||||
SetDParam(2, _cargoc.names_s[i->accepts_cargo[2]]);
|
||||
str++;
|
||||
}
|
||||
}
|
||||
DrawString(2, 107, str, 0);
|
||||
}
|
||||
|
||||
if (i->produced_cargo[0] != 0xFF) {
|
||||
if (i->produced_cargo[0] != CT_INVALID) {
|
||||
DrawString(2, 117, STR_482A_PRODUCTION_LAST_MONTH, 0);
|
||||
|
||||
SET_DPARAM16(1, i->total_production[0]);
|
||||
SET_DPARAM16(0, _cargoc.names_long_s[i->produced_cargo[0]] + ((i->total_production[0]!=1)<<5));
|
||||
SET_DPARAM16(2, i->pct_transported[0] * 100 >> 8);
|
||||
DrawString(4, 127, STR_482B_TRANSPORTED, 0);
|
||||
SetDParam(1, i->total_production[0]);
|
||||
SetDParam(0, _cargoc.names_long_s[i->produced_cargo[0]] + ((i->total_production[0]!=1)<<5));
|
||||
SetDParam(2, i->pct_transported[0] * 100 >> 8);
|
||||
DrawString(4 + (NEED_ALTERB ? 30 : 0), 127, STR_482B_TRANSPORTED, 0);
|
||||
// Let's put out those buttons..
|
||||
if (NEED_ALTERB)
|
||||
DrawArrowButtons(5, 127, (WP(w,vp2_d).data_2 == 1 ? WP(w,vp2_d).data_3 : 0));
|
||||
|
||||
if (i->produced_cargo[1] != 0xFF) {
|
||||
SET_DPARAM16(1, i->total_production[1]);
|
||||
SET_DPARAM16(0, _cargoc.names_long_s[i->produced_cargo[1]] + ((i->total_production[1]!=1)<<5));
|
||||
SET_DPARAM16(2, i->pct_transported[1] * 100 >> 8);
|
||||
DrawString(4, 137, STR_482B_TRANSPORTED, 0);
|
||||
if (i->produced_cargo[1] != CT_INVALID) {
|
||||
SetDParam(1, i->total_production[1]);
|
||||
SetDParam(0, _cargoc.names_long_s[i->produced_cargo[1]] + ((i->total_production[1]!=1)<<5));
|
||||
SetDParam(2, i->pct_transported[1] * 100 >> 8);
|
||||
DrawString(4 + (NEED_ALTERB ? 30 : 0), 137, STR_482B_TRANSPORTED, 0);
|
||||
// Let's put out those buttons..
|
||||
if (NEED_ALTERB)
|
||||
DrawArrowButtons(5, 137, (WP(w,vp2_d).data_2 == 2 ? WP(w,vp2_d).data_3 : 0));
|
||||
}
|
||||
}
|
||||
|
||||
DrawWindowViewport(w);
|
||||
break;
|
||||
|
||||
case WE_CLICK:
|
||||
switch(e->click.widget) {
|
||||
case 5:
|
||||
i = DEREF_INDUSTRY(w->window_number);
|
||||
ScrollMainWindowToTile(i->xy + TILE_XY(1,1));
|
||||
break;
|
||||
case 6:
|
||||
// Destroy Industry button costing money removed per request of dominik
|
||||
//i = DEREF_INDUSTRY(w->window_number);
|
||||
/* passing only i->xy is not safe if industry has a weird shape like:
|
||||
_ X X
|
||||
X X X
|
||||
_ <--- grass, no industry, but i->xy points there (first top-left tile)!,
|
||||
so passing i->xy to destroy industry will fail in called procedure
|
||||
*/
|
||||
//DoCommandP(i->xy, w->window_number, 0, CcPlaySound10, CMD_DESTROY_INDUSTRY | CMD_MSG(STR_00B5_CAN_T_CLEAR_THIS_AREA));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case WE_CLICK: {
|
||||
Industry *i;
|
||||
|
||||
switch(e->click.widget) {
|
||||
case 5: {
|
||||
int line;
|
||||
int x;
|
||||
byte b;
|
||||
|
||||
i = GetIndustry(w->window_number);
|
||||
|
||||
// We should work if needed..
|
||||
if (!NEED_ALTERB)
|
||||
return;
|
||||
|
||||
x = e->click.pt.x;
|
||||
line = (e->click.pt.y - 127) / 10;
|
||||
if (e->click.pt.y >= 127 && IS_INT_INSIDE(line, 0, 2) && i->produced_cargo[line]) {
|
||||
if (IS_INT_INSIDE(x, 5, 25) ) {
|
||||
// clicked buttons
|
||||
if (x < 15) {
|
||||
// decrease
|
||||
i->production_rate[line] /= 2;
|
||||
if (i->production_rate[line] < 4)
|
||||
i->production_rate[line] = 4;
|
||||
} else {
|
||||
// increase
|
||||
b = i->production_rate[line] * 2;
|
||||
if (i->production_rate[line] >= 128)
|
||||
b=255;
|
||||
i->production_rate[line] = b;
|
||||
}
|
||||
UpdateIndustryProduction(i);
|
||||
SetWindowDirty(w);
|
||||
w->flags4 |= 5 << WF_TIMEOUT_SHL;
|
||||
WP(w,vp2_d).data_2 = line+1;
|
||||
WP(w,vp2_d).data_3 = (x < 15 ? 1 : 2);
|
||||
} else if (IS_INT_INSIDE(x, 34, 160)) {
|
||||
// clicked the text
|
||||
WP(w,vp2_d).data_1 = line;
|
||||
SetDParam(0, i->production_rate[line] * 8);
|
||||
ShowQueryString(STR_CONFIG_PATCHES_INT32,
|
||||
STR_CONFIG_GAME_PRODUCTION,
|
||||
10, 100, w->window_class,
|
||||
w->window_number);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
i = GetIndustry(w->window_number);
|
||||
ScrollMainWindowToTile(i->xy + TILE_XY(1,1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WE_TIMEOUT:
|
||||
WP(w,vp2_d).data_2 = 0;
|
||||
WP(w,vp2_d).data_3 = 0;
|
||||
SetWindowDirty(w);
|
||||
break;
|
||||
|
||||
case WE_ON_EDIT_TEXT:
|
||||
if (*e->edittext.str) {
|
||||
Industry *i;
|
||||
int val;
|
||||
int line;
|
||||
|
||||
i = GetIndustry(w->window_number);
|
||||
line = WP(w,vp2_d).data_1;
|
||||
val = atoi(e->edittext.str);
|
||||
if (!IS_INT_INSIDE(val, 32, 2040)) {
|
||||
if (val < 32) val = 32;
|
||||
else val = 2040;
|
||||
}
|
||||
i->production_rate[line] = (byte)(val / 8);
|
||||
UpdateIndustryProduction(i);
|
||||
SetWindowDirty(w);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void UpdateIndustryProduction(Industry *i)
|
||||
{
|
||||
if (i->produced_cargo[0] != CT_INVALID)
|
||||
i->total_production[0] = 8 * i->production_rate[0];
|
||||
|
||||
if (i->produced_cargo[1] != CT_INVALID)
|
||||
i->total_production[1] = 8 * i->production_rate[1];
|
||||
}
|
||||
|
||||
static const Widget _industry_view_widgets[] = {
|
||||
{ WWT_TEXTBTN, 9, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, 9, 11, 259, 0, 13, STR_4801, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_IMGBTN, 9, 0, 259, 14, 105, 0x0, STR_NULL},
|
||||
{ WWT_6, 9, 2, 257, 16, 103, 0x0, STR_NULL},
|
||||
{ WWT_IMGBTN, 9, 0, 259, 106, 147, 0x0, STR_NULL},
|
||||
{ WWT_PUSHTXTBTN, 9, 0, 129, 148, 159, STR_00E4_LOCATION, STR_482C_CENTER_THE_MAIN_VIEW_ON},
|
||||
{ WWT_IMGBTN, 9, 130, 259, 148, 159, 0x0, STR_NULL},
|
||||
{ WWT_TEXTBTN, RESIZE_NONE, 9, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 9, 11, 247, 0, 13, STR_4801, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_STICKYBOX, RESIZE_NONE, 9, 248, 259, 0, 13, 0x0, STR_STICKY_BUTTON},
|
||||
{ WWT_IMGBTN, RESIZE_NONE, 9, 0, 259, 14, 105, 0x0, STR_NULL},
|
||||
{ WWT_6, RESIZE_NONE, 9, 2, 257, 16, 103, 0x0, STR_NULL},
|
||||
{ WWT_IMGBTN, RESIZE_NONE, 9, 0, 259, 106, 147, 0x0, STR_NULL},
|
||||
{ WWT_PUSHTXTBTN, RESIZE_NONE, 9, 0, 129, 148, 159, STR_00E4_LOCATION, STR_482C_CENTER_THE_MAIN_VIEW_ON},
|
||||
{ WWT_IMGBTN, RESIZE_NONE, 9, 130, 259, 148, 159, 0x0, STR_NULL},
|
||||
// Destroy Industry button costing money removed per request of dominik
|
||||
//{ WWT_PUSHTXTBTN, 9, 130, 259, 148, 159, STR_INDUSTRYDIR_DESTROY, STR_482C_DESTROY_INDUSTRY},
|
||||
//{ WWT_PUSHTXTBTN, RESIZE_NONE, 9, 130, 259, 148, 159, STR_INDUSTRYDIR_DESTROY, STR_482C_DESTROY_INDUSTRY},
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
static const WindowDesc _industry_view_desc = {
|
||||
-1, -1, 260, 160,
|
||||
WC_INDUSTRY_VIEW,0,
|
||||
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
|
||||
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON,
|
||||
_industry_view_widgets,
|
||||
IndustryViewWndProc
|
||||
};
|
||||
@@ -362,38 +445,42 @@ void ShowIndustryViewWindow(int industry)
|
||||
w = AllocateWindowDescFront(&_industry_view_desc, industry);
|
||||
if (w) {
|
||||
w->flags4 |= WF_DISABLE_VP_SCROLL;
|
||||
i = DEREF_INDUSTRY(w->window_number);
|
||||
WP(w,vp2_d).data_1 = 0;
|
||||
WP(w,vp2_d).data_2 = 0;
|
||||
WP(w,vp2_d).data_3 = 0;
|
||||
i = GetIndustry(w->window_number);
|
||||
AssignWindowViewport(w, 3, 17, 0xFE, 0x56, i->xy + TILE_XY(1,1), 1);
|
||||
}
|
||||
}
|
||||
|
||||
static const Widget _industry_directory_widgets[] = {
|
||||
{ WWT_TEXTBTN, 13, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, 13, 11, 507, 0, 13, STR_INDUSTRYDIR_CAPTION, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_PUSHTXTBTN, 13, 0, 100, 14, 25, STR_SORT_BY_NAME, STR_SORT_TIP},
|
||||
{ WWT_PUSHTXTBTN, 13, 101, 200, 14, 25, STR_SORT_BY_TYPE, STR_SORT_TIP},
|
||||
{ WWT_PUSHTXTBTN, 13, 201, 300, 14, 25, STR_SORT_BY_PRODUCTION, STR_SORT_TIP},
|
||||
{ WWT_PUSHTXTBTN, 13, 301, 400, 14, 25, STR_SORT_BY_TRANSPORTED, STR_SORT_TIP},
|
||||
{ WWT_PANEL, 13, 401, 496, 14, 25, 0x0, STR_NULL},
|
||||
{ WWT_IMGBTN, 13, 0, 496, 26, 189, 0x0, STR_200A_TOWN_NAMES_CLICK_ON_NAME},
|
||||
{ WWT_SCROLLBAR, 13, 497, 507, 14, 189, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
|
||||
{ WWT_TEXTBTN, RESIZE_NONE, 13, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 13, 11, 495, 0, 13, STR_INDUSTRYDIR_CAPTION, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_STICKYBOX, RESIZE_NONE, 13, 496, 507, 0, 13, 0x0, STR_STICKY_BUTTON},
|
||||
{ WWT_PUSHTXTBTN, RESIZE_NONE, 13, 0, 100, 14, 25, STR_SORT_BY_NAME, STR_SORT_ORDER_TIP},
|
||||
{ WWT_PUSHTXTBTN, RESIZE_NONE, 13, 101, 200, 14, 25, STR_SORT_BY_TYPE, STR_SORT_ORDER_TIP},
|
||||
{ WWT_PUSHTXTBTN, RESIZE_NONE, 13, 201, 300, 14, 25, STR_SORT_BY_PRODUCTION, STR_SORT_ORDER_TIP},
|
||||
{ WWT_PUSHTXTBTN, RESIZE_NONE, 13, 301, 400, 14, 25, STR_SORT_BY_TRANSPORTED, STR_SORT_ORDER_TIP},
|
||||
{ WWT_PANEL, RESIZE_NONE, 13, 401, 495, 14, 25, 0x0, STR_NULL},
|
||||
{ WWT_IMGBTN, RESIZE_BOTTOM, 13, 0, 495, 26, 189, 0x0, STR_200A_TOWN_NAMES_CLICK_ON_NAME},
|
||||
{ WWT_SCROLLBAR, RESIZE_BOTTOM, 13, 496, 507, 14, 177, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
|
||||
{ WWT_RESIZEBOX, RESIZE_TB, 13, 496, 507, 178, 189, 0x0, STR_RESIZE_BUTTON},
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
static byte _industry_sort[lengthof(_industries)];
|
||||
static uint _num_industry_sort;
|
||||
|
||||
static char _bufcache[96];
|
||||
static byte _last_industry_idx;
|
||||
static uint16 _last_industry_idx;
|
||||
|
||||
static byte _industry_sort_order;
|
||||
|
||||
static int CDECL GeneralIndustrySorter(const void *a, const void *b)
|
||||
{
|
||||
char buf1[96];
|
||||
byte val;
|
||||
Industry *i = DEREF_INDUSTRY(*(const byte*)a);
|
||||
Industry *j = DEREF_INDUSTRY(*(const byte*)b);
|
||||
uint16 val;
|
||||
Industry *i = GetIndustry(*(const uint16*)a);
|
||||
Industry *j = GetIndustry(*(const uint16*)b);
|
||||
int r = 0;
|
||||
|
||||
switch (_industry_sort_order >> 1) {
|
||||
@@ -434,12 +521,12 @@ static int CDECL GeneralIndustrySorter(const void *a, const void *b)
|
||||
|
||||
// default to string sorting if they are otherwise equal
|
||||
if (r == 0) {
|
||||
SET_DPARAM32(0, i->town->townnameparts);
|
||||
SetDParam(0, i->town->townnameparts);
|
||||
GetString(buf1, i->town->townnametype);
|
||||
|
||||
if ( (val=*(const byte*)b) != _last_industry_idx) {
|
||||
if ( (val=*(const uint16*)b) != _last_industry_idx) {
|
||||
_last_industry_idx = val;
|
||||
SET_DPARAM32(0, j->town->townnameparts);
|
||||
SetDParam(0, j->town->townnameparts);
|
||||
GetString(_bufcache, j->town->townnametype);
|
||||
}
|
||||
r = strcmp(buf1, _bufcache);
|
||||
@@ -449,19 +536,24 @@ static int CDECL GeneralIndustrySorter(const void *a, const void *b)
|
||||
return r;
|
||||
}
|
||||
|
||||
static void MakeSortedIndustryList()
|
||||
static void MakeSortedIndustryList(void)
|
||||
{
|
||||
Industry *i;
|
||||
int n = 0, index = 0;
|
||||
int n = 0;
|
||||
|
||||
for(i=_industries; i != endof(_industries); i++) {
|
||||
if(i->xy) _industry_sort[n++] = index;
|
||||
index++;
|
||||
/* Create array for sorting */
|
||||
_industry_sort = realloc(_industry_sort, GetIndustryPoolSize() * sizeof(_industry_sort[0]));
|
||||
if (_industry_sort == NULL)
|
||||
error("Could not allocate memory for the industry-sorting-list");
|
||||
|
||||
FOR_ALL_INDUSTRIES(i) {
|
||||
if(i->xy)
|
||||
_industry_sort[n++] = i->index;
|
||||
}
|
||||
_num_industry_sort = n;
|
||||
_last_industry_idx = 255; // used for "cache"
|
||||
_last_industry_idx = 0xFFFF; // used for "cache"
|
||||
|
||||
qsort(_industry_sort, n, 1, GeneralIndustrySorter);
|
||||
qsort(_industry_sort, n, sizeof(_industry_sort[0]), GeneralIndustrySorter);
|
||||
|
||||
DEBUG(misc, 1) ("Resorting Industries list...");
|
||||
}
|
||||
@@ -481,7 +573,7 @@ static void IndustryDirectoryWndProc(Window *w, WindowEvent *e)
|
||||
MakeSortedIndustryList();
|
||||
}
|
||||
|
||||
w->vscroll.count = _num_industry_sort;
|
||||
SetVScrollCount(w, _num_industry_sort);
|
||||
|
||||
DrawWindowWidgets(w);
|
||||
DoDrawString(_industry_sort_order & 1 ? "\xAA" : "\xA0", _indicator_positions[_industry_sort_order>>1], 15, 0x10);
|
||||
@@ -490,68 +582,68 @@ static void IndustryDirectoryWndProc(Window *w, WindowEvent *e)
|
||||
n = 0;
|
||||
|
||||
while (p < _num_industry_sort) {
|
||||
i = DEREF_INDUSTRY(_industry_sort[p]);
|
||||
SET_DPARAM16(0, i->town->index);
|
||||
SET_DPARAM16(1, i->type + STR_4802_COAL_MINE);
|
||||
i = GetIndustry(_industry_sort[p]);
|
||||
SetDParam(0, i->town->index);
|
||||
SetDParam(1, i->type + STR_4802_COAL_MINE);
|
||||
if (i->produced_cargo[0] != 0xFF) {
|
||||
SET_DPARAM16(3, i->total_production[0]);
|
||||
SET_DPARAM16(2, _cargoc.names_long_s[i->produced_cargo[0]] + ((i->total_production[0]!=1)<<5));
|
||||
SetDParam(3, i->total_production[0]);
|
||||
SetDParam(2, _cargoc.names_long_s[i->produced_cargo[0]] + ((i->total_production[0]!=1)<<5));
|
||||
|
||||
if (i->produced_cargo[1] != 0xFF) {
|
||||
SET_DPARAM16(5, i->total_production[1]);
|
||||
SET_DPARAM16(4, _cargoc.names_long_s[i->produced_cargo[1]] + ((i->total_production[1]!=1)<<5));
|
||||
SET_DPARAM16(6, i->pct_transported[0] * 100 >> 8);
|
||||
SET_DPARAM16(7, i->pct_transported[1] * 100 >> 8);
|
||||
SetDParam(5, i->total_production[1]);
|
||||
SetDParam(4, _cargoc.names_long_s[i->produced_cargo[1]] + ((i->total_production[1]!=1)<<5));
|
||||
SetDParam(6, i->pct_transported[0] * 100 >> 8);
|
||||
SetDParam(7, i->pct_transported[1] * 100 >> 8);
|
||||
DrawString(4, 28+n*10, STR_INDUSTRYDIR_ITEM_TWO, 0);
|
||||
} else {
|
||||
SET_DPARAM16(4, i->pct_transported[0] * 100 >> 8);
|
||||
SetDParam(4, i->pct_transported[0] * 100 >> 8);
|
||||
DrawString(4, 28+n*10, STR_INDUSTRYDIR_ITEM, 0);
|
||||
}
|
||||
} else {
|
||||
DrawString(4, 28+n*10, STR_INDUSTRYDIR_ITEM_NOPROD, 0);
|
||||
}
|
||||
p++;
|
||||
if (++n == 16)
|
||||
if (++n == w->vscroll.cap)
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
|
||||
case WE_CLICK:
|
||||
switch(e->click.widget) {
|
||||
case 2: {
|
||||
case 3: {
|
||||
_industry_sort_order = _industry_sort_order==0 ? 1 : 0;
|
||||
_industry_sort_dirty = true;
|
||||
SetWindowDirty(w);
|
||||
} break;
|
||||
|
||||
case 3: {
|
||||
case 4: {
|
||||
_industry_sort_order = _industry_sort_order==2 ? 3 : 2;
|
||||
_industry_sort_dirty = true;
|
||||
SetWindowDirty(w);
|
||||
} break;
|
||||
|
||||
case 4: {
|
||||
case 5: {
|
||||
_industry_sort_order = _industry_sort_order==4 ? 5 : 4;
|
||||
_industry_sort_dirty = true;
|
||||
SetWindowDirty(w);
|
||||
} break;
|
||||
|
||||
case 5: {
|
||||
case 6: {
|
||||
_industry_sort_order = _industry_sort_order==6 ? 7 : 6;
|
||||
_industry_sort_dirty = true;
|
||||
SetWindowDirty(w);
|
||||
} break;
|
||||
|
||||
case 7: {
|
||||
case 8: {
|
||||
int y = (e->click.pt.y - 28) / 10;
|
||||
byte p;
|
||||
uint16 p;
|
||||
Industry *c;
|
||||
|
||||
if (!IS_INT_INSIDE(y, 0, 16))
|
||||
if (!IS_INT_INSIDE(y, 0, w->vscroll.cap))
|
||||
return;
|
||||
p = y + w->vscroll.pos;
|
||||
if (p < _num_industry_sort) {
|
||||
c = DEREF_INDUSTRY(_industry_sort[p]);
|
||||
c = GetIndustry(_industry_sort[p]);
|
||||
ScrollMainWindowToTile(c->xy);
|
||||
}
|
||||
} break;
|
||||
@@ -561,6 +653,10 @@ static void IndustryDirectoryWndProc(Window *w, WindowEvent *e)
|
||||
case WE_4:
|
||||
SetWindowDirty(w);
|
||||
break;
|
||||
|
||||
case WE_RESIZE:
|
||||
w->vscroll.cap += e->sizing.diff.y / 10;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -569,14 +665,14 @@ static void IndustryDirectoryWndProc(Window *w, WindowEvent *e)
|
||||
static const WindowDesc _industry_directory_desc = {
|
||||
-1, -1, 508, 190,
|
||||
WC_INDUSTRY_DIRECTORY,0,
|
||||
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
|
||||
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
|
||||
_industry_directory_widgets,
|
||||
IndustryDirectoryWndProc
|
||||
};
|
||||
|
||||
|
||||
|
||||
void ShowIndustryDirectory()
|
||||
void ShowIndustryDirectory(void)
|
||||
{
|
||||
/* Industry List */
|
||||
Window *w;
|
||||
@@ -584,6 +680,8 @@ void ShowIndustryDirectory()
|
||||
w = AllocateWindowDescFront(&_industry_directory_desc, 0);
|
||||
if (w) {
|
||||
w->vscroll.cap = 16;
|
||||
w->resize.height = w->height - 6 * 10; // minimum 10 items
|
||||
w->resize.step_height = 10;
|
||||
SetWindowDirty(w);
|
||||
}
|
||||
}
|
||||
|
||||
+127
-158
@@ -1,6 +1,6 @@
|
||||
#include "stdafx.h"
|
||||
#include "ttd.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
#include "window.h"
|
||||
#include "gui.h"
|
||||
#include "viewport.h"
|
||||
@@ -8,78 +8,112 @@
|
||||
#include "player.h"
|
||||
#include "command.h"
|
||||
#include "console.h"
|
||||
#include "network.h"
|
||||
|
||||
extern void MakeNewGame();
|
||||
extern void StartScenario();
|
||||
extern void SwitchMode(int new_mode);
|
||||
|
||||
/*
|
||||
static void ShowSelectTutorialWindow()
|
||||
{
|
||||
}
|
||||
*/
|
||||
#if 0
|
||||
static void ShowSelectTutorialWindow() {}
|
||||
#endif
|
||||
|
||||
static const Widget _select_game_widgets[] = {
|
||||
{ WWT_CAPTION, 13, 0, 335, 0, 13, STR_0307_OPENTTD, STR_NULL},
|
||||
{ WWT_IMGBTN, 13, 0, 335, 14, 196, 0x0, STR_NULL},
|
||||
{ WWT_PUSHTXTBTN, 12, 10, 167, 22, 33, STR_0140_NEW_GAME, STR_02FB_START_A_NEW_GAME},
|
||||
{ WWT_PUSHTXTBTN, 12, 168, 325, 22, 33, STR_0141_LOAD_GAME, STR_02FC_LOAD_A_SAVED_GAME_FROM},
|
||||
//{ WWT_PUSHTXTBTN, 12, 10, 167, 177, 188, STR_0142_TUTORIAL_DEMONSTRATION, STR_02FD_VIEW_DEMONSTRATIONS_TUTORIALS},
|
||||
{ WWT_PUSHTXTBTN, 12, 10, 167, 177, 188, STR_CONFIG_PATCHES, STR_CONFIG_PATCHES_TIP},
|
||||
{ WWT_PUSHTXTBTN, 12, 10, 167, 40, 51, STR_0220_CREATE_SCENARIO,STR_02FE_CREATE_A_CUSTOMIZED_GAME},
|
||||
{ WWT_PUSHTXTBTN, 12, 10, 167, 136, 147, STR_SINGLE_PLAYER, STR_02FF_SELECT_SINGLE_PLAYER_GAME},
|
||||
{ WWT_PUSHTXTBTN, 12, 168, 325, 136, 147, STR_MULTIPLAYER, STR_0300_SELECT_TWO_PLAYER_GAME},
|
||||
{ WWT_PUSHTXTBTN, 12, 10, 167, 159, 170, STR_0148_GAME_OPTIONS, STR_0301_DISPLAY_GAME_OPTIONS},
|
||||
{ WWT_PUSHTXTBTN, 12, 168, 325, 159, 170, STR_01FE_DIFFICULTY, STR_0302_DISPLAY_DIFFICULTY_OPTIONS},
|
||||
{ WWT_PUSHTXTBTN, 12, 168, 325, 40, 51, STR_029A_PLAY_SCENARIO, STR_0303_START_A_NEW_GAME_USING},
|
||||
{ WWT_PUSHTXTBTN, 12, 168, 325, 177, 188, STR_0304_QUIT, STR_0305_LEAVE_OPENTTD},
|
||||
{ WWT_PANEL_2, 12, 10, 85, 69, 122, 0x1312, STR_030E_SELECT_TEMPERATE_LANDSCAPE},
|
||||
{ WWT_PANEL_2, 12, 90, 165, 69, 122, 0x1314, STR_030F_SELECT_SUB_ARCTIC_LANDSCAPE},
|
||||
{ WWT_PANEL_2, 12, 170, 245, 69, 122, 0x1316, STR_0310_SELECT_SUB_TROPICAL_LANDSCAPE},
|
||||
{ WWT_PANEL_2, 12, 250, 325, 69, 122, 0x1318, STR_0311_SELECT_TOYLAND_LANDSCAPE},
|
||||
{ WIDGETS_END},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 13, 0, 335, 0, 13, STR_0307_OPENTTD, STR_NULL},
|
||||
{ WWT_IMGBTN, RESIZE_NONE, 13, 0, 335, 14, 196, STR_NULL, STR_NULL},
|
||||
{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 10, 167, 22, 33, STR_0140_NEW_GAME, STR_02FB_START_A_NEW_GAME},
|
||||
{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 168, 325, 22, 33, STR_0141_LOAD_GAME, STR_02FC_LOAD_A_SAVED_GAME},
|
||||
{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 10, 167, 40, 51, STR_0220_CREATE_SCENARIO,STR_02FE_CREATE_A_CUSTOMIZED_GAME},
|
||||
{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 168, 325, 40, 51, STR_029A_PLAY_SCENARIO, STR_0303_START_A_NEW_GAME_USING},
|
||||
{ WWT_PANEL_2, RESIZE_NONE, 12, 10, 86, 59, 113, 0x1312, STR_030E_SELECT_TEMPERATE_LANDSCAPE},
|
||||
{ WWT_PANEL_2, RESIZE_NONE, 12, 90, 166, 59, 113, 0x1314, STR_030F_SELECT_SUB_ARCTIC_LANDSCAPE},
|
||||
{ WWT_PANEL_2, RESIZE_NONE, 12, 170, 246, 59, 113, 0x1316, STR_0310_SELECT_SUB_TROPICAL_LANDSCAPE},
|
||||
{ WWT_PANEL_2, RESIZE_NONE, 12, 250, 326, 59, 113, 0x1318, STR_0311_SELECT_TOYLAND_LANDSCAPE},
|
||||
|
||||
{ WWT_PANEL, RESIZE_NONE, 12, 219, 254, 120, 131, STR_NULL, STR_NULL},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 12, 255, 266, 120, 131, STR_0225, STR_NULL},
|
||||
{ WWT_PANEL, RESIZE_NONE, 12, 279, 314, 120, 131, STR_NULL, STR_NULL},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 12, 315, 326, 120, 131, STR_0225, STR_NULL},
|
||||
|
||||
{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 10, 167, 138, 149, STR_SINGLE_PLAYER, STR_02FF_SELECT_SINGLE_PLAYER_GAME},
|
||||
{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 168, 325, 138, 149, STR_MULTIPLAYER, STR_0300_SELECT_MULTIPLAYER_GAME},
|
||||
{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 10, 167, 159, 170, STR_0148_GAME_OPTIONS, STR_0301_DISPLAY_GAME_OPTIONS},
|
||||
{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 168, 325, 159, 170, STR_01FE_DIFFICULTY, STR_0302_DISPLAY_DIFFICULTY_OPTIONS},
|
||||
{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 10, 167, 177, 188, STR_CONFIG_PATCHES, STR_CONFIG_PATCHES_TIP},
|
||||
{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 168, 325, 177, 188, STR_0304_QUIT, STR_0305_QUIT_OPENTTD},
|
||||
{ WIDGETS_END },
|
||||
};
|
||||
|
||||
static void SelectGameWndProc(Window *w, WindowEvent *e) {
|
||||
switch(e->event) {
|
||||
extern void HandleOnEditText(WindowEvent *e);
|
||||
extern void HandleOnEditTextCancel(void);
|
||||
|
||||
static inline void CreateScenario(void) {_switch_mode = SM_EDITOR;}
|
||||
|
||||
static inline void SetNewLandscapeType(byte landscape)
|
||||
{
|
||||
_opt_newgame.landscape = landscape;
|
||||
InvalidateWindowClasses(WC_SELECT_GAME);
|
||||
}
|
||||
|
||||
static void SelectGameWndProc(Window *w, WindowEvent *e)
|
||||
{
|
||||
/* We do +/- 6 for the map_xy because 64 is 2^6, but it is the lowest available element */
|
||||
static const StringID mapsizes[] = {STR_64, STR_128, STR_256, STR_512, STR_1024, STR_2048, INVALID_STRING_ID};
|
||||
|
||||
switch (e->event) {
|
||||
case WE_PAINT:
|
||||
w->click_state = (w->click_state & ~(0xC0) & ~(0xF << 12)) | (1 << (_new_opt.landscape+12)) | (!_networking?(1<<6):(1<<7));
|
||||
w->disabled_state = _networking ? 0x30 : 0;
|
||||
SET_DPARAM16(0, STR_6801_EASY + _new_opt.diff_level);
|
||||
w->click_state = (w->click_state & ~(1 << 14) & ~(0xF << 6)) | (1 << (_opt_newgame.landscape + 6)) | (1 << 14);
|
||||
SetDParam(0, STR_6801_EASY + _opt_newgame.diff_level);
|
||||
DrawWindowWidgets(w);
|
||||
|
||||
DrawStringRightAligned(216, 121, STR_MAPSIZE, 0);
|
||||
DrawString(223, 121, mapsizes[_patches.map_x - 6], 0x10);
|
||||
DrawString(270, 121, STR_BY, 0);
|
||||
DrawString(283, 121, mapsizes[_patches.map_y - 6], 0x10);
|
||||
break;
|
||||
|
||||
case WE_CLICK:
|
||||
switch(e->click.widget) {
|
||||
case 2: DoCommandP(0, 0, 0, NULL, CMD_START_NEW_GAME); break;
|
||||
switch (e->click.widget) {
|
||||
case 2: AskForNewGameToStart(); break;
|
||||
case 3: ShowSaveLoadDialog(SLD_LOAD_GAME); break;
|
||||
case 4: ShowPatchesSelection(); break;
|
||||
case 5: DoCommandP(0, InteractiveRandom(), 0, NULL, CMD_CREATE_SCENARIO); break;
|
||||
case 6:
|
||||
if (_networking)
|
||||
DoCommandP(0, 0, 0, NULL, CMD_SET_SINGLE_PLAYER);
|
||||
case 4: CreateScenario(); break;
|
||||
case 5: ShowSaveLoadDialog(SLD_LOAD_SCENARIO); break;
|
||||
case 6: case 7: case 8: case 9:
|
||||
SetNewLandscapeType(e->click.widget - 6);
|
||||
break;
|
||||
case 7:
|
||||
case 10: case 11: /* Mapsize X */
|
||||
ShowDropDownMenu(w, mapsizes, _patches.map_x - 6, 11, 0, 0);
|
||||
break;
|
||||
case 12: case 13: /* Mapsize Y */
|
||||
ShowDropDownMenu(w, mapsizes, _patches.map_y - 6, 13, 0, 0);
|
||||
break;
|
||||
case 15:
|
||||
#ifdef ENABLE_NETWORK
|
||||
if (!_network_available) {
|
||||
ShowErrorMessage(-1,STR_NETWORK_ERR_NOTAVAILABLE, 0, 0);
|
||||
} else {
|
||||
ShowErrorMessage(-1, STR_NETWORK_ERR_NOTAVAILABLE, 0, 0);
|
||||
} else
|
||||
ShowNetworkGameWindow();
|
||||
ShowErrorMessage(-1, TEMP_STRING_NO_NETWORK, 0, 0);
|
||||
}
|
||||
#else
|
||||
ShowErrorMessage(-1 ,STR_NETWORK_ERR_NOTAVAILABLE, 0, 0);
|
||||
#endif
|
||||
break;
|
||||
case 8: ShowGameOptions(); break;
|
||||
case 9: ShowGameDifficulty(); break;
|
||||
case 10:ShowSaveLoadDialog(SLD_LOAD_SCENARIO); break;
|
||||
case 11:AskExitGame(); break;
|
||||
case 12: case 13: case 14: case 15:
|
||||
DoCommandP(0, e->click.widget - 12, 0, NULL, CMD_SET_NEW_LANDSCAPE_TYPE);
|
||||
break;
|
||||
}
|
||||
case WE_KEYPRESS:
|
||||
switch(e->keypress.keycode) {
|
||||
case WKC_BACKQUOTE: IConsoleSwitch(); break;
|
||||
case 16: ShowGameOptions(); break;
|
||||
case 17: ShowGameDifficulty(); break;
|
||||
case 18: ShowPatchesSelection(); break;
|
||||
case 19: AskExitGame(); break;
|
||||
}
|
||||
break;
|
||||
|
||||
case WE_ON_EDIT_TEXT: HandleOnEditText(e); break;
|
||||
case WE_ON_EDIT_TEXT_CANCEL: HandleOnEditTextCancel(); break;
|
||||
|
||||
case WE_DROPDOWN_SELECT: /* Mapsize selection */
|
||||
switch (e->dropdown.button) {
|
||||
case 11: _patches.map_x = e->dropdown.index + 6; break;
|
||||
case 13: _patches.map_y = e->dropdown.index + 6; break;
|
||||
}
|
||||
SetWindowDirty(w);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static const WindowDesc _select_game_desc = {
|
||||
@@ -90,99 +124,34 @@ static const WindowDesc _select_game_desc = {
|
||||
SelectGameWndProc
|
||||
};
|
||||
|
||||
void ShowSelectGameWindow()
|
||||
void ShowSelectGameWindow(void)
|
||||
{
|
||||
AllocateWindowDesc(&_select_game_desc);
|
||||
}
|
||||
|
||||
|
||||
// p1 = mode
|
||||
// 0 - start new game
|
||||
// 1 - close new game dialog
|
||||
|
||||
int32 CmdStartNewGame(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
void GenRandomNewGame(uint32 rnd1, uint32 rnd2)
|
||||
{
|
||||
if (!(flags & DC_EXEC))
|
||||
return 0;
|
||||
_random_seeds[0][0] = rnd1;
|
||||
_random_seeds[0][1] = rnd2;
|
||||
|
||||
switch(p1) {
|
||||
case 0: // show select game window
|
||||
AskForNewGameToStart();
|
||||
break;
|
||||
case 1: // close select game window
|
||||
DeleteWindowById(WC_SAVELOAD, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
SwitchMode(SM_NEWGAME);
|
||||
}
|
||||
|
||||
int32 CmdGenRandomNewGame(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
void StartScenarioEditor(uint32 rnd1, uint32 rnd2)
|
||||
{
|
||||
if (!(flags & DC_EXEC))
|
||||
return 0;
|
||||
_random_seeds[0][0] = rnd1;
|
||||
_random_seeds[0][1] = rnd2;
|
||||
|
||||
// this forces stuff into test mode.
|
||||
_docommand_recursive = 0;
|
||||
|
||||
_random_seeds[0][0] = p1;
|
||||
_random_seeds[0][1] = p2;
|
||||
|
||||
if (_networking) { NetworkStartSync(true); }
|
||||
|
||||
MakeNewGame();
|
||||
return 0;
|
||||
SwitchMode(SM_START_SCENARIO);
|
||||
}
|
||||
|
||||
int32 CmdLoadGame(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
if (!(flags & DC_EXEC))
|
||||
return 0;
|
||||
|
||||
// ShowSaveLoadDialog(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32 CmdCreateScenario(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
if (!(flags & DC_EXEC))
|
||||
return 0;
|
||||
|
||||
_switch_mode = SM_EDITOR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32 CmdSetSinglePlayer(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
printf("CmdSetSinglePlayer\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32 CmdStartScenario(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
if (!(flags & DC_EXEC))
|
||||
return 0;
|
||||
|
||||
// this forces stuff into test mode.
|
||||
_docommand_recursive = 0;
|
||||
|
||||
_random_seeds[0][0] = p1;
|
||||
_random_seeds[0][1] = p2;
|
||||
|
||||
if (_networking) { NetworkStartSync(true); }
|
||||
|
||||
StartScenario();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static const Widget _ask_abandon_game_widgets[] = {
|
||||
{ WWT_TEXTBTN, 4, 0, 10, 0, 13, STR_00C5, STR_NULL},
|
||||
{ WWT_CAPTION, 4, 11, 179, 0, 13, STR_00C7_QUIT, STR_NULL},
|
||||
{ WWT_IMGBTN, 4, 0, 179, 14, 91, 0x0, STR_NULL},
|
||||
{ WWT_TEXTBTN, 12, 25, 84, 72, 83, STR_00C9_NO, STR_NULL},
|
||||
{ WWT_TEXTBTN, 12, 95, 154, 72, 83, STR_00C8_YES, STR_NULL},
|
||||
{ WIDGETS_END},
|
||||
{ WWT_TEXTBTN, RESIZE_NONE, 4, 0, 10, 0, 13, STR_00C5, STR_NULL},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 4, 11, 179, 0, 13, STR_00C7_QUIT, STR_NULL},
|
||||
{ WWT_IMGBTN, RESIZE_NONE, 4, 0, 179, 14, 91, 0x0, STR_NULL},
|
||||
{ WWT_TEXTBTN, RESIZE_NONE, 12, 25, 84, 72, 83, STR_00C9_NO, STR_NULL},
|
||||
{ WWT_TEXTBTN, RESIZE_NONE, 12, 95, 154, 72, 83, STR_00C8_YES, STR_NULL},
|
||||
{ WIDGETS_END },
|
||||
};
|
||||
|
||||
static void AskAbandonGameWndProc(Window *w, WindowEvent *e) {
|
||||
@@ -190,15 +159,19 @@ static void AskAbandonGameWndProc(Window *w, WindowEvent *e) {
|
||||
case WE_PAINT:
|
||||
DrawWindowWidgets(w);
|
||||
#if defined(_WIN32)
|
||||
SET_DPARAM16(0, STR_0133_WINDOWS);
|
||||
SetDParam(0, STR_0133_WINDOWS);
|
||||
#elif defined(__APPLE__)
|
||||
SET_DPARAM16(0, STR_0135_OSX);
|
||||
SetDParam(0, STR_0135_OSX);
|
||||
#elif defined(__BEOS__)
|
||||
SET_DPARAM16(0, STR_OSNAME_BEOS);
|
||||
SetDParam(0, STR_OSNAME_BEOS);
|
||||
#elif defined(__MORPHOS__)
|
||||
SET_DPARAM16(0, STR_OSNAME_MORPHOS);
|
||||
SetDParam(0, STR_OSNAME_MORPHOS);
|
||||
#elif defined(__AMIGA__)
|
||||
SetDParam(0, STR_OSNAME_AMIGAOS);
|
||||
#elif defined(__OS2__)
|
||||
SetDParam(0, STR_OSNAME_OS2);
|
||||
#else
|
||||
SET_DPARAM16(0, STR_0134_UNIX);
|
||||
SetDParam(0, STR_0134_UNIX);
|
||||
#endif
|
||||
DrawStringMultiCenter(0x5A, 0x26, STR_00CA_ARE_YOU_SURE_YOU_WANT_TO, 178);
|
||||
return;
|
||||
@@ -214,7 +187,7 @@ static void AskAbandonGameWndProc(Window *w, WindowEvent *e) {
|
||||
}
|
||||
break;
|
||||
case WE_KEYPRESS: /* Exit game on pressing 'Enter' */
|
||||
if (e->keypress.keycode == WKC_RETURN)
|
||||
if (e->keypress.keycode == WKC_RETURN || e->keypress.keycode == WKC_NUM_ENTER)
|
||||
_exit_game = true;
|
||||
break;
|
||||
}
|
||||
@@ -228,19 +201,19 @@ static const WindowDesc _ask_abandon_game_desc = {
|
||||
AskAbandonGameWndProc
|
||||
};
|
||||
|
||||
void AskExitGame()
|
||||
void AskExitGame(void)
|
||||
{
|
||||
AllocateWindowDescFront(&_ask_abandon_game_desc, 0);
|
||||
}
|
||||
|
||||
|
||||
static const Widget _ask_quit_game_widgets[] = {
|
||||
{ WWT_TEXTBTN, 4, 0, 10, 0, 13, STR_00C5, STR_NULL},
|
||||
{ WWT_CAPTION, 4, 11, 179, 0, 13, STR_0161_QUIT_GAME, STR_NULL},
|
||||
{ WWT_IMGBTN, 4, 0, 179, 14, 91, 0x0, STR_NULL},
|
||||
{ WWT_TEXTBTN, 12, 25, 84, 72, 83, STR_00C9_NO, STR_NULL},
|
||||
{ WWT_TEXTBTN, 12, 95, 154, 72, 83, STR_00C8_YES, STR_NULL},
|
||||
{ WIDGETS_END},
|
||||
{ WWT_TEXTBTN, RESIZE_NONE, 4, 0, 10, 0, 13, STR_00C5, STR_NULL},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 4, 11, 179, 0, 13, STR_0161_QUIT_GAME, STR_NULL},
|
||||
{ WWT_IMGBTN, RESIZE_NONE, 4, 0, 179, 14, 91, 0x0, STR_NULL},
|
||||
{ WWT_TEXTBTN, RESIZE_NONE, 12, 25, 84, 72, 83, STR_00C9_NO, STR_NULL},
|
||||
{ WWT_TEXTBTN, RESIZE_NONE, 12, 95, 154, 72, 83, STR_00C8_YES, STR_NULL},
|
||||
{ WIDGETS_END },
|
||||
};
|
||||
|
||||
static void AskQuitGameWndProc(Window *w, WindowEvent *e) {
|
||||
@@ -263,6 +236,12 @@ static void AskQuitGameWndProc(Window *w, WindowEvent *e) {
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case WE_KEYPRESS: /* Return to main menu on pressing 'Enter' */
|
||||
if (e->keypress.keycode == WKC_RETURN)
|
||||
_switch_mode = SM_MENU;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,17 +254,7 @@ static const WindowDesc _ask_quit_game_desc = {
|
||||
};
|
||||
|
||||
|
||||
void AskExitToGameMenu()
|
||||
void AskExitToGameMenu(void)
|
||||
{
|
||||
AllocateWindowDescFront(&_ask_quit_game_desc, 0);
|
||||
}
|
||||
|
||||
int32 CmdSetNewLandscapeType(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
if (flags & DC_EXEC) {
|
||||
// XXX: some stuff
|
||||
_new_opt.landscape = p1;
|
||||
InvalidateWindowClasses(WC_SELECT_GAME);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
README
|
||||
------------------------------------------------------------------------
|
||||
All bugs listed below are marked as known. Please do not submit any bugs
|
||||
that are the same as these. If you do, don't act surprised, because
|
||||
we WILL flame you!!
|
||||
|
||||
There is an experimental AI included in the game which you can enable
|
||||
from the "Configure Patches" window. All bugs related to this AI should
|
||||
go to: http://www.tt-forums.net/viewtopic.php?t=9576
|
||||
|
||||
Of course if you have more knowledge about any of these bugs, have more
|
||||
specifics, we welcome you to report them. React to the given bug indicated
|
||||
by the number below on http://sourceforge.net/tracker/?group_id=103924&atid=636365
|
||||
If the the bug report is closed, it has been fixed, which then can be verified
|
||||
in the latest SVN version.
|
||||
|
||||
Bugs for 0.4.0.1
|
||||
------------------------------------------------------------------------
|
||||
URL: http://sourceforge.net/tracker/?atid=636365&group_id=103924&func=browse
|
||||
|
||||
- Minimap crash with certain views and certain resolutions
|
||||
- "Broken" autoreplace for dual-headed trains
|
||||
-1203319 Pre-signal exits not working when one way signal
|
||||
-1197116 Some stations are cargo-less
|
||||
-1188897 Station with cargo enroute_from INVALID_STATION
|
||||
-1186802 Company value problem (loans)
|
||||
-1181888 Invaild Station Order => Crash
|
||||
-1174829 Waypoint / Orders Bug
|
||||
-1168820 Some mouse and keyboard events are lost
|
||||
-1167810 Cargo payment after deleting stations (st->xy = 0)
|
||||
-1157244 Can't save game if name contains german umlauts
|
||||
-1144510 Make install tries to install scenarios to the wrong place
|
||||
-1116638 "More, but smaller changes" deficiency
|
||||
-1106356 re-offered prototypes
|
||||
-1099233 production down before it's working
|
||||
-1085486 Subsidies: Only count when station is in right suburb
|
||||
-992677 BeOS MIDI does not initialise on newer BeOS releases
|
||||
|
||||
Minor Bugs for 0.4.0.1
|
||||
------------------------------------------------------------------------
|
||||
URL: http://sourceforge.net/tracker/?atid=669662&group_id=103924&func=browse
|
||||
|
||||
-1201284 permanent hilight in a depot
|
||||
-1197258 Window Z-order locked when exiting openttd
|
||||
-1193882 problems with dualhead engins in DB Set XL (v0.81)
|
||||
-1193870 keep the date counter running
|
||||
-1185852 Scrollbars get arbitrarily small
|
||||
-1184634 Replace vehicles window bug
|
||||
-1183253 Incorrect Load vs Loading Sprites
|
||||
-1183251 Hangar sprite does not update when refit.
|
||||
-1179933 autorail removal does not go completely red.
|
||||
-1160732 little bug with transparency
|
||||
-1153937 Game wont run from a start menu shortcut
|
||||
-1117731 Editor-StartingDate
|
||||
-1114237 Wrong autoreplace hint
|
||||
-1112784 detailed sound options
|
||||
-1108046 game freezes
|
||||
-1106889 Chat Interface enhancements
|
||||
-1104358 train lost message - history
|
||||
-1102174 Bug if 3 people buy 25% shares in one company
|
||||
-1087407 wrong message in history
|
||||
-1084620 Minor bug considering buses/trucks
|
||||
-1034310 color mauve in diagrams
|
||||
-1030661 It's possible to build a tunnel under oil wells
|
||||
-1009171 Canals and locks at sea level cause flooding
|
||||
-993516 Canal + bouy -> wrong graphics.
|
||||
-987891 Large UFO destruction bug
|
||||
-987884 farm fences
|
||||
-987883 Aircraft landing/taking off
|
||||
-987880 company league table updating
|
||||
-985924 aircraft taxi speed
|
||||
-980276 Overflow in factory directory
|
||||
-976824 transmitter base
|
||||
-941694 Clipping problems stations/vehicles on slopes
|
||||
-936997 Stationname too long to fit in trainwindow bug
|
||||
+229
-304
@@ -1,19 +1,15 @@
|
||||
#include "stdafx.h"
|
||||
#include "ttd.h"
|
||||
#include "map.h"
|
||||
#include "spritecache.h"
|
||||
#include "table/sprites.h"
|
||||
#include "tile.h"
|
||||
#include <stdarg.h>
|
||||
#include "gfx.h"
|
||||
#include "viewport.h"
|
||||
#include "command.h"
|
||||
#include "vehicle.h"
|
||||
|
||||
byte _map_type_and_height[TILES_X * TILES_Y];
|
||||
byte _map5[TILES_X * TILES_Y];
|
||||
byte _map3_lo[TILES_X * TILES_Y];
|
||||
byte _map3_hi[TILES_X * TILES_Y];
|
||||
byte _map_owner[TILES_X * TILES_Y];
|
||||
byte _map2[TILES_X * TILES_Y];
|
||||
byte _map_extra_bits[TILES_X * TILES_Y/4];
|
||||
|
||||
extern const TileTypeProcs
|
||||
_tile_type_clear_procs,
|
||||
_tile_type_rail_procs,
|
||||
@@ -47,84 +43,33 @@ const byte _tileh_to_sprite[32] = {
|
||||
0,0,0,0,0,0,0,16,0,0,0,17,0,15,18,0,
|
||||
};
|
||||
|
||||
uint GetTileSlope(uint tile, int *h)
|
||||
|
||||
void FindLandscapeHeightByTile(TileInfo *ti, TileIndex tile)
|
||||
{
|
||||
uint a,b,c,d,min;
|
||||
int r;
|
||||
|
||||
if (GET_TILE_X(tile) == TILE_X_MAX || GET_TILE_Y(tile) == TILE_Y_MAX) {
|
||||
if (h)
|
||||
*h = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(tile < TILES_X * TILES_Y && GET_TILE_X(tile) != TILE_X_MAX && GET_TILE_Y(tile) != TILE_Y_MAX);
|
||||
|
||||
min = a = _map_type_and_height[tile] & 0xF;
|
||||
b = _map_type_and_height[tile+TILE_XY(1,0)] & 0xF;
|
||||
if (min >= b) min = b;
|
||||
c = _map_type_and_height[tile+TILE_XY(0,1)] & 0xF;
|
||||
if (min >= c) min = c;
|
||||
d = _map_type_and_height[tile+TILE_XY(1,1)] & 0xF;
|
||||
if (min >= d) min = d;
|
||||
|
||||
r = 0;
|
||||
if ((a-=min)!=0) { r += (--a << 4) + 8; }
|
||||
if ((c-=min)!=0) { r += (--c << 4) + 4; }
|
||||
if ((d-=min)!=0) { r += (--d << 4) + 2; }
|
||||
if ((b-=min)!=0) { r += (--b << 4) + 1; }
|
||||
|
||||
if (h != 0)
|
||||
*h = min * 8;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int GetTileZ(uint tile)
|
||||
{
|
||||
int h;
|
||||
GetTileSlope(tile, &h);
|
||||
return h;
|
||||
}
|
||||
|
||||
void FindLandscapeHeightByTile(TileInfo *ti, uint tile)
|
||||
{
|
||||
if (GET_TILE_X(tile) == TILE_X_MAX ||
|
||||
GET_TILE_Y(tile) == TILE_Y_MAX) {
|
||||
ti->tileh = 0;
|
||||
ti->type = MP_STRANGE;
|
||||
ti->tile = 0;
|
||||
ti->map5 = 0;
|
||||
ti->z = 0;
|
||||
return;
|
||||
}
|
||||
assert(tile < MapSize());
|
||||
|
||||
ti->tile = tile;
|
||||
ti->map5 = _map5[tile];
|
||||
ti->type = GET_TILETYPE(tile);
|
||||
ti->type = GetTileType(tile);
|
||||
ti->tileh = GetTileSlope(tile, &ti->z);
|
||||
// ti->z = min * 8;
|
||||
}
|
||||
|
||||
/* find the landscape height for the coordinates x y */
|
||||
void FindLandscapeHeight(TileInfo *ti, uint x, uint y)
|
||||
{
|
||||
int tile;
|
||||
|
||||
ti->x = x;
|
||||
ti->y = y;
|
||||
|
||||
if (x >= TILE_X_MAX*16-1 || y >= TILE_Y_MAX*16-1) {
|
||||
if (x >= MapMaxX() * 16 - 1 || y >= MapMaxY() * 16 - 1) {
|
||||
ti->tileh = 0;
|
||||
ti->type = MP_STRANGE;
|
||||
ti->type = MP_VOID;
|
||||
ti->tile = 0;
|
||||
ti->map5 = 0;
|
||||
ti->z = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
tile = TILE_FROM_XY(x,y);
|
||||
FindLandscapeHeightByTile(ti, tile);
|
||||
FindLandscapeHeightByTile(ti, TILE_FROM_XY(x,y));
|
||||
}
|
||||
|
||||
uint GetPartialZ(int x, int y, int corners)
|
||||
@@ -225,24 +170,15 @@ uint GetPartialZ(int x, int y, int corners)
|
||||
uint GetSlopeZ(int x, int y)
|
||||
{
|
||||
TileInfo ti;
|
||||
// int z;
|
||||
|
||||
FindLandscapeHeight(&ti, x, y);
|
||||
|
||||
/*
|
||||
z = ti.z;
|
||||
x &= 0xF;
|
||||
y &= 0xF;
|
||||
|
||||
|
||||
assert(z < 256);
|
||||
*/
|
||||
return _tile_type_procs[ti.type]->get_slope_z_proc(&ti);
|
||||
}
|
||||
|
||||
// direction=true: check for foundation in east and south corner
|
||||
// direction=false: check for foundation in west and south corner
|
||||
bool hasFoundation(TileInfo *ti, bool direction)
|
||||
static bool hasFoundation(TileInfo *ti, bool direction)
|
||||
{
|
||||
bool south, other; // southern corner and east/west corner
|
||||
uint slope = _tile_type_procs[ti->type]->get_slope_tileh_proc(ti);
|
||||
@@ -291,7 +227,7 @@ void DrawFoundation(TileInfo *ti, uint f)
|
||||
}
|
||||
}
|
||||
|
||||
void DoClearSquare(uint tile)
|
||||
void DoClearSquare(TileIndex tile)
|
||||
{
|
||||
ModifyTile(tile,
|
||||
MP_SETTYPE(MP_CLEAR) |
|
||||
@@ -301,30 +237,30 @@ void DoClearSquare(uint tile)
|
||||
);
|
||||
}
|
||||
|
||||
uint32 GetTileTrackStatus(uint tile, TransportType mode)
|
||||
uint32 GetTileTrackStatus(TileIndex tile, TransportType mode)
|
||||
{
|
||||
return _tile_type_procs[GET_TILETYPE(tile)]->get_tile_track_status_proc(tile, mode);
|
||||
return _tile_type_procs[GetTileType(tile)]->get_tile_track_status_proc(tile, mode);
|
||||
}
|
||||
|
||||
void ChangeTileOwner(uint tile, byte old_player, byte new_player)
|
||||
void ChangeTileOwner(TileIndex tile, byte old_player, byte new_player)
|
||||
{
|
||||
_tile_type_procs[GET_TILETYPE(tile)]->change_tile_owner_proc(tile, old_player, new_player);
|
||||
_tile_type_procs[GetTileType(tile)]->change_tile_owner_proc(tile, old_player, new_player);
|
||||
}
|
||||
|
||||
void GetAcceptedCargo(uint tile, AcceptedCargo *ac)
|
||||
void GetAcceptedCargo(TileIndex tile, AcceptedCargo ac)
|
||||
{
|
||||
memset(ac, 0, sizeof(AcceptedCargo));
|
||||
_tile_type_procs[GET_TILETYPE(tile)]->get_accepted_cargo_proc(tile, ac);
|
||||
_tile_type_procs[GetTileType(tile)]->get_accepted_cargo_proc(tile, ac);
|
||||
}
|
||||
|
||||
void AnimateTile(uint tile)
|
||||
void AnimateTile(TileIndex tile)
|
||||
{
|
||||
_tile_type_procs[GET_TILETYPE(tile)]->animate_tile_proc(tile);
|
||||
_tile_type_procs[GetTileType(tile)]->animate_tile_proc(tile);
|
||||
}
|
||||
|
||||
void ClickTile(uint tile)
|
||||
void ClickTile(TileIndex tile)
|
||||
{
|
||||
_tile_type_procs[GET_TILETYPE(tile)]->click_tile_proc(tile);
|
||||
_tile_type_procs[GetTileType(tile)]->click_tile_proc(tile);
|
||||
}
|
||||
|
||||
void DrawTile(TileInfo *ti)
|
||||
@@ -332,73 +268,81 @@ void DrawTile(TileInfo *ti)
|
||||
_tile_type_procs[ti->type]->draw_tile_proc(ti);
|
||||
}
|
||||
|
||||
void GetTileDesc(uint tile, TileDesc *td)
|
||||
void GetTileDesc(TileIndex tile, TileDesc *td)
|
||||
{
|
||||
_tile_type_procs[GET_TILETYPE(tile)]->get_tile_desc_proc(tile, td);
|
||||
_tile_type_procs[GetTileType(tile)]->get_tile_desc_proc(tile, td);
|
||||
}
|
||||
|
||||
/* Clear a piece of landscape
|
||||
* p1 = 0,
|
||||
* p2 = 0
|
||||
/** Clear a piece of landscape
|
||||
* @param x,y coordinates of clearance
|
||||
* @param p1 unused
|
||||
* @param p2 unused
|
||||
*/
|
||||
|
||||
int32 CmdLandscapeClear(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
uint tile;
|
||||
TileIndex tile = TILE_FROM_XY(x, y);
|
||||
|
||||
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
|
||||
|
||||
tile = TILE_FROM_XY(x,y);
|
||||
return _tile_type_procs[GET_TILETYPE(tile)]->clear_tile_proc(tile, flags);
|
||||
return _tile_type_procs[GetTileType(tile)]->clear_tile_proc(tile, flags);
|
||||
}
|
||||
|
||||
// p1 = end tile
|
||||
/** Clear a big piece of landscape
|
||||
* @param x,y end coordinates of area dragging
|
||||
* @param p1 start tile of area dragging
|
||||
* @param p2 unused
|
||||
*/
|
||||
int32 CmdClearArea(int ex, int ey, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
int32 cost,ret, money;
|
||||
int32 cost, ret, money;
|
||||
int sx,sy;
|
||||
int x,y;
|
||||
bool success = false;
|
||||
|
||||
if (p1 > MapSize()) return CMD_ERROR;
|
||||
|
||||
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
|
||||
|
||||
// make sure sx,sy are smaller than ex,ey
|
||||
sx = GET_TILE_X(p1)*16;
|
||||
sy = GET_TILE_Y(p1)*16;
|
||||
sx = TileX(p1) * 16;
|
||||
sy = TileY(p1) * 16;
|
||||
if (ex < sx) intswap(ex, sx);
|
||||
if (ey < sy) intswap(ey, sy);
|
||||
|
||||
money = GetAvailableMoneyForCommand();
|
||||
cost = 0;
|
||||
|
||||
for(x=sx; x<=ex; x+=16) {
|
||||
for(y=sy; y<=ey; y+=16) {
|
||||
for (x = sx; x <= ex; x += 16) {
|
||||
for (y = sy; y <= ey; y += 16) {
|
||||
ret = DoCommandByTile(TILE_FROM_XY(x,y), 0, 0, flags &~DC_EXEC, CMD_LANDSCAPE_CLEAR);
|
||||
if (ret == CMD_ERROR) continue;
|
||||
if (CmdFailed(ret)) continue;
|
||||
cost += ret;
|
||||
success = true;
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
if ( ret>0 && (money -= ret) < 0) {
|
||||
if (ret > 0 && (money -= ret) < 0) {
|
||||
_additional_cash_required = ret;
|
||||
return cost - ret;
|
||||
}
|
||||
DoCommandByTile(TILE_FROM_XY(x,y), 0, 0, flags, CMD_LANDSCAPE_CLEAR);
|
||||
|
||||
// draw explosion animation...
|
||||
if ((x==sx || x==ex) && (y==sy || y==ey)) {
|
||||
if ((x == sx || x == ex) && (y == sy || y == ey)) {
|
||||
// big explosion in each corner, or small explosion for single tiles
|
||||
CreateEffectVehicleAbove(x + 8,y + 8, 2, sy==ey && sx==ex ? EV_DEMOLISH : EV_CRASHED_SMOKE);
|
||||
CreateEffectVehicleAbove(x + 8, y + 8, 2,
|
||||
sy == ey && sx == ex ? EV_EXPLOSION_SMALL : EV_EXPLOSION_LARGE
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!success)
|
||||
cost = CMD_ERROR;
|
||||
return cost;
|
||||
return (success) ? cost : CMD_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/* utility function used to modify a tile */
|
||||
void CDECL ModifyTile(uint tile, uint flags, ...)
|
||||
void CDECL ModifyTile(TileIndex tile, uint flags, ...)
|
||||
{
|
||||
va_list va;
|
||||
int i;
|
||||
@@ -406,7 +350,7 @@ void CDECL ModifyTile(uint tile, uint flags, ...)
|
||||
va_start(va, flags);
|
||||
|
||||
if ((i = (flags >> 8) & 0xF) != 0) {
|
||||
_map_type_and_height[tile] = (_map_type_and_height[tile]&~0xF0)|((i-1) << 4);
|
||||
SetTileType(tile, i - 1);
|
||||
}
|
||||
|
||||
if (flags & (MP_MAP2_CLEAR | MP_MAP2)) {
|
||||
@@ -443,82 +387,72 @@ void CDECL ModifyTile(uint tile, uint flags, ...)
|
||||
MarkTileDirtyByTile(tile);
|
||||
}
|
||||
|
||||
void SetMapExtraBits(uint tile, byte bits)
|
||||
{
|
||||
_map_extra_bits[tile >> 2] &= ~(3 << ((tile&3)*2));
|
||||
_map_extra_bits[tile >> 2] |= (bits&3) << ((tile&3)*2);
|
||||
}
|
||||
|
||||
uint GetMapExtraBits(uint tile)
|
||||
{
|
||||
return (_map_extra_bits[tile >> 2] >> (tile&3)*2)&3;
|
||||
}
|
||||
|
||||
#define TILELOOP_BITS 4
|
||||
#define TILELOOP_SIZE (1 << TILELOOP_BITS)
|
||||
#define TILELOOP_ASSERTMASK ((TILELOOP_SIZE-1) + ((TILELOOP_SIZE-1) << TILE_X_BITS))
|
||||
#define TILELOOP_CHKMASK (((1 << (TILE_X_BITS - TILELOOP_BITS))-1) << TILELOOP_BITS)
|
||||
#define TILELOOP_ASSERTMASK ((TILELOOP_SIZE-1) + ((TILELOOP_SIZE-1) << MapLogX()))
|
||||
#define TILELOOP_CHKMASK (((1 << (MapLogX() - TILELOOP_BITS))-1) << TILELOOP_BITS)
|
||||
|
||||
void RunTileLoop()
|
||||
void RunTileLoop(void)
|
||||
{
|
||||
uint tile;
|
||||
TileIndex tile;
|
||||
uint count;
|
||||
|
||||
tile = _cur_tileloop_tile;
|
||||
|
||||
assert( (tile & ~TILELOOP_ASSERTMASK) == 0);
|
||||
count = (TILES_X/TILELOOP_SIZE) * (TILES_Y/TILELOOP_SIZE);
|
||||
count = (MapSizeX() / TILELOOP_SIZE) * (MapSizeY() / TILELOOP_SIZE);
|
||||
do {
|
||||
_tile_type_procs[GET_TILETYPE(tile)]->tile_loop_proc(tile);
|
||||
_tile_type_procs[GetTileType(tile)]->tile_loop_proc(tile);
|
||||
|
||||
if ( GET_TILE_X(tile) < TILES_X - TILELOOP_SIZE) {
|
||||
if (TileX(tile) < MapSizeX() - TILELOOP_SIZE) {
|
||||
tile += TILELOOP_SIZE; /* no overflow */
|
||||
} else {
|
||||
tile = TILE_MASK(tile - TILELOOP_SIZE * (TILES_X/TILELOOP_SIZE-1) + TILE_XY(0, TILELOOP_SIZE)); /* x would overflow, also increase y */
|
||||
tile = TILE_MASK(tile - TILELOOP_SIZE * (MapSizeX() / TILELOOP_SIZE-1) + TILE_XY(0, TILELOOP_SIZE)); /* x would overflow, also increase y */
|
||||
}
|
||||
} while (--count);
|
||||
assert( (tile & ~TILELOOP_ASSERTMASK) == 0);
|
||||
|
||||
tile += 9;
|
||||
if (tile & TILELOOP_CHKMASK)
|
||||
tile = (tile + TILES_X) & TILELOOP_ASSERTMASK;
|
||||
tile = (tile + MapSizeX()) & TILELOOP_ASSERTMASK;
|
||||
_cur_tileloop_tile = tile;
|
||||
}
|
||||
|
||||
void InitializeLandscape()
|
||||
void InitializeLandscape(uint log_x, uint log_y)
|
||||
{
|
||||
int i;
|
||||
uint map_size;
|
||||
uint i;
|
||||
|
||||
memset(_map_owner, OWNER_NONE, sizeof(_map_owner));
|
||||
memset(_map2, 0, sizeof(_map2));
|
||||
memset(_map3_lo, 0, sizeof(_map3_lo));
|
||||
memset(_map3_hi, 0, sizeof(_map3_hi));
|
||||
memset(_map_extra_bits, 0, sizeof(_map_extra_bits));
|
||||
memset(_map_type_and_height, MP_WATER << 4, sizeof(_map_type_and_height));
|
||||
InitMap(log_x, log_y);
|
||||
map_size = MapSize();
|
||||
|
||||
for(i=0; i!=TILES_Y-1; i++)
|
||||
memset(_map_type_and_height + i*TILES_X, 0, TILES_X-1);
|
||||
memset(_map_type_and_height, MP_CLEAR << 4, map_size);
|
||||
memset(_map_owner, OWNER_NONE, map_size);
|
||||
memset(_map2, 0, map_size * sizeof(_map2[0]));
|
||||
memset(_map3_lo, 0, map_size);
|
||||
memset(_map3_hi, 0, map_size);
|
||||
memset(_map5, 3, map_size);
|
||||
memset(_map_extra_bits, 0, map_size / 4);
|
||||
|
||||
memset(_map5, 3, sizeof(_map5));
|
||||
// create void tiles at the border
|
||||
for (i = 0; i < MapMaxY(); ++i)
|
||||
SetTileType(i * MapSizeX() + MapMaxX(), MP_VOID);
|
||||
for (i = 0; i < MapSizeX(); ++i)
|
||||
SetTileType(MapSizeX() * MapMaxY() + i, MP_VOID);
|
||||
}
|
||||
|
||||
void ConvertGroundTilesIntoWaterTiles()
|
||||
void ConvertGroundTilesIntoWaterTiles(void)
|
||||
{
|
||||
uint tile = 0;
|
||||
int h;
|
||||
TileIndex tile = 0;
|
||||
uint h;
|
||||
|
||||
while(true) {
|
||||
if (IS_TILETYPE(tile, MP_CLEAR) && GetTileSlope(tile, &h) == 0 && h == 0) {
|
||||
_map_type_and_height[tile] = MP_WATER << 4;
|
||||
for (tile = 0; tile < MapSize(); ++tile) {
|
||||
if (IsTileType(tile, MP_CLEAR) && GetTileSlope(tile, &h) == 0 && h == 0) {
|
||||
SetTileType(tile, MP_WATER);
|
||||
_map5[tile] = 0;
|
||||
_map_owner[tile] = OWNER_WATER;
|
||||
}
|
||||
tile++;
|
||||
if (GET_TILE_X(tile) == TILE_X_MAX) {
|
||||
tile += TILE_XY(-TILE_X_MAX, 1);
|
||||
if (GET_TILE_Y(tile) == TILE_Y_MAX)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -528,182 +462,192 @@ static const byte _genterrain_tbl_2[5] = { 0, 0, 0, 0, 33 };
|
||||
static void GenerateTerrain(int type, int flag)
|
||||
{
|
||||
uint32 r;
|
||||
int x,y;
|
||||
int w,h;
|
||||
byte *p,*tile;
|
||||
uint x;
|
||||
uint y;
|
||||
uint w;
|
||||
uint h;
|
||||
const Sprite* template;
|
||||
const byte *p;
|
||||
byte *tile;
|
||||
byte direction;
|
||||
|
||||
r = Random();
|
||||
p = GetSpritePtr((((r >> 24) * _genterrain_tbl_1[type]) >> 8) + _genterrain_tbl_2[type] + 4845);
|
||||
template = GetSprite((((r >> 24) * _genterrain_tbl_1[type]) >> 8) + _genterrain_tbl_2[type] + 4845);
|
||||
|
||||
x = r & TILE_X_MAX;
|
||||
y = (r >> TILE_X_BITS) & TILE_Y_MAX;
|
||||
x = r & MapMaxX();
|
||||
y = (r >> MapLogX()) & MapMaxY();
|
||||
|
||||
|
||||
if (x < 2 || y < 2)
|
||||
return;
|
||||
|
||||
direction = (byte)(r >> 22) & 3;
|
||||
w = p[2];
|
||||
h = p[1];
|
||||
if (direction & 1) { w = p[1]; h = p[2]; }
|
||||
p += 8;
|
||||
direction = (r >> 22) & 3;
|
||||
if (direction & 1) {
|
||||
w = template->height;
|
||||
h = template->width;
|
||||
} else {
|
||||
w = template->width;
|
||||
h = template->height;
|
||||
}
|
||||
p = template->data;
|
||||
|
||||
if (flag & 4) {
|
||||
if (!(flag & 2)) {
|
||||
if (!(flag & 1)) {
|
||||
if (x + y > 190)
|
||||
return;
|
||||
} else {
|
||||
if (y < 30 + x)
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (!(flag & 1)) {
|
||||
if (x + y < 256)
|
||||
return;
|
||||
} else {
|
||||
if (x < 30 + y)
|
||||
return;
|
||||
}
|
||||
uint xw = x * MapSizeY();
|
||||
uint yw = y * MapSizeX();
|
||||
uint bias = (MapSizeX() + MapSizeY()) * 16;
|
||||
|
||||
switch (flag & 3) {
|
||||
case 0:
|
||||
if (xw + yw > MapSize() - bias) return;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if (yw < xw + bias) return;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (xw + yw < MapSize() + bias) return;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if (xw < yw + bias) return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (x + w >= TILE_X_MAX-1)
|
||||
if (x + w >= MapMaxX() - 1)
|
||||
return;
|
||||
|
||||
if (y + h >= TILE_Y_MAX-1)
|
||||
if (y + h >= MapMaxY() - 1)
|
||||
return;
|
||||
|
||||
tile = &_map_type_and_height[TILE_XY(x,y)];
|
||||
tile = &_map_type_and_height[TILE_XY(x, y)];
|
||||
|
||||
if (direction == 0) {
|
||||
do {
|
||||
int w_cur = w;
|
||||
byte *tile_cur = tile;
|
||||
switch (direction) {
|
||||
case 0:
|
||||
do {
|
||||
if (*p >= *tile_cur) *tile_cur = *p;
|
||||
p++;
|
||||
tile_cur++;
|
||||
} while (--w_cur != 0);
|
||||
tile += TILE_XY(0,1);
|
||||
} while (--h != 0);
|
||||
} else if (direction == 1) {
|
||||
do {
|
||||
int h_cur = h;
|
||||
byte *tile_cur = tile;
|
||||
byte *tile_cur = tile;
|
||||
uint w_cur;
|
||||
|
||||
for (w_cur = w; w_cur != 0; --w_cur) {
|
||||
if (*p >= *tile_cur) *tile_cur = *p;
|
||||
p++;
|
||||
tile_cur++;
|
||||
}
|
||||
tile += TILE_XY(0, 1);
|
||||
} while (--h != 0);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
do {
|
||||
if (*p >= *tile_cur) *tile_cur = *p;
|
||||
p++;
|
||||
tile_cur+=TILE_XY(0,1);
|
||||
} while (--h_cur != 0);
|
||||
tile++;
|
||||
} while (--w != 0);
|
||||
} else if (direction == 2) {
|
||||
tile += w - 1;
|
||||
do {
|
||||
int w_cur = w;
|
||||
byte *tile_cur = tile;
|
||||
byte *tile_cur = tile;
|
||||
uint h_cur;
|
||||
|
||||
for (h_cur = h; h_cur != 0; --h_cur) {
|
||||
if (*p >= *tile_cur) *tile_cur = *p;
|
||||
p++;
|
||||
tile_cur += TILE_XY(0, 1);
|
||||
}
|
||||
tile++;
|
||||
} while (--w != 0);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
tile += TILE_XY(w - 1, 0);
|
||||
do {
|
||||
if (*p >= *tile_cur) *tile_cur = *p;
|
||||
p++;
|
||||
tile_cur--;
|
||||
} while (--w_cur != 0);
|
||||
tile += TILE_XY(0,1);
|
||||
} while (--h != 0);
|
||||
} else {
|
||||
tile += (h - 1) * TILE_XY(0,1);
|
||||
do {
|
||||
int h_cur = h;
|
||||
byte *tile_cur = tile;
|
||||
byte *tile_cur = tile;
|
||||
uint w_cur;
|
||||
|
||||
for (w_cur = w; w_cur != 0; --w_cur) {
|
||||
if (*p >= *tile_cur) *tile_cur = *p;
|
||||
p++;
|
||||
tile_cur--;
|
||||
}
|
||||
tile += TILE_XY(0, 1);
|
||||
} while (--h != 0);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
tile += TILE_XY(0, h - 1);
|
||||
do {
|
||||
if (*p >= *tile_cur) *tile_cur = *p;
|
||||
p++;
|
||||
tile_cur-=TILE_XY(0,1);
|
||||
} while (--h_cur != 0);
|
||||
tile++;
|
||||
} while (--w != 0);
|
||||
byte *tile_cur = tile;
|
||||
uint h_cur;
|
||||
|
||||
for (h_cur = h; h_cur != 0; --h_cur) {
|
||||
if (*p >= *tile_cur) *tile_cur = *p;
|
||||
p++;
|
||||
tile_cur -= TILE_XY(0, 1);
|
||||
}
|
||||
tile++;
|
||||
} while (--w != 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#include "table/genland.h"
|
||||
|
||||
static void CreateDesertOrRainForest()
|
||||
static void CreateDesertOrRainForest(void)
|
||||
{
|
||||
uint tile;
|
||||
const TileIndexDiff *data;
|
||||
byte mt;
|
||||
int i;
|
||||
TileIndex tile;
|
||||
const TileIndexDiffC *data;
|
||||
uint i;
|
||||
|
||||
tile = 0;
|
||||
do {
|
||||
data = _make_desert_or_rainforest_data;
|
||||
do {
|
||||
if ((i = *data++) == MDORD_LAST) {
|
||||
SetMapExtraBits(tile, 1);
|
||||
break;
|
||||
}
|
||||
mt = _map_type_and_height[TILE_MASK(tile + i)];
|
||||
} while ((mt & 0xC) == 0 && (mt >> 4) != MP_WATER);
|
||||
} while (++tile != TILES_X*TILES_Y);
|
||||
for (tile = 0; tile != MapSize(); ++tile) {
|
||||
for (data = _make_desert_or_rainforest_data;
|
||||
data != endof(_make_desert_or_rainforest_data); ++data) {
|
||||
TileIndex t = TILE_MASK(tile + ToTileIndexDiff(*data));
|
||||
if (TileHeight(t) >= 4 || IsTileType(t, MP_WATER)) break;
|
||||
}
|
||||
if (data == endof(_make_desert_or_rainforest_data))
|
||||
SetMapExtraBits(tile, 1);
|
||||
}
|
||||
|
||||
for(i=0; i!=256; i++)
|
||||
for (i = 0; i != 256; i++)
|
||||
RunTileLoop();
|
||||
|
||||
tile = 0;
|
||||
do {
|
||||
data = _make_desert_or_rainforest_data;
|
||||
do {
|
||||
if ((i = *data++) == MDORD_LAST) {
|
||||
SetMapExtraBits(tile, 2);
|
||||
break;
|
||||
}
|
||||
} while ( !IS_TILETYPE(TILE_MASK(tile+i), MP_CLEAR) || (_map5[TILE_MASK(tile + i)]&0x1C) != 0x14);
|
||||
} while (++tile != TILES_X*TILES_Y);
|
||||
for (tile = 0; tile != MapSize(); ++tile) {
|
||||
for (data = _make_desert_or_rainforest_data;
|
||||
data != endof(_make_desert_or_rainforest_data); ++data) {
|
||||
TileIndex t = TILE_MASK(tile + ToTileIndexDiff(*data));
|
||||
if (IsTileType(t, MP_CLEAR) && (_map5[t] & 0x1c) == 0x14) break;
|
||||
}
|
||||
if (data == endof(_make_desert_or_rainforest_data))
|
||||
SetMapExtraBits(tile, 2);
|
||||
}
|
||||
}
|
||||
|
||||
void GenerateLandscape()
|
||||
void GenerateLandscape(void)
|
||||
{
|
||||
int i,flag;
|
||||
uint i;
|
||||
uint flag;
|
||||
uint32 r;
|
||||
|
||||
if (_opt.landscape == LT_HILLY) {
|
||||
i = ((Random() & 0x7F) + 950) * LANDSCAPE_SIZE_FACTOR;
|
||||
do {
|
||||
for (i = ScaleByMapSize((Random() & 0x7F) + 950); i != 0; --i)
|
||||
GenerateTerrain(2, 0);
|
||||
} while (--i);
|
||||
|
||||
r = Random();
|
||||
flag = (r & 3) | 4;
|
||||
i = (((r >> 16) & 0x7F) + 450) * LANDSCAPE_SIZE_FACTOR;
|
||||
do {
|
||||
for (i = ScaleByMapSize(((r >> 16) & 0x7F) + 450); i != 0; --i)
|
||||
GenerateTerrain(4, flag);
|
||||
} while (--i);
|
||||
} else if (_opt.landscape == LT_DESERT) {
|
||||
i = ((Random()&0x7F) + 170) * LANDSCAPE_SIZE_FACTOR;
|
||||
do {
|
||||
for (i = ScaleByMapSize((Random()&0x7F) + 170); i != 0; --i)
|
||||
GenerateTerrain(0, 0);
|
||||
} while (--i);
|
||||
|
||||
r = Random();
|
||||
flag = (r & 3) | 4;
|
||||
i = (((r >> 16) & 0xFF) + 1700) * LANDSCAPE_SIZE_FACTOR;
|
||||
do {
|
||||
for (i = ScaleByMapSize(((r >> 16) & 0xFF) + 1700); i != 0; --i)
|
||||
GenerateTerrain(0, flag);
|
||||
} while (--i);
|
||||
|
||||
flag ^= 2;
|
||||
|
||||
i = ((Random() & 0x7F) + 410) * LANDSCAPE_SIZE_FACTOR;
|
||||
do {
|
||||
for (i = ScaleByMapSize((Random() & 0x7F) + 410); i != 0; --i)
|
||||
GenerateTerrain(3, flag);
|
||||
} while (--i);
|
||||
} else {
|
||||
i = ((Random() & 0x7F) + (3 - _opt.diff.quantity_sea_lakes)*256 + 100) * LANDSCAPE_SIZE_FACTOR;
|
||||
do {
|
||||
i = ScaleByMapSize((Random() & 0x7F) + (3 - _opt.diff.quantity_sea_lakes) * 256 + 100);
|
||||
for (; i != 0; --i)
|
||||
GenerateTerrain(_opt.diff.terrain_type, 0);
|
||||
} while (--i);
|
||||
}
|
||||
|
||||
ConvertGroundTilesIntoWaterTiles();
|
||||
@@ -712,15 +656,15 @@ void GenerateLandscape()
|
||||
CreateDesertOrRainForest();
|
||||
}
|
||||
|
||||
void OnTick_Town();
|
||||
void OnTick_Trees();
|
||||
void OnTick_Station();
|
||||
void OnTick_Industry();
|
||||
void OnTick_Town(void);
|
||||
void OnTick_Trees(void);
|
||||
void OnTick_Station(void);
|
||||
void OnTick_Industry(void);
|
||||
|
||||
void OnTick_Players();
|
||||
void OnTick_Train();
|
||||
void OnTick_Players(void);
|
||||
void OnTick_Train(void);
|
||||
|
||||
void CallLandscapeTick()
|
||||
void CallLandscapeTick(void)
|
||||
{
|
||||
OnTick_Town();
|
||||
OnTick_Trees();
|
||||
@@ -736,32 +680,13 @@ TileIndex AdjustTileCoordRandomly(TileIndex a, byte rng)
|
||||
int rn = rng;
|
||||
uint32 r = Random();
|
||||
|
||||
return TILE_XY(
|
||||
GET_TILE_X(a) + ((byte)r * rn * 2 >> 8) - rn,
|
||||
GET_TILE_Y(a) + ((byte)(r>>8) * rn * 2 >> 8) - rn
|
||||
);
|
||||
return TILE_MASK(TILE_XY(
|
||||
TileX(a) + ((byte)r * rn * 2 >> 8) - rn,
|
||||
TileY(a) + ((byte)(r >> 8) * rn * 2 >> 8) - rn
|
||||
));
|
||||
}
|
||||
|
||||
// This function checks if we add addx/addy to tile, if we
|
||||
// do wrap around the edges. For example, tile = (10,2) and
|
||||
// addx = +3 and addy = -4. This function will now return
|
||||
// TILE_WRAPPED, because the y is wrapped. This is needed in
|
||||
// for example, farmland. When the tile is not wrapped,
|
||||
// the result will be tile + TILE_XY(addx, addy)
|
||||
uint TileAddWrap(TileIndex tile, int addx, int addy)
|
||||
bool IsValidTile(TileIndex tile)
|
||||
{
|
||||
int x, y;
|
||||
x = GET_TILE_X(tile) + addx;
|
||||
y = GET_TILE_Y(tile) + addy;
|
||||
|
||||
// Are we about to wrap?
|
||||
if (x > 0 && x < TILE_X_MAX && y > 0 && y < TILE_Y_MAX)
|
||||
return tile + TILE_XY(addx, addy);
|
||||
|
||||
return TILE_WRAPPED;
|
||||
}
|
||||
|
||||
bool IsValidTile(uint tile)
|
||||
{
|
||||
return (tile < TILES_X * TILE_Y_MAX && GET_TILE_X(tile) != TILE_X_MAX);
|
||||
return (tile < MapSizeX() * MapMaxY() && TileX(tile) != MapMaxX());
|
||||
}
|
||||
|
||||
+2626
-2395
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+2821
File diff suppressed because it is too large
Load Diff
+2625
-2395
File diff suppressed because it is too large
Load Diff
+2649
-2253
File diff suppressed because it is too large
Load Diff
+2638
-1925
File diff suppressed because it is too large
Load Diff
+2626
-2395
File diff suppressed because it is too large
Load Diff
+2626
-2395
File diff suppressed because it is too large
Load Diff
+2626
-2395
File diff suppressed because it is too large
Load Diff
+2630
-2310
File diff suppressed because it is too large
Load Diff
+2626
-2395
File diff suppressed because it is too large
Load Diff
+2626
-2395
File diff suppressed because it is too large
Load Diff
+2823
File diff suppressed because it is too large
Load Diff
+2626
-2361
File diff suppressed because it is too large
Load Diff
+2821
File diff suppressed because it is too large
Load Diff
+2822
File diff suppressed because it is too large
Load Diff
+2663
-2187
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,6 @@
|
||||
##name Original vehicle names (ENG)
|
||||
##ownname Original vehicle names (ENG)
|
||||
##isocode xx
|
||||
|
||||
##id 0x8000
|
||||
STR_8000_KIRBY_PAUL_TANK_STEAM :Collett Pannier Tank (Steam)
|
||||
|
||||
+2670
-2291
File diff suppressed because it is too large
Load Diff
+2823
File diff suppressed because it is too large
Load Diff
+2626
-2395
File diff suppressed because it is too large
Load Diff
+2663
-2186
File diff suppressed because it is too large
Load Diff
+2823
File diff suppressed because it is too large
Load Diff
+2642
-2273
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,366 @@
|
||||
##name Frisian
|
||||
##ownname Frysk
|
||||
##isocode fy
|
||||
|
||||
##id 0x0000
|
||||
STR_NULL :
|
||||
STR_0001_OFF_EDGE_OF_MAP :{WHITE}Off edge of map
|
||||
STR_0002_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}Too close to edge of map
|
||||
STR_0003_NOT_ENOUGH_CASH_REQUIRES :{WHITE}Not enough cash - requires {CURRENCY}
|
||||
STR_0004 :{WHITE}{CURRENCY64}
|
||||
STR_0005 :{RED}{CURRENCY64}
|
||||
STR_EMPTY :
|
||||
STR_0007_FLAT_LAND_REQUIRED :{WHITE}Flat land required
|
||||
STR_0008_WAITING :{BLACK}Waiting: {WHITE}{STRING}
|
||||
STR_0009 :{WHITE}{STRING}
|
||||
STR_000A_EN_ROUTE_FROM :{WHITE}{STRING}{YELLOW} (en-route from
|
||||
STR_000B :{YELLOW}{STATION})
|
||||
STR_000C_ACCEPTS :{BLACK}Accepts: {WHITE}
|
||||
STR_000D_ACCEPTS :{BLACK}Accepts: {GOLD}
|
||||
STR_000E :
|
||||
STR_000F_PASSENGERS :Passengers
|
||||
STR_0010_COAL :Coal
|
||||
STR_0011_MAIL :Post
|
||||
STR_0012_OIL :Oalje
|
||||
STR_0013_LIVESTOCK :Livestock
|
||||
STR_0014_GOODS :Guod
|
||||
STR_0015_GRAIN :Graan
|
||||
STR_0016_WOOD :Hout
|
||||
STR_0017_IRON_ORE :Iron Ore
|
||||
STR_0018_STEEL :Stiel
|
||||
STR_0019_VALUABLES :Kostbere spullen
|
||||
STR_001A_COPPER_ORE :Koper erts
|
||||
STR_001B_MAIZE :Mais
|
||||
STR_001C_FRUIT :Fruit
|
||||
STR_001D_DIAMONDS :Diamant
|
||||
STR_001E_FOOD :Iten
|
||||
STR_001F_PAPER :Papier
|
||||
STR_0020_GOLD :Goud
|
||||
STR_0021_WATER :Wetter
|
||||
STR_0022_WHEAT :Weet
|
||||
STR_0023_RUBBER :Rubber
|
||||
STR_0024_SUGAR :Sûker
|
||||
STR_0025_TOYS :Boartersguod
|
||||
STR_0026_CANDY :Snobbersguod
|
||||
STR_0027_COLA :Cola
|
||||
STR_0028_COTTON_CANDY :Sûkerspin
|
||||
STR_0029_BUBBLES :Bubbels
|
||||
STR_002A_TOFFEE :Toffee
|
||||
STR_002B_BATTERIES :Batterijen
|
||||
STR_002C_PLASTIC :Plestik
|
||||
STR_002E :
|
||||
STR_002F_PASSENGER :Passazjier
|
||||
STR_0030_COAL :Coal
|
||||
STR_0031_MAIL :Post
|
||||
STR_0032_OIL :Oalje
|
||||
STR_0033_LIVESTOCK :Fee
|
||||
STR_0034_GOODS :Guod
|
||||
STR_0035_GRAIN :Nôt
|
||||
STR_0036_WOOD :Hout
|
||||
STR_0037_IRON_ORE :Izer Erts
|
||||
STR_0038_STEEL :Stiel
|
||||
STR_0039_VALUABLES :Kostber guod
|
||||
STR_003A_COPPER_ORE :Koper Erts
|
||||
STR_003B_MAIZE :Mais
|
||||
STR_003C_FRUIT :Fruit
|
||||
STR_003D_DIAMOND :Diamant
|
||||
STR_003E_FOOD :Iten
|
||||
STR_003F_PAPER :Papier
|
||||
STR_0040_GOLD :Goud
|
||||
STR_0041_WATER :Wetter
|
||||
STR_0043_RUBBER :Rubber
|
||||
STR_0044_SUGAR :Sûker
|
||||
STR_0045_TOY :Boartesguod
|
||||
STR_0046_CANDY :Snobbersguod
|
||||
STR_0047_COLA :Cola
|
||||
STR_004A_TOFFEE :Toffee
|
||||
STR_004B_BATTERY :Batterij
|
||||
STR_004C_PLASTIC :Plestik
|
||||
STR_004E :
|
||||
STR_004F_PASSENGER :{COMMA16} passazjier
|
||||
STR_0050_TON_OF_COAL :{COMMA16} ton coal
|
||||
STR_0051_BAG_OF_MAIL :{COMMA16} tassen mei post
|
||||
STR_0052_OF_OIL :{VOLUME} oalje
|
||||
STR_0055_TON_OF_GRAIN :{COMMA16} ton graan
|
||||
STR_0056_TON_OF_WOOD :{COMMA16} ton hout
|
||||
STR_0058_TON_OF_STEEL :{COMMA16} ton stiel
|
||||
STR_0059_BAG_OF_VALUABLES :{COMMA16} tas kostber guod
|
||||
STR_005B_TON_OF_MAIZE :{COMMA16} ton mais
|
||||
STR_005C_TON_OF_FRUIT :{COMMA16} ton fruit
|
||||
STR_005E_TON_OF_FOOD :{COMMA16} ton iten
|
||||
STR_005F_TON_OF_PAPER :{COMMA16} ton papier
|
||||
STR_0060_BAG_OF_GOLD :{COMMA16} tas goud
|
||||
STR_0061_OF_WATER :{VOLUME} wetter
|
||||
STR_00B2_MESSAGE :{YELLOW}Bericht
|
||||
STR_00B3_MESSAGE_FROM :{YELLOW}Bericht fan {STRING}
|
||||
STR_00B7_VERSION :{BLACK}OpenTTD fersje {REV}
|
||||
|
||||
STR_00C8_YES :{BLACK}Ja
|
||||
STR_00C9_NO :{BLACK}Nee
|
||||
STR_00D1_DARK_BLUE :Tsjuster Blauw
|
||||
STR_00D3_PINK :Roze
|
||||
STR_00D4_YELLOW :Giel
|
||||
STR_00D5_RED :Read
|
||||
STR_00D6_LIGHT_BLUE :Ljocht Blauw
|
||||
STR_00D7_GREEN :Grien
|
||||
STR_00D8_DARK_GREEN :Tsjuster Grien
|
||||
STR_00D9_BLUE :Blauw
|
||||
STR_00DC_PURPLE :Pears
|
||||
STR_00DD_ORANGE :Oranje
|
||||
STR_00DE_BROWN :Brún
|
||||
STR_00DF_GREY :Griis
|
||||
STR_00E0_WHITE :Wyt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
############ range for menu starts
|
||||
############ range for menu ends
|
||||
|
||||
|
||||
|
||||
############ range for months starts
|
||||
############ range for months ends
|
||||
|
||||
|
||||
############ range for service numbers starts
|
||||
############ range for service numbers ends
|
||||
|
||||
|
||||
############ range for days starts
|
||||
STR_01B0_5TH :5
|
||||
STR_01B1_6TH :6
|
||||
STR_01B2_7TH :7
|
||||
STR_01B3_8TH :8
|
||||
STR_01B4_9TH :9
|
||||
STR_01B5_10TH :10
|
||||
STR_01B6_11TH :11
|
||||
STR_01B7_12TH :12
|
||||
STR_01B8_13TH :13
|
||||
STR_01B9_14TH :14
|
||||
STR_01BA_15TH :15
|
||||
STR_01BB_16TH :16
|
||||
STR_01BC_17TH :17
|
||||
STR_01BD_18TH :18
|
||||
STR_01BE_19TH :19
|
||||
STR_01BF_20TH :20
|
||||
STR_01C0_21ST :21
|
||||
STR_01C1_22ND :22
|
||||
STR_01C2_23RD :23
|
||||
STR_01C3_24TH :24
|
||||
STR_01C4_25TH :25
|
||||
STR_01C5_26TH :26
|
||||
STR_01C6_27TH :27
|
||||
STR_01C7_28TH :28
|
||||
STR_01C8_29TH :29
|
||||
############ range for days ends
|
||||
|
||||
|
||||
############ range for cargo acecpted starts
|
||||
############ range for cargo acecpted ends
|
||||
|
||||
|
||||
|
||||
############ range for menu starts
|
||||
############ range ends here
|
||||
|
||||
############ range for menu starts
|
||||
############ range ends here
|
||||
|
||||
|
||||
|
||||
|
||||
############ range for menu starts
|
||||
############ range ends here
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
############ start of townname region
|
||||
############ end of townname region
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Start of order review system.
|
||||
# DON'T ADD OR REMOVE LINES HERE
|
||||
# end of order system
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
############ network gui strings
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
############ Leave those lines in this order!!
|
||||
############ End of leave-in-this-order
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
############ Leave those lines in this order!!
|
||||
|
||||
############ End of leave-in-this-order
|
||||
|
||||
|
||||
|
||||
|
||||
############ Leave those lines in this order!!
|
||||
############ End of leave-in-this-order
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
############ end network gui strings
|
||||
|
||||
|
||||
|
||||
##id 0x0800
|
||||
|
||||
##id 0x1000
|
||||
|
||||
|
||||
|
||||
##id 0x1800
|
||||
|
||||
##id 0x2000
|
||||
|
||||
##id 0x2800
|
||||
|
||||
##id 0x3000
|
||||
|
||||
|
||||
############ range for rating starts
|
||||
############ range for rating ends
|
||||
|
||||
|
||||
##id 0x3800
|
||||
|
||||
##id 0x4000
|
||||
|
||||
##id 0x4800
|
||||
|
||||
############ range for requires starts
|
||||
############ range for requires ends
|
||||
|
||||
|
||||
##id 0x5000
|
||||
|
||||
##id 0x5800
|
||||
|
||||
|
||||
############ WARNING, using range 0x6000 for strings that are stored in the savegame
|
||||
############ These strings may never get a new id, or savegames will break!
|
||||
##id 0x6000
|
||||
|
||||
|
||||
############ end of savegame specific region!
|
||||
|
||||
##id 0x6800
|
||||
|
||||
############ range for difficulty levels starts
|
||||
############ range for difficulty levels ends
|
||||
|
||||
############ range for difficulty settings starts
|
||||
############ range for difficulty settings ends
|
||||
|
||||
|
||||
##id 0x7000
|
||||
|
||||
##id 0x8000
|
||||
|
||||
##id 0x8800
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
##id 0x9000
|
||||
|
||||
|
||||
##id 0x9800
|
||||
|
||||
|
||||
##id 0xA000
|
||||
|
||||
|
||||
##id 0xB000
|
||||
|
||||
|
||||
############ Those following lines need to be in this order!!
|
||||
############ End of order list
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
############ Lists rail types
|
||||
|
||||
|
||||
############ End of list of rail types
|
||||
|
||||
@@ -0,0 +1,435 @@
|
||||
##name Russian_latin_char
|
||||
##ownname Russkiy
|
||||
##isocode ru
|
||||
|
||||
##id 0x0000
|
||||
STR_NULL :
|
||||
STR_0001_OFF_EDGE_OF_MAP :{WHITE}Za krayami karti
|
||||
STR_0002_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}Blizko k krayu karti
|
||||
STR_0003_NOT_ENOUGH_CASH_REQUIRES :{WHITE}Ne hvataet deneg - neobhodimo {CURRENCY}
|
||||
STR_0004 :{WHITE}{CURRENCY64}
|
||||
STR_0005 :{RED}{CURRENCY64}
|
||||
STR_EMPTY :
|
||||
STR_0007_FLAT_LAND_REQUIRED :{WHITE}Neobhodima ploskaya poverhnosty
|
||||
STR_0008_WAITING :{BLACK}Ozhidanie: {WHITE}{STRING}
|
||||
STR_0009 :{WHITE}{STRING}
|
||||
STR_000A_EN_ROUTE_FROM :{WHITE}{STRING}{YELLOW} (marshrut iz
|
||||
STR_000B :{YELLOW}{STATION})
|
||||
STR_000C_ACCEPTS :{BLACK}Prinimaetsya: {WHITE}
|
||||
STR_000D_ACCEPTS :{BLACK}Prinimaetsya: {GOLD}
|
||||
STR_000E :
|
||||
STR_000F_PASSENGERS :Passajiri
|
||||
STR_0010_COAL :Ugoly
|
||||
STR_0011_MAIL :Pochta
|
||||
STR_0012_OIL :Nefty
|
||||
STR_0013_LIVESTOCK :Domashniy skot
|
||||
STR_0014_GOODS :Tovary
|
||||
STR_0015_GRAIN :Zerno
|
||||
STR_0016_WOOD :Derevo
|
||||
STR_0017_IRON_ORE :Zheleznaya Ruda
|
||||
STR_0018_STEEL :Staly
|
||||
STR_0019_VALUABLES :Dragocennosti
|
||||
STR_001A_COPPER_ORE :Mednaya Ruda
|
||||
STR_001B_MAIZE :Kukuruza
|
||||
STR_001C_FRUIT :Frukti
|
||||
STR_001D_DIAMONDS :Almazi
|
||||
STR_001E_FOOD :Prodovolstvie
|
||||
STR_001F_PAPER :Bumaga
|
||||
STR_0020_GOLD :Zoloto
|
||||
STR_0021_WATER :Voda
|
||||
STR_0022_WHEAT :Pshenica
|
||||
STR_0023_RUBBER :Rezina
|
||||
STR_0024_SUGAR :Sahar
|
||||
STR_0025_TOYS :Igrushki
|
||||
STR_0026_CANDY :Sladosti
|
||||
STR_0027_COLA :Kola
|
||||
STR_0028_COTTON_CANDY :Saharnaya vata
|
||||
STR_0029_BUBBLES :Puzirki
|
||||
STR_002A_TOFFEE :Iriska
|
||||
STR_002B_BATTERIES :Batareyki
|
||||
STR_002C_PLASTIC :Plastik
|
||||
STR_002D_FIZZY_DRINKS :Shipuchie napitki
|
||||
STR_002E :
|
||||
STR_002F_PASSENGER :Passajiri
|
||||
STR_0030_COAL :Ugoly
|
||||
STR_0031_MAIL :Pochta
|
||||
STR_0032_OIL :Nefty
|
||||
STR_0033_LIVESTOCK :Domashniy skot
|
||||
STR_0034_GOODS :Tovary
|
||||
STR_0035_GRAIN :Zerno
|
||||
STR_0036_WOOD :Derevo
|
||||
STR_0037_IRON_ORE :Zheleznaya ruda
|
||||
STR_0038_STEEL :Staly
|
||||
STR_0039_VALUABLES :Dragocennosti
|
||||
STR_003A_COPPER_ORE :Mednaya ruda
|
||||
STR_003B_MAIZE :Kukuruza
|
||||
STR_003C_FRUIT :Frukti
|
||||
STR_003D_DIAMOND :Almazi
|
||||
STR_003E_FOOD :Prodovolstvie
|
||||
STR_003F_PAPER :Bumaga
|
||||
STR_0040_GOLD :Zoloto
|
||||
STR_0041_WATER :Voda
|
||||
STR_0042_WHEAT :Pshenica
|
||||
STR_0043_RUBBER :Rezina
|
||||
STR_0044_SUGAR :Sahar
|
||||
STR_0045_TOY :Igrushki
|
||||
STR_0046_CANDY :Sladosti
|
||||
STR_0047_COLA :Kola
|
||||
STR_0048_COTTON_CANDY :Saharnaya vata
|
||||
STR_0049_BUBBLE :Puzirki
|
||||
STR_004A_TOFFEE :Iriska
|
||||
STR_004B_BATTERY :Batareyki
|
||||
STR_004C_PLASTIC :Plastik
|
||||
STR_004D_FIZZY_DRINK :Shipuchie napitki
|
||||
STR_004E :
|
||||
STR_004F_PASSENGER :{COMMA16} passajirov
|
||||
STR_0050_TON_OF_COAL :{COMMA16} tonna uglya
|
||||
STR_0051_BAG_OF_MAIL :{COMMA16} sumka s pochtoy
|
||||
STR_0052_OF_OIL :{VOLUME} nefti
|
||||
STR_0053_ITEM_OF_LIVESTOCK :{COMMA16} golov domashnego skota
|
||||
STR_0054_CRATE_OF_GOODS :{COMMA16} korobka s tovarom
|
||||
STR_0055_TON_OF_GRAIN :{COMMA16} tonna zerna
|
||||
STR_0056_TON_OF_WOOD :{COMMA16} tonna dereva
|
||||
STR_0057_TON_OF_IRON_ORE :{COMMA16} tonna zheleznoy rudi
|
||||
STR_0058_TON_OF_STEEL :{COMMA16} tonna stali
|
||||
STR_0059_BAG_OF_VALUABLES :{COMMA16} sumka s dragocennostyami
|
||||
STR_005A_TON_OF_COPPER_ORE :{COMMA16} tonna mednoy rudi
|
||||
STR_005B_TON_OF_MAIZE :{COMMA16} tonna kukuruzi
|
||||
STR_005C_TON_OF_FRUIT :{COMMA16} tonna fruktov
|
||||
STR_005D_BAG_OF_DIAMONDS :{COMMA16} meshok s almazami
|
||||
STR_005E_TON_OF_FOOD :{COMMA16} tonna prodovolstviya
|
||||
STR_005F_TON_OF_PAPER :{COMMA16} tonna bumagi
|
||||
STR_0060_BAG_OF_GOLD :{COMMA16} meshok zolota
|
||||
STR_0061_OF_WATER :{VOLUME} vodi
|
||||
STR_0062_TON_OF_WHEAT :{COMMA16} tonna pshenici
|
||||
STR_0063_OF_RUBBER :{VOLUME} rezini
|
||||
STR_0064_TON_OF_SUGAR :{COMMA16} tonna sahara
|
||||
STR_0065_TOY :{COMMA16} igrushka
|
||||
STR_0066_BAG_OF_CANDY :{COMMA16} meshok sladostey
|
||||
STR_0067_OF_COLA :{VOLUME} koli
|
||||
STR_0068_TON_OF_COTTON_CANDY :{COMMA16} tonna saharnoy vati
|
||||
STR_0069_BUBBLE :{COMMA16} puzirki
|
||||
STR_006A_TON_OF_TOFFEE :{COMMA16} tonna irisok
|
||||
STR_006B_BATTERY :{COMMA16} batareyki
|
||||
STR_006C_OF_PLASTIC :{VOLUME} plastika
|
||||
STR_006D_FIZZY_DRINK :{COMMA16} shipuchie napitki
|
||||
STR_006E :
|
||||
STR_006F_PASSENGERS :{COMMA16} passajiri
|
||||
STR_0070_TONS_OF_COAL :{COMMA16} tonn uglya
|
||||
STR_0071_BAGS_OF_MAIL :{COMMA16} meshkov s pochtoy
|
||||
STR_0072_OF_OIL :{VOLUME} nefti
|
||||
STR_0073_ITEMS_OF_LIVESTOCK :{COMMA16} golov domashnego skota
|
||||
STR_0074_CRATES_OF_GOODS :{COMMA16} korobok s tovarom
|
||||
STR_0075_TONS_OF_GRAIN :{COMMA16} tonn zerna
|
||||
STR_0076_TONS_OF_WOOD :{COMMA16} tonn dereva
|
||||
STR_0077_TONS_OF_IRON_ORE :{COMMA16} tonn zheleznoy rudi
|
||||
STR_0078_TONS_OF_STEEL :{COMMA16} tonn stali
|
||||
STR_0079_BAGS_OF_VALUABLES :{COMMA16} meshkov s dragocennostyami
|
||||
STR_007A_TONS_OF_COPPER_ORE :{COMMA16} tonn mednoy rudi
|
||||
STR_007B_TONS_OF_MAIZE :{COMMA16} tonn kukuruzi
|
||||
STR_007C_TONS_OF_FRUIT :{COMMA16} tonn fruktov
|
||||
STR_007D_BAGS_OF_DIAMONDS :{COMMA16} meshkov s almazami
|
||||
STR_007E_TONS_OF_FOOD :{COMMA16} tonn prodovolstviya
|
||||
STR_007F_TONS_OF_PAPER :{COMMA16} tonn bumagi
|
||||
STR_0080_BAGS_OF_GOLD :{COMMA16} meshkov zolota
|
||||
STR_0081_OF_WATER :{VOLUME} vodi
|
||||
STR_0082_TONS_OF_WHEAT :{COMMA16} tonn pshenici
|
||||
STR_0083_OF_RUBBER :{VOLUME} rezini
|
||||
STR_0084_TONS_OF_SUGAR :{COMMA16} tonn sahara
|
||||
STR_0085_TOYS :{COMMA16} igrushek
|
||||
STR_0086_BAGS_OF_CANDY :{COMMA16} meshkov so sladostyami
|
||||
STR_0087_OF_COLA :{VOLUME} koli
|
||||
STR_0088_TONS_OF_COTTON_CANDY :{COMMA16} tonn saharnoy vati
|
||||
STR_0089_BUBBLES :{COMMA16} puzirkov
|
||||
STR_008A_TONS_OF_TOFFEE :{COMMA16} tonn irisok
|
||||
STR_008B_BATTERIES :{COMMA16} batareek
|
||||
STR_008C_OF_PLASTIC :{VOLUME} plastika
|
||||
STR_008D_FIZZY_DRINKS :{COMMA16} shipuchih napitkov
|
||||
STR_008E :
|
||||
STR_008F_PS :{TINYFONT}PS
|
||||
STR_0090_CL :{TINYFONT}CL
|
||||
STR_0091_ML :{TINYFONT}ML
|
||||
STR_0092_OL :{TINYFONT}OL
|
||||
STR_0093_LV :{TINYFONT}LV
|
||||
STR_0094_GD :{TINYFONT}GD
|
||||
STR_0095_GR :{TINYFONT}GR
|
||||
STR_00AF :{WHITE}{DATE_LONG}
|
||||
STR_00B0_MAP :{WHITE}Karta - {STRING}
|
||||
STR_00B1_GAME_OPTIONS :{WHITE}Igrovie Opcii
|
||||
STR_00B2_MESSAGE :{YELLOW}Soobshenie
|
||||
STR_00B3_MESSAGE_FROM :{YELLOW}Soobshenie ot {STRING}
|
||||
STR_00B4_CAN_T_DO_THIS :{WHITE}Ne mogu eto sdelaty....
|
||||
STR_00B5_CAN_T_CLEAR_THIS_AREA :{WHITE}Ne vozmozno ochistity etu mestnosty....
|
||||
STR_00B6_ORIGINAL_COPYRIGHT :{BLACK}Originalnie avtorskie prava {COPYRIGHT} 1995 Chris Sawyer, Vse prava sohraneni
|
||||
STR_00B7_VERSION :{BLACK}OpenTTD versiya {REV}
|
||||
STR_00BA_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT}2002-2005 Komanda OpenTTD
|
||||
STR_TRANSLATED_BY :{BLACK} Perevodchik(i) -
|
||||
|
||||
STR_00C5 :{BLACK}{CROSS}
|
||||
STR_00C6 :{SILVER}{CROSS}
|
||||
STR_00C7_QUIT :{WHITE}Vihod
|
||||
STR_00C8_YES :{BLACK}Da
|
||||
STR_00C9_NO :{BLACK}Net
|
||||
STR_00CA_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Vi uvereni, chto hotite pokinuty etu igru i vernutsya k {STRING}?
|
||||
STR_00CB_1 :{BLACK}1
|
||||
STR_00CC_2 :{BLACK}2
|
||||
STR_00CD_3 :{BLACK}3
|
||||
STR_00CE_4 :{BLACK}4
|
||||
STR_00CF_5 :{BLACK}5
|
||||
STR_00D0_NOTHING :Nichego
|
||||
STR_00D1_DARK_BLUE :Temno-Siniy
|
||||
STR_00D2_PALE_GREEN :Bledno-Zeleniy
|
||||
STR_00D3_PINK :Rozoviy
|
||||
STR_00D4_YELLOW :Zheltiy
|
||||
STR_00D5_RED :Krasniy
|
||||
STR_00D6_LIGHT_BLUE :Svetlo-Siniy
|
||||
STR_00D7_GREEN :Zeleniy
|
||||
STR_00D8_DARK_GREEN :Temno-Zeleniy
|
||||
STR_00D9_BLUE :Siniy
|
||||
STR_00DA_CREAM :Kremoviy
|
||||
STR_00DB_MAUVE :Liloviy
|
||||
STR_00DC_PURPLE :Purpurniy
|
||||
STR_00DD_ORANGE :Oranjeviy
|
||||
STR_00DE_BROWN :Korichneviy
|
||||
STR_00DF_GREY :Seriy
|
||||
STR_00E0_WHITE :Beliy
|
||||
STR_00E1_TOO_MANY_VEHICLES_IN_GAME :{WHITE}Slishkom mnogo transporta v igre
|
||||
STR_00E2 :{BLACK}{COMMA16}
|
||||
STR_00E3 :{RED}{COMMA16}
|
||||
STR_00E4_LOCATION :{BLACK}Poziciya
|
||||
STR_00E5_CONTOURS :Konturi
|
||||
STR_00E6_VEHICLES :Transportnie sredstva
|
||||
STR_00E7_INDUSTRIES :Industrii
|
||||
STR_00E8_ROUTES :Marshruti
|
||||
STR_00E9_VEGETATION :Rastitelnosty
|
||||
STR_00EA_OWNERS :Vladelci
|
||||
STR_00EB_ROADS :{BLACK}{TINYFONT}Dorogi
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
############ range for menu starts
|
||||
############ range for menu ends
|
||||
|
||||
|
||||
|
||||
############ range for months starts
|
||||
############ range for months ends
|
||||
|
||||
|
||||
############ range for service numbers starts
|
||||
############ range for service numbers ends
|
||||
|
||||
|
||||
############ range for days starts
|
||||
############ range for days ends
|
||||
|
||||
|
||||
############ range for cargo acecpted starts
|
||||
############ range for cargo acecpted ends
|
||||
|
||||
|
||||
|
||||
############ range for menu starts
|
||||
############ range ends here
|
||||
|
||||
############ range for menu starts
|
||||
############ range ends here
|
||||
|
||||
|
||||
|
||||
|
||||
############ range for menu starts
|
||||
############ range ends here
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
############ start of townname region
|
||||
############ end of townname region
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Start of order review system.
|
||||
# DON'T ADD OR REMOVE LINES HERE
|
||||
# end of order system
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
############ network gui strings
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
############ Leave those lines in this order!!
|
||||
############ End of leave-in-this-order
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
############ Leave those lines in this order!!
|
||||
|
||||
############ End of leave-in-this-order
|
||||
|
||||
|
||||
|
||||
|
||||
############ Leave those lines in this order!!
|
||||
############ End of leave-in-this-order
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
############ end network gui strings
|
||||
|
||||
|
||||
|
||||
##id 0x0800
|
||||
|
||||
##id 0x1000
|
||||
|
||||
|
||||
|
||||
##id 0x1800
|
||||
|
||||
##id 0x2000
|
||||
|
||||
##id 0x2800
|
||||
|
||||
##id 0x3000
|
||||
|
||||
|
||||
############ range for rating starts
|
||||
############ range for rating ends
|
||||
|
||||
|
||||
##id 0x3800
|
||||
|
||||
##id 0x4000
|
||||
|
||||
##id 0x4800
|
||||
|
||||
############ range for requires starts
|
||||
############ range for requires ends
|
||||
|
||||
|
||||
##id 0x5000
|
||||
|
||||
##id 0x5800
|
||||
|
||||
|
||||
############ WARNING, using range 0x6000 for strings that are stored in the savegame
|
||||
############ These strings may never get a new id, or savegames will break!
|
||||
##id 0x6000
|
||||
|
||||
|
||||
############ end of savegame specific region!
|
||||
|
||||
##id 0x6800
|
||||
|
||||
############ range for difficulty levels starts
|
||||
############ range for difficulty levels ends
|
||||
|
||||
############ range for difficulty settings starts
|
||||
############ range for difficulty settings ends
|
||||
|
||||
|
||||
##id 0x7000
|
||||
|
||||
##id 0x8000
|
||||
|
||||
##id 0x8800
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
##id 0x9000
|
||||
|
||||
|
||||
##id 0x9800
|
||||
|
||||
|
||||
##id 0xA000
|
||||
|
||||
|
||||
##id 0xB000
|
||||
|
||||
|
||||
############ Those following lines need to be in this order!!
|
||||
############ End of order list
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
############ Lists rail types
|
||||
|
||||
|
||||
############ End of list of rail types
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user